admin / Synapse-Cortex
publicSelf Hosted ITSM Tool with RBAC/Tenanting and MFA
Synapse-Cortex / Synapse-Cortexv2 / .venv / Lib / site-packages / PIL / GimpGradientFile.py
4137 B · main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | # # Python Imaging Library # $Id$ # # stuff to read (and render) GIMP gradient files # # History: # 97-08-23 fl Created # # Copyright (c) Secret Labs AB 1997. # Copyright (c) Fredrik Lundh 1997. # # See the README file for information on usage and redistribution. # """ Stuff to translate curve segments to palette values (derived from the corresponding code in GIMP, written by Federico Mena Quintero. See the GIMP distribution for more information.) """ from __future__ import annotations from math import log, pi, sin, sqrt from ._binary import o8 TYPE_CHECKING = False if TYPE_CHECKING: from collections.abc import Callable from typing import IO EPSILON = 1e-10 """""" # Enable auto-doc for data member def linear(middle: float, pos: float) -> float: if pos <= middle: if middle < EPSILON: return 0.0 else: return 0.5 * pos / middle else: pos = pos - middle middle = 1.0 - middle if middle < EPSILON: return 1.0 else: return 0.5 + 0.5 * pos / middle def curved(middle: float, pos: float) -> float: return pos ** (log(0.5) / log(max(middle, EPSILON))) def sine(middle: float, pos: float) -> float: return (sin((-pi / 2.0) + pi * linear(middle, pos)) + 1.0) / 2.0 def sphere_increasing(middle: float, pos: float) -> float: return sqrt(1.0 - (linear(middle, pos) - 1.0) ** 2) def sphere_decreasing(middle: float, pos: float) -> float: return 1.0 - sqrt(1.0 - linear(middle, pos) ** 2) SEGMENTS = [linear, curved, sine, sphere_increasing, sphere_decreasing] """""" # Enable auto-doc for data member class GradientFile: gradient: ( list[ tuple[ float, float, float, list[float], list[float], Callable[[float, float], float], ] ] | None ) = None def getpalette(self, entries: int = 256) -> tuple[bytes, str]: assert self.gradient is not None palette = [] ix = 0 x0, x1, xm, rgb0, rgb1, segment = self.gradient[ix] for i in range(entries): x = i / (entries - 1) while x1 < x: ix += 1 x0, x1, xm, rgb0, rgb1, segment = self.gradient[ix] w = x1 - x0 if w < EPSILON: scale = segment(0.5, 0.5) else: scale = segment((xm - x0) / w, (x - x0) / w) # expand to RGBA r = o8(int(255 * ((rgb1[0] - rgb0[0]) * scale + rgb0[0]) + 0.5)) g = o8(int(255 * ((rgb1[1] - rgb0[1]) * scale + rgb0[1]) + 0.5)) b = o8(int(255 * ((rgb1[2] - rgb0[2]) * scale + rgb0[2]) + 0.5)) a = o8(int(255 * ((rgb1[3] - rgb0[3]) * scale + rgb0[3]) + 0.5)) # add to palette palette.append(r + g + b + a) return b"".join(palette), "RGBA" class GimpGradientFile(GradientFile): """File handler for GIMP's gradient format.""" def __init__(self, fp: IO[bytes]) -> None: if not fp.readline().startswith(b"GIMP Gradient"): msg = "not a GIMP gradient file" raise SyntaxError(msg) line = fp.readline() # GIMP 1.2 gradient files don't contain a name, but GIMP 1.3 files do if line.startswith(b"Name: "): line = fp.readline().strip() count = int(line) self.gradient = [] for i in range(count): s = fp.readline().split() w = [float(x) for x in s[:11]] x0, x1 = w[0], w[2] xm = w[1] rgb0 = w[3:7] rgb1 = w[7:11] segment = SEGMENTS[int(s[11])] cspace = int(s[12]) if cspace != 0: msg = "cannot handle HSV colour space" raise OSError(msg) self.gradient.append((x0, x1, xm, rgb0, rgb1, segment)) |