Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plans to replace HttpModule with an OWIN component? #116

Closed
togakangaroo opened this issue Dec 8, 2014 · 15 comments
Closed

Plans to replace HttpModule with an OWIN component? #116

togakangaroo opened this issue Dec 8, 2014 · 15 comments
Milestone

Comments

@togakangaroo
Copy link

These are generally considered the way going forward. And from what I've seen, dependency on System.Web for generic components is on the way out.

Is there something about ImageResizer that is IIS-specific or will it eventually be implemented as an OWIN module?

@lilith
Copy link
Member

lilith commented Dec 9, 2014

We do hope to offer an OWIN pipeline. We'd have one already, except our 2010-era plugin API exposes dozens of interfaces that assume an HttpModule environment and use System.Web classes. Despite this, ImageResizer 3.X is mono-compatible.

Given that there are hundreds of customers with custom plugins using this API, we don't want to break them all for the next major 'tick' release - 4.0.

We're hoping that for 5.0 ('tock' release), we will be able to remove our dependency on both System.Drawing and System.Web. (Hopefully vNext will be out, then, as well).

System.Drawing is particularly unsuited to use in a server-side environment, both for its global locks and threading design, and also for it's terribly buggy memory management. While ImageResizer abstracts and patches it admirably, it would be better for everyone if a cross-platform, server-friendly alternative existed.

We've been working on LibGD for several years at this point, as we see it as the most likely successor to System.Drawing. We've improved performance and stability, and performed proof of concept benchmarking and validation with a prototype .NET wrapper, but we're still likely a man-year away from a production-ready NuGet package. We're actively looking for a sponsor to complete LibGD.NET. All of our income goes back into OSS development, but it's not enough..

@NicoJuicy
Copy link

vNext is out, i'm already using Asp.Net 5 and was wondering how the status would be with imageresizing.net :)

@evgenyt1
Copy link

+1
ASP.NET 5 is RC

@Gillardo
Copy link

Any news on this? vNext is out and we need an alternative to System.Drawing

@lilith
Copy link
Member

lilith commented Oct 26, 2015

ASP.NET 5 is expected to reach 1.0 in 2016. What do you mean by 'out'?

I avoid needlessly breaking backwards compatibility, so I would aim to group the "Core CLR compatible" and OWIN changes together in the same release.

It is not possible to do image processing directly in C# in any reasonable amount of time. Processing a small image in C# can take several seconds, where a hand-optimized C version can finish in 10 milliseconds. That's several orders of magnitude. Support for native code is a baseline prerequisite.

Primitive support for native (C) libraries was just implemented 4 days ago in DNX. It will be a while before this appears in a public build.

On paper, DNX is designed to be aware of native libraries and load them directly from nuget packages. This is fantastic.

Unfortunately, .NET Full (what everyone actually uses) is blind to unmanaged binaries. They get left behind whenever stuff is shadow-copied - like when an ASP.NET website is deployed, or unit tests are run with isolation. There's no architecture-awareness, so you can't switch between running an app in 32 and 64-bit modes (which kills PaaS nicely). Deployment breaks because there's a per-process model instead of per-appdomain, so you can't use them on Azure Websites, as the deploy will fail due to a locked native binary. .NET fails to expose even the original path a managed binary was shadow-copied from, preventing even a convoluted workaround for existing.. At this time, there is no clean solution to using native dependencies on .NET classic. It cannot be done in a user-friendly way.

ImageResizer's native plugins have seen very little popularity over the last 5 years, as native code makes everything miserably complicated and increases the rate of Visual Studio segfaults. .NET Core forces us to go native, and that makes the learning curve for new ImageResizer users quite steep. We would expect a decline in adoption if we force native assemblies on all users.

In v4, we resorted to using C++/CLI so we could embed our hand-crafted rendering engine into a "managed" (but platform-specific) binary. Thus FastScaling.x64 and FastScaling.x86 were created.

We still depend on System.Drawing extensively - both for image codecs (jpeg, png, gif, tiff, etc) and for public API objects (Bitmap, Image, Color, Pen, Font, PointF, Point, SizeF, Size, RectangleF, Rectangle, etc). Moving to CoreCLR would mean a full rewrite and a new API.

Progress so far

We ported MetadataExtractor from Java to C# - and transitioned ownership to Drew Noakes, the author of the Java version. This gives .NET it's first managed parsing library for images. Until this, all libraries wrapped WPF or GDI+ tooling, inheriting their bugs and quirky limitations, as well as security issues. In the process we fixed dozens of bugs in Sharpen, and set it up with automated CI and releases (we also extracted it from Eclipse, so you can use it as a standalone command-line app instead of as an eclipse plugin).

We've done lots of internal refactoring to increase the amount of code directly re-usable without System.Drawing or ASP.NET base class references.

But most significantly...

In the last 3 years we've put a massive amount of time and money into the ecosystem. We've been upgrading imaging codecs to use Continuous Integration, GitHub, automated testing, etc. We focused on LibGD, Libjpeg-turbo, libpng, libtiff, openjpeg, FreeImage, libraw, and zlib. These now build cross-platform under Travis and AppVeyor CI, with decent test coverage.

It seems extremely doubtful that Microsoft will provide any solution to cross-platform imaging.

If this happens, the .NET community will have to do it. The .NET team doesn't have the resources to pull it off.

We've been laying the groundwork for a blazingly fast, cross-platform ImageResizer 5 which melds the FastScaling rendering engine with the FreeImage codec support.

Unfortunately, this may not ever be completed, as we're witnessing the simultaneous decline of .NET adoption for new projects and the forced split between .NET Full and .NET Core, where one must make separate builds and use separate deployment strategies for native binaries between the two targets. We're already 'nonprofit', and supporting both of these platforms would put us even farther in the red. It's intractably unmaintainable to support two forks that are so different.

Unless there is progress to unify .NET Full and .NET Core so that package authors can reliably distribute and access native packages, we really can't do anything. This requires changes both in NuGet and in .NET itself. .NET must let developers override the native and managed assembly load process (managed, since we have arch-specific manage assemblies too), and native, so that we can P/Invoke app-versioned stuff. NuGet needs to establish conditional references so that we can fetch the right binary for each platform, and provide transitive information. NuGet 3 makes a bit of progress on the transitive side with the new manifests, but (a) doesn't do anything about conditional references, and (b) doesn't work on VS2013, where nearly all users are at.

My hope is that Paket will supplant the NuGet client, and with it bring determinism and solid algorithmic approaches to what has historically been a set of Visual Studio scripts. Compatibility can be determined by what the community cares about, instead of driven by marketing needs (like selling a new version of VS). Unfortunately, Paket doesn't ship with Visual Studio, and MSBuild doesn't let you reload a build script if you modify it during execution. This kills any third-party package managers and keeps you locked into the official MS toolset if you want to distribute project files that 'just work'.

There are a lot of things blocking progress in this space - the MSBuild team attitude towards community extension, the utter lack of transparency around NuGet design & development itself, and the unwillingness in general of Microsoft teams to consider or value the burden placed on package authors. I'm hoping that we'll see change if Microsoft finds itself in the situation of needing to support and ship native binary packages to both .NET classic and .NET Core, and for some reason is required to support VS2013 users.... Who knows, it might happen.

If we had a fully-complete, cross-platform imaging library ready today - with .NET bindings, error handling, memory management, thread management, etc - we would have no good way to deliver it. Frankly, we'd also have no customers, either, as a very limited number of business people in .NET care about x-plat, and the rest think that ImageResizer 3/4 is "good enough/fast enough". When we've given users so many orders of magnitude in performance improvements, what's another 2-5x?

I've approached many of the companies that process petabytes of images; offering them massive savings on infrastructure costs - usually easily demonstrable via a benchmark with their data on their servers. So far I've had no takers. Even at scale, saving thousand$ per day, they don't care about reducing 100ms to 20ms.

Current Imazen sales figures aren't enough to cover a single developer salary. That's why support contracts aren't going to be sold after Nov 13th; I can't afford to do this full-time any more. Dev tools are not a profitable business, although they're usually a business developers can care about. I'm not unique here. libjpeg-turbo ships on nearly every piece of silicon in the world, and the maintainer has trouble making ends meet. Pretty much every imaging library and codec out there has the same problem - no funding. Photograph processing also has such a high learning curve (so much signal processing, discrete math, etc) that there's never a significant amount of contributed code; the burden always falls squarely on one set of shoulders. Computer vision isn't quite as bad - lots of money going into OpenCV, I suspect, but there's very little we can use from that library.

Image processing is the perfect storm of complexity - raw pointer access on a wide variety of bitmap formats, with metadata and string parsing mixed in liberally, and usually a few hundred pages of assembler. It's a nightmare to audit. Running Valgrind on libgd caught so many buffer overflows and underflows you'd have a conniption. Memory leaks are quickly evident, but they're not what you should be worried about. Anyhow, there's a lot of risk here, and codecs see more than their share of CVEs. Side note: Don't ever run ImageMagick on untrusted data unless you've isolated it in a Docker container or unprivileged VM.

To sum up, I don't want to do this unless I can afford to do it correctly, and maintain it well. Having a poorly maintained, widely deployed imaging library with an exploited vulnerability is not be a legacy I'd like to have. A top-to-bottom implementation in Rust is actually attractive, although I'd have to implement the whole stack - jpeg/png/gif codecs, rendering, color profile parsing and application, etc. The route I've taken so far (securing FreeImage & codecs, merging my rendering engine) is more pragmatic, but also requires a strong long-term commitment. Microsoft is not committed to package authors, and ImageResizer doesn't provide enough income to fund even the initial development. My primary focus has to move on to more traditional employment; family comes first. I'll maintain and support v4, but unless there is a dramatic increase in sales, I can't afford to create v5 -- let alone the cross-platform imaging library it requires.

@davidfowl
Copy link

@nathanaeljones We should talk more about the native support. When you get some time, ping me on https://jabbr.net, I think you'l find things are moving in the right direction and I'll be the first to admit we've been particularly bad at communicating added capabilities lately. That will change. We're sorta in a mad rush to make the product work but we're starting to document more stuff as we go.

@LinusEkstrom
Copy link

Any news or updates regarding the support for asp.NET Core 1?

@lilith
Copy link
Member

lilith commented Mar 17, 2016

There's a working prototype/proof of concept for the underlying C library: https://github.com/imazen/imageflow

No C# wrapper for it exists at this point, let alone a .NET image server.

Hoping to get a kickstarter going soon once I have some impressive charts/graphs :)

@lilith
Copy link
Member

lilith commented Apr 1, 2016

Turns out that making a ruby port was < 1/10th the effort of porting to .NET Core. If you want to play with it, it's 2-10x faster than ImageResizer 4. You'll need ruby 2.2.1, conan, and C++ build tools. linux & mac os currently supported; windows builds are good occasionally, but are not yet reliable.

Instructions at https://github.com/imazen/imageflow

@lilith
Copy link
Member

lilith commented Jun 1, 2016

Help make ImageResizer 5 possible (and .NET Core compatible):

https://www.kickstarter.com/projects/njones/imageflow-respect-the-pixels-a-secure-alt-to-image

10x faster than ImageMagick.

imageresizer-imageflow

@lilith lilith modified the milestone: V5 Dec 27, 2016
@lilith
Copy link
Member

lilith commented Jul 18, 2020

We now have an ASP.NET Core middleware that nearly has feature parity with ImageResizer:

https://github.com/imazen/imageflow-dotnet-server

@lilith lilith closed this as completed Jul 18, 2020
@davidfowl
Copy link

@lilith Have ya'll performance tested this component? @sebastienros, this might be interesting to benchmark.

@lilith
Copy link
Member

lilith commented Jul 19, 2020

We've benchmarked Imageflow but not the end-to-end middleware. I would love to see how it performs against the competition! Is there an existing benchmark suite/harness we could add it to?

@lilith
Copy link
Member

lilith commented Jul 30, 2020

@davidfowl Is there a comparative benchmark harness I could plug in into? @sebastienros have you tested any other C# image servers?

@davidfowl
Copy link

Not that I'm aware of.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants