Android(Java)中RGB转XYZ再转LAB及LAB图像生成方法问询
Alright, let's walk through how to manually implement RGB → XYZ → LAB conversion in Android (Java) without relying on OpenCV's built-in functions. I'll break this into clear, actionable steps with code snippets you can drop right into your project.
Step 1: Quick Primer on the Conversion Pipeline
First, let's recap the flow we're implementing:
- Normalize RGB values: Convert 0-255 RGB channels to 0-1 floating point values, then apply gamma correction to get linear RGB.
- Linear RGB → XYZ: Use the standard sRGB to XYZ transformation matrix.
- XYZ → LAB: Convert using the D65 reference white point (the standard for most digital displays) and the CIE LAB formulas.
Step 2: RGB to XYZ Conversion
First, we need to handle gamma correction and the matrix transformation. Here's a static method that takes 0-255 RGB values and returns an XYZ float array:
public static float[] rgbToXyz(int r, int g, int b) { // Normalize RGB to 0-1 range float rf = r / 255.0f; float gf = g / 255.0f; float bf = b / 255.0f; // Apply gamma correction rf = (rf > 0.04045f) ? (float) Math.pow((rf + 0.055f) / 1.055f, 2.4f) : rf / 12.92f; gf = (gf > 0.04045f) ? (float) Math.pow((gf + 0.055f) / 1.055f, 2.4f) : gf / 12.92f; bf = (bf > 0.04045f) ? (float) Math.pow((bf + 0.055f) / 1.055f, 2.4f) : bf / 12.92f; // Apply sRGB to XYZ transformation matrix float x = rf * 0.4124564f + gf * 0.3575761f + bf * 0.1804375f; float y = rf * 0.2126729f + gf * 0.7151522f + bf * 0.0721750f; float z = rf * 0.0193339f + gf * 0.1191920f + bf * 0.9503041f; // Scale to standard XYZ range (X:0-95.047, Y:0-100, Z:0-108.883) x *= 100.0f; y *= 100.0f; z *= 100.0f; return new float[]{x, y, z}; }
Step 3: XYZ to LAB Conversion
Next, we convert XYZ to LAB using the D65 reference white point. Here's the method:
// D65 reference white point values private static final float Xn = 95.047f; private static final float Yn = 100.0f; private static final float Zn = 108.883f; public static float[] xyzToLab(float x, float y, float z) { // Normalize XYZ against reference white point float xr = x / Xn; float yr = y / Yn; float zr = z / Zn; // Apply the f(t) function xr = (xr > 0.008856f) ? (float) Math.pow(xr, 1.0/3.0) : (7.787f * xr) + (16.0f / 116.0f); yr = (yr > 0.008856f) ? (float) Math.pow(yr, 1.0/3.0) : (7.787f * yr) + (16.0f / 116.0f); zr = (zr > 0.008856f) ? (float) Math.pow(zr, 1.0/3.0) : (7.787f * zr) + (16.0f / 116.0f); // Calculate LAB values float L = (116.0f * yr) - 16.0f; float a = 500.0f * (xr - yr); float b = 200.0f * (yr - zr); return new float[]{L, a, b}; }
Step 4: Convert an Entire RGB Bitmap to LAB in Android
Now, let's put this together to process a full Bitmap. Note that LAB values don't fit into the 0-255 range of standard Bitmaps, so we'll map them to 0-255 for storage (L: 0-100 → 0-255; a/b: -128 to 127 → 0-255):
public static Bitmap convertRgbBitmapToLab(Bitmap rgbBitmap) { int width = rgbBitmap.getWidth(); int height = rgbBitmap.getHeight(); Bitmap labBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); int[] pixels = new int[width * height]; rgbBitmap.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 0; i < pixels.length; i++) { int pixel = pixels[i]; // Extract RGB channels from ARGB pixel int r = (pixel >> 16) & 0xFF; int g = (pixel >> 8) & 0xFF; int b = pixel & 0xFF; // Convert to XYZ then LAB float[] xyz = rgbToXyz(r, g, b); float[] lab = xyzToLab(xyz[0], xyz[1], xyz[2]); // Map LAB to 0-255 for Bitmap storage int l = Math.round(lab[0] * 2.55f); // L: 0-100 → 0-255 int a = Math.round(lab[1] + 128.0f); // a: -128→127 → 0→255 int ab = Math.round(lab[2] + 128.0f); // b: -128→127 → 0→255 // Reconstruct ARGB pixel (alpha remains 255) pixels[i] = (0xFF << 24) | (l << 16) | (a << 8) | ab; } labBitmap.setPixels(pixels, 0, width, 0, 0, width, height); return labBitmap; }
Key Notes
- Performance: For large Bitmaps, consider running this conversion on a background thread (like using
AsyncTaskor Kotlin Coroutines) to avoid blocking the UI thread. - Accuracy: The matrices and reference white point used here follow the standard sRGB to CIE LAB conversion, which matches most industry implementations.
- Reverse Conversion: If you ever need to go back from LAB to RGB, you can reverse the formulas (implement LAB→XYZ→linear RGB→gamma-corrected RGB).
内容的提问来源于stack exchange,提问作者yasir gakhar

