Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion vectorizing/solvers/color/ColorSolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def solve(self):
self.timer.end_timer()

self.timer.start_timer("Polygon Clipping")
compound_paths = remove_layering(traced_bitmaps)
compound_paths = remove_layering(traced_bitmaps, self.img)
self.timer.end_timer()

return [compound_paths, colors, self.img.size[0], self.img.size[1]]
Expand Down
65 changes: 56 additions & 9 deletions vectorizing/solvers/color/clip.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,70 @@
from pathops import op, PathOp
from pathops import op, PathOp, Path
from vectorizing.geometry.potrace import potrace_path_to_compound_path

def remove_layering(traced_bitmaps):
def create_background_rect(img, padding):
"""
Creates a rectangle that matches the image dimensions plus
some padding.

Parameters:
img: A Pillow image instance.

Returns:
The rectangle.
"""
rect = Path()
rect.moveTo(-padding, -padding)
rect.lineTo(img.width + padding, -padding)
rect.lineTo(img.width + padding, img.height + padding)
rect.lineTo(-padding, img.height + padding)
rect.close()
return rect

def remove_layering(traced_bitmaps, img):
"""
Performs boolean operations on a list of traced bitmaps
to ensure that they are all disjoint.

Parameters:
traced_bitmaps: The list of traced bitmaps (potrace paths).
This function uses a technique devised to try to minimize
the holes created / outright failures of SKPath boolean operations.
Even so, a failure can still happen (and often does), particularly
for very intricate paths (usually coming from real world photographs).
In such cases, the routine fallbacks to a mixture of disjoint paths
(the ones for which the boolean operations didn't fail), and layered paths.

Parameters:
traced_bitmaps: The list of traced bitmaps (potrace paths).
img: A Pillow image.

Returns:
The processed list of compound paths.
Returns:
The processed list of compound paths.
"""
compound_paths = [
potrace_path_to_compound_path(traced) for traced in traced_bitmaps
]

disjoint_paths = []
for x in range(len(compound_paths) - 1):
next = compound_paths[x + 1]
compound_paths[x] = op(compound_paths[x], next, PathOp.DIFFERENCE)
# Each base path has bigger padding to reduce
# the amount of overlapping borders.
base = create_background_rect(img, (x + 1) * 10)

to_subtract = Path()
for y in range(0, x):
to_subtract.addPath(disjoint_paths[y])
to_subtract.addPath(compound_paths[x + 1])

try:
result = op(base, to_subtract, PathOp.DIFFERENCE)
except:
break
disjoint_paths.append(result)

for x in range(len(disjoint_paths)):
try:
disjoint_paths[x] = op(disjoint_paths[x], create_background_rect(img, 0), PathOp.INTERSECTION)
except:
return compound_paths

return compound_paths
disjoint_paths = disjoint_paths + compound_paths[len(disjoint_paths) : len(compound_paths)]
return disjoint_paths
Loading