我正在使用第三方库将图像渲染到GDI DC上,我需要确保任何文本都不被平滑处理/抗锯齿,这样我就可以将图像转换为预定义调色板中的索引颜色。
我使用的渲染第三方库不支持此功能,只按照当前Windows字体渲染设置呈现文本。他们还表示,他们不太可能很快添加关闭反走样的能力。
我目前找到的最佳解决方法是以这种方式调用第三方库(出于简洁起见省略了错误处理和先前的设置检查):
我使用的渲染第三方库不支持此功能,只按照当前Windows字体渲染设置呈现文本。他们还表示,他们不太可能很快添加关闭反走样的能力。
我目前找到的最佳解决方法是以这种方式调用第三方库(出于简洁起见省略了错误处理和先前的设置检查):
private static void SetFontSmoothing(bool enabled)
{
int pv = 0;
SystemParametersInfo(Spi.SetFontSmoothing, enabled ? 1 : 0, ref pv, Spif.None);
}
// snip
Graphics graphics = Graphics.FromImage(bitmap)
IntPtr deviceContext = graphics.GetHdc();
SetFontSmoothing(false);
thirdPartyComponent.Render(deviceContext);
SetFontSmoothing(true);
这显然对操作系统产生了可怕的影响,每次渲染图像时,其他应用程序都会从ClearType启用到禁用,然后再切换回来。
那么问题是,有没有人知道我如何为特定的DC更改字体呈现设置?
即使我只能使更改进程或线程特定而不影响整个操作系统,这也将是一个重要的步骤!(这将使我有机会将此呈现外包给单独的进程-无论如何,结果都将被写入磁盘)
编辑:我想补充一下,如果解决方案比几个API调用更复杂,我也不介意。即使涉及挂钩系统dll的解决方案,只要可以完成一天的工作,我也很高兴。
编辑:背景信息
第三方库使用大约70种颜色的调色板进行渲染。在图像(实际上是地图块)渲染到DC之后,我将每个像素从其32位颜色转换回其调色板索引,并将结果存储为8bpp灰度图像。这被上传到视频卡作为纹理。在渲染期间,我使用像素着色器在视频卡上重新应用调色板(也存储为纹理)。这使我能够立即在不需要重新生成所有所需的瓷砖的情况下在不同的调色板之间切换和淡入淡出。为典型的世界视图生成和上传所有瓦片需要花费10-60秒。
编辑:将GraphicsDevice重命名为Graphics
上一个版本中的GraphicsDevice类实际上是System.Drawing.Graphics。我已经重命名了它(使用GraphicsDevice = ...),因为涉及到的代码位于MyCompany.Graphics命名空间中,编译器无法正确解析它。
编辑:成功!
我甚至成功地将下面的PatchIat函数移植到C#中,并借助Marshal.GetFunctionPointerForDelegate的帮助。.NET互操作团队确实做得非常好!我现在正在使用以下语法,其中Patch是System.Diagnostics.ProcessModule的扩展方法:module.Patch(
"Gdi32.dll",
"CreateFontIndirectA",
(CreateFontIndirectA original) => font =>
{
font->lfQuality = NONANTIALIASED_QUALITY;
return original(font);
});
private unsafe delegate IntPtr CreateFontIndirectA(LOGFONTA* lplf);
private const int NONANTIALIASED_QUALITY = 3;
[StructLayout(LayoutKind.Sequential)]
private struct LOGFONTA
{
public int lfHeight;
public int lfWidth;
public int lfEscapement;
public int lfOrientation;
public int lfWeight;
public byte lfItalic;
public byte lfUnderline;
public byte lfStrikeOut;
public byte lfCharSet;
public byte lfOutPrecision;
public byte lfClipPrecision;
public byte lfQuality;
public byte lfPitchAndFamily;
public unsafe fixed sbyte lfFaceName [32];
}