예제 #1
0
        private SKBitmap Crop(SKBitmap original, ResizeParams resizeParams)
        {
            var cropSides     = 0;
            var cropTopBottom = 0;

            // calculate amount of pixels to remove from sides and top/bottom
            if ((float)resizeParams.w / original.Width < resizeParams.h / original.Height) // crop sides
            {
                cropSides = original.Width - (int)Math.Round((float)original.Height / resizeParams.h * resizeParams.w);
            }
            else
            {
                cropTopBottom = original.Height - (int)Math.Round((float)original.Width / resizeParams.w * resizeParams.h);
            }

            // setup crop rect
            var cropRect = new SKRectI
            {
                Left   = cropSides / 2,
                Top    = cropTopBottom / 2,
                Right  = original.Width - cropSides + cropSides / 2,
                Bottom = original.Height - cropTopBottom + cropTopBottom / 2
            };

            // crop
            SKBitmap bitmap = new SKBitmap(cropRect.Width, cropRect.Height);

            original.ExtractSubset(bitmap, cropRect);
            original.Dispose();

            return(bitmap);
        }
예제 #2
0
        internal static SKBitmap WatermarkText(SKBitmap original, ResizeParams resizeParams, WatermarkTextModel watermarkText)
        {
            var toBitmap = new SKBitmap(original.Width, original.Height);
            var canvas   = new SKCanvas(toBitmap);
            // Draw a bitmap rescaled


            var paint = new SKPaint();

            //paint.Typeface = SKTypeface.FromFamilyName("Arial");
            paint.TextSize  = watermarkText.TextSize;
            paint.TextAlign = watermarkText.TextAlign.GetSKTextAlign();
            if (watermarkText.IsVerticalText)
            {
                paint.IsVerticalText = true;
            }
            else
            {
                paint.IsLinearText = true;
            }

            if (watermarkText.Type == 2)
            {
                paint.IsStroke    = true;
                paint.StrokeWidth = watermarkText.StrokeWidth;
                paint.StrokeCap   = SKStrokeCap.Round;
            }
            paint.Style         = watermarkText.Type.GetSKPaintStyle();
            paint.FilterQuality = watermarkText.Quality.GetSKFilterQuality();
            paint.TextSkewX     = watermarkText.TextSkewX;
            paint.IsAntialias   = true;

            //https://www.color-hex.com/
            if (SKColor.TryParse(watermarkText.Color, out SKColor color))
            {
                paint.Color = color;
            }
            else
            {
                paint.Color = SKColors.Black;
            }

            canvas.DrawBitmap(original, 0, 0);

            var x = watermarkText.PositionMeasureType == 1 ? watermarkText.X : watermarkText.X.ToPixel(original.Width);
            var y = watermarkText.PositionMeasureType == 1 ? watermarkText.Y : watermarkText.Y.ToPixel(original.Height);

            canvas.DrawText(watermarkText.Value, x, y, paint);

            canvas.Flush();

            canvas.Dispose();
            paint.Dispose();
            original.Dispose();

            return(toBitmap);
        }
예제 #3
0
        public async Task Invoke(HttpContext context)
        {
            PathString path = context.Request.Path;

            // hand to next middleware if we are not dealing with an image
            if (context.Request.Query.Count == 0 || !IsImagePath(path))
            {
                await _next.Invoke(context);

                return;
            }

            // hand to next middleware if we are dealing with an image but it doesn't have any usable resize querystring params
            ResizeParams resizeParams = GetResizeParams(path, context.Request.Query);

            if (!resizeParams.hasParams || (resizeParams.w == 0 && resizeParams.h == 0))
            {
                await _next.Invoke(context);

                return;
            }

            // get the image location on disk
            string imagePath = Path.Combine(
                _env.WebRootPath,
                path.Value.Replace('/', Path.DirectorySeparatorChar).TrimStart(Path.DirectorySeparatorChar));

            // check file lastwrite
            DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(imagePath);

            if (lastWriteTimeUtc.Year == 1601) // file doesn't exist, pass to next middleware
            {
                await _next.Invoke(context);

                return;
            }

            SKData imageData = GetImageData(imagePath, resizeParams, lastWriteTimeUtc);

            // write to stream
            context.Response.ContentType   = resizeParams.format == "png" ? "image/png" : "image/jpeg";
            context.Response.ContentLength = imageData.Size;
            await context.Response.Body.WriteAsync(imageData.ToArray(), 0, (int)imageData.Size);

            // cleanup
            imageData.Dispose();
        }
예제 #4
0
        private ResizeParams GetResizeParams(PathString path, IQueryCollection query)
        {
            ResizeParams resizeParams = new ResizeParams();

            // before we extract, do a quick check for resize params
            resizeParams.hasParams =
                resizeParams.GetType().GetTypeInfo()
                .GetFields().Where(f => f.Name != "hasParams")
                .Any(f => query.ContainsKey(f.Name));

            // if no params present, bug out
            if (!resizeParams.hasParams)
            {
                return(resizeParams);
            }

            // extract resize params

            if (query.ContainsKey("format"))
            {
                resizeParams.format = query["format"];
            }
            else
            {
                resizeParams.format = path.Value.Substring(path.Value.LastIndexOf('.') + 1);
            }

            if (query.ContainsKey("autorotate"))
            {
                bool.TryParse(query["autorotate"], out resizeParams.autorotate);
            }

            int quality = 100;

            if (query.ContainsKey("quality"))
            {
                int.TryParse(query["quality"], out quality);
            }
            resizeParams.quality = quality;

            int w = 0;

            if (query.ContainsKey("w"))
            {
                int.TryParse(query["w"], out w);
            }
            resizeParams.w = w;

            int h = 0;

            if (query.ContainsKey("h"))
            {
                int.TryParse(query["h"], out h);
            }
            resizeParams.h = h;

            resizeParams.mode = "max";
            // only apply mode if it's a valid mode and both w and h are specified
            if (h != 0 && w != 0 && query.ContainsKey("mode") && ResizeParams.modes.Any(m => query["mode"] == m))
            {
                resizeParams.mode = query["mode"];
            }

            return(resizeParams);
        }
예제 #5
0
        private SKData GetImageData(string imagePath, ResizeParams resizeParams, DateTime lastWriteTimeUtc)
        {
            // check cache and return if cached
            long cacheKey;

            unchecked
            {
                cacheKey = imagePath.GetHashCode() + lastWriteTimeUtc.ToBinary() + resizeParams.ToString().GetHashCode();
            }

            SKData imageData;

            byte[] imageBytes;
            bool   isCached = _memoryCache.TryGetValue <byte[]>(cacheKey, out imageBytes);

            if (isCached)
            {
                _logger.LogInformation("Serving from cache");
                return(SKData.CreateCopy(imageBytes));
            }

            SKCodecOrigin origin;                                                    // this represents the EXIF orientation
            var           bitmap = LoadBitmap(File.OpenRead(imagePath), out origin); // always load as 32bit (to overcome issues with indexed color)

            // if autorotate = true, and origin isn't correct for the rotation, rotate it
            if (resizeParams.autorotate && origin != SKCodecOrigin.TopLeft)
            {
                bitmap = RotateAndFlip(bitmap, origin);
            }

            // if either w or h is 0, set it based on ratio of original image
            if (resizeParams.h == 0)
            {
                resizeParams.h = (int)Math.Round(bitmap.Height * (float)resizeParams.w / bitmap.Width);
            }
            else if (resizeParams.w == 0)
            {
                resizeParams.w = (int)Math.Round(bitmap.Width * (float)resizeParams.h / bitmap.Height);
            }

            // if we need to crop, crop the original before resizing
            if (resizeParams.mode == "crop")
            {
                bitmap = Crop(bitmap, resizeParams);
            }

            // store padded height and width
            var paddedHeight = resizeParams.h;
            var paddedWidth  = resizeParams.w;

            // if we need to pad, or max, set the height or width according to ratio
            if (resizeParams.mode == "pad" || resizeParams.mode == "max")
            {
                var bitmapRatio = (float)bitmap.Width / bitmap.Height;
                var resizeRatio = (float)resizeParams.w / resizeParams.h;

                if (bitmapRatio > resizeRatio) // original is more "landscape"
                {
                    resizeParams.h = (int)Math.Round(bitmap.Height * ((float)resizeParams.w / bitmap.Width));
                }
                else
                {
                    resizeParams.w = (int)Math.Round(bitmap.Width * ((float)resizeParams.h / bitmap.Height));
                }
            }

            // resize
            var resizedImageInfo = new SKImageInfo(resizeParams.w, resizeParams.h, SKImageInfo.PlatformColorType, bitmap.AlphaType);
            var resizedBitmap    = bitmap.Resize(resizedImageInfo, SKBitmapResizeMethod.Lanczos3);

            // optionally pad
            if (resizeParams.mode == "pad")
            {
                resizedBitmap = Pad(resizedBitmap, paddedWidth, paddedHeight, resizeParams.format != "png");
            }

            // encode
            var resizedImage = SKImage.FromBitmap(resizedBitmap);
            var encodeFormat = resizeParams.format == "png" ? SKEncodedImageFormat.Png : SKEncodedImageFormat.Jpeg;

            imageData = resizedImage.Encode(encodeFormat, resizeParams.quality);

            // cache the result
            _memoryCache.Set <byte[]>(cacheKey, imageData.ToArray());

            // cleanup
            resizedImage.Dispose();
            bitmap.Dispose();
            resizedBitmap.Dispose();

            return(imageData);
        }
예제 #6
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(ResizeParams obj)
 {
     return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr);
 }
예제 #7
0
 internal static SKBitmap WatermarkImage(SKBitmap original, ResizeParams resizeParams, WatermarkImageModel watermarkImage)
 {
     return(null);
 }
예제 #8
0
        private SKData GetImageData(string imagePath, ResizeParams resizeParams, DateTime lastWriteTimeUtc)
        {
            // check cache and return if cached
            string cacheKey;

            unchecked
            {
                cacheKey = "imgasc_" + imagePath.GetHashCode() + lastWriteTimeUtc.ToBinary() + resizeParams.ToString().GetHashCode();
            }

            SKData imageData;

            byte[] cacheData = _asyncCacheService.GetByKeyAsync <byte[]>(cacheKey).Result;
            if (cacheData != null)
            {
                return(SKData.CreateCopy(cacheData));
            }

            // this represents the EXIF orientation
            SKBitmap bitmap = LoadBitmap(File.OpenRead(imagePath), out SKEncodedOrigin origin); // always load as 32bit (to overcome issues with indexed color)

            // if autorotate = true, and origin isn't correct for the rotation, rotate it
            if (resizeParams.autorotate && origin != SKEncodedOrigin.TopLeft)
            {
                bitmap = RotateAndFlip(bitmap, origin);
            }

            // if either w or h is 0, set it based on ratio of original image
            if (resizeParams.h == 0)
            {
                resizeParams.h = (int)Math.Round(bitmap.Height * (float)resizeParams.w / bitmap.Width);
            }
            else if (resizeParams.w == 0)
            {
                resizeParams.w = (int)Math.Round(bitmap.Width * (float)resizeParams.h / bitmap.Height);
            }

            // if we need to crop, crop the original before resizing
            if (resizeParams.mode == "crop")
            {
                bitmap = Crop(bitmap, resizeParams);
            }

            // store padded height and width
            int paddedHeight = resizeParams.h;
            int paddedWidth  = resizeParams.w;

            // if we need to pad, or max, set the height or width according to ratio
            if (resizeParams.mode == "pad" || resizeParams.mode == "max")
            {
                float bitmapRatio = (float)bitmap.Width / bitmap.Height;
                float resizeRatio = (float)resizeParams.w / resizeParams.h;

                if (bitmapRatio > resizeRatio) // original is more "landscape"
                {
                    resizeParams.h = (int)Math.Round(bitmap.Height * ((float)resizeParams.w / bitmap.Width));
                }
                else
                {
                    resizeParams.w = (int)Math.Round(bitmap.Width * ((float)resizeParams.h / bitmap.Height));
                }
            }

            // resize
            SKImageInfo resizedImageInfo = new SKImageInfo(resizeParams.w, resizeParams.h, SKImageInfo.PlatformColorType, bitmap.AlphaType);
            SKBitmap    resizedBitmap    = bitmap.Resize(resizedImageInfo, SKFilterQuality.None);

            // optionally pad
            if (resizeParams.mode == "pad")
            {
                resizedBitmap = Pad(resizedBitmap, paddedWidth, paddedHeight, resizeParams.format != "png");
            }

            // encode
            SKImage resizedImage = SKImage.FromBitmap(resizedBitmap);
            SKEncodedImageFormat encodeFormat = resizeParams.format == "png" ? SKEncodedImageFormat.Png : SKEncodedImageFormat.Jpeg;

            imageData = resizedImage.Encode(encodeFormat, resizeParams.quality);

            // cache the result
            _asyncCacheService.SetValueAsync(cacheKey, imageData.ToArray());

            // cleanup
            resizedImage.Dispose();
            bitmap.Dispose();
            resizedBitmap.Dispose();

            return(imageData);
        }