VC++图像旋转问题

1、这个lDstWidth应该与下面的lpDstDIBits中的lDstWidth一致,否则会导致LeaveCriticalSection(&m_sect)崩溃(原因是内存访问数组越界),但是最好使用lDstLineBytes(一行的字节数),否则当旋转之后宽、高为奇数,那么图像就会出现异常显示,撕裂等现象 

2、旋转代码如下,这部分代码在书上或者百度上都能找到 

HGLOBAL  Rotate(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight,
                long lLineBytes,    WORD palSize, long lDstWidth, 
                long lDstHeight,long lDstLineBytes,float    fSina, float fCosa)
{    
    float varFloat1;        //浮点参数变量1
    float varFloat2;        //浮点参数变量2
    LPSTR    lpDstDib;        //指向临时图像的指针

    long i;                 //行循环变量
    long j;                 //列循环变量
    long i1;                 //行循环变量
    long j1;                 //列循环变量
    LPSTR    lpSrcDIBBits;    //指向源像素的指针
    LPSTR    lpDstDIBBits;    //指向临时图像对应像素的指针
    LPSTR    lpDstStartBits;    //指向临时图像对应像素的指针             

    LPBITMAPINFOHEADER lpbmi;// 指向BITMAPINFOHEADER结构的指针        
    varFloat1= (float) (-0.5 * (lDstWidth - 1) * fCosa - 0.5 * (lDstHeight - 1) * fSina// 将经常用到的两个常数事先求出,以便作为常数使用
        + 0.5 * (lDstWidth  - 1));
    varFloat2= (float) ( 0.5 * (lDstWidth - 1) * fSina - 0.5 * (lDstHeight - 1) * fCosa
        + 0.5 * (lDstHeight - 1));        

//注意:    这个lDstWidth应该与下面的lpDstDIBits中的lDstWidth一致,否则会导致LeaveCriticalSection(&m_sect)崩溃(原因是内存访问数组越界),但是最好使用lDstLineBytes(一行的字节数),
//    否则当旋转之后宽高为奇数,那么图像就会出现异常显示,撕裂等现象

    HGLOBAL hDIB = (HGLOBAL) ::GlobalAlloc(GHND, /*lDstLineBytes*/ lDstWidth* lDstHeight + *(LPDWORD)lpSrcDib +palSize);// 分配内存,以保存新DIB        
    if (hDIB == NULL)// 判断是否是有效的DIB对象
    {        
        return FALSE;// 不是,则返回
    }    
    lpDstDib=  (char * )::GlobalLock((HGLOBAL) hDIB);// 锁定内存        
    memcpy(lpDstDib,lpSrcDib, *(LPDWORD)lpSrcDib +palSize);// 复制DIB信息头和调色板            
    
    lpbmi = (LPBITMAPINFOHEADER)lpDstDib;// 获取指针    
    lpbmi->biHeight=lDstHeight;// 更新DIB中图像的高度和宽度
    lpbmi->biWidth =lDstWidth;

    lpDstStartBits=lpDstDib+ *(LPDWORD)lpDstDib
        +palSize;// 求像素起始位置,作用如同::FindDIBBits(gCo.lpSrcDib),这里尝试使用了这种方法,以避免对全局函数的调用

    for(i = 0; i < lDstHeight; i++)// 行操作
    {        
        for(j = 0; j < lDstWidth; j++)// 列操作
        {            
            lpDstDIBBits= (char *)lpDstStartBits+ lDstWidth * (lDstHeight - 1 - i) + j;// 指向新DIB第i行,第j个像素的指针            
            i1= (long) (-((float) j) * fSina + ((float) i) * fCosa + varFloat2 + 0.5);// 计算该像素在源DIB中的坐标
            j1= (long) ( ((float) j) * fCosa + ((float) i) * fSina + varFloat1 + 0.5);                        
            if( (j1>= 0) && (j1< lWidth) && (i1>= 0) && (i1< lHeight))
            {// 判断是否在源图内                
                lpSrcDIBBits= (char *)lpSrcStartBits+ lLineBytes * (lHeight - 1 -i1) + j1;// 指向源DIB第i0行,第j0个像素的指针                                
                *lpDstDIBBits= *lpSrcDIBBits;// 复制像素
            }
            else
            {
                * ((unsigned char*)lpDstDIBBits) = 255;// 源图中不存在的像素,赋为255
            }            
        }        
    }
    return hDIB;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值