我已经建立了一个很好的旋转位图的功能。 在一些优化之后发生的问题是输出图像在旋转期间稍微重新定位。
我已经录制了一个360度旋转video给你,看看我的意思。 代码如下:
#define OFFSET_OF_ID (0x0)
#define OFFSET_OF_SIZE (0x2)
#define OFFSET_OF_PIXELS (0xA)
#define OFFSET_OF_NDIB (0xE)
#define OFFSET_OF_WIDTH (0x12)
#define OFFSET_OF_HEIGHT (0x16)
#define OFFSET_OF_BPP (0x1C)
#define OFFSET_OF_NRAW (0x22)
typedef unsigned char byte, pixel[3];
typedef unsigned short word;
typedef unsigned long dword;
typedef unsigned long long ddword;
byte*
bmp_rotate
(byte *buffer, float angle)
{
const dword src_width = *( (dword*)&buffer[OFFSET_OF_WIDTH]);
const dword src_height = *( (dword*)&buffer[OFFSET_OF_HEIGHT]);
const dword src_nraw = *( (dword*)&buffer[OFFSET_OF_NRAW]);
const dword src_pixels = *( (dword*)&buffer[OFFSET_OF_PIXELS]);
const dword src_bpp = *( (dword*)&buffer[OFFSET_OF_BPP]);
const dword single = src_bpp / 8;
const dword row = src_width * single;
dword rowsize = (row % 4) ? (row + 4 - row % 4) : (row);
byte *dest = calloc( src_pixels + src_nraw, sizeof(byte) );
double midX, midY;
int i, j;
double sin_angle = sin(angle);
double cos_angle = cos(angle);
midX = src_width / 2.0f;
midY = src_height / 2.0f;
memcpy(dest, buffer, src_pixels);
for(j = 0; j < src_height; j++)
{
dword dest_offset = src_pixels + j * rowsize;
double deltaY = j - midY;
double deltaX = 0 - midX;
double x_computation, y_computation;
x_computation = midX + deltaX * cos_angle + deltaY * sin_angle + 0.5f;
y_computation = midY - deltaX * sin_angle + deltaY * cos_angle + 0.5f;
for(i = 0; i < src_width; i++)
{
ddword rotX = x_computation;
ddword rotY = y_computation;
if(rotX >= 0 && rotX < src_width && rotY >= 0 && rotY < src_height)
{
ddword src_offset = src_pixels + rotY * rowsize + rotX * single;
memcpy(&dest[dest_offset], &buffer[src_offset], sizeof(pixel));
}
x_computation += cos_angle;
y_computation -= sin_angle;
dest_offset += single;
}
}
return dest;
}
导致这种不雅行为的原因是什么?
答案 0 :(得分:1)
我无法在视频中看到你的问题,但我认为在各种部分旋转中可以实现完整的360°旋转。
如果我们观察180°旋转,偏移变得清晰:正弦为0,余弦为-1。然后左上角(0,0)的旋转坐标为:
x' = xm + (x - xm) * cosa + (y - ym) * sina = xm + xm = w
y' = ym - (x - xm) * sina + (y - ym) * cosa = ym + ym = h
坐标(w,h)是专有的右边界和底边界。
您的工作坐标是实数。整数值描述左坐标和顶坐标。将(正)实型坐标转换为整数将截断小数部分并产生从零开始的像素指数。
将目标空间中的工作坐标加0.5,以强制执行正确的索引计算。相反,您应该将所有像素的实际坐标视为该像素的中间位置:
x(i) = i + 0.5
y(j) = j + 0.5
除了以下所有计算结果都是正确的:
double deltaY = j + 0.5 - midY;
double deltaX = 0 + 0.5 - midX;
x_computation = midX + deltaX * cos_angle + deltaY * sin_angle;
y_computation = midY - deltaX * sin_angle + deltaY * cos_angle;
我们的想法是将像素坐标视为源和目标空间中的像素中心。当收敛到整数时,通过向零舍入,自动实现目标空间中的正确表示。
答案 1 :(得分:0)
这可能是与舍入相关的问题。我过去在项目中也遇到过这种问题。请检查&#34;整数到其他类型&#34;的行。或&#34;其他类型为整数&#34;转换发生。