Skip to content

Commit

Permalink
Merge pull request sgothel#76 from esemplare/master
Browse files Browse the repository at this point in the history
Fix Bug 362: calculated dimensions for MipMaps smaller than 16x16
  • Loading branch information
sgothel committed Dec 15, 2013
2 parents ccfc9b5 + 82d7bae commit 82927b0
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -766,14 +766,19 @@ private void initFromData(int d3dFormat,

// 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() + ")");
}
curSize /= 4;
// Compute next mipmap size
if (mipmapWidth > 1) mipmapWidth /= 2;
if (mipmapHeight > 1) mipmapHeight /= 2;
curSize = computeBlockSize(mipmapWidth, mipmapHeight, 1, d3dFormat);
totalSize += mipmapData[i].remaining();
}

Expand Down Expand Up @@ -852,6 +857,32 @@ private static int computeCompressedBlockSize(int width,
return blockSize;
}

private static int computeBlockSize(int width,
int height,
int depth,
int pixelFormat) {
int blocksize;
switch (pixelFormat) {
case D3DFMT_R8G8B8:
blocksize = width*height*3;
break;
case D3DFMT_A8R8G8B8:
case D3DFMT_X8R8G8B8:
blocksize = width*height*4;
break;
case D3DFMT_DXT1:
case D3DFMT_DXT2:
case D3DFMT_DXT3:
case D3DFMT_DXT4:
case D3DFMT_DXT5:
blocksize = computeCompressedBlockSize(width, height, 1, pixelFormat);
break;
default:
throw new IllegalArgumentException("d3dFormat must be one of the known formats");
}
return blocksize;
}

private int mipMapWidth(int map) {
int width = getWidth();
for (int i = 0; i < map; i++) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.jogamp.opengl.test.junit.jogl.util.texture;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.jogamp.common.util.IOUtil;
import com.jogamp.opengl.util.texture.spi.DDSImage;
import com.jogamp.opengl.util.texture.spi.DDSImage.ImageInfo;

/**
* This test uses the DDSImage class to read a dds image from file, extract the data,
* and use the class to create a new DDSImage from the extracted data
* <br></br>
* Bug Reference: https://jogamp.org/bugzilla/show_bug.cgi?id=362
* <br></br>
* The bug pertains to incorrect size calculation for checking validity of data. Compressed DXT1 has min of 8 bytes, DXT5 has min of 16 bytes.
* It exists in {@link DDSImage#createFromData(int, int, int, ByteBuffer[])}
* where an {@link IllegalArgumentException} is thrown for Mipmap level size mismatch.
* <br></br>
* <ul>The following cases are tested:
* <li>Uncompressed 64x32 RGB DDS Image with all mipmap levels (64x32 --> 1x1)</li>
* <li>DXT1 compressed 64x32 RGB DDS Image with all mipmap levels (64x32 --> 1x1)</li>
* <li>DXT5 compressed 64x32 RGB DDS Image with all mipmap levels (64x32 --> 1x1)</li>
* </ul>
*
* @author Michael Esemplare
*
*/
public class TestBug362DDSImageCreateFromData {

File testDDSImage01Uncompressed;
File testDDSImage02DXT1;
File testDDSImage03DXT5;

@Before
public void setup() throws Throwable {
testDDSImage01Uncompressed = initFile("test-64x32_uncompressed.dds");
testDDSImage02DXT1 = initFile("test-64x32_DXT1.dds");
testDDSImage03DXT5 = initFile("test-64x32_DXT5.dds");
}

@After
public void teardown() {
testDDSImage01Uncompressed = null;
testDDSImage02DXT1 = null;
testDDSImage03DXT5 = null;
}

private File initFile(String filename) throws URISyntaxException {
URLConnection connection = IOUtil.getResource(getClass(), filename);
Assert.assertNotNull(connection);
URL url = connection.getURL();
File file = new File(url.toURI());
Assert.assertTrue(file.exists());
return file;
}

private void testImpl(File file) throws IOException {
DDSImage ddsImage = DDSImage.read(file);
Assert.assertNotNull(ddsImage);
int numMipMaps = ddsImage.getNumMipMaps();
ByteBuffer[] mipMapArray = new ByteBuffer[numMipMaps];
for (int i=0;i<numMipMaps;i++){
ImageInfo info = ddsImage.getMipMap(i);
mipMapArray[i] = info.getData();
}
DDSImage newImage = DDSImage.createFromData(ddsImage.getPixelFormat(), ddsImage.getWidth(), ddsImage.getHeight(), mipMapArray);
Assert.assertNotNull(newImage);
}

@Test
public void test00_DDSImage_CreateFromData_Uncompressed_RGB () throws IOException {
testImpl(testDDSImage01Uncompressed);
}

@Test
public void test01_DDSImage_CreateFromData_DXT1_RGB () throws IOException {
testImpl(testDDSImage02DXT1);
}

@Test
public void test02_DDSImage_CreateFromData_DXT5_RGB () throws IOException {
testImpl(testDDSImage03DXT5);
}

public static void main(String[] args) {
org.junit.runner.JUnitCore.main(TestBug362DDSImageCreateFromData.class.getName());
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 82927b0

Please sign in to comment.