Render image from hsv color
I've looking into a way to render an image on screen from a saturation map.
I'm currently using a regular widget (because I couldn't get transparency to work with the openGL one).
My paint even look something like
painter = QPainter() painter.begin(self) color = QColor() for x, y in np.transpose(np.nonzero(self.im)): color.setHsv(168, self.im[x, y], 180) painter.setPen(color) painter.drawPoint(QPoint(x, y)) painter.end()
where I iterate over the whole (nonzero) saturation map "self.im", change the QColor to that, update the painter with that color and paint that point.
But this is terribly inefficient and slow, how can I make this work?
Is there a way to make a hsv/hsl Image and render that?
I can layer the (constant) hue and value/saturation to a make a full hw3 numpy array if that helps.
@Adam-V Maybe it would help to write the pixel data into a QImage first and then draw this QImage once?
@jsulm How do I construct a QImage from hsv/hsl data?
@jsulm While this does draw faster but still 90ms paintEvent (improved from 180).
image = QImage(self.width(), self.height(), QImage.Format_ARGB32) painter = QPainter() painter.begin(self) color = QColor() for x, y in np.transpose(np.nonzero(self.im)): color.setHsv(168, self.im[x, y], 180) image.setPixelColor(x, y, color) painter.drawImage(self.rect(), image) painter.end()
@Adam-V Do you have to calculate the image each time paintEvent is called? If not then just do it when needed and just draw already calculated image in peintEvent.
Sadly I have to.
It only gets drawn on a touch event, and in that case the whole image needs to be recalculated.
Also, the profiler indicates that almost all of the time goes to setHsv and setPixelColor.
I have found a solution that kind of does the job, although takes three times as much memory.
Every update I calculate the difference between the new and the old saturation matrix, this eliminates 60% of the nonzero values, which means it gets drawn that much faster.
As a second layer of optimization I call repaint with a rectangle describing the most important zone, and call update every 60ms.