📄 coding.cpp
字号:
// ************************************************************************
// 文件名:Coding.cpp
//
// 图像编码压缩、解压缩函数库:
//
// LoadJPG() - 装载JPEG图象(解压用)
// SaveJPG() - 保存JPEG图象(压缩用)
// SaveBMP() - 保存BMP图象到文件(解压用)
// LoadBMP() - 从文件装载BMP图象(压缩用)
// DIBToPCX() - 将DIB保存为PCX文件
// PCXToDIB() - 读取PCX文件
// Huffman() - 哈夫曼编码
// Shannon_Fannon() - 仙农-弗诺编码
// DIBToGIF() - 将DIB保存到GIF文件
// LZW_Encode() - 对图象进行LZW编码
// OutputCode() - 为GIF-LZW算法输出一个编码
// GIFToDIB() - 读取GIF到DIB
// LZW_Decode() - 对LZW编码进行解码
// ReadGIF() - 读取指定GIF文件中的图像编码
//
//*************************************************************************
#include "stdafx.h"
#include "dip_system.h"
#include "Coding.h"
#include "JPEGfile.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Dib文件头标志(字符串"BM",写DIB时用到该常数)
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
/////////////////////////////////////////////////////////////////////////////
// CCoding
CCoding::CCoding()
{
}
CCoding::~CCoding()
{
}
BEGIN_MESSAGE_MAP(CCoding, CWnd)
//{{AFX_MSG_MAP(CCoding)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCoding message handlers
/*************************************************************************
*
* 函数名称:
* SaveJPG()
*
* 参数:
* CDIP_SystemDoc* pDoc - 文档指针
* CString fileName - 保存文件路径
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图象进行JPEG编码压缩
*
************************************************************************/
void CCoding::SaveJPG(CDIP_SystemDoc* pDoc, CString fileName)
{
// 临时缓存
BYTE *buf;
buf = NULL;
// 获取文档尺寸
CSize size = pDoc->GetDocSize();
UINT width = size.cx;
UINT height = size.cy;
buf = LoadBMP(pDoc->m_strCurrentFile, &width, &height);
// 压缩位图到JPEG文件,函数的最后参数标明压缩质量(1 - 100)
JpegFile::RGBToJpegFile(fileName, buf, width, height, TRUE, 50);
}
/*************************************************************************
*
* 函数名称:
* LoadJPG()
*
* 参数:
* HDIB hDIB - DIB句柄
* CDIP_SystemDoc* pDoc - 文档指针
* CString fileName - 装载文件路径
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数对图象进行JPEG编码解压缩
*
************************************************************************/
void CCoding::LoadJPG(HDIB hDIB, CDIP_SystemDoc* pDoc, CString fileName)
{
// 临时缓存
BYTE *buf;
buf = NULL;
// JPEG图象高度、宽度
UINT width = 0;
UINT height = 0;
// 读到临时缓存
buf = JpegFile::JpegFileToRGB(fileName, &width, &height);
// 交换红绿象素
JpegFile::BGRFromRGB(buf, width, height);
// 垂直翻转显示
JpegFile::VertFlipBuf(buf, width * 3, height);
// 保存解压后的数据到临时位图文件
SaveBMP("Temp.bmp", buf, width, height);
// 装载临时位图文件
pDoc->OnOpenDocument("Temp.bmp");
// 删除临时文件
::DeleteFile("Temp.bmp");
// 初始化标记为FALSE
pDoc->SetModifiedFlag(TRUE);
}
/*************************************************************************
*
* 函数名称:
* SaveBMP()
*
* 参数:
* CString fileName - 保存文件路径
* BYTE* buf - BGR缓存
* UINT width - 宽度
* UINT height - 高度
*
* 返回值:
* void - 无返回值
*
* 说明:
* 该函数把BMP图象从内存保存到文件
*
************************************************************************/
void CCoding::SaveBMP(CString fileName, BYTE * buf, UINT width, UINT height)
{
// 位图文件头
char m1 = 'B';
char m2 = 'M';
short res1 = 0;
short res2 = 0;
long pixoff = 54;
// 宽度
DWORD widthDW = WIDTHBYTES(width * 24);
// 文件长度
long bmfsize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + widthDW * height;
// 文件指针
long byteswritten = 0;
// 位图信息头
BITMAPINFOHEADER header;
header.biSize = 40; // 头大小
header.biWidth = width;
header.biHeight = height;
header.biPlanes = 1;
header.biBitCount = 24; // 24位
header.biCompression = BI_RGB; // 非压缩
header.biSizeImage = 0;
header.biXPelsPerMeter = 0;
header.biYPelsPerMeter = 0;
header.biClrUsed = 0;
header.biClrImportant = 0;
// 二进制写方式打开文件
FILE *fp;
fp = fopen(fileName, "wb");
// 写文件头
fwrite((BYTE*)&(m1), 1, 1, fp);
byteswritten += 1;
fwrite((BYTE*)&(m2), 1, 1, fp);
byteswritten += 1;
fwrite((long*)&(bmfsize), 4, 1, fp);
byteswritten += 4;
fwrite((int*)&(res1), 2, 1, fp);
byteswritten += 2;
fwrite((int*)&(res2), 2, 1, fp);
byteswritten += 2;
fwrite((long*)&(pixoff), 4, 1, fp);
byteswritten += 4;
// 写位图信息头
fwrite((BITMAPINFOHEADER *)&header, sizeof(BITMAPINFOHEADER), 1, fp);
// 移动指针
byteswritten += sizeof(BITMAPINFOHEADER);
// 临时变量
long row = 0;
long rowidx;
long row_size;
long rc;
// 行大小
row_size = header.biWidth * 3;
// 保存位图阵列
for (row = 0; row < header.biHeight; row++)
{
rowidx = (long unsigned)row * row_size;
// 写一行
rc = fwrite((void *)(buf + rowidx), row_size, 1, fp);
if (rc != 1)
break;
byteswritten += row_size;
for (DWORD count = row_size; count < widthDW; count++)
{
char dummy = 0;
fwrite(&dummy, 1, 1, fp);
byteswritten++;
}
}
// 关闭文件
fclose(fp);
}
/*************************************************************************
*
* 函数名称:
* LoadBMP()
*
* 参数:
* CString fileName - 装载路径
* UINT width - 宽度
* UINT height - 高度
*
* 返回值:
* BYTE* - 读取图象缓存首地址
*
* 说明:
* 该函数把BMP图象从文件装载到内存
*
************************************************************************/
BYTE* CCoding::LoadBMP(CString fileName, UINT *width, UINT *height)
{
BITMAP inBM;
BYTE m1,m2;
long filesize;
short res1,res2;
long pixoff;
long bmisize;
long compression;
unsigned long sizeimage;
long xscale, yscale;
long colors;
long impcol;
// 初始化
BYTE *outBuf = NULL;
*width = 0;
*height = 0;
DWORD m_bytesRead = 0;
// 以二进制读方式打开文件
FILE *fp;
fp = fopen(fileName, "rb");
// 读取文件
if (fp != NULL)
{
// 检验BMP标志
long rc;
rc = fread((BYTE*)&(m1), 1, 1,fp);
m_bytesRead += 1;
if (rc == -1)
{
fclose(fp);
return NULL;
}
rc = fread((BYTE*)&(m2), 1, 1,fp);
m_bytesRead += 1;
if ((m1!='B') || (m2!='M'))
{
fclose(fp);
return NULL;
}
// 读文件头信息
rc = fread((long*)&(filesize), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((int*)&(res1), 2, 1, fp);
m_bytesRead += 2;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((int*)&(res2), 2, 1, fp);
m_bytesRead += 2;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(pixoff), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(bmisize), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(inBM.bmWidth), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(inBM.bmHeight), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((int*)&(inBM.bmPlanes), 2, 1, fp);
m_bytesRead += 2;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((int*)&(inBM.bmBitsPixel), 2, 1, fp);
m_bytesRead += 2;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(compression), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(sizeimage), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(xscale), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(yscale), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(colors), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
rc = fread((long*)&(impcol), 4, 1, fp);
m_bytesRead += 4;
if (rc != 1)
{
fclose(fp);
return NULL;
}
// 对RLE文件不做处理
if (compression != BI_RGB)
{
fclose(fp);
return NULL;
}
if (colors == 0)
colors = 1 << inBM.bmBitsPixel;
// 读取颜色表
RGBQUAD *colormap = NULL;
if ((long)m_bytesRead > pixoff)
{
fclose(fp);
delete [] colormap;
fclose(fp);
return NULL;
}
while ((long)m_bytesRead < pixoff)
{
char dummy;
fread(&dummy,1,1,fp);
m_bytesRead++;
}
int w = inBM.bmWidth;
int h = inBM.bmHeight;
// 设置输出参数
*width = w;
*height = h;
long row_size = w * 3;
long bufsize = (long)w * 3 * (long)h;
// 分配内存
outBuf = (BYTE*) new BYTE [bufsize];
if (outBuf != NULL)
{
long row = 0;
long rowOffset = 0;
// 读取点阵数据
for (row = inBM.bmHeight - 1; row >= 0;row--)
{
rowOffset = (long unsigned)row*row_size;
if (inBM.bmBitsPixel == 24)
{
for (int col = 0; col < w; col++)
{
long offset = col * 3;
char pixel[3];
if (fread((void *)(pixel), 1, 3, fp) == 3)
{
//交换R、B信息
*(outBuf + rowOffset + offset + 0) = pixel[2]; // r
*(outBuf + rowOffset + offset + 1) = pixel[1]; // g
*(outBuf + rowOffset + offset + 2) = pixel[0]; // b
}
}
m_bytesRead += row_size;
while ((m_bytesRead - pixoff) & 3)
{
char dummy;
if (fread(&dummy, 1, 1, fp) != 1)
{
delete [] outBuf;
fclose(fp);
return NULL;
}
m_bytesRead++;
}
}
}
}
if (colormap)
delete [] colormap;
fclose(fp);
}
return outBuf;
}
/*************************************************************************
*
* 函数名称:
* DIBToPCX()
*
* 参数:
* HDIB hDIB - DIB句柄
* CString strPath - 要保存的文件路径
*
* 返回值:
* BOOL - 成功返回True,否则返回False。
*
* 说明:
* 该函数将DIB保存为PCX文件。
*
*************************************************************************/
BOOL CCoding::DIBToPCX(HDIB hDIB, CString strPath)
{
// 循环变量
LONG i;
LONG j;
LONG k;
// 中间变量
BYTE bChar1;
BYTE bChar2;
// 指向源图像象素的指针
BYTE* lpSrc;
// 指向编码后图像数据的指针
BYTE* lpDst;
// 重复像素计数
int iCount;
// 调整顺序:B、G、R
int RGB[3] = {2, 1, 0};
// 打开文件
CFile file;
file.Open(strPath, CFile::modeCreate | CFile::modeReadWrite);
// 缓冲区已使用的字节数
DWORD dwBuffUsed;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -