pyembroidery/pyembroidery/Vp3Reader.py

124 wiersze
3.6 KiB
Python

from .EmbThread import EmbThread
from .ReadHelper import (
read_int_8,
read_int_16be,
read_int_24be,
read_int_32be,
read_signed,
read_string_8,
read_string_16,
)
def read_vp3_string_16(stream):
# Reads the header strings which are 16le numbers of size followed by
# utf-16 text
string_length = read_int_16be(stream)
return read_string_16(stream, string_length)
def read_vp3_string_8(stream):
# Reads the body strings which are 16be numbers followed by utf-8 text
string_length = read_int_16be(stream)
return read_string_8(stream, string_length)
def skip_vp3_string(stream):
string_length = read_int_16be(stream)
stream.seek(string_length, 1)
def signed32(b):
b &= 0xFFFFFFFF
if b > 0x7FFFFFFF:
return -0x100000000 + b
else:
return b
def signed16(b0, b1):
b0 &= 0xFF
b1 &= 0xFF
b = (b0 << 8) | b1
if b > 0x7FFF:
return -0x10000 + b
else:
return b
def read(f, out, settings=None):
b = f.read(6)
# magic code: %vsm%\0
skip_vp3_string(f) # "Produced by Software Ltd"
f.seek(7, 1)
skip_vp3_string(f) # "" comments and note string.
f.seek(32, 1)
center_x = signed32(read_int_32be(f)) / 100
center_y = -(signed32(read_int_32be(f)) / 100)
f.seek(27, 1)
skip_vp3_string(f) # ""
f.seek(24, 1)
skip_vp3_string(f) # "Produced by Software Ltd"
count_colors = read_int_16be(f)
for i in range(0, count_colors):
vp3_read_colorblock(f, out, center_x, center_y)
if (i + 1) < count_colors: # Don't add the color change on the final read.
out.color_change()
out.end()
def vp3_read_colorblock(f, out, center_x, center_y):
bytescheck = f.read(3) # \x00\x05\x00
distance_to_next_block_050 = read_int_32be(f)
block_end_position = distance_to_next_block_050 + f.tell()
start_position_x = signed32(read_int_32be(f)) / 100
start_position_y = -(signed32(read_int_32be(f)) / 100)
abs_x = start_position_x + center_x
abs_y = start_position_y + center_y
if abs_x != 0 and abs_y != 0:
out.move_abs(abs_x, abs_y)
thread = vp3_read_thread(f)
out.add_thread(thread)
f.seek(15, 1)
bytescheck = f.read(3) # \x0A\xF6\x00
stitch_byte_length = block_end_position - f.tell()
stitch_bytes = read_signed(f, stitch_byte_length)
i = 0
while i < len(stitch_bytes) - 1:
x = stitch_bytes[i]
y = stitch_bytes[i + 1]
i += 2
if (x & 0xFF) != 0x80:
out.stitch(x, y)
continue
if y == 0x01:
x = signed16(stitch_bytes[i], stitch_bytes[i + 1])
i += 2
y = signed16(stitch_bytes[i], stitch_bytes[i + 1])
i += 2
out.stitch(x, y)
i += 2
# Final element is typically 0x80 0x02, this is skipped regardless of its value.
elif y == 0x02:
# This is only seen after 80 01 and should have been skipped. Has no known effect.
pass
elif y == 0x03:
out.trim()
def vp3_read_thread(f):
thread = EmbThread()
colors = read_int_8(f)
transition = read_int_8(f)
for m in range(0, colors):
thread.color = read_int_24be(f)
parts = read_int_8(f)
color_length = read_int_16be(f)
thread_type = read_int_8(f)
weight = read_int_8(f)
thread.catalog_number = read_vp3_string_8(f)
thread.description = read_vp3_string_8(f)
thread.brand = read_vp3_string_8(f)
return thread