Skip to content

Fix R/B channel swap in Android raw pixel data#158

Open
mrousavy wants to merge 2 commits into
mainfrom
fix/android-raw-pixel-rb-swap
Open

Fix R/B channel swap in Android raw pixel data#158
mrousavy wants to merge 2 commits into
mainfrom
fix/android-raw-pixel-rb-swap

Conversation

@mrousavy

Copy link
Copy Markdown
Owner

What

On Android, an ARGB_8888 Bitmap's memory is physically [R, G, B, A] bytes. The ARGB in the config name only describes the getPixel()/setPixel() ColorInt packing (0xAARRGGBB), not the layout that copyPixelsFromBuffer/copyPixelsToBuffer (raw memory copies) use.

Two coupled bugs made every raw pixel roundtrip swap red and blue on little-endian devices:

  • loadFromRawPixelData (slow path) packed ColorInt-ordered words and wrote them with copyPixelsFromBuffer, so on little-endian they landed as B, G, R, A bytes.
  • toRawPixelData labeled ARGB_8888 exports as BGRA, but the raw-copied bytes are physically R, G, B, A.

Fix

  • Pack the physical pixel word (0xAABBGGRR) in the slow path.
  • Label ARGB_8888 exports as RGBA.
  • Re-key the byte-identical raw-copy fast path from BGRA to RGBA, so BGRA input now goes through the corrected swizzle path.
  • Export PixelFormat, RawPixelData, EncodedImageData and ImageFormat from the entrypoint.

Note for consumers

This is a behavior fix. Code that worked around the swap by mislabeling RGBA bytes as 'BGRA' on Android must drop that workaround (for example react-native-vision-camera's harness tests).

Regression tests covering this land separately so they can validate all of the raw pixel data fixes together.

🤖 Generated with Claude Code

An ARGB_8888 Bitmap stores each pixel as a 32-bit word with R in the
least significant byte (physically [R, G, B, A] bytes). The "ARGB" in the
config name only refers to the getPixel/setPixel ColorInt packing
(0xAARRGGBB), not the memory layout that copyPixelsFromBuffer and
copyPixelsToBuffer read and write.

The slow load path packed ColorInt-ordered words, and pixelFormat
labeled ARGB_8888 exports as BGRA, so raw pixel data roundtrips swapped
red and blue on little-endian devices. Pack the physical word instead,
label exports as RGBA, and re-key the byte-identical raw-copy fast path
to RGBA so BGRA input now goes through the corrected swizzle path.

Also expose PixelFormat, RawPixelData, EncodedImageData and ImageFormat
from the package entrypoint so consumers can read the reported format.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant