📄 rotatezoom.c
字号:
srcy0_16 = Cy_16;
for (y = 0;y < Dst->height;++y)
{
srcx_16 = srcx0_16;
srcy_16 = srcy0_16;
for (x = 0;x < Dst->width;++x)
{
srcx = (srcx_16 >> 16);
srcy = (srcy_16 >> 16);
if (RGBRotScaPixelsIsInPic(Src, srcx, srcy))
{
srcpixels = RGBRotScaPixels(Src, srcx, srcy);
pDstLine[x] = *srcpixels;
}
srcx_16 += Ax_16;
srcy_16 += Ay_16;
}
srcx0_16 += Bx_16;
srcy0_16 += By_16;
((TUInt8*)pDstLine) += Dst->byte_width;
}
}
#else
//函数假设以原图片的中心点坐标为旋转和缩放的中心,定点版本
void RGBRotScaPicRotaryInt(const tpicregion* Dst, const tpicregion* Src, double ZoomX, double ZoomY, double move_x, double move_y, double centerx0, double centery0, int RotateTimes)
{
double rx0;
double ry0;
double tmprzoomxy = 1.0 / (ZoomX * ZoomY);
double rZoomX = tmprzoomxy * ZoomY;
double rZoomY = tmprzoomxy * ZoomX;
long x;
long y;
long srcx0, srcx1;
long srcy0, srcy1;
long h, v;
long coef1, coef2, coef3, coef4;
long r, g, b;
unsigned long p00, p01, p10, p11;
targbmodel* srcpixels;
long *pDstLine = (long*)Dst->pdata;
int RGBRotSca_gCosTable[4] = {1, 0, -1, 0};//0,PI/2,PI,PI*3/2
int RGBRotSca_gSinTable[4] = {0, 1, 0, -1};//0,PI/2,PI,PI*3/2
long Ax_16 = (long)(rZoomX * RGBRotSca_gCosTable[RotateTimes & 0x3] * (1 << 16));
long Ay_16 = (long)(rZoomX * RGBRotSca_gSinTable[RotateTimes & 0x3] * (1 << 16));
long Bx_16 = (long)(-rZoomY * RGBRotSca_gSinTable[RotateTimes & 0x3] * (1 << 16));
long By_16 = (long)(rZoomY * RGBRotSca_gCosTable[RotateTimes & 0x3] * (1 << 16));
long Cx_16;
long Cy_16;
long srcx0_16;
long srcy0_16;
long srcx_16;
long srcy_16;
rx0 = centerx0;//Src->width*0.5;
ry0 = centery0;//Src->height*0.5;//(rx0,ry0)为旋转中心
Cx_16 = (long)((-(rx0 + move_x) * rZoomX * RGBRotSca_gCosTable[RotateTimes & 0x3] + (ry0 + move_y) * rZoomY * RGBRotSca_gSinTable[RotateTimes & 0x3] + rx0) * (1 << 16));
Cy_16 = (long)((-(rx0 + move_x) * rZoomX * RGBRotSca_gSinTable[RotateTimes & 0x3] - (ry0 + move_y) * rZoomY * RGBRotSca_gCosTable[RotateTimes & 0x3] + ry0) * (1 << 16));
srcx0_16 = Cx_16;
srcy0_16 = Cy_16;
for (y = 0;y < Dst->height;++y)
{
srcx_16 = srcx0_16;
srcy_16 = srcy0_16;
for (x = 0;x < Dst->width;++x)
{
srcx0 = (srcx_16 >> 16);
srcx1 = srcx0 + 1;
srcy0 = (srcy_16 >> 16);
srcy1 = srcy0 + 1;
h = ((srcx1 << 16) - srcx_16) >> 6; // Q10
v = ((srcy1 << 16) - srcy_16) >> 6;
if (RGBRotScaPixelsIsInPic(Src, srcx0, srcy0))
{
p00 = *(unsigned long*)RGBRotScaPixels(Src, srcx0, srcy0);
if (RGBRotScaPixelsIsInPic(Src, srcx1, srcy1))
{
p01 = *(unsigned long*)RGBRotScaPixels(Src, srcx1, srcy0);
p10 = *(unsigned long*)RGBRotScaPixels(Src, srcx0, srcy1);
p11 = *(unsigned long*)RGBRotScaPixels(Src, srcx1, srcy1);
coef1 = v * h; // Q20
coef2 = v * (1024 - h);
coef3 = (1024 - v) * h;
coef4 = (1024 - v) * (1024 - h);
r = (coef1 * GET_R(p00) + coef2 * GET_R(p01) + coef3 * GET_R(p10) + coef4 * GET_R(p11)) >> 20;
g = (coef1 * GET_G(p00) + coef2 * GET_G(p01) + coef3 * GET_G(p10) + coef4 * GET_G(p11)) >> 20;
b = (coef1 * GET_B(p00) + coef2 * GET_B(p01) + coef3 * GET_B(p10) + coef4 * GET_B(p11)) >> 20;
pDstLine[x] = (b & 0xFF) | ((g & 0xFF) << 8) | ((r & 0xFF) << 16);
}
else
{
pDstLine[x] = p00;
}
}
srcx_16 += Ax_16;
srcy_16 += Ay_16;
}
srcx0_16 += Bx_16;
srcy0_16 += By_16;
((TUInt8*)pDstLine) += Dst->byte_width;
}
}
#endif
rgbrotatescale* RGBRotScaTransform(rgbrotatescale* org, tRGBPicRotateZoomInOut* pRGBRotateScale, unsigned char *ImageLCDLogicBuf, int ScreenWidth, int ScreenHeight)
{
tpicregion Src, Dst;
float zoomx;
float zoomy;
int rotatewidth;//源图像旋转后的宽度
int rotateheight;//源图像旋转后的高度
int zoomwidth;//原图像缩放后的图片宽度
int zoomheight;//原图像缩放后的图片高度
int movex;//x轴平移分量
int movey;//y轴平移分量
double centerx0;//旋转中心点x坐标
double centery0;//旋转中心点y坐标
double zoomuint;//表示原图片尺寸缩小到屏幕尺寸时,缩小后图片宽度/原图片宽度的比值,该值为缩小的基本单位
int RGBRotSca_gCosTable[4] = {1, 0, -1, 0};//0,PI/2,PI,PI*3/2
int RGBRotSca_gSinTable[4] = {0, 1, 0, -1};//0,PI/2,PI,PI*3/2
int RotateTimes;//顺时针旋转次数N,等价于N*PI/2
if (!org)
return (rgbrotatescale*)FALSE;
Src.width = org->width;
Src.height = org->height;
Src.byte_width = org->width * sizeof(targbmodel);//Src.byte_width = (org->width * sizeof(targbmodel)+ 3) & ~3;//一行字节宽度按4对齐;
Src.pdata = (targbmodel*)org->data;
Dst.width = ScreenWidth;//targetbmp->width;
Dst.height = ScreenHeight;//targetbmp->height;
Dst.byte_width = (Dst.width * sizeof(targbmodel) + 3) & ~3;//一行字节宽度按4对齐
Dst.pdata = (targbmodel*)(ImageLCDLogicBuf);//targetbmp->data;LCD_BUFFER
RotateTimes = /*clockwise*/pRGBRotateScale->rotateangleindex;//计算顺时针/逆时针的角度索引
if (pRGBRotateScale->rotateenable == 1)
{//若启动旋转,则缩放的高度和宽度,取原图旋转后图片的高度和宽度
rotatewidth = abs(Src.width * RGBRotSca_gCosTable[(RotateTimes) & 0x3] +
Src.height * RGBRotSca_gSinTable[RotateTimes & 0x3]);
rotateheight = abs(Src.height * RGBRotSca_gCosTable[RotateTimes & 0x3] -
Src.width * RGBRotSca_gSinTable[RotateTimes & 0x3]);//计算顺时针/逆时针旋转的角度
}
else
{//若没有启动旋转,则仍然采用原图的宽度和高度
rotatewidth = Src.width;
rotateheight = Src.height;
}
//旋转后的图片宽度、高度都小于等于屏幕的宽度、高度,则不放大也不缩小
if ((rotatewidth <= Dst.width) && (rotateheight <= Dst.height))
{//图片高宽都小于屏幕高宽时,显示原图尺寸大喜爱,且关闭缩放功能
zoomx = 1.0;
zoomy = 1.0;
zoomuint = 1.0;
pRGBRotateScale->zoomenable = 0;//关闭缩放功能
pRGBRotateScale->moveenable = 0;//关闭平移功能
}
else
{
//只要高度、宽度中的一个超过屏幕的高度、宽度,就按照屏幕高度/图片高度,屏幕宽度/图片宽度中那个更小的比率来缩小,屏图比率越小表示缩小的幅度越大,缩小的越慢;
zoomuint = zoomy = zoomx = MIN((float)Dst.width / rotatewidth, (float)Dst.height / rotateheight);
if (pRGBRotateScale->zoomenable == 1)//触发了缩放按键功能,没有触发直接缩放到屏幕大小,zoomrate最大值为1.0/zoomuint,最小值为1.0,这个比率值是相对于屏幕尺寸图片为参照
{
zoomy = zoomx = (float)MIN(1.0, pRGBRotateScale->zoomrate * zoomuint);//最坏缩小到屏幕,一般按原图的0.5倍来缩小,1.0就是显示原图大小,但原图太大显示不下,只能以中心点坐标为准切割一块屏幕大小区域显示
}
zoomwidth = (int)(rotatewidth * zoomx);//根据缩小比率系数计算缩小后图片宽度
zoomheight = (int)(rotateheight * zoomy);//根据缩小比率系数计算缩小后图片高度
}
if (pRGBRotateScale->moveenable == 1)
{
int movedx;
int movedy;
if (zoomwidth > Dst.width)
//if(rotatewidth > Dst.width)
{
if (pRGBRotateScale->movedx < -(zoomwidth / 2 - Dst.width / 2))//x轴平移区间的左边界为-(zoomwidth/2-Dst.width/2)
{
movedx = -(zoomwidth / 2 - Dst.width / 2);
}
else
{
if (pRGBRotateScale->movedx > (zoomwidth / 2 - Dst.width / 2))//x轴平移区间的右边界为zoomwidth/2-Dst.width/2
{
movedx = (zoomwidth / 2 - Dst.width / 2);
}
else
{
movedx = pRGBRotateScale->movedx;//x轴平移分量在边界范围内就取该值
}
}
}
else
{
movedx = 0;//如果缩放后的图片宽度小于屏幕的宽度,则平移分量取0,即x轴不平移
}
if (zoomheight > Dst.height)
//if(rotateheight > Dst.height)
{
if (pRGBRotateScale->movedy < -(zoomheight / 2 - Dst.height / 2))//y轴平移区间的左边界为-(zoomheight/2-Dst.height/2)
{
movedy = -(zoomheight / 2 - Dst.height / 2);
}
else
{
if (pRGBRotateScale->movedy > (zoomheight / 2 - Dst.height / 2))//y轴平移区间的右边界为zoomheight/2-Dst.height/2
{
movedy = (zoomheight / 2 - Dst.height / 2);
}
else
{
movedy = pRGBRotateScale->movedy;//y轴平移分量在边界范围内就取该值
}
}
}
else
{
movedy = 0;//如果缩放后的图片高度小于屏幕的高度,则平移分量取0,即y轴不平移
}
//若启动了平移标记,则设置相对于图片的中心而言的平移分量,要注意其可能超出平移边界
movex = (Dst.width - Src.width) / 2 + (/*pRGBRotateScale->movexwise */ movedx);
movey = (Dst.height - Src.height) / 2 + (/*pRGBRotateScale->moveywise */ movedy);
}
else
{ //若没有启动平移,则以图片的中心为显示的中心轴
movex = (Dst.width - Src.width) / 2;
movey = (Dst.height - Src.height) / 2;
}
//设置旋转中心点坐标
centerx0 = pRGBRotateScale->rcenterx0;
centery0 = pRGBRotateScale->rcentery0;
RGBRotScaPicRotaryInt(&Dst, &Src, zoomx, zoomy, movex, movey, centerx0, centery0, RotateTimes);
return ((rgbrotatescale*)Dst.pdata);//targetbmp;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -