Though the accepted answer works, it creates a new 32bpp ARGB image from the indexed bitmap.
To manipulate indexed bitmaps directly you can use this library (alert: shameless self promotion). Its GetReadWriteBitmapData
extension allows creating a writable managed accessor even for indexed pixel formats.
And then you can use one of the DrawInto
methods that can be used similarly to Graphics.DrawImage
. Of course, as the target bitmap is indexed, the drawing operation must quantize the pixels using the target palette colors but there are a sort of overloads that can use dithering to preserve more image details.
Usage example (see more examples in the links above):
using (IReadWriteBitmapData indexedTarget = myIndexedBitmap.GetReadWriteBitmapData())
using (IReadableBitmapData source = someTrueColorBitmap.GetReadableBitmapData())
{
// or DrawIntoAsync if you want to use async-await
source.DrawInto(indexedTarget, targetRect, OrderedDitherer.Bayer8x8);
}
Image examples:
All images below had been created with PixelFormat.Format8bppIndexed
format with the default palette, and a 256x256 icon and an alpha gradient rainbow were drawn on top of each other. Note that blending is used as much as possible with the available palette.
Disclaimer: Of course, the library has also some limitations compared to Graphics
, for example there are no shape-drawing methods. But in worst case you still can use the accepted answer, and then call the ConvertPixelFormat
method in the end if you need to produce an indexed result.