]> git.tdb.fi Git - libs/gui.git/blob - source/graphics/devil/devilloader.cpp
Implement automatic registration of image loaders
[libs/gui.git] / source / graphics / devil / devilloader.cpp
1 #include <algorithm>
2 #include <IL/il.h>
3 #include "devilloader.h"
4
5 using namespace std;
6
7 namespace {
8
9 unsigned char eof(void *handle)
10 {
11         return reinterpret_cast<Msp::IO::Seekable *>(handle)->eof();
12 }
13
14 int get(void *handle)
15 {
16         return reinterpret_cast<Msp::IO::Seekable *>(handle)->get();
17 }
18
19 int read(void *buf, unsigned size, unsigned count, void *handle)
20 {
21         Msp::IO::Seekable *io = reinterpret_cast<Msp::IO::Seekable *>(handle);
22         char *cbuf = reinterpret_cast<char *>(buf);
23         unsigned i = 0;
24         for(; i<count; ++i)
25         {
26                 unsigned len = io->read(cbuf, size);
27                 cbuf += size;
28                 if(len<size)
29                         break;
30         }
31         return i;
32 }
33
34 int seek(void *handle, int offset, int il_type)
35 {
36         Msp::IO::SeekType type;
37         if(il_type==IL_SEEK_SET)
38                 type = Msp::IO::S_BEG;
39         else if(il_type==IL_SEEK_CUR)
40                 type = Msp::IO::S_CUR;
41         else if(il_type==IL_SEEK_END)
42                 type = Msp::IO::S_END;
43         else
44                 return -1;
45
46         reinterpret_cast<Msp::IO::Seekable *>(handle)->seek(offset, type);
47
48         return 0;
49 }
50
51 int tell(void *handle)
52 {
53         return reinterpret_cast<Msp::IO::Seekable *>(handle)->tell();
54 }
55
56 } // namespace
57
58
59 namespace Msp {
60 namespace Graphics {
61
62 ImageLoader::Register<DevilLoader> DevilLoader::reg;
63
64 DevilLoader::DevilLoader(IO::Seekable &i):
65         io(i)
66 {
67         static bool il_init_done = false;
68
69         if(!il_init_done)
70         {
71                 ilInit();
72                 ilEnable(IL_ORIGIN_SET);
73                 ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
74                 il_init_done = true;
75         }
76
77         ilGenImages(1, &id);
78 }
79
80 DevilLoader::~DevilLoader()
81 {
82         ilDeleteImages(1, &id);
83 }
84
85 bool DevilLoader::detect(const string &sig)
86 {
87         unsigned type = ilDetermineTypeL(sig.data(), sig.size());
88         return type!=IL_TYPE_UNKNOWN;
89 }
90
91 void DevilLoader::load(Image::Data &data)
92 {
93         ilSetRead(0, 0, eof, get, read, seek, tell);
94         ilBindImage(id);
95         ilLoadF(IL_TYPE_UNKNOWN, &io);
96
97         switch(ilGetInteger(IL_IMAGE_FORMAT))
98         {
99         case IL_COLOR_INDEX:     data.fmt = COLOR_INDEX; break;
100         case IL_LUMINANCE:       data.fmt = LUMINANCE; break;
101         case IL_LUMINANCE_ALPHA: data.fmt = LUMINANCE_ALPHA; break;
102         case IL_RGB:             data.fmt = RGB; break;
103         case IL_RGBA:            data.fmt = RGBA; break;
104         case IL_BGR:             data.fmt = BGR; break;
105         case IL_BGRA:            data.fmt = BGRA; break;
106         default: throw unsupported_image_format("unknown pixel format");
107         }
108
109         data.width = ilGetInteger(IL_IMAGE_WIDTH);
110         data.height = ilGetInteger(IL_IMAGE_HEIGHT);
111         unsigned data_size = data.width*data.height*ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL);
112         data.data = new char[data_size];
113         ILubyte *il_data = ilGetData();
114         copy(il_data, il_data+data_size, data.data);
115
116         ilBindImage(0);
117         ilResetRead();
118 }
119
120 } // namespace Graphics
121 } // namespace Msp