Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

imagemagick convert png 16 bit to raw

I'm trying to convert a 16 bit greyscale PNG to a raw file. The image size is 640*480.

First, identify:

$ identify image.png 
image.png PNG 640x480 640x480+0+0 16-bit PseudoClass 65536c 299KB 0.000u 0:00.000

I'm expecting the result file to be 640*480*2 bytes in size.

Attempt 1:

$ convert image.png -depth 16 image.raw

This gives a file size of 330805 bytes. Its first 16 bytes look like:

0x00000000: 89504E47 0D0A1A0A 0000000D 49484452     .PNG........IHDR

Attempt 2:

$ convert image.png -depth 16 image.rgb

This gives a file size of 1843200 bytes, which is 640*480*2*3.

I'm running imagemagick version 6.7.7-10 on Ubuntu 14.04.

Any ideas?

like image 239
miluz Avatar asked Mar 18 '15 11:03

miluz


2 Answers

Updated Answer

It occurred to me since answering you, that there is a simpler method of doing what you want, that takes advantage of ImageMagick's little-used stream tool, to stream raw pixel data around.

In effect, you can use this command

stream -map r -storage-type short image.png image.raw

which will read the Red channel (-map r), which is the same as the Green and Blue channels if your image is greyscale, and write it out as unsigned 16-bit shorts (-storage-type short) to the output file image.raw.

This is cleaner than my original answer - though should give identical results.

Original Answer

If you write an RGB raw file, you will get 3 channels - R, G and B. Try writing a PGM (Portable Greymap) like this...

convert image.png -depth 16 pgm:-
P5
640 480
65535
<binary data> < binary data>

The PGM format is detailed here, but suffice to say that there is header with a P followed by a digit describing the actual subtype, then a width and height and then a MAX VALUE that describes the range of the pixel intensities. In your case, the MAX VALUE is 65535 rather than 255 because your data are 16-bit.

You can the strip the header like this:

convert image.png -depth 16 pgm:- | tail -c 614400 > file.raw

If you are converting lots of files of different sizes and dislike the hard-coded 614400, and are using bash, you can get ImageMagick to tell you the size (height * width * 2 bytes/pixel) and use that like this:

bytes=$(identify -format "%[fx:h*w*2]" image.png)
convert image.png -depth 16 pgm:- | tail -c $bytes > file.raw
like image 103
Mark Setchell Avatar answered Sep 22 '22 08:09

Mark Setchell


gray might be the format you want:

convert image.png -depth 16 image.gray

This command stores each pixel in 2 bytes and nothing else in the file.

Here I provide a minimal synthetic example: https://superuser.com/questions/294270/how-to-view-raw-binary-data-as-an-image-with-given-width-and-height/978432#978432

enter image description here

.raw is not really a "pixel only" format: it does contain some metadata: https://en.wikipedia.org/wiki/Raw_image_format#File_contents