Using float or double for own QML classes - qt

I've created some components and helper methods using C++ and Qt to be used in my QML GUI. Some of those methods calculate GUI elements (size, transformations, scene graph items creation). The target is an ARM 32 Bit using OpenGl / Eglfs to render the output.
OpenGl is using float, QML is using real (defined as double).
What should I use in C++ to do not lose any precision?

If you use qreal (double) then you shouldn't lose any precision. If you git grep float in qtbase.git, you can find out a bit more:
dist/changes-5.2.0-****************************************************************************
dist/changes-5.2.0-* Important Behavior Changes *
dist/changes-5.2.0-****************************************************************************
dist/changes-5.2.0-
dist/changes-5.2.0- - Qt is now compiled with qreal typedef'ed to double on all
dist/changes-5.2.0: platforms. qreal was a float on ARM chipsets before. This guarantees more
dist/changes-5.2.0- consistent behavior between all platforms Qt supports, but is binary
dist/changes-5.2.0- incompatible to Qt 5.1 on ARM. The old behavior can be restored by
dist/changes-5.2.0: passing -qreal float to configure.
It's interesting to note that within Qt, there are large pieces of code that have switched to using only float:
commit 51d40d7e9bdfc63c5109aef5b732aa2ba10f985a
Author: Sean Harmer <sean.harmer#kdab.com>
Date: Mon Aug 20 20:55:40 2012 +0100
Make gui/math3d classes use float rather than qreal
This corrects the mismatch between using floats for internal storage
and qreal in the API of QVector*D which leads to lots of implicit
casts between double and float.
This change also stops users from being surprised by the loss of
precision when using these classes on desktop platforms and removes
the need for the private constructors taking a dummy int as the final
argument.
The QMatrix4x4 and QQuaternion classes have been changed to use float
for their internal storage since these are meant to be used in
conjunction with the QVector*D classes. This is to prevent unexpected
loss of precision and to improve performance.
The on-disk format has also been changed from double to float thereby
reducing the storage required when streaming vectors and matrices. This
is potentially a large saving when working with complex 3D meshes etc.
This also has a significant performance improvement when passing
matrices to QOpenGLShaderProgram (and QGLShaderProgram) as we no
longer have to iterate and convert the data to floats. This is
an operation that could easily be needed many times per frame.
This change also opens the door for further optimisations of these
classes to be implemented by using SIMD intrinsics.
As it says, this was to avoid surprise loss of precision as the functions took qreal (double) but stored their data as float. If you use qreal everywhere in your own code, you won't have this problem.
The other reason was performance. I can't comment too much on that, but I'd say that it's more important for Qt to optimise for such things than it is for most users of Qt.

Related

Render YUV in JavaFX

I need to render a yuyv422 stream in JavaFX with minimum latency. If I convert it to RGB, I can use an ImageView with a WritableImage with a PixelFormat instance, and it works, but the RGB conversion consumes a lot of CPU, specially with high resolutions. I saw this exact feature request
https://bugs.openjdk.java.net/browse/JDK-8091933
but seems it will not be implemented in Java 9. And if it does, I wonder if it won't introduce latency or demand too much CPU. Is there another way using JavaFX?
In General:
Image processing is always expensive, this is why Vectorization or Hardware Acceleration is used for these tasks. Simple looping through an Image with just one thread is already really slow, especially in java. On top of that people tend to use Color objects for color modifications which is tremendously slow.
Pure Java:
If you want to keep your code in pure Java. You should check which internal format is used for the WriteableImage by calling:
myImage.getPixelWriter().getPixelFormat().getType()
If the internal format isn't RGB adapt your color conversion to the given format to avoid double conversion.
Additionally make sure that your code is optimized as much as possible:
-Don't use any objects except arrays
-Minimize the use of local variables
You can also try to multithread the conversion process via parallel loops.
JNI:
Moving away from Java opens up a lot of possibilities. There are several platform independent libraries for converting YUV to RGB and back:
OpenCV:
Easy to use and coming already with an java API:
byte[] myYuvImage = null; //your image here
byte[] myRgbImage = new byte[width * height * 3]; //the output image
Mat yuvMat = new Mat(height, width, CvType.CV_8UC2); //YUV422 should be 2 channel
Mat rgbMat = new Mat(height, width, CvType.CV_8UC3);
yuvMat.put(0,0, myYuvImage);
Imgproc.cvtColor(yuvMat, rgbMat, Imgproc.COLOR_YUV2RGB_Y422);
rgbMat.get(0, 0, myRgbImage);
Intel IPP:
Only available via JNI. You would use ippiRGBToYUV422_8u_C3C2R see RGBToYUV422 for more information.
SwScale as part of FFmpeg:
Only available via JNI. See this answer and adapt the example.
My personal experience is that IPP offers by far the best performance even on AMD machines. However the license it comes with may be free but it prohibits decompiling which might be an not compatible with LGPL libraries.

Is Double Now Fully Equivalent to Real in QML?

One peculiar aspect of the JS-heavy declarative user interface language QML is its inclusion of seemingly redundant decimal number types.
The native types declare two basic types for decimal numbers, whose names are similar to those in many other programming languages: real and double.
The table in the current Documentation (v5.8) describes double as...
Number with a decimal point, stored in double precision.
...and for real...
Number with a decimal point
Now the odd bit. The prior passage might lead one to believe that as with most language these are indeed different types based on the floating point precision (see: float and double in C/C++).
But that assumption is indicated to be incorrect. The documentation for real states:
Note: In QML all reals are stored in double precision, IEEE floating
point format.
This basic type is provided by the QML language.
Okay, a bit peculiar (why have two types then), but assuming that is wholly accurate, presumbably it would make sense to pick one (perhaps whichever was the standard in your codebase you're working on) and go with it.
But reportedly there's an unexpected issue, as noted by Kent Hansen on QtDeclarative:
The type "real" was documented to be a single-precision float, but
that's incorrect. It's always been double.
However, signal parameters of type "real" would be mapped to the C++
type "qreal", which can be either float or double depending on the
platform.
Since JavaScript floating point numbers have double precision, QML
should use the same, to avoid potential loss of precision.
That makes me question whether the statement given in the Qt Documentation is wholly accurate. Hansen's post was 4 years ago, back when Qt/QML v5.1-2 were the latest versions. Now we're at v5.6-8, so I'm wondering if what he reports is still an issue.
Can anybody answer whether this or any other inconsistencies still exist in the latest Qt/QML release versions (v5.6-8, as of Feb. 2017)?
Is this why two separate basic types for decimal numbers are included, in spite of the documentation seemingly indicates them to be identical?
Is there any other reason to use double versus float or vice versa in QML?
It's because of the tradition of keeping backward compatibility.
In Qt4 it was a float. In Qt5 the old code with real and double can run, but the implementation of the QML engine doesn't need to bother with floats any more.

QGLWidget is slower than QWidget

The problem mainly is determined in the title. I tried out the Qt's example (2dpainting) and noticed, that the same code consumes more CPU power if I try to draw on QGLWidget and less if I try to draw simply on QWidget. I thought that the QGLWidget should be faster. And one more interesting phenomenon: In QGLWidget the antialiasing hint seems to be ignored.
OpenGL version: 3.3.0
So why is that?
Firstly, note this text at the bottom of the documentation that you link to:
The example shows the same painting operations performed at the same
time in a Widget and a GLWidget. The quality and speed of rendering in
the GLWidget depends on the level of support for multisampling and
hardware acceleration that your system's OpenGL driver provides. If
support for either of these is lacking, the driver may fall back on a
software renderer that may trade quality for speed.
Putting that aside, hardware rendering is not always guaranteed to be faster than software rendering; it all depends upon what the renderer is being asked to do.
An example of where software can exceed hardware is if the goal of the item being rendered is constantly changing. So, if you have a drawing program that draws a line being created by the mouse being constantly moved and it is implemented by adding points to a painter path that is drawn every frame, a hardware renderer will be subject to constant pipeline stalls as new points are added to the painter path. Setting up the graphics pipeline from a stall takes time, which is not something a software renderer has to deal with.
In the 2dPainting example you ask about, the helper class, which performs the paint calls, is doing a lot of unnecessary work; saving the painter state; setting the pen / brush; rotating the painter; restoring the brush. All of this is a bigger overhead in hardware than software. To really see hardware rendering outperform software, pre-calculating the objects' positions outside of the render loop (paint function) and then doing nothing put actually rendering in the paint function is likely to display a noticeable difference here.
Finally, regarding anti-aliasing, the documentation that you linked to states: "the QGLWidget will also use anti-aliasing if the required extensions are supported by your system's OpenGL driver"

What's the equivalent std::deque in Qt?

I am on several lines codes from a Qt project to appending into a Qvector every 1s. I noticed that in STL deque could have a better performance in adding a new element into the end that vector. What's the equivalent or similar Qt way? Cause I don't find any in Qt libraries.
Julio
There is no direct equivalent to the std::deque class in QT.
However, your best bet is to use QList.
Here is what the documentation says about QT container classes:
For most purposes, QList is the right class to use. Its index-based API is more convenient than QLinkedList's iterator-based API, and it is usually faster than QVector because of the way it stores its items in memory. It also expands to less code in your executable.
Anyways, if you are only appending items once every second, there will not be much impact to choose one over the other.
There is no need to have a Qt equivalent for every std container, you can use std::deque if that is what you are after.
Anyway, note that for the case when you do a lot of insertions at the end of the vector both std::vector and QVector have a member function named reserve (see the links) that can be used to pre-allocates a bigger buffer and make insertions at the end faster.

Shifting the hue of a QImage / QPixmap

I suppose this is more of a graphics manipulation question in general, but I'd like to accomplish this in Qt (c++). If I have an image - let's just say a circle on a transparent background - of a light gray color, is there any built-in functionality in Qt to shift the hue / saturation to color it?
I suppose I could go pixel by pixel, and modifying the rgb mathematically - add x to r, g, and b, to get a desired color, but there must be a better way than modifying every single pixel.
Nothing in the Qt Docs goes this far into image manipulation, just altering alpha and colors. Should I look into an open source library (the end result will likely be an independently sold software)? If so, are there any recommendations? Or is there a secret function hidden in the Qt docs that can accomplish without the need of outside libraries / crazy algorithms?
A possible course of action:
Load your image as a QImage
Do a QImage
QImage::convertToFormat(QImage::Format_Indexed8) to get a indexed
image with a color table
Get color table values with QRgb
QImage::color ( int i ) const
Manipulate the colors with QColor
( QRgb color ) and the other QColor methods
Alter the color
table with void QImage::setColor ( int index, QRgb colorValue )
You've got a few options, none of which are built-in Qt solutions, unfortunately.
Use OpenMP or some other concurrency library to take advantage of
SSE/SSE2.
Use the GPU via OpenGL, DirectX or various GPGPU programming techniques.
(the solution I chose) Use OpenCL to take advantage of both CPU and GPU concurency without all the "fun" of shader programming.
Spawn off a pool of thread workers and have each of them handle a chunk of the image.
My application does lots of image filtering and I was honestly shocked at the performance gain that was to be had after I ported filters to OpenCL.
At 1936×2592 a brightness modification filter was running in 175ms in native C++ code iterating through each pixel within a QImage.
After porting to OpenCL that went down to 15ms. Of course, the data had to be pulled out of the QImage and reinserted but that overhead was nothing compared to the OpenCL performance gains.
Best of luck on your coding adventures!
In this case it sounds like you might be able to get away with using a QGraphicsColorizeEffect.
Instead of shifting the hue, this method will set it. Although it seems QGraphicsEffects can only be applied to QWidgets and QGraphicsItems, which can be inconvenient.
Another option - in this case - would be to use a QPainter's CompositionMode.
Just use QImage::pixelColor and QImage::setPixelColor (available since Qt 5.6).

Resources