I'm trying to write a couple of methods to convert an Android Bitmap to an RGBA byte array and then back to a Bitmap. The problem is that I don't seem to hit the formula, because the colors are always coming back wrong. I have tried with several different assumptions but to no avail.
So, this is the method to convert from Bitmap to RGBA that I think is fine:
public static byte[] bitmapToRgba(Bitmap bitmap) {
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
byte[] bytes = new byte[pixels.length * 4];
bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
int i = 0;
for (int pixel : pixels) {
// Get components assuming is ARGB
int A = (pixel >> 24) & 0xff;
int R = (pixel >> 16) & 0xff;
int G = (pixel >> 8) & 0xff;
int B = pixel & 0xff;
bytes[i++] = (byte) R;
bytes[i++] = (byte) G;
bytes[i++] = (byte) B;
bytes[i++] = (byte) A;
}
return bytes;
}
And this is the method aimed at creating back a bitmap from those bytes that is not working as expected:
public static Bitmap bitmapFromRgba(int width, int height, byte[] bytes) {
int[] pixels = new int[bytes.length / 4];
int j = 0;
// It turns out Bitmap.Config.ARGB_8888 is in reality RGBA_8888!
// Source: https://stackoverflow.com/a/47982505/1160360
// Now, according to my own experiments, it seems it is ABGR... this sucks.
// So we have to change the order of the components
for (int i = 0; i < pixels.length; i++) {
byte R = bytes[j++];
byte G = bytes[j++];
byte B = bytes[j++];
byte A = bytes[j++];
int pixel = (A << 24) | (B << 16) | (G << 8) | R;
pixels[i] = pixel;
}
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(IntBuffer.wrap(pixels));
return bitmap;
}
That's my last implementation, though I have tried several different ones without success. I'm assuming createBitmap expects ABGR in spite of specifying ARGB_8888 because I have done experiments hardcoding all the pixels to things like:
0xff_ff_00_00 -> got blue
0xff_00_ff_00 -> got green
0xff_00_00_ff -> got red
Anyway maybe that assumption is wrong and a consequence of some other mistaken one before.
I think the main problem may be related to the use of signed numeric values, since there are no unsigned ones in Java (well, there's something in Java 8+ but on one hand I don't think it should be necessary to use these, and on the other it is not supported by older Android versions that I need to support).
Any help will be very appreciated.
Thanks a lot in advance!