Click here to Skip to main content
15,846,211 members
Please Sign up or sign in to vote.
0.00/5 (No votes)

I am trying to change the color of an existing metafile(.emf) file from my machine and save it as another modified copy. I am able to render the run time metafile on the windows form but haven't been able to save it on my machine.

I have attached my code below and would be grateful if somebody can help.

What I have tried:

        static extern IntPtr CopyEnhMetaFile(  // Copy EMF to file
         IntPtr hemfSrc,   // Handle to EMF
         String lpszFile // File

        static extern int DeleteEnhMetaFile(  // Delete EMF
          IntPtr hemf // Handle to EMF
        static extern uint GetEnhMetaFileBits(IntPtr hemf, uint cbBuffer,
        [Out] byte[] lpbBuffer);

        private void PicModified_Paint(object sender, PaintEventArgs e)
            Graphics g = e.Graphics;
            float[][] matrixColTrans =
                        new float[] {0, 0, 0, 0, 0}
                        , new float[] {0, 0, 0, 0, 0}
                        , new float[] {0, 0, 0, 0, 0}
                        , new float[] {0, 204, 0, 1, 0}
                        , new float[] {0, 0, 0, 0, 0}
            ColorMatrix colorMatrix = new ColorMatrix(matrixColTrans);

            ImageAttributes ia = new ImageAttributes();

            if (txtSelectEMFFilePath.Text.EndsWith(".emf"))
                string destFileName = txtSelectEMFFilePath.Text;
                Metafile mf = new Metafile(destFileName);
                    , new Rectangle(0, 0, picModified.Width, picModified.Height)// destination rectangle 
                    , 0, 0 // upper-left corner of source rectangle 
                    , mf.PhysicalDimension.Width // width of source rectangle
                    , mf.PhysicalDimension.Height // height of source rectangle
                    , GraphicsUnit.Pixel
                    , ia
                // Save it as a metafile
                IntPtr iptrMetafileHandle = mf.GetHenhmetafile();

                // Export metafile to an image file
                IntPtr iptrMetafileHandleCopy = CopyEnhMetaFile(iptrMetafileHandle, "image.emf");
                //Binding Output file
                Image newimg = new Metafile("image.emf");
                imgOut.Image = newimg;
                imgOut.SizeMode = PictureBoxSizeMode.Zoom;

                //// Delete the metafile from memory

                //1. End 
Updated 17-Jul-19 9:16am

1 solution

You need to get a separate encoder for this; as GDI+ cannot save those types of metafiles
Microsoft Docs:
If no encoder exists for the file format of the image, the Portable Network Graphics (PNG) encoder is used. When you use the Save method to save a graphic image as a Windows Metafile Format (WMF) or Enhanced Metafile Format (EMF) file, the resulting file is saved as a Portable Network Graphics (PNG) file.
This behavior occurs because the GDI+ component of the .NET Framework does not have an encoder that you can use to save files as .wmf or .emf files.

Image.Save Method (System.Drawing) | Microsoft Docs[^]
Share this answer
itm.abhishek 19-Jul-19 8:27am    
Hi, I tried Image.Save method but it only produces an image with .emf extension. It does not actually produce a true .emf file. I went through some articles on MSDN and found that CopyEnhMetaFile(iptrMetafileHandle, "image.emf") function actually copies the contents of an .emf file into a new one. But in my case, it's only copying the original file content into a new file and saving it back to the machine. The new file created by CopyEnhMetaFile function doesn't include the color changes done by g.DrawImage function in the above code.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900