Масштабирование растрового изображения в EMF через System.Drawing с указанием c ширина в миллиметрах? - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть пара растровых изображений / снимков (скриншотов), которые я хотел бы «обернуть» в ЭДС, имеющие определенную ширину c в миллиметрах (и пропорциональную высоту). В идеале я также хотел бы добавить несколько оверлеев (текст и прямоугольники).

Создание и сохранение ЭМП, как правило, работают нормально, но я не могу правильно настроить масштабирование.

Вот мой код:

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

Ни прямоугольник, ни диагональные линии не верны, а исходное растровое изображение не правильно заполнено в EMF. Что я здесь не так делаю?

Окончательный ЭДС должен быть встроен в документ Word - следовательно, указана c ширина. Обратите внимание, что я не хочу уменьшать размер растровых изображений и включать их напрямую, так как я, вероятно, потеряю качество таким образом. Также обратите внимание, что я не хочу включать в Word полный растровый файл и заставлять его настраивать / масштабировать изображение, так как мне нужно использовать {includepicture}, который, похоже, не работает надежно с масштабированием.

...