WTL 界面设计篇(CImageEx)

2023-10-29

头文件声明(CImageEx.h):

#pragma once
#include <atlimage.h>

class CImageEx : public CImage
{
public:
	CImageEx(void);
	virtual ~CImageEx(void);

public:
	BOOL LoadFromFile(LPCTSTR pszFileName);// 从文件加载
	BOOL LoadFromIStream(IStream* pStream);// 从内存流加载
	BOOL LoadFromBuffer(const BYTE* lpBuf, DWORD dwSize);// 从缓存加载
	BOOL LoadFromResource(HINSTANCE hInstance, LPCTSTR pszResourceName, LPCTSTR pszResType);// 根据资源名称和类型加载
	BOOL LoadFromResource(HINSTANCE hInstance, UINT nIDResource, LPCTSTR pszResType);// 根据资源ID加载

	void SetNinePart(const RECT * lpNinePart);// 设置9宫格区域
	BOOL Draw2(HDC hDestDC, const RECT& rectDest);// 图像绘制

	void GrayScale();	// 图像灰度化处理

private:
	BOOL AlphaPremultiplication();	// Alpha预乘,否则会出现黑色噪点
	BOOL DrawNinePartImage(int pleft, int ptop, int pright, int pbottom,
		HDC hDC, int height, int width, int left, int top, int right, int bottom);// 9宫格贴图
	BOOL DrawNinePartImage(HDC hDC, int x, int y, int cx, int cy, 
		int nLeft, int nTop, int nRight, int nBottom);// 9宫格贴图
	int GetFileType(LPCTSTR lpszFileName);// 根据文件头字节,判断文件类型

private:
	BOOL m_bIsNinePart;// 是否9宫格
	RECT m_rcNinePart;// 9宫格区域
};

源码实现(CImageEx.cpp):

#include "StdAfx.h"
#include "ImageEx.h"

CImageEx::CImageEx(void)
{
	m_bIsNinePart = FALSE;
	::SetRectEmpty(&m_rcNinePart);
}

CImageEx::~CImageEx(void)
{
}

BOOL CImageEx::LoadFromFile(LPCTSTR pszFileName)
{
	HRESULT hr = CImage::Load(pszFileName);
	if (hr == S_OK)
	{
		if (GetFileType(pszFileName) == 0)	// png
			AlphaPremultiplication();

		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

BOOL CImageEx::LoadFromIStream(IStream* pStream)
{
	HRESULT hr = CImage::Load(pStream);
	if (hr == S_OK)
	{
		AlphaPremultiplication();
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

BOOL CImageEx::LoadFromBuffer(const BYTE* lpBuf, DWORD dwSize)
{
	if (NULL == lpBuf || dwSize <= 0)
		return FALSE;

	HGLOBAL hGlobal = ::GlobalAlloc(GHND, dwSize);
	if (NULL == hGlobal)
		return FALSE;

	LPVOID lpBuffer = ::GlobalLock(hGlobal);
	if (NULL == lpBuffer)
	{
		::GlobalFree(hGlobal);
		return FALSE;
	}

	memcpy(lpBuffer, lpBuf, dwSize);
	::GlobalUnlock(hGlobal);

	LPSTREAM lpStream = NULL;
	HRESULT hr = ::CreateStreamOnHGlobal(hGlobal, TRUE, &lpStream);
	if (hr != S_OK)
	{
		::GlobalFree(hGlobal);
		return FALSE;
	}
	
	BOOL bRet = LoadFromIStream(lpStream);
	lpStream->Release();

	return bRet;
}

BOOL CImageEx::LoadFromResource(HINSTANCE hInstance, LPCTSTR pszResourceName, LPCTSTR pszResType)
{
	HRSRC hRsrc = ::FindResource(hInstance, pszResourceName, pszResType);
	if (NULL == hRsrc)
		return FALSE;

	DWORD dwSize = ::SizeofResource(hInstance, hRsrc); 
	if (0 == dwSize)
		return FALSE;

	HGLOBAL hGlobal = ::LoadResource(hInstance, hRsrc); 
	if (NULL == hGlobal)
		return FALSE;

	LPVOID pBuffer = ::LockResource(hGlobal);
	if (NULL == pBuffer)
	{
		::FreeResource(hGlobal);
		return FALSE;
	}

	HGLOBAL hGlobal2 = ::GlobalAlloc(GHND, dwSize);
	if (NULL == hGlobal2)
	{
		::FreeResource(hGlobal);
		return FALSE;
	}

	LPVOID pBuffer2 = ::GlobalLock(hGlobal2);
	if (NULL == pBuffer2)
	{
		::GlobalFree(hGlobal2);
		::FreeResource(hGlobal);
		return FALSE;
	}

	memcpy(pBuffer2, pBuffer, dwSize);
	::GlobalUnlock(hGlobal2);

	LPSTREAM pStream = NULL;
	HRESULT hr = ::CreateStreamOnHGlobal(hGlobal2, TRUE, &pStream);
	if (hr != S_OK)
	{
		::GlobalFree(hGlobal2);
		::FreeResource(hGlobal);
		return FALSE;
	}

	BOOL bRet = LoadFromIStream(pStream);

	if (pStream)
		pStream->Release();

	::FreeResource(hGlobal);

	return bRet;
}

BOOL CImageEx::LoadFromResource(HINSTANCE hInstance, UINT nIDResource, LPCTSTR pszResType)
{
	return LoadFromResource(hInstance, MAKEINTRESOURCE(nIDResource), pszResType);
}

void CImageEx::SetNinePart(const RECT * lpNinePart)
{
	if ((NULL == lpNinePart) || (0 == lpNinePart->left && 0 == lpNinePart->top
		&& 0 == lpNinePart->right && 0 == lpNinePart->bottom))
	{
		m_bIsNinePart = FALSE;
		::SetRectEmpty(&m_rcNinePart);
	}
	else
	{
		m_bIsNinePart = TRUE;
		m_rcNinePart = *lpNinePart;
	}
}

BOOL CImageEx::Draw2(HDC hDestDC, const RECT& rectDest)
{
	if (m_bIsNinePart)
	{
		int nWidth = rectDest.right - rectDest.left;
		int nHeight = rectDest.bottom - rectDest.top;
		if (GetWidth() != nWidth || GetHeight() != nHeight)
		{
			return DrawNinePartImage(hDestDC, rectDest.left, rectDest.top, nWidth, nHeight, 
				m_rcNinePart.left, m_rcNinePart.top, m_rcNinePart.right, m_rcNinePart.bottom);
		}
	}
	
	return Draw(hDestDC, rectDest);
}

// 图像灰度化
void CImageEx::GrayScale()
{
	int nWidth = GetWidth();
	int nHeight = GetHeight();

	BYTE* pArray = (BYTE*)GetBits();
	int nPitch = GetPitch();
	int nBitCount = GetBPP() / 8;

	for (int i = 0; i < nHeight; i++) 
	{
		for (int j = 0; j < nWidth; j++) 
		{
			int grayVal = (BYTE)(((*(pArray + nPitch * i + j * nBitCount) * 306)
				+ (*(pArray + nPitch * i + j * nBitCount + 1) * 601)
				+ (*(pArray + nPitch * i + j * nBitCount + 2) * 117) + 512 ) >> 10);	// 计算灰度值

			*(pArray + nPitch * i + j * nBitCount) = grayVal;							// 赋灰度值
			*(pArray + nPitch * i + j * nBitCount + 1) = grayVal;
			*(pArray + nPitch * i + j * nBitCount + 2) = grayVal;
		}
	}
}

// Alpha预乘
BOOL CImageEx::AlphaPremultiplication()
{
	LPVOID pBitsSrc = NULL;
	BYTE * psrc = NULL;
	BITMAP stBmpInfo;

	HBITMAP hBmp = (HBITMAP)*this;

	::GetObject(hBmp, sizeof(BITMAP), &stBmpInfo);

	// Only support 32bit DIB section
	if (32 != stBmpInfo.bmBitsPixel || NULL == stBmpInfo.bmBits)
		return FALSE;

	psrc = (BYTE *) stBmpInfo.bmBits;

	// Just mix it
	for (int nPosY = 0; nPosY < abs(stBmpInfo.bmHeight); nPosY++)
	{
		for (int nPosX = stBmpInfo.bmWidth; nPosX > 0; nPosX--)
		{
			BYTE alpha  = psrc[3];
			psrc[0] = (BYTE)((psrc[0] * alpha) / 255);
			psrc[1] = (BYTE)((psrc[1] * alpha) / 255);
			psrc[2] = (BYTE)((psrc[2] * alpha) / 255);
			psrc += 4;
		}
	}

	return TRUE;
}

BOOL CImageEx::DrawNinePartImage(int pleft, int ptop, int pright, int pbottom,
					   HDC hDC, int height, int width, int left, int top, int right, int bottom)
{
	// 左上
	{
		CRect rcDest(pleft, ptop, pleft+left, ptop+top);
		CRect rcSrc(0, 0, left, top);
		if (!rcDest.IsRectEmpty() && !rcSrc.IsRectEmpty())
			Draw(hDC, rcDest, rcSrc);
	}

	// 左边
	{
		CRect rcDest(pleft, top+ptop, pleft+left, top+(height-top-bottom-ptop-pbottom));
		CRect rcSrc(0, top, left, top+(GetHeight()-top-bottom));
		if (!rcDest.IsRectEmpty() && !rcSrc.IsRectEmpty())
			Draw(hDC, rcDest, rcSrc);
	}

	// 上边
	{
		CRect rcDest(left+pleft, ptop, (left+pleft)+(width-left-right-pleft-pright), ptop+top);
		CRect rcSrc(left, 0, left+(GetWidth()-left-right), top);
		if (!rcDest.IsRectEmpty() && !rcSrc.IsRectEmpty())
			Draw(hDC, rcDest, rcSrc);
	}

	// 右上
	{
		CRect rcDest(width- right-pright, ptop, (width- right-pright)+right, ptop+top);
		CRect rcSrc(GetWidth()-right, 0, (GetWidth()-right)+right, top);
		if (!rcDest.IsRectEmpty() && !rcSrc.IsRectEmpty())
			Draw(hDC, rcDest, rcSrc);
	}

	// 右边
	{
		CRect rcDest(width-right-pright, top+ptop, (width-right-pright)+right, (top+ptop)+(height-top-bottom-ptop-pbottom));
		CRect rcSrc(GetWidth()-right, top, (GetWidth()-right)+right, top+(GetHeight()-top-bottom));
		if (!rcDest.IsRectEmpty() && !rcSrc.IsRectEmpty())
			Draw(hDC, rcDest, rcSrc);
	}

	// 下边
	{
		CRect rcDest(left+pleft, height-bottom-pbottom, (left+pleft)+(width-left-right-pleft-pright), (height-bottom-pbottom)+bottom);
		CRect rcSrc(left, GetHeight()-bottom, left+(GetWidth()-left-right), (GetHeight()-bottom)+bottom);
		if (!rcDest.IsRectEmpty() && !rcSrc.IsRectEmpty())
			Draw(hDC, rcDest, rcSrc);
	}

	// 右下
	{
		CRect rcDest(width-right-pright, height-bottom-pbottom, (width-right-pright)+right, (height-bottom-pbottom)+bottom);
		CRect rcSrc(GetWidth()-right, GetHeight()-bottom, (GetWidth()-right)+right, (GetHeight()-bottom)+bottom);
		if (!rcDest.IsRectEmpty() && !rcSrc.IsRectEmpty())
			Draw(hDC, rcDest, rcSrc);
	}

	// 左下
	{
		CRect rcDest(pleft, height-bottom-pbottom, pleft+left, (height-bottom-pbottom)+bottom);
		CRect rcSrc(0, GetHeight()-bottom, left, (GetHeight()-bottom)+bottom);
		if (!rcDest.IsRectEmpty() && !rcSrc.IsRectEmpty())
			Draw(hDC, rcDest, rcSrc);
	}

	// 中间
	{
		CRect rcDest(left+pleft, top+ptop, (left+pleft)+(width-left-right-pleft-pright), (top+ptop)+(height-top-bottom-ptop-pbottom));
		CRect rcSrc(left, top, left+(GetWidth()-left-right), top+(GetHeight()-top-bottom));
		if (!rcDest.IsRectEmpty() && !rcSrc.IsRectEmpty())
			Draw(hDC, rcDest, rcSrc);
	}

	return TRUE;
}

BOOL CImageEx::DrawNinePartImage(HDC hDC, int x, int y, int cx, int cy, 
								 int nLeft, int nTop, int nRight, int nBottom)
{
	int cxImage = GetWidth();
	int cyImage = GetHeight();

	// 左上
	{
		RECT rcDest = {x, y, x+nLeft, y+nTop};
		RECT rcSrc = {0, 0, nLeft, nTop};
		if (!::IsRectEmpty(&rcDest) && !::IsRectEmpty(&rcSrc))
			Draw(hDC, rcDest, rcSrc);
	}

	// 左边
	{
		RECT rcDest = {x, y+nTop, x+nLeft, (y+nTop)+(cy-nTop-nBottom)};
		RECT rcSrc = {0, nTop, nLeft, nTop+(cyImage-nTop-nBottom)};
		if (!::IsRectEmpty(&rcDest) && !::IsRectEmpty(&rcSrc))
			Draw(hDC, rcDest, rcSrc);
	}

	// 上边
	{
		RECT rcDest = {x+nLeft, y, (x+nLeft)+(cx-nLeft-nRight), y+nTop};
		RECT rcSrc = {nLeft, 0, nLeft+(cxImage-nLeft-nRight), nTop};
		if (!::IsRectEmpty(&rcDest) && !::IsRectEmpty(&rcSrc))
			Draw(hDC, rcDest, rcSrc);
	}

	// 右上
	{
		RECT rcDest = {x+(cx-nRight), y, (x+(cx-nRight))+nRight, y+nTop};
		RECT rcSrc = {cxImage-nRight, 0, (cxImage-nRight)+nRight, nTop};
		if (!::IsRectEmpty(&rcDest) && !::IsRectEmpty(&rcSrc))
			Draw(hDC, rcDest, rcSrc);
	}

	// 右边
	{
		RECT rcDest = {x+(cx-nRight), y+nTop, (x+(cx-nRight))+nRight, (y+nTop)+(cy-nTop-nBottom)};
		RECT rcSrc = {cxImage-nRight, nTop, (cxImage-nRight)+nRight, nTop+(cyImage-nTop-nBottom)};
		if (!::IsRectEmpty(&rcDest) && !::IsRectEmpty(&rcSrc))
			Draw(hDC, rcDest, rcSrc);
	}

	// 下边
	{
		RECT rcDest = {x+nLeft, y+(cy-nBottom), (x+nLeft)+(cx-nLeft-nRight), (y+(cy-nBottom))+nBottom};
		RECT rcSrc = {nLeft, cyImage-nBottom, nLeft+(cxImage-nLeft-nRight), (cyImage-nBottom)+nBottom};
		if (!::IsRectEmpty(&rcDest) && !::IsRectEmpty(&rcSrc))
			Draw(hDC, rcDest, rcSrc);
	}

	// 右下
	{
		RECT rcDest = {x+(cx-nRight), y+(cy-nBottom), (x+(cx-nRight))+nRight, (y+(cy-nBottom))+nBottom};
		RECT rcSrc = {cxImage-nRight, cyImage-nBottom, (cxImage-nRight)+nRight, (cyImage-nBottom)+nBottom};
		if (!::IsRectEmpty(&rcDest) && !::IsRectEmpty(&rcSrc))
			Draw(hDC, rcDest, rcSrc);
	}

	// 左下
	{
		RECT rcDest = {x, y+(cy-nBottom), x+nLeft, (y+(cy-nBottom))+nBottom};
		RECT rcSrc = {0, cyImage-nBottom, nLeft, (cyImage-nBottom)+nBottom};
		if (!::IsRectEmpty(&rcDest) && !::IsRectEmpty(&rcSrc))
			Draw(hDC, rcDest, rcSrc);
	}

	// 中间
	{
		RECT rcDest = {x+nLeft, y+nTop, (x+nLeft)+(cx-nLeft-nRight), (y+nTop)+(cy-nTop-nBottom)};
		RECT rcSrc = {nLeft, nTop, nLeft+(cxImage-nLeft-nRight), nTop+(cyImage-nTop-nBottom)};
		if (!::IsRectEmpty(&rcDest) && !::IsRectEmpty(&rcSrc))
			Draw(hDC, rcDest, rcSrc);
	}

	return TRUE;
}

//获取文件类型(通过文件头几个字节获取)
int CImageEx::GetFileType(LPCTSTR lpszFileName)
{
	unsigned char png_head[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
	unsigned char gif89a_head[6] = {'G','I','F','8','9','a'};
	unsigned char gif87a_head[6] = {'G','I','F','8','7','a'};
	unsigned char jpg_head[2] = {0xFF, 0xD8};
	unsigned char bmp_head[2] = {0x42, 0x4D};
	unsigned char cData[16] = {0};

	FILE * fp = _tfopen(lpszFileName, _T("rb"));
	if (NULL == fp)
		return -1;
	fread(cData, sizeof(cData), 1, fp);
	fclose(fp);

	if (!memcmp(cData, png_head, 8))
		return 0;
	else if (!memcmp(cData, gif89a_head, 6) || !memcmp(cData, gif87a_head, 6))
		return 1;
	if (!memcmp(cData, jpg_head, 2))
		return 2;
	else if (!memcmp(cData, bmp_head, 2))
		return 3;
	else
		return -1;
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WTL 界面设计篇(CImageEx) 的相关文章

随机推荐

  • Effective Modern C++ Item 20 对于类似std::shared_ptr但有可能悬空的指针,使用std::weak_ptr

    如果需要某种智能指针能够像std shared ptr一样方便 但又无需参与管理所指涉到的对象的共享所有权的话 就很好适合用std weak ptr 但这样的功能同样会带来一个问题 这种指针需要处理一个对std shared ptr而言不是
  • softmax分类器_Softmax 理解

    Softmax深入理解 译 AIUAI www aiuai cn Pytorch的交叉熵nn CrossEntropyLoss在训练阶段 里面是内置了softmax操作的 因此只需要喂入原始的数据结果即可 不需要在之前再添加softmax层
  • OpenWrt-SDK-编译生成ipk软件包

    版本 Barrier Breaker 类型 brcm2708 下载SDK http downloads openwrt org barrier breaker 14 07 brcm2708 generic OpenWrt SDK brcm2
  • linux部署vue项目

    命令行进入配置文件 vi usr local nginx conf nginx conf 输入i进行修改端口号和文件路径 按ESC保存后输入 wq退出 进入sbin启动nginx cd usr local nginx sbin nginx
  • FMC164-基于JESD204B的4路1Gsps AD 4路1.25Gsps DA FMC子卡

    板卡介绍 FMC164子卡集成4通道1Gsps采样率 16位AD 4通道1 25Gsps 16位DA 板载时钟芯片HMC7044 可以提供JESD204B所需要的各种时钟 具有同步 触发功能 模拟信号采用SSMC射频连接器输入和输出 板卡可
  • es 修改mappings字段结构

    es不支持直接修改mappings字段结构 可以通过 reindex 重建索引 方式修改 POST reindex source index old index dest index new index op type create Ela
  • 记录:Qt Creator 10配置安卓开发环境

    Qt Creator 现在的安卓开发环境配置相比老版本方便了不少 本文以目前在线安装版的 Qt Creator 10 0 2 Qt 5 15 Qt 6 5 为例做演示 有些文件可能会因为网络问题需要科学上网才能下载 1 下载 JDK htt
  • 【css】css动画实现的3种方式

    css实现动画主要有3种方式 transition实现过渡动画 transform转变动画 animation实现自定义动画 一 transition过渡动画 1 语法 transition property duration timing
  • UnityAPI.Transform变换(Yanlz+Unity+API+Transform+)

    UnityAPI Transform变换 版本 作者 参与者 完成日期 备注 UnityAPI Transform V01 1 0 严立钻 2018 08 21 UnityAPI Transform变换 发布说明 UnityAPI Tran
  • Linux·C++多线程基础知识

    目录 1 多线程 1 1 多进程与多线程 1 2 多线程理解 1 3 创建线程 1 4 join与detach方式 1 join举例 2 detach举例 1 5 this thread 2 mutex 2 1 lock与unlock 2
  • 【Tensorflow】tf.nn.depthwise_conv2d如何实现深度卷积?

    实验环境 tensorflow版本1 2 0 python2 7 介绍 depthwise conv2d来源于深度可分离卷积 Xception Deep Learning with Depthwise Separable Convoluti
  • C#时间字符串转换

    class Program static void Main string args DateTime datetime DateTime Now 打印当前时间 Console WriteLine 时间为 n datetime n 方法1
  • Generator 函数

    Generator 函数 基本概念 与 Iterator 接口的关系 next 方法的参数 for of 循环 Generator prototype throw Generator prototype return next throw
  • docker quick start

    文章目录 安装 验证 设置阿里云加速代理 测试 常用命令 镜像和容器存储位置 容器生命周期 Dockerfile 构建镜像 部署tomcat 基础指令 构建redis镜像 容器间Link单向通信 容器间Bridge网桥双向通信 volume
  • 【Node.js实战】一文带你开发博客项目之日志(文件读写、stream流、写日志)

    个人简介 个人主页 前端杂货铺 学习方向 主攻前端方向 也会涉及到服务端 个人状态 在校大学生一枚 已拿多个前端 offer 秋招 未来打算 为中国的工业软件事业效力n年 推荐学习 前端面试宝典 Vue2 Vue3 Vue2 Vue3项目实
  • memcache清除缓存

    打开cmd 输入 telnet localhost 11211 flush all
  • 为博客添加樱花飘落的效果

    偶然看见别人博客中樱花飘落的效果 感觉很棒 于是我也给博客加上了樱花 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 新建 sakura js 新建一个 sakura js 文件 在里面填入下面的代码 代码来自于 折月
  • 快速排序的优化

    1 快速排序的基本思想 快速排序使用分治的思想 通过一趟排序将待排序列分割成两部分 其中一部分记录的关键字均比另一部分记录的关键字小 之后分别对这两部分记录继续进行排序 以达到整个序列有序的目的 2 快速排序的三个步骤 1 选择基准 在待排
  • 24. 在QML界面中嵌入QWidget窗口

    1 说明 目前QT官方主推的界面开发方式是采用QML进行界面设计 但在QML未流行之前 很多的项目都是采用QWidget开发的 把之前的代码全部转换为QML代码显然工作量非常大 如果能将QWidget窗口嵌入到QML界面中 那么开发效率将提
  • WTL 界面设计篇(CImageEx)

    头文件声明 CImageEx h pragma once include