From f4202fcacdcc5b8834bca816c12050e386aec7e7 Mon Sep 17 00:00:00 2001 From: kimikage Date: Wed, 8 Apr 2020 03:28:29 +0900 Subject: [PATCH] Update docs (#11) --- README.md | 2 +- docs/make.jl | 22 +++- docs/src/assets/blue.png | Bin 0 -> 324 bytes docs/src/assets/checker16.png | Bin 0 -> 86 bytes docs/src/assets/green.png | Bin 0 -> 471 bytes docs/src/assets/mix.css | 53 ++++++++- docs/src/assets/source-atop_normal.svg | 15 +++ docs/src/assets/source-over_normal.svg | 15 +++ docs/src/{blendmodes.md => blend-modes.md} | 64 +++------- docs/src/blending-and-compositing.md | 110 ++++++++++++++++++ docs/src/composite-operations.md | 53 +++++++++ .../{functionindex.md => function-index.md} | 0 docs/src/index.md | 1 + 13 files changed, 283 insertions(+), 52 deletions(-) create mode 100644 docs/src/assets/blue.png create mode 100644 docs/src/assets/checker16.png create mode 100644 docs/src/assets/green.png create mode 100644 docs/src/assets/source-atop_normal.svg create mode 100644 docs/src/assets/source-over_normal.svg rename docs/src/{blendmodes.md => blend-modes.md} (65%) create mode 100644 docs/src/blending-and-compositing.md create mode 100644 docs/src/composite-operations.md rename docs/src/{functionindex.md => function-index.md} (100%) diff --git a/README.md b/README.md index d85f464..d424389 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ColorBlendModes [![Docs Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://kimikage.github.io/ColorBlendModes.jl/stable) -[![Docs Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://kimikage.github.io/ColorBlendModes.jl/dev) +[![Docs Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://kimikage.github.io/ColorBlendModes.jl/dev) [![Build Status](https://travis-ci.com/kimikage/ColorBlendModes.jl.svg?branch=master)](https://travis-ci.com/kimikage/ColorBlendModes.jl) [![Codecov](https://codecov.io/gh/kimikage/ColorBlendModes.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/kimikage/ColorBlendModes.jl) diff --git a/docs/make.jl b/docs/make.jl index fdbd008..37850aa 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -23,6 +23,22 @@ module CompositingExamples PNGFiles.save(joinpath("assets", keyword(bm) * ".png"), out) nothing end + + function generate(bm::BlendMode, opacity::Int) + blue = load_image("blue.png") + green = load_image("green.png") + out = blend.(blue, green, mode=bm, opacity=opacity/100) + PNGFiles.save(joinpath("assets", keyword(bm) * "_" * string(opacity) * ".png"), out) + nothing + end + + function generate(op::CompositeOperation, bm::BlendMode) + blue = load_image("blue.png") + green = load_image("green.png") + out = blend.(blue, green, mode=bm, op=op) + PNGFiles.save(joinpath("assets", keyword(op) * "_" * keyword(bm) * ".png"), out) + nothing + end end makedocs( @@ -34,8 +50,10 @@ makedocs( sitename = "ColorBlendModes", pages = Any[ "Introduction" => "index.md", - "Blend Modes" => "blendmodes.md", - "Index" => "functionindex.md", + "Blending and Compositing" => "blending-and-compositing.md", + "Blend Modes" => "blend-modes.md", + "Composite Operations" => "composite-operations.md", + "Index" => "function-index.md", ] ) diff --git a/docs/src/assets/blue.png b/docs/src/assets/blue.png new file mode 100644 index 0000000000000000000000000000000000000000..9865d83ec794baed322e492bf0b1a70632cd0214 GIT binary patch literal 324 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?I3?vN&YJLDI(Ey(iSBK;qAe3~~A?Z3$%pv7E z5PjU%t^nk)mjw9*m;bkEU}$iN*)cT?D0JP^#WAFUF)2kP;Q)6F#|h(`#t+y(u{@a> zVJ8sa;30RRPgaJbHFEr*DPE%&H*|?gTe~DWM4f#i5_T literal 0 HcmV?d00001 diff --git a/docs/src/assets/mix.css b/docs/src/assets/mix.css index 6c37938..da46ecc 100644 --- a/docs/src/assets/mix.css +++ b/docs/src/assets/mix.css @@ -15,10 +15,57 @@ div.mix { display: inline-block; } } +div.normal div { + mix-blend-mode: normal; +} +div.multiply div { + mix-blend-mode: multiply; +} +div.screen div { + mix-blend-mode: screen; +} +div.overlay div { + mix-blend-mode: overlay; +} +div.darken div { + mix-blend-mode: darken; +} +div.lighten div { + mix-blend-mode: lighten; +} +div.color-dodge div { + mix-blend-mode: color-dodge; +} +div.color-burn div { + mix-blend-mode: color-burn; +} +div.hard-light div { + mix-blend-mode: hard-light; +} +div.soft-light div { + mix-blend-mode: soft-light; +} +div.difference div { + mix-blend-mode: difference; +} +div.exclusion div { + mix-blend-mode: exclusion; +} +div.hue div { + mix-blend-mode: hue; +} +div.saturation div { + mix-blend-mode: saturation; +} +div.color div { + mix-blend-mode: color; +} +div.luminosity div { + mix-blend-mode: luminosity; +} div.mix div { position: absolute; - mix-blend-mode: inherit; width: 256px; height: 256px; background: url('juliadots.png'); @@ -43,3 +90,7 @@ div.mix:hover div:first-child { div.mix:hover div:last-child { transform:translateY(16%); } + +article td img { + background: url('checker16.png'); +} diff --git a/docs/src/assets/source-atop_normal.svg b/docs/src/assets/source-atop_normal.svg new file mode 100644 index 0000000..7d0faf8 --- /dev/null +++ b/docs/src/assets/source-atop_normal.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/src/assets/source-over_normal.svg b/docs/src/assets/source-over_normal.svg new file mode 100644 index 0000000..ac91ef9 --- /dev/null +++ b/docs/src/assets/source-over_normal.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/src/blendmodes.md b/docs/src/blend-modes.md similarity index 65% rename from docs/src/blendmodes.md rename to docs/src/blend-modes.md index 0d9463c..44d9265 100644 --- a/docs/src/blendmodes.md +++ b/docs/src/blend-modes.md @@ -12,9 +12,7 @@ CompositingExamples.generate(BlendNormal) # hide ``` ![normal](assets/normal.png) ```@raw html -
-
-
+
``` ```@docs @@ -27,9 +25,7 @@ CompositingExamples.generate(BlendMultiply) # hide ``` ![multiply](assets/multiply.png) ```@raw html -
-
-
+
``` ```@docs BlendMultiply @@ -40,9 +36,7 @@ CompositingExamples.generate(BlendScreen) # hide ``` ![screen](assets/screen.png) ```@raw html -
-
-
+
``` ```@docs BlendScreen @@ -54,9 +48,7 @@ CompositingExamples.generate(BlendOverlay) # hide ``` ![overlay](assets/overlay.png) ```@raw html -
-
-
+
``` ```@docs BlendOverlay @@ -68,9 +60,7 @@ CompositingExamples.generate(BlendDarken) # hide ``` ![darken](assets/darken.png) ```@raw html -
-
-
+
``` ```@docs BlendDarken @@ -82,9 +72,7 @@ CompositingExamples.generate(BlendLighten) # hide ``` ![lighten](assets/lighten.png) ```@raw html -
-
-
+
``` ```@docs BlendLighten @@ -96,9 +84,7 @@ CompositingExamples.generate(BlendColorDodge) # hide ``` ![color-dodge](assets/color-dodge.png) ```@raw html -
-
-
+
``` ```@docs BlendColorDodge @@ -110,9 +96,7 @@ CompositingExamples.generate(BlendColorBurn) # hide ``` ![color-burn](assets/color-burn.png) ```@raw html -
-
-
+
``` ```@docs BlendColorBurn @@ -124,9 +108,7 @@ CompositingExamples.generate(BlendHardLight) # hide ``` ![hard-light](assets/hard-light.png) ```@raw html -
-
-
+
``` ```@docs BlendHardLight @@ -138,9 +120,7 @@ CompositingExamples.generate(BlendSoftLight) # hide ``` ![soft-light](assets/soft-light.png) ```@raw html -
-
-
+
``` ```@docs BlendSoftLight @@ -151,9 +131,7 @@ CompositingExamples.generate(BlendDifference) # hide ``` ![difference](assets/difference.png) ```@raw html -
-
-
+
``` ```@docs BlendDifference @@ -164,9 +142,7 @@ CompositingExamples.generate(BlendExclusion) # hide ``` ![exclusion](assets/exclusion.png) ```@raw html -
-
-
+
``` ```@docs BlendExclusion @@ -177,9 +153,7 @@ CompositingExamples.generate(BlendHue) # hide ``` ![hue](assets/hue.png) ```@raw html -
-
-
+
``` ```@docs BlendHue @@ -190,9 +164,7 @@ CompositingExamples.generate(BlendSaturation) # hide ``` ![saturation](assets/saturation.png) ```@raw html -
-
-
+
``` ```@docs BlendSaturation @@ -203,9 +175,7 @@ CompositingExamples.generate(BlendColor) # hide ``` ![color](assets/color.png) ```@raw html -
-
-
+
``` ```@docs BlendColor @@ -216,9 +186,7 @@ CompositingExamples.generate(BlendLuminosity) # hide ``` ![luminosity](assets/luminosity.png) ```@raw html -
-
-
+
``` ```@docs BlendLuminosity diff --git a/docs/src/blending-and-compositing.md b/docs/src/blending-and-compositing.md new file mode 100644 index 0000000..e47f467 --- /dev/null +++ b/docs/src/blending-and-compositing.md @@ -0,0 +1,110 @@ +# Blending and Compositing + +## Types for specifying modes +ColorBlendModes defines two types for specifying modes: [`BlendMode`](@ref) for +the mixing of opaque colors, and [`CompositeOperation`](@ref) for the +generalized alpha compositing. + +The users typically do not need to handle these types directly. Instead, the +users can handle the predefined singleton instances of those types, e.g. +[`BlendMultiply`](@ref multiply), [`BlendScreen`](@ref screen) and +[`BlendOverlay`](@ref overlay) for [`BlendMode`](@ref), or +[`CompositeSourceOver`](@ref source-over) and +[`CompositeSourceAtop`](@ref source-atop) for [`CompositeOperation`](@ref). See +[Blend Modes](@ref) and [Composite Operations](@ref) for all supported modes and +their examples. Note that these predefined constants look like types, but are +just instances. + +```@docs +BlendMode +CompositeOperation +``` + +## Blending and compositing function +The [`blend`](@ref) function creates the mixed color of two colors based on +the specified blend mode and composite operation. +```@docs +blend +``` +For example: +```jldoctest ex; setup = :(using ColorBlendModes, ColorTypes, FixedPointNumbers;) +julia> blend(RGB(1, 0.5, 0), RGB(0, 0.5, 1), mode=BlendLighten) +RGB{Float64}(1.0,0.5,1.0) +``` + +### Broadcasting +The [`blend`](@ref) function is compatible with the broadcasting. Therefore, +you can blend two images with the same size. +```jldoctest ex +julia> image1 = [RGB(r, 1, b) for r=0:1, b=0:1] +2×2 Array{RGB{N0f8},2} with eltype RGB{Normed{UInt8,8}}: + RGB{N0f8}(0.0,1.0,0.0) RGB{N0f8}(0.0,1.0,1.0) + RGB{N0f8}(1.0,1.0,0.0) RGB{N0f8}(1.0,1.0,1.0) + +julia> image2 = [RGB(r, g, 0) for g=0:1, r=0:1] +2×2 Array{RGB{N0f8},2} with eltype RGB{Normed{UInt8,8}}: + RGB{N0f8}(0.0,0.0,0.0) RGB{N0f8}(1.0,0.0,0.0) + RGB{N0f8}(0.0,1.0,0.0) RGB{N0f8}(1.0,1.0,0.0) + +julia> blend.(image1, image2, mode=BlendMultiply) +2×2 Array{RGB{N0f8},2} with eltype RGB{Normed{UInt8,8}}: + RGB{N0f8}(0.0,0.0,0.0) RGB{N0f8}(0.0,0.0,0.0) + RGB{N0f8}(0.0,1.0,0.0) RGB{N0f8}(1.0,1.0,0.0) +``` +### Opacity +The keyword argument `opacity` controls the alpha of source color `c2`. If `c2` +is a opaque color, the `opacity` is used as the source alpha. If `c2` is a +transparent color, `opacity * alpha(c2)` is used as the source alpha. The +`opacity` is useful when used with broadcasting, i.e. the `opacity` acts as +so-called "layer opacity". + +The following are examples where an image of green triangles (`image_green`) is +layered on an image of blue triangles (`image_blue`). +```@example ex +using ColorBlendModes # hide +using Main: CompositingExamples # hide +image_blue, image_green = [],[] # hide +for mode in (BlendNormal, BlendMultiply, BlendScreen) + for opacity in (25, 50, 75, 100) + blend.(image_blue, image_green, mode=mode, opacity=opacity/100) + CompositingExamples.generate(mode, opacity) # hide + end +end +``` + +|blend mode|`opacity=0.25`|`opacity=0.5 `|`opacity=0.75`|`opacity=1.0 ` (default)| +|:--------:|:------------:|:------------:|:------------:|:----------------------:| +|normal|![normal25%](assets/normal_25.png)|![normal50%](assets/normal_50.png)|![normal75%](assets/normal_75.png)|![normal100%](assets/normal_100.png)| +|multiply|![multiply25%](assets/multiply_25.png)|![multiply50%](assets/multiply_50.png)|![multiply75%](assets/multiply_75.png)|![multiply100%](assets/multiply_100.png)| +|screen|![screen25%](assets/screen_25.png)|![screen50%](assets/screen_50.png)|![screen75%](assets/screen_75.png)|![screen100%](assets/screen_100.png)| + +!!! note + The `opacity` is typically specified in the range [0,1]. A value out of the + range can be specified, but the [`blend`](@ref) function does not clip + the intermediate values. Therefore an arbitrary color may be returned. + +## Calling with singleton instances + +For convenience, the instances of [`BlendMode`](@ref) and +[`CompositeOperation`](@ref) are callable. They are equivalent to the +[`blend`](@ref) function, with the instance assigned to the keyword argument +`mode` or `op`. +```jldoctest ex +julia> c1 = RGBA(1, 0.5, 0, 0.5); c2 = RGB(0, 0.5, 1); + +julia> BlendMultiply(c1, c2) === blend(c1, c2, mode=BlendMultiply) +true + +julia> CompositeSourceOver(c1, c2) === blend(c1, c2, op=CompositeSourceOver) +true + +julia> BlendDarken(c1, c2, opacity=0.25, op=CompositeSourceAtop) +RGBA{Float64}(0.75,0.5,0.125,0.5) + +julia> CompositeSourceAtop(c1, c2, opacity=0.25, mode=BlendDarken) +RGBA{Float64}(0.75,0.5,0.125,0.5) +``` + +However, it is not recommended to call the predefined constants directly, e.g. +`BlendMultiply(c1, c2)`. They are should be called via method arguments or local +variables. diff --git a/docs/src/composite-operations.md b/docs/src/composite-operations.md new file mode 100644 index 0000000..6c6239a --- /dev/null +++ b/docs/src/composite-operations.md @@ -0,0 +1,53 @@ +# Composite Operations +The [`CompositeOperation`](@ref) type represents the Porter-Duff operators, +or the modes of generalized alpha compositing. + +The general form of the Porter-Duff equation is: +``` + αo = αsrc × Fa + αb × Fb + co = αsrc × Fa × Csrc + αb × Fb × Cb + Co = co / αo +``` +where: +- `αo` is the output alpha +- `αsrc` and `αb` are the source alpha and backdrop alpha +- `Fa` and `Fb` are defined by the operator in use +- `co` is the output color pre-multiplied with the output alpha `α0` +- `Csrc` and `Cb` are the source color and backdrop color +- `Co` is the output color + +Note that the "destination" means the "backdrop", not the "output" in this +context. + +The following two images are used as examples below. + +| Destination (backdrop) | Source | +|:-----------------------------:|:-------------------------:| +|![destination](assets/blue.png)|![source](assets/green.png)| + + +## source-over +```@example ex +using ColorBlendModes # hide +using Main: CompositingExamples # hide +CompositingExamples.generate(CompositeSourceOver, BlendNormal) # hide +``` +| Result | SVG | +|:------:|:---:| +|![source-over](assets/source-over_normal.png)|![source-over_svg](assets/source-over_normal.svg)| + +```@docs +CompositeSourceOver +``` + +## source-atop +```@example ex +CompositingExamples.generate(CompositeSourceAtop, BlendNormal) # hide +``` +| Result | SVG | +|:------:|:---:| +|![source-atop](assets/source-atop_normal.png)|![source-atop_svg](assets/source-atop_normal.svg)| + +```@docs +CompositeSourceAtop +``` diff --git a/docs/src/functionindex.md b/docs/src/function-index.md similarity index 100% rename from docs/src/functionindex.md rename to docs/src/function-index.md diff --git a/docs/src/index.md b/docs/src/index.md index 1af9b7f..7446b70 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -7,6 +7,7 @@ The behavior of this package is based on the CSS [Compositing and Blending Level 1](https://drafts.fxtf.org/compositing-1/). ## Basic usage +For details of the API, see [Blending and Compositing](@ref). ```jldoctest julia> using ColorBlendModes, ColorTypes, FixedPointNumbers;