1 #include "IosImgProcess.h"
2 #include <math.h>
3 #include <stdlib.h>
4
5
6 extern char *dataFolder;
7
8
9 /** Image loading... free... conversion */
10
11 bool fullscreen = true;
12 bool useGL = false;
13
14 IIM_Surface imgList[4096];
15 int imgListSize = 0;
16
IIM_Load_DisplayFormat(const char * fname)17 IIM_Surface * IIM_Load_DisplayFormat (const char *fname)
18 {
19 char path[1024];
20 SDL_Surface *tmpsurf, *retsurf;
21 sprintf(path, "%s/gfx/%s", dataFolder, fname);
22 tmpsurf = IMG_Load (path);
23 if (tmpsurf==0) {
24 fprintf(stderr,"Could not load %s\n", path);
25 exit(1);
26 }
27 retsurf = SDL_DisplayFormat (tmpsurf);
28 SDL_FreeSurface (tmpsurf);
29 return IIM_RegisterImg(retsurf, false);
30 }
31
IIM_Load_DisplayFormatAlpha(const char * fname)32 IIM_Surface * IIM_Load_DisplayFormatAlpha (const char *fname)
33 {
34 char path[1024];
35 SDL_Surface *tmpsurf, *retsurf;
36 sprintf(path, "%s/gfx/%s", dataFolder, fname);
37 tmpsurf = IMG_Load (path);
38 if (tmpsurf==0) {
39 fprintf(stderr,"Could not load %s\n", path);
40 exit(1);
41 }
42 retsurf = SDL_DisplayFormatAlpha (tmpsurf);
43 SDL_SetAlpha (retsurf, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE);
44 SDL_FreeSurface (tmpsurf);
45 return IIM_RegisterImg(retsurf, true);
46 }
47
IIM_Free(IIM_Surface * img)48 void IIM_Free(IIM_Surface *img)
49 {
50 for (int i=0; i<imgListSize; ++i)
51 {
52 if (&imgList[i] == img)
53 {
54 SDL_FreeSurface(imgList[i].surf);
55 imgList[i].surf = 0;
56 return;
57 }
58 }
59 }
60
IIM_RegisterImg(SDL_Surface * img,bool isAlpha)61 IIM_Surface * IIM_RegisterImg(SDL_Surface *img, bool isAlpha)
62 {
63 imgList[imgListSize].isAlpha = isAlpha;
64 imgList[imgListSize].surf = img;
65 imgList[imgListSize].w = img->w;
66 imgList[imgListSize].h = img->h;
67 return &(imgList[imgListSize++]);
68 }
69
IIM_ReConvertAll(void)70 void IIM_ReConvertAll(void)
71 {
72 for (int i=0; i<imgListSize; ++i)
73 {
74 if (imgList[i].surf)
75 {
76 if (imgList[i].isAlpha)
77 {
78 SDL_Surface *retsurf = SDL_DisplayFormat(imgList[i].surf);
79 SDL_SetAlpha (retsurf, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE);
80 SDL_FreeSurface(imgList[i].surf);
81 imgList[i].surf = retsurf;
82 }
83 else
84 {
85 SDL_Surface *retsurf = SDL_DisplayFormat(imgList[i].surf);
86 SDL_FreeSurface(imgList[i].surf);
87 imgList[i].surf = retsurf;
88 }
89 }
90 }
91 }
92
93 /** Image processing */
94
max3(int i1,int i2,int i3)95 static int max3(int i1, int i2, int i3)
96 {
97 if ((i1>=i2)&&(i1>=i3)) return i1;
98 if ((i2>=i3)&&(i2>=i1)) return i2;
99 return i3;
100 }
101
min3(int i1,int i2,int i3)102 static int min3(int i1, int i2, int i3)
103 {
104 if ((i1<=i2)&&(i1<=i3)) return i1;
105 if ((i2<=i3)&&(i2<=i1)) return i2;
106 return i3;
107 }
108
109 /* Extracting color components from a 32-bit color value
110 * pre: SDL_Locked(surface) */
iim_surface_get_rgba(SDL_Surface * surface,Uint32 x,Uint32 y)111 RGBA iim_surface_get_rgba(SDL_Surface *surface, Uint32 x, Uint32 y)
112 {
113 Uint32 temp, pixel;
114 RGBA result;
115 int index = x*surface->format->BytesPerPixel + y*surface->pitch;
116 SDL_PixelFormat *fmt = surface->format;
117 pixel=*(Uint32*)((char*)surface->pixels+index);
118
119 /* Get Red component */
120 temp=pixel&fmt->Rmask; /* Isolate red component */
121 temp=temp>>fmt->Rshift;/* Shift it down to 8-bit */
122 temp=temp<<fmt->Rloss; /* Expand to a full 8-bit number */
123 result.red=(Uint8)temp;
124
125 /* Get Green component */
126 temp=pixel&fmt->Gmask; /* Isolate green component */
127 temp=temp>>fmt->Gshift;/* Shift it down to 8-bit */
128 temp=temp<<fmt->Gloss; /* Expand to a full 8-bit number */
129 result.green=(Uint8)temp;
130
131 /* Get Blue component */
132 temp=pixel&fmt->Bmask; /* Isolate blue component */
133 temp=temp>>fmt->Bshift;/* Shift it down to 8-bit */
134 temp=temp<<fmt->Bloss; /* Expand to a full 8-bit number */
135 result.blue=(Uint8)temp;
136
137 /* Get Alpha component */
138 temp=pixel&fmt->Amask; /* Isolate alpha component */
139 temp=temp>>fmt->Ashift;/* Shift it down to 8-bit */
140 temp=temp<<fmt->Aloss; /* Expand to a full 8-bit number */
141 result.alpha=(Uint8)temp;
142
143 return result;
144 }
145
iim_rgba2gray(RGBA col)146 Uint8 iim_rgba2gray(RGBA col)
147 {
148 unsigned int level;
149 level = col.red;
150 level += col.green;
151 level += col.blue;
152 level /= 3; // Volontairement assombrie.
153 return level;
154 }
155
156 /* pre: SDL_Locked(surface) */
iim_surface_set_rgb(SDL_Surface * surface,Uint32 x,Uint32 y,RGBA c)157 void iim_surface_set_rgb(SDL_Surface *surface,
158 Uint32 x, Uint32 y, RGBA c)
159 {
160 Uint32 temp, pixel;
161 int index = x*surface->format->BytesPerPixel + y*surface->pitch;
162 SDL_PixelFormat *fmt = surface->format;
163 temp = ~(fmt->Rmask | fmt->Gmask | fmt->Bmask);
164
165 pixel = *(Uint32*)((char*)surface->pixels+index);
166 pixel &= temp;
167
168 /* Get Red component */
169 temp = c.red >> fmt->Rloss;
170 temp = temp << fmt->Rshift;
171 pixel |= temp;
172
173 /* Get Green component */
174 temp = c.green >> fmt->Gloss;
175 temp = temp << fmt->Gshift;
176 pixel |= temp;
177
178 /* Get Blue component */
179 temp = c.blue >> fmt->Bloss;
180 temp = temp << fmt->Bshift;
181 pixel |= temp;
182
183 *(Uint32*)((char*)surface->pixels+index) = pixel;
184 }
185
186 /* pre: SDL_Locked(surface) */
iim_surface_set_rgba(SDL_Surface * surface,Uint32 x,Uint32 y,RGBA c)187 void iim_surface_set_rgba(SDL_Surface *surface,
188 Uint32 x, Uint32 y, RGBA c)
189 {
190 Uint32 temp, pixel = 0;
191 int index = x*surface->format->BytesPerPixel + y*surface->pitch;
192 SDL_PixelFormat *fmt = surface->format;
193
194 /* Get Red component */
195 temp = c.red >> fmt->Rloss;
196 temp = temp << fmt->Rshift;
197 pixel |= temp;
198
199 /* Get Green component */
200 temp = c.green >> fmt->Gloss;
201 temp = temp << fmt->Gshift;
202 pixel |= temp;
203
204 /* Get Blue component */
205 temp = c.blue >> fmt->Bloss;
206 temp = temp << fmt->Bshift;
207 pixel |= temp;
208
209 /* Get Alpha component */
210 temp = c.alpha >> fmt->Aloss;
211 temp = temp << fmt->Ashift;
212 pixel |= temp;
213
214 *(Uint32*)((char*)surface->pixels+index) = pixel;
215 }
216
217 //-- RGB<->HSV conversion
218
219 //-- RGB, each 0 to 255
220 //-- H = 0.0 to 360.0 (corresponding to 0..360.0 degrees around hexcone)
221 //-- S = 0.0 (shade of gray) to 1.0 (pure color)
222 //-- V = 0.0 (black) to 1.0 (white)
223
224 //-- Based on C Code in "Computer Graphics -- Principles and Practice,"
225 //-- Foley et al, 1996, pp. 592,593.
iim_rgba2hsva(RGBA c)226 HSVA iim_rgba2hsva(RGBA c)
227 {
228 HSVA res;
229 float minVal = (float)min3(c.red, c.blue, c.green);
230 res.value = (float)max3(c.red, c.green, c.blue);
231 float delta = res.value - minVal;
232
233 // -- Calculate saturation: saturation is 0 if r, g and b are all 0
234 if (res.value == 0.0f)
235 res.saturation = 0.0f;
236 else
237 res.saturation = delta / res.value;
238
239 if (res.saturation == 0.0f)
240 res.hue = 0.0f; // Achromatic: When s = 0, h is undefined but who cares
241 else // Chromatic
242 if (res.value == c.red) // between yellow and magenta [degrees]
243 res.hue = 60.0f * (c.green - c.blue) / delta;
244 else if (res.value == c.green) // between cyan and yellow
245 res.hue = 120.0 + 60.0f * (c.blue - c.red) / delta;
246 else // between magenta and cyan
247 res.hue = 240.0f + 60.0f * (c.red - c.green) / delta;
248
249 if (res.hue < 0.0f) res.hue += 360.0f;
250 // return a list of values as an rgb object would not be sensible
251 res.value /= 255.0f;
252 res.alpha = c.alpha;
253 return res;
254 }
255
iim_hsva2rgba(HSVA c)256 RGBA iim_hsva2rgba(HSVA c)
257 {
258 float red=0.0f,green=0.0f,blue=0.0f,hueTemp=0.0f;
259 if (c.saturation == 0.0f) // color is on black-and-white center line
260 {
261 red = c.value; // achromatic: shades of gray
262 green = c.value; // supposedly invalid for h=0 but who cares
263 blue = c.value;
264 }
265 else { // chromatic color
266 if (c.hue == 360.0f) // 360 degrees same as 0 degrees
267 hueTemp=0.0f;
268 else
269 hueTemp = c.hue;
270
271 hueTemp = hueTemp/60.0f; // h is now in [0,6)
272 float i = floor(hueTemp); // largest integer <= h
273 float f = hueTemp-i; // fractional part of h
274
275 float p = c.value*(1.0f - c.saturation);
276 float q = c.value*(1.0f-(c.saturation*f));
277 float t = c.value*(1.0f-(c.saturation*(1.0-f)));
278
279 switch((int)i) {
280 case 0:
281 red = c.value;
282 green = t;
283 blue = p;
284 break;
285 case 1:
286 red = q;
287 green = c.value;
288 blue = p;
289 break;
290 case 2:
291 red = p;
292 green = c.value;
293 blue = t;
294 break;
295 case 3:
296 red = p;
297 green = q;
298 blue = c.value;
299 break;
300 case 4:
301 red = t;
302 green = p;
303 blue = c.value;
304 break;
305 case 5:
306 red = c.value;
307 green = p;
308 blue = q;
309 break;
310 }
311 }
312 RGBA ret;
313 ret.red = (Uint8)(red * 255.0f);
314 ret.green = (Uint8)(green * 255.0f);
315 ret.blue = (Uint8)(blue * 255.0f);
316 ret.alpha = c.alpha;
317 return ret;
318 }
319
iim_surface_shift_hue(IIM_Surface * isrc,float hue_offset)320 IIM_Surface *iim_surface_shift_hue(IIM_Surface *isrc, float hue_offset)
321 {
322 SDL_Surface *src = isrc->surf;
323 SDL_PixelFormat *fmt = src->format;
324 SDL_Surface *ret = SDL_CreateRGBSurface(src->flags, src->w, src->h, 32,
325 fmt->Rmask, fmt->Gmask,
326 fmt->Bmask, fmt->Amask);
327 SDL_LockSurface(src);
328 SDL_LockSurface(ret);
329 for (int y=src->h; y--;)
330 {
331 for (int x=src->w; x--;)
332 {
333 RGBA rgba = iim_surface_get_rgba(src,x,y);
334 HSVA hsva = iim_rgba2hsva(rgba);
335 hsva.hue += hue_offset;
336 if (hsva.hue > 360.0f) hsva.hue -= 360.0f;
337 if (hsva.hue < 0.0f) hsva.hue += 360.0f;
338 rgba = iim_hsva2rgba(hsva);
339 iim_surface_set_rgba(ret,x,y,rgba);
340 }
341 }
342 SDL_UnlockSurface(ret);
343 SDL_UnlockSurface(src);
344 SDL_Surface *ret2 = SDL_DisplayFormatAlpha(ret);
345 SDL_SetAlpha(ret2, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE);
346 SDL_FreeSurface(ret);
347 ret = isrc->surf;
348 isrc->surf = SDL_DisplayFormatAlpha(ret);
349 SDL_SetAlpha(isrc->surf, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE);
350 SDL_FreeSurface(ret);
351 return IIM_RegisterImg(ret2, true);
352 }
353
iim_surface_set_value(IIM_Surface * isrc,float value)354 IIM_Surface *iim_surface_set_value(IIM_Surface *isrc, float value)
355 {
356 SDL_Surface *src = isrc->surf;
357 SDL_PixelFormat *fmt = src->format;
358 SDL_Surface *ret = SDL_CreateRGBSurface(src->flags, src->w, src->h, 32,
359 fmt->Rmask, fmt->Gmask,
360 fmt->Bmask, fmt->Amask);
361 SDL_LockSurface(src);
362 SDL_LockSurface(ret);
363 for (int y=src->h; y--;)
364 {
365 for (int x=src->w; x--;)
366 {
367 RGBA rgba = iim_surface_get_rgba(src,x,y);
368 HSVA hsva = iim_rgba2hsva(rgba);
369 hsva.value = value;
370 if (hsva.value > 1.0f) hsva.value = 1.0f;
371 if (hsva.value < 0.0f) hsva.value = 0.0f;
372 rgba = iim_hsva2rgba(hsva);
373 iim_surface_set_rgba(ret,x,y,rgba);
374 }
375 }
376 SDL_UnlockSurface(src);
377 SDL_UnlockSurface(ret);
378 SDL_Surface *ret2 = SDL_DisplayFormatAlpha(ret);
379 SDL_SetAlpha(ret2, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE);
380 SDL_FreeSurface(ret);
381 return IIM_RegisterImg(ret2, true);
382 }
383
iim_surface_convert_to_gray(IIM_Surface * isrc)384 void iim_surface_convert_to_gray(IIM_Surface *isrc)
385 {
386 SDL_Surface *src = isrc->surf;
387 SDL_PixelFormat *fmt = src->format;
388 SDL_LockSurface(src);
389 for (int y=src->h; y--;)
390 {
391 for (int x=src->w; x--;)
392 {
393 RGBA rgba = iim_surface_get_rgba(src,x,y);
394 Uint8 l = iim_rgba2gray(rgba);
395 rgba.red = rgba.blue = rgba.green = l;
396 iim_surface_set_rgb(src,x,y,rgba);
397 }
398 }
399 SDL_UnlockSurface(src);
400 isrc->surf = SDL_DisplayFormat(src);
401 SDL_FreeSurface(src);
402 }
403