28 #include <SFML/Graphics/ImageLoader.hpp>
35 #include <SOIL/SOIL.h>
45 void PngErrorHandler(png_structp Png, png_const_charp Message)
47 std::cerr <<
"Failed to write PNG image. Reason : " << Message << std::endl;
48 #if PNG_LIBPNG_VER_MAJOR >= 1 && PNG_LIBPNG_VER_MINOR >= 4
49 longjmp(png_jmpbuf(Png), 1);
51 longjmp(Png->jmpbuf, 1);
64 ImageLoader& ImageLoader::GetInstance()
66 static ImageLoader Instance;
75 ImageLoader::ImageLoader()
84 ImageLoader::~ImageLoader()
93 bool ImageLoader::LoadImageFromFile(
const std::string& Filename, std::vector<Color>& Pixels,
unsigned int& Width,
unsigned int& Height)
99 int ImgWidth, ImgHeight, ImgChannels;
100 unsigned char* PixelsPtr = SOIL_load_image(Filename.c_str(), &ImgWidth, &ImgHeight, &ImgChannels, SOIL_LOAD_RGBA);
109 Pixels.resize(Width * Height);
110 memcpy(&Pixels[0], PixelsPtr, Width * Height * 4);
113 SOIL_free_image_data(PixelsPtr);
120 std::cerr <<
"Failed to load image \"" << Filename <<
"\". Reason : " << SOIL_last_result() << std::endl;
130 bool ImageLoader::LoadImageFromMemory(
const char* Data, std::size_t SizeInBytes, std::vector<Color>& Pixels,
unsigned int& Width,
unsigned int& Height)
136 const unsigned char* Buffer =
reinterpret_cast<const unsigned char*
>(Data);
137 int Size =
static_cast<int>(SizeInBytes);
138 int ImgWidth, ImgHeight, ImgChannels;
139 unsigned char* PixelsPtr = SOIL_load_image_from_memory(Buffer, Size, &ImgWidth, &ImgHeight, &ImgChannels, SOIL_LOAD_RGBA);
148 Pixels.resize(Width * Height);
149 memcpy(&Pixels[0], PixelsPtr, Width * Height * 4);
152 SOIL_free_image_data(PixelsPtr);
159 std::cerr <<
"Failed to load image from memory. Reason : " << SOIL_last_result() << std::endl;
169 bool ImageLoader::SaveImageToFile(
const std::string& Filename,
const std::vector<Color>& Pixels,
unsigned int Width,
unsigned int Height)
173 if (Filename.size() > 3)
175 std::string Extension = Filename.substr(Filename.size() - 3);
176 if (Extension ==
"bmp" || Extension ==
"BMP") Type = SOIL_SAVE_TYPE_BMP;
177 else if (Extension ==
"tga" || Extension ==
"TGA") Type = SOIL_SAVE_TYPE_TGA;
178 else if (Extension ==
"dds" || Extension ==
"DDS") Type = SOIL_SAVE_TYPE_DDS;
181 else if (Extension ==
"png" || Extension ==
"PNG")
return WritePng(Filename, Pixels, Width, Height);
182 else if (Extension ==
"jpg" || Extension ==
"JPG")
return WriteJpg(Filename, Pixels, Width, Height);
188 std::cerr <<
"Failed to save image \"" << Filename <<
"\". Reason : this image format is not supported" << std::endl;
193 const unsigned char* PixelsPtr =
reinterpret_cast<const unsigned char*
>(&Pixels[0]);
194 if (!SOIL_save_image(Filename.c_str(), Type,
static_cast<int>(Width), static_cast<int>(Height), 4, PixelsPtr))
197 std::cerr <<
"Failed to save image \"" << Filename <<
"\". Reason : " << SOIL_last_result() << std::endl;
208 bool ImageLoader::WriteJpg(
const std::string& Filename,
const std::vector<Color>& Pixels,
unsigned int Width,
unsigned int Height)
211 FILE* File = fopen(Filename.c_str(),
"wb");
214 std::cerr <<
"Failed to save image file \"" << Filename <<
"\". Reason : cannot open file" << std::endl;
219 jpeg_compress_struct CompressInfo;
220 jpeg_error_mgr ErrorManager;
221 CompressInfo.err = jpeg_std_error(&ErrorManager);
224 jpeg_create_compress(&CompressInfo);
225 CompressInfo.image_width = Width;
226 CompressInfo.image_height = Height;
227 CompressInfo.input_components = 3;
228 CompressInfo.in_color_space = JCS_RGB;
229 jpeg_stdio_dest(&CompressInfo, File);
230 jpeg_set_defaults(&CompressInfo);
231 jpeg_set_quality(&CompressInfo, 90, TRUE);
234 std::vector<Uint8> PixelsBuffer(Width * Height * 3);
235 for (std::size_t i = 0; i < Pixels.size(); ++i)
237 PixelsBuffer[i * 3 + 0] = Pixels[i].r;
238 PixelsBuffer[i * 3 + 1] = Pixels[i].g;
239 PixelsBuffer[i * 3 + 2] = Pixels[i].b;
241 Uint8* PixelsPtr = &PixelsBuffer[0];
244 jpeg_start_compress(&CompressInfo, TRUE);
247 while (CompressInfo.next_scanline < CompressInfo.image_height)
249 JSAMPROW RowPointer = PixelsPtr + (CompressInfo.next_scanline * Width * 3);
250 jpeg_write_scanlines(&CompressInfo, &RowPointer, 1);
254 jpeg_finish_compress(&CompressInfo);
255 jpeg_destroy_compress(&CompressInfo);
267 bool ImageLoader::WritePng(
const std::string& Filename,
const std::vector<Color>& Pixels,
unsigned int Width,
unsigned int Height)
270 FILE* File = fopen(Filename.c_str(),
"wb");
273 std::cerr <<
"Failed to save image file \"" << Filename <<
"\". Reason : cannot open file" << std::endl;
278 png_structp Png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &PngErrorHandler, NULL);
282 std::cerr <<
"Failed to save image file \"" << Filename <<
"\". Reason : cannot allocate PNG write structure" << std::endl;
287 png_infop PngInfo = png_create_info_struct(Png);
291 png_destroy_write_struct(&Png, NULL);
292 std::cerr <<
"Failed to save image file \"" << Filename <<
"\". Reason : cannot allocate PNG info structure" << std::endl;
297 #if PNG_LIBPNG_VER_MAJOR >= 1 && PNG_LIBPNG_VER_MINOR >= 4
298 if (setjmp(png_jmpbuf(Png)))
300 if (setjmp(Png->jmpbuf))
303 png_destroy_write_struct(&Png, &PngInfo);
308 png_init_io(Png, File);
311 png_set_IHDR(Png, PngInfo, Width, Height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
314 png_write_info(Png, PngInfo);
317 png_byte* PixelsPtr = (png_byte*)&Pixels[0];
318 std::vector<png_byte*> RowPointers(Height);
319 for (
unsigned int i = 0; i < Height; ++i)
321 RowPointers[i] = PixelsPtr;
322 PixelsPtr += Width * 4;
326 png_set_rows(Png, PngInfo, &RowPointers[0]);
327 png_write_png(Png, PngInfo, PNG_TRANSFORM_IDENTITY, NULL);
330 png_write_end(Png, PngInfo);
333 png_destroy_write_struct(&Png, &PngInfo);