MHOOS
MHOOS

Reputation: 5306

Re-size a Placeable Metafile

I know that standard WMF file uses an 18-byte header followed by GDI command records. A simple web search tells me that : "There are two additional WMF variations that place another header in front of the standard header. A Placeable Metafile uses a 22-byte header containing x-y coordinates for positioning the image on the page". but I kind of don't understaffed the real life application for such meta file type? What kind of requirements is this type supposed to address in comparison to the standard WMF? Why am I interested? I have the following code for re-sizing and converting a WMF to GIF which fails at the point it tries to construct the bitmap out of the META file:

    public Stream Resize(string filePath, int maxSize)
    {
        try
        {
            MemoryStream stream = new MemoryStream();

            using (Metafile img = new Metafile(filePath))
            {
                MetafileHeader header = img.GetMetafileHeader();
                float scale = header.DpiX / 96f;

                var newSize = CalcaulateSize(img.Width, img.Height, maxSize);

                using (Bitmap bitmap = new Bitmap((int)(scale * img.Width / header.DpiX * 100), (int)(scale * img.Height / header.DpiY * 100)))
                {
                    using (Graphics g = Graphics.FromImage(bitmap))
                    {
                        g.Clear(Color.White);
                        g.ScaleTransform(scale, scale);
                        g.DrawImage(img, 0, 0);
                    }

                    var resizedBitmap = new Bitmap(newSize.Width, newSize.Height);

                    using (var g2 = Graphics.FromImage(resizedBitmap))
                    {
                        g2.CompositingQuality = CompositingQuality.HighQuality;
                        g2.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g2.SmoothingMode = SmoothingMode.AntiAlias;
                        g2.PixelOffsetMode = PixelOffsetMode.HighQuality;
                        g2.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
                        g2.TextContrast = 12;
                        g2.Clear(Color.White);
                        g2.DrawImage(bitmap, 0, 0, newSize.Width, newSize.Height);
                    }

                    resizedBitmap.Save(stream, ImageFormat.Gif);
                }

                stream.Position = 0;
            }

            return stream;
        }
        catch (Exception)
        {
            return null;
        }

and raises the exception "Argument is not valid".

(int)(scale * img.Width / header.DpiX * 100) = 22181 (int)(scale * img.Height / header.DpiY * 100)) = 33718

[too much memory to be allocated for a single bitmap all at once which results in immediate exception]

How would you alter the attached code to re-size and convert a place-able meta file?

Upvotes: 0

Views: 651

Answers (1)

jschroedl
jschroedl

Reputation: 4986

I'd suspect that your size calculation is off.

Looking at my C++ code, I have this calculation based on the information in the enhanced metafile header where hEMF is the handle of the metafile. We then draw the image using a Graphics directly to the screen using those dimensions.

Hope this or the MSDN link helps a little. Sorry it's not more complete.

        ENHMETAHEADER emh;
    UINT nBytes = ::GetEnhMetaFileHeader(hEMF, sizeof(ENHMETAHEADER), &emh);
    if (nBytes != 0) {
        RECT rect{ // Based on info from http://support.microsoft.com/kb/230675
            (int) ((float) (emh.rclFrame.left) * emh.szlDevice.cx / (emh.szlMillimeters.cx*100.0f)),    // Left
            (int) ((float) (emh.rclFrame.top) * emh.szlDevice.cy / (emh.szlMillimeters.cy*100.0f)),     // Top
            (int) ((float) (emh.rclFrame.right) * emh.szlDevice.cx / (emh.szlMillimeters.cx*100.0f)),   // Right
            (int) ((float) (emh.rclFrame.bottom) * emh.szlDevice.cy / (emh.szlMillimeters.cy*100.0f))   // Bottom
        };
        bounds.x = abs(rect.right - rect.left);
        bounds.y = abs(rect.bottom - rect.top);

Upvotes: 0

Related Questions