00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
00049
00050 SOFA_DECL_CLASS(ImagePNG)
00051
00052 #ifdef SOFA_HAVE_PNG
00053
00054
00055
00056
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
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
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
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 }
00261
00262 }
00263
00264 }
00265