?? imagecoding.cpp
字號(hào):
#include "stdafx.h"
#include "GlobalApi.h"
#include "Cdib.h"
#include <io.h>
#include <errno.h>
#include <math.h>
#include <direct.h>
//using namespace std;
// FOURBYTES就是用來(lái)計(jì)算離4最近的整倍數(shù)
#define FOURBYTES(bits) (((bits) + 31) / 32 * 4)
/**************************************************************************
* 文件名:ImageCoding.cpp
*
* 正交變換API函數(shù)庫(kù):
*
* WRITE2IMG() - 256色圖象保存為256色I(xiàn)MG文件
* LOADIMG() - 讀取指定的256色I(xiàn)MG文件
* DIBBITPLANE() - 圖像位平面分解
*
************************************************************************
*/
// PCX文件頭結(jié)構(gòu)
typedef struct{
BYTE bManufacturer;
BYTE bVersion;
BYTE bEncoding;
BYTE bBpp;
WORD wLeft;
WORD wTop;
WORD wRight;
WORD wBottom;
WORD wXResolution;
WORD wYResolution;
BYTE bPalette[48];
BYTE bReserved;
BYTE bPlanes;
WORD wLineBytes;
WORD wPaletteType;
WORD wSrcWidth;
WORD wSrcDepth;
BYTE bFiller[54];
} PCXHEADER;
typedef struct{
BYTE bBpp;
WORD wLeft;
WORD wTop;
WORD wRight;
WORD wBottom;
WORD wXResolution;
WORD wYResolution;
} IMGHEADER;
/*************************************************************************
*
* 函數(shù)名稱:
* WRITE2IMG()
*
* 參數(shù):
* CDib * pDib - 指向CDib對(duì)象的指針
* CFile& file - 要保存的文件
*
* 返回值:
* BOOL - 成功返回True,否則返回False。
*
* 說明:
* 該函數(shù)將指定的圖象保存為IMG文件。
*
*************************************************************************/
BOOL WINAPI WRITE2IMG(CDib * pDib, CFile& file)
{
// 指向源圖像的指針
unsigned char* lpSrc;
//圖象的寬度和高度
LONG lWidth;
LONG lHeight;
// 圖像每行的字節(jié)數(shù)
LONG lLineBytes;
// 循環(huán)變量
LONG i;
LONG j;
// 參與預(yù)測(cè)的象素和當(dāng)前編碼的象素
BYTE bCharA;
BYTE bCharB;
BYTE bCharC;
BYTE bCharD;
// 預(yù)測(cè)值
int nTemp;
// 預(yù)測(cè)后的殘差
int nDpcm;
// 指向編碼后圖像數(shù)據(jù)的指針
BYTE * lpDst;
//得到圖象的寬度和高度
CSize SizeDim;
SizeDim = pDib->GetDimensions();
lWidth = SizeDim.cx;
lHeight = SizeDim.cy;
//得到實(shí)際的Dib圖象存儲(chǔ)大小
CSize SizeRealDim;
SizeRealDim = pDib->GetDibSaveDim();
// 計(jì)算圖像每行的字節(jié)數(shù)
lLineBytes = SizeRealDim.cx;
//圖像數(shù)據(jù)的指針
LPBYTE lpDIBBits = pDib->m_lpImage;
/**********************************************************************
*寫入IMG文件頭信息
***********************************************************************
*/
IMGHEADER Header4IMG;
// 給文件頭賦值
// 像素位數(shù)(256色為8位)
Header4IMG.bBpp = 8;
// 圖像相對(duì)于屏幕的左上角X坐標(biāo)(以像素為單位)
Header4IMG.wLeft = 0;
// 圖像相對(duì)于屏幕的左上角Y坐標(biāo)(以像素為單位)
Header4IMG.wTop = 0;
// 圖像相對(duì)于屏幕的右下角X坐標(biāo)(以像素為單位)
Header4IMG.wRight = lWidth - 1;
// 圖像相對(duì)于屏幕的右下角Y坐標(biāo)(以像素為單位)
Header4IMG.wBottom = lHeight - 1;
// 圖像的水平分辨率
Header4IMG.wXResolution = lWidth;
// 圖像的垂直分辨率
Header4IMG.wYResolution = lHeight;
// 寫入文件頭
file.Write((LPSTR)&Header4IMG, sizeof(IMGHEADER));
// 編碼第0行
i = 0;
for ( j = 0; j < lWidth; j++)
{
// 指向圖象0行j列象素的指針
lpSrc = (BYTE *)lpDIBBits + lLineBytes * (lHeight - 1 - i) +j ;
// 給bCharD賦值
bCharD = *lpSrc;
// 如果是第0行0列,直接將象素值寫入
if(j == 0)
nDpcm = (int)bCharD;
// 利用 Dpcm =D - A 計(jì)算殘差
else
{
bCharA = *(lpSrc - 1);
nDpcm = (int)bCharD - (int)bCharA;
}
// 將殘差寫入文件
file.Write(&nDpcm , sizeof(int));
}
// 編碼第1行到lHeight-1行
for ( i=1;i<lHeight; i++)
{
for ( j = 0; j < lWidth; j++)
{
// 指向當(dāng)前編碼元素的指針
lpSrc = (BYTE *)lpDIBBits + j + lLineBytes * (lHeight - 1 - i);
// 賦值
bCharD = *lpSrc;
bCharB = *(lpSrc + lLineBytes);
// 如果是第一列,利用 殘差=D -B 進(jìn)行預(yù)測(cè)
if(j == 0)
nDpcm = (int)bCharD - (int)bCharB;
else
{
// 利用(B-C)/2+A計(jì)算預(yù)測(cè)值
bCharA = *(lpSrc - 1);
bCharC = *(lpSrc + lLineBytes - 1);
nTemp = (int)((bCharB-bCharC) / 2 + bCharA);
// 如果預(yù)測(cè)值小于0,直接賦零
if(nTemp < 0)
nTemp = 0;
// 如果預(yù)測(cè)值大于255,直接賦值255
else if(nTemp > 255)
nTemp = 255;
else
nTemp = nTemp;
// 得到殘差
nDpcm = (int)bCharD - nTemp;
}
// 將殘差寫入文件
file.Write(&nDpcm , sizeof(int));
}
}
// 開辟一片緩沖區(qū)以保存調(diào)色板
lpDst = new BYTE[769];
// 調(diào)色板起始字節(jié)
* lpDst = 0x0C;
// 得到圖象的調(diào)色板
LPRGBQUAD lpbmc = (LPRGBQUAD)pDib->m_lpvColorTable;
// 讀取當(dāng)前圖象的調(diào)色板
for (i = 0; i < 256; i ++)
{
// 讀取DIB調(diào)色板紅色分量
lpDst[i * 3 + 1] = lpbmc[i].rgbRed;
// 讀取DIB調(diào)色板綠色分量
lpDst[i * 3 + 2] = lpbmc[i].rgbGreen;
// 讀取DIB調(diào)色板藍(lán)色分量
lpDst[i * 3 + 3] = lpbmc[i].rgbBlue;
}
// 寫入調(diào)色板信息
file.Write((LPSTR)lpDst, 769);
// 返回值
return TRUE;
}
/*************************************************************************
*
* 函數(shù)名稱:
* LOADIMG()
*
* 參數(shù):
* CDib * pDib - 指向CDib類的指針
* CFile& file - 要讀取的文件
*
* 返回值:
* BOOL - 成功返回TRUE
*
* 說明:
* 該函數(shù)將讀取指定的IMG文件
*
*************************************************************************/
BOOL WINAPI LOADIMG(CDib * pDib, CFile& file)
{
// 循環(huán)變量
LONG i;
LONG j;
// 圖象高度
LONG lHeight;
// 圖象寬度
LONG lWidth;
// 圖像每行的字節(jié)數(shù)
LONG lLineBytes;
// 中間變量
BYTE bChar;
int nTemp;
// 指向源圖像象素的指針
int * lpSrc;
// 指向編碼后圖像數(shù)據(jù)的指針
BYTE * lpDst;
// 臨時(shí)指針
int * lpTemp;
// 用來(lái)參與預(yù)測(cè)的三個(gè)象素和當(dāng)前編碼象素
BYTE bCharA;
BYTE bCharB;
BYTE bCharC;
// IMG頭文件
IMGHEADER Header4IMG;
/**********************************************************************
*讀出IMG文件頭信息
***********************************************************************
*/
// 嘗試讀取文件頭
if (file.Read((LPSTR)&Header4IMG, sizeof(IMGHEADER))
!= sizeof(IMGHEADER))
{
// 大小不對(duì),返回NULL。
return NULL;
}
// 獲取圖像高度
lHeight = Header4IMG.wBottom - Header4IMG.wTop + 1;
// 獲取圖像寬度
lWidth = Header4IMG.wRight - Header4IMG.wLeft + 1;
// 計(jì)算圖像每行的字節(jié)數(shù)
lLineBytes = FOURBYTES(lWidth * 8);
// 獲得顯示圖象的頭文件
LPBITMAPINFOHEADER lpBI=pDib->m_lpBMIH;
// 給圖象頭文件成員賦值
lpBI->biSize = 40;
lpBI->biWidth = lWidth;
lpBI->biHeight = lHeight;
lpBI->biPlanes = 1;
lpBI->biBitCount = 8;
lpBI->biCompression = BI_RGB;
lpBI->biSizeImage = lHeight * lLineBytes;
lpBI->biXPelsPerMeter = Header4IMG.wXResolution;
lpBI->biYPelsPerMeter = Header4IMG.wYResolution;
lpBI->biClrUsed = 0;
lpBI->biClrImportant = 0;
// 分配內(nèi)存以讀取編碼后的象素
lpSrc = new int[(file.GetLength() - sizeof(IMGHEADER)-769) ];
lpTemp = lpSrc;
// 讀取編碼后的象素
if (file.ReadHuge(lpSrc, file.GetLength() - sizeof(IMGHEADER)-769)
!= file.GetLength() - sizeof(IMGHEADER)-769 )
{
return FALSE;
}
// 重新分配內(nèi)存,以適應(yīng)新的圖象大小
delete pDib->m_lpImage;
pDib->m_lpImage = new unsigned char[lHeight * lLineBytes];
// CDib類中像素位置
lpDst = pDib->m_lpImage;
// 解碼第0行
i = 0;
for(j = 0; j < lWidth; j++)
{
if(j==0)
{
// 如果是0行0列,編碼值就是真實(shí)值
lpDst[j + lLineBytes * (lHeight - 1 - i)] = (BYTE)(*lpTemp);
lpTemp ++;
}
else
{
// 利用 D=A+殘差 得到原來(lái)的象素
lpDst[j+ lLineBytes * (lHeight - 1 - i)]
= (BYTE)(*lpTemp) + lpDst[j + lLineBytes * (lHeight - 1 - i) - 1];
lpTemp++;
}
}
// 解碼第1行到第lHeight-1行
for (i = 1; i < lHeight; i++)
{
for (j = 0; j < lWidth; j++)
{
// 得到象素B的值
bCharB = lpDst[j + lLineBytes * (lHeight - i)];
// 解碼第一列
if(j==0)
{
// 利用 D=B+殘差 得到原來(lái)的象素值
lpDst[j+ lLineBytes * (lHeight - 1 - i)] = (BYTE)((*lpTemp) + bCharB);
lpTemp++;
}
// 解碼剩下的列
else
{
// 利用 D=(B-C)/2 + A + 殘差 得到原來(lái)的象素值
bCharA=lpDst[j - 1 + lLineBytes * (lHeight - 1 - i)];
bCharC=lpDst[j - 1 + lLineBytes * (lHeight - i)];
// 解碼時(shí)的預(yù)測(cè)
nTemp=(int)((bCharB - bCharC) / 2 +bCharA);
// 預(yù)測(cè)值小于0,直接賦0
if(nTemp<0)
nTemp = 0;
// 預(yù)測(cè)值大于255,直接賦值255
else if(nTemp>255)
nTemp = 255;
else
nTemp = nTemp;
// 預(yù)測(cè)值+殘差
lpDst[j + lLineBytes * (lHeight - 1 - i)]
= (BYTE)(*lpTemp + (BYTE)nTemp);
lpTemp++;
}
}
}
// 釋放內(nèi)存
delete lpSrc;
lpDst = NULL;
// 讀調(diào)色板標(biāo)志位
file.Read(&bChar, 1);
if (bChar != 0x0C)
{
// 返回NULL。
return FALSE;
}
// 分配內(nèi)存以讀取編碼后的象素
lpDst = new BYTE[768];
// 圖象中調(diào)色板的位置
LPRGBQUAD lpbmc = (LPRGBQUAD)pDib->m_lpvColorTable;
// 讀取調(diào)色板
if (file.Read(lpDst, 768) != 768)
{
return FALSE;
}
// 給調(diào)色板賦值
for (i = 0; i < 256; i++)
{
lpbmc[i].rgbRed = lpDst[i * 3 + 2];
lpbmc[i].rgbGreen = lpDst[i * 3 + 1];
lpbmc[i].rgbBlue = lpDst[i * 3];
lpbmc[i].rgbReserved = 0;
}
// 返回值
return TRUE;
}
/*************************************************************************
*
* 函數(shù)名稱:
* DIBBITPLANE()
*
* 參數(shù):
* CDib * pDib - 指向CDib類的指針
* CFile& file - 要讀取的文件
*
* 返回值:
* BOOL - 成功返回TRUE
*
* 說明:
* 該函數(shù)將制定的圖象進(jìn)行位平面分解
*
*************************************************************************/
BOOL WINAPI DIBBITPLANE(CDib *pDib,BYTE bBitNum)
{
// 如果輸入的數(shù)不符合要求,不進(jìn)行分解
if(bBitNum <1 || bBitNum >8)
return FALSE;
// 指向源圖像的指針
BYTE * lpSrc;
//圖象的寬度和高度
LONG lWidth;
LONG lHeight;
// 圖像每行的字節(jié)數(shù)
LONG lLineBytes;
// 循環(huán)變量
LONG i;
LONG j;
// 中間變量
BYTE bTemp;
BYTE bA;
// 二進(jìn)制第i位對(duì)應(yīng)的十進(jìn)制值
BYTE bCount;
//得到圖象的寬度和高度
CSize SizeDim;
SizeDim = pDib->GetDimensions();
lWidth = SizeDim.cx;
lHeight = SizeDim.cy;
//得到實(shí)際的Dib圖象存儲(chǔ)大小
CSize SizeRealDim;
SizeRealDim = pDib->GetDibSaveDim();
// 計(jì)算圖像每行的字節(jié)數(shù)
lLineBytes = SizeRealDim.cx;
//圖像數(shù)據(jù)的指針
LPBYTE lpDIBBits = pDib->m_lpImage;
bCount = 1<<(bBitNum - 1);
for (i = 0; i<lHeight; i++)
{
for ( j = 0; j < lWidth; j++)
{
// 指向位圖i行j列的指針
lpSrc = (BYTE *)lpDIBBits + j+lLineBytes * (lHeight - 1 - i);
// 對(duì)位圖按灰度碼進(jìn)行分解
if(bBitNum == 8)
{
// 如果求的是位圖8,直接取二值的第8位
bTemp = (*(lpSrc) & bCount) / bCount;
bTemp = bTemp * 255;
}
else
{
// 否則進(jìn)行異或,求得灰度碼
bTemp = (*(lpSrc) & bCount) / bCount;
bA = bCount * 2;
// 第i+1位圖的象素值
bA = (*(lpSrc) & bA) / bA;
// 異或
bTemp = (bTemp ^ bA) * 255;
}
// 更新源圖象
*(lpSrc) = bTemp;
}
}
// 返回值
return TRUE;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -