Windows图像处理工具包(1)VC:FileUtils.dll

同系列文章

工程下载

FileUtils.zip

FileUtils.def

LIBRARY FileUtils

EXPORTS
	Prepare

	FreeByteArray
	ReadFromFile	
	WriteToFile

	BgraToGray
	BgraToBgr

	ToBgra
	ToGray

	ToHBitmapFromFile
	ToBgraFromFile	
	ToGrayFromFile

	StartupGdiplus
	ShutdownGdiplus
	ToHBitmapFromBuffer
	ToBgraFromBuffer
	ToGrayFromBuffer

FileUtils.h

/* ----------------------------------------------------------
* 文件名称:FileUtils.h
*
* 作者:秦建辉
*
* 微信:splashcn
*
* 博客:http://www.firstsolver.com/wordpress/
*
* 开发环境:
*      Visual Studio V2017
*
* 版本历史:
*   V1.0    2018年01月16日
*           文件读写工具类
* ---------------------------------------------------------- */
#pragma once

#include <Windows.h>

#ifdef __cplusplus
extern "C"
{
#endif

	/*
	功能:用于预加载动态库
	返回值:TRUE
	*/
	BOOL WINAPI Prepare();

	/*
	功能:释放内存空间
	参数说明:
	buffer:输入,存储空间
	*/
	VOID WINAPI FreeByteArray(IN BYTE* &buffer);

	/*
	功能:读取二进制文件数据
	参数说明:
	filename:输入,要读取的二进制文件名
	buffer:输出,存储空间,后续必须调用Free释放存储空间
	size:输出,存储空间占用字节数大小
	返回值:
	错误代码
	*/
	HRESULT WINAPI ReadFromFile(IN const TCHAR* filename, OUT BYTE* & buffer, OUT INT & size);

	/*
	功能:存储数据到二进制文件
	参数说明:
	filename:输入,要存储的二进制文件名
	buffer:输入,存储空间
	size:输入,存储空间占用字节数大小
	返回值:
	错误代码
	*/
	HRESULT WINAPI WriteToFile(IN const TCHAR* filename, IN BYTE* buffer, IN INT size);

	/*
	功能:将Bgra数组转换为灰度数组
	参数说明:
	bgra:要转换的Bgra数组
	gray:灰度数组
	size:需要转换的像素数
	*/
	VOID WINAPI BgraToGray(IN const BYTE* bgra, IN OUT BYTE* gray, IN INT size);

	/*
	功能:将Bgra数组转换为Bgr数组
	参数说明:
	bgra:要转换的Bgra数组
	bgr:Bgr数组
	size:需要转换的像素数
	*/
	VOID WINAPI BgraToBgr(IN const BYTE* bgra, IN OUT BYTE* bgr, IN INT size);

#ifdef __cplusplus
}
#endif

FileUtils.cpp

#include "FileUtils.h"
#include <stdio.h>
#include <tchar.h>
#include <new>

// 用于预加载
BOOL WINAPI Prepare() { return TRUE; }

// 释放存储空间
VOID WINAPI FreeByteArray(IN BYTE* &buffer)
{
	if (buffer != NULL)
	{
		delete[] buffer;
		buffer = NULL;
	}
}

// 从文件读取数据到存储空间
HRESULT WINAPI ReadFromFile(IN const TCHAR* filename, OUT BYTE* & buffer, OUT INT & size)
{
	FILE* fp;
	if (_tfopen_s(&fp, filename, TEXT("rb")) != 0) return E_FAIL;

	fseek(fp, 0, SEEK_END);
	size = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	buffer = new (std::nothrow)BYTE[size];
	if (buffer == NULL)
	{
		fclose(fp);
		return E_OUTOFMEMORY; // 内存不足
	}

	fread(buffer, 1, size, fp);
	fclose(fp);
	return S_OK;
}

// 存储数据到二进制文件
HRESULT WINAPI WriteToFile(IN const TCHAR* filename, IN BYTE* buffer, IN INT size)
{
	FILE* fp;
	if (_tfopen_s(&fp, filename, TEXT("wb")) != 0) return E_FAIL;

	fwrite(buffer, 1, size, fp);
	fclose(fp);
	return S_OK;
}

// 将Bgra数组转换为灰度数组
VOID WINAPI BgraToGray(IN const BYTE* bgra, IN OUT BYTE* gray, IN INT size)
{
	BYTE B, G, R;
	for (int i = 0; i < size; i++)
	{
		B = *bgra++;
		G = *bgra++;
		R = *bgra++;
		*gray++ = (B * 7471 + G * 38469 + R * 19595 + 32768) >> 16;
		bgra++;
	}
}

// 将Bgra数组转换为Bgr数组
VOID WINAPI BgraToBgr(IN const BYTE* bgra, IN OUT BYTE* bgr, IN INT size)
{
	for (int i = 0; i < size; i++)
	{
		*bgr++ = *bgra++;
		*bgr++ = *bgra++;
		*bgr++ = *bgra++;
		bgra++;
	}
}

GdiUtils.h

/* ----------------------------------------------------------
* 文件名称:GdiUtils.h
*
* 作者:秦建辉
*
* 微信:splashcn
*
* 博客:http://www.firstsolver.com/wordpress/
*
* 开发环境:
*      Visual Studio V2017
*
* 版本历史:
*   V1.0    2018年12月08日
*           Gdi扩展函数
* ---------------------------------------------------------- */
#pragma once

#include <Windows.h>
#include <gdiplus.h>

#pragma comment(lib, "Gdiplus.lib")

using namespace Gdiplus;

#ifdef __cplusplus
extern "C"
{
#endif	

	/*
	功能:获取位图图像Bgra数组
	参数说明:
	hbmp:图像句柄
	bgra:输出,存储图像Bgra数组
	width:输出,存储图像宽度
	height:输出,存储图像高度
	返回值:错误编码
	*/
	HRESULT WINAPI ToBgra(IN HBITMAP hBmp, OUT BYTE* &bgra, OUT INT& width, OUT INT& height);

	/*
	功能:获取位图图像灰度数组
	参数说明:
	hbmp:图像句柄
	gray:输出,存储图像灰度数组
	width:输出,存储图像宽度
	height:输出,存储图像高度
	返回值:错误编码
	*/
	HRESULT WINAPI ToGray(IN HBITMAP hBmp, OUT BYTE* &gray, OUT INT& width, OUT INT& height);

	/*
	功能:从文件生成HBITMAP
	参数说明:
	filename:图像文件路径
	返回值:位图图像句柄
	*/
	HBITMAP WINAPI ToHBitmapFromFile(IN const TCHAR * filename);

	/*
	功能:从文件获取位图图像Bgra数组
	参数说明:
	filename:图像文件路径
	bgra:输出,存储图像Bgra数组
	width:输出,存储图像宽度
	height:输出,存储图像高度
	返回值:错误编码
	*/
	HRESULT WINAPI ToBgraFromFile(IN const TCHAR * filename, OUT BYTE* &bgra, OUT INT& width, OUT INT& height);

	/*
	功能:获取位图图像灰度数组
	参数说明:
	filename:图像文件路径
	gray:输出,存储图像灰度数组
	width:输出,存储图像宽度
	height:输出,存储图像高度
	返回值:错误编码
	*/
	HRESULT WINAPI ToGrayFromFile(IN const TCHAR * filename, OUT BYTE* &gray, OUT INT& width, OUT INT& height);

	/*
	功能:启动Gdiplus
	返回值:状态码
	*/
	Gdiplus::Status WINAPI StartupGdiplus();

	/*
	功能:关闭Gdiplus
	*/
	VOID WINAPI ShutdownGdiplus();

	/*
	功能:基于Gdiplus从内存缓冲区生成HBITMAP
	参数说明:
	buffer:图像内存缓冲区
	size:图像字节数
	返回值:位图图像句柄
	说明:需要预先启动Gdiplus
	*/
	HBITMAP WINAPI ToHBitmapFromBuffer(const BYTE* buffer, int size);

	/*
	功能:获取位图图像Bgra数组
	参数说明:
	buffer:图像内存缓冲区
	size:图像字节数
	bgra:输出,存储图像Bgra数组
	width:输出,存储图像宽度
	height:输出,存储图像高度
	返回值:错误编码
	说明:需要预先启动Gdiplus
	*/
	HRESULT WINAPI ToBgraFromBuffer(const BYTE* buffer, int size, OUT BYTE* &bgra, OUT INT& width, OUT INT& height);

	/*
	功能:获取位图图像灰度数组
	参数说明:
	buffer:图像内存缓冲区
	size:图像字节数
	gray:输出,存储图像灰度数组
	width:输出,存储图像宽度
	height:输出,存储图像高度
	返回值:错误编码
	说明:需要预先启动Gdiplus
	*/
	HRESULT WINAPI ToGrayFromBuffer(const BYTE* buffer, int size, OUT BYTE* &gray, OUT INT& width, OUT INT& height);

#ifdef __cplusplus
}
#endif

GdiUtils.cpp

#include "GdiUtils.h"
#include <new>

ULONG_PTR mToken = NULL;

// 获取位图图像Bgra数组
HRESULT WINAPI ToBgra(IN HBITMAP hBmp, OUT BYTE* &bgra, OUT INT& width, OUT INT& height)
{
	BITMAP bm;
	if (::GetObject(hBmp, sizeof(BITMAP), &bm) == 0) return E_INVALIDARG;

	width = bm.bmWidth;		// 图像像素宽度
	height = bm.bmHeight;	// 图像像素高度
	int biSizeImage = (bm.bmWidth * bm.bmHeight) << 2;

	BITMAPINFO bmi;
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth = bm.bmWidth;
	bmi.bmiHeader.biHeight = -bm.bmHeight; // 负数表示图像左上角为起始点
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;
	bmi.bmiHeader.biCompression = BI_RGB; // 不压缩
	bmi.bmiHeader.biSizeImage = 0; // 对于BI_RGB,可以设置为0
	bmi.bmiHeader.biClrUsed = 0;
	bmi.bmiHeader.biClrImportant = 0;

	bgra = new (std::nothrow) BYTE[biSizeImage];
	if (bgra == NULL) return E_OUTOFMEMORY;

	HRESULT hr = S_OK;
	HDC hDC = ::GetDC(NULL);
	if (hDC == NULL)
	{
		hr = E_FAIL;
	}
	else
	{
		if (::GetDIBits(hDC, hBmp, 0, bm.bmHeight, bgra, &bmi, DIB_RGB_COLORS) == 0)
		{
			hr = E_INVALIDARG;
		}

		::ReleaseDC(NULL, hDC);
	}

	if (FAILED(hr)) { delete[] bgra; bgra = NULL; }
	return hr;
}

// 获取位图图像灰度数组
HRESULT WINAPI ToGray(IN HBITMAP hBmp, OUT BYTE* &gray, OUT INT& width, OUT INT& height)
{
	BITMAP bm;
	if (::GetObject(hBmp, sizeof(BITMAP), &bm) == 0) return E_INVALIDARG;

	width = bm.bmWidth;	// 图像像素宽度
	height = bm.bmHeight;	// 图像像素高度
	int biPixels = bm.bmWidth * bm.bmHeight;
	int biSizeImage = biPixels << 2;

	BITMAPINFO bmi;
	bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmi.bmiHeader.biWidth = bm.bmWidth;
	bmi.bmiHeader.biHeight = -bm.bmHeight; // 负数表示图像左上角为起始点
	bmi.bmiHeader.biPlanes = 1;
	bmi.bmiHeader.biBitCount = 32;
	bmi.bmiHeader.biCompression = BI_RGB;
	bmi.bmiHeader.biSizeImage = 0; // 对于BI_RGB,可以设置为0
	bmi.bmiHeader.biClrUsed = 0;
	bmi.bmiHeader.biClrImportant = 0;

	BYTE* bgra = new (std::nothrow) BYTE[biSizeImage];
	if (bgra == NULL) return E_OUTOFMEMORY;

	HRESULT hr = S_OK;
	HDC hDC = ::GetDC(NULL);
	if (hDC == NULL)
	{
		hr = E_FAIL;
	}
	else
	{
		if (::GetDIBits(hDC, hBmp, 0, bm.bmHeight, bgra, &bmi, DIB_RGB_COLORS) == 0)
		{
			hr = E_INVALIDARG;
		}
		else
		{
			gray = new (std::nothrow) BYTE[biPixels];
			if (gray == NULL)
			{
				hr = E_OUTOFMEMORY;
			}
			else
			{
				BYTE* pSrc = bgra;
				BYTE* pDest = gray;
				for (int i = 0; i < biPixels; i++)
				{
					*pDest++ = ((*pSrc++) * 7471 + (*pSrc++) * 38469 + (*pSrc++) * 19595 + 32768) >> 16;
					pSrc++;
				}
			}
		}

		::ReleaseDC(NULL, hDC);
	}

	delete[] bgra;
	return hr;
}

// 从文件生成HBITMAP
HBITMAP WINAPI ToHBitmapFromFile(IN const TCHAR * filename)
{
	return (HBITMAP)::LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
}

// 获取位图图像Bgra数组
HRESULT WINAPI ToBgraFromFile(IN const TCHAR * filename, OUT BYTE* &bgra, OUT INT& width, OUT INT& height)
{
	HBITMAP hBmp = (HBITMAP)::LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
	if (hBmp == NULL)
	{
		return HRESULT_FROM_WIN32(GetLastError());
	}
	else
	{
		HRESULT hr = ToBgra(hBmp, bgra, width, height);
		DeleteObject(hBmp);
		return hr;
	}
}

// 获取位图图像灰度数组
HRESULT WINAPI ToGrayFromFile(IN const TCHAR * filename, OUT BYTE* &gray, OUT INT& width, OUT INT& height)
{
	HBITMAP hBmp = (HBITMAP)::LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
	if (hBmp == NULL)
	{
		return HRESULT_FROM_WIN32(GetLastError());
	}
	else
	{
		HRESULT hr = ToGray(hBmp, gray, width, height);
		DeleteObject(hBmp);
		return hr;
	}
}

// 启动Gdiplus
Gdiplus::Status WINAPI StartupGdiplus()
{
	if (mToken == NULL)
	{
		GdiplusStartupInput input;
		return GdiplusStartup(&mToken, &input, NULL);
	}
	else
	{
		return Status::Ok;
	}
}

// 关闭Gdiplus
VOID WINAPI ShutdownGdiplus()
{
	if (mToken != NULL)
	{
		GdiplusShutdown(mToken);
		mToken = 0;
	}
}

// 从内存缓冲区生成HBITMAP
HBITMAP WINAPI ToHBitmapFromBuffer(const BYTE* buffer, int size)
{
	HBITMAP hBmp = NULL;
	HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, size);
	if (hMem != NULL)
	{
		LPVOID pMem = ::GlobalLock(hMem);
		if (pMem != NULL)
		{
			CopyMemory(pMem, buffer, size);

			IStream *pStream = NULL;
			if (SUCCEEDED(CreateStreamOnHGlobal(hMem, FALSE, &pStream)))
			{
				Bitmap* pBmp = Bitmap::FromStream(pStream, FALSE);
				if (pBmp != NULL)
				{
					Gdiplus::Color bg(0, 255, 255, 255);
					pBmp->GetHBITMAP(bg, &hBmp);
					delete pBmp;
				}

				pStream->Release();
			}

			::GlobalUnlock(hMem);
		}
		::GlobalFree(hMem);
	}

	return hBmp;
}

// 获取位图图像Bgra数组
HRESULT WINAPI ToBgraFromBuffer(const BYTE* buffer, int size, OUT BYTE* &bgra, OUT INT& width, OUT INT& height)
{
	HBITMAP hBmp = ToHBitmapFromBuffer(buffer, size);
	if (hBmp == NULL)
	{
		return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
	}
	else
	{
		HRESULT hr = ToBgra(hBmp, bgra, width, height);
		DeleteObject(hBmp);
		return hr;
	}
}

// 获取位图图像灰度数组
HRESULT WINAPI ToGrayFromBuffer(const BYTE* buffer, int size, OUT BYTE* &gray, OUT INT& width, OUT INT& height)
{
	HBITMAP hBmp = ToHBitmapFromBuffer(buffer, size);
	if (hBmp == NULL)
	{
		return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
	}
	else
	{
		HRESULT hr = ToGray(hBmp, gray, width, height);
		DeleteObject(hBmp);
		return hr;
	}
}

Comments are closed.