import numpy as np
from PIL import Image
# --- CONFIGURATION ---
IMAGE_SIZE = 4096
TOTAL_COLORS = IMAGE_SIZE * IMAGE_SIZE
RULE = 101 # Wolfram's CA Rule
SEED_ROW_CENTER = 1
# --- STEP 1: Generate All 24-bit RGB Colors ---
def generate_rgb_colors():
colors = np.arange(TOTAL_COLORS, dtype=np.uint32)
r = (colors >> 16) & 0xFF
g = (colors >> 8) & 0xFF
b = colors & 0xFF
return np.stack([r, g, b], axis=1).astype(np.uint8)
# --- STEP 2: Generate CA Binary Mask (0 or 1 for each pixel) ---
def generate_ca_binary_mask(rule, size):
rule_bin = np.array([int(b) for b in np.binary_repr(rule, width=8)], dtype=np.uint8)
ca = np.zeros((size, size), dtype=np.uint8)
ca[0, size // 2] = SEED_ROW_CENTER
for y in range(1, size):
left = np.roll(ca[y - 1], 1)
center = ca[y - 1]
right = np.roll(ca[y - 1], -1)
pattern = (left << 2) | (center << 1) | right
ca[y] = rule_bin[7 - pattern]
return ca
# --- STEP 3: Measure Number of 0s and 1s in CA ---
def count_dark_light_pixels(ca_mask):
num_light = np.count_nonzero(ca_mask) # CA=1
num_dark = TOTAL_COLORS - num_light # CA=0
return num_dark, num_light
# --- STEP 4: Split Colors by Luminance, Then Shuffle ---
def split_and_shuffle_colors(colors, num_dark, num_light):
def luminance(c):
r, g, b = c / 255.0
return 0.2126 * r + 0.7152 * g + 0.0722 * b
lums = np.array([luminance(c) for c in colors])
sorted_indices = np.argsort(lums)
# Take the lowest luminance for dark, highest for light
dark_indices = sorted_indices[:num_dark]
light_indices = sorted_indices[num_dark:]
dark_colors = colors[dark_indices]
light_colors = colors[light_indices]
rng = np.random.default_rng(42)
rng.shuffle(dark_colors)
rng.shuffle(light_colors)
return dark_colors, light_colors
# --- STEP 5: Assign Colors to Pixels Based on CA Mask ---
def assign_colors_by_ca(ca_mask, dark_colors, light_colors):
output = np.zeros((IMAGE_SIZE, IMAGE_SIZE, 3), dtype=np.uint8)
dark_idx = 0
light_idx = 0
for y in range(IMAGE_SIZE):
for x in range(IMAGE_SIZE):
if ca_mask[y, x] == 0:
output[y, x] = dark_colors[dark_idx]
dark_idx += 1
else:
output[y, x] = light_colors[light_idx]
light_idx += 1
return output
# --- MAIN EXECUTION ---
if __name__ == "__main__":
print("Generating RGB colors...")
all_colors = generate_rgb_colors()
print("Generating cellular automaton (Rule {})...".format(RULE))
ca_mask = generate_ca_binary_mask(RULE, IMAGE_SIZE)
print("Counting dark/light CA pixels...")
num_dark, num_light = count_dark_light_pixels(ca_mask)
print("Splitting and shuffling colors...")
dark_colors, light_colors = split_and_shuffle_colors(all_colors, num_dark, num_light)
print("Assigning colors to image...")
image = assign_colors_by_ca(ca_mask, dark_colors, light_colors)
print("Saving image...")
Image.fromarray(image, mode='RGB').save("rgb_ca_shuffled_by_luminance_split.png")
print("Done! Saved as 'rgb_ca_shuffled_by_luminance_split.png'"