Append EOI marker to progressive image binary to reduce decoding failures
Currently there are intermittent errors when decoding progressive jpegs on iOS:
makeImagePlus:3744: *** ERROR: 'JPEG'-_reader->initImage[0] failed err=-50
createImageAtIndex:2093: *** ERROR: createImageAtIndex[0] - 'JPEG' - failed to create image [-59]
CGImageSourceCreateImageAtIndex:5107: *** ERROR: CGImageSourceCreateImageAtIndex[0] - 'JPEG' - failed to create image [-59]
makeImagePlus:3744: *** ERROR: 'JPEG'-_reader->initImage[0] failed err=-50
I looked at the data being sent to UIImage(data: data, scale: scale) and looks like it's correctly formatted and not malformed, it's just missing the EOI (end-of-image) marker which seems to be tripping up the UIImage decoder.
I was able to validate that the data works correctly if you add [0xFF, 0xD9] at the end of the binary and outputs a functional Jpeg. Interestingly this seems to only happen intermittently, so I'm not sure if UIImage has some fallbacks if EOI is missing but only fails in certain cases.
Nevertheless, here's what fixed it for me:
diff --git a/Sources/Nuke/Decoding/ImageDecoders+Default.swift b/Sources/Nuke/Decoding/ImageDecoders+Default.swift
index 5d6d8ace..ba126104 100644
--- a/Sources/Nuke/Decoding/ImageDecoders+Default.swift
+++ b/Sources/Nuke/Decoding/ImageDecoders+Default.swift
@@ -92,7 +92,12 @@ extension ImageDecoders {
guard let endOfScan = scanner.scan(data), endOfScan > 0 else {
return nil
}
- guard let image = ImageDecoders.Default._decode(data[0...endOfScan], scale: scale) else {
+ // To decode data correctly, binary needs to end with an EOI (End Of Image) marker (0xFFD9)
+ var imageData = data[0...endOfScan]
+ if data[endOfScan - 1] != 0xFF || data[endOfScan] != 0xD9 {
+ imageData += [0xFF, 0xD9]
+ }
+ guard let image = ImageDecoders.Default._decode(imageData, scale: scale) else {
return nil
}
Hey, great finding. Would you mind opening a quick PR with a fix?
Yessir! https://github.com/kean/Nuke/pull/835