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; }
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); }