package model;
/**
*
*/
import gr.zdimensions.jsquish.Squish.CompressionType;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
import javax.activation.UnsupportedDataTypeException;
import jogl.DDSImage;
import compression.ARGBBufferDecompressor;
import compression.BufferDecompressor;
import compression.DXTBufferDecompressor;
import ddsutil.MipMapsUtil;
import ddsutil.PixelFormats;
/**
* @author danielsenff
*
*/
public class DDSFile extends AbstractTextureImage{
protected TextureType textureType;
private DDSImage ddsimage;
/**
* @param filename
*/
public DDSFile(final String filename) {
this(new File(filename));
}
/**
* Constructs a DDSFile from a {@link File}
* @param file
*/
public DDSFile(final File file) {
this.file = file;
try {
init(DDSImage.read(file));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Constructs a DDSFile from a {@link File} and a {@link DDSImage}
* @param file
* @param ddsimage
*/
public DDSFile(final File file, final DDSImage ddsimage) {
this.file = file;
init(ddsimage);
}
/**
* Constructs a DDSFile from a file path and a {@link DDSImage}
* @param filename
* @param ddsimage
*/
public DDSFile(final String filename, final DDSImage ddsimage) {
this(new File(filename), ddsimage);
}
/**
*
* @param filename
* @param bi
* @param pixelformat
* @param hasMipMaps
*/
public DDSFile(final File filename,
final BufferedImage bi,
final int pixelformat,
final boolean hasMipMaps) {
this.file = filename;
this.width = bi.getWidth();
this.height = bi.getHeight();
this.pixelformat = pixelformat;
this.hasMipMaps = hasMipMaps;
if(hasMipMaps) {
this.numMipMaps = MipMapsUtil.calculateMaxNumberOfMipMaps(width, height);
} else {
this.numMipMaps = 1;
}
this.mipMaps = new MipMaps(this.numMipMaps);
this.mipMaps.setMipMap(0, bi);
}
/**
* @param ddsimage
*/
protected void init(final DDSImage ddsimage) {
this.ddsimage = ddsimage;
this.width = ddsimage.getWidth();
this.height = ddsimage.getHeight();
this.depth = ddsimage.getDepth();
this.pixelformat = ddsimage.getPixelFormat();
this.textureType = getTextureType(ddsimage);
this.numMipMaps = ddsimage.getNumMipMaps();
this.mipMaps = new MipMaps(this.numMipMaps);
this.hasMipMaps = (ddsimage.getNumMipMaps() > 1); // there is always at least the topmost MipMap
}
/**
* Load the ImageData for the specified MipMap from original {@link DDSImage}.
* @param mipmap
* @throws UnsupportedDataTypeException
*/
public void loadImageData(int mipmap) throws UnsupportedDataTypeException {
if(mipmap <= this.numMipMaps ) {
int width = MipMaps.getMipMapSizeAtIndex(mipmap, ddsimage.getWidth());
int height = MipMaps.getMipMapSizeAtIndex(mipmap, ddsimage.getHeight());
ByteBuffer data = ddsimage.getMipMap(mipmap).getData();
BufferDecompressor bufferDecompressor;
if(isCompressed()) {
CompressionType compressionType =
PixelFormats.getSquishCompressionFormat(ddsimage.getPixelFormat());
bufferDecompressor = new DXTBufferDecompressor(
data,
width,
height,
compressionType);
} else {
bufferDecompressor = new ARGBBufferDecompressor(
data,
width,
height,
this.pixelformat);
}
this.mipMaps.addMipMap(bufferDecompressor.getImage());
}
}
@Override
public void loadImageData() throws UnsupportedDataTypeException {
for (int i = 0; i < this.numMipMaps; i++) {
loadImageData(i);
}
}
@Override
public String toString() {
return this.file.getAbsolutePath() + PixelFormats.verbosePixelformat(this.pixelformat);
}
@Override
public boolean equals(Object second) {
if(second != null && second instanceof DDSFile) {
DDSFile secondFile = (DDSFile) second;
return (this.getFile().getAbsoluteFile().equals(secondFile.getFile().getAbsoluteFile()) &&
this.hasMipMaps() == secondFile.hasMipMaps() &&
this.getPixelformat() == secondFile.getPixelformat() &&
this.getHeight() == secondFile.getHeight() &&
this.getWidth() == secondFile.getWidth());
}
return false;
}
// public ByteBuffer[] getMipMapData() {
// ByteBuffer[] buffer = new ByteBuffer[ddsimage.getNumMipMaps()+1];
// for (int i = 0; i < buffer.length; i++) {
// buffer[i] = ddsimage.getMipMap(i).getData();
// }
// return buffer;
// }
/**
* The DDS-Image can have different texture types.
* Regular Texture, Volume-Texture and CubeMap
* @return TextureType Type of Texture
*/
public TextureType getTextureType() {
return this.textureType;
}
/**
* The DDS-Image can have different texture types.
* Regular Texture, Volume-Texture and CubeMap
* This returns the textureType from a {@link DDSImage}
* @param ddsimage
* @return
*/
public static TextureType getTextureType(final DDSImage ddsimage) {
if(ddsimage.isCubemap()) {
return TextureType.CUBEMAP;
} else if (ddsimage.isVolume()) {
return TextureType.VOLUME;
} else {
return TextureType.TEXTURE;
}
}
public void write(final File targetFile) throws IOException {
ByteBuffer[] mipmaps = new ByteBuffer[getNumMipMaps()];
for (int i = 0; i < mipmaps.length; i++) {
mipmaps[i] = DDSImage.read(this.file).getMipMap(i).getData();
}
DDSImage outputDDS = DDSImage.createFromData(this.pixelformat, width, height, mipmaps);
outputDDS.write(file);
outputDDS.close();
}
/**
* Checks if the {@link File} is a valid DDS-Image
* @param file
* @return
* @throws IOException
*
*/
public static boolean isValidDDSImage(final File file) throws IOException {
FileInputStream fis = new FileInputStream(file);
boolean isDDSImage = DDSImage.isDDSImage(fis);
fis.close();
return isDDSImage;
}
/**
* Returns the stored MipMaps as a {@link BufferedImage}-Array
* @return
*/
public BufferedImage[] getAllMipMapsBI(){
return mipMaps.getAllMipMapsArray();
}
/**
* returns the stored MipMaps as {@link ByteBuffer}-Array
* @return
*/
public List<BufferedImage> generateAllMipMaps(){
MipMaps mipMaps = new MipMaps();
mipMaps.generateMipMaps(getTopMipMap());
return mipMaps.getAllMipMaps();
}
public BufferedImage getMipMap(int index) {
return this.mipMaps.getMipMap(index);
}
}