ImagePNG.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #include <sofa/helper/io/ImagePNG.h>
00028 #include <sofa/helper/system/FileRepository.h>
00029 #include <iostream>
00030 
00031 #ifdef SOFA_HAVE_PNG
00032 #include <png.h>
00033 #ifdef _MSC_VER
00034 #pragma comment(lib,"libpng.lib")
00035 #pragma comment(lib,"zlib.lib")
00036 #endif
00037 #endif
00038 
00039 namespace sofa
00040 {
00041 
00042 namespace helper
00043 {
00044 
00045 namespace io
00046 {
00047 
00048 //using namespace sofa::defaulttype;
00049 
00050 SOFA_DECL_CLASS(ImagePNG)
00051 
00052 #ifdef SOFA_HAVE_PNG
00053 
00054 // Set the compression level. The valid values for "COMPRESSION_LEVEL" range from [0,9]
00055 // The value 0 implies no compression and 9 implies maximal compression
00056 // The value -1 implies default compression (level 6)
00057 
00058 Creator<Image::FactoryImage,ImagePNG> ImagePNGClass("png");
00059 
00060 bool ImagePNG::load(std::string filename)
00061 {
00062     if (!sofa::helper::system::DataRepository.findFile(filename))
00063     {
00064     std::cerr << "File " << filename << " not found " << std::endl;
00065     return false;
00066     }
00067     FILE *file;
00068     /* make sure the file is there and open it read-only (binary) */
00069     if ((file = fopen(filename.c_str(), "rb")) == NULL)
00070     {
00071         std::cerr << "File not found : " << filename << std::endl;
00072         return false;
00073     }
00074     
00075     png_structp PNG_reader = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00076     if (PNG_reader == NULL)
00077     {
00078         std::cerr << "png_create_read_struct failed for file "<< filename << std::endl;
00079         fclose(file);
00080         return false;
00081     }
00082     
00083     png_infop PNG_info = png_create_info_struct(PNG_reader);
00084     if (PNG_info == NULL)
00085     {
00086         std::cerr << "png_create_info_struct failed for file " << filename << std::endl;
00087         png_destroy_read_struct(&PNG_reader, NULL, NULL);
00088         fclose(file);
00089         return false;
00090     }
00091     
00092     png_infop PNG_end_info = png_create_info_struct(PNG_reader);
00093     if (PNG_end_info == NULL)
00094     {
00095         std::cerr << "png_create_info_struct failed for file " << filename << std::endl;
00096         png_destroy_read_struct(&PNG_reader, &PNG_info, NULL);
00097         fclose(file);
00098         return false;
00099     }
00100     
00101     if (setjmp(png_jmpbuf(PNG_reader)))
00102     {
00103         std::cerr << "Loading failed for PNG file " << filename << std::endl;
00104         png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
00105         fclose(file);
00106         return false;
00107     }
00108     
00109     png_init_io(PNG_reader, file);
00110     
00111     png_read_info(PNG_reader, PNG_info);
00112     
00113     png_uint_32 width, height;
00114     width = png_get_image_width(PNG_reader, PNG_info);
00115     height = png_get_image_height(PNG_reader, PNG_info);
00116     
00117     png_uint_32 bit_depth, channels, color_type;
00118     bit_depth = png_get_bit_depth(PNG_reader, PNG_info);
00119     channels = png_get_channels(PNG_reader, PNG_info);
00120     color_type = png_get_color_type(PNG_reader, PNG_info);
00121     
00122     std::cout << "PNG image "<<filename<<": "<<width<<"x"<<height<<"x"<<bit_depth*channels<<std::endl;
00123     bool changed = false;
00124     if (color_type == PNG_COLOR_TYPE_PALETTE)
00125     {
00126         png_set_palette_to_rgb(PNG_reader);
00127         changed = true;
00128     }
00129     
00130     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
00131     {
00132         png_set_gray_1_2_4_to_8(PNG_reader);
00133         changed = true;
00134     }
00135     
00136     if (bit_depth == 16)
00137     {
00138         png_set_strip_16(PNG_reader);
00139         changed = true;
00140     }
00141     if (changed)
00142     {
00143         png_read_update_info(PNG_reader, PNG_info);
00144         bit_depth = png_get_bit_depth(PNG_reader, PNG_info);
00145         channels = png_get_channels(PNG_reader, PNG_info);
00146         color_type = png_get_color_type(PNG_reader, PNG_info);
00147         std::cout << "Converted PNG image "<<filename<<": "<<width<<"x"<<height<<"x"<<bit_depth*channels<<std::endl;
00148     }
00149     init(width, height, channels*bit_depth);
00150     png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*));
00151     
00152     for (png_uint_32 row = 0; row < height; ++row)
00153         PNG_rows[height - 1 - row] = getData()+row*getLineSize();
00154     
00155     png_read_image(PNG_reader, PNG_rows);
00156     
00157     free(PNG_rows);
00158     
00159     png_read_end(PNG_reader, PNG_end_info);
00160     
00161     png_destroy_read_struct(&PNG_reader, &PNG_info, &PNG_end_info);
00162     fclose(file);
00163     
00164     return true;
00165 }
00166 
00167 bool ImagePNG::save(std::string filename, int compression_level)
00168 {
00169     
00170     FILE *file;
00171     std::cout << "Writing PNG file " << filename << std::endl;
00172     /* make sure the file is there and open it read-only (binary) */
00173     if ((file = fopen(filename.c_str(), "wb")) == NULL)
00174     {
00175         std::cerr << "File write access failed : " << filename << std::endl;
00176         return false;
00177     }
00178     
00179     png_structp PNG_writer = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00180     if (PNG_writer == NULL)
00181     {
00182         std::cerr << "png_create_write_struct failed for file "<< filename << std::endl;
00183         fclose(file);
00184         return false;
00185     }
00186     
00187     png_infop PNG_info = png_create_info_struct(PNG_writer);
00188     if (PNG_info == NULL)
00189     {
00190         std::cerr << "png_create_info_struct failed for file " << filename << std::endl;
00191         png_destroy_write_struct(&PNG_writer, NULL);
00192         fclose(file);
00193         return false;
00194     }
00195     
00196     if (setjmp(png_jmpbuf(PNG_writer)))
00197     {
00198         std::cerr << "Writing failed for PNG file " << filename << std::endl;
00199         png_destroy_write_struct(&PNG_writer, &PNG_info);
00200         fclose(file);
00201         return false;
00202     }
00203     
00204     png_init_io(PNG_writer, file);
00205     
00206     png_uint_32 width, height;
00207     png_uint_32 bit_depth, channels, color_type;
00208     
00209     width = getWidth();
00210     height = getHeight();
00211     
00212     bit_depth = (getNbBits()<8)?getNbBits():8;
00213     channels = (getNbBits()+7)/8;
00214     if (channels == 1)
00215         color_type = PNG_COLOR_TYPE_GRAY;
00216     else if (channels == 2)
00217         color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
00218     else if (channels == 3)
00219         color_type = PNG_COLOR_TYPE_RGB;
00220     else if (channels == 4)
00221         color_type = PNG_COLOR_TYPE_RGB_ALPHA;
00222     else
00223     {
00224         std::cerr << "Unsupported bitdepth "<<getNbBits()<<" to write to PNG file "<<filename<<std::endl;
00225         png_destroy_write_struct(&PNG_writer, &PNG_info);
00226         fclose(file);
00227         return false;
00228     }
00229     std::cout << "PNG image "<<filename<<": "<<width<<"x"<<height<<"x"<<bit_depth*channels<<std::endl;
00230     png_set_IHDR(PNG_writer, PNG_info, width, height,
00231                  bit_depth, color_type, PNG_INTERLACE_NONE,
00232                  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00233     /* set the zlib compression level */
00234     if (compression_level!=-1)
00235     {
00236         if (compression_level>=0 && compression_level<=9)
00237             png_set_compression_level(PNG_writer, compression_level);
00238         else
00239             std::cerr << "ERROR: compression level must be a value between 0 and 9" << std::endl;
00240     }
00241     
00242     png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*));
00243     
00244     for (png_uint_32 row = 0; row < height; ++row)
00245         PNG_rows[height - 1 - row] = getData()+row*getLineSize();
00246     
00247     png_set_rows(PNG_writer, PNG_info, PNG_rows);
00248 
00249     png_write_png(PNG_writer, PNG_info, PNG_TRANSFORM_IDENTITY, NULL);
00250 
00251     free(PNG_rows);
00252     
00253     png_destroy_write_struct(&PNG_writer, &PNG_info);
00254     fclose(file);
00255     return true;
00256 }
00257 
00258 #endif
00259 
00260 } // namespace io
00261 
00262 } // namespace helper
00263 
00264 } // namespace sofa
00265 

Generated on Sun Nov 23 02:29:30 2008 for Sofa by  doxygen 1.5.7.1