some problems about html to pdf in iOS - objective-c

Recently i'm trouble in some problems about html convert to PDF files.
I find use the followed method to convert is not quickly enough and the PDF files created are big (the file size is about 2M - 5M / 7 pages ) . And some html pages are inconsistent with the converted PDF files.
Are there any methods to control the pdf size?
Are there any methods can convert it more quickly?
Are there any methods can solve the pdf files be inconsistent with the html pages in webview ?
I would very much appreciate your help. Thank you.
- (NSData*) printToPDF
{
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );
[self prepareForDrawingPages: NSMakeRange(0, self.numberOfPages)];
CGRect bounds = UIGraphicsGetPDFContextBounds();
for ( int i = 0 ; i < self.numberOfPages ; i++ )
{
UIGraphicsBeginPDFPage();
[self drawPageAtIndex: i inRect: bounds];//
}
UIGraphicsEndPDFContext();
return pdfData;
}

Related

How to combine two pdfs without losing any information?

My goal is to combine two PDFs. One has 10 pages, and another has 6 pages, so the output should be 16 pages. My approach is to load both PDFs into two NSData stored in an NSMutableArray.
Here is my saving method:
NSMutableData *toSave = [NSMutableData data];
for(NSData *pdf in PDFArray){
[toSave appendData:pdf];
}
[toSave writeToFile:path atomically:YES];
However the output PDF only has the second part, which only contains 6 pages. So I don't know what did I miss. Can anyone give me some hints?
PDF is a file format which describes a single document. You cannot concatenate to PDF files to get the concatenated document.
But might achieve this with PDFKit:
Create both documents with initWithData:.
Insert all pages of the second document into the first one with insertPage:atIndex:.
This should look like:
PDFDocument *theDocument = [[PDFDocument alloc] initWithData:PDFArray[0]]
PDFDocument *theSecondDocument = [[PDFDocument alloc] initWithData:PDFArray[1]]
NSInteger theCount = theDocument.pageCount;
NSInteger theSecondCount = theSecondDocument.pageCount;
for(NSInteger i = 0; i < theSecondCount; ++i) {
PDFPage *thePage = [theSecondDocument pageAtIndex:i];
[theDocument insertPage:thePage atIndex:theCount + i];
}
[theDocument writeToURL:theTargetURL];
You have to add either #import <PDFKit/PDFKit.h> or #import PDFKit; to your source file, and you should add PDFKit.framework to the Linked Frameworks and Libraries of the build target in Xcode.
I've made a Swift command line tool to combine any number of PDF files. It takes the output path as the first argument and the input PDF files as the other arguments. There's no error handling whatsoever, so you can add that if you want to. Here's the full code:
import PDFKit
let args = CommandLine.arguments.map { URL(fileURLWithPath: $0) }
let doc = PDFDocument(url: args[2])!
for i in 3..<args.count {
let docAdd = PDFDocument(url: args[i])!
for i in 0..<docAdd.pageCount {
let page = docAdd.page(at: i)!
doc.insert(page, at: doc.pageCount)
}
}
doc.write(to: args[1])

How to allow forms(pdf) to be re-editable after they have been saved(Objective C)

I'm new to CoreGraphics framework.
We have used ILPDFKit library to render PDF or form
We embedded the drawn paths to existing PDF.Here is the code
-(NSData *)embededPdfAnnotationPointsInPdfAtPath:(NSString *)pdfPath
{
NSURL *pdfUrl = [NSURL fileURLWithPath:pdfPath];
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfUrl);
NSMutableData *data = [NSMutableData new];
UIGraphicsBeginPDFContextToData(data, CGRectZero, nil);
for(NSUInteger pageIndex = 1; pageIndex <= [self pdfDrawViewInfo].count; pageIndex ++)
{
// Get the current page and page frame
CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdf, pageIndex);
const CGRect pageFrame = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);
UIGraphicsBeginPDFPageWithInfo(pageFrame, nil);
// Draw the page (flipped)
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -pageFrame.size.height);
CGContextDrawPDFPage(ctx, pdfPage);
CGContextRestoreGState(ctx);
UIImage *drawViewImage = [self annotatedImageForPdfPageAtIndex:(pageIndex - 1)];
UIImage *annotatedImgForPdfPage = [self imageWithImage:drawViewImage scaledToSize:pageFrame.size] ;
[annotatedImgForPdfPage drawInRect:pageFrame];
}
UIGraphicsEndPDFContext();
// CGPDFDocumentRelease(pdf);
// CGImageRelease(annotatedImgCGref);
return data;
}
Above code indicates, we are just pasting image(drawn paths) on existing PDF.
Later functionality changed as "After saving PDF with annotations(freehand drawing), we need to have control over annotated stuff"
Question:
Edit PDF with annotation(freehand drawing), save it.After saving the PDF with annotated stuff, we need to again gain its editing capability. We need to know the saving mechanism and steps of this process.Please put your views here, so that it help me a lot.
Thanks inadvance
I would probably conserve the pdf original version, and store the edits in another file.
Than each time the user save, the app apply the annotations and other stuff to original version and generate the final pdf (in case of sharing or exportation features)
That would give you a complete control, (i guess this is also the same way "apple photo", "iPhoto" and "Aperture" manage the pictures modifications...)

ios- pdf generation in uiscrollview

in my ios app i am listing out some data in scroll view. When a button is clicked the datas in the page are been generated in pdf file format. Following is the bit of code.
- (void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename{
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];
// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[aView.layer renderInContext:pdfContext];
// remove PDF rendering context
UIGraphicsEndPDFContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(#"documentDirectoryFileName: %#",documentDirectoryFilename);
}
From the above code, i am able to generate a pdf file, but i am facing the following issue.
If i have more than 50 data, in my app i am able to see only the first 10 data and to see the others i need to scroll them. In this case when the pdf file gets generated it is taking only the data of first 10 and not the others. How to get the other data too
renderInContext: will only render what you currently see - UIScrollView is smart and will only have the views in the hierarchy that you need right now. You need a for-loop to manually scroll and redraw. This might be tricky to get right, maybe call [aView layoutSubviews] manually after scrolling to force the scrollView to rearrange the subviews instantly.
as steipete said, you can use loop to renderIncontext
- You need to calculate num of loop
numOfLoop = webview.ScrollView.ContentSize.Height/weview.frame.size.height
use loop to renderInContext
for(int i = 0; i < numOfLopp; i ++)
1.UIGraphicsBeginPDFPage()
get current context
renderIncontext
This way run correct in my app but I am getting with BIG issue when the numOfLoop lager
- you will get slow to renderInContext
- Memory will be increase -> Close app
In this way, How can I remove/release context when I am in once loop ?
Other way, you can use https://github.com/iclems/iOS-htmltopdf/blob/master/NDHTMLtoPDF.h
to generate to PDF
#steipete, #all Hi i tried the below code it generate multipage PDF, but the visible area in view is repeated for all the pages. please add any further ideas to improve the result.
-(void)createPDFfromUIView:(UIWebView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
NSString *oldFilePath= [[NSBundle mainBundle] pathForResource:#"ABC" ofType:#"pdf"];
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
CFURLRef url = CFURLCreateWithFileSystemPath (NULL, (CFStringRef)oldFilePath, kCFURLPOSIXPathStyle, 0);
CGPDFDocumentRef templateDocument = CGPDFDocumentCreateWithURL(url);
CFRelease(url); size_t count = CGPDFDocumentGetNumberOfPages(templateDocument);
for (size_t pageNumber = 1; pageNumber <= count; pageNumber++)
{
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
[aView.layer renderInContext:pdfContext];
}
CGPDFDocumentRelease(templateDocument);
// remove PDF rendering context UIGraphicsEndPDFContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(#"documentDirectoryFileName: %#",documentDirectoryFilename);
}
Check ScrollViewToPDF example
It uses same scrollview's layer renderInContext but here PDF is created according to your requirement such as one page PDF or multiple page PDF
Note : It captures all visible as well as invisible part of scrollView

How to compress a PNG image using Cocoa?

So, this is what I need :
Take an NSImage
Compress it as much as possible (loseless compress, no obvious drop in quality)
Save it back to disk
In the past, I tried using OptiPNG - as compiled binary (and getting results asynchronously) - which worked.
However, what if I don't want a terminal-like solution with external apps, but something more Cocoa-native?
Any ideas?
NSImage* image; // your NSImage
// With compression
NSData* data = [image
TIFFRepresentationUsingCompression:NSTIFFCompressionLZW
factor:0.5f]; // you can change factor between 0 and 1.0 for preferred compression rate
if (data != nil) {
NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithData:data];
if (bitmap != nil) {
NSData* bitmapData = [bitmap
representationUsingType:NSBitmapImageFileTypePNG
properties:#{}];
if (bitmapData != nil) {
[bitmapData
writeToFile:<file_path> //path where to save png
atomically:true];
}
}
}
Update: As mentioned in comments, this does not compress png.
However I have used this code in ShareExtension and it compress received screenshots well (from 1.1-1.5MB if save in plain to 0.4-0.7MB using representationUsingType) and without quality loss, just like OP asked.

iOS - Creating multi page PDF from HTML content [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have a long html page and wanted to convert it in to a multipage PDF file.
I have followed the instructions provided in
apple and here - how to make multi page PDF for a given string content.
But the formatting the NSString ( with some like data ) is difficult than creating a html page. I have created this html and displaying it in a UIWebView.
Now I want to create a PDF out of this HTML to a Multi page PDF file.
The code I'm using can create single PDF.
- (void)createPDFfromUIView:(UIWebView *)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
// Creates a mutable data object for updating with binary data, like a byte array
NSMutableData *pdfData = [NSMutableData data];
// Points the pdf converter to the mutable data object and to the UIView to be converted
UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();
// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
[aView.layer renderInContext:pdfContext];
// remove PDF rendering context
UIGraphicsEndPDFContext();
// Retrieves the document directories from the iOS device
NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString* documentDirectory = [documentDirectories objectAtIndex:0];
NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];
// instructs the mutable data object to write its context to a file on disk
[pdfData writeToFile:documentDirectoryFilename atomically:YES];
NSLog(#"documentDirectoryFileName: %#",documentDirectoryFilename);
}
Can any one give some help ?
I created a class based on every good advice I found around. I've been digging a lot and I hope my class will offer some good start for anyone trying to create multi-page PDF directly out of some HTML source.
You'll find the whole code here with some basic sample code : https://github.com/iclems/iOS-htmltopdf
I had just the same issue as you and my requirements were:
- full PDF (real text, no bitmap)
- smart multi-pages (compared to cutting a full height webview every X pixels...)
Thus, the solution I use is pretty nice as it resorts to the same tools iOS uses to split pages for print.
Let me explain, I setup a UIPrintPageRenderer based on the web view print formatter (first tip) :
UIPrintPageRenderer *render = [[UIPrintPageRenderer alloc] init];
[render addPrintFormatter:webView.viewPrintFormatter startingAtPageAtIndex:0];
CGRect printableRect = CGRectMake(self.pageMargins.left,
self.pageMargins.top,
self.pageSize.width - self.pageMargins.left - self.pageMargins.right,
self.pageSize.height - self.pageMargins.top - self.pageMargins.bottom);
CGRect paperRect = CGRectMake(0, 0, self.pageSize.width, self.pageSize.height);
[render setValue:[NSValue valueWithCGRect:paperRect] forKey:#"paperRect"];
[render setValue:[NSValue valueWithCGRect:printableRect] forKey:#"printableRect"];
NSData *pdfData = [render printToPDF];
[pdfData writeToFile: self.PDFpath atomically: YES];
In the meantime, I have created a category on UIPrintPageRenderer to support:
-(NSData*) printToPDF
{
[self doNotRasterizeSubviews:self.view];
NSMutableData *pdfData = [NSMutableData data];
UIGraphicsBeginPDFContextToData( pdfData, CGRectZero, nil );
[self prepareForDrawingPages: NSMakeRange(0, self.numberOfPages)];
CGRect bounds = UIGraphicsGetPDFContextBounds();
for ( int i = 0 ; i < self.numberOfPages ; i++ )
{
UIGraphicsBeginPDFPage();
[self drawPageAtIndex: i inRect: bounds];
}
UIGraphicsEndPDFContext();
return pdfData;
}