There is a two-dimensional uchar array containing only two values — 0 and 255 (white and black, respectively). It is necessary to convert this array into an image. How to do it?
2 answers
If the task requires drawing something (including text) on the image or even just displaying the image on the widget, then you need to use the format suitable for that in Qt. In the opposite case, the performance will sag, since if the desired and drawn, then all the same transparently will be performed the image conversion from one format to another.
In Qt, the optimal formats for drawing are QImage::Format_ARGB32_Premultiplied
(if necessary in the alpha channel), QImage::Format_RGB32
and QImage::Format_RGB16
. The Qt raster engine is able to draw images of these formats directly.
Other formats, including QImage::Format_Indexed8
, QImage::Format_Grayscale8
and others, are better considered as intermediate in the drawing problem and can only be used if the original data cannot be converted to the appropriate optimized formats.
All eight-bit formats in Qt use a color table (the so-called palette) and store in the image data for each pixel only the indices corresponding to the data in the palette. For 32-bit formats only, pixel values are stored directly in the image data.
If the palette is not specific, then its creation is usually reduced to adding values from 0
to 255
, somewhere immediately after receiving the image from the original data:
// Одномерный массив исходных данных изображения. uchar *data = ...; // Ширина и высота изображения в пикселях. int width = 320; int height = 240; // Количество байт в одной строке изображения. // Для одноканальных восьмибитных изображений этот параметр // будет равен ширине в пикселях. int stride = 320; // Для трёхканальных - width * 3. // int stride = 320 * 3; QImage img(data, width, height, stride, QImage::Format_Indexed8); // Создание таблицы цветов. QVector<QRgb> color_table; for(int i = 0; i < 256; ++i) color_table->append(qRgb(i,i,i)); img.setColorTable(color_table); // Конвертация изображения в оптимальный для рисования формат. QImage optimal_img = img.convertToFormat(QImage::Format_RGB32);
Of course, optimal_img
will take up more memory than if it were in the original format, but drawing on it, or even just displaying it on the screen, will be much faster.
Not all image formats can be converted to Qt from one to another. In this case, you will need to use intermediate.
- Thank. There was another difficulty, when trying to save an image in Format_Indexed8 format - the program crashes with an error. if you convert, as written in you, to Format_RGB32, then everything is saved (saved via QImageWriter). What could be the problem? - bronstein87 6:49 pm
- @ bronstein87, probably because
Format_Indexed8
not supported as a source when saving to one of the file formats, like png, jpg and others. You need to use theQImageWriter::canWrite()
method to check whether the current format is supported when saving the image to a file to avoid crashing the application. If the method returnsfalse
, then transfer the image to a different format. Well, or as an option, write your own implementation of saving to a custom file format. - alexis031182
QImage::QImage(uchar * data, int width, int height, Format format)
Format set QImage::Format_Indexed8
- It is only necessary to wrap the two-dimensional array in one-dimensional, and to adjust the palette properly. - αλεχολυτ
- Thank. The only thing that I do not really understand. There is a note in the documentation.
Note: Drawing into a QImage with QImage::Format_Indexed8 is not supported
. Ie this means that I can not use, for example, the methodvoid QPainter::drawText
for this image format? I just need to put inscriptions on the images ... - bronstein87 - And one moment. What about the
QImage::Format_Grayscale8
? In theory, he, too, should come. I can not understand, for him the palette is set in the same way? - bronstein87