Example #1
0
        public void Save(Stream output)
        {
            ImageSettings modSettings = Settings;

            modSettings.Width  = Image.Width;
            modSettings.Height = Image.Height;

            byte[] data = Common.Save(Image, modSettings);
            using (BinaryWriterX br = new BinaryWriterX(new MemoryStream()))
            {
                JTEXRawHeader.width = (ushort)Image.Width; JTEXRawHeader.height = (ushort)Image.Height;
                br.WriteStruct <RawHeader>(JTEXRawHeader);
                br.BaseStream.Position = JTEXRawHeader.dataStart;
                br.Write(data);
                br.BaseStream.Position = 0;

                if (lz11_compressed)
                {
                    byte[] comp = LZ11.Compress(br.BaseStream);
                    output.Write(comp, 0, comp.Length);
                }
                else
                {
                    output.Write(new BinaryReaderX(br.BaseStream).ReadBytes((int)br.BaseStream.Length), 0, (int)br.BaseStream.Length);
                }
                output.Close();
            }
        }
Example #2
0
        public XI(Stream input)
        {
            using (var br = new BinaryReaderX(input))
            {
                var header = br.ReadStruct <Header>();
                Settings = new ImageSettings {
                    Width = header.width, Height = header.height, Format = ImageSettings.ConvertFormat(header.imageFormat), Orientation = header.orientation, PadToPowerOf2 = false
                };
                CombineFormat = header.combineFormat;

                if (CombineFormat != 1)
                {
                    throw new Exception($"Unknown combine format {header.combineFormat}");
                }

                var buf1 = Level5.Decompress(input);
                while (input.Position % 4 != 0)
                {
                    input.ReadByte();
                }
                var buf2 = Level5.Decompress(input);

                var ms = new MemoryStream();
                for (int i = 0; i < buf1.Length / 2; i++)
                {
                    int index = BitConverter.ToInt16(buf1, 2 * i);
                    ms.Write(buf2, index * header.bytesPerTile, header.bytesPerTile);
                }
                Image = Common.Load(ms.ToArray(), Settings);
            }
        }
Example #3
0
        public static Bitmap Load(byte[] tex, ImageSettings settings)
        {
            int width = settings.Width, height = settings.Height;
            var colors = GetColorsFromTexture(tex, settings);

            var points = GetPointSequence(settings);

            // Now we just need to merge the points with the colors
            var bmp  = new Bitmap(width, height);
            var data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

            unsafe
            {
                var ptr = (int *)data.Scan0;
                foreach (var pair in points.Zip(colors, Tuple.Create))
                {
                    int x = pair.Item1.X, y = pair.Item1.Y;
                    if (0 <= x && x < width && 0 <= y && y < height)
                    {
                        var color = pair.Item2;
                        if (settings.PixelShader != null)
                        {
                            color = settings.PixelShader(color);
                        }
                        ptr[data.Stride * y / 4 + x] = color.ToArgb();
                    }
                }
            }
            bmp.UnlockBits(data);
            return(bmp);
        }
Example #4
0
        public BXLIM(Stream input)
        {
            using (var br = new BinaryReaderX(input))
            {
                var tex = br.ReadBytes((int)br.BaseStream.Length - 40);
                sections = br.ReadSections();
                switch (sections.Header.magic)
                {
                case "CLIM":
                    BCLIMHeader = sections[0].Data.BytesToStruct <BCLIMImageHeader>(br.ByteOrder);
                    Settings    = new ImageSettings {
                        Width = BCLIMHeader.width, Height = BCLIMHeader.height, Format = ImageSettings.ConvertFormat(BCLIMHeader.format), Orientation = BCLIMHeader.orientation
                    };
                    break;

                case "FLIM":
                    BFLIMHeader = sections[0].Data.BytesToStruct <BFLIMImageHeader>(br.ByteOrder);
                    Settings    = new ImageSettings {
                        Width = BFLIMHeader.width, Height = BFLIMHeader.height, Format = ImageSettings.ConvertFormat(BFLIMHeader.format), Orientation = BFLIMHeader.orientation
                    };
                    break;

                default:
                    throw new NotSupportedException($"Unknown image format {sections.Header.magic}");
                }
                Image = Common.Load(tex, Settings);
            }
        }
Example #5
0
        public RawJTEX(Stream input)
        {
            using (var br = new BinaryReaderX(input))
            {
                Stream stream;

                if (br.ReadByte() == 0x11)
                {
                    br.BaseStream.Position = 0;
                    uint size = br.ReadUInt32() >> 8;
                    br.BaseStream.Position = 0;
                    lz11_compressed        = true;
                    byte[] decomp = LZ11.Decompress(br.BaseStream);
                    stream = new MemoryStream(decomp);
                }
                else
                {
                    br.BaseStream.Position = 0;
                    stream = br.BaseStream;
                }

                //File.OpenWrite("test.decomp").Write(new BinaryReaderX(stream).ReadBytes((int)stream.Length), 0, (int)stream.Length);

                using (BinaryReaderX br2 = new BinaryReaderX(stream))
                {
                    JTEXRawHeader           = br2.ReadStruct <RawHeader>();
                    br2.BaseStream.Position = JTEXRawHeader.dataStart;
                    Settings = new ImageSettings {
                        Width = JTEXRawHeader.width, Height = JTEXRawHeader.height, Format = JTEXRawHeader.format
                    };
                    Image = Common.Load(br2.ReadBytes((int)(br2.BaseStream.Length - br2.BaseStream.Position)), Settings);
                }
            }
        }
Example #6
0
        static IEnumerable <Point> GetPointSequence(ImageSettings settings)
        {
            int strideWidth  = (settings.Width + 7) & ~7;
            int strideHeight = (settings.Height + 7) & ~7;

            if (settings.PadToPowerOf2)
            {
                strideWidth  = 2 << (int)Math.Log(strideWidth - 1, 2);
                strideHeight = 2 << (int)Math.Log(strideHeight - 1, 2);
            }
            int stride = (int)settings.Orientation < 4 ? strideWidth : strideHeight;

            for (int i = 0; i < strideWidth * strideHeight; i++)
            {
                int x_out = 0, y_out = 0, x_in = 0, y_in = 0;
                if (settings.ZOrder)
                {
                    x_out = (i / 64 % (stride / 8)) * 8;
                    y_out = (i / 64 / (stride / 8)) * 8;
                    x_in  = (i / 4 & 4) | (i / 2 & 2) | (i & 1);
                    y_in  = (i / 8 & 4) | (i / 4 & 2) | (i / 2 & 1);
                }
                else
                {
                    x_out = (i / 64 % (stride / 8)) * 8;
                    y_out = (i / 64 / (stride / 8)) * 8;
                    x_in  = i % 64 % 8;
                    y_in  = i % 64 / 8;
                }

                switch (settings.Orientation)
                {
                case Orientation.Default:
                    yield return(new Point(x_out + x_in, y_out + y_in));

                    break;

                case Orientation.TransposeTile:
                    yield return(new Point(x_out + y_in, y_out + x_in));

                    break;

                case Orientation.Rotate90:
                    yield return(new Point(y_out + y_in, stride - 1 - (x_out + x_in)));

                    break;

                case Orientation.Transpose:
                    yield return(new Point(y_out + y_in, x_out + x_in));

                    break;

                default:
                    throw new NotSupportedException($"Unknown orientation format {settings.Orientation}");
                }
            }
        }
Example #7
0
        public BXLIM(Stream input)
        {
            using (var br = new BinaryReaderX(input))
            {
                var tex = br.ReadBytes((int)br.BaseStream.Length - 40);
                sections  = br.ReadSections();
                byteOrder = br.ByteOrder;
                switch (sections.Header.magic)
                {
                case "CLIM":
                    BCLIMHeader = sections[0].Data.BytesToStruct <BCLIMImageHeader>(byteOrder);
                    Settings    = new ImageSettings
                    {
                        Width       = BCLIMHeader.width,
                        Height      = BCLIMHeader.height,
                        Format      = ImageSettings.ConvertFormat(BCLIMHeader.format),
                        Orientation = ImageSettings.ConvertOrientation(BCLIMHeader.orientation)
                    };
                    Image = Common.Load(tex, Settings);
                    break;

                case "FLIM":
                    if (byteOrder == ByteOrder.LittleEndian)
                    {
                        BFLIMHeaderLE = sections[0].Data.BytesToStruct <BFLIMImageHeaderLE>(byteOrder);
                        Settings      = new ImageSettings
                        {
                            Width       = BFLIMHeaderLE.width,
                            Height      = BFLIMHeaderLE.height,
                            Format      = ImageSettings.ConvertFormat(BFLIMHeaderLE.format),
                            Orientation = ImageSettings.ConvertOrientation(BFLIMHeaderLE.orientation),
                        };
                        Image = Common.Load(tex, Settings);
                    }
                    else
                    {
                        BFLIMHeaderBE = sections[0].Data.BytesToStruct <BFLIMImageHeaderBE>(byteOrder);
                        var padWidth  = 2 << (int)Math.Log(BFLIMHeaderBE.width - 1, 2);
                        var padHeight = 2 << (int)Math.Log(BFLIMHeaderBE.height - 1, 2);
                        Settings = new ImageSettings
                        {
                            Width         = padWidth,
                            Height        = padHeight,
                            Format        = ImageSettings.ConvertFormat(BFLIMHeaderBE.format),
                            Orientation   = Cetera.Image.Orientation.Default,
                            PadToPowerOf2 = true,
                            ZOrder        = (br.ByteOrder == ByteOrder.LittleEndian) ? true : false
                        };
                        Image = SwizzleTiles(Common.Load(tex, Settings), padWidth, padHeight, BFLIMHeaderBE.width, BFLIMHeaderBE.height, 8, BFLIMHeaderBE.tileMode);
                    }
                    break;

                default:
                    throw new NotSupportedException($"Unknown image format {sections.Header.magic}");
                }
            }
        }
Example #8
0
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output))
            {
                var    settings = new ImageSettings();
                byte[] texture;

                switch (sections.Header.magic)
                {
                case "CLIM":
                    settings.Width       = BCLIMHeader.width;
                    settings.Height      = BCLIMHeader.height;
                    settings.Orientation = ImageSettings.ConvertOrientation(BCLIMHeader.orientation);
                    settings.Format      = ImageSettings.ConvertFormat(BCLIMHeader.format);
                    texture = Common.Save(Image, settings);
                    bw.Write(texture);

                    // We can now change the image width/height/filesize!
                    BCLIMHeader.width         = (short)Image.Width;
                    BCLIMHeader.height        = (short)Image.Height;
                    BCLIMHeader.datasize      = texture.Length;
                    sections[0].Data          = BCLIMHeader.StructToBytes();
                    sections.Header.file_size = texture.Length + 40;
                    bw.WriteSections(sections);
                    break;

                case "FLIM":
                    if (byteOrder == ByteOrder.LittleEndian)
                    {
                        settings.Width       = BFLIMHeaderLE.width;
                        settings.Height      = BFLIMHeaderLE.height;
                        settings.Orientation = ImageSettings.ConvertOrientation(BFLIMHeaderLE.orientation);
                        settings.Format      = ImageSettings.ConvertFormat(BFLIMHeaderLE.format);
                        texture = Common.Save(Image, settings);
                        bw.Write(texture);

                        // We can now change the image width/height/filesize!
                        BFLIMHeaderLE.width       = (short)Image.Width;
                        BFLIMHeaderLE.height      = (short)Image.Height;
                        BFLIMHeaderLE.datasize    = texture.Length;
                        sections[0].Data          = BFLIMHeaderLE.StructToBytes();
                        sections.Header.file_size = texture.Length + 40;
                        bw.WriteSections(sections);
                    }
                    else
                    {
                        throw new NotSupportedException($"Big Endian FLIM isn't savable yet!");
                    }
                    break;

                default:
                    throw new NotSupportedException($"Unknown image format {sections.Header.magic}");
                }
            }
        }
Example #9
0
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output))
            {
                var    settings = new ImageSettings();
                byte[] texture;

                switch (sections.Header.magic)
                {
                case "CLIM":
                    settings.Width       = BCLIMHeader.width;
                    settings.Height      = BCLIMHeader.height;
                    settings.Orientation = BCLIMHeader.orientation;
                    settings.Format      = ImageSettings.ConvertFormat(BCLIMHeader.format);
                    texture = Common.Save(Image, settings);
                    bw.Write(texture);

                    // We can now change the image width/height/filesize!
                    var modifiedBCLIMHeader = BCLIMHeader;
                    modifiedBCLIMHeader.width    = (short)Image.Width;
                    modifiedBCLIMHeader.height   = (short)Image.Height;
                    modifiedBCLIMHeader.datasize = texture.Length;
                    BCLIMHeader               = modifiedBCLIMHeader;
                    sections[0].Data          = BCLIMHeader.StructToBytes();
                    sections.Header.file_size = texture.Length + 40;
                    bw.WriteSections(sections);
                    break;

                case "FLIM":
                    settings.Width       = BFLIMHeader.width;
                    settings.Height      = BFLIMHeader.height;
                    settings.Orientation = BFLIMHeader.orientation;
                    settings.Format      = ImageSettings.ConvertFormat(BFLIMHeader.format);
                    texture = Common.Save(Image, settings);
                    bw.Write(texture);

                    // We can now change the image width/height/filesize!
                    var modifiedBFLIMHeader = BFLIMHeader;
                    modifiedBFLIMHeader.width    = (short)Image.Width;
                    modifiedBFLIMHeader.height   = (short)Image.Height;
                    modifiedBFLIMHeader.datasize = texture.Length;
                    BFLIMHeader               = modifiedBFLIMHeader;
                    sections[0].Data          = BFLIMHeader.StructToBytes();
                    sections.Header.file_size = texture.Length + 40;
                    bw.WriteSections(sections);
                    break;

                default:
                    throw new NotSupportedException($"Unknown image format {sections.Header.magic}");
                }
            }
        }
Example #10
0
 public JTEX(Stream input)
 {
     using (var br = new BinaryReaderX(input))
     {
         JTEXHeader = br.ReadStruct <Header>();
         Settings   = new ImageSettings {
             Width = JTEXHeader.width, Height = JTEXHeader.height
         };
         Settings.SetFormat(JTEXHeader.format);
         var texture2 = br.ReadBytes(JTEXHeader.unk3[0]); // bytes to read?
         Image = Common.Load(texture2, Settings);
     }
 }
Example #11
0
        public void Save(Stream output)
        {
            using (var bw = new BinaryWriterX(output))
            {
                var modifiedJTEXHeader = JTEXHeader;
                modifiedJTEXHeader.width  = (short)Image.Width;
                modifiedJTEXHeader.height = (short)Image.Height;

                var settings = new ImageSettings();
                settings.Width  = modifiedJTEXHeader.width;
                settings.Height = modifiedJTEXHeader.height;
                settings.Format = ImageSettings.ConvertFormat(modifiedJTEXHeader.format);

                byte[] texture = Common.Save(Image, settings);
                modifiedJTEXHeader.unk3[0] = texture.Length;
                JTEXHeader = modifiedJTEXHeader;

                bw.WriteStruct(JTEXHeader);
                bw.Write(texture);
            }
        }
Example #12
0
        public static byte[] Save(Bitmap bmp, ImageSettings settings)
        {
            settings.Width  = bmp.Width;
            settings.Height = bmp.Height;
            var points = GetPointSequence(settings);

            var ms          = new MemoryStream();
            var etc1encoder = new ETC1.Encoder();

            Enum.TryParse <DXT.Formats>(settings.Format.ToString(), false, out var dxtFormat);
            var dxtencoder = new DXT.Encoder(dxtFormat);

            using (var bw = new BinaryWriterX(ms))
            {
                foreach (var point in points)
                {
                    int x = Clamp(point.X, 0, bmp.Width);
                    int y = Clamp(point.Y, 0, bmp.Height);

                    var color = bmp.GetPixel(x, y);
                    if (settings.PixelShader != null)
                    {
                        color = settings.PixelShader(color);
                    }

                    switch (settings.Format)
                    {
                    case Format.L8:
                        bw.Write(color.G);
                        break;

                    case Format.A8:
                        bw.Write(color.A);
                        break;

                    case Format.LA44:
                        bw.WriteNibble(color.A / 16);
                        bw.WriteNibble(color.G / 16);
                        break;

                    case Format.LA88:
                        bw.Write(color.A);
                        bw.Write(color.G);
                        break;

                    case Format.HL88:
                        bw.Write(color.G);
                        bw.Write(color.R);
                        break;

                    case Format.RGB565:
                        bw.Write((short)((color.R / 8 << 11) | (color.G / 4 << 5) | (color.B / 8)));
                        break;

                    case Format.RGB888:
                        bw.Write(color.B);
                        bw.Write(color.G);
                        bw.Write(color.R);
                        break;

                    case Format.RGBA5551:
                        bw.Write((short)((color.R / 8 << 11) | (color.G / 8 << 6) | (color.B / 8 << 1) | color.A / 128));
                        break;

                    case Format.RGBA4444:
                        bw.WriteNibble(color.A / 16);
                        bw.WriteNibble(color.B / 16);
                        bw.WriteNibble(color.G / 16);
                        bw.WriteNibble(color.R / 16);
                        break;

                    case Format.RGBA8888:
                        bw.Write(color.A);
                        bw.Write(color.B);
                        bw.Write(color.G);
                        bw.Write(color.R);
                        break;

                    case Format.ETC1:
                    case Format.ETC1A4:
                        etc1encoder.Set(color, data =>
                        {
                            if (settings.Format == Format.ETC1A4)
                            {
                                bw.Write(data.Alpha);
                            }
                            bw.WriteStruct(data.Block);
                        });
                        break;

                    case Format.DXT1:
                    case Format.DXT5:
                        dxtencoder.Set(color, data =>
                        {
                            if (settings.Format == Format.DXT5)
                            {
                                bw.Write(data.alpha);
                            }
                            bw.Write(data.block);
                        });
                        break;

                    case Format.L4:
                        bw.WriteNibble(color.G / 16);
                        break;

                    case Format.A4:
                        bw.WriteNibble(color.A / 16);
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                }
            }

            return(ms.ToArray());
        }
Example #13
0
        static IEnumerable <Point> GetPointSequence(ImageSettings settings)
        {
            switch (settings.Format)
            {
            case Format.ATI1A:
            case Format.ATI1L:
            case Format.ATI2:
            case Format.ETC1:
            case Format.ETC1A4:
            case Format.DXT1:
            case Format.DXT3:
            case Format.DXT5:
                settings.TileSize = settings.TileSize + 3 & ~0x3;
                break;
            }

            int strideWidth  = (settings.Width + 7) & ~7;
            int strideHeight = (settings.Height + 7) & ~7;

            if (settings.PadToPowerOf2)
            {
                strideWidth  = 2 << (int)Math.Log(strideWidth - 1, 2);
                strideHeight = 2 << (int)Math.Log(strideHeight - 1, 2);
            }

            //stride TileSize
            var tileSize = 0;

            if (settings.ZOrder)
            {
                tileSize = 2 << (int)(Math.Log(((settings.TileSize + 7) & ~7) - 1, 2));
            }
            else
            {
                tileSize = settings.TileSize;
            }
            int powTileSize = (int)Math.Pow(tileSize, 2);

            int stride = strideWidth;

            switch (settings.Orientation)
            {
            case Orientation.Rotate90:
            case Orientation.Transpose:
                stride = strideHeight;
                break;
            }

            for (int i = 0; i < strideWidth * strideHeight; i++)
            {
                //in == order inside a tile
                //out == order of tiles themselves
                int x_out = 0, y_out = 0, x_in = 0, y_in = 0;
                if (settings.ZOrder)
                {
                    x_out = (i / powTileSize % (stride / tileSize)) * tileSize;
                    y_out = (i / powTileSize / (stride / tileSize)) * tileSize;
                    x_in  = ZOrderX(tileSize, i);
                    y_in  = ZOrderY(tileSize, i);
                }
                else
                {
                    x_out = (i / powTileSize % (stride / tileSize)) * tileSize;
                    y_out = (i / powTileSize / (stride / tileSize)) * tileSize;

                    switch (settings.Format)
                    {
                    case Format.ATI1A:
                    case Format.ATI1L:
                    case Format.ATI2:
                    case Format.ETC1:
                    case Format.ETC1A4:
                    case Format.DXT1:
                    case Format.DXT3:
                    case Format.DXT5:
                        x_in = (i % 4 + i % powTileSize / 16 * 4) % tileSize;
                        y_in = (i % 16 / 4 + i / (tileSize * 4) * 4) % tileSize;
                        break;

                    default:
                        x_in = i % powTileSize % tileSize;
                        y_in = i % powTileSize / tileSize;
                        break;
                    }
                }

                switch (settings.Orientation)
                {
                case Orientation.Default:
                    yield return(new Point(x_out + x_in, y_out + y_in));

                    break;

                case Orientation.HorizontalFlip:
                    yield return(new Point(stride - 1 - (x_out + x_in), y_out + y_in));

                    break;

                case Orientation.Rotate90:
                    yield return(new Point(y_out + y_in, stride - 1 - (x_out + x_in)));

                    break;

                case Orientation.Transpose:
                    yield return(new Point(y_out + y_in, x_out + x_in));

                    break;

                case Orientation.TransposeTile:
                    yield return(new Point(x_out + y_in, y_out + x_in));

                    break;

                default:
                    throw new NotSupportedException($"Unknown orientation format {settings.Orientation}");
                }
            }
        }
Example #14
0
        static IEnumerable <Color> GetColorsFromTexture(byte[] tex, ImageSettings settings)
        {
            var format = settings.Format;

            using (var br = new BinaryReaderX(new MemoryStream(tex)))
            {
                var etc1decoder = new ETC1.Decoder();

                Enum.TryParse <DXT.Formats>(format.ToString(), false, out var dxtFormat);
                var dxtdecoder = new DXT.Decoder(dxtFormat);

                Enum.TryParse <ATI.Formats>(format.ToString(), false, out var atiFormat);
                var atidecoder = new ATI.Decoder(atiFormat);

                while (true)
                {
                    int a = 255, r = 255, g = 255, b = 255;
                    switch (format)
                    {
                    case Format.L8:
                        b = g = r = br.ReadByte();
                        break;

                    case Format.A8:
                        a = br.ReadByte();
                        break;

                    case Format.LA44:
                        a = br.ReadNibble() * 17;
                        b = g = r = br.ReadNibble() * 17;
                        break;

                    case Format.LA88:
                        if (settings.ByteOrder == ByteOrder.LittleEndian)
                        {
                            a = br.ReadByte();
                            b = g = r = br.ReadByte();
                        }
                        else
                        {
                            b = g = r = br.ReadByte();
                            a = br.ReadByte();
                        }
                        break;

                    case Format.HL88:
                        g = br.ReadByte();
                        r = br.ReadByte();
                        break;

                    case Format.RGB565:
                        var s = br.ReadUInt16();
                        b = (s % 32) * 33 / 4;
                        g = (s >> 5) % 64 * 65 / 16;
                        r = (s >> 11) * 33 / 4;
                        break;

                    case Format.RGB888:
                        b = br.ReadByte();
                        g = br.ReadByte();
                        r = br.ReadByte();
                        break;

                    case Format.RGBA5551:
                        var s2 = br.ReadUInt16();
                        a = (s2 & 1) * 255;
                        b = (s2 >> 1) % 32 * 33 / 4;
                        g = (s2 >> 6) % 32 * 33 / 4;
                        r = (s2 >> 11) % 32 * 33 / 4;
                        break;

                    case Format.RGBA4444:
                        a = br.ReadNibble() * 17;
                        b = br.ReadNibble() * 17;
                        g = br.ReadNibble() * 17;
                        r = br.ReadNibble() * 17;
                        break;

                    case Format.RGBA8888:
                        if (settings.ByteOrder == ByteOrder.LittleEndian)
                        {
                            a = br.ReadByte();
                            b = br.ReadByte();
                            g = br.ReadByte();
                            r = br.ReadByte();
                        }
                        else
                        {
                            r = br.ReadByte();
                            g = br.ReadByte();
                            b = br.ReadByte();
                            a = br.ReadByte();
                        }
                        break;

                    case Format.RGBA1010102:
                        var pack = br.ReadUInt32();
                        r = (int)((pack >> 22) / 4);
                        g = (int)(((pack >> 12) & 0x3FF) / 4);
                        b = (int)(((pack >> 2) & 0x3FF) / 4);
                        a = (int)((pack & 0x3) * 85);
                        break;

                    case Format.ETC1:
                    case Format.ETC1A4:
                        yield return(etc1decoder.Get(() =>
                        {
                            var etc1Alpha = format == Format.ETC1A4 ? br.ReadUInt64() : ulong.MaxValue;
                            return new ETC1.PixelData {
                                Alpha = etc1Alpha, Block = br.ReadStruct <ETC1.Block>()
                            };
                        }));

                        continue;

                    case Format.DXT1:
                    case Format.DXT3:
                    case Format.DXT5:
                        yield return(dxtdecoder.Get(() =>
                        {
                            if (br.BaseStream.Position == br.BaseStream.Length)
                            {
                                return (0, 0);
                            }
                            var dxt5Alpha = format == Format.DXT3 || format == Format.DXT5 ? br.ReadUInt64() : 0;
                            return (dxt5Alpha, br.ReadUInt64());
                        }));

                        continue;

                    case Format.ATI1L:
                    case Format.ATI1A:
                    case Format.ATI2:
                        yield return(atidecoder.Get(() =>
                        {
                            if (br.BaseStream.Position == br.BaseStream.Length)
                            {
                                return (0, 0);
                            }
                            return (br.ReadUInt64(), format == Format.ATI2 ? br.ReadUInt64() : 0);
                        }));

                        continue;

                    case Format.L4:
                        b = g = r = br.ReadNibble() * 17;
                        break;

                    case Format.A4:
                        a = br.ReadNibble() * 17;
                        break;

                    case Format.PVRTC:
                        var bmp = PVRTC.PvrtcDecompress.DecodeRgb4Bpp(tex, settings.Width);
                        for (int y = 0; y < settings.Height; y++)
                        {
                            for (int x = 0; x < settings.Width; x++)
                            {
                                yield return(bmp.GetPixel(x, y));
                            }
                        }
                        continue;

                    case Format.PVRTCA:
                        bmp = PVRTC.PvrtcDecompress.DecodeRgba4Bpp(tex, settings.Width);
                        for (int y = 0; y < settings.Height; y++)
                        {
                            for (int x = 0; x < settings.Width; x++)
                            {
                                yield return(bmp.GetPixel(x, y));
                            }
                        }
                        continue;

                    default:
                        throw new NotSupportedException($"Unknown image format {format}");
                    }
                    yield return(Color.FromArgb(a, r, g, b));
                }
            }
        }
Example #15
0
        public static byte[] Save(Bitmap bmp, ImageSettings settings)
        {
            settings.Width  = bmp.Width;
            settings.Height = bmp.Height;
            var points = GetPointSequence(settings);

            var ms          = new MemoryStream();
            var etc1encoder = new ETC1.Encoder();

            using (var bw = new BinaryWriterX(ms))
            {
                foreach (var point in points)
                {
                    int x = Clamp(point.X, 0, bmp.Width);
                    int y = Clamp(point.Y, 0, bmp.Height);

                    var color = bmp.GetPixel(x, y);
                    //if (color.A == 0) color = default(Color); // daigasso seems to need this

                    switch (settings.Format)
                    {
                    case Format.L8:
                        bw.Write(color.G);
                        break;

                    case Format.A8:
                        bw.Write(color.A);
                        break;

                    case Format.LA44:
                        bw.WriteNibble(color.A / 16);
                        bw.WriteNibble(color.G / 16);
                        break;

                    case Format.LA88:
                        bw.Write(color.A);
                        bw.Write(color.G);
                        break;

                    case Format.HL88:
                        bw.Write(color.G);
                        bw.Write(color.R);
                        break;

                    case Format.RGB565:
                        bw.Write((short)((color.R / 8 << 11) | (color.G / 4 << 5) | (color.B / 8)));
                        break;

                    case Format.RGB888:
                        bw.Write(color.B);
                        bw.Write(color.G);
                        bw.Write(color.R);
                        break;

                    case Format.RGBA5551:
                        bw.Write((short)((color.R / 8 << 11) | (color.G / 8 << 6) | (color.B / 8 << 1) | color.A / 128));
                        break;

                    case Format.RGBA4444:
                        bw.WriteNibble(color.A / 16);
                        bw.WriteNibble(color.B / 16);
                        bw.WriteNibble(color.G / 16);
                        bw.WriteNibble(color.R / 16);
                        break;

                    case Format.RGBA8888:
                        bw.Write(color.A);
                        bw.Write(color.B);
                        bw.Write(color.G);
                        bw.Write(color.R);
                        break;

                    case Format.ETC1:
                    case Format.ETC1A4:
                        etc1encoder.Set(color, data =>
                        {
                            if (settings.Format == Format.ETC1A4)
                            {
                                bw.Write(data.Alpha);
                            }
                            bw.WriteStruct(data.Block);
                        });
                        break;

                    case Format.L4:
                        bw.WriteNibble(color.G / 16);
                        break;

                    case Format.A4:
                        bw.WriteNibble(color.A / 16);
                        break;

                    default:
                        throw new NotSupportedException();
                    }
                }
            }

            return(ms.ToArray());
        }