Browse Source

add support for uncompressed luminance and luminance-alpha dds files

David Rose 15 years ago
parent
commit
30155fb72e
2 changed files with 101 additions and 0 deletions
  1. 98 0
      panda/src/gobj/texture.cxx
  2. 3 0
      panda/src/gobj/texture.h

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

@@ -2776,6 +2776,12 @@ do_read_dds(istream &in, const string &filename, bool header_only) {
           header.pf.b_mask == 0x000000ff &&
           header.pf.a_mask == 0xff000000U) {
         func = read_dds_level_rgba8;
+
+      } else if (header.pf.r_mask != 0 && 
+                 header.pf.g_mask == 0 && 
+                 header.pf.b_mask == 0) {
+        func = read_dds_level_luminance_uncompressed;
+        format = F_luminance_alpha;
       }
     } else {
       // An uncompressed format that doesn't involve alpha.
@@ -2789,8 +2795,15 @@ do_read_dds(istream &in, const string &filename, bool header_only) {
                  header.pf.g_mask == 0x0000ff00 &&
                  header.pf.b_mask == 0x00ff0000) {
         func = read_dds_level_rgb8;
+
+      } else if (header.pf.r_mask != 0 && 
+                 header.pf.g_mask == 0 && 
+                 header.pf.b_mask == 0) {
+        func = read_dds_level_luminance_uncompressed;
+        format = F_luminance;
       }
     }
+      
   }
 
   do_setup_texture(texture_type, header.width, header.height, header.depth,
@@ -5074,6 +5087,91 @@ read_dds_level_generic_uncompressed(Texture *tex, const DDSHeader &header,
   return image;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::read_dds_level_luminance_uncompressed
+//       Access: Private, Static
+//  Description: Called by read_dds for a DDS file in uncompressed
+//               luminance or luminance-alpha format.
+////////////////////////////////////////////////////////////////////
+PTA_uchar Texture::
+read_dds_level_luminance_uncompressed(Texture *tex, const DDSHeader &header,
+                                      int n, istream &in) {
+  int x_size = tex->do_get_expected_mipmap_x_size(n);
+  int y_size = tex->do_get_expected_mipmap_y_size(n);
+
+  int pitch = (x_size * header.pf.rgb_bitcount) / 8;
+
+  // MS says the pitch can be supplied in the header file and must be
+  // DWORD aligned, but this appears to apply to level 0 mipmaps only
+  // (where it almost always will be anyway).  Other mipmap levels
+  // seem to be tightly packed, but there isn't a separate pitch for
+  // each mipmap level.  Weird.
+  if (n == 0) {
+    pitch = ((pitch + 3) / 4) * 4;
+    if (header.dds_flags & DDSD_PITCH) {
+      pitch = header.pitch;
+    }
+  }
+
+  int bpp = header.pf.rgb_bitcount / 8;
+  int skip_bytes = pitch - (bpp * x_size);
+  nassertr(skip_bytes >= 0, PTA_uchar());
+
+  unsigned int r_mask = header.pf.r_mask;
+  unsigned int a_mask = header.pf.a_mask;
+
+  // Determine the number of bits to shift each mask to the right so
+  // that the lowest on bit is at bit 0.
+  int r_shift = get_lowest_on_bit(r_mask);
+  int a_shift = get_lowest_on_bit(a_mask);
+
+  // Then determine the scale factor required to raise the highest
+  // color value to 0xff000000.
+  unsigned int r_scale = 0;
+  if (r_mask != 0) {
+    r_scale = 0xff000000 / (r_mask >> r_shift);
+  }
+  unsigned int a_scale = 0;
+  if (a_mask != 0) {
+    a_scale = 0xff000000 / (a_mask >> a_shift);
+  }
+
+  bool add_alpha = has_alpha(tex->_format);
+
+  size_t size = tex->do_get_expected_ram_mipmap_page_size(n);
+  size_t row_bytes = x_size * tex->_num_components;
+  PTA_uchar image = PTA_uchar::empty_array(size);
+  for (int y = y_size - 1; y >= 0; --y) {
+    unsigned char *p = image.p() + y * row_bytes;
+    for (int x = 0; x < x_size; ++x) {
+
+      // Read a little-endian numeric value of bpp bytes.
+      unsigned int pixel = 0;
+      int shift = 0;
+      for (int bi = 0; bi < bpp; ++bi) {
+        unsigned int ch = (unsigned char)in.get();
+        pixel |= (ch << shift);
+        shift += 8;
+      }
+
+      unsigned int r = (((pixel & r_mask) >> r_shift) * r_scale) >> 24;
+
+      // Store the components in the Texture's image data.
+      store_unscaled_byte(p, r);
+      if (add_alpha) {
+        unsigned int a = (((pixel & a_mask) >> a_shift) * a_scale) >> 24;
+        store_unscaled_byte(p, a);
+      }
+    }
+    nassertr(p <= image.p() + size, PTA_uchar());
+    for (int bi = 0; bi < skip_bytes; ++bi) {
+      in.get();
+    }
+  }
+
+  return image;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::read_dds_level_dxt1
 //       Access: Private, Static

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

@@ -591,6 +591,9 @@ private:
   static PTA_uchar read_dds_level_generic_uncompressed(Texture *tex, 
                                                        const DDSHeader &header, 
                                                        int n, istream &in);
+  static PTA_uchar read_dds_level_luminance_uncompressed(Texture *tex, 
+                                                         const DDSHeader &header, 
+                                                         int n, istream &in);
   static PTA_uchar read_dds_level_dxt1(Texture *tex, 
                                        const DDSHeader &header, 
                                        int n, istream &in);