Esempio n. 1
0
def output_sixel(data, im, tw, th):
    from libsixel import sixel_dither_initialize, sixel_dither_set_palette, sixel_dither_new, SIXEL_BUILTIN_G8, SIXEL_BUILTIN_G1, SIXEL_PIXELFORMAT_RGB888, SIXEL_PIXELFORMAT_RGBA8888, sixel_encode, sixel_dither_unref, sixel_output_new, sixel_dither_get, sixel_dither_set_pixelformat, SIXEL_PIXELFORMAT_PAL8, SIXEL_PIXELFORMAT_G8, SIXEL_PIXELFORMAT_G1
    s = BytesIO()
    if im.mode == 'P':
        im2 = im.convert('RGB')
        im = im2

    im.thumbnail(size=(tw, th), resample=Image.LANCZOS)
    data = im.tobytes()
    output = sixel_output_new(lambda data, s : s.write(data), s)


    if im.mode == 'RGB':
        dither = sixel_dither_new(256)
        sixel_dither_initialize(dither, data, tw, th, SIXEL_PIXELFORMAT_RGB888)
    elif im.mode == 'RGBA':
        dither = sixel_dither_new(256)
        sixel_dither_initialize(dither, data, tw, th, SIXEL_PIXELFORMAT_RGBA8888)

    elif im.mode == 'P':
        print("Its broken")
        sys.exit(1)
        palette = im.getpalette()
        print(">>", type(palette), "<<")
        dither = sixel_dither_new(256)
        print(">>", type(dither), "<< ")
        sixel_dither_set_palette(dither, palette)
        sixel_dither_set_pixelformat(dither, SIXEL_PIXELFORMAT_PAL8)
    elif im.mode == 'L':
        dither = sixel_dither_get(SIXEL_BUILTIN_G8)
        sixel_dither_set_pixelformat(dither, SIXEL_PIXELFORMAT_G8)
    elif im.mode == '1':
        dither = sixel_dither_get(SIXEL_BUILTIN_G1)
        sixel_dither_set_pixelformat(dither, SIXEL_PIXELFORMAT_G1)
    sixel_encode(data, tw, th, 1, dither, output)
    print(s.getvalue().decode('ascii'))
    sixel_dither_unref(dither)
Esempio n. 2
0
def display_in_terminal(obj):
    """ Convert and display an output tensor from BigGAN in the terminal.
        This function use `libsixel` and will only work in a libsixel-compatible terminal.
        Please refer to https://github.com/saitoha/libsixel for more details.

        Params:
            obj: tensor or numpy array of shape (batch_size, channels, height, width)
            file_name: path and beggingin of filename to save.
                Images will be saved as `file_name_{image_number}.png`
    """
    try:
        import PIL
        from libsixel import (sixel_output_new, sixel_dither_new,
                              sixel_dither_initialize,
                              sixel_dither_set_palette,
                              sixel_dither_set_pixelformat, sixel_dither_get,
                              sixel_encode, sixel_dither_unref,
                              sixel_output_unref, SIXEL_PIXELFORMAT_RGBA8888,
                              SIXEL_PIXELFORMAT_RGB888, SIXEL_PIXELFORMAT_PAL8,
                              SIXEL_PIXELFORMAT_G8, SIXEL_PIXELFORMAT_G1)
    except ImportError:
        raise ImportError(
            "Display in Terminal requires Pillow, libsixel "
            "and a libsixel compatible terminal. "
            "Please read info at https://github.com/saitoha/libsixel "
            "and install with pip install Pillow libsixel-python")

    s = BytesIO()

    images = convert_to_images(obj)
    widths, heights = zip(*(i.size for i in images))

    output_width = sum(widths)
    output_height = max(heights)

    output_image = PIL.Image.new('RGB', (output_width, output_height))

    x_offset = 0
    for im in images:
        output_image.paste(im, (x_offset, 0))
        x_offset += im.size[0]

    try:
        data = output_image.tobytes()
    except NotImplementedError:
        data = output_image.tostring()
    output = sixel_output_new(lambda data, s: s.write(data), s)

    try:
        if output_image.mode == 'RGBA':
            dither = sixel_dither_new(256)
            sixel_dither_initialize(dither, data, output_width, output_height,
                                    SIXEL_PIXELFORMAT_RGBA8888)
        elif output_image.mode == 'RGB':
            dither = sixel_dither_new(256)
            sixel_dither_initialize(dither, data, output_width, output_height,
                                    SIXEL_PIXELFORMAT_RGB888)
        elif output_image.mode == 'P':
            palette = output_image.getpalette()
            dither = sixel_dither_new(256)
            sixel_dither_set_palette(dither, palette)
            sixel_dither_set_pixelformat(dither, SIXEL_PIXELFORMAT_PAL8)
        elif output_image.mode == 'L':
            dither = sixel_dither_get(SIXEL_BUILTIN_G8)
            sixel_dither_set_pixelformat(dither, SIXEL_PIXELFORMAT_G8)
        elif output_image.mode == '1':
            dither = sixel_dither_get(SIXEL_BUILTIN_G1)
            sixel_dither_set_pixelformat(dither, SIXEL_PIXELFORMAT_G1)
        else:
            raise RuntimeError('unexpected output_image mode')
        try:
            sixel_encode(data, output_width, output_height, 1, dither, output)
            print(s.getvalue().decode('ascii'))
        finally:
            sixel_dither_unref(dither)
    finally:
        sixel_output_unref(output)
Esempio n. 3
0
def image_to_display(path, start=None, length=None):
    """
    Display an image
    """
    rows, columns = os.popen('stty size', 'r').read().split()
    if not start:
        start = c['IMAGE_SHIFT']
    if not length:
        length = int(columns) - 2 * start
    i = Image.open(path)
    i = i.convert('RGBA')
    w, h = i.size
    i.load()
    width = min(w, length)
    height = int(float(h) * (float(width) / float(w)))

    if c['IMAGE_RESIZE_TO_FIT'] is True:
        # If it image won't fit in the terminal without scrolling shrink it
        # Subtract 3 from rows so the tweet message fits in too.
        h = 2 * (int(rows) - 3)
        if height >= h:
            width = int(float(width) * (float(h) / float(height)))
            height = h
    if (height <= 0) or (width <= 0):
        raise ValueError("image has negative dimensions")

    height = min(height, c['IMAGE_MAX_HEIGHT'])

    # Sixel
    if c['IMAGE_ON_TERM'] == 'sixel':
        import fcntl, struct, termios
        from io import BytesIO
        from libsixel import sixel_dither_new, sixel_dither_initialize, sixel_encode, sixel_output_new, SIXEL_PIXELFORMAT_RGBA8888
        from resizeimage import resizeimage

        # FIXME: rows and columns are gotten a second time. Maybe use this at 
        # the begining of function instead of the call to stty size
        farg = struct.pack("HHHH", 0, 0, 0, 0)
        fd_stdout = sys.stdout.fileno()
        fretint = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, farg)
        rows, columns, xpixels, ypixels = struct.unpack("HHHH", fretint)
        max_width_pixels = width * (xpixels // columns)
        max_height_pixels = height * (ypixels // rows)

        # FIXME: This way is preferable to avoid an addition dependency, but it doesn't work correctly
        # i = i.resize((max_width_pixels, max_height_pixels), Image.ANTIALIAS)
        i = resizeimage.resize_thumbnail(i, [max_width_pixels, max_height_pixels])

        sixel = BytesIO()
        dither = sixel_dither_new(256)
        sixel_dither_initialize(dither, i.tobytes(), i.width, i.height, SIXEL_PIXELFORMAT_RGBA8888)
        sixel_encode(i.tobytes(), i.width, i.height, 1, dither, 
                sixel_output_new(lambda imgdata, sixel: sixel.write(imgdata), sixel))
        sys.stdout.write('%s%s' % (' ' * start, sixel.getvalue().decode('ascii')))

    # SGR
    else:
        i = i.resize((width, height), Image.ANTIALIAS)

        for real_y in xrange(height // 2):
            sys.stdout.write(' ' * start)
            for x in xrange(width):
                y = real_y * 2
                p0 = i.getpixel((x, y))
                p1 = i.getpixel((x, y + 1))
                block_print(p1, p0)
            sys.stdout.write('\n')