- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试找到一种方法来使用 Gdiplus::Graphics.DrawString 方法来创建在黑色背景上具有白色文本的位图。
(为什么?因为我需要能够旋转文本,而 Gdiplus::Graphics 对象有 RotateTransform 可用于此。)
我编写了一个示例控制台应用程序,它演示了我在尝试在黑色矩形上绘制白色文本时看到的内容。 (代码贴在下面。)
有人知道我做错了什么吗?在此先感谢您的帮助。
////////////////////////
// DrawTextTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#pragma comment (lib,"Gdiplus.lib")
#include <Windows.h>
#include <GdiPlusEnums.h>
#include <GdiPlusTypes.h>
#include <GdiPlus.h>
#include <iostream>
#include <string>
using namespace Gdiplus;
using namespace std;
bool RunTheTest(string);
bool SaveBitmapToFile(HDC, HBITMAP, BITMAPINFO&, string);
bool WriteBitmapFile(BYTE*, BITMAPINFOHEADER&, LPCTSTR);
void ShowError();
#define BUFFER_SIZE 1024
int _tmain(int argc, _TCHAR* argv[])
{
bool bRet(false);
char szBuff[BUFFER_SIZE];
size_t retVal;
string sFileName, sUserInput;
ULONG_PTR gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
if (argc > 1)
{
for (int nArg = 1; nArg < argc; nArg++)
{
wcstombs_s(&retVal, szBuff, (size_t)BUFFER_SIZE, argv[nArg], (size_t)BUFFER_SIZE );
if (nArg > 1)
sFileName += " ";
sFileName += szBuff;
}
}
else
{
cout << "Input the full path filename (do not enclose in quotes)" << endl;
cin >> sUserInput;
sFileName += sUserInput;
}
Status s = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
bRet = RunTheTest(sFileName);
GdiplusShutdown(gdiplusToken);
if (bRet)
return 0;
return 1;
}
bool RunTheTest(string sfileName)
{
BITMAPINFO bitmapInfo;
bool bRet(false);
Brush* pBlackBrush = new SolidBrush(Gdiplus::Color::Black);
Brush* pWhiteBrush = new SolidBrush(Gdiplus::Color::White);
double inchesPerMeter(39.3700787);
float fontSize(30);
Font* pFont(NULL);
FontFamily* pFontFamily(NULL);
FontStyle fs(FontStyleRegular);
HBITMAP hMemoryBitmap(NULL);
HDC hMemoryDC(NULL);
HGDIOBJ hDefaultBitmap(NULL);
int pelsPerMeter(0), resolution(240);
int oldBkMode(0);
LPTSTR pFileName(NULL);
PointF origin(0, 0);
SIZE sizeRect;
Status s;
// Initialize a memory device context compatible with the screen
hMemoryDC = CreateCompatibleDC(NULL);
// Prepare some values for creating a memory bitmap
pelsPerMeter = (int)(resolution * inchesPerMeter);
sizeRect.cx = sizeRect.cy = 400;
// Create the memory bitmap
bitmapInfo.bmiHeader.biBitCount = 24;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biXPelsPerMeter = pelsPerMeter;
bitmapInfo.bmiHeader.biYPelsPerMeter = pelsPerMeter;
bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo.bmiHeader);
bitmapInfo.bmiHeader.biWidth = sizeRect.cx;
bitmapInfo.bmiHeader.biHeight = sizeRect.cy;
hMemoryBitmap = CreateCompatibleBitmap(hMemoryDC, sizeRect.cx, sizeRect.cy);
hDefaultBitmap = SelectObject(hMemoryDC, hMemoryBitmap);
// Draw a white rectangle on the bitmap
SelectObject(hMemoryDC, GetStockObject(WHITE_BRUSH));
Rectangle(hMemoryDC, 0, 0, sizeRect.cx, sizeRect.cy);
SelectObject(hMemoryDC, GetStockObject(NULL_BRUSH));
// Set bitmap background mode to transparent mode
oldBkMode = SetBkMode(hMemoryDC, TRANSPARENT);
// Get a Graphics object from the memory device context
Graphics graphics(hMemoryDC);
// draw a black rectangle on the bitmap
s = graphics.FillRectangle(pBlackBrush, 0, 0, 400, 400);
if (s != Ok)
{
cout << "FillRectangle failed" << endl;
return false;
}
// draw white text on the black rectangle using the font we created
s = graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
if (s != Ok)
{
cout << "SetTextRenderingHint failed" << endl;
return false;
}
// Create a font object and draw the text on the bitmap
pFontFamily = new FontFamily(L"Arial");
if (pFontFamily == NULL)
{
cout << "new FontFamily failed" << endl;
return false;
}
pFont = new Font(pFontFamily, fontSize, fs);
if (pFont == NULL)
{
cout << "new Font failed" << endl;
if (pFontFamily != NULL)
delete pFontFamily;
return false;
}
s = graphics.DrawString(L"TEST STRING", 11, pFont, origin, pWhiteBrush);
if (s == Ok)
{ // Save the bitmap to a file
bRet = SaveBitmapToFile(hMemoryDC, hMemoryBitmap, bitmapInfo, sfileName);
}
// Clean up
SetBkMode(hMemoryDC, oldBkMode);
if (pFont != NULL)
delete pFont;
if (pFontFamily != NULL)
delete pFontFamily;
if (hDefaultBitmap != NULL && hMemoryBitmap != NULL)
SelectObject(hMemoryDC, hDefaultBitmap);
if (hMemoryBitmap != NULL)
DeleteObject(hMemoryBitmap);
if (hMemoryDC != NULL)
DeleteDC(hMemoryDC);
return bRet;
}
bool SaveBitmapToFile(HDC hMemoryDC, HBITMAP hMemoryBitmap, BITMAPINFO& bitmapInfo, string sFileName)
{
bool bRet(false);
DWORD dwBmpSize(0);
BYTE* pBytes(NULL);
ULONG ulcb(0);
WCHAR wchBuff[BUFFER_SIZE];
PSTR pTemp = (PSTR)wchBuff;
for (unsigned int nChar = 0; nChar < sFileName.length(); nChar++)
{
*pTemp++ = sFileName[nChar];
*pTemp++ = 0;
}
*pTemp++ = 0;
*pTemp = 0;
dwBmpSize = ((bitmapInfo.bmiHeader.biWidth * bitmapInfo.bmiHeader.biBitCount + 31) / 32) * 4 * bitmapInfo.bmiHeader.biHeight;
pBytes = new BYTE[dwBmpSize];
bRet = (GetDIBits(hMemoryDC, hMemoryBitmap, 0, bitmapInfo.bmiHeader.biHeight, &pBytes[0], &bitmapInfo, DIB_RGB_COLORS) != 0);
if (bRet)
bRet = WriteBitmapFile(pBytes, bitmapInfo.bmiHeader, wchBuff);
if (pBytes != NULL)
{
delete[] pBytes;
pBytes = NULL;
}
return bRet;
}
bool WriteBitmapFile(BYTE* pBitmapBits, BITMAPINFOHEADER& bmpInfoHeader, LPCTSTR lpszFileName)
{
BITMAPFILEHEADER bfh = {0};
bool bRet(false);
DWORD dwcb2Write(0), dwcbWritten(0);
// This value should be values of BM letters i.e 0×4D42
// 0x4D = M 0x42 = B storing in reverse order to match with endian
bfh.bfType=0x4D42;
// or...
// bfh.bfType = ‘B’+(’M’ << 8);
// <<8 used to shift ‘M’ to end
// Offset to the RGBQUAD
bfh.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER);
bfh.bfSize = bfh.bfOffBits + bmpInfoHeader.biSizeImage;
HANDLE hFile = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
cout << "CreateFile failed" << endl;
ShowError();
return false;
}
dwcb2Write = sizeof(bfh);
bRet = (WriteFile(hFile, &bfh, dwcb2Write, &dwcbWritten, NULL) != 0);
if (!bRet || (dwcbWritten != dwcb2Write))
{
cout << "WriteFile failed" << endl;
ShowError();
CloseHandle(hFile);
return false;
}
dwcb2Write = sizeof(bmpInfoHeader);
bRet = (WriteFile(hFile, &bmpInfoHeader, dwcb2Write, &dwcbWritten, NULL) != 0);
if (!bRet || (dwcbWritten != dwcb2Write))
{
cout << "WriteFile failed" << endl;
ShowError();
CloseHandle(hFile);
return false;
}
dwcb2Write = bmpInfoHeader.biSizeImage;
bRet = (WriteFile(hFile, pBitmapBits, dwcb2Write, &dwcbWritten, NULL) != 0);
if (!bRet || (dwcbWritten != dwcb2Write))
{
cout << "WriteFile failed" << endl;
ShowError();
CloseHandle(hFile);
return false;
}
CloseHandle(hFile);
return true;
}
void ShowError()
{ // Retrieve the system error message for the last-error code
char szBuff[BUFFER_SIZE];
LPTSTR lpMsgBuf;
size_t retVal;
DWORD dw = GetLastError(), dwRet(0);
dwRet = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
wcstombs_s(&retVal, szBuff, (size_t)BUFFER_SIZE, lpMsgBuf, (size_t)BUFFER_SIZE );
// Display the error message
cout << szBuff << endl;
LocalFree(lpMsgBuf);
}
最佳答案
只需先使用 Graphics::FillRectangle() 绘制矩形。从 Graphics::MeasureString() 获取所需的矩形大小。
关于c++ - 使用 Gdiplus::Graphics::DrawText 在黑色背景上绘制白色文本时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5503649/
绘制文本选项 有一个 '画' 指定是否应绘制文本的表达式。 http://www.ffmpeg.org/ffmpeg-filters.html#drawtext-1 我发现我们可以使用以下表达式在特定
我正在使用 ffmpeg 库在特定时间在视频上绘制文本,我成功了 我正在使用此命令将文本从上到下移动,但我无法确定 x 和 Y 从 x,y 移动到特定 x,y ffmpeg -i VideoInput
我们正在尝试使用 ffmpeg drawtext 来支持印地语字体。但是数据的顺序是不正确的。 印地语文本的 unicode 是这样传递的 1. पिता माता िस्रफ 但输出呈现为 Outp
我正在开发一个对 FFmpeg 进行系统调用的应用程序。 我找到了一种方法来隔离和淡出 drawtext 过滤器,但是渲染时间增加了大约 5 倍。 我只是想看看我提出的命令是否有明显错误。 ffmpe
我正在尝试设置此 FFmpeg 命令的 drawtext 何时开始,我尝试使用 start_number 但看起来它不会成功。 ffmpeg -i 1.mp4 -acodec aac -keyint_
我正在尝试使用 ffmpeg drawtext 过滤器将藏文呈现为视频。但有些字符没有正确呈现。 例如: སྤྱི་སྟེགས Expected render output 一些垂直太长的字符无法正确
我使用 shell_exec 在 PHP 中运行以下命令: ffmpeg -i $sourcePath -vf \"drawtext=text='$txt':fontfile='$fontPath':
我正在使用 ffmpeg 库在特定时间在视频上绘制文本,我成功了 我正在使用此命令将文本从上到下移动,但我无法确定 x 和 Y 从 x,y 移动到特定 x,y ffmpeg -i VideoInput
我在 ffmpeg 中为 drawtext 使用以下参数 ffmpeg -i input.gif -vf drawtext="fontfile='ariblk.ttf':text=' Hello
我必须在视频开头添加声明符几秒钟,水平居中,绿色背景,如何使用单个命令来完成并覆盖现有视频而不重新编码 最佳答案 如果您愿意将免责声明图像转换为视频剪辑,则可以将两个视频合并为一个序列而无需重新编码。
是否可以在一个 ffmpeg 命令中包含电影覆盖和绘制文本。 我尝试了命令,但它给出了错误 [drawtext @ 03B2BBC0] Key '"fontsize' not found. [draw
将一些代码从 D2007 移植到 XE2 时,我遇到了一个我无法理解的编译器错误。请参阅以下示例: procedure TForm1.FormPaint(Sender: TObject); var
如何在一张图像上显示多行 我尝试了命令,但它给出了错误 [NULL @ 0203D780] Unable to find a suitable output format for '[in][T1]'
我正在 Canvas 上绘制关于现在轮到谁的信息。我使用 validate() 两次使屏幕无效并再次绘制文本。但是使用 invalidate() 我正在重绘所有板,这会持续很长时间,有什么方法可以使
我在 Win32 程序中使用 DrawText 函数在屏幕顶部中央显示“本地”,在中央显示“服务器”。当我运行程序时,它显示“本地”而不是“服务器”。这是我的消息循环中的代码: case WM_PAI
我想在屏幕 Canvas 上绘制与第一个字符串相邻的第二个字符串。第二个字符串的起点应该是第一个字符串的宽度。我使用了Android的paint.measuretext()方法。但它返回的宽度小于实际
我的主要目标是收集用户输入并将其转换为黑色背景的视频,然后输入文本将从左向右移动,同时视频在背景中播放音频。 目前有人建议我使用“drawtext”,但我发现它不起作用。 我的命令: ffmpeg -
有没有办法检测文本何时传递给 DrawText被剪掉了? 我希望能够在给定的矩形中绘制任何文本(即已被 DrawText 剪裁,这意味着用户可能会错过文本的某些重要部分)。 我想获得显示剪切文本所需的
我正在使用 DrawText 将一些文本绘制到我在插件中制作的一堆矩形中。 现在我从嵌入式 python 接收到一个字符指针: char *a=PyString_AsString(value); 当我
我目前正在创建一个图像编辑器,并尝试使用 canvas.drawText() 在图像上绘制文本。到目前为止,我已经成功地做到了这一点,但是当用户输入太长的文本时,文本只会在页面外的一行上继续,并且不会
我是一名优秀的程序员,十分优秀!