Refactor descrambling bitmap

This commit is contained in:
Koitharu
2024-05-23 16:55:41 +03:00
parent 88b3e5cf34
commit da6db9c1b4
6 changed files with 57 additions and 70 deletions

View File

@@ -82,11 +82,7 @@ afterEvaluate {
}
dependencies {
//noinspection GradleDependency
// TODO: change bac
// implementation('com.github.KotatsuApp:kotatsu-parsers:078b59b1e2') {
// exclude group: 'org.json', module: 'json'
// }
implementation('com.github.AwkwardPeak7:kotatsu-parsers:d7d42465de') {
implementation('com.github.KotatsuApp:kotatsu-parsers:350bc0ad58') {
exclude group: 'org.json', module: 'json'
}

View File

@@ -1,48 +0,0 @@
package org.koitharu.kotatsu.core.parser
import android.graphics.Canvas
import android.graphics.Bitmap as AndroidBitmap
import android.graphics.Rect as AndroidRect
import org.koitharu.kotatsu.parsers.bitmap.Bitmap
import org.koitharu.kotatsu.parsers.bitmap.Rect
class BitmapImpl private constructor() : Bitmap {
lateinit var androidBitmap: AndroidBitmap
private lateinit var canvas: Canvas
override val height: Int
get() = androidBitmap.height
override val width: Int
get() = androidBitmap.width
override fun drawBitmap(sourceBitmap: Bitmap, src: Rect, dst: Rect) {
val androidSourceBitmap = (sourceBitmap as BitmapImpl).androidBitmap
canvas.drawBitmap(androidSourceBitmap, src.toAndroidRect(), dst.toAndroidRect(), null)
}
companion object {
fun create(width: Int, height: Int): Bitmap {
val instance = BitmapImpl()
instance.androidBitmap = AndroidBitmap.createBitmap(width, height, AndroidBitmap.Config.ARGB_8888)
instance.canvas = Canvas(instance.androidBitmap)
return instance
}
fun create(bitmap: AndroidBitmap): Bitmap {
val instance = BitmapImpl()
instance.androidBitmap = bitmap.copy(AndroidBitmap.Config.ARGB_8888, true)
instance.canvas = Canvas(instance.androidBitmap)
return instance
}
}
}
private fun Rect.toAndroidRect(): AndroidRect {
return AndroidRect(left, top, right, bottom)
}

View File

@@ -0,0 +1,43 @@
package org.koitharu.kotatsu.core.parser
import android.graphics.Canvas
import org.koitharu.kotatsu.parsers.bitmap.Bitmap
import org.koitharu.kotatsu.parsers.bitmap.Rect
import java.io.OutputStream
import android.graphics.Bitmap as AndroidBitmap
import android.graphics.Rect as AndroidRect
class BitmapWrapper private constructor(
private val androidBitmap: AndroidBitmap,
) : Bitmap {
private val canvas by lazy { Canvas(androidBitmap) } // is not always used, so initialized lazily
override val height: Int
get() = androidBitmap.height
override val width: Int
get() = androidBitmap.width
override fun drawBitmap(sourceBitmap: Bitmap, src: Rect, dst: Rect) {
val androidSourceBitmap = (sourceBitmap as BitmapWrapper).androidBitmap
canvas.drawBitmap(androidSourceBitmap, src.toAndroidRect(), dst.toAndroidRect(), null)
}
fun compressTo(output: OutputStream) {
androidBitmap.compress(AndroidBitmap.CompressFormat.PNG, 100, output)
}
companion object {
fun create(width: Int, height: Int): Bitmap = BitmapWrapper(
AndroidBitmap.createBitmap(width, height, AndroidBitmap.Config.ARGB_8888),
)
fun create(bitmap: AndroidBitmap): Bitmap = BitmapWrapper(
if (bitmap.isMutable) bitmap else bitmap.copy(AndroidBitmap.Config.ARGB_8888, true),
)
private fun Rect.toAndroidRect() = AndroidRect(left, top, right, bottom)
}
}

View File

@@ -1,6 +1,5 @@
package org.koitharu.kotatsu.core.parser
import android.graphics.Bitmap as AndroidBitmap
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.BitmapFactory
@@ -22,6 +21,7 @@ import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
import org.koitharu.kotatsu.core.prefs.SourceSettings
import org.koitharu.kotatsu.core.util.ext.configureForParser
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.core.util.ext.requireBody
import org.koitharu.kotatsu.core.util.ext.sanitizeHeaderValue
import org.koitharu.kotatsu.core.util.ext.toList
import org.koitharu.kotatsu.parsers.MangaLoaderContext
@@ -76,17 +76,16 @@ class MangaLoaderContextImpl @Inject constructor(
}
override fun redrawImageResponse(response: Response, redraw: (image: Bitmap) -> Bitmap): Response {
val image = requireNotNull(response.body) {
"Response is null"
}.byteStream()
val image = response.requireBody().byteStream()
val bitmap = BitmapFactory.decodeStream(image)
val result = redraw(BitmapImpl.create(bitmap)) as BitmapImpl
val opts = BitmapFactory.Options()
opts.inMutable = true
val bitmap = BitmapFactory.decodeStream(image, null, opts) ?: error("Cannot decode bitmap")
val result = redraw(BitmapWrapper.create(bitmap)) as BitmapWrapper
val body = Buffer().run {
result.androidBitmap.compress(AndroidBitmap.CompressFormat.JPEG, 90, outputStream())
asResponseBody("image/jpeg".toMediaType())
}
val body = Buffer().also {
result.compressTo(it.outputStream())
}.asResponseBody("image/jpeg".toMediaType())
return response.newBuilder()
.body(body)
@@ -94,7 +93,7 @@ class MangaLoaderContextImpl @Inject constructor(
}
override fun createBitmap(width: Int, height: Int): Bitmap {
return BitmapImpl.create(width, height)
return BitmapWrapper.create(width, height)
}
@MainThread

View File

@@ -150,10 +150,6 @@ class FaviconFetcher(
return if (networkResponse != null) DataSource.NETWORK else DataSource.DISK
}
private fun Response.requireBody(): ResponseBody {
return checkNotNull(body) { "response body == null" }
}
private fun Size.toCacheKey() = buildString {
append(width.toString())
append('x')

View File

@@ -1,13 +1,12 @@
package org.koitharu.kotatsu.core.util.ext
import okhttp3.Cookie
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import okhttp3.ResponseBody
import okhttp3.internal.closeQuietly
import okhttp3.internal.isSensitiveHeader
import okio.IOException
import org.json.JSONObject
import org.jsoup.HttpStatusException
@@ -42,6 +41,8 @@ fun Response.ensureSuccess() = apply {
}
}
fun Response.requireBody(): ResponseBody = checkNotNull(body) { "Response body is null" }
fun Cookie.newBuilder(): Cookie.Builder = Cookie.Builder().also { c ->
c.name(name)
c.value(value)