È possibile utilizzare curl
per scaricare parti dell'immagine. Tutto dipende da quanto deve essere robusto. Un caso di test potrebbe essere i primi 500 byte. Sembra funzionare per un sacco di png
e jpg
, quindi utilizzare identify
o simili per controllare le dimensioni.
curl -o 500-peek -r0-500 "http://example.net/some-image.png"
Modificare:
Molto tempo da quando ho scritto i parser di immagini, ma ci ho pensato e rinfrescato un po 'della mia memoria.
Sospetto che siano tutti i tipi di immagini che vuoi controllare (ma poi di nuovo, forse no). Descriverò alcuni di quelli più comuni: PNG
, JPEG
(JFIF) e GIF
.
PNG:
Questi sono semplici quando si tratta di estrazione di dimensioni. png
Un'intestazione memorizza la dimensione entro i primi 24 byte. Prima arriva un'intestazione fissa:
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.
Poi arrivano i pezzi attraverso il file. Sono costituiti da un campo fisso di lunghezza, tipo e checksum. Inoltre, una sezione dati opzionale di dimensioni di lunghezza .
Fortunatamente il primo pezzo è sempre un IHDR
con questo layout:
byte description
0-3 Image Width
4-7 Image Height
8 Bits per sample or per palette index
... ...
Con questo abbiamo che le dimensioni sono byte 16-20 e 21-24. È possibile scaricare i dati ad es. 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
Su una macchina Big Endian / Motorola si possono anche stampare le dimensioni direttamente da:
hexdump -s16 -n8 -e '1/4 "%u" "\n"' sample.png
Tuttavia, su Little Endian / Intel, non è così facile, né è molto portatile.
Con questo è possibile implementare uno script bash + hexdump come in:
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
Ma questo non è direttamente efficiente. Sebbene richieda un blocco più grande (75-100 byte), identify
è piuttosto più veloce. Oppure scrivi la routine in es. C, che sarebbe più veloce delle chiamate in libreria.
JPEG:
Quando si tratta di jpg
non è così facile. Comincia anche con un'intestazione della firma , ma il blocco delle dimensioni non ha un offset fisso. Dopo l'intestazione:
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 ...
arriva un nuovo blocco specificato da un marcatore a due byte che inizia con 0xff
. Quello che contiene le informazioni sulle dimensioni ha il valore 0xffc0
ma può essere sepolto un po 'nei dati.
In altre parole, si salta un byte di dimensione blocco , si seleziona un marker, si salta un byte di dimensione blocco , si legge un marker e così via fino a quando viene visualizzato quello corretto.
Quando viene trovato, le dimensioni vengono memorizzate da due byte ciascuna a offset 3 e 5 dopo il marker .
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.
Scritto un semplice programma C per controllare alcuni file e di circa 10.000 immagini jpg, circa il 50% aveva le informazioni sulla dimensione entro i primi 500 byte, per lo più il 50% tra ca. 100 e 200. Il peggio era di circa 80.000 byte. Un'immagine, mentre parliamo di immagini:
GIF:
Sebbene in genere gif possa contenere più immagini all'interno, ha una dimensione di tela specificata nell'intestazione, ma è abbastanza grande per ospitare le immagini. È facile come con PNG e richiede anche byte di febbre: 10. Dopo la magia e la versione troviamo le dimensioni. Esempio da un'immagine 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
In altre parole è possibile controllare i primi sei byte per vedere se si tratta di una gif, quindi leggere le quattro successive per le dimensioni.
Altri formati:
Avrebbe potuto continuare, ma suppongo che mi fermerò qui per ora.