Exemple #1
0
    static void Write(IReadOnlyTexture <byte> existing, ISerializer s)
    {
        if (existing.Regions.Count > 255)
        {
            throw new ArgumentOutOfRangeException($"Tried to save an image with more than 255 frames as a multi-header sprite ({existing.Name} with {existing.Regions.Count} regions)");
        }

        for (int i = 0; i < existing.Regions.Count; i++)
        {
            var region = existing.Regions[i];
            s.UInt16("FrameWidth", (ushort)region.Width);
            s.UInt16("FrameHeight", (ushort)region.Height);
            s.UInt8(null, 0);
            s.UInt8(null, (byte)existing.Regions.Count);

            var    frameSize  = region.Width * region.Height;
            byte[] frameBytes = ArrayPool <byte> .Shared.Rent(frameSize);

            try
            {
                Debug.Assert(existing != null, nameof(existing) + " != null");

                BlitUtil.BlitDirect(
                    existing.GetRegionBuffer(i),
                    new ImageBuffer <byte>(region.Width, region.Height, region.Width, frameBytes));

                s.Bytes("Frame" + i, frameBytes, region.Width * region.Height);
            }
            finally { ArrayPool <byte> .Shared.Return(frameBytes); }
        }
    }
Exemple #2
0
        static void Write(IReadOnlyTexture <byte> existing, ISerializer s)
        {
            var distinctSizes = existing.Regions.Select(x => (x.Width, x.Height)).Distinct();

            if (distinctSizes.Count() > 1)
            {
                var parts  = distinctSizes.Select(x => $"({x.Width}, {x.Height})");
                var joined = string.Join(", ", parts);
                throw new InvalidOperationException($"Tried to a write an image with non-uniform frames to a single-header sprite (sizes: {joined})");
            }

            var width      = (ushort)existing.Regions[0].Width;
            var height     = (ushort)existing.Regions[0].Height;
            var frameCount = (byte)existing.Regions.Count;

            s.UInt16("Width", width);
            s.UInt16("Height", height);
            s.UInt8(null, 0);
            s.UInt8("Frames", frameCount);

            var frameBytes = new byte[width * height];
            var frame      = new ImageBuffer <byte>(width, height, width, frameBytes);

            for (int i = 0; i < frameCount; i++)
            {
                BlitUtil.BlitDirect(existing.GetRegionBuffer(i), frame);
                s.Bytes("Frame" + i, frameBytes, width * height);
            }
        }
Exemple #3
0
    IReadOnlyTexture <byte> Write(IReadOnlyTexture <byte> existing, AssetInfo info, AssetMapping mapping, ISerializer s, IJsonUtil jsonUtil)
    {
        if (existing == null)
        {
            throw new ArgumentNullException(nameof(existing));
        }
        int width  = info.Width;
        int height = info.Height;

        if (width == 0 || height == 0)
        {
            throw new ArgumentException("Explicit width and height must be defined when using FontSpriteLoader", nameof(info));
        }

        var repacked = new SimpleTexture <byte>(existing.Id, existing.Name, width, height * existing.Regions.Count);

        for (int i = 0; i < existing.Regions.Count; i++)
        {
            var oldFrame = existing.GetRegionBuffer(i);
            repacked.AddRegion(0, i * height, width, height);
            BlitUtil.BlitDirect(oldFrame, repacked.GetMutableRegionBuffer(i));
        }

        var font = _loader.Serdes(repacked, info, mapping, s, jsonUtil);

        return(font == null ? null : existing);
    }
Exemple #4
0
        void TrackFrameCount_ValueChanged(object sender, EventArgs e)
        {
            var asset = _core.SelectedObject;

            if (_logicalSprite != null && asset != null)
            {
                int?newHeight =
                    trackFrameCount.Value <= 1
                        ? (int?)null
                        : _logicalSprite.Height / trackFrameCount.Value;

                if (!asset.File.Height.HasValue &&
                    asset.File.Loader == FixedSizeSpriteLoader.TypeString &&
                    asset.Height != newHeight)
                {
                    asset.Set(AssetProperty.Height, newHeight);
                    _logicalSprite = null; // Force sprite reload
                    _visualSprite  = null;
                    Render();
                }
            }

            if (sender != numFrameCount && (int)numFrameCount.Value != trackFrameCount.Value)
            {
                numFrameCount.Value = trackFrameCount.Value;
            }
        }
Exemple #5
0
    public IReadOnlyTexture <byte> Serdes(IReadOnlyTexture <byte> existing, AssetInfo info, AssetMapping mapping, ISerializer s, IJsonUtil jsonUtil)
    {
        if (info == null)
        {
            throw new ArgumentNullException(nameof(info));
        }
        if (s == null)
        {
            throw new ArgumentNullException(nameof(s));
        }

        var paletteNum = info.Get(AssetProperty.PaletteId, 0);
        var paletteId  = new PaletteId(AssetType.Palette, paletteNum);
        var palette    = Resolve <IAssetManager>().LoadPalette(paletteId);

        if (palette == null)
        {
            throw new InvalidOperationException($"Could not load palette {paletteId} ({paletteNum}) for asset {info.AssetId} in file {info.File.Filename}");
        }
        var unambiguousPalette = palette.GetUnambiguousPalette();

        if (s.IsWriting())
        {
            if (existing == null)
            {
                throw new ArgumentNullException(nameof(existing));
            }
            var encoder = new PngEncoder();
            PackedChunks.Pack(s, existing.Regions.Count, frameNum => Write(encoder, unambiguousPalette, existing, frameNum));
            return(existing);
        }

        // Read
        var decoder       = new PngDecoder();
        var configuration = new Configuration();
        var images        = new List <Image <Rgba32> >();

        try
        {
            foreach (var(bytes, _) in PackedChunks.Unpack(s))
            {
                using var stream = new MemoryStream(bytes);
                images.Add(decoder.Decode <Rgba32>(configuration, stream));
            }

            return(Read(info.AssetId, unambiguousPalette, images));
        }
        finally { foreach (var image in images)
                  {
                      image.Dispose();
                  }
        }
    }
Exemple #6
0
        Bitmap GenerateBitmap(IReadOnlyTexture <byte> sprite, int frameNumber, int width, int magnify, uint[] palette)
        {
            var frame  = sprite.Regions[frameNumber];
            var offset = frame.Y * sprite.Width;
            int height = Math.Min(frame.Height, (sprite.PixelData.Length - offset + (width - 1)) / width);

            if (height == 0)
            {
                return(new Bitmap(1, 1));
            }
            Bitmap bmp;

            if (canvas.Image?.Width == width * magnify && canvas.Image?.Height == height * magnify)
            {
                bmp = (Bitmap)canvas.Image;
            }
            else
            {
                bmp = new Bitmap(width * magnify, height * magnify);
            }

            var d = bmp.LockBits(
                new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.WriteOnly,
                PixelFormat.Format24bppRgb);

            try
            {
                for (int n = offset; n < offset + width * height && n < sprite.PixelData.Length; n++)
                {
                    unsafe
                    {
                        for (int my = 0; my < magnify; my++)
                        {
                            for (int mx = 0; mx < magnify; mx++)
                            {
                                int   x     = magnify * ((n - offset) % width) + mx;
                                int   y     = magnify * ((n - offset) / width) + my;
                                byte *p     = (byte *)d.Scan0 + y * d.Stride + x * 3;
                                byte  color = sprite.PixelData[n];

                                p[0] = (byte)((palette[color] & 0x00ff0000) >> 16);
                                p[1] = (byte)((palette[color] & 0x0000ff00) >> 8);
                                p[2] = (byte)(palette[color] & 0x000000ff);
                            }
                        }
                    }
                }
            }
            finally { bmp.UnlockBits(d); }

            return(bmp);
        }
Exemple #7
0
    static byte[] Write(IImageEncoder encoder, uint[] palette, IReadOnlyTexture <byte> existing, int frameNum)
    {
        var frame  = existing.Regions[frameNum];
        var buffer = new ReadOnlyImageBuffer <byte>(
            frame.Width,
            frame.Height,
            existing.Width,
            existing.PixelData.Slice(frame.PixelOffset, frame.PixelLength));

        Image <Rgba32> image = ImageSharpUtil.ToImageSharp(buffer, palette);
        var            bytes = FormatUtil.BytesFromStream(stream => encoder.Encode(image, stream));

        return(bytes);
    }
 public IReadOnlyTexture <byte> Serdes(IReadOnlyTexture <byte> existing, AssetInfo info, AssetMapping mapping, ISerializer s, IJsonUtil jsonUtil)
 {
     if (s == null)
     {
         throw new ArgumentNullException(nameof(s));
     }
     if (info == null)
     {
         throw new ArgumentNullException(nameof(info));
     }
     return(s.IsWriting()
         ? Write(existing, info, s)
         : Read(info, s));
 }
Exemple #9
0
        public CommonColors()
        {
            var texture = new ArrayTexture <byte>(
                AssetId.None,
                "CommonColors",
                1, 1, Palette.Count,
                Palette.OrderBy(x => x.Value).Select(x => (byte)x.Key).ToArray());

            foreach (var entry in Palette.OrderBy(x => x.Value))
            {
                texture.AddRegion(0, 0, 1, 1, (int)entry.Value);
            }

            BorderTexture = texture;
        }
Exemple #10
0
        public IReadOnlyTexture <byte> Serdes(IReadOnlyTexture <byte> existing, AssetInfo info, AssetMapping mapping, ISerializer s, IJsonUtil jsonUtil)
        {
            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }
            if (s == null)
            {
                throw new ArgumentNullException(nameof(s));
            }

            var paletteId = info.Get(AssetProperty.PaletteId, 0);
            var palette   = Resolve <IAssetManager>()
                            .LoadPalette(new PaletteId(AssetType.Palette, paletteId))
                            .GetUnambiguousPalette();

            if (info.AssetId.Type == AssetType.Font)
            {
                palette    = new uint[256];
                palette[1] = 0xffffffff;
                palette[2] = 0xffcccccc;
                palette[3] = 0xffaaaaaa;
                palette[4] = 0xff777777;
                palette[5] = 0xff555555;
            }

            if (s.IsWriting())
            {
                if (existing == null)
                {
                    throw new ArgumentNullException(nameof(existing));
                }
                var encoder = new PngEncoder();
                var bytes   = Write(encoder, palette, existing);
                s.Bytes(null, bytes, bytes.Length);
                return(existing);
            }
            else // Read
            {
                var decoder       = new PngDecoder();
                var configuration = new Configuration();
                var bytes         = s.Bytes(null, null, (int)s.BytesRemaining);
                using var stream = new MemoryStream(bytes);
                using var image  = decoder.Decode <Rgba32>(configuration, stream);
                return(Read(info.AssetId, palette, image, info.Width, info.Height));
            }
        }
    static void InnerWrite(IReadOnlyTexture <byte> sprite, ISerializer s)
    {
        var f         = sprite.Regions[0];
        int frameSize = f.Width * f.Height;

        byte[] pixelData = ArrayPool <byte> .Shared.Rent(frameSize);

        try
        {
            for (int i = 0; i < sprite.Regions.Count; i++)
            {
                BlitUtil.BlitDirect(
                    sprite.GetRegionBuffer(i),
                    new ImageBuffer <byte>(f.Width, f.Height, f.Width, pixelData));

                s.Bytes(null, pixelData, frameSize);
            }
        }
        finally { ArrayPool <byte> .Shared.Return(pixelData); }
    }
    static IReadOnlyTexture <byte> Write(IReadOnlyTexture <byte> existing, AssetInfo info, ISerializer s)
    {
        if (existing == null)
        {
            throw new ArgumentNullException(nameof(existing));
        }

        var f = existing.Regions[0];

        foreach (var frame in existing.Regions)
        {
            ApiUtil.Assert(f.Width == frame.Width, "FixedSizeSpriteLoader tried to serialise sprite with non-uniform frames");
            ApiUtil.Assert(f.Height == frame.Height, "FixedSizeSpriteLoader tried to serialise sprite with non-uniform frames");
        }

        var sprite = info.Get(AssetProperty.Transposed, false)
            ? Transpose(existing)
            : existing;

        InnerWrite(sprite, s);
        return(existing);
    }
    static IReadOnlyTexture <byte> Transpose(IReadOnlyTexture <byte> sprite)
    {
        var firstFrame  = sprite.Regions[0];
        int width       = firstFrame.Width;
        int height      = firstFrame.Height;
        int spriteCount = sprite.Regions.Count;

        int rotatedFrameHeight = width;

        byte[] pixelData = new byte[spriteCount * width * height];
        var    frames    = new Region[spriteCount];

        for (int i = 0; i < spriteCount; i++)
        {
            var oldFrame = sprite.Regions[i];
            frames[i] = new Region(0, rotatedFrameHeight * i, height, rotatedFrameHeight, height, width * spriteCount, 0);

            ApiUtil.TransposeImage(width, height, // TODO: This should really take stride via ImageBuffers etc
                                   sprite.PixelData.Slice(oldFrame.PixelOffset, oldFrame.PixelLength),
                                   pixelData.AsSpan(frames[i].PixelOffset, frames[i].PixelLength));
        }
        return(new SimpleTexture <byte>(sprite.Id, sprite.Name, height, width * spriteCount, pixelData, frames));
    }
Exemple #14
0
        public IReadOnlyTexture <byte> Serdes(IReadOnlyTexture <byte> existing, AssetInfo info, AssetMapping mapping, ISerializer s, IJsonUtil jsonUtil)
        {
            IReadOnlyTexture <byte> singleFrame = null;

            if (s.IsWriting())
            {
                if (existing == null)
                {
                    throw new ArgumentNullException(nameof(existing));
                }
                singleFrame =
                    new SimpleTexture <byte>(
                        existing.Id,
                        existing.Name,
                        existing.Width,
                        existing.Height,
                        existing.PixelData.ToArray())
                    .AddRegion(existing.Regions[0].X, existing.Regions[0].Y, existing.Regions[0].Width, existing.Regions[0].Height);
            }

            var sprite = new FixedSizeSpriteLoader().Serdes(singleFrame, info, mapping, s, jsonUtil);

            if (sprite == null)
            {
                return(null);
            }

            return(new SimpleTexture <byte>(
                       sprite.Id,
                       sprite.Name,
                       sprite.Width,
                       sprite.Height,
                       sprite.PixelData.ToArray())
                   .AddRegion(0, 0, sprite.Width, sprite.Height)
                   .AddRegion(0, sprite.Height - StatusBarHeight, sprite.Width, StatusBarHeight));
        }
Exemple #15
0
        void TrackWidth_ValueChanged(object sender, EventArgs e)
        {
            var asset = _core.SelectedObject;

            if (asset == null)
            {
                return;
            }

            if (!asset.File.Width.HasValue &&
                asset.File.Loader == FixedSizeSpriteLoader.TypeString &&
                asset.Width != trackWidth.Value)
            {
                asset.Width    = trackWidth.Value;
                _logicalSprite = null; // Force sprite reload
                _visualSprite  = null;
                Render();
            }

            if (sender != numWidth && (int)numWidth.Value != trackWidth.Value)
            {
                numWidth.Value = trackWidth.Value;
            }
        }
Exemple #16
0
        static byte[] Write(IImageEncoder encoder, uint[] palette, IReadOnlyTexture <byte> existing)
        {
            var image = ImageSharpUtil.PackSpriteSheet(palette, existing.Regions.Count, existing.GetRegionBuffer);

            return(FormatUtil.BytesFromStream(stream => encoder.Encode(image, stream)));
        }
Exemple #17
0
        public static unsafe Texture CreateSimpleTexture <T>(GraphicsDevice gd, TextureUsage usage, IReadOnlyTexture <T> texture) where T : unmanaged
        {
            if (gd == null)
            {
                throw new ArgumentNullException(nameof(gd));
            }
            if (texture == null)
            {
                throw new ArgumentNullException(nameof(texture));
            }

            var  pixelFormat = GetFormat(typeof(T));
            bool mip         = (usage & TextureUsage.GenerateMipmaps) != 0;
            uint mipLevels   = mip ? MipLevelCount(texture.Width, texture.Height) : 1;

            using Texture staging = gd.ResourceFactory.CreateTexture(new TextureDescription(
                                                                         (uint)texture.Width, (uint)texture.Height, 1,
                                                                         mipLevels,
                                                                         1,
                                                                         pixelFormat,
                                                                         TextureUsage.Staging,
                                                                         TextureType.Texture2D));

            staging.Name = "T_" + texture.Name + "_Staging";

            var buffer = texture.PixelData;

            fixed(T *texDataPtr = &buffer[0])
            {
                gd.UpdateTexture(
                    staging, (IntPtr)texDataPtr, (uint)(buffer.Length * Unsafe.SizeOf <T>()),
                    0, 0, 0,
                    (uint)texture.Width, (uint)texture.Height, 1,
                    0, 0);
            }

            Texture veldridTexture = gd.ResourceFactory.CreateTexture(new TextureDescription(
                                                                          (uint)texture.Width, (uint)texture.Height, 1,
                                                                          mipLevels,
                                                                          1,
                                                                          pixelFormat,
                                                                          usage,
                                                                          TextureType.Texture2D));

            veldridTexture.Name = "T_" + texture.Name;

            using CommandList cl = gd.ResourceFactory.CreateCommandList();
            cl.Begin();
            cl.CopyTexture(staging, veldridTexture);
            if (mip)
            {
                cl.GenerateMipmaps(veldridTexture);
            }
            cl.End();
            gd.SubmitCommands(cl);

            return(veldridTexture);
        }
Exemple #18
0
        public static unsafe Texture CreateArrayTexture <T>(GraphicsDevice gd, TextureUsage usage, IReadOnlyTexture <T> texture) where T : unmanaged
        {
            if (gd == null)
            {
                throw new ArgumentNullException(nameof(gd));
            }
            if (texture == null)
            {
                throw new ArgumentNullException(nameof(texture));
            }

            var  pixelFormat = GetFormat(typeof(T));
            bool mip         = (usage & TextureUsage.GenerateMipmaps) != 0;
            uint mipLevels   = mip ? MipLevelCount(texture.Width, texture.Height) : 1;

            using Texture staging = gd.ResourceFactory.CreateTexture(new TextureDescription(
                                                                         (uint)texture.Width, (uint)texture.Height, 1, mipLevels,
                                                                         (uint)texture.ArrayLayers,
                                                                         pixelFormat,
                                                                         TextureUsage.Staging,
                                                                         TextureType.Texture2D));

            staging.Name = "T_" + texture.Name + "_Staging";

            for (int layer = 0; layer < texture.ArrayLayers; layer++)
            {
                var mapped = gd.Map(staging, MapMode.Write, (uint)layer * mipLevels);
                try
                {
                    var span  = new Span <T>(mapped.Data.ToPointer(), (int)mapped.SizeInBytes / sizeof(T));
                    int pitch = (int)(mapped.RowPitch / sizeof(T));

                    var source = texture.GetLayerBuffer(layer);
                    var dest   = new ImageBuffer <T>(texture.Width, texture.Height, pitch, span);

                    BlitUtil.BlitDirect(source, dest);

                    //gd.UpdateTexture(
                    //    staging, (IntPtr) texDataPtr, (uint) (buffer.Buffer.Length * Unsafe.SizeOf<T>()),
                    //    0, 0, 0,
                    //    (uint) texture.Width, (uint) texture.Height, 1,
                    //    0, (uint) layer);
                }
                finally { gd.Unmap(staging, (uint)layer * mipLevels); }
            }

            Texture veldridTexture = gd.ResourceFactory.CreateTexture(new TextureDescription(
                                                                          (uint)texture.Width, (uint)texture.Height, 1,
                                                                          mipLevels,
                                                                          (uint)texture.ArrayLayers,
                                                                          pixelFormat,
                                                                          usage,
                                                                          TextureType.Texture2D));

            veldridTexture.Name = "T_" + texture.Name;

            using CommandList cl = gd.ResourceFactory.CreateCommandList();
            cl.Begin();
            cl.CopyTexture(staging, veldridTexture);
            if (mip)
            {
                cl.GenerateMipmaps(veldridTexture);
            }
            cl.End();
            gd.SubmitCommands(cl);

            return(veldridTexture);
        }
Exemple #19
0
        void Render()
        {
            var asset = _core.SelectedObject;

            if (asset == null)
            {
                return;
            }

            Bitmap bmp;

            if (IsSprite(asset.File))
            {
                // if (asset.File.Filename != _logicalSprite?.Name) // ??
                // {

                // Ugh
                bool isRotated = asset.File.Get(AssetProperty.Transposed, false);
                asset.File.Set <bool?>(AssetProperty.Transposed, null);
                _logicalSprite = LoadSprite(_core.GetRawPath(asset), asset);
                asset.File.Set <bool?>(AssetProperty.Transposed, isRotated);

                _visualSprite = isRotated ? LoadSprite(asset.File.Filename, asset) : _logicalSprite;
                // }

                if (_logicalSprite == null)
                {
                    return;
                }

                trackFrameCount.Maximum = _logicalSprite.Height;
                numFrameCount.Maximum   = trackFrameCount.Maximum;
                trackFrame.Maximum      = _logicalSprite.Regions.Count - 1;
                numFrame.Maximum        = trackFrame.Maximum;

                if (trackWidth.Value == 1)
                {
                    trackWidth.Value = _logicalSprite.Width;
                }

                var    palette    = (AlbionPalette)(chkListPalettes.SelectedItem ?? chkListPalettes.Items[0]);
                uint[] curPalette = palette.GetPaletteAtTime((int)((DateTime.Now - _startTime).TotalSeconds * 4));

                var width = _visualSprite.Width;
                var frame = Math.Max(0, trackFrame.Value);
                bmp = GenerateBitmap(_visualSprite, frame, width, Magnify, curPalette);
            }
            //else if (asset.Layer == FileFormat.Map2D)
            //{
            //    _logicalSprite = null;
            //    _visualSprite = null;
            //    bmp = new Bitmap(1, 1);
            //}
            else
            {
                _logicalSprite = null;
                _visualSprite  = null;
                bmp            = new Bitmap(1, 1);
            }

            canvas.Image = bmp;
        }