Loading WMF is failing, yet converting a PNG to WMF succeeds but loss of background

579 views Asked by At

Working with the RichTextBox, I gave up on trying to make a PNG have a transparent background, and I really don't like the code from Microsoft that in order to convert an image object to wmf, that you must write two files, then read it back in to the memory stream, so I cracked open Illustrator, and converted one emote to WMF so it is allegedly in the format that RTF requires.

Enclosed are the images in the formats I am trying :

  • WMF big-smile.wmf (had to link this as SO doesn't allow upload of WMF)
  • PNG big-smile.png

The trouble I am having right now, is that the following code, results in no image being displayed:

public string GetImage( string file, int width, int height ) {
    float dpiX;
    float dpiY;
    string rtfimage;

    using ( Graphics g= this.CreateGraphics() ) {
        dpiX=g.DpiX;
        dpiY=g.DpiY;
    }

    using ( MemoryStream ms=new MemoryStream() ) {
        byte[] data=File.ReadAllBytes( file );
        ms.Write( data, 0, data.Length );
        rtfimage=@"{\pict\wmetafile8\picw"+(int)( ( (float)width/dpiX )*2540 )
                            +@"\pich"+(int)( ( (float)height/dpiY )*2540 )
                            +@"\picwgoal"+(int)( ( (float)width/dpiX )*1440 )
                            +@"\pichgoal"+(int)( ( (float)height/dpiY )*1440 )
                            +" "
                    +BitConverter.ToString( ms.ToArray() ).Replace( "-", "" ).ToLower()
                            +"}";
    }
    return rtfimage;
}

While the following code works (but only with non-wmf files) :

public static string GetEmbedImageString( Image image ) {
    Metafile metafile=null;
    float dpiX;
    float dpiY;

    using ( Graphics g=Graphics.FromImage( image ) ) {
        IntPtr hDC=g.GetHdc();
        metafile=new Metafile( hDC, EmfType.EmfOnly );
        g.ReleaseHdc( hDC );
    }

    using ( Graphics g=Graphics.FromImage( metafile ) ) {
        g.CompositingMode = CompositingMode.SourceOver;
        g.CompositingQuality = CompositingQuality.HighQuality;
        g.DrawImage( image, 0, 0 );
        g.Clear( Color.White );
        dpiX=g.DpiX;
        dpiY=g.DpiY;
    }

    IntPtr _hEmf=metafile.GetHenhmetafile();
    uint _bufferSize=GdipEmfToWmfBits( _hEmf, 0, null, MM_ANISOTROPIC,
    EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault );
    byte[] _buffer=new byte[_bufferSize];
    GdipEmfToWmfBits( _hEmf, _bufferSize, _buffer, MM_ANISOTROPIC,
                                EmfToWmfBitsFlags.EmfToWmfBitsFlagsDefault );
    IntPtr hmf=SetMetaFileBitsEx( _bufferSize, _buffer );
    string tempfile=Path.GetTempFileName();
    CopyMetaFile( hmf, tempfile );
    DeleteMetaFile( hmf );
    DeleteEnhMetaFile( _hEmf );

    var stream=new MemoryStream();
    byte[] data=File.ReadAllBytes( tempfile );
    //File.Delete (tempfile);
    int count=data.Length;
    stream.Write( data, 0, count );

    string proto=@"{\pict\wmetafile8\picw"+(int)( ( (float)image.Width/dpiX )*2540 )
                      +@"\pich"+(int)( ( (float)image.Height/dpiY )*2540 )
                      +@"\picwgoal"+(int)( ( (float)image.Width/dpiX )*1440 )
                      +@"\pichgoal"+(int)( ( (float)image.Height/dpiY )*1440 )
                      +" "
                      +BitConverter.ToString( stream.ToArray() ).Replace( "-", "" )
                      +"}";

    return proto;
}

They both return the appropriate string format for embedding a wmf file in a RichTextBox control as follows

{\pict\wmetafile8\picw[WIDTH]\pich[HEIGHT]\picwgoal[WIDTH (twips)]\pichgoal[HEIGHT (twips)] [HEX BYTE ARRAY OF FILE]}

I am looking for a way to get the appropriate string value for this that works with the WinForms RichTextBox component.

I do feel this is a VERY specific question relating to a very specific problem and have given more than enough code and details in order for you to duplicate the problem. Ideally, if you have experienced this issue and have found a work-around that does not involve messing with the users clipboard (I am aware of the copy/paste method which is not only much slower, but it interferes with the users clipboard. I am also aware of the work-around the clipboard issue which stores the old clipboard data in memory and sets it back, however this is not without flaw in some cases the data can not be set back).

I am not looking for the easy road, although you would think by 2015, that the RichTextBox control in WinForms would have evolved during the 10 years in .NET.

I also realize, that the other option is to use WPF which opens Pandora's box to all the other problems (as well as benefits) of using WPF. I prefer to stick with the language that is overall much more mature.

What I need help with, is very specific: I posted another thread referencing something else regarding this matter, but it was closed under the claim that it was not specific. This is the same question, with many MANY more details, in the hopes that you will see how specific this is.

C# > WinForms > RichTextBox > Replace String with Image which requires the format to be very specific and in WMF as a very specific byte string with very specific formatting tags as a string > Problem getting the images to load properly in the format required while maintaining transparency or at least using a definable color if can't keep transparency on vector.

0

There are 0 answers