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
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
28using std::istream;
29using std::ostream;
30using std::string;
31
32static const char * const extensions_img[] = {
33 "img"
34};
35static const int num_extensions_img = sizeof(extensions_img) / sizeof(const char *);
36
37TypeHandle PNMFileTypeIMG::_type_handle;
38
39/**
40 *
41 */
42PNMFileTypeIMG::
43PNMFileTypeIMG() {
44}
45
46/**
47 * Returns a few words describing the file type.
48 */
49string PNMFileTypeIMG::
50get_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 */
58int PNMFileTypeIMG::
59get_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 */
67string PNMFileTypeIMG::
68get_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 */
77string PNMFileTypeIMG::
78get_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 */
87PNMReader *PNMFileTypeIMG::
88make_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 */
98PNMWriter *PNMFileTypeIMG::
99make_writer(ostream *file, bool owns_file) {
100 init_pnm();
101 return new Writer(this, file, owns_file);
102}
103
104
105inline unsigned long
106read_ulong(istream *file) {
107 unsigned long x;
108 return pm_readbiglong(file, (long *)&x)==0 ? x : 0;
109}
110
111inline unsigned short
112read_ushort_IMG(istream *file) {
113 unsigned short x;
114 return pm_readbigshort(file, (short *)&x)==0 ? x : 0;
115}
116
117inline unsigned char
118read_uchar_IMG(istream *file) {
119 int x;
120 x = file->get();
121 return (x!=EOF) ? (unsigned char)x : 0;
122}
123
124inline void
125write_ulong(ostream *file, unsigned long x) {
126 pm_writebiglong(file, (long)x);
127}
128
129inline void
130write_ushort_IMG(ostream *file, unsigned long x) {
131 pm_writebigshort(file, (short)(long)x);
132}
133
134inline void
135write_uchar_IMG(ostream *file, unsigned char x) {
136 file->put(x);
137}
138
139/**
140 *
141 */
142PNMFileTypeIMG::Reader::
143Reader(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 */
221bool PNMFileTypeIMG::Reader::
222supports_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 */
232bool PNMFileTypeIMG::Reader::
233read_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 */
250PNMFileTypeIMG::Writer::
251Writer(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 */
262bool PNMFileTypeIMG::Writer::
263supports_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 */
277bool PNMFileTypeIMG::Writer::
278write_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 */
300bool PNMFileTypeIMG::Writer::
301write_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 */
317void PNMFileTypeIMG::
318register_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 */
331TypedWritable *PNMFileTypeIMG::
332make_PNMFileTypeIMG(const FactoryParams &params) {
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.