hacked image loading to use assman
[laserbrain_demo] / src / image.cc
1 #include <string.h>
2
3 #if defined(WIN32) || defined(__WIN32__)
4 #include <malloc.h>
5 #else
6 #include <alloca.h>
7 #endif
8
9 #include "imago2.h"
10 #include "assman.h"
11 #include "image.h"
12
13 static int pixel_elements(Image::Format fmt);
14 static int elem_size(Image::Format fmt);
15 static int pixel_size(Image::Format fmt);
16
17 Image::Image()
18 {
19         fmt = FMT_RGBA;
20         width = height = 0;
21         pixels = 0;
22 }
23
24 Image::~Image()
25 {
26         delete [] (char*)pixels;
27 }
28
29 int Image::get_width() const
30 {
31         return width;
32 }
33
34 int Image::get_height() const
35 {
36         return height;
37 }
38
39 Image::Format Image::get_format() const
40 {
41         return fmt;
42 }
43
44 bool Image::create(int x, int y, Format fmt)
45 {
46         width = x;
47         height = y;
48         this->fmt = fmt;
49
50         try {
51                 pixels = new char[x * y * pixel_size(fmt)];
52         }
53         catch(...) {
54                 return false;
55         }
56         return true;
57 }
58
59 bool Image::set_pixels(int xsz, int ysz, void *pixels, Format fmt)
60 {
61         if(!create(xsz, ysz, fmt)) {
62                 return false;
63         }
64         memcpy(this->pixels, pixels, xsz * ysz * pixel_size(fmt));
65         return true;
66 }
67
68 bool Image::set_pixels(int xsz, int ysz, void *pixels, int scan_width, Format fmt)
69 {
70         return set_pixels(xsz, ysz, pixels, 0, 0, scan_width, fmt);
71 }
72
73 bool Image::set_pixels(int xsz, int ysz, void *pixels, int x, int y, int scan_width, Format fmt)
74 {
75         if(scan_width <= 0) {
76                 scan_width = xsz;
77         }
78
79         if(!create(xsz, ysz, fmt)) {
80                 return false;
81         }
82
83         int pixsz = pixel_size(fmt);
84
85         unsigned char *dest = (unsigned char*)this->pixels;
86         unsigned char *src = (unsigned char*)pixels + (y * scan_width + x) * pixsz;
87         for(int i=0; i<ysz; i++) {
88                 memcpy(dest, src, xsz * pixsz);
89                 dest += xsz * pixsz;
90                 src += scan_width * pixsz;
91         }
92         return true;
93 }
94
95 void *Image::get_pixels() const
96 {
97         return pixels;
98 }
99
100 void Image::flip_horizontal()
101 {
102         int pixsz = pixel_size(fmt);
103
104         unsigned char *tmppix = (unsigned char*)alloca(pixsz);
105
106         unsigned char *scan = (unsigned char*)pixels;
107         for(int i=0; i<height; i++) {
108                 unsigned char *dest = scan;
109                 unsigned char *src = scan + (width - 1) * pixsz;
110
111                 while(src > dest) {
112                         memcpy(tmppix, src, pixsz);
113                         memcpy(src, dest, pixsz);
114                         memcpy(dest, tmppix, pixsz);
115                         dest += pixsz;
116                         src -= pixsz;
117                 }
118
119                 scan += width * pixsz;
120         }
121 }
122
123 void Image::flip_vertical()
124 {
125         int pixsz = pixel_size(fmt);
126
127         unsigned char *tmpscan = (unsigned char*)alloca(width * pixsz);
128
129         unsigned char *dest = (unsigned char*)pixels;
130         unsigned char *src = (unsigned char*)pixels + (height - 1) * width * pixsz;
131
132         while(src > dest) {
133                 memcpy(tmpscan, src, width * pixsz);
134                 memcpy(src, dest, width * pixsz);
135                 memcpy(dest, tmpscan, width * pixsz);
136                 dest += width * pixsz;
137                 src -= width * pixsz;
138         }
139 }
140
141 void Image::rotate_180()
142 {
143         flip_vertical();
144         flip_horizontal();
145 }
146
147 void Image::resize_half()
148 {
149         int pixsz = pixel_size(fmt);
150         int newxsz = width / 2;
151         int newysz = height / 2;
152
153         if(!newxsz || !newysz) return;
154
155         unsigned char *newpix = new unsigned char[newxsz * newysz * pixsz];
156
157         unsigned char *sptr = (unsigned char*)pixels;
158         unsigned char *dptr = newpix;
159
160         for(int i=0; i<newysz; i++) {
161                 if(i & 1) sptr += width * pixsz;
162                 for(int j=0; j<newxsz; j++) {
163                         memcpy(dptr, sptr, pixsz);
164                         dptr += pixsz;
165                         sptr += pixsz * 2;
166                 }
167         }
168
169         delete [] (char*)pixels;
170         pixels = newpix;
171         width = newxsz;
172         height = newysz;
173 }
174
175 static size_t io_read(void *buf, size_t bytes, void *fp)
176 {
177         return ass_fread(buf, 1, bytes, fp);
178 }
179
180 static long io_seek(long offs, int whence, void *fp)
181 {
182         ass_fseek(fp, offs, whence);
183         return ass_ftell(fp);
184 }
185
186 bool Image::load(const char *fname)
187 {
188         struct img_pixmap pixmap;
189         struct img_io io = {0, io_read, 0, io_seek};
190         ass_file *fp;
191
192         if(!(fp = ass_fopen(fname, "rb"))) {
193                 return false;
194         }
195         io.uptr = fp;
196
197         img_init(&pixmap);
198         if(img_read(&pixmap, &io) == -1) {
199                 return false;
200         }
201
202         Format fmt;
203         switch(pixmap.fmt) {
204         case IMG_FMT_GREY8:
205                 fmt = FMT_GREY;
206                 break;
207         case IMG_FMT_RGB24:
208                 fmt = FMT_RGB;
209                 break;
210         case IMG_FMT_RGBA32:
211                 fmt = FMT_RGBA;
212                 break;
213         case IMG_FMT_GREYF:
214                 fmt = FMT_GREY_FLOAT;
215                 break;
216         case IMG_FMT_RGBF:
217                 fmt = FMT_RGB_FLOAT;
218                 break;
219         case IMG_FMT_RGBAF:
220                 fmt = FMT_RGBA_FLOAT;
221                 break;
222         default:
223                 img_destroy(&pixmap);
224                 return false;
225         }
226
227         if(!set_pixels(pixmap.width, pixmap.height, pixmap.pixels, fmt)) {
228                 img_destroy(&pixmap);
229                 return false;
230         }
231         img_destroy(&pixmap);
232         return true;
233 }
234
235 bool Image::save(const char *fname) const
236 {
237         struct img_pixmap pixmap;
238
239         img_init(&pixmap);
240
241         switch(fmt) {
242         case FMT_GREY:
243                 pixmap.fmt = IMG_FMT_GREY8;
244                 break;
245         case FMT_GREY_FLOAT:
246                 pixmap.fmt = IMG_FMT_GREYF;
247                 break;
248         case FMT_RGB:
249                 pixmap.fmt = IMG_FMT_RGB24;
250                 break;
251         case FMT_RGB_FLOAT:
252                 pixmap.fmt = IMG_FMT_RGBF;
253                 break;
254         case FMT_RGBA:
255                 pixmap.fmt = IMG_FMT_RGBA32;
256                 break;
257         case FMT_RGBA_FLOAT:
258                 pixmap.fmt = IMG_FMT_RGBAF;
259                 break;
260         default:
261                 return false;
262         }
263
264         pixmap.width = width;
265         pixmap.height = height;
266         pixmap.pixels = pixels;
267         pixmap.pixelsz = pixel_size(fmt);
268
269         if(img_save(&pixmap, fname) == -1) {
270                 return false;
271         }
272         return true;
273 }
274
275 static int pixel_elements(Image::Format fmt)
276 {
277         switch(fmt) {
278         case Image::FMT_GREY:
279         case Image::FMT_GREY_FLOAT:
280                 return 1;
281
282         case Image::FMT_RGB:
283         case Image::FMT_RGB_FLOAT:
284                 return 3;
285
286         case Image::FMT_RGBA:
287         case Image::FMT_RGBA_FLOAT:
288                 return 4;
289
290         default:
291                 break;
292         }
293         return 0;
294 }
295
296 static int elem_size(Image::Format fmt)
297 {
298         switch(fmt) {
299         case Image::FMT_GREY:
300         case Image::FMT_RGB:
301         case Image::FMT_RGBA:
302                 return 1;
303
304         case Image::FMT_GREY_FLOAT:
305         case Image::FMT_RGB_FLOAT:
306         case Image::FMT_RGBA_FLOAT:
307                 return sizeof(float);
308
309         default:
310                 break;
311         }
312         return 0;
313 }
314
315 static int pixel_size(Image::Format fmt)
316 {
317         return elem_size(fmt) * pixel_elements(fmt);
318 }