Replace transparency with white for all pictures

Bug 5261517

Change-Id: I6c16bb1f9897589beec222fc63ad899cd478b923
diff --git a/src/com/android/providers/contacts/PhotoProcessor.java b/src/com/android/providers/contacts/PhotoProcessor.java
index cf81ff3..1b8fc3f 100644
--- a/src/com/android/providers/contacts/PhotoProcessor.java
+++ b/src/com/android/providers/contacts/PhotoProcessor.java
@@ -15,13 +15,18 @@
  */
 package com.android.providers.contacts;
 
-import com.android.providers.contacts.util.MemoryUtils;
-
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
 import android.os.SystemProperties;
 
+import com.android.providers.contacts.util.MemoryUtils;
+import com.google.common.annotations.VisibleForTesting;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
@@ -43,6 +48,12 @@
     /** Compression for thumbnails that also have a display photo */
     private static final int COMPRESSION_THUMBNAIL_LOW = 90;
 
+    private static final Paint WHITE_PAINT = new Paint();
+
+    static {
+        WHITE_PAINT.setColor(Color.WHITE);
+    }
+
     private static int sMaxThumbnailDim;
     private static int sMaxDisplayPhotoDim;
 
@@ -169,43 +180,65 @@
         if (mOriginal == null) {
             throw new IOException("Invalid image file");
         }
-        mDisplayPhoto = getScaledBitmap(mMaxDisplayPhotoDim);
-        mThumbnailPhoto = getScaledBitmap(mMaxThumbnailPhotoDim);
+        mDisplayPhoto = getNormalizedBitmap(mOriginal, mMaxDisplayPhotoDim, mForceCropToSquare);
+        mThumbnailPhoto = getNormalizedBitmap(mOriginal,mMaxThumbnailPhotoDim, mForceCropToSquare);
     }
 
     /**
      * Scales down the original bitmap to fit within the given maximum width and height.
      * If the bitmap already fits in those dimensions, the original bitmap will be
      * returned unmodified unless the photo processor is set up to crop it to a square.
+     *
+     * Also, if the image has transparency, conevrt it to white.
+     *
+     * @param original Original bitmap
      * @param maxDim Maximum width and height (in pixels) for the image.
+     * @param forceCropToSquare See {@link #PhotoProcessor(Bitmap, int, int, boolean)}
      * @return A bitmap that fits the maximum dimensions.
      */
     @SuppressWarnings({"SuspiciousNameCombination"})
-    private Bitmap getScaledBitmap(int maxDim) {
-        Bitmap scaledBitmap = mOriginal;
-        int width = mOriginal.getWidth();
-        int height = mOriginal.getHeight();
+    @VisibleForTesting
+    static Bitmap getNormalizedBitmap(Bitmap original, int maxDim, boolean forceCropToSquare) {
+        final boolean originalHasAlpha = original.hasAlpha();
+
+        // All cropXxx's are in the original coordinate.
+        int cropWidth = original.getWidth();
+        int cropHeight = original.getHeight();
         int cropLeft = 0;
         int cropTop = 0;
-        if (mForceCropToSquare && width != height) {
+        if (forceCropToSquare && cropWidth != cropHeight) {
             // Crop the image to the square at its center.
-            if (height > width) {
-                cropTop = (height - width) / 2;
-                height = width;
+            if (cropHeight > cropWidth) {
+                cropTop = (cropHeight - cropWidth) / 2;
+                cropHeight = cropWidth;
             } else {
-                cropLeft = (width - height) / 2;
-                width = height;
+                cropLeft = (cropWidth - cropHeight) / 2;
+                cropWidth = cropHeight;
             }
         }
-        float scaleFactor = ((float) maxDim) / Math.max(width, height);
-        if (scaleFactor < 1.0f || cropLeft != 0 || cropTop != 0) {
-            // Need to scale or crop the photo.
-            Matrix matrix = new Matrix();
-            if (scaleFactor < 1.0f) matrix.setScale(scaleFactor, scaleFactor);
-            scaledBitmap = Bitmap.createBitmap(
-                    mOriginal, cropLeft, cropTop, width, height, matrix, true);
+        // Calculate the scale factor.  We don't want to scale up, so the max scale is 1f.
+        final float scaleFactor = Math.min(1f, ((float) maxDim) / Math.max(cropWidth, cropHeight));
+
+        if (scaleFactor < 1.0f || cropLeft != 0 || cropTop != 0 || originalHasAlpha) {
+            final int newWidth = (int) (cropWidth * scaleFactor);
+            final int newHeight = (int) (cropHeight * scaleFactor);
+            final Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight,
+                    Bitmap.Config.ARGB_8888);
+            final Canvas c = new Canvas(scaledBitmap);
+
+            if (originalHasAlpha) {
+                c.drawRect(0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), WHITE_PAINT);
+            }
+
+            final Rect src = new Rect(cropLeft, cropTop,
+                    cropLeft + cropWidth, cropTop + cropHeight);
+            final RectF dst = new RectF(0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight());
+
+            c.drawBitmap(original, src, dst, null);
+            return scaledBitmap;
+        } else {
+            return original;
         }
-        return scaledBitmap;
     }
 
     /**
diff --git a/tests/res/drawable-nodpi/transparent_10x10.png b/tests/res/drawable-nodpi/transparent_10x10.png
new file mode 100644
index 0000000..d11c2cd
--- /dev/null
+++ b/tests/res/drawable-nodpi/transparent_10x10.png
Binary files differ
diff --git a/tests/src/com/android/providers/contacts/PhotoProcessorTest.java b/tests/src/com/android/providers/contacts/PhotoProcessorTest.java
new file mode 100644
index 0000000..3d882d5
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/PhotoProcessorTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.providers.contacts;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.test.AndroidTestCase;
+
+import com.android.providers.contacts.tests.R;
+
+
+/**
+ * Tests for {@link PhotoProcessor}.
+ *
+ * Most of tests are covered by {@link PhotoStoreTest}.
+ */
+public class PhotoProcessorTest extends AndroidTestCase {
+
+    public void testTransparency() {
+        final Drawable source = getTestContext().getResources().getDrawable(
+                R.drawable.transparent_10x10);
+        final Bitmap sourceBitmap = ((BitmapDrawable) source).getBitmap();
+
+        final Bitmap normalized = PhotoProcessor.getNormalizedBitmap(sourceBitmap, 50, false);
+
+        // Make sure it's not scaled up.
+        assertEquals(10, normalized.getWidth());
+        assertEquals(10, normalized.getHeight());
+
+        // Make sure the transparent pixel is now 100% white.
+        assertEquals(Color.argb(255, 255, 255, 255), normalized.getPixel(0, 0));
+    }
+}
diff --git a/tests/src/com/android/providers/contacts/PhotoStoreTest.java b/tests/src/com/android/providers/contacts/PhotoStoreTest.java
index 1550d0b..4e797f7 100644
--- a/tests/src/com/android/providers/contacts/PhotoStoreTest.java
+++ b/tests/src/com/android/providers/contacts/PhotoStoreTest.java
@@ -16,9 +16,7 @@
 
 package com.android.providers.contacts;
 
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.tests.R;
-import com.android.providers.contacts.util.Hex;
+import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
 
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
@@ -26,17 +24,17 @@
 import android.provider.ContactsContract.PhotoFiles;
 import android.test.suitebuilder.annotation.MediumTest;
 
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.tests.R;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
-import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
-
 /**
  * Tests for {@link PhotoStore}.
  */
@@ -81,7 +79,7 @@
 
     public void testStoreNonSquare300x200Photo() throws IOException {
         // The longer side should be downscaled to the target size
-        runStorageTestForResource(R.drawable.earth_300x200, 256, 171);
+        runStorageTestForResource(R.drawable.earth_300x200, 256, 170);
     }
 
     public void testStoreNonSquare300x200PhotoWithCrop() throws IOException {