读取MP3文件内的ID3V2专辑图片并显示

这里说的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端口  删除动态申请的内存 

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老猿的春天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值