---- Reported by dahie 2008-09-06 10:10:55 ---- Hello everybody! I've been working on some DirectDraw-Surface tools. For now, mostly simple stuff like texture loading, preview and MipMap generating, resaving. I used the DDSImage-class from JOGL as base for the File-Handling and using JSquish for DXT-(De)Compression. When I implemented automatic generated MipMaps I stumbled upon a possible bug in the DDSImage class. I hope this is the right place to address this, the bugtracker seemed kinda dead. Here is my scenario: I generate an array of ByteBuffers, which contain the pixel data. Each ByteBuffer is then compressed using a DXTn-method. This data-array is then given to the DDSImage class to create a new DDSImage-Object, which then can be written to disc. Code: DDSImage.createFromData(pixelformat, width, height, mipmapBufferArray); This gave me an IllegalArgumentException in the initFromData()-method saying, that the remaining data size for the lowest mipmaps exceeded the expected size. In fact the compressed buffer could never be smaller than 16kbyte (8kbyte DXT1). I did some research and found, that DXT-compressors always use the usual 8x8 pixel block for compression, even if the actual texture is smaller. So the resulting compressed block is always of this size. This is even hinted at the official DDS-Specification at MSDN So now what is the problem. The current implementation of the expected mipmap data size: Code: // Now check the mipmaps against this size int curSize = topmostMipmapSize; int totalSize = 0; for (int i = 0; i < mipmapData.length; i++) { if (mipmapData[i].remaining() != curSize) { throw new IllegalArgumentException("Mipmap level " + i + " didn't match expected data size (expected " + curSize + ", got " + mipmapData[i].remaining() + ")"); } curSize /= 4; totalSize += mipmapData[i].remaining(); } This always expects the datasize is 1/4 the size of the mipmap before. Works as far as MipMaps are bigger or equal 8x8 pixels. In that case it throughs my mentioned exception, as it expects the size to be smaller than it actually is. I did some patch job to fix this. Code: // Now check the mipmaps against this size int curSize = topmostMipmapSize; int mipmapWidth = width; int mipmapHeight = height; int totalSize = 0; for (int i = 0; i < mipmapData.length; i++) { if (mipmapData[i].remaining() != curSize) { throw new IllegalArgumentException("Mipmap level " + i + " didn't match expected data size (expected " + curSize + ", got " + mipmapData[i].remaining() + ")"); } /* Change * I got the problem, that MipMaps below the dimension of 8x8 blocks with DXTn * where assume smaller than they are created. * Assumed: smaller than 16byte where 16byte where used by the compression. */ if(isCompressed) { // size calculation for compressed mipmaps if(mipmapWidth > 1) mipmapWidth /= 2; if(mipmapHeight > 1) mipmapHeight /= 2; curSize = computeCompressedBlockSize(mipmapWidth, mipmapHeight, 1, d3dFormat); } else { curSize /= 4; } /* changes end */ totalSize += mipmapData[i].remaining(); } This patchjob is tested for saving DXT1-5 compressed files. I bet it could be done a bit nicer, but it does the job. I don't know if this can be classified as a bug, but I certainly think, the original behavour was not desired and could be fixed in future versions. So much from my part, hope this is patched in future releases. best regards, Dahie --- Bug imported by sgothel@jausoft.com 2010-03-24 07:51 EDT --- This bug was previously known as _bug_ 362 at https://jogl.dev.java.net/bugs/show_bug.cgi?id=362
Besides compression, the size calculation is incorrect for other mipmap sequences. The current calculation uses a divisor of 4, which is true for the difference between all mipmap levels except the smallest on occasion. The following sequence for example: 64x32 RGB Uncompressed DDS Image with generated mipmaps. 64x32 -> 6144 bytes 32x16 -> 1536 bytes 16x8 -> 384 bytes 8x4 -> 96 bytes 4x2 -> 24 bytes 2x1 -> 6 bytes 1x1 -> 3 bytes 6/4 != 3 Mipmap level 6 didn't match expected data size (expected 1, got 3)) Created patch and unit test. Ready for pull.
82d7bae212ad5a540a29003aaec8c7e026615f68 Fix Bug 362: calculated dimensions for MipMaps smaller than 16x16 Added method to calculate mipmap blocksize for uncompressed and DXTn images