Open-source project
saucecontrol/PhotoSauce avatar
saucecontrol/PhotoSauce

PhotoSauce MagicScaler: resizing images in linear light on .NET

MagicScaler high-performance, high-quality image processing pipeline for .NET

738 stars62 forksC#MIT

At a glance

What is it?
MagicScaler is a .NET image processing pipeline built around high quality resizing, with linear light processing and sharpening as its distinguishing features. It suits teams that need predictable thumbnails and derivatives at speed on Windows or Linux, and it suits them less if their format list includes TIFF or BMP on a Linux host.
Who is it for?
Adopt MagicScaler when you serve resized images from .NET on Windows or Linux and quality of the downscale matters more than a single built-in codec, and verify first that your host can load the cross-platform codec packages from nuget.org. Do not adopt it if TIFF or BMP decoding on Linux is a requirement, because the documentation names those as the notable unsupported formats there.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 25 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A .NET imaging pipeline built around one hard problem

PhotoSauce is a repository of .NET imaging libraries, and MagicScaler is the one it is built around. The description calls it a high-performance, high-quality image processing pipeline for .NET, focused on making complex imaging tasks simple. That phrase is doing real work in the project's favour, because resizing is exactly the operation where naive implementations look acceptable on small images and fall apart on large ones.

The stated technical commitments are specific. MagicScaler implements what the README calls best-of-breed algorithms, processes pixels in linear light, and applies sharpening, with the claim that this yields the best image resizing quality available on the platform. Linear light processing is the part worth understanding. Working in linear light rather than in gamma-encoded sRGB values keeps the maths physically meaningful when you average or filter pixels, which is what downscaling mostly is. Doing it in sRGB space directly weights dark and light pixels incorrectly and produces the muddy or overly contrasty results people associate with resized images.

The audience is engineers who already live in .NET and need image derivatives: thumbnailers, media pipelines, import services. The MIT licence and the NuGet distribution make it a library you reference rather than a tool you run.

Resizing is one call and one settings object

The API is small enough to show in full. Resizing a source file to a destination file with a target width takes one static call:

csharp
MagicImageProcessor.ProcessImage(@"\img\big.jpg", @"\img\small.jpg", new ProcessImageSettings { Width = 400 });

You pass an input path, an output path and a settings object. The height is derived automatically to preserve the aspect ratio, so a single Width property is enough for the common case. The README states that the default settings are optimized for a balance of speed and image quality, which is the sensible starting point for a service that has not measured its own workload yet.

The settings object is where the tuning happens. Because it is a plain object passed into the call, the same code path serves a thumbnail endpoint and a full size export, with different settings chosen per request rather than per pipeline build. For a web service the pattern is straightforward: take the requested width, clamp it, and hand it to ProcessImage in the same way every time.

The documentation points to the full API reference for the parts of the settings surface that the README does not enumerate, so treat the options beyond Width as something to read about rather than guess at.

The pipeline accepts an alternate pixel source and hands pixels back

The interesting part of the design is that MagicScaler is not a closed box around a single resize routine. The README states that the pipeline is customizable if you want to use an alternate pixel source, capture the output pixels for additional processing, or add custom filtering.

Those three hooks cover most of what an imaging team actually needs. An alternate pixel source lets you feed in frames that never existed as a file, which matters for a service that receives images over a network or decodes them earlier in its own pipeline. Capturing the output pixels lets you run your own pass over the result, for instance to apply a watermark or a uniform tint, without re-decoding the file. Custom filtering sits inside the pipeline rather than after it, so a filter you add participates in the same linear light arithmetic as the resampler.

The practical consequence is that you can keep a single decode and encode path for the whole request instead of writing the image to a temporary file, running an external tool over it and reading it back. For a high volume service that removes a lot of disk traffic.

What you do not get from the README is a description of the extension points as an interface you implement, or a sample of a custom filter. The documentation link for the API reference is where those details live, and the README itself stays silent on them.

What the benchmark table in the README does and does not prove

The README includes end-to-end resize benchmarks, and it is unusually careful about their provenance. It says the results come from the tests used in a Microsoft .NET blog post on .NET Core image processing, updated to use current versions of the libraries and runtime as of November 2022, and that the original benchmark project is on GitHub. It also explains a methodological change: the benchmarks were modified to use a constant UnrollFactor, because the default BenchmarkDotNet behaviour of targeting a runtime range per iteration can under-report allocations and GC counts, which are then extrapolated from limited iterations.

On the Windows x64 configuration the README lists MagicScaler Load, Resize, Save at a mean of 46.85 ms against 354.73 ms for System.Drawing, with ImageSharp at 115.90 ms, NetVips at 100.92 ms, SkiaSharp at 117.43 ms and ImageMagick at 345.99 ms. The scenario is twelve JPEGs of roughly one megapixel each resized to 150 pixel wide thumbnails and saved back as JPEG. The Arm64 table shows the same ordering with MagicScaler at 65.72 ms.

Two caveats deserve attention. The numbers are from a shared benchmark suite, so they reflect that suite's workload rather than yours, and the README states that not all libraries are supported on all platforms, which is why the tables have different row sets. Treat them as a ranking of the approaches, not as a prediction for your hardware.

Linux support depends on codec packages you install separately

This is the constraint that decides whether MagicScaler fits your deployment. The README states that MagicScaler runs on Windows and Linux, then adds that Linux hosting requires one or more of the cross-platform codec plugins available on nuget.org, under the photosauce.nativecodecs search. Most common image formats are supported, and the notable exceptions are support for BMP and TIFF images.

So the answer to whether TIFF works is not simply no. It works where the codec is present and not where it is missing, and the set of supported formats on a Linux host is decided by which native codec packages you add rather than by the core library alone. The split is architectural: the managed pipeline stays portable and the format support is pluggable.

The practical consequence is deployment planning. A Linux container image needs the codec packages baked in, and an upgrade that changes which formats are handled can change behaviour without a version bump in your own code. If your workload is web images, JPEG and PNG are in the comfortable zone. If a print shop pipeline or a scanner workflow depends on TIFF, you need to confirm the codec path before committing to the library.

A library under an MIT licence, with releases that trail the commits

The repository layout is that of a multi package solution. The root holds build, src, modules and doc directories, along with building.md, nuget.config, azure-pipelines.yml, a license file and a third-party-notices file. The presence of third-party-notices alongside the MIT license text is the usual sign that bundled native components carry their own attribution requirements, and the license file and third-party-notices directory are what you read before redistributing a build. This is a note about where to look, not legal advice.

On release rhythm, the pattern is worth naming because it affects how you plan upgrades. The tagged releases are v0.14.1 and v0.14.2 on 2024-03-06, then v0.15.0 on 2024-12-05. The last push was on 2026-10-01, which is well after that tag, so the repository is receiving work that has not been cut into a published version. In practice you either pin a tagged package and take the behaviour of that tag, or you track the source.

The library is still pre-1.0, which means the namespace and API surface can still move between minor versions. For a service that pins a version, that is a routine concern. For a library you intend to expose in your own public API, the API reference under docs.photosauce.net is where you check what you are actually depending on.

Editorial conclusion

Adopt MagicScaler when you serve resized images from .NET on Windows or Linux and quality of the downscale matters more than a single built-in codec, and verify first that your host can load the cross-platform codec packages from nuget.org. Do not adopt it if TIFF or BMP decoding on Linux is a requirement, because the documentation names those as the notable unsupported formats there.

Frequently asked questions

How do I install PhotoSauce MagicScaler in a .NET project?

The library is distributed on nuget.org as PhotoSauce.MagicScaler. On Linux you also need one or more of the cross-platform codec plugins published under the photosauce.nativecodecs search, because the core package alone does not carry format support there.

Does MagicScaler support TIFF and BMP on Linux?

The README names BMP and TIFF as the notable exceptions to format support on Linux. Most common image formats are supported, and the exact set depends on which cross-platform codec plugins you install.

How do I resize an image with MagicScaler?

Call MagicImageProcessor.ProcessImage with an input path, an output path and a ProcessImageSettings object. Setting only the Width resizes to that width and derives the height automatically to preserve the aspect ratio.

Can I customize the MagicScaler processing pipeline?

Yes. The README states the pipeline is customizable so you can use an alternate pixel source, capture the output pixels for additional processing, or add custom filtering.

What licence does PhotoSauce use?

The repository lists the MIT licence. The root also contains a license file and a third-party-notices directory, which are worth reading before you redistribute a build that bundles native components.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. saucecontrol/PhotoSauce on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/saucecontrol-photosauce.svg)](https://hysenlabs.com/projects/saucecontrol-photosauce)

Was this useful?