diff options
Diffstat (limited to '')
-rw-r--r-- | src/libcoopgamma.py | 86 | ||||
-rw-r--r-- | src/libcoopgamma_native.pyx.gpp | 160 | ||||
-rwxr-xr-x | src/test | 88 |
3 files changed, 315 insertions, 19 deletions
diff --git a/src/libcoopgamma.py b/src/libcoopgamma.py index 3519881..c09c59e 100644 --- a/src/libcoopgamma.py +++ b/src/libcoopgamma.py @@ -31,6 +31,22 @@ class Support(enum.IntEnum): NO = 0 MAYBE = 1 YES = 2 + + @staticmethod + def str(v): + ''' + Get string representation of a value + + @param v:int The value, must be value of the enum + @return :str Human-readable string representation of the value + ''' + if v == Support.NO: + return 'no' + if v == Support.YES: + return 'yes' + if v == Support.MAYBE: + return 'maybe' + raise ValueError() class Depth(enum.IntEnum): @@ -53,6 +69,28 @@ class Depth(enum.IntEnum): UINT64 = 64 FLOAT = -1 DOUBLE = -2 + + @staticmethod + def str(v): + ''' + Get string representation of a value + + @param v:int The value, must be value of the enum + @return :str Human-readable string representation of the value + ''' + if v == Depth.UINT8: + return '8-bits' + if v == Depth.UINT16: + return '16-bits' + if v == Depth.UINT32: + return '326-bits' + if v == Depth.UINT64: + return '64-bits' + if v == Depth.FLOAT: + return 'single-precision floating-point' + if v == Depth.DOUBLE: + return 'double-precision floating-point' + raise ValueError() class Lifespan(enum.IntEnum): @@ -66,6 +104,22 @@ class Lifespan(enum.IntEnum): REMOVE = 0 UNTIL_DEATH = 1 UNTIL_REMOVAL = 2 + + @staticmethod + def str(v): + ''' + Get string representation of a value + + @param v:int The value, must be value of the enum + @return :str Human-readable string representation of the value + ''' + if v == Lifespan.REMOVE: + return 'remove' + if v == Lifespan.UNTIL_DEATH: + return 'until death' + if v == Lifespan.UNTIL_REMOVAL: + return 'until removal' + raise ValueError() class Colourspace(enum.IntEnum): @@ -83,6 +137,26 @@ class Colourspace(enum.IntEnum): RGB = 2 NON_RGB = 3 GREY = 4 + + @staticmethod + def str(v): + ''' + Get string representation of a value + + @param v:int The value, must be value of the enum + @return :str Human-readable string representation of the value + ''' + if v == Colourspace.UNKNOWN: + return 'unknown' + if v == Colourspace.SRGB: + return 'sRGB' + if v == Colourspace.RGB: + return 'RGB' + if v == Colourspace.NON_RGB: + return 'non-RGB' + if v == Colourspace.GREY: + return 'greyscale' + raise ValueError() class Ramps: @@ -223,6 +297,14 @@ class GamutPoint: ''' params = (self.x_raw, self.y_raw) return 'libcoopgamma.GamutPoint(%s)' % ', '.join(repr(p) for p in params) + + def __str__(self): + ''' + Get human-readable string representation of instance + + @return :str Human-readable string representation of instance + ''' + return '(%f, %f)' % (self.x, self.y) class Gamut: @@ -409,9 +491,9 @@ class QueriedFilter: ''' self.priority = priority self.fclass = fclass + self.ramps = None if ramps is not None: self.ramps = Ramps(*ramps) if isinstance(ramps, tuple) else ramps - self.ramps = None def clone(self, shallow = False): ''' @@ -553,7 +635,7 @@ class ErrorReport: error = ErrorReport(*error) if not error.custom and not error.server_side: import os - return OSError(error.number, os.strerror(error)) + return OSError(error.number, os.strerror(error.number)) else: return LibcoopgammaError(error) diff --git a/src/libcoopgamma_native.pyx.gpp b/src/libcoopgamma_native.pyx.gpp index 694e8f5..5c6b796 100644 --- a/src/libcoopgamma_native.pyx.gpp +++ b/src/libcoopgamma_native.pyx.gpp @@ -1476,7 +1476,7 @@ def libcoopgamma_native_get_gamma_recv(address : int, async : int): cdef libcoopgamma_filter_table_t table cdef bytes bs cdef libcoopgamma_ramps_t* rampsp - cdef bytes fclass + cdef char* fclass try: if libcoopgamma_filter_table_initialise(&table) < 0: return int(errno) @@ -1488,9 +1488,9 @@ def libcoopgamma_native_get_gamma_recv(address : int, async : int): ret = (False, (int(ctx.error.number), ctx.error.custom != 0, ctx.error.server_side != 0, desc)) else: filters = [None] * int(table.filter_count) - for i in range(int(table.filter_count)): - rampsp = &(table.filters[i].ramps) - fclass = table.filters[i].fclass + for j in range(int(table.filter_count)): + rampsp = &(table.filters[j].ramps) + fclass = table.filters[j].fclass red = [None] * rampsp.u_red_size green = [None] * rampsp.u_green_size blue = [None] * rampsp.u_blue_size @@ -1536,8 +1536,12 @@ def libcoopgamma_native_get_gamma_recv(address : int, async : int): green[i] = (<uint64_t*>(rampsp.u_green))[i] for i in range(rampsp.u_blue_size): blue[i] = (<uint64_t*>(rampsp.u_blue))[i] - ramps = (rampsp.u_red_size, rampsp.u_green_size, rampsp.u_blue_size, red, green, blue) - filters[i] = (int(table.filters[i].priority), fclass.decode('utf-8', 'strict'), ramps) + ramps = (red, green, blue) + pclass = None + if fclass is not NULL: + bs = fclass + pclass = bs.decode('utf-8', 'strict') + filters[j] = (int(table.filters[j].priority), pclass, ramps) ret = (True, (int(table.red_size), int(table.green_size), int(table.blue_size), int(table.depth), filters)) finally: @@ -1565,7 +1569,7 @@ def libcoopgamma_native_get_gamma_sync(query, address : int): cdef libcoopgamma_filter_query_t qry cdef bytes bs cdef libcoopgamma_ramps_t* rampsp - cdef bytes fclass + cdef char* fclass crtc_bs = query.crtc.encode('utf-8') + bytes([0]) qry.high_priority = <int64_t>(query.high_priority) qry.low_priority = <int64_t>(query.low_priority) @@ -1589,9 +1593,9 @@ def libcoopgamma_native_get_gamma_sync(query, address : int): ret = (False, (int(ctx.error.number), ctx.error.custom != 0, ctx.error.server_side != 0, desc)) else: filters = [None] * int(table.filter_count) - for i in range(int(table.filter_count)): - rampsp = &(table.filters[i].ramps) - fclass = table.filters[i].fclass + for j in range(int(table.filter_count)): + rampsp = &(table.filters[j].ramps) + fclass = table.filters[j].fclass red = [None] * rampsp.u_red_size green = [None] * rampsp.u_green_size blue = [None] * rampsp.u_blue_size @@ -1637,8 +1641,12 @@ def libcoopgamma_native_get_gamma_sync(query, address : int): green[i] = (<uint64_t*>(rampsp.u_green))[i] for i in range(rampsp.u_blue_size): blue[i] = (<uint64_t*>(rampsp.u_blue))[i] - ramps = (rampsp.u_red_size, rampsp.u_green_size, rampsp.u_blue_size, red, green, blue) - filters[i] = (int(table.filters[i].priority), fclass.decode('utf-8', 'strict'), ramps) + ramps = (red, green, blue) + pclass = None + if fclass is not NULL: + bs = fclass + pclass = bs.decode('utf-8', 'strict') + filters[j] = (int(table.filters[j].priority), pclass, ramps) ret = (True, (int(table.red_size), int(table.green_size), int(table.blue_size), int(table.depth), filters)) finally: @@ -1648,6 +1656,116 @@ def libcoopgamma_native_get_gamma_sync(query, address : int): return ret +def libcoopgamma_native_copy_ramps(intptr_t dest_address, src, libcoopgamma_depth_t depth): + ''' + Copy a Python ramp-trio into C ramp-trio + + @param dest_address:intptr_t The address of the C ramp-trio + @param src:Ramps The Python ramp-trio + @param depth:libcoopgamma_depth_t The data type of the ramp stops + ''' + cdef libcoopgamma_ramps_t* dest = <libcoopgamma_ramps_t*><void*><intptr_t>dest_address + cdef uint8_t* r8 + cdef uint8_t* g8 + cdef uint8_t* b8 + cdef uint16_t* r16 + cdef uint16_t* g16 + cdef uint16_t* b16 + cdef uint32_t* r32 + cdef uint32_t* g32 + cdef uint32_t* b32 + cdef uint64_t* r64 + cdef uint64_t* g64 + cdef uint64_t* b64 + cdef float* rf + cdef float* gf + cdef float* bf + cdef double* rd + cdef double* gd + cdef double* bd + cdef size_t rn = <size_t>len(src.red) + cdef size_t gn = <size_t>len(src.green) + cdef size_t bn = <size_t>len(src.blue) + if depth == 8: + r8 = <uint8_t*>malloc((rn + gn + bn) * sizeof(uint8_t)) + g8 = r8 + rn + b8 = g8 + gn + for i in range(int(rn)): + r8[i] = <uint8_t>(src.red[i]) + for i in range(int(gn)): + g8[i] = <uint8_t>(src.green[i]) + for i in range(int(bn)): + b8[i] = <uint8_t>(src.blue[i]) + dest.u_red = <void*>r8 + dest.u_green = <void*>g8 + dest.u_blue = <void*>b8 + elif depth == 16: + r16 = <uint16_t*>malloc((rn + gn + bn) * sizeof(uint16_t)) + g16 = r16 + rn + b16 = g16 + gn + for i in range(int(rn)): + r16[i] = <uint16_t>(src.red[i]) + for i in range(int(gn)): + g16[i] = <uint16_t>(src.green[i]) + for i in range(int(bn)): + b16[i] = <uint16_t>(src.blue[i]) + dest.u_red = <void*>r16 + dest.u_green = <void*>g16 + dest.u_blue = <void*>b16 + elif depth == 32: + r32 = <uint32_t*>malloc((rn + gn + bn) * sizeof(uint32_t)) + g32 = r32 + rn + b32 = g32 + gn + for i in range(int(rn)): + r32[i] = <uint32_t>(src.red[i]) + for i in range(int(gn)): + g32[i] = <uint32_t>(src.green[i]) + for i in range(int(bn)): + b32[i] = <uint32_t>(src.blue[i]) + dest.u_red = <void*>r32 + dest.u_green = <void*>g32 + dest.u_blue = <void*>b32 + elif depth == 64: + r64 = <uint64_t*>malloc((rn + gn + bn) * sizeof(uint64_t)) + g64 = r64 + rn + b64 = g64 + gn + for i in range(int(rn)): + r64[i] = <uint64_t>(src.red[i]) + for i in range(int(gn)): + g64[i] = <uint64_t>(src.green[i]) + for i in range(int(bn)): + b64[i] = <uint64_t>(src.blue[i]) + dest.u_red = <void*>r64 + dest.u_green = <void*>g64 + dest.u_blue = <void*>b64 + elif depth == -1: + rf = <float*>malloc((rn + gn + bn) * sizeof(float)) + gf = rf + rn + bf = gf + gn + for i in range(int(rn)): + rf[i] = <float>(src.red[i]) + for i in range(int(gn)): + gf[i] = <float>(src.green[i]) + for i in range(int(bn)): + bf[i] = <float>(src.blue[i]) + dest.u_red = <void*>rf + dest.u_green = <void*>gf + dest.u_blue = <void*>bf + else: + rd = <double*>malloc((rn + gn + bn) * sizeof(double)) + gd = rd + rn + bd = gd + gn + for i in range(int(rn)): + rd[i] = <double>(src.red[i]) + for i in range(int(gn)): + gd[i] = <double>(src.green[i]) + for i in range(int(bn)): + bd[i] = <double>(src.blue[i]) + dest.u_red = <void*>rd + dest.u_green = <void*>gd + dest.u_blue = <void*>bd + + def libcoopgamma_native_set_gamma_send(filtr, address : int, async : int): ''' Apply, update, or remove a gamma ramp adjustment, send request part @@ -1670,8 +1788,14 @@ def libcoopgamma_native_set_gamma_send(filtr, address : int, async : int): flr.lifespan = <libcoopgamma_lifespan_t>(filtr.lifespan) flr.depth = <libcoopgamma_depth_t>(filtr.depth) flr.fclass = NULL - flr.crtc = <char*>malloc(len(crtc_bs) * sizeof(char)) + flr.crtc = NULL + flr.ramps.u_red_size = len(filtr.ramps.red) + flr.ramps.u_green_size = len(filtr.ramps.green) + flr.ramps.u_blue_size = len(filtr.ramps.blue) + flr.ramps.u_red = NULL try: + libcoopgamma_native_copy_ramps(<intptr_t><void*>&(flr.ramps), filtr.ramps, flr.depth) + flr.crtc = <char*>malloc(len(crtc_bs) * sizeof(char)) if flr.crtc is NULL: return int(errno) flr.fclass = <char*>malloc(len(clss_bs) * sizeof(char)) @@ -1686,6 +1810,7 @@ def libcoopgamma_native_set_gamma_send(filtr, address : int, async : int): finally: free(flr.crtc) free(flr.fclass) + free(flr.ramps.u_red) return 0 @@ -1736,8 +1861,14 @@ def libcoopgamma_native_set_gamma_sync(filtr, address : int): flr.lifespan = <libcoopgamma_lifespan_t>(filtr.lifespan) flr.depth = <libcoopgamma_depth_t>(filtr.depth) flr.fclass = NULL - flr.crtc = <char*>malloc(len(crtc_bs) * sizeof(char)) + flr.crtc = NULL + flr.ramps.u_red_size = len(filtr.ramps.red) + flr.ramps.u_green_size = len(filtr.ramps.green) + flr.ramps.u_blue_size = len(filtr.ramps.blue) + flr.ramps.u_red = NULL try: + libcoopgamma_native_copy_ramps(<intptr_t><void*>&(flr.ramps), filtr.ramps, flr.depth) + flr.crtc = <char*>malloc(len(crtc_bs) * sizeof(char)) if flr.crtc is NULL: return int(errno) flr.fclass = <char*>malloc(len(clss_bs) * sizeof(char)) @@ -1756,5 +1887,6 @@ def libcoopgamma_native_set_gamma_sync(filtr, address : int): finally: free(flr.crtc) free(flr.fclass) + free(flr.ramps.u_red) return None @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this library. If not, see <http://www.gnu.org/licenses/>. ''' -import os, sys +import os, sys, time os.chdir('/'.join(sys.argv[0].split('/')[:-1])) sys.path.append('../bin') @@ -65,8 +65,90 @@ for crtc in g.get_crtcs_sync(): print(crtc) print() -print(g.get_gamma_info_sync(crtc)) -print(g.get_gamma_sync(cg.FilterQuery(crtc = crtc))) +info = g.get_gamma_info_sync(crtc) +print('\033[1m%s:\033[m' % 'CRTC info') +print('Cooperative:', 'yes' if info.cooperative else 'no') +if info.depth is not None: + print('Depth:', cg.Depth.str(info.depth)) +print('Supported:', cg.Support.str(info.supported)) +if info.red_size is not None: + print('Red stops:', info.red_size) +if info.green_size is not None: + print('Green stops:', info.green_size) +if info.blue_size is not None: + print('Blue stops:', info.blue_size) +print('Colourspace:', cg.Colourspace.str(info.colourspace)) +if info.gamut is not None: + print('Red point:', str(info.gamut.red)) + print('Green point:', str(info.gamut.green)) + print('Blue point:', str(info.gamut.blue)) + print('White point:', str(info.gamut.white)) +print() + +table = g.get_gamma_sync(cg.FilterQuery(crtc = crtc, coalesce = False)) +print('\033[1m%s:\033[m' % 'Filter table') +print('Red stops:', table.red_size) +print('Green stops:', table.green_size) +print('Blue stops:', table.blue_size) +print('Depth:', cg.Depth.str(table.depth)) +for i, fltr in enumerate(table.filters): + print('Filter %i:' % i) + print(' Priority:', fltr.priority) + print(' Class:', fltr.fclass) + print(' Ramps:') + rr, gr, br = fltr.ramps.red, fltr.ramps.green, fltr.ramps.blue + n = max(len(rr), len(gr), len(br)) + fmt = ' \033[31m%s \033[32m%s \033[34m%s\033[m' + rr = [str(rr[i]) if i < len(rr) else '' for i in range(n)] + gr = [str(gr[i]) if i < len(gr) else '' for i in range(n)] + br = [str(br[i]) if i < len(br) else '' for i in range(n)] + for y in zip(rr, gr, br): + print(fmt % y) +print() + +table = g.get_gamma_sync(cg.FilterQuery(crtc = crtc, coalesce = True)) +print('\033[1m%s:\033[m' % 'Filter table') +print('Red stops:', table.red_size) +print('Green stops:', table.green_size) +print('Blue stops:', table.blue_size) +print('Depth:', cg.Depth.str(table.depth)) +for fltr in table.filters: + print('Ramps:') + rr, gr, br = fltr.ramps.red, fltr.ramps.green, fltr.ramps.blue + n = max(len(rr), len(gr), len(br)) + fmt = ' \033[31m%s \033[32m%s \033[34m%s\033[m' + rr = [str(rr[i]) if i < len(rr) else '' for i in range(n)] + gr = [str(gr[i]) if i < len(gr) else '' for i in range(n)] + br = [str(br[i]) if i < len(br) else '' for i in range(n)] + for y in zip(rr, gr, br): + print(fmt % y) +print() + +fltr = cg.Filter(0, crtc, 'pylibcoopgamma::test::test', cg.Lifespan.UNTIL_DEATH, table.depth, + cg.Ramps(table.red_size, table.green_size, table.blue_size)) + +if table.depth < 0: + Y = lambda x : x +else: + m = 2 ** table.depth - 1 + Y = lambda x : int(x * m) + +redzero = fltr.ramps.red +greenzero = fltr.ramps.green + +fltr.ramps.red = [Y(x / (table.red_size - 1)) for x in range(table.red_size)] +g.set_gamma_sync(fltr) +time.sleep(0.5) + +fltr.ramps.red = redzero +fltr.ramps.green = [Y(x / (table.green_size - 1)) for x in range(table.green_size)] +g.set_gamma_sync(fltr) +time.sleep(0.5) + +fltr.ramps.green = greenzero +fltr.ramps.blue = [Y(x / (table.blue_size - 1)) for x in range(table.blue_size)] +g.set_gamma_sync(fltr) +time.sleep(0.5) del g |