atanunq / viuer

Rust library for displaying images in the terminal.
MIT License
241 stars 43 forks source link

Images with transparency leak the transparency color into the borders even with 0 opacity. #43

Open i30817 opened 2 years ago

i30817 commented 2 years ago

For instance (you need to pip install pillow to run this):

#! /usr/bin/env python3

from PIL import Image
import subprocess, io, os

solid = Image.new('RGBA', (50,50), (0, 0, 0, 255))
t_red = Image.new('RGBA', (50,50), (255, 0, 0, 0))

combined = Image.new('RGBA', (100, 50))
combined.paste(solid, box=(0,0))
combined.paste(t_red, box=(solid.size[0],0))

with io.BytesIO() as f:
    combined.save(f, format='png')
    subprocess.run(['viu', '-t', '-'], input=f.getbuffer())
#if the terminal is small enough that the combined image fills the width this will show the border
size = os.get_terminal_size()
print('*'*int(size[0]/2))

I believe this is a of by one bug in printing transparent pixels. Sometimes the border appears 'darker' depending on size, and that's interpolation (probably on a odd total width and a small enough terminal width), but the red must not be interpolation because with a small enough terminal, the midpoint of the terminal width coincides with the last star, and with the end of the first image, and those stars stop before the red line.

FWIW chafa when it needs to 'interpolate' doesn't print a darker red line, but it does print some odd spikes ('-') at the border. Your solution is better +/- this bug.

This is on a terminal without kitty protocol or sixel support of course.