#include "image.hpp"
+#include <ImageIO/ImageIO.h>
Image::Image(const std::string &path) {
- auto provider = CGDataProviderCreateWithFilename(path.c_str());
- std::ifstream file(path);
- long magic;
- file.read((char*)&magic, 8);
- file.close();
+ CFStringRef str = CFStringCreateWithCString(NULL, path.c_str(), kCFStringEncodingUTF8);
+ CFURLRef url = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, false);
+ CGImageSourceRef source = CGImageSourceCreateWithURL(url, NULL);
+ CGImageRef ref = CGImageSourceCreateImageAtIndex(source, 0, NULL);
+ initWithImageRef(ref);
+ CGImageRelease(ref);
+}
+Image::Image(const unsigned char *data, size_t length, const char *formatHint) {
+ CGDataProviderRef dpRef = CGDataProviderCreateWithData(NULL, data, length, NULL);
CGImageRef ref;
-
- if (magic == 0x0a1a0a0d474e5089) // png magic number
- ref = CGImageCreateWithPNGDataProvider(provider, nullptr, false, kCGRenderingIntentDefault);
+ if (strcmp("png", formatHint) == 0)
+ ref = CGImageCreateWithPNGDataProvider(dpRef, NULL, false, kCGRenderingIntentDefault);
+ else if (strcmp("jpg", formatHint) == 0)
+ ref = CGImageCreateWithJPEGDataProvider(dpRef, NULL, false, kCGRenderingIntentDefault);
else
- ref = CGImageCreateWithJPEGDataProvider(provider, nullptr, false, kCGRenderingIntentDefault);
+ abort();
+ initWithImageRef(ref);
+ CGImageRelease(ref);
+}
+void Image::initWithImageRef(CGImageRef ref) {
_width = CGImageGetWidth(ref), _height = CGImageGetHeight(ref);
+ info = CGImageGetBitmapInfo(ref);
+ alphaInfo = CGImageGetAlphaInfo(ref);
+ colorSpace = CGImageGetColorSpace(ref);
+ bitsPerComponent = CGImageGetBitsPerComponent(ref);
dataRef = CGDataProviderCopyData(CGImageGetDataProvider(ref));
- CGImageRelease(ref);
-
}
-unsigned char *Image::data() {
+unsigned char *Image::data() const {
return (unsigned char*) CFDataGetBytePtr(dataRef);
}
GLfloat Image::width() const { return _width; }
GLfloat Image::height() const { return _height; }
+// TODO: Properly implement this for both internal format + format
+GLenum Image::format() const {
+ if (CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelMonochrome) {
+ return GL_DEPTH_COMPONENT;
+ }
+ if (alphaInfo == kCGImageAlphaNone) {
+ return GL_RGB;
+ }
+ return GL_RGBA;
+}
+
+inline bool Image::usesFloat() const { return info & kCGBitmapFloatComponents; }
+
+GLint Image::internalFormat() const {
+ switch (format()) {
+ case GL_DEPTH_COMPONENT: return GL_DEPTH_COMPONENT;
+ case GL_RGB:
+ if (bitsPerComponent == 16)
+ return usesFloat() ? GL_RGB16F : GL_RGB16;
+ else if (bitsPerComponent == 8)
+ return GL_RGB;
+ else abort();
+ default: return GL_RGBA;
+ }
+}
+
+GLenum Image::type() const {
+ if (usesFloat()) {
+ if (bitsPerComponent == 16) return GL_HALF_FLOAT;
+ else if (bitsPerComponent == 32) return GL_FLOAT;
+ abort();
+ }
+ return GL_UNSIGNED_BYTE;
+
+ //TODO:
+ /* switch (bitsPerComponent) { */
+ /* case 1: return GL_UNSIGNED_BYTE; */
+ /* case 16: return GL_UNSIGNED_SHORT; */
+ /* case 24: */
+}
+
Image::~Image() { CFRelease(dataRef); }