1 /* 2 * Copyright (C) 2006 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 android.graphics.drawable; 18 19 import android.graphics.Bitmap; 20 import android.graphics.Canvas; 21 import android.os.Handler; 22 import android.os.HandlerThread; 23 import android.os.Parcel; 24 import android.test.AndroidTestCase; 25 import android.test.suitebuilder.annotation.SmallTest; 26 import android.util.Log; 27 28 import java.io.ByteArrayOutputStream; 29 import java.io.File; 30 import java.io.FileOutputStream; 31 import java.lang.Override; 32 import java.util.Arrays; 33 import java.util.ArrayList; 34 35 import com.android.frameworks.graphicstests.R; 36 37 public class IconTest extends AndroidTestCase { 38 public static final String TAG = IconTest.class.getSimpleName(); 39 public static void L(String s, Object... parts) { 40 Log.d(TAG, (parts.length == 0) ? s : String.format(s, parts)); 41 } 42 43 @SmallTest 44 public void testWithBitmap() throws Exception { 45 final Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888); 46 final Bitmap bm2 = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565); 47 final Bitmap bm3 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape)) 48 .getBitmap(); 49 50 final Canvas can1 = new Canvas(bm1); 51 can1.drawColor(0xFFFF0000); 52 final Canvas can2 = new Canvas(bm2); 53 can2.drawColor(0xFF00FF00); 54 55 final Icon im1 = Icon.createWithBitmap(bm1); 56 final Icon im2 = Icon.createWithBitmap(bm2); 57 final Icon im3 = Icon.createWithBitmap(bm3); 58 59 final Drawable draw1 = im1.loadDrawable(mContext); 60 final Drawable draw2 = im2.loadDrawable(mContext); 61 final Drawable draw3 = im3.loadDrawable(mContext); 62 63 final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(), 64 draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 65 final Bitmap test2 = Bitmap.createBitmap(draw2.getIntrinsicWidth(), 66 draw2.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 67 final Bitmap test3 = Bitmap.createBitmap(draw3.getIntrinsicWidth(), 68 draw3.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 69 70 draw1.setBounds(0, 0, draw1.getIntrinsicWidth(), draw1.getIntrinsicHeight()); 71 draw1.draw(new Canvas(test1)); 72 73 draw2.setBounds(0, 0, draw2.getIntrinsicWidth(), draw2.getIntrinsicHeight()); 74 draw2.draw(new Canvas(test2)); 75 76 draw3.setBounds(0, 0, draw3.getIntrinsicWidth(), draw3.getIntrinsicHeight()); 77 draw3.draw(new Canvas(test3)); 78 79 final File dir = getContext().getExternalFilesDir(null); 80 L("writing temp bitmaps to %s...", dir); 81 82 bm1.compress(Bitmap.CompressFormat.PNG, 100, 83 new FileOutputStream(new File(dir, "bitmap1-original.png"))); 84 test1.compress(Bitmap.CompressFormat.PNG, 100, 85 new FileOutputStream(new File(dir, "bitmap1-test.png"))); 86 if (!equalBitmaps(bm1, test1)) { 87 findBitmapDifferences(bm1, test1); 88 fail("bitmap1 differs, check " + dir); 89 } 90 91 bm2.compress(Bitmap.CompressFormat.PNG, 100, 92 new FileOutputStream(new File(dir, "bitmap2-original.png"))); 93 test2.compress(Bitmap.CompressFormat.PNG, 100, 94 new FileOutputStream(new File(dir, "bitmap2-test.png"))); 95 if (!equalBitmaps(bm2, test2)) { 96 findBitmapDifferences(bm2, test2); 97 fail("bitmap2 differs, check " + dir); 98 } 99 100 bm3.compress(Bitmap.CompressFormat.PNG, 100, 101 new FileOutputStream(new File(dir, "bitmap3-original.png"))); 102 test3.compress(Bitmap.CompressFormat.PNG, 100, 103 new FileOutputStream(new File(dir, "bitmap3-test.png"))); 104 if (!equalBitmaps(bm3, test3)) { 105 findBitmapDifferences(bm3, test3); 106 fail("bitmap3 differs, check " + dir); 107 } 108 } 109 110 @SmallTest 111 public void testWithBitmapResource() throws Exception { 112 final Bitmap res1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape)) 113 .getBitmap(); 114 115 final Icon im1 = Icon.createWithResource(getContext(), R.drawable.landscape); 116 final Drawable draw1 = im1.loadDrawable(mContext); 117 final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(), 118 draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 119 draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight()); 120 draw1.draw(new Canvas(test1)); 121 122 final File dir = getContext().getExternalFilesDir(null); 123 res1.compress(Bitmap.CompressFormat.PNG, 100, 124 new FileOutputStream(new File(dir, "res1-original.png"))); 125 test1.compress(Bitmap.CompressFormat.PNG, 100, 126 new FileOutputStream(new File(dir, "res1-test.png"))); 127 if (!equalBitmaps(res1, test1)) { 128 findBitmapDifferences(res1, test1); 129 fail("res1 differs, check " + dir); 130 } 131 } 132 133 @SmallTest 134 public void testWithFile() throws Exception { 135 final Bitmap bit1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape)) 136 .getBitmap(); 137 final File dir = getContext().getExternalFilesDir(null); 138 final File file1 = new File(dir, "file1-original.png"); 139 bit1.compress(Bitmap.CompressFormat.PNG, 100, 140 new FileOutputStream(file1)); 141 142 final Icon im1 = Icon.createWithFilePath(file1.toString()); 143 final Drawable draw1 = im1.loadDrawable(mContext); 144 final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(), 145 draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 146 draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight()); 147 draw1.draw(new Canvas(test1)); 148 149 test1.compress(Bitmap.CompressFormat.PNG, 100, 150 new FileOutputStream(new File(dir, "file1-test.png"))); 151 if (!equalBitmaps(bit1, test1)) { 152 findBitmapDifferences(bit1, test1); 153 fail("testWithFile: file1 differs, check " + dir); 154 } 155 } 156 157 @SmallTest 158 public void testAsync() throws Exception { 159 final Bitmap bit1 = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape)) 160 .getBitmap(); 161 final File dir = getContext().getExternalFilesDir(null); 162 final File file1 = new File(dir, "async-original.png"); 163 bit1.compress(Bitmap.CompressFormat.PNG, 100, 164 new FileOutputStream(file1)); 165 166 final Icon im1 = Icon.createWithFilePath(file1.toString()); 167 final HandlerThread thd = new HandlerThread("testAsync"); 168 thd.start(); 169 final Handler h = new Handler(thd.getLooper()); 170 L(TAG, "asyncTest: dispatching load to thread: " + thd); 171 im1.loadDrawableAsync(mContext, new Icon.OnDrawableLoadedListener() { 172 @Override 173 public void onDrawableLoaded(Drawable draw1) { 174 L(TAG, "asyncTest: thread: loading drawable"); 175 L(TAG, "asyncTest: thread: loaded: %dx%d", draw1.getIntrinsicWidth(), 176 draw1.getIntrinsicHeight()); 177 final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(), 178 draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 179 draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight()); 180 draw1.draw(new Canvas(test1)); 181 182 try { 183 test1.compress(Bitmap.CompressFormat.PNG, 100, 184 new FileOutputStream(new File(dir, "async-test.png"))); 185 } catch (java.io.FileNotFoundException ex) { 186 fail("couldn't create test file: " + ex); 187 } 188 if (!equalBitmaps(bit1, test1)) { 189 findBitmapDifferences(bit1, test1); 190 fail("testAsync: file1 differs, check " + dir); 191 } 192 } 193 }, h); 194 L(TAG, "asyncTest: awaiting result"); 195 Thread.sleep(500); // ;_; 196 assertTrue("async-test.png does not exist!", new File(dir, "async-test.png").exists()); 197 L(TAG, "asyncTest: done"); 198 } 199 200 @SmallTest 201 public void testParcel() throws Exception { 202 final Bitmap originalbits = ((BitmapDrawable) getContext().getDrawable(R.drawable.landscape)) 203 .getBitmap(); 204 205 final ByteArrayOutputStream ostream = new ByteArrayOutputStream( 206 originalbits.getWidth() * originalbits.getHeight() * 2); // guess 50% compression 207 originalbits.compress(Bitmap.CompressFormat.PNG, 100, ostream); 208 final byte[] pngdata = ostream.toByteArray(); 209 210 L("starting testParcel; bitmap: %d bytes, PNG: %d bytes", 211 originalbits.getByteCount(), 212 pngdata.length); 213 214 final File dir = getContext().getExternalFilesDir(null); 215 final File originalfile = new File(dir, "parcel-original.png"); 216 new FileOutputStream(originalfile).write(pngdata); 217 218 ArrayList<Icon> imgs = new ArrayList<>(); 219 final Icon file1 = Icon.createWithFilePath(originalfile.getAbsolutePath()); 220 imgs.add(file1); 221 final Icon bit1 = Icon.createWithBitmap(originalbits); 222 imgs.add(bit1); 223 final Icon data1 = Icon.createWithData(pngdata, 0, pngdata.length); 224 imgs.add(data1); 225 final Icon res1 = Icon.createWithResource(getContext(), R.drawable.landscape); 226 imgs.add(res1); 227 228 ArrayList<Icon> test = new ArrayList<>(); 229 final Parcel parcel = Parcel.obtain(); 230 int pos = 0; 231 parcel.writeInt(imgs.size()); 232 for (Icon img : imgs) { 233 img.writeToParcel(parcel, 0); 234 L("used %d bytes parceling: %s", parcel.dataPosition() - pos, img); 235 pos = parcel.dataPosition(); 236 } 237 238 parcel.setDataPosition(0); // rewind 239 final int N = parcel.readInt(); 240 for (int i=0; i<N; i++) { 241 Icon img = Icon.CREATOR.createFromParcel(parcel); 242 L("test %d: read from parcel: %s", i, img); 243 final File testfile = new File(dir, 244 String.format("parcel-test%02d.png", i)); 245 246 final Drawable draw1 = img.loadDrawable(mContext); 247 if (draw1 == null) { 248 fail("null drawable from img: " + img); 249 } 250 final Bitmap test1 = Bitmap.createBitmap(draw1.getIntrinsicWidth(), 251 draw1.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 252 draw1.setBounds(0, 0, test1.getWidth(), test1.getHeight()); 253 draw1.draw(new Canvas(test1)); 254 255 try { 256 test1.compress(Bitmap.CompressFormat.PNG, 100, 257 new FileOutputStream(testfile)); 258 } catch (java.io.FileNotFoundException ex) { 259 fail("couldn't create test file " + testfile + ": " + ex); 260 } 261 if (!equalBitmaps(originalbits, test1)) { 262 findBitmapDifferences(originalbits, test1); 263 fail(testfile + " differs from original: " + originalfile); 264 } 265 266 } 267 } 268 269 270 // ======== utils ======== 271 272 static final char[] GRADIENT = " .:;+=xX$#".toCharArray(); 273 static float[] hsv = new float[3]; 274 static char colorToChar(int color) { 275 int sum = ((color >> 16) & 0xff) 276 + ((color >> 8) & 0xff) 277 + ((color) & 0xff); 278 return GRADIENT[sum * (GRADIENT.length-1) / (3*0xff)]; 279 } 280 static void printBits(int[] a, int w, int h) { 281 final StringBuilder sb = new StringBuilder(); 282 for (int i=0; i<w; i++) { 283 for (int j=0; j<h; j++) { 284 sb.append(colorToChar(a[i+w*j])); 285 } 286 sb.append('\n'); 287 } 288 L(sb.toString()); 289 } 290 static void printBits(Bitmap a) { 291 final int w = a.getWidth(); 292 final int h = a.getHeight(); 293 int[] aPix = new int[w * h]; 294 printBits(aPix, w, h); 295 } 296 boolean equalBitmaps(Bitmap a, Bitmap b) { 297 if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) return false; 298 299 final int w = a.getWidth(); 300 final int h = a.getHeight(); 301 int[] aPix = new int[w * h]; 302 int[] bPix = new int[w * h]; 303 304 a.getPixels(aPix, 0, w, 0, 0, w, h); 305 b.getPixels(bPix, 0, w, 0, 0, w, h); 306 307 return Arrays.equals(aPix, bPix); 308 } 309 310 void findBitmapDifferences(Bitmap a, Bitmap b) { 311 if (a.getWidth() != b.getWidth() || a.getHeight() != b.getHeight()) { 312 L("different sizes: %dx%d vs %dx%d", 313 a.getWidth(), a.getHeight(), b.getWidth(), b.getHeight()); 314 return; 315 } 316 317 final int w = a.getWidth(); 318 final int h = a.getHeight(); 319 int[] aPix = new int[w * h]; 320 int[] bPix = new int[w * h]; 321 322 a.getPixels(aPix, 0, w, 0, 0, w, h); 323 b.getPixels(bPix, 0, w, 0, 0, w, h); 324 325 L("bitmap a (%dx%d)", w, h); 326 printBits(aPix, w, h); 327 L("bitmap b (%dx%d)", w, h); 328 printBits(bPix, w, h); 329 330 StringBuffer sb = new StringBuffer("Different pixels: "); 331 for (int i=0; i<w; i++) { 332 for (int j=0; j<h; j++) { 333 if (aPix[i+w*j] != bPix[i+w*j]) { 334 sb.append(" ").append(i).append(",").append(j); 335 } 336 } 337 } 338 L(sb.toString()); 339 } 340 } 341