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.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
PNMFileType * get_type_by_handle(TypeHandle handle) const
Returns the PNMFileType instance stored in the registry for the given TypeHandle, e....
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
This is the base class of a family of classes that represent particular image file types that PNMImag...
Definition: pnmFileType.h:32
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
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.