Beim Zeichnen einer Metadatei in Grafiken mit Einheitenkonvertierung werden Grenzen ignoriertC#

Ein Treffpunkt für C#-Programmierer
Anonymous
 Beim Zeichnen einer Metadatei in Grafiken mit Einheitenkonvertierung werden Grenzen ignoriert

Post by Anonymous »

Wir verwenden FastReports und seinen ImageExporter, um Bilder zu generieren, die dann an bestimmten Stellen auf einem PrintDocument gedruckt werden. Wir verwenden Metafile als Bildformat, um alles effizient zu halten. FastReports führt unter der Haube einige Bitmap-Skalierungstricks durch, um die Metadatei zu generieren, aber wenn wir die Metadatei in ein pixelbasiertes PNG exportieren, erhalten wir genau das Ergebnis, das wir wollen.
Uns ist jetzt aufgefallen, dass es unerwünschte Ränder gibt, wenn wir die exportierte Metadatei auf ein millimeterbasiertes Zielgrafikobjekt zeichnen (das beim Drucken verwendet wird). Es scheint, dass GDI zu viel Inhalt aus der Quellmetadatei übernimmt. Wir legen daher ein Quellrechteck fest und setzen GraphicsUnit auf Pixel, wenn wir das Bild zum Ziel zeichnen. Dies hat dazu geführt, dass die oberen und linken Ränder verschwunden sind, aber die Ränder unten und rechts werden immer noch angezeigt.
Ich möchte betonen, dass wir viel mehr Rand erhalten als das übliche 1-Pixel-Interpolationsproblem, das Leute, die mit GDI zu tun haben, oft quält. Die üblichen Tricks mit Interpolation und Pixel-Offset-Einstellungen haben nicht geholfen.
Ich habe ein kurzes Programm geschrieben, das das Problem veranschaulicht. Entschuldigung für den langen Beitrag, aber ich werde Sie Schritt für Schritt durch den Artikel führen.
Den vollständigen Code finden Sie hier: https://dotnetfiddle.net/mpF0in
Quellgröße
Das Quellbild wird in Pixeln mit einer Abmessung von 500 x 250 generiert.

Code: Select all

const int SrcWidthPx = 500;
const int SrcHeightPx = 250;

var srcRectPx = new Rectangle(0, 0, SrcWidthPx, SrcHeightPx);
Generieren der Quellmetadatei
Ich erzeuge eine Metadatei mit der angegebenen Quellgröße als Rahmenrechteck und Pixeln als Einheit und zeichne ein Bild darauf.

Code: Select all

const string MetaFileName = "metafile.emf";

using (var referenceGraphics = Graphics.FromHwnd(IntPtr.Zero))
{
IntPtr hdc = referenceGraphics.GetHdc();
try
{
using var metafile = new Metafile(MetaFileName,
hdc,
srcRectPx,
MetafileFrameUnit.Pixel,
EmfType.EmfPlusDual);

using var g = Graphics.FromImage(metafile);

DrawImage(g, srcRectPx);
}
finally
{
referenceGraphics.ReleaseHdc(hdc);
}
}
Generieren der Quellbitmap
Zum Vergleich erzeuge ich auch eine Bitmap mit der angegebenen Quellgröße und zeichne das gleiche Bild darauf.

Code: Select all

const string BitmapFileName = "bitmap.bmp";

using (var bitmap = new Bitmap(srcRectPx.Width, srcRectPx.Height))
{
using var g = Graphics.FromImage(bitmap);

DrawImage(g, srcRectPx);

bitmap.Save(BitmapFileName, ImageFormat.Bmp);
}
Zeichnen des endgültigen Bildes
Ich erstelle dann eine PNG-Datei für jedes Quellbild mit einem millimeterbasierten Grafikobjekt und zeichne das Quellbild in das Ziel. Die Einheit und Größe des Ziels ist unterschiedlich, aber das Seitenverhältnis ist dasselbe wie das der Quelle.
Ich lösche den PNG-Hintergrund in Orange. Wenn die Quelle das gesamte Ziel ausfüllt, sollte kein Pixel orange sein.

Code: Select all

const int DestWidthMm = 20;
const int DestHeightMm = 10;
const float Dpi = 300f;

var destRectMm = new RectangleF(0, 0, DestWidthMm, DestHeightMm);
var destRectPx = new Rectangle(0, 0, (int)Math.Floor(DestWidthMm / 25.4f * Dpi), (int)Math.Floor(DestHeightMm / 25.4f * Dpi));

foreach (var fileName in new[] { MetaFileName, BitmapFileName })
{
using var srcImage = Image.FromFile(fileName);

using var destImage = new Bitmap(destRectPx.Width, destRectPx.Height, PixelFormat.Format32bppArgb);
destImage.SetResolution(Dpi, Dpi);

using (var gDest = Graphics.FromImage(destImage))
{
gDest.PageUnit = GraphicsUnit.Millimeter; //

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post