1

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? *)

    HeaderL = Bytestest -2*25*25

    stream=OpenRead[PGM,BinaryFormat -> True];
    SetStreamPosition[stream,HeaderL];
    MyPGM = BinaryReadList[stream,"UnsignedInteger16",ByteOrdering->-1];
    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]
thomasS
  • 33
  • 6
  • 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. – george2079 Sep 12 '16 at 17:53

1 Answers1

1

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

SetStreamPosition[stream, HeaderL - 1];
MyPGM = BinaryReadList[stream, "UnsignedInteger16", 
   ByteOrdering -> 1];

The combined errors happen to make every value < 256 correct, which makes the image look sort-of right. I think 16 bit PGM is always big endian regardless of your file system.

just by the way you can directly request the integer data from ImageData as:

RI = ImageData[ReImp, "Bit16"];
george2079
  • 38,913
  • 1
  • 43
  • 110
  • 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. – thomasS Sep 13 '16 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 ... – thomasS Sep 13 '16 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*) – george2079 Sep 13 '16 at 15:14
  • I will put this question as answered. Maybe the "real life" sample is of different format. I put a Drop-Box Link to the sample-image. @george2079 Can you check that? Thnx – thomasS Sep 14 '16 at 11:25