ImageCoding.cpp
上传用户:panpan8800
上传日期:2013-06-29
资源大小:274k
文件大小:11k
源码类别:

图形图像处理

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "GlobalApi.h"
  3. #include "Cdib.h"
  4. #include <io.h>
  5. #include <errno.h>
  6. #include <math.h>
  7. #include <direct.h>
  8. //using namespace std;
  9. // FOURBYTES就是用来计算离4最近的整倍数
  10. #define FOURBYTES(bits)    (((bits) + 31) / 32 * 4)
  11. /**************************************************************************
  12.  *  文件名:ImageCoding.cpp
  13.  *
  14.  *  正交变换API函数库:
  15.  *
  16.  *  WRITE2IMG() - 256色图象保存为256色IMG文件
  17.  *  LOADIMG() - 读取指定的256色IMG文件 
  18.  *  DIBBITPLANE() - 图像位平面分解
  19.  *
  20.  ************************************************************************
  21. */
  22. // PCX文件头结构
  23. typedef struct{
  24.  BYTE bManufacturer;
  25.  BYTE bVersion;
  26.  BYTE bEncoding;
  27.  BYTE bBpp;
  28.  WORD wLeft;
  29.  WORD wTop;
  30.  WORD wRight;
  31.  WORD wBottom;
  32.  WORD wXResolution;
  33.  WORD wYResolution;
  34.  BYTE bPalette[48];
  35.  BYTE bReserved;
  36.  BYTE bPlanes;
  37.  WORD wLineBytes;
  38.  WORD wPaletteType;
  39.  WORD wSrcWidth;
  40.  WORD wSrcDepth;
  41.  BYTE bFiller[54];
  42. } PCXHEADER;
  43. typedef struct{
  44.  BYTE bBpp;
  45.  WORD wLeft;
  46.  WORD wTop;
  47.  WORD wRight;
  48.  WORD wBottom;
  49.  WORD wXResolution;
  50.  WORD wYResolution;
  51. } IMGHEADER;
  52. /*************************************************************************
  53.  *
  54.  * 函数名称:
  55.  *   WRITE2IMG()
  56.  *
  57.  * 参数:
  58.  *   CDib * pDib        - 指向CDib对象的指针
  59.  *   CFile& file        - 要保存的文件
  60.  *
  61.  * 返回值:
  62.  *   BOOL               - 成功返回True,否则返回False。
  63.  *
  64.  * 说明:
  65.  *   该函数将指定的图象保存为IMG文件。
  66.  *
  67.  *************************************************************************/
  68. BOOL WINAPI WRITE2IMG(CDib * pDib, CFile& file)
  69. {
  70. // 指向源图像的指针
  71. unsigned char* lpSrc;
  72. //图象的宽度和高度
  73. LONG    lWidth;
  74. LONG    lHeight;
  75. // 图像每行的字节数
  76. LONG lLineBytes;
  77. // 循环变量
  78. LONG i;
  79. LONG j;
  80. // 参与预测的象素和当前编码的象素
  81. BYTE bCharA;
  82. BYTE bCharB;
  83. BYTE bCharC;
  84. BYTE bCharD;
  85.     
  86. // 预测值
  87. int nTemp;
  88. // 预测后的残差
  89. int nDpcm;
  90. // 指向编码后图像数据的指针
  91. BYTE * lpDst;
  92. //得到图象的宽度和高度
  93. CSize   SizeDim;
  94. SizeDim = pDib->GetDimensions();
  95. lWidth  = SizeDim.cx;
  96. lHeight = SizeDim.cy;
  97. //得到实际的Dib图象存储大小
  98. CSize   SizeRealDim;
  99. SizeRealDim = pDib->GetDibSaveDim();
  100. // 计算图像每行的字节数
  101. lLineBytes = SizeRealDim.cx;
  102. //图像数据的指针
  103. LPBYTE  lpDIBBits = pDib->m_lpImage;
  104. /**********************************************************************
  105. *写入IMG文件头信息
  106. ***********************************************************************
  107. */
  108. IMGHEADER Header4IMG;
  109. // 给文件头赋值
  110. // 像素位数(256色为8位)
  111. Header4IMG.bBpp = 8;
  112. // 图像相对于屏幕的左上角X坐标(以像素为单位)
  113. Header4IMG.wLeft = 0;
  114. // 图像相对于屏幕的左上角Y坐标(以像素为单位)
  115. Header4IMG.wTop = 0;
  116. // 图像相对于屏幕的右下角X坐标(以像素为单位)
  117. Header4IMG.wRight = lWidth - 1;
  118. // 图像相对于屏幕的右下角Y坐标(以像素为单位)
  119. Header4IMG.wBottom = lHeight - 1;
  120. // 图像的水平分辨率
  121. Header4IMG.wXResolution = lWidth;
  122. // 图像的垂直分辨率
  123. Header4IMG.wYResolution = lHeight;
  124. // 写入文件头
  125. file.Write((LPSTR)&Header4IMG, sizeof(IMGHEADER));
  126. // 编码第0行
  127. i = 0;
  128. for ( j = 0; j < lWidth; j++)
  129. {
  130. // 指向图象0行j列象素的指针
  131. lpSrc = (BYTE *)lpDIBBits + lLineBytes * (lHeight - 1 - i) +j ;
  132. // 给bCharD赋值
  133. bCharD = *lpSrc;
  134. // 如果是第0行0列,直接将象素值写入
  135. if(j == 0)
  136. nDpcm = (int)bCharD;
  137. // 利用 Dpcm =D - A 计算残差 
  138. else
  139. {
  140. bCharA = *(lpSrc - 1);
  141. nDpcm  = (int)bCharD - (int)bCharA;
  142. }
  143. // 将残差写入文件
  144. file.Write(&nDpcm , sizeof(int));
  145. }
  146. // 编码第1行到lHeight-1行
  147. for ( i=1;i<lHeight; i++)
  148. {
  149. for ( j = 0; j < lWidth; j++)
  150. {
  151. // 指向当前编码元素的指针
  152. lpSrc = (BYTE *)lpDIBBits + j + lLineBytes * (lHeight - 1 - i);
  153. // 赋值
  154. bCharD = *lpSrc;
  155. bCharB = *(lpSrc + lLineBytes);
  156. // 如果是第一列,利用 残差=D -B 进行预测
  157. if(j == 0)
  158. nDpcm = (int)bCharD - (int)bCharB;
  159. else
  160. {
  161. // 利用(B-C)/2+A计算预测值
  162. bCharA = *(lpSrc - 1);
  163. bCharC = *(lpSrc + lLineBytes - 1);
  164. nTemp  =  (int)((bCharB-bCharC) / 2 + bCharA);
  165. // 如果预测值小于0,直接赋零
  166. if(nTemp < 0)
  167. nTemp = 0;
  168. // 如果预测值大于255,直接赋值255
  169. else if(nTemp > 255)
  170. nTemp = 255;
  171. else
  172. nTemp = nTemp;
  173. // 得到残差
  174. nDpcm = (int)bCharD - nTemp;
  175. }
  176. // 将残差写入文件
  177. file.Write(&nDpcm , sizeof(int));
  178. }
  179. }
  180. // 开辟一片缓冲区以保存调色板
  181. lpDst = new BYTE[769];
  182. // 调色板起始字节
  183. * lpDst = 0x0C;
  184. // 得到图象的调色板
  185. LPRGBQUAD lpbmc = (LPRGBQUAD)pDib->m_lpvColorTable;
  186. // 读取当前图象的调色板
  187. for (i = 0; i < 256; i ++)
  188. {
  189. // 读取DIB调色板红色分量
  190. lpDst[i * 3 + 1] = lpbmc[i].rgbRed;
  191. // 读取DIB调色板绿色分量
  192. lpDst[i * 3 + 2] = lpbmc[i].rgbGreen;
  193. // 读取DIB调色板蓝色分量
  194. lpDst[i * 3 + 3] = lpbmc[i].rgbBlue;
  195. }
  196. // 写入调色板信息
  197. file.Write((LPSTR)lpDst, 769);
  198. // 返回值
  199. return TRUE;
  200. }
  201. /*************************************************************************
  202.  *
  203.  * 函数名称:
  204.  *   LOADIMG()
  205.  *
  206.  * 参数:
  207.  *   CDib * pDib        - 指向CDib类的指针
  208.  *   CFile& file        - 要读取的文件
  209.  *
  210.  * 返回值:
  211.  *   BOOL               - 成功返回TRUE
  212.  *
  213.  * 说明:
  214.  *   该函数将读取指定的IMG文件
  215.  *
  216.  *************************************************************************/
  217. BOOL WINAPI LOADIMG(CDib * pDib, CFile& file)
  218. {
  219. // 循环变量
  220. LONG i;
  221. LONG j;
  222. // 图象高度
  223. LONG lHeight;
  224. // 图象宽度
  225. LONG lWidth;
  226. // 图像每行的字节数
  227. LONG lLineBytes;
  228. // 中间变量
  229. BYTE bChar;
  230. int     nTemp;
  231. // 指向源图像象素的指针
  232. int * lpSrc;
  233. // 指向编码后图像数据的指针
  234. BYTE * lpDst;
  235. // 临时指针
  236. int * lpTemp;
  237. // 用来参与预测的三个象素和当前编码象素
  238. BYTE bCharA;
  239. BYTE bCharB;
  240. BYTE bCharC;
  241. // IMG头文件
  242. IMGHEADER Header4IMG;
  243. /**********************************************************************
  244. *读出IMG文件头信息
  245. ***********************************************************************
  246. */
  247. // 尝试读取文件头
  248. if (file.Read((LPSTR)&Header4IMG, sizeof(IMGHEADER)) 
  249. != sizeof(IMGHEADER))
  250. {
  251. // 大小不对,返回NULL。
  252. return NULL;
  253. }
  254. // 获取图像高度
  255. lHeight = Header4IMG.wBottom - Header4IMG.wTop + 1;
  256. // 获取图像宽度
  257. lWidth  = Header4IMG.wRight - Header4IMG.wLeft + 1;
  258. // 计算图像每行的字节数
  259. lLineBytes = FOURBYTES(lWidth * 8);
  260. // 获得显示图象的头文件
  261. LPBITMAPINFOHEADER lpBI=pDib->m_lpBMIH;
  262. // 给图象头文件成员赋值
  263. lpBI->biSize = 40;
  264. lpBI->biWidth = lWidth;
  265. lpBI->biHeight = lHeight;
  266. lpBI->biPlanes = 1;
  267. lpBI->biBitCount = 8;
  268. lpBI->biCompression = BI_RGB;
  269. lpBI->biSizeImage = lHeight * lLineBytes;
  270. lpBI->biXPelsPerMeter = Header4IMG.wXResolution;
  271. lpBI->biYPelsPerMeter = Header4IMG.wYResolution;
  272. lpBI->biClrUsed = 0;
  273. lpBI->biClrImportant = 0;
  274. // 分配内存以读取编码后的象素
  275. lpSrc = new int[(file.GetLength() - sizeof(IMGHEADER)-769) ];
  276. lpTemp = lpSrc;
  277. // 读取编码后的象素
  278. if (file.ReadHuge(lpSrc, file.GetLength() - sizeof(IMGHEADER)-769) 
  279. != file.GetLength() - sizeof(IMGHEADER)-769 )
  280. {
  281. return FALSE;
  282. }
  283. // 重新分配内存,以适应新的图象大小
  284. delete  pDib->m_lpImage;
  285. pDib->m_lpImage = new unsigned char[lHeight * lLineBytes];
  286. // CDib类中像素位置
  287. lpDst = pDib->m_lpImage;
  288. // 解码第0行
  289. i = 0;
  290. for(j = 0; j < lWidth; j++)
  291. {
  292. if(j==0)
  293. {
  294. // 如果是0行0列,编码值就是真实值
  295. lpDst[j + lLineBytes * (lHeight - 1 - i)] = (BYTE)(*lpTemp);
  296. lpTemp ++;
  297. }
  298. else
  299. {
  300. // 利用 D=A+残差 得到原来的象素
  301. lpDst[j+ lLineBytes * (lHeight - 1 - i)]
  302. = (BYTE)(*lpTemp) + lpDst[j + lLineBytes * (lHeight - 1 - i) - 1];
  303. lpTemp++;
  304. }
  305. }
  306. // 解码第1行到第lHeight-1行
  307. for (i = 1; i < lHeight; i++)
  308.     {
  309. for (j = 0; j < lWidth; j++)
  310. {
  311. // 得到象素B的值
  312. bCharB = lpDst[j + lLineBytes * (lHeight  - i)];
  313. // 解码第一列
  314. if(j==0)
  315. {
  316. // 利用 D=B+残差 得到原来的象素值
  317. lpDst[j+ lLineBytes * (lHeight - 1 - i)] = (BYTE)((*lpTemp) + bCharB);
  318. lpTemp++;
  319. }
  320. // 解码剩下的列
  321. else
  322. {
  323. // 利用 D=(B-C)/2 + A + 残差 得到原来的象素值
  324. bCharA=lpDst[j - 1 + lLineBytes * (lHeight - 1 - i)];
  325. bCharC=lpDst[j - 1 + lLineBytes * (lHeight - i)];
  326. // 解码时的预测
  327. nTemp=(int)((bCharB - bCharC) / 2  +bCharA);
  328. // 预测值小于0,直接赋0
  329. if(nTemp<0)
  330. nTemp = 0;
  331. // 预测值大于255,直接赋值255
  332. else if(nTemp>255)
  333. nTemp = 255;  
  334. else
  335. nTemp = nTemp;
  336. // 预测值+残差
  337. lpDst[j + lLineBytes * (lHeight - 1 - i)] 
  338. = (BYTE)(*lpTemp + (BYTE)nTemp);
  339. lpTemp++;
  340. }
  341. }
  342. }
  343. // 释放内存
  344. delete lpSrc;
  345. lpDst  = NULL;
  346. // 读调色板标志位
  347. file.Read(&bChar, 1);
  348. if (bChar != 0x0C)
  349. {
  350. // 返回NULL。
  351. return FALSE;
  352. }
  353. // 分配内存以读取编码后的象素
  354. lpDst = new BYTE[768];
  355. // 图象中调色板的位置
  356. LPRGBQUAD lpbmc = (LPRGBQUAD)pDib->m_lpvColorTable;
  357. // 读取调色板
  358. if (file.Read(lpDst, 768) != 768)
  359. {
  360. return FALSE;
  361. }
  362. // 给调色板赋值
  363. for (i = 0; i < 256; i++)
  364. {
  365. lpbmc[i].rgbRed   = lpDst[i * 3 + 2];
  366. lpbmc[i].rgbGreen = lpDst[i * 3 + 1];
  367. lpbmc[i].rgbBlue  = lpDst[i * 3];
  368. lpbmc[i].rgbReserved = 0;
  369. }
  370. // 返回值
  371. return TRUE;
  372. }
  373. /*************************************************************************
  374.  *
  375.  * 函数名称:
  376.  *   DIBBITPLANE()
  377.  *
  378.  * 参数:
  379.  *   CDib * pDib        - 指向CDib类的指针
  380.  *   CFile& file        - 要读取的文件
  381.  *
  382.  * 返回值:
  383.  *   BOOL               - 成功返回TRUE
  384.  *
  385.  * 说明:
  386.  *   该函数将制定的图象进行位平面分解
  387.  *
  388.  *************************************************************************/
  389. BOOL WINAPI DIBBITPLANE(CDib *pDib,BYTE bBitNum)
  390. {
  391. // 如果输入的数不符合要求,不进行分解
  392. if(bBitNum <1 || bBitNum >8)
  393. return FALSE;
  394. // 指向源图像的指针
  395. BYTE * lpSrc;
  396. //图象的宽度和高度
  397. LONG    lWidth;
  398. LONG    lHeight;
  399. // 图像每行的字节数
  400. LONG lLineBytes;
  401. // 循环变量
  402. LONG i;
  403. LONG j;
  404. // 中间变量
  405. BYTE bTemp;
  406. BYTE bA;
  407. // 二进制第i位对应的十进制值
  408. BYTE bCount;
  409. //得到图象的宽度和高度
  410. CSize   SizeDim;
  411. SizeDim = pDib->GetDimensions();
  412. lWidth  = SizeDim.cx;
  413. lHeight = SizeDim.cy;
  414. //得到实际的Dib图象存储大小
  415. CSize   SizeRealDim;
  416. SizeRealDim = pDib->GetDibSaveDim();
  417. // 计算图像每行的字节数
  418. lLineBytes = SizeRealDim.cx;
  419. //图像数据的指针
  420. LPBYTE  lpDIBBits = pDib->m_lpImage;
  421. bCount = 1<<(bBitNum - 1);
  422. for (i = 0; i<lHeight; i++)
  423. {
  424. for ( j = 0; j < lWidth; j++)
  425. {
  426. // 指向位图i行j列的指针
  427. lpSrc = (BYTE *)lpDIBBits + j+lLineBytes * (lHeight - 1 - i);
  428. // 对位图按灰度码进行分解
  429. if(bBitNum == 8)
  430. {
  431. // 如果求的是位图8,直接取二值的第8位
  432. bTemp = (*(lpSrc) & bCount) / bCount;
  433. bTemp = bTemp * 255;
  434. }
  435. else
  436. {
  437. // 否则进行异或,求得灰度码
  438. bTemp = (*(lpSrc) & bCount) / bCount;
  439. bA    = bCount * 2;
  440. // 第i+1位图的象素值
  441. bA = (*(lpSrc) & bA) / bA;
  442. // 异或
  443. bTemp = (bTemp ^ bA) * 255;
  444. }
  445. // 更新源图象
  446. *(lpSrc) = bTemp;
  447. }
  448. }
  449. // 返回值
  450. return TRUE;
  451. }