| OLD | NEW |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
| 6 | 6 |
| 7 #include "../../../../third_party/base/nonstd_unique_ptr.h" | 7 #include "../../../../third_party/base/nonstd_unique_ptr.h" |
| 8 #include "../../../../third_party/zlib_v128/zlib.h" | 8 #include "../../../../third_party/zlib_v128/zlib.h" |
| 9 #include "../../../include/fxcodec/fx_codec.h" | 9 #include "../../../include/fxcodec/fx_codec.h" |
| 10 #include "../../../include/fxcodec/fx_codec_flate.h" | 10 #include "../../../include/fxcodec/fx_codec_flate.h" |
| 11 #include "codec_int.h" | 11 #include "codec_int.h" |
| 12 | 12 |
| 13 extern "C" | 13 extern "C" { |
| 14 { | 14 static void* my_alloc_func(void* opaque, |
| 15 static void* my_alloc_func(void* opaque, unsigned int items, unsigned int si
ze) | 15 unsigned int items, |
| 16 { | 16 unsigned int size) { |
| 17 return FX_Alloc2D(uint8_t, items, size); | 17 return FX_Alloc2D(uint8_t, items, size); |
| 18 } | 18 } |
| 19 static void my_free_func(void* opaque, void* address) | 19 static void my_free_func(void* opaque, void* address) { |
| 20 { | 20 FX_Free(address); |
| 21 FX_Free(address); | 21 } |
| 22 } | 22 static int FPDFAPI_FlateGetTotalOut(void* context) { |
| 23 static int FPDFAPI_FlateGetTotalOut(void* context) | 23 return ((z_stream*)context)->total_out; |
| 24 { | 24 } |
| 25 return ((z_stream*)context)->total_out; | 25 static int FPDFAPI_FlateGetTotalIn(void* context) { |
| 26 } | 26 return ((z_stream*)context)->total_in; |
| 27 static int FPDFAPI_FlateGetTotalIn(void* context) | 27 } |
| 28 { | 28 static void FPDFAPI_FlateCompress(unsigned char* dest_buf, |
| 29 return ((z_stream*)context)->total_in; | 29 unsigned long* dest_size, |
| 30 } | 30 const unsigned char* src_buf, |
| 31 static void FPDFAPI_FlateCompress(unsigned char* dest_buf, | 31 unsigned long src_size) { |
| 32 unsigned long* dest_size, | 32 compress(dest_buf, dest_size, src_buf, src_size); |
| 33 const unsigned char* src_buf, | 33 } |
| 34 unsigned long src_size) | 34 void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned int), |
| 35 { | 35 void (*free_func)(void*, void*)) { |
| 36 compress(dest_buf, dest_size, src_buf, src_size); | 36 z_stream* p = (z_stream*)alloc_func(0, 1, sizeof(z_stream)); |
| 37 } | 37 if (p == NULL) { |
| 38 void* FPDFAPI_FlateInit(void* (*alloc_func)(void*, unsigned int, unsigned in
t), | 38 return NULL; |
| 39 void (*free_func)(void*, void*)) | 39 } |
| 40 { | 40 FXSYS_memset(p, 0, sizeof(z_stream)); |
| 41 z_stream* p = (z_stream*)alloc_func(0, 1, sizeof(z_stream)); | 41 p->zalloc = alloc_func; |
| 42 if (p == NULL) { | 42 p->zfree = free_func; |
| 43 return NULL; | 43 inflateInit(p); |
| 44 } | 44 return p; |
| 45 FXSYS_memset(p, 0, sizeof(z_stream)); | 45 } |
| 46 p->zalloc = alloc_func; | 46 void FPDFAPI_FlateInput(void* context, |
| 47 p->zfree = free_func; | 47 const unsigned char* src_buf, |
| 48 inflateInit(p); | 48 unsigned int src_size) { |
| 49 return p; | 49 ((z_stream*)context)->next_in = (unsigned char*)src_buf; |
| 50 } | 50 ((z_stream*)context)->avail_in = src_size; |
| 51 void FPDFAPI_FlateInput(void* context, const unsigned char* src_buf, unsigne
d int src_size) | 51 } |
| 52 { | 52 int FPDFAPI_FlateOutput(void* context, |
| 53 ((z_stream*)context)->next_in = (unsigned char*)src_buf; | 53 unsigned char* dest_buf, |
| 54 ((z_stream*)context)->avail_in = src_size; | 54 unsigned int dest_size) { |
| 55 } | 55 ((z_stream*)context)->next_out = dest_buf; |
| 56 int FPDFAPI_FlateOutput(void* context, unsigned char* dest_buf, unsigned int
dest_size) | 56 ((z_stream*)context)->avail_out = dest_size; |
| 57 { | 57 unsigned int pre_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context); |
| 58 ((z_stream*)context)->next_out = dest_buf; | 58 int ret = inflate((z_stream*)context, Z_SYNC_FLUSH); |
| 59 ((z_stream*)context)->avail_out = dest_size; | 59 unsigned int post_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context); |
| 60 unsigned int pre_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context); | 60 unsigned int written = post_pos - pre_pos; |
| 61 int ret = inflate((z_stream*)context, Z_SYNC_FLUSH); | 61 if (written < dest_size) { |
| 62 unsigned int post_pos = (unsigned int)FPDFAPI_FlateGetTotalOut(context); | 62 FXSYS_memset(dest_buf + written, '\0', dest_size - written); |
| 63 unsigned int written = post_pos - pre_pos; | 63 } |
| 64 if (written < dest_size) { | 64 return ret; |
| 65 FXSYS_memset(dest_buf + written, '\0', dest_size - written); | 65 } |
| 66 } | 66 int FPDFAPI_FlateGetAvailIn(void* context) { |
| 67 return ret; | 67 return ((z_stream*)context)->avail_in; |
| 68 } | 68 } |
| 69 int FPDFAPI_FlateGetAvailIn(void* context) | 69 int FPDFAPI_FlateGetAvailOut(void* context) { |
| 70 { | 70 return ((z_stream*)context)->avail_out; |
| 71 return ((z_stream*)context)->avail_in; | 71 } |
| 72 } | 72 void FPDFAPI_FlateEnd(void* context) { |
| 73 int FPDFAPI_FlateGetAvailOut(void* context) | 73 inflateEnd((z_stream*)context); |
| 74 { | 74 ((z_stream*)context)->zfree(0, context); |
| 75 return ((z_stream*)context)->avail_out; | 75 } |
| 76 } | |
| 77 void FPDFAPI_FlateEnd(void* context) | |
| 78 { | |
| 79 inflateEnd((z_stream*)context); | |
| 80 ((z_stream*)context)->zfree(0, context); | |
| 81 } | |
| 82 } // extern "C" | 76 } // extern "C" |
| 83 | 77 |
| 84 class CLZWDecoder | 78 class CLZWDecoder { |
| 85 { | 79 public: |
| 86 public: | 80 int Decode(uint8_t* output, |
| 87 int Decode(uint8_t* output, FX_DWORD& outlen, const uint8_t* input, FX_DWORD
& size, FX_BOOL bEarlyChange); | 81 FX_DWORD& outlen, |
| 82 const uint8_t* input, |
| 83 FX_DWORD& size, |
| 84 FX_BOOL bEarlyChange); |
| 88 | 85 |
| 89 private: | 86 private: |
| 90 void AddCode(FX_DWORD prefix_code, uint8_t append_char); | 87 void AddCode(FX_DWORD prefix_code, uint8_t append_char); |
| 91 void DecodeString(FX_DWORD code); | 88 void DecodeString(FX_DWORD code); |
| 92 | 89 |
| 93 FX_DWORD» m_InPos; | 90 FX_DWORD m_InPos; |
| 94 FX_DWORD» m_OutPos; | 91 FX_DWORD m_OutPos; |
| 95 uint8_t*» m_pOutput; | 92 uint8_t* m_pOutput; |
| 96 const uint8_t*» m_pInput; | 93 const uint8_t* m_pInput; |
| 97 FX_BOOL» » m_Early; | 94 FX_BOOL m_Early; |
| 98 FX_DWORD» m_CodeArray[5021]; | 95 FX_DWORD m_CodeArray[5021]; |
| 99 FX_DWORD» m_nCodes; | 96 FX_DWORD m_nCodes; |
| 100 uint8_t» » m_DecodeStack[4000]; | 97 uint8_t m_DecodeStack[4000]; |
| 101 FX_DWORD» m_StackLen; | 98 FX_DWORD m_StackLen; |
| 102 int»» » m_CodeLen; | 99 int m_CodeLen; |
| 103 }; | 100 }; |
| 104 void CLZWDecoder::AddCode(FX_DWORD prefix_code, uint8_t append_char) | 101 void CLZWDecoder::AddCode(FX_DWORD prefix_code, uint8_t append_char) { |
| 105 { | 102 if (m_nCodes + m_Early == 4094) { |
| 106 if (m_nCodes + m_Early == 4094) { | 103 return; |
| 107 return; | 104 } |
| 108 } | 105 m_CodeArray[m_nCodes++] = (prefix_code << 16) | append_char; |
| 109 m_CodeArray[m_nCodes ++] = (prefix_code << 16) | append_char; | 106 if (m_nCodes + m_Early == 512 - 258) { |
| 110 if (m_nCodes + m_Early == 512 - 258) { | 107 m_CodeLen = 10; |
| 111 m_CodeLen = 10; | 108 } else if (m_nCodes + m_Early == 1024 - 258) { |
| 112 } else if (m_nCodes + m_Early == 1024 - 258) { | 109 m_CodeLen = 11; |
| 113 m_CodeLen = 11; | 110 } else if (m_nCodes + m_Early == 2048 - 258) { |
| 114 } else if (m_nCodes + m_Early == 2048 - 258) { | 111 m_CodeLen = 12; |
| 115 m_CodeLen = 12; | 112 } |
| 116 } | 113 } |
| 117 } | 114 void CLZWDecoder::DecodeString(FX_DWORD code) { |
| 118 void CLZWDecoder::DecodeString(FX_DWORD code) | 115 while (1) { |
| 119 { | 116 int index = code - 258; |
| 117 if (index < 0 || index >= (int)m_nCodes) { |
| 118 break; |
| 119 } |
| 120 FX_DWORD data = m_CodeArray[index]; |
| 121 if (m_StackLen >= sizeof(m_DecodeStack)) { |
| 122 return; |
| 123 } |
| 124 m_DecodeStack[m_StackLen++] = (uint8_t)data; |
| 125 code = data >> 16; |
| 126 } |
| 127 if (m_StackLen >= sizeof(m_DecodeStack)) { |
| 128 return; |
| 129 } |
| 130 m_DecodeStack[m_StackLen++] = (uint8_t)code; |
| 131 } |
| 132 int CLZWDecoder::Decode(uint8_t* dest_buf, |
| 133 FX_DWORD& dest_size, |
| 134 const uint8_t* src_buf, |
| 135 FX_DWORD& src_size, |
| 136 FX_BOOL bEarlyChange) { |
| 137 m_CodeLen = 9; |
| 138 m_InPos = 0; |
| 139 m_OutPos = 0; |
| 140 m_pInput = src_buf; |
| 141 m_pOutput = dest_buf; |
| 142 m_Early = bEarlyChange ? 1 : 0; |
| 143 m_nCodes = 0; |
| 144 FX_DWORD old_code = (FX_DWORD)-1; |
| 145 uint8_t last_char; |
| 146 while (1) { |
| 147 if (m_InPos + m_CodeLen > src_size * 8) { |
| 148 break; |
| 149 } |
| 150 int byte_pos = m_InPos / 8; |
| 151 int bit_pos = m_InPos % 8, bit_left = m_CodeLen; |
| 152 FX_DWORD code = 0; |
| 153 if (bit_pos) { |
| 154 bit_left -= 8 - bit_pos; |
| 155 code = (m_pInput[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_left; |
| 156 } |
| 157 if (bit_left < 8) { |
| 158 code |= m_pInput[byte_pos] >> (8 - bit_left); |
| 159 } else { |
| 160 bit_left -= 8; |
| 161 code |= m_pInput[byte_pos++] << bit_left; |
| 162 if (bit_left) { |
| 163 code |= m_pInput[byte_pos] >> (8 - bit_left); |
| 164 } |
| 165 } |
| 166 m_InPos += m_CodeLen; |
| 167 if (code < 256) { |
| 168 if (m_OutPos == dest_size) { |
| 169 return -5; |
| 170 } |
| 171 if (m_pOutput) { |
| 172 m_pOutput[m_OutPos] = (uint8_t)code; |
| 173 } |
| 174 m_OutPos++; |
| 175 last_char = (uint8_t)code; |
| 176 if (old_code != (FX_DWORD)-1) { |
| 177 AddCode(old_code, last_char); |
| 178 } |
| 179 old_code = code; |
| 180 } else if (code == 256) { |
| 181 m_CodeLen = 9; |
| 182 m_nCodes = 0; |
| 183 old_code = (FX_DWORD)-1; |
| 184 } else if (code == 257) { |
| 185 break; |
| 186 } else { |
| 187 if (old_code == (FX_DWORD)-1) { |
| 188 return 2; |
| 189 } |
| 190 m_StackLen = 0; |
| 191 if (code >= m_nCodes + 258) { |
| 192 if (m_StackLen < sizeof(m_DecodeStack)) { |
| 193 m_DecodeStack[m_StackLen++] = last_char; |
| 194 } |
| 195 DecodeString(old_code); |
| 196 } else { |
| 197 DecodeString(code); |
| 198 } |
| 199 if (m_OutPos + m_StackLen > dest_size) { |
| 200 return -5; |
| 201 } |
| 202 if (m_pOutput) { |
| 203 for (FX_DWORD i = 0; i < m_StackLen; i++) { |
| 204 m_pOutput[m_OutPos + i] = m_DecodeStack[m_StackLen - i - 1]; |
| 205 } |
| 206 } |
| 207 m_OutPos += m_StackLen; |
| 208 last_char = m_DecodeStack[m_StackLen - 1]; |
| 209 if (old_code < 256) { |
| 210 AddCode(old_code, last_char); |
| 211 } else if (old_code - 258 >= m_nCodes) { |
| 212 dest_size = m_OutPos; |
| 213 src_size = (m_InPos + 7) / 8; |
| 214 return 0; |
| 215 } else { |
| 216 AddCode(old_code, last_char); |
| 217 } |
| 218 old_code = code; |
| 219 } |
| 220 } |
| 221 dest_size = m_OutPos; |
| 222 src_size = (m_InPos + 7) / 8; |
| 223 return 0; |
| 224 } |
| 225 static uint8_t PaethPredictor(int a, int b, int c) { |
| 226 int p = a + b - c; |
| 227 int pa = FXSYS_abs(p - a); |
| 228 int pb = FXSYS_abs(p - b); |
| 229 int pc = FXSYS_abs(p - c); |
| 230 if (pa <= pb && pa <= pc) { |
| 231 return (uint8_t)a; |
| 232 } |
| 233 if (pb <= pc) { |
| 234 return (uint8_t)b; |
| 235 } |
| 236 return (uint8_t)c; |
| 237 } |
| 238 static FX_BOOL PNG_PredictorEncode(uint8_t*& data_buf, |
| 239 FX_DWORD& data_size, |
| 240 int predictor, |
| 241 int Colors, |
| 242 int BitsPerComponent, |
| 243 int Columns) { |
| 244 const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8; |
| 245 const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; |
| 246 if (row_size <= 0) |
| 247 return FALSE; |
| 248 const int row_count = (data_size + row_size - 1) / row_size; |
| 249 const int last_row_size = data_size % row_size; |
| 250 uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size + 1, row_count); |
| 251 int byte_cnt = 0; |
| 252 uint8_t* pSrcData = data_buf; |
| 253 uint8_t* pDestData = dest_buf; |
| 254 for (int row = 0; row < row_count; row++) { |
| 255 if (predictor == 10) { |
| 256 pDestData[0] = 0; |
| 257 int move_size = row_size; |
| 258 if (move_size * (row + 1) > (int)data_size) { |
| 259 move_size = data_size - (move_size * row); |
| 260 } |
| 261 FXSYS_memmove(pDestData + 1, pSrcData, move_size); |
| 262 pDestData += (move_size + 1); |
| 263 pSrcData += move_size; |
| 264 byte_cnt += move_size; |
| 265 continue; |
| 266 } |
| 267 for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte++) { |
| 268 switch (predictor) { |
| 269 case 11: { |
| 270 pDestData[0] = 1; |
| 271 uint8_t left = 0; |
| 272 if (byte >= BytesPerPixel) { |
| 273 left = pSrcData[byte - BytesPerPixel]; |
| 274 } |
| 275 pDestData[byte + 1] = pSrcData[byte] - left; |
| 276 } break; |
| 277 case 12: { |
| 278 pDestData[0] = 2; |
| 279 uint8_t up = 0; |
| 280 if (row) { |
| 281 up = pSrcData[byte - row_size]; |
| 282 } |
| 283 pDestData[byte + 1] = pSrcData[byte] - up; |
| 284 } break; |
| 285 case 13: { |
| 286 pDestData[0] = 3; |
| 287 uint8_t left = 0; |
| 288 if (byte >= BytesPerPixel) { |
| 289 left = pSrcData[byte - BytesPerPixel]; |
| 290 } |
| 291 uint8_t up = 0; |
| 292 if (row) { |
| 293 up = pSrcData[byte - row_size]; |
| 294 } |
| 295 pDestData[byte + 1] = pSrcData[byte] - (left + up) / 2; |
| 296 } break; |
| 297 case 14: { |
| 298 pDestData[0] = 4; |
| 299 uint8_t left = 0; |
| 300 if (byte >= BytesPerPixel) { |
| 301 left = pSrcData[byte - BytesPerPixel]; |
| 302 } |
| 303 uint8_t up = 0; |
| 304 if (row) { |
| 305 up = pSrcData[byte - row_size]; |
| 306 } |
| 307 uint8_t upper_left = 0; |
| 308 if (byte >= BytesPerPixel && row) { |
| 309 upper_left = pSrcData[byte - row_size - BytesPerPixel]; |
| 310 } |
| 311 pDestData[byte + 1] = |
| 312 pSrcData[byte] - PaethPredictor(left, up, upper_left); |
| 313 } break; |
| 314 default: { pDestData[byte + 1] = pSrcData[byte]; } break; |
| 315 } |
| 316 byte_cnt++; |
| 317 } |
| 318 pDestData += (row_size + 1); |
| 319 pSrcData += row_size; |
| 320 } |
| 321 FX_Free(data_buf); |
| 322 data_buf = dest_buf; |
| 323 data_size = (row_size + 1) * row_count - |
| 324 (last_row_size > 0 ? (row_size - last_row_size) : 0); |
| 325 return TRUE; |
| 326 } |
| 327 static void PNG_PredictLine(uint8_t* pDestData, |
| 328 const uint8_t* pSrcData, |
| 329 const uint8_t* pLastLine, |
| 330 int bpc, |
| 331 int nColors, |
| 332 int nPixels) { |
| 333 int row_size = (nPixels * bpc * nColors + 7) / 8; |
| 334 int BytesPerPixel = (bpc * nColors + 7) / 8; |
| 335 uint8_t tag = pSrcData[0]; |
| 336 if (tag == 0) { |
| 337 FXSYS_memmove(pDestData, pSrcData + 1, row_size); |
| 338 return; |
| 339 } |
| 340 for (int byte = 0; byte < row_size; byte++) { |
| 341 uint8_t raw_byte = pSrcData[byte + 1]; |
| 342 switch (tag) { |
| 343 case 1: { |
| 344 uint8_t left = 0; |
| 345 if (byte >= BytesPerPixel) { |
| 346 left = pDestData[byte - BytesPerPixel]; |
| 347 } |
| 348 pDestData[byte] = raw_byte + left; |
| 349 break; |
| 350 } |
| 351 case 2: { |
| 352 uint8_t up = 0; |
| 353 if (pLastLine) { |
| 354 up = pLastLine[byte]; |
| 355 } |
| 356 pDestData[byte] = raw_byte + up; |
| 357 break; |
| 358 } |
| 359 case 3: { |
| 360 uint8_t left = 0; |
| 361 if (byte >= BytesPerPixel) { |
| 362 left = pDestData[byte - BytesPerPixel]; |
| 363 } |
| 364 uint8_t up = 0; |
| 365 if (pLastLine) { |
| 366 up = pLastLine[byte]; |
| 367 } |
| 368 pDestData[byte] = raw_byte + (up + left) / 2; |
| 369 break; |
| 370 } |
| 371 case 4: { |
| 372 uint8_t left = 0; |
| 373 if (byte >= BytesPerPixel) { |
| 374 left = pDestData[byte - BytesPerPixel]; |
| 375 } |
| 376 uint8_t up = 0; |
| 377 if (pLastLine) { |
| 378 up = pLastLine[byte]; |
| 379 } |
| 380 uint8_t upper_left = 0; |
| 381 if (byte >= BytesPerPixel && pLastLine) { |
| 382 upper_left = pLastLine[byte - BytesPerPixel]; |
| 383 } |
| 384 pDestData[byte] = raw_byte + PaethPredictor(left, up, upper_left); |
| 385 break; |
| 386 } |
| 387 default: |
| 388 pDestData[byte] = raw_byte; |
| 389 break; |
| 390 } |
| 391 } |
| 392 } |
| 393 static FX_BOOL PNG_Predictor(uint8_t*& data_buf, |
| 394 FX_DWORD& data_size, |
| 395 int Colors, |
| 396 int BitsPerComponent, |
| 397 int Columns) { |
| 398 const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8; |
| 399 const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; |
| 400 if (row_size <= 0) |
| 401 return FALSE; |
| 402 const int row_count = (data_size + row_size) / (row_size + 1); |
| 403 const int last_row_size = data_size % (row_size + 1); |
| 404 uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size, row_count); |
| 405 int byte_cnt = 0; |
| 406 uint8_t* pSrcData = data_buf; |
| 407 uint8_t* pDestData = dest_buf; |
| 408 for (int row = 0; row < row_count; row++) { |
| 409 uint8_t tag = pSrcData[0]; |
| 410 byte_cnt++; |
| 411 if (tag == 0) { |
| 412 int move_size = row_size; |
| 413 if ((row + 1) * (move_size + 1) > (int)data_size) { |
| 414 move_size = last_row_size - 1; |
| 415 } |
| 416 FXSYS_memmove(pDestData, pSrcData + 1, move_size); |
| 417 pSrcData += move_size + 1; |
| 418 pDestData += move_size; |
| 419 byte_cnt += move_size; |
| 420 continue; |
| 421 } |
| 422 for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte++) { |
| 423 uint8_t raw_byte = pSrcData[byte + 1]; |
| 424 switch (tag) { |
| 425 case 1: { |
| 426 uint8_t left = 0; |
| 427 if (byte >= BytesPerPixel) { |
| 428 left = pDestData[byte - BytesPerPixel]; |
| 429 } |
| 430 pDestData[byte] = raw_byte + left; |
| 431 break; |
| 432 } |
| 433 case 2: { |
| 434 uint8_t up = 0; |
| 435 if (row) { |
| 436 up = pDestData[byte - row_size]; |
| 437 } |
| 438 pDestData[byte] = raw_byte + up; |
| 439 break; |
| 440 } |
| 441 case 3: { |
| 442 uint8_t left = 0; |
| 443 if (byte >= BytesPerPixel) { |
| 444 left = pDestData[byte - BytesPerPixel]; |
| 445 } |
| 446 uint8_t up = 0; |
| 447 if (row) { |
| 448 up = pDestData[byte - row_size]; |
| 449 } |
| 450 pDestData[byte] = raw_byte + (up + left) / 2; |
| 451 break; |
| 452 } |
| 453 case 4: { |
| 454 uint8_t left = 0; |
| 455 if (byte >= BytesPerPixel) { |
| 456 left = pDestData[byte - BytesPerPixel]; |
| 457 } |
| 458 uint8_t up = 0; |
| 459 if (row) { |
| 460 up = pDestData[byte - row_size]; |
| 461 } |
| 462 uint8_t upper_left = 0; |
| 463 if (byte >= BytesPerPixel && row) { |
| 464 upper_left = pDestData[byte - row_size - BytesPerPixel]; |
| 465 } |
| 466 pDestData[byte] = raw_byte + PaethPredictor(left, up, upper_left); |
| 467 break; |
| 468 } |
| 469 default: |
| 470 pDestData[byte] = raw_byte; |
| 471 break; |
| 472 } |
| 473 byte_cnt++; |
| 474 } |
| 475 pSrcData += row_size + 1; |
| 476 pDestData += row_size; |
| 477 } |
| 478 FX_Free(data_buf); |
| 479 data_buf = dest_buf; |
| 480 data_size = row_size * row_count - |
| 481 (last_row_size > 0 ? (row_size + 1 - last_row_size) : 0); |
| 482 return TRUE; |
| 483 } |
| 484 static void TIFF_PredictorEncodeLine(uint8_t* dest_buf, |
| 485 int row_size, |
| 486 int BitsPerComponent, |
| 487 int Colors, |
| 488 int Columns) { |
| 489 int BytesPerPixel = BitsPerComponent * Colors / 8; |
| 490 if (BitsPerComponent < 8) { |
| 491 uint8_t mask = 0x01; |
| 492 if (BitsPerComponent == 2) { |
| 493 mask = 0x03; |
| 494 } else if (BitsPerComponent == 4) { |
| 495 mask = 0x0F; |
| 496 } |
| 497 int row_bits = Colors * BitsPerComponent * Columns; |
| 498 for (int i = row_bits - BitsPerComponent; i >= BitsPerComponent; |
| 499 i -= BitsPerComponent) { |
| 500 int col = i % 8; |
| 501 int index = i / 8; |
| 502 int col_pre = |
| 503 (col == 0) ? (8 - BitsPerComponent) : (col - BitsPerComponent); |
| 504 int index_pre = (col == 0) ? (index - 1) : index; |
| 505 uint8_t cur = (dest_buf[index] >> (8 - col - BitsPerComponent)) & mask; |
| 506 uint8_t left = |
| 507 (dest_buf[index_pre] >> (8 - col_pre - BitsPerComponent)) & mask; |
| 508 cur -= left; |
| 509 cur &= mask; |
| 510 cur <<= (8 - col - BitsPerComponent); |
| 511 dest_buf[index] &= ~(mask << ((8 - col - BitsPerComponent))); |
| 512 dest_buf[index] |= cur; |
| 513 } |
| 514 } else if (BitsPerComponent == 8) { |
| 515 for (int i = row_size - 1; i >= BytesPerPixel; i--) { |
| 516 dest_buf[i] -= dest_buf[i - BytesPerPixel]; |
| 517 } |
| 518 } else { |
| 519 for (int i = row_size - BytesPerPixel; i >= BytesPerPixel; |
| 520 i -= BytesPerPixel) { |
| 521 FX_WORD pixel = (dest_buf[i] << 8) | dest_buf[i + 1]; |
| 522 pixel -= |
| 523 (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1]; |
| 524 dest_buf[i] = pixel >> 8; |
| 525 dest_buf[i + 1] = (uint8_t)pixel; |
| 526 } |
| 527 } |
| 528 } |
| 529 static FX_BOOL TIFF_PredictorEncode(uint8_t*& data_buf, |
| 530 FX_DWORD& data_size, |
| 531 int Colors, |
| 532 int BitsPerComponent, |
| 533 int Columns) { |
| 534 int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; |
| 535 if (row_size == 0) |
| 536 return FALSE; |
| 537 const int row_count = (data_size + row_size - 1) / row_size; |
| 538 const int last_row_size = data_size % row_size; |
| 539 for (int row = 0; row < row_count; row++) { |
| 540 uint8_t* scan_line = data_buf + row * row_size; |
| 541 if ((row + 1) * row_size > (int)data_size) { |
| 542 row_size = last_row_size; |
| 543 } |
| 544 TIFF_PredictorEncodeLine(scan_line, row_size, BitsPerComponent, Colors, |
| 545 Columns); |
| 546 } |
| 547 return TRUE; |
| 548 } |
| 549 static void TIFF_PredictLine(uint8_t* dest_buf, |
| 550 int row_size, |
| 551 int BitsPerComponent, |
| 552 int Colors, |
| 553 int Columns) { |
| 554 if (BitsPerComponent == 1) { |
| 555 int row_bits = FX_MIN(BitsPerComponent * Colors * Columns, row_size * 8); |
| 556 int index_pre = 0; |
| 557 int col_pre = 0; |
| 558 for (int i = 1; i < row_bits; i++) { |
| 559 int col = i % 8; |
| 560 int index = i / 8; |
| 561 if (((dest_buf[index] >> (7 - col)) & 1) ^ |
| 562 ((dest_buf[index_pre] >> (7 - col_pre)) & 1)) { |
| 563 dest_buf[index] |= 1 << (7 - col); |
| 564 } else { |
| 565 dest_buf[index] &= ~(1 << (7 - col)); |
| 566 } |
| 567 index_pre = index; |
| 568 col_pre = col; |
| 569 } |
| 570 return; |
| 571 } |
| 572 int BytesPerPixel = BitsPerComponent * Colors / 8; |
| 573 if (BitsPerComponent == 16) { |
| 574 for (int i = BytesPerPixel; i < row_size; i += 2) { |
| 575 FX_WORD pixel = |
| 576 (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerPixel + 1]; |
| 577 pixel += (dest_buf[i] << 8) | dest_buf[i + 1]; |
| 578 dest_buf[i] = pixel >> 8; |
| 579 dest_buf[i + 1] = (uint8_t)pixel; |
| 580 } |
| 581 } else { |
| 582 for (int i = BytesPerPixel; i < row_size; i++) { |
| 583 dest_buf[i] += dest_buf[i - BytesPerPixel]; |
| 584 } |
| 585 } |
| 586 } |
| 587 static FX_BOOL TIFF_Predictor(uint8_t*& data_buf, |
| 588 FX_DWORD& data_size, |
| 589 int Colors, |
| 590 int BitsPerComponent, |
| 591 int Columns) { |
| 592 int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; |
| 593 if (row_size == 0) |
| 594 return FALSE; |
| 595 const int row_count = (data_size + row_size - 1) / row_size; |
| 596 const int last_row_size = data_size % row_size; |
| 597 for (int row = 0; row < row_count; row++) { |
| 598 uint8_t* scan_line = data_buf + row * row_size; |
| 599 if ((row + 1) * row_size > (int)data_size) { |
| 600 row_size = last_row_size; |
| 601 } |
| 602 TIFF_PredictLine(scan_line, row_size, BitsPerComponent, Colors, Columns); |
| 603 } |
| 604 return TRUE; |
| 605 } |
| 606 class CCodec_FlateScanlineDecoder : public CCodec_ScanlineDecoder { |
| 607 public: |
| 608 CCodec_FlateScanlineDecoder(); |
| 609 ~CCodec_FlateScanlineDecoder(); |
| 610 void Create(const uint8_t* src_buf, |
| 611 FX_DWORD src_size, |
| 612 int width, |
| 613 int height, |
| 614 int nComps, |
| 615 int bpc, |
| 616 int predictor, |
| 617 int Colors, |
| 618 int BitsPerComponent, |
| 619 int Columns); |
| 620 virtual void Destroy() { delete this; } |
| 621 virtual void v_DownScale(int dest_width, int dest_height) {} |
| 622 virtual FX_BOOL v_Rewind(); |
| 623 virtual uint8_t* v_GetNextLine(); |
| 624 virtual FX_DWORD GetSrcOffset(); |
| 625 void* m_pFlate; |
| 626 const uint8_t* m_SrcBuf; |
| 627 FX_DWORD m_SrcSize; |
| 628 uint8_t* m_pScanline; |
| 629 uint8_t* m_pLastLine; |
| 630 uint8_t* m_pPredictBuffer; |
| 631 uint8_t* m_pPredictRaw; |
| 632 int m_Predictor; |
| 633 int m_Colors, m_BitsPerComponent, m_Columns, m_PredictPitch, m_LeftOver; |
| 634 }; |
| 635 CCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder() { |
| 636 m_pFlate = NULL; |
| 637 m_pScanline = NULL; |
| 638 m_pLastLine = NULL; |
| 639 m_pPredictBuffer = NULL; |
| 640 m_pPredictRaw = NULL; |
| 641 m_LeftOver = 0; |
| 642 } |
| 643 CCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder() { |
| 644 if (m_pScanline) { |
| 645 FX_Free(m_pScanline); |
| 646 } |
| 647 if (m_pLastLine) { |
| 648 FX_Free(m_pLastLine); |
| 649 } |
| 650 if (m_pPredictBuffer) { |
| 651 FX_Free(m_pPredictBuffer); |
| 652 } |
| 653 if (m_pPredictRaw) { |
| 654 FX_Free(m_pPredictRaw); |
| 655 } |
| 656 if (m_pFlate) { |
| 657 FPDFAPI_FlateEnd(m_pFlate); |
| 658 } |
| 659 } |
| 660 void CCodec_FlateScanlineDecoder::Create(const uint8_t* src_buf, |
| 661 FX_DWORD src_size, |
| 662 int width, |
| 663 int height, |
| 664 int nComps, |
| 665 int bpc, |
| 666 int predictor, |
| 667 int Colors, |
| 668 int BitsPerComponent, |
| 669 int Columns) { |
| 670 m_SrcBuf = src_buf; |
| 671 m_SrcSize = src_size; |
| 672 m_OutputWidth = m_OrigWidth = width; |
| 673 m_OutputHeight = m_OrigHeight = height; |
| 674 m_nComps = nComps; |
| 675 m_bpc = bpc; |
| 676 m_bColorTransformed = FALSE; |
| 677 m_Pitch = (width * nComps * bpc + 7) / 8; |
| 678 m_pScanline = FX_Alloc(uint8_t, m_Pitch); |
| 679 m_Predictor = 0; |
| 680 if (predictor) { |
| 681 if (predictor >= 10) { |
| 682 m_Predictor = 2; |
| 683 } else if (predictor == 2) { |
| 684 m_Predictor = 1; |
| 685 } |
| 686 if (m_Predictor) { |
| 687 if (BitsPerComponent * Colors * Columns == 0) { |
| 688 BitsPerComponent = m_bpc; |
| 689 Colors = m_nComps; |
| 690 Columns = m_OrigWidth; |
| 691 } |
| 692 m_Colors = Colors; |
| 693 m_BitsPerComponent = BitsPerComponent; |
| 694 m_Columns = Columns; |
| 695 m_PredictPitch = (m_BitsPerComponent * m_Colors * m_Columns + 7) / 8; |
| 696 m_pLastLine = FX_Alloc(uint8_t, m_PredictPitch); |
| 697 m_pPredictRaw = FX_Alloc(uint8_t, m_PredictPitch + 1); |
| 698 m_pPredictBuffer = FX_Alloc(uint8_t, m_PredictPitch); |
| 699 } |
| 700 } |
| 701 } |
| 702 FX_BOOL CCodec_FlateScanlineDecoder::v_Rewind() { |
| 703 if (m_pFlate) { |
| 704 FPDFAPI_FlateEnd(m_pFlate); |
| 705 } |
| 706 m_pFlate = FPDFAPI_FlateInit(my_alloc_func, my_free_func); |
| 707 if (m_pFlate == NULL) { |
| 708 return FALSE; |
| 709 } |
| 710 FPDFAPI_FlateInput(m_pFlate, m_SrcBuf, m_SrcSize); |
| 711 m_LeftOver = 0; |
| 712 return TRUE; |
| 713 } |
| 714 uint8_t* CCodec_FlateScanlineDecoder::v_GetNextLine() { |
| 715 if (m_Predictor) { |
| 716 if (m_Pitch == m_PredictPitch) { |
| 717 if (m_Predictor == 2) { |
| 718 FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); |
| 719 PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine, |
| 720 m_BitsPerComponent, m_Colors, m_Columns); |
| 721 FXSYS_memcpy(m_pLastLine, m_pScanline, m_PredictPitch); |
| 722 } else { |
| 723 FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch); |
| 724 TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps, |
| 725 m_OutputWidth); |
| 726 } |
| 727 } else { |
| 728 int bytes_to_go = m_Pitch; |
| 729 int read_leftover = m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftOver; |
| 730 if (read_leftover) { |
| 731 FXSYS_memcpy(m_pScanline, |
| 732 m_pPredictBuffer + m_PredictPitch - m_LeftOver, |
| 733 read_leftover); |
| 734 m_LeftOver -= read_leftover; |
| 735 bytes_to_go -= read_leftover; |
| 736 } |
| 737 while (bytes_to_go) { |
| 738 if (m_Predictor == 2) { |
| 739 FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1); |
| 740 PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine, |
| 741 m_BitsPerComponent, m_Colors, m_Columns); |
| 742 FXSYS_memcpy(m_pLastLine, m_pPredictBuffer, m_PredictPitch); |
| 743 } else { |
| 744 FPDFAPI_FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPitch); |
| 745 TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPerComponent, |
| 746 m_Colors, m_Columns); |
| 747 } |
| 748 int read_bytes = |
| 749 m_PredictPitch > bytes_to_go ? bytes_to_go : m_PredictPitch; |
| 750 FXSYS_memcpy(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuffer, |
| 751 read_bytes); |
| 752 m_LeftOver += m_PredictPitch - read_bytes; |
| 753 bytes_to_go -= read_bytes; |
| 754 } |
| 755 } |
| 756 } else { |
| 757 FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch); |
| 758 } |
| 759 return m_pScanline; |
| 760 } |
| 761 FX_DWORD CCodec_FlateScanlineDecoder::GetSrcOffset() { |
| 762 return FPDFAPI_FlateGetTotalIn(m_pFlate); |
| 763 } |
| 764 static void FlateUncompress(const uint8_t* src_buf, |
| 765 FX_DWORD src_size, |
| 766 FX_DWORD orig_size, |
| 767 uint8_t*& dest_buf, |
| 768 FX_DWORD& dest_size, |
| 769 FX_DWORD& offset) { |
| 770 const FX_BOOL useOldImpl = src_size < 10240; |
| 771 FX_DWORD guess_size = orig_size ? orig_size : src_size * 2; |
| 772 FX_DWORD alloc_step = |
| 773 orig_size ? 10240 : (src_size < 10240 ? 10240 : src_size); |
| 774 static const FX_DWORD kMaxInitialAllocSize = 10000000; |
| 775 if (guess_size > kMaxInitialAllocSize) { |
| 776 guess_size = kMaxInitialAllocSize; |
| 777 alloc_step = kMaxInitialAllocSize; |
| 778 } |
| 779 FX_DWORD buf_size = guess_size; |
| 780 FX_DWORD last_buf_size = buf_size; |
| 781 void* context = nullptr; |
| 782 |
| 783 uint8_t* guess_buf = FX_Alloc(uint8_t, guess_size + 1); |
| 784 uint8_t* cur_buf = guess_buf; |
| 785 guess_buf[guess_size] = '\0'; |
| 786 context = FPDFAPI_FlateInit(my_alloc_func, my_free_func); |
| 787 if (!context) |
| 788 goto fail; |
| 789 FPDFAPI_FlateInput(context, src_buf, src_size); |
| 790 if (useOldImpl) { |
| 120 while (1) { | 791 while (1) { |
| 121 int index = code - 258; | 792 int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); |
| 122 if (index < 0 || index >= (int)m_nCodes) { | 793 if (ret != Z_OK) |
| 123 break; | 794 break; |
| 124 } | 795 int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); |
| 125 FX_DWORD data = m_CodeArray[index]; | 796 if (avail_buf_size != 0) |
| 126 if (m_StackLen >= sizeof(m_DecodeStack)) { | 797 break; |
| 127 return; | 798 |
| 128 } | 799 // |avail_buf_size| == 0 case. |
| 129 m_DecodeStack[m_StackLen++] = (uint8_t)data; | 800 FX_DWORD old_size = guess_size; |
| 130 code = data >> 16; | 801 guess_size += alloc_step; |
| 131 } | 802 if (guess_size < old_size || guess_size + 1 < guess_size) |
| 132 if (m_StackLen >= sizeof(m_DecodeStack)) { | 803 goto fail; |
| 133 return; | 804 guess_buf = FX_Realloc(uint8_t, guess_buf, guess_size + 1); |
| 134 } | 805 if (!guess_buf) |
| 135 m_DecodeStack[m_StackLen++] = (uint8_t)code; | 806 goto fail; |
| 136 } | 807 guess_buf[guess_size] = '\0'; |
| 137 int CLZWDecoder::Decode(uint8_t* dest_buf, FX_DWORD& dest_size, const uint8_t* s
rc_buf, FX_DWORD& src_size, FX_BOOL bEarlyChange) | 808 cur_buf = guess_buf + old_size; |
| 138 { | 809 buf_size = guess_size - old_size; |
| 139 m_CodeLen = 9; | 810 } |
| 140 m_InPos = 0; | 811 dest_size = FPDFAPI_FlateGetTotalOut(context); |
| 141 m_OutPos = 0; | 812 offset = FPDFAPI_FlateGetTotalIn(context); |
| 142 m_pInput = src_buf; | 813 if (guess_size / 2 > dest_size) { |
| 143 m_pOutput = dest_buf; | 814 guess_buf = FX_Realloc(uint8_t, guess_buf, dest_size + 1); |
| 144 m_Early = bEarlyChange ? 1 : 0; | 815 if (!guess_buf) |
| 145 m_nCodes = 0; | 816 goto fail; |
| 146 FX_DWORD old_code = (FX_DWORD) - 1; | 817 guess_size = dest_size; |
| 147 uint8_t last_char; | 818 guess_buf[guess_size] = '\0'; |
| 819 } |
| 820 dest_buf = guess_buf; |
| 821 } else { |
| 822 CFX_ArrayTemplate<uint8_t*> result_tmp_bufs; |
| 148 while (1) { | 823 while (1) { |
| 149 if (m_InPos + m_CodeLen > src_size * 8) { | 824 int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); |
| 150 break; | 825 int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); |
| 151 } | 826 if (ret != Z_OK) { |
| 152 int byte_pos = m_InPos / 8; | 827 last_buf_size = buf_size - avail_buf_size; |
| 153 int bit_pos = m_InPos % 8, bit_left = m_CodeLen; | 828 result_tmp_bufs.Add(cur_buf); |
| 154 FX_DWORD code = 0; | 829 break; |
| 155 if (bit_pos) { | 830 } |
| 156 bit_left -= 8 - bit_pos; | 831 if (avail_buf_size != 0) { |
| 157 code = (m_pInput[byte_pos++] & ((1 << (8 - bit_pos)) - 1)) << bit_le
ft; | 832 last_buf_size = buf_size - avail_buf_size; |
| 158 } | 833 result_tmp_bufs.Add(cur_buf); |
| 159 if (bit_left < 8) { | 834 break; |
| 160 code |= m_pInput[byte_pos] >> (8 - bit_left); | 835 } |
| 161 } else { | 836 |
| 162 bit_left -= 8; | 837 // |avail_buf_size| == 0 case. |
| 163 code |= m_pInput[byte_pos++] << bit_left; | 838 result_tmp_bufs.Add(cur_buf); |
| 164 if (bit_left) { | 839 cur_buf = FX_Alloc(uint8_t, buf_size + 1); |
| 165 code |= m_pInput[byte_pos] >> (8 - bit_left); | 840 cur_buf[buf_size] = '\0'; |
| 166 } | 841 } |
| 167 } | 842 dest_size = FPDFAPI_FlateGetTotalOut(context); |
| 168 m_InPos += m_CodeLen; | 843 offset = FPDFAPI_FlateGetTotalIn(context); |
| 169 if (code < 256) { | 844 if (result_tmp_bufs.GetSize() == 1) { |
| 170 if (m_OutPos == dest_size) { | 845 dest_buf = result_tmp_bufs[0]; |
| 171 return -5; | |
| 172 } | |
| 173 if (m_pOutput) { | |
| 174 m_pOutput[m_OutPos] = (uint8_t)code; | |
| 175 } | |
| 176 m_OutPos ++; | |
| 177 last_char = (uint8_t)code; | |
| 178 if (old_code != (FX_DWORD) - 1) { | |
| 179 AddCode(old_code, last_char); | |
| 180 } | |
| 181 old_code = code; | |
| 182 } else if (code == 256) { | |
| 183 m_CodeLen = 9; | |
| 184 m_nCodes = 0; | |
| 185 old_code = (FX_DWORD) - 1; | |
| 186 } else if (code == 257) { | |
| 187 break; | |
| 188 } else { | |
| 189 if (old_code == (FX_DWORD) - 1) { | |
| 190 return 2; | |
| 191 } | |
| 192 m_StackLen = 0; | |
| 193 if (code >= m_nCodes + 258) { | |
| 194 if (m_StackLen < sizeof(m_DecodeStack)) { | |
| 195 m_DecodeStack[m_StackLen++] = last_char; | |
| 196 } | |
| 197 DecodeString(old_code); | |
| 198 } else { | |
| 199 DecodeString(code); | |
| 200 } | |
| 201 if (m_OutPos + m_StackLen > dest_size) { | |
| 202 return -5; | |
| 203 } | |
| 204 if (m_pOutput) { | |
| 205 for (FX_DWORD i = 0; i < m_StackLen; i ++) { | |
| 206 m_pOutput[m_OutPos + i] = m_DecodeStack[m_StackLen - i - 1]; | |
| 207 } | |
| 208 } | |
| 209 m_OutPos += m_StackLen; | |
| 210 last_char = m_DecodeStack[m_StackLen - 1]; | |
| 211 if (old_code < 256) { | |
| 212 AddCode(old_code, last_char); | |
| 213 } else if (old_code - 258 >= m_nCodes) { | |
| 214 dest_size = m_OutPos; | |
| 215 src_size = (m_InPos + 7) / 8; | |
| 216 return 0; | |
| 217 } else { | |
| 218 AddCode(old_code, last_char); | |
| 219 } | |
| 220 old_code = code; | |
| 221 } | |
| 222 } | |
| 223 dest_size = m_OutPos; | |
| 224 src_size = (m_InPos + 7) / 8; | |
| 225 return 0; | |
| 226 } | |
| 227 static uint8_t PaethPredictor(int a, int b, int c) | |
| 228 { | |
| 229 int p = a + b - c; | |
| 230 int pa = FXSYS_abs(p - a); | |
| 231 int pb = FXSYS_abs(p - b); | |
| 232 int pc = FXSYS_abs(p - c); | |
| 233 if (pa <= pb && pa <= pc) { | |
| 234 return (uint8_t)a; | |
| 235 } | |
| 236 if (pb <= pc) { | |
| 237 return (uint8_t)b; | |
| 238 } | |
| 239 return (uint8_t)c; | |
| 240 } | |
| 241 static FX_BOOL PNG_PredictorEncode(uint8_t*& data_buf, FX_DWORD& data_size, | |
| 242 int predictor, int Colors, | |
| 243 int BitsPerComponent, int Columns) | |
| 244 { | |
| 245 const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8; | |
| 246 const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; | |
| 247 if (row_size <= 0) | |
| 248 return FALSE; | |
| 249 const int row_count = (data_size + row_size - 1) / row_size; | |
| 250 const int last_row_size = data_size % row_size; | |
| 251 uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size + 1, row_count); | |
| 252 int byte_cnt = 0; | |
| 253 uint8_t* pSrcData = data_buf; | |
| 254 uint8_t* pDestData = dest_buf; | |
| 255 for (int row = 0; row < row_count; row++) { | |
| 256 if (predictor == 10) { | |
| 257 pDestData[0] = 0; | |
| 258 int move_size = row_size; | |
| 259 if (move_size * (row + 1) > (int)data_size) { | |
| 260 move_size = data_size - (move_size * row); | |
| 261 } | |
| 262 FXSYS_memmove(pDestData + 1, pSrcData, move_size); | |
| 263 pDestData += (move_size + 1); | |
| 264 pSrcData += move_size; | |
| 265 byte_cnt += move_size; | |
| 266 continue; | |
| 267 } | |
| 268 for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte++)
{ | |
| 269 switch (predictor) { | |
| 270 case 11: { | |
| 271 pDestData[0] = 1; | |
| 272 uint8_t left = 0; | |
| 273 if (byte >= BytesPerPixel) { | |
| 274 left = pSrcData[byte - BytesPerPixel]; | |
| 275 } | |
| 276 pDestData[byte + 1] = pSrcData[byte] - left; | |
| 277 } | |
| 278 break; | |
| 279 case 12: { | |
| 280 pDestData[0] = 2; | |
| 281 uint8_t up = 0; | |
| 282 if (row) { | |
| 283 up = pSrcData[byte - row_size]; | |
| 284 } | |
| 285 pDestData[byte + 1] = pSrcData[byte] - up; | |
| 286 } | |
| 287 break; | |
| 288 case 13: { | |
| 289 pDestData[0] = 3; | |
| 290 uint8_t left = 0; | |
| 291 if (byte >= BytesPerPixel) { | |
| 292 left = pSrcData[byte - BytesPerPixel]; | |
| 293 } | |
| 294 uint8_t up = 0; | |
| 295 if (row) { | |
| 296 up = pSrcData[byte - row_size]; | |
| 297 } | |
| 298 pDestData[byte + 1] = pSrcData[byte] - (left + up) / 2; | |
| 299 } | |
| 300 break; | |
| 301 case 14: { | |
| 302 pDestData[0] = 4; | |
| 303 uint8_t left = 0; | |
| 304 if (byte >= BytesPerPixel) { | |
| 305 left = pSrcData[byte - BytesPerPixel]; | |
| 306 } | |
| 307 uint8_t up = 0; | |
| 308 if (row) { | |
| 309 up = pSrcData[byte - row_size]; | |
| 310 } | |
| 311 uint8_t upper_left = 0; | |
| 312 if (byte >= BytesPerPixel && row) { | |
| 313 upper_left = pSrcData[byte - row_size - BytesPerPixe
l]; | |
| 314 } | |
| 315 pDestData[byte + 1] = pSrcData[byte] - PaethPredictor(le
ft, up, upper_left); | |
| 316 } | |
| 317 break; | |
| 318 default: { | |
| 319 pDestData[byte + 1] = pSrcData[byte]; | |
| 320 } | |
| 321 break; | |
| 322 } | |
| 323 byte_cnt++; | |
| 324 } | |
| 325 pDestData += (row_size + 1); | |
| 326 pSrcData += row_size; | |
| 327 } | |
| 328 FX_Free(data_buf); | |
| 329 data_buf = dest_buf; | |
| 330 data_size = (row_size + 1) * row_count - (last_row_size > 0 ? (row_size - la
st_row_size) : 0); | |
| 331 return TRUE; | |
| 332 } | |
| 333 static void PNG_PredictLine(uint8_t* pDestData, const uint8_t* pSrcData, const u
int8_t* pLastLine, | |
| 334 int bpc, int nColors, int nPixels) | |
| 335 { | |
| 336 int row_size = (nPixels * bpc * nColors + 7) / 8; | |
| 337 int BytesPerPixel = (bpc * nColors + 7) / 8; | |
| 338 uint8_t tag = pSrcData[0]; | |
| 339 if (tag == 0) { | |
| 340 FXSYS_memmove(pDestData, pSrcData + 1, row_size); | |
| 341 return; | |
| 342 } | |
| 343 for (int byte = 0; byte < row_size; byte ++) { | |
| 344 uint8_t raw_byte = pSrcData[byte + 1]; | |
| 345 switch (tag) { | |
| 346 case 1: { | |
| 347 uint8_t left = 0; | |
| 348 if (byte >= BytesPerPixel) { | |
| 349 left = pDestData[byte - BytesPerPixel]; | |
| 350 } | |
| 351 pDestData[byte] = raw_byte + left; | |
| 352 break; | |
| 353 } | |
| 354 case 2: { | |
| 355 uint8_t up = 0; | |
| 356 if (pLastLine) { | |
| 357 up = pLastLine[byte]; | |
| 358 } | |
| 359 pDestData[byte] = raw_byte + up; | |
| 360 break; | |
| 361 } | |
| 362 case 3: { | |
| 363 uint8_t left = 0; | |
| 364 if (byte >= BytesPerPixel) { | |
| 365 left = pDestData[byte - BytesPerPixel]; | |
| 366 } | |
| 367 uint8_t up = 0; | |
| 368 if (pLastLine) { | |
| 369 up = pLastLine[byte]; | |
| 370 } | |
| 371 pDestData[byte] = raw_byte + (up + left) / 2; | |
| 372 break; | |
| 373 } | |
| 374 case 4: { | |
| 375 uint8_t left = 0; | |
| 376 if (byte >= BytesPerPixel) { | |
| 377 left = pDestData[byte - BytesPerPixel]; | |
| 378 } | |
| 379 uint8_t up = 0; | |
| 380 if (pLastLine) { | |
| 381 up = pLastLine[byte]; | |
| 382 } | |
| 383 uint8_t upper_left = 0; | |
| 384 if (byte >= BytesPerPixel && pLastLine) { | |
| 385 upper_left = pLastLine[byte - BytesPerPixel]; | |
| 386 } | |
| 387 pDestData[byte] = raw_byte + PaethPredictor(left, up, upper_
left); | |
| 388 break; | |
| 389 } | |
| 390 default: | |
| 391 pDestData[byte] = raw_byte; | |
| 392 break; | |
| 393 } | |
| 394 } | |
| 395 } | |
| 396 static FX_BOOL PNG_Predictor(uint8_t*& data_buf, FX_DWORD& data_size, | |
| 397 int Colors, int BitsPerComponent, int Columns) | |
| 398 { | |
| 399 const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8; | |
| 400 const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; | |
| 401 if (row_size <= 0) | |
| 402 return FALSE; | |
| 403 const int row_count = (data_size + row_size) / (row_size + 1); | |
| 404 const int last_row_size = data_size % (row_size + 1); | |
| 405 uint8_t* dest_buf = FX_Alloc2D(uint8_t, row_size, row_count); | |
| 406 int byte_cnt = 0; | |
| 407 uint8_t* pSrcData = data_buf; | |
| 408 uint8_t* pDestData = dest_buf; | |
| 409 for (int row = 0; row < row_count; row ++) { | |
| 410 uint8_t tag = pSrcData[0]; | |
| 411 byte_cnt++; | |
| 412 if (tag == 0) { | |
| 413 int move_size = row_size; | |
| 414 if ((row + 1) * (move_size + 1) > (int)data_size) { | |
| 415 move_size = last_row_size - 1; | |
| 416 } | |
| 417 FXSYS_memmove(pDestData, pSrcData + 1, move_size); | |
| 418 pSrcData += move_size + 1; | |
| 419 pDestData += move_size; | |
| 420 byte_cnt += move_size; | |
| 421 continue; | |
| 422 } | |
| 423 for (int byte = 0; byte < row_size && byte_cnt < (int)data_size; byte ++
) { | |
| 424 uint8_t raw_byte = pSrcData[byte + 1]; | |
| 425 switch (tag) { | |
| 426 case 1: { | |
| 427 uint8_t left = 0; | |
| 428 if (byte >= BytesPerPixel) { | |
| 429 left = pDestData[byte - BytesPerPixel]; | |
| 430 } | |
| 431 pDestData[byte] = raw_byte + left; | |
| 432 break; | |
| 433 } | |
| 434 case 2: { | |
| 435 uint8_t up = 0; | |
| 436 if (row) { | |
| 437 up = pDestData[byte - row_size]; | |
| 438 } | |
| 439 pDestData[byte] = raw_byte + up; | |
| 440 break; | |
| 441 } | |
| 442 case 3: { | |
| 443 uint8_t left = 0; | |
| 444 if (byte >= BytesPerPixel) { | |
| 445 left = pDestData[byte - BytesPerPixel]; | |
| 446 } | |
| 447 uint8_t up = 0; | |
| 448 if (row) { | |
| 449 up = pDestData[byte - row_size]; | |
| 450 } | |
| 451 pDestData[byte] = raw_byte + (up + left) / 2; | |
| 452 break; | |
| 453 } | |
| 454 case 4: { | |
| 455 uint8_t left = 0; | |
| 456 if (byte >= BytesPerPixel) { | |
| 457 left = pDestData[byte - BytesPerPixel]; | |
| 458 } | |
| 459 uint8_t up = 0; | |
| 460 if (row) { | |
| 461 up = pDestData[byte - row_size]; | |
| 462 } | |
| 463 uint8_t upper_left = 0; | |
| 464 if (byte >= BytesPerPixel && row) { | |
| 465 upper_left = pDestData[byte - row_size - BytesPerPix
el]; | |
| 466 } | |
| 467 pDestData[byte] = raw_byte + PaethPredictor(left, up, up
per_left); | |
| 468 break; | |
| 469 } | |
| 470 default: | |
| 471 pDestData[byte] = raw_byte; | |
| 472 break; | |
| 473 } | |
| 474 byte_cnt++; | |
| 475 } | |
| 476 pSrcData += row_size + 1; | |
| 477 pDestData += row_size; | |
| 478 } | |
| 479 FX_Free(data_buf); | |
| 480 data_buf = dest_buf; | |
| 481 data_size = row_size * row_count - (last_row_size > 0 ? (row_size + 1 - last
_row_size) : 0); | |
| 482 return TRUE; | |
| 483 } | |
| 484 static void TIFF_PredictorEncodeLine(uint8_t* dest_buf, int row_size, int BitsPe
rComponent, int Colors, int Columns) | |
| 485 { | |
| 486 int BytesPerPixel = BitsPerComponent * Colors / 8; | |
| 487 if (BitsPerComponent < 8) { | |
| 488 uint8_t mask = 0x01; | |
| 489 if (BitsPerComponent == 2) { | |
| 490 mask = 0x03; | |
| 491 } else if (BitsPerComponent == 4) { | |
| 492 mask = 0x0F; | |
| 493 } | |
| 494 int row_bits = Colors * BitsPerComponent * Columns; | |
| 495 for (int i = row_bits - BitsPerComponent; i >= BitsPerComponent; i -= Bi
tsPerComponent) { | |
| 496 int col = i % 8; | |
| 497 int index = i / 8; | |
| 498 int col_pre = (col == 0) ? (8 - BitsPerComponent) : (col - BitsPerCo
mponent); | |
| 499 int index_pre = (col == 0) ? (index - 1) : index; | |
| 500 uint8_t cur = (dest_buf[index] >> (8 - col - BitsPerComponent)) & ma
sk; | |
| 501 uint8_t left = (dest_buf[index_pre] >> (8 - col_pre - BitsPerCompone
nt)) & mask; | |
| 502 cur -= left; | |
| 503 cur &= mask; | |
| 504 cur <<= (8 - col - BitsPerComponent); | |
| 505 dest_buf[index] &= ~(mask << ((8 - col - BitsPerComponent))); | |
| 506 dest_buf[index] |= cur; | |
| 507 } | |
| 508 } else if (BitsPerComponent == 8) { | |
| 509 for (int i = row_size - 1; i >= BytesPerPixel; i--) { | |
| 510 dest_buf[i] -= dest_buf[i - BytesPerPixel]; | |
| 511 } | |
| 512 } else { | 846 } else { |
| 513 for (int i = row_size - BytesPerPixel; i >= BytesPerPixel; i -= BytesPer
Pixel) { | 847 uint8_t* result_buf = FX_Alloc(uint8_t, dest_size); |
| 514 FX_WORD pixel = (dest_buf[i] << 8) | dest_buf[i + 1]; | 848 FX_DWORD result_pos = 0; |
| 515 pixel -= (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - BytesPerP
ixel + 1]; | 849 for (int32_t i = 0; i < result_tmp_bufs.GetSize(); i++) { |
| 516 dest_buf[i] = pixel >> 8; | 850 uint8_t* tmp_buf = result_tmp_bufs[i]; |
| 517 dest_buf[i + 1] = (uint8_t)pixel; | 851 FX_DWORD tmp_buf_size = buf_size; |
| 518 } | 852 if (i == result_tmp_bufs.GetSize() - 1) { |
| 519 } | 853 tmp_buf_size = last_buf_size; |
| 520 } | 854 } |
| 521 static FX_BOOL TIFF_PredictorEncode(uint8_t*& data_buf, FX_DWORD& data_size, | 855 FXSYS_memcpy(result_buf + result_pos, tmp_buf, tmp_buf_size); |
| 522 int Colors, int BitsPerComponent, int Column
s) | 856 result_pos += tmp_buf_size; |
| 523 { | 857 FX_Free(result_tmp_bufs[i]); |
| 524 int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; | 858 } |
| 525 if (row_size == 0) | 859 dest_buf = result_buf; |
| 526 return FALSE; | 860 } |
| 527 const int row_count = (data_size + row_size - 1) / row_size; | 861 } |
| 528 const int last_row_size = data_size % row_size; | 862 FPDFAPI_FlateEnd(context); |
| 529 for (int row = 0; row < row_count; row++) { | 863 return; |
| 530 uint8_t* scan_line = data_buf + row * row_size; | |
| 531 if ((row + 1) * row_size > (int)data_size) { | |
| 532 row_size = last_row_size; | |
| 533 } | |
| 534 TIFF_PredictorEncodeLine(scan_line, row_size, BitsPerComponent, Colors,
Columns); | |
| 535 } | |
| 536 return TRUE; | |
| 537 } | |
| 538 static void TIFF_PredictLine(uint8_t* dest_buf, int row_size, int BitsPerCompone
nt, int Colors, int Columns) | |
| 539 { | |
| 540 if (BitsPerComponent == 1) { | |
| 541 int row_bits = FX_MIN(BitsPerComponent * Colors * Columns, row_size * 8)
; | |
| 542 int index_pre = 0; | |
| 543 int col_pre = 0; | |
| 544 for(int i = 1; i < row_bits; i ++) { | |
| 545 int col = i % 8; | |
| 546 int index = i / 8; | |
| 547 if( ((dest_buf[index] >> (7 - col)) & 1) ^ ((dest_buf[index_pre] >>
(7 - col_pre)) & 1) ) { | |
| 548 dest_buf[index] |= 1 << (7 - col); | |
| 549 } else { | |
| 550 dest_buf[index] &= ~(1 << (7 - col)); | |
| 551 } | |
| 552 index_pre = index; | |
| 553 col_pre = col; | |
| 554 } | |
| 555 return; | |
| 556 } | |
| 557 int BytesPerPixel = BitsPerComponent * Colors / 8; | |
| 558 if (BitsPerComponent == 16) { | |
| 559 for (int i = BytesPerPixel; i < row_size; i += 2) { | |
| 560 FX_WORD pixel = (dest_buf[i - BytesPerPixel] << 8) | dest_buf[i - By
tesPerPixel + 1]; | |
| 561 pixel += (dest_buf[i] << 8) | dest_buf[i + 1]; | |
| 562 dest_buf[i] = pixel >> 8; | |
| 563 dest_buf[i + 1] = (uint8_t)pixel; | |
| 564 } | |
| 565 } else { | |
| 566 for (int i = BytesPerPixel; i < row_size; i ++) { | |
| 567 dest_buf[i] += dest_buf[i - BytesPerPixel]; | |
| 568 } | |
| 569 } | |
| 570 } | |
| 571 static FX_BOOL TIFF_Predictor(uint8_t*& data_buf, FX_DWORD& data_size, | |
| 572 int Colors, int BitsPerComponent, int Columns) | |
| 573 { | |
| 574 int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; | |
| 575 if (row_size == 0) | |
| 576 return FALSE; | |
| 577 const int row_count = (data_size + row_size - 1) / row_size; | |
| 578 const int last_row_size = data_size % row_size; | |
| 579 for (int row = 0; row < row_count; row ++) { | |
| 580 uint8_t* scan_line = data_buf + row * row_size; | |
| 581 if ((row + 1) * row_size > (int)data_size) { | |
| 582 row_size = last_row_size; | |
| 583 } | |
| 584 TIFF_PredictLine(scan_line, row_size, BitsPerComponent, Colors, Columns)
; | |
| 585 } | |
| 586 return TRUE; | |
| 587 } | |
| 588 class CCodec_FlateScanlineDecoder : public CCodec_ScanlineDecoder | |
| 589 { | |
| 590 public: | |
| 591 CCodec_FlateScanlineDecoder(); | |
| 592 ~CCodec_FlateScanlineDecoder(); | |
| 593 void Create(const uint8_t* src_buf, FX_DWORD src_size, int width, int height
, int nComps, int bpc, | |
| 594 int predictor, int Colors, int BitsPerComponent, int Columns); | |
| 595 virtual void Destroy() | |
| 596 { | |
| 597 delete this; | |
| 598 } | |
| 599 virtual void v_DownScale(int dest_width, int dest_height) {} | |
| 600 virtual FX_BOOL v_Rewind(); | |
| 601 virtual uint8_t* v_GetNextLine(); | |
| 602 virtual FX_DWORD GetSrcOffset(); | |
| 603 void* m_pFlate; | |
| 604 const uint8_t* m_SrcBuf; | |
| 605 FX_DWORD m_SrcSize; | |
| 606 uint8_t* m_pScanline; | |
| 607 uint8_t* m_pLastLine; | |
| 608 uint8_t* m_pPredictBuffer; | |
| 609 uint8_t* m_pPredictRaw; | |
| 610 int m_Predictor; | |
| 611 int m_Colors, m_BitsPerComponent, m_Columns,
m_PredictPitch, m_LeftOver; | |
| 612 }; | |
| 613 CCodec_FlateScanlineDecoder::CCodec_FlateScanlineDecoder() | |
| 614 { | |
| 615 m_pFlate = NULL; | |
| 616 m_pScanline = NULL; | |
| 617 m_pLastLine = NULL; | |
| 618 m_pPredictBuffer = NULL; | |
| 619 m_pPredictRaw = NULL; | |
| 620 m_LeftOver = 0; | |
| 621 } | |
| 622 CCodec_FlateScanlineDecoder::~CCodec_FlateScanlineDecoder() | |
| 623 { | |
| 624 if (m_pScanline) { | |
| 625 FX_Free(m_pScanline); | |
| 626 } | |
| 627 if (m_pLastLine) { | |
| 628 FX_Free(m_pLastLine); | |
| 629 } | |
| 630 if (m_pPredictBuffer) { | |
| 631 FX_Free(m_pPredictBuffer); | |
| 632 } | |
| 633 if (m_pPredictRaw) { | |
| 634 FX_Free(m_pPredictRaw); | |
| 635 } | |
| 636 if (m_pFlate) { | |
| 637 FPDFAPI_FlateEnd(m_pFlate); | |
| 638 } | |
| 639 } | |
| 640 void CCodec_FlateScanlineDecoder::Create(const uint8_t* src_buf, FX_DWORD src_si
ze, int width, int height, | |
| 641 int nComps, int bpc, int predictor, int Colors, int BitsPerComponent, in
t Columns) | |
| 642 { | |
| 643 m_SrcBuf = src_buf; | |
| 644 m_SrcSize = src_size; | |
| 645 m_OutputWidth = m_OrigWidth = width; | |
| 646 m_OutputHeight = m_OrigHeight = height; | |
| 647 m_nComps = nComps; | |
| 648 m_bpc = bpc; | |
| 649 m_bColorTransformed = FALSE; | |
| 650 m_Pitch = (width * nComps * bpc + 7) / 8; | |
| 651 m_pScanline = FX_Alloc(uint8_t, m_Pitch); | |
| 652 m_Predictor = 0; | |
| 653 if (predictor) { | |
| 654 if (predictor >= 10) { | |
| 655 m_Predictor = 2; | |
| 656 } else if (predictor == 2) { | |
| 657 m_Predictor = 1; | |
| 658 } | |
| 659 if (m_Predictor) { | |
| 660 if (BitsPerComponent * Colors * Columns == 0) { | |
| 661 BitsPerComponent = m_bpc; | |
| 662 Colors = m_nComps; | |
| 663 Columns = m_OrigWidth; | |
| 664 } | |
| 665 m_Colors = Colors; | |
| 666 m_BitsPerComponent = BitsPerComponent; | |
| 667 m_Columns = Columns; | |
| 668 m_PredictPitch = (m_BitsPerComponent * m_Colors * m_Columns + 7) / 8
; | |
| 669 m_pLastLine = FX_Alloc(uint8_t, m_PredictPitch); | |
| 670 m_pPredictRaw = FX_Alloc(uint8_t, m_PredictPitch + 1); | |
| 671 m_pPredictBuffer = FX_Alloc(uint8_t, m_PredictPitch); | |
| 672 } | |
| 673 } | |
| 674 } | |
| 675 FX_BOOL CCodec_FlateScanlineDecoder::v_Rewind() | |
| 676 { | |
| 677 if (m_pFlate) { | |
| 678 FPDFAPI_FlateEnd(m_pFlate); | |
| 679 } | |
| 680 m_pFlate = FPDFAPI_FlateInit(my_alloc_func, my_free_func); | |
| 681 if (m_pFlate == NULL) { | |
| 682 return FALSE; | |
| 683 } | |
| 684 FPDFAPI_FlateInput(m_pFlate, m_SrcBuf, m_SrcSize); | |
| 685 m_LeftOver = 0; | |
| 686 return TRUE; | |
| 687 } | |
| 688 uint8_t* CCodec_FlateScanlineDecoder::v_GetNextLine() | |
| 689 { | |
| 690 if (m_Predictor) { | |
| 691 if (m_Pitch == m_PredictPitch) { | |
| 692 if (m_Predictor == 2) { | |
| 693 FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch + 1)
; | |
| 694 PNG_PredictLine(m_pScanline, m_pPredictRaw, m_pLastLine, m_BitsP
erComponent, m_Colors, m_Columns); | |
| 695 FXSYS_memcpy(m_pLastLine, m_pScanline, m_PredictPitch); | |
| 696 } else { | |
| 697 FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch); | |
| 698 TIFF_PredictLine(m_pScanline, m_PredictPitch, m_bpc, m_nComps, m
_OutputWidth); | |
| 699 } | |
| 700 } else { | |
| 701 int bytes_to_go = m_Pitch; | |
| 702 int read_leftover = m_LeftOver > bytes_to_go ? bytes_to_go : m_LeftO
ver; | |
| 703 if (read_leftover) { | |
| 704 FXSYS_memcpy(m_pScanline, m_pPredictBuffer + m_PredictPitch - m_
LeftOver, read_leftover); | |
| 705 m_LeftOver -= read_leftover; | |
| 706 bytes_to_go -= read_leftover; | |
| 707 } | |
| 708 while (bytes_to_go) { | |
| 709 if (m_Predictor == 2) { | |
| 710 FPDFAPI_FlateOutput(m_pFlate, m_pPredictRaw, m_PredictPitch
+ 1); | |
| 711 PNG_PredictLine(m_pPredictBuffer, m_pPredictRaw, m_pLastLine
, m_BitsPerComponent, m_Colors, m_Columns); | |
| 712 FXSYS_memcpy(m_pLastLine, m_pPredictBuffer, m_PredictPitch); | |
| 713 } else { | |
| 714 FPDFAPI_FlateOutput(m_pFlate, m_pPredictBuffer, m_PredictPit
ch); | |
| 715 TIFF_PredictLine(m_pPredictBuffer, m_PredictPitch, m_BitsPer
Component, m_Colors, m_Columns); | |
| 716 } | |
| 717 int read_bytes = m_PredictPitch > bytes_to_go ? bytes_to_go : m_
PredictPitch; | |
| 718 FXSYS_memcpy(m_pScanline + m_Pitch - bytes_to_go, m_pPredictBuff
er, read_bytes); | |
| 719 m_LeftOver += m_PredictPitch - read_bytes; | |
| 720 bytes_to_go -= read_bytes; | |
| 721 } | |
| 722 } | |
| 723 } else { | |
| 724 FPDFAPI_FlateOutput(m_pFlate, m_pScanline, m_Pitch); | |
| 725 } | |
| 726 return m_pScanline; | |
| 727 } | |
| 728 FX_DWORD CCodec_FlateScanlineDecoder::GetSrcOffset() | |
| 729 { | |
| 730 return FPDFAPI_FlateGetTotalIn(m_pFlate); | |
| 731 } | |
| 732 static void FlateUncompress(const uint8_t* src_buf, FX_DWORD src_size, FX_DWORD
orig_size, | |
| 733 uint8_t*& dest_buf, FX_DWORD& dest_size, FX_DWORD& o
ffset) | |
| 734 { | |
| 735 const FX_BOOL useOldImpl = src_size < 10240; | |
| 736 FX_DWORD guess_size = orig_size ? orig_size : src_size * 2; | |
| 737 FX_DWORD alloc_step = orig_size ? 10240 : (src_size < 10240 ? 10240 : src_si
ze); | |
| 738 static const FX_DWORD kMaxInitialAllocSize = 10000000; | |
| 739 if (guess_size > kMaxInitialAllocSize) { | |
| 740 guess_size = kMaxInitialAllocSize; | |
| 741 alloc_step = kMaxInitialAllocSize; | |
| 742 } | |
| 743 FX_DWORD buf_size = guess_size; | |
| 744 FX_DWORD last_buf_size = buf_size; | |
| 745 void* context = nullptr; | |
| 746 | |
| 747 uint8_t* guess_buf = FX_Alloc(uint8_t, guess_size + 1); | |
| 748 uint8_t* cur_buf = guess_buf; | |
| 749 guess_buf[guess_size] = '\0'; | |
| 750 context = FPDFAPI_FlateInit(my_alloc_func, my_free_func); | |
| 751 if (!context) | |
| 752 goto fail; | |
| 753 FPDFAPI_FlateInput(context, src_buf, src_size); | |
| 754 if (useOldImpl) { | |
| 755 while (1) { | |
| 756 int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); | |
| 757 if (ret != Z_OK) | |
| 758 break; | |
| 759 int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); | |
| 760 if (avail_buf_size != 0) | |
| 761 break; | |
| 762 | |
| 763 // |avail_buf_size| == 0 case. | |
| 764 FX_DWORD old_size = guess_size; | |
| 765 guess_size += alloc_step; | |
| 766 if (guess_size < old_size || guess_size + 1 < guess_size) | |
| 767 goto fail; | |
| 768 guess_buf = FX_Realloc(uint8_t, guess_buf, guess_size + 1); | |
| 769 if (!guess_buf) | |
| 770 goto fail; | |
| 771 guess_buf[guess_size] = '\0'; | |
| 772 cur_buf = guess_buf + old_size; | |
| 773 buf_size = guess_size - old_size; | |
| 774 } | |
| 775 dest_size = FPDFAPI_FlateGetTotalOut(context); | |
| 776 offset = FPDFAPI_FlateGetTotalIn(context); | |
| 777 if (guess_size / 2 > dest_size) { | |
| 778 guess_buf = FX_Realloc(uint8_t, guess_buf, dest_size + 1); | |
| 779 if (!guess_buf) | |
| 780 goto fail; | |
| 781 guess_size = dest_size; | |
| 782 guess_buf[guess_size] = '\0'; | |
| 783 } | |
| 784 dest_buf = guess_buf; | |
| 785 } else { | |
| 786 CFX_ArrayTemplate<uint8_t*> result_tmp_bufs; | |
| 787 while (1) { | |
| 788 int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); | |
| 789 int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); | |
| 790 if (ret != Z_OK) { | |
| 791 last_buf_size = buf_size - avail_buf_size; | |
| 792 result_tmp_bufs.Add(cur_buf); | |
| 793 break; | |
| 794 } | |
| 795 if (avail_buf_size != 0) { | |
| 796 last_buf_size = buf_size - avail_buf_size; | |
| 797 result_tmp_bufs.Add(cur_buf); | |
| 798 break; | |
| 799 } | |
| 800 | |
| 801 // |avail_buf_size| == 0 case. | |
| 802 result_tmp_bufs.Add(cur_buf); | |
| 803 cur_buf = FX_Alloc(uint8_t, buf_size + 1); | |
| 804 cur_buf[buf_size] = '\0'; | |
| 805 } | |
| 806 dest_size = FPDFAPI_FlateGetTotalOut(context); | |
| 807 offset = FPDFAPI_FlateGetTotalIn(context); | |
| 808 if (result_tmp_bufs.GetSize() == 1) { | |
| 809 dest_buf = result_tmp_bufs[0]; | |
| 810 } else { | |
| 811 uint8_t* result_buf = FX_Alloc(uint8_t, dest_size); | |
| 812 FX_DWORD result_pos = 0; | |
| 813 for (int32_t i = 0; i < result_tmp_bufs.GetSize(); i++) { | |
| 814 uint8_t* tmp_buf = result_tmp_bufs[i]; | |
| 815 FX_DWORD tmp_buf_size = buf_size; | |
| 816 if (i == result_tmp_bufs.GetSize() - 1) { | |
| 817 tmp_buf_size = last_buf_size; | |
| 818 } | |
| 819 FXSYS_memcpy(result_buf + result_pos, tmp_buf, tmp_buf_size); | |
| 820 result_pos += tmp_buf_size; | |
| 821 FX_Free(result_tmp_bufs[i]); | |
| 822 } | |
| 823 dest_buf = result_buf; | |
| 824 } | |
| 825 } | |
| 826 FPDFAPI_FlateEnd(context); | |
| 827 return; | |
| 828 | 864 |
| 829 fail: | 865 fail: |
| 830 FX_Free(guess_buf); | 866 FX_Free(guess_buf); |
| 831 dest_buf = nullptr; | 867 dest_buf = nullptr; |
| 832 dest_size = 0; | 868 dest_size = 0; |
| 833 return; | 869 return; |
| 834 } | 870 } |
| 835 ICodec_ScanlineDecoder*»CCodec_FlateModule::CreateDecoder(const uint8_t* src_buf
, FX_DWORD src_size, int width, int height, | 871 ICodec_ScanlineDecoder* CCodec_FlateModule::CreateDecoder( |
| 836 int nComps, int bpc, int predictor, int Colors, int BitsPerComponent, in
t Columns) | 872 const uint8_t* src_buf, |
| 837 { | 873 FX_DWORD src_size, |
| 838 CCodec_FlateScanlineDecoder* pDecoder = new CCodec_FlateScanlineDecoder; | 874 int width, |
| 839 pDecoder->Create(src_buf, src_size, width, height, nComps, bpc, predictor, C
olors, BitsPerComponent, Columns); | 875 int height, |
| 840 return pDecoder; | 876 int nComps, |
| 841 } | 877 int bpc, |
| 842 FX_DWORD CCodec_FlateModule::FlateOrLZWDecode(FX_BOOL bLZW, const uint8_t* src_b
uf, FX_DWORD src_size, FX_BOOL bEarlyChange, | 878 int predictor, |
| 843 int predictor, int Colors, int BitsPerComponent, int Columns, | 879 int Colors, |
| 844 FX_DWORD estimated_size, uint8_t*& dest_buf, FX_DWORD& dest_size) | 880 int BitsPerComponent, |
| 845 { | 881 int Columns) { |
| 846 dest_buf = NULL; | 882 CCodec_FlateScanlineDecoder* pDecoder = new CCodec_FlateScanlineDecoder; |
| 847 FX_DWORD offset = 0; | 883 pDecoder->Create(src_buf, src_size, width, height, nComps, bpc, predictor, |
| 848 int predictor_type = 0; | 884 Colors, BitsPerComponent, Columns); |
| 849 if (predictor) { | 885 return pDecoder; |
| 850 if (predictor >= 10) { | 886 } |
| 851 predictor_type = 2; | 887 FX_DWORD CCodec_FlateModule::FlateOrLZWDecode(FX_BOOL bLZW, |
| 852 } else if (predictor == 2) { | 888 const uint8_t* src_buf, |
| 853 predictor_type = 1; | 889 FX_DWORD src_size, |
| 854 } | 890 FX_BOOL bEarlyChange, |
| 855 } | 891 int predictor, |
| 856 if (bLZW) { | 892 int Colors, |
| 857 { | 893 int BitsPerComponent, |
| 858 nonstd::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder); | 894 int Columns, |
| 859 dest_size = (FX_DWORD) - 1; | 895 FX_DWORD estimated_size, |
| 860 offset = src_size; | 896 uint8_t*& dest_buf, |
| 861 int err = decoder->Decode(NULL, dest_size, src_buf, offset, | 897 FX_DWORD& dest_size) { |
| 862 bEarlyChange); | 898 dest_buf = NULL; |
| 863 if (err || dest_size == 0 || dest_size + 1 < dest_size) { | 899 FX_DWORD offset = 0; |
| 864 return -1; | 900 int predictor_type = 0; |
| 865 } | 901 if (predictor) { |
| 866 } | 902 if (predictor >= 10) { |
| 867 { | 903 predictor_type = 2; |
| 868 nonstd::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder); | 904 } else if (predictor == 2) { |
| 869 dest_buf = FX_Alloc( uint8_t, dest_size + 1); | 905 predictor_type = 1; |
| 870 dest_buf[dest_size] = '\0'; | 906 } |
| 871 decoder->Decode(dest_buf, dest_size, src_buf, offset, bEarlyChange); | 907 } |
| 872 } | 908 if (bLZW) { |
| 873 } else { | 909 { |
| 874 FlateUncompress(src_buf, src_size, estimated_size, dest_buf, dest_size,
offset); | 910 nonstd::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder); |
| 875 } | 911 dest_size = (FX_DWORD)-1; |
| 876 if (predictor_type == 0) { | 912 offset = src_size; |
| 877 return offset; | 913 int err = decoder->Decode(NULL, dest_size, src_buf, offset, bEarlyChange); |
| 878 } | 914 if (err || dest_size == 0 || dest_size + 1 < dest_size) { |
| 879 FX_BOOL ret = TRUE; | 915 return -1; |
| 880 if (predictor_type == 2) { | 916 } |
| 881 ret = PNG_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, | 917 } |
| 882 Columns); | 918 { |
| 883 } else if (predictor_type == 1) { | 919 nonstd::unique_ptr<CLZWDecoder> decoder(new CLZWDecoder); |
| 884 ret = TIFF_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, | 920 dest_buf = FX_Alloc(uint8_t, dest_size + 1); |
| 885 Columns); | 921 dest_buf[dest_size] = '\0'; |
| 886 } | 922 decoder->Decode(dest_buf, dest_size, src_buf, offset, bEarlyChange); |
| 887 return ret ? offset : -1; | 923 } |
| 888 } | 924 } else { |
| 889 FX_BOOL CCodec_FlateModule::Encode(const uint8_t* src_buf, FX_DWORD src_size, | 925 FlateUncompress(src_buf, src_size, estimated_size, dest_buf, dest_size, |
| 890 int predictor, int Colors, int BitsPerCompone
nt, int Columns, | 926 offset); |
| 891 uint8_t*& dest_buf, FX_DWORD& dest_size) | 927 } |
| 892 { | 928 if (predictor_type == 0) { |
| 893 if (predictor != 2 && predictor < 10) { | 929 return offset; |
| 894 return Encode(src_buf, src_size, dest_buf, dest_size); | 930 } |
| 895 } | 931 FX_BOOL ret = TRUE; |
| 896 uint8_t* pSrcBuf = NULL; | 932 if (predictor_type == 2) { |
| 897 pSrcBuf = FX_Alloc(uint8_t, src_size); | 933 ret = PNG_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns); |
| 898 FXSYS_memcpy(pSrcBuf, src_buf, src_size); | 934 } else if (predictor_type == 1) { |
| 899 FX_BOOL ret = TRUE; | 935 ret = |
| 900 if (predictor == 2) { | 936 TIFF_Predictor(dest_buf, dest_size, Colors, BitsPerComponent, Columns); |
| 901 ret = TIFF_PredictorEncode(pSrcBuf, src_size, Colors, BitsPerComponent, | 937 } |
| 902 Columns); | 938 return ret ? offset : -1; |
| 903 } else if (predictor >= 10) { | 939 } |
| 904 ret = PNG_PredictorEncode(pSrcBuf, src_size, predictor, Colors, | 940 FX_BOOL CCodec_FlateModule::Encode(const uint8_t* src_buf, |
| 905 BitsPerComponent, Columns); | 941 FX_DWORD src_size, |
| 906 } | 942 int predictor, |
| 907 if (ret) | 943 int Colors, |
| 908 ret = Encode(pSrcBuf, src_size, dest_buf, dest_size); | 944 int BitsPerComponent, |
| 909 FX_Free(pSrcBuf); | 945 int Columns, |
| 910 return ret; | 946 uint8_t*& dest_buf, |
| 911 } | 947 FX_DWORD& dest_size) { |
| 912 FX_BOOL CCodec_FlateModule::Encode(const uint8_t* src_buf, FX_DWORD src_size, ui
nt8_t*& dest_buf, FX_DWORD& dest_size) | 948 if (predictor != 2 && predictor < 10) { |
| 913 { | 949 return Encode(src_buf, src_size, dest_buf, dest_size); |
| 914 dest_size = src_size + src_size / 1000 + 12; | 950 } |
| 915 dest_buf = FX_Alloc( uint8_t, dest_size); | 951 uint8_t* pSrcBuf = NULL; |
| 916 unsigned long temp_size = dest_size; | 952 pSrcBuf = FX_Alloc(uint8_t, src_size); |
| 917 FPDFAPI_FlateCompress(dest_buf, &temp_size, src_buf, src_size); | 953 FXSYS_memcpy(pSrcBuf, src_buf, src_size); |
| 918 dest_size = (FX_DWORD)temp_size; | 954 FX_BOOL ret = TRUE; |
| 919 return TRUE; | 955 if (predictor == 2) { |
| 920 } | 956 ret = TIFF_PredictorEncode(pSrcBuf, src_size, Colors, BitsPerComponent, |
| 957 Columns); |
| 958 } else if (predictor >= 10) { |
| 959 ret = PNG_PredictorEncode(pSrcBuf, src_size, predictor, Colors, |
| 960 BitsPerComponent, Columns); |
| 961 } |
| 962 if (ret) |
| 963 ret = Encode(pSrcBuf, src_size, dest_buf, dest_size); |
| 964 FX_Free(pSrcBuf); |
| 965 return ret; |
| 966 } |
| 967 FX_BOOL CCodec_FlateModule::Encode(const uint8_t* src_buf, |
| 968 FX_DWORD src_size, |
| 969 uint8_t*& dest_buf, |
| 970 FX_DWORD& dest_size) { |
| 971 dest_size = src_size + src_size / 1000 + 12; |
| 972 dest_buf = FX_Alloc(uint8_t, dest_size); |
| 973 unsigned long temp_size = dest_size; |
| 974 FPDFAPI_FlateCompress(dest_buf, &temp_size, src_buf, src_size); |
| 975 dest_size = (FX_DWORD)temp_size; |
| 976 return TRUE; |
| 977 } |
| OLD | NEW |