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