1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fxcodec/progressivedecoder.h"
8
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13
14 #include "build/build_config.h"
15 #include "core/fxcodec/cfx_codec_memory.h"
16 #include "core/fxcodec/fx_codec.h"
17 #include "core/fxcrt/fx_safe_types.h"
18 #include "core/fxcrt/fx_stream.h"
19 #include "core/fxge/dib/cfx_cmyk_to_srgb.h"
20 #include "core/fxge/dib/cfx_dibitmap.h"
21 #include "core/fxge/fx_dib.h"
22 #include "third_party/base/logging.h"
23 #include "third_party/base/numerics/safe_math.h"
24 #include "third_party/base/ptr_util.h"
25
26 namespace fxcodec {
27
28 namespace {
29
30 constexpr size_t kBlockSize = 4096;
31
32 #ifdef PDF_ENABLE_XFA_PNG
33 #if defined(OS_MACOSX)
34 const double kPngGamma = 1.7;
35 #else
36 const double kPngGamma = 2.2;
37 #endif // defined(OS_MACOSX)
38 #endif // PDF_ENABLE_XFA_PNG
39
RGB2BGR(uint8_t * buffer,int width=1)40 void RGB2BGR(uint8_t* buffer, int width = 1) {
41 if (buffer && width > 0) {
42 uint8_t temp;
43 int i = 0;
44 int j = 0;
45 for (; i < width; i++, j += 3) {
46 temp = buffer[j];
47 buffer[j] = buffer[j + 2];
48 buffer[j + 2] = temp;
49 }
50 }
51 }
52
53 } // namespace
54
55 ProgressiveDecoder::CFXCODEC_WeightTable::CFXCODEC_WeightTable() = default;
56
57 ProgressiveDecoder::CFXCODEC_WeightTable::~CFXCODEC_WeightTable() = default;
58
Calc(int dest_len,int src_len)59 void ProgressiveDecoder::CFXCODEC_WeightTable::Calc(int dest_len, int src_len) {
60 double scale = static_cast<double>(src_len) / dest_len;
61 double base = dest_len < 0 ? src_len : 0.0;
62 m_ItemSize = (int)(sizeof(int) * 2 + sizeof(int) * (ceil(fabs(scale)) + 1));
63 m_DestMin = 0;
64 m_pWeightTables.resize(dest_len * m_ItemSize + 4);
65 if (fabs(scale) < 1.0) {
66 for (int dest_pixel = 0; dest_pixel < dest_len; dest_pixel++) {
67 PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
68 double src_pos = dest_pixel * scale + scale / 2 + base;
69 pixel_weights.m_SrcStart = (int)floor((float)src_pos - 1.0f / 2);
70 pixel_weights.m_SrcEnd = (int)floor((float)src_pos + 1.0f / 2);
71 pixel_weights.m_SrcStart = std::max(pixel_weights.m_SrcStart, 0);
72 pixel_weights.m_SrcEnd = std::min(pixel_weights.m_SrcEnd, src_len - 1);
73 if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) {
74 pixel_weights.m_Weights[0] = 65536;
75 } else {
76 pixel_weights.m_Weights[1] = FXSYS_roundf(
77 (float)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 65536);
78 pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1];
79 }
80 }
81 return;
82 }
83 for (int dest_pixel = 0; dest_pixel < dest_len; dest_pixel++) {
84 PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
85 double src_start = dest_pixel * scale + base;
86 double src_end = src_start + scale;
87 int start_i;
88 int end_i;
89 if (src_start < src_end) {
90 start_i = (int)floor((float)src_start);
91 end_i = (int)ceil((float)src_end);
92 } else {
93 start_i = (int)floor((float)src_end);
94 end_i = (int)ceil((float)src_start);
95 }
96 start_i = std::max(start_i, 0);
97 end_i = std::min(end_i, src_len - 1);
98 if (start_i > end_i) {
99 pixel_weights.m_SrcStart = start_i;
100 pixel_weights.m_SrcEnd = start_i;
101 continue;
102 }
103 pixel_weights.m_SrcStart = start_i;
104 pixel_weights.m_SrcEnd = end_i;
105 for (int j = start_i; j <= end_i; j++) {
106 double dest_start = ((float)j - base) / scale;
107 double dest_end = ((float)(j + 1) - base) / scale;
108 if (dest_start > dest_end) {
109 double temp = dest_start;
110 dest_start = dest_end;
111 dest_end = temp;
112 }
113 double area_start =
114 dest_start > (float)(dest_pixel) ? dest_start : (float)(dest_pixel);
115 double area_end = dest_end > (float)(dest_pixel + 1)
116 ? (float)(dest_pixel + 1)
117 : dest_end;
118 double weight = area_start >= area_end ? 0.0 : area_end - area_start;
119 if (weight == 0 && j == end_i) {
120 pixel_weights.m_SrcEnd--;
121 break;
122 }
123 pixel_weights.m_Weights[j - start_i] =
124 FXSYS_roundf((float)(weight * 65536));
125 }
126 }
127 }
128
129 ProgressiveDecoder::CFXCODEC_HorzTable::CFXCODEC_HorzTable() = default;
130
131 ProgressiveDecoder::CFXCODEC_HorzTable::~CFXCODEC_HorzTable() = default;
132
Calc(int dest_len,int src_len)133 void ProgressiveDecoder::CFXCODEC_HorzTable::Calc(int dest_len, int src_len) {
134 double scale = (double)dest_len / (double)src_len;
135 m_ItemSize = sizeof(int) * 4;
136 int size = dest_len * m_ItemSize + 4;
137 m_pWeightTables.resize(size, 0);
138 if (scale > 1) {
139 int pre_dest_col = 0;
140 for (int src_col = 0; src_col < src_len; src_col++) {
141 double dest_col_f = src_col * scale;
142 int dest_col = FXSYS_roundf((float)dest_col_f);
143 PixelWeight* pWeight = GetPixelWeight(dest_col);
144 pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
145 pWeight->m_Weights[0] = 65536;
146 pWeight->m_Weights[1] = 0;
147 if (src_col == src_len - 1 && dest_col < dest_len - 1) {
148 for (int dest_col_index = pre_dest_col + 1; dest_col_index < dest_len;
149 dest_col_index++) {
150 pWeight = GetPixelWeight(dest_col_index);
151 pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
152 pWeight->m_Weights[0] = 65536;
153 pWeight->m_Weights[1] = 0;
154 }
155 return;
156 }
157 int dest_col_len = dest_col - pre_dest_col;
158 for (int dest_col_index = pre_dest_col + 1; dest_col_index < dest_col;
159 dest_col_index++) {
160 pWeight = GetPixelWeight(dest_col_index);
161 pWeight->m_SrcStart = src_col - 1;
162 pWeight->m_SrcEnd = src_col;
163 pWeight->m_Weights[0] =
164 FXSYS_roundf((float)(((float)dest_col - (float)dest_col_index) /
165 (float)dest_col_len * 65536));
166 pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0];
167 }
168 pre_dest_col = dest_col;
169 }
170 return;
171 }
172 for (int dest_col = 0; dest_col < dest_len; dest_col++) {
173 double src_col_f = dest_col / scale;
174 int src_col = FXSYS_roundf((float)src_col_f);
175 PixelWeight* pWeight = GetPixelWeight(dest_col);
176 pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
177 pWeight->m_Weights[0] = 65536;
178 pWeight->m_Weights[1] = 0;
179 }
180 }
181
182 ProgressiveDecoder::CFXCODEC_VertTable::CFXCODEC_VertTable() = default;
183
184 ProgressiveDecoder::CFXCODEC_VertTable::~CFXCODEC_VertTable() = default;
185
Calc(int dest_len,int src_len)186 void ProgressiveDecoder::CFXCODEC_VertTable::Calc(int dest_len, int src_len) {
187 double scale = (double)dest_len / (double)src_len;
188 m_ItemSize = sizeof(int) * 4;
189 int size = dest_len * m_ItemSize + 4;
190 m_pWeightTables.resize(size, 0);
191 if (scale <= 1) {
192 for (int dest_row = 0; dest_row < dest_len; dest_row++) {
193 PixelWeight* pWeight = GetPixelWeight(dest_row);
194 pWeight->m_SrcStart = dest_row;
195 pWeight->m_SrcEnd = dest_row;
196 pWeight->m_Weights[0] = 65536;
197 pWeight->m_Weights[1] = 0;
198 }
199 return;
200 }
201
202 double step = 0.0;
203 int src_row = 0;
204 while (step < (double)dest_len) {
205 int start_step = (int)step;
206 step = scale * (++src_row);
207 int end_step = (int)step;
208 if (end_step >= dest_len) {
209 end_step = dest_len;
210 for (int dest_row = start_step; dest_row < end_step; dest_row++) {
211 PixelWeight* pWeight = GetPixelWeight(dest_row);
212 pWeight->m_SrcStart = start_step;
213 pWeight->m_SrcEnd = start_step;
214 pWeight->m_Weights[0] = 65536;
215 pWeight->m_Weights[1] = 0;
216 }
217 return;
218 }
219 int length = end_step - start_step;
220 {
221 PixelWeight* pWeight = GetPixelWeight(start_step);
222 pWeight->m_SrcStart = start_step;
223 pWeight->m_SrcEnd = start_step;
224 pWeight->m_Weights[0] = 65536;
225 pWeight->m_Weights[1] = 0;
226 }
227 for (int dest_row = start_step + 1; dest_row < end_step; dest_row++) {
228 PixelWeight* pWeight = GetPixelWeight(dest_row);
229 pWeight->m_SrcStart = start_step;
230 pWeight->m_SrcEnd = end_step;
231 pWeight->m_Weights[0] =
232 FXSYS_roundf((float)(end_step - dest_row) / (float)length * 65536);
233 pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0];
234 }
235 }
236 }
237
ProgressiveDecoder(ModuleMgr * pCodecMgr)238 ProgressiveDecoder::ProgressiveDecoder(ModuleMgr* pCodecMgr)
239 : m_pCodecMgr(pCodecMgr) {}
240
241 ProgressiveDecoder::~ProgressiveDecoder() = default;
242
243 #ifdef PDF_ENABLE_XFA_PNG
PngReadHeader(int width,int height,int bpc,int pass,int * color_type,double * gamma)244 bool ProgressiveDecoder::PngReadHeader(int width,
245 int height,
246 int bpc,
247 int pass,
248 int* color_type,
249 double* gamma) {
250 if (!m_pDeviceBitmap) {
251 m_SrcWidth = width;
252 m_SrcHeight = height;
253 m_SrcBPC = bpc;
254 m_SrcPassNumber = pass;
255 switch (*color_type) {
256 case 0:
257 m_SrcComponents = 1;
258 break;
259 case 4:
260 m_SrcComponents = 2;
261 break;
262 case 2:
263 m_SrcComponents = 3;
264 break;
265 case 3:
266 case 6:
267 m_SrcComponents = 4;
268 break;
269 default:
270 m_SrcComponents = 0;
271 break;
272 }
273 m_clipBox = FX_RECT(0, 0, width, height);
274 return false;
275 }
276 FXDIB_Format format = m_pDeviceBitmap->GetFormat();
277 switch (format) {
278 case FXDIB_1bppMask:
279 case FXDIB_1bppRgb:
280 NOTREACHED();
281 return false;
282 case FXDIB_8bppMask:
283 case FXDIB_8bppRgb:
284 *color_type = 0;
285 break;
286 case FXDIB_Rgb:
287 *color_type = 2;
288 break;
289 case FXDIB_Rgb32:
290 case FXDIB_Argb:
291 *color_type = 6;
292 break;
293 default:
294 NOTREACHED();
295 return false;
296 }
297 *gamma = kPngGamma;
298 return true;
299 }
300
PngAskScanlineBuf(int line,uint8_t ** pSrcBuf)301 bool ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t** pSrcBuf) {
302 RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
303 if (!pDIBitmap) {
304 NOTREACHED();
305 return false;
306 }
307 if (line >= m_clipBox.top && line < m_clipBox.bottom) {
308 double scale_y = static_cast<double>(m_sizeY) / m_clipBox.Height();
309 int32_t row = (int32_t)((line - m_clipBox.top) * scale_y) + m_startY;
310 const uint8_t* src_scan = pDIBitmap->GetScanline(row);
311 uint8_t* dest_scan = m_pDecodeBuf.get();
312 *pSrcBuf = m_pDecodeBuf.get();
313 int32_t src_Bpp = pDIBitmap->GetBPP() >> 3;
314 int32_t dest_Bpp = (m_SrcFormat & 0xff) >> 3;
315 int32_t src_left = m_startX;
316 int32_t dest_left = m_clipBox.left;
317 src_scan += src_left * src_Bpp;
318 dest_scan += dest_left * dest_Bpp;
319 for (int32_t src_col = 0; src_col < m_sizeX; src_col++) {
320 PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(src_col);
321 if (pPixelWeights->m_SrcStart != pPixelWeights->m_SrcEnd) {
322 continue;
323 }
324 switch (pDIBitmap->GetFormat()) {
325 case FXDIB_1bppMask:
326 case FXDIB_1bppRgb:
327 NOTREACHED();
328 return false;
329 case FXDIB_8bppMask:
330 case FXDIB_8bppRgb: {
331 if (pDIBitmap->GetPalette()) {
332 return false;
333 }
334 uint32_t dest_g = 0;
335 dest_g += pPixelWeights->m_Weights[0] * src_scan[src_col];
336 dest_scan[pPixelWeights->m_SrcStart] = (uint8_t)(dest_g >> 16);
337 } break;
338 case FXDIB_Rgb:
339 case FXDIB_Rgb32: {
340 uint32_t dest_b = 0;
341 uint32_t dest_g = 0;
342 uint32_t dest_r = 0;
343 const uint8_t* p = src_scan + src_col * src_Bpp;
344 dest_b += pPixelWeights->m_Weights[0] * (*p++);
345 dest_g += pPixelWeights->m_Weights[0] * (*p++);
346 dest_r += pPixelWeights->m_Weights[0] * (*p);
347 uint8_t* pDes = &dest_scan[pPixelWeights->m_SrcStart * dest_Bpp];
348 *pDes++ = (uint8_t)((dest_b) >> 16);
349 *pDes++ = (uint8_t)((dest_g) >> 16);
350 *pDes = (uint8_t)((dest_r) >> 16);
351 } break;
352 case FXDIB_Argb: {
353 uint32_t dest_r = 0;
354 uint32_t dest_g = 0;
355 uint32_t dest_b = 0;
356 const uint8_t* p = src_scan + src_col * src_Bpp;
357 dest_b += pPixelWeights->m_Weights[0] * (*p++);
358 dest_g += pPixelWeights->m_Weights[0] * (*p++);
359 dest_r += pPixelWeights->m_Weights[0] * (*p++);
360 uint8_t* pDes = &dest_scan[pPixelWeights->m_SrcStart * dest_Bpp];
361 *pDes++ = (uint8_t)((dest_b) >> 16);
362 *pDes++ = (uint8_t)((dest_g) >> 16);
363 *pDes++ = (uint8_t)((dest_r) >> 16);
364 *pDes = *p;
365 } break;
366 default:
367 return false;
368 }
369 }
370 }
371 return true;
372 }
373
PngFillScanlineBufCompleted(int pass,int line)374 void ProgressiveDecoder::PngFillScanlineBufCompleted(int pass, int line) {
375 RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
376 ASSERT(pDIBitmap);
377 int src_top = m_clipBox.top;
378 int src_bottom = m_clipBox.bottom;
379 int dest_top = m_startY;
380 int src_height = m_clipBox.Height();
381 int dest_height = m_sizeY;
382 if (line >= src_top && line < src_bottom) {
383 double scale_y = static_cast<double>(dest_height) / src_height;
384 int src_row = line - src_top;
385 int dest_row = (int)(src_row * scale_y) + dest_top;
386 if (dest_row >= dest_top + dest_height) {
387 return;
388 }
389 PngOneOneMapResampleHorz(pDIBitmap, dest_row, m_pDecodeBuf.get(),
390 m_SrcFormat);
391 if (m_SrcPassNumber == 1 && scale_y > 1.0) {
392 ResampleVert(pDIBitmap, scale_y, dest_row);
393 return;
394 }
395 if (pass == 6 && scale_y > 1.0) {
396 ResampleVert(pDIBitmap, scale_y, dest_row);
397 }
398 }
399 }
400 #endif // PDF_ENABLE_XFA_PNG
401
402 #ifdef PDF_ENABLE_XFA_GIF
GifRecordCurrentPosition(uint32_t & cur_pos)403 void ProgressiveDecoder::GifRecordCurrentPosition(uint32_t& cur_pos) {
404 uint32_t remain_size =
405 m_pCodecMgr->GetGifModule()->GetAvailInput(m_pGifContext.get());
406 cur_pos = m_offSet - remain_size;
407 }
408
GifInputRecordPositionBuf(uint32_t rcd_pos,const FX_RECT & img_rc,int32_t pal_num,CFX_GifPalette * pal_ptr,int32_t delay_time,bool user_input,int32_t trans_index,int32_t disposal_method,bool interlace)409 bool ProgressiveDecoder::GifInputRecordPositionBuf(uint32_t rcd_pos,
410 const FX_RECT& img_rc,
411 int32_t pal_num,
412 CFX_GifPalette* pal_ptr,
413 int32_t delay_time,
414 bool user_input,
415 int32_t trans_index,
416 int32_t disposal_method,
417 bool interlace) {
418 m_offSet = rcd_pos;
419 m_InvalidateGifBuffer = true;
420
421 FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
422 if (!GifReadMoreData(m_pCodecMgr->GetGifModule(), error_status)) {
423 return false;
424 }
425 CFX_GifPalette* pPalette = nullptr;
426 if (pal_num != 0 && pal_ptr) {
427 pPalette = pal_ptr;
428 } else {
429 if (!m_pGifPalette)
430 return false;
431 pal_num = m_GifPltNumber;
432 pPalette = m_pGifPalette;
433 }
434 if (!m_pSrcPalette)
435 m_pSrcPalette.reset(FX_Alloc(FX_ARGB, pal_num));
436 else if (pal_num > m_SrcPaletteNumber)
437 m_pSrcPalette.reset(FX_Realloc(FX_ARGB, m_pSrcPalette.release(), pal_num));
438 if (!m_pSrcPalette)
439 return false;
440
441 m_SrcPaletteNumber = pal_num;
442 for (int i = 0; i < pal_num; i++) {
443 m_pSrcPalette.get()[i] =
444 ArgbEncode(0xff, pPalette[i].r, pPalette[i].g, pPalette[i].b);
445 }
446 m_GifTransIndex = trans_index;
447 m_GifFrameRect = img_rc;
448 m_SrcPassNumber = interlace ? 4 : 1;
449 int32_t pal_index = m_GifBgIndex;
450 RetainPtr<CFX_DIBitmap> pDevice = m_pDeviceBitmap;
451 if (trans_index >= pal_num)
452 trans_index = -1;
453 if (trans_index != -1) {
454 m_pSrcPalette.get()[trans_index] &= 0x00ffffff;
455 if (pDevice->HasAlpha())
456 pal_index = trans_index;
457 }
458 if (pal_index >= pal_num)
459 return false;
460
461 int startX = m_startX;
462 int startY = m_startY;
463 int sizeX = m_sizeX;
464 int sizeY = m_sizeY;
465 int Bpp = pDevice->GetBPP() / 8;
466 FX_ARGB argb = m_pSrcPalette.get()[pal_index];
467 for (int row = 0; row < sizeY; row++) {
468 uint8_t* pScanline =
469 pDevice->GetWritableScanline(row + startY) + startX * Bpp;
470 switch (m_TransMethod) {
471 case 3: {
472 uint8_t gray =
473 FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
474 memset(pScanline, gray, sizeX);
475 break;
476 }
477 case 8: {
478 for (int col = 0; col < sizeX; col++) {
479 *pScanline++ = FXARGB_B(argb);
480 *pScanline++ = FXARGB_G(argb);
481 *pScanline++ = FXARGB_R(argb);
482 pScanline += Bpp - 3;
483 }
484 break;
485 }
486 case 12: {
487 for (int col = 0; col < sizeX; col++) {
488 FXARGB_SETDIB(pScanline, argb);
489 pScanline += 4;
490 }
491 break;
492 }
493 }
494 }
495 return true;
496 }
497
GifReadScanline(int32_t row_num,uint8_t * row_buf)498 void ProgressiveDecoder::GifReadScanline(int32_t row_num, uint8_t* row_buf) {
499 RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
500 ASSERT(pDIBitmap);
501 int32_t img_width = m_GifFrameRect.Width();
502 if (!pDIBitmap->HasAlpha()) {
503 uint8_t* byte_ptr = row_buf;
504 for (int i = 0; i < img_width; i++) {
505 if (*byte_ptr == m_GifTransIndex) {
506 *byte_ptr = m_GifBgIndex;
507 }
508 byte_ptr++;
509 }
510 }
511 int32_t pal_index = m_GifBgIndex;
512 if (m_GifTransIndex != -1 && m_pDeviceBitmap->HasAlpha()) {
513 pal_index = m_GifTransIndex;
514 }
515 memset(m_pDecodeBuf.get(), pal_index, m_SrcWidth);
516 bool bLastPass = (row_num % 2) == 1;
517 int32_t line = row_num + m_GifFrameRect.top;
518 int32_t left = m_GifFrameRect.left;
519 memcpy(m_pDecodeBuf.get() + left, row_buf, img_width);
520 int src_top = m_clipBox.top;
521 int src_bottom = m_clipBox.bottom;
522 int dest_top = m_startY;
523 int src_height = m_clipBox.Height();
524 int dest_height = m_sizeY;
525 if (line < src_top || line >= src_bottom)
526 return;
527
528 double scale_y = static_cast<double>(dest_height) / src_height;
529 int src_row = line - src_top;
530 int dest_row = (int)(src_row * scale_y) + dest_top;
531 if (dest_row >= dest_top + dest_height)
532 return;
533
534 ReSampleScanline(pDIBitmap, dest_row, m_pDecodeBuf.get(), m_SrcFormat);
535 if (scale_y > 1.0 && m_SrcPassNumber == 1) {
536 ResampleVert(pDIBitmap, scale_y, dest_row);
537 return;
538 }
539 if (scale_y <= 1.0)
540 return;
541
542 int dest_bottom = dest_top + m_sizeY;
543 int dest_Bpp = pDIBitmap->GetBPP() >> 3;
544 uint32_t dest_ScanOffet = m_startX * dest_Bpp;
545 if (dest_row + (int)scale_y >= dest_bottom - 1) {
546 const uint8_t* scan_src = pDIBitmap->GetScanline(dest_row) + dest_ScanOffet;
547 int cur_row = dest_row;
548 while (++cur_row < dest_bottom) {
549 uint8_t* scan_des =
550 pDIBitmap->GetWritableScanline(cur_row) + dest_ScanOffet;
551 uint32_t size = m_sizeX * dest_Bpp;
552 memmove(scan_des, scan_src, size);
553 }
554 }
555 if (bLastPass)
556 GifDoubleLineResampleVert(pDIBitmap, scale_y, dest_row);
557 }
558 #endif // PDF_ENABLE_XFA_GIF
559
560 #ifdef PDF_ENABLE_XFA_BMP
BmpInputImagePositionBuf(uint32_t rcd_pos)561 bool ProgressiveDecoder::BmpInputImagePositionBuf(uint32_t rcd_pos) {
562 m_offSet = rcd_pos;
563 FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
564 return BmpReadMoreData(m_pCodecMgr->GetBmpModule(), m_pBmpContext.get(),
565 error_status);
566 }
567
BmpReadScanline(uint32_t row_num,pdfium::span<const uint8_t> row_buf)568 void ProgressiveDecoder::BmpReadScanline(uint32_t row_num,
569 pdfium::span<const uint8_t> row_buf) {
570 RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
571 ASSERT(pDIBitmap);
572
573 pdfium::span<const uint8_t> src_span = row_buf.first(m_ScanlineSize);
574 std::copy(std::begin(src_span), std::end(src_span), m_pDecodeBuf.get());
575
576 int src_top = m_clipBox.top;
577 int src_bottom = m_clipBox.bottom;
578 int dest_top = m_startY;
579 int src_height = m_clipBox.Height();
580 int dest_height = m_sizeY;
581 if ((src_top >= 0 && row_num < static_cast<uint32_t>(src_top)) ||
582 src_bottom < 0 || row_num >= static_cast<uint32_t>(src_bottom)) {
583 return;
584 }
585
586 double scale_y = static_cast<double>(dest_height) / src_height;
587 int src_row = row_num - src_top;
588 int dest_row = (int)(src_row * scale_y) + dest_top;
589 if (dest_row >= dest_top + dest_height)
590 return;
591
592 ReSampleScanline(pDIBitmap, dest_row, m_pDecodeBuf.get(), m_SrcFormat);
593 if (scale_y <= 1.0)
594 return;
595
596 if (m_BmpIsTopBottom) {
597 ResampleVert(pDIBitmap, scale_y, dest_row);
598 return;
599 }
600 ResampleVertBT(pDIBitmap, scale_y, dest_row);
601 }
602
ResampleVertBT(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)603 void ProgressiveDecoder::ResampleVertBT(
604 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
605 double scale_y,
606 int dest_row) {
607 int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
608 uint32_t dest_ScanOffet = m_startX * dest_Bpp;
609 int dest_top = m_startY;
610 int dest_bottom = m_startY + m_sizeY;
611 pdfium::base::CheckedNumeric<int> check_dest_row_1 = dest_row;
612 check_dest_row_1 += pdfium::base::checked_cast<int>(scale_y);
613 int dest_row_1 = check_dest_row_1.ValueOrDie();
614 if (dest_row_1 >= dest_bottom - 1) {
615 const uint8_t* scan_src =
616 pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
617 while (++dest_row < dest_bottom) {
618 uint8_t* scan_des =
619 pDeviceBitmap->GetWritableScanline(dest_row) + dest_ScanOffet;
620 uint32_t size = m_sizeX * dest_Bpp;
621 memmove(scan_des, scan_src, size);
622 }
623 return;
624 }
625 for (; dest_row_1 > dest_row; dest_row_1--) {
626 uint8_t* scan_des =
627 pDeviceBitmap->GetWritableScanline(dest_row_1) + dest_ScanOffet;
628 PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
629 const uint8_t* scan_src1 =
630 pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) +
631 dest_ScanOffet;
632 const uint8_t* scan_src2 =
633 pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) +
634 dest_ScanOffet;
635 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
636 switch (pDeviceBitmap->GetFormat()) {
637 case FXDIB_Invalid:
638 case FXDIB_1bppMask:
639 case FXDIB_1bppRgb:
640 return;
641 case FXDIB_8bppMask:
642 case FXDIB_8bppRgb: {
643 if (pDeviceBitmap->GetPalette()) {
644 return;
645 }
646 int dest_g = 0;
647 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
648 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
649 *scan_des++ = (uint8_t)(dest_g >> 16);
650 } break;
651 case FXDIB_Rgb:
652 case FXDIB_Rgb32: {
653 uint32_t dest_b = 0;
654 uint32_t dest_g = 0;
655 uint32_t dest_r = 0;
656 dest_b += pWeight->m_Weights[0] * (*scan_src1++);
657 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
658 dest_r += pWeight->m_Weights[0] * (*scan_src1++);
659 scan_src1 += dest_Bpp - 3;
660 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
661 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
662 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
663 scan_src2 += dest_Bpp - 3;
664 *scan_des++ = (uint8_t)((dest_b) >> 16);
665 *scan_des++ = (uint8_t)((dest_g) >> 16);
666 *scan_des++ = (uint8_t)((dest_r) >> 16);
667 scan_des += dest_Bpp - 3;
668 } break;
669 case FXDIB_Argb: {
670 uint32_t dest_a = 0;
671 uint32_t dest_b = 0;
672 uint32_t dest_g = 0;
673 uint32_t dest_r = 0;
674 dest_b += pWeight->m_Weights[0] * (*scan_src1++);
675 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
676 dest_r += pWeight->m_Weights[0] * (*scan_src1++);
677 dest_a += pWeight->m_Weights[0] * (*scan_src1++);
678 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
679 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
680 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
681 dest_a += pWeight->m_Weights[1] * (*scan_src2++);
682 *scan_des++ = (uint8_t)((dest_b) >> 16);
683 *scan_des++ = (uint8_t)((dest_g) >> 16);
684 *scan_des++ = (uint8_t)((dest_r) >> 16);
685 *scan_des++ = (uint8_t)((dest_a) >> 16);
686 } break;
687 default:
688 return;
689 }
690 }
691 }
692 }
693
BmpDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)694 bool ProgressiveDecoder::BmpDetectImageTypeInBuffer(
695 CFX_DIBAttribute* pAttribute) {
696 BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
697 if (!pBmpModule) {
698 m_status = FXCODEC_STATUS_ERR_MEMORY;
699 return false;
700 }
701
702 std::unique_ptr<ModuleIface::Context> pBmpContext = pBmpModule->Start(this);
703 pBmpModule->Input(pBmpContext.get(), m_pCodecMemory, nullptr);
704
705 const std::vector<uint32_t>* palette;
706 BmpModule::Status read_result = pBmpModule->ReadHeader(
707 pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
708 &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
709 while (read_result == BmpModule::Status::kContinue) {
710 FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
711 if (!BmpReadMoreData(pBmpModule, pBmpContext.get(), error_status)) {
712 m_status = error_status;
713 return false;
714 }
715 read_result = pBmpModule->ReadHeader(
716 pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
717 &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
718 }
719
720 if (read_result != BmpModule::Status::kSuccess) {
721 m_status = FXCODEC_STATUS_ERR_FORMAT;
722 return false;
723 }
724
725 FXDIB_Format format = FXDIB_Invalid;
726 switch (m_SrcComponents) {
727 case 1:
728 m_SrcFormat = FXCodec_8bppRgb;
729 format = FXDIB_8bppRgb;
730 break;
731 case 3:
732 m_SrcFormat = FXCodec_Rgb;
733 format = FXDIB_Rgb;
734 break;
735 case 4:
736 m_SrcFormat = FXCodec_Rgb32;
737 format = FXDIB_Rgb32;
738 break;
739 default:
740 m_status = FXCODEC_STATUS_ERR_FORMAT;
741 return false;
742 }
743
744 uint32_t pitch = 0;
745 uint32_t neededData = 0;
746 if (!CFX_DIBitmap::CalculatePitchAndSize(m_SrcWidth, m_SrcHeight, format,
747 &pitch, &neededData)) {
748 m_status = FXCODEC_STATUS_ERR_FORMAT;
749 return false;
750 }
751
752 uint32_t availableData = m_pFile->GetSize() - m_offSet +
753 pBmpModule->GetAvailInput(pBmpContext.get());
754 if (neededData > availableData) {
755 m_status = FXCODEC_STATUS_ERR_FORMAT;
756 return false;
757 }
758
759 m_SrcBPC = 8;
760 m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
761 m_pBmpContext = std::move(pBmpContext);
762 if (m_SrcPaletteNumber) {
763 m_pSrcPalette.reset(FX_Alloc(FX_ARGB, m_SrcPaletteNumber));
764 memcpy(m_pSrcPalette.get(), palette->data(),
765 m_SrcPaletteNumber * sizeof(FX_ARGB));
766 } else {
767 m_pSrcPalette.reset();
768 }
769 return true;
770 }
771
BmpReadMoreData(BmpModule * pBmpModule,ModuleIface::Context * pContext,FXCODEC_STATUS & err_status)772 bool ProgressiveDecoder::BmpReadMoreData(BmpModule* pBmpModule,
773 ModuleIface::Context* pContext,
774 FXCODEC_STATUS& err_status) {
775 return ReadMoreData(pBmpModule, pContext, false, err_status);
776 }
777
BmpStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)778 FXCODEC_STATUS ProgressiveDecoder::BmpStartDecode(
779 const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
780 BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
781 if (!pBmpModule) {
782 m_pDeviceBitmap = nullptr;
783 m_pFile = nullptr;
784 m_status = FXCODEC_STATUS_ERR_MEMORY;
785 return m_status;
786 }
787 GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
788 m_ScanlineSize = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents);
789 m_pDecodeBuf.reset(FX_Alloc(uint8_t, m_ScanlineSize));
790 m_WeightHorz.Calc(m_sizeX, m_clipBox.Width());
791 m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
792 m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
793 return m_status;
794 }
795
BmpContinueDecode()796 FXCODEC_STATUS ProgressiveDecoder::BmpContinueDecode() {
797 BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
798 if (!pBmpModule) {
799 m_status = FXCODEC_STATUS_ERR_MEMORY;
800 return m_status;
801 }
802
803 BmpModule::Status read_res = pBmpModule->LoadImage(m_pBmpContext.get());
804 while (read_res == BmpModule::Status::kContinue) {
805 FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
806 if (!BmpReadMoreData(pBmpModule, m_pBmpContext.get(), error_status)) {
807 m_pDeviceBitmap = nullptr;
808 m_pFile = nullptr;
809 m_status = error_status;
810 return m_status;
811 }
812 read_res = pBmpModule->LoadImage(m_pBmpContext.get());
813 }
814
815 m_pDeviceBitmap = nullptr;
816 m_pFile = nullptr;
817 m_status = read_res == BmpModule::Status::kSuccess
818 ? FXCODEC_STATUS_DECODE_FINISH
819 : FXCODEC_STATUS_ERROR;
820 return m_status;
821 }
822 #endif // PDF_ENABLE_XFA_BMP
823
824 #ifdef PDF_ENABLE_XFA_GIF
GifReadMoreData(GifModule * pGifModule,FXCODEC_STATUS & err_status)825 bool ProgressiveDecoder::GifReadMoreData(GifModule* pGifModule,
826 FXCODEC_STATUS& err_status) {
827 if (!ReadMoreData(pGifModule, m_pGifContext.get(), m_InvalidateGifBuffer,
828 err_status)) {
829 return false;
830 }
831 m_InvalidateGifBuffer = false;
832 return true;
833 }
834
GifDetectImageTypeInBuffer()835 bool ProgressiveDecoder::GifDetectImageTypeInBuffer() {
836 GifModule* pGifModule = m_pCodecMgr->GetGifModule();
837 if (!pGifModule) {
838 m_status = FXCODEC_STATUS_ERR_MEMORY;
839 return false;
840 }
841 m_pGifContext = pGifModule->Start(this);
842 pGifModule->Input(m_pGifContext.get(), m_pCodecMemory, nullptr);
843 m_SrcComponents = 1;
844 CFX_GifDecodeStatus readResult =
845 pGifModule->ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
846 &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
847 while (readResult == CFX_GifDecodeStatus::Unfinished) {
848 FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
849 if (!GifReadMoreData(pGifModule, error_status)) {
850 m_pGifContext = nullptr;
851 m_status = error_status;
852 return false;
853 }
854 readResult =
855 pGifModule->ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
856 &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
857 }
858 if (readResult == CFX_GifDecodeStatus::Success) {
859 m_SrcBPC = 8;
860 m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
861 return true;
862 }
863 m_pGifContext = nullptr;
864 m_status = FXCODEC_STATUS_ERR_FORMAT;
865 return false;
866 }
867
GifStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)868 FXCODEC_STATUS ProgressiveDecoder::GifStartDecode(
869 const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
870 GifModule* pGifModule = m_pCodecMgr->GetGifModule();
871 if (!pGifModule) {
872 m_pDeviceBitmap = nullptr;
873 m_pFile = nullptr;
874 m_status = FXCODEC_STATUS_ERR_MEMORY;
875 return m_status;
876 }
877 m_SrcFormat = FXCodec_8bppRgb;
878 GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
879 int scanline_size = FxAlignToBoundary<4>(m_SrcWidth);
880 m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size));
881 m_WeightHorz.Calc(m_sizeX, m_clipBox.Width());
882 m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
883 m_FrameCur = 0;
884 m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
885 return m_status;
886 }
887
GifContinueDecode()888 FXCODEC_STATUS ProgressiveDecoder::GifContinueDecode() {
889 GifModule* pGifModule = m_pCodecMgr->GetGifModule();
890 if (!pGifModule) {
891 m_pDeviceBitmap = nullptr;
892 m_pFile = nullptr;
893 m_status = FXCODEC_STATUS_ERR_MEMORY;
894 return m_status;
895 }
896
897 CFX_GifDecodeStatus readRes =
898 pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur);
899 while (readRes == CFX_GifDecodeStatus::Unfinished) {
900 FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
901 if (!GifReadMoreData(pGifModule, error_status)) {
902 m_pDeviceBitmap = nullptr;
903 m_pFile = nullptr;
904 m_status = error_status;
905 return m_status;
906 }
907 readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur);
908 }
909
910 if (readRes == CFX_GifDecodeStatus::Success) {
911 m_pDeviceBitmap = nullptr;
912 m_pFile = nullptr;
913 m_status = FXCODEC_STATUS_DECODE_FINISH;
914 return m_status;
915 }
916
917 m_pDeviceBitmap = nullptr;
918 m_pFile = nullptr;
919 m_status = FXCODEC_STATUS_ERROR;
920 return m_status;
921 }
922
GifDoubleLineResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)923 void ProgressiveDecoder::GifDoubleLineResampleVert(
924 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
925 double scale_y,
926 int dest_row) {
927 int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
928 uint32_t dest_ScanOffet = m_startX * dest_Bpp;
929 int dest_top = m_startY;
930 pdfium::base::CheckedNumeric<double> scale_y2 = scale_y;
931 scale_y2 *= 2;
932 pdfium::base::CheckedNumeric<int> check_dest_row_1 = dest_row;
933 check_dest_row_1 -= scale_y2.ValueOrDie();
934 int dest_row_1 = check_dest_row_1.ValueOrDie();
935 dest_row_1 = std::max(dest_row_1, dest_top);
936 for (; dest_row_1 < dest_row; dest_row_1++) {
937 uint8_t* scan_des =
938 pDeviceBitmap->GetWritableScanline(dest_row_1) + dest_ScanOffet;
939 PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
940 const uint8_t* scan_src1 =
941 pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) +
942 dest_ScanOffet;
943 const uint8_t* scan_src2 =
944 pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) +
945 dest_ScanOffet;
946 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
947 switch (pDeviceBitmap->GetFormat()) {
948 case FXDIB_Invalid:
949 case FXDIB_1bppMask:
950 case FXDIB_1bppRgb:
951 return;
952 case FXDIB_8bppMask:
953 case FXDIB_8bppRgb: {
954 if (pDeviceBitmap->GetPalette()) {
955 return;
956 }
957 int dest_g = 0;
958 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
959 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
960 *scan_des++ = (uint8_t)(dest_g >> 16);
961 } break;
962 case FXDIB_Rgb:
963 case FXDIB_Rgb32: {
964 uint32_t dest_b = 0;
965 uint32_t dest_g = 0;
966 uint32_t dest_r = 0;
967 dest_b += pWeight->m_Weights[0] * (*scan_src1++);
968 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
969 dest_r += pWeight->m_Weights[0] * (*scan_src1++);
970 scan_src1 += dest_Bpp - 3;
971 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
972 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
973 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
974 scan_src2 += dest_Bpp - 3;
975 *scan_des++ = (uint8_t)((dest_b) >> 16);
976 *scan_des++ = (uint8_t)((dest_g) >> 16);
977 *scan_des++ = (uint8_t)((dest_r) >> 16);
978 scan_des += dest_Bpp - 3;
979 } break;
980 case FXDIB_Argb: {
981 uint32_t dest_a = 0;
982 uint32_t dest_b = 0;
983 uint32_t dest_g = 0;
984 uint32_t dest_r = 0;
985 dest_b += pWeight->m_Weights[0] * (*scan_src1++);
986 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
987 dest_r += pWeight->m_Weights[0] * (*scan_src1++);
988 dest_a += pWeight->m_Weights[0] * (*scan_src1++);
989 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
990 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
991 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
992 dest_a += pWeight->m_Weights[1] * (*scan_src2++);
993 *scan_des++ = (uint8_t)((dest_b) >> 16);
994 *scan_des++ = (uint8_t)((dest_g) >> 16);
995 *scan_des++ = (uint8_t)((dest_r) >> 16);
996 *scan_des++ = (uint8_t)((dest_a) >> 16);
997 } break;
998 default:
999 return;
1000 }
1001 }
1002 }
1003 int dest_bottom = dest_top + m_sizeY - 1;
1004 if (dest_row + (int)(2 * scale_y) >= dest_bottom &&
1005 dest_row + (int)scale_y < dest_bottom) {
1006 GifDoubleLineResampleVert(pDeviceBitmap, scale_y, dest_row + (int)scale_y);
1007 }
1008 }
1009 #endif // PDF_ENABLE_XFA_GIF
1010
JpegReadMoreData(JpegModule * pJpegModule,FXCODEC_STATUS & err_status)1011 bool ProgressiveDecoder::JpegReadMoreData(JpegModule* pJpegModule,
1012 FXCODEC_STATUS& err_status) {
1013 return ReadMoreData(pJpegModule, m_pJpegContext.get(), false, err_status);
1014 }
1015
JpegDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)1016 bool ProgressiveDecoder::JpegDetectImageTypeInBuffer(
1017 CFX_DIBAttribute* pAttribute) {
1018 JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1019 m_pJpegContext = pJpegModule->Start();
1020 if (!m_pJpegContext) {
1021 m_status = FXCODEC_STATUS_ERR_MEMORY;
1022 return false;
1023 }
1024 pJpegModule->Input(m_pJpegContext.get(), m_pCodecMemory, nullptr);
1025
1026 // Setting jump marker before calling ReadHeader, since a longjmp to
1027 // the marker indicates a fatal error.
1028 if (setjmp(pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
1029 m_pJpegContext.reset();
1030 m_status = FXCODEC_STATUS_ERR_FORMAT;
1031 return false;
1032 }
1033
1034 int32_t readResult =
1035 pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight,
1036 &m_SrcComponents, pAttribute);
1037 while (readResult == 2) {
1038 FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
1039 if (!JpegReadMoreData(pJpegModule, error_status)) {
1040 m_status = error_status;
1041 return false;
1042 }
1043 readResult =
1044 pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight,
1045 &m_SrcComponents, pAttribute);
1046 }
1047 if (!readResult) {
1048 m_SrcBPC = 8;
1049 m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1050 return true;
1051 }
1052 m_pJpegContext.reset();
1053 m_status = FXCODEC_STATUS_ERR_FORMAT;
1054 return false;
1055 }
1056
JpegStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)1057 FXCODEC_STATUS ProgressiveDecoder::JpegStartDecode(
1058 const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
1059 JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1060 int down_scale = 1;
1061 GetDownScale(down_scale);
1062 // Setting jump marker before calling StartScanLine, since a longjmp to
1063 // the marker indicates a fatal error.
1064 if (setjmp(pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
1065 m_pJpegContext.reset();
1066 m_status = FXCODEC_STATUS_ERROR;
1067 return FXCODEC_STATUS_ERROR;
1068 }
1069
1070 bool startStatus =
1071 pJpegModule->StartScanline(m_pJpegContext.get(), down_scale);
1072 while (!startStatus) {
1073 FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
1074 if (!JpegReadMoreData(pJpegModule, error_status)) {
1075 m_pDeviceBitmap = nullptr;
1076 m_pFile = nullptr;
1077 m_status = error_status;
1078 return m_status;
1079 }
1080
1081 startStatus = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale);
1082 }
1083 int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale;
1084 scanline_size = FxAlignToBoundary<4>(scanline_size * m_SrcComponents);
1085 m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size));
1086 m_WeightHorz.Calc(m_sizeX, m_clipBox.Width());
1087 m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
1088 switch (m_SrcComponents) {
1089 case 1:
1090 m_SrcFormat = FXCodec_8bppGray;
1091 break;
1092 case 3:
1093 m_SrcFormat = FXCodec_Rgb;
1094 break;
1095 case 4:
1096 m_SrcFormat = FXCodec_Cmyk;
1097 break;
1098 }
1099 GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat);
1100 m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1101 return m_status;
1102 }
1103
JpegContinueDecode()1104 FXCODEC_STATUS ProgressiveDecoder::JpegContinueDecode() {
1105 JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1106 // Setting jump marker before calling ReadScanLine, since a longjmp to
1107 // the marker indicates a fatal error.
1108 if (setjmp(pJpegModule->GetJumpMark(m_pJpegContext.get())) == -1) {
1109 m_pJpegContext.reset();
1110 m_status = FXCODEC_STATUS_ERROR;
1111 return FXCODEC_STATUS_ERROR;
1112 }
1113
1114 while (true) {
1115 bool readRes =
1116 pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf.get());
1117 while (!readRes) {
1118 FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
1119 if (!JpegReadMoreData(pJpegModule, error_status)) {
1120 m_pDeviceBitmap = nullptr;
1121 m_pFile = nullptr;
1122 m_status = error_status;
1123 return m_status;
1124 }
1125 readRes =
1126 pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf.get());
1127 }
1128 if (m_SrcFormat == FXCodec_Rgb) {
1129 int src_Bpp = (m_SrcFormat & 0xff) >> 3;
1130 RGB2BGR(m_pDecodeBuf.get() + m_clipBox.left * src_Bpp, m_clipBox.Width());
1131 }
1132 if (m_SrcRow >= m_clipBox.bottom) {
1133 m_pDeviceBitmap = nullptr;
1134 m_pFile = nullptr;
1135 m_status = FXCODEC_STATUS_DECODE_FINISH;
1136 return m_status;
1137 }
1138 Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf.get(), m_SrcFormat);
1139 m_SrcRow++;
1140 }
1141 }
1142
1143 #ifdef PDF_ENABLE_XFA_PNG
PngOneOneMapResampleHorz(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int32_t dest_line,uint8_t * src_scan,FXCodec_Format src_format)1144 void ProgressiveDecoder::PngOneOneMapResampleHorz(
1145 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1146 int32_t dest_line,
1147 uint8_t* src_scan,
1148 FXCodec_Format src_format) {
1149 uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line);
1150 int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3;
1151 int32_t dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
1152 int32_t src_left = m_clipBox.left;
1153 int32_t dest_left = m_startX;
1154 src_scan += src_left * src_Bpp;
1155 dest_scan += dest_left * dest_Bpp;
1156 for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) {
1157 PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col);
1158 switch (pDeviceBitmap->GetFormat()) {
1159 case FXDIB_1bppMask:
1160 case FXDIB_1bppRgb:
1161 NOTREACHED();
1162 return;
1163 case FXDIB_8bppMask:
1164 case FXDIB_8bppRgb: {
1165 if (pDeviceBitmap->GetPalette()) {
1166 return;
1167 }
1168 uint32_t dest_g = 0;
1169 dest_g +=
1170 pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart];
1171 dest_g +=
1172 pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd];
1173 *dest_scan++ = (uint8_t)(dest_g >> 16);
1174 } break;
1175 case FXDIB_Rgb:
1176 case FXDIB_Rgb32: {
1177 uint32_t dest_b = 0;
1178 uint32_t dest_g = 0;
1179 uint32_t dest_r = 0;
1180 const uint8_t* p = src_scan;
1181 p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
1182 dest_b += pPixelWeights->m_Weights[0] * (*p++);
1183 dest_g += pPixelWeights->m_Weights[0] * (*p++);
1184 dest_r += pPixelWeights->m_Weights[0] * (*p);
1185 p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
1186 dest_b += pPixelWeights->m_Weights[1] * (*p++);
1187 dest_g += pPixelWeights->m_Weights[1] * (*p++);
1188 dest_r += pPixelWeights->m_Weights[1] * (*p);
1189 *dest_scan++ = (uint8_t)((dest_b) >> 16);
1190 *dest_scan++ = (uint8_t)((dest_g) >> 16);
1191 *dest_scan++ = (uint8_t)((dest_r) >> 16);
1192 dest_scan += dest_Bpp - 3;
1193 } break;
1194 case FXDIB_Argb: {
1195 uint32_t dest_a = 0;
1196 uint32_t dest_b = 0;
1197 uint32_t dest_g = 0;
1198 uint32_t dest_r = 0;
1199 const uint8_t* p = src_scan;
1200 p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
1201 dest_b += pPixelWeights->m_Weights[0] * (*p++);
1202 dest_g += pPixelWeights->m_Weights[0] * (*p++);
1203 dest_r += pPixelWeights->m_Weights[0] * (*p++);
1204 dest_a += pPixelWeights->m_Weights[0] * (*p);
1205 p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
1206 dest_b += pPixelWeights->m_Weights[1] * (*p++);
1207 dest_g += pPixelWeights->m_Weights[1] * (*p++);
1208 dest_r += pPixelWeights->m_Weights[1] * (*p++);
1209 dest_a += pPixelWeights->m_Weights[1] * (*p);
1210 *dest_scan++ = (uint8_t)((dest_b) >> 16);
1211 *dest_scan++ = (uint8_t)((dest_g) >> 16);
1212 *dest_scan++ = (uint8_t)((dest_r) >> 16);
1213 *dest_scan++ = (uint8_t)((dest_a) >> 16);
1214 } break;
1215 default:
1216 return;
1217 }
1218 }
1219 }
1220
PngDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)1221 bool ProgressiveDecoder::PngDetectImageTypeInBuffer(
1222 CFX_DIBAttribute* pAttribute) {
1223 PngModule* pPngModule = m_pCodecMgr->GetPngModule();
1224 if (!pPngModule) {
1225 m_status = FXCODEC_STATUS_ERR_MEMORY;
1226 return false;
1227 }
1228 m_pPngContext = pPngModule->Start(this);
1229 if (!m_pPngContext) {
1230 m_status = FXCODEC_STATUS_ERR_MEMORY;
1231 return false;
1232 }
1233 while (pPngModule->Input(m_pPngContext.get(), m_pCodecMemory, pAttribute)) {
1234 uint32_t remain_size = static_cast<uint32_t>(m_pFile->GetSize()) - m_offSet;
1235 uint32_t input_size = std::min<uint32_t>(remain_size, kBlockSize);
1236 if (input_size == 0) {
1237 m_pPngContext.reset();
1238 m_status = FXCODEC_STATUS_ERR_FORMAT;
1239 return false;
1240 }
1241 if (m_pCodecMemory && input_size > m_pCodecMemory->GetSize())
1242 m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(input_size);
1243
1244 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBuffer(), m_offSet,
1245 input_size)) {
1246 m_status = FXCODEC_STATUS_ERR_READ;
1247 return false;
1248 }
1249 m_offSet += input_size;
1250 }
1251 m_pPngContext.reset();
1252 if (m_SrcPassNumber == 0) {
1253 m_status = FXCODEC_STATUS_ERR_FORMAT;
1254 return false;
1255 }
1256 return true;
1257 }
1258
PngStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)1259 FXCODEC_STATUS ProgressiveDecoder::PngStartDecode(
1260 const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
1261 PngModule* pPngModule = m_pCodecMgr->GetPngModule();
1262 if (!pPngModule) {
1263 m_pDeviceBitmap = nullptr;
1264 m_pFile = nullptr;
1265 m_status = FXCODEC_STATUS_ERR_MEMORY;
1266 return m_status;
1267 }
1268 m_pPngContext = pPngModule->Start(this);
1269 if (!m_pPngContext) {
1270 m_pDeviceBitmap = nullptr;
1271 m_pFile = nullptr;
1272 m_status = FXCODEC_STATUS_ERR_MEMORY;
1273 return m_status;
1274 }
1275 m_offSet = 0;
1276 switch (m_pDeviceBitmap->GetFormat()) {
1277 case FXDIB_8bppMask:
1278 case FXDIB_8bppRgb:
1279 m_SrcComponents = 1;
1280 m_SrcFormat = FXCodec_8bppGray;
1281 break;
1282 case FXDIB_Rgb:
1283 m_SrcComponents = 3;
1284 m_SrcFormat = FXCodec_Rgb;
1285 break;
1286 case FXDIB_Rgb32:
1287 case FXDIB_Argb:
1288 m_SrcComponents = 4;
1289 m_SrcFormat = FXCodec_Argb;
1290 break;
1291 default: {
1292 m_pDeviceBitmap = nullptr;
1293 m_pFile = nullptr;
1294 m_status = FXCODEC_STATUS_ERR_PARAMS;
1295 return m_status;
1296 }
1297 }
1298 GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
1299 int scanline_size = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents);
1300 m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size));
1301 m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width());
1302 m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
1303 m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1304 return m_status;
1305 }
1306
PngContinueDecode()1307 FXCODEC_STATUS ProgressiveDecoder::PngContinueDecode() {
1308 PngModule* pPngModule = m_pCodecMgr->GetPngModule();
1309 if (!pPngModule) {
1310 m_status = FXCODEC_STATUS_ERR_MEMORY;
1311 return m_status;
1312 }
1313 while (true) {
1314 uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet;
1315 uint32_t input_size = std::min<uint32_t>(remain_size, kBlockSize);
1316 if (input_size == 0) {
1317 m_pPngContext.reset();
1318 m_pDeviceBitmap = nullptr;
1319 m_pFile = nullptr;
1320 m_status = FXCODEC_STATUS_DECODE_FINISH;
1321 return m_status;
1322 }
1323 if (m_pCodecMemory && input_size > m_pCodecMemory->GetSize())
1324 m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(input_size);
1325
1326 bool bResult = m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBuffer(),
1327 m_offSet, input_size);
1328 if (!bResult) {
1329 m_pDeviceBitmap = nullptr;
1330 m_pFile = nullptr;
1331 m_status = FXCODEC_STATUS_ERR_READ;
1332 return m_status;
1333 }
1334 m_offSet += input_size;
1335 bResult = pPngModule->Input(m_pPngContext.get(), m_pCodecMemory, nullptr);
1336 if (!bResult) {
1337 m_pDeviceBitmap = nullptr;
1338 m_pFile = nullptr;
1339 m_status = FXCODEC_STATUS_ERROR;
1340 return m_status;
1341 }
1342 }
1343 }
1344 #endif // PDF_ENABLE_XFA_PNG
1345
1346 #ifdef PDF_ENABLE_XFA_TIFF
TiffDetectImageTypeFromFile(CFX_DIBAttribute * pAttribute)1347 bool ProgressiveDecoder::TiffDetectImageTypeFromFile(
1348 CFX_DIBAttribute* pAttribute) {
1349 TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule();
1350 if (!pTiffModule) {
1351 m_status = FXCODEC_STATUS_ERR_FORMAT;
1352 return false;
1353 }
1354 m_pTiffContext = pTiffModule->CreateDecoder(m_pFile);
1355 if (!m_pTiffContext) {
1356 m_status = FXCODEC_STATUS_ERR_FORMAT;
1357 return false;
1358 }
1359 int32_t dummy_bpc;
1360 bool ret = pTiffModule->LoadFrameInfo(m_pTiffContext.get(), 0, &m_SrcWidth,
1361 &m_SrcHeight, &m_SrcComponents,
1362 &dummy_bpc, pAttribute);
1363 m_SrcComponents = 4;
1364 m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1365 if (!ret) {
1366 m_pTiffContext.reset();
1367 m_status = FXCODEC_STATUS_ERR_FORMAT;
1368 return false;
1369 }
1370 return true;
1371 }
1372
TiffContinueDecode()1373 FXCODEC_STATUS ProgressiveDecoder::TiffContinueDecode() {
1374 TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule();
1375 if (!pTiffModule) {
1376 m_status = FXCODEC_STATUS_ERR_MEMORY;
1377 return m_status;
1378 }
1379 bool ret = false;
1380 if (m_pDeviceBitmap->GetBPP() == 32 &&
1381 m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX &&
1382 m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY &&
1383 m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 &&
1384 m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth &&
1385 m_clipBox.bottom == m_SrcHeight) {
1386 ret = pTiffModule->Decode(m_pTiffContext.get(), m_pDeviceBitmap);
1387 m_pDeviceBitmap = nullptr;
1388 m_pFile = nullptr;
1389 if (!ret) {
1390 m_status = FXCODEC_STATUS_ERROR;
1391 return m_status;
1392 }
1393 m_status = FXCODEC_STATUS_DECODE_FINISH;
1394 return m_status;
1395 }
1396
1397 auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1398 pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb);
1399 if (!pDIBitmap->GetBuffer()) {
1400 m_pDeviceBitmap = nullptr;
1401 m_pFile = nullptr;
1402 m_status = FXCODEC_STATUS_ERR_MEMORY;
1403 return m_status;
1404 }
1405 ret = pTiffModule->Decode(m_pTiffContext.get(), pDIBitmap);
1406 if (!ret) {
1407 m_pDeviceBitmap = nullptr;
1408 m_pFile = nullptr;
1409 m_status = FXCODEC_STATUS_ERROR;
1410 return m_status;
1411 }
1412 RetainPtr<CFX_DIBitmap> pClipBitmap =
1413 (m_clipBox.left == 0 && m_clipBox.top == 0 &&
1414 m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight)
1415 ? pDIBitmap
1416 : pDIBitmap->Clone(&m_clipBox);
1417 if (!pClipBitmap) {
1418 m_pDeviceBitmap = nullptr;
1419 m_pFile = nullptr;
1420 m_status = FXCODEC_STATUS_ERR_MEMORY;
1421 return m_status;
1422 }
1423 RetainPtr<CFX_DIBitmap> pFormatBitmap;
1424 switch (m_pDeviceBitmap->GetFormat()) {
1425 case FXDIB_8bppRgb:
1426 pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1427 pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1428 FXDIB_8bppRgb);
1429 break;
1430 case FXDIB_8bppMask:
1431 pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1432 pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1433 FXDIB_8bppMask);
1434 break;
1435 case FXDIB_Rgb:
1436 pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1437 pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1438 FXDIB_Rgb);
1439 break;
1440 case FXDIB_Rgb32:
1441 pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1442 pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1443 FXDIB_Rgb32);
1444 break;
1445 case FXDIB_Argb:
1446 pFormatBitmap = pClipBitmap;
1447 break;
1448 default:
1449 break;
1450 }
1451 switch (m_pDeviceBitmap->GetFormat()) {
1452 case FXDIB_8bppRgb:
1453 case FXDIB_8bppMask: {
1454 for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1455 const uint8_t* src_line = pClipBitmap->GetScanline(row);
1456 uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row);
1457 for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1458 uint8_t _a = 255 - src_line[3];
1459 uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1460 uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1461 uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1462 *dest_line++ = FXRGB2GRAY(r, g, b);
1463 src_line += 4;
1464 }
1465 }
1466 } break;
1467 case FXDIB_Rgb:
1468 case FXDIB_Rgb32: {
1469 int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4;
1470 for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1471 const uint8_t* src_line = pClipBitmap->GetScanline(row);
1472 uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row);
1473 for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1474 uint8_t _a = 255 - src_line[3];
1475 uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1476 uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1477 uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1478 *dest_line++ = b;
1479 *dest_line++ = g;
1480 *dest_line++ = r;
1481 dest_line += desBpp - 3;
1482 src_line += 4;
1483 }
1484 }
1485 } break;
1486 default:
1487 break;
1488 }
1489 if (!pFormatBitmap) {
1490 m_pDeviceBitmap = nullptr;
1491 m_pFile = nullptr;
1492 m_status = FXCODEC_STATUS_ERR_MEMORY;
1493 return m_status;
1494 }
1495
1496 FXDIB_ResampleOptions options;
1497 options.bInterpolateBilinear = true;
1498 RetainPtr<CFX_DIBitmap> pStrechBitmap =
1499 pFormatBitmap->StretchTo(m_sizeX, m_sizeY, options, nullptr);
1500 pFormatBitmap = nullptr;
1501 if (!pStrechBitmap) {
1502 m_pDeviceBitmap = nullptr;
1503 m_pFile = nullptr;
1504 m_status = FXCODEC_STATUS_ERR_MEMORY;
1505 return m_status;
1506 }
1507 m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY,
1508 pStrechBitmap, 0, 0);
1509 m_pDeviceBitmap = nullptr;
1510 m_pFile = nullptr;
1511 m_status = FXCODEC_STATUS_DECODE_FINISH;
1512 return m_status;
1513 }
1514 #endif // PDF_ENABLE_XFA_TIFF
1515
DetectImageType(FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute)1516 bool ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType,
1517 CFX_DIBAttribute* pAttribute) {
1518 #ifdef PDF_ENABLE_XFA_TIFF
1519 if (imageType == FXCODEC_IMAGE_TIFF)
1520 return TiffDetectImageTypeFromFile(pAttribute);
1521 #endif // PDF_ENABLE_XFA_TIFF
1522
1523 size_t size = std::min<size_t>(m_pFile->GetSize(), kBlockSize);
1524 m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(size);
1525 m_offSet = 0;
1526 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBuffer(), m_offSet,
1527 size)) {
1528 m_status = FXCODEC_STATUS_ERR_READ;
1529 return false;
1530 }
1531 m_offSet += size;
1532
1533 if (imageType == FXCODEC_IMAGE_JPG)
1534 return JpegDetectImageTypeInBuffer(pAttribute);
1535
1536 #ifdef PDF_ENABLE_XFA_BMP
1537 if (imageType == FXCODEC_IMAGE_BMP)
1538 return BmpDetectImageTypeInBuffer(pAttribute);
1539 #endif // PDF_ENABLE_XFA_BMP
1540
1541 #ifdef PDF_ENABLE_XFA_GIF
1542 if (imageType == FXCODEC_IMAGE_GIF)
1543 return GifDetectImageTypeInBuffer();
1544 #endif // PDF_ENABLE_XFA_GIF
1545
1546 #ifdef PDF_ENABLE_XFA_PNG
1547 if (imageType == FXCODEC_IMAGE_PNG)
1548 return PngDetectImageTypeInBuffer(pAttribute);
1549 #endif // PDF_ENABLE_XFA_PNG
1550
1551 m_status = FXCODEC_STATUS_ERR_FORMAT;
1552 return false;
1553 }
1554
ReadMoreData(ModuleIface * pModule,ModuleIface::Context * pContext,bool invalidate_buffer,FXCODEC_STATUS & err_status)1555 bool ProgressiveDecoder::ReadMoreData(ModuleIface* pModule,
1556 ModuleIface::Context* pContext,
1557 bool invalidate_buffer,
1558 FXCODEC_STATUS& err_status) {
1559 // Check for EOF.
1560 if (m_offSet >= static_cast<uint32_t>(m_pFile->GetSize()))
1561 return false;
1562
1563 // Try to get whatever remains.
1564 uint32_t dwBytesToFetchFromFile = m_pFile->GetSize() - m_offSet;
1565
1566 // Figure out if the codec stopped processing midway through the buffer.
1567 size_t dwUnconsumed = 0;
1568 if (!invalidate_buffer) {
1569 FX_SAFE_SIZE_T avail_input = pModule->GetAvailInput(pContext);
1570 if (!avail_input.IsValid())
1571 return false;
1572 dwUnconsumed = avail_input.ValueOrDie();
1573 }
1574
1575 if (dwUnconsumed == m_pCodecMemory->GetSize()) {
1576 // Codec couldn't make any progress against the bytes in the buffer.
1577 // Increase the buffer size so that there might be enough contiguous
1578 // bytes to allow whatever operation is having difficulty to succeed.
1579 dwBytesToFetchFromFile =
1580 std::min<uint32_t>(dwBytesToFetchFromFile, kBlockSize);
1581 size_t dwNewSize = m_pCodecMemory->GetSize() + dwBytesToFetchFromFile;
1582 if (!m_pCodecMemory->TryResize(dwNewSize)) {
1583 err_status = FXCODEC_STATUS_ERR_MEMORY;
1584 return false;
1585 }
1586 } else {
1587 size_t dwConsumed = m_pCodecMemory->GetSize() - dwUnconsumed;
1588 m_pCodecMemory->Consume(dwConsumed);
1589 dwBytesToFetchFromFile =
1590 std::min<uint32_t>(dwBytesToFetchFromFile, dwConsumed);
1591 }
1592
1593 // Append new data past the bytes not yet processed by the codec.
1594 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBuffer() + dwUnconsumed,
1595 m_offSet, dwBytesToFetchFromFile)) {
1596 err_status = FXCODEC_STATUS_ERR_READ;
1597 return false;
1598 }
1599 m_offSet += dwBytesToFetchFromFile;
1600 return pModule->Input(pContext, m_pCodecMemory, nullptr);
1601 }
1602
LoadImageInfo(const RetainPtr<IFX_SeekableReadStream> & pFile,FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute,bool bSkipImageTypeCheck)1603 FXCODEC_STATUS ProgressiveDecoder::LoadImageInfo(
1604 const RetainPtr<IFX_SeekableReadStream>& pFile,
1605 FXCODEC_IMAGE_TYPE imageType,
1606 CFX_DIBAttribute* pAttribute,
1607 bool bSkipImageTypeCheck) {
1608 ASSERT(pAttribute);
1609
1610 switch (m_status) {
1611 case FXCODEC_STATUS_FRAME_READY:
1612 case FXCODEC_STATUS_FRAME_TOBECONTINUE:
1613 case FXCODEC_STATUS_DECODE_READY:
1614 case FXCODEC_STATUS_DECODE_TOBECONTINUE:
1615 return FXCODEC_STATUS_ERROR;
1616 default:
1617 break;
1618 }
1619 if (!pFile) {
1620 m_status = FXCODEC_STATUS_ERR_PARAMS;
1621 m_pFile = nullptr;
1622 return m_status;
1623 }
1624 m_pFile = pFile;
1625 m_offSet = 0;
1626 m_SrcWidth = m_SrcHeight = 0;
1627 m_SrcComponents = m_SrcBPC = 0;
1628 m_clipBox = FX_RECT();
1629 m_startX = m_startY = 0;
1630 m_sizeX = m_sizeY = 0;
1631 m_SrcPassNumber = 0;
1632 if (imageType != FXCODEC_IMAGE_UNKNOWN &&
1633 DetectImageType(imageType, pAttribute)) {
1634 m_imageType = imageType;
1635 m_status = FXCODEC_STATUS_FRAME_READY;
1636 return m_status;
1637 }
1638 // If we got here then the image data does not match the requested decoder.
1639 // If we're skipping the type check then bail out at this point and return
1640 // the failed status.
1641 if (bSkipImageTypeCheck)
1642 return m_status;
1643
1644 for (int type = FXCODEC_IMAGE_UNKNOWN + 1; type < FXCODEC_IMAGE_MAX; type++) {
1645 if (DetectImageType(static_cast<FXCODEC_IMAGE_TYPE>(type), pAttribute)) {
1646 m_imageType = static_cast<FXCODEC_IMAGE_TYPE>(type);
1647 m_status = FXCODEC_STATUS_FRAME_READY;
1648 return m_status;
1649 }
1650 }
1651 m_status = FXCODEC_STATUS_ERR_FORMAT;
1652 m_pFile = nullptr;
1653 return m_status;
1654 }
1655
SetClipBox(FX_RECT * clip)1656 void ProgressiveDecoder::SetClipBox(FX_RECT* clip) {
1657 if (m_status != FXCODEC_STATUS_FRAME_READY)
1658 return;
1659
1660 if (clip->IsEmpty()) {
1661 m_clipBox = FX_RECT();
1662 return;
1663 }
1664 clip->left = std::max(clip->left, 0);
1665 clip->right = std::min(clip->right, m_SrcWidth);
1666 clip->top = std::max(clip->top, 0);
1667 clip->bottom = std::min(clip->bottom, m_SrcHeight);
1668 if (clip->IsEmpty()) {
1669 m_clipBox = FX_RECT();
1670 return;
1671 }
1672 m_clipBox = *clip;
1673 }
1674
GetDownScale(int & down_scale)1675 void ProgressiveDecoder::GetDownScale(int& down_scale) {
1676 down_scale = 1;
1677 int ratio_w = m_clipBox.Width() / m_sizeX;
1678 int ratio_h = m_clipBox.Height() / m_sizeY;
1679 int ratio = (ratio_w > ratio_h) ? ratio_h : ratio_w;
1680 if (ratio >= 8) {
1681 down_scale = 8;
1682 } else if (ratio >= 4) {
1683 down_scale = 4;
1684 } else if (ratio >= 2) {
1685 down_scale = 2;
1686 }
1687 m_clipBox.left /= down_scale;
1688 m_clipBox.right /= down_scale;
1689 m_clipBox.top /= down_scale;
1690 m_clipBox.bottom /= down_scale;
1691 if (m_clipBox.right == m_clipBox.left) {
1692 m_clipBox.right = m_clipBox.left + 1;
1693 }
1694 if (m_clipBox.bottom == m_clipBox.top) {
1695 m_clipBox.bottom = m_clipBox.top + 1;
1696 }
1697 }
1698
GetTransMethod(FXDIB_Format dest_format,FXCodec_Format src_format)1699 void ProgressiveDecoder::GetTransMethod(FXDIB_Format dest_format,
1700 FXCodec_Format src_format) {
1701 switch (dest_format) {
1702 case FXDIB_1bppMask:
1703 case FXDIB_1bppRgb: {
1704 switch (src_format) {
1705 case FXCodec_1bppGray:
1706 m_TransMethod = 0;
1707 break;
1708 default:
1709 m_TransMethod = -1;
1710 }
1711 } break;
1712 case FXDIB_8bppMask:
1713 case FXDIB_8bppRgb: {
1714 switch (src_format) {
1715 case FXCodec_1bppGray:
1716 m_TransMethod = 1;
1717 break;
1718 case FXCodec_8bppGray:
1719 m_TransMethod = 2;
1720 break;
1721 case FXCodec_1bppRgb:
1722 case FXCodec_8bppRgb:
1723 m_TransMethod = 3;
1724 break;
1725 case FXCodec_Rgb:
1726 case FXCodec_Rgb32:
1727 case FXCodec_Argb:
1728 m_TransMethod = 4;
1729 break;
1730 case FXCodec_Cmyk:
1731 m_TransMethod = 5;
1732 break;
1733 default:
1734 m_TransMethod = -1;
1735 }
1736 } break;
1737 case FXDIB_Rgb: {
1738 switch (src_format) {
1739 case FXCodec_1bppGray:
1740 m_TransMethod = 6;
1741 break;
1742 case FXCodec_8bppGray:
1743 m_TransMethod = 7;
1744 break;
1745 case FXCodec_1bppRgb:
1746 case FXCodec_8bppRgb:
1747 m_TransMethod = 8;
1748 break;
1749 case FXCodec_Rgb:
1750 case FXCodec_Rgb32:
1751 case FXCodec_Argb:
1752 m_TransMethod = 9;
1753 break;
1754 case FXCodec_Cmyk:
1755 m_TransMethod = 10;
1756 break;
1757 default:
1758 m_TransMethod = -1;
1759 }
1760 } break;
1761 case FXDIB_Rgb32:
1762 case FXDIB_Argb: {
1763 switch (src_format) {
1764 case FXCodec_1bppGray:
1765 m_TransMethod = 6;
1766 break;
1767 case FXCodec_8bppGray:
1768 m_TransMethod = 7;
1769 break;
1770 case FXCodec_1bppRgb:
1771 case FXCodec_8bppRgb:
1772 if (dest_format == FXDIB_Argb) {
1773 m_TransMethod = 12;
1774 } else {
1775 m_TransMethod = 8;
1776 }
1777 break;
1778 case FXCodec_Rgb:
1779 case FXCodec_Rgb32:
1780 m_TransMethod = 9;
1781 break;
1782 case FXCodec_Cmyk:
1783 m_TransMethod = 10;
1784 break;
1785 case FXCodec_Argb:
1786 m_TransMethod = 11;
1787 break;
1788 default:
1789 m_TransMethod = -1;
1790 }
1791 } break;
1792 default:
1793 m_TransMethod = -1;
1794 }
1795 }
1796
ReSampleScanline(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int dest_line,uint8_t * src_scan,FXCodec_Format src_format)1797 void ProgressiveDecoder::ReSampleScanline(
1798 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1799 int dest_line,
1800 uint8_t* src_scan,
1801 FXCodec_Format src_format) {
1802 int src_left = m_clipBox.left;
1803 int dest_left = m_startX;
1804 uint8_t* dest_scan =
1805 pDeviceBitmap->GetBuffer() + dest_line * pDeviceBitmap->GetPitch();
1806 int src_bytes_per_pixel = (src_format & 0xff) / 8;
1807 int dest_bytes_per_pixel = pDeviceBitmap->GetBPP() / 8;
1808 src_scan += src_left * src_bytes_per_pixel;
1809 dest_scan += dest_left * dest_bytes_per_pixel;
1810 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1811 PixelWeight* pPixelWeights = m_WeightHorz.GetPixelWeight(dest_col);
1812 switch (m_TransMethod) {
1813 case -1:
1814 return;
1815 case 0:
1816 return;
1817 case 1:
1818 return;
1819 case 2: {
1820 uint32_t dest_g = 0;
1821 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1822 j++) {
1823 int pixel_weight =
1824 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1825 dest_g += pixel_weight * src_scan[j];
1826 }
1827 *dest_scan++ = (uint8_t)(dest_g >> 16);
1828 } break;
1829 case 3: {
1830 int dest_r = 0;
1831 int dest_g = 0;
1832 int dest_b = 0;
1833 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1834 j++) {
1835 int pixel_weight =
1836 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1837 unsigned long argb = m_pSrcPalette.get()[src_scan[j]];
1838 dest_r += pixel_weight * FXARGB_R(argb);
1839 dest_g += pixel_weight * FXARGB_G(argb);
1840 dest_b += pixel_weight * FXARGB_B(argb);
1841 }
1842 *dest_scan++ =
1843 (uint8_t)FXRGB2GRAY((dest_r >> 16), (dest_g >> 16), (dest_b >> 16));
1844 } break;
1845 case 4: {
1846 uint32_t dest_b = 0;
1847 uint32_t dest_g = 0;
1848 uint32_t dest_r = 0;
1849 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1850 j++) {
1851 int pixel_weight =
1852 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1853 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1854 dest_b += pixel_weight * (*src_pixel++);
1855 dest_g += pixel_weight * (*src_pixel++);
1856 dest_r += pixel_weight * (*src_pixel);
1857 }
1858 *dest_scan++ =
1859 (uint8_t)FXRGB2GRAY((dest_r >> 16), (dest_g >> 16), (dest_b >> 16));
1860 } break;
1861 case 5: {
1862 uint32_t dest_b = 0;
1863 uint32_t dest_g = 0;
1864 uint32_t dest_r = 0;
1865 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1866 j++) {
1867 int pixel_weight =
1868 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1869 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1870 uint8_t src_b = 0;
1871 uint8_t src_g = 0;
1872 uint8_t src_r = 0;
1873 std::tie(src_r, src_g, src_b) =
1874 AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1875 255 - src_pixel[2], 255 - src_pixel[3]);
1876 dest_b += pixel_weight * src_b;
1877 dest_g += pixel_weight * src_g;
1878 dest_r += pixel_weight * src_r;
1879 }
1880 *dest_scan++ =
1881 (uint8_t)FXRGB2GRAY((dest_r >> 16), (dest_g >> 16), (dest_b >> 16));
1882 } break;
1883 case 6:
1884 return;
1885 case 7: {
1886 uint32_t dest_g = 0;
1887 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1888 j++) {
1889 int pixel_weight =
1890 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1891 dest_g += pixel_weight * src_scan[j];
1892 }
1893 memset(dest_scan, (uint8_t)(dest_g >> 16), 3);
1894 dest_scan += dest_bytes_per_pixel;
1895 } break;
1896 case 8: {
1897 int dest_r = 0;
1898 int dest_g = 0;
1899 int dest_b = 0;
1900 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1901 j++) {
1902 int pixel_weight =
1903 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1904 unsigned long argb = m_pSrcPalette.get()[src_scan[j]];
1905 dest_r += pixel_weight * FXARGB_R(argb);
1906 dest_g += pixel_weight * FXARGB_G(argb);
1907 dest_b += pixel_weight * FXARGB_B(argb);
1908 }
1909 *dest_scan++ = (uint8_t)((dest_b) >> 16);
1910 *dest_scan++ = (uint8_t)((dest_g) >> 16);
1911 *dest_scan++ = (uint8_t)((dest_r) >> 16);
1912 dest_scan += dest_bytes_per_pixel - 3;
1913 } break;
1914 case 12: {
1915 #ifdef PDF_ENABLE_XFA_BMP
1916 if (m_pBmpContext) {
1917 int dest_r = 0;
1918 int dest_g = 0;
1919 int dest_b = 0;
1920 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1921 j++) {
1922 int pixel_weight =
1923 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1924 unsigned long argb = m_pSrcPalette.get()[src_scan[j]];
1925 dest_r += pixel_weight * FXARGB_R(argb);
1926 dest_g += pixel_weight * FXARGB_G(argb);
1927 dest_b += pixel_weight * FXARGB_B(argb);
1928 }
1929 *dest_scan++ = (uint8_t)((dest_b) >> 16);
1930 *dest_scan++ = (uint8_t)((dest_g) >> 16);
1931 *dest_scan++ = (uint8_t)((dest_r) >> 16);
1932 *dest_scan++ = 0xFF;
1933 break;
1934 }
1935 #endif // PDF_ENABLE_XFA_BMP
1936 int dest_a = 0;
1937 int dest_r = 0;
1938 int dest_g = 0;
1939 int dest_b = 0;
1940 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1941 j++) {
1942 int pixel_weight =
1943 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1944 unsigned long argb = m_pSrcPalette.get()[src_scan[j]];
1945 dest_a += pixel_weight * FXARGB_A(argb);
1946 dest_r += pixel_weight * FXARGB_R(argb);
1947 dest_g += pixel_weight * FXARGB_G(argb);
1948 dest_b += pixel_weight * FXARGB_B(argb);
1949 }
1950 *dest_scan++ = (uint8_t)((dest_b) >> 16);
1951 *dest_scan++ = (uint8_t)((dest_g) >> 16);
1952 *dest_scan++ = (uint8_t)((dest_r) >> 16);
1953 *dest_scan++ = (uint8_t)((dest_a) >> 16);
1954 } break;
1955 case 9: {
1956 uint32_t dest_b = 0;
1957 uint32_t dest_g = 0;
1958 uint32_t dest_r = 0;
1959 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1960 j++) {
1961 int pixel_weight =
1962 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1963 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1964 dest_b += pixel_weight * (*src_pixel++);
1965 dest_g += pixel_weight * (*src_pixel++);
1966 dest_r += pixel_weight * (*src_pixel);
1967 }
1968 *dest_scan++ = (uint8_t)((dest_b) >> 16);
1969 *dest_scan++ = (uint8_t)((dest_g) >> 16);
1970 *dest_scan++ = (uint8_t)((dest_r) >> 16);
1971 dest_scan += dest_bytes_per_pixel - 3;
1972 } break;
1973 case 10: {
1974 uint32_t dest_b = 0;
1975 uint32_t dest_g = 0;
1976 uint32_t dest_r = 0;
1977 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1978 j++) {
1979 int pixel_weight =
1980 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1981 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1982 uint8_t src_b = 0;
1983 uint8_t src_g = 0;
1984 uint8_t src_r = 0;
1985 std::tie(src_r, src_g, src_b) =
1986 AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1987 255 - src_pixel[2], 255 - src_pixel[3]);
1988 dest_b += pixel_weight * src_b;
1989 dest_g += pixel_weight * src_g;
1990 dest_r += pixel_weight * src_r;
1991 }
1992 *dest_scan++ = (uint8_t)((dest_b) >> 16);
1993 *dest_scan++ = (uint8_t)((dest_g) >> 16);
1994 *dest_scan++ = (uint8_t)((dest_r) >> 16);
1995 dest_scan += dest_bytes_per_pixel - 3;
1996 } break;
1997 case 11: {
1998 uint32_t dest_alpha = 0;
1999 uint32_t dest_r = 0;
2000 uint32_t dest_g = 0;
2001 uint32_t dest_b = 0;
2002 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
2003 j++) {
2004 int pixel_weight =
2005 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
2006 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
2007 pixel_weight = pixel_weight * src_pixel[3] / 255;
2008 dest_b += pixel_weight * (*src_pixel++);
2009 dest_g += pixel_weight * (*src_pixel++);
2010 dest_r += pixel_weight * (*src_pixel);
2011 dest_alpha += pixel_weight;
2012 }
2013 *dest_scan++ = (uint8_t)((dest_b) >> 16);
2014 *dest_scan++ = (uint8_t)((dest_g) >> 16);
2015 *dest_scan++ = (uint8_t)((dest_r) >> 16);
2016 *dest_scan++ = (uint8_t)((dest_alpha * 255) >> 16);
2017 } break;
2018 default:
2019 return;
2020 }
2021 }
2022 }
2023
ResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)2024 void ProgressiveDecoder::ResampleVert(
2025 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
2026 double scale_y,
2027 int dest_row) {
2028 int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
2029 uint32_t dest_ScanOffet = m_startX * dest_Bpp;
2030 int dest_top = m_startY;
2031 pdfium::base::CheckedNumeric<int> check_dest_row_1 = dest_row;
2032 check_dest_row_1 -= pdfium::base::checked_cast<int>(scale_y);
2033 int dest_row_1 = check_dest_row_1.ValueOrDie();
2034 if (dest_row_1 < dest_top) {
2035 int dest_bottom = dest_top + m_sizeY;
2036 if (dest_row + (int)scale_y >= dest_bottom - 1) {
2037 const uint8_t* scan_src =
2038 pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
2039 while (++dest_row < dest_bottom) {
2040 uint8_t* scan_des =
2041 pDeviceBitmap->GetWritableScanline(dest_row) + dest_ScanOffet;
2042 uint32_t size = m_sizeX * dest_Bpp;
2043 memmove(scan_des, scan_src, size);
2044 }
2045 }
2046 return;
2047 }
2048 for (; dest_row_1 < dest_row; dest_row_1++) {
2049 uint8_t* scan_des =
2050 pDeviceBitmap->GetWritableScanline(dest_row_1) + dest_ScanOffet;
2051 PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
2052 const uint8_t* scan_src1 =
2053 pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) +
2054 dest_ScanOffet;
2055 const uint8_t* scan_src2 =
2056 pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) +
2057 dest_ScanOffet;
2058 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
2059 switch (pDeviceBitmap->GetFormat()) {
2060 case FXDIB_Invalid:
2061 case FXDIB_1bppMask:
2062 case FXDIB_1bppRgb:
2063 return;
2064 case FXDIB_8bppMask:
2065 case FXDIB_8bppRgb: {
2066 if (pDeviceBitmap->GetPalette()) {
2067 return;
2068 }
2069 int dest_g = 0;
2070 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
2071 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
2072 *scan_des++ = (uint8_t)(dest_g >> 16);
2073 } break;
2074 case FXDIB_Rgb:
2075 case FXDIB_Rgb32: {
2076 uint32_t dest_b = 0;
2077 uint32_t dest_g = 0;
2078 uint32_t dest_r = 0;
2079 dest_b += pWeight->m_Weights[0] * (*scan_src1++);
2080 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
2081 dest_r += pWeight->m_Weights[0] * (*scan_src1++);
2082 scan_src1 += dest_Bpp - 3;
2083 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
2084 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
2085 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
2086 scan_src2 += dest_Bpp - 3;
2087 *scan_des++ = (uint8_t)((dest_b) >> 16);
2088 *scan_des++ = (uint8_t)((dest_g) >> 16);
2089 *scan_des++ = (uint8_t)((dest_r) >> 16);
2090 scan_des += dest_Bpp - 3;
2091 } break;
2092 case FXDIB_Argb: {
2093 uint32_t dest_a = 0;
2094 uint32_t dest_b = 0;
2095 uint32_t dest_g = 0;
2096 uint32_t dest_r = 0;
2097 dest_b += pWeight->m_Weights[0] * (*scan_src1++);
2098 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
2099 dest_r += pWeight->m_Weights[0] * (*scan_src1++);
2100 dest_a += pWeight->m_Weights[0] * (*scan_src1++);
2101 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
2102 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
2103 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
2104 dest_a += pWeight->m_Weights[1] * (*scan_src2++);
2105 *scan_des++ = (uint8_t)((dest_b) >> 16);
2106 *scan_des++ = (uint8_t)((dest_g) >> 16);
2107 *scan_des++ = (uint8_t)((dest_r) >> 16);
2108 *scan_des++ = (uint8_t)((dest_a) >> 16);
2109 } break;
2110 default:
2111 return;
2112 }
2113 }
2114 }
2115 int dest_bottom = dest_top + m_sizeY;
2116 if (dest_row + (int)scale_y >= dest_bottom - 1) {
2117 const uint8_t* scan_src =
2118 pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
2119 while (++dest_row < dest_bottom) {
2120 uint8_t* scan_des =
2121 pDeviceBitmap->GetWritableScanline(dest_row) + dest_ScanOffet;
2122 uint32_t size = m_sizeX * dest_Bpp;
2123 memmove(scan_des, scan_src, size);
2124 }
2125 }
2126 }
2127
Resample(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int32_t src_line,uint8_t * src_scan,FXCodec_Format src_format)2128 void ProgressiveDecoder::Resample(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
2129 int32_t src_line,
2130 uint8_t* src_scan,
2131 FXCodec_Format src_format) {
2132 int src_top = m_clipBox.top;
2133 int dest_top = m_startY;
2134 int src_height = m_clipBox.Height();
2135 int dest_height = m_sizeY;
2136 if (src_line >= src_top) {
2137 double scale_y = static_cast<double>(dest_height) / src_height;
2138 int src_row = src_line - src_top;
2139 int dest_row = (int)(src_row * scale_y) + dest_top;
2140 if (dest_row >= dest_top + dest_height)
2141 return;
2142
2143 ReSampleScanline(pDeviceBitmap, dest_row, m_pDecodeBuf.get(), src_format);
2144 if (scale_y > 1.0)
2145 ResampleVert(pDeviceBitmap, scale_y, dest_row);
2146 }
2147 }
2148
GetFrames()2149 std::pair<FXCODEC_STATUS, size_t> ProgressiveDecoder::GetFrames() {
2150 if (!(m_status == FXCODEC_STATUS_FRAME_READY ||
2151 m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) {
2152 return {FXCODEC_STATUS_ERROR, 0};
2153 }
2154
2155 switch (m_imageType) {
2156 #ifdef PDF_ENABLE_XFA_BMP
2157 case FXCODEC_IMAGE_BMP:
2158 #endif // PDF_ENABLE_XFA_BMP
2159 case FXCODEC_IMAGE_JPG:
2160 #ifdef PDF_ENABLE_XFA_PNG
2161 case FXCODEC_IMAGE_PNG:
2162 #endif // PDF_ENABLE_XFA_PNG
2163 #ifdef PDF_ENABLE_XFA_TIFF
2164 case FXCODEC_IMAGE_TIFF:
2165 #endif // PDF_ENABLE_XFA_TIFF
2166 m_FrameNumber = 1;
2167 m_status = FXCODEC_STATUS_DECODE_READY;
2168 return {m_status, 1};
2169 #ifdef PDF_ENABLE_XFA_GIF
2170 case FXCODEC_IMAGE_GIF: {
2171 GifModule* pGifModule = m_pCodecMgr->GetGifModule();
2172 if (!pGifModule) {
2173 m_status = FXCODEC_STATUS_ERR_MEMORY;
2174 return {m_status, 0};
2175 }
2176 while (true) {
2177 CFX_GifDecodeStatus readResult;
2178 std::tie(readResult, m_FrameNumber) =
2179 pGifModule->LoadFrameInfo(m_pGifContext.get());
2180 while (readResult == CFX_GifDecodeStatus::Unfinished) {
2181 FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ;
2182 if (!GifReadMoreData(pGifModule, error_status))
2183 return {error_status, 0};
2184
2185 std::tie(readResult, m_FrameNumber) =
2186 pGifModule->LoadFrameInfo(m_pGifContext.get());
2187 }
2188 if (readResult == CFX_GifDecodeStatus::Success) {
2189 m_status = FXCODEC_STATUS_DECODE_READY;
2190 return {m_status, m_FrameNumber};
2191 }
2192 m_pGifContext = nullptr;
2193 m_status = FXCODEC_STATUS_ERROR;
2194 return {m_status, 0};
2195 }
2196 }
2197 #endif // PDF_ENABLE_XFA_GIF
2198 default:
2199 return {FXCODEC_STATUS_ERROR, 0};
2200 }
2201 }
2202
StartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap,int start_x,int start_y,int size_x,int size_y)2203 FXCODEC_STATUS ProgressiveDecoder::StartDecode(
2204 const RetainPtr<CFX_DIBitmap>& pDIBitmap,
2205 int start_x,
2206 int start_y,
2207 int size_x,
2208 int size_y) {
2209 if (m_status != FXCODEC_STATUS_DECODE_READY)
2210 return FXCODEC_STATUS_ERROR;
2211
2212 if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0)
2213 return FXCODEC_STATUS_ERR_PARAMS;
2214
2215 m_pDeviceBitmap = pDIBitmap;
2216 if (m_clipBox.IsEmpty())
2217 return FXCODEC_STATUS_ERR_PARAMS;
2218 if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535)
2219 return FXCODEC_STATUS_ERR_PARAMS;
2220
2221 FX_RECT device_rc =
2222 FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y);
2223 int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth();
2224 int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight();
2225 device_rc.Intersect(
2226 FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight()));
2227 if (device_rc.IsEmpty())
2228 return FXCODEC_STATUS_ERR_PARAMS;
2229
2230 m_startX = device_rc.left;
2231 m_startY = device_rc.top;
2232 m_sizeX = device_rc.Width();
2233 m_sizeY = device_rc.Height();
2234 m_FrameCur = 0;
2235 if (start_x < 0 || out_range_x > 0) {
2236 float scaleX = (float)m_clipBox.Width() / (float)size_x;
2237 if (start_x < 0) {
2238 m_clipBox.left -= (int32_t)ceil((float)start_x * scaleX);
2239 }
2240 if (out_range_x > 0) {
2241 m_clipBox.right -= (int32_t)floor((float)out_range_x * scaleX);
2242 }
2243 }
2244 if (start_y < 0 || out_range_y > 0) {
2245 float scaleY = (float)m_clipBox.Height() / (float)size_y;
2246 if (start_y < 0) {
2247 m_clipBox.top -= (int32_t)ceil((float)start_y * scaleY);
2248 }
2249 if (out_range_y > 0) {
2250 m_clipBox.bottom -= (int32_t)floor((float)out_range_y * scaleY);
2251 }
2252 }
2253 if (m_clipBox.IsEmpty()) {
2254 return FXCODEC_STATUS_ERR_PARAMS;
2255 }
2256 switch (m_imageType) {
2257 #ifdef PDF_ENABLE_XFA_BMP
2258 case FXCODEC_IMAGE_BMP:
2259 return BmpStartDecode(pDIBitmap);
2260 #endif // PDF_ENABLE_XFA_BMP
2261 #ifdef PDF_ENABLE_XFA_GIF
2262 case FXCODEC_IMAGE_GIF:
2263 return GifStartDecode(pDIBitmap);
2264 #endif // PDF_ENABLE_XFA_GIF
2265 case FXCODEC_IMAGE_JPG:
2266 return JpegStartDecode(pDIBitmap);
2267 #ifdef PDF_ENABLE_XFA_PNG
2268 case FXCODEC_IMAGE_PNG:
2269 return PngStartDecode(pDIBitmap);
2270 #endif // PDF_ENABLE_XFA_PNG
2271 #ifdef PDF_ENABLE_XFA_TIFF
2272 case FXCODEC_IMAGE_TIFF:
2273 m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
2274 return m_status;
2275 #endif // PDF_ENABLE_XFA_TIFF
2276 default:
2277 return FXCODEC_STATUS_ERROR;
2278 }
2279 }
2280
ContinueDecode()2281 FXCODEC_STATUS ProgressiveDecoder::ContinueDecode() {
2282 if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE)
2283 return FXCODEC_STATUS_ERROR;
2284
2285 switch (m_imageType) {
2286 case FXCODEC_IMAGE_JPG:
2287 return JpegContinueDecode();
2288 #ifdef PDF_ENABLE_XFA_BMP
2289 case FXCODEC_IMAGE_BMP:
2290 return BmpContinueDecode();
2291 #endif // PDF_ENABLE_XFA_BMP
2292 #ifdef PDF_ENABLE_XFA_GIF
2293 case FXCODEC_IMAGE_GIF:
2294 return GifContinueDecode();
2295 #endif // PDF_ENABLE_XFA_GIF
2296 #ifdef PDF_ENABLE_XFA_PNG
2297 case FXCODEC_IMAGE_PNG:
2298 return PngContinueDecode();
2299 #endif // PDF_ENABLE_XFA_PNG
2300 #ifdef PDF_ENABLE_XFA_TIFF
2301 case FXCODEC_IMAGE_TIFF:
2302 return TiffContinueDecode();
2303 #endif // PDF_ENABLE_XFA_TIFF
2304 default:
2305 return FXCODEC_STATUS_ERROR;
2306 }
2307 }
2308
CreateProgressiveDecoder()2309 std::unique_ptr<ProgressiveDecoder> ModuleMgr::CreateProgressiveDecoder() {
2310 return pdfium::MakeUnique<ProgressiveDecoder>(this);
2311 }
2312
2313 } // namespace fxcodec
2314