static void Run(Options options)
        {
            using (var stream = File.OpenRead(options.Input))
            {
                var outputFileName = GetOutputFilename(options.Input);

                using (var outStream = File.OpenWrite(outputFileName))
                {
                    var hints = new ResampleHints
                    {
                        SharpenWhen    = SharpenWhen.Downscaling,
                        SharpenPercent = 100
                    };
                    using (var job = new ImageJob())
                    {
                        job.Decode(stream, false)
                        .ConstrainWithin(options.Width, options.height)
                        .SaturationSrgb(0)
                        .EncodeToStream(outStream, false, new MozJpegEncoder(90))
                        .Finish()
                        .InProcessAsync()
                        .Wait();
                    }
                }
            }
        }
Exemplo n.º 2
0
        private async Task <string> EncodeToPreferredFormatAndSave(byte[] formFileContent, string name)
        {
            using (var job = new ImageJob())
            {
                var info = await ImageJob.GetImageInfo(new BytesSource(formFileContent));

                GetEncoder(info, out IEncoderPreset encoder, out string expectedExt);

                var resized = await job.Decode(formFileContent)
                              .EncodeToBytes(encoder)
                              .Finish()
                              .InProcessAndDisposeAsync();

                var result = resized.First.TryGetBytes();

                if (result.HasValue)
                {
                    var fileName = Path.GetFileName(name);
                    var ext      = Path.GetExtension(fileName);

                    var newFileName = name.Replace(ext, expectedExt);

                    return(await _blog.SaveFile(result.Value.Array, newFileName));
                }
            }

            return(null);
        }
Exemplo n.º 3
0
        public async Task TestConstraints()
        {
            var imageBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                var r = await b.Decode(imageBytes).
                        Constrain(new Constraint(ConstraintMode.Fit_Crop, 10, 20)
                {
                    CanvasColor = null,
                    H           = 20,
                    W           = 10,
                    Hints       = new ResampleHints()
                    {
                        InterpolationColorspace = ScalingFloatspace.Linear,
                        DownFilter     = InterpolationFilter.Mitchell,
                        ResampleWhen   = ResampleWhen.Size_Differs_Or_Sharpening_Requested,
                        SharpenWhen    = SharpenWhen.Always,
                        SharpenPercent = 15,
                        UpFilter       = InterpolationFilter.Ginseng
                    },
                    Mode = ConstraintMode.Fit_Crop
                })
                        .EncodeToBytes(new GifEncoder()).Finish().InProcessAsync();

                Assert.Equal(10, r.First.Width);
                Assert.Equal(20, r.First.Height);
                Assert.True(r.First.TryGetBytes().HasValue);
            }
        }
Exemplo n.º 4
0
        private async Task DuplicateSmallerImageIfLargeAndSave(byte[] formFileContent, string name, int ifLargerThan, int constrainX, int constrainY)
        {
            using (var job = new ImageJob())
            {
                var info = await ImageJob.GetImageInfo(new BytesSource(formFileContent));

                if (info.ImageWidth > ifLargerThan)
                {
                    GetEncoder(info, out IEncoderPreset encoder, out string expectedExt);

                    var resized = await job.Decode(formFileContent)
                                  .ConstrainWithin((uint)constrainX, (uint)constrainY)
                                  .EncodeToBytes(encoder)
                                  .Finish()
                                  .InProcessAndDisposeAsync();

                    var result = resized.First.TryGetBytes();

                    if (result.HasValue)
                    {
                        var fileName = Path.GetFileName(name);
                        var ext      = Path.GetExtension(fileName);

                        var newFileName = name.Replace(ext, "-sm" + expectedExt);

                        await _blog.SaveFile(result.Value.Array, newFileName);
                    }
                }
            }
        }
Exemplo n.º 5
0
        static void Run(Options options)
        {
            var directory = Path.GetDirectoryName(options.Input);
            var files     = Directory.GetFiles(directory, "*.jpg");

            foreach (var filePath in files)
            {
                using (var stream = File.OpenRead(filePath))
                {
                    var outputFileName = GetOutputFileName(filePath);

                    using (var outStream = new FileStream(outputFileName, FileMode.Create, FileAccess.Write))
                    {
                        using (var job = new ImageJob())
                        {
                            job.Decode(stream, false)
                            .ConstrainWithin(options.Width, options.Height)
                            .ColorFilterSrgb(ColorFilterSrgb.Grayscale_Bt709)
                            .EncodeToStream(outStream, false, new MozJpegEncoder(90))
                            .Finish()
                            .InProcessAsync()
                            .Wait();
                        }
                    }
                }
            }
        }
Exemplo n.º 6
0
        public async Task TestCustomDownscalingAndDecodeEncodeResults()
        {
            var imageBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                var cmd = new DecodeCommands
                {
                    JpegDownscaleHint   = new Size(20, 20),
                    JpegDownscalingMode = DecoderDownscalingMode.Fastest,
                    DiscardColorProfile = true
                };
                var r = await b.Decode(new BytesSource(imageBytes), 0, cmd)
                        .Distort(30, 20, new ResampleHints().SetSharpen(50.0f, SharpenWhen.Always).SetResampleFilters(InterpolationFilter.Robidoux_Fast, InterpolationFilter.Cubic))
                        .ConstrainWithin(5, 5)
                        .EncodeToBytes(new LodePngEncoder()).Finish().InProcessAsync();

                Assert.Equal(5, r.First.Width);
                Assert.True(r.First.TryGetBytes().HasValue);
                Assert.Equal(r.DecodeResults.First().Width, 1);
                Assert.Equal(r.DecodeResults.First().Height, 1);
                Assert.Equal(r.DecodeResults.First().PreferredExtension, "png");
                Assert.Equal(r.DecodeResults.First().PreferredMimeType, "image/png");

                Assert.Equal(r.EncodeResults.First().Width, 5);
                Assert.Equal(r.EncodeResults.First().Height, 3);
                Assert.Equal(r.EncodeResults.First().PreferredExtension, "png");
                Assert.Equal(r.EncodeResults.First().PreferredMimeType, "image/png");
            }
        }
Exemplo n.º 7
0
        private static async Task <Stream> GenerateImageAsync(byte[] originalImage, ImageFileSpec imageFileSpec, Table table)
        {
            var individualImageStopwatch = new Stopwatch();

            individualImageStopwatch.Start();

            using (var job = new ImageJob())
            {
                var buildNode     = job.Decode(originalImage);
                var resampleHints = new ResampleHints();

                if (imageFileSpec.FileSpecFormat != FileSpecFormat.WebPLossless && imageFileSpec.SharpeningAmount > 0)
                {
                    resampleHints.SetSharpen(imageFileSpec.SharpeningAmount, SharpenWhen.Downscaling).SetResampleFilters(imageFileSpec.InterpolationFilter, null);
                }

                buildNode = buildNode.ConstrainWithin(imageFileSpec.PixelLength, imageFileSpec.PixelLength, resampleHints);
                IEncoderPreset encoderPreset;

                if (imageFileSpec.FileSpecFormat == FileSpecFormat.WebPLossless)
                {
                    encoderPreset = new WebPLosslessEncoder();
                }
                else if (imageFileSpec.FileSpecFormat == FileSpecFormat.WebPLossy)
                {
                    encoderPreset = new WebPLossyEncoder(imageFileSpec.Quality);
                }
                else
                {
                    encoderPreset = new MozJpegEncoder(imageFileSpec.Quality, true);
                }

                var result = await buildNode
                             .EncodeToBytes(encoderPreset)
                             .Finish()
                             .SetSecurityOptions(new SecurityOptions()
                                                 .SetMaxDecodeSize(new FrameSizeLimit(99999, 99999, 200))
                                                 .SetMaxFrameSize(new FrameSizeLimit(99999, 99999, 200))
                                                 .SetMaxEncodeSize(new FrameSizeLimit(99999, 99999, 200)))
                             .InProcessAsync();

                var newImageBytes = result.First.TryGetBytes();
                if (newImageBytes.HasValue)
                {
                    var newStream = new MemoryStream(newImageBytes.Value.ToArray());

                    individualImageStopwatch.Stop();
                    var kb   = newImageBytes.Value.Count / 1024;
                    var size = $"{kb} kb";
                    table.AddRow(imageFileSpec.ToString(), individualImageStopwatch.ElapsedMilliseconds.ToString(), size);

                    return(newStream);
                }
            }

            individualImageStopwatch.Stop();
            AnsiConsole.Render(new Markup("[bold red]Something went wrong with an image generation.[/]"));
            return(null);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Generates an resized image of the original in WebP format (quicker, smaller files).
        /// </summary>
        /// <param name="image">The Image the new file should be generated for. Used for logging purposes.</param>
        /// <param name="originalImage">The byte array for the original image.</param>
        /// <param name="imageFileSpec">The name of the image file specification to base the new image.</param>
        /// <returns>A new image stream for the resized image</returns>
        private static async Task <Stream> GenerateImageAsync(Image image, byte[] originalImage, ImageFileSpec imageFileSpec)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            using (var job = new ImageJob())
            {
                var buildNode     = job.Decode(originalImage);
                var resampleHints = new ResampleHints();

                if (imageFileSpec.FileSpecFormat != FileSpecFormat.WebPLossless && imageFileSpec.SharpeningAmount > 0)
                {
                    resampleHints.SetSharpen(imageFileSpec.SharpeningAmount, SharpenWhen.Downscaling).SetResampleFilters(imageFileSpec.InterpolationFilter, null);
                }

                buildNode = buildNode.ConstrainWithin(imageFileSpec.PixelLength, imageFileSpec.PixelLength, resampleHints);
                IEncoderPreset encoderPreset;

                if (imageFileSpec.FileSpecFormat == FileSpecFormat.WebPLossless)
                {
                    encoderPreset = new WebPLosslessEncoder();
                }
                else if (imageFileSpec.FileSpecFormat == FileSpecFormat.WebPLossy)
                {
                    encoderPreset = new WebPLossyEncoder(imageFileSpec.Quality);
                }
                else
                {
                    encoderPreset = new MozJpegEncoder(imageFileSpec.Quality, true);
                }

                var result = await buildNode
                             .EncodeToBytes(encoderPreset)
                             .Finish()
                             .SetSecurityOptions(new SecurityOptions()
                                                 .SetMaxDecodeSize(new FrameSizeLimit(99999, 99999, 200))
                                                 .SetMaxFrameSize(new FrameSizeLimit(99999, 99999, 200))
                                                 .SetMaxEncodeSize(new FrameSizeLimit(99999, 99999, 200)))
                             .InProcessAsync();

                var newImageBytes = result.First.TryGetBytes();
                if (newImageBytes.HasValue)
                {
                    var newStream = new MemoryStream(newImageBytes.Value.ToArray());

                    stopwatch.Stop();
                    _log.Information($"LB.PhotoGalleries.Worker.Program.GenerateImageAsync() - Image {image.Id} and spec {imageFileSpec} done. Elapsed time: {stopwatch.ElapsedMilliseconds}ms");
                    return(newStream);
                }
            }

            stopwatch.Stop();
            _log.Warning($"LB.PhotoGalleries.Worker.Program.GenerateImageAsync() - Couldn't generate new image for {image.Id}! Elapsed time: {stopwatch.ElapsedMilliseconds}ms");
            return(null);
        }
Exemplo n.º 9
0
        public async Task TestJobWithCommandString()
        {
            var imageBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                var r = await b.Decode(imageBytes).ResizerCommands("width=3&height=2&mode=stretch&scale=both")
                        .EncodeToBytes(new GifEncoder()).Finish().InProcessAsync();

                Assert.Equal(3, r.First.Width);
                Assert.True(r.First.TryGetBytes().HasValue);
            }
        }
Exemplo n.º 10
0
        public async Task TestAllJob()
        {
            var imageBytes = Convert.FromBase64String(
                "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                var r = await b.Decode(imageBytes)
                        .FlipVertical()
                        .FlipHorizontal()
                        .Rotate90()
                        .Rotate180()
                        .Rotate270()
                        .Transpose()
                        .CropWhitespace(80, 0.5f)
                        .Distort(30, 20)
                        .Crop(0, 0, 10, 10)
                        .Region(-5, -5, 10, 10, AnyColor.Black)
                        .RegionPercent(-10f, -10f, 110f, 110f, AnyColor.Transparent)
                        .BrightnessSrgb(-1f)
                        .ContrastSrgb(1f)
                        .SaturationSrgb(1f)
                        .WhiteBalanceSrgb(80)
                        .ColorFilterSrgb(ColorFilterSrgb.Invert)
                        .ColorFilterSrgb(ColorFilterSrgb.Sepia)
                        .ColorFilterSrgb(ColorFilterSrgb.Grayscale_Bt709)
                        .ColorFilterSrgb(ColorFilterSrgb.Grayscale_Flat)
                        .ColorFilterSrgb(ColorFilterSrgb.Grayscale_Ntsc)
                        .ColorFilterSrgb(ColorFilterSrgb.Grayscale_Ry)
                        .ExpandCanvas(5, 5, 5, 5, AnyColor.FromHexSrgb("FFEECCFF"))
                        .FillRectangle(2, 2, 8, 8, AnyColor.Black)
                        .ResizerCommands("width=10&height=10&mode=crop")
                        .ConstrainWithin(5, 5)
                        .Watermark(new BytesSource(imageBytes),
                                   new WatermarkOptions()
                                   .SetMarginsLayout(
                                       new WatermarkMargins(WatermarkAlign.Image, 1, 1, 1, 1),
                                       WatermarkConstraintMode.Within,
                                       new ConstraintGravity(90, 90))
                                   .SetOpacity(0.5f)
                                   .SetHints(new ResampleHints().SetSharpen(15f, SharpenWhen.Always))
                                   .SetMinCanvasSize(1, 1))
                        .EncodeToBytes(new MozJpegEncoder(80, true))
                        .Finish().InProcessAsync();

                Assert.Equal(5, r.First.Width);
                Assert.True(r.First.TryGetBytes().HasValue);
            }
        }
Exemplo n.º 11
0
        public async Task TestMultipleInputs()
        {
            var imageBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                var canvas = b.Decode(imageBytes)
                             .Distort(30, 30);

                var r = await b.Decode(imageBytes)
                        .Distort(20, 20)
                        .FillRectangle(5, 5, 15, 15, AnyColor.FromHexSrgb("FFEECC"))
                        .TransparencySrgb(0.5f)
                        .DrawImageExactTo(canvas,
                                          new Rectangle(5, 5, 25, 25),
                                          new ResampleHints(),
                                          CompositingMode.Compose)
                        .EncodeToBytes(new LodePngEncoder())
                        .Finish().InProcessAsync();

                Assert.Equal(30, r.TryGet(2).Width);
                Assert.True(r.First.TryGetBytes().HasValue);
            }
        }
Exemplo n.º 12
0
        public async Task TestConstraints()
        {
            var imageBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                var r = await b.Decode(imageBytes).
                        Constrain(new Constraint(ConstraintMode.Fit_Crop, 10, 20))
                        .EncodeToBytes(new GifEncoder()).Finish().InProcessAsync();

                Assert.Equal(10, r.First.Width);
                Assert.Equal(20, r.First.Height);
                Assert.True(r.First.TryGetBytes().HasValue);
            }
        }
Exemplo n.º 13
0
        public async Task TestBuildJob()
        {
            var imageBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                var r = await b.Decode(imageBytes)
                        .FlipHorizontal()
                        .Rotate90()
                        .Distort(30, 20)
                        .ConstrainWithin(5, 5)
                        .EncodeToBytes(new GifEncoder()).Finish().InProcessAsync();

                Assert.Equal(5, r.First.Width);
                Assert.True(r.First.TryGetBytes().HasValue);
            }
        }
Exemplo n.º 14
0
        public async Task TestFilesystemJobPrep()
        {
            var isUnix = Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX;

            var imageBytes = Convert.FromBase64String(
                "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                string jsonPath;
                using (var job = await b.Decode(imageBytes).FlipHorizontal().Rotate90().Distort(30, 20)
                                 .ConstrainWithin(5, 5)
                                 .EncodeToBytes(new GifEncoder()).Finish().WithCancellationTimeout(2000)
                                 .WriteJsonJobAndInputs(true))
                {
                    jsonPath = job.JsonPath;

                    if (isUnix)
                    {
                        Assert.True(File.Exists(jsonPath));
                    }
                    else
                    {
                        using (var file = System.IO.MemoryMappedFiles.MemoryMappedFile.OpenExisting(jsonPath))
                        {
                        } // Will throw filenotfoundexception if missing
                    }
                }

                if (isUnix)
                {
                    Assert.False(File.Exists(jsonPath));
                }
                else
                {
                    Assert.Throws <FileNotFoundException>(delegate()
                    {
                        using (var file = System.IO.MemoryMappedFiles.MemoryMappedFile.OpenExisting(jsonPath))
                        {
                        }
                    });
                }
            }
        }
Exemplo n.º 15
0
        public async Task TestEncodeSizeLimit()
        {
            var imageBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                var e = await Assert.ThrowsAsync <ImageflowException>(async() =>
                {
                    await b.Decode(imageBytes)
                    .ResizerCommands("width=3&height=2&mode=stretch&scale=both")
                    .EncodeToBytes(new GifEncoder())
                    .Finish()
                    .SetSecurityOptions(new SecurityOptions().SetMaxEncodeSize(new FrameSizeLimit(1, 1, 1)))
                    .InProcessAsync();
                });

                Assert.StartsWith("ArgumentInvalid: SizeLimitExceeded: Frame width 3 exceeds max_encode_size.w", e.Message);
            }
        }
Exemplo n.º 16
0
        public async Task TestMultipleOutputs()
        {
            var imageBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");

            using (var b = new ImageJob())
            {
                var r = await b.Decode(imageBytes).
                        Constrain(new Constraint(ConstraintMode.Fit, 160, 120))
                        .Branch(f => f.ConstrainWithin(80, 60).EncodeToBytes(new WebPLosslessEncoder()))
                        .Branch(f => f.ConstrainWithin(40, 30).EncodeToBytes(new WebPLossyEncoder(50)))
                        .EncodeToBytes(new LodePngEncoder())
                        .Finish().InProcessAsync();


                Assert.Equal(60, r.TryGet(1).Width);
                Assert.Equal(30, r.TryGet(2).Width);
                Assert.Equal(120, r.TryGet(3).Width);
                Assert.True(r.First.TryGetBytes().HasValue);
            }
        }
Exemplo n.º 17
0
        static void Run(Options options)
        {
            using (var stream = File.OpenRead(options.Input))
            {
                var outputFileName = GetOutputFileName(options.Input);


                using (var outStream = File.OpenWrite(outputFileName))
                {
                    using (var job = new ImageJob())
                    {
                        job.Decode(stream, false)
                        .ResizerCommands("height=500&mode=crop")
                        .ConstrainWithin(300, null)
                        .ContrastSrgb(10f)
                        .EncodeToStream(outStream, false, new MozJpegEncoder(90))
                        .Finish().InProcessAsync()
                        .Wait();
                    }
                }
            }
        }
Exemplo n.º 18
0
        public async Task TestBuildJobSubprocess()
        {
            string imageflowTool = Environment.GetEnvironmentVariable("IMAGEFLOW_TOOL");

            if (!string.IsNullOrWhiteSpace(imageflowTool))
            {
                var imageBytes = Convert.FromBase64String(
                    "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEX/TQBcNTh/AAAAAXRSTlPM0jRW/QAAAApJREFUeJxjYgAAAAYAAzY3fKgAAAAASUVORK5CYII=");
                using (var b = new ImageJob())
                {
                    var r = await b.Decode(imageBytes).FlipHorizontal().Rotate90().Distort(30, 20).ConstrainWithin(5, 5)
                            .EncodeToBytes(new GifEncoder())
                            .Finish()
                            .WithCancellationTimeout(2000)
                            .InSubprocessAsync(imageflowTool);

                    // ExecutableLocator.FindExecutable("imageflow_tool", new [] {"/home/n/Documents/imazen/imageflow/target/release/"})

                    Assert.Equal(5, r.First.Width);
                    Assert.True(r.First.TryGetBytes().HasValue);
                }
            }
        }
        private Task <Result <Image> > ConvertAndUpload(Image dbImage, FormFile uploadedFile)
        {
            return(GetBytes()
                   .Ensure(AreDimensionsValid,
                           $"Uploading image size must be at least {MinimumImageWidth}×{MinimumImageHeight} pixels and the width mustn't exceed two heights and vice versa")
                   .Bind(Convert)
                   .Bind(Upload));


            Result <byte[]> GetBytes()
            {
                using var binaryReader = new BinaryReader(uploadedFile.OpenReadStream());
                return(Result.Success(binaryReader.ReadBytes((int)uploadedFile.Length)));
            }

            async Task <bool> AreDimensionsValid(byte[] imageBytes)
            {
                var info = await ImageJob.GetImageInfo(new BytesSource(imageBytes));

                return(MinimumImageWidth <= info.ImageWidth &&
                       MinimumImageHeight <= info.ImageHeight &&
                       info.ImageWidth / info.ImageHeight < 2 &&
                       info.ImageHeight / info.ImageWidth < 2);
            }

            async Task <Result <ImageSet> > Convert(byte[] imageBytes)
            {
                var imagesSet = new ImageSet();

                using var imageJob = new ImageJob();
                var jobResult = await imageJob.Decode(imageBytes)
                                .Constrain(new Constraint(ConstraintMode.Within, ResizedLargeImageMaximumSideSize, ResizedLargeImageMaximumSideSize))
                                .Branch(f => f.ConstrainWithin(ResizedSmallImageMaximumSideSize, ResizedSmallImageMaximumSideSize).EncodeToBytes(new MozJpegEncoder(TargetJpegQuality, true)))
                                .EncodeToBytes(new MozJpegEncoder(TargetJpegQuality, true))
                                .Finish().InProcessAsync();

                imagesSet.SmallImage = GetImage(1);
                imagesSet.MainImage  = GetImage(2);

                return(imagesSet.MainImage.Any() && imagesSet.SmallImage.Any()
                    ? Result.Success(imagesSet)
                    : Result.Failure <ImageSet>("Processing of the images failed"));


                byte[] GetImage(int index)
                {
                    var encodeResult = jobResult?.TryGet(index);
                    var bytes        = encodeResult?.TryGetBytes();

                    return(bytes != null?bytes.Value.ToArray() : new byte[]
                    {
                    });
                }
            }

            async Task <Result <Image> > Upload(ImageSet imageSet)
            {
                dbImage.Position = _dbContext.Images.Count(i => i.ReferenceId == dbImage.ReferenceId && i.ImageType == dbImage.ImageType);
                var entry = _dbContext.Images.Add(dbImage);
                await _dbContext.SaveChangesAsync();

                var imageId = entry.Entity.Id;

                SetImageKeys();

                var addToBucketResult = await AddImagesToBucket();

                if (!addToBucketResult)
                {
                    _dbContext.Images.Remove(entry.Entity);

                    await _dbContext.SaveChangesAsync();

                    return(Result.Failure <Image>("Uploading of the image failed"));
                }

                _dbContext.Images.Update(entry.Entity);

                await _dbContext.SaveChangesAsync();

                _dbContext.DetachEntry(entry.Entity);

                return(Result.Success(dbImage));


                void SetImageKeys()
                {
                    var basePartOfKey = $"{S3FolderName}/{dbImage.ServiceSupplierId}/{imageId}";

                    dbImage.Keys.MainImage  = $"{basePartOfKey}-main.jpg";
                    dbImage.Keys.SmallImage = $"{basePartOfKey}-small.jpg";
                }

                async Task <bool> AddImagesToBucket()
                {
                    await using var largeStream = new MemoryStream(imageSet.MainImage);
                    await using var smallStream = new MemoryStream(imageSet.SmallImage);
                    var imageList = new List <(string key, Stream stream)>
                    {
                        (dbImage.Keys.MainImage, largeStream),
                        (dbImage.Keys.SmallImage, smallStream)
                    };

                    var resultList = await _amazonS3ClientService.Add(_bucketName, imageList);

                    foreach (var result in resultList)
                    {
                        if (result.IsFailure)
                        {
                            var keyList = new List <string>
                            {
                                dbImage.Keys.MainImage,
                                dbImage.Keys.SmallImage
                            };
                            await _amazonS3ClientService.Delete(_bucketName, keyList);

                            return(false);
                        }
                    }

                    return(true);
                }
            }
        }