Plotting a graph over a QPixmap using QPainter - c++

I need to plot a real time graph keeping the background an image. Let's say I am plotting the graph with a red color.
But the logic I use for plotting is drawing small lines using painter.drawline, where painter is a pixmap painter. Then I am constantly drawing this pixmap using a painter to parent widget on a timer timeout() event. So it appears the updated Image (which is the graph) gets plotted in the Gui.
The pixmap is black in background and plotting pen color is red, So when it reaches the end of screen width, I have to start drawing the graph from position 0, but from the second cycle onwards I have to fill the previously drawn pixels (not the entire pixmap, just a rect of width few pixels and height, height of pixmap) with black color.
But now I need to keep a background image, and draw a graph over it. So the fillling with black color doesn't do, as I have to keep a background an image. So how can I plot a graph over an image like aforementioned?
Is there any way to blend two images such that the pixels only having a particular color (red) in source image is blended/replaced with corresponding pixels in destination image?

Keep previously drawed Ys in memory than fill exactly the same pixels by corresponding background. It's faster and much more reliable.

Related

How to save a QImage with transparency?

I want to create a PNG image with transparency.
QImage image(dim, dim, QImage;;Format_ARGB32);
And I set the
qRgba(qRed, qGreen, qBlue, alpha)
But the alpha channel does not modify the transparency/opacity of the color, instead modify the intensity color (from white to color).
Thus, how can I set the transparency of the QImage (which I save on file)?
I have to use QImage, no other stuff.
How do you expect to see the transparency? Ordinary image viewers like photo viewers in Windows and Linux are painting the image on a white canvas. That's why the transparent pixels are being blended with white color. Look at the pictures below :
White background with no transparency on the circle:
The same circle with 50% opacity on white background:
The circle with transparency on a grid background:
That is why advanced image editors like Photoshop, are using such canvas as their default background.

How to erase cv::circle from display window

I use OpenCV library for drawing circles on image.
I need to erase last circle which was drawn on window by clicking on right button click.
Currently, I wrote workaround, I replace red circle by white.
but seems there is another solution such as erase it.
How I can update my UI?
std::vector<Point2f> right_image; // stores 4 points that the user clicks(mouse left click) in the main image.
if (e == EVENT_RBUTTONDOWN && right_image.size() > 0) {
float x0 = right_image[right_image.size()-1].x;
float y0 = right_image[right_image.size()-1].y;
cv::circle(dispImg, cv::Point(x0, y0), 10, cv::Scalar(255, 255, 255), 3);
cv::imshow(cv::String(fullWindowName), dispImg);
right_image.pop_back();
}
It will be faster to store image without any overlays, and redraw circles each frame. If you want to append, move or delete circle just remove it from the list of objects to plot.
If you are developing a raster drawing program you could implement a simple undo. You would have to use an off-screen image (dispImg) and a smaller 'undo' image. Before drawing the circle on the off-screen image, save the part of the image that will be occupied by the new circle into a new, smaller image. You must also save the position of the image. Then when you want to erase the circle, copy the saved image back to the off-screen image to the position that was saved along with the undo image. Finally, draw the off-screen image to the window (imshow).
You could extend this to multiple levels of undo, assuming you have enough memory.
If your program is a vector drawing program, a display list like the one suggested by Andrey is a better option.

How to set a "plain" or "flat" background color for a QTableWidgetItem

I have a QTableWidget. I want to have alternating background colors for the rows, but I can't use QTableWidget::setAlternatingRowColors because I need one color for two rows and the other one for the next two and so on (see the below image).
Thus, when I add a QTableWidgetItem, I set the according background color manually by QTableWidgetItem::setBackground().
But I don't get a "flat" or "plain" background by this, but a gradient and rounded corners:
I would like to have the background color all over the cells, without further "decoration". How can I get rid of this?
When you select a single color as the background (QBrush constructed from a QColor), the style engine tries to render a styled background, which in your case draws this gradient with border.
You can trick the style engine by using a QBrush constructed from a QImage, so the render engine draws exactly that image and nothing more. In your case, use an image with a single pixel, namely the color you want as the background. For this, construct a 1x1-sized QImage and set the color of the pixel using fill, then use that image as a brush:
// Create the image (using the default image format)
QImage img(QSize(1, 1), QImage::Format_ARGB32_Premultiplied);
// Set the color, here light gray:
img.fill(QColor(224, 224, 224));
// Apply the image as the background for the item:
item->setBackground(QBrush(img));

TTF_RenderTextSolid() returns a Surface with 1 byte per pixel?

This code:
TTF_Font * titania = TTF_OpenFont( "chintzy.ttf",28);
SDL_Color textColor = {255,255,0};
SDL_Surface * textSurface = TTF_RenderText_Solid(titania,"Its Working!",textColor);
std::cout << (int)textSurface->format->BytesPerPixel;
Prints the number one, meaning that the surface returned by TTF_RenderTextSolid has one byte per pixel. If I am correct it should be 4 bytes per pixel. Does anyone know why this is happening?
Looks like it's doing exactly what the documentation says it ought to:
Solid
Create an 8-bit palettized surface and render the given text at fast quality with the given font and color. The pixel value of 0 is the colorkey, giving a transparent background when blitted. Pixel and colormap value 1 is set to the text foreground color. This allows you to change the color without having to render the text again. Palette index 0 is of course not drawn when blitted to another surface, since it is the colorkey, and thus transparent, though its actual color is 255 minus each of the RGB components of the foreground color. This is the fastest rendering speed of all the rendering modes. This results in no box around the text, but the text is not as smooth. The resulting surface should blit faster than the Blended one. Use this mode for FPS and other fast changing updating text displays.
If you want 32bpp you need to use the *_Blended() variants:
Blended
Create a 32-bit ARGB surface and render the given text at high quality, using alpha blending to dither the font with the given color. This results in a surface with alpha transparency, so you don't have a solid colored box around the text. The text is antialiased. This will render slower than Solid, but in about the same time as Shaded mode. The resulting surface will blit slower than if you had used Solid or Shaded. Use this when you want high quality, and the text isn't changing too fast.
Self Answer:
TTF_RenderTextSolid() returns a surface in false color. This means that it is kind of like black and white but white is a color you have defined and black is just the opposite of that color (which is usually completely transparent). It can be changed into a regular surface by using SDL_ConvertSurface.

"Lantern effect" or show only a part of a scene

I'm trying to show only a part of a background image (game scenenario in the future). The basic way to work is for example, first I draw a background image, after that i need to "hide"/cover the image with some dark or darness (no light, don't know what option must be chosen) and use the mouse click to using a circle or a triangle (my options) show only the part of the image background over with the circle/triangle centered on mouse position. I called this "lantern effect".
First Option: Play with the alpha channel, creating a an square covering all the window size and after that trying to substract the circle area over the alpha square over the image.
Second Option: Play again with a black square covering all the image background and trying to substract a circle/triangle. Try with glLogicOp but this method only plays mixing colors. Don't know how to do operation with 2D polygons with OpenGL.
...
Any other idea or easy example to learn how to do something similar.
Image example:
That's quite easy to achieve actually:
Create black texture with your lantern light shape in Alpha channel. (Texture could be animated)
Render background.
Render Lantern texture centered at your in-game mouse cursor.
Render black padding around the lantern texture to hide everything around till screen edges.
There's no need to use any special blending modes, just an overlay.