#!python # -*- mode: python; Encoding: utf-8; coding: utf-8 -*- # Last updated: <2022/06/19 23:18:39 +0900> """ Ordered dithering Windows10 x64 21H2 + Python 3.9.13 64bit + Pillow 9.1.1 """ from PIL import Image odtbl2x2 = [ [1, 3], [4, 2] ] odtbl3x3 = [ [3, 7, 4], [6, 1, 9], [2, 8, 5] ] # odtbl3x3 = [ # [7, 9, 5], # [2, 1, 4], # [6, 3, 8] # ] odtbl4x4 = [ [1, 9, 3, 11], [13, 5, 15, 7], [4, 12, 2, 10], [16, 8, 14, 6] ] odtbl8x8 = [ [1, 33, 9, 41, 3, 35, 11, 43], [49, 17, 57, 25, 51, 19, 59, 27], [13, 45, 5, 37, 15, 47, 7, 39], [61, 29, 53, 21, 63, 31, 55, 23], [4, 36, 12, 44, 2, 34, 10, 42], [52, 20, 60, 28, 50, 18, 58, 26], [16, 48, 8, 40, 14, 46, 6, 38], [64, 32, 56, 24, 62, 30, 54, 22] ] odtbls = { "2x2": [5, odtbl2x2], "3x3": [10, odtbl3x3], "4x4": [17, odtbl4x4], "8x8": [65, odtbl8x8] } def get_dither_table(odtype): d, tbl = odtbls[odtype] w = len(tbl[0]) h = len(tbl) odtbl = [[0 for i in range(w)] for j in range(h)] for y in range(h): for x in range(w): odtbl[y][x] = tbl[y][x] * 256 / d return w, h, odtbl def get_dither_image(odtype, im): width, height = im.size oim = Image.new("L", im.size) tw, th, od = get_dither_table(odtype) src_pixel = im.load() dst_pixel = oim.load() for y in range(height): dy = y % th for x in range(width): dx = x % tw if src_pixel[x, y] < od[dy][dx]: dst_pixel[x, y] = 0 else: dst_pixel[x, y] = 255 return oim def main(): # im = Image.open("mandrill.png").convert("L") im = Image.open("gradation.png") for odtype in ["2x2", "3x3", "4x4", "8x8"]: oim = get_dither_image(odtype, im) oim.save("output_dither_%s.png" % odtype) if __name__ == '__main__': main()