Skip to content

Commit 1d68123

Browse files
committed
Merge branch 'lensfun'
2 parents 243e4d6 + 58d55e3 commit 1d68123

File tree

6 files changed

+13
-190
lines changed

6 files changed

+13
-190
lines changed

CHANGELOG.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,17 @@
22

33
## Image 0.59.0
44

5-
This is the changelog for Image version 0.59.0 released on March 13th, 2025. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-image/image/tags)
5+
This is the changelog for Image version 0.59.0 released on March 14th, 2025. For older changelogs please consult the release tag on [GitHub](https://github.com/elixir-image/image/tags)
66

77
### Breaking Change
88

9-
* Rename `Image.barrel_correction/5` to `Image.radial_distortion_correction/5` since it applies to both barrel and pincushion distortion.
9+
* `Image.radial_distortion_correction/5` and `Image.vignette_correction/4` have moved to a new library [image_lens_correction](https://github.com/elixir-image/image_lens_correction).
1010

1111
### Enhancements
1212

1313
* Tolerate non-compliant null-terminated datatime strings in Exif. Thanks to @hansihe for the PR. Closes #181.
1414

15-
* Add `Image.vignette_correct/4` to apply a vignette correction to an image - typically a digital photograph.
16-
17-
* Add `Image.Math.max/1`, `Image.Math.min/1`, `Image.Math.max!/1` and `Image.Math.min!/1`
15+
* Add `Image.Math.max/1`, `Image.Math.min/1`, `Image.Math.max!/1`, `Image.Math.min!/1` and `Image.Complex.polar/1`.
1816

1917
## Image 0.58.0
2018

lib/image.ex

Lines changed: 0 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -9690,173 +9690,6 @@ defmodule Image do
96909690
Vix.Vips.Operation.mapim(image, index, interpolate: bicubic_interpolator)
96919691
end
96929692

9693-
@doc """
9694-
Applies a correction for [barrel distortion](https://www.iphotography.com/blog/what-is-lens-barrel-distortion/)
9695-
and pincushion distortion.
9696-
9697-
Barrel/pincushion distortion is present in all but the most optically
9698-
perfect camera lens. Some cameras will apply a correction
9699-
in-camera, many do not.
9700-
9701-
The parameters to the function, which are "a", "b", "c" and
9702-
optionally "d", are specific to each lens and focal distance.
9703-
9704-
The primary source of these parameters is the [lensfun database](https://github.com/lensfun/lensfun)
9705-
which lists the parameters for many lens.
9706-
9707-
In general these numbers are very small, typically less than
9708-
0.1, so when experimenting to find acceptable output start with
9709-
small numbers for `a` and `b` and `0.0` for `c`. Omit the `d`
9710-
parameter in most, if not all, cases.
9711-
9712-
A future release may incorporate the lensfun database to automatically
9713-
derive the correct parameters based upon image [exif](https://en.wikipedia.org/wiki/Exif) data.
9714-
9715-
### Arguments
9716-
9717-
* `image` is any `t:Vimage.t/0`.
9718-
9719-
* `a`, `b`, `c` are parameters specific to each
9720-
camera lens and focal distance, typically found in the
9721-
[lensfun](https://github.com/lensfun/lensfun) database.
9722-
9723-
### Returns
9724-
9725-
* `{:ok, undistorted_image}` or
9726-
9727-
* `{:error, reason}`
9728-
9729-
### Example
9730-
9731-
iex> image = Image.open!("./test/support/images/gridlines_barrel.png")
9732-
iex> Image.radial_distortion_correction(image, -0.007715, 0.086731, 0.0)
9733-
9734-
"""
9735-
@doc subject: "Distortion", since: "0.58.0"
9736-
9737-
@spec radial_distortion_correction(
9738-
image :: Vimage.t(),
9739-
a :: number(),
9740-
b :: number(),
9741-
c :: number(),
9742-
d :: (number() | nil)
9743-
) ::
9744-
{:ok, Vimage.t()} | {:error, error_message}
9745-
9746-
def radial_distortion_correction(%Vimage{} = image, a, b, c, d \\ nil)
9747-
when is_number(a) and is_number(b) and is_number(c) and (is_number(d) or is_nil(d)) do
9748-
use Image.Math
9749-
9750-
d = if is_nil(d), do: 1.0 - a - b - c, else: d
9751-
9752-
width = width(image)
9753-
height = height(image)
9754-
9755-
radius = min(width, height) / 2
9756-
centre_x = (width - 1) / 2
9757-
centre_y = (height - 1) / 2
9758-
9759-
# Cartesian coordinates of the destination point
9760-
# relative to the centre of the image.
9761-
index = Vix.Vips.Operation.xyz!(width, height)
9762-
delta = (index - [centre_x, centre_y]) / radius
9763-
9764-
# distance or radius of destination image
9765-
dstr = pow!(delta[0] ** 2 + delta[1] ** 2, 0.5)
9766-
9767-
# distance or radius of source image (with formula)
9768-
srcr = dstr * (a * dstr ** 3 + b * dstr ** 2 + c * dstr + d)
9769-
9770-
# comparing old and new distance to get factor
9771-
factor = Vix.Vips.Operation.abs!(dstr / srcr)
9772-
9773-
# coordinates in the source image
9774-
transform = [centre_x, centre_y] + delta * factor * radius
9775-
9776-
# Map new coordinates
9777-
Operation.mapim(image, transform)
9778-
end
9779-
9780-
@doc """
9781-
Applies a correction for [vignetting](https://en.wikipedia.org/wiki/Vignetting).
9782-
9783-
In photography and optics, vignetting is a reduction of an image's
9784-
brightness or saturation toward the periphery compared to the
9785-
image center.
9786-
9787-
Vignetting is often an unintended and undesired effect caused by
9788-
camera settings or lens limitations.
9789-
9790-
The parameters to the function, which are "k1", "k2" and "k3"
9791-
are specific to each lens, aperature and focal distance.
9792-
9793-
The primary source of these parameters is the [lensfun database](https://github.com/lensfun/lensfun)
9794-
which lists the parameters for many lens.
9795-
9796-
In general these numbers are very small, typically less than
9797-
0.1, so when experimenting to find acceptable output start with
9798-
small numbers for `k1` and `k2` and `0.0` for `k3`.
9799-
9800-
A future release may incorporate the lensfun database to automatically
9801-
derive the correct parameters based upon image [exif](https://en.wikipedia.org/wiki/Exif) data.
9802-
9803-
### Arguments
9804-
9805-
* `image` is any `t:Vimage.t/0`.
9806-
9807-
* `k1`, `k2`, `k3` are parameters specific to each
9808-
camera lens and focal distance, typically found in the
9809-
[lensfun](https://github.com/lensfun/lensfun) database.
9810-
9811-
### Returns
9812-
9813-
* `{:ok, unvignetted_image}` or
9814-
9815-
* `{:error, reason}`
9816-
9817-
### Example
9818-
9819-
iex> image = Image.new!(200, 200, color: :green)
9820-
iex> Image.vignette_correction(image, -0.2764, -1.26031, 0.7727)
9821-
9822-
"""
9823-
9824-
@doc subject: "Distortion", since: "0.59.0"
9825-
9826-
@spec vignette_correction(
9827-
image :: Vimage.t(),
9828-
k1 :: number(),
9829-
k2 :: number(),
9830-
k3 :: number()
9831-
) ::
9832-
{:ok, Vimage.t()} | {:error, error_message}
9833-
9834-
def vignette_correction(%Vimage{} = image, k1, k2, k3) do
9835-
use Image.Math
9836-
9837-
format = Image.band_format(image)
9838-
width = Image.width(image)
9839-
height = Image.height(image)
9840-
9841-
centre_x = (width - 1) / 2
9842-
centre_y = (height - 1) / 2
9843-
9844-
# Cartesian coordinates of the destination point
9845-
# relative to the centre of the image.
9846-
index = Operation.xyz!(width, height)
9847-
index = (index - [centre_x, centre_y])
9848-
r = pow!(index[0]**2 + index[1]**2, 0.5)
9849-
r = r / max!(r)
9850-
9851-
# Correction function from https://lensfun.github.io/calibration-tutorial/lens-vignetting.html
9852-
# Also http://download.macromedia.com/pub/labs/lensprofile_creator/lensprofile_creator_cameramodel.pdf
9853-
# Cd = Cs * (1 + k1 * R^2 + k2 * R^4 + k3 * R^6)
9854-
# Inverting the formula to un-vignette (rather than calibrate the vignette)
9855-
d_dest = 1.0 - (k1 * r**2) + (k2 * r**4) + (k3 * r**6)
9856-
9857-
Image.cast(image / d_dest, format)
9858-
end
9859-
98609693
@doc """
98619694
Returns a transformation matrix for a given
98629695
image, source quadrilateral and desintation quadrilateral.

lib/image/complex.ex

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ defmodule Image.Complex do
1515
complex(image, &Operation.complex(&1, :VIPS_OPERATION_COMPLEX_POLAR))
1616
end
1717

18+
@dialyzer {:nowarn_function, {:polar!, 1}}
19+
20+
def polar!(%Vimage{} = image) do
21+
case polar(image) do
22+
{:ok, polar} -> polar
23+
{:error, reason} -> raise Image.Error, reason
24+
end
25+
end
26+
1827
@dialyzer {:nowarn_function, {:rectangular, 1}}
1928

2029
def rectangular(%Vimage{} = image) do

mix.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ defmodule Image.MixProject do
115115
"lib",
116116
"priv/color",
117117
"priv/fonts",
118+
"priv/lensfun",
118119
"mix.exs",
119120
"README*",
120121
"CHANGELOG*",

test/distortion_correction_test.exs

Lines changed: 0 additions & 18 deletions
This file was deleted.
-29.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)