I am creating an Azure function to convert a png (stored in the blob store) to a pdf and upload it to the blob store. My code is failing for pngs over ~4000 pixels. I have tried to amend my method for converting the png stream to pdf stream to take into account that I may handle larger pngs hence, I introduced chunking to manage this and I am converting the streams to help with memory usage.
I have confirmed that the the signature of the png is correct (89 50 4E 47 0D 0A 1A 0A) however, I still get a "System.InvalidOperationException: Unsupported image format." What other reasons could cause this? I have reset the stream position to 0 as thats all I have read elsewhere online to fix it. I am able to open the png to confirm that it is not corrupt or empty.
[2025-04-23T08:13:37.124Z] ConvertPngToPdf function started.
[2025-04-23T08:13:37.132Z] Request body read successfully.
[2025-04-23T08:13:37.273Z] Parsed URLs from request body.
[2025-04-23T08:13:37.313Z] Retrieved blob container.
[2025-04-23T08:13:37.319Z] Processing URL... 989f6b77-cec9-4f78-8f89-39fe1a1b165b.png
[2025-04-23T08:13:37.846Z] Blob stream opened.
[2025-04-23T08:13:37.859Z] Converting PNG stream to PDF stream.
[2025-04-23T08:13:37.894Z] Starting chunk-based PNG to PDF conversion.
[2025-04-23T08:13:38.384Z] Read 2853026 bytes from PNG stream.
[2025-04-23T08:13:42.492Z] Stream length: 2853026
[2025-04-23T08:13:45.838Z] Stream header: 89-50-4E-47-0D-0A-1A-0A
[2025-04-23T08:13:54.478Z] Image loaded successfully. Dimensions: 4965x3511
[2025-04-23T08:14:40.226Z] An error occurred during PNG to PDF conversion.
[2025-04-23T08:14:40.229Z] Result: An error occurred during PNG to PDF conversion.
Please see this code for my method to convert the png stream to pdf stream. The error is thrown on the line containing "using (var xImage = XImage.FromStream(reconstructedStream))"
/// <summary>
/// Convert png stream to pdf.
/// </summary>
/// <param name="pngStream">Png stream.</param>
/// <param name="pdfStream">Pdf stream.</param>
[SupportedOSPlatform("windows")]
public void ConvertPngStreamToPdfStream(Stream pngStream, Stream pdfStream)
{
try
{
this.log.LogInformation("Starting chunk-based PNG to PDF conversion.");
// Define the chunk size (e.g., 4MB)
const int chunkSize = 4 * 1024 * 1024; // 4 MiB
byte[] buffer = new byte[chunkSize];
using var reconstructedStream = new MemoryStream();
// Read the PNG stream in chunks and write to a memory stream
int bytesRead;
while ((bytesRead = pngStream.Read(buffer, 0, buffer.Length)) > 0)
{
reconstructedStream.Write(buffer, 0, bytesRead);
this.log.LogInformation("Read {BytesRead} bytes from PNG stream.", bytesRead);
}
// Reset the position of the reconstructed stream
this.log.LogInformation("Stream length: {Length}", reconstructedStream.Length);
reconstructedStream.Position = 0;
byte[] buffer2 = new byte[8];
int bytesRead2 = reconstructedStream.Read(buffer2, 0, buffer2.Length);
this.log.LogInformation("Stream header: {Header}", BitConverter.ToString(buffer2, 0, bytesRead2));
reconstructedStream.Position = 0;
// Load the image from the reconstructed stream
using (var image = Image.FromStream(reconstructedStream))
{
this.log.LogInformation("Image loaded successfully. Dimensions: {Width}x{Height}", image.Width, image.Height);
// Create a new PDF document
using (var document = new PdfDocument())
{
// Add a page to the PDF document
var page = document.AddPage();
page.Width = XUnit.FromPoint(image.Width);
page.Height = XUnit.FromPoint(image.Height);
// Draw the image onto the PDF page
using (var gfx = XGraphics.FromPdfPage(page))
{
reconstructedStream.Position = 0;
using (var xImage = XImage.FromStream(reconstructedStream))
{
gfx.DrawImage(xImage, 0, 0, image.Width, image.Height);
}
}
// Save the PDF document to the provided PDF stream
document.Save(pdfStream, false);
this.log.LogInformation("PDF saved successfully to the provided stream.");
}
}
// Reset the position of the PDF stream to the beginning
pdfStream.Position = 0;
}
catch (ArgumentException ex)
{
this.log.LogError(ex, "Invalid image format or corrupted PNG stream.");
throw;
}
catch (Exception ex)
{
this.log.LogError(ex, "An error occurred during PNG to PDF conversion.");
throw;
}
}
System.InvalidOperationException: Unsupported image format.
This issue occurs because PdfSharpCore
's XImage.FromStream()
has limited support for large or complex PNG formats, especially in environments like Azure Functions.
First we have to Convert the PNG stream to a JPEG format in-memory before passing it to PdfSharpCore
.
Function code:
public class ConvertPngToPdfFunction
{
private readonly ILogger<ConvertPngToPdfFunction> _logger;
private readonly IConfiguration _configuration;
public ConvertPngToPdfFunction(ILogger<ConvertPngToPdfFunction> logger, IConfiguration configuration)
{
_logger = logger;
_configuration = configuration;
}
[Function("ConvertPngToPdfFunction")]
public async Task Run([
BlobTrigger("png-images/{name}", Connection = "AzureWebJobsStorage")
] Stream pngStream,
string name)
{
_logger.LogInformation($"Triggered by PNG blob: {name}");
try
{
// Load the PNG image using ImageSharp
using var image = await Image.LoadAsync(pngStream);
// Convert PNG to JPEG in-memory
using var jpegStream = new MemoryStream();
await image.SaveAsJpegAsync(jpegStream);
jpegStream.Position = 0;
// Create a PDF from the JPEG stream
using var pdfStream = new MemoryStream();
var document = new PdfDocument();
var page = document.AddPage();
using var gfx = XGraphics.FromPdfPage(page);
using var xImage = XImage.FromStream(() => jpegStream);
page.Width = xImage.PointWidth;
page.Height = xImage.PointHeight;
gfx.DrawImage(xImage, 0, 0);
document.Save(pdfStream);
pdfStream.Position = 0;
// Upload to Blob Storage
var connectionString = _configuration["AzureWebJobsStorage"];
var blobClient = new BlobContainerClient(connectionString, "pdfs");
await blobClient.CreateIfNotExistsAsync();
var outputBlob = blobClient.GetBlobClient($"{Path.GetFileNameWithoutExtension(name)}.pdf");
await outputBlob.UploadAsync(pdfStream, overwrite: true);
_logger.LogInformation($"Successfully converted and uploaded PDF: {outputBlob.Uri}");
}
catch (Exception ex)
{
_logger.LogError(ex, $"Error converting PNG to PDF for {name}");
throw;
}
}
}
By using this code successfully converted the file and downloaded.
Check below for the function logs:
Output:
[2025-04-23T10:22:01.238Z] Executing 'ConvertPngToPdfFunction' (Reason='New blob detected: test5/sample-image.png', Id=d2f12a67-a3fc-4ec7-93d5-bfa7e99a9e0c)
[2025-04-23T10:22:01.238Z] Triggered by PNG blob: sample-image.png
[2025-04-23T10:22:01.954Z] PNG image loaded successfully with ImageSharp. Dimensions: 4965x3511
[2025-04-23T10:22:02.486Z] PNG converted to JPEG format in memory.
[2025-04-23T10:22:03.029Z] JPEG image embedded into PDF document.
[2025-04-23T10:22:03.372Z] PDF stream created successfully.
[2025-04-23T10:22:04.005Z] Blob container 'pdfs' verified/created.
[2025-04-23T10:22:04.362Z] PDF uploaded to Blob Storage: https://sampleteststore65354.blob.core.windows.net/pdfs/sample-image.pdf
[2025-04-23T10:22:04.362Z] Successfully converted and uploaded PDF: https://sampleteststore65354.blob.core.windows.net/pdfs/sample-image.pdf
[2025-04-23T10:22:04.365Z] Executed 'ConvertPngToPdfFunction' (Succeeded, Id=d2f12a67-a3fc-4ec7-93d5-bfa7e99a9e0c)