同系列文章
工程下载
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;
}
}