| Index: experimental/tools/coreGraphicsPdf2png.cpp
|
| diff --git a/experimental/tools/coreGraphicsPdf2png.cpp b/experimental/tools/coreGraphicsPdf2png.cpp
|
| index a8459326162428c5886330badd422193b2dc626e..c747a269ae0f868da865b11170e77496f373a1a6 100644
|
| --- a/experimental/tools/coreGraphicsPdf2png.cpp
|
| +++ b/experimental/tools/coreGraphicsPdf2png.cpp
|
| @@ -5,56 +5,72 @@
|
| * found in the LICENSE file.
|
| */
|
|
|
| -#include <stdio.h>
|
| -
|
| -#include "SkBitmap.h"
|
| -#include "SkCGUtils.h"
|
| -#include "SkForceLinking.h"
|
| -#include "SkImageEncoder.h"
|
| -#include "SkStream.h"
|
| -
|
| -__SK_FORCE_IMAGE_DECODER_LINKING;
|
| -
|
| -class StdOutWStream : public SkWStream {
|
| -public:
|
| - StdOutWStream() : fBytesWritten(0) {}
|
| - bool write(const void* buffer, size_t size) final {
|
| - fBytesWritten += size;
|
| - return size == fwrite(buffer, 1, size, stdout);
|
| - }
|
| - size_t bytesWritten() const final { return fBytesWritten; }
|
| +// c++ --std=c++11 coreGraphicsPdf2png.cpp -o coreGraphicsPdf2png -framework ApplicationServices
|
|
|
| -private:
|
| - size_t fBytesWritten;
|
| -};
|
| +#include <cstdio>
|
| +#include <memory>
|
|
|
| -static SkStreamAsset* open_for_reading(const char* path) {
|
| - if (!path || !path[0] || 0 == strcmp(path, "-")) {
|
| - return new SkFILEStream(stdin, SkFILEStream::kCallerRetains_Ownership);
|
| - }
|
| - return SkStream::NewFromFile(path);
|
| -}
|
| +#include <ApplicationServices/ApplicationServices.h>
|
|
|
| -static SkWStream* open_for_writing(const char* path) {
|
| - if (!path || !path[0] || 0 == strcmp(path, "-")) {
|
| - return new StdOutWStream;
|
| - }
|
| - return new SkFILEWStream(path);
|
| -}
|
| +#define ASSERT(x) \
|
| + do { \
|
| + if (!(x)) { \
|
| + fprintf(stderr, "ERROR: " __FILE__ \
|
| + ":%d (%s)\n", __LINE__, #x); \
|
| + return 1; \
|
| + } \
|
| + } while (false) \
|
|
|
| -static bool to_png(SkWStream* o, const SkBitmap& bm) {
|
| - return SkImageEncoder::EncodeStream(o, bm, SkImageEncoder::kPNG_Type, 100);
|
| -}
|
| +const int PAGE = 1;
|
|
|
| -// Note: I could implement this using only MacOS|CG API calls, but
|
| -// since most of this is already done in Skia, here it is.
|
| int main(int argc, char** argv) {
|
| - SkBitmap bm;
|
| - SkAutoTDelete<SkStream> in(open_for_reading(argc > 1 ? argv[1] : NULL));
|
| - SkAutoTDelete<SkWStream> out(open_for_writing(argc > 2 ? argv[2] : NULL));
|
| - if (SkPDFDocumentToBitmap(in.release(), &bm) && to_png(out, bm)) {
|
| - return 0;
|
| - } else {
|
| + 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;
|
| }
|
| +
|
| +
|
|
|