Make a palette image from palette data
-
Code
QImage MainWindow::createPaletteImage(QJsonArray jsonArr) { // Make image here } void MainWindow::checkForNewPalettes() { QFile file(save_path + data_folder + palette_json); QByteArray jsonArray; if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { jsonArray = file.readAll(); file.close(); } QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(jsonArray, &error); QJsonObject object = doc.object(); QJsonArray value = object.find("Palettes")->toArray(); for (auto v : value) { QString paletteName = v.toObject().value("Name").toString(); QString paletteImage = v.toObject().value("imageURL").toString(); QJsonArray palettePalette = v.toObject().value("palette").toArray(); if ( paletteImage.size() == 0) { QImage img; img = createPaletteImage(palettePalette); // Save the image to palette folder (using the name "paletteName") // Update the URL to img "paletteImage" to the json file // Done } } }Json file
{ "Palettes": [ { "Name": "Rainbow", "imageURL": "", "palette": [ 0, 255, 0, 0, 32, 171, 85, 0, 64, 171, 171, 0, 96, 0, 255, 0, 128, 0, 171, 85, 160, 0, 0, 255, 192, 85, 0, 171, 224, 171, 0, 85, 255, 255, 0, 0 ] } ] }To clarify
// Position (X), Red, Green, Blue 0, 255, 0, 0, 32,171,85,0, 64,171,171,0, 96,0,255,0, 128,0,171,85, 160,0,0,255, 192,85,0,171, 224,171,0,85, 255,255,0,0I have never touched QImage, QPainter, QPen nor QLinearGradient so would be great with some help to this
-
Don't paste my code as this !
QLinearGradient gradient = QLinearGradient(0,0, rect().width(), 0);should be the image width no ?
@mpergand oh yea! now it worked :) thank you all
here is the working code and the solution
QImage MainWindow::createPaletteImage(QJsonArray jsonArr) { int width = 500; int height = 26; QImage image(width, height, QImage::Format_RGB32); image.fill(Qt::white); QPainter painter(&image); int amountPoint; amountPoint = jsonArr.count()/4; float p=0,s=1.0/(amountPoint-1); QLinearGradient gradient = QLinearGradient(0,0, width, 0); for (int p = 0; p < amountPoint; p++) { int pos=jsonArr[p*4].toInt(); int r=jsonArr[p*4+1].toInt(); int g=jsonArr[p*4+2].toInt(); int b=jsonArr[p*4+3].toInt(); gradient.setColorAt(pos/255.0, QColor(r,g,b)); } painter.fillRect(rect(),QBrush(gradient)); return image; } -
Code
QImage MainWindow::createPaletteImage(QJsonArray jsonArr) { // Make image here } void MainWindow::checkForNewPalettes() { QFile file(save_path + data_folder + palette_json); QByteArray jsonArray; if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { jsonArray = file.readAll(); file.close(); } QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(jsonArray, &error); QJsonObject object = doc.object(); QJsonArray value = object.find("Palettes")->toArray(); for (auto v : value) { QString paletteName = v.toObject().value("Name").toString(); QString paletteImage = v.toObject().value("imageURL").toString(); QJsonArray palettePalette = v.toObject().value("palette").toArray(); if ( paletteImage.size() == 0) { QImage img; img = createPaletteImage(palettePalette); // Save the image to palette folder (using the name "paletteName") // Update the URL to img "paletteImage" to the json file // Done } } }Json file
{ "Palettes": [ { "Name": "Rainbow", "imageURL": "", "palette": [ 0, 255, 0, 0, 32, 171, 85, 0, 64, 171, 171, 0, 96, 0, 255, 0, 128, 0, 171, 85, 160, 0, 0, 255, 192, 85, 0, 171, 224, 171, 0, 85, 255, 255, 0, 0 ] } ] }To clarify
// Position (X), Red, Green, Blue 0, 255, 0, 0, 32,171,85,0, 64,171,171,0, 96,0,255,0, 128,0,171,85, 160,0,0,255, 192,85,0,171, 224,171,0,85, 255,255,0,0I have never touched QImage, QPainter, QPen nor QLinearGradient so would be great with some help to this
@Kris-Revi
I would start with a new QImage using the constructor
QImage::QImage(const QSize &size, QImage::Format format)Then you can call fill to fill with a background color.
Then you attach a QPainter to it like so:QPainter painter(&image);And then you can use functions like QPainter::drawRectangle to paint color samples where you want them.
When you are done painting, you can use QImage::save to write it to a file.
-
@Kris-Revi
I would start with a new QImage using the constructor
QImage::QImage(const QSize &size, QImage::Format format)Then you can call fill to fill with a background color.
Then you attach a QPainter to it like so:QPainter painter(&image);And then you can use functions like QPainter::drawRectangle to paint color samples where you want them.
When you are done painting, you can use QImage::save to write it to a file.
QImage MainWindow::createPaletteImage(QJsonArray jsonArr) { int width = 500; int height = 26; QImage image(width, height, QImage::Format_RGB32); image.fill(Qt::white); QPainter painter(&image); }so far so good? but dont i have to use QLinearGradient?
-
I don't fully understand how your palette image should look like.
If you'd like to have a gradient, you can apply a QLinearGradient to the QBrush, which you set as active brush on QPainter (QPainter::setBrush) before you draw the rectangle -
I don't fully understand how your palette image should look like.
If you'd like to have a gradient, you can apply a QLinearGradient to the QBrush, which you set as active brush on QPainter (QPainter::setBrush) before you draw the rectangleThis is how it is supposed to look :)

from this
// Position (X), Red, Green, Blue 0, 255, 0, 0, 32,171,85,0, 64,171,171,0, 96,0,255,0, 128,0,171,85, 160,0,0,255, 192,85,0,171, 224,171,0,85, 255,255,0,0 -
This is how it is supposed to look :)

from this
// Position (X), Red, Green, Blue 0, 255, 0, 0, 32,171,85,0, 64,171,171,0, 96,0,255,0, 128,0,171,85, 160,0,0,255, 192,85,0,171, 224,171,0,85, 255,255,0,0@Kris-Revi
Gradients only do linear interpolation between colors. Not sure whether this yields the result you like. Try what happens, if you don't like the result, I would fall back to drawing vertical lines from left to right, each with the correct color. -
@Kris-Revi
Gradients only do linear interpolation between colors. Not sure whether this yields the result you like. Try what happens, if you don't like the result, I would fall back to drawing vertical lines from left to right, each with the correct color.@Asperamanca am i in the ballpark here or?
QImage MainWindow::createPaletteImage(QJsonArray jsonArr) { int width = 500; int height = 26; QImage image(width, height, QImage::Format_RGB32); image.fill(Qt::white); for (int i = 0; i < jsonArr.size(); i++) { for (int h = 0; h < height; ++h) { QPainter painter(&image); QLinearGradient gradient; gradient = QLinearGradient(i, h, width, height); gradient.setColorAt(0.0, QColor(0,0,0,255)); painter.setBrush(QBrush(gradient)); } } } -
@Asperamanca am i in the ballpark here or?
QImage MainWindow::createPaletteImage(QJsonArray jsonArr) { int width = 500; int height = 26; QImage image(width, height, QImage::Format_RGB32); image.fill(Qt::white); for (int i = 0; i < jsonArr.size(); i++) { for (int h = 0; h < height; ++h) { QPainter painter(&image); QLinearGradient gradient; gradient = QLinearGradient(i, h, width, height); gradient.setColorAt(0.0, QColor(0,0,0,255)); painter.setBrush(QBrush(gradient)); } } }@Kris-Revi
Never used gradients myself, so I would try and see. But I think you'd need to set at least 2 colors to make it a gradient. -
@Kris-Revi
Never used gradients myself, so I would try and see. But I think you'd need to set at least 2 colors to make it a gradient.@Asperamanca well hmmm i will wait and see if anyone else respons to this that has used QLinearGradient then :)
-
@Kris-Revi
Never used gradients myself, so I would try and see. But I think you'd need to set at least 2 colors to make it a gradient.@Asperamanca just tested this code
QImage MainWindow::createPaletteImage(QJsonArray jsonArr) { int width = 500; int height = 26; QImage image(width, height, QImage::Format_RGB32); image.fill(Qt::white); for (int i = 0; i < jsonArr.size(); i++) { for (int h = 0; h < height; ++h) { QPainter painter(&image); QLinearGradient gradient; gradient = QLinearGradient(i, h, width, height); gradient.setColorAt(0.0, QColor(0,0,0,255)); painter.setBrush(QBrush(gradient)); } } return image; } void MainWindow::checkForNewPalettes() { QFile file(save_path + data_folder + palette_json); QByteArray jsonArray; if ( file.open(QIODevice::ReadOnly | QIODevice::Text) ) { jsonArray = file.readAll(); file.close(); } QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(jsonArray, &error); QJsonObject object = doc.object(); QJsonArray value = object.find("Palettes")->toArray(); for (auto v : value) { QString paletteName = v.toObject().value("Name").toString(); QString paletteImage = v.toObject().value("imageURL").toString(); QJsonArray palettePalette = v.toObject().value("palette").toArray(); if ( paletteImage.size() == 0) { qDebug() << "Found a palette that has no image"; QImage img; qDebug() << "Creating Image"; img = createPaletteImage(palettePalette); qDebug() << "Image Created, now saving it!"; img.save(save_path + palette_folder + "/" + paletteName + ".jpg"); // Save the image to palette folder (using the name "paletteName") // Update the URL to img "paletteImage" to the json file // Done } qDebug() << "DONE!"; } }this creates Rainbow.jpg with a white background and the right dimensions
int width = 500; int height = 26;but no rainbow palette gradient
-
classic rainbow like the above image:
float p=0,s=1.0/6; QLinearGradient gradient = QLinearGradient(0,0, rect().width(), 0); gradient.setColorAt(p, QColor(255,0,0)); // red gradient.setColorAt(p+=s, QColor(255,255,0)); // yellow gradient.setColorAt(p+=s, QColor(0,255,0)); // green gradient.setColorAt(p+=s, QColor(0,255,255)); // cyan gradient.setColorAt(p+=s, QColor(0,0,255)); // blue gradient.setColorAt(p+=s, QColor(255,0,255)); // magenta gradient.setColorAt(p+=s, QColor(255,0,0)); // red painter.fillRect(rect(),QBrush(gradient));from your data:
float p=0,s=1.0/8; QLinearGradient gradient = QLinearGradient(0,0, rect().width(), 0); gradient.setColorAt(p, QColor(255,0,0)); gradient.setColorAt(p+=s, QColor(171,85,0)); gradient.setColorAt(p+=s, QColor(171,171,0)); gradient.setColorAt(p+=s, QColor(0,255,0)); gradient.setColorAt(p+=s, QColor(0,171,85)); gradient.setColorAt(p+=s, QColor(0,0,255)); gradient.setColorAt(p+=s, QColor(85,0,171)); gradient.setColorAt(p+=s, QColor(171,0,85)); gradient.setColorAt(p+=s, QColor(255,0,0)); painter.fillRect(rect(),QBrush(gradient));
-
classic rainbow like the above image:
float p=0,s=1.0/6; QLinearGradient gradient = QLinearGradient(0,0, rect().width(), 0); gradient.setColorAt(p, QColor(255,0,0)); // red gradient.setColorAt(p+=s, QColor(255,255,0)); // yellow gradient.setColorAt(p+=s, QColor(0,255,0)); // green gradient.setColorAt(p+=s, QColor(0,255,255)); // cyan gradient.setColorAt(p+=s, QColor(0,0,255)); // blue gradient.setColorAt(p+=s, QColor(255,0,255)); // magenta gradient.setColorAt(p+=s, QColor(255,0,0)); // red painter.fillRect(rect(),QBrush(gradient));from your data:
float p=0,s=1.0/8; QLinearGradient gradient = QLinearGradient(0,0, rect().width(), 0); gradient.setColorAt(p, QColor(255,0,0)); gradient.setColorAt(p+=s, QColor(171,85,0)); gradient.setColorAt(p+=s, QColor(171,171,0)); gradient.setColorAt(p+=s, QColor(0,255,0)); gradient.setColorAt(p+=s, QColor(0,171,85)); gradient.setColorAt(p+=s, QColor(0,0,255)); gradient.setColorAt(p+=s, QColor(85,0,171)); gradient.setColorAt(p+=s, QColor(171,0,85)); gradient.setColorAt(p+=s, QColor(255,0,0)); painter.fillRect(rect(),QBrush(gradient));
@mpergand yes but how would that work in my code? you setup all the points manualy here
i need to go through
QJsonArray jsonArrand in this caseQJsonArray jsonArrcontains// Position (X), Red, Green, Blue 0, 255, 0, 0, 32,171,85,0, 64,171,171,0, 96,0,255,0, 128,0,171,85, 160,0,0,255, 192,85,0,171, 224,171,0,85, 255,255,0,0as this is the default but i plan to add more palettes to the json so it can be bigger (more points) or less but always 0 (start) and 255 (end) point but there could be many points in between
-
@mpergand yes but how would that work in my code? you setup all the points manualy here
i need to go through
QJsonArray jsonArrand in this caseQJsonArray jsonArrcontains// Position (X), Red, Green, Blue 0, 255, 0, 0, 32,171,85,0, 64,171,171,0, 96,0,255,0, 128,0,171,85, 160,0,0,255, 192,85,0,171, 224,171,0,85, 255,255,0,0as this is the default but i plan to add more palettes to the json so it can be bigger (more points) or less but always 0 (start) and 255 (end) point but there could be many points in between
-
As you can see in my example, you need to define a step variable base of the number of points.
float step=1.0/(points-1) -
jsonArr.count() ?
As the first param in the json array defines the point position, you need to convert the range 0-255 to 0.0-1.0
@mpergand but would that not count every int in the array? :S
{ "Palettes": [ { "Name": "Rainbow", "imageURL": "", "palette": [ 0, 255, 0, 0, 32, 171, 85, 0, 64, 171, 171, 0, 96, 0, 255, 0, 128, 0, 171, 85, 160, 0, 0, 255, 192, 85, 0, 171, 224, 171, 0, 85, 255, 255, 0, 0 ] } ] } -
int amountPoint; amountPoint = jsonArr.count()/4;gives
9so now i can dofloat p=0,s=1.0/amountPoint;?