C++ BMP转JPG方法一

读取文件数据后创建IStream对象,再调用IStream类方法read将JPG数据以二进制流读取出来。

使用GetImageEncodersSize之前一定要初始化GDIplus。最好在函数里面

ULONG_PTR gdiplusToken;

Gdiplus::GdiplusStartupInput gdiplusStartupInput;

Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);


退出的时候记得

Gdiplus::GdiplusShutdown(gdiplusToken);



1.添加GDI头文件

#include < Gdiplus.h>
#pragma comment(lib, "Gdiplus.lib")
using namespace Gdiplus;


#include <Objbase.h>
#include <Objidl.h>
#pragma comment(lib, "Ole32.lib")
#pragma comment(lib, "Uuid.lib")



2.定义两个公共函数:

INT GetEncoderClsid(const WCHAR *format, CLSID *pClsid)
{
	UINT  num = 0;          // number of image encoders    
	UINT  size = 0;         // size of the image encoder array in bytes    

	ImageCodecInfo* pImageCodecInfo = NULL;

	GetImageEncodersSize(&num, &size);
	if (size == 0){
		return -1;  // Failure   
	}

	pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
	if (pImageCodecInfo == NULL){
		return -1;  // Failure   
	}

	GetImageEncoders(num, size, pImageCodecInfo);

	for (UINT j = 0; j < num; ++j){
		if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0){
			*pClsid = pImageCodecInfo[j].Clsid;
			free(pImageCodecInfo);
			return j;  // Success    
		}
	}

	free(pImageCodecInfo);
	return -1;  // Failure   
}

void WriteJPGFile(BYTE *pData, DWORD dwLen)
{
	HANDLE hFile = CreateFile(L"F:\\1.jpg", GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile != INVALID_HANDLE_VALUE){
		DWORD dwWrite = 0;
		WriteFile(hFile, pData, dwLen, &dwWrite, NULL);
		CloseHandle(hFile);
	}
}

调用:

HANDLE hFile = CreateFile(L"F:\\nn\\m_2.bmp", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile != INVALID_HANDLE_VALUE){
		DWORD dwFilesize = GetFileSize(hFile, NULL);//获取文件大小
		HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFilesize);//分配文件内存
		if (hGlobal){
			BYTE *pvData = (BYTE*)GlobalLock(hGlobal);
			DWORD dwRead = 0;
			ReadFile(hFile, pvData, dwFilesize, &dwRead, NULL);//将文件数据读取到内存中
			GlobalUnlock(hGlobal);


			{
				IStream *pBMPStream = NULL;
				HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pBMPStream);//将二进制流存到流对象
				if (SUCCEEDED(hr)){
					CLSID codecClsid;
					GetEncoderClsid(L"image/jpeg", &codecClsid);

					int iQuality = 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 = &iQuality;

					Image pImage(pBMPStream);//这里可以改成图片路径
					IStorage* pIStorage = NULL;
					IStream* pJPGStream = NULL;
					HRESULT hr = StgCreateDocfile(NULL, STGM_READWRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
					if (SUCCEEDED(hr)){
						hr = pIStorage->CreateStream(L"StreamImage1", STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pJPGStream);
						DWORD dwErr = GetLastError();
						if (SUCCEEDED(hr)){
							Status bStatus = pImage.Save(pJPGStream, &codecClsid);//将bmp转jpg后保存在内存中
							//Status bStatus = pImage.Save(L"f:\\1.jpg", &codecClsid);//如果是保存为文件则把注释去掉

							BYTE * pJPGData = new BYTE[1024 * 1024];//申请1M的空间
							memset(pJPGData, 0, 1024 * 1024);

							LARGE_INTEGER move;
							move.QuadPart = 0;
							pJPGStream->Seek(move, STREAM_SEEK_SET, NULL);//定位到流的起始位置

							DWORD dwRead = 0;
							hr = pJPGStream->Read(pJPGData, 1024 * 1024, &dwRead);//在read之前必须seek。否则读取不出来数据
							WriteJPGFile(pJPGData, dwRead);
							delete[] pJPGData;
						}
					}

					// Get the class identifier for the JPEG encoder.
					if (pJPGStream){
						pJPGStream->Release();
					}
					if (pBMPStream){
						pBMPStream->Release();
					}
					if (pIStorage){
						pIStorage->Release();
					}
				}
			}

			GlobalFree(hGlobal);
		}

		CloseHandle(hFile);
	}
demo: http://download.csdn.net/detail/sz76211822/9819193


版权声明:本文为sz76211822原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。