2010-11-05 38 views
10

Hiện tại, chúng tôi đang hiển thị nội dung PDF bằng cách sử dụng UIWebViews. Lý tưởng nhất là tôi muốn có thể hiển thị hình thu nhỏ trong UITableView mà không tải nhiều khác nhau UIWebViews đồng thời ... chúng đủ chậm tải một tài liệu - không bao giờ nhớ 10+!Làm cách nào tôi có thể tạo một hình thu nhỏ của một tệp PDF bằng SDK iPhone?

Có ai có bất kỳ mẹo nào về cách tôi thực hiện việc này không?

Tôi đã nghĩ về màn hình chụp tài liệu được tải bằng cách sử dụng UIDocumentInteractionController hoặc UIWebView nhưng điều này có nghĩa là tất cả chúng phải được thu nhỏ trước khi hiển thị bảng.

Trả lời

11

Apple cung cấp toàn bộ các phương thức ở cấp độ CoreGraphics để vẽ trực tiếp nội dung PDF. Theo tôi biết, không có gói nào được đóng gói gọn gàng ở mức UIKit, vì vậy nó có thể không phù hợp với dự án của bạn vào thời điểm này, đặc biệt nếu bạn không thoải mái ở cấp độ C. Tuy nhiên, hàm liên quan là CGContextDrawPDFPage; theo cách thông thường là CoreGraphics có các phương pháp khác để tạo tham chiếu PDF từ nguồn dữ liệu và sau đó lấy tham chiếu trang từ PDF. Sau đó, bạn sẽ cần phải xử lý việc chia tỷ lệ và dịch sang chế độ xem bạn muốn và được cảnh báo rằng bạn cần thực hiện lật ngang vì PDF (và OS X) sử dụng phần dưới bên trái làm nguồn gốc trong khi iOS sử dụng phần trên cùng bên trái . mã ví dụ, ra khỏi đỉnh đầu của tôi:

UIGraphicsBeginImageContext(thumbnailSize); 
CGPDFDocumentRef pdfRef = CGPDFDocumentCreateWithProvider((CGDataProviderRef)instanceOfNSDataWithPDFInside); 
CGPDFPageRef pageRef = CGPDFDocumentGetPage(pdfRef, 1); // get the first page 

CGContextRef contextRef = UIGraphicsGetCurrentContext(); 

// ignore issues of transforming here; depends on exactly what you want and 
// involves a whole bunch of normal CoreGraphics stuff that is nothing to do 
// with PDFs 
CGContextDrawPDFPage(contextRef, pageRef); 

UIImage *imageToReturn = UIGraphicsGetImageFromCurrentImageContext(); 

// clean up 
UIGraphicsEndImageContext(); 
CGPDFDocumentRelease(pdfRef); 

return imageToReturn; 

Tại một đoán, có thể bạn sẽ muốn sử dụng CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox) để có được hộp cây trồng của trang và sau đó làm việc ra làm thế nào để mở rộng/di chuyển mà để phù hợp với kích thước hình ảnh của bạn .

lẽ dễ dàng hơn cho mục đích của bạn là -renderInContext: phương pháp trên CALayer (xem QA 1703) - phương tiện cũ nhận được một ảnh chụp màn hình đã UIGetScreenImage, nhưng điều đó không bao giờ thực sự chính thức API và được dường như tạm thời cho phép chỉ vì có sự chấp thuận tình cờ RedLaser . Với mã trong QA, bạn có thể tự nâng cấp lên để nhận được UIImage từ bất kỳ chế độ xem nào khác mà không cần phải xem trên màn hình. Mà có thể giải quyết một số vấn đề của bạn với chụp màn hình? Mặc dù nó có nghĩa là bạn chỉ có thể hỗ trợ OS 4.x.

Trong cả hai trường hợp, các tệp PDF chỉ không vẽ nhanh chóng. Bạn có thể cần điền bảng sau đó vẽ hình thu nhỏ trên một chuỗi nền, đẩy chúng lên trên khi có sẵn. Bạn không thể sử dụng các đối tượng UIKit một cách an toàn trên các chủ đề nền nhưng tất cả các công cụ CoreGraphics đều an toàn.

12

Đây là mã mẫu xem xét chuyển đổi. :)

NSURL* pdfFileUrl = [NSURL fileURLWithPath:finalPath]; 
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfFileUrl); 
CGPDFPageRef page; 

CGRect aRect = CGRectMake(0, 0, 70, 100); // thumbnail size 
UIGraphicsBeginImageContext(aRect.size); 
CGContextRef context = UIGraphicsGetCurrentContext(); 
UIImage* thumbnailImage; 


NSUInteger totalNum = CGPDFDocumentGetNumberOfPages(pdf); 

for(int i = 0; i < totalNum; i++) { 


    CGContextSaveGState(context); 
    CGContextTranslateCTM(context, 0.0, aRect.size.height); 
    CGContextScaleCTM(context, 1.0, -1.0); 

    CGContextSetGrayFillColor(context, 1.0, 1.0); 
    CGContextFillRect(context, aRect); 


    // Grab the first PDF page 
    page = CGPDFDocumentGetPage(pdf, i + 1); 
    CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, aRect, 0, true); 
    // And apply the transform. 
    CGContextConcatCTM(context, pdfTransform); 

    CGContextDrawPDFPage(context, page); 

    // Create the new UIImage from the context 
    thumbnailImage = UIGraphicsGetImageFromCurrentImageContext(); 

    //Use thumbnailImage (e.g. drawing, saving it to a file, etc) 

    CGContextRestoreGState(context); 

} 


UIGraphicsEndImageContext();  
CGPDFDocumentRelease(pdf); 
+0

Hi Alones, Tôi đang sử dụng mã của bạn để có được thumbnails PDF. Có vẻ như dòng CGContextConcatCTM (ngữ cảnh, pdfTransform) tạo ra một nút cổ chai bộ nhớ, tôi phát hiện ra rằng nếu tôi rời khỏi dòng này, thì OK. Nhưng tôi không thể bỏ nó ra vì tôi cần cái này cho một hình thu nhỏ thích hợp. Bạn có ý tưởng về cách chúng tôi có thể cải thiện điều này không? Thx btw ... – aslisabanci

+0

cái này hoạt động cho tôi ... cái ở trên tôi không biết tại sao nhưng nó tạo ra hình thu nhỏ giả hoặc rác ... cảm ơn ... – Underdog

+0

Nói của doc UIGraphicsGetImageFromCurrentImageContext() không phải là chủ đề an toàn –

1

Đây là một phương pháp nhanh chóng 3 để tạo ra một hình ảnh thu nhỏ UIImage cho một trang pdf

static func getThumbnailForPDF(_ urlString:String, pageNumber:Int) -> UIImage? { 
    let bundle = Bundle.main 
    let path = bundle.path(forResource: urlString, ofType: "pdf") 
    let pdfURL = URL(fileURLWithPath: path!) 

    let pdf = CGPDFDocument(pdfURL as CFURL)! 
    let page = pdf.page(at: pageNumber)! 
    let rect = CGRect(x: 0, y: 0, width: 100.0, height: 70.0) //Image size here 

    UIGraphicsBeginImageContext(rect.size) 
    let context = UIGraphicsGetCurrentContext()! 

    context.saveGState() 
    context.translateBy(x: 0, y: rect.height) 
    context.scaleBy(x: 1.0, y: -1.0) 
    context.setFillColor(gray: 1.0, alpha: 1.0) 
    context.fill(rect) 


    let pdfTransform = page.getDrawingTransform(CGPDFBox.mediaBox, rect: rect, rotate: 0, preserveAspectRatio: true) 
    context.concatenate(pdfTransform) 
    context.drawPDFPage(page) 

    let thumbImage = UIGraphicsGetImageFromCurrentImageContext() 
    context.restoreGState() 

    UIGraphicsEndImageContext() 

    return thumbImage 
} 
+0

Xin chào Emil, bạn đã đến bữa tiệc trễ khoảng 7 năm - nhưng cảm ơn bạn không phải trả lời câu hỏi này cho bất kỳ ai gặp phải vấn đề tương tự ;-) –

Các vấn đề liên quan