禁用反锯齿为特定的GDI设备上下文 [英] Disable antialiasing for a specific GDI device context

查看:532
本文介绍了禁用反锯齿为特定的GDI设备上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是第三方库来渲染到GDI DC的图像,我需要确保任何文本没有任何平滑/抗锯齿渲染,这样我可以将图像转换为与索引颜色预定义的调色板。


>我使用的渲染第三方库不支持这一点,只是呈现文本中为每个字体渲染当前的Windows设置。他们还表示,它不太可能他们会添加切换很快抗锯齿关闭任何时候的能力。



我周围的最好的工作已经找到了迄今调用这样的第三方库(错误处理和以前设置的检查ommitted为了简洁):

 私有静态无效SetFontSmoothi​​ng(布尔启用)
{
INT PV = 0;
SystemParametersInfo(Spi.SetFontSmoothi​​ng,支持1:0,参考PV,Spif.None?);
}

//剪断
显卡显卡= Graphics.FromImage(位图)
IntPtr的deviceContext = graphics.GetHdc();

SetFontSmoothi​​ng(假);
thirdPartyComponent.Render(deviceContext);
SetFontSmoothi​​ng(真);

这显然有在操作系统上一个可怕的影响,其他应用程序的ClearType闪烁启用禁用和背部每次我呈现图像。



所以现在的问题是,没有人知道我可以改变字体渲染设置一个特定的DC?



即使我可以只进行修改进程或线程特定的,而不是影响整个操作系统,这将是向前迈进了一大步! (这会给我这个养殖呈现出一个单独的流程 - 结果呈现后反正写入到磁盘的选项)



编辑:我想补充一点,如果该解决方案不仅仅是几个API调用更复杂,我不介意。 ,我甚至会很高兴,涉及挂钩系统DLL,如果它是只有一天的工作的解决方案



编辑:背景资料
中的第三方库呈现使用约70颜色的调色板。图像(这实际上是一个地图切片)呈现到DC后,我将每个像素从它的32位颜色回到它的调色板索引,并将结果作为8bpp灰度图像。这被上传到视频卡作为纹理。在渲染过程中,我重新申请与视频卡上的像素着色器执行调色板(也存储为一个纹理)。这让我和切换不同的调色板之间褪色需要重新生成所有需要的瓷砖瞬间来代替。它需要10-60秒之间产生并上传所有的瓷砖,为世界的典型视图



编辑:重命名的GraphicsDevice为图形
在以前的版本这个问题的类GraphicsDevice的实际上是System.Drawing.Graphics。我给它改名(使用GraphicsDevice的= ...),因为有问题的代码是在命名空间MyCompany.Graphics,编译器无法解析正确。



修改:成功
我甚至设法端口下的 PatchIat 函数C#与的帮助元帅.GetFunctionPointerForDelegate 。在.NET互操作团队真的做了出色的工作!现在,我使用下面的语法,其中补丁是一个扩展方法 System.Diagnostics.ProcessModule

  module.Patch(
GDI32.DLL,
CreateFontIndirectA,
(CreateFontIndirectA原)=> FONT = GT;
{
字体 - > lfQuality = NONANTIALIASED_QUALITY;
返回原(字体);
});

私人不安全委托的IntPtr CreateFontIndirectA(LOGFONTA * lplf);

私人const int的NONANTIALIASED_QUALITY = 3;

[StructLayout(LayoutKind.Sequential)]
私人结构LOGFONTA
{
公众诠释lfHeight;
公众诠释lfWidth;
公众诠释lfEscapement;
公众诠释lfOrientation;
公众诠释lfWeight;
公共字节lfItalic;
公共字节lfUnderline;
公共字节lfStrikeOut;
公共字节为lfcharset;
公共字节lfOutPrecision;
公共字节lfClipPrecision;
公共字节lfQuality;
公共字节lfPitchAndFamily;
公共不安全固定为sbyte lfFaceName [32];
}


解决方案

按照要求,我已经打包了代码我写来解决这个问题,并把它放在一个GitHub的仓库: http://github.com/ jystic /补丁IAT



它看起来像一个大量的代码,因为我不得不重现所有的Win32结构这个东西的工作,并在时间我选择了把每一个在其自己的文件



如果您想直接进入的代码的肉它在: ImportAddressTable。 CS



这是非常自由许可,是所有意图和目的,公共领域,可以随意在任何你喜欢的项目中使用它


I'm using a third party library to render an image to a GDI DC and I need to ensure that any text is rendered without any smoothing/antialiasing so that I can convert the image to a predefined palette with indexed colors.

The third party library i'm using for rendering doesn't support this and just renders text as per the current windows settings for font rendering. They've also said that it's unlikely they'll add the ability to switch anti-aliasing off any time soon.

The best work around I've found so far is to call the third party library in this way (error handling and prior settings checks ommitted for brevity):

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);

This obviously has a horrible effect on the operating system, other applications flicker from cleartype enabled to disabled and back every time I render the image.

So the question is, does anyone know how I can alter the font rendering settings for a specific DC?

Even if I could just make the changes process or thread specific instead of affecting the whole operating system, that would be a big step forward! (That would give me the option of farming this rendering out to a separate process- the results are written to disk after rendering anyway)

EDIT: I'd like to add that I don't mind if the solution is more complex than just a few API calls. I'd even be happy with a solution that involved hooking system dlls if it was only about a days work.

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];
}

解决方案

As requested, I have packaged up the code I wrote to solve this problem and placed it in a github repository: http://github.com/jystic/patch-iat

It looks like a lot of code because I had to reproduce all the Win32 structures for this stuff to work, and at the time I chose to put each one in its own file.

If you want to go straight to the meat of of the code it's in: ImportAddressTable.cs

It's licensed very freely and is for all intents and purposes, public domain, so feel free to use it in any project that you like.

这篇关于禁用反锯齿为特定的GDI设备上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆