ImageMagick "invalid colormap index" on greyscale image - c++

I'm attempting to use ImageMagick 6.9.3-1 to convert a medical X-ray format into a more common one, be it a png, bmp or whatever. I have zero documentation on this file format. I have zero access to the software that loads the image. I'm hoping this wonderful community can help me out here.
So far I have determined it is a grey scale jfif with 12 bits per pixel.
I have compiled ImageMagick to enable decompression of 12 bit jfifs, which is where the problem may lie, but more on that later.
ImageMagick identify outputs no errors
C:\libjpeg\ImageMagick-6.9.3-1\VisualMagick\bin>identify.exe C:\Users\alexander\
Desktop\708_885_5856.xdr
C:\Users\alexander\Desktop\708_885_5856.xdr JPEG 1896x1368 1896x1368+0+0 12-bit
Gray 4096c 659KB 0.000u 0:00.000
However, ImageMagick identify -verbose reports the error "invalid colormap index"
C:\libjpeg\ImageMagick-6.9.3-1\VisualMagick\bin>identify.exe -verbose C:\Users\a
lexander\Desktop\708_885_5856.xdr
Image: C:\Users\alexander\Desktop\708_885_5856.xdr
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
Class: PseudoClass
Geometry: 1896x1368+0+0
Units: Undefined
Type: Grayscale
Endianess: Undefined
Colorspace: Gray
Depth: 12/16-bit
Channel depth:
gray: 16-bit
Channel statistics:
Pixels: 2593728
Gray:
min: 0 (0)
max: 319.989 (0.0781415)
mean: 0.0593298 (1.44883e-05)
standard deviation: 2.68324 (0.000655247)
kurtosis: 3867.56
skewness: 57.5931
entropy: 0.00257194
Colormap entries: 4096
Colormap:
Rendering intent: Undefined
Gamma: 0.454545
Background color: gray(255)
Border color: gray(223)
Matte color: gray(189)
Transparent color: gray(0)
Interlace: None
Intensity: Undefined
Compose: Over
Page geometry: 1896x1368+0+0
Dispose: Undefined
Iterations: 0
Compression: JPEG
Quality: 84
Orientation: Undefined
Properties:
comment: ♦
date:create: 2016-01-12T12:53:56-05:00
date:modify: 2016-01-19T16:41:03-05:00
jpeg:colorspace: 1
jpeg:sampling-factor: 1x1
signature: f913f28ee8f54a718a3224d8b097f5cf3086509c6e4229974f4ce8570fd97f6e
Artifacts:
filename: C:\Users\alexander\Desktop\708_885_5856.xdr
verbose: true
Tainted: False
Filesize: 659KB
Number pixels: 2.594M
Pixels per second: 41.2KB
User time: 62.672u
Elapsed time: 1:04.010
Version: ImageMagick 6.9.3-1 Q16 x64 2016-01-19 http://www.imagemagick.org
identify.exe: Invalid colormap index `C:\Users\alexander\Desktop\708_885_5856.xd
r' # error/colormap-private.h/ConstrainColormapIndex/34.
This seems strange to me because identify was able to calculate the statistics for the gray channel, and "Colormap entries" registers as 4096.
When I attempt to use ImageMagick to convert one of these images, I end up with a appropriately sized grey scale image that is 100% black pixels, and I get the "invalid colormap index" message.
C:\libjpeg\ImageMagick-6.9.3-1\VisualMagick\bin>convert.exe -verbose C:\Users\al
exander\Desktop\708_885_5856.xdr C:\Users\alexander\Desktop\output.png
C:\Users\alexander\Desktop\708_885_5856.xdr JPEG 1896x1368 1896x1368+0+0 12-bit
Gray 4096c 659KB 61.844u 1:02.400
C:\Users\alexander\Desktop\708_885_5856.xdr=>C:\Users\alexander\Desktop\output.p
ng JPEG 1896x1368 1896x1368+0+0 16-bit Gray 22c 9.73KB 0.391u 0:00.187
convert.exe: Invalid colormap index `C:\Users\alexander\Desktop\708_885_5856.xdr
' # error/colormap-private.h/ConstrainColormapIndex/34.
The block of code referenced in the "invalid colormap index" error is
static inline IndexPacket ConstrainColormapIndex(Image *image,
const size_t index)
{
if ((index < image->colors) && ((ssize_t) index >= 0))
return((IndexPacket) index);
(void) ThrowMagickException(&image->exception,GetMagickModule(),
CorruptImageError,"InvalidColormapIndex","`%s'",image->filename);
return((IndexPacket) 0);
}
Which seems to make sense, index is coming in > 4095 or < 0.
I'm not very familiar with Visual Studio or c++, so please bear with me.
When I was setting libjpeg to read 12 bit images, I came across a line of code in jdct.h that caught my attention. The middle word "UINT32" on the middle line was underlined in red.
typedef INT32 DCTELEM; /* must have 32 bits */
typedef UINT32 UDCTELEM;
typedef unsigned long long UDCTELEM2;
Visual Studio does not recognize UINT32 as a valid data type.
In the process of getting the project loaded into Visual Studio, I had to "convert" the project from Visual Studio 2010 to Visual Studio 2015. I fear that something got messed up when I "Converted" the project from Visual Studio 2010 to Visual Studio 2015. Or it may be a red herring.
In conclusion, I guess my questions really are:
How can I print the value of index? (like java "System.println.out(index);")
Isn't there something I can include in C & C++ for standard data types like cstd.h or something?
Why do I even need a color map index? If identify can calculate an average for the pixel values, it can obviously read each one, and if it can read each one, why does it fail?
Would obtaining Visual Studio 2010 most likely solve my problem?

The maximum value in your image is only 319 on a 12-bit range, i.e. 319 out of a possible 4095, or just 7% brightness, so your image is dark and will look black.
Try setting the contrast higher like this:
convert "C:\Users\alexander\Desktop\708_885_5856.xdr" -auto-level result.png

Related

How to query true display bit depth under Windows 10?

I'm struggling to find any win32 api call that can correctly identify the bit depth of a connected monitor in terms of bits per channel. The attached screenshot shows the setting visible.
With DXGI it is possible to enumerate all modes on an output and identify their bit depth easily, however there is no call to get the current mode.
All current win32 calls which return bitsPerPel always indicate 32bpp.
Does anybody know which call can get this data? I can detect this with NvAPI and ADL however have no solution for intel based machines.
I would additionally be interested in the active signal resolution vs desktop resolution field and how to retrieve these.
DXGI_OUTPUT_DESC1 structure gets you that:
BitsPerColor
Type: UINT
The number of bits per color channel for the active wire format of the display attached to this output.
…
The DXGI_OUTPUT_DESC1 structure is initialized by the IDXGIOutput6::GetDesc1 method.
Just an example of what sort of data you get there:
--
Adapter: Radeon RX 570 Series
Output: \.\DISPLAY4
Desktop Coordinates: (0, 0) - (3840, 2160); 3840 x 2160
Attached To Desktop: 1
Rotation: DXGI_MODE_ROTATION_IDENTITY
Monitor: 0x000100AF
Physical Monitors: LG ULTRA HD(DisplayPort) (0x00000000)
Bits Per Color: 10 <<----------------------------------
Color Space: DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
Primaries, White Point: R { 0.652, 0.335 }, G { 0.305, 0.637 }, B { 0.148, 0.062 }; { 0.313, 0.329 }
Luminance: Min 0.500, Max 270.000, Max Full Frame 270.000
Hardware Composition Support: DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_FULLSCREEN | DXGI_HARDWARE_COMPOSITION_SUPPORT_FLAG_CURSOR_STRETCHED
In my opinion, the Bit depth in advanced display settings actually means bit depth for each color, it's just a naming confusion. Standard 32 bit color is 8 bits each for red, green, blue, the remaining 8 bits are either used for transparency or are just filled with zeros. That's why you always get 32 bits for each pixel.

Compare rendered images using imagemagick

I have rendered multiple images from an application. Here is sample images that illustrate two images that looks almost the same to the eye .
I try to compare them with the following command in image magick.
compare -metric AE img1.png img2.png diff.png
6384
This means 6384 pixels differ even if the images are similar.
I got minor changes like if a pattern is moved 1 pixel to the right this will give me a large error in number of different pixels. Is there a good way of do this kind of diff with ImageMagick? I have experimented with the fuzz parameter, but it really does not help me. Is ImageMagick compare only suited for comparing photographic images? Are there better switches to ImageMagick that can recognize a text that has moved some pixels and report it as equal? Should I use another tool?
Edit:
Adding an example on a image that looks clearly different for a human and will illustrate the kind of difference I am trying to differentiate. In this image not many pixels are changed, but the visible pattern is clearly changed.
It's hard to give any detailed answer as I don't know what you are looking for or expecting. I guess you may need some sort of Perceptual Hash if you are looking for images that people would perceive as similar or dissimilar, or maybe a Scale/Rotation/Translation Invariant technique that identifies similar images independently of resizes, shifts and rotations.
You could look at the Perceptual Hash and Image Moments with ImageMagick like this:
identify -verbose -features 1 -moments 1.png
Image: 1.png
Format: PNG (Portable Network Graphics)
Mime type: image/png
Class: PseudoClass
Geometry: 103x115+0+0
Resolution: 37.79x37.79
Print size: 2.72559x3.04313
Units: PixelsPerCentimeter
Type: Grayscale
Base type: Grayscale
Endianess: Undefined
Colorspace: Gray
Depth: 8-bit
Channel depth:
gray: 8-bit
Channel statistics:
Pixels: 11845
Gray:
min: 62 (0.243137)
max: 255 (1)
mean: 202.99 (0.79604)
standard deviation: 85.6322 (0.335812)
kurtosis: -0.920271
skewness: -1.0391
entropy: 0.840719
Channel moments:
Gray:
Centroid: 51.6405,57.1281
Ellipse Semi-Major/Minor axis: 66.5375,60.336
Ellipse angle: 0.117192
Ellipse eccentricity: 0.305293
Ellipse intensity: 190.641 (0.747614)
I1: 0.000838838 (0.213904)
I2: 6.69266e-09 (0.00043519)
I3: 3.34956e-15 (5.55403e-08)
I4: 5.38335e-15 (8.92633e-08)
I5: 2.27572e-29 (6.25692e-15)
I6: -4.33202e-19 (-1.83169e-09)
I7: -2.16323e-30 (-5.94763e-16)
I8: 3.96612e-20 (1.67698e-10)
Channel perceptual hash:
Red, Hue:
PH1: 0.669868, 11
PH2: 3.35965, 11
PH3: 7.27735, 11
PH4: 7.05343, 11
PH5: 11, 11
PH6: 8.746, 11
PH7: 11, 11
Green, Chroma:
PH1: 0.669868, 11
PH2: 3.35965, 11
PH3: 7.27735, 11
PH4: 7.05343, 11
PH5: 11, 11
PH6: 8.746, 11
PH7: 11, 11
Blue, Luma:
PH1: 0.669868, 0.669868
PH2: 3.35965, 3.35965
PH3: 7.27735, 7.27735
PH4: 7.05343, 7.05343
PH5: 11, 11
PH6: 8.746, 8.746
PH7: 11, 11
Channel features (horizontal, vertical, left and right diagonals, average):
Gray:
Angular Second Moment:
0.364846, 0.615673, 0.372224, 0.372224, 0.431242
Contrast:
0.544246, 0.0023846, 0.546612, 0.546612, 0.409963
Correlation:
-0.406263, 0.993832, -0.439964, -0.439964, -0.07309
Sum of Squares Variance:
1.19418, 1.1939, 1.19101, 1.19101, 1.19253
Inverse Difference Moment:
0.737681, 1.00758, 0.745356, 0.745356, 0.808993
Sum Average:
1.63274, 0.546074, 1.63983, 1.63983, 1.36462
Sum Variance:
4.43991, 0.938019, 4.46048, 4.46048, 3.57472
Sum Entropy:
0.143792, 0.159713, 0.143388, 0.143388, 0.14757
Entropy:
0.462204, 0.258129, 0.461828, 0.461828, 0.410997
Difference Variance:
0.0645055, 0.189604, 0.0655494, 0.0655494, 0.0963021
Difference Entropy:
0.29837, 0.003471, 0.297282, 0.297282, 0.224101
Information Measure of Correlation 1:
-0.160631, -0.971422, -0.146024, -0.146024, -0.356026
Information Measure of Correlation 2:
0.294281, 0.625514, 0.29546, 0.29546, 0.377679
You could also go on Fred Weinhaus's excellent website (here) and download his script called moments which will calculate the Hu and Maitra moments and see if those will tell you what you want. Basically, you could run the script on each of your images like this:
./moments image1.png > 1.txt
./moments image2.png > 2.txt
and then use your favourite diff tool to see what has changed between the two images you wish to compare.

C++ loading and looping through pixels of an image (JPEG format)

Hello there and thank you for at the very least, trying to help me.
I need to, firstly, load an image and then loop through all pixels of that image and check the color of each pixel.
I have never tried messing around with images or whatnot.
Any help is greatly appreciated.
Thank you.
Looking at the bigger picture, of counting the dots on a dice, I would look at using ImageMagick - with the C++ binding called Magick++ from here
I would be looking at using "Blob Analysis", or "Connected Component Analysis" to count the dots on a dice.
Using this dice...
If I use ImageMagick at the command line like this:
convert dice.png -colorspace gray -threshold 50% \
-define connected-components:verbose=true \
-define connected-components:area-threshold=10 \
-connected-components 8 -auto-level output.png
Output
Objects (id: bounding-box centroid area mean-color):
0: 380x362+0+0 189.6,180.0 103867 srgba(255,255,255,1)
2: 93x92+248+32 293.8,77.5 6743 srgba(0,0,0,1)
4: 92x93+39+241 84.8,286.7 6741 srgba(0,0,0,1)
5: 93x93+248+241 293.8,286.8 6738 srgba(0,0,0,1)
1: 92x92+39+32 84.8,77.5 6736 srgba(0,0,0,1)
3: 93x93+143+136 189.3,182.1 6735 srgba(0,0,0,1)
You can see it has found 5 dots (the first one is actually the whole, white image), and I can put a red box around each dot like this so you can see what it has found:
convert dice.png -stroke red -fill none -strokewidth 1 -draw "rectangle 248,32 341,124" -draw "rectangle 39,241 131,334" -draw "rectangle 248,241 341,334" -draw "rectangle 39,32 131,124" -draw "rectangle 143,136 236,229" result.png
I think you may use OpenCV image processing library. You have a detailed manual for installing for VS2013 here:
OpenCV installation for Visual Studio 2013
After you've installed it. You will get a lot of functions for image processing, including what you are looking for.
For example:
Mat inputImage = imread(filename, CV_LOAD_IMAGE_COLOR);
then:
Cycle through pixels with opencv
One of the methods you could use, is to interpret the file as binary. If you know how to interpret the header part and know what color depth the image has (the header has such info), then it wont be a longshot to just compare binary or hexadecimal color codes - probably hexadecimal since C++ doesnt have a built in binary variable.
if you dont think you can handle binary and need a library to work with, refer to
How do I read JPEG and PNG pixels in C++ on Linux?
EDIT - or just use any image processing libraries such as http://cimg.eu since the objective appears to be interpretation of dice from an image.

How can I store each pixel in an image as a 16 bit index into a colortable?

I have a 2D array of float values:
float values[1024][1024];
that I want to store as an image.
The values are in the range: [-range,+range].
I want to use a colortable that goes from red(-range) to white(0) to black(+range).
So far I have been storing each pixel as a 32 bit RGBA using the BMP file format. The total memory for storing my array is then 1024*1024*4 bytes = 4MB.
This seems very vasteful knowing that my colortable is "1 dimensional" whereas the 32 RGBA is "4 dimensional".
To see what I mean; lets assume that my colortable went from black(-range) to blue(+range).
In this case the only component that varies is clearly the B, all the others are fixed.
So I am only getting 8bits of precision whereas I am "paying" for 32 :-(.
I am therefore looking for a "palette" based file format.
Ideally I would like each pixel to be a 16 bit index (unsigned short int) into a "palette" consisting of 2^16 RGBA values.
The total memory used for storing my array in this case would be: 1024*1024*2 bytes + 2^16*4bytes = 2.25 MB.
So I would get twice as good precision for almost half the "price"!
Which image formats support this?
At the moment I am using Qt's QImage to write the array to file as an image. QImage has an internal 8 bit indexed ("palette") format. I would like a 16 bit one. Also I did not understand from Qt's documentation which file formats support the 8 bit indexed internal format.
Store it as a 16 bit greyscale PNG and do the colour table manually yourself.
You don't say why your image can be decomposed in 2^16 colours but using your knowledge of this special image you could make an algorithm so that indices that are near each other have similar colours and are therefore easier to compress.
"I want to use a colortable that goes from red(-range) to white(0) to black(+range)."
Okay, so you've got FF,00,00 (red) to FF,FF,FF (white) to 00,00,00 (black). In 24 bit RGB, that looks to me like 256 values from red to white and then another 256 from white to black. So you don't need a palette size of 2^16 (16384); you need 2^9 (512).
If you're willing to compromise and use a palette size of 2^8 then the GIF format could work. That's still relatively fine resolution: 128 shades of red on the negative size, plus 128 shades of grey on the positive. Each of a GIF's 256 palette entries can be an RGB value.
PNG is another candidate for palette-based color. You have more flexibility with PNG, including RGBA if you need an alpha channel.
You mentioned RGBA in your question but the use of the alpha channel was not explained.
So independent of file format, if you can use a 256 entry palette then you will have a very well compressed image. Back to your mapping requirement (i.e. mapping floats [-range -> 0.0 -> +range] to [red -> white -> black], here is a 256 entry palette that covers the range red-white-black you wanted:
float entry# color rgb
------ ------- ----- --------
-range 0 00 red FF,00,00
1 01 FF,02,02
2 02 FF,04,04
... ...
... ...
127 7F FF,FD,FD
0.0 128 80 white FF,FF,FF
129 81 FD,FD,FD
... ....
... ...
253 FD 04,04,04
254 FE 02,02,02
+range 255 FF black 00,00,00
If you double the size of the color table to be 9 bits (512 values) then you can make the increments between RGB entries more fine: increments of 1 instead of 2. Such a 9-bit palette would give you full single-channel resolution in RGB on both the negative and positive sides of the range. It's not clear that allocating 16 bits of palette would really be able to store any more visual information given the mapping you want to do. I hope I understand your question and maybe this is helpful.
PNG format supports paletted format up to 8-bits, but should also support grayscale images up to 16-bits. However, 16-bit modes are less used, and software support may be lacking. You should test your tools first.
But you could also test with plain 24-bit RGB truecolor PNG images. They are compressed and should produce better result than BMP in any case.

OpenCV - HSV range of values for tracking red color

Could you please tell me how to what are ranges for Hue, Saturation and Value indices for intense red?
I try to use this values for color tracking and I couldn't find a specific answer via Google.
you can map any color to OpenCV HSV. Actually opencv use 1800 hue cylinder while ideally it is 360, on the orher hand MS paint use 2400 cyllinder.
So to get OpenCV HSV value, simply open MS paint, open mixer, and read the value of HSV, now to map this value into OpenCV HSV multiply it with 180/240.
the range to value for saturation and value is 00-1800
You are the only one who can answer this question, since we don't know your criteria for "intense red". Collect as many samples as you can, some of which you consider intense red and some which are close but just miss the cut. Convert them all to HSL. Study the pattern.
You might put together a small app that has sliders for the H, S, and L parameters and displays a block of color corresponding to the settings. That will tell you your limits very quickly.