# -*- Mode: Python -*-

# Convert a 'Kolor Raw' file (.kro) from AutopanoPro to a netpbm PPM file/stream.

import struct

def read_kro_header (fi):
    block = fi.read (20)
    magic, width, height, bits, colors = struct.unpack ('>4sllll', block)
    assert (magic == 'KRO\x01')
    return magic, width, height, bits, colors 

def write_ppm_header (fo, bits, w, h):
    if bits == 8:
        fo.write ('P6\n#converted from KRO\n%d %d\n255\n' % (w, h))
    elif bits == 16:
        fo.write ('P6\n#converted from KRO\n%d %d\n65535\n' % (w, h))
    else:
        raise NotImplementedError

def copy (fi, fo):
    magic, width, height, bits, colors = read_kro_header (fi)
    pixels = width * height
    write_ppm_header (fo, bits, width, height)
    if bits == 8:
        # doing this in blocks roughly doubles the speed...
        while 1:
            block = fi.read (16384)
            if not block:
                break
            else:
                oblock = []
                for x in range (0, len(block), 4):
                    oblock.append (block[x:x+3])
                fo.write (''.join (oblock))
    elif bits == 16:
        while pixels:
            r,g,b,a = struct.unpack ('>HHHH', fi.read (8))
            # some tools (e.g., XnView) expect little-endian shorts in
            # 16-bit PPM files, use this line instead:
            #fo.write (struct.pack ('<HHH', r,g,b))
            fo.write (struct.pack ('>HHH', r,g,b))            
            pixels -= 1
    else:
        raise NotImplementedError

if __name__ == '__main__':
    import sys
    fi = open (sys.argv[1], 'rb')
    # '-c' will output to stdout, for example:
    #  $ python kro2ppm.py input.kro -c | pnmscale 0.5 | cjpeg > output.jpg
    if '-c' in sys.argv:
        fo = sys.stdout
    else:
        fo = open (sys.argv[1] + '.ppm', 'wb')
    copy (fi, fo)
    fo.close()
    fi.close()
