blob: f8809a4c3f531cb2c24cf6b2134fc5623930f30b [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 Sepez5ea5fa92022-03-08 00:15:23 +000025#include "core/fxcrt/stl_util.h"
Lei Zhang0ac7b4e2020-07-18 00:35:53 +000026#include "core/fxge/cfx_defaultrenderdevice.h"
K. Moon52814962023-06-05 22:08:59 +000027#include "core/fxge/dib/cfx_dibitmap.h"
Dan Sinclair7aba4722018-03-28 17:04:16 +000028#include "fpdfsdk/cpdfsdk_customaccess.h"
Dan Sinclair00d47a62018-03-28 18:39:04 +000029#include "fpdfsdk/cpdfsdk_helpers.h"
Lei Zhang1e1e1732023-09-14 03:33:49 +000030#include "third_party/base/notreached.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070031
Lei Zhangcbd89572017-03-15 17:35:47 -070032namespace {
thestigc54bb432016-07-29 19:34:20 -070033
Jane Liuca898292017-08-16 11:25:35 -040034// These checks ensure the consistency of colorspace values across core/ and
35// public/.
Tom Sepezd30786c2021-05-18 23:05:54 +000036static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceGray) ==
37 FPDF_COLORSPACE_DEVICEGRAY,
38 "kDeviceGray value mismatch");
39static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceRGB) ==
40 FPDF_COLORSPACE_DEVICERGB,
41 "kDeviceRGB value mismatch");
42static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceCMYK) ==
43 FPDF_COLORSPACE_DEVICECMYK,
44 "kDeviceCMYK value mismatch");
45static_assert(static_cast<int>(CPDF_ColorSpace::Family::kCalGray) ==
46 FPDF_COLORSPACE_CALGRAY,
47 "kCalGray value mismatch");
48static_assert(static_cast<int>(CPDF_ColorSpace::Family::kCalRGB) ==
49 FPDF_COLORSPACE_CALRGB,
50 "kCalRGB value mismatch");
51static_assert(static_cast<int>(CPDF_ColorSpace::Family::kLab) ==
52 FPDF_COLORSPACE_LAB,
53 "kLab value mismatch");
54static_assert(static_cast<int>(CPDF_ColorSpace::Family::kICCBased) ==
55 FPDF_COLORSPACE_ICCBASED,
56 "kICCBased value mismatch");
57static_assert(static_cast<int>(CPDF_ColorSpace::Family::kSeparation) ==
58 FPDF_COLORSPACE_SEPARATION,
59 "kSeparation value mismatch");
60static_assert(static_cast<int>(CPDF_ColorSpace::Family::kDeviceN) ==
61 FPDF_COLORSPACE_DEVICEN,
62 "kDeviceN value mismatch");
63static_assert(static_cast<int>(CPDF_ColorSpace::Family::kIndexed) ==
64 FPDF_COLORSPACE_INDEXED,
65 "kIndexed value mismatch");
66static_assert(static_cast<int>(CPDF_ColorSpace::Family::kPattern) ==
67 FPDF_COLORSPACE_PATTERN,
68 "kPattern value mismatch");
Jane Liuca898292017-08-16 11:25:35 -040069
Dan Sinclair7aba4722018-03-28 17:04:16 +000070RetainPtr<IFX_SeekableReadStream> MakeSeekableReadStream(
71 FPDF_FILEACCESS* pFileAccess) {
72 return pdfium::MakeRetain<CPDFSDK_CustomAccess>(pFileAccess);
73}
74
Lei Zhang22375412018-10-24 17:26:50 +000075CPDF_ImageObject* CPDFImageObjectFromFPDFPageObject(
76 FPDF_PAGEOBJECT image_object) {
77 CPDF_PageObject* pPageObject = CPDFPageObjectFromFPDFPageObject(image_object);
78 return pPageObject ? pPageObject->AsImage() : nullptr;
79}
80
Lei Zhangcbd89572017-03-15 17:35:47 -070081bool LoadJpegHelper(FPDF_PAGE* pages,
Lei Zhangf0542892019-01-17 18:46:27 +000082 int count,
Lei Zhangcbd89572017-03-15 17:35:47 -070083 FPDF_PAGEOBJECT image_object,
Lei Zhangf0542892019-01-17 18:46:27 +000084 FPDF_FILEACCESS* file_access,
85 bool inline_jpeg) {
Lei Zhang22375412018-10-24 17:26:50 +000086 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
87 if (!pImgObj)
tsepez4cf55152016-11-02 14:37:54 -070088 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070089
Lei Zhangf0542892019-01-17 18:46:27 +000090 if (!file_access)
Tom Sepez525147a2018-05-03 17:19:53 +000091 return false;
Andrew Weintraub21f88ff2017-05-10 13:19:52 -040092
93 if (pages) {
Lei Zhangf0542892019-01-17 18:46:27 +000094 for (int index = 0; index < count; index++) {
Andrew Weintraub21f88ff2017-05-10 13:19:52 -040095 CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
96 if (pPage)
Lei Zhang66601c42018-10-02 18:58:16 +000097 pImgObj->GetImage()->ResetCache(pPage);
Andrew Weintraub21f88ff2017-05-10 13:19:52 -040098 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070099 }
rbpotterf085db32016-12-14 11:44:31 -0800100
Lei Zhangf0542892019-01-17 18:46:27 +0000101 RetainPtr<IFX_SeekableReadStream> pFile = MakeSeekableReadStream(file_access);
102 if (inline_jpeg)
Tom Sepez965b9362022-08-08 17:28:04 +0000103 pImgObj->GetImage()->SetJpegImageInline(std::move(pFile));
rbpotterf085db32016-12-14 11:44:31 -0800104 else
Tom Sepez965b9362022-08-08 17:28:04 +0000105 pImgObj->GetImage()->SetJpegImage(std::move(pFile));
106
wileyryae858aa42017-05-31 14:49:05 -0500107 pImgObj->SetDirty(true);
tsepez4cf55152016-11-02 14:37:54 -0700108 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700109}
110
Lei Zhangcbd89572017-03-15 17:35:47 -0700111} // namespace
112
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400113FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
Lei Zhangcbd89572017-03-15 17:35:47 -0700114FPDFPageObj_NewImageObj(FPDF_DOCUMENT document) {
115 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
116 if (!pDoc)
117 return nullptr;
118
Tom Sepez5af95432020-05-15 22:55:16 +0000119 auto pImageObj = std::make_unique<CPDF_ImageObject>();
Tom Sepez7d4f6a82017-03-31 17:10:34 -0700120 pImageObj->SetImage(pdfium::MakeRetain<CPDF_Image>(pDoc));
Tom Sepez525147a2018-05-03 17:19:53 +0000121
122 // Caller takes ownership.
123 return FPDFPageObjectFromCPDFPageObject(pImageObj.release());
Lei Zhangcbd89572017-03-15 17:35:47 -0700124}
125
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400126FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
rbpotterf085db32016-12-14 11:44:31 -0800127FPDFImageObj_LoadJpegFile(FPDF_PAGE* pages,
Lei Zhangf0542892019-01-17 18:46:27 +0000128 int count,
rbpotterf085db32016-12-14 11:44:31 -0800129 FPDF_PAGEOBJECT image_object,
Lei Zhangf0542892019-01-17 18:46:27 +0000130 FPDF_FILEACCESS* file_access) {
131 return LoadJpegHelper(pages, count, image_object, file_access, false);
rbpotterf085db32016-12-14 11:44:31 -0800132}
133
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400134FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
rbpotterf085db32016-12-14 11:44:31 -0800135FPDFImageObj_LoadJpegFileInline(FPDF_PAGE* pages,
Lei Zhangf0542892019-01-17 18:46:27 +0000136 int count,
rbpotterf085db32016-12-14 11:44:31 -0800137 FPDF_PAGEOBJECT image_object,
Lei Zhangf0542892019-01-17 18:46:27 +0000138 FPDF_FILEACCESS* file_access) {
139 return LoadJpegHelper(pages, count, image_object, file_access, true);
rbpotterf085db32016-12-14 11:44:31 -0800140}
141
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400142FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
143FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object,
144 double a,
145 double b,
146 double c,
147 double d,
148 double e,
149 double f) {
Lei Zhang22375412018-10-24 17:26:50 +0000150 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
Tom Sepez525147a2018-05-03 17:19:53 +0000151 if (!pImgObj)
152 return false;
153
Lei Zhang7dd720e2021-06-25 20:15:56 +0000154 pImgObj->SetImageMatrix(CFX_Matrix(
155 static_cast<float>(a), static_cast<float>(b), static_cast<float>(c),
156 static_cast<float>(d), static_cast<float>(e), static_cast<float>(f)));
wileyryae858aa42017-05-31 14:49:05 -0500157 pImgObj->SetDirty(true);
tsepez4cf55152016-11-02 14:37:54 -0700158 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700159}
160
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400161FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
162FPDFImageObj_SetBitmap(FPDF_PAGE* pages,
Lei Zhangf0542892019-01-17 18:46:27 +0000163 int count,
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400164 FPDF_PAGEOBJECT image_object,
165 FPDF_BITMAP bitmap) {
Lei Zhang22375412018-10-24 17:26:50 +0000166 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
Tom Sepez525147a2018-05-03 17:19:53 +0000167 if (!pImgObj)
168 return false;
169
Lei Zhang22375412018-10-24 17:26:50 +0000170 if (!bitmap)
171 return false;
172
Lei Zhangd19dc582019-01-17 18:47:38 +0000173 if (pages) {
174 for (int index = 0; index < count; index++) {
175 CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
176 if (pPage)
177 pImgObj->GetImage()->ResetCache(pPage);
178 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700179 }
Lei Zhangd19dc582019-01-17 18:47:38 +0000180
Tom Sepez525147a2018-05-03 17:19:53 +0000181 RetainPtr<CFX_DIBitmap> holder(CFXDIBitmapFromFPDFBitmap(bitmap));
Tom Sepezf0799fe2017-03-28 09:31:32 -0700182 pImgObj->GetImage()->SetImage(holder);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700183 pImgObj->CalcBoundingBox();
wileyryae858aa42017-05-31 14:49:05 -0500184 pImgObj->SetDirty(true);
tsepez4cf55152016-11-02 14:37:54 -0700185 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700186}
Jane Liu28fb7ba2017-08-02 21:45:57 -0400187
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400188FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
Jane Liu28fb7ba2017-08-02 21:45:57 -0400189FPDFImageObj_GetBitmap(FPDF_PAGEOBJECT image_object) {
Lei Zhang22375412018-10-24 17:26:50 +0000190 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
191 if (!pImgObj)
Jane Liu28fb7ba2017-08-02 21:45:57 -0400192 return nullptr;
193
Lei Zhang22375412018-10-24 17:26:50 +0000194 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liu28fb7ba2017-08-02 21:45:57 -0400195 if (!pImg)
196 return nullptr;
197
Tom Sepeze6ff2eb2018-08-24 21:55:46 +0000198 RetainPtr<CFX_DIBBase> pSource = pImg->LoadDIBBase();
Jane Liu28fb7ba2017-08-02 21:45:57 -0400199 if (!pSource)
200 return nullptr;
201
Lei Zhang1e1e1732023-09-14 03:33:49 +0000202 // If the source image has a representation of 1 bit per pixel, or if the
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000203 // source image has a color palette, convert it to a representation that does
204 // not have a color palette, as there is no public API to access the palette.
Lei Zhang1e1e1732023-09-14 03:33:49 +0000205 //
206 // Otherwise, convert the source image to a bitmap directly,
Jane Liu28fb7ba2017-08-02 21:45:57 -0400207 // retaining its color representation.
Lei Zhang1e1e1732023-09-14 03:33:49 +0000208 //
209 // Only return FPDF_BITMAPs in formats that FPDFBitmap_CreateEx() would
210 // return.
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000211 enum class ConversionOp {
212 kRealize,
213 kConvertTo8bppRgb,
214 kConvertToRgb,
215 };
216
217 ConversionOp op;
Lei Zhang1e1e1732023-09-14 03:33:49 +0000218 switch (pSource->GetFormat()) {
219 case FXDIB_Format::k1bppMask:
Lei Zhang1e1e1732023-09-14 03:33:49 +0000220 case FXDIB_Format::k8bppMask:
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000221 // Masks do not have palettes, so they can be safely converted to
222 // `FXDIB_Format::k8bppRgb`.
223 CHECK(!pSource->HasPalette());
224 op = ConversionOp::kConvertTo8bppRgb;
225 break;
226 case FXDIB_Format::k1bppRgb:
227 // If there is a palette, then convert to `FXDIB_Format::kRgb` to avoid
228 // creating a bitmap with a palette.
229 op = pSource->HasPalette() ? ConversionOp::kConvertToRgb
230 : ConversionOp::kConvertTo8bppRgb;
231 break;
Lei Zhang1e1e1732023-09-14 03:33:49 +0000232 case FXDIB_Format::k8bppRgb:
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000233 // If there is a palette, then convert to `FXDIB_Format::kRgb` to avoid
234 // creating a bitmap with a palette.
235 op = pSource->HasPalette() ? ConversionOp::kConvertToRgb
236 : ConversionOp::kRealize;
Lei Zhang1e1e1732023-09-14 03:33:49 +0000237 break;
238
239 case FXDIB_Format::kArgb:
240 case FXDIB_Format::kRgb:
241 case FXDIB_Format::kRgb32:
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000242 CHECK(!pSource->HasPalette());
243 op = ConversionOp::kRealize;
Lei Zhang1e1e1732023-09-14 03:33:49 +0000244 break;
245
246 case FXDIB_Format::kInvalid: {
247 NOTREACHED_NORETURN();
248 }
249 }
Jane Liu28fb7ba2017-08-02 21:45:57 -0400250
Lei Zhangb5bc2e92023-09-18 21:25:39 +0000251 RetainPtr<CFX_DIBitmap> pBitmap;
252 switch (op) {
253 case ConversionOp::kRealize:
254 pBitmap = pSource->Realize();
255 break;
256 case ConversionOp::kConvertTo8bppRgb:
257 pBitmap = pSource->ConvertTo(FXDIB_Format::k8bppRgb);
258 break;
259 case ConversionOp::kConvertToRgb:
260 pBitmap = pSource->ConvertTo(FXDIB_Format::kRgb);
261 break;
262 }
263 if (pBitmap) {
264 CHECK(!pBitmap->HasPalette());
265 }
266
Tom Sepez525147a2018-05-03 17:19:53 +0000267 return FPDFBitmapFromCFXDIBitmap(pBitmap.Leak());
Jane Liu28fb7ba2017-08-02 21:45:57 -0400268}
Jane Liu548334e2017-08-03 16:33:40 -0400269
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000270FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
271FPDFImageObj_GetRenderedBitmap(FPDF_DOCUMENT document,
272 FPDF_PAGE page,
273 FPDF_PAGEOBJECT image_object) {
274 CPDF_Document* doc = CPDFDocumentFromFPDFDocument(document);
275 if (!doc)
276 return nullptr;
277
278 CPDF_Page* optional_page = CPDFPageFromFPDFPage(page);
279 if (optional_page && optional_page->GetDocument() != doc)
280 return nullptr;
281
282 CPDF_ImageObject* image = CPDFImageObjectFromFPDFPageObject(image_object);
283 if (!image)
284 return nullptr;
285
286 // Create |result_bitmap|.
287 const CFX_Matrix& image_matrix = image->matrix();
288 int output_width = image_matrix.a;
289 int output_height = image_matrix.d;
290 auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Tom Sepez26813ad2020-10-20 17:37:43 +0000291 if (!result_bitmap->Create(output_width, output_height, FXDIB_Format::kArgb))
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000292 return nullptr;
293
294 // Set up all the rendering code.
Tom Sepeza22da902022-06-30 18:08:32 +0000295 RetainPtr<CPDF_Dictionary> page_resources =
296 optional_page ? optional_page->GetMutablePageResources() : nullptr;
Tom Sepeze282b0f2022-09-30 19:37:29 +0000297 CPDF_RenderContext context(doc, std::move(page_resources),
298 /*pPageCache=*/nullptr);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000299 CFX_DefaultRenderDevice device;
Lei Zhange381fe92022-07-08 21:53:54 +0000300 device.Attach(result_bitmap);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000301 CPDF_RenderStatus status(&context, &device);
Tom Sepezbf57f852022-07-26 18:33:34 +0000302 CPDF_ImageRenderer renderer(&status);
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000303
304 // Need to first flip the image, as expected by |renderer|.
305 CFX_Matrix render_matrix(1, 0, 0, -1, 0, output_height);
306
307 // Then take |image_matrix|'s offset into account.
308 render_matrix.Translate(-image_matrix.e, image_matrix.f);
309
310 // Do the actual rendering.
Tom Sepezbf57f852022-07-26 18:33:34 +0000311 bool should_continue = renderer.Start(image, render_matrix,
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000312 /*bStdCS=*/false, BlendMode::kNormal);
313 while (should_continue)
314 should_continue = renderer.Continue(/*pPause=*/nullptr);
315
316 if (!renderer.GetResult())
317 return nullptr;
318
Lei Zhangb26a1102023-12-16 00:04:05 +0000319#if defined(PDF_USE_SKIA)
Lei Zhang334a9ca2023-10-24 17:47:10 +0000320 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
Alan Screene44f1672022-09-15 20:09:43 +0000321 result_bitmap->UnPreMultiply();
Lei Zhang334a9ca2023-10-24 17:47:10 +0000322 }
Hui Yingst2a9c98c2022-08-26 20:27:23 +0000323#endif
324
Lei Zhang0ac7b4e2020-07-18 00:35:53 +0000325 // Caller takes ownership.
326 return FPDFBitmapFromCFXDIBitmap(result_bitmap.Leak());
327}
328
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400329FPDF_EXPORT unsigned long FPDF_CALLCONV
Jane Liu548334e2017-08-03 16:33:40 -0400330FPDFImageObj_GetImageDataDecoded(FPDF_PAGEOBJECT image_object,
331 void* buffer,
332 unsigned long buflen) {
Lei Zhang22375412018-10-24 17:26:50 +0000333 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
334 if (!pImgObj)
Jane Liu548334e2017-08-03 16:33:40 -0400335 return 0;
336
Lei Zhang22375412018-10-24 17:26:50 +0000337 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liu548334e2017-08-03 16:33:40 -0400338 if (!pImg)
339 return 0;
340
Tom Sepezbb040742022-09-28 16:33:34 +0000341 RetainPtr<const CPDF_Stream> pImgStream = pImg->GetStream();
Jane Liu548334e2017-08-03 16:33:40 -0400342 if (!pImgStream)
343 return 0;
344
Tom Sepez06943a92022-11-10 20:29:34 +0000345 return DecodeStreamMaybeCopyAndReturnLength(
346 std::move(pImgStream),
347 {static_cast<uint8_t*>(buffer), static_cast<size_t>(buflen)});
Jane Liu548334e2017-08-03 16:33:40 -0400348}
349
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400350FPDF_EXPORT unsigned long FPDF_CALLCONV
Jane Liu548334e2017-08-03 16:33:40 -0400351FPDFImageObj_GetImageDataRaw(FPDF_PAGEOBJECT image_object,
352 void* buffer,
353 unsigned long buflen) {
Lei Zhang22375412018-10-24 17:26:50 +0000354 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
355 if (!pImgObj)
Jane Liu548334e2017-08-03 16:33:40 -0400356 return 0;
357
Lei Zhang22375412018-10-24 17:26:50 +0000358 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liu548334e2017-08-03 16:33:40 -0400359 if (!pImg)
360 return 0;
361
Tom Sepezbb040742022-09-28 16:33:34 +0000362 RetainPtr<const CPDF_Stream> pImgStream = pImg->GetStream();
Jane Liu548334e2017-08-03 16:33:40 -0400363 if (!pImgStream)
364 return 0;
365
Tom Sepez06943a92022-11-10 20:29:34 +0000366 return GetRawStreamMaybeCopyAndReturnLength(
367 std::move(pImgStream),
368 {static_cast<uint8_t*>(buffer), static_cast<size_t>(buflen)});
Jane Liu548334e2017-08-03 16:33:40 -0400369}
Jane Liube63ab92017-08-09 14:09:34 -0400370
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400371FPDF_EXPORT int FPDF_CALLCONV
Jane Liube63ab92017-08-09 14:09:34 -0400372FPDFImageObj_GetImageFilterCount(FPDF_PAGEOBJECT image_object) {
Lei Zhang22375412018-10-24 17:26:50 +0000373 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
374 if (!pImgObj)
Jane Liube63ab92017-08-09 14:09:34 -0400375 return 0;
376
Lei Zhang22375412018-10-24 17:26:50 +0000377 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liube63ab92017-08-09 14:09:34 -0400378 if (!pImg)
379 return 0;
380
Tom Sepez8a185fa2022-09-26 18:33:13 +0000381 RetainPtr<const CPDF_Dictionary> pDict = pImg->GetDict();
Tom Sepeze0dcb6b2022-09-08 00:29:53 +0000382 if (!pDict)
383 return 0;
384
385 RetainPtr<const CPDF_Object> pFilter = pDict->GetDirectObjectFor("Filter");
Jane Liube63ab92017-08-09 14:09:34 -0400386 if (!pFilter)
387 return 0;
388
389 if (pFilter->IsArray())
Tom Sepez5ea5fa92022-03-08 00:15:23 +0000390 return fxcrt::CollectionSize<int>(*pFilter->AsArray());
391
Jane Liube63ab92017-08-09 14:09:34 -0400392 if (pFilter->IsName())
393 return 1;
394
395 return 0;
396}
397
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400398FPDF_EXPORT unsigned long FPDF_CALLCONV
Jane Liube63ab92017-08-09 14:09:34 -0400399FPDFImageObj_GetImageFilter(FPDF_PAGEOBJECT image_object,
400 int index,
401 void* buffer,
402 unsigned long buflen) {
403 if (index < 0 || index >= FPDFImageObj_GetImageFilterCount(image_object))
404 return 0;
405
406 CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
Tom Sepez8a185fa2022-09-26 18:33:13 +0000407 RetainPtr<const CPDF_Dictionary> pDict =
408 pObj->AsImage()->GetImage()->GetDict();
Tom Sepeze0dcb6b2022-09-08 00:29:53 +0000409 RetainPtr<const CPDF_Object> pFilter = pDict->GetDirectObjectFor("Filter");
Tom Sepez773310d2022-06-24 22:13:38 +0000410 ByteString bsFilter = pFilter->IsName()
411 ? pFilter->AsName()->GetString()
Tom Sepez56902472022-09-14 21:37:14 +0000412 : pFilter->AsArray()->GetByteStringAt(index);
Jane Liube63ab92017-08-09 14:09:34 -0400413
Daniel Hosseinian5bc1f982020-04-14 01:05:27 +0000414 return NulTerminateMaybeCopyAndReturnLength(bsFilter, buffer, buflen);
Jane Liube63ab92017-08-09 14:09:34 -0400415}
Jane Liuca898292017-08-16 11:25:35 -0400416
417FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
418FPDFImageObj_GetImageMetadata(FPDF_PAGEOBJECT image_object,
419 FPDF_PAGE page,
420 FPDF_IMAGEOBJ_METADATA* metadata) {
Lei Zhang22375412018-10-24 17:26:50 +0000421 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
422 if (!pImgObj || !metadata)
Jane Liuca898292017-08-16 11:25:35 -0400423 return false;
424
Lei Zhang22375412018-10-24 17:26:50 +0000425 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
Jane Liuca898292017-08-16 11:25:35 -0400426 if (!pImg)
427 return false;
428
Tom Sepez6eb915b2021-04-30 00:11:34 +0000429 metadata->marked_content_id =
430 pImgObj->GetContentMarks()->GetMarkedContentID();
Julian Lungerecd063e2017-12-27 10:18:50 -0500431
Jane Liuca898292017-08-16 11:25:35 -0400432 const int nPixelWidth = pImg->GetPixelWidth();
433 const int nPixelHeight = pImg->GetPixelHeight();
434 metadata->width = nPixelWidth;
435 metadata->height = nPixelHeight;
436
Lei Zhang22375412018-10-24 17:26:50 +0000437 const float nWidth = pImgObj->GetRect().Width();
438 const float nHeight = pImgObj->GetRect().Height();
Jane Liuca898292017-08-16 11:25:35 -0400439 constexpr int nPointsPerInch = 72;
440 if (nWidth != 0 && nHeight != 0) {
441 metadata->horizontal_dpi = nPixelWidth / nWidth * nPointsPerInch;
442 metadata->vertical_dpi = nPixelHeight / nHeight * nPointsPerInch;
443 }
444
445 metadata->bits_per_pixel = 0;
446 metadata->colorspace = FPDF_COLORSPACE_UNKNOWN;
447
448 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
Lei Zhang8f637632018-05-07 23:36:26 +0000449 if (!pPage || !pPage->GetDocument() || !pImg->GetStream())
Jane Liuca898292017-08-16 11:25:35 -0400450 return true;
451
Tom Sepez6bc9ee52022-08-11 18:13:09 +0000452 // A cross-document image may have come from the embedder.
453 if (pPage->GetDocument() != pImg->GetDocument())
454 return false;
455
456 RetainPtr<CPDF_DIB> pSource = pImg->CreateNewDIB();
Tom Sepezd7fa6a42022-04-06 20:50:00 +0000457 CPDF_DIB::LoadState ret = pSource->StartLoadDIBBase(
Tom Sepez4ede0792022-10-07 20:25:36 +0000458 false, nullptr, pPage->GetPageResources().Get(), false,
fineaskotnikov231e7e12022-10-28 20:23:20 +0000459 CPDF_ColorSpace::Family::kUnknown, false, {0, 0});
Lei Zhang87c415a2020-01-14 19:54:36 +0000460 if (ret == CPDF_DIB::LoadState::kFail)
Jane Liuca898292017-08-16 11:25:35 -0400461 return true;
Jane Liuca898292017-08-16 11:25:35 -0400462
463 metadata->bits_per_pixel = pSource->GetBPP();
Tom Sepezd30786c2021-05-18 23:05:54 +0000464 if (pSource->GetColorSpace()) {
465 metadata->colorspace =
466 static_cast<int>(pSource->GetColorSpace()->GetFamily());
467 }
Jane Liuca898292017-08-16 11:25:35 -0400468 return true;
469}
fineaskotnikov379bfc92023-04-20 20:20:24 +0000470
471FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
472FPDFImageObj_GetImagePixelSize(FPDF_PAGEOBJECT image_object,
473 unsigned int* width,
474 unsigned int* height) {
475 CPDF_ImageObject* pImgObj = CPDFImageObjectFromFPDFPageObject(image_object);
476 if (!pImgObj || !width || !height) {
477 return false;
478 }
479
480 RetainPtr<CPDF_Image> pImg = pImgObj->GetImage();
481 if (!pImg) {
482 return false;
483 }
484
485 *width = pImg->GetPixelWidth();
486 *height = pImg->GetPixelHeight();
487 return true;
488}