3

I'm using the Syncfusion PDF viewer for Xamarin Forms to display a collection of PDF files and it seems the conversion from PDF to PNG (to extract the first page (the cover) of the PDF file to show it, to the user, into a carousel) didn't work in Xamarin [see https://www.syncfusion.com/kb/9112/how-to-convert-pdf-to-png]

I wonder if there is a way to convert PDF into PNG on the Xamarin platform or if I should convert it on the server side.

Thank you.

  • 1
    About converting pdf file to png, please look at https://stackoverflow.com/questions/23905169/how-to-convert-pdf-files-to-image – Cherry Bu - MSFT Nov 28 '18 at 08:48
  • 1
    I know _how to_ convert PDF into png (using `ImageMagik`). As I'm working with Xamarin Forms, my question was about doing this on the device (on the fly), an Android/iOs smartphone/tablet or if I must do it on a web server side and provide a download link to the device. – Crusty Applesniffer Nov 29 '18 at 08:18

1 Answers1

12

You can export PDF pages to images without using Syncfusion PDF Viewer control by consuming the PdfRenderer , CGPDFDocument, and PdfDocument classes.

Xamarin.Forms.Android:

//initialize PDFRenderer by passing PDF file from location.
PdfRenderer renderer = new PdfRenderer(GetSeekableFileDescriptor()); 
int pageCount = renderer.PageCount;
for(int i=0;i<pageCount;i++)
{
// Use `openPage` to open a specific page in PDF.
Page page =  renderer.OpenPage(i); 
//Creates bitmap
Bitmap bmp = Bitmap.CreateBitmap(page.Width, page.Height, Bitmap.Config.Argb8888); 
//renderes page as bitmap, to use portion of the page use second and third parameter
page.Render(bmp, null, null, PdfRenderMode.ForDisplay);
//Save the bitmap
SaveImage(bmp);
page.Close();
}

//Method to retrieve PDF file from the location
private ParcelFileDescriptor GetSeekableFileDescriptor()
{
ParcelFileDescriptor fileDescriptor = null;
try
{
string root = Android.OS.Environment.ExternalStorageDirectory.ToString()+ "/Syncfusion/sample.pdf";
fileDescriptor = ParcelFileDescriptor.Open(new Java.IO.File(root),ParcelFileMode.ReadOnly
);
}
catch (FileNotFoundException e)
{

}
return fileDescriptor;
}

Xamarin.Forms.iOS:

public void ConvertToImage(Stream fileStream)  //Pass PDF stream

{
MemoryStream stream = new MemoryStream();
// Create memory stream from file stream.
fileStream.CopyTo(stream);
// Create data provider from bytes.
CGDataProvider provider = new CGDataProvider(stream.ToArray());
try
{
//Load a PDF file.
m_pdfDcument = new CGPDFDocument(provider);
}
catch (Exception)
{
}
//Get PDF's page and convert as image.
using (CGPDFPage pdfPage = m_pdfDcument.GetPage(2))
{
//initialise image context.
UIGraphics.BeginImageContext(pdfPage.GetBoxRect(CGPDFBox.Media).Size);
// get current context.
CGContext context = UIGraphics.GetCurrentContext();
context.SetFillColor(1.0f, 1.0f, 1.0f, 1.0f);
// Gets page's bounds.
CGRect bounds = new CGRect(pdfPage.GetBoxRect(CGPDFBox.Media).X, pdfPage.GetBoxRect(CGPDFBox.Media).Y, pdfPage.GetBoxRect(CGPDFBox.Media).Width, pdfPage.GetBoxRect(CGPDFBox.Media).Height);
if (pdfPage != null)
{
context.FillRect(bounds);
context.TranslateCTM(0, bounds.Height);
context.ScaleCTM(1.0f, -1.0f);
context.ConcatCTM(pdfPage.GetDrawingTransform(CGPDFBox.Crop, bounds, 0, true));
context.SetRenderingIntent(CGColorRenderingIntent.Default);
context.InterpolationQuality = CGInterpolationQuality.Default;
// Draw PDF page in the context.
context.DrawPDFPage(pdfPage);
// Get image from current context.
pdfImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
}
}
// Get bytes from UIImage object.
using (var imageData = pdfImage.AsPNG())
{
imageBytes = new byte[imageData.Length];
System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, imageBytes, 0, Convert.ToInt32(imageData.Length));
//return bytes;
}
//Create image from bytes.
imageStream = new MemoryStream(imageBytes);
//Save the image. It is a custom method to save the image
Save("PDFtoImage.png", "image/png", imageStream);
}

Xamarin.Forms.UWP

public async void ConvertToImage(Stream fileStream) //Pass PDF stream
{
StorageFile file = null;
//Creates file picker to choose PDF file.
FileOpenPicker filePicker = new FileOpenPicker();

filePicker.FileTypeFilter.Add(".pdf");

filePicker.ViewMode = PickerViewMode.Thumbnail;

filePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;

filePicker.SettingsIdentifier = "picker1";

filePicker.CommitButtonText = "Open Pdf File";
//Open file picker option
file = await filePicker.PickSingleFileAsync();

// Load selected PDF file from the file picker.
PdfDocument pdfDocument = await PdfDocument.LoadFromFileAsync(file);

if (pdfDocument != null && pdfDocument.PageCount > 0)
{
for (int pageIndex = 0; pageIndex < pdfDocument.PageCount; pageIndex++)
{
//Get page from a PDF file.
var pdfPage = pdfDocument.GetPage((uint)pageIndex);

if (pdfPage != null)
{
//Create temporary folder to store images.
StorageFolder tempFolder = ApplicationData.Current.TemporaryFolder;
//Create image file.
StorageFile destinationFile = await KnownFolders.CameraRoll.CreateFileAsync(Guid.NewGuid().ToString() + ".jpg");

if (destinationFile != null)
{
IRandomAccessStream randomStream = await destinationFile.OpenAsync(FileAccessMode.ReadWrite);
//Crerate PDF rendering options
PdfPageRenderOptions pdfPageRenderOptions = new PdfPageRenderOptions();

pdfPageRenderOptions.DestinationWidth = (uint)(300);
// Render the PDF's page as stream.
await pdfPage.RenderToStreamAsync(randomStream, pdfPageRenderOptions);

await randomStream.FlushAsync();
//Dispose the random stream
randomStream.Dispose();
//Dispose the PDF's page.
pdfPage.Dispose();
}
}
}
}
}

I work for Syncfusion.

Karthikk
  • 326
  • 2
  • 7