Skip to content

Commit

Permalink
Allow JPEGs with padding at image end.
Browse files Browse the repository at this point in the history
Some JPEGs (e.g. Sony Alpha 6000) pad the end of the JPEG image with null bytes,
instead of the JPEG End-Of-Image marker 0xFFD9. Others apparently do the same
thing, but with 0xFF instead of 0x00.

Due to strict sanity checks, this lead to otherwise valid JPEGs returning
PARSE_EXIF_ERROR_NO_JPEG. This commit loosens the sanity check and handles
the case of 0x00/0xFF padding at the end of image, and fixes #9, fixes #7.
  • Loading branch information
Mayank Lahiri committed Nov 14, 2015
1 parent 6c5d9d9 commit 2315ffe
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 5 deletions.
25 changes: 20 additions & 5 deletions exif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,12 +414,27 @@ IFEntry parseIFEntry(const unsigned char *buf, const unsigned offs,
// Locates the EXIF segment and parses it using parseFromEXIFSegment
//
int easyexif::EXIFInfo::parseFrom(const unsigned char *buf, unsigned len) {
// Sanity check: all JPEG files start with 0xFFD8 and end with 0xFFD9
// This check also ensures that the user has supplied a correct value for len.
if (!buf || len < 4) return PARSE_EXIF_ERROR_NO_EXIF;
// Sanity check: all JPEG files start with 0xFFD8.
if (!buf || len < 4) return PARSE_EXIF_ERROR_NO_JPEG;
if (buf[0] != 0xFF || buf[1] != 0xD8) return PARSE_EXIF_ERROR_NO_JPEG;
if (buf[len - 2] != 0xFF || buf[len - 1] != 0xD9)
return PARSE_EXIF_ERROR_NO_JPEG;

// Sanity check: some cameras pad the JPEG image with null bytes at the end.
// Normally, we should able to find the JPEG end marker 0xFFD9 at the end
// of the image, but not always. As long as there are null/0xFF bytes at the
// end of the image buffer, keep decrementing len until an 0xFFD9 is found,
// or some other bytes are. If the first non-zero/0xFF bytes from the end are
// not 0xFFD9, then we can be reasonably sure that the buffer is not a JPEG.
while (len > 2) {
if (buf[len - 1] == 0 || buf[len - 1] == 0xFF) {
len--;
} else {
if (buf[len - 1] != 0xD9 || buf[len - 2] != 0xFF) {
return PARSE_EXIF_ERROR_NO_JPEG;

This comment has been minimized.

Copy link
@TheNicker

TheNicker Nov 26, 2016

There's no guarantee that 0xFFD9 EOI marker would be found as expected here.
Samsung add their own trailer 'Image_UTC_Data' and I'm not sure whether it's wise to handle and maintain a different use case for every manufacturer.
I commented this sanity check and I'm currently rely on 'PARSE_EXIF_ERROR_NO_EXIF' error code.

} else {
break;
}
}
}
clear();

// Scan for EXIF header (bytes 0xFF 0xE1) and do a sanity check by
Expand Down
Binary file added test-images/sony-alpha-6000.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions test-images/sony-alpha-6000.jpg.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
Camera make : SONY
Camera model : ILCE-6000
Software : ILCE-6000 v1.00
Bits per sample : 0
Image width : 6000
Image height : 4000
Image description :
Image orientation : 1
Image copyright :
Image date/time : 2014:04:18 20:33:53
Original date/time : 2014:04:18 20:33:53
Digitize date/time : 2014:04:18 20:33:53
Subsecond time :
Exposure time : 1/0 s
F-stop : f/8.0
ISO speed : 100
Subject distance : 0.000000 m
Exposure bias : 0.000000 EV
Flash used? : 1
Metering mode : 5
Lens focal length : 22.000000 mm
35mm focal length : 33 mm
GPS Latitude : 0.000000 deg (0.000000 deg, 0.000000 min, 0.000000 sec ?)
GPS Longitude : 0.000000 deg (0.000000 deg, 0.000000 min, 0.000000 sec ?)
GPS Altitude : 0.000000 m
Lens min focal length: 16.000000 mm
Lens max focal length: 50.000000 mm
Lens f-stop min : f/3.5
Lens f-stop max : f/5.6
Lens make :
Lens model : E PZ 16-50mm F3.5-5.6 OSS

0 comments on commit 2315ffe

Please sign in to comment.