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