从jpeg文件中提取缩略图

时间:2012-04-27 11:15:50

标签: jpeg extract exif

我想从jpegs中提取缩略图,而不需要任何外部库。我的意思是这并不太难,因为我需要知道缩略图的起始位置,并在文件中结束,然后简单地剪切它。我研究了许多文档(即:http://www.media.mit.edu/pia/Research/deepview/exif.html),并尝试分析jpeg,但并非一切都清楚。我试图逐步跟踪字节,但在深度我困惑。是否有任何好的文档或可读的源代码来提取有关jpeg文件中缩略图开始和结束位置的信息?

谢谢!

4 个答案:

答案 0 :(得分:15)

对于手机或数码相机创建的大多数JPEG图像,缩略图图像(如果存在)存储在APP1标记(FFE1)中。在此标记段内是一个TIFF文件,其中包含主图像的EXIF信息和存储为JPEG压缩图像的可选缩略图图像。 TIFF文件通常包含两个“页面”,其中第一页是EXIF信息,第二页是以“旧”TIFF类型6格式存储的缩略图。类型6格式是指JPEG文件只是按原样存储在TIFF包装器中。如果您希望使用最简单的代码将缩略图提取为JFIF,则需要执行以下步骤:

  1. 熟悉JFIF和TIFF标记/标记。 JFIF标记由两个字节组成:0xFF后跟标记类型(APP1为0xE1)。这两个字节后跟以big-endian顺序存储的双字节长度。有关TIFF文件,请参阅Adobe TIFF 6.0参考。
  2. 在JPEG文件中搜索APP1(FFE1)EXIF标记。可能有多个APP1标记,APP1之前可能有多个标记。
  3. 您要查找的APP1标记在长度字段后面紧跟着字母“EXIF”。
  4. 查找“II”或“MM”(距离长度6个字节)以指示TIFF文件中使用的字节序。 II = Intel = little endian,MM = Motorola = big endian。
  5. 浏览第一页的标签,找到存储图像的第二个IFD。在第二个“页面”中,查找指向JPEG数据的两个TIFF标记。标签0x201具有JPEG数据的偏移量(相对于II / MM),标签0x202具有字节长度。

答案 1 :(得分:14)

Exiftool能够快速轻松地完成这项任务:

exiftool -b -ThumbnailImage my_image.jpg > my_thumbnail.jpg

答案 2 :(得分:3)

这个问题有一个更简单的解决方案,但我不知道它有多可靠:从第三个字节开始读取JPEG文件并搜索FFD8(JPEG图像标记的开始),然后搜索FFD9(结束) JPEG图像标记)。提取它,瞧,这是你的缩略图。

一个简单的JavaScript实现:

function getThumbnail(file, callback) {
    if (file.type == "image/jpeg") {
        var reader = new FileReader();
        reader.onload = function (e) {
            var array = new Uint8Array(e.target.result),
                start, end;
            for (var i = 2; i < array.length; i++) {
                if (array[i] == 0xFF) {
                    if (!start) {
                        if (array[i + 1] == 0xD8) {
                            start = i;
                        }
                    } else {
                        if (array[i + 1] == 0xD9) {
                            end = i;
                            break;
                        }
                    }
                }
            }
            if (start && end) {
                callback(new Blob([array.subarray(start, end)], {type:"image/jpeg"}));
            } else {
                // TODO scale with canvas
            }
        }
        reader.readAsArrayBuffer(file.slice(0, 50000));
    } else if (file.type.indexOf("image/") === 0) {
        // TODO scale with canvas
    }
}

答案 3 :(得分:-1)

位于http://en.wikipedia.org/wiki/JPEG_File_Interchange_Format的JFIF上的维基百科页面提供了JPEG标题的良好描述(标题包含缩略图作为未压缩的光栅图像)。这应该可以让您了解布局以及提取信息所需的代码。

图像标题的Hexdump(小端显示):

sdk@AndroidDev:~$ head -c 48 stfu.jpg |hexdump
0000000 d8ff e0ff 1000 464a 4649 0100 0101 4800
0000010 4800 0000 e1ff 1600 7845 6669 0000 4d4d
0000020 2a00 0000 0800 0000 0000 0000 feff 1700

Image Magic(字节1,0),App0段标题Magic(字节3,2),标题长度(5,4)标题类型签名(“JFIF \ 0”||“JFXX \ 0”)(字节6 -10),版本(字节11,12)密度单位(字节13),X密度(字节15,14),Y密度(字节17,16),缩略图宽度(字节19),缩略图高度(字节18),最后休息到“标题长度”是缩略图数据。

从上面的例子中,你可以看到标题长度是16个字节(字节6,5),版本是01.01(字节12,13)。此外,由于缩略图宽度和缩略图高度均为0x00,因此图像不包含缩略图。