How to insert a dynamically generated bitmap into PDF document using PDFsharp?

6.4k views Asked by At

I am trying to use PDFsharp to insert a dynamically generated bitmap of a QR Code in to a PDF document. I don't want to save the bitmap to the file but just want to insert it into the PDF. The problem I'm having is the DrawImage command is looking for a string where the image file is located. But I don't want to save the file, I just want to insert it into the PDF document. Is there a way of doing this?

var QRCode_BMP = _generalCode.QR_CodeGenerator(AddReviewPath); //This generates the bitmap
MemoryStream streamQR = new MemoryStream();
QRCode_BMP.Save(streamQR, System.Drawing.Imaging.ImageFormat.Jpeg); //save bitmap into memory stream in jpeg format System.Drawing.Image QR_Jpeg = System.Drawing.Image.FromStream(streamQR);// save memory stream to image file
XImage xImage = XImage.FromGdiPlusImage(QR_Jpeg);
gfx = XGraphics.FromPdfPage(page);

DrawImage(gfx, xImage, 0, 0, 100, 100); //This is not working

QRCode_BMP.Dispose();
streamQR.Close();
gfx.Dispose();
3

There are 3 answers

0
I liked the old Stack Overflow On

You create a QR code in QRCode_BMP and then you create an XImage from QR_Jpeg and write it is not working.

QRCode_BMP is only used to create a stream that is never used. We don't see where QR_Jpeg is coming from.

Provide a complete sample.

BTW: You can use XImage.FromStream to use the stream you created.

P.S.: IMHO JPEG is a bad choice for QR codes. Just use BMP and PDFsharp will use a lossless compression.

0
SourceSeeker On

Using XImage.FromStream like @I liked the old Stack Overflow mentioned, in your posted code you should be able to just use:

var QRCode_BMP = _generalCode.QR_CodeGenerator(AddReviewPath); //This generates the bitmap
MemoryStream streamQR = new MemoryStream();
QRCode_BMP.Save(streamQR, System.Drawing.Imaging.ImageFormat.Jpeg); //save bitmap into memory stream in jpeg format System.Drawing.Image QR_Jpeg = System.Drawing.Image.FromStream(streamQR);// save memory stream to image file
//XImage xImage = XImage.FromGdiPlusImage(QR_Jpeg); // <-- Removed
gfx = XGraphics.FromPdfPage(page);
gfx.DrawImage(XImage.FromStream(streamQR), 0, 0, 100, 100); // <-- Added

//DrawImage(gfx, xImage, 0, 0, 100, 100); //This is not working // <-- Removed

QRCode_BMP.Dispose();
streamQR.Close();
gfx.Dispose();

For general usage of streams for XGraphics.DrawImage (library PDFSharp) here's some code I use to print SVG vector path data to PDF:

System.Windows.Shapes.Path path = new System.Windows.Shapes.Path();

// YouTube like button SVG vector path data:
path.Data = Geometry.Parse("M12.42,14A1.54,1.54,0,0,0,14,12.87l1-4.24C15.12,7.76,15,7,14,7H10l1.48-3.54A1.17,1.17,0,0,0,10.24,2a1.49,1.49,0,0,0-1.08.46L5,7H1v7ZM9.89,3.14A.48.48,0,0,1,10.24,3a.29.29,0,0,1,.23.09S9,6.61,9,6.61L8.46,8H14c0,.08-1,4.65-1,4.65a.58.58,0,0,1-.58.35H6V7.39ZM2,8H5v5H2Z");
// Visual check of the path:
// https://yqnn.github.io/svg-path-editor/

// Color area bordered through path of SVG vector:
path.Fill = new SolidColorBrush(Colors.Black);

// Upscale path, if final image is blurry:
double scale = 2;
path.RenderTransform = new ScaleTransform(scale, scale);

Rect bounds = path.Data.GetRenderBounds(null);

// Increase render bounds (here: "+ 4"), if parts of the path in the final image are cut off (test it with "scale = 1" before upscaling):
bounds.Width = (bounds.Width + 4) * scale;
bounds.Height = (bounds.Height + 4) * scale;

path.Measure(bounds.Size);
path.Arrange(bounds);

RenderTargetBitmap bitmap = new RenderTargetBitmap(
    (int)bounds.Width, (int)bounds.Height, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(path);

// Transparent areas are replaced with black pixels when using a "BmpBitmapEncoder", so instead use a "PngBitmapEncoder":
PngBitmapEncoder encoderPng = new PngBitmapEncoder();
encoderPng.Frames.Add(BitmapFrame.Create(bitmap));
using (MemoryStream stream = new MemoryStream())
{
    encoderPng.Save(stream);
    
    // Draw image to PDF using "XGraphics.DrawImage":
    gfx.DrawImage(XImage.FromStream(stream), 10, 100, 14.05, 12.05);
}
3
mkavici On

This is how I made it work;

        PdfDocument pdf = PdfGenerator.GeneratePdf("<b>some html here</b>", PageSize.A4);

        QRCodeGenerator qrGenerator = new QRCodeGenerator();
        QRCodeData qrCodeData = qrGenerator.CreateQrCode("some text here", QRCodeGenerator.ECCLevel.Q);
        QRCode qrCode = new QRCode(qrCodeData);

        Bitmap qrCodeImage = qrCode.GetGraphic(10);


        PdfPage page = pdf.Pages[0]; //I will add it to 1st page

        // Get an XGraphics object for drawing
        XGraphics gfx = XGraphics.FromPdfPage(page);

        XImage image = XImage.FromGdiPlusImage(qrCodeImage); //you can use XImage.FromGdiPlusImage to get the bitmap object as image (not a stream)
        gfx.DrawImage(image, 50, 50, 150, 150);
//save your pdf, dispose other objects