1 // Copyright 2014 PDFium Authors. All rights reserved.
\r
2 // Use of this source code is governed by a BSD-style license that can be
\r
3 // found in the LICENSE file.
\r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
\r
7 #include "../../../include/fxcodec/fx_codec.h"
\r
8 #include "../../../include/fxge/fx_dib.h"
\r
9 #include "codec_int.h"
\r
12 #include "../fx_lpng/include/fx_png.h"
\r
14 static void _png_error_data(png_structp png_ptr, png_const_charp error_msg)
\r
16 if(png_get_error_ptr(png_ptr)) {
\r
17 FXSYS_strncpy((char*)png_get_error_ptr(png_ptr), error_msg, PNG_ERROR_SIZE - 1);
\r
19 longjmp(png_jmpbuf(png_ptr), 1);
\r
21 static void _png_warning_data(png_structp png_ptr, png_const_charp error_msg)
\r
24 static void _png_load_bmp_attribute(png_structp png_ptr, png_infop info_ptr, CFX_DIBAttribute* pAttribute)
\r
27 #if defined(PNG_pHYs_SUPPORTED)
\r
28 pAttribute->m_nXDPI = png_get_x_pixels_per_meter(png_ptr, info_ptr);
\r
29 pAttribute->m_nYDPI = png_get_y_pixels_per_meter(png_ptr, info_ptr);
\r
30 png_uint_32 res_x, res_y;
\r
32 png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type);
\r
33 switch (unit_type) {
\r
34 case PNG_RESOLUTION_METER:
\r
35 pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_METER;
\r
38 pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_NONE;
\r
41 #if defined(PNG_iCCP_SUPPORTED)
\r
43 png_bytep icc_profile;
\r
44 png_uint_32 icc_proflen;
\r
46 png_get_iCCP(png_ptr, info_ptr, &icc_name, &compress_type, &icc_profile, &icc_proflen);
\r
49 #if defined(PNG_tIME_SUPPORTED)
\r
51 png_get_tIME(png_ptr, info_ptr, &t);
\r
53 FXSYS_memset32(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime));
\r
54 FXSYS_snprintf((FX_LPSTR)pAttribute->m_strTime, sizeof(pAttribute->m_strTime), "%4d:%2d:%2d %2d:%2d:%2d",
\r
55 t->year, t->month, t->day, t->hour, t->minute, t->second);
\r
56 pAttribute->m_strTime[sizeof(pAttribute->m_strTime) - 1] = 0;
\r
60 #if defined(PNG_TEXT_SUPPORTED)
\r
65 png_textp text = NULL;
\r
66 png_get_text(png_ptr, info_ptr, &text, &num_text);
\r
67 for (i = 0; i < num_text; i++) {
\r
68 len = (FX_DWORD)FXSYS_strlen(text[i].key);
\r
70 if (!FXSYS_memcmp32(buf, text[i].key, FX_MIN(len, FXSYS_strlen(buf)))) {
\r
72 FXSYS_memset32(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime));
\r
73 FXSYS_memcpy32(pAttribute->m_strTime, text[i].text,
\r
74 FX_MIN(sizeof(pAttribute->m_strTime) - 1, text[i].text_length));
\r
78 if (!FXSYS_memcmp32(buf, text[i].key, FX_MIN(len, FXSYS_strlen(buf)))) {
\r
79 pAttribute->m_strAuthor.Empty();
\r
80 pAttribute->m_strAuthor.Load((FX_LPBYTE)text[i].text, (FX_STRSIZE)text[i].text_length);
\r
87 struct FXPNG_Context {
\r
88 png_structp png_ptr;
\r
93 void* (*m_AllocFunc)(unsigned int);
\r
94 void (*m_FreeFunc)(void*);
\r
97 static void* _png_alloc_func(unsigned int size)
\r
99 return FX_Alloc(char, size);
\r
101 static void _png_free_func(void* p)
\r
108 static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr)
\r
110 FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr);
\r
114 CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr;
\r
115 if(pModule == NULL) {
\r
118 png_uint_32 width = 0, height = 0;
\r
119 int bpc = 0, color_type = 0 , color_type1 = 0, pass = 0;
\r
120 double gamma = 1.0;
\r
121 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bpc, &color_type, NULL, NULL, NULL);
\r
122 color_type1 = color_type;
\r
124 png_set_strip_16(png_ptr);
\r
125 } else if(bpc < 8) {
\r
126 png_set_expand_gray_1_2_4_to_8(png_ptr);
\r
129 if(color_type == PNG_COLOR_TYPE_PALETTE) {
\r
130 png_set_palette_to_rgb(png_ptr);
\r
132 pass = png_set_interlace_handling(png_ptr);
\r
133 if(!pModule->ReadHeaderCallback(p->child_ptr, width, height, bpc, pass, &color_type, &gamma)) {
\r
134 png_error(p->png_ptr, "Read Header Callback Error");
\r
137 if (png_get_sRGB(png_ptr, info_ptr, &intent)) {
\r
138 png_set_gamma(png_ptr, gamma, 0.45455);
\r
140 double image_gamma;
\r
141 if(png_get_gAMA(png_ptr, info_ptr, &image_gamma)) {
\r
142 png_set_gamma(png_ptr, gamma, image_gamma);
\r
144 png_set_gamma(png_ptr, gamma, 0.45455);
\r
147 switch(color_type) {
\r
148 case PNG_COLOR_TYPE_GRAY:
\r
149 case PNG_COLOR_TYPE_GRAY_ALPHA: {
\r
150 if(color_type1 & PNG_COLOR_MASK_COLOR) {
\r
151 png_set_rgb_to_gray(png_ptr, 1, 0.299, 0.587);
\r
155 case PNG_COLOR_TYPE_PALETTE:
\r
156 if(color_type1 != PNG_COLOR_TYPE_PALETTE) {
\r
157 png_error(p->png_ptr, "Not Support Output Palette Now");
\r
159 case PNG_COLOR_TYPE_RGB:
\r
160 case PNG_COLOR_TYPE_RGB_ALPHA:
\r
161 if(!(color_type1 & PNG_COLOR_MASK_COLOR)) {
\r
162 png_set_gray_to_rgb(png_ptr);
\r
164 png_set_bgr(png_ptr);
\r
167 if(!(color_type & PNG_COLOR_MASK_ALPHA)) {
\r
168 png_set_strip_alpha(png_ptr);
\r
170 if(color_type & PNG_COLOR_MASK_ALPHA && !(color_type1 & PNG_COLOR_MASK_ALPHA)) {
\r
171 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
\r
173 png_read_update_info(png_ptr, info_ptr);
\r
175 static void _png_get_end_func(png_structp png_ptr, png_infop info_ptr) {}
\r
176 static void _png_get_row_func(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass)
\r
178 FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr);
\r
182 CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr;
\r
183 FX_LPBYTE src_buf = NULL;
\r
184 if(!pModule->AskScanlineBufCallback(p->child_ptr, row_num, src_buf)) {
\r
185 png_error(png_ptr, "Ask Scanline buffer Callback Error");
\r
187 if(src_buf != NULL) {
\r
188 png_progressive_combine_row(png_ptr, src_buf, new_row);
\r
190 pModule->FillScanlineBufCompletedCallback(p->child_ptr, pass, row_num);
\r
192 void* CCodec_PngModule::Start(void* pModule)
\r
194 FXPNG_Context* p = (FXPNG_Context*)FX_Alloc(uint8_t, sizeof(FXPNG_Context));
\r
198 p->m_AllocFunc = _png_alloc_func;
\r
199 p->m_FreeFunc = _png_free_func;
\r
201 p->info_ptr = NULL;
\r
202 p->parent_ptr = (void*)this;
\r
203 p->child_ptr = pModule;
\r
204 p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
\r
205 if (p->png_ptr == NULL) {
\r
209 p->info_ptr = png_create_info_struct(p->png_ptr);
\r
210 if (p->info_ptr == NULL) {
\r
211 png_destroy_read_struct(&(p->png_ptr), (png_infopp)NULL, (png_infopp)NULL);
\r
215 if (setjmp(png_jmpbuf(p->png_ptr))) {
\r
217 png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL);
\r
222 png_set_progressive_read_fn(p->png_ptr, p,
\r
223 _png_get_header_func,
\r
225 _png_get_end_func);
\r
226 png_set_error_fn(p->png_ptr, m_szLastError, (png_error_ptr)_png_error_data, (png_error_ptr)_png_warning_data);
\r
229 void CCodec_PngModule::Finish(void* pContext)
\r
231 FXPNG_Context* p = (FXPNG_Context*)pContext;
\r
233 png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL);
\r
237 FX_BOOL CCodec_PngModule::Input(void* pContext, FX_LPCBYTE src_buf, FX_DWORD src_size, CFX_DIBAttribute* pAttribute)
\r
239 FXPNG_Context* p = (FXPNG_Context*)pContext;
\r
240 if(setjmp(png_jmpbuf(p->png_ptr))) {
\r
241 if (pAttribute && 0 == FXSYS_strcmp(m_szLastError, "Read Header Callback Error")) {
\r
242 _png_load_bmp_attribute(p->png_ptr, p->info_ptr, pAttribute);
\r
246 png_process_data(p->png_ptr, p->info_ptr, (FX_LPBYTE)src_buf, src_size);
\r