예제 #1
0
        private void writeFrame(BufferFrame src)
        {
            using var quant = new OctreeQuantizer();
            using var buffI = new FrameBufferSource(ctx.Source.Width, ctx.Source.Height, PixelFormat.Indexed8Bpp);
            var buffC = EncodeFrame.Source;

            quant.CreateHistorgram(buffC.Span, buffC.Width, buffC.Height, buffC.Stride);
            quant.Quantize(buffC.Span, buffI.Span, buffC.Width, buffC.Height, buffC.Stride, buffI.Stride);
            var palette = quant.Palette;

            using var pal = default(ComPtr <IWICPalette>);
            HRESULT.Check(Wic.Factory->CreatePalette(pal.GetAddressOf()));

            fixed(uint *ppal = palette)
            HRESULT.Check(pal.Get()->InitializeCustom(ppal, (uint)palette.Length));

            ctx.WicContext.DestPalette = pal;
            ctx.Source = buffI;

            using var frm     = new WicImageEncoderFrame(ctx, encoder, src.Area);
            using var frmmeta = default(ComPtr <IWICMetadataQueryWriter>);
            HRESULT.Check(frm.WicEncoderFrame->GetMetadataQueryWriter(frmmeta.GetAddressOf()));

            frmmeta.SetValue(Wic.Metadata.Gif.FrameDisposal, (byte)src.Disposal);
            frmmeta.SetValue(Wic.Metadata.Gif.FrameDelay, (ushort)src.Delay);

            if (src.Area.X != 0)
            {
                frmmeta.SetValue(Wic.Metadata.Gif.FrameLeft, (ushort)src.Area.X);
            }
            if (src.Area.Y != 0)
            {
                frmmeta.SetValue(Wic.Metadata.Gif.FrameTop, (ushort)src.Area.Y);
            }

            frmmeta.SetValue(Wic.Metadata.Gif.TransparencyFlag, true);
            frmmeta.SetValue(Wic.Metadata.Gif.TransparentColorIndex, (byte)(palette.Length - 1));

            frm.WriteSource(ctx, src.Area);

            ctx.WicContext.DestPalette = null;
        }
예제 #2
0
        private void writeFrame(BufferFrame src)
        {
            var  curFormat = ctx.Source.Format;
            var  newFormat = PixelFormat.Indexed8Bpp;
            bool alpha     = src.Trans || src.Disposal != GifDisposalMethod.RestoreBackground;

            using var pal = ComHandle.Wrap(Wic.Factory.CreatePalette());
            pal.ComObject.InitializeFromBitmap(wicSource, 256u, alpha);
            ctx.WicContext.DestPalette = pal.ComObject;

            using var conv = ComHandle.Wrap(Wic.Factory.CreateFormatConverter());
            conv.ComObject.Initialize(wicSource, newFormat.FormatGuid, WICBitmapDitherType.WICBitmapDitherTypeErrorDiffusion, pal.ComObject, 25.0, WICBitmapPaletteType.WICBitmapPaletteTypeCustom);
            ctx.Source = conv.ComObject.AsPixelSource($"{nameof(IWICFormatConverter)}: {curFormat.Name}->{newFormat.Name}", false);

            using var frm = new WicImageEncoderFrame(ctx, encoder, src.Area);

            using var frmmeta = ComHandle.Wrap(frm.WicEncoderFrame.GetMetadataQueryWriter());
            var fm = frmmeta.ComObject;

            fm.SetMetadataByName(Wic.Metadata.Gif.FrameDisposal, new PropVariant((byte)src.Disposal));
            fm.SetMetadataByName(Wic.Metadata.Gif.FrameDelay, new PropVariant((ushort)src.Delay));

            if (src.Area.X != 0)
            {
                fm.SetMetadataByName(Wic.Metadata.Gif.FrameLeft, new PropVariant((ushort)src.Area.X));
            }
            if (src.Area.Y != 0)
            {
                fm.SetMetadataByName(Wic.Metadata.Gif.FrameTop, new PropVariant((ushort)src.Area.Y));
            }

            if (alpha)
            {
                fm.SetMetadataByName(Wic.Metadata.Gif.TransparencyFlag, new PropVariant(true));
                fm.SetMetadataByName(Wic.Metadata.Gif.TransparentColorIndex, new PropVariant((byte)(pal.ComObject.GetColorCount() - 1)));
            }

            frm.WriteSource(ctx, src.Area);
        }