bmp数据提取

  • bmp格式文件的解析

image.png

image.png

  • bmp格式文件第一个数据是图片的左下角
  • 每一行数据的宽度都向4取整

缩放

  • 图片缩放涉及一定的算法
  • 近值取样插值算法
  • image.png

    1. /* 首先定义图像数据结构 */
    2. typedef unsigned char TUInt8; // [0..255]
    3. struct TARGB32 //32 bit color
    4. {
    5. TUInt8 B,G,R,A; // A is alpha
    6. };
    7. struct TPicRegion //一块颜色数据区的描述,便于参数传递
    8. {
    9. TARGB32* pdata; //颜色数据首地址
    10. long byte_width; //一行数据的物理宽度(字节宽度);
    11. //abs(byte_width)有可能大于等于width*sizeof(TARGB32), bmp文件一行数据宽度要4字节对齐;
    12. long width; //像素宽度
    13. long height; //像素高度
    14. };
    15. //那么访问一个点的函数可以写为:
    16. inline TARGB32& Pixels(const TPicRegion& pic,const long x,const long y)
    17. {
    18. return ( (TARGB32*)((TUInt8*)pic.pdata+pic.byte_width*y) )[x];
    19. }
    20. //---------------------------------------------------------------------
    21. /* 插值算法3 ZOOM
    22. * Dst : 目的区域
    23. * Src : 源区域
    24. */
    25. void PicZoom3(const TPicRegion& Dst,const TPicRegion& Src)
    26. {
    27. if ( (0==Dst.width)||(0==Dst.height)
    28. ||(0==Src.width)||(0==Src.height)) return;
    29. unsigned long xrIntFloat_16=(Src.width<<16)/Dst.width+1;
    30. unsigned long yrIntFloat_16=(Src.height<<16)/Dst.height+1;
    31. unsigned long dst_width=Dst.width;
    32. TARGB32* pDstLine=Dst.pdata;
    33. unsigned long srcy_16=0;
    34. for (unsigned long y=0;y<Dst.height;++y)
    35. {
    36. TARGB32* pSrcLine=((TARGB32*)((TUInt8*)Src.pdata+Src.byte_width*(srcy_16>>16)));
    37. unsigned long srcx_16=0;
    38. for (unsigned long x=0;x<dst_width;++x)
    39. {
    40. pDstLine[x]=pSrcLine[srcx_16>>16];
    41. srcx_16+=xrIntFloat_16;
    42. }
    43. srcy_16+=yrIntFloat_16;
    44. ((TUInt8*&)pDstLine)+=Dst.byte_width;
    45. }
    46. }
  1. /* 定点数的方法来优化除法运算 */
  2. void PicZoom2( const TPicRegion& Dst, const TPicRegion& Src)
  3. {
  4. if ( (0==Dst.width)||(0==Dst.height)
  5. ||(0==Src.width)||(0==Src.height)) return;
  6. //函数能够处理的最大图片尺寸65536*65536
  7. unsigned long xrIntFloat_16=(Src.width<<16)/Dst.width+1; //16.16格式定点数
  8. unsigned long yrIntFloat_16=(Src.height<<16)/Dst.height+1; //16.16格式定点数
  9. //可证明: (Dst.width-1)*xrIntFloat_16<Src.width成立
  10. for (unsigned long y=0;y<Dst.height;++y)
  11. {
  12. for (unsigned long x=0;x<Dst.width;++x)
  13. {
  14. unsigned long srcx=(x*xrIntFloat_16)>>16;
  15. unsigned long srcy=(y*yrIntFloat_16)>>16;
  16. Pixels(Dst,x,y)=Pixels(Src,srcx,srcy);
  17. }
  18. }
  19. }
  1. /* 交换x,y循环的顺序, 以按照颜色数据在内存中的排列顺序读写 */
  2. void PicZoom1(const TPicRegion& Dst,const TPicRegion& Src)
  3. {
  4. if ( (0==Dst.width)||(0==Dst.height)
  5. ||(0==Src.width)||(0==Src.height)) return;
  6. for (long y=0;y<Dst.height;++y)
  7. {
  8. for (long x=0;x<Dst.width;++x)
  9. {
  10. long srcx=(x*Src.width/Dst.width);
  11. long srcy=(y*Src.height/Dst.height);
  12. Pixels(Dst,x,y)=Pixels(Src,srcx,srcy);
  13. }
  14. }
  15. }
  1. //Src.PColorData指向源数据区,Dst.PColorData指向目的数据区
  2. //函数将大小为Src.Width*Src.Height的图片缩放到Dst.Width*Dst.Height的区域中
  3. void PicZoom0(const TPicRegion& Dst,const TPicRegion& Src)
  4. {
  5. if ( (0==Dst.width)||(0==Dst.height)
  6. ||(0==Src.width)||(0==Src.height)) return;
  7. for (long x=0;x<Dst.width;++x)
  8. {
  9. for (long y=0;y<Dst.height;++y)
  10. {
  11. /* 计算目标区域中的每一点对应的源区域位置 */
  12. long srcx=(x*Src.width/Dst.width);
  13. long srcy=(y*Src.height/Dst.height);
  14. /* 将源区域位置像素赋值给目标区域对应位置 */
  15. Pixels(Dst,x,y)=Pixels(Src,srcx,srcy);
  16. }
  17. }
  18. }

image.png