Zixel: simple sixel library and CLI application

This library/app allows you to display images right inside of your terminal using sixel format.

https://github.com/daredemo/zixel

Images are processed with zigimg library, therefore zixel has the same limitations as zigimg when opening image files. If the conversion fails, try to convert the image to PNG first and try again.

5 Likes

Couple of quick fixes and new features:

  • RGBA is automatically converted to RGB
  • Use scale factor in addition to width and height of output

FIX: RGBA resulted in “broken” output

Exact pixel size is not always important when quickly displaying an image. In such cases a scale factor can be used.

1 Like

Very nice! Have you considered exposing this as a library or upstreaming the encoder into zigimg? Have you benchmarked vs chafa or libsixel?

I get a lot of requests for sixels in libvaxis, but haven’t done any work on it yet - having a zig sixel library is a great first step towards adding it!

EDIT: Oh, it is a library already!

3 Likes

Just a couple of (opinionated) thoughts on the library API:

  1. Accept a std.io.AnyWriter for any function that writes
  2. Have a few different options of where in the pipeline the image is coming from (IE a filepath, a slice of bytes we already read, an already decoded zigimg object)
3 Likes

Good points. I have planned to re-write the writer part. Just will take some time to fix it :smiley:

I’m also making my simple text UI library and the zixel library will go in there as well (as an optional add-on).

To be honest, this has been mainly a “learning-by-doing” process. I’m still struggling with many zig basic concepts :smiley:

I have not focused on speed (yet).

If you have ideas how to improve this lib, let me know. Having someone to discuss the stuff would also motivate me to keep working on it.

1 Like

There are several things that I already would like to change… just have to make some list of priorities.

For example, the zigimg quantize method gives me really bad results when using less than 128 colors.

I would suggest a variation: use a writer: anytype parameter which respects the calling conventions of AnyWriter. Meaning that the functions which take the writer parameter, treat that argument as though it’s an AnyWriter, calling only those functions using compatible types and so on.

I’ve had occasion to make wrapped “writer” types which offer additional functions, and pass through the standard collection to the underlying type. So leaving the writer’s type completely generic is a useful affordance to preserve in library code.

In the event that only an AnyWriter actually gets provided, the outcome is equivalent, Zig will only specialize the generic function once for that type. So it’s more flexible, with the only cost being that you don’t get IDE completion from ZLS while writing the functions which take it.

Very cool library @daredemo! I was looking for something exactly like this not long ago.

4 Likes

I’m in the process of re-writing it and I indeed chose the anytype route.

1 Like

Pushed an update with more generic writer using the anytype.

1 Like

Pushed a new version that is more “generic”.

Now the sixelMaker accepts zigimg object. It is up to the user to open the file, scale the file, etc. The main.zig provides examples how to do all of those things. Scaling, etc have separated into functions.

1 Like

Added basic support for alpha channels. Not yet happy how it works. Sixels should be able to have transparency, i.e., show the terminal as background. But it shows black right now. I’m not 100% sure why.