Qt 4.8
Classes | Macros | Functions
qpnghandler.cpp File Reference
#include "private/qpnghandler_p.h"
#include <qcoreapplication.h>
#include <qiodevice.h>
#include <qimage.h>
#include <qlist.h>
#include <qtextcodec.h>
#include <qvariant.h>
#include <qvector.h>
#include <png.h>
#include <pngconf.h>

Go to the source code of this file.

Classes

class  QPngHandlerPrivate
 
class  QPNGImageWriter
 

Macros

#define CALLBACK_CALL_TYPE   __cdecl
 
#define FAST_SCAN_LINE(data, bpl, y)   (data + (y) * bpl)
 
#define Q_INTERNAL_WIN_NO_THROW
 

Functions

static void CALLBACK_CALL_TYPE iod_read_fn (png_structp png_ptr, png_bytep data, png_size_t length)
 
static void CALLBACK_CALL_TYPE qpiw_flush_fn (png_structp)
 
static void CALLBACK_CALL_TYPE qpiw_write_fn (png_structp png_ptr, png_bytep data, png_size_t length)
 
static void CALLBACK_CALL_TYPE qt_png_warning (png_structp, png_const_charp message)
 
static void set_text (const QImage &image, png_structp png_ptr, png_infop info_ptr, const QString &description)
 
static void setup_qt (QImage &image, png_structp png_ptr, png_infop info_ptr, float screen_gamma=0.0)
 
static bool write_png_image (const QImage &image, QIODevice *device, int quality, float gamma, const QString &description)
 

Macro Definition Documentation

◆ CALLBACK_CALL_TYPE

#define CALLBACK_CALL_TYPE   __cdecl

Definition at line 85 of file qpnghandler.cpp.

◆ FAST_SCAN_LINE

#define FAST_SCAN_LINE (   data,
  bpl,
 
)    (data + (y) * bpl)

Definition at line 99 of file qpnghandler.cpp.

Referenced by QPngHandlerPrivate::readPngImage().

◆ Q_INTERNAL_WIN_NO_THROW

#define Q_INTERNAL_WIN_NO_THROW

Definition at line 95 of file qpnghandler.cpp.

Function Documentation

◆ iod_read_fn()

static void CALLBACK_CALL_TYPE iod_read_fn ( png_structp  png_ptr,
png_bytep  data,
png_size_t  length 
)
static

Definition at line 179 of file qpnghandler.cpp.

Referenced by QPngHandlerPrivate::readPngHeader().

180 {
181  QPngHandlerPrivate *d = (QPngHandlerPrivate *)png_get_io_ptr(png_ptr);
182  QIODevice *in = d->q->device();
183 
184  if (d->state == QPngHandlerPrivate::ReadingEnd && !in->isSequential() && (in->size() - in->pos()) < 4 && length == 4) {
185  // Workaround for certain malformed PNGs that lack the final crc bytes
186  uchar endcrc[4] = { 0xae, 0x42, 0x60, 0x82 };
187  qMemCopy(data, endcrc, 4);
188  in->seek(in->size());
189  return;
190  }
191 
192  while (length) {
193  int nr = in->read((char*)data, length);
194  if (nr <= 0) {
195  png_error(png_ptr, "Read Error");
196  return;
197  }
198  length -= nr;
199  }
200 }
double d
Definition: qnumeric_p.h:62
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
Definition: qiodevice.cpp:642
QPngHandler * q
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
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
unsigned char uchar
Definition: qglobal.h:994
static const char * data(const QByteArray &arr)
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
Definition: qiodevice.cpp:454
void * qMemCopy(void *dest, const void *src, size_t n)
Definition: qglobal.cpp:2508
QIODevice * device() const
Returns the device currently assigned to the QImageIOHandler.
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
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

◆ qpiw_flush_fn()

static void CALLBACK_CALL_TYPE qpiw_flush_fn ( png_structp  )
static

Definition at line 218 of file qpnghandler.cpp.

Referenced by QPNGImageWriter::writeImage().

219 {
220 }

◆ qpiw_write_fn()

static void CALLBACK_CALL_TYPE qpiw_write_fn ( png_structp  png_ptr,
png_bytep  data,
png_size_t  length 
)
static

Definition at line 204 of file qpnghandler.cpp.

Referenced by QPNGImageWriter::writeImage().

205 {
206  QPNGImageWriter* qpiw = (QPNGImageWriter*)png_get_io_ptr(png_ptr);
207  QIODevice* out = qpiw->device();
208 
209  uint nr = out->write((char*)data, length);
210  if (nr != length) {
211  png_error(png_ptr, "Write Error");
212  return;
213  }
214 }
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
QIODevice * device()
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66

◆ qt_png_warning()

static void CALLBACK_CALL_TYPE qt_png_warning ( png_structp  ,
png_const_charp  message 
)
static

Definition at line 378 of file qpnghandler.cpp.

Referenced by QPngHandlerPrivate::readPngHeader(), and QPNGImageWriter::writeImage().

379 {
380  qWarning("libpng warning: %s", message);
381 }
Q_CORE_EXPORT void qWarning(const char *,...)

◆ set_text()

static void set_text ( const QImage image,
png_structp  png_ptr,
png_infop  info_ptr,
const QString description 
)
static

Definition at line 649 of file qpnghandler.cpp.

Referenced by QPNGImageWriter::writeImage().

651 {
653  foreach (const QString &key, image.textKeys()) {
654  if (!key.isEmpty())
655  text.insert(key, image.text(key));
656  }
657  foreach (const QString &pair, description.split(QLatin1String("\n\n"))) {
658  int index = pair.indexOf(QLatin1Char(':'));
659  if (index >= 0 && pair.indexOf(QLatin1Char(' ')) < index) {
660  QString s = pair.simplified();
661  if (!s.isEmpty())
662  text.insert(QLatin1String("Description"), s);
663  } else {
664  QString key = pair.left(index);
665  if (!key.simplified().isEmpty())
666  text.insert(key, pair.mid(index + 2).simplified());
667  }
668  }
669 
670  if (text.isEmpty())
671  return;
672 
673  png_textp text_ptr = new png_text[text.size()];
674  qMemSet(text_ptr, 0, text.size() * sizeof(png_text));
675 
677  int i = 0;
678  while (it != text.constEnd()) {
679  text_ptr[i].key = qstrdup(it.key().left(79).toLatin1().constData());
680  bool noCompress = (it.value().length() < 40);
681 
682 #ifdef PNG_iTXt_SUPPORTED
683  bool needsItxt = false;
684  foreach(const QChar c, it.value()) {
685  uchar ch = c.cell();
686  if (c.row() || (ch < 0x20 && ch != '\n') || (ch > 0x7e && ch < 0xa0)) {
687  needsItxt = true;
688  break;
689  }
690  }
691 
692  if (needsItxt) {
693  text_ptr[i].compression = noCompress ? PNG_ITXT_COMPRESSION_NONE : PNG_ITXT_COMPRESSION_zTXt;
694  QByteArray value = it.value().toUtf8();
695  text_ptr[i].text = qstrdup(value.constData());
696  text_ptr[i].itxt_length = value.size();
697  text_ptr[i].lang = const_cast<char*>("UTF-8");
698  text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());
699  }
700  else
701 #endif
702  {
703  text_ptr[i].compression = noCompress ? PNG_TEXT_COMPRESSION_NONE : PNG_TEXT_COMPRESSION_zTXt;
704  QByteArray value = it.value().toLatin1();
705  text_ptr[i].text = qstrdup(value.constData());
706  text_ptr[i].text_length = value.size();
707  }
708  ++i;
709  ++it;
710  }
711 
712  png_set_text(png_ptr, info_ptr, text_ptr, i);
713  for (i = 0; i < text.size(); ++i) {
714  delete [] text_ptr[i].key;
715  delete [] text_ptr[i].text;
716 #ifdef PNG_iTXt_SUPPORTED
717  delete [] text_ptr[i].lang_key;
718 #endif
719  }
720  delete [] text_ptr;
721 }
unsigned char c[8]
Definition: qnumeric_p.h:62
const Key key(const T &value) const
Returns the first key with value value.
Definition: qmap.h:844
#define it(className, varName)
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
int size() const
Returns the number of (key, value) pairs in the map.
Definition: qmap.h:201
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
unsigned char uchar
Definition: qglobal.h:994
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
const T value(const Key &key) const
Returns the value associated with the key key.
Definition: qmap.h:499
QString text(const QString &key=QString()) const
Returns the image text associated with the given key.
Definition: qimage.cpp:5736
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:2838
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the map.
Definition: qmap.h:374
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the map...
Definition: qmap.h:380
void * qMemSet(void *dest, int c, size_t n)
Definition: qglobal.cpp:2509
QString simplified() const Q_REQUIRED_RESULT
Returns a string that has whitespace removed from the start and the end, and that has each sequence o...
Definition: qstring.cpp:4415
iterator insert(const Key &key, const T &value)
Inserts a new item with the key key and a value of value.
Definition: qmap.h:559
int key
bool isEmpty() const
Returns true if the map contains no items; otherwise returns false.
Definition: qmap.h:203
uchar cell() const
Returns the cell (least significant byte) of the Unicode character.
Definition: qchar.h:283
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
quint16 index
char * qstrdup(const char *src)
Returns a duplicate string.
Definition: qbytearray.cpp:114
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
uchar row() const
Returns the row (most significant byte) of the Unicode character.
Definition: qchar.h:284
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
QStringList textKeys() const
Returns the text keys for this image.
Definition: qimage.cpp:5724
#define text
Definition: qobjectdefs.h:80

◆ setup_qt()

static void setup_qt ( QImage image,
png_structp  png_ptr,
png_infop  info_ptr,
float  screen_gamma = 0.0 
)
static

Definition at line 227 of file qpnghandler.cpp.

Referenced by QPngHandlerPrivate::readPngImage().

228 {
229  if (screen_gamma != 0.0 && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) {
230  double file_gamma;
231  png_get_gAMA(png_ptr, info_ptr, &file_gamma);
232  png_set_gamma(png_ptr, screen_gamma, file_gamma);
233  }
234 
235  png_uint_32 width;
236  png_uint_32 height;
237  int bit_depth;
238  int color_type;
239  png_bytep trans_alpha = 0;
240  png_color_16p trans_color_p = 0;
241  int num_trans;
242  png_colorp palette = 0;
243  int num_palette;
244  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
245  png_set_interlace_handling(png_ptr);
246 
247  if (color_type == PNG_COLOR_TYPE_GRAY) {
248  // Black & White or 8-bit grayscale
249  if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
250  png_set_invert_mono(png_ptr);
251  png_read_update_info(png_ptr, info_ptr);
252  if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {
253  image = QImage(width, height, QImage::Format_Mono);
254  if (image.isNull())
255  return;
256  }
257  image.setColorCount(2);
258  image.setColor(1, qRgb(0,0,0));
259  image.setColor(0, qRgb(255,255,255));
260  } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
261  png_set_expand(png_ptr);
262  png_set_strip_16(png_ptr);
263  png_set_gray_to_rgb(png_ptr);
264  if (image.size() != QSize(width, height) || image.format() != QImage::Format_ARGB32) {
265  image = QImage(width, height, QImage::Format_ARGB32);
266  if (image.isNull())
267  return;
268  }
269  if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
270  png_set_swap_alpha(png_ptr);
271 
272  png_read_update_info(png_ptr, info_ptr);
273  } else {
274  if (bit_depth == 16)
275  png_set_strip_16(png_ptr);
276  else if (bit_depth < 8)
277  png_set_packing(png_ptr);
278  int ncols = bit_depth < 8 ? 1 << bit_depth : 256;
279  png_read_update_info(png_ptr, info_ptr);
280  if (image.size() != QSize(width, height) || image.format() != QImage::Format_Indexed8) {
281  image = QImage(width, height, QImage::Format_Indexed8);
282  if (image.isNull())
283  return;
284  }
285  image.setColorCount(ncols);
286  for (int i=0; i<ncols; i++) {
287  int c = i*255/(ncols-1);
288  image.setColor(i, qRgba(c,c,c,0xff));
289  }
290  if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
291  const int g = trans_color_p->gray;
292  if (g < ncols) {
293  image.setColor(g, 0);
294  }
295  }
296  }
297  } else if (color_type == PNG_COLOR_TYPE_PALETTE
298  && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
299  && num_palette <= 256)
300  {
301  // 1-bit and 8-bit color
302  if (bit_depth != 1)
303  png_set_packing(png_ptr);
304  png_read_update_info(png_ptr, info_ptr);
305  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
307  if (image.size() != QSize(width, height) || image.format() != format) {
308  image = QImage(width, height, format);
309  if (image.isNull())
310  return;
311  }
312  png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
313  image.setColorCount(num_palette);
314  int i = 0;
315  if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
316  while (i < num_trans) {
317  image.setColor(i, qRgba(
318  palette[i].red,
319  palette[i].green,
320  palette[i].blue,
321  trans_alpha[i]
322  )
323  );
324  i++;
325  }
326  }
327  while (i < num_palette) {
328  image.setColor(i, qRgba(
329  palette[i].red,
330  palette[i].green,
331  palette[i].blue,
332  0xff
333  )
334  );
335  i++;
336  }
337  } else {
338  // 32-bit
339  if (bit_depth == 16)
340  png_set_strip_16(png_ptr);
341 
342  png_set_expand(png_ptr);
343 
344  if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
345  png_set_gray_to_rgb(png_ptr);
346 
348  // Only add filler if no alpha, or we can get 5 channel data.
349  if (!(color_type & PNG_COLOR_MASK_ALPHA)
350  && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
351  png_set_filler(png_ptr, 0xff, QSysInfo::ByteOrder == QSysInfo::BigEndian ?
352  PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
353  // We want 4 bytes, but it isn't an alpha channel
354  format = QImage::Format_RGB32;
355  }
356  if (image.size() != QSize(width, height) || image.format() != format) {
357  image = QImage(width, height, format);
358  if (image.isNull())
359  return;
360  }
361 
362  if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
363  png_set_swap_alpha(png_ptr);
364 
365  png_read_update_info(png_ptr, info_ptr);
366  }
367 
368  // Qt==ARGB==Big(ARGB)==Little(BGRA)
369  if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
370  png_set_bgr(png_ptr);
371  }
372 }
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
unsigned char c[8]
Definition: qnumeric_p.h:62
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
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
QRgb qRgba(int r, int g, int b, int a)
Returns the ARGB quadruplet ({a}, {r}, {g}, {b}).
Definition: qrgb.h:72

◆ write_png_image()

static bool write_png_image ( const QImage image,
QIODevice device,
int  quality,
float  gamma,
const QString description 
)
static

Definition at line 915 of file qpnghandler.cpp.

Referenced by QPngHandler::write().

917 {
918  QPNGImageWriter writer(device);
919  if (quality >= 0) {
920  quality = qMin(quality, 100);
921  quality = (100-quality) * 9 / 91; // map [0,100] -> [9,0]
922  }
923  writer.setGamma(gamma);
924  return writer.writeImage(image, quality, description);
925 }
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215