gKit2 light
image_io.cpp
1 
2 #include <cstdio>
3 #include <string>
4 #include <algorithm>
5 #include <cmath>
6 
7 #ifdef GK_MACOS
8 #include <SDL2_image/SDL_image.h>
9 #else
10 #include <SDL2/SDL_image.h>
11 #endif
12 
13 #include "image_io.h"
14 
15 
16 Image read_image( const char *filename )
17 {
18  // importer le fichier en utilisant SDL_image
19  SDL_Surface *surface= IMG_Load(filename);
20  if(surface == NULL)
21  {
22  printf("loading image '%s'... sdl_image failed.\n", filename);
23  return Image::error();
24  }
25 
26  // verifier le format, rgb ou rgba
27  const SDL_PixelFormat format= *surface->format;
28  if(format.BitsPerPixel != 24 && format.BitsPerPixel != 32)
29  {
30  printf("loading image '%s'... format failed. (bpp %d)\n", filename, format.BitsPerPixel);
31  SDL_FreeSurface(surface);
32  return Image::error();
33  }
34 
35  int width= surface->w;
36  int height= surface->h;
37  int channels= (format.BitsPerPixel == 32) ? 4 : 3;
38 
39  Image image(surface->w, surface->h);
40 
41  printf("loading image '%s' %dx%d %d channels...\n", filename, width, height, channels);
42 
43  // converti les donnees en pixel rgba, et retourne l'image, origine en bas a gauche.
44  if(format.BitsPerPixel == 32)
45  {
46  int py= 0;
47  for(int y= height -1; y >= 0; y--, py++)
48  {
49  Uint8 *pixel= (Uint8 *) surface->pixels + py * surface->pitch;
50 
51  for(int x= 0; x < width; x++)
52  {
53  Uint8 r= pixel[format.Rshift / 8];
54  Uint8 g= pixel[format.Gshift / 8];
55  Uint8 b= pixel[format.Bshift / 8];
56  Uint8 a= pixel[format.Ashift / 8];
57 
58  image(x, y)= Color((float) r / 255.f, (float) g / 255.f, (float) b / 255.f, (float) a / 255.f);
59  pixel= pixel + format.BytesPerPixel;
60  }
61  }
62  }
63 
64  else if(format.BitsPerPixel == 24)
65  {
66  int py= 0;
67  for(int y= height -1; y >= 0; y--, py++)
68  {
69  Uint8 *pixel= (Uint8 *) surface->pixels + py * surface->pitch;
70 
71  for(int x= 0; x < surface->w; x++)
72  {
73  const Uint8 r= pixel[format.Rshift / 8];
74  const Uint8 g= pixel[format.Gshift / 8];
75  const Uint8 b= pixel[format.Bshift / 8];
76 
77  image(x, y)= Color((float) r / 255.f, (float) g / 255.f, (float) b / 255.f);
78  pixel= pixel + format.BytesPerPixel;
79  }
80  }
81  }
82 
83  SDL_FreeSurface(surface);
84  return image;
85 }
86 
87 
88 int write_image( const Image& image, const char *filename )
89 {
90  if(std::string(filename).rfind(".png") == std::string::npos && std::string(filename).rfind(".bmp") == std::string::npos )
91  {
92  printf("writing color image '%s'... failed, not a .png / .bmp image.\n", filename);
93  return -1;
94  }
95 
96  // flip de l'image : Y inverse entre GL et BMP
97  std::vector<Uint8> flip(image.width() * image.height() * 4);
98 
99  int p= 0;
100  for(int y= 0; y < image.height(); y++)
101  for(int x= 0; x < image.width(); x++)
102  {
103  Color color= image(x, image.height() - y -1);
104  Uint8 r= (Uint8) std::min(std::floor(color.r * 255.f), 255.f);
105  Uint8 g= (Uint8) std::min(std::floor(color.g * 255.f), 255.f);
106  Uint8 b= (Uint8) std::min(std::floor(color.b * 255.f), 255.f);
107  Uint8 a= (Uint8) std::min(std::floor(color.a * 255.f), 255.f);
108 
109  flip[p]= r;
110  flip[p +1]= g;
111  flip[p +2]= b;
112  flip[p +3]= a;
113  p= p + 4;
114  }
115 
116  SDL_Surface *surface= SDL_CreateRGBSurfaceFrom((void *) &flip.front(), image.width(), image.height(),
117  32, image.width() * 4,
118 #if 0
119  0xFF000000,
120  0x00FF0000,
121  0x0000FF00,
122  0x000000FF
123 #else
124  0x000000FF,
125  0x0000FF00,
126  0x00FF0000,
127  0xFF000000
128 #endif
129  );
130 
131  int code= -1;
132  if(std::string(filename).rfind(".png") != std::string::npos)
133  code= IMG_SavePNG(surface, filename);
134  else if(std::string(filename).rfind(".bmp") != std::string::npos)
135  code= SDL_SaveBMP(surface, filename);
136 
137  SDL_FreeSurface(surface);
138  if(code < 0)
139  printf("writing color image '%s'... failed\n%s\n", filename, SDL_GetError());
140  return code;
141 }
142 
143 
144 ImageData read_image_data( const char *filename )
145 {
146  // importer le fichier en utilisant SDL_image
147  SDL_Surface *surface= IMG_Load(filename);
148  if(surface == NULL)
149  {
150  printf("loading image '%s'... sdl_image failed.\n", filename);
151  return ImageData();
152  }
153 
154  // verifier le format, rgb ou rgba
155  const SDL_PixelFormat format= *surface->format;
156  if(format.BitsPerPixel != 24 && format.BitsPerPixel != 32)
157  {
158  printf("loading image '%s'... format failed. (bpp %d)\n", filename, format.BitsPerPixel);
159  SDL_FreeSurface(surface);
160  return ImageData();
161  }
162 
163  int width= surface->w;
164  int height= surface->h;
165  int channels= (format.BitsPerPixel == 32) ? 4 : 3;
166 
167  ImageData image(width, height, channels);
168 
169  printf("loading image '%s' %dx%d %d channels...\n", filename, width, height, channels);
170 
171  // converti les donnees en pixel rgba, et retourne l'image, origine en bas a gauche.
172  if(format.BitsPerPixel == 32)
173  {
174  int py= 0;
175  for(int y= height -1; y >= 0; y--, py++)
176  {
177  Uint8 *pixel= (Uint8 *) surface->pixels + py * surface->pitch;
178 
179  for(int x= 0; x < width; x++)
180  {
181  Uint8 r= pixel[format.Rshift / 8];
182  Uint8 g= pixel[format.Gshift / 8];
183  Uint8 b= pixel[format.Bshift / 8];
184  Uint8 a= pixel[format.Ashift / 8];
185 
186  std::size_t offset= image.offset(x, y);
187  image.data[offset]= r;
188  image.data[offset +1]= g;
189  image.data[offset +2]= b;
190  image.data[offset +3]= a;
191  pixel= pixel + format.BytesPerPixel;
192  }
193  }
194  }
195 
196  else if(format.BitsPerPixel == 24)
197  {
198  int py= 0;
199  for(int y= height -1; y >= 0; y--, py++)
200  {
201  Uint8 *pixel= (Uint8 *) surface->pixels + py * surface->pitch;
202 
203  for(int x= 0; x < surface->w; x++)
204  {
205  const Uint8 r= pixel[format.Rshift / 8];
206  const Uint8 g= pixel[format.Gshift / 8];
207  const Uint8 b= pixel[format.Bshift / 8];
208 
209  std::size_t offset= image.offset(x, y);
210  image.data[offset]= r;
211  image.data[offset +1]= g;
212  image.data[offset +2]= b;
213  pixel= pixel + format.BytesPerPixel;
214  }
215  }
216  }
217 
218  SDL_FreeSurface(surface);
219  return image;
220 }
221 
222 int write_image_data( ImageData& image, const char *filename )
223 {
224  if(std::string(filename).rfind(".png") == std::string::npos && std::string(filename).rfind(".bmp") == std::string::npos )
225  {
226  printf("writing color image '%s'... failed, not a .png / .bmp image.\n", filename);
227  return -1;
228  }
229 
230  if(image.size != 1)
231  {
232  printf("writing color image '%s'... failed, not an 8 bits image.\n", filename);
233  return -1;
234  }
235 
236  // flip de l'image : origine en bas a gauche
237  std::vector<Uint8> flip(image.width * image.height * 4);
238 
239  int p= 0;
240  for(int y= 0; y < image.height; y++)
241  for(int x= 0; x < image.width; x++)
242  {
243  std::size_t offset= image.offset(x, image.height - y -1);
244  Uint8 r= image.data[offset];
245  Uint8 g= image.data[offset +1];
246  Uint8 b= image.data[offset +2];
247  Uint8 a= 255;
248  if(image.channels > 3)
249  a= image.data[offset +3];
250 
251  flip[p]= r;
252  flip[p +1]= g;
253  flip[p +2]= b;
254  flip[p +3]= a;
255  p= p + 4;
256  }
257 
258  // construit la surface sdl
259  SDL_Surface *surface= SDL_CreateRGBSurfaceFrom((void *) &flip.front(), image.width, image.height,
260  32, image.width * 4,
261 #if 0
262  0xFF000000,
263  0x00FF0000,
264  0x0000FF00,
265  0x000000FF
266 #else
267  0x000000FF,
268  0x0000FF00,
269  0x00FF0000,
270  0xFF000000
271 #endif
272  );
273 
274  // enregistre le fichier
275  int code= -1;
276  if(std::string(filename).rfind(".png") != std::string::npos)
277  code= IMG_SavePNG(surface, filename);
278  else if(std::string(filename).rfind(".bmp") != std::string::npos)
279  code= SDL_SaveBMP(surface, filename);
280 
281  SDL_FreeSurface(surface);
282  if(code < 0)
283  printf("writing color image '%s'... failed\n%s\n", filename, SDL_GetError());
284  return code;
285 }
ImageData read_image_data(const char *filename)
charge les donnees d'un fichier png. renvoie une image initialisee par defaut en cas d'echec...
Definition: image_io.cpp:144
stockage temporaire des donnees d'une image.
Definition: image_io.h:23
static Image & error()
Definition: image.h:75
representation d'une couleur (rgba) transparente ou opaque.
Definition: color.h:13
int write_image_data(ImageData &image, const char *filename)
enregistre des donnees dans un fichier png.
Definition: image_io.cpp:222
int height() const
renvoie la hauteur de l'image.
Definition: image.h:63
Image read_image(const char *filename)
Definition: image_io.cpp:16
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition: text.cpp:140
int write_image(const Image &image, const char *filename)
enregistre une image dans un fichier png.
Definition: image_io.cpp:88
representation d'une image.
Definition: image.h:18
int width() const
renvoie la largeur de l'image.
Definition: image.h:61