|  | /* | 
|  | * Copyright 2015 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | //  c++ --std=c++11 coreGraphicsPdf2png.cpp -o coreGraphicsPdf2png  -framework ApplicationServices | 
|  |  | 
|  | #include <cstdio> | 
|  | #include <memory> | 
|  |  | 
|  | #include <ApplicationServices/ApplicationServices.h> | 
|  |  | 
|  | #define ASSERT(x)                                \ | 
|  | do {                                         \ | 
|  | if (!(x)) {                              \ | 
|  | fprintf(stderr, "ERROR: " __FILE__   \ | 
|  | ":%d (%s)\n", __LINE__, #x); \ | 
|  | return 1;                            \ | 
|  | }                                        \ | 
|  | } while (false)                              \ | 
|  |  | 
|  | const int PAGE = 1; | 
|  |  | 
|  | 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; | 
|  | } | 
|  |  | 
|  |  |