我正在使用第三方库将图像渲染到 GDI DC 上,需要确保任何文本都不带有平滑/反走样,以便我可以将图像转换为具有索引颜色的预定义调色板。
我正在使用的第三方库不支持这种渲染方式,只会按照当前的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);
这显然对操作系统有可怕的影响,每次我渲染图像时,其他应用程序都会从启用清晰类型到禁用,反复闪烁。
所以问题是,有人知道我如何更改特定DC的字体呈现设置吗?
即使我只能将更改过程或线程特定化,而不是影响整个操作系统,那也是一个重要的步骤!(这会使我有选择将这个渲染过程交给一个单独的进程-渲染后的结果仍将写入磁盘)
编辑: 我想添加,如果解决方案比只使用几个 API 调用更复杂,我也不介意。如果只需要一天的工作,即使涉及挂接系统 dlls 的解决方案,我也会很高兴。
EDIT: Background Information The third-party library renders using a palette of about 70 colors. After the image (which is actually a map tile) is rendered to the DC, I convert each pixel from it s 32-bit color back to it s palette index and store the result as an 8bpp greyscale image. This is uploaded to the video card as a texture. During rendering, I re-apply the palette (also stored as a texture) with a pixel shader executing on the video card. This allows me to switch and fade between different palettes instantaneously instead of needing to regenerate all the required tiles. It takes between 10-60 seconds to generate and upload all the tiles for a typical view of the world.
EDIT: Renamed GraphicsDevice to Graphics The class GraphicsDevice in the previous version of this question is actually System.Drawing.Graphics. I had renamed it (using GraphicsDevice = ...) because the code in question is in the namespace MyCompany.Graphics and the compiler wasn t able resolve it properly.
EDIT: Success!
I even managed to port the PatchIat
function below to C# with the help of Marshal.GetFunctionPointerForDelegate
. The .NET interop team really did a fantastic job! I m now using the following syntax, where Patch
is an extension method on 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];
}