-
-
Save davemorrissey/e2781ba5b966c9e95539 to your computer and use it in GitHub Desktop.
/** | |
* Created by gokhanbarisaker on 8/30/15. | |
*/ | |
public class PicassoDecoder implements ImageDecoder | |
{ | |
private String tag; | |
private String picasso; | |
public PicassoDecoder(String tag, Picasso picasso) { | |
this.tag = tag; | |
this.picasso = picasso; | |
} | |
@Override | |
public Bitmap decode(Context context, Uri uri) throws Exception { | |
return picasso | |
.load(uri) | |
.tag(tag) | |
.config(Bitmap.Config.RGB_565) | |
.memoryPolicy(MemoryPolicy.NO_CACHE) | |
.get(); | |
} | |
} |
/** | |
* Created by gokhanbarisaker on 8/30/15. | |
*/ | |
public class PicassoRegionDecoder implements ImageRegionDecoder { | |
private OkHttpClient client; | |
private BitmapRegionDecoder decoder; | |
private final Object decoderLock = new Object(); | |
public PicassoRegionDecoder (OkHttpClient client) { | |
this.client = client; | |
} | |
@Override | |
public Point init(Context context, Uri uri) throws Exception { | |
OkHttpDownloader downloader = new OkHttpDownloader(client); | |
InputStream inputStream = downloader.load(uri, 0).getInputStream(); | |
this.decoder = BitmapRegionDecoder.newInstance(inputStream, false); | |
return new Point(this.decoder.getWidth(), this.decoder.getHeight()); | |
} | |
@Override | |
public Bitmap decodeRegion(Rect rect, int sampleSize) { | |
synchronized(this.decoderLock) { | |
BitmapFactory.Options options = new BitmapFactory.Options(); | |
options.inSampleSize = sampleSize; | |
options.inPreferredConfig = Bitmap.Config.RGB_565; | |
Bitmap bitmap = this.decoder.decodeRegion(rect, options); | |
if(bitmap == null) { | |
throw new RuntimeException("Region decoder returned null bitmap - image format may not be supported"); | |
} else { | |
return bitmap; | |
} | |
} | |
} | |
@Override | |
public boolean isReady() { | |
return this.decoder != null && !this.decoder.isRecycled(); | |
} | |
@Override | |
public void recycle() { | |
this.decoder.recycle(); | |
} | |
} |
With the new Picasso snapshot the init
function of the PicassoRegionDecoder
looks like this:
@Override
public Point init(Context context, Uri uri) throws Exception {
OkHttp3Downloader downloader = new OkHttp3Downloader(client);
okhttp3.Request request = new Request.Builder().url(uri.toString()).build();
InputStream inputStream = downloader.load(request).body().byteStream();
this.decoder = BitmapRegionDecoder.newInstance(inputStream, false);
return new Point(this.decoder.getWidth(), this.decoder.getHeight());
}
Jesus! Combine libraries can be a nightmare sometimes. You need to line up the proper versions of each library.
These are the versions that work for me:
implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0'
implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.squareup.okhttp:okhttp:2.1.0'
Anyone got a code snippet that uses the isImageLoaded() override so I can have a "downloading...." display until the image comes up when using this with Picasso/Okhttp?
(Nevermind -- figured it out ;-) I like this a lot....)
@tickerguy how did you do that?
use the SSIV listener
image.setOnImageEventListener(new SubsamplingScaleImageView.OnImageEventListener() {
@Override
public void onReady() {
//You could start loading your image here, so the ssiv is ready.
}
@Override
public void onImageLoaded() {
//Do your stuff here.
}
@Override
public void onPreviewLoadError(Exception e) {}
@Override
public void onImageLoadError(Exception e) {}
@Override
public void onTileLoadError(Exception e) {}
@Override
public void onPreviewReleased() {}
});
** How to intercept the bitmap before the SSIV** : using Glide : (Working on 8k images with latest implementation 4.11.0)
Glide.with(ssiv.getContext())
.asBitmap()
.load("https://vah.dy.fi/testcard/7680x4320.png") //Your own link
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
//Do whatever you want with the bitmap (like saving it to storage)
//ex : ssiv.setImage(ImageSource.bitmap(resource);
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
Provide a decoder based on HttpUrlConnection
, not OkHttp
or Picasso
dependency needed. Use only if you don't need image cache.
class URLImageDecoder : ImageDecoder {
private var bitmapConfig: Bitmap.Config =
SubsamplingScaleImageView.getPreferredBitmapConfig() ?: Bitmap.Config.RGB_565
@Throws(java.lang.Exception::class)
override fun decode(context: Context, uri: Uri): Bitmap {
val options = BitmapFactory.Options().apply { inPreferredConfig = bitmapConfig }
val bitmap: Bitmap?
var inputStream: InputStream? = null
try {
inputStream = URL(uri.toString()).openStream()
bitmap = BitmapFactory.decodeStream(inputStream, null, options)
} finally {
try {
inputStream?.close()
} catch (ignored: Exception) {
}
}
return bitmap
?: throw RuntimeException("Region decoder returned null bitmap - image format may not be supported")
}
}
class URLImageRegionDecoder : ImageRegionDecoder {
private lateinit var decoder: BitmapRegionDecoder
private val decoderLock: ReadWriteLock = ReentrantReadWriteLock(true)
private val bitmapConfig: Bitmap.Config =
SubsamplingScaleImageView.getPreferredBitmapConfig() ?: Bitmap.Config.RGB_565
@Throws(Exception::class)
override fun init(context: Context, uri: Uri): Point {
var inputStream: InputStream? = null
try {
inputStream = URL(uri.toString()).openStream()
decoder = BitmapRegionDecoder.newInstance(inputStream, false)
} finally {
try {
inputStream?.close()
} catch (ignored: Exception) {
}
}
return Point(decoder.width, decoder.height)
}
override fun decodeRegion(rect: Rect, sampleSize: Int): Bitmap {
getDecodeLock().lock()
return try {
if (!decoder.isRecycled) {
val options = BitmapFactory.Options()
options.inSampleSize = sampleSize
options.inPreferredConfig = bitmapConfig
decoder.decodeRegion(rect, options) ?: throw java.lang.RuntimeException(
"Skia image decoder returned null bitmap - image format may not be supported")
} else {
throw IllegalStateException("Cannot decode region after decoder has been recycled")
}
} finally {
getDecodeLock().unlock()
}
}
override fun isReady(): Boolean = !decoder.isRecycled
override fun recycle() = decoder.recycle()
/**
* Before SDK 21, BitmapRegionDecoder was not synchronized internally. Any attempt to decode
* regions from multiple threads with one decoder instance causes a segfault. For old versions
* use the write lock to enforce single threaded decoding.
*/
private fun getDecodeLock(): Lock {
return if (Build.VERSION.SDK_INT < 21) {
decoderLock.writeLock()
} else {
decoderLock.readLock()
}
}
}
Has anyone tried to do this for Glide?