public void compressImage(java.awt.image.BufferedImage image, DXTCompressionAttributes attributes,
                                  java.nio.ByteBuffer buffer)
        {
            if (image == null)
            {
                String message = Logging.getMessage("nullValue.ImageIsNull");
                Logging.logger().severe(message);
                throw new ArgumentException(message);
            }
            if (attributes == null)
            {
                String message = Logging.getMessage("nullValue.AttributesIsNull");
                Logging.logger().severe(message);
                throw new ArgumentException(message);
            }
            if (buffer == null)
            {
                String message = Logging.getMessage("nullValue.BufferNull");
                Logging.logger().severe(message);
                throw new ArgumentException(message);
            }

            // If it is determined that the image and block have no alpha component, then we compress with DXT1 using a
            // four color palette. Otherwise, we use the three color palette (with the fourth color as transparent black).

            ColorBlock4x4       colorBlock          = new ColorBlock4x4();
            ColorBlockExtractor colorBlockExtractor = this.getColorBlockExtractor(image);

            BlockDXT1           dxt1Block      = new BlockDXT1();
            BlockDXT1Compressor dxt1Compressor = new BlockDXT1Compressor();

            int width  = image.getWidth();
            int height = image.getHeight();

            bool imageHasAlpha  = image.getColorModel().hasAlpha();
            bool enableAlpha    = attributes.isEnableDXT1Alpha();
            int  alphaThreshold = attributes.getDXT1AlphaThreshold();

            for (int j = 0; j < height; j += 4)
            {
                for (int i = 0; i < width; i += 4)
                {
                    colorBlockExtractor.extractColorBlock4x4(attributes, i, j, colorBlock);

                    if (enableAlpha && imageHasAlpha && blockHasDXT1Alpha(colorBlock, alphaThreshold))
                    {
                        dxt1Compressor.compressBlockDXT1a(colorBlock, attributes, dxt1Block);
                    }
                    else
                    {
                        dxt1Compressor.compressBlockDXT1(colorBlock, attributes, dxt1Block);
                    }

                    buffer.putShort((short)dxt1Block.color0);
                    buffer.putShort((short)dxt1Block.color1);
                    buffer.putInt((int)dxt1Block.colorIndexMask);
                }
            }
        }
        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));
            }

            return(mask);
        }