Page 1 of 1

Setting Pixel value in Q16 HDRI 7.4.5

Posted: 2018-06-27T01:29:58-07:00
by JohnnyGubbins
Sorry if I am asking a question that has been asked before - I googled a lot and couldn't find anything on this.

I am trying to create some 32bpc images procedurally (for game development purposes). I tried few different approaches but it seems that no matter what pixel value I am setting, the resulting image is always black. My understanding of pixel collection is that it returns array of all channels (RGBA) which I can directly access and set value per channel. Sounds easy peasy but like I mentioned, resulting image is black.

Code: Select all

            MagickColor startCol = new MagickColor();
            startCol.R = 10f;
            startCol.G = 2f;
            startCol.B = 0.5f;
            startCol.A = 1.0f;
            
            MagickImage img = new MagickImage(startCol, 4, 4);
            img.ColorSpace = ColorSpace.sRGB;
            img.Format = MagickFormat.Tiff;
            
            IPixelCollection pixels =  img.GetPixels();
            float[] colChannels= new float[pixels.Channels];
            Console.WriteLine("colChannels length " + colChannels.Length); //returns 3
            for (int i = 0; i < col.Length; i++)
            {
                colChannels[i] = 100f;
            }
            pixels.SetPixel(1, 1, colChannels);
            Console.WriteLine(pixels.GetValue(1, 1)[0]); //returns 100.0f
            Console.WriteLine(pixels.GetPixel(1, 1).ToColor().ToColor()); //returns RGBA 0;0;0;0
            
            img.Write("asd.tiff"); //resulting image is black with alpha=0

Re: Setting Pixel value in Q16 HDRI 7.4.5

Posted: 2018-06-27T22:40:50-07:00
by dlemstra
The color is almost black because you are setting the value to 100f when the range is 0f to 65535f. This is almost black in the output image. And when you convert the pixel to a `System.Drawing.Color` the value will be zero because it only uses a range from 0f to 256f and when 100f is converted to that range it will become zero: 256 * (100/65535) = 0.39f = (byte)0. To get a non black image you will need to increase the value.

And make sure that you put "img" and "pixels" inside a using block.

Re: Setting Pixel value in Q16 HDRI 7.4.5

Posted: 2018-06-28T00:20:48-07:00
by JohnnyGubbins
dlemstra wrote:
2018-06-27T22:40:50-07:00
And when you convert the pixel to a `System.Drawing.Color` the value will be zero because it only uses a range from 0f to 256f and when 100f is converted to that range it will become zero: 256 * (100/65535) = 0.39f
Ok, I tried what you said and increased colour values but it absolutely makes no sense for me. What I am trying to do is saving signed 32bit per channel image where RGB values are essentially XYZ coortinate values. It seems that Image Magick will always remap to 8bit per channel when saving the image. So if I want to store a value of RGB(-150f, 250f, 5f) I have to multiply that by 256 and Image Magick will remap that to 8bit anyway so I am also loosing negative values and precision? Am I missing something? Why would I ever want such a behaviour and is there a way to avoid it? I want to save the exact floating point values into my image as I define them in my code without any remapping occurring. I tried tiff, tga and hdr formats but it keeps remapping these values no matter what.

Re: Setting Pixel value in Q16 HDRI 7.4.5

Posted: 2018-06-28T14:20:52-07:00
by dlemstra
The mapping to 8 bit will happen when you convert a pixel to a `System.Drawing.Color` because that only supports values in the range 0-255.

ImageMagick will not remap the value to 8bit when you are using Q16 HDRI but not all formats support 16bit HDRI. Have you tried the exr format?

Re: Setting Pixel value in Q16 HDRI 7.4.5

Posted: 2018-06-28T14:47:05-07:00
by snibgo
@JohnnyGubbins: you haven't said what version of IM you are using. Is it Q8, Q16, Q32 or Q64? Does it have HDRI?
JohnnyGubbins wrote:What I am trying to do is saving signed 32bit per channel image where ...
Do you want 32 bit/channel integer or HDRI? In either case, if you want that much precision, I suggest you use Q32 IM, with or without HDRI.
TIFF is a flexible format, and can store either 32-bit integer or 32-bit float.

Re: Setting Pixel value in Q16 HDRI 7.4.5

Posted: 2018-06-29T00:14:56-07:00
by JohnnyGubbins
Ok, forget about Console.WriteLine(pixels.GetPixel(1, 1).ToColor().ToColor());
I am checking pixel values in another app which displays with any bpc precision, supports both signed and usigned values. I used that line just for quick debugging but I rely on other app to check values with precision.

What I need in a nutshell:
* 16 or 32 bits per channel (I haven't decided yet how much precision do I need so let's assume I need 16bits per channel)
* I don't want any 8bit remapping happening at all. Setting pixel RGB 1f,1f,1f should result in saving these exact values
* Signed values need to be saved
* Ideally I should be able to use tif format (I have a working implementation of all that in Python but I want to translate to c# and use it's gui system)
* Colour space should be linear

I am using Q16 HDRI 7.4.5 (mentioned in the name of the thread but I guess it's easy to miss ;) ). And to be honest, I didn't know there is Q32 and Q64 available. Documentation lists versions Q8 and Q16, Q32 and Q64 are not there ( https://github.com/dlemstra/Magick.NET ). I can't find Q32/64 on NuGet Gallery either.

Thanks for helping me out with that guys! Really appreciated.

Re: Setting Pixel value in Q16 HDRI 7.4.5

Posted: 2018-06-29T01:29:36-07:00
by snibgo
Yes, sorry I missed your title {embarrassed}. The current version is v7.0.8-3. V7.4.5 isn't (yet) an IM version.

I think V7 Q16 HDRI records values internally as 32-bit float, so you can expect that precision.

I don't use Magick.NET, so I'll leave those aspects to dlemstra.

Beware that white has values of 2^q-1 in each channel. In scripts and programs, we often scale values so the user sees 1.0 or 100 as the maximum.
JohnnyGubbins wrote:Signed values need to be saved
Then you must save as floating-point. At the command level, use

Code: Select all

-depth 32 -define "quantum:format=floating-point"
I don't know the equivalent in Magick.NET.
JohnnyGubbins wrote:Colour space should be linear
So I suppose you want anti-aliasing etc to operate in linear RGB space? That is a reasonable need. Sadly, IM is biased towards non-linear sRGB. For some operations, IM will check whether the image is in sRGB space and will convert it if it isn't. A workaround is to "-set colorspace sRGB". This tells IM to change just the metadata of an image that is in RGB or Lab or whatever, so it won't automatically change the pixel data to sRGB when performing operations or saving to a file.

Re: Setting Pixel value in Q16 HDRI 7.4.5

Posted: 2018-06-30T05:43:33-07:00
by dlemstra
@snibgo: Magick.NET has a different version number than ImageMagick. You can see here which version of ImageMagick is being used: https://github.com/dlemstra/Magick.NET/ ... ag/7.4.5.0.

Re: Setting Pixel value in Q16 HDRI 7.4.5

Posted: 2018-06-30T05:53:26-07:00
by snibgo
dlemstra wrote:@snibgo: Magick.NET has a different version number than ImageMagick.
Oops, sorry, thanks.