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