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 {