exv*_*nce 8 bash wget imagemagick
我试图在 bash 中找出一种非常快速的方法来确定图像尺寸。
我知道我可以 wget 图像,然后使用 imagemagick 来确定图像的高度和宽度。我担心这可能不是最快的方法。
当我只需要非常小的功能子集时,我还担心必须安装 imagemagick。我在一个资源(CPU、RAM、存储)非常有限的嵌入式系统上。
有任何想法吗?
gol*_*cks 13
正如您所注意到的,您不需要整个ImageMagick包。你只需要identify
.
您还需要可执行链接到的库(以及这些库链接到的库)。
> whereis identify
identify: /bin/identify /usr/bin/identify /usr/share/man/man1/identify.1.gz
> ldd /bin/identify
Run Code Online (Sandbox Code Playgroud)
ldd
将显示一个列表。当我这样做时,它包含一些 X 库、libjpeg 等,以及来自 ImageMagick 包的两个库,libMagickCore
以及libMagickWand
. 那些看起来与同一堆东西相关联,所以如果你有的话,identify
应该可以工作。
您不必下载整个图像来获取尺寸,因为它们位于文件开头的标题中,这就是identify
外观。例如,这里我将完整 jpeg 中的前 4 kB 复制到一个新文件中:
dd if=real.jpg of=test.jpg bs=1024 count=4
Run Code Online (Sandbox Code Playgroud)
4 kB 应该足以包含标题——我相信你可以用 1/4 的量来完成。现在:
>identify test.jpg
test.jpg JPEG 893x558 893x558+0+0 8-bit DirectClass 4.1KB 0.000u 0:00.000
Run Code Online (Sandbox Code Playgroud)
这些是 的正确尺寸real.jpg
。但是请注意,大小 (4.1KB) 是截断文件的大小,因为该信息不是来自图像标题。
所以:你只需要下载每个图像的前千字节左右。
Run*_*ium 12
您可以使用curl
下载图像的一部分。这一切都取决于它必须有多坚固。测试用例可能是前 500 个字节。似乎适用于很多png
和jpg
,然后使用identify
等检查大小。
curl -o 500-peek -r0-500 "http://example.net/some-image.png"
Run Code Online (Sandbox Code Playgroud)
编辑:
很久没有写图像解析器了,但我想了想,刷新了我的一些记忆。
我怀疑这是您想要检查的所有类型的图像(但话说回来,也许不是)。我将描述一些更常见的:PNG
, JPEG
(JFIF)和GIF
.
PNG:
在提取大小时,这些很简单。甲png
头存储所述前24个字节内的大小。首先是一个固定的标题:
byte value description
0 0x89 Bit-check. 0x89 has bit 7 set.
1-3 PNG The letters P,N and G
4-5 \r\n Newline check.
6 ^z MS-DOS won't print data beyond this using `print`
7 \n *nix newline.
Run Code Online (Sandbox Code Playgroud)
接下来是文件中的块。它们由长度、类型和校验和的固定字段组成。另外一个可选的长度大小的数据部分。
幸运的是,第一个块总是IHDR
具有以下布局:
byte description
0-3 Image Width
4-7 Image Height
8 Bits per sample or per palette index
... ...
Run Code Online (Sandbox Code Playgroud)
通过这个我们有大小是字节 16-20 和 21-24。您可以通过例如 hexdump 转储数据:
hexdump -vn29 -e '"Bit-test: " /1 "%02x" "\n" "Magic : " 3/1 "%_c" "\n" "DOS-EOL : " 2/1 "%02x" "\n" "DOS-EOF : " /1 "%02x" "\n" "NIX-EOL : " /1 "%02x" "\n" "Chunk Size: " 4/1 "%02u" "\n" "Chunk-type: " 4/1 "%_c" "\n" "Img-Width : " 4/1 "%02x" "\n" "Img-Height: " 4/1 "%02x" "\n" /1 "Depth : %u bit" "\n" /1 "Color : %u" "\n" /1 "Compr.: %u" "\n" /1 "Filter: %u" "\n" /1 "Interl: %u" "\n"' sample.png
Run Code Online (Sandbox Code Playgroud)
在 Big Endian/Motorola 机器上,还可以通过以下方式直接打印尺寸:
hexdump -s16 -n8 -e '1/4 "%u" "\n"' sample.png
Run Code Online (Sandbox Code Playgroud)
但是,在 Little Endian / Intel 上,就不是那么容易了,而且也不是很便携。
这样我们就可以实现一个 bash + hexdump 脚本,如下所示:
png_hex='16/1 "%02x" " " 4/1 "%02x" " " 4/1 "%02x" "\n"'
png_valid="89504e470d0a1a0a0000000d49484452"
function png_wh()
{
read -r chunk1 img_w img_h<<<$(hexdump -vn24 -e "$png_hex" "$1")
if [[ "$chunk1" != "$png_valid" ]]; then
printf "Not valid PNG: \`%s'\n" "$1" >&2
return 1
fi
printf "%10ux%-10u\t%s\n" "0x$img_w" "0x$img_h" "$1"
return 0
}
if [[ "$1" == "-v" ]]; then verbose=1; shift; fi
while [[ "$1" ]]; do png_wh "$1"; shift; done
Run Code Online (Sandbox Code Playgroud)
但是,这不是直接有效的。虽然它需要更大的块(75-100 字节),但identify
速度相当快。或者用例如 C 编写例程,这会比库调用更快。
JPEG:
说jpg
起来就不是那么容易了。它也以签名 header 开始,但大小块不是固定的偏移量。标题后:
byte value
0-1 ffd8 SOI (Start Of Image)
2-3 ffe0 JFIF marker
4-5 <block-size> Size of this block including this number
6-10 JFIF\0 ...
11-12 <version>
13 ...
Run Code Online (Sandbox Code Playgroud)
一个新块出现,由一个以 开头的两字节标记指定0xff
。保存有关维度的信息具有价值,0xffc0
但可以隐藏在数据中的相当多的地方。
换句话说,一个跳过块大小的字节,检查标记,跳过块大小的字节,读取标记等等,直到出现正确的一个。
找到后,大小将按两个字节存储在标记之后的偏移量 3 和 5 处。
0-1 ffc0 SOF marker
2-3 <block-size> Size of this block including this number
4 <bits> Sample precision.
5-6 <Y-size> Height
7-8 <X-size> Width
9 <components> Three for color baseline, one for grayscale.
Run Code Online (Sandbox Code Playgroud)
编写了一个简单的 C 程序来检查一些文件和大约 10.000 张 jpg 图像,大约 50% 在前 500 个字节内具有大小信息,大约 50% 在大约 50% 之间。100 和 200。最糟糕的是大约 80.000 字节。一张图,正如我们所说的图片:
动图:
尽管gif通常可以存储多个图像,但它在标题中指定了画布大小,这足以容纳图像。它就像使用PNG一样简单,甚至需要发烧字节:10。在魔术和版本之后,我们找到了大小。来自 364x472 图像的示例:
<byte> <hex> <value>
0-2 474946 GIF Magic
3-5 383961 89a Version (87a or 89a)
6-7 6c01 364 Logical Screen Width
8-9 d801 472 Logical Screen Height
Run Code Online (Sandbox Code Playgroud)
换句话说,您可以检查前六个字节以查看它是否是 gif,然后读取接下来的四个字节的大小。
其他格式:
本来可以继续的,但我想我现在就停在这里。
mohsen@debian:~/codes/amlak/amlak/src$ file ~/Screenshot\ from\ 2013-07-10\ 01\:25\:34.png
/home/mohsen/Screenshot from 2013-07-10 01:25:34.png: PNG image data, 1366 x 768, 8-bit/color RGB, non-interlaced
Run Code Online (Sandbox Code Playgroud)
file command
默认情况下安装在 distors 上并且仅依赖于:
Depends: libc6 (>= 2.4), libmagic1 (= 1:5.14-2), zlib1g (>= 1:1.1.4)
Run Code Online (Sandbox Code Playgroud)
我认为您可以轻松地将其安装为嵌入式。你只需regular expression
为它的输出写一个。
归档时间: |
|
查看次数: |
5316 次 |
最近记录: |