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 
ErrorCalculator(Context c, Resources resources)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 
calcErrorRS(Bitmap ideal, Bitmap given)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 
calcErrorHeatmapRS(Bitmap ideal, Bitmap given, Bitmap output)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 
calcError(Bitmap ideal, Bitmap given)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 
inspectRegion(Bitmap ideal, int x, int y)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