# Import an binary image with non-standard header

I have binary images with an fixed sized header. These can be converted into PGM images, provided cutting the header, and putting the appropriate information using linux/OSX tools as "head -c", "tail -c", and "cat". I can later import these images in Mathematica for further treatment.

I would like to create an importer in Mathematica as treated in the documentation which could do all this so the import can be done on a Windows station without using the linux/OSX tools.

I have not been able to manage this problem.

The only Idea I had is to use the functions BinaryReadList or BinaryRead. But since the information I get with them is not the same as what I get with ImageData[Import[file, "PGM"]]. I am stuck.

The difference can be directly verified with binread-module based an answer of Sjoerd C. de Vries. And also with a little code I wrote to show the difference on readable files

    (* PGM : filename for output *)

PGM= "/Users/thomas/Documents/Mathematica/LM.pgm";
Dim = {25,25};
f[x_,y_]:=2^16*E^(-(2/3) (x^2-0.5 x y+0.25 y^2));

(* Creating now an small Image *)

LittleMat=IntegerPart[Array[f,Dim,{{-6,6},{-6,6}}]+1];
(*LittleMat= RandomInteger[{1,2^16},Dim];*)
ArrayPlot[LittleMat, ImageSize->{300,300},AspectRatio->Full]

(* Exporting and re-importing the small Image *)

Export[PGM,Image[LittleMat,"UnsignedInteger16"],"PGM"];
ReImp = Import[PGM,"PGM"];
RI = IntegerPart[2^16*ImageData[ReImp]];

ArrayPlot[RI, ImageSize->{300,300},AspectRatio->Full]

(* Information is luckily still the same *)
(*LittleMat-RI*)

(* Now reading the file binary, bitwise *)

Bytestest = FileByteCount[PGM]
N[Bytestest /(25*25)]

(* Why is the ImageSize in bits twice the pixel-number? *)

SetStreamPosition[stream,0];
Close[stream];

(* MyPGM list of the same size as pixel-number *)

PGMmat = Partition[MyPGM,25];
ArrayPlot[PGMmat, ImageSize->{300,300},AspectRatio->Full]

(* Information not the same aby more *)

ArrayPlot[PGMmat-RI, ImageSize->{300,300},AspectRatio->Full]

• just to answer the easy one "ImageSize in bits twice the pixel - number": the image size in bytes is twice the pixel size because you are using 16 bit / 2 byte integers. Sep 12, 2016 at 17:53

you are one byte off when you set stream position, and have the wrong byte ordering. This makes it work:

SetStreamPosition[stream, HeaderL - 1];

just by the way you can directly request the integer data from ImageData as:
RI = ImageData[ReImp, "Bit16"];

• Thank you. Even if it looks fine, there is the center pixel which is different, and PGMmat == RI gives False. Still I would be happy with the result, if the "real life" PGM-Image would work as well, ... I should find a way to send you that small image. Sep 13, 2016 at 14:28
• For the given example : RI = ImageData[ReImp, "Bit16"]; is much better, since PGMmat == RI answers with True, but still not for the "real life" PGM-Image. For this image : Even the maximum/minimum are different ... Sep 13, 2016 at 14:52
• the 16 bit range is actually 0-(2^16-1), so you should have had IntegerPart[(2^16-1)*ImageData[ReImp]] You should have (2^16-1) in your f definition and don't add the 1 after IntegerPart and then it all works out. RI == PGMmat == LittleMat (*True*) Sep 13, 2016 at 15:14