Пример #1
0
        public static Bitmap DecodeByteArray(byte[] imagedata, ushort Width, ushort Height, TextureFormat Format)
        {
            CTRTexture tex = new CTRTexture
            {
                Format    = Format,
                Size      = new Size(Width, Height),
                ImageData = (byte[])imagedata.Clone()
            };

            return(DecodeTexture(tex));
        }
Пример #2
0
        public static Bitmap DecodeTexture(CTRTexture tex)
        {
            tex.BytesPerPixel = GetBytesPerPixel(tex.Format);

            if (tex.IsEtc1)
            {
                return(GetEtcBitmap(tex));
            }

            tex.RedBitSize       = GetRedBitSize(tex.Format);
            tex.GreenBitSize     = GetGreenBitSize(tex.Format);
            tex.BlueBitSize      = GetBlueBitSize(tex.Format);
            tex.AlphaBitSize     = GetAlphaBitSize(tex.Format);
            tex.LuminanceBitSize = GetLuminanceBitSize(tex.Format);
            tex.PostProcess      = getPostProcessingDelegate(tex.Format);

            tex.ChannelOrder = GetChannelOrder(tex.Format);

            return(GetGenericBitmap(tex));
        }
Пример #3
0
        /* private static readonly int[] etcScramble = new int[4] { 2, 3, 1, 0 }; */

        public static Bitmap DecodeBCLIM(string filename)
        {
            CTRTexture bclim = new CTRTexture();

            using (FileStream fs = File.OpenRead(filename))
            {
                using (BinaryReader br = new BinaryReader(fs))
                {
                    br.BaseStream.Seek(fs.Length - 0x28 + 0x1C, SeekOrigin.Begin);
                    bclim.Size = new Size {
                        Width = br.ReadUInt16(), Height = br.ReadUInt16()
                    };
                    bclim.Format = (TextureFormat)br.ReadUInt32();
                    int imageDataLen = br.ReadInt32();
                    br.BaseStream.Seek(0, SeekOrigin.Begin);
                    bclim.ImageData = br.ReadBytes(imageDataLen);
                }
            }

            return(DecodeTexture(bclim));
        }
Пример #4
0
        private static Bitmap GetEtcBitmap(CTRTexture tex)
        {
            Bitmap     bmp     = new Bitmap(tex.Size.Width, tex.Size.Height);
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite,
                                              bmp.PixelFormat);

            IntPtr ptr   = bmpData.Scan0;
            int    bytes = Math.Abs(bmpData.Stride) * bmp.Height;

            byte[] rgbaValues = new byte[bytes];


            bool hasAlpha = tex.HasAlpha;

            int offset = 0;

            for (int y = 0; y < tex.Size.Height; y += 4)
            {
                for (int x = 0; x < tex.Size.Width; x += 4)
                {
                    offset = GetEtc1BlockOffset(tex.Size, x, y, hasAlpha);

                    ulong alphaValue = hasAlpha ? BitConverter.ToUInt64(tex.ImageData, offset) : ulong.MaxValue;
                    ulong rgbValue   = BitConverter.ToUInt64(tex.ImageData, hasAlpha ? offset + 8 : offset);

                    bool flip = (rgbValue & 0x100000000L) != 0;
                    bool dif  = (rgbValue & 0x200000000L) != 0;

                    uint r1, g1, b1;
                    uint r2, g2, b2;

                    if (dif)
                    {
                        uint mult = 0xFF / 0x1F;

                        sbyte rt, gt, bt;

                        rt = (sbyte)((long)(rgbValue >> 56) & 7);
                        gt = (sbyte)((long)(rgbValue >> 48) & 7);
                        bt = (sbyte)((long)(rgbValue >> 40) & 7);

                        rt = (sbyte)((int)rt << 5);
                        rt = (sbyte)((int)rt >> 5);
                        gt = (sbyte)((int)gt << 5);
                        gt = (sbyte)((int)gt >> 5);
                        bt = (sbyte)((int)bt << 5);
                        bt = (sbyte)((int)bt >> 5);

                        r1 = (uint)(rgbValue >> 59) & 31;
                        g1 = (uint)(rgbValue >> 51) & 31;
                        b1 = (uint)(rgbValue >> 43) & 31;

                        r2 = (uint)(r1 + (int)rt) * mult;
                        g2 = (uint)(g1 + (int)gt) * mult;
                        b2 = (uint)(b1 + (int)bt) * mult;

                        r1 *= mult;
                        g1 *= mult;
                        b1 *= mult;
                    }
                    else
                    {
                        uint mult = 0xFF / 0xF;

                        r1 = (uint)((rgbValue >> 60) & 0xF) * mult;
                        g1 = (uint)((rgbValue >> 52) & 0xF) * mult;
                        b1 = (uint)((rgbValue >> 44) & 0xF) * mult;

                        r2 = (uint)((rgbValue >> 56) & 0xF) * mult;
                        g2 = (uint)((rgbValue >> 48) & 0xF) * mult;
                        b2 = (uint)((rgbValue >> 40) & 0xF) * mult;
                    }

                    uint cmpOne = (uint)((rgbValue >> 37) & 7);
                    uint cmpTwo = (uint)((rgbValue >> 34) & 7);

                    byte[] block = new byte[0x40];
                    if (flip)
                    {
                        for (int bY = 0; bY < 2; bY++)
                        {
                            for (int bX = 0; bX < 4; bX++)
                            {
                                GetEtc1Pixel(r1, g1, b1, bX, bY, rgbValue, alphaValue, cmpOne).CopyTo(rgbaValues, ((x + bX) * 4 + ((y + bY) * 4 * tex.Size.Width)));
                                GetEtc1Pixel(r2, g2, b2, bX, bY + 2, rgbValue, alphaValue, cmpTwo).CopyTo(rgbaValues, ((x + bX) * 4 + (((y + 2) + bY) * 4 * tex.Size.Width)));
                            }
                        }
                    }
                    else
                    {
                        for (int bY = 0; bY < 4; bY++)
                        {
                            for (int bX = 0; bX < 2; bX++)
                            {
                                GetEtc1Pixel(r1, g1, b1, bX, bY, rgbValue, alphaValue, cmpOne).CopyTo(rgbaValues, ((x + bX) * 4 + ((y + bY) * 4 * tex.Size.Width)));
                                GetEtc1Pixel(r2, g2, b2, bX + 2, bY, rgbValue, alphaValue, cmpTwo).CopyTo(rgbaValues, ((x + bX + 2) * 4 + ((y + bY) * 4 * tex.Size.Width)));
                            }
                        }
                    }
                }
            }

            Marshal.Copy(rgbaValues, 0, ptr, bytes);
            bmp.UnlockBits(bmpData);

            return(bmp);
        }
Пример #5
0
        private static Bitmap GetGenericBitmap(CTRTexture tex)
        {
            uint redBitMask       = (uint)((1 << tex.RedBitSize) - 1);
            uint blueBitMask      = (uint)((1 << tex.BlueBitSize) - 1);
            uint greenBitMask     = (uint)((1 << tex.GreenBitSize) - 1);
            uint alphaBitMask     = (uint)((1 << tex.AlphaBitSize) - 1);
            uint luminanceBitMask = (uint)((1 << tex.LuminanceBitSize) - 1);

            bool crop = false;

            Size size = new Size {
                Width = tex.Size.Width, Height = tex.Size.Height
            };

            if ((int)(tex.ImageData.Length / tex.BytesPerPixel) > (tex.Size.Width * tex.Size.Height))
            {
                size = new Size {
                    Width = Nlpo2(tex.Size.Width), Height = Nlpo2(tex.Size.Height)
                };
                crop = true;
            }

            Bitmap     bmp     = new Bitmap(size.Width, size.Height);
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite,
                                              bmp.PixelFormat);

            IntPtr ptr   = bmpData.Scan0;
            int    bytes = Math.Abs(bmpData.Stride) * bmp.Height;

            byte[] rgbaValues = new byte[bytes];

            int bitsPerPixel = (int)tex.BytesPerPixel * 8;

            int Offset = 0;

            for (int y = 0; y < size.Height; y++)
            {
                for (int x = 0; x < size.Width; x++)
                {
                    int  xInd = x & 7, yInd = y & 7;
                    int  pixelOffset = GetPixelDataOffset(size, x, y, tex.BytesPerPixel) + (int)(tex.BytesPerPixel * (double)TileTable[yInd, xInd]);
                    uint Value;
                    switch (bitsPerPixel)
                    {
                    case 4:
                        Value = (uint)(tex.ImageData[pixelOffset] >> (4 * (x & 1))) & 0xF;
                        break;

                    case 8:
                        Value = (uint)(tex.ImageData[pixelOffset]);
                        break;

                    case 16:
                        Value = BitConverter.ToUInt16(tex.ImageData, pixelOffset);
                        break;

                    case 24:
                        Value = (uint)(BitConverter.ToUInt32(tex.ImageData, pixelOffset));
                        break;

                    case 32:
                        Value = BitConverter.ToUInt32(tex.ImageData, pixelOffset);
                        break;

                    default:
                        Value = 0;
                        break;
                    }

                    uint Red, Green, Blue, Alpha, Luminance;
                    Red = Green = Blue = Alpha = Luminance = 0xFF;

                    if (tex.LuminanceBitSize > 0)
                    {
                        Luminance = (Value & luminanceBitMask) * (0xFF / luminanceBitMask);
                        Value   >>= tex.LuminanceBitSize;
                    }



                    switch (tex.ChannelOrder)
                    {
                    case ChannelOrder.Rgba:
                        if (tex.RedBitSize > 0)
                        {
                            Red     = (Value & redBitMask) * (0xFF / redBitMask);
                            Value >>= tex.RedBitSize;
                        }
                        if (tex.GreenBitSize > 0)
                        {
                            Green   = (Value & greenBitMask) * (0xFF / greenBitMask);
                            Value >>= tex.GreenBitSize;
                        }
                        if (tex.BlueBitSize > 0)
                        {
                            Blue    = (Value & blueBitMask) * (0xFF / blueBitMask);
                            Value >>= tex.BlueBitSize;
                        }
                        if (tex.AlphaBitSize > 0)
                        {
                            Alpha   = (Value & alphaBitMask) * (0xFF / alphaBitMask);
                            Value >>= tex.AlphaBitSize;
                        }
                        break;

                    case ChannelOrder.Abgr:
                        if (tex.AlphaBitSize > 0)
                        {
                            Alpha   = (Value & alphaBitMask) * (0xFF / alphaBitMask);
                            Value >>= tex.AlphaBitSize;
                        }
                        if (tex.BlueBitSize > 0)
                        {
                            Blue    = (Value & blueBitMask) * (0xFF / blueBitMask);
                            Value >>= tex.BlueBitSize;
                        }
                        if (tex.GreenBitSize > 0)
                        {
                            Green   = (Value & greenBitMask) * (0xFF / greenBitMask);
                            Value >>= tex.GreenBitSize;
                        }
                        if (tex.RedBitSize > 0)
                        {
                            Red     = (Value & redBitMask) * (0xFF / redBitMask);
                            Value >>= tex.RedBitSize;
                        }
                        break;
                    }

                    if (tex.LuminanceBitSize > 0)
                    {
                        rgbaValues[Offset + 0] = (byte)Luminance;
                        rgbaValues[Offset + 1] = (byte)Luminance;
                        rgbaValues[Offset + 2] = (byte)Luminance;
                        rgbaValues[Offset + 3] = (byte)Alpha;
                    }
                    else
                    {
                        rgbaValues[Offset + 0] = (byte)Blue;
                        rgbaValues[Offset + 1] = (byte)Green;
                        rgbaValues[Offset + 2] = (byte)Red;
                        rgbaValues[Offset + 3] = (byte)Alpha;
                    }
                    Offset += 4;
                }
            }

            tex.PostProcess(size, rgbaValues);

            Marshal.Copy(rgbaValues, 0, ptr, bytes);
            bmp.UnlockBits(bmpData);

            if (crop)
            {
                Bitmap bmp2 = new Bitmap(tex.Size.Width, tex.Size.Height);
                using (Graphics g = Graphics.FromImage(bmp2))
                    g.DrawImage(bmp, new Point(0, 0));
                return(bmp2);
            }

            return(bmp);
        }