## 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 fromthe corresponding code in GIMP, written by Federico Mena Quintero.See the GIMP distribution for more information.)"""from__future__importannotationsfrommathimportlog,pi,sin,sqrtfrom._binaryimporto8TYPE_CHECKING=FalseifTYPE_CHECKING:fromcollections.abcimportCallablefromtypingimportIOEPSILON=1e-10""""""# Enable auto-doc for data member[docs]deflinear(middle:float,pos:float)->float:ifpos<=middle:ifmiddle<EPSILON:return0.0else:return0.5*pos/middleelse:pos=pos-middlemiddle=1.0-middleifmiddle<EPSILON:return1.0else:return0.5+0.5*pos/middle [docs]defcurved(middle:float,pos:float)->float:returnpos**(log(0.5)/log(max(middle,EPSILON))) [docs]defsine(middle:float,pos:float)->float:return(sin((-pi/2.0)+pi*linear(middle,pos))+1.0)/2.0 [docs]defsphere_increasing(middle:float,pos:float)->float:returnsqrt(1.0-(linear(middle,pos)-1.0)**2) [docs]defsphere_decreasing(middle:float,pos:float)->float:return1.0-sqrt(1.0-linear(middle,pos)**2) SEGMENTS=[linear,curved,sine,sphere_increasing,sphere_decreasing]""""""# Enable auto-doc for data member[docs]classGradientFile:gradient:(list[tuple[float,float,float,list[float],list[float],Callable[[float,float],float],]]|None)=None[docs]defgetpalette(self,entries:int=256)->tuple[bytes,str]:assertself.gradientisnotNonepalette=[]ix=0x0,x1,xm,rgb0,rgb1,segment=self.gradient[ix]foriinrange(entries):x=i/(entries-1)whilex1<x:ix+=1x0,x1,xm,rgb0,rgb1,segment=self.gradient[ix]w=x1-x0ifw<EPSILON:scale=segment(0.5,0.5)else:scale=segment((xm-x0)/w,(x-x0)/w)# expand to RGBAr=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 palettepalette.append(r+g+b+a)returnb"".join(palette),"RGBA" [docs]classGimpGradientFile(GradientFile):"""File handler for GIMP's gradient format."""def__init__(self,fp:IO[bytes])->None:ifnotfp.readline().startswith(b"GIMP Gradient"):msg="not a GIMP gradient file"raiseSyntaxError(msg)line=fp.readline()# GIMP 1.2 gradient files don't contain a name, but GIMP 1.3 files doifline.startswith(b"Name: "):line=fp.readline().strip()count=int(line)self.gradient=[]foriinrange(count):s=fp.readline().split()w=[float(x)forxins[: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])ifcspace!=0:msg="cannot handle HSV colour space"raiseOSError(msg)self.gradient.append((x0,x1,xm,rgb0,rgb1,segment))