1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci//  c++ --std=c++11 coreGraphicsPdf2png.cpp -o coreGraphicsPdf2png  -framework ApplicationServices
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include <cstdio>
11cb93a386Sopenharmony_ci#include <memory>
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci#include <ApplicationServices/ApplicationServices.h>
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci#define ASSERT(x)                                \
16cb93a386Sopenharmony_ci    do {                                         \
17cb93a386Sopenharmony_ci        if (!(x)) {                              \
18cb93a386Sopenharmony_ci            fprintf(stderr, "ERROR: " __FILE__   \
19cb93a386Sopenharmony_ci                    ":%d (%s)\n", __LINE__, #x); \
20cb93a386Sopenharmony_ci            return 1;                            \
21cb93a386Sopenharmony_ci        }                                        \
22cb93a386Sopenharmony_ci    } while (false)                              \
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ciconst int PAGE = 1;
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ciint main(int argc, char** argv) {
27cb93a386Sopenharmony_ci    if (argc <= 1 || !*(argv[1]) || 0 == strcmp(argv[1], "-")) {
28cb93a386Sopenharmony_ci        fprintf(stderr, "usage:\n\t%s INPUT_PDF_FILE_PATH [OUTPUT_PNG_PATH]\n", argv[0]);
29cb93a386Sopenharmony_ci        return 1;
30cb93a386Sopenharmony_ci    }
31cb93a386Sopenharmony_ci    const char* output = argc > 2 ? argv[2] : nullptr;
32cb93a386Sopenharmony_ci    CGDataProviderRef data = CGDataProviderCreateWithFilename(argv[1]);
33cb93a386Sopenharmony_ci    ASSERT(data);
34cb93a386Sopenharmony_ci    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data);
35cb93a386Sopenharmony_ci    CGDataProviderRelease(data);
36cb93a386Sopenharmony_ci    ASSERT(pdf);
37cb93a386Sopenharmony_ci    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, PAGE);
38cb93a386Sopenharmony_ci    ASSERT(page);
39cb93a386Sopenharmony_ci    CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
40cb93a386Sopenharmony_ci    int w = (int)CGRectGetWidth(bounds);
41cb93a386Sopenharmony_ci    int h = (int)CGRectGetHeight(bounds);
42cb93a386Sopenharmony_ci    CGBitmapInfo info = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
43cb93a386Sopenharmony_ci    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
44cb93a386Sopenharmony_ci    ASSERT(cs);
45cb93a386Sopenharmony_ci    std::unique_ptr<uint32_t[]> bitmap(new uint32_t[w * h]);
46cb93a386Sopenharmony_ci    memset(bitmap.get(), 0xFF, 4 * w * h);
47cb93a386Sopenharmony_ci    CGContextRef ctx = CGBitmapContextCreate(bitmap.get(), w, h, 8, w * 4, cs, info);
48cb93a386Sopenharmony_ci    ASSERT(ctx);
49cb93a386Sopenharmony_ci    CGContextDrawPDFPage(ctx, page);
50cb93a386Sopenharmony_ci    CGPDFDocumentRelease(pdf);
51cb93a386Sopenharmony_ci    CGImageRef image = CGBitmapContextCreateImage(ctx);
52cb93a386Sopenharmony_ci    ASSERT(image);
53cb93a386Sopenharmony_ci    CGDataConsumerCallbacks procs;
54cb93a386Sopenharmony_ci    procs.putBytes = [](void* f, const void* buf, size_t s) {
55cb93a386Sopenharmony_ci        return fwrite(buf, 1, s, (FILE*)f);
56cb93a386Sopenharmony_ci    };
57cb93a386Sopenharmony_ci    procs.releaseConsumer = [](void* info) { fclose((FILE*)info); };
58cb93a386Sopenharmony_ci    FILE* ofile = (!output || !output[0] || 0 == strcmp(output, "-"))
59cb93a386Sopenharmony_ci        ? stdout : fopen(output, "wb");
60cb93a386Sopenharmony_ci    ASSERT(ofile);
61cb93a386Sopenharmony_ci    CGDataConsumerRef consumer = CGDataConsumerCreate(ofile, &procs);
62cb93a386Sopenharmony_ci    ASSERT(consumer);
63cb93a386Sopenharmony_ci    CGImageDestinationRef dst =
64cb93a386Sopenharmony_ci        CGImageDestinationCreateWithDataConsumer(consumer, kUTTypePNG, 1, nullptr);
65cb93a386Sopenharmony_ci    CFRelease(consumer);
66cb93a386Sopenharmony_ci    ASSERT(dst);
67cb93a386Sopenharmony_ci    CGImageDestinationAddImage(dst, image, nullptr);
68cb93a386Sopenharmony_ci    ASSERT(CGImageDestinationFinalize(dst));
69cb93a386Sopenharmony_ci    CFRelease(dst);
70cb93a386Sopenharmony_ci    CGImageRelease(image);
71cb93a386Sopenharmony_ci    CGColorSpaceRelease(cs);
72cb93a386Sopenharmony_ci    CGContextRelease(ctx);
73cb93a386Sopenharmony_ci    return 0;
74cb93a386Sopenharmony_ci}
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ci
77