一种使用GDI+对图片尺寸和质量的压缩方法
生活随笔
收集整理的這篇文章主要介紹了
一种使用GDI+对图片尺寸和质量的压缩方法
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
? ? ? ? 今天同事向我詢(xún)問(wèn)圖片壓縮的算法,我想起大概兩三年前做過(guò)的一個(gè)項(xiàng)目。其中包含了尺寸和質(zhì)量?jī)煞N壓縮算法,并且支持JPEG、bmp、PNG等格式。今天把這段邏輯貼出來(lái),供大家參考。(轉(zhuǎn)載請(qǐng)指明來(lái)源于breaksoftware的CSDN博客)
- 尺寸壓縮
bool CompressImagePixel( const WCHAR* pszOriFilePath, const WCHAR* pszDestFilePah, UINT ulNewHeigth, UINT ulNewWidth )
{// Initialize GDI+.GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;Status stat = GenericError;stat = GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL );if ( Ok != stat ) {return false;}// 重置狀態(tài)stat = GenericError;// Get an image from the disk.Image* pImage = new Image(pszOriFilePath);do {if ( NULL == pImage ) {break;}// 獲取長(zhǎng)寬UINT unOriHeight = pImage->GetHeight();UINT unOriWidth = pImage->GetWidth();do {CLSID encoderClsid;if ( unOriWidth < 1 || unOriHeight < 1 ) {break;}// Get the CLSID of the JPEG encoder.if ( !GetEncoderClsid(L"image/jpeg", &encoderClsid) ) {break;}REAL fSrcX = 0.0f;REAL fSrcY = 0.0f;REAL fSrcWidth = (REAL) unOriWidth;REAL fSrcHeight = (REAL) unOriHeight ;RectF RectDest( 0.0f, 0.0f, (REAL)ulNewWidth, (REAL)ulNewHeigth);Bitmap* pTempBitmap = new Bitmap( ulNewWidth, ulNewHeigth );Graphics* graphics = NULL;do {if ( !pTempBitmap ) {break;}graphics = Graphics::FromImage( pTempBitmap );if ( !graphics ) {break;}stat = graphics->SetInterpolationMode(Gdiplus::InterpolationModeHighQuality);if ( Ok != stat ) {break;}stat = graphics->SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);if ( Ok != stat ) {break;}stat = graphics->DrawImage( pImage, RectDest, fSrcX, fSrcY, fSrcWidth, fSrcHeight,UnitPixel, NULL, NULL, NULL);if ( Ok != stat ) {break;}stat = pTempBitmap->Save( pszDestFilePah, &encoderClsid, NULL );if ( Ok != stat ) {break;}} while(0);if ( NULL != graphics ) {delete graphics;graphics = NULL;}if ( NULL != pTempBitmap ) {delete pTempBitmap;pTempBitmap = NULL;}} while(0);} while (0);if ( pImage ) {delete pImage;pImage = NULL;}GdiplusShutdown(gdiplusToken);return ( ( Ok == stat ) ? true : false );
} - 質(zhì)量壓縮
bool CompressImageQuality( const WCHAR* pszOriFilePath, const WCHAR* pszDestFilePah,ULONG quality )
{// copy from http://msdn.microsoft.com/en-us/library/ms533844(v=VS.85).aspx// Initialize GDI+.GdiplusStartupInput gdiplusStartupInput;ULONG_PTR gdiplusToken;Status stat = GenericError;stat = GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL );if ( Ok != stat ) {return false;}// 重置狀態(tài)stat = GenericError;// Get an image from the disk.Image* pImage = new Image(pszOriFilePath);do {if ( NULL == pImage ) {break;}// 獲取長(zhǎng)寬UINT ulHeight = pImage->GetHeight();UINT ulWidth = pImage->GetWidth();if ( ulWidth < 1 || ulHeight < 1 ) {break;}// Get the CLSID of the JPEG encoder.CLSID encoderClsid;if ( !GetEncoderClsid(L"image/jpeg", &encoderClsid) ) {break;}// The one EncoderParameter object has an array of values.// In this case, there is only one value (of type ULONG)// in the array. We will let this value vary from 0 to 100.EncoderParameters encoderParameters;encoderParameters.Count = 1;encoderParameters.Parameter[0].Guid = EncoderQuality;encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;encoderParameters.Parameter[0].NumberOfValues = 1;encoderParameters.Parameter[0].Value = &quality;stat = pImage->Save(pszDestFilePah, &encoderClsid, &encoderParameters);} while(0);if ( pImage ) {delete pImage;pImage = NULL;}GdiplusShutdown(gdiplusToken);return ( ( stat == Ok ) ? true : false );
}? ? ? ? 這兩個(gè)算法,都關(guān)聯(lián)了一個(gè)函數(shù)GetEncoderClsid,其實(shí)現(xiàn)是: #include <Windows.h>
#include <GdiPlus.h>
#pragma comment( lib, "GdiPlus.lib" )
using namespace Gdiplus;bool GetEncoderClsid(const WCHAR* pszFormat, CLSID* pClsid)
{UINT unNum = 0; // number of image encodersUINT unSize = 0; // size of the image encoder array in bytesImageCodecInfo* pImageCodecInfo = NULL;// How many encoders are there?// How big (in bytes) is the array of all ImageCodecInfo objects?GetImageEncodersSize( &unNum, &unSize );if ( 0 == unSize ) {return false; // Failure}// Create a buffer large enough to hold the array of ImageCodecInfo// objects that will be returned by GetImageEncoders.pImageCodecInfo = (ImageCodecInfo*)( malloc(unSize) );if ( !pImageCodecInfo ) {return false; // Failure}// GetImageEncoders creates an array of ImageCodecInfo objects// and copies that array into a previously allocated buffer. // The third argument, imageCodecInfos, is a pointer to that buffer. GetImageEncoders( unNum, unSize, pImageCodecInfo );for ( UINT j = 0; j < unNum; ++j ) {if ( wcscmp( pImageCodecInfo[j].MimeType, pszFormat ) == 0 ) {*pClsid = pImageCodecInfo[j].Clsid;free(pImageCodecInfo);pImageCodecInfo = NULL;return true; // Success} }free( pImageCodecInfo );pImageCodecInfo = NULL;return false; // Failure
}? ? ? ? 在我的測(cè)試代碼中,文件名中包含A的為源文件,文件名中包含B的是尺寸壓縮算法得到的文件,文件名中包含C的是質(zhì)量壓縮(尺寸不變)算法得到的文件。測(cè)試代碼是 int _tmain(int argc, _TCHAR* argv[])
{CompressImagePixel( L"1A.jpg", L"1B.jpg", 100, 100 );CompressImageQuality( L"1A.jpg", L"1C.jpg", 30 );CompressImagePixel( L"2A.png", L"2B.jpg", 100, 100 );CompressImageQuality( L"2A.png", L"2C.jpg", 30 );CompressImagePixel( L"3A.bmp", L"3B.jpg", 100, 100 );CompressImageQuality( L"3A.bmp", L"3C.jpg", 30 );return 0;
}? ? ? ? 其壓縮結(jié)果是 ? ? ? ? 從壓縮結(jié)果看,尺寸壓縮是穩(wěn)定的,質(zhì)量壓縮是不穩(wěn)定的。如果想通過(guò)壓縮算法控制文件大小,需要結(jié)合這兩種方法。但是需要指出的是,該質(zhì)量壓縮算法不可以濫用。因?yàn)樵谝欢ㄇ闆r下,該質(zhì)量壓縮會(huì)使文件空間大小變大。
最后附上工程代碼。
總結(jié)
以上是生活随笔為你收集整理的一种使用GDI+对图片尺寸和质量的压缩方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: PE文件和COFF文件格式分析——导出表
- 下一篇: Windows客户端C/C++编程规范“