internal GifskiError AddFrame(IntPtr handle, uint index, string path, int delay, double lastTimestamp = 0, bool isLast = false) { if (Version.Major == 0 && Version.Minor < 9) { return(_addPngFrame(handle, index, path, (ushort)(delay / 10))); } //var aa = new FormatConvertedBitmap(path.SourceFrom(), PixelFormats.Rgb24, null, 0); var util = new PixelUtil(new FormatConvertedBitmap(path.SourceFrom(), PixelFormats.Rgb24, null, 0)); util.LockBitsAndUnpad(); var bytesPerRow = util.Width * 3; //Was ((util.Width * 24 + 31) / 32) * 3 //if (bytesPerRow % 4 != 0) // bytesPerRow += (4 - (bytesPerRow % 4)); //Pin the buffer in order to pass the address as parameter later. var pinnedBuffer = GCHandle.Alloc(util.Pixels, GCHandleType.Pinned); var address = pinnedBuffer.AddrOfPinnedObject(); GifskiError result; if (Version > new Version(0, 10, 4)) { //First frame receives the delay set of the last frame. result = AddFrame2Pixels(handle, index, (uint)util.Width, (uint)bytesPerRow, (uint)util.Height, address, index == 0 ? lastTimestamp : _timeStamp); _timeStamp += (delay / 1000d); } else if (Version.Major == 0 && Version.Minor >= 10) { result = AddFrame2Pixels(handle, index, (uint)util.Width, (uint)bytesPerRow, (uint)util.Height, address, _timeStamp); //As a dirty fix for Gifski 0.10.2, the last frame must be duplicated to preserve the timings. if (isLast) { _timeStamp += ((delay / 1000d) / 2d); result = AddFrame2Pixels(handle, index + 1, (uint)util.Width, (uint)bytesPerRow, (uint)util.Height, address, _timeStamp); } //Frames can't be more than 1 second apart. TODO: Add support for dealing with this issue. _timeStamp += (delay / 1000d); } else { //Normal delay. result = AddFramePixels(handle, index, (uint)util.Width, (uint)bytesPerRow, (uint)util.Height, address, (ushort)delay); } //The buffer must be unpinned, to free resources. pinnedBuffer.Free(); util.UnlockBitsWithoutCommit(); return(result); }