{"id":22206736,"url":"https://github.com/usercode/imagewizard","last_synced_at":"2025-04-07T15:09:46.735Z","repository":{"id":37431035,"uuid":"190033467","full_name":"usercode/ImageWizard","owner":"usercode","description":"Image processing webservice based on ASP.NET Core and ImageSharp / SkiaSharp / SvgNet / DocNET","archived":false,"fork":false,"pushed_at":"2024-07-26T22:52:47.000Z","size":5028,"stargazers_count":67,"open_issues_count":0,"forks_count":11,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-08-25T12:05:18.542Z","etag":null,"topics":["c-sharp","image-manipulation","image-processing","image-processor","imageproxy","pdf","thumbnail-generator"],"latest_commit_sha":null,"homepage":"https://imagewizard.net/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/usercode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-03T15:34:13.000Z","updated_at":"2024-07-26T20:54:25.000Z","dependencies_parsed_at":"2024-04-12T06:31:19.145Z","dependency_job_id":"312b1355-52a0-48ac-ba5c-3413b4672184","html_url":"https://github.com/usercode/ImageWizard","commit_stats":{"total_commits":433,"total_committers":2,"mean_commits":216.5,"dds":0.004618937644341847,"last_synced_commit":"d2024c8b82b05738cff642c700c2d27fe6e4df4e"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usercode%2FImageWizard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usercode%2FImageWizard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usercode%2FImageWizard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/usercode%2FImageWizard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/usercode","download_url":"https://codeload.github.com/usercode/ImageWizard/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247675607,"owners_count":20977377,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-sharp","image-manipulation","image-processing","image-processor","imageproxy","pdf","thumbnail-generator"],"created_at":"2024-12-02T18:17:45.594Z","updated_at":"2025-04-07T15:09:46.714Z","avatar_url":"https://github.com/usercode.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ImageWizard\nA ASP.NET Core service / middleware to resize your images on the fly as alternative for thumbor.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)\n[![NuGet](https://img.shields.io/nuget/v/ImageWizard.Core.svg?style=flat-square)](https://www.nuget.org/packages/ImageWizard.Core/)\n[![Docker](https://img.shields.io/docker/pulls/usercode/imagewizard?style=flat-square)](https://hub.docker.com/r/usercode/imagewizard)\n\nDemo: [imagewizard.net](https://imagewizard.net)\n\n## Features\n- loader:\n\t- Http (streaming mode)\n\t- File (use IFileProvider)\n\t- YouTube (get thumbnail)\n\t- Gravatar\n\t- OpenGraph\n- caches:\n\t-  File\n\t-  Distributed cache\n\t-  MongoDB\n- image filters: resize, crop, rotate,..\n- common image effects like grayscale and blur are available \n- create your custom data filter\n- pdf filters: page-to-image for documents\n- url is protected by a HMACSHA256 signature to prevent DDoS attacks\n- can handle the device pixel ratio (DPR)\n- support for cache control and ETag\n- enable range processing by http request\n- use RecyclableMemoryStream for smarter memory management (IStreamPool)\n- cleanup service\n\n## Example\n\nhttps://localhost/image/cGiAwFYGYWx0SzO0YyCidWIfkdlUYrVgBwbm7bcTOjE/resize(200,200)/grayscale()/jpg(90)/fetch/https://upload.wikimedia.org/wikipedia/commons/b/b7/Europe_topography_map.png\n\n| Description         | Url segment |\n|---------------------------------|-----------------|\n| base path                       | \"image\" | \n| signature based on HMACSHA256   | \"cGiAwFYGYWx0SzO0YyCidWIfkdlUYrVgBwbm7bcTOjE\" or \"unsafe\" (if enabled) |\n| any filters                     | \"resize(200,200)/grayscale()/jpg(90)\" |\n| loader type                     | \"fetch\" |\n| loader source                   | https://upload.wikimedia.org/wikipedia/commons/b/b7/Europe_topography_map.png | \n\n## Loader\n| Name                | Loader type | Loader source | NuGet |\n|-----------------------------------|-----------------|----|---|\n| Http loader        | fetch       | absolute or relative url |  [![NuGet](https://img.shields.io/nuget/v/ImageWizard.Core.svg)](https://www.nuget.org/packages/ImageWizard.Core/) \n| File loader         | file        | relative path to file   | [![NuGet](https://img.shields.io/nuget/v/ImageWizard.Core.svg)](https://www.nuget.org/packages/ImageWizard.Core/) \n| YouTube loader      | youtube     | video id                | [![NuGet](https://img.shields.io/nuget/v/ImageWizard.Core.svg)](https://www.nuget.org/packages/ImageWizard.Core/)\n| Gravatar loader     | gravatar    | encoded email address   | [![NuGet](https://img.shields.io/nuget/v/ImageWizard.Core.svg)](https://www.nuget.org/packages/ImageWizard.Core/)\n| OpenGraph loader     | opengraph  | absolute url   | [![NuGet](https://img.shields.io/nuget/v/ImageWizard.OpenGraph.svg)](https://www.nuget.org/packages/ImageWizard.OpenGraph/)\n| Azure loader       | azure       | relative path to file   | [![NuGet](https://img.shields.io/nuget/v/ImageWizard.Azure.svg)](https://www.nuget.org/packages/ImageWizard.Azure/)\n| PuppeteerSharp loader  | screenshot  | absolute url   | [![NuGet](https://img.shields.io/nuget/v/ImageWizard.PuppeteerSharp.svg)](https://www.nuget.org/packages/ImageWizard.PuppeteerSharp/)\n\n## Cache\n| Name                 | Description        | NuGet     |\n|----------------------|--------------------|-----------|\n|  File cache         |  Meta and blob file path based on cache id.  |  [![NuGet](https://img.shields.io/nuget/v/ImageWizard.Core.svg)](https://www.nuget.org/packages/ImageWizard.Core/)  |\n|  Distributed cache   | MS SQL, Redis      |  [![NuGet](https://img.shields.io/nuget/v/ImageWizard.Core.svg)](https://www.nuget.org/packages/ImageWizard.Core/)  |\n|  MongoDB cache       | Use GridFS |  [![NuGet](https://img.shields.io/nuget/v/ImageWizard.MongoDB.svg)](https://www.nuget.org/packages/ImageWizard.MongoDB/) |\n\n## Pipeline\n\n| Name  |  Mime type | NuGet |\n|------------------------------------|-----------------|------------|\n| ImageSharp | image/jpeg, image/png, image/gif, image/bmp, image/webp, image/tga |  [![NuGet](https://img.shields.io/nuget/v/ImageWizard.ImageSharp.svg)](https://www.nuget.org/packages/ImageWizard.ImageSharp/)\n| SkiaSharp  | image/jpeg, image/png, image/gif, image/bmp, image/webp  | [![NuGet](https://img.shields.io/nuget/v/ImageWizard.SkiaSharp.svg)](https://www.nuget.org/packages/ImageWizard.SkiaSharp/)\n| SvgNet     | image/svg+xml | [![NuGet](https://img.shields.io/nuget/v/ImageWizard.SvgNet.svg)](https://www.nuget.org/packages/ImageWizard.SvgNet/)\n| DocNET     | application/pdf | [![NuGet](https://img.shields.io/nuget/v/ImageWizard.DocNET.svg)](https://www.nuget.org/packages/ImageWizard.DocNET/)\n\n## How to use it\n\n```csharp\nservices.AddImageWizard();\n\n//or\n\nservices.AddImageWizard(options =\u003e \n                       {\n                           options.AllowUnsafeUrl = true;\n                           options.AllowedDPR = new double[] { 1.0, 1.5, 2.0, 3.0, 4.0 };\n                           options.Key = new byte[64] { .. };\n                           options.UseETag = true;                                                \n                           options.CacheControl.IsEnabled = true;\n                           options.CacheControl.MaxAge = TimeSpan.FromDays(365);\n                           options.CacheControl.MustRevalidate = false;\n                           options.CacheControl.Public = true;\n                           options.CacheControl.NoCache = false;\n                           options.CacheControl.NoStore = false;\n                           //select automatically the compatible mime type by request header\n                           options.UseAcceptHeader = true;\n\t\t\t   options.RefreshLastAccessInterval = TimeSpan.FromMinutes(1);\n\t\t\t   options.FallbackHandler = (state, url, cachedData) =\u003e\n\t\t\t    {\n\t\t\t\t//use the existing cached data if available?\n\t\t\t\tif (cachedData != null)\n\t\t\t\t{\n\t\t\t\t    return cachedData;\n\t\t\t\t}\n\n\t\t\t\t//load fallback image\n\t\t\t\tFileInfo fallbackImage = state switch\n\t\t\t\t{\n\t\t\t\t    LoaderResultState.NotFound =\u003e new FileInfo(@\"notfound.jpg\"),\n\t\t\t\t    LoaderResultState.Failed =\u003e new FileInfo(@\"failed.jpg\"),\n\t\t\t\t   _ =\u003e throw new Exception()\n\t\t\t\t};\n\n\t\t\t\tif (fallbackImage.Exists == false)\n\t\t\t\t{\n\t\t\t\t    return null;\n\t\t\t\t}\n\n\t\t\t\t//convert FileInfo to CachedData\n\t\t\t\treturn fallbackImage.ToCachedData();\n\t\t\t    };\n                       })\n            //registers ImageSharp pipeline for specified mime types\n           .AddImageSharp(c =\u003e c\n                .WithMimeTypes(MimeTypes.WebP, MimeTypes.Jpeg, MimeTypes.Png, MimeTypes.Gif)\n                .WithOptions(x =\u003e\n                            {\n                                x.ImageMaxHeight = 4000;\n                                x.ImageMaxWidth = 4000;\n                            })\n                //Adds your custom filters\n                .WithFilter\u003cBlurFilter\u003e()\n\t\t//Executes custom action before the pipeline is started.\n                .WithPreProcessing(x =\u003e\n                            {\n                                x.Image.Mutate(m =\u003e m.AutoOrient());\n                            })\n\t\t//Executes custom action after the pipeline is finished.\n                .WithPostProcessing(x =\u003e\n                            {\n\t\t\t    \t//blurs all images\n                                x.Image.Mutate(m =\u003e m.Blur());\n                              \n                                //overrides target format (Jpeg to WebP)\n\t\t\t\tif (x.ImageFormat is JpegFormat)\n\t\t\t\t{\n                                    x.ImageFormat = new WebPFormat() { Lossless = false };\n\t\t\t\t}\n\t\t\t\t//overrides target format (Png to WebP)\n\t\t\t\telse if (x.ImageFormat is PngFormat)\n\t\t\t\t{\n                                    x.ImageFormat = new WebPFormat() { Lossless = true };\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t//overrides metadata\n\t\t\t\tx.Image.Metadata.ExifProfile = new ExifProfile();\n                        \tx.Image.Metadata.ExifProfile.SetValue(ExifTag.Copyright, \"ImageWizard\");\n                            }))\n           //.AddSkiaSharp()\n           .AddSvgNet()\n\t   .AddDocNET()\n           //uses file cache (relative or absolute path)\n           .SetFileCache(options =\u003e options.Folder = \"FileCache\") \n           //or MongoDB cache\n           .SetMongoDBCache(options =\u003e options.Hostname = \"localhost\")\n           //or distributed cache\n           .SetDistributedCache()\n           //adds some loaders\n           .AddFileLoader(options =\u003e options.Folder = \"FileStorage\")\n           .AddHttpLoader(options =\u003e \n          \t{\n\t\t   //checks every time for a new version of the original image.\n\t\t   options.RefreshMode = LoaderRefreshMode.EveryTime;\n\n\t\t   //sets base url for relative urls\n\t\t   options.DefaultBaseUrl = \"https://mydomain\";\n\n\t\t   //allows only relative urls \n\t\t   //(use base url from request or DefaultBaseUrl from options)\n\t\t   options.AllowAbsoluteUrls = false;\n\n\t\t   //allows only specified hosts\n\t\t   options.AllowedHosts = new [] { \"mydomain\" };\n\n\t\t   //adds custom http header like apikey to prevent \n\t\t   //that user can download the original image\n\t\t   options.SetHeader(\"ApiKey\", \"123456\");\n     \t\t})\n           .AddYoutubeLoader()\n           .AddGravatarLoader()\n\t   .AddOpenGraphLoader()\n           .AddAnalytics()\n\t    //Adds a background service which removes cached data based on defined CleanupReason.\n            //The cache needs to implements ICleanupCache.\n            .AddCleanupService(x =\u003e\n\t\t    {\n\t\t\t//Duration between the cleanup actions. (Default: 1 day)\n\t\t\tx.Interval = TimeSpan.FromMinutes(1);\n\n\t\t\t//Removes cached data which are older than defined duration. \n\t\t\tx.OlderThan(TimeSpan.FromMinutes(2));\n\n\t\t\t//Removes cached data which are last used since defined duration. \n\t\t\tx.LastUsedSince(TimeSpan.FromMinutes(2));\n\n\t\t\t//Removes cached data which are expired (based on the loader result).\n\t\t\tx.Expired();\n\t\t    })\n           ;\n```\n\n```csharp\n//default path (\"/image\")\n\n//use middleware\napp.UseImageWizard(x =\u003e\n\t\t{\n\t\t\t//default path  (\"/analytics\")\n\t\t\tx.MapAnalytics();\n\t\t});\n\n//or use endpoint\napp.Endpoints(e =\u003e e.MapImageWizard(\"/image\"));\n\n```\n\n## Internal services\n- ICacheKey\n- ICacheHash\n- ICacheLock\n- IUrlSignature\n- IStreamPool\n\n## Create custom filter\n\n- add ImageWizard.Generator package to project\n- add a public method which is marked with the filter attribute\n  - at url level are the following types possible for method overloading: \n    - integer (\"0\")\n    - floating-point number (\"0.0\")\n    - bool (\"True\" or \"False\")\n    - enum (value)\n    - string ('Hello')\n\n```csharp\npublic partial class BackgroundColorFilter : ImageSharpFilter\n{\n    //use dependency injection\n    public BackgroundColorFilter(ILogger\u003cBackgroundColorFilter\u003e logger)\n    {\n       //...\n    }\n\n    [Filter]\n    public void BackgroundColor(byte r, byte g, byte b)\n    {\n        Context.Image.Mutate(m =\u003e m.BackgroundColor(new Rgba32(r, g, b)));\n    }\n\n    [Filter]\n    public void BackgroundColor(float r, float g, float b)\n    {\n        Context.Image.Mutate(m =\u003e m.BackgroundColor(new Rgba32(r, g, b)));\n    }\n}\n```\n\nThe source generator creates the following code:\n\n```csharp\npublic partial class BackgroundColorFilter : IFilterFactory\n{\n    public static IEnumerable\u003cIFilterAction\u003e Create()\n    {\n        return [ \n        new FilterAction\u003cBackgroundColorFilter\u003e(\"backgroundcolor\", new Regex(@\"^\\((?\u003cr\u003e-?\\d+),(?\u003cg\u003e-?\\d+),(?\u003cb\u003e-?\\d+)\\)$\"), (filter, group) =\u003e { byte r = byte.Parse(group[\"r\"].ValueSpan, CultureInfo.InvariantCulture);byte g = byte.Parse(group[\"g\"].ValueSpan, CultureInfo.InvariantCulture);byte b = byte.Parse(group[\"b\"].ValueSpan, CultureInfo.InvariantCulture);filter.BackgroundColor(r,g,b); }),       \n        new FilterAction\u003cBackgroundColorFilter\u003e(\"backgroundcolor\", new Regex(@\"^\\((?\u003cr\u003e-?\\d+\\.\\d+),(?\u003cg\u003e-?\\d+\\.\\d+),(?\u003cb\u003e-?\\d+\\.\\d+)\\)$\"), (filter, group) =\u003e { float r = float.Parse(group[\"r\"].ValueSpan, CultureInfo.InvariantCulture);float g = float.Parse(group[\"g\"].ValueSpan, CultureInfo.InvariantCulture);float b = float.Parse(group[\"b\"].ValueSpan, CultureInfo.InvariantCulture);filter.BackgroundColor(r,g,b); }),       \n        ];\n    }\n}\n```\n\nRegister filter:\n\n```csharp\nservices.AddImageWizard()\n\t.AddImageSharp(c =\u003e c.WithFilter\u003cBackgroundColorFilter\u003e());\n```\n\nURL segments: \n\n```csharp\n\"/backgroundcolor(255,255,255)/\"\n\"/backgroundcolor(1.0,1.0,1.0)/\"\n```\n\n### How to use the DPR (device pixel ratio) attribute\n\n- use dpr filter to set the value or enable the client hints\n- all parameter with DPR attribute will be multiplied by the DPR factor\n\n```csharp\n public class ResizeFilter : ImageSharpFilter\n {\n      [Filter]\n      public void Resize([DPR]int width, [DPR]int height)\n      {\n          Context.Image.Mutate(m =\u003e m.Resize(width, height));\n      }\n }\n```\n\nURL segment: \n```csharp\n\"/dpr(2.0)/resize(200,100)/\"             //calls resize filter with the resolution 400 x 200\nor \n\"/resize(200,100)/\" + client hints  \n```\nResponse header:\n```csharp\nContent-DPR: 2\n```\n\n### How to use optional parameters\n\n- use rather method overloading if possible\n- if all parameter have default values you can set all parameters by name\n\nExample:\n\n```csharp\n public class TextFilter : ImageSharpFilter\n {\n      [Filter]\n      public void DrawText(int x = 0, int y = 0, string text = \"\", int size = 12, string font = \"Arial\")\n      {\n          Context.Image.Mutate(m =\u003e\n          {\n              m.DrawText(\n                  text,\n                  new Font(SystemFonts.Find(font), size),\n                  Rgba32.Black,\n                  new PointF(x, y));\n          });\n      }\n }\n```\n\nURL segment: \n```csharp\n\"/drawtext(text='Hello',x=10,y=20)/\"\n```\n\n## ASP.NET Core UrlBuilder\n\nhttps://www.nuget.org/packages/ImageWizard.Client/\n\nExample:\n\nAdd settings to the appsettings.json\n\n```json\n \"ImageWizard\": {\n    \"BaseUrl\": \"https://\u003cyour-domain\u003e/image\",\n    \"Key\": \"DEMO-KEY---PLEASE-CHANGE-THIS-KEY---PLEASE-CHANGE-THIS-KEY---PLEASE-CHANGE-THIS-KEY---==\",\n    \"Enabled\": true\n  }\n```\n\nRegister settings to services\n\n```csharp\nservices.Configure\u003cImageWizardClientSettings\u003e(Configuration.GetSection(\"ImageWizard\"));\n\nservices.AddImageWizardClient();\n\n//or\n\nservices.AddImageWizardClient(options =\u003e \n{\n    options.BaseUrl = \"https://\u003cyour-domain\u003e/image\";\n    options.Key = \"..\";\n    options.Enabled = true;\n    options.UseUnsafeUrl = false;\n});\n```\nCreate url with fluent api\n\n```csharp\n@Url\n.ImageWizard()\n//use HTTP loader\n.Fetch(\"https://\u003cyour-domain\u003e/test/picture.jpg\")\n//fetch local file from wwwroot folder (with fingerprint)\n.FetchLocal(\"picture.jpg\")\n//or file loader\n.File(\"test/picture.jpg\")\n//or azure\n.Azure(\"image.jpg\")\n.AsImage()\n.Resize(160,140,ResizeMode.Max)\n.Blur()\n.Grayscale()\n.Jpg(90)\n.BuildUrl()\n```\n\nUse dependency injection\n```csharp\n@IImageWizardUrlBuilder UrlBuilder\n\n\u003cimg src=\"@UrlBuilder.FetchLocalFile(\"picture.jpg\").AsImage().Resize(400, 200, ResizeMode.Max).Grayscale().BuildUrl()\" /\u003e\n```\n\nUse IUrlHelper\n```csharp\n\u003cimg src=\"@Url.ImageWizard().FetchLocalFile(\"picture.jpg\").AsImage().Resize(400, 200, ResizeMode.Max).Grayscale().BuildUrl()\" /\u003e\n```\n\n## Processing pipelines\n### ImageSharp\n#### Image transformations\n- resize(size)\n- resize(width,height)\n- resize(width,height,mode)\n  - mode: min, max, crop, pad, stretch\n- resize(width,height,mode,anchor)\n  - anchor: center, top, bottom, left, right, topleft, topright, bottomleft, bottomright\n- crop(width,height)\n  - int for absolute values, 0.0 to 1.0 for relative values\n- crop(x,y,width,height)\n  - int for absolute values, 0.0 to 1.0 for relative values\n- backgroundcolor(r,g,b)\n  - int (0 to 255) or float (0.0 to 1.0)\n- backgroundcolor(r,g,b,a)\n  - int (0 to 255) or float (0.0 to 1.0)\n- flip(type)\n  - type: horizontal, vertical\n- rotate(value) \n  - value: 90, 180 or 270\n- grayscale()\n- grayscale(amount)\n  - amount: 0.0 to 1.0\n- blackwhite()\n- blur()\n- invert()\n- brightness(value)\n- contrast(value)\n- autoorient()\n- drawtext(text='Hello',size=24,x=0.5,y=0.5)\n  - string: raw ('Hello') or base64url (SGVsbG8)\n\n#### Output formats\n- jpg()\n- jpg(quality)\n- png()\n- gif()\n- tga()\n- bmp()\n- webp()\n- webp(quality)\n\n#### Special options\n- dpr(value) //set allowed device pixel ratio\n\n### SkiaSharp\n#### Image transformations\n- resize(width,height)\n- resize(width,height,mode)\n  - mode: min, max, crop, pad, stretch\n- crop(width,height)\n  - 0.0 to 1.0 for relative values\n- crop(x,y,width,height)\n  - 0.0 to 1.0 for relative values\n- flip(type)\n  - type: horizontal, vertical\n- rotate(value)\n  - value: 0.0 to 360.0\n- grayscale()\n- blur()\n- blur(radius)\n- drawtext(text='Hello',size=24,x=0.5,y=0.5)\n  - string: raw ('Hello') or base64url (SGVsbG8)\n  \n#### Output formats\n- jpg()\n- jpg(quality)\n- png()\n- gif()\n- bmp()\n- webp()\n\n### DocNET\n#### DocNET transformations\n- pagetoimage(pageindex)\n- pagetoimage(pageindex,width,height)\n- subpages(pageFromIndex, pageToIndex)\n\n### SvgNet\n#### SVG transformations\n- removesize()\n- blur()\n- blur(deviation)\n  - value: float\n- rotate(angle)\n  - value: float\n\n\n## Plugin for Piranha CMS 8.0\n\nImageWizard.Piranha [![NuGet](https://img.shields.io/nuget/v/ImageWizard.Piranha.svg)](https://www.nuget.org/packages/ImageWizard.Piranha/)\n\nUseful to resize imagefields.\n\n```csharp\n\u003cimg src=\"@Url.ImageWizard().Fetch(Model.Body).Resize(900,900).Grayscale().Blur().BuildUrl()\"\u003e\n```\n\n## Docker \n[![Docker](https://img.shields.io/docker/pulls/usercode/imagewizard)](https://hub.docker.com/r/usercode/imagewizard)\n\n```yml\nstatic:\n    image: usercode/imagewizard\n    container_name: imagewizard\n    restart: always\n    networks:\n      - default      \n    volumes:\n      - file_cache:/data\n    environment:\n      - General__Key=DEMO+KEY+++PLEASE+CHANGE+THIS+KEY+++PLEASE+CHANGE+THIS+KEY+++PLEASE+CHANGE+THIS+KEY+++==\n      - General__AllowUnsafeUrl=false\n      - General__UseAcceptHeader=false\n      - General__UseETag=true\n      - General__AllowedDPR__0=1.0\n      - General__AllowedDPR__1=1.5\n      - General__AllowedDPR__2=2.0\n      - General__AllowedDPR__3=3.0\n      - General__CacheControl__IsEnabled=true\n      - General__CacheControl__Public=true\n      - General__CacheControl__MaxAge=60\n      - General__CacheControl__MustRevalidate=false\n      - General__CacheControl__NoCache=false\n      - General__CacheControl__NoStore=false      \n      - FileCache__Folder=/cache\n      - FileLoader__Folder=/data\n      - HttpLoader__DefaultBaseUrl=https://domain.tld\n      - HttpLoader__AllowAbsoluteUrls=false\n      - HttpLoader__AllowedHosts__0=domain.tld\n      - HttpLoader__Headers__0__Name=ApiKey\n      - HttpLoader__Headers__0__Value=123      \n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusercode%2Fimagewizard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fusercode%2Fimagewizard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fusercode%2Fimagewizard/lists"}