58

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.

62

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
| improve this answer | |
  • 1
    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 8:58
  • @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
  • @HonoreDoktorr thank you so much! – roachsinai Dec 11 '19 at 0:33
54

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.

| improve this answer | |
18

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
| improve this answer | |
  • 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 9 '14 at 17:48
  • Not true, it does under recent macOS versions at least. – rien333 May 6 '18 at 22:23
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
| improve this answer | |
1

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.

| improve this answer | |
  • 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 at 3:42
0

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).

| improve this answer | |
0

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"'
| improve this answer | |
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)"
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.