50 typedef PNMFileTypeSGI::Reader::TabEntry TabEntry;
    52 typedef short       ScanElem;
    53 typedef ScanElem *  ScanLine;
    56 static unsigned char get_byte ( istream* f );
    57 static long get_big_long (istream *f);
    58 static short get_big_short (istream *f);
    59 static short get_byte_as_short (istream *f);
    60 static int readerr (istream *f);
    61 static void * xmalloc (
int bytes);
    62 #define MALLOC(n, type)     (type *)xmalloc((n) * sizeof(type))    63 static const char * compression_name (
char compr);
    64 static void       read_bytes (istream *ifp, 
int n, 
char *buf);
    65 static bool read_header(istream *ifp, 
Header *head, 
const string &magic_number);
    66 static TabEntry * read_table (istream *ifp, 
int tablen);
    67 static void       read_channel (istream *ifp, 
int xsize, 
int ysize,
    68                                      int zsize, 
int bpc, TabEntry *table,
    69                                      ScanElem *channel_data, 
long table_start,
    70                                      int channel, 
int row);
    71 static void       rle_decompress (ScanElem *src, 
long srclen, ScanElem *dest, 
long destlen);
    73 #define WORSTCOMPR(x)   (2*(x) + 2)    75 #define MAXVAL_BYTE     255    76 #define MAXVAL_WORD     65535    81 static bool eof_err = 
false;
    87 PNMFileTypeSGI::Reader::
    88 Reader(
PNMFileType *type, istream *file, 
bool owns_file, 
string magic_number) :
    96     if (pnmimage_sgi_cat.is_debug()) {
    97       pnmimage_sgi_cat.debug()
    98         << 
"RGB file appears to be empty.\n";
   110   long pixmax = (head.bpc == 1) ? MAXVAL_BYTE : MAXVAL_WORD;
   111   if( pixmax > PNM_MAXMAXVAL ) {
   112     pnmimage_sgi_cat.error()
   113       << 
"Cannot read RGB image with maxval of " << pixmax
   114       << 
"--largest allowable maxval is currently " << PNM_MAXMAXVAL << 
"\n";
   119   _maxval = (xelval)pixmax;
   121   table_start = file->tellg();
   122   if( head.storage != STORAGE_VERBATIM )
   123     table = read_table(file, head.ysize * head.zsize);
   125   _x_size = head.xsize;
   126   _y_size = head.ysize;
   127   _num_channels = std::min((
int)head.zsize, 4);
   130   current_row = _y_size - 1;
   132   if (_is_valid && pnmimage_sgi_cat.is_debug()) {
   133     head.name[79] = 
'\0';  
   134     pnmimage_sgi_cat.debug()
   135       << 
"Read RGB image:\n"   136       << 
"  raster size " << head.xsize << 
" x " << head.ysize
   137       << 
", " << head.zsize << 
" channels\n"   138       << 
"  compression: " << (int)head.storage << 
" = "   139       << compression_name(head.storage) << 
"\n"   140       << 
"  image name: " << head.name << 
"\n"   141       << 
"  bpc: " << (int)head.bpc << 
" dimension: " << head.dimension << 
"\n"   142       << 
"  pixmin: " << head.pixmin << 
" pixmax: " << head.pixmax
   143       << 
"  colormap: " << head.colormap << 
"\n";
   150 PNMFileTypeSGI::Reader::
   152   if (table != 
nullptr) {
   163 bool PNMFileTypeSGI::Reader::
   164 supports_read_row()
 const {
   174 bool PNMFileTypeSGI::Reader::
   175 read_row(
xel *row_data, xelval *alpha_data, 
int x_size, 
int y_size) {
   179   nassertr(current_row >= 0, 
false);
   181   ScanElem *red = (ScanElem *)alloca(x_size * 
sizeof(ScanElem));
   182   ScanElem *grn = (ScanElem *)alloca(x_size * 
sizeof(ScanElem));
   183   ScanElem *blu = (ScanElem *)alloca(x_size * 
sizeof(ScanElem));
   184   ScanElem *alpha = (ScanElem *)alloca(x_size * 
sizeof(ScanElem));
   186   read_channel(_file, x_size, y_size, _num_channels, bpc, table, red,
   187                table_start, 0, current_row);
   189   if (!is_grayscale()) {
   190     read_channel(_file, x_size, y_size, _num_channels, bpc, table, grn,
   191                  table_start, 1, current_row);
   192     read_channel(_file, x_size, y_size, _num_channels, bpc, table, blu,
   193                  table_start, 2, current_row);
   197     read_channel(_file, x_size, y_size, _num_channels, bpc, table, alpha,
   198                  table_start, _num_channels - 1, current_row);
   201   for (
int x = 0; x < x_size; x++) {
   202     if (is_grayscale()) {
   203       PPM_PUTB(row_data[x], (xelval)red[x]);
   209       PPM_ASSIGN(row_data[x], r, g, b);
   213       alpha_data[x] = (xelval)alpha[x];
   223 read_header(istream *ifp, 
Header *head, 
const string &magic_number) {
   224     nassertr(magic_number.size() == 4, 
false);
   226       ((
unsigned char)magic_number[0] << 8) |
   227       ((
unsigned char)magic_number[1]);
   228     head->storage   = (
unsigned char)magic_number[2];
   229     head->bpc       = (
unsigned char)magic_number[3];
   230     head->dimension = get_big_short(ifp);
   231     head->xsize     = get_big_short(ifp);
   232     head->ysize     = get_big_short(ifp);
   233     head->zsize     = get_big_short(ifp);
   234     head->pixmin    = get_big_long(ifp);
   235     head->pixmax    = get_big_long(ifp);
   236     read_bytes(ifp, 4, head->dummy1);
   237     read_bytes(ifp, 80, head->name);
   238     head->colormap  = get_big_long(ifp);
   239     read_bytes(ifp, 404, head->dummy2);
   241     if (head->magic != SGI_MAGIC) {
   242       pnmimage_sgi_cat.error()
   243         << 
"Invalid magic number: not an SGI image file.\n";
   247     if (head->storage != 0 && head->storage != 1) {
   248       pnmimage_sgi_cat.error()
   249         << 
"Unknown compression type.\n";
   253     if (head->bpc < 1 || head->bpc > 2) {
   254       pnmimage_sgi_cat.error()
   255         << 
"Illegal precision value " << head->bpc << 
" (only 1-2 allowed)\n";
   315 read_table(istream *ifp, 
int tablen) {
   319     table = MALLOC(tablen, TabEntry);
   321     for( i = 0; i < tablen; i++ ) {
   322         table[i].start = get_big_long(ifp);
   324     for( i = 0; i < tablen; i++ ) {
   325         table[i].length = get_big_long(ifp);
   334 read_channel(istream *ifp,
   335              int xsize, 
int ysize, 
int, 
int bpc,
   337              ScanElem *channel_data, 
long table_start,
   338              int channel, 
int row) {
   339     ScanElem *temp = 
nullptr;
   343     short (*func)(istream *);
   344     func = (bpc==1) ? get_byte_as_short : get_big_short;
   347       temp = (ScanElem *)alloca(WORSTCOMPR(xsize) * 
sizeof(ScanElem));
   350     sgi_index = channel * ysize + row;
   352       offset = table[sgi_index].start;
   353       length = table[sgi_index].length;
   356       if(!ifp->seekg(offset))
   357         pm_error(
"seek error for offset %ld", offset);
   359       nassertv(length <= WORSTCOMPR(xsize));
   360       for( i = 0; i < length; i++ )
   361         temp[i] = (*func)(ifp);
   363       rle_decompress(temp, length, channel_data, xsize);
   366       offset = sgi_index * xsize + table_start;
   367       if(!ifp->seekg(offset))
   368         pm_error(
"seek error for offset %ld", offset);
   369       for( i = 0; i < xsize; i++ )
   370         channel_data[i] = (*func)(ifp);
   377 rle_decompress(ScanElem *src,
   385         el = (
unsigned char)(*src++ & 0xff);
   387         count = (int)(el & 0x7f);
   391         if( destleft < count )
   392             pm_error(
"RLE error: too much input data (space left %d, need %d)", destleft, count);
   395             if( srcleft < count )
   396                 pm_error(
"RLE error: not enough data for literal run (data left %d, need %d)", srcleft, count);
   403                 pm_error(
"RLE error: not enough data for replicate run");
   410     pm_error(
"RLE error: no terminating 0-byte");
   417 get_big_short(istream *ifp) {
   420     if( pm_readbigshort(ifp, &s) == -1 )
   427 get_big_long(istream *ifp) {
   430     if( pm_readbiglong(ifp, &l) == -1 )
   437 get_byte(istream *ifp) {
   444     return (
unsigned char) i;
   449 readerr(istream *f) {
   452       pnmimage_sgi_cat.warning()
   453         << 
"Read error on file.\n";
   455       pnmimage_sgi_cat.warning()
   456         << 
"Premature EOF on file.\n";
   466 read_bytes(istream *ifp,
   475       memset(buf+r, 0, n-r);
   482 get_byte_as_short(istream *ifp) {
   483     return (
short)get_byte(ifp);
   496         pm_error(
"out of memory allocating %d bytes", bytes);
   501 compression_name(
char compr) {
   503         case STORAGE_VERBATIM:
   512 #endif  // HAVE_SGI_RGB 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
This is the base class of a family of classes that represent particular image file types that PNMImag...
 
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
 
void pm_error(const char *format,...)
Outputs the given printf-style message to the user and terminates messily.
 
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.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
 
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.