?? 復件 jpegdoc.cpp
字號:
// JPEGDoc.cpp : implementation of the CJPEGDoc class
//
#include "stdafx.h"
#include "JPEG.h"
#include "math.h"
#include "JPEGDoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define PI (double)3.1415926535
unsigned char LumQuantTable[64]={ //luminance標準亮度量化表
/* 16,11,10,16,24, 40, 51, 61,
12,12,14,19,26, 58, 60, 55,
14,13,16,24,40, 57, 69, 56,
14,17,22,29,51, 87, 80, 62,
18,22,37,56,68, 109,103,77,
24,35,55,64,81, 104,113,92,
49,64,78,87,103,121,120,101,
72,92,95,98,112,100,103,99
*/
0x8, 0x6, 0x6, 0x7, 0x6, 0x5, 0x8, 0x7,
0x7, 0x7, 0x9, 0x9, 0x8, 0xa, 0xc, 0x14,
0xd, 0xc, 0xb, 0xb, 0xc, 0x19,0x12,0x13,
0xf, 0x14,0x1d,0x1a,0x1f,0x1e,0x1d,0x1a,
0x1c,0x1c,0x20,0x24,0x2e,0x27,0x20,0x22,
0x2c,0x23,0x1c,0x1c,0x28,0x37,0x29,0x2c,
0x30,0x31,0x34,0x34,0x34,0x1f,0x27,0x39,
0x3d,0x38,0x32,0x3c,0x2e,0x33,0x34,0x32
};
unsigned char ChrQuantTable[64]={ //chrominance標準色度量化表
/* 17,18,24,47,99,99,99,99,
18,21,26,66,99,99,99,99,
24,26,56,99,99,99,99,99,
47,66,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99,
99,99,99,99,99,99,99,99
*/
12,13,13,17,16,17,33,18,
18,33,69,46,39,46,69,69,
69,69,69,69,69,69,69,69,
69,69,69,69,69,69,69,69,
69,69,69,69,69,69,69,69,
69,69,69,69,69,69,69,69,
69,69,69,69,69,69,69,69,
69,69,69,69,69,69,69,69
/*
4, 5, 5, 8, 6, 8, 13,10,
10,13,39,26,19,26,49,49,
49,49,49,49,49,49,49,49,
49,49,49,49,49,49,49,49,
49,49,49,49,49,49,49,49,
49,49,49,49,49,49,49,49,
49,49,49,49,49,49,49,49,
49,49,49,49,49,49,49,49
*/
};
unsigned char LumDCHuffmanBit[17]={0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; //亮度DC哈夫曼表的位值
unsigned char LumDCHuffmanVal[12]={0,1,2,3,4,5,6,7,8,9,10,11}; //亮度DC哈夫曼表的碼值
unsigned char LumACHuffmanBit[17]={0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; //亮度AC哈夫曼表的位值
unsigned char LumACHuffmanVal[162]={ //亮度AC哈夫曼表的碼值
0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,
0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,
0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,
0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,
0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,
0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,
0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,
0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,
0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,
0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
0xf9,0xfa
};
unsigned char ChrDCHuffmanBit[17]={0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
unsigned char ChrDCHuffmanVal[12]={0,1,2,3,4,5,6,7,8,9,10,11};
unsigned char ChrACHuffmanBit[17]={0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
unsigned char ChrACHuffmanVal[162]={
0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,
0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,
0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,
0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,
0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,
0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,
0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,
0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,
0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,
0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,
0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
0xf9,0xfa
};
static const short zig[8*8]={ //Z型掃描的順序
0,1,5,6,14,15,27,28,
2,4,7,13,16,26,29,42,
3,8,12,17,25,30,41,43,
9,11,18,24,31,40,44,53,
10,19,23,32,39,45,52,54,
20,22,33,38,46,51,55,60,
21,34,37,47,50,56,59,61,
35,36,48,49,57,58,62,63
};
int ehufco[251],ehufsi[251];
#define WaitCursorBegin() HCURSOR hcURSOR = SetCursor(LoadCursor(NULL, IDC_WAIT))//定義為等待光標
#define WaitCursorEnd() SetCursor(hcURSOR) //定義的等待光標結束,回到默認光標
/////////////////////////////////////////////////////////////////////////////
// CJPEGDoc
IMPLEMENT_DYNCREATE(CJPEGDoc, CDocument)
BEGIN_MESSAGE_MAP(CJPEGDoc, CDocument)
//{{AFX_MSG_MAP(CJPEGDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CJPEGDoc construction/destruction
CJPEGDoc::CJPEGDoc()
{
// TODO: add one-time construction code here
}
CJPEGDoc::~CJPEGDoc()
{
}
BOOL CJPEGDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CJPEGDoc serialization
void CJPEGDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
CDib::CDib()
{
m_pDib=NULL; // 先設置DIB位圖指針為NULL,以便知道位圖是否被裝載
m_bit24=0; // 顏色數初值設為0
surplus=32; //
EncodeJpeg=0; //
for(int i=0;i<64;i++)
table[i]=0;
}
CDib::~CDib()
{
// 如果位圖的指針不為空,將它刪除
if(m_pDib!=NULL)
delete [] m_pDib;
}
//////////////////////////////////////////////////////
//
//
//
//////////////////////////////////////////////////////
BOOL CDib::Load(const char *pszFilename)
{
CFile cf;
// 打開一個名為pszFilename的位圖文件
if(!cf.Open(pszFilename,CFile::modeRead))
return(FALSE);
// 獲得文件的大小,并且減去BITMAPFILEHEADER結構,因為不析算把它留在內存中
DWORD dwDibSize;
dwDibSize=cf.GetLength()-sizeof(BITMAPFILEHEADER);
unsigned char *pDib;
pDib=new unsigned char [dwDibSize];
if(pDib==NULL)
return(FALSE);
BITMAPFILEHEADER BFH;
// 讀取文件的頭和數據
if(cf.Read(&BFH,sizeof(BITMAPFILEHEADER))!=sizeof(BITMAPFILEHEADER)||
BFH.bfType!='MB'||cf.Read(pDib,dwDibSize)!=dwDibSize) //MB為BMP文件的標識符
{
// 如果出現錯誤,釋放DIB位圖的存儲空間
delete [] pDib;
return(FALSE);
}
// 如果類中的位圖指針不為空,釋放它
if(m_pDib!=NULL)
delete m_pDib;
// 將位圖結構的指針和大小賦給成員變量
m_pDib=pDib;
m_dwDibSize=dwDibSize;
m_pBIH=(BITMAPINFOHEADER *)m_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指向實際的DIB位數據
m_pDibBits=&m_pDib[sizeof(BITMAPINFOHEADER)+m_nPaletteEntries*sizeof(RGBQUAD)];
// 如果有一個調色板,釋放它
if(m_Palette.GetSafeHandle()!=NULL)
m_Palette.DeleteObject();
// 創建調色板
if(m_nPaletteEntries!=0)
{
// 分配LOGPALETTE結構的存儲空間
LOGPALETTE *pLogPal=(LOGPALETTE *)new char [sizeof(LOGPALETTE)+
m_nPaletteEntries*sizeof(PALETTEENTRY)];
if(pLogPal!=NULL)
{
// 設置調色板的版本為0x300,保存調色板的數目
pLogPal->palVersion=0x300;
pLogPal->palNumEntries=m_nPaletteEntries;
// 將RGB值放入每個PALETTEENTRY項
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].rgbBlue;
}
// 創建調色板對象并刪除PALETTEENTRY的內存
m_Palette.CreatePalette(pLogPal);
delete [] pLogPal;
}
}
// 如果是24位圖,設置m_bit24=1,并讀入位數據給data數組,不是24位圖,m_bit24=0
if(m_pBIH->biBitCount==8)
{
// AfxMessageBox("此文件不是24位的位圖文件夾!!!");
m_bit24=0;
}
else if(m_pBIH->biBitCount==24)
m_bit24=1;
width=m_pBIH->biWidth; //得到BMP文件的寬度
height=m_pBIH->biHeight; //得到BMP文件的高度
DWORD offset=BFH.bfOffBits; //得到BMP文件的數據偏移量
if(width>1024||height>1024)
{
AfxMessageBox("本軟件目前只能顯示小于等于1024*1024的BMP圖像,請確認圖像!!!");
// exit(0);
return(FALSE);
}
/* CString x;
x.Format("m_bit24=%d",m_bit24);
AfxMessageBox(x);
DWORD filesize=BFH.bfSize;
WORD type=BFH.bfType;
int first=type;
int second=type>>8;
CString st;
st.Format("BMP文件標識符:%c%c 圖像寬度為:%ld 圖像高度為:%ld 偏移量為:%ld 文件大小:%ld字節",first,second,width,height,offset,filesize);
AfxMessageBox(st);
*/
LONG i,j;
if(m_bit24==1)
{
for(i=0;i<1024;i++)
{
data[i]=new RGBData[1024];
for(j=0;j<1024;j++)
{
data[i][j].Blue=0;
data[i][j].Green=0;
data[i][j].Red=0;
}
}
cf.Seek(offset,CFile::begin); //定位至位數據的開始處
for(LONG y=height-1;y>=0;y--)
{
cf.Read(data[y],width*3); //數組data存儲24位色BMP文件的圖像數據
cf.Seek(width%4,CFile::current); //***** 此處很重要,位圖行的字節數等于
} //行除以4乘以3,再加上行除以4的余。
cf.Close();
}
else if(m_bit24==0)
{
for(i=0;i<1024;i++)
{
hdata[i]=new unsigned char [1024];
for(j=0;j<1024;j++)
hdata[i][j]=0;
}
cf.Seek(offset,CFile::begin); //定位至位數據的開始處
// 從最后一行開始讀數據,BMP圖像文件依次從最后一行到第一行進行存儲
for(LONG y=height-1;y>=0;y--)
{
cf.Read(hdata[y],width); //數組hdata存儲灰度圖像的數據
// cf.Seek(width%4,CFile::current); //灰度圖像不用考慮這種情況
}
cf.Close();
}
return(TRUE);
}
/*CFile類
CFile與CArchive類一起支持對MFC對象的串行化,常用的成員函數為:
Open函數 用一個錯誤測試安全地打開一個文件
Close函數 關閉一個文件并刪除該文件
Read函數 從文件的當前位置處讀出一段數據給緩沖區
ReadHuge函數 從文件的當前位置處讀出一段可大于64K的數據給緩沖區
Write函數 將一段數據寫入文件的當前位置處
WriteHuge函數 將一段可大于64K的數據寫入文件的當前位置處
Seek函數 用于定位當前文件指針至任意處
GetLength函數 函數用一獲取文件長(以字節計)
*/
////////////////////////////////////////
//
// BMP文件的存儲
//
////////////////////////////////////////
BOOL CDib::Save(const char *pszFilename)
{
//如果沒有數據,不能保存
if(m_pDib==NULL)
return(FALSE);
CFile cf;
if(!cf.Open(pszFilename,CFile::modeCreate|CFile::modeWrite))
return(FALSE);
BITMAPFILEHEADER BFH;
// 預設BITMAPFILEHEADER結構的所有量全為0
memset(&BFH,0,sizeof(BITMAPFILEHEADER));
BFH.bfType='MB';
BFH.bfSize=sizeof(BITMAPFILEHEADER)+m_dwDibSize;
BFH.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
m_nPaletteEntries*sizeof(RGBQUAD);
// 寫具體數據到指定文件
cf.Write(&BFH,sizeof(BITMAPFILEHEADER));
cf.Write(m_pDib,m_dwDibSize);
return(TRUE);
}
/////////////////////////////////////////
//
// JPEG文件的存儲
//
/////////////////////////////////////////
BOOL CDib::SaveJpeg(const char *pszFilename)
{
WaitCursorBegin(); //顯示等待光標
if(!file.Open(pszFilename,CFile::modeCreate|CFile::modeWrite))
return(FALSE);
unsigned short int filehead=0xd8ff; //JPEG標識符FFD8(16bit)
unsigned char app0[18]={0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46,0x00,0x01,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x00};
unsigned char quant0[5]={0xFF,0xDB,0x00,0x43,0x00}; //量化表標記頭的前幾個字節,后接具體的量化表。
unsigned char quant1[5]={0xFF,0xDB,0x00,0x43,0x01};
unsigned char GreyFrame[13]={0xff,0xc0,0x00,0x0b,0x08,0,0,0,0,0x01,0x01,0x11,0x00};
unsigned char ColorFrame[19]={0xff,0xc0,0x00,0x11,0x08,0,0,0,0,0x03,0x01,0x22,0x00,
0x02,0x11,0x01,0x03,0x11,0x01 }; //真彩色幀開始的標識符
unsigned char LumDchuffman[5]={0xff,0xc4,0x00,0x1f,0x00};
unsigned char LumAchuffman[5]={0xff,0xc4,0x00,0xb5,0x10};
unsigned char ChrDchuffman[5]={0xff,0xc4,0x00,0x1f,0x01};
unsigned char ChrAchuffman[5]={0xff,0xc4,0x00,0xb5,0x11};
unsigned char GreySos[10]={0xff,0xda,0x00,0x08,0x01,0x01,0x00,0x00,0x3f,0x00};//掃描開始(SOS)標記符
unsigned char ColorSos[14]={0xff,0xda,0x00,0x0c,0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00};//掃描開始(SOS)標記符
unsigned char eoi[2]={0xff,0xd9}; //文件結束標識符End of Image
GreyFrame[5]=ColorFrame[5]=height/256;
GreyFrame[6]=ColorFrame[6]=height%256; //圖像的高度
GreyFrame[7]=ColorFrame[7]=width/256;
GreyFrame[8]=ColorFrame[8]=width%256; //圖像的寬度
/////////////////////////////////////////////////////////////////////////////////
file.Write(&filehead,sizeof(unsigned short int)); //寫JPEG標識符FF D8
file.Write(app0,18); //寫app0
file.Write(quant0,5); //寫量化表標記頭前5個字節
file.Write(LumQuantTable,64); //寫量化表的64個字節
if(m_bit24==1)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -