1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 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#include "include/codec/SkEncodedOrigin.h" 9cb93a386Sopenharmony_ci#include "include/ports/SkImageGeneratorCG.h" 10cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 11cb93a386Sopenharmony_ci#include "include/utils/mac/SkCGUtils.h" 12cb93a386Sopenharmony_ci#include "src/core/SkPixmapPriv.h" 13cb93a386Sopenharmony_ci#include "src/utils/mac/SkUniqueCFRef.h" 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_MAC 16cb93a386Sopenharmony_ci#include <ApplicationServices/ApplicationServices.h> 17cb93a386Sopenharmony_ci#endif 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_IOS 20cb93a386Sopenharmony_ci#include <CoreGraphics/CoreGraphics.h> 21cb93a386Sopenharmony_ci#include <ImageIO/ImageIO.h> 22cb93a386Sopenharmony_ci#include <MobileCoreServices/MobileCoreServices.h> 23cb93a386Sopenharmony_ci#endif 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_cinamespace { 26cb93a386Sopenharmony_ciclass ImageGeneratorCG : public SkImageGenerator { 27cb93a386Sopenharmony_cipublic: 28cb93a386Sopenharmony_ci ImageGeneratorCG(const SkImageInfo&, SkUniqueCFRef<CGImageSourceRef> imageSrc, 29cb93a386Sopenharmony_ci sk_sp<SkData> data, SkEncodedOrigin); 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_ciprotected: 32cb93a386Sopenharmony_ci sk_sp<SkData> onRefEncodedData() override; 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci bool onGetPixels(const SkImageInfo&, void* pixels, size_t rowBytes, const Options&) override; 35cb93a386Sopenharmony_ci 36cb93a386Sopenharmony_ciprivate: 37cb93a386Sopenharmony_ci const SkUniqueCFRef<CGImageSourceRef> fImageSrc; 38cb93a386Sopenharmony_ci const sk_sp<SkData> fData; 39cb93a386Sopenharmony_ci const SkEncodedOrigin fOrigin; 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci using INHERITED = SkImageGenerator; 42cb93a386Sopenharmony_ci}; 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_cistatic SkUniqueCFRef<CGImageSourceRef> data_to_CGImageSrc(SkData* data) { 45cb93a386Sopenharmony_ci SkUniqueCFRef<CGDataProviderRef> cgData( 46cb93a386Sopenharmony_ci CGDataProviderCreateWithData(data, data->data(), data->size(), nullptr)); 47cb93a386Sopenharmony_ci if (!cgData) { 48cb93a386Sopenharmony_ci return nullptr; 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci return SkUniqueCFRef<CGImageSourceRef>( 51cb93a386Sopenharmony_ci CGImageSourceCreateWithDataProvider(cgData.get(), nullptr)); 52cb93a386Sopenharmony_ci} 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci} // namespace 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_cistd::unique_ptr<SkImageGenerator> SkImageGeneratorCG::MakeFromEncodedCG(sk_sp<SkData> data) { 57cb93a386Sopenharmony_ci SkUniqueCFRef<CGImageSourceRef> imageSrc = data_to_CGImageSrc(data.get()); 58cb93a386Sopenharmony_ci if (!imageSrc) { 59cb93a386Sopenharmony_ci return nullptr; 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci SkUniqueCFRef<CFDictionaryRef> properties( 63cb93a386Sopenharmony_ci CGImageSourceCopyPropertiesAtIndex(imageSrc.get(), 0, nullptr)); 64cb93a386Sopenharmony_ci if (!properties) { 65cb93a386Sopenharmony_ci return nullptr; 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci CFNumberRef widthRef = static_cast<CFNumberRef>( 69cb93a386Sopenharmony_ci CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth)); 70cb93a386Sopenharmony_ci CFNumberRef heightRef = static_cast<CFNumberRef>( 71cb93a386Sopenharmony_ci CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight)); 72cb93a386Sopenharmony_ci if (nullptr == widthRef || nullptr == heightRef) { 73cb93a386Sopenharmony_ci return nullptr; 74cb93a386Sopenharmony_ci } 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci int width, height; 77cb93a386Sopenharmony_ci if (!CFNumberGetValue(widthRef , kCFNumberIntType, &width ) || 78cb93a386Sopenharmony_ci !CFNumberGetValue(heightRef, kCFNumberIntType, &height)) 79cb93a386Sopenharmony_ci { 80cb93a386Sopenharmony_ci return nullptr; 81cb93a386Sopenharmony_ci } 82cb93a386Sopenharmony_ci 83cb93a386Sopenharmony_ci bool hasAlpha = bool(CFDictionaryGetValue(properties.get(), kCGImagePropertyHasAlpha)); 84cb93a386Sopenharmony_ci SkAlphaType alphaType = hasAlpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType; 85cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeS32(width, height, alphaType); 86cb93a386Sopenharmony_ci 87cb93a386Sopenharmony_ci SkEncodedOrigin origin = kDefault_SkEncodedOrigin; 88cb93a386Sopenharmony_ci CFNumberRef orientationRef = static_cast<CFNumberRef>( 89cb93a386Sopenharmony_ci CFDictionaryGetValue(properties.get(), kCGImagePropertyOrientation)); 90cb93a386Sopenharmony_ci int originInt; 91cb93a386Sopenharmony_ci if (orientationRef && CFNumberGetValue(orientationRef, kCFNumberIntType, &originInt)) { 92cb93a386Sopenharmony_ci origin = (SkEncodedOrigin) originInt; 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci if (SkEncodedOriginSwapsWidthHeight(origin)) { 96cb93a386Sopenharmony_ci info = SkPixmapPriv::SwapWidthHeight(info); 97cb93a386Sopenharmony_ci } 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci // FIXME: We have the opportunity to extract color space information here, 100cb93a386Sopenharmony_ci // though I think it makes sense to wait until we understand how 101cb93a386Sopenharmony_ci // we want to communicate it to the generator. 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci return std::unique_ptr<SkImageGenerator>(new ImageGeneratorCG(info, std::move(imageSrc), 104cb93a386Sopenharmony_ci std::move(data), origin)); 105cb93a386Sopenharmony_ci} 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ciImageGeneratorCG::ImageGeneratorCG(const SkImageInfo& info, SkUniqueCFRef<CGImageSourceRef> src, 108cb93a386Sopenharmony_ci sk_sp<SkData> data, SkEncodedOrigin origin) 109cb93a386Sopenharmony_ci : INHERITED(info) 110cb93a386Sopenharmony_ci , fImageSrc(std::move(src)) 111cb93a386Sopenharmony_ci , fData(std::move(data)) 112cb93a386Sopenharmony_ci , fOrigin(origin) 113cb93a386Sopenharmony_ci{} 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_cisk_sp<SkData> ImageGeneratorCG::onRefEncodedData() { 116cb93a386Sopenharmony_ci return fData; 117cb93a386Sopenharmony_ci} 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_cibool ImageGeneratorCG::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, 120cb93a386Sopenharmony_ci const Options&) 121cb93a386Sopenharmony_ci{ 122cb93a386Sopenharmony_ci if (kN32_SkColorType != info.colorType()) { 123cb93a386Sopenharmony_ci // FIXME: Support other colorTypes. 124cb93a386Sopenharmony_ci return false; 125cb93a386Sopenharmony_ci } 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci switch (info.alphaType()) { 128cb93a386Sopenharmony_ci case kOpaque_SkAlphaType: 129cb93a386Sopenharmony_ci if (kOpaque_SkAlphaType != this->getInfo().alphaType()) { 130cb93a386Sopenharmony_ci return false; 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci break; 133cb93a386Sopenharmony_ci case kPremul_SkAlphaType: 134cb93a386Sopenharmony_ci break; 135cb93a386Sopenharmony_ci default: 136cb93a386Sopenharmony_ci return false; 137cb93a386Sopenharmony_ci } 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_ci SkUniqueCFRef<CGImageRef> image(CGImageSourceCreateImageAtIndex(fImageSrc.get(), 0, nullptr)); 140cb93a386Sopenharmony_ci if (!image) { 141cb93a386Sopenharmony_ci return false; 142cb93a386Sopenharmony_ci } 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci SkPixmap dst(info, pixels, rowBytes); 145cb93a386Sopenharmony_ci auto decode = [&image](const SkPixmap& pm) { 146cb93a386Sopenharmony_ci // FIXME: Using SkCopyPixelsFromCGImage (as opposed to swizzling 147cb93a386Sopenharmony_ci // ourselves) greatly restricts the color and alpha types that we 148cb93a386Sopenharmony_ci // support. If we swizzle ourselves, we can add support for: 149cb93a386Sopenharmony_ci // kUnpremul_SkAlphaType 150cb93a386Sopenharmony_ci // 16-bit per component RGBA 151cb93a386Sopenharmony_ci // kGray_8_SkColorType 152cb93a386Sopenharmony_ci // Additionally, it would be interesting to compare the performance 153cb93a386Sopenharmony_ci // of SkSwizzler with CG's built in swizzler. 154cb93a386Sopenharmony_ci return SkCopyPixelsFromCGImage(pm, image.get()); 155cb93a386Sopenharmony_ci }; 156cb93a386Sopenharmony_ci return SkPixmapPriv::Orient(dst, fOrigin, decode); 157cb93a386Sopenharmony_ci} 158