/*
* 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;
}