Kaydet (Commit) 3102b8c8 authored tarafından Ashod Nakashian's avatar Ashod Nakashian Kaydeden (comit) Ashod Nakashian

vcl: support rendering multiple PDF pages to bitmap

Change-Id: Id42ecabcad90dde84475a01e5df4ed94f221f5ce
Reviewed-on: https://gerrit.libreoffice.org/51255Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarAshod Nakashian <ashnakash@gmail.com>
üst ac6e6753
......@@ -58,8 +58,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;
......@@ -76,45 +77,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)
{
BitmapScopedWriteAccess 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);
BitmapScopedWriteAccess 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.
......@@ -182,10 +191,11 @@ 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 nPos, sal_uInt64 nSize,
size_t nFirstPage = 0, int nLastPage = 0)
{
return true;
return false;
}
bool getCompatibleStream(SvStream& rInStream, SvStream& rOutStream,
......@@ -207,9 +217,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))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment