Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revisit and revise dithered rainbow rasters. #2011

Open
tatarize opened this issue Jul 28, 2023 · 3 comments
Open

Revisit and revise dithered rainbow rasters. #2011

tatarize opened this issue Jul 28, 2023 · 3 comments

Comments

@tatarize
Copy link
Member

cherries
363817366_10224374928140668_2560984528372720421_n

@tatarize
Copy link
Member Author

cherries2
cherries-planting-growing-harvesting

@tatarize
Copy link
Member Author

cherries-final

@tatarize
Copy link
Member Author

cherries-steinberg

from PIL import Image

# Fixed palette of seven RGB colors in #RRGGBB string format
palette = [
    "#dfddce",
    "#81857d",
    "#b3a367",
    "#a7695d",
    "#895377",
    "#52657f",
    "#697e7a",
]

def hex_to_rgb(hex_color):
    # Convert the #RRGGBB string to RGB tuple (R, G, B)
    hex_color = hex_color.lstrip("#")
    return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))

def find_closest_color(rgb):
    # Calculate the squared distance between the given RGB color and each color in the palette
    return min(palette, key=lambda c: sum((a - b) ** 2 for a, b in zip(rgb, hex_to_rgb(c))))

def floyd_steinberg_dither(image):
    width, height = image.size
    for y in range(height):
        for x in range(width):
            old_pixel = image.getpixel((x, y))
            new_pixel = hex_to_rgb(find_closest_color(old_pixel))
            image.putpixel((x, y), new_pixel)

            # Calculate the quantization error
            quant_error = tuple(a - b for a, b in zip(old_pixel, new_pixel))

            # Distribute the error to neighboring pixels
            for dx, dy in [(1, 0), (-1, 1), (0, 1), (1, 1)]:
                if 0 <= x + dx < width and 0 <= y + dy < height:
                    neighbor_pixel = image.getpixel((x + dx, y + dy))
                    updated_neighbor = tuple(c + e * 3 // 16 for c, e in zip(neighbor_pixel, quant_error))
                    image.putpixel((x + dx, y + dy), updated_neighbor)

if __name__ == "__main__":
    input_image_path = "cherries.jpg"  # Replace with the path to your input image
    output_image_path = "cherries.png"  # Replace with the desired output path

    image = Image.open(input_image_path)
    floyd_steinberg_dither(image)
    image.save(output_image_path)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant