15#include <private/qicc_p.h>
16#include <private/qsimd_p.h>
17#include <private/qimage_p.h>
52 (*cinfo->err->output_message)(cinfo);
59 char buffer[JMSG_LENGTH_MAX];
60 (*cinfo->err->format_message)(cinfo,
buffer);
90 src->next_input_byte = (
const JOCTET *)(
src->memDevice->data().constData() +
src->memDevice->pos());
91 num_read =
src->memDevice->data().size() -
src->memDevice->pos();
92 src->device->seek(
src->memDevice->data().size());
94 src->next_input_byte =
src->buffer;
99 src->next_input_byte =
src->buffer;
100 src->buffer[0] = (JOCTET) 0xFF;
101 src->buffer[1] = (JOCTET) JPEG_EOI;
102 src->bytes_in_buffer = 2;
104 src->bytes_in_buffer = num_read;
120 while (num_bytes > (
long)
src->bytes_in_buffer) {
121 num_bytes -= (long)
src->bytes_in_buffer;
127 src->next_input_byte += (size_t) num_bytes;
128 src->bytes_in_buffer -= (size_t) num_bytes;
135 if (!
src->device->isSequential())
136 src->device->seek(
src->device->pos() -
src->bytes_in_buffer);
146 jpeg_source_mgr::resync_to_restart = jpeg_resync_to_restart;
157 (
void) jpeg_calc_output_dimensions(cinfo);
159 w = cinfo->output_width;
160 h = cinfo->output_height;
164#define HIGH_QUALITY_THRESHOLD 50
170 switch (cinfo->output_components) {
182 cinfo->output_scanline = cinfo->output_height;
190 switch (
info->output_components) {
207 QRect clipRect,
int quality,
219 if (!scaledClipRect.
isEmpty()) {
222 clipRect = scaledClipRect;
223 scaledClipRect =
QRect();
224 }
else if (scaledSize.
isEmpty()) {
228 scaledClipRect =
QRect();
229 }
else if (clipRect.
isEmpty()) {
232 if ((
info->image_width % scaledSize.
width()) == 0 &&
233 (
info->image_height % scaledSize.
height()) == 0) {
234 int x = scaledClipRect.
x() *
info->image_width /
236 int y = scaledClipRect.
y() *
info->image_height /
243 scaledSize = scaledClipRect.
size();
244 scaledClipRect =
QRect();
253 if (!scaledSize.
isEmpty() &&
info->image_width &&
info->image_height) {
256 double(
info->image_height) / scaledSize.
height());
261 info->scale_denom = 8;
268 if (
info->scale_denom < 2)
269 info->scale_denom = 1;
270 else if (
info->scale_denom < 4)
271 info->scale_denom = 2;
272 else if (
info->scale_denom < 8)
273 info->scale_denom = 4;
275 info->scale_denom = 8;
281 while (
info->scale_denom > 1 &&
282 ((clipRect.
x() %
info->scale_denom) != 0 ||
283 (clipRect.
y() %
info->scale_denom) != 0 ||
284 (clipRect.
width() %
info->scale_denom) != 0 ||
285 (clipRect.
height() %
info->scale_denom) != 0)) {
286 info->scale_denom /= 2;
293 info->dct_method = JDCT_IFAST;
294 info->do_fancy_upsampling = FALSE;
297 (
void) jpeg_calc_output_dimensions(
info);
300 QRect imageRect(0, 0,
info->output_width,
info->output_height);
304 }
else if (
info->scale_denom ==
info->scale_num) {
309 clip =
QRect(clipRect.
x() /
int(
info->scale_denom),
310 clipRect.
y() /
int(
info->scale_denom),
311 clipRect.
width() /
int(
info->scale_denom),
321 bool quickGray = (
info->output_components == 1 &&
330 JSAMPARRAY rows = (
info->mem->alloc_sarray)
331 ((j_common_ptr)
info, JPOOL_IMAGE,
332 info->output_width *
info->output_components, 1);
336 while (
info->output_scanline <
info->output_height) {
337 int y = int(
info->output_scanline) - clip.
y();
341 (
void) jpeg_read_scanlines(
info, rows, 1);
346 if (
info->output_components == 3) {
350 }
else if (
info->out_color_space == JCS_CMYK) {
354 for (
int i = 0;
i < clip.
width(); ++
i) {
360 }
else if (
info->output_components == 1) {
363 rows[0] + clip.
x(), clip.
width());
369 while (
info->output_scanline <
info->output_height) {
375 if (
info->output_scanline ==
info->output_height)
376 (
void) jpeg_finish_decompress(
info);
378 if (
info->density_unit == 1) {
381 }
else if (
info->density_unit == 2) {
386 if (scaledSize.
isValid() && scaledSize != clip.
size()) {
391 *outImage = outImage->
copy(scaledClipRect);
392 return !outImage->
isNull();
422 (*cinfo->err->error_exit)((j_common_ptr)cinfo);
424 dest->next_output_byte = dest->
buffer;
425 dest->free_in_buffer =
max_buf;
437 (*cinfo->err->error_exit)((j_common_ptr)cinfo);
448 next_output_byte =
buffer;
461 comment +=
it.value().toUtf8();
464 jpeg_write_marker(cinfo, JPEG_COM, (
const JOCTET *)comment.
constData(), comment.
size());
474 const QByteArray iccSignature(
"ICC_PROFILE", 12);
477 const int markers = (iccProfile.
size() + (maxIccMarkerSize - 1)) / maxIccMarkerSize;
484 jpeg_write_marker(cinfo, JPEG_APP0 + 2,
reinterpret_cast<const JOCTET *
>(block.
constData()), block.
size());
490 JSAMPROW *row_pointer,
498 bool success =
false;
507 cinfo.err = jpeg_std_error(&jerr);
516 jpeg_create_compress(&cinfo);
518 cinfo.dest = iod_dest;
520 cinfo.image_width =
image.width();
521 cinfo.image_height =
image.height();
524 switch (
image.format()) {
529 for (
int i =
image.colorCount(); gray &&
i;
i--) {
532 cinfo.input_components = gray ? 1 : 3;
533 cinfo.in_color_space = gray ? JCS_GRAYSCALE : JCS_RGB;
538 cinfo.input_components = 1;
539 cinfo.in_color_space = JCS_GRAYSCALE;
542 cinfo.input_components = 3;
543 cinfo.in_color_space = JCS_RGB;
546 jpeg_set_defaults(&cinfo);
552 if (diffInch < diffCm) {
553 cinfo.density_unit = 1;
554 cinfo.X_density =
qRound(
image.dotsPerMeterX()*2.54/100.);
555 cinfo.Y_density =
qRound(
image.dotsPerMeterY()*2.54/100.);
557 cinfo.density_unit = 2;
558 cinfo.X_density = (
image.dotsPerMeterX()+50) / 100;
559 cinfo.Y_density = (
image.dotsPerMeterY()+50) / 100;
563 cinfo.optimize_coding =
true;
566 jpeg_simple_progression(&cinfo);
568 int quality = sourceQuality >= 0 ?
qMin(
int(sourceQuality),100) : 75;
569 jpeg_set_quality(&cinfo, quality, TRUE );
570 jpeg_start_compress(&cinfo, TRUE);
573 if (cinfo.in_color_space == JCS_RGB)
576 row_pointer[0] =
new uchar[cinfo.image_width*cinfo.input_components];
577 int w = cinfo.image_width;
578 while (cinfo.next_scanline < cinfo.image_height) {
580 switch (
image.format()) {
586 for (
int i=0;
i<
w;
i++) {
587 bool bit = !!(*(
data + (
i >> 3)) & (1 << (
i & 7)));
591 for (
int i=0;
i<
w;
i++) {
592 bool bit = !!(*(
data + (
i >> 3)) & (1 << (7 -(
i & 7))));
599 for (
int i=0;
i<
w;
i++) {
600 bool bit = !!(*(
data + (
i >> 3)) & (1 << (
i & 7)));
606 for (
int i=0;
i<
w;
i++) {
607 bool bit = !!(*(
data + (
i >> 3)) & (1 << (7 -(
i & 7))));
618 for (
int i=0;
i<
w;
i++) {
624 for (
int i=0;
i<
w;
i++) {
633 memcpy(
row,
image.constScanLine(cinfo.next_scanline),
w);
642 memcpy(
row,
image.constScanLine(cinfo.next_scanline),
w * 3);
649 for (
int i=0;
i<
w;
i++) {
662 for (
int i=0;
i<
w;
i++) {
671 jpeg_write_scanlines(&cinfo, row_pointer, 1);
674 jpeg_finish_compress(&cinfo);
675 jpeg_destroy_compress(&cinfo);
679 jpeg_destroy_compress(&cinfo);
696 struct jpeg_compress_struct cinfo;
697 JSAMPROW row_pointer[1];
698 row_pointer[0] =
nullptr;
702 sourceQuality, description,
703 optimize, progressive);
705 delete [] row_pointer[0];
728 jpeg_destroy_decompress(&
info);
748 struct jpeg_decompress_struct
info;
765 if (
stream.readRawData(prefix,
sizeof(prefix)) !=
sizeof(prefix))
767 static const char exifMagic[6] = {
'E',
'x',
'i',
'f', 0, 0};
768 return memcmp(prefix, exifMagic, 6) == 0;
787 const int maxIfdCount = 10;
796 const qint64 headerStart = 6;
803 else if (
val == 0x4d4d)
816 for (
int n = 0;
n < maxIfdCount; ++
n) {
820 if (bytesToSkip < 0 || (
offset + headerStart >= exifData.
size())) {
823 }
else if (bytesToSkip != 0) {
844 if (value < 1 || value > 8)
865static QImageIOHandler::Transformations
exif2Qt(
int exifOrientation)
867 switch (exifOrientation) {
885 qCWarning(lcJpeg,
"Invalid EXIF orientation");
899 info.err = jpeg_std_error(&
err);
903 jpeg_create_decompress(&
info);
907 jpeg_save_markers(&
info, JPEG_COM, 0xFFFF);
908 jpeg_save_markers(&
info, JPEG_APP0 + 1, 0xFFFF);
909 jpeg_save_markers(&
info, JPEG_APP0 + 2, 0xFFFF);
911 (
void) jpeg_read_header(&
info, TRUE);
924 if (
marker->marker == JPEG_COM) {
925#ifndef QT_NO_IMAGEIO_TEXT_LOADING
942 }
else if (
marker->marker == JPEG_APP0 + 1) {
944 }
else if (
marker->marker == JPEG_APP0 + 2) {
945 if (
marker->data_length > 128 + 4 + 14 && strcmp((
const char *)
marker->data,
"ICC_PROFILE") == 0) {
954 if (exifOrientation > 0)
1003#if defined(__ARM_NEON__)
1009#if defined(QT_COMPILER_SUPPORTS_SSSE3)
1015#if defined(QT_COMPILER_SUPPORTS_MIPS_DSPR2)
1043 qCWarning(lcJpeg,
"QJpegHandler::canRead() called with no device");
1093 return d->scaledSize;
1095 return d->scaledClipRect;
1100 return d->description;
1110 return d->progressive;
1113 return int(
d->transformation);
1125 d->quality =
value.toInt();
1128 d->scaledSize =
value.toSize();
1131 d->scaledClipRect =
value.toRect();
1134 d->clipRect =
value.toRect();
1137 d->description =
value.toString();
1140 d->optimize =
value.toBool();
1143 d->progressive =
value.toBool();
1146 int transformation =
value.toInt();
1147 if (transformation > 0 && transformation < 8)
1148 d->transformation = QImageIOHandler::Transformations(transformation);
IOBluetoothDevice * device
\inmodule QtCore \reentrant
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
void truncate(qsizetype pos)
Truncates the byte array at index position pos.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray mid(qsizetype index, qsizetype len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos.
static QColorSpace fromIccProfile(const QByteArray &iccProfile)
Creates a QColorSpace from ICC profile iccProfile.
\inmodule QtCore\reentrant
\inmodule QtCore \reentrant
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
qint64 peek(char *data, qint64 maxlen)
The QImageIOHandler class defines the common image I/O interface for all image formats in Qt.
ImageOption
This enum describes the different options supported by QImageIOHandler.
static bool allocateImage(QSize size, QImage::Format format, QImage *image)
QIODevice * device() const
Returns the device currently assigned to the QImageIOHandler.
@ TransformationRotate270
@ TransformationFlipAndRotate90
@ TransformationMirrorAndRotate90
@ TransformationRotate180
void setFormat(const QByteArray &format)
Sets the format of the QImageIOHandler to format.
void setDotsPerMeterY(int)
Sets the number of pixels that fit vertically in a physical meter, to y.
QImage scaled(int w, int h, Qt::AspectRatioMode aspectMode=Qt::IgnoreAspectRatio, Qt::TransformationMode mode=Qt::FastTransformation) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Format
The following image formats are available in Qt.
@ Format_ARGB32_Premultiplied
const uchar * constScanLine(int) const
Returns a pointer to the pixel data at the scanline with index i.
void setDotsPerMeterX(int)
Sets the number of pixels that fit horizontally in a physical meter, to x.
bool readJpegHeader(QIODevice *)
struct jpeg_decompress_struct info
Rgb888ToRgb32Converter rgb888ToRgb32ConverterPtr
QJpegHandlerPrivate(QJpegHandler *qq)
struct my_jpeg_source_mgr * iod_src
QImageIOHandler::Transformations transformation
bool supportsOption(ImageOption option) const override
Returns true if the QImageIOHandler supports the option option; otherwise returns false.
bool read(QImage *image) override
Read an image from the device, and stores it in image.
void setOption(ImageOption option, const QVariant &value) override
Sets the option option with the value value.
QVariant option(ImageOption option) const override
Returns the value assigned to option as a QVariant.
bool write(const QImage &image) override
Writes the image image to the assigned device.
bool canRead() const override
Returns true if an image can be read from the device (i.e., the image format is supported,...
\inmodule QtCore\reentrant
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
constexpr int height() const noexcept
Returns the height of the rectangle.
QRect intersected(const QRect &other) const noexcept
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr QSize size() const noexcept
Returns the size of the rectangle.
constexpr void translate(int dx, int dy) noexcept
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position.
constexpr int width() const noexcept
Returns the width of the rectangle.
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
\macro QT_RESTRICTED_CAST_FROM_ASCII
iterator begin()
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first character in the string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
iterator end()
Returns an \l{STL-style iterators}{STL-style iterator} pointing just after the last character in the ...
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QSet< QString >::iterator it
Combined button and popup list for selecting options.
#define QT_WARNING_DISABLE_GCC(text)
AudioChannelLayoutTag tag
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
int qRound(qfloat16 d) noexcept
Q_GUI_EXPORT void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient)
QMap< QString, QString > qt_getImageText(const QImage &image, const QString &description)
void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(uint *dst, const uchar *src, int len)
static void my_error_exit(j_common_ptr cinfo)
#define HIGH_QUALITY_THRESHOLD
static void qt_init_source(j_decompress_ptr)
static bool write_jpeg_image(const QImage &image, QIODevice *device, int sourceQuality, const QString &description, bool optimize, bool progressive)
static bool do_write_jpeg_image(struct jpeg_compress_struct &cinfo, JSAMPROW *row_pointer, const QImage &image, QIODevice *device, int sourceQuality, const QString &description, bool optimize, bool progressive)
static void my_output_message(j_common_ptr cinfo)
static void qt_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
static void set_text(const QImage &image, j_compress_ptr cinfo, const QString &description)
static void write_icc_profile(const QImage &image, j_compress_ptr cinfo)
static bool readExifHeader(QDataStream &stream)
void(QT_FASTCALL * Rgb888ToRgb32Converter)(quint32 *dst, const uchar *src, int len)
static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info, const QSize &size)
static constexpr int maxMarkerSize
static bool read_jpeg_format(QImage::Format &format, j_decompress_ptr cinfo)
static void qt_init_destination(j_compress_ptr)
static void qt_term_destination(j_compress_ptr cinfo)
void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orient)
static void qt_term_source(j_decompress_ptr cinfo)
static bool read_jpeg_size(int &w, int &h, j_decompress_ptr cinfo)
static int getExifOrientation(QByteArray &exifData)
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, const uchar *src, int len)
Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, const uchar *src, int len)
void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uchar *src, int len)
static boolean qt_empty_output_buffer(j_compress_ptr cinfo)
static boolean qt_fill_input_buffer(j_decompress_ptr cinfo)
static bool read_jpeg_image(QImage *outImage, QSize scaledSize, QRect scaledClipRect, QRect clipRect, int quality, Rgb888ToRgb32Converter converter, j_decompress_ptr info, struct my_error_mgr *err)
QT_BEGIN_NAMESPACE Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32(quint32 *dst, const uchar *src, int len)
static QImageIOHandler::Transformations exif2Qt(int exifOrientation)
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qBound(const T &min, const T &val, const T &max)
constexpr T qAbs(const T &t)
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLint GLenum GLint components
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
GLfloat GLfloat GLfloat GLfloat h
GLdouble GLdouble GLdouble GLdouble q
GLenum GLenum GLsizei void * row
constexpr bool qIsGray(QRgb rgb)
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
constexpr QRgb qRgb(int r, int g, int b)
constexpr int qRed(QRgb rgb)
constexpr int qGreen(QRgb rgb)
constexpr int qBlue(QRgb rgb)
#define qCpuHasFeature(feature)
QLatin1StringView QLatin1String
QFileInfo info(fileName)
[8]
QTextStream out(stdout)
[7]
\inmodule QtCore \reentrant
my_jpeg_destination_mgr(QIODevice *)
my_jpeg_source_mgr(QIODevice *device)
const QBuffer * memDevice