Refactor descrambling bitmap

master
Koitharu 2 years ago
parent 88b3e5cf34
commit da6db9c1b4
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

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

@ -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)
}

@ -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)
}
}

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

@ -150,10 +150,6 @@ class FaviconFetcher(
return if (networkResponse != null) DataSource.NETWORK else DataSource.DISK 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 { private fun Size.toCacheKey() = buildString {
append(width.toString()) append(width.toString())
append('x') append('x')

@ -1,13 +1,12 @@
package org.koitharu.kotatsu.core.util.ext package org.koitharu.kotatsu.core.util.ext
import okhttp3.Cookie import okhttp3.Cookie
import okhttp3.Headers
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response import okhttp3.Response
import okhttp3.ResponseBody
import okhttp3.internal.closeQuietly import okhttp3.internal.closeQuietly
import okhttp3.internal.isSensitiveHeader
import okio.IOException import okio.IOException
import org.json.JSONObject import org.json.JSONObject
import org.jsoup.HttpStatusException 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 -> fun Cookie.newBuilder(): Cookie.Builder = Cookie.Builder().also { c ->
c.name(name) c.name(name)
c.value(value) c.value(value)

Loading…
Cancel
Save