Just to make it a little clearer, here's a (cleaned up) version of my renderer. If I skip lines 26 to 36 (the transform filter) this renders in the bounding box size wise. But if I keep those lines in, I get the out of memory exception.
This unfortunately isn't just a simple rotation, because, well, 2D box on a 3D Earth. But hopefully that helps explain a little more what's going on.
class PDFOverlayRenderer: MKOverlayRenderer {
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
var boundingRect = self.rect(for: overlay.boundingMapRect)
guard let cgDocument = CGPDFDocument(overlay.pdfUrl as CFURL),
let cgPage = cgDocument.page(at: 1) else { return }
let pdfPageRect = cgPage.getBoxRect(.mediaBox)
let renderer = UIGraphicsImageRenderer(size: pdfPageRect.size)
img = renderer.image { ctx in
UIColor.white.set()
ctx.fill(pdfPageRect)
ctx.cgContext.translateBy(x: 0.0, y: pdfPageRect.size.height)
ctx.cgContext.scaleBy(x: 1.0, y: -1.0)
ctx.cgContext.drawPDFPage(cgPage)
}
var img: UIImage!
UIGraphicsPushContext(context)
if !overlay.actualCoords.isEmpty {
var ll = self.point(for: overlay.actualCoords[3])
var lr = self.point(for: overlay.actualCoords[2])
var ur = self.point(for: overlay.actualCoords[1])
var ul = self.point(for: overlay.actualCoords[0])
let ciImg = CIImage(image: img)!
let perspectiveTransformFilter = CIFilter.perspectiveTransform()
perspectiveTransformFilter.inputImage = ciImg
perspectiveTransformFilter.topRight = cartesianForPoint(point: ur, extent: boundingRect)
perspectiveTransformFilter.topLeft = cartesianForPoint(point: ul, extent: boundingRect)
perspectiveTransformFilter.bottomRight = cartesianForPoint(point: lr, extent: boundingRect)
perspectiveTransformFilter.bottomLeft = cartesianForPoint(point: ll, extent: boundingRect)
let txImg = perspectiveTransformFilter.outputImage!
img = UIImage(ciImage: txImg)
boundingRect.origin = CGPoint(x: minX, y: minY)
}
img.draw(in: boundingRect, blendMode: .normal, alpha: 1.0)
UIGraphicsPopContext()
}
func cartesianForPoint(point:CGPoint, extent:CGRect) -> CGPoint {
return CGPoint(x: point.x,y: extent.height - point.y)
}
}