예제 #1
0
        private static void CropImage(CustomRatio ratio, IMagickImage image)
        {
            var cropWidth  = Math.Abs(ratio.X2 - ratio.X1);
            var cropHeight = Math.Abs(ratio.Y2 - ratio.Y1);

            if (image.BaseWidth == cropWidth && image.BaseHeight == cropHeight) //requested image is same size
            {
                return;
            }

            var cropSize = new MagickGeometry(cropWidth, cropHeight)
            {
                IgnoreAspectRatio = false, //keep aspect ratio!
                FillArea          = false,
                X = ratio.X1,
                Y = ratio.Y1
            };

            image.Crop(cropSize);
        }
예제 #2
0
        public byte[] GetImageAsBytes(int requestWidth, int requestHeight, int quality, byte[] bytes, string options, out string mimeType, CustomRatio ratio = null)
        {
            if (!IsGif(bytes))
            {
                return(ProcessImage(requestWidth, requestHeight, quality, bytes, options, ratio, out mimeType));
            }

            mimeType = "image/gif";
            return(ProcessGif(requestWidth, requestHeight, quality, bytes, options));
        }
예제 #3
0
        private static byte[] ProcessImage(int requestWidth, int requestHeight, int quality, byte[] bytes, string options, CustomRatio ratio, out string mimeType)
        {
            if (ratio != null)
            {
                using (MagickImage image = new MagickImage(bytes))
                {
                    CropImage(ratio, image);

                    bytes = image.ToByteArray();
                }
            }

            using (MagickImage image = new MagickImage(bytes))
            {
                ResizeImage(requestWidth, requestHeight, quality, options, image);

                // return the result
                if (image.HasAlpha)
                {
                    mimeType = "image/png";
                    bytes    = image.ToByteArray(MagickFormat.Png);
                }
                else
                {
                    mimeType = "image/jpeg";
                    bytes    = image.ToByteArray(MagickFormat.Pjpeg);
                }
            }

            return(bytes);
        }
예제 #4
0
        private async Task <IActionResult> ImageResult(string id, string slug, int w = 0, int h = 0, int quality = 100, string options = "", string hash = "")
        {
            if (string.IsNullOrWhiteSpace(id))
            {
                _logger.LogError("Id is null");
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }

            if (0 > w || 0 > h)
            {
                _logger.LogError("Width or height is negative");
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }

            byte[]      bytes;
            CustomRatio customRatio = null;

            try
            {
                var host = _fileService.GetHostConfig(slug);

                if (host.WhiteList != null && host.WhiteList.Any() && host.WhiteList.All(x => x != $"{w}x{h}")) //whitelist checking
                {
                    _logger.LogError("Image request cancelled due to whitelist.");
                    return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
                }

                if (w != 0 && h != 0 && !string.IsNullOrEmpty(hash) && host.Type == HostType.GridFs) //customratio & mongodb file
                {
                    var metadata = await _metadataService.GetFileMetadataAsync(host, id);

                    var ratio = (double)w / h; //image request ratio

                    customRatio = double.IsNaN(ratio)
                        ? metadata.CustomRatio.FirstOrDefault(x => x.Hash == hash)
                        : metadata.CustomRatio.FirstOrDefault(x => x.MinRatio < ratio && x.MaxRatio >= ratio);

                    if (customRatio == null) // request with hash but no customratio
                    {
                        _logger.LogError(
                            "Image request redirected due to wrong custom ratio hash (redirected to base url)");
                        return(Redirect(string.IsNullOrEmpty(options)
                            ? $"/i/{slug}/{quality}/{w}x{h}/{id}"
                            : $"/i/{slug}/{quality}/{w}x{h}/{options}/{id}"));
                    }

                    if (!double.IsNaN(ratio) && customRatio.Hash != hash) //hash is not correct
                    {
                        _logger.LogError(
                            "Image request redirected due to wrong custom ratio hash (redirected to new customRatio)");
                        return(Redirect(string.IsNullOrEmpty(options)
                            ? $"/i/{slug}/{quality}/{w}x{h}/h-{customRatio.Hash}/{id}"
                            : $"/i/{slug}/{quality}/{w}x{h}/{options}/h-{customRatio.Hash}/{id}"));
                    }
                }

                bytes = await _fileService.GetFileAsync(slug, id);

                if (bytes == null)
                {
                    _logger.LogError("File not found");
                    return(NotFound());
                }
            }
            catch (RedirectToFallbackException e)
            {
                _logger.LogWarning(e, e.Message);
                return(Redirect(string.IsNullOrEmpty(options)
                    ? $"/i/{slug}/{quality}/{w}x{h}/{e.FallbackImage}"
                    : $"/i/{slug}/{quality}/{w}x{h}/{options}/{e.FallbackImage}"));
            }
            catch (SlugNotFoundException e)
            {
                _logger.LogError(e, e.Message);
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }
            catch (GridFsObjectIdException e)
            {
                _logger.LogError(e, "GridFS ObjectId Parse Error:" + e.Message);
                return(new StatusCodeResult((int)HttpStatusCode.BadRequest));
            }
            catch (TimeoutException e)
            {
                _logger.LogError(e, "Timeout: " + e.Message);
                return(new StatusCodeResult((int)HttpStatusCode.GatewayTimeout));
            }
            catch (Exception e)
            {
                _logger.LogError(e, e.Message);
                throw;
            }

            try
            {
                bytes = _imageService.GetImageAsBytes(w, h, quality, bytes, options, out var mime, customRatio);

                if (bytes != null)
                {
                    return(File(bytes, mime));
                }

                _logger.LogError("File found but image operation failed by unknown cause");
                return(StatusCode((int)HttpStatusCode.NotAcceptable));
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Image Service Error: " + e.Message);
                throw;
            }
        }