www.pudn.com > avi 到 mpeg 的转换程序及源代码.zip > READPIC.C
/* readpic.c, read source pictures from avi file */ /* * 4/4/97 - John Schlichther * * completely rewritten to create avi2mpg1 - avi to mpeg-1 encoder * * Copyright (C) 1997 John Schlichther * * 7-19-97 - added support for 8 bit palletized video * - corrected chroma subsampling * 7-30-97 - added support for faking corrupted frames (optional) * - used frame by frame data to determine horizontal and vertical * size of bitmap instead of AVIFILEINFO structure. Found at least one * avi which does not have this set properly. * - added support for 10, 12, and 15FPS video by frame replication * - adjusted RGB->YUV conversion * 8-23-97 - center cropping region * 10-19-97 - dynamically allocated space for U and V buffers */ #include#include #include #include #include "global.h" #include "video.h" unsigned int u, v, bpscanl, dib_offset, j, hblank, vblank, hcrop, vcrop, topblank; int x, y; float R, G, B; // RGB->YUV conversion constants const float RY = (77.0/256.0), GY = (150.0/256.0), BY = (29.0/256.0); const float RU = (-44.0/256.0), GU = (-87.0/256.0), BU = (131.0/256.0); const float RV = (131.0/256.0), GV = (-110.0/256.0), BV = (-21.0/256.0); void readframe(lCurFrame,frame) unsigned char *frame[]; unsigned long lCurFrame; { unsigned char *lpframeY, *lpframeU, *lpframeV; unsigned int pixsz; unsigned char *lpColor; unsigned int palletized; // now retrieve desired frame // get pointer to bitmap lpbi = AVIStreamGetFrame(pget, lCurFrame/frame_repl); if(!lpbi && !fake_bad_frames) { fprintf(stderr, "\ncould not retrieve video frame %i!\n", lCurFrame); fprintf(stderr, "\npossibly corrupt avi file, try -e option."); exit(-1); } else if(!lpbi && fake_bad_frames) { lpbi = AVIStreamGetFrame(pget, last_good_video_frame); bad_frame_count++; } else if(lpbi) { last_good_video_frame = lCurFrame/frame_repl; } pixsz = lpbi->biBitCount; if((pixsz!=8)&&(pixsz!=16)&&(pixsz!=24)&&(pixsz!=32)) { fprintf(stderr, "\ncan only handle 8 bit palettized, or 16, 24, or 32 bit RGB video!"); exit(-1); } if(pixsz==8) palletized=1; else palletized=0; // check for compression type of retrieved DIB if (lpbi->biCompression != BI_RGB) // does not support BI_BITFIELDS { fprintf(stderr, "\ncan not handle compressed DIBs from codec!"); exit(-1); } // locate color table lpColor = (unsigned char *)lpbi + lpbi->biSize; // next, actual DIB if(palletized) dib_offset = sizeof(BITMAPINFOHEADER) + lpbi->biClrUsed * 4; else dib_offset = sizeof(BITMAPINFOHEADER); // offset past bitmap header lpbitmp = (unsigned char *)lpbi + dib_offset; // pointer to actual bitmap switch(pixsz) { case 8: bpscanl = (unsigned int)(((lpbi->biWidth + 3)>>2)<<2); break; case 16: bpscanl = (unsigned int)(lpbi->biWidth * 2); break; case 24: bpscanl = ((((unsigned int)lpbi->biWidth * 3 + 3)>>2)<<2); break; case 32: bpscanl = (unsigned int)(lpbi->biWidth * 4); break; default: fprintf(stderr, "\ninternal error: illegal pixsz value\n"); exit(-1); // should never occur } // if frame width is less than output width, then there are blank pixels in output frame on left and right if(width>lpbi->biWidth) hblank = width - lpbi->biWidth; else hblank=0; // similarily, if height is less than output, then there are blank lines at the top and bottom if(height>lpbi->biHeight) vblank = height - lpbi->biHeight; else vblank=0; // if frame width is greater than output width, we have to trim pixels if(width biWidth) hcrop = lpbi->biWidth - width; else hcrop=0; // if frame height is greater than output height, we have to trim pixels if(height biHeight) vcrop = lpbi->biHeight - height; else vcrop=0; if(vertical_size>lpbi->biHeight) topblank = (vertical_size - lpbi->biHeight)/2; else topblank = 0; // convert RGB DIB to YUV (4:2:0) lpframeY = (unsigned char *)frame[0]; lpframeU = (unsigned char *)frame[1]; lpframeV = (unsigned char *)frame[2]; // take care of any blank lines on the top j = topblank; while(j > 0) { for(x = 0; x < width; x++) { *lpframeY++ = 0; Ubuffer[x + (j - 1)*width] = 128; Vbuffer[x + (j - 1)*width] = 128; } j--; } for(y = 0; y < (lpbi->biHeight-(int)vcrop); y++) { // take care of any blank pixels on the left j = hblank/2; while(j > 0) { *lpframeY = 0; lpframeY++; Ubuffer[j - 1 + (topblank+y)*width] = 128; Vbuffer[j - 1 + (topblank+y)*width] = 128; j--; } for(x = 0; x < (lpbi->biWidth-(int)hcrop); x++) { switch(pixsz) { case 8: lpcurpix = (unsigned char *)(lpbitmp + ((lpbi->biHeight - 1 - (y+(vcrop/2))) * bpscanl) + (x+(hcrop/2))); R = (float)lpColor[*lpcurpix * 4 + 2]; G = (float)lpColor[*lpcurpix * 4 + 1]; B = (float)lpColor[*lpcurpix * 4 + 0]; break; case 16: lpcurpixw = (unsigned short *)(lpbitmp + ((lpbi->biHeight - 1 - (y+(vcrop/2))) * bpscanl) + ((x+(hcrop/2)) * 2)); R = (float)(((*lpcurpixw >> 7) & 0xf8)|0x07); G = (float)(((*lpcurpixw >> 2) & 0xf8)|0x07); B = (float)(((*lpcurpixw << 3) & 0xf8)|0x07); break; case 24: lpcurpix = (unsigned char *)(lpbitmp + ((lpbi->biHeight - 1 - (y+(vcrop/2))) * bpscanl) + ((x+(hcrop/2)) * 3)); R = *(lpcurpix + 2); G = *(lpcurpix + 1); B = *(lpcurpix + 0); break; case 32: lpcurpix = (unsigned char *)(lpbitmp + ((lpbi->biHeight - 1 - (y+(vcrop/2))) * bpscanl) + ((x+(hcrop/2)) * 4)); R = *(lpcurpix + 2); G = *(lpcurpix + 1); B = *(lpcurpix + 0); break; default: fprintf(stderr, "\ninternal error: illegal pixsz value\n"); exit(-1); // should never occur } *lpframeY++ = (int)(RY*R + GY*G + BY*B); Ubuffer[(hblank/2)+x + (topblank+y)*width] = (int)(RU*R + GU*G + BU*B + 128); Vbuffer[(hblank/2)+x + (topblank+y)*width] = (int)(RV*R + GV*G + BV*B + 128); } // take care of any blank pixels on the right j = hblank - (hblank/2); while(j > 0) { *lpframeY = 0; lpframeY++; Ubuffer[lpbi->biWidth + (hblank/2) + j - 1 + (topblank+y)*width] = 128; Vbuffer[lpbi->biWidth + (hblank/2) + j - 1 + (topblank+y)*width] = 128; j--; } } // and any blank lines on the bottom j = vblank - topblank; //printf("j=%u, vblank=%u, vertical_size=%u, biHeight=%u\n",j,vblank,vertical_size,lpbi->biHeight); while(j > 0) { for(x = 0; x < width; x++) { *lpframeY++ = 0; Ubuffer[x + (topblank+lpbi->biHeight + j - 1)*width] = 128; Vbuffer[x + (topblank+lpbi->biHeight + j - 1)*width] = 128; } j--; } // now do chroma subsampling for(y = 0; y < height/2; y++) { for(x = 0; x < width/2; x++) { *lpframeU++ = (Ubuffer[x*2 + (y*2)*width]+Ubuffer[x*2+1 + (y*2)*width]+Ubuffer[x*2 + (y*2+1)*width]+Ubuffer[x*2+1 + (y*2+1)*width])/4; *lpframeV++ = (Vbuffer[x*2 + (y*2)*width]+Vbuffer[x*2+1 + (y*2)*width]+Vbuffer[x*2 + (y*2+1)*width]+Vbuffer[x*2+1 + (y*2+1)*width])/4; } } }