Home | History | Annotate | Download | only in ui
      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