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

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.

Related

What is the best approach to displaying drawings on different-sized Paper JS views?

Context
I'm using Paper JS to build a multi-player drawing game. At any given point, a single user will be drawing to his/her canvas, and the data will get sent to the server to be broadcast to other users. Each user's canvas may be of variable size, and it resizes as the window resizes while maintaining the same aspect ratio.
The goal is for each user to have a scaled representation of the drawing (i.e. everything fits inside the different sized canvases and the content doesn't get distorted). This should be the case if a drawing transfers from a larger canvas to a smaller canvas, and vice-versa. The project supports a drawing tool as well as an eraser tool.
Problem
Approach 1 below scales the drawings the way I want, but there is substantial lag. Approach 2 deals with the lag, but doesn't scale the drawings the way I want.
My understanding is that SVGs will scale nicely whether they are scaled-up or scaled-down. But rasters are pixel-based and will become "blurry" when scaled-up. When I test approach 2, a drawing from a smaller canvas gets blurred on a larger canvas. The result is the same whether I use export/importJSON or export/importSVG. Is there a way to get both good performance and scaled-drawings? See below for example implementations of the tools.
Approach 1: Paths + Symbols:
Every path/symbol placement is kept in the active layer.
The eraser tool draws a white rectangle (defined as a symbol) to
mimic an "erasing" effect.
This works fine as a demo, but will start to lag very quickly as the
number of items in the active layer increases. The eraser tool in
particular will not function smoothly.
Relevant sketch
Approach 2: Rasterization:
After a path is drawn or a symbol is placed, the active layer is
rasterized and its children are removed.
This seems to work quite well on a single canvas, and the eraser
doesn't lag like in the first approach. There are only 2 items in the
active layer after each rasterization.
When a drawing from a client with a smaller canvas is exported (using exportJSON or exportSVG) to a client with a larger canvas, the result is "blurry".
The above also happens when a drawing is made and then the canvas is re-sized to be larger.
Relevant sketch
You could send your objects as SVG and rasterize them once received.

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).

QPainter drawImage becomes very pixelated

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

SCNNode material scale

I have an SCNNode that has its geometry populated from a collada file (.dae) and displays correctly on screen. I can apply materials to the geometry easily enough, however I'd like to change the scale of the material.
I currently populate it with
nodeArray[0].geometry?.firstMaterial!.diffuse.contents="wood.png"
but the scale of the material is too small. While I can edit the png in GIMP or something similar and import it as wood2.png is there any way I can set the material scale programatically?
what do you mean by "too small" ?
Geometries are made of different sources such as the vertices' positions, but also their texture coordinates. These texture coordinates (they belong in [0,1]x[0,1]) are specified per vertex and indicate where to look in the texture.
In your 3D modeler please check that your texture coordinates match what you want (i.e. they cover the whole image i.e. they go from 0 to 1 in very direction), and make sure that your image has no extra transparent margin or other wasted space.
You can have a look at SCNMaterialProperty's contentsTransform property. But please check your model and texture before using it.
You need to open your UV snapshot in an image editing software like Photoshop, scale the wood texture in Photoshop over your UV's, then resave your PNG/JPG, move PNG/JPG back to Xcode

How do I resize a flat vector icon so that it preserves hard edges?

I recently purchased Drew Wilson's Pictos icon library. It is a library of flat, monochromatic icons for use on the web and elsewhere. The only issue is: they're vectors. I know my way around Illustrator a little bit, but ultimately I want to import these icons into Photoshop CS4 and resize to various dimensions.
When I import an icon and resize it to, say, 20x20 pixels, I notice that there is a fair bit of aliasing around the edges of the icon. I'm sure there is some magic number where the edges of these icons will remain crisp, but I can't find any option or setting that will allow me to size these icons properly.
How can I snap these icons to the closest size that removes or minimizes the aliasing?
The aliasing / pixelating is because vectors export out of illustator # whatever size they're copied #
Try opening the icons in illustrator... scaling them waaay up
And then just keep a copy of the huge ones in a separate layer
Copy that layer when you want to scale it down ..annnd that way you'll have a copy to work with..and u won't have to re
Open the file every time u need to make an edit
And a good rule of thumb for pixelation is
You can always size down.. but sizing up will create pixelating in bitmaps
Chances are, you have your logo in .eps format. If you do, open your .eps file in Photoshop. A dialog box will pop up asking the size you want to import. Be sure to select RGB color if this will display on the web. Select the Anti-aliasing checkbox. When your file opens up, zoom in, and you'll notice that Photoshop has neatly anti-aliased all of your edges for you.

Resources