#A bare-bone ink-jet printer

1 messages Β· Page 1 of 1 (latest)

quick wing
#

A bare-bone ink-jet printer

#

in python, here a minimal test-bench

#
import copy

# The goal:
# We have a printer that can only print black and white squares, from an input image (a linear gradient) with
# many shades of gray, we need to reduce these colours to only white and black while still keeping a "feel" of
# the original gradient.
#
# input image:
# |      β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’|
# |    β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’|
# |  β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–’β–’|
# |β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’|
# |β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–“β–“|
# |β–‘β–‘β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–“β–“β–“β–“|
# |β–‘β–‘β–‘β–‘β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–“β–“β–“β–“β–“β–“|
# |β–‘β–‘β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–“β–“β–“β–“β–“β–“β–“β–“|
# |β–’β–’β–’β–’β–’β–’β–’β–’β–’β–’β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“|
# |β–’β–’β–’β–’β–’β–’β–’β–’β–“β–“β–“β–“β–“β–“β–“β–“β–“β–“β–ˆβ–ˆ|
#
# output image: (goal)
# |           β–ˆ      β–ˆ |
# |               β–ˆ   β–ˆ|
# |       β–ˆ    β–ˆ β–ˆ  β–ˆ β–ˆ|
# |          β–ˆ    β–ˆ β–ˆ β–ˆ|
# |   β–ˆ     β–ˆ  β–ˆ β–ˆ  β–ˆβ–ˆβ–ˆ|
# |      β–ˆ    β–ˆ β–ˆ β–ˆβ–ˆβ–ˆ β–ˆ|
# |β–ˆ  β–ˆ    β–ˆ β–ˆ β–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆ|
# |      β–ˆ β–ˆ β–ˆ β–ˆ β–ˆ β–ˆβ–ˆβ–ˆβ–ˆ|
# |β–ˆ  β–ˆ β–ˆ  β–ˆ β–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆ|
# | β–ˆ β–ˆ β–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ|
# (pretty much, although I just hand-wrote it)
#
# This is called "dithering", a down-sampling strategy for colors, that conserves as best as it can the shades of the
# original image. There are various strategies to achieve that: unordered (floyd steinberg error diffusion algorithm),
# or ordered, such as here, with a threshold matrix which is an extension from the bayer's base matrix, which maximize
# the distance between two similar values in a matrix (eg: 2 and 3, 9 and 10...), also accounting for the wrap-around.
#
# I left it to you to implement a function that generates a Bayer's threshold matrix, whichever way you like best. The
# rest is pretty much there and finalized already.
# Without the bayer's matrix generator, the threshold is a mid-gray, which will rander our gradiant as a crude triangle.


edge_size = 10 # the base image is a square
#
# utilities
def print_2D_mat(mat):
    for i in range(len(mat)):
        for j in range(len(mat[0])):
            print(f'{mat[j][i]:03d}', end =", ")
        print() # end line

def discretize(val, min, max):
    tone_map = " β–‘β–’β–“β–ˆ"
    values_range = max-min
    return tone_map[round(((val-min)/values_range)*(len(tone_map)-1))]

def print_img(img, min, max):
    for i in range(len(base_image)):
        print('|', end = "")
        for j in range(len(base_image[0])):
            symbol = discretize(base_image[j][i], min, max)
            print(f'{symbol}{symbol}', end = "")
        print('|') # end line

#
#############################
# Generates the base image:

def init_mat(default_value, size):
    a = []
    b = []
    for k in range(0, size):
        b.append(default_value)
    for j in range(0, size):
        a.append(copy.deepcopy(b))
    return a

def apply_gradiant(matrix, min, max):
    for(i) in range(len(matrix)):
        for(j) in range(len(matrix[0])):
            matrix[j][i] = round(min+((i+j)*(max-min)/(len(matrix)*2)))
    return matrix

base_image = init_mat(0, edge_size)
apply_gradiant(base_image, 0, 100)

#display
print_2D_mat(base_image)
print_img(base_image, 0, 100)
#
######### task to work on:
def bayer_matrix(size, min, max):

    matrix = init_mat(round((max-min)/2), size) # blank:
                            # |0, 0|
                            # |0, 0|
    # TODO
    # Need to find how to implement it
    # cool resource-> https://blog.kaetemi.be/2015/04/01/practical-bayer-dithering/

    # Do some computing, potentially recursively...

    # with a size = 2,
    # matrix = |0, 2|
    #          |3, 1|
    # with a size = 4,
    # matrix = | 0,  8,  2, 10|
    #          |12,  4, 14,  6|
    #          | 3, 11,  1,  9|
    #          |15,  7, 13,  5|

    return matrix
#########


dithering_map_size = 16
dithering_threshold = bayer_matrix(dithering_map_size, 0, 100)
#
########################################
# finally I want to use the dithering bayer's threshold to dither the image to binary B&W (0 or 100% black only)

for i in range(edge_size):
    print('|', end='')
    for j in range(edge_size):
        base_image_pixel_value = base_image[j][i]
        j_in_dither_map = j%dithering_map_size
        i_in_dither_map = i%dithering_map_size
        dithering_map_threshold_value = dithering_threshold[j_in_dither_map][i_in_dither_map]
        if base_image_pixel_value > dithering_map_threshold_value:
            print("β–ˆβ–ˆ", end="")
        else:
            print("  ", end="")
    print('|') # end line