Skip to content

Commit 0496c60

Browse files
FooIbarcuong-tran
authored andcommitted
Fix some issues when reading/saving images
(mihonapp/mihon#993) * Fix unsupported mime type error when saving images Avoid using platform mime type map to get extensions as it may not have all mime types we support. * Fix jxl images downloading/reading (cherry picked from commit daa47e0)
1 parent b127357 commit 0496c60

File tree

4 files changed

+23
-34
lines changed

4 files changed

+23
-34
lines changed

app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import logcat.LogPriority
2121
import tachiyomi.core.common.i18n.stringResource
2222
import tachiyomi.core.common.storage.extension
2323
import tachiyomi.core.common.util.lang.launchIO
24+
import tachiyomi.core.common.util.system.ImageUtil
2425
import tachiyomi.core.common.util.system.logcat
2526
import tachiyomi.domain.category.interactor.GetCategories
2627
import tachiyomi.domain.chapter.model.Chapter
@@ -170,7 +171,7 @@ class DownloadManager(
170171
source,
171172
)
172173
val files = chapterDir?.listFiles().orEmpty()
173-
.filter { "image" in it.type.orEmpty() }
174+
.filter { it.isFile && ImageUtil.isImage(it.name) { it.openInputStream() } }
174175

175176
if (files.isEmpty()) {
176177
throw Exception(context.stringResource(MR.strings.page_list_empty_error))

app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -553,14 +553,8 @@ class Downloader(
553553
* @param file the file where the image is already downloaded.
554554
*/
555555
private fun getImageExtension(response: Response, file: UniFile): String {
556-
// Read content type if available.
557556
val mime = response.body.contentType()?.run { if (type == "image") "image/$subtype" else null }
558-
// Else guess from the uri.
559-
?: context.contentResolver.getType(file.uri)
560-
// Else read magic numbers.
561-
?: ImageUtil.findImageType { file.openInputStream() }?.mime
562-
563-
return ImageUtil.getExtensionFromMimeType(mime)
557+
return ImageUtil.getExtensionFromMimeType(mime) { file.openInputStream() }
564558
}
565559

566560
private fun splitTallImageIfNeeded(page: Page, tmpDir: UniFile) {
@@ -758,7 +752,7 @@ class Downloader(
758752
download.status = Download.State.NOT_DOWNLOADED
759753
}
760754
}
761-
queue - downloads
755+
queue - downloads.toSet()
762756
}
763757
}
764758

app/src/main/java/eu/kanade/tachiyomi/data/saver/ImageSaver.kt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.net.Uri
77
import android.os.Build
88
import android.os.Environment
99
import android.provider.MediaStore
10+
import android.webkit.MimeTypeMap
1011
import androidx.annotation.RequiresApi
1112
import androidx.core.content.contentValuesOf
1213
import androidx.core.net.toUri
@@ -65,21 +66,26 @@ class ImageSaver(
6566
filename: String,
6667
data: () -> InputStream,
6768
): Uri {
68-
val pictureDir =
69+
val isMimeTypeSupported = MimeTypeMap.getSingleton().hasMimeType(type.mime)
70+
71+
val pictureDir = if (isMimeTypeSupported) {
6972
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
73+
} else {
74+
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
75+
}
7076

7177
val imageLocation = (image.location as Location.Pictures).relativePath
7278
val relativePath = listOf(
73-
Environment.DIRECTORY_PICTURES,
79+
if (isMimeTypeSupported) Environment.DIRECTORY_PICTURES else Environment.DIRECTORY_DOCUMENTS,
7480
context.stringResource(MR.strings.app_name),
7581
imageLocation,
7682
).joinToString(File.separator)
7783

7884
val contentValues = contentValuesOf(
79-
MediaStore.Images.Media.RELATIVE_PATH to relativePath,
80-
MediaStore.Images.Media.DISPLAY_NAME to image.name,
81-
MediaStore.Images.Media.MIME_TYPE to type.mime,
82-
MediaStore.Images.Media.DATE_MODIFIED to Instant.now().epochSecond,
85+
MediaStore.MediaColumns.RELATIVE_PATH to relativePath,
86+
MediaStore.MediaColumns.DISPLAY_NAME to if (isMimeTypeSupported) image.name else filename,
87+
MediaStore.MediaColumns.MIME_TYPE to type.mime,
88+
MediaStore.MediaColumns.DATE_MODIFIED to Instant.now().epochSecond,
8389
)
8490

8591
val picture = findUriOrDefault(relativePath, filename) {

core/common/src/main/kotlin/tachiyomi/core/common/util/system/ImageUtil.kt

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import android.graphics.drawable.ColorDrawable
1414
import android.graphics.drawable.Drawable
1515
import android.graphics.drawable.GradientDrawable
1616
import android.os.Build
17-
import android.webkit.MimeTypeMap
1817
import androidx.annotation.ColorInt
1918
import androidx.core.graphics.alpha
2019
import androidx.core.graphics.applyCanvas
@@ -32,7 +31,6 @@ import tachiyomi.decoder.Format
3231
import tachiyomi.decoder.ImageDecoder
3332
import java.io.File
3433
import java.io.InputStream
35-
import java.net.URLConnection
3634
import java.security.SecureRandom
3735
import java.util.Locale
3836
import kotlin.math.abs
@@ -47,12 +45,8 @@ object ImageUtil {
4745
if (File(name).extension.equals("cbi", ignoreCase = true)) return true
4846
// SY <--
4947

50-
val contentType = try {
51-
URLConnection.guessContentTypeFromName(name)
52-
} catch (e: Exception) {
53-
null
54-
} ?: openStream?.let { findImageType(it)?.mime }
55-
return contentType?.startsWith("image/") ?: false
48+
val extension = name.substringAfterLast('.')
49+
return ImageType.entries.any { it.extension == extension } || openStream?.let { findImageType(it) } != null
5650
}
5751

5852
fun findImageType(openStream: () -> InputStream): ImageType? {
@@ -76,10 +70,9 @@ object ImageUtil {
7670
}
7771
}
7872

79-
fun getExtensionFromMimeType(mime: String?): String {
80-
return MimeTypeMap.getSingleton().getExtensionFromMimeType(mime)
81-
?: SUPPLEMENTARY_MIMETYPE_MAPPING[mime]
82-
?: "jpg"
73+
fun getExtensionFromMimeType(mime: String?, openStream: () -> InputStream): String {
74+
val type = mime?.let { ImageType.entries.find { it.mime == mime } } ?: findImageType(openStream)
75+
return type?.extension ?: "jpg"
8376
}
8477

8578
fun isAnimatedAndSupported(source: BufferedSource): Boolean {
@@ -217,7 +210,6 @@ object ImageUtil {
217210
* new image with added center padding scaled relative to the height of the display view
218211
* to compensate for scaling.
219212
*/
220-
221213
fun addHorizontalCenterMargin(imageSource: BufferedSource, viewHeight: Int, backgroundContext: Context): BufferedSource {
222214
val imageBitmap = ImageDecoder.newInstance(imageSource.inputStream())?.decode()!!
223215
val height = imageBitmap.height
@@ -623,12 +615,7 @@ object ImageUtil {
623615

624616
private val optimalImageHeight = getDisplayMaxHeightInPx * 2
625617

626-
// Android doesn't include some mappings
627-
private val SUPPLEMENTARY_MIMETYPE_MAPPING = mapOf(
628-
// https://issuetracker.google.com/issues/182703810
629-
"image/jxl" to "jxl",
630-
)
631-
618+
// SY -->
632619
fun mergeBitmaps(
633620
imageBitmap: Bitmap,
634621
imageBitmap2: Bitmap,
@@ -674,6 +661,7 @@ object ImageUtil {
674661

675662
private val Bitmap.rect: Rect
676663
get() = Rect(0, 0, width, height)
664+
// SY <--
677665
}
678666

679667
val getDisplayMaxHeightInPx: Int

0 commit comments

Comments
 (0)