1 /* 2 * Copyright (C) 2010 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.gallery3d.ui; 18 19 import android.graphics.Bitmap; 20 import android.graphics.Bitmap.Config; 21 import android.graphics.BitmapFactory; 22 import android.graphics.BitmapRegionDecoder; 23 import android.graphics.Canvas; 24 import android.graphics.Rect; 25 26 import com.android.gallery3d.common.Utils; 27 28 public class TileImageViewAdapter implements TileImageView.Model { 29 private static final String TAG = "TileImageViewAdapter"; 30 protected BitmapRegionDecoder mRegionDecoder; 31 protected int mImageWidth; 32 protected int mImageHeight; 33 protected Bitmap mBackupImage; 34 protected int mLevelCount; 35 protected boolean mFailedToLoad; 36 37 private final Rect mIntersectRect = new Rect(); 38 private final Rect mRegionRect = new Rect(); 39 40 public TileImageViewAdapter() { 41 } 42 43 public TileImageViewAdapter(Bitmap backup, BitmapRegionDecoder regionDecoder) { 44 mBackupImage = Utils.checkNotNull(backup); 45 mRegionDecoder = regionDecoder; 46 mImageWidth = regionDecoder.getWidth(); 47 mImageHeight = regionDecoder.getHeight(); 48 mLevelCount = calculateLevelCount(); 49 } 50 51 public synchronized void clear() { 52 mBackupImage = null; 53 mImageWidth = 0; 54 mImageHeight = 0; 55 mLevelCount = 0; 56 mRegionDecoder = null; 57 mFailedToLoad = false; 58 } 59 60 public synchronized void setBackupImage(Bitmap backup, int width, int height) { 61 mBackupImage = Utils.checkNotNull(backup); 62 mImageWidth = width; 63 mImageHeight = height; 64 mRegionDecoder = null; 65 mLevelCount = 0; 66 mFailedToLoad = false; 67 } 68 69 public synchronized void setRegionDecoder(BitmapRegionDecoder decoder) { 70 mRegionDecoder = Utils.checkNotNull(decoder); 71 mImageWidth = decoder.getWidth(); 72 mImageHeight = decoder.getHeight(); 73 mLevelCount = calculateLevelCount(); 74 mFailedToLoad = false; 75 } 76 77 private int calculateLevelCount() { 78 return Math.max(0, Utils.ceilLog2( 79 (float) mImageWidth / mBackupImage.getWidth())); 80 } 81 82 @Override 83 public synchronized Bitmap getTile(int level, int x, int y, int length) { 84 if (mRegionDecoder == null) return null; 85 86 Rect region = mRegionRect; 87 Rect intersectRect = mIntersectRect; 88 region.set(x, y, x + (length << level), y + (length << level)); 89 intersectRect.set(0, 0, mImageWidth, mImageHeight); 90 91 // Get the intersected rect of the requested region and the image. 92 Utils.assertTrue(intersectRect.intersect(region)); 93 94 BitmapFactory.Options options = new BitmapFactory.Options(); 95 options.inPreferredConfig = Config.ARGB_8888; 96 options.inPreferQualityOverSpeed = true; 97 options.inSampleSize = (1 << level); 98 99 Bitmap bitmap; 100 101 // In CropImage, we may call the decodeRegion() concurrently. 102 synchronized (mRegionDecoder) { 103 bitmap = mRegionDecoder.decodeRegion(intersectRect, options); 104 } 105 106 // The returned region may not match with the targetLength. 107 // If so, we fill black pixels on it. 108 if (intersectRect.equals(region)) return bitmap; 109 110 if (bitmap == null) { 111 Log.w(TAG, "fail in decoding region"); 112 return null; 113 } 114 115 Bitmap tile = Bitmap.createBitmap(length, length, Config.ARGB_8888); 116 Canvas canvas = new Canvas(tile); 117 canvas.drawBitmap(bitmap, 118 (intersectRect.left - region.left) >> level, 119 (intersectRect.top - region.top) >> level, null); 120 bitmap.recycle(); 121 return tile; 122 } 123 124 @Override 125 public Bitmap getBackupImage() { 126 return mBackupImage; 127 } 128 129 @Override 130 public int getImageHeight() { 131 return mImageHeight; 132 } 133 134 @Override 135 public int getImageWidth() { 136 return mImageWidth; 137 } 138 139 @Override 140 public int getLevelCount() { 141 return mLevelCount; 142 } 143 144 public void setFailedToLoad() { 145 mFailedToLoad = true; 146 } 147 148 @Override 149 public boolean isFailedToLoad() { 150 return mFailedToLoad; 151 } 152 } 153