From 5c6d6a820152e57cd0005ec02db7698908f5d873 Mon Sep 17 00:00:00 2001 From: Alessandro Jean <14254807+alessandrojean@users.noreply.github.com> Date: Tue, 18 Apr 2023 15:19:00 -0300 Subject: [PATCH] Maybe fix the JPEG EXIF parsing in VIZ (#16096) * Maybe fix the JPEG EXIF parsing in VIZ. * Handle the common HTTP 403 case while getting the image. --- src/en/vizshonenjump/build.gradle | 2 +- .../en/vizshonenjump/VizImageInterceptor.kt | 52 ++++++++++--------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/en/vizshonenjump/build.gradle b/src/en/vizshonenjump/build.gradle index 793c0613f..b53130ba7 100644 --- a/src/en/vizshonenjump/build.gradle +++ b/src/en/vizshonenjump/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'VIZ Shonen Jump' pkgNameSuffix = 'en.vizshonenjump' extClass = '.VizShonenJump' - extVersionCode = 16 + extVersionCode = 17 } dependencies { diff --git a/src/en/vizshonenjump/src/eu/kanade/tachiyomi/extension/en/vizshonenjump/VizImageInterceptor.kt b/src/en/vizshonenjump/src/eu/kanade/tachiyomi/extension/en/vizshonenjump/VizImageInterceptor.kt index 0a4697b9f..07b22530a 100644 --- a/src/en/vizshonenjump/src/eu/kanade/tachiyomi/extension/en/vizshonenjump/VizImageInterceptor.kt +++ b/src/en/vizshonenjump/src/eu/kanade/tachiyomi/extension/en/vizshonenjump/VizImageInterceptor.kt @@ -4,7 +4,7 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.Rect -import com.drew.imaging.jpeg.JpegMetadataReader +import com.drew.imaging.ImageMetadataReader import com.drew.metadata.exif.ExifSubIFDDirectory import eu.kanade.tachiyomi.network.GET import kotlinx.serialization.decodeFromString @@ -14,12 +14,12 @@ import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaType import okhttp3.Request import okhttp3.Response +import okhttp3.ResponseBody import okhttp3.ResponseBody.Companion.toResponseBody import uy.kohesive.injekt.injectLazy import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.IOException -import java.io.InputStream class VizImageInterceptor : Interceptor { @@ -35,12 +35,15 @@ class VizImageInterceptor : Interceptor { val imageUrl = imageUrlParse(response) val imageResponse = chain.proceed(imageRequest(imageUrl)) - val image = imageResponse.body.byteStream().decodeImage() - val body = image.toResponseBody(MEDIA_TYPE) + if (!imageResponse.isSuccessful) { + imageResponse.close() + throw IOException(FAILED_TO_FETCH_PAGE_URL) + } + + val imageBody = imageResponse.decodeImage() return imageResponse.newBuilder() - .body(body) - .header("Content-Type", MEDIA_TYPE.toString()) + .body(imageBody) .build() } @@ -60,17 +63,18 @@ class VizImageInterceptor : Interceptor { return GET(url, headers) } - private fun InputStream.decodeImage(): ByteArray { + private fun Response.decodeImage(): ResponseBody { // See: https://stackoverflow.com/a/5924132 // See: https://github.com/tachiyomiorg/tachiyomi-extensions/issues/2678#issuecomment-645857603 val byteOutputStream = ByteArrayOutputStream() - copyTo(byteOutputStream) + .apply { body.byteStream().copyTo(this) } + val contentType = headers["Content-Type"]?.toMediaType() val byteInputStreamForImage = ByteArrayInputStream(byteOutputStream.toByteArray()) val byteInputStreamForMetadata = ByteArrayInputStream(byteOutputStream.toByteArray()) - val imageData = byteInputStreamForMetadata.getImageData() - ?: return byteOutputStream.toByteArray() + val imageData = byteInputStreamForMetadata.getImageData().getOrNull() + ?: return byteOutputStream.toByteArray().toResponseBody(contentType) val input = BitmapFactory.decodeStream(byteInputStreamForImage) val width = input.width @@ -139,9 +143,10 @@ class VizImageInterceptor : Interceptor { ) } - val output = ByteArrayOutputStream() - result.compress(Bitmap.CompressFormat.JPEG, 95, output) - return output.toByteArray() + return ByteArrayOutputStream() + .apply { result.compress(Bitmap.CompressFormat.JPEG, 95, this) } + .toByteArray() + .toResponseBody(JPEG_MEDIA_TYPE) } private fun Canvas.drawImage( @@ -158,8 +163,13 @@ class VizImageInterceptor : Interceptor { drawBitmap(from, srcRect, dstRect, null) } - private fun ByteArrayInputStream.getImageData(): ImageData? { - val metadata = JpegMetadataReader.readMetadata(this) + private fun ByteArrayInputStream.getImageData(): Result = runCatching { + val metadata = ImageMetadataReader.readMetadata(this) + + val keyDir = metadata.directories + .firstOrNull { it.containsTag(ExifSubIFDDirectory.TAG_IMAGE_UNIQUE_ID) } + val metaUniqueId = keyDir?.getString(ExifSubIFDDirectory.TAG_IMAGE_UNIQUE_ID) + ?: return@runCatching null val sizeDir = metadata.directories.firstOrNull { it.containsTag(ExifSubIFDDirectory.TAG_IMAGE_WIDTH) && @@ -168,13 +178,7 @@ class VizImageInterceptor : Interceptor { val metaWidth = sizeDir?.getInt(ExifSubIFDDirectory.TAG_IMAGE_WIDTH) ?: COMMON_WIDTH val metaHeight = sizeDir?.getInt(ExifSubIFDDirectory.TAG_IMAGE_HEIGHT) ?: COMMON_HEIGHT - val keyDir = metadata.directories.firstOrNull { - it.containsTag(ExifSubIFDDirectory.TAG_IMAGE_UNIQUE_ID) - } - val metaUniqueId = keyDir?.getString(ExifSubIFDDirectory.TAG_IMAGE_UNIQUE_ID) - ?: return null - - return ImageData(metaWidth, metaHeight, metaUniqueId) + ImageData(metaWidth, metaHeight, metaUniqueId) } private data class ImageData(val width: Int, val height: Int, val uniqueId: String) { @@ -186,9 +190,9 @@ class VizImageInterceptor : Interceptor { companion object { private const val IMAGE_URL_ENDPOINT = "get_manga_url" - private val MEDIA_TYPE = "image/jpeg".toMediaType() + private val JPEG_MEDIA_TYPE = "image/jpeg".toMediaType() - private const val FAILED_TO_FETCH_PAGE_URL = "Something went wrong while trying to fetch page." + private const val FAILED_TO_FETCH_PAGE_URL = "Something went wrong while trying to fetch the page." private const val CELL_WIDTH_COUNT = 10 private const val CELL_HEIGHT_COUNT = 15