ImageWizard
Image processing webservice based on ASP.NET Core and ImageSharp / SkiaSharp / SvgNet / DocNET
Install / Use
/learn @usercode/ImageWizardREADME
ImageWizard
A ASP.NET Core service / middleware to resize your images on the fly as alternative for thumbor.
Demo: imagewizard.net
Features
- loader:
- Http (streaming mode)
- File (use IFileProvider)
- YouTube (get thumbnail)
- Gravatar
- OpenGraph
- caches:
- File
- Distributed cache
- MongoDB
- image filters: resize, crop, rotate,..
- common image effects like grayscale and blur are available
- create your custom data filter
- pdf filters: page-to-image for documents
- url is protected by a HMACSHA256 signature to prevent DDoS attacks
- can handle the device pixel ratio (DPR)
- support for cache control and ETag
- enable range processing by http request
- use RecyclableMemoryStream for smarter memory management (IStreamPool)
- cleanup service
Example
https://localhost/image/cGiAwFYGYWx0SzO0YyCidWIfkdlUYrVgBwbm7bcTOjE/resize(200,200)/grayscale()/jpg(90)/fetch/https://upload.wikimedia.org/wikipedia/commons/b/b7/Europe_topography_map.png
| Description | Url segment | |---------------------------------|-----------------| | base path | "image" | | signature based on HMACSHA256 | "cGiAwFYGYWx0SzO0YyCidWIfkdlUYrVgBwbm7bcTOjE" or "unsafe" (if enabled) | | any filters | "resize(200,200)/grayscale()/jpg(90)" | | loader type | "fetch" | | loader source | https://upload.wikimedia.org/wikipedia/commons/b/b7/Europe_topography_map.png |
Loader
| Name | Loader type | Loader source | NuGet |
|-----------------------------------|-----------------|----|---|
| Http loader | fetch | absolute or relative url |
| File loader | file | relative path to file |
| YouTube loader | youtube | video id |
| Gravatar loader | gravatar | encoded email address |
| OpenGraph loader | opengraph | absolute url |
| Azure loader | azure | relative path to file |
| PuppeteerSharp loader | screenshot | absolute url |
Cache
| Name | Description | NuGet |
|----------------------|--------------------|-----------|
| File cache | Meta and blob file path based on cache id. | |
| Distributed cache | MS SQL, Redis |
|
| MongoDB cache | Use GridFS |
|
Pipeline
| Name | Mime type | NuGet |
|------------------------------------|-----------------|------------|
| ImageSharp | image/jpeg, image/png, image/gif, image/bmp, image/webp, image/tga |
| SkiaSharp | image/jpeg, image/png, image/gif, image/bmp, image/webp |
| SvgNet | image/svg+xml |
| DocNET | application/pdf |
How to use it
services.AddImageWizard();
//or
services.AddImageWizard(options =>
{
options.AllowUnsafeUrl = true;
options.AllowedDPR = new double[] { 1.0, 1.5, 2.0, 3.0, 4.0 };
options.Key = new byte[64] { .. };
options.UseETag = true;
options.CacheControl.IsEnabled = true;
options.CacheControl.MaxAge = TimeSpan.FromDays(365);
options.CacheControl.MustRevalidate = false;
options.CacheControl.Public = true;
options.CacheControl.NoCache = false;
options.CacheControl.NoStore = false;
//select automatically the compatible mime type by request header
options.UseAcceptHeader = true;
options.RefreshLastAccessInterval = TimeSpan.FromMinutes(1);
options.FallbackHandler = (state, url, cachedData) =>
{
//use the existing cached data if available?
if (cachedData != null)
{
return cachedData;
}
//load fallback image
FileInfo fallbackImage = state switch
{
LoaderResultState.NotFound => new FileInfo(@"notfound.jpg"),
LoaderResultState.Failed => new FileInfo(@"failed.jpg"),
_ => throw new Exception()
};
if (fallbackImage.Exists == false)
{
return null;
}
//convert FileInfo to CachedData
return fallbackImage.ToCachedData();
};
})
//registers ImageSharp pipeline for specified mime types
.AddImageSharp(c => c
.WithMimeTypes(MimeTypes.WebP, MimeTypes.Jpeg, MimeTypes.Png, MimeTypes.Gif)
.WithOptions(x =>
{
x.ImageMaxHeight = 4000;
x.ImageMaxWidth = 4000;
})
//Adds your custom filters
.WithFilter<BlurFilter>()
//Executes custom action before the pipeline is started.
.WithPreProcessing(x =>
{
x.Image.Mutate(m => m.AutoOrient());
})
//Executes custom action after the pipeline is finished.
.WithPostProcessing(x =>
{
//blurs all images
x.Image.Mutate(m => m.Blur());
//overrides target format (Jpeg to WebP)
if (x.ImageFormat is JpegFormat)
{
x.ImageFormat = new WebPFormat() { Lossless = false };
}
//overrides target format (Png to WebP)
else if (x.ImageFormat is PngFormat)
{
x.ImageFormat = new WebPFormat() { Lossless = true };
}
//overrides metadata
x.Image.Metadata.ExifProfile = new ExifProfile();
x.Image.Metadata.ExifProfile.SetValue(ExifTag.Copyright, "ImageWizard");
}))
//.AddSkiaSharp()
.AddSvgNet()
.AddDocNET()
//uses file cache (relative or absolute path)
.SetFileCache(options => options.Folder = "FileCache")
//or MongoDB cache
.SetMongoDBCache(options => options.Hostname = "localhost")
//or distributed cache
.SetDistributedCache()
//adds some loaders
.AddFileLoader(options => options.Folder = "FileStorage")
.AddHttpLoader(options =>
{
//checks every time for a new version of the original image.
options.RefreshMode = LoaderRefreshMode.EveryTime;
//sets base url for relative urls
options.DefaultBaseUrl = "https://mydomain";
//allows only relative urls
//(use base url from request or DefaultBaseUrl from options)
options.AllowAbsoluteUrls = false;
//allows only specified hosts
options.AllowedHosts = new [] { "mydomain" };
//adds custom http header like apikey to prevent
//that user can download the original image
options.SetHeader("ApiKey", "123456");
})
.AddYoutubeLoader()
.AddGravatarLoader()
.AddOpenGraphLoader()
.AddAnalytics()
//Adds a background service which removes cached data based on defined CleanupReason.
//The cache needs to implements ICleanupCache.
.AddCleanupService(x =>
{
//Duration between the cleanup actions. (Default: 1 day)
x.Interval = TimeSpan.FromMinutes(1);
//Removes cached data which are older than defined duration.
x.OlderThan(TimeSpan.FromMinutes(2));
//Removes cached data which are last used since defined duration.
x.LastUsedSince(TimeSpan.FromMinutes(2));
//Removes cached data which are expired (based on the loader result).
x.Expired();
})
;
//default path ("/image")
//use middleware
app.UseImageWizard(x =>
{
//default path ("/analytics")
Related Skills
node-connect
339.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.9kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
summarize
339.5kSummarize or extract text/transcripts from URLs, podcasts, and local files (great fallback for “transcribe this YouTube/video”).
feishu-doc
339.5k|
