111

Is there a shell command that returns the pixel size of an image?

I'm trying to produce an animated gif starting from different gifs with different sizes using convert (e.g. convert -delay 50 1.gif 2.gif -loop 0 animated.gif).

The problem is that convert simply overlaps the images using the first image's size as the size of the animated gif, and since they have different sizes the result is a bit of a mess, with bits of the old frames showing under the new ones.

blue
  • 2,952

10 Answers10

120

found a solution: identify, part of the imagemagick package, does exactly what I need

$ identify color.jpg 
> color.jpg JPEG 1980x650 1980x650+0+0 8-bit DirectClass 231KB 0.000u 0:00.000
Hugolpz
  • 163
  • 1
  • 5
blue
  • 2,952
  • 2
    Could you explain why I got multiple rows when I run identify imagename.ico? Like todour.ico[0] ICO 32x32 32x32+0+0 4-bit sRGB 0.000u 0:00.000 todour.ico[1] ICO 16x16 16x16+0+0 4-bit sRGB 0.000u 0:00.000 todour.ico[2] ICO 48x48 48x48+0+0 8-bit sRGB 0.000u 0:00.000 – roachsinai Feb 26 '19 at 08:58
  • 1
    @roachsinai, identify does this for images with multiple resolutions and for animations. Your icon file contained 16x16, 32x32, & 48x48 sizes. Animations may also show placement offsets and durations, like a.gif[0] GIF 163x130 163x130+0+0 8-bit sRGB 65c 0.000u 0:00.000 a.gif[1] GIF 132x125 163x130+20+3 8-bit sRGB 65c 0.000u 0:00.000 – Honore Doktorr Dec 10 '19 at 20:30
  • 1
    @HonoreDoktorr thank you so much! – roachsinai Dec 11 '19 at 00:33
  • If speed is of concern (or large image/s) I'd recommend using GraphicsMagick, a fork of ImageMagick, but so much faster and lower CPU usage. See Jerry Epas answer way down. https://unix.stackexchange.com/a/176972/43139 – Mint Feb 21 '22 at 03:00
97

Rather than parsing the output of identify by eye, or by text utilities, you can use its -format option to output the width and height in whatever format suits you best. For example:

$ identify -format '%w %h' img.png
100 200
$ identify -format '%wx%h' img.png
100x200

A list of image properties that you can output can be found on this page, but for the question here, it seems all you need are %w and %h, which give the image's width and height, respectively, in pixels.


The flexibility afforded by -format came in handy for me in finding the largest images in terms of pixels, by outputting %[fx:w*h] for a number of images and sorting the output.

You might want to specify the -ping option if you're processing many images, using more complicated escapes, and want to make sure the program doesn't waste time loading the entire images. With simple escapes, -ping should be the default. More information on the choice between -ping and +ping can be found here.

Dan Getz
  • 1,451
47

you can just use the command "file" to get the informations you need:

~# file cha_2.png 
cha_2.png: PNG image data, 656 x 464, 8-bit/color RGB, non-interlaced
  • 1
    This does NOT report the size for other (non-png) image types... file taylor-swift-money-makers-990.jpg -> taylor-swift-money-makers-990.jpg: JPEG image data, JFIF standard 1.01, comment: "CREATOR: gd-jpeg v1.0 (using IJ" – alex gray Oct 09 '14 at 17:48
  • 2
    Not true, it does under recent macOS versions at least. – rien333 May 06 '18 at 22:23
  • 2
    Confirm png and jpg are supported by file (version 5.04 of the file command). Example: $ file mlk.jpg outputs JPEG image data, baseline, precision 8, 960x801, components 3 – DeBraid Oct 30 '20 at 16:39
6

You can also try GraphicsMagick, which is a well maintained fork of ImageMagick used at e.g. Flickr and Etsy:

$ gm identify a.jpg
a.jpg JPEG 480x309+0+0 DirectClass 8-bit 25.2K 0.000u 0:01

It is faster than ImageMagick's identify (in my tests about twice).

  • Can't believe this isn't higher. Especially for larger images, im: 1.629s vs gm: 0.009s in my tests. In general GraphicsMagick is much faster, even ffmpeg can be, depending on your use case. – Mint Feb 21 '22 at 02:57
5

Use identify to see the sizes :

$ identify color.jpg 
> color.jpg JPEG 1980x650 1980x650+0+0 8-bit DirectClass 231KB 0.000u 0:00.000

Extract value via cut | sed, from field 3:

identify ./color.jpg | cut -f 3 -d " " | sed s/x.*// #width
identify ./color.jpg | cut -f 3 -d " " | sed s/.*x// #height

Asign to variable:

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
Hugolpz
  • 163
  • 1
  • 5
3

Both display and file are quite slow, and have the potential to bring even quite capable systems to their knees dealing with many multiple files. A small test:

     $ 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

By reading only the bytes necessary, this operation can be significantly sped up.

     $ /usr/bin/time ./pngsize *.png
-->  0.00user 0.00system 0:00.03elapsed 12%CPU (0avgtext+0avgdata 1904maxresident)k
     0inputs+0outputs (0major+160minor)pagefaults 0swaps

Here is pngsize:

#include <stdlib.h>
#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;
}

This method is much faster than using a library which loads the PNG forwards, backwards and sideways just to get the image size :P (Consider the code carefully before feeding it a directory full of arbitrary PNGs of course.)

The code uses inet.h for htonl() to de-endian-ize the header byte ordering.

i336_
  • 1,017
  • 1
    Just a little note if you want to compile the above code. Save the C code above to pngimage.c then run the command gcc -o pngimage pngimage.c this will create a command line executable called pngimage you can then call. You will need to hav Xcode installed on your system. – John Ballinger Apr 24 '20 at 03:42
3

This was a helpful snippet (I didn't write) that does returns dimensions for every png and jpg in the folder:

file ./* | perl -ne '@m = /^.*.jpg|^.*.png|[0-9][0-9]*[ ]?x[ ]?[0-9][0-9]*/g; print "@m\n"'
ArleyM
  • 139
0

For those like me who want the size in megapixels :

perl -le "printf \"=> fileName = %s size = %.2f Mpix\n\", \"$fileName\", $(identify -format '%w*%h/10**6' $fileName)"
SebMa
  • 2,149
0

It's been added to act:

$ npm install @lancejpollard/act -g
$ act read image.png --size
2000x2000

Lance
  • 447
0

If performance is an issue, you can install w3m-img utilities and use it like this:

printf "5;%s" "/path/to/img.jpg" | "/usr/lib/w3m/w3mimgdisplay"
desgua
  • 61