16 #ifdef HAVE_SOFTIMAGE_PIC 27 static const float imageVersionNumber = 3.0;
28 static const int imageCommentLength = 80;
29 static const char imageComment[imageCommentLength+1] =
30 "Written by pnmimage.";
33 #define UNCOMPRESSED 0x00 34 #define MIXED_RUN_LENGTH 0x02 37 #define RGB_CHANNEL 0xe0 38 #define ALPHA_CHANNEL 0x10 41 #define SOFTIMAGE_MAGIC1 0x5380 42 #define SOFTIMAGE_MAGIC2 0xf634 44 static const char *
const extensions_softimage[] = {
47 static const int num_extensions_softimage =
sizeof(extensions_softimage) /
sizeof(
const char *);
52 read_float(istream *file) {
55 if (pm_readbiglong(file, &l)==0) {
63 read_ushort_SI(istream *file) {
65 return pm_readbigshort(file, (
short *)&x)==0 ? x : 0;
69 read_uchar_SI(istream *file) {
72 return (x!=EOF) ? (
unsigned char)x : 0;
76 write_ushort_SI(ostream *file,
unsigned short x) {
77 pm_writebigshort(file, (
short)x);
81 write_uchar_SI(ostream *file,
unsigned char x) {
86 write_float(ostream *file,
float x) {
87 pm_writebiglong(file, *(
long *)&x);
91 read_channel_pkt(istream *file,
92 int &chained,
int &size,
int &type,
int &channel) {
93 chained = read_uchar_SI(file);
94 size = read_uchar_SI(file);
95 type = read_uchar_SI(file);
96 channel = read_uchar_SI(file);
98 if (file->eof() || file->fail()) {
103 pnmimage_soft_cat.error()
104 <<
"Don't know how to interpret " << size <<
" bits per pixel!\n";
112 read_rgb(
xel *row_data, xelval *, istream *file,
int x,
int repeat) {
113 xelval red, grn, blu;
114 red = read_uchar_SI(file);
115 grn = read_uchar_SI(file);
116 blu = read_uchar_SI(file);
119 PPM_ASSIGN(row_data[x], red, grn, blu);
126 read_alpha(
xel *, xelval *alpha_data, istream *file,
int x,
int repeat) {
127 xelval alpha = read_uchar_SI(file);
130 alpha_data[x] = alpha;
137 read_rgba(
xel *row_data, xelval *alpha_data, istream *file,
int x,
int repeat) {
138 xelval red, grn, blu, alpha;
139 red = read_uchar_SI(file);
140 grn = read_uchar_SI(file);
141 blu = read_uchar_SI(file);
142 alpha = read_uchar_SI(file);
145 PPM_ASSIGN(row_data[x], red, grn, blu);
146 alpha_data[x] = alpha;
154 read_scanline(
xel *row_data, xelval *alpha_data,
int cols, istream *file,
155 void (*read_data)(
xel *row_data, xelval *alpha_data, istream *file,
158 if (ctype==UNCOMPRESSED) {
159 for (
int x = 0; x<cols; x++) {
160 read_data(row_data, alpha_data, file, x, 1);
169 num = read_uchar_SI(file);
178 read_data(row_data, alpha_data, file, x, 1);
179 if (file->eof() || file->fail()) {
188 num = read_ushort_SI(file);
195 read_data(row_data, alpha_data, file, x, num);
196 if (file->eof() || file->fail()) {
210 PNMFileTypeSoftImage::
211 PNMFileTypeSoftImage() {
217 string PNMFileTypeSoftImage::
226 int PNMFileTypeSoftImage::
227 get_num_extensions()
const {
228 return num_extensions_softimage;
235 string PNMFileTypeSoftImage::
236 get_extension(
int n)
const {
237 nassertr(n >= 0 && n < num_extensions_softimage,
string());
238 return extensions_softimage[n];
245 string PNMFileTypeSoftImage::
246 get_suggested_extension()
const {
254 bool PNMFileTypeSoftImage::
255 has_magic_number()
const {
264 bool PNMFileTypeSoftImage::
265 matches_magic_number(
const string &magic_number)
const {
266 nassertr(magic_number.size() >= 2,
false);
268 ((
unsigned char)magic_number[0] << 8) |
269 ((
unsigned char)magic_number[1]);
270 return (mn == SOFTIMAGE_MAGIC1);
279 make_reader(istream *file,
bool owns_file,
const string &magic_number) {
281 return new Reader(
this, file, owns_file, magic_number);
290 make_writer(ostream *file,
bool owns_file) {
292 return new Writer(
this, file, owns_file);
299 PNMFileTypeSoftImage::Reader::
300 Reader(
PNMFileType *type, istream *file,
bool owns_file,
string magic_number) :
305 if (pnmimage_soft_cat.is_debug()) {
306 pnmimage_soft_cat.debug()
307 <<
"SoftImage image file appears to be empty.\n";
314 ((
unsigned char)magic_number[0] << 8) |
315 ((
unsigned char)magic_number[1]);
317 ((
unsigned char)magic_number[2] << 8) |
318 ((
unsigned char)magic_number[3]);
320 if (magic1 != SOFTIMAGE_MAGIC1 || magic2 != SOFTIMAGE_MAGIC2) {
329 _file->seekg(imageCommentLength, std::ios::cur);
332 _file->read(pict_id, 4);
333 if (_file->gcount() < 4) {
338 if (memcmp(pict_id,
"PICT", 4)!=0) {
343 _x_size = read_ushort_SI(_file);
344 _y_size = read_ushort_SI(_file);
347 read_ushort_SI(_file);
348 read_ushort_SI(_file);
350 int chained, size, channel;
351 if (!read_channel_pkt(_file, chained, size, rgb_ctype, channel)) {
356 soft_color = unknown;
358 if (channel == (RGB_CHANNEL | ALPHA_CHANNEL)) {
362 }
else if (channel == RGB_CHANNEL) {
367 if (!read_channel_pkt(_file, chained, size, alpha_ctype, channel)) {
372 if (channel == ALPHA_CHANNEL) {
379 switch (soft_color) {
390 pnmimage_soft_cat.error()
391 <<
"Image is not RGB or RGBA!\n";
397 pnmimage_soft_cat.error()
398 <<
"Unexpected additional channels in image file.\n";
405 if (pnmimage_soft_cat.is_debug()) {
406 pnmimage_soft_cat.debug()
407 <<
"Reading SoftImage " << *
this <<
"\n";
418 bool PNMFileTypeSoftImage::Reader::
419 supports_read_row()
const {
429 bool PNMFileTypeSoftImage::Reader::
430 read_row(
xel *row_data, xelval *alpha_data,
int x_size,
int) {
434 switch (soft_color) {
436 if (!read_scanline(row_data, alpha_data, x_size, _file,
437 read_rgb, rgb_ctype)) {
443 if (!read_scanline(row_data, alpha_data, x_size, _file,
444 read_rgba, rgb_ctype)) {
450 if (!read_scanline(row_data, alpha_data, x_size, _file,
451 read_rgb, rgb_ctype)) {
454 if (!read_scanline(row_data, alpha_data, x_size, _file,
455 read_alpha, alpha_ctype)) {
469 write_channel_pkt(ostream *file,
470 int chained,
int size,
int type,
int channel) {
471 write_uchar_SI(file, chained);
472 write_uchar_SI(file, size);
473 write_uchar_SI(file, type);
474 write_uchar_SI(file, channel);
478 write_rgb(
xel *row_data, xelval *, ostream *file,
int x) {
479 write_uchar_SI(file, PPM_GETR(row_data[x]));
480 write_uchar_SI(file, PPM_GETG(row_data[x]));
481 write_uchar_SI(file, PPM_GETB(row_data[x]));
485 compare_rgb(
xel *row_data, xelval *,
int x1,
int x2) {
486 return PPM_EQUAL(row_data[x1], row_data[x2]);
490 write_gray(
xel *row_data, xelval *, ostream *file,
int x) {
491 write_uchar_SI(file, PPM_GETB(row_data[x]));
492 write_uchar_SI(file, PPM_GETB(row_data[x]));
493 write_uchar_SI(file, PPM_GETB(row_data[x]));
497 compare_gray(
xel *row_data, xelval *,
int x1,
int x2) {
498 return (PPM_GETB(row_data[x1])==PPM_GETB(row_data[x2]));
502 write_alpha(
xel *, xelval *alpha_data, ostream *file,
int x) {
503 write_uchar_SI(file, alpha_data[x]);
507 compare_alpha(
xel *, xelval *alpha_data,
int x1,
int x2) {
508 return (alpha_data[x1]==alpha_data[x2]);
512 write_diff(
xel *row_data, xelval *alpha_data, ostream *file,
513 void (*write_data)(
xel *row_data, xelval *alpha_data, ostream *file,
515 int tox,
int length) {
517 nassertv(length<=128);
519 write_uchar_SI(file, length-1);
522 write_data(row_data, alpha_data, file, tox-length);
528 write_same(
xel *row_data, xelval *alpha_data, ostream *file,
529 void (*write_data)(
xel *row_data, xelval *alpha_data, ostream *file,
531 int tox,
int length) {
533 write_diff(row_data, alpha_data, file, write_data, tox, length);
535 }
else if (length>0) {
537 write_uchar_SI(file, length+127);
539 write_uchar_SI(file, 128);
540 write_ushort_SI(file, length);
542 write_data(row_data, alpha_data, file, tox);
548 write_scanline(
xel *row_data, xelval *alpha_data,
int cols, ostream *file,
549 int (*compare_data)(
xel *row_data, xelval *alpha_data,
551 void (*write_data)(
xel *row_data, xelval *alpha_data,
552 ostream *file,
int x)) {
567 if (!compare_data(row_data, alpha_data, x, x-run_length)) {
570 if (run_length <= 1) {
581 write_same(row_data, alpha_data, file, write_data, x-1, run_length);
592 if (run_length>128) {
596 int excess = run_length - 128;
597 write_diff(row_data, alpha_data, file, write_data, x-excess-1, 128);
600 }
else if (run_length > 2 &&
601 compare_data(row_data, alpha_data, x, x-1) &&
602 compare_data(row_data, alpha_data, x, x-2)) {
607 write_diff(row_data, alpha_data, file, write_data, x-3, run_length-2);
621 write_same(row_data, alpha_data, file, write_data, cols-1, run_length);
625 if (run_length>128) {
626 int excess = run_length - 128;
627 write_diff(row_data, alpha_data, file, write_data, cols-excess-1, 128);
631 write_diff(row_data, alpha_data, file, write_data, cols-1, run_length);
639 PNMFileTypeSoftImage::Writer::
640 Writer(
PNMFileType *type, ostream *file,
bool owns_file) :
651 bool PNMFileTypeSoftImage::Writer::
652 supports_write_row()
const {
666 bool PNMFileTypeSoftImage::Writer::
668 write_ushort_SI(_file, SOFTIMAGE_MAGIC1);
669 write_ushort_SI(_file, SOFTIMAGE_MAGIC2);
670 write_float(_file, imageVersionNumber);
672 _file->write(imageComment, imageCommentLength);
673 _file->write(
"PICT", 4);
675 write_ushort_SI(_file, _x_size);
676 write_ushort_SI(_file, _y_size);
678 write_float(_file, 1.0);
679 write_ushort_SI(_file, 3);
680 write_ushort_SI(_file, 0);
686 write_channel_pkt(_file, 1, 8, MIXED_RUN_LENGTH, RGB_CHANNEL);
687 write_channel_pkt(_file, 0, 8, MIXED_RUN_LENGTH, ALPHA_CHANNEL);
689 write_channel_pkt(_file, 0, 8, MIXED_RUN_LENGTH, RGB_CHANNEL);
706 bool PNMFileTypeSoftImage::Writer::
707 write_row(
xel *row_data, xelval *alpha_data) {
708 if (is_grayscale()) {
709 write_scanline(row_data, alpha_data, _x_size, _file, compare_gray, write_gray);
712 write_scanline(row_data, alpha_data, _x_size, _file, compare_rgb, write_rgb);
716 write_scanline(row_data, alpha_data, _x_size, _file, compare_alpha, write_alpha);
719 return !_file->fail();
727 void PNMFileTypeSoftImage::
728 register_with_read_factory() {
730 register_factory(get_class_type(), make_PNMFileTypeSoftImage);
746 #endif // HAVE_SOFTIMAGE_PIC PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base class for objects that can be written to and read from Bam files.
This is the base class of a family of classes that represent particular image file types that PNMImag...
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
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.
This is an abstract base class that defines the interface for writing image files of various types.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
TypeHandle is the identifier used to differentiate C++ class types.