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