Exemplo n.º 1
0
        public static byte[] DecodeBlock(byte[] Input, int Width, int Height, TEX_FORMAT Format)
        {
            if (Format == TEX_FORMAT.ETC1 || Format == TEX_FORMAT.ETC1_A4)
            {
                return(ETC1.ETC1Decompress(Input, Width, Height, Format == TEX_FORMAT.ETC1_A4));
            }

            byte[] Output = new byte[Width * Height * 4];

            int Increment = FmtBPP[(int)ConvertToPICAFormat(Format)] / 8;

            if (Increment == 0)
            {
                Increment = 1;
            }

            int IOffset = 0;

            for (int TY = 0; TY < Height; TY += 8)
            {
                for (int TX = 0; TX < Width; TX += 8)
                {
                    for (int Px = 0; Px < 64; Px++)
                    {
                        int X = SwizzleLUT[Px] & 7;
                        int Y = (SwizzleLUT[Px] - X) >> 3;

                        int OOffet = (TX + X + ((Height - 1 - (TY + Y)) * Width)) * 4;

                        switch (Format)
                        {
                        case TEX_FORMAT.R8G8_UNORM:
                            Output[OOffet + 0] = Input[IOffset + 3];
                            Output[OOffet + 1] = Input[IOffset + 2];
                            Output[OOffet + 2] = Input[IOffset + 1];
                            Output[OOffet + 3] = Input[IOffset + 0];
                            break;

                        case TEX_FORMAT.R8G8B8A8_UNORM:
                            Output[OOffet + 0] = Input[IOffset + 2];
                            Output[OOffet + 1] = Input[IOffset + 1];
                            Output[OOffet + 2] = Input[IOffset + 0];
                            Output[OOffet + 3] = 0xff;
                            break;

                        case TEX_FORMAT.B5G5R5A1_UNORM:
                            DecodeRGBA5551(Output, OOffet, GetUShort(Input, IOffset));
                            break;

                        case TEX_FORMAT.B5G6R5_UNORM:
                            DecodeRGB565(Output, OOffet, GetUShort(Input, IOffset));
                            break;

                        case TEX_FORMAT.B4G4R4A4_UNORM:
                            DecodeRGBA4(Output, OOffet, GetUShort(Input, IOffset));
                            break;

                        case TEX_FORMAT.LA8:
                            Output[OOffet + 0] = Input[IOffset + 1];
                            Output[OOffet + 1] = Input[IOffset + 1];
                            Output[OOffet + 2] = Input[IOffset + 1];
                            Output[OOffet + 3] = Input[IOffset + 0];
                            break;

                        case TEX_FORMAT.HIL08:
                            Output[OOffet + 0] = Input[IOffset + 1];
                            Output[OOffet + 1] = Input[IOffset + 0];
                            Output[OOffet + 2] = 0;
                            Output[OOffet + 3] = 0xff;
                            break;

                        case TEX_FORMAT.L8:
                            Output[OOffet + 0] = Input[IOffset];
                            Output[OOffet + 1] = Input[IOffset];
                            Output[OOffet + 2] = Input[IOffset];
                            Output[OOffet + 3] = 0xff;
                            break;

                        case TEX_FORMAT.A8_UNORM:
                            Output[OOffet + 0] = 0xff;
                            Output[OOffet + 1] = 0xff;
                            Output[OOffet + 2] = 0xff;
                            Output[OOffet + 3] = Input[IOffset];
                            break;

                        case TEX_FORMAT.LA4:
                            Output[OOffet + 0] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
                            Output[OOffet + 1] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
                            Output[OOffet + 2] = (byte)((Input[IOffset] >> 4) | (Input[IOffset] & 0xf0));
                            Output[OOffet + 3] = (byte)((Input[IOffset] << 4) | (Input[IOffset] & 0x0f));
                            break;

                        case TEX_FORMAT.L4:
                            int L = (Input[IOffset >> 1] >> ((IOffset & 1) << 2)) & 0xf;
                            Output[OOffet + 0] = (byte)((L << 4) | L);
                            Output[OOffet + 1] = (byte)((L << 4) | L);
                            Output[OOffet + 2] = (byte)((L << 4) | L);
                            Output[OOffet + 3] = 0xff;
                            break;

                        case TEX_FORMAT.A4:
                            int A = (Input[IOffset >> 1] >> ((IOffset & 1) << 2)) & 0xf;

                            Output[OOffet + 0] = 0xff;
                            Output[OOffet + 1] = 0xff;
                            Output[OOffet + 2] = 0xff;
                            Output[OOffet + 3] = (byte)((A << 4) | A);

                            break;
                        }

                        Output[OOffet + 0] = 0xff;
                        Output[OOffet + 1] = 0xff;
                        Output[OOffet + 2] = 0xff;
                        Output[OOffet + 3] = Input[IOffset];

                        IOffset += Increment;
                    }
                }
            }

            return(Output);
        }
        /// <summary>
        /// Gets a <see cref="Bitmap"/> given an array and mip index.
        /// </summary>
        /// <param name="ArrayIndex">The index of the surface/array. Cubemaps will have 6</param>
        /// <param name="MipLevel">The index of the mip level.</param>
        /// <returns></returns>
        public Bitmap GetBitmap(int ArrayLevel = 0, int MipLevel = 0)
        {
            uint width  = Math.Max(1, Width >> MipLevel);
            uint height = Math.Max(1, Height >> MipLevel);

            byte[] data = GetImageData(ArrayLevel, MipLevel);

            try
            {
                if (data == null)
                {
                    throw new Exception("Data is null!");
                }

                if (PlatformSwizzle == PlatformSwizzle.Platform_3DS && !IsCompressed(Format))
                {
                    var Image = BitmapExtension.GetBitmap(ConvertBgraToRgba(CTR_3DS.DecodeBlock(data, (int)width, (int)height, Format)),
                                                          (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                    Image.RotateFlip(RotateFlipType.RotateNoneFlipY); //It's upside down for some reason so flip it
                    return(Image);
                }

                switch (Format)
                {
                case TEX_FORMAT.R4G4_UNORM:
                    return(BitmapExtension.GetBitmap(R4G4.Decompress(data, (int)width, (int)height, false),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));

                case TEX_FORMAT.BC5_SNORM:
                    return(DDSCompressor.DecompressBC5(data, (int)width, (int)height, true));

                case TEX_FORMAT.ETC1:
                    return(BitmapExtension.GetBitmap(ETC1.ETC1Decompress(data, (int)width, (int)height, false),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));

                case TEX_FORMAT.ETC1_A4:
                    return(BitmapExtension.GetBitmap(ETC1.ETC1Decompress(data, (int)width, (int)height, true),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));

                default:
                    return(BitmapExtension.GetBitmap(DecodeBlock(data, width, height, Format),
                                                     (int)width, (int)height, System.Drawing.Imaging.PixelFormat.Format32bppArgb));
                }
            }
            catch (Exception ex)
            {
                Forms.STErrorDialog.Show($"Texture failed to load!", "Texture [GetBitmap({MipLevel},{ArrayLevel})]", DebugInfo() + " \n" + ex);

                try
                {
                    if (Format == TEX_FORMAT.BC1_UNORM)
                    {
                        return(DDSCompressor.DecompressBC1(data, (int)Width, (int)Height, false));
                    }
                    else if (Format == TEX_FORMAT.BC1_UNORM_SRGB)
                    {
                        return(DDSCompressor.DecompressBC1(data, (int)Width, (int)Height, true));
                    }
                    else if (Format == TEX_FORMAT.BC3_UNORM_SRGB)
                    {
                        return(DDSCompressor.DecompressBC3(data, (int)Width, (int)Height, false));
                    }
                    else if (Format == TEX_FORMAT.BC3_UNORM)
                    {
                        return(DDSCompressor.DecompressBC3(data, (int)Width, (int)Height, true));
                    }
                    else if (Format == TEX_FORMAT.BC4_UNORM)
                    {
                        return(DDSCompressor.DecompressBC4(data, (int)Width, (int)Height, false));
                    }
                    else if (Format == TEX_FORMAT.BC4_SNORM)
                    {
                        return(DDSCompressor.DecompressBC4(data, (int)Width, (int)Height, true));
                    }
                    else if (Format == TEX_FORMAT.BC5_UNORM)
                    {
                        return(DDSCompressor.DecompressBC5(data, (int)Width, (int)Height, false));
                    }
                    else
                    {
                        if (Runtime.UseOpenGL)
                        {
                            Runtime.OpenTKInitialized = true;
                            LoadOpenGLTexture();
                            return(RenderableTex.GLTextureToBitmap(RenderableTex));
                        }
                    }
                }
                catch
                {
                    Forms.STErrorDialog.Show($"Texture failed to load!", "Texture [GetBitmap({MipLevel},{ArrayLevel})]", DebugInfo() + " \n" + ex);
                }

                return(null);
            }
        }