| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2008 The Android Open Source Project | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #include "SkTypes.h" | |
| 9 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) | |
| 10 | |
| 11 #include "SkCGUtils.h" | |
| 12 #include "SkColorPriv.h" | |
| 13 #include "SkData.h" | |
| 14 #include "SkImageEncoder.h" | |
| 15 #include "SkMovie.h" | |
| 16 #include "SkStream.h" | |
| 17 #include "SkStreamPriv.h" | |
| 18 #include "SkTemplates.h" | |
| 19 #include "SkUnPreMultiply.h" | |
| 20 | |
| 21 #ifdef SK_BUILD_FOR_MAC | |
| 22 #include <ApplicationServices/ApplicationServices.h> | |
| 23 #endif | |
| 24 | |
| 25 #ifdef SK_BUILD_FOR_IOS | |
| 26 #include <CoreGraphics/CoreGraphics.h> | |
| 27 #include <ImageIO/ImageIO.h> | |
| 28 #include <MobileCoreServices/MobileCoreServices.h> | |
| 29 #endif | |
| 30 | |
| 31 ///////////////////////////////////////////////////////////////////////// | |
| 32 | |
| 33 SkMovie* SkMovie::DecodeStream(SkStreamRewindable* stream) { | |
| 34 return nullptr; | |
| 35 } | |
| 36 | |
| 37 ///////////////////////////////////////////////////////////////////////// | |
| 38 | |
| 39 static size_t consumer_put(void* info, const void* buffer, size_t count) { | |
| 40 SkWStream* stream = reinterpret_cast<SkWStream*>(info); | |
| 41 return stream->write(buffer, count) ? count : 0; | |
| 42 } | |
| 43 | |
| 44 static void consumer_release(void* info) { | |
| 45 // we do nothing, since by design we don't "own" the stream (i.e. info) | |
| 46 } | |
| 47 | |
| 48 static CGDataConsumerRef SkStreamToCGDataConsumer(SkWStream* stream) { | |
| 49 CGDataConsumerCallbacks procs; | |
| 50 procs.putBytes = consumer_put; | |
| 51 procs.releaseConsumer = consumer_release; | |
| 52 // we don't own/reference the stream, so it our consumer must not live | |
| 53 // longer that our caller's ownership of the stream | |
| 54 return CGDataConsumerCreate(stream, &procs); | |
| 55 } | |
| 56 | |
| 57 static CGImageDestinationRef SkStreamToImageDestination(SkWStream* stream, | |
| 58 CFStringRef type) { | |
| 59 CGDataConsumerRef consumer = SkStreamToCGDataConsumer(stream); | |
| 60 if (nullptr == consumer) { | |
| 61 return nullptr; | |
| 62 } | |
| 63 SkAutoTCallVProc<const void, CFRelease> arconsumer(consumer); | |
| 64 | |
| 65 return CGImageDestinationCreateWithDataConsumer(consumer, type, 1, nullptr); | |
| 66 } | |
| 67 | |
| 68 class SkImageEncoder_CG : public SkImageEncoder { | |
| 69 public: | |
| 70 SkImageEncoder_CG(Type t) : fType(t) {} | |
| 71 | |
| 72 protected: | |
| 73 virtual bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality); | |
| 74 | |
| 75 private: | |
| 76 Type fType; | |
| 77 }; | |
| 78 | |
| 79 /* Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes | |
| 80 to our SkWStream. Since we don't reference/own the SkWStream, our consumer | |
| 81 must only live for the duration of the onEncode() method. | |
| 82 */ | |
| 83 bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm, | |
| 84 int quality) { | |
| 85 // Used for converting a bitmap to 8888. | |
| 86 const SkBitmap* bmPtr = &bm; | |
| 87 SkBitmap bitmap8888; | |
| 88 | |
| 89 CFStringRef type; | |
| 90 switch (fType) { | |
| 91 case kICO_Type: | |
| 92 type = kUTTypeICO; | |
| 93 break; | |
| 94 case kBMP_Type: | |
| 95 type = kUTTypeBMP; | |
| 96 break; | |
| 97 case kGIF_Type: | |
| 98 type = kUTTypeGIF; | |
| 99 break; | |
| 100 case kJPEG_Type: | |
| 101 type = kUTTypeJPEG; | |
| 102 break; | |
| 103 case kPNG_Type: | |
| 104 // PNG encoding an ARGB_4444 bitmap gives the following errors in GM
: | |
| 105 // <Error>: CGImageDestinationAddImage image could not be converted
to destination | |
| 106 // format. | |
| 107 // <Error>: CGImageDestinationFinalize image destination does not ha
ve enough images | |
| 108 // So instead we copy to 8888. | |
| 109 if (bm.colorType() == kARGB_4444_SkColorType) { | |
| 110 bm.copyTo(&bitmap8888, kN32_SkColorType); | |
| 111 bmPtr = &bitmap8888; | |
| 112 } | |
| 113 type = kUTTypePNG; | |
| 114 break; | |
| 115 default: | |
| 116 return false; | |
| 117 } | |
| 118 | |
| 119 CGImageDestinationRef dst = SkStreamToImageDestination(stream, type); | |
| 120 if (nullptr == dst) { | |
| 121 return false; | |
| 122 } | |
| 123 SkAutoTCallVProc<const void, CFRelease> ardst(dst); | |
| 124 | |
| 125 CGImageRef image = SkCreateCGImageRef(*bmPtr); | |
| 126 if (nullptr == image) { | |
| 127 return false; | |
| 128 } | |
| 129 SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image); | |
| 130 | |
| 131 CGImageDestinationAddImage(dst, image, nullptr); | |
| 132 return CGImageDestinationFinalize(dst); | |
| 133 } | |
| 134 | |
| 135 /////////////////////////////////////////////////////////////////////////////// | |
| 136 | |
| 137 static SkImageEncoder* sk_imageencoder_cg_factory(SkImageEncoder::Type t) { | |
| 138 switch (t) { | |
| 139 case SkImageEncoder::kICO_Type: | |
| 140 case SkImageEncoder::kBMP_Type: | |
| 141 case SkImageEncoder::kGIF_Type: | |
| 142 case SkImageEncoder::kJPEG_Type: | |
| 143 case SkImageEncoder::kPNG_Type: | |
| 144 break; | |
| 145 default: | |
| 146 return nullptr; | |
| 147 } | |
| 148 return new SkImageEncoder_CG(t); | |
| 149 } | |
| 150 | |
| 151 static SkImageEncoder_EncodeReg gEReg(sk_imageencoder_cg_factory); | |
| 152 | |
| 153 class SkPNGImageEncoder_CG : public SkImageEncoder_CG { | |
| 154 public: | |
| 155 SkPNGImageEncoder_CG() | |
| 156 : SkImageEncoder_CG(kPNG_Type) { | |
| 157 } | |
| 158 }; | |
| 159 | |
| 160 DEFINE_ENCODER_CREATOR(PNGImageEncoder_CG); | |
| 161 | |
| 162 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) | |
| OLD | NEW |