首先Q给Static控gd一个Control变量QID要改了以后才能添加变量,也就是说ID不能为IDC_STATICQ,本例为m_staticTest?br>然后Q用ModifyStyle函数修改Static控g的StyleQ让它可以显C图片:
m_staticTest.ModifyStyle(0, SS_BITMAP | SS_CENTERIMAGE);
最后,是Load文g昄出来Q?/p>
CRect rect;
m_staticTest.GetWindowRect(&rect);
// 下面的方法是按照Static控g的大显CbmpQ如果要安装囄实际大小昄Q用q个ҎLoad囄Q?br>// HBITMAP hBmp = (HBITMAP)::LoadImage(0, _T("D:\\test.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HBITMAP hBmp = (HBITMAP)::LoadImage(0, _T("D:\\test.bmp"), IMAGE_BITMAP, rect.Width(), rect.Height(), LR_LOADFROMFILE);
m_staticTest.SetBitmap(hBmp);
DeleteObject(hBmp);
一、徏立编译环?/p>
所谓徏立编译环境,其实非常单,是把上面提到的Q个文g拯C的项目文件夹下,把libjpeg.libdC的项目中Q然后在你完成压~功能的那个文g里加?include "jpeglib.h"Q需要注意的是,libjpeg.lib是用c语言开发的Q如果要用在你的C++E序里,需要用到extern "C"Q如下:
// TestLibjpeg.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "memory.h"
extern "C" {
#include "jpeglib.h"
}
二、压~步?/p>
Q、申请ƈ初始化jpeg压羃对象Q同时要指定错误处理?/p>
struct jpeg_compress_struct jcs;
// 声明错误处理器,q赋值给jcs.err?br> struct jpeg_error_mgr jem;
jcs.err = jpeg_std_error(&jem);
jpeg_create_compress(&jcs);
Q、指定压~后的图像所存放的目标文Ӟ注意Q目标文件应以二q制模式打开
f=fopen("03.jpg","wb");
if (f==NULL)
{
delete [] data;
delete [] pDataConv;
return 0;
}
jpeg_stdio_dest(&jcs, f);
Q、设|压~参敎ͼ主要参数有图像宽、高、色彩通道敎ͼQ:索引囑փQ3Q其他)Q色彩空_JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色囑փQ,压羃质量{,如下Q?/p>
jcs.image_width = nWidth; // 为图的宽和高Q单位ؓ像素
jcs.image_height = nHeight;
jcs.input_components = 1; // 在此?,表示灰度图, 如果是彩色位图,则ؓ3
jcs.in_color_space = JCS_GRAYSCALE; //JCS_GRAYSCALE表示灰度图,JCS_RGB表示彩色囑փ
jpeg_set_defaults(&jcs);
jpeg_set_quality (&jcs, 80, true);
需要注意的是,jpeg_set_defaults函数一定要{设|好囑փ宽、高、色彩通道数计色彩I间四个参数后才能调用,因ؓq个函数要用到这四个|调用jpeg_set_defaults函数后,jpeglib库采用默认的讄对图像进行压~,如果需要改变设|,如压~质量,调用q个函数后,可以调用其它讄函数Q如jpeg_set_quality函数。其实图像压~时有好多参数可以设|,但大部分我们都用不着讄Q只需调用jpeg_set_defaults函数gؓ默认值即可?/p>
Q、上面的工作准备完成后,可以压~了Q压~过E非常简单,首先调用jpeg_start_compressQ然后可以对每一行进行压~,也可以对若干行进行压~,甚至可以Ҏ个的囑փq行一ơ压~,压羃完成后,记得要调用jpeg_finish_compress函数Q如下:
jpeg_start_compress(&jcs, TRUE);
JSAMPROW row_pointer[1]; // 一行位?br> int row_stride; // 每一行的字节?
row_stride = jcs.image_width; // 如果不是索引?此处需要乘?
// Ҏ一行进行压~?br> while (jcs.next_scanline < jcs.image_height) {
row_pointer[0] = & pDataConv[jcs.next_scanline * row_stride];
jpeg_write_scanlines(&jcs, row_pointer, 1);
}
jpeg_finish_compress(&jcs);
Q、最后就是释攑֎~工作过E中所甌的资源了Q主要就是jpeg压羃对象Q由于在本例中我是直接用的局部变量,所以只需调用jpeg_destroy_compressq个函数卛_Q如下:
jpeg_destroy_compress(&jcs);
三、解压羃步骤
解压~步骤与压羃步骤非常怼Q只是解压羃对象为jpeg_decompress_structcdQ步骤如下:
1、声明ƈ初始化解压羃对象Q同时制定错误信息管理器
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
2、打开jpg囑փ文gQƈ指定压羃对象的源文g
FILE *f = fopen(strSourceFileName,"rb");
if (f==NULL)
{
printf("Open file error!\n");
return;
}
//
jpeg_stdio_src(&cinfo, f);
3、读取图像信?br> jpeg_read_header(&cinfo, TRUE);
4、根据图像信息申请一个图像缓冲区
data = new BYTE cinfo.image_width*cinfo.image_height*cinfo.num_components];
5、开始解压羃
jpeg_start_decompress(&cinfo);
JSAMPROW row_pointer[1];
while (cinfo.output_scanline < cinfo.output_height)
{
row_pointer[0] = &data[(cinfo.output_height - cinfo.output_scanline-1)*cinfo.image_width*cinfo.num_components];
jpeg_read_scanlines(&cinfo,row_pointer ,
1);
}
jpeg_finish_decompress(&cinfo);
6、释放资?br> jpeg_destroy_decompress(&cinfo);
fclose(f);
好了Q利用IJG JPEG Libraryq行囑փ压羃׃l到q里Q希望对大家有所帮助Q实例代码已l实C囑փ的压~和解压~的全部功能
用Independent JPEG Group发行的JpegLibq行Jpeg囑փ的读取与保存?br> q里只加了一个简单的处理CZ——负片。其他的处理可以用与q个cM的方法,有了处理的算法对像素数据q行操作。或者加上鼠标事件的处理来完成绘d能等{,q里主要是对JPEG文gq行操作的部分?br> 注意Q程序中的CTScreenBufferq未使用Q原因是使用它加载后有段内存没有释放Q加上BMP数据本来比较好处理Q所以自己写一D,BMP数据加上头信息就可以CreateDIBSection了?br> 保存的默认质量Q=85Q大家在使用时可以按照要求改变?/p>
MacintoshM 2006-05-14, 11:38
详细的用方法:
1.pȝ需?br> Microsoft eMbedded Visual C++ 4.0 + Pocket PC 2003 SDK
Pocket PC的JpegLib?在本帖的附g?
2.背景
Jpeg库的׃下两个文仉|?jconfig.h和jmorecfg.h。一般用时是不需要改变jmorecfg.h的,但这样可能在Pocket PC中运行时遇到问题Q所以这里还是对jmorecfg.hq行了修攏V下面将讨论q个修改Q以使这个库在Pocket PC上正怋用。不q这里能够下载的附g已经做好了这个修攏V?br>
3.JpegLib引入Pocket PC
jmorecfg.h文g含有与Embedded Visual Studio冲突的定?需要做以下修改:
(1)代码:
#ifndef XMD_H
typedef long INT32;
#endif
改ؓ:
#if !defined(XMD_H) && !defined(_BASETSD_H_)
typedef long INT32;
#endif
(2)代码:
#ifdef NEED_FAR_POINTERS
#define FAR far
#else
#define FAR
#endif
用下面的ifdef代替
#ifndef FAR
....
#endif
4.使用JpegLib加蝲Jpeg囄
在前面的附g的程序中Q已l有q个E序的框Ӟq里不再赘述。只讲主要的部分?br> (1)加蝲Jpeg囄的函敎ͼ
void CImageView::LoadImage(const CString &strFileName)
{
FILE * pFile;
struct jpeg_error_mgr jerr;
struct jpeg_decompress_struct cinfo;
int i,start;
start=0;
if ((pFile = _tfopen(strFileName, _T("rb")) == NULL) {
CString strError;
strError.Format(_T("无法打开文g '%s'", strFileName);
AfxMessageBox(strError);
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, pFile);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
nRowSize = cinfo.output_width * cinfo.output_components;
Width=cinfo.output_width;
Height=cinfo.output_height;
if(bmpLoaded)
{
delete bmpBuffer;
}
bmpBuffer=new BYTE[(Height+1)*Width*3]; //q里多申请一行,是因为在模拟器执行时Q会出现无法加蝲的错误,但在机器上正?br>
bmpLoaded=TRUE;
pBuffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, nRowSize, 1);
while(cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines(&cinfo, pBuffer, 1);
start=nRowSize*cinfo.output_scanline;
for(i=0;i<nRowSize;i++)
{
bmpBuffer[start+i]=pBuffer[0];
}
}
CreateBitmap();
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(pFile);
}
(2)加载后的像素数据徏立一个HBITMAP对象的函?br> 注意q里没有使用CSTScreenBuffer,因ؓ在我实验Ӟ用这个函数加载后Q内存资源没有释放,q样每加载一q图或做一ơ处理,׃多消耗几兆内?Pocket PC内存很快׃被耗尽。所以这里将像素数据加上头信息就可以CreateDIBSection了?br> void CImageView::CreateBitmap()
{
int m_nCorrectedWidth,m_nWidth,m_nHeight;
m_nCorrectedWidth = ( ( Width + 3 ) / 4 ) * 4;
m_nWidth = Width;
m_nHeight = Height;
DIBINFO dibInfo;
BGRColor *m_pBuffer;
dibInfo.bmiHeader.biBitCount = 24;
dibInfo.bmiHeader.biClrImportant = 0;
dibInfo.bmiHeader.biClrUsed = 0;
dibInfo.bmiHeader.biCompression = 0;
dibInfo.bmiHeader.biHeight = m_nHeight;
dibInfo.bmiHeader.biPlanes = 1;
dibInfo.bmiHeader.biSize = 40;
dibInfo.bmiHeader.biSizeImage = m_nCorrectedWidth*m_nHeight*3;
dibInfo.bmiHeader.biWidth = m_nCorrectedWidth;
dibInfo.bmiHeader.biXPelsPerMeter = 3780;
dibInfo.bmiHeader.biYPelsPerMeter = 3780;
dibInfo.bmiColors[0].rgbBlue = 0;
dibInfo.bmiColors[0].rgbGreen = 0;
dibInfo.bmiColors[0].rgbRed = 0;
dibInfo.bmiColors[0].rgbReserved = 0;
HDC hDC = ::GetDC(NULL);
if(m_hBitmap)
{
:eleteObject(m_hBitmap);
m_hBitmap=0;
}
m_hBitmap = CreateDIBSection(hDC, (const BITMAPINFO*)dibInfo, DIB_RGB_COLORS, (void**)&m_pBuffer, NULL, 0);
::ReleaseDC(NULL,hDC);
int nPosition = 0;
int nDataPosition = 0;
for (int y=0; y<Height; y++) {
nPosition = m_nCorrectedWidth*(m_nHeight-y-1);
nDataPosition = Width*3*y;
for (int x=0; x<Width; x++) {
m_pBuffer[nPosition].m_R = bmpBuffer[nDataPosition++];
m_pBuffer[nPosition].m_G = bmpBuffer[nDataPosition++];
m_pBuffer[nPosition].m_B = bmpBuffer[nDataPosition++];
nPosition++;
}
}
}
(3)在绘dCQ这里是OnDraw()Q加入如下代码:
if (m_hBitmap)
{
CDC memDc;
VERIFY(memDc.CreateCompatibleDC(&dc));
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(memDc.GetSafeHdc(), m_hBitmap);
VERIFY(dc.BitBlt(-LeftTop.x, -LeftTop.y, Width, Height, &memDc, 0, 0, SRCCOPY));
::SelectObject(memDc.GetSafeHdc(), hOldBitmap);
VERIFY( memDc.DeleteDC() );
}
5.使用JpegLib库保存Jpeg囄
q里是一U实现方法:
void CImageView::SaveImage(const CString &strFileName)
{
int nQuality=85; //保存质量Qgؓ85
if(!::WriteRGBBytesIntoJpegFile(strFileName,Width,Height,nQuality,bmpBuffer))
{
::AfxMessageBox(GetJpegWriterError());
}
}
其他的更详细内容的看例程中的其他消息处理函数可以了?/span>
1.问题的由?br> Jpeg囄在图像处理领域已l用的相当广泛了。但在编E领域,其是嵌入式~程领域使用的还不是很广。主要的原因是Jpeg的数据结构和法q较bmp复杂Q非囑փ法的专业h士,通常是无法理解这些的。(我有个同事,他曾l花了半个月Q研I过Jpeg的原理,qؓ此在team内部丑֊了一个讲座,讲了有一个小Ӟ令众人对之Ԓ慕万分,但他却说Q仅得皮毛,未得要害。从此我对Jpeg的原理近而远之。)
q来Q因工作需要,要在winceq_下,为程序添加Jpeg支持。一般来_此类问题最Ҏ的解x案是使用OS提供的相兛_Q毕竟现在不支持Jpeg的OS几乎没有。但在wince下这里出了个问题。目前绝大多数的wince讑֤是wince 4.X?.X的,不过y在图像处理这块,5.X?.X的方法是不一L?.X提供的方法在IMGDECMP.DLL中,?.X提供的方法在Imaging.DLL中,而且不止是链接库不同Q库的接口也是完全两L。因此,如果软g采用OS提供的相兛_的话Q在q里p准备两套接口Q非常的ȝ。况且,我们的Y件不仅要在wince下部|Ԍ来q打推q到其他的^収ͼ因此q种Ҏ昄是不太好的?br> q时我想CJpegLib。JpegLib是Independent JPEG Group——一个非Jpeg官方l织推出的Jpeg库。这是个开源免费的库,支持多种q_和编译器Q你可以?a target=_blank>www.ijg.org中获得它的最新版本。在PC上它的效率比不了intel的Jpeg库,因ؓ后者进行了汇编优化。但在wince上应该和pȝ库的效率相当。事实上如果查看pȝ的版权信息的话,Microsoft在wince中也使用了这个库。RISC的芯片也基本没有汇编优化的问题?br> |上的中文资料以以下两篇文章最?br> http://mobile.winfans.net/ccs/forums/516/PrintPost.aspx Q文献AQ?br> http://blog.csdn.net/zhao3728/archive/2007/08/22/1754877.aspx Q文献BQ?br> 所以我的这文章主要作遗之用?br>
2.~译JpegLib?br> 文献A和B都是使用现成的JpegLib库,q样的库只在特定的^C才能用,完全体现不出JpegLib的优ѝ所以掌握编译JpegLib库的ҎQ是很有必要的?br> JpegLib库源代码的组?br> 1Qmakefile。JpegLib库中有很多文件名为makefile的文件。它的后~名表C它所用于的^台或用途。随便打开一个,可以看到JpegLib库源代码的组成?br> 2Qmakefile中LIBSOURCES变量所代表的文件是JpegLib的核心算法部分?br> 3Qmakefile中SYSDEPSOURCES变量所代表的文件是JpegLib中负责内存分配的部分。这部分是系l相关的Q所以根据需要选用一个就行了?br> 4Qmakefile中APPSOURCES变量所代表的文件是JpegLib中提供诸如命令行压羃Jpeg之类的功能的部分Q实际上是一些小工具。不q在~译JpegLib库时Q不要将之添加到工程中?br> 5Qmakefile中INCLUDES变量所代表的文件是源代码中用到的头文g。不是所有的头文仉被核心算法部分用到Q因此有些头文g在编译JpegLib库时Q是不必要的Q当然将之添加到工程中也不会出错?br> 6Qmakefile中DOCS变量所代表的文件是一些文档、测试用例之cȝ东西。其中最有用的是example.cQ文献A和B的示例最重要的部分,来自这里?br> 7Qjconfig。JpegLib库中q有很多和makefilecM的jconfigQ这是针对不同^台的cd声明。在使用Ӟ应根据需要,适当的jconfig文g的后~名改为h?br> 以上q些内容更详l的说明见JpegLib库的文档Q以?br> http://blog.csdn.net/axlrosek/archive/2007/03/29/1545496.aspx
VC:不同版本的VC、EVC都差不多Q参照文献A的步骤修改相xӞ然后新徏一个空工程Q然后打开JpegLib中的makefile.vc文g,?Q和3Q?Q?Q中的文件添加到工程中。将生成文g的类型定为libp了。此外,q需要针对调用的情况选择适当的运行时库,否则可能会出LNK2005错误?br>
3.使用JpegLib?br> JpegLib库的使用参照文献A和BQ以及example.c可以了。但文献A的示例是有问题的?br> bmpBuffer[start+i]=pBuffer[0];
应改?br> bmpBuffer[start+i]=pBuffer[0][i];
jpeg_read_scanlines(&cinfo, pBuffer, 1)执行之后Q?span style="FONT-WEIGHT: bold">扫描U的内容被放到pBuffer[0]Q而不是pBuffer?/span>Q用memcpy扫描线的内容{Ud其他的缓冲区p了,无需用@环语句?br>
4.输入的Jpeg的处?br> 上面的示例处理的都是从文件读入的JpegQ在现实中,q存在流输入的Jpeg。在很多PC游戏中,E序的数据都被集中v来放入一个大文g之中Q最典型的当属暴雪的mpq文g。当q些文g被读入内存时Q就形成了字节流形式的文件。将之存Z时文Ӟ然后再用之前的方法,昄是笨Ҏ。这时可以采用jpeg_arr_src函数来替换jpeg_stdio_src函数?br> q一点还可以参考以下文档,不过该文针对的好像是旧版本,使用时要注意?br> http://blog.china.com/u/060803/5544/200608/15355.html