Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- import re, struct, sys
- from PIL import Image
- # Author: @doegox
- # Original version was from
- # https://www.reddit.com/r/programming/comments/1ye0th/i_found_this_in_a_computer_magazine_from_1986/
- # This version expects a perfect BW image, 1 pixel per dot
- # Relevant patents:
- # https://www.google.com/patents/US4692603
- # https://www.google.com/patents/US4728783
- # https://www.google.com/patents/US4782221
- # very first lines: count number of black lines N -> there are (N+4)/2 nibbles in each data line
- # here 10 -> (10+4)/2 = 7 nibbles per line
- # dibit/bit/dibit_sync/dibit_P1/dibit_nibbles/dibit_P2/bit_or_dibit/dibit/bit_sync
- # P1: parity of the even bits
- # P2: parity of the odd bits
- # First data line should be 00 00 00 LL HH -> total nr of bytes
- image = Image.open("softstrip_bw.png")
- w, h = image.size
- def getcolor(pixel):
- return pixel^1
- def paritycheck(bits):
- a = bits[::2]
- b = bits[1::2]
- if '?' in a:
- a = False
- else:
- a = (sum(a) % 2 == 0)
- if '?' in b:
- b = False
- else:
- b = (sum(b) % 2 == 0)
- return a and b
- def getnibbles(bits):
- 'return [(nibble, validmask)]'
- ret = []
- par = paritycheck(bits)
- bits = bits[1:-1] # remove parity bits
- assert len(bits) % 4 == 0
- while len(bits):
- nib, bits = bits[:4], bits[4:]
- n = 0
- invalid = 0
- for b in reversed(nib):
- n <<= 1
- invalid <<= 1
- if b not in (0, 1):
- invalid |= 1
- else:
- n |= b
- if not par:
- invalid = 0b1111
- ret.append((n, invalid ^ 0b1111))
- return ret
- def getbytes(nibbles):
- bytes = []
- while len(nibbles) >= 2:
- a, av = nibbles.pop(0)
- b, bv = nibbles.pop(0)
- c = chr((b << 4) | a)
- v = chr((bv << 4) | av)
- bytes.append((c, v))
- return bytes
- firstline=[]
- nibbles = []
- bytes = []
- for y in range(h):
- dibits = []
- for x in range(w):
- dibits.append(getcolor(image.getpixel((x,y))))
- bits = []
- for i in range(5, len(dibits) - 5, 2):
- a, b = dibits[i:i+2]
- if a != b:
- bits.append(int(a))
- else:
- bits.append('?')
- print ''.join(' #'[b] for b in dibits), ''.join(map(str, bits)), ''.join("%x" % c for c, v in getnibbles(bits)), ''.join("%x" % v for c, v in getnibbles(bits))
- if nibbles == [] and '?' in bits:
- continue
- if firstline == []:
- firstline = bits
- else:
- if bits != firstline:
- # Start recording data
- nibbles += getnibbles(bits)
- bytes += getbytes(nibbles)
- raw = ''.join(c for c, v in bytes)
- valid = ''.join(v for c, v in bytes)
- header = raw[:5]
- assert header[:3]=='\0\0\0'
- size, = struct.unpack('<H', header[3:])
- data = raw[5:]
- valid = valid[5:]
- assert len(data) >= size, 'data length doesn\'t match size given in header'
- if len(data) > size:
- print "Truncating data from %i to %i bytes" % (len(data), size)
- data=data[:size]
- open('out.bin', 'w').write(data)
- open('out.valid', 'w').write(valid)
- fmt = '%-48s %-16s %-32s'
- allvalid = bool(re.match(r'\xff+$', valid))
- print
- print fmt % ('hex', 'ascii', '' if allvalid else 'valid bits')
- for i in range(0, len(data), 16):
- d = data[i:i+16]
- v = valid[i:i+16]
- hex = ' '.join('%02x' % ord(c) for c in d)
- ascii = ''.join((c if 32 <= ord(c) <= 126 else '.') for c in d)
- val = '' if allvalid else ''.join('%02x' % ord(c) for c in v)
- print fmt % (hex, ascii, val)
Add Comment
Please, Sign In to add comment