Qt : Smooth a circular mask. Remove Jagged edges - c++

I am currently doing the following for putting a circular mask on my image. As a result only circular region of my image is displayed.This works fine however the image tends to have jagged edges (border). Any suggestion on how I could do this.

From the documentation of QPixmap you can learn:
The hasAlpha(), setMask() and mask() functions are legacy and should not be used. They are potentially very slow.
Apart from being slow, they operate on a binary mask (QBitmap) which does not support anti-aliasing, each pixel is either fully opaque or fully transparent. This results in jagged edges.
The solution is to manipulate the alpha channel of the pixmap directly. However, you cannot use drawing operations on a pixmap. Instead, you need to draw on the QImage before converting it via QPixmap::fromImage().
With this method, the alpha channel you manipulate has 8 bits (instead of 1) which allows antialiasing. At the edges you will find a smooth transition between fully opaque and fully transparent.
So to draw the alpha in the original QImage:
Make sure that it actually has an alpha channel, e.g. by calling img.convertToFormat(QImage::Format_ARGB32);
Initialize your QPainter on img as paint device
Set the DestinationIn composition mode on the painter; see http://qt-project.org/doc/qt-4.8/qpainter.html#CompositionMode-enum
Perform the drawEllipse operation with a white brush of a certain alpha.

I think the easiest way is:
oImage.convertToFormat(QImage::Format_ARGB32);
QImage oCircleProfileImage (oImage.width(), oImage.height(), QImage::Format_ARGB32);
oCircleProfileImage.fill(Qt::transparent);
QBrush oImageBrush(oImage);
QPainter oPainter(&oCircleProfileImage);
oPainter.setBrush(oImageBrush);
oPainter.setPen(Qt::NoPen);
oPainter.setRenderHint(QPainter::Antialiasing);
oPainter.drawEllipse(0, 0, oImage.width(), oImage.height());
Where oImage is your image you want to be in a circle.

Related

make background of sprite transparent in SDL

How to change background color of sprites to transparent by changing alpha after loading it to a SDL_Surface. Are there any functions in SDL which use a floodfill kind of algorithm and change all pixel with a given color to transparent on the outside. I don't want it to happen inside the border of the sprite if the same color is used.
Sample Image:
I would like to make the background blue here transparent before I blit it on the window surface using SDL_BlitSurface.
Only a color key (SDL_SetColorKey()) or a full alpha channel are going to help you here.
Note, that you can provide an alpha channel in your source graphics if you use a format such as PNG. If you only sometimes need/want an alpha, then provide the alpha channel in your source graphics and use SDL_SetSurfaceBlendMode() with SDL_BLENDMODE_NONE to blend without the alpha and SDL_BLENDMODE_BLEND to blend with it.
Both SDL_Surface and SDL_Texture support SDL_BlendMode.
Even if SDL provided another method, such as the fill you mentioned. You wouldn't want to use that. It is more difficult, expensive, and unnecessary overhead. You should stick with best practices here.
You may want to look into SDL_Texture and SDL_Renderer and switch to using a "texture atlas" instead of individual surfaces/textures for each image to maximize performance.

Add transparency when drawing a rectangle in opencv

I am trying to paint rectangles in locations which face detection algorithm locate faces. I want to use alpha transparency in order to draw my rectangles. I have found in opencv documentation the following in here: Note The functions do not support alpha-transparency when the target image is 4-channel. In this case, the color[3] is simply copied to the repainted pixels. Thus, if you want to paint semi-transparent shapes, you can paint them in a separate buffer and then blend it with the main image.
How is it possible to blend main image with buffer image? And what exactly means with buffer image?
You can use the OpenCV addWeighted function to blend your image.
Refer to the documentation of the function.
You can provide the function with the amount of transparency you want to have.
Here is an tutorial to do so.

How to get the color of XY point on QGraphicsScene?

This seems trivial, but can't find a solution. I need to read a color of certain x,y point on QGraphicsScene.
Something like graphScen->colorAt(x,y);
A QGraphivsScene doesn't have the knowledge of the colors on points, and it's not really trivial (you have transformations both on scenes and items). what you could do is to access the pixmap of the rendered scene and access the pixel information there.
QPixmap paintDevice(sceneBoundingRect());
QPainter painter(&paintDevice);
graphScen->render(painter);
// Now you have the pixmap, get the pixel information.
QImage pixels = paintDevice.toImage();
QRgb colorAt = pixels.pixel(x,y);
Done.

Copying SDL_Surfaces with Alpha Channels

I've run into issues preserving the alpha channels of surfaces being copied/clip blitted (blitting sections of a surface onto a smaller surface, they're spritesheets). I've tried various solutions, but the end result is that any surface that's supposed to have transparency ends up becoming fully opaque (alpha mask becomes white).
So my question is, how does one copy one RGBA SDL_Surface to another new surface (also RGBA), including the alpha channel? And if it's any different, how does one copy a section of an RGBA surface, to a new RGBA surface (the same size of the clipped portion of the source surface), ala tilesheet blitting.
It seems that SDL_BlitSurface blends the alpha channels, so when for example, I want to copy a tile from my tilesheet surface to a new surface (which is of course, blank, I'm assuming SDL fills surfaces with black or white by default), it ends up losing it's alpha mask, so that when that tile is finally blitted to the screen, it doesn't blend with whatever is on the screen.
SDL_DisplayFormatAlpha works great to copy surfaces with an alpha mask, but it doesn't take clip parameters, it's only intended to copy the entire surface, not a portion of it, hence my problem.
If anyone is still wondering after all these years:
Before bliting the surface, you need to make sure that the blending mode of the source (which is an SDL_Surface) is set to SDL_BLENDMODE_NONE as described in the documentation: SDL_SetSurfaceBlendMode(). Is should look something simple like this:
SDL_SetSurfaceBlendMode(source, SDL_BLENDMODE_BLEND);
SDL_BlitSurface(source, sourceRect, destination, destinationRect);
I had this problem before and have not come to an official answer yet.
However, I think the only way to do it will be to write your own copy function.
http://www.libsdl.org/docs/html/sdlpixelformat.html
This page will help you understand how SDL_Surface stores color information. Note that there is a huge difference between colors above and below 8 bits.

Blending two different images in Qt

My program generate 3 different images and I'd like to combine them using some opacity settings.
First I have the raw image, which I already converted into a QPixmap to display it in a QGraphicsView.
.
Then with this image I make some calculation and generate a QImage because I need basic pixel access, I also add a legend.
.
What I'd like to do is to be able to blend the two images while being able to modify the opacity.
I don't have the tools to show an example, it should look like this:
But with the first image and the data image blended with opacity. Also I'd like the legend to stay 100% visible. I can create a different QImage for the legend if it's needed.
Also I know exactly which pixel should be considered transparent instead of white if it comes to that.
In the future I would like to adjust the opacity just with a slider so I think it would be better if there was a solution that didn't involve calculating a whole new image every-time...
Any lead would be appreciated...
You could use QGraphicsPixmapItem::setOpacity to set the alpha blend value in the range 0.0...1.0 for the overlay image and have separate graphics items for the background an the foreground.
If you actually need to generate a pixmap with the blended image, you can use setOpacity on QPainter before drawing the pixmap on it.
There is a QImage type that supports an alpha channel QImage::Format_ARGB32_Premultiplied which will display the two images with an opacity controlled by the alpha - simply draw the two QImages over the top of each other
But it is premultiplied so you need to adjust all the pixels if you change A