python-lottie  0.6.11+deved4e6c7
A framework to work with lottie files and telegram animated stickers (tgs)
raster.py
Go to the documentation of this file.
1 from PIL import Image
2 import glaxnimate
3 from . import glaxnimate_helpers
4 import enum
5 from .. import objects
6 from ..nvector import NVector
7 from .pixel import _vectorizing_func
8 
9 
10 class QuantizationMode(enum.Enum):
11  Nearest = 1
12  Exact = 2
13 
14 
16  def get_colors(self, image, n_colors):
17  pass
18 
19 
20 class KMeansPalette(PaletteAlgorithm):
21  def __init__(self, iterations=100, match=glaxnimate.utils.quantize.MatchType.MostFrequent):
22  self.iterationsiterations = iterations
23  self.matchmatch = match
24 
25  def get_colors(self, image, n_colors):
26  return glaxnimate.utils.quantize.k_means(image, n_colors, self.iterationsiterations, self.matchmatch)
27 
28 
30  def get_colors(self, image, n_colors):
31  return glaxnimate.utils.quantize.octree(image, n_colors)
32 
33 
35  def get_colors(self, image, n_colors):
36  return glaxnimate.utils.quantize.k_modes(image, n_colors)
37 
38 
40  def __init__(self, min_frequency=0.0005):
41  self.min_frequencymin_frequency = min_frequency
42 
43  def get_colors(self, image, n_colors):
44  return glaxnimate.utils.quantize.edge_exclusion_modes(image, n_colors, self.min_frequencymin_frequency)
45 
46 
48  def __init__(
49  self,
50  color_mode=QuantizationMode.Nearest,
51  palette_algorithm=OctreePalette(),
52  tolerance=100,
53  stroke_width=1,
54  smoothness=0.75,
55  min_area=16
56  ):
57  self.trace_optionstrace_options = glaxnimate.utils.trace.TraceOptions()
58  self.palette_algorithmpalette_algorithm = palette_algorithm
59  self.color_modecolor_mode = color_mode
60  self.tolerancetolerance = tolerance
61  self.stroke_widthstroke_width = stroke_width
62  self.min_areamin_areamin_areamin_area = min_area
63  self.smoothnesssmoothnesssmoothnesssmoothness = smoothness
64 
65  @property
66  def smoothness(self):
67  return self.trace_optionstrace_options.smoothness
68 
69  @smoothness.setter
70  def smoothness(self, value):
71  self.trace_optionstrace_options.smoothness = value
72 
73  @property
74  def min_area(self):
75  return self.trace_optionstrace_options.min_area
76 
77  @min_area.setter
78  def min_area(self, value):
79  self.trace_optionstrace_options.min_area = value
80 
81  def quantize(self, image, n_colors):
82  """!
83  Returns a list of RGB values
84  """
85  return self.palette_algorithmpalette_algorithm.get_colors(image, n_colors)
86 
87  def trace(self, image, codebook):
88  """!
89  Returns a list of tuple [color, data] where for each color in codebook
90  data is a list of bezier
91 
92  You can get codebook from quantize()
93  """
94 
95  if codebook is None or len(codebook) == 0:
96  tracer = glaxnimate.utils.trace.Tracer(image, self.trace_optionstrace_options)
97  tracer.set_target_alpha(128, False)
98  return [glaxnimate.utils.Color(0, 0, 0), tracer.trace()]
99 
100  if self.color_modecolor_mode == QuantizationMode.Nearest:
101  return list(zip(codebook, glaxnimate.utils.trace.quantize_and_trace(image, self.trace_optionstrace_options, codebook)))
102 
103  mono_data = []
104  tracer = glaxnimate.utils.trace.Tracer(image, self.trace_optionstrace_options)
105  for color in codebook:
106  tracer.set_target_color(color, self.tolerancetolerance)
107  mono_data.append((color, tracer.trace()))
108 
109  return mono_data
110 
111 
113  def __init__(self, trace_options: TraceOptions):
114  self.palettepalette = None
115  self.layerslayers = {}
116  self.trace_optionstrace_options = trace_options
117 
118  def _create_layer(self, animation, layer_name):
119  layer = animation.add_layer(objects.ShapeLayer())
120  if layer_name:
121  self.layerslayers[layer_name] = layer
122  layer.name = layer_name
123  return layer
124 
125  def prepare_layer(self, animation, layer_name=None):
126  layer = self._create_layer_create_layer(animation, layer_name)
127  layer._max_verts = {}
128  for color in self.palettepalette:
129  group = layer.add_shape(objects.Group())
130  group.name = "color_%s" % color.name
131  layer._max_verts[group.name] = 0
132  fcol = glaxnimate_helpers.color_from_glaxnimate(color)
133  group.add_shape(objects.Fill(NVector(*fcol)))
134  if self.trace_optionstrace_options.stroke_width > 0:
135  group.add_shape(objects.Stroke(NVector(*fcol), self.trace_optionstrace_options.stroke_width))
136  return layer
137 
138  def raster_to_layer(self, animation, raster, layer_name=None):
139  layer = self.prepare_layerprepare_layer(animation, layer_name)
140  mono_data = self.trace_optionstrace_options.trace(raster, self.palettepalette)
141  for (color, beziers), group in zip(mono_data, layer.shapes):
142  self.traced_to_shapestraced_to_shapes(group, beziers)
143  return layer
144 
145  def traced_to_shapes(self, group, beziers):
146  shapes = []
147  for bezier in beziers:
148  shape = group.insert_shape(0, objects.Path())
149  shapes.append(shape)
150  shape.shape.value = self.traced_to_beziertraced_to_bezier(bezier)
151  return shapes
152 
153  def traced_to_bezier(self, path):
154  bezier = objects.Bezier()
155  for point in path:
156  pos = glaxnimate_helpers.point_from_glaxnimate(point.pos)
157  tan_in = glaxnimate_helpers.point_from_glaxnimate(point.tan_in - point.pos)
158  tan_out = glaxnimate_helpers.point_from_glaxnimate(point.tan_out - point.pos)
159  bezier.add_point(pos, tan_in, tan_out)
160  if path.closed:
161  bezier.closed = True
162  return bezier
163 
164 
166  filenames,
167  n_colors=1,
168  frame_delay=1,
169  framerate=60,
170  palette=[],
171  trace_options=TraceOptions()
172 ):
173  vc = Vectorizer(trace_options)
174 
175  def callback(animation, raster, frame, time, duration):
176  if vc.palette is None:
177  if palette:
178  vc.palette = [glaxnimate_helpers.color_to_glaxnimate(c) for c in palette]
179  elif n_colors > 1:
180  vc.palette = trace_options.quantize(raster, n_colors)
181  else:
182  vc.palette = [glaxnimate.utils.Color(0, 0, 0, 255)]
183  layer = vc.raster_to_layer(animation, raster, "frame_%s" % frame)
184  layer.in_point = time
185  layer.out_point = layer.in_point + duration
186 
187  animation = _vectorizing_func(filenames, frame_delay, framerate, callback)
188 
189  return animation
Single bezier curve.
Definition: bezier.py:123
Layer containing ShapeElement objects.
Definition: layers.py:193
Solid fill color.
Definition: shapes.py:509
ShapeElement that can contain other shapes.
Definition: shapes.py:433
Animatable Bezier curve.
Definition: shapes.py:399
def __init__(self, min_frequency=0.0005)
Definition: raster.py:40
def get_colors(self, image, n_colors)
Definition: raster.py:43
def get_colors(self, image, n_colors)
Definition: raster.py:25
def __init__(self, iterations=100, match=glaxnimate.utils.quantize.MatchType.MostFrequent)
Definition: raster.py:21
def get_colors(self, image, n_colors)
Definition: raster.py:35
def get_colors(self, image, n_colors)
Definition: raster.py:30
def get_colors(self, image, n_colors)
Definition: raster.py:16
def trace(self, image, codebook)
Returns a list of tuple [color, data] where for each color in codebook data is a list of bezier.
Definition: raster.py:87
def quantize(self, image, n_colors)
Returns a list of RGB values.
Definition: raster.py:81
def min_area(self, value)
Definition: raster.py:78
def smoothness(self, value)
Definition: raster.py:70
def __init__(self, color_mode=QuantizationMode.Nearest, palette_algorithm=OctreePalette(), tolerance=100, stroke_width=1, smoothness=0.75, min_area=16)
Definition: raster.py:56
def traced_to_shapes(self, group, beziers)
Definition: raster.py:145
def traced_to_bezier(self, path)
Definition: raster.py:153
def prepare_layer(self, animation, layer_name=None)
Definition: raster.py:125
def __init__(self, TraceOptions trace_options)
Definition: raster.py:113
def raster_to_layer(self, animation, raster, layer_name=None)
Definition: raster.py:138
def _create_layer(self, animation, layer_name)
Definition: raster.py:118
def raster_to_animation(filenames, n_colors=1, frame_delay=1, framerate=60, palette=[], trace_options=TraceOptions())
Definition: raster.py:172