160 |
165 |
161 png_uint_32 width; |
166 png_uint_32 width; |
162 png_uint_32 height; |
167 png_uint_32 height; |
163 int bit_depth; |
168 int bit_depth; |
164 int color_type; |
169 int color_type; |
|
170 png_bytep trans_alpha = 0; |
|
171 png_color_16p trans_color_p = 0; |
|
172 int num_trans; |
|
173 png_colorp palette = 0; |
|
174 int num_palette; |
165 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); |
175 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); |
166 |
176 |
167 if (color_type == PNG_COLOR_TYPE_GRAY) { |
177 if (color_type == PNG_COLOR_TYPE_GRAY) { |
168 // Black & White or 8-bit grayscale |
178 // Black & White or 8-bit grayscale |
169 if (bit_depth == 1 && info_ptr->channels == 1) { |
179 if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) { |
170 png_set_invert_mono(png_ptr); |
180 png_set_invert_mono(png_ptr); |
171 png_read_update_info(png_ptr, info_ptr); |
181 png_read_update_info(png_ptr, info_ptr); |
172 if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) { |
182 if (image.size() != QSize(width, height) || image.format() != QImage::Format_Mono) { |
173 image = QImage(width, height, QImage::Format_Mono); |
183 image = QImage(width, height, QImage::Format_Mono); |
174 if (image.isNull()) |
184 if (image.isNull()) |
205 image.setColorCount(ncols); |
215 image.setColorCount(ncols); |
206 for (int i=0; i<ncols; i++) { |
216 for (int i=0; i<ncols; i++) { |
207 int c = i*255/(ncols-1); |
217 int c = i*255/(ncols-1); |
208 image.setColor(i, qRgba(c,c,c,0xff)); |
218 image.setColor(i, qRgba(c,c,c,0xff)); |
209 } |
219 } |
210 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
220 if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_color_p) { |
211 #if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4) |
221 const int g = trans_color_p->gray; |
212 const int g = info_ptr->trans_values.gray; |
|
213 #else |
|
214 const int g = info_ptr->trans_color.gray; |
|
215 #endif |
|
216 if (g < ncols) { |
222 if (g < ncols) { |
217 image.setColor(g, 0); |
223 image.setColor(g, 0); |
218 } |
224 } |
219 } |
225 } |
220 } |
226 } |
221 } else if (color_type == PNG_COLOR_TYPE_PALETTE |
227 } else if (color_type == PNG_COLOR_TYPE_PALETTE |
222 && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE) |
228 && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) |
223 && info_ptr->num_palette <= 256) |
229 && num_palette <= 256) |
224 { |
230 { |
225 // 1-bit and 8-bit color |
231 // 1-bit and 8-bit color |
226 if (bit_depth != 1) |
232 if (bit_depth != 1) |
227 png_set_packing(png_ptr); |
233 png_set_packing(png_ptr); |
228 png_read_update_info(png_ptr, info_ptr); |
234 png_read_update_info(png_ptr, info_ptr); |
231 if (image.size() != QSize(width, height) || image.format() != format) { |
237 if (image.size() != QSize(width, height) || image.format() != format) { |
232 image = QImage(width, height, format); |
238 image = QImage(width, height, format); |
233 if (image.isNull()) |
239 if (image.isNull()) |
234 return; |
240 return; |
235 } |
241 } |
236 image.setColorCount(info_ptr->num_palette); |
242 png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette); |
|
243 image.setColorCount(num_palette); |
237 int i = 0; |
244 int i = 0; |
238 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
245 if (png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, &trans_color_p) && trans_alpha) { |
239 while (i < info_ptr->num_trans) { |
246 while (i < num_trans) { |
240 image.setColor(i, qRgba( |
247 image.setColor(i, qRgba( |
241 info_ptr->palette[i].red, |
248 palette[i].red, |
242 info_ptr->palette[i].green, |
249 palette[i].green, |
243 info_ptr->palette[i].blue, |
250 palette[i].blue, |
244 #if PNG_LIBPNG_VER_MAJOR < 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR < 4) |
251 trans_alpha[i] |
245 info_ptr->trans[i] |
|
246 #else |
|
247 info_ptr->trans_alpha[i] |
|
248 #endif |
|
249 ) |
252 ) |
250 ); |
253 ); |
251 i++; |
254 i++; |
252 } |
255 } |
253 } |
256 } |
254 while (i < info_ptr->num_palette) { |
257 while (i < num_palette) { |
255 image.setColor(i, qRgba( |
258 image.setColor(i, qRgba( |
256 info_ptr->palette[i].red, |
259 palette[i].red, |
257 info_ptr->palette[i].green, |
260 palette[i].green, |
258 info_ptr->palette[i].blue, |
261 palette[i].blue, |
259 0xff |
262 0xff |
260 ) |
263 ) |
261 ); |
264 ); |
262 i++; |
265 i++; |
263 } |
266 } |
529 QImage::Format QPngHandlerPrivate::readImageFormat() |
532 QImage::Format QPngHandlerPrivate::readImageFormat() |
530 { |
533 { |
531 QImage::Format format = QImage::Format_Invalid; |
534 QImage::Format format = QImage::Format_Invalid; |
532 png_uint_32 width, height; |
535 png_uint_32 width, height; |
533 int bit_depth, color_type; |
536 int bit_depth, color_type; |
534 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) { |
537 png_colorp palette; |
|
538 int num_palette; |
|
539 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); |
|
540 if (color_type == PNG_COLOR_TYPE_GRAY) { |
535 // Black & White or 8-bit grayscale |
541 // Black & White or 8-bit grayscale |
536 if (info_ptr->bit_depth == 1 && info_ptr->channels == 1) { |
542 if (bit_depth == 1 && png_get_channels(png_ptr, info_ptr) == 1) { |
537 format = QImage::Format_Mono; |
543 format = QImage::Format_Mono; |
538 } else if (info_ptr->bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
544 } else if (bit_depth == 16 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
539 format = QImage::Format_ARGB32; |
545 format = QImage::Format_ARGB32; |
540 } else { |
546 } else { |
541 format = QImage::Format_Indexed8; |
547 format = QImage::Format_Indexed8; |
542 } |
548 } |
543 } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE |
549 } else if (color_type == PNG_COLOR_TYPE_PALETTE |
544 && png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE) |
550 && png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) |
545 && info_ptr->num_palette <= 256) |
551 && num_palette <= 256) |
546 { |
552 { |
547 // 1-bit and 8-bit color |
553 // 1-bit and 8-bit color |
548 if (info_ptr->bit_depth != 1) |
554 if (bit_depth != 1) |
549 png_set_packing(png_ptr); |
555 png_set_packing(png_ptr); |
550 png_read_update_info(png_ptr, info_ptr); |
556 png_read_update_info(png_ptr, info_ptr); |
551 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); |
557 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0); |
552 format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8; |
558 format = bit_depth == 1 ? QImage::Format_Mono : QImage::Format_Indexed8; |
553 } else { |
559 } else { |
554 // 32-bit |
560 // 32-bit |
555 if (info_ptr->bit_depth == 16) |
561 if (bit_depth == 16) |
556 png_set_strip_16(png_ptr); |
562 png_set_strip_16(png_ptr); |
557 |
563 |
558 format = QImage::Format_ARGB32; |
564 format = QImage::Format_ARGB32; |
559 // Only add filler if no alpha, or we can get 5 channel data. |
565 // Only add filler if no alpha, or we can get 5 channel data. |
560 if (!(info_ptr->color_type & PNG_COLOR_MASK_ALPHA) |
566 if (!(color_type & PNG_COLOR_MASK_ALPHA) |
561 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
567 && !png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
562 // We want 4 bytes, but it isn't an alpha channel |
568 // We want 4 bytes, but it isn't an alpha channel |
563 format = QImage::Format_RGB32; |
569 format = QImage::Format_RGB32; |
564 } |
570 } |
565 } |
571 } |
733 quality = 9; |
739 quality = 9; |
734 } |
740 } |
735 png_set_compression_level(png_ptr, quality); |
741 png_set_compression_level(png_ptr, quality); |
736 } |
742 } |
737 |
743 |
738 if (gamma != 0.0) { |
|
739 png_set_gAMA(png_ptr, info_ptr, 1.0/gamma); |
|
740 } |
|
741 |
|
742 png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn); |
744 png_set_write_fn(png_ptr, (void*)this, qpiw_write_fn, qpiw_flush_fn); |
743 |
|
744 info_ptr->channels = |
|
745 (image.depth() == 32) |
|
746 ? (image.format() == QImage::Format_RGB32 ? 3 : 4) |
|
747 : 1; |
|
748 |
745 |
749 png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), |
746 png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), |
750 image.depth() == 1 ? 1 : 8 /* per channel */, |
747 image.depth() == 1 ? 1 : 8 /* per channel */, |
751 image.depth() == 32 |
748 image.depth() == 32 |
752 ? image.format() == QImage::Format_RGB32 |
749 ? image.format() == QImage::Format_RGB32 |
753 ? PNG_COLOR_TYPE_RGB |
750 ? PNG_COLOR_TYPE_RGB |
754 : PNG_COLOR_TYPE_RGB_ALPHA |
751 : PNG_COLOR_TYPE_RGB_ALPHA |
755 : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); |
752 : PNG_COLOR_TYPE_PALETTE, 0, 0, 0); // also sets #channels |
756 |
753 |
757 |
754 if (gamma != 0.0) { |
758 //png_set_sBIT(png_ptr, info_ptr, 8); |
755 png_set_gAMA(png_ptr, info_ptr, 1.0/gamma); |
759 info_ptr->sig_bit.red = 8; |
756 } |
760 info_ptr->sig_bit.green = 8; |
757 |
761 info_ptr->sig_bit.blue = 8; |
758 png_color_8 sig_bit; |
|
759 sig_bit.red = 8; |
|
760 sig_bit.green = 8; |
|
761 sig_bit.blue = 8; |
|
762 sig_bit.alpha = image.hasAlphaChannel() ? 8 : 0; |
|
763 png_set_sBIT(png_ptr, info_ptr, &sig_bit); |
762 |
764 |
763 if (image.format() == QImage::Format_MonoLSB) |
765 if (image.format() == QImage::Format_MonoLSB) |
764 png_set_packswap(png_ptr); |
766 png_set_packswap(png_ptr); |
765 |
767 |
766 png_colorp palette = 0; |
|
767 png_bytep copy_trans = 0; |
|
768 if (image.colorCount()) { |
768 if (image.colorCount()) { |
769 // Paletted |
769 // Paletted |
770 int num_palette = image.colorCount(); |
770 int num_palette = qMin(256, image.colorCount()); |
771 palette = new png_color[num_palette]; |
771 png_color palette[256]; |
772 png_set_PLTE(png_ptr, info_ptr, palette, num_palette); |
772 png_byte trans[256]; |
773 int* trans = new int[num_palette]; |
|
774 int num_trans = 0; |
773 int num_trans = 0; |
775 for (int i=0; i<num_palette; i++) { |
774 for (int i=0; i<num_palette; i++) { |
776 QRgb rgb=image.color(i); |
775 QRgb rgba=image.color(i); |
777 info_ptr->palette[i].red = qRed(rgb); |
776 palette[i].red = qRed(rgba); |
778 info_ptr->palette[i].green = qGreen(rgb); |
777 palette[i].green = qGreen(rgba); |
779 info_ptr->palette[i].blue = qBlue(rgb); |
778 palette[i].blue = qBlue(rgba); |
780 trans[i] = rgb >> 24; |
779 trans[i] = qAlpha(rgba); |
781 if (trans[i] < 255) { |
780 if (trans[i] < 255) { |
782 num_trans = i+1; |
781 num_trans = i+1; |
783 } |
782 } |
784 } |
783 } |
|
784 png_set_PLTE(png_ptr, info_ptr, palette, num_palette); |
|
785 |
785 if (num_trans) { |
786 if (num_trans) { |
786 copy_trans = new png_byte[num_trans]; |
787 png_set_tRNS(png_ptr, info_ptr, trans, num_trans, 0); |
787 for (int i=0; i<num_trans; i++) |
788 } |
788 copy_trans[i] = trans[i]; |
|
789 png_set_tRNS(png_ptr, info_ptr, copy_trans, num_trans, 0); |
|
790 } |
|
791 delete [] trans; |
|
792 } |
|
793 |
|
794 if (image.format() != QImage::Format_RGB32) { |
|
795 info_ptr->sig_bit.alpha = 8; |
|
796 } |
789 } |
797 |
790 |
798 // Swap ARGB to RGBA (normal PNG format) before saving on |
791 // Swap ARGB to RGBA (normal PNG format) before saving on |
799 // BigEndian machines |
792 // BigEndian machines |
800 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { |
793 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { |