kopia lustrzana https://github.com/EmbroidePy/pyembroidery
393 wiersze
13 KiB
Python
393 wiersze
13 KiB
Python
import struct
|
|
import zlib
|
|
|
|
from .EmbConstant import *
|
|
from .EmbThread import EmbThread
|
|
|
|
SEQUIN_CONTINGENCY = CONTINGENCY_SEQUIN_STITCH
|
|
FULL_JUMP = True
|
|
|
|
characters = {
|
|
"0": [
|
|
[9, 9, 4, 1, 0, 1, 5, 9, 9],
|
|
[9, 3, 0, 0, 0, 0, 0, 5, 9],
|
|
[7, 0, 1, 7, 9, 6, 0, 0, 9],
|
|
[4, 0, 5, 9, 9, 9, 4, 0, 6],
|
|
[3, 0, 8, 9, 9, 9, 6, 0, 4],
|
|
[2, 0, 9, 5, 0, 6, 8, 0, 3],
|
|
[2, 0, 9, 4, 0, 6, 8, 0, 3],
|
|
[2, 0, 9, 9, 9, 9, 8, 0, 3],
|
|
[3, 0, 8, 9, 9, 9, 6, 0, 4],
|
|
[4, 0, 5, 9, 9, 9, 4, 0, 6],
|
|
[7, 0, 1, 7, 9, 6, 0, 0, 8],
|
|
[9, 3, 0, 0, 0, 0, 0, 5, 9],
|
|
[9, 9, 4, 1, 0, 1, 5, 9, 9],
|
|
],
|
|
"1": [
|
|
[9, 8, 5, 2, 0, 1, 9, 9, 9],
|
|
[9, 1, 0, 0, 0, 1, 9, 9, 9],
|
|
[9, 2, 4, 7, 1, 1, 9, 9, 9],
|
|
[9, 9, 9, 9, 1, 1, 9, 9, 9],
|
|
[9, 9, 9, 9, 1, 1, 9, 9, 9],
|
|
[9, 9, 9, 9, 1, 1, 9, 9, 9],
|
|
[9, 9, 9, 9, 1, 1, 9, 9, 9],
|
|
[9, 9, 9, 9, 1, 1, 9, 9, 9],
|
|
[9, 9, 9, 9, 1, 1, 9, 9, 9],
|
|
[9, 9, 9, 9, 1, 1, 9, 9, 9],
|
|
[9, 9, 9, 9, 1, 1, 9, 9, 9],
|
|
[9, 3, 0, 0, 0, 0, 0, 0, 3],
|
|
[9, 3, 0, 0, 0, 0, 0, 0, 3],
|
|
],
|
|
"2": [
|
|
[8, 5, 2, 1, 1, 2, 6, 9, 9],
|
|
[4, 0, 0, 0, 0, 0, 0, 4, 9],
|
|
[5, 4, 7, 8, 8, 5, 0, 0, 8],
|
|
[9, 9, 9, 9, 9, 9, 3, 0, 7],
|
|
[9, 9, 9, 9, 9, 9, 3, 0, 9],
|
|
[9, 9, 9, 9, 9, 8, 0, 4, 9],
|
|
[9, 9, 9, 9, 8, 1, 2, 9, 9],
|
|
[9, 9, 9, 8, 2, 2, 9, 9, 9],
|
|
[9, 9, 8, 1, 2, 9, 9, 9, 9],
|
|
[9, 8, 1, 2, 9, 9, 9, 9, 9],
|
|
[7, 1, 2, 9, 9, 9, 9, 9, 9],
|
|
[3, 0, 0, 0, 0, 0, 0, 0, 6],
|
|
[3, 0, 0, 0, 0, 0, 0, 0, 6],
|
|
],
|
|
"3": [
|
|
[9, 6, 2, 1, 1, 2, 6, 9, 9],
|
|
[5, 0, 0, 0, 0, 0, 0, 4, 9],
|
|
[6, 3, 7, 8, 9, 6, 1, 0, 8],
|
|
[9, 9, 9, 9, 9, 9, 3, 0, 8],
|
|
[9, 9, 9, 9, 8, 6, 1, 1, 9],
|
|
[9, 9, 4, 0, 0, 0, 2, 8, 9],
|
|
[9, 9, 4, 0, 0, 0, 2, 8, 9],
|
|
[9, 9, 9, 9, 8, 6, 1, 1, 8],
|
|
[9, 9, 9, 9, 9, 9, 5, 0, 6],
|
|
[9, 9, 9, 9, 9, 9, 5, 0, 5],
|
|
[3, 5, 7, 9, 8, 6, 1, 0, 7],
|
|
[2, 0, 0, 0, 0, 0, 0, 3, 9],
|
|
[8, 4, 2, 0, 1, 2, 5, 9, 9],
|
|
],
|
|
"4": [
|
|
[9, 9, 9, 9, 7, 0, 0, 7, 9],
|
|
[9, 9, 9, 9, 2, 1, 0, 7, 9],
|
|
[9, 9, 9, 5, 2, 4, 0, 7, 9],
|
|
[9, 9, 8, 1, 7, 4, 0, 7, 9],
|
|
[9, 9, 3, 4, 9, 4, 0, 7, 9],
|
|
[9, 6, 1, 9, 9, 4, 0, 7, 9],
|
|
[8, 1, 6, 9, 9, 4, 0, 7, 9],
|
|
[4, 3, 9, 9, 9, 4, 0, 7, 9],
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
[0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
[9, 9, 9, 9, 9, 4, 0, 7, 9],
|
|
[9, 9, 9, 9, 9, 4, 0, 7, 9],
|
|
[9, 9, 9, 9, 9, 4, 0, 7, 9],
|
|
],
|
|
"5": [
|
|
[7, 0, 0, 0, 0, 0, 0, 5, 9],
|
|
[7, 0, 0, 0, 0, 0, 0, 5, 9],
|
|
[7, 0, 5, 9, 9, 9, 9, 9, 9],
|
|
[7, 0, 5, 9, 9, 9, 9, 9, 9],
|
|
[7, 0, 1, 1, 0, 2, 6, 9, 9],
|
|
[7, 0, 0, 0, 0, 0, 0, 5, 9],
|
|
[7, 4, 7, 9, 8, 4, 0, 0, 9],
|
|
[9, 9, 9, 9, 9, 9, 3, 0, 6],
|
|
[9, 9, 9, 9, 9, 9, 5, 0, 6],
|
|
[9, 9, 9, 9, 9, 9, 3, 0, 6],
|
|
[3, 5, 8, 9, 8, 5, 0, 0, 9],
|
|
[2, 0, 0, 0, 0, 0, 0, 6, 9],
|
|
[8, 4, 1, 0, 1, 2, 7, 9, 9],
|
|
],
|
|
"6": [
|
|
[9, 9, 7, 2, 1, 0, 3, 8, 9],
|
|
[9, 6, 0, 0, 0, 0, 0, 3, 9],
|
|
[8, 0, 0, 4, 8, 9, 6, 4, 9],
|
|
[5, 0, 4, 9, 9, 9, 9, 9, 9],
|
|
[3, 0, 8, 9, 9, 9, 9, 9, 9],
|
|
[2, 1, 8, 3, 0, 1, 3, 8, 9],
|
|
[2, 2, 2, 0, 0, 0, 0, 1, 8],
|
|
[2, 0, 2, 7, 9, 8, 2, 0, 5],
|
|
[3, 0, 7, 9, 9, 9, 7, 0, 3],
|
|
[4, 0, 7, 9, 9, 9, 7, 0, 3],
|
|
[7, 0, 2, 7, 9, 8, 2, 0, 5],
|
|
[9, 3, 0, 0, 0, 0, 0, 1, 8],
|
|
[9, 9, 4, 1, 0, 1, 3, 8, 9],
|
|
],
|
|
"7": [
|
|
[2, 0, 0, 0, 0, 0, 0, 0, 5],
|
|
[2, 0, 0, 0, 0, 0, 0, 0, 7],
|
|
[9, 9, 9, 9, 9, 9, 3, 2, 9],
|
|
[9, 9, 9, 9, 9, 8, 0, 5, 9],
|
|
[9, 9, 9, 9, 9, 4, 0, 8, 9],
|
|
[9, 9, 9, 9, 9, 1, 3, 9, 9],
|
|
[9, 9, 9, 9, 6, 0, 6, 9, 9],
|
|
[9, 9, 9, 9, 2, 1, 9, 9, 9],
|
|
[9, 9, 9, 7, 0, 4, 9, 9, 9],
|
|
[9, 9, 9, 3, 0, 8, 9, 9, 9],
|
|
[9, 9, 8, 0, 2, 9, 9, 9, 9],
|
|
[9, 9, 5, 0, 6, 9, 9, 9, 9],
|
|
[9, 9, 1, 0, 9, 9, 9, 9, 9],
|
|
],
|
|
"8": [
|
|
[9, 8, 3, 1, 0, 1, 4, 8, 9],
|
|
[8, 1, 0, 0, 0, 0, 0, 1, 9],
|
|
[5, 0, 3, 8, 9, 7, 2, 0, 6],
|
|
[5, 0, 7, 9, 9, 9, 5, 0, 6],
|
|
[7, 0, 3, 8, 9, 7, 2, 1, 8],
|
|
[9, 7, 2, 0, 0, 0, 2, 7, 9],
|
|
[9, 5, 1, 0, 0, 0, 1, 6, 9],
|
|
[6, 0, 3, 8, 9, 7, 2, 0, 7],
|
|
[2, 0, 9, 9, 9, 9, 7, 0, 4],
|
|
[2, 0, 9, 9, 9, 9, 7, 0, 3],
|
|
[3, 0, 3, 8, 9, 7, 2, 0, 4],
|
|
[7, 0, 0, 0, 0, 0, 0, 1, 8],
|
|
[9, 8, 3, 1, 0, 1, 4, 8, 9],
|
|
],
|
|
"9": [
|
|
[9, 7, 3, 0, 0, 2, 6, 9, 9],
|
|
[7, 0, 0, 0, 0, 0, 0, 5, 9],
|
|
[3, 0, 4, 8, 9, 7, 1, 0, 9],
|
|
[1, 0, 9, 9, 9, 9, 5, 0, 6],
|
|
[1, 1, 9, 9, 9, 9, 5, 0, 5],
|
|
[3, 0, 4, 8, 9, 7, 1, 0, 4],
|
|
[7, 0, 0, 0, 0, 0, 3, 0, 4],
|
|
[9, 7, 2, 0, 1, 4, 7, 0, 4],
|
|
[9, 9, 9, 9, 9, 9, 5, 0, 5],
|
|
[9, 9, 9, 9, 9, 9, 2, 0, 7],
|
|
[9, 3, 7, 9, 8, 3, 0, 2, 9],
|
|
[9, 1, 0, 0, 0, 0, 0, 7, 9],
|
|
[9, 7, 2, 0, 1, 3, 8, 9, 9],
|
|
],
|
|
"-": [
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 1, 0, 0, 0, 3, 9, 9],
|
|
[9, 9, 1, 0, 0, 0, 3, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
],
|
|
"m": [
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[9, 9, 9, 9, 9, 9, 9, 9, 9],
|
|
[0, 5, 2, 1, 7, 6, 1, 2, 8],
|
|
[0, 1, 0, 0, 1, 1, 0, 0, 3],
|
|
[0, 2, 9, 4, 0, 4, 8, 2, 1],
|
|
[0, 5, 9, 6, 0, 7, 9, 4, 1],
|
|
[0, 5, 9, 6, 0, 7, 9, 4, 0],
|
|
[0, 5, 9, 6, 0, 7, 9, 4, 0],
|
|
[0, 5, 9, 6, 0, 7, 9, 4, 0],
|
|
[0, 5, 9, 6, 0, 7, 9, 4, 0],
|
|
[0, 5, 9, 6, 0, 7, 9, 4, 0],
|
|
[0, 5, 9, 6, 0, 7, 9, 4, 0],
|
|
],
|
|
}
|
|
|
|
|
|
def write_png(buf, width, height):
|
|
width_byte_4 = width * 4
|
|
raw_data = b"".join(
|
|
b"\x00" + buf[span : span + width_byte_4]
|
|
for span in range(0, height * width * 4, width_byte_4)
|
|
)
|
|
|
|
def png_pack(png_tag, data):
|
|
chunk_head = png_tag + data
|
|
return (
|
|
struct.pack("!I", len(data))
|
|
+ chunk_head
|
|
+ struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head))
|
|
)
|
|
|
|
return b"".join(
|
|
[
|
|
b"\x89PNG\r\n\x1a\n",
|
|
png_pack(b"IHDR", struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
|
|
png_pack(b"IDAT", zlib.compress(raw_data, 9)),
|
|
png_pack(b"IEND", b""),
|
|
]
|
|
)
|
|
|
|
|
|
class PngBuffer:
|
|
def __init__(self, width, height):
|
|
self.width = int(width + 3)
|
|
self.height = int(height + 3)
|
|
self.buf = [0] * (4 * self.width * self.height)
|
|
self.red = 0
|
|
self.green = 0
|
|
self.blue = 0
|
|
self.alpha = 0
|
|
self.line_width = 3
|
|
|
|
def background(self, red, green, blue, alpha):
|
|
for i in range(0, len(self.buf), 4):
|
|
self.buf[i] = red
|
|
self.buf[i + 1] = green
|
|
self.buf[i + 2] = blue
|
|
self.buf[i + 3] = alpha
|
|
|
|
def plot(self, x, y):
|
|
try:
|
|
x += 1
|
|
y += 1
|
|
pos = (self.width * y) + x
|
|
idx = pos * 4
|
|
self.buf[idx] = self.red
|
|
self.buf[idx + 1] = self.green
|
|
self.buf[idx + 2] = self.blue
|
|
self.buf[idx + 3] = self.alpha
|
|
except IndexError:
|
|
pass
|
|
|
|
def draw_line(self, x0, y0, x1, y1):
|
|
dy = y1 - y0 # BRESENHAM LINE DRAW ALGORITHM
|
|
dx = x1 - x0
|
|
if dy < 0:
|
|
dy = -dy
|
|
step_y = -1
|
|
else:
|
|
step_y = 1
|
|
if dx < 0:
|
|
dx = -dx
|
|
step_x = -1
|
|
else:
|
|
step_x = 1
|
|
if dx > dy:
|
|
dy <<= 1 # dy is now 2*dy
|
|
dx <<= 1
|
|
fraction = dy - (dx >> 1) # same as 2*dy - dx
|
|
self.line_for_point(x0, y0, False)
|
|
|
|
while x0 != x1:
|
|
if fraction >= 0:
|
|
y0 += step_y
|
|
fraction -= dx # same as fraction -= 2*dx
|
|
x0 += step_x
|
|
fraction += dy # same as fraction += 2*dy
|
|
self.line_for_point(x0, y0, False)
|
|
else:
|
|
dy <<= 1 # dy is now 2*dy
|
|
dx <<= 1 # dx is now 2*dx
|
|
fraction = dx - (dy >> 1)
|
|
self.line_for_point(x0, y0, True)
|
|
while y0 != y1:
|
|
if fraction >= 0:
|
|
x0 += step_x
|
|
fraction -= dy
|
|
y0 += step_y
|
|
fraction += dx
|
|
self.line_for_point(x0, y0, True)
|
|
|
|
def line_for_point(self, x, y, dy):
|
|
w = self.line_width
|
|
left = w >> 1
|
|
right = w - left
|
|
if dy:
|
|
for pos in range(-left, right):
|
|
self.plot(x + pos, y)
|
|
else:
|
|
for pos in range(-left, right):
|
|
self.plot(x, y + pos)
|
|
|
|
def draw_text(self, x, y, string, rotate=False):
|
|
for c in string:
|
|
m = characters[c]
|
|
for cx in range(len(m[0])):
|
|
for cy in range(len(m)):
|
|
v = m[cy][cx]
|
|
if v == 9:
|
|
continue
|
|
if rotate:
|
|
gx = x + (len(m) - cy) + 1
|
|
gy = y + cx + 2
|
|
else:
|
|
gx = x + cx + 2
|
|
gy = y + cy + 2
|
|
pos = (self.width * gy) + gx
|
|
idx = pos * 4
|
|
a2 = (9.0 - v) / 9.0
|
|
r = (1.0 - a2) * self.buf[idx]
|
|
g = (1.0 - a2) * self.buf[idx + 1]
|
|
b = (1.0 - a2) * self.buf[idx + 2]
|
|
a1 = self.buf[idx + 3] / 255.0
|
|
a = a2 + a1 * (1.0 - a2)
|
|
try:
|
|
self.buf[idx] = int(r)
|
|
self.buf[idx + 1] = int(g)
|
|
self.buf[idx + 2] = int(b)
|
|
self.buf[idx + 3] = int(a * 255)
|
|
except IndexError:
|
|
pass
|
|
if rotate:
|
|
y += 11
|
|
else:
|
|
x += 11
|
|
|
|
|
|
def write(pattern, f, settings=None):
|
|
guides = settings.get("guides", False)
|
|
extends = pattern.bounds()
|
|
pattern.translate(-extends[0], -extends[1])
|
|
width = int(extends[2] - extends[0])
|
|
height = int(extends[3] - extends[1])
|
|
draw_buff = PngBuffer(width, height)
|
|
if settings is not None:
|
|
background = settings.get("background", None)
|
|
linewidth = settings.get("linewidth", None)
|
|
if background is not None:
|
|
b = EmbThread()
|
|
b.set(background)
|
|
draw_buff.background(b.get_red(), b.get_green(), b.get_blue(), 0xFF)
|
|
if linewidth is not None and isinstance(linewidth, int):
|
|
draw_buff.line_width = linewidth
|
|
|
|
for stitchblock in pattern.get_as_stitchblock():
|
|
block = stitchblock[0]
|
|
thread = stitchblock[1]
|
|
draw_buff.red = thread.get_red()
|
|
draw_buff.green = thread.get_green()
|
|
draw_buff.blue = thread.get_blue()
|
|
draw_buff.alpha = 255
|
|
last_x = None
|
|
last_y = None
|
|
for stitch in block:
|
|
x = int(stitch[0])
|
|
y = int(stitch[1])
|
|
if last_x is not None:
|
|
draw_buff.draw_line(last_x, last_y, x, y)
|
|
last_x = x
|
|
last_y = y
|
|
|
|
if guides:
|
|
draw_buff.red = 0
|
|
draw_buff.green = 0
|
|
draw_buff.blue = 0
|
|
draw_buff.alpha = 255
|
|
draw_buff.line_width = 1
|
|
min_x = extends[0]
|
|
min_y = extends[1]
|
|
points = 50
|
|
draw_buff.draw_text(0, 0, "mm")
|
|
for x in range(points - (min_x % points), width - 30, points):
|
|
if x < 30:
|
|
continue
|
|
draw_buff.draw_text(x, 0, str(int((x + min_x) / 10)), rotate=True)
|
|
draw_buff.draw_line(x, 0, x, 30)
|
|
for y in range(points - (min_y % points), height - 30, points):
|
|
if y < 30:
|
|
continue
|
|
draw_buff.draw_text(0, y, str(int((y + min_y) / 10)))
|
|
draw_buff.draw_line(0, y, 30, y)
|
|
|
|
f.write(
|
|
write_png(bytes(bytearray(draw_buff.buf)), draw_buff.width, draw_buff.height)
|
|
)
|