I'm rendering a UIWebView's layer into a graphics context and then using the UIGraphicsBeginPDFPageWithInfo() family of functions to include it in a PDF.
My problem is that the output includes an extra set of gray lines that aren't part of my data set. I'm hoping someone can shed some light on where they're coming from.
An example of the output is included below. The HTML document that is being rendered contains nothing but the text 'THIS IS A TEST' - the boxes you see are coming from the rendering process somewhere. When rendered on the screen, it's just black text on a white screen - no lines/boxes.
Anyone have any ideas what's going on? Thanks!
Here's the code I'm using to render this web view as a PDF:
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, CGRectZero, nil);
CGRect viewBounds = webView.bounds;
UIGraphicsBeginPDFPageWithInfo(viewBounds, nil);
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
[webView.layer renderInContext:pdfContext];
UIGraphicsEndPDFContext();
Also, here's a screenshot of what I'm seeing for output:
I ran into the same issue. It would happen whenever trying to render the UIWebView into the PDF context, and frame width > 512. I was not able to diagnose the exact issue, but worked around it by rendering the UIWebView into a UIImage, and then rendering the UIImage into the pdf context.
Code as:
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kWidth, kHeight), nil);
CGContextRef currentContext = UIGraphicsGetCurrentContext();
UIImage* image = nil;
UIGraphicsPushContext(currentContext);
UIGraphicsBeginImageContext(self.webview.frame.size);
{
[self.webview.layer renderInContext: UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
}
UIGraphicsEndImageContext();
UIGraphicsPopContext();
[image drawInRect:CGRectMake(0, 0, kWidth, kHeight)];
Related
I'm rendering PDF content into a UIView and I'm seeing that the text provided by the PDF is blurry when zoomed.
The way I'm rendering the text is as follows
CGSize size = CGSizeMake(96, 9); // These numbers come from the PDF
NSString* text = #"Text to render";
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
[text drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
This UIImage has the correct size and when I inspect it via XCode it is crisp.
When I call CGContextDrawImage below
CGRect widgetRect = CGRectMake(0,0,180,90);
CGContextDrawImage(mainContext, size, image.CGImage);
The result is blurry.
Notes:
The mainContext above has it's origin lower left so that's why I render text into a separate context and draw an image.
The UIView has a contentScaleFactor of 3 and the mainContext has a size to match that scale.
I looked at CGContextDrawImage draws large images very blurry and it doesn't address my problem.
I can't reproduce this problem outside my app in it's own.
This last part shows me that the problem is somewhere in the app code so I' hoping for hints and ideas about where to look in the rendering pipeline and how to debug.
EDIT:
Updated the calll to CGContextDrawImage to use the correct size.
I am trying to generate a PDF report from a UIWebView. Using Graphics Contexts I can get the images of screen frame and draw it in PDF.
Problems in curent method are,
Images are blurred (bad quality)
So the report pdf is not readable.
How can I get a high quality images of a screen frame? Or is there any other better solutions for my problem?
P.S. Report includes multiple background colors and images, I think it is hard to directly draw them in PDF.
+ (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, webview.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
[webview.layer renderInContext:pdfContext];
UIGraphicsEndPDFContext();
Have you tried like this?
I am trying to take a screenshot of a webView and change it to PDF. I have used this method: http://www.ioslearner.com/wp-content/uploads/2012/01/HtmlToPdfDemo.zip
I mean the code in this project. It works fine for iPad but it doesn't covers full width for iPhone. I have used -sizeThatFits: for the webView, but that gives unreadable images for large html pages. I have searched a lot but all I could find out was in Android.. not iPhone. Please help me.Thanks!
By changing the webView's frame before you render it, you will be able to capture the entire page.
NSMutableData *pdfData = [NSMutableData data];
CGRect contentRect = CGRectMake(0, 0, webView.scrollView.contentSize.width, webView.scrollView.contentSize.height);
[webView setFrame:contentRect];
UIGraphicsBeginPDFContextToData(pdfData, contentRect, nil);
UIGraphicsBeginPDFPage();
CGContextRef context = UIGraphicsGetCurrentContext();
[webView.layer renderInContext:context];
UIGraphicsEndPDFContext();
I am having some trouble with saving a PDF page as UIImage...the pdf is loaded from the internet and it has one page(original PDF has been splitted in sever)...but the converted image sometimes is cropped...sometimes it is small and leave white space when it is putted on UIImageview...
here is the code
-(UIImage *)imageFromPdf:(NSString *) pdfUrl{
NSURL *pdfUrlStr=[NSURL URLWithString:pdfUrl];
CFURLRef docURLRef=(CFURLRef)pdfUrlStr;
UIGraphicsBeginImageContext(CGSizeMake(768, 1024)); //840, 960
NSLog(#"save begin");
CGContextRef context = UIGraphicsGetCurrentContext();
//CFURLRef pdfURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("/file.pdf"), NULL, NULL);
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL(docURLRef);
NSLog(#"save complete");
CGContextTranslateCTM(context, 0.0, 900);//320
CGContextScaleCTM(context, 1.0, -1.0);
CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
CGContextSaveGState(context);
CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, CGRectMake(0, 0, 768, 1024), 0, true);
CGContextConcatCTM(context, pdfTransform);
CGContextDrawPDFPage(context, page);
CGContextRestoreGState(context);
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
btw I have prepared my UIImageview by coding like this
self.PDFImageVIew.contentMode = UIViewContentModeScaleAspectFit;
self.PDFImageVIew.clipsToBounds = YES;
I just want this image perfectly fitted on UIImageview and may be its reducing the quality of image...can you have suggesion how can I keep the quality also? please help and give me some suggestion
thanks
CGContextTranslateCTM(context, 0.0, 900);//320
Here generally last parameter of translate operation should be the height of context or height of rectangle for which you creating image. So, i think it should be 1024(You have taken height of image context is 1024 so here i am assuming that status bar is not present). This may eliminate the issue of cropping. Some more things that i have noted on your code you should have to save the state of graphics before any operation on context. You have are saving it but after few operations.
Above code will try to make it height fit so if height of actual page is bigger than your context height then it will be scaled down. so you can obviously see white space around page.
One more thing if your original pdf page have white space in it then there is no way to eliminate it as far as i know.
How is iBooks able to create PDF page thumbnails so fast on first load? I tried using CGContext functions to draw the page and then resize it to get a thumbnail. But this approach takes way to long. Is there an efficient way to get thumbnails of PDF pages?
Thanks in advance,
Anupam
First get all your PDF files Path in an array[here ie:pdfs].Then if you want to show all these PDF thumbnails in UICollectionView,just pass the index obtained from the collection view Delegate Method "CellForRowAtIndexPath" to the following,
-(UIImage *)GeneratingIcon:(int)index
{
NSURL* pdfFileUrl = [NSURL fileURLWithPath:[pdfs objectAtIndex:index]];
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((__bridge CFURLRef)pdfFileUrl);
CGPDFPageRef page;
CGRect aRect = CGRectMake(0, 0, 102, 141); // thumbnail size
UIGraphicsBeginImageContext(aRect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
UIImage* IconImage;
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0.0, aRect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetGrayFillColor(context, 1.0, 1.0);
CGContextFillRect(context, aRect);
// Grab the first PDF page
page = CGPDFDocumentGetPage(pdf, 1);
CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, aRect, 0, true);
// And apply the transform.
CGContextConcatCTM(context, pdfTransform);
CGContextDrawPDFPage(context, page);
// Create the new UIImage from the context
IconImage = UIGraphicsGetImageFromCurrentImageContext();
CGContextRestoreGState(context);
UIGraphicsEndImageContext();
CGPDFDocumentRelease(pdf);
return IconImage;
}
Hope this would be fast enough to create thumbnail images for the PDF.
Disclaimer: I have not checked if this is faster or not.
There are some built in methods in ImageIO that are specialized in creating thumbnails. These methods should be optimized for creating thumbnails. You would need to add ImageIO.framework to your project and #import <ImageIO/ImageIO.h> in your code.
// Get PDF-data
NSData *pdfData = [NSData dataWithContentsOfURL:myFileURL];
// Get reference to the source
// NOTE: You are responsible for releasing the created image source
CGImageSourceRef imageSourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)pdfData, NULL);
// Configure how to create the thumbnail
// NOTE: You should change the thumbnail size depending on how large thumbnails you need.
// 512 pixels is probably way too big. Smaller sizes will be faster.
NSDictionary* thumbnailOptions =
#{(id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue,
(id)kCGImageSourceCreateThumbnailFromImageIfAbsent: (id)kCFBooleanTrue,
(id)kCGImageSourceThumbnailMaxPixelSize: #512}; // no more than 512 px wide or high
// Create thumbnail
// NOTE: You are responsible for releasing the created image
CGImageRef imageRef =
CGImageSourceCreateThumbnailAtIndex(imageSourceRef,
0, // index 0 of the source
(__bridge CFDictionaryRef)thumbnailOptions);
// Do something with the thumbnail ...
// Release the imageRef and imageSourceRef
CGImageRelease (imageRef);
CFRelease(imageSourceRef);