Browse Source

TexturePeeker

David Rose 17 years ago
parent
commit
515c6cd83a

+ 5 - 1
panda/src/gobj/Sources.pp

@@ -55,6 +55,7 @@
     sliderTable.I sliderTable.h \
     texture.I texture.h \
     textureContext.I textureContext.h \
+    texturePeeker.I texturePeeker.h \
     texturePool.I texturePool.h \
     texturePoolFilter.I texturePoolFilter.h \
     textureStage.I textureStage.h \
@@ -116,7 +117,9 @@
     simpleAllocator.cxx \
     simpleLru.cxx \
     sliderTable.cxx \
-    texture.cxx textureContext.cxx texturePool.cxx \
+    texture.cxx textureContext.cxx \
+    texturePeeker.cxx \
+    texturePool.cxx \
     texturePoolFilter.cxx \
     textureStage.cxx \
     transformBlend.cxx \
@@ -181,6 +184,7 @@
     sliderTable.I sliderTable.h \
     texture.I texture.h \
     textureContext.I textureContext.h \
+    texturePeeker.I texturePeeker.h \
     texturePool.I texturePool.h \
     texturePoolFilter.I texturePoolFilter.h \
     textureStage.I textureStage.h \

+ 1 - 0
panda/src/gobj/gobj_composite2.cxx

@@ -14,6 +14,7 @@
 #include "sliderTable.cxx"
 #include "texture.cxx"
 #include "textureContext.cxx"
+#include "texturePeeker.cxx"
 #include "texturePool.cxx"
 #include "texturePoolFilter.cxx"
 #include "textureStage.cxx"

+ 29 - 0
panda/src/gobj/texture.cxx

@@ -37,6 +37,7 @@
 #include "pStatTimer.h"
 #include "pbitops.h"
 #include "streamReader.h"
+#include "texturePeeker.h"
 
 #include <stddef.h>
 
@@ -1946,6 +1947,34 @@ clear_simple_ram_image() {
   ++_simple_image_modified;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::peek
+//       Access: Published
+//  Description: Returns a TexturePeeker object that can be used to
+//               examine the individual texels stored within this
+//               Texture by (u, v) coordinate.
+//
+//               If the texture has a ram image resident, that image
+//               is used.  If it does not have a full ram image but
+//               does have a simple_ram_image resident, that image is
+//               used instead.  If neither image is resident the full
+//               image is reloaded.
+//
+//               Returns NULL if the texture cannot find an image to
+//               load, or the texture format is incompatible.
+////////////////////////////////////////////////////////////////////
+PT(TexturePeeker) Texture::
+peek() {
+  ReMutexHolder holder(_lock);
+
+  PT(TexturePeeker) peeker = new TexturePeeker(this);
+  if (peeker->is_valid()) {
+    return peeker;
+  }
+
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::prepare
 //       Access: Published

+ 4 - 0
panda/src/gobj/texture.h

@@ -38,6 +38,7 @@ class PreparedGraphicsObjects;
 class CullTraverser;
 class CullTraverserData;
 class BamCacheRecord;
+class TexturePeeker;
 struct DDSHeader;
 
 ////////////////////////////////////////////////////////////////////
@@ -337,6 +338,8 @@ PUBLISHED:
   void generate_simple_ram_image();
   void clear_simple_ram_image();
 
+  PT(TexturePeeker) peek();
+
   INLINE UpdateSeq get_properties_modified() const;
   INLINE UpdateSeq get_image_modified() const;
   INLINE UpdateSeq get_simple_image_modified() const;
@@ -670,6 +673,7 @@ private:
   friend class TextureContext;
   friend class PreparedGraphicsObjects;
   friend class TexturePool;
+  friend class TexturePeeker;
 };
 
 extern EXPCL_PANDA_GOBJ ConfigVariableEnum<Texture::QualityLevel> texture_quality_level;

+ 64 - 0
panda/src/gobj/texturePeeker.I

@@ -0,0 +1,64 @@
+// Filename: texturePeeker.I
+// Created by:  drose (26Aug08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::is_valid
+//       Access: Public
+//  Description: Returns true if the TexturePeeker was able to
+//               initialize itself and is ready to return texel
+//               colors.
+////////////////////////////////////////////////////////////////////
+INLINE bool TexturePeeker::
+is_valid() const {
+  return !_image.is_null();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_x_size
+//       Access: Published
+//  Description: Returns the width of the texture image that is
+//               contributing to the TexturePeeker's information.
+//               This may be either the Texture's full width, or its
+//               simple ram image's width.
+////////////////////////////////////////////////////////////////////
+INLINE int TexturePeeker::
+get_x_size() const {
+  return _x_size;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_y_size
+//       Access: Published
+//  Description: Returns the height of the texture image that is
+//               contributing to the TexturePeeker's information.
+//               This may be either the Texture's full height, or its
+//               simple ram image's height.
+////////////////////////////////////////////////////////////////////
+INLINE int TexturePeeker::
+get_y_size() const {
+  return _y_size;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_z_size
+//       Access: Published
+//  Description: Returns the depth of the texture image that is
+//               contributing to the TexturePeeker's information.
+////////////////////////////////////////////////////////////////////
+INLINE int TexturePeeker::
+get_z_size() const {
+  return _z_size;
+}
+

+ 521 - 0
panda/src/gobj/texturePeeker.cxx

@@ -0,0 +1,521 @@
+// Filename: texturePeeker.cxx
+// Created by:  drose (26Aug08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "texturePeeker.h"
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::Constructor
+//       Access: Private
+//  Description: Use Texture::peek() to construct a TexturePeeker.
+////////////////////////////////////////////////////////////////////
+TexturePeeker::
+TexturePeeker(Texture *tex) {
+  _x_size = tex->_x_size;
+  _y_size = tex->_y_size;
+  _z_size = tex->_z_size;
+  _component_width = tex->_component_width;
+  _num_components = tex->_num_components;
+  _format = tex->_format;
+  _component_type = tex->_component_type;
+
+  if (tex->_texture_type == Texture::TT_cube_map) {
+    // Cube map texture.  We'll need to map from (u, v, w) to (u, v)
+    // within the appropriate page, where w indicates the page.
+
+    // TODO: handle cube maps.
+    return;
+
+  } else {
+    // Regular 1-d, 2-d, or 3-d texture.  The coordinates map
+    // directly.  Simple ram images are possible if it is a 2-d
+    // texture.
+    if (!(tex->has_ram_image() && tex->get_ram_image_compression() == Texture::CM_off) && tex->has_simple_ram_image()) {
+      _image = tex->_simple_ram_image._image;
+      _x_size = tex->_simple_x_size;
+      _y_size = tex->_simple_y_size;
+      _z_size = 1;
+
+      _component_width = 1;
+      _num_components = 4;
+      _format = Texture::F_rgba;
+      _component_type = Texture::T_unsigned_byte;
+
+    } else {
+      _image = tex->get_uncompressed_ram_image();
+    }
+  }
+
+  if (_image.is_null()) {
+    return;
+  }
+  _pixel_width = _component_width * _num_components;
+
+  switch (_component_type) {
+  case Texture::T_unsigned_byte:
+    _get_component = Texture::get_unsigned_byte;
+    break;
+
+  case Texture::T_unsigned_short:
+    _get_component = Texture::get_unsigned_short;
+    break;
+
+  case Texture::T_float:
+    // Not supported.
+    _image.clear();
+    return;
+  }
+
+  switch (_format) {
+  case Texture::F_depth_stencil:
+  case Texture::F_color_index:
+    // Not supported.
+    _image.clear();
+    return;
+
+  case Texture::F_red:
+    _get_texel = get_texel_r;
+    break;
+
+  case Texture::F_green:
+    _get_texel = get_texel_g;
+    break;
+
+  case Texture::F_blue:
+    _get_texel = get_texel_b;
+    break;
+
+  case Texture::F_alpha:
+    _get_texel = get_texel_a;
+    break;
+
+  case Texture::F_luminance:
+    _get_texel = get_texel_l;
+    break;
+
+  case Texture::F_luminance_alpha:
+  case Texture::F_luminance_alphamask:
+    _get_texel = get_texel_la;
+    break;
+
+  case Texture::F_rgb:
+  case Texture::F_rgb5:
+  case Texture::F_rgb8:
+  case Texture::F_rgb12:
+  case Texture::F_rgb332:
+    _get_texel = get_texel_rgb;
+    break;
+
+  case Texture::F_rgba:
+  case Texture::F_rgbm:
+  case Texture::F_rgba4:
+  case Texture::F_rgba5:
+  case Texture::F_rgba8:
+  case Texture::F_rgba12:
+  case Texture::F_rgba16:
+  case Texture::F_rgba32:
+    _get_texel = get_texel_rgba;
+    break;
+  }    
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::lookup
+//       Access: Published
+//  Description: Fills "color" with the RGBA color of the texel at
+//               point (u, v).
+//
+//               The texel color is determined via nearest-point
+//               sampling (no filtering of adjacent pixels),
+//               regardless of the filter type associated with the
+//               texture.  u, v, and w will wrap around regardless of
+//               the texture's wrap mode.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+lookup(Colorf &color, float u, float v) const {
+  int x = int((u - cfloor(u)) * (float)_x_size + 0.5f) % _x_size;
+  int y = int((v - cfloor(v)) * (float)_y_size + 0.5f) % _y_size;
+
+  const unsigned char *p = _image.p() + (y * _x_size + x) * _pixel_width;
+
+  (*_get_texel)(color, p, _get_component);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::lookup
+//       Access: Published
+//  Description: Fills "color" with the RGBA color of the texel at
+//               point (u, v, w).
+//
+//               The texel color is determined via nearest-point
+//               sampling (no filtering of adjacent pixels),
+//               regardless of the filter type associated with the
+//               texture.  u, v, and w will wrap around regardless of
+//               the texture's wrap mode.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+lookup(Colorf &color, float u, float v, float w) const {
+  int x = int((u - cfloor(u)) * (float)_x_size + 0.5f) % _x_size;
+  int y = int((v - cfloor(v)) * (float)_y_size + 0.5f) % _y_size;
+  int z = int((w - cfloor(w)) * (float)_z_size + 0.5f) % _z_size;
+
+  const unsigned char *p = _image.p() + (z * _x_size * _y_size + y * _x_size + x) * _pixel_width;
+
+  (*_get_texel)(color, p, _get_component);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::filter_rect
+//       Access: Published
+//  Description: Fills "color" with the average RGBA color of the
+//               texels within the rectangle defined by the specified
+//               coordinate range.
+//
+//               The texel color is linearly filtered over the entire
+//               region.  u, v, and w will wrap around regardless of
+//               the texture's wrap mode.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+filter_rect(Colorf &color, 
+            float min_u, float min_v, float max_u, float max_v) const {
+  int min_x, max_x;
+  init_rect_minmax(min_x, max_x, min_u, max_u, _x_size);
+
+  int min_y, max_y;
+  init_rect_minmax(min_y, max_y, min_v, max_v, _y_size);
+
+  color.set(0.0f, 0.0f, 0.0f, 0.0f);
+  float net = 0.0f;
+  accum_filter_y(color, net, 0,
+                 min_x, max_x, min_u, max_u,
+                 min_y, max_y, min_v, max_v, 
+                 1.0f);
+
+  if (net != 0.0f) {
+    color /= net;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::filter_rect
+//       Access: Published
+//  Description: Fills "color" with the average RGBA color of the
+//               texels within the rectangle defined by the specified
+//               coordinate range.
+//
+//               The texel color is linearly filtered over the entire
+//               region.  u, v, and w will wrap around regardless of
+//               the texture's wrap mode.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+filter_rect(Colorf &color, 
+            float min_u, float min_v, float min_w,
+            float max_u, float max_v, float max_w) const {
+  int min_x, max_x;
+  init_rect_minmax(min_x, max_x, min_u, max_u, _x_size);
+
+  int min_y, max_y;
+  init_rect_minmax(min_y, max_y, min_v, max_v, _y_size);
+
+  int min_z, max_z;
+  init_rect_minmax(min_z, max_z, min_w, max_w, _z_size);
+
+  color.set(0.0f, 0.0f, 0.0f, 0.0f);
+  float net = 0.0f;
+  accum_filter_z(color, net,
+                 min_x, max_x, min_u, max_u,
+                 min_y, max_y, min_v, max_v,
+                 min_z, max_z, min_w, max_w);
+
+  if (net != 0.0f) {
+    color /= net;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::init_rect_minmax
+//       Access: Private, Static
+//  Description: Sanity-checks min_u, max_u and computes min_x and
+//               min_y based on them.  Also works for y and z.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+init_rect_minmax(int &min_x, int &max_x, float &min_u, float &max_u,
+                 int x_size) {
+  if (min_u > max_u) {
+    float t = min_u;
+    min_u = max_u;
+    max_u = t;
+  }
+  if (max_u - min_u >= 1.0f) {
+    min_u = 0.0f;
+    max_u = 1.0f;
+  }
+  min_x = (int)cfloor(min_u * (float)x_size);
+  max_x = (int)cceil(max_u * (float)x_size);
+  nassertv(min_x <= max_x);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::accum_filter_z
+//       Access: Private
+//  Description: Accumulates the range of pixels from min_z to max_z.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+accum_filter_z(Colorf &color, float &net,
+               int min_x, int max_x, float min_u, float max_u,
+               int min_y, int max_y, float min_v, float max_v,
+               int min_z, int max_z, float min_w, float max_w) const {
+  int zi = min_z;
+
+  if (min_z >= max_z - 1) {
+    // Within a single texel.
+    accum_filter_y(color, net, zi % _z_size, 
+                   min_x, max_x, min_u, max_u,
+                   min_y, max_y, min_v, max_v,
+                   1.0f);
+
+  } else {
+    // First part-texel.
+    float w = (min_z + 1) - min_w * _z_size;
+    accum_filter_y(color, net, zi % _z_size, 
+                   min_x, max_x, min_u, max_u,
+                   min_y, max_y, min_v, max_v,
+                   w);
+    int zs = max_z - 1;
+    
+    // Run of full texels.
+    zi = min_z + 1;
+    while (zi < zs) {
+      accum_filter_y(color, net, zi % _z_size, 
+                     min_x, max_x, min_u, max_u,
+                     min_y, max_y, min_v, max_v,
+                     1.0f);
+      ++zi;
+    }
+    
+    // Last part-texel.
+    w = max_w * _z_size - (max_z - 1);
+    accum_filter_y(color, net, zi % _z_size, 
+                   min_x, max_x, min_u, max_u,
+                   min_y, max_y, min_v, max_v,
+                   w);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::accum_filter_y
+//       Access: Private
+//  Description: Accumulates the range of pixels from min_y to max_y.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+accum_filter_y(Colorf &color, float &net, int zi,
+               int min_x, int max_x, float min_u, float max_u,
+               int min_y, int max_y, float min_v, float max_v,
+               float weight) const {
+  int yi = min_y;
+
+  if (min_y >= max_y - 1) {
+    // Within a single texel.
+    accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight);
+
+  } else {
+    // First part-texel.
+    float w = (min_y + 1) - min_v * _y_size;
+    accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight * w);
+    int ys = max_y - 1;
+    
+    // Run of full texels.
+    yi = min_y + 1;
+    while (yi < ys) {
+      accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight);
+      ++yi;
+    }
+    
+    // Last part-texel.
+    w = max_v * _y_size - (max_y - 1);
+    accum_filter_x(color, net, yi % _y_size, zi, min_x, max_x, min_u, max_u, weight * w);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::accum_filter_x
+//       Access: Private
+//  Description: Accumulates the range of pixels from min_x to max_x.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+accum_filter_x(Colorf &color, float &net, int yi, int zi,
+               int min_x, int max_x, float min_u, float max_u,
+               float weight) const {
+  // Compute the p corresponding to min_x.
+  int xi = min_x % _x_size;
+  const unsigned char *p = _image.p() + (zi * _x_size * _y_size + yi * _x_size + xi) * _pixel_width;
+
+  if (min_x >= max_x - 1) {
+    // Within a single texel.
+    accum_texel(color, net, p, weight);
+
+  } else {
+    // First part-texel.
+    float w = (min_x + 1) - min_u * _x_size;
+    accum_texel(color, net, p, weight * w);
+    int xs = max_x - 1;
+    
+    // Run of full texels.
+    xi = min_x + 1;
+    while (xi < xs) {
+      if (xi == _x_size) {
+        xi = 0;
+        p = _image.p() + (zi * _x_size * _y_size + yi * _x_size + xi) * _pixel_width;
+        xs -= _x_size;
+      }
+      accum_texel(color, net, p, weight);
+      ++xi;
+    }
+    
+    // Last part-texel.
+    if (xi == _x_size) {
+      xi = 0;
+      p = _image.p() + (zi * _x_size * _y_size + yi * _x_size + xi) * _pixel_width;
+    }
+    w = max_u * _x_size - (max_x - 1);
+    accum_texel(color, net, p, weight * w);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::accum_texel
+//       Access: Private
+//  Description: Accumulates a single texel into the total computed by
+//               filter_rect().
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+accum_texel(Colorf &color, float &net, const unsigned char *&p, float weight) const {
+  Colorf c;
+  (*_get_texel)(c, p, _get_component);
+  color += c * weight;
+  net += weight;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_texel_r
+//       Access: Private, Static
+//  Description: Gets the color of the texel at byte p, given that the
+//               texture is in format F_red.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+get_texel_r(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) {
+  color[0] = (*get_component)(p);
+  color[1] = 0.0f;
+  color[2] = 0.0f;
+  color[3] = 1.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_texel_g
+//       Access: Private, Static
+//  Description: Gets the color of the texel at byte p, given that the
+//               texture is in format F_green.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+get_texel_g(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) {
+  color[0] = 0.0f;
+  color[1] = (*get_component)(p);
+  color[2] = 0.0f;
+  color[3] = 1.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_texel_b
+//       Access: Private, Static
+//  Description: Gets the color of the texel at byte p, given that the
+//               texture is in format F_blue.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+get_texel_b(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) {
+  color[0] = 0.0f;
+  color[1] = 0.0f;
+  color[2] = (*get_component)(p);
+  color[3] = 1.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_texel_a
+//       Access: Private, Static
+//  Description: Gets the color of the texel at byte p, given that the
+//               texture is in format F_alpha.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+get_texel_a(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) {
+  color[0] = 0.0f;
+  color[1] = 0.0f;
+  color[2] = 1.0f;
+  color[3] = (*get_component)(p);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_texel_l
+//       Access: Private, Static
+//  Description: Gets the color of the texel at byte p, given that the
+//               texture is in format F_luminance.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+get_texel_l(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) {
+  color[0] = (*get_component)(p);
+  color[1] = color[0];
+  color[2] = color[0];
+  color[3] = 1.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_texel_la
+//       Access: Private, Static
+//  Description: Gets the color of the texel at byte p, given that the
+//               texture is in format F_luminance_alpha or similar.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+get_texel_la(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) {
+  color[0] = (*get_component)(p);
+  color[1] = color[0];
+  color[2] = color[0];
+  color[3] = (*get_component)(p);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_texel_rgb
+//       Access: Private, Static
+//  Description: Gets the color of the texel at byte p, given that the
+//               texture is in format F_rgb or similar.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+get_texel_rgb(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) {
+  color[2] = (*get_component)(p);
+  color[1] = (*get_component)(p);
+  color[0] = (*get_component)(p);
+  color[3] = 1.0f;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TexturePeeker::get_texel_rgba
+//       Access: Private, Static
+//  Description: Gets the color of the texel at byte p, given that the
+//               texture is in format F_rgba or similar.
+////////////////////////////////////////////////////////////////////
+void TexturePeeker::
+get_texel_rgba(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component) {
+  color[2] = (*get_component)(p);
+  color[1] = (*get_component)(p);
+  color[0] = (*get_component)(p);
+  color[3] = (*get_component)(p);
+}

+ 102 - 0
panda/src/gobj/texturePeeker.h

@@ -0,0 +1,102 @@
+// Filename: texturePeeker.h
+// Created by:  drose (26Aug08)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) Carnegie Mellon University.  All rights reserved.
+//
+// All use of this software is subject to the terms of the revised BSD
+// license.  You should have received a copy of this license along
+// with this source code in a file named "LICENSE."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef TEXTUREPEEKER_H
+#define TEXTUREPEEKER_H
+
+#include "pandabase.h"
+
+#include "referenceCount.h"
+#include "texture.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : TexturePeeker
+// Description : An instance of this object is returned by
+//               Texture::peek().  This object allows quick and easy
+//               inspection of a texture's texels by (u, v)
+//               coordinates.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA_GOBJ TexturePeeker : public ReferenceCount {
+private:
+  TexturePeeker(Texture *tex);
+
+public:
+  INLINE bool is_valid() const;
+
+PUBLISHED:
+  INLINE int get_x_size() const;
+  INLINE int get_y_size() const;
+  INLINE int get_z_size() const;
+
+  void lookup(Colorf &color, float u, float v) const;
+  void lookup(Colorf &color, float u, float v, float w) const;
+  void filter_rect(Colorf &color, 
+                   float min_u, float min_v, 
+                   float max_u, float max_v) const;
+  void filter_rect(Colorf &color, 
+                   float min_u, float min_v, float min_w,
+                   float max_u, float max_v, float max_w) const;
+
+private:
+  static void init_rect_minmax(int &min_x, int &max_x, 
+                               float &min_u, float &max_u,
+                               int x_size);
+
+  void accum_filter_z(Colorf &color, float &net,
+                      int min_x, int max_x, float min_u, float max_u,
+                      int min_y, int max_y, float min_v, float max_v,
+                      int min_z, int max_z, float min_w, float max_w) const;
+  void accum_filter_y(Colorf &color, float &net, int zi,
+                      int min_x, int max_x, float min_u, float max_u,
+                      int min_y, int max_y, float min_v, float max_v,
+                      float weight) const;
+  void accum_filter_x(Colorf &color, float &net, int yi, int zi,
+                      int min_x, int max_x, float min_u, float max_u,
+                      float weight) const;
+  void accum_texel(Colorf &color, float &net, const unsigned char *&p, 
+                   float weight) const;
+
+  typedef double GetComponentFunc(const unsigned char *&p);
+  typedef void GetTexelFunc(Colorf &color, const unsigned char *&p,
+                            GetComponentFunc *get_component);
+
+  static void get_texel_r(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component);
+  static void get_texel_g(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component);
+  static void get_texel_b(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component);
+  static void get_texel_a(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component);
+  static void get_texel_l(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component);
+  static void get_texel_la(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component);
+  static void get_texel_rgb(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component);
+  static void get_texel_rgba(Colorf &color, const unsigned char *&p, GetComponentFunc *get_component);
+  
+  int _x_size;
+  int _y_size;
+  int _z_size;
+  int _component_width;
+  int _num_components;
+  int _pixel_width;
+  Texture::Format _format;
+  Texture::ComponentType _component_type;
+  CPTA_uchar _image;
+
+  GetComponentFunc *_get_component;
+  GetTexelFunc *_get_texel;
+
+  friend class Texture;
+};
+
+#include "texturePeeker.I"
+
+#endif
+