私はBashで画像サイズを決定する非常に迅速な方法を見つけようとしています。
私は画像を取得し、imagemagickを使用して画像の高さと幅を決定できることを知っています。これが最速の方法ではないかもしれません。
また、小さな機能セットだけが必要なときにimagemagickをインストールする必要があることも心配です。私が作業している組み込みシステムには、リソース(CPU、RAM、ストレージ)が非常に限られています。
どんなアイデアがありますか?
答え1
ご存知のように、全体は必要ありません。イメージマジシャンパック。あなたはただidentify
。
また、実行可能ファイルがリンクされているライブラリ(およびこれらのライブラリがリンクされているライブラリ)が必要です。
> whereis identify
identify: /bin/identify /usr/bin/identify /usr/share/man/man1/identify.1.gz
> ldd /bin/identify
ldd
リストが表示されます。私がこれを行ったとき、いくつかのXライブラリ、libjpegなどが含まれており、ImageMagickパッケージから来たように見える2つのライブラリもlibMagickCore
含まれていましたlibMagickWand
。これらは同じ項目に結び付けられているように見えるため、identify
機能します。 。
identify
サイズはファイルの先頭のヘッダーにあり、私たちが見ているものなので、サイズを取得するためにイメージ全体をダウンロードする必要はありません。たとえば、ここではjpeg全体の最初の4kBを新しいファイルにコピーします。
dd if=real.jpg of=test.jpg bs=1024 count=4
ヘッダーを含めるには4kBで十分です。その量の1/4で十分だと思います。今:
>identify test.jpg
test.jpg JPEG 893x558 893x558+0+0 8-bit DirectClass 4.1KB 0.000u 0:00.000
これらは正しいサイズですreal.jpg
。ただし、その情報は画像ヘッダーでは提供されないため、サイズ(4.1KB)は切り捨てられたファイルのサイズです。
したがって、各画像の最初のKB程度をダウンロードするだけです。
答え2
これを使用してcurl
画像の一部をダウンロードできます。それはすべてそれがどれほど頑丈であるかに依存します。テストケースは最初の500バイトです。多くのpng
金額を処理し、jpg
サイズをidentify
確認するために、または同様のものを使用するようです。
curl -o 500-peek -r0-500 "http://example.net/some-image.png"
編集する:
イメージパーサーを作成してからかなり時間が経ちましたが、思いを見て思い出を少し蘇りました。
私はそれだと思うあらゆる種類の確認したい画像(ただし、もう一度確認しない可能性があります)。より一般的なものについて説明しますPNG
。JPEG
(JFIF)そしてGIF
。
パプアニューギニア:
次元抽出においては簡単です。ヘッダーは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.
次は彫刻ファイルを削除します。これは、固定長フィールド、タイプ、およびチェックサムで構成されます。オプションもありますデータ部分長さサイズ。
最初になったのは幸運です彫刻レイアウトは常にIHDR
次のようになります。
byte description
0-3 Image Width
4-7 Image Height
8 Bits per sample or per palette index
... ...
これから、バイト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
Big Endian / Motorolaシステムでは、次の方法で寸法を直接印刷することもできます。
hexdump -s16 -n8 -e '1/4 "%u" "\n"' sample.png
しかし、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
しかし、これは直接的に効果的ではありません。より大きなブロック(75〜100バイト)が必要ですが、identify
かなり高速です。あるいは、Cでルーチンを作成すると、ライブラリ呼び出しよりも高速です。
JPEG:
それに関してはjpg
それほど簡単ではありません。また、次から始まります。署名ヘッダしかし、大小の塊固定オフセットではありません。タイトルの後ろ:
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 ...
で始まる2バイトのタグで指定された新しいブロックが表示されます0xff
。ディメンションに関する情報を保持するデータは価値がありますが、0xffc0
データにかなり埋もれている可能性があります。
つまり、ジャンプブロックサイズバイト、チェックマーク、スキップブロックサイズ正しいタグが表示されるまでバイト、タグの読み取りなどを実行します。
見つかった場合、サイズはオフセット3と5にそれぞれ2バイトとして格納されます。表示。
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.
いくつかのファイル(約10,000個のjpg画像)を確認するための簡単なCプログラムを書いています。約50%は最初の500バイト内のサイズ情報を持ち、ほとんどの50%は約10,000バイトの間にあります。 100と200。最悪の場合は約80,000バイトです。私たちが絵と呼ぶ絵は次のとおりです。
GIF:
しかし、GIF複数の画像を保存できることがよくあります。キャンバスヘッダーで指定されたサイズで、画像を収容するのに十分な大きさです。それは同じですパプアニューギニア、さらに発熱バイトも必要です: 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
つまり、最初の6バイトをチェックしてgifであることを確認し、次の4バイトを読み取ってサイズを判断できます。
その他の形式:
続けることもできましたが、今はここで止まります。
答え3
「識別」があるとします。これをスクリプトに入れてchmod +x <scriptname>
実行すると、<scriptname> picture.jpg
画像の高さと幅を取得できます。最初の2つの部分は画像が存在することを確認し、それをIMAGE変数に設定します。次の部分は、ファイルが実際に存在することを確認することです。最後の2つの部分は、「識別」出力から関連情報を取得して表示することです。
#!/bin/bash
if [[ "${#}" -ne "1" ]]
then
die "Usage: $0 <image>"
fi
IMAGE="${1}"
if [[ ! -f "${IMAGE}" ]]
then
die "File not found: ${IMAGE}"
fi
IMG_CHARS=`identify "$1" | cut -f 3 -d' '`
WIDTH=`echo $IMG_CHARS | cut -d'x' -f 1`
HEIGHT=`echo $IMG_CHARS | cut -d'x' -f 2`
echo -e "W: ${WIDTH} H: ${HEIGHT}"
答え4
mohsen@debian:~/codes/amlak/amlak/src$ php -r "print_r(getimagesize('file:///archives/Picture/12 farvardin/20120331_013.jpg'));"
Array
(
[0] => 2560
[1] => 1440
[2] => 2
[3] => width="2560" height="1440"
[bits] => 8
[channels] => 3
[mime] => image/jpeg
)
mohsen@debian:~/codes/amlak/amlak/src$ php -r "print_r(getimagesize('file:///archives/Picture/12 farvardin/20120331_013.jpg'));" |egrep w
[3] => width="2560" height="1440"
mohsen@debian:~/codes/amlak/amlak/src$ php -r "print_r(getimagesize('file:///archives/Picture/12 farvardin/20120331_013.jpg'));" |egrep w | awk {'print $3'}
width="2560"
mohsen@debian:~/codes/amlak/amlak/src$ php -r "print_r(getimagesize('file:///archives/Picture/12 farvardin/20120331_013.jpg'));" |egrep w | awk {'print $4'}
height="1440"
あなたfile://
はhttp://