|
1096
|
1 /**
|
|
|
2 * Copyright (c) 2006-2012 LOVE Development Team
|
|
|
3 *
|
|
|
4 * This software is provided 'as-is', without any express or implied
|
|
|
5 * warranty. In no event will the authors be held liable for any damages
|
|
|
6 * arising from the use of this software.
|
|
|
7 *
|
|
|
8 * Permission is granted to anyone to use this software for any purpose,
|
|
|
9 * including commercial applications, and to alter it and redistribute it
|
|
|
10 * freely, subject to the following restrictions:
|
|
|
11 *
|
|
|
12 * 1. The origin of this software must not be misrepresented; you must not
|
|
|
13 * claim that you wrote the original software. If you use this software
|
|
|
14 * in a product, an acknowledgment in the product documentation would be
|
|
|
15 * appreciated but is not required.
|
|
|
16 * 2. Altered source versions must be plainly marked as such, and must not be
|
|
|
17 * misrepresented as being the original software.
|
|
|
18 * 3. This notice may not be removed or altered from any source distribution.
|
|
|
19 **/
|
|
|
20
|
|
|
21 #include "ImageData.h"
|
|
|
22
|
|
|
23 // STD
|
|
|
24 #include <cstring>
|
|
|
25 #include <iostream>
|
|
|
26
|
|
|
27 // LOVE
|
|
|
28 #include "common/Exception.h"
|
|
|
29 #include "common/math.h"
|
|
|
30 #include "filesystem/File.h"
|
|
|
31
|
|
|
32 using love::thread::Lock;
|
|
|
33
|
|
|
34 static Mutex devilMutex;
|
|
|
35
|
|
|
36 namespace love
|
|
|
37 {
|
|
|
38 namespace image
|
|
|
39 {
|
|
|
40 namespace devil
|
|
|
41 {
|
|
|
42
|
|
|
43 static inline void ilxClearErrors()
|
|
|
44 {
|
|
|
45 while (ilGetError() != IL_NO_ERROR);
|
|
|
46 }
|
|
|
47
|
|
|
48 ImageData::ImageData(Data *data)
|
|
|
49 {
|
|
|
50 load(data);
|
|
|
51 }
|
|
|
52
|
|
|
53 ImageData::ImageData(filesystem::File *file)
|
|
|
54 {
|
|
|
55 Data *data = file->read();
|
|
|
56 load(data);
|
|
|
57 data->release();
|
|
|
58 }
|
|
|
59
|
|
|
60 ImageData::ImageData(int width, int height)
|
|
|
61 {
|
|
|
62 this->width = width;
|
|
|
63 this->height = height;
|
|
|
64 create(width, height);
|
|
|
65
|
|
|
66 // Set to black.
|
|
|
67 memset(data, 0, width*height*4);
|
|
|
68 }
|
|
|
69
|
|
|
70 ImageData::ImageData(int width, int height, void *data)
|
|
|
71 {
|
|
|
72 this->width = width;
|
|
|
73 this->height = height;
|
|
|
74 create(width, height, data);
|
|
|
75 }
|
|
|
76
|
|
|
77 ImageData::~ImageData()
|
|
|
78 {
|
|
|
79 delete[] data;
|
|
|
80 }
|
|
|
81
|
|
|
82 void ImageData::create(int width, int height, void *data)
|
|
|
83 {
|
|
|
84 try
|
|
|
85 {
|
|
|
86 this->data = new unsigned char[width*height*sizeof(pixel)];
|
|
|
87 }
|
|
|
88 catch(std::bad_alloc &)
|
|
|
89 {
|
|
|
90 throw love::Exception("Out of memory");
|
|
|
91 }
|
|
|
92
|
|
|
93 if (data)
|
|
|
94 memcpy(this->data, data, width*height*sizeof(pixel));
|
|
|
95 }
|
|
|
96
|
|
|
97 void ImageData::load(Data *data)
|
|
|
98 {
|
|
|
99 Lock lock(devilMutex);
|
|
|
100 ILuint image;
|
|
|
101 ilGenImages(1, &image);
|
|
|
102 ilBindImage(image);
|
|
|
103
|
|
|
104 try
|
|
|
105 {
|
|
|
106 bool success = IL_TRUE == ilLoadL(IL_TYPE_UNKNOWN, (void *)data->getData(), data->getSize());
|
|
|
107
|
|
|
108 if (!success)
|
|
|
109 throw love::Exception("Could not decode image!");
|
|
|
110
|
|
|
111 width = ilGetInteger(IL_IMAGE_WIDTH);
|
|
|
112 height = ilGetInteger(IL_IMAGE_HEIGHT);
|
|
|
113
|
|
|
114 // Make sure the image is in RGBA format.
|
|
|
115 ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
|
|
|
116
|
|
|
117 // This should always be four.
|
|
|
118 int bpp = ilGetInteger(IL_IMAGE_BPP);
|
|
|
119 if (bpp != sizeof(pixel))
|
|
|
120 throw love::Exception("Could not convert image!");
|
|
|
121
|
|
|
122 create(width, height, ilGetData());
|
|
|
123 }
|
|
|
124 catch(std::exception &)
|
|
|
125 {
|
|
|
126 ilDeleteImages(1, &image);
|
|
|
127 throw;
|
|
|
128 }
|
|
|
129
|
|
|
130 ilDeleteImages(1, &image);
|
|
|
131 }
|
|
|
132
|
|
|
133 void ImageData::encode(love::filesystem::File *f, ImageData::Format format)
|
|
|
134 {
|
|
|
135 Lock lock1(devilMutex);
|
|
|
136 Lock lock2(mutex);
|
|
|
137
|
|
|
138 ILuint tempimage;
|
|
|
139 ilGenImages(1, &tempimage);
|
|
|
140 ilBindImage(tempimage);
|
|
|
141 ilxClearErrors();
|
|
|
142
|
|
|
143 ILubyte *encoded_data = NULL;
|
|
|
144
|
|
|
145 try
|
|
|
146 {
|
|
|
147 bool success = IL_TRUE == ilTexImage(width, height, 1, sizeof(pixel), IL_RGBA, IL_UNSIGNED_BYTE, this->data);
|
|
|
148
|
|
|
149 ILenum err = ilGetError();
|
|
|
150 ilxClearErrors();
|
|
|
151
|
|
|
152 if (!success)
|
|
|
153 {
|
|
|
154 if (err != IL_NO_ERROR)
|
|
|
155 {
|
|
|
156 switch (err)
|
|
|
157 {
|
|
|
158 case IL_ILLEGAL_OPERATION:
|
|
|
159 throw love::Exception("Illegal operation");
|
|
|
160 case IL_INVALID_PARAM:
|
|
|
161 throw love::Exception("Invalid parameters");
|
|
|
162 case IL_OUT_OF_MEMORY:
|
|
|
163 throw love::Exception("Out of memory");
|
|
|
164 default:
|
|
|
165 throw love::Exception("Unknown error (%d)", (int) err);
|
|
|
166 }
|
|
|
167 }
|
|
|
168
|
|
|
169 throw love::Exception("Could not create image for the encoding!");
|
|
|
170 }
|
|
|
171
|
|
|
172 ilRegisterOrigin(IL_ORIGIN_UPPER_LEFT);
|
|
|
173
|
|
|
174 ILuint ilFormat;
|
|
|
175 switch (format)
|
|
|
176 {
|
|
|
177 case ImageData::FORMAT_BMP:
|
|
|
178 ilFormat = IL_BMP;
|
|
|
179 break;
|
|
|
180 case ImageData::FORMAT_TGA:
|
|
|
181 ilFormat = IL_TGA;
|
|
|
182 break;
|
|
|
183 case ImageData::FORMAT_GIF:
|
|
|
184 ilFormat = IL_GIF;
|
|
|
185 break;
|
|
|
186 case ImageData::FORMAT_JPG:
|
|
|
187 ilFormat = IL_JPG;
|
|
|
188 break;
|
|
|
189 case ImageData::FORMAT_PNG:
|
|
|
190 default: // PNG is the default format
|
|
|
191 ilFormat = IL_PNG;
|
|
|
192 break;
|
|
|
193 }
|
|
|
194
|
|
|
195 ILuint size = ilSaveL(ilFormat, NULL, 0);
|
|
|
196 if (!size)
|
|
|
197 throw love::Exception("Could not encode image!");
|
|
|
198
|
|
|
199 try
|
|
|
200 {
|
|
|
201 encoded_data = new ILubyte[size];
|
|
|
202 }
|
|
|
203 catch(std::bad_alloc &)
|
|
|
204 {
|
|
|
205 throw love::Exception("Out of memory");
|
|
|
206 }
|
|
|
207
|
|
|
208 ilSaveL(ilFormat, encoded_data, size);
|
|
|
209
|
|
|
210 f->open(love::filesystem::File::WRITE);
|
|
|
211 f->write(encoded_data, size);
|
|
|
212 f->close();
|
|
|
213 }
|
|
|
214 catch(std::exception &)
|
|
|
215 {
|
|
|
216 ilDeleteImages(1, &tempimage);
|
|
|
217 delete[] encoded_data;
|
|
|
218 throw;
|
|
|
219 }
|
|
|
220
|
|
|
221 ilDeleteImages(1, &tempimage);
|
|
|
222 delete[] encoded_data;
|
|
|
223 }
|
|
|
224
|
|
|
225 } // devil
|
|
|
226 } // image
|
|
|
227 } // love
|