9

I want to add the signature on existing pdf. I have done this in following way:

1) Load existing pdf on UIView say mainView.

2) Add a signature image on mainView.

3) Call a following function

-(NSMutableData *)getPDFDatafromUIView
{
DebugLog(@"");
// 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, mainView.bounds, nil);
UIGraphicsBeginPDFPage();
CGContextRef pdfContext = UIGraphicsGetCurrentContext();

// draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData
mainView.layer renderInContext:pdfContext];

// remove PDF rendering context
UIGraphicsEndPDFContext();

return pdfData;
} 

4) This function block your UI for a while, so call it on new thread

   [NSThread detachNewThreadSelector:@selector(launchExportViewForExportDrawing) toTarget:self withObject:nil];

Using above method I get a pdf data with signature which contain the old pdf data too.

But for above method I must need to show the pdf in UIView. If I want do the above thing without loading on UIView, without showing pdf to user, How do I do that?

I am able to add a Image on pdf with creating the new pdf page. How do I add a image on existing pdf?

RohitK
  • 1,444
  • 1
  • 14
  • 37
  • I have the NSData of pdf and UIImage of signature. From ray’s tutorial http://www.raywenderlich.com/6818/how-to-create-a-pdf-with-quartz-2d-in-ios-5-tutorial-part-2 , I am able to add the signature Image on a PDF. But I don’t want to create the new pdf. “ I want to add the signature on existing PDF ”. – RohitK Apr 22 '14 at 05:32

3 Answers3

11

I have solved by creating the new PDF and drawing the pdf data and signature on it. Please refer following code:

// For adding the Siganture we need to wite the content on new PDF
-(void) addSignature:(UIImage *) imgSignature onPDFData:(NSData *)pdfData {

NSMutableData* outputPDFData = [[NSMutableData alloc] init];
CGDataConsumerRef dataConsumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)outputPDFData);

CFMutableDictionaryRef attrDictionary = NULL;
attrDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(attrDictionary, kCGPDFContextTitle, CFSTR("My Doc"));
CGContextRef pdfContext = CGPDFContextCreate(dataConsumer, NULL, attrDictionary);
CFRelease(dataConsumer);
CFRelease(attrDictionary);
CGRect pageRect;

// Draw the old "pdfData" on pdfContext
CFDataRef myPDFData = (__bridge CFDataRef) pdfData;
CGDataProviderRef provider = CGDataProviderCreateWithCFData(myPDFData);
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(provider);
CGDataProviderRelease(provider);
CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);
pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
CGContextBeginPage(pdfContext, &pageRect);
CGContextDrawPDFPage(pdfContext, page);

// Draw the signature on pdfContext
pageRect = CGRectMake(0, 0,imgSignature.size.width , imgSignature.size.height);
CGImageRef pageImage = [imgSignature CGImage];
CGContextDrawImage(pdfContext, pageRect, pageImage);

// release the allocated memory
CGPDFContextEndPage(pdfContext);
CGPDFContextClose(pdfContext);
CGContextRelease(pdfContext);

// write new PDFData in "outPutPDF.pdf" file in document directory
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pdfFilePath =[NSString stringWithFormat:@"%@/outPutPDF.pdf",docsDirectory];
[outputPDFData writeToFile:pdfFilePath atomically:YES];

}
RawMean
  • 8,374
  • 6
  • 55
  • 82
RohitK
  • 1,444
  • 1
  • 14
  • 37
  • This solution changes a specific page in the PDF and adds the signature to it. If the PDF has more than one page, the rest of the pages are lost. Do you know a way that a specific pdf page can be modified without losing the rest of the pages? – RawMean Aug 05 '14 at 02:19
  • You need to add the signature to required page by specifying page number in CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1); and after that you need to merge the pdf pages as per requirement. – RohitK Aug 07 '14 at 10:33
  • It has been a while but is there a way to use this code to sign the PDF anywhere ? Because you are adding the signature to a hard-coded position – H4Hugo Mar 02 '16 at 13:48
  • Is there a swift version of this ?? – Umar Farooque Nov 14 '17 at 13:39
1

Rohit Answer is working perfectly,But it works only single page so i just Added some code for all pages displaying with image(image shown in single page reaming pages are looks same).Thanks @Rohit

NSString *path = [[NSBundle mainBundle] pathForResource:@"PartB" ofType:@"pdf"];
NSURL *docURL = [NSURL fileURLWithPath:path];
NSString *pdfName = [NSString stringWithFormat:@"%@",docURL];
NSLog(@"pdfName: %@", pdfName);
NSData *pdfData = [NSData dataWithContentsOfFile:path];


NSURL *pdfURL = [[NSBundle mainBundle] URLForResource:@"PartB.pdf" withExtension:nil];
CGPDFDocumentRef pdf1 = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);
long pageCount = CGPDFDocumentGetNumberOfPages(pdf1);
NSLog(@"the page count %ld",pageCount);



NSMutableData* outputPDFData = [[NSMutableData alloc] init];
CGDataConsumerRef dataConsumer = CGDataConsumerCreateWithCFData((CFMutableDataRef)outputPDFData);

CFMutableDictionaryRef attrDictionary = NULL;
attrDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(attrDictionary, kCGPDFContextTitle, CFSTR("My Doc"));
CGContextRef pdfContext = CGPDFContextCreate(dataConsumer, NULL, attrDictionary);
CFRelease(dataConsumer);
CFRelease(attrDictionary);
CGRect pageRect;


// Draw the old "pdfData" on pdfContext
CFDataRef myPDFData = (__bridge CFDataRef) pdfData;
CGDataProviderRef provider = CGDataProviderCreateWithCFData(myPDFData);
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(provider);
CGDataProviderRelease(provider);

for (int k=1; k<=pageCount; k++) {

    CGPDFPageRef page3 = CGPDFDocumentGetPage(pdf, k);
    pageRect = CGPDFPageGetBoxRect(page3, kCGPDFMediaBox);
    CGContextBeginPage(pdfContext, &pageRect);
    CGContextDrawPDFPage(pdfContext, page3);
    if (k==pageSelect) {
        pageRect = CGRectMake(0, 0,100 , 100);
        CGImageRef pageImage = [mainImage.image CGImage];
        CGContextDrawImage(pdfContext, pageRect, pageImage);
    }
    CGPDFContextEndPage(pdfContext);
}
CGPDFContextClose(pdfContext);
CGContextRelease(pdfContext);

// write new PDFData in "outPutPDF.pdf" file in document directory
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pdfFilePath =[NSString stringWithFormat:@"%@/outPutPDF.pdf",docsDirectory];
[outputPDFData writeToFile:pdfFilePath atomically:YES];
NSLog(@"save the pdf %@",pdfFilePath);
-1

I'm not sure I understand your problem completely. From what I can tell you have a UIView that you're rendering onto a PDF document, and you want to add a signature image and not show it to the user.

If you're trying to add a "signature image" to your pdf, you can add a UIImageView to the UIView that you're rendering to the pdf.

If you don't want the user to see the UIView in the mean time, you could change it's origin to somewhere off bounds, for example:

CGRect originalFrame = mainView.frame;
CGRect newFrame = mainView.frame;
newFrame.origin.x = -newFrame.size.width;
newFrame.origin.y = -newFrame.size.height;
mainView.frame = newFrame; 

//do all your PDF stuff here

mainView.frame = originalFrame; 

I hope that helps. If it doesn't, please clarify the problem :)

Rob
  • 1,025
  • 2
  • 10
  • 27
  • Hey, Thanks for the reply. I want to add the signature on PDF i.e. I have the NSData of pdf and UIImage of signature. How do I do that? From ray’s tutorial http://www.raywenderlich.com/6818/how-to-create-a-pdf-with-quartz-2d-in-ios-5-tutorial-part-2 , I am able to add the signature Image on a PDF. But I don’t want to create the new pdf. “ I want to add the signature on existing PDF ”. – RohitK Apr 22 '14 at 05:31
  • That should be easy. Instead of using a new filename for your output pdf, just use the old filename. This will overwrite the original file, and you will have "updated" the original one. – Rob Apr 22 '14 at 20:07