2 #include <CoreGraphics/CGColorSpace.h>
3 #include <CoreGraphics/CGImage.h>
4 #include <ImageIO/CGImageSource.h>
5 // Avoid messing up sigc++ headers
7 #include "quartzloader.h"
13 size_t get_bytes(void *info, void *buffer, size_t count)
15 Msp::IO::Seekable *io = reinterpret_cast<Msp::IO::Seekable *>(info);
16 char *cbuf = reinterpret_cast<char *>(buffer);
17 return io->read(cbuf, count);
20 off_t skip_forward(void *info, off_t count)
22 Msp::IO::Seekable *io = reinterpret_cast<Msp::IO::Seekable *>(info);
27 i += io->read(buf, min<unsigned>(sizeof(buf), count-i));
32 void rewind(void *info)
34 Msp::IO::Seekable *io = reinterpret_cast<Msp::IO::Seekable *>(info);
35 io->seek(0, Msp::IO::S_BEG);
38 CGDataProviderSequentialCallbacks callbacks =
53 struct QuartzLoader::Private
55 CGDataProviderRef provider;
56 CGImageSourceRef source;
60 ImageLoader::Register<QuartzLoader> QuartzLoader::reg;
62 QuartzLoader::QuartzLoader(IO::Seekable &io):
65 priv->provider = CGDataProviderCreateSequential(&io, &callbacks);
66 priv->source = CGImageSourceCreateWithDataProvider(priv->provider, 0);
69 QuartzLoader::~QuartzLoader()
71 CFRelease(priv->source);
72 CFRelease(priv->provider);
76 bool QuartzLoader::detect(const string &sig)
78 CGImageSourceRef source = CGImageSourceCreateIncremental(0);
79 CFDataRef data = CFDataCreate(0, reinterpret_cast<const UInt8 *>(sig.data()), sig.size());
80 CGImageSourceUpdateData(source, data, false);
81 CGImageSourceStatus status = CGImageSourceGetStatus(source);
85 return status==kCGImageStatusIncomplete || status==kCGImageStatusReadingHeader;
88 void QuartzLoader::load(Image::Data &data)
90 CGImageRef image = CGImageSourceCreateImageAtIndex(priv->source, 0, 0);
92 throw bad_image_data("null image");
96 data.width = CGImageGetWidth(image);
97 data.height = CGImageGetHeight(image);
98 data.stride = CGImageGetBytesPerRow(image);
100 CGColorSpaceRef color = CGImageGetColorSpace(image);
101 CGColorSpaceModel model = CGColorSpaceGetModel(color);
102 CGImageAlphaInfo alpha = CGImageGetAlphaInfo(image);
103 if(model==kCGColorSpaceModelRGB)
105 if(alpha==kCGImageAlphaLast)
107 else if(alpha==kCGImageAlphaNoneSkipLast || alpha==kCGImageAlphaNoneSkipFirst)
109 else if(alpha==kCGImageAlphaNone)
112 throw unsupported_image_format("unknown alpha mode");
115 throw unsupported_image_format("unknown colorspace");
117 CGDataProviderRef dp = CGImageGetDataProvider(image);
118 CFDataRef image_data = CGDataProviderCopyData(dp);
119 data.data = new char[data.height*data.stride];
120 unsigned offset = (alpha==kCGImageAlphaNoneSkipFirst);
121 CFRange range = CFRangeMake(offset, CFDataGetLength(image_data)-offset);
122 CFDataGetBytes(image_data, range, reinterpret_cast<UInt8 *>(data.data));
123 CFRelease(image_data);
134 } // namespace Graphics