Pixdither Today
One of the most popular and "natural-looking" algorithms, it diffuses error among neighboring pixels, creating organic, noisy gradients.
# Create output image output_img = Image.fromarray(output_pixels, 'RGB') pixdither
: Allows users to import custom color swatches using Adobe's .ase file format via the open-source libase library. User Experience and Performance One of the most popular and "natural-looking" algorithms,
parser.add_argument('input', help='Input image path') parser.add_argument('-o', '--output', help='Output image path') parser.add_argument('-b', '--bits', type=int, default=1, help='Bits per channel (1-8, default: 1)') parser.add_argument('-p', '--palette', choices=['monochrome', 'grayscale', 'rgb'], default='monochrome', help='Color palette type (default: monochrome)') parser.add_argument('-a', '--algorithm', choices=['floyd-steinberg', 'atkinson', 'none'], default='floyd-steinberg', help='Dithering algorithm (default: floyd-steinberg)') parser.add_argument('--gif', help='Create animated dithering GIF (provide output path)') it diffuses error among neighboring pixels
def floyd_steinberg(self): """Apply Floyd-Steinberg dithering""" result = self.pixels.copy()
for y in range(self.height): for x in range(self.width): old_pixel = result[y, x].copy() new_pixel = self.quantize_color(old_pixel) result[y, x] = new_pixel
def process(self): """Process the image with selected algorithm""" print(f"Processing: {self.image_path.name}") print(f" Size: {self.width}x{self.height}") print(f" Palette: {self.palette_type}") print(f" Bits per channel: {self.bits}") print(f" Algorithm: {self.algorithm}")