From c60b14998af9a69206a58c0d50a547156907bfa8 Mon Sep 17 00:00:00 2001 From: FooIbar <118464521+FooIbar@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:57:35 +0800 Subject: [PATCH] Fix crash when drawing > 100 MB bitmaps --- .../hippo/ehviewer/ui/reader/BitmapPainter.kt | 48 +++++++++++++++++++ .../com/hippo/ehviewer/ui/reader/PagerItem.kt | 4 +- 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 app/src/main/kotlin/com/hippo/ehviewer/ui/reader/BitmapPainter.kt diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/BitmapPainter.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/BitmapPainter.kt new file mode 100644 index 000000000..77c5a02ad --- /dev/null +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/BitmapPainter.kt @@ -0,0 +1,48 @@ +package com.hippo.ehviewer.ui.reader + +import android.graphics.Bitmap +import android.graphics.Matrix +import android.graphics.Paint +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.drawscope.drawIntoCanvas +import androidx.compose.ui.graphics.nativeCanvas +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.toOffset +import androidx.compose.ui.unit.toSize + +class BitmapPainter( + private val image: Bitmap, + srcOffset: IntOffset = IntOffset.Zero, + srcSize: IntSize = IntSize(image.width, image.height), +) : Painter() { + + private val offset = (-srcOffset).toOffset() + + private val srcSize = srcSize.toSize() + + private val matrix = Matrix() + + override fun DrawScope.onDraw() = drawIntoCanvas { + // Use the overload that takes a `Matrix` to bypass the 100 MB size limit + it.nativeCanvas.drawBitmap( + image, + matrix.apply { + setTranslate(offset.x, offset.y) + postScale(size.width / srcSize.width, size.height / srcSize.height) + }, + bitmapPaint, + ) + } + + override val intrinsicSize get() = srcSize + + companion object { + private val bitmapPaint = Paint().apply { + isAntiAlias = true + isFilterBitmap = true + isDither = true + } + } +} diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PagerItem.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PagerItem.kt index 62eb65eb0..e232f65e9 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PagerItem.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/reader/PagerItem.kt @@ -20,8 +20,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorMatrix -import androidx.compose.ui.graphics.asImageBitmap -import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign @@ -114,7 +112,7 @@ fun PagerItem( private fun Image.toPainter() = when (val image = innerImage) { is BitmapImage -> BitmapPainter( - image = image.bitmap.asImageBitmap(), + image = image.bitmap, srcOffset = rect.topLeft, srcSize = rect.size, )