blockdxt1compressor.java

来自「world wind java sdk 源码」· Java 代码 · 共 527 行 · 第 1/2 页

JAVA
527
字号
/* Copyright (C) 2001, 2008 United States Government as represented bythe Administrator of the National Aeronautics and Space Administration.All Rights Reserved.*/package gov.nasa.worldwind.formats.dds;import gov.nasa.worldwind.util.Logging;/** * Compressor for DXT1 color blocks. This class is not thread safe. Unsynchronized access will result in unpredictable * behavior. Acces to methods of this class must be synchronized by the caller. * <p> * Documentation on the DXT1 format is available at http://msdn.microsoft.com/en-us/library/bb694531.aspx under * the name "BC1". * * @author dcollins * @version $Id: BlockDXT1Compressor.java 8991 2009-02-25 01:20:20Z dcollins $ */public class BlockDXT1Compressor{    // Implementation based on the paper "Real-Time DXT Compression" by J.M.P van Waveren    // http://www.intel.com/cd/ids/developer/asmo-na/eng/324337.htm    // and on the NVidia Texture Tools    // http://code.google.com/p/nvidia-texture-tools/    protected final Color32 minColor;    protected final Color32 maxColor;    protected final Color32[] palette;    /**     * Creates a new DXT1 block compressor.     */    public BlockDXT1Compressor()    {        this.minColor = new Color32();        this.maxColor = new Color32();        this.palette = new Color32[4];        for (int i = 0; i < 4; i++)        {            this.palette[i] = new Color32();        }    }    /**     * Compress the 4x4 color block into a DXT1 block using four colors. This method ignores transparency and     * guarantees that the DXT1 block will use four colors.     * <p>     * Access to this method must be synchronized by the caller. This method is frequenty invoked by the DXT     * compressor, so in order to reduce garbage each instance of this class has unsynchronized properties that are     * reused during each call.     *     * @param colorBlock the 4x4 color block to compress.     * @param attributes attributes that will control the compression.     * @param dxtBlock the DXT1 block that will receive the compressed data.     *     * @throws IllegalArgumentException if either <code>colorBlock</code> or <code>dxtBlock</code> are null.     */    public void compressBlockDXT1(ColorBlock4x4 colorBlock, DXTCompressionAttributes attributes, BlockDXT1 dxtBlock)    {        if (colorBlock == null)        {            String message = Logging.getMessage("nullValue.ColorBlockIsNull");            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);        }        if (dxtBlock == null)        {            String message = Logging.getMessage("nullValue.DXTBlockIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        this.chooseMinMaxColors(colorBlock, attributes, this.minColor, this.maxColor);        int color0 = short565FromColor32(this.maxColor);        int color1 = short565FromColor32(this.minColor);        if (color0 < color1)        {            int tmp = color0;            color0 = color1;            color1 = tmp;        }        // To get a four color palette with no alpha, the first color must be greater than the second color.        computeColorPalette4(color0, color1, this.palette);        dxtBlock.color0 = color0;        dxtBlock.color1 = color1;        dxtBlock.colorIndexMask = computePaletteIndices4(colorBlock, this.palette);    }    /**     * Compress the 4x4 color block into a DXT1 block with three colors. This method will consider a color transparent     * if its alpha value is less than <code>alphaThreshold</code>.     * <p>     * This method is frequenty invoked by the DXT compressor. In order to reduce garbage each instance of this class     * has buffer that is used during each call. Access to this method must be synchronized by the caller.     *     * @param colorBlock the 4x4 color block to compress.     * @param attributes attributes that will control the compression.     * @param dxtBlock the DXT1 block that will receive the compressed data.     *      * @throws IllegalArgumentException if either <code>colorBlock</code> or <code>dxtBlock</code> are null.     */    public void compressBlockDXT1a(ColorBlock4x4 colorBlock, DXTCompressionAttributes attributes, BlockDXT1 dxtBlock)    {        if (colorBlock == null)        {            String message = Logging.getMessage("nullValue.ColorBlockIsNull");            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);        }        if (dxtBlock == null)        {            String message = Logging.getMessage("nullValue.DXTBlockIsNull");            Logging.logger().severe(message);            throw new IllegalArgumentException(message);        }        this.chooseMinMaxColors(colorBlock, attributes, this.minColor, this.maxColor);        int color0 = short565FromColor32(this.maxColor);        int color1 = short565FromColor32(this.minColor);        if (color0 < color1)        {            int tmp = color0;            color0 = color1;            color1 = tmp;        }        // To get a three color palette with alpha, the first color must be less than the second color.        computeColorPalette3(color1, color0, this.palette);        dxtBlock.color0 = color1;        dxtBlock.color1 = color0;        dxtBlock.colorIndexMask = computePaletteIndices3(colorBlock, attributes, this.palette);    }    protected void chooseMinMaxColors(ColorBlock4x4 block, DXTCompressionAttributes attributes,        Color32 minColor, Color32 maxColor)    {        //noinspection StringEquality        if (attributes.getColorBlockCompressionType() == DXTCompressionAttributes.COLOR_BLOCK_COMPRESSION_BBOX)        {            findMinMaxColorsBox(block, minColor, maxColor);            selectDiagonal(block, minColor, maxColor);            insetBox(minColor, maxColor);        }        else //noinspection StringEquality            if (attributes.getColorBlockCompressionType() == DXTCompressionAttributes.COLOR_BLOCK_COMPRESSION_EUCLIDEAN_DISTANCE)        {            findMinMaxColorsEuclideanDistance(block, minColor, maxColor);        }        else //noinspection StringEquality                if (attributes.getColorBlockCompressionType() == DXTCompressionAttributes.COLOR_BLOCK_COMPRESSION_LUMINANCE_DISTANCE)        {            // Default to using euclidean distance to compute the min and max palette colors.            findMinMaxColorsLuminanceDistance(block, minColor, maxColor);        }    }    //**************************************************************//    //********************  Color Block Palette Assembly  **********//    //**************************************************************//    protected static void computeColorPalette3(int color0, int color1, Color32[] palette)    {        // Assign 16 bit 565 values to the color palette. We want to find the closest match to the hardware computed        // colors, and the hardware will be computing the colors using 16 bit 565 values. The second color is 1/2 on        // the line between max and min. The third color is considered to be transparent black. Computations of the        // second colors is based on the current hardware algorithms, and the Direct3D SDK docuemntation at        // http://msdn.microsoft.com/en-us/library/bb694531(VS.85).aspx        short565ToColor32(color0, palette[0]);        short565ToColor32(color1, palette[1]);        palette[2].a = 255;        palette[2].r = (palette[0].r + palette[1].r) / 2;        palette[2].g = (palette[0].g + palette[1].g) / 2;        palette[2].b = (palette[0].b + palette[1].b) / 2;        // Set all components to 0 to match DXT specs.        palette[3].a = 0;        palette[3].r = 0;        palette[3].g = 0;        palette[3].b = 0;    }    protected static void computeColorPalette4(int color0, int color1, Color32[] palette)    {        // Assign 16 bit 565 values to the color palette. We want to find the closest match to the hardware computed        // colors, and the hardware will be computing the colors using 16 bit 565 values. The second color is 1/3 on        // the line between max and min. The third color is 2/3 on the line between max and min. Computations of the        // second and third colors are based on the current hardware algorithms, and the Direct3D SDK docuemntation at        // http://msdn.microsoft.com/en-us/library/bb694531(VS.85).aspx        short565ToColor32(color0, palette[0]);        short565ToColor32(color1, palette[1]);        palette[2].a = 255;        palette[2].r = (2 * palette[0].r + palette[1].r) / 3;        palette[2].g = (2 * palette[0].g + palette[1].g) / 3;        palette[2].b = (2 * palette[0].b + palette[1].b) / 3;        palette[2].a = 255;        palette[3].r = (palette[0].r + 2 * palette[1].r) / 3;        palette[3].g = (palette[0].g + 2 * palette[1].g) / 3;        palette[3].b = (palette[0].b + 2 * palette[1].b) / 3;    }    protected static long computePaletteIndices3(ColorBlock4x4 block, DXTCompressionAttributes attributes,        Color32[] palette)    {        // This implementation is based on code available in the nvidia-texture-tools project:        // http://code.google.com/p/nvidia-texture-tools/        //        // If the pixel alpha is below the specified threshold, we return index 3. In a three color DXT1 palette,        // index 3 is interpreted as transparent black. Otherwise, we compare the sums of absolute differences, and        // choose the nearest color index.        int alphaThreshold = attributes.getDXT1AlphaThreshold();        long mask = 0L;        long index;        for (int i = 0; i < 16; i++)        {            int d0 = colorDistanceSquared(palette[0], block.color[i]);            int d1 = colorDistanceSquared(palette[1], block.color[i]);            int d2 = colorDistanceSquared(palette[2], block.color[i]);            // TODO: implement bit twiddle as in computePaletteIndex4 to avoid conditional branching            if (block.color[i].a < alphaThreshold)            {                index = 3;            }            else if (d0 < d1 && d0 < d2)            {                index = 0;            }            else if (d1 < d2)            {                index = 1;            }            else            {                index = 2;            }            mask |= (index << (i << 1));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?