summaryrefslogtreecommitdiffstats
path: root/Third_Party
diff options
context:
space:
mode:
Diffstat (limited to 'Third_Party')
-rw-r--r--Third_Party/generate_recursive_dithering.py88
-rw-r--r--Third_Party/shift_image_to_corner.py97
2 files changed, 185 insertions, 0 deletions
diff --git a/Third_Party/generate_recursive_dithering.py b/Third_Party/generate_recursive_dithering.py
new file mode 100644
index 0000000..417647e
--- /dev/null
+++ b/Third_Party/generate_recursive_dithering.py
@@ -0,0 +1,88 @@
+import numpy as np
+from PIL import Image, ImageDraw
+import argparse
+import math
+
+from shift_image_to_corner import shift_to_corner
+
+def create_circle_image(res, radius, center=None):
+ """Create a binary image with a white circle on black background."""
+ if center is None:
+ center = (res/2, res/2)
+
+ img = Image.new('L', (res, res), 0)
+ draw = ImageDraw.Draw(img)
+
+ # Convert radius and center to pixels
+ r_px = int(radius * res)
+ cx, cy = int(center[0]), int(center[1])
+
+ # Draw white circle (255)
+ draw.ellipse([cx-r_px, cy-r_px, cx+r_px, cy+r_px], fill=255)
+ return img
+
+def main():
+ parser = argparse.ArgumentParser(description="Generate dot and circle images.")
+ parser.add_argument("--res", type=int, default=128, help="Resolution of the images.")
+ args = parser.parse_args()
+
+ res = args.res
+ goal_area = 0.1
+ # a = pi * r^2
+ # r = sqrt(a / pi)
+ initial_r = math.sqrt(goal_area / math.pi) * res # Start with a circle that fills 1/4 of the image
+
+ # Calculate areas and radii for each layer
+ initial_area = math.pi * (initial_r/res)**2
+
+ # Layer 1: Single circle in corner
+ r1 = math.sqrt(initial_area/1) * res # Calculate radius consistently with other layers
+ base_img = create_circle_image(res, r1/res)
+ corner_img = shift_to_corner(base_img)
+ corner_img.save("dots_L1.png")
+
+ # Layer 2: Two circles, split area
+ r2 = math.sqrt(initial_area/2) * res # New radius for each circle
+ # Create corner circle
+ corner_img = shift_to_corner(create_circle_image(res, r2/res))
+ # Create center circle
+ center_img = create_circle_image(res, r2/res)
+ # Combine images
+ layer2 = Image.fromarray(np.maximum(np.array(corner_img), np.array(center_img)))
+ layer2.save("dots_L2.png")
+
+ # Layer 3: Three circles
+ r3 = math.sqrt(initial_area/3) * res
+ # Create corner and center circles as before
+ corner_img = shift_to_corner(create_circle_image(res, r3/res))
+ center_img = create_circle_image(res, r3/res)
+ # Create top circle
+ top_img = shift_to_corner(create_circle_image(res, r3/res), shift_side=False)
+ # Combine images
+ layer3 = Image.fromarray(np.maximum.reduce([
+ np.array(corner_img),
+ np.array(center_img),
+ np.array(top_img)
+ ]))
+ layer3.save("dots_L3.png")
+
+ # Layer 4: Four circles
+ r4 = math.sqrt(initial_area/4) * res
+ # Create corner and center circles
+ corner_img = shift_to_corner(create_circle_image(res, r4/res))
+ center_img = create_circle_image(res, r4/res)
+ # Create top and right circles
+ top_img = shift_to_corner(create_circle_image(res, r4/res), shift_side=False)
+ right_img = shift_to_corner(create_circle_image(res, r4/res), shift_up=False)
+ # Combine images
+
+ layer4 = Image.fromarray(np.maximum.reduce([
+ np.array(corner_img),
+ np.array(center_img),
+ np.array(top_img),
+ np.array(right_img)
+ ]))
+ layer4.save("dots_L4.png")
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/Third_Party/shift_image_to_corner.py b/Third_Party/shift_image_to_corner.py
new file mode 100644
index 0000000..8f365a7
--- /dev/null
+++ b/Third_Party/shift_image_to_corner.py
@@ -0,0 +1,97 @@
+"""
+Shift image to corner, wrapping it toroidally.
+"""
+
+from PIL import Image
+import numpy as np
+import argparse
+import os
+
+def shift_to_corner(img, shift_side=True, shift_up=True):
+ """
+ Shifts an image to edges with toroidal wrapping based on specified directions.
+
+ Args:
+ img (PIL.Image): Input Pillow image
+ shift_side (bool): Whether to shift horizontally to the right edge
+ shift_up (bool): Whether to shift vertically to the top edge
+
+ Returns:
+ PIL.Image: Shifted image
+ """
+ # Convert image to numpy array
+ img_array = np.array(img)
+
+ # Get dimensions
+ height, width = img_array.shape[:2]
+ half_height = height // 2
+ half_width = width // 2
+
+ # Create new array for the shifted image
+ shifted = np.zeros_like(img_array)
+
+ if shift_side and shift_up:
+ # Original behavior - shift to upper right corner
+ shifted[half_height:, half_width:] = img_array[:half_height, :half_width] # Q1 -> BR
+ shifted[half_height:, :half_width] = img_array[:half_height, half_width:] # Q2 -> BL
+ shifted[:half_height, half_width:] = img_array[half_height:, :half_width] # Q3 -> TR
+ shifted[:half_height, :half_width] = img_array[half_height:, half_width:] # Q4 -> TL
+ elif shift_side:
+ # Only shift horizontally to right
+ shifted[:, half_width:] = img_array[:, :half_width] # Left half -> Right
+ shifted[:, :half_width] = img_array[:, half_width:] # Right half -> Left
+ elif shift_up:
+ # Only shift vertically to top
+ shifted[half_height:, :] = img_array[:half_height, :] # Top half -> Bottom
+ shifted[:half_height, :] = img_array[half_height:, :] # Bottom half -> Top
+ else:
+ # No shift, return original image
+ shifted = img_array.copy()
+
+ # Convert back to PIL Image and return
+ return Image.fromarray(shifted)
+
+def shift_to_corner_from_file(image_path, output_path, shift_side=True, shift_up=True):
+ """
+ Wrapper function that shifts an image file to edges with toroidal wrapping.
+
+ Args:
+ image_path (str): Path to the input image
+ output_path (str): Path where the shifted image will be saved
+ shift_side (bool): Whether to shift horizontally to the right edge
+ shift_up (bool): Whether to shift vertically to the top edge
+
+ Returns:
+ PIL.Image: Shifted image
+ """
+ img = Image.open(image_path)
+ result = shift_to_corner(img, shift_side=shift_side, shift_up=shift_up)
+ result.save(output_path)
+ return result
+
+def get_output_path(input_path):
+ """
+ Generate output path by adding '_shifted' before the file extension.
+
+ Args:
+ input_path (str): Path to the input image
+ Returns:
+ str: Path for the output image
+ """
+ base, ext = os.path.splitext(input_path)
+ return f"{base}_shifted{ext}"
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description='Shift an image to the corner with toroidal wrapping.')
+ parser.add_argument('input_image', help='Path to the input image file')
+ parser.add_argument('--no-side', action='store_false', dest='shift_side',
+ help='Disable horizontal shifting (default: enabled)')
+ parser.add_argument('--no-up', action='store_false', dest='shift_up',
+ help='Disable vertical shifting (default: enabled)')
+
+ args = parser.parse_args()
+ output_path = get_output_path(args.input_image)
+
+ shift_to_corner_from_file(args.input_image, output_path,
+ shift_side=args.shift_side,
+ shift_up=args.shift_up)