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; |
} |
+ |
+ |