Add a brewfile
[opengl.git] / image.cpp
1 #include "image.hpp"
2 #include <ImageIO/ImageIO.h>
3
4 Image::Image(const std::string &path) {
5         CFStringRef str = CFStringCreateWithCString(NULL, path.c_str(), kCFStringEncodingUTF8);
6         CFURLRef url = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, false);
7         CGImageSourceRef source = CGImageSourceCreateWithURL(url, NULL);
8         CGImageRef ref = CGImageSourceCreateImageAtIndex(source, 0, NULL);
9         initWithImageRef(ref);
10         CGImageRelease(ref);
11 }
12
13 Image::Image(const unsigned char *data, size_t length, const char *formatHint) {
14         CGDataProviderRef dpRef = CGDataProviderCreateWithData(NULL, data, length, NULL);
15         CGImageRef ref;
16         if (strcmp("png", formatHint) == 0)
17                 ref = CGImageCreateWithPNGDataProvider(dpRef, NULL, false, kCGRenderingIntentDefault);
18         else if (strcmp("jpg", formatHint) == 0)
19                 ref = CGImageCreateWithJPEGDataProvider(dpRef, NULL, false, kCGRenderingIntentDefault);
20         else
21                 abort();
22         initWithImageRef(ref);
23         CGImageRelease(ref);
24 }
25
26 void Image::initWithImageRef(CGImageRef ref) {
27         _width = CGImageGetWidth(ref), _height = CGImageGetHeight(ref);
28         info = CGImageGetBitmapInfo(ref);
29         alphaInfo = CGImageGetAlphaInfo(ref);
30         colorSpace = CGImageGetColorSpace(ref);
31         bitsPerComponent = CGImageGetBitsPerComponent(ref);
32
33         dataRef = CGDataProviderCopyData(CGImageGetDataProvider(ref));
34 }
35
36 unsigned char *Image::data() const {
37         return (unsigned char*) CFDataGetBytePtr(dataRef);
38 }
39
40 GLfloat Image::width() const { return _width; }
41 GLfloat Image::height() const { return _height; }
42
43 // TODO: Properly implement this for both internal format + format
44 GLenum Image::format() const {
45         if (CGColorSpaceGetModel(colorSpace) == kCGColorSpaceModelMonochrome) {
46                 return GL_DEPTH_COMPONENT;
47         }
48         if (alphaInfo == kCGImageAlphaNone) {
49                 return GL_RGB;
50         }
51         return GL_RGBA;
52 }
53
54 inline bool Image::usesFloat() const { return info & kCGBitmapFloatComponents; }
55
56 GLint Image::internalFormat() const {
57         switch (format()) {
58                 case GL_DEPTH_COMPONENT: return GL_DEPTH_COMPONENT;
59         case GL_RGB:
60             if (bitsPerComponent == 16)
61                                 return usesFloat() ? GL_RGB16F : GL_RGB16;
62             else if (bitsPerComponent == 8)
63                                 return GL_RGB;
64             else abort();
65                 default: return GL_RGBA;
66         }
67 }
68
69 GLenum Image::type() const {
70         if (usesFloat()) {
71                 if (bitsPerComponent == 16) return GL_HALF_FLOAT;
72                 else if (bitsPerComponent == 32) return GL_FLOAT;
73                 abort();
74         }
75         return GL_UNSIGNED_BYTE;
76         
77         //TODO:
78         /* switch (bitsPerComponent) { */
79         /*      case 1: return GL_UNSIGNED_BYTE; */
80         /*      case 16: return GL_UNSIGNED_SHORT; */
81         /*  case 24: */ 
82 }
83
84 Image::~Image() { CFRelease(dataRef); }