koush / ion

Android Asynchronous Networking and Image Loading
Other
6.29k stars 1.03k forks source link

DeepZoom scaling quality issues #771

Open ghost opened 8 years ago

ghost commented 8 years ago

I'm the lead developer of Nori, an open-source image search API client for Android. Nori recently switched from okHTTP/Picasso to Ion as its HTTP and image loading library. It uses PhotoView to implement multi-touch scale and pan gestures in the full-screen image pager.

I wanted to take advantage of DeepZoom to reduce memory footprint of the full-screen image viewer, but enabling it causes issues with scaling down high-resolution images to the PhotoView's dimensions. The lines and edges of objects look jagged, as if the image was scaled up from a lower resolution. This is especially noticeable with line-art and digital paintings, less so with photographs. The quality improves as the image is zoomed in.

Example - DeepZoom enabled. PhotoView default zoom. Looks jagged. Example - DeepZoom enabled. PhotoView zoomed in. Looks fine. Example - DeepZoom disabled. PhotoView default zoom. Looks fine. Original Image (1000x1414)

My device's screen resolution is 1280x720. (hdpi)

You can use Nori 3.0.0 to test this, as it has DeepZoom enabled. This is the relevant image loading code: RemoteImageFragment.java#L68

I'm not sure if this is a duplicate of #466, as I can't view the bug report on Google Plus. subsampling-image-view is another "DeepZoom" image loading library that apparently does not have this issue.

koush commented 8 years ago

if i recall correctly, photoview's imageview provides a hint for what tiling level deepzoom should use.

https://github.com/koush/ion/blob/master/ion-sample/src/com/koushikdutta/ion/sample/DeepZoomSample.java

See setMaximumScale

I think basically, the zoom you need to set on PhotoView has to be something like

Max.max( image.actualWidth / PhotoView.getMeasuredWidth, image.actualHeight / PhotoView.getMeasuredHeight, )

Basically, you want the zoom at the maximum scale to be a 1:1 pixel mapping between the photoview and the loaded image.

koush commented 8 years ago

So for you, your maximum scale in that sample (1000 / 1280) is roughly 7.8125. Since you set yours to 4, I think that's why you get those jaggies. Ion relies on the target canvas (PhotoView in this case) to provide correct info to handle the image loading:

https://github.com/koush/ion/blob/master/ion/src/com/koushikdutta/ion/IonDrawable.java#L629

koush commented 8 years ago

What you can do is after .intoImageView, use setCallback, and then get the photoview's drawable. Grab the intrinsic with and height, and divide it by the photoview's measured width and height (as shown above) to do the max scale math.

DeepZoom is meant to work with any library (as it simply provides a Drawable to an ImageView), but there's some level of developer "glue" that needs to happen.