Search code examples
imageimagemagickimagemagick-convertraw

ImageMagick: guess raw image height


I'm using convert utility from ImageMagick to convert raw image bytes to usable image format such as PNG. My raw files are generated by code, so there is no any headers, just pure pixels.

In order to convert my image I'm using command:

$ convert -depth 1 -size 576x391 -identify gray:image.raw image.png
gray:image.raw=>image.raw GRAY 576x391 576x391+0+0 1-bit Gray 28152B 0.010u 0:00.009

The width is fixed and pretty known for me. However I have to evaluate the height of the image from the file size each time which is annoying.

Without height specified or if wrong height is specified the utility compains:

$ convert -depth 1 -size 576 -identify gray:image.raw image.png
convert-im6.q16: must specify image size `image.raw' @ error/gray.c/ReadGRAYImage/143.
convert-im6.q16: no images defined `image.png' @ error/convert.c/ConvertImageCommand/3258.
$ convert -depth 1 -size 576x390 -identify gray:iphone.raw iphone.png
convert-im6.q16: unexpected end-of-file `image.raw': No such file or directory @ error/gray.c/ReadGRAYImage/237.
convert-im6.q16: no images defined `image.png' @ error/convert.c/ConvertImageCommand/3258.

So I wonder is there a way to automatically detect the image height based on the file/blob size?


Solution

  • A couple of ideas...

    You may not be aware of the NetPBM format, but it is very simple and you may be able to change your software that creates the raw images so that it directly generates PBM format images which are readable and useable by OpenCV, Photoshop, GIMP, feh, eog and ImageMagick of course. It would not require any libraries or extra dependencies in your software, all you need to do is put a textual PBM header on the front, so your file looks like this:

    P4
    576 391
    ... YOUR EXISTING BINARY DATA ...
    

    Do not forget to put newlines (i.e. linefeed character) after P4 and after 391.

    You can try it for yourself and add a header onto one of your files like this and then view it with GIMP or other tool:

    printf "P4\n576 391\n"    >  image.pbm
    cat image.raw             >> image.pbm
    

    If you prefer a one-liner, just use a bash command grouping like this - which is equivalent to the 2 lines above:

    { printf "P4\n576 391\n"; cat image.raw; } > image.pbm
    

    Be careful to have all the spaces and semi-colons exactly as I have them!


    Another idea, just putting some meat on Fred's answer, might be the following one-liner which uses a bash arithmetic context and a bash command substitution, you can do this:

    convert -depth 1 -size "576x$(($(stat -c "%s" image.raw)*8/576))" gray:image.raw image.png
    

    Note that if you are on macOS, stat is a little different, so you may prefer the slightly less efficient, but more portable:

    convert -depth 1 -size "576x$(($(wc -c < image.raw)*8/576))" gray:image.raw image.png