| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "core/include/fxcodec/fx_codec.h" | |
| 10 #include "core/include/fxge/fx_dib.h" | |
| 11 #include "core/src/fxcodec/codec/codec_int.h" | |
| 12 | |
| 13 extern "C" { | |
| 14 #undef FAR | |
| 15 #include "third_party/libpng16/png.h" | |
| 16 } | |
| 17 | |
| 18 static void _png_error_data(png_structp png_ptr, png_const_charp error_msg) { | |
| 19 if (png_get_error_ptr(png_ptr)) { | |
| 20 FXSYS_strncpy((char*)png_get_error_ptr(png_ptr), error_msg, | |
| 21 PNG_ERROR_SIZE - 1); | |
| 22 } | |
| 23 longjmp(png_jmpbuf(png_ptr), 1); | |
| 24 } | |
| 25 static void _png_warning_data(png_structp png_ptr, png_const_charp error_msg) {} | |
| 26 static void _png_load_bmp_attribute(png_structp png_ptr, | |
| 27 png_infop info_ptr, | |
| 28 CFX_DIBAttribute* pAttribute) { | |
| 29 if (pAttribute) { | |
| 30 #if defined(PNG_pHYs_SUPPORTED) | |
| 31 pAttribute->m_nXDPI = png_get_x_pixels_per_meter(png_ptr, info_ptr); | |
| 32 pAttribute->m_nYDPI = png_get_y_pixels_per_meter(png_ptr, info_ptr); | |
| 33 png_uint_32 res_x, res_y; | |
| 34 int unit_type; | |
| 35 png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type); | |
| 36 switch (unit_type) { | |
| 37 case PNG_RESOLUTION_METER: | |
| 38 pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_METER; | |
| 39 break; | |
| 40 default: | |
| 41 pAttribute->m_wDPIUnit = FXCODEC_RESUNIT_NONE; | |
| 42 } | |
| 43 #endif | |
| 44 #if defined(PNG_iCCP_SUPPORTED) | |
| 45 png_charp icc_name; | |
| 46 png_bytep icc_profile; | |
| 47 png_uint_32 icc_proflen; | |
| 48 int compress_type; | |
| 49 png_get_iCCP(png_ptr, info_ptr, &icc_name, &compress_type, &icc_profile, | |
| 50 &icc_proflen); | |
| 51 #endif | |
| 52 int bTime = 0; | |
| 53 #if defined(PNG_tIME_SUPPORTED) | |
| 54 png_timep t = NULL; | |
| 55 png_get_tIME(png_ptr, info_ptr, &t); | |
| 56 if (t) { | |
| 57 FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime)); | |
| 58 FXSYS_snprintf((FX_CHAR*)pAttribute->m_strTime, | |
| 59 sizeof(pAttribute->m_strTime), "%4d:%2d:%2d %2d:%2d:%2d", | |
| 60 t->year, t->month, t->day, t->hour, t->minute, t->second); | |
| 61 pAttribute->m_strTime[sizeof(pAttribute->m_strTime) - 1] = 0; | |
| 62 bTime = 1; | |
| 63 } | |
| 64 #endif | |
| 65 #if defined(PNG_TEXT_SUPPORTED) | |
| 66 int i; | |
| 67 FX_STRSIZE len; | |
| 68 const FX_CHAR* buf; | |
| 69 int num_text; | |
| 70 png_textp text = NULL; | |
| 71 png_get_text(png_ptr, info_ptr, &text, &num_text); | |
| 72 for (i = 0; i < num_text; i++) { | |
| 73 len = FXSYS_strlen(text[i].key); | |
| 74 buf = "Time"; | |
| 75 if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) { | |
| 76 if (!bTime) { | |
| 77 FXSYS_memset(pAttribute->m_strTime, 0, sizeof(pAttribute->m_strTime)); | |
| 78 FXSYS_memcpy( | |
| 79 pAttribute->m_strTime, text[i].text, | |
| 80 std::min(sizeof(pAttribute->m_strTime) - 1, text[i].text_length)); | |
| 81 } | |
| 82 } else { | |
| 83 buf = "Author"; | |
| 84 if (!FXSYS_memcmp(buf, text[i].key, std::min(len, FXSYS_strlen(buf)))) { | |
| 85 pAttribute->m_strAuthor.Empty(); | |
| 86 pAttribute->m_strAuthor.Load((uint8_t*)text[i].text, | |
| 87 (FX_STRSIZE)text[i].text_length); | |
| 88 } | |
| 89 } | |
| 90 } | |
| 91 #endif | |
| 92 } | |
| 93 } | |
| 94 struct FXPNG_Context { | |
| 95 png_structp png_ptr; | |
| 96 png_infop info_ptr; | |
| 97 void* parent_ptr; | |
| 98 void* child_ptr; | |
| 99 | |
| 100 void* (*m_AllocFunc)(unsigned int); | |
| 101 void (*m_FreeFunc)(void*); | |
| 102 }; | |
| 103 extern "C" { | |
| 104 static void* _png_alloc_func(unsigned int size) { | |
| 105 return FX_Alloc(char, size); | |
| 106 } | |
| 107 static void _png_free_func(void* p) { | |
| 108 FX_Free(p); | |
| 109 } | |
| 110 }; | |
| 111 static void _png_get_header_func(png_structp png_ptr, png_infop info_ptr) { | |
| 112 FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr); | |
| 113 if (p == NULL) { | |
| 114 return; | |
| 115 } | |
| 116 CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr; | |
| 117 if (pModule == NULL) { | |
| 118 return; | |
| 119 } | |
| 120 png_uint_32 width = 0, height = 0; | |
| 121 int bpc = 0, color_type = 0, color_type1 = 0, pass = 0; | |
| 122 double gamma = 1.0; | |
| 123 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bpc, &color_type, NULL, | |
| 124 NULL, NULL); | |
| 125 color_type1 = color_type; | |
| 126 if (bpc > 8) { | |
| 127 png_set_strip_16(png_ptr); | |
| 128 } else if (bpc < 8) { | |
| 129 png_set_expand_gray_1_2_4_to_8(png_ptr); | |
| 130 } | |
| 131 bpc = 8; | |
| 132 if (color_type == PNG_COLOR_TYPE_PALETTE) { | |
| 133 png_set_palette_to_rgb(png_ptr); | |
| 134 } | |
| 135 pass = png_set_interlace_handling(png_ptr); | |
| 136 if (!pModule->ReadHeaderCallback(p->child_ptr, width, height, bpc, pass, | |
| 137 &color_type, &gamma)) { | |
| 138 png_error(p->png_ptr, "Read Header Callback Error"); | |
| 139 } | |
| 140 int intent; | |
| 141 if (png_get_sRGB(png_ptr, info_ptr, &intent)) { | |
| 142 png_set_gamma(png_ptr, gamma, 0.45455); | |
| 143 } else { | |
| 144 double image_gamma; | |
| 145 if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) { | |
| 146 png_set_gamma(png_ptr, gamma, image_gamma); | |
| 147 } else { | |
| 148 png_set_gamma(png_ptr, gamma, 0.45455); | |
| 149 } | |
| 150 } | |
| 151 switch (color_type) { | |
| 152 case PNG_COLOR_TYPE_GRAY: | |
| 153 case PNG_COLOR_TYPE_GRAY_ALPHA: { | |
| 154 if (color_type1 & PNG_COLOR_MASK_COLOR) { | |
| 155 png_set_rgb_to_gray(png_ptr, 1, 0.299, 0.587); | |
| 156 } | |
| 157 } break; | |
| 158 case PNG_COLOR_TYPE_PALETTE: | |
| 159 if (color_type1 != PNG_COLOR_TYPE_PALETTE) { | |
| 160 png_error(p->png_ptr, "Not Support Output Palette Now"); | |
| 161 } | |
| 162 case PNG_COLOR_TYPE_RGB: | |
| 163 case PNG_COLOR_TYPE_RGB_ALPHA: | |
| 164 if (!(color_type1 & PNG_COLOR_MASK_COLOR)) { | |
| 165 png_set_gray_to_rgb(png_ptr); | |
| 166 } | |
| 167 png_set_bgr(png_ptr); | |
| 168 break; | |
| 169 } | |
| 170 if (!(color_type & PNG_COLOR_MASK_ALPHA)) { | |
| 171 png_set_strip_alpha(png_ptr); | |
| 172 } | |
| 173 if (color_type & PNG_COLOR_MASK_ALPHA && | |
| 174 !(color_type1 & PNG_COLOR_MASK_ALPHA)) { | |
| 175 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); | |
| 176 } | |
| 177 png_read_update_info(png_ptr, info_ptr); | |
| 178 } | |
| 179 static void _png_get_end_func(png_structp png_ptr, png_infop info_ptr) {} | |
| 180 static void _png_get_row_func(png_structp png_ptr, | |
| 181 png_bytep new_row, | |
| 182 png_uint_32 row_num, | |
| 183 int pass) { | |
| 184 FXPNG_Context* p = (FXPNG_Context*)png_get_progressive_ptr(png_ptr); | |
| 185 if (p == NULL) { | |
| 186 return; | |
| 187 } | |
| 188 CCodec_PngModule* pModule = (CCodec_PngModule*)p->parent_ptr; | |
| 189 uint8_t* src_buf = NULL; | |
| 190 if (!pModule->AskScanlineBufCallback(p->child_ptr, row_num, src_buf)) { | |
| 191 png_error(png_ptr, "Ask Scanline buffer Callback Error"); | |
| 192 } | |
| 193 if (src_buf) { | |
| 194 png_progressive_combine_row(png_ptr, src_buf, new_row); | |
| 195 } | |
| 196 pModule->FillScanlineBufCompletedCallback(p->child_ptr, pass, row_num); | |
| 197 } | |
| 198 void* CCodec_PngModule::Start(void* pModule) { | |
| 199 FXPNG_Context* p = (FXPNG_Context*)FX_Alloc(uint8_t, sizeof(FXPNG_Context)); | |
| 200 if (p == NULL) { | |
| 201 return NULL; | |
| 202 } | |
| 203 p->m_AllocFunc = _png_alloc_func; | |
| 204 p->m_FreeFunc = _png_free_func; | |
| 205 p->png_ptr = NULL; | |
| 206 p->info_ptr = NULL; | |
| 207 p->parent_ptr = (void*)this; | |
| 208 p->child_ptr = pModule; | |
| 209 p->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | |
| 210 if (p->png_ptr == NULL) { | |
| 211 FX_Free(p); | |
| 212 return NULL; | |
| 213 } | |
| 214 p->info_ptr = png_create_info_struct(p->png_ptr); | |
| 215 if (p->info_ptr == NULL) { | |
| 216 png_destroy_read_struct(&(p->png_ptr), (png_infopp)NULL, (png_infopp)NULL); | |
| 217 FX_Free(p); | |
| 218 return NULL; | |
| 219 } | |
| 220 if (setjmp(png_jmpbuf(p->png_ptr))) { | |
| 221 if (p) { | |
| 222 png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL); | |
| 223 FX_Free(p); | |
| 224 } | |
| 225 return NULL; | |
| 226 } | |
| 227 png_set_progressive_read_fn(p->png_ptr, p, _png_get_header_func, | |
| 228 _png_get_row_func, _png_get_end_func); | |
| 229 png_set_error_fn(p->png_ptr, m_szLastError, (png_error_ptr)_png_error_data, | |
| 230 (png_error_ptr)_png_warning_data); | |
| 231 return p; | |
| 232 } | |
| 233 void CCodec_PngModule::Finish(void* pContext) { | |
| 234 FXPNG_Context* p = (FXPNG_Context*)pContext; | |
| 235 if (p) { | |
| 236 png_destroy_read_struct(&(p->png_ptr), &(p->info_ptr), (png_infopp)NULL); | |
| 237 p->m_FreeFunc(p); | |
| 238 } | |
| 239 } | |
| 240 FX_BOOL CCodec_PngModule::Input(void* pContext, | |
| 241 const uint8_t* src_buf, | |
| 242 FX_DWORD src_size, | |
| 243 CFX_DIBAttribute* pAttribute) { | |
| 244 FXPNG_Context* p = (FXPNG_Context*)pContext; | |
| 245 if (setjmp(png_jmpbuf(p->png_ptr))) { | |
| 246 if (pAttribute && | |
| 247 0 == FXSYS_strcmp(m_szLastError, "Read Header Callback Error")) { | |
| 248 _png_load_bmp_attribute(p->png_ptr, p->info_ptr, pAttribute); | |
| 249 } | |
| 250 return FALSE; | |
| 251 } | |
| 252 png_process_data(p->png_ptr, p->info_ptr, (uint8_t*)src_buf, src_size); | |
| 253 return TRUE; | |
| 254 } | |
| OLD | NEW |