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

Support Full System.Drawing Functionality on .NET Core #20325

Closed
mellinoe opened this Issue May 25, 2017 · 99 comments

Comments

Projects
None yet
@mellinoe
Contributor

mellinoe commented May 25, 2017

Update: The following is the current plan.

  • Port the .NET Framework implementation to .NET Core. WIP, See #20593 .
  • Move mono's libgdiplus-based managed implementation from mono to corefx
  • Ensure that there is a code-sharing story between mono and corefx. This likely means removing the source code from mono and importing code from the submodule link that already exists. In progress. Mono has begun using some portions of the Windows implementation already.
  • Port mono's tests for System.Drawing, making any modifications necessary to ensure that they pass on the Windows implementation, which is our baseline for compatibility. In progress
  • Consolidate differences between the Windows and Unix versions of the library. Document all differences in behavior and mark test cases appropriately.

System.Drawing has been identified as one of the top most-used assemblies that are missing from .NET Core. Although there are 3rd-party alternatives that provide more modern versions of the same functionality (ImageSharp, SkiaSharp, etc.), we believe there is still value in providing a binary-compatible implementation of System.Drawing itself. This issue is intended to document and track the work items involved. There are still lots of open questions; feedback and suggestions are encouraged.

Priorities:

  • Simplify migration from .NET Framework to .NET Core. We need to be binary compatible (no recompilation needed for existing assets), and we need to match the behavior as closely as possible.
  • Support System.Drawing where mono does, and facilitate code sharing between our implementations. As part of this, we will be open-sourcing the original Windows implementation from .NET Framework. This should allow us to improve mono's implementation where it diverges, and hopefully reduce the maintenance burden between us by consolidating code and effort.
  • NON-GOALS: We do not view this library as an opportunity for innovation, nor will we invest significant amounts of effort into optimizing or refactoring it. High performance, rich OS-specific functionality, and a redesigned, modern API are not areas we are interested in investing in as part of this effort. There are alternative libraries which target all of those issues and more.

Plan

System.Drawing is, fundamentally, a very thin wrapper over the GDI+ component on Windows. Worse yet, it is not available for UWP applications, so support is limited strictly to Win32 applications. This makes cross-platform implementations difficult, and the largest chunk of work involved with this effort will be figuring out how we can support the library on all of our platforms, and maintaining compatibility between them. There are several existing implementations that we can leverage, but none will support all of our platforms by themselves. We may need several distinct backends in order to get full cross-platform support, although some options could avoid that. The below chart maps implementation approaches (rows) with platform applicability (columns):

Win32 UWP macOS Linux / Others
.NET Framework Version (GDI+) X X X
Direct2D/Win2D X X
Mono/libgdiplus X
Xamarin/CoreGraphics X X X
Managed

.NET Framework Version (GDI+)

This is the existing implementation from the .NET Framework on Windows. It is a very thin wrapper around GDI+.

  • ✔️ Baseline implementation. Well-tested, stable.
  • Can only be used in non-UWP Windows apps (Win32).

Direct2D/Win2D

In order to get UWP support, we could implement a compatibility layer over Direct2D, or Win2D.

  • ✔️ GPU acceleration
  • Only buys us UWP support over the existing .NET Framework implementation.
  • High implementation cost
  • Can be shared between Win32 and UWP applications (Windows 8+ only).

Mono/libgdiplus

This is the implementation used in mono. It uses a complicated native shim called "libgdiplus", which relies on a large set of native binaries.

  • ✔️ libgdiplus is available in a large number of package managers across the Unix ecosystem already. This means we can treat the dependency the same way we do the other native dependencies for .NET Core.
  • Native code adds a lot of complexity for new devs.

Xamarin/CoreGraphics

This is a specialized implementation used by Xamarin, in support of macOS and iOS. Unlike the "libgdiplus" mono version, it only uses CoreGraphics (a system component).

  • ✔️ No extra native dependencies; only uses system libraries.
  • macOS-specific. Could be used for iOS (not supported by .NET Core yet).

Managed (ImageSharp or custom)

One option is to implement the library in managed code. We can call into an existing library, like ImageSharp, for image-processing and graphics functionality. This is very desirable for a lot of reasons, but it does have a higher implementation cost.

  • ✔️ Can be used everywhere.
  • ✔️ Can achieve uniform behavior everywhere (at the expense of conformity with .NET Framework).
  • ✔️ Lower maintenance costs in the long-term.
  • High implementation cost.

Windows-Specific

One option is to treat the library as a Windows-specific component, similar to Registry. Attempting to install and load the library on other platforms would throw PlatformNotSupportedException's, as Registry does.

Tests

We do not have a very good existing test suite in the .NET Framework. The library is mainly covered indirectly, through other components like WinForms. Mono has a good set of conformance tests for their implementation, which we should be able to re-use. Where appropriate, we should also consider test cases which directly compare output from the .NET Framework implementation and other implementations (assuming we choose to support such things).

Location

An open question is where this library should live. If we take third-party dependencies to support some platforms, we may not want this code to live in corefx.

Printing Functionality

One thing skimmed over above is the fact that System.Drawing exposes a lot of functionality for printing images and documents. This poses a different problem from image-processing and graphics, which can be implemented portably. We may decide to exclude all printing-related portions of the library.

Future investments

Once the library is supported on all platforms, we will accept small, targeted improvements to the library, keeping in mind that legacy compatibility is the only important metric for the library. We will not want to merge any code that refactors, optimizes, or augments the Windows version until we have a fully-working cross-platform implementation. This matches our strategy with other compatibility libraries, like System.IO.SerialPort.

@marek-safar @JimBobSquarePants @ViktorHofer @qmfrederik @karelz

@qmfrederik

This comment has been minimized.

Show comment
Hide comment
@qmfrederik

qmfrederik May 25, 2017

Collaborator

@mellinoe Thanks for the additional information!

I actually have a good experience with using Mono/libgdiplus via CoreCompat.System.Drawing. Here's why:

  • Mono/libgdiplus actually does run on .NET Core on Windows. When on Windows, Mono's System.Drawing just uses GDI+ from Windows. So I think you can add a checkbox to 'Win32' for Mono's System.Drawing
  • I don't think the native dependencies need to be a problem. libgdiplus ships as a native component for most operating systems .NET Core supports. All Linux distros which .NET Core supports include libgdiplus in their mainline repositories: Ubuntu, Debian, Fedora, OpenSuse - even Alpine has it. Plus, libgidplus was recently added to Homebrew, too.
    So, I would suggest treating libgdiplus as a the single native dependency which would be acquired from the Linux distro or Homebrew - using the same acquisition mechanism for other .NET Core dependencies, such as curl or OpenSSL.
  • Mono's System.Drawing does include the Printing components, so you would get those for free, too.
  • Mono's System.Drawing runs natively on netstandard2.0 (and all unit tests pass!) and is very close to running on netstandard1.6.
  • Could you elaborate on "Native code adds a lot of complexity for new devs"?
  • Regarding "Behavior and performance issues", I'm not really aware of them, so it would be good to have them listed, too.
  • Since it's part of Mono, Mono's System.Drawing is still being maintained.

Another option would be to use the System.Drawing code from NetFX and have it consume libgdiplus instead of GDI+ on Linux. There's been some talk of open sourcing System.Drawing before, not sure if that's still an option? It would be fairly easy to implement, too.

Regarding UWP, do you currently have demand for System.Drawing on UWP?

/cc @akoeplinger

Collaborator

qmfrederik commented May 25, 2017

@mellinoe Thanks for the additional information!

I actually have a good experience with using Mono/libgdiplus via CoreCompat.System.Drawing. Here's why:

  • Mono/libgdiplus actually does run on .NET Core on Windows. When on Windows, Mono's System.Drawing just uses GDI+ from Windows. So I think you can add a checkbox to 'Win32' for Mono's System.Drawing
  • I don't think the native dependencies need to be a problem. libgdiplus ships as a native component for most operating systems .NET Core supports. All Linux distros which .NET Core supports include libgdiplus in their mainline repositories: Ubuntu, Debian, Fedora, OpenSuse - even Alpine has it. Plus, libgidplus was recently added to Homebrew, too.
    So, I would suggest treating libgdiplus as a the single native dependency which would be acquired from the Linux distro or Homebrew - using the same acquisition mechanism for other .NET Core dependencies, such as curl or OpenSSL.
  • Mono's System.Drawing does include the Printing components, so you would get those for free, too.
  • Mono's System.Drawing runs natively on netstandard2.0 (and all unit tests pass!) and is very close to running on netstandard1.6.
  • Could you elaborate on "Native code adds a lot of complexity for new devs"?
  • Regarding "Behavior and performance issues", I'm not really aware of them, so it would be good to have them listed, too.
  • Since it's part of Mono, Mono's System.Drawing is still being maintained.

Another option would be to use the System.Drawing code from NetFX and have it consume libgdiplus instead of GDI+ on Linux. There's been some talk of open sourcing System.Drawing before, not sure if that's still an option? It would be fairly easy to implement, too.

Regarding UWP, do you currently have demand for System.Drawing on UWP?

/cc @akoeplinger

@mellinoe

This comment has been minimized.

Show comment
Hide comment
@mellinoe

mellinoe May 25, 2017

Contributor

All Linux distros which .NET Core supports include libgdiplus in their mainline repositories: Ubuntu, Debian, Fedora, OpenSuse - even Alpine has it. Plus, libgidplus was recently added to Homebrew, too.

That is good to know; thanks for the info. If we are able to treat it as a fully external dependency, like the other native libs we use, then I would have less hesitation about using it. I'm not an expert on libgdiplus, so I would certainly like to understand more about it. The folks that I have talked with have been hesitant to readily suggest that we go ahead and use it, but it may be okay in the face of less-promising alternatives. In general, though, I think we should be really cautious about any new native dependencies we adopt in .NET Core. They make a lot of things more complicated for us and for customers.

Could you elaborate on "Native code adds a lot of complexity for new devs"?

I was trying to express the idea that folks trying to submit fixes for System.Drawing will have a harder time contributing to an external C library than a managed C# library here. Just a different skill-set, is all.

There's been some talk of open sourcing System.Drawing before, not sure if that's still an option? It would be fairly easy to implement, too.

At the very least, we will be using the .NET Framework version for Windows, so we will certainly open-source it. We can attempt to use that same implementation against libgdiplus on other platforms, but I fear that would involve reworking tons of the native code. Then again, that is just a guess on my part.

Regarding UWP, do you currently have demand for System.Drawing on UWP?

We view System.Drawing as one of the main libraries blocking old customers (and their code) from migrating to our new platforms, including UWP. That's not exactly the question you asked, but the end result is: we'd like to support System.Drawing everywhere, because it has proven to be an important dependency for existing libraries.

Contributor

mellinoe commented May 25, 2017

All Linux distros which .NET Core supports include libgdiplus in their mainline repositories: Ubuntu, Debian, Fedora, OpenSuse - even Alpine has it. Plus, libgidplus was recently added to Homebrew, too.

That is good to know; thanks for the info. If we are able to treat it as a fully external dependency, like the other native libs we use, then I would have less hesitation about using it. I'm not an expert on libgdiplus, so I would certainly like to understand more about it. The folks that I have talked with have been hesitant to readily suggest that we go ahead and use it, but it may be okay in the face of less-promising alternatives. In general, though, I think we should be really cautious about any new native dependencies we adopt in .NET Core. They make a lot of things more complicated for us and for customers.

Could you elaborate on "Native code adds a lot of complexity for new devs"?

I was trying to express the idea that folks trying to submit fixes for System.Drawing will have a harder time contributing to an external C library than a managed C# library here. Just a different skill-set, is all.

There's been some talk of open sourcing System.Drawing before, not sure if that's still an option? It would be fairly easy to implement, too.

At the very least, we will be using the .NET Framework version for Windows, so we will certainly open-source it. We can attempt to use that same implementation against libgdiplus on other platforms, but I fear that would involve reworking tons of the native code. Then again, that is just a guess on my part.

Regarding UWP, do you currently have demand for System.Drawing on UWP?

We view System.Drawing as one of the main libraries blocking old customers (and their code) from migrating to our new platforms, including UWP. That's not exactly the question you asked, but the end result is: we'd like to support System.Drawing everywhere, because it has proven to be an important dependency for existing libraries.

@qmfrederik

This comment has been minimized.

Show comment
Hide comment
@qmfrederik

qmfrederik May 26, 2017

Collaborator

At the very least, we will be using the .NET Framework version for Windows, so we will certainly open-source it. We can attempt to use that same implementation against libgdiplus on other platforms, but I fear that would involve reworking tons of the native code. Then again, that is just a guess on my part.

My guess is that the .NET Framework version will work well with libgdiplus. It's an assumption based on my experience with libgdiplus and how it tries to be binary compatible with GDI+.
The proof of the pudding is in the eating, though. If you can make the .NET Framework System.Drawing source code available under an open source license, I'd be happy to give it a spin, and run Mono's unit tests for System.Drawing on .NET Framework's System.Drawing backed by libgdiplus running on .NET Core on, say, Linux -- that would give the definitive answer.

I was trying to express the idea that folks trying to submit fixes for System.Drawing will have a harder time contributing to an external C library than a managed C# library here. Just a different skill-set, is all.

That's a fair point, although on the other hand the C libraries that libgdiplus uses - such as libpng, libjpeg,... have matured for a long time so there's some value to that, too. Graphics code requires a special skillset anyway, perhaps the bulk of people with that skillset are knowledgeable in C?

Perhaps another option is to start with libgdiplus and move code from unmanaged to managed. It could help kick start the System.Drawing implementation by reusing libgdiplus and move towards the goal of cross-platform managed code step by step.

Collaborator

qmfrederik commented May 26, 2017

At the very least, we will be using the .NET Framework version for Windows, so we will certainly open-source it. We can attempt to use that same implementation against libgdiplus on other platforms, but I fear that would involve reworking tons of the native code. Then again, that is just a guess on my part.

My guess is that the .NET Framework version will work well with libgdiplus. It's an assumption based on my experience with libgdiplus and how it tries to be binary compatible with GDI+.
The proof of the pudding is in the eating, though. If you can make the .NET Framework System.Drawing source code available under an open source license, I'd be happy to give it a spin, and run Mono's unit tests for System.Drawing on .NET Framework's System.Drawing backed by libgdiplus running on .NET Core on, say, Linux -- that would give the definitive answer.

I was trying to express the idea that folks trying to submit fixes for System.Drawing will have a harder time contributing to an external C library than a managed C# library here. Just a different skill-set, is all.

That's a fair point, although on the other hand the C libraries that libgdiplus uses - such as libpng, libjpeg,... have matured for a long time so there's some value to that, too. Graphics code requires a special skillset anyway, perhaps the bulk of people with that skillset are knowledgeable in C?

Perhaps another option is to start with libgdiplus and move code from unmanaged to managed. It could help kick start the System.Drawing implementation by reusing libgdiplus and move towards the goal of cross-platform managed code step by step.

@JimBobSquarePants

This comment has been minimized.

Show comment
Hide comment
@JimBobSquarePants

JimBobSquarePants May 26, 2017

Perhaps another option is to start with libgdiplus and move code from unmanaged to managed. It could help kick start the System.Drawing implementation by reusing libgdiplus and move towards the goal of cross-platform managed code step by step.

If I was to build a managed 2D graphics library (I am) I wouldn't, by choice, re-implement the System.Drawing API.

That said @mellinoe I'm happy to offer and assist in migration if the decision was made to use ImageSharp as an underlying managed library. In Jamestopia though we wouldn't bother and would actively push developers to migrate to better API's. Seems a lot cheaper and easier for MS.

There are some fundamental differences in how the two libraries currently work which would have to be discussed and workarounds considered. We're still unfinished so we have great flexibility to alter the API to improve flexibility and fill gaps which would help a lot.

Pixel Formats
ImageSharp expands all image formats into one of 20 different pixel formats we bundle. System.Drawing stores images in Format8bppIndexed format and similar in their indexed form. There would have to be a workaround developed to do the same.

Image Formats

  • Gif - Our output for gif is different to System.Drawing. We support animated gif plus transparency, we also quantize the output using Octrees by default and dither the result. This is all configurable but we would have to limit our encoder to use the default System.Drawing palette.
  • Png - We use all the available filters to encode pngs to reduce file size plus we support indexed png. We can add a switch to not filter the output scanlines to make the types compatible.
  • Jpeg - Our output is very slightly different to System.Drawing (I think due to rounding errors on decode) and our decoder performance is not as good just now. We need help on that to make it up to scratch.
  • Bmp - Should be no issues there. We support more output types but that can be limited.
  • Tiff - We have a tiff format in the works. Great progress is being made but it is unfinished.

MetaData
System.Drawing bundles everything together into the PropertyItem class from EXIF metadata to gif loop count and frame delay and makes no effort to decode that data. We've split out metadata into generic, EXIF, and ICC components and offer full reading/writing for those data types. You would have to create Property items to match that data and store the raw bytes.

Affine Transforms - Resize, Crop etc
We would need to do some work to ensure that we can produce the same output as System.Drawing. I'm not sure what sampler it uses for the different quality enumerations. We also don't support matrix operations within resize operations so there would have to be work done there.

Drawing
We offer drawing with a very similar API to System.Drawing. There may be a few gaps but I imagine. I know off-hand we haven't implemented all the Hatch bushes @tocsoft is our resident expert there so he can fill you in on what is/isn't there.

I'm sure there's more...

Regarding "Behavior and performance issues", I'm not really aware of them, so it would be good to have them listed, too.

@qmfrederik I had a very, very quick scan of the libgdi codebase and immediately found unsupported areas 1, 2. I've no idea what is out there. I remember having issues with Image.FromStream(stream, useembeddedColorManagement) in the past but I don't know if that is still an issue.

Graphics code requires a special skillset anyway, perhaps the bulk of people with that skillset are knowledgeable in C?

Btw I couldn't read/write C if you held a gun to my head plus I'm teaching myself graphics programming as I write ImagSharp. Shocking 😝

Perhaps another option is to start with libgdiplus and move code from unmanaged to managed. It could help kick start the System.Drawing implementation by reusing libgdiplus and move towards the goal of cross-platform managed code step by step.

If I was to build a managed 2D graphics library (I am) I wouldn't, by choice, re-implement the System.Drawing API.

That said @mellinoe I'm happy to offer and assist in migration if the decision was made to use ImageSharp as an underlying managed library. In Jamestopia though we wouldn't bother and would actively push developers to migrate to better API's. Seems a lot cheaper and easier for MS.

There are some fundamental differences in how the two libraries currently work which would have to be discussed and workarounds considered. We're still unfinished so we have great flexibility to alter the API to improve flexibility and fill gaps which would help a lot.

Pixel Formats
ImageSharp expands all image formats into one of 20 different pixel formats we bundle. System.Drawing stores images in Format8bppIndexed format and similar in their indexed form. There would have to be a workaround developed to do the same.

Image Formats

  • Gif - Our output for gif is different to System.Drawing. We support animated gif plus transparency, we also quantize the output using Octrees by default and dither the result. This is all configurable but we would have to limit our encoder to use the default System.Drawing palette.
  • Png - We use all the available filters to encode pngs to reduce file size plus we support indexed png. We can add a switch to not filter the output scanlines to make the types compatible.
  • Jpeg - Our output is very slightly different to System.Drawing (I think due to rounding errors on decode) and our decoder performance is not as good just now. We need help on that to make it up to scratch.
  • Bmp - Should be no issues there. We support more output types but that can be limited.
  • Tiff - We have a tiff format in the works. Great progress is being made but it is unfinished.

MetaData
System.Drawing bundles everything together into the PropertyItem class from EXIF metadata to gif loop count and frame delay and makes no effort to decode that data. We've split out metadata into generic, EXIF, and ICC components and offer full reading/writing for those data types. You would have to create Property items to match that data and store the raw bytes.

Affine Transforms - Resize, Crop etc
We would need to do some work to ensure that we can produce the same output as System.Drawing. I'm not sure what sampler it uses for the different quality enumerations. We also don't support matrix operations within resize operations so there would have to be work done there.

Drawing
We offer drawing with a very similar API to System.Drawing. There may be a few gaps but I imagine. I know off-hand we haven't implemented all the Hatch bushes @tocsoft is our resident expert there so he can fill you in on what is/isn't there.

I'm sure there's more...

Regarding "Behavior and performance issues", I'm not really aware of them, so it would be good to have them listed, too.

@qmfrederik I had a very, very quick scan of the libgdi codebase and immediately found unsupported areas 1, 2. I've no idea what is out there. I remember having issues with Image.FromStream(stream, useembeddedColorManagement) in the past but I don't know if that is still an issue.

Graphics code requires a special skillset anyway, perhaps the bulk of people with that skillset are knowledgeable in C?

Btw I couldn't read/write C if you held a gun to my head plus I'm teaching myself graphics programming as I write ImagSharp. Shocking 😝

@migueldeicaza

This comment has been minimized.

Show comment
Hide comment
@migueldeicaza

migueldeicaza May 26, 2017

Member

It is worth updating the original issue with the new information provided in the comments.

Mono's System.Drawing implementation was used for Mono's Windows.Forms implementation and we spent a few years tuning it to work with various third party component vendors. We delegated the hard graphic problems to Cairo.

It was also built so that on Windows, it would use the system provided GDI+ library, and on other platforms, it uses Mono's libgdiplus, it achieves this by having libgdiplus surface the same API as the Windows libgdiplus.

This means a couple of things:

  • That Mono's System.Drawing is actually a very thin layer on top of libgdiplus.
  • that on Windows, you get to use the real GDI+, which is quite nice.

While the implementation works, the font handling capabilities are complicated on Unix, so we used FreeType to get this information. While this works great on Linux systems, it is very slow on first use on a Mac that typically lacks FreeType, so if I was going to do the work in this space, I would start by improving libgdiplus to have a swappable font backend and use Apple's CoreText on OSX to avoid the initial font cache creation problems.

Cairo and the underlying libraries are faster than any C# code you can write.

That said, if I was going to take on the long-term maintenance of System.Drawing, today I would take a different approach.

I would use SkiaSharp as the backing engine as it is actively maintained, actively developed, actively fine tuned and optimized for both Chrome and Android. It also addresses some of the design limitations of Cairo, both the bottlenecks of the API as well as issues with the coordinate space that happen due to loss of precision with huge matrix transformations (Mozilla went through this, and made essentially this switch as well).

I would start with the sysdrawing-coregraphics which is a project that moved most of the logic from libgdiplus from C to C# and replaced the calls to Cairo with calls to CoreGraphics.

And then I would replace the calls to CoreGraphics with calls to the Skia APIs.

Last year I did some work along those lines on my spare time, where I mostly butchered the codebase so it would compile without CoreGraphics and I was planning on adding the Skia support. The time to do that never materialized. If you are interested in that fork, you can find it here.

Member

migueldeicaza commented May 26, 2017

It is worth updating the original issue with the new information provided in the comments.

Mono's System.Drawing implementation was used for Mono's Windows.Forms implementation and we spent a few years tuning it to work with various third party component vendors. We delegated the hard graphic problems to Cairo.

It was also built so that on Windows, it would use the system provided GDI+ library, and on other platforms, it uses Mono's libgdiplus, it achieves this by having libgdiplus surface the same API as the Windows libgdiplus.

This means a couple of things:

  • That Mono's System.Drawing is actually a very thin layer on top of libgdiplus.
  • that on Windows, you get to use the real GDI+, which is quite nice.

While the implementation works, the font handling capabilities are complicated on Unix, so we used FreeType to get this information. While this works great on Linux systems, it is very slow on first use on a Mac that typically lacks FreeType, so if I was going to do the work in this space, I would start by improving libgdiplus to have a swappable font backend and use Apple's CoreText on OSX to avoid the initial font cache creation problems.

Cairo and the underlying libraries are faster than any C# code you can write.

That said, if I was going to take on the long-term maintenance of System.Drawing, today I would take a different approach.

I would use SkiaSharp as the backing engine as it is actively maintained, actively developed, actively fine tuned and optimized for both Chrome and Android. It also addresses some of the design limitations of Cairo, both the bottlenecks of the API as well as issues with the coordinate space that happen due to loss of precision with huge matrix transformations (Mozilla went through this, and made essentially this switch as well).

I would start with the sysdrawing-coregraphics which is a project that moved most of the logic from libgdiplus from C to C# and replaced the calls to Cairo with calls to CoreGraphics.

And then I would replace the calls to CoreGraphics with calls to the Skia APIs.

Last year I did some work along those lines on my spare time, where I mostly butchered the codebase so it would compile without CoreGraphics and I was planning on adding the Skia support. The time to do that never materialized. If you are interested in that fork, you can find it here.

@JimBobSquarePants

This comment has been minimized.

Show comment
Hide comment
@JimBobSquarePants

JimBobSquarePants May 26, 2017

Just had a thought. What about server support. What are the plans there? That should factor into any decision making.

Just had a thought. What about server support. What are the plans there? That should factor into any decision making.

@TheBlueSky

This comment has been minimized.

Show comment
Hide comment
@TheBlueSky

TheBlueSky May 26, 2017

So what is the goal here? Only API compatibility? This is what I understood from what @mellinoe said.

If this is the case, @migueldeicaza comparison between native code and C# isn't very relevant, as long as C# performance is decent:

Cairo and the underlying libraries are faster than any C# code you can write.

I mean if building the API in managed code is an option, let's go for it.

On the other hand, if we settled on "let's just create something" option, let's not go with Win32-only option; this makes it a bit confusing.

So what is the goal here? Only API compatibility? This is what I understood from what @mellinoe said.

If this is the case, @migueldeicaza comparison between native code and C# isn't very relevant, as long as C# performance is decent:

Cairo and the underlying libraries are faster than any C# code you can write.

I mean if building the API in managed code is an option, let's go for it.

On the other hand, if we settled on "let's just create something" option, let's not go with Win32-only option; this makes it a bit confusing.

@vibeeshan025

This comment has been minimized.

Show comment
Hide comment
@vibeeshan025

vibeeshan025 May 26, 2017

Great initiative!! Its better to have System.Drawing implemented on top of set of interfaces and let the community develop each implementation.
Example we can use DirectX on windows and OpenGL on linux and mac OS. but the System.Drawing will internally call the interfaces which is platform agnostic.
If we are going for windows only option then its not going to make any difference to existing .net frameworks.

Great initiative!! Its better to have System.Drawing implemented on top of set of interfaces and let the community develop each implementation.
Example we can use DirectX on windows and OpenGL on linux and mac OS. but the System.Drawing will internally call the interfaces which is platform agnostic.
If we are going for windows only option then its not going to make any difference to existing .net frameworks.

@JimBobSquarePants

This comment has been minimized.

Show comment
Hide comment
@JimBobSquarePants

JimBobSquarePants May 26, 2017

You need good APIs for that that to be a viable idea. This is a stopgap not a solution.

You need good APIs for that that to be a viable idea. This is a stopgap not a solution.

@bitapparat

This comment has been minimized.

Show comment
Hide comment
@bitapparat

bitapparat May 26, 2017

I'd personally prefer a more forward-looking approach with an officially supported modern cross-platform graphics API for all .Net platforms, and a generic and optional System.Drawing implementation on top of it. But i'm aware that's a rather extensive and expensive solution and, thus, probably unrealistic.

I'd personally prefer a more forward-looking approach with an officially supported modern cross-platform graphics API for all .Net platforms, and a generic and optional System.Drawing implementation on top of it. But i'm aware that's a rather extensive and expensive solution and, thus, probably unrealistic.

@gulbanana

This comment has been minimized.

Show comment
Hide comment
@gulbanana

gulbanana May 26, 2017

I would love to see something like an implementation on top of ImageSharp. This hypothetical System.Drawing port isn't for high performance or high quality use - it's just to remove a blocker for porting legacy code in which image handling might be one small function. It would be fine if it was slower than the original netfx System.Drawing or didn't produce bit-identical output in all ops- it might even be able to get away with throwing NotSupported for some rarely-used apis.

Building on top of a community library with a modern API would provide a path forward for people to move their code to make direct use of that implentation later on.

gulbanana commented May 26, 2017

I would love to see something like an implementation on top of ImageSharp. This hypothetical System.Drawing port isn't for high performance or high quality use - it's just to remove a blocker for porting legacy code in which image handling might be one small function. It would be fine if it was slower than the original netfx System.Drawing or didn't produce bit-identical output in all ops- it might even be able to get away with throwing NotSupported for some rarely-used apis.

Building on top of a community library with a modern API would provide a path forward for people to move their code to make direct use of that implentation later on.

@stefanolson

This comment has been minimized.

Show comment
Hide comment
@stefanolson

stefanolson May 26, 2017

Whilst I'm aware that a lot of people use System.Drawing, the WPF System.Windows.Media api is a lot more capable in many areas, and more similar to the UWP API so personally I would rather see a better, more flexible/modern API than System.Drawing available, although of course there may be valuable things in System.Drawing that may be worth implementing

Whilst I'm aware that a lot of people use System.Drawing, the WPF System.Windows.Media api is a lot more capable in many areas, and more similar to the UWP API so personally I would rather see a better, more flexible/modern API than System.Drawing available, although of course there may be valuable things in System.Drawing that may be worth implementing

@Rekeyea

This comment has been minimized.

Show comment
Hide comment
@Rekeyea

Rekeyea May 26, 2017

IMHO System.Drawing should be left as Windows only. It is already being used in .Net Framework projects using ASP.Net Core, but those will still be using Windows since those are enterprise applications and I don't see them moving their whole infrastructure "because now they can".

Rekeyea commented May 26, 2017

IMHO System.Drawing should be left as Windows only. It is already being used in .Net Framework projects using ASP.Net Core, but those will still be using Windows since those are enterprise applications and I don't see them moving their whole infrastructure "because now they can".

@ViktorHofer

This comment has been minimized.

Show comment
Hide comment
@ViktorHofer

ViktorHofer May 26, 2017

Member

IMHO System.Drawing should be left as Windows only. It is already being used in .Net Framework projects using ASP.Net Core, but those will still be using Windows since those are enterprise applications and I don't see them moving their whole infrastructure "because now they can".

I disagree. ASP.NET Core is being used by more and more open source projects and startups because of cross-platform support and its speed improvements in comparison to nodeJS. I think it's viable to support System.Drawing on all environments where .NET Core and ASP.NET Core is running.

I'm a little worried about binary compatibility here. I think that we definitely need a System.Drawing implementation which is compatible with .NET Framework but I also think that we should build something (together with the community) which is modern, scalable and fast. It might be a good idea to 1. port the existing lib to core (managed) and 2. build a successor of System.Drawing which has all the innovations and improvements which aren't possible with the current API spec.

Member

ViktorHofer commented May 26, 2017

IMHO System.Drawing should be left as Windows only. It is already being used in .Net Framework projects using ASP.Net Core, but those will still be using Windows since those are enterprise applications and I don't see them moving their whole infrastructure "because now they can".

I disagree. ASP.NET Core is being used by more and more open source projects and startups because of cross-platform support and its speed improvements in comparison to nodeJS. I think it's viable to support System.Drawing on all environments where .NET Core and ASP.NET Core is running.

I'm a little worried about binary compatibility here. I think that we definitely need a System.Drawing implementation which is compatible with .NET Framework but I also think that we should build something (together with the community) which is modern, scalable and fast. It might be a good idea to 1. port the existing lib to core (managed) and 2. build a successor of System.Drawing which has all the innovations and improvements which aren't possible with the current API spec.

@Rekeyea

This comment has been minimized.

Show comment
Hide comment
@Rekeyea

Rekeyea May 26, 2017

@ViktorHofer it was said that there are other more modern alternatives like ImageSharp or SkiaSharp. That's why I think it's pointless since those open source projects and startups should use those other alternatives.

Rekeyea commented May 26, 2017

@ViktorHofer it was said that there are other more modern alternatives like ImageSharp or SkiaSharp. That's why I think it's pointless since those open source projects and startups should use those other alternatives.

@JimBobSquarePants

This comment has been minimized.

Show comment
Hide comment
@JimBobSquarePants

JimBobSquarePants May 26, 2017

@ViktorHofer I've literally spent the last two years of my life doing just that with ImageSharp. It's already faster than System.Drawing in many respects and has a much simpler/easier to extend API.

It needs the community to step up to help me push it over the line. Building something else would be a crushing blow to me.

@ViktorHofer I've literally spent the last two years of my life doing just that with ImageSharp. It's already faster than System.Drawing in many respects and has a much simpler/easier to extend API.

It needs the community to step up to help me push it over the line. Building something else would be a crushing blow to me.

@ViktorHofer

This comment has been minimized.

Show comment
Hide comment
@ViktorHofer

ViktorHofer May 26, 2017

Member

@JimBobSquarePants Then we should definitely also talk about building upon existing libraries 👍 If you put a lot of effort into it we shouldn't exclude ImageSharp from the discussion.

Member

ViktorHofer commented May 26, 2017

@JimBobSquarePants Then we should definitely also talk about building upon existing libraries 👍 If you put a lot of effort into it we shouldn't exclude ImageSharp from the discussion.

@benaadams

This comment has been minimized.

Show comment
Hide comment
@benaadams

benaadams May 26, 2017

Collaborator

What's the goal?

  1. Is it so people can move their apps from Framework to Core with minimal changes?
  2. Is it so people can move their apps from Framework on Windows to Core on Linux?
  3. Is it so people can develop new server apps with an api that is remarked as:

Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions.

I had initially imagined it was for (1) where people used System.Drawing in spite of the warnings; but maybe is for (2) and (3)?

Collaborator

benaadams commented May 26, 2017

What's the goal?

  1. Is it so people can move their apps from Framework to Core with minimal changes?
  2. Is it so people can move their apps from Framework on Windows to Core on Linux?
  3. Is it so people can develop new server apps with an api that is remarked as:

Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions.

I had initially imagined it was for (1) where people used System.Drawing in spite of the warnings; but maybe is for (2) and (3)?

@willdean

This comment has been minimized.

Show comment
Hide comment
@willdean

willdean May 26, 2017

Collaborator

@JimBobSquarePants What needs to be done to remove the "in early stages (alpha). As such, we cannot support its use on production environments until the library reaches release candidate status." warning from your project?

It's rather off-putting, and given the way that the .NET Core team have redefined 'Release Candidate' to mean what 'Alpha Experimental Technology Preview' might have once meant, it's now anyone's guess in the world of .NET what "early stages (alpha)" might mean, but it does sound like "not something I want to invest time in right now".

If you want to mop-up the world of System.Drawing users - I'm one, with a important (to us) ASP.Net application which can't currently be ported to .NET Core because it depends on, inter alia, System.Drawing - then you perhaps need to work a little on the optics for that market.

  • Would it be feasible to have a big table of features with green check-marks and red crosses to show the current state of feature parity with System.Drawing and then get rid of the generic warning?
  • Can you get onto Nuget rather than MyGet? (albeit marked pre-release?)
  • Can you make it clear that it works with full .NET, rather than people needing to pick through the platform types?
  • Don't publicly admit that you taught yourself graphics programming while working on this library. :-)

I don't want to see anyone suffer 'a crushing blow', especially an unintended one from a myopic pachyderm like MS, but I went to look at ImageSharp this morning and came away discouraged.

Collaborator

willdean commented May 26, 2017

@JimBobSquarePants What needs to be done to remove the "in early stages (alpha). As such, we cannot support its use on production environments until the library reaches release candidate status." warning from your project?

It's rather off-putting, and given the way that the .NET Core team have redefined 'Release Candidate' to mean what 'Alpha Experimental Technology Preview' might have once meant, it's now anyone's guess in the world of .NET what "early stages (alpha)" might mean, but it does sound like "not something I want to invest time in right now".

If you want to mop-up the world of System.Drawing users - I'm one, with a important (to us) ASP.Net application which can't currently be ported to .NET Core because it depends on, inter alia, System.Drawing - then you perhaps need to work a little on the optics for that market.

  • Would it be feasible to have a big table of features with green check-marks and red crosses to show the current state of feature parity with System.Drawing and then get rid of the generic warning?
  • Can you get onto Nuget rather than MyGet? (albeit marked pre-release?)
  • Can you make it clear that it works with full .NET, rather than people needing to pick through the platform types?
  • Don't publicly admit that you taught yourself graphics programming while working on this library. :-)

I don't want to see anyone suffer 'a crushing blow', especially an unintended one from a myopic pachyderm like MS, but I went to look at ImageSharp this morning and came away discouraged.

@Kukkimonsuta

This comment has been minimized.

Show comment
Hide comment
@Kukkimonsuta

Kukkimonsuta May 26, 2017

I'd go with path of least resistance - identify which scenario would be the cheapest and do that. Put warnings all around that it's just compatibility layer that should not be used for new projects. If feeling bad about leftover manpower invest it in improving ImageSharp :)

I'd go with path of least resistance - identify which scenario would be the cheapest and do that. Put warnings all around that it's just compatibility layer that should not be used for new projects. If feeling bad about leftover manpower invest it in improving ImageSharp :)

@qmfrederik

This comment has been minimized.

Show comment
Hide comment
@qmfrederik

qmfrederik May 26, 2017

Collaborator

@willdaen Out of curiosity, did you have a look at CoreCompat.System.Drawing (Mono's Sysyem.Drawing ported to Core)? Would that meet your requirements?

Collaborator

qmfrederik commented May 26, 2017

@willdaen Out of curiosity, did you have a look at CoreCompat.System.Drawing (Mono's Sysyem.Drawing ported to Core)? Would that meet your requirements?

@qmfrederik

This comment has been minimized.

Show comment
Hide comment
@qmfrederik

qmfrederik May 26, 2017

Collaborator

@Kukkimonsuta Yeah, that kind of is what I thought this was about - a cross platform impkementation of System.Drawing which people can (temporarly) use as they move to .NET Core - basically removing one of the adoption blockers.

It may not be the most pure solution, but it kind of is what libgdiplus was built for.

Collaborator

qmfrederik commented May 26, 2017

@Kukkimonsuta Yeah, that kind of is what I thought this was about - a cross platform impkementation of System.Drawing which people can (temporarly) use as they move to .NET Core - basically removing one of the adoption blockers.

It may not be the most pure solution, but it kind of is what libgdiplus was built for.

@JimBobSquarePants

This comment has been minimized.

Show comment
Hide comment
@JimBobSquarePants

JimBobSquarePants May 26, 2017

@willdean

I went to look at ImageSharp this morning and came away discouraged.

Really? Well that's terribly disappointing.

You didn't see the feature list linked to from the readme? I need to update that actually to add all our Porter Duff support and flesh out some other things.

Can you make it clear that it works with full .NET, rather than people needing to pick through the platform types?

It's in the readme.

Built against .Net Standard 1.1 ImageSharp can be used in device, cloud, and embedded/IoT scenarios

The message means exactly what it says. The API is subject to change. (Btw I don't think MS have redefined anything, they just rushed things certainly but alpha, beta etc is not defined by them)

What needs to be done to remove the "in early stages (alpha). As such, we cannot support its use on production environments until the library reaches release candidate status." warning from your project?

We need to do two things.

  1. Get the jpeg decoder refactored to reduce memory usage and speed it up.
  2. Change the IPixel interface to not pack/unpack from bytes and use predefined structs instead. RGBA32, RGB24, BGRA32, BGR24 and also use refs for the Vector4 packing/unpacking

After that I'm happy to move to beta and add the library to Nuget.

It's been a very slow alpha as I want to get this right. There's simply no point creating a half/baked graphics library. No one will use it and you'll end up wasting your time.

P.S. I've no shame in admitting I learned by doing. It's the absolute best way to thoroughly understand things IMO and I see it as an encouragement that others can do the same. 😄

JimBobSquarePants commented May 26, 2017

@willdean

I went to look at ImageSharp this morning and came away discouraged.

Really? Well that's terribly disappointing.

You didn't see the feature list linked to from the readme? I need to update that actually to add all our Porter Duff support and flesh out some other things.

Can you make it clear that it works with full .NET, rather than people needing to pick through the platform types?

It's in the readme.

Built against .Net Standard 1.1 ImageSharp can be used in device, cloud, and embedded/IoT scenarios

The message means exactly what it says. The API is subject to change. (Btw I don't think MS have redefined anything, they just rushed things certainly but alpha, beta etc is not defined by them)

What needs to be done to remove the "in early stages (alpha). As such, we cannot support its use on production environments until the library reaches release candidate status." warning from your project?

We need to do two things.

  1. Get the jpeg decoder refactored to reduce memory usage and speed it up.
  2. Change the IPixel interface to not pack/unpack from bytes and use predefined structs instead. RGBA32, RGB24, BGRA32, BGR24 and also use refs for the Vector4 packing/unpacking

After that I'm happy to move to beta and add the library to Nuget.

It's been a very slow alpha as I want to get this right. There's simply no point creating a half/baked graphics library. No one will use it and you'll end up wasting your time.

P.S. I've no shame in admitting I learned by doing. It's the absolute best way to thoroughly understand things IMO and I see it as an encouragement that others can do the same. 😄

@willdean

This comment has been minimized.

Show comment
Hide comment
@willdean

willdean May 26, 2017

Collaborator

@JimBobSquarePants Thanks for the response - I am really reluctant to hijack this thread by extending discussion about ImageSharp specifically... I'll give it a try and file any issues on your repo.

Collaborator

willdean commented May 26, 2017

@JimBobSquarePants Thanks for the response - I am really reluctant to hijack this thread by extending discussion about ImageSharp specifically... I'll give it a try and file any issues on your repo.

@willdean

This comment has been minimized.

Show comment
Hide comment
@willdean

willdean May 26, 2017

Collaborator

@qmfrederik I haven't looked at CoreCompat.System.Drawing - we're blocked on several things (SignalR is another) and I haven't really searched hard for alternatives to everything which is missing - I just keep a vague eye on what's happening to the things I know will cause us problems.

Collaborator

willdean commented May 26, 2017

@qmfrederik I haven't looked at CoreCompat.System.Drawing - we're blocked on several things (SignalR is another) and I haven't really searched hard for alternatives to everything which is missing - I just keep a vague eye on what's happening to the things I know will cause us problems.

@karelz

This comment has been minimized.

Show comment
Hide comment
@karelz

karelz May 26, 2017

Member

Lots of great feedback from anyone, thank you! (I didn't catch up on all of it)

Here's how I look at System.Drawing priorities and options:

Priorities

  1. Primary goal of System.Drawing is to simplify migration from Desktop to .NET Core (on Windows), i.e. high-compat between Desktop and Core implementation on Windows.
  2. Second-level goal is to support System.Drawing where it is needed -- currently Mono needs it on Mac & Linux (Mono is trying to reuse CoreFX libraries / source code, so synergy is desired).
    • Note: Mono has additional requirement on iOS -- size has to be small (i.e. it requires using Mac APIs - @marek-safar to confirm if I didn't mix it up with our discussion about HttpClient).
  3. Third-level (stretch) goal is to simplify migration from Windows to Linux/Mac on .NET Core.
    • Note: Easy migration does not necessarily imply great perf.
  4. Non-goals are high-perf, rich OS-specific capabilities, modern API surface, etc. (anything not listed in (1)-(3)).

Solutions

(2) Mono needs it on Mac & Linux

  • From our chats with @marek-safar we learned that Mono implementation on Linux is extremely involved - it requires special builds for specific versions of distros (not even just distros, but their versions).
  • We agreed with @marek-safar that Linux implementation's complexities are not something we should try to port to CoreFX (due to high cost, little value). We should rather prepare simple migration path (see (3)).
  • @migueldeicaza how does that align with your reply? Is libgdiplus the complex piece @marek-safar told me about? Is there a viable option to NOT migrate that part into CoreFX?

(3) simplify migration from Windows to Linux/Mac

  • Platforms which are easy to implement (e.g. Mac implementation from Mono), we should just implement.
  • For platforms which are not feasible to implement due to cost/benefit, we should recommend migration to 3rd party libraries (ImageSharp, SkiaSharp, etc.).
  • To make migration easier for devs, we could invest into shims which fake old System.Drawing API surface on top of the libraries. The shims would likely be in different namespace though (e.g. SkiaSharp.Drawing.Compat), so a small code change and/or cross-compilation would be required. The shims should probably live in the library repo, or in separate repo (not tied to CoreFX itself to avoid dependency of CoreFX on the libraries).
Member

karelz commented May 26, 2017

Lots of great feedback from anyone, thank you! (I didn't catch up on all of it)

Here's how I look at System.Drawing priorities and options:

Priorities

  1. Primary goal of System.Drawing is to simplify migration from Desktop to .NET Core (on Windows), i.e. high-compat between Desktop and Core implementation on Windows.
  2. Second-level goal is to support System.Drawing where it is needed -- currently Mono needs it on Mac & Linux (Mono is trying to reuse CoreFX libraries / source code, so synergy is desired).
    • Note: Mono has additional requirement on iOS -- size has to be small (i.e. it requires using Mac APIs - @marek-safar to confirm if I didn't mix it up with our discussion about HttpClient).
  3. Third-level (stretch) goal is to simplify migration from Windows to Linux/Mac on .NET Core.
    • Note: Easy migration does not necessarily imply great perf.
  4. Non-goals are high-perf, rich OS-specific capabilities, modern API surface, etc. (anything not listed in (1)-(3)).

Solutions

(2) Mono needs it on Mac & Linux

  • From our chats with @marek-safar we learned that Mono implementation on Linux is extremely involved - it requires special builds for specific versions of distros (not even just distros, but their versions).
  • We agreed with @marek-safar that Linux implementation's complexities are not something we should try to port to CoreFX (due to high cost, little value). We should rather prepare simple migration path (see (3)).
  • @migueldeicaza how does that align with your reply? Is libgdiplus the complex piece @marek-safar told me about? Is there a viable option to NOT migrate that part into CoreFX?

(3) simplify migration from Windows to Linux/Mac

  • Platforms which are easy to implement (e.g. Mac implementation from Mono), we should just implement.
  • For platforms which are not feasible to implement due to cost/benefit, we should recommend migration to 3rd party libraries (ImageSharp, SkiaSharp, etc.).
  • To make migration easier for devs, we could invest into shims which fake old System.Drawing API surface on top of the libraries. The shims would likely be in different namespace though (e.g. SkiaSharp.Drawing.Compat), so a small code change and/or cross-compilation would be required. The shims should probably live in the library repo, or in separate repo (not tied to CoreFX itself to avoid dependency of CoreFX on the libraries).
@qmfrederik

This comment has been minimized.

Show comment
Hide comment
@qmfrederik

qmfrederik May 26, 2017

Collaborator

@karelz Regarding the Mono implementation on Linux, I don't think it is involved at all. In fact, libgdiplus, the native part, ships with all Linux distros .NET Core supports. So you don't need to port it, the distros have already done that for you. You can declare a dependency on libgdiplus pretty much the same way you do for openssl or curl - acquire it via the distro instead of NuGet.

You can consider distributing libgdiplus and its dependencies as native components un NuGet packages. That does get complicated, fast - I tried with CoreCompat.System.Drawing.

Mono/libgdiplus gets you 1, 2 and 3 at almost no cost - most of the work has already been done. The result is in the CoreCompat.System.Drawing NuGet package.

Collaborator

qmfrederik commented May 26, 2017

@karelz Regarding the Mono implementation on Linux, I don't think it is involved at all. In fact, libgdiplus, the native part, ships with all Linux distros .NET Core supports. So you don't need to port it, the distros have already done that for you. You can declare a dependency on libgdiplus pretty much the same way you do for openssl or curl - acquire it via the distro instead of NuGet.

You can consider distributing libgdiplus and its dependencies as native components un NuGet packages. That does get complicated, fast - I tried with CoreCompat.System.Drawing.

Mono/libgdiplus gets you 1, 2 and 3 at almost no cost - most of the work has already been done. The result is in the CoreCompat.System.Drawing NuGet package.

@karelz

This comment has been minimized.

Show comment
Hide comment
@karelz

karelz May 26, 2017

Member

@qmfrederik I was relying only on info from @marek-safar who works on Mono - so I let him chime in.

Member

karelz commented May 26, 2017

@qmfrederik I was relying only on info from @marek-safar who works on Mono - so I let him chime in.

@migueldeicaza

This comment has been minimized.

Show comment
Hide comment
@migueldeicaza

migueldeicaza May 26, 2017

Member

Mr @qmfrederik is correct, libgdiplus is available on pretty much every Linux distribution already and it only relies on the unmanaged pieces. If Marek had any feedback on dealing with build complexity, it would be around you trying to ship a forked version of yours, and then you would have the same issues that you have in shipping CoreCLR - namely that you will want to compile for each system.

So that should not be an issue if you want to take the fastest/easiest path to bring System.Drawing.

You do not need to worry about iOS, for historical reasons System.Drawing is not used there and we do not even distribute it (beyond the basic Rectangle, Point types).

On iOS, the world has gone with either CoreGraphics or our cross-platform SkiaSharp.

Given the outlined priorities from @karelz, I would change my recommendation. Given these priorities, really System.Drawing wont be a long-term foundation for graphics, and I would essentially just reuse the Mono code.

Rely on gdiplus, and use Mono's System.Drawing stack (and ifdef out parts that wont work on .NET Core 2).

You can certainly choose a different path, but given the above goals, it sounds like investing on rewriting this code is a waste of time.

Member

migueldeicaza commented May 26, 2017

Mr @qmfrederik is correct, libgdiplus is available on pretty much every Linux distribution already and it only relies on the unmanaged pieces. If Marek had any feedback on dealing with build complexity, it would be around you trying to ship a forked version of yours, and then you would have the same issues that you have in shipping CoreCLR - namely that you will want to compile for each system.

So that should not be an issue if you want to take the fastest/easiest path to bring System.Drawing.

You do not need to worry about iOS, for historical reasons System.Drawing is not used there and we do not even distribute it (beyond the basic Rectangle, Point types).

On iOS, the world has gone with either CoreGraphics or our cross-platform SkiaSharp.

Given the outlined priorities from @karelz, I would change my recommendation. Given these priorities, really System.Drawing wont be a long-term foundation for graphics, and I would essentially just reuse the Mono code.

Rely on gdiplus, and use Mono's System.Drawing stack (and ifdef out parts that wont work on .NET Core 2).

You can certainly choose a different path, but given the above goals, it sounds like investing on rewriting this code is a waste of time.

@karelz

This comment has been minimized.

Show comment
Hide comment
@karelz

karelz May 26, 2017

Member

Given these priorities, really System.Drawing wont be a long-term foundation for graphics, and I would essentially just reuse the Mono code.

That was my thinking as well. With the caveat that we might want to use Desktop implementation on Windows to have higher-confidence compat (I've been bitten by HttpListener Mono compat recently, so I'm a bit cautious now ;)).

given the above goals, it sounds like investing on rewriting this code is a waste of time.

Agreed. We didn't plan huge investment. And I am not fan of wasting effort.

Overall, I don't think System.Drawing is such a great API & implementation that we want to innovate on it -- other projects like SkiaSharp, ImageSharp already did that, so let's rely on them to innovate for future in the graphics space. We should not reinvent the wheel in CoreFX, unless there are really good reasons. One .NET ecosystem to rule them all! ;)

Member

karelz commented May 26, 2017

Given these priorities, really System.Drawing wont be a long-term foundation for graphics, and I would essentially just reuse the Mono code.

That was my thinking as well. With the caveat that we might want to use Desktop implementation on Windows to have higher-confidence compat (I've been bitten by HttpListener Mono compat recently, so I'm a bit cautious now ;)).

given the above goals, it sounds like investing on rewriting this code is a waste of time.

Agreed. We didn't plan huge investment. And I am not fan of wasting effort.

Overall, I don't think System.Drawing is such a great API & implementation that we want to innovate on it -- other projects like SkiaSharp, ImageSharp already did that, so let's rely on them to innovate for future in the graphics space. We should not reinvent the wheel in CoreFX, unless there are really good reasons. One .NET ecosystem to rule them all! ;)

@migueldeicaza

This comment has been minimized.

Show comment
Hide comment
@migueldeicaza

migueldeicaza May 26, 2017

Member

Mono's System.Drawing approach has the advantage that it calls into the native GDI+, so on Windows, you get to use the one that ships with the system already. And if we get approval for release of .NET's System.Drawing, you can swap that out as well.

(I've been bitten by HttpListener Mono compat recently, so I'm a bit cautious now ;)).

The feeling is mutual @karelz, Mono has also been bitten by code in CoreFX :-)

Member

migueldeicaza commented May 26, 2017

Mono's System.Drawing approach has the advantage that it calls into the native GDI+, so on Windows, you get to use the one that ships with the system already. And if we get approval for release of .NET's System.Drawing, you can swap that out as well.

(I've been bitten by HttpListener Mono compat recently, so I'm a bit cautious now ;)).

The feeling is mutual @karelz, Mono has also been bitten by code in CoreFX :-)

@karelz

This comment has been minimized.

Show comment
Hide comment
@karelz

karelz May 26, 2017

Member

I agree that more code/library sharing with Mono would be beneficial overall.
If we can address the compat concern on Windows (likely with lots of tests), I'd be fine with that approach :)

The feeling is mutual @karelz, Mono has also been bitten by code in CoreFX :-)

When you hit those cases (or if you have a list from the past), please send the feedback to us/me. While it is usually not actionable right away, it is critical to prevent such unfortunate situations in future. Without knowing about such cases, we won't fully understand the impact we have on Mono and we will likely keep doing what we're doing, causing you the same pain over and over again. Let's try to prevent that.

Member

karelz commented May 26, 2017

I agree that more code/library sharing with Mono would be beneficial overall.
If we can address the compat concern on Windows (likely with lots of tests), I'd be fine with that approach :)

The feeling is mutual @karelz, Mono has also been bitten by code in CoreFX :-)

When you hit those cases (or if you have a list from the past), please send the feedback to us/me. While it is usually not actionable right away, it is critical to prevent such unfortunate situations in future. Without knowing about such cases, we won't fully understand the impact we have on Mono and we will likely keep doing what we're doing, causing you the same pain over and over again. Let's try to prevent that.

@qmfrederik

This comment has been minimized.

Show comment
Hide comment
@qmfrederik

qmfrederik May 26, 2017

Collaborator

What would the next steps be? Building a NuGet package for .NET Core from Mono's sources is straightforward, as should be setting up CI and tests. Would Mono produce the package or would the code be exported to a separate repository under dotnet? There's also the work of ingesting the NetFX code if possible.

Collaborator

qmfrederik commented May 26, 2017

What would the next steps be? Building a NuGet package for .NET Core from Mono's sources is straightforward, as should be setting up CI and tests. Would Mono produce the package or would the code be exported to a separate repository under dotnet? There's also the work of ingesting the NetFX code if possible.

@migueldeicaza

This comment has been minimized.

Show comment
Hide comment
@migueldeicaza

migueldeicaza May 26, 2017

Member

@karelz What part of the compat with Windows are you concerned about? Like I said, our System.Drawing is a thin layer on top of GDI+, so on Windows, it is the Windows GDI+ that does all the heavy lifting.

There are likely gaps in our implementation (both on the managed and unmanaged side) and those should be filled.

Perhaps the most comprehensive test that we have is Mono's Windows.Forms implementation, which emulates the entire toolkit (even on Windows) on top of pure GDI+. There are two other test suites, a unit testing suite that is already in place that tests some elements of GDI+ and one that we had for fuzzy-comparison of image outputs, this latter test suite needs to be brought back to life.

Logistically speaking, I would like to keep the same source tree compiling on both Mono and .NET Core to maximize code sharing, and avoid forks as this is a single unit.

Let us start by saying that we should add the proper ifdefs to make the source code compile both against .NET Core and Mono.

  • We can keep System.Drawing in Mono, and modify to build against .NET Core add build tools to produce a NuGet that is suitable to be published (easiest).

  • We can extract System.Drawing into a separate git module, to preserve history and have both Mono and CoreFX take a dependency.

  • We can outright copy the source code into CoreFX, and switch Mono to it, but we would lose the source control history that goes with it for future generations to debug. Perhaps the first commit should point to a mono/branch so people can resume archeologic debugging at that point.

Member

migueldeicaza commented May 26, 2017

@karelz What part of the compat with Windows are you concerned about? Like I said, our System.Drawing is a thin layer on top of GDI+, so on Windows, it is the Windows GDI+ that does all the heavy lifting.

There are likely gaps in our implementation (both on the managed and unmanaged side) and those should be filled.

Perhaps the most comprehensive test that we have is Mono's Windows.Forms implementation, which emulates the entire toolkit (even on Windows) on top of pure GDI+. There are two other test suites, a unit testing suite that is already in place that tests some elements of GDI+ and one that we had for fuzzy-comparison of image outputs, this latter test suite needs to be brought back to life.

Logistically speaking, I would like to keep the same source tree compiling on both Mono and .NET Core to maximize code sharing, and avoid forks as this is a single unit.

Let us start by saying that we should add the proper ifdefs to make the source code compile both against .NET Core and Mono.

  • We can keep System.Drawing in Mono, and modify to build against .NET Core add build tools to produce a NuGet that is suitable to be published (easiest).

  • We can extract System.Drawing into a separate git module, to preserve history and have both Mono and CoreFX take a dependency.

  • We can outright copy the source code into CoreFX, and switch Mono to it, but we would lose the source control history that goes with it for future generations to debug. Perhaps the first commit should point to a mono/branch so people can resume archeologic debugging at that point.

@akoeplinger

This comment has been minimized.

Show comment
Hide comment
@akoeplinger

akoeplinger May 26, 2017

Member

@migueldeicaza Mono's System.Drawing+libgdiplus already compiles and works on .NET Core due to some great PRs that @qmfrederik sent over the last week/months :)

I agree that open sourcing the managed System.Drawing layer from .NET Framework would be great so we can replace our managed layer and be more compatible (I'm assuming that most of the work is done by the underlying gdiplus in the .NET Framework implementation too).

This would mean that on Windows you'd end up with a highly compatible version and other platforms have Mono's libgdiplus underneath. Moving to a separate repo or into corefx sounds good to me.

And of course we should promote ImageSharp etc as the modern alternative!

Member

akoeplinger commented May 26, 2017

@migueldeicaza Mono's System.Drawing+libgdiplus already compiles and works on .NET Core due to some great PRs that @qmfrederik sent over the last week/months :)

I agree that open sourcing the managed System.Drawing layer from .NET Framework would be great so we can replace our managed layer and be more compatible (I'm assuming that most of the work is done by the underlying gdiplus in the .NET Framework implementation too).

This would mean that on Windows you'd end up with a highly compatible version and other platforms have Mono's libgdiplus underneath. Moving to a separate repo or into corefx sounds good to me.

And of course we should promote ImageSharp etc as the modern alternative!

@mellinoe

This comment has been minimized.

Show comment
Hide comment
@mellinoe

mellinoe Sep 11, 2017

Contributor

Sorry @Emasoft , I don't agree with much of this. SkiaSharp is a fine library, and there would be nothing inherently wrong with building a System.Drawing-compatible layer on top of it. But that endeavor, and the costs associated with it, just don't line up with what we are trying to accomplish with this effort right now. We are simply trying to provide a migration story for folks with legacy assets to move into the new world of .NET Core. We don't want this to be the new future-facing, modern library for image manipulation.

Very soon many .Net devs will start using it for developing the GUI of NetCore cross platform apps, and if the performance are lacking we would end making a remake of the Java Swing disaster. A slow and sluggy GUI would make cross platform development with NETCore much less palatable and will throw a bad light on all NETCore apps, like happened with Swing apps, that were never able to compete with native applications.

There are already multiple UI frameworks running on .NET Core -- none of them use System.Drawing, and none of them should. Using System.Drawing in a future-facing library would be a very foolish decision. By its very nature it is slow and poorly-organized, and it has a VERY dated and archaic API. Since it is a semi-transparent wrapper over a Windows component (GDI+), much of its surface area is intrinsically non-portable. If you're building a new, modern, cross-platform UI stack, you really should be building on top of a library which was designed for such an environment, not GDI+.

It is not true that we need a managed implementation of System.Drawing. There is no such thing as a managed graphics back end. When it comes to graphics devices, you have to work low level. Pointers, bitwise operations, memory allocations and data structures that fit the specific hardware architecture are necessary. This is the very reason why the old System.Drawing is not easy to port, being specifically linked to the windows drivers and the non managed GDI back end.

Managed code supports all of the things that you mentioned. We are also making it a top priority to ensure that these types of things can be accomplished with .NET. I don't think System.Drawing needs to (or ever should) be such a library, but I do believe these things can be built with .NET. There are so many advantages to a managed solution over a native wrapper; I think it would be a failure on our part if we don't try our best to make these things possible.

The work to support all different platforms low level is huge. Creating and maintaining many differents graphic backends is a waste of everybody time. Skia is already a cross platform open project with many contributors worldwide and with specific code for low level support added in the years for dozen of hardware platforms and OS. SkiaSharp, being a Skia wrapper, is a definitive solution for NetCore when it comes to cross platform graphics and the only one we have to maintain for true multiplatform durable and open code.

Yes, I want to support as few backends as possible. Given that the libgidplus backend is already mostly-functional, that seemed to be the way to go initially. Creating a SkiaSharp-based backend would constitute creating an entirely new wrapper layer; it's a LOT more work.

Making the standard version of System.Drawing a wrapper around SkiaSharp will also help developers to learn how to use SkiaSharp directly when they need to do more complex things, in a gradual way.

I understand what you're saying, and I agree to an extent. This reasoning was why I considered writing the wrapper layer over ImageSharp rather than libgdiplus. If we were considering writing a new wrapper layer, I would still strongly advocate that we use ImageSharp, because pulling in yet another native dependency is going in the wrong direction for .NET Core.

Contributor

mellinoe commented Sep 11, 2017

Sorry @Emasoft , I don't agree with much of this. SkiaSharp is a fine library, and there would be nothing inherently wrong with building a System.Drawing-compatible layer on top of it. But that endeavor, and the costs associated with it, just don't line up with what we are trying to accomplish with this effort right now. We are simply trying to provide a migration story for folks with legacy assets to move into the new world of .NET Core. We don't want this to be the new future-facing, modern library for image manipulation.

Very soon many .Net devs will start using it for developing the GUI of NetCore cross platform apps, and if the performance are lacking we would end making a remake of the Java Swing disaster. A slow and sluggy GUI would make cross platform development with NETCore much less palatable and will throw a bad light on all NETCore apps, like happened with Swing apps, that were never able to compete with native applications.

There are already multiple UI frameworks running on .NET Core -- none of them use System.Drawing, and none of them should. Using System.Drawing in a future-facing library would be a very foolish decision. By its very nature it is slow and poorly-organized, and it has a VERY dated and archaic API. Since it is a semi-transparent wrapper over a Windows component (GDI+), much of its surface area is intrinsically non-portable. If you're building a new, modern, cross-platform UI stack, you really should be building on top of a library which was designed for such an environment, not GDI+.

It is not true that we need a managed implementation of System.Drawing. There is no such thing as a managed graphics back end. When it comes to graphics devices, you have to work low level. Pointers, bitwise operations, memory allocations and data structures that fit the specific hardware architecture are necessary. This is the very reason why the old System.Drawing is not easy to port, being specifically linked to the windows drivers and the non managed GDI back end.

Managed code supports all of the things that you mentioned. We are also making it a top priority to ensure that these types of things can be accomplished with .NET. I don't think System.Drawing needs to (or ever should) be such a library, but I do believe these things can be built with .NET. There are so many advantages to a managed solution over a native wrapper; I think it would be a failure on our part if we don't try our best to make these things possible.

The work to support all different platforms low level is huge. Creating and maintaining many differents graphic backends is a waste of everybody time. Skia is already a cross platform open project with many contributors worldwide and with specific code for low level support added in the years for dozen of hardware platforms and OS. SkiaSharp, being a Skia wrapper, is a definitive solution for NetCore when it comes to cross platform graphics and the only one we have to maintain for true multiplatform durable and open code.

Yes, I want to support as few backends as possible. Given that the libgidplus backend is already mostly-functional, that seemed to be the way to go initially. Creating a SkiaSharp-based backend would constitute creating an entirely new wrapper layer; it's a LOT more work.

Making the standard version of System.Drawing a wrapper around SkiaSharp will also help developers to learn how to use SkiaSharp directly when they need to do more complex things, in a gradual way.

I understand what you're saying, and I agree to an extent. This reasoning was why I considered writing the wrapper layer over ImageSharp rather than libgdiplus. If we were considering writing a new wrapper layer, I would still strongly advocate that we use ImageSharp, because pulling in yet another native dependency is going in the wrong direction for .NET Core.

@clrjunkie

This comment has been minimized.

Show comment
Hide comment
@clrjunkie

clrjunkie Sep 12, 2017

@mellinoe I totally agree with your stand on this; however @Emasoft does hint to a valid concern about users viewing System.Drawing as a legitimate / preferable dependency for future graphics development by virtue of its presence in the BCL. History shows that “fit for purpose" statements about API's “doesn’t hold water” they tend to cause confusion and uncertainty among users (example: NET FX System.Drawing not recommend in ASP.NET / My frustration with HttpListener labeled "legacy" in .NET Core). There is also a substantial cost involved in communicating such statements (doc’s/ blogs). I also suspect that future introductory books about .NET Core will choose to cover System.Drawing to address simple graphics scenarios and that will effectively further establish the API and extend its lifetime. So I think we need a more formal strategy to deal with components that are included in the BCL purely for backward compatibility. Perhaps putting such components in a dedicated “Compatibility” namespace so to align expectations upfront, down at the code level.

@mellinoe I totally agree with your stand on this; however @Emasoft does hint to a valid concern about users viewing System.Drawing as a legitimate / preferable dependency for future graphics development by virtue of its presence in the BCL. History shows that “fit for purpose" statements about API's “doesn’t hold water” they tend to cause confusion and uncertainty among users (example: NET FX System.Drawing not recommend in ASP.NET / My frustration with HttpListener labeled "legacy" in .NET Core). There is also a substantial cost involved in communicating such statements (doc’s/ blogs). I also suspect that future introductory books about .NET Core will choose to cover System.Drawing to address simple graphics scenarios and that will effectively further establish the API and extend its lifetime. So I think we need a more formal strategy to deal with components that are included in the BCL purely for backward compatibility. Perhaps putting such components in a dedicated “Compatibility” namespace so to align expectations upfront, down at the code level.

@mellinoe

This comment has been minimized.

Show comment
Hide comment
@mellinoe

mellinoe Sep 12, 2017

Contributor

@clrjunkie

I think we need a more formal strategy to deal with components that are included in the BCL purely for backward compatibility.

Yes, this is something we've long struggled with on the team, and I think it's something we're still learning how to best manage. We've discussed various strategies, but haven't settled on anything satisfactory. Many of those past options have been removed to us in our more recent releases, so it's even more important for us to figure out how to message this stuff properly.

Contributor

mellinoe commented Sep 12, 2017

@clrjunkie

I think we need a more formal strategy to deal with components that are included in the BCL purely for backward compatibility.

Yes, this is something we've long struggled with on the team, and I think it's something we're still learning how to best manage. We've discussed various strategies, but haven't settled on anything satisfactory. Many of those past options have been removed to us in our more recent releases, so it's even more important for us to figure out how to message this stuff properly.

@migueldeicaza

This comment has been minimized.

Show comment
Hide comment
@migueldeicaza

migueldeicaza Sep 13, 2017

Member

Hello,

Generally, for new code, I would advocate using SkiaSharp directly for the many arguments already made in this thread.

For providing System.Drawing to .NET Core, adopting libgdiplus has the advantage that it has very low friction, the work to package this across the board and make it available is already there and some of the hard pieces of text rendering are already in place.

A win with the current approach is that System.Drawing on Windows would consume the Windows libgdiplus, which means that compatibility there will be great. The downside is that unless folks file and provide good bug reports and patches, the Unix version will not match it - it is very close, but there are a few known gaps and some known gaps to some of those that worked on it that might not be extensively documented -- Ill file issues later.

For those concerned about performance, a path that could be taken in the future is to replace the use of Cairo in libgdiplus with Skia, and that would not affect the managed code at all, it would be a transparent swap out.

I would not go as far as @mellinoe has gone with his criticism of GDI+, I think some of it is painting it with a too wide brush, but this is right on target:

If you're building a new, modern, cross-platform UI stack, you really should be building on top of a library which was designed for such an environment, not GDI+.

Exactly. And given that there is something of the caliber of SkiaSharp, you should use that instead. And this is exactly what projects like Avalonia have done. Google is continuously evolving it, and we are keeping it fresh and up to date, and it is the foundation of two of the most used pieces of software in the world.

Member

migueldeicaza commented Sep 13, 2017

Hello,

Generally, for new code, I would advocate using SkiaSharp directly for the many arguments already made in this thread.

For providing System.Drawing to .NET Core, adopting libgdiplus has the advantage that it has very low friction, the work to package this across the board and make it available is already there and some of the hard pieces of text rendering are already in place.

A win with the current approach is that System.Drawing on Windows would consume the Windows libgdiplus, which means that compatibility there will be great. The downside is that unless folks file and provide good bug reports and patches, the Unix version will not match it - it is very close, but there are a few known gaps and some known gaps to some of those that worked on it that might not be extensively documented -- Ill file issues later.

For those concerned about performance, a path that could be taken in the future is to replace the use of Cairo in libgdiplus with Skia, and that would not affect the managed code at all, it would be a transparent swap out.

I would not go as far as @mellinoe has gone with his criticism of GDI+, I think some of it is painting it with a too wide brush, but this is right on target:

If you're building a new, modern, cross-platform UI stack, you really should be building on top of a library which was designed for such an environment, not GDI+.

Exactly. And given that there is something of the caliber of SkiaSharp, you should use that instead. And this is exactly what projects like Avalonia have done. Google is continuously evolving it, and we are keeping it fresh and up to date, and it is the foundation of two of the most used pieces of software in the world.

@FixBo

This comment has been minimized.

Show comment
Hide comment
@FixBo

FixBo Sep 27, 2017

Is there any chance to get netstandard stub like it done for Microsoft.Win32.Registry?

FixBo commented Sep 27, 2017

Is there any chance to get netstandard stub like it done for Microsoft.Win32.Registry?

@karelz

This comment has been minimized.

Show comment
Hide comment
@karelz

karelz Sep 28, 2017

Member

@FixBo which stub do you mean? Throwing PlatformNotSupported exceptions on platforms which are not supported?

Member

karelz commented Sep 28, 2017

@FixBo which stub do you mean? Throwing PlatformNotSupported exceptions on platforms which are not supported?

@danmosemsft

This comment has been minimized.

Show comment
Hide comment
@danmosemsft

danmosemsft Sep 28, 2017

Member

@FixBo you rae correct that we normally do that, eg in this case so code that references it could load on UAP (even if not use it). @FixBo what platform would you need this for -- what scenario?

Member

danmosemsft commented Sep 28, 2017

@FixBo you rae correct that we normally do that, eg in this case so code that references it could load on UAP (even if not use it). @FixBo what platform would you need this for -- what scenario?

@FixBo

This comment has been minimized.

Show comment
Hide comment
@FixBo

FixBo Sep 28, 2017

@danmosemsft I'm in process of porting a set of libraries to netstandard. Some part's of them relies on Drawing, eg document exporting/printing. On the other hand document generation/pdf export/dataaccess can work on pure netstandart.
For now I have three options: change target to netcore, split dlls, use a lot of defines.

FixBo commented Sep 28, 2017

@danmosemsft I'm in process of porting a set of libraries to netstandard. Some part's of them relies on Drawing, eg document exporting/printing. On the other hand document generation/pdf export/dataaccess can work on pure netstandart.
For now I have three options: change target to netcore, split dlls, use a lot of defines.

@qmfrederik

This comment has been minimized.

Show comment
Hide comment
@qmfrederik

qmfrederik Sep 28, 2017

Collaborator

@FixBo Is your issue that System.Drawing.Common targets netcoreapp2.0 but not netstandard?

Collaborator

qmfrederik commented Sep 28, 2017

@FixBo Is your issue that System.Drawing.Common targets netcoreapp2.0 but not netstandard?

@FixBo

This comment has been minimized.

Show comment
Hide comment

FixBo commented Sep 28, 2017

@qmfrederik Correct.

@qmfrederik

This comment has been minimized.

Show comment
Hide comment
@qmfrederik

qmfrederik Sep 28, 2017

Collaborator

@FixBo I think the plan is to have System.Drawing.Common target netstandard but @mellinoe can confirm.

Collaborator

qmfrederik commented Sep 28, 2017

@FixBo I think the plan is to have System.Drawing.Common target netstandard but @mellinoe can confirm.

@mellinoe

This comment has been minimized.

Show comment
Hide comment
@mellinoe

mellinoe Sep 28, 2017

Contributor

@qmfrederik At the moment, it actually relies on some private state in the Color structure which is not publically available in netstandard2.0, but are implemented (privately) in .NET Core 2.0. We would have to make some structural changes to the code to re-target to .NET Standard 2.0. Perhaps it is worth looking into after we are stable and solid.

Contributor

mellinoe commented Sep 28, 2017

@qmfrederik At the moment, it actually relies on some private state in the Color structure which is not publically available in netstandard2.0, but are implemented (privately) in .NET Core 2.0. We would have to make some structural changes to the code to re-target to .NET Standard 2.0. Perhaps it is worth looking into after we are stable and solid.

@jmroyb

This comment has been minimized.

Show comment
Hide comment
@jmroyb

jmroyb Oct 13, 2017

Will System.Drawing.ColorTranslator (I miss System.Drawing.ColorTranslator.FromHtml) be available at net core 2.1?

jmroyb commented Oct 13, 2017

Will System.Drawing.ColorTranslator (I miss System.Drawing.ColorTranslator.FromHtml) be available at net core 2.1?

@karelz

This comment has been minimized.

Show comment
Hide comment
@karelz

karelz Oct 13, 2017

Member

@safern can you please comment on FromHtml?

Member

karelz commented Oct 13, 2017

@safern can you please comment on FromHtml?

@VahidN

This comment has been minimized.

Show comment
Hide comment
@VahidN

VahidN Oct 16, 2017

I can't use https://www.nuget.org/packages/System.Drawing.Common from a .NET Standard project:
error NU1202: Package System.Drawing.Common 4.5.0-preview1-25718-03 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package System.Drawing.Common 4.5.0-preview1-25718-03 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)

Do you have any plan to make it compatible with .NET Standard projects too. Library authors would appreciate it.

VahidN commented Oct 16, 2017

I can't use https://www.nuget.org/packages/System.Drawing.Common from a .NET Standard project:
error NU1202: Package System.Drawing.Common 4.5.0-preview1-25718-03 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package System.Drawing.Common 4.5.0-preview1-25718-03 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)

Do you have any plan to make it compatible with .NET Standard projects too. Library authors would appreciate it.

@safern

This comment has been minimized.

Show comment
Hide comment
@safern

safern Oct 17, 2017

Member

I can't use https://www.nuget.org/packages/System.Drawing.Common from a .NET Standard project:
error NU1202: Package System.Drawing.Common 4.5.0-preview1-25718-03 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package System.Drawing.Common 4.5.0-preview1-25718-03 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)
Do you have any plan to make it compatible with .NET Standard projects too. Library authors would appreciate it.

Hi @VahidN thanks for bringing that up. We created issue: #24675 and I'll be solving the issue in the upcoming days.

Will System.Drawing.ColorTranslator (I miss System.Drawing.ColorTranslator.FromHtml) be available at net core 2.1?

I will have to look why we didn't port it from the beginning. @jmroyb I'll update you on that.

Member

safern commented Oct 17, 2017

I can't use https://www.nuget.org/packages/System.Drawing.Common from a .NET Standard project:
error NU1202: Package System.Drawing.Common 4.5.0-preview1-25718-03 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package System.Drawing.Common 4.5.0-preview1-25718-03 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)
Do you have any plan to make it compatible with .NET Standard projects too. Library authors would appreciate it.

Hi @VahidN thanks for bringing that up. We created issue: #24675 and I'll be solving the issue in the upcoming days.

Will System.Drawing.ColorTranslator (I miss System.Drawing.ColorTranslator.FromHtml) be available at net core 2.1?

I will have to look why we didn't port it from the beginning. @jmroyb I'll update you on that.

@mqudsi

This comment has been minimized.

Show comment
Hide comment
@mqudsi

mqudsi Dec 26, 2017

@mellinoe and others: it has taken me considerable time but I’ve read - carefully - through each article nd every comment here. Without weighing in on some of the implementation specific details, I have a question that was mentioned in passing but not addressed.

What is the benefit to providing this as a part of .NET Core? Please do not misunderstand me - I appreciate the importance of System.Drawing as a blocking dependency preventing any legacy codebases from migrating to .NET Core. But why must this be addressed by adding a legacy, deprecated, highly system-specific library to the actual .NET Core/Standard specification and implementation? To rephrase: how would simply providing a NuGet package that implements, via one or more of the means discussed above, System.Drawing on these specific platforms not be a sufficient stopgap to help these developers that do not have access to the needed resources to migrate to a better/more modern alternative?

By including this in .NET Core, we are not only committing to providing a solution for platforms currently supported by CoreFx but also severely restricting what platforms CoreFx can be easily ported to in the future.

It’s all well and good to discuss how awesome SkiaSharp support is on Linux and Android and whatnot, but what happens when someone wants to port CoreFx to SPARC or even just some archaic ARM variant not supported by Skia or libgdiplus or whatnot? What about FreeBSD? Or another OS not yet developed?

I am all for developing this library, but I think careful thought needs to be given to its repercussions. I am speaking as a die-hard SWF fan that shunned Silverlight, WPF, and XAML until Windows 10 Creators Update, when I finally embraced UWP. I deeply appreciate the difficulties in learning the subtleties and nuances of new toolkit’s and the difficulties in migrating to a platform with missing dependencies. But what is to be gained by bending over backwards to support System.Drawing?

It seems this discussion has almost derailed into a conversation about support SWF on CoreFx and lost sight of the initial goal: to make it easier for applications consuming SD to migrate to CoreFx. I would really appreciate if you would take a step back and perhaps reevaluate this. I do appreciate the time and effort already invested in this undertaking, but none of it need by lost, simply publishing everything discussed but under the context of a separate package than part of .NET Core would accomplish all the same goals.

Now to ask a different question that was previously asked but not answered: while SD is definitely a major blocking concern for users of legacy .NET FX apps on Windows blocking their migration to CoreFx, what is the actual number of projects that would benefit from this being a Windows-only NuGet package vs this giant effort to support it across all platforms? How many organizations currently using SD are expected to migrate to .NET Core if SD were available and expand to non-Windows platforms that haven’t already used a better alternative to SD/GDI+?

mqudsi commented Dec 26, 2017

@mellinoe and others: it has taken me considerable time but I’ve read - carefully - through each article nd every comment here. Without weighing in on some of the implementation specific details, I have a question that was mentioned in passing but not addressed.

What is the benefit to providing this as a part of .NET Core? Please do not misunderstand me - I appreciate the importance of System.Drawing as a blocking dependency preventing any legacy codebases from migrating to .NET Core. But why must this be addressed by adding a legacy, deprecated, highly system-specific library to the actual .NET Core/Standard specification and implementation? To rephrase: how would simply providing a NuGet package that implements, via one or more of the means discussed above, System.Drawing on these specific platforms not be a sufficient stopgap to help these developers that do not have access to the needed resources to migrate to a better/more modern alternative?

By including this in .NET Core, we are not only committing to providing a solution for platforms currently supported by CoreFx but also severely restricting what platforms CoreFx can be easily ported to in the future.

It’s all well and good to discuss how awesome SkiaSharp support is on Linux and Android and whatnot, but what happens when someone wants to port CoreFx to SPARC or even just some archaic ARM variant not supported by Skia or libgdiplus or whatnot? What about FreeBSD? Or another OS not yet developed?

I am all for developing this library, but I think careful thought needs to be given to its repercussions. I am speaking as a die-hard SWF fan that shunned Silverlight, WPF, and XAML until Windows 10 Creators Update, when I finally embraced UWP. I deeply appreciate the difficulties in learning the subtleties and nuances of new toolkit’s and the difficulties in migrating to a platform with missing dependencies. But what is to be gained by bending over backwards to support System.Drawing?

It seems this discussion has almost derailed into a conversation about support SWF on CoreFx and lost sight of the initial goal: to make it easier for applications consuming SD to migrate to CoreFx. I would really appreciate if you would take a step back and perhaps reevaluate this. I do appreciate the time and effort already invested in this undertaking, but none of it need by lost, simply publishing everything discussed but under the context of a separate package than part of .NET Core would accomplish all the same goals.

Now to ask a different question that was previously asked but not answered: while SD is definitely a major blocking concern for users of legacy .NET FX apps on Windows blocking their migration to CoreFx, what is the actual number of projects that would benefit from this being a Windows-only NuGet package vs this giant effort to support it across all platforms? How many organizations currently using SD are expected to migrate to .NET Core if SD were available and expand to non-Windows platforms that haven’t already used a better alternative to SD/GDI+?

@benaadams

This comment has been minimized.

Show comment
Hide comment
@benaadams

benaadams Dec 26, 2017

Collaborator

@mqudsi I assume its being provided via the Windows Compatibility Pack for .NET Core rather than being part of .NET Standard

Collaborator

benaadams commented Dec 26, 2017

@mqudsi I assume its being provided via the Windows Compatibility Pack for .NET Core rather than being part of .NET Standard

@safern

This comment has been minimized.

Show comment
Hide comment
@safern

safern Dec 26, 2017

Member

If I understand clearly your concern is that by adding System.Drawing to .NET Core it would make really hard to extend/port this platform to another framework, platform using different libraries right?

If that is your concern and I understood correctly, System.Drawing is not inbox in .NET Core neither netstandard, which means that it is shipped as an independent package in NuGet and if people want to use it they just reference that package in their project. This was done as a compatibility effort to make migration from .NET Framework to .NET Core easier. So we are accomplishing both goals, compatibility and we’re not adding this as part of the framework inbox. Which for your concern (which is reasonable) doesn’t affect you either from what I understood in your comment. Please feel free to correct me if that wasn’t your main concern.

To answer your last question, the point of .NET Core is provide portability and extensibility to different platforms, if developers have a .NET Framework app that use System.Drawing but they don’t want to port it because they don’t gain much because it will be Windows-Only supported (the same as they have in their current app), what would be the pint of this effort vs if we support it in Unix also, they gain the portability of their app for free and is a good incentive to move to .NET Core.

Member

safern commented Dec 26, 2017

If I understand clearly your concern is that by adding System.Drawing to .NET Core it would make really hard to extend/port this platform to another framework, platform using different libraries right?

If that is your concern and I understood correctly, System.Drawing is not inbox in .NET Core neither netstandard, which means that it is shipped as an independent package in NuGet and if people want to use it they just reference that package in their project. This was done as a compatibility effort to make migration from .NET Framework to .NET Core easier. So we are accomplishing both goals, compatibility and we’re not adding this as part of the framework inbox. Which for your concern (which is reasonable) doesn’t affect you either from what I understood in your comment. Please feel free to correct me if that wasn’t your main concern.

To answer your last question, the point of .NET Core is provide portability and extensibility to different platforms, if developers have a .NET Framework app that use System.Drawing but they don’t want to port it because they don’t gain much because it will be Windows-Only supported (the same as they have in their current app), what would be the pint of this effort vs if we support it in Unix also, they gain the portability of their app for free and is a good incentive to move to .NET Core.

@safern

This comment has been minimized.

Show comment
Hide comment
@safern

safern Dec 26, 2017

Member

@mqudsi I assume its being provided via the Windows Compatibility Pack for .NET Core rather than being part of .NET Standard

Correct, and also as an individual package in NuGet.

Member

safern commented Dec 26, 2017

@mqudsi I assume its being provided via the Windows Compatibility Pack for .NET Core rather than being part of .NET Standard

Correct, and also as an individual package in NuGet.

@mqudsi

This comment has been minimized.

Show comment
Hide comment
@mqudsi

mqudsi Dec 26, 2017

Thank you! This is my second forray into the github page for CoreFX (first was my PR from earlier today) and presumed the issue being here meant it was part of “core” CoreFx.

Thanks for clarifying!

mqudsi commented Dec 26, 2017

Thank you! This is my second forray into the github page for CoreFX (first was my PR from earlier today) and presumed the issue being here meant it was part of “core” CoreFx.

Thanks for clarifying!

@JimBobSquarePants

This comment has been minimized.

Show comment
Hide comment
@JimBobSquarePants

JimBobSquarePants Dec 27, 2017

To answer your last question, the point of .NET Core is provide portability and extensibility to different platforms, if developers have a .NET Framework app that use System.Drawing but they don’t want to port it because they don’t gain much because it will be Windows-Only supported (the same as they have in their current app), what would be the pint of this effort vs if we support it in Unix also, they gain the portability of their app for free and is a good incentive to move to .NET Core.

I would argue that offering System.Drawing support on Unix would offer zero incentive to move to .NET Core

To answer your last question, the point of .NET Core is provide portability and extensibility to different platforms, if developers have a .NET Framework app that use System.Drawing but they don’t want to port it because they don’t gain much because it will be Windows-Only supported (the same as they have in their current app), what would be the pint of this effort vs if we support it in Unix also, they gain the portability of their app for free and is a good incentive to move to .NET Core.

I would argue that offering System.Drawing support on Unix would offer zero incentive to move to .NET Core

@qmfrederik

This comment has been minimized.

Show comment
Hide comment
@qmfrederik

qmfrederik Dec 27, 2017

Collaborator

I would argue that offering System.Drawing support on Unix would offer zero incentive to move to .NET Core

There seems to be demand for System.Drawing on .NET Core; CoreCompat.System.Drawing, CoreCompat.System.Drawing.v2 and System.Drawing.Common combined have over 300,000 downloads on NuGet.

To put the "giant effort to support it across all platforms" in some context: Mono has ported System.Drawing to Linux and macOS more than 10 years ago. They've also made libgdiplus compatible with ARM-based OSes such as Android and iOS. What CoreFX is doing is consolidating the Windows, Linux and macOS implementations of System.Drawing.

At the end of the day, it's another NuGet package which is available to you, and you're free to use any imaging library which meets your requirements 😄.

Collaborator

qmfrederik commented Dec 27, 2017

I would argue that offering System.Drawing support on Unix would offer zero incentive to move to .NET Core

There seems to be demand for System.Drawing on .NET Core; CoreCompat.System.Drawing, CoreCompat.System.Drawing.v2 and System.Drawing.Common combined have over 300,000 downloads on NuGet.

To put the "giant effort to support it across all platforms" in some context: Mono has ported System.Drawing to Linux and macOS more than 10 years ago. They've also made libgdiplus compatible with ARM-based OSes such as Android and iOS. What CoreFX is doing is consolidating the Windows, Linux and macOS implementations of System.Drawing.

At the end of the day, it's another NuGet package which is available to you, and you're free to use any imaging library which meets your requirements 😄.

@clrjunkie

This comment has been minimized.

Show comment
Hide comment
@clrjunkie

clrjunkie Dec 27, 2017

There seems to be demand for System.Drawing on .NET Core; CoreCompat.System.Drawing, CoreCompat.System.Drawing.v2 and System.Drawing.Common combined have over 300,000 downloads on NuGet.

Now that System.Drawing is out of the BCL (a good thing) I think it's important we have new basic (but quality) image manipulation support as part of the BCL, specifically for image resizing and rotation which does not mandate any external dependency.

There seems to be demand for System.Drawing on .NET Core; CoreCompat.System.Drawing, CoreCompat.System.Drawing.v2 and System.Drawing.Common combined have over 300,000 downloads on NuGet.

Now that System.Drawing is out of the BCL (a good thing) I think it's important we have new basic (but quality) image manipulation support as part of the BCL, specifically for image resizing and rotation which does not mandate any external dependency.

@danmosemsft

This comment has been minimized.

Show comment
Hide comment
@danmosemsft

danmosemsft Feb 2, 2018

Member

@safern is this issue still useful? We already have an issue to track marking the compat pack stable. If we want to track consolidating the Windows and Unix code further it would probably make sense to have a new more focused issue.

Member

danmosemsft commented Feb 2, 2018

@safern is this issue still useful? We already have an issue to track marking the compat pack stable. If we want to track consolidating the Windows and Unix code further it would probably make sense to have a new more focused issue.

@safern

This comment has been minimized.

Show comment
Hide comment
@safern

safern Feb 2, 2018

Member

Agree. We can close this issue.

Member

safern commented Feb 2, 2018

Agree. We can close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment