OpenCoverage

qpnghandler.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/image/qpnghandler.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>-
4** Copyright (C) 2016 The Qt Company Ltd.-
5** Contact: https://www.qt.io/licensing/-
6**-
7** This file is part of the QtGui module of the Qt Toolkit.-
8**-
9** $QT_BEGIN_LICENSE:LGPL$-
10** Commercial License Usage-
11** Licensees holding valid commercial Qt licenses may use this file in-
12** accordance with the commercial license agreement provided with the-
13** Software or, alternatively, in accordance with the terms contained in-
14** a written agreement between you and The Qt Company. For licensing terms-
15** and conditions see https://www.qt.io/terms-conditions. For further-
16** information use the contact form at https://www.qt.io/contact-us.-
17**-
18** GNU Lesser General Public License Usage-
19** Alternatively, this file may be used under the terms of the GNU Lesser-
20** General Public License version 3 as published by the Free Software-
21** Foundation and appearing in the file LICENSE.LGPL3 included in the-
22** packaging of this file. Please review the following information to-
23** ensure the GNU Lesser General Public License version 3 requirements-
24** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
25**-
26** GNU General Public License Usage-
27** Alternatively, this file may be used under the terms of the GNU-
28** General Public License version 2.0 or (at your option) the GNU General-
29** Public license version 3 or any later version approved by the KDE Free-
30** Qt Foundation. The licenses are as published by the Free Software-
31** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
32** included in the packaging of this file. Please review the following-
33** information to ensure the GNU General Public License requirements will-
34** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
35** https://www.gnu.org/licenses/gpl-3.0.html.-
36**-
37** $QT_END_LICENSE$-
38**-
39****************************************************************************/-
40-
41#include "private/qpnghandler_p.h"-
42-
43#ifndef QT_NO_IMAGEFORMAT_PNG-
44#include <qcoreapplication.h>-
45#include <qiodevice.h>-
46#include <qimage.h>-
47#include <qlist.h>-
48#include <qtextcodec.h>-
49#include <qvariant.h>-
50#include <qvector.h>-
51-
52#include <png.h>-
53#include <pngconf.h>-
54-
55#if PNG_LIBPNG_VER >= 10400 && PNG_LIBPNG_VER <= 10502 \-
56 && defined(PNG_PEDANTIC_WARNINGS_SUPPORTED)-
57/*-
58 Versions 1.4.0 to 1.5.2 of libpng declare png_longjmp_ptr to-
59 have a noreturn attribute if PNG_PEDANTIC_WARNINGS_SUPPORTED-
60 is enabled, but most declarations of longjmp in the wild do-
61 not add this attribute. This causes problems when the png_jmpbuf-
62 macro expands to calling png_set_longjmp_fn with a mismatched-
63 longjmp, as compilers such as Clang will treat this as an error.-
64-
65 To work around this we override the png_jmpbuf macro to cast-
66 longjmp to a png_longjmp_ptr.-
67*/-
68# undef png_jmpbuf-
69# ifdef PNG_SETJMP_SUPPORTED-
70# define png_jmpbuf(png_ptr) \-
71 (*png_set_longjmp_fn((png_ptr), (png_longjmp_ptr)longjmp, sizeof(jmp_buf)))-
72# else-
73# define png_jmpbuf(png_ptr) \-
74 (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP)-
75# endif-
76#endif-
77-
78#ifdef Q_OS_WINCE-
79#define CALLBACK_CALL_TYPE __cdecl-
80#else-
81#define CALLBACK_CALL_TYPE-
82#endif-
83-
84QT_BEGIN_NAMESPACE-
85-
86#if defined(Q_OS_WINCE) && defined(STANDARDSHELL_UI_MODEL)-
87# define Q_INTERNAL_WIN_NO_THROW __declspec(nothrow)-
88#else-
89# define Q_INTERNAL_WIN_NO_THROW-
90#endif-
91-
92// avoid going through QImage::scanLine() which calls detach-
93#define FAST_SCAN_LINE(data, bpl, y) (data + (y) * bpl)-
94-
95/*-
96 All PNG files load to the minimal QImage equivalent.-
97-
98 All QImage formats output to reasonably efficient PNG equivalents.-
99*/-
100-
101class QPngHandlerPrivate-
102{-
103public:-
104 enum State {-
105 Ready,-
106 ReadHeader,-
107 ReadingEnd,-
108 Error-
109 };-
110-
111 QPngHandlerPrivate(QPngHandler *qq)-
112 : gamma(0.0), fileGamma(0.0), quality(2), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq)-
113 { }
never executed: end of block
0
114-
115 float gamma;-
116 float fileGamma;-
117 int quality;-
118 QString description;-
119 QSize scaledSize;-
120 QStringList readTexts;-
121-
122 png_struct *png_ptr;-
123 png_info *info_ptr;-
124 png_info *end_info;-
125-
126 bool readPngHeader();-
127 bool readPngImage(QImage *image);-
128 void readPngTexts(png_info *info);-
129-
130 QImage::Format readImageFormat();-
131-
132 struct AllocatedMemoryPointers {-
133 AllocatedMemoryPointers()-
134 : row_pointers(0), accRow(0), inRow(0), outRow(0)-
135 { }
never executed: end of block
0
136 void deallocate()-
137 {-
138 delete [] row_pointers;-
139 row_pointers = 0;-
140 delete [] accRow;-
141 accRow = 0;-
142 delete [] inRow;-
143 inRow = 0;-
144 delete [] outRow;-
145 outRow = 0;-
146 }
never executed: end of block
0
147-
148 png_byte **row_pointers;-
149 quint32 *accRow;-
150 png_byte *inRow;-
151 uchar *outRow;-
152 };-
153-
154 AllocatedMemoryPointers amp;-
155-
156 State state;-
157-
158 QPngHandler *q;-
159};-
160-
161-
162class QPNGImageWriter {-
163public:-
164 explicit QPNGImageWriter(QIODevice*);-
165 ~QPNGImageWriter();-
166-
167 enum DisposalMethod { Unspecified, NoDisposal, RestoreBackground, RestoreImage };-
168 void setDisposalMethod(DisposalMethod);-
169 void setLooping(int loops=0); // 0 == infinity-
170 void setFrameDelay(int msecs);-
171 void setGamma(float);-
172-
173 bool writeImage(const QImage& img, int x, int y);-
174 bool writeImage(const QImage& img, volatile int quality, const QString &description, int x, int y);-
175 bool writeImage(const QImage& img)-
176 { return writeImage(img, 0, 0); }
never executed: return writeImage(img, 0, 0);
0
177 bool writeImage(const QImage& img, int quality, const QString &description)-
178 { return writeImage(img, quality, description, 0, 0); }
never executed: return writeImage(img, quality, description, 0, 0);
0
179-
180 QIODevice* device() { return dev; }
never executed: return dev;
0
181-
182private:-
183 QIODevice* dev;-
184 int frames_written;-
185 DisposalMethod disposal;-
186 int looping;-
187 int ms_delay;-
188 float gamma;-
189};-
190-
191extern "C" {-
192static-
193void CALLBACK_CALL_TYPE iod_read_fn(png_structp png_ptr, png_bytep data, png_size_t length)-
194{-
195 QPngHandlerPrivate *d = (QPngHandlerPrivate *)png_get_io_ptr(png_ptr);-
196 QIODevice *in = d->q->device();-
197-
198 if (d->state == QPngHandlerPrivate::ReadingEnd && !in->isSequential() && (in->size() - in->pos()) < 4 && length == 4) {
d->state == QP...te::ReadingEndDescription
TRUEnever evaluated
FALSEnever evaluated
!in->isSequential()Description
TRUEnever evaluated
FALSEnever evaluated
(in->size() - in->pos()) < 4Description
TRUEnever evaluated
FALSEnever evaluated
length == 4Description
TRUEnever evaluated
FALSEnever evaluated
0
199 // Workaround for certain malformed PNGs that lack the final crc bytes-
200 uchar endcrc[4] = { 0xae, 0x42, 0x60, 0x82 };-
201 memcpy(data, endcrc, 4);-
202 in->seek(in->size());-
203 return;
never executed: return;
0
204 }-
205-
206 while (length) {
lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
207 int nr = in->read((char*)data, length);-
208 if (nr <= 0) {
nr <= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
209 png_error(png_ptr, "Read Error");-
210 return;
never executed: return;
0
211 }-
212 length -= nr;-
213 }
never executed: end of block
0
214}
never executed: end of block
0
215-
216-
217static-
218void CALLBACK_CALL_TYPE qpiw_write_fn(png_structp png_ptr, png_bytep data, png_size_t length)-
219{-
220 QPNGImageWriter* qpiw = (QPNGImageWriter*)png_get_io_ptr(png_ptr);-
221 QIODevice* out = qpiw->device();-
222-
223 uint nr = out->write((char*)data, length);-
224 if (nr != length) {
nr != lengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
225 png_error(png_ptr, "Write Error");-
226 return;
never executed: return;
0
227 }-
228}
never executed: end of block
0
229-
230-
231static-
232void CALLBACK_CALL_TYPE qpiw_flush_fn(png_structp /* png_ptr */)-
233{-
234}-
235-
236}-
237-
238static-
239void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead, float screen_gamma=0.0, float file_gamma=0.0)-
240{-
241 if (screen_gamma != 0.0 && file_gamma != 0.0)
screen_gamma != 0.0Description
TRUEnever evaluated
FALSEnever evaluated
file_gamma != 0.0Description
TRUEnever evaluated
FALSEnever evaluated
0
242 png_set_gamma(png_ptr, 1.0f / screen_gamma, file_gamma);
never executed: png_set_gamma(png_ptr, 1.0f / screen_gamma, file_gamma);
0
243-
244 png_uint_32 width;-
245 png_uint_32 height;-
246 int bit_depth;-
247 int color_type;-
248 png_bytep trans_alpha = 0;-
249 png_color_16p trans_color_p = 0;-
250 int num_trans;-
251 png_colorp palette = 0;-
252 int num_palette;-
253 int interlace_method;-
254 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_method, 0, 0);-
255 png_set_interlace_handling(png_ptr);-
256-
257 if (color_type == PNG_COLOR_TYPE_GRAY) {
color_type == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
258 // Black & White or 8-bit grayscale-
259 if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
bit_depth == 1Description
TRUEnever evaluated
FALSEnever evaluated
png_get_channe...info_ptr) == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
260 png_set_invert_mono(png_ptr);-
261 png_read_update_info(png_ptr, info_ptr);-
262 if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {
image.size() !...width, height)Description
TRUEnever evaluated
FALSEnever evaluated
image.format()...e::Format_MonoDescription
TRUEnever evaluated
FALSEnever evaluated
0
263 image = QImage(width, height, QImage::Format_Mono);-
264 if (image.isNull())
image.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
265 return;
never executed: return;
0
266 }
never executed: end of block
0
267 image.setColorCount(2);-
268 image.setColor(1, qRgb(0,0,0));-
269 image.setColor(0, qRgb(255,255,255));-
270 if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
png_get_tRNS(p...trans_color_p)Description
TRUEnever evaluated
FALSEnever evaluated
trans_color_pDescription
TRUEnever evaluated
FALSEnever evaluated
0
271 const int g = trans_color_p->gray;-
272 // the image has white in the first position of the color table,-
273 // black in the second. g is 0 for black, 1 for white.-
274 if (g == 0)
g == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
275 image.setColor(1, qRgba(0, 0, 0, 0));
never executed: image.setColor(1, qRgba(0, 0, 0, 0));
0
276 else if (g == 1)
g == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
277 image.setColor(0, qRgba(255, 255, 255, 0));
never executed: image.setColor(0, qRgba(255, 255, 255, 0));
0
278 }
never executed: end of block
0
279 } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
never executed: end of block
bit_depth == 16Description
TRUEnever evaluated
FALSEnever evaluated
png_get_valid(...o_ptr, 0x0010)Description
TRUEnever evaluated
FALSEnever evaluated
0
280 png_set_expand(png_ptr);-
281 png_set_strip_16(png_ptr);-
282 png_set_gray_to_rgb(png_ptr);-
283 if (image.size() != QSize(width, height) || image.format() != QImage::Format_ARGB32) {
image.size() !...width, height)Description
TRUEnever evaluated
FALSEnever evaluated
image.format()...:Format_ARGB32Description
TRUEnever evaluated
FALSEnever evaluated
0
284 image = QImage(width, height, QImage::Format_ARGB32);-
285 if (image.isNull())
image.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
286 return;
never executed: return;
0
287 }
never executed: end of block
0
288 if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
QSysInfo::Byte...nfo::BigEndianDescription
TRUEnever evaluated
FALSEnever evaluated
0
289 png_set_swap_alpha(png_ptr);
never executed: png_set_swap_alpha(png_ptr);
0
290-
291 png_read_update_info(png_ptr, info_ptr);-
292 } else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
never executed: end of block
bit_depth == 8Description
TRUEnever evaluated
FALSEnever evaluated
!png_get_valid...o_ptr, 0x0010)Description
TRUEnever evaluated
FALSEnever evaluated
0
293 png_set_expand(png_ptr);-
294 if (image.size() != QSize(width, height) || image.format() != QImage::Format_Grayscale8) {
image.size() !...width, height)Description
TRUEnever evaluated
FALSEnever evaluated
image.format()...mat_Grayscale8Description
TRUEnever evaluated
FALSEnever evaluated
0
295 image = QImage(width, height, QImage::Format_Grayscale8);-
296 if (image.isNull())
image.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
297 return;
never executed: return;
0
298 }
never executed: end of block
0
299-
300 png_read_update_info(png_ptr, info_ptr);-
301 } else {
never executed: end of block
0
302 if (bit_depth == 16)
bit_depth == 16Description
TRUEnever evaluated
FALSEnever evaluated
0
303 png_set_strip_16(png_ptr);
never executed: png_set_strip_16(png_ptr);
0
304 else if (bit_depth < 8)
bit_depth < 8Description
TRUEnever evaluated
FALSEnever evaluated
0
305 png_set_packing(png_ptr);
never executed: png_set_packing(png_ptr);
0
306 int ncols = bit_depth < 8 ? 1 << bit_depth : 256;
bit_depth < 8Description
TRUEnever evaluated
FALSEnever evaluated
0
307 png_read_update_info(png_ptr, info_ptr);-
308 if (image.size() != QSize(width, height) || image.format() != QImage::Format_Indexed8) {
image.size() !...width, height)Description
TRUEnever evaluated
FALSEnever evaluated
image.format()...ormat_Indexed8Description
TRUEnever evaluated
FALSEnever evaluated
0
309 image = QImage(width, height, QImage::Format_Indexed8);-
310 if (image.isNull())
image.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
311 return;
never executed: return;
0
312 }
never executed: end of block
0
313 image.setColorCount(ncols);-
314 for (int i=0; i<ncols; i++) {
i<ncolsDescription
TRUEnever evaluated
FALSEnever evaluated
0
315 int c = i*255/(ncols-1);-
316 image.setColor(i, qRgba(c,c,c,0xff));-
317 }
never executed: end of block
0
318 if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {
png_get_tRNS(p...trans_color_p)Description
TRUEnever evaluated
FALSEnever evaluated
trans_color_pDescription
TRUEnever evaluated
FALSEnever evaluated
0
319 const int g = trans_color_p->gray;-
320 if (g < ncols) {
g < ncolsDescription
TRUEnever evaluated
FALSEnever evaluated
0
321 image.setColor(g, 0);-
322 }
never executed: end of block
0
323 }
never executed: end of block
0
324 }
never executed: end of block
0
325 } else if (color_type == PNG_COLOR_TYPE_PALETTE
color_type == (2 | 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
326 && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
png_get_PLTE(p... &num_palette)Description
TRUEnever evaluated
FALSEnever evaluated
0
327 && num_palette <= 256)
num_palette <= 256Description
TRUEnever evaluated
FALSEnever evaluated
0
328 {-
329 // 1-bit and 8-bit color-
330 if (bit_depth != 1)
bit_depth != 1Description
TRUEnever evaluated
FALSEnever evaluated
0
331 png_set_packing(png_ptr);
never executed: png_set_packing(png_ptr);
0
332 png_read_update_info(png_ptr, info_ptr);-
333 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);-
334 QImage::Format format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
bit_depth == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
335 if (image.size() != QSize(width, height) || image.format() != format) {
image.size() !...width, height)Description
TRUEnever evaluated
FALSEnever evaluated
image.format() != formatDescription
TRUEnever evaluated
FALSEnever evaluated
0
336 image = QImage(width, height, format);-
337 if (image.isNull())
image.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
338 return;
never executed: return;
0
339 }
never executed: end of block
0
340 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);-
341 image.setColorCount(num_palette);-
342 int i = 0;-
343 if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {
png_get_tRNS(p...trans_color_p)Description
TRUEnever evaluated
FALSEnever evaluated
trans_alphaDescription
TRUEnever evaluated
FALSEnever evaluated
0
344 while (i < num_trans) {
i < num_transDescription
TRUEnever evaluated
FALSEnever evaluated
0
345 image.setColor(i, qRgba(-
346 palette[i].red,-
347 palette[i].green,-
348 palette[i].blue,-
349 trans_alpha[i]-
350 )-
351 );-
352 i++;-
353 }
never executed: end of block
0
354 }
never executed: end of block
0
355 while (i < num_palette) {
i < num_paletteDescription
TRUEnever evaluated
FALSEnever evaluated
0
356 image.setColor(i, qRgba(-
357 palette[i].red,-
358 palette[i].green,-
359 palette[i].blue,-
360 0xff-
361 )-
362 );-
363 i++;-
364 }
never executed: end of block
0
365 } else {
never executed: end of block
0
366 // 32-bit-
367 if (bit_depth == 16)
bit_depth == 16Description
TRUEnever evaluated
FALSEnever evaluated
0
368 png_set_strip_16(png_ptr);
never executed: png_set_strip_16(png_ptr);
0
369-
370 png_set_expand(png_ptr);-
371-
372 if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
color_type == (4)Description
TRUEnever evaluated
FALSEnever evaluated
0
373 png_set_gray_to_rgb(png_ptr);
never executed: png_set_gray_to_rgb(png_ptr);
0
374-
375 QImage::Format format = QImage::Format_ARGB32;-
376 // Only add filler if no alpha, or we can get 5 channel data.-
377 if (!(color_type & PNG_COLOR_MASK_ALPHA)
!(color_type & 4)Description
TRUEnever evaluated
FALSEnever evaluated
0
378 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
!png_get_valid...o_ptr, 0x0010)Description
TRUEnever evaluated
FALSEnever evaluated
0
379 png_set_filler(png_ptr, 0xff, QSysInfo::ByteOrder == QSysInfo::BigEndian ?-
380 PNG_FILLER_BEFORE : PNG_FILLER_AFTER);-
381 // We want 4 bytes, but it isn't an alpha channel-
382 format = QImage::Format_RGB32;-
383 }
never executed: end of block
0
384 QSize outSize(width,height);-
385 if (!scaledSize.isEmpty() && quint32(scaledSize.width()) <= width &&
!scaledSize.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
quint32(scaled...th()) <= widthDescription
TRUEnever evaluated
FALSEnever evaluated
0
386 quint32(scaledSize.height()) <= height && interlace_method == PNG_INTERLACE_NONE) {
quint32(scaled...t()) <= heightDescription
TRUEnever evaluated
FALSEnever evaluated
interlace_method == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
387 // Do inline downscaling-
388 outSize = scaledSize;-
389 if (doScaledRead)
doScaledReadDescription
TRUEnever evaluated
FALSEnever evaluated
0
390 *doScaledRead = true;
never executed: *doScaledRead = true;
0
391 }
never executed: end of block
0
392 if (image.size() != outSize || image.format() != format) {
image.size() != outSizeDescription
TRUEnever evaluated
FALSEnever evaluated
image.format() != formatDescription
TRUEnever evaluated
FALSEnever evaluated
0
393 image = QImage(outSize, format);-
394 if (image.isNull())
image.isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
395 return;
never executed: return;
0
396 }
never executed: end of block
0
397-
398 if (QSysInfo::ByteOrder == QSysInfo::BigEndian)
QSysInfo::Byte...nfo::BigEndianDescription
TRUEnever evaluated
FALSEnever evaluated
0
399 png_set_swap_alpha(png_ptr);
never executed: png_set_swap_alpha(png_ptr);
0
400-
401 png_read_update_info(png_ptr, info_ptr);-
402 }
never executed: end of block
0
403-
404 // Qt==ARGB==Big(ARGB)==Little(BGRA)-
405 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
QSysInfo::Byte...::LittleEndianDescription
TRUEnever evaluated
FALSEnever evaluated
0
406 png_set_bgr(png_ptr);-
407 }
never executed: end of block
0
408}
never executed: end of block
0
409-
410static void read_image_scaled(QImage *outImage, png_structp png_ptr, png_infop info_ptr,-
411 QPngHandlerPrivate::AllocatedMemoryPointers &amp, QSize scaledSize)-
412{-
413-
414 png_uint_32 width = 0;-
415 png_uint_32 height = 0;-
416 png_int_32 offset_x = 0;-
417 png_int_32 offset_y = 0;-
418-
419 int bit_depth = 0;-
420 int color_type = 0;-
421 int unit_type = PNG_OFFSET_PIXEL;-
422 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);-
423 png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);-
424 uchar *data = outImage->bits();-
425 int bpl = outImage->bytesPerLine();-
426-
427 if (scaledSize.isEmpty() || !width || !height)
scaledSize.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
!widthDescription
TRUEnever evaluated
FALSEnever evaluated
!heightDescription
TRUEnever evaluated
FALSEnever evaluated
0
428 return;
never executed: return;
0
429-
430 const quint32 iysz = height;-
431 const quint32 ixsz = width;-
432 const quint32 oysz = scaledSize.height();-
433 const quint32 oxsz = scaledSize.width();-
434 const quint32 ibw = 4*width;-
435 amp.accRow = new quint32[ibw];-
436 memset(amp.accRow, 0, ibw*sizeof(quint32));-
437 amp.inRow = new png_byte[ibw];-
438 memset(amp.inRow, 0, ibw*sizeof(png_byte));-
439 amp.outRow = new uchar[ibw];-
440 memset(amp.outRow, 0, ibw*sizeof(uchar));-
441 qint32 rval = 0;-
442 for (quint32 oy=0; oy<oysz; oy++) {
oy<oyszDescription
TRUEnever evaluated
FALSEnever evaluated
0
443 // Store the rest of the previous input row, if any-
444 for (quint32 i=0; i < ibw; i++)
i < ibwDescription
TRUEnever evaluated
FALSEnever evaluated
0
445 amp.accRow[i] = rval*amp.inRow[i];
never executed: amp.accRow[i] = rval*amp.inRow[i];
0
446 // Accumulate the next input rows-
447 for (rval = iysz-rval; rval > 0; rval-=oysz) {
rval > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
448 png_read_row(png_ptr, amp.inRow, NULL);-
449 quint32 fact = qMin(oysz, quint32(rval));-
450 for (quint32 i=0; i < ibw; i++)
i < ibwDescription
TRUEnever evaluated
FALSEnever evaluated
0
451 amp.accRow[i] += fact*amp.inRow[i];
never executed: amp.accRow[i] += fact*amp.inRow[i];
0
452 }
never executed: end of block
0
453 rval *= -1;-
454-
455 // We have a full output row, store it-
456 for (quint32 i=0; i < ibw; i++)
i < ibwDescription
TRUEnever evaluated
FALSEnever evaluated
0
457 amp.outRow[i] = uchar(amp.accRow[i]/iysz);
never executed: amp.outRow[i] = uchar(amp.accRow[i]/iysz);
0
458-
459 quint32 a[4] = {0, 0, 0, 0};-
460 qint32 cval = oxsz;-
461 quint32 ix = 0;-
462 for (quint32 ox=0; ox<oxsz; ox++) {
ox<oxszDescription
TRUEnever evaluated
FALSEnever evaluated
0
463 for (quint32 i=0; i < 4; i++)
i < 4Description
TRUEnever evaluated
FALSEnever evaluated
0
464 a[i] = cval * amp.outRow[ix+i];
never executed: a[i] = cval * amp.outRow[ix+i];
0
465 for (cval = ixsz - cval; cval > 0; cval-=oxsz) {
cval > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
466 ix += 4;-
467 if (ix >= ibw)
ix >= ibwDescription
TRUEnever evaluated
FALSEnever evaluated
0
468 break; // Safety belt, should not happen
never executed: break;
0
469 quint32 fact = qMin(oxsz, quint32(cval));-
470 for (quint32 i=0; i < 4; i++)
i < 4Description
TRUEnever evaluated
FALSEnever evaluated
0
471 a[i] += fact * amp.outRow[ix+i];
never executed: a[i] += fact * amp.outRow[ix+i];
0
472 }
never executed: end of block
0
473 cval *= -1;-
474 for (quint32 i=0; i < 4; i++)
i < 4Description
TRUEnever evaluated
FALSEnever evaluated
0
475 data[(4*ox)+i] = uchar(a[i]/ixsz);
never executed: data[(4*ox)+i] = uchar(a[i]/ixsz);
0
476 }
never executed: end of block
0
477 data += bpl;-
478 }
never executed: end of block
0
479 amp.deallocate();-
480-
481 outImage->setDotsPerMeterX((png_get_x_pixels_per_meter(png_ptr,info_ptr)*oxsz)/ixsz);-
482 outImage->setDotsPerMeterY((png_get_y_pixels_per_meter(png_ptr,info_ptr)*oysz)/iysz);-
483-
484 if (unit_type == PNG_OFFSET_PIXEL)
unit_type == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
485 outImage->setOffset(QPoint(offset_x*oxsz/ixsz, offset_y*oysz/iysz));
never executed: outImage->setOffset(QPoint(offset_x*oxsz/ixsz, offset_y*oysz/iysz));
0
486-
487}
never executed: end of block
0
488-
489extern "C" {-
490static void CALLBACK_CALL_TYPE qt_png_warning(png_structp /*png_ptr*/, png_const_charp message)-
491{-
492 qWarning("libpng warning: %s", message);-
493}
never executed: end of block
0
494-
495}-
496-
497-
498void Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngTexts(png_info *info)-
499{-
500 png_textp text_ptr;-
501 int num_text=0;-
502 png_get_text(png_ptr, info, &text_ptr, &num_text);-
503-
504 while (num_text--) {
num_text--Description
TRUEnever evaluated
FALSEnever evaluated
0
505 QString key, value;-
506 key = QString::fromLatin1(text_ptr->key);-
507#if defined(PNG_iTXt_SUPPORTED)-
508 if (text_ptr->itxt_length) {-
509 value = QString::fromUtf8(text_ptr->text, int(text_ptr->itxt_length));-
510 } else-
511#endif-
512 {-
513 value = QString::fromLatin1(text_ptr->text, int(text_ptr->text_length));-
514 }-
515 if (!description.isEmpty())
!description.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
516 description += QLatin1String("\n\n");
never executed: description += QLatin1String("\n\n");
0
517 description += key + QLatin1String(": ") + value.simplified();-
518 readTexts.append(key);-
519 readTexts.append(value);-
520 text_ptr++;-
521 }
never executed: end of block
0
522}
never executed: end of block
0
523-
524-
525bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngHeader()-
526{-
527 state = Error;-
528 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0);-
529 if (!png_ptr)
!png_ptrDescription
TRUEnever evaluated
FALSEnever evaluated
0
530 return false;
never executed: return false;
0
531-
532 png_set_error_fn(png_ptr, 0, 0, qt_png_warning);-
533-
534 info_ptr = png_create_info_struct(png_ptr);-
535 if (!info_ptr) {
!info_ptrDescription
TRUEnever evaluated
FALSEnever evaluated
0
536 png_destroy_read_struct(&png_ptr, 0, 0);-
537 png_ptr = 0;-
538 return false;
never executed: return false;
0
539 }-
540-
541 end_info = png_create_info_struct(png_ptr);-
542 if (!end_info) {
!end_infoDescription
TRUEnever evaluated
FALSEnever evaluated
0
543 png_destroy_read_struct(&png_ptr, &info_ptr, 0);-
544 png_ptr = 0;-
545 return false;
never executed: return false;
0
546 }-
547-
548 if (setjmp(png_jmpbuf(png_ptr))) {
_setjmp (((png_ptr)->jmpbuf))Description
TRUEnever evaluated
FALSEnever evaluated
0
549 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);-
550 png_ptr = 0;-
551 return false;
never executed: return false;
0
552 }-
553-
554 png_set_read_fn(png_ptr, this, iod_read_fn);-
555 png_read_info(png_ptr, info_ptr);-
556-
557 readPngTexts(info_ptr);-
558-
559 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) {
png_get_valid(...o_ptr, 0x0001)Description
TRUEnever evaluated
FALSEnever evaluated
0
560 double file_gamma = 0.0;-
561 png_get_gAMA(png_ptr, info_ptr, &file_gamma);-
562 fileGamma = file_gamma;-
563 }
never executed: end of block
0
564-
565 state = ReadHeader;-
566 return true;
never executed: return true;
0
567}-
568-
569bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage)-
570{-
571 if (state == Error)
state == ErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
572 return false;
never executed: return false;
0
573-
574 if (state == Ready && !readPngHeader()) {
state == ReadyDescription
TRUEnever evaluated
FALSEnever evaluated
!readPngHeader()Description
TRUEnever evaluated
FALSEnever evaluated
0
575 state = Error;-
576 return false;
never executed: return false;
0
577 }-
578-
579 if (setjmp(png_jmpbuf(png_ptr))) {
_setjmp (((png_ptr)->jmpbuf))Description
TRUEnever evaluated
FALSEnever evaluated
0
580 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);-
581 png_ptr = 0;-
582 amp.deallocate();-
583 state = Error;-
584 return false;
never executed: return false;
0
585 }-
586-
587 bool doScaledRead = false;-
588 setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma, fileGamma);-
589-
590 if (outImage->isNull()) {
outImage->isNull()Description
TRUEnever evaluated
FALSEnever evaluated
0
591 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);-
592 png_ptr = 0;-
593 amp.deallocate();-
594 state = Error;-
595 return false;
never executed: return false;
0
596 }-
597-
598 if (doScaledRead) {
doScaledReadDescription
TRUEnever evaluated
FALSEnever evaluated
0
599 read_image_scaled(outImage, png_ptr, info_ptr, amp, scaledSize);-
600 } else {
never executed: end of block
0
601 png_uint_32 width = 0;-
602 png_uint_32 height = 0;-
603 png_int_32 offset_x = 0;-
604 png_int_32 offset_y = 0;-
605-
606 int bit_depth = 0;-
607 int color_type = 0;-
608 int unit_type = PNG_OFFSET_PIXEL;-
609 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);-
610 png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);-
611 uchar *data = outImage->bits();-
612 int bpl = outImage->bytesPerLine();-
613 amp.row_pointers = new png_bytep[height];-
614-
615 for (uint y = 0; y < height; y++)
y < heightDescription
TRUEnever evaluated
FALSEnever evaluated
0
616 amp.row_pointers[y] = data + y * bpl;
never executed: amp.row_pointers[y] = data + y * bpl;
0
617-
618 png_read_image(png_ptr, amp.row_pointers);-
619 amp.deallocate();-
620-
621 outImage->setDotsPerMeterX(png_get_x_pixels_per_meter(png_ptr,info_ptr));-
622 outImage->setDotsPerMeterY(png_get_y_pixels_per_meter(png_ptr,info_ptr));-
623-
624 if (unit_type == PNG_OFFSET_PIXEL)
unit_type == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
625 outImage->setOffset(QPoint(offset_x, offset_y));
never executed: outImage->setOffset(QPoint(offset_x, offset_y));
0
626-
627 // sanity check palette entries-
628 if (color_type == PNG_COLOR_TYPE_PALETTE && outImage->format() == QImage::Format_Indexed8) {
color_type == (2 | 1)Description
TRUEnever evaluated
FALSEnever evaluated
outImage->form...ormat_Indexed8Description
TRUEnever evaluated
FALSEnever evaluated
0
629 int color_table_size = outImage->colorCount();-
630 for (int y=0; y<(int)height; ++y) {
y<(int)heightDescription
TRUEnever evaluated
FALSEnever evaluated
0
631 uchar *p = FAST_SCAN_LINE(data, bpl, y);-
632 uchar *end = p + width;-
633 while (p < end) {
p < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
634 if (*p >= color_table_size)
*p >= color_table_sizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
635 *p = 0;
never executed: *p = 0;
0
636 ++p;-
637 }
never executed: end of block
0
638 }
never executed: end of block
0
639 }
never executed: end of block
0
640 }
never executed: end of block
0
641-
642 state = ReadingEnd;-
643 png_read_end(png_ptr, end_info);-
644-
645 readPngTexts(end_info);-
646 for (int i = 0; i < readTexts.size()-1; i+=2)
i < readTexts.size()-1Description
TRUEnever evaluated
FALSEnever evaluated
0
647 outImage->setText(readTexts.at(i), readTexts.at(i+1));
never executed: outImage->setText(readTexts.at(i), readTexts.at(i+1));
0
648-
649 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);-
650 png_ptr = 0;-
651 amp.deallocate();-
652 state = Ready;-
653-
654 if (scaledSize.isValid() && outImage->size() != scaledSize)
scaledSize.isValid()Description
TRUEnever evaluated
FALSEnever evaluated
outImage->size() != scaledSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
655 *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
never executed: *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
0
656-
657 return true;
never executed: return true;
0
658}-
659-
660QImage::Format QPngHandlerPrivate::readImageFormat()-
661{-
662 QImage::Format format = QImage::Format_Invalid;-
663 png_uint_32 width, height;-
664 int bit_depth, color_type;-
665 png_colorp palette;-
666 int num_palette;-
667 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);-
668 if (color_type == PNG_COLOR_TYPE_GRAY) {
color_type == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
669 // Black & White or 8-bit grayscale-
670 if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {
bit_depth == 1Description
TRUEnever evaluated
FALSEnever evaluated
png_get_channe...info_ptr) == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
671 format = QImage::Format_Mono;-
672 } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
never executed: end of block
bit_depth == 16Description
TRUEnever evaluated
FALSEnever evaluated
png_get_valid(...o_ptr, 0x0010)Description
TRUEnever evaluated
FALSEnever evaluated
0
673 format = QImage::Format_ARGB32;-
674 } else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
never executed: end of block
bit_depth == 8Description
TRUEnever evaluated
FALSEnever evaluated
!png_get_valid...o_ptr, 0x0010)Description
TRUEnever evaluated
FALSEnever evaluated
0
675 format = QImage::Format_Grayscale8;-
676 } else {
never executed: end of block
0
677 format = QImage::Format_Indexed8;-
678 }
never executed: end of block
0
679 } else if (color_type == PNG_COLOR_TYPE_PALETTE
color_type == (2 | 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
680 && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)
png_get_PLTE(p... &num_palette)Description
TRUEnever evaluated
FALSEnever evaluated
0
681 && num_palette <= 256)
num_palette <= 256Description
TRUEnever evaluated
FALSEnever evaluated
0
682 {-
683 // 1-bit and 8-bit color-
684 format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;
bit_depth == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
685 } else {
never executed: end of block
0
686 // 32-bit-
687 format = QImage::Format_ARGB32;-
688 // Only add filler if no alpha, or we can get 5 channel data.-
689 if (!(color_type & PNG_COLOR_MASK_ALPHA)
!(color_type & 4)Description
TRUEnever evaluated
FALSEnever evaluated
0
690 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
!png_get_valid...o_ptr, 0x0010)Description
TRUEnever evaluated
FALSEnever evaluated
0
691 // We want 4 bytes, but it isn't an alpha channel-
692 format = QImage::Format_RGB32;-
693 }
never executed: end of block
0
694 }
never executed: end of block
0
695-
696 return format;
never executed: return format;
0
697}-
698-
699QPNGImageWriter::QPNGImageWriter(QIODevice* iod) :-
700 dev(iod),-
701 frames_written(0),-
702 disposal(Unspecified),-
703 looping(-1),-
704 ms_delay(-1),-
705 gamma(0.0)-
706{-
707}
never executed: end of block
0
708-
709QPNGImageWriter::~QPNGImageWriter()-
710{-
711}-
712-
713void QPNGImageWriter::setDisposalMethod(DisposalMethod dm)-
714{-
715 disposal = dm;-
716}
never executed: end of block
0
717-
718void QPNGImageWriter::setLooping(int loops)-
719{-
720 looping = loops;-
721}
never executed: end of block
0
722-
723void QPNGImageWriter::setFrameDelay(int msecs)-
724{-
725 ms_delay = msecs;-
726}
never executed: end of block
0
727-
728void QPNGImageWriter::setGamma(float g)-
729{-
730 gamma = g;-
731}
never executed: end of block
0
732-
733-
734static void set_text(const QImage &image, png_structp png_ptr, png_infop info_ptr,-
735 const QString &description)-
736{-
737 QMap<QString, QString> text;-
738 foreach (const QString &key, image.textKeys()) {-
739 if (!key.isEmpty())
!key.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
740 text.insert(key, image.text(key));
never executed: text.insert(key, image.text(key));
0
741 }
never executed: end of block
0
742 foreach (const QString &pair, description.split(QLatin1String("\n\n"))) {-
743 int index = pair.indexOf(QLatin1Char(':'));-
744 if (index >= 0 && pair.indexOf(QLatin1Char(' ')) < index) {
index >= 0Description
TRUEnever evaluated
FALSEnever evaluated
pair.indexOf(Q...(' ')) < indexDescription
TRUEnever evaluated
FALSEnever evaluated
0
745 QString s = pair.simplified();-
746 if (!s.isEmpty())
!s.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
747 text.insert(QLatin1String("Description"), s);
never executed: text.insert(QLatin1String("Description"), s);
0
748 } else {
never executed: end of block
0
749 QString key = pair.left(index);-
750 if (!key.simplified().isEmpty())
!key.simplified().isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
751 text.insert(key, pair.mid(index + 2).simplified());
never executed: text.insert(key, pair.mid(index + 2).simplified());
0
752 }
never executed: end of block
0
753 }-
754-
755 if (text.isEmpty())
text.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
756 return;
never executed: return;
0
757-
758 png_textp text_ptr = new png_text[text.size()];-
759 memset(text_ptr, 0, text.size() * sizeof(png_text));-
760-
761 QMap<QString, QString>::ConstIterator it = text.constBegin();-
762 int i = 0;-
763 while (it != text.constEnd()) {
it != text.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
0
764 text_ptr[i].key = qstrdup(it.key().leftRef(79).toLatin1().constData());-
765 bool noCompress = (it.value().length() < 40);-
766-
767#ifdef PNG_iTXt_SUPPORTED-
768 bool needsItxt = false;-
769 foreach(const QChar c, it.value()) {-
770 uchar ch = c.cell();-
771 if (c.row() || (ch < 0x20 && ch != '\n') || (ch > 0x7e && ch < 0xa0)) {-
772 needsItxt = true;-
773 break;-
774 }-
775 }-
776-
777 if (needsItxt) {-
778 text_ptr[i].compression = noCompress ? PNG_ITXT_COMPRESSION_NONE : PNG_ITXT_COMPRESSION_zTXt;-
779 QByteArray value = it.value().toUtf8();-
780 text_ptr[i].text = qstrdup(value.constData());-
781 text_ptr[i].itxt_length = value.size();-
782 text_ptr[i].lang = const_cast<char*>("UTF-8");-
783 text_ptr[i].lang_key = qstrdup(it.key().toUtf8().constData());-
784 }-
785 else-
786#endif-
787 {-
788 text_ptr[i].compression = noCompress ? PNG_TEXT_COMPRESSION_NONE : PNG_TEXT_COMPRESSION_zTXt;
noCompressDescription
TRUEnever evaluated
FALSEnever evaluated
0
789 QByteArray value = it.value().toLatin1();-
790 text_ptr[i].text = qstrdup(value.constData());-
791 text_ptr[i].text_length = value.size();-
792 }-
793 ++i;-
794 ++it;-
795 }
never executed: end of block
0
796-
797 png_set_text(png_ptr, info_ptr, text_ptr, i);-
798 for (i = 0; i < text.size(); ++i) {
i < text.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
799 delete [] text_ptr[i].key;-
800 delete [] text_ptr[i].text;-
801#ifdef PNG_iTXt_SUPPORTED-
802 delete [] text_ptr[i].lang_key;-
803#endif-
804 }
never executed: end of block
0
805 delete [] text_ptr;-
806}
never executed: end of block
0
807-
808bool QPNGImageWriter::writeImage(const QImage& image, int off_x, int off_y)-
809{-
810 return writeImage(image, -1, QString(), off_x, off_y);
never executed: return writeImage(image, -1, QString(), off_x, off_y);
0
811}-
812-
813bool Q_INTERNAL_WIN_NO_THROW QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, const QString &description,-
814 int off_x_in, int off_y_in)-
815{-
816 QPoint offset = image.offset();-
817 int off_x = off_x_in + offset.x();-
818 int off_y = off_y_in + offset.y();-
819-
820 png_structp png_ptr;-
821 png_infop info_ptr;-
822-
823 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0);-
824 if (!png_ptr) {
!png_ptrDescription
TRUEnever evaluated
FALSEnever evaluated
0
825 return false;
never executed: return false;
0
826 }-
827-
828 png_set_error_fn(png_ptr, 0, 0, qt_png_warning);-
829-
830 info_ptr = png_create_info_struct(png_ptr);-
831 if (!info_ptr) {
!info_ptrDescription
TRUEnever evaluated
FALSEnever evaluated
0
832 png_destroy_write_struct(&png_ptr, 0);-
833 return false;
never executed: return false;
0
834 }-
835-
836 if (setjmp(png_jmpbuf(png_ptr))) {
_setjmp (((png_ptr)->jmpbuf))Description
TRUEnever evaluated
FALSEnever evaluated
0
837 png_destroy_write_struct(&png_ptr, &info_ptr);-
838 return false;
never executed: return false;
0
839 }-
840-
841 int quality = quality_in;-
842 if (quality >= 0) {
quality >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
843 if (quality > 9) {
quality > 9Description
TRUEnever evaluated
FALSEnever evaluated
0
844 qWarning("PNG: Quality %d out of range", quality);-
845 quality = 9;-
846 }
never executed: end of block
0
847 png_set_compression_level(png_ptr, quality);-
848 }
never executed: end of block
0
849-
850 png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);-
851-
852-
853 int color_type = 0;-
854 if (image.colorCount()) {
image.colorCount()Description
TRUEnever evaluated
FALSEnever evaluated
0
855 if (image.isGrayscale())
image.isGrayscale()Description
TRUEnever evaluated
FALSEnever evaluated
0
856 color_type = PNG_COLOR_TYPE_GRAY;
never executed: color_type = 0;
0
857 else-
858 color_type = PNG_COLOR_TYPE_PALETTE;
never executed: color_type = (2 | 1);
0
859 }-
860 else if (image.format() == QImage::Format_Grayscale8)
image.format()...mat_Grayscale8Description
TRUEnever evaluated
FALSEnever evaluated
0
861 color_type = PNG_COLOR_TYPE_GRAY;
never executed: color_type = 0;
0
862 else if (image.hasAlphaChannel())
image.hasAlphaChannel()Description
TRUEnever evaluated
FALSEnever evaluated
0
863 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
never executed: color_type = (2 | 4);
0
864 else-
865 color_type = PNG_COLOR_TYPE_RGB;
never executed: color_type = (2);
0
866-
867 png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),-
868 image.depth() == 1 ? 1 : 8, // per channel-
869 color_type, 0, 0, 0); // sets #channels-
870-
871 if (gamma != 0.0) {
gamma != 0.0Description
TRUEnever evaluated
FALSEnever evaluated
0
872 png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);-
873 }
never executed: end of block
0
874-
875 if (image.format() == QImage::Format_MonoLSB)
image.format()...Format_MonoLSBDescription
TRUEnever evaluated
FALSEnever evaluated
0
876 png_set_packswap(png_ptr);
never executed: png_set_packswap(png_ptr);
0
877-
878 if (color_type == PNG_COLOR_TYPE_PALETTE) {
color_type == (2 | 1)Description
TRUEnever evaluated
FALSEnever evaluated
0
879 // Paletted-
880 int num_palette = qMin(256, image.colorCount());-
881 png_color palette[256];-
882 png_byte trans[256];-
883 int num_trans = 0;-
884 for (int i=0; i<num_palette; i++) {
i<num_paletteDescription
TRUEnever evaluated
FALSEnever evaluated
0
885 QRgb rgba=image.color(i);-
886 palette[i].red = qRed(rgba);-
887 palette[i].green = qGreen(rgba);-
888 palette[i].blue = qBlue(rgba);-
889 trans[i] = qAlpha(rgba);-
890 if (trans[i] < 255) {
trans[i] < 255Description
TRUEnever evaluated
FALSEnever evaluated
0
891 num_trans = i+1;-
892 }
never executed: end of block
0
893 }
never executed: end of block
0
894 png_set_PLTE(png_ptr, info_ptr, palette, num_palette);-
895-
896 if (num_trans) {
num_transDescription
TRUEnever evaluated
FALSEnever evaluated
0
897 png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);-
898 }
never executed: end of block
0
899 }
never executed: end of block
0
900-
901 // Swap ARGB to RGBA (normal PNG format) before saving on-
902 // BigEndian machines-
903 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
QSysInfo::Byte...nfo::BigEndianDescription
TRUEnever evaluated
FALSEnever evaluated
0
904 png_set_swap_alpha(png_ptr);-
905 }
never executed: end of block
0
906-
907 // Qt==ARGB==Big(ARGB)==Little(BGRA). But RGB888 is RGB regardless-
908 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian
QSysInfo::Byte...::LittleEndianDescription
TRUEnever evaluated
FALSEnever evaluated
0
909 && image.format() != QImage::Format_RGB888) {
image.format()...:Format_RGB888Description
TRUEnever evaluated
FALSEnever evaluated
0
910 png_set_bgr(png_ptr);-
911 }
never executed: end of block
0
912-
913 if (off_x || off_y) {
off_xDescription
TRUEnever evaluated
FALSEnever evaluated
off_yDescription
TRUEnever evaluated
FALSEnever evaluated
0
914 png_set_oFFs(png_ptr, info_ptr, off_x, off_y, PNG_OFFSET_PIXEL);-
915 }
never executed: end of block
0
916-
917 if (frames_written > 0)
frames_written > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
918 png_set_sig_bytes(png_ptr, 8);
never executed: png_set_sig_bytes(png_ptr, 8);
0
919-
920 if (image.dotsPerMeterX() > 0 || image.dotsPerMeterY() > 0) {
image.dotsPerMeterX() > 0Description
TRUEnever evaluated
FALSEnever evaluated
image.dotsPerMeterY() > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
921 png_set_pHYs(png_ptr, info_ptr,-
922 image.dotsPerMeterX(), image.dotsPerMeterY(),-
923 PNG_RESOLUTION_METER);-
924 }
never executed: end of block
0
925-
926 set_text(image, png_ptr, info_ptr, description);-
927-
928 png_write_info(png_ptr, info_ptr);-
929-
930 if (image.depth() != 1)
image.depth() != 1Description
TRUEnever evaluated
FALSEnever evaluated
0
931 png_set_packing(png_ptr);
never executed: png_set_packing(png_ptr);
0
932-
933 if (color_type == PNG_COLOR_TYPE_RGB && image.format() != QImage::Format_RGB888)
color_type == (2)Description
TRUEnever evaluated
FALSEnever evaluated
image.format()...:Format_RGB888Description
TRUEnever evaluated
FALSEnever evaluated
0
934 png_set_filler(png_ptr, 0,
never executed: png_set_filler(png_ptr, 0, QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 1);
0
935 QSysInfo::ByteOrder == QSysInfo::BigEndian ?
never executed: png_set_filler(png_ptr, 0, QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 1);
0
936 PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
never executed: png_set_filler(png_ptr, 0, QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 1);
0
937-
938 if (looping >= 0 && frames_written == 0) {
looping >= 0Description
TRUEnever evaluated
FALSEnever evaluated
frames_written == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
939 uchar data[13] = "NETSCAPE2.0";-
940 // 0123456789aBC-
941 data[0xB] = looping%0x100;-
942 data[0xC] = looping/0x100;-
943 png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFx"), data, 13);-
944 }
never executed: end of block
0
945 if (ms_delay >= 0 || disposal!=Unspecified) {
ms_delay >= 0Description
TRUEnever evaluated
FALSEnever evaluated
disposal!=UnspecifiedDescription
TRUEnever evaluated
FALSEnever evaluated
0
946 uchar data[4];-
947 data[0] = disposal;-
948 data[1] = 0;-
949 data[2] = (ms_delay/10)/0x100; // hundredths-
950 data[3] = (ms_delay/10)%0x100;-
951 png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFg"), data, 4);-
952 }
never executed: end of block
0
953-
954 int height = image.height();-
955 int width = image.width();-
956 switch (image.format()) {-
957 case QImage::Format_Mono:
never executed: case QImage::Format_Mono:
0
958 case QImage::Format_MonoLSB:
never executed: case QImage::Format_MonoLSB:
0
959 case QImage::Format_Indexed8:
never executed: case QImage::Format_Indexed8:
0
960 case QImage::Format_Grayscale8:
never executed: case QImage::Format_Grayscale8:
0
961 case QImage::Format_RGB32:
never executed: case QImage::Format_RGB32:
0
962 case QImage::Format_ARGB32:
never executed: case QImage::Format_ARGB32:
0
963 case QImage::Format_RGB888:
never executed: case QImage::Format_RGB888:
0
964 {-
965 png_bytep* row_pointers = new png_bytep[height];-
966 for (int y=0; y<height; y++)
y<heightDescription
TRUEnever evaluated
FALSEnever evaluated
0
967 row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y));
never executed: row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y));
0
968 png_write_image(png_ptr, row_pointers);-
969 delete [] row_pointers;-
970 }-
971 break;
never executed: break;
0
972 default:
never executed: default:
0
973 {-
974 QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;
image.hasAlphaChannel()Description
TRUEnever evaluated
FALSEnever evaluated
0
975 QImage row;-
976 png_bytep row_pointers[1];-
977 for (int y=0; y<height; y++) {
y<heightDescription
TRUEnever evaluated
FALSEnever evaluated
0
978 row = image.copy(0, y, width, 1).convertToFormat(fmt);-
979 row_pointers[0] = const_cast<png_bytep>(row.constScanLine(0));-
980 png_write_rows(png_ptr, row_pointers, 1);-
981 }
never executed: end of block
0
982 }-
983 break;
never executed: break;
0
984 }-
985-
986 png_write_end(png_ptr, info_ptr);-
987 frames_written++;-
988-
989 png_destroy_write_struct(&png_ptr, &info_ptr);-
990-
991 return true;
never executed: return true;
0
992}-
993-
994static bool write_png_image(const QImage &image, QIODevice *device,-
995 int quality, float gamma, const QString &description)-
996{-
997 QPNGImageWriter writer(device);-
998 if (quality >= 0) {
quality >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
999 quality = qMin(quality, 100);-
1000 quality = (100-quality) * 9 / 91; // map [0,100] -> [9,0]-
1001 }
never executed: end of block
0
1002 writer.setGamma(gamma);-
1003 return writer.writeImage(image, quality, description);
never executed: return writer.writeImage(image, quality, description);
0
1004}-
1005-
1006QPngHandler::QPngHandler()-
1007 : d(new QPngHandlerPrivate(this))-
1008{-
1009}
never executed: end of block
0
1010-
1011QPngHandler::~QPngHandler()-
1012{-
1013 if (d->png_ptr)
d->png_ptrDescription
TRUEnever evaluated
FALSEnever evaluated
0
1014 png_destroy_read_struct(&d->png_ptr, &d->info_ptr, &d->end_info);
never executed: png_destroy_read_struct(&d->png_ptr, &d->info_ptr, &d->end_info);
0
1015 delete d;-
1016}
never executed: end of block
0
1017-
1018bool QPngHandler::canRead() const-
1019{-
1020 if (d->state == QPngHandlerPrivate::Ready && !canRead(device()))
d->state == QP...Private::ReadyDescription
TRUEnever evaluated
FALSEnever evaluated
!canRead(device())Description
TRUEnever evaluated
FALSEnever evaluated
0
1021 return false;
never executed: return false;
0
1022-
1023 if (d->state != QPngHandlerPrivate::Error) {
d->state != QP...Private::ErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1024 setFormat("png");-
1025 return true;
never executed: return true;
0
1026 }-
1027-
1028 return false;
never executed: return false;
0
1029}-
1030-
1031bool QPngHandler::canRead(QIODevice *device)-
1032{-
1033 if (!device) {
!deviceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1034 qWarning("QPngHandler::canRead() called with no device");-
1035 return false;
never executed: return false;
0
1036 }-
1037-
1038 return device->peek(8) == "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
never executed: return device->peek(8) == "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
0
1039}-
1040-
1041bool QPngHandler::read(QImage *image)-
1042{-
1043 if (!canRead())
!canRead()Description
TRUEnever evaluated
FALSEnever evaluated
0
1044 return false;
never executed: return false;
0
1045 return d->readPngImage(image);
never executed: return d->readPngImage(image);
0
1046}-
1047-
1048bool QPngHandler::write(const QImage &image)-
1049{-
1050 return write_png_image(image, device(), d->quality, d->gamma, d->description);
never executed: return write_png_image(image, device(), d->quality, d->gamma, d->description);
0
1051}-
1052-
1053bool QPngHandler::supportsOption(ImageOption option) const-
1054{-
1055 return option == Gamma
never executed: return option == Gamma || option == Description || option == ImageFormat || option == Quality || option == Size || option == ScaledSize;
0
1056 || option == Description
never executed: return option == Gamma || option == Description || option == ImageFormat || option == Quality || option == Size || option == ScaledSize;
0
1057 || option == ImageFormat
never executed: return option == Gamma || option == Description || option == ImageFormat || option == Quality || option == Size || option == ScaledSize;
0
1058 || option == Quality
never executed: return option == Gamma || option == Description || option == ImageFormat || option == Quality || option == Size || option == ScaledSize;
0
1059 || option == Size
never executed: return option == Gamma || option == Description || option == ImageFormat || option == Quality || option == Size || option == ScaledSize;
0
1060 || option == ScaledSize;
never executed: return option == Gamma || option == Description || option == ImageFormat || option == Quality || option == Size || option == ScaledSize;
0
1061}-
1062-
1063QVariant QPngHandler::option(ImageOption option) const-
1064{-
1065 if (d->state == QPngHandlerPrivate::Error)
d->state == QP...Private::ErrorDescription
TRUEnever evaluated
FALSEnever evaluated
0
1066 return QVariant();
never executed: return QVariant();
0
1067 if (d->state == QPngHandlerPrivate::Ready && !d->readPngHeader())
d->state == QP...Private::ReadyDescription
TRUEnever evaluated
FALSEnever evaluated
!d->readPngHeader()Description
TRUEnever evaluated
FALSEnever evaluated
0
1068 return QVariant();
never executed: return QVariant();
0
1069-
1070 if (option == Gamma)
option == GammaDescription
TRUEnever evaluated
FALSEnever evaluated
0
1071 return d->gamma == 0.0 ? d->fileGamma : d->gamma;
never executed: return d->gamma == 0.0 ? d->fileGamma : d->gamma;
0
1072 else if (option == Quality)
option == QualityDescription
TRUEnever evaluated
FALSEnever evaluated
0
1073 return d->quality;
never executed: return d->quality;
0
1074 else if (option == Description)
option == DescriptionDescription
TRUEnever evaluated
FALSEnever evaluated
0
1075 return d->description;
never executed: return d->description;
0
1076 else if (option == Size)
option == SizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1077 return QSize(png_get_image_width(d->png_ptr, d->info_ptr),
never executed: return QSize(png_get_image_width(d->png_ptr, d->info_ptr), png_get_image_height(d->png_ptr, d->info_ptr));
0
1078 png_get_image_height(d->png_ptr, d->info_ptr));
never executed: return QSize(png_get_image_width(d->png_ptr, d->info_ptr), png_get_image_height(d->png_ptr, d->info_ptr));
0
1079 else if (option == ScaledSize)
option == ScaledSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1080 return d->scaledSize;
never executed: return d->scaledSize;
0
1081 else if (option == ImageFormat)
option == ImageFormatDescription
TRUEnever evaluated
FALSEnever evaluated
0
1082 return d->readImageFormat();
never executed: return d->readImageFormat();
0
1083 return QVariant();
never executed: return QVariant();
0
1084}-
1085-
1086void QPngHandler::setOption(ImageOption option, const QVariant &value)-
1087{-
1088 if (option == Gamma)
option == GammaDescription
TRUEnever evaluated
FALSEnever evaluated
0
1089 d->gamma = value.toFloat();
never executed: d->gamma = value.toFloat();
0
1090 else if (option == Quality)
option == QualityDescription
TRUEnever evaluated
FALSEnever evaluated
0
1091 d->quality = value.toInt();
never executed: d->quality = value.toInt();
0
1092 else if (option == Description)
option == DescriptionDescription
TRUEnever evaluated
FALSEnever evaluated
0
1093 d->description = value.toString();
never executed: d->description = value.toString();
0
1094 else if (option == ScaledSize)
option == ScaledSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1095 d->scaledSize = value.toSize();
never executed: d->scaledSize = value.toSize();
0
1096}
never executed: end of block
0
1097-
1098QByteArray QPngHandler::name() const-
1099{-
1100 return "png";
never executed: return "png";
0
1101}-
1102-
1103QT_END_NAMESPACE-
1104-
1105#endif // QT_NO_IMAGEFORMAT_PNG-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9