bmp数据提取
- bmp格式文件的解析
关于bitmap文件格式
https://blog.csdn.net/huanggengxing/article/details/82529221 https://blog.csdn.net/gx19862005/article/details/22513249 https://blog.51cto.com/redwolf/22909
bmp图片每一行数据都要是4的整数倍,不是则后面补0以满足
- bmp格式文件第一个数据是图片的左下角
- 每一行数据的宽度都向4取整
缩放
- 图片缩放涉及一定的算法
- 近值取样插值算法
/* 首先定义图像数据结构 */
typedef unsigned char TUInt8; // [0..255]
struct TARGB32 //32 bit color
{
TUInt8 B,G,R,A; // A is alpha
};
struct TPicRegion //一块颜色数据区的描述,便于参数传递
{
TARGB32* pdata; //颜色数据首地址
long byte_width; //一行数据的物理宽度(字节宽度);
//abs(byte_width)有可能大于等于width*sizeof(TARGB32), bmp文件一行数据宽度要4字节对齐;
long width; //像素宽度
long height; //像素高度
};
//那么访问一个点的函数可以写为:
inline TARGB32& Pixels(const TPicRegion& pic,const long x,const long y)
{
return ( (TARGB32*)((TUInt8*)pic.pdata+pic.byte_width*y) )[x];
}
//---------------------------------------------------------------------
/* 插值算法3 ZOOM
* Dst : 目的区域
* Src : 源区域
*/
void PicZoom3(const TPicRegion& Dst,const TPicRegion& Src)
{
if ( (0==Dst.width)||(0==Dst.height)
||(0==Src.width)||(0==Src.height)) return;
unsigned long xrIntFloat_16=(Src.width<<16)/Dst.width+1;
unsigned long yrIntFloat_16=(Src.height<<16)/Dst.height+1;
unsigned long dst_width=Dst.width;
TARGB32* pDstLine=Dst.pdata;
unsigned long srcy_16=0;
for (unsigned long y=0;y<Dst.height;++y)
{
TARGB32* pSrcLine=((TARGB32*)((TUInt8*)Src.pdata+Src.byte_width*(srcy_16>>16)));
unsigned long srcx_16=0;
for (unsigned long x=0;x<dst_width;++x)
{
pDstLine[x]=pSrcLine[srcx_16>>16];
srcx_16+=xrIntFloat_16;
}
srcy_16+=yrIntFloat_16;
((TUInt8*&)pDstLine)+=Dst.byte_width;
}
}
/* 定点数的方法来优化除法运算 */
void PicZoom2( const TPicRegion& Dst, const TPicRegion& Src)
{
if ( (0==Dst.width)||(0==Dst.height)
||(0==Src.width)||(0==Src.height)) return;
//函数能够处理的最大图片尺寸65536*65536
unsigned long xrIntFloat_16=(Src.width<<16)/Dst.width+1; //16.16格式定点数
unsigned long yrIntFloat_16=(Src.height<<16)/Dst.height+1; //16.16格式定点数
//可证明: (Dst.width-1)*xrIntFloat_16<Src.width成立
for (unsigned long y=0;y<Dst.height;++y)
{
for (unsigned long x=0;x<Dst.width;++x)
{
unsigned long srcx=(x*xrIntFloat_16)>>16;
unsigned long srcy=(y*yrIntFloat_16)>>16;
Pixels(Dst,x,y)=Pixels(Src,srcx,srcy);
}
}
}
/* 交换x,y循环的顺序, 以按照颜色数据在内存中的排列顺序读写 */
void PicZoom1(const TPicRegion& Dst,const TPicRegion& Src)
{
if ( (0==Dst.width)||(0==Dst.height)
||(0==Src.width)||(0==Src.height)) return;
for (long y=0;y<Dst.height;++y)
{
for (long x=0;x<Dst.width;++x)
{
long srcx=(x*Src.width/Dst.width);
long srcy=(y*Src.height/Dst.height);
Pixels(Dst,x,y)=Pixels(Src,srcx,srcy);
}
}
}
//Src.PColorData指向源数据区,Dst.PColorData指向目的数据区
//函数将大小为Src.Width*Src.Height的图片缩放到Dst.Width*Dst.Height的区域中
void PicZoom0(const TPicRegion& Dst,const TPicRegion& Src)
{
if ( (0==Dst.width)||(0==Dst.height)
||(0==Src.width)||(0==Src.height)) return;
for (long x=0;x<Dst.width;++x)
{
for (long y=0;y<Dst.height;++y)
{
/* 计算目标区域中的每一点对应的源区域位置 */
long srcx=(x*Src.width/Dst.width);
long srcy=(y*Src.height/Dst.height);
/* 将源区域位置像素赋值给目标区域对应位置 */
Pixels(Dst,x,y)=Pixels(Src,srcx,srcy);
}
}
}