Пример #1
0
        public static PiczOptions Load()
        {
            // Defaults
            var options = new PiczOptions
            {
                Route = "picz",
                Sizes = new List <int> {
                    4000, 2500, 1024, 640, 320
                },
                BackgroundAdjustmentPercent = 10,
                CacheDurationHours          = 48,
                Quality = 90
            };

            // Mandatory Config
            options.CacheRootPath = Config("PiczCachePath");

            // Optional Config
            var configRoute = Config("PiczRoute");

            if (!string.IsNullOrWhiteSpace(configRoute))
            {
                options.Route = configRoute;
            }

            var configSizes = Config("PiczSizes");

            if (!string.IsNullOrWhiteSpace(configSizes))
            {
                options.Sizes = configSizes.Split(',').Select(s => int.Parse(s)).ToList();
            }

            var configBackgroundPercent = Config("PiczBackgroundAdjustmentPercent");

            if (!string.IsNullOrWhiteSpace(configBackgroundPercent))
            {
                options.BackgroundAdjustmentPercent = int.Parse(configBackgroundPercent);
            }

            var configDuration = Config("PiczCacheDurationHours");

            if (!string.IsNullOrWhiteSpace(configDuration))
            {
                options.CacheDurationHours = int.Parse(configDuration);
            }

            var configQuality = Config("PiczQuality");

            if (!string.IsNullOrWhiteSpace(configQuality))
            {
                options.Quality = int.Parse(configQuality);
            }

            return(options);
        }
Пример #2
0
        private static int ConstrainSize(int size, PiczOptions options)
        {
            // Important!
            // This prevents random sizes being requested, which would take up infinitely more
            // disk space than predicted - this method constrains the size to one of the configured
            // values.
            if (!options.Sizes.Contains(size))
            {
                size = options.Sizes.OrderBy(item => Math.Abs(size - item)).First();
            }

            return(size);
        }
Пример #3
0
        private static ISupportedImageFormat GetFormat(ReplacementImage replacement, PiczOptions options)
        {
            switch (replacement.MimeType)
            {
            case "image/png":
                return(new PngFormat {
                    Quality = options.Quality
                });

            case "image/gif":
                return(new GifFormat {
                    Quality = options.Quality
                });

            default:
                return(new JpegFormat {
                    Quality = options.Quality
                });
            }
        }
Пример #4
0
        private void Resize(int width, ReplacementImage replacement, byte[] photoBytes, PiczOptions options)
        {
            using (var inStream = new MemoryStream(photoBytes))
                using (var fileStream = new FileStream(replacement.Path, FileMode.Create, FileAccess.Write))
                    using (var imageFactory = new ImageFactory())
                    {
                        // No upscaling! No point creating images larger than the original
                        using (var image = Image.FromStream(inStream))
                        {
                            if (image.Width < width)
                            {
                                width = image.Width;
                            }
                        }

                        inStream.Position = 0;

                        var size = new Size(width, 0);

                        // Load, resize, set the format and quality and save an image.
                        imageFactory
                        .Load(inStream)
                        .Resize(size)
                        .Format(GetFormat(replacement, options))
                        .Quality(options.Quality)
                        .Save(fileStream);

                        fileStream.Close();
                        inStream.Close();
                    }
        }
Пример #5
0
        private void Resize(int width, ReplacementImage replacement, string originalPath, PiczOptions options)
        {
            byte[] photoBytes;
            using (var webClient = new WebClient())
            {
                photoBytes = webClient.DownloadData(originalPath);
            }

            Resize(width, replacement, photoBytes, options);
        }
Пример #6
0
        public ReplacementImage GetReplacementImage(int size, string originalUrl, string hash, Func <byte[]> getImage = null, Func <string> checkHash = null)
        {
            // Configuration values
            var options = PiczOptions.Load();
            var hasHash = HasHashCode(hash);

            size = ConstrainSize(size, options);

            // Create a cache folder that includes the image size
            var cacheFolderPath = Path.Combine(options.CacheRootPath, size.ToString());

            ReplacementImage replacement = null;

            if (hasHash)
            {
                cacheFolderPath = Path.Combine(cacheFolderPath, "hashvalidated");

                replacement = GetSafeNamedImage(hash, originalUrl, cacheFolderPath);

                var fileInfo = new FileInfo(replacement.Path);

                // Cache Miss - chance the hash has been fiddled so double check it if a validator is supplied
                if (!fileInfo.Exists && checkHash != null)
                {
                    var checkedHash = checkHash();

                    if (checkedHash != hash)
                    {
                        // Ah - the hash is not right, so let's try again with the correct one
                        // this stops us from creating lots of copies of the same image every time
                        // a robot sends a different hash
                        hash        = checkedHash;
                        replacement = GetSafeNamedImage(hash, originalUrl, cacheFolderPath);
                        fileInfo    = new FileInfo(replacement.Path);
                    }
                }

                if (fileInfo.Exists)
                {
                    return(replacement);
                }
            }
            else
            {
                replacement = GetSafeNamedImage(hash, originalUrl, cacheFolderPath);

                var fileInfo = new FileInfo(replacement.Path);

                if (fileInfo.Exists)
                {
                    if (fileInfo.LastWriteTimeUtc.AddHours(options.CacheDurationHours) > DateTime.UtcNow)
                    {
                        // If no hash is supplied, check the file is new enough to use
                        return(replacement);
                    }
                }
            }

            // Create image
            Directory.CreateDirectory(cacheFolderPath);

            if (getImage == null)
            {
                Resize(size, replacement, originalUrl, options);
            }
            else
            {
                Resize(size, replacement, getImage(), options);
            }

            return(replacement);
        }