I want insert company logo image into pdf of every page. So we are referring following site
Tutorial Link
I want to insert logo right bottom page of pdf, I am unable do to that process.
Please find the tried both way code:
let documentURL = url
// Create a `CGPDFDocument` object for accessing the PDF pages.
// We need these pages in order to draw the original/existing content, because `UIGraphicsBeginPDFContextToFile` creates a file with a clean slate.
// We will have the original file contents in memory as long as the `CGPDFDocument` object is around, even after we have started rewriting the file at the path.
guard let originalDocument = CGPDFDocument(documentURL as CFURL) else {
print("Unable to create read document.")
return
}
// Create a new PDF at the same path to draw the contents into.
UIGraphicsBeginPDFContextToFile(documentURL.path, CGRect.zero, nil)
let image = UIImage(named: "inactive")!
guard let pdfContext = UIGraphicsGetCurrentContext() else {
print("Unable to access PDF Context.")
return
}
let pageSize = UIGraphicsGetPDFContextBounds().size
for pageIndex in 0..<originalDocument.numberOfPages {
// Mark the beginning of the page.
pdfContext.beginPDFPage(nil)
// Pages are numbered starting from 1.
// Access the `CGPDFPage` object with the original contents.
guard let currentPage = originalDocument.page(at: pageIndex + 1) else {
return
}
// Draw the existing page contents.
pdfContext.drawPDFPage(currentPage)
// Save the context state to restore after we are done drawing the image.
pdfContext.saveGState()
// Change the PDF context to match the UIKit coordinate system.
pdfContext.translateBy(x: 0, y: pageSize.height)
pdfContext.scaleBy(x: 1, y: -1)
// Location of the image to be drawn in UIKit coordinates.
let imagePosition = CGRect(x: 100, y: 0, width: 50, height: 50)
image.draw(in: imagePosition)
// UIColor.orange.set()
// UIRectFill(CGRect(x: 100, y: 0, width: 50, height: 50))
// Restoring the context back to its original state.
pdfContext.restoreGState()
// Mark the end of the current page.
pdfContext.endPDFPage()
}
// End the PDF context, essentially closing the PDF document context.
UIGraphicsEndPDFContext()
Updated Code:
let documentURL = url
guard let originalDocument = CGPDFDocument(documentURL as CFURL) else {
print("Unable to create read document.")
return
}
UIGraphicsBeginPDFContextToFile(documentURL.path, CGRect.zero, nil)
// let image = UIImage(named: "verified_kuwy")
let image = UIImage(named: "watermark")
guard let pdfContext = UIGraphicsGetCurrentContext() else {
print("Unable to access PDF Context.")
return
}
let pageSize = UIGraphicsGetPDFContextBounds().size
for pageIndex in 0..<originalDocument.numberOfPages {
pdfContext.beginPDFPage(nil)
guard let currentPage = originalDocument.page(at: pageIndex + 1) else {
return
}
pdfContext.drawPDFPage(currentPage)
pdfContext.saveGState()
pdfContext.translateBy(x: 0, y: pageSize.height)
pdfContext.scaleBy(x: 1, y: -1)
let imagePosition = CGRect(x: pageSize.width - 150, y: pageSize.height - 150, width: 100, height: 100)
image!.draw(in: imagePosition)
pdfContext.restoreGState()
pdfContext.endPDFPage()
}
// End the PDF context, essentially closing the PDF document context.
UIGraphicsEndPDFContext()
Related
I am successfully creating a pdf document from 3 images using the following code:
struct ExportImagesView: View {
var body: some View {
ShareLink("Export Licence as PDF", item: render())
}
func render() -> URL {
// 1: Render Hello World with some modifiers
let renderer = ImageRenderer(content:
VStack {
Image("Page1")
Image("Page2")
Image("Page3")
}
)
// 2: Save it to our documents directory
let url = URL.documentsDirectory.appending(path: "output.pdf")
// 3: Start the rendering process
renderer.render { size, context in
// 4: Tell SwiftUI our PDF should be the same size as the views we're rendering
var box = CGRect(x: 0, y: 0, width: size.width, height: size.height)
// 5: Create the CGContext for our PDF pages
guard let pdf = CGContext(url as CFURL, mediaBox: &box, nil) else {
return
}
// 6: Start a new PDF page
pdf.beginPDFPage(nil)
// 7: Render the SwiftUI view data onto the page
context(pdf)
// 8: End the page and close the file
pdf.endPDFPage()
pdf.closePDF()
}
return url
}
}
The above is from a tutorial at the following link:
https://www.hackingwithswift.com/quick-start/swiftui/how-to-render-a-swiftui-view-to-a-pdf
How can I iterate through the images to create a 3 page pdf document with one image per each page? I will specify the page size.
you have it already. simply reshuffle the order of operations:
struct ExportImagesView: View {
let pages = [ "Page1", "Page2", "Page3" ]
var body: some View {
VStack {
ShareLink("Export Licence as PDF", item: render())
}
}
#MainActor func render() -> URL {
// 1: Save path
let url = URL.documentsDirectory.appending(path: "output.pdf")
// 2: PDF size
var box = CGRect(x: 0, y: 0, width: 600, height: 800)
// 3: Create the CGContext for our PDF pages
guard let pdf = CGContext(url as CFURL, mediaBox: &box, nil) else {
return url
}
// 4: Render each page
for page in pages {
pdf.beginPDFPage(nil)
let renderer = ImageRenderer(content:
Image(page)
)
renderer.render { size, context in
context(pdf)
}
pdf.endPDFPage()
}
pdf.closePDF()
return url
}
}
I'm trying to get the orientation property of a PDF document. The purpose is, I would like to add a button widget in a location that depends on the orientation of the PDF document.
For example:
func openPDFDocument() {
if let documentURL = Bundle.main.url(forResource: "PDF document", withExtension: "pdf"),
let document = PDFDocument(url: documentURL),
let page = document.page(at: 0) {
// Set our document to the view, center it, and set a background color
pdfView?.document = document
pdfView?.autoScales = true
pdfView?.backgroundColor = UIColor.lightGray
//I think I should be able to add a code here like:
if page.orientation = Horizontal {
self.insertResetButtonInto(page)
} else {
//do nothing or do something else
}
}
}
This is the function I would like to add in case the document is in Landscape mode:
func insertResetButtonInto(_ page: PDFPage) {
let pageBounds = page.bounds(for: .cropBox)
let resetButtonBounds = CGRect(x: 90, y: pageBounds.size.height - 300, width: 106, height: 32)
let resetButton = PDFAnnotation(bounds: resetButtonBounds, forType: PDFAnnotationSubtype(rawValue: PDFAnnotationSubtype.widget.rawValue), withProperties: nil)
resetButton.widgetFieldType = PDFAnnotationWidgetSubtype(rawValue: PDFAnnotationWidgetSubtype.button.rawValue)
resetButton.widgetControlType = .pushButtonControl
resetButton.caption = "Reset"
page.addAnnotation(resetButton)
// Create PDFActionResetForm action to clear form fields.
let resetFormAction = PDFActionResetForm()
resetFormAction.fieldsIncludedAreCleared = false
resetButton.action = resetFormAction
}
I got the example project from Apple's documentation website. I looked at a previous similar question, however it seems this was in Objective C.
I would appreciate the help in this matter.
There is no direct API to get the orientation from a PDFPage. But you can first get the page size from .mediaBox, then calculate the orientation like below.
let pageSize = page.bounds(for: .mediaBox).size
if pageSize.width > pageSize.height {
//landscape
} else {
//portrait
}
I use another way to get the orientation of my pdf page.
func IsLandscape(page: PDFPage) -> Bool {
let pointZero = pdfView.convert(CGPoint(x: 0, y: 0), from: page)
let pointTen = pdfView.convert(CGPoint(x: 10, y: 10), from: page)
let caculate = pointTen.x - pointZero.x
print("pointZero: \(pointZero), pointTen:\(pointTen)")
if (caculate > 0) {
print("landscape")
return true
}
else {
print("portrait")
return false
}
}
I am facing the problem while inserting a blank page in pdf using PDFKit. when there are images on pdf importing from gallery or capturing from the camera. and then we add a blank page on that pdf at that time the page is very small. it's not in A4 size. here I would post the code. and I am also going to post the screenshot of what problem actually I am getting please refer to it and provide a possible solution.in the screenshot, I am adding 2 blank pages enter image description here
let format = UIGraphicsPDFRendererFormat()
// 2
let pageWidth = 8.5 * 72.0
let pageHeight = 11 * 72.0
let pageRect = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)
// 3
let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)
// 4
var firstPdfDocument = PDFDocument()
var SecondpdfDocument = self.pdfView.document
let data = renderer.pdfData { (context) in
// 5
context.beginPage()
// 6
let context = context.cgContext
// let page = PDFPage()
// page.setBounds(pageRect, for: .mediaBox)
// pdfDocument!.insert(page, at: self.pdfView.document!.pageCount)
}
print(data)
firstPdfDocument = PDFDocument(data: data)!
let page = firstPdfDocument.page(at: 0)!
SecondpdfDocument!.insert(page, at: self.pdfView.document!.pageCount)
SecondpdfDocument!.write(toFile: self.pdfFile.url.path)
I have this PDF file with me. I use following code to render the first page of this PDF file.
let page = self.pdfDocument.page(at: 0 )! // get first page
let rotationAngle = page.rotation // this value is 90
let renderedPdfData = renderPDF(page: page.pageRef!)
where renderPDF method is,
func renderPDF(page: CGPDFPage) -> Data {
let pageRect = page.getBoxRect(.mediaBox)
let renderer = UIGraphicsPDFRenderer(bounds: pageRect)
return renderer.pdfData { (context) in
context.beginPage()
context.cgContext.setFillColor(UIColor.white.cgColor)
context.fill(pageRect)
context.cgContext.translateBy(x: 0.0, y: pageRect.size.height)
context.cgContext.scaleBy(x: 1, y: -1)
context.cgContext.drawPDFPage(page)
}
}
Then later I want to create a CGPDFPage back with above renderedPdfData . For that I use following method.
var newPage: CGPDFPage = createPDFPage(pdfData: renderedPdfData)
where createPDFPage method is,
func createPDFPage(pdfData: Data) -> CGPDFPage? {
guard let provider = CGDataProvider(data: pdfData as CFData) else {
return nil
}
guard let document = CGPDFDocument(provider) else {
return nil
}
// page starting at 1. The input PDF data only has 1 page.
return document.page(at: 1)
}
But how should I set newPage's rotation angle data (ie. 90)? Because 'rotationAngle' is a get-only property. Since I haven't set a value for it, it's value is always 0.
let angle = newPage.rotationAngle // value is 0
Is there a way I can create a CGPDFPage with rotation information available with it?
I'm working in Swift 5 and on iOS. I'm trying to overlay text onto a current PDF I have. I'm essentially porting code I made from an app for macOS. This is the code from the Mac version:
func executeContext(at srcURL: URL, to dstURL: URL) {
// Confirm there is a document there
if let doc: PDFDocument = PDFDocument(url: srcURL) {
// Create a document, get the first page, and set the size of the page
let page: PDFPage = doc.page(at: 0)!
var mediaBox: CGRect = CGRect(x: 0, y: 0, width: 792, height: 612)
// This is where the magic happens. Create the drawing context on the PDF
let context = CGContext(dstURL as CFURL, mediaBox: &mediaBox, nil)
let graphicsContext = NSGraphicsContext(cgContext: context!, flipped: false)
NSGraphicsContext.current = graphicsContext
context!.beginPDFPage(nil)
// Draws the PDF into the context
page.draw(with: .mediaBox, to: context!)
// Parse and Draw Text on the context
//drawText()
let attributes = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 72)
]
let text = "I'm a PDF!"
text.draw(at: CGPoint(x: 0, y: 0), withAttributes: attributes)
context!.saveGState()
context!.restoreGState()
context!.endPDFPage()
NSGraphicsContext.current = nil
context?.closePDF()
}
}
The drawText() function did most of the text overlaying that was needed, but I put another "draw "method below it to test it out.
I'm understandably getting an error Cannot find 'NSGraphicsContext' in scope since NSGraphicsContext doesn't exist on iOS. I've tried to find an equivalent translation with UIGraphicsPDFRenderer or UIGraphicsBeginPDFContextToData, and using some code from a Ray Wenderlich tutorial, I was able to create a new PDF and place text on it with the below code:
func createDocument(url: URL) -> Data {
//let pdfData = try? Data.init(contentsOf: url)
// 1
let pdfMetaData = [
kCGPDFContextCreator: "Timecard App",
kCGPDFContextAuthor: "Timecard App"
]
let format = UIGraphicsPDFRendererFormat()
format.documentInfo = pdfMetaData as [String: Any]
// 2
let pageWidth = 8.5 * 72.0
let pageHeight = 11 * 72.0
let pageRect = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)
// 3
let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format)
// 4
let data = renderer.pdfData { (context) in
// 5
context.beginPage()
// 6
let attributes = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 72)
]
let text = "I'm a PDF!"
text.draw(at: CGPoint(x: 0, y: 0), withAttributes: attributes)
}
return data
}
...but I couldn't find a way to load in current PDF "data" to the renderer and then draw from there. Does anyone have any suggestions on the proper way to do this?
Here is possible solution - actually you just need to operate with CoreGraphics context directly, set current, flip transform, etc. (style and conventions of original code preserved).
Tested with Xcode 12 / iOS 14.
func executeContext(at srcURL: URL, to dstURL: URL) {
// Confirm there is a document there
if let doc: PDFDocument = PDFDocument(url: srcURL) {
// Create a document, get the first page, and set the size of the page
let page: PDFPage = doc.page(at: 0)!
var mediaBox: CGRect = page.bounds(for: .mediaBox)
// This is where the magic happens. Create the drawing context on the PDF
let context = CGContext(dstURL as CFURL, mediaBox: &mediaBox, nil)
UIGraphicsPushContext(context!)
context!.beginPDFPage(nil)
// Draws the PDF into the context
page.draw(with: .mediaBox, to: context!)
let flipVertical: CGAffineTransform = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: mediaBox.size.height)
context!.concatenate(flipVertical)
let attributes = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 72)
]
let text = "I'm a PDF!"
text.draw(at: CGPoint(x: 0, y: 0), withAttributes: attributes)
context!.endPDFPage()
context?.closePDF()
UIGraphicsPopContext()
}
}
Edit additional pages using the following function
// add a new page
func addPage(number: Int){
// index is one less than document page number
let index = number - 1
context.endPDFPage()
if let page = document.page(at: index) {
context.beginPDFPage(nil)
page.draw(with: .mediaBox, to: context)
context.concatenate(flipVertical)
}
}
Where document is the PDF document you wish to edit.
Then start editing that new page. The X and Y coordinates reset to 0,0 again for the new page.