Panda3D
Loading...
Searching...
No Matches
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...
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.