1#!/usr/bin/env python 2# 3# Copyright (c) 2014-2020 Hayaki Saito 4# 5# Permission is hereby granted, free of charge, to any person obtaining a copy of 6# this software and associated documentation files (the "Software"), to deal in 7# the Software without restriction, including without limitation the rights to 8# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9# the Software, and to permit persons to whom the Software is furnished to do so, 10# subject to the following conditions: 11# 12# The above copyright notice and this permission notice shall be included in all 13# copies or substantial portions of the Software. 14# 15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21# 22 23from ctypes import cdll, c_void_p, c_int, c_byte, c_char_p, POINTER, byref, CFUNCTYPE, string_at 24from ctypes.util import find_library 25 26# limitations 27SIXEL_OUTPUT_PACKET_SIZE = 16384 28SIXEL_PALETTE_MIN = 2 29SIXEL_PALETTE_MAX = 256 30SIXEL_USE_DEPRECATED_SYMBOLS = 1 31SIXEL_ALLOCATE_BYTES_MAX = 10248 * 1024 * 128 # up to 128M 32SIXEL_WIDTH_LIMIT = 1000000 33SIXEL_HEIGHT_LIMIT = 1000000 34 35# loader settings 36SIXEL_DEFALUT_GIF_DELAY = 1 37 38# return value 39SIXEL_OK = 0x0000 40SIXEL_FALSE = 0x1000 41 42# error codes 43SIXEL_RUNTIME_ERROR = (SIXEL_FALSE | 0x0100) # runtime error 44SIXEL_LOGIC_ERROR = (SIXEL_FALSE | 0x0200) # logic error 45SIXEL_FEATURE_ERROR = (SIXEL_FALSE | 0x0300) # feature not enabled 46SIXEL_LIBC_ERROR = (SIXEL_FALSE | 0x0400) # errors caused by curl 47SIXEL_CURL_ERROR = (SIXEL_FALSE | 0x0500) # errors occures in libc functions 48SIXEL_JPEG_ERROR = (SIXEL_FALSE | 0x0600) # errors occures in libjpeg functions 49SIXEL_PNG_ERROR = (SIXEL_FALSE | 0x0700) # errors occures in libpng functions 50SIXEL_GDK_ERROR = (SIXEL_FALSE | 0x0800) # errors occures in gdk functions 51SIXEL_GD_ERROR = (SIXEL_FALSE | 0x0900) # errors occures in gd functions 52SIXEL_STBI_ERROR = (SIXEL_FALSE | 0x0a00) # errors occures in stb_image functions 53SIXEL_STBIW_ERROR = (SIXEL_FALSE | 0x0b00) # errors occures in stb_image_write functions 54 55SIXEL_INTERRUPTED = (SIXEL_OK | 0x0001) # interrupted by a signal 56 57SIXEL_BAD_ALLOCATION = (SIXEL_RUNTIME_ERROR | 0x0001) # malloc() failed 58SIXEL_BAD_ARGUMENT = (SIXEL_RUNTIME_ERROR | 0x0002) # bad argument detected 59SIXEL_BAD_INPUT = (SIXEL_RUNTIME_ERROR | 0x0003) # bad input detected 60SIXEL_BAD_INTEGER_OVERFLOW = (SIXEL_RUNTIME_ERROR | 0x0004) # integer overflow 61 62SIXEL_NOT_IMPLEMENTED = (SIXEL_FEATURE_ERROR | 0x0001) # feature not implemented 63 64def SIXEL_SUCCEEDED(status): 65 return (((status) & 0x1000) == 0) 66 67def SIXEL_FAILED(status): 68 return (((status) & 0x1000) != 0) 69 70# method for finding the largest dimension for splitting, 71# and sorting by that component 72SIXEL_LARGE_AUTO = 0x0 # choose automatically the method for finding the largest dimension 73SIXEL_LARGE_NORM = 0x1 # simply comparing the range in RGB space 74SIXEL_LARGE_LUM = 0x2 # transforming into luminosities before the comparison 75 76# method for choosing a color from the box 77SIXEL_REP_AUTO = 0x0 # choose automatically the method for selecting representative color from each box 78SIXEL_REP_CENTER_BOX = 0x1 # choose the center of the box 79SIXEL_REP_AVERAGE_COLORS = 0x2 # choose the average all the color in the box (specified in Heckbert's paper) 80SIXEL_REP_AVERAGE_PIXELS = 0x3 # choose the average all the pixels in the box 81 82# method for diffusing 83SIXEL_DIFFUSE_AUTO = 0x0 # choose diffusion type automatically 84SIXEL_DIFFUSE_NONE = 0x1 # don't diffuse 85SIXEL_DIFFUSE_ATKINSON = 0x2 # diffuse with Bill Atkinson's method 86SIXEL_DIFFUSE_FS = 0x3 # diffuse with Floyd-Steinberg method 87SIXEL_DIFFUSE_JAJUNI = 0x4 # diffuse with Jarvis, Judice & Ninke method 88SIXEL_DIFFUSE_STUCKI = 0x5 # diffuse with Stucki's method 89SIXEL_DIFFUSE_BURKES = 0x6 # diffuse with Burkes' method 90SIXEL_DIFFUSE_A_DITHER = 0x7 # positionally stable arithmetic dither 91SIXEL_DIFFUSE_X_DITHER = 0x8 # positionally stable arithmetic xor based dither 92 93# quality modes 94SIXEL_QUALITY_AUTO = 0x0 # choose quality mode automatically 95SIXEL_QUALITY_HIGH = 0x1 # high quality palette construction 96SIXEL_QUALITY_LOW = 0x2 # low quality palette construction 97SIXEL_QUALITY_FULL = 0x3 # full quality palette construction 98SIXEL_QUALITY_HIGHCOLOR = 0x4 # high color 99 100# built-in dither 101SIXEL_BUILTIN_MONO_DARK = 0x0 # monochrome terminal with dark background 102SIXEL_BUILTIN_MONO_LIGHT = 0x1 # monochrome terminal with light background 103SIXEL_BUILTIN_XTERM16 = 0x2 # xterm 16color 104SIXEL_BUILTIN_XTERM256 = 0x3 # xterm 256color 105SIXEL_BUILTIN_VT340_MONO = 0x4 # vt340 monochrome 106SIXEL_BUILTIN_VT340_COLOR = 0x5 # vt340 color 107SIXEL_BUILTIN_G1 = 0x6 # 1bit grayscale 108SIXEL_BUILTIN_G2 = 0x7 # 2bit grayscale 109SIXEL_BUILTIN_G4 = 0x8 # 4bit grayscale 110SIXEL_BUILTIN_G8 = 0x9 # 8bit grayscale 111 112# offset value of pixelFormat 113SIXEL_FORMATTYPE_COLOR = (0) 114SIXEL_FORMATTYPE_GRAYSCALE = (1 << 6) 115SIXEL_FORMATTYPE_PALETTE = (1 << 7) 116 117# pixelformat type of input image 118# NOTE: for compatibility, the value of PIXELFORAMT_COLOR_RGB888 must be 3 119SIXEL_PIXELFORMAT_RGB555 = (SIXEL_FORMATTYPE_COLOR | 0x01) # 15bpp 120SIXEL_PIXELFORMAT_RGB565 = (SIXEL_FORMATTYPE_COLOR | 0x02) # 16bpp 121SIXEL_PIXELFORMAT_RGB888 = (SIXEL_FORMATTYPE_COLOR | 0x03) # 24bpp 122SIXEL_PIXELFORMAT_BGR555 = (SIXEL_FORMATTYPE_COLOR | 0x04) # 15bpp 123SIXEL_PIXELFORMAT_BGR565 = (SIXEL_FORMATTYPE_COLOR | 0x05) # 16bpp 124SIXEL_PIXELFORMAT_BGR888 = (SIXEL_FORMATTYPE_COLOR | 0x06) # 24bpp 125SIXEL_PIXELFORMAT_ARGB8888 = (SIXEL_FORMATTYPE_COLOR | 0x10) # 32bpp 126SIXEL_PIXELFORMAT_RGBA8888 = (SIXEL_FORMATTYPE_COLOR | 0x11) # 32bpp 127SIXEL_PIXELFORMAT_ABGR8888 = (SIXEL_FORMATTYPE_COLOR | 0x12) # 32bpp 128SIXEL_PIXELFORMAT_BGRA8888 = (SIXEL_FORMATTYPE_COLOR | 0x13) # 32bpp 129SIXEL_PIXELFORMAT_G1 = (SIXEL_FORMATTYPE_GRAYSCALE | 0x00) # 1bpp grayscale 130SIXEL_PIXELFORMAT_G2 = (SIXEL_FORMATTYPE_GRAYSCALE | 0x01) # 2bpp grayscale 131SIXEL_PIXELFORMAT_G4 = (SIXEL_FORMATTYPE_GRAYSCALE | 0x02) # 4bpp grayscale 132SIXEL_PIXELFORMAT_G8 = (SIXEL_FORMATTYPE_GRAYSCALE | 0x03) # 8bpp grayscale 133SIXEL_PIXELFORMAT_AG88 = (SIXEL_FORMATTYPE_GRAYSCALE | 0x13) # 16bpp gray+alpha 134SIXEL_PIXELFORMAT_GA88 = (SIXEL_FORMATTYPE_GRAYSCALE | 0x23) # 16bpp gray+alpha 135SIXEL_PIXELFORMAT_PAL1 = (SIXEL_FORMATTYPE_PALETTE | 0x00) # 1bpp palette 136SIXEL_PIXELFORMAT_PAL2 = (SIXEL_FORMATTYPE_PALETTE | 0x01) # 2bpp palette 137SIXEL_PIXELFORMAT_PAL4 = (SIXEL_FORMATTYPE_PALETTE | 0x02) # 4bpp palette 138SIXEL_PIXELFORMAT_PAL8 = (SIXEL_FORMATTYPE_PALETTE | 0x03) # 8bpp palette 139 140# palette type 141SIXEL_PALETTETYPE_AUTO = 0 # choose palette type automatically 142SIXEL_PALETTETYPE_HLS = 1 # HLS colorspace 143SIXEL_PALETTETYPE_RGB = 2 # RGB colorspace 144 145# policies of SIXEL encoding 146SIXEL_ENCODEPOLICY_AUTO = 0 # choose encoding policy automatically 147SIXEL_ENCODEPOLICY_FAST = 1 # encode as fast as possible 148SIXEL_ENCODEPOLICY_SIZE = 2 # encode to as small sixel sequence as possible 149 150# method for re-sampling 151SIXEL_RES_NEAREST = 0 # Use nearest neighbor method 152SIXEL_RES_GAUSSIAN = 1 # Use guaussian filter 153SIXEL_RES_HANNING = 2 # Use hanning filter 154SIXEL_RES_HAMMING = 3 # Use hamming filter 155SIXEL_RES_BILINEAR = 4 # Use bilinear filter 156SIXEL_RES_WELSH = 5 # Use welsh filter 157SIXEL_RES_BICUBIC = 6 # Use bicubic filter 158SIXEL_RES_LANCZOS2 = 7 # Use lanczos-2 filter 159SIXEL_RES_LANCZOS3 = 8 # Use lanczos-3 filter 160SIXEL_RES_LANCZOS4 = 9 # Use lanczos-4 filter 161 162# image format 163SIXEL_FORMAT_GIF = 0x0 # read only 164SIXEL_FORMAT_PNG = 0x1 # read/write 165SIXEL_FORMAT_BMP = 0x2 # read only 166SIXEL_FORMAT_JPG = 0x3 # read only 167SIXEL_FORMAT_TGA = 0x4 # read only 168SIXEL_FORMAT_WBMP = 0x5 # read only with --with-gd configure option 169SIXEL_FORMAT_TIFF = 0x6 # read only 170SIXEL_FORMAT_SIXEL = 0x7 # read only 171SIXEL_FORMAT_PNM = 0x8 # read only 172SIXEL_FORMAT_GD2 = 0x9 # read only with --with-gd configure option 173SIXEL_FORMAT_PSD = 0xa # read only 174SIXEL_FORMAT_HDR = 0xb # read only 175 176# loop mode 177SIXEL_LOOP_AUTO = 0 # honer the setting of GIF header 178SIXEL_LOOP_FORCE = 1 # always enable loop 179SIXEL_LOOP_DISABLE = 2 # always disable loop 180 181# setopt flags 182SIXEL_OPTFLAG_INPUT = 'i' # -i, --input: specify input file name. 183SIXEL_OPTFLAG_OUTPUT = 'o' # -o, --output: specify output file name. 184SIXEL_OPTFLAG_OUTFILE = 'o' # -o, --outfile: specify output file name. 185SIXEL_OPTFLAG_7BIT_MODE = '7' # -7, --7bit-mode: for 7bit terminals or printers (default) 186SIXEL_OPTFLAG_8BIT_MODE = '8' # -8, --8bit-mode: for 8bit terminals or printers 187SIXEL_OPTFLAG_COLORS = 'p' # -p COLORS, --colors=COLORS: specify number of colors 188SIXEL_OPTFLAG_MAPFILE = 'm' # -m FILE, --mapfile=FILE: specify set of colors 189SIXEL_OPTFLAG_MONOCHROME = 'e' # -e, --monochrome: output monochrome sixel image 190SIXEL_OPTFLAG_INSECURE = 'k' # -k, --insecure: allow to connect to SSL sites without certs 191SIXEL_OPTFLAG_INVERT = 'i' # -i, --invert: assume the terminal background color 192SIXEL_OPTFLAG_HIGH_COLOR = 'I' # -I, --high-color: output 15bpp sixel image 193SIXEL_OPTFLAG_USE_MACRO = 'u' # -u, --use-macro: use DECDMAC and DEVINVM sequences 194SIXEL_OPTFLAG_MACRO_NUMBER = 'n' # -n MACRONO, --macro-number=MACRONO: 195 # specify macro register number 196SIXEL_OPTFLAG_COMPLEXION_SCORE = 'C' # -C COMPLEXIONSCORE, --complexion-score=COMPLEXIONSCORE: 197 # specify an number argument for the score of 198 # complexion correction. 199SIXEL_OPTFLAG_IGNORE_DELAY = 'g' # -g, --ignore-delay: render GIF animation without delay 200SIXEL_OPTFLAG_STATIC = 'S' # -S, --static: render animated GIF as a static image 201SIXEL_OPTFLAG_DIFFUSION = 'd' # -d DIFFUSIONTYPE, --diffusion=DIFFUSIONTYPE: 202 # choose diffusion method which used with -p option. 203 # DIFFUSIONTYPE is one of them: 204 # auto -> choose diffusion type 205 # automatically (default) 206 # none -> do not diffuse 207 # fs -> Floyd-Steinberg method 208 # atkinson -> Bill Atkinson's method 209 # jajuni -> Jarvis, Judice & Ninke 210 # stucki -> Stucki's method 211 # burkes -> Burkes' method 212 # a_dither -> positionally stable 213 # arithmetic dither 214 # x_dither -> positionally stable 215 # arithmetic xor based dither 216 217SIXEL_OPTFLAG_FIND_LARGEST = 'f' # -f FINDTYPE, --find-largest=FINDTYPE: 218 # choose method for finding the largest 219 # dimension of median cut boxes for 220 # splitting, make sense only when -p 221 # option (color reduction) is 222 # specified 223 # FINDTYPE is one of them: 224 # auto -> choose finding method 225 # automatically (default) 226 # norm -> simply comparing the 227 # range in RGB space 228 # lum -> transforming into 229 # luminosities before the 230 # comparison 231 232SIXEL_OPTFLAG_SELECT_COLOR = 's' # -s SELECTTYPE, --select-color=SELECTTYPE 233 # choose the method for selecting 234 # representative color from each 235 # median-cut box, make sense only 236 # when -p option (color reduction) is 237 # specified 238 # SELECTTYPE is one of them: 239 # auto -> choose selecting 240 # method automatically 241 # (default) 242 # center -> choose the center of 243 # the box 244 # average -> calculate the color 245 # average into the box 246 # histogram -> similar with average 247 # but considers color 248 # histogram 249 250SIXEL_OPTFLAG_CROP = 'c' # -c REGION, --crop=REGION: 251 # crop source image to fit the 252 # specified geometry. REGION should 253 # be formatted as '%dx%d+%d+%d' 254 255SIXEL_OPTFLAG_WIDTH = 'w' # -w WIDTH, --width=WIDTH: 256 # resize image to specified width 257 # WIDTH is represented by the 258 # following syntax 259 # auto -> preserving aspect 260 # ratio (default) 261 # <number>% -> scale width with 262 # given percentage 263 # <number> -> scale width with 264 # pixel counts 265 # <number>px -> scale width with 266 # pixel counts 267 268SIXEL_OPTFLAG_HEIGHT = 'h' # -h HEIGHT, --height=HEIGHT: 269 # resize image to specified height 270 # HEIGHT is represented by the 271 # following syntax 272 # auto -> preserving aspect 273 # ratio (default) 274 # <number>% -> scale height with 275 # given percentage 276 # <number> -> scale height with 277 # pixel counts 278 # <number>px -> scale height with 279 # pixel counts 280 281SIXEL_OPTFLAG_RESAMPLING = 'r' # -r RESAMPLINGTYPE, --resampling=RESAMPLINGTYPE: 282 # choose resampling filter used 283 # with -w or -h option (scaling) 284 # RESAMPLINGTYPE is one of them: 285 # nearest -> Nearest-Neighbor 286 # method 287 # gaussian -> Gaussian filter 288 # hanning -> Hanning filter 289 # hamming -> Hamming filter 290 # bilinear -> Bilinear filter 291 # (default) 292 # welsh -> Welsh filter 293 # bicubic -> Bicubic filter 294 # lanczos2 -> Lanczos-2 filter 295 # lanczos3 -> Lanczos-3 filter 296 # lanczos4 -> Lanczos-4 filter 297 298SIXEL_OPTFLAG_QUALITY = 'q' # -q QUALITYMODE, --quality=QUALITYMODE: 299 # select quality of color 300 # quanlization. 301 # auto -> decide quality mode 302 # automatically (default) 303 # low -> low quality and high 304 # speed mode 305 # high -> high quality and low 306 # speed mode 307 # full -> full quality and careful 308 # speed mode 309 310SIXEL_OPTFLAG_LOOPMODE = 'l' # -l LOOPMODE, --loop-control=LOOPMODE: 311 # select loop control mode for GIF 312 # animation. 313 # auto -> honor the setting of 314 # GIF header (default) 315 # force -> always enable loop 316 # disable -> always disable loop 317 318SIXEL_OPTFLAG_PALETTE_TYPE = 't' # -t PALETTETYPE, --palette-type=PALETTETYPE: 319 # select palette color space type 320 # auto -> choose palette type 321 # automatically (default) 322 # hls -> use HLS color space 323 # rgb -> use RGB color space 324 325SIXEL_OPTFLAG_BUILTIN_PALETTE = 'b' # -b BUILTINPALETTE, --builtin-palette=BUILTINPALETTE: 326 # select built-in palette type 327 # xterm16 -> X default 16 color map 328 # xterm256 -> X default 256 color map 329 # vt340mono -> VT340 monochrome map 330 # vt340color -> VT340 color map 331 # gray1 -> 1bit grayscale map 332 # gray2 -> 2bit grayscale map 333 # gray4 -> 4bit grayscale map 334 # gray8 -> 8bit grayscale map 335 336SIXEL_OPTFLAG_ENCODE_POLICY = 'E' # -E ENCODEPOLICY, --encode-policy=ENCODEPOLICY: 337 # select encoding policy 338 # auto -> choose encoding policy 339 # automatically (default) 340 # fast -> encode as fast as possible 341 # size -> encode to as small sixel 342 # sequence as possible 343 344SIXEL_OPTFLAG_BGCOLOR = 'B' # -B BGCOLOR, --bgcolor=BGCOLOR: 345 # specify background color 346 # BGCOLOR is represented by the 347 # following syntax 348 # #rgb 349 # #rrggbb 350 # #rrrgggbbb 351 # #rrrrggggbbbb 352 # rgb:r/g/b 353 # rgb:rr/gg/bb 354 # rgb:rrr/ggg/bbb 355 # rgb:rrrr/gggg/bbbb 356 357SIXEL_OPTFLAG_PENETRATE = 'P' # -P, --penetrate: 358 # penetrate GNU Screen using DCS 359 # pass-through sequence 360SIXEL_OPTFLAG_PIPE_MODE = 'D' # -D, --pipe-mode: (deprecated) 361 # read source images from stdin continuously 362SIXEL_OPTFLAG_VERBOSE = 'v' # -v, --verbose: show debugging info 363SIXEL_OPTFLAG_VERSION = 'V' # -V, --version: show version and license info 364SIXEL_OPTFLAG_HELP = 'H' # -H, --help: show this help 365 366if not find_library('sixel'): 367 raise ImportError("libsixel not found.") 368 369# load shared library 370_sixel = cdll.LoadLibrary(find_library('sixel')) 371 372# convert error status code int formatted string 373def sixel_helper_format_error(status): 374 _sixel.sixel_helper_format_error.restype = c_char_p; 375 _sixel.sixel_helper_format_error.argtypes = [c_int]; 376 return _sixel.sixel_helper_format_error(status) 377 378 379# compute pixel depth from pixelformat 380def sixel_helper_compute_depth(pixelformat): 381 _sixel.sixel_helper_compute_depth.restype = c_int 382 _sixel.sixel_encoder_encode.argtypes = [c_int] 383 return _sixel.sixel_helper_compute_depth(pixelformat) 384 385 386# create new output context object 387def sixel_output_new(fn_write, priv=None, allocator=c_void_p(None)): 388 def _fn_write_local(data, size, priv_from_c): 389 fn_write(string_at(data, size), priv) 390 return size 391 sixel_write_function = CFUNCTYPE(c_int, c_char_p, c_int, c_void_p) 392 _sixel.sixel_output_new.restype = c_int 393 _sixel.sixel_output_new.argtypes = [POINTER(c_void_p), sixel_write_function, c_void_p, c_void_p] 394 output = c_void_p(None) 395 _fn_write = sixel_write_function(_fn_write_local) 396 _fn_write.restype = c_int 397 _fn_write.argtypes = [sixel_write_function, c_void_p, c_void_p] 398 status = _sixel.sixel_output_new(byref(output), _fn_write, c_void_p(None), allocator) 399 if SIXEL_FAILED(status): 400 message = sixel_helper_format_error(status) 401 raise RuntimeError(message) 402 output.__fn_write = _fn_write 403 return output 404 405 406# increase reference count of output object (thread-unsafe) 407def sixel_output_ref(output): 408 _sixel.sixel_output_ref.restype = None 409 _sixel.sixel_output_ref.argtypes = [c_void_p] 410 _sixel.sixel_output_ref(output) 411 412 413# decrease reference count of output object (thread-unsafe) 414def sixel_output_unref(output): 415 _sixel.sixel_output_unref.restype = None 416 _sixel.sixel_output_unref.argtypes = [c_void_p] 417 _sixel.sixel_output_unref(output) 418 output.__fn_write = None 419 420 421# get 8bit output mode which indicates whether it uses C1 control characters 422def sixel_output_get_8bit_availability(output): 423 _sixel.sixel_output_get_8bit_availability.restype = None 424 _sixel.sixel_output_get_8bit_availability.argtypes = [c_void_p] 425 _sixel.sixel_output_get_8bit_availability(output) 426 427 428# set 8bit output mode state 429def sixel_output_set_8bit_availability(output): 430 _sixel.sixel_output_set_8bit_availability.restype = None 431 _sixel.sixel_output_set_8bit_availability.argtypes = [c_void_p, c_int] 432 _sixel.sixel_output_set_8bit_availability(output) 433 434 435# set whether limit arguments of DECGRI('!') to 255 436def sixel_output_set_gri_arg_limit(output): 437 _sixel.sixel_output_set_gri_arg_limit.restype = None 438 _sixel.sixel_output_set_gri_arg_limit.argtypes = [c_void_p, c_int] 439 _sixel.sixel_output_set_gri_arg_limit(output) 440 441 442# set GNU Screen penetration feature enable or disable 443def sixel_output_set_penetrate_multiplexer(output): 444 _sixel.sixel_output_set_penetrate_multiplexer.restype = None 445 _sixel.sixel_output_set_penetrate_multiplexer.argtypes = [c_void_p, c_int] 446 _sixel.sixel_output_set_penetrate_multiplexer(output) 447 448 449# set whether we skip DCS envelope 450def sixel_output_set_skip_dcs_envelope(output): 451 _sixel.sixel_output_set_skip_dcs_envelope.restype = None 452 _sixel.sixel_output_set_skip_dcs_envelope.argtypes = [c_void_p, c_int] 453 _sixel.sixel_output_set_skip_dcs_envelope(output) 454 455 456# set palette type: RGB or HLS 457def sixel_output_set_palette_type(output): 458 _sixel.sixel_output_set_palette_type.restype = None 459 _sixel.sixel_output_set_palette_type.argtypes = [c_void_p, c_int] 460 _sixel.sixel_output_set_palette_type(output) 461 462 463# set encodeing policy: auto, fast or size 464def sixel_output_set_encode_policy(output): 465 _sixel.sixel_output_set_encode_policy.restype = None 466 _sixel.sixel_output_set_encode_policy.argtypes = [c_void_p, c_int] 467 _sixel.sixel_output_set_encode_policy(output) 468 469 470# create dither context object 471def sixel_dither_new(ncolors, allocator=None): 472 _sixel.sixel_dither_new.restype = c_int 473 _sixel.sixel_dither_new.argtypes = [POINTER(c_void_p), c_int, c_void_p] 474 dither = c_void_p(None) 475 status = _sixel.sixel_dither_new(byref(dither), ncolors, allocator) 476 if SIXEL_FAILED(status): 477 message = sixel_helper_format_error(status) 478 raise RuntimeError(message) 479 return dither 480 481 482# get built-in dither context object 483def sixel_dither_get(builtin_dither): 484 _sixel.sixel_dither_get.restype = c_void_p 485 _sixel.sixel_dither_get.argtypes = [c_int] 486 return _sixel.sixel_dither_get(builtin_dither) 487 488 489# destroy dither context object 490def sixel_dither_destroy(dither): 491 _sixel.sixel_dither_destroy.restype = None 492 _sixel.sixel_dither_destroy.argtypes = [c_void_p] 493 return _sixel.sixel_dither_destroy(dither) 494 495 496# increase reference count of dither context object (thread-unsafe) 497def sixel_dither_ref(dither): 498 _sixel.sixel_dither_ref.restype = None 499 _sixel.sixel_dither_ref.argtypes = [c_void_p] 500 return _sixel.sixel_dither_ref(dither) 501 502 503# decrease reference count of dither context object (thread-unsafe) 504def sixel_dither_unref(dither): 505 _sixel.sixel_dither_unref.restype = None 506 _sixel.sixel_dither_unref.argtypes = [c_void_p] 507 return _sixel.sixel_dither_unref(dither) 508 509 510# initialize internal palette from specified pixel buffer 511def sixel_dither_initialize(dither, data, width, height, pixelformat, 512 method_for_largest=SIXEL_LARGE_AUTO, 513 method_for_rep=SIXEL_REP_AUTO, 514 quality_mode=SIXEL_QUALITY_AUTO): 515 _sixel.sixel_dither_initialize.restype = c_int 516 _sixel.sixel_dither_initialize.argtypes = [c_void_p, c_char_p, c_int, c_int, c_int, 517 c_int, c_int, c_int] 518 status = _sixel.sixel_dither_initialize(dither, data, width, height, pixelformat, 519 method_for_largest, 520 method_for_rep, 521 quality_mode) 522 if SIXEL_FAILED(status): 523 message = sixel_helper_format_error(status) 524 raise RuntimeError(message) 525 526 527# set diffusion type, choose from enum methodForDiffuse 528def sixel_dither_set_diffusion_type(dither, method_for_diffuse): 529 _sixel.sixel_dither_set_diffusion_type.restype = None 530 _sixel.sixel_dither_set_diffusion_type.argtypes = [c_void_p, c_int] 531 _sixel.sixel_dither_set_diffusion_type(dither, method_for_diffuse) 532 533 534# get number of palette colors 535def sixel_dither_get_num_of_palette_colors(dither): 536 _sixel.sixel_dither_get_num_of_palette_colors.restype = c_int 537 _sixel.sixel_dither_get_num_of_palette_colors.argtypes = [c_void_p] 538 return _sixel.sixel_dither_get_num_of_palette_colors(dither) 539 540 541# get number of histogram colors */ 542def sixel_dither_get_num_of_histogram_colors(dither): 543 _sixel.sixel_dither_get_num_of_histogram_colors.restype = c_int 544 _sixel.sixel_dither_get_num_of_histogram_colors.argtypes = [c_void_p] 545 return _sixel.sixel_dither_get_num_of_histogram_colors(dither) 546 547 548def sixel_dither_get_palette(dither): 549 _sixel.sixel_dither_get_palette.restype = c_char_p 550 _sixel.sixel_dither_get_palette.argtypes = [c_void_p] 551 cpalette = _sixel.sixel_dither_get_palette(dither) 552 return [ord(c) for c in cpalette] 553 554 555def sixel_dither_set_palette(dither, palette): 556 _sixel.sixel_dither_set_palette.restype = None 557 _sixel.sixel_dither_set_palette.argtypes = [c_void_p, c_char_p] 558 cpalette = ''.join(map(chr, palette)) 559 _sixel.sixel_dither_set_palette(dither, cpalette) 560 561 562def sixel_dither_set_complexion_score(dither, score): 563 _sixel.sixel_dither_set_complexion_score.restype = None 564 _sixel.sixel_dither_set_complexion_score.argtypes = [c_void_p, c_int] 565 _sixel.sixel_dither_set_complexion_score(dither, score) 566 567 568def sixel_dither_set_body_only(dither, bodyonly): 569 _sixel.sixel_dither_set_body_only.restype = None 570 _sixel.sixel_dither_set_body_only.argtypes = [c_void_p, c_int] 571 _sixel.sixel_dither_set_body_only(dither, bodyonly) 572 573 574def sixel_dither_set_optimize_palette(dither, do_opt): 575 _sixel.sixel_dither_set_optimize_palette.restype = None 576 _sixel.sixel_dither_set_optimize_palette.argtypes = [c_void_p, c_int] 577 _sixel.sixel_dither_set_optimize_palette(dither, do_opt) 578 579 580def sixel_dither_set_pixelformat(dither, pixelformat): 581 _sixel.sixel_dither_set_pixelformat.restype = None 582 _sixel.sixel_dither_set_pixelformat.argtypes = [c_void_p, c_int] 583 _sixel.sixel_dither_set_pixelformat(dither, pixelformat) 584 585 586def sixel_dither_set_transparent(dither, transparent): 587 _sixel.sixel_dither_set_transparent.restype = None 588 _sixel.sixel_dither_set_transparent.argtypes = [c_void_p, c_int] 589 _sixel.sixel_dither_set_transparent(dither, transparent) 590 591 592# convert pixels into sixel format and write it to output context 593def sixel_encode(pixels, width, height, depth, dither, output): 594 _sixel.sixel_encode.restype = c_int 595 _sixel.sixel_encode.argtypes = [c_char_p, c_int, c_int, c_int, c_void_p, c_void_p] 596 return _sixel.sixel_encode(pixels, width, height, depth, dither, output) 597 598 599# create encoder object 600def sixel_encoder_new(allocator=c_void_p(None)): 601 _sixel.sixel_encoder_new.restype = c_int 602 _sixel.sixel_encoder_new.argtypes = [POINTER(c_void_p), c_void_p] 603 encoder = c_void_p(None) 604 status = _sixel.sixel_encoder_new(byref(encoder), allocator) 605 if SIXEL_FAILED(status): 606 message = sixel_helper_format_error(status) 607 raise RuntimeError(message) 608 return encoder 609 610 611# increase reference count of encoder object (thread-unsafe) 612def sixel_encoder_ref(encoder): 613 _sixel.sixel_encoder_ref.restype = None 614 _sixel.sixel_encoder_ref.argtypes = [c_void_p] 615 _sixel.sixel_encoder_ref(encoder) 616 617 618# decrease reference count of encoder object (thread-unsafe) 619def sixel_encoder_unref(encoder): 620 _sixel.sixel_encoder_unref.restype = None 621 _sixel.sixel_encoder_unref.argtypes = [c_void_p] 622 _sixel.sixel_encoder_unref(encoder) 623 624 625# set an option flag to encoder object 626def sixel_encoder_setopt(encoder, flag, arg=None): 627 _sixel.sixel_encoder_setopt.restype = c_int 628 _sixel.sixel_encoder_setopt.argtypes = [c_void_p, c_int, c_char_p] 629 flag = ord(flag) 630 if arg: 631 arg = str(arg).encode('utf-8') 632 status = _sixel.sixel_encoder_setopt(encoder, flag, arg) 633 if SIXEL_FAILED(status): 634 message = sixel_helper_format_error(status) 635 raise RuntimeError(message) 636 637 638# load source data from specified file and encode it to SIXEL format 639def sixel_encoder_encode(encoder, filename): 640 import locale 641 language, encoding = locale.getdefaultlocale() 642 643 _sixel.sixel_encoder_encode.restype = c_int 644 _sixel.sixel_encoder_encode.argtypes = [c_void_p, c_char_p] 645 status = _sixel.sixel_encoder_encode(encoder, filename.encode(encoding)) 646 if SIXEL_FAILED(status): 647 message = sixel_helper_format_error(status) 648 raise RuntimeError(message) 649 650 651# encode specified pixel data to SIXEL format 652def sixel_encoder_encode_bytes(encoder, buf, width, height, pixelformat, palette): 653 654 depth = sixel_helper_compute_depth(pixelformat) 655 656 if depth <= 0: 657 raise ValueError("invalid pixelformat value : %d" % pixelformat) 658 659 if len(buf) < width * height * depth: 660 raise ValueError("buf.len is too short : %d < %d * %d * %d" % (buf.len, width, height, depth)) 661 662 if not hasattr(buf, "readonly") or buf.readonly: 663 cbuf = c_void_p.from_buffer_copy(buf) 664 else: 665 cbuf = c_void_p.from_buffer(buf) 666 667 if palette: 668 cpalettelen = len(palette) 669 cpalette = (c_byte * cpalettelen)(*palette) 670 else: 671 cpalettelen = None 672 cpalette = None 673 674 _sixel.sixel_encoder_encode_bytes.restype = c_int 675 _sixel.sixel_encoder_encode.argtypes = [c_void_p, c_void_p, c_int, c_int, c_int, c_void_p, c_int] 676 677 status = _sixel.sixel_encoder_encode_bytes(encoder, buf, width, height, pixelformat, cpalette, cpalettelen) 678 if SIXEL_FAILED(status): 679 message = sixel_helper_format_error(status) 680 raise RuntimeError(message) 681 682 683# create decoder object 684def sixel_decoder_new(allocator=c_void_p(None)): 685 _sixel.sixel_decoder_new.restype = c_int 686 _sixel.sixel_decoder_new.argtypes = [POINTER(c_void_p), c_void_p] 687 decoder = c_void_p(None) 688 status = _sixel.sixel_decoder_new(byref(decoder), c_void_p(None)) 689 if SIXEL_FAILED(status): 690 message = sixel_helper_format_error(status) 691 raise RuntimeError(message) 692 return decoder 693 694 695# increase reference count of decoder object (thread-unsafe) 696def sixel_decoder_ref(decoder): 697 _sixel.sixel_decoder_ref.restype = None 698 _sixel.sixel_decoder_ref.argtypes = [c_void_p] 699 _sixel.sixel_decoder_ref(decoder) 700 701 702# decrease reference count of decoder object (thread-unsafe) 703def sixel_decoder_unref(decoder): 704 _sixel.sixel_decoder_unref.restype = None 705 _sixel.sixel_decoder_unref.argtypes = [c_void_p] 706 _sixel.sixel_decoder_unref(decoder) 707 708 709# set an option flag to decoder object 710def sixel_decoder_setopt(decoder, flag, arg=None): 711 _sixel.sixel_decoder_setopt.restype = c_int 712 _sixel.sixel_decoder_setopt.argtypes = [c_void_p, c_int, c_char_p] 713 flag = ord(flag) 714 if arg: 715 arg = str(arg).encode('utf-8') 716 status = _sixel.sixel_decoder_setopt(decoder, flag, arg) 717 if SIXEL_FAILED(status): 718 message = sixel_helper_format_error(status) 719 raise RuntimeError(message) 720 721 722# load source data from stdin or the file 723def sixel_decoder_decode(decoder, infile=None): 724 _sixel.sixel_decoder_decode.restype = c_int 725 _sixel.sixel_decoder_decode.argtypes = [c_void_p] 726 if infile: 727 sixel_decoder_setopt(decoder, SIXEL_OPTFLAG_INPUT, infile) 728 status = _sixel.sixel_decoder_decode(decoder) 729 if SIXEL_FAILED(status): 730 message = sixel_helper_format_error(status) 731 raise RuntimeError(message) 732