diff options
author | Ashod Nakashian <ashod.nakashian@collabora.co.uk> | 2018-03-13 21:07:17 -0400 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2018-06-01 08:59:09 +0200 |
commit | b26c7beaa3f3a642917a8ab88088401e971eefbc (patch) | |
tree | b9e7f983ebf95678548fc1b940b120270774a8d0 /vcl | |
parent | 499f472bd1b3e7f557b743a4f57d3ea0412922fb (diff) |
vcl: support rendering multiple PDF pages to bitmap
Change-Id: Id42ecabcad90dde84475a01e5df4ed94f221f5ce
Reviewed-on: https://gerrit.libreoffice.org/51255
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Ashod Nakashian <ashnakash@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/filter/ipdf/pdfread.cxx | 83 |
1 files changed, 47 insertions, 36 deletions
diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index b1e85f6816de..a38d21174ce6 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -56,8 +56,9 @@ double pointToPixel(double fPoint) } /// Does PDF to bitmap conversion using pdfium. -bool generatePreview(SvStream& rStream, Bitmap& rBitmap, - sal_uInt64 nPos, sal_uInt64 nSize) +size_t generatePreview(SvStream& rStream, std::vector<Bitmap>& rBitmaps, + sal_uInt64 nPos, sal_uInt64 nSize, + const size_t nFirstPage = 0, int nPages = 1) { FPDF_LIBRARY_CONFIG aConfig; aConfig.version = 2; @@ -74,45 +75,53 @@ bool generatePreview(SvStream& rStream, Bitmap& rBitmap, // Load the buffer using pdfium. FPDF_DOCUMENT pPdfDocument = FPDF_LoadMemDocument(aInBuffer.GetData(), aInBuffer.GetSize(), /*password=*/nullptr); if (!pPdfDocument) - return false; - - // Render the first page. - FPDF_PAGE pPdfPage = FPDF_LoadPage(pPdfDocument, /*page_index=*/0); - if (!pPdfPage) - return false; - - // Returned unit is points, convert that to pixel. - size_t nPageWidth = pointToPixel(FPDF_GetPageWidth(pPdfPage)); - size_t nPageHeight = pointToPixel(FPDF_GetPageHeight(pPdfPage)); - FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1); - if (!pPdfBitmap) - return false; + return 0; - FPDF_DWORD nColor = FPDFPage_HasTransparency(pPdfPage) ? 0x00000000 : 0xFFFFFFFF; - FPDFBitmap_FillRect(pPdfBitmap, 0, 0, nPageWidth, nPageHeight, nColor); - FPDF_RenderPageBitmap(pPdfBitmap, pPdfPage, /*start_x=*/0, /*start_y=*/0, nPageWidth, nPageHeight, /*rotate=*/0, /*flags=*/0); - - // Save the buffer as a bitmap. - Bitmap aBitmap(Size(nPageWidth, nPageHeight), 24); + const int nPageCount = FPDF_GetPageCount(pPdfDocument); + if (nPages <= 0) + nPages = nPageCount; + const size_t nLastPage = std::min<int>(nPageCount, nFirstPage + nPages) - 1; + for (size_t nPageIndex = nFirstPage; nPageIndex <= nLastPage; ++nPageIndex) { - Bitmap::ScopedWriteAccess pWriteAccess(aBitmap); - auto pPdfBuffer = static_cast<ConstScanline>(FPDFBitmap_GetBuffer(pPdfBitmap)); - for (size_t nRow = 0; nRow < nPageHeight; ++nRow) + // Render next page. + FPDF_PAGE pPdfPage = FPDF_LoadPage(pPdfDocument, nPageIndex); + if (!pPdfPage) + break; + + // Returned unit is points, convert that to pixel. + const size_t nPageWidth = pointToPixel(FPDF_GetPageWidth(pPdfPage)); + const size_t nPageHeight = pointToPixel(FPDF_GetPageHeight(pPdfPage)); + FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1); + if (!pPdfBitmap) + break; + + const FPDF_DWORD nColor = FPDFPage_HasTransparency(pPdfPage) ? 0x00000000 : 0xFFFFFFFF; + FPDFBitmap_FillRect(pPdfBitmap, 0, 0, nPageWidth, nPageHeight, nColor); + FPDF_RenderPageBitmap(pPdfBitmap, pPdfPage, /*start_x=*/0, /*start_y=*/0, nPageWidth, nPageHeight, /*rotate=*/0, /*flags=*/0); + + // Save the buffer as a bitmap. + Bitmap aBitmap(Size(nPageWidth, nPageHeight), 24); { - int nStride = FPDFBitmap_GetStride(pPdfBitmap); - ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow); - // pdfium byte order is BGRA. - pWriteAccess->CopyScanline(nRow, pPdfLine, ScanlineFormat::N32BitTcBgra, nStride); + Bitmap::ScopedWriteAccess pWriteAccess(aBitmap); + const auto pPdfBuffer = static_cast<ConstScanline>(FPDFBitmap_GetBuffer(pPdfBitmap)); + const int nStride = FPDFBitmap_GetStride(pPdfBitmap); + for (size_t nRow = 0; nRow < nPageHeight; ++nRow) + { + ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow); + // pdfium byte order is BGRA. + pWriteAccess->CopyScanline(nRow, pPdfLine, ScanlineFormat::N32BitTcBgra, nStride); + } } + + rBitmaps.emplace_back(std::move(aBitmap)); + FPDFBitmap_Destroy(pPdfBitmap); + FPDF_ClosePage(pPdfPage); } - rBitmap = aBitmap; - FPDFBitmap_Destroy(pPdfBitmap); - FPDF_ClosePage(pPdfPage); FPDF_CloseDocument(pPdfDocument); FPDF_DestroyLibrary(); - return true; + return rBitmaps.size(); } /// Decide if PDF data is old enough to be compatible. @@ -180,10 +189,9 @@ bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream, return rOutStream.good(); } #else -bool generatePreview(SvStream&, Bitmap&, - sal_uInt64, sal_uInt64) +size_t generatePreview(SvStream&, std::vector<Bitmap>&, sal_uInt64, sal_uInt64, size_t, int) { - return true; + return 0; } bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream, @@ -205,9 +213,12 @@ bool ImportPDF(SvStream& rStream, Bitmap& rBitmap, sal_uInt64 nPos, sal_uInt64 nSize) { // Get the preview of the first page. - if (!generatePreview(rStream, rBitmap, nPos, nSize)) + std::vector<Bitmap> aBitmaps; + if (generatePreview(rStream, aBitmaps, nPos, nSize, 0, 1) != 1) return false; + rBitmap = aBitmaps[0]; + // Save the original PDF stream for later use. SvMemoryStream aMemoryStream; if (!getCompatibleStream(rStream, aMemoryStream, nPos, nSize)) |