我想从jpegs中提取缩略图,而不需要任何外部库。我的意思是这并不太难,因为我需要知道缩略图的起始位置,并在文件中结束,然后简单地剪切它。我研究了许多文档(即:http://www.media.mit.edu/pia/Research/deepview/exif.html),并尝试分析jpeg,但并非一切都清楚。我试图逐步跟踪字节,但在深度我困惑。是否有任何好的文档或可读的源代码来提取有关jpeg文件中缩略图开始和结束位置的信息?
谢谢!
答案 0 :(得分:15)
对于手机或数码相机创建的大多数JPEG图像,缩略图图像(如果存在)存储在APP1标记(FFE1)中。在此标记段内是一个TIFF文件,其中包含主图像的EXIF信息和存储为JPEG压缩图像的可选缩略图图像。 TIFF文件通常包含两个“页面”,其中第一页是EXIF信息,第二页是以“旧”TIFF类型6格式存储的缩略图。类型6格式是指JPEG文件只是按原样存储在TIFF包装器中。如果您希望使用最简单的代码将缩略图提取为JFIF,则需要执行以下步骤:
答案 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,因此图像不包含缩略图。