?? dibapi.cpp
字號:
// 圖像的水平分辨率
pcxHdr.wXResolution = wWidth;
// 圖像的垂直分辨率
pcxHdr.wYResolution = wHeight;
// 調色板數據(對于256色PCX無意義,直接賦值為0)
for (i = 0; i < 48; i ++)
{
pcxHdr.bPalette[i] = 0;
}
// 保留域,設定為0。
pcxHdr.bReserved = 0;
// 圖像色彩平面數目(對于256色PCX設定為1)。
pcxHdr.bPlanes = 1;
// 圖像的寬度(字節為單位),必須為偶數。
// if ((wWidth & 1) == 0)
// {
pcxHdr.wLineBytes = wWidth;
// }
// else
// {
// pcxHdr.wLineBytes = wWidth + 1;
// }
// 圖像調色板的類型,1表示彩色或者單色圖像,2表示圖像是灰度圖。
pcxHdr.wPaletteType = 1;
// 制作該圖像的屏幕寬度(像素為單位)
pcxHdr.wSrcWidth = 0;
// 制作該圖像的屏幕高度(像素為單位)
pcxHdr.wSrcDepth = 0;
// 保留域,取值設定為0。
for (i = 0; i < 54; i ++)
{
pcxHdr.bFiller[i] = 0;
}
// 寫入文件頭
file.Write((LPSTR)&pcxHdr, sizeof(PCXHEADER));
//*******************************************************************************
// 開始編碼
// 開辟一片緩沖區(2被原始圖像大小)以保存編碼結果
lpDst = new BYTE[wHeight * wWidth * 2];
// 指明當前已經用了多少緩沖區(字節數)
dwBuffUsed = 0;
// 每行
for (i = 0; i < wHeight; i++)
{
// 指向DIB第i行,第0個象素的指針
lpSrc = (BYTE *)lpDIBBits + lLineBytes * (wHeight - 1 - i);
// 給bChar1賦值
bChar1 = *lpSrc;
// 設置iCount為1
iCount = 1;
// 剩余列
for (j = 1; j < wWidth; j ++)
{
// 指向DIB第i行,第j個象素的指針
lpSrc++;
// 讀取下一個像素
bChar2 = *lpSrc;
// 判斷是否和bChar1相同并且iCount < 63
if ((bChar1 == bChar2) && (iCount < 63))
{
// 相同,計數加1
iCount ++;
// 繼續讀下一個
}
else
{
// 不同,或者iCount = 63
// 寫入緩沖區
if ((iCount > 1) || (bChar1 >= 0xC0))
{
// 保存碼長信息
lpDst[dwBuffUsed] = iCount | 0xC0;
// 保存bChar1
lpDst[dwBuffUsed + 1] = bChar1;
// 更新dwBuffUsed
dwBuffUsed += 2;
}
else
{
// 直接保存該值
lpDst[dwBuffUsed] = bChar1;
// 更新dwBuffUsed
dwBuffUsed ++;
}
// 重新給bChar1賦值
bChar1 = bChar2;
// 設置iCount為1
iCount = 1;
}
}
// 保存每行最后一部分編碼
if ((iCount > 1) || (bChar1 >= 0xC0))
{
// 保存碼長信息
lpDst[dwBuffUsed] = iCount | 0xC0;
// 保存bChar1
lpDst[dwBuffUsed + 1] = bChar1;
// 更新dwBuffUsed
dwBuffUsed += 2;
}
else
{
// 直接保存該值
lpDst[dwBuffUsed] = bChar1;
// 更新dwBuffUsed
dwBuffUsed ++;
}
}
// 寫入編碼結果
file.WriteHuge((LPSTR)lpDst, dwBuffUsed);
// 釋放內存
delete lpDst;
//**************************************************************************
// 寫入調色板信息
// 指向BITMAPINFO結構的指針(Win3.0)
LPBITMAPINFO lpbmi;
// 指向BITMAPCOREINFO結構的指針
LPBITMAPCOREINFO lpbmc;
// 表明是否是Win3.0 DIB的標記
BOOL bWinStyleDIB;
// 開辟一片緩沖區以保存調色板
lpDst = new BYTE[769];
// 調色板起始字節
* lpDst = 0x0C;
// 獲取指向BITMAPINFO結構的指針(Win3.0)
lpbmi = (LPBITMAPINFO)lpDIB;
// 獲取指向BITMAPCOREINFO結構的指針
lpbmc = (LPBITMAPCOREINFO)lpDIB;
// 判斷是否是WIN3.0的DIB
bWinStyleDIB = IS_WIN30_DIB(lpDIB);
// 讀取當前DIB調色板
for (i = 0; i < 256; i ++)
{
if (bWinStyleDIB)
{
// 讀取DIB調色板紅色分量
lpDst[i * 3 + 1] = lpbmi->bmiColors[i].rgbRed;
// 讀取DIB調色板綠色分量
lpDst[i * 3 + 2] = lpbmi->bmiColors[i].rgbGreen;
// 讀取DIB調色板藍色分量
lpDst[i * 3 + 3] = lpbmi->bmiColors[i].rgbBlue;
}
else
{
// 讀取DIB調色板紅色分量
lpDst[i * 3 + 1] = lpbmc->bmciColors[i].rgbtRed;
// 讀取DIB調色板綠色分量
lpDst[i * 3 + 2] = lpbmc->bmciColors[i].rgbtGreen;
// 讀取DIB調色板藍色分量
lpDst[i * 3 + 3] = lpbmc->bmciColors[i].rgbtBlue;
}
}
// 寫入調色板信息
file.Write((LPSTR)lpDst, 769);
// 返回
return TRUE;
}
/*************************************************************************
*
* 函數名稱:
* ReadPCX256()
*
* 參數:
* CFile& file - 要讀取的文件
*
* 返回值:
* HDIB - 成功返回DIB的句柄,否則返回NULL。
*
* 說明:
* 該函數將讀取指定的256色PCX文件。將讀取的結果保存在一個未壓縮
* 編碼的DIB對象中。
*
*************************************************************************/
HDIB WINAPI ReadPCX256(CFile& file)
{
// PCX文件頭
PCXHEADER pcxHdr;
// DIB大小(字節數)
DWORD dwDIBSize;
// DIB句柄
HDIB hDIB;
// DIB指針
LPSTR pDIB;
// 循環變量
LONG i;
LONG j;
// 重復像素計數
int iCount;
// DIB高度
WORD wHeight;
// DIB寬度
WORD wWidth;
// 圖像每行的字節數
LONG lLineBytes;
// 中間變量
BYTE bChar;
// 指向源圖像象素的指針
BYTE * lpSrc;
// 指向編碼后圖像數據的指針
BYTE * lpDst;
// 臨時指針
BYTE * lpTemp;
// 嘗試讀取PCX文件頭
if (file.Read((LPSTR)&pcxHdr, sizeof(PCXHEADER)) != sizeof(PCXHEADER))
{
// 大小不對,返回NULL。
return NULL;
}
// 判斷是否是256色PCX文件,檢查第一個字節是否是0x0A,
if ((pcxHdr.bManufacturer != 0x0A) || (pcxHdr.bBpp != 8) || (pcxHdr.bPlanes != 1))
{
// 非256色PCX文件,返回NULL。
return NULL;
}
// 獲取圖像高度
wHeight = pcxHdr.wBottom - pcxHdr.wTop + 1;
// 獲取圖像寬度
wWidth = pcxHdr.wRight - pcxHdr.wLeft + 1;
// 計算圖像每行的字節數
lLineBytes = WIDTHBYTES(wWidth * 8);
// 計算DIB長度(字節)
dwDIBSize = sizeof(BITMAPINFOHEADER) + 1024 + wHeight * lLineBytes;
// 為DIB分配內存
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize);
if (hDIB == 0)
{
// 內存分配失敗,返回NULL。
return NULL;
}
// 鎖定
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
// 指向BITMAPINFOHEADER的指針
LPBITMAPINFOHEADER lpBI;
// 賦值
lpBI = (LPBITMAPINFOHEADER) pDIB;
// 給lpBI成員賦值
lpBI->biSize = 40;
lpBI->biWidth = wWidth;
lpBI->biHeight = wHeight;
lpBI->biPlanes = 1;
lpBI->biBitCount = 8;
lpBI->biCompression = BI_RGB;
lpBI->biSizeImage = wHeight * lLineBytes;
lpBI->biXPelsPerMeter = pcxHdr.wXResolution;
lpBI->biYPelsPerMeter = pcxHdr.wYResolution;
lpBI->biClrUsed = 0;
lpBI->biClrImportant = 0;
// 分配內存以讀取編碼后的象素
lpSrc = new BYTE[file.GetLength() - sizeof(PCXHEADER) - 769];
lpTemp = lpSrc;
// 讀取編碼后的象素
if (file.ReadHuge(lpSrc, file.GetLength() - sizeof(PCXHEADER) - 769) !=
file.GetLength() - sizeof(PCXHEADER) - 769 )
{
// 大小不對。
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
// 釋放內存
::GlobalFree((HGLOBAL) hDIB);
// 返回NULL。
return NULL;
}
// 計算DIB中像素位置
lpDst = (BYTE *) FindDIBBits(pDIB);
// 一行一行解碼
for (j = 0; j <wHeight; j++)
{
i = 0;
while (i < wWidth)
{
// 讀取一個字節
bChar = *lpTemp;
lpTemp++;
if ((bChar & 0xC0) == 0xC0)
{
// 行程
iCount = bChar & 0x3F;
// 讀取下一個字節
bChar = *lpTemp;
lpTemp++;
// bChar重復iCount次保存
memset(&lpDst[(wHeight - j - 1) * lLineBytes + i], bChar, iCount);
// 已經讀取像素的個數加iCount
i += iCount;
}
else
{
// 保存當前字節
lpDst[(wHeight - j - 1) * lLineBytes + i] = bChar;
// 已經讀取像素的個數加1
i += 1;
}
}
}
// 釋放內存
delete lpSrc;
//*************************************************************
// 調色板
// 讀調色板標志位
file.Read(&bChar, 1);
if (bChar != 0x0C)
{
// 出錯
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
// 釋放內存
::GlobalFree((HGLOBAL) hDIB);
// 返回NULL。
return NULL;
}
// 分配內存以讀取編碼后的象素
lpSrc = new BYTE[768];
// 計算DIB中調色板的位置
lpDst = (BYTE *) pDIB + sizeof(BITMAPINFOHEADER);
// 讀取調色板
if (file.Read(lpSrc, 768) != 768)
{
// 大小不對。
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
// 釋放內存
::GlobalFree((HGLOBAL) hDIB);
// 返回NULL。
return NULL;
}
// 給調色板賦值
for (i = 0; i < 256; i++)
{
lpDst[i * 4] = lpSrc[i * 3 + 2];
lpDst[i * 4 + 1] = lpSrc[i * 3 + 1];
lpDst[i * 4 + 2] = lpSrc[i * 3];
lpDst[i * 4 + 3] = 0;
}
// 釋放內存
delete lpSrc;
// 解除鎖定
::GlobalUnlock((HGLOBAL) hDIB);
// 返回DIB句柄
return hDIB;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -