88
99import itertools
1010from math import floor
11+
1112from mathics .builtin .base import Builtin
12- from mathics .builtin .colors .color_directives import (
13- _ColorObject ,
14- ColorError ,
15- RGBColor ,
16- )
13+ from mathics .builtin .colors .color_directives import ColorError , RGBColor , _ColorObject
1714from mathics .builtin .colors .color_internals import convert_color
18- from mathics .builtin .drawing .image import _ImageBuiltin , Image
19-
20- from mathics .core .atoms import (
21- Integer ,
22- MachineReal ,
23- Rational ,
24- Real ,
25- )
15+ from mathics .builtin .drawing .image import Image , _ImageBuiltin
16+ from mathics .core .atoms import Integer , MachineReal , Rational , Real
2617from mathics .core .convert .expression import to_expression , to_mathics_list
2718from mathics .core .expression import Expression
2819from mathics .core .list import ListExpression
3223_image_requires = ("numpy" , "PIL" )
3324
3425try :
35- import PIL .ImageOps
3626 import numpy
27+ import PIL .ImageOps
3728
3829 _enabled = True
3930except ImportError :
@@ -45,14 +36,16 @@ class Blend(Builtin):
4536 <url>:WMA link:https://reference.wolfram.com/language/ref/Blend.html</url>
4637
4738 <dl>
48- <dt>'Blend[{$c1$, $c2$}]'
49- <dd>represents the color between $c1$ and $c2$.
50- <dt>'Blend[{$c1$, $c2$}, $x$]'
51- <dd>represents the color formed by blending $c1$ and $c2$ with
52- factors 1 - $x$ and $x$ respectively.
53- <dt>'Blend[{$c1$, $c2$, ..., $cn$}, $x$]'
54- <dd>blends between the colors $c1$ to $cn$ according to the
55- factor $x$.
39+ <dt>'Blend[{$c1$, $c2$}]'
40+ <dd>represents the color between $c1$ and $c2$.
41+
42+ <dt>'Blend[{$c1$, $c2$}, $x$]'
43+ <dd>represents the color formed by blending $c1$ and $c2$ with
44+ factors 1 - $x$ and $x$ respectively.
45+
46+ <dt>'Blend[{$c1$, $c2$, ..., $cn$}, $x$]'
47+ <dd>blends between the colors $c1$ to $cn$ according to the
48+ factor $x$.
5649 </dl>
5750
5851 >> Blend[{Red, Blue}]
@@ -111,7 +104,7 @@ def do_blend(self, colors, values):
111104 result = [r + p for r , p in zip (result , part )]
112105 return type (components = result )
113106
114- def apply (self , colors , u , evaluation ):
107+ def eval (self , colors , u , evaluation ):
115108 "Blend[{colors___}, u_]"
116109
117110 colors_orig = colors
@@ -156,12 +149,13 @@ def apply(self, colors, u, evaluation):
156149
157150class ColorConvert (Builtin ):
158151 """
159- <url>:WMA link:https://reference.wolfram.com/language/ref/ColorConvert.html</url>
152+ <url>:WMA link:
153+ https://reference.wolfram.com/language/ref/ColorConvert.html</url>
160154
161155 <dl>
162- <dt>'ColorConvert[$c$, $colspace$]'
163- <dd>returns the representation of $c$ in the color space $colspace$. $c$
164- may be a color or an image.
156+ <dt>'ColorConvert[$c$, $colspace$]'
157+ <dd>returns the representation of $c$ in the color space $colspace$. $c$ \
158+ may be a color or an image.
165159 </dl>
166160
167161 Valid values for $colspace$ are:
@@ -182,15 +176,15 @@ class ColorConvert(Builtin):
182176 }
183177 summary_text = "convert between color models"
184178
185- def apply (self , input , colorspace , evaluation ):
179+ def eval (self , input , colorspace , evaluation ):
186180 "ColorConvert[input_, colorspace_String]"
187181
188182 if isinstance (input , Image ):
189183 return input .color_convert (colorspace .get_string_value ())
190184 else :
191185 from mathics .builtin .colors .color_directives import (
192- expression_to_color ,
193186 color_to_expression ,
187+ expression_to_color ,
194188 )
195189
196190 py_color = expression_to_color (input )
@@ -229,7 +223,7 @@ class ColorNegate(_ImageBuiltin):
229223
230224 summary_text = "the negative color of a given color"
231225
232- def apply_for_color (self , color , evaluation ):
226+ def eval_for_color (self , color , evaluation ):
233227 "ColorNegate[color_RGBColor]"
234228 # Get components
235229 r , g , b = [element .to_python () for element in color .elements ]
@@ -238,7 +232,7 @@ def apply_for_color(self, color, evaluation):
238232 # Reconstitute
239233 return Expression (SymbolRGBColor , Real (r ), Real (g ), Real (b ))
240234
241- def apply_for_image (self , image , evaluation ):
235+ def eval_for_image (self , image , evaluation ):
242236 "ColorNegate[image_Image]"
243237 return image .filter (lambda im : PIL .ImageOps .invert (im ))
244238
@@ -273,22 +267,30 @@ class DominantColors(_ImageBuiltin):
273267 <url>:WMA link:https://reference.wolfram.com/language/ref/DominantColors.html</url>
274268
275269 <dl>
276- <dt>'DominantColors[$image$]'
270+ <dt>'DominantColors[$image$]'
277271 <dd>gives a list of colors which are dominant in the given image.
278- <dt>'DominantColors[$image$, $n$]'
272+
273+ <dt>'DominantColors[$image$, $n$]'
279274 <dd>returns at most $n$ colors.
280- <dt>'DominantColors[$image$, $n$, $prop$]'
281- <dd>returns the given property $prop$, which may be "Color" (return RGB colors), "LABColor" (return
282- LAB colors), "Count" (return the number of pixels a dominant color covers), "Coverage" (return the
283- fraction of the image a dominant color covers), or "CoverageImage" (return a black and white image
284- indicating with white the parts that are covered by a dominant color).
275+
276+ <dt>'DominantColors[$image$, $n$, $prop$]'
277+ <dd>returns the given property $prop$, which may be:
278+ <ul>
279+ <li>"Color": return RGB colors,
280+ <li> "LABColor": return LAB colors,
281+ <li> "Count": return the number of pixels a dominant color covers,
282+ <li> "Coverage": return the fraction of the image a dominant color \
283+ covers, or
284+ <li> "CoverageImage": return a black and white image indicating with \
285+ white the parts that are covered by a dominant color.
286+ </ul>
285287 </dl>
286288
287- The option "ColorCoverage" specifies the minimum amount of coverage needed to include a dominant color
288- in the result.
289+ The option "ColorCoverage" specifies the minimum amount of coverage needed to \
290+ include a dominant color in the result.
289291
290- The option "MinColorDistance" specifies the distance (in LAB color space) up to which colors are merged
291- and thus regarded as belonging to the same dominant color.
292+ The option "MinColorDistance" specifies the distance (in LAB color space) up \
293+ to which colors are merged and thus regarded as belonging to the same dominant color.
292294
293295 >> img = Import["ExampleData/lena.tif"]
294296 = -Image-
@@ -326,7 +328,7 @@ class DominantColors(_ImageBuiltin):
326328 options = {"ColorCoverage" : "Automatic" , "MinColorDistance" : "Automatic" }
327329 summary_text = "find a list of dominant colors"
328330
329- def apply (self , image , n , prop , evaluation , options ):
331+ def eval (self , image , n , prop , evaluation , options ):
330332 "DominantColors[image_Image, n_Integer, prop_String, OptionsPattern[%(name)s]]"
331333
332334 py_prop = prop .get_string_value ()
@@ -389,9 +391,9 @@ def apply(self, image, n, prop, evaluation, options):
389391 num_pixels = im .size [0 ] * im .size [1 ]
390392
391393 from mathics .algorithm .clusters import (
392- agglomerate ,
393- PrecomputedDistances ,
394394 FixedDistanceCriterion ,
395+ PrecomputedDistances ,
396+ agglomerate ,
395397 )
396398
397399 norm = numpy .linalg .norm
@@ -426,7 +428,7 @@ def result():
426428 elif py_prop == "Coverage" :
427429 yield Rational (int (count ), num_pixels )
428430 elif py_prop == "CoverageImage" :
429- mask = numpy .ndarray (shape = pixels .shape , dtype = numpy . bool )
431+ mask = numpy .ndarray (shape = pixels .shape , dtype = bool )
430432 mask .fill (0 )
431433 for i in members :
432434 mask = mask | (pixels == i )
0 commit comments