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