Color by Number — Pipeline Algorithm Specification
Pipeline tổng quan
PNG/JPEG input
│
▼
[1] vectorizer.ai API (fill_shapes, max_colors=20)
│
▼
SVG vector
│
├──[2]──→ after/ (full color PNG)
├──[3]──→ before/ (line art PNG)
└──[4]──→ zip/ (Iceors ZIP)
[1] Vectorize: PNG → SVG
POST https://api.vectorizer.ai/api/v1/vectorize
Auth: HTTP Basic (API_ID, API_SECRET)
Body: multipart/form-data
image = <file bytes>
output.file_format = "svg"
mode = "production"
processing.max_colors = "20"
output.gap_filler.enabled = "true"
Response: raw SVG bytes (200 OK)
Cost: 1 credit/ảnh
[2] After PNG (full color)
Input: SVG bytes từ bước 1
Tool: cairosvg.svg2png(bytestring=svg, output_width=2048, output_height=2048)
Output: PNG 2048x2048, full color
Save: after/{name}.png
[3] Before PNG (line art)
Input: SVG bytes từ bước 1
Logic:
1. Parse SVG bằng svgelements
2. Duyệt mọi Shape element
3. Chỉ giữ element có:
- stroke != none (có nét vẽ)
- stroke_width > 0
- stroke luminance < 200
(luminance = 0.299*R + 0.587*G + 0.114*B)
4. Render mỗi path giữ lại thành:
<path d="..." fill="none" stroke="black"
stroke-width="{gốc}" stroke-linecap="round"
stroke-linejoin="round"/>
5. Đặt trên nền trắng:
<rect fill="white" phủ toàn bộ viewBox/>
6. cairosvg.svg2png → PNG 2048x2048
Output: PNG 2048x2048, đen trắng (lineart)
Save: before/{name}.png
[4] Iceors ZIP
ZIP chứa 3 files, không có extension:
{key}_b.zip
├── {key}b ← path data (text, CRLF line ending)
├── {key}c ← reference JPEG 2048x2048
└── sp_new_paint_flag ← nội dung: "111\r\n" (5 bytes)
{key} = tên file gốc bỏ ký tự đặc biệt, max 20 chars. VD: anh1.png → key = anh1
File {key}b — Path data
Mỗi dòng là 1 region, ngăn cách bằng \r\n (CRLF). 6 fields phân cách bằng |:
{path_d}|{color}|{stroke_width}|{label_pos}|{font_size}|{flag}
3 loại dòng:
| Loại | color | stroke_width | label_pos | font_size | flag | Ý nghĩa |
|---|---|---|---|---|---|---|
| Fill màu | 8A572D (hex RGB) |
0 |
cy*2048+cx |
10-124 |
0 |
Vùng user tô được |
| Fill đen | 000000 |
0 |
0 |
0 |
0 |
Vùng cố định (decoration) |
| Stroke | 0 |
2 (int px) |
0 |
0 |
0 |
Nét viền |
Công thức từng field
path_d
SVG path commands (M, L, C, Q, Z — uppercase absolute coords). Tọa độ trong canvas 2048x2048.
VD: M957.87,299.21C30.52,1.46...Z
color
- Fill: hex 6 chars (VD:
8A572D),000000nếu đen - Stroke:
0 - Lưu ý: white (255,255,255) →
FEFEFE
stroke_width
- Fill:
0 - Stroke: int pixel width (VD:
2)
label_pos
- Fill:
cy * 2048 + cx(cx, cy = tâm bounding box của path) - Stroke:
0
font_size
- Fill: tính theo diện tích vùng:
ratio = area / (2048 * 2048)
if ratio > 0.05:
font_size = clamp(ratio * 800, 10, 124)
elif ratio > 0.01:
font_size = clamp(ratio * 1500, 10, 30)
else:
font_size = max(10, ratio * 3000)
- Stroke:
0
flag
- Fill:
0 - Stroke:
0
Thứ tự dòng
- Fill lines trước (sort diện tích giảm dần — vùng lớn nhất trước)
- Stroke lines sau
Xử lý đặc biệt trước khi xuất
- Merge similar colors: các shade RGB cách nhau ≤ 15 (Euclidean) → gộp về shade lớn nhất
- Subtract overlaps: mỗi fill chỉ giữ pixel KHÔNG bị fill nào ở trên che (dùng boolean path DIFFERENCE)
- Auto outline: mỗi fill tự động sinh thêm 1 stroke line đen width=1.5px cùng path
File {key}c — Reference JPEG
Input: SVG bytes
Logic:
1. cairosvg.svg2png(svg, output_width=W, output_height=H)
W, H = scale SVG về max cạnh = 2048, giữ aspect ratio
2. PIL resize → (W, H)
3. Center-pad trắng → 2048x2048
4. Save JPEG quality=92
Output: JPEG 2048x2048
File sp_new_paint_flag
Nội dung cố định: "111\r\n" (5 bytes, ASCII)
Hệ tọa độ
Canvas: 2048 x 2048 pixels (vuông)
Gốc tọa độ: top-left (0, 0)
SVG không vuông: pad center vào khung vuông trước khi scale
label_pos encoding:
pack: label_pos = y * 2048 + x
unpack: x = label_pos % 2048
y = label_pos // 2048
Cấu trúc Output
output/
├── before/ ← Line art PNG (black strokes on white)
│ ├── anh1.png 2048x2048
│ ├── anh2.png
│ └── ...
├── after/ ← Full color PNG (rendered from SVG)
│ ├── anh1.png 2048x2048
│ ├── anh2.png
│ └── ...
└── zip/ ← Iceors ZIP (load vào Android app)
├── anh1_b.zip
│ ├── anh1b path data (pipe-delimited, CRLF)
│ ├── anh1c reference JPEG 2048x2048
│ └── sp_new_paint_flag "111\r\n"
├── anh2_b.zip
└── ...
CLI Usage
cd tools/
# Batch processing
python batch_pipeline.py input_folder/ output_folder/ \
--api-id <VECTORIZER_API_ID> \
--api-secret <VECTORIZER_API_SECRET> \
--max-colors 20 \
--workers 1
# Hoặc dùng environment variables
export VECTORIZER_API_ID="your_id"
export VECTORIZER_API_SECRET="your_secret"
python batch_pipeline.py input/ output/
CLI Options
| Flag | Default | Mô tả |
|---|---|---|
--max-colors |
20 |
Số màu tối đa cho vectorizer |
--dark-threshold |
200 |
Ngưỡng luminance cho line art (0-255) |
--workers |
1 |
Số thread chạy song song |
--api-id |
env var | Vectorizer.ai API Id |
--api-secret |
env var | Vectorizer.ai API Secret |