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,0
I 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,0
I 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 jsonArr
and in this caseQJsonArray jsonArr
contains// 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
as 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 jsonArr
and in this caseQJsonArray jsonArr
contains// 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
as 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
9
so now i can dofloat p=0,s=1.0/amountPoint;
?