libcvd
load_and_save.h
1 #ifndef CVD_LOAD_AND_SAVE_H
2 #define CVD_LOAD_AND_SAVE_H
3 
4 #include <cvd/colourspace_convert.h>
5 #include <cvd/convert_image.h>
6 #include <cvd/exceptions.h>
7 #include <cvd/internal/convert_pixel_types.h>
8 #include <cvd/internal/io/parameter.h>
9 #include <cvd/internal/name_CVD_rgb_types.h>
10 #include <iostream>
11 #include <map>
12 #include <memory>
13 #include <string>
14 #include <typeinfo>
15 
16 namespace CVD
17 {
18 
19 namespace Exceptions
20 {
23  namespace Image_IO
24  {
27  struct All : public CVD::Exceptions::All
28  {
29  using CVD::Exceptions::All::All;
30  };
31 
34  struct MissingImageType : public All
35  {
36  MissingImageType(const std::string& type);
37  };
38 
41  struct UnsupportedImageType : public All
42  {
44  };
45 
48  struct EofBeforeImage : public All
49  {
51  };
52 
55  struct IfstreamNotOpen : public All
56  {
58  };
59 
62  struct MalformedImage : public All
63  {
64  MalformedImage(const std::string&);
65  };
66 
69  struct ImageSizeMismatch : public All
70  {
71  ImageSizeMismatch(const ImageRef& src, const ImageRef& dest);
72  };
73 
76  struct WriteError : public All
77  {
78  WriteError(const std::string& err);
79  };
80 
83  struct UnseekableIstream : public All
84  {
85  UnseekableIstream(const std::string& type);
86  };
87 
90  struct ReadTypeMismatch : public All
91  {
92  ReadTypeMismatch(bool read8);
93  ReadTypeMismatch(const std::string& available, const std::string& requested);
94  };
95 
98  struct WriteTypeMismatch : public All
99  {
100  WriteTypeMismatch(const std::string& available, const std::string& requested);
101  };
102 
105  struct InternalLibraryError : public All
106  {
107  InternalLibraryError(const std::string& lib, const std::string err);
108  };
109 
112  struct UnsupportedImageSubType : public All
113  {
114  UnsupportedImageSubType(const std::string&, const std::string&);
115  };
116 
119  struct OpenError : public All
120  {
121  OpenError(const std::string&, const std::string&, int);
122  };
123 
124  }
125 }
126 
127 namespace Internal
128 {
129  template <class C, int i>
131  {
132  static const bool use_16bit = 1;
133  };
134 
135  template <class C>
136  struct save_default_<C, 1>
137  {
138  static const bool use_16bit = (CVD::Pixel::traits<typename CVD::Pixel::Component<C>::type>::bits_used) > 8;
139  };
140 
141  template <class C>
143  {
144  static const bool use_16bit = save_default_<C, CVD::Pixel::traits<typename CVD::Pixel::Component<C>::type>::integral>::use_16bit;
145  };
146 
148  //Mechanisms for generic image loading
149  //
150  // Image readers are duck-types and must provide the following:
151  // typedef Types Typelist containing types which can be loaded
152  // string datatype() Stringified name of datatype on disk
153  // string name() Name of the reader (JPEG, TIFF, etc)
154  // ImageRef size() size()
155  // void get_raw_pixel_line(T) Where T is available for everything in Types
156  // Constructor accepting istream;
157 
158  //Basic typelist.
159  struct Head
160  {
161  };
162  template <class A, class B>
163  struct TypeList
164  {
165  typedef A Type;
166  typedef B Next;
167  };
168 
170  //
171  // Read data and process if necessary.
172  // In the case where the in-memory and on-disk datatypes match, no processing
173  // is performed.
174  template <class PixelType, class DiskPixelType, class ImageLoader>
176  {
177  static void exec(BasicImage<PixelType>& im, ImageLoader& r)
178  {
179  Image<DiskPixelType> rowbuf(ImageRef(r.size().x, 1));
180 
181  for(int row = 0; row < r.size().y; row++)
182  {
183  r.get_raw_pixel_line(rowbuf.data());
184  PixelType* rowptr;
185 
186  if(r.top_row_first())
187  rowptr = im[row];
188  else
189  rowptr = im[im.size().y - row - 1];
190 
192  }
193  }
194  };
195 
196  template <class PixelType, class ImageLoader>
197  struct read_and_maybe_process<PixelType, PixelType, ImageLoader>
198  {
199  static void exec(BasicImage<PixelType>& im, ImageLoader& r)
200  {
201  for(int row = 0; row < r.size().y; row++)
202  if(r.top_row_first())
203  r.get_raw_pixel_line(im[row]);
204  else
205  r.get_raw_pixel_line(im[im.size().y - row - 1]);
206  }
207  };
208 
209  template <class PixelType, class DiskPixelType, class ImageLoader>
211  {
212  static void exec(BasicImage<PixelType>& im, ImageLoader& r)
213  {
214  Image<DiskPixelType> imgbuf(r.size());
216 
217  convert_image(imgbuf, im);
218  }
219  };
220 
222  //
223  // Iterate over the typelist, and decide which type to load.
224  //
225  template <class PixelType, class ImageLoader, class List>
226  struct Reader
227  {
228  static void read(BasicImage<PixelType>& im, ImageLoader& r)
229  {
230  if(r.datatype() == PNM::type_name<typename List::Type>::name())
231  {
232  //std::cout << "converting " << r.datatype() << " -> " << PNM::type_name<PixelType>::name() << " PixelByPixel: " << PixelByPixelConvertible<typename List::Type, PixelType>::is << " Convertible: " << IsConvertible<typename List::Type, PixelType>::is << std::endl;
237  else
239  }
240  else
242  }
243  };
244 
245  template <class PixelType, class ImageLoader>
246  struct Reader<PixelType, ImageLoader, Head>
247  {
248  static void read(BasicImage<PixelType>&, ImageLoader& r)
249  {
250  throw Exceptions::Image_IO::UnsupportedImageSubType(r.name(), r.datatype() + " not yet supported");
251  }
252  };
253 
255  //
256  // Driver functions for loading images.
257  //
258 
259  template <class T, class ImageLoader>
260  void readImage(BasicImage<T>& im, ImageLoader& r)
261  {
263  }
264 
265  template <class T, class ImageLoader>
266  void readImage(BasicImage<T>& im, std::istream& in)
267  {
268  ImageLoader loader(in);
269  ImageRef size = loader.size();
270  if(im.size() != size)
272 
273  readImage(im, loader);
274  }
275 
276  template <class T, class ImageLoader>
277  void readImage(Image<T>& im, std::istream& in)
278  {
279  ImageLoader loader(in);
280  im.resize(loader.size());
281  readImage(im, loader);
282  }
283 
285  //
286  // Functions for attempting to choose an image type based on the datatype.
287  // The template code provides information detailing the ideal image type.
288  // The writer object is initialized with this information, and returns the type
289  // that it will write.
290  //
291  // Unlike loading, where the type on disk is known only dynamically, the type
292  // being saved and any necessary conversions can be deduced statically.
293  //
294  // The writer objects provide an interface with the following parts:
295  //
296  // template<class C> Outgoing::type For a given incoming pixel type C, this is the outgoing type
297  // constructor(ostream&, ImageRef, string type) Construct an image writer for a given type
298  // void write_raw_pixel_line(T*) Write pixels of type T.
299 
301  //
302  // Select an outgoing type, convert if necessary and then save.
303  //
304  template <class Pixel, class ImageWriter, class OutgoingPixel>
306  {
307  static void write(std::ostream& os, const BasicImage<Pixel>& im, const std::map<std::string, Parameter<>>& p)
308  {
309  ImageWriter w(os, im.size(), CVD::PNM::type_name<OutgoingPixel>::name(), p);
310  Image<OutgoingPixel> row(ImageRef(im.size().x, 1));
311 
312  if(w.top_row_first)
313  for(int r = 0; r < im.size().y; r++)
314  {
316  w.write_raw_pixel_line(row.data());
317  }
318  else
319  for(int r = im.size().y - 1; r >= 0; r--)
320  {
322  w.write_raw_pixel_line(row.data());
323  }
324  }
325  };
326 
327  template <class Pixel, class ImageWriter>
328  struct maybe_process_and_write<Pixel, ImageWriter, Pixel>
329  {
330  static void write(std::ostream& os, const BasicImage<Pixel>& im, const std::map<std::string, Parameter<>>& p)
331  {
332  ImageWriter w(os, im.size(), CVD::PNM::type_name<Pixel>::name(), p);
333 
334  if(w.top_row_first)
335  for(int r = 0; r < im.size().y; r++)
336  w.write_raw_pixel_line(im[r]);
337  else
338  for(int r = im.size().y - 1; r >= 0; r--)
339  w.write_raw_pixel_line(im[r]);
340  }
341  };
342 
343  template <class Pixel, class Writer>
344  void writeImage(const BasicImage<Pixel>& im, std::ostream& o, const std::map<std::string, Parameter<>>& p)
345  {
347  }
348 
349 }
350 
351 }
352 
353 #endif
The ifstream which the file is being read from is not open.
Definition: load_and_save.h:55
The image was incorrect.
Definition: load_and_save.h:62
Can two types be converted with CVD::convert_image?
Definition: convert_image.h:170
Definition: load_and_save.h:142
Definition: load_and_save.h:226
All classes and functions are within the CVD namespace.
Definition: argb.h:6
ImageRef size() const
What is the size of this image?
Definition: image.h:557
Cannot seek in this stream.
Definition: load_and_save.h:83
Definition: load_and_save.h:163
Definition: load_and_save.h:130
void resize(const ImageRef &size)
Resize the image (destroying the data).
Definition: image.h:731
Error in opening file.
Definition: load_and_save.h:119
This image type is not supported.
Definition: load_and_save.h:41
Definition: load_and_save.h:159
This image subtype is not supported.
Definition: load_and_save.h:112
The file ended before the image.
Definition: load_and_save.h:48
Error writing the image.
Definition: load_and_save.h:76
ConstPointerType data() const
Returns the raw image data.
Definition: image.h:535
Definition: load_and_save.h:175
Base class for all CVD exceptions.
Definition: exceptions.h:15
This image type is not supported.
Definition: load_and_save.h:34
Definition: image_ref.h:29
A generic image class to manage a block of arbitrarily padded data as an image.
Definition: image.h:273
void convert_image(const BasicImage< bayer_bggr > &from, BasicImage< byte > &to)
Convert Bayer pattern of various forms to greyscale data.
The loaded image is not the right size.
Definition: load_and_save.h:69
Definition: load_and_save.h:305
Definition: load_and_save.h:210
Definition: name_builtin_types.h:11
Definition: convert_pixel_types.h:441
A full image which manages its own data.
Definition: image.h:623
Type mismatch reading the image (image data is either 8- or 16-bit, and it must be the same in the fi...
Definition: load_and_save.h:90
Class for holding parameters for image savers, with type erasure.
Definition: parameter.h:18
Can individual pixels of two types be converted with ConvertPixels::convert()? E.g.
Definition: convert_image.h:179
Base class for all Image_IO exceptions.
Definition: load_and_save.h:27
Definition: pixel_traits.h:16
An error occurred in one of the helper libraries.
Definition: load_and_save.h:105
Type mismatch reading the image (image data is either 8- or 16-bit, and it must be the same in the fi...
Definition: load_and_save.h:98