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 QuartzLoader::QuartzLoader(IO::Seekable &io):
61 priv->provider = CGDataProviderCreateSequential(&io, &callbacks);
62 priv->source = CGImageSourceCreateWithDataProvider(priv->provider, 0);
65 QuartzLoader::~QuartzLoader()
67 CFRelease(priv->source);
68 CFRelease(priv->provider);
72 bool QuartzLoader::detect(const string &sig)
74 CGImageSourceRef source = CGImageSourceCreateIncremental(0);
75 CFDataRef data = CFDataCreate(0, reinterpret_cast<const UInt8 *>(sig.data()), sig.size());
76 CGImageSourceUpdateData(source, data, false);
77 CGImageSourceStatus status = CGImageSourceGetStatus(source);
81 return status==kCGImageStatusIncomplete || status==kCGImageStatusReadingHeader;
84 void QuartzLoader::load(Image::Data &data)
86 CGImageRef image = CGImageSourceCreateImageAtIndex(priv->source, 0, 0);
88 throw bad_image_data("null image");
92 data.width = CGImageGetWidth(image);
93 data.height = CGImageGetHeight(image);
94 data.stride = CGImageGetBytesPerRow(image);
96 CGColorSpaceRef color = CGImageGetColorSpace(image);
97 CGColorSpaceModel model = CGColorSpaceGetModel(color);
98 CGImageAlphaInfo alpha = CGImageGetAlphaInfo(image);
99 if(model==kCGColorSpaceModelRGB)
101 if(alpha==kCGImageAlphaLast)
103 else if(alpha==kCGImageAlphaNoneSkipLast || alpha==kCGImageAlphaNoneSkipFirst)
105 else if(alpha==kCGImageAlphaNone)
108 throw unsupported_image_format("unknown alpha mode");
111 throw unsupported_image_format("unknown colorspace");
113 CGDataProviderRef dp = CGImageGetDataProvider(image);
114 CFDataRef image_data = CGDataProviderCopyData(dp);
115 data.data = new char[data.height*data.stride];
116 unsigned offset = (alpha==kCGImageAlphaNoneSkipFirst);
117 CFRange range = CFRangeMake(offset, CFDataGetLength(image_data)-offset);
118 CFDataGetBytes(image_data, range, reinterpret_cast<UInt8 *>(data.data));
119 CFRelease(image_data);
130 } // namespace Graphics