首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

RGB565图片旋转后颜色显示不对的有关问题

2013-11-13 
求助RGB565图片旋转后颜色显示不对的问题?程序运行后,能显示旋转后的图片,透明通道正常,只是图片颜色总是

求助RGB565图片旋转后颜色显示不对的问题?
程序运行后,能显示旋转后的图片,透明通道正常,只是图片颜色总是不对。
请各位高手帮忙看下问题在哪里!!!
原图片已经读入存储空间,下面函数是新建一存储空间,把旋转后的图片像素信息存入,
显示程序按原图同样方式读出显示。
typedef struct dibData
{
DWORD type;//MAGIC
DWORD width;
DWORD height;
DWORD bitcount;//16
DWORD widthBytes;//对齐
DWORD widthAlphas;//width
DWORD reserved0;
DWORD reserved1;
DWORD reserved2;
DWORD reserved3;
BYTE* alpha;
BYTE dib[1];
}DIBDATA_Z,*LPDIBDATA_Z;

///RGB565
#define RGB565_MASK_RED      0xF800   
#define RGB565_MASK_GREEN    0x3F   
#define RGB565_MASK_BLUE     0x001F 

#define DIB_BITCOUNT   16

#define B_565(c)  (((c)&0xF800)>>11)
#define G_565(c)  (((c)&0x07E0)>>5)
#define R_565(c)  ((c)&0x001F)
#define RGB_565(r,g,b) (WORD)((((b)>>3)<<11)|(((g)>>2)<<5)|((r)>>3))

///////////////////////////////////////////////////////////////
BOOL CLiImage::RotateImageBuffer(
const BYTE* pSrcBuf,                 // 原图像缓冲区(RGB565)
DWORD dwSrcWidth,                    // 原图像像素宽度
DWORD dwSrcHeight,                   // 原图像像素高度
int iRotateAngle,                    // 旋转角度(单位:度)
CLiImage* pNewImage // 新图对像类
)
{
    // 参数有效性  
    if (pSrcBuf==NULL || dwSrcWidth==0 || dwSrcHeight==0)  
    {  
RETAILMSG(1,(L"[RotateImageBuffer]:====pSrcBuf==NULL======\n"));
        return FALSE;  
    }  

// 计算有效的旋转角
int dbAngle = iRotateAngle%360;

    // 旋转角度为0或为360不需要旋转  
    if (dbAngle==0 || dbAngle==360)  
    {  
RETAILMSG(1,(L"[RotateImageBuffer]:====dbAngle==0/==360======\n"));
        return FALSE;  
    }

PWFBYTE pDstBuf = NULL; //输出旋转后图像缓冲区指针(RGB565)
DWORD dwDstWidth = 0;// 输出旋转后图像像素宽度
DWORD dwDstHeight = 0;// 输出旋转后图像像素高度

  //定义原图片宽高
int m_iWidth= dwSrcWidth;
int m_iHeight= dwSrcHeight; 

//计算角度对应的弧度值
// 计算sin(dbAngle)和cos(dbAngle)的值
//double dbPI = 3.1415926535; //dbPI/180=0.0174532925
double dbA = dbAngle*-0.0174532925;
double sinA = sin(dbA);
double cosA = cos(dbA);

int dstWidth = 0, dstHeight = 0;
int num1 = 0, num2 = 0;
UINT crDefault = 0;

// 以位图中点为原点,建立数学坐标系(因为这里我们只要得到新图的宽高,所以不用转到屏幕坐标系)
// 约定第一象限点(w/2,h/2)为第1点,依次第二象限第2点,三象限第3点,四象限第4点
// 容易知道:dstWidth = max(一对主副对角线上两点横坐标距离), dstHeight类似
// 在数学坐标系中,某点(x0,y0)顺时针旋转A度后的坐标公式为:(x1, y1)=(x0*cosA+y0*sinA, -x0*sinA+y0*cosA)
//以图片中心点为原点,坐标值/2
double w_2 = 0.5*m_iWidth;
double h_2 = 0.5*m_iHeight;
double cosAW_2 = cosA*w_2;
double sinAW_2 = sinA*w_2;
double cosAH_2 = cosA*h_2;
double sinAH_2 = sinA*h_2;

/////旋转后图片的4个点的坐标值(x1,y1),(x2,y2),(x3,y3),(x4,y4)
double DstX1 = cosAW_2 + sinAH_2;
double DstY1 = cosAH_2 - sinAW_2;
double DstX2 = cosAW_2 - sinAH_2;
double DstY2 = -sinAW_2 - cosAH_2;
double DstX3 = -cosAW_2 - sinAH_2;
double DstY3 = sinAW_2 - cosAH_2;
double DstX4 = sinAH_2 - cosAW_2;
double DstY4 = sinAW_2 + cosAH_2;

// 计算旋转后图像的宽度和高度
dstWidth = (int)(max(fabs(DstX4-DstX2),fabs(DstX3-DstX1)) + 0.5);
dstHeight = (int)(max(fabs(DstY4-DstY2),fabs(DstY3-DstY1)) + 0.5);


DWORD m_iWidth4 = m_iWidth*2;
m_iWidth4 = m_iWidth4 + (4 - m_iWidth%4);
DWORD dstWidth4 = dstWidth*2;
dstWidth4 = dstWidth4 + (4 - dstWidth4%4);
DWORD m_iWidth4 = (((m_iWidth*16 + 31)/32)*32)/8/*((m_iWidth*16+ 31) & ~31) >> 3*/; //原图每行位值
DWORD dstWidth4 = (((dstWidth*16 + 31)/32)*32)/8;/*((dstWidth*16+ 31) & ~31) >> 3*/; //转后图每行位值

////计算旋转后图像的总存储空间
DWORD iDibSize = offsetof_(DIBDATA_Z, dib) ; //LPDIBDATA_Z_SIZE结构体存储占用位
DWORD dwDstBufSize = iDibSize+dstWidth4*dstHeight;
if( m_pDib->alpha )
{


dwDstBufSize += dstWidth*dstHeight;
}

int iPix  = (dstWidth4*dstHeight);
pDstBuf = new BYTE[dwDstBufSize];

////原图像缓冲区指针,旋转后图像缓冲区指针,原图透明通道指针
UINT16* pSrc = (UINT16*)m_pDib->dib;
UINT16* pDst = (UINT16*)(pDstBuf+iDibSize);
UINT8*  pAlpha = m_pDib->alpha;

UINT32 color[2][2]; 
UINT32 colorAlpha[2][2]; 
BYTE alpha[2][2];
BYTE rColor[2][2]; 
BYTE gColor[2][2];
BYTE bColor[2][2];  

//计算旋转后图片的中心点坐标(num1,num2)
// 下面为了避免浮点数计算,将浮点数转为Fix Point Arithmetic,因为根本不用那么高的精度
int icosA = (int)(cosA * 65536.0/*256.0 * 256.0*/); 
int isinA = (int)(sinA * 65536.0/*256.0 * 256.0*/);

num1 = ((-dstWidth*icosA - dstHeight*isinA)/2 + (m_iWidth <<15/*256*256/2*/));
num2 = (( dstWidth*isinA - dstHeight*icosA)/2 + (m_iHeight<<15/*256*256/2*/));

////Alpha通道值,R色值,G色值,B色值
int afinal, rfinal, gfinal, bfinal;
int srcX = 0, srcY = 0; 
int x, y, iDstx, iDsty,iSrcbufbyte, dx, dy, dxdy, xdy, dxy, xy;
for (int j = 0; j < dstHeight; ++j) 
{
for (int i = 0; i < dstWidth; ++i) 
{

// 与原图中的像素点坐标对应的目标位图中的点(Dstx,Dsty)
srcX = i*icosA + j*isinA + num1; 
srcY = j*icosA - i*isinA + num2; 
iDstx = srcX>>16;    
iDsty = srcY>>16;

//判断目标图中的点坐标是否在原图范围内
if (0 <= iDstx && iDstx < m_iWidth && 0 <= iDsty && iDsty < m_iHeight)
{
//像素点在原图存储空间的位置=行*原图宽+x坐标
iSrcbufbyte = iDsty*(m_iWidth4>>1)+iDstx;

//从原图取出像素点的色值(与目标图像素点对应)
color[0][0] = pSrc[iSrcbufbyte];

///////////////////////////////////
//取出与x,y相临的3个像素点,用来作双线性内插值
//判断目标图片的坐标是否是行尾点或列尾点,否则赋0
color[1][1] = pSrc[((iDsty+1)*(m_iWidth4>>1))+iDstx+1];

//像素点是行尾[1][0]赋默认值
if (iDstx + 1 >= m_iWidth)
{
color[1][0] = crDefault;
color[1][1] = crDefault;//像素点是行尾或列尾[1][1]赋默认值
}
else
{
color[1][0] = pSrc[((iDsty+1)*(m_iWidth4>>1))+iDstx]; 
}
//像素点是列尾[0][1]赋默认值
if (iDsty + 1 >= m_iHeight)
{

color[0][1] = crDefault;
color[1][1] = crDefault;//像素点是行尾或列尾[1][1]赋默认值
}
else
{
color[0][1] = pSrc[iSrcbufbyte+1];
}

//判断图像是否有Alpha通道值
if( m_pDib->alpha )
{
DWORD xyAlpha = iDsty*m_iWidth + iDstx;
////从原图取出像素点透明通道值
colorAlpha[0][0] = pAlpha[xyAlpha];
colorAlpha[1][1] = pAlpha[xyAlpha+m_iWidth+1];
//是行尾点[1][0]赋默认值
if (iDstx + 1 >= m_iWidth)
{
colorAlpha[1][0] = crDefault;
colorAlpha[1][1] = crDefault; //是行尾点或列尾点[1][1]赋默认值
}
else
{
colorAlpha[1][0] = pAlpha[xyAlpha+m_iWidth];
}
//是列尾点[0][1]赋默认值
if (iDsty + 1 >= m_iHeight)
{
colorAlpha[0][1] = crDefault;
colorAlpha[1][1] = crDefault; //是行尾点或列尾点[1][1]赋默认值
}
else
{
colorAlpha[0][1] = pAlpha[xyAlpha+1];
}
}
//////////////////////////////////////////////////////////////
////计算相临4个像素点的RGB565的RGB值
bColor[0][0] = B_565(color[0][0]);
gColor[0][0] = G_565(color[0][0]);
rColor[0][0] = R_565(color[0][0]);

bColor[1][0] = B_565(color[1][0]);
gColor[1][0] = G_565(color[1][0]);
rColor[1][0] = R_565(color[1][0]);

bColor[0][1] = B_565(color[0][1]);
gColor[0][1] = G_565(color[0][1]);
rColor[0][1] = R_565(color[0][1]);

bColor[1][1] = B_565(color[1][1]);
gColor[1][1] = G_565(color[1][1]);
rColor[1][1] = R_565(color[1][1]);
////计算透明通道值
alpha[0][0]  = (colorAlpha[0][0]);
alpha[1][0]  = (colorAlpha[1][0]);
alpha[0][1]  = (colorAlpha[0][1]);
alpha[1][1]  = (colorAlpha[1][1]);

//双线性内插值: 
        //对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(i+u,j+v), 
//其中i、j均为非负整数,u、v为[0,1)区间的浮点数,则这个像素得值f(i+u,j+v)可由原图像 
//中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定, 
//即:f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1) 
//其中f(i,j)表示源图像(i,j)处的的像素值,以此类推。
x = (srcX >> 8) & 0xFF;
y = (srcY >> 8) & 0xFF;
dx = 256 - x, dy = 256 - y;//dx=>(1-u),dy=>(1-v)  ,//256 = 0x100


dxdy = dx*dy, xdy = x*dy,//dxdy=>(1-u)(1-v), xdy=>u(1-v)
dxy = dx*y, xy = x*y;//dxy=>(1-u)v,xy=>uv

//计算RGB值
rfinal = (dxdy*rColor[0][0] + xdy*rColor[1][0] + dxy*rColor[0][1] + xy*rColor[1][1])>>16;
gfinal = (dxdy*gColor[0][0] + xdy*gColor[1][0] + dxy*gColor[0][1] + xy*gColor[1][1])>>16;
bfinal = (dxdy*bColor[0][0] + xdy*bColor[1][0] + dxy*bColor[0][1] + xy*bColor[1][1])>>16;

//计算出RGB565的值放入存储空间
BYTE* pColor = (BYTE*)pDst;
 *(pColor + j * dstWidth4 + i*2) = (UINT16)((((rfinal << 11)& 0xF800)|((gfinal << 5)& 0x07E0)|(bfinal& 0x001F)));
//*(pColor + j * (dstWidth4) + i*2) =RGB_565(rfinal,gfinal,bfinal);

if( m_pDib->alpha )
{
////透明通道值
afinal = (dxdy*alpha[0][0]  + xdy*alpha[1][0]  + dxy*alpha[0][1]  + xy*alpha[1][1] )>>16;
BYTE* pAlphaTemp = (BYTE*)pDst;
*(pAlphaTemp + j * dstWidth + i + iPix) = afinal;
}

}
}
}
//计算完的图片信息写入结构体中
if( pDstBuf  != NULL && pNewImage != NULL )
{
pNewImage->m_pDib = (LPDIBDATA_Z)pDstBuf;
pNewImage->m_pDib->type = MAGIC;
pNewImage->m_pDib->bitcount = DIB_BITCOUNT;
pNewImage->m_pDib->width = dstWidth;
pNewImage->m_pDib->height= dstHeight;
pNewImage->m_pDib->widthBytes = dstWidth4;
pNewImage->m_pDib->widthAlphas= dstWidth;
pNewImage->m_pDib->alpha = m_pDib->alpha?(pNewImage->m_pDib->dib + pNewImage->m_pDib->widthBytes*pNewImage->m_pDib->height) : 0;
}
//RETAILMSG(1,(L"Rota--------retrun true-------\n"));

return TRUE;
}
[解决办法]
肯定是你的颜色字节没有对齐,错位了;以前搞过,错位了颜色就出现混乱,自己好好检查一下;其实不用自己发明轮子,SetWorldTransform做的和你那个函数是一样的功能

热点排行