mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-18 00:00:03 -04:00
Read header (DDSHeader) and pass into DDSReader
Remove header methods using buffer offset addressing. Switch endian for DX1-DX5 types
This commit is contained in:
@@ -1,5 +1,15 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.dds;
|
package com.twelvemonkeys.imageio.plugins.dds;
|
||||||
|
|
||||||
interface DDS {
|
interface DDS {
|
||||||
byte[] MAGIC = new byte[] {'D', 'D', 'S', ' '};
|
byte[] MAGIC = new byte[]{'D', 'D', 'S', ' '};
|
||||||
|
int HEADER_SIZE = 124;
|
||||||
|
|
||||||
|
int FLAG_CAPS = 0x1; // Required in every .dds file.
|
||||||
|
int FLAG_HEIGHT = 0x2; // Required in every .dds file.
|
||||||
|
int FLAG_WIDTH = 0x4; // Required in every .dds file.
|
||||||
|
int FLAG_PITCH = 0x8; // Required when pitch is provided for an uncompressed texture.
|
||||||
|
int FLAG_PIXELFORMAT = 0x1000; // Required in every .dds file.
|
||||||
|
int FLAG_MIPMAPCOUNT = 0x20000; // Required in a mipmapped texture.
|
||||||
|
int FLAG_LINEARSIZE = 0x80000; // Required when pitch is provided for a compressed texture.
|
||||||
|
int FLAG_DEPTH = 0x800000; // Required in a depth texture.
|
||||||
}
|
}
|
||||||
|
|||||||
+106
-29
@@ -1,56 +1,97 @@
|
|||||||
package com.twelvemonkeys.imageio.plugins.dds;
|
package com.twelvemonkeys.imageio.plugins.dds;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
final class DDSHeader {
|
public final class DDSHeader {
|
||||||
|
|
||||||
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide
|
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide
|
||||||
|
private int flags;
|
||||||
private int width;
|
private int width;
|
||||||
private int height;
|
private int height;
|
||||||
|
private int mipmap;
|
||||||
|
|
||||||
|
private int pixelFormatFlags;
|
||||||
|
private int fourCC;
|
||||||
|
private int bitCount;
|
||||||
|
private int redMask;
|
||||||
|
private int greenMask;
|
||||||
|
private int blueMask;
|
||||||
|
private int alphaMask;
|
||||||
|
|
||||||
public static DDSHeader read(final ImageInputStream imageInput) throws IOException {
|
public static DDSHeader read(final ImageInputStream imageInput) throws IOException {
|
||||||
DDSHeader header = new DDSHeader();
|
DDSHeader header = new DDSHeader();
|
||||||
|
|
||||||
imageInput.mark();
|
imageInput.mark();
|
||||||
imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
|
||||||
|
|
||||||
byte[] magic = new byte[4];
|
try {
|
||||||
imageInput.readFully(magic);
|
imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
|
||||||
// DDS_HEADER structure
|
// Read MAGIC bytes [0,3]
|
||||||
int dwSize = imageInput.readInt();
|
byte[] magic = new byte[DDS.MAGIC.length];
|
||||||
int dwFlags = imageInput.readInt();
|
imageInput.readFully(magic);
|
||||||
header.height = imageInput.readInt();
|
if (!Arrays.equals(DDS.MAGIC, magic)) {
|
||||||
header.width = imageInput.readInt();
|
throw new IIOException("Unsupported MAGIC bytes.");
|
||||||
int dwPitchOrLinearSize = imageInput.readInt();
|
}
|
||||||
int dwDepth = imageInput.readInt();
|
|
||||||
int dwMipMapCount = imageInput.readInt();
|
|
||||||
|
|
||||||
byte[] dwReserved1 = new byte[11];
|
// DDS_HEADER structure
|
||||||
imageInput.readFully(dwReserved1);
|
// https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-header
|
||||||
|
int dwSize = imageInput.readInt(); // [4,7]
|
||||||
|
if (dwSize != DDS.HEADER_SIZE) {
|
||||||
|
throw new IIOException("Invalid header size: " + dwSize);
|
||||||
|
}
|
||||||
|
|
||||||
// DDS_PIXELFORMAT structure
|
// Verify flags
|
||||||
int px_dwSize = imageInput.readInt();
|
header.flags = imageInput.readInt(); // [8,11]
|
||||||
int px_dwFlags = imageInput.readInt();
|
if (header.getFlag(DDS.FLAG_CAPS
|
||||||
int px_dwFourCC = imageInput.readInt();
|
& DDS.FLAG_HEIGHT
|
||||||
int px_dwRGBBitCount = imageInput.readInt();
|
& DDS.FLAG_WIDTH
|
||||||
int px_dwRBitMask = imageInput.readInt();
|
& DDS.FLAG_PIXELFORMAT)) {
|
||||||
int px_dwGBitMask = imageInput.readInt();
|
throw new IIOException("Required DDS Flag missing in header: " + Integer.toHexString(header.flags));
|
||||||
int px_dwBBitMask = imageInput.readInt();
|
}
|
||||||
int px_dwABitMask = imageInput.readInt();
|
|
||||||
|
|
||||||
int dwCaps = imageInput.readInt();
|
// Read Height & Width
|
||||||
int dwCaps2 = imageInput.readInt();
|
header.height = imageInput.readInt(); // [12,15]
|
||||||
int dwCaps3 = imageInput.readInt();
|
header.width = imageInput.readInt(); // [16,19]
|
||||||
int dwCaps4 = imageInput.readInt();
|
|
||||||
int dwReserved2 = imageInput.readInt();
|
|
||||||
|
|
||||||
imageInput.reset();
|
|
||||||
|
int dwPitchOrLinearSize = imageInput.readInt(); // [20,23]
|
||||||
|
int dwDepth = imageInput.readInt(); // [24,27]
|
||||||
|
header.mipmap = imageInput.readInt(); // [28,31]
|
||||||
|
|
||||||
|
byte[] dwReserved1 = new byte[11 * 4]; // [32,75]
|
||||||
|
imageInput.readFully(dwReserved1);
|
||||||
|
|
||||||
|
// DDS_PIXELFORMAT structure
|
||||||
|
int px_dwSize = imageInput.readInt(); // [76,79]
|
||||||
|
|
||||||
|
header.pixelFormatFlags = imageInput.readInt(); // [80,83]
|
||||||
|
header.fourCC = imageInput.readInt(); // [84,87]
|
||||||
|
header.bitCount = imageInput.readInt(); // [88,91]
|
||||||
|
header.redMask = imageInput.readInt(); // [92,95]
|
||||||
|
header.greenMask = imageInput.readInt(); // [96,99]
|
||||||
|
header.blueMask = imageInput.readInt(); // [100,103]
|
||||||
|
header.alphaMask = imageInput.readInt(); // [104,107]
|
||||||
|
|
||||||
|
int dwCaps = imageInput.readInt();
|
||||||
|
int dwCaps2 = imageInput.readInt();
|
||||||
|
int dwCaps3 = imageInput.readInt();
|
||||||
|
int dwCaps4 = imageInput.readInt();
|
||||||
|
|
||||||
|
int dwReserved2 = imageInput.readInt();
|
||||||
|
} finally {
|
||||||
|
imageInput.reset();
|
||||||
|
}
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean getFlag(int mask) {
|
||||||
|
return (flags & mask) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
@@ -58,4 +99,40 @@ final class DDSHeader {
|
|||||||
public int getHeight() {
|
public int getHeight() {
|
||||||
return height;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getMipmap() {
|
||||||
|
return mipmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAlphaMask() {
|
||||||
|
return alphaMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBitCount() {
|
||||||
|
return bitCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlueMask() {
|
||||||
|
return blueMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFlags() {
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFourCC() {
|
||||||
|
return fourCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGreenMask() {
|
||||||
|
return greenMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPixelFormatFlags() {
|
||||||
|
return pixelFormatFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRedMask() {
|
||||||
|
return redMask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-11
@@ -7,9 +7,7 @@ import javax.imageio.ImageIO;
|
|||||||
import javax.imageio.ImageReadParam;
|
import javax.imageio.ImageReadParam;
|
||||||
import javax.imageio.ImageTypeSpecifier;
|
import javax.imageio.ImageTypeSpecifier;
|
||||||
import javax.imageio.spi.ImageReaderSpi;
|
import javax.imageio.spi.ImageReaderSpi;
|
||||||
import java.awt.color.ColorSpace;
|
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.DataBuffer;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -45,13 +43,19 @@ public final class DDSImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
|
public ImageTypeSpecifier getRawImageType(int imageIndex) throws IOException {
|
||||||
checkBounds(imageIndex);
|
checkBounds(imageIndex);
|
||||||
readHeader();
|
readHeader();
|
||||||
|
|
||||||
// TODO changes based on format
|
// TODO change based on format DXT1 4bpp / DXT1-nonalpha
|
||||||
ColorSpace sRGB = ColorSpace.getInstance(ColorSpace.CS_sRGB);
|
|
||||||
return Collections.singletonList(ImageTypeSpecifiers.createInterleaved(sRGB, new int[]{0, 1, 2}, DataBuffer.TYPE_FLOAT, false, false)).iterator();
|
|
||||||
|
return ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
|
||||||
|
return Collections.singletonList(getRawImageType(imageIndex)).iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -68,13 +72,13 @@ public final class DDSImageReader extends ImageReaderBase {
|
|||||||
byte[] buffer = new byte[width * height * 4];
|
byte[] buffer = new byte[width * height * 4];
|
||||||
imageInput.read(buffer);
|
imageInput.read(buffer);
|
||||||
|
|
||||||
int[] pixels = DDSReader.read(buffer, DDSReader.ARGB, 0);
|
DDSReader dds = new DDSReader(header);
|
||||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
int[] pixels = dds.read(buffer, 0);
|
||||||
image.setRGB(0, 0, width, height, pixels, 0, width);
|
destination.setRGB(0, 0, width, height, pixels, 0, width);
|
||||||
|
|
||||||
processImageComplete();
|
processImageComplete();
|
||||||
|
|
||||||
return image;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readHeader() throws IOException {
|
private void readHeader() throws IOException {
|
||||||
@@ -88,7 +92,8 @@ public final class DDSImageReader extends ImageReaderBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(final String[] args) throws IOException {
|
public static void main(final String[] args) throws IOException {
|
||||||
File file = new File("imageio/imageio-dds/src/test/resources/dds/dxt5.dds");
|
File file = new File("imageio/imageio-dds/src/test/resources/dds/stones.dxt5.dds");
|
||||||
|
//File file = new File("imageio/imageio-dds/src/test/resources/dds/dxt1-noalpha.dds");
|
||||||
|
|
||||||
BufferedImage image = ImageIO.read(file);
|
BufferedImage image = ImageIO.read(file);
|
||||||
|
|
||||||
|
|||||||
+79
-116
@@ -1,74 +1,40 @@
|
|||||||
/**
|
/**
|
||||||
* DDSReader.java
|
* DDSReader.java
|
||||||
*
|
* <p>
|
||||||
* Copyright (c) 2015 Kenji Sasaki
|
* Copyright (c) 2015 Kenji Sasaki
|
||||||
* Released under the MIT license.
|
* Released under the MIT license.
|
||||||
* https://github.com/npedotnet/DDSReader/blob/master/LICENSE
|
* https://github.com/npedotnet/DDSReader/blob/master/LICENSE
|
||||||
*
|
* <p>
|
||||||
* English document
|
* English document
|
||||||
* https://github.com/npedotnet/DDSReader/blob/master/README.md
|
* https://github.com/npedotnet/DDSReader/blob/master/README.md
|
||||||
*
|
* <p>
|
||||||
* Japanese document
|
* Japanese document
|
||||||
* http://3dtech.jp/wiki/index.php?DDSReader
|
* http://3dtech.jp/wiki/index.php?DDSReader
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.twelvemonkeys.imageio.plugins.dds;
|
package com.twelvemonkeys.imageio.plugins.dds;
|
||||||
|
|
||||||
public final class DDSReader {
|
public final class DDSReader {
|
||||||
|
|
||||||
public static final Order ARGB = new Order(16, 8, 0, 24);
|
|
||||||
public static final Order ABGR = new Order(0, 8, 16, 24);
|
public static final Order ABGR = new Order(0, 8, 16, 24);
|
||||||
|
public static final Order order = new Order(16, 8, 0, 24);
|
||||||
|
|
||||||
public static int getHeight(byte[] buffer) {
|
private final DDSHeader header;
|
||||||
return (buffer[12] & 0xFF) | (buffer[13] & 0xFF) << 8 | (buffer[14] & 0xFF) << 16 | (buffer[15] & 0xFF) << 24;
|
|
||||||
|
|
||||||
|
public DDSReader(DDSHeader header) {
|
||||||
|
this.header = header;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getWidth(byte[] buffer) {
|
public int[] read(byte[] buffer, int mipmapLevel) {
|
||||||
return (buffer[16] & 0xFF) | (buffer[17] & 0xFF) << 8 | (buffer[18] & 0xFF) << 16 | (buffer[19] & 0xFF) << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getMipmap(byte[] buffer) {
|
|
||||||
return (buffer[28] & 0xFF) | (buffer[29] & 0xFF) << 8 | (buffer[30] & 0xFF) << 16 | (buffer[31] & 0xFF) << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getPixelFormatFlags(byte[] buffer) {
|
|
||||||
return (buffer[80] & 0xFF) | (buffer[81] & 0xFF) << 8 | (buffer[82] & 0xFF) << 16 | (buffer[83] & 0xFF) << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getFourCC(byte[] buffer) {
|
|
||||||
return (buffer[84] & 0xFF) << 24 | (buffer[85] & 0xFF) << 16 | (buffer[86] & 0xFF) << 8 | (buffer[87] & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getBitCount(byte[] buffer) {
|
|
||||||
return (buffer[88] & 0xFF) | (buffer[89] & 0xFF) << 8 | (buffer[90] & 0xFF) << 16 | (buffer[91] & 0xFF) << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getRedMask(byte[] buffer) {
|
|
||||||
return (buffer[92] & 0xFF) | (buffer[93] & 0xFF) << 8 | (buffer[94] & 0xFF) << 16 | (buffer[95] & 0xFF) << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getGreenMask(byte[] buffer) {
|
|
||||||
return (buffer[96] & 0xFF) | (buffer[97] & 0xFF) << 8 | (buffer[98] & 0xFF) << 16 | (buffer[99] & 0xFF) << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getBlueMask(byte[] buffer) {
|
|
||||||
return (buffer[100] & 0xFF) | (buffer[101] & 0xFF) << 8 | (buffer[102] & 0xFF) << 16 | (buffer[103] & 0xFF) << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getAlphaMask(byte[] buffer) {
|
|
||||||
return (buffer[104] & 0xFF) | (buffer[105] & 0xFF) << 8 | (buffer[106] & 0xFF) << 16 | (buffer[107] & 0xFF) << 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int[] read(byte[] buffer, Order order, int mipmapLevel) {
|
|
||||||
|
|
||||||
// header
|
// header
|
||||||
int width = getWidth(buffer);
|
int width = header.getWidth();
|
||||||
int height = getHeight(buffer);
|
int height = header.getHeight();
|
||||||
int mipmap = getMipmap(buffer);
|
int mipmap = header.getMipmap();
|
||||||
|
|
||||||
// type
|
// type
|
||||||
int type = getType(buffer);
|
int type = getType(header);
|
||||||
if (type == 0) return null;
|
if (type == 0) return null;
|
||||||
|
|
||||||
// offset
|
// offset
|
||||||
@@ -108,71 +74,71 @@ public final class DDSReader {
|
|||||||
int[] pixels = null;
|
int[] pixels = null;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case DXT1:
|
case DXT1:
|
||||||
pixels = decodeDXT1(width, height, offset, buffer, order);
|
pixels = decodeDXT1(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case DXT2:
|
case DXT2:
|
||||||
pixels = decodeDXT2(width, height, offset, buffer, order);
|
pixels = decodeDXT2(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case DXT3:
|
case DXT3:
|
||||||
pixels = decodeDXT3(width, height, offset, buffer, order);
|
pixels = decodeDXT3(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case DXT4:
|
case DXT4:
|
||||||
pixels = decodeDXT4(width, height, offset, buffer, order);
|
pixels = decodeDXT4(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case DXT5:
|
case DXT5:
|
||||||
pixels = decodeDXT5(width, height, offset, buffer, order);
|
pixels = decodeDXT5(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case A1R5G5B5:
|
case A1R5G5B5:
|
||||||
pixels = readA1R5G5B5(width, height, offset, buffer, order);
|
pixels = readA1R5G5B5(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case X1R5G5B5:
|
case X1R5G5B5:
|
||||||
pixels = readX1R5G5B5(width, height, offset, buffer, order);
|
pixels = readX1R5G5B5(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case A4R4G4B4:
|
case A4R4G4B4:
|
||||||
pixels = readA4R4G4B4(width, height, offset, buffer, order);
|
pixels = readA4R4G4B4(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case X4R4G4B4:
|
case X4R4G4B4:
|
||||||
pixels = readX4R4G4B4(width, height, offset, buffer, order);
|
pixels = readX4R4G4B4(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case R5G6B5:
|
case R5G6B5:
|
||||||
pixels = readR5G6B5(width, height, offset, buffer, order);
|
pixels = readR5G6B5(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case R8G8B8:
|
case R8G8B8:
|
||||||
pixels = readR8G8B8(width, height, offset, buffer, order);
|
pixels = readR8G8B8(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case A8B8G8R8:
|
case A8B8G8R8:
|
||||||
pixels = readA8B8G8R8(width, height, offset, buffer, order);
|
pixels = readA8B8G8R8(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case X8B8G8R8:
|
case X8B8G8R8:
|
||||||
pixels = readX8B8G8R8(width, height, offset, buffer, order);
|
pixels = readX8B8G8R8(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case A8R8G8B8:
|
case A8R8G8B8:
|
||||||
pixels = readA8R8G8B8(width, height, offset, buffer, order);
|
pixels = readA8R8G8B8(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
case X8R8G8B8:
|
case X8R8G8B8:
|
||||||
pixels = readX8R8G8B8(width, height, offset, buffer, order);
|
pixels = readX8R8G8B8(width, height, offset, buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getType(byte[] buffer) {
|
private static int getType(DDSHeader header) {
|
||||||
|
|
||||||
int type = 0;
|
int type = 0;
|
||||||
|
|
||||||
int flags = getPixelFormatFlags(buffer);
|
int flags = header.getPixelFormatFlags();
|
||||||
|
|
||||||
if ((flags & 0x04) != 0) {
|
if ((flags & 0x04) != 0) {
|
||||||
// DXT
|
// DXT
|
||||||
type = getFourCC(buffer);
|
type = header.getFourCC();
|
||||||
} else if ((flags & 0x40) != 0) {
|
} else if ((flags & 0x40) != 0) {
|
||||||
// RGB
|
// RGB
|
||||||
int bitCount = getBitCount(buffer);
|
int bitCount = header.getBitCount();
|
||||||
int redMask = getRedMask(buffer);
|
int redMask = header.getRedMask();
|
||||||
int greenMask = getGreenMask(buffer);
|
int greenMask = header.getGreenMask();
|
||||||
int blueMask = getBlueMask(buffer);
|
int blueMask = header.getBlueMask();
|
||||||
int alphaMask = ((flags & 0x01) != 0) ? getAlphaMask(buffer) : 0; // 0x01 alpha
|
int alphaMask = ((flags & 0x01) != 0) ? header.getAlphaMask() : 0; // 0x01 alpha
|
||||||
if (bitCount == 16) {
|
if (bitCount == 16) {
|
||||||
if (redMask == A1R5G5B5_MASKS[0] && greenMask == A1R5G5B5_MASKS[1] && blueMask == A1R5G5B5_MASKS[2] && alphaMask == A1R5G5B5_MASKS[3]) {
|
if (redMask == A1R5G5B5_MASKS[0] && greenMask == A1R5G5B5_MASKS[1] && blueMask == A1R5G5B5_MASKS[2] && alphaMask == A1R5G5B5_MASKS[3]) {
|
||||||
// A1R5G5B5
|
// A1R5G5B5
|
||||||
@@ -224,7 +190,7 @@ public final class DDSReader {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] decodeDXT1(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] decodeDXT1(int width, int height, int offset, byte[] buffer) {
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int w = (width + 3) / 4;
|
int w = (width + 3) / 4;
|
||||||
@@ -241,24 +207,24 @@ public final class DDSReader {
|
|||||||
int t1 = (buffer[index] & 0x0C) >> 2;
|
int t1 = (buffer[index] & 0x0C) >> 2;
|
||||||
int t2 = (buffer[index] & 0x30) >> 4;
|
int t2 = (buffer[index] & 0x30) >> 4;
|
||||||
int t3 = (buffer[index++] & 0xC0) >> 6;
|
int t3 = (buffer[index++] & 0xC0) >> 6;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 0] = getDXTColor(c0, c1, 0xFF, t0, order);
|
pixels[4 * width * i + 4 * j + width * k + 0] = getDXTColor(c0, c1, 0xFF, t0);
|
||||||
if (4 * j + 1 >= width) continue;
|
if (4 * j + 1 >= width) continue;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, 0xFF, t1, order);
|
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, 0xFF, t1);
|
||||||
if (4 * j + 2 >= width) continue;
|
if (4 * j + 2 >= width) continue;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 2] = getDXTColor(c0, c1, 0xFF, t2, order);
|
pixels[4 * width * i + 4 * j + width * k + 2] = getDXTColor(c0, c1, 0xFF, t2);
|
||||||
if (4 * j + 3 >= width) continue;
|
if (4 * j + 3 >= width) continue;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 3] = getDXTColor(c0, c1, 0xFF, t3, order);
|
pixels[4 * width * i + 4 * j + width * k + 3] = getDXTColor(c0, c1, 0xFF, t3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] decodeDXT2(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] decodeDXT2(int width, int height, int offset, byte[] buffer) {
|
||||||
return decodeDXT3(width, height, offset, buffer, order);
|
return decodeDXT3(width, height, offset, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] decodeDXT3(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] decodeDXT3(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int w = (width + 3) / 4;
|
int w = (width + 3) / 4;
|
||||||
int h = (height + 3) / 4;
|
int h = (height + 3) / 4;
|
||||||
@@ -286,24 +252,24 @@ public final class DDSReader {
|
|||||||
int t1 = (buffer[index] & 0x0C) >> 2;
|
int t1 = (buffer[index] & 0x0C) >> 2;
|
||||||
int t2 = (buffer[index] & 0x30) >> 4;
|
int t2 = (buffer[index] & 0x30) >> 4;
|
||||||
int t3 = (buffer[index++] & 0xC0) >> 6;
|
int t3 = (buffer[index++] & 0xC0) >> 6;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 0] = getDXTColor(c0, c1, alphaTable[4 * k + 0], t0, order);
|
pixels[4 * width * i + 4 * j + width * k + 0] = getDXTColor(c0, c1, alphaTable[4 * k + 0], t0);
|
||||||
if (4 * j + 1 >= width) continue;
|
if (4 * j + 1 >= width) continue;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, alphaTable[4 * k + 1], t1, order);
|
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, alphaTable[4 * k + 1], t1);
|
||||||
if (4 * j + 2 >= width) continue;
|
if (4 * j + 2 >= width) continue;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 2] = getDXTColor(c0, c1, alphaTable[4 * k + 2], t2, order);
|
pixels[4 * width * i + 4 * j + width * k + 2] = getDXTColor(c0, c1, alphaTable[4 * k + 2], t2);
|
||||||
if (4 * j + 3 >= width) continue;
|
if (4 * j + 3 >= width) continue;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 3] = getDXTColor(c0, c1, alphaTable[4 * k + 3], t3, order);
|
pixels[4 * width * i + 4 * j + width * k + 3] = getDXTColor(c0, c1, alphaTable[4 * k + 3], t3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] decodeDXT4(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] decodeDXT4(int width, int height, int offset, byte[] buffer) {
|
||||||
return decodeDXT5(width, height, offset, buffer, order);
|
return decodeDXT5(width, height, offset, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] decodeDXT5(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] decodeDXT5(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int w = (width + 3) / 4;
|
int w = (width + 3) / 4;
|
||||||
int h = (height + 3) / 4;
|
int h = (height + 3) / 4;
|
||||||
@@ -344,20 +310,20 @@ public final class DDSReader {
|
|||||||
int t1 = (buffer[index] & 0x0C) >> 2;
|
int t1 = (buffer[index] & 0x0C) >> 2;
|
||||||
int t2 = (buffer[index] & 0x30) >> 4;
|
int t2 = (buffer[index] & 0x30) >> 4;
|
||||||
int t3 = (buffer[index++] & 0xC0) >> 6;
|
int t3 = (buffer[index++] & 0xC0) >> 6;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 0] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 0]), t0, order);
|
pixels[4 * width * i + 4 * j + width * k + 0] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 0]), t0);
|
||||||
if (4 * j + 1 >= width) continue;
|
if (4 * j + 1 >= width) continue;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 1]), t1, order);
|
pixels[4 * width * i + 4 * j + width * k + 1] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 1]), t1);
|
||||||
if (4 * j + 2 >= width) continue;
|
if (4 * j + 2 >= width) continue;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 2] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 2]), t2, order);
|
pixels[4 * width * i + 4 * j + width * k + 2] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 2]), t2);
|
||||||
if (4 * j + 3 >= width) continue;
|
if (4 * j + 3 >= width) continue;
|
||||||
pixels[4 * width * i + 4 * j + width * k + 3] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 3]), t3, order);
|
pixels[4 * width * i + 4 * j + width * k + 3] = getDXTColor(c0, c1, getDXT5Alpha(a0, a1, alphaTable[4 * k + 3]), t3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readA1R5G5B5(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readA1R5G5B5(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -372,7 +338,7 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readX1R5G5B5(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readX1R5G5B5(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -387,7 +353,7 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readA4R4G4B4(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readA4R4G4B4(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -402,7 +368,7 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readX4R4G4B4(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readX4R4G4B4(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -417,7 +383,7 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readR5G6B5(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readR5G6B5(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -432,7 +398,7 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readR8G8B8(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readR8G8B8(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -445,7 +411,7 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readA8B8G8R8(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readA8B8G8R8(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -458,7 +424,7 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readX8B8G8R8(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readX8B8G8R8(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -472,7 +438,7 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readA8R8G8B8(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readA8R8G8B8(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -485,7 +451,7 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int[] readX8R8G8B8(int width, int height, int offset, byte[] buffer, Order order) {
|
private static int[] readX8R8G8B8(int width, int height, int offset, byte[] buffer) {
|
||||||
int index = offset;
|
int index = offset;
|
||||||
int[] pixels = new int[width * height];
|
int[] pixels = new int[width * height];
|
||||||
for (int i = 0; i < height * width; i++) {
|
for (int i = 0; i < height * width; i++) {
|
||||||
@@ -499,21 +465,21 @@ public final class DDSReader {
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getDXTColor(int c0, int c1, int a, int t, Order order) {
|
private static int getDXTColor(int c0, int c1, int a, int t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case 0:
|
case 0:
|
||||||
return getDXTColor1(c0, a, order);
|
return getDXTColor1(c0, a);
|
||||||
case 1:
|
case 1:
|
||||||
return getDXTColor1(c1, a, order);
|
return getDXTColor1(c1, a);
|
||||||
case 2:
|
case 2:
|
||||||
return (c0 > c1) ? getDXTColor2_1(c0, c1, a, order) : getDXTColor1_1(c0, c1, a, order);
|
return (c0 > c1) ? getDXTColor2_1(c0, c1, a) : getDXTColor1_1(c0, c1, a);
|
||||||
case 3:
|
case 3:
|
||||||
return (c0 > c1) ? getDXTColor2_1(c1, c0, a, order) : 0;
|
return (c0 > c1) ? getDXTColor2_1(c1, c0, a) : 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getDXTColor2_1(int c0, int c1, int a, Order order) {
|
private static int getDXTColor2_1(int c0, int c1, int a) {
|
||||||
// 2*c0/3 + c1/3
|
// 2*c0/3 + c1/3
|
||||||
int r = (2 * BIT5[(c0 & 0xFC00) >> 11] + BIT5[(c1 & 0xFC00) >> 11]) / 3;
|
int r = (2 * BIT5[(c0 & 0xFC00) >> 11] + BIT5[(c1 & 0xFC00) >> 11]) / 3;
|
||||||
int g = (2 * BIT6[(c0 & 0x07E0) >> 5] + BIT6[(c1 & 0x07E0) >> 5]) / 3;
|
int g = (2 * BIT6[(c0 & 0x07E0) >> 5] + BIT6[(c1 & 0x07E0) >> 5]) / 3;
|
||||||
@@ -521,7 +487,7 @@ public final class DDSReader {
|
|||||||
return (a << order.alphaShift) | (r << order.redShift) | (g << order.greenShift) | (b << order.blueShift);
|
return (a << order.alphaShift) | (r << order.redShift) | (g << order.greenShift) | (b << order.blueShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getDXTColor1_1(int c0, int c1, int a, Order order) {
|
private static int getDXTColor1_1(int c0, int c1, int a) {
|
||||||
// (c0+c1) / 2
|
// (c0+c1) / 2
|
||||||
int r = (BIT5[(c0 & 0xFC00) >> 11] + BIT5[(c1 & 0xFC00) >> 11]) / 2;
|
int r = (BIT5[(c0 & 0xFC00) >> 11] + BIT5[(c1 & 0xFC00) >> 11]) / 2;
|
||||||
int g = (BIT6[(c0 & 0x07E0) >> 5] + BIT6[(c1 & 0x07E0) >> 5]) / 2;
|
int g = (BIT6[(c0 & 0x07E0) >> 5] + BIT6[(c1 & 0x07E0) >> 5]) / 2;
|
||||||
@@ -529,7 +495,7 @@ public final class DDSReader {
|
|||||||
return (a << order.alphaShift) | (r << order.redShift) | (g << order.greenShift) | (b << order.blueShift);
|
return (a << order.alphaShift) | (r << order.redShift) | (g << order.greenShift) | (b << order.blueShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getDXTColor1(int c, int a, Order order) {
|
private static int getDXTColor1(int c, int a) {
|
||||||
int r = BIT5[(c & 0xFC00) >> 11];
|
int r = BIT5[(c & 0xFC00) >> 11];
|
||||||
int g = BIT6[(c & 0x07E0) >> 5];
|
int g = BIT6[(c & 0x07E0) >> 5];
|
||||||
int b = BIT5[(c & 0x001F)];
|
int b = BIT5[(c & 0x001F)];
|
||||||
@@ -577,11 +543,11 @@ public final class DDSReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Image Type
|
// Image Type
|
||||||
private static final int DXT1 = (0x44585431);
|
private static final int DXT1 = (0x31545844);
|
||||||
private static final int DXT2 = (0x44585432);
|
private static final int DXT2 = (0x32545844);
|
||||||
private static final int DXT3 = (0x44585433);
|
private static final int DXT3 = (0x33545844);
|
||||||
private static final int DXT4 = (0x44585434);
|
private static final int DXT4 = (0x34545844);
|
||||||
private static final int DXT5 = (0x44585435);
|
private static final int DXT5 = (0x35545844);
|
||||||
private static final int A1R5G5B5 = ((1 << 16) | 2);
|
private static final int A1R5G5B5 = ((1 << 16) | 2);
|
||||||
private static final int X1R5G5B5 = ((2 << 16) | 2);
|
private static final int X1R5G5B5 = ((2 << 16) | 2);
|
||||||
private static final int A4R4G4B4 = ((3 << 16) | 2);
|
private static final int A4R4G4B4 = ((3 << 16) | 2);
|
||||||
@@ -609,9 +575,6 @@ public final class DDSReader {
|
|||||||
private static final int[] BIT5 = {0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255};
|
private static final int[] BIT5 = {0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255};
|
||||||
private static final int[] BIT6 = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255};
|
private static final int[] BIT6 = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247, 251, 255};
|
||||||
|
|
||||||
private DDSReader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class Order {
|
private static final class Order {
|
||||||
Order(int redShift, int greenShift, int blueShift, int alphaShift) {
|
Order(int redShift, int greenShift, int blueShift, int alphaShift) {
|
||||||
this.redShift = redShift;
|
this.redShift = redShift;
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user