1 /*
2  * Copyright 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.hardware.camera2.cts.rs;
17 
18 import android.graphics.Bitmap;
19 import android.graphics.Color;
20 
21 /**
22  * Utility class providing methods for various pixel-wise ARGB bitmap operations.
23  */
24 public class BitmapUtils {
25     private static final String TAG = "BitmapUtils";
26     private static final int COLOR_BIT_DEPTH = 256;
27     public static int NUM_CHANNELS = 4;
28 
29     // Some stats output from comparing two Bitmap using calcDifferenceMetric
30     public static class BitmapCompareResult {
31         // difference between two bitmaps using average of per-pixel differences.
32         public double mDiff;
33         // If the LHS Bitmap has same RGB values for all pixels
34         public boolean mLhsFlat;
35         // If the RHS Bitmap has same RGB values for all pixels
36         public boolean mRhsFlat;
37         // The R/G/B average pixel value of LHS Bitmap
38         public double[] mLhsAverage = new double[3];
39         // The R/G/B average pixel value of RHS Bitmap
40         public double[] mRhsAverage = new double[3];
41     }
42 
43     /**
44      * Compare two bitmaps and also return some statistics about the two Bitmap.
45      *
46      * @param a first {@link android.graphics.Bitmap}.
47      * @param b second {@link android.graphics.Bitmap}.
48      * @return the results in a BitmapCompareResult
49      */
compareBitmap(Bitmap a, Bitmap b)50     public static BitmapCompareResult compareBitmap(Bitmap a, Bitmap b) {
51         if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) {
52             throw new IllegalArgumentException("Bitmap dimensions for arguments do not match a=" +
53                     a.getWidth() + "x" + a.getHeight() + ", b=" + b.getWidth() + "x" +
54                     b.getHeight());
55         }
56 
57         int[] aPixels = new int[a.getHeight() * a.getWidth()];
58         int[] bPixels = new int[aPixels.length];
59         a.getPixels(aPixels, /*offset*/0, /*stride*/a.getWidth(), /*x*/0, /*y*/0, a.getWidth(),
60                 a.getHeight());
61         b.getPixels(bPixels, /*offset*/0, /*stride*/b.getWidth(), /*x*/0, /*y*/0, b.getWidth(),
62                 b.getHeight());
63         double diff = 0;
64         double[] aSum = new double[3];
65         double[] bSum = new double[3];
66         int[] aFirstPix = new int[3];
67         int[] bFirstPix = new int[3];
68         aFirstPix[0] = Color.red(aPixels[0]);
69         aFirstPix[1] = Color.green(aPixels[1]);
70         aFirstPix[2] = Color.blue(aPixels[2]);
71         bFirstPix[0] = Color.red(bPixels[0]);
72         bFirstPix[1] = Color.green(bPixels[1]);
73         bFirstPix[2] = Color.blue(bPixels[2]);
74         boolean isAFlat = true, isBFlat = true;
75 
76         for (int i = 0; i < aPixels.length; i++) {
77             int aPix = aPixels[i];
78             int bPix = bPixels[i];
79             int aR = Color.red(aPix);
80             int aG = Color.green(aPix);
81             int aB = Color.blue(aPix);
82             int bR = Color.red(bPix);
83             int bG = Color.green(bPix);
84             int bB = Color.blue(bPix);
85             aSum[0] += aR;
86             aSum[1] += aG;
87             aSum[2] += aB;
88             bSum[0] += bR;
89             bSum[1] += bG;
90             bSum[2] += bB;
91 
92             if (isAFlat && (aR != aFirstPix[0] || aG != aFirstPix[1] || aB != aFirstPix[2])) {
93                 isAFlat = false;
94             }
95 
96             if (isBFlat && (bR != bFirstPix[0] || bG != bFirstPix[1] || bB != bFirstPix[2])) {
97                 isBFlat = false;
98             }
99 
100             diff += Math.abs(aR - bR); // red
101             diff += Math.abs(aG - bG); // green
102             diff += Math.abs(aB - bB); // blue
103         }
104         diff /= (aPixels.length * 3);
105         BitmapCompareResult result = new BitmapCompareResult();
106         result.mDiff = diff;
107         result.mLhsFlat = isAFlat;
108         result.mRhsFlat = isBFlat;
109         for (int i = 0; i < 3; i++) {
110             result.mLhsAverage[i] = aSum[i] / aPixels.length;
111             result.mRhsAverage[i] = bSum[i] / bPixels.length;
112         }
113         return result;
114     }
115 
116     /**
117      * Find the difference between two bitmaps using average of per-pixel differences.
118      *
119      * @param a first {@link android.graphics.Bitmap}.
120      * @param b second {@link android.graphics.Bitmap}.
121      * @return the difference.
122      */
calcDifferenceMetric(Bitmap a, Bitmap b)123     public static double calcDifferenceMetric(Bitmap a, Bitmap b) {
124         BitmapCompareResult result = compareBitmap(a, b);
125         return result.mDiff;
126     }
127 
128 }
129