⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 图像处理.txt

📁 用数字图像处理主要是为了修改图形,改善图像质量,或是从图像中提起有效信息,还有利用数字图像处理可以对图像进行体积.
💻 TXT
📖 第 1 页 / 共 4 页
字号:

            pPal->palPalEntry[i].peBlue=Gray;

            pPal->palPalEntry[i].peFlags=0;

            *(lpTempPtr++)=(unsigned char)Gray;

            *(lpTempPtr++)=(unsigned char)Gray;

            *(lpTempPtr++)=(unsigned char)Gray;

            *(lpTempPtr++)=0;

        }

 

    if(hPalette!=NULL)                     

        DeleteObject(hPalette);

//生成新的逻辑调色板

    hPalette=CreatePalette(pPal);

    LocalUnlock(hPal);

    LocalFree(hPal);

    hDc=GetDC(hWnd);

    if(hPalette){

        hPrevPalette=SelectPalette(hDc,hPalette,FALSE);

        RealizePalette(hDc);

    }

    if(NumColors==0) //真彩色图才需要处理位图数据

        for(y=0;y<bi.biHeight;y++){

            lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-

y*LineBytes);

            lpTempPtr=(char *)lpTempImgData+(DstBufSize-

DstLineBytes-y*DstLineBytes);

            for(x=0;x<bi.biWidth;x++){

                Blue=(unsigned char )(*lpPtr++);

                Green=(unsigned char )(*lpPtr++);

                Red=(unsigned char )(*lpPtr++);

            

    Y=(float)(Red*0.299+Green*0.587+Blue*0.114);

            //从位图数据计算得到Y值,写入新图中

                Gray=(BYTE)Y; 

                *(lpTempPtr++)=(unsigned char)Gray;

            }

        }

    if(hBitmap!=NULL)

        DeleteObject(hBitmap);

    //产生新的位图

hBitmap=CreateDIBitmap(hDc,

    (LPBITMAPINFOHEADER)lpTempImgData, (LONG)CBM_INIT,

    (LPSTR)lpTempImgData+sizeof(BITMAPINFOHEADER) +

NewNumColors*sizeof(RGBQUAD),(LPBITMAPINFO)lpTempImgData, 

DIB_RGB_COLORS);

    if(hPalette && hPrevPalette){

        SelectPalette(hDc,hPrevPalette,FALSE);

        RealizePalette(hDc);

    }

    hf=_lcreat("c:\\gray.bmp",0);

    _lwrite(hf,(LPSTR)&DstBf,sizeof(BITMAPFILEHEADER)); 

    _lwrite(hf,(LPSTR)lpTempImgData,DstBufSize);

    _lclose(hf);

    //释放内存和资源

    ReleaseDC(hWnd,hDc);

    LocalUnlock(hTempImgData);

    LocalFree(hTempImgData);

    GlobalUnlock(hImgData);

    return TRUE;

}

 

3. 真彩图转256色图(true color to 256 indexed color) 

    我们知道,真彩图中包含最多达2的24次方种颜色,怎样从中选出256种颜色,又要使颜色的失真比较小,这是一个比较复杂的问题。一种简单的做法是将R:G:B以3:3:2表示,即取R,G的高3位,B的高两位,组成一个字节,这样就可以表示256种颜色了,但不难想象,这种方法的失真肯定很严重。我们下面介绍的算法能够比较好的实现真彩到256色的转换。

它的思想是:准备一个长度为4096的数组,代表4096种颜色。对图中的每一个像素,取R,G,B的最高四位,拼成一个12位的整数,对应的数组元素加1。全部统计完后,就得到了这4096种颜色的使用频率。这其中,可能有一些颜色一次也没用到,即对应的数组元素为零(假设不为零的数组元素共有PalCounts个)。将这些为零的数组元素清除出去,使得前PalCounts个元素都不为零。将这PalCounts个数按从大到小的顺序排列(这里我们使用起泡排序),这样,前256种颜色就是用的最多的颜色,它们将作为调色板上的256种颜色。对于剩下的PalCounts-256种颜色并不是简单的丢弃,而是用前256种颜色中的一种来代替,代替的原则是找有最小平方误差的那个。再次对图中的每一个像素,取R,G,B的最高四位,拼成一个12位的整数,如果对应值在前256种颜色中,则直接将该索引值填入位图数据中,如果是在后PalCounts-256种颜色中,则用代替色的索引值填入位图数据中。

下面的两幅图,图3是原真彩图,图4是用上面的算法转成的256色图,可以看出,效果还不错。

                               图3. 原真彩图                               图4. 转换后的256色图

 

下面是上述算法的源程序。

BOOL Trueto256(HWND hWnd)

{

    DWORD                

SrcBufSize,OffBits,DstBufSize,DstLineBytes;

    LPBITMAPINFOHEADER  lpImgData;

    LPSTR                  lpPtr;

    HLOCAL                hTempImgData;

    LPBITMAPINFOHEADER  lpTempImgData;

    LPSTR                  lpTempPtr;

    HDC                    hDc;

    HFILE                  hf;

    LONG                  x,y;

    BITMAPFILEHEADER    DstBf;

    BITMAPINFOHEADER    DstBi;

    LOGPALETTE           *pPal;

    HPALETTE             hPrevPalette; 

    HLOCAL               hPal;

    WORD                 i,j;

    int                    Red,Green,Blue,ClrIndex;

    DWORD               ColorHits[4096];

    WORD                ColorIndex[4096];

    DWORD               PalCounts,temp;

    long                      ColorError1,ColorError2;

 

    if(NumColors!=0){ //NumColors不为零,所以不是真彩图

        MessageBox(hWnd,"Must be a true color bitmap!","Error 

Message",MB_OK|

MB_ICONEXCLAMATION);

        return FALSE;

}

//由于颜色位数有可能发生了改变,所以要重新计算每行占用的字节数以及新图

//的缓冲区大小

    DstLineBytes=(DWORD)WIDTHBYTES(bi.biWidth*8);

    DstBufSize=(DWORD)(sizeof(BITMAPINFOHEADER)+256

*sizeof(RGBQUAD)+

(DWORD)DstLineBytes*bi.biHeight

);

    //DstBf和DstBi为新的BITMAPFILEHEADER和

BITMAPINFOHEADER

    //拷贝原来的头信息

    memcpy((char *)&DstBf,(char 

*)&bf,sizeof(BITMAPFILEHEADER));

    memcpy((char *)&DstBi,(char 

*)&bi,sizeof(BITMAPINFOHEADER));

//做必要的改变

    DstBf.bfSize=DstBufSize+sizeof(BITMAPFILEHEADER);

    DstBf.bfOffBits=(DWORD)(256*sizeof(RGBQUAD)+sizeof(

BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER));

    DstBi.biClrUsed=0;

    DstBi.biBitCount=8;

    //OffBits为到实际位图数据的偏移值

    OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);

    //SrcBufSize为原图缓冲区的大小

    SrcBufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);

    if((hTempImgData=LocalAlloc(LHND,DstBufSize))==NULL)

    {

            MessageBox(hWnd,"Error alloc memory!","Error 

Message",MB_OK|MB_ICONEXCLAMATION);

        return FALSE;

    }

    lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);    

    lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);

    //拷贝位图数据

    memcpy(lpTempImgData,lpImgData,OffBits);

//用新的头信息取代旧的头信息

    memcpy(lpTempImgData,(char*)&DstBi,sizeof(BITMAPINFOHEADER));

//ColorHits为记录颜色使用频率的数组,ColorIndex为记录颜色索引值的数组

//先全部清零

    memset(ColorHits,0,4096*sizeof(DWORD));

    memset(ColorIndex,0,4096*sizeof(WORD));

    for(y=0;y<bi.biHeight;y++){

        lpPtr=(unsigned char *)lpImgData+(SrcBufSize-LineBytes-y*LineBytes);

        for(x=0;x<bi.biWidth;x++){

            //R,G,B各取4位

            Blue=(int)(*(lpPtr++) & 0xf0);

            Green=(int)(*(lpPtr++) & 0xf0);

            Red=(int)(*(lpPtr++) & 0xf0);

            //拼成一个12位整数

            ClrIndex=(Blue<<4) + Green +(Red >>4);

            //相应的数组元素加1

            ColorHits[ClrIndex]++;

        }

    }

    PalCounts=0;

//将为零的元素清除出去

    for (ClrIndex = 0; ClrIndex < 4096; ClrIndex++)

    {

        if(ColorHits[ClrIndex]!=0){

            ColorHits[PalCounts]=ColorHits[ClrIndex];

            //注意调整相应的索引值

            ColorIndex[PalCounts]=ClrIndex;

            PalCounts++; //颜色数加1

        }

    }

//用起泡排序将PalCounts种颜色按从大到小的顺序排列

    for (i = 0; i < PalCounts-1; i++)

        for (j = i + 1; j < PalCounts; j++){

            if (ColorHits[j] > ColorHits[i]){

                temp = ColorHits[i];

                ColorHits[i] = ColorHits[j];

                ColorHits[j] = temp;  

            //注意调整相应的索引值

            temp = ColorIndex[i];

                ColorIndex[i] = ColorIndex[j];

                ColorIndex[j] = (WORD)temp;

            }

        }

    //为新的调色板分配内存

    hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) + 256* sizeof(PALETTEENTRY));

    pPal =(LOGPALETTE *)LocalLock(hPal);

    pPal->palNumEntries =(WORD) 256;

    pPal->palVersion    = 0x300;

    lpTempPtr=(char *)lpTempImgData+sizeof(BITMAPINFOHEADER);

    for (i = 0; i < 256; i++) {

//由12位索引值得到R,G,B的最高4位值

        pPal->palPalEntry[i].peRed=(BYTE)((ColorIndex[i] & 0x00f) << 4);

        pPal->palPalEntry[i].peGreen=(BYTE)((ColorIndex[i] & 0x0f0));

        pPal->palPalEntry[i].peBlue=(BYTE)((ColorIndex[i] & 0xf00) >> 4);

        pPal->palPalEntry[i].peFlags=(BYTE)0;

        *(lpTempPtr++)=(unsigned char)((ColorIndex[i] & 0xf00) >> 4);

        *(lpTempPtr++)=(unsigned char)((ColorIndex[i] & 0x0f0));

        *(lpTempPtr++)=(unsigned char)((ColorIndex[i] & 0x00f) << 4);

        *(lpTempPtr++)=0;

//ColorHits作为颜色记数的作用已经完成了,下面的作用是记录12位索引值对应

//的调色板中的索引值

        ColorHits[i]=i;

    }

    //其余的颜色依据最小平方误差近似为前256中最接近的一种

    if (PalCounts > 256){

        for (i = 256; i < PalCounts; i++){

            //ColorError1记录最小平方误差,一开始赋一个很大的值

            ColorError1=1000000000;

//由12位索引值得到R,G,B的最高4位值

            Blue = (long)((ColorIndex[i] & 0xf00) >> 4);

            Green = (long)((ColorIndex[i] & 0x0f0));

            Red = (long)((ColorIndex[i] & 0x00f) << 4);

            ClrIndex = 0;

            for (j = 0; j < 256; j++){

                //ColorError2计算当前的平方误差

                ColorError2=(long)(Blue-pPal->palPalEntry[j].peBlue)*

(Blue-pPal->palPalEntry[j].peBlue)+(long)(Green-pPal->palPalEntry[j].peGreen)*

(Green-pPal->palPalEntry[j].peGreen)+(long)(Red-pPal->palPalEntry[j].peRed)*

(Red-pPal->palPalEntry[j].peRed); 

                if (ColorError2 < ColorError1){ //找到更小的了

                    ColorError1 = ColorError2;

                    ClrIndex = j; //记录对应的调色板的索引值

                }

            }

//ColorHits记录12位索引值对应的调色板中的索引值

            ColorHits[i] = ClrIndex;

        }

    }                

    if(hPalette!=NULL)                     

        DeleteObject(hPalette);

//产生新的逻辑调色板

    hPalette=CreatePalette(pPal);

    LocalUnlock(hPal);

    LocalFree(hPal);

    hDc=GetDC(hWnd);

    if(hPalette){

        hPrevPalette=SelectPalette(hDc,hPalette,FALSE);

        RealizePalette(hDc);

    }

    for(y=0;y<bi.biHeight;y++){

        lpPtr=(char *)lpImgData+(SrcBufSize-LineBytes-

y*LineBytes);

        lpTempPtr=(char *)lpTempImgData+(DstBufSize-

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -