diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/QUICKSTART.md b/QUICKSTART.md index ed288ca..525d5e7 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -78,6 +78,24 @@ find . -name "*.pcx" | python3 punchcard-generator.py --stitches 24 --layout mot - `-d ./output` preserve subfolder structure in output folder - `--threshold 220` change punch sensitivity - `--invert` invert pixel-to-punch behavior +- `--jacquard {none,doublebed,birdseye,tuck}` double bed jacquard mode + +## 6) Double bed jacquard + +For double bed jacquard knitting the punchcard rows are doubled โ€” each design row becomes two punchcard rows (pattern row + backing row). Three backing styles are available: + +```bash +# Solid/full-jacquard backing (all stitches punched on backing row) +python3 punchcard-generator.py design.png 24 motif 6 --jacquard doublebed + +# Bird's eye backing (alternating checkerboard on backing row) +python3 punchcard-generator.py design.png 24 motif 6 --jacquard birdseye + +# Tuck-stitch backing (inverse of pattern on backing row) +python3 punchcard-generator.py design.png 24 motif 6 --jacquard tuck +``` + +> A 6-row design with `--jacquard doublebed` produces a 12-row card. ## Troubleshooting ๐Ÿ”ง diff --git a/README.md b/README.md index c8f8302..c8e09b8 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ This uttility generates SVG files, usable in most diecutting machines, for punch - ๐Ÿงต Supports 12-stitch and 24-stitch card widths - ๐Ÿ” Layout modes: `auto`, `motif`, and `repeat` - ๐Ÿ“ Vertical repeats for longer pattern runs +- ๐Ÿงถ Double bed jacquard modes: `doublebed`, `birdseye`, and `tuck` - ๐Ÿงช Batch processing from shell globs and stdin - โš™๏ธ Threshold and inversion controls for image-to-punch mapping @@ -87,6 +88,7 @@ find . -name "*.pcx" | python3 punchcard-generator.py --stitches 24 --layout mot - `--stitches {12,24}` card width (default `24`) - `--layout {auto,motif,repeat}` layout mode (default `auto`) - `--repeat-height N` vertical repeats (default `1`) +- `--jacquard {none,doublebed,birdseye,tuck}` double bed jacquard mode (default `none`) - `--threshold 0-255` image threshold (default `255`) - `--invert` invert punched and non-punched spaces on the card - `--hole-ratio 0-1` hole size ratio (default `0.55`) @@ -97,6 +99,23 @@ find . -name "*.pcx" | python3 punchcard-generator.py --stitches 24 --layout mot - `repeat`: tiles design across width (design width must divide by card width) - `auto`: picks `motif` or `repeat` based on width compatibility +## ๐Ÿงถ Double Bed Jacquard + +Double bed jacquard uses both the main bed and the ribber to create a two-layer fabric. Each design row is split into two punchcard rows: the pattern row (colour selection) and a backing row. Use `--jacquard` to enable this mode: + +- `none` (default): standard 1:1 punchcard +- `doublebed`: solid/full-jacquard backing โ€” every stitch punched on the backing row +- `birdseye`: bird's eye backing โ€” alternating checkerboard pattern on the backing row +- `tuck`: tuck-stitch backing โ€” inverse of the pattern row on the backing row + +```bash +python3 punchcard-generator.py design.png 24 motif 6 --jacquard doublebed +python3 punchcard-generator.py design.png 24 motif 6 --jacquard birdseye +python3 punchcard-generator.py design.png 24 motif 6 --jacquard tuck +``` + +> **Note:** Double bed jacquard doubles the number of rows on the card. A 6-row motif with `--jacquard doublebed` produces a 12-row card. + ## ๐Ÿค Contributing Ideas, bug reports, and PRs are welcome. diff --git a/punchcard-generator.py b/punchcard-generator.py index 3b60159..46804a6 100644 --- a/punchcard-generator.py +++ b/punchcard-generator.py @@ -184,6 +184,45 @@ def compose_card_rows(rows, card_stitches, card_layout, repeat_height): raise ValueError(f"Unsupported card layout '{layout}'") +def build_double_bed_rows(rows, backing="doublebed"): + """Transform card rows for double bed jacquard knitting. + + Each pattern row is doubled into two punchcard rows: + - Row 1 (odd pass): the original pattern row (selects needles for colour A) + - Row 2 (even pass): a backing row whose style is chosen by ``backing`` + + Backing modes + ------------- + doublebed : every stitch punched โ€“ solid / full-jacquard backing + birdseye : alternating x-/checkerboard backing (bird's eye) + tuck : inverse of the pattern row (tuck-stitch backing) + """ + if not rows: + return rows + + width = len(rows[0]) + result = [] + + for i, row in enumerate(rows): + result.append(row) + + if backing == "doublebed": + result.append("x" * width) + elif backing == "birdseye": + # Checkerboard: phase shifts by 1 each pair so the backing forms a + # diagonal bird's eye grid across the fabric. + offset = i % 2 + backing_row = "".join("x" if (j + offset) % 2 == 0 else "-" for j in range(width)) + result.append(backing_row) + elif backing == "tuck": + tuck_row = "".join("-" if ch == "x" else "x" for ch in row) + result.append(tuck_row) + else: + raise ValueError(f"Unsupported double bed backing mode: '{backing}'") + + return result + + def write_brother_style_svg( path, rows, @@ -326,6 +365,7 @@ def generate_punchcard( card_stitches=None, card_layout="auto", card_repeat_height=1, + jacquard="none", ): img = open_flattened_rgb_image(input_path) rows, width_cells, height_cells = build_punch_rows(img, threshold=threshold, invert=invert) @@ -346,6 +386,9 @@ def generate_punchcard( ) output_width = card_stitches + if jacquard != "none": + output_rows = build_double_bed_rows(output_rows, backing=jacquard) + if punchcard_mode in ("text", "both"): txt_path = output_base + ".punch.txt" write_punch_text(txt_path, output_rows) @@ -373,7 +416,8 @@ def generate_punchcard( print(f"Created: {svg_path}") if layout_used is not None: - print(f"Card layout: {layout_used}, width: {card_stitches}, rows: {len(output_rows)}") + jacquard_info = f", jacquard: {jacquard}" if jacquard != "none" else "" + print(f"Card layout: {layout_used}, width: {card_stitches}, rows: {len(output_rows)}{jacquard_info}") def process_file( @@ -389,6 +433,7 @@ def process_file( stitches=24, layout="auto", repeat_height=1, + jacquard="none", ): input_path = input_path.strip() if not input_path or not os.path.exists(input_path): @@ -416,6 +461,7 @@ def process_file( card_stitches=stitches, card_layout=layout, card_repeat_height=repeat_height, + jacquard=jacquard, ) except Exception as e: print(f"Error on {input_path}: {e}", file=sys.stderr) @@ -483,6 +529,19 @@ def process_file( default=1, help="Number of vertical repeats for card pattern. Default: 1.", ) + parser.add_argument( + "--jacquard", + choices=["none", "doublebed", "birdseye", "tuck"], + default="none", + help=( + "Double bed jacquard mode. Each pattern row is doubled: the original row" + " followed by a backing row. " + "none: standard 1:1 card (default). " + "doublebed: full/solid backing (all stitches punched). " + "birdseye: alternating checkerboard backing (bird's eye). " + "tuck: inverse of the pattern row (tuck-stitch backing)." + ), + ) parser.add_argument("-help", action="help", help="Show this help message and exit.") parser.add_argument( @@ -561,6 +620,7 @@ def process_file( stitches=stitches, layout=layout, repeat_height=repeat_height, + jacquard=args.jacquard, ) # 2. Process files passed via pipe (e.g., find . -name '*.pcx' | punchcard) @@ -579,6 +639,7 @@ def process_file( stitches=stitches, layout=layout, repeat_height=repeat_height, + jacquard=args.jacquard, ) # 3. If no input was provided via either method, show the help