ImageCoding.cpp
上传用户:wangchdtw
上传日期:2014-04-02
资源大小:329k
文件大小:11k
- #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就是用来计算离4最近的整倍数
- #define FOURBYTES(bits) (((bits) + 31) / 32 * 4)
- /**************************************************************************
- * 文件名:ImageCoding.cpp
- *
- * 正交变换API函数库:
- *
- * WRITE2IMG() - 256色图象保存为256色IMG文件
- * LOADIMG() - 读取指定的256色IMG文件
- * DIBBITPLANE() - 图像位平面分解
- *
- ************************************************************************
- */
- // PCX文件头结构
- 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;
- /*************************************************************************
- *
- * 函数名称:
- * WRITE2IMG()
- *
- * 参数:
- * CDib * pDib - 指向CDib对象的指针
- * CFile& file - 要保存的文件
- *
- * 返回值:
- * BOOL - 成功返回True,否则返回False。
- *
- * 说明:
- * 该函数将指定的图象保存为IMG文件。
- *
- *************************************************************************/
- BOOL WINAPI WRITE2IMG(CDib * pDib, CFile& file)
- {
-
- // 指向源图像的指针
- unsigned char* lpSrc;
- //图象的宽度和高度
- LONG lWidth;
- LONG lHeight;
- // 图像每行的字节数
- LONG lLineBytes;
-
- // 循环变量
- LONG i;
- LONG j;
-
- // 参与预测的象素和当前编码的象素
- BYTE bCharA;
- BYTE bCharB;
- BYTE bCharC;
- BYTE bCharD;
-
- // 预测值
- int nTemp;
-
- // 预测后的残差
- int nDpcm;
-
- // 指向编码后图像数据的指针
- BYTE * lpDst;
-
- //得到图象的宽度和高度
- CSize SizeDim;
- SizeDim = pDib->GetDimensions();
- lWidth = SizeDim.cx;
- lHeight = SizeDim.cy;
-
- //得到实际的Dib图象存储大小
- CSize SizeRealDim;
- SizeRealDim = pDib->GetDibSaveDim();
- // 计算图像每行的字节数
- lLineBytes = SizeRealDim.cx;
-
- //图像数据的指针
- LPBYTE lpDIBBits = pDib->m_lpImage;
-
- /**********************************************************************
- *写入IMG文件头信息
- ***********************************************************************
- */
- IMGHEADER Header4IMG;
-
- // 给文件头赋值
-
- // 像素位数(256色为8位)
- Header4IMG.bBpp = 8;
-
- // 图像相对于屏幕的左上角X坐标(以像素为单位)
- Header4IMG.wLeft = 0;
-
- // 图像相对于屏幕的左上角Y坐标(以像素为单位)
- Header4IMG.wTop = 0;
-
- // 图像相对于屏幕的右下角X坐标(以像素为单位)
- Header4IMG.wRight = lWidth - 1;
-
- // 图像相对于屏幕的右下角Y坐标(以像素为单位)
- 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 计算残差
- 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++)
- {
- // 指向当前编码元素的指针
- lpSrc = (BYTE *)lpDIBBits + j + lLineBytes * (lHeight - 1 - i);
-
- // 赋值
- bCharD = *lpSrc;
- bCharB = *(lpSrc + lLineBytes);
- // 如果是第一列,利用 残差=D -B 进行预测
- if(j == 0)
- nDpcm = (int)bCharD - (int)bCharB;
- else
- {
- // 利用(B-C)/2+A计算预测值
- bCharA = *(lpSrc - 1);
- bCharC = *(lpSrc + lLineBytes - 1);
- nTemp = (int)((bCharB-bCharC) / 2 + bCharA);
-
- // 如果预测值小于0,直接赋零
- if(nTemp < 0)
- nTemp = 0;
- // 如果预测值大于255,直接赋值255
- else if(nTemp > 255)
- nTemp = 255;
- else
- nTemp = nTemp;
- // 得到残差
- nDpcm = (int)bCharD - nTemp;
- }
- // 将残差写入文件
- file.Write(&nDpcm , sizeof(int));
- }
- }
-
- // 开辟一片缓冲区以保存调色板
- lpDst = new BYTE[769];
-
- // 调色板起始字节
- * lpDst = 0x0C;
- // 得到图象的调色板
- LPRGBQUAD lpbmc = (LPRGBQUAD)pDib->m_lpvColorTable;
-
- // 读取当前图象的调色板
- for (i = 0; i < 256; i ++)
- {
-
- // 读取DIB调色板红色分量
- lpDst[i * 3 + 1] = lpbmc[i].rgbRed;
-
- // 读取DIB调色板绿色分量
- lpDst[i * 3 + 2] = lpbmc[i].rgbGreen;
-
- // 读取DIB调色板蓝色分量
- lpDst[i * 3 + 3] = lpbmc[i].rgbBlue;
- }
-
- // 写入调色板信息
- file.Write((LPSTR)lpDst, 769);
- // 返回值
- return TRUE;
- }
- /*************************************************************************
- *
- * 函数名称:
- * LOADIMG()
- *
- * 参数:
- * CDib * pDib - 指向CDib类的指针
- * CFile& file - 要读取的文件
- *
- * 返回值:
- * BOOL - 成功返回TRUE
- *
- * 说明:
- * 该函数将读取指定的IMG文件
- *
- *************************************************************************/
- BOOL WINAPI LOADIMG(CDib * pDib, CFile& file)
- {
- // 循环变量
- LONG i;
- LONG j;
-
- // 图象高度
- LONG lHeight;
-
- // 图象宽度
- LONG lWidth;
-
- // 图像每行的字节数
- LONG lLineBytes;
-
- // 中间变量
- BYTE bChar;
- int nTemp;
-
- // 指向源图像象素的指针
- int * lpSrc;
-
- // 指向编码后图像数据的指针
- BYTE * lpDst;
-
- // 临时指针
- int * lpTemp;
- // 用来参与预测的三个象素和当前编码象素
- BYTE bCharA;
- BYTE bCharB;
- BYTE bCharC;
- // IMG头文件
- IMGHEADER Header4IMG;
-
- /**********************************************************************
- *读出IMG文件头信息
- ***********************************************************************
- */
-
- // 尝试读取文件头
- if (file.Read((LPSTR)&Header4IMG, sizeof(IMGHEADER))
- != sizeof(IMGHEADER))
- {
- // 大小不对,返回NULL。
- return NULL;
- }
-
- // 获取图像高度
- lHeight = Header4IMG.wBottom - Header4IMG.wTop + 1;
-
- // 获取图像宽度
- lWidth = Header4IMG.wRight - Header4IMG.wLeft + 1;
-
- // 计算图像每行的字节数
- 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;
-
- // 分配内存以读取编码后的象素
- 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;
- }
-
- // 重新分配内存,以适应新的图象大小
- 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列,编码值就是真实值
- lpDst[j + lLineBytes * (lHeight - 1 - i)] = (BYTE)(*lpTemp);
- lpTemp ++;
- }
- else
- {
- // 利用 D=A+残差 得到原来的象素
- 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+残差 得到原来的象素值
- lpDst[j+ lLineBytes * (lHeight - 1 - i)] = (BYTE)((*lpTemp) + bCharB);
- lpTemp++;
- }
-
- // 解码剩下的列
- else
- {
- // 利用 D=(B-C)/2 + A + 残差 得到原来的象素值
- bCharA=lpDst[j - 1 + lLineBytes * (lHeight - 1 - i)];
- bCharC=lpDst[j - 1 + lLineBytes * (lHeight - i)];
-
- // 解码时的预测
- nTemp=(int)((bCharB - bCharC) / 2 +bCharA);
-
- // 预测值小于0,直接赋0
- if(nTemp<0)
- nTemp = 0;
- // 预测值大于255,直接赋值255
- else if(nTemp>255)
- nTemp = 255;
- else
- nTemp = nTemp;
- // 预测值+残差
- lpDst[j + lLineBytes * (lHeight - 1 - i)]
- = (BYTE)(*lpTemp + (BYTE)nTemp);
- lpTemp++;
- }
- }
- }
- // 释放内存
- delete lpSrc;
- lpDst = NULL;
-
- // 读调色板标志位
- file.Read(&bChar, 1);
- if (bChar != 0x0C)
- {
- // 返回NULL。
- return FALSE;
- }
-
- // 分配内存以读取编码后的象素
- lpDst = new BYTE[768];
-
- // 图象中调色板的位置
- LPRGBQUAD lpbmc = (LPRGBQUAD)pDib->m_lpvColorTable;
-
- // 读取调色板
- if (file.Read(lpDst, 768) != 768)
- {
- return FALSE;
- }
-
- // 给调色板赋值
- 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;
- }
- /*************************************************************************
- *
- * 函数名称:
- * DIBBITPLANE()
- *
- * 参数:
- * CDib * pDib - 指向CDib类的指针
- * CFile& file - 要读取的文件
- *
- * 返回值:
- * BOOL - 成功返回TRUE
- *
- * 说明:
- * 该函数将制定的图象进行位平面分解
- *
- *************************************************************************/
- BOOL WINAPI DIBBITPLANE(CDib *pDib,BYTE bBitNum)
- {
- // 如果输入的数不符合要求,不进行分解
- if(bBitNum <1 || bBitNum >8)
- return FALSE;
-
- // 指向源图像的指针
- BYTE * lpSrc;
- //图象的宽度和高度
- LONG lWidth;
- LONG lHeight;
- // 图像每行的字节数
- LONG lLineBytes;
-
- // 循环变量
- LONG i;
- LONG j;
- // 中间变量
- BYTE bTemp;
- BYTE bA;
- // 二进制第i位对应的十进制值
- BYTE bCount;
-
- //得到图象的宽度和高度
- CSize SizeDim;
- SizeDim = pDib->GetDimensions();
- lWidth = SizeDim.cx;
- lHeight = SizeDim.cy;
-
- //得到实际的Dib图象存储大小
- CSize SizeRealDim;
- SizeRealDim = pDib->GetDibSaveDim();
- // 计算图像每行的字节数
- lLineBytes = SizeRealDim.cx;
-
- //图像数据的指针
- 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);
- // 对位图按灰度码进行分解
- if(bBitNum == 8)
- {
- // 如果求的是位图8,直接取二值的第8位
- bTemp = (*(lpSrc) & bCount) / bCount;
- bTemp = bTemp * 255;
- }
- else
- {
- // 否则进行异或,求得灰度码
- bTemp = (*(lpSrc) & bCount) / bCount;
- bA = bCount * 2;
- // 第i+1位图的象素值
- bA = (*(lpSrc) & bA) / bA;
- // 异或
- bTemp = (bTemp ^ bA) * 255;
- }
- // 更新源图象
- *(lpSrc) = bTemp;
- }
- }
- // 返回值
- return TRUE;
- }