QImage reduce color to nearest indexed palette
-
can someone provide some example code on how to convert an image to raw data and display it?
I have googled around for tutorials but I can't find one.tiletable.h
#ifndef TILETABLE_H #define TILETABLE_H #include <QImage> class TileTable { public: TileTable(); ~TileTable(); unsigned char tiles[65536]; unsigned char pal[256]; QColor cset[16]; unsigned char load_image(QImage *image); }; #endif // TILETABLE_H
tiletable.cpp
#include "tiletable.h" TileTable:: TileTable() { } TileTable::~TileTable() { } unsigned char TileTable::load_image(QImage *file) { QImage image = QImage.load(file); image.convertToFormat(QImage::Format_RGB444); uchar bits = image.bits(); //I'm not sure what to do here. }
-
can someone provide some example code on how to convert an image to raw data and display it?
I have googled around for tutorials but I can't find one.tiletable.h
#ifndef TILETABLE_H #define TILETABLE_H #include <QImage> class TileTable { public: TileTable(); ~TileTable(); unsigned char tiles[65536]; unsigned char pal[256]; QColor cset[16]; unsigned char load_image(QImage *image); }; #endif // TILETABLE_H
tiletable.cpp
#include "tiletable.h" TileTable:: TileTable() { } TileTable::~TileTable() { } unsigned char TileTable::load_image(QImage *file) { QImage image = QImage.load(file); image.convertToFormat(QImage::Format_RGB444); uchar bits = image.bits(); //I'm not sure what to do here. }
@Shadowblitz16 What do you mean by "raw data"? Do you mean RAW as in a digital camera? What do you expect to get?
-
can someone provide some example code on how to convert an image to raw data and display it?
I have googled around for tutorials but I can't find one.tiletable.h
#ifndef TILETABLE_H #define TILETABLE_H #include <QImage> class TileTable { public: TileTable(); ~TileTable(); unsigned char tiles[65536]; unsigned char pal[256]; QColor cset[16]; unsigned char load_image(QImage *image); }; #endif // TILETABLE_H
tiletable.cpp
#include "tiletable.h" TileTable:: TileTable() { } TileTable::~TileTable() { } unsigned char TileTable::load_image(QImage *file) { QImage image = QImage.load(file); image.convertToFormat(QImage::Format_RGB444); uchar bits = image.bits(); //I'm not sure what to do here. }
@Shadowblitz16 mmh, do you want it in a QByteArray?
You could do something like this than:
QImage img; QByteArray bArray; QBuffer buffer(&bArray); buffer.open(QIODevice::WriteOnly); img.save(&buffer, "format");
-
Hello jsulm and j.Hilk
I mean like loading the image and finding the closest colors in the current color set , and converting them into a array of 4 bit indexed pixel data.
so there would be 65536 tiles and each tile would hold a 256 sized array of unsigned chars representing the color of the current palette and color set.
-
Hello jsulm and j.Hilk
I mean like loading the image and finding the closest colors in the current color set , and converting them into a array of 4 bit indexed pixel data.
so there would be 65536 tiles and each tile would hold a 256 sized array of unsigned chars representing the color of the current palette and color set.
I had made a toy project a few months back that does that.
I could upload the source for you somewhere if you're interested.It uses a median cut to get the palette and then "reconstructs" the image by replacing each color with its closest counterpart from the palette. It should be somewhat trivial to adapt it to your needs.Edit:
Source code available here. -
thankyou so much kshegunov I will take a look at this.
however I see that you use the boost library and I seem to not have it.
can you explain where to get it? -
thankyou so much kshegunov I will take a look at this.
however I see that you use the boost library and I seem to not have it.
can you explain where to get it?@Shadowblitz16 For which platform, OS and compiler?
-
thankyou so much kshegunov I will take a look at this.
however I see that you use the boost library and I seem to not have it.
can you explain where to get it?@Shadowblitz16 said in Convert Image to Array based pixel data?:
however I see that you use the boost library and I seem to not have it.
can you explain where to get it?Note that I use only the statistics framework (header-only) so you don't need to compile anything before hand. You just need to point your project file to the boost directory (through the
INCLUDEPATH
variable). Also, since I only use themin
,max
andmean
accumulator extractors from that library you can simply provide your own implementations and not care about includingboost
at all. -
Thankyou kshegunov I will do that
-
@kshegunov I'm not sure if this does what I want.
I'm trying to make my game draw things from pixel data not convert them back into indexed images.
this way I can store the tiledata directly into a json file representing the tiles and there index
here is an example json explaining what format I want my tiles in{ "TILES": [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ...all the way to 65535... [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ] }
EDIT: here is what I got for a loading function so far
QImage TileTable::load_image(QString file, int tilewidth, int tileheight) { QImage image(file); image.convertToFormat(QImage::Format_RGB444); char data[65536]; // need a 2d array here later int len = (image.width / tilewidth) * (image.height / tileheight); for(int i=0; i<len; i++) { int x = i % tile_width; int y = i / tile_height; QImage subImage = image.copy(x,y,tilw_width, tile_height); //Todo convert subImage to to array of palette indexes data[i] = subImage; //temparary I want to eventully store a array of indexed pixels here } }
I just need a way of converting the image
-
@kshegunov I'm not sure if this does what I want.
I'm trying to make my game draw things from pixel data not convert them back into indexed images.
this way I can store the tiledata directly into a json file representing the tiles and there index
here is an example json explaining what format I want my tiles in{ "TILES": [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ...all the way to 65535... [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] ] }
EDIT: here is what I got for a loading function so far
QImage TileTable::load_image(QString file, int tilewidth, int tileheight) { QImage image(file); image.convertToFormat(QImage::Format_RGB444); char data[65536]; // need a 2d array here later int len = (image.width / tilewidth) * (image.height / tileheight); for(int i=0; i<len; i++) { int x = i % tile_width; int y = i / tile_height; QImage subImage = image.copy(x,y,tilw_width, tile_height); //Todo convert subImage to to array of palette indexes data[i] = subImage; //temparary I want to eventully store a array of indexed pixels here } }
I just need a way of converting the image
Well, I have provided sample code for the conversion. If you don't want to save the data back to an image, you need to modify the code and save the index in an array, but I don't really see a big difference so should be easy to adapt.
Instead ofsetPixelColor
used here you just save the index of the palette color in your array, should be as simple as this. -
@kshegunov I see you didn't use the QImage.bits() method like i did can you explain why?
-
@kshegunov I see you didn't use the QImage.bits() method like i did can you explain why?
QImage::bits
returns internal data, thus it requires me to know what is the image's format and data padding (if any). Using the pixel modification API does not, on the other hand. Moreover, as this all boils down to interpolation in RGB space, having a color value represented in other color spaces isn't as useful, because the "finding closest" approximation requires a bit more work. For example if I used CMYK I'd have to use 4D color space, if I were to work in HSV I'd have to calculate distances in cylindrical coordinate system, which while possible makes it more complicated for no good reason. -
thankyou kshegunov however when I add an image and try to reduce its color by lowering the color count it doesn't do anything can you explain why?
-
thankyou kshegunov however when I add an image and try to reduce its color by lowering the color count it doesn't do anything can you explain why?
You mean for my toy application?
The color count should be a power of two, so 16, 32, 64, 128 are valid, but not say 3, 9, 11. -
oh I see why its called color reduction now...
it doesn't index the image it just reduces the color.. -
oh I see why its called color reduction now...
it doesn't index the image it just reduces the color..@Shadowblitz16 said in QImage reduce color to nearest indexed palette:
it doesn't index the image it just reduces the color..
I don't follow, what's the difference?
An index-colored image is a table of colors (again 8, 16, 32 etc. in number) and instead of assigning RGB values directly to the pixels you assign them indices from that table. My toy app does the table, but instead of saving the table and using index-colored format it just uses the colors directly, but it's basically the same principle. If you open the image histogram you'll see only that number of colors that would otherwise be in the color table. -
but it should round the colors to the nearest color on the palette if the palette size isn't big enough to hold all the colors.
-
but it should round the colors to the nearest color on the palette if the palette size isn't big enough to hold all the colors.
-
hmm its not doing it for me.. for example I gave it an image and specified a palette size of 4.
after it was done processing it just recolored parts of the image..EDIT: now it doesn't look like its doing anything.
EDIT2: ok so when I open the file browser to load an image, all my images are listed as paint.net images when they are not.
I think its getting the file extension confused with the default program that opens the file.