94

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.

2

10 Answers 10

98

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
4
  • 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, 2019 at 8: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 Dec 10, 2019 at 20:30
  • 1
    @HonoreDoktorr thank you so much!
    – roachsinai
    Dec 11, 2019 at 0: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. unix.stackexchange.com/a/176972/43139
    – Mint
    Feb 21 at 3:00
86

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.

0
40

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
3
  • 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, 2014 at 17:48
  • 2
    Not true, it does under recent macOS versions at least.
    – rien333
    May 6, 2018 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, 2020 at 16:39
6

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
1
  • 1
    genius. XDDDDDD
    – alexzander
    Aug 11, 2021 at 18:01
3

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

1
  • 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 at 2:57
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.

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. Apr 24, 2020 at 3:42
2

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"'
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)"
0

It's been added to act:

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

    2000x2000
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"

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.