mirror of
https://github.com/Suwayomi/Tachidesk.git
synced 2025-12-09 22:32:06 +01:00
Support more image types (#700)
This commit is contained in:
5
.gitattributes
vendored
5
.gitattributes
vendored
@@ -25,4 +25,7 @@
|
||||
*.pyc binary
|
||||
*.swp binary
|
||||
*.pdf binary
|
||||
*.exe binary
|
||||
*.exe binary
|
||||
*.avif binary
|
||||
*.heif binary
|
||||
*.jxl binary
|
||||
@@ -7,8 +7,11 @@ package suwayomi.tachidesk.manga.impl.util.storage
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil.ImageType.AVIF
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil.ImageType.GIF
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil.ImageType.JPG
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil.ImageType.HEIF
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil.ImageType.JPEG
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil.ImageType.JXL
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil.ImageType.PNG
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil.ImageType.WEBP
|
||||
import java.io.InputStream
|
||||
@@ -31,7 +34,7 @@ object ImageUtil {
|
||||
|
||||
fun findImageType(stream: InputStream): ImageType? {
|
||||
try {
|
||||
val bytes = ByteArray(8)
|
||||
val bytes = ByteArray(12)
|
||||
|
||||
val length = if (stream.markSupported()) {
|
||||
stream.mark(bytes.size)
|
||||
@@ -45,7 +48,7 @@ object ImageUtil {
|
||||
}
|
||||
|
||||
if (bytes.compareWith(charByteArrayOf(0xFF, 0xD8, 0xFF))) {
|
||||
return JPG
|
||||
return JPEG
|
||||
}
|
||||
if (bytes.compareWith(charByteArrayOf(0x89, 0x50, 0x4E, 0x47))) {
|
||||
return PNG
|
||||
@@ -56,11 +59,88 @@ object ImageUtil {
|
||||
if (bytes.compareWith("RIFF".toByteArray())) {
|
||||
return WEBP
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (bytes.copyOfRange(4, 12).compareWith("ftypavif".toByteArray())) {
|
||||
return AVIF
|
||||
}
|
||||
if (isHEIF(bytes)) {
|
||||
return HEIF
|
||||
}
|
||||
if (bytes.compareWith(charByteArrayOf(0xFF, 0x0A))) {
|
||||
return JXL
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun isHEIF(bytes: ByteArray): Boolean {
|
||||
// ftypheic
|
||||
if (bytes[4] == 0x66.toByte() &&
|
||||
bytes[5] == 0x74.toByte() &&
|
||||
bytes[6] == 0x79.toByte() &&
|
||||
bytes[7] == 0x70.toByte() &&
|
||||
bytes[8] == 0x68.toByte() &&
|
||||
bytes[9] == 0x65.toByte() &&
|
||||
bytes[10] == 0x69.toByte() &&
|
||||
bytes[11] == 0x63.toByte()
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
// ftypmif1
|
||||
if (bytes[4] == 0x66.toByte() &&
|
||||
bytes[5] == 0x74.toByte() &&
|
||||
bytes[6] == 0x79.toByte() &&
|
||||
bytes[7] == 0x70.toByte() &&
|
||||
bytes[8] == 0x6D.toByte() &&
|
||||
bytes[9] == 0x69.toByte() &&
|
||||
bytes[10] == 0x66.toByte() &&
|
||||
bytes[11] == 0x31.toByte()
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
// ftypmsf1
|
||||
if (bytes[4] == 0x66.toByte() &&
|
||||
bytes[5] == 0x74.toByte() &&
|
||||
bytes[6] == 0x79.toByte() &&
|
||||
bytes[7] == 0x70.toByte() &&
|
||||
bytes[8] == 0x6D.toByte() &&
|
||||
bytes[9] == 0x73.toByte() &&
|
||||
bytes[10] == 0x66.toByte() &&
|
||||
bytes[11] == 0x31.toByte()
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
// ftypheis
|
||||
if (bytes[4] == 0x66.toByte() &&
|
||||
bytes[5] == 0x74.toByte() &&
|
||||
bytes[6] == 0x79.toByte() &&
|
||||
bytes[7] == 0x70.toByte() &&
|
||||
bytes[8] == 0x68.toByte() &&
|
||||
bytes[9] == 0x65.toByte() &&
|
||||
bytes[10] == 0x69.toByte() &&
|
||||
bytes[11] == 0x73.toByte()
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
// ftyphevc
|
||||
if (bytes[4] == 0x66.toByte() &&
|
||||
bytes[5] == 0x74.toByte() &&
|
||||
bytes[6] == 0x79.toByte() &&
|
||||
bytes[7] == 0x70.toByte() &&
|
||||
bytes[8] == 0x68.toByte() &&
|
||||
bytes[9] == 0x65.toByte() &&
|
||||
bytes[10] == 0x76.toByte() &&
|
||||
bytes[11] == 0x63.toByte()
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun ByteArray.compareWith(magic: ByteArray): Boolean {
|
||||
return magic.indices.none { this[it] != magic[it] }
|
||||
}
|
||||
@@ -73,10 +153,13 @@ object ImageUtil {
|
||||
}
|
||||
}
|
||||
|
||||
enum class ImageType(val mime: String) {
|
||||
JPG("image/jpeg"),
|
||||
PNG("image/png"),
|
||||
GIF("image/gif"),
|
||||
WEBP("image/webp")
|
||||
enum class ImageType(val mime: String, val extension: String) {
|
||||
AVIF("image/avif", "avif"),
|
||||
GIF("image/gif", "gif"),
|
||||
HEIF("image/heif", "heif"),
|
||||
JPEG("image/jpeg", "jpg"),
|
||||
JXL("image/jxl", "jxl"),
|
||||
PNG("image/png", "png"),
|
||||
WEBP("image/webp", "webp")
|
||||
}
|
||||
}
|
||||
|
||||
25
server/src/test/kotlin/suwayomi/tachidesk/ImageUtilTest.kt
Normal file
25
server/src/test/kotlin/suwayomi/tachidesk/ImageUtilTest.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
package suwayomi.tachidesk
|
||||
|
||||
import suwayomi.tachidesk.manga.impl.util.storage.ImageUtil
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ImageUtilTest {
|
||||
@Test
|
||||
fun jxlTest() {
|
||||
val type = ImageUtil.findImageType(this::class.java.classLoader.getResourceAsStream("dice.jxl")!!)
|
||||
assertEquals(ImageUtil.ImageType.JXL, type)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun avifTest() {
|
||||
val type = ImageUtil.findImageType(this::class.java.classLoader.getResourceAsStream("fox.profile0.8bpc.yuv420.avif")!!)
|
||||
assertEquals(ImageUtil.ImageType.AVIF, type)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun heifTest() {
|
||||
val type = ImageUtil.findImageType(this::class.java.classLoader.getResourceAsStream("sample1.heif")!!)
|
||||
assertEquals(ImageUtil.ImageType.HEIF, type)
|
||||
}
|
||||
}
|
||||
BIN
server/src/test/resources/dice.jxl
Normal file
BIN
server/src/test/resources/dice.jxl
Normal file
Binary file not shown.
BIN
server/src/test/resources/fox.profile0.8bpc.yuv420.avif
Normal file
BIN
server/src/test/resources/fox.profile0.8bpc.yuv420.avif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
BIN
server/src/test/resources/sample1.heif
Normal file
BIN
server/src/test/resources/sample1.heif
Normal file
Binary file not shown.
Reference in New Issue
Block a user