更新JPEG文件中的JFIF缩略图

1 投票
2 回答
1415 浏览
提问于 2025-04-18 05:48

我正在尝试用Python更新JPEG文件中的嵌入式JFIF缩略图。

这是一个(有点小技巧的)方法,应该可以实现这个目标:

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

这个函数在我重新写入旧的缩略图时工作得很好,也就是说缩略图的数据大小没有变化。然而,一旦我对它进行了一些处理(比如裁剪或旋转)并重新保存,生成的文件似乎就不再有效了。

为了更好地比较,我上传了一个原始图片和一个更新了缩略图的图片

我从例如identify得到的错误信息如下:

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

在对比这两张图片时,0x202大小标签中的值与嵌入缩略图数据的大小相匹配,文件的大小也相应增大了。

2 个回答

1

这是你图像文件的结构。注意在你的APP1标记后面还有一个SOI标记。

{ 图像开始 }

{ APP0标记 长度:16 版本:1.1 密度单位: (每英寸像素数) X方向密度:72 Y方向密度:72 缩略图宽度:0 缩略图高度:0 }

{ APP1标记 长度:7678 Exif }

{ 图像开始 }

{ 定义量化表 长度:67 表索引:0 表精度:0 表值: 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 }

{ 定义量化表 长度:67 表索引:1 表精度:0 表值: 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 }

{ 帧开始 类型:基线(霍夫曼) 长度:17 精度:8 高度:360 宽度:480 组件数量:3 组件 1 水平频率:2 垂直频率:2 量化表:0 组件 2 水平频率:1 垂直频率:1 量化表:1 组件 3 水平频率:1 垂直频率:1 量化表:1 }

{ 定义霍夫曼表 长度:28 表索引:0 表类别:DC 代码计数:0 1 5 1 1 1 0 0 0 0 0 0 0 0 0 0 代码值:3 1 2 4 5 6 0 7 8 }

{ 定义霍夫曼表 长度:65 表索引:0 表类别:AC 代码计数:0 2 1 3 2 4 4 4 4 4 5 3 3 4 3 0 代码值: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 }

{ 定义霍夫曼表 长度:26 表索引:1 表类别:DC 代码计数:0 3 1 1 1 1 0 0 0 0 0 0 0 0 0 0 代码值:0 1 2 3 4 5 6 }

{ 定义霍夫曼表 长度:45 表索引:1 表类别:AC 代码计数:0 2 2 1 4 1 4 2 2 2 1 5 0 0 0 0 代码值: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 }

{ 扫描开始 长度:12 组件ID:1 AC熵表:0 DC熵表:0 组件ID:2 AC熵表:1 DC熵表:1 组件ID:3 AC熵表:1 DC熵表:1 频谱选择开始:0 频谱选择结束:63 逐次逼近高:0 逐次逼近低:0 }

{ 图像结束 }

1

我刚找到答案:

问题是我在更新TIFF标签中的缩略图大小时,没有更新APP1的长度。一旦这个长度也更新了,图片就能正确加载了。

撰写回答