Microsoft KB Archive/814675

From BetaArchive Wiki

Article ID: 814675

Article Last Modified on 4/21/2006



APPLIES TO

  • Microsoft GDI+ 1.0
  • Microsoft .NET Framework Software Development Kit 1.0 Service Pack 2
  • Microsoft .NET Framework Software Development Kit 1.0 Service Pack 1
  • Microsoft .NET Framework Software Development Kit 1.0 Service Pack 2
  • Microsoft Windows XP Professional
  • Microsoft Windows XP Professional for Itanium-based systems



SYMPTOMS

When either a Bitmap object or an Image object is constructed from a file, the file remains locked for the lifetime of the object. As a result, you cannot change an image and save it back to the same file where it originated.

Additionally, if the stream was destroyed during the life of the Bitmap object, you cannot successfully access an image that was based on a stream. For example, the Graphics.DrawImage() function may not succeed after the stream has been destroyed.

CAUSE

GDI+, and therefore the System.Drawing namespace, may defer the decoding of raw image bits until the bits are required by the image. Additionally, even after the image has been decoded, GDI+ may determine that it is more efficient to discard the memory for a large Bitmap and to re-decode later. Therefore, GDI+ must have access to the source bits for the image for the life of the Bitmap or the Image object.

To retain access to the source bits, GDI+ locks any source file, and forces the application to maintain the life of any source stream, for the life of the Bitmap or the Image object.

WORKAROUND

To work around this problem, create new Bitmap images by using one of the following methods (as described later in this section):

  • Create a non-indexed image.
  • Create an indexed image.

In both cases, calling the Bitmap.Dispose() method on the original Bitmap removes the lock on the file or removes the requirement that the stream or memory stay alive.

Create a Non-Indexed Image

This approach requires that the new image be in a non-indexed pixel format (more than 8 bits-per-pixel), even if the original image was in an indexed format. This workaround uses the Graphics.DrawImage() method to copy the image to a new Bitmap object:

  1. Construct the original Bitmap from the stream, from the memory, or from the file.
  2. Create a new Bitmap of the same size, with a pixel format of more than 8 bits-per-pixel (BPP).
  3. Use the Graphics.FromImage() method to obtain a Graphics object for the second Bitmap.
  4. Use Graphics.DrawImage() to draw the first Bitmap onto the second Bitmap.
  5. Use Graphics.Dispose() to dispose of the Graphics.
  6. Use Bitmap.Dispose() to dispose of the first Bitmap.

Create an Indexed Image

This workaround creates a Bitmap object in an indexed format:

  1. Construct the original Bitmap from the stream, from the memory, or from the file.
  2. Create a new Bitmap with the same size and pixel format as the first Bitmap.
  3. Use the Bitmap.LockBits() method to lock the whole image for both Bitmap objects in their native pixel format.
  4. Use either the Marshal.Copy function or another memory copying function to copy the image bits from the first Bitmap to the second Bitmap.
  5. Use the Bitmap.UnlockBits() method to unlock both Bitmap objects.
  6. Use Bitmap.Dispose() to dispose of the first Bitmap.


STATUS

This behavior is by design.

MORE INFORMATION

By using the Bitmap class constructor and the Image class constructor, you can create a Bitmap or an Image object that is based on the contents of a file or a stream. Also, a Bitmap object may be created from a block of memory or from a Windows GDI HBITMAP handle.

GDI+ requires access to the data that is contained in the file or stream or memory block during the life of the new Bitmap or the new Image object. This requirement is because GDI+ does not immediately decode the image bits. Instead, GDI+ delays the decoding of the image bits until the first time that the image is accessed. Additionally, GDI+ may sometimes choose to discard its buffer for the image and re-decode later.

To make these types of delayed decoding easier, GDI+ must have access to the raw image data during the life of the object. This can result in some unexpected consequences:

  • You cannot overwrite the file.

When a file name is provided to the Bitmap or to the Image class constructor, GDI+ opens the file and maintains a lock on the file during the life of the Bitmap or the Image object. As a result, you cannot write to the file before that Bitmap or the Image object is destroyed. This prevents the Image and the Bitmap classes from being able to save to the same file that the object was created from.

  • You must not destroy the stream.

When a stream is provided to the Bitmap or the Image class constructor, GDI+ may defer reading from the stream until later. This means that you must not destroy the stream until after you destroy the Bitmap or the Image object. If you try to use the Bitmap or the Image object after you destroy the stream, you may receive an error message. It is the responsibility of the application to make sure that the stream can be used during the life of the new image object.

  • You must retain the memory.

When a Bitmap object is created with a pointer to image bits, the new object may or may not use the memory at that address as backing for the image. Therefore, the application must make sure that the memory can be used during the life of the Bitmap object.

  • You may destroy the HBITMAP.

A Bitmap object that is based on an HBITMAP (DIBSection or device dependent bitmap) just makes a copy of the image from the HBITMAP. Therefore, you may destroy the HBITMAP immediately after creating the new Bitmap object.

For additional information about using GDI and GDI+ together, click the following article number to view the article in the Microsoft Knowledge Base:

311221 INFO: Interoperability between GDI and GDI+


Keywords: kbbitmap kbprb kbgdipimaging kbdswgdi2003swept KB814675