Skip to content

Commit

Permalink
removed old images to make way for multiple image sets
Browse files Browse the repository at this point in the history
  • Loading branch information
gingerbeardman committed Dec 14, 2010
1 parent 4b001ef commit 65b410a
Show file tree
Hide file tree
Showing 12 changed files with 62 additions and 16 deletions.
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ The following blend modes work perfectly (or as nearly as the [vagaries of the H
* `multiply`
* `difference`

These blend modes mostly work as intended:
These blend modes mostly work as intended, but have issues when it comes to dealing with the alpha channel:

* `src-in` - the output of this blend mode is slightly different from the effect
of applying the transparency of one layer as a mask to another; the difference only appears
Expand All @@ -66,21 +66,34 @@ These blend modes mostly work as intended:
of either/both images, the more the colors get high contrast.
* ![comparison of result versus intended for add blend mode](http://phrogz.net/tmp/context-blender_overlay.png)

These blend modes are known to be broken:
* `hardlight` - this is the opposite of "overlay" and same caveats apply

* `colordodge` (or `dodge`)
* ![comparison of result versus intended for dodge blend mode](http://phrogz.net/tmp/context-blender_dodge.png)

* `colorburn` (or `burn`)

* `darken`

* `lighten`

* `exclusion`

## Requirements/Browser Support

Tested on Safari v5.0, Chrome v8, and FF v3.6. Should work on any user agent that supplies a
`CanvasRenderingContext2D` along with `getImageData` and `putImageData`.


## About

This library was created around the need solely for a one-off 'screen' blend mode to match the company-mandated style for bar graphs used internally, previously only available via a Microsoft® Excel® template. Clearly this functionality is useful in more contexts than just my one-off, so I decided to make a framework around it and encourage others to help figure out the formulae. Please, fork this project, add blend modes and/or fix math, and send me pull requests! I feel certain that the resources must exist out there on the equations Photoshop uses in the presence of alpha, but so far I have not found them.

## Reference Material
[PDF Blend Modes: Addendum (January 23, 2006)](http://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/pdf_reference_archives/blend_modes.pdf) PDF
[SVG Compositing 1.2, Part 1: Primer](http://dev.w3.org/SVG/modules/compositing/master/SVGCompositingPrimer.html)
[Custom blend modes for Flash 10](http://www.lostinactionscript.com/blog/index.php/2009/05/26/custom-blend-modes-for-flash-10/) blog post
[Blend Modes in Delphi](http://www.pegtop.net/delphi/articles/blendmodes/) blog post

### License

This library is released under an MIT-style license. That generally means that you are free to do almost anything you want with it as long as you give a bit of credit where credit is due. See the LICENSE file included for the actual legal limitations.
59 changes: 46 additions & 13 deletions context_blender.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ if (window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype.getIma
dst[px+1] = (sGA + dGA - 2 * Math.min( sGA*dA, dGA*sA )) * demultiply;
dst[px+2] = (sBA + dBA - 2 * Math.min( sBA*dA, dBA*sA )) * demultiply;
break;
// ******* Slightly different from Photoshop

// ******* Slightly different from Photoshop, where alpha is concerned
case 'src-in':
// Only differs from Photoshop in low-opacity areas
dA2 = sA*dA;
Expand Down Expand Up @@ -113,20 +113,53 @@ if (window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype.getIma
// dst[px+2] = ( (sBA < 0.5) ? (2 * dBA * sBA) : (1 - 2 * (1 - sBA) * (1 - dBA)) ) * demultiply;
break;

// ******* BROKEN
case 'hardlight':
// opposite of overlay, same caveats apply as to how well it works
dst[px ] = (sRA<=0.5) ? (2*dst[px ]*sRA/dA) : 255 - (2 - 2*sRA/sA) * (255-dst[px ]);
dst[px+1] = (sGA<=0.5) ? (2*dst[px+1]*sGA/dA) : 255 - (2 - 2*sGA/sA) * (255-dst[px+1]);
dst[px+2] = (sBA<=0.5) ? (2*dst[px+2]*sBA/dA) : 255 - (2 - 2*sBA/sA) * (255-dst[px+2]);
break;

case 'colordodge':
case 'dodge':
if (src[px ]==255 && dRA==0) dst[px ] = sRA*(1-dA) * demultiply;
else if (src[px ]==255) dst[px ] = (sA*dA + sRA*(1-dA) + dRA*(1-sA)) * demultiply;
else if (sRA<sA) dst[px ] = Math.min( sA*dA, dRA*sA/(sA*dA - sRA*dA)) * demultiply;
if ( src[px ] == 255 && dRA==0) dst[px ] = 255;
else dst[px ] = Math.min(255, dst[px ]/(255 - src[px ])) * demultiply;

if ( src[px+1] == 255 && dGA==0) dst[px+1] = 255;
else dst[px+1] = Math.min(255, dst[px+1]/(255 - src[px+1])) * demultiply;

if ( src[px+2] == 255 && dBA==0) dst[px+2] = 255;
else dst[px+2] = Math.min(255, dst[px+2]/(255 - src[px+2])) * demultiply;
break;

case 'colorburn':
case 'burn':
if ( src[px ] == 0 && dRA==0) dst[px ] = 0;
else dst[px ] = (1 - Math.min(1, (1 - dRA)/sRA)) * demultiply;

if ( src[px+1] == 0 && dGA==0) dst[px+1] = 0;
else dst[px+1] = (1 - Math.min(1, (1 - dGA)/sGA)) * demultiply;

if (src[px+1]==255 && dGA==0) dst[px+1] = sGA*(1-dA) * demultiply;
else if (src[px+1]==255) dst[px+1] = (sA*dA + sGA*(1-dA) + dGA*(1-sA)) * demultiply;
else if (sGA<sA) dst[px+1] = Math.min( sA*dA, dGA*sA/(sA*dA - sGA*dA)) * demultiply;
if ( src[px+2] == 0 && dBA==0) dst[px+2] = 0;
else dst[px+2] = (1 - Math.min(1, (1 - dBA)/sBA)) * demultiply;
break;

case 'darken':
dst[px ] = Math.min( sRA, dRA*dA) * demultiply;
dst[px+1] = Math.min( sGA, dGA*dA) * demultiply;
dst[px+2] = Math.min( sBA, dBA*dA) * demultiply;
break;

case 'lighten':
dst[px ] = Math.max( sRA, dRA*dA) * demultiply;
dst[px+1] = Math.max( sGA, dGA*dA) * demultiply;
dst[px+2] = Math.max( sBA, dBA*dA) * demultiply;
break;

if (src[px+2]==255 && dBA==0) dst[px+2] = sBA*(1-dA) * demultiply;
else if (src[px+2]==255) dst[px+2] = (sA*dA + sBA*(1-dA) + dBA*(1-sA)) * demultiply;
else if (sBA<sA) dst[px+2] = Math.min( sA*dA, dBA*sA/(sA*dA - sBA*dA)) * demultiply;
case 'exclusion':
dst[px ] = (dRA+sRA - 2*dRA*sRA) * demultiply;
dst[px+1] = (dGA+sGA - 2*dGA*sGA) * demultiply;
dst[px+2] = (dBA+sBA - 2*dBA*sBA) * demultiply;
break;

// ******* UNSUPPORTED
Expand All @@ -139,7 +172,7 @@ if (window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype.getIma
destContext.putImageData(dstD,offsets.destX,offsets.destY);
};
// For querying of functionality from other libraries
var modes = CanvasRenderingContext2D.prototype.blendOnto.supportedBlendModes = 'normal src-over screen multiply difference src-in plus add'.split(' ');
var modes = CanvasRenderingContext2D.prototype.blendOnto.supportedBlendModes = 'normal src-over screen multiply difference src-in plus add overlay hardlight colordodge dodge colorburn burn darken lighten exclusion'.split(' ');
var supports = CanvasRenderingContext2D.prototype.blendOnto.supports = {};
for (var i=0,len=modes.length;i<len;++i) supports[modes[i]] = true;
}
Binary file removed test/multi_add.png
Binary file not shown.
Binary file removed test/multi_difference.png
Binary file not shown.
Binary file removed test/multi_dodge.png
Binary file not shown.
Binary file removed test/multi_multiply.png
Binary file not shown.
Binary file removed test/multi_normal.png
Binary file not shown.
Binary file removed test/multi_overlay.png
Binary file not shown.
Binary file removed test/multi_screen.png
Binary file not shown.
Binary file removed test/multi_src-in.png
Binary file not shown.
Binary file removed test/over.png
Binary file not shown.
Binary file removed test/under.png
Binary file not shown.

0 comments on commit 65b410a

Please sign in to comment.