diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d76018..bd07f77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,16 +17,20 @@ jobs: MIX_ENV: test strategy: matrix: - otp_version: [25, 26] - - name: Linux x86_64 - OTP ${{ matrix.otp_version }} + job: + - { otp_version: "26", elixir_version: "1.15" } + - { otp_version: "24", elixir_version: "1.13" } + + name: Linux x86_64 - OTP ${{ matrix.job.otp_version }} steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v4 + - uses: erlef/setup-beam@v1 with: - otp-version: ${{ matrix.otp_version }} - elixir-version: 1.15 + otp-version: ${{ matrix.job.otp_version }} + elixir-version: ${{ matrix.job.elixir_version }} - name: Compile and Test run: | @@ -40,17 +44,20 @@ jobs: MIX_ENV: test strategy: matrix: - otp_version: [25, 26] + job: + - { otp_version: "26", elixir_version: "1.15" } + - { otp_version: "24", elixir_version: "1.13" } - name: Windows x86_64 - OTP ${{ matrix.otp_version }} + name: Windows x86_64 - OTP ${{ matrix.job.otp_version }} steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: - otp-version: ${{ matrix.otp_version }} - elixir-version: 1.15 + otp-version: ${{ matrix.job.otp_version }} + elixir-version: ${{ matrix.job.elixir_version }} - uses: ilammy/msvc-dev-cmd@v1 with: @@ -67,7 +74,7 @@ jobs: runs-on: macos-11 env: MIX_ENV: test - ELIXIR_VERSION: "1.16.0" + ELIXIR_VERSION: "1.16.2" strategy: matrix: otp_version: ["25.3.2.8", "26.2.2"] @@ -75,7 +82,8 @@ jobs: name: macOS x86_64 - OTP ${{ matrix.otp_version }} steps: - - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@v4 - name: Cache OTP uses: actions/cache@v3 @@ -109,6 +117,7 @@ jobs: cd ./cache/elixir tar -xzf elixir-${{ env.ELIXIR_VERSION }}.tar.gz cd elixir-${{ env.ELIXIR_VERSION }} + make compile make -j$(sysctl -n hw.ncpu) install - name: Install Mix and Rebar @@ -122,7 +131,7 @@ jobs: run: | export PATH=$(pwd)/./cache/otp/usr/local/bin:$(pwd)/./cache/elixir/elixir-${{ env.ELIXIR_VERSION }}/bin:${PATH} export ERL_ROOTDIR=$(pwd)/./cache/otp/usr/local/lib/erlang - + mix deps.get mix elixir_make.precompile mix test diff --git a/.github/workflows/precompile.yml b/.github/workflows/precompile.yml index 38b5de2..62dd13d 100644 --- a/.github/workflows/precompile.yml +++ b/.github/workflows/precompile.yml @@ -7,22 +7,23 @@ on: jobs: linux: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 env: MIX_ENV: prod strategy: matrix: - otp_version: [25, 26] - + otp_version: [24] + name: Linux x86_64 - OTP ${{ matrix.otp_version }} steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: ${{ matrix.otp_version }} - elixir-version: 1.15 + elixir-version: 1.13 - name: Install system dependecies run: | @@ -56,12 +57,13 @@ jobs: ELIXIR_VERSION: "1.16.0" strategy: matrix: - otp_version: ["25.3.2.8", "26.2.2"] + otp_version: ["24.3.4.16"] name: macOS x86_64 - OTP ${{ matrix.otp_version }} steps: - - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@v4 - name: Cache OTP uses: actions/cache@v3 @@ -84,7 +86,7 @@ jobs: with: path: ./cache/elixir key: ${{ runner.os }}-elixir-${{ env.ELIXIR_VERSION }} - + - name: Download and Compile Elixir if: steps.cache-elixir.outputs.cache-hit != 'true' run: | @@ -126,17 +128,18 @@ jobs: MIX_ENV: prod strategy: matrix: - otp_version: [25, 26] - + otp_version: [24] + name: Windows x86_64 - OTP ${{ matrix.otp_version }} steps: - - uses: actions/checkout@v3 + - name: Checkout + uses: actions/checkout@v4 - uses: erlef/setup-beam@v1 with: otp-version: ${{ matrix.otp_version }} - elixir-version: 1.15 + elixir-version: 1.11 - uses: ilammy/msvc-dev-cmd@v1 with: diff --git a/Makefile b/Makefile index c4c7894..80f1a64 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ endif endif ifeq ($(TARGET_ABI),darwin) - CPPFLAGS += -undefined dynamic_lookup -flat_namespace + CPPFLAGS += -undefined dynamic_lookup -flat_namespace -Wno-unused-function endif .DEFAULT_GLOBAL := build diff --git a/c_src/stb_image_nif.c b/c_src/stb_image_nif.c index 125f3a4..b64fb66 100644 --- a/c_src/stb_image_nif.c +++ b/c_src/stb_image_nif.c @@ -48,10 +48,6 @@ static ERL_NIF_TERM pack_data(ErlNifEnv *env, unsigned char *data, int x, int y, } static ERL_NIF_TERM read_file(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 2) { - return error(env, "expecting 2 arguments: path and desired_channels"); - } - char * c_path = NULL; ErlNifBinary path; int desired_channels = 0, bytes_per_channel; @@ -103,10 +99,6 @@ static ERL_NIF_TERM read_file(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[ } static ERL_NIF_TERM read_binary(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 2) { - return error(env, "expecting 2 arguments: binary and desired_channels"); - } - ErlNifBinary binary; int desired_channels, bytes_per_channel; int x, y, n; @@ -133,10 +125,6 @@ static ERL_NIF_TERM read_binary(ErlNifEnv *env, int argc, const ERL_NIF_TERM arg } static ERL_NIF_TERM read_gif_binary(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 1) { - return error(env, "expecting 1 argument: binary"); - } - ErlNifBinary binary; if (enif_inspect_binary(env, argv[0], &binary)) { @@ -203,10 +191,6 @@ static ERL_NIF_TERM read_gif_binary(ErlNifEnv *env, int argc, const ERL_NIF_TERM } static ERL_NIF_TERM write_file(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 6) { - return error(env, "expecting 6 arguments: path, format, data, height, width, and number of channels"); - } - char * c_path = NULL; char format[MAX_EXTNAME_LENGTH]; ErlNifBinary path; @@ -344,10 +328,6 @@ static void finalize_write(WriteContext *context, ErlNifEnv *env, ERL_NIF_TERM * } static ERL_NIF_TERM to_binary(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { - if (argc != 5) { - return error(env, "expecting 5 arguments: format, data, height, width, and number of channels"); - } - char format[MAX_EXTNAME_LENGTH]; ErlNifBinary img; int w, h, comp; @@ -417,10 +397,6 @@ static ERL_NIF_TERM to_binary(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[ } static ERL_NIF_TERM resize(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]){ - if (argc != 7) { - return error(env, "expecting 7 arguments: input pixels, input height, input width, number of channels, output height, output width, and bytes per channel"); - } - ErlNifBinary input_pixels; int input_h, input_w, output_h, output_w, num_channels, bytes_per_channel; int stride_in_bytes = 0; @@ -447,7 +423,7 @@ static ERL_NIF_TERM resize(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]){ return error(env, "invalid bytes per channel"); } - int status; + void * status; ErlNifBinary result; if (enif_alloc_binary(output_w * output_h * num_channels * bytes_per_channel, &result)) { @@ -459,7 +435,7 @@ static ERL_NIF_TERM resize(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]){ return error(env, "invalid type"); } - if (!status) { + if (status == NULL) { return error(env, "failed to resize"); } diff --git a/lib/stb_image.ex b/lib/stb_image.ex index c8607d7..6bc3695 100644 --- a/lib/stb_image.ex +++ b/lib/stb_image.ex @@ -90,7 +90,9 @@ defmodule StbImage do and one of the supported types (u8/f32). """ def from_nx(tensor) when is_struct(tensor, Nx.Tensor) do - new(Nx.to_binary(tensor), tensor_shape(Nx.shape(tensor)), type: tensor_type(Nx.type(tensor))) + new(Nx.to_binary(tensor), tensor_shape(Nx.shape(tensor)), + type: tensor_type(Nx.type(tensor)) + ) end defp tensor_type({:u, 8}), do: {:u, 8} diff --git a/mix.exs b/mix.exs index c71c7ca..38dc245 100644 --- a/mix.exs +++ b/mix.exs @@ -1,26 +1,25 @@ defmodule StbImage.MixProject do use Mix.Project + @app :stb_image @version "0.6.6" @github_url "https://github.com/elixir-nx/stb_image" def project do [ - app: :stb_image, + app: @app, version: @version, - elixir: "~> 1.12", + elixir: "~> 1.13", deps: deps(), name: "StbImage", description: "A tiny image reader/writer library using stb_image as the backend", docs: docs(), package: package(), - make_executable: make_executable(), - make_makefile: make_makefile(), compilers: [:elixir_make] ++ Mix.compilers(), make_precompiler: {:nif, CCPrecompiler}, make_precompiler_url: "#{@github_url}/releases/download/v#{@version}/@{artefact_filename}", make_precompiler_filename: "stb_image_nif", - make_precompiler_nif_versions: [versions: ["2.16", "2.17"]] + make_precompiler_nif_versions: [versions: ["2.16"]] ] end @@ -39,7 +38,7 @@ defmodule StbImage.MixProject do [ # compilation {:cc_precompiler, "~> 0.1.0"}, - {:elixir_make, "~> 0.7.0"}, + {:elixir_make, "~> 0.8.2"}, # optional {:nx, "~> 0.4", optional: true}, {:kino, "~> 0.7", optional: true}, @@ -56,26 +55,13 @@ defmodule StbImage.MixProject do ] end - defp package() do + defp package do [ name: "stb_image", - files: ~w(3rd_party/stb c_src lib mix.exs README* LICENSE* Makefile checksum.exs), + files: + ~w(3rd_party/stb c_src lib mix.exs README* LICENSE* Makefile Makefile.win checksum.exs), licenses: ["Apache-2.0"], links: %{"GitHub" => @github_url} ] end - - defp make_executable() do - case :os.type() do - {:win32, _} -> "nmake" - _ -> "make" - end - end - - defp make_makefile() do - case :os.type() do - {:win32, _} -> "Makefile.win" - _ -> "Makefile" - end - end end diff --git a/mix.lock b/mix.lock index 6e6d409..447a385 100644 --- a/mix.lock +++ b/mix.lock @@ -1,8 +1,8 @@ %{ - "cc_precompiler": {:hex, :cc_precompiler, "0.1.0", "03f0fc42f157b02e3cc54d11e56a87830455e43789483dd298a4a3787f876ad1", [:mix], [{:elixir_make, "~> 0.7.0", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3c61c5ff5ecf6f30d90577d25a83ea542bbbfab29d739b9f676a34e3198167f1"}, + "cc_precompiler": {:hex, :cc_precompiler, "0.1.10", "47c9c08d8869cf09b41da36538f62bc1abd3e19e41701c2cea2675b53c704258", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f6e046254e53cd6b41c6bacd70ae728011aa82b2742a80d6e2214855c6e06b22"}, "complex": {:hex, :complex, "0.4.2", "923e5db0be13dbb3ea00cf8459d9f75f3afdd9ff5a82742ded21064330d28273", [:mix], [], "hexpm", "069a085ef820ce675a2619fd125b963ff4514af2102c7f7d7965128e5ec0a429"}, "earmark_parser": {:hex, :earmark_parser, "1.4.37", "2ad73550e27c8946648b06905a57e4d454e4d7229c2dafa72a0348c99d8be5f7", [:mix], [], "hexpm", "6b19783f2802f039806f375610faa22da130b8edc21209d0bff47918bb48360e"}, - "elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, + "elixir_make": {:hex, :elixir_make, "0.8.2", "cd4a5a75891362e9207adaac7e66223fd256ec2518ae013af7f10c9c85b50b5c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "9d9607d640c372a7291e5a56ce655aa2351897929be20bd211648fdb79e725dc"}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "kino": {:hex, :kino, "0.7.0", "98d2623bebf8d1c4d761c5ed9741c6aae2f1909706baec501f2fdad347cb9d92", [:mix], [{:table, "~> 0.1.2", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "3dd1ee761c241caa30364333e3102a954d68188414a46e867f95c858d745f3fd"}, "makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"}, diff --git a/test/stb_image_test.exs b/test/stb_image_test.exs index d610942..7c85f5c 100644 --- a/test/stb_image_test.exs +++ b/test/stb_image_test.exs @@ -97,21 +97,35 @@ defmodule StbImageTest do assert Enum.all?(frames, &(&1.type == {:u, 8})) assert Enum.all?(frames, &(&1.shape == {2, 3, 4})) - assert Enum.at(frames, 0).data == <<180, 128, 70, 255, 171, 119, 61, 255, 65, 143, 117, 255, 222, 170, 112, 255, 205, 153, 95, 255, 88, 166, 140, 255>> - assert Enum.at(frames, 1).data == <<241, 145, 126, 255, 136, 190, 78, 255, 68, 122, 183, 255, 244, 196, 187, 255, 190, 205, 145, 255, 144, 184, 200, 255>> + assert Enum.at(frames, 0).data == + <<180, 128, 70, 255, 171, 119, 61, 255, 65, 143, 117, 255, 222, 170, 112, 255, 205, + 153, 95, 255, 88, 166, 140, 255>> + + assert Enum.at(frames, 1).data == + <<241, 145, 126, 255, 136, 190, 78, 255, 68, 122, 183, 255, 244, 196, 187, 255, 190, + 205, 145, 255, 144, 184, 200, 255>> end test "decode gif dispose mode previous" do - {:ok, frames, delays} = StbImage.read_gif_file(Path.join(__DIR__, "test_dispose_mode_previous.gif")) + {:ok, frames, delays} = + StbImage.read_gif_file(Path.join(__DIR__, "test_dispose_mode_previous.gif")) + assert delays == [70, 70, 70, 70] assert Enum.all?(frames, &(&1.type == {:u, 8})) assert Enum.all?(frames, &(&1.shape == {2, 2, 4})) - assert Enum.at(frames, 0).data == <<255, 255, 255, 255, 255, 255, 255, 255, 128, 128, 128, 255, 255, 255, 255, 255>> - assert Enum.at(frames, 1).data == <<128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 240, 240, 255>> - assert Enum.at(frames, 2).data == <<0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255>> - assert Enum.at(frames, 3).data == <<255, 255, 255, 255, 0, 0, 0, 255, 255, 255, 255, 255, 200, 200, 200, 255>> + assert Enum.at(frames, 0).data == + <<255, 255, 255, 255, 255, 255, 255, 255, 128, 128, 128, 255, 255, 255, 255, 255>> + + assert Enum.at(frames, 1).data == + <<128, 128, 128, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 240, 240, 255>> + + assert Enum.at(frames, 2).data == + <<0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255>> + + assert Enum.at(frames, 3).data == + <<255, 255, 255, 255, 0, 0, 0, 255, 255, 255, 255, 255, 200, 200, 200, 255>> end for ext <- ~w(bmp png tga jpg hdr)a do @@ -173,8 +187,8 @@ defmodule StbImageTest do assert img.shape == {2, 3, 4} assert img.data == - <<241, 145, 126, 255, 136, 190, 78, 255, 68, 122, 183, 255, 244, 196, 187, 255, 190, - 205, 145, 255, 144, 184, 200, 255>> + <<241, 145, 126, 255, 136, 190, 78, 255, 68, 122, 183, 255, 244, 196, 187, 255, + 190, 205, 145, 255, 144, 184, 200, 255>> assert StbImage.new(img.data, img.shape) == img assert StbImage.new(img.data, img.shape, type: :u8) == img