Stitch format PMV

The educational technology and digital learning wiki
Revision as of 04:57, 10 September 2018 by Tatarize (talk | contribs) (→‎Header)
Jump to navigation Jump to search

.pmv files are a brother stitch format.

Overview

Stitch formats are strictly embroidery in the traditional sense. They are the applications of patterned stitches on to fabric. But these are done with programs within the sewing machine itself. Rather than the entire XY field of the hoop they have a Y field of the presser foot and an X dimension forward and back along the fabric. It is for this reason that the formatting is stored in a hybrid absolute/relative manner with different encoding schemes. The amount the element moves up in the fabric is different than the amount the needle moves within the presser foot.

There are several other related Brother stitch files this is simply the only one analyzed.

Header

The header is exactly 100 bytes long. 7 bytes of format spec, 36 of copyright. And 57 bytes of a few different stitch settings.

Type Bytes Value Description
`string` 7 "#PMV0001" Nearly ever brother format starts with a similar header.
`string` 36 copyright This is not needed for the format explicitly but the files contain a copyright message. This doesn't affect whether the files work or not.
`s8` 9 b'\x01\x00\x00\x00\x00\x00\x00\x00\x00' Unknown
`s8` 1 Length Offset Usually 00, but can be set within the stitch and saved. It's the offset from the default in signed 8 bit.
`s8` 1 Width Offset Usually 00, but can be set within the stitch and saved. It's the offset from the default in signed 8 bit.
`s8` 3 b'\x00\x00\x01' Unknown
`s8` 14 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' Unknown
`s8` 3 b'\x00\x00\x00' Unknown
`s16` 2 L/R shift Usually 0, but gives the length offset in left and right directly to the current value.
`s8` 9 b'\x00\x00\x01\x00\x00\x00\x00\x00\x00' Unknown
`s8` 14 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00' Unknown

L/R shift is a 16 bit integer located at 0x4A-0x4B. The length table offset is an 8 bit int located at 0x34 and the width table offset is located at 0x35. These can be set within the stitch on the machine and then saved out again saving their value. The table offsets are signed 8 bit numbers, and are added to the default table values located within the tables.

Stitch Block

Point count Byte count. 6 bits forward/back 5 bits movement within presser foot.

While +15,-16 is possible beyond 14,14 is never seen.

Ends with 0, 256 16le 0 16le 256 Likely due to there not being another stitch block.

Followed by 16 bytes of unknown. b'\x00\x00\x00\x00\x05\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x02\x00'

Control Tables

Unknown: 16le 256 8 0 8 0

The sewing machines apparently don't do the math themselves so they process a bunch of tables of settings.

   length_range = max_x - min_x
   write_length_lookup_table(f, length_range)
   width_range = max_y - min_y
   write_width_lookup_table(f, width_range)
   write_int_16le(f, 0x12)
   f.write(b'\x00\x00\x00\x00\x00\x00\x00\x00'
           b'\x00\x00\x00\x00\x00\x00\x00\x00')

Length Lookup Table

   write_values = [(0, 0), (10, 71), (20, 143), (40, 214), (60, 286), (80, 357),
                   (100, 429), (120, 500), (140, 571), (160, 714), (180, 786), (200, 857),
                   (250, 1000), (300, 1286), (350, 1429), (400, 1571), (450, 1786), (500, 2000)]
   write_int_8(f, 12)
   steps = len(write_values)
   write_int_8(f, steps)
   for value in write_values:
       length_at_step = value[0]
       other_at_step = value[1]
       write_int_16le(f, length_at_step)
       write_int_16le(f, other_at_step)

Width Lookup Table

   pos = int(width_range / 2)
   write_int_8(f, pos)
   if width_range == 0:
       write_int_8(f, 1)
       write_int_16le(f, 8192)
       write_int_16le(f, 1000)
       return
   steps = 15
   write_int_8(f, steps)
   second_max = other_step = 28000.0 / float(width_range)
   second_step = second_max / float(steps - 1)
   for i in range(0, steps):
       width_at_step = 50 * i
       other_at_step = second_step * i
       write_int_16le(f, width_at_step)
       write_int_16le(f, int(round(other_at_step)))