Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider adding workaround for U + gainmap + hardware bitmap bug #2094

Open
jreck opened this issue Jan 31, 2024 · 2 comments
Open

Consider adding workaround for U + gainmap + hardware bitmap bug #2094

jreck opened this issue Jan 31, 2024 · 2 comments
Labels
help wanted Issues that are up for grabs + are good candidates for community PRs

Comments

@jreck
Copy link

jreck commented Jan 31, 2024

Prior to Android V there exists a bug where when:

  1. A decode to Config.HARDWARE is requested
  2. The image format is A8 / gray8
  3. The device supports A8 hardware buffers
  4. The device is using OpenGL

Then the decode fails. As A8 images are extremely rare, this hadn't come up before. However, with the addition of gainmap images the usage of A8 "images" became much more common as a common space/quality tradeoff for the gainmap is to use a8 and provide only luminance modulation as a result. In this scenario it becomes quite possible for all 4 of the above conditions to be hit.

However, it is rather easy to both detect the presence of the bug (simply try to copy an A8 bitmap to Config.HARDWARE - if null is returned the bug is present) and to workaround it in a decently efficient means by simply decoding to non-hardware first, converting the A8 gainmap to 8888, and then copying the result to HARDWARE and returning that. This is not dissimilar to how decoding directly to HARDWARE works, so performance impact should be minimal. See the Glide implementation of both here: bumptech/glide#5357

If nothing is done about this then the failure mode is simply that the decoding of the gainmap portion fails, but the primary image is still successfully returned. As in, the behavior simply matches what Android T did, prior to the introduction of gainmaps. So the failure mode is quite forgiving.

@jreck
Copy link
Author

jreck commented Jan 31, 2024

To reproduce decode this: https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/tests/graphics/SilkFX/assets/gainmaps/fountain_night.jpg

to a Config.HARDWARE output and check that bitmap#getGainmap() returns non-null. You can force this failure path on a pixel device by first doing adb shell setprop debug.hwui.renderer skiagl (kill & re-launch the app to pick up the setting change)

@colinrtwhite colinrtwhite added the help wanted Issues that are up for grabs + are good candidates for community PRs label Feb 1, 2024
@jreck
Copy link
Author

jreck commented Mar 13, 2024

Correction to #1, you can't simply .copy the Config.ALPHA_8 to Config.ARGB_8888, you need to instead do this:

private static Bitmap copyWithOpaqueAlpha(Bitmap bitmap) {
  Bitmap newContents =
      Bitmap.createBitmap(
          bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888);
  Canvas canvas = new Canvas(newContents);
  Paint paint = new Paint();
  paint.setColorFilter(
      new ColorMatrixColorFilter(
          new float[] {
            0f, 0f, 0f, 1f, 0f,
            0f, 0f, 0f, 1f, 0f,
            0f, 0f, 0f, 1f, 0f,
            0f, 0f, 0f, 0f, 255f
          }));
  canvas.drawBitmap(bitmap, 0f, 0f, paint);
  canvas.setBitmap(null);
  return newContents;
}

to transform the alpha into rgbx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Issues that are up for grabs + are good candidates for community PRs
Projects
None yet
Development

No branches or pull requests

2 participants