Image.Save( ..., ImageFormat.Bmp ) slow in simple case

F

F. Hall

If I read a bitmap image from one file and save it to another the save
operation is slow unless I draw on the image. In other words,

Image inputImage = Image.FromFile( @"c:\temp\source.bmp" );
using ( Graphics g = Graphics.FromImage( inputImage ) )
{
g.DrawLine( new Pen(Brushes.White), 0, 0, 1, 1 );
}
inputImage.Save( @"c:\temp\sink.bmp", ImageFormat.Bmp );

is many times faster than

Image inputImage = Image.FromFile( @"c:\temp\source.bmp" );
inputImage.Save( @"c:\temp\sink.bmp", ImageFormat.Bmp );

So what side effect is created by DrawLine that speeds up the Save?

I have a small console app I called ImageCopy that demostrates what
I'm talking about. The results go like this on my machine using a
3.5Mb .bmp file:

C:\>ImageCopy c:\temp\source.bmp c:\temp\sink.bmp nodrawing
no drawing
READ: 00:00:00.0312500
DRAW: 00:00:00
SAVE: 00:00:00.3437500
TOTAL: 00:00:00.3750000

C:\>ImageCopy c:\temp\source.bmp c:\temp\sink.bmp draw
with drawing
READ: 00:00:00.0312500
DRAW: 00:00:00
SAVE: 00:00:00.0156250
TOTAL: 00:00:00.0468750

The save time differs by a factor of about 20x in this run. On a 5x
slower CPU the difference was more like 60x.

Here's the source for my ImageCopy console application (C#):

using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace ImageCopy
{
class ImageCopy
{
[STAThread]
static void Main(string[] args)
{
DateTime startTotalTime = DateTime.Now;
DateTime startReadTime = DateTime.Now;

Image inputImage = Image.FromFile( args[0] ); // Read
TimeSpan readDuration = DateTime.Now - startReadTime;

DateTime startDrawTime = DateTime.Now;

if ( args.Length == 3 && args[2] == "draw" )
{
Console.WriteLine( "with drawing" );
using ( Graphics g = Graphics.FromImage( inputImage ) )
{
g.DrawLine( new Pen(Brushes.White), 0, 0, 1, 1 );
}
}
else
{
Console.WriteLine( "no drawing" );
}
TimeSpan drawDuration = DateTime.Now - startDrawTime;

DateTime startSaveTime = DateTime.Now;

inputImage.Save( args[1], ImageFormat.Bmp ); // Save
TimeSpan saveDuration = DateTime.Now - startSaveTime;
TimeSpan totalDuration = DateTime.Now - startTotalTime;

Console.WriteLine( " READ: " + readDuration.ToString() );
Console.WriteLine( " DRAW: " + drawDuration.ToString() );
Console.WriteLine( " SAVE: " + saveDuration.ToString() );
Console.WriteLine( "TOTAL: " + totalDuration.ToString() );
}
}


I run tests from a .bat file that contains these two lines:

imagecopy c:\temp\source.bmp c:\temp\sink.bmp dontdraw
imagecopy c:\temp\source.bmp c:\temp\sink.bmp draw
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top