mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-21 07:56:56 +08:00
Handle other cases in jpeg header (#1611)
* Handle other cases in jpeg header Co-authored-by: sandtechnology <a1294790523@hotmail.com> * Add unit tests Co-authored-by: Karlatemp <karlatemp@vip.qq.com>
This commit is contained in:
parent
d0171878ff
commit
3d502a496e
@ -18,20 +18,21 @@ import java.io.IOException
|
||||
//SOF0-SOF3 SOF5-SOF7 SOF9-SOF11 SOF13-SOF15 Segment
|
||||
// (0xC4, 0xC8 and 0xCC not included due to is not an SOF)
|
||||
private val JPG_SOF_RANGE = listOf(
|
||||
0xC0.toByte()..0xC3.toByte(),
|
||||
0xC5.toByte()..0xC7.toByte(),
|
||||
0xC9.toByte()..0xCB.toByte(),
|
||||
0xCD.toByte()..0xCF.toByte()
|
||||
0xC0..0xC3,
|
||||
0xC5..0xC7,
|
||||
0xC9..0xCB,
|
||||
0xCD..0xCF
|
||||
)
|
||||
|
||||
// https://docs.fileformat.com/image/jpeg/
|
||||
// http://www.vip.sugovica.hu/Sardi/kepnezo/JPEG%20File%20Layout%20and%20Format.htm
|
||||
private fun Input.getJPGImageInfo(): ImageInfo {
|
||||
require(readBytes(2).contentEquals(byteArrayOf(0xFF.toByte(), 0xD8.toByte()))) {
|
||||
"It's not a valid jpg file"
|
||||
}
|
||||
//0xFF Segment Start
|
||||
while (readByte() == 0xFF.toByte()) {
|
||||
val type = readByte()
|
||||
val type = readByte().toIntUnsigned()
|
||||
//Find SOF
|
||||
if (JPG_SOF_RANGE.any { it.contains(type) }) {
|
||||
//Length
|
||||
@ -42,15 +43,16 @@ private fun Input.getJPGImageInfo(): ImageInfo {
|
||||
val width = readShort().toInt()
|
||||
return ImageInfo(width = width, height = height, imageType = ImageType.JPG)
|
||||
} else {
|
||||
//SOS Segment, header is ended
|
||||
if (type == 0xDA.toByte()) {
|
||||
break
|
||||
when (type) {
|
||||
//SOS Segment, header is ended
|
||||
0xDA -> break
|
||||
//0x00 (Byte alignment) and 0x01 (TEM)
|
||||
in 0x00..0x01 -> continue
|
||||
//RST[0-7] no length and content, skip
|
||||
in 0xD0..0xD7 -> continue
|
||||
//Normal segment, Skipped size=Segment Length - 2 (Length data itself)
|
||||
else -> discardExact(readShort().toIntUnsigned() - 2)
|
||||
}
|
||||
//Other segment, skip
|
||||
discardExact(
|
||||
//Skip size=segment length - 2 (length data itself)
|
||||
readShort().toIntUnsigned() - 2
|
||||
)
|
||||
}
|
||||
}
|
||||
throw IllegalArgumentException("It's not a valid jpg file, failed to find an SOF segment")
|
||||
|
@ -15,6 +15,7 @@ import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
|
||||
import net.mamoe.mirai.utils.hexToBytes
|
||||
import net.mamoe.mirai.utils.withUse
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
@ -52,6 +53,23 @@ internal class ImageReadingTest : AbstractTest() {
|
||||
"FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 78 00 78 00 00 FF E1 00 5A 45 78 69 66 00 00 4D 4D 00 2A 00 00 00 08 00 05 03 01 00 05 00 00 00 01 00 00 00 4A 03 03 00 01 00 00 00 01 00 00 00 00 51 10 00 01 00 00 00 01 01 00 00 00 51 11 00 04 00 00 00 01 00 00 12 74 51 12 00 04 00 00 00 01 00 00 12 74 00 00 00 00 00 01 86 A0 00 00 B1 8F FF DB 00 43 00 02 01 01 02 01 01 02 02 02 02 02 02 02 02 03 05 03 03 03 03 03 06 04 04 03 05 07 06 07 07 07 06 07 07 08 09 0B 09 08 08 0A 08 07 07 0A 0D 0A 0A 0B 0C 0C 0C 0C 07 09 0E 0F 0D 0C 0E 0B 0C 0C 0C FF DB 00 43 01 02 02 02 03 03 03 06 03 03 06 0C 08 07 08 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C FF C2 00 11 08 01 90 01 E0 03 01 22 00 02 11 01 03 11 01 FF DA".testMatch(
|
||||
ImageType.JPG
|
||||
)
|
||||
//FF 01
|
||||
"FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 78 00 78 00 00 FF 01 FF E1 00 5A 45 78 69 66 00 00 4D 4D 00 2A 00 00 00 08 00 05 03 01 00 05 00 00 00 01 00 00 00 4A 03 03 00 01 00 00 00 01 00 00 00 00 51 10 00 01 00 00 00 01 01 00 00 00 51 11 00 04 00 00 00 01 00 00 12 74 51 12 00 04 00 00 00 01 00 00 12 74 00 00 00 00 00 01 86 A0 00 00 B1 8F FF DB 00 43 00 02 01 01 02 01 01 02 02 02 02 02 02 02 02 03 05 03 03 03 03 03 06 04 04 03 05 07 06 07 07 07 06 07 07 08 09 0B 09 08 08 0A 08 07 07 0A 0D 0A 0A 0B 0C 0C 0C 0C 07 09 0E 0F 0D 0C 0E 0B 0C 0C 0C FF DB 00 43 01 02 02 02 03 03 03 06 03 03 06 0C 08 07 08 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C FF C2 00 11 08 01 90 01 E0 03 01 22 00 02 11 01 03 11 01 FF DA".testMatch(
|
||||
ImageType.JPG
|
||||
)
|
||||
//FF 00
|
||||
"FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 78 00 78 00 00 FF 00 FF E1 00 5A 45 78 69 66 00 00 4D 4D 00 2A 00 00 00 08 00 05 03 01 00 05 00 00 00 01 00 00 00 4A 03 03 00 01 00 00 00 01 00 00 00 00 51 10 00 01 00 00 00 01 01 00 00 00 51 11 00 04 00 00 00 01 00 00 12 74 51 12 00 04 00 00 00 01 00 00 12 74 00 00 00 00 00 01 86 A0 00 00 B1 8F FF DB 00 43 00 02 01 01 02 01 01 02 02 02 02 02 02 02 02 03 05 03 03 03 03 03 06 04 04 03 05 07 06 07 07 07 06 07 07 08 09 0B 09 08 08 0A 08 07 07 0A 0D 0A 0A 0B 0C 0C 0C 0C 07 09 0E 0F 0D 0C 0E 0B 0C 0C 0C FF DB 00 43 01 02 02 02 03 03 03 06 03 03 06 0C 08 07 08 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C FF C2 00 11 08 01 90 01 E0 03 01 22 00 02 11 01 03 11 01 FF DA".testMatch(
|
||||
ImageType.JPG
|
||||
)
|
||||
//RST[0-7]
|
||||
"FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 78 00 78 00 00 FF D0 FF D1 FF D2 FF D3 FF D4 FF D5 FF D6 FF D7 FF E1 00 5A 45 78 69 66 00 00 4D 4D 00 2A 00 00 00 08 00 05 03 01 00 05 00 00 00 01 00 00 00 4A 03 03 00 01 00 00 00 01 00 00 00 00 51 10 00 01 00 00 00 01 01 00 00 00 51 11 00 04 00 00 00 01 00 00 12 74 51 12 00 04 00 00 00 01 00 00 12 74 00 00 00 00 00 01 86 A0 00 00 B1 8F FF DB 00 43 00 02 01 01 02 01 01 02 02 02 02 02 02 02 02 03 05 03 03 03 03 03 06 04 04 03 05 07 06 07 07 07 06 07 07 08 09 0B 09 08 08 0A 08 07 07 0A 0D 0A 0A 0B 0C 0C 0C 0C 07 09 0E 0F 0D 0C 0E 0B 0C 0C 0C FF DB 00 43 01 02 02 02 03 03 03 06 03 03 06 0C 08 07 08 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C FF C2 00 11 08 01 90 01 E0 03 01 22 00 02 11 01 03 11 01 FF DA".testMatch(
|
||||
ImageType.JPG
|
||||
)
|
||||
println("Current path: "+File(".").absolutePath)
|
||||
//Issue 1610
|
||||
File("./src/commonTest/resources/image/jpeg-header-issue-1610.bin").readBytes().testRead(
|
||||
ImageType.JPG
|
||||
)
|
||||
//Failed to find
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
"FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 78 00 78 00 00 FF E1 00 5A 45 78 69 66 00 00 4D 4D 00 2A 00 00 00 08 00 05 03 01 00 05 00 00 00 01 00 00 00 4A 03 03 00 01 00 00 00 01 00 00 00 00 51 10 00 01 00 00 00 01 01 00 00 00 51 11 00 04 00 00 00 01 00 00 12 74 51 12 00 04 00 00 00 01 00 00 12 74 00 00 00 00 00 01 86 A0 00 00 B1 8F FF DB 00 43 00 02 01 01 02 01 01 02 02 02 02 02 02 02 02 03 05 03 03 03 03 03 06 04 04 03 05 07 06 07 07 07 06 07 07 08 09 0B 09 08 08 0A 08 07 07 0A 0D 0A 0A 0B 0C 0C 0C 0C 07 09 0E 0F 0D 0C 0E 0B 0C 0C 0C FF DB 00 43 01 02 02 02 03 03 03 06 03 03 06 0C 08 07 08 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C 0C FF DA".testMatch(
|
||||
@ -83,6 +101,13 @@ internal class ImageReadingTest : AbstractTest() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun ByteArray.testRead(type: ImageType) {
|
||||
this.toExternalResource().withUse {
|
||||
calculateImageInfo().run {
|
||||
assertEquals(type, imageType, "imageType")
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun String.testMatch(type: ImageType) {
|
||||
this.hexToBytes().toExternalResource().withUse {
|
||||
calculateImageInfo().run {
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 153 KiB |
Loading…
Reference in New Issue
Block a user