我正在使用第三方库将图像渲染到GDI DC,我需要确保在没有任何平滑/抗锯齿的情况下渲染任何文本,以便我可以将图像转换为带有索引颜色的预定义调色板.
我用于渲染的第三方库不支持这个,只是根据字体渲染的当前窗口设置呈现文本.他们还表示他们不太可能在短时间内添加切换抗锯齿功能.
到目前为止,我发现的最好的工作是以这种方式调用第三方库(为简洁起见,省略了错误处理和先前的设置检查):
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);
Run Code Online (Sandbox Code Playgroud)
这显然对操作系统产生了可怕的影响,每次我渲染图像时,其他应用程序都会从禁用的cleartype闪烁到禁用和返回.
所以问题是,有没有人知道如何改变特定DC的字体渲染设置?
即使我可以只进行更改过程或线程而不是影响整个操作系统,这将是向前迈出的一大步!(这样我就可以选择将这个渲染转换为一个单独的进程 - 无论如何都会在渲染后将结果写入磁盘)
编辑:我想补充一点,我不介意解决方案是否比一些API调用更复杂.我甚至会对一个解决方案感到满意,如果它只用了一天工作就会挂钩系统dll.
编辑:背景信息 第三方库使用约70种颜色的调色板渲染.在将图像(实际上是地图图块)渲染到DC之后,我将每个像素从其32位颜色转换回其调色板索引,并将结果存储为8bpp灰度图像.这将作为纹理上传到视频卡.在渲染过程中,我重新应用了调色板(也存储为纹理),并在视频卡上执行了像素着色器.这允许我立即在不同的调色板之间切换和淡入淡出,而不需要重新生成所有需要的切片.生成并上传所有瓷砖需要10-60秒才能获得典型的世界观.
编辑:将GraphicsDevice重命名为图形 此问题的先前版本中的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 …Run Code Online (Sandbox Code Playgroud)