sgltk 0.6
Simple OpenGL Tool Kit
Loading...
Searching...
No Matches
image.cpp
1#include "image.h"
2
3using namespace sgltk;
4
5std::vector<std::string> Image::paths = {"./"};
6
7Image::Image() {
8 free_data = false;
9 image = nullptr;
10 width = 0;
11 height = 0;
13 data = nullptr;
14}
15
16Image::Image(std::string filename) {
17 free_data = false;
18 image = nullptr;
19 width = 0;
20 height = 0;
22 data = nullptr;
23 if(!load(filename)) {
24 std::string error = std::string("Error loading image: ") +
25 SDL_GetError();
26 App::error_string.push_back(error);
27 throw std::runtime_error(error);
28 }
29}
30
31Image::Image(unsigned int width,
32 unsigned int height,
33 unsigned int bytes_per_pixel,
34 void *data) {
35
36 free_data = false;
37 image = nullptr;
38 width = 0;
39 height = 0;
41 data = nullptr;
43 std::string error = std::string("Error loading image: ") +
44 SDL_GetError();
45 App::error_string.push_back(error);
46 throw std::runtime_error(error);
47 }
48}
49
50Image::~Image() {
51 SDL_FreeSurface(image);
52 if(free_data)
53 free(data);
54}
55
56bool Image::create_empty(unsigned int width, unsigned int height) {
57 if(image) {
58 SDL_FreeSurface(image);
59 if(free_data)
60 free(data);
61 image = nullptr;
62 }
63 free_data = false;
64
65 this->width = width;
66 this->height = height;
68
69 Uint32 rmask, gmask, bmask, amask;
70#if SDL_BYTEORDER == SDL_BIG_ENDIAN
71 rmask = 0xff000000;
72 gmask = 0x00ff0000;
73 bmask = 0x0000ff00;
74 amask = 0x000000ff;
75#else
76 rmask = 0x000000ff;
77 gmask = 0x0000ff00;
78 bmask = 0x00ff0000;
79 amask = 0xff000000;
80#endif
81
82 image = SDL_CreateRGBSurface(0, width, height, 32,
83 rmask, gmask, bmask, amask);
84 if(!image) {
85 App::error_string.push_back(std::string("Unable to create an"
86 "empty image: ") + SDL_GetError());
87 this->width = 0;
88 this->height = 0;
90 data = nullptr;
91 return false;
92 }
93 data = image->pixels;
94 return true;
95}
96
97bool Image::load(const std::string& filename) {
98 if(image) {
99 SDL_FreeSurface(image);
100 if(free_data)
101 free(data);
102 }
103 free_data = false;
104
105 if((filename.length() > 1 && filename[0] == '/') ||
106 (filename.length() > 2 && filename[1] == ':')) {
107 //absolute path
108 image = IMG_Load(filename.c_str());
109 } else {
110 //relative path
111 for(unsigned int i = 0; i < paths.size(); i++) {
112 image = IMG_Load((paths[i] + filename).c_str());
113 if(image)
114 break;
115 }
116 }
117 if(!image) {
118 App::error_string.push_back(std::string("Unable to load image: ")
119 + filename + std::string(" - ") + IMG_GetError());
120 width = 0;
121 height = 0;
122 bytes_per_pixel = 0;
123 data = nullptr;
124 return false;
125 }
126
127 width = image->w;
128 height = image->h;
129 bytes_per_pixel = image->format->BytesPerPixel;
130 data = image->pixels;
131
132 return true;
133}
134
135bool Image::load(unsigned int width,
136 unsigned int height,
137 unsigned int bytes_per_pixel,
138 void *data) {
139
140 if(image) {
141 SDL_FreeSurface(image);
142 if(free_data)
143 free(this->data);
144 image = nullptr;
145 }
146
147 Uint32 rmask, gmask, bmask, amask;
148#if SDL_BYTEORDER == SDL_BIG_ENDIAN
149 rmask = 0xff000000;
150 gmask = 0x00ff0000;
151 bmask = 0x0000ff00;
152 amask = 0x000000ff;
153#else
154 rmask = 0x000000ff;
155 gmask = 0x0000ff00;
156 bmask = 0x00ff0000;
157 amask = 0xff000000;
158#endif
159
160 if(!data) {
161 App::error_string.push_back(std::string("Image - load: "
162 "data is null"));
163 this->width = 0;
164 this->height = 0;
165 this->bytes_per_pixel = 0;
166 this->data = nullptr;
167 free_data = false;
168 return false;
169 }
170
171 this->width = width;
172 this->height = height;
173 this->bytes_per_pixel = bytes_per_pixel;
174 this->data = malloc(width * height * bytes_per_pixel);
175 if(!this->data) {
176 App::error_string.push_back(std::string("Image - load: "
177 "Unable to allocate memory"));
178 this->width = 0;
179 this->height = 0;
180 this->bytes_per_pixel = 0;
181 free_data = false;
182 return false;
183 }
184 memcpy(this->data, data, width * height * bytes_per_pixel);
185 free_data = true;
186
187 image = SDL_CreateRGBSurfaceFrom(this->data, width, height,
189 rmask, gmask, bmask, amask);
190
191 if(!image) {
192 App::error_string.push_back(std::string("Unable to load the"
193 "image from buffer: ") + SDL_GetError());
194 free(this->data);
195 this->data = nullptr;
196 this->width = 0;
197 this->height = 0;
198 this->bytes_per_pixel = 0;
199 free_data = false;
200 return false;
201 }
202 return true;
203}
204
205bool Image::save(const std::string& filename) {
206 int ret = SDL_SaveBMP(image, filename.c_str());
207 if(ret < 0) {
208 App::error_string.push_back(std::string("Unable to save the"
209 "image to ") + filename + std::string(": ") + SDL_GetError());
210 return false;
211 }
212 return true;
213}
214
215#ifdef HAVE_SDL_TTF_H
216TTF_Font *Image::open_font_file(const std::string& font_file, unsigned int size) {
217 TTF_Font *font;
218 if((font_file.length() > 1 && font_file[0] == '/') ||
219 (font_file.length() > 2 && font_file[1] == ':')) {
220 //absolute path
221 font = TTF_OpenFont(font_file.c_str(), size);
222 } else {
223 //relative path
224 for(unsigned int i = 0; i < paths.size(); i++) {
225 font = TTF_OpenFont((paths[i] + font_file).c_str(), size);
226 if(font)
227 break;
228 }
229 }
230 return font;
231}
232
233void Image::close_font_file(TTF_Font *font_file) {
234 TTF_CloseFont(font_file);
235}
236
237bool Image::create_text(const std::string& text,
238 TTF_Font *font, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
239 if (!font)
240 return false;
241 if(image) {
242 SDL_FreeSurface(image);
243 if(free_data)
244 free(data);
245 image = nullptr;
246 }
247 SDL_Color color = {r, g, b, a};
248 image = TTF_RenderUTF8_Blended(font, text.c_str(), color);
249 if(!image) {
250 App::error_string.push_back(
251 std::string("TTF_RenderUTF8_Blended failed: ") +
252 TTF_GetError());
253 return false;
254 }
255 width = image->w;
256 height = image->h;
257 bytes_per_pixel = 4;
258 data = image->pixels;
259 free_data = false;
260 return true;
261}
262
263bool Image::create_text(const std::string& text, const std::string& font_file,
264 unsigned int size, Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
265 TTF_Font *font = open_font_file(font_file, size);
266 if(!font) {
267 App::error_string.push_back(std::string("TTF_OpenFont for ")
268 + font_file + std::string(" failed."));
269 return false;
270 }
271
272 bool ret = create_text(text, font, r, g, b, a);
273 if(ret) {
274 data = image->pixels;
275 free_data = false;
276 }
277 close_font_file(font);
278 return ret;
279}
280#endif //HAVE_SDL_TTF_H
281
282bool Image::copy_from(const Image& src, int x, int y) {
283 SDL_Rect rect;
284 rect.x = x;
285 rect.y = y;
286 return copy_from(src, rect);
287}
288
289bool Image::copy_from(const Image& src, SDL_Rect& dst_rect) {
290 if(!image) {
291 image = SDL_ConvertSurface(src.image, src.image->format,
292 src.image->flags);
293 if(!image) {
294 App::error_string.push_back(std::string("SDL_ConvertSurface"
295 " failed: ") + SDL_GetError());
296 return false;
297 }
298 }
299 if(SDL_BlitSurface(src.image, nullptr, image, &dst_rect) < 0) {
300 App::error_string.push_back(std::string("SDL_BlitSurface"
301 " failed: ") + SDL_GetError());
302 return false;
303 }
304 return true;
305}
306
307bool Image::copy_from(const Image& src, SDL_Rect& dst_rect,
308 const SDL_Rect& src_rect) {
309 if(!image) {
310 image = SDL_ConvertSurface(src.image, src.image->format,
311 src.image->flags);
312 if(!image) {
313 App::error_string.push_back(std::string("SDL_ConvertSurface"
314 " failed: ") + SDL_GetError());
315 return false;
316 }
317 }
318 if(SDL_BlitSurface(src.image, &src_rect, image, &dst_rect) < 0) {
319 App::error_string.push_back(std::string("SDL_BlitSurface"
320 " failed: ") + SDL_GetError());
321 return false;
322 }
323 return true;
324}
325
326/*bool Image::copy_scaled() {
327 SDL_BlitScaled(src,srcrect, dst, dstrect);
328}*/
329
331 if(!image)
332 return;
333
334 unsigned int bpp = image->format->BytesPerPixel;
335
336 std::unique_ptr<unsigned char[]> buf = std::make_unique<unsigned char[]>(width * height * bpp);
337
338 for(unsigned int y = 0; y < height; y++) {
339 for(unsigned int x = 0; x < width; x++) {
340 for(unsigned int c = 0; c < bpp; c++) {
341 buf[(y * width + x) * bpp + c] =
342 ((unsigned char *)image->pixels)[((height - y - 1) * width + x) * bpp + c];
343 }
344 }
345 }
346
347 memcpy(image->pixels, buf.get(), width * height * bpp);
348}
349
351 if(!image)
352 return;
353
354 unsigned int bpp = image->format->BytesPerPixel;
355
356 std::unique_ptr<unsigned char[]> buf = std::make_unique<unsigned char[]>(width * height * bpp);
357
358 for(unsigned int y = 0; y < height; y++) {
359 for(unsigned int x = 0; x < width; x++) {
360 for(unsigned int c = 0; c < bpp; c++) {
361 buf[(y * width + x) * bpp + c] =
362 ((unsigned char *)image->pixels)[(y * width + (width - x - 1)) * bpp + c];
363 }
364 }
365 }
366
367 memcpy(image->pixels, buf.get(), width * height * bpp);
368}
369
370void Image::set_color_key(int r, int g, int b, bool enable) {
371 SDL_SetColorKey(image, enable, SDL_MapRGB(image->format, r, g, b));
372}
373
374void Image::add_path(std::string path) {
375 if(path[path.length() - 1] != '/')
376 path += '/';
377
378 if(std::find(paths.begin(), paths.end(), path) == paths.end())
379 paths.push_back(path);
380}
static std::vector< std::string > error_string
A list of all error strings.
Definition app.h:151
void * data
The pixel data.
Definition image.h:39
bool save(const std::string &filename)
Saves the image as a file.
Definition image.cpp:205
bool copy_from(const Image &src, int x, int y)
Copies an image into the current image.
Definition image.cpp:282
unsigned int height
The width of the image surface.
Definition image.h:31
bool create_empty(unsigned int width, unsigned int height)
Creates an empty image.
Definition image.cpp:56
SDL_Surface * image
The image surface.
Definition image.h:44
void set_color_key(int r, int g, int b, bool enable=true)
Sets a color to be transparent.
Definition image.cpp:370
static void add_path(std::string path)
Adds a path to the list of paths to be searched for image files.
Definition image.cpp:374
void vertical_flip()
Flips the image along its x-axis.
Definition image.cpp:330
bool load(const std::string &filename)
Loads a new image file.
Definition image.cpp:97
void horizontal_flip()
Flips the image along its y-axis.
Definition image.cpp:350
unsigned int bytes_per_pixel
The number of bytes that make up a single pixel.
Definition image.h:35
unsigned int width
The width of the image surface.
Definition image.h:27