blob: 3f8b6ee7e7a885ba3addee1f07d5bccdf8c023ea [file] [log] [blame]
/*
* Copyright (C) 2008 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 android.graphics.cts;
import com.android.cts.graphics.R;
import android.content.res.Resources;
import android.cts.util.WidgetTestUtils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.os.Parcel;
import android.test.AndroidTestCase;
import android.util.DisplayMetrics;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;
public class BitmapTest extends AndroidTestCase {
private Resources mRes;
private Bitmap mBitmap;
private BitmapFactory.Options mOptions;
// small alpha values cause color values to be pre-multiplied down, losing accuracy
private final int PREMUL_COLOR = Color.argb(2, 255, 254, 253);
private final int PREMUL_ROUNDED_COLOR = Color.argb(2, 255, 255, 255);
private final int PREMUL_STORED_COLOR = Color.argb(2, 2, 2, 2);
@Override
protected void setUp() throws Exception {
super.setUp();
mRes = getContext().getResources();
mOptions = new BitmapFactory.Options();
mOptions.inScaled = false;
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
}
public void testCompress(){
mBitmap.recycle();
//abnormal case: the bitmap has been recycled
try{
mBitmap.compress(CompressFormat.JPEG, 0, null);
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
// abnormal case: out stream is null
try{
mBitmap.compress(CompressFormat.JPEG, 0, null);
fail("shouldn't come to here");
}catch(NullPointerException e){
}
// abnormal case: quality less than 0
try{
mBitmap.compress(CompressFormat.JPEG, -1, new ByteArrayOutputStream());
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// abnormal case: quality bigger than 100
try{
mBitmap.compress(CompressFormat.JPEG, 101, new ByteArrayOutputStream());
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
//normal case
assertTrue(mBitmap.compress(CompressFormat.JPEG, 50, new ByteArrayOutputStream()));
}
public void testCopy(){
mBitmap.recycle();
//abnormal case: the bitmap has been recycled
try{
mBitmap.copy(Config.RGB_565, false);
fail("shouldn't come to here");
}catch(IllegalStateException e){
// expected
}
mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
Bitmap bitmap = mBitmap.copy(Config.ARGB_8888, false);
WidgetTestUtils.assertEquals(mBitmap, bitmap);
}
public void testCopyPixelsToBuffer(){
final int pixSize = mBitmap.getRowBytes() * mBitmap.getHeight();
final int tooSmall = pixSize / 2;
// abnormal case: unsupported Buffer subclass
try{
mBitmap.copyPixelsToBuffer(CharBuffer.allocate(pixSize));
fail("shouldn't come to here");
}catch(RuntimeException e1){
}
// abnormal case: Buffer not large enough for pixels
try{
mBitmap.copyPixelsToBuffer(ByteBuffer.allocate(tooSmall));
fail("shouldn't come to here");
}catch(RuntimeException e2){
}
// normal case
ByteBuffer byteBuf = ByteBuffer.allocate(pixSize);
assertEquals(0, byteBuf.position());
mBitmap.copyPixelsToBuffer(byteBuf);
assertEquals(pixSize, byteBuf.position());
// abnormal case: Buffer not large enough for pixels
try{
mBitmap.copyPixelsToBuffer(ByteBuffer.allocate(tooSmall));
fail("shouldn't come to here");
}catch(RuntimeException e3){
}
// normal case
ShortBuffer shortBuf = ShortBuffer.allocate(pixSize);
assertEquals(0, shortBuf.position());
mBitmap.copyPixelsToBuffer(shortBuf);
assertEquals(pixSize >> 1, shortBuf.position());
// abnormal case: Buffer not large enough for pixels
try{
mBitmap.copyPixelsToBuffer(ByteBuffer.allocate(tooSmall));
fail("shouldn't come to here");
}catch(RuntimeException e4){
}
// normal case
IntBuffer intBuf1 = IntBuffer.allocate(pixSize);
assertEquals(0, intBuf1.position());
mBitmap.copyPixelsToBuffer(intBuf1);
assertEquals(pixSize >> 2, intBuf1.position());
Bitmap bitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(),
mBitmap.getConfig());
intBuf1.position(0); // copyPixelsToBuffer adjusted the position, so rewind to start
bitmap.copyPixelsFromBuffer(intBuf1);
IntBuffer intBuf2 = IntBuffer.allocate(pixSize);
bitmap.copyPixelsToBuffer(intBuf2);
assertEquals(pixSize >> 2, intBuf2.position());
assertEquals(intBuf1.position(), intBuf2.position());
int size = intBuf1.position();
intBuf1.position(0);
intBuf2.position(0);
for (int i = 0; i < size; i++) {
assertEquals("mismatching pixels at position " + i, intBuf1.get(), intBuf2.get());
}
}
public void testCreateBitmap1(){
int[] colors = createColors(100);
Bitmap bitmap = Bitmap.createBitmap(colors, 10, 10, Config.RGB_565);
Bitmap ret = Bitmap.createBitmap(bitmap);
assertNotNull(ret);
assertEquals(10, ret.getWidth());
assertEquals(10, ret.getHeight());
assertEquals(Config.RGB_565, ret.getConfig());
}
public void testCreateBitmap2(){
//abnormal case: Illegal Argument
try{
Bitmap.createBitmap(mBitmap, -100, 50, 50, 200);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// special case: output bitmap is equal to the input bitmap
mBitmap = Bitmap.createBitmap(new int[100 * 100], 100, 100, Config.ARGB_8888);
Bitmap ret = Bitmap.createBitmap(mBitmap, 0, 0, 100, 100);
assertNotNull(ret);
assertTrue(mBitmap.equals(ret));
//normal case
mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
ret = Bitmap.createBitmap(mBitmap, 10, 10, 50, 50);
assertNotNull(ret);
assertFalse(mBitmap.equals(ret));
}
public void testCreateBitmap3(){
mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
//abnormal case: x and/or y less than 0
try{
Bitmap.createBitmap(mBitmap, -1, -1, 10, 10, null, false);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
//abnormal case: width and/or height less than 0
try{
Bitmap.createBitmap(mBitmap, 1, 1, -10, -10, null, false);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
//abnormal case: (x + width) bigger than source bitmap's width
try{
Bitmap.createBitmap(mBitmap, 10, 10, 95, 50, null, false);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
//abnormal case: (y + height) bigger than source bitmap's height
try{
Bitmap.createBitmap(mBitmap, 10, 10, 50, 95, null, false);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// special case: output bitmap is equal to the input bitmap
mBitmap = Bitmap.createBitmap(new int[100 * 100], 100, 100, Config.ARGB_8888);
Bitmap ret = Bitmap.createBitmap(mBitmap, 0, 0, 100, 100, null, false);
assertNotNull(ret);
assertTrue(mBitmap.equals(ret));
// normal case
mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
ret = Bitmap.createBitmap(mBitmap, 10, 10, 50, 50, new Matrix(), true);
assertNotNull(ret);
assertFalse(mBitmap.equals(ret));
}
public void testCreateBitmap4(){
Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
assertNotNull(ret);
assertEquals(100, ret.getWidth());
assertEquals(200, ret.getHeight());
assertEquals(Config.RGB_565, ret.getConfig());
}
public void testCreateBitmap6(){
int[] colors = createColors(100);
//abnormal case: width and/or height less than 0
try{
Bitmap.createBitmap(colors, 0, 100, -1, 100, Config.RGB_565);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
//abnormal case: stride less than width and bigger than -width
try{
Bitmap.createBitmap(colors, 10, 10, 100, 100, Config.RGB_565);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
//abnormal case: offset less than 0
try{
Bitmap.createBitmap(colors, -10, 100, 100, 100, Config.RGB_565);
fail("shouldn't come to here");
}catch(ArrayIndexOutOfBoundsException e){
}
//abnormal case: (offset + width) bigger than colors' length
try{
Bitmap.createBitmap(colors, 10, 100, 100, 100, Config.RGB_565);
fail("shouldn't come to here");
}catch(ArrayIndexOutOfBoundsException e){
}
//abnormal case: (lastScanline + width) bigger than colors' length
try{
Bitmap.createBitmap(colors, 10, 100, 50, 100, Config.RGB_565);
fail("shouldn't come to here");
}catch(ArrayIndexOutOfBoundsException e){
}
// normal case
Bitmap ret = Bitmap.createBitmap(colors, 5, 10, 10, 5, Config.RGB_565);
assertNotNull(ret);
assertEquals(10, ret.getWidth());
assertEquals(5, ret.getHeight());
assertEquals(Config.RGB_565, ret.getConfig());
}
public void testCreateScaledBitmap(){
mBitmap = Bitmap.createBitmap(100, 200, Config.RGB_565);
Bitmap ret = Bitmap.createScaledBitmap(mBitmap, 50, 100, false);
assertNotNull(ret);
assertEquals(50, ret.getWidth());
assertEquals(100, ret.getHeight());
}
public void testDescribeContents(){
assertEquals(0, mBitmap.describeContents());
}
public void testEraseColor(){
mBitmap.recycle();
//abnormal case: the bitmap has been recycled
try{
mBitmap.eraseColor(0);
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
//abnormal case: bitmap is immutable
try{
mBitmap.eraseColor(0);
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
// normal case
mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
mBitmap.eraseColor(0xffff0000);
assertEquals(0xffff0000, mBitmap.getPixel(10, 10));
assertEquals(0xffff0000, mBitmap.getPixel(50, 50));
}
public void testExtractAlpha1(){
mBitmap.recycle();
//abnormal case: the bitmap has been recycled
try{
mBitmap.extractAlpha();
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
// normal case
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
Bitmap ret = mBitmap.extractAlpha();
assertNotNull(ret);
int color = ret.getPixel(10, 20);
assertEquals(0x00, Color.alpha(color));
}
public void testExtractAlpha2(){
mBitmap.recycle();
//abnormal case: the bitmap has been recycled
try{
mBitmap.extractAlpha(new Paint(), new int[]{0, 1});
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
// normal case
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
Bitmap ret = mBitmap.extractAlpha(new Paint(), new int[]{0, 1});
assertNotNull(ret);
int color = ret.getPixel(10, 20);
assertEquals(0x00, Color.alpha(color));
}
public void testGetAllocationByteCount() {
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ALPHA_8);
int alloc = mBitmap.getAllocationByteCount();
assertEquals(mBitmap.getByteCount(), alloc);
// reconfigure same size
mBitmap.reconfigure(50, 100, Bitmap.Config.ARGB_8888);
assertEquals(mBitmap.getByteCount(), alloc);
assertEquals(mBitmap.getAllocationByteCount(), alloc);
// reconfigure different size
mBitmap.reconfigure(10, 10, Bitmap.Config.ALPHA_8);
assertEquals(mBitmap.getByteCount(), 100);
assertEquals(mBitmap.getAllocationByteCount(), alloc);
}
public void testGetConfig(){
Bitmap bm0 = Bitmap.createBitmap(100, 200, Bitmap.Config.ALPHA_8);
Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
Bitmap bm2 = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
Bitmap bm3 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444);
assertEquals(Bitmap.Config.ALPHA_8, bm0.getConfig());
assertEquals(Bitmap.Config.ARGB_8888, bm1.getConfig());
assertEquals(Bitmap.Config.RGB_565, bm2.getConfig());
// Attempting to create a 4444 bitmap actually creates an 8888 bitmap.
assertEquals(Bitmap.Config.ARGB_8888, bm3.getConfig());
}
public void testGetHeight(){
assertEquals(31, mBitmap.getHeight());
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
assertEquals(200, mBitmap.getHeight());
}
public void testGetNinePatchChunk(){
assertNull(mBitmap.getNinePatchChunk());
}
public void testGetPixel(){
mBitmap.recycle();
//abnormal case: the bitmap has been recycled
try{
mBitmap.getPixel(10, 16);
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
//abnormal case: x bigger than the source bitmap's width
try{
mBitmap.getPixel(200, 16);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
//abnormal case: y bigger than the source bitmap's height
try{
mBitmap.getPixel(10, 300);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// normal case 565
mBitmap.setPixel(10, 16, 0xFF << 24);
assertEquals(0xFF << 24, mBitmap.getPixel(10, 16));
// normal case A_8
mBitmap = Bitmap.createBitmap(10, 10, Config.ALPHA_8);
mBitmap.setPixel(5, 5, 0xFFFFFFFF);
assertEquals(0xFFFFFFFF, mBitmap.getPixel(5, 5));
mBitmap.setPixel(5, 5, 0xA8A8A8A8);
assertEquals(0xA8A8A8A8, mBitmap.getPixel(5, 5));
mBitmap.setPixel(5, 5, 0x00000000);
assertEquals(0x00000000, mBitmap.getPixel(5, 5));
// test reconstructing color channels
mBitmap.setPixel(5, 5, 0x1F000000);
assertEquals(0x1F1F1F1F, mBitmap.getPixel(5, 5));
}
public void testGetRowBytes(){
Bitmap bm0 = Bitmap.createBitmap(100, 200, Bitmap.Config.ALPHA_8);
Bitmap bm1 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
Bitmap bm2 = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
Bitmap bm3 = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_4444);
assertEquals(100, bm0.getRowBytes());
assertEquals(400, bm1.getRowBytes());
assertEquals(200, bm2.getRowBytes());
// Attempting to create a 4444 bitmap actually creates an 8888 bitmap.
assertEquals(400, bm3.getRowBytes());
}
public void testGetWidth(){
assertEquals(31, mBitmap.getWidth());
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
assertEquals(100, mBitmap.getWidth());
}
public void testHasAlpha(){
assertFalse(mBitmap.hasAlpha());
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
assertTrue(mBitmap.hasAlpha());
}
public void testIsMutable(){
assertFalse(mBitmap.isMutable());
mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
assertTrue(mBitmap.isMutable());
}
public void testIsRecycled(){
assertFalse(mBitmap.isRecycled());
mBitmap.recycle();
assertTrue(mBitmap.isRecycled());
}
public void testReconfigure() {
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
int alloc = mBitmap.getAllocationByteCount();
// test shrinking
mBitmap.reconfigure(50, 100, Bitmap.Config.ALPHA_8);
assertEquals(mBitmap.getAllocationByteCount(), alloc);
assertEquals(mBitmap.getByteCount() * 8, alloc);
// test expanding
try {
mBitmap.reconfigure(101, 201, Bitmap.Config.ARGB_8888);
fail("shouldn't come to here");
} catch (IllegalArgumentException e) {
}
// test mutable
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
try {
mBitmap.reconfigure(1, 1, Bitmap.Config.ALPHA_8);
fail("shouldn't come to here");
} catch (IllegalStateException e) {
}
}
// Used by testAlphaAndPremul. FIXME: Should we also test Index8? That would require decoding a
// Bitmap, since one cannot be created directly. It will also have a Config of null, since it
// has no Java equivalent.
private static Config[] CONFIGS = new Config[] { Config.ALPHA_8, Config.ARGB_4444,
Config.ARGB_8888, Config.RGB_565 };
// test that reconfigure, setHasAlpha, and setPremultiplied behave as expected with
// respect to alpha and premultiplied.
public void testAlphaAndPremul() {
boolean falseTrue[] = new boolean[] { false, true };
for (Config fromConfig : CONFIGS) {
for (Config toConfig : CONFIGS) {
for (boolean hasAlpha : falseTrue) {
for (boolean isPremul : falseTrue) {
Bitmap bitmap = Bitmap.createBitmap(10, 10, fromConfig);
// 4444 is deprecated, and will convert to 8888. No need to
// attempt a reconfigure, which will be tested when fromConfig
// is 8888.
if (fromConfig == Config.ARGB_4444) {
assertEquals(bitmap.getConfig(), Config.ARGB_8888);
break;
}
bitmap.setHasAlpha(hasAlpha);
bitmap.setPremultiplied(isPremul);
checkAlphaAndPremul(bitmap, hasAlpha, isPremul, false);
// reconfigure to a smaller size so the function will still succeed when
// going to a Config that requires more bits.
bitmap.reconfigure(1, 1, toConfig);
if (toConfig == Config.ARGB_4444) {
assertEquals(bitmap.getConfig(), Config.ARGB_8888);
} else {
assertEquals(bitmap.getConfig(), toConfig);
}
// Check that the alpha and premultiplied state has not changed (unless
// we expected it to).
checkAlphaAndPremul(bitmap, hasAlpha, isPremul, fromConfig == Config.RGB_565);
}
}
}
}
}
/**
* Assert that bitmap returns the appropriate values for hasAlpha() and isPremultiplied().
* @param bitmap Bitmap to check.
* @param expectedAlpha Expected return value from bitmap.hasAlpha(). Note that this is based
* on what was set, but may be different from the actual return value depending on the
* Config and convertedFrom565.
* @param expectedPremul Expected return value from bitmap.isPremultiplied(). Similar to
* expectedAlpha, this is based on what was set, but may be different from the actual
* return value depending on the Config.
* @param convertedFrom565 Whether bitmap was converted to its current Config by being
* reconfigured from RGB_565. If true, and bitmap is now a Config that supports alpha,
* hasAlpha() is expected to be true even if expectedAlpha is false.
*/
private void checkAlphaAndPremul(Bitmap bitmap, boolean expectedAlpha, boolean expectedPremul,
boolean convertedFrom565) {
switch (bitmap.getConfig()) {
case ARGB_4444:
// This shouldn't happen, since we don't allow creating or converting
// to 4444.
assertFalse(true);
break;
case RGB_565:
assertFalse(bitmap.hasAlpha());
assertFalse(bitmap.isPremultiplied());
break;
case ALPHA_8:
// ALPHA_8 behaves mostly the same as 8888, except for premultiplied. Fall through.
case ARGB_8888:
// Since 565 is necessarily opaque, we revert to hasAlpha when switching to a type
// that can have alpha.
if (convertedFrom565) {
assertTrue(bitmap.hasAlpha());
} else {
assertEquals(bitmap.hasAlpha(), expectedAlpha);
}
if (bitmap.hasAlpha()) {
// ALPHA_8's premultiplied status is undefined.
if (bitmap.getConfig() != Config.ALPHA_8) {
assertEquals(bitmap.isPremultiplied(), expectedPremul);
}
} else {
// Opaque bitmap is never considered premultiplied.
assertFalse(bitmap.isPremultiplied());
}
break;
}
}
public void testSetConfig() {
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
int alloc = mBitmap.getAllocationByteCount();
// test shrinking
mBitmap.setConfig(Bitmap.Config.ALPHA_8);
assertEquals(mBitmap.getAllocationByteCount(), alloc);
assertEquals(mBitmap.getByteCount() * 2, alloc);
// test expanding
try {
mBitmap.setConfig(Bitmap.Config.ARGB_8888);
fail("shouldn't come to here");
} catch (IllegalArgumentException e) {
}
// test mutable
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
try {
mBitmap.setConfig(Bitmap.Config.ALPHA_8);
fail("shouldn't come to here");
} catch (IllegalStateException e) {
}
}
public void testSetHeight() {
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
int alloc = mBitmap.getAllocationByteCount();
// test shrinking
mBitmap.setHeight(100);
assertEquals(mBitmap.getAllocationByteCount(), alloc);
assertEquals(mBitmap.getByteCount() * 2, alloc);
// test expanding
try {
mBitmap.setHeight(201);
fail("shouldn't come to here");
} catch (IllegalArgumentException e) {
}
// test mutable
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
try {
mBitmap.setHeight(1);
fail("shouldn't come to here");
} catch (IllegalStateException e) {
}
}
public void testSetPixel(){
int color = 0xff << 24;
mBitmap.recycle();
//abnormal case: the bitmap has been recycled
try{
mBitmap.setPixel(10, 16, color);
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
//abnormal case: the bitmap is immutable
try{
mBitmap.setPixel(10, 16, color);
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.RGB_565);
//abnormal case: x bigger than the source bitmap's width
try{
mBitmap.setPixel(200, 16, color);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
//abnormal case: y bigger than the source bitmap's height
try{
mBitmap.setPixel(10, 300, color);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// normal case
mBitmap.setPixel(10, 16, 0xFF << 24);
assertEquals(0xFF << 24, mBitmap.getPixel(10, 16));
}
public void testSetPixels(){
int[] colors = createColors(100);
//abnormal case: the bitmap has been recycled
mBitmap.recycle();
try{
mBitmap.setPixels(colors, 0, 0, 0, 0, 0, 0);
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
// abnormal case: the bitmap is immutable
try{
mBitmap.setPixels(colors, 0, 0, 0, 0, 0, 0);
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
mBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
// abnormal case: x and/or y less than 0
try{
mBitmap.setPixels(colors, 0, 0, -1, -1, 200, 16);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// abnormal case: width and/or height less than 0
try{
mBitmap.setPixels(colors, 0, 0, 0, 0, -1, -1);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// abnormal case: (x + width) bigger than the source bitmap's width
try{
mBitmap.setPixels(colors, 0, 0, 10, 10, 95, 50);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// abnormal case: (y + height) bigger than the source bitmap's height
try{
mBitmap.setPixels(colors, 0, 0, 10, 10, 50, 95);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// abnormal case: stride less than width and bigger than -width
try{
mBitmap.setPixels(colors, 0, 10, 10, 10, 50, 50);
fail("shouldn't come to here");
}catch(IllegalArgumentException e){
}
// abnormal case: offset less than 0
try{
mBitmap.setPixels(colors, -1, 50, 10, 10, 50, 50);
fail("shouldn't come to here");
}catch(ArrayIndexOutOfBoundsException e){
}
// abnormal case: (offset + width) bigger than the length of colors
try{
mBitmap.setPixels(colors, 60, 50, 10, 10, 50, 50);
fail("shouldn't come to here");
}catch(ArrayIndexOutOfBoundsException e){
}
// abnormal case: lastScanline less than 0
try{
mBitmap.setPixels(colors, 10, -50, 10, 10, 50, 50);
fail("shouldn't come to here");
}catch(ArrayIndexOutOfBoundsException e){
}
// abnormal case: (lastScanline + width) bigger than the length of colors
try{
mBitmap.setPixels(colors, 10, 50, 10, 10, 50, 50);
fail("shouldn't come to here");
}catch(ArrayIndexOutOfBoundsException e){
}
// normal case
colors = createColors(100 * 100);
mBitmap.setPixels(colors, 0, 100, 0, 0, 100, 100);
int[] ret = new int[100 * 100];
mBitmap.getPixels(ret, 0, 100, 0, 0, 100, 100);
for(int i = 0; i < 10000; i++){
assertEquals(ret[i], colors[i]);
}
}
private void checkPremultipliedBitmapConfig(Config config, boolean expectedPremul) {
Bitmap bitmap = Bitmap.createBitmap(1, 1, config);
bitmap.setPremultiplied(true);
bitmap.setPixel(0, 0, Color.TRANSPARENT);
assertTrue(bitmap.isPremultiplied() == expectedPremul);
bitmap.setHasAlpha(false);
assertFalse(bitmap.isPremultiplied());
}
public void testSetPremultipliedSimple() {
checkPremultipliedBitmapConfig(Bitmap.Config.ALPHA_8, true);
checkPremultipliedBitmapConfig(Bitmap.Config.RGB_565, false);
checkPremultipliedBitmapConfig(Bitmap.Config.ARGB_4444, true);
checkPremultipliedBitmapConfig(Bitmap.Config.ARGB_8888, true);
}
public void testSetPremultipliedData() {
// with premul, will store 2,2,2,2, so it doesn't get value correct
Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
bitmap.setPixel(0, 0, PREMUL_COLOR);
assertEquals(bitmap.getPixel(0, 0), PREMUL_ROUNDED_COLOR);
// read premultiplied value directly
bitmap.setPremultiplied(false);
assertEquals(bitmap.getPixel(0, 0), PREMUL_STORED_COLOR);
// value can now be stored/read correctly
bitmap.setPixel(0, 0, PREMUL_COLOR);
assertEquals(bitmap.getPixel(0, 0), PREMUL_COLOR);
// verify with array methods
int testArray[] = new int[] { PREMUL_COLOR };
bitmap.setPixels(testArray, 0, 1, 0, 0, 1, 1);
bitmap.getPixels(testArray, 0, 1, 0, 0, 1, 1);
assertEquals(bitmap.getPixel(0, 0), PREMUL_COLOR);
}
public void testPremultipliedCanvas() {
Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
bitmap.setHasAlpha(true);
bitmap.setPremultiplied(false);
assertFalse(bitmap.isPremultiplied());
Canvas c = new Canvas();
try {
c.drawBitmap(bitmap, 0, 0, null);
fail("canvas should fail with exception");
} catch (RuntimeException e) {
}
}
private int getBitmapRawInt(Bitmap bitmap) {
IntBuffer buffer = IntBuffer.allocate(1);
bitmap.copyPixelsToBuffer(buffer);
return buffer.get(0);
}
private void bitmapStoreRawInt(Bitmap bitmap, int value) {
IntBuffer buffer = IntBuffer.allocate(1);
buffer.put(0, value);
bitmap.copyPixelsFromBuffer(buffer);
}
public void testSetPremultipliedToBuffer() {
Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
bitmap.setPixel(0, 0, PREMUL_COLOR);
int storedPremul = getBitmapRawInt(bitmap);
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
bitmap.setPremultiplied(false);
bitmap.setPixel(0, 0, PREMUL_STORED_COLOR);
assertEquals(getBitmapRawInt(bitmap), storedPremul);
}
public void testSetPremultipliedFromBuffer() {
Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
bitmap.setPremultiplied(false);
bitmap.setPixel(0, 0, PREMUL_COLOR);
int rawTestColor = getBitmapRawInt(bitmap);
bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
bitmap.setPremultiplied(false);
bitmapStoreRawInt(bitmap, rawTestColor);
assertEquals(bitmap.getPixel(0, 0), PREMUL_COLOR);
}
public void testSetWidth() {
mBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
int alloc = mBitmap.getAllocationByteCount();
// test shrinking
mBitmap.setWidth(50);
assertEquals(mBitmap.getAllocationByteCount(), alloc);
assertEquals(mBitmap.getByteCount() * 2, alloc);
// test expanding
try {
mBitmap.setWidth(101);
fail("shouldn't come to here");
} catch (IllegalArgumentException e) {
}
// test mutable
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
try {
mBitmap.setWidth(1);
fail("shouldn't come to here");
} catch (IllegalStateException e) {
}
}
public void testWriteToParcel(){
mBitmap.recycle();
// abnormal case: the bitmap to be written has been recycled
try{
mBitmap.writeToParcel(null, 0);
fail("shouldn't come to here");
}catch(IllegalStateException e){
}
// abnormal case: failed to unparcel Bitmap
mBitmap = BitmapFactory.decodeResource(mRes, R.drawable.start, mOptions);
Parcel p = Parcel.obtain();
mBitmap.writeToParcel(p, 0);
try{
Bitmap.CREATOR.createFromParcel(p);
fail("shouldn't come to here");
}catch(RuntimeException e){
}
// normal case
mBitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
mBitmap.writeToParcel(p, 0);
p.setDataPosition(0);
mBitmap.equals(Bitmap.CREATOR.createFromParcel(p));
}
public void testGetScaledHeight1() {
int dummyDensity = 5;
Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
int scaledHeight = scaleFromDensity(ret.getHeight(), ret.getDensity(), dummyDensity);
assertNotNull(ret);
assertEquals(scaledHeight, ret.getScaledHeight(dummyDensity));
}
public void testGetScaledHeight2() {
Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
DisplayMetrics metrics = new DisplayMetrics();
metrics = getContext().getResources().getDisplayMetrics();
int scaledHeight = scaleFromDensity(ret.getHeight(), ret.getDensity(), metrics.densityDpi);
assertEquals(scaledHeight, ret.getScaledHeight(metrics));
}
public void testGetScaledHeight3() {
Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
Bitmap mMutableBitmap = Bitmap.createBitmap(100, 200, Config.ARGB_8888);
Canvas mCanvas = new Canvas(mMutableBitmap);
// set Density
mCanvas.setDensity(DisplayMetrics.DENSITY_HIGH);
int scaledHeight = scaleFromDensity(
ret.getHeight(), ret.getDensity(), mCanvas.getDensity());
assertEquals(scaledHeight, ret.getScaledHeight(mCanvas));
}
public void testGetScaledWidth1() {
int dummyDensity = 5;
Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
int scaledWidth = scaleFromDensity(ret.getWidth(), ret.getDensity(), dummyDensity);
assertNotNull(ret);
assertEquals(scaledWidth, ret.getScaledWidth(dummyDensity));
}
public void testGetScaledWidth2() {
Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
DisplayMetrics metrics = new DisplayMetrics();
metrics = getContext().getResources().getDisplayMetrics();
int scaledWidth = scaleFromDensity(ret.getWidth(), ret.getDensity(), metrics.densityDpi);
assertEquals(scaledWidth, ret.getScaledWidth(metrics));
}
public void testGetScaledWidth3() {
Bitmap ret = Bitmap.createBitmap(100, 200, Config.RGB_565);
Bitmap mMutableBitmap = Bitmap.createBitmap(100, 200, Config.ARGB_8888);
Canvas mCanvas = new Canvas(mMutableBitmap);
// set Density
mCanvas.setDensity(DisplayMetrics.DENSITY_HIGH);
int scaledWidth = scaleFromDensity(ret.getWidth(), ret.getDensity(), mCanvas.getDensity());
assertEquals(scaledWidth, ret.getScaledWidth(mCanvas));
}
private int scaleFromDensity(int size, int sdensity, int tdensity) {
if (sdensity == Bitmap.DENSITY_NONE || sdensity == tdensity) {
return size;
}
// Scale by tdensity / sdensity, rounding up.
return ((size * tdensity) + (sdensity >> 1)) / sdensity;
}
private int[] createColors(int size){
int[] colors = new int[size];
for (int i = 0; i < size; i++) {
colors[i] = (0xFF << 24) | (i << 16) | (i << 8) | i;
}
return colors;
}
}