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