26int main(
int argc,
char** argv) {
27 if (argc <= 1 || !*(
argv[1]) || 0 == strcmp(
argv[1],
"-")) {
28 fprintf(stderr,
"usage:\n\t%s INPUT_PDF_FILE_PATH [OUTPUT_PNG_PATH]\n",
argv[0]);
31 const char* output = argc > 2 ?
argv[2] :
nullptr;
32 CGDataProviderRef data = CGDataProviderCreateWithFilename(
argv[1]);
34 CGPDFDocumentRef
pdf = CGPDFDocumentCreateWithProvider(data);
35 CGDataProviderRelease(data);
37 CGPDFPageRef page = CGPDFDocumentGetPage(
pdf,
PAGE);
39 CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
40 int w = (
int)CGRectGetWidth(bounds);
41 int h = (
int)CGRectGetHeight(bounds);
42 CGBitmapInfo
info = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
43 CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
45 std::unique_ptr<uint32_t[]>
bitmap(
new uint32_t[
w *
h]);
46 memset(
bitmap.get(), 0xFF, 4 *
w *
h);
47 CGContextRef ctx = CGBitmapContextCreate(
bitmap.get(),
w,
h, 8,
w * 4, cs,
info);
49 CGContextDrawPDFPage(ctx, page);
50 CGPDFDocumentRelease(
pdf);
51 CGImageRef
image = CGBitmapContextCreateImage(ctx);
53 CGDataConsumerCallbacks procs;
54 procs.putBytes = [](
void* f,
const void* buf,
size_t s) {
55 return fwrite(buf, 1,
s, (FILE*)f);
57 procs.releaseConsumer = [](
void*
info) { fclose((FILE*)
info); };
58 FILE* ofile = (!output || !output[0] || 0 == strcmp(output,
"-"))
59 ? stdout : fopen(output,
"wb");
61 CGDataConsumerRef consumer = CGDataConsumerCreate(ofile, &procs);
63 CGImageDestinationRef dst =
64 CGImageDestinationCreateWithDataConsumer(consumer, kUTTypePNG, 1,
nullptr);
67 CGImageDestinationAddImage(dst,
image,
nullptr);
68 ASSERT(CGImageDestinationFinalize(dst));
70 CGImageRelease(
image);
71 CGColorSpaceRelease(cs);
72 CGContextRelease(ctx);