Link to home
Start Free TrialLog in
Avatar of ericvbnet
ericvbnet

asked on

Draw PNG files from EMF files faster

Hello Experts, I use the code below to convert my EMF files to PNG files for many graphs at a time. Two of the steps are very slow: memoryGraphics.DrawImage and memoryBitmap.Save

I am asking for suggestions on how to speed these two steps up considerably, or an alternative faster way to generate the .png files from the EMF files.

'NewImage is the path to my EMF file        
Dim imgMeta As New Metafile(NewImage)
Dim myWidth As Integer
Dim myHeight As Integer
myWidth = imgMeta.Width
myHeight = imgMeta.Height
'  We want a high quality .png file.
'  Let's quadruple the height and width.
myWidth = myWidth * 4
myHeight = myHeight * 4
Dim memoryBitmap As Bitmap
memoryBitmap = New Bitmap(myWidth, myHeight) 'adds 4 seconds for 107 graphs (14 seconds to 18 seconds)
Dim memoryGraphics As Graphics
memoryGraphics = Graphics.FromImage(memoryBitmap)
' Draw the Metafile to memory
memoryGraphics.DrawImage(imgMeta, 0, 0, myWidth, myHeight) 'adds 20 seconds for 107 graphs (18 to 38)
memoryBitmap.Save(GloTempPath & "\pngversion.png", ImageFormat.Png) 'add 30 more seconds (38 to 68) 68 is total time
imgMeta.Dispose()

Open in new window

Avatar of Anurag Thakur
Anurag Thakur
Flag of India image

are you generating one image file or multiple image files (i am assuming multiple images)
in case of multiple images you can use threads to generate your images and it will expedite your process of images generation as each independent thread will be generating one image
I dont think there is much there to improve the performance as i think its a standard piece of code what you have shown in the query above
Avatar of aikimark
>>'  We want a high quality .png file.
>>'  Let's quadruple the height and width.

Larger size does not equate to higher quality

Please do a performance test and do this conversion without increasing the image size.
Avatar of ericvbnet
ericvbnet

ASKER

I generate each image file in sequence so I don't have the option of using multiple threads.
If the images are not made larger before conversion, then when the png is resized larger, it becomes blurry.
ASKER CERTIFIED SOLUTION
Avatar of aikimark
aikimark
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
To clarify, there are 107 EMF files. The process (with N = 107 in my example) goes

For i = 1 to N
   Run some code
   Create EMF file
   Convert EMF file for 3rd party software that won't use EMFs
Next  
aikimark, you were absolutely right. If I don't do the 4x4 increase, the time goes from 54 seconds down to 3 seconds. The one drawback is I now have an image that is fuzzy when it is resized larger.
> The process (with N = 107 in my example) goes
>Create EMF file

Do you have  control on the Create EMF Files process?
Yes. They are graphs that are also created in the same program.
Can you not change size of those?
But they are based on the incoming numbers, so each graph is different.
I'm not sure I understand what you mean by changing the size.
Can you show the code that's generating these EMF files?
I like where you're going with this CC.  In addition to the source program, we might also consider preprocessing the EMF file, adjusting the size parameters before bringing it into the conversion process.
There is a lot of code for creating the individual lines and symbols so I've just left the shell to give you an idea.
Public Function GetMetaFile(ByVal FileName As String) As Metafile
        Dim G As Graphics = MetaDisplayFrm.CreateGraphics()
        Dim ipHdc As IntPtr = G.GetHdc()
        Dim MF As Metafile
        MF = New Metafile(FileName, ipHdc)
        G.ReleaseHdc(ipHdc)
        G.Dispose()
        Return MF
    End Function

        Using MF As Metafile = GetMetaFile(H.MFName)
            If IsNothing(MF) Then
                Exit Sub
            End If
            Using G As Graphics = Graphics.FromImage(MF)
                G.SmoothingMode = SmoothingMode.AntiAlias
                G.TextRenderingHint = GloTextRenderingHint

                HistoReadBinParms(H.HP)
                AxisOppositesInit(H.Axis(_Ax.T), H.Axis(_Ax.L))
                AxisOppositesInit(H.Axis(_Ax.B), H.Axis(_Ax.R))
                HistoSetAxisBoundaries(_Ax.T, H.Axis(_Ax.T))
                HistoSetAxisBoundaries(_Ax.B, H.Axis(_Ax.B))
                AxisBoundariesInit(_Ax.L, H.Axis(_Ax.L))
                AxisBoundariesInit(_Ax.R, H.Axis(_Ax.R))
.
.
.
G.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
            G.DrawLine(MyPen, PX0, PY0, PX1, PY1)
(many more lines and symbols in similar manner)
.
.
.
            End Using
        End Using

Open in new window

Hmm. Looks like a lot of drawing is going on in the EMF file. One of the constructors for Metafile class takes a rectangle as bounds. Try that

http://msdn.microsoft.com/en-us/library/2ea632z6.aspx

I can't get the graph to draw properly with the rectangle. I think the difficulty might be that I don't know what the coordinates of the rectangle should be until after the drawing takes place.
You may have to live with it then? Are you using .NET 4? Then you can use Parallels or Tasks or else you can use threading.
We are still in 3.5. Thank you for your input.