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 }
637 }
638 }
639
BmpDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)640 bool ProgressiveDecoder::BmpDetectImageTypeInBuffer(
641 CFX_DIBAttribute* pAttribute) {
642 std::unique_ptr<ProgressiveDecoderIface::Context> pBmpContext =
643 BmpDecoder::StartDecode(this);
644 BmpDecoder::Input(pBmpContext.get(), m_pCodecMemory);
645
646 const std::vector<uint32_t>* palette;
647 BmpDecoder::Status read_result = BmpDecoder::ReadHeader(
648 pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
649 &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
650 while (read_result == BmpDecoder::Status::kContinue) {
651 FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
652 if (!BmpReadMoreData(pBmpContext.get(), &error_status)) {
653 m_status = error_status;
654 return false;
655 }
656 read_result = BmpDecoder::ReadHeader(
657 pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
658 &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
659 }
660
661 if (read_result != BmpDecoder::Status::kSuccess) {
662 m_status = FXCODEC_STATUS::kError;
663 return false;
664 }
665
666 FXDIB_Format format = FXDIB_Format::kInvalid;
667 switch (m_SrcComponents) {
668 case 1:
669 m_SrcFormat = FXCodec_8bppRgb;
670 format = FXDIB_Format::k8bppRgb;
671 break;
672 case 3:
673 m_SrcFormat = FXCodec_Rgb;
674 format = FXDIB_Format::kRgb;
675 break;
676 case 4:
677 m_SrcFormat = FXCodec_Rgb32;
678 format = FXDIB_Format::kRgb32;
679 break;
680 default:
681 m_status = FXCODEC_STATUS::kError;
682 return false;
683 }
684
685 // Set to 0 to make CalculatePitchAndSize() calculate it.
686 constexpr uint32_t kNoPitch = 0;
687 absl::optional<CFX_DIBitmap::PitchAndSize> needed_data =
688 CFX_DIBitmap::CalculatePitchAndSize(m_SrcWidth, m_SrcHeight, format,
689 kNoPitch);
690 if (!needed_data.has_value()) {
691 m_status = FXCODEC_STATUS::kError;
692 return false;
693 }
694
695 uint32_t available_data = pdfium::base::checked_cast<uint32_t>(
696 m_pFile->GetSize() - m_offSet +
697 BmpDecoder::GetAvailInput(pBmpContext.get()));
698 if (needed_data.value().size > available_data) {
699 m_status = FXCODEC_STATUS::kError;
700 return false;
701 }
702
703 m_SrcBPC = 8;
704 m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
705 m_pBmpContext = std::move(pBmpContext);
706 if (m_SrcPaletteNumber) {
707 m_SrcPalette.resize(m_SrcPaletteNumber);
708 memcpy(m_SrcPalette.data(), palette->data(),
709 m_SrcPaletteNumber * sizeof(FX_ARGB));
710 } else {
711 m_SrcPalette.clear();
712 }
713 return true;
714 }
715
BmpReadMoreData(ProgressiveDecoderIface::Context * pContext,FXCODEC_STATUS * err_status)716 bool ProgressiveDecoder::BmpReadMoreData(
717 ProgressiveDecoderIface::Context* pContext,
718 FXCODEC_STATUS* err_status) {
719 return ReadMoreData(BmpProgressiveDecoder::GetInstance(), pContext,
720 err_status);
721 }
722
BmpStartDecode()723 FXCODEC_STATUS ProgressiveDecoder::BmpStartDecode() {
724 GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
725 m_ScanlineSize = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents);
726 m_DecodeBuf.resize(m_ScanlineSize);
727 FXDIB_ResampleOptions options;
728 options.bInterpolateBilinear = true;
729 m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
730 m_clipBox.Width(), options);
731 m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
732 m_status = FXCODEC_STATUS::kDecodeToBeContinued;
733 return m_status;
734 }
735
BmpContinueDecode()736 FXCODEC_STATUS ProgressiveDecoder::BmpContinueDecode() {
737 BmpDecoder::Status read_res = BmpDecoder::LoadImage(m_pBmpContext.get());
738 while (read_res == BmpDecoder::Status::kContinue) {
739 FXCODEC_STATUS error_status = FXCODEC_STATUS::kDecodeFinished;
740 if (!BmpReadMoreData(m_pBmpContext.get(), &error_status)) {
741 m_pDeviceBitmap = nullptr;
742 m_pFile = nullptr;
743 m_status = error_status;
744 return m_status;
745 }
746 read_res = BmpDecoder::LoadImage(m_pBmpContext.get());
747 }
748
749 m_pDeviceBitmap = nullptr;
750 m_pFile = nullptr;
751 m_status = read_res == BmpDecoder::Status::kSuccess
752 ? FXCODEC_STATUS::kDecodeFinished
753 : FXCODEC_STATUS::kError;
754 return m_status;
755 }
756 #endif // PDF_ENABLE_XFA_BMP
757
758 #ifdef PDF_ENABLE_XFA_GIF
GifReadMoreData(FXCODEC_STATUS * err_status)759 bool ProgressiveDecoder::GifReadMoreData(FXCODEC_STATUS* err_status) {
760 return ReadMoreData(GifProgressiveDecoder::GetInstance(), m_pGifContext.get(),
761 err_status);
762 }
763
GifDetectImageTypeInBuffer()764 bool ProgressiveDecoder::GifDetectImageTypeInBuffer() {
765 m_pGifContext = GifDecoder::StartDecode(this);
766 GifDecoder::Input(m_pGifContext.get(), m_pCodecMemory);
767 m_SrcComponents = 1;
768 GifDecoder::Status readResult =
769 GifDecoder::ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
770 &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
771 while (readResult == GifDecoder::Status::kUnfinished) {
772 FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
773 if (!GifReadMoreData(&error_status)) {
774 m_pGifContext = nullptr;
775 m_status = error_status;
776 return false;
777 }
778 readResult =
779 GifDecoder::ReadHeader(m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight,
780 &m_GifPltNumber, &m_pGifPalette, &m_GifBgIndex);
781 }
782 if (readResult == GifDecoder::Status::kSuccess) {
783 m_SrcBPC = 8;
784 m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
785 return true;
786 }
787 m_pGifContext = nullptr;
788 m_status = FXCODEC_STATUS::kError;
789 return false;
790 }
791
GifStartDecode()792 FXCODEC_STATUS ProgressiveDecoder::GifStartDecode() {
793 m_SrcFormat = FXCodec_8bppRgb;
794 GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
795 int scanline_size = FxAlignToBoundary<4>(m_SrcWidth);
796 m_DecodeBuf.resize(scanline_size);
797 FXDIB_ResampleOptions options;
798 options.bInterpolateBilinear = true;
799 m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
800 m_clipBox.Width(), options);
801 m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
802 m_FrameCur = 0;
803 m_status = FXCODEC_STATUS::kDecodeToBeContinued;
804 return m_status;
805 }
806
GifContinueDecode()807 FXCODEC_STATUS ProgressiveDecoder::GifContinueDecode() {
808 GifDecoder::Status readRes =
809 GifDecoder::LoadFrame(m_pGifContext.get(), m_FrameCur);
810 while (readRes == GifDecoder::Status::kUnfinished) {
811 FXCODEC_STATUS error_status = FXCODEC_STATUS::kDecodeFinished;
812 if (!GifReadMoreData(&error_status)) {
813 m_pDeviceBitmap = nullptr;
814 m_pFile = nullptr;
815 m_status = error_status;
816 return m_status;
817 }
818 readRes = GifDecoder::LoadFrame(m_pGifContext.get(), m_FrameCur);
819 }
820
821 if (readRes == GifDecoder::Status::kSuccess) {
822 m_pDeviceBitmap = nullptr;
823 m_pFile = nullptr;
824 m_status = FXCODEC_STATUS::kDecodeFinished;
825 return m_status;
826 }
827
828 m_pDeviceBitmap = nullptr;
829 m_pFile = nullptr;
830 m_status = FXCODEC_STATUS::kError;
831 return m_status;
832 }
833
GifDoubleLineResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)834 void ProgressiveDecoder::GifDoubleLineResampleVert(
835 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
836 double scale_y,
837 int dest_row) {
838 int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
839 uint32_t dest_ScanOffset = m_startX * dest_Bpp;
840 int dest_top = m_startY;
841 pdfium::base::CheckedNumeric<double> scale_y2 = scale_y;
842 scale_y2 *= 2;
843 FX_SAFE_INT32 check_dest_row_1 = dest_row;
844 check_dest_row_1 -= scale_y2.ValueOrDie();
845 int dest_row_1 = check_dest_row_1.ValueOrDie();
846 dest_row_1 = std::max(dest_row_1, dest_top);
847 for (; dest_row_1 < dest_row; dest_row_1++) {
848 uint8_t* scan_des = pDeviceBitmap->GetWritableScanline(dest_row_1)
849 .subspan(dest_ScanOffset)
850 .data();
851 PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
852 const uint8_t* scan_src1 =
853 pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top)
854 .subspan(dest_ScanOffset)
855 .data();
856 const uint8_t* scan_src2 =
857 pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top)
858 .subspan(dest_ScanOffset)
859 .data();
860 switch (pDeviceBitmap->GetFormat()) {
861 case FXDIB_Format::kInvalid:
862 case FXDIB_Format::k1bppMask:
863 case FXDIB_Format::k1bppRgb:
864 return;
865 case FXDIB_Format::k8bppMask:
866 case FXDIB_Format::k8bppRgb:
867 if (pDeviceBitmap->HasPalette())
868 return;
869 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
870 uint32_t dest_g = 0;
871 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
872 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
873 *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
874 }
875 break;
876 case FXDIB_Format::kRgb:
877 case FXDIB_Format::kRgb32:
878 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
879 uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
880 uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
881 uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
882 scan_src1 += dest_Bpp - 3;
883 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
884 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
885 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
886 scan_src2 += dest_Bpp - 3;
887 *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
888 *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
889 *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
890 scan_des += dest_Bpp - 3;
891 }
892 break;
893 case FXDIB_Format::kArgb:
894 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
895 uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
896 uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
897 uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
898 uint32_t dest_a = pWeight->m_Weights[0] * (*scan_src1++);
899 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
900 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
901 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
902 dest_a += pWeight->m_Weights[1] * (*scan_src2++);
903 *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
904 *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
905 *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
906 *scan_des++ = CStretchEngine::PixelFromFixed(dest_a);
907 }
908 break;
909 }
910 }
911 int dest_bottom = dest_top + m_sizeY - 1;
912 if (dest_row + (int)(2 * scale_y) >= dest_bottom &&
913 dest_row + (int)scale_y < dest_bottom) {
914 GifDoubleLineResampleVert(pDeviceBitmap, scale_y, dest_row + (int)scale_y);
915 }
916 }
917 #endif // PDF_ENABLE_XFA_GIF
918
JpegReadMoreData(FXCODEC_STATUS * err_status)919 bool ProgressiveDecoder::JpegReadMoreData(FXCODEC_STATUS* err_status) {
920 return ReadMoreData(JpegProgressiveDecoder::GetInstance(),
921 m_pJpegContext.get(), err_status);
922 }
923
JpegDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)924 bool ProgressiveDecoder::JpegDetectImageTypeInBuffer(
925 CFX_DIBAttribute* pAttribute) {
926 m_pJpegContext = JpegProgressiveDecoder::Start();
927 if (!m_pJpegContext) {
928 m_status = FXCODEC_STATUS::kError;
929 return false;
930 }
931 JpegProgressiveDecoder::GetInstance()->Input(m_pJpegContext.get(),
932 m_pCodecMemory);
933
934 // Setting jump marker before calling ReadHeader, since a longjmp to
935 // the marker indicates a fatal error.
936 if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
937 m_pJpegContext.reset();
938 m_status = FXCODEC_STATUS::kError;
939 return false;
940 }
941
942 int32_t readResult = JpegProgressiveDecoder::ReadHeader(
943 m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
944 pAttribute);
945 while (readResult == 2) {
946 FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
947 if (!JpegReadMoreData(&error_status)) {
948 m_status = error_status;
949 return false;
950 }
951 readResult = JpegProgressiveDecoder::ReadHeader(
952 m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
953 pAttribute);
954 }
955 if (!readResult) {
956 m_SrcBPC = 8;
957 m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
958 return true;
959 }
960 m_pJpegContext.reset();
961 m_status = FXCODEC_STATUS::kError;
962 return false;
963 }
964
JpegStartDecode(FXDIB_Format format)965 FXCODEC_STATUS ProgressiveDecoder::JpegStartDecode(FXDIB_Format format) {
966 int down_scale = GetDownScale();
967 // Setting jump marker before calling StartScanLine, since a longjmp to
968 // the marker indicates a fatal error.
969 if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
970 m_pJpegContext.reset();
971 m_status = FXCODEC_STATUS::kError;
972 return FXCODEC_STATUS::kError;
973 }
974
975 bool startStatus =
976 JpegProgressiveDecoder::StartScanline(m_pJpegContext.get(), down_scale);
977 while (!startStatus) {
978 FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
979 if (!JpegReadMoreData(&error_status)) {
980 m_pDeviceBitmap = nullptr;
981 m_pFile = nullptr;
982 m_status = error_status;
983 return m_status;
984 }
985
986 startStatus =
987 JpegProgressiveDecoder::StartScanline(m_pJpegContext.get(), down_scale);
988 }
989 int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale;
990 scanline_size = FxAlignToBoundary<4>(scanline_size * m_SrcComponents);
991 m_DecodeBuf.resize(scanline_size);
992 FXDIB_ResampleOptions options;
993 options.bInterpolateBilinear = true;
994 m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
995 m_clipBox.Width(), options);
996 m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
997 switch (m_SrcComponents) {
998 case 1:
999 m_SrcFormat = FXCodec_8bppGray;
1000 break;
1001 case 3:
1002 m_SrcFormat = FXCodec_Rgb;
1003 break;
1004 case 4:
1005 m_SrcFormat = FXCodec_Cmyk;
1006 break;
1007 }
1008 GetTransMethod(format, m_SrcFormat);
1009 m_status = FXCODEC_STATUS::kDecodeToBeContinued;
1010 return m_status;
1011 }
1012
JpegContinueDecode()1013 FXCODEC_STATUS ProgressiveDecoder::JpegContinueDecode() {
1014 // JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1015 // Setting jump marker before calling ReadScanLine, since a longjmp to
1016 // the marker indicates a fatal error.
1017 if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
1018 m_pJpegContext.reset();
1019 m_status = FXCODEC_STATUS::kError;
1020 return FXCODEC_STATUS::kError;
1021 }
1022
1023 while (true) {
1024 bool readRes = JpegProgressiveDecoder::ReadScanline(m_pJpegContext.get(),
1025 m_DecodeBuf.data());
1026 while (!readRes) {
1027 FXCODEC_STATUS error_status = FXCODEC_STATUS::kDecodeFinished;
1028 if (!JpegReadMoreData(&error_status)) {
1029 m_pDeviceBitmap = nullptr;
1030 m_pFile = nullptr;
1031 m_status = error_status;
1032 return m_status;
1033 }
1034 readRes = JpegProgressiveDecoder::ReadScanline(m_pJpegContext.get(),
1035 m_DecodeBuf.data());
1036 }
1037 if (m_SrcFormat == FXCodec_Rgb) {
1038 int src_Bpp = (m_SrcFormat & 0xff) >> 3;
1039 RGB2BGR(m_DecodeBuf.data() + m_clipBox.left * src_Bpp, m_clipBox.Width());
1040 }
1041 if (m_SrcRow >= m_clipBox.bottom) {
1042 m_pDeviceBitmap = nullptr;
1043 m_pFile = nullptr;
1044 m_status = FXCODEC_STATUS::kDecodeFinished;
1045 return m_status;
1046 }
1047 Resample(m_pDeviceBitmap, m_SrcRow, m_DecodeBuf.data(), m_SrcFormat);
1048 m_SrcRow++;
1049 }
1050 }
1051
1052 #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)1053 void ProgressiveDecoder::PngOneOneMapResampleHorz(
1054 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1055 int32_t dest_line,
1056 pdfium::span<uint8_t> src_span,
1057 FXCodec_Format src_format) {
1058 int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3;
1059 int32_t dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
1060 int32_t src_left = m_clipBox.left;
1061 int32_t dest_left = m_startX;
1062 uint8_t* src_scan = src_span.subspan(src_left * src_Bpp).data();
1063 uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line)
1064 .subspan(dest_left * dest_Bpp)
1065 .data();
1066 switch (pDeviceBitmap->GetFormat()) {
1067 case FXDIB_Format::k1bppMask:
1068 case FXDIB_Format::k1bppRgb:
1069 NOTREACHED_NORETURN();
1070 case FXDIB_Format::k8bppMask:
1071 case FXDIB_Format::k8bppRgb:
1072 if (pDeviceBitmap->HasPalette())
1073 return;
1074 for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) {
1075 PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col);
1076 uint32_t dest_g =
1077 pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart];
1078 dest_g +=
1079 pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd];
1080 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1081 }
1082 break;
1083 case FXDIB_Format::kRgb:
1084 case FXDIB_Format::kRgb32:
1085 for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) {
1086 PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col);
1087 const uint8_t* p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
1088 uint32_t dest_b = pPixelWeights->m_Weights[0] * (*p++);
1089 uint32_t dest_g = pPixelWeights->m_Weights[0] * (*p++);
1090 uint32_t dest_r = pPixelWeights->m_Weights[0] * (*p);
1091 p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
1092 dest_b += pPixelWeights->m_Weights[1] * (*p++);
1093 dest_g += pPixelWeights->m_Weights[1] * (*p++);
1094 dest_r += pPixelWeights->m_Weights[1] * (*p);
1095 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1096 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1097 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1098 dest_scan += dest_Bpp - 3;
1099 }
1100 break;
1101 case FXDIB_Format::kArgb:
1102 for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) {
1103 PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col);
1104 const uint8_t* p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
1105 uint32_t dest_b = pPixelWeights->m_Weights[0] * (*p++);
1106 uint32_t dest_g = pPixelWeights->m_Weights[0] * (*p++);
1107 uint32_t dest_r = pPixelWeights->m_Weights[0] * (*p++);
1108 uint32_t dest_a = pPixelWeights->m_Weights[0] * (*p);
1109 p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
1110 dest_b += pPixelWeights->m_Weights[1] * (*p++);
1111 dest_g += pPixelWeights->m_Weights[1] * (*p++);
1112 dest_r += pPixelWeights->m_Weights[1] * (*p++);
1113 dest_a += pPixelWeights->m_Weights[1] * (*p);
1114 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1115 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1116 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1117 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_a);
1118 }
1119 break;
1120 default:
1121 return;
1122 }
1123 }
1124
PngDetectImageTypeInBuffer(CFX_DIBAttribute * pAttribute)1125 bool ProgressiveDecoder::PngDetectImageTypeInBuffer(
1126 CFX_DIBAttribute* pAttribute) {
1127 m_pPngContext = PngDecoder::StartDecode(this);
1128 if (!m_pPngContext) {
1129 m_status = FXCODEC_STATUS::kError;
1130 return false;
1131 }
1132 while (PngDecoder::ContinueDecode(m_pPngContext.get(), m_pCodecMemory,
1133 pAttribute)) {
1134 uint32_t remain_size = static_cast<uint32_t>(m_pFile->GetSize()) - m_offSet;
1135 uint32_t input_size = std::min<uint32_t>(remain_size, kBlockSize);
1136 if (input_size == 0) {
1137 m_pPngContext.reset();
1138 m_status = FXCODEC_STATUS::kError;
1139 return false;
1140 }
1141 if (m_pCodecMemory && input_size > m_pCodecMemory->GetSize())
1142 m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(input_size);
1143
1144 if (!m_pFile->ReadBlockAtOffset(
1145 m_pCodecMemory->GetBufferSpan().first(input_size), m_offSet)) {
1146 m_status = FXCODEC_STATUS::kError;
1147 return false;
1148 }
1149 m_offSet += input_size;
1150 }
1151 m_pPngContext.reset();
1152 if (m_SrcPassNumber == 0) {
1153 m_status = FXCODEC_STATUS::kError;
1154 return false;
1155 }
1156 return true;
1157 }
1158
PngStartDecode()1159 FXCODEC_STATUS ProgressiveDecoder::PngStartDecode() {
1160 m_pPngContext = PngDecoder::StartDecode(this);
1161 if (!m_pPngContext) {
1162 m_pDeviceBitmap = nullptr;
1163 m_pFile = nullptr;
1164 m_status = FXCODEC_STATUS::kError;
1165 return m_status;
1166 }
1167 m_offSet = 0;
1168 switch (m_pDeviceBitmap->GetFormat()) {
1169 case FXDIB_Format::k8bppMask:
1170 case FXDIB_Format::k8bppRgb:
1171 m_SrcComponents = 1;
1172 m_SrcFormat = FXCodec_8bppGray;
1173 break;
1174 case FXDIB_Format::kRgb:
1175 m_SrcComponents = 3;
1176 m_SrcFormat = FXCodec_Rgb;
1177 break;
1178 case FXDIB_Format::kRgb32:
1179 case FXDIB_Format::kArgb:
1180 m_SrcComponents = 4;
1181 m_SrcFormat = FXCodec_Argb;
1182 break;
1183 default: {
1184 m_pDeviceBitmap = nullptr;
1185 m_pFile = nullptr;
1186 m_status = FXCODEC_STATUS::kError;
1187 return m_status;
1188 }
1189 }
1190 GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
1191 int scanline_size = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents);
1192 m_DecodeBuf.resize(scanline_size);
1193 m_WeightHorzOO.CalculateWeights(m_sizeX, m_clipBox.Width());
1194 m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
1195 m_status = FXCODEC_STATUS::kDecodeToBeContinued;
1196 return m_status;
1197 }
1198
PngContinueDecode()1199 FXCODEC_STATUS ProgressiveDecoder::PngContinueDecode() {
1200 while (true) {
1201 uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet;
1202 uint32_t input_size = std::min<uint32_t>(remain_size, kBlockSize);
1203 if (input_size == 0) {
1204 m_pPngContext.reset();
1205 m_pDeviceBitmap = nullptr;
1206 m_pFile = nullptr;
1207 m_status = FXCODEC_STATUS::kDecodeFinished;
1208 return m_status;
1209 }
1210 if (m_pCodecMemory && input_size > m_pCodecMemory->GetSize())
1211 m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(input_size);
1212
1213 bool bResult = m_pFile->ReadBlockAtOffset(
1214 m_pCodecMemory->GetBufferSpan().first(input_size), m_offSet);
1215 if (!bResult) {
1216 m_pDeviceBitmap = nullptr;
1217 m_pFile = nullptr;
1218 m_status = FXCODEC_STATUS::kError;
1219 return m_status;
1220 }
1221 m_offSet += input_size;
1222 bResult = PngDecoder::ContinueDecode(m_pPngContext.get(), m_pCodecMemory,
1223 nullptr);
1224 if (!bResult) {
1225 m_pDeviceBitmap = nullptr;
1226 m_pFile = nullptr;
1227 m_status = FXCODEC_STATUS::kError;
1228 return m_status;
1229 }
1230 }
1231 }
1232 #endif // PDF_ENABLE_XFA_PNG
1233
1234 #ifdef PDF_ENABLE_XFA_TIFF
TiffDetectImageTypeFromFile(CFX_DIBAttribute * pAttribute)1235 bool ProgressiveDecoder::TiffDetectImageTypeFromFile(
1236 CFX_DIBAttribute* pAttribute) {
1237 m_pTiffContext = TiffDecoder::CreateDecoder(m_pFile);
1238 if (!m_pTiffContext) {
1239 m_status = FXCODEC_STATUS::kError;
1240 return false;
1241 }
1242 int32_t dummy_bpc;
1243 bool ret = TiffDecoder::LoadFrameInfo(m_pTiffContext.get(), 0, &m_SrcWidth,
1244 &m_SrcHeight, &m_SrcComponents,
1245 &dummy_bpc, pAttribute);
1246 m_SrcComponents = 4;
1247 m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1248 if (!ret) {
1249 m_pTiffContext.reset();
1250 m_status = FXCODEC_STATUS::kError;
1251 return false;
1252 }
1253 return true;
1254 }
1255
TiffContinueDecode()1256 FXCODEC_STATUS ProgressiveDecoder::TiffContinueDecode() {
1257 bool ret = false;
1258 if (m_pDeviceBitmap->GetBPP() == 32 &&
1259 m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX &&
1260 m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY &&
1261 m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 &&
1262 m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth &&
1263 m_clipBox.bottom == m_SrcHeight) {
1264 ret = TiffDecoder::Decode(m_pTiffContext.get(), m_pDeviceBitmap);
1265 m_pDeviceBitmap = nullptr;
1266 m_pFile = nullptr;
1267 if (!ret) {
1268 m_status = FXCODEC_STATUS::kError;
1269 return m_status;
1270 }
1271 m_status = FXCODEC_STATUS::kDecodeFinished;
1272 return m_status;
1273 }
1274
1275 auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1276 pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Format::kArgb);
1277 if (pDIBitmap->GetBuffer().empty()) {
1278 m_pDeviceBitmap = nullptr;
1279 m_pFile = nullptr;
1280 m_status = FXCODEC_STATUS::kError;
1281 return m_status;
1282 }
1283 ret = TiffDecoder::Decode(m_pTiffContext.get(), pDIBitmap);
1284 if (!ret) {
1285 m_pDeviceBitmap = nullptr;
1286 m_pFile = nullptr;
1287 m_status = FXCODEC_STATUS::kError;
1288 return m_status;
1289 }
1290 RetainPtr<CFX_DIBitmap> pClipBitmap =
1291 (m_clipBox.left == 0 && m_clipBox.top == 0 &&
1292 m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight)
1293 ? pDIBitmap
1294 : pDIBitmap->ClipTo(m_clipBox);
1295 if (!pClipBitmap) {
1296 m_pDeviceBitmap = nullptr;
1297 m_pFile = nullptr;
1298 m_status = FXCODEC_STATUS::kError;
1299 return m_status;
1300 }
1301 RetainPtr<CFX_DIBitmap> pFormatBitmap;
1302 switch (m_pDeviceBitmap->GetFormat()) {
1303 case FXDIB_Format::k8bppRgb:
1304 pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1305 pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1306 FXDIB_Format::k8bppRgb);
1307 break;
1308 case FXDIB_Format::k8bppMask:
1309 pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1310 pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1311 FXDIB_Format::k8bppMask);
1312 break;
1313 case FXDIB_Format::kRgb:
1314 pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1315 pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1316 FXDIB_Format::kRgb);
1317 break;
1318 case FXDIB_Format::kRgb32:
1319 pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
1320 pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
1321 FXDIB_Format::kRgb32);
1322 break;
1323 case FXDIB_Format::kArgb:
1324 pFormatBitmap = pClipBitmap;
1325 break;
1326 default:
1327 break;
1328 }
1329 switch (m_pDeviceBitmap->GetFormat()) {
1330 case FXDIB_Format::k8bppRgb:
1331 case FXDIB_Format::k8bppMask: {
1332 for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1333 const uint8_t* src_line = pClipBitmap->GetScanline(row).data();
1334 uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row).data();
1335 for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1336 uint8_t _a = 255 - src_line[3];
1337 uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1338 uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1339 uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1340 *dest_line++ = FXRGB2GRAY(r, g, b);
1341 src_line += 4;
1342 }
1343 }
1344 } break;
1345 case FXDIB_Format::kRgb:
1346 case FXDIB_Format::kRgb32: {
1347 int32_t desBpp =
1348 (m_pDeviceBitmap->GetFormat() == FXDIB_Format::kRgb) ? 3 : 4;
1349 for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1350 const uint8_t* src_line = pClipBitmap->GetScanline(row).data();
1351 uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row).data();
1352 for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1353 uint8_t _a = 255 - src_line[3];
1354 uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1355 uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1356 uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1357 *dest_line++ = b;
1358 *dest_line++ = g;
1359 *dest_line++ = r;
1360 dest_line += desBpp - 3;
1361 src_line += 4;
1362 }
1363 }
1364 } break;
1365 default:
1366 break;
1367 }
1368 if (!pFormatBitmap) {
1369 m_pDeviceBitmap = nullptr;
1370 m_pFile = nullptr;
1371 m_status = FXCODEC_STATUS::kError;
1372 return m_status;
1373 }
1374
1375 FXDIB_ResampleOptions options;
1376 options.bInterpolateBilinear = true;
1377 RetainPtr<CFX_DIBitmap> pStrechBitmap =
1378 pFormatBitmap->StretchTo(m_sizeX, m_sizeY, options, nullptr);
1379 pFormatBitmap = nullptr;
1380 if (!pStrechBitmap) {
1381 m_pDeviceBitmap = nullptr;
1382 m_pFile = nullptr;
1383 m_status = FXCODEC_STATUS::kError;
1384 return m_status;
1385 }
1386 m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY,
1387 pStrechBitmap, 0, 0);
1388 m_pDeviceBitmap = nullptr;
1389 m_pFile = nullptr;
1390 m_status = FXCODEC_STATUS::kDecodeFinished;
1391 return m_status;
1392 }
1393 #endif // PDF_ENABLE_XFA_TIFF
1394
DetectImageType(FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute)1395 bool ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType,
1396 CFX_DIBAttribute* pAttribute) {
1397 #ifdef PDF_ENABLE_XFA_TIFF
1398 if (imageType == FXCODEC_IMAGE_TIFF)
1399 return TiffDetectImageTypeFromFile(pAttribute);
1400 #endif // PDF_ENABLE_XFA_TIFF
1401
1402 size_t size = pdfium::base::checked_cast<size_t>(
1403 std::min<FX_FILESIZE>(m_pFile->GetSize(), kBlockSize));
1404 m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(size);
1405 m_offSet = 0;
1406 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().first(size),
1407 m_offSet)) {
1408 m_status = FXCODEC_STATUS::kError;
1409 return false;
1410 }
1411 m_offSet += size;
1412
1413 if (imageType == FXCODEC_IMAGE_JPG)
1414 return JpegDetectImageTypeInBuffer(pAttribute);
1415
1416 #ifdef PDF_ENABLE_XFA_BMP
1417 if (imageType == FXCODEC_IMAGE_BMP)
1418 return BmpDetectImageTypeInBuffer(pAttribute);
1419 #endif // PDF_ENABLE_XFA_BMP
1420
1421 #ifdef PDF_ENABLE_XFA_GIF
1422 if (imageType == FXCODEC_IMAGE_GIF)
1423 return GifDetectImageTypeInBuffer();
1424 #endif // PDF_ENABLE_XFA_GIF
1425
1426 #ifdef PDF_ENABLE_XFA_PNG
1427 if (imageType == FXCODEC_IMAGE_PNG)
1428 return PngDetectImageTypeInBuffer(pAttribute);
1429 #endif // PDF_ENABLE_XFA_PNG
1430
1431 m_status = FXCODEC_STATUS::kError;
1432 return false;
1433 }
1434
ReadMoreData(ProgressiveDecoderIface * pModule,ProgressiveDecoderIface::Context * pContext,FXCODEC_STATUS * err_status)1435 bool ProgressiveDecoder::ReadMoreData(
1436 ProgressiveDecoderIface* pModule,
1437 ProgressiveDecoderIface::Context* pContext,
1438 FXCODEC_STATUS* err_status) {
1439 // Check for EOF.
1440 if (m_offSet >= static_cast<uint32_t>(m_pFile->GetSize()))
1441 return false;
1442
1443 // Try to get whatever remains.
1444 uint32_t dwBytesToFetchFromFile =
1445 pdfium::base::checked_cast<uint32_t>(m_pFile->GetSize() - m_offSet);
1446
1447 // Figure out if the codec stopped processing midway through the buffer.
1448 size_t dwUnconsumed;
1449 FX_SAFE_SIZE_T avail_input = pModule->GetAvailInput(pContext);
1450 if (!avail_input.AssignIfValid(&dwUnconsumed))
1451 return false;
1452
1453 if (dwUnconsumed == m_pCodecMemory->GetSize()) {
1454 // Codec couldn't make any progress against the bytes in the buffer.
1455 // Increase the buffer size so that there might be enough contiguous
1456 // bytes to allow whatever operation is having difficulty to succeed.
1457 dwBytesToFetchFromFile =
1458 std::min<uint32_t>(dwBytesToFetchFromFile, kBlockSize);
1459 size_t dwNewSize = m_pCodecMemory->GetSize() + dwBytesToFetchFromFile;
1460 if (!m_pCodecMemory->TryResize(dwNewSize)) {
1461 *err_status = FXCODEC_STATUS::kError;
1462 return false;
1463 }
1464 } else {
1465 // TODO(crbug.com/pdfium/1904): Simplify the `CFX_CodecMemory` API so we
1466 // don't need to do this awkward dance to free up exactly enough buffer
1467 // space for the next read.
1468 size_t dwConsumable = m_pCodecMemory->GetSize() - dwUnconsumed;
1469 dwBytesToFetchFromFile = pdfium::base::checked_cast<uint32_t>(
1470 std::min<size_t>(dwBytesToFetchFromFile, dwConsumable));
1471 m_pCodecMemory->Consume(dwBytesToFetchFromFile);
1472 m_pCodecMemory->Seek(dwConsumable - dwBytesToFetchFromFile);
1473 dwUnconsumed += m_pCodecMemory->GetPosition();
1474 }
1475
1476 // Append new data past the bytes not yet processed by the codec.
1477 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().subspan(
1478 dwUnconsumed, dwBytesToFetchFromFile),
1479 m_offSet)) {
1480 *err_status = FXCODEC_STATUS::kError;
1481 return false;
1482 }
1483 m_offSet += dwBytesToFetchFromFile;
1484 return pModule->Input(pContext, m_pCodecMemory);
1485 }
1486
LoadImageInfo(RetainPtr<IFX_SeekableReadStream> pFile,FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute,bool bSkipImageTypeCheck)1487 FXCODEC_STATUS ProgressiveDecoder::LoadImageInfo(
1488 RetainPtr<IFX_SeekableReadStream> pFile,
1489 FXCODEC_IMAGE_TYPE imageType,
1490 CFX_DIBAttribute* pAttribute,
1491 bool bSkipImageTypeCheck) {
1492 DCHECK(pAttribute);
1493
1494 switch (m_status) {
1495 case FXCODEC_STATUS::kFrameReady:
1496 case FXCODEC_STATUS::kFrameToBeContinued:
1497 case FXCODEC_STATUS::kDecodeReady:
1498 case FXCODEC_STATUS::kDecodeToBeContinued:
1499 return FXCODEC_STATUS::kError;
1500 default:
1501 break;
1502 }
1503 m_pFile = std::move(pFile);
1504 if (!m_pFile) {
1505 m_status = FXCODEC_STATUS::kError;
1506 return m_status;
1507 }
1508 m_offSet = 0;
1509 m_SrcWidth = m_SrcHeight = 0;
1510 m_SrcComponents = m_SrcBPC = 0;
1511 m_clipBox = FX_RECT();
1512 m_startX = m_startY = 0;
1513 m_sizeX = m_sizeY = 0;
1514 m_SrcPassNumber = 0;
1515 if (imageType != FXCODEC_IMAGE_UNKNOWN &&
1516 DetectImageType(imageType, pAttribute)) {
1517 m_imageType = imageType;
1518 m_status = FXCODEC_STATUS::kFrameReady;
1519 return m_status;
1520 }
1521 // If we got here then the image data does not match the requested decoder.
1522 // If we're skipping the type check then bail out at this point and return
1523 // the failed status.
1524 if (bSkipImageTypeCheck)
1525 return m_status;
1526
1527 for (int type = FXCODEC_IMAGE_UNKNOWN + 1; type < FXCODEC_IMAGE_MAX; type++) {
1528 if (DetectImageType(static_cast<FXCODEC_IMAGE_TYPE>(type), pAttribute)) {
1529 m_imageType = static_cast<FXCODEC_IMAGE_TYPE>(type);
1530 m_status = FXCODEC_STATUS::kFrameReady;
1531 return m_status;
1532 }
1533 }
1534 m_status = FXCODEC_STATUS::kError;
1535 m_pFile = nullptr;
1536 return m_status;
1537 }
1538
SetClipBox(FX_RECT * clip)1539 void ProgressiveDecoder::SetClipBox(FX_RECT* clip) {
1540 if (m_status != FXCODEC_STATUS::kFrameReady)
1541 return;
1542
1543 if (clip->IsEmpty()) {
1544 m_clipBox = FX_RECT();
1545 return;
1546 }
1547 clip->left = std::max(clip->left, 0);
1548 clip->right = std::min(clip->right, m_SrcWidth);
1549 clip->top = std::max(clip->top, 0);
1550 clip->bottom = std::min(clip->bottom, m_SrcHeight);
1551 if (clip->IsEmpty()) {
1552 m_clipBox = FX_RECT();
1553 return;
1554 }
1555 m_clipBox = *clip;
1556 }
1557
GetDownScale()1558 int ProgressiveDecoder::GetDownScale() {
1559 int down_scale = 1;
1560 int ratio_w = m_clipBox.Width() / m_sizeX;
1561 int ratio_h = m_clipBox.Height() / m_sizeY;
1562 int ratio = std::min(ratio_w, ratio_h);
1563 if (ratio >= 8)
1564 down_scale = 8;
1565 else if (ratio >= 4)
1566 down_scale = 4;
1567 else if (ratio >= 2)
1568 down_scale = 2;
1569
1570 m_clipBox.left /= down_scale;
1571 m_clipBox.right /= down_scale;
1572 m_clipBox.top /= down_scale;
1573 m_clipBox.bottom /= down_scale;
1574 if (m_clipBox.right == m_clipBox.left)
1575 m_clipBox.right = m_clipBox.left + 1;
1576 if (m_clipBox.bottom == m_clipBox.top)
1577 m_clipBox.bottom = m_clipBox.top + 1;
1578 return down_scale;
1579 }
1580
GetTransMethod(FXDIB_Format dest_format,FXCodec_Format src_format)1581 void ProgressiveDecoder::GetTransMethod(FXDIB_Format dest_format,
1582 FXCodec_Format src_format) {
1583 switch (dest_format) {
1584 case FXDIB_Format::k1bppMask:
1585 case FXDIB_Format::k1bppRgb: {
1586 switch (src_format) {
1587 case FXCodec_1bppGray:
1588 m_TransMethod = 0;
1589 break;
1590 default:
1591 m_TransMethod = -1;
1592 }
1593 } break;
1594 case FXDIB_Format::k8bppMask:
1595 case FXDIB_Format::k8bppRgb: {
1596 switch (src_format) {
1597 case FXCodec_1bppGray:
1598 m_TransMethod = 1;
1599 break;
1600 case FXCodec_8bppGray:
1601 m_TransMethod = 2;
1602 break;
1603 case FXCodec_1bppRgb:
1604 case FXCodec_8bppRgb:
1605 m_TransMethod = 3;
1606 break;
1607 case FXCodec_Rgb:
1608 case FXCodec_Rgb32:
1609 case FXCodec_Argb:
1610 m_TransMethod = 4;
1611 break;
1612 case FXCodec_Cmyk:
1613 m_TransMethod = 5;
1614 break;
1615 default:
1616 m_TransMethod = -1;
1617 }
1618 } break;
1619 case FXDIB_Format::kRgb: {
1620 switch (src_format) {
1621 case FXCodec_1bppGray:
1622 m_TransMethod = 6;
1623 break;
1624 case FXCodec_8bppGray:
1625 m_TransMethod = 7;
1626 break;
1627 case FXCodec_1bppRgb:
1628 case FXCodec_8bppRgb:
1629 m_TransMethod = 8;
1630 break;
1631 case FXCodec_Rgb:
1632 case FXCodec_Rgb32:
1633 case FXCodec_Argb:
1634 m_TransMethod = 9;
1635 break;
1636 case FXCodec_Cmyk:
1637 m_TransMethod = 10;
1638 break;
1639 default:
1640 m_TransMethod = -1;
1641 }
1642 } break;
1643 case FXDIB_Format::kRgb32:
1644 case FXDIB_Format::kArgb: {
1645 switch (src_format) {
1646 case FXCodec_1bppGray:
1647 m_TransMethod = 6;
1648 break;
1649 case FXCodec_8bppGray:
1650 m_TransMethod = 7;
1651 break;
1652 case FXCodec_1bppRgb:
1653 case FXCodec_8bppRgb:
1654 if (dest_format == FXDIB_Format::kArgb) {
1655 m_TransMethod = 12;
1656 } else {
1657 m_TransMethod = 8;
1658 }
1659 break;
1660 case FXCodec_Rgb:
1661 case FXCodec_Rgb32:
1662 m_TransMethod = 9;
1663 break;
1664 case FXCodec_Cmyk:
1665 m_TransMethod = 10;
1666 break;
1667 case FXCodec_Argb:
1668 m_TransMethod = 11;
1669 break;
1670 default:
1671 m_TransMethod = -1;
1672 }
1673 } break;
1674 default:
1675 m_TransMethod = -1;
1676 }
1677 }
1678
ResampleScanline(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int dest_line,pdfium::span<uint8_t> src_span,FXCodec_Format src_format)1679 void ProgressiveDecoder::ResampleScanline(
1680 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1681 int dest_line,
1682 pdfium::span<uint8_t> src_span,
1683 FXCodec_Format src_format) {
1684 uint8_t* src_scan = src_span.data();
1685 int src_left = m_clipBox.left;
1686 int dest_left = m_startX;
1687 uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line).data();
1688 int src_bytes_per_pixel = (src_format & 0xff) / 8;
1689 int dest_bytes_per_pixel = pDeviceBitmap->GetBPP() / 8;
1690 src_scan += src_left * src_bytes_per_pixel;
1691 dest_scan += dest_left * dest_bytes_per_pixel;
1692 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1693 PixelWeight* pPixelWeights = m_WeightHorz.GetPixelWeight(dest_col);
1694 switch (m_TransMethod) {
1695 case -1:
1696 return;
1697 case 0:
1698 return;
1699 case 1:
1700 return;
1701 case 2: {
1702 uint32_t dest_g = 0;
1703 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1704 j++) {
1705 uint32_t pixel_weight =
1706 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1707 dest_g += pixel_weight * src_scan[j];
1708 }
1709 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1710 } break;
1711 case 3: {
1712 uint32_t dest_r = 0;
1713 uint32_t dest_g = 0;
1714 uint32_t dest_b = 0;
1715 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1716 j++) {
1717 uint32_t pixel_weight =
1718 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1719 uint32_t argb = m_SrcPalette[src_scan[j]];
1720 dest_r += pixel_weight * FXARGB_R(argb);
1721 dest_g += pixel_weight * FXARGB_G(argb);
1722 dest_b += pixel_weight * FXARGB_B(argb);
1723 }
1724 *dest_scan++ = static_cast<uint8_t>(
1725 FXRGB2GRAY(CStretchEngine::PixelFromFixed(dest_r),
1726 CStretchEngine::PixelFromFixed(dest_g),
1727 CStretchEngine::PixelFromFixed(dest_b)));
1728 } break;
1729 case 4: {
1730 uint32_t dest_b = 0;
1731 uint32_t dest_g = 0;
1732 uint32_t dest_r = 0;
1733 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1734 j++) {
1735 uint32_t pixel_weight =
1736 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1737 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1738 dest_b += pixel_weight * (*src_pixel++);
1739 dest_g += pixel_weight * (*src_pixel++);
1740 dest_r += pixel_weight * (*src_pixel);
1741 }
1742 *dest_scan++ = static_cast<uint8_t>(
1743 FXRGB2GRAY(CStretchEngine::PixelFromFixed(dest_r),
1744 CStretchEngine::PixelFromFixed(dest_g),
1745 CStretchEngine::PixelFromFixed(dest_b)));
1746 } break;
1747 case 5: {
1748 uint32_t dest_b = 0;
1749 uint32_t dest_g = 0;
1750 uint32_t dest_r = 0;
1751 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1752 j++) {
1753 uint32_t pixel_weight =
1754 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1755 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1756 uint8_t src_b = 0;
1757 uint8_t src_g = 0;
1758 uint8_t src_r = 0;
1759 std::tie(src_r, src_g, src_b) =
1760 AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1761 255 - src_pixel[2], 255 - src_pixel[3]);
1762 dest_b += pixel_weight * src_b;
1763 dest_g += pixel_weight * src_g;
1764 dest_r += pixel_weight * src_r;
1765 }
1766 *dest_scan++ = static_cast<uint8_t>(
1767 FXRGB2GRAY(CStretchEngine::PixelFromFixed(dest_r),
1768 CStretchEngine::PixelFromFixed(dest_g),
1769 CStretchEngine::PixelFromFixed(dest_b)));
1770 } break;
1771 case 6:
1772 return;
1773 case 7: {
1774 uint32_t dest_g = 0;
1775 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1776 j++) {
1777 uint32_t pixel_weight =
1778 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1779 dest_g += pixel_weight * src_scan[j];
1780 }
1781 memset(dest_scan, CStretchEngine::PixelFromFixed(dest_g), 3);
1782 dest_scan += dest_bytes_per_pixel;
1783 } break;
1784 case 8: {
1785 uint32_t dest_r = 0;
1786 uint32_t dest_g = 0;
1787 uint32_t dest_b = 0;
1788 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1789 j++) {
1790 uint32_t pixel_weight =
1791 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1792 uint32_t argb = m_SrcPalette[src_scan[j]];
1793 dest_r += pixel_weight * FXARGB_R(argb);
1794 dest_g += pixel_weight * FXARGB_G(argb);
1795 dest_b += pixel_weight * FXARGB_B(argb);
1796 }
1797 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1798 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1799 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1800 dest_scan += dest_bytes_per_pixel - 3;
1801 } break;
1802 case 12: {
1803 #ifdef PDF_ENABLE_XFA_BMP
1804 if (m_pBmpContext) {
1805 uint32_t dest_r = 0;
1806 uint32_t dest_g = 0;
1807 uint32_t dest_b = 0;
1808 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1809 j++) {
1810 uint32_t pixel_weight =
1811 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1812 uint32_t argb = m_SrcPalette[src_scan[j]];
1813 dest_r += pixel_weight * FXARGB_R(argb);
1814 dest_g += pixel_weight * FXARGB_G(argb);
1815 dest_b += pixel_weight * FXARGB_B(argb);
1816 }
1817 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1818 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1819 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1820 *dest_scan++ = 0xFF;
1821 break;
1822 }
1823 #endif // PDF_ENABLE_XFA_BMP
1824 uint32_t dest_a = 0;
1825 uint32_t dest_r = 0;
1826 uint32_t dest_g = 0;
1827 uint32_t dest_b = 0;
1828 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1829 j++) {
1830 uint32_t pixel_weight =
1831 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1832 unsigned long argb = m_SrcPalette[src_scan[j]];
1833 dest_a += pixel_weight * FXARGB_A(argb);
1834 dest_r += pixel_weight * FXARGB_R(argb);
1835 dest_g += pixel_weight * FXARGB_G(argb);
1836 dest_b += pixel_weight * FXARGB_B(argb);
1837 }
1838 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1839 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1840 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1841 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_a);
1842 } break;
1843 case 9: {
1844 uint32_t dest_b = 0;
1845 uint32_t dest_g = 0;
1846 uint32_t dest_r = 0;
1847 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1848 j++) {
1849 uint32_t pixel_weight =
1850 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1851 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1852 dest_b += pixel_weight * (*src_pixel++);
1853 dest_g += pixel_weight * (*src_pixel++);
1854 dest_r += pixel_weight * (*src_pixel);
1855 }
1856 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1857 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1858 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1859 dest_scan += dest_bytes_per_pixel - 3;
1860 } break;
1861 case 10: {
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 uint32_t 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++ = CStretchEngine::PixelFromFixed(dest_b);
1881 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1882 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1883 dest_scan += dest_bytes_per_pixel - 3;
1884 } break;
1885 case 11: {
1886 uint32_t dest_alpha = 0;
1887 uint32_t dest_r = 0;
1888 uint32_t dest_g = 0;
1889 uint32_t dest_b = 0;
1890 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1891 j++) {
1892 uint32_t pixel_weight =
1893 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1894 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1895 pixel_weight = pixel_weight * src_pixel[3] / 255;
1896 dest_b += pixel_weight * (*src_pixel++);
1897 dest_g += pixel_weight * (*src_pixel++);
1898 dest_r += pixel_weight * (*src_pixel);
1899 dest_alpha += pixel_weight;
1900 }
1901 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1902 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1903 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1904 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_alpha * 255);
1905 } break;
1906 default:
1907 return;
1908 }
1909 }
1910 }
1911
ResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int dest_row)1912 void ProgressiveDecoder::ResampleVert(
1913 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1914 double scale_y,
1915 int dest_row) {
1916 int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
1917 uint32_t dest_ScanOffset = m_startX * dest_Bpp;
1918 int dest_top = m_startY;
1919 FX_SAFE_INT32 check_dest_row_1 = dest_row;
1920 check_dest_row_1 -= pdfium::base::checked_cast<int>(scale_y);
1921 int dest_row_1 = check_dest_row_1.ValueOrDie();
1922 if (dest_row_1 < dest_top) {
1923 int dest_bottom = dest_top + m_sizeY;
1924 if (dest_row + (int)scale_y >= dest_bottom - 1) {
1925 pdfium::span<const uint8_t> scan_src =
1926 pDeviceBitmap->GetScanline(dest_row).subspan(dest_ScanOffset,
1927 m_sizeX * dest_Bpp);
1928 while (++dest_row < dest_bottom) {
1929 fxcrt::spanmove(pDeviceBitmap->GetWritableScanline(dest_row).subspan(
1930 dest_ScanOffset),
1931 scan_src);
1932 }
1933 }
1934 return;
1935 }
1936 for (; dest_row_1 < dest_row; dest_row_1++) {
1937 uint8_t* scan_des = pDeviceBitmap->GetWritableScanline(dest_row_1)
1938 .subspan(dest_ScanOffset)
1939 .data();
1940 PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
1941 const uint8_t* scan_src1 =
1942 pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top)
1943 .subspan(dest_ScanOffset)
1944 .data();
1945 const uint8_t* scan_src2 =
1946 pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top)
1947 .subspan(dest_ScanOffset)
1948 .data();
1949 switch (pDeviceBitmap->GetFormat()) {
1950 case FXDIB_Format::kInvalid:
1951 case FXDIB_Format::k1bppMask:
1952 case FXDIB_Format::k1bppRgb:
1953 return;
1954 case FXDIB_Format::k8bppMask:
1955 case FXDIB_Format::k8bppRgb:
1956 if (pDeviceBitmap->HasPalette())
1957 return;
1958 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1959 uint32_t dest_g = 0;
1960 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
1961 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
1962 *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
1963 }
1964 break;
1965 case FXDIB_Format::kRgb:
1966 case FXDIB_Format::kRgb32:
1967 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1968 uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
1969 uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
1970 uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
1971 scan_src1 += dest_Bpp - 3;
1972 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
1973 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
1974 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
1975 scan_src2 += dest_Bpp - 3;
1976 *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
1977 *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
1978 *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
1979 scan_des += dest_Bpp - 3;
1980 }
1981 break;
1982 case FXDIB_Format::kArgb:
1983 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1984 uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
1985 uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
1986 uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
1987 uint32_t dest_a = pWeight->m_Weights[0] * (*scan_src1++);
1988 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
1989 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
1990 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
1991 dest_a += pWeight->m_Weights[1] * (*scan_src2++);
1992 *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
1993 *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
1994 *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
1995 *scan_des++ = CStretchEngine::PixelFromFixed(dest_a);
1996 }
1997 break;
1998 }
1999 }
2000 int dest_bottom = dest_top + m_sizeY;
2001 if (dest_row + (int)scale_y >= dest_bottom - 1) {
2002 pdfium::span<const uint8_t> scan_src =
2003 pDeviceBitmap->GetScanline(dest_row).subspan(dest_ScanOffset,
2004 m_sizeX * dest_Bpp);
2005 while (++dest_row < dest_bottom) {
2006 fxcrt::spanmove(
2007 pDeviceBitmap->GetWritableScanline(dest_row).subspan(dest_ScanOffset),
2008 scan_src);
2009 }
2010 }
2011 }
2012
Resample(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int32_t src_line,uint8_t * src_scan,FXCodec_Format src_format)2013 void ProgressiveDecoder::Resample(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
2014 int32_t src_line,
2015 uint8_t* src_scan,
2016 FXCodec_Format src_format) {
2017 int src_top = m_clipBox.top;
2018 int dest_top = m_startY;
2019 int src_height = m_clipBox.Height();
2020 int dest_height = m_sizeY;
2021 if (src_line >= src_top) {
2022 double scale_y = static_cast<double>(dest_height) / src_height;
2023 int src_row = src_line - src_top;
2024 int dest_row = (int)(src_row * scale_y) + dest_top;
2025 if (dest_row >= dest_top + dest_height)
2026 return;
2027
2028 ResampleScanline(pDeviceBitmap, dest_row, m_DecodeBuf, src_format);
2029 if (scale_y > 1.0)
2030 ResampleVert(pDeviceBitmap, scale_y, dest_row);
2031 }
2032 }
2033
GetFrames()2034 std::pair<FXCODEC_STATUS, size_t> ProgressiveDecoder::GetFrames() {
2035 if (!(m_status == FXCODEC_STATUS::kFrameReady ||
2036 m_status == FXCODEC_STATUS::kFrameToBeContinued)) {
2037 return {FXCODEC_STATUS::kError, 0};
2038 }
2039
2040 switch (m_imageType) {
2041 #ifdef PDF_ENABLE_XFA_BMP
2042 case FXCODEC_IMAGE_BMP:
2043 #endif // PDF_ENABLE_XFA_BMP
2044 case FXCODEC_IMAGE_JPG:
2045 #ifdef PDF_ENABLE_XFA_PNG
2046 case FXCODEC_IMAGE_PNG:
2047 #endif // PDF_ENABLE_XFA_PNG
2048 #ifdef PDF_ENABLE_XFA_TIFF
2049 case FXCODEC_IMAGE_TIFF:
2050 #endif // PDF_ENABLE_XFA_TIFF
2051 m_FrameNumber = 1;
2052 m_status = FXCODEC_STATUS::kDecodeReady;
2053 return {m_status, 1};
2054 #ifdef PDF_ENABLE_XFA_GIF
2055 case FXCODEC_IMAGE_GIF: {
2056 while (true) {
2057 GifDecoder::Status readResult;
2058 std::tie(readResult, m_FrameNumber) =
2059 GifDecoder::LoadFrameInfo(m_pGifContext.get());
2060 while (readResult == GifDecoder::Status::kUnfinished) {
2061 FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
2062 if (!GifReadMoreData(&error_status))
2063 return {error_status, 0};
2064
2065 std::tie(readResult, m_FrameNumber) =
2066 GifDecoder::LoadFrameInfo(m_pGifContext.get());
2067 }
2068 if (readResult == GifDecoder::Status::kSuccess) {
2069 m_status = FXCODEC_STATUS::kDecodeReady;
2070 return {m_status, m_FrameNumber};
2071 }
2072 m_pGifContext = nullptr;
2073 m_status = FXCODEC_STATUS::kError;
2074 return {m_status, 0};
2075 }
2076 }
2077 #endif // PDF_ENABLE_XFA_GIF
2078 default:
2079 return {FXCODEC_STATUS::kError, 0};
2080 }
2081 }
2082
StartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap,int start_x,int start_y,int size_x,int size_y)2083 FXCODEC_STATUS ProgressiveDecoder::StartDecode(
2084 const RetainPtr<CFX_DIBitmap>& pDIBitmap,
2085 int start_x,
2086 int start_y,
2087 int size_x,
2088 int size_y) {
2089 if (m_status != FXCODEC_STATUS::kDecodeReady)
2090 return FXCODEC_STATUS::kError;
2091
2092 if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0)
2093 return FXCODEC_STATUS::kError;
2094
2095 m_pDeviceBitmap = pDIBitmap;
2096 if (m_clipBox.IsEmpty())
2097 return FXCODEC_STATUS::kError;
2098 if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535)
2099 return FXCODEC_STATUS::kError;
2100
2101 FX_RECT device_rc =
2102 FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y);
2103 int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth();
2104 int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight();
2105 device_rc.Intersect(
2106 FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight()));
2107 if (device_rc.IsEmpty())
2108 return FXCODEC_STATUS::kError;
2109
2110 m_startX = device_rc.left;
2111 m_startY = device_rc.top;
2112 m_sizeX = device_rc.Width();
2113 m_sizeY = device_rc.Height();
2114 m_FrameCur = 0;
2115 if (start_x < 0 || out_range_x > 0) {
2116 float scaleX = (float)m_clipBox.Width() / (float)size_x;
2117 if (start_x < 0) {
2118 m_clipBox.left -= static_cast<int32_t>(ceil((float)start_x * scaleX));
2119 }
2120 if (out_range_x > 0) {
2121 m_clipBox.right -=
2122 static_cast<int32_t>(floor((float)out_range_x * scaleX));
2123 }
2124 }
2125 if (start_y < 0 || out_range_y > 0) {
2126 float scaleY = (float)m_clipBox.Height() / (float)size_y;
2127 if (start_y < 0) {
2128 m_clipBox.top -= static_cast<int32_t>(ceil((float)start_y * scaleY));
2129 }
2130 if (out_range_y > 0) {
2131 m_clipBox.bottom -=
2132 static_cast<int32_t>(floor((float)out_range_y * scaleY));
2133 }
2134 }
2135 if (m_clipBox.IsEmpty()) {
2136 return FXCODEC_STATUS::kError;
2137 }
2138 switch (m_imageType) {
2139 #ifdef PDF_ENABLE_XFA_BMP
2140 case FXCODEC_IMAGE_BMP:
2141 return BmpStartDecode();
2142 #endif // PDF_ENABLE_XFA_BMP
2143 #ifdef PDF_ENABLE_XFA_GIF
2144 case FXCODEC_IMAGE_GIF:
2145 return GifStartDecode();
2146 #endif // PDF_ENABLE_XFA_GIF
2147 case FXCODEC_IMAGE_JPG:
2148 return JpegStartDecode(pDIBitmap->GetFormat());
2149 #ifdef PDF_ENABLE_XFA_PNG
2150 case FXCODEC_IMAGE_PNG:
2151 return PngStartDecode();
2152 #endif // PDF_ENABLE_XFA_PNG
2153 #ifdef PDF_ENABLE_XFA_TIFF
2154 case FXCODEC_IMAGE_TIFF:
2155 m_status = FXCODEC_STATUS::kDecodeToBeContinued;
2156 return m_status;
2157 #endif // PDF_ENABLE_XFA_TIFF
2158 default:
2159 return FXCODEC_STATUS::kError;
2160 }
2161 }
2162
ContinueDecode()2163 FXCODEC_STATUS ProgressiveDecoder::ContinueDecode() {
2164 if (m_status != FXCODEC_STATUS::kDecodeToBeContinued)
2165 return FXCODEC_STATUS::kError;
2166
2167 switch (m_imageType) {
2168 case FXCODEC_IMAGE_JPG:
2169 return JpegContinueDecode();
2170 #ifdef PDF_ENABLE_XFA_BMP
2171 case FXCODEC_IMAGE_BMP:
2172 return BmpContinueDecode();
2173 #endif // PDF_ENABLE_XFA_BMP
2174 #ifdef PDF_ENABLE_XFA_GIF
2175 case FXCODEC_IMAGE_GIF:
2176 return GifContinueDecode();
2177 #endif // PDF_ENABLE_XFA_GIF
2178 #ifdef PDF_ENABLE_XFA_PNG
2179 case FXCODEC_IMAGE_PNG:
2180 return PngContinueDecode();
2181 #endif // PDF_ENABLE_XFA_PNG
2182 #ifdef PDF_ENABLE_XFA_TIFF
2183 case FXCODEC_IMAGE_TIFF:
2184 return TiffContinueDecode();
2185 #endif // PDF_ENABLE_XFA_TIFF
2186 default:
2187 return FXCODEC_STATUS::kError;
2188 }
2189 }
2190
2191 } // namespace fxcodec
2192