@@ -5,7 +5,6 @@ import android.content.Context
55import android.graphics.Bitmap
66import android.graphics.Point
77import android.net.Uri
8- import android.os.Build
98import android.view.LayoutInflater
109import android.view.View
1110import android.view.ViewGroup
@@ -53,17 +52,8 @@ import me.devsaki.hentoid.util.Settings.Value.VIEWER_ORIENTATION_VERTICAL
5352import me.devsaki.hentoid.util.Settings.Value.VIEWER_SEPARATING_BARS_LARGE
5453import me.devsaki.hentoid.util.Settings.Value.VIEWER_SEPARATING_BARS_MEDIUM
5554import me.devsaki.hentoid.util.Settings.Value.VIEWER_SEPARATING_BARS_SMALL
56- import me.devsaki.hentoid.util.file.getInputStream
5755import me.devsaki.hentoid.util.getScreenDimensionsPx
58- import me.devsaki.hentoid.util.image.MIME_IMAGE_AVIF
59- import me.devsaki.hentoid.util.image.MIME_IMAGE_GIF
60- import me.devsaki.hentoid.util.image.MIME_IMAGE_JXL
61- import me.devsaki.hentoid.util.image.MIME_IMAGE_PNG
62- import me.devsaki.hentoid.util.image.MIME_IMAGE_WEBP
63- import me.devsaki.hentoid.util.image.MIME_VIDEO_MP4
6456import me.devsaki.hentoid.util.image.getImageDimensions
65- import me.devsaki.hentoid.util.image.getMimeTypeFromPictureBinary
66- import me.devsaki.hentoid.util.image.isImageAnimated
6757import me.devsaki.hentoid.util.image.needsRotating
6858import me.devsaki.hentoid.views.ZoomableRecyclerView
6959import me.devsaki.hentoid.widget.OnZoneTapListener
@@ -92,6 +82,7 @@ class ImagePagerAdapter(context: Context) :
9282 ListAdapter <ImageFile , ImagePagerAdapter .ImageViewHolder >(IMAGE_DIFF_CALLBACK ) {
9383
9484 enum class ImageType (val value : Int ) {
85+ IMG_TYPE_UNSET (- 1 ),
9586 IMG_TYPE_OTHER (0 ), // PNGs, JPEGs and WEBPs -> use CustomSubsamplingScaleImageView; will fallback to Coil if animation detected
9687 IMG_TYPE_GIF (1 ), // Static and animated GIFs -> use Coil
9788 IMG_TYPE_APNG (2 ), // Animated PNGs -> use Coil
@@ -106,9 +97,6 @@ class ImagePagerAdapter(context: Context) :
10697 SSIV , IMAGEVIEW , VIDEOVIEW
10798 }
10899
109- // Cached image types
110- private val cachedImageTypes: MutableMap <Long , ImageType > = HashMap ()
111-
112100 private val pageMinHeight = context.resources.getDimension(R .dimen.page_min_height).toInt()
113101 private val screenWidth: Int
114102 private val screenHeight: Int
@@ -181,38 +169,6 @@ class ImagePagerAdapter(context: Context) :
181169 this .itemTouchListener = itemTouchListener
182170 }
183171
184- private fun getImageType (context : Context , img : ImageFile ): ImageType {
185- if (img.fileUri.isBlank()) return ImageType .IMG_TYPE_OTHER
186-
187- try {
188- getInputStream(context, img.fileUri.toUri()).use { input ->
189- val header = ByteArray (400 )
190- if (input.read(header) > 0 ) {
191- val mime = getMimeTypeFromPictureBinary(header)
192- val isAnimated = isImageAnimated(header)
193- if (isAnimated) {
194- when (mime) {
195- MIME_IMAGE_PNG -> return ImageType .IMG_TYPE_APNG
196- MIME_IMAGE_WEBP -> return ImageType .IMG_TYPE_AWEBP
197- MIME_IMAGE_GIF -> return ImageType .IMG_TYPE_GIF
198- MIME_IMAGE_AVIF -> return ImageType .IMG_TYPE_AAVIF
199- MIME_VIDEO_MP4 -> return ImageType .IMG_TYPE_VIDEO
200- }
201- } else {
202- when (mime) {
203- MIME_IMAGE_GIF -> return ImageType .IMG_TYPE_GIF
204- MIME_IMAGE_JXL -> return ImageType .IMG_TYPE_JXL
205- MIME_IMAGE_AVIF -> return ImageType .IMG_TYPE_AVIF
206- }
207- }
208- }
209- }
210- } catch (e: Exception ) {
211- Timber .w(e, " Unable to open image file" )
212- }
213- return ImageType .IMG_TYPE_OTHER
214- }
215-
216172 override fun onCreateViewHolder (viewGroup : ViewGroup , viewType : Int ): ImageViewHolder {
217173 val inflater = LayoutInflater .from(viewGroup.context)
218174 val view = inflater.inflate(R .layout.item_reader_image, viewGroup, false )
@@ -380,7 +336,6 @@ class ImagePagerAdapter(context: Context) :
380336 private var isSmoothRendering = false
381337 private var isHalfWidth = false
382338
383- // private var isImageView = false
384339 private var activeView: ActiveView = ActiveView .SSIV
385340
386341 private var img: ImageFile ? = null
@@ -411,13 +366,9 @@ class ImagePagerAdapter(context: Context) :
411366 ssiv.setIgnoreTouchEvents(isVertical || isHalfWidth)
412367
413368 val img = getImageAt(position)
414- var imgType: ImageType = ImageType .IMG_TYPE_OTHER
415- img?.let {
416- imgType =
417- if (cachedImageTypes.containsKey(it.id)) cachedImageTypes.getValue(it.id)
418- else getImageType(rootView.context, it)
419- }
369+ val imgType = img?.imageType ? : ImageType .IMG_TYPE_UNSET
420370
371+ Timber .d(" Picture ${img?.id ? : - 1 } @ $position : bind $imgType " )
421372 if (ImageType .IMG_TYPE_VIDEO == imgType) {
422373 setActiveView(ActiveView .VIDEOVIEW , isClickThrough = true )
423374 } else if (ImageType .IMG_TYPE_GIF == imgType || ImageType .IMG_TYPE_APNG == imgType || ImageType .IMG_TYPE_AWEBP == imgType || ImageType .IMG_TYPE_JXL == imgType || (ImageType .IMG_TYPE_AVIF == imgType) || ImageType .IMG_TYPE_AAVIF == imgType) {
@@ -453,7 +404,7 @@ class ImagePagerAdapter(context: Context) :
453404 }
454405
455406 var imageAvailable = true
456- if (img != null && img.fileUri .isNotEmpty()) setImage(img, imgType)
407+ if (img != null && img.displayUri .isNotEmpty()) setImage(img, imgType)
457408 else imageAvailable = false
458409
459410 val isStreaming = img != null && ! imageAvailable && img.status == StatusContent .ONLINE
@@ -496,10 +447,10 @@ class ImagePagerAdapter(context: Context) :
496447
497448 private fun setImage (img : ImageFile , imgType : ImageType ) {
498449 this .img = img
499- val uri = img.fileUri .toUri()
450+ val uri = img.displayUri .toUri()
500451 isLoading.set(true )
501452 noImgTxt.isVisible = false
502- Timber .d(" Picture $absoluteAdapterPosition : binding viewholder $imgType $uri " )
453+ Timber .d(" Picture $absoluteAdapterPosition ( ${img.id} ) : binding viewholder $imgType $uri " )
503454 when (activeView) {
504455 ActiveView .SSIV -> {
505456 Timber .d(" Picture $absoluteAdapterPosition : Using SSIV" )
@@ -524,7 +475,11 @@ class ImagePagerAdapter(context: Context) :
524475 }
525476
526477 ActiveView .IMAGEVIEW -> {
527- imgView?.let { loadImageView(it, uri, imgType) }
478+ imgView?.let {
479+ it.lifecycleScope?.launch {
480+ loadImageView(it, uri, imgType)
481+ }
482+ }
528483 }
529484
530485 ActiveView .VIDEOVIEW -> {
@@ -534,47 +489,47 @@ class ImagePagerAdapter(context: Context) :
534489 Timber .d(" Picture $absoluteAdapterPosition : binding viewholder END $imgType $uri " )
535490 }
536491
537- fun loadImageView (view : View , uri : Uri , imgType : ImageType ) {
538- view.lifecycleScope?.launch {
539- val isChangeDims = when (autoRotate) {
540- Settings . Value . READER_AUTO_ROTATE_NONE -> false
541- else -> {
492+ suspend fun loadImageView (view : View , uri : Uri , imgType : ImageType ) {
493+ val isChangeDims = when (autoRotate) {
494+ Settings . Value . READER_AUTO_ROTATE_NONE -> false
495+ else -> {
496+ withContext( Dispatchers . IO ) {
542497 // Preload the pic to get its dimensions
543498 val dims = getImageDimensions(view.context, uri.toString())
544499 needsRotating(screenWidth, screenHeight, dims.x, dims.y)
545500 }
546501 }
502+ }
547503
548- recyclerView?.let {
549- val imgLayoutParams = view.layoutParams
550- imgLayoutParams.width =
551- if (isChangeDims) it.height else ViewGroup .LayoutParams .MATCH_PARENT
552- imgLayoutParams.height =
553- if (isChangeDims) it.width else ViewGroup .LayoutParams .MATCH_PARENT
554- view.layoutParams = imgLayoutParams
555- }
504+ recyclerView?.let {
505+ val imgLayoutParams = view.layoutParams
506+ imgLayoutParams.width =
507+ if (isChangeDims) it.height else ViewGroup .LayoutParams .MATCH_PARENT
508+ imgLayoutParams.height =
509+ if (isChangeDims) it.width else ViewGroup .LayoutParams .MATCH_PARENT
510+ view.layoutParams = imgLayoutParams
511+ }
556512
557- Timber .d(" Picture $absoluteAdapterPosition : Using Coil" )
558- imageView.scaleType = scaleType
559-
560- // Custom loader to handle JXL and AVIF
561- // (doesn't support Hardware bitmaps : https://github.com/awxkee/jxl-coder-coil/issues/7)
562- view.context.let { ctx ->
563- val imageLoader = SingletonImageLoader .get(ctx)
564- val request = ImageRequest .Builder (ctx)
565- .data(uri)
566- .diskCacheKey(uri.toString())
567- .memoryCacheKey(uri.toString())
568- .target(imageView)
569- .allowHardware(imgType != ImageType .IMG_TYPE_JXL && imgType != ImageType .IMG_TYPE_AVIF )
570- .listener(
571- onError = { _, err -> onCoilLoadFailed(err) },
572- onSuccess = { _, res -> onCoilLoadSuccess(res) }
573- )
574- .allowConversionToBitmap(false )
575- imageLoader.enqueue(request.build())
576- }
577- } // Lifecyclescope
513+ Timber .d(" Picture $absoluteAdapterPosition : Using Coil" )
514+ imageView.scaleType = scaleType
515+
516+ // Custom loader to handle JXL and AVIF
517+ // (doesn't support Hardware bitmaps : https://github.com/awxkee/jxl-coder-coil/issues/7)
518+ view.context.let { ctx ->
519+ val imageLoader = SingletonImageLoader .get(ctx)
520+ val request = ImageRequest .Builder (ctx)
521+ .data(uri)
522+ .diskCacheKey(uri.toString())
523+ .memoryCacheKey(uri.toString())
524+ .target(imageView)
525+ .allowHardware(imgType != ImageType .IMG_TYPE_JXL && imgType != ImageType .IMG_TYPE_AVIF )
526+ .listener(
527+ onError = { _, err -> onCoilLoadFailed(err) },
528+ onSuccess = { _, res -> onCoilLoadSuccess(res) }
529+ )
530+ .allowConversionToBitmap(false )
531+ imageLoader.enqueue(request.build())
532+ }
578533 }
579534
580535 fun loadVideoView (uri : Uri ) {
@@ -799,14 +754,12 @@ class ImagePagerAdapter(context: Context) :
799754 override fun onImageLoadError (e : Throwable ) {
800755 Timber .d(
801756 e,
802- " Picture %d : SSIV loading failed: %s" ,
803- absoluteAdapterPosition,
804- img!! .fileUri
757+ " Picture $absoluteAdapterPosition : SSIV loading failed: ${img?.displayUri ? : " " } " ,
805758 )
806759 }
807760
808761 override fun onTileLoadError (e : Throwable ) {
809- Timber .d(e, " Picture %d : tileLoad error" , absoluteAdapterPosition )
762+ Timber .d(e, " Picture $absoluteAdapterPosition : tileLoad error" )
810763 }
811764
812765 override fun onPreviewReleased () {
@@ -817,9 +770,7 @@ class ImagePagerAdapter(context: Context) :
817770 private fun onCoilLoadFailed (err : ErrorResult ) {
818771 Timber .d(
819772 err.throwable,
820- " Picture %d : Coil loading failed : %s" ,
821- absoluteAdapterPosition,
822- img!! .fileUri
773+ " Picture $absoluteAdapterPosition : Coil loading failed : ${img?.displayUri ? : " " } "
823774 )
824775 if (activeView == ActiveView .IMAGEVIEW ) noImgTxt.visibility = View .VISIBLE
825776 isLoading.set(false )
0 commit comments