Skip to content

Commit

Permalink
Add pixel guards
Browse files Browse the repository at this point in the history
Update cmap types
  • Loading branch information
red-jade committed Aug 31, 2024
1 parent 749bbf7 commit 8877549
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 30 deletions.
8 changes: 3 additions & 5 deletions lib/color/col3b.ex
Original file line number Diff line number Diff line change
Expand Up @@ -181,20 +181,18 @@ defmodule Exa.Color.Col3b do
# unless the src and dst pixels are different
# then need 2 args

@c3 [:rgb, :bgr]

@behaviour Colorb

@impl Colorb
def to_bin(col, pix \\ :rgb) when pix in @c3,
def to_bin(col, pix \\ :rgb) when is_pix3(pix),
do: append_bin(<<>>, pix, col)

@impl Colorb
def append_bin(buf, pix \\ :rgb, {c1, c2, c3}) when pix in @c3 and is_binary(buf),
def append_bin(buf, pix \\ :rgb, {c1, c2, c3}) when is_pix3(pix) and is_binary(buf),
do: <<buf::binary, c1, c2, c3>>

@impl Colorb
def from_bin(<<c1, c2, c3, rest::binary>>, pix \\ :rgb) when pix in @c3,
def from_bin(<<c1, c2, c3, rest::binary>>, pix \\ :rgb) when is_pix3(pix),
do: {{c1, c2, c3}, rest}

# -----------------
Expand Down
27 changes: 20 additions & 7 deletions lib/color/colormap3b.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule Exa.Color.Colormap3b do
@moduledoc """
A map of a 1-byte index to 3-byte RGB or 4-byte RGBA colors.
A map of a 1-byte index to 3-byte RGB colors.
"""

require Logger
Expand All @@ -17,6 +17,19 @@ defmodule Exa.Color.Colormap3b do
alias Exa.Color.Col3f
alias Exa.Color.ColorSpace

# intermediate colormap in col3f format
@typep cmap3f() :: %{byte() => C.col3f()}

# special 3-component pixel type
# only for colormap arguments

@typep pix_cmap() :: :rgb | :hsl
defguard is_pix_cmap(px) when px in [:rgb, :hsl]

# TODO - other colormap pixel formats, gray, rgba, ...

# TODO - factor out the gradients

# ---------
# constants
# ---------
Expand Down Expand Up @@ -63,18 +76,18 @@ defmodule Exa.Color.Colormap3b do
# ------------

@doc """
Build a colormap with a list of colors.
Build a colormap with a list of 3-byte colors.
The list of colors can be any size.
The colors will formed into a zero-based colormap,
with a contiguous range of integers `0..(length(cols)-1)`.
The pixel specifies the color format of the input colors.
The color specifies the color format of the input colors.
If the pixel is HSL, the colors are converted from HSL to RGB.
The final colormap is always in RGB byte format.
"""
@spec new([C.col3f()], :rgb | :hsl) :: C.colormap3b()
def new(cols, pix \\ :rgb) when is_cols3f(cols) do
@spec new([C.col3f()], pix_cmap()) :: C.colormap3b()
def new(cols, pix \\ :rgb) when is_cols3f(cols) and is_pix_cmap(pix) do
imax = length(cols)

{^imax, cmap} =
Expand Down Expand Up @@ -183,7 +196,7 @@ defmodule Exa.Color.Colormap3b do
# private methods
# ---------------

# TOCO - fix HSL interpolation
# TODO - implement HSL interpolation
# when H should be nil (s == 0 or l == 0)
# then keep the other H fixed as s and l are interpolated

Expand Down Expand Up @@ -212,7 +225,7 @@ defmodule Exa.Color.Colormap3b do
end

# convert colormap from HSL to RGB 3f to RGB 3b
@spec convert(C.cmap3b(), C.pixel()) :: C.cmap3b()
@spec convert(cmap3f(), pix_cmap()) :: C.cmap3b()

defp convert(cmap, :rgb) do
for({i, c} <- cmap, into: %{}, do: {i, Col3f.to_col3b(c)})
Expand Down
34 changes: 16 additions & 18 deletions lib/color/types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -143,35 +143,27 @@ defmodule Exa.Color.Types do

@typedoc "Color channel components."
@type channel() :: :index | :gray | :a | :r | :g | :b | :h | :s | :l
defguard is_chan(ch) when ch in [:index, :gray, :a, :r, :g, :b, :h, :s, :l]

@typedoc "1-channel pixel formats."
@type pixel1() :: :index | :gray | :alpha
defguard is_pix1(px) when px in [:index, :gray, :alpha]

@typedoc "2-channel pixel formats."
@type pixel2() :: :gray_alpha | :alpha_gray
defguard is_pix2(px) when px in [:gray_alpha, :alpha_gray]

@typedoc "3-channel pixel formats."
@type pixel3() :: :rgb | :bgr
defguard is_pix3(px) when px in [:rgb, :bgr]

@typedoc "4-channel pixel formats."
@type pixel4() :: :rgba | :argb | :bgra | :abgr
defguard is_pix4(px) when px in [:rgba, :argb, :bgra, :abgr]

@typedoc "All pixel formats."
@type pixel() :: pixel1() | pixel2() | pixel3() | pixel4()
defguard is_pix(px)
when px in [
:gray,
:index,
:rgb,
:rgba,
:bgr,
:argb,
:abgr,
:bgra,
:gray_alpha,
:alpha_gray,
:alpha
]
defguard is_pix(px) when is_pix1(px) or is_pix3(px) or is_pix4(px) or is_pix2(px)

@typedoc "A component of a color: byte (0..255) or unit float (0.0-1.0)."
@type component() :: byte() | E.unit()
Expand Down Expand Up @@ -281,21 +273,27 @@ defmodule Exa.Color.Types do
# colormap
# --------

@typedoc "A control point to specify an indexed colormap gradient."
@type icol3f() :: {byte(), col3f()}
@typedoc "A colormap to lookup a 1-byte grayscale for a byte index."
@type cmap1b() :: %{byte() => col1b()}

@typedoc "A colormap to lookup a 3-byte color for a byte index."
@type cmap3b() :: %{byte() => col3b()}

@typedoc "A colormap to lookup a 4-byte color for a byte index."
@type cmap4b() :: %{byte() => col4b()}

@typedoc "A full colormap with pixel types and 1-byte lookup table."
@type colormap1b() :: {:colormap, :index, :gray, cmap1b()}

@typedoc "A full colormap with pixel types and 3-byte lookup table."
@type colormap3b() :: {:colormap, :index, :rgb, cmap3b()}

@typedoc "A full colormap with pixel types and 4-byte lookup table."
@type colormap4b() :: {:colormap, :index, :rgba, cmap4b()}

@typedoc "Any 3- or 4-byte colormap."
@type colormap() :: colormap3b() | colormap4b()
@typedoc "Any 1,3,4-byte colormap."
@type colormap() :: colormap1b() | colormap3b() | colormap4b()

@typedoc "A control point to specify an indexed colormap gradient."
@type icol3f() :: {byte(), col3f()}
end

0 comments on commit 8877549

Please sign in to comment.