- index = [ qoi_rgba_t() for _ in range(64) ]
-
- # Header
- #
- data.extend( bytearray(c_uint32(0x66696f71)) )
- data.extend( qoi_32bit( img.size[0] ) )
- data.extend( qoi_32bit( img.size[1] ) )
- data.extend( bytearray(c_uint8(4)) )
- data.extend( bytearray(c_uint8(0)) )
-
- run = 0
- px_prev = qoi_rgba_t()
- px_prev.r = c_uint8(0)
- px_prev.g = c_uint8(0)
- px_prev.b = c_uint8(0)
- px_prev.a = c_uint8(255)
-
- px = qoi_rgba_t()
- px.r = c_uint8(0)
- px.g = c_uint8(0)
- px.b = c_uint8(0)
- px.a = c_uint8(255)
-
- px_len = img.size[0] * img.size[1]
- paxels = [ int(min(max(_,0),1)*255) for _ in img.pixels ]
-
- for px_pos in range( px_len ): #{
- idx = px_pos * img.channels
- nc = img.channels-1
-
- px.r = paxels[idx+min(0,nc)]
- px.g = paxels[idx+min(1,nc)]
- px.b = paxels[idx+min(2,nc)]
- px.a = paxels[idx+min(3,nc)]
-
- if qoi_eq( px, px_prev ): #{
- run += 1
-
- if (run == 62) or (px_pos == px_len-1): #{
- data.extend( bytearray( c_uint8(QOI_OP_RUN | (run-1))) )
- run = 0
- #}
- #}
- else: #{
- if run > 0: #{
- data.extend( bytearray( c_uint8(QOI_OP_RUN | (run-1))) )
- run = 0
- #}
-
- index_pos = qoi_colour_hash(px) % 64
-
- if qoi_eq( index[index_pos], px ): #{
- data.extend( bytearray( c_uint8(QOI_OP_INDEX | index_pos)) )
- #}
- else: #{
- index[ index_pos ].r = px.r
- index[ index_pos ].g = px.g
- index[ index_pos ].b = px.b
- index[ index_pos ].a = px.a
-
- if px.a == px_prev.a: #{
- vr = int(px.r) - int(px_prev.r)
- vg = int(px.g) - int(px_prev.g)
- vb = int(px.b) - int(px_prev.b)
-
- vg_r = vr - vg
- vg_b = vb - vg
-
- if (vr > -3) and (vr < 2) and\
- (vg > -3) and (vg < 2) and\
- (vb > -3) and (vb < 2):
- #{
- op = QOI_OP_DIFF | (vr+2) << 4 | (vg+2) << 2 | (vb+2)
- data.extend( bytearray( c_uint8(op) ))
- #}
- elif (vg_r > -9) and (vg_r < 8) and\
- (vg > -33) and (vg < 32 ) and\
- (vg_b > -9) and (vg_b < 8):
- #{
- op = QOI_OP_LUMA | (vg+32)
- delta = (vg_r+8) << 4 | (vg_b + 8)
- data.extend( bytearray( c_uint8(op) ) )
- data.extend( bytearray( c_uint8(delta) ))
- #}
- else: #{
- data.extend( bytearray( c_uint8(QOI_OP_RGB) ) )
- data.extend( bytearray( c_uint8(px.r) ))
- data.extend( bytearray( c_uint8(px.g) ))
- data.extend( bytearray( c_uint8(px.b) ))
- #}
- #}
- else: #{
- data.extend( bytearray( c_uint8(QOI_OP_RGBA) ) )
- data.extend( bytearray( c_uint8(px.r) ))
- data.extend( bytearray( c_uint8(px.g) ))
- data.extend( bytearray( c_uint8(px.b) ))
- data.extend( bytearray( c_uint8(px.a) ))
- #}
- #}
- #}
-
- px_prev.r = px.r
- px_prev.g = px.g
- px_prev.b = px.b
- px_prev.a = px.a
- #}
-
- # Padding
- for i in range(7):
- data.extend( bytearray( c_uint8(0) ))
- data.extend( bytearray( c_uint8(1) ))
- bytearray_align_to( data, 16, b'\x00' )