ddscompressor.java
来自「world wind java sdk 源码」· Java 代码 · 共 436 行 · 第 1/2 页
JAVA
436 行
* @param attributes attributes that will control the compression. * * @return buffer little endian ordered ByteBuffer containing the dds file bytes. * @throws IllegalArgumentException if either <code>image</code> or <code>attributes</code> are null, or if * <code>image</code> has non power of two dimensions. */ public java.nio.ByteBuffer compressImageDXT3(java.awt.image.BufferedImage image, DXTCompressionAttributes attributes) { if (image == null) { String message = Logging.getMessage("nullValue.ImageIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (!WWMath.isPowerOfTwo(image.getWidth()) || !WWMath.isPowerOfTwo(image.getHeight())) { String message = Logging.getMessage("generic.InvalidImageSize", image.getWidth(), image.getHeight()); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (attributes == null) { String message = Logging.getMessage("nullValue.AttributesIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } DXT3Compressor compressor = new DXT3Compressor(); return this.doCompressImage(compressor, image, attributes); } protected java.nio.ByteBuffer doCompressImage(DXTCompressor compressor, java.awt.image.BufferedImage image, DXTCompressionAttributes attributes) { // Create the DDS header structure that describes the specified image, compressor, and compression attributes. DDSHeader header = this.createDDSHeader(compressor, image, attributes); // Compute the DDS file size and mip map levels. If the attributes specify to build mip maps, then we compute // the total file size including mip maps, create a chain of mip map images, and update the DDS header to // describe the number of mip map levels. Otherwise, we compute the file size for a single image and do nothing // to the DDS header. java.awt.image.BufferedImage[] mipMapLevels = null; int fileSize = 4 + header.getSize(); if (attributes.isBuildMipmaps()) { mipMapLevels = this.buildMipMaps(image, attributes); for (java.awt.image.BufferedImage mipMapImage : mipMapLevels) { fileSize += compressor.getCompressedSize(mipMapImage, attributes); } header.setFlags(header.getFlags() | DDSConstants.DDSD_MIPMAPCOUNT); header.setMipMapCount(mipMapLevels.length); } else { fileSize += compressor.getCompressedSize(image, attributes); } // Create a little endian buffer that will hold the bytes of the DDS file. java.nio.ByteBuffer buffer = this.createBuffer(fileSize); buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN); // Write the DDS magic number and DDS header to the file. buffer.putInt(DDSConstants.MAGIC); this.writeDDSHeader(header, buffer); // Write the compressed DXT blocks to the DDS file. If the attributes specify to build mip maps, then we write // each mip map level to the DDS file, starting with level 0 and ending with level N. Otherwise, we write a // single image to the DDS file. if (mipMapLevels == null) { compressor.compressImage(image, attributes, buffer); } else { for (java.awt.image.BufferedImage mipMapImage : mipMapLevels) { compressor.compressImage(mipMapImage, attributes, buffer); } } buffer.rewind(); return buffer; } protected DXTCompressor getDXTCompressor(java.awt.image.BufferedImage image, DXTCompressionAttributes attributes) { // If the caller specified a DXT format in the attributes, then we return a compressor matching that format. // Otherwise, we choose one automatically from the image type. If no choice can be made from the image type, // we default to using a DXT3 compressor. if (attributes.getDXTFormat() == DDSConstants.D3DFMT_DXT1) { return new DXT1Compressor(); } else if (attributes.getDXTFormat() == DDSConstants.D3DFMT_DXT2 || attributes.getDXTFormat() == DDSConstants.D3DFMT_DXT3) { return new DXT3Compressor(); } else if (!image.getColorModel().hasAlpha()) { return new DXT1Compressor(); } else { return new DXT3Compressor(); } } protected java.nio.ByteBuffer createBuffer(int size) { return java.nio.ByteBuffer.allocateDirect(size); } @SuppressWarnings({"UnusedDeclaration"}) protected java.awt.image.BufferedImage[] buildMipMaps(java.awt.image.BufferedImage image, DXTCompressionAttributes attributes) { // Build the mipmap chain using a premultiplied alpha image format. This is necessary to ensure that // transparent colors do not bleed into the opaque colors. For example, without premultiplied alpha the colors // in a totally transparent pixel may contribute when one mipmap level is filtered (with either a box or a // bilinear filter) to produce the pixels for the next level. // // The DXT color block extractor typically accessed BufferedImage data via a call to getRGB(). This returns // a packed 8888 ARGB int, where the color components are known to be not premultiplied, and in the sRGB color // space. Therefore computing mipmaps in this way does not affect the rest of the DXT pipeline, unless color // data is accessed directly. In this case, such code would be responsible for recognizing the color model // (premultiplied) and behaving accordingly. int mipmapImageType = BufferedImage.TYPE_INT_ARGB_PRE; int maxLevel = ImageUtil.getMaxMipmapLevel(image.getWidth(), image.getHeight()); return ImageUtil.buildMipmaps(image, mipmapImageType, maxLevel); } protected DDSHeader createDDSHeader(DXTCompressor compressor, java.awt.image.BufferedImage image, DXTCompressionAttributes attributes) { DDSPixelFormat pixelFormat = new DDSPixelFormat(); pixelFormat.setFlags(pixelFormat.getFlags() | DDSConstants.DDPF_FOURCC); pixelFormat.setFourCC(compressor.getDXTFormat()); DDSHeader header = new DDSHeader(); header.setFlags(header.getFlags() | DDSConstants.DDSD_WIDTH | DDSConstants.DDSD_HEIGHT | DDSConstants.DDSD_LINEARSIZE | DDSConstants.DDSD_PIXELFORMAT | DDSConstants.DDSD_CAPS); header.setWidth(image.getWidth()); header.setHeight(image.getHeight()); header.setLinearSize(compressor.getCompressedSize(image, attributes)); header.setPixelFormat(pixelFormat); header.setCaps(header.getCaps() | DDSConstants.DDSCAPS_TEXTURE); return header; } /** * Documentation on the DDS header format is available at * http://msdn.microsoft.com/en-us/library/bb943982(VS.85).aspx * * @param header header structure to write. * @param buffer buffer that will receive the header structure bytes. */ protected void writeDDSHeader(DDSHeader header, java.nio.ByteBuffer buffer) { int pos = buffer.position(); buffer.putInt(header.getSize()); // dwSize buffer.putInt(header.getFlags()); // dwFlags buffer.putInt(header.getHeight()); // dwHeight buffer.putInt(header.getWidth()); // dwWidth buffer.putInt(header.getLinearSize()); // dwLinearSize buffer.putInt(header.getDepth()); // dwDepth buffer.putInt(header.getMipMapCount()); // dwMipMapCount buffer.position(buffer.position() + 44); // dwReserved1[11] (unused) this.writeDDSPixelFormat(header.getPixelFormat(), buffer); // ddpf buffer.putInt(header.getCaps()); // dwCaps buffer.putInt(header.getCaps2()); // dwCaps2 buffer.putInt(header.getCaps3()); // dwCaps3 buffer.putInt(header.getCaps4()); // dwCaps4 buffer.position(buffer.position() + 4); // dwReserved2 (unused) buffer.position(pos + header.getSize()); } /** * Documentation on the DDS pixel format is available at * http://msdn.microsoft.com/en-us/library/bb943984(VS.85).aspx * * @param pixelFormat pixel format structure to write. * @param buffer buffer that will receive the pixel format structure bytes. */ protected void writeDDSPixelFormat(DDSPixelFormat pixelFormat, java.nio.ByteBuffer buffer) { int pos = buffer.position(); buffer.putInt(pixelFormat.getSize()); // dwSize buffer.putInt(pixelFormat.getFlags()); // dwFlags buffer.putInt(pixelFormat.getFourCC()); // dwFourCC buffer.putInt(pixelFormat.getRGBBitCount()); // dwRGBBitCount buffer.putInt(pixelFormat.getRBitMask()); // dwRBitMask buffer.putInt(pixelFormat.getGBitMask()); // dwGBitMask buffer.putInt(pixelFormat.getBBitMask()); // dwBBitMask buffer.putInt(pixelFormat.getABitMask()); // dwABitMask buffer.position(pos + pixelFormat.getSize()); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?