goat3dgfx

view src/image.cc @ 20:d9c8cd19c606

fixed the face index loading bug
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 08 Dec 2013 03:00:49 +0200
parents 3d96734fd477
children
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"
13 using namespace goatgfx;
15 static int pixel_elements(Image::Format fmt);
16 static int elem_size(Image::Format fmt);
17 static int pixel_size(Image::Format fmt);
19 Image::Image()
20 {
21 fmt = FMT_RGBA;
22 width = height = 0;
23 pixels = 0;
24 }
26 Image::~Image()
27 {
28 delete [] (char*)pixels;
29 }
31 int Image::get_width() const
32 {
33 return width;
34 }
36 int Image::get_height() const
37 {
38 return height;
39 }
41 Image::Format Image::get_format() const
42 {
43 return fmt;
44 }
46 bool Image::create(int x, int y, Format fmt)
47 {
48 width = x;
49 height = y;
50 this->fmt = fmt;
52 try {
53 pixels = new char[x * y * pixel_size(fmt)];
54 }
55 catch(...) {
56 return false;
57 }
58 return true;
59 }
61 bool Image::set_pixels(int xsz, int ysz, void *pixels, Format fmt)
62 {
63 if(!create(xsz, ysz, fmt)) {
64 return false;
65 }
66 memcpy(this->pixels, pixels, xsz * ysz * pixel_size(fmt));
67 return true;
68 }
70 bool Image::set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt)
71 {
72 return set_pixels(xsz, ysz, pixels, 0, 0, scan_width, fmt);
73 }
75 bool Image::set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width, Format fmt)
76 {
77 if(scan_width <= 0) {
78 scan_width = xsz;
79 }
81 if(!create(xsz, ysz, fmt)) {
82 return false;
83 }
85 int pixsz = pixel_size(fmt);
87 unsigned char *dest = (unsigned char*)this->pixels;
88 unsigned char *src = (unsigned char*)pixels + (y * scan_width + x) * pixsz;
89 for(int i=0; i<ysz; i++) {
90 memcpy(dest, src, xsz * pixsz);
91 dest += xsz * pixsz;
92 src += scan_width * pixsz;
93 }
94 return true;
95 }
97 void *Image::get_pixels() const
98 {
99 return pixels;
100 }
102 void Image::flip_horizontal()
103 {
104 int pixsz = pixel_size(fmt);
106 unsigned char *tmppix = (unsigned char*)alloca(pixsz);
108 unsigned char *scan = (unsigned char*)pixels;
109 for(int i=0; i<height; i++) {
110 unsigned char *dest = scan;
111 unsigned char *src = scan + (width - 1) * pixsz;
113 while(src > dest) {
114 memcpy(tmppix, src, pixsz);
115 memcpy(src, dest, pixsz);
116 memcpy(dest, tmppix, pixsz);
117 dest += pixsz;
118 src -= pixsz;
119 }
121 scan += width * pixsz;
122 }
123 }
125 void Image::flip_vertical()
126 {
127 int pixsz = pixel_size(fmt);
129 unsigned char *tmpscan = (unsigned char*)alloca(width * pixsz);
131 unsigned char *dest = (unsigned char*)pixels;
132 unsigned char *src = (unsigned char*)pixels + (height - 1) * width * pixsz;
134 while(src > dest) {
135 memcpy(tmpscan, src, width * pixsz);
136 memcpy(src, dest, width * pixsz);
137 memcpy(dest, tmpscan, width * pixsz);
138 dest += width * pixsz;
139 src -= width * pixsz;
140 }
141 }
143 void Image::rotate_180()
144 {
145 flip_vertical();
146 flip_horizontal();
147 }
149 bool Image::load(const char *fname)
150 {
151 struct img_pixmap pixmap;
153 img_init(&pixmap);
154 if(img_load(&pixmap, fname) == -1) {
155 return false;
156 }
158 Format fmt;
159 switch(pixmap.fmt) {
160 case IMG_FMT_GREY8:
161 fmt = FMT_GREY;
162 break;
163 case IMG_FMT_RGB24:
164 fmt = FMT_RGB;
165 break;
166 case IMG_FMT_RGBA32:
167 fmt = FMT_RGBA;
168 break;
169 case IMG_FMT_GREYF:
170 fmt = FMT_GREY_FLOAT;
171 break;
172 case IMG_FMT_RGBF:
173 fmt = FMT_RGB_FLOAT;
174 break;
175 case IMG_FMT_RGBAF:
176 fmt = FMT_RGBA_FLOAT;
177 break;
178 default:
179 img_destroy(&pixmap);
180 return false;
181 }
183 if(!set_pixels(pixmap.width, pixmap.height, pixmap.pixels, fmt)) {
184 img_destroy(&pixmap);
185 return false;
186 }
187 img_destroy(&pixmap);
188 return true;
189 }
191 bool Image::save(const char *fname) const
192 {
193 struct img_pixmap pixmap;
195 img_init(&pixmap);
197 switch(fmt) {
198 case FMT_GREY:
199 pixmap.fmt = IMG_FMT_GREY8;
200 break;
201 case FMT_GREY_FLOAT:
202 pixmap.fmt = IMG_FMT_GREYF;
203 break;
204 case FMT_RGB:
205 pixmap.fmt = IMG_FMT_RGB24;
206 break;
207 case FMT_RGB_FLOAT:
208 pixmap.fmt = IMG_FMT_RGBF;
209 break;
210 case FMT_RGBA:
211 pixmap.fmt = IMG_FMT_RGBA32;
212 break;
213 case FMT_RGBA_FLOAT:
214 pixmap.fmt = IMG_FMT_RGBAF;
215 break;
216 default:
217 return false;
218 }
220 pixmap.width = width;
221 pixmap.height = height;
222 pixmap.pixels = pixels;
223 pixmap.pixelsz = pixel_size(fmt);
225 if(img_save(&pixmap, fname) == -1) {
226 return false;
227 }
228 return true;
229 }
231 static int pixel_elements(Image::Format fmt)
232 {
233 switch(fmt) {
234 case Image::FMT_GREY:
235 case Image::FMT_GREY_FLOAT:
236 return 1;
238 case Image::FMT_RGB:
239 case Image::FMT_RGB_FLOAT:
240 return 3;
242 case Image::FMT_RGBA:
243 case Image::FMT_RGBA_FLOAT:
244 return 4;
246 default:
247 break;
248 }
249 return 0;
250 }
252 static int elem_size(Image::Format fmt)
253 {
254 switch(fmt) {
255 case Image::FMT_GREY:
256 case Image::FMT_RGB:
257 case Image::FMT_RGBA:
258 return 1;
260 case Image::FMT_GREY_FLOAT:
261 case Image::FMT_RGB_FLOAT:
262 case Image::FMT_RGBA_FLOAT:
263 return sizeof(float);
265 default:
266 break;
267 }
268 return 0;
269 }
271 static int pixel_size(Image::Format fmt)
272 {
273 return elem_size(fmt) * pixel_elements(fmt);
274 }