1 /* 2 * Copyright (C) 2013 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.filtershow.pipeline; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.graphics.Bitmap; 22 import android.graphics.Canvas; 23 import android.graphics.Matrix; 24 import android.graphics.Paint; 25 import android.graphics.Rect; 26 import android.graphics.RectF; 27 import android.util.Log; 28 29 import com.android.gallery3d.filtershow.cache.BitmapCache; 30 import com.android.gallery3d.filtershow.cache.ImageLoader; 31 import com.android.gallery3d.filtershow.filters.FilterRepresentation; 32 import com.android.gallery3d.filtershow.filters.FiltersManager; 33 import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils; 34 import com.android.gallery3d.filtershow.imageshow.PrimaryImage; 35 36 import java.util.Vector; 37 38 public class CachingPipeline implements PipelineInterface { 39 private static final String LOGTAG = "CachingPipeline"; 40 private boolean DEBUG = false; 41 42 private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; 43 44 private FiltersManager mFiltersManager = null; 45 private volatile Bitmap mOriginalBitmap = null; 46 private volatile Bitmap mResizedOriginalBitmap = null; 47 48 private FilterEnvironment mEnvironment = new FilterEnvironment(); 49 private CacheProcessing mCachedProcessing = new CacheProcessing(); 50 51 private volatile int mWidth = 0; 52 private volatile int mHeight = 0; 53 54 private volatile float mPreviewScaleFactor = 1.0f; 55 private volatile float mHighResPreviewScaleFactor = 1.0f; 56 private volatile String mName = ""; 57 CachingPipeline(FiltersManager filtersManager, String name)58 public CachingPipeline(FiltersManager filtersManager, String name) { 59 mFiltersManager = filtersManager; 60 mName = name; 61 } 62 stop()63 public void stop() { 64 mEnvironment.setStop(true); 65 } 66 reset()67 public synchronized void reset() { 68 synchronized (CachingPipeline.class) { 69 mOriginalBitmap = null; // just a reference to the bitmap in ImageLoader 70 if (mResizedOriginalBitmap != null) { 71 mResizedOriginalBitmap.recycle(); 72 mResizedOriginalBitmap = null; 73 } 74 75 mPreviewScaleFactor = 1.0f; 76 mHighResPreviewScaleFactor = 1.0f; 77 78 mWidth = 0; 79 mHeight = 0; 80 } 81 } 82 getType(RenderingRequest request)83 private String getType(RenderingRequest request) { 84 if (request.getType() == RenderingRequest.ICON_RENDERING) { 85 return "ICON_RENDERING"; 86 } 87 if (request.getType() == RenderingRequest.FILTERS_RENDERING) { 88 return "FILTERS_RENDERING"; 89 } 90 if (request.getType() == RenderingRequest.FULL_RENDERING) { 91 return "FULL_RENDERING"; 92 } 93 if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) { 94 return "GEOMETRY_RENDERING"; 95 } 96 if (request.getType() == RenderingRequest.PARTIAL_RENDERING) { 97 return "PARTIAL_RENDERING"; 98 } 99 if (request.getType() == RenderingRequest.HIGHRES_RENDERING) { 100 return "HIGHRES_RENDERING"; 101 } 102 return "UNKNOWN TYPE!"; 103 } 104 setupEnvironment(ImagePreset preset, boolean highResPreview)105 private void setupEnvironment(ImagePreset preset, boolean highResPreview) { 106 mEnvironment.setPipeline(this); 107 mEnvironment.setFiltersManager(mFiltersManager); 108 mEnvironment.setBitmapCache(PrimaryImage.getImage().getBitmapCache()); 109 if (highResPreview) { 110 mEnvironment.setScaleFactor(mHighResPreviewScaleFactor); 111 } else { 112 mEnvironment.setScaleFactor(mPreviewScaleFactor); 113 } 114 mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); 115 mEnvironment.setImagePreset(preset); 116 mEnvironment.setStop(false); 117 } 118 setOriginal(Bitmap bitmap)119 public void setOriginal(Bitmap bitmap) { 120 mOriginalBitmap = bitmap; 121 Log.v(LOGTAG,"setOriginal, size " + bitmap.getWidth() + " x " + bitmap.getHeight()); 122 ImagePreset preset = PrimaryImage.getImage().getPreset(); 123 setupEnvironment(preset, false); 124 updateOriginalAllocation(preset); 125 } 126 updateOriginalAllocation(ImagePreset preset)127 private synchronized boolean updateOriginalAllocation(ImagePreset preset) { 128 if (preset == null) { 129 return false; 130 } 131 Bitmap originalBitmap = mOriginalBitmap; 132 133 if (originalBitmap == null) { 134 return false; 135 } 136 137 mResizedOriginalBitmap = preset.applyGeometry(originalBitmap, mEnvironment); 138 139 return true; 140 } 141 renderHighres(RenderingRequest request)142 public void renderHighres(RenderingRequest request) { 143 synchronized (CachingPipeline.class) { 144 ImagePreset preset = request.getImagePreset(); 145 setupEnvironment(preset, false); 146 Bitmap bitmap = PrimaryImage.getImage().getOriginalBitmapHighres(); 147 if (bitmap == null) { 148 return; 149 } 150 bitmap = mEnvironment.getBitmapCopy(bitmap, BitmapCache.HIGHRES); 151 bitmap = preset.applyGeometry(bitmap, mEnvironment); 152 153 mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); 154 Bitmap bmp = preset.apply(bitmap, mEnvironment); 155 if (!mEnvironment.needsStop()) { 156 request.setBitmap(bmp); 157 } else { 158 mEnvironment.cache(bmp); 159 } 160 mFiltersManager.freeFilterResources(preset); 161 } 162 } 163 renderGeometry(RenderingRequest request)164 public void renderGeometry(RenderingRequest request) { 165 synchronized (CachingPipeline.class) { 166 ImagePreset preset = request.getImagePreset(); 167 setupEnvironment(preset, false); 168 Bitmap bitmap = PrimaryImage.getImage().getOriginalBitmapHighres(); 169 if (bitmap == null) { 170 return; 171 } 172 bitmap = mEnvironment.getBitmapCopy(bitmap, BitmapCache.GEOMETRY); 173 bitmap = preset.applyGeometry(bitmap, mEnvironment); 174 if (!mEnvironment.needsStop()) { 175 request.setBitmap(bitmap); 176 } else { 177 mEnvironment.cache(bitmap); 178 } 179 mFiltersManager.freeFilterResources(preset); 180 } 181 } 182 renderFilters(RenderingRequest request)183 public void renderFilters(RenderingRequest request) { 184 synchronized (CachingPipeline.class) { 185 ImagePreset preset = request.getImagePreset(); 186 setupEnvironment(preset, false); 187 Bitmap bitmap = PrimaryImage.getImage().getOriginalBitmapHighres(); 188 if (bitmap == null) { 189 return; 190 } 191 bitmap = mEnvironment.getBitmapCopy(bitmap, BitmapCache.FILTERS); 192 bitmap = preset.apply(bitmap, mEnvironment); 193 if (!mEnvironment.needsStop()) { 194 request.setBitmap(bitmap); 195 } else { 196 mEnvironment.cache(bitmap); 197 } 198 mFiltersManager.freeFilterResources(preset); 199 } 200 } 201 render(RenderingRequest request)202 public synchronized void render(RenderingRequest request) { 203 // TODO: cleanup/remove GEOMETRY / FILTERS paths 204 synchronized (CachingPipeline.class) { 205 if ((request.getType() != RenderingRequest.PARTIAL_RENDERING 206 && request.getType() != RenderingRequest.ICON_RENDERING 207 && request.getBitmap() == null) 208 || request.getImagePreset() == null) { 209 return; 210 } 211 212 if (DEBUG) { 213 Log.v(LOGTAG, "render image of type " + getType(request)); 214 } 215 216 Bitmap bitmap = request.getBitmap(); 217 ImagePreset preset = request.getImagePreset(); 218 setupEnvironment(preset, true); 219 mFiltersManager.freeFilterResources(preset); 220 221 if (request.getType() == RenderingRequest.PARTIAL_RENDERING) { 222 PrimaryImage primary = PrimaryImage.getImage(); 223 bitmap = ImageLoader.getScaleOneImageForPreset(primary.getActivity(), 224 mEnvironment.getBimapCache(), 225 primary.getUri(), request.getBounds(), 226 request.getDestination()); 227 if (bitmap == null) { 228 Log.w(LOGTAG, "could not get bitmap for: " + getType(request)); 229 return; 230 } 231 } 232 233 if (request.getType() == RenderingRequest.FULL_RENDERING 234 || request.getType() == RenderingRequest.GEOMETRY_RENDERING 235 || request.getType() == RenderingRequest.FILTERS_RENDERING) { 236 updateOriginalAllocation(preset); 237 } 238 239 if (DEBUG && bitmap != null) { 240 Log.v(LOGTAG, "after update, req bitmap (" + bitmap.getWidth() + "x" 241 + bitmap.getHeight() + " ? resizeOriginal (" 242 + mResizedOriginalBitmap.getWidth() + "x" 243 + mResizedOriginalBitmap.getHeight()); 244 } 245 246 if (request.getType() == RenderingRequest.FULL_RENDERING 247 || request.getType() == RenderingRequest.GEOMETRY_RENDERING) { 248 bitmap = mResizedOriginalBitmap; 249 } else if (request.getType() == RenderingRequest.FILTERS_RENDERING) { 250 bitmap = mOriginalBitmap; 251 } 252 253 if (request.getType() == RenderingRequest.FULL_RENDERING 254 || request.getType() == RenderingRequest.FILTERS_RENDERING 255 || request.getType() == RenderingRequest.ICON_RENDERING 256 || request.getType() == RenderingRequest.PARTIAL_RENDERING 257 || request.getType() == RenderingRequest.STYLE_ICON_RENDERING) { 258 259 if (request.getType() == RenderingRequest.ICON_RENDERING) { 260 mEnvironment.setQuality(FilterEnvironment.QUALITY_ICON); 261 } else { 262 mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); 263 } 264 265 if (request.getType() == RenderingRequest.ICON_RENDERING) { 266 Rect iconBounds = request.getIconBounds(); 267 Bitmap source = PrimaryImage.getImage().getThumbnailBitmap(); 268 if (iconBounds.width() > source.getWidth() * 2) { 269 source = PrimaryImage.getImage().getLargeThumbnailBitmap(); 270 } 271 if (iconBounds != null) { 272 bitmap = mEnvironment.getBitmap(iconBounds.width(), 273 iconBounds.height(), BitmapCache.ICON); 274 Canvas canvas = new Canvas(bitmap); 275 Matrix m = new Matrix(); 276 float minSize = Math.min(source.getWidth(), source.getHeight()); 277 float maxSize = Math.max(iconBounds.width(), iconBounds.height()); 278 float scale = maxSize / minSize; 279 m.setScale(scale, scale); 280 float dx = (iconBounds.width() - (source.getWidth() * scale))/2.0f; 281 float dy = (iconBounds.height() - (source.getHeight() * scale))/2.0f; 282 m.postTranslate(dx, dy); 283 canvas.drawBitmap(source, m, new Paint(Paint.FILTER_BITMAP_FLAG)); 284 } else { 285 bitmap = mEnvironment.getBitmapCopy(source, BitmapCache.ICON); 286 } 287 } 288 Bitmap bmp = preset.apply(bitmap, mEnvironment); 289 if (!mEnvironment.needsStop()) { 290 request.setBitmap(bmp); 291 } 292 mFiltersManager.freeFilterResources(preset); 293 } 294 } 295 } 296 renderFinalImage(Bitmap bitmap, ImagePreset preset)297 public synchronized Bitmap renderFinalImage(Bitmap bitmap, ImagePreset preset) { 298 synchronized (CachingPipeline.class) { 299 setupEnvironment(preset, false); 300 mEnvironment.setQuality(FilterEnvironment.QUALITY_FINAL); 301 mEnvironment.setScaleFactor(1.0f); 302 mFiltersManager.freeFilterResources(preset); 303 bitmap = preset.applyGeometry(bitmap, mEnvironment); 304 bitmap = preset.apply(bitmap, mEnvironment); 305 return bitmap; 306 } 307 } 308 renderGeometryIcon(Bitmap bitmap, ImagePreset preset)309 public Bitmap renderGeometryIcon(Bitmap bitmap, ImagePreset preset) { 310 return GeometryMathUtils.applyGeometryRepresentations(preset.getGeometryFilters(), bitmap); 311 } 312 compute(SharedBuffer buffer, ImagePreset preset, int type)313 public void compute(SharedBuffer buffer, ImagePreset preset, int type) { 314 setupEnvironment(preset, false); 315 Vector<FilterRepresentation> filters = preset.getFilters(); 316 Bitmap result = mCachedProcessing.process(mOriginalBitmap, filters, mEnvironment); 317 buffer.setProducer(result); 318 mEnvironment.cache(result); 319 } 320 needsRepaint()321 public boolean needsRepaint() { 322 SharedBuffer buffer = PrimaryImage.getImage().getPreviewBuffer(); 323 return buffer.checkRepaintNeeded(); 324 } 325 setPreviewScaleFactor(float previewScaleFactor)326 public void setPreviewScaleFactor(float previewScaleFactor) { 327 mPreviewScaleFactor = previewScaleFactor; 328 } 329 setHighResPreviewScaleFactor(float highResPreviewScaleFactor)330 public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) { 331 mHighResPreviewScaleFactor = highResPreviewScaleFactor; 332 } 333 isInitialized()334 public synchronized boolean isInitialized() { 335 return mOriginalBitmap != null; 336 } 337 getName()338 public String getName() { 339 return mName; 340 } 341 } 342