42 #include "private/qpnghandler_p.h" 44 #ifndef QT_NO_IMAGEFORMAT_PNG 53 #ifdef QT_USE_BUNDLED_LIBPNG 54 #include <../../3rdparty/libpng/png.h> 55 #include <../../3rdparty/libpng/pngconf.h> 61 #if PNG_LIBPNG_VER >= 10400 && PNG_LIBPNG_VER <= 10502 \ 62 && defined(PNG_PEDANTIC_WARNINGS_SUPPORTED) 75 # ifdef PNG_SETJMP_SUPPORTED 76 # define png_jmpbuf(png_ptr) \ 77 (*png_set_longjmp_fn((png_ptr), (png_longjmp_ptr)longjmp, sizeof(jmp_buf))) 79 # define png_jmpbuf(png_ptr) \ 80 (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) 85 #define CALLBACK_CALL_TYPE __cdecl 87 #define CALLBACK_CALL_TYPE 92 #if defined(Q_OS_WINCE) && defined(STANDARDSHELL_UI_MODEL) 93 # define Q_INTERNAL_WIN_NO_THROW __declspec(nothrow) 95 # define Q_INTERNAL_WIN_NO_THROW 99 #define FAST_SCAN_LINE(data, bpl, y) (data + (y) * bpl) 145 #if defined(Q_C_CALLBACKS) 156 void setLooping(
int loops=0);
157 void setFrameDelay(
int msecs);
158 void setGamma(
float);
160 bool writeImage(
const QImage& img,
int x,
int y);
163 {
return writeImage(img, 0, 0); }
165 {
return writeImage(img, quality, description, 0, 0); }
186 uchar endcrc[4] = { 0xae, 0x42, 0x60, 0x82 };
193 int nr = in->
read((
char*)data, length);
195 png_error(png_ptr,
"Read Error");
209 uint nr = out->
write((
char*)data, length);
211 png_error(png_ptr,
"Write Error");
222 #if defined(Q_C_CALLBACKS) 229 if (screen_gamma != 0.0 && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) {
231 png_get_gAMA(png_ptr, info_ptr, &file_gamma);
232 png_set_gamma(png_ptr, screen_gamma, file_gamma);
239 png_bytep trans_alpha = 0;
240 png_color_16p trans_color_p = 0;
242 png_colorp palette = 0;
244 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
245 png_set_interlace_handling(png_ptr);
247 if (color_type == PNG_COLOR_TYPE_GRAY) {
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);
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);
269 if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
270 png_set_swap_alpha(png_ptr);
272 png_read_update_info(png_ptr, info_ptr);
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);
286 for (
int i=0; i<ncols; i++) {
287 int c = i*255/(ncols-1);
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;
297 }
else if (color_type == PNG_COLOR_TYPE_PALETTE
298 && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
299 && num_palette <= 256)
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);
308 image =
QImage(width, height, format);
312 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
315 if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
316 while (i < num_trans) {
327 while (i < num_palette) {
340 png_set_strip_16(png_ptr);
342 png_set_expand(png_ptr);
344 if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
345 png_set_gray_to_rgb(png_ptr);
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);
357 image =
QImage(width, height, format);
362 if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
363 png_set_swap_alpha(png_ptr);
365 png_read_update_info(png_ptr, info_ptr);
369 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
370 png_set_bgr(png_ptr);
375 #if defined(Q_C_CALLBACKS) 380 qWarning(
"libpng warning: %s", message);
383 #if defined(Q_C_CALLBACKS) 393 #ifndef QT_NO_IMAGE_TEXT 396 png_get_text(
png_ptr, info, &text_ptr, &num_text);
401 #if defined(PNG_iTXt_SUPPORTED) 402 if (text_ptr->itxt_length) {
426 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);
434 png_destroy_read_struct(&
png_ptr, 0, 0);
446 if (setjmp(png_jmpbuf(
png_ptr))) {
475 if (setjmp(png_jmpbuf(
png_ptr))) {
493 png_uint_32 width = 0;
494 png_uint_32 height = 0;
495 png_int_32 offset_x = 0;
496 png_int_32 offset_y = 0;
499 int unit_type = PNG_OFFSET_PIXEL;
500 png_get_IHDR(
png_ptr,
info_ptr, &width, &height, &bit_depth, &color_type,
508 for (
uint y = 0; y < height; y++)
513 #if 0 // libpng takes care of this. 517 (
info_ptr->trans_values.red << 8 >> bit_depth)&0xff,
518 (
info_ptr->trans_values.green << 8 >> bit_depth)&0xff,
519 (
info_ptr->trans_values.blue << 8 >> bit_depth)&0xff);
520 for (
uint y=0; y<height; y++) {
522 if (((
uint**)jt)[y][x] == trans) {
523 ((
uint**)jt)[y][x] &= 0x00FFFFFF;
534 if (unit_type == PNG_OFFSET_PIXEL)
540 #ifndef QT_NO_IMAGE_TEXT 552 if (color_type == PNG_COLOR_TYPE_PALETTE
554 int color_table_size = outImage->
colorCount();
555 for (
int y=0; y<(int)height; ++y) {
559 if (*p >= color_table_size)
572 png_uint_32 width, height;
573 int bit_depth, color_type;
576 png_get_IHDR(
png_ptr,
info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
577 if (color_type == PNG_COLOR_TYPE_GRAY) {
581 }
else if (bit_depth == 16 && png_get_valid(
png_ptr,
info_ptr, PNG_INFO_tRNS)) {
586 }
else if (color_type == PNG_COLOR_TYPE_PALETTE
588 && num_palette <= 256)
594 png_get_IHDR(
png_ptr,
info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
603 if (!(color_type & PNG_COLOR_MASK_ALPHA)
616 disposal(Unspecified),
648 #ifndef QT_NO_IMAGE_TEXT 649 static void set_text(
const QImage &image, png_structp png_ptr, png_infop info_ptr,
673 png_textp text_ptr =
new png_text[text.
size()];
674 qMemSet(text_ptr, 0, text.
size() *
sizeof(png_text));
682 #ifdef PNG_iTXt_SUPPORTED 683 bool needsItxt =
false;
686 if (c.
row() || (ch < 0x20 && ch != '\n') || (ch > 0x7e && ch < 0xa0)) {
693 text_ptr[i].compression = noCompress ? PNG_ITXT_COMPRESSION_NONE : PNG_ITXT_COMPRESSION_zTXt;
696 text_ptr[i].itxt_length = value.
size();
697 text_ptr[i].lang =
const_cast<char*
>(
"UTF-8");
703 text_ptr[i].compression = noCompress ? PNG_TEXT_COMPRESSION_NONE : PNG_TEXT_COMPRESSION_zTXt;
706 text_ptr[i].text_length = value.
size();
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;
730 int off_x_in,
int off_y_in)
732 #ifdef QT_NO_IMAGE_TEXT 737 int off_x = off_x_in + offset.
x();
738 int off_y = off_y_in + offset.
y();
743 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);
750 info_ptr = png_create_info_struct(png_ptr);
752 png_destroy_write_struct(&png_ptr, 0);
756 if (setjmp(png_jmpbuf(png_ptr))) {
757 png_destroy_write_struct(&png_ptr, &info_ptr);
761 int quality = quality_in;
764 qWarning(
"PNG: Quality %d out of range", quality);
767 png_set_compression_level(png_ptr, quality);
775 color_type = PNG_COLOR_TYPE_PALETTE;
777 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
779 color_type = PNG_COLOR_TYPE_RGB;
781 png_set_IHDR(png_ptr, info_ptr, image.
width(), image.
height(),
782 image.
depth() == 1 ? 1 : 8,
783 color_type, 0, 0, 0);
786 png_set_gAMA(png_ptr, info_ptr, 1.0/
gamma);
794 png_set_sBIT(png_ptr, info_ptr, &sig_bit);
797 png_set_packswap(png_ptr);
802 png_color palette[256];
805 for (
int i=0; i<num_palette; i++) {
807 palette[i].red =
qRed(rgba);
808 palette[i].green =
qGreen(rgba);
809 palette[i].blue =
qBlue(rgba);
811 if (trans[i] < 255) {
815 png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
818 png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);
824 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
825 png_set_swap_alpha(png_ptr);
829 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian
831 png_set_bgr(png_ptr);
834 if (off_x || off_y) {
835 png_set_oFFs(png_ptr, info_ptr, off_x, off_y, PNG_OFFSET_PIXEL);
839 png_set_sig_bytes(png_ptr, 8);
842 png_set_pHYs(png_ptr, info_ptr,
844 PNG_RESOLUTION_METER);
847 #ifndef QT_NO_IMAGE_TEXT 848 set_text(image, png_ptr, info_ptr, description);
850 png_write_info(png_ptr, info_ptr);
852 if (image.
depth() != 1)
853 png_set_packing(png_ptr);
856 png_set_filler(png_ptr, 0,
857 QSysInfo::ByteOrder == QSysInfo::BigEndian ?
858 PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
865 png_write_chunk(png_ptr, (png_byte*)
"gIFx", data, 13);
873 png_write_chunk(png_ptr, (png_byte*)
"gIFg", data, 4);
876 int height = image.
height();
877 int width = image.
width();
886 png_bytep* row_pointers =
new png_bytep[height];
887 for (
int y=0; y<height; y++)
889 png_write_image(png_ptr, row_pointers);
890 delete [] row_pointers;
897 png_bytep row_pointers[1];
898 for (
int y=0; y<height; y++) {
901 png_write_rows(png_ptr, row_pointers, 1);
907 png_write_end(png_ptr, info_ptr);
910 png_destroy_write_struct(&png_ptr, &info_ptr);
920 quality =
qMin(quality, 100);
921 quality = (100-quality) * 9 / 91;
924 return writer.
writeImage(image, quality, description);
955 qWarning(
"QPngHandler::canRead() called with no device");
959 return device->
peek(8) ==
"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
976 return option ==
Gamma 996 else if (option ==
Size)
1006 if (option ==
Gamma)
1021 #endif // QT_NO_IMAGEFORMAT_PNG The QVariant class acts like a union for the most common Qt data types.
Format
The following image formats are available in Qt.
virtual qint64 size() const
For open random-access devices, this function returns the size of the device.
void setFormat(const QByteArray &format)
Sets the format of the QImageIOHandler to format.
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
void setColor(int i, QRgb c)
Sets the color at the given index in the color table, to the given to colorValue. ...
static mach_timebase_info_data_t info
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
#define QT_END_NAMESPACE
This macro expands to.
const Key key(const T &value) const
Returns the first key with value value.
#define it(className, varName)
Q_GUI_EXPORT_INLINE int qAlpha(QRgb rgb)
void readPngTexts(png_info *info)
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
bool isNull() const
Returns true if it is a null image, otherwise returns false.
The QByteArray class provides an array of bytes.
int length() const
Returns the number of characters in this string.
virtual qint64 pos() const
For random-access devices, this function returns the position that data is written to or read from...
static void CALLBACK_CALL_TYPE qpiw_flush_fn(png_structp)
#define FAST_SCAN_LINE(data, bpl, y)
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
int size() const
Returns the number of (key, value) pairs in the map.
bool hasAlphaChannel() const
Returns true if the image has a format that respects the alpha channel, otherwise returns false...
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
int bytesPerLine() const
Returns the number of bytes per image scanline.
int dotsPerMeterY() const
Returns the number of pixels that fit vertically in a physical meter.
The QString class provides a Unicode character string.
void setOption(ImageOption option, const QVariant &value)
Sets the option option with the value value.
The QChar class provides a 16-bit Unicode character.
QPoint offset() const
Returns the number of pixels by which the image is intended to be offset by when positioning relative...
Format format() const
Returns the format of the image.
Q_GUI_EXPORT_INLINE int qRed(QRgb rgb)
static bool write_png_image(const QImage &image, QIODevice *device, int quality, float gamma, const QString &description)
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
void setOffset(const QPoint &)
Sets the number of pixels by which the image is intended to be offset by when positioning relative to...
bool read(QImage *image)
Read an image from the device, and stores it in image.
void append(const T &t)
Inserts value at the end of the list.
bool writeImage(const QImage &img, int x, int y)
void setColorCount(int)
Resizes the color table to contain colorCount entries.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Q_GUI_EXPORT_INLINE QRgb qRgba(int r, int g, int b, int a)
QImage::Format readImageFormat()
QVariant option(ImageOption option) const
Returns the value assigned to option as a QVariant.
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
static void CALLBACK_CALL_TYPE qpiw_write_fn(png_structp png_ptr, png_bytep data, png_size_t length)
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
void setText(const QString &key, const QString &value)
Sets the image text to the given text and associate it with the given key.
ImageOption
This enum describes the different options supported by QImageIOHandler.
const T value(const Key &key) const
Returns the value associated with the key key.
const T & at(int i) const
Returns the item at index position i in the list.
The QStringList class provides a list of strings.
QString text(const QString &key=QString()) const
Returns the image text associated with the given key.
qint64 peek(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, without side effects (i.
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Q_CORE_EXPORT void qWarning(const char *,...)
bool readPngImage(QImage *image)
The QImage class provides a hardware-independent image representation that allows direct access to th...
static const char * data(const QByteArray &arr)
QPNGImageWriter(QIODevice *)
int indexOf(QChar c, int from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
void setDotsPerMeterY(int)
Sets the number of pixels that fit vertically in a physical meter, to y.
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
int depth() const
Returns the depth of the image.
The State element defines configurations of objects and properties.
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the map.
Q_GUI_EXPORT_INLINE int qBlue(QRgb rgb)
virtual bool isSequential() const
Returns true if this device is sequential; otherwise returns false.
QSize size() const
Returns the size of the image, i.
const uchar * constScanLine(int) const
Returns a pointer to the pixel data at the scanline with index i.
void * qMemCopy(void *dest, const void *src, size_t n)
const char * constData() const
Returns a pointer to the data stored in the byte array.
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...
uchar * bits()
Returns a pointer to the first pixel data.
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the map...
int width() const
Returns the width of the image.
void * qMemSet(void *dest, int c, size_t n)
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const Q_REQUIRED_RESULT
Returns a copy of the image in the given format.
void setDotsPerMeterX(int)
Sets the number of pixels that fit horizontally in a physical meter, to x.
bool supportsOption(ImageOption option) const
Returns true if the QImageIOHandler supports the option option; otherwise returns false...
bool canRead() const
Returns true if an image can be read from the device (i.
int colorCount() const
Returns the size of the color table for the image.
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...
Q_CORE_EXPORT char * qstrdup(const char *)
bool writeImage(const QImage &img)
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
bool writeImage(const QImage &img, int quality, const QString &description)
iterator insert(const Key &key, const T &value)
Inserts a new item with the key key and a value of value.
bool write(const QImage &image)
Writes the image image to the assigned device.
Q_GUI_EXPORT_INLINE QRgb qRgb(int r, int g, int b)
static void CALLBACK_CALL_TYPE iod_read_fn(png_structp png_ptr, png_bytep data, png_size_t length)
The QPoint class defines a point in the plane using integer precision.
#define CALLBACK_CALL_TYPE
int size() const
Returns the number of items in the list.
bool isEmpty() const
Returns true if the map contains no items; otherwise returns false.
float toFloat(bool *ok=0) const
Returns the variant as a float if the variant has type() Double , QMetaType::Float ...
uchar cell() const
Returns the cell (least significant byte) of the Unicode character.
void setFrameDelay(int msecs)
QIODevice * device() const
Returns the device currently assigned to the QImageIOHandler.
int height() const
Returns the height of the image.
static void setup_qt(QImage &image, png_structp png_ptr, png_infop info_ptr, float screen_gamma=0.0)
int size() const
Returns the number of bytes in this byte array.
int y() const
Returns the y coordinate of this point.
Q_GUI_EXPORT_INLINE int qGreen(QRgb rgb)
#define Q_INTERNAL_WIN_NO_THROW
The QSize class defines the size of a two-dimensional object using integer point precision.
void setDisposalMethod(DisposalMethod)
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...
void setLooping(int loops=0)
int x() const
Returns the x coordinate of this point.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
QByteArray name() const
Use format() instead.
static const KeyPair *const end
The QIODevice class is the base interface class of all I/O devices in Qt.
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
virtual bool seek(qint64 pos)
For random-access devices, this function sets the current position to pos, returning true on success...
uchar row() const
Returns the row (most significant byte) of the Unicode character.
int dotsPerMeterX() const
Returns the number of pixels that fit horizontally in a physical meter.
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
QStringList textKeys() const
Returns the text keys for this image.
QRgb color(int i) const
Returns the color in the color table at index i.
QPngHandlerPrivate(QPngHandler *qq)
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)