package ddsutil;
import gr.zdimensions.jsquish.Squish;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileLockInterruptionException;
import javax.activation.UnsupportedDataTypeException;
import jogl.DDSImage;
import jogl.TEXImage;
import model.TextureMap;
import util.FileUtil;
import util.ImageUtils;
import compression.DXTBufferCompressor;
import compression.DXTBufferDecompressor;
/**
* Easy loading, saving and manipulation of DDSImages and DXT-Compression.
*
* @author danielsenff
*
*/
public class DDSUtil {
/**
* Topmost MipMap Index
*/
public static final int TOP_MOST_MIP_MAP = 0;
private DDSUtil() { }
@Deprecated
public static BufferedImage decompressTexture(final File file) throws IOException {
return read(file);
}
/**
* Create a {@link BufferedImage} from a DXT-compressed
* dds-texture {@link FileLockInterruptionException}.
* @param file
* @return
* @throws IOException
*/
public static BufferedImage read(final File file) throws IOException {
if(file.getName().endsWith(".dds"))
return loadBufferedImage(DDSImage.read(file));
else
return loadBufferedImage(TEXImage.read(file));
}
/**
* Create a {@link BufferedImage} from a DXT-compressed {@link DDSImage}
* @param image
* @return
* @throws UnsupportedDataTypeException
*/
public static BufferedImage loadBufferedImage (final DDSImage image) throws UnsupportedDataTypeException {
if (image.isCompressed())
return decompressTexture(
image.getMipMap(0).getData(),
image.getWidth(),
image.getHeight(),
findCompressionFormat(image));
else
return loadBufferedImageFromByteBuffer(
image.getMipMap(0).getData(),
image.getWidth(),
image.getHeight(),
image);
}
/**
* @param data
* @param width
* @param height
* @param ddsimage
* @return
*/
public static BufferedImage loadBufferedImageFromByteBuffer(
ByteBuffer data, int width, int height,
DDSImage ddsimage) {
// check pixelformat
if(ddsimage.getPixelFormat() == DDSImage.D3DFMT_A8R8G8B8) {
// data in buffer in 4 byte chunks ordered ARGB
ByteBufferedImage bi = new ByteBufferedImage(width, height, data);
} else if(ddsimage.getPixelFormat() == DDSImage.D3DFMT_A8R8G8B8) {
}
// if weird or unknown check RGB-offsets
return null;
}
/**
* Create a {@link BufferedImage} from a DXT-compressed {@link DDSImage}
* @param image
* @return
* @throws UnsupportedDataTypeException
*/
@Deprecated
public static BufferedImage decompressTexture (final DDSImage image) throws UnsupportedDataTypeException {
return loadBufferedImage(image);
}
/**
* Create a {@link BufferedImage} from a DXT-compressed {@link TEXImage}
* @param image
* @return
* @throws UnsupportedDataTypeException
*/
public static BufferedImage loadBufferedImage(final TEXImage image) throws UnsupportedDataTypeException {
return decompressTexture(
image.getEmbeddedMaps(0).getMipMap(0).getData(),
image.getWidth(),
image.getHeight(),
findCompressionFormat(image.getEmbeddedMaps(0)));
}
/**
* Create a {@link BufferedImage} from a DXT-compressed {@link TEXImage}
* @param image
* @return
* @throws UnsupportedDataTypeException
*/
@Deprecated
public static BufferedImage decompressTexture (final TEXImage image) throws UnsupportedDataTypeException {
return loadBufferedImage(image);
}
/**
* Create a {@link BufferedImage} from a DXT-compressed Byte-array.
* @param compressedData
* @param width
* @param height
* @param compressionType
* @return
*/
public static BufferedImage decompressTexture(final byte[] compressedData,
final int width,
final int height,
final Squish.CompressionType compressionType) {
return new DXTBufferDecompressor(compressedData, width, height, compressionType).getImage();
}
/**
* Create a {@link BufferedImage} from a DXT-compressed ByteBuffer.
* @param textureBuffer
* @param width
* @param height
* @param compressionType
* @return
*/
public static BufferedImage decompressTexture(final ByteBuffer textureBuffer,
final int width,
final int height,
final Squish.CompressionType compressionType) {
return new DXTBufferDecompressor(textureBuffer, width, height, compressionType).getImage();
}
/**
* Create a {@link BufferedImage} from a DXT-compressed ByteBuffer.
* @param textureBuffer
* @param width
* @param height
* @param pixelformat
* @return
* @throws UnsupportedDataTypeException
*/
public static BufferedImage decompressTexture(final ByteBuffer textureBuffer,
final int width,
final int height,
final int pixelformat) throws UnsupportedDataTypeException {
Squish.CompressionType compressionType = PixelFormats.getSquishCompressionFormat(pixelformat);
return new DXTBufferDecompressor(textureBuffer, width, height, compressionType).getImage();
}
/**
* Compresses a {@link BufferedImage} into a {@link ByteBuffer}
* @param image
* @param compressionType
* @return
*/
public static ByteBuffer compressTexture(final BufferedImage image,
final Squish.CompressionType compressionType) {
return new DXTBufferCompressor(image, compressionType).getByteBuffer();
}
/**
* @param image
* @param compressionType
* @return
*/
public static byte[] compressTextureToArray(final BufferedImage image,
final Squish.CompressionType compressionType) {
return new DXTBufferCompressor(image, compressionType).getArray();
}
/**
* Writes a DDS-Image file to disk.
* @param destinationfile
* @param sourceImage
* @param pixelformat
* @param generateMipMaps
* @throws IOException
*
*/
public static void write(final File destinationfile,
BufferedImage sourceImage,
final int pixelformat,
boolean generateMipMaps) throws IOException {
int width = sourceImage.getWidth();
int height = sourceImage.getHeight();
//convert RGB to RGBA image
if(!sourceImage.getColorModel().hasAlpha())
sourceImage = ImageUtils.convert(sourceImage, BufferedImage.TYPE_4BYTE_ABGR);
TextureMap maps = TextureFactory.createTextureMap(generateMipMaps, sourceImage);
ByteBuffer[] mipmapBuffer = null;
if (PixelFormats.isDXTCompressed(pixelformat)) {
mipmapBuffer = maps.getDXTCompressedBuffer(pixelformat);
} else
mipmapBuffer = maps.getUncompressedBuffer();
writeDDSImage(destinationfile, mipmapBuffer, width, height, pixelformat);
}
/**
* TODO: what about DXT1?
* @param file
* @param map
* @param pixelformat
* @throws IOException
*
*/
public void write(final File file,
final TextureMap map,
final int pixelformat) throws IOException {
writeDDSImage(file, map.getDXTCompressedBuffer(pixelformat),
map.getWidth(),
map.getHeight(),
pixelformat);
}
private static DDSImage writeDDSImage(final File file,
final ByteBuffer[] mipmapBuffer,
final int width,
final int height,
final int pixelformat) throws IllegalArgumentException, IOException {
DDSImage writedds = DDSImage.createFromData(pixelformat, width, height, mipmapBuffer);
// writedds.debugPrint();
writedds.write(file);
return writedds;
}
/**
* Returns the PixelFormat of a {@link File}
* This makes file-IO, therefor handle with caution!
* @param file
* @return
* @throws IOException
*/
public static int getCompressionType(final File file) throws IOException {
return DDSImage.read(file).getPixelFormat();
}
private static Squish.CompressionType findCompressionFormat(DDSImage ddsimage) throws UnsupportedDataTypeException {
int pixelFormat = ddsimage.getPixelFormat();
return PixelFormats.getSquishCompressionFormat(pixelFormat);
}
/**
* Returns true for file formats supported by this library.
* Currently TEX and DDS reading is supported.
* @param file
* @return
*/
public static boolean isReadSupported(final File file) {
String fileSuffix = FileUtil.getFileSuffix(file);
return fileSuffix.endsWith("dds")
|| fileSuffix.endsWith("tex");
}
}