/DDSReader

DDS image reader for Java and C.

Primary LanguageCMIT LicenseMIT

DDSReader

DDS image reader for Java and C.

alt text

Online DDS Canvas Demo page is http://npe-net.appspot.com/npesdk/gwt/ddsimagedemo/index.html

alt text

Online DDS WebGL Texture Demo page is http://npe-net.appspot.com/npesdk/gwt/ddswebgldemo/index.html

License

Released under the MIT license.

https://github.com/npedotnet/DDSReader/blob/master/LICENSE

Getting Started

1. Add the source code to your project.

Java

  • Add src/java/DDSReader.java to your project, and modify package statement.

C

  • Add src/c/dds_reader.{c,h} to your project.

2. Create a DDS binary data buffer.

Java

	FileInputStream fis = new FileInputStream(new File("test.dds"));
	byte [] buffer = new byte[fis.available()];
	fis.read(buffer);
	fis.close();

C

#include "dds_reader.h"

FILE *file = fopen("test.dds", "rb");
if(file) {
	int size;
	fseek(file, 0, SEEK_END);
	size = ftell(file);
	fseek(file, 0, SEEK_SET);

	unsigned char *buffer = (unsigned char *)ddsMalloc(size);
	fread(buffer, 1, size, file);
	fclose(file);
}

3. Create pixels with the RGBA byte order and mipmap parameter.

ByteOrder Java C Comments
ARGB DDSReader.ARGB DDS_READER_ARGB for java.awt.image.BufferedImage, android.graphics.Bitmap
ABGR DDSReader.ABGR DDS_READER_ABGR for OpenGL Texture(GL_RGBA), iOS UIImage

Java

	byte [] buffer = ...;
	int [] pixels = DDSReader.read(buffer, DDSReader.ARGB, 0);
	int width = DDSReader.getWidth(buffer);
	int height = DDSReader.getHeight(buffer);

C

	unsigned char *buffer = ...;
	int *pixels = ddsRead(buffer, DDS_READER_ABGR, 0);
	int width = ddsGetWidth(buffer);
	int height = ddsGetHeight(buffer);

4. Use created pixels in your application.

4.1. Java OpenGL Application

Sample code to create Java OpenGL texture.

Java

	public int createDDSTexture() {
		int texture = 0;
	
		try {
			FileInputStream fis = new FileInputStream(path);
			byte [] buffer = new byte[fis.available()];
			fis.read(buffer);
			fis.close();

			int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, 0);
			int width = DDSReader.getWidth(buffer);
			int height = DDSReader.getHeight(buffer);
			int mipmap = DDSReader.getMipmap(buffer);

			int [] textures = new int[1];
			gl.glGenTextures(1, textures, 0);

			gl.glEnable(GL.TEXTURE_2D);
			gl.glBindTexture(GL.TEXTURE_2D, textures[0]);
			gl.glPixelStorei(GL.UNPACK_ALIGNMENT, 4);

			if(mipmap > 0) {
				// mipmaps
				for(int i=0; (width > 0) || (height > 0); i++) {
					if(width <= 0) width = 1;
					if(height <= 0) height = 1;
					int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, i);
	
					IntBuffer texBuffer = IntBuffer.wrap(pixels);
					gl.glTexImage2D(TEXTURE_2D, i, RGBA, width, height, 0, RGBA, UNSIGNED_BYTE, texBuffer);
	
					width /= 2;
					height /= 2;
				}
	
				gl.glTexParameteri(TEXTURE_2D, TEXTURE_WRAP_S, REPEAT);
				gl.glTexParameteri(TEXTURE_2D, TEXTURE_WRAP_T, REPEAT);
				gl.glTexParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, LINEAR);
				gl.glTexParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR_MIPMAP_NEAREST);
			}
			else {
				// no mipmaps
				int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, 0);
	
				IntBuffer texBuffer = IntBuffer.wrap(pixels);
				gl.glTexImage2D(TEXTURE_2D, 0, RGBA, width, height, 0, RGBA, UNSIGNED_BYTE, texBuffer);
	
				gl.glTexParameteri(TEXTURE_2D, TEXTURE_WRAP_S, REPEAT);
				gl.glTexParameteri(TEXTURE_2D, TEXTURE_WRAP_T, REPEAT);
				gl.glTexParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, LINEAR);
				gl.glTexParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR);

			}
	        
			texture = textures[0];
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	
		return texture;
	}

4.2. Java Application

Sample code to create java.awt.image.BufferedImage.

Java

    private static JLabel createDDSLabel(String path) throws IOException {

        FileInputStream fis = new FileInputStream(path);
        byte [] buffer = new byte[fis.available()];
        fis.read(buffer);
        fis.close();

        int [] pixels = DDSReader.read(buffer, DDSReader.ARGB, 0);
        int width = DDSReader.getWidth(buffer);
        int height = DDSReader.getHeight(buffer);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        image.setRGB(0, 0, width, height, pixels, 0, width);

        ImageIcon icon = new ImageIcon(image.getScaledInstance(128, 128, BufferedImage.SCALE_SMOOTH));
        return new JLabel(icon);
    }

For more details, please refer to the sample project.

https://github.com/npedotnet/DDSReader/tree/master/samples/DDSSwingBufferedImage

4.3. Android OpenGL Application

Sample code to create Android OpenGL texture.

Java

	import static javax.microedition.khronos.opengles.GL10;

	public int createDDSTexture(GL10 gl, String path) {
		int texture = 0;
		try {
			
			InputStream is = getContext().getAssets().open(path);
			byte [] buffer = new byte[is.available()];
			is.read(buffer);
			is.close();
			
			int width = DDSReader.getWidth(buffer);
			int height = DDSReader.getHeight(buffer);
			int mipmap = DDSReader.getMipmap(buffer);
			
			int [] textures = new int[1];
			gl.glGenTextures(1, textures, 0);
			
			gl.glEnable(GL_TEXTURE_2D);
			gl.glBindTexture(GL_TEXTURE_2D, textures[0]);
			gl.glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
			
			if(mipmap > 0) {
				// mipmap
				for(int i=0; (width > 0) || (height > 0); i++) {
					if(width <= 0) width = 1;
					if(height <= 0) height = 1;
					int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, i);
					
					IntBuffer texBuffer = IntBuffer.wrap(pixels);
					gl.glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer);
					
					width /= 2;
					height /= 2;
				}
				
				gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
				gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
				gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
				gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
			}
			else {
				// no mipmap
				int [] pixels = DDSReader.read(buffer, DDSReader.ABGR, 0);
				
				IntBuffer texBuffer = IntBuffer.wrap(pixels);
				gl.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texBuffer);
				
				gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
				gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
				gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
				gl.glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			}
			
			texture = textures[0];
			
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		
		return texture;
	}

For more details, please refer to the sample project.

https://github.com/npedotnet/DDSReader/tree/master/samples/DDSGLViewer_Android

4.4. Android Application

Sample code to create android.graphics.Bitmap.

Java

    private Bitmap createDDSBitmap(String path) {
        Bitmap bitmap = null;
        try {
            InputStream is = getAssets().open(path);
            byte [] buffer = new byte[is.available()];
            is.read(buffer);
            is.close();
            
            int [] pixels = DDSReader.read(buffer, DDSReader.ARGB, 0);
            int width = DDSReader.getWidth(buffer);
            int height = DDSReader.getHeight(buffer);
            
            bitmap = Bitmap.createBitmap(pixels, 0, width, width, height, Config.ARGB_8888);
        }
        catch(Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

For more details, please refer to the sample project.

https://github.com/npedotnet/DDSReader/tree/master/samples/DDSBitmapViewer_Android

4.5. iOS OpenGL Application

Sample code to create iOS OpenGL texture.

Objective-C

- (GLuint)createDDSTexture:(NSString *)path {
    
    GLuint texture = 0;
    
    FILE *file = fopen([path UTF8String], "rb");
    if(file) {
        fseek(file, 0, SEEK_END);
        int size = ftell(file);
        fseek(file, 0, SEEK_SET);
        
        unsigned char *buffer = (unsigned char *)ddsMalloc(size);
        fread(buffer, 1, size, file);
        fclose(file);
        
        int width = ddsGetWidth(buffer);
        int height = ddsGetHeight(buffer);
        int mipmap = ddsGetMipmap(buffer);
        
        glGenTextures(1, &texture);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, texture);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        
        if(mipmap > 0) {
            // mipmap
            for(int i=0; (width > 0) || (height > 0); i++) {
                if(width <= 0) width = 1;
                if(height <= 0) height = 1;
                int *pixels = ddsRead(buffer, DDS_READER_ABGR, i);
                
                glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

                width /= 2;
                height /= 2;

                ddsFree(pixels);
            }
            
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        }
        else {
            // no mipmap
            int *pixels = ddsRead(buffer, DDS_READER_ABGR, 0);
            
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
            
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            
            ddsFree(pixels);
        }
        
        ddsFree(buffer);
    }
    
    return texture;
    
}

For more details, please refer to the sample project.

https://github.com/npedotnet/DDSReader/tree/master/samples/DDSGLViewer_iOS

4.6. iOS Application

Sample code to create iOS UIImage.

Objective-C

- (UIImage *)createDDSImage:(NSString *)path {
	    
    FILE *file = fopen([path UTF8String], "rb");
    if(file) {
        fseek(file, 0, SEEK_END);
        int size = ftell(file);
        fseek(file, 0, SEEK_SET);
        
        unsigned char *buffer = (unsigned char *)ddsMalloc(size);
        fread(buffer, 1, size, file);
        fclose(file);
        
        int width = ddsGetWidth(buffer);
        int height = ddsGetHeight(buffer);
        int *pixels = ddsRead(buffer, DDS_READER_ABGR, 0);
        
        ddsFree(buffer);
        
        CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
        CGBitmapInfo bitmapInfo = (CGBitmapInfo)kCGImageAlphaLast;
        CGDataProviderRef providerRef = CGDataProviderCreateWithData(NULL, pixels, 4*width*height, releaseDataCallback);
	        
        CGImageRef imageRef = CGImageCreate(width, height, 8, 32, 4*width, colorSpaceRef, bitmapInfo, providerRef, NULL, 0, kCGRenderingIntentDefault);
	        
        UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
	        
        CGColorSpaceRelease(colorSpaceRef);
	        
        return image;
    }
	    
    return nil;
	    
}

static void releaseDataCallback(void *info, const void *data, size_t size) {
	ddsFree((void *)data);
}

For more details, please refer to the sample project.

https://github.com/npedotnet/DDSReader/tree/master/samples/DDSImageViewer_iOS

4.7. GWT Web Application

Sample code to create DDS HTML5 Canvas with GWT.

Java

import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.CanvasPixelArray;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.ImageData;
import com.google.gwt.typedarrays.client.Uint8ArrayNative;
import com.google.gwt.typedarrays.shared.ArrayBuffer;
import com.google.gwt.xhr.client.ReadyStateChangeHandler;
import com.google.gwt.xhr.client.XMLHttpRequest;
import com.google.gwt.xhr.client.XMLHttpRequest.ResponseType;

private Canvas createImageCanvas(int [] pixels, int width, int height) {
	
	Canvas canvas = Canvas.createIfSupported();
	canvas.setCoordinateSpaceWidth(width);
	canvas.setCoordinateSpaceHeight(height);
	
	Context2d context = canvas.getContext2d();
	ImageData data = context.createImageData(width, height);

	CanvasPixelArray array = data.getData();
	for(int i=0; i<width*height; i++) { // ABGR
		array.set(4*i+0, pixels[i] & 0xFF);
		array.set(4*i+1, (pixels[i] >> 8) & 0xFF);
		array.set(4*i+2, (pixels[i] >> 16) & 0xFF);
		array.set(4*i+3, (pixels[i] >> 24) & 0xFF);
	}
	context.putImageData(data, 0, 0);
	
	return canvas;
	
}

private void addDDSCanvas(String url) {
	XMLHttpRequest request = XMLHttpRequest.create();
	request.open("GET", url);
	request.setResponseType(ResponseType.ArrayBuffer);
	request.setOnReadyStateChange(new ReadyStateChangeHandler() {
		@Override
		public void onReadyStateChange(XMLHttpRequest xhr) {
			if(xhr.getReadyState() == XMLHttpRequest.DONE) {
				if(xhr.getStatus() >= 400) {
					// error
					System.out.println("Error");
				}
				else {
					try {
						ArrayBuffer arrayBuffer = xhr.getResponseArrayBuffer();
						Uint8ArrayNative u8array = Uint8ArrayNative.create(arrayBuffer);
						byte [] buffer = new byte[u8array.length()];
						for(int i=0; i<buffer.length; i++) {
							buffer[i] = (byte)u8array.get(i);
						}
						int pixels [] = DDSReader.read(buffer, DDSReader.ABGR, 0);
						int width = DDSReader.getWidth(buffer);
						int height = DDSReader.getHeight(buffer);
						
						Canvas canvas = createImageCanvas(pixels, width, height);
						
						panel.add(canvas);
					}
					catch(Exception e) {
						e.printStackTrace();
					}
				}
			}
		}
	});
	request.send();
}

For more details, please refer to the sample project.

https://github.com/npedotnet/DDSReader/tree/master/samples/DDSWebViewer_GWT

4.8 GWT WebGL(GwtGL) Application

Sample code to create DDS WebGL texture with GWT.

import com.google.gwt.canvas.client.Canvas;
import com.googlecode.gwtgl.binding.WebGLRenderingContext;
import com.googlecode.gwtgl.binding.WebGLTexture;

import static com.googlecode.gwtgl.binding.WebGLRenderingContext.*;

WegGLRenderingContext gl = ...;

// See 4.7. GWT Web Application
Canvas canvas = createImageCanvas(pixels, width, height);

WebGLTexture texture = gl.createTexture();

gl.enable(TEXTURE_2D);
gl.bindTexture(TEXTURE_2D, texture);
gl.texImage2D(TEXTURE_2D, 0, RGBA, RGBA, UNSIGNED_BYTE, canvas.getElement());

For more details, please refer to the sample project.

https://github.com/npedotnet/DDSReader/tree/master/samples/DDSWebGLViewer_GWT

5. Free allocated memory (C language Only)

C

	unsigned char *buffer = ...;
	int *pixels = ddsRead(buffer, DDS_READER_ABGR, 0);
	if(pixels) {
		ddsFree(pixels);
	}
	ddsFree(buffer);

Memory Management (C language Only)

If you have your memory management system, please customize ddsMalloc() and ddsFree().

C

	void *ddsMalloc(size_t size) {
		return malloc(size);
	}

	void ddsFree(void *memory) {
		free(memory);
	}

Supported

  • Mipmaps
  • DXT compressed images (DXT1, DXT2, DXT3, DXT4, DXT5)
  • 16bit RGB images (A1R5G5B5, X1R5G5B5, A4R4G4B4, X4R4G4B4, R5G6B5)
  • 24bit RGB image (R8G8B8)
  • 32bit RGB images (A8B8G8R8, X8B8G8R8, A8R8G8B8, X8R8G8B8)

Unsupported

  • Other RGB images
  • Luminance images
  • YUV images
  • Floating-Point images

Thank you for reading through. Enjoy your programming life!