diff --git a/ImageFilters/ear.jpg b/ImageFilters/ear.jpg new file mode 100644 index 0000000..3ee58ee Binary files /dev/null and b/ImageFilters/ear.jpg differ diff --git a/ImageFilters/ear.png b/ImageFilters/ear.png new file mode 100644 index 0000000..e5aab4e Binary files /dev/null and b/ImageFilters/ear.png differ diff --git a/ImageFilters/imagefilters.py b/ImageFilters/imagefilters.py new file mode 100644 index 0000000..3b8e093 --- /dev/null +++ b/ImageFilters/imagefilters.py @@ -0,0 +1,97 @@ +import PIL.Image + +KERNEL_GAUSSIAN_BLUR = [ + [1, 2, 1], + [2, 3, 2], + [1, 2, 1], +] +KERNEL_EDGE_DETECTION_H = [ + [-2, 0, 2], + [-2, 0, 2], + [-2, 0, 2], +] +def index_to_xy(index, width): + (y, x) = divmod(index, width) + return (x, y) + +def xy_to_index(x, y, width): + return (y * width) + x + +def apply_filter(old_image, kernel): + kernel_height = len(kernel) + kernel_width = len(kernel[0]) + if (kernel_height % 2 != 1) or (kernel_width % 2 != 1): + raise ValueError('Kernel is not of odd size') + + if any(len(segment) != kernel_width for segment in kernel): + raise ValueError('Kernel is of inconsistent size') + + kernel_center = (kernel_width // 2, kernel_height // 2) + flat_kernel = list(flatten_list(kernel)) + lower = min(flat_kernel) + lower = min(0, lower * 255) + upper = max(flat_kernel) + upper = max(255, upper * 255) + print(lower, upper) + + (image_width, image_height) = old_image.size + old_pixels = old_image.getdata() + new_pixels = list(old_image.getdata()) + + for (index, old_pixel) in enumerate(old_pixels): + operation_sum = 0 + operation_denominator = 0 + (x, y) = index_to_xy(index, image_width) + #print(x, y, index) + for (kernel_y, kernel_row) in enumerate(kernel): + #print(kernel_row) + subject_y = y - (kernel_center[1] - kernel_y) + if subject_y < 0 or subject_y >= image_height: + continue + for (kernel_x, kernel_entry) in enumerate(kernel_row): + subject_x = x - (kernel_center[0] - kernel_x) + if subject_x < 0 or subject_x >= image_width: + continue + subject = old_pixels[xy_to_index(subject_x, subject_y, image_width)] + #print(x, y, subject_x, subject_y, kernel_entry, subject) + operation_sum += kernel_entry * subject + operation_denominator += kernel_entry + + operation_denominator = max(1, operation_denominator) + operation_avg = abs(operation_sum / operation_denominator) + #n_operation_avg = int(map_range(operation_avg, lower, upper, 0, 255)) + if index % 4096 == 0: + print(x, y, operation_sum, operation_denominator, operation_avg) + #print(y, '/', image_height) + new_pixels[index] = operation_avg + + #print(new_pixels) + new_image = PIL.Image.new('L', (old_image.size)) + new_image.putdata(new_pixels, 1, 0) + #print(new_pixels) + #print(list(new_image.getdata())) + return new_image + +def flatten_list(li): + for element in li: + if hasattr(element, '__iter__'): + yield from flatten_list(element) + else: + yield element + +def map_range(x, old_low, old_high, new_low, new_high): + ''' + Given a number x in range [old_low, old_high], return corresponding + number in range [new_low, new_high]. + ''' + if x > old_high or x < old_low: + raise ValueError('%d not in range [%d..%d]' % (x, old_low, old_high)) + percentage = (x - old_low) / (old_high - old_low) + y = (percentage * (new_high - new_low)) + new_low + return y + +if __name__ == '__main__': + i = PIL.Image.open('ear.jpg') + i = i.convert('L') + i = apply_filter(apply_filter(i, KERNEL_GAUSSIAN_BLUR), KERNEL_EDGE_DETECTION_H) + i.save('ear.png') \ No newline at end of file diff --git a/Minecraft3DVector/README.md b/Minecraft3DVector/README.md new file mode 100644 index 0000000..363f2c2 --- /dev/null +++ b/Minecraft3DVector/README.md @@ -0,0 +1,21 @@ +Minecraft 3D Vector +=================== + +Given one, two, or three square images, produce a 3-dimensional rendering of them as a block in glorious SVG. + +The svg has two layers. They contain identical shapes, but the lower one is slightly blurred. Although the shapes are aligned pretty well, some rendering engines create a 1px gap between shapes due to rounding. The blurred object helps fill these in. A mask is used to make sure the blur does not cause a halo around the edges. The seams still aren't perfect but they're pretty good, man. + +Because each pixel of each face produces two shapes, you should probably stick to small source images. + +##Usage: + + > mc3dvector.py dirt.png + Creates a block with dirt on all sides + + > mc3dvector.py tree_top.png tree_side.png + Creates a block with tree_top on the top, and tree_side on both sides. + + > mc3dvector.py dirt.png gravel.png obsidian.png + Creates a block with dirt on top, gravel on the left, and obsidian on the right. + +The images do not need to be the same size as each other, but they each must be square. \ No newline at end of file diff --git a/Minecraft3DVector/examples/rendering_furnace_2048.png b/Minecraft3DVector/examples/rendering_furnace_2048.png new file mode 100644 index 0000000..eddcb7c Binary files /dev/null and b/Minecraft3DVector/examples/rendering_furnace_2048.png differ diff --git a/Minecraft3DVector/examples/rendering_hellsand_1024.png b/Minecraft3DVector/examples/rendering_hellsand_1024.png new file mode 100644 index 0000000..003973d Binary files /dev/null and b/Minecraft3DVector/examples/rendering_hellsand_1024.png differ diff --git a/Minecraft3DVector/examples/rendering_minecraft_2048.png b/Minecraft3DVector/examples/rendering_minecraft_2048.png new file mode 100644 index 0000000..a95c29c Binary files /dev/null and b/Minecraft3DVector/examples/rendering_minecraft_2048.png differ diff --git a/Minecraft3DVector/examples/rendering_obsidian_1024.png b/Minecraft3DVector/examples/rendering_obsidian_1024.png new file mode 100644 index 0000000..7b2ac8d Binary files /dev/null and b/Minecraft3DVector/examples/rendering_obsidian_1024.png differ diff --git a/Minecraft3DVector/examples/rendering_tree_1024.png b/Minecraft3DVector/examples/rendering_tree_1024.png new file mode 100644 index 0000000..f39914f Binary files /dev/null and b/Minecraft3DVector/examples/rendering_tree_1024.png differ diff --git a/Minecraft3DVector/examples/source_furnace_left.png b/Minecraft3DVector/examples/source_furnace_left.png new file mode 100644 index 0000000..92c89f3 Binary files /dev/null and b/Minecraft3DVector/examples/source_furnace_left.png differ diff --git a/Minecraft3DVector/examples/source_furnace_right.png b/Minecraft3DVector/examples/source_furnace_right.png new file mode 100644 index 0000000..115f73d Binary files /dev/null and b/Minecraft3DVector/examples/source_furnace_right.png differ diff --git a/Minecraft3DVector/examples/source_furnace_top.png b/Minecraft3DVector/examples/source_furnace_top.png new file mode 100644 index 0000000..a3a5a08 Binary files /dev/null and b/Minecraft3DVector/examples/source_furnace_top.png differ diff --git a/Minecraft3DVector/examples/source_hellsand.png b/Minecraft3DVector/examples/source_hellsand.png new file mode 100644 index 0000000..fca7e8f Binary files /dev/null and b/Minecraft3DVector/examples/source_hellsand.png differ diff --git a/Minecraft3DVector/examples/source_minecraft_left.png b/Minecraft3DVector/examples/source_minecraft_left.png new file mode 100644 index 0000000..f703584 Binary files /dev/null and b/Minecraft3DVector/examples/source_minecraft_left.png differ diff --git a/Minecraft3DVector/examples/source_minecraft_right.png b/Minecraft3DVector/examples/source_minecraft_right.png new file mode 100644 index 0000000..5456138 Binary files /dev/null and b/Minecraft3DVector/examples/source_minecraft_right.png differ diff --git a/Minecraft3DVector/examples/source_minecraft_top.png b/Minecraft3DVector/examples/source_minecraft_top.png new file mode 100644 index 0000000..245e68b Binary files /dev/null and b/Minecraft3DVector/examples/source_minecraft_top.png differ diff --git a/Minecraft3DVector/examples/source_obsidian.png b/Minecraft3DVector/examples/source_obsidian.png new file mode 100644 index 0000000..ff0a683 Binary files /dev/null and b/Minecraft3DVector/examples/source_obsidian.png differ diff --git a/Minecraft3DVector/examples/source_tree_side.png b/Minecraft3DVector/examples/source_tree_side.png new file mode 100644 index 0000000..914cb5f Binary files /dev/null and b/Minecraft3DVector/examples/source_tree_side.png differ diff --git a/Minecraft3DVector/examples/source_tree_top.png b/Minecraft3DVector/examples/source_tree_top.png new file mode 100644 index 0000000..7a44e77 Binary files /dev/null and b/Minecraft3DVector/examples/source_tree_top.png differ diff --git a/Minecraft3DVector/examples/svg_furnace.svg b/Minecraft3DVector/examples/svg_furnace.svg new file mode 100644 index 0000000..ad213f5 --- /dev/null +++ b/Minecraft3DVector/examples/svg_furnace.svg @@ -0,0 +1,9319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Minecraft3DVector/examples/svg_hellsand.svg b/Minecraft3DVector/examples/svg_hellsand.svg new file mode 100644 index 0000000..855e6e8 --- /dev/null +++ b/Minecraft3DVector/examples/svg_hellsand.svg @@ -0,0 +1,9319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Minecraft3DVector/examples/svg_minecraft.svg b/Minecraft3DVector/examples/svg_minecraft.svg new file mode 100644 index 0000000..11dde3a --- /dev/null +++ b/Minecraft3DVector/examples/svg_minecraft.svg @@ -0,0 +1,9319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Minecraft3DVector/examples/svg_obsidian.svg b/Minecraft3DVector/examples/svg_obsidian.svg new file mode 100644 index 0000000..cf8090e --- /dev/null +++ b/Minecraft3DVector/examples/svg_obsidian.svg @@ -0,0 +1,9319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Minecraft3DVector/examples/svg_tree.svg b/Minecraft3DVector/examples/svg_tree.svg new file mode 100644 index 0000000..101f1a6 --- /dev/null +++ b/Minecraft3DVector/examples/svg_tree.svg @@ -0,0 +1,9319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Minecraft3DVector/mc3dvector.py b/Minecraft3DVector/mc3dvector.py new file mode 100644 index 0000000..0cfaf4c --- /dev/null +++ b/Minecraft3DVector/mc3dvector.py @@ -0,0 +1,200 @@ +TEMPLATE_PRIMARY = ''' + + + + + + + + + + + + + + + + + + {elements_top} + + + {elements_left} + + + {elements_right} + + + + + {elements_top} + + + {elements_left} + + + {elements_right} + + + + +''' +TEMPLATE_PIXEL = ''' + +''' +import os +import PIL.Image +import random +import sys + +# These numbers are MAGIC, and only work because of how the template was made. +SQUARE_WIDTH = 300 +START_X = 194.94924 +START_Y = 637.82417 + +def hexadecimal(i): + i = hex(i)[2:] + width = 2 - (len(i) % 2) + if width == 2: width = 0 + i = ('0'*width) + i + return i + +def mirror(image, direction): + new_image = image.copy() + for y in range(image.size[1]): + for x in range(image.size[0]): + pixel = image.getpixel((x, y)) + if direction == 'horizontal': + x = (image.size[0] - 1) - x + elif direction == 'vertical': + y = (image.size[1] - 1) - y + new_image.putpixel((x, y), pixel) + return new_image + + +def vectorize(filenames): + images = [PIL.Image.open(f) for f in filenames] + if len(images) == 1: + images = [images[0], images[0], images[0]] + elif len(images) == 2: + images = [images[0], images[1], images[1]] + elif len(images) == 3: + pass + else: + raise ValueError('Invalid number of images supplied') + + images[0] = images[0].rotate(270) + images[2] = mirror(images[2], 'horizontal') + elements_total = [] + for (image_index, image) in enumerate(images): + elements_local = [] + width = image.size[0] + step = SQUARE_WIDTH / width + pixsize = SQUARE_WIDTH / width + for y in range(width): + y_point = START_Y + (y * step) + for x in range(width): + x_point = START_X + (x * step) + color = image.getpixel((x, y)) + + opacity = 1 + if isinstance(color, int): + color = hexadecimal(color) * 3 + elif isinstance(color, tuple): + if len(color) == 4: + opacity = color[3] / 255 + if len(color) >= 3: + color = ''.join(hexadecimal(channel) for channel in color[:3]) + + element = TEMPLATE_PIXEL.format( + x=x_point, + y=y_point, + opacity=opacity, + pixsize=pixsize, + color=color, + id='face_%d_%d' % (image_index, x + (y*width))) + elements_local.append(element) + elements_total.append(elements_local) + + elements_total = [''.join(elements) for elements in elements_total] + image = TEMPLATE_PRIMARY.format(elements_top=elements_total[0], elements_right=elements_total[1], elements_left=elements_total[2]) + image = image.strip() + + basenames = [os.path.splitext(f)[0] for f in filenames] + outputname = '+'.join(basenames) + '.svg' + print(outputname) + f = open(outputname, 'w') + f.write(image) + f.close() + +if __name__ == '__main__': + filenames = sys.argv[1:] + vectorize(filenames) \ No newline at end of file diff --git a/OpenDirDL/opendirdl.py b/OpenDirDL/opendirdl.py index 458a3bc..9078dca 100644 --- a/OpenDirDL/opendirdl.py +++ b/OpenDirDL/opendirdl.py @@ -1,87 +1,107 @@ -''' +DOCSTRING=''' OpenDirDL downloads open directories -Usage: +The basics: +1. Create a database of the directory's files with + > opendirdl digest http://website.com/directory/ +2. Enable and disable the files you are interested in with + > opendirdl remove_pattern ".*" + > opendirdl keep_pattern "Daft%20Punk" + > opendirdl remove_pattern "folder\.jpg" + Note the percent-encoded string. +3. Download the enabled files with + > opendirdl download database.db -DIGEST: +Specifics: + +digest: Recursively fetch directories and build a database of file URLs. - > opendirdl digest !clipboard > opendirdl digest http://website.com/directory/ + > opendirdl digest !clipboard flags: -f | --fullscan: - When included, perform HEAD requests on all files, to know the size of the entire directory. + When included, perform HEAD requests on all files, to know the size of + the entire directory. -db "x.db" | --databasename "x.db": - Use a custom database filename. By default, databases are named after the web domain. + Use a custom database filename. By default, databases are named after + the web domain. -DOWNLOAD: - Download the files whose URLs are enabled in the database. +download: + Download the files whose URLs are Enabled in the database. > opendirdl download website.com.db flags: -o "x" | --outputdir "x": - Save the files to a custom directory, "x". By default, files are saved to a folder named - after the web domain. + Save the files to a custom directory, "x". By default, files are saved + to a folder named after the web domain. -ow | --overwrite: - When included, download and overwrite files even if they already exist in the output directory. + When included, download and overwrite files even if they already exist + in the output directory. -bps 100 | --bytespersecond 100: - Ratelimit yourself to downloading at 100 BYTES per second. The webmaster will appreciate this. + Ratelimit yourself to downloading at 100 BYTES per second. + The webmaster will appreciate this. -KEEP_PATTERN: - Enable URLs which match a regex pattern. Matches are based on the percent-encoded strings! +keep_pattern: + Enable URLs which match a regex pattern. Matches are based on the percent- + encoded strings! - > opendirdl keep_pattern website.com.db ".*" + > opendirdl keep_pattern database.db ".*" -REMOVE_PATTERN: - Disable URLs which match a regex pattern. Matches are based on the percent-encoded strings! +remove_pattern: + Disable URLs which match a regex pattern. Matches are based on the percent- + encoded strings! - > opendirdl remove_pattern website.com.db ".*" + > opendirdl remove_pattern database.db ".*" -LIST_BASENAMES: - List enabled URLs in order of their base filename. This makes it easier to find titles of - interest in a directory that is very scattered or poorly organized. +list_basenames: + List enabled URLs in order of their base filename. This makes it easier to + find titles of interest in a directory that is very scattered or poorly + organized. > opendirdl list_basenames website.com.db flags: -o "x.txt" | --outputfile "x.txt": - Output the results to a file instead of stdout. This is useful if the filenames contain - special characters that crash Python, or are so long that the console becomes unreadable. + Output the results to a file instead of stdout. This is useful if the + filenames contain special characters that crash Python, or are so long + that the console becomes unreadable. -MEASURE: - Sum up the filesizes of all enabled URLs. +measure: + Sum up the filesizes of all Enabled URLs. - > opendirdl measure website.com.db + > opendirdl measure database.db flags: -f | --fullscan: - When included, perform HEAD requests on any URL whose size is not known. If this flag is - not included, and some file's size is unkown, you will receive a printed note. + When included, perform HEAD requests when a file's size is not known. + If this flag is not included, and some file's size is unkown, you will + receive a printed note. ''' -# Module names preceeded by two hashes indicate modules that are imported during + +# Module names preceeded by `## ~` indicate modules that are imported during # a function, because they are not used anywhere else and we don't need to waste # time importing them usually. - import sys sys.path.append('C:\\git\\else\\ratelimiter'); import ratelimiter import argparse -## import bs4 -## import hashlib +## ~import bs4 +## ~import hashlib import os -## import re +## ~import re import requests import shutil import sqlite3 -## tkinter +## ~tkinter import urllib.parse FILENAME_BADCHARS = '/\\:*?"<>|' @@ -249,6 +269,7 @@ class Walker: databasename = databasename.replace(':', '') self.databasename = databasename + safeprint('Opening %s' % self.databasename) self.sql = sqlite3.connect(self.databasename) self.cur = self.sql.cursor() db_init(self.sql, self.cur) @@ -269,7 +290,7 @@ class Walker: External links, index sort links, and desktop.ini are discarded. ''' import bs4 - soup = bs4.BeautifulSoup(response.text) + soup = bs4.BeautifulSoup(response.text, 'html.parser') elements = soup.findAll(tag) for element in elements: try: @@ -615,10 +636,10 @@ def filter_pattern(databasename, regex, action='keep', *trash): should_keep = (keep and contains) if keep and contains and not current_do_dl: - safeprint('Keeping "%s"' % url) + safeprint('Enabling "%s"' % url) cur.execute('UPDATE urls SET do_download = 1 WHERE url == ?', [url]) if remove and contains and current_do_dl: - safeprint('Removing "%s"' % url) + safeprint('Disabling "%s"' % url) cur.execute('UPDATE urls SET do_download = 0 WHERE url == ?', [url]) sql.commit() @@ -735,6 +756,9 @@ def remove_pattern(args): if __name__ == '__main__': + if listget(sys.argv, 1, '').lower() in ('help', '-h', '--help'): + print(DOCSTRING) + quit() parser = argparse.ArgumentParser() subparsers = parser.add_subparsers() @@ -758,7 +782,7 @@ if __name__ == '__main__': p_list_basenames = subparsers.add_parser('list_basenames') p_list_basenames.add_argument('databasename') - p_list_basenames.add_argument('-o', '--outputfile', dest='outputfile', default=None) + p_list_basenames.add_argument('outputfile', nargs='?', default=None) p_list_basenames.set_defaults(func=list_basenames) p_measure = subparsers.add_parser('measure') diff --git a/RateMeter/README.md b/RateMeter/README.md new file mode 100644 index 0000000..37269f5 --- /dev/null +++ b/RateMeter/README.md @@ -0,0 +1,4 @@ +RateMeter +========= + +Provides a `RateMeter` class to measure the speed of something. Create an instance with the appropriate `span`, and call `meter.digest(x)` where `x` is the number of units processed. Later, call `meter.report()` to receive the current speed information. \ No newline at end of file diff --git a/RateMeter/ratemeter.py b/RateMeter/ratemeter.py index 4abbb25..4b4b58d 100644 --- a/RateMeter/ratemeter.py +++ b/RateMeter/ratemeter.py @@ -8,14 +8,10 @@ class RateMeter: This class is used to calculate a rolling average of units per second over `span` seconds. - Minimum span is 1 second. - Set `span` to None to calculate unit/s over the lifetime of the object after the first digest, rather than over a span. This saves the effort of tracking timestamps. Don't just use a large number! ''' - if span is not None and span < 1: - raise ValueError('Span must be >= 1') self.sum = 0 self.span = span @@ -23,10 +19,9 @@ class RateMeter: self.first_digest = None def digest(self, value): - now = math.ceil(time.time()) + now = time.time() self.sum += value - if self.span is None: if self.first_digest is None: self.first_digest = now diff --git a/RateMeter/speedtest.py b/RateMeter/speedtest.py index 3cdf0eb..8a2d923 100644 --- a/RateMeter/speedtest.py +++ b/RateMeter/speedtest.py @@ -4,8 +4,8 @@ import ratemeter import requests import time -URL = 'http://cdn.speedof.me/sample32768k.bin?r=0.8817502672426312' -METER = ratemeter.RateMeter(span=10) +URL = 'http://cdn.speedof.me/sample32768k.bin?r=0.881750426312' +METER = ratemeter.RateMeter(span=5) METER_2 = ratemeter.RateMeter(span=None) class G: pass @@ -13,7 +13,7 @@ class G: g = G() g.total = 0 g.start = None -g.last = int(time.time()) +g.last = time.time() def callback_progress(bytes_downloaded, bytes_total): if g.start is None: @@ -25,7 +25,7 @@ def callback_progress(bytes_downloaded, bytes_total): METER.digest(chunk) METER_2.digest(chunk) now = round(time.time(), 1) - if now > g.last: + if now > g.last or (bytes_downloaded >= bytes_total): g.last = now percent = percent.rjust(9, ' ') rate = bytestring.bytestring(METER.report()[2]).rjust(15, ' ') @@ -35,5 +35,5 @@ def callback_progress(bytes_downloaded, bytes_total): #print(METER.report(), METER_2.report()) print(URL) -print('Progress'.rjust(9, ' '), 'bps over 10s'.rjust(15, ' '), 'bps overall'.rjust(15, ' '), 'elapsed'.rjust(10, ' ')) +print('Progress'.rjust(9, ' '), 'bps over 5s'.rjust(15, ' '), 'bps overall'.rjust(15, ' '), 'elapsed'.rjust(10, ' ')) downloady.download_file(URL, 'nul', callback_progress=callback_progress) \ No newline at end of file diff --git a/Ratelimiter/README.md b/Ratelimiter/README.md new file mode 100644 index 0000000..2a273ce --- /dev/null +++ b/Ratelimiter/README.md @@ -0,0 +1,6 @@ +Ratelimiter +=========== + +Provides a `Ratelimiter` class to regulate timing. Create an instance with the appropriate allowance and timing rules, then just call `limiter.limit()` in your loop. + +Note that allowance=10, period=10 is not the same as allowance=1, period=1. The first allows for more "burstiness" because all 10 operations can happen in the first second, as long as you wait for the other 9. \ No newline at end of file diff --git a/Ratelimiter/ratelimiter.py b/Ratelimiter/ratelimiter.py index 55f856e..f7953c1 100644 --- a/Ratelimiter/ratelimiter.py +++ b/Ratelimiter/ratelimiter.py @@ -2,10 +2,10 @@ import time class Ratelimiter: - def __init__(self, allowance_per_period, period, operation_cost=1, mode='sleep'): + def __init__(self, allowance_per_period, period=1, operation_cost=1, mode='sleep'): ''' allowance_per_period: - The number of operations we can perform per `period` seconds. + Our spending balance per `period` seconds. period: The number of seconds over which we can perform `allowance_per_period` operations. @@ -15,12 +15,17 @@ class Ratelimiter: Pass a `cost` parameter to `self.limit` to use a nondefault value. mode: - 'sleep': If we do not have the balance for an operation, sleep until we do. - Return True every time. - 'reject': If we do not have the balance for an operation, return False. + 'sleep': + If we do not have the balance for an operation, sleep until we do. + Return True every time. + + 'reject': + If we do not have the balance for an operation, return False. + The cost is not subtracted, so hopefully we have enough next time. ''' if mode not in ('sleep', 'reject'): raise ValueError('Invalid mode %s' % repr(mode)) + self.allowance_per_period = allowance_per_period self.period = period self.operation_cost = operation_cost @@ -28,29 +33,34 @@ class Ratelimiter: self.last_operation = time.time() self.balance = 0 - self.gain_rate = allowance_per_period / period + + @property + def gain_rate(self): + return self.allowance_per_period / self.period def limit(self, cost=None): + ''' + See the main class docstring for info about cost and mode behavior. + ''' if cost is None: cost = self.operation_cost - timediff = time.time() - self.last_operation - self.balance += timediff * self.gain_rate + + time_diff = time.time() - self.last_operation + self.balance += time_diff * self.gain_rate self.balance = min(self.balance, self.allowance_per_period) - successful = False - deficit = cost - self.balance - if deficit > 0 and self.mode == 'sleep': - time_needed = (deficit / self.gain_rate) - #print(self.balance, deficit, 'Need to sleep %f' % time_needed) - time.sleep(time_needed) - self.balance = cost - - #print(self.balance) if self.balance >= cost: - #print('pass') self.balance -= cost - successful = True + succesful = True + else: + if self.mode == 'reject': + succesful = False + else: + deficit = cost - self.balance + time_needed = deficit / self.gain_rate + time.sleep(time_needed) + self.balance = 0 + succesful = True self.last_operation = time.time() - - return successful + return succesful diff --git a/SinWave/sinwave.py b/SinWave/sinwave.py new file mode 100644 index 0000000..94b0ee1 --- /dev/null +++ b/SinWave/sinwave.py @@ -0,0 +1,270 @@ +import math +import random +import string +import threading +import time +import tkinter + +# Nice patterns +# 0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 255, 270, 285, 300, 315, 330, 345 +# 0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330 +# 0, 15, 30, 45, 60, 180, 195, 210, 225, 240 +# 0, 90, 180, 270 +# ░▒▓ + +SCREEN_WIDTH = 114 + +DEFAULT_LINE = { + 'character': '#', + 'degree': 0, + 'degree_step': 1, + 'horizontal_offset': 0, + 'line_thickness': 1, + 'original_degree': 0, + 'damping': 3, + 'depth': 0, +} +variables = { + 'clock': 0, + 'frames':[], + 'delay': 0.01, + 'lines':[ + ] +} + +class LineControl(tkinter.Frame): + def __init__(self, master, line, *args, **kwargs): + tkinter.Frame.__init__(self, master, *args, **kwargs) + + self.line = line + for x in range(4): + self.columnconfigure(x, minsize=40) + row = 0 + tkinter.Button(self, text='\u21bb', command=self.refresh).grid(row=row, column=0, sticky='news') + tkinter.Button(self, text='Clone', command=self.clone).grid(row=row, column=1, columnspan=2, sticky='news') + tkinter.Button(self, text='X', command=self.suicide).grid(row=row, column=3, sticky='news') + row += 1 + + tkinter.Label(self, text='Degree:').grid(row=row, column=0, sticky='e') + self.entry_degree = tkinter.Entry(self, width=3) + self.entry_degree.insert(0, self.line['original_degree']) + self.entry_degree.grid(row=row, column=1, sticky='news') + tkinter.Button(self, text='Set', command=self.apply_degree).grid(row=row, column=2, sticky='news') + row += 1 + + def create_buttonpair(key, row): + minus = tkinter.Button(self, text='-', command=lambda *a: self.step_variable(key, -1, self.value_labels[key])) + minus.grid(row=row, column=1, sticky='news') + plus = tkinter.Button(self, text='+', command=lambda *a: self.step_variable(key, +1, self.value_labels[key])) + plus.grid(row=row, column=2, sticky='news') + + self.value_labels = {} + tkinter.Label(self, text='Step:').grid(row=row, column=0, sticky='e') + create_buttonpair('degree_step', row) + self.value_labels['degree_step'] = tkinter.Label(self, text=str(self.line['degree_step'])) + self.value_labels['degree_step'].grid(row=row, column=3) + row += 1 + + tkinter.Label(self, text='Thick:').grid(row=row, column=0, sticky='e') + create_buttonpair('line_thickness', row) + self.value_labels['line_thickness'] = tkinter.Label(self, text=str(self.line['line_thickness'])) + self.value_labels['line_thickness'].grid(row=row, column=3) + row += 1 + + tkinter.Label(self, text='Offset:').grid(row=row, column=0, sticky='e') + create_buttonpair('horizontal_offset', row) + self.value_labels['horizontal_offset'] = tkinter.Label(self, text=str(self.line['horizontal_offset'])) + self.value_labels['horizontal_offset'].grid(row=row, column=3) + row += 1 + + tkinter.Label(self, text='Dampen:').grid(row=row, column=0, sticky='e') + create_buttonpair('damping', row) + self.value_labels['damping'] = tkinter.Label(self, text=str(self.line['damping'])) + self.value_labels['damping'].grid(row=row, column=3) + row += 1 + + tkinter.Label(self, text='Depth:').grid(row=row, column=0, sticky='e') + create_buttonpair('depth', row) + self.value_labels['depth'] = tkinter.Label(self, text=str(self.line['depth'])) + self.value_labels['depth'].grid(row=row, column=3) + row += 1 + + tkinter.Label(self, text='Char:').grid(row=row, column=0, sticky='e') + self.entry_character = tkinter.Entry(self, width=2, font=('Consolas', 12)) + self.entry_character.grid(row=row, column=1, sticky='news') + self.entry_character.insert(0, self.line['character']) + tkinter.Button(self, text='Set', command=self.apply_character).grid(row=row, column=2, sticky='news') + row += 1 + + def apply_character(self, *trash): + char = self.entry_character.get() + try: + assert len(char) == 1 + except: + return + self.line['character'] = char + + def apply_degree(self, *trash): + value = self.entry_degree.get() + try: + value = int(value) + except ValueError: + return + self.line['original_degree'] = value % 360 + self.refresh() + regrid_frames() + + def clone(self, *trash): + line = self.line.copy() + create_line_frame(line=line) + regrid_frames() + + def refresh(self, *trash): + self.line['degree'] = self.line['original_degree'] + (self.line['degree_step'] * variables['clock']) + + def step_variable(self, key, direction, label): + value = self.line[key] + value += direction + + if key == 'line_thickness': + value = max(value, 0) + elif key == 'horizontal_offset': + value = value % SCREEN_WIDTH + elif key == 'delay': + value = max(value, 0.001) + elif key in ('damping', 'depth'): + value = max(value, 0) + value = min(value, int(SCREEN_WIDTH / 2)) + + self.line[key] = value + label.configure(text=str(value)[:5]) + + def suicide(self, *trash): + unregister_line(self.line) + variables['frames'].remove(self) + self.grid_forget() + regrid_frames() + +def create_line(degree_offset, **kwargs): + line = DEFAULT_LINE.copy() + line.update(kwargs) + line['original_degree'] = degree_offset + line['degree'] = (variables['clock'] + degree_offset) % 360 + # Line ID exists solely to make sure that even clones are unique. + line['id'] = random.getrandbits(32) + return line + +def create_line_frame(offset=None, line=None): + if line is None: + if offset is None: + offset = entry_add.get() + offset = offset.replace(' ', '') + offset = offset.split(',') + try: + offset = [int(o) for o in offset] + except ValueError: + return + entry_add.delete(0, 'end') + + lines = [] + for x in offset: + line = create_line(x) + lines.append(line) + else: + line['id'] = random.getrandbits(32) + lines = [line] + + for line in lines: + register_line(line) + frame = LineControl(t, line, relief='groove', borderwidth=2) + variables['frames'].append(frame) + regrid_frames() + +def map_range(x, old_low, old_high, new_low, new_high): + ''' + Given a number x in range [old_low, old_high], return corresponding + number in range [new_low, new_high]. + ''' + if x > old_high or x < old_low: + raise ValueError('%d not in range [%d..%d]' % (x, old_low, old_high)) + percentage = (x - old_low) / (old_high - old_low) + y = (percentage * (new_high - new_low)) + new_low + return y + +def position_from_degree(d, damping_units): + rad = math.radians(d) + sin = math.sin(rad) + sin = map_range(sin, -1, 1, 0, 1) + position = sin * (SCREEN_WIDTH - 1) + position = map_range(position, 0, SCREEN_WIDTH, damping_units, SCREEN_WIDTH-damping_units) + #position = (position * (1- (2 * damping_percent))) + damping_units + position = round(position) + position = position % SCREEN_WIDTH + return position + +def print_loop(): + while True: + next_frame = time.time() + variables['delay'] + variables['clock'] = (variables['clock'] + 1) % 360 + + screen = ([' '] * SCREEN_WIDTH) + z_indexes = {} + + for line_vars in variables['lines']: + start_degree = line_vars['degree'] + end_degree = (start_degree + line_vars['degree_step']) % 360 + line_vars['degree'] = end_degree + + damping = line_vars['damping'] + start_pos = position_from_degree(start_degree, damping) + end_pos = position_from_degree(end_degree, damping) + (start_pos, end_pos) = sorted([start_pos, end_pos]) + + start_pos -= line_vars['line_thickness'] + end_pos += line_vars['line_thickness'] + + mini_step = line_vars['degree_step'] / max((end_pos - start_pos), 1) + for (index, position) in enumerate(range(start_pos, end_pos+1)): + position = (position + line_vars['horizontal_offset']) % SCREEN_WIDTH + this_rads = math.radians(start_degree + (mini_step * index)) + z_index = math.cos(this_rads) + z_index = map_range(z_index, -1, 1, line_vars['depth'], SCREEN_WIDTH-line_vars['depth']) + #print(line_vars['character'], z_index) + if z_index > z_indexes.get(position, -2): + screen[position] = line_vars['character'] + z_indexes[position] = z_index + + print('%03d' % variables['clock'], ''.join(screen)) + delay = max(next_frame - time.time(), 0) + time.sleep(delay) + +def register_line(line): + variables['lines'].append(line) + +def regrid_frames(): + frames = variables['frames'] + #frames.sort(key=lambda x: x.line['original_degree']) + for (index, frame) in enumerate(frames): + (row, column) = divmod(index, 4) + row += 1 + frame.grid(row=row, column=column) + +def unregister_line(line): + variables['lines'].remove(line) + +t = tkinter.Tk() + +frame_add = tkinter.Frame(t) +entry_add = tkinter.Entry(frame_add) +entry_add.grid(row=0, column=0) +tkinter.Button(frame_add, text='+', command=create_line_frame).grid(row=0, column=1) +frame_add.grid(row=0, column=0) + +frame_delay = tkinter.Frame(t) +tkinter.Label(frame_delay, text='Speed:') +thread = threading.Thread(target=print_loop) +thread.daemon=True +thread.start() + +create_line_frame([0]) +t.mainloop() \ No newline at end of file diff --git a/Steganographic/README.md b/Steganographic/README.md index 88b15ab..8ba50b6 100644 --- a/Steganographic/README.md +++ b/Steganographic/README.md @@ -1,7 +1,16 @@ Steganographic ============== - 2015 01 15: + 2016 05 12: + Now pads the remaining pixels with random data. Previously, the fact that the secret + file resided in only as many pixels as it needed meant there was a sudden decrease in + visual noise when the secret ended. Now there is noise throughout. + Your secret file should resemble random noise for this to be effective. Thus + encryption is recommended. + This does not change decoding, because the decoder only reads as many bytes as + needed. + + 2016 01 15: Now supports variable "bitness", the number of bits per color channel to overwrite. Previously, bitness was always 1, to maximize transparency. Now, bitness can be 1-8 to favor transparency or information density. diff --git a/Steganographic/steganographic.py b/Steganographic/steganographic.py index f5da08c..3cf53e8 100644 --- a/Steganographic/steganographic.py +++ b/Steganographic/steganographic.py @@ -178,10 +178,6 @@ def set_bit(number, index, newvalue): #### ## #### #### #### #### #### #### #### #### #### ## ############## #### #### ######## ###### ########## ############## def encode(imagefilename, secretfilename, bitness=1): - global image - global pixel - global pixel_index - global channel_index pixel_index = 0 channel_index = 0 @@ -198,18 +194,18 @@ def encode(imagefilename, secretfilename, bitness=1): image = Image.open(imagefilename) image_steg = BitsToImage(image, bitness) - totalpixels = image.size[0] * image.size[1] - if totalpixels < HEADER_SIZE: + total_pixels = image.size[0] * image.size[1] + if total_pixels < HEADER_SIZE: raise StegError('Image cannot have fewer than %d pixels. They are used to store Secret\'s length' % HEADER_SIZE) secret_extension = os.path.splitext(secretfilename)[1][1:] secret_content_length = (secret_size) + (len(secret_extension)) + 1 requiredpixels = math.ceil(((secret_content_length * 8) + 32) / (3 * bitness)) - if totalpixels < requiredpixels: + if total_pixels < requiredpixels: raise StegError('Image does not have enough pixels to store the Secret. ' 'Must have at least %d pixels' % requiredpixels) - print('%d pixels available, %d required' % (totalpixels, requiredpixels)) + print('%d pixels available, %d required' % (total_pixels, requiredpixels)) # --> YOU ARE HERE <-- @@ -226,23 +222,40 @@ def encode(imagefilename, secretfilename, bitness=1): # Write the secret data bytes_written = 0 - done = False - secretfile = open(secretfilename, 'rb') - while not done: - if bytes_written % 1024 == 0: - percentage = (bytes_written + 1) / secret_size - percentage = '%07.3f%%\r' % (100 * percentage) - print(percentage, end='') + one_complete_file = False - bytes = secretfile.read(FILE_READ_SIZE) + # Yes, we're assuming the whole file fits in memory. + secret_file = open(secretfilename, 'rb') + secret_data = secret_file.read() + secret_data_size = len(secret_data) + secret_index = 0 + for pixel_number in range(total_pixels): + if pixel_number % 4 == 0: + #percentage = (bytes_written + 1) / secret_size + #percentage = '%07.3f%%\r' % (100 * percentage) + #print(percentage, end='') + print(pixel_number) - done = len(bytes) == 0 + secret_chunk = secret_data[secret_index:secret_index+FILE_READ_SIZE] + secret_index += FILE_READ_SIZE + if len(secret_chunk) < FILE_READ_SIZE: + one_complete_file = True + #secret_index = 0 + rs = FILE_READ_SIZE - len(secret_chunk) + secret_chunk += os.urandom(rs) + #secret_chunk += secret_data[secret_index:secret_index+rs] - bytes = list(bytes) - bytes = [binary(byte) for byte in bytes] - bytes_written += len(bytes) - bytes = ''.join(bytes) - image_steg.write(bytes) + secret_chunk = list(secret_chunk) + secret_chunk = [binary(byte) for byte in secret_chunk] + bytes_written += len(secret_chunk) + secret_chunk = ''.join(secret_chunk) + try: + image_steg.write(secret_chunk) + except IndexError: + if one_complete_file: + break + else: + raise # haha print('100.000%') @@ -271,7 +284,6 @@ def encode(imagefilename, secretfilename, bitness=1): #### #### #### ## #### #### #### #### #### #### #### ## ########## ############## ######## ###### ########## ############## def decode(imagefilename, bitness=1): - print('Extracting content from "%s"' % imagefilename) image = Image.open(imagefilename) image_steg = ImageToBits(image, bitness) @@ -331,16 +343,16 @@ if __name__ == '__main__': command = listget(sys.argv, 1, '').lower() if command not in ['encode', 'decode']: print('Usage:') - print('> steganographic.py encode imagefilename.png secretfilename.ext') - print('> steganographic.py decode lacedimagename.png') + print('> steganographic.py encode imagefilename.png secretfilename.ext bitness') + print('> steganographic.py decode lacedimagename.png bitness') quit() imagefilename = sys.argv[2] if command == 'encode': secretfilename = sys.argv[3] - bitness = int(listget(sys.argv, 4, 1)) + bitness = int(sys.argv[4]) encode(imagefilename, secretfilename, bitness) else: - bitness = int(listget(sys.argv, 3, 1)) + bitness = int(sys.argv[3]) decode(imagefilename, bitness) \ No newline at end of file