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 + -
显示快捷键?