使用Borland C++ Builder与Windows API旋转图片时出现边缘裁剪问题
图片90度旋转侧边裁剪问题修复方案
问题根因
代码核心问题出在两处:
- 90度旋转后目标画布宽高没有互换:如果原图片不是正方形,旋转后宽高会发生交换,直接把目标画布的宽高设为和原图一致,必然会出现内容超出画布被裁剪的情况
- 坐标偏移计算没有适配画布尺寸变化:原偏移逻辑是基于原图中心旋转后对齐原画布中心,画布尺寸本身设置错误的情况下偏移自然不符合预期
修正后的代码
void rotate() { Graphics::TBitmap *SrcBitmap = new Graphics::TBitmap; Graphics::TBitmap *DestBitmap = new Graphics::TBitmap; SrcBitmap->LoadFromFile("Crayon.bmp"); // 改动点1:90度旋转后宽高互换 DestBitmap->Width = SrcBitmap->Height; DestBitmap->Height = SrcBitmap->Width; SetGraphicsMode(DestBitmap->Canvas->Handle, GM_ADVANCED); // 可以用系统定义的M_PI获得更高精度,也可保留原有3.1415926写法 double myangle = 90.0 * M_PI / 180.0; // 改动点2:适配90度旋转的坐标偏移,保证原图内容完全填充到新画布 XFORM xForm; xForm.eM11 = (FLOAT) cos(myangle); xForm.eM12 = (FLOAT) sin(myangle); xForm.eM21 = (FLOAT) -sin(myangle); xForm.eM22 = (FLOAT) cos(myangle); xForm.eDx = (FLOAT) SrcBitmap->Height; xForm.eDy = 0; SetWorldTransform(DestBitmap->Canvas->Handle, &xForm); BitBlt(DestBitmap->Canvas->Handle, 0, 0, SrcBitmap->Width, SrcBitmap->Height, SrcBitmap->Canvas->Handle, 0, 0, SRCCOPY); DestBitmap->SaveToFile("Crayon2.bmp"); delete DestBitmap; delete SrcBitmap; }
补充优化建议
- 如果要实现任意角度旋转,不能直接互换宽高,需要先计算旋转后的外接矩形尺寸,再对应调整坐标偏移量
- 可以增加
SrcBitmap加载成功的判断逻辑,避免文件不存在引发的空指针异常 - 如果编译器没有默认定义M_PI,可以在引入头文件前加
#define _USE_MATH_DEFINES后再引入cmath头文件
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

