-import bpy, blf, math, gpu, os
+import bpy, blf, math, gpu, os, time
import cProfile
+import numpy as np
from ctypes import *
from mathutils import *
from gpu_extras.batch import batch_for_shader
bpy.types.SpaceView3D.draw_handler_remove(cv_view_pixel_handler,'WINDOW')
#}
-# ---------------------------------------------------------------------------- #
-# #
-# QOI encoder #
-# #
-# ---------------------------------------------------------------------------- #
-# #
-# Transliteration of: #
-# https://github.com/phoboslab/qoi/blob/master/qoi.h #
-# #
-# Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org #
-# SPDX-License-Identifier: MIT #
-# QOI - The "Quite OK Image" format for fast, lossless image compression #
-# #
-# ---------------------------------------------------------------------------- #
-
-class qoi_rgba_t(Structure):
-#{
- _pack_ = 1
- _fields_ = [("r",c_uint8),
- ("g",c_uint8),
- ("b",c_uint8),
- ("a",c_uint8)]
-#}
-
-QOI_OP_INDEX = 0x00 # 00xxxxxx
-QOI_OP_DIFF = 0x40 # 01xxxxxx
-QOI_OP_LUMA = 0x80 # 10xxxxxx
-QOI_OP_RUN = 0xc0 # 11xxxxxx
-QOI_OP_RGB = 0xfe # 11111110
-QOI_OP_RGBA = 0xff # 11111111
-
-QOI_MASK_2 = 0xc0 # 11000000
-
-def qoi_colour_hash( c ):
-#{
- return c.r*3 + c.g*5 + c.b*7 + c.a*11
-#}
-
-def qoi_eq( a, b ):
-#{
- return (a.r==b.r) and (a.g==b.g) and (a.b==b.b) and (a.a==b.a)
-#}
-
-def qoi_32bit( v ):
-#{
- return bytearray([ (0xff000000 & v) >> 24, \
- (0x00ff0000 & v) >> 16, \
- (0x0000ff00 & v) >> 8, \
- (0x000000ff & v) ])
-#}
+qoi_lib = None
+qoi_encode_rgbaf32 = None
+qoi_free = None
def qoi_encode( img ):
#{
- data = bytearray()
+ global qoi_lib
+ global qoi_encode_rgbaf32
+ global qoi_free
+ if not qoi_lib:
+ #{
+ ext = '.dll' if os.name=='nt' else '.so'
+ path = F'{os.path.dirname(__file__)}/qoi{ext}'
+ qoi_lib = cdll.LoadLibrary( path )
+ qoi_encode_rgbaf32 = qoi_lib.qoi_encode_rgbaf32
+ qoi_encode_rgbaf32.argtypes = \
+ [ np.ctypeslib.ndpointer(dtype=np.float32,\
+ ndim=1,\
+ flags='C_CONTIGUOUS'), \
+ c_uint32, c_uint32, POINTER(c_int32) ]
+ qoi_encode_rgbaf32.restype = POINTER(c_uint8)
+
+ qoi_free = qoi_lib.qoi_free
+ qoi_free.argtypes = [ POINTER(c_uint8) ]
+ #}
+
print(F"{' ':<30}",end='\r')
print(F"[QOI] Encoding {img.name}.qoi[{img.size[0]},{img.size[1]}]",end='\r')
- 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' )
+ crab = np.asarray(img.pixels, dtype=np.float32)
+ cock = c_int()
+ comped = qoi_encode_rgbaf32( crab, img.size[0], img.size[1], byref(cock) )
+ end = time.time()
- return data
+ bingo = bytearray(comped[:cock.value])
+ bytearray_align_to( bingo, 16, b'\x00' )
+ qoi_free( comped )
+ return bingo
#}
vg_compile_project( proj );
}
+void compile_tools( struct vg_env *env, struct vg_project *proj )
+{
+ struct vg_env backup = *env;
+ env->optimization = 3; /* force optimization always */
+ env->debug_asan = 0;
+
+ vg_project_new_target( proj, "tools/qoi", k_obj_type_shared );
+ vg_add_source( proj, "qoi_lib.c " );
+ vg_compile_project( proj );
+
+ *env = backup;
+}
+
/*
* Scripts
* -------------------------------------------------------------------------- */
-void s_release_all(void){
+void s_release_all(void)
+{
vg_info( "running script: s_release_all(void)\n" );
struct vg_project content_proj, windows_proj, linux_proj;
env.platform = k_platform_windows;
vg_project_init( &windows_proj, &env, "skaterift" );
build_game_bin( &windows_proj );
+ compile_tools( &env, &windows_proj );
/* binaries for linux */
env = vg_release_env;
env.platform = k_platform_linux;
vg_project_init( &linux_proj, &env, "skaterift" );
build_game_bin( &linux_proj );
+ compile_tools( &env, &linux_proj );
/* package them up for storage */
vg_tarball_project( &content_proj );
vg_project_init( &test_proj, &vg_test_env, "skaterift-test" );
build_game_bin( &test_proj );
+ compile_tools( &vg_test_env, &test_proj );
build_game_content( &test_proj );
vg_add_blob( &test_proj, "steam_appid.txt", "" );
}