blob: a441c21c213e4606c8afce94462a01a4dee29561 [file] [log] [blame]
Owen Lina2fba682011-08-17 22:07:43 +08001/*
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
17package com.android.gallery3d.ui;
18
Owen Lina2fba682011-08-17 22:07:43 +080019import android.graphics.Bitmap;
20import android.graphics.Bitmap.Config;
21import android.graphics.BitmapFactory;
22import android.graphics.BitmapRegionDecoder;
23import android.graphics.Canvas;
24import android.graphics.Rect;
25
Owen Lin2e4790c2011-10-18 16:57:15 +080026import com.android.gallery3d.common.Utils;
27
Owen Lina2fba682011-08-17 22:07:43 +080028public class TileImageViewAdapter implements TileImageView.Model {
Owen Lin2e4790c2011-10-18 16:57:15 +080029 private static final String TAG = "TileImageViewAdapter";
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +080030 protected ScreenNail mScreenNail;
Owen Lina2fba682011-08-17 22:07:43 +080031 protected BitmapRegionDecoder mRegionDecoder;
32 protected int mImageWidth;
33 protected int mImageHeight;
Owen Lina2fba682011-08-17 22:07:43 +080034 protected int mLevelCount;
35 protected boolean mFailedToLoad;
36
Owen Lina2fba682011-08-17 22:07:43 +080037 public TileImageViewAdapter() {
38 }
39
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +080040 public TileImageViewAdapter(Bitmap bitmap, BitmapRegionDecoder regionDecoder) {
41 mScreenNail = new BitmapScreenNail(Utils.checkNotNull(bitmap), 0);
Owen Lina2fba682011-08-17 22:07:43 +080042 mRegionDecoder = regionDecoder;
43 mImageWidth = regionDecoder.getWidth();
44 mImageHeight = regionDecoder.getHeight();
45 mLevelCount = calculateLevelCount();
46 }
47
48 public synchronized void clear() {
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +080049 mScreenNail = null;
Owen Lina2fba682011-08-17 22:07:43 +080050 mImageWidth = 0;
51 mImageHeight = 0;
52 mLevelCount = 0;
53 mRegionDecoder = null;
54 mFailedToLoad = false;
55 }
56
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +080057 public synchronized void setScreenNail(Bitmap bitmap, int width, int height) {
58 mScreenNail = new BitmapScreenNail(Utils.checkNotNull(bitmap), 0);
59 mImageWidth = width;
60 mImageHeight = height;
61 mRegionDecoder = null;
62 mLevelCount = 0;
63 mFailedToLoad = false;
64 }
65
66 public synchronized void setScreenNail(
67 ScreenNail screenNail, int width, int height) {
68 mScreenNail = Utils.checkNotNull(screenNail);
Owen Lina2fba682011-08-17 22:07:43 +080069 mImageWidth = width;
70 mImageHeight = height;
71 mRegionDecoder = null;
72 mLevelCount = 0;
73 mFailedToLoad = false;
74 }
75
76 public synchronized void setRegionDecoder(BitmapRegionDecoder decoder) {
77 mRegionDecoder = Utils.checkNotNull(decoder);
78 mImageWidth = decoder.getWidth();
79 mImageHeight = decoder.getHeight();
80 mLevelCount = calculateLevelCount();
81 mFailedToLoad = false;
82 }
83
84 private int calculateLevelCount() {
85 return Math.max(0, Utils.ceilLog2(
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +080086 (float) mImageWidth / mScreenNail.getWidth()));
Owen Lina2fba682011-08-17 22:07:43 +080087 }
88
89 @Override
Chih-Chung Chang4a01c6e2012-03-21 16:19:21 +080090 public synchronized Bitmap getTile(int level, int x, int y, int tileSize,
91 int borderSize) {
Owen Lin2e4790c2011-10-18 16:57:15 +080092 if (mRegionDecoder == null) return null;
93
Chih-Chung Chang4a01c6e2012-03-21 16:19:21 +080094 // wantRegion is the rectangle on the original image we want. askRegion
95 // is the rectangle on the original image that we will ask from
96 // mRegionDecoder. Both are in the coordinates of the original image,
97 // not the coordinates of the scaled-down images.
98 Rect wantRegion = new Rect();
99 Rect askRegion = new Rect();
Owen Lina2fba682011-08-17 22:07:43 +0800100
Chih-Chung Chang4a01c6e2012-03-21 16:19:21 +0800101 int b = borderSize << level;
102 wantRegion.set(x - b, y - b, x + (tileSize << level) + b,
103 y + (tileSize << level) + b);
104
105 // askRegion is the intersection of wantRegion and the original image.
106 askRegion.set(0, 0, mImageWidth, mImageHeight);
107 Utils.assertTrue(askRegion.intersect(wantRegion));
Owen Lina2fba682011-08-17 22:07:43 +0800108
109 BitmapFactory.Options options = new BitmapFactory.Options();
110 options.inPreferredConfig = Config.ARGB_8888;
111 options.inPreferQualityOverSpeed = true;
112 options.inSampleSize = (1 << level);
113
114 Bitmap bitmap;
115
116 // In CropImage, we may call the decodeRegion() concurrently.
117 synchronized (mRegionDecoder) {
Chih-Chung Chang4a01c6e2012-03-21 16:19:21 +0800118 bitmap = mRegionDecoder.decodeRegion(askRegion, options);
Owen Lina2fba682011-08-17 22:07:43 +0800119 }
120
Owen Lin2e4790c2011-10-18 16:57:15 +0800121 if (bitmap == null) {
122 Log.w(TAG, "fail in decoding region");
123 return null;
124 }
125
Chih-Chung Chang4a01c6e2012-03-21 16:19:21 +0800126 if (wantRegion.equals(askRegion)) return bitmap;
127
128 // Now the wantRegion does not match the askRegion. This means we are at
129 // a boundary tile, and we need to add paddings. Create a new Bitmap
130 // and copy over.
131 int size = tileSize + 2 * borderSize;
132 Bitmap result = Bitmap.createBitmap(size, size, Config.ARGB_8888);
133 Canvas canvas = new Canvas(result);
134 int offsetX = (askRegion.left - wantRegion.left) >> level;
135 int offsetY = (askRegion.top - wantRegion.top) >> level;
136 canvas.drawBitmap(bitmap, offsetX, offsetY, null);
137
138 // If the valid region (covered by bitmap or border) is smaller than the
139 // result bitmap, subset it.
140 int endX = offsetX + bitmap.getWidth() + borderSize;
141 int endY = offsetY + bitmap.getHeight() + borderSize;
Owen Lina2fba682011-08-17 22:07:43 +0800142 bitmap.recycle();
Chih-Chung Chang4a01c6e2012-03-21 16:19:21 +0800143 if (endX < size || endY < size) {
144 return Bitmap.createBitmap(result, 0, 0, Math.min(size, endX),
145 Math.min(size, endY));
146 } else {
147 return result;
148 }
Owen Lina2fba682011-08-17 22:07:43 +0800149 }
150
151 @Override
Chih-Chung Chang706a7cf2012-03-15 16:38:45 +0800152 public ScreenNail getScreenNail() {
153 return mScreenNail;
Owen Lina2fba682011-08-17 22:07:43 +0800154 }
155
156 @Override
157 public int getImageHeight() {
158 return mImageHeight;
159 }
160
161 @Override
162 public int getImageWidth() {
163 return mImageWidth;
164 }
165
166 @Override
167 public int getLevelCount() {
168 return mLevelCount;
169 }
170
171 public void setFailedToLoad() {
172 mFailedToLoad = true;
173 }
174
175 @Override
176 public boolean isFailedToLoad() {
177 return mFailedToLoad;
178 }
179}