Exemplo n.º 1
0
        private static async Task <ImageSource> GetLottieFrame(string path, int frame, int width, int height)
        {
            var dpi = WindowContext.Current.RasterizationScale;

            width  = (int)(width * dpi);
            height = (int)(height * dpi);

            var cache = $"{path}.{width}x{height}.png";

            if (System.IO.File.Exists(cache))
            {
                return(new BitmapImage(UriEx.ToLocal(cache)));
            }

            await Task.Run(() =>
            {
                var frameSize = new Windows.Graphics.SizeInt32 {
                    Width = width, Height = height
                };

                var animation = LottieAnimation.LoadFromFile(path, frameSize, false, null);
                if (animation != null)
                {
                    animation.RenderSync(cache, frame);
                    animation.Dispose();
                }
            });

            return(new BitmapImage(UriEx.ToLocal(cache)));
        }
Exemplo n.º 2
0
        public static ImageSource GetLottieFrame(string path, int frame, int width, int height, bool webp = true)
        {
            // Frame size affects disk cache, so we always use 256.
            var frameSize = new Windows.Graphics.SizeInt32 {
                Width = 256, Height = 256
            };

            var animation = LottieAnimation.LoadFromFile(path, frameSize, false, null);

            if (animation == null)
            {
                if (webp)
                {
                    return(GetWebPFrame(path, width));
                }

                return(null);
            }

            var bitmap = new WriteableBitmap(width, height);

            animation.RenderSync(bitmap, frame);
            animation.Dispose();

            return(bitmap);
        }
Exemplo n.º 3
0
        public static ImageSource GetLottieFrame(string path, int frame, int width, int height, bool webp = true)
        {
            var animation = LottieAnimation.LoadFromFile(path, false, null);

            if (animation == null)
            {
                if (webp)
                {
                    return(GetWebPFrame(path));
                }

                return(null);
            }

            var bitmap = new WriteableBitmap(width, height);

            animation.RenderSync(bitmap, frame);
            animation.Dispose();

            return(bitmap);
        }
Exemplo n.º 4
0
        private void OnSourceChanged(string newValue, string oldValue)
        {
            var canvas = _canvas;

            if (canvas == null)
            {
                return;
            }

            if (newValue == null)
            {
                //canvas.Paused = true;
                //canvas.ResetElapsedTime();
                Subscribe(false);

                Dispose();
                return;
            }

            if (string.Equals(newValue, oldValue, StringComparison.OrdinalIgnoreCase) ||
                string.Equals(newValue, _source, StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            var animation = LottieAnimation.LoadFromFile(newValue, _isCachingEnabled, ColorReplacements);

            if (animation == null)
            {
                // The app can't access the file specified
                return;
            }

            _source    = newValue;
            _animation = animation;

            _animationShouldCache = animation.ShouldCache;
            _animationFrameRate   = animation.FrameRate;
            _animationTotalFrame  = animation.TotalFrame;

            _index = _isCachingEnabled ? 0 : _animationTotalFrame - 1;

            //canvas.Paused = true;
            //canvas.ResetElapsedTime();
            //canvas.TargetElapsedTime = update > TimeSpan.Zero ? update : TimeSpan.MaxValue;

            if (AutoPlay || _shouldPlay)
            {
                _shouldPlay = false;
                Subscribe(true);
                //canvas.Paused = false;
            }
            else
            {
                Subscribe(false);

                // Invalidate to render the first frame
                Invalidate();
                _canvas.Invalidate();
            }
        }
Exemplo n.º 5
0
        private async void OnSourceChanged(string newValue, string oldValue)
        {
            var canvas = _canvas;

            if (canvas == null)
            {
                return;
            }

            if (newValue == null)
            {
                _source = null;
                Subscribe(false);
                return;
            }

            if (string.Equals(newValue, oldValue, StringComparison.OrdinalIgnoreCase) ||
                string.Equals(newValue, _source, StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            _source = newValue;

            var shouldPlay = _shouldPlay;

            var animation = await Task.Run(() => LottieAnimation.LoadFromFile(newValue, _isCachingEnabled, ColorReplacements));

            if (animation == null || !string.Equals(newValue, _source, StringComparison.OrdinalIgnoreCase))
            {
                // The app can't access the file specified
                return;
            }

            if (_shouldPlay)
            {
                shouldPlay = true;
            }

            _animation     = animation;
            _hideThumbnail = true;

            _animationFrameRate  = animation.FrameRate;
            _animationTotalFrame = animation.TotalFrame;

            if (_backward)
            {
                _index = _animationTotalFrame - 1;
            }
            else
            {
                _index = 0; //_isCachingEnabled ? 0 : _animationTotalFrame - 1;
            }

            //canvas.Paused = true;
            //canvas.ResetElapsedTime();
            //canvas.TargetElapsedTime = update > TimeSpan.Zero ? update : TimeSpan.MaxValue;

            if (AutoPlay || _shouldPlay)
            {
                _shouldPlay = false;
                Subscribe(true);
                //canvas.Paused = false;
            }
            else if (!_unloaded)
            {
                Subscribe(false);

                // Invalidate to render the first frame
                Invalidate();
                _canvas.Invalidate();
            }
        }
Exemplo n.º 6
0
        public async void SetValue(DiceStickers state, int newValue)
        {
            var canvas = _canvas;

            if (canvas == null)
            {
                _previous      = newValue;
                _previousState = state;
                return;
            }

            if (state == null)
            {
                //canvas.Paused = true;
                //canvas.ResetElapsedTime();
                Subscribe(false);

                Dispose();
                return;
            }

            if (newValue == _value)
            {
                return;
            }

            if (newValue != _value && /*newValue != _enqueued &&*/ _value == 0)
            {
                if (_subscribed)
                {
                    _shouldPlay    = true;
                    _enqueued      = newValue;
                    _enqueuedState = state;
                    return;
                }
            }

            var force = _enqueued == newValue;

            _value      = newValue;
            _valueState = state;

            _previous      = newValue;
            _previousState = state;

            _enqueued      = 0;
            _enqueuedState = null;

            var initial    = newValue == 0;
            var shouldPlay = _shouldPlay;

            var animations = new LottieAnimation[_parts];
            await Task.Run(() =>
            {
                if (state is DiceStickersSlotMachine slotMachine)
                {
                    animations[0] = _backAnimation ??= LottieAnimation.LoadFromFile(slotMachine.Background.StickerValue.Local.Path, false, null);
                    animations[1] = LottieAnimation.LoadFromData(MergeReels(slotMachine), $"{newValue}", false, null);
                    animations[2] = _frontAnimation ??= LottieAnimation.LoadFromFile(slotMachine.Lever.StickerValue.Local.Path, false, null);
                }
                else if (state is DiceStickersRegular regular)
                {
                    animations[1] = LottieAnimation.LoadFromFile(regular.Sticker.StickerValue.Local.Path, false, null);
                }
            });

            if (_shouldPlay)
            {
                shouldPlay = true;
            }

            _animations          = animations;
            _isLoopingEnabled[1] = initial;

            _animationFrameRate  = animations.Max(x => x?.FrameRate ?? 0);
            _animationTotalFrame = animations.Max(x => x?.TotalFrame ?? 0);

            _startIndex[0] = _animationTotalFrame;

            _index[0] = 1;
            _index[1] = IsContentUnread || initial ? 0 : animations[1].TotalFrame - 1;
            _index[2] = initial ? 0 : _index[2];

            //canvas.Paused = true;
            //canvas.ResetElapsedTime();
            //canvas.TargetElapsedTime = update > TimeSpan.Zero ? update : TimeSpan.MaxValue;

            if (AutoPlay || shouldPlay || force)
            {
                _shouldPlay = false;
                Subscribe(true);
                //canvas.Paused = false;
            }
            else
            {
                Subscribe(false);

                // Invalidate to render the first frame
                Invalidate();
                _canvas?.Invalidate();
            }
        }
Exemplo n.º 7
0
        private async Task ChatPhotoAsync(UpdateFileGenerationStart update, string[] args)
        {
            try
            {
                var conversion = JsonConvert.DeserializeObject <ChatPhotoConversion>(args[2]);

                var sticker = await _protoService.SendAsync(new GetFile(conversion.StickerFileId)) as Telegram.Td.Api.File;

                if (sticker == null || !sticker.Local.IsFileExisting())
                {
                    _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, "FILE_GENERATE_LOCATION_INVALID No sticker found")));
                    return;
                }

                Background background = null;

                var backgroundLink = await _protoService.SendAsync(new GetInternalLinkType(conversion.BackgroundUrl ?? string.Empty)) as InternalLinkTypeBackground;

                if (backgroundLink != null)
                {
                    background = await _protoService.SendAsync(new SearchBackground(backgroundLink.BackgroundName)) as Background;
                }
                else
                {
                    var freeform = new[] { 0xDBDDBB, 0x6BA587, 0xD5D88D, 0x88B884 };
                    background = new Background(0, true, false, string.Empty,
                                                new Document(string.Empty, "application/x-tgwallpattern", null, null, TdExtensions.GetLocalFile("Assets\\Background.tgv", "Background")),
                                                new BackgroundTypePattern(new BackgroundFillFreeformGradient(freeform), 50, false, false));
                }

                if (background == null || (background.Document != null && !background.Document.DocumentValue.Local.IsFileExisting()))
                {
                    _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, "FILE_GENERATE_LOCATION_INVALID No background found")));
                    return;
                }

                var device  = CanvasDevice.GetSharedDevice();
                var bitmaps = new List <CanvasBitmap>();

                var sfondo = new CanvasRenderTarget(device, 640, 640, 96, DirectXPixelFormat.B8G8R8A8UIntNormalized, CanvasAlphaMode.Premultiplied);

                using (var session = sfondo.CreateDrawingSession())
                {
                    if (background.Type is BackgroundTypePattern pattern)
                    {
                        if (pattern.Fill is BackgroundFillFreeformGradient freeform)
                        {
                            var colors    = freeform.GetColors();
                            var positions = new Vector2[]
                            {
                                new Vector2(0.80f, 0.10f),
                                new Vector2(0.35f, 0.25f),
                                new Vector2(0.20f, 0.90f),
                                new Vector2(0.65f, 0.75f),
                            };

                            using (var gradient = CanvasBitmap.CreateFromBytes(device, ChatBackgroundFreeform.GenerateGradientData(50, 50, colors, positions), 50, 50, DirectXPixelFormat.B8G8R8A8UIntNormalized))
                                using (var cache = await PlaceholderHelper.GetPatternBitmapAsync(device, null, background.Document.DocumentValue))
                                {
                                    using (var scale = new ScaleEffect {
                                        Source = gradient, BorderMode = EffectBorderMode.Hard, Scale = new Vector2(640f / 50f, 640f / 50f)
                                    })
                                        using (var colorize = new TintEffect {
                                            Source = cache, Color = Color.FromArgb(0x76, 00, 00, 00)
                                        })
                                            using (var tile = new BorderEffect {
                                                Source = colorize, ExtendX = CanvasEdgeBehavior.Wrap, ExtendY = CanvasEdgeBehavior.Wrap
                                            })
                                                using (var effect = new BlendEffect {
                                                    Foreground = tile, Background = scale, Mode = BlendEffectMode.Overlay
                                                })
                                                {
                                                    session.DrawImage(effect, new Rect(0, 0, 640, 640), new Rect(0, 0, 640, 640));
                                                }
                                }
                        }
                    }
                }

                bitmaps.Add(sfondo);

                var width  = (int)(512d * conversion.Scale);
                var height = (int)(512d * conversion.Scale);

                var animation = await Task.Run(() => LottieAnimation.LoadFromFile(sticker.Local.Path, new Windows.Graphics.SizeInt32 {
                    Width = width, Height = height
                }, false, null));

                if (animation == null)
                {
                    _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, "FILE_GENERATE_LOCATION_INVALID Can't load Lottie animation")));
                    return;
                }

                var composition = new MediaComposition();
                var layer       = new MediaOverlayLayer();

                var buffer = ArrayPool <byte> .Shared.Rent(width *height * 4);

                var framesPerUpdate = animation.FrameRate < 60 ? 1 : 2;
                var duration        = TimeSpan.Zero;

                for (int i = 0; i < animation.TotalFrame; i += framesPerUpdate)
                {
                    var bitmap = CanvasBitmap.CreateFromBytes(device, buffer, width, height, DirectXPixelFormat.B8G8R8A8UIntNormalized);
                    animation.RenderSync(bitmap, i);

                    var clip    = MediaClip.CreateFromSurface(bitmap, TimeSpan.FromMilliseconds(1000d / 30d));
                    var overlay = new MediaOverlay(clip, new Rect(320 - (width / 2d), 320 - (height / 2d), width, height), 1);

                    overlay.Delay = duration;

                    layer.Overlays.Add(overlay);
                    duration += clip.OriginalDuration;

                    bitmaps.Add(bitmap);
                }

                composition.OverlayLayers.Add(layer);
                composition.Clips.Add(MediaClip.CreateFromSurface(sfondo, duration));

                var temp = await _protoService.GetFileAsync(update.DestinationPath);

                var profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);
                profile.Audio                       = null;
                profile.Video.Bitrate               = 1800000;
                profile.Video.Width                 = 640;
                profile.Video.Height                = 640;
                profile.Video.FrameRate.Numerator   = 30;
                profile.Video.FrameRate.Denominator = 1;

                var progress = composition.RenderToFileAsync(temp, MediaTrimmingPreference.Precise, profile);
                progress.Progress = (result, delta) =>
                {
                    _protoService.Send(new SetFileGenerationProgress(update.GenerationId, 100, (int)delta));
                };

                var result = await progress;
                if (result == TranscodeFailureReason.None)
                {
                    _protoService.Send(new FinishFileGeneration(update.GenerationId, null));
                }
                else
                {
                    _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, result.ToString())));
                }

                ArrayPool <byte> .Shared.Return(buffer);

                foreach (var bitmap in bitmaps)
                {
                    bitmap.Dispose();
                }
            }
            catch (Exception ex)
            {
                _protoService.Send(new FinishFileGeneration(update.GenerationId, new Error(500, "FILE_GENERATE_LOCATION_INVALID " + ex.ToString())));
            }
        }