1

I have got this code running what it does is stream an RDLC file, converts it to image and saves it. The stream is created before hand and kept in the memory. The Problem i am facing is this function is very slow. It take 2-3 sec to execute. It takes most time to execute this line

      graphics.DrawImage(imge, adjustedRect);

most. How can I make it faster please help.

    public void PrintImagePage(int PageNo)
    {
        try
        {
            Metafile imge;
            Graphics graphics;
            Image pageImage;
            PageNo = PageNo - 1;
            if (m_streams == null || m_streams.Count == 0)
                throw new Exception("Error: no stream to print.");


            m_streams[PageNo].Position = 0;
            string filePath = _folderPath + _fileNamePrifix + PageNo + ".png";
            imge = new Metafile(m_streams[PageNo]);
            pageImage = new Bitmap(imge.Width, imge.Height);
            graphics = Graphics.FromImage(pageImage);

            Rectangle adjustedRect = new Rectangle(
                0,
                0,
                pageImage.Width,
                pageImage.Height);
            graphics.FillRectangle(Brushes.White, adjustedRect);

            // Draw the report content
            graphics.DrawImage(imge, adjustedRect);
            pageImage = ResizeBitmap(pageImage, .35f, InterpolationMode.HighQualityBicubic);
            pageImage.Save(filePath, ImageFormat.Png);
            //using (var m = new MemoryStream())
            //{
            //    pageImage.Save(filePath, ImageFormat.Png);

            //    var img = Image.FromStream(m);

            //    img.Save(filePath);
            //    img.Dispose();
            //}
            imge.Dispose();
            graphics.Dispose();
            pageImage.Dispose();

        }
        catch (Exception)
        {
            throw;
        }
    }
Taufiq Abdur Rahman
  • 1,348
  • 4
  • 24
  • 44
  • 1
    I remembered that this function is just lighting fast. Are you dealing with very large images? – Naruil May 29 '13 at 13:47
  • yes the original image is very large. that why i resize it before saving – Taufiq Abdur Rahman May 29 '13 at 17:35
  • Just don't resize. Create it the right size to begin with, saves you cycles on DrawImage() as well. Getting the pixel format to match is important. If you want it faster still then you'll need to settle for a lesser InterpolationMode. – Hans Passant May 30 '13 at 02:42
  • I am trying to overcome this speed problem with large format Multipage Tiff files (600dpi scans, 3000px+ X 2500px+ per frame). Did you ever find optimizations that worked? This thread [link](https://stackoverflow.com/questions/11020710/is-graphics-drawimage-too-slow-for-bigger-images/11025428#11025428) helped me shave 30% of my draw time but I still need more performance. – reachingnexus Nov 07 '17 at 21:08

3 Answers3

1

As for your question, no, i don't think there is a way to speed up the Graphics class.

I haven't worked with Metafiles before, so I don't really know what's fast and slow. But as far as I can understand it recreates a image based on the draw-operations done before(like on some client or something).

Couldn't it be that there are a lot of draw-operations inside your Metafile? So maybe it's a better solution to just create the image on the fly @ your client, then just send the image?

[edit]Or don't use the Graphics class and create your own?[/edit]

ikwillem
  • 1,044
  • 1
  • 12
  • 24
  • imge = new Metafile(m_streams[PageNo]); there a stream created by reporting tool and than put on a new metafile – Taufiq Abdur Rahman May 29 '13 at 13:48
  • Maybe downloading the stream first into a memorystream, then create your image based on that MemoryStream? Maybe the I/O is taking to much time. (just guessing here ;) – ikwillem May 29 '13 at 13:54
1

Oh, I see. If you are dealing with very large images. You are actually

  1. Convert a metafile to a large bitmap
  2. resize the bitmap

I suggest you just convert it to a smaller bitmap in one step.

pageImage = new Bitmap(imge.Width * 0.35f, imge.Height * 0.35f);

And remove the resize code

//pageImage = ResizeBitmap(pageImage, .35f, InterpolationMode.HighQualityBicubic);

If this cannot solve your problem, it means your metafile is just too complex to render. In this case the slow DrawImage is unavoidable. You may consider some speculation technique (guess and render the image before it is needed) to cover the latency of this function.

Naruil
  • 2,300
  • 11
  • 15
1

You could use the Graphics' in-built transform and re-sampling features to draw it to a smaller rect.

graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
float scale = 0.35f;
graphics.Transform = new System.Drawing.Drawing2D.Matrix(scale, 0.0f, 0.0f, scale, 0.0f, 0.0f);

This will allow you to draw the large image to a smaller one using the same draw call:

graphics.DrawImage(imge, adjustedRect);

The transform is a 2x2 matrix and a position offset. By setting the top-left and bottom-right elements of the matrix to the scale you have created a scale-transform. This way the re-sizing is done ASAP. This removes the need for the second copy/re-size.

axon
  • 1,190
  • 6
  • 16