Bash: URL에서 이미지 크기를 결정하는 가장 빠른 방법

Bash: URL에서 이미지 크기를 결정하는 가장 빠른 방법

저는 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바이트입니다. 우리가 그림이라고 부르는 그림은 다음과 같습니다.

JFIF_SOF_graph


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://

관련 정보