diff --git a/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt b/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt index 7a79c011a..3723079ed 100644 --- a/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt +++ b/app/src/main/java/org/koitharu/kotatsu/domain/MangaUtils.kt @@ -1,7 +1,11 @@ package org.koitharu.kotatsu.domain +import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.graphics.Color +import android.graphics.Rect import android.util.Size +import androidx.core.graphics.get import okhttp3.OkHttpClient import okhttp3.Request import org.koin.core.KoinComponent @@ -11,6 +15,8 @@ import org.koitharu.kotatsu.core.model.MangaPage import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.utils.ext.await import org.koitharu.kotatsu.utils.ext.medianOrNull +import org.koitharu.kotatsu.utils.ext.use +import java.io.File import java.io.InputStream object MangaUtils : KoinComponent { @@ -54,4 +60,81 @@ object MangaUtils : KoinComponent { check(imageHeight > 0 && imageWidth > 0) return Size(imageWidth, imageHeight) } + + @JvmStatic + fun cropBitmap(input: Bitmap): Bitmap? { + return try { + val bounds = Rect(0, 0, input.width, input.height) + var isBoundsChanged = false + for (x in 1 until input.width / 2) { + var leftColor = 0 + var rightColor = 0 + for (y in 0 until input.height) { + leftColor += input[x, y] + rightColor += input[input.width - x - 1, y] + } + leftColor /= input.height + rightColor /= input.height + var consumed = false + if (leftColor == Color.WHITE) { + bounds.left++ + consumed = true + } + if (rightColor == Color.WHITE) { + bounds.right-- + consumed = true + } + if (consumed) { + isBoundsChanged = true + } else { + break + } + } + for (y in 1 until input.height / 2) { + var topColor = 0 + var bottomColor = 0 + for (x in 0 until input.width) { + topColor += input[x, y] + bottomColor += input[x, input.height - y - 1] + } + topColor /= input.width + bottomColor /= input.width + var consumed = false + if (topColor == Color.WHITE) { + bounds.top++ + consumed = true + } + if (bottomColor == Color.WHITE) { + bounds.bottom-- + consumed = true + } + if (consumed) { + isBoundsChanged = true + } else { + break + } + } + if (isBoundsChanged) { + Bitmap.createBitmap(input, bounds.left, bounds.top, bounds.width(), bounds.height()) + } else { + null + } + } catch (e: Throwable) { + if (BuildConfig.DEBUG) { + e.printStackTrace() + } + null + } + } + + @JvmStatic + fun cropBitmap(file: File) { + BitmapFactory.decodeFile(file.path).use { bmp -> + cropBitmap(bmp)?.use { cropped -> + file.outputStream().use { out -> + cropped.compress(Bitmap.CompressFormat.WEBP, 100, out) + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageLoader.kt b/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageLoader.kt index badbe52d2..fd9bf762b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageLoader.kt +++ b/app/src/main/java/org/koitharu/kotatsu/ui/reader/PageLoader.kt @@ -1,7 +1,9 @@ package org.koitharu.kotatsu.ui.reader import android.net.Uri +import androidx.annotation.WorkerThread import kotlinx.coroutines.* +import kotlinx.coroutines.sync.Mutex import okhttp3.OkHttpClient import okhttp3.Request import org.koin.core.KoinComponent @@ -16,13 +18,14 @@ import kotlin.coroutines.CoroutineContext class PageLoader : KoinComponent, CoroutineScope, DisposableHandle { private val job = SupervisorJob() - private val tasks = HashMap() + private val mutex = Mutex() private val okHttp by inject() private val cache by inject() override val coroutineContext: CoroutineContext get() = Dispatchers.Main + job + @WorkerThread @Suppress("BlockingMethodInNonBlockingContext") suspend fun loadFile(url: String, force: Boolean): File { if (!force) { @@ -55,6 +58,10 @@ class PageLoader : KoinComponent, CoroutineScope, DisposableHandle { response.body!!.byteStream().copyTo(out) } } + }.also { + mutex.withLock(this) { + MangaUtils.cropBitmap(it) + } } } diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CommonExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CommonExt.kt index 39b790d39..ab4015db9 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CommonExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CommonExt.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.utils.ext import android.content.res.Resources +import android.graphics.Bitmap import kotlinx.coroutines.delay import org.koitharu.kotatsu.BuildConfig import org.koitharu.kotatsu.R @@ -43,4 +44,10 @@ fun Throwable.getDisplayMessage(resources: Resources) = when (this) { } else { resources.getString(R.string.error_occurred) } +} + +inline fun Bitmap.use(block: (Bitmap) -> R): R = try { + block(this) +} finally { + recycle() } \ No newline at end of file