1c3683b552f592d8039a466c663f7de8c8286e975Chris Craik/* 2c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * Copyright (C) 2012 The Android Open Source Project 3c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * 4c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * you may not use this file except in compliance with the License. 6c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * You may obtain a copy of the License at 7c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * 8c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 9c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * 10c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * Unless required by applicable law or agreed to in writing, software 11c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * See the License for the specific language governing permissions and 14c3683b552f592d8039a466c663f7de8c8286e975Chris Craik * limitations under the License. 15c3683b552f592d8039a466c663f7de8c8286e975Chris Craik */ 16c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 17c3683b552f592d8039a466c663f7de8c8286e975Chris Craikpackage com.android.test.hwuicompare; 18c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 19c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport com.android.test.hwuicompare.R; 20c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport com.android.test.hwuicompare.ScriptC_errorCalculator; 21c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 22c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport android.content.Context; 23c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport android.content.res.Resources; 24c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport android.graphics.Bitmap; 25c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport android.graphics.Color; 26c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport android.renderscript.Allocation; 27c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport android.renderscript.Element; 28c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport android.renderscript.RenderScript; 29c3683b552f592d8039a466c663f7de8c8286e975Chris Craikimport android.util.Log; 30c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 31c3683b552f592d8039a466c663f7de8c8286e975Chris Craikpublic class ErrorCalculator { 32c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private static final String LOG_TAG = "ErrorCalculator"; 33c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private static final int REGION_SIZE = 8; 34c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 35c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private static final boolean LOG_TIMING = false; 36c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private static final boolean LOG_CALC = false; 37c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 38c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private final RenderScript mRS; 39c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private Allocation mIdealPixelsAllocation; 40c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private Allocation mGivenPixelsAllocation; 41c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private Allocation mOutputPixelsAllocation; 42c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 43c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private final Allocation mInputRowsAllocation; 44c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private final Allocation mOutputRegionsAllocation; 45c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 46c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private final ScriptC_errorCalculator mScript; 47c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 48c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private final int[] mOutputRowRegions; 49c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 50c3683b552f592d8039a466c663f7de8c8286e975Chris Craik public ErrorCalculator(Context c, Resources resources) { 51c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int width = resources.getDimensionPixelSize(R.dimen.layer_width); 52c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int height = resources.getDimensionPixelSize(R.dimen.layer_height); 53c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mOutputRowRegions = new int[height / REGION_SIZE]; 54c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 55c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mRS = RenderScript.create(c); 56c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int[] rowIndices = new int[height / REGION_SIZE]; 57c3683b552f592d8039a466c663f7de8c8286e975Chris Craik for (int i = 0; i < rowIndices.length; i++) 58c3683b552f592d8039a466c663f7de8c8286e975Chris Craik rowIndices[i] = i * REGION_SIZE; 59c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 60c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript = new ScriptC_errorCalculator(mRS, resources, R.raw.errorcalculator); 61c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.set_HEIGHT(height); 62c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.set_WIDTH(width); 63c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.set_REGION_SIZE(REGION_SIZE); 64c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 65c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mInputRowsAllocation = Allocation.createSized(mRS, Element.I32(mRS), rowIndices.length, 66c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Allocation.USAGE_SCRIPT); 67c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mInputRowsAllocation.copyFrom(rowIndices); 68c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mOutputRegionsAllocation = Allocation.createSized(mRS, Element.I32(mRS), 69c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mOutputRowRegions.length, Allocation.USAGE_SCRIPT); 70c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 71c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 72c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 73c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private static long startMillis, middleMillis; 74c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 75c3683b552f592d8039a466c663f7de8c8286e975Chris Craik public float calcErrorRS(Bitmap ideal, Bitmap given) { 76c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (LOG_TIMING) { 77c3683b552f592d8039a466c663f7de8c8286e975Chris Craik startMillis = System.currentTimeMillis(); 78c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 79c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 80c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mIdealPixelsAllocation = Allocation.createFromBitmap(mRS, ideal, 81c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 82c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mGivenPixelsAllocation = Allocation.createFromBitmap(mRS, given, 83c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 84c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 85c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.bind_ideal(mIdealPixelsAllocation); 86c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.bind_given(mGivenPixelsAllocation); 87c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 88c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.forEach_countInterestingRegions(mInputRowsAllocation, mOutputRegionsAllocation); 89c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mOutputRegionsAllocation.copyTo(mOutputRowRegions); 90c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 91c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int regionCount = 0; 92c3683b552f592d8039a466c663f7de8c8286e975Chris Craik for (int region : mOutputRowRegions) { 93c3683b552f592d8039a466c663f7de8c8286e975Chris Craik regionCount += region; 94c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 95c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int interestingPixels = Math.max(1, regionCount) * REGION_SIZE * REGION_SIZE; 96c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 97c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (LOG_TIMING) { 98c3683b552f592d8039a466c663f7de8c8286e975Chris Craik long startMillis2 = System.currentTimeMillis(); 99c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 100c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 101c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.forEach_accumulateError(mInputRowsAllocation, mOutputRegionsAllocation); 102c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mOutputRegionsAllocation.copyTo(mOutputRowRegions); 103c3683b552f592d8039a466c663f7de8c8286e975Chris Craik float totalError = 0; 104c3683b552f592d8039a466c663f7de8c8286e975Chris Craik for (int row : mOutputRowRegions) { 105c3683b552f592d8039a466c663f7de8c8286e975Chris Craik totalError += row; 106c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 107c3683b552f592d8039a466c663f7de8c8286e975Chris Craik totalError /= 1024.0f; 108c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 109c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (LOG_TIMING) { 110c3683b552f592d8039a466c663f7de8c8286e975Chris Craik long finalMillis = System.currentTimeMillis(); 111c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Log.d(LOG_TAG, "rs: first part took " + (middleMillis - startMillis) + "ms"); 112c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Log.d(LOG_TAG, "rs: last part took " + (finalMillis - middleMillis) + "ms"); 113c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 114c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (LOG_CALC) { 115c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Log.d(LOG_TAG, "rs: error " + totalError + ", pixels " + interestingPixels); 116c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 117c3683b552f592d8039a466c663f7de8c8286e975Chris Craik return totalError / interestingPixels; 118c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 119c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 120c3683b552f592d8039a466c663f7de8c8286e975Chris Craik public void calcErrorHeatmapRS(Bitmap ideal, Bitmap given, Bitmap output) { 121c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mIdealPixelsAllocation = Allocation.createFromBitmap(mRS, ideal, 122c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 123c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mGivenPixelsAllocation = Allocation.createFromBitmap(mRS, given, 124c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 125c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 126c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.bind_ideal(mIdealPixelsAllocation); 127c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.bind_given(mGivenPixelsAllocation); 128c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 129c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mOutputPixelsAllocation = Allocation.createFromBitmap(mRS, output, 130c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); 131c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mScript.forEach_displayDifference(mOutputPixelsAllocation, mOutputPixelsAllocation); 132c3683b552f592d8039a466c663f7de8c8286e975Chris Craik mOutputPixelsAllocation.copyTo(output); 133c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 134c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 135c3683b552f592d8039a466c663f7de8c8286e975Chris Craik public static float calcError(Bitmap ideal, Bitmap given) { 136c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (LOG_TIMING) { 137c3683b552f592d8039a466c663f7de8c8286e975Chris Craik startMillis = System.currentTimeMillis(); 138c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 139c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 140c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int interestingRegions = 0; 141c3683b552f592d8039a466c663f7de8c8286e975Chris Craik for (int x = 0; x < ideal.getWidth(); x += REGION_SIZE) { 142c3683b552f592d8039a466c663f7de8c8286e975Chris Craik for (int y = 0; y < ideal.getWidth(); y += REGION_SIZE) { 143c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (inspectRegion(ideal, x, y)) { 144c3683b552f592d8039a466c663f7de8c8286e975Chris Craik interestingRegions++; 145c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 146c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 147c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 148c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 149c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int interestingPixels = Math.max(1, interestingRegions) * REGION_SIZE * REGION_SIZE; 150c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 151c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (LOG_TIMING) { 152c3683b552f592d8039a466c663f7de8c8286e975Chris Craik long startMillis2 = System.currentTimeMillis(); 153c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 154c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 155c3683b552f592d8039a466c663f7de8c8286e975Chris Craik float totalError = 0; 156c3683b552f592d8039a466c663f7de8c8286e975Chris Craik for (int x = 0; x < ideal.getWidth(); x++) { 157c3683b552f592d8039a466c663f7de8c8286e975Chris Craik for (int y = 0; y < ideal.getHeight(); y++) { 158c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int idealColor = ideal.getPixel(x, y); 159c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int givenColor = given.getPixel(x, y); 160c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (idealColor == givenColor) 161c3683b552f592d8039a466c663f7de8c8286e975Chris Craik continue; 162c3683b552f592d8039a466c663f7de8c8286e975Chris Craik totalError += Math.abs(Color.red(idealColor) - Color.red(givenColor)); 163c3683b552f592d8039a466c663f7de8c8286e975Chris Craik totalError += Math.abs(Color.green(idealColor) - Color.green(givenColor)); 164c3683b552f592d8039a466c663f7de8c8286e975Chris Craik totalError += Math.abs(Color.blue(idealColor) - Color.blue(givenColor)); 165c3683b552f592d8039a466c663f7de8c8286e975Chris Craik totalError += Math.abs(Color.alpha(idealColor) - Color.alpha(givenColor)); 166c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 167c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 168c3683b552f592d8039a466c663f7de8c8286e975Chris Craik totalError /= 1024.0f; 169c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (LOG_TIMING) { 170c3683b552f592d8039a466c663f7de8c8286e975Chris Craik long finalMillis = System.currentTimeMillis(); 171c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Log.d(LOG_TAG, "dvk: first part took " + (middleMillis - startMillis) + "ms"); 172c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Log.d(LOG_TAG, "dvk: last part took " + (finalMillis - middleMillis) + "ms"); 173c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 174c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (LOG_CALC) { 175c3683b552f592d8039a466c663f7de8c8286e975Chris Craik Log.d(LOG_TAG, "dvk: error " + totalError + ", pixels " + interestingPixels); 176c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 177c3683b552f592d8039a466c663f7de8c8286e975Chris Craik return totalError / interestingPixels; 178c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 179c3683b552f592d8039a466c663f7de8c8286e975Chris Craik 180c3683b552f592d8039a466c663f7de8c8286e975Chris Craik private static boolean inspectRegion(Bitmap ideal, int x, int y) { 181c3683b552f592d8039a466c663f7de8c8286e975Chris Craik int regionColor = ideal.getPixel(x, y); 182c3683b552f592d8039a466c663f7de8c8286e975Chris Craik for (int i = 0; i < REGION_SIZE; i++) { 183c3683b552f592d8039a466c663f7de8c8286e975Chris Craik for (int j = 0; j < REGION_SIZE; j++) { 184c3683b552f592d8039a466c663f7de8c8286e975Chris Craik if (ideal.getPixel(x + i, y + j) != regionColor) 185c3683b552f592d8039a466c663f7de8c8286e975Chris Craik return true; 186c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 187c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 188c3683b552f592d8039a466c663f7de8c8286e975Chris Craik return false; 189c3683b552f592d8039a466c663f7de8c8286e975Chris Craik } 190c3683b552f592d8039a466c663f7de8c8286e975Chris Craik} 191