15 #include "pnmImageHeader.h" 16 #include "pnmFileTypeRegistry.h" 17 #include "pnmFileType.h" 18 #include "pnmReader.h" 19 #include "pnmWriter.h" 20 #include "config_pnmimage.h" 21 #include "virtualFileSystem.h" 35 bool report_unknown_type) {
63 bool report_unknown_type) {
65 (&data,
false, filename,
string(), type, report_unknown_type);
90 bool report_unknown_type)
const {
91 if (pnmimage_cat.is_debug()) {
93 <<
"Reading image from " << filename <<
"\n";
95 bool owns_file =
false;
96 istream *file = (istream *)NULL;
98 if (filename ==
"-") {
102 if (pnmimage_cat.is_debug()) {
104 <<
"(reading standard input)\n";
112 if (file == (istream *)NULL) {
113 if (pnmimage_cat.is_debug()) {
115 <<
"Unable to open file.\n";
120 return make_reader(file, owns_file, filename,
string(), type,
121 report_unknown_type);
157 bool report_unknown_type)
const {
161 if (pnmimage_cat.is_debug()) {
163 <<
"Image file appears to be empty.\n";
179 get_type_from_magic_number(magic_number);
181 if (pnmimage_cat.is_debug()) {
184 <<
"By magic number, image file appears to be type " 185 << type->get_name() <<
".\n";
188 <<
"Unable to determine image file type from magic number.\n";
193 if (type == (
PNMFileType *)NULL && !filename.empty()) {
198 if (pnmimage_cat.is_debug()) {
201 <<
"From its extension, image file is probably type " 202 << type->get_name() <<
".\n";
205 <<
"Unable to guess image file type from its extension.\n";
214 if (pnmimage_cat.is_debug() && type != (
PNMFileType *)NULL) {
216 <<
"Assuming image file type is " << type->get_name() <<
".\n";
222 if (report_unknown_type && pnmimage_cat.is_error()) {
224 <<
"Cannot determine type of image file " << filename <<
".\n" 225 <<
"Currently supported image types:\n";
227 write(pnmimage_cat.error(
false), 2);
243 if (reader == NULL && owns_file) {
271 if (pnmimage_cat.is_debug()) {
273 <<
"Writing image to " << filename <<
"\n";
275 bool owns_file =
false;
276 ostream *file = (ostream *)NULL;
278 if (filename ==
"-") {
282 if (pnmimage_cat.is_debug()) {
284 <<
"(writing to standard output)\n";
289 Filename actual_name = Filename::binary_filename(filename);
296 if (file == (ostream *)NULL) {
297 if (pnmimage_cat.is_debug()) {
299 <<
"Unable to write to file.\n";
304 return make_writer(file, owns_file, filename, type);
334 if (type == (
PNMFileType *)NULL && !filename.empty()) {
339 if (pnmimage_cat.is_debug()) {
342 <<
"From its extension, image file is intended to be type " 343 << type->get_name() <<
".\n";
346 <<
"Unable to guess image file type from its extension.\n";
355 if (pnmimage_cat.is_debug() && type != (
PNMFileType *)NULL) {
357 <<
"Assuming image file type is " << type->get_name() <<
".\n";
363 if (pnmimage_cat.is_debug()) {
365 <<
"Cannot determine type of image file " << filename <<
".\n";
374 if (writer == NULL && owns_file) {
378 if (writer != NULL && !writer->
is_valid()) {
398 while ((
int)magic_number.size() < num_bytes) {
399 int ch = file->get();
400 if (file->eof() || file->fail()) {
403 magic_number += (char)ch;
414 void PNMImageHeader::
415 output(ostream &out)
const {
416 out <<
"image: " << _x_size <<
" by " << _y_size <<
" pixels, " 417 << _num_channels <<
" channels, " << _maxval <<
" maxval.";
438 bool PNMImageHeader::
440 xel *array, xelval *alpha,
int max_colors) {
441 int num_pixels = _x_size * _y_size;
449 for (pi = 0; pi < num_pixels; pi++) {
450 record_color(hist,
PixelSpec(PPM_GETB(array[pi])));
451 if (max_colors > 0 && (
int)hist.size() > max_colors) {
458 for (pi = 0; pi < num_pixels; pi++) {
459 record_color(hist,
PixelSpec(PPM_GETB(array[pi]), alpha[pi]));
460 if (max_colors > 0 && (
int)hist.size() > max_colors) {
467 for (pi = 0; pi < num_pixels; pi++) {
468 record_color(hist,
PixelSpec(PPM_GETR(array[pi]), PPM_GETG(array[pi]), PPM_GETB(array[pi])));
469 if (max_colors > 0 && (
int)hist.size() > max_colors) {
475 case CT_four_channel:
476 for (pi = 0; pi < num_pixels; pi++) {
477 record_color(hist,
PixelSpec(PPM_GETR(array[pi]), PPM_GETG(array[pi]), PPM_GETB(array[pi]), alpha[pi]));
478 if (max_colors > 0 && (
int)hist.size() > max_colors) {
494 bool PNMImageHeader::
496 xel *array, xelval *alpha,
int max_colors) {
499 int num_pixels = _x_size * _y_size;
502 Palette::const_iterator pi;
503 for (pi = palette.begin(); pi != palette.end(); ++pi) {
504 hist.insert(HistMap::value_type(*pi, num_pixels + 1));
507 if (!compute_histogram(hist, array, alpha, max_colors)) {
513 palette.reserve(hist.size());
514 HistMap::const_iterator hi;
515 for (hi = hist.begin(); hi != hist.end(); ++hi) {
516 if ((*hi).second <= num_pixels) {
517 palette.push_back((*hi).first);
529 void PNMImageHeader::PixelSpec::
530 output(ostream &out)
const {
531 out <<
"(" << _red <<
", " << _green <<
", " << _blue <<
", " << _alpha <<
")";
539 void PNMImageHeader::Histogram::
540 write(ostream &out)
const {
541 out <<
"Histogram: {\n";
542 PixelCount::const_iterator pi;
543 for (pi = _pixels.begin(); pi != _pixels.end(); ++pi) {
544 out <<
" " << (*pi)._pixel <<
": " << (*pi)._count <<
",\n";
bool is_valid() const
Returns true if the PNMWriter can be used to write data, false if something is wrong.
virtual PNMWriter * make_writer(ostream *file, bool owns_file=true)
Allocates and returns a new PNMWriter suitable for reading from this file type, if possible...
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
istream * open_read_file(const Filename &filename, bool auto_unwrap) const
Convenience function; returns a newly allocated istream if the file exists and can be read...
This is the base class of a family of classes that represent particular image file types that PNMImag...
virtual PNMReader * make_reader(istream *file, bool owns_file=true, const string &magic_number=string())
Allocates and returns a new PNMReader suitable for reading from this file type, if possible...
static void close_read_file(istream *stream)
Closes a file opened by a previous call to open_read_file().
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
This is our own Panda specialization on the default STL vector.
bool is_valid() const
Returns true if the PNMReader can be used to read data, false if something is wrong.
The name of a file, such as a texture file or an Egg file.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PNMFileType * get_type_from_extension(const string &filename) const
Tries to determine what the PNMFileType is likely to be for a particular image file based on its exte...
This is an abstract base class that defines the interface for reading image files of various types...
This is an abstract base class that defines the interface for writing image files of various types...
ostream * open_write_file(const Filename &filename, bool auto_wrap, bool truncate)
Convenience function; returns a newly allocated ostream if the file exists and can be written...