1 /*
2  * Copyright (C) 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 
17 package android.renderscript.cts.refocus;
18 
19 import android.graphics.Bitmap;
20 import android.graphics.Color;
21 import java.lang.Math;
22 
23 public class ImageCompare {
24 
25     /**
26      * Compute the luma channel of an RGB image, i.e., the Y channel of the
27      * equivalent YCbCr image.
28      * https://en.wikipedia.org/wiki/YCbCr
29      */
luma(int pixel)30     private static double luma(int pixel) {
31         final int R = Color.red(pixel);
32         final int G = Color.green(pixel);
33         final int B = Color.blue(pixel);
34         return 0.299 * R + 0.587 * G + 0.114 * B;
35     }
36 
37     /**
38      * Compute peak signal-to-noise ration (PSNR) between two images
39      * The greater the value of psnr, the closer the two images are to each
40      * other. For identical images, psnr = +infinity.
41      * For 8-bit images, a psnr above 50 is commonly acceptable for a lossy
42      * conversion.
43      *
44      * References:
45      * http://www.mathworks.com/help/vision/ref/psnr.html
46      * https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio
47      */
psnr(Bitmap bitmap1, Bitmap bitmap2)48     public static double psnr(Bitmap bitmap1, Bitmap bitmap2) {
49         if (bitmap1.getWidth() != bitmap2.getWidth() ||
50             bitmap1.getHeight() != bitmap2.getHeight()) {
51             throw new RuntimeException("images were of diffrent size");
52         }
53 
54         if (bitmap1.sameAs(bitmap2)) {
55             android.util.Log.i("RefocusTest",
56                                "bitmaps verified to be identical in fast path.");
57             return Double.POSITIVE_INFINITY;
58         }
59 
60         final int width = bitmap1.getWidth();
61         final int height = bitmap1.getHeight();
62         final int numPixels = width * height;
63 
64         double noise = 0;
65         for (int y = 0; y < height; y++) {
66             for (int x = 0; x < width; x++) {
67                 int pixel1 = bitmap1.getPixel(x, y);
68                 int pixel2 = bitmap2.getPixel(x, y);
69                 if (pixel1 != pixel2) {
70                     final double Y1 = luma(pixel1);
71                     final double Y2 = luma(pixel2);
72                     noise += (Y1 - Y2) * (Y1 - Y2);
73                 }
74             }
75         }
76 
77         final double mse = noise / numPixels;
78         final double psnr = 20 * Math.log10(255) - 10 * Math.log10(mse);
79         return psnr;
80     }
81 }
82