1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include "public/fpdf_edit.h"
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include <memory>
10*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
11*3ac0a46fSAndroid Build Coastguard Worker
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_dib.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_image.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_imageobject.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_page.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/page/cpdf_pageobject.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_array.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_dictionary.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_name.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_stream.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/parser/cpdf_stream_acc.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/render/cpdf_imagerenderer.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/render/cpdf_rendercontext.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "core/fpdfapi/render/cpdf_renderstatus.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/stl_util.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_defaultrenderdevice.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/dib/cfx_dibitmap.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_customaccess.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/cpdfsdk_helpers.h"
30*3ac0a46fSAndroid Build Coastguard Worker
31*3ac0a46fSAndroid Build Coastguard Worker namespace {
32*3ac0a46fSAndroid Build Coastguard Worker
33*3ac0a46fSAndroid Build Coastguard Worker // These checks ensure the consistency of colorspace values across core/ and
34*3ac0a46fSAndroid Build Coastguard Worker // public/.
35*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceGray) ==
36*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_DEVICEGRAY,
37*3ac0a46fSAndroid Build Coastguard Worker "kDeviceGray value mismatch");
38*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceRGB) ==
39*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_DEVICERGB,
40*3ac0a46fSAndroid Build Coastguard Worker "kDeviceRGB value mismatch");
41*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceCMYK) ==
42*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_DEVICECMYK,
43*3ac0a46fSAndroid Build Coastguard Worker "kDeviceCMYK value mismatch");
44*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kCalGray) ==
45*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_CALGRAY,
46*3ac0a46fSAndroid Build Coastguard Worker "kCalGray value mismatch");
47*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kCalRGB) ==
48*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_CALRGB,
49*3ac0a46fSAndroid Build Coastguard Worker "kCalRGB value mismatch");
50*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kLab) ==
51*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_LAB,
52*3ac0a46fSAndroid Build Coastguard Worker "kLab value mismatch");
53*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kICCBased) ==
54*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_ICCBASED,
55*3ac0a46fSAndroid Build Coastguard Worker "kICCBased value mismatch");
56*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kSeparation) ==
57*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_SEPARATION,
58*3ac0a46fSAndroid Build Coastguard Worker "kSeparation value mismatch");
59*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceN) ==
60*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_DEVICEN,
61*3ac0a46fSAndroid Build Coastguard Worker "kDeviceN value mismatch");
62*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kIndexed) ==
63*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_INDEXED,
64*3ac0a46fSAndroid Build Coastguard Worker "kIndexed value mismatch");
65*3ac0a46fSAndroid Build Coastguard Worker static_assert(static_cast<int>(CPDF_ColorSpace::Family::kPattern) ==
66*3ac0a46fSAndroid Build Coastguard Worker FPDF_COLORSPACE_PATTERN,
67*3ac0a46fSAndroid Build Coastguard Worker "kPattern value mismatch");
68*3ac0a46fSAndroid Build Coastguard Worker
MakeSeekableReadStream(FPDF_FILEACCESS * pFileAccess)69*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
70*3ac0a46fSAndroid Build Coastguard Worker FPDF_FILEACCESS* pFileAccess) {
71*3ac0a46fSAndroid Build Coastguard Worker return pdfium::MakeRetain<CPDFSDK_CustomAccess>(pFileAccess);
72*3ac0a46fSAndroid Build Coastguard Worker }
73*3ac0a46fSAndroid Build Coastguard Worker
CPDFImageObjectFromFPDFPageObject(FPDF_PAGEOBJECT image_object)74*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* CPDFImageObjectFromFPDFPageObject(
75*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT image_object) {
76*3ac0a46fSAndroid Build Coastguard Worker CPDF_PageObject* pPageObject = CPDFPageObjectFromFPDFPageObject(image_object);
77*3ac0a46fSAndroid Build Coastguard Worker return pPageObject ? pPageObject->AsImage() : nullptr;
78*3ac0a46fSAndroid Build Coastguard Worker }
79*3ac0a46fSAndroid Build Coastguard Worker
LoadJpegHelper(FPDF_PAGE * pages,int count,FPDF_PAGEOBJECT image_object,FPDF_FILEACCESS * file_access,bool inline_jpeg)80*3ac0a46fSAndroid Build Coastguard Worker bool LoadJpegHelper(FPDF_PAGE* pages,
81*3ac0a46fSAndroid Build Coastguard Worker int count,
82*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT image_object,
83*3ac0a46fSAndroid Build Coastguard Worker FPDF_FILEACCESS* file_access,
84*3ac0a46fSAndroid Build Coastguard Worker bool inline_jpeg) {
85*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
86*3ac0a46fSAndroid Build Coastguard Worker if (!pImgObj)
87*3ac0a46fSAndroid Build Coastguard Worker return false;
88*3ac0a46fSAndroid Build Coastguard Worker
89*3ac0a46fSAndroid Build Coastguard Worker if (!file_access)
90*3ac0a46fSAndroid Build Coastguard Worker return false;
91*3ac0a46fSAndroid Build Coastguard Worker
92*3ac0a46fSAndroid Build Coastguard Worker if (pages) {
93*3ac0a46fSAndroid Build Coastguard Worker for (int index = 0; index < count; index++) {
94*3ac0a46fSAndroid Build Coastguard Worker CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
95*3ac0a46fSAndroid Build Coastguard Worker if (pPage)
96*3ac0a46fSAndroid Build Coastguard Worker pImgObj->GetImage()->ResetCache(pPage);
97*3ac0a46fSAndroid Build Coastguard Worker }
98*3ac0a46fSAndroid Build Coastguard Worker }
99*3ac0a46fSAndroid Build Coastguard Worker
100*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<IFX_SeekableReadStream> pFile = MakeSeekableReadStream(file_access);
101*3ac0a46fSAndroid Build Coastguard Worker if (inline_jpeg)
102*3ac0a46fSAndroid Build Coastguard Worker pImgObj->GetImage()->SetJpegImageInline(std::move(pFile));
103*3ac0a46fSAndroid Build Coastguard Worker else
104*3ac0a46fSAndroid Build Coastguard Worker pImgObj->GetImage()->SetJpegImage(std::move(pFile));
105*3ac0a46fSAndroid Build Coastguard Worker
106*3ac0a46fSAndroid Build Coastguard Worker pImgObj->SetDirty(true);
107*3ac0a46fSAndroid Build Coastguard Worker return true;
108*3ac0a46fSAndroid Build Coastguard Worker }
109*3ac0a46fSAndroid Build Coastguard Worker
110*3ac0a46fSAndroid Build Coastguard Worker } // namespace
111*3ac0a46fSAndroid Build Coastguard Worker
112*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
FPDFPageObj_NewImageObj(FPDF_DOCUMENT document)113*3ac0a46fSAndroid Build Coastguard Worker FPDFPageObj_NewImageObj(FPDF_DOCUMENT document) {
114*3ac0a46fSAndroid Build Coastguard Worker CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
115*3ac0a46fSAndroid Build Coastguard Worker if (!pDoc)
116*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
117*3ac0a46fSAndroid Build Coastguard Worker
118*3ac0a46fSAndroid Build Coastguard Worker auto pImageObj = std::make_unique<CPDF_ImageObject>();
119*3ac0a46fSAndroid Build Coastguard Worker pImageObj->SetImage(pdfium::MakeRetain<CPDF_Image>(pDoc));
120*3ac0a46fSAndroid Build Coastguard Worker
121*3ac0a46fSAndroid Build Coastguard Worker // Caller takes ownership.
122*3ac0a46fSAndroid Build Coastguard Worker return FPDFPageObjectFromCPDFPageObject(pImageObj.release());
123*3ac0a46fSAndroid Build Coastguard Worker }
124*3ac0a46fSAndroid Build Coastguard Worker
125*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_LoadJpegFile(FPDF_PAGE * pages,int count,FPDF_PAGEOBJECT image_object,FPDF_FILEACCESS * file_access)126*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_LoadJpegFile(FPDF_PAGE* pages,
127*3ac0a46fSAndroid Build Coastguard Worker int count,
128*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT image_object,
129*3ac0a46fSAndroid Build Coastguard Worker FPDF_FILEACCESS* file_access) {
130*3ac0a46fSAndroid Build Coastguard Worker return LoadJpegHelper(pages, count, image_object, file_access, false);
131*3ac0a46fSAndroid Build Coastguard Worker }
132*3ac0a46fSAndroid Build Coastguard Worker
133*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_LoadJpegFileInline(FPDF_PAGE * pages,int count,FPDF_PAGEOBJECT image_object,FPDF_FILEACCESS * file_access)134*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_LoadJpegFileInline(FPDF_PAGE* pages,
135*3ac0a46fSAndroid Build Coastguard Worker int count,
136*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT image_object,
137*3ac0a46fSAndroid Build Coastguard Worker FPDF_FILEACCESS* file_access) {
138*3ac0a46fSAndroid Build Coastguard Worker return LoadJpegHelper(pages, count, image_object, file_access, true);
139*3ac0a46fSAndroid Build Coastguard Worker }
140*3ac0a46fSAndroid Build Coastguard Worker
141*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object,double a,double b,double c,double d,double e,double f)142*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object,
143*3ac0a46fSAndroid Build Coastguard Worker double a,
144*3ac0a46fSAndroid Build Coastguard Worker double b,
145*3ac0a46fSAndroid Build Coastguard Worker double c,
146*3ac0a46fSAndroid Build Coastguard Worker double d,
147*3ac0a46fSAndroid Build Coastguard Worker double e,
148*3ac0a46fSAndroid Build Coastguard Worker double f) {
149*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
150*3ac0a46fSAndroid Build Coastguard Worker if (!pImgObj)
151*3ac0a46fSAndroid Build Coastguard Worker return false;
152*3ac0a46fSAndroid Build Coastguard Worker
153*3ac0a46fSAndroid Build Coastguard Worker pImgObj->SetImageMatrix(CFX_Matrix(
154*3ac0a46fSAndroid Build Coastguard Worker static_cast<float>(a), static_cast<float>(b), static_cast<float>(c),
155*3ac0a46fSAndroid Build Coastguard Worker static_cast<float>(d), static_cast<float>(e), static_cast<float>(f)));
156*3ac0a46fSAndroid Build Coastguard Worker pImgObj->SetDirty(true);
157*3ac0a46fSAndroid Build Coastguard Worker return true;
158*3ac0a46fSAndroid Build Coastguard Worker }
159*3ac0a46fSAndroid Build Coastguard Worker
160*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_SetBitmap(FPDF_PAGE * pages,int count,FPDF_PAGEOBJECT image_object,FPDF_BITMAP bitmap)161*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_SetBitmap(FPDF_PAGE* pages,
162*3ac0a46fSAndroid Build Coastguard Worker int count,
163*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT image_object,
164*3ac0a46fSAndroid Build Coastguard Worker FPDF_BITMAP bitmap) {
165*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
166*3ac0a46fSAndroid Build Coastguard Worker if (!pImgObj)
167*3ac0a46fSAndroid Build Coastguard Worker return false;
168*3ac0a46fSAndroid Build Coastguard Worker
169*3ac0a46fSAndroid Build Coastguard Worker if (!bitmap)
170*3ac0a46fSAndroid Build Coastguard Worker return false;
171*3ac0a46fSAndroid Build Coastguard Worker
172*3ac0a46fSAndroid Build Coastguard Worker if (pages) {
173*3ac0a46fSAndroid Build Coastguard Worker for (int index = 0; index < count; index++) {
174*3ac0a46fSAndroid Build Coastguard Worker CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
175*3ac0a46fSAndroid Build Coastguard Worker if (pPage)
176*3ac0a46fSAndroid Build Coastguard Worker pImgObj->GetImage()->ResetCache(pPage);
177*3ac0a46fSAndroid Build Coastguard Worker }
178*3ac0a46fSAndroid Build Coastguard Worker }
179*3ac0a46fSAndroid Build Coastguard Worker
180*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CFX_DIBitmap> holder(CFXDIBitmapFromFPDFBitmap(bitmap));
181*3ac0a46fSAndroid Build Coastguard Worker pImgObj->GetImage()->SetImage(holder);
182*3ac0a46fSAndroid Build Coastguard Worker pImgObj->CalcBoundingBox();
183*3ac0a46fSAndroid Build Coastguard Worker pImgObj->SetDirty(true);
184*3ac0a46fSAndroid Build Coastguard Worker return true;
185*3ac0a46fSAndroid Build Coastguard Worker }
186*3ac0a46fSAndroid Build Coastguard Worker
187*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
FPDFImageObj_GetBitmap(FPDF_PAGEOBJECT image_object)188*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_GetBitmap(FPDF_PAGEOBJECT image_object) {
189*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
190*3ac0a46fSAndroid Build Coastguard Worker if (!pImgObj)
191*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
192*3ac0a46fSAndroid Build Coastguard Worker
193*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
194*3ac0a46fSAndroid Build Coastguard Worker if (!pImg)
195*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
196*3ac0a46fSAndroid Build Coastguard Worker
197*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CFX_DIBBase> pSource = pImg->LoadDIBBase();
198*3ac0a46fSAndroid Build Coastguard Worker if (!pSource)
199*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
200*3ac0a46fSAndroid Build Coastguard Worker
201*3ac0a46fSAndroid Build Coastguard Worker // If the source image has a representation of 1 bit per pixel, then convert
202*3ac0a46fSAndroid Build Coastguard Worker // it to a grayscale bitmap having 1 byte per pixel, since bitmaps have no
203*3ac0a46fSAndroid Build Coastguard Worker // concept of bits. Otherwise, convert the source image to a bitmap directly,
204*3ac0a46fSAndroid Build Coastguard Worker // retaining its color representation.
205*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CFX_DIBitmap> pBitmap =
206*3ac0a46fSAndroid Build Coastguard Worker pSource->GetBPP() == 1 ? pSource->ConvertTo(FXDIB_Format::k8bppRgb)
207*3ac0a46fSAndroid Build Coastguard Worker : pSource->Realize();
208*3ac0a46fSAndroid Build Coastguard Worker
209*3ac0a46fSAndroid Build Coastguard Worker return FPDFBitmapFromCFXDIBitmap(pBitmap.Leak());
210*3ac0a46fSAndroid Build Coastguard Worker }
211*3ac0a46fSAndroid Build Coastguard Worker
212*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
FPDFImageObj_GetRenderedBitmap(FPDF_DOCUMENT document,FPDF_PAGE page,FPDF_PAGEOBJECT image_object)213*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_GetRenderedBitmap(FPDF_DOCUMENT document,
214*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page,
215*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGEOBJECT image_object) {
216*3ac0a46fSAndroid Build Coastguard Worker CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
217*3ac0a46fSAndroid Build Coastguard Worker if (!doc)
218*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
219*3ac0a46fSAndroid Build Coastguard Worker
220*3ac0a46fSAndroid Build Coastguard Worker CPDF_Page* optional_page = CPDFPageFromFPDFPage(page);
221*3ac0a46fSAndroid Build Coastguard Worker if (optional_page && optional_page->GetDocument() != doc)
222*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
223*3ac0a46fSAndroid Build Coastguard Worker
224*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* image = CPDFImageObjectFromFPDFPageObject(image_object);
225*3ac0a46fSAndroid Build Coastguard Worker if (!image)
226*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
227*3ac0a46fSAndroid Build Coastguard Worker
228*3ac0a46fSAndroid Build Coastguard Worker // Create |result_bitmap|.
229*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& image_matrix = image->matrix();
230*3ac0a46fSAndroid Build Coastguard Worker int output_width = image_matrix.a;
231*3ac0a46fSAndroid Build Coastguard Worker int output_height = image_matrix.d;
232*3ac0a46fSAndroid Build Coastguard Worker auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
233*3ac0a46fSAndroid Build Coastguard Worker if (!result_bitmap->Create(output_width, output_height, FXDIB_Format::kArgb))
234*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
235*3ac0a46fSAndroid Build Coastguard Worker
236*3ac0a46fSAndroid Build Coastguard Worker // Set up all the rendering code.
237*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Dictionary> page_resources =
238*3ac0a46fSAndroid Build Coastguard Worker optional_page ? optional_page->GetMutablePageResources() : nullptr;
239*3ac0a46fSAndroid Build Coastguard Worker CPDF_RenderContext context(doc, std::move(page_resources),
240*3ac0a46fSAndroid Build Coastguard Worker /*pPageCache=*/nullptr);
241*3ac0a46fSAndroid Build Coastguard Worker CFX_DefaultRenderDevice device;
242*3ac0a46fSAndroid Build Coastguard Worker device.Attach(result_bitmap);
243*3ac0a46fSAndroid Build Coastguard Worker CPDF_RenderStatus status(&context, &device);
244*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageRenderer renderer(&status);
245*3ac0a46fSAndroid Build Coastguard Worker
246*3ac0a46fSAndroid Build Coastguard Worker // Need to first flip the image, as expected by |renderer|.
247*3ac0a46fSAndroid Build Coastguard Worker CFX_Matrix render_matrix(1, 0, 0, -1, 0, output_height);
248*3ac0a46fSAndroid Build Coastguard Worker
249*3ac0a46fSAndroid Build Coastguard Worker // Then take |image_matrix|'s offset into account.
250*3ac0a46fSAndroid Build Coastguard Worker render_matrix.Translate(-image_matrix.e, image_matrix.f);
251*3ac0a46fSAndroid Build Coastguard Worker
252*3ac0a46fSAndroid Build Coastguard Worker // Do the actual rendering.
253*3ac0a46fSAndroid Build Coastguard Worker bool should_continue = renderer.Start(image, render_matrix,
254*3ac0a46fSAndroid Build Coastguard Worker /*bStdCS=*/false, BlendMode::kNormal);
255*3ac0a46fSAndroid Build Coastguard Worker while (should_continue)
256*3ac0a46fSAndroid Build Coastguard Worker should_continue = renderer.Continue(/*pPause=*/nullptr);
257*3ac0a46fSAndroid Build Coastguard Worker
258*3ac0a46fSAndroid Build Coastguard Worker if (!renderer.GetResult())
259*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
260*3ac0a46fSAndroid Build Coastguard Worker
261*3ac0a46fSAndroid Build Coastguard Worker #if defined(_SKIA_SUPPORT_)
262*3ac0a46fSAndroid Build Coastguard Worker if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
263*3ac0a46fSAndroid Build Coastguard Worker result_bitmap->UnPreMultiply();
264*3ac0a46fSAndroid Build Coastguard Worker #endif
265*3ac0a46fSAndroid Build Coastguard Worker
266*3ac0a46fSAndroid Build Coastguard Worker // Caller takes ownership.
267*3ac0a46fSAndroid Build Coastguard Worker return FPDFBitmapFromCFXDIBitmap(result_bitmap.Leak());
268*3ac0a46fSAndroid Build Coastguard Worker }
269*3ac0a46fSAndroid Build Coastguard Worker
270*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFImageObj_GetImageDataDecoded(FPDF_PAGEOBJECT image_object,void * buffer,unsigned long buflen)271*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_GetImageDataDecoded(FPDF_PAGEOBJECT image_object,
272*3ac0a46fSAndroid Build Coastguard Worker void* buffer,
273*3ac0a46fSAndroid Build Coastguard Worker unsigned long buflen) {
274*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
275*3ac0a46fSAndroid Build Coastguard Worker if (!pImgObj)
276*3ac0a46fSAndroid Build Coastguard Worker return 0;
277*3ac0a46fSAndroid Build Coastguard Worker
278*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
279*3ac0a46fSAndroid Build Coastguard Worker if (!pImg)
280*3ac0a46fSAndroid Build Coastguard Worker return 0;
281*3ac0a46fSAndroid Build Coastguard Worker
282*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Stream> pImgStream = pImg->GetStream();
283*3ac0a46fSAndroid Build Coastguard Worker if (!pImgStream)
284*3ac0a46fSAndroid Build Coastguard Worker return 0;
285*3ac0a46fSAndroid Build Coastguard Worker
286*3ac0a46fSAndroid Build Coastguard Worker return DecodeStreamMaybeCopyAndReturnLength(
287*3ac0a46fSAndroid Build Coastguard Worker std::move(pImgStream),
288*3ac0a46fSAndroid Build Coastguard Worker {static_cast<uint8_t*>(buffer), static_cast<size_t>(buflen)});
289*3ac0a46fSAndroid Build Coastguard Worker }
290*3ac0a46fSAndroid Build Coastguard Worker
291*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFImageObj_GetImageDataRaw(FPDF_PAGEOBJECT image_object,void * buffer,unsigned long buflen)292*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_GetImageDataRaw(FPDF_PAGEOBJECT image_object,
293*3ac0a46fSAndroid Build Coastguard Worker void* buffer,
294*3ac0a46fSAndroid Build Coastguard Worker unsigned long buflen) {
295*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
296*3ac0a46fSAndroid Build Coastguard Worker if (!pImgObj)
297*3ac0a46fSAndroid Build Coastguard Worker return 0;
298*3ac0a46fSAndroid Build Coastguard Worker
299*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
300*3ac0a46fSAndroid Build Coastguard Worker if (!pImg)
301*3ac0a46fSAndroid Build Coastguard Worker return 0;
302*3ac0a46fSAndroid Build Coastguard Worker
303*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Stream> pImgStream = pImg->GetStream();
304*3ac0a46fSAndroid Build Coastguard Worker if (!pImgStream)
305*3ac0a46fSAndroid Build Coastguard Worker return 0;
306*3ac0a46fSAndroid Build Coastguard Worker
307*3ac0a46fSAndroid Build Coastguard Worker return GetRawStreamMaybeCopyAndReturnLength(
308*3ac0a46fSAndroid Build Coastguard Worker std::move(pImgStream),
309*3ac0a46fSAndroid Build Coastguard Worker {static_cast<uint8_t*>(buffer), static_cast<size_t>(buflen)});
310*3ac0a46fSAndroid Build Coastguard Worker }
311*3ac0a46fSAndroid Build Coastguard Worker
312*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT int FPDF_CALLCONV
FPDFImageObj_GetImageFilterCount(FPDF_PAGEOBJECT image_object)313*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_GetImageFilterCount(FPDF_PAGEOBJECT image_object) {
314*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
315*3ac0a46fSAndroid Build Coastguard Worker if (!pImgObj)
316*3ac0a46fSAndroid Build Coastguard Worker return 0;
317*3ac0a46fSAndroid Build Coastguard Worker
318*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
319*3ac0a46fSAndroid Build Coastguard Worker if (!pImg)
320*3ac0a46fSAndroid Build Coastguard Worker return 0;
321*3ac0a46fSAndroid Build Coastguard Worker
322*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> pDict = pImg->GetDict();
323*3ac0a46fSAndroid Build Coastguard Worker if (!pDict)
324*3ac0a46fSAndroid Build Coastguard Worker return 0;
325*3ac0a46fSAndroid Build Coastguard Worker
326*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Object> pFilter = pDict->GetDirectObjectFor("Filter");
327*3ac0a46fSAndroid Build Coastguard Worker if (!pFilter)
328*3ac0a46fSAndroid Build Coastguard Worker return 0;
329*3ac0a46fSAndroid Build Coastguard Worker
330*3ac0a46fSAndroid Build Coastguard Worker if (pFilter->IsArray())
331*3ac0a46fSAndroid Build Coastguard Worker return fxcrt::CollectionSize<int>(*pFilter->AsArray());
332*3ac0a46fSAndroid Build Coastguard Worker
333*3ac0a46fSAndroid Build Coastguard Worker if (pFilter->IsName())
334*3ac0a46fSAndroid Build Coastguard Worker return 1;
335*3ac0a46fSAndroid Build Coastguard Worker
336*3ac0a46fSAndroid Build Coastguard Worker return 0;
337*3ac0a46fSAndroid Build Coastguard Worker }
338*3ac0a46fSAndroid Build Coastguard Worker
339*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFImageObj_GetImageFilter(FPDF_PAGEOBJECT image_object,int index,void * buffer,unsigned long buflen)340*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_GetImageFilter(FPDF_PAGEOBJECT image_object,
341*3ac0a46fSAndroid Build Coastguard Worker int index,
342*3ac0a46fSAndroid Build Coastguard Worker void* buffer,
343*3ac0a46fSAndroid Build Coastguard Worker unsigned long buflen) {
344*3ac0a46fSAndroid Build Coastguard Worker if (index < 0 || index >= FPDFImageObj_GetImageFilterCount(image_object))
345*3ac0a46fSAndroid Build Coastguard Worker return 0;
346*3ac0a46fSAndroid Build Coastguard Worker
347*3ac0a46fSAndroid Build Coastguard Worker CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
348*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Dictionary> pDict =
349*3ac0a46fSAndroid Build Coastguard Worker pObj->AsImage()->GetImage()->GetDict();
350*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<const CPDF_Object> pFilter = pDict->GetDirectObjectFor("Filter");
351*3ac0a46fSAndroid Build Coastguard Worker ByteString bsFilter = pFilter->IsName()
352*3ac0a46fSAndroid Build Coastguard Worker ? pFilter->AsName()->GetString()
353*3ac0a46fSAndroid Build Coastguard Worker : pFilter->AsArray()->GetByteStringAt(index);
354*3ac0a46fSAndroid Build Coastguard Worker
355*3ac0a46fSAndroid Build Coastguard Worker return NulTerminateMaybeCopyAndReturnLength(bsFilter, buffer, buflen);
356*3ac0a46fSAndroid Build Coastguard Worker }
357*3ac0a46fSAndroid Build Coastguard Worker
358*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_GetImageMetadata(FPDF_PAGEOBJECT image_object,FPDF_PAGE page,FPDF_IMAGEOBJ_METADATA * metadata)359*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_GetImageMetadata(FPDF_PAGEOBJECT image_object,
360*3ac0a46fSAndroid Build Coastguard Worker FPDF_PAGE page,
361*3ac0a46fSAndroid Build Coastguard Worker FPDF_IMAGEOBJ_METADATA* metadata) {
362*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
363*3ac0a46fSAndroid Build Coastguard Worker if (!pImgObj || !metadata)
364*3ac0a46fSAndroid Build Coastguard Worker return false;
365*3ac0a46fSAndroid Build Coastguard Worker
366*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
367*3ac0a46fSAndroid Build Coastguard Worker if (!pImg)
368*3ac0a46fSAndroid Build Coastguard Worker return false;
369*3ac0a46fSAndroid Build Coastguard Worker
370*3ac0a46fSAndroid Build Coastguard Worker metadata->marked_content_id =
371*3ac0a46fSAndroid Build Coastguard Worker pImgObj->GetContentMarks()->GetMarkedContentID();
372*3ac0a46fSAndroid Build Coastguard Worker
373*3ac0a46fSAndroid Build Coastguard Worker const int nPixelWidth = pImg->GetPixelWidth();
374*3ac0a46fSAndroid Build Coastguard Worker const int nPixelHeight = pImg->GetPixelHeight();
375*3ac0a46fSAndroid Build Coastguard Worker metadata->width = nPixelWidth;
376*3ac0a46fSAndroid Build Coastguard Worker metadata->height = nPixelHeight;
377*3ac0a46fSAndroid Build Coastguard Worker
378*3ac0a46fSAndroid Build Coastguard Worker const float nWidth = pImgObj->GetRect().Width();
379*3ac0a46fSAndroid Build Coastguard Worker const float nHeight = pImgObj->GetRect().Height();
380*3ac0a46fSAndroid Build Coastguard Worker constexpr int nPointsPerInch = 72;
381*3ac0a46fSAndroid Build Coastguard Worker if (nWidth != 0 && nHeight != 0) {
382*3ac0a46fSAndroid Build Coastguard Worker metadata->horizontal_dpi = nPixelWidth / nWidth * nPointsPerInch;
383*3ac0a46fSAndroid Build Coastguard Worker metadata->vertical_dpi = nPixelHeight / nHeight * nPointsPerInch;
384*3ac0a46fSAndroid Build Coastguard Worker }
385*3ac0a46fSAndroid Build Coastguard Worker
386*3ac0a46fSAndroid Build Coastguard Worker metadata->bits_per_pixel = 0;
387*3ac0a46fSAndroid Build Coastguard Worker metadata->colorspace = FPDF_COLORSPACE_UNKNOWN;
388*3ac0a46fSAndroid Build Coastguard Worker
389*3ac0a46fSAndroid Build Coastguard Worker CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
390*3ac0a46fSAndroid Build Coastguard Worker if (!pPage || !pPage->GetDocument() || !pImg->GetStream())
391*3ac0a46fSAndroid Build Coastguard Worker return true;
392*3ac0a46fSAndroid Build Coastguard Worker
393*3ac0a46fSAndroid Build Coastguard Worker // A cross-document image may have come from the embedder.
394*3ac0a46fSAndroid Build Coastguard Worker if (pPage->GetDocument() != pImg->GetDocument())
395*3ac0a46fSAndroid Build Coastguard Worker return false;
396*3ac0a46fSAndroid Build Coastguard Worker
397*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_DIB> pSource = pImg->CreateNewDIB();
398*3ac0a46fSAndroid Build Coastguard Worker CPDF_DIB::LoadState ret = pSource->StartLoadDIBBase(
399*3ac0a46fSAndroid Build Coastguard Worker false, nullptr, pPage->GetPageResources().Get(), false,
400*3ac0a46fSAndroid Build Coastguard Worker CPDF_ColorSpace::Family::kUnknown, false, {0, 0});
401*3ac0a46fSAndroid Build Coastguard Worker if (ret == CPDF_DIB::LoadState::kFail)
402*3ac0a46fSAndroid Build Coastguard Worker return true;
403*3ac0a46fSAndroid Build Coastguard Worker
404*3ac0a46fSAndroid Build Coastguard Worker metadata->bits_per_pixel = pSource->GetBPP();
405*3ac0a46fSAndroid Build Coastguard Worker if (pSource->GetColorSpace()) {
406*3ac0a46fSAndroid Build Coastguard Worker metadata->colorspace =
407*3ac0a46fSAndroid Build Coastguard Worker static_cast<int>(pSource->GetColorSpace()->GetFamily());
408*3ac0a46fSAndroid Build Coastguard Worker }
409*3ac0a46fSAndroid Build Coastguard Worker return true;
410*3ac0a46fSAndroid Build Coastguard Worker }
411*3ac0a46fSAndroid Build Coastguard Worker
412*3ac0a46fSAndroid Build Coastguard Worker FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFImageObj_GetImagePixelSize(FPDF_PAGEOBJECT image_object,unsigned int * width,unsigned int * height)413*3ac0a46fSAndroid Build Coastguard Worker FPDFImageObj_GetImagePixelSize(FPDF_PAGEOBJECT image_object,
414*3ac0a46fSAndroid Build Coastguard Worker unsigned int* width,
415*3ac0a46fSAndroid Build Coastguard Worker unsigned int* height) {
416*3ac0a46fSAndroid Build Coastguard Worker CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
417*3ac0a46fSAndroid Build Coastguard Worker if (!pImgObj || !width || !height) {
418*3ac0a46fSAndroid Build Coastguard Worker return false;
419*3ac0a46fSAndroid Build Coastguard Worker }
420*3ac0a46fSAndroid Build Coastguard Worker
421*3ac0a46fSAndroid Build Coastguard Worker RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
422*3ac0a46fSAndroid Build Coastguard Worker if (!pImg) {
423*3ac0a46fSAndroid Build Coastguard Worker return false;
424*3ac0a46fSAndroid Build Coastguard Worker }
425*3ac0a46fSAndroid Build Coastguard Worker
426*3ac0a46fSAndroid Build Coastguard Worker *width = pImg->GetPixelWidth();
427*3ac0a46fSAndroid Build Coastguard Worker *height = pImg->GetPixelHeight();
428*3ac0a46fSAndroid Build Coastguard Worker return true;
429*3ac0a46fSAndroid Build Coastguard Worker }
430