Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ run the program with the following options (the default zig install directory is
- `-e, --detect_edges`: enable edge detection (optional)
- ` --sigma1 <float>`: set the sigma1 value for DoG filter (optional, default: 0.3)
- ` --sigma2 <float>`: set the sigma2 value for DoG filter (optional, default: 1.0)
- ` --dither floydstein`: enable dithering (currently only supports floydstein algorithm)
- `-b, --brightness_boost <float>`: increase/decrease perceived brightness (optional, default: 1.0)
advanced options:
- ` --full_characters`: Uses all ascii characters in generated output.
Expand All @@ -63,6 +62,10 @@ run the program with the following options (the default zig install directory is
- ` --keep_audio`: Preserves audio from input video.
- ` --stretched`: Resizes media to fit terminal window
- `-f, --frame_rate`: Target frame rate for video output (default: matches input fps)
- `-d, --dither <str>`: Dithering, supported values: "floydstein" (default: "floydstein")
- ` --fg <str>`: Set a 6-digit hex value like "#ffffff" for the foreground color (default: "#d36a6f")
- ` --bg <str>`: Set a 6-digit hex value like "#000000" for the background color (default: "#15091b")
- ` --transparent_bg`: Set the background to transparent

>To render on the terminal directly, just omit the output option.

Expand Down
27 changes: 13 additions & 14 deletions src/core.zig
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub const CoreParams = struct {
dither: ?DitherType,
bg_color: ?[3]u8,
fg_color: ?[3]u8,
transparent_bg: bool,

pub fn deinit(self: *CoreParams) void {
var it = self.ffmpeg_options.iterator();
Expand Down Expand Up @@ -505,11 +506,12 @@ fn convertToAscii(
color: [3]u8,
block_size: u8,
color_enabled: bool,
channels: u8,
args: CoreParams,
) !void {
const bm = &(try bitmap.getCharSet(ascii_char));
const block_w = @min(block_size, w - x);
const block_h = @min(block_size, img.len / (w * 3) - y);
const block_h = @min(block_size, h - y);

// Define new colors
const background_color = if (args.bg_color != null) args.bg_color.? else [3]u8{ 21, 9, 27 }; // Blackcurrant
Expand All @@ -523,7 +525,7 @@ fn convertToAscii(
const img_y = y + dy;

if (img_x < w and img_y < h) {
const idx = (img_y * w + img_x) * 3;
const idx = (img_y * w + img_x) * channels;
const shift: u3 = @intCast(7 - dx);
const bit: u8 = @as(u8, 1) << shift;
if ((bm[dy] & bit) != 0) {
Expand All @@ -537,17 +539,13 @@ fn convertToAscii(
img[idx + 1] = text_color[1];
img[idx + 2] = text_color[2];
}
} else {
// not a character pixel: set to black
if (color_enabled) {
img[idx] = 0;
img[idx + 1] = 0;
img[idx + 2] = 0;
} else {
img[idx] = background_color[0];
img[idx + 1] = background_color[1];
img[idx + 2] = background_color[2];
if (channels == 4) {
img[idx + 3] = 255;
}
} else if (!color_enabled) {
img[idx] = background_color[0];
img[idx + 1] = background_color[1];
img[idx + 2] = background_color[2];
}
}
}
Expand Down Expand Up @@ -582,7 +580,8 @@ pub fn generateAsciiArt(
if (curr_ditherr) |buf| @memset(buf, 0);
if (next_ditherr) |buf| @memset(buf, 0);

const ascii_img = try allocator.alloc(u8, out_w * out_h * 3);
const channels: u8 = if (args.transparent_bg) 4 else 3;
const ascii_img = try allocator.alloc(u8, out_w * out_h * channels);
@memset(ascii_img, 0);

var y: usize = 0;
Expand Down Expand Up @@ -621,7 +620,7 @@ pub fn generateAsciiArt(
const ascii_char = selectAsciiChar(block_info, args);
const avg_color = calculateAverageColor(block_info, args);

try convertToAscii(ascii_img, out_w, out_h, x, y, ascii_char, avg_color, args.block_size, args.color, args);
try convertToAscii(ascii_img, out_w, out_h, x, y, ascii_char, avg_color, args.block_size, args.color, channels, args);
}

if (curr_ditherr != null and next_ditherr != null) {
Expand Down
7 changes: 3 additions & 4 deletions src/image.zig
Original file line number Diff line number Diff line change
Expand Up @@ -218,21 +218,20 @@ fn saveOutputImage(ascii_img: []u8, img: core.Image, args: core.CoreParams) !voi

out_w = @max(out_w, 1);
out_h = @max(out_h, 1);

const channels: u8 = if (args.transparent_bg) 4 else 3;
const save_result = stb.stbi_write_png(
@ptrCast(args.output.?.ptr),
@intCast(out_w),
@intCast(out_h),
@intCast(img.channels),
channels,
@ptrCast(ascii_img.ptr),
@intCast(out_w * 3),
@intCast(out_w * channels),
);
if (save_result == 0) {
std.debug.print("Error writing output image\n", .{});
return error.ImageWriteFailed;
}
}

pub fn processImage(allocator: std.mem.Allocator, args: core.CoreParams) !void {
const original_img = try loadAndScaleImage(allocator, args);

Expand Down
6 changes: 4 additions & 2 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ fn parseArgs(allocator: std.mem.Allocator) !core.CoreParams {
\\ --stretched Resizes media to fit terminal window
\\-f, --frame_rate <f32> Target frame rate for video output (default: matches input fps)
\\-d, --dither <str> Dithering, supported values: "floydstein" (default: "floydstein")
\\ --fg <str> Enter a hex value like "#ffffff" for the foreground color (default: "#d36a6f")
\\ --bg <str> Enter a hex value like "#000000" for the background color (default: "#15091b")
\\ --fg <str> Enter a 6-digit hex value like "#ffffff" for the foreground color (default: "#d36a6f")
\\ --bg <str> Enter a 6-digit hex value like "#000000" for the background color (default: "#15091b")
\\ --transparent_bg Set the background to transparent
\\<str>...
);

Expand Down Expand Up @@ -160,6 +161,7 @@ fn parseArgs(allocator: std.mem.Allocator) !core.CoreParams {
.dither = dither,
.fg_color = fg_color,
.bg_color = bg_color,
.transparent_bg = res.args.transparent_bg != 0,
};
}

Expand Down
1 change: 1 addition & 0 deletions src/tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ test "text" {
.bg_color = null,
.fg_color = null,
.threshold_disabled = false,
.transparent_bg = false,
};

const ascii_txt = try image.generateAsciiTxt(allocator, img, null, args);
Expand Down