Пример #1
0
    private ConsoleBitmapDiffFrame PrepareDiffFrame(ConsoleBitmapRawFrame previous, ConsoleBitmap bitmap)
    {
        ConsoleBitmapDiffFrame diff = new ConsoleBitmapDiffFrame();

        diff.Diffs = new List <ConsoleBitmapPixelDiff>();
        int changes = 0;

        for (int y = 0; y < GetEffectiveHeight(bitmap); y++)
        {
            for (int x = 0; x < GetEffectiveWidth(bitmap); x++)
            {
                var pixel            = bitmap.GetPixel(GetEffectiveLeft + x, GetEffectiveTop + y);
                var hasPreviousPixel = previous.Pixels.Length == GetEffectiveWidth(bitmap) && previous.Pixels[0].Length == GetEffectiveHeight(bitmap);
                var previousPixel    = hasPreviousPixel ? previous.Pixels[x][y] : default(ConsoleCharacter);

                if (hasPreviousPixel == false || (pixel.EqualsIn(previousPixel) == false))
                {
                    changes++;
                    diff.Diffs.Add(new ConsoleBitmapPixelDiff()
                    {
                        X     = x,
                        Y     = y,
                        Value = pixel
                    });
                }
            }
        }

        return(diff);
    }
Пример #2
0
    private ConsoleBitmapRawFrame GetRawFrame(ConsoleBitmap bitmap)
    {
        var rawFrame = new ConsoleBitmapRawFrame();

        rawFrame.Pixels = new ConsoleCharacter[GetEffectiveWidth(bitmap)][];
        for (int x = 0; x < GetEffectiveWidth(bitmap); x++)
        {
            rawFrame.Pixels[x] = new ConsoleCharacter[GetEffectiveHeight(bitmap)];
            for (int y = 0; y < GetEffectiveHeight(bitmap); y++)
            {
                var pixel = bitmap.GetPixel(GetEffectiveLeft + x, GetEffectiveTop + y);
                rawFrame.Pixels[x][y] = pixel;
            }
        }
        return(rawFrame);
    }
Пример #3
0
    /// <summary>
    /// Writes the given bitmap image as a frame to the stream.  If this is the first image or more than half of the pixels have
    /// changed then a raw frame will be written.   Otherwise, a diff frame will be written.
    ///
    /// This method uses the system's wall clock to determine the timestamp for this frame. The timestamp will be
    /// relative to the wall clock time when the first frame was written.
    /// </summary>
    /// <param name="bitmap">the image to write</param>
    /// <param name="desiredFrameTime">if provided, sstamp the frame with this time, otherwise stamp it with the wall clock delta from the first frame time</param>
    /// <param name="force">if true, writes the frame even if there are no changes</param>
    /// <returns>the same bitmap that was passed in</returns>
    public ConsoleBitmap WriteFrame(ConsoleBitmap bitmap, bool force = false, TimeSpan?desiredFrameTime = null)
    {
        if (isFinished)
        {
            throw new NotSupportedException("Already finished");
        }



        if (pausedAt.HasValue)
        {
            return(bitmap);
        }

        var rawFrame = GetRawFrame(bitmap);

        var now = DateTime.UtcNow - TotalPauseTime;

        if (firstFrameTime.HasValue == false)
        {
            rawFrame.Timestamp = TimeSpan.Zero;
            firstFrameTime     = now;
        }
        else
        {
            rawFrame.Timestamp = desiredFrameTime.HasValue ? desiredFrameTime.Value : now - firstFrameTime.Value;
        }

        if (lastFrame == null)
        {
            StreamHeader(bitmap);
            Append(serializer.SerializeFrame(rawFrame));
            FramesWritten++;
        }
        else
        {
            if (GetEffectiveWidth(bitmap) != lastFrame.Pixels.Length || GetEffectiveHeight(bitmap) != lastFrame.Pixels[0].Length)
            {
                throw new InvalidOperationException("Video frame has changed size");
            }

            var diff = PrepareDiffFrame(lastFrame, bitmap);
            diff.Timestamp = rawFrame.Timestamp;

            var numPixels = GetEffectiveWidth(bitmap) * GetEffectiveHeight(bitmap);
            if (force || diff.Diffs.Count > numPixels / 2)
            {
                var frame = serializer.SerializeFrame(rawFrame);
                //checking to make sure we can deserialize what we just wrote so that if we can't
                // we still have time to debug. I'd love to get rid of this check for perf, but
                // there have been some cases where I wasn't able to read back what was written and if
                // that edge case creeps up I want to catch it early.
                var deserialized = serializer.DeserializeFrame(frame, bitmap.Width, bitmap.Height);
                var frameBack    = serializer.SerializeFrame((ConsoleBitmapRawFrame)deserialized);
                if (frameBack.Equals(frame) == false)
                {
                    throw new Exception("Serialization failure");
                }
                if (frame.EndsWith("\n") == false)
                {
                    throw new Exception();
                }
                Append(frame);
                FramesWritten++;
            }
            else if (diff.Diffs.Count > 0)
            {
                Append(serializer.SerializeFrame(diff));
                FramesWritten++;
            }
        }

        lastFrame = rawFrame;
        return(bitmap);
    }