/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.test.hwuicompare; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Color; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.RenderScript; import android.util.Log; public class ErrorCalculator { private static final String LOG_TAG = "ErrorCalculator"; private static final int REGION_SIZE = 8; private static final boolean LOG_TIMING = false; private static final boolean LOG_CALC = false; private RenderScript mRS; private Allocation mIdealPixelsAllocation; private Allocation mGivenPixelsAllocation; private Allocation mOutputPixelsAllocation; private Allocation mInputRowsAllocation; private Allocation mOutputRegionsAllocation; private ScriptC_errorCalculator mScript; private int[] mOutputRowRegions; public ErrorCalculator(Context c, Resources resources) { int width = resources.getDimensionPixelSize(R.dimen.layer_width); int height = resources.getDimensionPixelSize(R.dimen.layer_height); mOutputRowRegions = new int[height / REGION_SIZE]; mRS = RenderScript.create(c); int[] rowIndices = new int[height / REGION_SIZE]; for (int i = 0; i < rowIndices.length; i++) rowIndices[i] = i * REGION_SIZE; mScript = new ScriptC_errorCalculator(mRS); mScript.set_HEIGHT(height); mScript.set_WIDTH(width); mScript.set_REGION_SIZE(REGION_SIZE); mInputRowsAllocation = Allocation.createSized(mRS, Element.I32(mRS), rowIndices.length, Allocation.USAGE_SCRIPT); mInputRowsAllocation.copyFrom(rowIndices); mOutputRegionsAllocation = Allocation.createSized(mRS, Element.I32(mRS), mOutputRowRegions.length, Allocation.USAGE_SCRIPT); } private static long startMillis, middleMillis; public float calcErrorRS(Bitmap ideal, Bitmap given) { if (LOG_TIMING) { startMillis = System.currentTimeMillis(); } mIdealPixelsAllocation = Allocation.createFromBitmap(mRS, ideal, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); mGivenPixelsAllocation = Allocation.createFromBitmap(mRS, given, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); mScript.set_ideal(mIdealPixelsAllocation); mScript.set_given(mGivenPixelsAllocation); mScript.forEach_countInterestingRegions(mInputRowsAllocation, mOutputRegionsAllocation); mOutputRegionsAllocation.copyTo(mOutputRowRegions); int regionCount = 0; for (int region : mOutputRowRegions) { regionCount += region; } int interestingPixels = Math.max(1, regionCount) * REGION_SIZE * REGION_SIZE; if (LOG_TIMING) { long startMillis2 = System.currentTimeMillis(); } mScript.forEach_accumulateError(mInputRowsAllocation, mOutputRegionsAllocation); mOutputRegionsAllocation.copyTo(mOutputRowRegions); float totalError = 0; for (int row : mOutputRowRegions) { totalError += row; } totalError /= 1024.0f; if (LOG_TIMING) { long finalMillis = System.currentTimeMillis(); Log.d(LOG_TAG, "rs: first part took " + (middleMillis - startMillis) + "ms"); Log.d(LOG_TAG, "rs: last part took " + (finalMillis - middleMillis) + "ms"); } if (LOG_CALC) { Log.d(LOG_TAG, "rs: error " + totalError + ", pixels " + interestingPixels); } return totalError / interestingPixels; } public void calcErrorHeatmapRS(Bitmap ideal, Bitmap given, Bitmap output) { mIdealPixelsAllocation = Allocation.createFromBitmap(mRS, ideal, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); mGivenPixelsAllocation = Allocation.createFromBitmap(mRS, given, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); mScript.set_ideal(mIdealPixelsAllocation); mScript.set_given(mGivenPixelsAllocation); mOutputPixelsAllocation = Allocation.createFromBitmap(mRS, output, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); mScript.forEach_displayDifference(mOutputPixelsAllocation, mOutputPixelsAllocation); mOutputPixelsAllocation.copyTo(output); } public static float calcError(Bitmap ideal, Bitmap given) { if (LOG_TIMING) { startMillis = System.currentTimeMillis(); } int interestingRegions = 0; for (int x = 0; x < ideal.getWidth(); x += REGION_SIZE) { for (int y = 0; y < ideal.getWidth(); y += REGION_SIZE) { if (inspectRegion(ideal, x, y)) { interestingRegions++; } } } int interestingPixels = Math.max(1, interestingRegions) * REGION_SIZE * REGION_SIZE; if (LOG_TIMING) { long startMillis2 = System.currentTimeMillis(); } float totalError = 0; for (int x = 0; x < ideal.getWidth(); x++) { for (int y = 0; y < ideal.getHeight(); y++) { int idealColor = ideal.getPixel(x, y); int givenColor = given.getPixel(x, y); if (idealColor == givenColor) continue; totalError += Math.abs(Color.red(idealColor) - Color.red(givenColor)); totalError += Math.abs(Color.green(idealColor) - Color.green(givenColor)); totalError += Math.abs(Color.blue(idealColor) - Color.blue(givenColor)); totalError += Math.abs(Color.alpha(idealColor) - Color.alpha(givenColor)); } } totalError /= 1024.0f; if (LOG_TIMING) { long finalMillis = System.currentTimeMillis(); Log.d(LOG_TAG, "dvk: first part took " + (middleMillis - startMillis) + "ms"); Log.d(LOG_TAG, "dvk: last part took " + (finalMillis - middleMillis) + "ms"); } if (LOG_CALC) { Log.d(LOG_TAG, "dvk: error " + totalError + ", pixels " + interestingPixels); } return totalError / interestingPixels; } private static boolean inspectRegion(Bitmap ideal, int x, int y) { int regionColor = ideal.getPixel(x, y); for (int i = 0; i < REGION_SIZE; i++) { for (int j = 0; j < REGION_SIZE; j++) { if (ideal.getPixel(x + i, y + j) != regionColor) return true; } } return false; } }