http://dis.eafit.edu.co/areas/telematica/proyectos/jmf/src/jmf211a_scsl_src/src/share/com/sun/media/parser/video/AviParser.java
http://themonospot.googlecode.com/svn-history/r77/trunk/themonospot-base/src/components/clsParserAVI.cs
http://www.codeforge.com/s/0/mp4-parser
http://www.experts-exchange.com/Programming/Languages/CPP/Q_20884897.html
http://read.pudn.com/downloads170/sourcecode/app/787664/aviparser.cpp__.htm
http://read.pudn.com/downloads170/sourcecode/app/787664/incaviparser.cpp__.htm
http://www.codeproject.com/KB/audio-video/avifilewrapper/avifilewrapper_src.zip
AVI frame split using C or C++
Hi
I wish to split an AVI file into individual frames. I would like to use these frames and later store in a BMP file.
I have the AVI file format from
http://www.wotsit.org
I can get all the header info etc.
The problem is the main data part. The format says that the file contains DIB in compressed and/or uncompressed format starting with 'dc' and 'db' respectively. I tried to get those parts but the image does not come out proper.
I also noticed that the total no. of 'db's and 'dc's in the file are twice the no. of frames.
I am working with gcc on Linux platform. This is part of my project.
Dhyanesh
I wish to split an AVI file into individual frames. I would like to use these frames and later store in a BMP file.
I have the AVI file format from
http://www.wotsit.org
I can get all the header info etc.
The problem is the main data part. The format says that the file contains DIB in compressed and/or uncompressed format starting with 'dc' and 'db' respectively. I tried to get those parts but the image does not come out proper.
I also noticed that the total no. of 'db's and 'dc's in the file are twice the no. of frames.
I am working with gcc on Linux platform. This is part of my project.
Dhyanesh
This question has been solved and asker verified
All Experts Exchange premium technology solutions are available to subscription members.
You might check whether your
structs are getting the right packing and alignment. You might need a
#pragma pack(1) to get things lined up straight.
What I usually do in a case like this is to "tidy up" the code. Almost always find the problem this way:
#1: comment each loop and if. It would be nice to see comments like "getting bitmap info", "reading bitmap", etc.
#2: Add calls to a Bomb() function for impossible or unexpected input. It would be nice to see lines like: Bomb("Not a db");
Bomb("Impossible dimension"); Bomb("Impossible length");
-----------------
A good 88% of the time I find the problem just by following these practices. Someday I will catch on and write code like this the FIRST time and avoid a lot of headaches.
What I usually do in a case like this is to "tidy up" the code. Almost always find the problem this way:
#1: comment each loop and if. It would be nice to see comments like "getting bitmap info", "reading bitmap", etc.
#2: Add calls to a Bomb() function for impossible or unexpected input. It would be nice to see lines like: Bomb("Not a db");
Bomb("Impossible dimension"); Bomb("Impossible length");
-----------------
A good 88% of the time I find the problem just by following these practices. Someday I will catch on and write code like this the FIRST time and avoid a lot of headaches.
>>I have tried reading
exactly that but in between two 'db's or 'dc's the no. of bytes are much
less than biSizeImage. I also tried reading until I get biSizeimage
still I do not get correct bmp.
Don't you think biSizeImage includes the size of header!? Looking at your comments, I think you have not taken into consideration the header as part of data.
So, do try by taking size of header also into consideration....
-ssnkumar
Don't you think biSizeImage includes the size of header!? Looking at your comments, I think you have not taken into consideration the header as part of data.
So, do try by taking size of header also into consideration....
-ssnkumar
Hi,
Sorry for delay, here is the source of program that copies frames into bmps.
====start aviparser.cpp===
// AviParser.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <strstream>
using namespace std;
#pragma pack(2)
typedef struct tagBITMAPFILEHEADER { // bmfh
char bfType[2]; /* always 'BM' */
unsigned long bfSize; /* size of bitmap file in bytes */
unsigned short bfReserved1; /* always 0 */
unsigned short bfReserved2; /* always 0 */
unsigned long bfOffBits; /* offset to data for bitmap */
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{ // bmih
unsigned long biSize;
unsigned long biWidth;
unsigned long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression; /* a DIB can be compressed using run length encoding */
unsigned long biSizeImage;
unsigned long biXPelsPerMeter;
unsigned long biYPelsPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
} BITMAPINFOHEADER;
typedef struct _avistreamheader
{
char fccType[4];
char fccHandler[4];
unsigned long dwFlags;
unsigned short wPriority;
unsigned short wLanguage;
unsigned long dwInitialFrames;
unsigned long dwScale;
unsigned long dwRate;
unsigned long dwStart;
unsigned long dwLength;
unsigned long dwSuggestedBufferSize;
unsigned long dwQuality;
unsigned long dwSampleSize;
struct {
short int left;
short int top;
short int right;
short int bottom;
} rcFrame;
} AVISTREAMHEADER;
typedef struct _RIFF_HDR
{
char FOURCC[4];
long filesize;
char filetype[4];
} RIFFHDR;
typedef struct _CHUNK_HDR
{
char chunkid[4];
long realblocksize;
long blocksize;
} CHUNKHDR;
typedef struct _avimainheader {
unsigned long dwMicroSecPerFrame;
unsigned long dwMaxBytesPerSec;
unsigned long dwPaddingGranularity;
unsigned long dwFlags;
unsigned long dwTotalFrames;
unsigned long dwInitialFrames;
unsigned long dwStreams;
unsigned long dwSuggestedBufferSize;
unsigned long dwWidth;
unsigned long dwHeight;
unsigned long dwReserved[4];
} AVIMAINHEADER;
#define AVI_FILE_NAME _T("C:\\filecopy.avi") //<<--- Change here file name.
long readList(ifstream* favi,long chunk_size);
#define UNPACK_FOURCC(lfourcc,four cc) (fourcc)[0] = (char)(lfourcc & 0x00FF); \
(fourcc)[1] = (char)((lfourcc >> 8) & 0x00FF);\
(fourcc)[2] = (char)((lfourcc >> 16) & 0x00FF);\
(fourcc)[3] = (char)((lfourcc >> 24) & 0x00FF);
void printFOURCC(char* Msg, char fourcc[4])
{
cout<< Msg << fourcc[0]<< fourcc[1] << fourcc[2] << fourcc[3] << endl;
}
long readChunkDsc(ifstream* favi, char* fourcc, long* chunk_size)
{
long lfourcc = 0;
favi->read((char*)&lfourcc ,sizeof(lo ng));
UNPACK_FOURCC(lfourcc,four cc)
long qq=0;
favi->read((char *)&qq,sizeof(long));
*chunk_size = qq;
return *chunk_size;
}
void printAviHeader(AVIMAINHEAD ER *hdr)
{
cout << " ==== AVI HEADER ====" << endl;
}
void printAviStreamHeader(AVIST REAMHEADER *hdr)
{
cout << " ==== AVI STREAM HEADER ====" <<endl;
}
bool readAviHeader(ifstream* favi,AVIMAINHEADER* avimainhdr)
{
favi->read((char *)avimainhdr,sizeof(AVIMAI NHEADER));
return favi->good();
}
long readhdrlList(ifstream* favi,long ch_size)
{
char chunk_id[4];
long chunk_size;
long len = 0;
while (ch_size>len)
{
readChunkDsc(favi, (char *)chunk_id, &chunk_size);
long pad = favi->tellg();
if (chunk_size == 0)
return 0;
if (strncmp(chunk_id,"LIST",4 ) == 0)
readList(favi,chunk_size);
if (strncmp(chunk_id,"avih",4 ) == 0)
{
AVIMAINHEADER hdr;
readAviHeader(favi,&hdr);
printAviHeader(&hdr);
}
len += chunk_size + 8;
favi->seekg(chunk_size + pad, ios::beg);
}
return chunk_size;
}
typedef struct tagRGBQUAD {
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
} RGBQUAD;
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
BITMAPINFO *bmpinf = NULL;
long sz_BITMAPINFO = 0;
long readstrlList(ifstream* favi,long ch_size)
{
char chunk_id[4];
long chunk_size;
long len = 4;
int flag_set = 0;
while (ch_size>len)
{
readChunkDsc(favi, (char *)chunk_id, &chunk_size);
long pad = favi->tellg();
if (chunk_size == 0)
return 0;
if (strncmp(chunk_id,"LIST",4 ) == 0)
readList(favi,chunk_size);
if (strncmp(chunk_id,"strh",4 ) == 0)
{
AVISTREAMHEADER hdr;
favi->read((char *)&hdr,sizeof(AVISTREAMHEA DER));
if (strncmp(hdr.fccType, "vids",4) == 0)
flag_set = 1;
printAviStreamHeader(&hdr) ;
}
if (flag_set && strncmp(chunk_id,"strf",4) == 0)
{
bmpinf = (BITMAPINFO *) malloc(chunk_size);
favi->read((char*)bmpinf, chunk_size);
sz_BITMAPINFO = chunk_size;
flag_set = 0;
}
if ((chunk_size % 2) == 1)
chunk_size +=1;
len += chunk_size + 8;
favi->seekg(chunk_size + pad, ios::beg);
}
return chunk_size;
}
void printmovichunkinfo(char chunk_id[4])
{
cout << "Stream " << chunk_id[0] << chunk_id[1] << endl;
if (strncmp(&chunk_id[2],"db" ,2) == 0)
cout << "Uncompressed video" << endl;
if (strncmp(&chunk_id[2],"dc" ,2) == 0)
cout << "Compressed video" << endl;
if (strncmp(&chunk_id[2],"pc" ,2) == 0)
cout << "palette change" << endl;
if (strncmp(&chunk_id[2],"wb" ,2) == 0)
cout << "Audio Data" << endl;
}
bool copyBMPtoFile(ifstream *favi,long chunk_size, long fnameid)
{
BITMAPFILEHEADER bmfh;
memset(&bmfh,0,sizeof(BITM APFILEHEAD ER));
bmfh.bfType[0] = 'B';
bmfh.bfType[1] = 'M';
bmfh.bfSize = (unsigned long)(chunk_size + sizeof(BITMAPFILEHEADER) + sz_BITMAPINFO);
bmfh.bfOffBits = sz_BITMAPINFO + sizeof(BITMAPFILEHEADER);
ofstream fout;
char * buf = new char[chunk_size];
try
{
strstream str_str;
str_str << "c:\\" << "bmp" << fnameid << ".bmp" << '\0';
fout.open(str_str.str(),io s::binary| ios::out|i os::trunc) ;
favi->read(buf, chunk_size);
fout.write((char *)(void *)&bmfh,sizeof(BITMAPFILEH EADER));
fout.write((char *)bmpinf,sz_BITMAPINFO);
fout.write(buf, chunk_size);
fout.close();
}
catch(...)
{
cout << "copy to bmp failed" << endl;
}
delete [] buf;
return favi->good();
}
long readmoviList(ifstream* favi,long ch_size)
{
long len = 4;
int imgNumber = 1;
long chunk_size;
char chunk_id[4];
while (ch_size>len)
{
memset(&chunk_id[0],0,4);
readChunkDsc(favi, (char *)chunk_id, &chunk_size);
long pad = favi->tellg();
if (chunk_size == 0)
return 0;
if (strncmp(chunk_id,"LIST",4 ) == 0)
readList(favi,chunk_size);
else
{
printmovichunkinfo(chunk_i d);
cout << "Chunk Size: " << chunk_size << endl;
copyBMPtoFile(favi,chunk_s ize,imgNum ber++);
favi->seekg(chunk_size + pad, ios::beg);
}
len += chunk_size + 8;
}
return chunk_size;
}
long readIdxList(ifstream* favi,long chunk_size)
{
return chunk_size;
}
long readmovirecList(ifstream* favi,long ch_size)
{
long len = 4;
int imgNumber = 1;
long chunk_size;
char chunk_id[4];
while (ch_size>len)
{
memset(&chunk_id[0],0,4);
long pad = favi->tellg();
readChunkDsc(favi, (char *)chunk_id, &chunk_size);
pad = favi->tellg();
if (chunk_size == 0)
return 0;
if (strncmp(chunk_id,"LIST",4 ) == 0)
readList(favi,chunk_size);
// printFOURCC("Chunk_id: ",chunk_id);
if (strncmp(chunk_id,"JUNK",4 ) != 0)
{
printmovichunkinfo(chunk_i d);
cout << "Chunk Size: " << chunk_size << endl;
copyBMPtoFile(favi,chunk_s ize,imgNum ber++);
}
favi->seekg(chunk_size + pad, ios::beg);
len += chunk_size + 8;
}
return chunk_size;
}
long readList(ifstream* favi,long chunk_size)
{
char listtype[4];
long pos = favi->tellg();
favi->read((char *)&listtype[0], sizeof(listtype));
printFOURCC("List Type: ", listtype);
if(strncmp(listtype,"hdrl" ,4) == 0)
readhdrlList(favi,chunk_si ze );
else if(strncmp(listtype,"movi" ,4) == 0)
readmoviList(favi,chunk_si ze );
else if(strncmp(listtype,"idx1" ,4) == 0)
readIdxList(favi,chunk_siz e );
else if(strncmp(listtype,"indx" ,4) == 0)
readIdxList(favi,chunk_siz e );
else if(strncmp(listtype,"strl" ,4) == 0)
readstrlList(favi,chunk_si ze );
else if(strncmp(listtype,"rec ",4) == 0)
readmovirecList(favi,chunk _size );
favi->seekg(pos + chunk_size);
return chunk_size;
}
int _tmain(int argc, _TCHAR* argv[])
{
ifstream favi;
favi.open(AVI_FILE_NAME,io s::binary) ;
if (favi == NULL)
{
cout << "Can't open file " << AVI_FILE_NAME << endl;
}
try
{
RIFFHDR rh;
favi.read((char *)&rh,sizeof(rh));
printFOURCC("RIFF header: ",rh.FOURCC);
cout << "FileSize: "<<rh.filesize << endl;
printFOURCC("FileType: ",rh.filetype);
char chid[4];
memset(&chid[0],0,4);
long chunk_size;
long chunk_pos = favi.tellg();
while(!favi.eof())
{
if (readChunkDsc(&favi,(char *)chid,&chunk_size))
{
printFOURCC("Chunk ID: ",chid);
cout << "Chunk Size: " << chunk_size << endl;
if (strncmp(chid,"LIST",4) == 0)
{
//readlist
readList(&favi,chunk_size) ;
}
if (strncmp(chid,"hdrl",4) == 0)
{
//read hdrl
cout << "hdrl chunk" << endl;
}
if (strncmp(chid,"movi",4) == 0)
{
//read movi
cout << "movi chunk" << endl;
}
if (strncmp(chid,"idx1",4) == 0)
{
//read movi
cout << "idx1 chunk" << endl;
}
}
else
break;
favi.seekg( chunk_pos + chunk_size + 8,ios::beg);
chunk_pos = favi.tellg();
}
}
catch(...)
{
}
free(bmpinf);
favi.close();
char _a;
cin >> _a;
}
====end of aviparser.cpp===
Tell me if this is what you need?
Sorry for delay, here is the source of program that copies frames into bmps.
====start aviparser.cpp===
// AviParser.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <strstream>
using namespace std;
#pragma pack(2)
typedef struct tagBITMAPFILEHEADER { // bmfh
char bfType[2]; /* always 'BM' */
unsigned long bfSize; /* size of bitmap file in bytes */
unsigned short bfReserved1; /* always 0 */
unsigned short bfReserved2; /* always 0 */
unsigned long bfOffBits; /* offset to data for bitmap */
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{ // bmih
unsigned long biSize;
unsigned long biWidth;
unsigned long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression; /* a DIB can be compressed using run length encoding */
unsigned long biSizeImage;
unsigned long biXPelsPerMeter;
unsigned long biYPelsPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
} BITMAPINFOHEADER;
typedef struct _avistreamheader
{
char fccType[4];
char fccHandler[4];
unsigned long dwFlags;
unsigned short wPriority;
unsigned short wLanguage;
unsigned long dwInitialFrames;
unsigned long dwScale;
unsigned long dwRate;
unsigned long dwStart;
unsigned long dwLength;
unsigned long dwSuggestedBufferSize;
unsigned long dwQuality;
unsigned long dwSampleSize;
struct {
short int left;
short int top;
short int right;
short int bottom;
} rcFrame;
} AVISTREAMHEADER;
typedef struct _RIFF_HDR
{
char FOURCC[4];
long filesize;
char filetype[4];
} RIFFHDR;
typedef struct _CHUNK_HDR
{
char chunkid[4];
long realblocksize;
long blocksize;
} CHUNKHDR;
typedef struct _avimainheader {
unsigned long dwMicroSecPerFrame;
unsigned long dwMaxBytesPerSec;
unsigned long dwPaddingGranularity;
unsigned long dwFlags;
unsigned long dwTotalFrames;
unsigned long dwInitialFrames;
unsigned long dwStreams;
unsigned long dwSuggestedBufferSize;
unsigned long dwWidth;
unsigned long dwHeight;
unsigned long dwReserved[4];
} AVIMAINHEADER;
#define AVI_FILE_NAME _T("C:\\filecopy.avi") //<<--- Change here file name.
long readList(ifstream* favi,long chunk_size);
#define UNPACK_FOURCC(lfourcc,four
(fourcc)[1] = (char)((lfourcc >> 8) & 0x00FF);\
(fourcc)[2] = (char)((lfourcc >> 16) & 0x00FF);\
(fourcc)[3] = (char)((lfourcc >> 24) & 0x00FF);
void printFOURCC(char* Msg, char fourcc[4])
{
cout<< Msg << fourcc[0]<< fourcc[1] << fourcc[2] << fourcc[3] << endl;
}
long readChunkDsc(ifstream* favi, char* fourcc, long* chunk_size)
{
long lfourcc = 0;
favi->read((char*)&lfourcc
UNPACK_FOURCC(lfourcc,four
long qq=0;
favi->read((char *)&qq,sizeof(long));
*chunk_size = qq;
return *chunk_size;
}
void printAviHeader(AVIMAINHEAD
{
cout << " ==== AVI HEADER ====" << endl;
}
void printAviStreamHeader(AVIST
{
cout << " ==== AVI STREAM HEADER ====" <<endl;
}
bool readAviHeader(ifstream* favi,AVIMAINHEADER* avimainhdr)
{
favi->read((char *)avimainhdr,sizeof(AVIMAI
return favi->good();
}
long readhdrlList(ifstream* favi,long ch_size)
{
char chunk_id[4];
long chunk_size;
long len = 0;
while (ch_size>len)
{
readChunkDsc(favi, (char *)chunk_id, &chunk_size);
long pad = favi->tellg();
if (chunk_size == 0)
return 0;
if (strncmp(chunk_id,"LIST",4
readList(favi,chunk_size);
if (strncmp(chunk_id,"avih",4
{
AVIMAINHEADER hdr;
readAviHeader(favi,&hdr);
printAviHeader(&hdr);
}
len += chunk_size + 8;
favi->seekg(chunk_size + pad, ios::beg);
}
return chunk_size;
}
typedef struct tagRGBQUAD {
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
} RGBQUAD;
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO;
BITMAPINFO *bmpinf = NULL;
long sz_BITMAPINFO = 0;
long readstrlList(ifstream* favi,long ch_size)
{
char chunk_id[4];
long chunk_size;
long len = 4;
int flag_set = 0;
while (ch_size>len)
{
readChunkDsc(favi, (char *)chunk_id, &chunk_size);
long pad = favi->tellg();
if (chunk_size == 0)
return 0;
if (strncmp(chunk_id,"LIST",4
readList(favi,chunk_size);
if (strncmp(chunk_id,"strh",4
{
AVISTREAMHEADER hdr;
favi->read((char *)&hdr,sizeof(AVISTREAMHEA
if (strncmp(hdr.fccType, "vids",4) == 0)
flag_set = 1;
printAviStreamHeader(&hdr)
}
if (flag_set && strncmp(chunk_id,"strf",4)
{
bmpinf = (BITMAPINFO *) malloc(chunk_size);
favi->read((char*)bmpinf, chunk_size);
sz_BITMAPINFO = chunk_size;
flag_set = 0;
}
if ((chunk_size % 2) == 1)
chunk_size +=1;
len += chunk_size + 8;
favi->seekg(chunk_size + pad, ios::beg);
}
return chunk_size;
}
void printmovichunkinfo(char chunk_id[4])
{
cout << "Stream " << chunk_id[0] << chunk_id[1] << endl;
if (strncmp(&chunk_id[2],"db"
cout << "Uncompressed video" << endl;
if (strncmp(&chunk_id[2],"dc"
cout << "Compressed video" << endl;
if (strncmp(&chunk_id[2],"pc"
cout << "palette change" << endl;
if (strncmp(&chunk_id[2],"wb"
cout << "Audio Data" << endl;
}
bool copyBMPtoFile(ifstream *favi,long chunk_size, long fnameid)
{
BITMAPFILEHEADER bmfh;
memset(&bmfh,0,sizeof(BITM
bmfh.bfType[0] = 'B';
bmfh.bfType[1] = 'M';
bmfh.bfSize = (unsigned long)(chunk_size + sizeof(BITMAPFILEHEADER) + sz_BITMAPINFO);
bmfh.bfOffBits = sz_BITMAPINFO + sizeof(BITMAPFILEHEADER);
ofstream fout;
char * buf = new char[chunk_size];
try
{
strstream str_str;
str_str << "c:\\" << "bmp" << fnameid << ".bmp" << '\0';
fout.open(str_str.str(),io
favi->read(buf, chunk_size);
fout.write((char *)(void *)&bmfh,sizeof(BITMAPFILEH
fout.write((char *)bmpinf,sz_BITMAPINFO);
fout.write(buf, chunk_size);
fout.close();
}
catch(...)
{
cout << "copy to bmp failed" << endl;
}
delete [] buf;
return favi->good();
}
long readmoviList(ifstream* favi,long ch_size)
{
long len = 4;
int imgNumber = 1;
long chunk_size;
char chunk_id[4];
while (ch_size>len)
{
memset(&chunk_id[0],0,4);
readChunkDsc(favi, (char *)chunk_id, &chunk_size);
long pad = favi->tellg();
if (chunk_size == 0)
return 0;
if (strncmp(chunk_id,"LIST",4
readList(favi,chunk_size);
else
{
printmovichunkinfo(chunk_i
cout << "Chunk Size: " << chunk_size << endl;
copyBMPtoFile(favi,chunk_s
favi->seekg(chunk_size + pad, ios::beg);
}
len += chunk_size + 8;
}
return chunk_size;
}
long readIdxList(ifstream* favi,long chunk_size)
{
return chunk_size;
}
long readmovirecList(ifstream* favi,long ch_size)
{
long len = 4;
int imgNumber = 1;
long chunk_size;
char chunk_id[4];
while (ch_size>len)
{
memset(&chunk_id[0],0,4);
long pad = favi->tellg();
readChunkDsc(favi, (char *)chunk_id, &chunk_size);
pad = favi->tellg();
if (chunk_size == 0)
return 0;
if (strncmp(chunk_id,"LIST",4
readList(favi,chunk_size);
// printFOURCC("Chunk_id: ",chunk_id);
if (strncmp(chunk_id,"JUNK",4
{
printmovichunkinfo(chunk_i
cout << "Chunk Size: " << chunk_size << endl;
copyBMPtoFile(favi,chunk_s
}
favi->seekg(chunk_size + pad, ios::beg);
len += chunk_size + 8;
}
return chunk_size;
}
long readList(ifstream* favi,long chunk_size)
{
char listtype[4];
long pos = favi->tellg();
favi->read((char *)&listtype[0], sizeof(listtype));
printFOURCC("List Type: ", listtype);
if(strncmp(listtype,"hdrl"
readhdrlList(favi,chunk_si
else if(strncmp(listtype,"movi"
readmoviList(favi,chunk_si
else if(strncmp(listtype,"idx1"
readIdxList(favi,chunk_siz
else if(strncmp(listtype,"indx"
readIdxList(favi,chunk_siz
else if(strncmp(listtype,"strl"
readstrlList(favi,chunk_si
else if(strncmp(listtype,"rec ",4) == 0)
readmovirecList(favi,chunk
favi->seekg(pos + chunk_size);
return chunk_size;
}
int _tmain(int argc, _TCHAR* argv[])
{
ifstream favi;
favi.open(AVI_FILE_NAME,io
if (favi == NULL)
{
cout << "Can't open file " << AVI_FILE_NAME << endl;
}
try
{
RIFFHDR rh;
favi.read((char *)&rh,sizeof(rh));
printFOURCC("RIFF header: ",rh.FOURCC);
cout << "FileSize: "<<rh.filesize << endl;
printFOURCC("FileType: ",rh.filetype);
char chid[4];
memset(&chid[0],0,4);
long chunk_size;
long chunk_pos = favi.tellg();
while(!favi.eof())
{
if (readChunkDsc(&favi,(char *)chid,&chunk_size))
{
printFOURCC("Chunk ID: ",chid);
cout << "Chunk Size: " << chunk_size << endl;
if (strncmp(chid,"LIST",4) == 0)
{
//readlist
readList(&favi,chunk_size)
}
if (strncmp(chid,"hdrl",4) == 0)
{
//read hdrl
cout << "hdrl chunk" << endl;
}
if (strncmp(chid,"movi",4) == 0)
{
//read movi
cout << "movi chunk" << endl;
}
if (strncmp(chid,"idx1",4) == 0)
{
//read movi
cout << "idx1 chunk" << endl;
}
}
else
break;
favi.seekg( chunk_pos + chunk_size + 8,ios::beg);
chunk_pos = favi.tellg();
}
}
catch(...)
{
}
free(bmpinf);
favi.close();
char _a;
cin >> _a;
}
====end of aviparser.cpp===
Tell me if this is what you need?
They have different format I
think. For larger files used some kind of codecs...(DivX, XviD and so
on). so you can't extract bitmaps directly from AVI.
this is the clasic schema how video Player works...
FileParser->Codec->Frames- >Monitor(B MP) and there io no codecs in my prog FileParser->Frames->Monito r. So youcan work only with "original" avi(created without codecs).
Is it motion estimation? I'm not sure. This is like frames stored in avi.
this is the clasic schema how video Player works...
FileParser->Codec->Frames-
Is it motion estimation? I'm not sure. This is like frames stored in avi.
in idx1 chunk stored following structure:
typedef struct _avioldindex {
FOURCC fcc;
DWORD cb;
struct _avioldindex_entry {
DWORD dwChunkId;
DWORD dwFlags;
DWORD dwOffset;
DWORD dwSize;
} aIndex[];
} AVIOLDINDEX;
where dwFlags can contain AVIIF_KEYFRAME which mean that this frame is full picture, frames between key frames contains just difference images.
AVIMAINHEADER also contains dwFlags that can be AVIF_HASINDEX - means that avi file contain idx1 chunk and AVIF_MUSTUSEINDEX - which means that you should use index instead of physical ordering of chunks.
look this three links:
http://msdn.microsoft.com/ library/de fault.asp? url=/libra ry/ en-us/d irectx9_c/ directx/ht m/avioldin dexstructu re.asp
http://msdn.microsoft.com/ library/de fault.asp? url=/libra ry/ en-us/d irectx9_c/ directx/ht m/avirifff ilereferen ce.asp
http://msdn.microsoft.com/ library/de fault.asp? url=/libra ry/ en-us/d irectx9_c/ directx/ht m/avimainh eaderstruc ture.asp
typedef struct _avioldindex {
FOURCC fcc;
DWORD cb;
struct _avioldindex_entry {
DWORD dwChunkId;
DWORD dwFlags;
DWORD dwOffset;
DWORD dwSize;
} aIndex[];
} AVIOLDINDEX;
where dwFlags can contain AVIIF_KEYFRAME which mean that this frame is full picture, frames between key frames contains just difference images.
AVIMAINHEADER also contains dwFlags that can be AVIF_HASINDEX - means that avi file contain idx1 chunk and AVIF_MUSTUSEINDEX - which means that you should use index instead of physical ordering of chunks.
look this three links:
http://msdn.microsoft.com/
http://msdn.microsoft.com/
http://msdn.microsoft.com/
*********************************************************************************
****************************************************
using System; using System.IO; using System.Text; using System.Threading; using Utility; using System.Collections; using System.Collections.Generic; using themonospot_Base_Main; namespace themonospot_Base_Main { /// <summary> /// AVI Parser for Themonospot /// </summary> public class clsParserAVI : IParser { #region CONSTANTS public const int DWORDSIZE = 4; public const int TWODWORDSSIZE = 8; public static readonly string RIFF4CC = "RIFF"; public static readonly string RIFX4CC = "RIFX"; public static readonly string LIST4CC = "LIST"; // Known file types public static readonly int ckidAVI = Utility.clsEncoding.ToFourCC("AVI "); public static readonly int ckidWAV = Utility.clsEncoding.ToFourCC("WAVE"); public static readonly int ckidRMID = Utility.clsEncoding.ToFourCC("RMID"); #endregion #region GENERIC OBJECTS public List<clsInfoItem> VideoItems { get {return _VideoItems; } } public List<clsInfoItem> AudioItems { get {return _AudioItems; } } private List<clsInfoItem> _VideoItems; private List<clsInfoItem> _AudioItems; private AVIMAINHEADER myAviHeader = new AVIMAINHEADER(); private AVISTREAMHEADER[] myAviStreamHeader = new AVISTREAMHEADER[0]; private BITMAPINFOHEADER[] myAviBitMap = new BITMAPINFOHEADER[0]; private WAVEFORMATEX[] myAviWave = new WAVEFORMATEX[0]; private string[] myUData = new string[0]; private string[] myMUData = new string[0]; private string _m_filename; private string _m_shortname; private string _udToChange = ""; private long _m_fourCC_AviStreamHeader; private long _m_fourCC_AviVideoHeader; private long _m_filesize; private long _m_posStream; private long _m_MoviSize=0; private long _m_MoviSizeNew=0; private long _m_MoviStart=0; private long _m_IdxSize=0; private long _m_IdxStart=0; private double sizOfAudio=0; private FileStream aviStreamReader = null; private FileStream outFile = null; private bool pbDetect = false; private bool _rec_ix_presence = false; private int stdBufferSize = 4096; private int newTotalBytes = 0; long[] framesOffset = new long[0]; long[] framesSize = new long[0]; #endregion GENERIC OBJECTS #region PROPERTIES public string udToChange { get { return _udToChange;} set { _udToChange = value ;} } public bool rec_ix_presence { get { return _rec_ix_presence;} } public long fourCC_AVISTREAMHEADER_offset { get { return _m_fourCC_AviStreamHeader;} } public long fourCC_AVIVIDEOHEADER_offset { get { return _m_fourCC_AviVideoHeader;} } public AVIMAINHEADER headerFile { get { return myAviHeader;} } public BITMAPINFOHEADER[] videoStreams { get { return myAviBitMap;} } public WAVEFORMATEX[] audioStreams { get { return myAviWave;} } public AVISTREAMHEADER[] headerStreams { get { return myAviStreamHeader;} } public string[] userData { get { return myUData;} } public string[] MOVIuserData { get { return myMUData;} } public string m_filename { get { return _m_filename; } } public string m_shortname { get { return _m_shortname; } } public long m_filesize { get { return _m_filesize; } } public long m_MoviSize { get { return _m_MoviSize; } set { _m_MoviSize = value; } } public long m_MoviStart { get { return _m_MoviStart; } set { _m_MoviStart = value; } } public long m_IdxSize { get { return _m_IdxSize; } set { _m_IdxSize = value; } } public long m_IdxStart { get { return _m_IdxStart; } set { _m_IdxStart = value; } } #endregion PROPERTIES #region METHODS TO ADD ITEMS AT STRUCTURES private void addNew_AVISTREAMHEADER() { int j; if (myAviStreamHeader == null) { // There isn't any elements myAviStreamHeader = new AVISTREAMHEADER[1]; } else { // There is another element AVISTREAMHEADER[] tmpASR; tmpASR = new AVISTREAMHEADER[myAviStreamHeader.Length + 1]; for (j=0; j<myAviStreamHeader.Length; j++) { tmpASR[j] = myAviStreamHeader[j]; } myAviStreamHeader = tmpASR; } return; } private void addNew_BITMAPINFOHEADER() { int j; if (myAviBitMap == null) { // There isn't any elements myAviBitMap = new BITMAPINFOHEADER[1]; } else { // There is another element BITMAPINFOHEADER[] tmpASR; tmpASR = new BITMAPINFOHEADER[myAviBitMap.Length + 1]; for (j=0; j<myAviBitMap.Length; j++) { tmpASR[j] = myAviBitMap[j]; } myAviBitMap = tmpASR; } return; } private void addNew_WAVEFORMATEX() { int j; if (myAviWave == null) { // There isn't any elements myAviWave = new WAVEFORMATEX[1]; } else { // There is another element WAVEFORMATEX[] tmpASR; tmpASR = new WAVEFORMATEX[myAviWave.Length + 1]; for (j=0; j<myAviWave.Length; j++) { tmpASR[j] = myAviWave[j]; } myAviWave = tmpASR; } return; } private void addNew_STRING() { int j; if (myUData == null) { // There isn't any elements myUData = new string[1]; } else { // There is another element string[] tmpASR; tmpASR = new string[myUData.Length + 1]; for (j=0; j<myUData.Length; j++) { tmpASR[j] = myUData[j]; } myUData = tmpASR; } return; } private void addNew_moviSTRING() { int j; if (myMUData == null) { // There isn't any elements myMUData = new string[1]; } else { // There is another element string[] tmpASR; tmpASR = new string[myMUData.Length + 1]; for (j=0; j<myMUData.Length; j++) { tmpASR[j] = myMUData[j]; } myMUData = tmpASR; } return; } #endregion METHODS TO ADD ITEMS AT STRUCTURES public clsParserAVI() { } /// <summary> /// Parse the selected file /// </summary> public void OpenFile(string FileName) { // File Not Found... if (File.Exists(FileName) != true) throw new ParserException("File (" + FileName + ") Not Found..."); _VideoItems = new List<clsInfoItem>(); _AudioItems = new List<clsInfoItem>(); // Read File Infos FileInfo fi = new FileInfo(FileName); _m_filename = fi.FullName; _m_shortname = fi.Name; _m_filesize = fi.Length; // DEBUG Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine("_m_filename = " + _m_filename); Console.WriteLine("_m_shortname = " + _m_shortname); Console.WriteLine("_m_filesize = " + _m_filesize.ToString("#,###.##")); // Open the streamer aviStreamReader = new FileStream(_m_filename, FileMode.Open, FileAccess.Read, FileShare.Read); _m_posStream = 0; #region Verify Integrity // Detect File Format int FourCC = readDWord(); _m_posStream +=4; string sFourCC; string hexFourCC; int dataSize = readDWord(); int fileType = readDWord(); _m_posStream +=8; // Check FourCC Header sFourCC = Utility.clsEncoding.FromFourCC(FourCC); Console.WriteLine("FourCC ".PadRight(20,(char)46) + sFourCC + " (" + dataSize.ToString("#,###.##") + ")"); if (sFourCC != RIFF4CC && sFourCC != RIFX4CC) { // No Riff File aviStreamReader.Close(); aviStreamReader = null; throw new ParserException("Error. Not a valid RIFF file"); } // Check File Size if (_m_filesize < (dataSize + 8) ) { // No Riff File aviStreamReader.Close(); aviStreamReader = null; throw new ParserException("Error. Truncated file"); } #endregion byte[] tmpByteArray; int byteToRead; int readBytes; long byteOfList; int byteOfINFO=0; int byteOfINFOReaded=0; string strType = ""; _m_fourCC_AviVideoHeader = 0; _m_fourCC_AviStreamHeader = 0; // Loop until EOF while (_m_posStream < _m_filesize ) { FourCC = readDWord(); sFourCC = Utility.clsEncoding.FromFourCC(FourCC); hexFourCC = FourCC.ToString("X8"); byteToRead = readDWord(); // Adjust bytes to read (no odd) // TO VERIFY *********************************** if (byteToRead % 2 != 0) byteToRead++; _m_posStream +=8; Console.WriteLine("FourCC ".PadRight(20,(char)46) + sFourCC + " (" + byteToRead.ToString("#,###.##") + ") [" + hexFourCC + "]" + " filepos=" + _m_posStream.ToString("#,###.00") ); // Check REC? or IX?? FourCC presence if (sFourCC.ToLower().Substring(3) == "rec" || sFourCC.ToLower().Substring(2) == "ix" ) { _rec_ix_presence = true; } // Check memory if (_m_posStream + byteToRead > _m_filesize) { aviStreamReader.Close(); aviStreamReader = null; return; } // Parse FourCC if (sFourCC == LIST4CC) { // LIST section FourCC = readDWord(); _m_posStream += 4; sFourCC = Utility.clsEncoding.FromFourCC(FourCC); hexFourCC = FourCC.ToString("X8"); byteOfList = byteToRead; Console.WriteLine("LIST type ".PadRight(20,(char)46) + sFourCC + "[" + hexFourCC + "]"+ " filepos=" + _m_posStream.ToString("#,###.00") ); // Verify FourCC if (FourCC == AviRiffData.ckidAVIMovieData) { // skip "movi" section 6D 6F 76 69 _m_MoviStart = aviStreamReader.Position; _m_posStream += byteOfList-4; // aviStreamReader.Seek(byteOfList-4, SeekOrigin.Current); parseMoviChunk(byteOfList-4); _m_MoviSize = byteOfList-4; } else if (FourCC == AviRiffData.ckidINFOList ) { // INFO section byteOfINFOReaded=0; byteOfINFO=(int)(byteOfList-4); } } else { // Other TAGS if(FourCC == AviRiffData.ckidMainAVIHeader) { // "avih" tmpByteArray = new byte[56]; readBytes = aviStreamReader.Read(tmpByteArray,0,56); _m_posStream +=readBytes; myAviHeader.loadDataStructure(tmpByteArray); } else if(FourCC == AviRiffData.ckidAVIStreamHeader) { // "strh" tmpByteArray = new byte[byteToRead]; readBytes = aviStreamReader.Read(tmpByteArray,0,byteToRead); _m_posStream +=byteToRead; // Update Array of Stream Headers addNew_AVISTREAMHEADER(); AVISTREAMHEADER tmpSH = new AVISTREAMHEADER(); tmpSH.loadDataStructure(tmpByteArray); myAviStreamHeader[ myAviStreamHeader.Length-1 ] = tmpSH; strType = clsEncoding.FromFourCC(tmpSH.fccType); Console.WriteLine("STREAM TYPE ".PadRight(20,(char)46) + clsEncoding.FromFourCC(tmpSH.fccType) ); Console.WriteLine("STREAM HEARER ".PadRight(20,(char)46) + clsEncoding.FromFourCC(tmpSH.fccHandler) ); // fourCC_AviStreamHeader position if (_m_fourCC_AviVideoHeader == 0) _m_fourCC_AviStreamHeader = _m_posStream - (byteToRead - 4); } else if(FourCC == AviRiffData.ckidStreamFormat) { // "strf" if (strType == "vids") { tmpByteArray = new byte[byteToRead]; readBytes = aviStreamReader.Read(tmpByteArray,0,byteToRead); _m_posStream +=readBytes; // fourCC_AviVideoHeader position _m_fourCC_AviVideoHeader = _m_posStream - 24; // Update Array of Stream Format Video addNew_BITMAPINFOHEADER(); BITMAPINFOHEADER tmpBMP = new BITMAPINFOHEADER(); tmpBMP.loadDataStructure(tmpByteArray); myAviBitMap[ myAviBitMap.Length-1 ] = tmpBMP; } else if (strType == "auds") { tmpByteArray = new byte[byteToRead]; readBytes = aviStreamReader.Read(tmpByteArray,0,byteToRead); _m_posStream +=readBytes; // Update Array of Stream Format Video addNew_WAVEFORMATEX(); WAVEFORMATEX tmpWFR = new WAVEFORMATEX(); tmpWFR.loadDataStructure(tmpByteArray); myAviWave[ myAviWave.Length-1 ] = tmpWFR; string strAudioType = tmpWFR.wFormatTag.ToString("X4"); } else { // other FourCC in a stream list aviStreamReader.Seek(byteToRead, SeekOrigin.Current); _m_posStream +=byteToRead; } } else if(FourCC == AviRiffData.ckidAVIOldIndex) { // "idx1" // parseIdxChunk(byteToRead); _m_IdxStart = aviStreamReader.Position; _m_IdxSize = byteToRead; aviStreamReader.Seek(byteToRead, SeekOrigin.Current); _m_posStream +=byteToRead; } else if(FourCC == AviRiffData.ckidJUNKTag) { // "JUNK" // Skip tmpByteArray = new byte[byteToRead]; readBytes = aviStreamReader.Read(tmpByteArray,0,byteToRead); _m_posStream +=readBytes; clsEncoding myEnc = new clsEncoding(); string theStrData = myEnc.getAsciiFromArray(tmpByteArray); if (theStrData.Trim() != "") { addNew_STRING(); myUData[myUData.Length-1] = theStrData; Console.WriteLine("JUNKDATA ".PadRight(20,(char)46) + myEnc.getAsciiFromArray(tmpByteArray)); } // aviStreamReader.Seek(byteToRead, SeekOrigin.Current); } else if(FourCC == AviRiffData.ckidAVIISFT) { // "ISFT" tmpByteArray = new byte[byteToRead]; readBytes = aviStreamReader.Read(tmpByteArray,0,byteToRead); _m_posStream +=readBytes; byteOfINFOReaded += byteToRead+8; addNew_STRING(); clsEncoding myEnc = new clsEncoding(); myUData[myUData.Length-1] = myEnc.getAsciiFromArray(tmpByteArray); Console.WriteLine("ISFTDATA ".PadRight(20,(char)46) + myEnc.getAsciiFromArray(tmpByteArray)); // Check remaining byte if ((byteOfINFO - byteOfINFOReaded) < 8 ) aviStreamReader.Seek((byteOfINFO - byteOfINFOReaded), SeekOrigin.Current); _m_posStream +=(byteOfINFO - byteOfINFOReaded); } else { // other FourCC aviStreamReader.Seek(byteToRead, SeekOrigin.Current); _m_posStream +=byteToRead; } } } // end while (_m_posStream < dataSize) // Close the streamer aviStreamReader.Close(); aviStreamReader = null; GetAudioInformations(); GetVideoInformations(); return; } // Parse MOVI Chunk to extract xxdc or xxdb subarea private void parseMoviChunk(long MoviChunkSize) { long tmpMoviPointer = 0; int FourCC = 0; int byteOfRead = 0; string sFourCC = ""; int frameCount = 0; pbDetect=false; while (tmpMoviPointer < MoviChunkSize) { FourCC = readDWord(); sFourCC = Utility.clsEncoding.FromFourCC(FourCC); byteOfRead = readDWord(); // Adjust bytes to read (no odd) if ((byteOfRead % 2) != 0 ) byteOfRead++; tmpMoviPointer += 8; // Console.WriteLine(sFourCC + " Founded, size = " + byteOfRead.ToString()); if (sFourCC.Substring(2,2) == "dc" || sFourCC.Substring(2,2) == "db") { frameCount ++; if (frameCount == 1) parseDCuserdata(byteOfRead); else parseDCvopdata(byteOfRead); tmpMoviPointer += byteOfRead; // scan only first 100 xxdc or xxdb frames in MOVI chunk if (frameCount >= 200) { aviStreamReader.Seek(MoviChunkSize - tmpMoviPointer, SeekOrigin.Current); tmpMoviPointer += (MoviChunkSize - tmpMoviPointer); } } else { //Console.WriteLine(sFourCC + " Founded, size = " + byteOfRead.ToString()); aviStreamReader.Seek(byteOfRead, SeekOrigin.Current); tmpMoviPointer += byteOfRead; } } } // Extract UserData info from DC subarea private void parseDCuserdata(long DCsubareaSize) { //aviStreamReader.Seek(DCsubareaSize, SeekOrigin.Current); clsEncoding myEnc = new clsEncoding(); string outValue=""; int sPoint = 0; int ePoint = 0; byte[] dcBuffer = new byte[(int)DCsubareaSize]; aviStreamReader.Read(dcBuffer,0,(int)DCsubareaSize); // Find UserData ... START sPoint = myEnc.compareBytesArray(dcBuffer, AviRiffData.UserDataBytes, 0); while (sPoint < DCsubareaSize && sPoint >= 0) { ePoint = myEnc.compareBytesArray(dcBuffer, AviRiffData.UserDataBytes, sPoint + 3); if (ePoint < 0) ePoint = myEnc.compareBytesArray(dcBuffer, AviRiffData.VOLStartBytes , sPoint + 3); if (ePoint < 0) ePoint = myEnc.compareBytesArray(dcBuffer, AviRiffData.VOPStartBytes , sPoint + 3); if (ePoint < 0) { // from sPoint to end of Byte Array outValue = myEnc.getHexFromBytes(dcBuffer,sPoint+4, ((int)DCsubareaSize - (sPoint+3))); addNew_moviSTRING(); myMUData[myMUData.Length-1] = myEnc.getAsciiFromHex(outValue); Console.WriteLine("UD founded".PadRight(20,(char)46) + myEnc.getAsciiFromHex(outValue)); break; } else { // from sPoint to ePoint outValue = myEnc.getHexFromBytes(dcBuffer,sPoint+4, (ePoint - (sPoint+4))); addNew_moviSTRING(); myMUData[myMUData.Length-1] = myEnc.getAsciiFromHex(outValue); Console.WriteLine("UD founded".PadRight(20,(char)46) + myEnc.getAsciiFromHex(outValue)); sPoint = myEnc.compareBytesArray(dcBuffer, AviRiffData.UserDataBytes, ePoint); } } // Find UserData ... END dcBuffer = null; } // Extract VOP count in to DC subarea (Packet Bitstream Detect) private void parseDCvopdata(long DCsubareaSize) { //aviStreamReader.Seek(DCsubareaSize, SeekOrigin.Current); clsEncoding myEnc = new clsEncoding(); //string outValue=""; int sPoint = 0; //int ePoint = 0; int vopCount = 0; byte[] dcBuffer = new byte[(int)DCsubareaSize]; aviStreamReader.Read(dcBuffer,0,(int)DCsubareaSize); // Find Packed Bitstream ... START sPoint = myEnc.compareBytesArray(dcBuffer, AviRiffData.VOPStartBytes, 0); while (sPoint < (DCsubareaSize-2) && sPoint >= 0) { vopCount++; sPoint = myEnc.compareBytesArray(dcBuffer, AviRiffData.VOPStartBytes, sPoint+3); } // Find Packed Bitstream ... END // Debug Packet Bitstream Detect // Console.WriteLine("VOP detect".PadRight(20,(char)46) + vopCount.ToString()); if (vopCount > 1) pbDetect = true; dcBuffer = null; } // Parse IDX_ Chunk to extract index private void parseIdxChunk(long IdxChunkSize) { long tmpIdxPointer = 0; int FourCC = 0; int byteOfRead = 0; string sFourCC = ""; int frameCount = 0; while (tmpIdxPointer < IdxChunkSize) { FourCC = readDWord(); sFourCC = Utility.clsEncoding.FromFourCC(FourCC); // Adjust bytes to read (no odd) if ((byteOfRead % 2) != 0 ) byteOfRead++; tmpIdxPointer += 4; frameCount ++; // Console.WriteLine(sFourCC + " Founded, size = " + (byteOfRead).ToString()); aviStreamReader.Seek(12, SeekOrigin.Current); tmpIdxPointer += 12; } Console.WriteLine("Total Frame Counted: " + frameCount.ToString() ); } /// <summary> /// Detect audio codec /// </summary> /// <param name="audioVal">codec id</param> /// <returns>codec string name</returns> public string parseAudioType(string audioVal) { // return name of codec audio if (audioVal == "0055") return "0x" + audioVal + " (MP3)"; else if (audioVal == "0001") return "0x" + audioVal + " (PCM)"; else if (audioVal == "2001") return "0x" + audioVal + " (DTS)"; else if (audioVal == "000A") return "0x" + audioVal + " (WMA9)"; else if (audioVal == "0030") return "0x" + audioVal + " (Dolby AC2)"; else if (audioVal == "0050") return "0x" + audioVal + " (MPEG)"; else if (audioVal == "2000") return "0x" + audioVal + " (AC3)"; else return "0x" + audioVal + " (?)"; } public void saveNewAvi(string newFileName, ref bool _redrawInfo, ref string _saveError, ref double _saveStatus, ref bool _saveFlag, ref double _totProgressItems, ref string _saveInfo ) { // Begin Write new avi file aviStreamReader = new FileStream(_m_filename, FileMode.Open, FileAccess.Read, FileShare.Read); outFile = new FileStream(newFileName, FileMode.Create,FileAccess.Write, FileShare.None); FileInfo fi = new FileInfo(_m_filename); long filmsize = fi.Length; long filmoffset = 0; long diffBytes = 0; byte[] tmpBytes; int totMoviItems = Convert.ToInt32(_m_IdxSize / 16) + 3000; framesOffset = new long[ totMoviItems ]; framesSize = new long[ totMoviItems ]; int bufferSize = stdBufferSize; // Write data before MOVI chunk _totProgressItems = (double)_m_MoviStart; Console.WriteLine("Write Header START"); _saveInfo = clsLanguages.EXPMESSAGE1; _redrawInfo=true; Console.WriteLine("filmoffset = " + filmoffset.ToString() + " - _m_MoviStart = " + _m_MoviStart.ToString() ); while (filmoffset < _m_MoviStart) { if ((filmoffset + bufferSize) > _m_MoviStart) bufferSize = (int)(_m_MoviStart - filmoffset); tmpBytes = new byte[bufferSize]; aviStreamReader.Read(tmpBytes, 0, bufferSize); outFile.Write(tmpBytes, 0, bufferSize); _saveStatus = (double)filmoffset; // myPBar.Text = Convert.ToInt32(myPBar.Fraction * 100).ToString("D3") + "%"; if (_saveFlag == false) { outFile.Close(); outFile.Dispose(); outFile = null; aviStreamReader.Close(); aviStreamReader.Dispose(); aviStreamReader = null; return; } filmoffset += bufferSize; } Console.WriteLine("Write Header END"); // Write new MOVI chunk from old if (writeMoviChunk(ref _redrawInfo, ref _saveError, ref _saveStatus, ref _saveFlag, ref _totProgressItems, ref _saveInfo) != 0) { outFile.Close(); outFile.Dispose(); outFile = null; aviStreamReader.Close(); aviStreamReader.Dispose(); aviStreamReader = null; return; } // Write data before IDX1 chunk diffBytes = (_m_IdxStart - aviStreamReader.Position); bufferSize = stdBufferSize; _saveStatus = 0; _totProgressItems = (double)diffBytes; filmoffset = 0; Console.WriteLine("Write CONTENT_1 START"); _saveInfo = clsLanguages.EXPMESSAGE2; _redrawInfo = true; while (filmoffset < diffBytes) { if ((filmoffset + bufferSize) > diffBytes) bufferSize = (int)(diffBytes - filmoffset); tmpBytes = new byte[bufferSize]; aviStreamReader.Read(tmpBytes, 0, bufferSize); outFile.Write(tmpBytes, 0, bufferSize); _saveStatus = (double)filmoffset; // myPBar.Text = Convert.ToInt32(myPBar.Fraction * 100).ToString("D3") + "%"; if (_saveFlag == false) { outFile.Close(); outFile.Dispose(); outFile = null; aviStreamReader.Close(); aviStreamReader.Dispose(); aviStreamReader = null; return; } filmoffset += bufferSize; } Console.WriteLine("Write CONTENT 1 END"); // Write new IDX1 chunk from new MOVI created if (writeIdx1Chunk(ref _redrawInfo, ref _saveError, ref _saveStatus, ref _saveFlag, ref _totProgressItems, ref _saveInfo) != 0) { outFile.Close(); outFile.Dispose(); outFile = null; aviStreamReader.Close(); aviStreamReader.Dispose(); aviStreamReader = null; return; } // Write data after IDX1 chunk diffBytes = (filmsize - aviStreamReader.Position); bufferSize = stdBufferSize; _saveStatus = 0; _totProgressItems = (double)diffBytes; filmoffset = 0; Console.WriteLine("Write CONTENT 2 START"); _saveInfo = clsLanguages.EXPMESSAGE2; _redrawInfo = true; while (filmoffset < diffBytes) { if ((filmoffset + bufferSize) > diffBytes) bufferSize = (int)(diffBytes - filmoffset); tmpBytes = new byte[bufferSize]; aviStreamReader.Read(tmpBytes, 0, bufferSize); outFile.Write(tmpBytes, 0, bufferSize); _saveStatus = (double)filmoffset; // myPBar.Text = Convert.ToInt32(myPBar.Fraction * 100).ToString("D3") + "%"; if (_saveFlag == false) { outFile.Close(); outFile.Dispose(); outFile = null; aviStreamReader.Close(); aviStreamReader.Dispose(); aviStreamReader = null; return; } filmoffset += bufferSize; } Console.WriteLine("Write CONTENT 2 END"); // Close output outFile.Close(); outFile.Dispose(); outFile = null; // Read File Infos fi = new FileInfo(newFileName); newTotalBytes = (int)(fi.Length - 8); fi = null; // Update MOVI Size and File Size outFile = new FileStream(newFileName, FileMode.Open,FileAccess.Write, FileShare.None); outFile.Seek(4,SeekOrigin.Begin); outFile.Write(intToByteArray(newTotalBytes),0,4); outFile.Seek(_m_MoviStart - 8,SeekOrigin.Begin); outFile.Write(intToByteArray((int)(_m_MoviSizeNew + 4)),0,4); // Close all streams and return to Main Window outFile.Close(); outFile.Dispose(); outFile = null; aviStreamReader.Close(); aviStreamReader.Dispose(); aviStreamReader = null; _saveFlag=false; } // write MOVI Chunk frames private int writeMoviChunk(ref bool _redrawInfo, ref string _saveError, ref double _saveStatus, ref bool _saveFlag, ref double _totProgressItems, ref string _saveInfo ) { long tmpMoviPointer = 0; int FourCC = 0; int byteOfRead = 0; int sizeOfFrame = 0; int newByteOfRead = 0; string sFourCC = ""; int frameCount = 0; int lenOfFrame = 0; string hexFourCC = ""; byte[] tmpByteArray = new byte[0]; int stepGuiUpdate = 1024; int stepFrame = 0; // Write data before MOVI chunk _saveStatus = 0; _totProgressItems = (double)_m_MoviSize; _saveInfo = clsLanguages.EXPMESSAGE3; _redrawInfo = true; Console.WriteLine("Write MOVI START (" + _m_MoviStart.ToString() + " SIZE " + _m_MoviSize.ToString() + ")"); _m_MoviSizeNew = 0; while (tmpMoviPointer < _m_MoviSize) { // Exit if Cancel button was pressed if (_saveFlag == false) return 1; FourCC = readDWord(); hexFourCC = FourCC.ToString("X8"); sFourCC = Utility.clsEncoding.FromFourCC(FourCC); byteOfRead = readDWord(); tmpMoviPointer += 8; _m_MoviSizeNew += 8; // Adjust bytes to read (no odd) sizeOfFrame = byteOfRead; if ((byteOfRead % 2) != 0 ) byteOfRead++; tmpByteArray = new byte[byteOfRead]; aviStreamReader.Read(tmpByteArray, 0, byteOfRead); stepFrame ++; // Verify frame type if (sFourCC.Substring(2,2) == "dc" || sFourCC.Substring(2,2) == "db") { // tmpByteArray = processFrame(tmpByteArray, ref sizeOfFrame); newByteOfRead = tmpByteArray.Length; framesOffset[frameCount] = outFile.Position; framesSize[frameCount] = (long)newByteOfRead; outFile.Write(intToByteArray(FourCC),0, 4); outFile.Write(intToByteArray(sizeOfFrame),0, 4); outFile.Write(tmpByteArray, 0, newByteOfRead); tmpMoviPointer += byteOfRead; _m_MoviSizeNew += newByteOfRead; } else { framesOffset[frameCount] = outFile.Position; framesSize[frameCount] = (long)byteOfRead; outFile.Write(intToByteArray(FourCC),0, 4); outFile.Write(intToByteArray(sizeOfFrame),0, 4); outFile.Write(tmpByteArray, 0, byteOfRead); tmpMoviPointer += byteOfRead; _m_MoviSizeNew += byteOfRead; } frameCount ++; if (stepFrame >= stepGuiUpdate) { // Update progressbar _saveStatus = (double)tmpMoviPointer; // myPBar.Text = Convert.ToInt32(myPBar.Fraction * 100).ToString("D3") + "%"; stepFrame = 0; } } Console.WriteLine("Tot Frames: " + frameCount.ToString()); Console.WriteLine("Write MOVI END"); return 0; } // Extract UserData info from DC subarea private byte[] processFrame(byte[] inByteArray, ref int frameLength) { clsEncoding myEnc = new clsEncoding(); byte[] tmpByteArray = null; byte[] userdataOld = null; byte[] outByteArray = null; ASCIIEncoding TextEncoding = new ASCIIEncoding(); tmpByteArray = inByteArray; userdataOld = TextEncoding.GetBytes(_udToChange); int startPos = myEnc.compareBytesArray(tmpByteArray, userdataOld,0); // int totalFrameBytes = 0; int totalFrameBytes, newFrameLength; if (startPos >= 0) { // totalFrameBytes = tmpByteArray.Length - _udToChange.Length + 12; newFrameLength = (frameLength - _udToChange.Length) + 12; // Padded to an even number of bytes but make sure the padding isn't included // in the size written to the chunk header or index totalFrameBytes = newFrameLength; if ((totalFrameBytes % 2) != 0) totalFrameBytes ++; // frameLength = totalFrameBytes; // frameLength = newFrameLength; outByteArray = new byte[totalFrameBytes]; Array.Copy(tmpByteArray, outByteArray, startPos); Array.Copy(TextEncoding.GetBytes("DivX999b000p"), 0, outByteArray, startPos, 12); Array.Copy(tmpByteArray, startPos + _udToChange.Length , outByteArray, startPos + 12, frameLength - (_udToChange.Length + startPos)); frameLength = newFrameLength; } else outByteArray = tmpByteArray; return outByteArray; } // Write new Idx1 Chunk private int writeIdx1Chunk(ref bool _redrawInfo, ref string _saveError, ref double _saveStatus, ref bool _saveFlag, ref double _totProgressItems, ref string _saveInfo ) { long tmpIdxPointer = 0; int FourCC = 0; int byteOfRead = 0; string sFourCC = ""; int frameCount = 0; string hexFourCC = ""; byte[] tmpByteArray = new byte[16]; byte[] tmpDWordArray = new byte[4]; int stepGuiUpdate = 256; int stepFrame = 0; // Write data before MOVI chunk _saveStatus = 0; _totProgressItems = (double)_m_IdxSize; _saveInfo = clsLanguages.EXPMESSAGE4; _redrawInfo=true; Console.WriteLine("Write IDX START (" + _m_IdxStart.ToString() + " SIZE " + _m_IdxSize.ToString() + ")"); while (tmpIdxPointer < _m_IdxSize) { // Exit if Cancel button was pressed if (_saveFlag == false) return 1; aviStreamReader.Read(tmpByteArray,0,16); // Offsets are relative to the start of the 'movi' list type tmpDWordArray = intToByteArray((int)(framesOffset[frameCount] - (_m_MoviStart - 4))); for (int j=0; j<4; j++) tmpByteArray[8+j]=tmpDWordArray[j]; tmpDWordArray = intToByteArray((int)framesSize[frameCount]); for (int j=0; j<4; j++) tmpByteArray[12+j]=tmpDWordArray[j]; outFile.Write(tmpByteArray,0,16); tmpIdxPointer += 16; frameCount ++; stepFrame++; if (stepFrame >= stepGuiUpdate) { // Update progressbar _saveStatus = (double)tmpIdxPointer; // myPBar.Text = Convert.ToInt32(myPBar.Fraction * 100).ToString("D3") + "%"; stepFrame = 0; } } Console.WriteLine("Tot Frames: " + frameCount.ToString()); Console.WriteLine("Write IDX END"); return 0; } /// <summary> /// Read 2 bytes and return the value /// </summary> /// <returns></returns> private int readWord() { int retValue; int readBytes; byte[] tmpBuffer = new byte[2]; readBytes = aviStreamReader.Read(tmpBuffer,0,2); retValue = (tmpBuffer[0]) + (tmpBuffer[1]<<8); return retValue; } // returns a byte array of length 4 private byte[] intToByteArray(int i) { byte[] dword = new byte[4]; dword[0] = (byte) (i & 0x00FF); dword[1] = (byte) ((i >> 8) & 0x000000FF); dword[2] = (byte) ((i >> 16) & 0x000000FF); dword[3] = (byte) ((i >> 24) & 0x000000FF); return dword; } /// <summary> /// Read 4 bytes and return the value /// </summary> /// <returns></returns> private int readDWord() { int retValue; int readBytes; byte[] tmpBuffer = new byte[4]; readBytes = aviStreamReader.Read(tmpBuffer,0,4); retValue = tmpBuffer[0]+(tmpBuffer[1]<<8)+(tmpBuffer[2]<<16)+(tmpBuffer[3]<<24); return retValue; } public void change4CC(string ASHval, string VSHval, long ASHpos, long VSHpos) { byte[] tmpASHarray = null; byte[] tmpVSHarray = null; FileStream updaterSW = new FileStream(_m_filename , FileMode.Open ,FileAccess.ReadWrite); updaterSW.Seek(ASHpos, SeekOrigin.Current); tmpASHarray = Utility.clsEncoding.ToFourCCByte(ASHval); Console.WriteLine(tmpASHarray[0].ToString("X2") + tmpASHarray[1].ToString("X2") + tmpASHarray[2].ToString("X2") + tmpASHarray[3].ToString("X2")); updaterSW.Write(tmpASHarray, 0, 4); updaterSW.Seek(VSHpos, SeekOrigin.Begin); tmpVSHarray = Utility.clsEncoding.ToFourCCByte(VSHval); Console.WriteLine(tmpVSHarray[0].ToString("X2") + tmpVSHarray[1].ToString("X2") + tmpVSHarray[2].ToString("X2") + tmpVSHarray[3].ToString("X2")); updaterSW.Write(tmpVSHarray, 0, 4); updaterSW.Close(); updaterSW.Dispose(); updaterSW = null; return; } private void GetVideoInformations () { int k, l; int iV=0; int iA=0; //double sizOfAudio=0; double sizOfVideo=0; double sizOfHeader=0; double videoQuality=0; double WdH=0; int framePerSec=1; int AverageVideoBitRate = 0; string fccDesc = ""; string Frame_Size = ""; string Total_Time = ""; string Frame_Rate = ""; string Total_Frames = ""; string Video_Data_Rate = ""; string Packet_Bitstream = "Off"; Console.WriteLine(myAviStreamHeader.Length); for (k=0; k < headerStreams.Length; k++ ) { Console.WriteLine(k); if(clsEncoding.FromFourCC(headerStreams[k].fccType) != "vids" ) continue; long totalTime = 0; fccDesc = clsEncoding.FromFourCC(headerStreams[k].fccHandler); if (headerFile.dwMicroSecPerFrame > 0) totalTime =(long)((long)headerFile.dwTotalFrames * (long) headerFile.dwMicroSecPerFrame); totalTime = (long)(totalTime / 1000000.0); int hours = (int)(totalTime / 3600); totalTime -= (long)(hours * 3600); int mins = (int)(totalTime / 60); totalTime -= (long)(mins * 60); framePerSec = headerStreams[k].dwRate / headerStreams[k].dwScale; WdH = videoStreams[0].biWidth; WdH /= videoStreams[0].biHeight; Frame_Size = videoStreams[0].biWidth.ToString() + " x " + videoStreams[0].biHeight.ToString(); Total_Time = String.Format("{0:00}:{1:00}:{2:00.00#} seconds", hours, mins, totalTime); Frame_Rate = String.Format("{0:N2} Frames/Sec", (1000000.0 / headerFile.dwMicroSecPerFrame)); Total_Frames = String.Format("{0:G}", headerFile.dwTotalFrames ); Video_Data_Rate = String.Format("{0:N2} frames/Sec", framePerSec ); iV++; } sizOfHeader = headerFile.dwTotalFrames * 8 * (iA+1); sizOfVideo = m_MoviSize - sizOfHeader - sizOfAudio; Console.WriteLine("m_MoviSize = " + m_MoviSize.ToString()); Console.WriteLine("sizOfHeader = " + sizOfHeader.ToString()); Console.WriteLine("sizOfAudio = " + sizOfAudio.ToString()); Console.WriteLine("sizOfVideo = " + sizOfVideo.ToString()); Console.WriteLine("dwTotalFrames = " + headerFile.dwTotalFrames.ToString()); AverageVideoBitRate = (int)((sizOfVideo * framePerSec * 8) / (headerFile.dwTotalFrames * 1000)); videoQuality = (0.75 * WdH) * (AverageVideoBitRate / framePerSec); if (pbDetect == true) Packet_Bitstream = "On"; _VideoItems.Add(new clsInfoItem("Video codec:", clsEncoding.FromFourCC(videoStreams[0].biCompression)) ); _VideoItems.Add(new clsInfoItem("Codec descr:", fccDesc)); _VideoItems.Add(new clsInfoItem("Frame Size:", Frame_Size) ); _VideoItems.Add(new clsInfoItem("Average Video Bitrate:", AverageVideoBitRate.ToString() + " Kb/Sec")); _VideoItems.Add(new clsInfoItem("Avi file size:", ((m_filesize / 1024).ToString("#,### KB")))); _VideoItems.Add(new clsInfoItem("Total Time:", Total_Time )); _VideoItems.Add(new clsInfoItem("Frame Rate:", Frame_Rate)) ; _VideoItems.Add(new clsInfoItem("Total Frames:", Total_Frames)); _VideoItems.Add(new clsInfoItem("Video Data Rate:", Video_Data_Rate )); _VideoItems.Add(new clsInfoItem("Video Quality:", videoQuality.ToString("#,###.##") )); _VideoItems.Add(new clsInfoItem("Packet Bitstream:", Packet_Bitstream )); if (userData.Length >0 ) for (l=0; l<userData.Length;l++) _VideoItems.Add(new clsInfoItem("Info Data[" + l + "]:", userData[l].ToString())); if (MOVIuserData.Length >0 ) { for (l=0; l<MOVIuserData.Length;l++) { _VideoItems.Add(new clsInfoItem("User Data[" + l + "]:", MOVIuserData[l].ToString())); if (MOVIuserData[l].IndexOf("DivX") == 0 && MOVIuserData[l] != "DivX999b000p") this._udToChange = MOVIuserData[l]; } } return; } private void GetAudioInformations () { int k; int iA=0; int blockPerSec=0; sizOfAudio=0; for (k=0; k < headerStreams.Length; k++ ) { if(clsEncoding.FromFourCC(headerStreams[k].fccType) == "vids" ) continue; string aFormat = audioStreams[iA].wFormatTag.ToString("X4"); string CVBR = ""; double audioRate = (8.0 * audioStreams[iA].nAvgBytesPerSec) ; //if (headerStreams[k].dwSampleSize > 0 ) // audioRate /= (double) headerStreams[k].dwSampleSize; if(aFormat == "0055") { CVBR = ""; // MP3 CODEC _AudioItems.Add(new clsInfoItem("Audio " + (iA+1).ToString() + ":", parseAudioType(aFormat) + " " + CVBR + " " + String.Format("{0:N2} Kb/Sec", audioRate / 1000.0) + " " + "- " + audioStreams[iA].nSamplesPerSec + " Hz (" + audioStreams[iA].nChannels.ToString() + " Channels)")); } else { // Other codec _AudioItems.Add(new clsInfoItem("Audio " + (iA+1).ToString() + ":", parseAudioType(aFormat) + " " + String.Format("{0:N2} Kb/Sec", audioRate / 1000.0) + " " + "- " + audioStreams[iA].nSamplesPerSec + " Hz (" + audioStreams[iA].nChannels.ToString() + " Channels)")); } // Calc Data for AVBitrate blockPerSec = headerStreams[k].dwRate / headerStreams[k].dwScale; double tmpAudio = headerStreams[k].dwLength; tmpAudio *= audioStreams[iA].nAvgBytesPerSec; tmpAudio /= blockPerSec; sizOfAudio += tmpAudio; // increment total audio streams iA++; } return; } } }
#include <fstream.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
/*RIFF ('AVI '
LIST ('hdrl'
'avih'(<Main AVI Header>)
LIST ('strl'
'strh'(<Stream header>)
'strf'(<Stream format>)
'strd'(additional header data)
.
.
.
)
.
.
.
)
LIST ('movi'
{SubChunk | LIST('rec '
SubChunk1
SubChunk2
.
.
.
)
.
.
.
}
.
.
.
)
['idx1'<AVIIndex>]
)*/
typedef struct { //The Main AVI Header
DWORD dwMicroSecPerFrame;
DWORD dwMaxBytesPerSec;
DWORD dwReserved1;
DWORD dwFlags;
DWORD dwTotalFrames;
DWORD dwInitialFrames;
DWORD dwStreams;
DWORD dwSuggestedBufferSize;
DWORD dwWidth;
DWORD dwHeight;
DWORD dwScale;
DWORD dwRate;
DWORD dwStart;
DWORD dwLength;
} MainAVIHeader;
typedef struct { //AVI Stream Header
char fccType[4];
char fccHandler[4];
DWORD dwFlags;
DWORD dwReserved1;
DWORD dwInitialFrames;
DWORD dwScale;
DWORD dwRate;
DWORD dwStart;
DWORD dwLength;
DWORD dwSuggestedBufferSize;
DWORD dwQuality;
DWORD dwSampleSize;
} AVIStreamHeader;
/*WAVE Bytes '##wb'
BYTE abBytes[];*/
/*DIB Bits '##db'
BYTE abBits[];*/
typedef struct {
BYTE bFirstEntry;
BYTE bNumEntries;
WORD wFlags;
BYTE *peNew;
} AVIPALCHANGE;
typedef struct {
DWORD ckid;
DWORD dwFlags;
DWORD dwChunkOffset;
DWORD dwChunkLength;
} AVIINDEXENTRY;
typedef struct BMPFILEHEADER {
char type[2];
DWORD size;
DWORD reserved;
DWORD offset;
}FileHeader;
typedef struct BMPINFOHEADER {
DWORD headersize;
DWORD width;
DWORD height;
WORD planes;
WORD bitsperpixel;
DWORD compression;
DWORD sizeimage;
DWORD xpixelspermeter;
DWORD ypixelspermeter;
DWORD colorsused;
DWORD colorsimportant;
} BmpHeader;
typedef struct tagBITMAP {
DWORD width;
DWORD height;
BYTE *data;
}BITMAP;
int main(void)
{
ifstream infile;
ofstream outfile;
infile.open("filedisk.avi"
outfile.open("testnew.bmp"
if (!infile)
cout << "Error opening file";
// DWORD x;
FileHeader bmpf;
bmpf.type[0] = 'B';
bmpf.type[1] = 'M';
bmpf.reserved = 0;
// DWORD size;
// DWORD offset;
BmpHeader bmph;
BITMAP bitmap;
char palette[768];
char ch,che[4];
int i=0,count;
int imageno = 1;
int skip = 0; //This is no. of fields delimited by 'db' and/or 'dc' to skip
int x=0,y=261;
MainAVIHeader avih;
while (!infile.eof())
{
infile >> ch;
if (ch == 'a')
{
infile >> che[0];
infile >> che[1];
infile >> che[2];
che[3] = '\0';
if (!strcmp(che,"vih"))
{
infile.ignore(4);
infile.read((char *)&avih,14*4);
break;
}
}
}
while (!infile.eof())
{
infile >> ch;
if (ch == 'v')
{
infile >> che[0];
infile >> che[1];
infile >> che[2];
che[3] = '\0';
if (!strcmp(che,"ids"))
{
while(1)
{
infile >> ch;
if (ch == 's')
{
infile >> che[0];
infile >> che[1];
infile >> che[2];
che[3] = '\0';
if (!strcmp(che,"trf"))
{
infile.ignore(4);
infile.read((char *)&bmph,40);
// cout << bmph.bitsperpixel;
if (bmph.bitsperpixel != 24)
{
/***read palette information***/
for(i=0;i<256;i++)
{
palette[i*3+2]=infile.get(
palette[i*3+1]=infile.get(
palette[i*3+0]=infile.get(
infile.get();
}
}
bitmap.width=bmph.width;
bitmap.height=bmph.height;
bitmap.data=new BYTE[bitmap.width*bitmap.h
count = bitmap.width*bitmap.height
while(1)
{
infile >> ch;
if (ch == '0')
{
infile >> che[0];
infile >> che[1];
infile >> che[2];
che[3] = '\0';
if (!strcmp(che,"0db") || !strcmp(che,"0dc"))
{
imageno--;
if (imageno == 0)
{
infile >> bitmap.data[i++];
while (1)
{
infile >> ch;
if (ch == '0')
{
infile >> che[0];
infile >> che[1];
infile >> che[2];
che[3] = '\0';
if (!strcmp(che,"0db") || !strcmp(che,"0dc"))
{
skip--;
if (skip == -1)
{
count = i;
bmpf.size = i;
break;
}
}
else
{
bitmap.data[i++] = ch;
bitmap.data[i++] = che[0];
bitmap.data[i++] = che[1];
bitmap.data[i++] = che[2];
if (i > bmph.sizeimage)
break;
}
}
else
{
bitmap.data[i++] = ch;
if (i > bmph.sizeimage)
break;
}
}
break;
}
}
}
}
break;
}
}
}
}
}
// infile.read((char *)&x,4);
// outfile.write((char *)&x,4);
}
bmpf.offset = 54;
bmpf.size += 54;
if (bmph.bitsperpixel != 24)
{
bmpf.offset += 1024;
bmpf.size += 1024;
}
outfile.write((char *)&bmpf,14);
outfile.write((char *)&bmph,40);
for(i=0;i<256;i++)
{
outfile.put(palette[i*3+2]
outfile.put(palette[i*3+1]
outfile.put(palette[i*3+0]
outfile.put(0);
}
outfile.write(bitmap.data,
delete bitmap.data;
outfile.close();
infile.close();
getch();
closegraph();
return 0;
}