最近开始学习图像处理方面的知识,想起以前曾经做过的给图片添加文字水印,不过,那时还在前一个公司,时间也很长了,这次就当复习一遍。
这里所说的水印,就是在图片内部添加文字标记,通常用于标明版权。为了提高重用性,我把这个功能的实现封装成了一个类。
实现原理:
1. 加载一个位图到内存
2. 创建一个与屏幕内存设备兼容的内存设备上下文memDC
3. 把位图选进memDC
4. 设置自定义字体font
5. 把font选进memDC
6. 设置memDC的TextColor(文字颜色),BkColor(文字背景色),Transparent(文字背景是否透明)
7. 自动或手动设置文字在图片的位置
8. 使用TextOut函数将水印文字输出到内存设备memDC
9. 把memDC中的内容保存到位图文件
代码实现:-类CWaterMark
头文件
/* Copyright (C) wuchen 2011 ALL RIGHTS RESERVED.
* Author:niewucai
* Email:niewucai@126.com
* Last Update:2011/05/11
* 实现对位图图片添加文字水印功能 -- 头文件
*/
#pragmaonce
#include<string>
usingnamespace std;
class CWaterMark{
public:
/*构造方法
* @lpszImgFile:要添加水印的位图图片文件
*/
CWaterMark(LPCTSTR lpszImgFile);
/*构造方法
* @nIDResource:位图资源标识
*/
CWaterMark(UINT nIDResource);
~CWaterMark();
//水印文字位置枚举
typedefenum
{
/* 表示左上位置。
*/
LeftTop = 1,
/* 表示中上位置。
*/
CenterTop,
/* 表示右上位置。
*/
RightTop,
/* 表示左中位置。
*/
LeftMiddle,
/* 表示中心位置。
*/
CenterMiddle,
/* 表示右中位置。
*/
RightMiddle,
/* 表示左下位置。
*/
LeftBottom,
/* 表示中下位置。
*/
CenterBottom,
/* 表示右下位置。
*/
RightBottom
}Location;
public:
int m_topSpacing; //水印文字与图片顶部的间距(像素)
int m_rightSpacing; //水印文字与图片右端的间距(像素)
int m_bottomSpacing;//水印文字与图片底部的间距(像素)
int m_leftSpacing; //水印文字与图片左端的间距(像素)
public:
/*更换当前操作位图
* @nIDResouce:位图资源标识
* return:是否更换成功
*/
bool ChangeBitmap(UINT nIDResource);
/*更换当前操作位图
* @lpszImgFile:位图文件路径
* return:是否更换成功
*/
bool ChangeBitmap(LPCTSTR lpszImgFile);
/*获取与设备无关的内存设备上下文*/
inline HDC GetMemoryDC()
{
return m_hMemDC;
}
/*获取当前处理位图的BITMAP结构*/
int GetBitmap(BITMAP* pBitMap);
/*获取水印文字的前景色*/
COLORREF GetForeColor();
/*设置水印文字的前景色*/
void SetForeColor(COLORREF foreColor = 0);
/*获取水印文字的背景色*/
COLORREF GetBkColor();
/*设置水印文字的背景色*/
void SetBkColor(COLORREF bkColor = RGB(255, 255, 255));
/*获取当前是否设置水印文字为透明背景*/
bool IsTransparent();
/*设置当前是否设置水印文字为透明背景*/
void SetTransparent(bool transparent = true);
/*获取当前用于输出水印文字的字体*/
HFONT GetTextFont();
/*设置当前用于输出水印文字的字体,返回上一次设置的字体*/
HFONT SetTextFont(HFONT hFont);
/*添加水印文字
* @lpszText:水印文本
* @x:水印文本相对图片左上角的水平位置(像素)
* @y:水印文本相对图片左上角的垂直位置(像素)
*/
void AddWaterMark(LPCTSTR lpszText, int x, int y);
/*根据选择的方式和上下左右的间距,自动添加水印文本到合适的位置,默认添加到图片右下角*/
void AddWaterMark(LPCTSTR lpszText, Location type = Location::RightBottom);
/*保存到当前操作位图文件,返回是否保存成功- 只针对以位图文件加载的情况*/
bool Save();
/*保存到指定位图文件,返回是否保存成功*/
bool Save(LPCTSTR lpszFile);
private:
/*初始化工作*/
void Init();
/*根据BITMAP句柄创建位图文件信息*/
PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp);
/*创建位图文件*/
void CreateBMPFile(HWND hwnd, LPCTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
private:
string m_imgFile; //要添加水印的图片文件
HFONT m_hFont; //水印文字的当前字体
HFONT m_hOldFont;
HFONT m_hInitFont; //水印文字的初始字体
COLORREF m_foreColor; //水印文字的文本颜色
COLORREF m_bkColor; //水印文字的背景颜色
bool m_isTransparant; //水印文字是否透明
HBITMAP m_hBmp; //HBITMAP对象
HBITMAP m_hOldBmp;
HDC m_hMemDC; //内存设备句柄
};
实现文件:
/* Copyright (C) wuchen 2011 ALL RIGHTS RESERVED.
* Author:niewucai
* Email:niewucai@126.com
* Last Update:2011/05/11
* 实现对位图图片添加文字水印功能-- 实现文件
*/
#include<stdafx.h>
#include"WaterMark.h"
CWaterMark::CWaterMark(LPCTSTR lpszImgFile)
: m_topSpacing(10),
m_rightSpacing(10),
m_bottomSpacing(10),
m_leftSpacing(10),
m_isTransparant(true),
m_foreColor(0),
m_bkColor(RGB(255, 255, 255))
{
this->m_imgFile = lpszImgFile;
//创建默认字体
m_hFont = CreateFontA(0, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, _T("宋体"));
m_hInitFont = m_hFont;
m_hBmp = (HBITMAP)LoadImage(AfxGetInstanceHandle(), lpszImgFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
Init();
}
CWaterMark::CWaterMark(UINT nIDResource)
: m_topSpacing(10),
m_rightSpacing(10),
m_bottomSpacing(10),
m_leftSpacing(10),
m_isTransparant(true),
m_foreColor(0),
m_bkColor(RGB(255, 255, 255))
{
//创建默认字体
m_hFont = CreateFontA(0, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, _T("宋体"));
m_hInitFont = m_hFont;
m_hBmp = (HBITMAP)LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(nIDResource));
Init();
}
CWaterMark::~CWaterMark()
{
SelectObject(m_hMemDC, m_hOldBmp);
SelectObject(m_hMemDC, m_hOldFont);
DeleteObject(m_hInitFont);
}
void CWaterMark::Init()
{
m_hMemDC = CreateCompatibleDC(NULL); //创建一个与屏幕内存设备兼容的内存设备
m_hOldFont = (HFONT)SelectObject(m_hMemDC, (HFONT)m_hFont);//选择默认字体
m_hOldBmp = (HBITMAP)SelectObject(m_hMemDC, m_hBmp);//选择位图到内存设备
SetBkMode(m_hMemDC, m_isTransparant ? TRANSPARENT : OPAQUE);//是否背景透明
SetTextColor(m_hMemDC, m_foreColor);//前景色
::SetBkColor(m_hMemDC, m_bkColor);//背景色
}
/*更换当前操作位图
* @nIDResouce:位图资源标识
* return:是否更换成功
*/
bool CWaterMark::ChangeBitmap(UINT nIDResource)
{
m_hBmp = (HBITMAP)LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(nIDResource));
if(!m_hBmp)
{
returnfalse;
}
m_imgFile.clear();
m_hOldBmp = (HBITMAP)SelectObject(m_hMemDC, m_hBmp);//选择位图到内存设备
returntrue;
}
/*更换当前操作位图
* @lpszImgFile:位图文件路径
* return:是否更换成功
*/
bool CWaterMark::ChangeBitmap(LPCTSTR lpszImgFile)
{
m_hBmp = (HBITMAP)LoadImage(AfxGetInstanceHandle(), lpszImgFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if(!m_hBmp)
{
returnfalse;
}
this->m_imgFile = lpszImgFile;
m_hOldBmp = (HBITMAP)SelectObject(m_hMemDC, m_hBmp);//选择位图到内存设备
returntrue;
}
/*获取当前处理位图的BITMAP结构*/
int CWaterMark::GetBitmap(BITMAP* pBitMap)
{
if(!m_hBmp)
{
return 0;
}
return CBitmap::FromHandle(m_hBmp)->GetBitmap(pBitMap);
}
/*获取水印文字的前景色*/
COLORREF CWaterMark::GetForeColor()
{
return m_foreColor;
}
/*设置水印文字的前景色*/
void CWaterMark::SetForeColor(COLORREF foreColor/* = 0*/)
{
m_foreColor = foreColor;
SetTextColor(m_hMemDC, m_foreColor);//设置前景色
}
/*获取水印文字的背景色*/
COLORREF CWaterMark::GetBkColor()
{
return m_bkColor;
}
/*设置水印文字的背景色*/
void CWaterMark::SetBkColor(COLORREF bkColor/* = RGB(255, 255, 255)*/)
{
m_bkColor = bkColor;
::SetBkColor(m_hMemDC, m_bkColor);//背景色
}
/*获取当前是否设置水印文字为透明背景*/
bool CWaterMark::IsTransparent()
{
return m_isTransparant;
}
/*设置当前是否设置水印文字为透明背景*/
void CWaterMark::SetTransparent(bool transparent/* = true*/)
{
m_isTransparant = transparent;
SetBkMode(m_hMemDC, m_isTransparant ? TRANSPARENT : OPAQUE);//是否背景透明
}
/*获取当前用于输出水印文字的字体*/
HFONT CWaterMark::GetTextFont()
{
return m_hFont;
}
/*设置当前用于输出水印文字的字体,返回上一次设置的字体*/
HFONT CWaterMark::SetTextFont(HFONT hFont)
{
m_hFont = hFont;
m_hOldFont = (HFONT)SelectObject(m_hMemDC, (HFONT)m_hFont);//设置水印文字字体
return m_hOldFont;
}
/*添加水印文字
* @lpszText:水印文本
* @x:水印文本相对图片左上角的水平位置(像素)
* @y:水印文本相对图片左上角的垂直位置(像素)
*/
void CWaterMark::AddWaterMark(LPCTSTR lpszText, int x, int y)
{
TextOut(m_hMemDC, x, y, lpszText, strlen(lpszText));
}