Intro
Current API provided by Android Bitmap doesn’t provide a constructor
to create a mutable bitmap object, however you can make it mutable by copying
the existing one with a mutable flag set.
e.g.
Bitmap bitmap = new Bitmap(100, 100, Bitmap.Config.Argb8888);
Bitmap mutableBitmap = bm.Copy(Bitmap.Config.Argb8888, true);
Another way is to use a BitmapFactory and create bitmap
object from stream or byte array with a mutable flag set.So for byte array it goes like this:
BitmapFactory.Options options = new BitmapFactory.Options();
options.InMutable
= true;
options.InPreferredConfig
= Bitmap.Config.Argb8888;
Bitmap result = BitmapFactory.DecodeByteArray(imageData, 0, imageData.Length, options);
But imageData
is required to contain an encoded image not the raw pixel data. One of the
solutions here that doesn’t require bitmap copying or reading from disk is to
provide BitmapFactory with some data it’s able to recognize as an image and
therefore decode.
The code
/// <summary>
/// A bitmap helper class by Apitron.
/// </summary>
static class BitmapHelper
{
/// <summary>
/// Creates mutable bitmap with ARGB32 pixel format.
/// </summary>
/// <param name="width">The width of the bitmap.</param>
/// <param
name="height">The height of the
bitmap.</param>
/// <returns>Created bitmap.</returns>
public static Bitmap CreateMutableBitmapARGB32(int width, int height)
{
// pixel
data
uint pixelDataSize = (uint) (width*height*4);
byte[] imageData = new byte[pixelDataSize+54];
//
BITMAPFILEHEADER
//
"BM" +2
imageData[0] = 0x42;
imageData[1] = 0x4D;
//
bitmapsize +4; pixeldata size + bitmap file header(14 bytes) + bitmapinfo
header(40 bytes)
Array.Copy(BitConverter.GetBytes(pixelDataSize+54), 0, imageData, 2, 4);
//
reserved +4
imageData[6] = 0;
imageData[7] = 0;
imageData[8] = 0;
imageData[9] = 0;
// pixel
offset +4
imageData[10] = 54;
imageData[11] = 0;
imageData[12] = 0;
imageData[13] = 0;
//
BITMAPINFOHEADER
//
header size offset +4
imageData[14] = 40;
imageData[15] = 0;
imageData[16] = 0;
imageData[17] = 0;
//
bitmapWidth +4
Array.Copy(BitConverter.GetBytes(width), 0, imageData, 18, 4);
// bitmapHeight
+4
Array.Copy(BitConverter.GetBytes(height), 0, imageData, 22, 4);
//
planes +2
imageData[26] = 1;
imageData[27] = 0;
//
bitcount +2
imageData[28] = 32;
imageData[29] = 0;
// compression
+4, BI_RGB
imageData[30] = 0;
imageData[31] = 0;
imageData[32] = 0;
imageData[33] = 0;
// pixel
data size +4
Array.Copy(BitConverter.GetBytes(pixelDataSize), 0, imageData, 34, 4);
//
dpiX +4
Array.Copy(BitConverter.GetBytes(2835), 0, imageData, 38, 4);
// dpiY
+4
Array.Copy(BitConverter.GetBytes(2835), 0, imageData, 42, 4);
//
clrUsed +4
imageData[46] = 0;
imageData[47] = 0;
imageData[48] = 0;
imageData[49] = 0;
// clr
important +4
imageData[50] = 0;
imageData[51] = 0;
imageData[52] = 0;
imageData[53] = 0;
BitmapFactory.Options options = new BitmapFactory.Options();
options.InMutable = true;
options.InPreferredConfig = Bitmap.Config.Argb8888;
Bitmap result = BitmapFactory.DecodeByteArray(imageData, 0, imageData.Length, options);
result.HasAlpha = true;
return result;
}
}
So
it just creates a byte array sized to fit the requested bitmap data and adds
BITMAPFILEHEADER and BITMAPINFOHEADER to make it look like an image in BMP
format for BitmapFactory. Hope it will help someone looking for a mutable
bitmap.
No comments:
Post a Comment