Estoy utilizando una biblioteca de terceros para representar una imagen en un GDI DC y necesito asegurarme de que cualquier texto se representa sin suavizado/antialiasing para poder convertir la imagen a una paleta predefinida con colores indexados.Desactivar antialiasing para un contexto de dispositivo GDI específico
La biblioteca de terceros que estoy utilizando para el procesamiento no es compatible con esto y solo representa el texto según la configuración actual de Windows para la representación de fuentes. También dijeron que es poco probable que agreguen la capacidad de desactivar el anti-aliasing en el corto plazo.
El mejor trabajo en todo lo que he encontrado hasta ahora es llamar a la biblioteca de terceros de esta manera (manejo de errores y controles de ajustes previos omitido por razones de brevedad):
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);
Obviamente, esto tiene un efecto horrible en el sistema operativo, otras aplicaciones parpadean desde cleartype habilitado a desactivado y viceversa cada vez que renderizo la imagen.
Entonces, la pregunta es, ¿alguien sabe cómo puedo alterar la configuración de representación de fuente para un DC específico?
Incluso si pudiera hacer el proceso de cambios o el hilo específico en lugar de afectar todo el sistema operativo, ¡eso sería un gran paso adelante! (Eso me daría la opción de la agricultura de esta traducción a un proceso- por separado los resultados se escriben en el disco después de la prestación de todos modos)
EDIT: me gustaría añadir que no me importa si la solución es más complejo que solo unas pocas llamadas API. Incluso estaría contento con una solución que implicara conectar dlls del sistema si solo fuera un día de trabajo.
EDITAR: Información de fondo La biblioteca de terceros representa usando una paleta de aproximadamente 70 colores. Después de que la imagen (que en realidad es un mosaico de mapa) se represente en el DC, convierto cada píxel de su color de 32 bits a su índice de paleta y almaceno el resultado como una imagen de escala de grises de 8bpp. Esto se carga en la tarjeta de video como una textura. Durante el renderizado, vuelvo a aplicar la paleta (también almacenada como una textura) con un sombreador de píxeles que se ejecuta en la tarjeta de video. Esto me permite cambiar y fundir instantáneamente diferentes paletas en lugar de tener que volver a generar todas las fichas requeridas. Se tarda entre 10-60 segundos para generar y cargar todas las fichas para una vista típica del mundo.
EDIT: GraphicsDevice Renombrado de Gráficos El GraphicsDevice clase en la versión anterior de esta pregunta es en realidad System.Drawing.Graphics. Le cambié el nombre (usando GraphicsDevice = ...) porque el código en cuestión está en el espacio de nombres MyCompany.Graphics y el compilador no pudo resolverlo correctamente.
EDIT: ¡Éxito! Incluso pude portar la función PatchIat
a continuación a C# con la ayuda de Marshal.GetFunctionPointerForDelegate
. ¡El equipo de interoperabilidad de .NET realmente hizo un trabajo fantástico! Ahora estoy usando la siguiente sintaxis, donde Patch
es un método de extensión en 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];
}
si este código resolvió el problema, probablemente debería Marque su propia respuesta como la respuesta aceptada. –
@Justin, sí, buen punto. Como se puede ver en las fechas, no puse el código C# hasta un año después, así que no pensé en hacer eso en ese momento. Espero que @Chris Becke no pierda representante por la respuesta que se reasigne, nunca hubiera resuelto este problema sin su ayuda. –
¡Bien hecho! Tenga en cuenta que esto también funciona en la plataforma x64 pero necesita modificar ligeramente la estructura de ImageOptionalHeader ya que el campo _BaseOfData_ no está presente en IMAGE_OPTIONAL_HEADER64. – Poustic