///***************************************************************/
/*函数名称:Suofang(float xzoom, float yzoom)
/*函数类型:void
/*参数说明:xzoom --水平缩小的比率
/* yzoom --垂直缩小的比率
/*功能:对图像进行缩放处理。
/*****************************************************************/
void JiHeBianHuanDib::SuoXiao(float xzoom, float yzoom)
{
// 源图像的宽度和高度
LONG wide; //这里的宽度和高的是怎样计算的,是以 像素点 计算还是以 存储的字节计算
LONG height;
LONG LineBytes; //?????????
// 缩放后图像的宽度和高度
LONG newwide;
LONG newheight;
// 指向源图像的指针
LPBYTE p_data ;
LPBYTE temp;
temp=this->GetData(); //获得图像的存放的首地址
/* BYTE* CDib::GetData()
{
return m_pData;
}*/
p_data= temp;
// 指向源象素的指针
LPBYTE lpSrc;
// 指向缩放图像对应象素的指针
LPBYTE lpDst;
// 指向缩放图像的指针 ???????
LPBYTE hDIB;
// 循环变量(象素在新DIB中的坐标)
LONG i;
LONG j;
// 象素在源DIB中的坐标
LONG i0;
LONG j0;
if(m_pBitmapInfoHeader->biBitCount<9) //灰度图像
{
// 获取图像的宽度
wide = this->GetWidth();
LineBytes=(wide*8+31)/32*4;
// 获取图像的高度
height = this->GetHeight();
// 计算缩放后的图像实际宽度和高度
// 此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分
newwide = (LONG) (wide * xzoom + 0.5);
newheight = (LONG) (height * yzoom + 0.5);
// 分配内存,以保存新DIB
hDIB = new BYTE[ newwide * newheight*3 ];
int k1 =int(yzoom+ 0.5);
int k2 =int(xzoom+ 0.5);
// 针对图像每行进行操作
for(j = 0; j < height-1; j=j+k1)
{
// 针对图像每列进行操作
for(i = 0; i < wide-1; i=i+k2)
{
// 指向新DIB第i行,第j个象素的指针
// 注意此处宽度和高度是新DIB的宽度和高度
lpDst = (LPBYTE)hDIB + newwide * j + i;
// 计算该象素在源DIB中的坐标
j0 = (LONG) (j / yzoom + 0.5);
i0 = (LONG) (i / xzoom + 0.5);
// 判断是否在源图范围内
if( (i0 >= 0) && (i0 < wide) && (j0 >= 0) && (j0 < height))
{
// 指向源DIB第i0行,第j0个象素的指针
lpSrc = (LPBYTE)p_data + wide * j0 + i0;
// 复制象素
*lpDst = *lpSrc;
}
else
{
// 对于源图中没有的象素,直接赋值为255
*lpDst = 255;
}
}
}
// 复制缩小后的图像
for(j=0;j<height;j++)
{
for(i=0;i<wide;i++)
{
if(j<=newheight&&i<=newwide)
{
lpDst = (LPBYTE)hDIB + newwide * j + i;
*p_data=*lpDst;
}
else *p_data=255;
p_data++;
}
}
delete hDIB;
}
else //24位彩色
{
// 获取图像的宽度
wide = this->GetDibWidthBytes();
LineBytes = (((wide * 8)+31)/32*4);
//读取图片时候行字节数的算法
//已知:LineBytes是整型。width为bmp图像的宽度,以像素为单位。
/*该算法为:LineBytes = (width * bitCount + 31) / 32 * 4 bitCount为位图位宽,
32位BMP,位宽为32、24位BMP位宽为23、256色位图位宽为8、等等。
这是一种对齐算法,对于BMP等位图来说,要求是4字节对齐,
即每行字节数必须为4的整数倍。因为8bit等于1Byte,
同时满足以4字节为对齐单位向下对齐,
所以可以得:LineBytes = (width * bitCount / 8 + 3) / 4 * 4对于位宽不足8的位图,
有可能是多个像素才占用1Byte,所以应该将“/ 8”移出括号,
进一步得:LineBytes = (width * bitCount + 31) / 32 * 4*/
// 获取图像的高度
height = this->GetHeight();
CString str;
str.Format("w=%d h=%d l=%d",wide,height,LineBytes);
AfxMessageBox(str);
// 计算缩放后的图像实际宽度
// 此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分
newwide = (LONG) (LineBytes * xzoom + 0.5);
// 计算缩放后的图像高度
newheight = (LONG) (height * yzoom + 0.5);
// 分配内存,以保存新DIB
hDIB = new BYTE[ newwide * newheight*3 ]; //计算得到新位图所需要的内存单元的大小
// int k1 =(int)(yzoom+ 0.5);
// int k2 =(int)(xzoom+ 0.5);//向下取整?????????????
int k1=1;
int k2=1;
// 针对图像每行进行操作
for(j = 0; j < height-1; j=j+k1)
{
// 针对图像每列进行操作
for(i = 0; i < LineBytes-1; i=i+k2*3)//i=i+k2*3 ?????
{
// 指向新DIB第i行,第j个象素的指针
// 注意此处宽度和高度是新DIB的宽度和高度
lpDst = (LPBYTE)hDIB + newwide * j + i;
// 计算该象素在源DIB中的坐标
j0 = (LONG) (j / yzoom + 0.5);
i0 = (LONG) (i / xzoom + 0.5);
// 判断是否在源图范围内
if( (i0 >= 0) && (i0 < LineBytes) && (j0 >= 0) && (j0 < height))
{
// 指向源DIB第i0行,第j0个象素的指针
lpSrc = (LPBYTE)p_data + LineBytes * j0 + i0;
// 复制象素
*lpDst = *lpSrc; //每个像素三个内存单元, 都要复制到目的内存的
*(lpDst+1)=*(lpSrc+1);
*(lpDst+2)=*(lpSrc+2);
}
else
{
// 对于源图中没有的象素,直接赋值为255
*lpDst = 255;
}
}
}
// 复制缩小后的图像
for(j=0;j<height;j++)
{
for(i=0;i<LineBytes;i++)
{
if(j<=newheight&&i<=newwide)
{
//if(i<LineBytes*xzoom/3)
//if(i>LineBytes*xzoom/3&&i<2*LineBytes*xzoom/3) //添加的 中间的图像
// if(i>2*LineBytes*xzoom/3)
{
lpDst = (LPBYTE)hDIB + newwide * j + i;
*p_data=*lpDst;
}
// else
// {
// *p_data=255; //添加的
// }
}
else *p_data=255;
p_data++;
}
}
}
}