包括读取,保存,格式转换,图片优化等等。其中使用了MS的ijl151库把jpg转换成bmp。
// TestConsole.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <atlimage.h>
#include <fstream>
#include "ijl151.h"
#pragma comment(lib, "ijl151")
using namespace std;
#include <pshpack2.h> //指定补位值为2
struct sunBITMAPFILEHEADER
{
WORD bfType; //位图文件类型,必须为BMP
DWORD bfSize; //位图文件大小,以字节为单位
WORD bfReserved; //位图文件保留字,必须为0
WORD bfReservedEx; //位图文件保留字,必须为0
DWORD bfOffBits; //位图数据的起始位置,相对于位图文件头的偏移量,以字节为单位
};
#include <poppack.h>
int bmpWidth = 0;
int bmpHeight = 0;
int biBitCount= 0;
int lineByte = 0;
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
RGBQUAD* pColorTable= NULL;
unsigned char* pBmpBuf = NULL;
bool readBmp(char *bmpName)
{
FILE *fp=fopen(bmpName,"rb");//二进制读方式打开指定的图像文件
if(fp==0)
{
return 0;
}
fread(&fileHeader,sizeof(char),sizeof(BITMAPFILEHEADER),fp);
//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
fread(&infoHeader,1,sizeof(BITMAPINFOHEADER),fp);
//获取图像宽、高、每像素所占位数等信息
bmpWidth = infoHeader.biWidth;
bmpHeight = infoHeader.biHeight;
biBitCount = infoHeader.biBitCount;
//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
lineByte=(bmpWidth * biBitCount/8+3)/4*4;
//灰度图像有颜色表,且颜色表表项为256
if(biBitCount==8)
{
//申请颜色表所需要的空间,读颜色表进内存
pColorTable = new RGBQUAD[256];
fread(pColorTable,sizeof(RGBQUAD),256,fp);
}
//申请位图数据所需要的空间,读位图数据进内存
pBmpBuf = new unsigned char[lineByte * bmpHeight];
fread(pBmpBuf,1,lineByte * bmpHeight,fp);
//关闭文件
fclose(fp);
return TRUE;
}
void saveBmp()
{
FILE *fp=fopen("e:\testBmp\222.bmp","wb");
if (NULL == fp)
{
cout << "open file error in saveBmp()" << endl;
return;
}
//写文件头进文件
fwrite(&fileHeader,1,sizeof(BITMAPFILEHEADER),fp);
fwrite(&infoHeader,1,sizeof(BITMAPINFOHEADER),fp);
if (NULL != pColorTable)
{
fwrite(&fileHeader,1,sizeof(RGBQUAD)*256,fp);
}
fwrite(pBmpBuf,1,bmpHeight*lineByte,fp);
if (biBitCount == 8)
{
delete []pColorTable;
pColorTable = NULL;
}
delete []pBmpBuf;
pBmpBuf = NULL;
fclose(fp);
}
//直方图均衡化处理
BOOL HistogramEqualize()
{
int i,j;
int ns_r[256],ns_g[256],ns_b[256];
memset(ns_r,0,sizeof(ns_r));
memset(ns_g,0,sizeof(ns_r));
memset(ns_b,0,sizeof(ns_r));
int nHeight= abs(top-bottom);
int nWidth = abs(left-right);
double ps_r[256],ps_g[256],ps_b[256];
double temp_r[256],temp_g[256],temp_b[256];
for (i = 0; i < bmpHeight; i ++) // 对各像素进行灰度转换
{
for (j = 0; j < bmpWidth * 3; j ++)
{
// 对各像素进行灰度统计
unsigned char R = *(pBmpBuf + bmpWidth * 3 * i + j);
ns_r[R]++;
j++;
unsigned char G = *(pBmpBuf + bmpWidth * 3 * i + j);
ns_g[G]++;
j++;
unsigned char B = *(pBmpBuf + bmpWidth * 3 * i + j);
ns_b[B]++;
}
}
for(i=0;i<256;i++) // 计算灰度分布密度
{
ps_r[i] = ns_r[i] / (bmpHeight * bmpWidth * 1.0f);
ps_g[i] = ns_g[i] / (bmpHeight * bmpWidth * 1.0f);
ps_b[i] = ns_b[i] / (bmpHeight * bmpWidth * 1.0f);
}
for(i = 0; i < 256; i++)
{
//计算累计直方图分布
if(i == 0)
{
temp_r[0] = ps_r[0];
temp_g[0] = ps_g[0];
temp_b[0] = ps_b[0];
}
else
{
temp_r[i] = temp_r[i-1] + ps_r[i];
temp_g[i] = temp_g[i-1] + ps_g[i];
temp_b[i] = temp_b[i-1] + ps_b[i];
}
//累计分布取整,nNs_R[]、nNs_G[]、nNs_B[]保存有计算出来的灰度映射关系
ns_r[i] = (int)(255.0f * temp_r[i] + 0.5f);
ns_g[i] = (int)(255.0f * temp_g[i] + 0.5f);
ns_b[i] = (int)(255.0f * temp_b[i] + 0.5f);
}
for (i = 0; i < bmpHeight; i ++)
{
for (j = 0; j < bmpWidth * 3; j ++)
{
//对R分量进行灰度映射(均衡化)
unsigned char R = *(pBmpBuf + bmpWidth * 3 * i + j);
*(pBmpBuf + bmpWidth * 3 * i + j) = ns_r[R];
j++;
//对G分量进行灰度映射(均衡化)
unsigned char G = *(pBmpBuf + bmpWidth * 3 * i + j);
*(pBmpBuf + bmpWidth * 3 * i + j) = ns_g[G];
j++;
//对B分量进行灰度映射(均衡化)
unsigned char B = *(pBmpBuf + bmpWidth * 3 * i + j);
*(pBmpBuf + bmpWidth * 3 * i + j) = ns_b[B];
}
}
return TRUE;
}
void saveIjlBmp(BYTE* lpBuffer,DWORD dwSize)
{
BITMAPFILEHEADER bmfh;
bmfh.bfType=0x4d42;
bmfh.bfSize=54+dwSize;
bmfh.bfReserved1=bmfh.bfReserved2=0;
bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);//=54;
BITMAPINFOHEADER bmih;
bmih.biWidth =bmpWidth;
bmih.biHeight=bmpHeight;
bmih.biPlanes=1;
bmih.biBitCount=24;
bmih.biCompression=BI_RGB;
bmih.biSizeImage=bmpWidth*bmpHeight*3;
bmih.biXPelsPerMeter=0;
bmih.biYPelsPerMeter=0;
bmih.biClrUsed=0;
bmih.biClrImportant=0;
bmih.biSize=sizeof(BITMAPINFOHEADER);
FILE* pf=fopen("e:\testBmp\111.bmp","wb");
fwrite(&bmfh,sizeof(BITMAPFILEHEADER),1,pf);
fwrite(&bmih,sizeof(BITMAPINFOHEADER),1,pf);
fwrite(lpBuffer,dwSize,1,pf);
fclose(pf);
}
BOOL JpgDecode(BYTE *lpSrcBuffer, DWORD dwSrcSize, BYTE *lpDstBuffer, DWORD *dwDstSize, DWORD *lpdwWidth, DWORD *lpdwHeight, DWORD *lpBits, DWORD *dwReserve1)
{
BOOL bres;
IJLERR jerr;
DWORD dwWholeImageSize;
int nPad;
// Allocate the IJL JPEG_CORE_PROPERTIES structure.
JPEG_CORE_PROPERTIES jcprops;
bres = TRUE;
//__try
{
// Initialize the Intel(R) JPEG Library.
jerr = ijlInit2( &jcprops );
if(IJL_OK != jerr)
{
return FALSE;
}
// Get information on the JPEG image
// (i.e., width, height, and channels).
jcprops.JPGFile = NULL;
jcprops.JPGBytes = lpSrcBuffer;
jcprops.JPGSizeBytes = dwSrcSize;
jerr = ijlRead2(&jcprops, IJL_JBUFF_READPARAMS);
if(IJL_OK != jerr)
{
return FALSE;
}
switch(jcprops.JPGChannels)
{
case 1:
{
jcprops.JPGColor = IJL_G;
jcprops.DIBColor = IJL_RGB;
jcprops.DIBChannels = 3;
break;
}
case 3:
{
jcprops.JPGColor = IJL_YCBCR;
jcprops.DIBColor = IJL_BGR;
jcprops.DIBChannels = 3;
break;
}
default:
{
// This catches everything else, but no
// color twist will be performed by the IJL.
jcprops.JPGColor = IJL_OTHER;
jcprops.DIBColor = IJL_OTHER;
jcprops.DIBChannels = jcprops.JPGChannels;
break;
}
}
// Compute size of desired pixel buffer.
nPad = IJL_DIB_PAD_BYTES(jcprops.JPGWidth,3);
dwWholeImageSize = (jcprops.JPGWidth*jcprops.DIBChannels+nPad) * jcprops.JPGHeight;
// Set up the info on the desired DIB properties.
jcprops.DIBWidth = jcprops.JPGWidth;
jcprops.DIBHeight = jcprops.JPGHeight;
// int nPad = IJL_DIB_PAD_BYTES(dwWidth,3)
jcprops.DIBPadBytes = nPad;
jcprops.DIBBytes = lpDstBuffer;
// Now get the actual JPEG image data into the pixel buffer.
jerr = ijlRead2(&jcprops, IJL_JBUFF_READWHOLEIMAGE);
if(IJL_OK != jerr)
{
return FALSE;
}
bmpWidth = jcprops.DIBWidth;
bmpHeight= jcprops.DIBHeight;
} // __try
//__finally
//{
// Clean up the Intel(R) JPEG Library.
ijlFree2(&jcprops);
*lpdwWidth = jcprops.DIBWidth;
*lpdwHeight = jcprops.DIBHeight;
*lpBits = jcprops.DIBChannels * 3;
*dwDstSize = dwWholeImageSize;
//*dwReserve1 = jcprops.DIBPadBytes;
//} // __finally
return bres;
}
int _tmain(int argc, _TCHAR* argv[])
{
int g_cnBufferSize = 6*1024*1024;
BYTE* lpDstBuffer = new BYTE[g_cnBufferSize];
ZeroMemory(lpDstBuffer, g_cnBufferSize);
DWORD dwDstSize = 0,dwWidth = 0,dwHeight = 0,dwBits = 0;
BYTE*g_lpSrcBuffer = new BYTE[g_cnBufferSize];
ZeroMemory(g_lpSrcBuffer, g_cnBufferSize);
BYTE* g_lpSrcBuffer2 = new BYTE[g_cnBufferSize];
ZeroMemory(g_lpSrcBuffer2, g_cnBufferSize);
ifstream ifs;
ifs.open("e:\testBmp\16671.jpg", ios::binary);
ifs.read((char*)g_lpSrcBuffer, g_cnBufferSize);
DWORD g_dwSrcSize = ifs.gcount();
memcpy(g_lpSrcBuffer2, g_lpSrcBuffer, g_cnBufferSize);
DWORD iIndex = 0;
JpgDecode(g_lpSrcBuffer, g_dwSrcSize,lpDstBuffer, &dwDstSize,&dwWidth, &dwHeight, &dwBits, &iIndex);
saveIjlBmp(lpDstBuffer,dwDstSize);
readBmp("e:\testBmp\111.bmp");
if (!HistogramEqualize())
{
cout << "HistogramEqualize error" << endl;
}
saveBmp();
delete []lpDstBuffer;
delete []g_lpSrcBuffer;
delete []g_lpSrcBuffer2;
lpDstBuffer = NULL;
g_lpSrcBuffer = NULL;
g_lpSrcBuffer2= NULL;
int iNum;
cin >> iNum;
return 0;
}