SLIP  1.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JpegReader.hpp
Go to the documentation of this file.
1 
10 #ifndef JPEGREADER_HPP_
11 #define JPEGREADER_HPP_
12 
13 #include <iostream>
14 #include <sstream>
15 
16 #include "JpegDef.hpp"
17 #include "error.hpp"
18 #include "ContainerReader.hpp"
19 
20 
21 
22 
23 namespace slip {
24 
44 template<class Container2d, typename T, std::size_t Nb_components, std::size_t Nb_block>
45 class JpegReader: public ContainerReader<Container2d,T,Nb_block> {
46 public:
47  typedef Container2d container_type;
48  typedef T value_type;
50 
55 
60  :base(),cinfo(),jerr(),infile(NULL),buffer(),row_stride(0),
61  block_ind(1),block_size(0),last_block_size(0),last_it(0),finished(0),initialized(0){}
62 
68  JpegReader(std::string data_filename)
69  :base(data_filename),cinfo(),jerr(),infile(NULL),buffer(),row_stride(0),
70  block_ind(1),block_size(0),last_block_size(0),last_it(0),finished(0),initialized(0)
71  { initialize();}
72 
73 
78  virtual ~JpegReader(){
79  if(initialized){
80  release();
81  }
82  }
89  void initialize();
90 
95  void release();
96 
106  int read(Container2d & in);
107 
108 private:
109  jpeg_decompress_struct cinfo; /* JPEG decompression parameters and pointers to working space */
110  my_error_mgr jerr; /* We use our private extension JPEG error handler. */
111  FILE * infile; /* source file */
112  JSAMPARRAY buffer; /* Output row buffer */
113  int row_stride; /* physical row width in output buffer */
114  int block_ind;/*current read block indice*/
115  int block_size;/*block size*/
116  int last_block_size;/*last block size*/
117  bool last_it;/*indicates that the current read is the last.*/
118  bool finished;/*indicates that the last read has been done and no more data are available.*/
119  bool initialized;/*indicates that the reader has been initialized*/
120 };
121 
122 }
124 namespace slip {
125 
126 template<class Container2d, typename T, std::size_t Nb_components, std::size_t Nb_block>
127 inline
129  if (!initialized){
130  if (Nb_components != 1 && Nb_components != 3){
131  std::ostringstream err;
132  err << FILE_READ_ERROR << this->data_filename_ << " | Nb_components should be 1 or 3.";
133  slip::slip_exception exc(std::string("slip"), std::string("JpegReader::initialize()"), err.str());
134  throw (exc);
135  }
136 
137  /* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
138  * requires it in order to read binary files. */
139  if ((infile = fopen(this->data_filename_.c_str(), "rb")) == NULL) {
140  std::ostringstream err;
141  err << FILE_OPEN_ERROR << this->data_filename_;
142  slip::slip_exception exc(std::string("slip"), std::string("JpegReader::initialize()"), err.str());
143  throw (exc);
144  }
145  /* Step 1: allocate and initialize JPEG decompression object */
146 
147  /* We set up the normal JPEG error routines, then override error_exit. */
148  cinfo.err = jpeg_std_error(&jerr.pub);
149  jerr.pub.error_exit = my_error_exit;
150 
151  /* Establish the setjmp return context for my_error_exit to use. */
152  if (setjmp(jerr.setjmp_buffer)) {
153  /* If we get here, the JPEG code has signaled an error.
154  * We need to clean up the JPEG object, close the input file, and throw an exception
155  */
156  char buffer[JMSG_LENGTH_MAX];
157  /* Create the message */
158  (*cinfo.err->format_message) (reinterpret_cast<j_common_ptr>(&cinfo), buffer);
159  jpeg_destroy_decompress(&cinfo);
160  fclose(infile);
161  std::ostringstream err;
162  err << FILE_READ_ERROR << this->data_filename_ << " | JPEG library has signaled the error : "
163  << buffer;
164  slip::slip_exception exc(std::string("slip"), std::string("JpegReader::initialize()"), err.str());
165  throw (exc);
166  }
167  /* Now we can initialize the JPEG decompression object. */
168  jpeg_create_decompress(&cinfo);
169 
170  /* Step 2: specify data source (eg, a file) */
171 
172  slip_jpeg_stdio_src(&cinfo, infile);
173 
174  /* Step 3: read file parameters with jpeg_read_header() */
175 
176  jpeg_read_header(&cinfo, TRUE);
177 
178  /* Step 4: set parameters for decompression */
179 
180  /* Here we don't need to change any of the defaults set by
181  * jpeg_read_header(), so we do nothing here.
182  */
183 
184  /* Step 5: Start decompressor */
185 
186  jpeg_start_decompress(&cinfo);
187 
188  /* Test the number of components and allocate the input container */
189  if(cinfo.num_components != Nb_components){
190  fclose(infile);
191  std::ostringstream err;
192  err << FILE_READ_ERROR << this->data_filename_ << " | Nb_components does not match.";
193  slip::slip_exception exc(std::string("slip"), std::string("JpegReader::initialize()"), err.str());
194  throw(exc);
195  }
196 
197  /* JSAMPLEs per row in output buffer */
198  row_stride = cinfo.output_width * cinfo.output_components;
199  /* Make a one-row-high sample array that will go away when done with image */
200  buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
201  block_size = cinfo.output_height / Nb_block;
202  last_block_size = cinfo.output_height % Nb_block;
203  last_block_size = (last_block_size == 0 ? block_size : block_size+last_block_size);
204  last_it = (Nb_block == 1);
205  finished = (last_it && last_block_size == 0);
206  initialized = true;
207  }
208 }
209 
210 template<class Container2d, typename T, std::size_t Nb_components, std::size_t Nb_block>
212  if(!initialized){
213  std::ostringstream err;
214  err << FILE_READ_ERROR << this->data_filename_ << " | The reader needs to be initialized before reading.";
215  slip::slip_exception exc(std::string("slip"), std::string("JpegReader::read()"), err.str());
216  throw (exc);
217  }
218  if (finished)
219  return 0;
220 
221  if (last_it)
222  in.resize(last_block_size,cinfo.output_width,T());
223  else{
224  in.resize(block_size,cinfo.output_width,T());
225  }
226  if(cinfo.output_height - cinfo.output_scanline < in.height()){
227  std::ostringstream err;
228  err << FILE_READ_ERROR << this->data_filename_ << " | Bad image dimensions.";
229  slip::slip_exception exc(std::string("slip"), std::string("JpegReader::read()"), err.str());
230  throw (exc);
231  }
232 
233  for(unsigned int i=0; i < in.height(); ++i){
234  jpeg_read_scanlines(&cinfo, buffer, 1);
235  T * ptr_i = reinterpret_cast<T *>(in[i]);
236  std::copy(buffer[0],buffer[0]+row_stride,ptr_i);
237  }
238 
239  block_ind++;
240  if (last_it)
241  finished = true;
242  else
243  last_it = (block_ind == Nb_block);
244  return (!finished);
245 }
246 
247 template<class Container2d, typename T, std::size_t Nb_components, std::size_t Nb_block>
249  if(initialized){
250  /* Step 7: Finish decompression */
251  if(finished)
252  (void) jpeg_finish_decompress(&cinfo);
253  /* We can ignore the return value since suspension is not possible
254  * with the stdio data source.
255  */
256 
257  /* Step 8: Release JPEG decompression object */
258 
259  /* This is an important step since it will release a good deal of memory. */
260  jpeg_destroy_decompress(&cinfo);
261 
262  /* After finish_decompress, we can close the input file.
263  * Here we postpone it until after no more JPEG errors are possible,
264  * so as to simplify the setjmp error logic above. (Actually, I don't
265  * think that jpeg_destroy can do an error exit, but why assume anything...)
266  */
267  if (infile != NULL)
268  fclose(infile);
269 
270  row_stride = 0;
271  block_ind = 1;
272  block_size = 0;
273  last_block_size = 0;
274  last_it = false;
275  finished = false;
276  initialized = false;
277  }
278 }
279 
280 }
281 #endif /* JPEGREADER_HPP_ */
void initialize()
initialized the reading process.
Definition: JpegReader.hpp:128
Container2d container_type
Definition: JpegReader.hpp:47
Contains the container reader base class.
standard exception extension name have been changed to eliminate conflicts with QT ...
Definition: error.hpp:106
Some definitions specific to libjpeg.
const std::string FILE_OPEN_ERROR
Definition: error.hpp:82
ContainerReader is the base class of the readers classes. All readers are working the same way: ...
JpegReader, inherited from ContainerReader, is a reader for jpeg images.
Definition: JpegReader.hpp:45
ContainerReader< Container2d, T, Nb_block > base
Definition: JpegReader.hpp:49
void copy(_II first, _II last, _OI output_first)
Copy algorithm optimized for slip iterators.
Definition: copy_ext.hpp:177
int read(Container2d &in)
virtual read function. If Nb_block is more than one, it reads only one container, and returns 0...
Definition: JpegReader.hpp:211
Provides SLIP error messages.
JpegReader(std::string data_filename)
Definition: JpegReader.hpp:68
virtual ~JpegReader()
Definition: JpegReader.hpp:78
void release()
release the reading process.
Definition: JpegReader.hpp:248
const std::string FILE_READ_ERROR
Definition: error.hpp:90