qpnghandler.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/image/qpnghandler.cpp
Switch to Source codePreprocessed file
LineSourceCount
1-
2-
3-
4-
5class QPngHandlerPrivate-
6{-
7public:-
8 enum State {-
9 Ready,-
10 ReadHeader,-
11 ReadingEnd,-
12 Error-
13 };-
14-
15 QPngHandlerPrivate(QPngHandler *qq)-
16 : gamma(0.0), fileGamma(0.0), quality(2), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq)-
17 { }-
18-
19 float gamma;-
20 float fileGamma;-
21 int quality;-
22 QString description;-
23 QSize scaledSize;-
24 QStringList readTexts;-
25-
26 png_struct *png_ptr;-
27 png_info *info_ptr;-
28 png_info *end_info;-
29-
30 bool readPngHeader();-
31 bool readPngImage(QImage *image);-
32 void readPngTexts(png_info *info);-
33-
34 QImage::Format readImageFormat();-
35-
36 struct AllocatedMemoryPointers {-
37 AllocatedMemoryPointers()-
38 : row_pointers(0), accRow(0), inRow(0), outRow(0)-
39 { }-
40 void deallocate()-
41 {-
42 delete [] row_pointers;-
43 row_pointers = 0;-
44 delete [] accRow;-
45 accRow = 0;-
46 delete [] inRow;-
47 inRow = 0;-
48 delete [] outRow;-
49 outRow = 0;-
50 }-
51-
52 png_byte **row_pointers;-
53 quint32 *accRow;-
54 png_byte *inRow;-
55 uchar *outRow;-
56 };-
57-
58 AllocatedMemoryPointers amp;-
59-
60 State state;-
61-
62 QPngHandler *q;-
63};-
64-
65-
66class QPNGImageWriter {-
67public:-
68 explicit QPNGImageWriter(QIODevice*);-
69 ~QPNGImageWriter();-
70-
71 enum DisposalMethod { Unspecified, NoDisposal, RestoreBackground, RestoreImage };-
72 void setDisposalMethod(DisposalMethod);-
73 void setLooping(int loops=0);-
74 void setFrameDelay(int msecs);-
75 void setGamma(float);-
76-
77 bool writeImage(const QImage& img, int x, int y);-
78 bool writeImage(const QImage& img, volatile int quality, const QString &description, int x, int y);-
79 bool writeImage(const QImage& img)-
80 { return writeImage(img, 0, 0); }-
81 bool writeImage(const QImage& img, int quality, const QString &description)-
82 { return writeImage(img, quality, description, 0, 0); }-
83-
84 QIODevice* device() { return dev; }-
85-
86private:-
87 QIODevice* dev;-
88 int frames_written;-
89 DisposalMethod disposal;-
90 int looping;-
91 int ms_delay;-
92 float gamma;-
93};-
94-
95extern "C" {-
96static-
97void iod_read_fn(png_structp png_ptr, png_bytep data, png_size_t length)-
98{-
99 QPngHandlerPrivate *d = (QPngHandlerPrivate *)png_get_io_ptr(png_ptr);-
100 QIODevice *in = d->q->device();-
101-
102 if (d->state == QPngHandlerPrivate::ReadingEnd && !in->isSequential() && (in->size() - in->pos()) < 4 && length == 4) {-
103-
104 uchar endcrc[4] = { 0xae, 0x42, 0x60, 0x82 };-
105 memcpy(data, endcrc, 4);-
106 in->seek(in->size());-
107 return;-
108 }-
109-
110 while (length) {-
111 int nr = in->read((char*)data, length);-
112 if (nr <= 0) {-
113 png_error(png_ptr, "Read Error");-
114 return;-
115 }-
116 length -= nr;-
117 }-
118}-
119-
120-
121static-
122void qpiw_write_fn(png_structp png_ptr, png_bytep data, png_size_t length)-
123{-
124 QPNGImageWriter* qpiw = (QPNGImageWriter*)png_get_io_ptr(png_ptr);-
125 QIODevice* out = qpiw->device();-
126-
127 uint nr = out->write((char*)data, length);-
128 if (nr != length) {-
129 png_error(png_ptr, "Write Error");-
130 return;-
131 }-
132}-
133-
134-
135static-
136void qpiw_flush_fn(png_structp )-
137{-
138}-
139-
140}-
141-
142static-
143void 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)-
144{-
145 if (screen_gamma != 0.0 && file_gamma != 0.0)-
146 png_set_gamma(png_ptr, 1.0f / screen_gamma, file_gamma);-
147-
148 png_uint_32 width;-
149 png_uint_32 height;-
150 int bit_depth;-
151 int color_type;-
152 png_bytep trans_alpha = 0;-
153 png_color_16p trans_color_p = 0;-
154 int num_trans;-
155 png_colorp palette = 0;-
156 int num_palette;-
157 int interlace_method;-
158 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_method, 0, 0);-
159 png_set_interlace_handling(png_ptr);-
160-
161 if (color_type == 0) {-
162-
163 if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {-
164 png_set_invert_mono(png_ptr);-
165 png_read_update_info(png_ptr, info_ptr);-
166 if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) {-
167 image = QImage(width, height, QImage::Format_Mono);-
168 if (image.isNull())-
169 return;-
170 }-
171 image.setColorCount(2);-
172 image.setColor(1, qRgb(0,0,0));-
173 image.setColor(0, qRgb(255,255,255));-
174 if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {-
175 const int g = trans_color_p->gray;-
176-
177-
178 if (g == 0)-
179 image.setColor(1, qRgba(0, 0, 0, 0));-
180 else if (g == 1)-
181 image.setColor(0, qRgba(255, 255, 255, 0));-
182 }-
183 } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, 0x0010)) {-
184 png_set_expand(png_ptr);-
185 png_set_strip_16(png_ptr);-
186 png_set_gray_to_rgb(png_ptr);-
187 if (image.size() != QSize(width, height) || image.format() != QImage::Format_ARGB32) {-
188 image = QImage(width, height, QImage::Format_ARGB32);-
189 if (image.isNull())-
190 return;-
191 }-
192 if (QSysInfo::ByteOrder == QSysInfo::BigEndian)-
193 png_set_swap_alpha(png_ptr);-
194-
195 png_read_update_info(png_ptr, info_ptr);-
196 } else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, 0x0010)) {-
197 png_set_expand(png_ptr);-
198 if (image.size() != QSize(width, height) || image.format() != QImage::Format_Grayscale8) {-
199 image = QImage(width, height, QImage::Format_Grayscale8);-
200 if (image.isNull())-
201 return;-
202 }-
203-
204 png_read_update_info(png_ptr, info_ptr);-
205 } else {-
206 if (bit_depth == 16)-
207 png_set_strip_16(png_ptr);-
208 else if (bit_depth < 8)-
209 png_set_packing(png_ptr);-
210 int ncols = bit_depth < 8 ? 1 << bit_depth : 256;-
211 png_read_update_info(png_ptr, info_ptr);-
212 if (image.size() != QSize(width, height) || image.format() != QImage::Format_Indexed8) {-
213 image = QImage(width, height, QImage::Format_Indexed8);-
214 if (image.isNull())-
215 return;-
216 }-
217 image.setColorCount(ncols);-
218 for (int i=0; i<ncols; i++) {-
219 int c = i*255/(ncols-1);-
220 image.setColor(i, qRgba(c,c,c,0xff));-
221 }-
222 if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) {-
223 const int g = trans_color_p->gray;-
224 if (g < ncols) {-
225 image.setColor(g, 0);-
226 }-
227 }-
228 }-
229 } else if (color_type == (2 | 1)-
230 && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)-
231 && num_palette <= 256)-
232 {-
233-
234 if (bit_depth != 1)-
235 png_set_packing(png_ptr);-
236 png_read_update_info(png_ptr, info_ptr);-
237 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);-
238 QImage::Format format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;-
239 if (image.size() != QSize(width, height) || image.format() != format) {-
240 image = QImage(width, height, format);-
241 if (image.isNull())-
242 return;-
243 }-
244 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);-
245 image.setColorCount(num_palette);-
246 int i = 0;-
247 if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) {-
248 while (i < num_trans) {-
249 image.setColor(i, qRgba(-
250 palette[i].red,-
251 palette[i].green,-
252 palette[i].blue,-
253 trans_alpha[i]-
254 )-
255 );-
256 i++;-
257 }-
258 }-
259 while (i < num_palette) {-
260 image.setColor(i, qRgba(-
261 palette[i].red,-
262 palette[i].green,-
263 palette[i].blue,-
264 0xff-
265 )-
266 );-
267 i++;-
268 }-
269 } else {-
270-
271 if (bit_depth == 16)-
272 png_set_strip_16(png_ptr);-
273-
274 png_set_expand(png_ptr);-
275-
276 if (color_type == (4))-
277 png_set_gray_to_rgb(png_ptr);-
278-
279 QImage::Format format = QImage::Format_ARGB32;-
280-
281 if (!(color_type & 4)-
282 && !png_get_valid(png_ptr, info_ptr, 0x0010)) {-
283 png_set_filler(png_ptr, 0xff, QSysInfo::ByteOrder == QSysInfo::BigEndian ?-
284 0 : 1);-
285-
286 format = QImage::Format_RGB32;-
287 }-
288 QSize outSize(width,height);-
289 if (!scaledSize.isEmpty() && quint32(scaledSize.width()) <= width &&-
290 quint32(scaledSize.height()) <= height && interlace_method == 0) {-
291-
292 outSize = scaledSize;-
293 if (doScaledRead)-
294 *doScaledRead = true;-
295 }-
296 if (image.size() != outSize || image.format() != format) {-
297 image = QImage(outSize, format);-
298 if (image.isNull())-
299 return;-
300 }-
301-
302 if (QSysInfo::ByteOrder == QSysInfo::BigEndian)-
303 png_set_swap_alpha(png_ptr);-
304-
305 png_read_update_info(png_ptr, info_ptr);-
306 }-
307-
308-
309 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {-
310 png_set_bgr(png_ptr);-
311 }-
312}-
313-
314static void read_image_scaled(QImage *outImage, png_structp png_ptr, png_infop info_ptr,-
315 QPngHandlerPrivate::AllocatedMemoryPointers &amp, QSize scaledSize)-
316{-
317-
318 png_uint_32 width = 0;-
319 png_uint_32 height = 0;-
320 png_int_32 offset_x = 0;-
321 png_int_32 offset_y = 0;-
322-
323 int bit_depth = 0;-
324 int color_type = 0;-
325 int unit_type = 0;-
326 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);-
327 png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);-
328 uchar *data = outImage->bits();-
329 int bpl = outImage->bytesPerLine();-
330-
331 if (scaledSize.isEmpty() || !width || !height)-
332 return;-
333-
334 const quint32 iysz = height;-
335 const quint32 ixsz = width;-
336 const quint32 oysz = scaledSize.height();-
337 const quint32 oxsz = scaledSize.width();-
338 const quint32 ibw = 4*width;-
339 amp.accRow = new quint32[ibw];-
340 memset(amp.accRow, 0, ibw*sizeof(quint32));-
341 amp.inRow = new png_byte[ibw];-
342 memset(amp.inRow, 0, ibw*sizeof(png_byte));-
343 amp.outRow = new uchar[ibw];-
344 memset(amp.outRow, 0, ibw*sizeof(uchar));-
345 qint32 rval = 0;-
346 for (quint32 oy=0; oy<oysz; oy++) {-
347-
348 for (quint32 i=0; i < ibw; i++)-
349 amp.accRow[i] = rval*amp.inRow[i];-
350-
351 for (rval = iysz-rval; rval > 0; rval-=oysz) {-
352 png_read_row(png_ptr, amp.inRow, __null);-
353 quint32 fact = qMin(oysz, quint32(rval));-
354 for (quint32 i=0; i < ibw; i++)-
355 amp.accRow[i] += fact*amp.inRow[i];-
356 }-
357 rval *= -1;-
358-
359-
360 for (quint32 i=0; i < ibw; i++)-
361 amp.outRow[i] = uchar(amp.accRow[i]/iysz);-
362-
363 quint32 a[4] = {0, 0, 0, 0};-
364 qint32 cval = oxsz;-
365 quint32 ix = 0;-
366 for (quint32 ox=0; ox<oxsz; ox++) {-
367 for (quint32 i=0; i < 4; i++)-
368 a[i] = cval * amp.outRow[ix+i];-
369 for (cval = ixsz - cval; cval > 0; cval-=oxsz) {-
370 ix += 4;-
371 if (ix >= ibw)-
372 break;-
373 quint32 fact = qMin(oxsz, quint32(cval));-
374 for (quint32 i=0; i < 4; i++)-
375 a[i] += fact * amp.outRow[ix+i];-
376 }-
377 cval *= -1;-
378 for (quint32 i=0; i < 4; i++)-
379 data[(4*ox)+i] = uchar(a[i]/ixsz);-
380 }-
381 data += bpl;-
382 }-
383 amp.deallocate();-
384-
385 outImage->setDotsPerMeterX((png_get_x_pixels_per_meter(png_ptr,info_ptr)*oxsz)/ixsz);-
386 outImage->setDotsPerMeterY((png_get_y_pixels_per_meter(png_ptr,info_ptr)*oysz)/iysz);-
387-
388 if (unit_type == 0)-
389 outImage->setOffset(QPoint(offset_x*oxsz/ixsz, offset_y*oysz/iysz));-
390-
391}-
392-
393extern "C" {-
394static void qt_png_warning(png_structp , png_const_charp message)-
395{-
396 QMessageLogger(__FILE__, 486492, __PRETTY_FUNCTION__).warning("libpng warning: %s", message);-
397}-
398-
399}-
400-
401-
402void QPngHandlerPrivate::readPngTexts(png_info *info)-
403{-
404 png_textp text_ptr;-
405 int num_text=0;-
406 png_get_text(png_ptr, info, &text_ptr, &num_text);-
407-
408 while (num_text--) {-
409 QString key, value;-
410 key = QString::fromLatin1(text_ptr->key);-
411-
412-
413-
414-
415-
416 {-
417 value = QString::fromLatin1(text_ptr->text, int(text_ptr->text_length));-
418 }-
419 if (!description.isEmpty())-
420 description += QLatin1String("\n\n");-
421 description += key + QLatin1String(": ") + value.simplified();-
422 readTexts.append(key);-
423 readTexts.append(value);-
424 text_ptr++;-
425 }-
426}-
427-
428-
429bool QPngHandlerPrivate::readPngHeader()-
430{-
431 state = Error;-
432 png_ptr = png_create_read_struct("1.2.50",0,0,0);-
433 if (!png_ptr
!png_ptrDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
434 return
never executed: return false;
false;
never executed: return false;
0
435-
436 png_set_error_fn(png_ptr, 0, 0, qt_png_warning);-
437-
438 info_ptr = png_create_info_struct(png_ptr);-
439 if (!info_ptr
!info_ptrDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
440 png_destroy_read_struct(&png_ptr, 0, 0);-
441 png_ptr = 0;-
442 return
never executed: return false;
false;
never executed: return false;
0
443 }-
444-
445 end_info = png_create_info_struct(png_ptr);-
446 if (!end_info
!end_infoDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
447 png_destroy_read_struct(&png_ptr, &info_ptr, 0);-
448 png_ptr = 0;-
449 return
never executed: return false;
false;
never executed: return false;
0
450 }-
451-
452 if (_setjmp (((png_ptr)->jmpbuf))
_setjmp (((png_ptr)->jmpbuf))Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
453 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);-
454 png_ptr = 0;-
455 return
never executed: return false;
false;
never executed: return false;
0
456 }-
457-
458 png_set_read_fn(png_ptr, this, iod_read_fn);-
459 png_read_info(png_ptr, info_ptr);-
460-
461 readPngTexts(info_ptr);-
462-
463 if (png_get_valid(png_ptr, info_ptr, 0x0001)
png_get_valid(...o_ptr, 0x0001)Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
464 double file_gamma = 0.0;-
465 png_get_gAMA(png_ptr, info_ptr, &file_gamma);-
466 fileGamma = file_gamma;-
467 }
never executed: end of block
0
468-
469 state = ReadHeader;-
470 return
never executed: return true;
true;
never executed: return true;
0
471}-
472-
473bool QPngHandlerPrivate::readPngImage(QImage *outImage)-
474{-
475 if (state == Error)-
476 return false;-
477-
478 if (state == Ready && !readPngHeader()) {-
479 state = Error;-
480 return false;-
481 }-
482-
483 if (_setjmp (((png_ptr)->jmpbuf))) {-
484 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);-
485 png_ptr = 0;-
486 amp.deallocate();-
487 state = Error;-
488 return false;-
489 }-
490-
491 bool doScaledRead = false;-
492 setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma, fileGamma);-
493-
494 if (outImage->isNull()) {-
495 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);-
496 png_ptr = 0;-
497 amp.deallocate();-
498 state = Error;-
499 return false;-
500 }-
501-
502 if (doScaledRead) {-
503 read_image_scaled(outImage, png_ptr, info_ptr, amp, scaledSize);-
504 } else {-
505 png_uint_32 width = 0;-
506 png_uint_32 height = 0;-
507 png_int_32 offset_x = 0;-
508 png_int_32 offset_y = 0;-
509-
510 int bit_depth = 0;-
511 int color_type = 0;-
512 int unit_type = 0;-
513 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);-
514 png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);-
515 uchar *data = outImage->bits();-
516 int bpl = outImage->bytesPerLine();-
517 amp.row_pointers = new png_bytep[height];-
518-
519 for (uint y = 0; y < height; y++)-
520 amp.row_pointers[y] = data + y * bpl;-
521-
522 png_read_image(png_ptr, amp.row_pointers);-
523 amp.deallocate();-
524-
525 outImage->setDotsPerMeterX(png_get_x_pixels_per_meter(png_ptr,info_ptr));-
526 outImage->setDotsPerMeterY(png_get_y_pixels_per_meter(png_ptr,info_ptr));-
527-
528 if (unit_type == 0)-
529 outImage->setOffset(QPoint(offset_x, offset_y));-
530-
531-
532 if (color_type == (2 | 1) && outImage->format() == QImage::Format_Indexed8) {-
533 int color_table_size = outImage->colorCount();-
534 for (int y=0; y<(int)height; ++y) {-
535 uchar *p = (data + (y) * bpl);-
536 uchar *end = p + width;-
537 while (p < end) {-
538 if (*p >= color_table_size)-
539 *p = 0;-
540 ++p;-
541 }-
542 }-
543 }-
544 }-
545-
546 state = ReadingEnd;-
547 png_read_end(png_ptr, end_info);-
548-
549 readPngTexts(end_info);-
550 for (int i = 0; i < readTexts.size()-1; i+=2)-
551 outImage->setText(readTexts.at(i), readTexts.at(i+1));-
552-
553 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);-
554 png_ptr = 0;-
555 amp.deallocate();-
556 state = Ready;-
557-
558 if (scaledSize.isValid() && outImage->size() != scaledSize)-
559 *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);-
560-
561 return true;-
562}-
563-
564QImage::Format QPngHandlerPrivate::readImageFormat()-
565{-
566 QImage::Format format = QImage::Format_Invalid;-
567 png_uint_32 width, height;-
568 int bit_depth, color_type;-
569 png_colorp palette;-
570 int num_palette;-
571 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);-
572 if (color_type == 0) {-
573-
574 if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) {-
575 format = QImage::Format_Mono;-
576 } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, 0x0010)) {-
577 format = QImage::Format_ARGB32;-
578 } else if (bit_depth == 8 && !png_get_valid(png_ptr, info_ptr, 0x0010)) {-
579 format = QImage::Format_Grayscale8;-
580 } else {-
581 format = QImage::Format_Indexed8;-
582 }-
583 } else if (color_type == (2 | 1)-
584 && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)-
585 && num_palette <= 256)-
586 {-
587-
588 format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8;-
589 } else {-
590-
591 format = QImage::Format_ARGB32;-
592-
593 if (!(color_type & 4)-
594 && !png_get_valid(png_ptr, info_ptr, 0x0010)) {-
595-
596 format = QImage::Format_RGB32;-
597 }-
598 }-
599-
600 return format;-
601}-
602-
603QPNGImageWriter::QPNGImageWriter(QIODevice* iod) :-
604 dev(iod),-
605 frames_written(0),-
606 disposal(Unspecified),-
607 looping(-1),-
608 ms_delay(-1),-
609 gamma(0.0)-
610{-
611}-
612-
613QPNGImageWriter::~QPNGImageWriter()-
614{-
615}-
616-
617void QPNGImageWriter::setDisposalMethod(DisposalMethod dm)-
618{-
619 disposal = dm;-
620}-
621-
622void QPNGImageWriter::setLooping(int loops)-
623{-
624 looping = loops;-
625}-
626-
627void QPNGImageWriter::setFrameDelay(int msecs)-
628{-
629 ms_delay = msecs;-
630}-
631-
632void QPNGImageWriter::setGamma(float g)-
633{-
634 gamma = g;-
635}-
636-
637-
638static void set_text(const QImage &image, png_structp png_ptr, png_infop info_ptr,-
639 const QString &description)-
640{-
641 QMap<QString, QString> text;-
642 for (QForeachContainer<typename QtPrivate::remove_reference<decltype(image.textKeys())>::type> _container_((image.textKeys())); _container_.control && _container_.i != _container_.e; ++_container_.i, _container_.control ^= 1) for (const QString &key = *_container_.i; _container_.control; _container_.control = 0) {-
643 if (!key.isEmpty()
!key.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
644 text.insert(key, image.text(key));
never executed: text.insert(key, image.text(key));
0
645 }
never executed: end of block
0
646 for (QForeachContainer<typename QtPrivate::remove_reference<decltype(description.split(QLatin1String("\n\n")))>::type> _container_((description.split(QLatin1String("\n\n")))); _container_.control && _container_.i != _container_.e; ++_container_.i, _container_.control ^= 1) for (const QString &pair = *_container_.i; _container_.control; _container_.control = 0) {-
647 int index = pair.indexOf(QLatin1Char(':'));-
648 if (index >= 0
index >= 0Description
TRUEnever evaluated
FALSEnever evaluated
&& pair.indexOf(QLatin1Char(' ')) < index
pair.indexOf(Q...(' ')) < indexDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
649 QString s = pair.simplified();-
650 if (!s.isEmpty()
!s.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
651 text.insert(QLatin1String("Description"), s);
never executed: text.insert(QLatin1String("Description"), s);
0
652 }
never executed: end of block
else {
0
653 QString key = pair.left(index);-
654 if (!key.simplified().isEmpty()
!key.simplified().isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
655 text.insert(key, pair.mid(index + 2).simplified());
never executed: text.insert(key, pair.mid(index + 2).simplified());
0
656 }
never executed: end of block
0
657 }-
658-
659 if (text.isEmpty()
text.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
660 return;
never executed: return;
0
661-
662 png_textp text_ptr = new png_text[text.size()];-
663 memset(text_ptr, 0, text.size() * sizeof(png_text));-
664-
665 QMap<QString, QString>::ConstIterator it = text.constBegin();-
666 int i = 0;-
667 while (it != text.constEnd()
it != text.constEnd()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
668 text_ptr[i].key = qstrdup(it.key().leftleftRef(79).toLatin1().constData());-
669 bool noCompress = (it.value().length() < 40);-
670 {-
671 text_ptr[i].compression = noCompress
noCompressDescription
TRUEnever evaluated
FALSEnever evaluated
? -1 : 0;
0
672 QByteArray value = it.value().toLatin1();-
673 text_ptr[i].text = qstrdup(value.constData());-
674 text_ptr[i].text_length = value.size();-
675 }-
676 ++i;-
677 ++it;-
678 }
never executed: end of block
0
679-
680 png_set_text(png_ptr, info_ptr, text_ptr, i);-
681 for (i = 0; i < text.size()
i < text.size()Description
TRUEnever evaluated
FALSEnever evaluated
; ++i) {
0
682 delete [] text_ptr[i].key;-
683 delete [] text_ptr[i].text;-
684-
685-
686-
687 }
never executed: end of block
0
688 delete [] text_ptr;-
689}
never executed: end of block
0
690-
691bool QPNGImageWriter::writeImage(const QImage& image, int off_x, int off_y)-
692{-
693 return writeImage(image, -1, QString(), off_x, off_y);-
694}-
695-
696bool QPNGImageWriter::writeImage(const QImage& image, volatile int quality_in, const QString &description,-
697 int off_x_in, int off_y_in)-
698{-
699 QPoint offset = image.offset();-
700 int off_x = off_x_in + offset.x();-
701 int off_y = off_y_in + offset.y();-
702-
703 png_structp png_ptr;-
704 png_infop info_ptr;-
705-
706 png_ptr = png_create_write_struct("1.2.50",0,0,0);-
707 if (!png_ptr) {-
708 return false;-
709 }-
710-
711 png_set_error_fn(png_ptr, 0, 0, qt_png_warning);-
712-
713 info_ptr = png_create_info_struct(png_ptr);-
714 if (!info_ptr) {-
715 png_destroy_write_struct(&png_ptr, 0);-
716 return false;-
717 }-
718-
719 if (_setjmp (((png_ptr)->jmpbuf))) {-
720 png_destroy_write_struct(&png_ptr, &info_ptr);-
721 return false;-
722 }-
723-
724 int quality = quality_in;-
725 if (quality >= 0) {-
726 if (quality > 9) {-
727 QMessageLogger(__FILE__, 844, __PRETTY_FUNCTION__).warning("PNG: Quality %d out of range", quality);-
728 quality = 9;-
729 }-
730 png_set_compression_level(png_ptr, quality);-
731 }-
732-
733 png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn);-
734-
735-
736 int color_type = 0;-
737 if (image.colorCount()) {-
738 if (image.isGrayscale())-
739 color_type = 0;-
740 else-
741 color_type = (2 | 1);-
742 }-
743 else if (image.format() == QImage::Format_Grayscale8)-
744 color_type = 0;-
745 else if (image.hasAlphaChannel())-
746 color_type = (2 | 4);-
747 else-
748 color_type = (2);-
749-
750 png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(),-
751 image.depth() == 1 ? 1 : 8,-
752 color_type, 0, 0, 0);-
753-
754 if (gamma != 0.0) {-
755 png_set_gAMA(png_ptr, info_ptr, 1.0/gamma);-
756 }-
757-
758 if (image.format() == QImage::Format_MonoLSB)-
759 png_set_packswap(png_ptr);-
760-
761 if (color_type == (2 | 1)) {-
762-
763 int num_palette = qMin(256, image.colorCount());-
764 png_color palette[256];-
765 png_byte trans[256];-
766 int num_trans = 0;-
767 for (int i=0; i<num_palette; i++) {-
768 QRgb rgba=image.color(i);-
769 palette[i].red = qRed(rgba);-
770 palette[i].green = qGreen(rgba);-
771 palette[i].blue = qBlue(rgba);-
772 trans[i] = qAlpha(rgba);-
773 if (trans[i] < 255) {-
774 num_trans = i+1;-
775 }-
776 }-
777 png_set_PLTE(png_ptr, info_ptr, palette, num_palette);-
778-
779 if (num_trans) {-
780 png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0);-
781 }-
782 }-
783-
784-
785-
786 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {-
787 png_set_swap_alpha(png_ptr);-
788 }-
789-
790-
791 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian-
792 && image.format() != QImage::Format_RGB888) {-
793 png_set_bgr(png_ptr);-
794 }-
795-
796 if (off_x || off_y) {-
797 png_set_oFFs(png_ptr, info_ptr, off_x, off_y, 0);-
798 }-
799-
800 if (frames_written > 0)-
801 png_set_sig_bytes(png_ptr, 8);-
802-
803 if (image.dotsPerMeterX() > 0 || image.dotsPerMeterY() > 0) {-
804 png_set_pHYs(png_ptr, info_ptr,-
805 image.dotsPerMeterX(), image.dotsPerMeterY(),-
806 1);-
807 }-
808-
809 set_text(image, png_ptr, info_ptr, description);-
810-
811 png_write_info(png_ptr, info_ptr);-
812-
813 if (image.depth() != 1)-
814 png_set_packing(png_ptr);-
815-
816 if (color_type == (2) && image.format() != QImage::Format_RGB888)-
817 png_set_filler(png_ptr, 0,-
818 QSysInfo::ByteOrder == QSysInfo::BigEndian ?-
819 0 : 1);-
820-
821 if (looping >= 0 && frames_written == 0) {-
822 uchar data[13] = "NETSCAPE2.0";-
823-
824 data[0xB] = looping%0x100;-
825 data[0xC] = looping/0x100;-
826 png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFx"), data, 13);-
827 }-
828 if (ms_delay >= 0 || disposal!=Unspecified) {-
829 uchar data[4];-
830 data[0] = disposal;-
831 data[1] = 0;-
832 data[2] = (ms_delay/10)/0x100;-
833 data[3] = (ms_delay/10)%0x100;-
834 png_write_chunk(png_ptr, const_cast<png_bytep>((const png_byte *)"gIFg"), data, 4);-
835 }-
836-
837 int height = image.height();-
838 int width = image.width();-
839 switch (image.format()) {-
840 case QImage::Format_Mono:-
841 case QImage::Format_MonoLSB:-
842 case QImage::Format_Indexed8:-
843 case QImage::Format_Grayscale8:-
844 case QImage::Format_RGB32:-
845 case QImage::Format_ARGB32:-
846 case QImage::Format_RGB888:-
847 {-
848 png_bytep* row_pointers = new png_bytep[height];-
849 for (int y=0; y<height; y++)-
850 row_pointers[y] = const_cast<png_bytep>(image.constScanLine(y));-
851 png_write_image(png_ptr, row_pointers);-
852 delete [] row_pointers;-
853 }-
854 break;-
855 default:-
856 {-
857 QImage::Format fmt = image.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32;-
858 QImage row;-
859 png_bytep row_pointers[1];-
860 for (int y=0; y<height; y++) {-
861 row = image.copy(0, y, width, 1).convertToFormat(fmt);-
862 row_pointers[0] = const_cast<png_bytep>(row.constScanLine(0));-
863 png_write_rows(png_ptr, row_pointers, 1);-
864 }-
865 }-
866 break;-
867 }-
868-
869 png_write_end(png_ptr, info_ptr);-
870 frames_written++;-
871-
872 png_destroy_write_struct(&png_ptr, &info_ptr);-
873-
874 return true;-
875}-
876-
877static bool write_png_image(const QImage &image, QIODevice *device,-
878 int quality, float gamma, const QString &description)-
879{-
880 QPNGImageWriter writer(device);-
881 if (quality >= 0) {-
882 quality = qMin(quality, 100);-
883 quality = (100-quality) * 9 / 91;-
884 }-
885 writer.setGamma(gamma);-
886 return writer.writeImage(image, quality, description);-
887}-
888-
889QPngHandler::QPngHandler()-
890 : d(new QPngHandlerPrivate(this))-
891{-
892}-
893-
894QPngHandler::~QPngHandler()-
895{-
896 if (d->png_ptr)-
897 png_destroy_read_struct(&d->png_ptr, &d->info_ptr, &d->end_info);-
898 delete d;-
899}-
900-
901bool QPngHandler::canRead() const-
902{-
903 if (d->state == QPngHandlerPrivate::Ready && !canRead(device()))-
904 return false;-
905-
906 if (d->state != QPngHandlerPrivate::Error) {-
907 setFormat("png");-
908 return true;-
909 }-
910-
911 return false;-
912}-
913-
914bool QPngHandler::canRead(QIODevice *device)-
915{-
916 if (!device) {-
917 QMessageLogger(__FILE__, 1034, __PRETTY_FUNCTION__).warning("QPngHandler::canRead() called with no device");-
918 return false;-
919 }-
920-
921 return device->peek(8) == "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";-
922}-
923-
924bool QPngHandler::read(QImage *image)-
925{-
926 if (!canRead())-
927 return false;-
928 return d->readPngImage(image);-
929}-
930-
931bool QPngHandler::write(const QImage &image)-
932{-
933 return write_png_image(image, device(), d->quality, d->gamma, d->description);-
934}-
935-
936bool QPngHandler::supportsOption(ImageOption option) const-
937{-
938 return option == Gamma-
939 || option == Description-
940 || option == ImageFormat-
941 || option == Quality-
942 || option == Size-
943 || option == ScaledSize;-
944}-
945-
946QVariant QPngHandler::option(ImageOption option) const-
947{-
948 if (d->state == QPngHandlerPrivate::Error)-
949 return QVariant();-
950 if (d->state == QPngHandlerPrivate::Ready && !d->readPngHeader())-
951 return QVariant();-
952-
953 if (option == Gamma)-
954 return d->gamma == 0.0 ? d->fileGamma : d->gamma;-
955 else if (option == Quality)-
956 return d->quality;-
957 else if (option == Description)-
958 return d->description;-
959 else if (option == Size)-
960 return QSize(png_get_image_width(d->png_ptr, d->info_ptr),-
961 png_get_image_height(d->png_ptr, d->info_ptr));-
962 else if (option == ScaledSize)-
963 return d->scaledSize;-
964 else if (option == ImageFormat)-
965 return d->readImageFormat();-
966 return QVariant();-
967}-
968-
969void QPngHandler::setOption(ImageOption option, const QVariant &value)-
970{-
971 if (option == Gamma)-
972 d->gamma = value.toFloat();-
973 else if (option == Quality)-
974 d->quality = value.toInt();-
975 else if (option == Description)-
976 d->description = value.toString();-
977 else if (option == ScaledSize)-
978 d->scaledSize = value.toSize();-
979}-
980-
981QByteArray QPngHandler::name() const-
982{-
983 return "png";-
984}-
985-
986-
Switch to Source codePreprocessed file

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