summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qpnghandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image/qpnghandler.cpp')
-rw-r--r--src/gui/image/qpnghandler.cpp137
1 files changed, 63 insertions, 74 deletions
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index d5406cb..dd31834 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -50,8 +50,13 @@
#include <qvariant.h>
#include <qvector.h>
+#ifdef QT_USE_BUNDLED_LIBPNG
+#include <../../3rdparty/libpng/png.h>
+#include <../../3rdparty/libpng/pngconf.h>
+#else
#include <png.h>
#include <pngconf.h>
+#endif
#ifdef Q_OS_WINCE
#define CALLBACK_CALL_TYPE __cdecl
@@ -162,11 +167,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
png_uint_32 height;
int bit_depth;
int color_type;
+ png_bytep trans_alpha = 0;
+ png_color_16p trans_color_p = 0;
+ int num_trans;
+ png_colorp palette = 0;
+ int num_palette;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
if (color_type == PNG_COLOR_TYPE_GRAY) {
// Black & White or 8-bit grayscale
- if (bit_depth == 1 && info_ptr->channels == 1) {
+ if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
png_set_invert_mono(png_ptr);
png_read_update_info(png_ptr, info_ptr);
if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {
@@ -207,20 +217,16 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
int c = i*255/(ncols-1);
image.setColor(i, qRgba(c,c,c,0xff));
}
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
- const int g = info_ptr->trans_values.gray;
-#else
- const int g = info_ptr->trans_color.gray;
-#endif
+ if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
+ const int g = trans_color_p->gray;
if (g < ncols) {
image.setColor(g, 0);
}
}
}
} else if (color_type == PNG_COLOR_TYPE_PALETTE
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
- && info_ptr->num_palette <= 256)
+ && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+ && num_palette <= 256)
{
// 1-bit and 8-bit color
if (bit_depth != 1)
@@ -233,29 +239,26 @@ void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, float scre
if (image.isNull())
return;
}
- image.setColorCount(info_ptr->num_palette);
+ png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
+ image.setColorCount(num_palette);
int i = 0;
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
- while (i < info_ptr->num_trans) {
+ if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
+ while (i < num_trans) {
image.setColor(i, qRgba(
- info_ptr->palette[i].red,
- info_ptr->palette[i].green,
- info_ptr->palette[i].blue,
-#if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4)
- info_ptr->trans[i]
-#else
- info_ptr->trans_alpha[i]
-#endif
+ palette[i].red,
+ palette[i].green,
+ palette[i].blue,
+ trans_alpha[i]
)
);
i++;
}
}
- while (i < info_ptr->num_palette) {
+ while (i < num_palette) {
image.setColor(i, qRgba(
- info_ptr->palette[i].red,
- info_ptr->palette[i].green,
- info_ptr->palette[i].blue,
+ palette[i].red,
+ palette[i].green,
+ palette[i].blue,
0xff
)
);
@@ -531,33 +534,36 @@ QImage::Format QPngHandlerPrivate::readImageFormat()
QImage::Format format = QImage::Format_Invalid;
png_uint_32 width, height;
int bit_depth, color_type;
- if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) {
+ png_colorp palette;
+ int num_palette;
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
+ if (color_type == PNG_COLOR_TYPE_GRAY) {
// Black & White or 8-bit grayscale
- if (info_ptr->bit_depth == 1 && info_ptr->channels == 1) {
+ if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
format = QImage::Format_Mono;
- } else if (info_ptr->bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
format = QImage::Format_ARGB32;
} else {
format = QImage::Format_Indexed8;
}
- } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)
- && info_ptr->num_palette <= 256)
+ } else if (color_type == PNG_COLOR_TYPE_PALETTE
+ && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
+ && num_palette <= 256)
{
// 1-bit and 8-bit color
- if (info_ptr->bit_depth != 1)
+ if (bit_depth != 1)
png_set_packing(png_ptr);
png_read_update_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
} else {
// 32-bit
- if (info_ptr->bit_depth == 16)
+ if (bit_depth == 16)
png_set_strip_16(png_ptr);
format = QImage::Format_ARGB32;
// Only add filler if no alpha, or we can get 5 channel data.
- if (!(info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if (!(color_type & PNG_COLOR_MASK_ALPHA)
&& !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
// We want 4 bytes, but it isn't an alpha channel
format = QImage::Format_RGB32;
@@ -648,7 +654,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
text_ptr[i].text = qstrdup(value.constData());
text_ptr[i].text_length = 0;
text_ptr[i].itxt_length = value.size();
- text_ptr[i].lang = "UTF-8";
+ text_ptr[i].lang = const_cast<char*>("UTF-8");
text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());
#endif
++i;
@@ -735,64 +741,51 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_set_compression_level(png_ptr, quality);
}
- if (gamma != 0.0) {
- png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
- }
-
png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);
- info_ptr->channels =
- (image.depth() == 32)
- ? (image.format() == QImage::Format_RGB32 ? 3 : 4)
- : 1;
-
png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),
image.depth() == 1 ? 1 : 8 /* per channel */,
image.depth() == 32
? image.format() == QImage::Format_RGB32
? PNG_COLOR_TYPE_RGB
: PNG_COLOR_TYPE_RGB_ALPHA
- : PNG_COLOR_TYPE_PALETTE, 0, 0, 0);
+ : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); // also sets #channels
+ if (gamma != 0.0) {
+ png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);
+ }
- //png_set_sBIT(png_ptr, info_ptr, 8);
- info_ptr->sig_bit.red = 8;
- info_ptr->sig_bit.green = 8;
- info_ptr->sig_bit.blue = 8;
+ png_color_8 sig_bit;
+ sig_bit.red = 8;
+ sig_bit.green = 8;
+ sig_bit.blue = 8;
+ sig_bit.alpha = image.hasAlphaChannel() ? 8 : 0;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
if (image.format() == QImage::Format_MonoLSB)
png_set_packswap(png_ptr);
- png_colorp palette = 0;
- png_bytep copy_trans = 0;
if (image.colorCount()) {
// Paletted
- int num_palette = image.colorCount();
- palette = new png_color[num_palette];
- png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
- int* trans = new int[num_palette];
+ int num_palette = qMin(256, image.colorCount());
+ png_color palette[256];
+ png_byte trans[256];
int num_trans = 0;
for (int i=0; i<num_palette; i++) {
- QRgb rgb=image.color(i);
- info_ptr->palette[i].red = qRed(rgb);
- info_ptr->palette[i].green = qGreen(rgb);
- info_ptr->palette[i].blue = qBlue(rgb);
- trans[i] = rgb >> 24;
+ QRgb rgba=image.color(i);
+ palette[i].red = qRed(rgba);
+ palette[i].green = qGreen(rgba);
+ palette[i].blue = qBlue(rgba);
+ trans[i] = qAlpha(rgba);
if (trans[i] < 255) {
num_trans = i+1;
}
}
+ png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
+
if (num_trans) {
- copy_trans = new png_byte[num_trans];
- for (int i=0; i<num_trans; i++)
- copy_trans[i] = trans[i];
- png_set_tRNS(png_ptr, info_ptr, copy_trans, num_trans, 0);
+ png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);
}
- delete [] trans;
- }
-
- if (image.format() != QImage::Format_RGB32) {
- info_ptr->sig_bit.alpha = 8;
}
// Swap ARGB to RGBA (normal PNG format) before saving on
@@ -868,11 +861,6 @@ bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image_in,
png_write_end(png_ptr, info_ptr);
frames_written++;
- if (palette)
- delete [] palette;
- if (copy_trans)
- delete [] copy_trans;
-
png_destroy_write_struct(&png_ptr, &info_ptr);
return true;
@@ -958,7 +946,8 @@ QVariant QPngHandler::option(ImageOption option) const
else if (option == Description)
return d->description;
else if (option == Size)
- return QSize(d->info_ptr->width, d->info_ptr->height);
+ return QSize(png_get_image_width(d->png_ptr, d->info_ptr),
+ png_get_image_height(d->png_ptr, d->info_ptr));
else if (option == ImageFormat)
return d->readImageFormat();
return 0;