Чтение PDF-файлов в виде строки через приложение iPhone - PullRequest
20 голосов
/ 02 марта 2010

У меня возникла проблема при разработке приложения для iPhone для чтения PDF. Я пробовал следующий код. Я знаю, что использовал неправильные методы для анализа - методы анализа используются только для целей поиска. Но я хочу преобразовать весь текст PDF в строку. Скажем, например, Apple MobileHIG.pdf - я использовал в этом коде.

@implementation NetPDFViewController

size_t totalPages;  // a variable to store total pages

// a method to get the pdf ref
CGPDFDocumentRef MyGetPDFDocumentRef (const char *filename) {
    CFStringRef path;
    CFURLRef url;
    CGPDFDocumentRef document;
    path = CFStringCreateWithCString (NULL, filename,kCFStringEncodingUTF8);
    url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, 0);
    CFRelease (path);
    document = CGPDFDocumentCreateWithURL (url);// 2
    CFRelease(url);
    int count = CGPDFDocumentGetNumberOfPages (document);// 3
    if (count == 0) {
        printf("`%s' needs at least one page!", filename);
        return NULL;
    }
    return document;
}

// table methods to parse pdf
static void op_MP (CGPDFScannerRef s, void *info) {
    const char *name;
    if (!CGPDFScannerPopName(s, &name))
        return;
    printf("MP /%s\n", name);   
}

static void op_DP (CGPDFScannerRef s, void *info) {
    const char *name;
    if (!CGPDFScannerPopName(s, &name))
        return;
    printf("DP /%s\n", name);   
}

static void op_BMC (CGPDFScannerRef s, void *info) {
    const char *name;
    if (!CGPDFScannerPopName(s, &name))
        return;
    printf("BMC /%s\n", name);  
}

static void op_BDC (CGPDFScannerRef s, void *info) {
    const char *name;
    if (!CGPDFScannerPopName(s, &name))
        return;
    printf("BDC /%s\n", name);  
}

static void op_EMC (CGPDFScannerRef s, void *info) {
    const char *name;
    if (!CGPDFScannerPopName(s, &name))
        return;
    printf("EMC /%s\n", name);  
}

// a method to display pdf page.

void MyDisplayPDFPage (CGContextRef myContext,size_t pageNumber,const char *filename) {
    CGPDFDocumentRef document;
    CGPDFPageRef page;
    document = MyGetPDFDocumentRef (filename);// 1
    totalPages=CGPDFDocumentGetNumberOfPages(document);
    page = CGPDFDocumentGetPage (document, pageNumber);// 2

    CGPDFDictionaryRef d;

    d = CGPDFPageGetDictionary(page);

// ----- edit   problem here - CGPDFDictionary is completely unknown 
// ----- as we don't know keys & values of it.
    CGPDFScannerRef myScanner; 
    CGPDFOperatorTableRef myTable;
    myTable = CGPDFOperatorTableCreate();
    CGPDFOperatorTableSetCallback (myTable, "MP", &op_MP);
    CGPDFOperatorTableSetCallback (myTable, "DP", &op_DP);
    CGPDFOperatorTableSetCallback (myTable, "BMC", &op_BMC);
    CGPDFOperatorTableSetCallback (myTable, "BDC", &op_BDC);
    CGPDFOperatorTableSetCallback (myTable, "EMC", &op_EMC);

    CGPDFContentStreamRef myContentStream = CGPDFContentStreamCreateWithPage (page);// 3
    myScanner = CGPDFScannerCreate (myContentStream, myTable, NULL);// 4

    CGPDFScannerScan (myScanner);// 5

//  CGPDFDictionaryRef d;

    CGPDFStringRef str; // represents a sequence of bytes

    d = CGPDFPageGetDictionary(page);

    if (CGPDFDictionaryGetString(d, "Thumb", &str)){
        CFStringRef s;
        s = CGPDFStringCopyTextString(str);
        if (s != NULL) {
            //need something in here in case it cant find anything
            NSLog(@"%@ testing it", s);
        }
        CFRelease(s);       
//      CFDataRef data = CGPDFStreamCopyData (stream, CGPDFDataFormatRaw);
    }

// -----------------------------------  

    CGContextDrawPDFPage (myContext, page);// 3
    CGContextTranslateCTM(myContext, 0, 20);
    CGContextScaleCTM(myContext, 1.0, -1.0);
    CGPDFDocumentRelease (document);// 4
}

- (void)viewDidLoad {
    [super viewDidLoad];


// -------------------------------------------------------- 
// code for simple direct image from pdf docs.
    UIGraphicsBeginImageContext(CGSizeMake(320, 460));
    initialPage=28;
    MyDisplayPDFPage(UIGraphicsGetCurrentContext(), initialPage, [[[NSBundle mainBundle] pathForResource:@"MobileHIG" ofType:@"pdf"] UTF8String]);
    imgV.image=UIGraphicsGetImageFromCurrentImageContext();
    imgV.image=[imgV.image rotate:UIImageOrientationDownMirrored];  
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    CGPoint LasttouchPoint =  [touch locationInView:self.view];
    int LasttouchX = LasttouchPoint.x;
    startpoint=LasttouchX;
}


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch *touch = [touches anyObject];
    CGPoint LasttouchPoint =  [touch locationInView:self.view];
    int LasttouchX = LasttouchPoint.x;
    endpoint=LasttouchX;
    if(startpoint>(endpoint+75)){
        initialPage++;
        [self loadPage:initialPage nextOne:YES];
    } else if((startpoint+75)<endpoint){
        initialPage--;
        [self loadPage:initialPage nextOne:NO];
    }
}


-(void)loadPage:(NSUInteger)page nextOne:(BOOL)yesOrNo{
    if(page<=totalPages && page>0){
        UIGraphicsBeginImageContext(CGSizeMake(720, 720));  
        MyDisplayPDFPage(UIGraphicsGetCurrentContext(), page, [[[NSBundle mainBundle] pathForResource:@"MobileHIG" ofType:@"pdf"] UTF8String]);

        CATransition *transition = [CATransition animation];
        transition.duration = 0.75;
        transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        transition.type=kCATransitionPush;
        if(yesOrNo){
            transition.subtype=kCATransitionFromRight;
        } else {
            transition.subtype=kCATransitionFromLeft;
        }

        transition.delegate = self;
        [imgV.layer addAnimation:transition forKey:nil];
        imgV.image=UIGraphicsGetImageFromCurrentImageContext();
        imgV.image=[imgV.image rotate:UIImageOrientationDownMirrored];
    }
}

Но мне не удалось прочитать ни одной строки из документа PDF. Чего еще не хватает?

Ответы [ 3 ]

14 голосов
/ 04 марта 2010

Если вы хотите извлечь некоторый контент из PDF-файла, вы можете прочитать следующее:

Анализ содержимого PDF

из руководства по программированию Quartz 2D.

По сути, вы будете использовать CGPDFScanner объект для разбора содержимого, который работает следующим образом. Вы регистрируете несколько обратных вызовов, которые будут автоматически вызываться Quartz 2D при обнаружении некоторых операторов pdf в потоке pdf. После этого начального шага вы фактически начинаете парсинг потока PDF.

Если коротко взглянуть на ваш код, кажется, что вы не выполняете шаги, необходимые для анализа pdf-содержимого страницы, которую вы просматриваете CGPDFDocumentGetPage(). Сначала вам нужно настроить обратные вызовы, используя CGPDFOperatorTableCreate() и CGPDFOperatorTableSetCallback(), затем вы получите страницу, вам нужно создать поток контента, используя эту страницу (используя CGPDFContentStreamCreateWithPage()), а затем создать экземпляры с CGPDFScanner по CGPDFScannerCreate() и фактически начать сканирование через CGPDFScannerScan().

В разделе «Анализ содержимого PDF» документа, указанного вышеупомянутым URL-адресом, содержится вся информация, необходимая для выполнения анализа PDF.

Надеюсь, это поможет.

5 голосов
/ 15 июля 2010

У меня есть библиотека, которая может сделать именно эту вещь, связанную здесь: Извлечение PDF-текста в Objective C

4 голосов
/ 03 марта 2010

Посмотрите, как это делает пример приложения QuartzDemo , в частности класс QuartzPDFView в файлах QuartzImages.h и QuartzImages.m. Показан пример загрузки PDF через Quartz.

...