blob: 68a6a3243ce0db9c0b72098d81844e84f7520c95 [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"
Nicolas Pena0ef7ba02017-01-04 16:18:57 -050026#include "core/fpdfapi/render/cpdf_dibsource.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
tsepez4e4d1a62016-10-13 15:56:53 -070035CPDF_Image::CPDF_Image(CPDF_Document* pDoc) : m_pDocument(pDoc) {}
thestigdc359b02016-08-09 15:46:20 -070036
tsepez33fdebc2016-11-04 11:38:40 -070037CPDF_Image::CPDF_Image(CPDF_Document* pDoc,
38 std::unique_ptr<CPDF_Stream> pStream)
Tom Sepezbb1ee532018-01-30 18:10:01 +000039 : m_bIsInline(true), m_pDocument(pDoc), m_pStream(std::move(pStream)) {
tsepez9fd0c632016-11-23 14:34:58 -080040 ASSERT(m_pStream.IsOwned());
Tom Sepezbb1ee532018-01-30 18:10:01 +000041 FinishInitialization(m_pStream->GetDict());
thestigdc359b02016-08-09 15:46:20 -070042}
dan sinclair61b2fc72016-03-23 19:21:44 -040043
tsepez4e4d1a62016-10-13 15:56:53 -070044CPDF_Image::CPDF_Image(CPDF_Document* pDoc, uint32_t dwStreamObjNum)
45 : m_pDocument(pDoc),
Tom Sepezbb1ee532018-01-30 18:10:01 +000046 m_pStream(ToStream(pDoc->GetIndirectObject(dwStreamObjNum))) {
tsepez9fd0c632016-11-23 14:34:58 -080047 ASSERT(!m_pStream.IsOwned());
Tom Sepezbb1ee532018-01-30 18:10:01 +000048 FinishInitialization(m_pStream->GetDict());
tsepez4e4d1a62016-10-13 15:56:53 -070049}
50
51CPDF_Image::~CPDF_Image() {}
52
Lei Zhangaca3efc2018-03-16 20:27:04 +000053void CPDF_Image::FinishInitialization(CPDF_Dictionary* pStreamDict) {
54 m_pOC = pStreamDict->GetDictFor("OC");
55 m_bIsMask = !pStreamDict->KeyExist("ColorSpace") ||
56 pStreamDict->GetIntegerFor("ImageMask");
57 m_bInterpolate = !!pStreamDict->GetIntegerFor("Interpolate");
58 m_Height = pStreamDict->GetIntegerFor("Height");
59 m_Width = pStreamDict->GetIntegerFor("Width");
dan sinclair61b2fc72016-03-23 19:21:44 -040060}
61
tsepez137a3442016-11-14 15:03:55 -080062void CPDF_Image::ConvertStreamToIndirectObject() {
63 if (!m_pStream->IsInline())
64 return;
65
tsepez9fd0c632016-11-23 14:34:58 -080066 ASSERT(m_pStream.IsOwned());
67 m_pDocument->AddIndirectObject(m_pStream.Release());
tsepez137a3442016-11-14 15:03:55 -080068}
69
Lei Zhang731526e2017-12-11 21:28:38 +000070CPDF_Dictionary* CPDF_Image::GetDict() const {
71 return m_pStream ? m_pStream->GetDict() : nullptr;
72}
73
tsepez06104a82016-11-21 16:22:10 -080074std::unique_ptr<CPDF_Dictionary> CPDF_Image::InitJPEG(uint8_t* pData,
75 uint32_t size) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070076 int32_t width;
77 int32_t height;
78 int32_t num_comps;
79 int32_t bits;
thestigb0fcfad2016-06-06 17:54:29 -070080 bool color_trans;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070081 if (!CPDF_ModuleMgr::Get()->GetJpegModule()->LoadInfo(
thestigb0fcfad2016-06-06 17:54:29 -070082 pData, size, &width, &height, &num_comps, &bits, &color_trans)) {
83 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070084 }
thestigb0fcfad2016-06-06 17:54:29 -070085
tsepez06104a82016-11-21 16:22:10 -080086 auto pDict =
87 pdfium::MakeUnique<CPDF_Dictionary>(m_pDocument->GetByteStringPool());
tsepez0e606b52016-11-18 16:22:41 -080088 pDict->SetNewFor<CPDF_Name>("Type", "XObject");
89 pDict->SetNewFor<CPDF_Name>("Subtype", "Image");
90 pDict->SetNewFor<CPDF_Number>("Width", width);
91 pDict->SetNewFor<CPDF_Number>("Height", height);
Dan Sinclair812e96c2017-03-13 16:43:37 -040092 const char* csname = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -070093 if (num_comps == 1) {
94 csname = "DeviceGray";
95 } else if (num_comps == 3) {
96 csname = "DeviceRGB";
97 } else if (num_comps == 4) {
98 csname = "DeviceCMYK";
tsepez0e606b52016-11-18 16:22:41 -080099 CPDF_Array* pDecode = pDict->SetNewFor<CPDF_Array>("Decode");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700100 for (int n = 0; n < 4; n++) {
tsepez8a3aa452016-11-16 12:26:06 -0800101 pDecode->AddNew<CPDF_Number>(1);
102 pDecode->AddNew<CPDF_Number>(0);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700103 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700104 }
tsepez0e606b52016-11-18 16:22:41 -0800105 pDict->SetNewFor<CPDF_Name>("ColorSpace", csname);
106 pDict->SetNewFor<CPDF_Number>("BitsPerComponent", bits);
107 pDict->SetNewFor<CPDF_Name>("Filter", "DCTDecode");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700108 if (!color_trans) {
Lei Zhang26170562018-04-17 17:01:52 +0000109 CPDF_Dictionary* pParms =
110 pDict->SetNewFor<CPDF_Dictionary>(pdfium::stream::kDecodeParms);
tsepez0e606b52016-11-18 16:22:41 -0800111 pParms->SetNewFor<CPDF_Number>("ColorTransform", 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700112 }
tsepez12f3e4a2016-11-02 15:17:29 -0700113 m_bIsMask = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700114 m_Width = width;
115 m_Height = height;
tsepez9fd0c632016-11-23 14:34:58 -0800116 if (!m_pStream)
117 m_pStream = pdfium::MakeUnique<CPDF_Stream>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700118 return pDict;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700119}
dan sinclair61b2fc72016-03-23 19:21:44 -0400120
Dan Sinclair0b950422017-09-21 15:49:49 -0400121void CPDF_Image::SetJpegImage(const RetainPtr<IFX_SeekableReadStream>& pFile) {
tsepez06104a82016-11-21 16:22:10 -0800122 uint32_t size = pdfium::base::checked_cast<uint32_t>(pFile->GetSize());
thestigdc359b02016-08-09 15:46:20 -0700123 if (!size)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700124 return;
thestigdc359b02016-08-09 15:46:20 -0700125
126 uint32_t dwEstimateSize = std::min(size, 8192U);
127 std::vector<uint8_t> data(dwEstimateSize);
tsepez06104a82016-11-21 16:22:10 -0800128 if (!pFile->ReadBlock(data.data(), 0, dwEstimateSize))
129 return;
130
131 std::unique_ptr<CPDF_Dictionary> pDict =
132 InitJPEG(data.data(), dwEstimateSize);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700133 if (!pDict && size > dwEstimateSize) {
thestigdc359b02016-08-09 15:46:20 -0700134 data.resize(size);
135 pFile->ReadBlock(data.data(), 0, size);
136 pDict = InitJPEG(data.data(), size);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137 }
thestigdc359b02016-08-09 15:46:20 -0700138 if (!pDict)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139 return;
thestigdc359b02016-08-09 15:46:20 -0700140
tsepez06104a82016-11-21 16:22:10 -0800141 m_pStream->InitStreamFromFile(pFile, std::move(pDict));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700142}
dan sinclair61b2fc72016-03-23 19:21:44 -0400143
rbpotterf085db32016-12-14 11:44:31 -0800144void CPDF_Image::SetJpegImageInline(
Dan Sinclair0b950422017-09-21 15:49:49 -0400145 const RetainPtr<IFX_SeekableReadStream>& pFile) {
rbpotterf085db32016-12-14 11:44:31 -0800146 uint32_t size = pdfium::base::checked_cast<uint32_t>(pFile->GetSize());
147 if (!size)
148 return;
149
150 std::vector<uint8_t> data(size);
151 if (!pFile->ReadBlock(data.data(), 0, size))
152 return;
153
154 std::unique_ptr<CPDF_Dictionary> pDict = InitJPEG(data.data(), size);
155 if (!pDict)
156 return;
157
158 m_pStream->InitStream(&(data[0]), size, std::move(pDict));
159}
160
Dan Sinclair0b950422017-09-21 15:49:49 -0400161void CPDF_Image::SetImage(const RetainPtr<CFX_DIBitmap>& pBitmap) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700162 int32_t BitmapWidth = pBitmap->GetWidth();
163 int32_t BitmapHeight = pBitmap->GetHeight();
thestig4ccdb142016-11-21 15:09:23 -0800164 if (BitmapWidth < 1 || BitmapHeight < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700165 return;
dan sinclair61b2fc72016-03-23 19:21:44 -0400166
tsepez9e05ee12016-11-21 13:19:10 -0800167 auto pDict =
168 pdfium::MakeUnique<CPDF_Dictionary>(m_pDocument->GetByteStringPool());
tsepez0e606b52016-11-18 16:22:41 -0800169 pDict->SetNewFor<CPDF_Name>("Type", "XObject");
170 pDict->SetNewFor<CPDF_Name>("Subtype", "Image");
171 pDict->SetNewFor<CPDF_Number>("Width", BitmapWidth);
172 pDict->SetNewFor<CPDF_Number>("Height", BitmapHeight);
thestig4ccdb142016-11-21 15:09:23 -0800173
174 const int32_t bpp = pBitmap->GetBPP();
Ryan Harrison875e98c2017-09-27 10:53:11 -0400175 size_t dest_pitch = 0;
thestig4ccdb142016-11-21 15:09:23 -0800176 bool bCopyWithoutAlpha = true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700177 if (bpp == 1) {
thestig4ccdb142016-11-21 15:09:23 -0800178 int32_t reset_a = 0;
179 int32_t reset_r = 0;
180 int32_t reset_g = 0;
181 int32_t reset_b = 0;
182 int32_t set_a = 0;
183 int32_t set_r = 0;
184 int32_t set_g = 0;
185 int32_t set_b = 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700186 if (!pBitmap->IsAlphaMask()) {
Nicolas Penaddfc3dc2017-04-20 15:29:25 -0400187 std::tie(reset_a, reset_r, reset_g, reset_b) =
188 ArgbDecode(pBitmap->GetPaletteArgb(0));
189 std::tie(set_a, set_r, set_g, set_b) =
190 ArgbDecode(pBitmap->GetPaletteArgb(1));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700191 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700192 if (set_a == 0 || reset_a == 0) {
tsepez0e606b52016-11-18 16:22:41 -0800193 pDict->SetNewFor<CPDF_Boolean>("ImageMask", true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700194 if (reset_a == 0) {
tsepez0e606b52016-11-18 16:22:41 -0800195 CPDF_Array* pArray = pDict->SetNewFor<CPDF_Array>("Decode");
tsepez8a3aa452016-11-16 12:26:06 -0800196 pArray->AddNew<CPDF_Number>(1);
197 pArray->AddNew<CPDF_Number>(0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700198 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700199 } else {
tsepez0e606b52016-11-18 16:22:41 -0800200 CPDF_Array* pCS = pDict->SetNewFor<CPDF_Array>("ColorSpace");
tsepez8a3aa452016-11-16 12:26:06 -0800201 pCS->AddNew<CPDF_Name>("Indexed");
202 pCS->AddNew<CPDF_Name>("DeviceRGB");
203 pCS->AddNew<CPDF_Number>(1);
Ryan Harrison275e2602017-09-18 14:23:18 -0400204 ByteString ct;
Tom Sepez3d523e32018-04-16 17:28:17 +0000205 char* pBuf = ct.GetBuffer(6);
206 pBuf[0] = (char)reset_r;
207 pBuf[1] = (char)reset_g;
208 pBuf[2] = (char)reset_b;
209 pBuf[3] = (char)set_r;
210 pBuf[4] = (char)set_g;
211 pBuf[5] = (char)set_b;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700212 ct.ReleaseBuffer(6);
tsepez8a3aa452016-11-16 12:26:06 -0800213 pCS->AddNew<CPDF_String>(ct, true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700214 }
tsepez0e606b52016-11-18 16:22:41 -0800215 pDict->SetNewFor<CPDF_Number>("BitsPerComponent", 1);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700216 dest_pitch = (BitmapWidth + 7) / 8;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700217 } else if (bpp == 8) {
218 int32_t iPalette = pBitmap->GetPaletteSize();
219 if (iPalette > 0) {
tsepez70c4afd2016-11-15 11:33:44 -0800220 CPDF_Array* pCS = m_pDocument->NewIndirect<CPDF_Array>();
tsepez8a3aa452016-11-16 12:26:06 -0800221 pCS->AddNew<CPDF_Name>("Indexed");
222 pCS->AddNew<CPDF_Name>("DeviceRGB");
223 pCS->AddNew<CPDF_Number>(iPalette - 1);
tsepez47fb8c02016-12-15 13:51:34 -0800224 std::unique_ptr<uint8_t, FxFreeDeleter> pColorTable(
225 FX_Alloc2D(uint8_t, iPalette, 3));
226 uint8_t* ptr = pColorTable.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700227 for (int32_t i = 0; i < iPalette; i++) {
tsepezb5e8f142016-03-25 15:18:35 -0700228 uint32_t argb = pBitmap->GetPaletteArgb(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700229 ptr[0] = (uint8_t)(argb >> 16);
230 ptr[1] = (uint8_t)(argb >> 8);
231 ptr[2] = (uint8_t)argb;
232 ptr += 3;
233 }
tsepez9e05ee12016-11-21 13:19:10 -0800234 auto pNewDict =
235 pdfium::MakeUnique<CPDF_Dictionary>(m_pDocument->GetByteStringPool());
tsepez70c4afd2016-11-15 11:33:44 -0800236 CPDF_Stream* pCTS = m_pDocument->NewIndirect<CPDF_Stream>(
tsepez47fb8c02016-12-15 13:51:34 -0800237 std::move(pColorTable), iPalette * 3, std::move(pNewDict));
Tom Sepez47345122017-05-24 14:07:18 -0700238 pCS->AddNew<CPDF_Reference>(m_pDocument.Get(), pCTS->GetObjNum());
239 pDict->SetNewFor<CPDF_Reference>("ColorSpace", m_pDocument.Get(),
tsepez0e606b52016-11-18 16:22:41 -0800240 pCS->GetObjNum());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700241 } else {
tsepez0e606b52016-11-18 16:22:41 -0800242 pDict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700243 }
tsepez0e606b52016-11-18 16:22:41 -0800244 pDict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
thestig4ccdb142016-11-21 15:09:23 -0800245 dest_pitch = BitmapWidth;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700246 } else {
tsepez0e606b52016-11-18 16:22:41 -0800247 pDict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceRGB");
248 pDict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
thestig4ccdb142016-11-21 15:09:23 -0800249 dest_pitch = BitmapWidth * 3;
250 bCopyWithoutAlpha = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700251 }
thestig4ccdb142016-11-21 15:09:23 -0800252
Dan Sinclair0b950422017-09-21 15:49:49 -0400253 RetainPtr<CFX_DIBitmap> pMaskBitmap;
tsepez72c1bda2016-12-14 14:15:14 -0800254 if (pBitmap->HasAlpha())
255 pMaskBitmap = pBitmap->CloneAlphaMask();
256
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700257 if (pMaskBitmap) {
258 int32_t maskWidth = pMaskBitmap->GetWidth();
259 int32_t maskHeight = pMaskBitmap->GetHeight();
tsepez47fb8c02016-12-15 13:51:34 -0800260 std::unique_ptr<uint8_t, FxFreeDeleter> mask_buf;
Ryan Harrisonaa3a9cd2017-08-29 16:39:44 -0400261 int32_t mask_size = 0;
tsepez9e05ee12016-11-21 13:19:10 -0800262 auto pMaskDict =
263 pdfium::MakeUnique<CPDF_Dictionary>(m_pDocument->GetByteStringPool());
tsepez0e606b52016-11-18 16:22:41 -0800264 pMaskDict->SetNewFor<CPDF_Name>("Type", "XObject");
265 pMaskDict->SetNewFor<CPDF_Name>("Subtype", "Image");
266 pMaskDict->SetNewFor<CPDF_Number>("Width", maskWidth);
267 pMaskDict->SetNewFor<CPDF_Number>("Height", maskHeight);
268 pMaskDict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
269 pMaskDict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
thestig4ccdb142016-11-21 15:09:23 -0800270 if (pMaskBitmap->GetFormat() != FXDIB_1bppMask) {
tsepez47fb8c02016-12-15 13:51:34 -0800271 mask_buf.reset(FX_Alloc2D(uint8_t, maskHeight, maskWidth));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700272 mask_size = maskHeight * maskWidth; // Safe since checked alloc returned.
273 for (int32_t a = 0; a < maskHeight; a++) {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400274 memcpy(mask_buf.get() + a * maskWidth, pMaskBitmap->GetScanline(a),
275 maskWidth);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700276 }
277 }
tsepez0e606b52016-11-18 16:22:41 -0800278 pMaskDict->SetNewFor<CPDF_Number>("Length", mask_size);
tsepez9e05ee12016-11-21 13:19:10 -0800279 CPDF_Stream* pNewStream = m_pDocument->NewIndirect<CPDF_Stream>(
tsepez47fb8c02016-12-15 13:51:34 -0800280 std::move(mask_buf), mask_size, std::move(pMaskDict));
Tom Sepez47345122017-05-24 14:07:18 -0700281 pDict->SetNewFor<CPDF_Reference>("SMask", m_pDocument.Get(),
tsepez9e05ee12016-11-21 13:19:10 -0800282 pNewStream->GetObjNum());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283 }
dsinclair65ea3942016-03-25 09:16:34 -0700284
thestig4ccdb142016-11-21 15:09:23 -0800285 uint8_t* src_buf = pBitmap->GetBuffer();
286 int32_t src_pitch = pBitmap->GetPitch();
287 uint8_t* dest_buf = FX_Alloc2D(uint8_t, dest_pitch, BitmapHeight);
288 // Safe as checked alloc returned.
Ryan Harrison875e98c2017-09-27 10:53:11 -0400289 size_t dest_size = dest_pitch * BitmapHeight;
thestig4ccdb142016-11-21 15:09:23 -0800290 uint8_t* pDest = dest_buf;
291 if (bCopyWithoutAlpha) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700292 for (int32_t i = 0; i < BitmapHeight; i++) {
Dan Sinclair1c5d0b42017-04-03 15:05:11 -0400293 memcpy(pDest, src_buf, dest_pitch);
dsinclair65ea3942016-03-25 09:16:34 -0700294 pDest += dest_pitch;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700295 src_buf += src_pitch;
296 }
thestig4ccdb142016-11-21 15:09:23 -0800297 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700298 int32_t src_offset = 0;
299 int32_t dest_offset = 0;
300 for (int32_t row = 0; row < BitmapHeight; row++) {
301 src_offset = row * src_pitch;
302 for (int32_t column = 0; column < BitmapWidth; column++) {
Dan Sinclair05df0752017-03-14 14:43:42 -0400303 float alpha = 1;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304 pDest[dest_offset] = (uint8_t)(src_buf[src_offset + 2] * alpha);
305 pDest[dest_offset + 1] = (uint8_t)(src_buf[src_offset + 1] * alpha);
306 pDest[dest_offset + 2] = (uint8_t)(src_buf[src_offset] * alpha);
307 dest_offset += 3;
308 src_offset += bpp == 24 ? 3 : 4;
309 }
dsinclair65ea3942016-03-25 09:16:34 -0700310
311 pDest += dest_pitch;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700312 dest_offset = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700313 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700314 }
tsepez9fd0c632016-11-23 14:34:58 -0800315 if (!m_pStream)
316 m_pStream = pdfium::MakeUnique<CPDF_Stream>();
317
tsepez9e05ee12016-11-21 13:19:10 -0800318 m_pStream->InitStream(dest_buf, dest_size, std::move(pDict));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319 m_bIsMask = pBitmap->IsAlphaMask();
320 m_Width = BitmapWidth;
321 m_Height = BitmapHeight;
Lei Zhangda180e92015-08-14 22:22:13 -0700322 FX_Free(dest_buf);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700323}
dan sinclair61b2fc72016-03-23 19:21:44 -0400324
Tom Sepezf0799fe2017-03-28 09:31:32 -0700325void CPDF_Image::ResetCache(CPDF_Page* pPage,
Dan Sinclair0b950422017-09-21 15:49:49 -0400326 const RetainPtr<CFX_DIBitmap>& pBitmap) {
327 RetainPtr<CPDF_Image> pHolder(this);
Tom Sepez258909c2017-05-23 14:31:00 -0700328 pPage->GetRenderCache()->ResetBitmap(pHolder, pBitmap);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700329}
dan sinclair61b2fc72016-03-23 19:21:44 -0400330
Dan Sinclair0b950422017-09-21 15:49:49 -0400331RetainPtr<CFX_DIBSource> CPDF_Image::LoadDIBSource() const {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700332 auto source = pdfium::MakeRetain<CPDF_DIBSource>();
Tom Sepez47345122017-05-24 14:07:18 -0700333 if (!source->Load(m_pDocument.Get(), m_pStream.Get()))
tsepez5bed98c2016-12-14 13:54:33 -0800334 return nullptr;
Nicolas Pena48f776f2017-01-05 13:22:17 -0500335
Lei Zhang1330ebb2018-03-05 15:16:37 +0000336 if (!source->IsJBigImage())
337 return source;
338
339 CPDF_DIBSource::LoadState ret = CPDF_DIBSource::LoadState::kContinue;
340 while (ret == CPDF_DIBSource::LoadState::kContinue)
341 ret = source->ContinueLoadDIBSource(nullptr);
342 return ret == CPDF_DIBSource::LoadState::kSuccess ? source : nullptr;
dan sinclair61b2fc72016-03-23 19:21:44 -0400343}
344
Dan Sinclair0b950422017-09-21 15:49:49 -0400345RetainPtr<CFX_DIBSource> CPDF_Image::DetachBitmap() {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700346 return std::move(m_pDIBSource);
dan sinclair61b2fc72016-03-23 19:21:44 -0400347}
348
Dan Sinclair0b950422017-09-21 15:49:49 -0400349RetainPtr<CFX_DIBSource> CPDF_Image::DetachMask() {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700350 return std::move(m_pMask);
dan sinclair61b2fc72016-03-23 19:21:44 -0400351}
352
tsepez12f3e4a2016-11-02 15:17:29 -0700353bool CPDF_Image::StartLoadDIBSource(CPDF_Dictionary* pFormResource,
354 CPDF_Dictionary* pPageResource,
355 bool bStdCS,
356 uint32_t GroupFamily,
357 bool bLoadMask) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700358 auto source = pdfium::MakeRetain<CPDF_DIBSource>();
Lei Zhang40482e62018-03-05 15:03:37 +0000359 CPDF_DIBSource::LoadState ret = source->StartLoadDIBSource(
360 m_pDocument.Get(), m_pStream.Get(), true, pFormResource, pPageResource,
361 bStdCS, GroupFamily, bLoadMask);
362 if (ret == CPDF_DIBSource::LoadState::kFail) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700363 m_pDIBSource.Reset();
tsepez12f3e4a2016-11-02 15:17:29 -0700364 return false;
dan sinclair61b2fc72016-03-23 19:21:44 -0400365 }
Tom Sepezf0799fe2017-03-28 09:31:32 -0700366 m_pDIBSource = source;
Lei Zhang40482e62018-03-05 15:03:37 +0000367 if (ret == CPDF_DIBSource::LoadState::kContinue)
Tom Sepezf0799fe2017-03-28 09:31:32 -0700368 return true;
369
dan sinclair61b2fc72016-03-23 19:21:44 -0400370 m_pMask = source->DetachMask();
371 m_MatteColor = source->GetMatteColor();
tsepez12f3e4a2016-11-02 15:17:29 -0700372 return false;
dan sinclair61b2fc72016-03-23 19:21:44 -0400373}
374
Dan Sinclaira32145f2018-03-06 18:53:05 +0000375bool CPDF_Image::Continue(PauseIndicatorIface* pPause) {
Dan Sinclair0b950422017-09-21 15:49:49 -0400376 RetainPtr<CPDF_DIBSource> pSource = m_pDIBSource.As<CPDF_DIBSource>();
Lei Zhang40482e62018-03-05 15:03:37 +0000377 CPDF_DIBSource::LoadState ret = pSource->ContinueLoadDIBSource(pPause);
378 if (ret == CPDF_DIBSource::LoadState::kContinue)
Tom Sepezf0799fe2017-03-28 09:31:32 -0700379 return true;
380
Lei Zhang40482e62018-03-05 15:03:37 +0000381 if (ret == CPDF_DIBSource::LoadState::kSuccess) {
Lei Zhangb0583652018-03-05 14:46:57 +0000382 m_pMask = pSource->DetachMask();
383 m_MatteColor = pSource->GetMatteColor();
384 } else {
385 m_pDIBSource.Reset();
386 }
tsepez12f3e4a2016-11-02 15:17:29 -0700387 return false;
dan sinclair61b2fc72016-03-23 19:21:44 -0400388}