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