Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
progressive_decoder.cpp
Go to the documentation of this file.
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
41namespace fxcodec {
42
43namespace {
44
45constexpr size_t kBlockSize = 4096;
46
47#ifdef PDF_ENABLE_XFA_PNG
48#if BUILDFLAG(IS_APPLE)
49const double kPngGamma = 1.7;
50#else
51const double kPngGamma = 2.2;
52#endif // BUILDFLAG(IS_APPLE)
53#endif // PDF_ENABLE_XFA_PNG
54
55void 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
70ProgressiveDecoder::HorzTable::HorzTable() = default;
71
72ProgressiveDecoder::HorzTable::~HorzTable() = default;
73
74void 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;
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;
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;
109 ((float)dest_col - (float)dest_col_index) / (float)dest_col_len);
110 pWeight->m_Weights[1] =
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;
123 pWeight->m_Weights[1] = 0;
124 }
125}
126
127ProgressiveDecoder::VertTable::VertTable() = default;
128
129ProgressiveDecoder::VertTable::~VertTable() = default;
130
131void 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;
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;
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;
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;
181 (float)(end_step - dest_row) / (float)length);
182 pWeight->m_Weights[1] =
184 }
185 }
186}
187
188ProgressiveDecoder::ProgressiveDecoder() = default;
189
190ProgressiveDecoder::~ProgressiveDecoder() = default;
191
192#ifdef PDF_ENABLE_XFA_PNG
194 int height,
195 int bpc,
196 int pass,
197 int* color_type,
198 double* gamma) {
199 if (!m_pDeviceBitmap) {
202 m_SrcBPC = bpc;
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 }
226 switch (format) {
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:
243 }
244 *gamma = kPngGamma;
245 return true;
246}
247
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;
259 int32_t dest_Bpp = (m_SrcFormat & 0xff) >> 3;
262 pdfium::span<const uint8_t> src_span =
266 const uint8_t* src_scan = src_span.data();
268 switch (pDIBitmap->GetFormat()) {
271 for (int32_t src_col = 0; src_col < m_sizeX; src_col++) {
274 continue;
276 }
277 return true;
280 if (pDIBitmap->HasPalette())
281 return false;
282 for (int32_t src_col = 0; src_col < m_sizeX; src_col++) {
285 continue;
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++) {
296 continue;
297 const uint8_t* p = src_scan + src_col * src_Bpp;
305 }
306 return true;
307 case FXDIB_Format::kArgb:
308 for (int32_t src_col = 0; src_col < m_sizeX; src_col++) {
311 continue;
312 const uint8_t* p = src_scan + src_col * src_Bpp;
316 uint8_t dest_a = *p;
321 *pDes = dest_a;
322 }
323 return true;
324 default:
325 return false;
326 }
327}
328
332 int src_top = m_clipBox.top;
334 int dest_top = m_startY;
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 }
345 if (m_SrcPassNumber == 1 && scale_y > 1.0) {
347 return;
348 }
349 if (pass == 6 && scale_y > 1.0) {
351 }
352 }
353}
354#endif // PDF_ENABLE_XFA_PNG
355
356#ifdef PDF_ENABLE_XFA_GIF
360 return m_offSet - remain_size;
361}
362
364 const FX_RECT& img_rc,
368 bool interlace) {
370
374 return false;
375
376 CFX_GifPalette* pPalette = nullptr;
377 if (pal_num != 0 && pal_ptr) {
379 } else {
380 if (!m_pGifPalette)
381 return false;
384 }
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 }
393 m_SrcPassNumber = interlace ? 4 : 1;
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())
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;
412 for (int row = 0; row < sizeY; row++) {
415 switch (m_TransMethod) {
416 case 3: {
417 uint8_t gray =
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++) {
434 pScanline += 4;
435 }
436 break;
437 }
438 }
439 }
440 return true;
441}
442
448 if (!pDIBitmap->IsAlphaFormat()) {
450 for (int i = 0; i < img_width; i++) {
453 }
455 }
456 }
460 }
465
466 bool bLastPass = (row_num % 2) == 1;
468 int src_top = m_clipBox.top;
470 int dest_top = m_startY;
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;
480 return;
481
483 if (scale_y > 1.0 && m_SrcPassNumber == 1) {
485 return;
486 }
487 if (scale_y <= 1.0)
488 return;
489
491 int dest_Bpp = pDIBitmap->GetBPP() >> 3;
493 if (dest_row + (int)scale_y >= dest_bottom - 1) {
494 const uint8_t* scan_src =
496 int cur_row = dest_row;
497 while (++cur_row < dest_bottom) {
500 .data();
503 }
504 }
505 if (bLastPass)
507}
508#endif // PDF_ENABLE_XFA_GIF
509
510#ifdef PDF_ENABLE_XFA_BMP
515}
516
518 pdfium::span<const uint8_t> row_buf) {
521
523
524 int src_top = m_clipBox.top;
526 int dest_top = m_startY;
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;
538 return;
539
541 if (scale_y <= 1.0)
542 return;
543
544 if (m_BmpIsTopBottom) {
546 return;
547 }
549}
550
553 double scale_y,
554 int dest_row) {
555 int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
557 int dest_top = m_startY;
562 if (dest_row_1 >= dest_bottom - 1) {
563 const uint8_t* scan_src =
565 while (++dest_row < dest_bottom) {
568 .data();
571 }
572 return;
573 }
574 for (; dest_row_1 > dest_row; dest_row_1--) {
577 .data();
579 const uint8_t* scan_src1 =
582 .data();
583 const uint8_t* scan_src2 =
586 .data();
587 switch (pDeviceBitmap->GetFormat()) {
591 return;
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++);
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++) {
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;
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++) {
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++);
634 }
635 break;
636 }
637 }
638}
639
643 BmpDecoder::StartDecode(this);
645
646 const std::vector<uint32_t>* palette;
654 return false;
655 }
659 }
660
663 return false;
664 }
665
667 switch (m_SrcComponents) {
668 case 1:
671 break;
672 case 3:
675 break;
676 case 4:
679 break;
680 default:
682 return false;
683 }
684
685 // Set to 0 to make CalculatePitchAndSize() calculate it.
686 constexpr uint32_t kNoPitch = 0;
689 kNoPitch);
690 if (!needed_data.has_value()) {
692 return false;
693 }
694
700 return false;
701 }
702
703 m_SrcBPC = 8;
706 if (m_SrcPaletteNumber) {
709 m_SrcPaletteNumber * sizeof(FX_ARGB));
710 } else {
712 }
713 return true;
714}
715
720 err_status);
721}
722
733 return m_status;
734}
735
738 while (read_res == BmpDecoder::Status::kContinue) {
741 m_pDeviceBitmap = nullptr;
742 m_pFile = nullptr;
744 return m_status;
745 }
747 }
748
749 m_pDeviceBitmap = nullptr;
750 m_pFile = nullptr;
754 return m_status;
755}
756#endif // PDF_ENABLE_XFA_BMP
757
758#ifdef PDF_ENABLE_XFA_GIF
761 err_status);
762}
763
767 m_SrcComponents = 1;
774 m_pGifContext = nullptr;
776 return false;
777 }
778 readResult =
781 }
783 m_SrcBPC = 8;
785 return true;
786 }
787 m_pGifContext = nullptr;
789 return false;
790}
791
802 m_FrameCur = 0;
804 return m_status;
805}
806
810 while (readRes == GifDecoder::Status::kUnfinished) {
813 m_pDeviceBitmap = nullptr;
814 m_pFile = nullptr;
816 return m_status;
817 }
819 }
820
822 m_pDeviceBitmap = nullptr;
823 m_pFile = nullptr;
825 return m_status;
826 }
827
828 m_pDeviceBitmap = nullptr;
829 m_pFile = nullptr;
831 return m_status;
832}
833
836 double scale_y,
837 int dest_row) {
838 int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
840 int dest_top = m_startY;
842 scale_y2 *= 2;
847 for (; dest_row_1 < dest_row; dest_row_1++) {
850 .data();
852 const uint8_t* scan_src1 =
855 .data();
856 const uint8_t* scan_src2 =
859 .data();
860 switch (pDeviceBitmap->GetFormat()) {
864 return;
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++);
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++) {
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;
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++) {
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++);
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) {
915 }
916}
917#endif // PDF_ENABLE_XFA_GIF
918
919bool ProgressiveDecoder::JpegReadMoreData(FXCODEC_STATUS* err_status) {
920 return ReadMoreData(JpegProgressiveDecoder::GetInstance(),
921 m_pJpegContext.get(), err_status);
922}
923
924bool 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) {
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
965FXCODEC_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;
973 }
974
975 bool startStatus =
976 JpegProgressiveDecoder::StartScanline(m_pJpegContext.get(), down_scale);
977 while (!startStatus) {
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);
1010 return m_status;
1011}
1012
1013FXCODEC_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;
1021 }
1022
1023 while (true) {
1024 bool readRes = JpegProgressiveDecoder::ReadScanline(m_pJpegContext.get(),
1025 m_DecodeBuf.data());
1026 while (!readRes) {
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;
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
1058 int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3;
1065 .data();
1066 switch (pDeviceBitmap->GetFormat()) {
1067 case FXDIB_Format::k1bppMask:
1068 case FXDIB_Format::k1bppRgb:
1070 case FXDIB_Format::k8bppMask:
1071 case FXDIB_Format::k8bppRgb:
1073 return;
1074 for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) {
1078 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++) {
1092 dest_b += pPixelWeights->m_Weights[1] * (*p++);
1093 dest_g += pPixelWeights->m_Weights[1] * (*p++);
1094 dest_r += pPixelWeights->m_Weights[1] * (*p);
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++) {
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);
1118 }
1119 break;
1120 default:
1121 return;
1122 }
1123}
1124
1128 if (!m_pPngContext) {
1130 return false;
1131 }
1133 pAttribute)) {
1134 uint32_t remain_size = static_cast<uint32_t>(m_pFile->GetSize()) - m_offSet;
1136 if (input_size == 0) {
1139 return false;
1140 }
1143
1147 return false;
1148 }
1150 }
1152 if (m_SrcPassNumber == 0) {
1154 return false;
1155 }
1156 return true;
1157}
1158
1161 if (!m_pPngContext) {
1162 m_pDeviceBitmap = nullptr;
1163 m_pFile = nullptr;
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;
1173 break;
1174 case FXDIB_Format::kRgb:
1175 m_SrcComponents = 3;
1177 break;
1178 case FXDIB_Format::kRgb32:
1179 case FXDIB_Format::kArgb:
1180 m_SrcComponents = 4;
1182 break;
1183 default: {
1184 m_pDeviceBitmap = nullptr;
1185 m_pFile = nullptr;
1187 return m_status;
1188 }
1189 }
1196 return m_status;
1197}
1198
1200 while (true) {
1203 if (input_size == 0) {
1205 m_pDeviceBitmap = nullptr;
1206 m_pFile = nullptr;
1208 return m_status;
1209 }
1212
1215 if (!bResult) {
1216 m_pDeviceBitmap = nullptr;
1217 m_pFile = nullptr;
1219 return m_status;
1220 }
1223 nullptr);
1224 if (!bResult) {
1225 m_pDeviceBitmap = nullptr;
1226 m_pFile = nullptr;
1228 return m_status;
1229 }
1230 }
1231}
1232#endif // PDF_ENABLE_XFA_PNG
1233
1234#ifdef PDF_ENABLE_XFA_TIFF
1238 if (!m_pTiffContext) {
1240 return false;
1241 }
1246 m_SrcComponents = 4;
1248 if (!ret) {
1251 return false;
1252 }
1253 return true;
1254}
1255
1257 bool ret = false;
1258 if (m_pDeviceBitmap->GetBPP() == 32 &&
1261 m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 &&
1262 m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth &&
1265 m_pDeviceBitmap = nullptr;
1266 m_pFile = nullptr;
1267 if (!ret) {
1269 return m_status;
1270 }
1272 return m_status;
1273 }
1274
1277 m_pDeviceBitmap = nullptr;
1278 m_pFile = nullptr;
1280 return m_status;
1281 }
1283 if (!ret) {
1284 m_pDeviceBitmap = nullptr;
1285 m_pFile = nullptr;
1287 return m_status;
1288 }
1290 (m_clipBox.left == 0 && m_clipBox.top == 0 &&
1292 ? pDIBitmap
1294 if (!pClipBitmap) {
1295 m_pDeviceBitmap = nullptr;
1296 m_pFile = nullptr;
1298 return m_status;
1299 }
1301 bool created_format_bitmap = false;
1302 switch (m_pDeviceBitmap->GetFormat()) {
1303 case FXDIB_Format::k8bppRgb:
1308 break;
1309 case FXDIB_Format::k8bppMask:
1314 break;
1315 case FXDIB_Format::kRgb:
1320 break;
1321 case FXDIB_Format::kRgb32:
1326 break;
1327 case FXDIB_Format::kArgb:
1329 created_format_bitmap = true;
1330 break;
1331 default:
1332 break;
1333 }
1334 if (!created_format_bitmap) {
1335 m_pDeviceBitmap = nullptr;
1336 m_pFile = nullptr;
1338 return m_status;
1339 }
1340
1341 switch (m_pDeviceBitmap->GetFormat()) {
1342 case FXDIB_Format::k8bppRgb:
1343 case FXDIB_Format::k8bppMask: {
1344 for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1347 for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1348 uint8_t _a = 255 - src_line[3];
1349 uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1350 uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1351 uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1352 *dest_line++ = FXRGB2GRAY(r, g, b);
1353 src_line += 4;
1354 }
1355 }
1356 } break;
1357 case FXDIB_Format::kRgb:
1358 case FXDIB_Format::kRgb32: {
1359 int32_t desBpp =
1360 (m_pDeviceBitmap->GetFormat() == FXDIB_Format::kRgb) ? 3 : 4;
1361 for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
1364 for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
1365 uint8_t _a = 255 - src_line[3];
1366 uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
1367 uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
1368 uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
1369 *dest_line++ = b;
1370 *dest_line++ = g;
1371 *dest_line++ = r;
1372 dest_line += desBpp - 3;
1373 src_line += 4;
1374 }
1375 }
1376 } break;
1377 default:
1378 break;
1379 }
1380
1385 pFormatBitmap = nullptr;
1386 if (!pStrechBitmap) {
1387 m_pDeviceBitmap = nullptr;
1388 m_pFile = nullptr;
1390 return m_status;
1391 }
1393 std::move(pStrechBitmap), 0, 0);
1394 m_pDeviceBitmap = nullptr;
1395 m_pFile = nullptr;
1397 return m_status;
1398}
1399#endif // PDF_ENABLE_XFA_TIFF
1400
1401bool ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType,
1402 CFX_DIBAttribute* pAttribute) {
1403#ifdef PDF_ENABLE_XFA_TIFF
1404 if (imageType == FXCODEC_IMAGE_TIFF)
1405 return TiffDetectImageTypeFromFile(pAttribute);
1406#endif // PDF_ENABLE_XFA_TIFF
1407
1408 size_t size = pdfium::base::checked_cast<size_t>(
1409 std::min<FX_FILESIZE>(m_pFile->GetSize(), kBlockSize));
1410 m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(size);
1411 m_offSet = 0;
1412 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().first(size),
1413 m_offSet)) {
1414 m_status = FXCODEC_STATUS::kError;
1415 return false;
1416 }
1417 m_offSet += size;
1418
1419 if (imageType == FXCODEC_IMAGE_JPG)
1420 return JpegDetectImageTypeInBuffer(pAttribute);
1421
1422#ifdef PDF_ENABLE_XFA_BMP
1423 if (imageType == FXCODEC_IMAGE_BMP)
1424 return BmpDetectImageTypeInBuffer(pAttribute);
1425#endif // PDF_ENABLE_XFA_BMP
1426
1427#ifdef PDF_ENABLE_XFA_GIF
1428 if (imageType == FXCODEC_IMAGE_GIF)
1429 return GifDetectImageTypeInBuffer();
1430#endif // PDF_ENABLE_XFA_GIF
1431
1432#ifdef PDF_ENABLE_XFA_PNG
1433 if (imageType == FXCODEC_IMAGE_PNG)
1434 return PngDetectImageTypeInBuffer(pAttribute);
1435#endif // PDF_ENABLE_XFA_PNG
1436
1437 m_status = FXCODEC_STATUS::kError;
1438 return false;
1439}
1440
1441bool ProgressiveDecoder::ReadMoreData(
1442 ProgressiveDecoderIface* pModule,
1444 FXCODEC_STATUS* err_status) {
1445 // Check for EOF.
1446 if (m_offSet >= static_cast<uint32_t>(m_pFile->GetSize()))
1447 return false;
1448
1449 // Try to get whatever remains.
1450 uint32_t dwBytesToFetchFromFile =
1451 pdfium::base::checked_cast<uint32_t>(m_pFile->GetSize() - m_offSet);
1452
1453 // Figure out if the codec stopped processing midway through the buffer.
1454 size_t dwUnconsumed;
1455 FX_SAFE_SIZE_T avail_input = pModule->GetAvailInput(pContext);
1456 if (!avail_input.AssignIfValid(&dwUnconsumed))
1457 return false;
1458
1459 if (dwUnconsumed == m_pCodecMemory->GetSize()) {
1460 // Codec couldn't make any progress against the bytes in the buffer.
1461 // Increase the buffer size so that there might be enough contiguous
1462 // bytes to allow whatever operation is having difficulty to succeed.
1463 dwBytesToFetchFromFile =
1464 std::min<uint32_t>(dwBytesToFetchFromFile, kBlockSize);
1465 size_t dwNewSize = m_pCodecMemory->GetSize() + dwBytesToFetchFromFile;
1466 if (!m_pCodecMemory->TryResize(dwNewSize)) {
1467 *err_status = FXCODEC_STATUS::kError;
1468 return false;
1469 }
1470 } else {
1471 // TODO(crbug.com/pdfium/1904): Simplify the `CFX_CodecMemory` API so we
1472 // don't need to do this awkward dance to free up exactly enough buffer
1473 // space for the next read.
1474 size_t dwConsumable = m_pCodecMemory->GetSize() - dwUnconsumed;
1475 dwBytesToFetchFromFile = pdfium::base::checked_cast<uint32_t>(
1476 std::min<size_t>(dwBytesToFetchFromFile, dwConsumable));
1477 m_pCodecMemory->Consume(dwBytesToFetchFromFile);
1478 m_pCodecMemory->Seek(dwConsumable - dwBytesToFetchFromFile);
1479 dwUnconsumed += m_pCodecMemory->GetPosition();
1480 }
1481
1482 // Append new data past the bytes not yet processed by the codec.
1483 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().subspan(
1484 dwUnconsumed, dwBytesToFetchFromFile),
1485 m_offSet)) {
1486 *err_status = FXCODEC_STATUS::kError;
1487 return false;
1488 }
1489 m_offSet += dwBytesToFetchFromFile;
1490 return pModule->Input(pContext, m_pCodecMemory);
1491}
1492
1493FXCODEC_STATUS ProgressiveDecoder::LoadImageInfo(
1495 FXCODEC_IMAGE_TYPE imageType,
1496 CFX_DIBAttribute* pAttribute,
1497 bool bSkipImageTypeCheck) {
1498 DCHECK(pAttribute);
1499
1500 switch (m_status) {
1506 default:
1507 break;
1508 }
1509 m_pFile = std::move(pFile);
1510 if (!m_pFile) {
1511 m_status = FXCODEC_STATUS::kError;
1512 return m_status;
1513 }
1514 m_offSet = 0;
1515 m_SrcWidth = m_SrcHeight = 0;
1516 m_SrcComponents = m_SrcBPC = 0;
1517 m_clipBox = FX_RECT();
1518 m_startX = m_startY = 0;
1519 m_sizeX = m_sizeY = 0;
1520 m_SrcPassNumber = 0;
1521 if (imageType != FXCODEC_IMAGE_UNKNOWN &&
1522 DetectImageType(imageType, pAttribute)) {
1523 m_imageType = imageType;
1524 m_status = FXCODEC_STATUS::kFrameReady;
1525 return m_status;
1526 }
1527 // If we got here then the image data does not match the requested decoder.
1528 // If we're skipping the type check then bail out at this point and return
1529 // the failed status.
1530 if (bSkipImageTypeCheck)
1531 return m_status;
1532
1533 for (int type = FXCODEC_IMAGE_UNKNOWN + 1; type < FXCODEC_IMAGE_MAX; type++) {
1534 if (DetectImageType(static_cast<FXCODEC_IMAGE_TYPE>(type), pAttribute)) {
1535 m_imageType = static_cast<FXCODEC_IMAGE_TYPE>(type);
1536 m_status = FXCODEC_STATUS::kFrameReady;
1537 return m_status;
1538 }
1539 }
1540 m_status = FXCODEC_STATUS::kError;
1541 m_pFile = nullptr;
1542 return m_status;
1543}
1544
1545void ProgressiveDecoder::SetClipBox(FX_RECT* clip) {
1546 if (m_status != FXCODEC_STATUS::kFrameReady)
1547 return;
1548
1549 if (clip->IsEmpty()) {
1550 m_clipBox = FX_RECT();
1551 return;
1552 }
1553 clip->left = std::max(clip->left, 0);
1554 clip->right = std::min(clip->right, m_SrcWidth);
1555 clip->top = std::max(clip->top, 0);
1556 clip->bottom = std::min(clip->bottom, m_SrcHeight);
1557 if (clip->IsEmpty()) {
1558 m_clipBox = FX_RECT();
1559 return;
1560 }
1561 m_clipBox = *clip;
1562}
1563
1564int ProgressiveDecoder::GetDownScale() {
1565 int down_scale = 1;
1566 int ratio_w = m_clipBox.Width() / m_sizeX;
1567 int ratio_h = m_clipBox.Height() / m_sizeY;
1568 int ratio = std::min(ratio_w, ratio_h);
1569 if (ratio >= 8)
1570 down_scale = 8;
1571 else if (ratio >= 4)
1572 down_scale = 4;
1573 else if (ratio >= 2)
1574 down_scale = 2;
1575
1576 m_clipBox.left /= down_scale;
1577 m_clipBox.right /= down_scale;
1578 m_clipBox.top /= down_scale;
1579 m_clipBox.bottom /= down_scale;
1580 if (m_clipBox.right == m_clipBox.left)
1581 m_clipBox.right = m_clipBox.left + 1;
1582 if (m_clipBox.bottom == m_clipBox.top)
1583 m_clipBox.bottom = m_clipBox.top + 1;
1584 return down_scale;
1585}
1586
1587void ProgressiveDecoder::GetTransMethod(FXDIB_Format dest_format,
1588 FXCodec_Format src_format) {
1589 switch (dest_format) {
1592 switch (src_format) {
1593 case FXCodec_1bppGray:
1594 m_TransMethod = 0;
1595 break;
1596 default:
1597 m_TransMethod = -1;
1598 }
1599 } break;
1602 switch (src_format) {
1603 case FXCodec_1bppGray:
1604 m_TransMethod = 1;
1605 break;
1606 case FXCodec_8bppGray:
1607 m_TransMethod = 2;
1608 break;
1609 case FXCodec_1bppRgb:
1610 case FXCodec_8bppRgb:
1611 m_TransMethod = 3;
1612 break;
1613 case FXCodec_Rgb:
1614 case FXCodec_Rgb32:
1615 case FXCodec_Argb:
1616 m_TransMethod = 4;
1617 break;
1618 case FXCodec_Cmyk:
1619 m_TransMethod = 5;
1620 break;
1621 default:
1622 m_TransMethod = -1;
1623 }
1624 } break;
1625 case FXDIB_Format::kRgb: {
1626 switch (src_format) {
1627 case FXCodec_1bppGray:
1628 m_TransMethod = 6;
1629 break;
1630 case FXCodec_8bppGray:
1631 m_TransMethod = 7;
1632 break;
1633 case FXCodec_1bppRgb:
1634 case FXCodec_8bppRgb:
1635 m_TransMethod = 8;
1636 break;
1637 case FXCodec_Rgb:
1638 case FXCodec_Rgb32:
1639 case FXCodec_Argb:
1640 m_TransMethod = 9;
1641 break;
1642 case FXCodec_Cmyk:
1643 m_TransMethod = 10;
1644 break;
1645 default:
1646 m_TransMethod = -1;
1647 }
1648 } break;
1650 case FXDIB_Format::kArgb: {
1651 switch (src_format) {
1652 case FXCodec_1bppGray:
1653 m_TransMethod = 6;
1654 break;
1655 case FXCodec_8bppGray:
1656 m_TransMethod = 7;
1657 break;
1658 case FXCodec_1bppRgb:
1659 case FXCodec_8bppRgb:
1660 if (dest_format == FXDIB_Format::kArgb) {
1661 m_TransMethod = 12;
1662 } else {
1663 m_TransMethod = 8;
1664 }
1665 break;
1666 case FXCodec_Rgb:
1667 case FXCodec_Rgb32:
1668 m_TransMethod = 9;
1669 break;
1670 case FXCodec_Cmyk:
1671 m_TransMethod = 10;
1672 break;
1673 case FXCodec_Argb:
1674 m_TransMethod = 11;
1675 break;
1676 default:
1677 m_TransMethod = -1;
1678 }
1679 } break;
1680 default:
1681 m_TransMethod = -1;
1682 }
1683}
1684
1685void ProgressiveDecoder::ResampleScanline(
1686 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1687 int dest_line,
1688 pdfium::span<uint8_t> src_span,
1689 FXCodec_Format src_format) {
1690 uint8_t* src_scan = src_span.data();
1691 int src_left = m_clipBox.left;
1692 int dest_left = m_startX;
1693 uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line).data();
1694 int src_bytes_per_pixel = (src_format & 0xff) / 8;
1695 int dest_bytes_per_pixel = pDeviceBitmap->GetBPP() / 8;
1696 src_scan += src_left * src_bytes_per_pixel;
1697 dest_scan += dest_left * dest_bytes_per_pixel;
1698 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1699 PixelWeight* pPixelWeights = m_WeightHorz.GetPixelWeight(dest_col);
1700 switch (m_TransMethod) {
1701 case -1:
1702 return;
1703 case 0:
1704 return;
1705 case 1:
1706 return;
1707 case 2: {
1708 uint32_t dest_g = 0;
1709 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1710 j++) {
1711 uint32_t pixel_weight =
1712 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1713 dest_g += pixel_weight * src_scan[j];
1714 }
1715 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1716 } break;
1717 case 3: {
1718 uint32_t dest_r = 0;
1719 uint32_t dest_g = 0;
1720 uint32_t dest_b = 0;
1721 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1722 j++) {
1723 uint32_t pixel_weight =
1724 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1725 uint32_t argb = m_SrcPalette[src_scan[j]];
1726 dest_r += pixel_weight * FXARGB_R(argb);
1727 dest_g += pixel_weight * FXARGB_G(argb);
1728 dest_b += pixel_weight * FXARGB_B(argb);
1729 }
1730 *dest_scan++ = static_cast<uint8_t>(
1734 } break;
1735 case 4: {
1736 uint32_t dest_b = 0;
1737 uint32_t dest_g = 0;
1738 uint32_t dest_r = 0;
1739 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1740 j++) {
1741 uint32_t pixel_weight =
1742 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1743 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1744 dest_b += pixel_weight * (*src_pixel++);
1745 dest_g += pixel_weight * (*src_pixel++);
1746 dest_r += pixel_weight * (*src_pixel);
1747 }
1748 *dest_scan++ = static_cast<uint8_t>(
1752 } break;
1753 case 5: {
1754 uint32_t dest_b = 0;
1755 uint32_t dest_g = 0;
1756 uint32_t dest_r = 0;
1757 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1758 j++) {
1759 uint32_t pixel_weight =
1760 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1761 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1762 uint8_t src_b = 0;
1763 uint8_t src_g = 0;
1764 uint8_t src_r = 0;
1765 std::tie(src_r, src_g, src_b) =
1766 AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1767 255 - src_pixel[2], 255 - src_pixel[3]);
1768 dest_b += pixel_weight * src_b;
1769 dest_g += pixel_weight * src_g;
1770 dest_r += pixel_weight * src_r;
1771 }
1772 *dest_scan++ = static_cast<uint8_t>(
1776 } break;
1777 case 6:
1778 return;
1779 case 7: {
1780 uint32_t dest_g = 0;
1781 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1782 j++) {
1783 uint32_t pixel_weight =
1784 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1785 dest_g += pixel_weight * src_scan[j];
1786 }
1787 memset(dest_scan, CStretchEngine::PixelFromFixed(dest_g), 3);
1788 dest_scan += dest_bytes_per_pixel;
1789 } break;
1790 case 8: {
1791 uint32_t dest_r = 0;
1792 uint32_t dest_g = 0;
1793 uint32_t dest_b = 0;
1794 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1795 j++) {
1796 uint32_t pixel_weight =
1797 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1798 uint32_t argb = m_SrcPalette[src_scan[j]];
1799 dest_r += pixel_weight * FXARGB_R(argb);
1800 dest_g += pixel_weight * FXARGB_G(argb);
1801 dest_b += pixel_weight * FXARGB_B(argb);
1802 }
1803 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1804 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1805 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1806 dest_scan += dest_bytes_per_pixel - 3;
1807 } break;
1808 case 12: {
1809#ifdef PDF_ENABLE_XFA_BMP
1810 if (m_pBmpContext) {
1811 uint32_t dest_r = 0;
1812 uint32_t dest_g = 0;
1813 uint32_t dest_b = 0;
1814 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1815 j++) {
1816 uint32_t pixel_weight =
1817 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1818 uint32_t argb = m_SrcPalette[src_scan[j]];
1819 dest_r += pixel_weight * FXARGB_R(argb);
1820 dest_g += pixel_weight * FXARGB_G(argb);
1821 dest_b += pixel_weight * FXARGB_B(argb);
1822 }
1823 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1824 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1825 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1826 *dest_scan++ = 0xFF;
1827 break;
1828 }
1829#endif // PDF_ENABLE_XFA_BMP
1830 uint32_t dest_a = 0;
1831 uint32_t dest_r = 0;
1832 uint32_t dest_g = 0;
1833 uint32_t dest_b = 0;
1834 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1835 j++) {
1836 uint32_t pixel_weight =
1837 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1838 unsigned long argb = m_SrcPalette[src_scan[j]];
1839 dest_a += pixel_weight * FXARGB_A(argb);
1840 dest_r += pixel_weight * FXARGB_R(argb);
1841 dest_g += pixel_weight * FXARGB_G(argb);
1842 dest_b += pixel_weight * FXARGB_B(argb);
1843 }
1844 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1845 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1846 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1847 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_a);
1848 } break;
1849 case 9: {
1850 uint32_t dest_b = 0;
1851 uint32_t dest_g = 0;
1852 uint32_t dest_r = 0;
1853 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1854 j++) {
1855 uint32_t pixel_weight =
1856 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1857 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1858 dest_b += pixel_weight * (*src_pixel++);
1859 dest_g += pixel_weight * (*src_pixel++);
1860 dest_r += pixel_weight * (*src_pixel);
1861 }
1862 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1863 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1864 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1865 dest_scan += dest_bytes_per_pixel - 3;
1866 } break;
1867 case 10: {
1868 uint32_t dest_b = 0;
1869 uint32_t dest_g = 0;
1870 uint32_t dest_r = 0;
1871 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1872 j++) {
1873 uint32_t pixel_weight =
1874 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1875 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1876 uint8_t src_b = 0;
1877 uint8_t src_g = 0;
1878 uint8_t src_r = 0;
1879 std::tie(src_r, src_g, src_b) =
1880 AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1881 255 - src_pixel[2], 255 - src_pixel[3]);
1882 dest_b += pixel_weight * src_b;
1883 dest_g += pixel_weight * src_g;
1884 dest_r += pixel_weight * src_r;
1885 }
1886 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1887 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1888 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1889 dest_scan += dest_bytes_per_pixel - 3;
1890 } break;
1891 case 11: {
1892 uint32_t dest_alpha = 0;
1893 uint32_t dest_r = 0;
1894 uint32_t dest_g = 0;
1895 uint32_t dest_b = 0;
1896 for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1897 j++) {
1898 uint32_t pixel_weight =
1899 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1900 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1901 pixel_weight = pixel_weight * src_pixel[3] / 255;
1902 dest_b += pixel_weight * (*src_pixel++);
1903 dest_g += pixel_weight * (*src_pixel++);
1904 dest_r += pixel_weight * (*src_pixel);
1905 dest_alpha += pixel_weight;
1906 }
1907 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1908 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1909 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1910 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_alpha * 255);
1911 } break;
1912 default:
1913 return;
1914 }
1915 }
1916}
1917
1918void ProgressiveDecoder::ResampleVert(
1919 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1920 double scale_y,
1921 int dest_row) {
1922 int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
1923 uint32_t dest_ScanOffset = m_startX * dest_Bpp;
1924 int dest_top = m_startY;
1925 FX_SAFE_INT32 check_dest_row_1 = dest_row;
1926 check_dest_row_1 -= pdfium::base::checked_cast<int>(scale_y);
1927 int dest_row_1 = check_dest_row_1.ValueOrDie();
1928 if (dest_row_1 < dest_top) {
1929 int dest_bottom = dest_top + m_sizeY;
1930 if (dest_row + (int)scale_y >= dest_bottom - 1) {
1931 pdfium::span<const uint8_t> scan_src =
1932 pDeviceBitmap->GetScanline(dest_row).subspan(dest_ScanOffset,
1933 m_sizeX * dest_Bpp);
1934 while (++dest_row < dest_bottom) {
1935 fxcrt::spanmove(pDeviceBitmap->GetWritableScanline(dest_row).subspan(
1936 dest_ScanOffset),
1937 scan_src);
1938 }
1939 }
1940 return;
1941 }
1942 for (; dest_row_1 < dest_row; dest_row_1++) {
1943 uint8_t* scan_des = pDeviceBitmap->GetWritableScanline(dest_row_1)
1944 .subspan(dest_ScanOffset)
1945 .data();
1946 PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
1947 const uint8_t* scan_src1 =
1948 pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top)
1949 .subspan(dest_ScanOffset)
1950 .data();
1951 const uint8_t* scan_src2 =
1952 pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top)
1953 .subspan(dest_ScanOffset)
1954 .data();
1955 switch (pDeviceBitmap->GetFormat()) {
1956 case FXDIB_Format::kInvalid:
1957 case FXDIB_Format::k1bppMask:
1958 case FXDIB_Format::k1bppRgb:
1959 return;
1960 case FXDIB_Format::k8bppMask:
1961 case FXDIB_Format::k8bppRgb:
1962 if (pDeviceBitmap->HasPalette())
1963 return;
1964 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1965 uint32_t dest_g = 0;
1966 dest_g += pWeight->m_Weights[0] * (*scan_src1++);
1967 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
1968 *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
1969 }
1970 break;
1971 case FXDIB_Format::kRgb:
1972 case FXDIB_Format::kRgb32:
1973 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1974 uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
1975 uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
1976 uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
1977 scan_src1 += dest_Bpp - 3;
1978 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
1979 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
1980 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
1981 scan_src2 += dest_Bpp - 3;
1982 *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
1983 *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
1984 *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
1985 scan_des += dest_Bpp - 3;
1986 }
1987 break;
1988 case FXDIB_Format::kArgb:
1989 for (int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1990 uint32_t dest_b = pWeight->m_Weights[0] * (*scan_src1++);
1991 uint32_t dest_g = pWeight->m_Weights[0] * (*scan_src1++);
1992 uint32_t dest_r = pWeight->m_Weights[0] * (*scan_src1++);
1993 uint32_t dest_a = pWeight->m_Weights[0] * (*scan_src1++);
1994 dest_b += pWeight->m_Weights[1] * (*scan_src2++);
1995 dest_g += pWeight->m_Weights[1] * (*scan_src2++);
1996 dest_r += pWeight->m_Weights[1] * (*scan_src2++);
1997 dest_a += pWeight->m_Weights[1] * (*scan_src2++);
1998 *scan_des++ = CStretchEngine::PixelFromFixed(dest_b);
1999 *scan_des++ = CStretchEngine::PixelFromFixed(dest_g);
2000 *scan_des++ = CStretchEngine::PixelFromFixed(dest_r);
2001 *scan_des++ = CStretchEngine::PixelFromFixed(dest_a);
2002 }
2003 break;
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
2019void 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
2040std::pair<FXCODEC_STATUS, size_t> ProgressiveDecoder::GetFrames() {
2041 if (!(m_status == FXCODEC_STATUS::kFrameReady ||
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;
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
2089FXCODEC_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)
2097
2098 if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0)
2100
2101 m_pDeviceBitmap = pDIBitmap;
2102 if (m_clipBox.IsEmpty())
2104 if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535)
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())
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()) {
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:
2166 }
2167}
2168
2169FXCODEC_STATUS ProgressiveDecoder::ContinueDecode() {
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:
2194 }
2195}
2196
2197} // namespace fxcodec
static uint32_t FixedFromFloat(float f)
static uint8_t PixelFromFixed(uint32_t fixed)
static constexpr uint32_t kFixedPointOne
std::pair< FXCODEC_STATUS, size_t > GetFrames()
FXCODEC_STATUS LoadImageInfo(RetainPtr< IFX_SeekableReadStream > pFile, FXCODEC_IMAGE_TYPE imageType, CFX_DIBAttribute *pAttribute, bool bSkipImageTypeCheck)
FXCODEC_STATUS StartDecode(const RetainPtr< CFX_DIBitmap > &pDIBitmap, int start_x, int start_y, int size_x, int size_y)
FXCODEC_STATUS
#define FXRGB2GRAY(r, g, b)
Definition fx_dib.h:131
#define FXARGB_B(argb)
Definition fx_dib.h:127
#define FXARGB_G(argb)
Definition fx_dib.h:126
#define FXARGB_A(argb)
Definition fx_dib.h:124
#define FXARGB_R(argb)
Definition fx_dib.h:125
FXDIB_Format
Definition fx_dib.h:19
int FXSYS_roundf(float f)
Definition fx_system.cpp:92
#define FX_FILESIZE
Definition fx_types.h:19
bool bInterpolateBilinear
Definition fx_dib.h:41
FX_RECT & operator=(const FX_RECT &that)=default
int Height() const
int32_t bottom
int32_t right
int Width() const
constexpr FX_RECT()=default
int32_t top
int32_t left
bool IsEmpty() const
constexpr FX_RECT(int l, int t, int r, int b)