先看效果图:
参考了另一篇C#的文章:https://blog.csdn.net/shenqiankk/article/details/99636425,本文将其大致翻译到VC
1 项目肯定要包含gdi+头文件
#include <GdiPlus.h>
#pragma comment(lib, "gdiplus.lib")
2 初始化gdi+
ULONG_PTR m_gdiplusToken;
Gdiplus::GdiplusStartupInput StartupInput;
GdiplusStartup(&m_gdiplusToken,&StartupInput,NULL);
3 相关代码
bool GetEncoderClsid2(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0, size = 0;
Gdiplus::GetImageEncodersSize(&num, &size);
if(size == 0)
return -1; // Failure
Gdiplus::ImageCodecInfo* pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);
bool found = false;
for (UINT ix = 0; !found && ix < num; ++ix)
{
if (_wcsicmp(pImageCodecInfo[ix].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[ix].Clsid;
found = true;
break;
}
}
free(pImageCodecInfo);
return found;
}
int RangedRand(int range_min, int range_max)
{
int u = (double)rand() / (RAND_MAX + 1) * (range_max - range_min)
+ range_min;
return u;
}
DWORD GetMsInterval(DWORD dwNow, DWORD dwLast)
{
if( dwNow < dwLast )
return 0xFFFFFFFF - dwLast + dwNow;
else
return dwNow - dwLast;
}
//生成的代码
void GenerateCode()
{
DWORD dwBegin = GetTickCount();
using namespace Gdiplus;
wchar_t toDrawText[64] = {0};
swprintf_s(toDrawText, 63, L"%d", RangedRand(1000, 9999));
Gdiplus::Bitmap bmp(120, 40, PixelFormat32bppARGB);
Graphics g(&bmp);
for (int i = 0; i < bmp.GetWidth(); i++)
{
for (int j = 0; j < bmp.GetHeight(); j++){
bmp.SetPixel(i, j, Color::Transparent);
}
}
std::vector<std::wstring> fonts;
fonts.push_back(L"微软雅黑");
fonts.push_back(L"宋体");
fonts.push_back(L"楷体");
fonts.push_back(L"仿宋");
std::vector<DWORD> colors;
colors.push_back(Color::Yellow);
colors.push_back(Color::Blue);
colors.push_back(Color::Red);
colors.push_back(Color::Green);
colors.push_back(Color::Purple);
int len = wcslen(toDrawText);
for (int i = 0; i < len; i++)
{
Gdiplus::PointF p(i * 20, 0);
Color clr;
clr.SetFromCOLORREF(colors[rand() % colors.size()]);
g.DrawString(toDrawText + i,
1,
&Gdiplus::Font(&FontFamily(fonts[rand() % fonts.size()].c_str()), 25, Gdiplus::FontStyleBold, Gdiplus::Unit::UnitPoint),
p,
&SolidBrush(clr));
}
// 干扰线
Color lineColor(colors[rand() % colors.size()]); //随机颜色
for (int i = 0; i < 3; i++){
PointF p1(RangedRand(0, bmp.GetWidth()), RangedRand(0, bmp.GetHeight()));
PointF p2(RangedRand(0, bmp.GetWidth()), RangedRand(0, bmp.GetHeight()));
g.DrawLine(&Gdiplus::Pen(lineColor), p1, p2);
}
Color lineColor2(colors[rand() % colors.size()]);
for (int i = 0; i < 3; i++){
PointF p1(RangedRand(0, bmp.GetWidth()), RangedRand(0, bmp.GetHeight()));
PointF p2(RangedRand(0, bmp.GetWidth()), RangedRand(0, bmp.GetHeight()));
g.DrawLine(&Gdiplus::Pen(lineColor2), p1, p2);
}
// 干扰点
for (int i = 0; i < 500; i++)
{
PointF p(RangedRand(0, bmp.GetWidth()), RangedRand(0, bmp.GetHeight()));
bmp.SetPixel(p.X, p.Y, Color::Black);
}
IStream* pIStream = NULL;
CreateStreamOnHGlobal(NULL, TRUE, &pIStream);
std::vector<BYTE> data;
CLSID clsID = GUID_NULL;
wchar_t ext[_MAX_EXT] = {0};
wchar_t format[_MAX_EXT] = {L"image/"};
std::wstring strPicPath = L"E:\\my2.png";
_wsplitpath_s(strPicPath.c_str(), NULL, 0, NULL, 0, NULL, 0, ext, _MAX_EXT);
wcscat_s(format, _MAX_EXT, ext + 1);
if (GetEncoderClsid2(format, &clsID))
{
Gdiplus::Status status = bmp.Save(pIStream, &clsID);
if (status != Gdiplus::Status::Ok)
return;
HGLOBAL hg = NULL;
GetHGlobalFromStream(pIStream, &hg);
int bufSize = GlobalSize(hg);
data.resize(bufSize);
LPVOID pImage = GlobalLock(hg);
memcpy(&data[0], pImage, bufSize);
GlobalUnlock(hg);
pIStream->Release();
//printf("success\n");
//bmp.Save(strPicPath.c_str(), &clsID, NULL);
}
else{
printf("failed\n");
}
}
代码里,显示绘制数字,核心函数Graphics::DrawText,然后是绘制干扰线和干扰点,后面是测试保存到本地或字节流。
缺少啥头文件酌情添加。