none
How to convert EMF file to PNG format with antialiasing tehnique? RRS feed

  • Question

  • Hi All,

    I have create the new meta file without anti aliasing, then saves that Meta file into png format using System.Drawing.Bitmap. How to save the png file with anti aliasing, if the below given code is correct, "How can i identify the difference between anti aliased image and non anti aliased image .

                foreach (Image image in images)
                {
                    Bitmap bitmap = null;
                    Metafile metafile = image as Metafile;
                    bitmap = new Bitmap(bitmapWidth, bitmapHeight);
                    bitmap.SetResolution((float)resolution, (float)resolution);
                    using (Graphics g = Graphics.FromImage(bitmap))
                    {
                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                        g.DrawImage(metafile, 0, 0, (float)bitmapWidth, (float)bitmapHeight);
                        g.Dispose();
                    }
                    bitmap.Save(i.ToString("D3")+"new" + ".png", ImageFormat.Png);
                    bitmap.Dispose();
                    i++;
                }
    Can anyone please post your suggestion here?

    Thursday, January 14, 2016 6:57 AM

Answers

  • Hi Pradeep L(c23),

    Please check the following code,

    public static string ConvertWMFToBitmap(string sEMFfilename, int width, int height, string sOutName)
        {
          string res = "";      
    
          // open WMF file and read to byte array
          FileStream fs_WMF = File.OpenRead(sEMFfilename);
          byte[] dataWMF = new byte[fs_WMF.Length];
          int offset = 0;
          int remaining = dataWMF.Length;
          while (remaining > 0)
          {
            int read = fs_WMF.Read(dataWMF, offset, remaining);
            if (read <= 0)
              throw new EndOfStreamException
                (String.Format("{0} bytes left to read", remaining));
            remaining -= read;
            offset += read;
          }
          fs_WMF.Close();
    
          // get Placeable header (if not exist)
          byte[] bAddHeader = EMFImage.RestorePlaceableHeader(dataWMF);
          
    
          MemoryStream ms_WMF = new MemoryStream();
          ms_WMF.Write(bAddHeader, 0, bAddHeader.Length);
          ms_WMF.Write(dataWMF, 0, dataWMF.Length);
          ms_WMF.Position = 0;
    
          Image ODTImage = Image.FromStream(ms_WMF);
        
          if (ODTImage.RawFormat.Guid == ImageFormat.Emf.Guid || ODTImage.RawFormat.Guid == ImageFormat.Wmf.Guid)
          {
            int actualWidth = (int)((width / 25.4) * 300);
            int actualHeight = (int)((height / 25.4) * 300);
                    
            Rectangle imageRect = new Rectangle(0, 0, ODTImage.Width, ODTImage.Height);
    
    
            Bitmap newImage = new Bitmap(actualWidth, actualHeight);
            newImage.SetResolution(300.0F, 300.0F);
    
            Graphics g = Graphics.FromImage(newImage);
            // fill white
            g.FillRectangle(new SolidBrush(Color.White), imageRect);
    
            g.DrawImage(ODTImage, 0, 0, actualWidth, actualHeight);
    
            ImageCodecInfo encoderInfo = EMFImage.GetEncoderInfo("image/tiff");
            EncoderParameters encoderParams = new EncoderParameters(2);
            encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT4);
            encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 1L);
    
            // convert to bitonal
            Bitmap BitonalImage = EMFImage.ConvertToBitonal(newImage);
            BitonalImage.SetResolution(300.0F, 300.0F);
            BitonalImage.Save(sOutName, encoderInfo, encoderParams);
    
            g.Dispose();
            BitonalImage.Dispose();
            newImage.Dispose();
    
            return "tif";
          }
          else
          {
            ImageCodecInfo encoderInfo = EMFImage.GetEncoderInfo("image/jpeg");
            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 80L);
    
            ODTImage.Save(sOutName, encoderInfo, encoderParams);
    
            return "jpg";
          }
        }
    
        private static byte[] RestorePlaceableHeader(byte[] bMetafile)
        {
          byte[] bHeader = new byte[0]; //22
    
          MemoryStream memstreamWMF = new MemoryStream();
          memstreamWMF.Write(bMetafile, 0, bMetafile.Length);
          memstreamWMF.Position = 0;
    
          Metafile tmpM = new Metafile(memstreamWMF);
          if (!tmpM.GetMetafileHeader().IsWmfPlaceable())
          {
            bHeader = new byte[22];        
            
            byte[] bBounds = GetBounds(tmpM);
    
            // Create header for placeable WMF
            WmfPlaceableFileHeader newhdr = new WmfPlaceableFileHeader();
            newhdr.BboxBottom = BitConverter.ToInt16(bBounds, 4); //1280;        
            newhdr.BboxLeft = 0;
            newhdr.BboxRight = BitConverter.ToInt16(bBounds, 0); //5056        
            newhdr.BboxTop = 0;
            newhdr.Hmf = 0;
            newhdr.Inch = 1400;
    
            // evaluate checksum
            int checksum = 0;
            checksum ^= (newhdr.Key & 0x0000FFFF);
            checksum ^= (int)(((ulong)newhdr.Key & 0xFFFF0000) >> 16);
            checksum ^= newhdr.Hmf;
            checksum ^= newhdr.BboxLeft;
            checksum ^= newhdr.BboxTop;
            checksum ^= newhdr.BboxRight;
            checksum ^= newhdr.BboxBottom;
            checksum ^= newhdr.Inch;
            checksum ^= (newhdr.Reserved & 0x0000FFFF);
            newhdr.Checksum = (short)checksum;
    
            MemoryStream msHeader = new MemoryStream();
            msHeader.Write(Reverse(newhdr.Key), 0, 4);
            msHeader.Write(Reverse(newhdr.Hmf), 0, 2);
            msHeader.Write(Reverse(newhdr.BboxLeft), 0, 2);
            msHeader.Write(Reverse(newhdr.BboxTop), 0, 2);
            msHeader.Write(Reverse(newhdr.BboxRight), 0, 2);
            msHeader.Write(Reverse(newhdr.BboxBottom), 0, 2);
            msHeader.Write(Reverse(newhdr.Inch), 0, 2);
            msHeader.Write(Reverse(newhdr.Reserved), 0, 4);
            msHeader.Write(Reverse(newhdr.Checksum), 0, 2);
            msHeader.Position = 0;
            int n = msHeader.Read(bHeader, 0, Convert.ToInt32(msHeader.Length));
            msHeader.Close();
          }
    
          
    
          memstreamWMF.Close();
    
          return bHeader;
        }
    
        private static byte[] Reverse(object isrc)
        {
          byte[] src;
          if (isrc.GetType().ToString() == "System.Int32")
          {
            src = BitConverter.GetBytes((int)isrc);
          }
          else
          {
            src = BitConverter.GetBytes((short)isrc);
          }
    
    
          if (!BitConverter.IsLittleEndian)
          {
    
            byte[] res = new byte[src.Length];
            int i = src.Length - 1;
            foreach (byte b in src)
            {
              res[i] = b;
              i--;
            }
            return res;
          }
          return src;
        }
    
        // restore bounds for 22-bytes header
        private static byte[] bBounds = new byte[8];
        private static byte[] GetBounds(Metafile mf)
        {
          
          RECT bounds;
          bounds.Left = 0;
          bounds.Top = 0;
          bounds.Right = 800;
          bounds.Bottom = 600;
    
          IntPtr hEmfDC = CreateEnhMetaFile(IntPtr.Zero ,
                     null ,
                     ref bounds,
                     "My Application\0Bitmap Entry\0\0");
    
    
          Graphics grfx = Graphics.FromHdc(hEmfDC);
          grfx.EnumerateMetafile(mf, new Point(0, 0), new Graphics.EnumerateMetafileProc(MetafileCallback));
          grfx.Dispose();
          return bBounds;
        }
    
        private static bool MetafileCallback(
        EmfPlusRecordType recordType,
        int flags,
        int dataSize,
        IntPtr data,
        PlayRecordCallback callbackData)
        {
          byte[] dataArray = null;
          if (data != IntPtr.Zero)
          {        
            dataArray = new byte[dataSize];
            Marshal.Copy(data, dataArray, 0, dataSize);
    
            if (recordType == EmfPlusRecordType.EmfSetWindowExtEx)
            {
              bBounds = dataArray;          
            }
          }      
          return true;
        }
    

    as the poster said:

    This source file is not EMF. It's WMF.

    This WMF is not "placeable WMF". This mean that WMF not contains additional 22 byte header with bounds for visualize. I have tried to append header and after that bitmap create without distortion.

    Please also use WMF instead.  For more information, please check convert EMF to raster format

    Some pictures you also can refer to https://onedrive.live.com/?id=E323ECC35FBBFAB3%21108&cid=E323ECC35FBBFAB3

    Have a nice day!

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, January 15, 2016 2:38 AM
  • One minor correction. EMF is better than WMF. It's the WMF that lacks the bounds information in header.

    The "Object 6.emf" in the "convert EMF to raster format" link is in fact a WMF that misnamed as EMF, therefore renders incorrectly.

    Friday, January 15, 2016 7:22 AM
    Answerer

All replies

  • Hi Pradeep L(c23),

    Please check the following code,

    public static string ConvertWMFToBitmap(string sEMFfilename, int width, int height, string sOutName)
        {
          string res = "";      
    
          // open WMF file and read to byte array
          FileStream fs_WMF = File.OpenRead(sEMFfilename);
          byte[] dataWMF = new byte[fs_WMF.Length];
          int offset = 0;
          int remaining = dataWMF.Length;
          while (remaining > 0)
          {
            int read = fs_WMF.Read(dataWMF, offset, remaining);
            if (read <= 0)
              throw new EndOfStreamException
                (String.Format("{0} bytes left to read", remaining));
            remaining -= read;
            offset += read;
          }
          fs_WMF.Close();
    
          // get Placeable header (if not exist)
          byte[] bAddHeader = EMFImage.RestorePlaceableHeader(dataWMF);
          
    
          MemoryStream ms_WMF = new MemoryStream();
          ms_WMF.Write(bAddHeader, 0, bAddHeader.Length);
          ms_WMF.Write(dataWMF, 0, dataWMF.Length);
          ms_WMF.Position = 0;
    
          Image ODTImage = Image.FromStream(ms_WMF);
        
          if (ODTImage.RawFormat.Guid == ImageFormat.Emf.Guid || ODTImage.RawFormat.Guid == ImageFormat.Wmf.Guid)
          {
            int actualWidth = (int)((width / 25.4) * 300);
            int actualHeight = (int)((height / 25.4) * 300);
                    
            Rectangle imageRect = new Rectangle(0, 0, ODTImage.Width, ODTImage.Height);
    
    
            Bitmap newImage = new Bitmap(actualWidth, actualHeight);
            newImage.SetResolution(300.0F, 300.0F);
    
            Graphics g = Graphics.FromImage(newImage);
            // fill white
            g.FillRectangle(new SolidBrush(Color.White), imageRect);
    
            g.DrawImage(ODTImage, 0, 0, actualWidth, actualHeight);
    
            ImageCodecInfo encoderInfo = EMFImage.GetEncoderInfo("image/tiff");
            EncoderParameters encoderParams = new EncoderParameters(2);
            encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionCCITT4);
            encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 1L);
    
            // convert to bitonal
            Bitmap BitonalImage = EMFImage.ConvertToBitonal(newImage);
            BitonalImage.SetResolution(300.0F, 300.0F);
            BitonalImage.Save(sOutName, encoderInfo, encoderParams);
    
            g.Dispose();
            BitonalImage.Dispose();
            newImage.Dispose();
    
            return "tif";
          }
          else
          {
            ImageCodecInfo encoderInfo = EMFImage.GetEncoderInfo("image/jpeg");
            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 80L);
    
            ODTImage.Save(sOutName, encoderInfo, encoderParams);
    
            return "jpg";
          }
        }
    
        private static byte[] RestorePlaceableHeader(byte[] bMetafile)
        {
          byte[] bHeader = new byte[0]; //22
    
          MemoryStream memstreamWMF = new MemoryStream();
          memstreamWMF.Write(bMetafile, 0, bMetafile.Length);
          memstreamWMF.Position = 0;
    
          Metafile tmpM = new Metafile(memstreamWMF);
          if (!tmpM.GetMetafileHeader().IsWmfPlaceable())
          {
            bHeader = new byte[22];        
            
            byte[] bBounds = GetBounds(tmpM);
    
            // Create header for placeable WMF
            WmfPlaceableFileHeader newhdr = new WmfPlaceableFileHeader();
            newhdr.BboxBottom = BitConverter.ToInt16(bBounds, 4); //1280;        
            newhdr.BboxLeft = 0;
            newhdr.BboxRight = BitConverter.ToInt16(bBounds, 0); //5056        
            newhdr.BboxTop = 0;
            newhdr.Hmf = 0;
            newhdr.Inch = 1400;
    
            // evaluate checksum
            int checksum = 0;
            checksum ^= (newhdr.Key & 0x0000FFFF);
            checksum ^= (int)(((ulong)newhdr.Key & 0xFFFF0000) >> 16);
            checksum ^= newhdr.Hmf;
            checksum ^= newhdr.BboxLeft;
            checksum ^= newhdr.BboxTop;
            checksum ^= newhdr.BboxRight;
            checksum ^= newhdr.BboxBottom;
            checksum ^= newhdr.Inch;
            checksum ^= (newhdr.Reserved & 0x0000FFFF);
            newhdr.Checksum = (short)checksum;
    
            MemoryStream msHeader = new MemoryStream();
            msHeader.Write(Reverse(newhdr.Key), 0, 4);
            msHeader.Write(Reverse(newhdr.Hmf), 0, 2);
            msHeader.Write(Reverse(newhdr.BboxLeft), 0, 2);
            msHeader.Write(Reverse(newhdr.BboxTop), 0, 2);
            msHeader.Write(Reverse(newhdr.BboxRight), 0, 2);
            msHeader.Write(Reverse(newhdr.BboxBottom), 0, 2);
            msHeader.Write(Reverse(newhdr.Inch), 0, 2);
            msHeader.Write(Reverse(newhdr.Reserved), 0, 4);
            msHeader.Write(Reverse(newhdr.Checksum), 0, 2);
            msHeader.Position = 0;
            int n = msHeader.Read(bHeader, 0, Convert.ToInt32(msHeader.Length));
            msHeader.Close();
          }
    
          
    
          memstreamWMF.Close();
    
          return bHeader;
        }
    
        private static byte[] Reverse(object isrc)
        {
          byte[] src;
          if (isrc.GetType().ToString() == "System.Int32")
          {
            src = BitConverter.GetBytes((int)isrc);
          }
          else
          {
            src = BitConverter.GetBytes((short)isrc);
          }
    
    
          if (!BitConverter.IsLittleEndian)
          {
    
            byte[] res = new byte[src.Length];
            int i = src.Length - 1;
            foreach (byte b in src)
            {
              res[i] = b;
              i--;
            }
            return res;
          }
          return src;
        }
    
        // restore bounds for 22-bytes header
        private static byte[] bBounds = new byte[8];
        private static byte[] GetBounds(Metafile mf)
        {
          
          RECT bounds;
          bounds.Left = 0;
          bounds.Top = 0;
          bounds.Right = 800;
          bounds.Bottom = 600;
    
          IntPtr hEmfDC = CreateEnhMetaFile(IntPtr.Zero ,
                     null ,
                     ref bounds,
                     "My Application\0Bitmap Entry\0\0");
    
    
          Graphics grfx = Graphics.FromHdc(hEmfDC);
          grfx.EnumerateMetafile(mf, new Point(0, 0), new Graphics.EnumerateMetafileProc(MetafileCallback));
          grfx.Dispose();
          return bBounds;
        }
    
        private static bool MetafileCallback(
        EmfPlusRecordType recordType,
        int flags,
        int dataSize,
        IntPtr data,
        PlayRecordCallback callbackData)
        {
          byte[] dataArray = null;
          if (data != IntPtr.Zero)
          {        
            dataArray = new byte[dataSize];
            Marshal.Copy(data, dataArray, 0, dataSize);
    
            if (recordType == EmfPlusRecordType.EmfSetWindowExtEx)
            {
              bBounds = dataArray;          
            }
          }      
          return true;
        }
    

    as the poster said:

    This source file is not EMF. It's WMF.

    This WMF is not "placeable WMF". This mean that WMF not contains additional 22 byte header with bounds for visualize. I have tried to append header and after that bitmap create without distortion.

    Please also use WMF instead.  For more information, please check convert EMF to raster format

    Some pictures you also can refer to https://onedrive.live.com/?id=E323ECC35FBBFAB3%21108&cid=E323ECC35FBBFAB3

    Have a nice day!

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, January 15, 2016 2:38 AM
  • One minor correction. EMF is better than WMF. It's the WMF that lacks the bounds information in header.

    The "Object 6.emf" in the "convert EMF to raster format" link is in fact a WMF that misnamed as EMF, therefore renders incorrectly.

    Friday, January 15, 2016 7:22 AM
    Answerer