encontrou uma solução: identify
, parte do pacote imagemagick, faz exatamente o que eu preciso
$ identify color.jpg
> color.jpg JPEG 1980x650 1980x650+0+0 8-bit DirectClass 231KB 0.000u 0:00.000
Existe um comando shell que retorna o tamanho do pixel de uma imagem?
Estou tentando produzir um gif animado a partir de diferentes gifs com tamanhos diferentes usando convert
(por exemplo, convert -delay 50 1.gif 2.gif -loop 0 animated.gif
).
O problema é que a conversão simplesmente sobrepõe as imagens usando o tamanho da primeira imagem como o tamanho do gif animado, e como elas têm tamanhos diferentes, o resultado é um pouco confuso, com bits dos quadros antigos aparecendo sob o novo queridos.
Em vez de analisar a saída de identify
a olho nu ou por utilitários de texto, você pode usar sua opção -format
para exibir a largura e a altura em qualquer formato mais adequado a você. Por exemplo:
$ identify -format '%w %h' img.png
100 200
$ identify -format '%wx%h' img.png
100x200
Uma lista de propriedades de imagem que você pode imprimir pode ser encontrada em esta página , mas para a pergunta aqui , tudo o que você precisa é de %w
e %h
, que fornecem a largura e a altura da imagem, respectivamente, em pixels.
A flexibilidade oferecida pelo -format
foi útil para encontrar as maiores imagens em termos de pixels, gerando %[fx:w*h]
para várias imagens e classificando a saída.
Você pode querer especificar a opção -ping
se estiver processando muitas imagens, usando saídas mais complicadas e quiser garantir que o programa não perca tempo carregando as imagens inteiras. Com saídas simples, -ping
deve ser o padrão. Mais informações sobre a escolha entre -ping
e +ping
podem ser encontradas aqui .
você pode simplesmente usar o comando "file" para obter as informações necessárias:
~# file cha_2.png
cha_2.png: PNG image data, 656 x 464, 8-bit/color RGB, non-interlaced
Use identify
para ver os tamanhos:
$ identify color.jpg
> color.jpg JPEG 1980x650 1980x650+0+0 8-bit DirectClass 231KB 0.000u 0:00.000
Extrair valor via cut | sed
, do campo 3:
identify ./color.jpg | cut -f 3 -d " " | sed s/x.*// #width
identify ./color.jpg | cut -f 3 -d " " | sed s/.*x// #height
Atribuir à variável:
W='identify ./color.jpg | cut -f 3 -d " " | sed s/x.*//' #width
H='identify ./color.jpg | cut -f 3 -d " " | sed s/.*x//' #height
echo $W
> 1980
echo $H
> 650
Tanto o display
quanto o file
são bastante lentos e têm o potencial de colocar até mesmo sistemas capazes de lidar com vários arquivos múltiplos. Um pequeno teste:
$ du -h *.png --total | tail -n 1
9.2M total
$ ls -l *.png | wc -l
107
$ /usr/bin/time file *.png
--> 0.37user 0.26system 0:06.93elapsed 9%CPU (0avgtext+0avgdata 37232maxresident)k
22624inputs+0outputs (9major+2883minor)pagefaults 0swaps
$ /usr/bin/time identify *.png
--> 0.56user 0.22system 0:06.77elapsed 11%CPU (0avgtext+0avgdata 25648maxresident)k
34256inputs+0outputs (119major+2115minor)pagefaults 0swaps
Ao ler apenas os bytes necessários, esta operação pode ser significativamente acelerada.
$ /usr/bin/time ./pngsize *.png
--> 0.00user 0.00system 0:00.03elapsed 12%CPU (0avgtext+0avgdata 1904maxresident)k
0inputs+0outputs (0major+160minor)pagefaults 0swaps
Aqui está o pngsize:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <err.h>
#define oops(syscall) { printf("error processing %s: ", argv[i]); \
fflush(0); perror(syscall"()"); continue; }
int main(int argc, char **argv) {
int fd, i;
uint32_t h, w;
if (argc < 2) { printf("%s <pngfile> [pngfile ...]\n", argv[0]); exit(0); }
for (i = 1; i < argc; i++) {
if (argc > 2) printf("%s: ", argv[i]);
if ((fd = open(argv[i], O_RDONLY)) == -1) oops("open");
if (lseek(fd, 16, SEEK_SET) == -1) oops("lseek");
if (read(fd, &w, 4) < 1) oops("read");
if (read(fd, &h, 4) < 1) oops("read");
printf("%dx%d\n", htonl(w), htonl(h));
if (close(fd) == -1) oops("close");
}
return 0;
}
Este método é muito mais rápido do que usar uma biblioteca que carregue o PNG para a frente, para trás e para os lados apenas para obter o tamanho da imagem: P (Considere o código cuidadosamente antes de alimentá-lo com um diretório cheio de PNGs arbitrários, é claro.)
O código usa inet.h para htonl () para de- endian --ize a ordenação de bytes do cabeçalho.
Você também pode tentar o GraphicsMagick , que é um fork bem conservado do ImageMagick usado em, por exemplo, Flickr e Etsy:
$ gm identify a.jpg
a.jpg JPEG 480x309+0+0 DirectClass 8-bit 25.2K 0.000u 0:01
É mais rápido que o ImageMagick (nos meus testes, aproximadamente).
Este foi um snippet útil (não escrevi) que retorna dimensões para cada png e jpg na pasta:
file ./* | perl -ne '@m = /^.*.jpg|^.*.png|[0-9][0-9]*[ ]?x[ ]?[0-9][0-9]*/g; print "@m\n"'