Open alonalbert opened 1 year ago
cc @hoisie and @JuliaSullivanGoogle for RNG's compatibility behavior.
@alonalbert can you try with Robolectric 4.13 to see if this issue still exists?
Now it fails with:
Expected :10 20 30 ff
Actual :ff 10 20 30
I realize that ff 10 20 30
looks correct since we have the ARGB in that order, but when I run the test as an instrumented test, it does pass:
As a Robolectric test, it fails:
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(NATIVE)
class ExampleUnitTest {
@Test
fun testBitmapColor() {
val color = 0xff102030.toInt()
val bitmap = Bitmap.createBitmap(listOf(color).toIntArray(), 1, 1, ARGB_8888)
val buffer = ByteBuffer.allocate(bitmap.byteCount)
bitmap.copyPixelsToBuffer(buffer)
buffer.rewind()
val bytes = (0 until buffer.limit()).joinToString(" ") { "%02x".format(buffer.get(it)) }
assertEquals("10 20 30 ff", bytes)
}
}
As an Instrumented test, it passes:
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun testBitmapColor() {
val color = 0xff102030.toInt()
val bitmap = Bitmap.createBitmap(listOf(color).toIntArray(), 1, 1, ARGB_8888)
val buffer = ByteBuffer.allocate(bitmap.byteCount)
bitmap.copyPixelsToBuffer(buffer)
buffer.rewind()
val bytes = (0 until buffer.limit()).joinToString(" ") { "%02x".format(buffer.get(it)) }
assertEquals("10 20 30 ff", bytes)
}
}
In Android when a Bitmap is created, the underlying Skia Bitmap (SkBitmap) object in native code is using kN32_SkColorType
for the memory layout of the pixel data. This can vary across architectures depending on endianness. The value is determined by ifdef logic at build-time, so it depends on the build machine. See:
I think on Linux and Windows, it ends up being kBGRA_8888_SkColorType
, but on Mac it is kRGBA_8888_SkColorType
.
@alonalbert if that test is run on Mac, my guess is that it would pass.
As far as I know, the best approach is to usebitmap.getPixels
to return unpremultiplied ARGB, which is consistent across platforms. There may be something you can do with AWT's BufferedImage, but I'm not 100% sure.
For a bitmap created with
ARGB_8888
, the methodcopyPixelsToBuffer
behaves differently in Robolectric@GraphicsMode(NATIVE)
that it does on a device.Each pixel is represented by 4 bytes in the output buffer but on a device, the bytes are
RGBA
while in Robolectric, they areBGRA
.This can be demonstrated by the following test:
This test will succeed when run with
@RunWith(AndroidJUnit4::class)
but will fail when run with:With:
Note that for
RGB_565
, both Robolectric and device emit the same results.