blob: 662ad23d76834a560cbd1d2eb3b6beaf74c87419 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// Copyright 2014 PDFium Authors. All rights reserved.
2// 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
dsinclair39c62fd2016-09-29 12:49:17 -07009#include "core/fpdfapi/cpdf_modulemgr.h"
dsinclair41872fa2016-10-04 11:29:35 -070010#include "core/fpdfapi/page/cpdf_image.h"
11#include "core/fpdfapi/page/cpdf_imageobject.h"
Jane Liuca898292017-08-16 11:25:35 -040012#include "core/fpdfapi/page/cpdf_page.h"
dsinclair41872fa2016-10-04 11:29:35 -070013#include "core/fpdfapi/page/cpdf_pageobject.h"
Jane Liube63ab92017-08-09 14:09:34 -040014#include "core/fpdfapi/parser/cpdf_array.h"
15#include "core/fpdfapi/parser/cpdf_name.h"
Jane Liuca898292017-08-16 11:25:35 -040016#include "core/fpdfapi/render/cpdf_dibsource.h"
dsinclair114e46a2016-09-29 17:18:21 -070017#include "fpdfsdk/fsdk_define.h"
tsepez36eb4bd2016-10-03 15:24:27 -070018#include "third_party/base/ptr_util.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070019
Lei Zhangcbd89572017-03-15 17:35:47 -070020namespace {
thestigc54bb432016-07-29 19:34:20 -070021
Jane Liuca898292017-08-16 11:25:35 -040022// These checks ensure the consistency of colorspace values across core/ and
23// public/.
24static_assert(PDFCS_DEVICEGRAY == FPDF_COLORSPACE_DEVICEGRAY,
25 "PDFCS_DEVICEGRAY value mismatch");
26static_assert(PDFCS_DEVICERGB == FPDF_COLORSPACE_DEVICERGB,
27 "PDFCS_DEVICERGB value mismatch");
28static_assert(PDFCS_DEVICECMYK == FPDF_COLORSPACE_DEVICECMYK,
29 "PDFCS_DEVICECMYK value mismatch");
30static_assert(PDFCS_CALGRAY == FPDF_COLORSPACE_CALGRAY,
31 "PDFCS_CALGRAY value mismatch");
32static_assert(PDFCS_CALRGB == FPDF_COLORSPACE_CALRGB,
33 "PDFCS_CALRGB value mismatch");
34static_assert(PDFCS_LAB == FPDF_COLORSPACE_LAB, "PDFCS_LAB value mismatch");
35static_assert(PDFCS_ICCBASED == FPDF_COLORSPACE_ICCBASED,
36 "PDFCS_ICCBASED value mismatch");
37static_assert(PDFCS_SEPARATION == FPDF_COLORSPACE_SEPARATION,
38 "PDFCS_SEPARATION value mismatch");
39static_assert(PDFCS_DEVICEN == FPDF_COLORSPACE_DEVICEN,
40 "PDFCS_DEVICEN value mismatch");
41static_assert(PDFCS_INDEXED == FPDF_COLORSPACE_INDEXED,
42 "PDFCS_INDEXED value mismatch");
43static_assert(PDFCS_PATTERN == FPDF_COLORSPACE_PATTERN,
44 "PDFCS_PATTERN value mismatch");
45
Lei Zhangcbd89572017-03-15 17:35:47 -070046bool LoadJpegHelper(FPDF_PAGE* pages,
47 int nCount,
48 FPDF_PAGEOBJECT image_object,
49 FPDF_FILEACCESS* fileAccess,
50 bool inlineJpeg) {
Andrew Weintraub21f88ff2017-05-10 13:19:52 -040051 if (!image_object || !fileAccess)
tsepez4cf55152016-11-02 14:37:54 -070052 return false;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070053
tsepez833619b2016-12-07 09:21:17 -080054 CFX_RetainPtr<IFX_SeekableReadStream> pFile =
55 MakeSeekableReadStream(fileAccess);
Nicolas Pena46abb662017-05-17 17:23:22 -040056 CPDF_ImageObject* pImgObj = static_cast<CPDF_ImageObject*>(image_object);
Andrew Weintraub21f88ff2017-05-10 13:19:52 -040057
58 if (pages) {
59 for (int index = 0; index < nCount; index++) {
60 CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
61 if (pPage)
62 pImgObj->GetImage()->ResetCache(pPage, nullptr);
63 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070064 }
rbpotterf085db32016-12-14 11:44:31 -080065
66 if (inlineJpeg)
67 pImgObj->GetImage()->SetJpegImageInline(pFile);
68 else
69 pImgObj->GetImage()->SetJpegImage(pFile);
wileyryae858aa42017-05-31 14:49:05 -050070 pImgObj->SetDirty(true);
tsepez4cf55152016-11-02 14:37:54 -070071 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070072}
73
Lei Zhangcbd89572017-03-15 17:35:47 -070074} // namespace
75
Dan Sinclair00d2ad12017-08-10 14:13:02 -040076FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
Lei Zhangcbd89572017-03-15 17:35:47 -070077FPDFPageObj_NewImageObj(FPDF_DOCUMENT document) {
78 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
79 if (!pDoc)
80 return nullptr;
81
Tom Sepez7d4f6a82017-03-31 17:10:34 -070082 auto pImageObj = pdfium::MakeUnique<CPDF_ImageObject>();
83 pImageObj->SetImage(pdfium::MakeRetain<CPDF_Image>(pDoc));
84 return pImageObj.release();
Lei Zhangcbd89572017-03-15 17:35:47 -070085}
86
Dan Sinclair00d2ad12017-08-10 14:13:02 -040087FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
rbpotterf085db32016-12-14 11:44:31 -080088FPDFImageObj_LoadJpegFile(FPDF_PAGE* pages,
89 int nCount,
90 FPDF_PAGEOBJECT image_object,
91 FPDF_FILEACCESS* fileAccess) {
Lei Zhangcbd89572017-03-15 17:35:47 -070092 return LoadJpegHelper(pages, nCount, image_object, fileAccess, false);
rbpotterf085db32016-12-14 11:44:31 -080093}
94
Dan Sinclair00d2ad12017-08-10 14:13:02 -040095FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
rbpotterf085db32016-12-14 11:44:31 -080096FPDFImageObj_LoadJpegFileInline(FPDF_PAGE* pages,
97 int nCount,
98 FPDF_PAGEOBJECT image_object,
99 FPDF_FILEACCESS* fileAccess) {
Lei Zhangcbd89572017-03-15 17:35:47 -0700100 return LoadJpegHelper(pages, nCount, image_object, fileAccess, true);
rbpotterf085db32016-12-14 11:44:31 -0800101}
102
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400103FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
104FPDFImageObj_SetMatrix(FPDF_PAGEOBJECT image_object,
105 double a,
106 double b,
107 double c,
108 double d,
109 double e,
110 double f) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700111 if (!image_object)
tsepez4cf55152016-11-02 14:37:54 -0700112 return false;
thestigc54bb432016-07-29 19:34:20 -0700113
Nicolas Pena46abb662017-05-17 17:23:22 -0400114 CPDF_ImageObject* pImgObj = static_cast<CPDF_ImageObject*>(image_object);
Dan Sinclair05df0752017-03-14 14:43:42 -0400115 pImgObj->set_matrix(CFX_Matrix(static_cast<float>(a), static_cast<float>(b),
116 static_cast<float>(c), static_cast<float>(d),
117 static_cast<float>(e), static_cast<float>(f)));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700118 pImgObj->CalcBoundingBox();
wileyryae858aa42017-05-31 14:49:05 -0500119 pImgObj->SetDirty(true);
tsepez4cf55152016-11-02 14:37:54 -0700120 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700121}
122
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400123FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
124FPDFImageObj_SetBitmap(FPDF_PAGE* pages,
125 int nCount,
126 FPDF_PAGEOBJECT image_object,
127 FPDF_BITMAP bitmap) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700128 if (!image_object || !bitmap || !pages)
tsepez4cf55152016-11-02 14:37:54 -0700129 return false;
thestigc54bb432016-07-29 19:34:20 -0700130
Nicolas Pena46abb662017-05-17 17:23:22 -0400131 CPDF_ImageObject* pImgObj = static_cast<CPDF_ImageObject*>(image_object);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700132 for (int index = 0; index < nCount; index++) {
Tom Sepezdb0be962015-10-16 14:00:21 -0700133 CPDF_Page* pPage = CPDFPageFromFPDFPage(pages[index]);
thestigc54bb432016-07-29 19:34:20 -0700134 if (pPage)
thestigf41d9dc2016-08-05 22:34:58 -0700135 pImgObj->GetImage()->ResetCache(pPage, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700136 }
Tom Sepezf0799fe2017-03-28 09:31:32 -0700137 CFX_RetainPtr<CFX_DIBitmap> holder(CFXBitmapFromFPDFBitmap(bitmap));
138 pImgObj->GetImage()->SetImage(holder);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139 pImgObj->CalcBoundingBox();
wileyryae858aa42017-05-31 14:49:05 -0500140 pImgObj->SetDirty(true);
tsepez4cf55152016-11-02 14:37:54 -0700141 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700142}
Jane Liu28fb7ba2017-08-02 21:45:57 -0400143
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400144FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
Jane Liu28fb7ba2017-08-02 21:45:57 -0400145FPDFImageObj_GetBitmap(FPDF_PAGEOBJECT image_object) {
146 CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
147 if (!pObj || !pObj->IsImage())
148 return nullptr;
149
150 CFX_RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
151 if (!pImg)
152 return nullptr;
153
154 CFX_RetainPtr<CFX_DIBSource> pSource = pImg->LoadDIBSource();
155 if (!pSource)
156 return nullptr;
157
158 CFX_RetainPtr<CFX_DIBitmap> pBitmap;
159 // If the source image has a representation of 1 bit per pixel, then convert
160 // it to a grayscale bitmap having 1 byte per pixel, since bitmaps have no
161 // concept of bits. Otherwise, convert the source image to a bitmap directly,
162 // retaining its color representation.
163 if (pSource->GetBPP() == 1)
164 pBitmap = pSource->CloneConvert(FXDIB_8bppRgb);
165 else
166 pBitmap = pSource->Clone(nullptr);
167
168 return pBitmap.Leak();
169}
Jane Liu548334e2017-08-03 16:33:40 -0400170
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400171FPDF_EXPORT unsigned long FPDF_CALLCONV
Jane Liu548334e2017-08-03 16:33:40 -0400172FPDFImageObj_GetImageDataDecoded(FPDF_PAGEOBJECT image_object,
173 void* buffer,
174 unsigned long buflen) {
175 CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
176 if (!pObj || !pObj->IsImage())
177 return 0;
178
179 CFX_RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
180 if (!pImg)
181 return 0;
182
183 CPDF_Stream* pImgStream = pImg->GetStream();
184 if (!pImgStream)
185 return 0;
186
187 return DecodeStreamMaybeCopyAndReturnLength(pImgStream, buffer, buflen);
188}
189
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400190FPDF_EXPORT unsigned long FPDF_CALLCONV
Jane Liu548334e2017-08-03 16:33:40 -0400191FPDFImageObj_GetImageDataRaw(FPDF_PAGEOBJECT image_object,
192 void* buffer,
193 unsigned long buflen) {
194 CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
195 if (!pObj || !pObj->IsImage())
196 return 0;
197
198 CFX_RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
199 if (!pImg)
200 return 0;
201
202 CPDF_Stream* pImgStream = pImg->GetStream();
203 if (!pImgStream)
204 return 0;
205
206 uint32_t len = pImgStream->GetRawSize();
207 if (buffer && buflen >= len)
208 memcpy(buffer, pImgStream->GetRawData(), len);
209
210 return len;
211}
Jane Liube63ab92017-08-09 14:09:34 -0400212
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400213FPDF_EXPORT int FPDF_CALLCONV
Jane Liube63ab92017-08-09 14:09:34 -0400214FPDFImageObj_GetImageFilterCount(FPDF_PAGEOBJECT image_object) {
215 CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
216 if (!pObj || !pObj->IsImage())
217 return 0;
218
219 CFX_RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
220 if (!pImg)
221 return 0;
222
223 CPDF_Dictionary* pDict = pImg->GetDict();
224 CPDF_Object* pFilter = pDict ? pDict->GetDirectObjectFor("Filter") : nullptr;
225 if (!pFilter)
226 return 0;
227
228 if (pFilter->IsArray())
229 return pFilter->AsArray()->GetCount();
230 if (pFilter->IsName())
231 return 1;
232
233 return 0;
234}
235
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400236FPDF_EXPORT unsigned long FPDF_CALLCONV
Jane Liube63ab92017-08-09 14:09:34 -0400237FPDFImageObj_GetImageFilter(FPDF_PAGEOBJECT image_object,
238 int index,
239 void* buffer,
240 unsigned long buflen) {
241 if (index < 0 || index >= FPDFImageObj_GetImageFilterCount(image_object))
242 return 0;
243
244 CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
245 CPDF_Object* pFilter =
246 pObj->AsImage()->GetImage()->GetDict()->GetDirectObjectFor("Filter");
247 CFX_WideString wsFilters;
248 if (pFilter->IsName())
249 wsFilters = pFilter->AsName()->GetUnicodeText();
250 else
251 wsFilters = pFilter->AsArray()->GetUnicodeTextAt(index);
252
253 return Utf16EncodeMaybeCopyAndReturnLength(wsFilters, buffer, buflen);
254}
Jane Liuca898292017-08-16 11:25:35 -0400255
256FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
257FPDFImageObj_GetImageMetadata(FPDF_PAGEOBJECT image_object,
258 FPDF_PAGE page,
259 FPDF_IMAGEOBJ_METADATA* metadata) {
260 CPDF_PageObject* pObj = CPDFPageObjectFromFPDFPageObject(image_object);
261 if (!pObj || !pObj->IsImage() || !metadata)
262 return false;
263
264 CFX_RetainPtr<CPDF_Image> pImg = pObj->AsImage()->GetImage();
265 if (!pImg)
266 return false;
267
268 const int nPixelWidth = pImg->GetPixelWidth();
269 const int nPixelHeight = pImg->GetPixelHeight();
270 metadata->width = nPixelWidth;
271 metadata->height = nPixelHeight;
272
273 const float nWidth = pObj->m_Right - pObj->m_Left;
274 const float nHeight = pObj->m_Top - pObj->m_Bottom;
275 constexpr int nPointsPerInch = 72;
276 if (nWidth != 0 && nHeight != 0) {
277 metadata->horizontal_dpi = nPixelWidth / nWidth * nPointsPerInch;
278 metadata->vertical_dpi = nPixelHeight / nHeight * nPointsPerInch;
279 }
280
281 metadata->bits_per_pixel = 0;
282 metadata->colorspace = FPDF_COLORSPACE_UNKNOWN;
283
284 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
285 if (!pPage || !pPage->m_pDocument.Get() || !pImg->GetStream())
286 return true;
287
288 auto pSource = pdfium::MakeRetain<CPDF_DIBSource>();
289 if (!pSource->StartLoadDIBSource(pPage->m_pDocument.Get(), pImg->GetStream(),
290 false, nullptr,
291 pPage->m_pPageResources.Get())) {
292 return true;
293 }
294
295 metadata->bits_per_pixel = pSource->GetBPP();
296 if (pSource->GetColorSpace())
297 metadata->colorspace = pSource->GetColorSpace()->GetFamily();
298
299 return true;
300}