14d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Copyright 2014 PDFium Authors. All rights reserved.
24d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Use of this source code is governed by a BSD-style license that can be
34d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// found in the LICENSE file.
44d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
54d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
64d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
74d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <setjmp.h>
84d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
94d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <memory>
104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <utility>
114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcodec/codec/codec_int.h"
134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcodec/fx_codec.h"
144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcrt/fx_safe_types.h"
154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxge/fx_dib.h"
164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "third_party/base/ptr_util.h"
174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannextern "C" {
194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#undef FAR
204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if defined(USE_SYSTEM_LIBJPEG)
214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include <jpeglib.h>
224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#elif defined(USE_LIBJPEG_TURBO)
234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "third_party/libjpeg_turbo/jpeglib.h"
244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else
254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "third_party/libjpeg/jpeglib.h"
264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannextern "C" {
304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void JpegScanSOI(const uint8_t** src_buf, uint32_t* src_size) {
324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (*src_size == 0)
334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return;
344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t offset = 0;
364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  while (offset < *src_size - 1) {
374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if ((*src_buf)[offset] == 0xff && (*src_buf)[offset + 1] == 0xd8) {
384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      *src_buf += offset;
394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      *src_size -= offset;
404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    offset++;
434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void _src_do_nothing(struct jpeg_decompress_struct* cinfo) {}
474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void _error_fatal(j_common_ptr cinfo) {
494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  longjmp(*(jmp_buf*)cinfo->client_data, -1);
504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void _src_skip_data(struct jpeg_decompress_struct* cinfo, long num) {
534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (num > (long)cinfo->src->bytes_in_buffer) {
544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    _error_fatal((j_common_ptr)cinfo);
554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo->src->next_input_byte += num;
574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo->src->bytes_in_buffer -= num;
584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic boolean _src_fill_buffer(j_decompress_ptr cinfo) {
614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return 0;
624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic boolean _src_resync(j_decompress_ptr cinfo, int desired) {
654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return 0;
664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void _error_do_nothing(j_common_ptr cinfo) {}
694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void _error_do_nothing1(j_common_ptr cinfo, int) {}
714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void _error_do_nothing2(j_common_ptr cinfo, char*) {}
734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void _dest_do_nothing(j_compress_ptr cinfo) {}
764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic boolean _dest_empty(j_compress_ptr cinfo) {
784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return false;
794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann};
824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define JPEG_MARKER_ICC (JPEG_APP0 + 2)
844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define JPEG_MARKER_MAXSIZE 0xFFFF
854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PDF_ENABLE_XFA
874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void JpegLoadAttribute(struct jpeg_decompress_struct* pInfo,
884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              CFX_DIBAttribute* pAttribute) {
894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pAttribute)
904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return;
914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  pAttribute->m_nXDPI = pInfo->X_density;
934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  pAttribute->m_nYDPI = pInfo->Y_density;
944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  pAttribute->m_wDPIUnit = pInfo->density_unit;
954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif  // PDF_ENABLE_XFA
974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic bool JpegLoadInfo(const uint8_t* src_buf,
994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         uint32_t src_size,
1004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         int* width,
1014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         int* height,
1024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         int* num_components,
1034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         int* bits_per_components,
1044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                         bool* color_transform) {
1054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  JpegScanSOI(&src_buf, &src_size);
1064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  struct jpeg_decompress_struct cinfo;
1074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  struct jpeg_error_mgr jerr;
1084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.error_exit = _error_fatal;
1094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.emit_message = _error_do_nothing1;
1104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.output_message = _error_do_nothing;
1114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.format_message = _error_do_nothing2;
1124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.reset_error_mgr = _error_do_nothing;
1134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.trace_level = 0;
1144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.err = &jerr;
1154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jmp_buf mark;
1164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.client_data = &mark;
1174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(mark) == -1)
1184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
1194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_create_decompress(&cinfo);
1214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  struct jpeg_source_mgr src;
1224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.init_source = _src_do_nothing;
1234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.term_source = _src_do_nothing;
1244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.skip_input_data = _src_skip_data;
1254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.fill_input_buffer = _src_fill_buffer;
1264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.resync_to_restart = _src_resync;
1274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.bytes_in_buffer = src_size;
1284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.next_input_byte = src_buf;
1294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.src = &src;
1304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(mark) == -1) {
1314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    jpeg_destroy_decompress(&cinfo);
1324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
1334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
1344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int ret = jpeg_read_header(&cinfo, true);
1354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (ret != JPEG_HEADER_OK) {
1364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    jpeg_destroy_decompress(&cinfo);
1374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
1384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
1394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *width = cinfo.image_width;
1404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *height = cinfo.image_height;
1414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *num_components = cinfo.num_components;
1424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *color_transform =
1434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      cinfo.jpeg_color_space == JCS_YCbCr || cinfo.jpeg_color_space == JCS_YCCK;
1444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *bits_per_components = cinfo.data_precision;
1454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_destroy_decompress(&cinfo);
1464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
1474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
1484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannclass CCodec_JpegDecoder : public CCodec_ScanlineDecoder {
1504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann public:
1514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  CCodec_JpegDecoder();
1524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  ~CCodec_JpegDecoder() override;
1534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool Create(const uint8_t* src_buf,
1554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann              uint32_t src_size,
1564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann              int width,
1574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann              int height,
1584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann              int nComps,
1594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann              bool ColorTransform);
1604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  // CCodec_ScanlineDecoder
1624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool v_Rewind() override;
1634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint8_t* v_GetNextLine() override;
1644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t GetSrcOffset() override;
1654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool InitDecode();
1674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jmp_buf m_JmpBuf;
1694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  struct jpeg_decompress_struct cinfo;
1704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  struct jpeg_error_mgr jerr;
1714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  struct jpeg_source_mgr src;
1724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const uint8_t* m_SrcBuf;
1734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t m_SrcSize;
1744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint8_t* m_pScanlineBuf;
1754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool m_bInited;
1774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool m_bStarted;
1784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  bool m_bJpegTransform;
1794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann protected:
1814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t m_nDefaultScaleDenom;
1824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann};
1834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannCCodec_JpegDecoder::CCodec_JpegDecoder() {
1854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_pScanlineBuf = nullptr;
1864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_bStarted = false;
1874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_bInited = false;
1884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FXSYS_memset(&cinfo, 0, sizeof(cinfo));
1894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FXSYS_memset(&jerr, 0, sizeof(jerr));
1904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FXSYS_memset(&src, 0, sizeof(src));
1914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_nDefaultScaleDenom = 1;
1924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
1934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
1944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannCCodec_JpegDecoder::~CCodec_JpegDecoder() {
1954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FX_Free(m_pScanlineBuf);
1964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (m_bInited)
1974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    jpeg_destroy_decompress(&cinfo);
1984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
1994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_JpegDecoder::InitDecode() {
2014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.err = &jerr;
2024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.client_data = &m_JmpBuf;
2034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(m_JmpBuf) == -1)
2044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
2054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_create_decompress(&cinfo);
2074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_bInited = true;
2084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.src = &src;
2094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.bytes_in_buffer = m_SrcSize;
2104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.next_input_byte = m_SrcBuf;
2114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(m_JmpBuf) == -1) {
2124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    jpeg_destroy_decompress(&cinfo);
2134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    m_bInited = false;
2144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
2154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
2164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.image_width = m_OrigWidth;
2174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.image_height = m_OrigHeight;
2184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int ret = jpeg_read_header(&cinfo, true);
2194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (ret != JPEG_HEADER_OK)
2204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
2214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (cinfo.saw_Adobe_marker)
2234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    m_bJpegTransform = true;
2244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (cinfo.num_components == 3 && !m_bJpegTransform)
2264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    cinfo.out_color_space = cinfo.jpeg_color_space;
2274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_OrigWidth = cinfo.image_width;
2294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_OrigHeight = cinfo.image_height;
2304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_OutputWidth = m_OrigWidth;
2314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_OutputHeight = m_OrigHeight;
2324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_nDefaultScaleDenom = cinfo.scale_denom;
2334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
2344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
2354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_JpegDecoder::Create(const uint8_t* src_buf,
2374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                uint32_t src_size,
2384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                int width,
2394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                int height,
2404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                int nComps,
2414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                bool ColorTransform) {
2424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  JpegScanSOI(&src_buf, &src_size);
2434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_SrcBuf = src_buf;
2444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_SrcSize = src_size;
2454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.error_exit = _error_fatal;
2464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.emit_message = _error_do_nothing1;
2474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.output_message = _error_do_nothing;
2484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.format_message = _error_do_nothing2;
2494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.reset_error_mgr = _error_do_nothing;
2504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.init_source = _src_do_nothing;
2514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.term_source = _src_do_nothing;
2524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.skip_input_data = _src_skip_data;
2534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.fill_input_buffer = _src_fill_buffer;
2544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  src.resync_to_restart = _src_resync;
2554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_bJpegTransform = ColorTransform;
2564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (src_size > 1 &&
2574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      FXSYS_memcmp(src_buf + src_size - 2, "\xFF\xD9", 2) != 0) {
2584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    ((uint8_t*)src_buf)[src_size - 2] = 0xFF;
2594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    ((uint8_t*)src_buf)[src_size - 1] = 0xD9;
2604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
2614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_OutputWidth = m_OrigWidth = width;
2624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_OutputHeight = m_OrigHeight = height;
2634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!InitDecode())
2644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
2654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (cinfo.num_components < nComps)
2674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
2684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if ((int)cinfo.image_width < width)
2704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
2714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_Pitch =
2734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      (static_cast<uint32_t>(cinfo.image_width) * cinfo.num_components + 3) /
2744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      4 * 4;
2754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_pScanlineBuf = FX_Alloc(uint8_t, m_Pitch);
2764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_nComps = cinfo.num_components;
2774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_bpc = 8;
2784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_bStarted = false;
2794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
2804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
2814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
2824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_JpegDecoder::v_Rewind() {
2834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (m_bStarted) {
2844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    jpeg_destroy_decompress(&cinfo);
2854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (!InitDecode()) {
2864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return false;
2874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
2884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
2894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(m_JmpBuf) == -1) {
2904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
2914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
2924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.scale_denom = m_nDefaultScaleDenom;
2934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_OutputWidth = m_OrigWidth;
2944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_OutputHeight = m_OrigHeight;
2954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!jpeg_start_decompress(&cinfo)) {
2964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    jpeg_destroy_decompress(&cinfo);
2974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
2984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
2994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if ((int)cinfo.output_width > m_OrigWidth) {
3004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    ASSERT(false);
3014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
3024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
3034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  m_bStarted = true;
3044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
3054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannuint8_t* CCodec_JpegDecoder::v_GetNextLine() {
3084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(m_JmpBuf) == -1)
3094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
3104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int nlines = jpeg_read_scanlines(&cinfo, &m_pScanlineBuf, 1);
3124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return nlines > 0 ? m_pScanlineBuf : nullptr;
3134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannuint32_t CCodec_JpegDecoder::GetSrcOffset() {
3164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return (uint32_t)(m_SrcSize - src.bytes_in_buffer);
3174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstd::unique_ptr<CCodec_ScanlineDecoder> CCodec_JpegModule::CreateDecoder(
3204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    const uint8_t* src_buf,
3214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    uint32_t src_size,
3224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int width,
3234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int height,
3244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    int nComps,
3254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    bool ColorTransform) {
3264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!src_buf || src_size == 0)
3274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
3284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  auto pDecoder = pdfium::MakeUnique<CCodec_JpegDecoder>();
3304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!pDecoder->Create(src_buf, src_size, width, height, nComps,
3314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                        ColorTransform)) {
3324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return nullptr;
3334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
3344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return std::move(pDecoder);
3354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_JpegModule::LoadInfo(const uint8_t* src_buf,
3384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 uint32_t src_size,
3394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 int* width,
3404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 int* height,
3414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 int* num_components,
3424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 int* bits_per_components,
3434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                 bool* color_transform) {
3444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return JpegLoadInfo(src_buf, src_size, width, height, num_components,
3454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                      bits_per_components, color_transform);
3464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
3484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstruct FXJPEG_Context {
3494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jmp_buf m_JumpMark;
3504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_decompress_struct m_Info;
3514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_error_mgr m_ErrMgr;
3524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_source_mgr m_SrcMgr;
3534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  unsigned int m_SkipSize;
3544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  void* (*m_AllocFunc)(unsigned int);
3554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  void (*m_FreeFunc)(void*);
3564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann};
3574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannextern "C" {
3584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void _error_fatal1(j_common_ptr cinfo) {
3594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  longjmp(((FXJPEG_Context*)cinfo->client_data)->m_JumpMark, -1);
3604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann};
3624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannextern "C" {
3634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void _src_skip_data1(struct jpeg_decompress_struct* cinfo, long num) {
3644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (cinfo->src->bytes_in_buffer < (size_t)num) {
3654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    ((FXJPEG_Context*)cinfo->client_data)->m_SkipSize =
3664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        (unsigned int)(num - cinfo->src->bytes_in_buffer);
3674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    cinfo->src->bytes_in_buffer = 0;
3684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  } else {
3694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    cinfo->src->next_input_byte += num;
3704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    cinfo->src->bytes_in_buffer -= num;
3714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
3724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann};
3744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void* jpeg_alloc_func(unsigned int size) {
3754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return FX_Alloc(char, size);
3764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannstatic void jpeg_free_func(void* p) {
3784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FX_Free(p);
3794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
3804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. MoltmannFXJPEG_Context* CCodec_JpegModule::Start() {
3814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FXJPEG_Context* p = FX_Alloc(FXJPEG_Context, 1);
3824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_AllocFunc = jpeg_alloc_func;
3834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_FreeFunc = jpeg_free_func;
3844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_ErrMgr.error_exit = _error_fatal1;
3854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_ErrMgr.emit_message = _error_do_nothing1;
3864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_ErrMgr.output_message = _error_do_nothing;
3874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_ErrMgr.format_message = _error_do_nothing2;
3884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_ErrMgr.reset_error_mgr = _error_do_nothing;
3894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_SrcMgr.init_source = _src_do_nothing;
3904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_SrcMgr.term_source = _src_do_nothing;
3914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_SrcMgr.skip_input_data = _src_skip_data1;
3924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_SrcMgr.fill_input_buffer = _src_fill_buffer;
3934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_SrcMgr.resync_to_restart = _src_resync;
3944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_Info.client_data = p;
3954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_Info.err = &p->m_ErrMgr;
3964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(p->m_JumpMark) == -1) {
3974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return 0;
3984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
3994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_create_decompress(&p->m_Info);
4004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_Info.src = &p->m_SrcMgr;
4014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  p->m_SkipSize = 0;
4024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return p;
4034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
4044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid CCodec_JpegModule::Finish(FXJPEG_Context* ctx) {
4064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_destroy_decompress(&ctx->m_Info);
4074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  ctx->m_FreeFunc(ctx);
4084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
4094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannvoid CCodec_JpegModule::Input(FXJPEG_Context* ctx,
4114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              const unsigned char* src_buf,
4124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                              uint32_t src_size) {
4134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (ctx->m_SkipSize) {
4144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (ctx->m_SkipSize > src_size) {
4154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      ctx->m_SrcMgr.bytes_in_buffer = 0;
4164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      ctx->m_SkipSize -= src_size;
4174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      return;
4184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
4194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    src_size -= ctx->m_SkipSize;
4204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    src_buf += ctx->m_SkipSize;
4214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    ctx->m_SkipSize = 0;
4224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
4234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  ctx->m_SrcMgr.next_input_byte = src_buf;
4244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  ctx->m_SrcMgr.bytes_in_buffer = src_size;
4254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
4264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PDF_ENABLE_XFA
4284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannint CCodec_JpegModule::ReadHeader(FXJPEG_Context* ctx,
4294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                  int* width,
4304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                  int* height,
4314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                  int* nComps,
4324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                  CFX_DIBAttribute* pAttribute) {
4334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else   // PDF_ENABLE_XFA
4344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannint CCodec_JpegModule::ReadHeader(FXJPEG_Context* ctx,
4354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                  int* width,
4364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                  int* height,
4374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                  int* nComps) {
4384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif  // PDF_ENABLE_XFA
4394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(ctx->m_JumpMark) == -1)
4404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return 1;
4414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int ret = jpeg_read_header(&ctx->m_Info, true);
4434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (ret == JPEG_SUSPENDED)
4444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return 2;
4454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (ret != JPEG_HEADER_OK)
4464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return 1;
4474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *width = ctx->m_Info.image_width;
4494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *height = ctx->m_Info.image_height;
4504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *nComps = ctx->m_Info.num_components;
4514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#ifdef PDF_ENABLE_XFA
4524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  JpegLoadAttribute(&ctx->m_Info, pAttribute);
4534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
4544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return 0;
4554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
4564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_JpegModule::StartScanline(FXJPEG_Context* ctx, int down_scale) {
4584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(ctx->m_JumpMark) == -1)
4594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
4604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  ctx->m_Info.scale_denom = down_scale;
4624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return !!jpeg_start_decompress(&ctx->m_Info);
4634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
4644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_JpegModule::ReadScanline(FXJPEG_Context* ctx,
4664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                     unsigned char* dest_buf) {
4674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (setjmp(ctx->m_JumpMark) == -1)
4684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
4694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int nlines = jpeg_read_scanlines(&ctx->m_Info, &dest_buf, 1);
4714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return nlines == 1;
4724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
4734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannuint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx,
4754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                          uint8_t** avail_buf_ptr) {
4764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (avail_buf_ptr) {
4774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *avail_buf_ptr = nullptr;
4784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (ctx->m_SrcMgr.bytes_in_buffer > 0) {
4794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      *avail_buf_ptr = (uint8_t*)ctx->m_SrcMgr.next_input_byte;
4804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
4814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
4824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer;
4834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
4844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
4864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#define JPEG_BLOCK_SIZE 1048576
4874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannbool CCodec_JpegModule::JpegEncode(const CFX_DIBSource* pSource,
4884d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                   uint8_t** dest_buf,
4894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann                                   FX_STRSIZE* dest_size) {
4904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  struct jpeg_error_mgr jerr;
4914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.error_exit = _error_do_nothing;
4924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.emit_message = _error_do_nothing1;
4934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.output_message = _error_do_nothing;
4944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.format_message = _error_do_nothing2;
4954d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jerr.reset_error_mgr = _error_do_nothing;
4964d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
4974d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  struct jpeg_compress_struct cinfo;
4984d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  memset(&cinfo, 0, sizeof(cinfo));
4994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.err = &jerr;
5004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_create_compress(&cinfo);
5014d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  int Bpp = pSource->GetBPP() / 8;
5024d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t nComponents = Bpp >= 3 ? (pSource->IsCmykImage() ? 4 : 3) : 1;
5034d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t pitch = pSource->GetPitch();
5044d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t width = pdfium::base::checked_cast<uint32_t>(pSource->GetWidth());
5054d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t height = pdfium::base::checked_cast<uint32_t>(pSource->GetHeight());
5064d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FX_SAFE_UINT32 safe_buf_len = width;
5074d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  safe_buf_len *= height;
5084d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  safe_buf_len *= nComponents;
5094d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  safe_buf_len += 1024;
5104d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!safe_buf_len.IsValid())
5114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
5124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint32_t dest_buf_length = safe_buf_len.ValueOrDie();
5144d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *dest_buf = FX_TryAlloc(uint8_t, dest_buf_length);
5154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  const int MIN_TRY_BUF_LEN = 1024;
5164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  while (!(*dest_buf) && dest_buf_length > MIN_TRY_BUF_LEN) {
5174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    dest_buf_length >>= 1;
5184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    *dest_buf = FX_TryAlloc(uint8_t, dest_buf_length);
5194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
5204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (!(*dest_buf))
5214d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    return false;
5224d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5234d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  struct jpeg_destination_mgr dest;
5244d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  dest.init_destination = _dest_do_nothing;
5254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  dest.term_destination = _dest_do_nothing;
5264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  dest.empty_output_buffer = _dest_empty;
5274d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  dest.next_output_byte = *dest_buf;
5284d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  dest.free_in_buffer = dest_buf_length;
5294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.dest = &dest;
5304d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.image_width = width;
5314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.image_height = height;
5324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  cinfo.input_components = nComponents;
5334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (nComponents == 1) {
5344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    cinfo.in_color_space = JCS_GRAYSCALE;
5354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  } else if (nComponents == 3) {
5364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    cinfo.in_color_space = JCS_RGB;
5374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  } else {
5384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    cinfo.in_color_space = JCS_CMYK;
5394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
5404d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  uint8_t* line_buf = nullptr;
5414d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  if (nComponents > 1)
5424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    line_buf = FX_Alloc2D(uint8_t, width, nComponents);
5434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5444d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_set_defaults(&cinfo);
5454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_start_compress(&cinfo, TRUE);
5464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  JSAMPROW row_pointer[1];
5474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  JDIMENSION row;
5484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  while (cinfo.next_scanline < cinfo.image_height) {
5494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    const uint8_t* src_scan = pSource->GetScanline(cinfo.next_scanline);
5504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (nComponents > 1) {
5514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      uint8_t* dest_scan = line_buf;
5524d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      if (nComponents == 3) {
5534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        for (uint32_t i = 0; i < width; i++) {
5544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          dest_scan[0] = src_scan[2];
5554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          dest_scan[1] = src_scan[1];
5564d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          dest_scan[2] = src_scan[0];
5574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          dest_scan += 3;
5584d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          src_scan += Bpp;
5594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        }
5604d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      } else {
5614d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        for (uint32_t i = 0; i < pitch; i++) {
5624d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          *dest_scan++ = ~*src_scan++;
5634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann        }
5644d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      }
5654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      row_pointer[0] = line_buf;
5664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    } else {
5674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      row_pointer[0] = (uint8_t*)src_scan;
5684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
5694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    row = cinfo.next_scanline;
5704d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    jpeg_write_scanlines(&cinfo, row_pointer, 1);
5714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    if (cinfo.next_scanline == row) {
5724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      *dest_buf =
5734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann          FX_Realloc(uint8_t, *dest_buf, dest_buf_length + JPEG_BLOCK_SIZE);
5744d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      dest.next_output_byte = *dest_buf + dest_buf_length - dest.free_in_buffer;
5754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      dest_buf_length += JPEG_BLOCK_SIZE;
5764d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann      dest.free_in_buffer += JPEG_BLOCK_SIZE;
5774d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann    }
5784d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  }
5794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_finish_compress(&cinfo);
5804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  jpeg_destroy_compress(&cinfo);
5814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  FX_Free(line_buf);
5824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  *dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer;
5834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann
5844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann  return true;
5854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann}
5864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif
587