I need Glide to load the images using ARGB_8888 in just a single activity of my application. How can I do this? Do I have to detect the activity in the GlideModule?
You can't for a single Activity, but you can for each single Glide load inside that Activity:
....load(...).asBitmap().format(PREFER_ARGB_8888)....
Great. Thank you
that's cool , i need this
I've used the format method but the Images are still losing the quality. Is there any other option to download the image as a 100% JPG? Actually I'm not sure if this is a problem with Glide or PhotoView zooming (still checking this), so a good test would be to download the images to the cache and open them outside my app.
How can I do this with Glide and be notified after the image has been saved?
Did you clear the cache / reinstall app? The old cached files may be still there which were saved from 565 format into disk cache. However high quailty you load those, they'll still have low quailty colors. Can you post a screenshot of your expected/actual quality? It's also possbible that you're loading smaller images that upscale. Hard to tell without Glide load line or screenshot.
Yes, I did both. Here is the original image: http://hqcomicsonline.com.br/leitor/hq/V-Force%20V2/01/02.jpg
The code I'm using:
static class SamplePagerAdapter extends PagerAdapter {
@Override
public int getCount() {
return pageList.size();
}
@Override
public View instantiateItem(ViewGroup container, int position) {
PhotoView photoView = new PhotoView(container.getContext());
Glide.with(container.getContext())
.load(pageList.get(position))
.asBitmap()
.format(DecodeFormat.PREFER_ARGB_8888)
.asIs()
.into(photoView);
// Now just add PhotoView to ViewPager and return it
container.addView(photoView, ViewPager.LayoutParams.MATCH_PARENT, ViewPager.LayoutParams.MATCH_PARENT);
return photoView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
}

What is PhotoView? Do you have match_parent on the ViewPager in xml?
PhotoView is an ImageView implementation from Chris Banes that allows zooming: https://github.com/chrisbanes/PhotoView
Here is XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:id="@+id/viewer_container"
tools:context="br.com.hqcomicsonline.app.ui.Viewer2Activity">
<fr.castorflex.android.circularprogressbar.CircularProgressBar
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:indeterminate="true"
app:cpb_color="#F00"
app:cpb_colors="@array/color_array"
app:cpb_max_sweep_angle="300"
app:cpb_min_sweep_angle="10"
app:cpb_rotation_speed="1.0"
app:cpb_stroke_width="4dp"
app:cpb_sweep_speed="1.0"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
<br.com.hqcomicsonline.app.views.HackyViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Ok, so, since your screenshot looks like a full screen app with margins and only part of the image is shown it looks like you're zoomed in into PhotoView. Zooming in on an image will blow up pixels and you'll get this low quality look, so it's a natural phenomenon.
The important thing here is that Glide is designed for efficiency, that is to minimize memory, CPU and therefore battery consumption. When an average user loads an image with Glide they usually do so into a normal ImageView just to show it to the user. In that case Glide just measures the view and loads a Bitmap with that exact size to minimize memory footprint, loading a pixel-perfect match to the view size. On initial load your image may look nice, but if you zoom in you're not zooming the original full-resolution image, but the view-sized one.
To load the image with original size you can tell Glide: .override(Target.SIZE_ORIGINAL). I see that you tried to achieve the same with .asIs() which could work too: the problem here is that while the Bitmap is decoded with sampleSize = 1 you're still transforming it with .fitCenter() which is implicit (see GenericRequestBuilder.into(ImageView)) from ImageView's default. To disable transformation add .dontTransform().
So to summarize, use one of these:
.load().asBitmap().asIs().dontTransform()
.load().override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
In the first case it doesn't matter what the size of the target is, because neither decode nor transformation will be applied.
In the second case it doesn't matter if there's an implicity .fitCenter(), because the Bitmap size and the expect size will match and no transformation will be done, see BitmapTransformation.transform and TransformationUtils.fitCenter.
You might wonder what's the point of two different ones: in the second case you can still apply a transformation, for example adding a watermark, changing some colors, blurring, adding border, etc.
This is a HQ viewer app, that's why I need a better quality. I've tried with override() and the quality is perfect now. Normally this would cause OOME, however I think PhotoView handles such thing. I'll keep testing this.
Just one more question in case I have to switch to another ImageView control. How can I save the downloaded image with the override and get the path to the cached image? I know another control called SubsamplingScaleImageView that loads images from files on internal storage/SDCard.
Yes, sorry, I didn't emphasize that your use case is no the "average" one.
PhotoView can't handle OOMs, because you (via Glide) create the Bitmap so the OOM would occur before PhotoView gets to know the Bitmap. You can write a custom decoder/downsampler which retries on OOM and increases the sample size to load the largest possible image that can fit into that device's memory.
That other one looks more promising because it dynamically loads smaller and larger images on zoom and is likely only decoding the visible part with BitmapRegionDecoder. If you transition to that one you'll essentially use Glide as a network downloader, which is fine, but it's not what it's designed for. The advantage of still using it is that with .diskCacheStrategy(ALL) you can download and display thumbs with Glide and when you open one of them in another activity you can fetch the image File from the SOURCE cache using downloadOnly().
Now it makes sense. But how can I get the absolute path to the downloaded image on cache? The SubsamplingScaleImageView does not accept a Bitmap, only the path to an image.
downloadOnly, see last sentence above; you get a File, not a Bitmap.
Sorry about that. And thank you for taking your time to help me.
Sorry for one more question.
Should the code be like this?
final File file = Glide.with(ViewerActivity.this)
.load(url)
.downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL).get();
runOnUiThread(new Runnable() {
@Override
public void run() {
pagerAdapter.add(file.getAbsolutePath());
}
});
Because the lib that is trying to open the image is generating a File not found exception.
E/SubsamplingScaleImageView: Failed to initialise bitmap decoder
java.io.FileNotFoundException: /data/data/br.com.hqcomicsonline.app/cache/image_manager_disk_cache/761384cbe7a46252e42256adbb4c84450aff3fcf5a0681a8a0797a1891256cc7.0
at android.content.res.AssetManager.openAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:316)
at com.davemorrissey.labs.subscaleview.decoder.SkiaImageRegionDecoder.init(SkiaImageRegionDecoder.java:59)
at com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView$TilesInitTask.doInBackground(SubsamplingScaleImageView.java:1400)
at com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView$TilesInitTask.doInBackground(SubsamplingScaleImageView.java:1376)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
You're doing the Glide part right, you can see the file path is correct. The problem is your usage of SSIV, probably calling the wrong API: my guess would be that there are overloads to some method you call within your pager where String means asset and File means SDCard.
Edit: see the 3rd point at https://github.com/davemorrissey/subsampling-scale-image-view#quick-start
You were right. The fragment code was using ImageSource.asset instead of ImageSource.uri.
Thank you very much!
Most helpful comment
You can't for a single Activity, but you can for each single Glide load inside that Activity: