I have the following piece of code to convert a PDF page to a CGImage:
func testPrint(pp:UnsafePointer<Void>) { // debug to see bits
var p = UnsafePointer<UInt8>(pp)
var res = ""
for _ in 0..<200 {
res += "\(p.memory) "
p = p.advancedBy(1)
}
print(res)
}
func pageOneFromPDF(file:String) -> CGImage? {
let url = NSURL(fileURLWithPath: file)
let pdfDocument = CGPDFDocumentCreateWithURL(url)
let pageOne = CGPDFDocumentGetPage(pdfDocument, 1)
let rect = CGPDFPageGetBoxRect(pageOne, .MediaBox)
let width = Int(rect.size.width)
let height = Int(rect.size.height)
let context = CGBitmapContextCreate(nil, width, height, 8, width, CGColorSpaceCreateDeviceGray(), CGImageAlphaInfo.Only.rawValue)!
CGContextClearRect(context, rect)
CGContextDrawPDFPage(context, pageOne)
testPrint(CGBitmapContextGetData(context))
return CGBitmapContextCreateImage(context)
}
This converts my PDF page indeed into a gray scaled bit map. The only problem: the resulting CGImage
's color is inverted (black gets white and vice versa). I fiddled around with the parameters of CGBitmapContextCreate
but no luck.
P.S. I added this piece of code to reverse the negative to positive:
func inverse(pp:UnsafePointer<Void>, size:Int) {
var p = UnsafeMutablePointer<UInt8>(pp)
for _ in 0..<size {
p.memory = 255-p.memory
p = p.advancedBy(1)
}
}
which works, but of course I'd like to get the image right in the first place.
EDIT: I must be doing something stupid, I guess. When I render like above and invert the whole picture, it looks like
where the left it the Finder preview and the right my rendering. As I now notice, this inverts parts of the image. I tried with @Tricertops code and got (the black blocks above/below are from a list with other PDFs)
and obviously this has the right gray values, but there is some black mask which underlays the picture. The pure text to the left is now invisible, but the images appear correctly.
By passing CGImageAlphaInfo.Only
you are asking for alpha mask, not grayscale image as you may think.
First, try initializing the context using CGImageAlphaInfo.None
(because PDFs don’t have alpha anyway):
CGBitmapContextCreate(nil, width, height, 8, width, CGColorSpaceCreateDeviceGray(), CGImageAlphaInfo.None.rawValue)
Then fill the context with white color, as PDFs always do:
CGContextSetFillColorWithColor(context, UIColor.whiteColor().CGColor)
CGContextFillRect(context, rect)
Then continue as previously, by drawing the PDF page.
I think you were getting alpha bitmap, not grayscale. Zeros where nothing was drawn (and PDF defines that white) and Ones where some content was drawn (as it was probably black). It could appear by inspecting the bits as inverted gray bitmap. Always debug images as rendered, not printed in bits :)