diff --git a/Emby.Drawing.Skia/SkiaEncoder.cs b/Emby.Drawing.Skia/SkiaEncoder.cs index 7ccb75ec47..02e10f693c 100644 --- a/Emby.Drawing.Skia/SkiaEncoder.cs +++ b/Emby.Drawing.Skia/SkiaEncoder.cs @@ -174,28 +174,24 @@ namespace Emby.Drawing.Skia var newRect = SKRectI.Create(leftmost, topmost, rightmost - leftmost, bottommost - topmost); using (var image = SKImage.FromBitmap(bitmap)) + using (var subset = image.Subset(newRect)) { - using (var subset = image.Subset(newRect)) - { - return SKBitmap.FromImage(subset); - } + return SKBitmap.FromImage(subset); } } public ImageSize GetImageSize(string path) { using (var s = new SKFileStream(path)) + using (var codec = SKCodec.Create(s)) { - using (var codec = SKCodec.Create(s)) - { - var info = codec.Info; + var info = codec.Info; - return new ImageSize - { - Width = info.Width, - Height = info.Height - }; - } + return new ImageSize + { + Width = info.Width, + Height = info.Height + }; } } @@ -234,36 +230,36 @@ namespace Emby.Drawing.Skia return tempPath; } - private static SKCodecOrigin GetSKCodecOrigin(ImageOrientation? orientation) + private static SKEncodedOrigin GetSKCodecOrigin(ImageOrientation? orientation) { if (!orientation.HasValue) { - return SKCodecOrigin.TopLeft; + return SKEncodedOrigin.TopLeft; } switch (orientation.Value) { case ImageOrientation.TopRight: - return SKCodecOrigin.TopRight; + return SKEncodedOrigin.TopRight; case ImageOrientation.RightTop: - return SKCodecOrigin.RightTop; + return SKEncodedOrigin.RightTop; case ImageOrientation.RightBottom: - return SKCodecOrigin.RightBottom; + return SKEncodedOrigin.RightBottom; case ImageOrientation.LeftTop: - return SKCodecOrigin.LeftTop; + return SKEncodedOrigin.LeftTop; case ImageOrientation.LeftBottom: - return SKCodecOrigin.LeftBottom; + return SKEncodedOrigin.LeftBottom; case ImageOrientation.BottomRight: - return SKCodecOrigin.BottomRight; + return SKEncodedOrigin.BottomRight; case ImageOrientation.BottomLeft: - return SKCodecOrigin.BottomLeft; + return SKEncodedOrigin.BottomLeft; default: - return SKCodecOrigin.TopLeft; + return SKEncodedOrigin.TopLeft; } } private static string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" }; - internal static SKBitmap Decode(string path, bool forceCleanBitmap, IFileSystem fileSystem, ImageOrientation? orientation, out SKCodecOrigin origin) + internal static SKBitmap Decode(string path, bool forceCleanBitmap, IFileSystem fileSystem, ImageOrientation? orientation, out SKEncodedOrigin origin) { if (!fileSystem.FileExists(path)) { @@ -275,32 +271,30 @@ namespace Emby.Drawing.Skia if (requiresTransparencyHack || forceCleanBitmap) { using (var stream = new SKFileStream(NormalizePath(path, fileSystem))) + using (var codec = SKCodec.Create(stream)) { - using (var codec = SKCodec.Create(stream)) + if (codec == null) { - if (codec == null) - { - origin = GetSKCodecOrigin(orientation); - return null; - } + origin = GetSKCodecOrigin(orientation); + return null; + } - // create the bitmap - var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack); + // create the bitmap + var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack); - if (bitmap != null) - { - // decode - codec.GetPixels(bitmap.Info, bitmap.GetPixels()); - - origin = codec.Origin; - } - else - { - origin = GetSKCodecOrigin(orientation); - } + if (bitmap != null) + { + // decode + codec.GetPixels(bitmap.Info, bitmap.GetPixels()); - return bitmap; + origin = codec.EncodedOrigin; } + else + { + origin = GetSKCodecOrigin(orientation); + } + + return bitmap; } } @@ -320,11 +314,11 @@ namespace Emby.Drawing.Skia } } - origin = SKCodecOrigin.TopLeft; + origin = SKEncodedOrigin.TopLeft; return resultBitmap; } - private SKBitmap GetBitmap(string path, bool cropWhitespace, bool forceAnalyzeBitmap, ImageOrientation? orientation, out SKCodecOrigin origin) + private SKBitmap GetBitmap(string path, bool cropWhitespace, bool forceAnalyzeBitmap, ImageOrientation? orientation, out SKEncodedOrigin origin) { if (cropWhitespace) { @@ -339,7 +333,7 @@ namespace Emby.Drawing.Skia private SKBitmap GetBitmap(string path, bool cropWhitespace, bool autoOrient, ImageOrientation? orientation) { - SKCodecOrigin origin; + SKEncodedOrigin origin; if (autoOrient) { @@ -347,7 +341,7 @@ namespace Emby.Drawing.Skia if (bitmap != null) { - if (origin != SKCodecOrigin.TopLeft) + if (origin != SKEncodedOrigin.TopLeft) { using (bitmap) { @@ -362,7 +356,7 @@ namespace Emby.Drawing.Skia return GetBitmap(path, cropWhitespace, false, orientation, out origin); } - private SKBitmap OrientImage(SKBitmap bitmap, SKCodecOrigin origin) + private SKBitmap OrientImage(SKBitmap bitmap, SKEncodedOrigin origin) { //var transformations = { // 2: { rotate: 0, flip: true}, @@ -377,7 +371,7 @@ namespace Emby.Drawing.Skia switch (origin) { - case SKCodecOrigin.TopRight: + case SKEncodedOrigin.TopRight: { var rotated = new SKBitmap(bitmap.Width, bitmap.Height); using (var surface = new SKCanvas(rotated)) @@ -390,7 +384,7 @@ namespace Emby.Drawing.Skia return rotated; } - case SKCodecOrigin.BottomRight: + case SKEncodedOrigin.BottomRight: { var rotated = new SKBitmap(bitmap.Width, bitmap.Height); using (var surface = new SKCanvas(rotated)) @@ -408,7 +402,7 @@ namespace Emby.Drawing.Skia return rotated; } - case SKCodecOrigin.BottomLeft: + case SKEncodedOrigin.BottomLeft: { var rotated = new SKBitmap(bitmap.Width, bitmap.Height); using (var surface = new SKCanvas(rotated)) @@ -429,7 +423,7 @@ namespace Emby.Drawing.Skia return rotated; } - case SKCodecOrigin.LeftTop: + case SKEncodedOrigin.LeftTop: { // TODO: Remove dual canvases, had trouble with flipping using (var rotated = new SKBitmap(bitmap.Height, bitmap.Width)) @@ -456,7 +450,7 @@ namespace Emby.Drawing.Skia } } - case SKCodecOrigin.RightTop: + case SKEncodedOrigin.RightTop: { var rotated = new SKBitmap(bitmap.Height, bitmap.Width); using (var surface = new SKCanvas(rotated)) @@ -469,7 +463,7 @@ namespace Emby.Drawing.Skia return rotated; } - case SKCodecOrigin.RightBottom: + case SKEncodedOrigin.RightBottom: { // TODO: Remove dual canvases, had trouble with flipping using (var rotated = new SKBitmap(bitmap.Height, bitmap.Width)) @@ -493,7 +487,7 @@ namespace Emby.Drawing.Skia } } - case SKCodecOrigin.LeftBottom: + case SKEncodedOrigin.LeftBottom: { var rotated = new SKBitmap(bitmap.Height, bitmap.Width); using (var surface = new SKCanvas(rotated)) @@ -569,56 +563,51 @@ namespace Emby.Drawing.Skia } } - // create bitmap to use for canvas drawing + // create bitmap to use for canvas drawing used to draw into bitmap using (var saveBitmap = new SKBitmap(width, height))//, bitmap.ColorType, bitmap.AlphaType)) + using (var canvas = new SKCanvas(saveBitmap)) { - // create canvas used to draw into bitmap - using (var canvas = new SKCanvas(saveBitmap)) + // set background color if present + if (hasBackgroundColor) { - // set background color if present - if (hasBackgroundColor) - { - canvas.Clear(SKColor.Parse(options.BackgroundColor)); - } + canvas.Clear(SKColor.Parse(options.BackgroundColor)); + } - // Add blur if option is present - if (blur > 0) - { - using (var paint = new SKPaint()) - { - // create image from resized bitmap to apply blur - using (var filter = SKImageFilter.CreateBlur(blur, blur)) - { - paint.ImageFilter = filter; - canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height), paint); - } - } - } - else + // Add blur if option is present + if (blur > 0) + { + // create image from resized bitmap to apply blur + using (var paint = new SKPaint()) + using (var filter = SKImageFilter.CreateBlur(blur, blur)) { - // draw resized bitmap onto canvas - canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height)); + paint.ImageFilter = filter; + canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height), paint); } + } + else + { + // draw resized bitmap onto canvas + canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height)); + } - // If foreground layer present then draw - if (hasForegroundColor) - { - Double opacity; - if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4; + // If foreground layer present then draw + if (hasForegroundColor) + { + Double opacity; + if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4; - canvas.DrawColor(new SKColor(0, 0, 0, (Byte)((1 - opacity) * 0xFF)), SKBlendMode.SrcOver); - } + canvas.DrawColor(new SKColor(0, 0, 0, (Byte)((1 - opacity) * 0xFF)), SKBlendMode.SrcOver); + } - if (hasIndicator) - { - DrawIndicator(canvas, width, height, options); - } + if (hasIndicator) + { + DrawIndicator(canvas, width, height, options); + } - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath)); - using (var outputStream = new SKFileWStream(outputPath)) - { - saveBitmap.Encode(outputStream, skiaOutputFormat, quality); - } + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath)); + using (var outputStream = new SKFileWStream(outputPath)) + { + saveBitmap.Encode(outputStream, skiaOutputFormat, quality); } } } diff --git a/Emby.Drawing.Skia/StripCollageBuilder.cs b/Emby.Drawing.Skia/StripCollageBuilder.cs index 85eeaa9f59..32f0b65857 100644 --- a/Emby.Drawing.Skia/StripCollageBuilder.cs +++ b/Emby.Drawing.Skia/StripCollageBuilder.cs @@ -99,56 +99,48 @@ namespace Emby.Drawing.Skia using (var resizeBitmap = new SKBitmap(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType)) { currentBitmap.Resize(resizeBitmap, SKBitmapResizeMethod.Lanczos3); - // determine how much to crop + // crop image int ix = (int)Math.Abs((iWidth - iSlice) / 2); using (var image = SKImage.FromBitmap(resizeBitmap)) + using (var subset = image.Subset(SKRectI.Create(ix, 0, iSlice, iHeight))) { - // crop image - using (var subset = image.Subset(SKRectI.Create(ix, 0, iSlice, iHeight))) - { - // draw image onto canvas - canvas.DrawImage(subset ?? image, (horizontalImagePadding * (i + 1)) + (iSlice * i), verticalSpacing); + // draw image onto canvas + canvas.DrawImage(subset ?? image, (horizontalImagePadding * (i + 1)) + (iSlice * i), verticalSpacing); - if (subset == null) - { - continue; - } + if (subset == null) + { + continue; + } + // create reflection of image below the drawn image + using (var croppedBitmap = SKBitmap.FromImage(subset)) + using (var reflectionBitmap = new SKBitmap(croppedBitmap.Width, croppedBitmap.Height / 2, croppedBitmap.ColorType, croppedBitmap.AlphaType)) + { + // resize to half height + croppedBitmap.Resize(reflectionBitmap, SKBitmapResizeMethod.Lanczos3); - using (var croppedBitmap = SKBitmap.FromImage(subset)) + using (var flippedBitmap = new SKBitmap(reflectionBitmap.Width, reflectionBitmap.Height, reflectionBitmap.ColorType, reflectionBitmap.AlphaType)) + using (var flippedCanvas = new SKCanvas(flippedBitmap)) { - // create reflection of image below the drawn image - using (var reflectionBitmap = new SKBitmap(croppedBitmap.Width, croppedBitmap.Height / 2, croppedBitmap.ColorType, croppedBitmap.AlphaType)) + // flip image vertically + var matrix = SKMatrix.MakeScale(1, -1); + matrix.SetScaleTranslate(1, -1, 0, flippedBitmap.Height); + flippedCanvas.SetMatrix(matrix); + flippedCanvas.DrawBitmap(reflectionBitmap, 0, 0); + flippedCanvas.ResetMatrix(); + + // create gradient to make image appear as a reflection + var remainingHeight = height - (iHeight + (2 * verticalSpacing)); + flippedCanvas.ClipRect(SKRect.Create(reflectionBitmap.Width, remainingHeight)); + using (var gradient = new SKPaint()) { - // resize to half height - croppedBitmap.Resize(reflectionBitmap, SKBitmapResizeMethod.Lanczos3); - - using (var flippedBitmap = new SKBitmap(reflectionBitmap.Width, reflectionBitmap.Height, reflectionBitmap.ColorType, reflectionBitmap.AlphaType)) - { - using (var flippedCanvas = new SKCanvas(flippedBitmap)) - { - // flip image vertically - var matrix = SKMatrix.MakeScale(1, -1); - matrix.SetScaleTranslate(1, -1, 0, flippedBitmap.Height); - flippedCanvas.SetMatrix(matrix); - flippedCanvas.DrawBitmap(reflectionBitmap, 0, 0); - flippedCanvas.ResetMatrix(); - - // create gradient to make image appear as a reflection - var remainingHeight = height - (iHeight + (2 * verticalSpacing)); - flippedCanvas.ClipRect(SKRect.Create(reflectionBitmap.Width, remainingHeight)); - using (var gradient = new SKPaint()) - { - gradient.IsAntialias = true; - gradient.BlendMode = SKBlendMode.SrcOver; - gradient.Shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(0, remainingHeight), new[] { new SKColor(0, 0, 0, 128), new SKColor(0, 0, 0, 208), new SKColor(0, 0, 0, 240), new SKColor(0, 0, 0, 255) }, null, SKShaderTileMode.Clamp); - flippedCanvas.DrawPaint(gradient); - } - - // finally draw reflection onto canvas - canvas.DrawBitmap(flippedBitmap, (horizontalImagePadding * (i + 1)) + (iSlice * i), iHeight + (2 * verticalSpacing)); - } - } + gradient.IsAntialias = true; + gradient.BlendMode = SKBlendMode.SrcOver; + gradient.Shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(0, remainingHeight), new[] { new SKColor(0, 0, 0, 128), new SKColor(0, 0, 0, 208), new SKColor(0, 0, 0, 240), new SKColor(0, 0, 0, 255) }, null, SKShaderTileMode.Clamp); + flippedCanvas.DrawPaint(gradient); } + + // finally draw reflection onto canvas + canvas.DrawBitmap(flippedBitmap, (horizontalImagePadding * (i + 1)) + (iSlice * i), iHeight + (2 * verticalSpacing)); } } } @@ -172,7 +164,7 @@ namespace Emby.Drawing.Skia currentIndex = 0; } - SKCodecOrigin origin; + SKEncodedOrigin origin; bitmap = SkiaEncoder.Decode(paths[currentIndex], false, _fileSystem, null, out origin); imagesTested[currentIndex] = 0; @@ -202,7 +194,6 @@ namespace Emby.Drawing.Skia { for (var y = 0; y < 2; y++) { - SKCodecOrigin origin; int newIndex; using (var currentBitmap = GetNextValidImage(paths, imageIndex, out newIndex)) @@ -232,4 +223,4 @@ namespace Emby.Drawing.Skia return bitmap; } } -} \ No newline at end of file +}