ID2D1RenderTarget::FillOpacityMask render with low resolution - direct2d

here i got some images i rendered with ID2D1RenderTarget::FillOpacityMask (i actuall call this funtion with a ID2D1DeviceContext2 pointer but it reference to ID2D1RenderTarget interface...).
So i'm not happy of the rendering quality. The original image has perfect resolution and is much bigger than the limit rectangle i render it into.
d2d_device_context->CreateBitmapFromWicBitmap(
wicConverter,
NULL,
&bitmap
);
d2d_device_context->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
d2d_device_context->FillOpacityMask(
myBitmap,
myBrushMask,
D2D1_OPACITY_MASK_CONTENT_GRAPHICS,
limitRect,
renderRect
);
d2d_device_context->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
This is the code i use. It not take any agument to select D2D1_INTERPOLATION_MODE like DrawBitmap or DrawImage does.
How can i increase the rendering quality?

Related

Keep image centered in resized JavaFX Canvas

I am getting my feet wet with JavaFX, and have a simple drawing program which writes to a Canvas using a PixelWriter. The program draws a pixel at a time, reflecting each pixel over a number of axes to create a growing and evolving pattern centered on the canvas:
The Canvas is in the Center region of a BorderPane, and I have written the code to resize the canvas when the application window is resized. That works OK.
However, I would like to re-center the image on the new resized canvas so that the drawing can continue to grow on the larger canvas. What might be the best approach?
My ideas/attempts so far:
Capture a snapshot of the canvas and write it back to the resized canvas, but that comes out blurry (a couple of code examples below).
I dug into GraphicsContext translations, but that does not seem to move the existing image, just adjusts future drawing.
Maybe instead of resizing the canvas, I make a huge canvas bigger than I would expect my app window to be, and center it over the center region of the border pane (perhaps using a viewport of some kind?) I'm not thrilled about the whole idea of making some arbitrarily huge canvas that I think will be big enough though. I don't want to get into scaling - I am using PixelWriter so that I get the crispest image without antialiasing and other processing.
My snapshot attempt looked like this, but was blurry:
SnapshotParameters params = new SnapshotParameters();
params.setFill(Color.WHITE);
WritableImage image = canvas.snapshot(params, null);
canvas.getGraphicsContext2D().drawImage(image, 50, 50);
The 50, 50 offset above is just for my testing/learning - I'll replace it with a proper computed offset once I get the basic copy working. From the post How to copy contents of one canvas to another? I played with the setFill() parameter, to no effect.
From the post How to save a high DPI snapshot of a JavaFX Canvas I tried the following code. It was more clear, but I have not been able to figure out how to find or compute the pixelScale to get the most accurate snapshot (the value 10 is just some number I typed in bigger than 1 to see how it reacted):
int pixelScale = 10;
WritableImage image = new WritableImage((int)Math.rint(pixelScale * canvas.getWidth()),(int)Math.rint(pixelScale * canvas.getHeight()));
SnapshotParameters params = new SnapshotParameters();
params.setTransform(Transform.scale(pixelScale, pixelScale));
params.setFill(Color.WHITE);
canvas.snapshot(params, image);
canvas.getGraphicsContext2D().drawImage(image, 50, 50);
Thanks for any direction y'all can point me in!

Can I stop stationary SVG images from using excesssive CPU resources in QML?

I have a QML GridView, with a huge number of simple icons in it. The number can be in the millions, but only around a thousand will be visible at the same time, and there are only a few dozen types of images, so I guess they should be cached well.
If I use PNG images, everything is fine. The startup time is relatively long, but after everything is rendered, the application runs fine even on low-spec machines, and scrolling / resizing / zooming in the GridView is also fast and smooth.
However, if I use SVG instead, it slows my system down significantly. Even after everything is rendered, the responsiveness of the application is horrible, even GUI elements unrelated to the GridView are showing significant lag, the mouse cursor can barely be moved, etc. I thought after they are rendered, SVGs are presented just as any other image. Why must the CPU be busy if I don't even interact with them? And, most importantly, is there anything I can do about it? The same thing happens if I have SVG images containing nothing but a single rectangle, and use the same image in every cell. So it must mean the objects themselves are doing something.
"The number can be in the millions" and *"The startup time is relatively long"- those statement warrant a discussion about the design of your data model and bitmap caching strategy. But you didn't provide any code. So the following is a guess.
I'm not sure if you are loading the SVG images in C++ code or through QML, but I suspect you aren't setting the sourceSize (width and height) properties when you import your SVG. Hence, it's getting mapped into memory at a much larger size than it's getting rendered at. That is, it's eating up a lot more memory than it was with pre-sized PNG files. Or perhaps it's getting mapped in at a smaller size and Qt is is spending a lot of time having to resize these images at runtime as it scrolls in/out of view.
Open up one of your SVG files with notepad and look at at the attribute to see what the import size is.
In any case, try making sure your sourceSize.width and sourceSize.height match your render width/height.
Image {
id: icon
anchors.centerIn: parent
source: "cloud.svg"
sourceSize.width: 50
sourceSize.height: 50
width: 50
height: 50
}
Loading SVG's is an expensive operation...
Gridview manage dynamic objects.. creating visible items and destroying invisible items each time ....so, must render SVG each time you move the grid
One very bad idea is use that:
GridVIew{
cacheBuffer : 6000
//create 6000 items ...long startup time and memory expensive
...
}
This is a much better option:
Image {
id: icon
asynchronous : true //load image in asyncronus thread
sourceSize.width: width //scale as item size
sourceSize.height: height //scale as item size
...
}
If the load is too slow, you can add something like "LOADING..." text in the item background...

GWT - Getting the current size of an image

I use the GWT image class with a ClickHandler to trigger actions when specific areas of the image are clicked. In order to specify these areas, I use the image's dimensions. The problem occurs when you change the size of your browser window. While the image rescales nicely, the getWidth() and getHeight() methods still return the image's original size, not the size after rescaling.
Do you know a way to retrieve the current size of the image?
.getElement().getOffsetWidgth() ? and .getOffsetHeight().
I think thats what you need.
That will return the current size of the element in the Dom, including any decorations like borders in the CSS.

Why does WebGL canvas turn white on the second frame when alpha is masked?

Please see this thread for details.
To summarize, given the following circumstances:
gl = canvas.getContext('experimental-webgl');
gl.clearColor(0, 0, 0, 1);
gl.colorMask(1, 1, 1, 0);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
...and a standard render loop:
function doRender() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// render stuff, and request another frame
requestAnimationFrame(doRender);
}
...then I would like to know what the expected output should theoretically be.
In actuality, I'm seeing that the first frame renders as if there were no color mask, and the second (and subsequent) frames render the entire canvas opaque white.
Note that it doesn't matter what the alpha level is set to: the second frame is always immediately, completely white (including areas that were not rendered to), even if the rendered alpha values are extremely low.
The Question: what is the expected result of the above operations on the first, second, and subsequent frames? Also, is what I am experiencing the expected result, or due to some bug in the GL driver or WebGL implementation? And finally, if it is the expected result, why? What is actually happening on the video card to produce this result?
System details: Chrome / Firefox (both) on a MacBook Pro / GeForce 320M / Snow Leopard.
WebGL automatically clears the drawing buffer on each frame unless you tell it not to
try
gl = canvas.getContext('experimental-webgl', {
preserveDrawingBuffer: true
});
That's potentially slower than letting it clear though since it might have to make a copy of the drawing buffer each frame to preserve it so it has a copy to composite with the rest of the page while you draw new stuff into it. So, it's probably better to call gl.clear inside your render loop. Of course if the effect you were going for was to continually blend stuff into the drawing buffer then you either need to tell it to be preserved like the example above or you need to draw into a texture or renderbuffer using a framebuffer and then render that to the drawing buffer.

How to fix blurred Icon Decorator on DSL Tools?

I faced this problem and after an extensive research I found its root cause and a workaround that can be useful for other people.
The icon decorator becomes "blurred" because its positioning on the shape and the conversion from pixels to inches.
Usually the drawing surface of the Domain Specific Language has a resolution of 96dpi and the Icon Decorators are positioned using an offset of 0.06 inches. Translating it to pixels it becomes an offset of 5.76 pixels in the drawing surface. As it is not possible to draw a "half pixel" on the screen the GDI+ adjusts the image in an attempt to emulate the "haf pixel" positioning. That is the reason why the image becomes blurred.
My suggestion as workaround, is to use the Horizontal Offset and the Vertical Offset properties of the Icon decorator class for fixing the "half pixel" decorator position. If you use the "0.0025" inches as vertical and horizontal offsets, when the image positioning is translated from inches to pixels it becomes 6 pixels, instead of 5.76. It happens because the offset now is the default value 0.06 inches plus the offset you set 0.0025 = 0.0625.
I also found that using png images with transparency causes the image blurring, even using the offset workaround I suggested here. Converting the image to bitmap format fixes the problem.
If someone also has any suggestions for fixing the problem, please add your solution or workaround.
I fixed the blurred problem by creating a new Bitmap:
Under the overridden method
public override System.Drawing.Image GetDisplayImage(ShapeElement parentShape)
I call my custom method FixBitmap
Bitmap imageFixed = DynamicImageHelper.FixBitmap(image, out dynamicOffset);
This method receives the original image that DSL would show, but instead returns the exact same image but created as a new Bitmap
Bitmap fixedImage = new Bitmap(original, original.Width, original.Height);
return fixedImage;
If you check the new instance properties there are little differences (I don't quite remember which because i implemented this about 1 year ago).
Also, i mostly use .png files with transparency and they look exactly as they are.
Hope this helped.
If you need any further help, do not hesitate,
Regards,
Luís

Resources