SLIP  1.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PngWriter.hpp
Go to the documentation of this file.
1 
10 #ifndef PNGWRITER_HPP_
11 #define PNGWRITER_HPP_
12 
13 #include <iostream>
14 #include <sstream>
15 
16 #include "PngDef.hpp"
17 #include "error.hpp"
18 #include "ContainerWriter.hpp"
19 
20 
21 namespace slip {
22 
23 template <typename T>
25 {
26  template <typename T1> // T1 models type statically convertible to T
27  T operator()(const T1& x) const { return static_cast<T>(x); }
28 };
29 
42 template<class Container2d, typename T, std::size_t Nb_components>
43 class PngWriter: public ContainerWriter<Container2d, T>{
44 public:
45 
46  typedef Container2d container_type;
47  typedef T value_type;
49 
54 
59  :base(),outfile(NULL),png_ptr(NULL),info_ptr(NULL),row_stride(0),
60  finished(0),total_nb_row(0),initialized(false),output_image_width_(0),
61  output_image_height_(0)
62  {}
63 
72  PngWriter(std::string output_filename, std::size_t output_image_width, std::size_t output_image_height)
73  :base(output_filename),outfile(NULL),png_ptr(NULL),info_ptr(NULL),row_stride(0),finished(0),total_nb_row(0),
74  initialized(false),output_image_width_(output_image_width),output_image_height_(output_image_height){
75  initialize();
76  }
77 
81  virtual ~PngWriter(){
82  release();
83  }
91  void initialize(std::size_t output_image_width, std::size_t output_image_height);
92 
93 
97  void release();
98 
109  int write(const container_type & data);
110 
111 private:
112 
113  FILE *outfile;
114  png_structp png_ptr;
115  png_infop info_ptr;
116  //png_colorp palette;
117 
118  int row_stride;
119  bool finished;
120  std::size_t total_nb_row;
121  bool initialized;
122  std::size_t output_image_width_;
123  std::size_t output_image_height_;
124 
125  void initialize();
126 };
127 
128 }
130 namespace slip {
131 
132 template<class Container2d, typename T, std::size_t Nb_components>
133 inline
134 void PngWriter<Container2d,T,Nb_components>::initialize(std::size_t output_image_width,
135  std::size_t output_image_height){
136  output_image_width_ = output_image_width;
137  output_image_height_ = output_image_height;
138  initialize();
139 }
140 
141 
142 template<class Container2d, typename T, std::size_t Nb_components>
143 inline
145  if(!initialized){
146  if (Nb_components != 1 && Nb_components != 3){
147  std::ostringstream err;
148  err << FILE_WRITE_ERROR << this->output_filename_ << " | Nb_components should be 1 or 3.";
149  slip::slip_exception exc(std::string("slip"), std::string("PngWriter::initialize()"), err.str());
150  throw (exc);
151  }
152  /* Open the file */
153  if ((outfile = fopen(this->output_filename_.c_str(), "wb")) == NULL) {
154  std::ostringstream err;
155  err << FILE_OPEN_ERROR << this->output_filename_;
156  slip::slip_exception exc(std::string("slip"), std::string("PngWriter::initialize()"), err.str());
157  throw (exc);
158  }
159 
160  /* Create and initialize the png_struct with the desired error handler
161  * functions. If you want to use the default stderr and longjump method,
162  * you can supply NULL for the last three parameters. We also check that
163  * the library version is compatible with the one used at compile time,
164  * in case we are using dynamically linked libraries. REQUIRED.
165  */
166  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
167 
168  if (png_ptr == NULL)
169  {
170  fclose(outfile);
171  std::ostringstream err;
172  err << FILE_WRITE_ERROR << this->output_filename_ << " | Error in png_ptr initialization.";
173  slip::slip_exception exc(std::string("slip"), std::string("PngWriter::initialize()"), err.str());
174  throw (exc);
175  }
176 
177  /* Allocate/initialize the image information data. REQUIRED */
178  info_ptr = png_create_info_struct(png_ptr);
179  if (info_ptr == NULL)
180  {
181  png_destroy_write_struct(&png_ptr, png_infopp_NULL);
182  fclose(outfile);
183  std::ostringstream err;
184  err << FILE_WRITE_ERROR << this->output_filename_ << " | Error in info_ptr allocation.";
185  slip::slip_exception exc(std::string("slip"), std::string("PngWriter::initialize()"), err.str());
186  throw (exc);
187  }
188 
189  /* Set error handling. REQUIRED if you aren't supplying your own
190  * error handling functions in the png_create_write_struct() call.
191  */
192  if (setjmp(png_jmpbuf(png_ptr)))
193  {
194  /* If we get here, we had a problem writing the file */
195  png_destroy_write_struct(&png_ptr, &info_ptr);
196  fclose(outfile);
197  std::ostringstream err;
198  err << FILE_WRITE_ERROR << this->output_filename_ << " | PNG code has signaled an error.";
199  slip::slip_exception exc(std::string("slip"), std::string("PngWriter::initialize()"), err.str());
200  throw (exc);
201  }
202 
203  /* Set up the output control if you are using standard C streams */
204  png_init_io(png_ptr, outfile);
205 
206  /* Set the image information here. Width and height are up to 2^31,
207  * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
208  * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
209  * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
210  * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
211  * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
212  * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
213  */
214  if (Nb_components == 1){
215  png_set_IHDR(png_ptr, info_ptr, output_image_width_, output_image_height_,
216  8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
217  }else{
218  png_set_IHDR(png_ptr, info_ptr, output_image_width_, output_image_height_,
219  8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
220  }
221 
222  /* Write the file header information. REQUIRED */
223  png_write_info(png_ptr, info_ptr);
224 
225 
226  row_stride = output_image_width_ * Nb_components;
227  initialized = true;
228  }
229 }
230 
231 
232 
233 template<class Container2d, typename T, std::size_t Nb_components>
234 inline
236  if(!initialized){
237  std::ostringstream err;
238  err << FILE_WRITE_ERROR << this->output_filename_ << " | The writer to be initialized before writing.";
239  slip::slip_exception exc(std::string("slip"), std::string("PngWriter::write()"), err.str());
240  throw (exc);
241  }
242  if (finished){
243  return 0;
244  }
245 
246  total_nb_row += data.height();
247 
248  if(output_image_height_ < total_nb_row){
249  std::ostringstream err;
250  err << FILE_WRITE_ERROR << this->output_filename_ << " | Allocation problem during png writing.";
251  slip::slip_exception exc(std::string("slip"), std::string("PngWriter::write()"), err.str());
252  throw (exc);
253  }
254 
255 
256  png_bytep row_pointer[1];
257 
258  if (static_cast<png_uint_32>(output_image_height_) > PNG_UINT_32_MAX/png_sizeof(png_bytep))
259  png_error (png_ptr, "Image is too tall to process in memory");
260 
261  for (std::size_t j=0; j<data.height(); ++j){
262  row_pointer[0] = new unsigned char[row_stride];
263  const T * data_ptr_j = reinterpret_cast<const T *>(data[j]);
264  std::transform(data_ptr_j, data_ptr_j + row_stride,
265  row_pointer[0], png_static_cast_func<unsigned char>());
266  png_write_rows(png_ptr, &row_pointer[0], 1);
267  delete[] row_pointer[0];
268  }
269 
270  if (total_nb_row == output_image_height_){
271  png_write_end(png_ptr, info_ptr);
272  finished = true;
273  }
274 
275  return (!finished);
276 }
277 
278 template<class Container2d, typename T, std::size_t Nb_components>
279 inline
281  if(initialized){
282  /* Clean up after the write, and free any memory allocated */
283  png_destroy_write_struct(&png_ptr, &info_ptr);
284 
285  /* Close the file */
286  if (outfile != NULL)
287  fclose(outfile);
288 
289  row_stride = 0;
290  finished = false;
291  total_nb_row = 0;
292  output_image_width_ = 0;
293  output_image_height_ = 0;
294  initialized = false;
295  }
296 }
297 
298 }
300 #endif /* PNGWRITER_HPP_ */
void initialize(std::size_t output_image_width, std::size_t output_image_height)
initialized the writing process. Has to be called before the first write() call of a given image...
Definition: PngWriter.hpp:134
PngWriter(std::string output_filename, std::size_t output_image_width, std::size_t output_image_height)
Definition: PngWriter.hpp:72
const std::string FILE_WRITE_ERROR
Definition: error.hpp:91
standard exception extension name have been changed to eliminate conflicts with QT ...
Definition: error.hpp:106
Contains the container writer base class.
Container2d container_type
Definition: PngWriter.hpp:46
T operator()(const T1 &x) const
Definition: PngWriter.hpp:27
Some definitions specific to libpng.
const std::string FILE_OPEN_ERROR
Definition: error.hpp:82
void release()
release the writing process. Has to be called when an image has been fully written.
Definition: PngWriter.hpp:280
PngWriter is the png image writer.
Definition: PngWriter.hpp:43
virtual ~PngWriter()
Definition: PngWriter.hpp:81
ContainerWriter< Container2d, T > base
Definition: PngWriter.hpp:48
Provides SLIP error messages.
ContainerWriter is the base class of the writer classes. All the writers are working the same way: ...
int write(const container_type &data)
write function. This function write the data within the output file after the previous one...
Definition: PngWriter.hpp:235