저는 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 패키지에서 나온 것으로 보이는 두 개의 라이브러리 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
이미지의 높이와 너비를 얻을 수 있습니다. 처음 두 부분은 이미지가 존재하는지 확인한 다음 이를 IMAGE 변수로 설정합니다. 다음 부분은 파일이 실제로 존재하는지 확인하는 것입니다. 마지막 두 부분은 "식별" 출력에서 관련 정보를 가져와 표시하는 것입니다.
#!/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://