How to control the quality/filesize of images copied to the clipboard?
-
I am trying to control the quality/filesize of a QImage/QPixMap that is copied to the clipboard. Is there a simple way to do this?
I have tried using the "quality" parameter of QPixMap::save() to save it to a QByteArray. This works, as I can see the QByteArray's size changes depending on the quality. However, if I then try to recreate a QImage/QPixMap from the QByteArray so I can use the QClipBoard::setImage() or QClipBoard::setPixMap() functions, the filesize of the image in the clipboard is always the largest size!
I have also tried setting the QByteArray directly onto the clipboard using:
QMimeData *mimeData = new QMimeData; mimeData->setData("image/*", bytearray); QApplication::clipboard()->setMimeData(mimeData);
But this is not properly recognized by the clipboard.
-
Hi and welcome to devnet,
I might be wrong but I think you have to replace the
*
with the exact image format you are providing with your QMimeData object. -
Might be a silly question but are you sure your QByteArray contains png data ?
-
This works as expected:
QMimeData *mimeData = new QMimeData; mimeData->setImageData(QImage::fromData(bytearray)); QApplication::clipboard()->setMimeData(mimeData);
But re-creating a QImage from the QByteArray that is in PNG format (with decreased quality) causes the image in the clipboard to once again be max filesize, not the decreased filesize.
-
Isn't the image stored uncompressed in the clipboard ?
-
This works as expected:
QMimeData *mimeData = new QMimeData; mimeData->setImageData(QImage::fromData(bytearray)); QApplication::clipboard()->setMimeData(mimeData);
But re-creating a QImage from the QByteArray that is in PNG format (with decreased quality) causes the image in the clipboard to once again be max filesize, not the decreased filesize.
@btse said in How to control the quality/filesize of images copied to the clipboard?:
QMimeData *mimeData = new QMimeData;
mimeData->setImageData(QImage::fromData(bytearray));
QApplication::clipboard()->setMimeData(mimeData);But re-creating a QImage from the QByteArray that is in PNG format (with decreased quality) causes the image in the clipboard to once again be max filesize, not the decreased filesize.
Then why not simply use the
QMimeData::setData()
method directly?QMimeData *mimeData = new QMimeData; mimeData->setData("image/png", pngByteArray); QApplication::clipboard()->setMimeData(mimeData);
-
@SGaist I don't know...The problem is that QImage and QPixMap have no concept of compression/quality. I believe internally the amount of bytes used is mainly dependent on the dimensions. That's why loading the compressed PNG QByteArray back into a QImage causes the size to go back to its max, uncompressed size.
@raven-worx I did do that. It doesn't work. Nothing is copied to the clipboard. This is my exact code:
QMimeData *mimeData = new QMimeData; mimeData->setData("image/png", generateByteArray(copyDialog)); QApplication::clipboard()->setMimeData(mimeData);
I have verified that the return value of generateByteArray() is a valid PNG format by saving it to a file.
-
@SGaist I don't know...The problem is that QImage and QPixMap have no concept of compression/quality. I believe internally the amount of bytes used is mainly dependent on the dimensions. That's why loading the compressed PNG QByteArray back into a QImage causes the size to go back to its max, uncompressed size.
@raven-worx I did do that. It doesn't work. Nothing is copied to the clipboard. This is my exact code:
QMimeData *mimeData = new QMimeData; mimeData->setData("image/png", generateByteArray(copyDialog)); QApplication::clipboard()->setMimeData(mimeData);
I have verified that the return value of generateByteArray() is a valid PNG format by saving it to a file.
// Make a smaller version of the image (snippet is from http://doc.qt.io/qt-5/qpixmap.html#save-1). QPixmap pixmap; QByteArray bytes; QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); pixmap.save(&buffer, "PNG", 0); // This is where you'd play with the quality parameter // Then save that in the clipboard ... QMimeData *mimeData = new QMimeData; // ...
There's no reason to think Qt should abide by the compression/quality of images when they are in memory; it'd use the most convenient and portable way of representing them. Only when it comes to loading/saving you're to pass how the compression should be done.
-
// Make a smaller version of the image (snippet is from http://doc.qt.io/qt-5/qpixmap.html#save-1). QPixmap pixmap; QByteArray bytes; QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); pixmap.save(&buffer, "PNG", 0); // This is where you'd play with the quality parameter // Then save that in the clipboard ... QMimeData *mimeData = new QMimeData; // ...
There's no reason to think Qt should abide by the compression/quality of images when they are in memory; it'd use the most convenient and portable way of representing them. Only when it comes to loading/saving you're to pass how the compression should be done.
@kshegunov said in How to control the quality/filesize of images copied to the clipboard?:
// Make a smaller version of the image (snippet is from http://doc.qt.io/qt-5/qpixmap.html#save-1). QPixmap pixmap; QByteArray bytes; QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); pixmap.save(&buffer, "PNG", 0); // This is where you'd play with the quality parameter
That's what I did already to generate a lower quality image, but I can't get it into the clipboard properly with a QByteArray.
-
@kshegunov said in How to control the quality/filesize of images copied to the clipboard?:
// Make a smaller version of the image (snippet is from http://doc.qt.io/qt-5/qpixmap.html#save-1). QPixmap pixmap; QByteArray bytes; QBuffer buffer(&bytes); buffer.open(QIODevice::WriteOnly); pixmap.save(&buffer, "PNG", 0); // This is where you'd play with the quality parameter
That's what I did already to generate a lower quality image, but I can't get it into the clipboard properly with a QByteArray.
Perhaps I misunderstood then. What I mean is to save that data into the clipboard with your own mime type. Otherwise I believe Qt does serialization/deserialization through a
QVariant
internally. So try with something like:QMimeData *mimeData = new QMimeData; mimeData->setData("image/x-btse-png", bytes); QApplication::clipboard()->setMimeData(mimeData);
PS:
If that doesn't work, substitute withapplication/octet-stream
and try with it. -
Perhaps I misunderstood then. What I mean is to save that data into the clipboard with your own mime type. Otherwise I believe Qt does serialization/deserialization through a
QVariant
internally. So try with something like:QMimeData *mimeData = new QMimeData; mimeData->setData("image/x-btse-png", bytes); QApplication::clipboard()->setMimeData(mimeData);
PS:
If that doesn't work, substitute withapplication/octet-stream
and try with it.@kshegunov said in How to control the quality/filesize of images copied to the clipboard?:
Perhaps I misunderstood then. What I mean is to save that data into the clipboard with your own mime type. Otherwise I believe Qt does serialization/deserialization through a
QVariant
internally. So try with something like:QMimeData *mimeData = new QMimeData; mimeData->setData("image/x-btse-png", bytes); QApplication::clipboard()->setMimeData(mimeData);
PS:
If that doesn't work, substitute withapplication/octet-stream
and try with it.I tried both suggestions, neither do anything. FYI, this is on Mac OS. Here's a screenshot of the clipboard's contents:
And here is a screenshot of the clipboard when it's working properly, generated with:
QApplication::clipboard()->setImage(QImage::fromData(generateByteArray()));
-
@kshegunov said in How to control the quality/filesize of images copied to the clipboard?:
Perhaps I misunderstood then. What I mean is to save that data into the clipboard with your own mime type. Otherwise I believe Qt does serialization/deserialization through a
QVariant
internally. So try with something like:QMimeData *mimeData = new QMimeData; mimeData->setData("image/x-btse-png", bytes); QApplication::clipboard()->setMimeData(mimeData);
PS:
If that doesn't work, substitute withapplication/octet-stream
and try with it.I tried both suggestions, neither do anything. FYI, this is on Mac OS. Here's a screenshot of the clipboard's contents:
And here is a screenshot of the clipboard when it's working properly, generated with:
QApplication::clipboard()->setImage(QImage::fromData(generateByteArray()));
Something is still unclear to me ... are you trying to reduce the data size in the clipboard, or in your application. And after setting the mime to
application/octet-stream
have you deserialized the data from the receiving end? And how this relates to TIFF images, which are generally quite larger than pngs? -
Something is still unclear to me ... are you trying to reduce the data size in the clipboard, or in your application. And after setting the mime to
application/octet-stream
have you deserialized the data from the receiving end? And how this relates to TIFF images, which are generally quite larger than pngs?@kshegunov said in How to control the quality/filesize of images copied to the clipboard?:
Something is still unclear to me ... are you trying to reduce the data size in the clipboard, or in your application. And after setting the mime to
application/octet-stream
have you deserialized the data from the receiving end? And how this relates to TIFF images, which are generally quite larger than pngs?I am trying to reduce the size of the image in the clipboard. How can I deserialize it? I'm trying to use the contents of the clipboard in other applications, not my own. Example: Copy my image to the clipboard and then paste into a Powerpoint slide. My goal is to reduce the file size of the pasted image.
The screenshot I showed of it working properly is what happens when I copy to the clipboard as a QImage (see the code snippet). I guess internally it's converting it to a TIFF image.
-
@kshegunov said in How to control the quality/filesize of images copied to the clipboard?:
Something is still unclear to me ... are you trying to reduce the data size in the clipboard, or in your application. And after setting the mime to
application/octet-stream
have you deserialized the data from the receiving end? And how this relates to TIFF images, which are generally quite larger than pngs?I am trying to reduce the size of the image in the clipboard. How can I deserialize it? I'm trying to use the contents of the clipboard in other applications, not my own. Example: Copy my image to the clipboard and then paste into a Powerpoint slide. My goal is to reduce the file size of the pasted image.
The screenshot I showed of it working properly is what happens when I copy to the clipboard as a QImage (see the code snippet). I guess internally it's converting it to a TIFF image.
I understand now. Well unfortunately nothing else comes to mind. Does it work if you do nothing about the image and just put it into the clipboard (the ordinary way)?
-
I understand now. Well unfortunately nothing else comes to mind. Does it work if you do nothing about the image and just put it into the clipboard (the ordinary way)?
@kshegunov said in How to control the quality/filesize of images copied to the clipboard?:
Does it work if you do nothing about the image and just put it into the clipboard (the ordinary way)?
Yes that works perfectly fine. But my goal is to reduce the size of the image. A 1289 × 440 image copied to the clipboard has a size of 1.7MB when pasted, which is just way too big. It's making the size of our PowerPoints huge.
-
Then you should also resize your image to be smaller, change the encoding etc.
-
@SGaist said in How to control the quality/filesize of images copied to the clipboard?:
Then you should also resize your image to be smaller, change the encoding etc.
But does quality == image resolution? I guess I could just lower the image resolution, but I'd prefer not to if there's another solution.
By encoding do you mean PNG, JPG, etc? How can I control that at the QImage/QPixMap level? They have no concept of encoding until saved to a QIODevice.
-
You can't, QImage is an uncompressed hardware independent representation of the image that allows direct access to pixel data while QPixmap is an off-screen image representation that you can be used as a paint device so it's hardware dependent.
If you want small images in your PowerPoint document you have to start with the original image and make them lighter.