Skip to content

Commit 87e7e58

Browse files
committed
readme + almost finish
1 parent cde3a63 commit 87e7e58

16 files changed

Lines changed: 499 additions & 158 deletions

.coverage

52 KB
Binary file not shown.

README.md

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,60 @@
1-
# knitting_pattern
2-
A project in which I attempt to create a tool to help calculate knitting patterns.
3-
My goal is to develop an app where the user can move and scale alpha patterns (patterns on a pixel grid) on a garment, and based on selected measurement, yarn gauge and pattern placement, the app can calculate a knitting pattern to follow.
1+
```markdown
2+
# 🧶 Knit App
3+
4+
## About This Project
5+
Knit App is a comprehensive Streamlit-based application designed for knitters and compatible with crocheters and other textile makers. It bridges the gap between digital pixel art and physical garment construction. Users can upload images to generate alpha patterns, calculate garment shaping (Front, Back, and Sleeves) based on gauge and sizing, and edit multiple graphics on a digital canvas.
6+
7+
8+
## Key Features
9+
* **Pattern Digitization:** Upload any PNG/JPG and use dynamic thresholding and resampling to convert it into a pixel matrix that you can layer onto a sweater canvas.
10+
* **Multi-Panel Garment IDE:** Switch between Front Panel, Back Panel, and Sleeves canvases that make up a drop shoulder sweater. The app dynamically calculates dimensions and short-row shaping based on user measurements and gauge.
11+
* **Layer Design Studio:** Add, duplicate, merge, and transform (rotate, flip, mirror, scale) multiple graphics on a single canvas.
12+
* **Fine-Tune Pixel Editor:** A built-in, manual spreadsheet-style editor to fine-tune individual stitches or draw custom motifs from scratch on blank 25x25 or 50x50 canvases.
13+
* **Alpha JSON exporter:** Export your custom design to a JSON file to reuse in future projects.
14+
* **Master PDF Compiler:** Automatically chunks your digital canvas into a printable PDF pattern complete with cast-on counts, row instructions, and sweater specs.
15+
* **Project Saving:** Serialize your entire workspace (including layers, settings, and math grids) into a JSON file to resume your work later.
16+
17+
18+
## Prerequisites
19+
Before installing, ensure you have **Python 3.9 or newer** installed on your system. We highly recommend using a virtual environment (like `venv` or Anaconda) to keep dependencies clean.
20+
21+
22+
## Installation
23+
24+
### Option A: Using GitHub Desktop
25+
1. Download and install [GitHub Desktop](https://desktop.github.com/).
26+
2. Open GitHub Desktop and go to **File > Clone repository**.
27+
3. Select the **URL** tab and paste: `https://github.com/Programming-The-Next-Step-2026/knitting_pattern.git`
28+
4. Choose a local path on your computer and click **Clone**.
29+
5. Open your preferred terminal (or Anaconda Prompt) and navigate to the folder you just cloned.
30+
6. Run the following command to install the package and its dependencies:
31+
pip install -e .
32+
33+
34+
### Option B: Command Line (Windows / Mac / Linux)
35+
1. Open your Terminal/Command Prompt/PowerShell.
36+
2. Clone the repository:
37+
git clone [https://github.com/Programming-The-Next-Step-2026/knitting_pattern.git](https://github.com/Programming-The-Next-Step-2026/knitting_pattern.git)
38+
39+
3. Navigate into the directory:
40+
cd knitting_pattern
41+
42+
4. Install the package:
43+
pip install -e .
44+
45+
46+
## Usage
47+
Once installed, make sure your in the knitting_pattern directory, then run the application locally:
48+
streamlit run src/knitting_pattern/app.py
49+
50+
This will automatically open the Knit App dashboard in your default web browser.
51+
52+
## Project Architecture
53+
54+
* **`app.py`:** The Streamlit UI layer acting as the bridge for state management and user interaction.
55+
* **`math_engine.py`:** Calculates physical measurements, gauge conversions, and garment topography (like short row geometry).
56+
* **`image_engine.py`:** Handles digital formatting, utilizing Pillow and NumPy for image resampling, bounding box cropping, and Matplotlib for dynamic PDF generation.
57+
58+
## License
59+
60+
Distributed under the MIT License. Built for the course *Programming: The Next Step (2026)*.

docs/report.ipynb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
"id": "73620923-8165-4d80-a81a-cb768294cc6f",
66
"metadata": {},
77
"source": [
8-
"Week 3 Assignment: Knitting Pattern Calculator Project Report\n",
9-
"\n",
108
"1. Project Overview\n",
119
"Knitting a custom sweater from the top down requires translating physical body measurements into a discrete grid of stitches and rows based on a individual knitting gauge. Manual conversion often leads to structural math errors. Furthermore, knitters wanting to incorporate multi-colored intarsia or stranded motifs (\"alpha patterns\") must manually map those pixel charts onto their specific garment dimensions, which is a slow and error-prone process.\n",
1210
"\n",

pyproject.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ description = "Kitting pattern calculator tool for my programming course"
1515
readme = "README.md"
1616
requires-python = ">=3.9"
1717
dependencies = [
18-
"numpy",
19-
"Pillow",
20-
"streamlit",
21-
"matplotlib"
18+
"numpy>=1.24.0",
19+
"Pillow>=9.1.0",
20+
"streamlit>=1.30.0",
21+
"matplotlib>=3.5.0",
22+
"pandas>=1.5.0"
2223
]
2324
classifiers = [
2425
"Programming Language :: Python :: 3",

src/all_over_pattern.jpg

148 KB
Loading

src/alphabet.jpg

151 KB
Loading

src/alphabet.webp

8.82 KB
Loading

src/eyes.jpg

130 KB
Loading

src/flower_repeating.jpg

130 KB
Loading

src/knitting_pattern/app.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
# ==========================================
5252
st.set_page_config(page_title="Knit App", page_icon="🧶", layout="wide")
5353
st.title("Knitting Chart Maker")
54-
st.markdown("Transform any alpha pattern into a perfectly scaled, knittable chart.")
54+
st.markdown("Transform any alpha pattern into a knittable chart with instructions for a drop-shoulder sweater")
5555

5656
# ==========================================
5757
# SIDEBAR: SETTINGS & MEASUREMENTS
@@ -357,11 +357,24 @@ def restore_project_callback():
357357
st.session_state.active_stamp_idx = max(0, len(active_stamps) - 1)
358358
st.rerun()
359359
with c_exp:
360-
t_mat = rotate_matrix(active_stamp["matrix"], active_stamp.get("rotation", 0))
361-
t_mat = apply_transforms(t_mat, active_stamp.get("symmetry", "None"), active_stamp.get("axis", "Horizontal"), active_stamp.get("spacing_h", 0), active_stamp.get("spacing_v", 0))
362-
cropped_mat = crop_matrix_to_bounding_box(t_mat)
363-
st.download_button("💾 Export Alpha (JSON)", data=json.dumps(cropped_mat), file_name=f"{active_stamp['name'].replace(' ', '_')}_alpha.json", mime="application/json", use_container_width=True)
364-
360+
with st.expander("💾 Export JSON", expanded=False):
361+
export_scaled = st.checkbox("Include Scale Multiplier?", value=False, help="Check this to download the physically enlarged matrix instead of the original size.")
362+
363+
t_mat = rotate_matrix(active_stamp["matrix"], active_stamp.get("rotation", 0))
364+
t_mat = apply_transforms(t_mat, active_stamp.get("symmetry", "None"), active_stamp.get("axis", "Horizontal"), active_stamp.get("spacing_h", 0), active_stamp.get("spacing_v", 0))
365+
366+
# If the user checked the box, mathematically scale the matrix before saving it
367+
if export_scaled and active_stamp.get("scale", 1) > 1:
368+
t_mat = scale_pattern_matrix_integer(t_mat, active_stamp.get("scale", 1))
369+
370+
cropped_mat = crop_matrix_to_bounding_box(t_mat)
371+
st.download_button(
372+
label="📥 Download JSON",
373+
data=json.dumps(cropped_mat),
374+
file_name=f"{active_stamp['name'].replace(' ', '_')}_alpha.json",
375+
mime="application/json",
376+
use_container_width=True
377+
)
365378
st.write("---")
366379

367380
# 3. MANUAL PIXEL EDITOR (The "Tweezers")
@@ -373,7 +386,7 @@ def restore_project_callback():
373386
pk = st.session_state.proj_id
374387
idx = st.session_state.active_stamp_idx
375388

376-
# --- CSS HACK: Shrink the Data Editor rows and padding ---
389+
# --- CSS ---
377390
st.markdown("""
378391
<style>
379392
[data-testid="stDataEditor"] div {
@@ -391,7 +404,7 @@ def restore_project_callback():
391404
df = pd.DataFrame(bool_matrix)
392405

393406
# NEW: Force every column to be exactly 30 pixels wide (the smallest reliable checkbox size)
394-
# We also use the index as a 'Row Number' so you don't get lost
407+
# We also use the index as a 'Row Number'
395408
col_config = {
396409
column: st.column_config.CheckboxColumn(label="", width=20)
397410
for column in df.columns
@@ -439,8 +452,21 @@ def restore_project_callback():
439452

440453
active_stamp["spacing_h"] = st.slider("Horizontal Spacing", -30, 30, int(active_stamp.get("spacing_h", 0)), key=f"sh_{idx}_{pk}_{active_panel}")
441454
active_stamp["spacing_v"] = st.slider("Vertical Spacing", -30, 30, int(active_stamp.get("spacing_v", 0)), key=f"sv_{idx}_{pk}_{active_panel}")
442-
active_stamp["scale"] = st.slider("Scale", 1, 10, int(active_stamp.get("scale", 1)), key=f"sc_{idx}_{pk}_{active_panel}")
443-
455+
# --- BAKING SCALE SLIDER ---
456+
col_sc_slide, col_sc_bake = st.columns([2.5, 1])
457+
458+
with col_sc_slide:
459+
active_stamp["scale"] = st.slider("Scale", 1, 10, int(active_stamp.get("scale", 1)), key=f"sc_{idx}_{pk}_{active_panel}")
460+
461+
with col_sc_bake:
462+
st.markdown("<div style='margin-top: 28px;'></div>", unsafe_allow_html=True) # Pushes the button down to align with the slider
463+
if st.button("🔨 Bake", use_container_width=True, help="Permanently enlarge the pixel matrix so you can edit the scaled pixels individually.", key=f"bake_{idx}_{pk}_{active_panel}"):
464+
if active_stamp["scale"] > 1:
465+
# Mathematically enlarge the matrix
466+
active_stamp["matrix"] = scale_pattern_matrix_integer(active_stamp["matrix"], active_stamp["scale"])
467+
# Reset the slider back to 1
468+
active_stamp["scale"] = 1
469+
st.rerun()
444470
# Wrap Position in a border
445471
with st.container(border=True):
446472
st.markdown("#### Position")

0 commit comments

Comments
 (0)