Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/gobj/pixelBuffer.cxx

Go to the documentation of this file.
00001 // Filename: pixelBuffer.cxx
00002 // Created by:  mike (09Jan97)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "pixelBuffer.h"
00020 #include "config_gobj.h"
00021 
00022 ////////////////////////////////////////////////////////////////////
00023 // Static variables
00024 ////////////////////////////////////////////////////////////////////
00025 TypeHandle PixelBuffer::_type_handle;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: PixelBuffer::Constructor
00029 //       Access: Public
00030 //  Description:
00031 ////////////////////////////////////////////////////////////////////
00032 PixelBuffer::
00033 PixelBuffer(void) : ImageBuffer()
00034 {
00035   _xsize = 0;
00036   _ysize = 0;
00037   _xorg = 0;
00038   _yorg = 0;
00039   _border = 0;
00040   _format = F_rgb;
00041   _type = T_unsigned_byte;
00042   _components = 3;
00043   _component_width = 1;
00044   _image = PTA_uchar();
00045 
00046   _loaded = false;
00047 }
00048 
00049 ////////////////////////////////////////////////////////////////////
00050 //     Function: PixelBuffer::Constructor
00051 //       Access: Public
00052 //  Description:
00053 ////////////////////////////////////////////////////////////////////
00054 PixelBuffer::
00055 PixelBuffer(int xsize, int ysize, int components, int component_width,
00056             Type type, Format format) :
00057   ImageBuffer()
00058 {
00059   _xsize = xsize;
00060   _ysize = ysize;
00061   _xorg = 0;
00062   _yorg = 0;
00063   _border = 0;
00064   _components = components;
00065   _component_width = component_width;
00066   _type = type;
00067   _format = format;
00068   _image = PTA_uchar::empty_array((unsigned int)(_xsize * _ysize * _components * _component_width));
00069   _loaded = true;
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: PixelBuffer::Constructor
00074 //       Access: Public
00075 //  Description:  create a pixel buffer with specified format but do not alloc CPU RAM for it
00076 ////////////////////////////////////////////////////////////////////
00077 PixelBuffer::
00078 PixelBuffer(int xsize, int ysize, int components, int component_width, Type type, Format format,
00079             bool bAllocateRAM) : ImageBuffer()
00080 {
00081   _xsize = xsize;
00082   _ysize = ysize;
00083   _xorg = 0;
00084   _yorg = 0;
00085   _border = 0;
00086   _components = components;
00087   _component_width = component_width;
00088   _type = type;
00089   _format = format;
00090   if(bAllocateRAM)
00091     _image = PTA_uchar::empty_array((unsigned int)(_xsize * _ysize * _components * _component_width));
00092    else _image = PTA_uchar();
00093   _loaded = false;
00094 }
00095 
00096 ////////////////////////////////////////////////////////////////////
00097 //     Function: PixelBuffer::Copy Constructor
00098 //       Access: Public
00099 //  Description:
00100 ////////////////////////////////////////////////////////////////////
00101 PixelBuffer::
00102 PixelBuffer(const PixelBuffer &copy) :
00103   _xsize(copy._xsize),
00104   _ysize(copy._ysize),
00105   _xorg(copy._xorg),
00106   _yorg(copy._yorg),
00107   _border(copy._border),
00108   _components(copy._components),
00109   _component_width(copy._component_width),
00110   _format(copy._format),
00111   _type(copy._type),
00112   _loaded(copy._loaded),
00113   _image(copy._image)
00114 {
00115 }
00116 
00117 ////////////////////////////////////////////////////////////////////
00118 //     Function: PixelBuffer::Copy Assignment Operator
00119 //       Access: Public
00120 //  Description:
00121 ////////////////////////////////////////////////////////////////////
00122 void PixelBuffer::
00123 operator = (const PixelBuffer &copy) {
00124   _xsize = copy._xsize;
00125   _ysize = copy._ysize;
00126   _xorg = copy._xorg;
00127   _yorg = copy._yorg;
00128   _border = copy._border;
00129   _components = copy._components;
00130   _component_width = copy._component_width;
00131   _format = copy._format;
00132   _type = copy._type;
00133   _loaded = copy._loaded;
00134   _image = copy._image;
00135 }
00136 
00137 ////////////////////////////////////////////////////////////////////
00138 //     Function: config
00139 //       Access:
00140 //  Description:
00141 ////////////////////////////////////////////////////////////////////
00142 void PixelBuffer::config(void)
00143 {
00144   ImageBuffer::config();
00145 }
00146 
00147 ////////////////////////////////////////////////////////////////////
00148 //     Function: read
00149 //       Access:
00150 //  Description:
00151 ////////////////////////////////////////////////////////////////////
00152 bool PixelBuffer::
00153 read(const Filename &name) {
00154   PNMImage pnmimage;
00155 
00156   if (!pnmimage.read(name)) {
00157     gobj_cat.error()
00158       << "PixelBuffer::read() - couldn't read: " << name << endl;
00159     return false;
00160   }
00161 
00162   set_name(name.get_basename_wo_extension());
00163   set_filename(name);
00164   clear_alpha_filename();
00165   return load(pnmimage);
00166 }
00167 
00168 ////////////////////////////////////////////////////////////////////
00169 //     Function: write
00170 //       Access:
00171 //  Description:
00172 ////////////////////////////////////////////////////////////////////
00173 bool PixelBuffer::
00174 write(const Filename &name) const {
00175   PNMImage pnmimage;
00176   if (!store(pnmimage)) {
00177     return false;
00178   }
00179 
00180   Filename tname;
00181   if (name.empty()) {
00182     tname = get_filename();
00183   } else {
00184     tname = name;
00185   }
00186 
00187   if (!pnmimage.write(tname)) {
00188     gobj_cat.error()
00189       << "PixelBuffer::write() - couldn't write: " << name << endl;
00190     return false;
00191   }
00192   return true;
00193 }
00194 
00195 ////////////////////////////////////////////////////////////////////
00196 //     Function: load
00197 //       Access: Public
00198 //  Description: Extracts the image data from the given PNMImage and
00199 //               stores it in the _image member, as an unadorned array
00200 //               of pixel values.  Note that we now store pixel
00201 //               components in the order B, G, R, A.
00202 ////////////////////////////////////////////////////////////////////
00203 bool PixelBuffer::load(const PNMImage& pnmimage)
00204 {
00205   int num_components = pnmimage.get_num_channels();
00206 
00207   if (!_loaded || num_components != _components) {
00208     // Come up with a default format based on the number of channels.
00209     // But only do this the first time the file is loaded, or if the
00210     // number of channels in the image changes on subsequent loads.
00211 
00212     switch (pnmimage.get_color_type()) {
00213     case PNMImage::CT_grayscale:
00214       _format = F_luminance;
00215       break;
00216       
00217     case PNMImage::CT_two_channel:
00218       _format = F_luminance_alpha;
00219       break;
00220       
00221     case PNMImage::CT_color:
00222       _format = F_rgb;
00223       break;
00224       
00225     case PNMImage::CT_four_channel:
00226       _format = F_rgba;
00227       break;
00228       
00229     default:
00230       // Eh?
00231       nassertr(false, false);
00232       _format = F_rgb;
00233     };
00234   }
00235 
00236   _xsize = pnmimage.get_x_size();
00237   _ysize = pnmimage.get_y_size();
00238   _components = num_components;
00239   _loaded = true;
00240 
00241   // Now copy the pixel data from the PNMImage into our internal
00242   // _image component.
00243   bool has_alpha = pnmimage.has_alpha();
00244   bool is_grayscale = pnmimage.is_grayscale();
00245   xelval maxval = pnmimage.get_maxval();
00246     
00247   if (maxval == 255) {
00248     // Most common case: one byte per pixel, and the source image
00249     // shows a maxval of 255.  No scaling is necessary.
00250     _type = T_unsigned_byte;
00251     _image = PTA_uchar::empty_array((int)(_xsize * _ysize * _components));
00252     int idx = 0;
00253     
00254     for (int j = _ysize-1; j >= 0; j--) {
00255       for (int i = 0; i < _xsize; i++) {
00256         if (is_grayscale) {
00257           store_unscaled_byte(idx, pnmimage.get_gray_val(i, j));
00258         } else {
00259           store_unscaled_byte(idx, pnmimage.get_blue_val(i, j));
00260           store_unscaled_byte(idx, pnmimage.get_green_val(i, j));
00261           store_unscaled_byte(idx, pnmimage.get_red_val(i, j));
00262         }
00263         if (has_alpha) {
00264           store_unscaled_byte(idx, pnmimage.get_alpha_val(i, j));
00265         }
00266       }
00267     }
00268     
00269   } else if (maxval == 65535) {
00270     // Another possible case: two bytes per pixel, and the source
00271     // image shows a maxval of 65535.  Again, no scaling is necessary.
00272     _type = T_unsigned_short;
00273 //    _image = PTA_uchar::empty_array(_xsize * _ysize * _components * 2);
00274     int idx = 0;
00275     
00276     for (int j = _ysize-1; j >= 0; j--) {
00277       for (int i = 0; i < _xsize; i++) {
00278         if (is_grayscale) {
00279           store_unscaled_short(idx, pnmimage.get_gray_val(i, j));
00280         } else {
00281           store_unscaled_short(idx, pnmimage.get_blue_val(i, j));
00282           store_unscaled_short(idx, pnmimage.get_green_val(i, j));
00283           store_unscaled_short(idx, pnmimage.get_red_val(i, j));
00284         }
00285         if (has_alpha) {
00286           store_unscaled_short(idx, pnmimage.get_alpha_val(i, j));
00287         }
00288       }
00289     }
00290     
00291   } else if (maxval <= 255) {
00292     // A less common case: one byte per pixel, but the maxval is
00293     // something other than 255.  In this case, we should scale the
00294     // pixel values up to the appropriate amount.
00295     _type = T_unsigned_byte;
00296     _image = PTA_uchar::empty_array(_xsize * _ysize * _components);
00297     int idx = 0;
00298     double scale = 255.0 / (double)maxval;
00299     
00300     for (int j = _ysize-1; j >= 0; j--) {
00301       for (int i = 0; i < _xsize; i++) {
00302         if (is_grayscale) {
00303           store_scaled_byte(idx, pnmimage.get_gray_val(i, j), scale);
00304         } else {
00305           store_scaled_byte(idx, pnmimage.get_blue_val(i, j), scale);
00306           store_scaled_byte(idx, pnmimage.get_green_val(i, j), scale);
00307           store_scaled_byte(idx, pnmimage.get_red_val(i, j), scale);
00308         }
00309         if (has_alpha) {
00310           store_scaled_byte(idx, pnmimage.get_alpha_val(i, j), scale);
00311         }
00312       }
00313     }
00314     
00315   } else {
00316     // Another uncommon case: two bytes per pixel, and the maxval is
00317     // something other than 65535.  Again, we must scale the pixel
00318     // values.
00319     _type = T_unsigned_short;
00320     _image = PTA_uchar::empty_array(_xsize * _ysize * _components * 2);
00321     int idx = 0;
00322     double scale = 65535.0 / (double)maxval;
00323     
00324     for (int j = _ysize-1; j >= 0; j--) {
00325       for (int i = 0; i < _xsize; i++) {
00326         if (is_grayscale) {
00327           store_scaled_short(idx, pnmimage.get_gray_val(i, j), scale);
00328         } else {
00329           store_scaled_short(idx, pnmimage.get_blue_val(i, j), scale);
00330           store_scaled_short(idx, pnmimage.get_green_val(i, j), scale);
00331           store_scaled_short(idx, pnmimage.get_red_val(i, j), scale);
00332         }
00333         if (has_alpha) {
00334           store_scaled_short(idx, pnmimage.get_alpha_val(i, j), scale);
00335         }
00336       }
00337     }
00338   }
00339 
00340   config();
00341   return true;
00342 }
00343 
00344 
00345 ////////////////////////////////////////////////////////////////////
00346 //     Function: store
00347 //       Access:
00348 //  Description:
00349 ////////////////////////////////////////////////////////////////////
00350 bool PixelBuffer::
00351 store(PNMImage &pnmimage) const {
00352   if (_type == T_unsigned_byte) {
00353     pnmimage.clear(_xsize, _ysize, _components);
00354     bool has_alpha = pnmimage.has_alpha();
00355     bool is_grayscale = pnmimage.is_grayscale();
00356 
00357     int idx = 0;
00358     for (int j = _ysize-1; j >= 0; j--) {
00359       for (int i = 0; i < _xsize; i++) {
00360         if (is_grayscale) {
00361           pnmimage.set_gray(i, j, get_unsigned_byte(idx));
00362         } else {
00363           pnmimage.set_blue(i, j, get_unsigned_byte(idx));
00364           pnmimage.set_green(i, j, get_unsigned_byte(idx));
00365           pnmimage.set_red(i, j, get_unsigned_byte(idx));
00366         }
00367         if (has_alpha)
00368           pnmimage.set_alpha(i, j, get_unsigned_byte(idx));
00369       }
00370     }
00371     return true;
00372 
00373   } else if (_type == T_unsigned_short) {
00374     pnmimage.clear(_xsize, _ysize, _components, 65535);
00375     bool has_alpha = pnmimage.has_alpha();
00376     bool is_grayscale = pnmimage.is_grayscale();
00377 
00378     int idx = 0;
00379     for (int j = _ysize-1; j >= 0; j--) {
00380       for (int i = 0; i < _xsize; i++) {
00381         if (is_grayscale) {
00382           pnmimage.set_gray(i, j, get_unsigned_short(idx));
00383         } else {
00384           pnmimage.set_blue(i, j, get_unsigned_short(idx));
00385           pnmimage.set_green(i, j, get_unsigned_short(idx));
00386           pnmimage.set_red(i, j, get_unsigned_short(idx));
00387         }
00388         if (has_alpha)
00389           pnmimage.set_alpha(i, j, get_unsigned_short(idx));
00390       }
00391     }
00392     return true;
00393   }
00394 
00395   gobj_cat.error()
00396     << "Couldn't write image for " << get_name()
00397     << "; inappropriate type " << (int)_type << ".\n";
00398   return false;
00399 }
00400 
00401 ////////////////////////////////////////////////////////////////////
00402 //     Function: copy
00403 //       Access:
00404 //  Description: Deep copy of pixel buffer
00405 ////////////////////////////////////////////////////////////////////
00406 void PixelBuffer::
00407 copy(const PixelBuffer *pb) {
00408   nassertv(pb != NULL);
00409   _xorg = pb->_xorg;
00410   _yorg = pb->_yorg;
00411   _xsize = pb->_xsize;
00412   _ysize = pb->_ysize;
00413   _border = pb->_border;
00414   _components = pb->_components;
00415   _format = pb->_format;
00416   _image = PTA_uchar::empty_array(0);
00417   if (!pb->_image.empty())
00418     _image.v() = pb->_image.v();
00419 }
00420 
00421 void PixelBuffer::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr) {
00422   gsg->copy_pixel_buffer(this, dr);
00423 }
00424 
00425 void PixelBuffer::copy(GraphicsStateGuardianBase *gsg, const DisplayRegion *dr,
00426                        const RenderBuffer &rb) {
00427   gsg->copy_pixel_buffer(this, dr, rb);
00428 }
00429 

Generated on Fri May 2 00:39:41 2003 for Panda by doxygen1.3