• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "public/fpdf_thumbnail.h"
6 
7 #include <utility>
8 
9 #include "core/fpdfapi/page/cpdf_dib.h"
10 #include "core/fpdfapi/page/cpdf_page.h"
11 #include "core/fpdfapi/parser/cpdf_dictionary.h"
12 #include "core/fpdfapi/parser/cpdf_stream.h"
13 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
14 #include "core/fxcrt/compiler_specific.h"
15 #include "core/fxcrt/span.h"
16 #include "core/fxge/dib/cfx_dibitmap.h"
17 #include "fpdfsdk/cpdfsdk_helpers.h"
18 #include "public/fpdfview.h"
19 
20 namespace {
21 
CPDFStreamForThumbnailFromPage(FPDF_PAGE page)22 RetainPtr<const CPDF_Stream> CPDFStreamForThumbnailFromPage(FPDF_PAGE page) {
23   const CPDF_Page* pdf_page = CPDFPageFromFPDFPage(page);
24   if (!pdf_page)
25     return nullptr;
26 
27   RetainPtr<const CPDF_Dictionary> page_dict = pdf_page->GetDict();
28   if (!page_dict->KeyExist("Type"))
29     return nullptr;
30 
31   return page_dict->GetStreamFor("Thumb");
32 }
33 
34 }  // namespace
35 
36 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFPage_GetDecodedThumbnailData(FPDF_PAGE page,void * buffer,unsigned long buflen)37 FPDFPage_GetDecodedThumbnailData(FPDF_PAGE page,
38                                  void* buffer,
39                                  unsigned long buflen) {
40   RetainPtr<const CPDF_Stream> thumb_stream =
41       CPDFStreamForThumbnailFromPage(page);
42   if (!thumb_stream)
43     return 0u;
44 
45   // SAFETY: caller ensures `buffer` points to at least `buflen` bytes.
46   return DecodeStreamMaybeCopyAndReturnLength(
47       std::move(thumb_stream),
48       UNSAFE_BUFFERS(pdfium::make_span(static_cast<uint8_t*>(buffer),
49                                        static_cast<size_t>(buflen))));
50 }
51 
52 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFPage_GetRawThumbnailData(FPDF_PAGE page,void * buffer,unsigned long buflen)53 FPDFPage_GetRawThumbnailData(FPDF_PAGE page,
54                              void* buffer,
55                              unsigned long buflen) {
56   RetainPtr<const CPDF_Stream> thumb_stream =
57       CPDFStreamForThumbnailFromPage(page);
58   if (!thumb_stream)
59     return 0u;
60 
61   // SAFETY: caller ensures `buffer` points to at least `buflen` bytes.
62   return GetRawStreamMaybeCopyAndReturnLength(
63       std::move(thumb_stream),
64       UNSAFE_BUFFERS(pdfium::make_span(static_cast<uint8_t*>(buffer),
65                                        static_cast<size_t>(buflen))));
66 }
67 
68 FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV
FPDFPage_GetThumbnailAsBitmap(FPDF_PAGE page)69 FPDFPage_GetThumbnailAsBitmap(FPDF_PAGE page) {
70   RetainPtr<const CPDF_Stream> thumb_stream =
71       CPDFStreamForThumbnailFromPage(page);
72   if (!thumb_stream)
73     return nullptr;
74 
75   const CPDF_Page* pdf_page = CPDFPageFromFPDFPage(page);
76   auto dib_source = pdfium::MakeRetain<CPDF_DIB>(pdf_page->GetDocument(),
77                                                  std::move(thumb_stream));
78   const CPDF_DIB::LoadState start_status = dib_source->StartLoadDIBBase(
79       false, nullptr, pdf_page->GetPageResources().Get(), false,
80       CPDF_ColorSpace::Family::kUnknown, false, {0, 0});
81   if (start_status == CPDF_DIB::LoadState::kFail)
82     return nullptr;
83 
84   auto thumb_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
85   if (!thumb_bitmap->Copy(std::move(dib_source))) {
86     return nullptr;
87   }
88 
89   CHECK(!thumb_bitmap->IsPremultiplied());
90   return FPDFBitmapFromCFXDIBitmap(thumb_bitmap.Leak());
91 }
92