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