Qt 4.8
Classes | Macros | Typedefs | Functions | Variables
qjpeghandler.cpp File Reference
#include "qjpeghandler_p.h"
#include <qimage.h>
#include <qvariant.h>
#include <qvector.h>
#include <qbuffer.h>
#include <private/qsimd_p.h>
#include <stdio.h>
#include <setjmp.h>
#include <jpeglib.h>

Go to the source code of this file.

Classes

struct  my_error_mgr
 
struct  my_jpeg_destination_mgr
 
struct  my_jpeg_source_mgr
 
class  QJpegHandlerPrivate
 

Macros

#define HIGH_QUALITY_THRESHOLD   50
 
#define XMD_H
 

Typedefs

typedef void(QT_FASTCALLRgb888ToRgb32Converter) (quint32 *dst, const uchar *src, int len)
 

Functions

void QT_FASTCALL convert_rgb888_to_rgb32_C (quint32 *dst, const uchar *src, int len)
 
static bool ensureValidImage (QImage *dest, struct jpeg_decompress_struct *info, const QSize &size)
 
static void my_error_exit (j_common_ptr cinfo)
 
static boolean qt_empty_output_buffer (j_compress_ptr cinfo)
 
static boolean qt_fill_input_buffer (j_decompress_ptr cinfo)
 
static void qt_init_destination (j_compress_ptr)
 
static void qt_init_source (j_decompress_ptr)
 
static void qt_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
 
static void qt_term_destination (j_compress_ptr cinfo)
 
static void qt_term_source (j_decompress_ptr cinfo)
 
static bool read_jpeg_format (QImage::Format &format, j_decompress_ptr cinfo)
 
static bool read_jpeg_image (QImage *outImage, QSize scaledSize, QRect scaledClipRect, QRect clipRect, int inQuality, j_decompress_ptr info, struct my_error_mgr *err)
 
static bool read_jpeg_size (int &w, int &h, j_decompress_ptr cinfo)
 
static bool write_jpeg_image (const QImage &image, QIODevice *device, int sourceQuality)
 

Variables

static const int max_buf = 4096
 
static Rgb888ToRgb32Converter rgb888ToRgb32ConverterPtr = convert_rgb888_to_rgb32_C
 

Macro Definition Documentation

◆ HIGH_QUALITY_THRESHOLD

#define HIGH_QUALITY_THRESHOLD   50

Definition at line 220 of file qjpeghandler.cpp.

Referenced by read_jpeg_image().

◆ XMD_H

#define XMD_H

Definition at line 67 of file qjpeghandler.cpp.

Typedef Documentation

◆ Rgb888ToRgb32Converter

typedef void(QT_FASTCALL * Rgb888ToRgb32Converter) (quint32 *dst, const uchar *src, int len)

Definition at line 93 of file qjpeghandler.cpp.

Function Documentation

◆ convert_rgb888_to_rgb32_C()

void QT_FASTCALL convert_rgb888_to_rgb32_C ( quint32 dst,
const uchar src,
int  len 
)

Definition at line 84 of file qjpeghandler.cpp.

85 {
86  // Expand 24->32 bpp.
87  for (int i = 0; i < len; ++i) {
88  *dst++ = qRgb(src[0], src[1], src[2]);
89  src += 3;
90  }
91 }
QRgb qRgb(int r, int g, int b)
Returns the ARGB quadruplet (255, {r}, {g}, {b}).
Definition: qrgb.h:69

◆ ensureValidImage()

static bool ensureValidImage ( QImage dest,
struct jpeg_decompress_struct *  info,
const QSize size 
)
static

Definition at line 242 of file qjpeghandler.cpp.

244 {
246  switch (info->output_components) {
247  case 1:
248  format = QImage::Format_Indexed8;
249  break;
250  case 3:
251  case 4:
252  format = QImage::Format_RGB32;
253  break;
254  default:
255  return false; // unsupported format
256  }
257 
258  if (dest->size() != size || dest->format() != format) {
259  *dest = QImage(size, format);
260 
261  if (format == QImage::Format_Indexed8) {
262  dest->setColorCount(256);
263  for (int i = 0; i < 256; i++)
264  dest->setColor(i, qRgb(i,i,i));
265  }
266  }
267 
268  return !dest->isNull();
269 }
Format
The following image formats are available in Qt.
Definition: qimage.h:91
void setColor(int i, QRgb c)
Sets the color at the given index in the color table, to the given to colorValue. ...
Definition: qimage.cpp:1850
static mach_timebase_info_data_t info
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
void setColorCount(int)
Resizes the color table to contain colorCount entries.
Definition: qimage.cpp:2275
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
QSize size() const
Returns the size of the image, i.
Definition: qimage.cpp:1587
QRgb qRgb(int r, int g, int b)
Returns the ARGB quadruplet (255, {r}, {g}, {b}).
Definition: qrgb.h:69

◆ my_error_exit()

static void my_error_exit ( j_common_ptr  cinfo)
static

Definition at line 105 of file qjpeghandler.cpp.

Referenced by QJpegHandlerPrivate::readJpegHeader(), and write_jpeg_image().

106 {
107  my_error_mgr* myerr = (my_error_mgr*) cinfo->err;
108  char buffer[JMSG_LENGTH_MAX];
109  (*cinfo->err->format_message)(cinfo, buffer);
110  qWarning("%s", buffer);
111  longjmp(myerr->setjmp_buffer, 1);
112 }
jmp_buf setjmp_buffer
Q_CORE_EXPORT void qWarning(const char *,...)

◆ qt_empty_output_buffer()

static boolean qt_empty_output_buffer ( j_compress_ptr  cinfo)
static

Definition at line 477 of file qjpeghandler.cpp.

Referenced by my_jpeg_destination_mgr::my_jpeg_destination_mgr().

478 {
479  my_jpeg_destination_mgr* dest = (my_jpeg_destination_mgr*)cinfo->dest;
480 
481  int written = dest->device->write((char*)dest->buffer, max_buf);
482  if (written == -1)
483  (*cinfo->err->error_exit)((j_common_ptr)cinfo);
484 
485  dest->next_output_byte = dest->buffer;
486  dest->free_in_buffer = max_buf;
487 
488  return TRUE;
489 }
static const int max_buf
#define TRUE
Synonym for true.
Definition: qglobal.h:1018
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
JOCTET buffer[max_buf]

◆ qt_fill_input_buffer()

static boolean qt_fill_input_buffer ( j_decompress_ptr  cinfo)
static

Definition at line 139 of file qjpeghandler.cpp.

Referenced by my_jpeg_source_mgr::my_jpeg_source_mgr(), and qt_skip_input_data().

140 {
141  my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src;
142  qint64 num_read = 0;
143  if (src->memDevice) {
144  src->next_input_byte = (const JOCTET *)(src->memDevice->data().constData() + src->memDevice->pos());
145  num_read = src->memDevice->data().size() - src->memDevice->pos();
146  src->device->seek(src->memDevice->data().size());
147  } else {
148  src->next_input_byte = src->buffer;
149  num_read = src->device->read((char*)src->buffer, max_buf);
150  }
151  if (num_read <= 0) {
152  // Insert a fake EOI marker - as per jpeglib recommendation
153  src->next_input_byte = src->buffer;
154  src->buffer[0] = (JOCTET) 0xFF;
155  src->buffer[1] = (JOCTET) JPEG_EOI;
156  src->bytes_in_buffer = 2;
157  } else {
158  src->bytes_in_buffer = num_read;
159  }
160  return TRUE;
161 }
const QByteArray & data() const
Returns the data contained in the buffer.
Definition: qbuffer.cpp:301
static const int max_buf
qint64 pos() const
Reimplemented Function
Definition: qbuffer.cpp:367
JOCTET buffer[max_buf]
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
__int64 qint64
Definition: qglobal.h:942
#define TRUE
Synonym for true.
Definition: qglobal.h:1018
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
if(void) toggleToolbarShown
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qiodevice.cpp:659
const QBuffer * memDevice

◆ qt_init_destination()

static void qt_init_destination ( j_compress_ptr  )
static

Definition at line 473 of file qjpeghandler.cpp.

Referenced by my_jpeg_destination_mgr::my_jpeg_destination_mgr().

474 {
475 }

◆ qt_init_source()

static void qt_init_source ( j_decompress_ptr  )
static

Definition at line 135 of file qjpeghandler.cpp.

Referenced by my_jpeg_source_mgr::my_jpeg_source_mgr().

136 {
137 }

◆ qt_skip_input_data()

static void qt_skip_input_data ( j_decompress_ptr  cinfo,
long  num_bytes 
)
static

Definition at line 163 of file qjpeghandler.cpp.

Referenced by my_jpeg_source_mgr::my_jpeg_source_mgr().

164 {
165  my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src;
166 
167  // `dumb' implementation from jpeglib
168 
169  /* Just a dumb implementation for now. Could use fseek() except
170  * it doesn't work on pipes. Not clear that being smart is worth
171  * any trouble anyway --- large skips are infrequent.
172  */
173  if (num_bytes > 0) {
174  while (num_bytes > (long) src->bytes_in_buffer) { // Should not happen in case of memDevice
175  num_bytes -= (long) src->bytes_in_buffer;
176  (void) qt_fill_input_buffer(cinfo);
177  /* note we assume that qt_fill_input_buffer will never return false,
178  * so suspension need not be handled.
179  */
180  }
181  src->next_input_byte += (size_t) num_bytes;
182  src->bytes_in_buffer -= (size_t) num_bytes;
183  }
184 }
static boolean qt_fill_input_buffer(j_decompress_ptr cinfo)
if(void) toggleToolbarShown

◆ qt_term_destination()

static void qt_term_destination ( j_compress_ptr  cinfo)
static

Definition at line 491 of file qjpeghandler.cpp.

Referenced by my_jpeg_destination_mgr::my_jpeg_destination_mgr().

492 {
493  my_jpeg_destination_mgr* dest = (my_jpeg_destination_mgr*)cinfo->dest;
494  qint64 n = max_buf - dest->free_in_buffer;
495 
496  qint64 written = dest->device->write((char*)dest->buffer, n);
497  if (written == -1)
498  (*cinfo->err->error_exit)((j_common_ptr)cinfo);
499 }
static const int max_buf
__int64 qint64
Definition: qglobal.h:942
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
JOCTET buffer[max_buf]

◆ qt_term_source()

static void qt_term_source ( j_decompress_ptr  cinfo)
static

Definition at line 186 of file qjpeghandler.cpp.

Referenced by my_jpeg_source_mgr::my_jpeg_source_mgr().

187 {
188  my_jpeg_source_mgr* src = (my_jpeg_source_mgr*)cinfo->src;
189  if (!src->device->isSequential())
190  src->device->seek(src->device->pos() - src->bytes_in_buffer);
191 }
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from...
Definition: qiodevice.cpp:624
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
Definition: qiodevice.cpp:454
if(void) toggleToolbarShown
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
Definition: qiodevice.cpp:659

◆ read_jpeg_format()

static bool read_jpeg_format ( QImage::Format format,
j_decompress_ptr  cinfo 
)
inlinestatic

Definition at line 222 of file qjpeghandler.cpp.

223 {
224 
225  bool result = true;
226  switch (cinfo->output_components) {
227  case 1:
229  break;
230  case 3:
231  case 4:
233  break;
234  default:
235  result = false;
236  break;
237  }
238  cinfo->output_scanline = cinfo->output_height;
239  return result;
240 }

◆ read_jpeg_image()

static bool read_jpeg_image ( QImage outImage,
QSize  scaledSize,
QRect  scaledClipRect,
QRect  clipRect,
int  inQuality,
j_decompress_ptr  info,
struct my_error_mgr err 
)
static

Definition at line 271 of file qjpeghandler.cpp.

Referenced by QJpegHandlerPrivate::read().

274 {
275  if (!setjmp(err->setjmp_buffer)) {
276  // -1 means default quality.
277  int quality = inQuality;
278  if (quality < 0)
279  quality = 75;
280 
281  // If possible, merge the scaledClipRect into either scaledSize
282  // or clipRect to avoid doing a separate scaled clipping pass.
283  // Best results are achieved by clipping before scaling, not after.
284  if (!scaledClipRect.isEmpty()) {
285  if (scaledSize.isEmpty() && clipRect.isEmpty()) {
286  // No clipping or scaling before final clip.
287  clipRect = scaledClipRect;
288  scaledClipRect = QRect();
289  } else if (scaledSize.isEmpty()) {
290  // Clipping, but no scaling: combine the clip regions.
291  scaledClipRect.translate(clipRect.topLeft());
292  clipRect = scaledClipRect.intersected(clipRect);
293  scaledClipRect = QRect();
294  } else if (clipRect.isEmpty()) {
295  // No clipping, but scaling: if we can map back to an
296  // integer pixel boundary, then clip before scaling.
297  if ((info->image_width % scaledSize.width()) == 0 &&
298  (info->image_height % scaledSize.height()) == 0) {
299  int x = scaledClipRect.x() * info->image_width /
300  scaledSize.width();
301  int y = scaledClipRect.y() * info->image_height /
302  scaledSize.height();
303  int width = (scaledClipRect.right() + 1) *
304  info->image_width / scaledSize.width() - x;
305  int height = (scaledClipRect.bottom() + 1) *
306  info->image_height / scaledSize.height() - y;
307  clipRect = QRect(x, y, width, height);
308  scaledSize = scaledClipRect.size();
309  scaledClipRect = QRect();
310  }
311  } else {
312  // Clipping and scaling: too difficult to figure out,
313  // and not a likely use case, so do it the long way.
314  }
315  }
316 
317  // Determine the scale factor to pass to libjpeg for quick downscaling.
318  if (!scaledSize.isEmpty()) {
319  if (clipRect.isEmpty()) {
320  info->scale_denom =
321  qMin(info->image_width / scaledSize.width(),
322  info->image_height / scaledSize.height());
323  } else {
324  info->scale_denom =
325  qMin(clipRect.width() / scaledSize.width(),
326  clipRect.height() / scaledSize.height());
327  }
328  if (info->scale_denom < 2) {
329  info->scale_denom = 1;
330  } else if (info->scale_denom < 4) {
331  info->scale_denom = 2;
332  } else if (info->scale_denom < 8) {
333  info->scale_denom = 4;
334  } else {
335  info->scale_denom = 8;
336  }
337  info->scale_num = 1;
338  if (!clipRect.isEmpty()) {
339  // Correct the scale factor so that we clip accurately.
340  // It is recommended that the clip rectangle be aligned
341  // on an 8-pixel boundary for best performance.
342  while (info->scale_denom > 1 &&
343  ((clipRect.x() % info->scale_denom) != 0 ||
344  (clipRect.y() % info->scale_denom) != 0 ||
345  (clipRect.width() % info->scale_denom) != 0 ||
346  (clipRect.height() % info->scale_denom) != 0)) {
347  info->scale_denom /= 2;
348  }
349  }
350  }
351 
352  // If high quality not required, use fast decompression
353  if( quality < HIGH_QUALITY_THRESHOLD ) {
354  info->dct_method = JDCT_IFAST;
355  info->do_fancy_upsampling = FALSE;
356  }
357 
358  (void) jpeg_calc_output_dimensions(info);
359 
360  // Determine the clip region to extract.
361  QRect imageRect(0, 0, info->output_width, info->output_height);
362  QRect clip;
363  if (clipRect.isEmpty()) {
364  clip = imageRect;
365  } else if (info->scale_denom == info->scale_num) {
366  clip = clipRect.intersected(imageRect);
367  } else {
368  // The scale factor was corrected above to ensure that
369  // we don't miss pixels when we scale the clip rectangle.
370  clip = QRect(clipRect.x() / int(info->scale_denom),
371  clipRect.y() / int(info->scale_denom),
372  clipRect.width() / int(info->scale_denom),
373  clipRect.height() / int(info->scale_denom));
374  clip = clip.intersected(imageRect);
375  }
376 
377  // Allocate memory for the clipped QImage.
378  if (!ensureValidImage(outImage, info, clip.size()))
379  longjmp(err->setjmp_buffer, 1);
380 
381  // Avoid memcpy() overhead if grayscale with no clipping.
382  bool quickGray = (info->output_components == 1 &&
383  clip == imageRect);
384  if (!quickGray) {
385  // Ask the jpeg library to allocate a temporary row.
386  // The library will automatically delete it for us later.
387  // The libjpeg docs say we should do this before calling
388  // jpeg_start_decompress(). We can't use "new" here
389  // because we are inside the setjmp() block and an error
390  // in the jpeg input stream would cause a memory leak.
391  JSAMPARRAY rows = (info->mem->alloc_sarray)
392  ((j_common_ptr)info, JPOOL_IMAGE,
393  info->output_width * info->output_components, 1);
394 
395  (void) jpeg_start_decompress(info);
396 
397  while (info->output_scanline < info->output_height) {
398  int y = int(info->output_scanline) - clip.y();
399  if (y >= clip.height())
400  break; // We've read the entire clip region, so abort.
401 
402  (void) jpeg_read_scanlines(info, rows, 1);
403 
404  if (y < 0)
405  continue; // Haven't reached the starting line yet.
406 
407  if (info->output_components == 3) {
408  uchar *in = rows[0] + clip.x() * 3;
409  QRgb *out = (QRgb*)outImage->scanLine(y);
410  rgb888ToRgb32ConverterPtr(out, in, clip.width());
411  } else if (info->out_color_space == JCS_CMYK) {
412  // Convert CMYK->RGB.
413  uchar *in = rows[0] + clip.x() * 4;
414  QRgb *out = (QRgb*)outImage->scanLine(y);
415  for (int i = 0; i < clip.width(); ++i) {
416  int k = in[3];
417  *out++ = qRgb(k * in[0] / 255, k * in[1] / 255,
418  k * in[2] / 255);
419  in += 4;
420  }
421  } else if (info->output_components == 1) {
422  // Grayscale.
423  memcpy(outImage->scanLine(y),
424  rows[0] + clip.x(), clip.width());
425  }
426  }
427  } else {
428  // Load unclipped grayscale data directly into the QImage.
429  (void) jpeg_start_decompress(info);
430  while (info->output_scanline < info->output_height) {
431  uchar *row = outImage->scanLine(info->output_scanline);
432  (void) jpeg_read_scanlines(info, &row, 1);
433  }
434  }
435 
436  if (info->output_scanline == info->output_height)
437  (void) jpeg_finish_decompress(info);
438 
439  if (info->density_unit == 1) {
440  outImage->setDotsPerMeterX(int(100. * info->X_density / 2.54));
441  outImage->setDotsPerMeterY(int(100. * info->Y_density / 2.54));
442  } else if (info->density_unit == 2) {
443  outImage->setDotsPerMeterX(int(100. * info->X_density));
444  outImage->setDotsPerMeterY(int(100. * info->Y_density));
445  }
446 
447  if (scaledSize.isValid() && scaledSize != clip.size()) {
449  }
450 
451  if (!scaledClipRect.isEmpty())
452  *outImage = outImage->copy(scaledClipRect);
453  return !outImage->isNull();
454  }
455  else
456  return false;
457 }
#define HIGH_QUALITY_THRESHOLD
unsigned int QRgb
Definition: qrgb.h:53
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Definition: qimage.cpp:1410
static mach_timebase_info_data_t info
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
QRect intersected(const QRect &other) const
Returns the intersection of this rectangle and the given rectangle.
Definition: qrect.h:481
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
jmp_buf setjmp_buffer
unsigned char uchar
Definition: qglobal.h:994
int width() const
Returns the width.
Definition: qsize.h:126
static bool ensureValidImage(QImage *dest, struct jpeg_decompress_struct *info, const QSize &size)
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
#define FALSE
Synonym for false.
Definition: qglobal.h:1019
void setDotsPerMeterY(int)
Sets the number of pixels that fit vertically in a physical meter, to y.
Definition: qimage.cpp:5667
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:234
QRgb qRgb(int r, int g, int b)
Returns the ARGB quadruplet (255, {r}, {g}, {b}).
Definition: qrgb.h:69
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
void setDotsPerMeterX(int)
Sets the number of pixels that fit horizontally in a physical meter, to x.
Definition: qimage.cpp:5645
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
bool isValid() const
Returns true if both the width and height is equal to or greater than 0; otherwise returns false...
Definition: qsize.h:123
bool isEmpty() const
Returns true if either of the width and height is less than or equal to 0; otherwise returns false...
Definition: qsize.h:120
static Rgb888ToRgb32Converter rgb888ToRgb32ConverterPtr
QImage scaled(int w, int h, Qt::AspectRatioMode aspectMode=Qt::IgnoreAspectRatio, Qt::TransformationMode mode=Qt::FastTransformation) const
Definition: qimage.h:232
void translate(int dx, int dy)
Moves the rectangle dx along the x axis and dy along the y axis, relative to the current position...
Definition: qrect.h:312
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
QPoint topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:288

◆ read_jpeg_size()

static bool read_jpeg_size ( int &  w,
int &  h,
j_decompress_ptr  cinfo 
)
inlinestatic

Definition at line 211 of file qjpeghandler.cpp.

212 {
213  (void) jpeg_calc_output_dimensions(cinfo);
214 
215  w = cinfo->output_width;
216  h = cinfo->output_height;
217  return true;
218 }

◆ write_jpeg_image()

static bool write_jpeg_image ( const QImage image,
QIODevice device,
int  sourceQuality 
)
static

Definition at line 516 of file qjpeghandler.cpp.

Referenced by QJpegHandler::write().

517 {
518  bool success = false;
519  const QVector<QRgb> cmap = image.colorTable();
520 
521  struct jpeg_compress_struct cinfo;
522  JSAMPROW row_pointer[1];
523  row_pointer[0] = 0;
524 
525  struct my_jpeg_destination_mgr *iod_dest = new my_jpeg_destination_mgr(device);
526  struct my_error_mgr jerr;
527 
528  cinfo.err = jpeg_std_error(&jerr);
529  jerr.error_exit = my_error_exit;
530 
531  if (!setjmp(jerr.setjmp_buffer)) {
532  // WARNING:
533  // this if loop is inside a setjmp/longjmp branch
534  // do not create C++ temporaries here because the destructor may never be called
535  // if you allocate memory, make sure that you can free it (row_pointer[0])
536  jpeg_create_compress(&cinfo);
537 
538  cinfo.dest = iod_dest;
539 
540  cinfo.image_width = image.width();
541  cinfo.image_height = image.height();
542 
543  bool gray=false;
544  switch (image.format()) {
545  case QImage::Format_Mono:
548  gray = true;
549  for (int i = image.colorCount(); gray && i--;) {
550  gray = gray & (qRed(cmap[i]) == qGreen(cmap[i]) &&
551  qRed(cmap[i]) == qBlue(cmap[i]));
552  }
553  cinfo.input_components = gray ? 1 : 3;
554  cinfo.in_color_space = gray ? JCS_GRAYSCALE : JCS_RGB;
555  break;
556  default:
557  cinfo.input_components = 3;
558  cinfo.in_color_space = JCS_RGB;
559  }
560 
561  jpeg_set_defaults(&cinfo);
562 
563  qreal diffInch = qAbs(image.dotsPerMeterX()*2.54/100. - qRound(image.dotsPerMeterX()*2.54/100.))
564  + qAbs(image.dotsPerMeterY()*2.54/100. - qRound(image.dotsPerMeterY()*2.54/100.));
565  qreal diffCm = (qAbs(image.dotsPerMeterX()/100. - qRound(image.dotsPerMeterX()/100.))
566  + qAbs(image.dotsPerMeterY()/100. - qRound(image.dotsPerMeterY()/100.)))*2.54;
567  if (diffInch < diffCm) {
568  cinfo.density_unit = 1; // dots/inch
569  cinfo.X_density = qRound(image.dotsPerMeterX()*2.54/100.);
570  cinfo.Y_density = qRound(image.dotsPerMeterY()*2.54/100.);
571  } else {
572  cinfo.density_unit = 2; // dots/cm
573  cinfo.X_density = (image.dotsPerMeterX()+50) / 100;
574  cinfo.Y_density = (image.dotsPerMeterY()+50) / 100;
575  }
576 
577 
578  int quality = sourceQuality >= 0 ? qMin(sourceQuality,100) : 75;
579  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
580  jpeg_start_compress(&cinfo, TRUE);
581 
582  row_pointer[0] = new uchar[cinfo.image_width*cinfo.input_components];
583  int w = cinfo.image_width;
584  while (cinfo.next_scanline < cinfo.image_height) {
585  uchar *row = row_pointer[0];
586  switch (image.format()) {
587  case QImage::Format_Mono:
589  if (gray) {
590  const uchar* data = image.constScanLine(cinfo.next_scanline);
591  if (image.format() == QImage::Format_MonoLSB) {
592  for (int i=0; i<w; i++) {
593  bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7)));
594  row[i] = qRed(cmap[bit]);
595  }
596  } else {
597  for (int i=0; i<w; i++) {
598  bool bit = !!(*(data + (i >> 3)) & (1 << (7 -(i & 7))));
599  row[i] = qRed(cmap[bit]);
600  }
601  }
602  } else {
603  const uchar* data = image.constScanLine(cinfo.next_scanline);
604  if (image.format() == QImage::Format_MonoLSB) {
605  for (int i=0; i<w; i++) {
606  bool bit = !!(*(data + (i >> 3)) & (1 << (i & 7)));
607  *row++ = qRed(cmap[bit]);
608  *row++ = qGreen(cmap[bit]);
609  *row++ = qBlue(cmap[bit]);
610  }
611  } else {
612  for (int i=0; i<w; i++) {
613  bool bit = !!(*(data + (i >> 3)) & (1 << (7 -(i & 7))));
614  *row++ = qRed(cmap[bit]);
615  *row++ = qGreen(cmap[bit]);
616  *row++ = qBlue(cmap[bit]);
617  }
618  }
619  }
620  break;
622  if (gray) {
623  const uchar* pix = image.constScanLine(cinfo.next_scanline);
624  for (int i=0; i<w; i++) {
625  *row = qRed(cmap[*pix]);
626  ++row; ++pix;
627  }
628  } else {
629  const uchar* pix = image.constScanLine(cinfo.next_scanline);
630  for (int i=0; i<w; i++) {
631  *row++ = qRed(cmap[*pix]);
632  *row++ = qGreen(cmap[*pix]);
633  *row++ = qBlue(cmap[*pix]);
634  ++pix;
635  }
636  }
637  break;
639  memcpy(row, image.constScanLine(cinfo.next_scanline), w * 3);
640  break;
644  {
645  const QRgb* rgb = (const QRgb*)image.constScanLine(cinfo.next_scanline);
646  for (int i=0; i<w; i++) {
647  *row++ = qRed(*rgb);
648  *row++ = qGreen(*rgb);
649  *row++ = qBlue(*rgb);
650  ++rgb;
651  }
652  }
653  break;
654  default:
655  {
656  // (Testing shows that this way is actually faster than converting to RGB888 + memcpy)
657  QImage rowImg = image.copy(0, cinfo.next_scanline, w, 1).convertToFormat(QImage::Format_RGB32);
658  const QRgb* rgb = (const QRgb*)rowImg.constScanLine(0);
659  for (int i=0; i<w; i++) {
660  *row++ = qRed(*rgb);
661  *row++ = qGreen(*rgb);
662  *row++ = qBlue(*rgb);
663  ++rgb;
664  }
665  }
666  break;
667  }
668  jpeg_write_scanlines(&cinfo, row_pointer, 1);
669  }
670 
671  jpeg_finish_compress(&cinfo);
672  jpeg_destroy_compress(&cinfo);
673  success = true;
674  } else {
675  jpeg_destroy_compress(&cinfo);
676  success = false;
677  }
678 
679  delete iod_dest;
680  delete [] row_pointer[0];
681  return success;
682 }
unsigned int QRgb
Definition: qrgb.h:53
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Definition: qimage.cpp:1410
double qreal
Definition: qglobal.h:1193
static void my_error_exit(j_common_ptr cinfo)
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
static QColor cmap[256]
Definition: qgl_mac.mm:760
int dotsPerMeterY() const
Returns the number of pixels that fit vertically in a physical meter.
Definition: qimage.cpp:5628
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
int qRed(QRgb rgb)
Returns the red component of the ARGB quadruplet rgb.
Definition: qrgb.h:57
Format format() const
Returns the format of the image.
Definition: qimage.cpp:2305
unsigned char uchar
Definition: qglobal.h:994
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
static const char * data(const QByteArray &arr)
my_jpeg_destination_mgr(QIODevice *)
#define rgb(r, g, b)
Definition: qcolor_p.cpp:130
const uchar * constScanLine(int) const
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1926
#define TRUE
Synonym for true.
Definition: qglobal.h:1018
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const Q_REQUIRED_RESULT
Returns a copy of the image in the given format.
Definition: qimage.cpp:3966
int colorCount() const
Returns the size of the color table for the image.
Definition: qimage.cpp:1656
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
int qGreen(QRgb rgb)
Returns the green component of the ARGB quadruplet rgb.
Definition: qrgb.h:60
int qBlue(QRgb rgb)
Returns the blue component of the ARGB quadruplet rgb.
Definition: qrgb.h:63
int dotsPerMeterX() const
Returns the number of pixels that fit horizontally in a physical meter.
Definition: qimage.cpp:5615
QVector< QRgb > colorTable() const
Returns a list of the colors contained in the image&#39;s color table, or an empty list if the image does...
Definition: qimage.cpp:1770
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203

Variable Documentation

◆ max_buf

const int max_buf = 4096
static

◆ rgb888ToRgb32ConverterPtr

Rgb888ToRgb32Converter rgb888ToRgb32ConverterPtr = convert_rgb888_to_rgb32_C
static

Definition at line 95 of file qjpeghandler.cpp.

Referenced by QJpegHandler::QJpegHandler().