private BitmapEditState CopyBitmapEditState(BitmapEditState original)
 {
     return(new BitmapEditState()
     {
         Flip = original.Flip, Proportions = original.Proportions, Rectangle = original.Rectangle, Rotation = original.Rotation, Strokes = original.Strokes
     });
 }
Beispiel #2
0
        public static async Task <ImageSource> CropAndPreviewAsync(IRandomAccessStream imageStream, BitmapEditState editState)
        {
            var decoder = await BitmapDecoder.CreateAsync(imageStream);

            var cropWidth  = (double)decoder.PixelWidth;
            var cropHeight = (double)decoder.PixelHeight;

            if (decoder.PixelWidth > 1280 || decoder.PixelHeight > 1280)
            {
                double ratioX = 1280d / cropWidth;
                double ratioY = 1280d / cropHeight;
                double ratio  = Math.Min(ratioX, ratioY);

                cropWidth  *= ratio;
                cropHeight *= ratio;
            }

            var cropRectangle = new Rect(
                editState.Rectangle.X * decoder.PixelWidth,
                editState.Rectangle.Y * decoder.PixelHeight,
                editState.Rectangle.Width * decoder.PixelWidth,
                editState.Rectangle.Height * decoder.PixelHeight);

            if (editState.Rotation != BitmapRotation.None)
            {
                cropRectangle = RotateArea(cropRectangle, decoder.PixelWidth, decoder.PixelHeight, (int)editState.Rotation);
            }

            if (editState.Flip == BitmapFlip.Horizontal)
            {
                cropRectangle = FlipArea(cropRectangle, decoder.PixelWidth);
            }

            var(scaledCrop, scaledSize) = Scale(cropRectangle, new Size(decoder.PixelWidth, decoder.PixelHeight), new Size(cropWidth, cropHeight), 1280, 0);

            var bounds = new BitmapBounds();

            bounds.X      = (uint)scaledCrop.X;
            bounds.Y      = (uint)scaledCrop.Y;
            bounds.Width  = (uint)scaledCrop.Width;
            bounds.Height = (uint)scaledCrop.Height;

            var transform = new BitmapTransform();

            transform.ScaledWidth       = (uint)scaledSize.Width;
            transform.ScaledHeight      = (uint)scaledSize.Height;
            transform.Bounds            = bounds;
            transform.InterpolationMode = BitmapInterpolationMode.Linear;
            transform.Rotation          = editState.Rotation;
            transform.Flip = editState.Flip;

            var pixelData = await decoder.GetSoftwareBitmapAsync(decoder.BitmapPixelFormat, BitmapAlphaMode.Premultiplied, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.DoNotColorManage);

            if (editState.Strokes != null)
            {
                var stream = await DrawStrokesAsync(pixelData, editState.Strokes, editState.Rectangle, editState.Rotation, editState.Flip);

                var bitmapImage = new BitmapImage();
                await bitmapImage.SetSourceAsync(stream);

                return(bitmapImage);
            }
            else
            {
                var bitmapImage = new SoftwareBitmapSource();
                await bitmapImage.SetBitmapAsync(pixelData);

                return(bitmapImage);
            }
        }
Beispiel #3
0
        public static async Task <ImageSource> CropAndPreviewAsync(StorageFile sourceFile, BitmapEditState editState)
        {
            if (sourceFile.ContentType.Equals("video/mp4"))
            {
                var props = await sourceFile.Properties.GetVideoPropertiesAsync();

                var composition = new MediaComposition();
                var clip        = await MediaClip.CreateFromFileAsync(sourceFile);

                composition.Clips.Add(clip);

                using (var imageStream = await composition.GetThumbnailAsync(TimeSpan.Zero, (int)props.GetWidth(), (int)props.GetHeight(), VideoFramePrecision.NearestKeyFrame))
                {
                    return(await CropAndPreviewAsync(imageStream, editState));
                }
            }

            using (var imageStream = await sourceFile.OpenReadAsync())
            {
                return(await CropAndPreviewAsync(imageStream, editState));
            }
        }
Beispiel #4
0
        public static async Task <(int Width, int Height)> GetScaleAsync(StorageFile file, int requestedMinSide = 1280, BitmapEditState editState = null)
        {
            var props = await file.Properties.GetImagePropertiesAsync();

            var width  = props.Width;
            var height = props.Height;

            if (editState?.Rectangle is Rect crop)
            {
                width  = (uint)(crop.Width * props.Width);
                height = (uint)(crop.Height * props.Height);
            }

            if (width > requestedMinSide || height > requestedMinSide)
            {
                double ratioX = (double)requestedMinSide / width;
                double ratioY = (double)requestedMinSide / height;
                double ratio  = Math.Min(ratioX, ratioY);

                if (editState != null && editState.Rotation is BitmapRotation.Clockwise90Degrees or BitmapRotation.Clockwise270Degrees)
                {
                    return((int)(height * ratio), (int)(width * ratio));
                }

                return((int)(width * ratio), (int)(height * ratio));
            }

            if (editState != null && editState.Rotation is BitmapRotation.Clockwise90Degrees or BitmapRotation.Clockwise270Degrees)
            {
                return((int)height, (int)width);
            }

            return((int)width, (int)height);
        }
Beispiel #5
0
        public async Task <InputMessageFactory> CreatePhotoAsync(StorageFile file, bool asFile, int ttl = 0, BitmapEditState editState = null)
        {
            try
            {
                using (var stream = await file.OpenReadAsync())
                {
                    var decoder = await BitmapDecoder.CreateAsync(stream);

                    if (decoder.FrameCount > 1)
                    {
                        asFile = true;
                    }
                }
            }
            catch
            {
                asFile = true;
            }

            var size = await ImageHelper.GetScaleAsync(file, editState : editState);

            var generated = await file.ToGeneratedAsync(asFile?ConversionType.Copy : ConversionType.Compress, editState != null?JsonConvert.SerializeObject(editState) : null);

            var thumbnail = default(InputThumbnail);

            if (asFile)
            {
                return(new InputMessageFactory
                {
                    InputFile = generated,
                    Type = new FileTypeDocument(),
                    Delegate = (inputFile, caption) => new InputMessageDocument(inputFile, thumbnail, false, caption)
                });
            }

            return(new InputMessageFactory
            {
                InputFile = generated,
                Type = new FileTypePhoto(),
                Delegate = (inputFile, caption) => new InputMessagePhoto(generated, thumbnail, new int[0], size.Width, size.Height, caption, ttl)
            });
        }
        public EditMediaPopup(StorageMedia media, ImageCropperMask mask = ImageCropperMask.Rectangle, bool ttl = false)
        {
            InitializeComponent();

            Canvas.Strokes = media.EditState.Strokes;
            Cropper.SetMask(mask);
            if (mask == ImageCropperMask.Ellipse)
            {
                _hasMessageContext          = false;
                media.EditState.Proportions = BitmapProportions.Square;
            }
            Cropper.SetProportions(media.EditState.Proportions);

            _file  = media.File;
            _media = media;
            _originalMediaEditState = CopyBitmapEditState(media.EditState);

            Loaded += async(s, args) =>
            {
                await Cropper.SetSourceAsync(media.File, media.EditState.Rotation, media.EditState.Flip, media.EditState.Proportions, media.EditState.Rectangle);

                if (!_hasMessageContext) //TODO: Fix mask bug, remove hack (#2017 references mask position)
                {
                    await Cropper.SetSourceAsync(_media.File, _media.EditState.Rotation, _media.EditState.Flip, _media.EditState.Proportions, _media.EditState.Rectangle);

                    Cropper.SetProportions(_media.EditState.Proportions);
                }
                Cropper.IsCropEnabled = !_hasMessageContext && _media.IsVideo;
            };
            Unloaded += (s, args) =>
            {
                Media.Source = null;
            };

            #region Init UI
            if (mask == ImageCropperMask.Ellipse && string.Equals(media.File.FileType, ".mp4", StringComparison.OrdinalIgnoreCase))
            {
                FindName(nameof(TrimToolbar));
                TrimToolbar.Visibility    = Visibility.Visible;
                BasicToolbar.Visibility   = Visibility.Collapsed;
                SeparatorLeft.Visibility  = Visibility.Collapsed;
                SeparatorRight.Visibility = Visibility.Collapsed;

                InitializeVideo(media.File);
            }

            if (_media is StorageVideo video)
            {
                _originalVideoCompression = video.Compression;
                _originalVideoIsMuted     = video.IsMuted;
                Mute.IsChecked            = video.IsMuted;
                Mute.Visibility           = Visibility.Visible;
                Compress.IsChecked        = video.Compression != video.MaxCompression;
                Compress.Visibility       = video.CanCompress ? Visibility.Visible : Visibility.Collapsed;

                if (video.CanCompress)
                {
                    Compress.Glyph        = new CompressionToGlyphConverter().Convert(video.Compression, typeof(string), null, video.MaxCompression.ToString()).ToString();
                    Compress.CheckedGlyph = Compress.Glyph;
                    Compress.IsChecked    = video.Compression != video.MaxCompression;
                }
            }
            else
            {
                Mute.Visibility     = Visibility.Collapsed;
                Compress.Visibility = Visibility.Collapsed;
            }

            Crop.Visibility = _media is StoragePhoto ? Visibility.Visible : Visibility.Collapsed;
            Draw.Visibility = Crop.Visibility;
            Ttl.Visibility  = ttl ? Visibility.Visible : Visibility.Collapsed;
            Ttl.IsChecked   = _media.Ttl > 0;

            if (_media.EditState is BitmapEditState editSate)
            {
                Crop.IsChecked = editSate.Proportions != BitmapProportions.Custom ||
                                 editSate.Flip != BitmapFlip.None ||
                                 editSate.Rotation != BitmapRotation.None ||
                                 (!editSate.Rectangle.IsEmpty &&
                                  (editSate.Rectangle.X > 0 || editSate.Rectangle.Y > 0 ||
                                   Math.Abs(editSate.Rectangle.Width - 1) > 0.1f || Math.Abs(editSate.Rectangle.Height - 1) > 0.1f));

                Draw.IsChecked = editSate.Strokes != null && editSate.Strokes.Count > 0;
            }
            else
            {
                Crop.IsChecked = false;
                Draw.IsChecked = false;
            }

            if (_hasMessageContext)
            {
                if (!string.IsNullOrWhiteSpace(media.Caption?.Text))
                {
                    CaptionInput.SetText(media.Caption);
                }
            }
            else
            {
                CaptionInput.Visibility = Visibility.Collapsed;
            }
            #endregion
        }