public override SKQuantizedFrame Quantize(ReadOnlySpan <SKColor> colors) { var pixels = new byte[3 * colors.Length]; for (int i = 0, k = 0; i < colors.Length; i++) { var c = colors[i]; pixels[k++] = c.Red; pixels[k++] = c.Green; pixels[k++] = c.Blue; } int len = pixels.Length; int nPix = len / 3; neuQuant = new NeuQuant(len, SamplingFactor); var palette = neuQuant.Process(pixels); var frame = new SKQuantizedFrame(); frame.ColorDepth = 8; frame.PaletteSize = 7; frame.IndexedPixels = new byte[nPix]; frame.Palette = palette; for (int i = 0, k = 0; i < nPix; i++) { int index = neuQuant.Map( pixels[k++] & 0xff, pixels[k++] & 0xff, pixels[k++] & 0xff); frame.IndexedPixels[i] = (byte)index; } return(frame); }
private void WriteImageDescriptor(SKQuantizedFrame quantizedFrame) { // image separator stream.WriteByte(0x2c); // x, y, w, h WriteShort(0); WriteShort(0); WriteShort(frameSize.Width); WriteShort(frameSize.Height); // packed fields if (firstFrame) { // no LCT - GCT is used for first (or only) frame stream.WriteByte(0); } else { // specify normal LCT stream.WriteByte(Convert.ToByte( 0x80 | // 1 local color table 1=yes 0 | // 2 interlace - 0=no 0 | // 3 sorted - 0=no 0 | // 4-5 reserved quantizedFrame.PaletteSize)); // 6-8 size of color table } }
private void WritePalette(SKQuantizedFrame quantizedFrame) { stream.Write(quantizedFrame.Palette, 0, quantizedFrame.Palette.Length); var n = (3 * 256) - quantizedFrame.Palette.Length; for (var i = 0; i < n; i++) { stream.WriteByte(0); } }
private void WriteLogicalScreenDescriptor(SKQuantizedFrame quantizedFrame) { // logical screen size WriteShort(frameSize.Width); WriteShort(frameSize.Height); // packed fields stream.WriteByte(Convert.ToByte( 0x80 | // 1 : global color table flag = 1 (gct used) 0x70 | // 2-4 : color resolution = 7 0x00 | // 5 : gct sort flag = 0 quantizedFrame.PaletteSize)); // 6-8 : gct size stream.WriteByte(0); // background color index stream.WriteByte(0); // pixel aspect ratio - assume 1:1 }
// Write* private void WriteGraphicControlExtension(SKQuantizedFrame quantizedFrame, SKGifEncoderFrameInfo frameInfo) { stream.WriteByte(0x21); // extension introducer stream.WriteByte(0xf9); // GCE label stream.WriteByte(4); // data block size int transp, disp; if (frameInfo.TransparentColor != SKColor.Empty) { transp = 1; disp = 2; } else { transp = 0; disp = 0; } if (frameInfo.DisposalMethod >= 0) { disp = ((int)frameInfo.DisposalMethod) & 7; // user override } disp <<= 2; // packed fields stream.WriteByte(Convert.ToByte( 0 | // 1:3 reserved disp | // 4:6 disposal 0 | // 7 user input - 0 = none transp)); // 8 transparency flag WriteShort(frameInfo.Duration / 10); // delay x 1/100 sec // transparent color index if (frameInfo.TransparentColor != SKColor.Empty) { stream.WriteByte(quantizer.GetColorIndex(frameInfo.TransparentColor)); } else { stream.WriteByte(0); } stream.WriteByte(0); // block terminator }
private void WritePixels(SKQuantizedFrame quantizedFrame) { encoder.Encode(stream, quantizedFrame); }