2

How can I specify the bit depth for the MagickImage.Read() function when reading binary files?

I have a 1024x1024 image represented by 8-bit grayscale values (total file length = 1024x1024 = 1048576 bytes). Using ImageMagick v.7.0.8-7 Q16 x64, I can convert the file using

magick.exe -depth 8 -size 1024x1024 -format Gray Gray:filepath.bin convertedfile.png

When I try to convert the file using Magick.NET Q16-AnyCPU v7.5.0.1,

public MagickImage ReadNewMagickImageFromBinary(string fileName){
    MagickReadSettings settings = new MagickReadSettings();

    settings.Width = 1024;
    settings.Height = 1024; //if I use settings.Height = 512; , I'm OK.
    settings.Format = MagickFormat.Gray;
    //settings.Depth = 8;                                   //didn't work
    //settings.SetDefine(MagickFormat.Gray, "depth", "8");  //also didn't work

    MagickImage newImage = new MagickImage();
    newImage.Depth = 8; //this appears to be ignored once the Read function is called
    newImage.Read(fileName, settings);

    return newImage;
}

I get the error

Message: ImageMagick.MagickCorruptImageErrorException : unexpected end-of-file '': No such file or directory @ error/gray.c/ReadGRAYImage/241

Indicating that the program has read past the end of the file. I've confirmed that Magick.NET is reverting to a 16-bit depth instead of the 8-bit depth I want. I can read the file using settings.Height = 512 instead of 1024, which gives me a squashed version of my grayscale image.

I learned from Memory consumption in Magick.NET that Magick.NET Q16 stores pixels in memory with 16-bit precision; I'm fine with that but it doesn't seem that should preclude 8-bit reading capabilities.

How do I force Magick.NET Q16 to read pixels in with an 8-bit depth?

Stadem
  • 423
  • 1
  • 6
  • 15
  • Have you tried moving where you set the depth to before `NewImage`? I do not know Magick.Net, but perhaps it should be `settings.Depth=8;` – fmw42 Jul 23 '18 at 21:52
  • Looking at the documentation, perhaps you need to use a define as per https://github.com/dlemstra/Magick.NET/blob/master/Documentation/Defines.md to tell the output that it should be depth 8. – fmw42 Jul 23 '18 at 22:02
  • thanks @fmw42; I did try `settings.Depth=8;` as well as `settings.SetDefine(MagickFormat.Gray, "depth", "8");` and neither worked. I don't have a good understanding of ImageMagick's `-define`; I wonder if that would help me understand Magick.NET's `SetDefine()` better. Do you have any good resources on either? – Stadem Jul 23 '18 at 23:34
  • 1
    No, the only resource I have is the link I provided. But you can ask this question at http://www.imagemagick.org/discourse-server/viewforum.php?f=27, where the developer of Magick.NET should see it and respond. Give him time as he has another full time job. You can also post an issue at https://github.com/dlemstra/Magick.NET, which may be the faster way for him to find it. P.S. perhaps you do the define on the output image. – fmw42 Jul 23 '18 at 23:52
  • OK will do. Thanks for all your work, by the way, you're a primary reason this is my first and not 20th ImageMagick question. – Stadem Jul 24 '18 at 00:34
  • I sent email to the Magick.Net developer and he says he is working on a fix. – fmw42 Jul 24 '18 at 16:49

2 Answers2

1

I just published Magick.NET 7.6.0.0 that now has better API for reading raw pixels. You should change your code to this:

public MagickImage ReadNewMagickImageFromBinary(string fileName)
{
    var width = 1024;
    var height = 1024;
    var storageType = StorageType.Char;
    var mapping = "R";
    var pixelStorageSettings = new PixelStorageSettings(width, height, storageType, mapping);

    return new MagickImage(fileName, pixelStorageSettings);
}
dlemstra
  • 7,813
  • 2
  • 27
  • 43
  • Your solution is for dept of pixels that are exactly a byte. There are circumstances that the depth is 12 (12 bits), so it is 1 and half bytes. What solution is for 12 bits per pixel. – Eitan Dec 09 '18 at 10:31
  • I see that 12 bits are ok as 16 bits, but if I do: new MagickImage( ...) instead of new MagickImage( ...), the data is get as 8 bits (if I save it - I see that it is darkened/not as the original 16 bits). – Eitan Dec 17 '18 at 10:46
  • @Eitan, I'm guessing this is a problem of data type. How do you map a 12-bit value into a number corresponding to the brightness of the pixel? ImageMagick probably doesn't know, so Magick.NET won't know either. You may need to convert your 12-bit values into ushort data type, then read in using `var storageType = StorageType.Short` and `MagickImage.ReadPixels(uShortArray, pixelStorageSettings)` – Stadem Dec 19 '18 at 20:52
0

One workaround is to use the Magick.NET Q8 version instead of Magick.NET Q16. I successfully read the file using the program Magick.NET Q8-AnyCPU 7.5.0.1.

I'm still hoping there's a solution that allows me to still use Magick.NET Q16, but this works for now.

Stadem
  • 423
  • 1
  • 6
  • 15