QImage Custom Indexed Colors Using setColorTable - c++

In my project I need to convert an image with many colors to one that only uses any of the 144 predetermined colors I set in a custom colorTable.
Here is my code:
QImage convImage(128, 128, QImage::Format_Indexed8);
convImage.setColorCount(144);
convImage.setColorTable(colorTable); //colorTable is a const QVector with 144 qRgb values.
//scaledImage is the source image
convImage = scaledImage.convertToFormat(QImage::Format_Indexed8,Qt::ThresholdDither|Qt::AutoColor);
ui->mapView->setPixmap(QPixmap::fromImage(convImage));
I would expect convImage to only contain colors that exist in the colorTable I created, however it seems to completely ignore the table I set and instead creates it's own unique table with 256 max colors.
I could index everything myself by looping through every pixel and find a way to accurately select a color from the colorTable, but I am wondering if I am just using the colorTable wrong. I couldn't find anything in the documentation that explains why a new table is being created.
Thanks for your time.

Well, ask yourself: how should the convertToFormat() call on scaledImage possibly know about the colortable you applied to convImage? It doesn't know anything about the convImage on the left-hand-side.
Fortunately, there's an overload of convertToFormat that takes a colortable and should do the job:
QImage convImage = scaledImage.convertToFormat (QImage::Format_Indexed8,
colorTable,
Qt::ThresholdDither|Qt::AutoColor);

Related

How do I convert an RGB byte[] slice to an image.Image in go?

A C++ application running in another process passes in a char[] array of three-byte pixels (red, green, blue) to a go program. I've reconstructed this in go as a byte[] slice using cgo, but I'm unsure how to convert to an image. I can pass the width or height as well, if that is needed (I would imagine it would be).
I'm aware of the image.RGBA type, but the documentation seems to imply that those aren't just single-byte-per-color, and that assumes that there is an alpha channel, which my very simplistic bitmap does not have. Would converting the 3 byte values I have into something that works with image.RGBA be a solution? If so, how should I do that?
Alternatively, I could do the conversion in C/C++ before sending the values into a format that go recognizes (jpeg, gif, png). Either way works for my uses, but I don't know how to approach either.
The image package is based on interfaces. Just define a new type with those methods.
Your type's ColorModel would return color.RGBAModel, Bounds - your rectangle's borders, and At - the color at (x, y) that you can compute if you know the image's dimensions.

cimg display rendering black

Using CImg; I'll keep this quick and simple.
CImg<float> i = *spectralImages->at(currentImage);
disp.display(i);
float* f = i.data();
disp is displaying a black image despite the fact that stepping through *(f), *(f+1), *(f+2), etc. is retrieving the correct numbers (255.0, 245.0, etc.)
I've been working on this all day. Is there a quirk with CImg that I'm missing?
EDIT:
Saving the file as a BMP seems to make the correct result, so there's just an issue with drawing it.
If your CImg image contains only a single value, or several equal values, the default display will display them as black images, because of the normalization applied to the pixel values for the display.
As CImg is able to manage any type of images (including float-valued), it always normalize the pixel values in [0,255] for the display (it does not change the pixel value in your object of course, it just normalizes them internally for its display).
So if your image has a single pixel values, the normalization will always result to '0', hence the black image as a result.
That means you probably didn't construct your CImgDisplay disp with the right pixel normalization argument (by default, it is enabled).
disp should be constructed like this :
CImgDisplay disp(100,100,"my display",0);
to disable the default normalization of pixel values.

Cropping an 8-bit bitmap by its palette information

I'm currently using C++ to read my 8-bit bitmap and save off its pixel data and colour table. I currently have my colour table stored in an array:
RGBQUAD* colours;
I was wondering how I would go about finding the nearest unique pixel colour in all directions and cropping the bitmap to that pixel. I'm using C++ without any external libraries.
I would recommend using readily available libraries, like ImageMagick, instead of trying to re-implement that particular wheel.
There's only two reasons why you would implement something already implemented that well elsewhere: 1) Homework, or 2) you think you can actually do significantly better than existing code.
It cannot be 1) because there is no "homework" tag, and it cannot be 2) because you wouldn't have to ask, then...
"nearest unique pixel colour" means nearest in color space? In absolute terms (R/G/B) or human sense? So, given #0002FE wou may find #0000FF in your color table?
The "standard" simple C++ method is std::min_element(), which takes a range and a predicate. In your case, that range is your color table and the predicate is the close-ness to the color you want. E.g. [targetColor](RGBQUAD tableEntry) { return abs(RGBdiff(tableEntry, targetColor)); }

Comparing Sprites?

For a game I'm working on, I'd like to compare two sprites in SFML2, such as with an if() statement. For example, I could have a large 1280x1024 image with one gray pixel among all black pixels. I would then have 2 separate sprites, one is the gray pixel alone, and the other is the map. I would crop only the gray pixel from the map and compare the two, if true, do other things.
Do you see what I'm getting at here? Is this possible? If so, how?
Im with Alex in saying there are smarter ways to check sprites.
Compare the file names not, don't reference a single pixel within an image, because you have to load the entire image into memory to do that atm you are loading 1.3MBytes into memory just to check a single pixel?
Store all of your resources in a Resource Manager and reference them via a UID, if a resource has UID then use that resource.
Number 2 is preferable above all else, but there are many other ways
Edit: As per comments, you wouldn't "crop" out the pixel, you would just load image into memory and use the Image class to get the colour of a pixel at a location. The following would be an example
sf::Image* map = MapSprite->GetTexture()->CopyToImage()
if (map->GetPixel(666,666) == sf::Color::Black)
{
//Funky stuff here
}
NOTE: You mentioned SFML2 so this is from that set of Documentation, may be different for 1.6
Edit2: Its been a while since I've used SMFL so hopefully the code snippet will at least give you direction

Converting image to pixmap using ImageMagic libraries

My assignment is to get "images read into pixmaps which you will then convert to texture maps". So for the pixmap part only, hear me out and tell me if I have the right idea and if there's an easier way. Library docs I'm using: http://www.imagemagick.org/Magick++/Documentation.html
Read in image:
Image myimage;
myimage.read( "myimage.gif" );
I think this is the pixmap I need to read 'image' into:
GLubyte pixmap[TextureSize][TextureSize][3];
So I think I need a loop that, for every 'pixmap' pixel index, assigns R,G,B values from the corresponding 'image' pixel indices. I'm thinking the loop body is like this:
pixmap[i][j][0] = myimage.pixelColor(i,j).redQuantum(void);
pixmap[i][j][1] = myimage.pixelColor(i,j).greenQuantum(void);
pixmap[i][j][2] = myimage.pixelColor(i,j).blueQuantum(void);
But I think the above functions return Quantums where I need GLubytes, so can anyone offer help here?
-- OR --
Perhaps I can take care of both the pixmap and texture map by using OpenIL (docs here: http://openil.sourceforge.net/tuts/tut_10/index.htm). Think I could simply call these in sequence?
ilutOglLoadImage(char *FileName);
ilutOglBindTexImage(ILvoid);
You can copy the quantum values returned by pixelColor(x,y) to ColorRGB and you will get normalized (0.0,1.0) color values.
If you don't have to stick with Magick++ maybe you can try OpenIL, which can load and convert your image to OpenGL texture maps without too much hassle.