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;
88 void QuartzLoader::load(Image::Data &data)
90 CGImageRef image = CGImageSourceCreateImageAtIndex(priv->source, 0, 0);
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)
107 else if(alpha==kCGImageAlphaNone || alpha==kCGImageAlphaNoneSkipFirst)
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 CFDataGetBytes(image_data, CFRangeMake(0, CFDataGetLength(image_data)), reinterpret_cast<UInt8 *>(data.data));
119 CFRelease(image_data);
123 if(alpha==kCGImageAlphaNoneSkipFirst)
125 const char *src = data.data;
126 if(alpha==kCGImageAlphaNoneSkipFirst)
128 char *dest = data.data;
129 for(unsigned y=0; y<data.height; ++y)
130 for(unsigned x=0; x<data.width; ++x)
132 for(unsigned i=0; i<3; ++i)
146 } // namespace Graphics