Convert an image to PDF on the iPhone and iPad
April 22nd, 2011
A reader asked a me about image to PDF conversion a few days ago and I promised him an article, so here it is.
Image to PDF conversion is based on Quartz API. Using Quartz we can create PDF files and add content to them, the conversion actually means drawing the image on a PDF page.
Let's begin.
First we compute the size of the PDF page. Based on the image size and the resolution we want to draw the image, the page size is computed like this (for flexibility different horizontal and vertical resolutions are supported):
1 2 | double pageWidth = image.size.width * image.scale * 72 / horzRes; double pageHeight = image.size.height * image.scale * 72 / vertRes; |
Now we're ready to create the PDF file. It can be created directly on disk or in memory. For flexibility let's create it in memory.
1 2 3 4 5 6 | NSMutableData *pdfFile = [[NSMutableData alloc] init]; CGDataConsumerRef pdfConsumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)pdfFile); // The page size matches the image, no white borders. CGRect mediaBox = CGRectMake(0, 0, pageWidth, pageHeight); CGContextRef pdfContext = CGPDFContextCreate(pdfConsumer, &mediaBox, NULL); |
The PDF context is created, we can now perform the conversion:
1 2 3 | CGContextBeginPage(pdfContext, &mediaBox); CGContextDrawImage(pdfContext, mediaBox, [image CGImage]); CGContextEndPage(pdfContext); |
The work is done, finalize the PDF file and release the used objects.
1 2 | CGContextRelease(pdfContext); CGDataConsumerRelease(pdfConsumer); |
The PDF file is now available in the pdfFile variable.
I placed all the code above in the convertImageToPDF:withHorizontalResolution:verticalResolution: static method in the PDFImageConverter utility class, it can be used like this:
1 2 3 4 | NSData *pdfData = [PDFImageConverter convertImageToPDF: image withHorizontalResolution: 300 verticalResolution: 300]; NSString *path = [NSHomeDirectory() stringByAppendingPathComponent: @"Documents/image.pdf"]; [pdfData writeToFile:path atomically:NO]; |
Sometimes it is necessary to convert an image to PDF and use a predefined page size, such as Letter or A4. Also a maximum bounding rectangle can be specified for the image, so it is placed at a specific position on the page and it does not get out of the page. In this situation the image size must be adjusted (increased resolution) to make sure the image fits the given rectangle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | double imageWidth = image.size.width * image.scale * 72 / resolution; double imageHeight = image.size.height * image.scale * 72 / resolution; double sx = imageWidth / boundsRect.size.width; double sy = imageHeight / boundsRect.size.height; // At least one image edge is larger than maxBoundsRect, reduce its size. if ((sx > 1) || (sy > 1)) { double maxScale = sx > sy ? sx : sy; imageWidth = imageWidth / maxScale; imageHeight = imageHeight / maxScale; } // Put the image in the top left corner of the bounding rectangle CGRect imageBox = CGRectMake( boundsRect.origin.x, boundsRect.origin.y + boundsRect.size.height - imageHeight, imageWidth, imageHeight); |
Having the final box, the image can be converted to PDF using the code in the first half of the article.
The code for the new conversion method is placed in the convertImageToPDF:withResolution:maxBoundsRect:pageSize: static method in the PDFImageConverter utility class, it is used like this:
1 2 3 4 5 6 7 8 | CGSize pageSize = CGSizeMake(612, 792); CGRect imageBoundsRect = CGRectMake(50, 50, 512, 692); NSData *pdfData = [PDFImageConverter convertImageToPDF: image withResolution: 300 maxBoundsRect: imageBoundsRect pageSize: pageSize]; NSString *path = [NSHomeDirectory() stringByAppendingPathComponent: @"Documents/image.pdf"]; [pdfData writeToFile:path atomically:NO]; |
Source code: PDFImageConverter.zip
April 29th, 2011 - 07:47
It would be possible to add a digital signature (certificate, hash, etc) to a PDF on the iPhone?
Congratulations on the blog
April 29th, 2011 - 12:47
Current PDF API in iOS does not support adding new objects in a PDF file, such as digital signatures, annotations, etc. Let’s hope this will be fixed in iOS 5
July 11th, 2011 - 20:23
If I convert a PDF page to image, add some ink to it, and convert the image back to PDF, will it grow in size substantially? Is there an easy way to replace this new page in the original PDF document?
July 11th, 2011 - 20:38
The growth in size depends on the source PDF page. It is text and image based, the growth in size can be significant. If you convert the page to image at a lower resolution to get a smaller image, when you create the new page from the image it will look pixelated. If you convert the page to image at a higher resolution you will have an image with a higher quality but also greater size. I recommend to add the ink directly to the existing PDF page. You can create a CGPDFDocumentRef from your original PDF file, update the document’s pages and then save the new document.
July 11th, 2011 - 20:56
Thanks!
August 1st, 2011 - 21:10
We’re trying to save the ink in a separate context and send it up to the server with a document id where it will be combined with the original document. How can we determine what page of the PDF document the user is viewing?
August 3rd, 2011 - 09:53
In your application you should have a variable that stores the current displayed page, because you control what page is displayed on the screen.
September 16th, 2011 - 10:48
Thank you for your article. This works perfectly.But I am trying to convert tiff images to pdf. Actually it converts the first page of tiff images to pdf. Do you know how to convert multi-paged tiff images to pdf ?
September 27th, 2011 - 22:01
There is the NSTiffSplitter on GitHub (https://github.com/Sharrp/NSTiffSplitter) that lets you split multi frame TIFF image into single frames. You can draw then each frame on a PDF page.
May 11th, 2013 - 09:29
CEM, Have you found any soluion for the same?
March 8th, 2012 - 17:32
Thanks for this great post! I’m trying to take an image from the device’s camera and convert it to PDF. I’m using this method to grab the image and convert it with your class:
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *pdfData = [PDFImageConverter convertImageToPDF: image
withHorizontalResolution: 300 verticalResolution: 300];
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent: @"Documents/new.pdf"];
[pdfData writeToFile:path atomically:NO];
}
The issue is the image is saved rotated and it looks distorted. It works fine with any image that is not taken from the camera. Any ideas?
March 9th, 2012 - 19:31
If you can send me a sample project that I can run and reproduce the problem, I will investigate it and I’ll get back to you.
August 29th, 2012 - 06:20
Can i use this code to convert SVG images to PDF .
August 29th, 2012 - 09:16
No, this code cannot be used to convert SVG to PDF.
August 29th, 2012 - 06:22
Can you provide a code that converts SVG File to PDF.
August 29th, 2012 - 09:16
I do not have such code.
January 19th, 2013 - 10:20
It’s a nice article. One thing what I observed was the UIImage will be converted to an image in PDF rather than actual PDF . Is there any way to convert it into actual PDF text.
February 9th, 2013 - 19:43
Very helpful post as I have posted this on our forum so other people can find out also on image to PDF creation
February 10th, 2013 - 21:36
Thank you.
February 14th, 2013 - 12:48
Hi,
How can i make multiple image into a single pdf. I tried ur code. but it works oly for 1 image. The image which i choose last alone appears in the pdf but i want all the images which i choose from the photo library to be displayed in the pdf. please help me
February 14th, 2013 - 21:16
You have to call begin page, draw image, end page for each image you want to draw in the pdf file.
February 15th, 2013 - 07:55
Hi,
I could understatnd what you say. But i dont know how to implement as i am new to iOS . so, please help me with some sample code for multiple images in single pdf.