goat3dgfx

view src/image.cc @ 6:3d96734fd477

cubemap loading and cubemap example program
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 17 Nov 2013 08:20:13 +0200
parents 1873dfd13f2d
children 7d6b667821cf
line source
1 #include <string.h>
3 #ifndef _MSC_VER
4 #include <alloca.h>
5 #else
6 #include <malloc.h>
7 #endif
9 #include "imago2.h"
10 #include "image.h"
11 #include "logger.h"
14 static int pixel_elements(Image::Format fmt);
15 static int elem_size(Image::Format fmt);
16 static int pixel_size(Image::Format fmt);
18 Image::Image()
19 {
20 fmt = FMT_RGBA;
21 width = height = 0;
22 pixels = 0;
23 }
25 Image::~Image()
26 {
27 delete [] (char*)pixels;
28 }
30 int Image::get_width() const
31 {
32 return width;
33 }
35 int Image::get_height() const
36 {
37 return height;
38 }
40 Image::Format Image::get_format() const
41 {
42 return fmt;
43 }
45 bool Image::create(int x, int y, Format fmt)
46 {
47 width = x;
48 height = y;
49 this->fmt = fmt;
51 try {
52 pixels = new char[x * y * pixel_size(fmt)];
53 }
54 catch(...) {
55 return false;
56 }
57 return true;
58 }
60 bool Image::set_pixels(int xsz, int ysz, void *pixels, Format fmt)
61 {
62 if(!create(xsz, ysz, fmt)) {
63 return false;
64 }
65 memcpy(this->pixels, pixels, xsz * ysz * pixel_size(fmt));
66 return true;
67 }
69 bool Image::set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt)
70 {
71 return set_pixels(xsz, ysz, pixels, 0, 0, scan_width, fmt);
72 }
74 bool Image::set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width, Format fmt)
75 {
76 if(scan_width <= 0) {
77 scan_width = xsz;
78 }
80 if(!create(xsz, ysz, fmt)) {
81 return false;
82 }
84 int pixsz = pixel_size(fmt);
86 unsigned char *dest = (unsigned char*)this->pixels;
87 unsigned char *src = (unsigned char*)pixels + (y * scan_width + x) * pixsz;
88 for(int i=0; i<ysz; i++) {
89 memcpy(dest, src, xsz * pixsz);
90 dest += xsz * pixsz;
91 src += scan_width * pixsz;
92 }
93 return true;
94 }
96 void *Image::get_pixels() const
97 {
98 return pixels;
99 }
101 void Image::flip_horizontal()
102 {
103 int pixsz = pixel_size(fmt);
105 unsigned char *tmppix = (unsigned char*)alloca(pixsz);
107 unsigned char *scan = (unsigned char*)pixels;
108 for(int i=0; i<height; i++) {
109 unsigned char *dest = scan;
110 unsigned char *src = scan + (width - 1) * pixsz;
112 while(src > dest) {
113 memcpy(tmppix, src, pixsz);
114 memcpy(src, dest, pixsz);
115 memcpy(dest, tmppix, pixsz);
116 dest += pixsz;
117 src -= pixsz;
118 }
120 scan += width * pixsz;
121 }
122 }
124 void Image::flip_vertical()
125 {
126 int pixsz = pixel_size(fmt);
128 unsigned char *tmpscan = (unsigned char*)alloca(width * pixsz);
130 unsigned char *dest = (unsigned char*)pixels;
131 unsigned char *src = (unsigned char*)pixels + (height - 1) * width * pixsz;
133 while(src > dest) {
134 memcpy(tmpscan, src, width * pixsz);
135 memcpy(src, dest, width * pixsz);
136 memcpy(dest, tmpscan, width * pixsz);
137 dest += width * pixsz;
138 src -= width * pixsz;
139 }
140 }
142 void Image::rotate_180()
143 {
144 flip_vertical();
145 flip_horizontal();
146 }
148 bool Image::load(const char *fname)
149 {
150 struct img_pixmap pixmap;
152 img_init(&pixmap);
153 if(img_load(&pixmap, fname) == -1) {
154 return false;
155 }
157 Format fmt;
158 switch(pixmap.fmt) {
159 case IMG_FMT_GREY8:
160 fmt = FMT_GREY;
161 break;
162 case IMG_FMT_RGB24:
163 fmt = FMT_RGB;
164 break;
165 case IMG_FMT_RGBA32:
166 fmt = FMT_RGBA;
167 break;
168 case IMG_FMT_GREYF:
169 fmt = FMT_GREY_FLOAT;
170 break;
171 case IMG_FMT_RGBF:
172 fmt = FMT_RGB_FLOAT;
173 break;
174 case IMG_FMT_RGBAF:
175 fmt = FMT_RGBA_FLOAT;
176 break;
177 default:
178 img_destroy(&pixmap);
179 return false;
180 }
182 if(!set_pixels(pixmap.width, pixmap.height, pixmap.pixels, fmt)) {
183 img_destroy(&pixmap);
184 return false;
185 }
186 img_destroy(&pixmap);
187 return true;
188 }
190 bool Image::save(const char *fname) const
191 {
192 struct img_pixmap pixmap;
194 img_init(&pixmap);
196 switch(fmt) {
197 case FMT_GREY:
198 pixmap.fmt = IMG_FMT_GREY8;
199 break;
200 case FMT_GREY_FLOAT:
201 pixmap.fmt = IMG_FMT_GREYF;
202 break;
203 case FMT_RGB:
204 pixmap.fmt = IMG_FMT_RGB24;
205 break;
206 case FMT_RGB_FLOAT:
207 pixmap.fmt = IMG_FMT_RGBF;
208 break;
209 case FMT_RGBA:
210 pixmap.fmt = IMG_FMT_RGBA32;
211 break;
212 case FMT_RGBA_FLOAT:
213 pixmap.fmt = IMG_FMT_RGBAF;
214 break;
215 default:
216 return false;
217 }
219 pixmap.width = width;
220 pixmap.height = height;
221 pixmap.pixels = pixels;
222 pixmap.pixelsz = pixel_size(fmt);
224 if(img_save(&pixmap, fname) == -1) {
225 return false;
226 }
227 return true;
228 }
230 static int pixel_elements(Image::Format fmt)
231 {
232 switch(fmt) {
233 case Image::FMT_GREY:
234 case Image::FMT_GREY_FLOAT:
235 return 1;
237 case Image::FMT_RGB:
238 case Image::FMT_RGB_FLOAT:
239 return 3;
241 case Image::FMT_RGBA:
242 case Image::FMT_RGBA_FLOAT:
243 return 4;
245 default:
246 break;
247 }
248 return 0;
249 }
251 static int elem_size(Image::Format fmt)
252 {
253 switch(fmt) {
254 case Image::FMT_GREY:
255 case Image::FMT_RGB:
256 case Image::FMT_RGBA:
257 return 1;
259 case Image::FMT_GREY_FLOAT:
260 case Image::FMT_RGB_FLOAT:
261 case Image::FMT_RGBA_FLOAT:
262 return sizeof(float);
264 default:
265 break;
266 }
267 return 0;
268 }
270 static int pixel_size(Image::Format fmt)
271 {
272 return elem_size(fmt) * pixel_elements(fmt);
273 }