Skip to content

Commit

Permalink
Add an image format type
Browse files Browse the repository at this point in the history
  • Loading branch information
jrstrunk committed Oct 1, 2024
1 parent 8be558e commit d4ef83b
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 70 deletions.
16 changes: 0 additions & 16 deletions src/ansel.ex
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
defmodule Ansel do
alias Vix.Vips.{Image, Operation}

def from_bit_array(bin) do
with {:ok, %Image{} = img} <- Image.new_from_buffer(bin) do
{:ok, img}
else
{:error, reason} -> {:error, reason}
end
end

def write_to_file(img, path) do
save_path = Path.expand(path)

Expand All @@ -26,10 +18,6 @@ defmodule Ansel do
Operation.composite2(base_image, overlay_image, :VIPS_BLEND_MODE_OVER, x: l, y: t)
end

def extract_area(image, x, y, w, h) do
Operation.extract_area(image, x, y, w, h)
end

def new_image(height, width, background) do
case Operation.black(height, width, bands: 3) do
{:ok, img} ->
Expand All @@ -39,8 +27,4 @@ defmodule Ansel do
{:error, reason}
end
end

def resize(img, scale) do
Operation.resize(img, scale)
end
end
58 changes: 25 additions & 33 deletions src/ansel.gleam
Original file line number Diff line number Diff line change
@@ -1,39 +1,23 @@
import ansel/bounding_box
import ansel/color
import gleam/int
import gleam/io
import gleam/result
import simplifile
import snag

pub fn main() {
io.println("Hello from ansel!")

// let assert Ok(base) =
// simplifile.read_bits("test.jpg")
// |> result.unwrap(<<>>)
// |> from_bit_array

// let assert Ok(overlay) =
// simplifile.read_bits("ss.png")
// |> result.unwrap(<<>>)
// |> from_bit_array

// let _ =
// composite_over(base, overlay, 1, 1)
// |> result.map(write(_, "out.jpg"))

// base
// |> extract_area(LTWH(left: 100, top: 100, width: 400, height: 400))
// |> result.map(write(_, "out2.jpg"))
// |> io.debug

let assert Ok(bin) = simplifile.read_bits("comp.png")

let assert Ok(img) = from_bit_array(bin)
pub type ImageFormat {
AVIF(quality: Int)
JPG(quality: Int)
PNG
WEBP(quality: Int)
}

extract_area(img, at: bounding_box.LTWH(left: 3, top: 3, width: 6, height: 6))
|> result.map(write(_, "extract.png"))
fn image_format_to_string(format: ImageFormat) -> String {
case format {
PNG -> ".png"
JPG(quality) -> ".jpg[Q=" <> int.to_string(quality) <> "]"
WEBP(quality) -> ".webp[Q=" <> int.to_string(quality) <> "]"
AVIF(quality) -> ".avif[Q=" <> int.to_string(quality) <> "]"
}
}

pub type Image
Expand All @@ -44,11 +28,15 @@ pub fn from_bit_array(bin: BitArray) -> Result(Image, snag.Snag) {
|> snag.context("Failed to read image from bit array")
}

@external(erlang, "Elixir.Ansel", "from_bit_array")
@external(erlang, "Elixir.Vix.Vips.Image", "new_from_buffer")
fn from_bit_array_ffi(bin: BitArray) -> Result(Image, String)

pub fn to_bit_array(img: Image, format: ImageFormat) -> BitArray {
to_bit_array_ffi(img, image_format_to_string(format))
}

@external(erlang, "Elixir.Ansel", "to_bit_array")
pub fn to_bit_array(img: Image, format: String) -> BitArray
fn to_bit_array_ffi(img: Image, format: String) -> BitArray

pub fn new_image(
width width: Int,
Expand Down Expand Up @@ -123,8 +111,12 @@ pub fn resize_by(img: Image, scale scale: Float) -> Result(Image, snag.Snag) {
@external(erlang, "Elixir.Vix.Vips.Operation", "resize")
fn resize_ffi(img: Image, scale: Float) -> Result(Image, String)

pub fn write(img: Image, to path: String) -> Result(Nil, snag.Snag) {
write_ffi(img, path)
pub fn write(
img: Image,
to path: String,
in format: ImageFormat,
) -> Result(Nil, snag.Snag) {
write_ffi(img, path <> image_format_to_string(format))
|> result.map_error(snag.new)
|> snag.context("Failed to write image to file")
}
Expand Down
42 changes: 21 additions & 21 deletions test/ansel_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn new_image_solid_grey_test() {
simplifile.read_bits("test/resources/solid_grey_6x6.avif")

ansel.new_image(6, 6, color.Grey)
|> result.map(ansel.to_bit_array(_, ".avif"))
|> result.map(ansel.to_bit_array(_, ansel.AVIF(quality: 100)))
|> should.equal(Ok(bin))
}

Expand All @@ -24,7 +24,7 @@ pub fn new_image_nongrey_test() {
simplifile.read_bits("test/resources/gleam_lucy_6x6.avif")

ansel.new_image(6, 6, color.GleamLucy)
|> result.map(ansel.to_bit_array(_, ".avif"))
|> result.map(ansel.to_bit_array(_, ansel.AVIF(quality: 100)))
|> should.equal(Ok(bin))
}

Expand All @@ -33,23 +33,23 @@ pub fn bit_array_avif_round_trip_test() {
simplifile.read_bits("test/resources/gleam_lucy_6x6.avif")

ansel.from_bit_array(bin)
|> result.map(ansel.to_bit_array(_, ".avif"))
|> result.map(ansel.to_bit_array(_, ansel.AVIF(quality: 100)))
|> should.equal(Ok(bin))
}

pub fn bit_array_jpg_round_trip_test() {
let assert Ok(bin) = simplifile.read_bits("test/resources/gleam_lucy_6x6.jpg")

ansel.from_bit_array(bin)
|> result.map(ansel.to_bit_array(_, ".jpg"))
|> result.map(ansel.to_bit_array(_, ansel.JPG(quality: 100)))
|> should.equal(Ok(bin))
}

pub fn bit_array_png_round_trip_test() {
let assert Ok(bin) = simplifile.read_bits("test/resources/gleam_lucy_6x6.png")

ansel.from_bit_array(bin)
|> result.map(ansel.to_bit_array(_, ".png"))
|> result.map(ansel.to_bit_array(_, ansel.PNG))
|> should.equal(Ok(bin))
}

Expand All @@ -58,7 +58,7 @@ pub fn bit_array_webp_round_trip_test() {
simplifile.read_bits("test/resources/gleam_lucy_6x6.webp")

ansel.from_bit_array(bin)
|> result.map(ansel.to_bit_array(_, ".webp"))
|> result.map(ansel.to_bit_array(_, ansel.WEBP(quality: 100)))
|> should.equal(Ok(bin))
}

Expand All @@ -73,7 +73,7 @@ pub fn composite_over_test() {
ansel.new_image(width: 6, height: 6, color: color.GleamNavy)

ansel.composite_over(base, with: new, at_left_position: 1, at_top_position: 1)
|> result.map(ansel.to_bit_array(_, ".png"))
|> result.map(ansel.to_bit_array(_, ansel.PNG))
|> should.equal(Ok(bin))
}

Expand All @@ -99,7 +99,7 @@ pub fn extract_area_test() {
comp,
at: bounding_box.LTWH(left: 3, top: 3, width: 6, height: 6),
)
|> result.map(ansel.to_bit_array(_, ".png"))
|> result.map(ansel.to_bit_array(_, ansel.PNG))
|> should.equal(Ok(ext))
}

Expand All @@ -124,10 +124,10 @@ pub fn resize_width_down_test() {
ansel.new_image(width: 6, height: 4, color: color.GleamLucy)

ansel.resize_width_to(img, res: 3)
|> result.map(ansel.to_bit_array(_, ".png"))
|> result.map(ansel.to_bit_array(_, ansel.PNG))
|> should.equal(
ansel.new_image(width: 3, height: 2, color: color.GleamLucy)
|> result.map(ansel.to_bit_array(_, ".png")),
|> result.map(ansel.to_bit_array(_, ansel.PNG)),
)
}

Expand All @@ -136,10 +136,10 @@ pub fn resize_width_up_test() {
ansel.new_image(width: 6, height: 4, color: color.GleamLucy)

ansel.resize_width_to(img, res: 12)
|> result.map(ansel.to_bit_array(_, ".png"))
|> result.map(ansel.to_bit_array(_, ansel.PNG))
|> should.equal(
ansel.new_image(width: 12, height: 8, color: color.GleamLucy)
|> result.map(ansel.to_bit_array(_, ".png")),
|> result.map(ansel.to_bit_array(_, ansel.PNG)),
)
}

Expand All @@ -148,10 +148,10 @@ pub fn resize_height_down_test() {
ansel.new_image(width: 6, height: 8, color: color.GleamLucy)

ansel.resize_height_to(img, res: 4)
|> result.map(ansel.to_bit_array(_, ".png"))
|> result.map(ansel.to_bit_array(_, ansel.PNG))
|> should.equal(
ansel.new_image(width: 3, height: 4, color: color.GleamLucy)
|> result.map(ansel.to_bit_array(_, ".png")),
|> result.map(ansel.to_bit_array(_, ansel.PNG)),
)
}

Expand All @@ -160,10 +160,10 @@ pub fn resize_height_up_test() {
ansel.new_image(width: 6, height: 4, color: color.GleamNavy)

ansel.resize_height_to(img, res: 12)
|> result.map(ansel.to_bit_array(_, ".png"))
|> result.map(ansel.to_bit_array(_, ansel.PNG))
|> should.equal(
ansel.new_image(width: 18, height: 12, color: color.GleamNavy)
|> result.map(ansel.to_bit_array(_, ".png")),
|> result.map(ansel.to_bit_array(_, ansel.PNG)),
)
}

Expand All @@ -172,10 +172,10 @@ pub fn resize_scale_down_test() {
ansel.new_image(width: 6, height: 4, color: color.GleamLucy)

ansel.resize_by(img, scale: 0.5)
|> result.map(ansel.to_bit_array(_, ".png"))
|> result.map(ansel.to_bit_array(_, ansel.PNG))
|> should.equal(
ansel.new_image(width: 3, height: 2, color: color.GleamLucy)
|> result.map(ansel.to_bit_array(_, ".png")),
|> result.map(ansel.to_bit_array(_, ansel.PNG)),
)
}

Expand All @@ -184,9 +184,9 @@ pub fn resize_scale_up_test() {
ansel.new_image(width: 6, height: 4, color: color.GleamNavy)

ansel.resize_by(img, scale: 3.0)
|> result.map(ansel.to_bit_array(_, ".png"))
|> result.map(ansel.to_bit_array(_, ansel.PNG))
|> should.equal(
ansel.new_image(width: 18, height: 12, color: color.GleamNavy)
|> result.map(ansel.to_bit_array(_, ".png")),
|> result.map(ansel.to_bit_array(_, ansel.PNG)),
)
}
}
Binary file modified test/resources/gleam_lucy_6x6.avif
Binary file not shown.
Binary file modified test/resources/gleam_lucy_6x6.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/resources/gleam_lucy_6x6.webp
Binary file not shown.
Binary file modified test/resources/solid_grey_6x6.avif
Binary file not shown.

0 comments on commit d4ef83b

Please sign in to comment.