// 图片拉伸
// width, height 拉伸后的图片大小
// img 原图像
void ImageToSize(int width, int height, IMAGE* img)
{
IMAGE* pOldImage = GetWorkingImage();
SetWorkingImage(img);
IMAGE temp_image(width,height);
StretchBlt(
GetImageHDC(&temp_image), 0, 0, width, height,
GetImageHDC(img), 0, 0,
getwidth(), getheight(),
SRCCOPY
);
Resize(img,width,height);
putimage(0,0,&temp_image);
SetWorkingImage(pOldImage);
}
示例:
IMAGE img;
loadimage(&img,"./img.jpg");
ImageToSize(200,200,&img);
putimage(0,0,&img);
注意:
由于 StretchBlt 函数是有损的,所以请每次拉伸图像时使用原图,否则会越来越糊!
上面这个函数借用了 win32 的 StretchBlt 函数,拉伸效果并不太好,还有下面这个双线性插值法实现的:
备注:这个函数如果拉伸高度为 1 的图像会什么也得不到……
/*
* 参考自 http://tieba.baidu.com/p/5218523817
* 参数说明:pImg 是原图指针,width1 和 height1 是目标图片的尺寸。
* 函数功能:将图片进行缩放,返回目标图片。可以自定义宽高;也可以只给宽度,程序自动计算高度
* 返回目标图片
*/
IMAGE zoomImage(IMAGE* pImg, int newWidth, int newHeight = 0)
{
// 防止越界
if (newWidth < 0 || newHeight < 0) {
newWidth = pImg->getwidth();
newHeight = pImg->getheight();
}
// 当参数只有一个时按比例自动缩放
if (newHeight == 0) {
// 此处需要注意先*再/。不然当目标图片小于原图时会出错
newHeight = newWidth * pImg->getheight() / pImg->getwidth();
}
// 获取需要进行缩放的图片
IMAGE newImg(newWidth, newHeight);
// 分别对原图像和目标图像获取指针
DWORD* oldDr = GetImageBuffer(pImg);
DWORD* newDr = GetImageBuffer(&newImg);
// 赋值 使用双线性插值算法
for (int i = 0; i < newHeight - 1; i++) {
for (int j = 0; j < newWidth - 1; j++) {
int t = i * newWidth + j;
int xt = j * pImg->getwidth() / newWidth;
int yt = i * pImg->getheight() / newHeight;
newDr[i * newWidth + j] = oldDr[xt + yt * pImg->getwidth()];
// 实现逐行加载图片
byte r = (GetRValue(oldDr[xt + yt * pImg->getwidth()]) +
GetRValue(oldDr[xt + yt * pImg->getwidth() + 1]) +
GetRValue(oldDr[xt + (yt + 1) * pImg->getwidth()]) +
GetRValue(oldDr[xt + (yt + 1) * pImg->getwidth() + 1])) / 4;
byte g = (GetGValue(oldDr[xt + yt * pImg->getwidth()]) +
GetGValue(oldDr[xt + yt * pImg->getwidth()] + 1) +
GetGValue(oldDr[xt + (yt + 1) * pImg->getwidth()]) +
GetGValue(oldDr[xt + (yt + 1) * pImg->getwidth()]) + 1) / 4;
byte b = (GetBValue(oldDr[xt + yt * pImg->getwidth()]) +
GetBValue(oldDr[xt + yt * pImg->getwidth()] + 1) +
GetBValue(oldDr[xt + (yt + 1) * pImg->getwidth()]) +
GetBValue(oldDr[xt + (yt + 1) * pImg->getwidth() + 1])) / 4;
newDr[i * newWidth + j] = RGB(r, g, b);
}
}
return newImg;
}
注意,若不想使用双线性插值,可以将 rgb 的计算公式替换为:
byte r = GetRValue(oldDr[xt + yt * pImg->getwidth()]);
byte g = GetGValue(oldDr[xt + yt * pImg->getwidth()]);
byte b = GetBValue(oldDr[xt + yt * pImg->getwidth()]);