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 )
219inline float clamp(
const float x,
const float min,
const float max )
222 else if(x >
max)
return max;
228 if(image.size() == 0)
231 std::vector<unsigned char> tmp(image.width()*image.height()*4);
232 for(
unsigned i= 0, offset= 0; i < image.size(); i++, offset+= 4)
234 Color pixel= image(i) * 255;
235 tmp[offset ]=
clamp(pixel.r, 0, 255);
236 tmp[offset +1]=
clamp(pixel.g, 0, 255);
237 tmp[offset +2]=
clamp(pixel.b, 0, 255);
238 tmp[offset +3]=
clamp(pixel.a, 0, 255);
241 stbi_flip_vertically_on_write(
flipY);
242 return stbi_write_png(filename, image.width(), image.height(), 4, tmp.data(), image.width() * 4) != 0;
252 if(image.size() == 0)
255 std::vector<unsigned char> tmp(image.width()*image.height()*4);
256 for(
unsigned i= 0, offset= 0; i < image.size(); i++, offset+= 4)
258 Color pixel= image(i) * 255;
259 tmp[offset ]=
clamp(pixel.r, 0, 255);
260 tmp[offset +1]=
clamp(pixel.g, 0, 255);
261 tmp[offset +2]=
clamp(pixel.b, 0, 255);
262 tmp[offset +3]=
clamp(pixel.a, 0, 255);
265 stbi_flip_vertically_on_write(
flipY);
266 return stbi_write_bmp(filename, image.width(), image.height(), 4, tmp.data()) != 0;
271 if(image.size() == 0)
274 stbi_flip_vertically_on_write(
flipY);
275 return stbi_write_hdr(filename, image.width(), image.height(), 4, image.data()) != 0;
280 if(image.size() == 0)
283 Image tmp= tone(image, range(image));
288ImageData image_data(
unsigned char *data,
const int width,
const int height,
const int channels )
290 int n= std::max(3, channels);
295 for(
int i= 0; i < width*height*4; i+= 4)
297 image.pixels[i]= data[i];
298 image.pixels[i+1]= data[i+1];
299 image.pixels[i+2]= data[i+2];
300 image.pixels[i+3]= data[i+3];
303 else if(channels == 3)
305 for(
int i= 0; i < width*height*3; i+= 3)
307 image.pixels[i]= data[i];
308 image.pixels[i+1]= data[i+1];
309 image.pixels[i+2]= data[i+2];
315 for(
int i= 0; i < width*height*3; i+= 3)
321 if(n >= 1) { r= data[k++]; g= r; b= r; }
322 if(n >= 2) { g= data[k++]; b= 0; }
323 if(n >= 3) { b= data[k++]; }
326 image.pixels[i+1]= g;
327 image.pixels[i+2]= b;
331 stbi_image_free(data);
337 stbi_set_flip_vertically_on_load(
flipY);
339 int width, height, channels;
340 unsigned char *data= stbi_load_from_memory((
const unsigned char *) buffer, size, &width, &height, &channels, 0);
343 printf(
"[error] reading buffer image...\n");
347 return image_data(data, width, height, channels);
352 stbi_set_flip_vertically_on_load(
flipY);
354 int width, height, channels;
355 unsigned char *data= stbi_load(filename, &width, &height, &channels, 0);
358 printf(
"[error] loading '%s'...\n", filename);
362 return image_data(data, width, height, channels);
370 printf(
"[error] writing color image '%s'... not an 8 bits image.\n", filename);
374 stbi_flip_vertically_on_write(
flipY);
377 if(std::string(filename).rfind(
".png") != std::string::npos)
378 code= stbi_write_png(filename, image.width, image.height, image.channels, image.pixels.data(), image.width * image.channels) != 0;
379 else if(std::string(filename).rfind(
".bmp") != std::string::npos)
380 code= stbi_write_bmp(filename, image.width, image.height, image.channels, image.pixels.data()) != 0;
384 printf(
"[error] writing color image '%s'... not a .png / .bmp image.\n", filename);
391 printf(
"[error] writing color image '%s'...\n", filename);
399 ImageData tmp(image.width, image.height, image.channels);
401 for(
unsigned i= 0; i < image.pixels.size(); i+= image.channels)
403 Color pixel=
srgb(
Color( image.pixels[i], image.pixels[i+1], image.pixels[i+2], (image.channels > 3) ? image.pixels[i+3] : 255 ) / 255 );
405 tmp.pixels[i]=
clamp(pixel.r * 255, 0, 255);
406 tmp.pixels[i +1]=
clamp(pixel.g * 255, 0, 255);
407 tmp.pixels[i +2]=
clamp(pixel.b * 255, 0, 255);
408 if(image.channels > 3)
409 tmp.pixels[i +3]=
clamp(pixel.a * 255, 0, 255);
417 ImageData tmp(image.width, image.height, image.channels);
419 for(
unsigned i= 0; i < image.pixels.size(); i+= image.channels)
421 Color pixel=
linear(
Color( image.pixels[i], image.pixels[i+1], image.pixels[i+2], (image.channels > 3) ? image.pixels[i+3] : 255 ) / 255 );
423 tmp.pixels[i]=
clamp(pixel.r * 255, 0, 255);
424 tmp.pixels[i +1]=
clamp(pixel.g * 255, 0, 255);
425 tmp.pixels[i +2]=
clamp(pixel.b * 255, 0, 255);
426 if(image.channels > 3)
427 tmp.pixels[i +3]=
clamp(pixel.a * 255, 0, 255);
436 ImageData flip(image.width, image.height, image.channels);
438 for(
unsigned y= 0; y < image.height; y++)
439 for(
unsigned x= 0; x < image.width; x++)
441 unsigned s= image.offset(x, y);
442 unsigned d= flip.offset(x, flip.height - y -1);
444 for(
unsigned i= 0; i < image.channels; i++)
445 flip.pixels[d +i]= image.pixels[s +i];
453 ImageData flip(image.width, image.height, image.channels);
455 for(
unsigned y= 0; y < image.height; y++)
456 for(
unsigned x= 0; x < image.width; x++)
458 unsigned s= image.offset(x, y);
459 unsigned d= flip.offset(flip.width -x -1, y);
461 for(
unsigned i= 0; i < image.channels; i++)
462 flip.pixels[d +i]= image.pixels[s +i];
468ImageData copy(
const ImageData& image,
const unsigned xmin,
const unsigned ymin,
const unsigned width,
const unsigned height )
472 for(
unsigned y= 0; y < height; y++)
473 for(
unsigned x= 0; x < width; x++)
475 unsigned s= image.offset(xmin +x, ymin +y);
476 unsigned d=
copy.offset(x, y);
478 for(
unsigned i= 0; i < image.channels; i++)
479 copy.pixels[d +i]= image.pixels[s +i];
488 if(image.pixels.size() == 0)
490 if(pixels.pixels.size() == 0)
492 if(image.channels != pixels.channels)
495 unsigned xmax= std::min( image.width, xmin + pixels.width );
496 unsigned ymax= std::min( image.height, ymin + pixels.height );
497 unsigned w= xmax - xmin;
498 unsigned h= ymax - ymin;
500 for(
unsigned y= 0; y < h; y++)
501 for(
unsigned x= 0; x < w; x++)
503 unsigned char *dst= image.pixels.data() + image.offset(x + xmin, y + ymin);
504 const unsigned char *src= pixels.pixels.data() + pixels.offset(x, y);
505 for(
unsigned i= 0; i < pixels.channels; i++)
514 unsigned w= std::max(
unsigned(1), image.width / 2);
515 unsigned h= std::max(
unsigned(1), image.height / 2);
519 for(
unsigned py= 0; py < h; py++)
520 for(
unsigned px= 0; px < w; px++)
524 unsigned d= tmp.offset(px, py);
526 for(
unsigned i= 0; i < image.channels; i++)
528 image.pixels[image.offset(x, y) +i]
529 + image.pixels[image.offset(x+1, y) +i]
530 + image.pixels[image.offset(x, y+1) +i]
531 + image.pixels[image.offset(x+1, y+1) +i] ) / 4;
542 while(w > 1 || h > 1)
544 w= std::max(1, w / 2);
545 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)
float clamp(const float x, const float min, const float max)
renvoie une valeur comprise entre a et b.
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
Point max(const Point &a, const Point &b)
renvoie la plus grande composante de chaque point { max(a.x, b.x), max(a.y, b.y), max(a....
Point min(const Point &a, const Point &b)
renvoie la plus petite composante de chaque point { min(a.x, b.x), min(a.y, b.y), min(a....
representation d'une couleur (rgba) transparente ou opaque.
stockage temporaire des donnees d'une image.