blob: 479c6eb45acd57cff4b961444b56e4bde9acd706 [file] [log] [blame]
K. Moon832a6942022-10-31 20:11:31 +00001// Copyright 2014 The PDFium Authors
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 Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Lei Zhangb4e7f302015-11-06 15:52:32 -08007#include "public/fpdf_edit.h"
8
Tom Sepez5af95432020-05-15 22:55:16 +00009#include <memory>
Lei Zhang02d42b62018-10-24 17:56:26 +000010#include <utility>
11
Lei Zhang87c415a2020-01-14 19:54:36 +000012#include "core/fpdfapi/page/cpdf_dib.h"
dsinclair41872fa2016-10-04 11:29:35 -070013#include "core/fpdfapi/page/cpdf_image.h"
14#include "core/fpdfapi/page/cpdf_imageobject.h"
Jane Liuca898292017-08-16 11:25:35 -040015#include "core/fpdfapi/page/cpdf_page.h"
dsinclair41872fa2016-10-04 11:29:35 -070016#include "core/fpdfapi/page/cpdf_pageobject.h"
Jane Liube63ab92017-08-09 14:09:34 -040017#include "core/fpdfapi/parser/cpdf_array.h"
Lei Zhang81535612018-10-09 21:15:17 +000018#include "core/fpdfapi/parser/cpdf_dictionary.h"
Jane Liube63ab92017-08-09 14:09:34 -040019#include "core/fpdfapi/parser/cpdf_name.h"
Tom Sepezbb040742022-09-28 16:33:34 +000020#include "core/fpdfapi/parser/cpdf_stream.h"
Artem Strygineababa12018-06-06 12:31:18 +000021#include "core/fpdfapi/parser/cpdf_stream_acc.h"
Lei Zhang0ac7b4e2020-07-18 00:35:53 +000022#include "core/fpdfapi/render/cpdf_imagerenderer.h"
23#include "core/fpdfapi/render/cpdf_rendercontext.h"
24#include "core/fpdfapi/render/cpdf_renderstatus.h"
Tom Sepez946c0d32024-05-09 20:47:23 +000025#include "core/fxcrt/compiler_specific.h"
Lei Zhang91085882024-02-22 00:49:57 +000026#include "core/fxcrt/notreached.h"
Tom Sepez5ea5fa92022-03-08 00:15:23 +000027#include "core/fxcrt/stl_util.h"
Lei Zhang0ac7b4e2020-07-18 00:35:53 +000028#include "core/fxge/cfx_defaultrenderdevice.h"
K. Moon52814962023-06-05 22:08:59 +000029#include "core/fxge/dib/cfx_dibitmap.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000030#include "fpdfsdk/cpdfsdk_customaccess.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000031#include "fpdfsdk/cpdfsdk_helpers.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070032
Lei Zhangcbd89572017-03-15 17:35:47 -070033namespace {
thestigc54bb432016-07-29 19:34:20 -070034
Jane Liuca898292017-08-16 11:25:35 -040035// These checks ensure the consistency of colorspace values across core/ and
36// public/.
Tom Sepezd30786c2021-05-18 23:05:54 +000037static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceGray) ==
38 FPDF_COLORSPACE_DEVICEGRAY,
39 "kDeviceGray value mismatch");
40static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceRGB) ==
41 FPDF_COLORSPACE_DEVICERGB,
42 "kDeviceRGB value mismatch");
43static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceCMYK) ==
44 FPDF_COLORSPACE_DEVICECMYK,
45 "kDeviceCMYK value mismatch");
46static_assert(static_cast<int>(CPDF_ColorSpace::Family::kCalGray) ==
47 FPDF_COLORSPACE_CALGRAY,
48 "kCalGray value mismatch");
49static_assert(static_cast<int>(CPDF_ColorSpace::Family::kCalRGB) ==
50 FPDF_COLORSPACE_CALRGB,
51 "kCalRGB value mismatch");
52static_assert(static_cast<int>(CPDF_ColorSpace::Family::kLab) ==
53 FPDF_COLORSPACE_LAB,
54 "kLab value mismatch");
55static_assert(static_cast<int>(CPDF_ColorSpace::Family::kICCBased) ==
56 FPDF_COLORSPACE_ICCBASED,
57 "kICCBased value mismatch");
58static_assert(static_cast<int>(CPDF_ColorSpace::Family::kSeparation) ==
59 FPDF_COLORSPACE_SEPARATION,
60 "kSeparation value mismatch");
61static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceN) ==
62 FPDF_COLORSPACE_DEVICEN,
63 "kDeviceN value mismatch");
64static_assert(static_cast<int>(CPDF_ColorSpace::Family::kIndexed) ==
65 FPDF_COLORSPACE_INDEXED,
66 "kIndexed value mismatch");
67static_assert(static_cast<int>(CPDF_ColorSpace::Family::kPattern) ==
68 FPDF_COLORSPACE_PATTERN,
69 "kPattern value mismatch");
Jane Liuca898292017-08-16 11:25:35 -040070
Dan Sinclair7aba4722018-03-28 17:04:16 +000071RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
72 FPDF_FILEACCESS* pFileAccess) {
73 return pdfium::MakeRetain<CPDFSDK_CustomAccess>(pFileAccess);
74}
75
Lei Zhang22375412018-10-24 17:26:50 +000076CPDF_ImageObject* CPDFImageObjectFromFPDFPageObject(
77 FPDF_PAGEOBJECT image_object) {
78 CPDF_PageObject* pPageObject = CPDFPageObjectFromFPDFPageObject(image_object);
79 return pPageObject ? pPageObject->AsImage() : nullptr;
80}
81
Lei Zhangcbd89572017-03-15 17:35:47 -070082bool LoadJpegHelper(FPDF_PAGE* pages,
Lei Zhangf0542892019-01-17 18:46:27 +000083 int count,
Lei Zhangcbd89572017-03-15 17:35:47 -070084 FPDF_PAGEOBJECT image_object,
Lei Zhangf0542892019-01-17 18:46:27 +000085 FPDF_FILEACCESS* file_access,
86 bool inline_jpeg) {
Lei Zhang22375412018-10-24 17:26:50 +000087 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
88 if (!pImgObj)
tsepez4cf55152016-11-02 14:37:54 -070089 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070090
Lei Zhangf0542892019-01-17 18:46:27 +000091 if (!file_access)
Tom Sepez525147a2018-05-03 17:19:53 +000092 return false;
Andrew Weintraub21f88ff2017-05-10 13:19:52 -040093
94 if (pages) {
Lei Zhangf0542892019-01-17 18:46:27 +000095 for (int index = 0; index < count; index++) {
Tom Sepez26041602024-05-16 02:49:09 +000096 CPDF_Page* pPage = CPDFPageFromFPDFPage(UNSAFE_TODO(pages[index]));
Tom Sepez946c0d32024-05-09 20:47:23 +000097 if (pPage) {
Lei Zhang66601c42018-10-02 18:58:16 +000098 pImgObj->GetImage()->ResetCache(pPage);
Tom Sepez946c0d32024-05-09 20:47:23 +000099 }
Andrew Weintraub21f88ff2017-05-10 13:19:52 -0400100 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700101 }
rbpotterf085db32016-12-14 11:44:31 -0800102
Lei Zhangf0542892019-01-17 18:46:27 +0000103 RetainPtr<IFX_SeekableReadStream> pFile = MakeSeekableReadStream(file_access);
104 if (inline_jpeg)
Tom Sepez965b9362022-08-08 17:28:04 +0000105 pImgObj->GetImage()->SetJpegImageInline(std::move(pFile));
rbpotterf085db32016-12-14 11:44:31 -0800106 else
Tom Sepez965b9362022-08-08 17:28:04 +0000107 pImgObj->GetImage()->SetJpegImage(std::move(pFile));
108
wileyryae858aa42017-05-31 14:49:05 -0500109 pImgObj->SetDirty(true);
tsepez4cf55152016-11-02 14:37:54 -0700110 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700111}
112
Lei Zhangcbd89572017-03-15 17:35:47 -0700113} // namespace
114
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400115FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
Lei Zhangcbd89572017-03-15 17:35:47 -0700116FPDFPageObj_NewImageObj(FPDF_DOCUMENT document) {
117 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
118 if (!pDoc)
119 return nullptr;
120
Tom Sepez5af95432020-05-15 22:55:16 +0000121 auto pImageObj = std::make_unique<CPDF_ImageObject>();
Tom Sepez7d4f6a82017-03-31 17:10:34 -0700122 pImageObj->SetImage(pdfium::MakeRetain<CPDF_Image>(pDoc));
Tom Sepez525147a2018-05-03 17:19:53 +0000123
124 // Caller takes ownership.
125 return FPDFPageObjectFromCPDFPageObject(pImageObj.release());
Lei Zhangcbd89572017-03-15 17:35:47 -0700126}
127
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400128FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
rbpotterf085db32016-12-14 11:44:31 -0800129FPDFImageObj_LoadJpegFile(FPDF_PAGE* pages,
Lei Zhangf0542892019-01-17 18:46:27 +0000130 int count,
rbpotterf085db32016-12-14 11:44:31 -0800131 FPDF_PAGEOBJECT image_object,
Lei Zhangf0542892019-01-17 18:46:27 +0000132 FPDF_FILEACCESS* file_access) {
133 return LoadJpegHelper(pages, count, image_object, file_access, false);
rbpotterf085db32016-12-14 11:44:31 -0800134}
135
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400136FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
rbpotterf085db32016-12-14 11:44:31 -0800137FPDFImageObj_LoadJpegFileInline(FPDF_PAGE* pages,
Lei Zhangf0542892019-01-17 18:46:27 +0000138 int count,
rbpotterf085db32016-12-14 11:44:31 -0800139 FPDF_PAGEOBJECT image_object,
Lei Zhangf0542892019-01-17 18:46:27 +0000140 FPDF_FILEACCESS* file_access) {
141 return LoadJpegHelper(pages, count, image_object, file_access, true);
rbpotterf085db32016-12-14 11:44:31 -0800142}
143
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400144FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
145FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object,
146 double a,
147 double b,
148 double c,
149 double d,
150 double e,
151 double f) {
Lei Zhang22375412018-10-24 17:26:50 +0000152 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
Tom Sepez525147a2018-05-03 17:19:53 +0000153 if (!pImgObj)
154 return false;
155
Lei Zhang7dd720e2021-06-25 20:15:56 +0000156 pImgObj->SetImageMatrix(CFX_Matrix(
157 static_cast<float>(a), static_cast<float>(b), static_cast<float>(c),
158 static_cast<float>(d), static_cast<float>(e), static_cast<float>(f)));
wileyryae858aa42017-05-31 14:49:05 -0500159 pImgObj->SetDirty(true);
tsepez4cf55152016-11-02 14:37:54 -0700160 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700161}
162
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400163FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
164FPDFImageObj_SetBitmap(FPDF_PAGE* pages,
Lei Zhangf0542892019-01-17 18:46:27 +0000165 int count,
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400166 FPDF_PAGEOBJECT image_object,
167 FPDF_BITMAP bitmap) {
Lei Zhang22375412018-10-24 17:26:50 +0000168 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
Tom Sepez525147a2018-05-03 17:19:53 +0000169 if (!pImgObj)
170 return false;
171
Lei Zhang22375412018-10-24 17:26:50 +0000172 if (!bitmap)
173 return false;
174
Lei Zhangd19dc582019-01-17 18:47:38 +0000175 if (pages) {
176 for (int index = 0; index < count; index++) {
Tom Sepez26041602024-05-16 02:49:09 +0000177 CPDF_Page* pPage = CPDFPageFromFPDFPage(UNSAFE_TODO(pages[index]));
Tom Sepez946c0d32024-05-09 20:47:23 +0000178 if (pPage) {
Lei Zhangd19dc582019-01-17 18:47:38 +0000179 pImgObj->GetImage()->ResetCache(pPage);
Tom Sepez946c0d32024-05-09 20:47:23 +0000180 }
Lei Zhangd19dc582019-01-17 18:47:38 +0000181 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700182 }
Lei Zhangd19dc582019-01-17 18:47:38 +0000183
Tom Sepez525147a2018-05-03 17:19:53 +0000184 RetainPtr<CFX_DIBitmap> holder(CFXDIBitmapFromFPDFBitmap(bitmap));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700185 pImgObj->GetImage()->SetImage(holder);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700186 pImgObj->CalcBoundingBox();
wileyryae858aa42017-05-31 14:49:05 -0500187 pImgObj->SetDirty(true);
tsepez4cf55152016-11-02 14:37:54 -0700188 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700189}
Jane Liu28fb7ba2017-08-02 21:45:57 -0400190
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400191FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
Jane Liu28fb7ba2017-08-02 21:45:57 -0400192FPDFImageObj_GetBitmap(FPDF_PAGEOBJECT image_object) {
Lei Zhang22375412018-10-24 17:26:50 +0000193 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
194 if (!pImgObj)
Jane Liu28fb7ba2017-08-02 21:45:57 -0400195 return nullptr;
196
Lei Zhang22375412018-10-24 17:26:50 +0000197 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liu28fb7ba2017-08-02 21:45:57 -0400198 if (!pImg)
199 return nullptr;
200
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000201 RetainPtr<CFX_DIBBase> pSource = pImg->LoadDIBBase();
Jane Liu28fb7ba2017-08-02 21:45:57 -0400202 if (!pSource)
203 return nullptr;
204
Lei Zhang1e1e1732023-09-14 03:33:49 +0000205 // If the source image has a representation of 1 bit per pixel, or if the
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000206 // source image has a color palette, convert it to a representation that does
207 // not have a color palette, as there is no public API to access the palette.
Lei Zhang1e1e1732023-09-14 03:33:49 +0000208 //
209 // Otherwise, convert the source image to a bitmap directly,
Jane Liu28fb7ba2017-08-02 21:45:57 -0400210 // retaining its color representation.
Lei Zhang1e1e1732023-09-14 03:33:49 +0000211 //
212 // Only return FPDF_BITMAPs in formats that FPDFBitmap_CreateEx() would
213 // return.
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000214 enum class ConversionOp {
215 kRealize,
216 kConvertTo8bppRgb,
217 kConvertToRgb,
218 };
219
220 ConversionOp op;
Lei Zhang1e1e1732023-09-14 03:33:49 +0000221 switch (pSource->GetFormat()) {
222 case FXDIB_Format::k1bppMask:
Lei Zhang1e1e1732023-09-14 03:33:49 +0000223 case FXDIB_Format::k8bppMask:
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000224 // Masks do not have palettes, so they can be safely converted to
225 // `FXDIB_Format::k8bppRgb`.
226 CHECK(!pSource->HasPalette());
227 op = ConversionOp::kConvertTo8bppRgb;
228 break;
229 case FXDIB_Format::k1bppRgb:
230 // If there is a palette, then convert to `FXDIB_Format::kRgb` to avoid
231 // creating a bitmap with a palette.
232 op = pSource->HasPalette() ? ConversionOp::kConvertToRgb
233 : ConversionOp::kConvertTo8bppRgb;
234 break;
Lei Zhang1e1e1732023-09-14 03:33:49 +0000235 case FXDIB_Format::k8bppRgb:
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000236 // If there is a palette, then convert to `FXDIB_Format::kRgb` to avoid
237 // creating a bitmap with a palette.
238 op = pSource->HasPalette() ? ConversionOp::kConvertToRgb
239 : ConversionOp::kRealize;
Lei Zhang1e1e1732023-09-14 03:33:49 +0000240 break;
241
242 case FXDIB_Format::kArgb:
243 case FXDIB_Format::kRgb:
244 case FXDIB_Format::kRgb32:
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000245 CHECK(!pSource->HasPalette());
246 op = ConversionOp::kRealize;
Lei Zhang1e1e1732023-09-14 03:33:49 +0000247 break;
248
249 case FXDIB_Format::kInvalid: {
250 NOTREACHED_NORETURN();
251 }
252 }
Jane Liu28fb7ba2017-08-02 21:45:57 -0400253
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000254 RetainPtr<CFX_DIBitmap> pBitmap;
255 switch (op) {
256 case ConversionOp::kRealize:
257 pBitmap = pSource->Realize();
258 break;
259 case ConversionOp::kConvertTo8bppRgb:
260 pBitmap = pSource->ConvertTo(FXDIB_Format::k8bppRgb);
261 break;
262 case ConversionOp::kConvertToRgb:
263 pBitmap = pSource->ConvertTo(FXDIB_Format::kRgb);
264 break;
265 }
266 if (pBitmap) {
267 CHECK(!pBitmap->HasPalette());
268 }
269
Tom Sepez525147a2018-05-03 17:19:53 +0000270 return FPDFBitmapFromCFXDIBitmap(pBitmap.Leak());
Jane Liu28fb7ba2017-08-02 21:45:57 -0400271}
Jane Liu548334e2017-08-03 16:33:40 -0400272
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000273FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
274FPDFImageObj_GetRenderedBitmap(FPDF_DOCUMENT document,
275 FPDF_PAGE page,
276 FPDF_PAGEOBJECT image_object) {
277 CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
278 if (!doc)
279 return nullptr;
280
281 CPDF_Page* optional_page = CPDFPageFromFPDFPage(page);
282 if (optional_page && optional_page->GetDocument() != doc)
283 return nullptr;
284
285 CPDF_ImageObject* image = CPDFImageObjectFromFPDFPageObject(image_object);
286 if (!image)
287 return nullptr;
288
289 // Create |result_bitmap|.
290 const CFX_Matrix& image_matrix = image->matrix();
291 int output_width = image_matrix.a;
292 int output_height = image_matrix.d;
293 auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Tom Sepez26813ad2020-10-20 17:37:43 +0000294 if (!result_bitmap->Create(output_width, output_height, FXDIB_Format::kArgb))
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000295 return nullptr;
296
297 // Set up all the rendering code.
Tom Sepeza22da902022-06-30 18:08:32 +0000298 RetainPtr<CPDF_Dictionary> page_resources =
299 optional_page ? optional_page->GetMutablePageResources() : nullptr;
Tom Sepeze282b0f2022-09-30 19:37:29 +0000300 CPDF_RenderContext context(doc, std::move(page_resources),
301 /*pPageCache=*/nullptr);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000302 CFX_DefaultRenderDevice device;
Lei Zhange381fe92022-07-08 21:53:54 +0000303 device.Attach(result_bitmap);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000304 CPDF_RenderStatus status(&context, &device);
Tom Sepezbf57f852022-07-26 18:33:34 +0000305 CPDF_ImageRenderer renderer(&status);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000306
307 // Need to first flip the image, as expected by |renderer|.
308 CFX_Matrix render_matrix(1, 0, 0, -1, 0, output_height);
309
310 // Then take |image_matrix|'s offset into account.
311 render_matrix.Translate(-image_matrix.e, image_matrix.f);
312
313 // Do the actual rendering.
Tom Sepezbf57f852022-07-26 18:33:34 +0000314 bool should_continue = renderer.Start(image, render_matrix,
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000315 /*bStdCS=*/false, BlendMode::kNormal);
316 while (should_continue)
317 should_continue = renderer.Continue(/*pPause=*/nullptr);
318
319 if (!renderer.GetResult())
320 return nullptr;
321
Lei Zhangb26a1102023-12-16 00:04:05 +0000322#if defined(PDF_USE_SKIA)
Lei Zhang334a9ca2023-10-24 17:47:10 +0000323 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
Alan Screene44f1672022-09-15 20:09:43 +0000324 result_bitmap->UnPreMultiply();
Lei Zhang334a9ca2023-10-24 17:47:10 +0000325 }
Hui Yingst2a9c98c2022-08-26 20:27:23 +0000326#endif
327
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000328 // Caller takes ownership.
329 return FPDFBitmapFromCFXDIBitmap(result_bitmap.Leak());
330}
331
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400332FPDF_EXPORT unsigned long FPDF_CALLCONV
Jane Liu548334e2017-08-03 16:33:40 -0400333FPDFImageObj_GetImageDataDecoded(FPDF_PAGEOBJECT image_object,
334 void* buffer,
335 unsigned long buflen) {
Lei Zhang22375412018-10-24 17:26:50 +0000336 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
337 if (!pImgObj)
Jane Liu548334e2017-08-03 16:33:40 -0400338 return 0;
339
Lei Zhang22375412018-10-24 17:26:50 +0000340 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liu548334e2017-08-03 16:33:40 -0400341 if (!pImg)
342 return 0;
343
Tom Sepezbb040742022-09-28 16:33:34 +0000344 RetainPtr<const CPDF_Stream> pImgStream = pImg->GetStream();
Jane Liu548334e2017-08-03 16:33:40 -0400345 if (!pImgStream)
346 return 0;
347
Tom Sepez3b679fe2024-04-09 18:49:32 +0000348 // SAFETY: caller ensures `buffer` points to at least `buflen` bytes.
Tom Sepez06943a92022-11-10 20:29:34 +0000349 return DecodeStreamMaybeCopyAndReturnLength(
350 std::move(pImgStream),
Tom Sepez3b679fe2024-04-09 18:49:32 +0000351 UNSAFE_BUFFERS(pdfium::make_span(static_cast<uint8_t*>(buffer),
352 static_cast<size_t>(buflen))));
Jane Liu548334e2017-08-03 16:33:40 -0400353}
354
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400355FPDF_EXPORT unsigned long FPDF_CALLCONV
Jane Liu548334e2017-08-03 16:33:40 -0400356FPDFImageObj_GetImageDataRaw(FPDF_PAGEOBJECT image_object,
357 void* buffer,
358 unsigned long buflen) {
Lei Zhang22375412018-10-24 17:26:50 +0000359 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
360 if (!pImgObj)
Jane Liu548334e2017-08-03 16:33:40 -0400361 return 0;
362
Lei Zhang22375412018-10-24 17:26:50 +0000363 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liu548334e2017-08-03 16:33:40 -0400364 if (!pImg)
365 return 0;
366
Tom Sepezbb040742022-09-28 16:33:34 +0000367 RetainPtr<const CPDF_Stream> pImgStream = pImg->GetStream();
Jane Liu548334e2017-08-03 16:33:40 -0400368 if (!pImgStream)
369 return 0;
370
Tom Sepez3b679fe2024-04-09 18:49:32 +0000371 // SAFETY: caller ensures `buffer` points to at least `buflen` bytes.
Tom Sepez06943a92022-11-10 20:29:34 +0000372 return GetRawStreamMaybeCopyAndReturnLength(
373 std::move(pImgStream),
Tom Sepez3b679fe2024-04-09 18:49:32 +0000374 UNSAFE_BUFFERS(pdfium::make_span(static_cast<uint8_t*>(buffer),
375 static_cast<size_t>(buflen))));
Jane Liu548334e2017-08-03 16:33:40 -0400376}
Jane Liube63ab92017-08-09 14:09:34 -0400377
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400378FPDF_EXPORT int FPDF_CALLCONV
Jane Liube63ab92017-08-09 14:09:34 -0400379FPDFImageObj_GetImageFilterCount(FPDF_PAGEOBJECT image_object) {
Lei Zhang22375412018-10-24 17:26:50 +0000380 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
381 if (!pImgObj)
Jane Liube63ab92017-08-09 14:09:34 -0400382 return 0;
383
Lei Zhang22375412018-10-24 17:26:50 +0000384 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liube63ab92017-08-09 14:09:34 -0400385 if (!pImg)
386 return 0;
387
Tom Sepez8a185fa2022-09-26 18:33:13 +0000388 RetainPtr<const CPDF_Dictionary> pDict = pImg->GetDict();
Tom Sepeze0dcb6b2022-09-08 00:29:53 +0000389 if (!pDict)
390 return 0;
391
392 RetainPtr<const CPDF_Object> pFilter = pDict->GetDirectObjectFor("Filter");
Jane Liube63ab92017-08-09 14:09:34 -0400393 if (!pFilter)
394 return 0;
395
396 if (pFilter->IsArray())
Tom Sepez5ea5fa92022-03-08 00:15:23 +0000397 return fxcrt::CollectionSize<int>(*pFilter->AsArray());
398
Jane Liube63ab92017-08-09 14:09:34 -0400399 if (pFilter->IsName())
400 return 1;
401
402 return 0;
403}
404
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400405FPDF_EXPORT unsigned long FPDF_CALLCONV
Jane Liube63ab92017-08-09 14:09:34 -0400406FPDFImageObj_GetImageFilter(FPDF_PAGEOBJECT image_object,
407 int index,
408 void* buffer,
409 unsigned long buflen) {
410 if (index < 0 || index >= FPDFImageObj_GetImageFilterCount(image_object))
411 return 0;
412
413 CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
Tom Sepez8a185fa2022-09-26 18:33:13 +0000414 RetainPtr<const CPDF_Dictionary> pDict =
415 pObj->AsImage()->GetImage()->GetDict();
Tom Sepeze0dcb6b2022-09-08 00:29:53 +0000416 RetainPtr<const CPDF_Object> pFilter = pDict->GetDirectObjectFor("Filter");
Tom Sepez773310d2022-06-24 22:13:38 +0000417 ByteString bsFilter = pFilter->IsName()
418 ? pFilter->AsName()->GetString()
Tom Sepez56902472022-09-14 21:37:14 +0000419 : pFilter->AsArray()->GetByteStringAt(index);
Jane Liube63ab92017-08-09 14:09:34 -0400420
Tom Sepez946c0d32024-05-09 20:47:23 +0000421 // SAFETY: required from caller.
Tom Sepez6967ba92024-05-10 00:40:04 +0000422 return NulTerminateMaybeCopyAndReturnLength(
423 bsFilter, UNSAFE_BUFFERS(SpanFromFPDFApiArgs(buffer, buflen)));
Jane Liube63ab92017-08-09 14:09:34 -0400424}
Jane Liuca898292017-08-16 11:25:35 -0400425
426FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
427FPDFImageObj_GetImageMetadata(FPDF_PAGEOBJECT image_object,
428 FPDF_PAGE page,
429 FPDF_IMAGEOBJ_METADATA* metadata) {
Lei Zhang22375412018-10-24 17:26:50 +0000430 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
431 if (!pImgObj || !metadata)
Jane Liuca898292017-08-16 11:25:35 -0400432 return false;
433
Lei Zhang22375412018-10-24 17:26:50 +0000434 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liuca898292017-08-16 11:25:35 -0400435 if (!pImg)
436 return false;
437
Tom Sepez6eb915b2021-04-30 00:11:34 +0000438 metadata->marked_content_id =
439 pImgObj->GetContentMarks()->GetMarkedContentID();
Julian Lungerecd063e2017-12-27 10:18:50 -0500440
Jane Liuca898292017-08-16 11:25:35 -0400441 const int nPixelWidth = pImg->GetPixelWidth();
442 const int nPixelHeight = pImg->GetPixelHeight();
443 metadata->width = nPixelWidth;
444 metadata->height = nPixelHeight;
445
Lei Zhang22375412018-10-24 17:26:50 +0000446 const float nWidth = pImgObj->GetRect().Width();
447 const float nHeight = pImgObj->GetRect().Height();
Jane Liuca898292017-08-16 11:25:35 -0400448 constexpr int nPointsPerInch = 72;
449 if (nWidth != 0 && nHeight != 0) {
450 metadata->horizontal_dpi = nPixelWidth / nWidth * nPointsPerInch;
451 metadata->vertical_dpi = nPixelHeight / nHeight * nPointsPerInch;
452 }
453
454 metadata->bits_per_pixel = 0;
455 metadata->colorspace = FPDF_COLORSPACE_UNKNOWN;
456
457 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Lei Zhang8f637632018-05-07 23:36:26 +0000458 if (!pPage || !pPage->GetDocument() || !pImg->GetStream())
Jane Liuca898292017-08-16 11:25:35 -0400459 return true;
460
Tom Sepez6bc9ee52022-08-11 18:13:09 +0000461 // A cross-document image may have come from the embedder.
462 if (pPage->GetDocument() != pImg->GetDocument())
463 return false;
464
465 RetainPtr<CPDF_DIB> pSource = pImg->CreateNewDIB();
Tom Sepezd7fa6a42022-04-06 20:50:00 +0000466 CPDF_DIB::LoadState ret = pSource->StartLoadDIBBase(
Tom Sepez4ede0792022-10-07 20:25:36 +0000467 false, nullptr, pPage->GetPageResources().Get(), false,
fineaskotnikov231e7e12022-10-28 20:23:20 +0000468 CPDF_ColorSpace::Family::kUnknown, false, {0, 0});
Lei Zhang87c415a2020-01-14 19:54:36 +0000469 if (ret == CPDF_DIB::LoadState::kFail)
Jane Liuca898292017-08-16 11:25:35 -0400470 return true;
Jane Liuca898292017-08-16 11:25:35 -0400471
472 metadata->bits_per_pixel = pSource->GetBPP();
Tom Sepezd30786c2021-05-18 23:05:54 +0000473 if (pSource->GetColorSpace()) {
474 metadata->colorspace =
475 static_cast<int>(pSource->GetColorSpace()->GetFamily());
476 }
Jane Liuca898292017-08-16 11:25:35 -0400477 return true;
478}
fineaskotnikov379bfc92023-04-20 20:20:24 +0000479
480FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
481FPDFImageObj_GetImagePixelSize(FPDF_PAGEOBJECT image_object,
482 unsigned int* width,
483 unsigned int* height) {
484 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
485 if (!pImgObj || !width || !height) {
486 return false;
487 }
488
489 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
490 if (!pImg) {
491 return false;
492 }
493
494 *width = pImg->GetPixelWidth();
495 *height = pImg->GetPixelHeight();
496 return true;
497}