blob: d618b737be0860db8224c3d059db2232d245bea8 [file] [log] [blame]
dan sinclair61b2fc72016-03-23 19:21:44 -04001// Copyright 2016 PDFium Authors. All rights reserved.
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhang95e854f2015-06-13 00:58:06 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
dsinclair41872fa2016-10-04 11:29:35 -07007#include "core/fpdfapi/page/cpdf_image.h"
dan sinclair61b2fc72016-03-23 19:21:44 -04008
thestigdc359b02016-08-09 15:46:20 -07009#include <algorithm>
tsepez9e05ee12016-11-21 13:19:10 -080010#include <memory>
tsepez0e606b52016-11-18 16:22:41 -080011#include <utility>
thestigdc359b02016-08-09 15:46:20 -070012#include <vector>
13
Lei Zhang26170562018-04-17 17:01:52 +000014#include "constants/stream_dict_common.h"
dsinclair39c62fd2016-09-29 12:49:17 -070015#include "core/fpdfapi/cpdf_modulemgr.h"
dsinclair41872fa2016-10-04 11:29:35 -070016#include "core/fpdfapi/page/cpdf_page.h"
dsinclair488b7ad2016-10-04 11:55:50 -070017#include "core/fpdfapi/parser/cpdf_array.h"
18#include "core/fpdfapi/parser/cpdf_boolean.h"
tsepez4e4d1a62016-10-13 15:56:53 -070019#include "core/fpdfapi/parser/cpdf_dictionary.h"
dsinclair488b7ad2016-10-04 11:55:50 -070020#include "core/fpdfapi/parser/cpdf_document.h"
tsepez8a3aa452016-11-16 12:26:06 -080021#include "core/fpdfapi/parser/cpdf_name.h"
22#include "core/fpdfapi/parser/cpdf_number.h"
23#include "core/fpdfapi/parser/cpdf_reference.h"
tsepez9e05ee12016-11-21 13:19:10 -080024#include "core/fpdfapi/parser/cpdf_stream.h"
dsinclair488b7ad2016-10-04 11:55:50 -070025#include "core/fpdfapi/parser/cpdf_string.h"
Tom Sepeze6ff2eb2018-08-24 21:55:46 +000026#include "core/fpdfapi/render/cpdf_dibbase.h"
dsinclair69d9c682016-10-04 12:18:35 -070027#include "core/fpdfapi/render/cpdf_pagerendercache.h"
Lei Zhang7acd8262017-09-19 14:34:37 -070028#include "core/fxcodec/codec/ccodec_jpegmodule.h"
Dan Sinclairbcd1e702017-08-31 13:19:18 -040029#include "core/fxcrt/fx_stream.h"
Lei Zhang6e59fb52018-01-18 19:03:58 +000030#include "core/fxge/dib/cfx_dibitmap.h"
dsinclair74a34fc2016-09-29 16:41:42 -070031#include "core/fxge/fx_dib.h"
tsepez06104a82016-11-21 16:22:10 -080032#include "third_party/base/numerics/safe_conversions.h"
tsepez9e05ee12016-11-21 13:19:10 -080033#include "third_party/base/ptr_util.h"
dan sinclair61b2fc72016-03-23 19:21:44 -040034
Lei Zhang8590a982018-09-21 15:34:45 +000035// static
36bool CPDF_Image::IsValidJpegComponent(int32_t comps) {
Lei Zhang34cdc8f2018-09-20 16:23:02 +000037 return comps == 1 || comps == 3 || comps == 4;
38}
39
Lei Zhang8590a982018-09-21 15:34:45 +000040// static
41bool CPDF_Image::IsValidJpegBitsPerComponent(int32_t bpc) {
Lei Zhang34cdc8f2018-09-20 16:23:02 +000042 return bpc == 1 || bpc == 2 || bpc == 4 || bpc == 8 || bpc == 16;
43}
44
tsepez4e4d1a62016-10-13 15:56:53 -070045CPDF_Image::CPDF_Image(CPDF_Document* pDoc) : m_pDocument(pDoc) {}
thestigdc359b02016-08-09 15:46:20 -070046
tsepez33fdebc2016-11-04 11:38:40 -070047CPDF_Image::CPDF_Image(CPDF_Document* pDoc,
48 std::unique_ptr<CPDF_Stream> pStream)
Tom Sepezbb1ee532018-01-30 18:10:01 +000049 : m_bIsInline(true), m_pDocument(pDoc), m_pStream(std::move(pStream)) {
tsepez9fd0c632016-11-23 14:34:58 -080050 ASSERT(m_pStream.IsOwned());
Tom Sepezbb1ee532018-01-30 18:10:01 +000051 FinishInitialization(m_pStream->GetDict());
thestigdc359b02016-08-09 15:46:20 -070052}
dan sinclair61b2fc72016-03-23 19:21:44 -040053
tsepez4e4d1a62016-10-13 15:56:53 -070054CPDF_Image::CPDF_Image(CPDF_Document* pDoc, uint32_t dwStreamObjNum)
55 : m_pDocument(pDoc),
Tom Sepezbb1ee532018-01-30 18:10:01 +000056 m_pStream(ToStream(pDoc->GetIndirectObject(dwStreamObjNum))) {
tsepez9fd0c632016-11-23 14:34:58 -080057 ASSERT(!m_pStream.IsOwned());
Tom Sepezbb1ee532018-01-30 18:10:01 +000058 FinishInitialization(m_pStream->GetDict());
tsepez4e4d1a62016-10-13 15:56:53 -070059}
60
61CPDF_Image::~CPDF_Image() {}
62
Lei Zhangaca3efc2018-03-16 20:27:04 +000063void CPDF_Image::FinishInitialization(CPDF_Dictionary* pStreamDict) {
64 m_pOC = pStreamDict->GetDictFor("OC");
65 m_bIsMask = !pStreamDict->KeyExist("ColorSpace") ||
66 pStreamDict->GetIntegerFor("ImageMask");
67 m_bInterpolate = !!pStreamDict->GetIntegerFor("Interpolate");
68 m_Height = pStreamDict->GetIntegerFor("Height");
69 m_Width = pStreamDict->GetIntegerFor("Width");
dan sinclair61b2fc72016-03-23 19:21:44 -040070}
71
tsepez137a3442016-11-14 15:03:55 -080072void CPDF_Image::ConvertStreamToIndirectObject() {
73 if (!m_pStream->IsInline())
74 return;
75
tsepez9fd0c632016-11-23 14:34:58 -080076 ASSERT(m_pStream.IsOwned());
77 m_pDocument->AddIndirectObject(m_pStream.Release());
tsepez137a3442016-11-14 15:03:55 -080078}
79
Lei Zhang731526e2017-12-11 21:28:38 +000080CPDF_Dictionary* CPDF_Image::GetDict() const {
81 return m_pStream ? m_pStream->GetDict() : nullptr;
82}
83
Tom Sepez126927e2018-08-28 22:25:49 +000084std::unique_ptr<CPDF_Dictionary> CPDF_Image::InitJPEG(
85 pdfium::span<uint8_t> src_span) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070086 int32_t width;
87 int32_t height;
88 int32_t num_comps;
89 int32_t bits;
thestigb0fcfad2016-06-06 17:54:29 -070090 bool color_trans;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070091 if (!CPDF_ModuleMgr::Get()->GetJpegModule()->LoadInfo(
Tom Sepez126927e2018-08-28 22:25:49 +000092 src_span, &width, &height, &num_comps, &bits, &color_trans)) {
thestigb0fcfad2016-06-06 17:54:29 -070093 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070094 }
Lei Zhang34cdc8f2018-09-20 16:23:02 +000095 if (!IsValidJpegComponent(num_comps) || !IsValidJpegBitsPerComponent(bits))
96 return nullptr;
thestigb0fcfad2016-06-06 17:54:29 -070097
tsepez06104a82016-11-21 16:22:10 -080098 auto pDict =
99 pdfium::MakeUnique<CPDF_Dictionary>(m_pDocument->GetByteStringPool());
tsepez0e606b52016-11-18 16:22:41 -0800100 pDict->SetNewFor<CPDF_Name>("Type", "XObject");
101 pDict->SetNewFor<CPDF_Name>("Subtype", "Image");
102 pDict->SetNewFor<CPDF_Number>("Width", width);
103 pDict->SetNewFor<CPDF_Number>("Height", height);
Dan Sinclair812e96c2017-03-13 16:43:37 -0400104 const char* csname = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700105 if (num_comps == 1) {
106 csname = "DeviceGray";
107 } else if (num_comps == 3) {
108 csname = "DeviceRGB";
109 } else if (num_comps == 4) {
110 csname = "DeviceCMYK";
tsepez0e606b52016-11-18 16:22:41 -0800111 CPDF_Array* pDecode = pDict->SetNewFor<CPDF_Array>("Decode");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700112 for (int n = 0; n < 4; n++) {
tsepez8a3aa452016-11-16 12:26:06 -0800113 pDecode->AddNew<CPDF_Number>(1);
114 pDecode->AddNew<CPDF_Number>(0);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700115 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700116 }
tsepez0e606b52016-11-18 16:22:41 -0800117 pDict->SetNewFor<CPDF_Name>("ColorSpace", csname);
118 pDict->SetNewFor<CPDF_Number>("BitsPerComponent", bits);
119 pDict->SetNewFor<CPDF_Name>("Filter", "DCTDecode");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700120 if (!color_trans) {
Lei Zhang26170562018-04-17 17:01:52 +0000121 CPDF_Dictionary* pParms =
122 pDict->SetNewFor<CPDF_Dictionary>(pdfium::stream::kDecodeParms);
tsepez0e606b52016-11-18 16:22:41 -0800123 pParms->SetNewFor<CPDF_Number>("ColorTransform", 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700124 }
tsepez12f3e4a2016-11-02 15:17:29 -0700125 m_bIsMask = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700126 m_Width = width;
127 m_Height = height;
tsepez9fd0c632016-11-23 14:34:58 -0800128 if (!m_pStream)
129 m_pStream = pdfium::MakeUnique<CPDF_Stream>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700130 return pDict;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700131}
dan sinclair61b2fc72016-03-23 19:21:44 -0400132
Dan Sinclair0b950422017-09-21 15:49:49 -0400133void CPDF_Image::SetJpegImage(const RetainPtr<IFX_SeekableReadStream>& pFile) {
tsepez06104a82016-11-21 16:22:10 -0800134 uint32_t size = pdfium::base::checked_cast<uint32_t>(pFile->GetSize());
thestigdc359b02016-08-09 15:46:20 -0700135 if (!size)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700136 return;
thestigdc359b02016-08-09 15:46:20 -0700137
138 uint32_t dwEstimateSize = std::min(size, 8192U);
139 std::vector<uint8_t> data(dwEstimateSize);
tsepez06104a82016-11-21 16:22:10 -0800140 if (!pFile->ReadBlock(data.data(), 0, dwEstimateSize))
141 return;
142
Tom Sepez126927e2018-08-28 22:25:49 +0000143 std::unique_ptr<CPDF_Dictionary> pDict = InitJPEG(data);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700144 if (!pDict && size > dwEstimateSize) {
thestigdc359b02016-08-09 15:46:20 -0700145 data.resize(size);
146 pFile->ReadBlock(data.data(), 0, size);
Tom Sepez126927e2018-08-28 22:25:49 +0000147 pDict = InitJPEG(data);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700148 }
thestigdc359b02016-08-09 15:46:20 -0700149 if (!pDict)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700150 return;
thestigdc359b02016-08-09 15:46:20 -0700151
tsepez06104a82016-11-21 16:22:10 -0800152 m_pStream->InitStreamFromFile(pFile, std::move(pDict));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700153}
dan sinclair61b2fc72016-03-23 19:21:44 -0400154
rbpotterf085db32016-12-14 11:44:31 -0800155void CPDF_Image::SetJpegImageInline(
Dan Sinclair0b950422017-09-21 15:49:49 -0400156 const RetainPtr<IFX_SeekableReadStream>& pFile) {
rbpotterf085db32016-12-14 11:44:31 -0800157 uint32_t size = pdfium::base::checked_cast<uint32_t>(pFile->GetSize());
158 if (!size)
159 return;
160
161 std::vector<uint8_t> data(size);
162 if (!pFile->ReadBlock(data.data(), 0, size))
163 return;
164
Tom Sepez126927e2018-08-28 22:25:49 +0000165 std::unique_ptr<CPDF_Dictionary> pDict = InitJPEG(data);
rbpotterf085db32016-12-14 11:44:31 -0800166 if (!pDict)
167 return;
168
Tom Sepez367ed462018-08-23 23:52:53 +0000169 m_pStream->InitStream(data, std::move(pDict));
rbpotterf085db32016-12-14 11:44:31 -0800170}
171
Dan Sinclair0b950422017-09-21 15:49:49 -0400172void CPDF_Image::SetImage(const RetainPtr<CFX_DIBitmap>& pBitmap) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700173 int32_t BitmapWidth = pBitmap->GetWidth();
174 int32_t BitmapHeight = pBitmap->GetHeight();
thestig4ccdb142016-11-21 15:09:23 -0800175 if (BitmapWidth < 1 || BitmapHeight < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700176 return;
dan sinclair61b2fc72016-03-23 19:21:44 -0400177
tsepez9e05ee12016-11-21 13:19:10 -0800178 auto pDict =
179 pdfium::MakeUnique<CPDF_Dictionary>(m_pDocument->GetByteStringPool());
tsepez0e606b52016-11-18 16:22:41 -0800180 pDict->SetNewFor<CPDF_Name>("Type", "XObject");
181 pDict->SetNewFor<CPDF_Name>("Subtype", "Image");
182 pDict->SetNewFor<CPDF_Number>("Width", BitmapWidth);
183 pDict->SetNewFor<CPDF_Number>("Height", BitmapHeight);
thestig4ccdb142016-11-21 15:09:23 -0800184
185 const int32_t bpp = pBitmap->GetBPP();
Ryan Harrison875e98c2017-09-27 10:53:11 -0400186 size_t dest_pitch = 0;
thestig4ccdb142016-11-21 15:09:23 -0800187 bool bCopyWithoutAlpha = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700188 if (bpp == 1) {
thestig4ccdb142016-11-21 15:09:23 -0800189 int32_t reset_a = 0;
190 int32_t reset_r = 0;
191 int32_t reset_g = 0;
192 int32_t reset_b = 0;
193 int32_t set_a = 0;
194 int32_t set_r = 0;
195 int32_t set_g = 0;
196 int32_t set_b = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700197 if (!pBitmap->IsAlphaMask()) {
Nicolas Penaddfc3dc2017-04-20 15:29:25 -0400198 std::tie(reset_a, reset_r, reset_g, reset_b) =
199 ArgbDecode(pBitmap->GetPaletteArgb(0));
200 std::tie(set_a, set_r, set_g, set_b) =
201 ArgbDecode(pBitmap->GetPaletteArgb(1));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700202 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700203 if (set_a == 0 || reset_a == 0) {
tsepez0e606b52016-11-18 16:22:41 -0800204 pDict->SetNewFor<CPDF_Boolean>("ImageMask", true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700205 if (reset_a == 0) {
tsepez0e606b52016-11-18 16:22:41 -0800206 CPDF_Array* pArray = pDict->SetNewFor<CPDF_Array>("Decode");
tsepez8a3aa452016-11-16 12:26:06 -0800207 pArray->AddNew<CPDF_Number>(1);
208 pArray->AddNew<CPDF_Number>(0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700209 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210 } else {
tsepez0e606b52016-11-18 16:22:41 -0800211 CPDF_Array* pCS = pDict->SetNewFor<CPDF_Array>("ColorSpace");
tsepez8a3aa452016-11-16 12:26:06 -0800212 pCS->AddNew<CPDF_Name>("Indexed");
213 pCS->AddNew<CPDF_Name>("DeviceRGB");
214 pCS->AddNew<CPDF_Number>(1);
Ryan Harrison275e2602017-09-18 14:23:18 -0400215 ByteString ct;
Tom Sepez1dbfe992018-04-17 17:19:30 +0000216 {
217 // Span's lifetime must end before ReleaseBuffer() below.
218 pdfium::span<char> pBuf = ct.GetBuffer(6);
219 pBuf[0] = (char)reset_r;
220 pBuf[1] = (char)reset_g;
221 pBuf[2] = (char)reset_b;
222 pBuf[3] = (char)set_r;
223 pBuf[4] = (char)set_g;
224 pBuf[5] = (char)set_b;
225 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226 ct.ReleaseBuffer(6);
tsepez8a3aa452016-11-16 12:26:06 -0800227 pCS->AddNew<CPDF_String>(ct, true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700228 }
tsepez0e606b52016-11-18 16:22:41 -0800229 pDict->SetNewFor<CPDF_Number>("BitsPerComponent", 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700230 dest_pitch = (BitmapWidth + 7) / 8;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700231 } else if (bpp == 8) {
232 int32_t iPalette = pBitmap->GetPaletteSize();
233 if (iPalette > 0) {
tsepez70c4afd2016-11-15 11:33:44 -0800234 CPDF_Array* pCS = m_pDocument->NewIndirect<CPDF_Array>();
tsepez8a3aa452016-11-16 12:26:06 -0800235 pCS->AddNew<CPDF_Name>("Indexed");
236 pCS->AddNew<CPDF_Name>("DeviceRGB");
237 pCS->AddNew<CPDF_Number>(iPalette - 1);
tsepez47fb8c02016-12-15 13:51:34 -0800238 std::unique_ptr<uint8_t, FxFreeDeleter> pColorTable(
239 FX_Alloc2D(uint8_t, iPalette, 3));
240 uint8_t* ptr = pColorTable.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700241 for (int32_t i = 0; i < iPalette; i++) {
tsepezb5e8f142016-03-25 15:18:35 -0700242 uint32_t argb = pBitmap->GetPaletteArgb(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700243 ptr[0] = (uint8_t)(argb >> 16);
244 ptr[1] = (uint8_t)(argb >> 8);
245 ptr[2] = (uint8_t)argb;
246 ptr += 3;
247 }
tsepez9e05ee12016-11-21 13:19:10 -0800248 auto pNewDict =
249 pdfium::MakeUnique<CPDF_Dictionary>(m_pDocument->GetByteStringPool());
tsepez70c4afd2016-11-15 11:33:44 -0800250 CPDF_Stream* pCTS = m_pDocument->NewIndirect<CPDF_Stream>(
tsepez47fb8c02016-12-15 13:51:34 -0800251 std::move(pColorTable), iPalette * 3, std::move(pNewDict));
Artem Stryginfb727262018-06-11 18:19:57 +0000252 pCS->Add(pCTS->MakeReference(m_pDocument.Get()));
253 pDict->SetFor("ColorSpace", pCS->MakeReference(m_pDocument.Get()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700254 } else {
tsepez0e606b52016-11-18 16:22:41 -0800255 pDict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700256 }
tsepez0e606b52016-11-18 16:22:41 -0800257 pDict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
thestig4ccdb142016-11-21 15:09:23 -0800258 dest_pitch = BitmapWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700259 } else {
tsepez0e606b52016-11-18 16:22:41 -0800260 pDict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceRGB");
261 pDict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
thestig4ccdb142016-11-21 15:09:23 -0800262 dest_pitch = BitmapWidth * 3;
263 bCopyWithoutAlpha = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700264 }
thestig4ccdb142016-11-21 15:09:23 -0800265
Dan Sinclair0b950422017-09-21 15:49:49 -0400266 RetainPtr<CFX_DIBitmap> pMaskBitmap;
tsepez72c1bda2016-12-14 14:15:14 -0800267 if (pBitmap->HasAlpha())
268 pMaskBitmap = pBitmap->CloneAlphaMask();
269
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700270 if (pMaskBitmap) {
271 int32_t maskWidth = pMaskBitmap->GetWidth();
272 int32_t maskHeight = pMaskBitmap->GetHeight();
tsepez47fb8c02016-12-15 13:51:34 -0800273 std::unique_ptr<uint8_t, FxFreeDeleter> mask_buf;
Ryan Harrisonaa3a9cd2017-08-29 16:39:44 -0400274 int32_t mask_size = 0;
tsepez9e05ee12016-11-21 13:19:10 -0800275 auto pMaskDict =
276 pdfium::MakeUnique<CPDF_Dictionary>(m_pDocument->GetByteStringPool());
tsepez0e606b52016-11-18 16:22:41 -0800277 pMaskDict->SetNewFor<CPDF_Name>("Type", "XObject");
278 pMaskDict->SetNewFor<CPDF_Name>("Subtype", "Image");
279 pMaskDict->SetNewFor<CPDF_Number>("Width", maskWidth);
280 pMaskDict->SetNewFor<CPDF_Number>("Height", maskHeight);
281 pMaskDict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
282 pMaskDict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
thestig4ccdb142016-11-21 15:09:23 -0800283 if (pMaskBitmap->GetFormat() != FXDIB_1bppMask) {
tsepez47fb8c02016-12-15 13:51:34 -0800284 mask_buf.reset(FX_Alloc2D(uint8_t, maskHeight, maskWidth));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700285 mask_size = maskHeight * maskWidth; // Safe since checked alloc returned.
286 for (int32_t a = 0; a < maskHeight; a++) {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400287 memcpy(mask_buf.get() + a * maskWidth, pMaskBitmap->GetScanline(a),
288 maskWidth);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700289 }
290 }
tsepez0e606b52016-11-18 16:22:41 -0800291 pMaskDict->SetNewFor<CPDF_Number>("Length", mask_size);
tsepez9e05ee12016-11-21 13:19:10 -0800292 CPDF_Stream* pNewStream = m_pDocument->NewIndirect<CPDF_Stream>(
tsepez47fb8c02016-12-15 13:51:34 -0800293 std::move(mask_buf), mask_size, std::move(pMaskDict));
Artem Stryginfb727262018-06-11 18:19:57 +0000294 pDict->SetFor("SMask", pNewStream->MakeReference(m_pDocument.Get()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700295 }
dsinclair65ea3942016-03-25 09:16:34 -0700296
thestig4ccdb142016-11-21 15:09:23 -0800297 uint8_t* src_buf = pBitmap->GetBuffer();
298 int32_t src_pitch = pBitmap->GetPitch();
299 uint8_t* dest_buf = FX_Alloc2D(uint8_t, dest_pitch, BitmapHeight);
300 // Safe as checked alloc returned.
Ryan Harrison875e98c2017-09-27 10:53:11 -0400301 size_t dest_size = dest_pitch * BitmapHeight;
thestig4ccdb142016-11-21 15:09:23 -0800302 uint8_t* pDest = dest_buf;
303 if (bCopyWithoutAlpha) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304 for (int32_t i = 0; i < BitmapHeight; i++) {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400305 memcpy(pDest, src_buf, dest_pitch);
dsinclair65ea3942016-03-25 09:16:34 -0700306 pDest += dest_pitch;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700307 src_buf += src_pitch;
308 }
thestig4ccdb142016-11-21 15:09:23 -0800309 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700310 int32_t src_offset = 0;
311 int32_t dest_offset = 0;
312 for (int32_t row = 0; row < BitmapHeight; row++) {
313 src_offset = row * src_pitch;
314 for (int32_t column = 0; column < BitmapWidth; column++) {
Dan Sinclair05df0752017-03-14 14:43:42 -0400315 float alpha = 1;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700316 pDest[dest_offset] = (uint8_t)(src_buf[src_offset + 2] * alpha);
317 pDest[dest_offset + 1] = (uint8_t)(src_buf[src_offset + 1] * alpha);
318 pDest[dest_offset + 2] = (uint8_t)(src_buf[src_offset] * alpha);
319 dest_offset += 3;
320 src_offset += bpp == 24 ? 3 : 4;
321 }
dsinclair65ea3942016-03-25 09:16:34 -0700322
323 pDest += dest_pitch;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700324 dest_offset = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700325 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700326 }
tsepez9fd0c632016-11-23 14:34:58 -0800327 if (!m_pStream)
328 m_pStream = pdfium::MakeUnique<CPDF_Stream>();
329
Tom Sepez367ed462018-08-23 23:52:53 +0000330 m_pStream->InitStream({dest_buf, dest_size}, std::move(pDict));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700331 m_bIsMask = pBitmap->IsAlphaMask();
332 m_Width = BitmapWidth;
333 m_Height = BitmapHeight;
Lei Zhangda180e92015-08-14 22:22:13 -0700334 FX_Free(dest_buf);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700335}
dan sinclair61b2fc72016-03-23 19:21:44 -0400336
Lei Zhang66601c42018-10-02 18:58:16 +0000337void CPDF_Image::ResetCache(CPDF_Page* pPage) {
Dan Sinclair0b950422017-09-21 15:49:49 -0400338 RetainPtr<CPDF_Image> pHolder(this);
Lei Zhang66601c42018-10-02 18:58:16 +0000339 pPage->GetRenderCache()->ResetBitmap(pHolder);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700340}
dan sinclair61b2fc72016-03-23 19:21:44 -0400341
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000342RetainPtr<CFX_DIBBase> CPDF_Image::LoadDIBBase() const {
343 auto source = pdfium::MakeRetain<CPDF_DIBBase>();
Tom Sepez47345122017-05-24 14:07:18 -0700344 if (!source->Load(m_pDocument.Get(), m_pStream.Get()))
tsepez5bed98c2016-12-14 13:54:33 -0800345 return nullptr;
Nicolas Pena48f776f2017-01-05 13:22:17 -0500346
Lei Zhang1330ebb2018-03-05 15:16:37 +0000347 if (!source->IsJBigImage())
348 return source;
349
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000350 CPDF_DIBBase::LoadState ret = CPDF_DIBBase::LoadState::kContinue;
351 while (ret == CPDF_DIBBase::LoadState::kContinue)
352 ret = source->ContinueLoadDIBBase(nullptr);
353 return ret == CPDF_DIBBase::LoadState::kSuccess ? source : nullptr;
dan sinclair61b2fc72016-03-23 19:21:44 -0400354}
355
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000356RetainPtr<CFX_DIBBase> CPDF_Image::DetachBitmap() {
357 return std::move(m_pDIBBase);
dan sinclair61b2fc72016-03-23 19:21:44 -0400358}
359
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000360RetainPtr<CFX_DIBBase> CPDF_Image::DetachMask() {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700361 return std::move(m_pMask);
dan sinclair61b2fc72016-03-23 19:21:44 -0400362}
363
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000364bool CPDF_Image::StartLoadDIBBase(const CPDF_Dictionary* pFormResource,
365 CPDF_Dictionary* pPageResource,
366 bool bStdCS,
367 uint32_t GroupFamily,
368 bool bLoadMask) {
369 auto source = pdfium::MakeRetain<CPDF_DIBBase>();
370 CPDF_DIBBase::LoadState ret = source->StartLoadDIBBase(
Lei Zhang40482e62018-03-05 15:03:37 +0000371 m_pDocument.Get(), m_pStream.Get(), true, pFormResource, pPageResource,
372 bStdCS, GroupFamily, bLoadMask);
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000373 if (ret == CPDF_DIBBase::LoadState::kFail) {
374 m_pDIBBase.Reset();
tsepez12f3e4a2016-11-02 15:17:29 -0700375 return false;
dan sinclair61b2fc72016-03-23 19:21:44 -0400376 }
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000377 m_pDIBBase = source;
378 if (ret == CPDF_DIBBase::LoadState::kContinue)
Tom Sepezf0799fe2017-03-28 09:31:32 -0700379 return true;
380
dan sinclair61b2fc72016-03-23 19:21:44 -0400381 m_pMask = source->DetachMask();
382 m_MatteColor = source->GetMatteColor();
tsepez12f3e4a2016-11-02 15:17:29 -0700383 return false;
dan sinclair61b2fc72016-03-23 19:21:44 -0400384}
385
Dan Sinclaira32145f2018-03-06 18:53:05 +0000386bool CPDF_Image::Continue(PauseIndicatorIface* pPause) {
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000387 RetainPtr<CPDF_DIBBase> pSource = m_pDIBBase.As<CPDF_DIBBase>();
388 CPDF_DIBBase::LoadState ret = pSource->ContinueLoadDIBBase(pPause);
389 if (ret == CPDF_DIBBase::LoadState::kContinue)
Tom Sepezf0799fe2017-03-28 09:31:32 -0700390 return true;
391
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000392 if (ret == CPDF_DIBBase::LoadState::kSuccess) {
Lei Zhangb0583652018-03-05 14:46:57 +0000393 m_pMask = pSource->DetachMask();
394 m_MatteColor = pSource->GetMatteColor();
395 } else {
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000396 m_pDIBBase.Reset();
Lei Zhangb0583652018-03-05 14:46:57 +0000397 }
tsepez12f3e4a2016-11-02 15:17:29 -0700398 return false;
dan sinclair61b2fc72016-03-23 19:21:44 -0400399}