之前说过需要Jpeg代码的可以发邮件联系我,因为最近比较忙,恕不能一一回复。只好在这里将主要的实现代码写下拉,大家需要的话可以自己研究。
一。CDib类实现BMP图像数据解析与Jpeg编码
Dib.h
// Dib.h: interface for the CDib class.
//
//
#if !defined(AFX_DIB_H__FE6314AF_2346_49AE_A383_AA4421DBBF12__INCLUDED_)
#define AFX_DIB_H__FE6314AF_2346_49AE_A383_AA4421DBBF12__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
//戴玉超 2005,12,28
class CDib : public CObject
{
public:
CDib();
virtual ~CDib();
DWORD GetHeight() //得到图像的高度
{
return dwHeight;
}
DWORD GetWidth() //得到图像的宽度
{
return dwWidth;
}
BOOL Is24bit() //判断是否24位bmp图像
{
return m_bit24;
}
private:
DWORD dwHeight; // Height of the map
DWORD dwWidth; // Width of the map
BOOL m_bit24; // is a 24bit map
public:
BOOL RGB2YCbCr(double *rgb,double *yrr); // 实现RGB颜色空间到YCrCb颜色空间的变换
BOOL SetPalette(CDC *pDC); // 设置调色板
BOOL Draw(CDC* pDC, CPoint origin); // 图形绘制
BOOL SaveImage(LPCTSTR lpszFileName); // 保存图像
void LoadImage(LPCTSTR lpszFileName); // 加载图像
public:
BOOL Write32BitData(int nData); // 写入32位数据
BOOL Quant(double *data,int * table,unsigned char * QuantTable); // 根据给定的量化表实现8*8块的量化
BOOL DCT_1D(double *data,double *temp); // 一维DCT
BOOL DCT(double * sourcedata); // 二维DCT
BOOL YCbCr2RGB(double * yrr, double *rgb); // 实现YCrCb颜色空间到RGB颜色空间的变换
BOOL RunLengthCode(int * table, int * RLC_length); // 行程编码
void CDib::ShiftWrite(int huffmanbitnum,int huffmancode); // 按位写入数据
BOOL CDib::WriteSurplus(); // 写最后的位
BOOL SaveAsJpeg(LPCTSTR lpszFileName); //保存为Jpeg图像
BOOL Jpeg(); //完成 Jpeg压缩的全过程
int CDib::WriteData(int nPreDCdata,int * table,int *DChufco,int *DChufsi,int *AChufco,int *AChufsi); //写入数据
BOOL CDib::HuffmanTable(unsigned char *bit,unsigned char*val); //Huffman编码
public:
int HuffmanCode[251],HuffmanLength[251]; //Huffman码字和位
PBYTE pDibData; //数据
CFile file; //文件指针
struct RLC
{
int digit;
int length;
} rlc[64]; //记录8*8的游程数据
unsigned char * m_pDibBits; // pointer to the rgb data;
int m_nPaletteEntries; // 调色板数量
RGBQUAD * m_pPalette; // 调色板
CPalette m_Palette; //
DWORD m_dwDibSize; //文件大小
BITMAPINFOHEADER * m_pBIH; // bmp文件头信息
unsigned char * m_pDib; //指向数据的指针
int EncodeJpeg; //32位的数据缓冲区,用于把不等长的码串串成4个字节以便写入JPEG文件
int surplus; //32位数据缓冲区中剩余没使用的位长,使用数据缓冲区从高位到低位
};
#endif // !defined(AFX_DIB_H__FE6314AF_2346_49AE_A383_AA4421DBBF12__INCLUDED_)
Dib.cpp
// Dib.cpp: implementation of the CDib class.
//
//
#include "stdafx.h"
#include "JpegCompression.h"
#include "Dib.h"
#include "math.h"
#include "iostream.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
const double pi = 3.1415926535;
extern unsigned char LumQuantTable[64]; //亮度量化表
extern unsigned char ChrQuantTable[64]; //色差量化表
extern short ZigzagTable[8*8]; //ZigZag扫描
extern unsigned int LumDCValue[12]; //亮度DC码值
extern unsigned int ChrDCValue[12]; //色差DC码值
extern unsigned char LumACHuffmanVal[162];
extern unsigned char ChrACHuffmanVal[162];
extern unsigned char LumDCHuffmanBit[17]; //亮度DC哈夫曼表的位值
extern unsigned char LumDCHuffmanVal[12]; //亮度DC哈夫曼表的码值
extern unsigned char LumACHuffmanBit[17]; //亮度AC哈夫曼表的位值
extern unsigned char ChrDCHuffmanBit[17];
extern unsigned char ChrDCHuffmanVal[12];
extern unsigned char ChrACHuffmanBit[17];
extern int LumDCHuffmanLen[12];
extern int LumDCHuffmanCode[12];
extern int LumACHuffmanLen[162];
extern int LumACHuffmanCode[162];
extern int ChrDCHuffmanLen[12];
extern int ChrDCHuffmanCode[12];
extern int ChrACHuffmanLen[162];
extern int ChrACHuffmanCode[162];
//
// Construction/Destruction
//
CDib::CDib() //构造函数
{
m_pDib = NULL;
pDibData = NULL;
m_bit24 = 0;
surplus = 32;
EncodeJpeg=0;
}
CDib::~CDib()
{
}
//加载图像
void CDib::LoadImage(LPCTSTR lpszFileName)
{
CFile cf;
LPBYTE pDib = NULL;
DWORD dwDibSize = 0;
try
{
if(!cf.Open(lpszFileName,CFile::modeReadWrite,NULL))
{
throw new CException;
}
dwDibSize = cf.GetLength() - sizeof(BITMAPFILEHEADER);
pDib = (LPBYTE)VirtualAlloc(NULL,dwDibSize,MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
if (pDib == NULL)
{
AfxMessageBox("Error in allocate space!");
}
BITMAPFILEHEADER * pBMPHeader = new BITMAPFILEHEADER;
if(cf.Read(pBMPHeader,sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER))
{
throw new CException;
}
if(pBMPHeader->bfType != 0x4d42)
{
throw new CException;
}
if(cf.ReadHuge(pDib,dwDibSize) != dwDibSize)
{
throw new CException;
}
if(m_pDib != NULL)
{
delete m_pDib;
}
m_pDib = pDib;
m_dwDibSize = dwDibSize;
m_pBIH = (BITMAPINFOHEADER *)pDib;
m_pPalette = (RGBQUAD *)&m_pDib[sizeof(BITMAPINFOHEADER)];
m_nPaletteEntries = 1<< m_pBIH->biBitCount;
if (m_pBIH->biBitCount > 8)
{
m_nPaletteEntries = 0;
}
else if (m_pBIH->biClrUsed != 0)
{
m_nPaletteEntries = m_pBIH->biClrUsed;
}
m_pDibBits = m_pDib + sizeof(BITMAPINFOHEADER) + m_nPaletteEntries * sizeof(RGBQUAD);
if(m_Palette.GetSafeHandle() != NULL)
{
m_Palette.DeleteObject();
}
if (m_nPaletteEntries != 0)
{
LOGPALETTE *pLogPal =
(LOGPALETTE *)new char[sizeof(LOGPALETTE) + m_nPaletteEntries * sizeof(PALETTEENTRY)];
if (pLogPal != NULL)
{
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = m_nPaletteEntries;
for(int i = 0; i < m_nPaletteEntries; i++)
{
pLogPal->palPalEntry[i].peRed = m_pPalette[i].rgbRed;
pLogPal->palPalEntry[i].peGreen = m_pPalette[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue = m_pPalette[i].rgb