Question

I am trying to update the embedded JFIF thumbnail in a JPEG File using Python.

This is the (slightly hackish) method that is supposed to achieve this:

def set_thumbnail(self, data):
    # Data of the updated thumbnail
    data = bytearray(data)
    # Get offset of the old thumbnail data
    offset = (self._exif_start +
              self._unpack('I', self._get_tag_offset(0x201)+8))
    # Get size of the old thumbnail
    old_size = self._unpack('I', self._get_tag_offset(0x202)+8)
    try:
        # Strip everything between the JFIF APP1 and the quant table
        jfif_start = data.index('\xff\xe0')
        quant_start = data.index('\xff\xdb')
        stripped_data = data[0:jfif_start] + data[quant_start:]
    except ValueError:
        stripped_data = data
    # Writes the new length to the buffer
    self._pack('I', self._get_tag_offset(0x202)+8, len(stripped_data))
    # Writes the new data to the image buffer
    self._buf[offset:offset+old_size] = stripped_data

This function works fine when I re-write the old thumbnail, i.e. the size of the thumbnail data does not change. However, once I apply some transformation (e.g. crop or rotate) to it and store it again, the resulting file seems to be no longer valid.

I uploaded both an original image and one with an updated thumbnail for better comparison.

The error I get from e.g. identify is the following:

identify.im6: Invalid JPEG file structure: two SOI markers `/tmp/thumb_rotated.jpg' @ error/jpeg.c/JPEGErrorHandler/316.

On diffing the two images, the value in the 0x202 size tag matches the size of the embedded thumbnail data, and the file is also accordingly larger.

Was it helpful?

Solution 2

I just found the answer:

The problem was that while I updated the size of the thumbnail in the TIFF tag, I did not update the APP1 length. Once that was updated as well, the image loaded correctly.

OTHER TIPS

This is the structure of your image file. Notice there is a second SOI marker right after your APP1 marker.

{ Start Of Image }

{ APP0 Marker Length: 16 Version: 1.1 Density Unit: (pixels per inch) X Density: 72 Y Density: 72 Thumbnail Width: 0 Thumbnail Height: 0 }

{ APP1 Marker Length: 7678 Exif }

{ Start Of Image }

{ Define Quantization Table Length: 67 Table Index: 0 Table Precision: 0 Table Values: 8 6 6 7 6 5 8 7 7 7 9 9 8 10 12 20 13 12 11 11 12 25 18 19 15 20 29 26 31 30 29 26 28 28 32 36 46 39 32 34 44 35 28 28 40 55 41 44 48 49 52 52 52 31 39 57 61 56 50 60 46 51 52 50 }

{ Define Quantization Table Length: 67 Table Index: 1 Table Precision: 0 Table Values: 9 9 9 12 11 12 24 13 13 24 50 33 28 33 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 50 }

{ Start Of Frame Type: Baseline (Huffman) Length: 17 Precision: 8 Height: 360 Width: 480 Component Count: 3 Component 1 Horizontal Frequency: 2 Vertical Frequency: 2 Quantization Table: 0 Component 2 Horizontal Frequency: 1 Vertical Frequency: 1 Quantization Table: 1 Component 3 Horizontal Frequency: 1 Vertical Frequency: 1 Quantization Table: 1 }

{ Define Huffman Table Length: 28 Table Index 0 Table Class: DC Code Counts: 0 1 5 1 1 1 0 0 0 0 0 0 0 0 0 0 Code Values: 3 1 2 4 5 6 0 7 8 }

{ Define Huffman Table Length: 65 Table Index 0 Table Class: AC Code Counts: 0 2 1 3 2 4 4 4 4 4 5 3 3 4 3 0 Code Values: 1 2 3 0 4 11 12 21 5 31 41 51 13 22 61 71 6 32 81 91 14 42 a1 b1 23 52 c1 d1 7 15 33 62 e1 43 72 f0 24 92 f1 16 34 53 82 25 83 c2 }

{ Define Huffman Table Length: 26 Table Index 1 Table Class: DC Code Counts: 0 3 1 1 1 1 0 0 0 0 0 0 0 0 0 0 Code Values: 0 1 2 3 4 5 6 }

{ Define Huffman Table Length: 45 Table Index 1 Table Class: AC Code Counts: 0 2 2 1 4 1 4 2 2 2 1 5 0 0 0 0 Code Values: 0 1 2 11 3 4 12 21 31 41 13 22 51 61 32 71 5 14 23 91 f0 33 42 81 a1 b1 }

{ Start Of Scan Length: 12 Component ID: 1 AC Entropy Table: 0 DC Entropy Table: 0 Component ID: 2 AC Entropy Table: 1 DC Entropy Table: 1 Component ID: 3 AC Entropy Table: 1 DC Entropy Table: 1 Spectral Selection Start: 0 Spectral Selection End: 63 Sucessive Approximation High: 0 Sucessive Approximation Low: 0 }

{ End Of Image }

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top