Reputation: 759
I have a couple of bitmaps/pngs (screenshots), which I would like to "wrap" in EMFs having a specific width in millimeters (and a proportional height). Ideally, I would also want to add some overlays (text & rectangles).
Creating and saving an EMF seems to generally work fine, but I am unable to get any of the scaling right.
Here is my code:
var sourceBitmap = Image.FromFile(@"C:\temp\example.png");
Metafile metafile;
var aspectRatio = (float)sourceBitmap.Height / (float)sourceBitmap.Width;
var size = new Size(200, (int) (200*aspectRatio));
using (var stream = new MemoryStream())
{
using (var offScreenBufferGraphics = Graphics.FromHwndInternal(IntPtr.Zero))
{
IntPtr deviceContextHandle = offScreenBufferGraphics.GetHdc();
metafile = new Metafile(stream, deviceContextHandle, new RectangleF(0, 0, size.Width, size.Height), MetafileFrameUnit.Millimeter, EmfType.EmfPlusOnly); // this allocates one gdi object
offScreenBufferGraphics.ReleaseHdc();
using (var graphics = Graphics.FromImage(metafile))
{
graphics.PageUnit = GraphicsUnit.Millimeter;
// may need to do something with ScaleTransform here??
var metafileHeader = metafile.GetMetafileHeader();
float sx = metafileHeader.DpiX / graphics.DpiX;
float sy = metafileHeader.DpiY / graphics.DpiY;
graphics.ScaleTransform(sx, sy);
graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), new Rectangle(0, 0, size.Width, size.Height), GraphicsUnit.Pixel);
var pen1 = new Pen(new SolidBrush(Color.Blue));
var pen2 = new Pen(new SolidBrush(Color.Red));
graphics.DrawRectangle(pen1, 0, 0, size.Width, size.Height);
graphics.DrawLine(pen2, 0, 0, size.Width, size.Height);
graphics.DrawLine(pen2, 0, size.Height, size.Width, 0);
graphics.Dispose();
}
}
}
// save as a metafile
IntPtr metafileHandle = metafile.GetHenhmetafile();
var result = Gdi32.CopyEnhMetaFile(metafileHandle, @"C:\temp\example.emf");
if (result.ToInt32() == 0)
{
var error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}
Gdi32.DeleteEnhMetaFile(result);
Gdi32.DeleteEnhMetaFile(metafileHandle);
Neither are the rectangle and diagonal lines correct, nor is the source bitmap correctly filled into the EMF. What am I doing wrong here?
The final EMF should be embedded into a Word document - hence the specific width. Note that I do not want to downsize the bitmaps and include these directly, since I would likely loose quality this way. Also note that I do not want to include the full bitmap in Word and have it adjust/scale the image, as I need to use {includepicture} which does not seem to reliably work with scaling.
Upvotes: 1
Views: 569
Reputation: 80
I tried your code, the rectangle and diagonal lines are correct.
After changed(swaped param destRect
and srcRect
) the following code
graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), new Rectangle(0, 0, size.Width, size.Height), GraphicsUnit.Pixel);
to
graphics.DrawImage(sourceBitmap, new Rectangle(0, 0, size.Width, size.Height), new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), GraphicsUnit.Pixel);
The source bitmap correctly filled into the EMF.
Upvotes: 1