def convert(input_image_stream, output_image_stream): f = input_image_stream out = output_image_stream sz = os.path.getsize(f.name) side = int(math.sqrt(sz * 2)) out.write(strtoio("P5\n{} {}\n255\n".format(side, side))) s = ["a"] * (sz * 2) for y in range(side): for x in range(side // 2): v = ord(iotostr(f.read(1))) s[(x + x) * side + y] = chr(255 - (v >> 4) * 17) s[(x + x + 1) * side + y] = chr(255 - (v & 15) * 17) out.write(strtoio("".join(s)))
def convert(input_image_stream, output_image_stream): def dump(x): c = palette[x] out.write( strtoio( pack([ (getbit(c, 5) * 2 + getbit(c, 2)) * 85, (getbit(c, 4) * 2 + getbit(c, 1)) * 85, (getbit(c, 3) * 2 + getbit(c, 0)) * 85, ]))) f = input_image_stream out = output_image_stream escape = ord(iotostr(f.read(1))) packed = ord(iotostr(f.read(1))) bcolor = ord(iotostr(f.read(1))) if packed == 0: raise Exception("not packed") palette = [ord(ii) for ii in iotostr(f.read(16))] out.write(strtoio("P6\n320 199\n255\n")) ii = 199 * 160 while ii > 0: c = ord(iotostr(f.read(1))) if c != escape: repeat = 1 else: repeat = ord(iotostr(f.read(1))) c = ord(iotostr(f.read(1))) for jj in range(repeat): ii = ii - 1 dump(c >> 4) dump(c & 7)
def dump(x): c = palette[x] out.write( strtoio( pack([ (getbit(c, 5) * 2 + getbit(c, 2)) * 85, (getbit(c, 4) * 2 + getbit(c, 1)) * 85, (getbit(c, 3) * 2 + getbit(c, 0)) * 85, ])))
def convert(input_image_stream, output_image_stream, width, height, skip): def dump(x): c = palette[x] out.write( strtoio( pack([ (getbit(c, 5) * 2 + getbit(c, 2)) * 85, (getbit(c, 4) * 2 + getbit(c, 1)) * 85, (getbit(c, 3) * 2 + getbit(c, 0)) * 85, ]))) f = input_image_stream if skip: f.read(skip) out = output_image_stream palette = [ord(ii) for ii in iotostr(f.read(16))] out.write(strtoio("P6\n{} {}\n255\n".format(width, height))) for jj in range(height): for ii in range(width // 2): c = ord(iotostr(f.read(1))) dump(c >> 4) dump(c & 15)
def test_strtoio(self): self.assertEqual(b"abc", strtoio("abc"))
def convert(input_image_stream, output_image_stream): def debug(x): sys.stderr.write("{}\n".format(x)) def dmp500(x): c = palette[x] out.write( strtoio( pack([ (getbit(c, 5) * 2 + getbit(c, 2)) * 85, (getbit(c, 4) * 2 + getbit(c, 1)) * 85, (getbit(c, 3) * 2 + getbit(c, 0)) * 85, ]))) f = input_image_stream out = output_image_stream # Maps composite palette values to RGB c2r = [ 0, 21, 2, 20, 6, 49, 35, 4, 33, 5, 14, 1, 12, 10, 3, 28, 7, 17, 16, 22, 48, 34, 37, 32, 44, 40, 42, 13, 8, 11, 24, 26, 56, 19, 18, 50, 54, 52, 38, 36, 46, 45, 41, 15, 9, 25, 27, 30, 63, 58, 23, 51, 55, 53, 39, 60, 47, 61, 43, 57, 29, 31, 59, 62, ] subtyp = 0 cols = 320 << subtyp rows = 200 colors = 16 if subtyp == 0 else 4 a = ord(iotostr(f.read(1))) if a != 0: debug("invalid header") sys.exit(1) palette = [ord(iotostr(f.read(1))) for ii in range(16)] debug(palette) is_rgb = ord(iotostr(f.read(1))) == 0 colorspace = "RGB" if is_rgb else "CMP" if not is_rgb: for ii in range(16): palette[ii] = c2r[palette[ii]] packed = ord(iotostr(f.read(1))) != 0 titbuf = iotostr(f.read(30)) i = titbuf.index("\0") if i: titbuf = titbuf[:i] titbuf = titbuf.rstrip() if subtyp == 0: def dump(a): dmp500(a >> 4) dmp500(a & 0x0F) else: def dump(a): dmp500(a >> 6) dmp500((a >> 4) & 3) dmp500((a >> 2) & 3) dmp500(a & 3) cycles = ord(iotostr(f.read(1))) a = ord(iotostr(f.read(1))) botpal = a & 0xF toppal = (a >> 4) & 0xF debug("{}x{}, 16 couleurs {}, titre «{}»".format(cols, rows, colorspace, titbuf)) debug("palette={}, cycles={}, botpal={},]\ntoppal={}".format( palette, cycles, botpal, toppal)) out.write(strtoio("P6\n{} {}\n255\n".format(cols, rows))) y = 160 * rows if not packed: while True: b = ord(iotostr(f.read(1))) if b == 0: break a = ord(iotostr(f.read(1))) for jj in range(b): dump(a) y = y - 1 if y <= 0: break else: for jj in range(y): dump(ord(iotostr(f.read(1)))) # Look for extra junk at the end of the file extra = 0 while f.read(1) != strtoio(""): extra = extra + 1 pass if extra > 0: debug("{} octets de trop".format(extra))
def convert( input_image_stream, output_image_stream, arte, newsroom, cols, rows, skip, ignore_header_errors, ): def clip(v): return 255 if v > 255 else (0 if v < 0 else v) # imitate +I and -I colours using Coco palette br2 = [ pack(x) for x in [[0, 0, 0], [255, 85, 0], [0, 170, 255], [255, 255, 255]] ] # take names "blue" and "red" too literally like many "patched for Coco3" # programs br3 = [ pack(x) for x in [[0, 0, 0], [255, 0, 0], [0, 0, 255], [255, 255, 255]] ] # probably not exact... semig = [ pack(x) for x in [ [0, 0, 0], [0, 255, 0], [255, 255, 0], [0, 0, 255], [255, 0, 0], [255, 255, 255], [0, 211, 170], [204, 0, 255], [255, 128, 0], ] ] f = input_image_stream out = output_image_stream if skip: f.read(skip) if newsroom: head = iotostr(f.read(2)) cols = ord(head[0]) * 8 rows = ord(head[1]) else: head = iotostr(f.read(5)) if ord(head[0]) != 0: sys.stderr.write("bad first byte in header\n") if not ignore_header_errors: return False if not rows: size = ord(head[1]) * 256 + ord(head[2]) rows = 8 * size // cols if cols * rows // 8 != size: sys.stderr.write( "data length {} in header would be closest to {}x{} but " "that would be {} bytes\n".format(size, cols, rows, cols * rows // 8)) if not ignore_header_errors: return False out.write(strtoio("P6\n{} {}\n255\n".format(cols, rows))) for jj in range(rows): row = iotostr(f.read(cols >> 3)) oy = r2 = g2 = b2 = 0 for vv in row: v = ord(vv) if arte == PIXEL_MODE_BW: for k in range(8): out.write(strtoio(br2[getbit(v, 7 - k) * 3])) elif (arte == PIXEL_MODE_BR) or (arte == PIXEL_MODE_RB): x = -100 if arte == PIXEL_MODE_BR else 100 # this is using the exact YIQ-to-RGB formula, but the rest is # just trial-and-error of what looks ok, without actually using # the spec of NTSC and/or VDG/GIME. more pixel options could # be added to allow variants on : brightness/contrast ; # saturation ; double-resolution for greater detail in # emulation ; different smoothing and horiz phase ; and # replacing ±I colours by ±V colours (green-purple of PAL and # of SECAM). for k in range(8): ny = getbit(v, 7 - k) * 255 y = (oy + ny + (ny >> 2)) >> 1 i = (x * (y - oy)) >> 7 r = clip(int((y + 0.9563 * i))) g = clip(int((y - 0.2721 * i))) b = clip(int((y - 1.1070 * i))) out.write( strtoio( pack([(r + r2) >> 1, (g + g2) >> 1, (b + b2) >> 1]))) oy = ny x = -x r2 = r g2 = g b2 = b elif arte == PIXEL_MODE_BR2: for k in range(4): out.write( strtoio(br2[getbit(v, 7 - k - k) * 2 + getbit(v, 6 - k - k)] * 2)) elif arte == PIXEL_MODE_RB2: for k in range(4): out.write( strtoio(br2[getbit(v, 7 - k - k) + getbit(v, 6 - k - k) * 2] * 2)) elif arte == PIXEL_MODE_BR3: for k in range(4): out.write( strtoio(br3[getbit(v, 7 - k - k) * 2 + getbit(v, 6 - k - k)] * 2)) elif arte == PIXEL_MODE_RB3: for k in range(4): out.write( strtoio(br3[getbit(v, 7 - k - k) + getbit(v, 6 - k - k) * 2] * 2)) elif arte == PIXEL_MODE_S10: for k in range(4): out.write( strtoio(semig[1 + getbit(v, 7 - k - k) + getbit(v, 6 - k - k) * 2] * 2)) elif arte == PIXEL_MODE_S11: for k in range(4): out.write( strtoio(semig[5 + getbit(v, 7 - k - k) + getbit(v, 6 - k - k) * 2] * 2)) return True
def convert(input_image_stream, output_image_stream): def debug(x): sys.stderr.write("{}\n".format(x)) def dump(x): c = palette[x] out.write( strtoio( pack([ (getbit(c, 5) * 2 + getbit(c, 2)) * 85, (getbit(c, 4) * 2 + getbit(c, 1)) * 85, (getbit(c, 3) * 2 + getbit(c, 0)) * 85, ]))) # Read basic structure # - is is a 192 or 384 row image? # - motifs - patterns used for filling shapes stored in the image file f = input_image_stream cols = 320 pictyp = ord(iotostr(f.read(1))) rows = (getbit(pictyp, 7) + 1) * 192 sans_motifs = getbit(pictyp, 0) != 0 debug("{}x{}, 16 couleurs, sans_motifs={}".format(cols, rows, sans_motifs)) # Get palette information palette = [ord(iotostr(f.read(1))) for ii in range(16)] anirat = ord(iotostr(f.read(1))) cycrat = ord(iotostr(f.read(1))) cm3cyc = [ord(iotostr(f.read(1))) for ii in range(8)] aniflg = ord(iotostr(f.read(1))) & 0x80 != 0 cycflg = ord(iotostr(f.read(1))) & 0x80 != 0 debug("palette={}".format(palette)) debug("cm3cyc={} cycrat={} cycflg={} anirat={} aniflg={}".format( cm3cyc, cycrat, cycflg, anirat, aniflg)) if not sans_motifs: iotostr(f.read(243)) linbuf = [0] * 160 buff1 = [0] * 20 buff2 = [] # Start outputting image out = output_image_stream out.write(strtoio("P6\n{} {}\n255\n".format(cols, rows))) for ii in range(getbit(pictyp, 7) + 1): lines = ord(iotostr(f.read(1))) for jj in range(lines): u = 0 y = 0 bitu = 7 bity = 7 x = 0 a = None contr = ord(iotostr(f.read(1))) if contr < 128: for kk in range(20): buff1[kk] = ord(iotostr(f.read(1))) buff2 = [] for kk in range(contr): buff2.append(ord(iotostr(f.read(1)))) for kk in range(160): if contr >= 128: a = ord(iotostr(f.read(1))) else: cc = getbit(buff1[u], bitu) bitu = bitu - 1 if bitu < 0: bitu = 7 u = u + 1 if cc == 0: a = linbuf[(x - 1) % 160] else: cc = getbit(buff2[y], bity) bity = bity - 1 if bity < 0: bity = 7 y = y + 1 if cc == 0: a = linbuf[x] else: a = ord(iotostr(f.read(1))) linbuf[x] = a dump(a >> 4) dump(a & 15) x = x + 1 # Look for extra junk at the end of the file extra = 0 while iotostr(f.read(1)) != "": extra = extra + 1 pass if extra > 0: debug("{} octets de trop".format(extra))