/// <summary> /// Lazily enumerate the images that will end up in the final file. /// Return fully painted bitmaps ready for saving in the output. /// In case of early cancellation or error, the caller must dispose the bitmap to avoid a leak. /// </summary> private IEnumerable <Bitmap> FrameEnumerator(SavingSettings settings) { // When we move to a full hierarchy of exporters classes, // each one will implement its own logic to transform the frames from // the working zone (or just the kf) to the final list of bitmaps to save. foreach (VideoFrame vf in videoReader.FrameEnumerator()) { if (vf == null) { log.Error("Working zone enumerator yield null."); yield break; } Bitmap bmp = vf.Image.CloneDeep(); long ts = vf.Timestamp; Graphics g = Graphics.FromImage(bmp); long keyframeDistance = settings.ImageRetriever(g, bmp, ts, settings.FlushDrawings, settings.KeyframesOnly); if (!settings.KeyframesOnly || keyframeDistance == 0) { int duplication = settings.PausedVideo && keyframeDistance == 0 ? settings.KeyframeDuplication : settings.Duplication; for (int i = 0; i < duplication; i++) { yield return(bmp); } } bmp.Dispose(); } }
/// <summary> /// Lazily enumerate the images that will end up in the final file. /// Return fully painted bitmaps ready for saving in the output. /// In case of early cancellation or error, the caller must dispose the bitmap to avoid a leak. /// </summary> private IEnumerable <Bitmap> EnumerateImages(SavingSettings settings) { Bitmap output = null; // Enumerates the raw frames from the video (at original video size). foreach (VideoFrame vf in videoReader.FrameEnumerator()) { if (vf == null) { log.Error("Working zone enumerator yield null."); if (output != null) { output.Dispose(); } yield break; } if (output == null) { output = new Bitmap(vf.Image.Width, vf.Image.Height, vf.Image.PixelFormat); } bool onKeyframe = settings.ImageRetriever(vf, output); bool savable = onKeyframe || !settings.KeyframesOnly; if (savable) { int duplication = settings.PausedVideo && onKeyframe ? settings.KeyframeDuplication : settings.Duplication; for (int i = 0; i < duplication; i++) { yield return(output); } } } if (output != null) { output.Dispose(); } }