Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Porter-Duff enumaration split in two #535

Closed
4 tasks done
vpenades opened this issue Apr 18, 2018 · 6 comments
Closed
4 tasks done

Porter-Duff enumaration split in two #535

vpenades opened this issue Apr 18, 2018 · 6 comments

Comments

@vpenades
Copy link
Contributor

vpenades commented Apr 18, 2018

Prerequisites

  • I have written a descriptive issue title
  • I have verified that I am running the latest version of ImageSharp
  • I have verified if the problem exist in both DEBUG and RELEASE mode
  • I have searched open and closed issues to ensure it has not already been reported

Description

Right now, the Porter-Duff blend modes enumeration is a plain list of modes, but I noticed that some of the enumerated values are in fact a combination of two effects.

I think the enumeration could be split in two enumerations:

enum ColorBlendMode
{
    Source,
    Destination,
    Multiply,
    Add,
    Substract,
    Screen,
    Darken,
    Lighten,
    Overlay,
    HardLight,
}

and

enum AlphaBlendMode
{
    Clear,
    Atop,
    Over,
    In,
    Out,
    Xor
}

This would cover all current blending options, plus new ones currently unavailable.

This would allow having blend modes like Multiply + In and Multiply + Out that are very useful for dropping inner/outer shadows and other kind of effects.

Normal blend mode would be Source + Over

Steps to Reproduce

System Configuration

  • ImageSharp version: Beta 3
  • Other ImageSharp packages and versions:
  • Environment (Operating system, version and so on):
  • .NET Framework version:
  • Additional information:
@vpenades vpenades changed the title Porter-Duff enumaration split with flags Porter-Duff enumaration split in two Apr 18, 2018
@JimBobSquarePants
Copy link
Member

@vpenades You definitely know a lot more about this than I do. Fancy giving a PR a go?

@vpenades
Copy link
Contributor Author

@JimBobSquarePants Right now my hands are full at work and on another side project... maybe I could try to do something in two weeks if nobody else picks the task.

Just did a fast overview of the code, and it implies changing the T4 template generators so they can produce more pixel blender combinations.

@JimBobSquarePants
Copy link
Member

Leave as much detail as you can here describing the required changes and we'll see what we can do.

A bit rushed myself just now so completely understand.

@vpenades
Copy link
Contributor Author

vpenades commented Apr 19, 2018

Ok, here's more or less:

The current set of PixelBlenders generated with the T4 has two flavours:

So it's like if you have a NxM, but only Nx1 and 1xM combinations are being generated.

The current pixel blender generators look like this:

// Color blenders using alpha "SourceOver" composition
GeneratePixelBlender("Multiply");
GeneratePixelBlender("Add");
GeneratePixelBlender("Subtract");
.
.

// Alpha composers using "Source" color
GeneratePixelBlender("Atop");
GeneratePixelBlender("Over");
GeneratePixelBlender("In");
.
.

And I think the T4 template generator should be changed so the generators would look like this:

GeneratePixelBlender("Source","SourceOver"); // Generates Source-SourceOver AKA Normal
.
.

GeneratePixelBlender("Multiply","SourceAtop"); // Generates Multiply-SourceAtop
GeneratePixelBlender("Multiply","SourceOver"); // Generates Multiply-SourceOver
GeneratePixelBlender("Multiply","SourceIn");      // Generates Multiply-SourceIn
.
.

GeneratePixelBlender("Add","SourceAtop"); // Generates Add-SourceAtop
GeneratePixelBlender("Add","SourceOver"); // Generates Add-SourceOver
GeneratePixelBlender("Add","SourceIn");      // Generates Add-SourceIn
.
.

A hurdle for doing this is that the code for each Color Blender is custom code, so the generator needs some way of getting such code, maybe with a switch statement within the generator.

Once all the ColorBlender x AlphaComposer combinations are ready, it's about splitting the enum into Alpha and Color blend modes, which would affect the API surface quite a lot.

An alternative from splitting the enum to avoid heavy API surface changes would be to declare it with flags, something like that:

[flags]
enum BlendMode
{
  ColorMask = 255,  
  ColorSource = 1,
  ColorDest = 2,
  ColorMultiply = 3,
  ColorAdd = 4,
  .
  .
  AlphaMask = 255 << 8,
  AlphaSourceAtop = 1 << 8,
  AlphaSourceOver = 2 << 8,
  AlphaSourceIn = 3 <<8,
  AlphaSourceOut = 4 <<8,
  AlphaDestAtop = 5 << 8,
  AlphaDestOver = 6 << 8,
  AlphaDestIn = 7 <<8,
  AlphaDestOut = 8 <<8
.
.
}

So defining a specific mode would look like this:

mode = BlendMode.ColorMultiply | BlendMode.AlphaOver;

Also, changing the big span processors here would be required.

@vpenades
Copy link
Contributor Author

@dlemstra I had to undo some of your changes in order to easily allow all combinations; right now I'm looking only for something that works, I'm open to improvements and optimizations.

@JimBobSquarePants @tocsoft let me know if you see something fishy; I know this part of the code is quite critical.

JimBobSquarePants added a commit that referenced this issue Aug 19, 2018
WIP Generate all Pixel Blender/Composer possible combinations to solve #535
@vpenades
Copy link
Contributor Author

@JimBobSquarePants Thanks!

Now that we have the building blocks to move on, here's the proposal:

Until now, with the current PixelBlenderMode enumeration we can choose to do Color Blending (Add, Multiply) OR Alpha Composition (SrcOver, SrcAtop)... but not both at the same time.

In order to support combined operations, I would like to propose splitting BlendMode in two enumerations:

enum ColorBlendingMode
{
Normal,
Add,
Multiply,
Subtract,
etc
}
enum AlphaCompositionMode
{
Src,
SrcOver,
SrcAtop
Dst,
DstOver,
DstAtop,
etc
}

Also, GraphicsOptions would replace BlenderMode property with ColorBlending and AlphaComposition properties.

In most cases, users will probably need to change only the ColorBlending property as they used to do with BlenderMode , and only those that would require doing masking operations would also change 'AlphaComposition'

The only drawback is that the PixelBlender selector here becomes more convoluted, and will require a two tier switch.

antonfirsov pushed a commit to antonfirsov/ImageSharp that referenced this issue Nov 11, 2019
WIP Generate all Pixel Blender/Composer possible combinations to solve SixLabors#535
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants