旋转裁剪算法

来源:互联网 发布:互联网java开发 编辑:程序博客网 时间:2024/06/06 15:43

首先看一下QQ影像的旋转裁剪功能中的对比


其中裁剪决定了旋转后抽离其中的区域,并保持了原先的宽高比。


经过研究,转化为计算中间等比例矩形的宽高,即(x1,y1)(x2,y2)的值


当然这个裁剪的点也可能因为旋转角度以及图片原尺寸的关系取右上角的AC和BD直接与GH的两个相交点。因此在求出这些点的时候比较一下AB与EF的相交点 与 BD与GH的相交点的纵坐标哪个值更大则取相应的交点。

于是通过建立函数模型,需要注意的是y为向下为正方向,因此列方程的时候为当前的图形关于x轴对称的图形

  EF : y = k * x;  GH : y = R.h - k * x;  AB : y = -cotA * x + h * cosA;  CD : y = -cotA * (x - h * sinA - w / cosA ) ;  AC : y = tanA * (x - h * sinA);  BD : y = tanA * (x - h * sinA +  h / cos(90 - A)) = tanA * (x - h * sinA + h / sinA);


R.h为旋转后的图形高度 w与h 分别为原图的宽高值。A为旋转的角度


        int mod_angle = angle >= 270 ? (90 - angle % 90) : angle;        RGBQUAD color = { 255, 255, 255, 0 };        auto fiRotate = FreeImage_Rotate(dibs, angle, &color);        SIZE szRotate = { FreeImage_GetWidth(fiRotate), FreeImage_GetHeight(fiRotate) };        SIZE szNaive  = { FreeImage_GetWidth(dibs), FreeImage_GetHeight(dibs) }; #define M_PI       3.14159265358979323846   // pi        float sin_of_angle = sin(mod_angle * M_PI / 180);        float cos_of_angle = cos(mod_angle * M_PI / 180);        float tan_of_angle = tan(mod_angle * M_PI / 180);        float cot_of_angle = 1 / tan_of_angle;        float k = 1.0 * szRotate.cy / szRotate.cx;        int h = szNaive.cy, w = szNaive.cx;        // EF : y = k * x;        // GH : y = R.h - k * x;        // AB : y = -cotA * x + h * cosA;        // CD : y = -cotA * (x - h * sinA - w / cosA ) ;        // AC : y = tanA * (x - h * sinA);        // BD : y = tanA * (x - h * sinA +  h / cos(90 - A)) = tanA * (x - h * sinA + h / sinA);        // EF与AB相交于[(h * cosA / (k + cotA)),  k * 前者]         // EF与CD相交于[ (h * cosA + w / sinA) / (k + cotA), k * 前者 ]        // GH与AC相交于[ (R.h + h * sinA * tanA) / (tanA + k), R.h - k * 前者] R.h = szRotate.cy        // GH与BD相交于[ (R.h + h * sinA * tanA - h / cosA) / (tanA + k), h - k * 前者]        RECT rcCutter = { 0 };        POINTF ptEF_AB = { 0 };        ptEF_AB.x = h * cos_of_angle / (k + cot_of_angle);        ptEF_AB.y = ptEF_AB.x * k;        POINTF ptEF_CD = { 0 };        ptEF_CD.x = (h *cos_of_angle + w / sin_of_angle) / (k + cot_of_angle);        ptEF_CD.y = ptEF_CD.x * k;        POINTF ptGH_AC = { 0 };        ptGH_AC.x = (szRotate.cy + h * sin_of_angle * tan_of_angle) / (tan_of_angle + k);        ptGH_AC.y = szRotate.cy - k * ptGH_AC.x;        POINTF ptGH_BD = { 0 };        ptGH_BD.x = (szRotate.cy + h * sin_of_angle * tan_of_angle - h / cos_of_angle) / (tan_of_angle + k);        ptGH_BD.y = szRotate.cy - k * ptGH_BD.x;        if (ptEF_AB.y < ptGH_AC.y) { // 矩形取 ptGH_AC,ptGH_BD            rcCutter.left   = int(ptGH_BD.x + 0.5f);            rcCutter.top    = int(ptGH_AC.y + 0.5f);            rcCutter.right  = int(ptGH_AC.x);            rcCutter.bottom = int(ptGH_BD.y);        }        else {            rcCutter.left   = int(ptEF_AB.x + 0.5f);            rcCutter.top    = int(ptEF_AB.y + 0.5f);            rcCutter.right  = int(ptEF_CD.x);            rcCutter.bottom = int(ptEF_CD.y);        }                dibd = FreeImage_Copy(fiRotate, rcCutter.left, rcCutter.top, rcCutter.right, rcCutter.bottom);        FreeImage_Unload(fiRotate);