123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- #include "stdafx.h"
- #include "ImageCompress.h"
- ULONG_PTR ImageCompress::m_gdiplusToken = NULL;
- ImageCompress::ImageCompress(void)
- {
- }
- ImageCompress::~ImageCompress(void)
- {
- }
- // 图片压缩格式;
- //image/bmp
- //image/jpeg
- //image/gif
- //image/tiff
- //image/png
- int ImageCompress::GetEncoderClsid(IN const WCHAR* format, OUT CLSID* pClsid)
- {
- UINT nNumberOfImageEncoders = 0; // number of image encoders
- UINT nSizeOfImageEndcoderArray = 0; // size of the image encoder array in bytes
- ImageCodecInfo* pImageCodecInfo = NULL;
- GetImageEncodersSize(&nNumberOfImageEncoders, &nSizeOfImageEndcoderArray);
- if (nSizeOfImageEndcoderArray == 0)
- return -1; // Failure
- pImageCodecInfo = (ImageCodecInfo*)(malloc(nSizeOfImageEndcoderArray));
- if (pImageCodecInfo == NULL)
- return -1; // Failure
- GetImageEncoders(nNumberOfImageEncoders, nSizeOfImageEndcoderArray, pImageCodecInfo);
- for (UINT i = 0; i < nNumberOfImageEncoders; ++i)
- {
- if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0)
- {
- *pClsid = pImageCodecInfo[i].Clsid;
- free(pImageCodecInfo);
- return i; // Success
- }
- }
- free(pImageCodecInfo);
- return -1; // FailureFailure
- }
- //Scale 比例;
- //Zoom 缩放;
- // 给定最小(最大)宽度,按比例(原图宽/指定宽)缩放图片大小,获取完整缩放尺寸;
- //-----------------------------------------------------------------------------------------------------------------------
- //
- // 函数:ScaleZoombySpecificWidth
- // 描述:以指定高来缩放矩形;
- // 参数:
- // nWidth : 指定的压缩宽;
- // nHeight : 指定的压缩高;
- // rc : 压缩存放的区域;
- //
- // 返回:#;
- //
- // 注意:;
- //
- //-----------------------------------------------------------------------------------------------------------------------
- void ImageCompress::ScaleZoombySpecificHeight(IN const int &nWidth, IN const int &nHeight, IN OUT CRect &rc)
- {
- try
- {
- if (nWidth == 0 || nHeight == 0)return;
- // 图片长宽比例;
- float fscale = (float)nWidth / (float)nHeight;
- // 设备长宽比例;
- float rcscale = ((float)rc.Width()) / ((float)rc.Height());
- int rcwid = rc.Width();
- int rchei = rc.Height();
- int dt = 0;
- // Jeff.如果设备长宽比例 < 图片长宽比例;(即相同长度下,高越大比例值越小,所以此时图片尺寸 与 显示设备的尺寸相比,要显得更长)
- if (rcscale < fscale)
- {
- // Jeff.remarks
- // 调整显示设备的大小,以使之能容纳图片尺寸;(即长宽比例上,要大于或等于图片的长宽比例)
- // 所以有两种方法使得 rcscale >= fscale 表达式成立:
- // -----------------------------------------------
- // 方法1:显示设备宽加x值,计算出下面表达式x的值即可
- // (rc.Width()+x) / rc.Height() >= width/height;
- // 方法2:显示设备高减x值,计算出下面表达式x的值即可
- // (rc.Width()) / (rc.Height()-x) >= width/height;
- //------------------------------------------------
- // 两种方法的最后表达式为:
- // x >= rc.Height() - rcWidth()*(height/width);
- // 即 x >= rc.Height() - rcWidth()/fscale;
- //------------------------------------------------
- dt = (rchei - rcwid / fscale) / 2;
- rc.top += dt;
- rc.bottom -= dt;
- }
- else
- {
- dt = (rcwid - rchei*fscale) / 2;
- rc.left += dt;
- rc.right -= dt;
- }
- }
- catch (...)
- {
- }
- }
- //-----------------------------------------------------------------------------------------------------------------------
- //
- // 函数:ScaleZoombySpecificWidth
- // 描述:以指定宽来缩放矩形;
- // 参数:
- // nWidth : 指定的压缩宽;
- // nHeight : 指定的压缩高;
- // rc : 压缩存放的区域;
- //
- // 返回:#;
- //
- // 注意:;
- //
- //-----------------------------------------------------------------------------------------------------------------------
- void ImageCompress::ScaleZoombySpecificWidth(IN const int &nWidth, IN const int &nHeight, IN OUT CRect &rc)
- {
- try
- {
- if (nWidth == 0 || nHeight == 0)return;
- // 图片长宽比例;
- float fscale = (float)nWidth / (float)nHeight;
- // 设备长宽比例;
- float rcscale = ((float)rc.Width()) / ((float)rc.Height());
- int rcwid = rc.Width();
- int rchei = rc.Height();
- int dt = 0;
- // Jeff.如果设备长宽比例 < 图片长宽比例;(即相同长度下,高越大比例值越小,所以此时图片尺寸 与 显示设备的尺寸相比,要显得更长)
- if (rcscale < fscale)
- {
- // Jeff.remarks
- // 调整显示设备的大小,以使之能容纳图片尺寸;(即长宽比例上,要大于或等于图片的长宽比例)
- // 所以有两种方法使得 rcscale >= fscale 表达式成立:
- // -----------------------------------------------
- // 方法1:显示设备宽加x值,计算出下面表达式x的值即可
- // (rc.Width()+x) / rc.Height() >= width/height;
- // 方法2:显示设备高减x值,计算出下面表达式x的值即可
- // (rc.Width()) / (rc.Height()-x) >= width/height;
- //------------------------------------------------
- // 两种方法的最后表达式为:
- // x >= rc.Height() - rcWidth()*(height/width);
- // 即 x >= rc.Height() - rcWidth()/fscale;
- //------------------------------------------------
- dt = (rcwid - rchei*fscale) / 2;
- rc.left += dt;
- rc.right -= dt;
- }
- else
- {
- dt = (rchei - rcwid / fscale) / 2;
- rc.top += dt;
- rc.bottom -= dt;
- }
- }
- catch (...)
- {
- }
- }
- //-----------------------------------------------------------------------------------------------------------------------
- //
- // 函数:SaveImageToFile
- // 描述:压缩指定目录的相片到指定目录;
- // 参数:
- // img : Image对象;
- // path : 压缩后相片保存路径;
- // quality : 压缩的质量值;
- //
- // 返回:#;
- //
- // 注意:;
- //
- //-----------------------------------------------------------------------------------------------------------------------
- void ImageCompress::SaveImageToFile(IN Image *img, IN CString &path, IN ULONG quality)
- {
- try
- {
- if (img == NULL)return;
- CLSID encoderClsid;
- BSTR bstr = path.AllocSysString();
- path.MakeLower();
- if (path.Right(3) == _T("bmp"))
- {
- GetEncoderClsid(L"image/bmp", &encoderClsid);
- img->Save(bstr, &encoderClsid, NULL);
- }
- else if (path.Right(3) == _T("png"))
- {
- GetEncoderClsid(L"image/png", &encoderClsid);
- img->Save(bstr, &encoderClsid, NULL);
- }
- else// if(path.Right (3)== _T("jpg"))
- {
- GetEncoderClsid(L"image/jpeg", &encoderClsid);
- EncoderParameters encoderParameters;
- encoderParameters.Count = 1;
- encoderParameters.Parameter[0].Guid = EncoderQuality;
- encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
- encoderParameters.Parameter[0].NumberOfValues = 1;
- // Save the image as a JPEG with quality level 100.
- encoderParameters.Parameter[0].Value = &quality;
- img->Save(bstr, &encoderClsid, &encoderParameters);
- }
- SysFreeString(bstr);
- }
- catch (...)
- {
- }
- }
- //-----------------------------------------------------------------------------------------------------------------------
- //
- // 函数:ToCompressImage
- // 描述:压缩指定目录的相片到指定目录;
- // 参数:
- // pImageSource : 原相片完整路径;
- // pImageDest : 压缩后相片保存路径;
- // nXPiexel : 压缩的像素宽;
- // nYPiexel : 压缩的像素高;
- //
- // 返回:#;
- //
- // 注意:;
- //
- //-----------------------------------------------------------------------------------------------------------------------
- BOOL ImageCompress::ToCompressImage(IN const TCHAR *pImageSource, IN const TCHAR *pImageDest, IN const int &nXPiexel, IN const int &nYPiexel)
- {
- Image *pImage = NULL;
- ::DeleteFile(pImageDest);
- // 1.从文件中以读的方式加载图片到Image中;
- CFile cf;
- if (cf.Open(pImageSource, CFile::modeRead))
- {
- DWORD dwLength = cf.GetLength();
- BYTE *pData = new BYTE[dwLength];
- if (pData == NULL)// 创建内存失败;
- return FALSE;
- cf.Read(pData, dwLength);
- cf.Close();
- // 1.1.将文件数据加载到内存数据中;
- HGLOBAL taghMem = GlobalAlloc(GMEM_MOVEABLE, dwLength);
- if (taghMem == NULL) // 创建内存失败;
- return FALSE;
- BYTE *pMem = (BYTE*)GlobalLock(taghMem);
- memcpy(pMem, pData, dwLength);
- // 1.2.创建二进制流对象;
- IStream *pStream;
- CreateStreamOnHGlobal(taghMem, TRUE, &pStream);
- pImage = Gdiplus::Image::FromStream(pStream);
- GlobalUnlock(taghMem);
- pStream->Release();
- delete[]pData;
- }
- // 2.加载后……
- if (pImage == NULL) // 加载失败;
- return FALSE;
- // 2.1.当图片的像素大于要设定的像素时,进行处理;
- if (pImage->GetWidth() > nXPiexel || pImage->GetHeight() > nYPiexel)
- {
- CRect tagRect(0, 0, nXPiexel, nYPiexel);
- ScaleZoombySpecificWidth(pImage->GetWidth(), pImage->GetHeight(), tagRect);
- Bitmap bp(tagRect.Width(), tagRect.Height());
- Graphics *graphic = Graphics::FromImage(&bp);
- graphic->Clear(Color(255, 255, 255, 255));
- graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
- graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
- graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
- graphic->SetCompositingMode(CompositingModeSourceOver);
- graphic->SetCompositingQuality(CompositingQualityHighQuality);
- graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
- graphic->DrawImage(pImage, RectF(0, 0, tagRect.Width(), tagRect.Height()), 0, 0, pImage->GetWidth(), pImage->GetHeight(), UnitPixel);
- delete pImage;
- try
- {
- CString path(pImageDest);
- CLSID encoderClsid;
- BSTR bstr = path.AllocSysString();
- path.MakeLower();
- if (path.Right(3) == _T("bmp"))
- {
- GetEncoderClsid(L"image/bmp", &encoderClsid);
- bp.Save(bstr, &encoderClsid, NULL);
- }
- else if (path.Right(3) == _T("png"))
- {
- GetEncoderClsid(L"image/png", &encoderClsid);
- bp.Save(bstr, &encoderClsid, NULL);
- }
- else// if(path.Right (3)=="jpg")
- {
- ULONG quality = 95;
- GetEncoderClsid(L"image/jpeg", &encoderClsid);
- EncoderParameters encoderParameters;
- encoderParameters.Count = 1;
- encoderParameters.Parameter[0].Guid = EncoderQuality;
- encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
- encoderParameters.Parameter[0].NumberOfValues = 1;
- // Save the image as a JPEG with quality level 100.
- encoderParameters.Parameter[0].Value = &quality;
- bp.Save(bstr, &encoderClsid, &encoderParameters);
- }
- SysFreeString(bstr);
- }
- catch (...)
- {
- return FALSE;
- }
- }
- return TRUE;
- }
|