diff --git a/lib/image.ex b/lib/image.ex index 7215cc6d..ba2382ae 100644 --- a/lib/image.ex +++ b/lib/image.ex @@ -2373,18 +2373,16 @@ defmodule Image do @doc subject: "Mask", since: "0.13.0" - @spec chroma_mask(image :: Vimage.t(), options :: ChromaKey.chroma_key_options() | map()) :: + @spec chroma_mask(image :: Vimage.t(), options :: ChromaKey.chroma_key_options()) :: {:ok, Vimage.t()} | {:error, error()} - def chroma_mask(image, options \\ []) - - def chroma_mask(%Vimage{} = image, options) when is_list(options) do + def chroma_mask(%Vimage{} = image, options \\ []) do with {:ok, options} <- Options.ChromaKey.validate_options(image, options) do - chroma_mask(image, options) + do_chroma_mask(image, options) end end - def chroma_mask(%Vimage{} = image, %{color: color, threshold: threshold}) do + defp do_chroma_mask(%Vimage{} = image, %{color: color, threshold: threshold}) do alias Image.Math # The mask is computed from the color bands only so any alpha @@ -2392,7 +2390,7 @@ defmodule Image do {color_image, _alpha} = split_alpha(image) with {:ok, color} <- maybe_calculate_color(image, color) do - color = color |> List.wrap() |> Enum.take(bands(color_image)) + color = Enum.take(color, bands(color_image)) color_image |> Math.subtract!(color) @@ -2403,7 +2401,7 @@ defmodule Image do end end - def chroma_mask(%Vimage{} = image, %{greater_than: greater_than, less_than: less_than}) do + defp do_chroma_mask(%Vimage{} = image, %{greater_than: greater_than, less_than: less_than}) do alias Image.Math with {:ok, greater} <- Math.greater_than(image, greater_than), @@ -2553,7 +2551,7 @@ defmodule Image do def chroma_key(%Vimage{} = image, options \\ []) do with {:ok, options} <- Options.ChromaKey.validate_options(image, options), - {:ok, mask} <- chroma_mask(image, options), + {:ok, mask} <- do_chroma_mask(image, options), {:ok, flattened} <- flatten(image) do Operation.bandjoin([flattened, mask]) end @@ -2674,10 +2672,15 @@ defmodule Image do def blur(%Vimage{} = image, options \\ []) do with {:ok, options} <- Options.Blur.validate_options(options) do - Operation.gaussblur(image, options.sigma, "min-ampl": options.min_amplitude) + do_blur(image, options) end end + # Takes validated options so `feather/2` can blur without validating twice. + defp do_blur(%Vimage{} = image, options) do + Operation.gaussblur(image, options.sigma, "min-ampl": options.min_amplitude) + end + @doc """ Applies a gaussian blur to an image. @@ -3002,37 +3005,40 @@ defmodule Image do def feather(%Vimage{} = image, options \\ []) do with {:ok, options} <- Options.Blur.validate_options(options) do - margin = round(options.sigma * 2) + do_feather(image, options) + end + end - cond do - has_alpha?(image) -> - {image, alpha} = split_alpha(image) + defp do_feather(%Vimage{} = image, options) do + margin = round(options.sigma * 2) - with {:ok, feathered} <- feather(alpha, options) do - Operation.bandjoin([image, feathered]) - end + cond do + has_alpha?(image) -> + {image, alpha} = split_alpha(image) + + with {:ok, feathered} <- do_feather(alpha, options) do + Operation.bandjoin([image, feathered]) + end - bands(image) == 1 and (width(image) <= 2 * margin or height(image) <= 2 * margin) -> - message = - "Image of size {#{width(image)}, #{height(image)}} is too small to feather " <> - "with sigma #{inspect(options.sigma)}. The image must be larger than " <> - "{#{2 * margin}, #{2 * margin}}" + bands(image) == 1 and (width(image) <= 2 * margin or height(image) <= 2 * margin) -> + message = + "Image of size {#{width(image)}, #{height(image)}} is too small to feather " <> + "with sigma #{inspect(options.sigma)}. The image must be larger than " <> + "{#{2 * margin}, #{2 * margin}}" - {:error, %Image.Error{message: message, reason: message}} + {:error, %Image.Error{message: message, reason: message}} - bands(image) == 1 -> - crop!(image, margin, margin, width(image) - 2 * margin, height(image) - 2 * margin) - |> Operation.embed!(margin, margin, width(image), height(image)) - |> blur!(options) - |> wrap(:ok) + bands(image) == 1 -> + crop!(image, margin, margin, width(image) - 2 * margin, height(image) - 2 * margin) + |> Operation.embed!(margin, margin, width(image), height(image)) + |> do_blur(options) - true -> - {:error, - %Image.Error{ - message: "Image has no alpha band and is not a single band image", - reason: "Image has no alpha band and is not a single band image" - }} - end + true -> + {:error, + %Image.Error{ + message: "Image has no alpha band and is not a single band image", + reason: "Image has no alpha band and is not a single band image" + }} end end diff --git a/lib/image/draw.ex b/lib/image/draw.ex index 7dfdbaed..6a7e755f 100644 --- a/lib/image/draw.ex +++ b/lib/image/draw.ex @@ -13,7 +13,6 @@ defmodule Image.Draw do alias Vix.Vips.Image, as: Vimage alias Vix.Vips.MutableImage alias Image.Vips.MutableOperation - alias Image.Pixel alias Image.Options import Image, only: :macros @@ -104,24 +103,19 @@ defmodule Image.Draw do def point(%Vimage{} = image, left, top, options) when is_integer(left) and is_integer(top) and left >= 0 and top >= 0 do with {:ok, options} <- Options.Draw.validate_options(image, :point, options) do - color = maybe_add_alpha(image, options.color) - Vimage.mutate(image, fn mut_img -> - MutableOperation.draw_rect(mut_img, color, left, top, 1, 1) + MutableOperation.draw_rect(mut_img, options.color, left, top, 1, 1) end) end end def point(%MutableImage{} = image, left, top, options) when is_point(left, top) do with {:ok, options} <- Options.Draw.validate_options(image, :point, options) do - color = maybe_add_alpha(image, options.color) - - case MutableOperation.draw_rect(image, color, left, top, 1, 1) do + case MutableOperation.draw_rect(image, options.color, left, top, 1, 1) do :ok -> {:ok, image} other -> other end end - |> maybe_wrap() end @doc """ @@ -272,10 +266,8 @@ defmodule Image.Draw do when is_image(image_type) and is_box(left, top, width, height) do with {:ok, options} <- Options.Draw.validate_options(image, :rect, options) do %{stroke_width: stroke_width, fill: fill} = options - color = maybe_add_alpha(image, options.color) - rect(image, left, top, width, height, color, stroke_width, fill) + rect(image, left, top, width, height, options.color, stroke_width, fill) end - |> maybe_wrap() end # If the stroke width is 1 then use the underlying Vips call. @@ -477,10 +469,8 @@ defmodule Image.Draw do when is_image(image_type) and is_circle(cx, cy, radius) do with {:ok, options} <- Options.Draw.validate_options(image, :circle, options) do %{stroke_width: stroke_width, fill: fill, color: color} = options - color = maybe_add_alpha(image, color) circle(image, cx, cy, radius, color, stroke_width, fill) end - |> maybe_wrap() end # When drawing a circle with a stroke_wiodth of > 1 then @@ -661,21 +651,22 @@ defmodule Image.Draw do is_integer(x2) and is_integer(y2) and x2 >= 0 and y2 >= 0 do with {:ok, options} <- Options.Draw.validate_options(image, :line, options) do Image.mutate(image, fn mut_img -> - line(mut_img, x1, y1, x2, y2, options) + do_line(mut_img, x1, y1, x2, y2, options) end) end - |> maybe_wrap() end def line(%MutableImage{} = image, x1, y1, x2, y2, options) when is_integer(x1) and is_integer(y1) and x1 >= 0 and y1 >= 0 and is_integer(x2) and is_integer(y2) and x2 >= 0 and y2 >= 0 do with {:ok, options} <- Options.Draw.validate_options(image, :line, options) do - color = maybe_add_alpha(image, options.color) - :ok = MutableOperation.draw_line(image, color, x1, y1, x2, y2) - {:ok, image} + do_line(image, x1, y1, x2, y2, options) end - |> maybe_wrap() + end + + defp do_line(%MutableImage{} = image, x1, y1, x2, y2, options) do + :ok = MutableOperation.draw_line(image, options.color, x1, y1, x2, y2) + {:ok, image} end @doc """ @@ -823,19 +814,21 @@ defmodule Image.Draw do # Image.mutate/2. with {:ok, options} <- Options.Draw.validate_options(image, :image, options) do Image.mutate(image, fn mut_img -> - image(mut_img, sub_image, top, left, options) + do_image(mut_img, sub_image, top, left, options) end) end - |> maybe_wrap() end def image(%MutableImage{} = image, %Vimage{} = sub_image, top, left, options) when is_integer(top) and is_integer(left) and top >= 0 and left >= 0 do with {:ok, options} <- Options.Draw.validate_options(image, :image, options) do - :ok = MutableOperation.draw_image(image, sub_image, top, left, Map.to_list(options)) - {:ok, image} + do_image(image, sub_image, top, left, options) end - |> maybe_wrap() + end + + defp do_image(%MutableImage{} = image, %Vimage{} = sub_image, top, left, options) do + :ok = MutableOperation.draw_image(image, sub_image, top, left, Map.to_list(options)) + {:ok, image} end @doc """ @@ -989,10 +982,8 @@ defmodule Image.Draw do def flood(%image_type{} = image, left, top, options \\ []) when is_image(image_type) and is_point(left, top) do with {:ok, options} <- Options.Draw.validate_options(image, :flood, options) do - color = maybe_add_alpha(image, options.color) - flood(image, left, top, color, options.equal) + flood(image, left, top, options.color, options.equal) end - |> maybe_wrap() end defp flood(%Vimage{} = image, left, top, color, equal) do @@ -1119,23 +1110,18 @@ defmodule Image.Draw do def mask(%Vimage{} = image, %Vimage{} = mask, x, y, options) when is_integer(x) and is_integer(y) and x >= 0 and y >= 0 do with {:ok, options} <- Options.Draw.validate_options(image, :mask, options) do - color = maybe_add_alpha(image, options.color) - Image.mutate(image, fn mut_img -> - MutableOperation.draw_mask(mut_img, color, mask, x, y) + MutableOperation.draw_mask(mut_img, options.color, mask, x, y) end) end - |> maybe_wrap() end def mask(%MutableImage{} = image, %Vimage{} = mask, x, y, options) when is_integer(x) and is_integer(y) and x >= 0 and y >= 0 do with {:ok, options} <- Options.Draw.validate_options(image, :mask, options) do - color = maybe_add_alpha(image, options.color) - :ok = MutableOperation.draw_mask(image, color, mask, x, y) + :ok = MutableOperation.draw_mask(image, options.color, mask, x, y) {:ok, image} end - |> maybe_wrap() end @doc """ @@ -1174,7 +1160,6 @@ defmodule Image.Draw do MutableOperation.draw_smudge(mut_img, left, top, width, height) end) end - |> maybe_wrap() end def smudge(%MutableImage{} = image, left, top, width, height, options) @@ -1184,59 +1169,5 @@ defmodule Image.Draw do :ok = MutableOperation.draw_smudge(image, left, top, width, height) {:ok, image} end - |> maybe_wrap() - end - - ## Helpers - - @spec maybe_add_alpha(Vimage.t() | MutableImage.t(), Pixel.t()) :: Pixel.t() - - # Colors resolved by `Image.Pixel.to_pixel/2` already match the image's - # band count (including any alpha band), so this only adjusts colors that - # arrive unresolved (for example via map-shaped options) and are exactly - # one band short of, or one band over, the image's band count. - @doc false - def maybe_add_alpha(image, color) when is_list(color) do - bands = bands(image) - color_bands = length(color) - - cond do - color_bands == bands - 1 && has_alpha?(image) -> - List.insert_at(color, -1, Pixel.max_opacity()) - - color_bands == bands + 1 && not has_alpha?(image) -> - List.delete_at(color, -1) - - true -> - color - end - end - - defp bands(%MutableImage{} = image) do - {:ok, {_width, _height, bands}} = MutableImage.shape(image) - bands - end - - defp bands(%Vimage{} = image) do - Vimage.bands(image) - end - - defp has_alpha?(%MutableImage{} = image) do - case MutableImage.has_alpha?(image) do - {:ok, true} -> true - {:ok, false} -> false - end - end - - defp has_alpha?(%Vimage{} = image) do - Vimage.has_alpha?(image) - end - - defp maybe_wrap({:ok, result}) do - {:ok, result} - end - - defp maybe_wrap(error) do - error end end diff --git a/lib/image/options/affine.ex b/lib/image/options/affine.ex index 4f6c7443..1dfecb6a 100644 --- a/lib/image/options/affine.ex +++ b/lib/image/options/affine.ex @@ -84,7 +84,7 @@ defmodule Image.Options.Affine do """ @spec validate_options(Vimage.t(), Keyword.t()) :: {:ok, Keyword.t()} | {:error, Image.error()} - def validate_options(image, options) do + def validate_options(image, options) when is_list(options) do # A nil `:background` means "unset", i.e. it falls back to the default. options = Enum.reject(options, &match?({:background, nil}, &1)) options = Keyword.merge(default_options(), options) diff --git a/lib/image/options/blur.ex b/lib/image/options/blur.ex index 64249ae1..a4296188 100644 --- a/lib/image/options/blur.ex +++ b/lib/image/options/blur.ex @@ -16,7 +16,7 @@ defmodule Image.Options.Blur do Options list for Image.blur/2 """ - @type blur_options :: [blur_option()] | map() + @type blur_options :: [blur_option()] @default_blur_sigma 5 @@ -43,10 +43,6 @@ defmodule Image.Options.Blur do end end - def validate_options(%{} = options) do - {:ok, options} - end - defp validate_option({:sigma, sigma}, options) when is_number(sigma) and sigma > 0 do {:cont, options} end diff --git a/lib/image/options/blurhash.ex b/lib/image/options/blurhash.ex index 457d9d14..956d1e87 100644 --- a/lib/image/options/blurhash.ex +++ b/lib/image/options/blurhash.ex @@ -16,7 +16,7 @@ defmodule Image.Options.Blurhash do Options list for Image.Blurhash.encode/2 """ - @type blurhash_options :: [blurhash_option()] | map() + @type blurhash_options :: [blurhash_option()] @default_x_components 4 @default_y_components 3 diff --git a/lib/image/options/chroma_key.ex b/lib/image/options/chroma_key.ex index 5fde85fa..d31138fc 100644 --- a/lib/image/options/chroma_key.ex +++ b/lib/image/options/chroma_key.ex @@ -18,7 +18,6 @@ defmodule Image.Options.ChromaKey do | {:sigma, float()} | {:min_amplitude, float()} ] - | map() @doc """ Validate the options for `Image.chroma_key/2`. @@ -36,10 +35,6 @@ defmodule Image.Options.ChromaKey do end end - def validate_options(_image, %{} = options) do - {:ok, options} - end - defp validate_option({:color, :auto}, _image, options) do {:cont, options} end @@ -105,9 +100,6 @@ defmodule Image.Options.ChromaKey do end defp default_options do - [ - color: :auto, - threshold: 20 - ] + [color: :auto, threshold: 20] end end diff --git a/lib/image/options/compare.ex b/lib/image/options/compare.ex index 06d67f97..3f7a1724 100644 --- a/lib/image/options/compare.ex +++ b/lib/image/options/compare.ex @@ -18,7 +18,7 @@ defmodule Image.Options.Compare do | {:sigma, float()} | {:min_amplitude, float()} - @type compare_options :: [compare_option()] | map() + @type compare_options :: [compare_option()] # Ussed by Image.compare/3 and defines the # default metric to be used. diff --git a/lib/image/options/draw.ex b/lib/image/options/draw.ex index c0e676d3..8cea69a2 100644 --- a/lib/image/options/draw.ex +++ b/lib/image/options/draw.ex @@ -13,7 +13,6 @@ defmodule Image.Options.Draw do {:fill, boolean()} | {:color, Pixel.t()} ] - | map() @type rect :: [ @@ -21,40 +20,34 @@ defmodule Image.Options.Draw do | {:color, Pixel.t()} | {:stroke_width, pos_integer()} ] - | map() @type point :: [ {:color, Pixel.t()} ] - | map() @type flood :: [ {:equal, boolean()} | {:color, Pixel.t()} ] - | map() @type mask :: [ {:color, Pixel.t()} ] - | map() @type line :: [ {:color, Pixel.t()} ] - | map() - @type smudge :: [] | map() + @type smudge :: [] @type image :: [ {:mode, CombineMode.t()} ] - | map() @doc false def default_options(:circle) do @@ -119,11 +112,7 @@ defmodule Image.Options.Draw do Validate the options for `Image.Draw`. """ - def validate_options(_image, _type, %{} = options) do - {:ok, options} - end - - def validate_options(image, type, options) do + def validate_options(image, type, options) when is_list(options) do options = Keyword.merge(default_options(type), options) options = diff --git a/lib/image/options/embed.ex b/lib/image/options/embed.ex index 5d721326..8c612062 100644 --- a/lib/image/options/embed.ex +++ b/lib/image/options/embed.ex @@ -67,10 +67,6 @@ defmodule Image.Options.Embed do end end - def validate_options(_image, _width, _height, %{} = options) do - {:ok, options} - end - # `:average`, colors, and the `{color, alpha: a}` form are all resolved by # `Image.BackgroundColor.resolve/2`. The resolved pixel keeps its alpha band # (unlike `write`/`flatten`) so a transparent border can be requested. diff --git a/lib/image/options/histogram.ex b/lib/image/options/histogram.ex index c908b456..e65da410 100644 --- a/lib/image/options/histogram.ex +++ b/lib/image/options/histogram.ex @@ -12,9 +12,9 @@ defmodule Image.Options.Histogram do | {:height, pos_integer() | :auto} @typedoc """ - Options list or map for `Image.Histogram.as_svg/2`. + Options list for `Image.Histogram.as_svg/2`. """ - @type histogram_options :: [histogram_option()] | map() + @type histogram_options :: [histogram_option()] @doc """ Validate the options for `Image.Histogram.as_svg/2`. diff --git a/lib/image/options/linear_gradient.ex b/lib/image/options/linear_gradient.ex index 642159bf..766027af 100644 --- a/lib/image/options/linear_gradient.ex +++ b/lib/image/options/linear_gradient.ex @@ -14,9 +14,9 @@ defmodule Image.Options.LinearGradient do | {:angle, number()} @typedoc """ - Options list or map for `Image.linear_gradient/2`. + Options list for `Image.linear_gradient/2`. """ - @type linear_gradient_options :: [linear_gradient_option()] | map() + @type linear_gradient_options :: [linear_gradient_option()] @default_start_color [0.0, 0.0, 0.0, 0.0] @default_finish_color [0.0, 0.0, 0.0, 255.0] diff --git a/lib/image/options/local_contrast.ex b/lib/image/options/local_contrast.ex index f4612a2e..b00e4cf0 100644 --- a/lib/image/options/local_contrast.ex +++ b/lib/image/options/local_contrast.ex @@ -12,9 +12,9 @@ defmodule Image.Options.LocalContrast do | {:max_slope, non_neg_integer()} @typedoc """ - Options list or map for `Image.local_contrast/2`. + Options list for `Image.local_contrast/2`. """ - @type local_contrast_options :: [local_contrast_option()] | map() + @type local_contrast_options :: [local_contrast_option()] # Default window size in pixels over which the # local contrast is evaluated diff --git a/lib/image/options/meme.ex b/lib/image/options/meme.ex index 7d1c3ac0..f24c4ab5 100644 --- a/lib/image/options/meme.ex +++ b/lib/image/options/meme.ex @@ -23,7 +23,6 @@ defmodule Image.Options.Meme do | {:justify, boolean()} | {:transform, text_transform()} ] - | map() @doc """ Validate the options for `Image.meme/3`. @@ -55,10 +54,6 @@ defmodule Image.Options.Meme do end end - def validate_options(%{} = options) do - {:ok, options} - end - defp validate_option({:font, font}, options) when is_binary(font) do {:cont, options} end diff --git a/lib/image/options/modulate.ex b/lib/image/options/modulate.ex index 02c1d3f6..f0a72f53 100644 --- a/lib/image/options/modulate.ex +++ b/lib/image/options/modulate.ex @@ -20,7 +20,7 @@ defmodule Image.Options.Modulate do Options applicable to Image.modulate/2 """ - @type modulate_options :: [modulate_option()] | map() + @type modulate_options :: [modulate_option()] @doc """ Validate the options for `Image.modulate/2`. @@ -40,10 +40,6 @@ defmodule Image.Options.Modulate do end end - def validate_options(%{} = options) do - {:ok, options} - end - defp validate_option({:brightness, brightness}, options) when is_multiplier(brightness) do {:cont, options} end diff --git a/lib/image/options/radial_gradient.ex b/lib/image/options/radial_gradient.ex index 8a059016..800e3d95 100644 --- a/lib/image/options/radial_gradient.ex +++ b/lib/image/options/radial_gradient.ex @@ -15,9 +15,9 @@ defmodule Image.Options.RadialGradient do | {:radius, number()} @typedoc """ - Options list or map for `Image.radial_gradient/3`. + Options list for `Image.radial_gradient/3`. """ - @type radial_gradient_options :: [radial_gradient_option()] | map() + @type radial_gradient_options :: [radial_gradient_option()] @default_start_color [0.0, 0.0, 0.0, 0.0] @default_finish_color [0.0, 0.0, 0.0, 255.0] diff --git a/lib/image/options/resize.ex b/lib/image/options/resize.ex index 9044837c..729f1230 100644 --- a/lib/image/options/resize.ex +++ b/lib/image/options/resize.ex @@ -22,7 +22,7 @@ defmodule Image.Options.Resize do See `t:Image.Options.Resize.resize_options/0`. """ - def validate_options(options) do + def validate_options(options) when is_list(options) do case Enum.reduce_while(options, options, &validate_option(&1, &2)) do {:error, value} -> {:error, value} diff --git a/lib/image/options/rotate.ex b/lib/image/options/rotate.ex index 97c61abd..2cca9b46 100644 --- a/lib/image/options/rotate.ex +++ b/lib/image/options/rotate.ex @@ -58,7 +58,7 @@ defmodule Image.Options.Rotate do """ @spec validate_options(Vix.Vips.Image.t(), Keyword.t()) :: {:ok, Keyword.t()} | {:error, Image.error()} - def validate_options(image, options) do + def validate_options(image, options) when is_list(options) do # A nil `:background` means "unset", i.e. it falls back to the default. options = Enum.reject(options, &match?({:background, nil}, &1)) options = Keyword.merge(default_options(), options) diff --git a/lib/image/options/sharpen.ex b/lib/image/options/sharpen.ex index 53b76992..4a05acd5 100644 --- a/lib/image/options/sharpen.ex +++ b/lib/image/options/sharpen.ex @@ -20,7 +20,7 @@ defmodule Image.Options.Sharpen do Options applicable to Image.sharpen/2 """ - @type sharpen_options :: [sharpen_option()] | map() + @type sharpen_options :: [sharpen_option()] @doc """ Validate the options for `Image.sharpen/2`. @@ -40,10 +40,6 @@ defmodule Image.Options.Sharpen do end end - def validate_options(%{} = options) do - {:ok, options} - end - defp validate_option({:sigma, sigma}, options) when is_number(sigma) and sigma > 0 and sigma <= 10 do {:cont, options} diff --git a/lib/image/options/thumbnail.ex b/lib/image/options/thumbnail.ex index 8f117994..055015d4 100644 --- a/lib/image/options/thumbnail.ex +++ b/lib/image/options/thumbnail.ex @@ -52,7 +52,7 @@ defmodule Image.Options.Thumbnail do See `t:Image.Options.Resize.resize_options/0`. """ - def validate_options(options) do + def validate_options(options) when is_list(options) do case Enum.reduce_while(options, options, &validate_option(&1, &2)) do {:error, value} -> {:error, value} diff --git a/lib/image/options/tone_map.ex b/lib/image/options/tone_map.ex index 49c80379..3fd1af68 100644 --- a/lib/image/options/tone_map.ex +++ b/lib/image/options/tone_map.ex @@ -19,7 +19,7 @@ defmodule Image.Options.ToneCurve do | {:mid_points, tone_adjustment()} | {:highlights, tone_adjustment()} - @type tone_curve_options :: [tone_curve_option()] | map() + @type tone_curve_options :: [tone_curve_option()] @typedoc """ Range for setting the black point and diff --git a/lib/image/options/trim.ex b/lib/image/options/trim.ex index 496b1f95..1832e68e 100644 --- a/lib/image/options/trim.ex +++ b/lib/image/options/trim.ex @@ -30,10 +30,6 @@ defmodule Image.Options.Trim do end end - def validate_options(_image, %{} = options) do - {:ok, options} - end - defp validate_option({:background, :auto}, _image, options) do {:cont, options} end diff --git a/lib/image/options/vibrance.ex b/lib/image/options/vibrance.ex index 49b7a129..e42e08f9 100644 --- a/lib/image/options/vibrance.ex +++ b/lib/image/options/vibrance.ex @@ -14,7 +14,7 @@ defmodule Image.Options.Vibrance do Options list for Image.vibrance/3 """ - @type vibrance_options :: [vibrance_option()] | map() + @type vibrance_options :: [vibrance_option()] @default_vibrance_threshold 60 @@ -41,10 +41,6 @@ defmodule Image.Options.Vibrance do end end - def validate_options(%{} = options) do - {:ok, options} - end - defp validate_option({:threshold, threshold}, options) when is_integer(threshold) and threshold in 1..100//1 do {:cont, options} diff --git a/lib/image/options/vignette.ex b/lib/image/options/vignette.ex index b985b864..45c49ce8 100644 --- a/lib/image/options/vignette.ex +++ b/lib/image/options/vignette.ex @@ -18,7 +18,7 @@ defmodule Image.Options.Vignette do Options list for `Image.vignette/2`. """ - @type vignette_options :: [vignette_option()] | map() + @type vignette_options :: [vignette_option()] @default_strength 0.5 @@ -40,10 +40,6 @@ defmodule Image.Options.Vignette do end end - def validate_options(%{} = options) do - {:ok, normalize(options)} - end - defp validate_option({:strength, strength}, options) when is_number(strength) do {:cont, options} end diff --git a/test/coverage_wave3_core_test.exs b/test/coverage_wave3_core_test.exs index 7c448b25..350c1df2 100644 --- a/test/coverage_wave3_core_test.exs +++ b/test/coverage_wave3_core_test.exs @@ -5,7 +5,6 @@ defmodule Image.CoverageWave3.Core.Test do alias Image.Draw defp rgb, do: Image.new!(20, 20, color: [10, 20, 30]) - defp rgba, do: Image.new!(20, 20, color: [10, 20, 30, 255]) # An image with mismatched band count that makes most binary # libvips operations fail, exercising the bang raise branches. @@ -64,7 +63,7 @@ defmodule Image.CoverageWave3.Core.Test do end end - describe "Image.Draw default arguments and band-adjusted map colors" do + describe "Image.Draw default arguments" do test "point, rect, circle, line, flood, mask with default options" do mask = Image.new!(5, 5, color: 255) |> Image.to_colorspace!(:bw) @@ -82,26 +81,6 @@ defmodule Image.CoverageWave3.Core.Test do assert %Vix.Vips.Image{} = Draw.line!(rgb(), 0, 0, 9, 9) assert %Vix.Vips.Image{} = Draw.flood!(rgb(), 0, 0) end - - test "a map color one band short of an alpha image gains an alpha value" do - # Map options bypass validation, so maybe_add_alpha adjusts the - # band count. - assert {:ok, drawn} = Draw.point(rgba(), 1, 1, %{color: [255, 0, 0]}) - assert Image.get_pixel!(drawn, 1, 1) == [255, 0, 0, 255] - end - - test "a map color one band over a non-alpha image loses the extra value" do - assert {:ok, drawn} = Draw.point(rgb(), 1, 1, %{color: [255, 0, 0, 255]}) - assert Image.get_pixel!(drawn, 1, 1) == [255, 0, 0] - end - - test "a map color on a mutable image is band-adjusted" do - assert {:ok, _} = - Image.mutate(rgba(), fn mutable -> - {:ok, _} = Draw.point(mutable, 1, 1, %{color: [255, 0, 0]}) - :ok - end) - end end describe "Image.Text default arguments and background clauses" do diff --git a/test/coverage_wave3_options_test.exs b/test/coverage_wave3_options_test.exs index 458b3ab8..3d51e107 100644 --- a/test/coverage_wave3_options_test.exs +++ b/test/coverage_wave3_options_test.exs @@ -153,11 +153,6 @@ defmodule Image.CoverageWave3.Options.Test do describe "Image.Options.Embed" do alias Image.Options.Embed - test "map options pass through validate_options" do - assert {:ok, %{extend_mode: :VIPS_EXTEND_BLACK}} = - Embed.validate_options(rgb(), 40, 40, %{extend_mode: :VIPS_EXTEND_BLACK}) - end - test "the default is a background extend with no injected background" do # With no :background passed, libvips fills with its native all-zeros # pixel: transparent on this alpha image. @@ -273,18 +268,9 @@ defmodule Image.CoverageWave3.Options.Test do test "default_vibrance_threshold/0" do assert Image.Options.Vibrance.default_vibrance_threshold() == 60 end - - test "map options pass through validate_options" do - assert {:ok, %{threshold: 50}} = Image.Options.Vibrance.validate_options(%{threshold: 50}) - end end - describe "Image.Options.Trim and ChromaKey passthrough clauses" do - test "trim map options pass through" do - assert {:ok, %{background: [0, 0, 0]}} = - Image.Options.Trim.validate_options(rgb(), %{background: [0, 0, 0], threshold: 10}) - end - + describe "Image.Options.Trim and ChromaKey" do test "trim with :alpha background option" do assert {:ok, _} = Image.Options.Trim.validate_options(rgba(), background: :alpha) end @@ -295,11 +281,6 @@ defmodule Image.CoverageWave3.Options.Test do assert options.background == [255, 0, 0] end - test "chroma_key map options pass through" do - assert {:ok, %{color: [0, 255, 0]}} = - Image.Options.ChromaKey.validate_options(rgb(), %{color: [0, 255, 0], threshold: 20}) - end - test "chroma_key :sigma and :min_amplitude options" do green = Image.new!(20, 20, color: [0, 255, 0]) assert {:ok, _} = Image.chroma_key(green, sigma: 2.0, min_amplitude: 0.05) diff --git a/test/draw_coverage_test.exs b/test/draw_coverage_test.exs index 6b4fe75f..ee69ffe8 100644 --- a/test/draw_coverage_test.exs +++ b/test/draw_coverage_test.exs @@ -187,6 +187,17 @@ defmodule Image.DrawCoverage.Test do assert Image.get_pixel!(drawn, 15, 15) == [255, 255, 255] end + test "the :mode option selects how the sub-image combines" do + base = Image.new!(20, 20, color: [10, 20, 30]) + sub_image = Image.new!(5, 5, color: [10, 10, 10]) + + assert {:ok, set} = Draw.image(base, sub_image, 2, 2, mode: :set) + assert {:ok, add} = Draw.image(base, sub_image, 2, 2, mode: :add) + + assert Image.get_pixel!(set, 3, 3) == [10, 10, 10] + assert Image.get_pixel!(add, 3, 3) == [20, 30, 40] + end + test "returns an error for an invalid combine mode" do sub_image = Image.new!(5, 5, color: :green) @@ -316,11 +327,6 @@ defmodule Image.DrawCoverage.Test do end describe "Image.Options.Draw" do - test "validate_options/3 passes a map through unchanged" do - options = %{color: [1, 2, 3]} - assert Image.Options.Draw.validate_options(white_image(), :point, options) == {:ok, options} - end - test "default options for each draw operation" do assert Image.Options.Draw.default_options(:point) == [color: :black] assert Image.Options.Draw.default_options(:line) == [color: :black] diff --git a/test/image_draw_test.exs b/test/image_draw_test.exs index f7907996..0110eea8 100644 --- a/test/image_draw_test.exs +++ b/test/image_draw_test.exs @@ -57,17 +57,13 @@ defmodule Image.Draw.Test do end describe "drawing on non-3-band images" do - # Regression: maybe_add_alpha/2 assumed 3-band = no alpha and - # 4-band = alpha, crashing on greyscale images and deleting the K - # channel of CMYK images. - test "draws a point on a greyscale image" do grey = Image.new!(20, 20, color: 128) |> Image.to_colorspace!(:bw) assert {:ok, %Vimage{}} = Image.Draw.point(grey, 5, 5, color: :white) end - test "draws a rect on a CMYK image without deleting the K band" do + test "draws a rect on a CMYK image with the correct number of bands" do cmyk = Image.new!(20, 20, color: :white) |> Image.to_colorspace!(:cmyk) assert {:ok, %Vimage{} = drawn} = Image.Draw.rect(cmyk, 2, 2, 5, 5, color: :red, fill: true) diff --git a/test/options_blur_effects_test.exs b/test/options_blur_effects_test.exs index 8b1a46b2..0cec1ff9 100644 --- a/test/options_blur_effects_test.exs +++ b/test/options_blur_effects_test.exs @@ -24,6 +24,16 @@ defmodule Image.Options.BlurEffects.Test do assert {:ok, %Vimage{}} = Image.blur(image, min_amplitude: 0.1) end + test ":min_amplitude changes the mask size and so the result" do + image = Image.new!(60, 60, color: :white) |> Image.Draw.rect!(20, 20, 20, 20, color: :black) + + {:ok, coarse} = Image.blur(image, sigma: 3.0, min_amplitude: 0.9) + {:ok, accurate} = Image.blur(image, sigma: 3.0, min_amplitude: 0.001) + + assert Image.get_pixel!(coarse, 30, 18) == [255, 255, 255] + assert Image.get_pixel!(accurate, 30, 18) == [176, 176, 176] + end + test "with a zero :sigma", %{image: image} do assert {:error, %Image.Error{message: message}} = Image.blur(image, sigma: 0) assert message =~ "Invalid option" @@ -44,10 +54,6 @@ defmodule Image.Options.BlurEffects.Test do test "with an unknown option", %{image: image} do assert {:error, %Image.Error{}} = Image.blur(image, radius: 3) end - - test "validate_options/1 passes a map through unchanged" do - assert {:ok, %{sigma: 1}} = Image.Options.Blur.validate_options(%{sigma: 1}) - end end describe "Image.local_contrast/2 options" do diff --git a/test/pixel_test.exs b/test/pixel_test.exs index c104ce5d..d3ac1f1d 100644 --- a/test/pixel_test.exs +++ b/test/pixel_test.exs @@ -88,6 +88,18 @@ defmodule Image.PixelTest do test "opaque yields full alpha", %{image: image} do assert {:ok, [0, 0, 0, 255]} = Pixel.to_pixel(image, :opaque) end + + test "a list one band short gains the missing alpha", %{image: image} do + assert {:ok, [255, 0, 0, 255]} = Pixel.to_pixel(image, [255, 0, 0]) + end + end + + describe "to_pixel/3 fits a list color to the image band count" do + test "a list one band over a non-alpha image loses the extra value" do + {:ok, image} = Image.new(2, 2, color: [0, 0, 0]) + + assert {:ok, [255, 0, 0]} = Pixel.to_pixel(image, [255, 0, 0, 255]) + end end describe "to_pixel/3 against a Lab image" do