QPainter drawImage becomes very pixelated - qt

I use QPainter and the function drawImage to draw an airplane on a map. The image and redrawn each time the position of the airplane changes. The problem is, after some time, the image becomes extremely pixelated. I have tried to use a high quality .svg and that did not help either.
Below is my code. Can somebody spot where the error is or what has caused the image to be so pixelated?
// Load .svg image
airplane->load("AirplaneTopDown.svg");
// Downsize image
airplaneSmall = airplane->scaled(120, 120,Qt::KeepAspectRatio);
// Rotate image by trans
airplaneSmall = airplaneSmall.transformed(trans);
// Draw image and center at a certain screen position
painter.drawImage(airplaneX-airplaneSmall.width()/2,airplaneY-airplaneSmall.height()/2,airplaneSmall);
Below are the images of the drawn airplanes. One taken as screenshot at the beginning of the program runtime another one taken after a couple of minutes.
Airplane
Airplane-pixelated

One of your problems is that you first rescale the image and then rotate it.
The rotation needs to interpolate new pixels from the old ones. The higher the resolution of the input, the better the quality of the interpolation. The quality of your SVG is completely lost after the rescale operation.
The second problem you are facing is that you use the "fast" (default) transformation method. This method does not antialias. So instead of interpolating from several input pixels, it will only take one best fit. Calling transformed() with the second argument Qt::SmoothTransformation and scaled() with the sceond argument Qt::SmoothTransformation |Qt::KeepAspectRatio` will greatly improve your results.
However it is also slower, as is performing the rotation on the image in its original, higher resolution.
The arguably best solution to your problem is to take on a different approach. Instead of loading the SVG into a QImage, which is a raster-based image, you should work with the vector graphics. So the SVG is rendered in the right orientation and scale in the first place. A good starting point is the SVG Viewer Example: http://doc.qt.io/qt-5/qtsvg-svgviewer-example.html

Related

How can I set vector mask for clicking in Qt?

I need create clickable component with custom shape. Appearance is set by svg file. Clickable area must be constrained by svg shape. I find great example of what I need, but it use pixel mask or circle mask. Can you help me find solution?
Most probably you will need to create a pixel mask yourself from the SVG shape.
The question is how to approach this. Qt does not offer a simple way of doing it. However, in Qt you can render the SVG offscreen into an image that you initialize with transparent pixels or a color key. You can then use this image as a mask.
If the size of your viewpoint changes frequently, you might want to do the mask rendering in a higher resolution first and then scale it down accordingly for performance. Also note that if your SVG is animated, you would have to accomodate for that.
Or you might use a different library than Qt to obtain the mask. Also, if your SVG contains only a single polygon, you might go for a point-polygon test. But I doubt it, and such a test is also not trivial when the polygon is non-convex (you typically end up with a scanline algorithm anyways).

Qt - drawing image on image using another image as a mask

Here's the issue at hand. I need to be able to pick a background (an image showing an object, let's say, a starship model). I want to be able to apply various previously prepared textures to various areas on it, as some kind of a "colour your own object" app, but without the need to prepare dozens of individual segments.
Ok, so this is one, newbie way to do it. We have those images:
Two kind of different versions, an original photo and a quickly Photoshopped one. Let's say we only want the Borg-ish green deflector and warp nacelle from the second picture, without the odd pink hull. You have to have a mask, basicly an image of an equal resolution (or at least the same aspect ratio, which you can reliably scale to image's resolution), with the area filled with color (or whatever else), and transparent area everywhere else. As the mask, I've used a few strokes of brush on an empty layer, set to overlay mode, and then saved as PNG, with transparency. And this is how the code went:
First, import images.
QPixmap background("orig.png"); //import base image
//import alt version/texture/whatever you want, anything will work with a good mask
QPixmap element("alt.png");
QPixmap mask("deflector.png"); //mask. Just nacelles and deflector.
Then, isolate the area that interests us from alt version
QPainter painter(&element);
painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
painter.drawPixmap(0, 0, mask.width(), mask.height(), mask);
And finally draw it onto the target object.
QPainter inter(&background);
inter.drawPixmap(0, 0, element);
ui->label->setPixmap(background);
The result:
This method respects any and all transparency you could've done in Photoshop or another image editing software.
Simple, but an effective solution, for when your app has to work with graphics prepared by someone else, elsewhere.

Rendering an invisible occluder

I'm currently upgrading from a DirectDraw system (yeah I know, it's very old) to DirectX10. It's a 2D system but simulates real world as each object has a range/depth in meters. There is a background image that is rendered and kept on the farthest z-order. All other objects are drawn on top of it and scaled according to what their range/depth would be. However, there is a certain type of object I have that is defined as a polygon and renders a bit different. It acts as an invisible occluder. For instance, an occluder is at a range/depth of 40 (my units are meters) and is defined by 5 vertices (a pentagon) in the middle of the viewport. There is a sprite object at the same viewport position but at a range/depth of 50. The desired output is to have the sprite object not rendered, but the background should be seen through both of them. So in essence these are invisible occluders, except that they do not occlude the background.
As a note, the occluders and the sprites all derive from the same base object type and are mixed together in a depth-sorted container.
My idea was to override the occluders Render method so they draw to a render target writing the range/depth values. I then would render the sprites as normal, but in the vertex or pixel shader would compare the range value of the sprite with the range values in the render target. However, it seems to me that I'd have to potentially read/write from the render target in the same pass before Present is called, and that's undefined. If i was to render the occluders, unbind the render target and pass the texture in for a lookup by the other objects, I'll have to convert the sprite positions into that texture space which may be non-trivial. Are either of these methods possible?
After thinking some more about it, one other idea came to mind. I could take the occluders and set their texture coordinates in reference to the background texture. In this way they would draw the same color values as the background, and because of the sorting if a sprite was behind it the user would still see the "background" but really it's the occluder looking like it.
Sorry if this is less a question and more thinking out loud, but I wanted to get impressions and ideas on the best way to go about this. Seems to me I have options but wasn't certain which was most efficient and which is easiest. Thanks in advance for any responses.
As stated in my comments I went with setting the texture coordinates in reference to the background image and then making sure the occluder, which was a simple polygon, was triangulated properly to make use of those texture coordinates.

How does one smooth the cursor in a scaled flex/flash application?

I'm scaling my application to fit the browser window. I'm also defining my own cursor using a bitmap and CursorManager.setCursor.
The problem: when my app scales, the cursor bitmap is jagged. Is there a way to smooth the bitmap that is use?
I believe your problem is that you're scaling your root display object(e.g., stage), which means the cursor also gets scaled. You probably want to scale a child container instead, which means the cursor won't scale. I'm guessing you don't want the cursor to change sizes anyway.
Otherwise, you can look at using an svg file (or a swf image) since they're based on vectors and scale properly. You can also look at trying to smooth the bitmap using the bitmapData draw function. (http://livedocs.adobe.com/flex/3/langref/flash/display/BitmapData.html#draw())

Approaches / libraries for resize dragging

I'm currently working on a WYSISYG editor that allows the user to move, resize and rotate shapes by directly manipulating them. The resizing seems to be fairly complex when the shape is rotated. I got this working for non-rotated shapes, but it will take some trigonometric calculations to resize shapes that are rotated. The registration point is always is the middle of the rectangle because this makes rotating a lot easier.
Before I start implementing this, I was wondering if anyone knew of any libraries or sample source code that does this, or could share some tips and tricks to calculate the transformations.
I have the following parameters:
rotation (in degrees)
width, height
x, y
mouseX, mouseY
I attached a screenshot of what I'm trying to accomplish and another one that has some lines drawn onto it that should allow me to deduct the trigonometric calculations. The cross is the cursor.
alt text http://www.herrodius.com/images/resize.jpg
alt text http://www.herrodius.com/images/resize_lines.jpg
You might look at flex-object-handles, in particular the more recent version 2.
I recommend Transform Manager - http://www.greensock.com/transformmanageras3/
It's actually not that hard. Use the mouse coordinates (mouseX / mouseY)from the rotated display object and they will be transformed for you!

Resources