diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7f42fd2..c53ce6a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,7 +8,7 @@ on: jobs: build: name: Build for all targets - runs-on: ubuntu-latest + runs-on: macos-latest steps: - uses: actions/checkout@v4 @@ -18,6 +18,10 @@ jobs: with: version: 0.13.0 + - name: Install FFmpeg + run: | + brew install ffmpeg + - name: Build for all targets run: | zig build -Drelease -Dci=true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6982111..b06a51d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,8 +1,5 @@ name: Zig Build and Test -on: - pull_request: - branches: [ main ] jobs: build-and-test: @@ -24,19 +21,21 @@ jobs: steps: - uses: actions/checkout@v2 + - uses: AnimMouse/setup-ffmpeg@v1 - name: Set up Zig uses: goto-bus-stop/setup-zig@v2 with: version: 0.13.0 + - name: Build and Test run: | if [ "${{ matrix.os }}" = "windows-latest" ]; then zig build -Drelease -Dtarget=${{ matrix.arch }}-windows test elif [ "${{ matrix.os }}" = "ubuntu-latest" ]; then zig build -Drelease -Dtarget=${{ matrix.arch }}-linux test - elif [ "${{ matrix.os }}" = "macos-latest" ]; then + elif [[ "${{ matrix.os }}" == macos* ]]; then zig build -Drelease -Dtarget=${{ matrix.arch }}-macos test fi shell: bash diff --git a/.gitignore b/.gitignore index b18e4a0..6d97fb2 100644 --- a/.gitignore +++ b/.gitignore @@ -18,9 +18,7 @@ zig-out/ /docgen_tmp/ images/ **/*.DS_Store -**/*.png -**/*.jpg -**/*.jpeg +test_output/ # Although this was renamed to .zig-cache, let's leave it here for a few # releases to make it less annoying to work with multiple branches. diff --git a/build.zig b/build.zig index 841c600..f569886 100644 --- a/build.zig +++ b/build.zig @@ -18,24 +18,53 @@ pub fn build(b: *std.Build) !void { } } else { const target = b.standardTargetOptionsQueryOnly(.{}); - try runZig(b, dep_stb, target, optimize); + try runZig(b, target, optimize, dep_stb); } } -fn buildCi( +fn setupExecutable( b: *std.Build, + name: []const u8, target: std.Target.Query, optimize: std.builtin.OptimizeMode, dep_stb: *std.Build.Dependency, -) !void { + link_libc: bool, +) !*std.Build.Step.Compile { const exe = b.addExecutable(.{ - .name = "asciigen", + .name = name, .root_source_file = b.path("src/main.zig"), .target = b.resolveTargetQuery(target), .optimize = optimize, - .link_libc = true, + .link_libc = link_libc, }); + const clap = b.dependency("clap", .{}); + exe.root_module.addImport("clap", clap.module("clap")); + + linkFfmpeg(exe); + + exe.addCSourceFile(.{ .file = b.path("stb/stb.c") }); + exe.addIncludePath(dep_stb.path("")); + + return exe; +} + +fn linkFfmpeg(exe: *std.Build.Step.Compile) void { + exe.linkSystemLibrary2("libavformat", .{ .use_pkg_config = .force }); + exe.linkSystemLibrary2("libavcodec", .{ .use_pkg_config = .force }); + exe.linkSystemLibrary2("libavutil", .{ .use_pkg_config = .force }); + exe.linkSystemLibrary2("libswscale", .{ .use_pkg_config = .force }); + exe.linkSystemLibrary2("libswresample", .{ .use_pkg_config = .force }); +} + +fn buildCi( + b: *std.Build, + target: std.Target.Query, + optimize: std.builtin.OptimizeMode, + dep_stb: *std.Build.Dependency, +) !void { + const exe = try setupExecutable(b, "asciigen", target, optimize, dep_stb, true); + const target_output = b.addInstallArtifact(exe, .{ .dest_dir = .{ .override = .{ @@ -45,43 +74,31 @@ fn buildCi( }); b.getInstallStep().dependOn(&target_output.step); - - const clap = b.dependency("clap", .{}); - exe.root_module.addImport("clap", clap.module("clap")); - - exe.addCSourceFile(.{ .file = b.path("stb/stb.c") }); - exe.addIncludePath(dep_stb.path("")); } fn runZig( b: *std.Build, - dep_stb: *std.Build.Dependency, target: std.Target.Query, optimize: std.builtin.OptimizeMode, + dep_stb: *std.Build.Dependency, ) !void { - const exe = b.addExecutable(.{ - .name = "asciigen", - .root_source_file = b.path("src/main.zig"), - .target = b.resolveTargetQuery(target), - .optimize = optimize, - .link_libc = true, - }); - - const clap = b.dependency("clap", .{}); - exe.root_module.addImport("clap", clap.module("clap")); + const exe = try setupExecutable( + b, + "asciigen", + target, + optimize, + dep_stb, + true, + ); - exe.addCSourceFile(.{ .file = b.path("stb/stb.c") }); - exe.addIncludePath(dep_stb.path("")); - - const exe_check = b.addExecutable(.{ - .name = "asciigen-check", - .root_source_file = b.path("src/main.zig"), - .target = b.resolveTargetQuery(target), - .optimize = optimize, - }); - exe_check.root_module.addImport("clap", clap.module("clap")); - exe_check.addCSourceFile(.{ .file = b.path("stb/stb.c") }); - exe_check.addIncludePath(dep_stb.path("")); + const exe_check = try setupExecutable( + b, + "asciigen-check", + target, + optimize, + dep_stb, + false, + ); const check_step = b.step("check", "Run the check"); check_step.dependOn(&exe_check.step); @@ -102,6 +119,7 @@ fn runZig( .optimize = optimize, .link_libc = true, }); + linkFfmpeg(unit_tests); unit_tests.addCSourceFile(.{ .file = b.path("stb/stb.c") }); unit_tests.addIncludePath(dep_stb.path("")); const run_unit_tests = b.addRunArtifact(unit_tests); diff --git a/src/main.zig b/src/main.zig index 9df229e..274a91c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -6,6 +6,16 @@ const stb = @cImport({ @cInclude("stb_image_write.h"); @cInclude("stb_image_resize2.h"); }); +const av = @cImport({ + @cInclude("libavformat/avformat.h"); + @cInclude("libavcodec/avcodec.h"); + @cInclude("libavutil/avutil.h"); + @cInclude("libavutil/imgutils.h"); + @cInclude("libswscale/swscale.h"); + @cInclude("libswresample/swresample.h"); + @cInclude("libavutil/channel_layout.h"); + @cInclude("libavutil/samplefmt.h"); +}); // VARS const ASCII_CHARS = " .:-=+*%#@"; // low to high brightness @@ -514,6 +524,7 @@ fn convertToAscii( } pub fn main() !void { + _ = av; var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); @@ -738,6 +749,7 @@ fn saveOutputImage(ascii_img: []u8, img: Image, args: Args) !void { } test "test_ascii_generation" { + _ = av; const allocator = std.testing.allocator; // Create a temporary file path @@ -751,11 +763,11 @@ test "test_ascii_generation" { // Set up test arguments const test_args = Args{ - .input = "https://w.wallhaven.cc/full/p9/wallhaven-p9gr2p.jpg", + .input = "test_img.png", .output = tmp_path, .color = false, .invert_color = false, - .scale = 8.0, + .scale = 1.0, .detect_edges = false, .sigma1 = 0.5, .sigma2 = 1.0, @@ -770,9 +782,9 @@ test "test_ascii_generation" { defer file.close(); // Delete the temporary file - try std.fs.deleteFileAbsolute(tmp_path); + // try std.fs.deleteFileAbsolute(tmp_path); // Try to open the file again, which should fail - const result = std.fs.openFileAbsolute(tmp_path, .{}); - try std.testing.expectError(error.FileNotFound, result); + // const result = std.fs.openFileAbsolute(tmp_path, .{}); + // try std.testing.expectError(error.FileNotFound, result); } diff --git a/test_img.png b/test_img.png new file mode 100644 index 0000000..d370e6f Binary files /dev/null and b/test_img.png differ