BitmapExtensionsGetReadWriteBitmapData Method

KGy SOFT Drawing Libraries Help
Gets an IReadWriteBitmapData instance, which provides fast read-write access to the actual data of the specified bitmap. The bitmap can have any PixelFormat.
See the Remarks section for details and examples.

Namespace:  KGySoft.Drawing
Assembly:  KGySoft.Drawing (in KGySoft.Drawing.dll) Version: 5.0.0
Syntax

public static IReadWriteBitmapData GetReadWriteBitmapData(
	this Bitmap bitmap,
	Color backColor = null,
	byte alphaThreshold = 128
)

Parameters

bitmap
Type: System.DrawingBitmap
A Bitmap instance, whose data is about to be accessed.
backColor (Optional)
Type: System.DrawingColor
When setting pixels of indexed bitmaps and bitmaps without alpha support or with single bit alpha, then specifies the color of the background. Color values with alpha, which are considered opaque will be blended with this color before setting the pixel in the result bitmap data. The alpha value (Color.A property) of the specified background color is ignored. This parameter is optional.
Default value: Color.Empty, which has the same RGB values as Black.
alphaThreshold (Optional)
Type: SystemByte
When setting pixels of bitmaps with single bit alpha or with a palette that has a transparent color, then specifies a threshold value for the Color.A property, under which the color is considered transparent. If 0, then the pixels to be set will never be transparent. This parameter is optional.
Default value: 128.

Return Value

Type: IReadWriteBitmapData
An IReadWriteBitmapData instance, which provides fast read-write access to the actual data of the specified bitmap.

Usage Note

In Visual Basic and C#, you can call this method as an instance method on any object of type Bitmap. When you use instance method syntax to call this method, omit the first parameter. For more information, see Extension Methods (Visual Basic) or Extension Methods (C# Programming Guide).
Remarks

All possible PixelFormats are supported, of which a Bitmap can be created in the current operating system.

Note Note
For information about the possible usable PixelFormats on different platforms see the Remarks section of the ConvertPixelFormat method.

If alphaThreshold is zero, then setting a fully transparent pixel in a bitmap with indexed or single-bit-alpha pixel format will be blended with backColor even if the bitmap can handle transparent pixels.

If alphaThreshold is 1, then setting a pixel of a bitmap with indexed or single-bit-alpha pixel format will be transparent only if the color to set is completely transparent (has zero alpha).

If alphaThreshold is 255, then setting a pixel of a bitmap with indexed or single-bit-alpha pixel format will be opaque only if the color to set is completely opaque (its alpha value is 255).

If a pixel of a bitmap without alpha gradient support is set by the IWritableBitmapData.SetPixel/IWritableBitmapDataRow.SetColor methods or by the IReadWriteBitmapDataRow indexer, and the pixel has an alpha value that is greater than alphaThreshold, then the pixel to set will be blended with backColor.

Examples

The following example demonstrates how easily you can copy the content of a 32-bit ARGB image into an 8-bit indexed one by using the GetReadableBitmapData and GetWritableBitmapData methods:

C#
var targetFormat = PixelFormat.Format8bppIndexed; // feel free to try other formats as well
using (Bitmap bmpSrc = Icons.Shield.ExtractBitmap(new Size(256, 256)))
using (Bitmap bmpDst = new Bitmap(256, 256, targetFormat))
{
    using (IReadableBitmapData dataSrc = bmpSrc.GetReadableBitmapData())
    using (IWritableBitmapData dataDst = bmpDst.GetWritableBitmapData())
    {
        for (int y = 0; y < dataSrc.Height; y++)
        {
            for (int x = 0; x < dataSrc.Width; x++)
            {
                // Please note that bmpDst.SetPixel would not work for indexed formats
                // and even when it can be used it would be much slower.
                dataDst.SetPixel(x, y, dataSrc.GetPixel(x, y));
            }
        }
    }

    bmpSrc.SaveAsPng(@"c:\temp\bmpSrc.png");
    bmpDst.SaveAsPng(@"c:\temp\bmpDst.png"); // or saveAsGif/SaveAsTiff to preserve the indexed format
}

The example above produces the following results:

bmpSrc.pngShield icon with transparent background
bmpDst.png8 BPP shield icon with system default palette

If the pixels are not accessed randomly, then the sequential enumeration of rows can be a bit faster:

C#
// Replace the body of the inner using block of the previous example with the following code:
IReadableBitmapDataRow rowSrc = dataSrc.FirstRow;
IWritableBitmapDataRow rowDst = dataDst.FirstRow;
do
{
    for (int x = 0; x < dataSrc.Width; x++)
        rowDst[x] = rowSrc[x];
} while (rowSrc.MoveNextRow() && rowDst.MoveNextRow());

For parallel processing you can retrieve multiple rows by the indexer and process them concurrently. When targeting .NET Framework 4.0 or newer, the example above can be easily re-written to use parallel processing:

C#
// The parallel version of same body as in the previous example:
Parallel.For(0, dataSrc.Height, y =>
{
    IReadableBitmapDataRow rowSrc = dataSrc[y];
    IWritableBitmapDataRow rowDst = dataDst[y];
    for (int x = 0; x < dataSrc.Width; x++)
        rowDst[x] = rowSrc[x];
});
Note Note
The examples above are just for demonstration purpose. For the same result use the ConvertPixelFormat methods for more flexibility and optimized parallel processing. The ConvertPixelFormat(Image, PixelFormat, IQuantizer, IDitherer) overload allows using custom quantizer and ditherer implementations as well.

The following example demonstrates how to use the read-write IReadWriteBitmapData returned by the GetReadWriteBitmapData method to manipulate a Bitmap in-place:

C#
// This example produces the same result as the MakeGrayscale extension method without a ditherer:
using (Bitmap bmp = Icons.Information.ExtractBitmap(new Size(256, 256)))
{
    bmp.SaveAsPng(@"c:\temp\before.png");

    using (IReadWriteBitmapData bmpData = bmp.GetReadWriteBitmapData())
    {
        IReadWriteBitmapDataRow row = bmpData.FirstRow;
        do
        {
            for (int x = 0; x < bmpData.Width; x++)
                row[x] = row[x].ToGray();
        } while (row.MoveNextRow());
    }

    bmp.SaveAsPng(@"c:\temp\after.png");
}

The example above produces the following results:

before.pngColor shield icon
after.pngGrayscale shield icon

See Also

Reference