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