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
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