void drawWithColorBlendMode(CGContextRef context, CFURLRef url)
{
    // A pleasant green color.
    float green[4] = { 0.584, 0.871, 0.318, 1.0 }; 
    CGRect insetRect, pdfRect;
    
    // Create a CGPDFDocument object from the URL.
    CGPDFDocumentRef pdfDoc = CGPDFDocumentCreateWithURL(url);
    if(pdfDoc == NULL){
		fprintf(stderr, "Couldn't create CGPDFDocument from URL!\n");
		return;
    }
    // Obtain the media box for page 1 of the PDF document.
    pdfRect = CGPDFDocumentGetMediaBox(pdfDoc, 1);
    // Set the origin of the rectangle to (0,0).
    pdfRect.origin.x = pdfRect.origin.y = 0;
    
    // Graphic 1, the left portion of the figure.
    CGContextTranslateCTM(context, 20, 10 + CGRectGetHeight(pdfRect)/2);
    
    // Draw the PDF document.
    CGContextDrawPDFDocument(context, pdfRect, pdfDoc, 1);
    
    // Set the fill color space to that returned by getTheCalibratedRGBColorSpace.
    CGContextSetFillColorSpace(context, getTheCalibratedRGBColorSpace());
    // Set the fill color to green.
    CGContextSetFillColor(context, green);
    
    // Graphic 2, the top-right portion of the figure.
    CGContextTranslateCTM(context, CGRectGetWidth(pdfRect) + 10, 
				    CGRectGetHeight(pdfRect)/2 + 10);

    // Draw the PDF document again.
    CGContextDrawPDFDocument(context, pdfRect, pdfDoc, 1);

    // Make a fill rectangle that is the same size as the PDF document
    // but inset each side by 80 units in x and 20 units in y.
    insetRect = CGRectInset(pdfRect, 80, 20);
    // Fill the rectangle with green. Because the fill color is opaque and
    // the blend mode is Normal, this obscures the drawing underneath. 
    CGContextFillRect(context, insetRect);
    
    // Graphic 3, the bottom-right portion of the figure.
    CGContextTranslateCTM(context, 0, -(10 + CGRectGetHeight(pdfRect)));

    // Draw the PDF document again.
    CGContextDrawPDFDocument(context, pdfRect, pdfDoc, 1);
    
    // Set the blend mode to kCGBlendModeColor which will
    // colorize the destination with subsequent drawing.
    CGContextSetBlendMode(context, kCGBlendModeColor);
    // Draw the rectangle on top of the PDF document. The portion of the
    // background that is covered by the rectangle is colorized
    // with the fill color.
    CGContextFillRect(context, insetRect);

    // Release the CGPDFDocumentRef the code created.
    CGPDFDocumentRelease(pdfDoc);
}
示例#2
0
int main(int argc, char** argv) {
    if (argc <= 1 || !*(argv[1]) || 0 == strcmp(argv[1], "-")) {
        fprintf(stderr, "usage:\n\t%s INPUT_PDF_FILE_PATH [OUTPUT_PNG_PATH]\n", argv[0]);
        return 1;
    }
    const char* output = argc > 2 ? argv[2] : nullptr;
    CGDataProviderRef data = CGDataProviderCreateWithFilename(argv[1]);
    ASSERT(data);
    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data);
    CGDataProviderRelease(data);
    ASSERT(pdf);
    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, PAGE);
    ASSERT(page);
    CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
    int w = (int)CGRectGetWidth(bounds);
    int h = (int)CGRectGetHeight(bounds);
    CGBitmapInfo info = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
    ASSERT(cs);
    std::unique_ptr<uint32_t[]> bitmap(new uint32_t[w * h]);
    memset(bitmap.get(), 0xFF, 4 * w * h);
    CGContextRef ctx = CGBitmapContextCreate(bitmap.get(), w, h, 8, w * 4, cs, info);
    ASSERT(ctx);
    CGContextDrawPDFPage(ctx, page);
    CGPDFDocumentRelease(pdf);
    CGImageRef image = CGBitmapContextCreateImage(ctx);
    ASSERT(image);
    CGDataConsumerCallbacks procs;
    procs.putBytes = [](void* f, const void* buf, size_t s) {
        return fwrite(buf, 1, s, (FILE*)f);
    };
    procs.releaseConsumer = [](void* info) {
        fclose((FILE*)info);
    };
    FILE* ofile = (!output || !output[0] || 0 == strcmp(output, "-"))
                  ? stdout : fopen(output, "wb");
    ASSERT(ofile);
    CGDataConsumerRef consumer = CGDataConsumerCreate(ofile, &procs);
    ASSERT(consumer);
    CGImageDestinationRef dst =
        CGImageDestinationCreateWithDataConsumer(consumer, kUTTypePNG, 1, nullptr);
    CFRelease(consumer);
    ASSERT(dst);
    CGImageDestinationAddImage(dst, image, nullptr);
    ASSERT(CGImageDestinationFinalize(dst));
    CFRelease(dst);
    CGImageRelease(image);
    CGColorSpaceRelease(cs);
    CGContextRelease(ctx);
    return 0;
}
/*	From an input PDF document and a PDF document whose contents you
    want to draw on top of the other, create a new PDF document
    containing all the pages of the input document with the first page
    of the "stamping" overlayed. 
*/
void createStampedFileWithFile(CFURLRef inURL, 
			CFURLRef stampURL, CFURLRef outURL)
{
    CGContextRef pdfContext = NULL;
    MyPDFData stampFileData, sourceFileData;
    sourceFileData = myCreatePDFSourceDocument(inURL);
    if(!sourceFileData.pdfDoc){
		fprintf(stderr, 
			"Can't create PDFDocumentRef for source input file!\n");
		return;
    }

    stampFileData = myCreatePDFSourceDocument(stampURL);
    if(!stampFileData.pdfDoc){
		CGPDFDocumentRelease(sourceFileData.pdfDoc);
		fprintf(stderr, 
			"Can't create PDFDocumentRef for file to stamp with!\n");
		return;
    }
    
    pdfContext = myCreatePDFContext(outURL, sourceFileData.mediaRect);
    if(!pdfContext){
		CGPDFDocumentRelease(sourceFileData.pdfDoc);
		CGPDFDocumentRelease(stampFileData.pdfDoc);
		fprintf(stderr, 
			"Can't create PDFContext for output file!\n");
		return;
    }
    
    StampWithPDFDocument(pdfContext, sourceFileData.pdfDoc, 
	    stampFileData.pdfDoc, stampFileData.mediaRect);
    
    CGContextRelease(pdfContext);
    CGPDFDocumentRelease(sourceFileData.pdfDoc);
    CGPDFDocumentRelease(stampFileData.pdfDoc);
}
示例#4
0
int generatePages(const char *documentPath) {
	int error = 0;
	CFStringRef path = CFStringCreateWithCString(
		NULL, documentPath, kCFStringEncodingUTF8
	);
	CFURLRef url = CFURLCreateWithFileSystemPath(
		NULL, path, kCFURLPOSIXPathStyle, 0
	);
	CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(url);

	if (document != NULL) {
		size_t lastPageIndex = CGPDFDocumentGetNumberOfPages(document) + 1;
		CFStringRef pdfPath = CFSTR("document.pdf");
		CFURLRef pdfUrl = CFURLCreateWithFileSystemPath(
			NULL, pdfPath, kCFURLPOSIXPathStyle, 0
		);
		CGContextRef context = CGPDFContextCreateWithURL(pdfUrl, NULL, NULL);

		printf("Compressing PDF\n");
		for(size_t pageIndex = 1; pageIndex < lastPageIndex; ++pageIndex) {
			CGPDFPageRef page = CGPDFDocumentGetPage(document, pageIndex);
			const CGRect cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox);

			printf("Adding page %lu\n", pageIndex);
			CGContextBeginPage(context, &cropBox);
			CGContextDrawPDFPage(context, page);
			CGContextEndPage(context);
		}

		CGContextRelease(context);
		if (pdfUrl != NULL) CFRelease(pdfUrl);
		if (pdfPath != NULL) CFRelease(pdfPath);
		CGPDFDocumentRelease(document);
	} else {
		fprintf(stderr, "Cannot open PDF document\n");
		error = 1;
	}

	if(url != NULL) CFRelease(url);
	if(path != NULL) CFRelease(path);

	return error;
}
示例#5
0
int main (int argc, const char * argv[])
{
    if(argc >= 2) {
        CGPDFDocumentRef doc = CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithFilename(argv[1]));
        size_t pages = CGPDFDocumentGetNumberOfPages(doc);
        
        printf("%lu pages\n", pages);
        
        for(size_t i = 1; i <= pages; i++) {
            char filename[1024];
            
            snprintf(filename, 1024, "%s.%03lu.png", argv[1], i);
            
            printf("writing file: %s\n", filename);
         
            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            CGContextRef context = CGBitmapContextCreate(NULL, SIZE, SIZE, 8, 4 * SIZE, colorSpace, kCGImageAlphaPremultipliedLast);
            CGColorSpaceRelease(colorSpace);
            
            CGContextDrawPDFDocument(context, CGRectMake(0, 0, SIZE, SIZE), doc, (int)i);
            
            CGImageRef image = CGBitmapContextCreateImage(context);
            
            CGImageDestinationRef dest = CGImageDestinationCreateWithURL(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFStringCreateWithCString(kCFAllocatorDefault, filename, kCFStringEncodingASCII), kCFURLPOSIXPathStyle, false), kUTTypePNG, 1, NULL);
            
            CGImageDestinationAddImage(dest, image, NULL);
            
            CGImageDestinationFinalize(dest);
            
            CGImageRelease(image);
            CGContextRelease(context);
        }
        
        CGPDFDocumentRelease(doc);
    } else {
        printf("pdf2png [filename]\n");
        return 1;
    }
    
    return 0;
}
CGPDFDocumentRef getThePDFDoc(CFURLRef url, float *w, float *h)
/*
    This function caches a CGPDFDocumentRef for
    the most recently requested PDF document.
*/
{
    static CGPDFDocumentRef pdfDoc = NULL;
    static CFURLRef pdfURL = NULL;
    static float width = 0, height = 0;
    
    if(url == NULL)
		return;
    
    // See whether to update the cached PDF document.
    if(pdfDoc == NULL || url != pdfURL){ 
		// Release any cached document or URL.
		if (pdfDoc) CGPDFDocumentRelease(pdfDoc);
		if (pdfURL) CFRelease(pdfURL);
		
		pdfDoc = CGPDFDocumentCreateWithURL(url);
		if(pdfDoc != NULL){
			CGRect pdfMediaRect = CGPDFDocumentGetMediaBox(pdfDoc, 1);
			width = pdfMediaRect.size.width;
			height = pdfMediaRect.size.height;
			// Retain the URL of the PDF file being cached.
			pdfURL = CFRetain(url);
		}else{
			pdfURL = NULL;
		}
    }
    
    if(pdfDoc){
		// Let the caller know the width and height of the document.
		*w = width;
		*h = height;
    }
    
    return pdfDoc;
}
示例#7
0
PDFDocumentImage::~PDFDocumentImage()
{
    CGPDFDocumentRelease(m_document);
}
 ~SkAutoPDFRelease() {
     if (fDoc) {
         CGPDFDocumentRelease(fDoc);
     }
 }
void dumpPageStreams(CFURLRef url, FILE *outFile)
{
    CGPDFDocumentRef pdfDoc = NULL;
    CGPDFOperatorTableRef table = NULL;
    MyDataScan myData;
    size_t totalImages, totPages, i;

    // Create a CGPDFDocumentRef from the input PDF file.
    pdfDoc = CGPDFDocumentCreateWithURL(url);
    if(!pdfDoc){
		fprintf(stderr, "Couldn't open PDF document!\n"); return;
    }
    // Create the operator table with the needed callbacks.
    table = createMyOperatorTable();
    if(!table){
		CGPDFDocumentRelease(pdfDoc);
		fprintf(stderr, "Couldn't create operator table\n!"); return;
    }
    // Initialize the count of the images.
    totalImages = 0;

    // Obtain the total number of pages for the document.
    totPages = CGPDFDocumentGetNumberOfPages(pdfDoc);

    // Loop over all the pages in the document, scanning the
    // content stream of each one.
    for(i = 1; i <= totPages; i++){
		CGPDFScannerRef scanner = NULL;
		// Get the PDF page for this page in the document.
		CGPDFPageRef p = CGPDFDocumentGetPage(pdfDoc, i);
		// Create a reference to the content stream for this page.
		CGPDFContentStreamRef cs = CGPDFContentStreamCreateWithPage(p);
		if(!cs){
			CGPDFOperatorTableRelease(table);
			CGPDFDocumentRelease(pdfDoc);
			fprintf(stderr, 
			"Couldn't create content stream for page #%zd!\n", i);
			return;
		}
		// Create a scanner for this PDF document page.
		scanner = CGPDFScannerCreate(cs, table, &myData);
		if(!scanner){
			CGPDFContentStreamRelease(cs);
			CGPDFOperatorTableRelease(table);
			CGPDFDocumentRelease(pdfDoc);
			fprintf(stderr, "Couldn't create scanner for page #%zd!\n", i);
			return;
		}
		// Initialize the counters of images for this page.
		myData.numImagesWithColorThisPage = 0;
		myData.numImageMasksThisPage =  0;
		myData.numImagesMaskedWithMaskThisPage =  0;
		myData.numImagesMaskedWithColorsThisPage = 0;
	
		/* 	CGPDFScannerScan causes Quartz to scan the content stream,
			calling the callbacks in the table when the corresponding
			operator is encountered. Once the content stream for the
			page has been consumed or Quartz detects a malformed 
			content stream, CGPDFScannerScan returns. 
		*/
		if(!CGPDFScannerScan(scanner)){
			fprintf(stderr, "Scanner couldn't scan all of page #%zd!\n", i);
		}
		// Print the results for this page.
		printPageResults(outFile, myData, i);
		
		// Update the total count of images with the count of the
		// images on this page.
		totalImages += 
			myData.numImagesWithColorThisPage + 
			myData.numImageMasksThisPage +
			myData.numImagesMaskedWithMaskThisPage +
			myData.numImagesMaskedWithColorsThisPage;
	
		// Once the page has been scanned, release the 
		// scanner for this page.
		CGPDFScannerRelease(scanner);
		// Release the content stream for this page.
		CGPDFContentStreamRelease(cs);
		// Done with this page; loop to next page.
    }
    printDocResults(outFile, totPages, totalImages);

    // Release the operator table this code created.
    CGPDFOperatorTableRelease(table);
    // Release the input PDF CGPDFDocumentRef.
    CGPDFDocumentRelease(pdfDoc);
}