9#define STB_IMAGE_IMPLEMENTATION
12#define STB_IMAGE_WRITE_IMPLEMENTATION
13#include "stb_image_write.h"
17 Image tmp(image.width(), image.height());
19 for(
unsigned i= 0; i < image.size(); i++)
20 tmp(i)=
srgb(image(i));
27 Image tmp(image.width(), image.height());
29 for(
unsigned i= 0; i < image.size(); i++)
35float range(
const Image& image )
39 for(
unsigned i= 0; i < image.size(); i++)
41 Color color= image(i);
42 float g= color.r + color.g + color.b;
50 for(
unsigned i= 0; i < image.size(); i++)
52 Color color= image(i);
53 float g= color.r + color.g + color.b;
55 int b= (g - gmin) * 100 / (gmax - gmin);
63 for(
unsigned i= 0; i < 100; i++)
65 qbins= qbins + float(bins[i]) / float(image.size());
67 return gmin + float(i+1) / 100 * (gmax - gmin);
73Image tone(
const Image& image,
const float saturation )
75 Image tmp(image.width(), image.height());
77 float k= 1 / std::pow(saturation, 1 / 2.2f);
78 for(
unsigned i= 0; i < image.size(); i++)
80 Color color= image(i);
81 if(std::isnan(color.r) || std::isnan(color.g) || std::isnan(color.b))
83 color=
Color(1, 0, 1);
86 color= k *
srgb(color);
88 tmp(i)=
Color(color, 1);
97 unsigned w= std::max(
unsigned(1), image.width() / 2);
98 unsigned h= std::max(
unsigned(1), image.height() / 2);
102 for(
unsigned py= 0; py < h; py++)
103 for(
unsigned px= 0; px < w; px++)
107 tmp(px, py)= (image(x, y) + image(x +1, y) + image(x +1, y +1) + image(x, y +1)) / 4;
116 Image flip(image.width(), image.height());
118 for(
unsigned y= 0; y < image.height(); y++)
119 for(
unsigned x= 0; x < image.width(); x++)
121 unsigned s= image.offset(x, y);
132 Image flip(image.width(), image.height());
134 for(
unsigned y= 0; y < image.height(); y++)
135 for(
unsigned x= 0; x < image.width(); x++)
137 unsigned s= image.offset(x, y);
146Image copy(
const Image& image,
const unsigned xmin,
const unsigned ymin,
const unsigned width,
const unsigned height )
150 for(
unsigned y= 0; y < height; y++)
151 for(
unsigned x= 0; x < width; x++)
153 unsigned s= image.offset(xmin+x, ymin+y);
154 unsigned d=
copy.offset(x, y);
164 if(image.size() == 0)
166 if(pixels.size() == 0)
169 unsigned xmax= std::min( image.width(), xmin + pixels.width() );
170 unsigned ymax= std::min( image.height(), ymin + pixels.height() );
171 unsigned w= xmax - xmin;
172 unsigned h= ymax - ymin;
174 for(
unsigned y= 0; y < h; y++)
175 for(
unsigned x= 0; x < w; x++)
176 image(x + xmin, y + ymin)= pixels(x, y);
185 if(!stbi_info(filename, &w, &h, &c))
188 return sizeof(
Color)*w*h;
193 stbi_ldr_to_hdr_scale(1);
194 stbi_ldr_to_hdr_gamma(1);
195 stbi_set_flip_vertically_on_load(
flipY);
197 int width, height, channels;
198 float *data= stbi_loadf(filename, &width, &height, &channels, 4);
201 printf(
"[error] loading '%s'...\n", filename);
205 Image image(width, height);
206 for(
unsigned i= 0, offset= 0; i < image.size(); i++, offset+= 4)
207 image(i)=
Color( data[offset], data[offset + 1], data[offset + 2], data[offset + 3]);
209 stbi_image_free(data);
213Image read_image_hdr(
const char *filename,
const bool flipY )
221 if(image.size() == 0)
224 std::vector<unsigned char> tmp(image.width()*image.height()*4);
225 for(
unsigned i= 0, offset= 0; i < image.size(); i++, offset+= 4)
227 Color pixel= image(i) * 255;
228 tmp[offset ]= clamp(pixel.r, 0, 255);
229 tmp[offset +1]= clamp(pixel.g, 0, 255);
230 tmp[offset +2]= clamp(pixel.b, 0, 255);
231 tmp[offset +3]= clamp(pixel.a, 0, 255);
234 stbi_flip_vertically_on_write(
flipY);
235 return stbi_write_png(filename, image.width(), image.height(), 4, tmp.data(), image.width() * 4) != 0;
245 if(image.size() == 0)
248 std::vector<unsigned char> tmp(image.width()*image.height()*4);
249 for(
unsigned i= 0, offset= 0; i < image.size(); i++, offset+= 4)
251 Color pixel= image(i) * 255;
252 tmp[offset ]= clamp(pixel.r, 0, 255);
253 tmp[offset +1]= clamp(pixel.g, 0, 255);
254 tmp[offset +2]= clamp(pixel.b, 0, 255);
255 tmp[offset +3]= clamp(pixel.a, 0, 255);
258 stbi_flip_vertically_on_write(
flipY);
259 return stbi_write_bmp(filename, image.width(), image.height(), 4, tmp.data()) != 0;
264 if(image.size() == 0)
267 stbi_flip_vertically_on_write(
flipY);
268 return stbi_write_hdr(filename, image.width(), image.height(), 4, image.data()) != 0;
273 if(image.size() == 0)
276 Image tmp= tone(image, range(image));
281ImageData image_data(
unsigned char *data,
const int width,
const int height,
const int channels )
283 int n= std::max(3, channels);
288 for(
int i= 0; i < width*height*4; i+= 4)
290 image.pixels[i]= data[i];
291 image.pixels[i+1]= data[i+1];
292 image.pixels[i+2]= data[i+2];
293 image.pixels[i+3]= data[i+3];
296 else if(channels == 3)
298 for(
int i= 0; i < width*height*3; i+= 3)
300 image.pixels[i]= data[i];
301 image.pixels[i+1]= data[i+1];
302 image.pixels[i+2]= data[i+2];
308 for(
int i= 0; i < width*height*3; i+= 3)
314 if(n >= 1) { r= data[k++]; g= r; b= r; }
315 if(n >= 2) { g= data[k++]; b= 0; }
316 if(n >= 3) { b= data[k++]; }
319 image.pixels[i+1]= g;
320 image.pixels[i+2]= b;
324 stbi_image_free(data);
330 stbi_set_flip_vertically_on_load(
flipY);
332 int width, height, channels;
333 unsigned char *data= stbi_load_from_memory((
const unsigned char *) buffer, size, &width, &height, &channels, 0);
336 printf(
"[error] reading buffer image...\n");
340 return image_data(data, width, height, channels);
345 stbi_set_flip_vertically_on_load(
flipY);
347 int width, height, channels;
348 unsigned char *data= stbi_load(filename, &width, &height, &channels, 0);
351 printf(
"[error] loading '%s'...\n", filename);
355 return image_data(data, width, height, channels);
363 printf(
"[error] writing color image '%s'... not an 8 bits image.\n", filename);
367 stbi_flip_vertically_on_write(
flipY);
370 if(std::string(filename).rfind(
".png") != std::string::npos)
371 code= stbi_write_png(filename, image.width, image.height, image.channels, image.pixels.data(), image.width * image.channels) != 0;
372 else if(std::string(filename).rfind(
".bmp") != std::string::npos)
373 code= stbi_write_bmp(filename, image.width, image.height, image.channels, image.pixels.data()) != 0;
377 printf(
"[error] writing color image '%s'... not a .png / .bmp image.\n", filename);
384 printf(
"[error] writing color image '%s'...\n", filename);
392 ImageData tmp(image.width, image.height, image.channels);
394 for(
unsigned i= 0; i < image.pixels.size(); i+= image.channels)
396 Color pixel=
srgb(
Color( image.pixels[i], image.pixels[i+1], image.pixels[i+2], (image.channels > 3) ? image.pixels[i+3] : 255 ) / 255 );
398 tmp.pixels[i]= clamp(pixel.r * 255, 0, 255);
399 tmp.pixels[i +1]= clamp(pixel.g * 255, 0, 255);
400 tmp.pixels[i +2]= clamp(pixel.b * 255, 0, 255);
401 if(image.channels > 3)
402 tmp.pixels[i +3]= clamp(pixel.a * 255, 0, 255);
410 ImageData tmp(image.width, image.height, image.channels);
412 for(
unsigned i= 0; i < image.pixels.size(); i+= image.channels)
414 Color pixel=
linear(
Color( image.pixels[i], image.pixels[i+1], image.pixels[i+2], (image.channels > 3) ? image.pixels[i+3] : 255 ) / 255 );
416 tmp.pixels[i]= clamp(pixel.r * 255, 0, 255);
417 tmp.pixels[i +1]= clamp(pixel.g * 255, 0, 255);
418 tmp.pixels[i +2]= clamp(pixel.b * 255, 0, 255);
419 if(image.channels > 3)
420 tmp.pixels[i +3]= clamp(pixel.a * 255, 0, 255);
429 ImageData flip(image.width, image.height, image.channels);
431 for(
unsigned y= 0; y < image.height; y++)
432 for(
unsigned x= 0; x < image.width; x++)
434 unsigned s= image.offset(x, y);
435 unsigned d= flip.offset(x, flip.height - y -1);
437 for(
unsigned i= 0; i < image.channels; i++)
438 flip.pixels[d +i]= image.pixels[s +i];
446 ImageData flip(image.width, image.height, image.channels);
448 for(
unsigned y= 0; y < image.height; y++)
449 for(
unsigned x= 0; x < image.width; x++)
451 unsigned s= image.offset(x, y);
452 unsigned d= flip.offset(flip.width -x -1, y);
454 for(
unsigned i= 0; i < image.channels; i++)
455 flip.pixels[d +i]= image.pixels[s +i];
461ImageData copy(
const ImageData& image,
const unsigned xmin,
const unsigned ymin,
const unsigned width,
const unsigned height )
465 for(
unsigned y= 0; y < height; y++)
466 for(
unsigned x= 0; x < width; x++)
468 unsigned s= image.offset(xmin +x, ymin +y);
469 unsigned d=
copy.offset(x, y);
471 for(
unsigned i= 0; i < image.channels; i++)
472 copy.pixels[d +i]= image.pixels[s +i];
481 if(image.pixels.size() == 0)
483 if(pixels.pixels.size() == 0)
485 if(image.channels != pixels.channels)
488 unsigned xmax= std::min( image.width, xmin + pixels.width );
489 unsigned ymax= std::min( image.height, ymin + pixels.height );
490 unsigned w= xmax - xmin;
491 unsigned h= ymax - ymin;
493 for(
unsigned y= 0; y < h; y++)
494 for(
unsigned x= 0; x < w; x++)
496 unsigned char *dst= image.pixels.data() + image.offset(x + xmin, y + ymin);
497 const unsigned char *src= pixels.pixels.data() + pixels.offset(x, y);
498 for(
unsigned i= 0; i < pixels.channels; i++)
507 unsigned w= std::max(
unsigned(1), image.width / 2);
508 unsigned h= std::max(
unsigned(1), image.height / 2);
512 for(
unsigned py= 0; py < h; py++)
513 for(
unsigned px= 0; px < w; px++)
517 unsigned d= tmp.offset(px, py);
519 for(
unsigned i= 0; i < image.channels; i++)
521 image.pixels[image.offset(x, y) +i]
522 + image.pixels[image.offset(x+1, y) +i]
523 + image.pixels[image.offset(x, y+1) +i]
524 + image.pixels[image.offset(x+1, y+1) +i] ) / 4;
535 while(w > 1 || h > 1)
537 w= std::max(1, w / 2);
538 h= std::max(1, h / 2);
representation d'une image.
unsigned width() const
renvoie la largeur de l'image.
unsigned height() const
renvoie la hauteur de l'image.
unsigned offset(const int x, const int y) const
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().
bool write_image_png(const Image &image, const char *filename, const bool flipY)
enregistre une image au format .png
bool write_image_preview(const Image &image, const char *filename, const bool flipY)
raccourci pour write_image_png(tone(image, range(image)), "image.png")
bool write_image_hdr(const Image &image, const char *filename, const bool flipY)
enregistre une image au format .hdr
unsigned read_image_size(const char *filename)
renvoie la taille en octets de l'image chargee. ou 0 si erreur.
bool write_image_bmp(const Image &image, const char *filename, const bool flipY)
enregistre une image au format .bmp
Image & blit(Image &image, const unsigned xmin, const unsigned ymin, const Image &pixels)
remplace un bout d'image par une autre. copie l'image pixels dans image [xmin, xmin+pixels....
Image mipmap(const Image &image)
reduit une image.
Image flipY(const Image &image)
retourne l'image
Image flipX(const Image &image)
retourne l'image
Image read_image(const char *filename, const bool flipY)
int write_image_data(const ImageData &image, const char *filename, const bool flipY)
enregistre des donnees dans un fichier png.
Image linear(const Image &image)
transformation couleur : srgb vers rgb lineaire
ImageData read_image_data(const void *buffer, const unsigned size, const bool flipY)
charge les donnees d'un fichier png stocke en memoire. renvoie une image initialisee par defaut en ca...
bool write_image(const Image &image, const char *filename, const bool flipY)
enregistre une image au format .png
Image copy(const Image &image, const unsigned xmin, const unsigned ymin, const unsigned width, const unsigned height)
renvoie un bloc de l'image
int miplevels(const int width, const int height)
renvoie le nombre de mipmap d'une image width x height.
Image srgb(const Image &image)
transformation couleur : rgb lineaire vers srgb
representation d'une couleur (rgba) transparente ou opaque.
stockage temporaire des donnees d'une image.