2 #include <ApplicationServices/ApplicationServices.h>
3 // Avoid messing up sigc++ headers
5 #include "quartzloader.h"
11 size_t get_bytes(void *info, void *buffer, size_t count)
13 Msp::IO::Seekable *io = reinterpret_cast<Msp::IO::Seekable *>(info);
14 char *cbuf = reinterpret_cast<char *>(buffer);
15 return io->read(cbuf, count);
18 off_t skip_forward(void *info, off_t count)
20 Msp::IO::Seekable *io = reinterpret_cast<Msp::IO::Seekable *>(info);
25 i += io->read(buf, min<unsigned>(sizeof(buf), count-i));
30 void rewind(void *info)
32 Msp::IO::Seekable *io = reinterpret_cast<Msp::IO::Seekable *>(info);
33 io->seek(0, Msp::IO::S_BEG);
36 CGDataProviderSequentialCallbacks callbacks =
51 struct QuartzLoader::Private
53 CGDataProviderRef provider;
54 CGImageSourceRef source;
58 ImageLoader::Register<QuartzLoader> QuartzLoader::reg;
60 QuartzLoader::QuartzLoader(IO::Seekable &io):
63 priv->provider = CGDataProviderCreateSequential(&io, &callbacks);
64 priv->source = CGImageSourceCreateWithDataProvider(priv->provider, 0);
67 QuartzLoader::~QuartzLoader()
69 CFRelease(priv->source);
70 CFRelease(priv->provider);
74 bool QuartzLoader::detect(const string &sig)
76 CGImageSourceRef source = CGImageSourceCreateIncremental(0);
77 CFDataRef data = CFDataCreate(0, reinterpret_cast<const UInt8 *>(sig.data()), sig.size());
78 CGImageSourceUpdateData(source, data, false);
79 CGImageSourceStatus status = CGImageSourceGetStatus(source);
83 return status==kCGImageStatusIncomplete || status==kCGImageStatusReadingHeader;
86 void QuartzLoader::load(Image::Data &data)
88 CGImageRef image = CGImageSourceCreateImageAtIndex(priv->source, 0, 0);
90 throw bad_image_data("null image");
94 data.width = CGImageGetWidth(image);
95 data.height = CGImageGetHeight(image);
96 data.stride = CGImageGetBytesPerRow(image);
98 CGColorSpaceRef color = CGImageGetColorSpace(image);
99 CGColorSpaceModel model = CGColorSpaceGetModel(color);
100 CGImageAlphaInfo alpha = CGImageGetAlphaInfo(image);
101 if(model==kCGColorSpaceModelRGB)
103 if(alpha==kCGImageAlphaLast)
105 else if(alpha==kCGImageAlphaNoneSkipLast || alpha==kCGImageAlphaNoneSkipFirst)
107 else if(alpha==kCGImageAlphaNone)
110 throw unsupported_image_format("unknown alpha mode");
113 throw unsupported_image_format("unknown colorspace");
115 CGDataProviderRef dp = CGImageGetDataProvider(image);
116 CFDataRef image_data = CGDataProviderCopyData(dp);
117 data.data = new char[data.height*data.stride];
118 unsigned offset = (alpha==kCGImageAlphaNoneSkipFirst);
119 CFRange range = CFRangeMake(offset, CFDataGetLength(image_data)-offset);
120 CFDataGetBytes(image_data, range, reinterpret_cast<UInt8 *>(data.data));
121 CFRelease(image_data);
132 } // namespace Graphics