ImageLoader.cpp
00001 00002 // 00003 // SFML - Simple and Fast Multimedia Library 00004 // Copyright (C) 2007-2009 Laurent Gomila ([email protected]) 00005 // 00006 // This software is provided 'as-is', without any express or implied warranty. 00007 // In no event will the authors be held liable for any damages arising from the use of this software. 00008 // 00009 // Permission is granted to anyone to use this software for any purpose, 00010 // including commercial applications, and to alter it and redistribute it freely, 00011 // subject to the following restrictions: 00012 // 00013 // 1. The origin of this software must not be misrepresented; 00014 // you must not claim that you wrote the original software. 00015 // If you use this software in a product, an acknowledgment 00016 // in the product documentation would be appreciated but is not required. 00017 // 00018 // 2. Altered source versions must be plainly marked as such, 00019 // and must not be misrepresented as being the original software. 00020 // 00021 // 3. This notice may not be removed or altered from any source distribution. 00022 // 00024 00026 // Headers 00028 #include <SFML/Graphics/ImageLoader.hpp> 00029 extern "C" 00030 { 00031 #include <SFML/Graphics/libjpeg/jpeglib.h> 00032 #include <SFML/Graphics/libjpeg/jerror.h> 00033 } 00034 #include <SFML/Graphics/libpng/png.h> 00035 #include <SFML/Graphics/SOIL/SOIL.h> 00036 #include <iostream> 00037 00038 00039 namespace 00040 { 00044 void PngErrorHandler(png_structp Png, png_const_charp Message) 00045 { 00046 std::cerr << "Failed to write PNG image. Reason : " << Message << std::endl; 00047 longjmp(Png->jmpbuf, 1); 00048 } 00049 } 00050 00051 00052 namespace sf 00053 { 00054 namespace priv 00055 { 00059 ImageLoader& ImageLoader::GetInstance() 00060 { 00061 static ImageLoader Instance; 00062 00063 return Instance; 00064 } 00065 00066 00070 ImageLoader::ImageLoader() 00071 { 00072 // Nothing to do 00073 } 00074 00075 00079 ImageLoader::~ImageLoader() 00080 { 00081 // Nothing to do 00082 } 00083 00084 00088 bool ImageLoader::LoadImageFromFile(const std::string& Filename, std::vector<Color>& Pixels, unsigned int& Width, unsigned int& Height) 00089 { 00090 // Clear the array (just in case) 00091 Pixels.clear(); 00092 00093 // Load the image and get a pointer to the pixels in memory 00094 int ImgWidth, ImgHeight, ImgChannels; 00095 unsigned char* PixelsPtr = SOIL_load_image(Filename.c_str(), &ImgWidth, &ImgHeight, &ImgChannels, SOIL_LOAD_RGBA); 00096 00097 if (PixelsPtr) 00098 { 00099 // Assign the image properties 00100 Width = ImgWidth; 00101 Height = ImgHeight; 00102 00103 // Copy the loaded pixels to the pixel buffer 00104 Pixels.resize(Width * Height); 00105 memcpy(&Pixels[0], PixelsPtr, Width * Height * 4); 00106 00107 // Free the loaded pixels (they are now in our own pixel buffer) 00108 SOIL_free_image_data(PixelsPtr); 00109 00110 return true; 00111 } 00112 else 00113 { 00114 // Error, failed to load the image 00115 std::cerr << "Failed to load image \"" << Filename << "\". Reason : " << SOIL_last_result() << std::endl; 00116 00117 return false; 00118 } 00119 } 00120 00121 00125 bool ImageLoader::LoadImageFromMemory(const char* Data, std::size_t SizeInBytes, std::vector<Color>& Pixels, unsigned int& Width, unsigned int& Height) 00126 { 00127 // Clear the array (just in case) 00128 Pixels.clear(); 00129 00130 // Load the image and get a pointer to the pixels in memory 00131 const unsigned char* Buffer = reinterpret_cast<const unsigned char*>(Data); 00132 int Size = static_cast<int>(SizeInBytes); 00133 int ImgWidth, ImgHeight, ImgChannels; 00134 unsigned char* PixelsPtr = SOIL_load_image_from_memory(Buffer, Size, &ImgWidth, &ImgHeight, &ImgChannels, SOIL_LOAD_RGBA); 00135 00136 if (PixelsPtr) 00137 { 00138 // Assign the image properties 00139 Width = ImgWidth; 00140 Height = ImgHeight; 00141 00142 // Copy the loaded pixels to the pixel buffer 00143 Pixels.resize(Width * Height); 00144 memcpy(&Pixels[0], PixelsPtr, Width * Height * 4); 00145 00146 // Free the loaded pixels (they are now in our own pixel buffer) 00147 SOIL_free_image_data(PixelsPtr); 00148 00149 return true; 00150 } 00151 else 00152 { 00153 // Error, failed to load the image 00154 std::cerr << "Failed to load image from memory. Reason : " << SOIL_last_result() << std::endl; 00155 00156 return false; 00157 } 00158 } 00159 00160 00164 bool ImageLoader::SaveImageToFile(const std::string& Filename, const std::vector<Color>& Pixels, unsigned int Width, unsigned int Height) 00165 { 00166 // Deduce the image type from its extension 00167 int Type = -1; 00168 if (Filename.size() > 3) 00169 { 00170 std::string Extension = Filename.substr(Filename.size() - 3); 00171 if (Extension == "bmp" || Extension == "BMP") Type = SOIL_SAVE_TYPE_BMP; 00172 else if (Extension == "tga" || Extension == "TGA") Type = SOIL_SAVE_TYPE_TGA; 00173 else if (Extension == "dds" || Extension == "DDS") Type = SOIL_SAVE_TYPE_DDS; 00174 00175 // Special handling for PNG and JPG -- not handled by SOIL 00176 else if (Extension == "png" || Extension == "PNG") return WritePng(Filename, Pixels, Width, Height); 00177 else if (Extension == "jpg" || Extension == "JPG") return WriteJpg(Filename, Pixels, Width, Height); 00178 } 00179 00180 if (Type == -1) 00181 { 00182 // Error, incompatible type 00183 std::cerr << "Failed to save image \"" << Filename << "\". Reason : this image format is not supported" << std::endl; 00184 return false; 00185 } 00186 00187 // Finally save the image 00188 const unsigned char* PixelsPtr = reinterpret_cast<const unsigned char*>(&Pixels[0]); 00189 if (!SOIL_save_image(Filename.c_str(), Type, static_cast<int>(Width), static_cast<int>(Height), 4, PixelsPtr)) 00190 { 00191 // Error, failed to save the image 00192 std::cerr << "Failed to save image \"" << Filename << "\". Reason : " << SOIL_last_result() << std::endl; 00193 return false; 00194 } 00195 00196 return true; 00197 } 00198 00199 00203 bool ImageLoader::WriteJpg(const std::string& Filename, const std::vector<Color>& Pixels, unsigned int Width, unsigned int Height) 00204 { 00205 // Open the file to write in 00206 FILE* File = fopen(Filename.c_str(), "wb"); 00207 if (!File) 00208 { 00209 std::cerr << "Failed to save image file \"" << Filename << "\". Reason : cannot open file" << std::endl; 00210 return false; 00211 } 00212 00213 // Initialize the error handler 00214 jpeg_compress_struct CompressInfo; 00215 jpeg_error_mgr ErrorManager; 00216 CompressInfo.err = jpeg_std_error(&ErrorManager); 00217 00218 // Initialize all the writing and compression infos 00219 jpeg_create_compress(&CompressInfo); 00220 CompressInfo.image_width = Width; 00221 CompressInfo.image_height = Height; 00222 CompressInfo.input_components = 3; 00223 CompressInfo.in_color_space = JCS_RGB; 00224 jpeg_stdio_dest(&CompressInfo, File); 00225 jpeg_set_defaults(&CompressInfo); 00226 jpeg_set_quality(&CompressInfo, 90, TRUE); 00227 00228 // Get rid of the aplha channel 00229 std::vector<Uint8> PixelsBuffer(Width * Height * 3); 00230 for (std::size_t i = 0; i < Pixels.size(); ++i) 00231 { 00232 PixelsBuffer[i * 3 + 0] = Pixels[i].r; 00233 PixelsBuffer[i * 3 + 1] = Pixels[i].g; 00234 PixelsBuffer[i * 3 + 2] = Pixels[i].b; 00235 } 00236 Uint8* PixelsPtr = &PixelsBuffer[0]; 00237 00238 // Start compression 00239 jpeg_start_compress(&CompressInfo, TRUE); 00240 00241 // Write each row of the image 00242 while (CompressInfo.next_scanline < CompressInfo.image_height) 00243 { 00244 JSAMPROW RowPointer = PixelsPtr + (CompressInfo.next_scanline * Width * 3); 00245 jpeg_write_scanlines(&CompressInfo, &RowPointer, 1); 00246 } 00247 00248 // Finish compression 00249 jpeg_finish_compress(&CompressInfo); 00250 jpeg_destroy_compress(&CompressInfo); 00251 00252 // Close the file 00253 fclose(File); 00254 00255 return true; 00256 } 00257 00258 00262 bool ImageLoader::WritePng(const std::string& Filename, const std::vector<Color>& Pixels, unsigned int Width, unsigned int Height) 00263 { 00264 // Open the file to write in 00265 FILE* File = fopen(Filename.c_str(), "wb"); 00266 if (!File) 00267 { 00268 std::cerr << "Failed to save image file \"" << Filename << "\". Reason : cannot open file" << std::endl; 00269 return false; 00270 } 00271 00272 // Create the main PNG structure 00273 png_structp Png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, &PngErrorHandler, NULL); 00274 if (!Png) 00275 { 00276 fclose(File); 00277 std::cerr << "Failed to save image file \"" << Filename << "\". Reason : cannot allocate PNG write structure" << std::endl; 00278 return false; 00279 } 00280 00281 // Initialize the image informations 00282 png_infop PngInfo = png_create_info_struct(Png); 00283 if (!PngInfo) 00284 { 00285 fclose(File); 00286 png_destroy_write_struct(&Png, NULL); 00287 std::cerr << "Failed to save image file \"" << Filename << "\". Reason : cannot allocate PNG info structure" << std::endl; 00288 return false; 00289 } 00290 00291 // For proper error handling... 00292 if (setjmp(Png->jmpbuf)) 00293 { 00294 png_destroy_write_struct(&Png, &PngInfo); 00295 return false; 00296 } 00297 00298 // Link the file to the PNG structure 00299 png_init_io(Png, File); 00300 00301 // Set the image informations 00302 png_set_IHDR(Png, PngInfo, Width, Height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 00303 00304 // Write the header 00305 png_write_info(Png, PngInfo); 00306 00307 // Get the pointers to the pixels rows into an array 00308 png_byte* PixelsPtr = (png_byte*)&Pixels[0]; 00309 std::vector<png_byte*> RowPointers(Height); 00310 for (unsigned int i = 0; i < Height; ++i) 00311 { 00312 RowPointers[i] = PixelsPtr; 00313 PixelsPtr += Width * 4; 00314 } 00315 00316 // Write pixels row by row 00317 png_set_rows(Png, PngInfo, &RowPointers[0]); 00318 png_write_png(Png, PngInfo, PNG_TRANSFORM_IDENTITY, NULL); 00319 00320 // Finish writing the file 00321 png_write_end(Png, PngInfo); 00322 00323 // Cleanup resources 00324 png_destroy_write_struct(&Png, &PngInfo); 00325 fclose(File); 00326 00327 return true; 00328 } 00329 00330 } // namespace priv 00331 00332 } // namespace sf
:: Copyright © 2007-2008 Laurent Gomila, all rights reserved :: Documentation generated by doxygen 1.5.2 ::