示例#1
0
    static void Blit8To32Transparent(ReadOnlyImageBuffer <byte> fromBuffer, ImageBuffer <uint> toBuffer, uint[] palette, byte componentAlpha, byte transparentColor)
    {
        var from       = fromBuffer.Buffer;
        var to         = toBuffer.Buffer;
        int fromOffset = 0;
        int toOffset   = 0;

        for (int j = 0; j < fromBuffer.Height; j++)
        {
            for (int i = 0; i < fromBuffer.Width; i++)
            {
                byte index = from[fromOffset];
                if (index != transparentColor)
                {
                    to[toOffset] = palette[index] & 0x00ffffff | ((uint)componentAlpha << 24);
                }

                fromOffset++;
                toOffset++;
            }

            fromOffset += fromBuffer.Stride - fromBuffer.Width;
            toOffset   += toBuffer.Stride - toBuffer.Width;
        }
    }
示例#2
0
    public static void UnpackSpriteSheet(
        uint[] palette,
        int frameWidth,
        int frameHeight,
        ReadOnlyImageBuffer <uint> source,
        ImageBuffer <byte> dest,
        Action <int, int, int, int> frameFunc)
    {
        if (dest.Width < source.Width)
        {
            throw new ArgumentOutOfRangeException(nameof(dest), "Tried to unpack to a smaller destination");
        }
        if (dest.Height < source.Height)
        {
            throw new ArgumentOutOfRangeException(nameof(dest), "Tried to unpack to a smaller destination");
        }

        Blit32To8(source, dest, palette);

        int x = 0; int y = 0;

        do
        {
            frameFunc(x, y, frameWidth, frameHeight);
            x += frameWidth;
            if (x + frameWidth > source.Width)
            {
                y += frameHeight;
                x  = 0;
            }
        } while (y + frameHeight <= source.Height);
    }
示例#3
0
    static IReadOnlyTexture <byte> Read(AssetId id, uint[] palette, IList <Image <Rgba32> > images)
    {
        int totalWidth    = images.Max(x => x.Width);
        int totalHeight   = images.Sum(x => x.Height);
        var pixels        = new byte[totalWidth * totalHeight];
        var frames        = new List <Region>();
        int currentY      = 0;
        var quantizeCache = new Dictionary <uint, byte>();

        for (int i = 0; i < images.Count; i++)
        {
            Image <Rgba32> image = images[i];
            if (!image.TryGetSinglePixelSpan(out Span <Rgba32> rgbaSpan))
            {
                throw new InvalidOperationException("Could not retrieve single span from Image");
            }

            frames.Add(new Region(0, currentY, image.Width, image.Height, totalWidth, totalHeight, 0));
            var uintSpan = MemoryMarshal.Cast <Rgba32, uint>(rgbaSpan);
            var from     = new ReadOnlyImageBuffer <uint>(image.Width, image.Height, image.Width, uintSpan);
            var byteSpan = pixels.AsSpan(currentY * totalWidth, totalWidth * (image.Height - 1) + image.Width);
            var to       = new ImageBuffer <byte>(image.Width, image.Height, totalWidth, byteSpan);
            BlitUtil.Blit32To8(from, to, palette, quantizeCache);

            currentY += image.Height;
        }

        return(new SimpleTexture <byte>(id, id.ToString(), totalWidth, totalHeight, pixels, frames));
    }
示例#4
0
    public static void BlitMasked <T>(ReadOnlyImageBuffer <T> fromBuffer, ImageBuffer <T> toBuffer, Func <T, bool> opacityFunc) where T : unmanaged
    {
        var from       = fromBuffer.Buffer;
        var to         = toBuffer.Buffer;
        int fromOffset = 0;
        int toOffset   = 0;

        for (int j = 0; j < fromBuffer.Height; j++)
        {
            for (int i = 0; i < fromBuffer.Width; i++)
            {
                var pixel = from[fromOffset];
                if (opacityFunc(pixel))
                {
                    to[toOffset] = pixel;
                }

                fromOffset++;
                toOffset++;
            }

            fromOffset += fromBuffer.Stride - fromBuffer.Width;
            toOffset   += toBuffer.Stride - toBuffer.Width;
        }
    }
示例#5
0
    public static void Blit32To8(ReadOnlyImageBuffer <uint> fromBuffer, ImageBuffer <byte> toBuffer, uint[] palette, Dictionary <uint, byte> quantizeCache = null)
    {
        quantizeCache ??= new Dictionary <uint, byte>();
        var from       = fromBuffer.Buffer;
        var to         = toBuffer.Buffer;
        int fromOffset = 0;
        int toOffset   = 0;

        for (int j = 0; j < fromBuffer.Height; j++)
        {
            for (int i = 0; i < fromBuffer.Width; i++)
            {
                uint pixel = from[fromOffset];
                if (!quantizeCache.TryGetValue(pixel, out var index))
                {
                    index = Quantize(pixel, palette);
                    quantizeCache[pixel] = index;
                }

                to[toOffset] = index;

                fromOffset++;
                toOffset++;
            }

            fromOffset += fromBuffer.Stride - fromBuffer.Width;
            toOffset   += toBuffer.Stride - toBuffer.Width;
        }
    }
示例#6
0
 public ReadOnlyImageBuffer(ReadOnlyImageBuffer <T> existing, ReadOnlySpan <T> buffer)
 {
     Width  = existing.Width;
     Height = existing.Height;
     Stride = existing.Stride;
     Buffer = buffer;
 }
示例#7
0
 public static void BlitDirect <T>(ReadOnlyImageBuffer <T> fromBuffer, ImageBuffer <T> toBuffer) where T : unmanaged
 {
     for (int j = 0; j < fromBuffer.Height; j++)
     {
         var fromSlice = fromBuffer.Buffer.Slice(j * fromBuffer.Stride, fromBuffer.Width);
         var toSlice   = toBuffer.Buffer.Slice(j * toBuffer.Stride, toBuffer.Width);
         fromSlice.CopyTo(toSlice);
     }
 }
示例#8
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);
    }
示例#9
0
        public static Image <Rgba32> ToImageSharp(ReadOnlyImageBuffer <uint> from)
        {
            Image <Rgba32> image = new Image <Rgba32>(from.Width, from.Height);

            if (!image.TryGetSinglePixelSpan(out var rgbaSpan))
            {
                throw new InvalidOperationException("Could not retrieve single span from Image");
            }

            Span <uint> toBuffer = MemoryMarshal.Cast <Rgba32, uint>(rgbaSpan);
            var         to       = new ImageBuffer <uint>(from.Width, from.Height, from.Width, toBuffer);

            BlitUtil.BlitDirect(from, to);
            return(image);
        }
示例#10
0
    public static void BlitTiled8To32(ReadOnlyImageBuffer <byte> from, ImageBuffer <uint> to, uint[] palette, byte componentAlpha, byte?transparentColor)
    {
        if (palette == null)
        {
            throw new ArgumentNullException(nameof(palette));
        }
        int         remainingWidth  = to.Width;
        int         remainingHeight = to.Height;
        Span <uint> dest            = to.Buffer;

        int chunkHeight = Math.Min(from.Height, to.Height);

        do
        {
            Span <uint> rowStart = dest;
            chunkHeight = Math.Min(chunkHeight, remainingHeight);
            int chunkWidth = Math.Min(from.Width, to.Width);
            do
            {
                chunkWidth = Math.Min(chunkWidth, remainingWidth);
                var newFrom = new ReadOnlyImageBuffer <byte>(chunkWidth, chunkHeight, from.Stride, from.Buffer);
                var newTo   = new ImageBuffer <uint>(chunkWidth, chunkHeight, to.Stride, dest);

                if (transparentColor.HasValue)
                {
                    Blit8To32Transparent(newFrom, newTo, palette, componentAlpha, transparentColor.Value);
                }
                else
                {
                    Blit8To32Opaque(newFrom, newTo, palette, componentAlpha);
                }

                dest            = dest.Slice(chunkWidth);
                remainingWidth -= chunkWidth;
            } while (remainingWidth > 0);

            remainingHeight -= chunkHeight;
            remainingWidth   = to.Width;
            if (remainingHeight > 0)
            {
                dest = rowStart.Slice(chunkHeight * to.Stride);
            }
        } while (remainingHeight > 0);
    }
示例#11
0
    /*
     * public static void Blit8(ReadOnlySpan<byte> from, Span<byte> to, int width, int height, int fromStride, int toStride)
     * {
     *  int srcIndex = 0;
     *  int destIndex = 0;
     *  for (int i = 0; i < height; i++)
     *  {
     *      var row = from.Slice(srcIndex, width);
     *      row.CopyTo(to.Slice(destIndex));
     *      srcIndex += fromStride;
     *      destIndex += toStride;
     *  }
     * } */


    public static ISet <T> DistinctColors <T>(ReadOnlyImageBuffer <T> buffer) where T : unmanaged
    {
        int c      = 0;
        var active = new HashSet <T>();

        while (c < buffer.Buffer.Length)
        {
            int end = c + buffer.Width;
            while (c < end)
            {
                active.Add(buffer.Buffer[c]);
                c++;
            }

            c += buffer.Stride - buffer.Width;
        }

        return(active);
    }
        public object Process(object asset, AssetInfo info)
        {
            if (asset == null)
            {
                throw new ArgumentNullException(nameof(asset));
            }
            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }

            var bitmap  = (InterlacedBitmap)asset;
            var texture =
                new SimpleTexture <uint>(info.AssetId, bitmap.Width, bitmap.Height)
                .AddRegion(0, 0, bitmap.Width, bitmap.Height);

            var imageBuffer = new ReadOnlyImageBuffer <byte>(bitmap.Width, bitmap.Height, bitmap.Width, bitmap.ImageData);

            BlitUtil.BlitTiled8To32(imageBuffer, texture.GetMutableRegionBuffer(0), bitmap.Palette, 255, null);
            return(texture);
        }
示例#13
0
    public static void BlitTiled <T>(ReadOnlyImageBuffer <T> from, ImageBuffer <T> to, Func <T, bool> opacityFunc = null) where T : unmanaged
    {
        int      remainingWidth  = to.Width;
        int      remainingHeight = to.Height;
        Span <T> dest            = to.Buffer;

        int chunkHeight = Math.Min(from.Height, to.Height);

        do
        {
            Span <T> rowStart = dest;
            chunkHeight = Math.Min(chunkHeight, remainingHeight);
            int chunkWidth = Math.Min(from.Width, to.Width);
            do
            {
                chunkWidth = Math.Min(chunkWidth, remainingWidth);
                var newFrom = new ReadOnlyImageBuffer <T>(chunkWidth, chunkHeight, from.Stride, from.Buffer);
                var newTo   = new ImageBuffer <T>(chunkWidth, chunkHeight, to.Stride, dest);

                if (opacityFunc == null)
                {
                    BlitDirect(newFrom, newTo);
                }
                else
                {
                    BlitMasked(newFrom, newTo, opacityFunc);
                }

                dest            = dest.Slice(chunkWidth);
                remainingWidth -= chunkWidth;
            } while (remainingWidth > 0);

            remainingHeight -= chunkHeight;
            remainingWidth   = to.Width;
            if (remainingHeight > 0)
            {
                dest = rowStart.Slice(chunkHeight * to.Stride);
            }
        } while (remainingHeight > 0);
    }
示例#14
0
        static IReadOnlyTexture <byte> Read(AssetId id, uint[] palette, Image <Rgba32> image, int subItemWidth, int subItemHeight)
        {
            var pixels = new byte[image.Width * image.Height];
            var frames = new List <Region>();

            if (!image.TryGetSinglePixelSpan(out Span <Rgba32> rgbaSpan))
            {
                throw new InvalidOperationException("Could not retrieve single span from Image");
            }

            var uintSpan = MemoryMarshal.Cast <Rgba32, uint>(rgbaSpan);
            var source   = new ReadOnlyImageBuffer <uint>(image.Width, image.Height, image.Width, uintSpan);
            var dest     = new ImageBuffer <byte>(image.Width, image.Height, image.Width, pixels);

            BlitUtil.UnpackSpriteSheet(palette, subItemWidth, subItemHeight, source, dest,
                                       (x, y, w, h) => frames.Add(new Region(x, y, w, h, image.Width, image.Height, 0)));

            while (IsFrameEmpty(frames.Last(), pixels, image.Width))
            {
                frames.RemoveAt(frames.Count - 1);
            }

            return(new SimpleTexture <byte>(id, id.ToString(), image.Width, image.Height, pixels, frames));
        }
示例#15
0
 public static void BlitTiled32(ReadOnlyImageBuffer <uint> from, ImageBuffer <uint> to) => BlitTiled(from, to, OpacityFunc32);
示例#16
0
 public static void BlitTiled8(ReadOnlyImageBuffer <byte> from, ImageBuffer <byte> to) => BlitTiled(from, to, OpacityFunc8);