Click here to Skip to main content
6,305,776 members and growing! (17,038 online)
Email Password   helpLost your password?
Multimedia » General Graphics » Image Display     Beginner License: The Code Project Open License (CPOL)

Compressible Bitmap Using In-Memory Image Compressing Technique

By Lu Yixiang

A wrapper of System.Drawing.Bitmap that serves as a compromising solution in terms of memory usage and loading time.
C# 2.0, Windows, .NET 2.0, GDI+, VS2005, Dev
Posted:9 Oct 2006
Updated:14 Mar 2007
Views:20,752
Bookmarked:28 times
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
8 votes for this article.
Popularity: 4.08 Rating: 4.52 out of 5

1

2
1 vote, 12.5%
3
2 votes, 25.0%
4
5 votes, 62.5%
5

Introduction

The System.Drawing.Bitmap really provides a convenient way for us to create, save and process pictures of many types. However, there is one problem with this class that may not be noticed by all programmers -- it uses a lot of memory resources. For a non-indexed RGB picture of size 1280 by 1024, it will take up 1280 * 1024 * 3 = 3,932,160 = about 4 MB memory. Not so scary, since you have 1 GB memory on your workstation? What if you somehow have to load a thousand pictures of that size into memory at the same time? It will eat up all your physical memory plus virtual memory and then still complain that you don't have enough memory. It's not an imaginary scenario because I encountered the exact problem while writing my application. I'm sure someone would ask: "Why would you want to load so many pictures into memory? You can always load them from disk when they are needed." Unfortunately this doesn't work because loading from disk is too expensive for my application to afford. So I came up with this compromising solution, which takes less loading time than loading from disk and consumes less memory than storing the plain BITMAPs (with the capital BITMAP, I mean the one that stores RGB values in memory).

Background

The concept behind this is very simple. I take that BITMAP, dump it into a stream with some compression method, and save the stream in memory. Whenever the BITMAP is used, I take the stream and load the picture from it. As we all know, System.Drawing.Bitmap provides a bunch of very cute methods named Save(...). We can use one of them Save(Stream, ImageFormat) to serialize our BITMAP into a stream, and the compression method is controlled by the ImageFormat parameter.

Using the Code

The solution is coded into a single class CompressibleImage, which has two constructors, two important methods and one property.

Constructors CompressibleImage(Bitmap, ImageFormat) Creates a CompressibleImage instance, given the original image and format for compression.
CompressibleImage(MemoryStream) Creates a CompressibleImage instance, given the stream containing the compressed image.
Methods GetDecompressedImage() Gets the uncompressed image. If the image is compressed, it will be uncompressed first.
ClearDecompressedImage() Clears the uncompressed image, leaving the compressed one in memory.
Property IsCompressed Gets a value indicating if the image is compressed

The two most important methods are:

/// <summary>
/// Gets the uncompressed image. If the image is compressed, 
/// it will be uncompressed first.
/// </summary>
public Image GetDecompressedImage()
{
    if (decompressed == null)
    {
        stream.Seek(0, SeekOrigin.Begin);
        decompressed = new Bitmap(stream);
    }
    return decompressed;
}

/// <summary>
/// Clears the uncompressed image, leaving the compressed one in memory.
/// </summary>
public void ClearDecompressedImage()
{
    if (decompressed != null)
    {
        if (stream == null)
        {
            stream = new MemoryStream();
            decompressed.Save(stream, format);
        }
        decompressed = null;
    }
}

The following code segment shows how to use this class:

void Usage1(Bitmap b) 
{
    CompressibleImage ci = new CompressibleImage(b, ImageFormat.Jpeg);
    //...
    Image decompressed = ci.GetDecompressedImage();
    //use the decompressed image
    ci.ClearDecompressedImage();
    // make it compressed and use later
}

void Usage2(Bitmap b)
{
    MemoryStream ms = new MemoryStream();
    b.Save(ms, ImageFormat.Jpeg);
    CompressibleImage ci = new CompressibleImage(ms);
    // keep it compressed and use later
} 

Points of Interest

Note that the image quality will be compromised if the CompressibleImage object is created given a Bitmap instance and the ImageFormat.Jpeg format. However, if it is created given a MemoryStream instance, the quality of CompressibleImage will remain the same as what's contained in the MemoryStream. If lossless compression is a must, you should either use the right ImageFormat or better control the MemoryStream passed in.

The demo project shows the performance of the CompressibleImage class. Note that the resulting loading time of the two scenarios are more or less the same. They are due to the OS level or hardware level caching. For very large files or large number of files, the performances will differ.

History

  • 9th October, 2006 - First draft
  • 13th March, 2007 - Minor update

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Lu Yixiang


Member
This guy loves computer programming, software design and development. He is interested and specialized in C family languages, especially C#, Java, Objective-C and D Programming Language. Ruby and Python are starting to interest him as well.
Occupation: Software Developer
Location: Singapore Singapore

Other popular General Graphics articles:

  • A flexible charting library for .NET
    Looking for a way to draw 2D line graphs with C#? Here's yet another charting class library with a high degree of configurability, that is also easy to use.
  • CxImage
    CxImage is a C++ class to load, save, display, transform BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K images.
  • 3D Pie Chart
    A class library for drawing 3D pie charts.
  • Really cool visual FX
    A set of classes for doing stunning visual effects, including water, plasma and fire.
  • ImageStone
    An article on a library for image manipulation.
Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 1 of 1 (Total in Forum: 1) (Refresh)FirstPrevNext
GeneralGood Tip! Pinmembernorm .net5:22 9 Oct '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 14 Mar 2007
Editor: Deeksha Shenoy
Copyright 2006 by Lu Yixiang
Everything else Copyright © CodeProject, 1999-2009
Web18 | Advertise on the Code Project