- Main Page
- Namespaces
- Classes
- Files

- File List

# ImageLoader.cpp

    00001
    00002 //
    00003 // SFML - Simple and Fast Multimedia Library
    00004 // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
    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 ::