-1

Take a look on following code the Image is a class member of type QImage.

void ImageViewer::setImage(const QImage &newImage)
{
Image = newImage; // takes 108 milliseconds
imageLabel->setPixmap(QPixmap::fromImage(Image)); // takes 58 milliseconds
}

because I don't need to set newImage to Image class member anymore, I simply use reference of newImage and save time. But I was surprised.

void ImageViewer::setImage(const QImage &newImage)
{
imageLabel->setPixmap(QPixmap::fromImage(newImage)); // takes 158 milliseconds
}

It takes same time. What am I missing here?

EDIT For those who want to known how I measured times, I used QElapsedTimer suggested here

Image is everytime same the code is a part off custom scroll. Evrything you have to know is same image(.jpg) of size 2380x3368 is loaded every time we enter this function. The measured time are pretty much same every time those are in comments are avarage time.

But personally think that image format or size is not the question here the main question here. The main question should be why SetPixmap takes more time when I used ref to an existing QImage than creating a new QImage which is then sent to this function. It's not make any sense.

blah blah
  • 1
  • 2
  • Is this measured with a unoptimized debug build or an optimized release build? Also, what platform? What compiler? – Jesper Juhl May 31 '18 at 15:27
  • Times are measured in Debug and Release build and they are pretty much same. Platform mac using Qt Creator 4.6.1 and Qt version 5.10.1 clang 64 bit. – blah blah May 31 '18 at 15:35
  • Can you show how you benchmarked this? I suspect you are using a sampling profiler, which are really bad at assigning times to individual code lines in release builds. –  May 31 '18 at 15:47
  • This question is seriously deficient. Please provide a complete example. Most likely your source image has to undergo an expensive format conversion. Where does this image come from? What is it’s size and format? What is the format of a QImage::fromPixmap(QPixmap(1,1))? – Kuba hasn't forgotten Monica May 31 '18 at 19:43
  • @KubaOber question is edited please let me know if you have some more infromation but this is very is to write in Creator on your own I think. – blah blah Jun 01 '18 at 10:28
  • No, it's your job to provide a complete minimal example. It should be one file (all in `main.cpp`) and *simple* and *short*. Writing such is an important skill. – Kuba hasn't forgotten Monica Jun 01 '18 at 10:57
  • @KubaOber I edited my question like u want and rather helping me you just blaming the question. Your comments are just useless and I can't see any try to help me resolve my issue. Guys here have understand the problem and wrote something relevant you NOT. – blah blah Jun 07 '18 at 12:13
  • No, you did not edit the question like that. Again, there's no way to help you if you don't provide code that actually has this problem. People who know your answer generally tend to write correct code by habit and may have problems imagining what you're doing wrong - at least I certainly am like that. I have code that does all that your question claims and it is not that slow. Now what? See - your approach doesn't let us help you. I'm helping you resolve it by telling you exactly what you need to do to make the question work. Ignore it at your own peril. – Kuba hasn't forgotten Monica Jun 11 '18 at 12:45

2 Answers2

1

From the documentation: http://doc.qt.io/qt-5/qimage.html#operator-eq

QImage &QImage::operator=(const QImage &image) Assigns a shallow copy of the given image to this image and returns a reference to this image.

So we can establish that both of your blocks of code are effectively equivalent, since making a copy-on-write copy of an image is basically a free operation (when looking at Millisecond timescales).

The fact that it looks like a lot of time is spent doing the initial copy in your first example is probably an artifact of how you benchmarked the code.

Edit Copy-on-write means that both Image and newImage share the underlying data after the assignment, and will make a copy of the data on demand the first time one of them diverges. In effect, it's not much more expensive than copying a pointer.

  • Doesn't make a lot of sense for me. I am newbie in Qt. Can you explain it a little more deeply but simplified what's exactly happening here ? For me its looks like you are doubt about how I measure the code and that's doesn't a satisfactory answer. – blah blah May 31 '18 at 19:03
  • @blahblah What I'm saying is that both functions taking the same time is 100% normal. What's weird is the repartition of the time in the first example, but depending on the method you used to measure the time, it might not be so weird. (I'll add a full explanation of copy-on-write in the answer). –  May 31 '18 at 19:32
  • I edit my question which measure method I used and some more information are given. Whats is weird for you is the main question for me now as well. – blah blah Jun 01 '18 at 10:36
0

QPixmap is a thin wrapper around an internal QImage of a certain format. You need to decompose your call into two separate ones, and determine whether a format conversion takes time - that's the only way an image-to-pixmap conversion would take lots of time. When the source image has the proper format, the conversion takes no time at all.

void ImageViewer::setImage(const QImage &newImage) {
  static auto const format = QPixmap(1,1).toImage().format();
  if (format != newImage.format())
    qWarning("There is a format conversion. This won't be fast.");
  QElapsedTimer timer;
  timer.start();
  auto const pixmap = QPixmap::fromImage(newImage);
  auto time = timer.elapsed();
  qDebug() << "Pixmap conversion took" << time << "ms.";
  imageLabel->setPixmap(pixmap);
  time = timer.elapsed();
  qDebug() << "Pixmap setting took" << time << "ms.";
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313