libpng_wrapper.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2011, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034 
00035  * Author: Julius Kammerl (julius@kammerl.de)
00036  */
00037 
00038 #include <pcl/compression/libpng_wrapper.h>
00039 
00040 #include <png.h>
00041 #include <zlib.h>
00042 
00043 #include <vector>
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046 #include <stdint.h>
00047 #include <assert.h>
00048 
00049 
00050 // user defined I/O callback methods for libPNG
00051 namespace 
00052 {
00054   void 
00055   user_read_data (png_structp png_ptr, png_bytep data, png_size_t length)
00056   {
00057     uint8_t** input_pointer = reinterpret_cast<uint8_t**>(png_get_io_ptr (png_ptr));
00058 
00059     memcpy (data, *input_pointer, sizeof (uint8_t) * length);
00060     (*input_pointer) += length;
00061   }
00062 
00064   void 
00065   user_write_data (png_structp png_ptr,  png_bytep data, png_size_t length)
00066   {
00067     std::vector<uint8_t>* pngVec = reinterpret_cast<std::vector<uint8_t>*>(png_get_io_ptr (png_ptr));
00068     std::copy (data, data + length, std::back_inserter (*pngVec));
00069   }
00070 
00072   void 
00073   user_flush_data (png_structp)
00074   {
00075   }
00076 }
00077 
00078 namespace pcl
00079 {
00080   namespace io
00081   {
00083     template<typename T> void
00084     encodeImageToPNG (typename std::vector<T>& image_arg,
00085                       size_t width_arg,
00086                       size_t height_arg,
00087                       int image_format_arg,
00088                       typename std::vector<uint8_t>& pngData_arg,
00089                       int png_level_arg)
00090     {
00091       png_structp png_ptr;
00092       png_infop info_ptr;
00093       volatile int channels;
00094 
00095       if (image_arg.size () ==0)
00096         return;
00097 
00098       // Get amount of channels
00099       switch (image_format_arg)
00100        {
00101          case PNG_COLOR_TYPE_GRAY:
00102            channels = 1;
00103            break;
00104          case PNG_COLOR_TYPE_GRAY_ALPHA:
00105            channels = 2;
00106            break;
00107          case PNG_COLOR_TYPE_RGB:
00108            channels = 3;
00109            break;
00110          case PNG_COLOR_TYPE_RGB_ALPHA:
00111            channels = 4;
00112            break;
00113          default:
00114            channels = 0;
00115            break;
00116        }
00117 
00118       // Ensure valid input array
00119       assert (image_arg.size () == width_arg*height_arg*channels);
00120 
00121       // Initialize write structure
00122       png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0);
00123       assert (png_ptr && "creating png_create_write_structpng_create_write_struct failed");
00124 
00125       // Initialize info structure
00126       info_ptr = png_create_info_struct (png_ptr);
00127       assert (info_ptr && "Could not allocate info struct");
00128 
00129       // Setup Exception handling
00130       setjmp(png_jmpbuf(png_ptr));
00131 
00132       // reserve memory for output data (300kB)
00133       pngData_arg.clear ();
00134       pngData_arg.reserve (300 * 1024);
00135 
00136       // Define I/O methods
00137       png_set_write_fn (png_ptr, reinterpret_cast<void*> (&pngData_arg), 
00138                         user_write_data, user_flush_data);
00139 
00140       // Define zlib compression level
00141       if (png_level_arg >= 0)
00142       {
00143         png_set_compression_level (png_ptr, png_level_arg);
00144       }
00145       else
00146       {
00147         png_set_compression_level (png_ptr, Z_DEFAULT_COMPRESSION);
00148       }
00149 
00150       // Write header
00151       png_set_IHDR (png_ptr, info_ptr,
00152                     static_cast<png_uint_32> (width_arg), static_cast<png_uint_32> (height_arg),
00153                     sizeof(T) * 8,
00154                     image_format_arg, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
00155                     PNG_FILTER_TYPE_DEFAULT);
00156 
00157       png_write_info (png_ptr, info_ptr);
00158 
00159       // Write image data
00160       size_t y;
00161       for (y = 0; y < height_arg; y++)
00162       {
00163         png_write_row (png_ptr, reinterpret_cast<png_bytep> (&image_arg[y * width_arg * channels]));
00164       }
00165 
00166       // End write
00167       png_write_end (png_ptr, 0);
00168 
00169       if (info_ptr)
00170         png_free_data (png_ptr, info_ptr, PNG_FREE_ALL, -1);
00171       if (png_ptr)
00172         png_destroy_write_struct (&png_ptr, 0);
00173     }
00174     
00176     template<typename T> void
00177     decodePNGImage (typename std::vector<uint8_t>& pngData_arg,
00178                     typename std::vector<T>& imageData_arg,
00179                     size_t& width_arg,
00180                     size_t& height_arg,
00181                     unsigned int& channels_arg)
00182     {
00183       int y;
00184       png_structp png_ptr;
00185       png_infop info_ptr;
00186       png_uint_32 png_width;
00187       png_uint_32 png_height;
00188       int png_bit_depth, png_color_type, png_interlace_type;
00189 
00190       png_bytep * row_pointers;
00191 
00192       if (pngData_arg.size () == 0)
00193         return;
00194 
00195       png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0);
00196       assert (png_ptr && "creating png_create_write_structpng_create_write_struct failed");
00197 
00198       // Initialize info structure
00199       info_ptr = png_create_info_struct (png_ptr);
00200       assert(info_ptr && "Could not allocate info struct");
00201 
00202       // Setup Exception handling
00203       setjmp (png_jmpbuf(png_ptr));
00204 
00205       uint8_t* input_pointer = &pngData_arg[0];
00206       png_set_read_fn (png_ptr, reinterpret_cast<void*> (&input_pointer), user_read_data);
00207 
00208       png_read_info (png_ptr, info_ptr);
00209 
00210       png_get_IHDR (png_ptr, info_ptr, &png_width, &png_height, &png_bit_depth,
00211           &png_color_type, &png_interlace_type, NULL, NULL);
00212 
00213       // ensure a color bit depth of 8
00214       assert(png_bit_depth==sizeof(T)*8);
00215 
00216       unsigned int png_channels;
00217       switch (png_color_type)
00218       {
00219         case PNG_COLOR_TYPE_GRAY:
00220           png_channels = 1;
00221           break;
00222         case PNG_COLOR_TYPE_GRAY_ALPHA:
00223           png_channels = 2;
00224           break;
00225         case PNG_COLOR_TYPE_RGB:
00226           png_channels = 3;
00227           break;
00228         case PNG_COLOR_TYPE_RGB_ALPHA:
00229           png_channels = 4;
00230           break;
00231         default:
00232           png_channels = 0;
00233           break;
00234       }
00235 
00236       width_arg = png_width;
00237       height_arg = png_height;
00238       channels_arg = png_channels;
00239 
00240       imageData_arg.clear ();
00241       imageData_arg.resize (png_height * png_width * png_channels);
00242 
00243       row_pointers = reinterpret_cast<png_bytep*> (malloc (sizeof(png_bytep) * png_height));
00244 
00245       for (y = 0; y < png_height; y++)
00246         row_pointers[y] = reinterpret_cast<png_byte*> (&imageData_arg[y * png_width * png_channels]);
00247 
00248       png_read_image (png_ptr, row_pointers);
00249 
00250       if (info_ptr)
00251         png_free_data (png_ptr, info_ptr, PNG_FREE_ALL, -1);
00252       if (png_ptr)
00253         png_destroy_read_struct (&png_ptr, 0, 0);
00254       if (row_pointers)
00255         free (row_pointers);
00256     }
00257   } // namespace io
00258 } // namespace pcl
00259 
00260 
00262 void
00263 pcl::io::encodeMonoImageToPNG (std::vector<uint8_t>& image_arg,
00264                                size_t width_arg,
00265                                size_t height_arg,
00266                                std::vector<uint8_t>& pngData_arg,
00267                                int png_level_arg)
00268 {
00269   encodeImageToPNG<uint8_t> (image_arg, 
00270                              static_cast<png_uint_32> (width_arg), static_cast<png_uint_32> (height_arg),
00271                              PNG_COLOR_TYPE_GRAY, pngData_arg, png_level_arg);
00272 }
00273 
00275 void
00276 pcl::io::encodeMonoImageToPNG (std::vector<uint16_t>& image_arg,
00277                                size_t width_arg,
00278                                size_t height_arg,
00279                                std::vector<uint8_t>& pngData_arg,
00280                                int png_level_arg)
00281 {
00282   encodeImageToPNG<uint16_t> (image_arg,
00283                               static_cast<png_uint_32> (width_arg), static_cast<png_uint_32> (height_arg),
00284                               PNG_COLOR_TYPE_GRAY, pngData_arg, png_level_arg);
00285 }
00286 
00288 void
00289 pcl::io::encodeRGBImageToPNG (std::vector<uint8_t>& image_arg,
00290                               size_t width_arg,
00291                               size_t height_arg,
00292                               std::vector<uint8_t>& pngData_arg,
00293                               int png_level_arg)
00294 {
00295   encodeImageToPNG<uint8_t>(image_arg,
00296                             static_cast<png_uint_32> (width_arg), static_cast<png_uint_32> (height_arg),
00297                             PNG_COLOR_TYPE_RGB, pngData_arg, png_level_arg);
00298 }
00299 
00301 void
00302 pcl::io::encodeRGBImageToPNG (std::vector<uint16_t>& image_arg,
00303                               size_t width_arg,
00304                               size_t height_arg,
00305                               std::vector<uint8_t>& pngData_arg,
00306                               int png_level_arg)
00307 {
00308   encodeImageToPNG<uint16_t>(image_arg,
00309                              static_cast<png_uint_32> (width_arg), static_cast<png_uint_32> (height_arg),
00310                              PNG_COLOR_TYPE_RGB, pngData_arg, png_level_arg);
00311 }
00312 
00314 void
00315 pcl::io::decodePNGToImage (std::vector<uint8_t>& pngData_arg,
00316                            std::vector<uint8_t>& imageData_arg,
00317                            size_t& width_arg,
00318                            size_t& height_arg,
00319                            unsigned int& channels_arg)
00320 {
00321   decodePNGImage<uint8_t> (pngData_arg, imageData_arg, width_arg, height_arg, channels_arg);
00322 }
00323 
00325 void
00326 pcl::io::decodePNGToImage (std::vector<uint8_t>& pngData_arg,
00327                            std::vector<uint16_t>& imageData_arg,
00328                            size_t& width_arg,
00329                            size_t& height_arg,
00330                            unsigned int& channels_arg)
00331 {
00332   decodePNGImage<uint16_t> (pngData_arg, imageData_arg, width_arg, height_arg, channels_arg);
00333 }
00334 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:25:13