How to turn on alpha channel? - graphicsmagick

My English is not good. I apologize and let's go straight to a simple example.
#include <Magick++.h>
int main(int argc, char *argv[])
{
Magick::InitializeMagick(NULL);
Magick::Image *img = new Magick::Image();
img->magick("RGBA");
img->size(Magick::Geometry(150, 150));
img->read("xc:transparent");
img->fillColor(Magick::Color(0x00,0x00,0x00,0xFF));
img->lineWidth(10);
img->strokeColor(Magick::Color(0xFF, 0xAF, 0x00, 0x00));
img->draw(Magick::DrawableCircle(75,75,75,10));
img->write("foo.png");
delete img;
return 0;
}
Here, I tried to draw an orange circle and write the result to a .png file. If you open the .png with GIMP or some other image editor, you might notice that the border of the circle is ugly, especially when you open it as a layer on some other colorful image. The border is not transparent gradually. It uses black color in the position of transparency. Apparently it's using mask not alpha channel. What am I missing here? What method should I call and where? Thanks. :)

Related

How to customize text on Qpushbutton using QPalette?

How to set font, size and color for the Text of QPushButton in Qt5.6.1 using QPalette? As I am curious to know how we can set these properties without using QStyleSheet in Qt. Also how we can set hex code of color in QT.
Please suggest any way to do with QPalette.
Thanks
How to set font, size and color for the Text of QPushButton in Qt5.6.1 using QPalette?
A QPalette contains color groups for each widget state. It does not contain font/size information.
You can use QWidget::setPalette() to change specific color roles (Button, ButtonText, Window. . .), and use QWidget::setFont() to change font family/size. For example:
QPushButton button("Press Me");
//get initial default palette
QPalette pal= button.palette();
//change some color roles
pal.setColor(QPalette::Window, QColor(255, 0, 0)); //red color
pal.setColor(QPalette::Button, QColor(0x00, 0x00, 0xff)); //blue color (hex representation)
pal.setColor(QPalette::ButtonText, QColor(Qt::yellow)); //Qt global color
button.setPalette(pal);
//change font family and size
button.setFont(QFont("Helvetica [Cronyx]", 15, QFont::Bold));
In order for palettes to work properly, you may want to first use Fusion style in the application by calling:
QApplication::setStyle(QStyleFactory::create("Fusion"));
before instantiating the QApplication instance in main() because some styles do not use the palette for all drawing, for instance, if they make use of native theme engines. This is the case for both the Windows XP, Windows Vista, and the OS X styles.
Also, You may want to set the palette/font on the whole application, so that you get those colors in all widgets in the application. Something like this:
#include <QtWidgets>
int main(int argc, char** argv)
{
QApplication::setStyle(QStyleFactory::create("Fusion"));
QPalette pal= QApplication::palette();
pal.setColor(QPalette::Window, QColor(Qt::red));
pal.setColor(QPalette::Button, QColor(Qt::blue));
pal.setColor(QPalette::ButtonText, QColor(Qt::yellow));
pal.setBrush(QPalette::WindowText, QBrush(QColor(Qt::yellow)));
pal.setColor(QPalette::Highlight, QColor(Qt::green));
//further palette customization. . .
QApplication::setPalette(pal);
QApplication::setFont(QFont("Helvetica [Cronyx]", 15, QFont::Bold));
QApplication a(argc, argv);
//setup and show GUI components
return a.exec();
}
I agree with the above mentioned points.
Following is the another approach to achieve the Font Customization with QWidgets.
QPushButton *button3 = new QPushButton("CheckFont", this);
button3->setGeometry(QRect(QPoint(50,50),QSize(200,50)));
QFont FontObj;
FontObj.setFamily(QStringLiteral("Helvetica [Cronyx]"));
FontObj.setPointSize(15);
FontObj.setBold(true);
FontObj.setUnderline(true);
button3->setFont(FontObj);
Also when Color code is in format like "#ffffff" (which is white color code) then you can use following way to set the hex color code with QPalette.
pal.setColor(QPalette::Button, QColor(QRgb("#ffffff")));
OR
pal.setColor(QPalette::Button, QColor("#ffffff"));

Rendering a large QGraphicsScene on a QImage clips it off

I am creating some images rendering the contents of a QGraphicsScene.
My project requirement is that it should handle a canvas size of 10 ft by 8 inches. On screen, and scene size, that is 8640 x 576 pixels.
I can render it fine.
The thing is, the output images need to have 300 resolution.
That means, the rendered image will have a width of 36000, which is over 2^15 - 1 = 32767 pixels.....
The output is clipped - in the code below, I would get a QImage of correct expected size (36000) but the QGraphicsScene only renders to 32767 pixels.
That is confusing... I cannot explain the outcome - if the QImage limitations were 32767 pixels, then I should not be able to create one in the first place. But I checked and the QImage "sanity check" is much higher.
Once the image is created, I do not see anything in the code for rendering QGraphicsScene that would clip at any value....
This is a simple code that is trying to expose my problem.
It creates a QImage of required size, and fills with yellow (for control).
Then it renders a QGraphicsScene with blue background brush and a red rectangle close to the right margin.
If it works correctly, the result should be: an image of width 36000, blue with a tiny red rectangle at the far right.
But... as it is, the result is an image of width 36000, blue for the first 32766 pixels then yellow for the rest, no red rectangle.
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <QPainter>
void printScene(QGraphicsScene* s, qreal ratio) {
qreal w = s->width() * ratio;
qreal h = s->height() * ratio;
QRectF target(0, 0, w, h);
QImage image = QImage(w, h, QImage::Format_ARGB32_Premultiplied);
image.fill(QColor(Qt::yellow).rgb());
QPainter painter;
painter.begin(&image);
s->render(&painter, target);
painter.end();
image.save("image.png");
}
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene s;
s.setSceneRect(0, 0, 8640, 576);
s.setBackgroundBrush(Qt::blue);
QGraphicsView view(&s);
view.show();
QGraphicsRectItem* r = s.addRect(8530, 250, 100, 100);
r->setBrush(Qt::red);
qreal ratio = 300/72.;
printScene(&s, ratio);
return app.exec();
}
As seen in sample images, the QImage is created successfully, QGraphicsScene though only renders to 2^15 - 1... But I stepped through their code and I didn't see it stop....
(I also tried creating the original scene 36000 x something (and setting the ratio to 1), and it displays fine... it just won't render to QImage anything beyond 32767 pixels)
Am I missing some setting ? What could be the cause of the QGraphicsScene::render() to not render more ?
I would love to find out how I can render the size I want - width of 36000 pixels - or a reason why this is not possible.
I am running this in Windows 7, 32 bit Qt 5.5.1 or 4.7.4
I have found the reason for the clipping - and imagined 2 workarounds.
Why:
Stepping through the rendering code, the clip rect gets limited to 32767:
bool QRasterPaintEngine::setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op)
{
Q_D(QRasterPaintEngine);
QRect clipRect = r & d->deviceRect;
...
}
Where deviceRect is set by
void QRasterPaintEnginePrivate::systemStateChanged()
{
deviceRectUnclipped = QRect(0, 0,
qMin(QT_RASTER_COORD_LIMIT, device->width()),
qMin(QT_RASTER_COORD_LIMIT, device->height()));
QRegion clippedDeviceRgn = systemClip & deviceRectUnclipped;
deviceRect = clippedDeviceRgn.boundingRect();
baseClip->setClipRegion(clippedDeviceRgn);
...
}
and
// This limitations comes from qgrayraster.c. Any higher and
// rasterization of shapes will produce incorrect results.
const int QT_RASTER_COORD_LIMIT = 32767;
Options:
1) Render to a max of 32767 and, if the target must be bigger, scale result. (should give slightly lower quality)
2) Create 2 images and combine them (I still need to figure that out but I think it is the better fix)

Qt drawing icons using color and alpha-map

I would like to draw icons (only one color) in different colors. To do so, I would like to import a single alpha-texture and then combine this with a given color in the application.
The result should be, that nothing is drawn on to the background, when the alpha-map has an opacity of 0 and the used color should be drawn, when the opacity is 1.
One soulution should be hidden somewhere in QPainter, since you can manually set the Composition-Mode (QPainter::setCompositionMode). But I don't get it to work like I want.
Does somebody have an idea?
Thanks in advance.
EDIT: Here is a little graphic explaining what I would like to do. I want to use a Alpha-Map like shown in the graphic and then use a color layer to create my icon. Important is, that the background stays transparent.
You can do thos using QPainter like this:
QColor color;
// set color value
// load gray-scale image (an alpha map)
QPixmap pixmap = QPixmap(":/images/earth.png");
// initialize painter to draw on a pixmap and set composition mode
QPainter painter(&pixmap);
painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
painter.setBrush(color);
painter.setPen(color);
painter.drawRect(pixmap.rect());
// Here is our new colored icon!
QIcon icon = QIcon(pixmap);
Here is gray-scale image and two colored icons which i get using the code above (QPixmap.save() method):
icons
The DestinationIn composition mode will do the trick.
Draw the color layer using the default composition mode of SourceOver.
Draw the alpha layer using the DestinationIn composition mode.
For example:
// https://github.com/KubaO/stackoverflown/tree/master/questions/alpha-mask-24943711
#include <QtWidgets>
QImage icon(int size) {
QImage image{size, size, QImage::Format_ARGB32_Premultiplied};
image.fill(Qt::transparent);
QPainter p(&image);
p.setRenderHint(QPainter::Antialiasing);
p.setPen(Qt::NoPen);
p.translate(image.rect().center());
p.scale(image.width()/2.2, image.height()/2.2);
p.setBrush(Qt::white);
p.drawEllipse(QRectF{-.5, -.5, 1., 1.});
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.setBrush(Qt::transparent);
p.drawEllipse(QRectF{-.3, -.3, .6, .6});
for (auto angle : {0., 100., 150.}) {
p.save();
p.rotate(angle);
p.drawRect(QRectF{-.1, 0, .2, -1.});
p.restore();
}
return image;
}
QImage checkers(int size) {
QImage img{size*2, size*2, QImage::Format_ARGB32_Premultiplied};
QPainter p(&img);
p.fillRect(0, 0, size, size, Qt::darkGray);
p.fillRect(size, size, size, 2*size, Qt::darkGray);
p.fillRect(size, 0, size, size, Qt::lightGray);
p.fillRect(0, size, size, size, Qt::lightGray);
return img;
}
void drawColorIcon(QPainter & p, QColor color, const QImage & alpha)
{
p.save();
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
p.fillRect(QRect{0, 0, alpha.width(), alpha.height()}, color);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.drawImage(0, 0, alpha);
p.restore();
}
QImage drawColorIconProof(QColor color, const QImage & alpha) {
QImage result{alpha.size(), alpha.format()};
QPainter p(&result);
drawColorIcon(p, color, alpha);
p.setCompositionMode(QPainter::CompositionMode_DestinationAtop);
p.fillRect(alpha.rect(), {checkers(10)});
return result;
}
int main(int argc, char *argv[])
{
QApplication app{argc, argv};
QLabel label;
label.setPixmap(QPixmap::fromImage(drawColorIconProof("orangered", icon(200))));
label.show();
return app.exec();
}
I found a solution. However, instead of using a transparent graphic for the alpha map like I've used in the first post, I had to use a black/white-graphic where black pixels are transparent and white pixels are not (=rendered).
// ++++ in constructor ++++
QImage alphaMap = QImage(fileName);
QColor color;
// ++++ in paint Event ++++
QPainter painter(this);
painter.setRenderHints(QPainter::RenderHint::Antialiasing);
painter.setRenderHints(QPainter::RenderHint::HighQualityAntialiasing);
// draw icon
QImage renderedIcon(alphaMap);
// fill with color
renderedIcon.fill(color);
// set alpha-map, black pixels -> opacity of 0, white pixels -> opacity 1
renderedIcon.setAlphaChannel(alphaMap);
painter.drawImage(this->rect(), renderedIcon); // draw image to QWidget
I do not quite understand the problem, but may be you can use QGraphicsColorizeEffect class? QGraphicsColorizeEffect

QT change QImage alpha

I need to change the alpha of a QImage I have so it blends with the other QImages behind and infront of it. This needs to be toggled quickly on and off.
Previously I've had to recreate every single image and give them new colors with just a different alpha value. But now I want to retain that same original image instead of redrawing and painting it.
I'm trying to do it like this now:
QImage image;
unsigned int rgb;
for(int y=0;y<image.height();y++){
for(int x=0;x<image.width();x++){
rgb=image.pixel(x,y);
image.setPixel(x,y,qRgba(qRed(rgb),qGreen(rgb),qRed(rgb),120));
}
}
I'm getting some fairly unpredictable behavior. When I toggle the image sometimes I lose colors or the alpha isn't changed. And if the alpha did get changed when I toggle back (I hardcode the alpha 255 elsewhere instead of 120) it doesn't go back to normal.
This doesn't seem like the right way to do this anyways, it shouldn't be this difficult. It seems like there should be a single function call on an image to change the alpha but I haven't found one yet.
If you are using the QImage in QGraphicsView or in some other QWidget, you should look into this QGraphicsEffect:
http://qt-project.org/doc/qt-4.8/qgraphicsopacityeffect.html
http://doc-snapshot.qt-project.org/4.8/qwidget.html#setGraphicsEffect
http://doc-snapshot.qt-project.org/4.8/qgraphicsitem.html#setGraphicsEffect
If you are using a QLabel, I would try this out:
#include <QLabel>
#include <QPainter>
class TransparentQLabel : public QLabel
{
Q_OBJECT
public:
explicit TransparentQLabel() : QLabel() {}
~TransparentQLabel(){}
void setOpacity(const qreal & val)
{
if (this->pixmap() == null || this->pixmap().isNull())
return;
QPixmap result(this->pixmap()->size());
result.fill(Qt::transparent);
QPainter painter;
painter.begin(&result);
painter.setOpacity(val);
painter.drawPixmap(0, 0, *(this->pixmap()));
painter.end();
QLabel::setPixmap(result);
}
};
This next bit is only slightly related to your question, but it is nice to know. If you are layering outside of your QApplication onto the operating system, you need some things like this:
this->setWindowFlags( Qt::WindowStaysOnTopHint |
Qt::FramelessWindowHint | Qt::Tool);
this->setAttribute(Qt::WA_TranslucentBackground, true);
this->setAttribute (Qt::WA_TransparentForMouseEvents, true);
Here is an example of this stuff in action:
http://qt-project.org/wiki/QSplashScreen-Replacement-for-Semitransparent-Images
Hope that helps.

Draw text in QGLWidget when using raw OpenGL

I am writing Qt app that wraps an external 3D engine.I use QGLWidget to encapsulate the engine API.I don't use any Qt GL API methods though I do create GL context using Qt API:
QGLFormat format;
format.setProfile(QGLFormat::CompatibilityProfile);
format.setVersion(4,2);
format.setDoubleBuffer(true);
format.setSwapInterval(1);
Now,I was searching for a way to draw text in the viewport and found Qt's rendeText().
I have tried to use it but no text is begin drawn.
That is how I do it:
qglColor(Qt::black);
this->renderText(50, 50, "Some text");
What do I miss here?
Btw, my depth buffer is off.
I use the following method to draw text in my OpenGL widgets:
void myGL_Widget::OGL_Draw_Text(QString text,float x,float y, float z, float red, float green, float blue)
{
glPushMatrix();
glColor3f(red, green, blue);
renderText(x, y, z, text);
glPopMatrix();
}

Resources