Exemple #1
0
        public DDSHeader CreateHeader(int pixelWidth, int pixelHeight, uint fourCC)
        {
            if (pixelHeight < 0 || pixelWidth < 0)
            {
                throw new InvalidOperationException("Image width or height is negative.");
            }

            var pixelFormat = new DDSPixelFormat
            {
                Size   = 32,
                Flags  = 0x4,
                FourCC = fourCC
            };

            var header = new DDSHeader
            {
                Size        = 124, // has to be 124bytes ¯\_(ツ)_/¯
                Flags       = Helpers.DDSMinFlags(),
                Height      = (uint)pixelHeight,
                Width       = (uint)pixelWidth,
                PixelFormat = pixelFormat,
                MipMapCount = 0,
                Caps        = 0x1000 // texture, we don't handle harder things right now
            };

            header.PitchOrLinearSize = Math.Max(1, (header.Width + 3) / 4) * Math.Max(1, (header.Height + 3) / 4) * 8;

            return(header);
        }
Exemple #2
0
            internal static DDSHeader Read(BinaryReader br)
            {
                var h = new DDSHeader();

                h.size        = br.ReadInt32();
                h.flags       = br.ReadInt32();
                h.height      = br.ReadInt32();
                h.width       = br.ReadInt32();
                h.sizeOrPitch = br.ReadInt32();
                h.depth       = br.ReadInt32();
                h.mipMapCount = br.ReadInt32();

                h.reserved1 = new int[11];
                for (var i = 0; i < 11; ++i)
                {
                    h.reserved1[i] = br.ReadInt32();
                }

                h.pixelFormat = DDSPixelFormat.Read(br);
                h.caps        = DDSCaps.Read(br);

                h.reserved2 = br.ReadInt32();

                return(h);
            }
Exemple #3
0
        // iCompFormatToBpp
        internal static uint PixelFormatToBpp(DDSPixelFormat pf, uint rgbbitcount)
        {
            switch (pf)
            {
            case DDSPixelFormat.LUMINANCE:
            case DDSPixelFormat.LUMINANCE_ALPHA:
            case DDSPixelFormat.RGBA:
            case DDSPixelFormat.RGB:
                return(rgbbitcount / 8);

            case DDSPixelFormat.THREEDC:
            case DDSPixelFormat.RXGB:
                return(3);

            case DDSPixelFormat.ATI1N:
                return(1);

            case DDSPixelFormat.R16F:
                return(2);

            case DDSPixelFormat.A16B16G16R16:
            case DDSPixelFormat.A16B16G16R16F:
            case DDSPixelFormat.G32R32F:
                return(8);

            case DDSPixelFormat.A32B32G32R32F:
                return(16);

            default:
                return(4);
            }
        }
Exemple #4
0
        public static TextureFormat GetTextureFormat(DDSPixelFormat pixelFormat)
        {
            switch (pixelFormat.FourCC)
            {
            case DDSPixelFormatFourCC.R8G8B8:
                return(TextureFormat.RGB);

            case DDSPixelFormatFourCC.A8R8G8B8:
                return(TextureFormat.RGBA);

            case DDSPixelFormatFourCC.A4R4G4B4:
                return(TextureFormat.RGBA4);

            case DDSPixelFormatFourCC.DXT1:
                return(TextureFormat.DXT1);

            case DDSPixelFormatFourCC.DXT3:
                return(TextureFormat.DXT3);

            case DDSPixelFormatFourCC.DXT4:
                return(TextureFormat.DXT4);

            case DDSPixelFormatFourCC.DXT5:
                return(TextureFormat.DXT5);

            case DDSPixelFormatFourCC.ATI1:
                return(TextureFormat.ATI1);

            case DDSPixelFormatFourCC.ATI2N_3Dc:
                return(TextureFormat.ATI2);

            default:
                throw new ArgumentException(nameof(pixelFormat));
            }
        }
Exemple #5
0
        private void SetPixelFormatData(int pixelFormatID)
        {
            ddsPF               = new DDSPixelFormat();
            ddsPF.caps2         = 0;
            ddsPF.dwSize        = 32;
            ddsPF.dwFlags       = 4;
            ddsPF.dwFourCC      = 0x31545844;
            ddsPF.dwRGBBitCount = 0;
            ddsPF.dwRBitMask    = 0;
            ddsPF.dwGBitMask    = 0;
            ddsPF.dwBBitMask    = 0;
            ddsPF.dwABitMask    = 0;
            if (PixelFormatTypes.ContainsKey(pixelFormatID))
            {
                ddsPF.dwFourCC = PixelFormatTypes[pixelFormatID];
                if (pixelFormatID == 0x01)
                {
                    ddsPF.dwFlags |= 0x01;
                }
            }
            else
            {
                switch (pixelFormatID)
                {
                case 0x0B:
                case 0x36:
                    ddsPF.dwFourCC      = 0x00;
                    ddsPF.dwRGBBitCount = 0x20;
                    ddsPF.dwRBitMask    = 0xFF;
                    ddsPF.dwGBitMask    = 0xFF00;
                    ddsPF.dwBBitMask    = 0xFF0000;
                    ddsPF.dwABitMask    = 0xFF000000;
                    ddsPF.dwFlags       = 0x41;
                    if (pixelFormatID == 0x36)
                    {
                        ddsPF.caps2 = 0xFE00;
                    }
                    break;

                case 0x0C:
                    ddsPF.dwFourCC      = 0x00;
                    ddsPF.dwRGBBitCount = 0x08;
                    ddsPF.dwABitMask    = 0xFF;
                    ddsPF.dwFlags       = 0x02;
                    break;

                case 0x0D:
                    ddsPF.dwFourCC      = 0x00;
                    ddsPF.dwRGBBitCount = 0x10;
                    ddsPF.dwRBitMask    = 0xFFFF;
                    ddsPF.dwFlags       = 0x20000;
                    break;
                }
            }
        }
Exemple #6
0
        private static unsafe byte[] DecompressRGBA(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            // allocate bitmap
            int bpp         = (int)(DDSHelper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount));
            int bps         = (int)(header.width * bpp * DDSHelper.PixelFormatToBpc(pixelFormat));
            int sizeofplane = (int)(bps * header.height);
            int width       = (int)header.width;
            int height      = (int)header.height;
            int depth       = (int)header.depth;

            byte[] rawData = new byte[depth * sizeofplane + height * bps + width * bpp];

            uint valMask = (uint)((header.pixelformat.rgbbitcount == 32) ? ~0 : (1 << (int)header.pixelformat.rgbbitcount) - 1);
            // Funny x86s, make 1 << 32 == 1
            uint pixSize = (header.pixelformat.rgbbitcount + 7) / 8;
            int  rShift1 = 0; int rMul = 0; int rShift2 = 0;

            DDSHelper.ComputeMaskParams(header.pixelformat.rbitmask, ref rShift1, ref rMul, ref rShift2);
            int gShift1 = 0; int gMul = 0; int gShift2 = 0;

            DDSHelper.ComputeMaskParams(header.pixelformat.gbitmask, ref gShift1, ref gMul, ref gShift2);
            int bShift1 = 0; int bMul = 0; int bShift2 = 0;

            DDSHelper.ComputeMaskParams(header.pixelformat.bbitmask, ref bShift1, ref bMul, ref bShift2);
            int aShift1 = 0; int aMul = 0; int aShift2 = 0;

            DDSHelper.ComputeMaskParams(header.pixelformat.alphabitmask, ref aShift1, ref aMul, ref aShift2);

            int offset = 0;
            int pixnum = width * height * depth;

            fixed(byte *bytePtr = data)
            {
                byte *temp = bytePtr;

                while (pixnum-- > 0)
                {
                    uint px = *((uint *)temp) & valMask;
                    temp += pixSize;
                    uint pxc = px & header.pixelformat.rbitmask;
                    rawData[offset + 0] = (byte)(((pxc >> rShift1) * rMul) >> rShift2);
                    pxc = px & header.pixelformat.gbitmask;
                    rawData[offset + 1] = (byte)(((pxc >> gShift1) * gMul) >> gShift2);
                    pxc = px & header.pixelformat.bbitmask;
                    rawData[offset + 2] = (byte)(((pxc >> bShift1) * bMul) >> bShift2);
                    pxc = px & header.pixelformat.alphabitmask;
                    rawData[offset + 3] = (byte)(((pxc >> aShift1) * aMul) >> aShift2);
                    offset += 4;
                }
            }

            return(rawData);
        }
Exemple #7
0
        private static byte[] DecompressDXT4(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            // allocate bitmap
            int width  = (int)header.width;
            int height = (int)header.height;
            int depth  = (int)header.depth;

            // Can do color & alpha same as dxt5, but color is pre-multiplied
            // so the result will be wrong unless corrected.
            byte[] rawData = DecompressDXT5(header, data, pixelFormat);
            DDSHelper.CorrectPremult((uint)(width * height * depth), ref rawData);

            return(rawData);
        }
        public void CreateFileHeaderForBC1()
        {
            var expectedFlags = DDSFileHeaderFlags.DDSD_CAPS | DDSFileHeaderFlags.DDSD_HEIGHT |
                                DDSFileHeaderFlags.DDSD_WIDTH | DDSFileHeaderFlags.DDSD_PIXELFORMAT;
            var expectedPixelFormat = new DDSPixelFormat
            {
                Size   = 32,
                Flags  = DDSPixelFormatFlags.DDPF_FOURCC,
                FourCC = FourCC.BC1Unorm.Value
            };

            var header = DDSFileWriter.CreateHeader(1024, 512, FourCC.BC1Unorm.Value);

            Assert.AreEqual(124, header.Size);
            Assert.AreEqual(expectedFlags, header.Flags);
            Assert.AreEqual(512, header.Height);
            Assert.AreEqual(1024, header.Width);
            Assert.AreEqual(0, header.PitchOrLinearSize);
            Assert.AreEqual(0, header.Depth);
            Assert.AreEqual(0, header.MipMapCount);
            unsafe
            {
                Assert.AreEqual(0, header.Reserved1[0]);
                Assert.AreEqual(0, header.Reserved1[1]);
                Assert.AreEqual(0, header.Reserved1[2]);
                Assert.AreEqual(0, header.Reserved1[3]);
                Assert.AreEqual(0, header.Reserved1[4]);
                Assert.AreEqual(0, header.Reserved1[5]);
                Assert.AreEqual(0, header.Reserved1[6]);
                Assert.AreEqual(0, header.Reserved1[7]);
                Assert.AreEqual(0, header.Reserved1[8]);
                Assert.AreEqual(0, header.Reserved1[9]);
                Assert.AreEqual(0, header.Reserved1[10]);
            }
            Assert.AreEqual(DDSCapsFlags.DDSCAPS_TEXTURE, header.Caps);
            Assert.AreEqual(0, header.Caps2);
            Assert.AreEqual(0, header.Caps3);
            Assert.AreEqual(0, header.Caps4);
            Assert.AreEqual(0, header.Reserved2);

            Assert.AreEqual(expectedPixelFormat.Size, header.PixelFormat.Size);
            Assert.AreEqual(expectedPixelFormat.Flags, header.PixelFormat.Flags);
            Assert.AreEqual(expectedPixelFormat.FourCC, header.PixelFormat.FourCC);
            Assert.AreEqual(0, header.PixelFormat.RGBBitCount);
            Assert.AreEqual(0, header.PixelFormat.RBitMask);
            Assert.AreEqual(0, header.PixelFormat.GBitMask);
            Assert.AreEqual(0, header.PixelFormat.BBitMask);
            Assert.AreEqual(0, header.PixelFormat.ABitMask);
        }
Exemple #9
0
            internal static DDSPixelFormat Read(BinaryReader br)
            {
                var pf = new DDSPixelFormat();

                pf.size      = br.ReadInt32();
                pf.flags     = br.ReadInt32();
                pf.fourCC    = br.ReadInt32();
                pf.rgbBits   = br.ReadInt32();
                pf.redMask   = br.ReadInt32();
                pf.greenMask = br.ReadInt32();
                pf.blueMask  = br.ReadInt32();
                pf.alphaMask = br.ReadInt32();

                return(pf);
            }
Exemple #10
0
			internal static DDSPixelFormat Read( BinaryReader br )
			{
				var pf = new DDSPixelFormat();

				pf.size = br.ReadInt32();
				pf.flags = br.ReadInt32();
				pf.fourCC = br.ReadInt32();
				pf.rgbBits = br.ReadInt32();
				pf.redMask = br.ReadInt32();
				pf.greenMask = br.ReadInt32();
				pf.blueMask = br.ReadInt32();
				pf.alphaMask = br.ReadInt32();

				return pf;
			}
Exemple #11
0
        public static DDSPixelFormat ToPixelFormat(this TextureType T)
        {
            DDSPixelFormat ret = new DDSPixelFormat {
                size      = 32,
                flags     = 4,
                fourCC    = (uint)T,
                bitCount  = 32,
                redMask   = 0x0000FF00,
                greenMask = 0x00FF0000,
                blueMask  = 0xFF000000,
                alphaMask = 0x000000FF
            };

            if (T == TextureType.ATI2)
            {
                ret.flags |= 0x80000000;
            }
            return(ret);
        }
Exemple #12
0
        // iCompFormatToBpc
        internal static uint PixelFormatToBpc(DDSPixelFormat pf)
        {
            switch (pf)
            {
            case DDSPixelFormat.R16F:
            case DDSPixelFormat.G16R16F:
            case DDSPixelFormat.A16B16G16R16F:
                return(4);

            case DDSPixelFormat.R32F:
            case DDSPixelFormat.G32R32F:
            case DDSPixelFormat.A32B32G32R32F:
                return(4);

            case DDSPixelFormat.A16B16G16R16:
                return(2);

            default:
                return(1);
            }
        }
Exemple #13
0
        private static unsafe byte[] DecompressLum(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            // allocate bitmap
            int bpp         = (int)(DDSHelper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount));
            int bps         = (int)(header.width * bpp * DDSHelper.PixelFormatToBpc(pixelFormat));
            int sizeofplane = (int)(bps * header.height);
            int width       = (int)header.width;
            int height      = (int)header.height;
            int depth       = (int)header.depth;

            byte[] rawData = new byte[depth * sizeofplane + height * bps + width * bpp];

            int lShift1 = 0; int lMul = 0; int lShift2 = 0;

            DDSHelper.ComputeMaskParams(header.pixelformat.rbitmask, ref lShift1, ref lMul, ref lShift2);

            int offset = 0;
            int pixnum = width * height * depth;

            fixed(byte *bytePtr = data)
            {
                byte *temp = bytePtr;

                while (pixnum-- > 0)
                {
                    byte px = *(temp++);
                    rawData[offset + 0] = (byte)(((px >> lShift1) * lMul) >> lShift2);
                    rawData[offset + 1] = (byte)(((px >> lShift1) * lMul) >> lShift2);
                    rawData[offset + 2] = (byte)(((px >> lShift1) * lMul) >> lShift2);
                    rawData[offset + 3] = (byte)(((px >> lShift1) * lMul) >> lShift2);
                    offset += 4;
                }
            }

            return(rawData);
        }
Exemple #14
0
        /// <summary>
        /// Creates a DDS file header data structure with a single RGB surface.
        /// </summary>
        /// <param name="pixelWidth">The width of the DDS image described by this header.</param>
        /// <param name="pixelHeight">The height of the DDS image described by this header.</param>
        /// <param name="fourCC">The four-character code which specifies the BCn compression format.</param>
        public static DDSFileHeader CreateHeader(int pixelWidth, int pixelHeight, uint fourCC)
        {
            if (pixelHeight < 0 || pixelWidth < 0)
            {
                throw new ArgumentException("Received negative image dimension.");
            }

            var pixelFormat = new DDSPixelFormat();

            pixelFormat.Size   = 32;
            pixelFormat.Flags  = DDSPixelFormatFlags.DDPF_FOURCC;
            pixelFormat.FourCC = fourCC;

            var header = new DDSFileHeader();

            header.Size        = 124;
            header.Flags       = MinimumRequiredFlags();
            header.Height      = (uint)pixelHeight;
            header.Width       = (uint)pixelWidth;
            header.PixelFormat = pixelFormat;
            header.Caps        = DDSCapsFlags.DDSCAPS_TEXTURE;

            return(header);
        }
Exemple #15
0
        private static unsafe byte[] DecompressFloat(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            // allocate bitmap
            int bpp         = (int)(DDSHelper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount));
            int bps         = (int)(header.width * bpp * DDSHelper.PixelFormatToBpc(pixelFormat));
            int sizeofplane = (int)(bps * header.height);
            int width       = (int)header.width;
            int height      = (int)header.height;
            int depth       = (int)header.depth;

            byte[] rawData = new byte[depth * sizeofplane + height * bps + width * bpp];
            int    size    = 0;

            fixed(byte *bytePtr = data)
            {
                byte *temp = bytePtr;

                fixed(byte *destPtr = rawData)
                {
                    byte *destData = destPtr;

                    switch (pixelFormat)
                    {
                    case DDSPixelFormat.R32F:      // Red float, green = blue = max
                        size = width * height * depth * 3;
                        for (int i = 0, j = 0; i < size; i += 3, j++)
                        {
                            ((float *)destData)[i]     = ((float *)temp)[j];
                            ((float *)destData)[i + 1] = 1.0f;
                            ((float *)destData)[i + 2] = 1.0f;
                        }
                        break;

                    case DDSPixelFormat.A32B32G32R32F:      // Direct copy of float RGBA data
                        Array.Copy(data, rawData, data.Length);
                        break;

                    case DDSPixelFormat.G32R32F:      // Red float, green float, blue = max
                        size = width * height * depth * 3;
                        for (int i = 0, j = 0; i < size; i += 3, j += 2)
                        {
                            ((float *)destData)[i]     = ((float *)temp)[j];
                            ((float *)destData)[i + 1] = ((float *)temp)[j + 1];
                            ((float *)destData)[i + 2] = 1.0f;
                        }
                        break;

                    case DDSPixelFormat.R16F:      // Red float, green = blue = max
                        size = width * height * depth * bpp;
                        DDSHelper.ConvR16ToFloat32((uint *)destData, (ushort *)temp, (uint)size);
                        break;

                    case DDSPixelFormat.A16B16G16R16F:      // Just convert from half to float.
                        size = width * height * depth * bpp;
                        DDSHelper.ConvFloat16ToFloat32((uint *)destData, (ushort *)temp, (uint)size);
                        break;

                    case DDSPixelFormat.G16R16F:      // Convert from half to float, set blue = max.
                        size = width * height * depth * bpp;
                        DDSHelper.ConvG16R16ToFloat32((uint *)destData, (ushort *)temp, (uint)size);
                        break;

                    default:
                        break;
                    }
                }
            }

            return(rawData);
        }
Exemple #16
0
        internal static byte[] Expand(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            System.Diagnostics.Debug.WriteLine(pixelFormat);
            // allocate bitmap
            byte[] rawData = null;

            switch (pixelFormat)
            {
            case DDSPixelFormat.RGBA:
                rawData = DecompressRGBA(header, data, pixelFormat);
                break;

            case DDSPixelFormat.RGB:
                rawData = DecompressRGB(header, data, pixelFormat);
                break;

            case DDSPixelFormat.LUMINANCE:
            case DDSPixelFormat.LUMINANCE_ALPHA:
                rawData = DecompressLum(header, data, pixelFormat);
                break;

            case DDSPixelFormat.DXT1:
                rawData = DecompressDXT1(header, data, pixelFormat);
                break;

            case DDSPixelFormat.DXT2:
                rawData = DecompressDXT2(header, data, pixelFormat);
                break;

            case DDSPixelFormat.DXT3:
                rawData = DecompressDXT3(header, data, pixelFormat);
                break;

            case DDSPixelFormat.DXT4:
                rawData = DecompressDXT4(header, data, pixelFormat);
                break;

            case DDSPixelFormat.DXT5:
                rawData = DecompressDXT5(header, data, pixelFormat);
                break;

            case DDSPixelFormat.THREEDC:
                rawData = Decompress3Dc(header, data, pixelFormat);
                break;

            case DDSPixelFormat.ATI1N:
                rawData = DecompressAti1n(header, data, pixelFormat);
                break;

            case DDSPixelFormat.RXGB:
                rawData = DecompressRXGB(header, data, pixelFormat);
                break;

            case DDSPixelFormat.R16F:
            case DDSPixelFormat.G16R16F:
            case DDSPixelFormat.A16B16G16R16F:
            case DDSPixelFormat.R32F:
            case DDSPixelFormat.G32R32F:
            case DDSPixelFormat.A32B32G32R32F:
                rawData = DecompressFloat(header, data, pixelFormat);
                break;

            default:
                throw new UnknownFileFormatException();
            }

            return(rawData);
        }
Exemple #17
0
        private static unsafe byte[] DecompressRXGB(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            // allocate bitmap
            int bpp         = (int)(DDSHelper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount));
            int bps         = (int)(header.width * bpp * DDSHelper.PixelFormatToBpc(pixelFormat));
            int sizeofplane = (int)(bps * header.height);
            int width       = (int)header.width;
            int height      = (int)header.height;
            int depth       = (int)header.depth;

            byte[] rawData = new byte[depth * sizeofplane + height * bps + width * bpp];

            Colour565 color_0 = new Colour565();
            Colour565 color_1 = new Colour565();

            Colour8888[] colours = new Colour8888[4];
            byte[]       alphas  = new byte[8];

            fixed(byte *bytePtr = data)
            {
                byte *temp = bytePtr;

                for (int z = 0; z < depth; z++)
                {
                    for (int y = 0; y < height; y += 4)
                    {
                        for (int x = 0; x < width; x += 4)
                        {
                            if (y >= height || x >= width)
                            {
                                break;
                            }
                            alphas[0] = temp[0];
                            alphas[1] = temp[1];
                            byte *alphamask = temp + 2;
                            temp += 8;

                            DDSHelper.DxtcReadColors(temp, ref color_0, ref color_1);
                            temp += 4;

                            uint bitmask = ((uint *)temp)[1];
                            temp += 4;

                            colours[0].red   = (byte)(color_0.red << 3);
                            colours[0].green = (byte)(color_0.green << 2);
                            colours[0].blue  = (byte)(color_0.blue << 3);
                            colours[0].alpha = 0xFF;

                            colours[1].red   = (byte)(color_1.red << 3);
                            colours[1].green = (byte)(color_1.green << 2);
                            colours[1].blue  = (byte)(color_1.blue << 3);
                            colours[1].alpha = 0xFF;

                            // Four-color block: derive the other two colors.
                            // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
                            // These 2-bit codes correspond to the 2-bit fields
                            // stored in the 64-bit block.
                            colours[2].blue  = (byte)((2 * colours[0].blue + colours[1].blue + 1) / 3);
                            colours[2].green = (byte)((2 * colours[0].green + colours[1].green + 1) / 3);
                            colours[2].red   = (byte)((2 * colours[0].red + colours[1].red + 1) / 3);
                            colours[2].alpha = 0xFF;

                            colours[3].blue  = (byte)((colours[0].blue + 2 * colours[1].blue + 1) / 3);
                            colours[3].green = (byte)((colours[0].green + 2 * colours[1].green + 1) / 3);
                            colours[3].red   = (byte)((colours[0].red + 2 * colours[1].red + 1) / 3);
                            colours[3].alpha = 0xFF;

                            int k = 0;
                            for (int j = 0; j < 4; j++)
                            {
                                for (int i = 0; i < 4; i++, k++)
                                {
                                    int        select = (int)((bitmask & (0x03 << k * 2)) >> k * 2);
                                    Colour8888 col    = colours[select];

                                    // only put pixels out < width or height
                                    if (((x + i) < width) && ((y + j) < height))
                                    {
                                        uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp);
                                        rawData[offset + 0] = col.red;
                                        rawData[offset + 1] = col.green;
                                        rawData[offset + 2] = col.blue;
                                    }
                                }
                            }

                            // 8-alpha or 6-alpha block?
                            if (alphas[0] > alphas[1])
                            {
                                // 8-alpha block:  derive the other six alphas.
                                // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
                                alphas[2] = (byte)((6 * alphas[0] + 1 * alphas[1] + 3) / 7);    // bit code 010
                                alphas[3] = (byte)((5 * alphas[0] + 2 * alphas[1] + 3) / 7);    // bit code 011
                                alphas[4] = (byte)((4 * alphas[0] + 3 * alphas[1] + 3) / 7);    // bit code 100
                                alphas[5] = (byte)((3 * alphas[0] + 4 * alphas[1] + 3) / 7);    // bit code 101
                                alphas[6] = (byte)((2 * alphas[0] + 5 * alphas[1] + 3) / 7);    // bit code 110
                                alphas[7] = (byte)((1 * alphas[0] + 6 * alphas[1] + 3) / 7);    // bit code 111
                            }
                            else
                            {
                                // 6-alpha block.
                                // Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
                                alphas[2] = (byte)((4 * alphas[0] + 1 * alphas[1] + 2) / 5); // Bit code 010
                                alphas[3] = (byte)((3 * alphas[0] + 2 * alphas[1] + 2) / 5); // Bit code 011
                                alphas[4] = (byte)((2 * alphas[0] + 3 * alphas[1] + 2) / 5); // Bit code 100
                                alphas[5] = (byte)((1 * alphas[0] + 4 * alphas[1] + 2) / 5); // Bit code 101
                                alphas[6] = 0x00;                                            // Bit code 110
                                alphas[7] = 0xFF;                                            // Bit code 111
                            }

                            // Note: Have to separate the next two loops,
                            //	it operates on a 6-byte system.
                            // First three bytes
                            uint bits = *((uint *)alphamask);
                            for (int j = 0; j < 2; j++)
                            {
                                for (int i = 0; i < 4; i++)
                                {
                                    // only put pixels out < width or height
                                    if (((x + i) < width) && ((y + j) < height))
                                    {
                                        uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp + 3);
                                        rawData[offset] = alphas[bits & 0x07];
                                    }
                                    bits >>= 3;
                                }
                            }

                            // Last three bytes
                            bits = *((uint *)&alphamask[3]);
                            for (int j = 2; j < 4; j++)
                            {
                                for (int i = 0; i < 4; i++)
                                {
                                    // only put pixels out < width or height
                                    if (((x + i) < width) && ((y + j) < height))
                                    {
                                        uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp + 3);
                                        rawData[offset] = alphas[bits & 0x07];
                                    }
                                    bits >>= 3;
                                }
                            }
                        }
                    }
                }
            }

            return(rawData);
        }
Exemple #18
0
        private static unsafe byte[] DecompressDXT1(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            // allocate bitmap
            int bpp         = (int)(DDSHelper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount));
            int bps         = (int)(header.width * bpp * DDSHelper.PixelFormatToBpc(pixelFormat));
            int sizeofplane = (int)(bps * header.height);
            int width       = (int)header.width;
            int height      = (int)header.height;
            int depth       = (int)header.depth;

            // DXT1 decompressor
            byte[] rawData = new byte[depth * sizeofplane + height * bps + width * bpp];

            Colour8888[] colours = new Colour8888[4];
            colours[0].alpha = 0xFF;
            colours[1].alpha = 0xFF;
            colours[2].alpha = 0xFF;

            fixed(byte *bytePtr = data)
            {
                byte *temp = bytePtr;

                for (int z = 0; z < depth; z++)
                {
                    for (int y = 0; y < height; y += 4)
                    {
                        for (int x = 0; x < width; x += 4)
                        {
                            ushort colour0 = *((ushort *)temp);
                            ushort colour1 = *((ushort *)(temp + 2));
                            DDSHelper.DxtcReadColor(colour0, ref colours[0]);
                            DDSHelper.DxtcReadColor(colour1, ref colours[1]);

                            uint bitmask = ((uint *)temp)[1];
                            temp += 8;

                            if (colour0 > colour1)
                            {
                                // Four-color block: derive the other two colors.
                                // 00 = color_0, 01 = color_1, 10 = color_2, 11 = color_3
                                // These 2-bit codes correspond to the 2-bit fields
                                // stored in the 64-bit block.
                                colours[2].blue  = (byte)((2 * colours[0].blue + colours[1].blue + 1) / 3);
                                colours[2].green = (byte)((2 * colours[0].green + colours[1].green + 1) / 3);
                                colours[2].red   = (byte)((2 * colours[0].red + colours[1].red + 1) / 3);
                                //colours[2].alpha = 0xFF;

                                colours[3].blue  = (byte)((colours[0].blue + 2 * colours[1].blue + 1) / 3);
                                colours[3].green = (byte)((colours[0].green + 2 * colours[1].green + 1) / 3);
                                colours[3].red   = (byte)((colours[0].red + 2 * colours[1].red + 1) / 3);
                                colours[3].alpha = 0xFF;
                            }
                            else
                            {
                                // Three-color block: derive the other color.
                                // 00 = color_0,  01 = color_1,  10 = color_2,
                                // 11 = transparent.
                                // These 2-bit codes correspond to the 2-bit fields
                                // stored in the 64-bit block.
                                colours[2].blue  = (byte)((colours[0].blue + colours[1].blue) / 2);
                                colours[2].green = (byte)((colours[0].green + colours[1].green) / 2);
                                colours[2].red   = (byte)((colours[0].red + colours[1].red) / 2);
                                //colours[2].alpha = 0xFF;

                                colours[3].blue  = (byte)((colours[0].blue + 2 * colours[1].blue + 1) / 3);
                                colours[3].green = (byte)((colours[0].green + 2 * colours[1].green + 1) / 3);
                                colours[3].red   = (byte)((colours[0].red + 2 * colours[1].red + 1) / 3);
                                colours[3].alpha = 0x00;
                            }

                            for (int j = 0, k = 0; j < 4; j++)
                            {
                                for (int i = 0; i < 4; i++, k++)
                                {
                                    int        select = (int)((bitmask & (0x03 << k * 2)) >> k * 2);
                                    Colour8888 col    = colours[select];
                                    if (((x + i) < width) && ((y + j) < height))
                                    {
                                        uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp);
                                        rawData[offset + 0] = (byte)col.red;
                                        rawData[offset + 1] = (byte)col.green;
                                        rawData[offset + 2] = (byte)col.blue;
                                        rawData[offset + 3] = (byte)col.alpha;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(rawData);
        }
Exemple #19
0
        private static unsafe byte[] DecompressAti1n(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            // allocate bitmap
            int bpp         = (int)(DDSHelper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount));
            int bps         = (int)(header.width * bpp * DDSHelper.PixelFormatToBpc(pixelFormat));
            int sizeofplane = (int)(bps * header.height);
            int width       = (int)header.width;
            int height      = (int)header.height;
            int depth       = (int)header.depth;

            byte[] rawData = new byte[depth * sizeofplane + height * bps + width * bpp];
            byte[] colours = new byte[8];

            uint offset = 0;

            fixed(byte *bytePtr = data)
            {
                byte *temp = bytePtr;

                for (int z = 0; z < depth; z++)
                {
                    for (int y = 0; y < height; y += 4)
                    {
                        for (int x = 0; x < width; x += 4)
                        {
                            //Read palette
                            int t1 = colours[0] = temp[0];
                            int t2 = colours[1] = temp[1];
                            temp += 2;
                            if (t1 > t2)
                            {
                                for (int i = 2; i < 8; ++i)
                                {
                                    colours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 7);
                                }
                            }
                            else
                            {
                                for (int i = 2; i < 6; ++i)
                                {
                                    colours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 5);
                                }
                                colours[6] = 0;
                                colours[7] = 255;
                            }

                            //decompress pixel data
                            uint currOffset = offset;
                            for (int k = 0; k < 4; k += 2)
                            {
                                // First three bytes
                                uint bitmask = ((uint)(temp[0]) << 0) | ((uint)(temp[1]) << 8) | ((uint)(temp[2]) << 16);
                                for (int j = 0; j < 2; j++)
                                {
                                    // only put pixels out < height
                                    if ((y + k + j) < height)
                                    {
                                        for (int i = 0; i < 4; i++)
                                        {
                                            // only put pixels out < width
                                            if (((x + i) < width))
                                            {
                                                t1          = (int)(currOffset + (x + i));
                                                rawData[t1] = colours[bitmask & 0x07];
                                            }
                                            bitmask >>= 3;
                                        }
                                        currOffset += (uint)bps;
                                    }
                                }
                                temp += 3;
                            }
                        }
                        offset += (uint)(bps * 4);
                    }
                }
            }

            return(rawData);
        }
Exemple #20
0
 public DDSHeader(BinaryReader br)
 {
     Size = br.ReadUInt32();
     Flags = (DDSFlags)br.ReadUInt32();
     Height = br.ReadUInt32();
     Width = br.ReadUInt32();
     PitchOrLinearSize = br.ReadUInt32();
     Depth = br.ReadUInt32();
     MipMapCount = br.ReadUInt32();
     Reserved1 = new uint[11];
     for (int i = 0; i < 11; i++)
         Reserved1[i] = br.ReadUInt32();
     PixelFormat = new DDSPixelFormat(br);
     Caps = (DDSCaps)br.ReadUInt32();
     Caps2 = (DDSCaps2)br.ReadUInt32();
     Caps3 = br.ReadUInt32();
     Caps4 = br.ReadUInt32();
     Reserved2 = br.ReadUInt32();
 }
 private void SetPixelFormatData(int pixelFormatID)
 {
     ddsPF = new DDSPixelFormat();
     ddsPF.caps2 = 0;
     ddsPF.dwSize = 32;
     ddsPF.dwFlags = 4;
     ddsPF.dwFourCC = 0x31545844;
     ddsPF.dwRGBBitCount = 0;
     ddsPF.dwRBitMask = 0;
     ddsPF.dwGBitMask = 0;
     ddsPF.dwBBitMask = 0;
     ddsPF.dwABitMask = 0;
     if (PixelFormatTypes.ContainsKey(pixelFormatID))
     {
         ddsPF.dwFourCC = PixelFormatTypes[pixelFormatID];
         if (pixelFormatID == 0x01)
             ddsPF.dwFlags |= 0x01;
     }
     else
     {
         switch (pixelFormatID)
         {
             case 0x0B:
             case 0x36:
                 ddsPF.dwFourCC = 0x00;
                 ddsPF.dwRGBBitCount = 0x20;
                 ddsPF.dwRBitMask = 0xFF;
                 ddsPF.dwGBitMask = 0xFF00;
                 ddsPF.dwBBitMask = 0xFF0000;
                 ddsPF.dwABitMask = 0xFF000000;
                 ddsPF.dwFlags = 0x41;
                 if (pixelFormatID == 0x36)
                     ddsPF.caps2 = 0xFE00;
                 break;
             case 0x0C:
                 ddsPF.dwFourCC = 0x00;
                 ddsPF.dwRGBBitCount = 0x08;
                 ddsPF.dwABitMask = 0xFF;
                 ddsPF.dwFlags = 0x02;
                 break;
             case 0x0D:
                 ddsPF.dwFourCC = 0x00;
                 ddsPF.dwRGBBitCount = 0x10;
                 ddsPF.dwRBitMask = 0xFFFF;
                 ddsPF.dwFlags = 0x20000;
                 break;
         }
     }
 }
Exemple #22
0
        private static unsafe byte[] DecompressDXT3(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            // allocate bitmap
            int bpp         = (int)(DDSHelper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount));
            int bps         = (int)(header.width * bpp * DDSHelper.PixelFormatToBpc(pixelFormat));
            int sizeofplane = (int)(bps * header.height);
            int width       = (int)header.width;
            int height      = (int)header.height;
            int depth       = (int)header.depth;

            // DXT3 decompressor
            byte[]       rawData = new byte[depth * sizeofplane + height * bps + width * bpp];
            Colour8888[] colours = new Colour8888[4];

            fixed(byte *bytePtr = data)
            {
                byte *temp = bytePtr;

                for (int z = 0; z < depth; z++)
                {
                    for (int y = 0; y < height; y += 4)
                    {
                        for (int x = 0; x < width; x += 4)
                        {
                            byte *alpha = temp;
                            temp += 8;

                            DDSHelper.DxtcReadColors(temp, ref colours);
                            temp += 4;

                            uint bitmask = ((uint *)temp)[1];
                            temp += 4;

                            // Four-color block: derive the other two colors.
                            // 00 = color_0, 01 = color_1, 10 = color_2, 11	= color_3
                            // These 2-bit codes correspond to the 2-bit fields
                            // stored in the 64-bit block.
                            colours[2].blue  = (byte)((2 * colours[0].blue + colours[1].blue + 1) / 3);
                            colours[2].green = (byte)((2 * colours[0].green + colours[1].green + 1) / 3);
                            colours[2].red   = (byte)((2 * colours[0].red + colours[1].red + 1) / 3);
                            //colours[2].alpha = 0xFF;

                            colours[3].blue  = (byte)((colours[0].blue + 2 * colours[1].blue + 1) / 3);
                            colours[3].green = (byte)((colours[0].green + 2 * colours[1].green + 1) / 3);
                            colours[3].red   = (byte)((colours[0].red + 2 * colours[1].red + 1) / 3);
                            //colours[3].alpha = 0xFF;

                            for (int j = 0, k = 0; j < 4; j++)
                            {
                                for (int i = 0; i < 4; k++, i++)
                                {
                                    int select = (int)((bitmask & (0x03 << k * 2)) >> k * 2);

                                    if (((x + i) < width) && ((y + j) < height))
                                    {
                                        uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp);
                                        rawData[offset + 0] = (byte)colours[select].red;
                                        rawData[offset + 1] = (byte)colours[select].green;
                                        rawData[offset + 2] = (byte)colours[select].blue;
                                    }
                                }
                            }

                            for (int j = 0; j < 4; j++)
                            {
                                //ushort word = (ushort)(alpha[2 * j] + 256 * alpha[2 * j + 1]);
                                ushort word = (ushort)(alpha[2 * j] | (alpha[2 * j + 1] << 8));
                                for (int i = 0; i < 4; i++)
                                {
                                    if (((x + i) < width) && ((y + j) < height))
                                    {
                                        uint offset = (uint)(z * sizeofplane + (y + j) * bps + (x + i) * bpp + 3);
                                        rawData[offset] = (byte)(word & 0x0F);
                                        rawData[offset] = (byte)(rawData[offset] | (rawData[offset] << 4));
                                    }
                                    word >>= 4;
                                }
                            }
                        }
                    }
                }
            }

            return(rawData);
        }
Exemple #23
0
            private static bool ValidateTexture(HeaderDXT10 header, HeaderFlags flags, out int depth, out PixelFormat format, out ResourceDimension resDim, out int arraySize, out bool isCubeMap)
            {
                depth     = 0;
                format    = Renderer.PixelFormat.Unknown;
                resDim    = ResourceDimension.Unknown;
                arraySize = 0x1;
                isCubeMap = false;

                arraySize = header.ArraySize;
                if (arraySize == 0)
                {
                    return(false);
                }


                if (header.MiscFlag2 != FlagsDX10.AlphaModeUnknown)
                {
                    return(false);
                }


                if (DDSPixelFormat.BitsPerPixel(header.DXGIFormat) == 0)
                {
                    return(false);
                }


                format = header.DXGIFormat;

                switch (header.Dimension)
                {
                case ResourceDimension.Texture1D:
                    depth = 1;
                    break;

                case ResourceDimension.Texture2D:
                    if (header.MiscFlag.HasFlag(ResourceOptionFlags.TextureCube))
                    {
                        arraySize *= 6;
                        isCubeMap  = true;
                    }
                    depth = 1;
                    break;

                case ResourceDimension.Texture3D:
                    if (!flags.HasFlag(HeaderFlags.Depth))
                    {
                        return(false);
                    }


                    if (arraySize > 1)
                    {
                        return(false);
                    }

                    break;

                default:
                    return(false);
                }

                resDim = header.Dimension;

                return(true);
            }
Exemple #24
0
 public DDSHeader()
 {
     PixelFormat = new DDSPixelFormat();
 }
Exemple #25
0
        /// <summary>
        /// Constructs a new instance of DDS.
        /// </summary>
        /// <param name="reader">Reader to construct from.</param>
        public DDS( BinaryReader reader )
        {
            // Magic number 'DDS '
            if ( reader.ReadUInt32() != 0x20534444 )
                throw new DDSException( "Invalid DDS magic number" );

            if ( reader.ReadUInt32() != 124 )
                throw new DDSException( "Invalid DDS_HEADER size" );

            uint flags = reader.ReadUInt32();

            _Height = reader.ReadInt32();
            _Width = reader.ReadInt32();

            reader.ReadUInt32();

            _VolumeDepth = reader.ReadInt32();
            _MipMapLevels = reader.ReadInt32();

            // Skip reserved
            reader.BaseStream.Seek( sizeof( uint ) * 11, SeekOrigin.Current );

            // Pixel format
            _Format = ReadPixelFormat( reader );

            uint caps = reader.ReadUInt32();

            if ( ( caps & 0x400000 ) > 0 )
                _IsMipMap = true;

            uint caps2 = reader.ReadUInt32();

            if ( ( caps2 & 0x200 ) > 0 )
                _IsCubeMap = true;

            if ( ( caps2 & 0x200000 ) > 0 )
                _IsVolumeMap = true;

            // Crap
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();

            // Extended DX10
            uint dxgiFormat = 0;
            uint dimension = 0;
            uint cubeFlags = 0;
            uint arraySize = 0;

            if ( _Format == DDSPixelFormat.DX10 )
            {
                dxgiFormat = reader.ReadUInt32();
                dimension = reader.ReadUInt32();
                cubeFlags = reader.ReadUInt32();
                arraySize = reader.ReadUInt32();

                reader.ReadUInt32(); // crap

                throw new NotImplementedException();
            }

            if ( _IsVolumeMap )
            {
                _VolumeMaps = new List<VolumeMap>();

                if ( _IsMipMap )
                {
                    int width = _Width;
                    int height = _Height;
                    int depth = _VolumeDepth;

                    for ( int i = 0; i < _MipMapLevels; i++ )
                    {
                        _VolumeMaps.Add( ReadVolumeMap( reader, width, height, depth ) );

                        width = Math.Max( 1, width / 2 );
                        height = Math.Max( 1, height / 2 );
                        depth = Math.Max( 1, depth / 2 );
                    }
                }
                else
                    _VolumeMaps.Add( ReadVolumeMap( reader, _Width, _Height, _VolumeDepth ) );
            }
            else if ( _IsCubeMap )
            {
                if ( _IsMipMap )
                {
                    if ( ( caps2 & (uint) DDSCubeFace.PositiveX ) > 0 )
                        _PositiveX = ReadMipMaps( reader, _MipMapLevels );
                    if ( ( caps2 & (uint) DDSCubeFace.NegativeX ) > 0 )
                        _NegativeX = ReadMipMaps( reader, _MipMapLevels );
                    if ( ( caps2 & (uint) DDSCubeFace.PositiveY ) > 0 )
                        _PositiveY = ReadMipMaps( reader, _MipMapLevels );
                    if ( ( caps2 & (uint) DDSCubeFace.NegativeY ) > 0 )
                        _NegativeY = ReadMipMaps( reader, _MipMapLevels );
                    if ( ( caps2 & (uint) DDSCubeFace.PositiveZ ) > 0 )
                        _PositiveZ = ReadMipMaps( reader, _MipMapLevels );
                    if ( ( caps2 & (uint) DDSCubeFace.NegativeZ ) > 0 )
                        _NegativeZ = ReadMipMaps( reader, _MipMapLevels );
                }
                else
                {
                    if ( ( caps2 & (uint) DDSCubeFace.PositiveX ) > 0 )
                        _PositiveX = ReadTexture( reader );
                    if ( ( caps2 & (uint) DDSCubeFace.NegativeX ) > 0 )
                        _NegativeX = ReadTexture( reader );
                    if ( ( caps2 & (uint) DDSCubeFace.PositiveY ) > 0 )
                        _PositiveY = ReadTexture( reader );
                    if ( ( caps2 & (uint) DDSCubeFace.NegativeY ) > 0 )
                        _NegativeY = ReadTexture( reader );
                    if ( ( caps2 & (uint) DDSCubeFace.PositiveZ ) > 0 )
                        _PositiveZ = ReadTexture( reader );
                    if ( ( caps2 & (uint) DDSCubeFace.NegativeZ ) > 0 )
                        _NegativeZ = ReadTexture( reader );
                }
            }
            else
            {
                if ( _IsMipMap )
                    _Texture = ReadMipMaps( reader, _MipMapLevels );
                else
                    _Texture = ReadTexture( reader );
            }
        }
Exemple #26
0
        private static unsafe byte[] Decompress3Dc(DDSStruct header, byte[] data, DDSPixelFormat pixelFormat)
        {
            // allocate bitmap
            int bpp         = (int)(DDSHelper.PixelFormatToBpp(pixelFormat, header.pixelformat.rgbbitcount));
            int bps         = (int)(header.width * bpp * DDSHelper.PixelFormatToBpc(pixelFormat));
            int sizeofplane = (int)(bps * header.height);
            int width       = (int)header.width;
            int height      = (int)header.height;
            int depth       = (int)header.depth;

            byte[] rawData  = new byte[depth * sizeofplane + height * bps + width * bpp];
            byte[] yColours = new byte[8];
            byte[] xColours = new byte[8];

            int offset = 0;

            fixed(byte *bytePtr = data)
            {
                byte *temp = bytePtr;

                for (int z = 0; z < depth; z++)
                {
                    for (int y = 0; y < height; y += 4)
                    {
                        for (int x = 0; x < width; x += 4)
                        {
                            byte *temp2 = temp + 8;

                            //Read Y palette
                            int t1 = yColours[0] = temp[0];
                            int t2 = yColours[1] = temp[1];
                            temp += 2;
                            if (t1 > t2)
                            {
                                for (int i = 2; i < 8; ++i)
                                {
                                    yColours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 7);
                                }
                            }
                            else
                            {
                                for (int i = 2; i < 6; ++i)
                                {
                                    yColours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 5);
                                }
                                yColours[6] = 0;
                                yColours[7] = 255;
                            }

                            // Read X palette
                            t1     = xColours[0] = temp2[0];
                            t2     = xColours[1] = temp2[1];
                            temp2 += 2;
                            if (t1 > t2)
                            {
                                for (int i = 2; i < 8; ++i)
                                {
                                    xColours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 7);
                                }
                            }
                            else
                            {
                                for (int i = 2; i < 6; ++i)
                                {
                                    xColours[i] = (byte)(t1 + ((t2 - t1) * (i - 1)) / 5);
                                }
                                xColours[6] = 0;
                                xColours[7] = 255;
                            }

                            //decompress pixel data
                            int currentOffset = offset;
                            for (int k = 0; k < 4; k += 2)
                            {
                                // First three bytes
                                uint bitmask  = ((uint)(temp[0]) << 0) | ((uint)(temp[1]) << 8) | ((uint)(temp[2]) << 16);
                                uint bitmask2 = ((uint)(temp2[0]) << 0) | ((uint)(temp2[1]) << 8) | ((uint)(temp2[2]) << 16);
                                for (int j = 0; j < 2; j++)
                                {
                                    // only put pixels out < height
                                    if ((y + k + j) < height)
                                    {
                                        for (int i = 0; i < 4; i++)
                                        {
                                            // only put pixels out < width
                                            if (((x + i) < width))
                                            {
                                                int  t;
                                                byte tx, ty;

                                                t1 = currentOffset + (x + i) * 3;
                                                rawData[t1 + 1] = ty = yColours[bitmask & 0x07];
                                                rawData[t1 + 0] = tx = xColours[bitmask2 & 0x07];

                                                //calculate b (z) component ((r/255)^2 + (g/255)^2 + (b/255)^2 = 1
                                                t = 127 * 128 - (tx - 127) * (tx - 128) - (ty - 127) * (ty - 128);
                                                if (t > 0)
                                                {
                                                    rawData[t1 + 2] = (byte)(Math.Sqrt(t) + 128);
                                                }
                                                else
                                                {
                                                    rawData[t1 + 2] = 0x7F;
                                                }
                                            }
                                            bitmask  >>= 3;
                                            bitmask2 >>= 3;
                                        }
                                        currentOffset += bps;
                                    }
                                }
                                temp  += 3;
                                temp2 += 3;
                            }

                            //skip bytes that were read via Temp2
                            temp += 8;
                        }
                        offset += bps * 4;
                    }
                }
            }

            return(rawData);
        }