private Bitmap decodeWithOOMHandling(URI imageUri) throws IOException { Bitmap result = null; ImageDecoder decoder = new ImageDecoder(imageUri, downloader, options); decoder.setLoggingEnabled(loggingEnabled); for (int attempt = 1; attempt <= ATTEMPT_COUNT_TO_DECODE_BITMAP; attempt++) { try { ViewScaleType viewScaleType = ViewScaleType.fromImageView(imageView); result = decoder.decode(targetSize, options.getImageScaleType(), viewScaleType); } catch (OutOfMemoryError e) { L.e(e); switch (attempt) { case 1: System.gc(); break; case 2: configuration.memoryCache.clear(); System.gc(); break; case 3: throw e; } // Wait some time while GC is working SystemClock.sleep(attempt * 1000); continue; } break; } return result; }
public void doFetch() { synchronized (this) { if (consumers == null) { awaitingFetch = false; return; } } ImageDecoder imgd = getDecoder(); if (imgd == null) { badDecoder(); } else { setDecoder(imgd); try { imgd.produceImage(); } catch (IOException e) { e.printStackTrace(); // the finally clause will send an error. } catch (ImageFormatException e) { e.printStackTrace(); // the finally clause will send an error. } finally { removeDecoder(imgd); if (Thread.currentThread().isInterrupted() || !Thread.currentThread().isAlive()) { errorAllConsumers(imgd.queue, true); } else { errorAllConsumers(imgd.queue, false); } } } }
public synchronized boolean isConsumer(ImageConsumer ic) { for (ImageDecoder id = decoders; id != null; id = id.next) { if (id.isConsumer(ic)) { return true; } } return ImageConsumerQueue.isConsumer(consumers, ic); }
private Bitmap decodeImage(URI imageUri) throws IOException { Bitmap bmp = null; if (configuration.handleOutOfMemory) { bmp = decodeWithOOMHandling(imageUri); } else { ImageDecoder decoder = new ImageDecoder(imageUri, downloader, options); decoder.setLoggingEnabled(loggingEnabled); ViewScaleType viewScaleType = ViewScaleType.fromImageView(imageView); bmp = decoder.decode(targetSize, options.getImageScaleType(), viewScaleType); } return bmp; }
private synchronized void removeDecoder(ImageDecoder mydecoder) { doneDecoding(mydecoder); ImageDecoder idprev = null; for (ImageDecoder id = decoders; id != null; id = id.next) { if (id == mydecoder) { if (idprev == null) { decoders = id.next; } else { idprev.next = id.next; } break; } idprev = id; } }
private void saveImageOnDisc(File targetFile) throws IOException, URISyntaxException { int width = configuration.maxImageWidthForDiscCache; int height = configuration.maxImageHeightForDiscCache; if (width > 0 || height > 0) { // Download, decode, compress and save image ImageSize targetImageSize = new ImageSize(width, height); ImageDecoder decoder = new ImageDecoder(new URI(uri), downloader, options); decoder.setLoggingEnabled(loggingEnabled); Bitmap bmp = decoder.decode(targetImageSize, ImageScaleType.IN_SAMPLE_INT, ViewScaleType.FIT_INSIDE); if (bmp != null) { OutputStream os = new BufferedOutputStream(new FileOutputStream(targetFile), BUFFER_SIZE); boolean compressedSuccessfully = false; try { compressedSuccessfully = bmp.compress( configuration.imageCompressFormatForDiscCache, configuration.imageQualityForDiscCache, os); } finally { IoUtils.closeSilently(os); } if (compressedSuccessfully) { bmp.recycle(); return; } } } // If previous compression wasn't needed or failed // Download and save original image InputStream is = downloader.getStream(new URI(uri)); try { OutputStream os = new BufferedOutputStream(new FileOutputStream(targetFile), BUFFER_SIZE); try { IoUtils.copyStream(is, os); } finally { IoUtils.closeSilently(os); } } finally { IoUtils.closeSilently(is); } }
synchronized void addConsumer(ImageConsumer ic, boolean produce) { checkSecurity(null, false); for (ImageDecoder id = decoders; id != null; id = id.next) { if (id.isConsumer(ic)) { // This consumer is already being fed. return; } } ImageConsumerQueue cq = consumers; while (cq != null && cq.consumer != ic) { cq = cq.next; } if (cq == null) { cq = new ImageConsumerQueue(this, ic); cq.next = consumers; consumers = cq; } else { if (!cq.secure) { Object context = null; SecurityManager security = System.getSecurityManager(); if (security != null) { context = security.getSecurityContext(); } if (cq.securityContext == null) { cq.securityContext = context; } else if (!cq.securityContext.equals(context)) { // If there are two different security contexts that both // have a handle on the same ImageConsumer, then there has // been a security breach and whether or not they trade // image data is small fish compared to what they could be // trading. Throw a Security exception anyway... errorConsumer(cq, false); throw new SecurityException("Applets are trading image data!"); } } cq.interested = true; } if (produce && decoder == null) { startProduction(); } }
private void setDecoder(ImageDecoder mydecoder) { ImageConsumerQueue cq; synchronized (this) { mydecoder.next = decoders; decoders = mydecoder; decoder = mydecoder; cq = consumers; mydecoder.queue = cq; consumers = null; awaitingFetch = false; } while (cq != null) { if (cq.interested) { // Now that there is a decoder, security may have changed // so reverify it here, just in case. if (!checkSecurity(cq.securityContext, true)) { errorConsumer(cq, false); } } cq = cq.next; } }
public synchronized void removeConsumer(ImageConsumer ic) { for (ImageDecoder id = decoders; id != null; id = id.next) { id.removeConsumer(ic); } consumers = ImageConsumerQueue.removeConsumer(consumers, ic, false); }