diff options
author | crupest <crupest@outlook.com> | 2022-05-15 14:08:06 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-05-15 14:08:06 +0800 |
commit | 8ad2966933957ac5d6ff8dcd5e732736fd5e4dc6 (patch) | |
tree | 77e41cc14264060517c0f7ed95837012afb8342e /src/platform/graphics/quartz/ImageFactory.cpp | |
parent | 9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752 (diff) | |
download | cru-8ad2966933957ac5d6ff8dcd5e732736fd5e4dc6.tar.gz cru-8ad2966933957ac5d6ff8dcd5e732736fd5e4dc6.tar.bz2 cru-8ad2966933957ac5d6ff8dcd5e732736fd5e4dc6.zip |
...
Diffstat (limited to 'src/platform/graphics/quartz/ImageFactory.cpp')
-rw-r--r-- | src/platform/graphics/quartz/ImageFactory.cpp | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/platform/graphics/quartz/ImageFactory.cpp b/src/platform/graphics/quartz/ImageFactory.cpp new file mode 100644 index 00000000..a48b4b86 --- /dev/null +++ b/src/platform/graphics/quartz/ImageFactory.cpp @@ -0,0 +1,109 @@ +#include "cru/platform/graphics/quartz/ImageFactory.h" +#include "cru/common/Exception.h" +#include "cru/common/platform/osx/Convert.h" +#include "cru/platform/graphics/quartz/Convert.h" +#include "cru/platform/graphics/quartz/Image.h" +#include "cru/platform/Check.h" +#include "cru/platform/graphics/Image.h" + +#include <ImageIO/ImageIO.h> + +namespace cru::platform::graphics::quartz { +using cru::platform::osx::Convert; + +QuartzImageFactory::QuartzImageFactory(IGraphicsFactory* graphics_factory) + : OsxQuartzResource(graphics_factory) {} + +QuartzImageFactory::~QuartzImageFactory() {} + +std::unique_ptr<IImage> QuartzImageFactory::DecodeFromStream( + io::Stream* stream) { + CGDataProviderRef data_provider = ConvertStreamToCGDataProvider(stream); + CGImageSourceRef image_source = + CGImageSourceCreateWithDataProvider(data_provider, nullptr); + + CGImageRef cg_image = + CGImageSourceCreateImageAtIndex(image_source, 0, nullptr); + + CFRelease(image_source); + CGDataProviderRelease(data_provider); + + return std::unique_ptr<IImage>( + new QuartzImage(GetGraphicsFactory(), this, cg_image, true)); +} + +static String GetImageFormatUniformTypeIdentifier(ImageFormat format) { + switch (format) { + case ImageFormat::Png: + return u"public.png"; + case ImageFormat::Jpeg: + return u"public.jpeg"; + case ImageFormat::Gif: + return u"com.compuserve.gif"; + default: + throw Exception(u"Unknown image format."); + } +} + +void QuartzImageFactory::EncodeToStream(IImage* image, io::Stream* stream, + ImageFormat format, float quality) { + if (quality <= 0 || quality > 1) { + throw Exception(u"Invalid quality value."); + } + + auto quartz_image = CheckPlatform<QuartzImage>(image, GetPlatformId()); + auto cg_image = quartz_image->GetCGImage(); + + CFStringRef uti = Convert(GetImageFormatUniformTypeIdentifier(format)); + CGDataConsumerRef data_consumer = ConvertStreamToCGDataConsumer(stream); + CGImageDestinationRef destination = + CGImageDestinationCreateWithDataConsumer(data_consumer, uti, 1, nullptr); + + CFMutableDictionaryRef properties = + CFDictionaryCreateMutable(nullptr, 0, nullptr, nullptr); + CFNumberRef quality_wrap = + CFNumberCreate(nullptr, kCFNumberFloatType, &quality); + CFDictionaryAddValue(properties, kCGImageDestinationLossyCompressionQuality, + quality_wrap); + + CGImageDestinationAddImage(destination, cg_image, properties); + + if (!CGImageDestinationFinalize(destination)) { + throw Exception(u"Failed to finalize image destination."); + } + + CFRelease(quality_wrap); + CFRelease(properties); + CFRelease(destination); + CFRelease(data_consumer); + CFRelease(uti); +} + +std::unique_ptr<IImage> QuartzImageFactory::CreateBitmap(int width, + int height) { + if (width <= 0) throw Exception(u"Image width should be greater than 0."); + if (height <= 0) throw Exception(u"Image height should be greater than 0."); + + CGColorSpaceRef color_space = CGColorSpaceCreateDeviceRGB(); + + const auto buffer_size = width * height * 4; + auto buffer = new unsigned char[buffer_size]{0}; + + auto cg_data_provider = CGDataProviderCreateWithData( + nullptr, buffer, buffer_size, + [](void* info, const void* data, size_t size) { + delete[] static_cast<const unsigned char*>(data); + }); + + auto cg_image = + CGImageCreate(width, height, 8, 32, 4 * width, color_space, + kCGImageAlphaPremultipliedLast, cg_data_provider, nullptr, + true, kCGRenderingIntentDefault); + + CGColorSpaceRelease(color_space); + CGDataProviderRelease(cg_data_provider); + + return std::unique_ptr<IImage>( + new QuartzImage(GetGraphicsFactory(), this, cg_image, true, buffer)); +} +} // namespace cru::platform::graphics::quartz |