def err(i):
     "error function"
     f = 1 / (1. + quality * 254)
     t = rgba(i)
     c2 = (int(int(t[0] * f) / f), int(int(t[1] * f) / f),
           int(int(t[2] * f) / f), t[3])
     return reduce(c2)
 def err(i) : 
     "error function"
     f = 1/(1.+quality*254)
     t=rgba(i)
     c2=(int(int(t[0]*f)/f),int(int(t[1]*f)/f),int(int(t[2]*f)/f),t[3])
     return reduce(c2)
def image_encode(src,f,frame_height, quality) : 
    def err(i) : 
        "error function"
        f = 1/(1.+quality*254)
        t=rgba(i)
        c2=(int(int(t[0]*f)/f),int(int(t[1]*f)/f),int(int(t[2]*f)/f),t[3])
        return reduce(c2)

    data = [reduce(c) for c in src.getdata()] # keep image in RAM as RGBA tuples. 
    w,h=src.size

    s_blits = [] # stringified blits for all image
    
    start_file = f.tell()
    line16=[] # offsets from start as u16 index on  words 

    for y in range(h) :
        if y%16==0 : 
            ofs = sum(len(x) for x in s_blits)
            line16.append(ofs/4) # XXX use /4 but need to align 

        skipped=0
        blits=[]



        line=data[y*w:(y+1)*w] # 16 bit data
        singles=[] 
        for c,g in groupby(line, key=err) : 
            t = tuple(g)
            n = len(t)
            # take the most frequent reral color
            cnt = Counter(t)
            col = cnt.most_common(1)[0][0]

            blits.append([n,col,False])

        # set EOL 
        if blits : 
            blits[-1][2]=True
        else : 
            blits.append([0,[],True])


        # now encode line : (header + blit) x n
        for num, color, eol in blits :          
            header=(num<<3) | (1 if eol else 0)
            s = struct.pack('<HH', header, color)
            s_blits.append(s)

    # save header
    add_record(f,'header',struct.pack("<2I",w,frame_height)) # 1 frame for now

    # write data
    add_record(f,'rle',''.join(s_blits))

    # line16 record
    add_record(f,'line16',struct.pack("%dH"%len(line16),*line16))

    # finish file
    add_record(f,'end','')

    size=f.tell()

    print '// %d bytes (%d/1M), reduction by %.1f'%(size,1024*1024/size,2*float(w)*h/size)
def image_encode(src, f, frame_height, quality):
    def err(i):
        "error function"
        f = 1 / (1. + quality * 254)
        t = rgba(i)
        c2 = (int(int(t[0] * f) / f), int(int(t[1] * f) / f),
              int(int(t[2] * f) / f), t[3])
        return reduce(c2)

    data = [reduce(c)
            for c in src.getdata()]  # keep image in RAM as RGBA tuples.
    w, h = src.size

    s_blits = []  # stringified blits for all image

    start_file = f.tell()
    line16 = []  # offsets from start as u16 index on  words

    for y in range(h):
        if y % 16 == 0:
            ofs = sum(len(x) for x in s_blits)
            line16.append(ofs / 4)  # XXX use /4 but need to align

        skipped = 0
        blits = []

        line = data[y * w:(y + 1) * w]  # 16 bit data
        singles = []
        for c, g in groupby(line, key=err):
            t = tuple(g)
            n = len(t)
            # take the most frequent reral color
            cnt = Counter(t)
            col = cnt.most_common(1)[0][0]

            blits.append([n, col, False])

        # set EOL
        if blits:
            blits[-1][2] = True
        else:
            blits.append([0, [], True])

        # now encode line : (header + blit) x n
        for num, color, eol in blits:
            header = (num << 3) | (1 if eol else 0)
            s = struct.pack('<HH', header, color)
            s_blits.append(s)

    # save header
    add_record(f, 'header', struct.pack("<2I", w,
                                        frame_height))  # 1 frame for now

    # write data
    add_record(f, 'rle', ''.join(s_blits))

    # line16 record
    add_record(f, 'line16', struct.pack("%dH" % len(line16), *line16))

    # finish file
    add_record(f, 'end', '')

    size = f.tell()

    print '// %d bytes (%d/1M), reduction by %.1f' % (size, 1024 * 1024 / size,
                                                      2 * float(w) * h / size)