Example #1
0
 private static byte[] DecompressDxt(EndianBinaryReader reader, DxtFormat format, int width, int height)
 {
     byte[] pixelData = new byte[width * height * 4];
     for (int y = 0; y < height; y += 4)
     {
         for (int x = 0; x < width; x += 4)
         {
             byte[] decompressedBlock = DecompressDxtBlock(reader, format);
             for (int py = 0; py < 4; py++)
             {
                 for (int px = 0; px < 4; px++)
                 {
                     int ix = (x + px);
                     int iy = (y + py);
                     if (ix >= width || iy >= height)
                     {
                         continue;
                     }
                     for (int c = 0; c < 4; c++)
                     {
                         pixelData[(((iy * width) + ix) * 4) + c] = decompressedBlock[(((py * 4) + px) * 4) + c];
                     }
                 }
             }
         }
     }
     return(pixelData);
 }
Example #2
0
        public DXT(DxtFormat format)
        {
            BitDepth      = (format == DxtFormat.DXT1) ? 4 : 8;
            BlockBitDepth = (format == DxtFormat.DXT1) ? 64 : 128;

            _format = format;

            FormatName = format.ToString();
        }
Example #3
0
        private static byte[] DecompressDxtBlock(EndianBinaryReader reader, DxtFormat format)
        {
            byte[] outputData = new byte[(4 * 4) * 4];
            byte[] colorData  = null, alphaData = null;

            if (format != DxtFormat.DXT1)
            {
                alphaData = DecompressDxtAlpha(reader, format);
            }

            colorData = DecompressDxtColor(reader, format);

            for (int i = 0; i < colorData.Length; i += 4)
            {
                outputData[i]     = colorData[i];
                outputData[i + 1] = colorData[i + 1];
                outputData[i + 2] = colorData[i + 2];
                outputData[i + 3] = (alphaData != null ? alphaData[i + 3] : colorData[i + 3]);
            }

            return(outputData);
        }
Example #4
0
 public ColorFetcherDXT(Stream stream, long blockCount, DxtFormat format)
 {
     SourceStream = stream;
     BlockCount   = blockCount;
     Format       = format;
 }
Example #5
0
 public ColorFetcherDXT(Stream stream, long width, long height, DxtFormat format)
 {
     SourceStream = stream;
     BlockCount   = ((width + 3) / 4) * ((height + 3) / 4);
     Format       = format;
 }
Example #6
0
 public Encoder(DxtFormat format)
 {
     _queue  = new List <Color>();
     _format = format;
 }
Example #7
0
        private static Bitmap LoadDDS(EndianBinaryReader reader)
        {
            DDSHeader header = new DDSHeader(reader);
            Bitmap    bitmap = new Bitmap((int)header.Width, (int)header.Height, PixelFormat.Format32bppArgb);

            byte[] pixelData = null;

            if (header.PixelFormat.Flags.HasFlag(DDPF.FourCC))
            {
                DxtFormat dxtFormat = DxtFormat.DXT1;
                switch (header.PixelFormat.FourCC)
                {
                case "DXT1": dxtFormat = DxtFormat.DXT1; break;

                case "DXT3": dxtFormat = DxtFormat.DXT3; break;

                case "DXT5": dxtFormat = DxtFormat.DXT5; break;
                }

                pixelData = DecompressDxt(reader, dxtFormat, (int)header.Width, (int)header.Height);
            }
            else
            {
                // TODO: verify all of these, the non-32bit ones especially

                pixelData = new byte[(header.Width * header.Height) * 4];
                int rawLength = (int)(header.Height * (((header.Width * header.PixelFormat.RGBBitCount) + 7) / 8));

                if (header.PixelFormat.Flags.HasFlag(DDPF.RGB))
                {
                    switch (header.PixelFormat.RGBBitCount)
                    {
                    case 32:
                        if (CheckBitmasks(header.PixelFormat, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000))
                        {
                            // R8 G8 B8 A8
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 4)
                            {
                                pixelData[i + 2] = reader.ReadByte();
                                pixelData[i + 1] = reader.ReadByte();
                                pixelData[i + 0] = reader.ReadByte();
                                pixelData[i + 3] = reader.ReadByte();
                            }
                        }
                        else if (CheckBitmasks(header.PixelFormat, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000))
                        {
                            // B8 G8 R8 A8
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 4)
                            {
                                pixelData[i + 0] = reader.ReadByte();
                                pixelData[i + 1] = reader.ReadByte();
                                pixelData[i + 2] = reader.ReadByte();
                                pixelData[i + 3] = reader.ReadByte();
                            }
                        }
                        else if (CheckBitmasks(header.PixelFormat, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000))
                        {
                            // B8 G8 R8 X8
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 4)
                            {
                                pixelData[i + 0] = reader.ReadByte();
                                pixelData[i + 1] = reader.ReadByte();
                                pixelData[i + 2] = reader.ReadByte();
                                pixelData[i + 3] = 0xFF;
                                reader.ReadByte();      // X
                            }
                        }
                        else if (CheckBitmasks(header.PixelFormat, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000))
                        {
                            // X8 B8 G8 R8
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 4)
                            {
                                reader.ReadByte();      // X
                                pixelData[i + 0] = reader.ReadByte();
                                pixelData[i + 1] = reader.ReadByte();
                                pixelData[i + 2] = reader.ReadByte();
                                pixelData[i + 3] = 0xFF;
                            }
                        }
                        break;

                    case 24:
                        if (CheckBitmasks(header.PixelFormat, 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000))
                        {
                            // R8 G8 B8
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 3)
                            {
                                pixelData[i + 2] = reader.ReadByte();
                                pixelData[i + 1] = reader.ReadByte();
                                pixelData[i + 0] = reader.ReadByte();
                                pixelData[i + 3] = 0xFF;
                            }
                        }
                        break;

                    case 16:
                        if (CheckBitmasks(header.PixelFormat, 0x7C00, 0x03E0, 0x001F, 0x8000))
                        {
                            // B5 G5 R5 A1
                        }
                        else if (CheckBitmasks(header.PixelFormat, 0xF800, 0x07E0, 0x001F, 0x0000))
                        {
                            // B5 G6 R5
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 2)
                            {
                                UnpackRgb565(reader.ReadUInt16(), out byte r, out byte g, out byte b);
                                pixelData[i + 0] = b;
                                pixelData[i + 1] = g;
                                pixelData[i + 2] = r;
                                pixelData[i + 3] = 0xFF;
                            }
                        }
                        else if (CheckBitmasks(header.PixelFormat, 0x0F00, 0x00F0, 0x000F, 0xF000))
                        {
                            // B4 G4 R4 A4
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 2)
                            {
                                byte bg = reader.ReadByte();
                                byte ra = reader.ReadByte();
                                pixelData[i + 0] = (byte)((bg & 0xF0) | (bg & 0xF0) >> 4);
                                pixelData[i + 1] = (byte)((bg & 0x0F) << 4 | (bg & 0x0F));
                                pixelData[i + 2] = (byte)((ra & 0xF0) | (ra & 0xF0) >> 4);
                                pixelData[i + 3] = (byte)((ra & 0x0F) << 4 | (ra & 0x0F));
                            }
                        }
                        break;
                    }
                }
                else if (header.PixelFormat.Flags.HasFlag(DDPF.Luminance))
                {
                    switch (header.PixelFormat.RGBBitCount)
                    {
                    case 16:
                        if (CheckBitmasks(header.PixelFormat, 0x00FF, 0x0000, 0x0000, 0x00FF))
                        {
                            // R8 G8
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 2)
                            {
                                byte v = reader.ReadByte();
                                byte a = reader.ReadByte();
                                pixelData[i + 2] = v;
                                pixelData[i + 1] = v;
                                pixelData[i + 0] = v;
                                pixelData[i + 3] = a;
                            }
                        }
                        break;

                    case 8:
                        if (CheckBitmasks(header.PixelFormat, 0xFF, 0x00, 0x00, 0x00))
                        {
                            // R8
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 1)
                            {
                                byte v = reader.ReadByte();
                                pixelData[i + 2] = v;
                                pixelData[i + 1] = v;
                                pixelData[i + 0] = v;
                                pixelData[i + 3] = v;
                            }
                        }
                        else if (CheckBitmasks(header.PixelFormat, 0xF0, 0x00, 0x00, 0x0F))
                        {
                            // R4 G4
                            for (int i = 0, j = 0; j < rawLength; i += 4, j += 1)
                            {
                                byte v = reader.ReadByte();
                                pixelData[i + 2] = (byte)((v & 0xF0) | (v & 0xF0) >> 4);
                                pixelData[i + 1] = (byte)((v & 0xF0) | (v & 0xF0) >> 4);
                                pixelData[i + 0] = (byte)((v & 0xF0) | (v & 0xF0) >> 4);
                                pixelData[i + 3] = (byte)((v & 0x0F) << 4 | (v & 0x0F));
                            }
                        }
                        break;
                    }
                }
                else if (header.PixelFormat.Flags.HasFlag(DDPF.Alpha))
                {
                    if (header.PixelFormat.RGBBitCount == 8)
                    {
                        // A8
                        for (int i = 0, j = 0; j < rawLength; i += 4, j += 1)
                        {
                            pixelData[i + 2] = 0xFF;
                            pixelData[i + 1] = 0xFF;
                            pixelData[i + 0] = 0xFF;
                            pixelData[i + 3] = reader.ReadByte();
                        }
                    }
                }
            }

            if (pixelData != null)
            {
                BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat);
                Marshal.Copy(pixelData, 0, bmpData.Scan0, pixelData.Length);
                bitmap.UnlockBits(bmpData);
            }

            return(bitmap);
        }
Example #8
0
        private static byte[] DecompressDxtAlpha(EndianBinaryReader reader, DxtFormat format)
        {
            byte[] alphaOut = new byte[(4 * 4) * 4];
            switch (format)
            {
            case DxtFormat.DXT3:
            {
                ulong alpha = reader.ReadUInt64(Endian.LittleEndian);
                for (int i = 0; i < alphaOut.Length; i += 4)
                {
                    alphaOut[i + 3] = (byte)(((alpha & 0xF) << 4) | (alpha & 0xF));
                    alpha         >>= 4;
                }
            }
            break;

            case DxtFormat.DXT5:
            {
                byte alpha0 = reader.ReadByte();
                byte alpha1 = reader.ReadByte();
                byte bits_5 = reader.ReadByte();
                byte bits_4 = reader.ReadByte();
                byte bits_3 = reader.ReadByte();
                byte bits_2 = reader.ReadByte();
                byte bits_1 = reader.ReadByte();
                byte bits_0 = reader.ReadByte();

                ulong bits = (ulong)(((ulong)bits_0 << 40) | ((ulong)bits_1 << 32) | ((ulong)bits_2 << 24) | ((ulong)bits_3 << 16) | ((ulong)bits_4 << 8) | (ulong)bits_5);

                byte[] bitsExt = new byte[16];
                for (int i = 0; i < bitsExt.Length; i++)
                {
                    bitsExt[i] = (byte)((bits >> (i * 3)) & 0x7);
                }

                for (int y = 0; y < 4; y++)
                {
                    for (int x = 0; x < 4; x++)
                    {
                        byte code       = bitsExt[(y * 4) + x];
                        int  destOffset = (((y * 4) + x) * 4) + 3;

                        if (alpha0 > alpha1)
                        {
                            switch (code)
                            {
                            case 0x00: alphaOut[destOffset] = alpha0; break;

                            case 0x01: alphaOut[destOffset] = alpha1; break;

                            case 0x02: alphaOut[destOffset] = (byte)((6 * alpha0 + 1 * alpha1) / 7); break;

                            case 0x03: alphaOut[destOffset] = (byte)((5 * alpha0 + 2 * alpha1) / 7); break;

                            case 0x04: alphaOut[destOffset] = (byte)((4 * alpha0 + 3 * alpha1) / 7); break;

                            case 0x05: alphaOut[destOffset] = (byte)((3 * alpha0 + 4 * alpha1) / 7); break;

                            case 0x06: alphaOut[destOffset] = (byte)((2 * alpha0 + 5 * alpha1) / 7); break;

                            case 0x07: alphaOut[destOffset] = (byte)((1 * alpha0 + 6 * alpha1) / 7); break;
                            }
                        }
                        else
                        {
                            switch (code)
                            {
                            case 0x00: alphaOut[destOffset] = alpha0; break;

                            case 0x01: alphaOut[destOffset] = alpha1; break;

                            case 0x02: alphaOut[destOffset] = (byte)((4 * alpha0 + 1 * alpha1) / 5); break;

                            case 0x03: alphaOut[destOffset] = (byte)((3 * alpha0 + 2 * alpha1) / 5); break;

                            case 0x04: alphaOut[destOffset] = (byte)((2 * alpha0 + 3 * alpha1) / 5); break;

                            case 0x05: alphaOut[destOffset] = (byte)((1 * alpha0 + 4 * alpha1) / 5); break;

                            case 0x06: alphaOut[destOffset] = 0x00; break;

                            case 0x07: alphaOut[destOffset] = 0xFF; break;
                            }
                        }
                    }
                }
            }
            break;
            }

            return(alphaOut);
        }
Example #9
0
        private static byte[] DecompressDxtColor(EndianBinaryReader reader, DxtFormat format)
        {
            byte[] colorOut = new byte[(4 * 4) * 4];

            ushort color0 = reader.ReadUInt16(Endian.LittleEndian);
            ushort color1 = reader.ReadUInt16(Endian.LittleEndian);
            uint   bits   = reader.ReadUInt32(Endian.LittleEndian);

            byte c0r, c0g, c0b, c1r, c1g, c1b;

            UnpackRgb565(color0, out c0r, out c0g, out c0b);
            UnpackRgb565(color1, out c1r, out c1g, out c1b);

            byte[] bitsExt = new byte[16];
            for (int i = 0; i < bitsExt.Length; i++)
            {
                bitsExt[i] = (byte)((bits >> (i * 2)) & 0x3);
            }

            for (int y = 0; y < 4; y++)
            {
                for (int x = 0; x < 4; x++)
                {
                    byte code       = bitsExt[(y * 4) + x];
                    int  destOffset = ((y * 4) + x) * 4;

                    if (format == DxtFormat.DXT1)
                    {
                        colorOut[destOffset + 3] = (byte)((color0 <= color1 && code == 3) ? 0 : 0xFF);
                    }

                    if (format == DxtFormat.DXT1 && color0 <= color1)
                    {
                        switch (code)
                        {
                        case 0x00:
                            colorOut[destOffset + 0] = c0b;
                            colorOut[destOffset + 1] = c0g;
                            colorOut[destOffset + 2] = c0r;
                            break;

                        case 0x01:
                            colorOut[destOffset + 0] = c1b;
                            colorOut[destOffset + 1] = c1g;
                            colorOut[destOffset + 2] = c1r;
                            break;

                        case 0x02:
                            colorOut[destOffset + 0] = (byte)((c0b + c1b) / 2);
                            colorOut[destOffset + 1] = (byte)((c0g + c1g) / 2);
                            colorOut[destOffset + 2] = (byte)((c0r + c1r) / 2);
                            break;

                        case 0x03:
                            colorOut[destOffset + 0] = 0;
                            colorOut[destOffset + 1] = 0;
                            colorOut[destOffset + 2] = 0;
                            break;
                        }
                    }
                    else
                    {
                        switch (code)
                        {
                        case 0x00:
                            colorOut[destOffset + 0] = c0b;
                            colorOut[destOffset + 1] = c0g;
                            colorOut[destOffset + 2] = c0r;
                            break;

                        case 0x01:
                            colorOut[destOffset + 0] = c1b;
                            colorOut[destOffset + 1] = c1g;
                            colorOut[destOffset + 2] = c1r;
                            break;

                        case 0x02:
                            colorOut[destOffset + 0] = (byte)((2 * c0b + c1b) / 3);
                            colorOut[destOffset + 1] = (byte)((2 * c0g + c1g) / 3);
                            colorOut[destOffset + 2] = (byte)((2 * c0r + c1r) / 3);
                            break;

                        case 0x03:
                            colorOut[destOffset + 0] = (byte)((c0b + 2 * c1b) / 3);
                            colorOut[destOffset + 1] = (byte)((c0g + 2 * c1g) / 3);
                            colorOut[destOffset + 2] = (byte)((c0r + 2 * c1r) / 3);
                            break;
                        }
                    }
                }
            }

            return(colorOut);
        }
Example #10
0
 public Decoder(DxtFormat format)
 {
     _queue  = new Queue <Color>();
     _format = format;
 }