using a texture for the grid is better
[vrfileman] / src / image.cc
1 #include <string.h>
2 #include "assman.h"
3 #include "imago2.h"
4 #include "image.h"
5
6
7 static int pixel_elements(Image::Format fmt);
8 static int elem_size(Image::Format fmt);
9 static int pixel_size(Image::Format fmt);
10
11 Image::Image()
12 {
13         fmt = FMT_RGBA;
14         width = height = 0;
15         pixels = 0;
16 }
17
18 Image::~Image()
19 {
20         delete [] (char*)pixels;
21 }
22
23 Image::Image(const Image &img)
24 {
25         pixels = 0;
26         set_pixels(img.width, img.height, img.pixels, img.fmt);
27 }
28
29 Image &Image::operator =(const Image &img)
30 {
31         if(&img != this) {
32                 delete [] (char*)pixels;
33                 pixels = 0;
34                 set_pixels(img.width, img.height, img.pixels, img.fmt);
35         }
36         return *this;
37 }
38
39 Image::Image(Image &&img)
40 {
41         width = img.width;
42         height = img.height;
43         pixels = img.pixels;
44         fmt = img.fmt;
45
46         img.pixels = 0;
47 }
48
49 Image &Image::operator =(Image &&img)
50 {
51         if(&img != this) {
52                 width = img.width;
53                 height = img.height;
54                 pixels = img.pixels;
55                 fmt = img.fmt;
56
57                 img.pixels = 0;
58         }
59         return *this;
60 }
61
62 int Image::get_width() const
63 {
64         return width;
65 }
66
67 int Image::get_height() const
68 {
69         return height;
70 }
71
72 Image::Format Image::get_format() const
73 {
74         return fmt;
75 }
76
77 bool Image::create(int x, int y, Format fmt)
78 {
79         width = x;
80         height = y;
81         this->fmt = fmt;
82
83         try {
84                 pixels = new char[x * y * pixel_size(fmt)];
85         }
86         catch(...) {
87                 return false;
88         }
89         return true;
90 }
91
92 bool Image::set_pixels(int x, int y, void *pixels, Format fmt)
93 {
94         if(!create(x, y, fmt)) {
95                 return false;
96         }
97         memcpy(this->pixels, pixels, x * y * pixel_size(fmt));
98         return true;
99 }
100
101 void *Image::get_pixels() const
102 {
103         return pixels;
104 }
105
106 static size_t io_read(void *buf, size_t bytes, void *uptr)
107 {
108         return ass_fread(buf, 1, bytes, uptr);
109 }
110
111 static long io_seek(long offs, int whence, void *uptr)
112 {
113         return ass_fseek(uptr, offs, whence);
114 }
115
116 bool Image::load(const char *fname)
117 {
118         struct img_pixmap pixmap;
119         struct img_io io;
120
121         if(!(io.uptr = ass_fopen(fname, "rb"))) {
122                 fprintf(stderr, "failed to open image: %s\n", fname);
123                 return false;
124         }
125         io.read = io_read;
126         io.write = 0;
127         io.seek = io_seek;
128
129         img_init(&pixmap);
130         if(img_read(&pixmap, &io) == -1) {
131                 return false;
132         }
133         ass_fclose(io.uptr);
134
135         Format fmt;
136         switch(pixmap.fmt) {
137         case IMG_FMT_GREY8:
138                 fmt = FMT_GREY;
139                 break;
140         case IMG_FMT_RGB24:
141                 fmt = FMT_RGB;
142                 break;
143         case IMG_FMT_RGBA32:
144                 fmt = FMT_RGBA;
145                 break;
146         case IMG_FMT_GREYF:
147                 fmt = FMT_GREY_FLOAT;
148                 break;
149         case IMG_FMT_RGBF:
150                 fmt = FMT_RGB_FLOAT;
151                 break;
152         case IMG_FMT_RGBAF:
153                 fmt = FMT_RGBA_FLOAT;
154                 break;
155         default:
156                 img_destroy(&pixmap);
157                 return false;
158         }
159
160         if(!set_pixels(pixmap.width, pixmap.height, pixmap.pixels, fmt)) {
161                 img_destroy(&pixmap);
162                 return false;
163         }
164         img_destroy(&pixmap);
165         return true;
166 }
167
168 bool Image::save(const char *fname) const
169 {
170         struct img_pixmap pixmap;
171
172         img_init(&pixmap);
173
174         switch(fmt) {
175         case FMT_GREY:
176                 pixmap.fmt = IMG_FMT_GREY8;
177                 break;
178         case FMT_GREY_FLOAT:
179                 pixmap.fmt = IMG_FMT_GREYF;
180                 break;
181         case FMT_RGB:
182                 pixmap.fmt = IMG_FMT_RGB24;
183                 break;
184         case FMT_RGB_FLOAT:
185                 pixmap.fmt = IMG_FMT_RGBF;
186                 break;
187         case FMT_RGBA:
188                 pixmap.fmt = IMG_FMT_RGBA32;
189                 break;
190         case FMT_RGBA_FLOAT:
191                 pixmap.fmt = IMG_FMT_RGBAF;
192                 break;
193         default:
194                 return false;
195         }
196
197         pixmap.width = width;
198         pixmap.height = height;
199         pixmap.pixels = pixels;
200         pixmap.pixelsz = pixel_size(fmt);
201
202         if(img_save(&pixmap, fname) == -1) {
203                 return false;
204         }
205         return true;
206 }
207
208 static int pixel_elements(Image::Format fmt)
209 {
210         switch(fmt) {
211         case Image::FMT_GREY:
212         case Image::FMT_GREY_FLOAT:
213                 return 1;
214
215         case Image::FMT_RGB:
216         case Image::FMT_RGB_FLOAT:
217                 return 3;
218
219         case Image::FMT_RGBA:
220         case Image::FMT_RGBA_FLOAT:
221                 return 4;
222
223         default:
224                 break;
225         }
226         return 0;
227 }
228
229 static int elem_size(Image::Format fmt)
230 {
231         switch(fmt) {
232         case Image::FMT_GREY:
233         case Image::FMT_RGB:
234         case Image::FMT_RGBA:
235                 return 1;
236
237         case Image::FMT_GREY_FLOAT:
238         case Image::FMT_RGB_FLOAT:
239         case Image::FMT_RGBA_FLOAT:
240                 return sizeof(float);
241
242         default:
243                 break;
244         }
245         return 0;
246 }
247
248 static int pixel_size(Image::Format fmt)
249 {
250         return elem_size(fmt) * pixel_elements(fmt);
251 }