|
本程序在EVC4.0+PPC SDK 2003下调试通过。 用Independent JPEG Group发行的JpegLib进行Jpeg图像的读取与保存。 这里只加了一个简单的处理示例——负片。其他的处理可以用与这个类似的方法,有了处理的算法对像素数据进行操作。或者加上鼠标事件的处理来完成绘画功能等等,这里主要是对JPEG文件进行操作的部分。 注意:程序中的CTScreenBuffer并未使用,原因是使用它加载后有段内存没有释放,加上BMP数据本来就比较好处理,所以自己写一段,将BMP数据加上头信息就可以CreateDIBSection了。 保存的默认质量Q=85,大家在使用时可以按照要求改变。
对应的PC版可以在VC下面编译使用,是基本的图象处理程序框架。 详细的使用方法以及JpegLib库
详细的使用方法:
1.系统需求 Microsoft eMbedded Visual C++ 4.0 + Pocket PC 2003 SDK Pocket PC的JpegLib库(在本帖的附件中) 2.背景 Jpeg库的由以下两个文件配置:jconfig.h和jmorecfg.h。一般使用时是不需要改变jmorecfg.h的,但这样可能在Pocket PC中运行时遇到问题,所以这里还是对jmorecfg.h进行了修改。下面将讨论这个修改,以使这个库在Pocket PC上正常使用。不过这里能够下载的附件已经做好了这个修改。
3.将JpegLib引入Pocket PC jmorecfg.h文件含有与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图片 在前面的附件的程序中,已经有这个程序的框架,这里不再赘述。只讲主要的部分。 (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("无法打开文件 '%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]; //这里多申请一行,是因为在模拟器执行时,会出现无法加载的错误,但在机器上正常
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对象的函数 注意这里没有使用CSTScreenBuffer,因为在我实验时,用这个函数加载后,内存资源没有释放,这样每加载一幅图或做一次处理,就会多消耗几兆内存,Pocket PC内存很快就会被耗尽。所以这里将像素数据加上头信息就可以CreateDIBSection了。 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)在绘画函数中,这里是OnDraw(),加入如下代码: 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图片 这里是一种实现方法: void CImageView::SaveImage(const CString &strFileName) { int nQuality=85; //保存质量Q值为85
if(!::WriteRGBBytesIntoJpegFile(strFileName,Width,Height,nQuality,bmpBuffer)) { ::AfxMessageBox(GetJpegWriterError()); } }
其他的更详细内容的看例程中的其他消息处理函数就可以了。
|