Skip to content

Commit 800c686

Browse files
committed
Update changelog and reset version
1 parent 025c3d5 commit 800c686

2 files changed

Lines changed: 34 additions & 96 deletions

File tree

CHANGELOG.md

Lines changed: 33 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,29 @@
11
# Changelog
22

3-
## Image 0.67.0
3+
## Image 0.64.0
4+
5+
This is the changelog for Image version 0.64.0 released on April 9th, 2026. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-image/image/tags)
6+
7+
The primary intent of this release is to stablise the code in readiness for a 1.0 release. Deprecated code has been removed, a standardised color model introduced (via the new library [color](https://hex.pm/packages/color)) and objective classification and detection has been removed to a new `image_detection` library.
48

59
### Breaking Changes
610

7-
* **`Image.Classification` and `Image.Generation` have moved to a new sibling package, [`:image_detection`](https://hex.pm/packages/image_detection).** The two modules keep their fully-qualified names (`Image.Classification` and `Image.Generation`) so that existing call sites continue to work — they just live in a different OTP application now. To restore the previous functionality, add `:image_detection` to your `mix.exs`:
11+
* Five long-deprecated functions have been removed:
12+
* `Image.interpretation/1` — use `Image.colorspace/1`.
13+
* `Image.type/1` (was `format/1`) — use `Image.band_format/1`.
14+
* `Image.convert_to_mask/1` — use `Image.convert_alpha_to_mask/1`.
15+
* `Image.convert_to_mask!/1` — use `Image.convert_alpha_to_mask!/1`.
16+
* `Image.map_pages/2` — use `Image.map_join_pages/2`.
17+
18+
* `Image.Color` has been removed. Color handling now lives in two new modules and one new dependency:
19+
20+
* `Image.Pixel``to_pixel/3` resolves any colour input (atom, hex string, named colour, numeric list, `Color.*` struct) into a pixel matching the **interpretation, value range, and band layout** of a target image. This fixes a long-standing bug where colour arguments were treated as raw 8-bit sRGB regardless of the image's actual colour space (so `:red` against a Lab image would yield `[255, 0, 0]` instead of Lab red `[53.24, 80.09, 67.20]`). Every option validator that accepts a colour now routes through `Image.Pixel.to_pixel/3`. `Image.Pixel` also exposes `to_srgb/1`, `transparency/1`, the `is_pixel/1` defguard, and the `t/0` type.
21+
22+
* `Image.ICCProfile` — the libvips ICC profile helpers (`inbuilt/0`, `known?/1`, `is_inbuilt/1`, `t/0`).
23+
24+
* The new `:color` dependency — a full-featured colour science library (`Color.new/2`, `Color.convert/2,3`, `Color.SRGB.parse/1`, `Color.CSSNames`, all the major colour spaces, gamut mapping, ICC rendering intents). Hex parsing now supports `#RGB`, `#RGBA`, `#RRGGBB`, and `#RRGGBBAA`.
25+
26+
* `Image.Classification` and `Image.Generation` have moved to a new sibling package, [`:image_detection`](https://hex.pm/packages/image_detection). The two modules keep their fully-qualified names (`Image.Classification` and `Image.Generation`) so that existing call sites continue to work — they just live in a different OTP application now. To restore the previous functionality, add `:image_detection` to your `mix.exs`:
827

928
def deps do
1029
[
@@ -15,29 +34,9 @@
1534
]
1635
end
1736

18-
* **`:bumblebee` is no longer a dependency of `:image`.** It is brought in transitively only when you add `:image_detection`. The `:nx`, `:nx_image`, `:scholar`, `:exla`, and `:rustler` optional deps stay in `:image` because `Image.to_nx/2`, `Image.from_nx/1`, `Image.k_means/2`, and a few internal pipelines still use them.
19-
20-
* **`Image.bumblebee_configured?/0` has been removed.** It is replaced by `ImageDetection.bumblebee_configured?/0` which lives in the new package.
21-
22-
* **`Image.Application` no longer autostarts the classification or generation services.** That responsibility moved to `ImageDetection.Application`, which manages its own `ImageDetection.Supervisor`. Both services default to `autostart: false` in the new package — you opt in via `config :image_detection, :classifier, autostart: true` (or `:generator`).
23-
24-
* **`config :image, :classifier` and `config :image, :generator` no longer have any effect.** Move them to `config :image_detection, :classifier` / `:generator` in your `runtime.exs` (or equivalent).
25-
26-
* The `doctest Image.Classification` line has been removed from `test/image_test.exs` since the module is no longer part of `:image`.
27-
28-
### Enhancements
37+
* `:bumblebee` is no longer a dependency of `:image`. It is brought in transitively only when you add `:image_detection`. The `:nx`, `:nx_image`, `:scholar`, `:exla`, and `:rustler` optional deps stay in `:image` because `Image.to_nx/2`, `Image.from_nx/1`, `Image.k_means/2`, and a few internal pipelines still use them.
2938

30-
* `:image` no longer pulls `:bumblebee` (or its transitive deps) into the dependency graph. For users who don't need ML-backed classification/generation, the install footprint shrinks substantially. The Hex tarball is unchanged in size, but the dependency tree is much lighter.
31-
32-
* The `image_detection` package's `bumblebee_configured?/0` predicate only checks for `Nx` and `Bumblebee` at compile time; the Nx backend (e.g. `:exla`) is now a runtime-only requirement. Users who want to compile against `image_detection` no longer have to install EXLA on their build machine.
33-
34-
## Image 0.66.0
35-
36-
This release replaces the eVision-backed video frame extraction with an FFmpeg-backed implementation via `:xav`.
37-
38-
### Breaking Changes
39-
40-
* **`Image.Video` is now backed by [Xav](https://hex.pm/packages/xav)** (a thin Elixir wrapper around FFmpeg) instead of `:evision` / OpenCV. The public API surface is largely unchanged but the underlying type, options, and a few semantic details have moved:
39+
* `Image.Video` is now backed by [Xav](https://hex.pm/packages/xav) (a thin Elixir wrapper around FFmpeg) instead of `:evision` / OpenCV. The public API surface is largely unchanged but the underlying type, options, and a few semantic details have moved:
4140

4241
* The video struct is now `%Image.Video{}` (with fields `:reader`, `:source`, `:fps`, `:duration_seconds`, `:frame_count`, `:width`, `:height`) rather than `%Evision.VideoCapture{}`. Pattern-match on the new struct module if your code does so.
4342

@@ -53,87 +52,20 @@ This release replaces the eVision-backed video frame extraction with an FFmpeg-b
5352

5453
* Image and audio frames are decoded by FFmpeg + libswscale rather than by OpenCV's videoio backend. Pixel-exact comparisons against fixtures generated by the previous version will not match; the test fixture `test/support/validate/video/video_sample_frame_0.png` has been regenerated.
5554

56-
* **`:xav` is now an optional dependency.** Add it to your `mix.exs` if you use `Image.Video`:
55+
* `:xav` is now an optional dependency. It requires FFmpeg ≥ 6.0 to be installed on the system. Add it to your `mix.exs` if you use `Image.Video`:
5756

5857
{:xav, "~> 0.10", optional: true}
5958

60-
Xav requires FFmpeg ≥ 6.0 on the system.
61-
62-
* **`:evision` is no longer needed for `Image.Video`.** It is still required for `Image.QRcode` and for the `Image.to_evision/2` / `Image.from_evision/1` interop helpers, which are unchanged. The README's optional-dependency table reflects the new split.
63-
64-
### Enhancements
65-
66-
* `Image.Video` now supports HTTP/HTTPS/RTSP/RTMP URLs as video sources for free, since FFmpeg supports them natively.
67-
68-
* `Image.xav_configured?/0` is the new compile-time predicate that gates the `Image.Video` module (analogous to `Image.evision_configured?/0` and `Image.bumblebee_configured?/0`).
69-
70-
* The `Image.Video.frame_to_image/1` helper exposes the raw `Xav.Frame``Vix.Vips.Image.t()` conversion (used internally by `image_from_video/2` and `stream!/2`). Useful if you have a frame from elsewhere in the Xav ecosystem and want to bring it into `Image`.
59+
* `:evision` is no longer needed for `Image.Video`. It is still required for `Image.QRcode` and for the `Image.to_evision/2` / `Image.from_evision/1` interop helpers, which are unchanged. The README's optional-dependency table reflects the new split.
7160

72-
## Image 0.65.0
73-
74-
This release prepares the library for a 1.0 tag. It is dominated by API hygiene rather than new features.
75-
76-
### Breaking Changes
77-
78-
* **`Image.Error` is now a structured public exception.** It carries `:reason` (atom or `{atom, value}` tuple), `:operation`, `:path`, `:value`, and a derived `:message`. Every fallible function in the library now returns `{:ok, value}` or `{:error, %Image.Error{}}` — bare-string error tuples have been eliminated. Bang variants raise the same struct. The new `Image.Error.wrap/2` helper attaches structured context to a raw libvips or `File.*` error. Pattern-match on `:reason` instead of scraping `:message`:
61+
* `Image.Error` is now a structured public exception. It carries `:reason` (atom or `{atom, value}` tuple), `:operation`, `:path`, `:value`, and a derived `:message`. Every fallible function in the library now returns `{:ok, value}` or `{:error, %Image.Error{}}` — bare-string error tuples have been eliminated. Bang variants raise the same struct. The new `Image.Error.wrap/2` helper attaches structured context to a raw libvips or `File.*` error. Pattern-match on `:reason` instead of scraping `:message`:
7962

8063
case Image.open(path) do
8164
{:ok, image} -> ...
8265
{:error, %Image.Error{reason: :enoent}} -> not_found_handler()
8366
{:error, %Image.Error{} = err} -> raise err
8467
end
8568

86-
* **The `@type error_message :: term()` alias on `Image` has been removed** in favour of `@type error :: Image.Error.t()`. All `@spec` lines across the library that previously referenced `Image.error_message()` (or the bare `error_message` form inside `image.ex`) now reference `Image.error()`.
87-
88-
* **The dangerous fall-through in `Image.Error.exception/1` has been removed.** Previously, `raise Image.Error, %{}` evaluated to `raise %{}` and crashed with `BadStructError`. The fallback now wraps any unknown shape in a real struct.
89-
90-
* **Five long-deprecated functions have been removed:**
91-
* `Image.interpretation/1` — use `Image.colorspace/1`.
92-
* `Image.type/1` (was `format/1`) — use `Image.band_format/1`.
93-
* `Image.convert_to_mask/1` — use `Image.convert_alpha_to_mask/1`.
94-
* `Image.convert_to_mask!/1` — use `Image.convert_alpha_to_mask!/1`.
95-
* `Image.map_pages/2` — use `Image.map_join_pages/2`.
96-
97-
* **`Image.Application` no longer defines a sibling `Image.SetSafeLoader` module.** The single-function helper has been collapsed into a private `Image.Application.set_safe_loader/0`. The `VIPS_BLOCK_UNTRUSTED` behaviour is unchanged.
98-
99-
### Enhancements
100-
101-
* **Doctest coverage for the most-used modules.** `Image.Draw`, `Image.Text`, `Image.Exif`, `Image.Social`, `Image.YUV`, and `Image.QRcode` now have inline doctests. Total doctests rose from 88 to 110.
102-
103-
* **Dialyzer is now clean.** The `lib/image/text.ex` `embed` background contract violation, the `Image.distort/3` `if_then_else!` typing mismatch, and the `xmp/1` spec gap are all fixed. CI's lint cell runs `mix dialyzer` with zero warnings.
104-
105-
* **README rewritten** with Features, Supported Elixir/OTP, Quick Start, optional dependencies, security considerations, and License sections. The dependency line now reflects the current major version.
106-
107-
* **`Image.Pixels`, `Image.Complex`, `Image.Pixel`, and `Image.Xmp`** got specs added for their public surface (the internal-only modules remain `@moduledoc false`).
108-
109-
* **`Image.ICCProfile` doc clarification** explaining that "built-in" means libvips' own bundled profiles — `:image` does not ship `.icc` files.
110-
111-
* **New `Errors` and `Pixels` doc-module groups** in the generated docs.
112-
113-
* **`lib/image/color.ex`** (the empty zero-byte phantom file from the colour migration) has been deleted.
114-
115-
* **`Image.exif/1`** now wraps the underlying libvips `"No such field"` error in `%Image.Error{reason: "No such field"}` so consumers can pattern-match.
116-
117-
## Image 0.64.0
118-
119-
This is the changelog for Image version 0.64.0 released on April 7th, 2026. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-image/image/tags)
120-
121-
### Breaking Changes
122-
123-
* `Image.Color` has been removed. Color handling now lives in two new modules and one new dependency:
124-
125-
* `Image.Pixel``to_pixel/3` resolves any colour input (atom, hex string, named colour, numeric list, `Color.*` struct) into a pixel matching the **interpretation, value range, and band layout** of a target image. This fixes a long-standing bug where colour arguments were treated as raw 8-bit sRGB regardless of the image's actual colour space (so `:red` against a Lab image would yield `[255, 0, 0]` instead of Lab red `[53.24, 80.09, 67.20]`). Every option validator that accepts a colour now routes through `Image.Pixel.to_pixel/3`. `Image.Pixel` also exposes `to_srgb/1`, `transparency/1`, the `is_pixel/1` defguard, and the `t/0` type.
126-
127-
* `Image.ICCProfile` — the libvips ICC profile helpers (`inbuilt/0`, `known?/1`, `is_inbuilt/1`, `t/0`).
128-
129-
* The new `:color` dependency — a full-featured colour science library (`Color.new/2`, `Color.convert/2,3`, `Color.SRGB.parse/1`, `Color.CSSNames`, all the major colour spaces, gamut mapping, ICC rendering intents). Hex parsing now supports `#RGB`, `#RGBA`, `#RRGGBB`, and `#RRGGBBAA`.
130-
131-
* The `Image.Color.t/0`, `Image.Color.rgb_color/0`, `Image.Color.transparency/0`, and `Image.Color.icc_profile/0` types have been replaced with `Image.Pixel.t/0`, `Image.Pixel.transparency/0`, and `Image.ICCProfile.t/0`.
132-
133-
* `priv/color/css_colors.csv` and `priv/color/additional_colors.csv` have been removed; the named-colour list lives in `Color.CSSNames` upstream (which already includes `ChromaGreen` and `ChromaBlue` for drop-in compatibility).
134-
135-
* See `guides/color_migration.md` for the full migration plan and rationale.
136-
13769
### Enhancements
13870

13971
* `Image.dominant_color/2` now accepts a `:method` option of either `:histogram` (the existing default) or `:imagequant`. The `:imagequant` method routes through `libimagequant` (via `vips_gifsave_buffer`) and returns a palette of `{r, g, b}` tuples ordered by perceptual importance. New `:effort` and `:dither` options tune the quantiser. See `guides/performance.md` for a comparison of the two methods.
@@ -142,7 +74,13 @@ This is the changelog for Image version 0.64.0 released on April 7th, 2026. For
14274

14375
* New `Image.Pixel` and `Image.ICCProfile` modules. `Image.Pixel.to_pixel/3` is the canonical way to turn any user-friendly colour input into a libvips-ready pixel for a particular image; `Image.Pixel.to_srgb/1` is the image-independent equivalent for callers (SVG renderers, gradients) that need a fixed sRGB output.
14476

145-
* The `:color` library is now a dependency of `:image`. It will progressively become the canonical colour science layer for the project.
77+
* The `:color` library is now a dependency of `:image`. It is now the canonical colour science layer for the project.
78+
79+
* `Image.Video` now supports HTTP/HTTPS/RTSP/RTMP URLs as video sources for free, since FFmpeg supports them natively.
80+
81+
* `Image.xav_configured?/0` is the new compile-time predicate that gates the `Image.Video` module (analogous to `Image.evision_configured?/0` and `Image.bumblebee_configured?/0`).
82+
83+
* The `Image.Video.frame_to_image/1` helper exposes the raw `Xav.Frame``Vix.Vips.Image.t()` conversion (used internally by `image_from_video/2` and `stream!/2`). Useful if you have a frame from elsewhere in the Xav ecosystem and want to bring it into `Image`.
14684

14785
## Image 0.63.0
14886

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
defmodule Image.MixProject do
22
use Mix.Project
33

4-
@version "0.67.0"
4+
@version "0.64.0"
55
@app_name "image"
66

77
def project do

0 commit comments

Comments
 (0)