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= clamp(image(i) * 255, 0, 255);
228 tmp[offset ]= pixel.r;
229 tmp[offset +1]= pixel.g;
230 tmp[offset +2]= pixel.b;
231 tmp[offset +3]= pixel.a;
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= clamp(image(i) * 255, 0, 255);
252 tmp[offset ]= pixel.r;
253 tmp[offset +1]= pixel.g;
254 tmp[offset +2]= pixel.b;
255 tmp[offset +3]= pixel.a;
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);
361 if(!stbi_info(filename, &w, &h, &channels))
364 return w*h * channels;
372 printf(
"[error] writing color image '%s'... not an 8 bits image.\n", filename);
376 stbi_flip_vertically_on_write(
flipY);
379 if(std::string(filename).rfind(
".png") != std::string::npos)
380 code= stbi_write_png(filename, image.width, image.height, image.channels, image.pixels.data(), image.width * image.channels) != 0;
381 else if(std::string(filename).rfind(
".bmp") != std::string::npos)
382 code= stbi_write_bmp(filename, image.width, image.height, image.channels, image.pixels.data()) != 0;
386 printf(
"[error] writing color image '%s'... not a .png / .bmp image.\n", filename);
393 printf(
"[error] writing color image '%s'...\n", filename);
401 ImageData tmp(image.width, image.height, image.channels);
403 for(
unsigned i= 0; i < image.pixels.size(); i+= image.channels)
405 Color pixel=
srgb(
Color( image.pixels[i], image.pixels[i+1], image.pixels[i+2], (image.channels > 3) ? image.pixels[i+3] : 255 ) / 255 );
407 pixel= clamp(pixel * 255, 0, 255);
408 tmp.pixels[i]= pixel.r;
409 tmp.pixels[i +1]= pixel.g;
410 tmp.pixels[i +2]= pixel.b;
411 if(image.channels > 3)
412 tmp.pixels[i +3]= pixel.a;
420 ImageData tmp(image.width, image.height, image.channels);
422 for(
unsigned i= 0; i < image.pixels.size(); i+= image.channels)
424 Color pixel=
linear(
Color( image.pixels[i], image.pixels[i+1], image.pixels[i+2], (image.channels > 3) ? image.pixels[i+3] : 255 ) / 255 );
426 pixel= clamp(pixel * 255, 0, 255);
427 tmp.pixels[i]= pixel.r;
428 tmp.pixels[i +1]= pixel.g;
429 tmp.pixels[i +2]= pixel.b;
430 if(image.channels > 3)
431 tmp.pixels[i +3]= pixel.a;
440 ImageData flip(image.width, image.height, image.channels);
442 for(
unsigned y= 0; y < image.height; y++)
443 for(
unsigned x= 0; x < image.width; x++)
445 unsigned s= image.offset(x, y);
446 unsigned d= flip.offset(x, flip.height - y -1);
448 for(
unsigned i= 0; i < image.channels; i++)
449 flip.pixels[d +i]= image.pixels[s +i];
457 ImageData flip(image.width, image.height, image.channels);
459 for(
unsigned y= 0; y < image.height; y++)
460 for(
unsigned x= 0; x < image.width; x++)
462 unsigned s= image.offset(x, y);
463 unsigned d= flip.offset(flip.width -x -1, y);
465 for(
unsigned i= 0; i < image.channels; i++)
466 flip.pixels[d +i]= image.pixels[s +i];
472ImageData copy(
const ImageData& image,
const unsigned xmin,
const unsigned ymin,
const unsigned width,
const unsigned height )
476 for(
unsigned y= 0; y < height; y++)
477 for(
unsigned x= 0; x < width; x++)
479 unsigned s= image.offset(xmin +x, ymin +y);
480 unsigned d=
copy.offset(x, y);
482 for(
unsigned i= 0; i < image.channels; i++)
483 copy.pixels[d +i]= image.pixels[s +i];
492 if(image.pixels.size() == 0)
494 if(pixels.pixels.size() == 0)
496 if(image.channels != pixels.channels)
499 unsigned xmax= std::min( image.width, xmin + pixels.width );
500 unsigned ymax= std::min( image.height, ymin + pixels.height );
501 unsigned w= xmax - xmin;
502 unsigned h= ymax - ymin;
504 for(
unsigned y= 0; y < h; y++)
505 for(
unsigned x= 0; x < w; x++)
507 unsigned char *dst= image.pixels.data() + image.offset(x + xmin, y + ymin);
508 const unsigned char *src= pixels.pixels.data() + pixels.offset(x, y);
509 for(
unsigned i= 0; i < pixels.channels; i++)
518 unsigned w= std::max(
unsigned(1), image.width / 2);
519 unsigned h= std::max(
unsigned(1), image.height / 2);
523 for(
unsigned py= 0; py < h; py++)
524 for(
unsigned px= 0; px < w; px++)
528 unsigned d= tmp.offset(px, py);
530 for(
unsigned i= 0; i < image.channels; i++)
532 image.pixels[image.offset(x, y) +i]
533 + image.pixels[image.offset(x+1, y) +i]
534 + image.pixels[image.offset(x, y+1) +i]
535 + image.pixels[image.offset(x+1, y+1) +i] ) / 4;
546 while(w > 1 || h > 1)
548 w= std::max(1, w / 2);
549 h= std::max(1, h / 2);
558 if(data.pixels.empty())
561 assert(data.channels >= 3);
562 Image tmp( data.width, data.height );
564 for(
unsigned i= 0; i < tmp.
size(); i++)
566 unsigned offset= i * data.channels;
567 Color pixel=
Color( data.pixels[offset], data.pixels[offset+1], data.pixels[offset+2], (data.channels > 3) ? data.pixels[offset+3] : 255 ) / 255;
576 if(image.size() == 0)
579 ImageData tmp( image.width(), image.height(), 4 );
580 for(
unsigned i= 0; i < image.size(); i++)
582 Color pixel= clamp(image(i) * 255, 0, 255);
584 unsigned offset= i * tmp.channels;
585 tmp.pixels[offset]= pixel.r;
586 tmp.pixels[offset +1]= pixel.g;
587 tmp.pixels[offset +2]= pixel.b;
588 tmp.pixels[offset +3]= pixel.a;
representation d'une image.
unsigned width() const
renvoie la largeur de l'image.
unsigned size() const
renvoie le nombre de pixels 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.
ImageData make_image_data(const Image &image)
cree une image data à partir d'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)
Image make_image(const ImageData &data)
cree une image à partir d'une image data.
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
unsigned read_image_data_size(const char *filename)
renvoie la taille en octets de l'image data chargee. ou 0 si erreur.
representation d'une couleur (rgba) transparente ou opaque.
stockage temporaire des donnees d'une image.