diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 864c56d..382e3a3 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -19,7 +19,7 @@ jobs: fail-fast: false matrix: version: - - '1.9' + - '1.11' - 'nightly' os: - ubuntu-latest diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml new file mode 100644 index 0000000..c9da0b5 --- /dev/null +++ b/.github/workflows/Release.yml @@ -0,0 +1,105 @@ +name: Build Release Assets + +on: + workflow_dispatch: + inputs: + upload_tag: + description: 'Optional: Release tag to upload to' + required: false + default: '' + type: string + release: + types: [created] + +jobs: + build: + name: Build ${{ matrix.os }}-${{ matrix.arch }} + runs-on: ${{ matrix.runner }} + strategy: + matrix: + include: + - runner: macos-latest + os: macos + arch: x86_64 + - runner: macos-latest + os: macos + arch: aarch64 + - runner: ubuntu-latest + os: linux + arch: x86_64 + xvfb: true + - runner: ubuntu-24.04-arm + os: linux + arch: aarch64 + xvfb: true + - runner: windows-latest + os: windows + arch: x86_64 + + steps: + - uses: actions/checkout@v4 + + - name: Remove System32 OpenSSL DLLs (Windows) + if: runner.os == 'Windows' + run: | + $system32 = "C:\Windows\System32" + + foreach ($dll in @("libcrypto-3-x64.dll", "libssl-3-x64.dll")) { + $path = Join-Path $system32 $dll + if (Test-Path $path) { + Remove-Item -Path $path -Force + Write-Host "Removed $dll from System32" + } else { + Write-Host "$dll not found in System32" + } + } + shell: pwsh + + - uses: julia-actions/setup-julia@v2 + with: + version: '1.11' + + - uses: julia-actions/cache@v1 + + - name: Install dependencies + run: julia --project=meta -e 'using Pkg; Pkg.instantiate()' + + - name: Build + env: + MACOS_PFX_PASSWORD: ${{ secrets.MACOS_PFX_PASSWORD }} + WINDOWS_PFX_PASSWORD: ${{ secrets.WINDOWS_PFX_PASSWORD }} + run: | + ${{ matrix.xvfb && 'xvfb-run -s ''-screen 0 1024x768x24''' || '' }} julia --project=meta meta/build.jl --target-platform=${{ matrix.os }} --target-arch=${{ matrix.arch }} --build-dir=build + + - uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.os }}-${{ matrix.arch }} + path: build/* + retention-days: 1 + + upload: + name: Upload to release + runs-on: ubuntu-latest + needs: build + if: github.event_name == 'release' || github.event.inputs.upload_tag != '' + + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + path: ./artifacts + + - name: Upload to release + env: + GH_TOKEN: ${{ github.token }} + run: | + TAG_NAME="${{ github.event.inputs.upload_tag || github.event.release.tag_name }}" + echo "Uploading to release: $TAG_NAME" + + find artifacts/ -type f | while read -r file; do + echo "Uploading: $file" + gh release upload "$TAG_NAME" "$file" + done + + echo "All artifacts uploaded successfully!" \ No newline at end of file diff --git a/.gitignore b/.gitignore index d38868a..b4a831b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # Build artifacts for creating documentation generated by the Documenter package docs/build/ docs/site/ +build Manifest.toml +!/meta/Manifest.toml \ No newline at end of file diff --git a/Project.toml b/Project.toml index 1a10462..cefc787 100644 --- a/Project.toml +++ b/Project.toml @@ -5,15 +5,21 @@ version = "0.2.0" [deps] ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" +NativeFileDialog = "e1fe445b-aa65-4df4-81c1-2041507f0fd4" PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a" [compat] Aqua = "0.7" -ColorTypes = "0.11" -Makie = "0.19, 0.20" +ColorTypes = "0.12.1" +FileIO = "1.17.1" +GLMakie = "0.13.6" +Makie = "0.24.6" +NativeFileDialog = "0.2.1" PrecompileTools = "1" -julia = "1.6" +julia = "1.10" [extras] Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" @@ -21,3 +27,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] test = ["Aqua", "Test"] + +[bundle] +APP_NAME = "ImageColorThresholder" +APP_DISPLAY_NAME = "ImageColorThresholder" diff --git a/meta/Project.toml b/meta/Project.toml new file mode 100644 index 0000000..bb7fde7 --- /dev/null +++ b/meta/Project.toml @@ -0,0 +1,2 @@ +[deps] +AppBundler = "40eb83ae-c93a-480c-8f39-f018b568f472" diff --git a/meta/build.jl b/meta/build.jl new file mode 100644 index 0000000..bd6ca7a --- /dev/null +++ b/meta/build.jl @@ -0,0 +1,29 @@ +using AppBundler + +APP_DIR = dirname(@__DIR__) + +config = AppBundler.parse_args(ARGS) + +build_dir = config[:build_dir] +@info "Build products will be created at $build_dir" + +precompile = config[:precompile] +incremental = config[:incremental] +target_platforms = config[:target_platforms] +target_arch = config[:target_arch] +adhoc_signing = config[:adhoc_signing] + +version = AppBundler.get_version(APP_DIR) +target_name = "ImageColorThresholder-$version-$(target_arch)" + +if :linux in target_platforms + AppBundler.build_app(Linux(target_arch), APP_DIR, "$build_dir/$target_name.snap"; precompile, incremental) +end + +if :windows in target_platforms + AppBundler.build_app(Windows(target_arch), APP_DIR, "$build_dir/$target_name.msix"; precompile, incremental, adhoc_signing, windowed=false) +end + +if :macos in target_platforms + AppBundler.build_app(MacOS(target_arch), APP_DIR, "$build_dir/$target_name.dmg"; precompile, incremental, adhoc_signing) +end diff --git a/meta/patches/GLMakie/src/precompiles.jl b/meta/patches/GLMakie/src/precompiles.jl new file mode 100644 index 0000000..b8e5a7d --- /dev/null +++ b/meta/patches/GLMakie/src/precompiles.jl @@ -0,0 +1,77 @@ +using PrecompileTools + +# macro compile(block) +# return quote +# let +# figlike = $(esc(block)) +# Makie.colorbuffer(figlike; px_per_unit = 1) +# Makie.second_resolve(figlike, :gl_renderobject) +# return nothing +# end +# end +# end + +# let +# @setup_workload begin +# x = rand(5) +# @compile_workload begin + +# GLMakie.activate!() +# screen = GLMakie.singleton_screen(false) +# close(screen) +# destroy!(screen) + +# base_path = normpath(joinpath(dirname(pathof(Makie)), "..", "precompile")) +# shared_precompile = joinpath(base_path, "shared-precompile.jl") +# include(shared_precompile) +# try +# display(plot(x); visible = false) +# catch +# end +# Makie.CURRENT_FIGURE[] = nothing + +# screen = Screen(Scene()) +# refresh_func = refreshwindowcb(screen) +# refresh_func(to_native(screen)) +# close(screen) +# screen = empty_screen(false) +# close(screen) +# destroy!(screen) +# screen = empty_screen(false, false, nothing) +# destroy!(screen) +# config = Makie.merge_screen_config(ScreenConfig, Dict{Symbol, Any}()) +# screen = Screen(Scene(), config, nothing, MIME"image/png"(); visible = false, start_renderloop = false) +# close(screen) + + +# config = Makie.merge_screen_config(ScreenConfig, Dict{Symbol, Any}()) +# screen = Screen(Scene(), config; visible = false, start_renderloop = false) +# close(screen) + +# closeall(; empty_shader = false) +# @assert isempty(SCREEN_REUSE_POOL) +# @assert isempty(ALL_SCREENS) +# @assert isempty(SINGLETON_SCREEN) +# end +# end +# nothing +# end + +precompile(Screen, (Scene, ScreenConfig)) +precompile(GLFramebuffer, (NTuple{2, Int},)) +precompile(glTexImage, (GLenum, Int, GLenum, Int, Int, Int, GLenum, GLenum, Ptr{Float32})) +precompile(glTexImage, (GLenum, Int, GLenum, Int, Int, Int, GLenum, GLenum, Ptr{RGBAf})) +precompile(glTexImage, (GLenum, Int, GLenum, Int, Int, Int, GLenum, GLenum, Ptr{RGBf})) +precompile(glTexImage, (GLenum, Int, GLenum, Int, Int, Int, GLenum, GLenum, Ptr{RGBA{N0f8}})) +precompile( + glTexImage, + (GLenum, Int, GLenum, Int, Int, Int, GLenum, GLenum, Ptr{GLAbstraction.DepthStencil_24_8}) +) +precompile(glTexImage, (GLenum, Int, GLenum, Int, Int, Int, GLenum, GLenum, Ptr{Vec{2, GLuint}})) +precompile(glTexImage, (GLenum, Int, GLenum, Int, Int, Int, GLenum, GLenum, Ptr{RGBA{Float16}})) +precompile(glTexImage, (GLenum, Int, GLenum, Int, Int, Int, GLenum, GLenum, Ptr{N0f8})) +precompile(setindex!, (GLMakie.GLAbstraction.Texture{Float16, 2}, Matrix{Float32}, Rect2{Int32})) +precompile(getindex, (Makie.Text{Tuple{Vector{Point{2, Float32}}}}, Symbol)) +precompile(getproperty, (Makie.Text{Tuple{Vector{Point{2, Float32}}}}, Symbol)) +precompile(plot!, (Makie.Text{Tuple{Vector{Point{2, Float32}}}},)) +precompile(Base.getindex, (Attributes, Symbol)) diff --git a/src/ImageColorThresholderApp.jl b/src/ImageColorThresholderApp.jl index 9b4d0dd..6081113 100644 --- a/src/ImageColorThresholderApp.jl +++ b/src/ImageColorThresholderApp.jl @@ -295,4 +295,25 @@ function image_color_thresholder_app(img::Matrix{Lab{T}}) where {T} end include("precompile.jl") + +# Creating a launcher for the application +using NativeFileDialog +using FileIO +using GLMakie + +function (@main)(ARGS) + + file = NativeFileDialog.pick_file(homedir(); filterlist="png;jpg") + img = FileIO.load(file) + img_rgb = RGB.(img) + fig = image_color_thresholder_app(img_rgb) + + display(fig) + wait(fig.scene) # Wait until the window is closed + + return +end + +export main + end