/* Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes to our SkWStream. Since we don't reference/own the SkWStream, our consumer must only live for the duration of the onEncode() method. */ bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { CFStringRef type; switch (fType) { case kJPEG_Type: type = kUTTypeJPEG; break; case kPNG_Type: type = kUTTypePNG; break; default: return false; } CGImageDestinationRef dst = SkStreamToImageDestination(stream, type); if (NULL == dst) { return false; } SkAutoTCallVProc<const void, CFRelease> ardst(dst); CGImageRef image = SkCreateCGImageRef(bm); if (NULL == image) { return false; } SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image); CGImageDestinationAddImage(dst, image, NULL); CGImageDestinationFinalize(dst); return true; }
/* Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes to our SkWStream. Since we don't reference/own the SkWStream, our consumer must only live for the duration of the onEncode() method. */ bool SkEncodeImageWithCG(SkWStream* stream, const SkPixmap& pixmap, SkEncodedImageFormat format) { SkBitmap bm; if (!bm.installPixels(pixmap)) { return false; } bm.setImmutable(); CFStringRef type; switch (format) { case SkEncodedImageFormat::kICO: type = kUTTypeICO; break; case SkEncodedImageFormat::kBMP: type = kUTTypeBMP; break; case SkEncodedImageFormat::kGIF: type = kUTTypeGIF; break; case SkEncodedImageFormat::kJPEG: type = kUTTypeJPEG; break; case SkEncodedImageFormat::kPNG: // PNG encoding an ARGB_4444 bitmap gives the following errors in GM: // <Error>: CGImageDestinationAddImage image could not be converted to destination // format. // <Error>: CGImageDestinationFinalize image destination does not have enough images // So instead we copy to 8888. if (bm.colorType() == kARGB_4444_SkColorType) { SkBitmap bitmapN32; bitmapN32.allocPixels(bm.info().makeColorType(kN32_SkColorType)); bm.readPixels(bitmapN32.info(), bitmapN32.getPixels(), bitmapN32.rowBytes(), 0, 0); bm.swap(bitmapN32); } type = kUTTypePNG; break; default: return false; } CGImageDestinationRef dst = SkStreamToImageDestination(stream, type); if (nullptr == dst) { return false; } SkAutoTCallVProc<const void, CFRelease> ardst(dst); CGImageRef image = SkCreateCGImageRef(bm); if (nullptr == image) { return false; } SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image); CGImageDestinationAddImage(dst, image, nullptr); return CGImageDestinationFinalize(dst); }
/* Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes to our SkWStream. Since we don't reference/own the SkWStream, our consumer must only live for the duration of the onEncode() method. */ bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm, int quality) { // Used for converting a bitmap to 8888. const SkBitmap* bmPtr = &bm; SkBitmap bitmap8888; CFStringRef type; switch (fType) { case kICO_Type: type = kUTTypeICO; break; case kBMP_Type: type = kUTTypeBMP; break; case kGIF_Type: type = kUTTypeGIF; break; case kJPEG_Type: type = kUTTypeJPEG; break; case kPNG_Type: // PNG encoding an ARGB_4444 bitmap gives the following errors in GM: // <Error>: CGImageDestinationAddImage image could not be converted to destination // format. // <Error>: CGImageDestinationFinalize image destination does not have enough images // So instead we copy to 8888. if (bm.colorType() == kARGB_4444_SkColorType) { bm.copyTo(&bitmap8888, kN32_SkColorType); bmPtr = &bitmap8888; } type = kUTTypePNG; break; default: return false; } CGImageDestinationRef dst = SkStreamToImageDestination(stream, type); if (NULL == dst) { return false; } SkAutoTCallVProc<const void, CFRelease> ardst(dst); CGImageRef image = SkCreateCGImageRef(*bmPtr); if (NULL == image) { return false; } SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image); CGImageDestinationAddImage(dst, image, NULL); return CGImageDestinationFinalize(dst); }