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