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