How to get actual pdf page size in iPad?

家住魔仙堡 提交于 2019-11-28 10:24:59

I was using the answers here until I realised a one-liner for this

CGRect pageRect = CGPDFPageGetBoxRect(pdf, kCGPDFMediaBox);
// Which you can convert to size as
CGSize size = pageRect.size;

Used in Apple's sample ZoomingPDFViewer app

Donal O'Danachair

Here's the code to do it; also to convert a point on the page from PDF coordinates to iOS coordinates. See also Get PDF hyperlinks on iOS with Quartz

#import <CoreGraphics/CoreGraphics.h>


. . . . . . . . . . . 

NSString *pathToPdfDoc = [[NSBundle mainBundle] pathForResource:@"Test2" offType:@"pdf"];
NSURL *pdfUrl = [NSURL fileURLWithPath:pathToPdfDoc];

CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef)pdfUrl);

CGPDFPageRef page = CGPDFDocumentGetPage(document, 1); // assuming all the pages are the same size!

// code from https://stackoverflow.com/questions/4080373/get-pdf-hyperlinks-on-ios-with-quartz, 
// suitably amended

CGPDFDictionaryRef pageDictionary = CGPDFPageGetDictionary(page);


//******* getting the page size

CGPDFArrayRef pageBoxArray;
if(!CGPDFDictionaryGetArray(pageDictionary, "MediaBox", &pageBoxArray)) {
    return; // we've got something wrong here!!!
}

int pageBoxArrayCount = CGPDFArrayGetCount( pageBoxArray );
CGPDFReal pageCoords[4];
for( int k = 0; k < pageBoxArrayCount; ++k )
{
    CGPDFObjectRef pageRectObj;
    if(!CGPDFArrayGetObject(pageBoxArray, k, &pageRectObj))
    {
        return;
    }

    CGPDFReal pageCoord;
    if(!CGPDFObjectGetValue(pageRectObj, kCGPDFObjectTypeReal, &pageCoord)) {
        return;
    }

    pageCoords[k] = pageCoord;
}

NSLog(@"PDF coordinates -- bottom left x %f  ",pageCoords[0]); // should be 0
NSLog(@"PDF coordinates -- bottom left y %f  ",pageCoords[1]); // should be 0
NSLog(@"PDF coordinates -- top right   x %f  ",pageCoords[2]);
NSLog(@"PDF coordinates -- top right   y %f  ",pageCoords[3]);
NSLog(@"-- i.e. PDF page is %f wide and %f high",pageCoords[2],pageCoords[3]);

// **** now to convert a point on the page from PDF coordinates to iOS coordinates. 

double PDFHeight, PDFWidth;
PDFWidth =  pageCoords[2];
PDFHeight = pageCoords[3];

// the size of your iOS view or image into which you have rendered your PDF page 
// in this example full screen iPad in portrait orientation  
double iOSWidth = 768.0; 
double iOSHeight = 1024.0;

// the PDF co-ordinate values you want to convert 
double PDFxval = 89;  // or whatever
double PDFyval = 520; // or whatever

// the iOS coordinate values
int iOSxval, iOSyval;

iOSxval = (int) PDFxval * (iOSWidth/PDFWidth);
iOSyval = (int) (PDFHeight - PDFyval) * (iOSHeight/PDFHeight);

NSLog(@"PDF: %f %f",PDFxval,PDFyval);
NSLog(@"iOS: %i %i",iOSxval,iOSyval);

The following method returns the height of the first pdf page scaled according to a webview:

-(NSInteger) pdfPageSize:(NSData*) pdfData{

    CGPDFDocumentRef document = CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithCFData((__bridge CFDataRef)pdfData));

    CGPDFPageRef page = CGPDFDocumentGetPage(document, 1);
    CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);

    double pdfHeight, pdfWidth;
    pdfWidth =  pageRect.size.width;
    pdfHeight = pageRect.size.height;

    double iOSWidth = _webView.frame.size.width;
    double iOSHeight = _webView.frame.size.height;

    double scaleWidth = iOSWidth/pdfWidth;
    double scaleHeight = iOSHeight/pdfHeight;

    double scale = scaleWidth > scaleHeight ? scaleWidth : scaleHeight;
    NSInteger finalHeight = pdfHeight * scale;

    NSLog(@"MediaRect %f, %f, %f, %f", pageRect.origin.x, pageRect.origin.y, pageRect.size.width, pageRect.size.height);
    NSLog(@"Scale: %f",scale);
    NSLog(@"Final Height: %i", finalHeight);

    return finalHeight;
}

It's a lot smaller than Donal O'Danachair's and does basically the same thing. You could easily adapt it to your View size and to return the width along with the height.

Swift 3.x (based on answer provided by Ege Akpinar)

let pageRect = pdfPage.getBoxRect(CGPDFBox.mediaBox) // where pdfPage is a CGPDFPage
let pageSize = pageRect.size

A more full example showing how to extract the dimensions of page in a PDF file:

/**
 Returns the dimensions of a PDF page.
 - Parameter pdfURL: The URL of the PDF file.
 - Parameter pageNumber: The number of the page to obtain dimensions (Note: page numbers start from `1`, not `0`)
 */
func pageDimension(pdfURL: URL, pageNumber: Int) -> CGSize? {

    // convert URL to NSURL which is toll-free-briged with CFURL
    let url = pdfURL as NSURL
    guard let pdf = CGPDFDocument(url) else { return nil }
    guard let pdfPage = pdf.page(at: pageNumber) else { return nil }

    let pageRect = pdfPage.getBoxRect(CGPDFBox.mediaBox)
    let pageSize = pageRect.size

    return pageSize
}

let url = Bundle.main.url(forResource: "file", withExtension: "pdf")!
let dimensions = pageDimension(pdfURL: url, pageNumber: 1)
print(dimensions ?? "Cannot get dimensions")

I took Donal O'Danachair's answer and made a few modifications so the rect size is also scaled to the pdf's size. This code snipped actually gets all the annotations off a pdf page and creates the CGRect from the PDF rect. Part of the code is form the answer to a question Donal commented on his.

CGPDFDictionaryRef pageDictionary = CGPDFPageGetDictionary(pageRef);

    CGFloat boundsWidth = pdfView.bounds.size.width;
    CGFloat boundsHeight = pdfView.bounds.size.height;
    CGRect cropBoxRect = CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox);
    CGRect mediaBoxRect = CGPDFPageGetBoxRect(pageRef, kCGPDFMediaBox);
    CGRect effectiveRect = CGRectIntersection(cropBoxRect, mediaBoxRect);

    CGFloat effectiveWidth = effectiveRect.size.width;
    CGFloat effectiveHeight = effectiveRect.size.height;

    CGFloat widthScale = (boundsWidth / effectiveWidth);
    CGFloat heightScale = (boundsHeight / effectiveHeight);

    CGFloat pdfScale = (widthScale < heightScale) ? widthScale : heightScale;

    CGFloat x_offset = ((boundsWidth - (effectiveWidth * pdfScale)) / 2.0f);
    CGFloat y_offset = ((boundsHeight - (effectiveHeight * pdfScale)) / 2.0f);

    y_offset = (boundsHeight - y_offset); // Co-ordinate system adjust

    //CGFloat x_translate = (x_offset - effectiveRect.origin.x);
    //CGFloat y_translate = (y_offset + effectiveRect.origin.y);

    CGPDFArrayRef outputArray;

    if(!CGPDFDictionaryGetArray(pageDictionary, "Annots", &outputArray)) {
        return;
    }

    int arrayCount = CGPDFArrayGetCount( outputArray );
    if(!arrayCount) {
        //continue;
    }

    self.annotationRectArray = [[NSMutableArray alloc] initWithCapacity:arrayCount];

    for( int j = 0; j < arrayCount; ++j ) {
        CGPDFObjectRef aDictObj;
        if(!CGPDFArrayGetObject(outputArray, j, &aDictObj)) {
            return;
        }

        CGPDFDictionaryRef annotDict;
        if(!CGPDFObjectGetValue(aDictObj, kCGPDFObjectTypeDictionary, &annotDict)) {
            return;
        }

        CGPDFDictionaryRef aDict;
        if(!CGPDFDictionaryGetDictionary(annotDict, "A", &aDict)) {
            return;
        }

        CGPDFStringRef uriStringRef;
        if(!CGPDFDictionaryGetString(aDict, "URI", &uriStringRef)) {
            return;
        }

        CGPDFArrayRef rectArray;
        if(!CGPDFDictionaryGetArray(annotDict, "Rect", &rectArray)) {
            return;
        }

        int arrayCount = CGPDFArrayGetCount( rectArray );
        CGPDFReal coords[4];
        for( int k = 0; k < arrayCount; ++k ) {
            CGPDFObjectRef rectObj;
            if(!CGPDFArrayGetObject(rectArray, k, &rectObj)) {
                return;
            }

            CGPDFReal coord;
            if(!CGPDFObjectGetValue(rectObj, kCGPDFObjectTypeReal, &coord)) {
                return;
            }

            coords[k] = coord;
        }               

        char *uriString = (char *)CGPDFStringGetBytePtr(uriStringRef);
        //******* getting the page size

        CGPDFArrayRef pageBoxArray;
        if(!CGPDFDictionaryGetArray(pageDictionary, "MediaBox", &pageBoxArray)) {
            return; // we've got something wrong here!!!
        }

        int pageBoxArrayCount = CGPDFArrayGetCount( pageBoxArray );
        CGPDFReal pageCoords[4];
        for( int k = 0; k < pageBoxArrayCount; ++k )
        {
            CGPDFObjectRef pageRectObj;
            if(!CGPDFArrayGetObject(pageBoxArray, k, &pageRectObj))
            {
                return;
            }

            CGPDFReal pageCoord;
            if(!CGPDFObjectGetValue(pageRectObj, kCGPDFObjectTypeReal, &pageCoord)) {
                return;
            }

            pageCoords[k] = pageCoord;
        }

#if DEBUG
        NSLog(@"PDF coordinates -- bottom left x %f  ",pageCoords[0]); // should be 0
        NSLog(@"PDF coordinates -- bottom left y %f  ",pageCoords[1]); // should be 0
        NSLog(@"PDF coordinates -- top right   x %f  ",pageCoords[2]);
        NSLog(@"PDF coordinates -- top right   y %f  ",pageCoords[3]);
        NSLog(@"-- i.e. PDF page is %f wide and %f high",pageCoords[2],pageCoords[3]);
#endif
        // **** now to convert a point on the page from PDF coordinates to iOS coordinates. 

        double PDFHeight, PDFWidth;
        PDFWidth =  pageCoords[2];
        PDFHeight = pageCoords[3];

        // the size of your iOS view or image into which you have rendered your PDF page 
        // in this example full screen iPad in portrait orientation  
        double iOSWidth = 768.0; 
        double iOSHeight = 1024.0;

        // the PDF co-ordinate values you want to convert 
        double PDFxval = coords[0];  // or whatever
        double PDFyval = coords[3]; // or whatever
        double PDFhval = (coords[3]-coords[1]);
        double PDFwVal = coords[2]-coords[0];

        // the iOS coordinate values
        CGFloat iOSxval, iOSyval,iOShval,iOSwval;

        iOSxval =  PDFxval * (iOSWidth/PDFWidth);
        iOSyval =  (PDFHeight - PDFyval) * (iOSHeight/PDFHeight);
        iOShval =  PDFhval *(iOSHeight/PDFHeight);// here I scale the width and height
        iOSwval = PDFwVal *(iOSWidth/PDFWidth);

#if DEBUG
        NSLog(@"PDF: { {%f %f }, { %f %f } }",PDFxval,PDFyval,PDFwVal,PDFhval);
        NSLog(@"iOS: { {%f %f }, { %f %f } }",iOSxval,iOSyval,iOSwval,iOShval);
#endif


        NSString *uri = [NSString stringWithCString:uriString encoding:NSUTF8StringEncoding];
        CGRect rect = CGRectMake(iOSxval,iOSyval,iOSwval,iOShval);// create the rect and use it as you wish
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!