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(); } } } }
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); }
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); } }
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); } } } }
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(); } } } } }
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"); } }
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); }
/// <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); }
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); } }
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); } }
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); } }
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); } }
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); } }
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)) { } }); } } }
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); } }
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); } }
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(); } } } }
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); } } }