1 /* 2 * Copyright (C) 2012 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 com.android.test.hwuicompare; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.graphics.Bitmap; 22 import android.graphics.Color; 23 import android.renderscript.Allocation; 24 import android.renderscript.Element; 25 import android.renderscript.RenderScript; 26 import android.util.Log; 27 28 public class ErrorCalculator { 29 private static final String LOG_TAG = "ErrorCalculator"; 30 private static final int REGION_SIZE = 8; 31 32 private static final boolean LOG_TIMING = false; 33 private static final boolean LOG_CALC = false; 34 35 private RenderScript mRS; 36 private Allocation mIdealPixelsAllocation; 37 private Allocation mGivenPixelsAllocation; 38 private Allocation mOutputPixelsAllocation; 39 40 private Allocation mInputRowsAllocation; 41 private Allocation mOutputRegionsAllocation; 42 43 private ScriptC_errorCalculator mScript; 44 45 private int[] mOutputRowRegions; 46 47 public ErrorCalculator(Context c, Resources resources) { 48 int width = resources.getDimensionPixelSize(R.dimen.layer_width); 49 int height = resources.getDimensionPixelSize(R.dimen.layer_height); 50 mOutputRowRegions = new int[height / REGION_SIZE]; 51 52 mRS = RenderScript.create(c); 53 int[] rowIndices = new int[height / REGION_SIZE]; 54 for (int i = 0; i < rowIndices.length; i++) 55 rowIndices[i] = i * REGION_SIZE; 56 57 mScript = new ScriptC_errorCalculator(mRS); 58 mScript.set_HEIGHT(height); 59 mScript.set_WIDTH(width); 60 mScript.set_REGION_SIZE(REGION_SIZE); 61 62 mInputRowsAllocation = Allocation.createSized(mRS, Element.I32(mRS), rowIndices.length, 63 Allocation.USAGE_SCRIPT); 64 mInputRowsAllocation.copyFrom(rowIndices); 65 mOutputRegionsAllocation = Allocation.createSized(mRS, Element.I32(mRS), 66 mOutputRowRegions.length, Allocation.USAGE_SCRIPT); 67 } 68 69 70 private static long startMillis, middleMillis; 71 72 public float calcErrorRS(Bitmap ideal, Bitmap given) { 73 if (LOG_TIMING) { 74 startMillis = System.currentTimeMillis(); 75 } 76 77 mIdealPixelsAllocation = Allocation.createFromBitmap(mRS, ideal, 78 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 79 mGivenPixelsAllocation = Allocation.createFromBitmap(mRS, given, 80 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 81 82 mScript.set_ideal(mIdealPixelsAllocation); 83 mScript.set_given(mGivenPixelsAllocation); 84 85 mScript.forEach_countInterestingRegions(mInputRowsAllocation, mOutputRegionsAllocation); 86 mOutputRegionsAllocation.copyTo(mOutputRowRegions); 87 88 int regionCount = 0; 89 for (int region : mOutputRowRegions) { 90 regionCount += region; 91 } 92 int interestingPixels = Math.max(1, regionCount) * REGION_SIZE * REGION_SIZE; 93 94 if (LOG_TIMING) { 95 long startMillis2 = System.currentTimeMillis(); 96 } 97 98 mScript.forEach_accumulateError(mInputRowsAllocation, mOutputRegionsAllocation); 99 mOutputRegionsAllocation.copyTo(mOutputRowRegions); 100 float totalError = 0; 101 for (int row : mOutputRowRegions) { 102 totalError += row; 103 } 104 totalError /= 1024.0f; 105 106 if (LOG_TIMING) { 107 long finalMillis = System.currentTimeMillis(); 108 Log.d(LOG_TAG, "rs: first part took " + (middleMillis - startMillis) + "ms"); 109 Log.d(LOG_TAG, "rs: last part took " + (finalMillis - middleMillis) + "ms"); 110 } 111 if (LOG_CALC) { 112 Log.d(LOG_TAG, "rs: error " + totalError + ", pixels " + interestingPixels); 113 } 114 return totalError / interestingPixels; 115 } 116 117 public void calcErrorHeatmapRS(Bitmap ideal, Bitmap given, Bitmap output) { 118 mIdealPixelsAllocation = Allocation.createFromBitmap(mRS, ideal, 119 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 120 mGivenPixelsAllocation = Allocation.createFromBitmap(mRS, given, 121 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 122 123 mScript.set_ideal(mIdealPixelsAllocation); 124 mScript.set_given(mGivenPixelsAllocation); 125 126 mOutputPixelsAllocation = Allocation.createFromBitmap(mRS, output, 127 Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 128 mScript.forEach_displayDifference(mOutputPixelsAllocation, mOutputPixelsAllocation); 129 mOutputPixelsAllocation.copyTo(output); 130 } 131 132 public static float calcError(Bitmap ideal, Bitmap given) { 133 if (LOG_TIMING) { 134 startMillis = System.currentTimeMillis(); 135 } 136 137 int interestingRegions = 0; 138 for (int x = 0; x < ideal.getWidth(); x += REGION_SIZE) { 139 for (int y = 0; y < ideal.getWidth(); y += REGION_SIZE) { 140 if (inspectRegion(ideal, x, y)) { 141 interestingRegions++; 142 } 143 } 144 } 145 146 int interestingPixels = Math.max(1, interestingRegions) * REGION_SIZE * REGION_SIZE; 147 148 if (LOG_TIMING) { 149 long startMillis2 = System.currentTimeMillis(); 150 } 151 152 float totalError = 0; 153 for (int x = 0; x < ideal.getWidth(); x++) { 154 for (int y = 0; y < ideal.getHeight(); y++) { 155 int idealColor = ideal.getPixel(x, y); 156 int givenColor = given.getPixel(x, y); 157 if (idealColor == givenColor) 158 continue; 159 totalError += Math.abs(Color.red(idealColor) - Color.red(givenColor)); 160 totalError += Math.abs(Color.green(idealColor) - Color.green(givenColor)); 161 totalError += Math.abs(Color.blue(idealColor) - Color.blue(givenColor)); 162 totalError += Math.abs(Color.alpha(idealColor) - Color.alpha(givenColor)); 163 } 164 } 165 totalError /= 1024.0f; 166 if (LOG_TIMING) { 167 long finalMillis = System.currentTimeMillis(); 168 Log.d(LOG_TAG, "dvk: first part took " + (middleMillis - startMillis) + "ms"); 169 Log.d(LOG_TAG, "dvk: last part took " + (finalMillis - middleMillis) + "ms"); 170 } 171 if (LOG_CALC) { 172 Log.d(LOG_TAG, "dvk: error " + totalError + ", pixels " + interestingPixels); 173 } 174 return totalError / interestingPixels; 175 } 176 177 private static boolean inspectRegion(Bitmap ideal, int x, int y) { 178 int regionColor = ideal.getPixel(x, y); 179 for (int i = 0; i < REGION_SIZE; i++) { 180 for (int j = 0; j < REGION_SIZE; j++) { 181 if (ideal.getPixel(x + i, y + j) != regionColor) 182 return true; 183 } 184 } 185 return false; 186 } 187 } 188