@Override public Resource<Bitmap> transform(Resource<Bitmap> resource, int outWidth, int outHeight) { if (outWidth <= 0 || outHeight <= 0) { throw new IllegalArgumentException("Cannot center crop image to width=" + outWidth + " and height=" + outHeight); } final Bitmap toReuse = pool.get(outWidth, outHeight, resource.get().getConfig()); Bitmap transformed = TransformationUtils.centerCrop(toReuse, resource.get(), outWidth, outHeight); if (toReuse != null && toReuse != transformed && !pool.put(toReuse)) { toReuse.recycle(); } if (transformed == resource.get()) { return resource; } else { return new BitmapResource(transformed, pool); } }
@Override public Resource<Bitmap> decode(ImageVideoWrapper source, int width, int height) throws IOException { Resource<Bitmap> result = null; InputStream is = source.getStream(); if (is != null) { try { result = streamDecoder.decode(source.getStream(), width, height); } catch (IOException e) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Failed to load image from stream, trying FileDescriptor", e); } } } if (result == null) { result = fileDescriptorDecoder.decode(source.getFileDescriptor(), width, height); } return result; }
@Override public Resource<Drawable> transcode(Resource<GifBitmapWrapper> toTranscode) { GifBitmapWrapper gifBitmap = toTranscode.get(); Resource<Bitmap> bitmapResource = gifBitmap.getBitmapResource(); final Resource resource; final Drawable drawable; if (bitmapResource != null) { resource = bitmapResource; drawable = new BitmapDrawable(resources, bitmapResource.get()); } else { resource = gifBitmap.getGifResource(); drawable = gifBitmap.getGifResource().get().getDrawable(); } return new DrawableResource(drawable, resource); }
@Override public Resource<GifBitmapWrapper> transform(Resource<GifBitmapWrapper> resource, int outWidth, int outHeight) { Resource<Bitmap> bitmapResource = resource.get().getBitmapResource(); if (bitmapResource != null) { Resource<Bitmap> transformed = wrapped.transform(bitmapResource, outWidth, outHeight); if (transformed != bitmapResource) { GifBitmapWrapper gifBitmap = new GifBitmapWrapper(transformed, null); return new GifBitmapWrapperResource(gifBitmap); } } else { //TODO: this should be pushed down into a GifData transformation? Resource<GifData> gifResource = resource.get().getGifResource(); GifData gifData = gifResource.get(); Transformation<Bitmap> newTransformation = new MultiTransformation<Bitmap>(gifData.getFrameTransformation(), wrapped); gifData.setFrameTransformation(newTransformation); return new GifBitmapWrapperResource(new GifBitmapWrapper(null, new GifDataResource(gifData))); } return resource; }
@Override public void run() { if (isCancelled) { return; } long start = SystemClock.currentThreadTimeMillis(); Resource<Z> fromCache = loadFromDiskCache(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "loaded from disk cache in " + (SystemClock.currentThreadTimeMillis() - start)); } if (fromCache != null) { Resource<R> transcoded = transcoder.transcode(fromCache); job.onResourceReady(transcoded); } else { future = executorService.submit(sourceRunner); } }
private Resource<Z> loadFromDiskCache() { Resource<Z> result = null; InputStream fromCache = diskCache.get(key); if (fromCache != null) { try { result = cacheDecoder.decode(fromCache, width, height); } catch (IOException e) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Exception decoding image from cache", e); } } if (result == null) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Failed to decode image from cache or not present in cache"); } diskCache.delete(key); } } return result; }
@Override public void onResourceReady(Resource resource) { if (!canSetImage()) { resource.release(); return; } if (resource == null || !transcodeClass.isAssignableFrom(resource.get().getClass())) { if (resource != null) { resource.release(); } onException(new Exception("Expected to receive an object of " + transcodeClass + " but instead got " + (resource != null ? resource.get() : null))); return; } R result = (R) resource.get(); target.onResourceReady(result); if (!loadedFromMemoryCache && !isAnyImageSet()) { if (animation == null && animationId > 0) { animation = AnimationUtils.loadAnimation(context, animationId); } if (animation != null) { target.startAnimation(animation); } } if (requestListener != null) { requestListener.onImageReady(model, target, loadedFromMemoryCache, isAnyImageSet()); } this.resource = resource; }
@Override public boolean encode(Resource<GifData> resource, OutputStream os) { boolean result = true; try { os.write(resource.get().getData()); } catch (IOException e) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Failed to encode gif", e); } result = false; } return result; }
@Override public Resource<Bitmap> decode(ParcelFileDescriptor source, int width, int height) throws IOException { Bitmap bitmap = bitmapDecoder.decode(source, bitmapPool, width, height, decodeFormat); if (bitmap == null) { return null; } else { return new BitmapResource(bitmap, bitmapPool); } }
@Override public Resource<Bitmap> decode(InputStream source, int width, int height) { Bitmap bitmap = downsampler.decode(source, bitmapPool, width, height, decodeFormat); if (bitmap == null) { return null; } else { return new BitmapResource(bitmap, bitmapPool); } }
@Override public Resource<Bitmap> transform(Resource<Bitmap> resource, int outWidth, int outHeight) { if (outWidth <= 0 || outHeight <= 0) { throw new IllegalArgumentException("Cannot fit center image to within width=" + outWidth + " or height=" + outHeight); } Bitmap transformed = TransformationUtils.fitCenter(resource.get(), pool, outWidth, outHeight); if (transformed == resource.get()) { return resource; } else { return new BitmapResource(transformed, pool); } }
@Override public Resource<byte[]> transcode(Resource<Bitmap> toTranscode) { ByteArrayOutputStream os = new ByteArrayOutputStream(); toTranscode.get().compress(compressFormat, quality, os); toTranscode.recycle(); return new BytesResource(os.toByteArray()); }
@Override public boolean encode(Resource<GifBitmapWrapper> resource, OutputStream os) { final GifBitmapWrapper gifBitmap = resource.get(); final Resource<Bitmap> bitmapResource = gifBitmap.getBitmapResource(); if (bitmapResource != null) { return bitmapEncoder.encode(bitmapResource, os); } else { return gifEncoder.encode(gifBitmap.getGifResource(), os); } }
@Override public void run() { if (isCancelled) { return; } try { long start = SystemClock.currentThreadTimeMillis(); final Resource<Z> decoded = decode(); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "Decoded from source in " + (SystemClock.currentThreadTimeMillis() - start)); start = SystemClock.currentThreadTimeMillis(); } if (decoded != null) { Resource<Z> transformed = transformation.transform(decoded, width, height); if (decoded != transformed) { decoded.recycle(); } result = transformed; } if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "transformed in " + (SystemClock.currentThreadTimeMillis() - start)); } if (result != null) { diskCache.put(key, this); start = SystemClock.currentThreadTimeMillis(); Resource<R> transcoded = transcoder.transcode(result); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.d(TAG, "transcoded in " + (SystemClock.currentThreadTimeMillis() - start)); } cb.onResourceReady(transcoded); } else { cb.onException(null); } } catch (Exception e) { cb.onException(e); } }
private Resource<Z> decode() throws Exception { try { T toDecode = fetcher.loadData(priority); if (toDecode != null) { return decoder.decode(toDecode, width, height); } } finally { fetcher.cleanup(); } return null; }
@Override public void onResourceReady(final Resource resource) { mainHandler.post(new Runnable() { @Override public void run() { if (isCancelled) { resource.recycle(); return; } isComplete = true; // 1 to hold on for duration of request. resource.acquire(cbs.size() + 2); listener.onEngineJobComplete(key); if (isCacheable) { cache.put(key, resource); } else { resource.release(); } for (ResourceCallback cb : cbs) { cb.onResourceReady(resource); } // Our request is complete, so we can release the resource. resource.release(); } }); }
/** * * @param id A unique id for the model, dimensions, cache decoder, decoder, and encoder * @param cacheDecoder * @param fetcher * @param decoder * @param encoder * @param transcoder * @param priority * @param <T> The type of data the resource will be decoded from. * @param <Z> The type of the resource that will be decoded. * @param <R> The type of the resource that will be transcoded from the decoded resource. */ public <T, Z, R> LoadStatus load(String id, int width, int height, ResourceDecoder<InputStream, Z> cacheDecoder, DataFetcher<T> fetcher, ResourceDecoder<T, Z> decoder, Transformation<Z> transformation, ResourceEncoder<Z> encoder, ResourceTranscoder<Z, R> transcoder, Priority priority, boolean isMemoryCacheable, ResourceCallback cb) { Key key = keyFactory.buildKey(id, width, height, cacheDecoder, decoder, transformation, encoder, transcoder); Resource cached = cache.get(key); if (cached != null) { cached.acquire(1); cb.onResourceReady(cached); return null; } ResourceRunner current = runners.get(key); if (current != null) { EngineJob job = current.getJob(); job.addCallback(cb); return new LoadStatus(cb, job); } ResourceRunner<Z, R> runner = factory.build(key, width, height, cacheDecoder, fetcher, decoder, transformation, encoder, transcoder, priority, isMemoryCacheable, this); runner.getJob().addCallback(cb); runners.put(key, runner); runner.queue(); return new LoadStatus(cb, runner.getJob()); }
private Resource<T> transform(Resource<T> current, Transformation<T> transformation, int outWidth, int outHeight) { Resource<T> transformed = transformation.transform(current, outWidth, outHeight); if (current != null && current != transformed) { current.recycle(); } return transformed; }
/** * Get the next frame in the animation sequence. * * @return Bitmap representation of frame */ public Resource<Bitmap> getNextFrame() { if (header.frameCount <= 0 || framePointer < 0 ) { return null; } GifFrame frame = header.frames.get(framePointer); //Set the appropriate color table if (frame.lct == null) { act = header.gct; } else { act = frame.lct; if (header.bgIndex == frame.transIndex) { header.bgColor = 0; } } int save = 0; if (frame.transparency) { save = act[frame.transIndex]; act[frame.transIndex] = 0; // set transparent color if specified } if (act == null) { Log.w(TAG, "No Valid Color Table"); header.status = STATUS_FORMAT_ERROR; // no color table defined return null; } Bitmap result = setPixels(framePointer); // transfer pixel data to image currentImage = result; // Reset the transparent pixel in the color table if (frame.transparency) { act[frame.transIndex] = save; } return new BitmapResource(result, bitmapPool); }