Panda3D
pnmFileTypeIMG.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file pnmFileTypeIMG.cxx
10  * @author drose
11  * @date 2000-06-19
12  */
13 
14 #include "pnmFileTypeIMG.h"
15 
16 #ifdef HAVE_IMG
17 
18 #include "config_pnmimagetypes.h"
19 
20 #include "pnmFileTypeRegistry.h"
21 #include "bamReader.h"
22 
23 // Since raw image files don't have a magic number, we'll make a little sanity
24 // check on the size of the image. If either the width or height is larger
25 // than this, it must be bogus.
26 #define INSANE_SIZE 20000
27 
28 using std::istream;
29 using std::ostream;
30 using std::string;
31 
32 static const char * const extensions_img[] = {
33  "img"
34 };
35 static const int num_extensions_img = sizeof(extensions_img) / sizeof(const char *);
36 
37 TypeHandle PNMFileTypeIMG::_type_handle;
38 
39 /**
40  *
41  */
42 PNMFileTypeIMG::
43 PNMFileTypeIMG() {
44 }
45 
46 /**
47  * Returns a few words describing the file type.
48  */
49 string PNMFileTypeIMG::
50 get_name() const {
51  return "Raw binary RGB";
52 }
53 
54 /**
55  * Returns the number of different possible filename extensions associated
56  * with this particular file type.
57  */
58 int PNMFileTypeIMG::
59 get_num_extensions() const {
60  return num_extensions_img;
61 }
62 
63 /**
64  * Returns the nth possible filename extension associated with this particular
65  * file type, without a leading dot.
66  */
67 string PNMFileTypeIMG::
68 get_extension(int n) const {
69  nassertr(n >= 0 && n < num_extensions_img, string());
70  return extensions_img[n];
71 }
72 
73 /**
74  * Returns a suitable filename extension (without a leading dot) to suggest
75  * for files of this type, or empty string if no suggestions are available.
76  */
77 string PNMFileTypeIMG::
78 get_suggested_extension() const {
79  return "img";
80 }
81 
82 /**
83  * Allocates and returns a new PNMReader suitable for reading from this file
84  * type, if possible. If reading from this file type is not supported,
85  * returns NULL.
86  */
87 PNMReader *PNMFileTypeIMG::
88 make_reader(istream *file, bool owns_file, const string &magic_number) {
89  init_pnm();
90  return new Reader(this, file, owns_file, magic_number);
91 }
92 
93 /**
94  * Allocates and returns a new PNMWriter suitable for reading from this file
95  * type, if possible. If writing files of this type is not supported, returns
96  * NULL.
97  */
98 PNMWriter *PNMFileTypeIMG::
99 make_writer(ostream *file, bool owns_file) {
100  init_pnm();
101  return new Writer(this, file, owns_file);
102 }
103 
104 
105 inline unsigned long
106 read_ulong(istream *file) {
107  unsigned long x;
108  return pm_readbiglong(file, (long *)&x)==0 ? x : 0;
109 }
110 
111 inline unsigned short
112 read_ushort_IMG(istream *file) {
113  unsigned short x;
114  return pm_readbigshort(file, (short *)&x)==0 ? x : 0;
115 }
116 
117 inline unsigned char
118 read_uchar_IMG(istream *file) {
119  int x;
120  x = file->get();
121  return (x!=EOF) ? (unsigned char)x : 0;
122 }
123 
124 inline void
125 write_ulong(ostream *file, unsigned long x) {
126  pm_writebiglong(file, (long)x);
127 }
128 
129 inline void
130 write_ushort_IMG(ostream *file, unsigned long x) {
131  pm_writebigshort(file, (short)(long)x);
132 }
133 
134 inline void
135 write_uchar_IMG(ostream *file, unsigned char x) {
136  file->put(x);
137 }
138 
139 /**
140  *
141  */
142 PNMFileTypeIMG::Reader::
143 Reader(PNMFileType *type, istream *file, bool owns_file, string magic_number) :
144  PNMReader(type, file, owns_file)
145 {
146  if (img_header_type == IHT_long) {
147  if (!read_magic_number(_file, magic_number, 8)) {
148  // Although raw IMG files have no magic number, they may have a pair of
149  // ushorts or ulongs at the beginning to indicate the file size.
150  if (pnmimage_img_cat.is_debug()) {
151  pnmimage_img_cat.debug()
152  << "IMG image file appears to be empty.\n";
153  }
154  _is_valid = false;
155  return;
156  }
157 
158  _x_size =
159  ((unsigned char)magic_number[0] << 24) |
160  ((unsigned char)magic_number[1] << 16) |
161  ((unsigned char)magic_number[2] << 8) |
162  ((unsigned char)magic_number[3]);
163 
164  _y_size =
165  ((unsigned char)magic_number[4] << 24) |
166  ((unsigned char)magic_number[5] << 16) |
167  ((unsigned char)magic_number[6] << 8) |
168  ((unsigned char)magic_number[7]);
169 
170  } else if (img_header_type == IHT_short) {
171  if (!read_magic_number(_file, magic_number, 4)) {
172  if (pnmimage_img_cat.is_debug()) {
173  pnmimage_img_cat.debug()
174  << "IMG image file appears to be empty.\n";
175  }
176  _is_valid = false;
177  return;
178  }
179 
180  _x_size =
181  ((unsigned char)magic_number[0] << 8) |
182  ((unsigned char)magic_number[1]);
183 
184  _y_size =
185  ((unsigned char)magic_number[2] << 8) |
186  ((unsigned char)magic_number[3]);
187 
188  } else {
189  _x_size = img_size[0];
190  _y_size = img_size[1];
191  }
192 
193  if (_x_size == 0 || _y_size == 0 ||
194  _x_size > INSANE_SIZE || _y_size > INSANE_SIZE) {
195  _is_valid = false;
196  if (img_header_type == IHT_none) {
197  pnmimage_img_cat.error()
198  << "Must specify img-xsize and img-ysize to load headerless raw files.\n";
199  } else {
200  pnmimage_img_cat.debug()
201  << "IMG file does not have a valid xsize,ysize header.\n";
202  }
203  return;
204  }
205 
206  _maxval = 255;
207  _num_channels = 3;
208 
209  if (pnmimage_img_cat.is_debug()) {
210  pnmimage_img_cat.debug()
211  << "Reading IMG " << *this << "\n";
212  }
213 }
214 
215 /**
216  * Returns true if this particular PNMReader supports a streaming interface to
217  * reading the data: that is, it is capable of returning the data one row at a
218  * time, via repeated calls to read_row(). Returns false if the only way to
219  * read from this file is all at once, via read_data().
220  */
221 bool PNMFileTypeIMG::Reader::
222 supports_read_row() const {
223  return true;
224 }
225 
226 /**
227  * If supports_read_row(), above, returns true, this function may be called
228  * repeatedly to read the image, one horizontal row at a time, beginning from
229  * the top. Returns true if the row is successfully read, false if there is
230  * an error or end of file.
231  */
232 bool PNMFileTypeIMG::Reader::
233 read_row(xel *row_data, xelval *, int x_size, int) {
234  int x;
235  xelval red, grn, blu;
236  for (x = 0; x < x_size; x++) {
237  red = read_uchar_IMG(_file);
238  grn = read_uchar_IMG(_file);
239  blu = read_uchar_IMG(_file);
240 
241  PPM_ASSIGN(row_data[x], red, grn, blu);
242  }
243 
244  return true;
245 }
246 
247 /**
248  *
249  */
250 PNMFileTypeIMG::Writer::
251 Writer(PNMFileType *type, ostream *file, bool owns_file) :
252  PNMWriter(type, file, owns_file)
253 {
254 }
255 
256 /**
257  * Returns true if this particular PNMWriter supports a streaming interface to
258  * writing the data: that is, it is capable of writing the image one row at a
259  * time, via repeated calls to write_row(). Returns false if the only way to
260  * write from this file is all at once, via write_data().
261  */
262 bool PNMFileTypeIMG::Writer::
263 supports_write_row() const {
264  return true;
265 }
266 
267 /**
268  * If supports_write_row(), above, returns true, this function may be called
269  * to write out the image header in preparation to writing out the image data
270  * one row at a time. Returns true if the header is successfully written,
271  * false if there is an error.
272  *
273  * It is the user's responsibility to fill in the header data via calls to
274  * set_x_size(), set_num_channels(), etc., or copy_header_from(), before
275  * calling write_header().
276  */
277 bool PNMFileTypeIMG::Writer::
278 write_header() {
279  if (img_header_type == IHT_long) {
280  write_ulong(_file, _x_size);
281  write_ulong(_file, _y_size);
282  } else if (img_header_type == IHT_short) {
283  write_ushort_IMG(_file, _x_size);
284  write_ushort_IMG(_file, _y_size);
285  }
286  return true;
287 }
288 
289 /**
290  * If supports_write_row(), above, returns true, this function may be called
291  * repeatedly to write the image, one horizontal row at a time, beginning from
292  * the top. Returns true if the row is successfully written, false if there
293  * is an error.
294  *
295  * You must first call write_header() before writing the individual rows. It
296  * is also important to delete the PNMWriter class after successfully writing
297  * the last row. Failing to do this may result in some data not getting
298  * flushed!
299  */
300 bool PNMFileTypeIMG::Writer::
301 write_row(xel *row_data, xelval *) {
302  int x;
303  for (x = 0; x < _x_size; x++) {
304  write_uchar_IMG(_file, (unsigned char)(255*PPM_GETR(row_data[x])/_maxval));
305  write_uchar_IMG(_file, (unsigned char)(255*PPM_GETG(row_data[x])/_maxval));
306  write_uchar_IMG(_file, (unsigned char)(255*PPM_GETB(row_data[x])/_maxval));
307  }
308 
309  return true;
310 }
311 
312 
313 
314 /**
315  * Registers the current object as something that can be read from a Bam file.
316  */
317 void PNMFileTypeIMG::
318 register_with_read_factory() {
320  register_factory(get_class_type(), make_PNMFileTypeIMG);
321 }
322 
323 /**
324  * This method is called by the BamReader when an object of this type is
325  * encountered in a Bam file; it should allocate and return a new object with
326  * all the data read.
327  *
328  * In the case of the PNMFileType objects, since these objects are all shared,
329  * we just pull the object from the registry.
330  */
331 TypedWritable *PNMFileTypeIMG::
332 make_PNMFileTypeIMG(const FactoryParams &params) {
333  return PNMFileTypeRegistry::get_global_ptr()->get_type_by_handle(get_class_type());
334 }
335 
336 #endif // HAVE_IMG
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
This is the base class of a family of classes that represent particular image file types that PNMImag...
Definition: pnmFileType.h:32
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PNMFileType * get_type_by_handle(TypeHandle handle) const
Returns the PNMFileType instance stored in the registry for the given TypeHandle, e....
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is an abstract base class that defines the interface for reading image files of various types.
Definition: pnmReader.h:27
This is an abstract base class that defines the interface for writing image files of various types.
Definition: pnmWriter.h:27
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81