这里说的ID3V2一般指的2.3版本,MP3文件后128字节是ID3V1信息,ID3V1大小固定所以信息含量较少,由于项目需要,要读取专辑图片并显示,我找到ID3V2的格式说明,也不知准备不准确,但我读出图片也能成功显示,下面先说说ID3V2的格式,一个含有ID3V2信息的MP3文件,前面一段数据就是ID3V2信息,首先10个字节是标签头,然后是不定长度的标签体,标签体又包括很多部分,每一个部分又分为两部分:数据帧头和数据帧体,数据帧头也是标准的10个字节,不论是标签头还是数据帧头那10个字节都包含了标签体或数据帧体的大小信息,而专辑图片就是一个数据帧,它的数据帧头标示:APIC,数据帧体一般是标准的jpeg格式图片或png图片,数据帧有很多类型,具有不同的数据帧头标示表示,例如AENC、GEOB、LINK、TIT1等。
下面是定义的标签头结构体和数据帧头结构体
typedef struct
{
char identi[3]; // ID3标示
byte major; //版本号 3
byte revsion; // 0
byte flags; //
byte size[4]; //标签体大小
}ID3V2Header;
typedef struct
{
char FrameId[4]; //数据帧标示
byte size[4]; //数据帧体大小
byte flags[2]; //0
}ID3V2Frameheader;
因为是wince下的程序,我这里显示专辑图片是用的Image接口,createimagefrombuffer函数创建Image对象,然后绘制在界面上,下面大体写一下代码:
FILE *fp;
fp = fopen("\\Storage card\\mfc5158.mp3","rb");
if(!fp)
return 0;
fseek(fp,0,0); //定位到文件开始
BYTE *pBuf;
pBuf = new BYTE[10];
fread(pBuf,1,10,fp);
ID3V2Header *mp3ID3V2;
mp3ID3V2 = new ID3V2Header[10]; //感觉这里有错误,是不是不用10
ZeroMemory(mp3ID3V2,sizeof(ID3V2Header));
memcpy(mp3ID3V2,pbuf,10);
DWORD Len = (mp3ID3V2->size[0]&0x7f)*0x200000 +(mp3ID3V2->size[1]&0x7f)*0x400+(mp3ID3V2->size[2]&0x7f)*0x80 +(mp3ID3V2->size[3]&0x7f); //标签体的大小
//标签体是所有的数据帧大小和
BYTE *pDataBuf;
pDataBuf = new BYTE[Len];
fseek(fp,10,0);
fread(pDataBuf,1,Len,fp); //标签体所有数据在pDataBuf里
ID3V2FrameHeader *pFrameBuf;
pFrameBuf = new ID3V2FrameHeader[10]; //好像也有错误,这样好像是申请了一个结构体类型的数组??
memcpy(pFrameBuf,pDataBuf,10);
int num = 0;
DWORD dwFrame;
while((strncmp(pFrameBuf->FrameId,"APIC",4) != 0)) //查找专辑图片数据帧
{
dwFrame= pFrameBuf->size[0]*0x1000000+pFrameBuf->size[1]*0x10000+pFrameBuf->size[2]*0x100 + pFrameBuf->size[3]; //数据帧体大小
num = num +10+dwFrame;
ZeroMemory(pFrameBuf,10);
memcpy(pFrameBuf,pDataBuf+num,10); //下一个数据帧头
}
//默认这首歌是有专辑图片的 ,很有很多需要改进的,如果没有怎么办,现在都没考虑
dwFrame= pFrameBuf->size[0]*0x1000000+pFrameBuf->size[1]*0x10000+pFrameBuf->size[2]*0x100 + pFrameBuf->size[3]; //专辑图片数据帧大小
BYTE *pPicData;
pPicData = new BYTE[dwFrame - 14 ]; //我看到现在MP3专辑图片就有两种形式 在数据帧头10字节后连续14或者23个字节是没有用的,真正的图片数据要去掉
fseek(fp,10+num+10+14,0); //定位到真正的图片数据部分
fread(pPicData,1,dwFrame-14,fp); //图片数据都在pPicData里了
fclose(fp);
///绘制到界面
HRESULT hr;
IImagingFactory *pImagingFactory = NULL;
IImage *pImage = NULL;
CoCreateInstance (CLSID_ImagingFactory,NULL,CLSCTX_INPROC_SERVER,IID_ImagingFactory,(void**)&pImagingFactory );
pImagingFactory->CreateImageFromBuffer(pPicData,dwFrame-14,BufferDisposalFlagNone,&pImage);
RECT rc = {0,0,300,300};
pImage->draw(hdc,&rc,NULL);
垃圾处理此处省略 释放COM端口 删除动态申请的内存