以下是未旋转,加载的8位图像(大小,256*256),显示用24位,正常:
再看一眼中心旋转后的8位图像(大小改变,362*362),显示用8位(西游记里妖怪对孙大圣使出的绝招妖法):
再看一眼中心旋转后的8位图像(大小改变,362*362),显示用24位:
再看一眼中心旋转后的8位图像(大小改变,362*362),显示用32位:
图像中心旋转,c#代码如下(与c++保持一致,旋转的是32位图像):
//旋转后放入picturebox2
// 原始图像四个角的坐标
int srcX1, srcX2, srcX3, srcX4;
int srcY1, srcY2, srcY3, srcY4;
srcX1 = 0;
srcY1 = 0;
//srcX2 = w - 1;
srcX2 = 256 - 1;
srcY2 = 0;
srcX3 = 0;
//srcY3 = h - 1;
//srcX4 = w - 1;
//srcY4 = h - 1;
srcY3 = 256 - 1;
srcX4 =256 - 1;
srcY4 = 256 - 1;
// 计算旋转角度的正弦和余弦值
double fsin = Math.Sin(0.78);//近似45度
double fcos = Math.Cos(0.78);
// 图像经过旋转后四个角的坐标
double desX1, desX2, desX3, desX4;
double desY1, desY2, desY3, desY4;
desX1 = fcos * srcX1 + fsin * srcY1;
desY1 = -fsin * srcX1 + fcos * srcY1;
desX2 = fcos * srcX2 + fsin * srcY2;
desY2 = -fsin * srcX2 + fcos * srcY2;
desX3 = fcos * srcX3 + fsin * srcY3;
desY3 = -fsin * srcX3 + fcos * srcY3;
desX4 = fcos * srcX4 + fsin * srcY4;
desY4 = -fsin * srcX4 + fcos * srcY4;
/*int*/
int outwidth = (int)(max(Math.Abs(desX4 - desX1), Math.Abs(desX3 - desX2)) + 0.5);
/*int*/
int outheight = (int)(max(Math.Abs(desY4 - desY1), Math.Abs(desY3 - desY2)) + 0.5);
byte[] image1 = new byte[outwidth * outheight * 4];
// byte[] image1 = new byte[outwidth * outheight*3 ];
// byte[] image1 = new byte[outwidth * outheight ];
// memset(image1, 255, outwidth * outheight * 4);
//double num1 = -0.5 * outwidth * fcos - 0.5 * outheight * fsin + 0.5 * w;
//double num2 = 0.5 * outwidth * fsin - 0.5 * outheight * fcos + 0.5 * h;
double num1 = -0.5 * outwidth * fcos - 0.5 * outheight * fsin + 0.5 * 256;
double num2 = 0.5 * outwidth * fsin - 0.5 * outheight * fcos + 0.5 * 256;
//BYTE* copypixel = NULL;
//BYTE* objpixel = NULL;
int x = 0;
int y = 0;
for (int j = 0; j < outheight; j++)
for (int i = 0; i < outwidth; i++)
{
x = (int)(i * fcos + j * fsin + num1 + 0.5);
y = (int)(-i * fsin + j * fcos + num2 + 0.5);
//if (x == w)
if (x == 256)
x--;
//if (y == h)
if (y == 256)
y--;
//copypixel = image0 + y * w * 4 + x * 4;//原图像
//objpixel = image1 + j * outwidth * 4 + i * 4;//中心旋转后图像
//if (x >= 0 && x < w && y >= 0 && y < h)
// memcpy(objpixel, copypixel, 4);
if (x >= 0 && x < 256 && y >= 0 && y < 256)
{
int temp = j * outwidth + i;
//image1[temp ] = glob_buffer8[y * 256 + x];
image1[temp * 4] = glob_buffer8[y * 256 + x];
image1[temp * 4 + 1] = glob_buffer8[y * 256 + x];
image1[temp * 4+ 2] = glob_buffer8[y * 256 + x];
image1[temp * 4 + 3] = 255;
}
}
你用c++代码测试,也是一样的,这神奇的微软!微软也是一脉相承,保持一致啊!
多年前已经遇到这个问题,借今天这个机会,美妙的回忆一下曾经的迷茫的自己,算法是没有问题的,关键是微软这神奇的gdi显示,你占位(分8,24,32位)不够,一边歇菜去吧!(详细对比代码请看:机器视觉入门之路(十九,图像旋转之后,c#))
这不是西安泡馍的技法吗?粗人掰馍,师傅粗制;你细掰馍,师傅细制作!哈哈!
需要强调的是:(x0,y0,1)*=(x,y,1)
这个公式在这个例子中的运算是,平移(-128,-128),旋转0.78弧度,再平移(181,181):
(x0,y0,1)*=(x,y,1)
原因是,第一幅图中心(128,128),旋转后图像又256*256变为362*362,中心在(181,181)处。