From 06ba8994749ac515399eb3489b4018b342fcdc91 Mon Sep 17 00:00:00 2001
From: Turo Lamminen <turotl@gmail.com>
Date: Sat, 09 May 2015 14:47:08 +0000
Subject: [PATCH] Calculate miplevels from size if header says zero

---
 mojodds.c |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/mojodds.c b/mojodds.c
index c5e8124..6d69be5 100644
--- a/mojodds.c
+++ b/mojodds.c
@@ -104,6 +104,25 @@
 } MOJODDS_Header;
 
 
+//http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogDeBruijn
+static const uint32_t MultiplyDeBruijnBitPosition[32] =
+{
+  0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
+  8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
+};
+
+
+static uint32_t uintLog2(uint32_t v) {
+    v |= v >> 1; // first round down to one less than a power of 2
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+
+    return MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27];
+}
+
+
 static uint32 readui32(const uint8 **_ptr, size_t *_len)
 {
     uint32 retval = 0;
@@ -194,12 +213,18 @@
 
     *_miplevels = (header->dwCaps & DDSCAPS_MIPMAP) ? header->dwMipMapCount : 1;
 
+    unsigned int calculatedMipLevels = uintLog2(MAX(width, height)) + 1;
     if (*_miplevels > 32)
     {
         // too many mip levels, width and height would be larger than 32-bit int
         // file is corrupted
         return 0;
     }
+    else if (*_miplevels == 0)
+    {
+        // invalid, calculate it ourselves from size
+        *_miplevels = calculatedMipLevels;
+    }
 
     if (header->ddspf.dwFlags & DDPF_FOURCC)
     {

--
Gitblit v1.9.3