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 |