1#@gmic 2# 3# File : gmic_stdlib.gmic 4# ( G'MIC command file ) 5# 6# Description : GREYC's Magic for Image Computing - Standard library 7# ( https://gmic.eu ) 8# 9# Copyright : David Tschumperlé 10# ( https://tschumperle.users.greyc.fr/ ) 11# 12# Licenses : This file is 'dual-licensed', you have to choose one 13# of the two licenses below to apply. 14# 15# CeCILL-C 16# The CeCILL-C license is close to the GNU LGPL. 17# ( http://cecill.info/licences/Licence_CeCILL-C_V1-en.html ) 18# 19# or CeCILL v2.1 20# The CeCILL license is compatible with the GNU GPL. 21# ( http://cecill.info/licences/Licence_CeCILL_V2.1-en.html ) 22# 23# This software is governed either by the CeCILL or the CeCILL-C license 24# under French law and abiding by the rules of distribution of free software. 25# You can use, modify and or redistribute the software under the terms of 26# the CeCILL or CeCILL-C licenses as circulated by CEA, CNRS and INRIA 27# at the following URL: "http://cecill.info". 28# 29# As a counterpart to the access to the source code and rights to copy, 30# modify and redistribute granted by the license, users are provided only 31# with a limited warranty and the software's author, the holder of the 32# economic rights, and the successive licensors have only limited 33# liability. 34# 35# In this respect, the user's attention is drawn to the risks associated 36# with loading, using, modifying and/or developing or reproducing the 37# software by the user in light of its specific status of free software, 38# that may mean that it is complicated to manipulate, and that also 39# therefore means that it is reserved for developers and experienced 40# professionals having in-depth computer knowledge. Users are therefore 41# encouraged to load and test the software's suitability as regards their 42# requirements in conditions enabling the security of their systems and/or 43# data to be ensured and, more generally, to use and operate it in the 44# same conditions as regards security. 45# 46# The fact that you are presently reading this means that you have had 47# knowledge of the CeCILL and CeCILL-C licenses and that you accept its terms. 48# 49 50#------ Syntax rules for a G'MIC command file : 51# 52#*** General syntax : 53# 54# - Each line starting with 'command_name :' starts a new definition of the G'MIC custom command 'command_name'. 55# - Each line starting with '#' is a comment line. 56# - Any other line is considered as the continuation of a previously started G'MIC custom command. 57# 58#*** Specific rules for the command-line interface 'gmic': 59# 60# - A comment line starting with '#@cli' will be parsed by 'gmic' to print help for 61# G'MIC custom commands (when invoked with option 'h'). More precisely : 62# 63# _ '#@cli :: subsection' defines a new command subsection in the displayed help. 64# _ '#@cli command_name : arguments_format1 : arguments_format2 : ... : (qualifier)' 65# starts a new command description. 66# _ '#@cli : description' add a new description line to the current command description. 67# _ '#@cli : $ command_line' defines a new example of use of the current command. 68# _ '#@cli : $$ _pagename' tells the command has a dedicated page in the web tutorial. 69# 70#*** Specific rules for the universal plug-in 'gmic-qt': 71# 72# - A comment line starting with '#@gui' will be parsed by the plug-in to define the filters tree. 73# - A comment line starting with '#@gui_xx' will define a filter only for a specific language 'xx' 74# (e.g. 'en','fr'...). 75# - A comment line starting with '#@gui_xx hide(/Filter or folder name)' will hide the existing 76# filter of folder for the locale 'xx'. 77# - More precisely, the syntax of a '#@gui' comment line is : 78# 79# '#@gui Folder name' 80# 81# or 82# 83# '#@gui Command name : command, preview_command (zoom_factor)[+] [: default_input_mode] 84# '#@gui : parameter1 = typedef(arguments1...), parameter2 = typedef(arguments2...)' 85# '#@gui : parameter3 = typedef(arguments3...), 86# 87# where : 88# 89# 'command' is the G'MIC command name called to process the image. 90# 91# 'preview_command' is the G'MIC command name called to process the preview. 92# 93# Note that you can optionally specify a float-valued factor>=0 between parentheses at the end of 94# the 'preview_command' to force the default zoom factor used by the preview for this filter. 95# Use (0) for a 1:1 preview, (1) for previewing the whole image, (2) for 1/2 image and so on... 96# You can also put an additional '+' sign after the parenthesis to specify the rendered preview 97# is still accurate for different zoom factors. 98# 99# 'default_input_mode' set the default input mode for that filter. It can be 100# { x=none | .=active (default) | *=all | +=active & below | -=active & above | v=all visible | i=all invisible } 101# 102# 'parameter = typedef' tells about the names, types and default values of the filter parameters. 103# 104# 'typedef' can be : 105# 106# _ 'bool(default_value={ 0 | 1 | false | true })': 107# Add a boolean parameter (0 or 1) (as a checkbutton). 108# 109# _ 'button(_alignment)': 110# Add a boolean parameter (0 or 1) (as a button). 111# 112# _ 'choice(_default_index,Choice0,..,ChoiceN)': 113# Add a integer parameter (as a combobox). 114# 115# _ 'color(R,_G,_B,_A)': 116# Add R,G,B[,A] parameters (as a colorchooser). 117# 118# _ 'point(_X,_Y,_removable={ -1 | 0 | 1 },_burst={ 0 | 1 },_R,_G,_B,_[-]A,_radius[%])': 119# Add X,Y parameters (as a moveable point over the preview). 120# 121# _ 'file[_in,_out](_default_filename)': 122# Add a filename parameter (as a filechooser). 123# 124# _ 'float(default_value,min_value,max_value)': 125# Add a float-valued parameter (as a float slider). 126# 127# _ 'folder(_default_foldername)': 128# Add a foldername parameter (as a folderchooser). 129# 130# _ 'int(default_value,min_value,max_value)': 131# Add a integer parameter (as an integer slider). 132# 133# _ 'link(_alignment,_label,URL)': 134# Display a URL (do not add a parameter). 135# 136# _ 'note(_label)': 137# Display a label (do not add a parameter). 138# 139# _ 'text(_is_multiline={ 0 | 1 },_default text)': 140# Add a single or multi-line text parameter (as a text entry). 141# 142# _ 'separator()': 143# Display an horizontal separator (do not add a parameter). 144# 145# _ 'value(value)': 146# Add a pre-defined value parameter (not displayed). 147# 148# Type separators '()' can be replaced by '[]' or '{}' if necessary (for instance if parentheses are required in 149# an argument of the typedef, e.g in a text). You can also replace 'typedef' by '_typedef' to tell the plug-in not 150# being responsive, i.e not to update the image preview when the corresponding parameter is modified. 151# After the closing separator, you may specify a 'visibility state' character for the parameter, which can be 152# { _0=Hidden | _1=Grayed-out | _2=Visible (default) }, opt. followed by a propagation character that tells 153# if this visibility state must be propagated to neighboring non-valued interface widgets 154# (s.a. separator(), link() or note()). 155# This propagation character can be: 156# { '+'=propagate forward | '-'=propagate backward | '*'=propagate in both directions }. 157# 158# Use '_none_' as a special command or preview_command to tell the plug-in that the entry requires no G'MIC call. 159# 160# A G'MIC command can set new values for each filter parameter, through the status (see command ''status''). 161# To do so, the returned status must follow the syntax : 162# '{params1}{params2}{..}{paramsN}' where N must be exactly equal to the number of parameters 163# for the current filter. Optionnally, you can append to each {param} its visibility state suffix ( e.g: {param}_1 ). 164# 165# A G'MIC command can also specify the output blending mode, the opacity and the position of each of the output image 166# (i.e. layer in the plug-in). To do so, set the image name to something like: 167# 'mode(grainmerge),opacity(50),pos(30,50),name(name)'. 168# 169# - Blending mode name should be the same as the argument of the 'blend' command. 170# - Opacity is a float number in [0,100]. 171# - X and Y positions are integers. 172# - 'name' is the layer name. 173# 174#----------------------------------------------------------------------------------------------------------------------- 175 176#--------------------------------- 177# 178#@cli :: Global Options 179# 180#--------------------------------- 181 182# This command is run when the cli tool 'gmic' is invoked without arguments on the command line. 183cli_noarg : 184 v 0 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r _cli_noarg=1 version 185 +e[] "\n[gmic] No commands, options or data provided." 186 if {*,u}>0 187 +e[] "[gmic] (type "${c}"'gmic help'"$n" to print help, "${c}"'gmic demos'"$n" to launch demos)." 188 else 189 +e[] "[gmic] (type "${c}"'gmic help'"$n" to print help)." 190 fi 191 file_update=${_path_rc}update$_version.gmic 192 need_update={"Y = date(0); M = date(1); D = date(2); date_current = Y*365 + M*31 + D; 193 Y = date(0,'"{/$file_update}"'); M = date(1,'"{/$file_update}"'); 194 D = date(2,'"{/$file_update}"'); date_file = Y*365 + M*31 + D; 195 date_current - date_file>=7"} 196 if $need_update 197 +e[] "[gmic] Updating commands..." 198 l[] update 199 +e[] "\r[gmic] Updating commands: "${g}"Succeeded!"$n 200 onfail 201 +e[] "\r[gmic] Updating commands: "${r}"Failed!"$n 202 endl 203 fi 204 +e[] "\n" 205 206# cli_start 207# This command is called each time the cli interface 'gmic' starts. 208# Overload it in your local user command file if necessary. 209cli_start : 210 211#@cli debug : (+) 212#@cli : Activate debug mode. 213#@cli : When activated, the G'MIC interpreter becomes very verbose and outputs additional log 214#@cli : messages about its internal state on the standard output (stdout). 215#@cli : This option is useful for developers or to report possible bugs of the interpreter. 216 217#@cli h : eq. to 'help'. 218h : 219 help $"*" 220 221#@cli help : command : (no arg) 222#@cli : Display help (optionally for specified command only) and exit. 223#@cli : (eq. to 'h'). 224help : skip ${1=""} 225 use_vt100 226 if $!!=1" || w!=1 || d!=1 || s!=1" rm fi 227 if ['$1']==0 228 229 # Display global help. 230 _no_examples,_no_default_values,_no_tutorial_link=1 231 reference ascii 232 233 else 234 235 # Display help for a single command. 236 if narg("$1")" && "isfile(['{/$_path_user}']) 237 l[] it[] $_path_user onfail endl 238 fi 239 if isfile(['{/$_path_rc/update$_version.gmic}']) 240 l[] cimgz:$_path_rc/update$_version.gmic 241 onfail l[] it[] $_path_rc/update$_version.gmic onfail endl 242 endl 243 fi 244 if narg("$1")" && "narg($_path_commands) l[] 245 $_path_commands repeat $! l[$>] it[] {n} k. onfail rm 0 endl done 246 onfail 247 endl fi 248 if !$! return fi 249 a y 250 251 # Check that requested command exist. 252 ('"$1"') autocrop. {'-'} 253 if {i[-1,2]}==_']'" && "i!=_'[' l. s -,{'['} k[0] endl fi 254 command={t} rm. 255 s +,{'"#@cli "$command" :"'} s +,{'"#@cli "$command":"'} s +,{'"#@cli "$command"\n"'} 256 if $!==1 257 l[] m "foo : "$command # Detect command misspelling. 258 repeat 16 um $command done # Be sure the specified command does not exist anymore ! 259 foo um foo 260 onfail ('${}') s -,{'"; did you mean "'} if $!>1 s[1] -,39 k[1] misspelling={t} fi rm 261 endl 262 if narg($misspelling) misspelling="; did you mean '"$_vt100_g$misspelling$_vt100_n"' ?" fi 263 +e[] "\n[gmic] No help available for command '"$_vt100_r$command$_vt100_n"'"$misspelling". "\ 264 "\n Try '"${_vt100_c}"gmic -h"$_vt100_n"' for global help." 265 else 266 a y 267 _no_categories=1 268 +parse_cli ascii,$command 269 if narg(${}) parse_cli ascii,${} fi # In case of shortcut, display also help for shortcut command. 270 fi 271 fi 272 +e[] "\n" rm q 273 274# Command to write reference documentation with various output modes. 275# $1 = output mode, can be { ascii | html | man }. 276# $2 = name of the folder containing additional .gmd pages (optional). 277# Reference and command documentation is written using the G'MIC-markdown syntax. 278reference : skip "${2=}" 279 m "_section : reference_section_$1 \"$""*\"" 280 m "_text : reference_text_$1 \"$""*\"" 281 l reference_begin_$1 reference_header_$1 onfail endl 282 _section "Usage" 283 _text \ 284"~~~\ngmic [command1 [arg1_1,arg1_2,..]] .. [commandN [argN_1,argN_2,..]]\n~~~"\n\n\ 285"`gmic` is the open-source interpreter of the \\\G'MIC language, a script-based programming "\ 286"language dedicated to the design of possibly complex image processing pipelines and operators."\n\ 287"It can be used to convert, manipulate, filter and visualize image datasets made of one or "\ 288"several 1D/2D or 3D multi-spectral images."\n\ 289\n\ 290"This reference documentation describes all the technical aspects of the G'MIC framework, "\ 291"in its current version ___"${-strver}"___."\n\ 292\n\ 293"As a starting point, you may want to visit our detailed tutorial pages, at: <https://gmic.eu/tutorial/>" 294 295 _section "Overall Context" 296 _text \ 297"* At any time, \\G'MIC manages one list of numbered (and optionally named) pixel-based images, "\ 298"entirely stored in computer memory (uncompressed)."\n\ 299"* The first image of the list has index '0' and is denoted by '[0]'. The second image of the "\ 300"list is denoted by '[1]', the third by '[2]' and so on."\n\ 301"* Negative indices are treated in a periodic way: '[-1]' refers to the last image of the list, '[-2]' to the "\ 302"penultimate one, etc. Thus, if the list has 4 images, '[1]' and '[-3]' both designate the second image of the list."\n\ 303"* A named image may be also indicated by '[name]', if 'name' uses the character set `[a-zA-Z0-9_]` and does not "\ 304"start with a number. Image names can be set or reassigned at any moment during the processing pipeline "\ 305"(see command ''name'' for this purpose)."\n\ 306"* G'MIC defines a set of various commands and substitution mechanisms to allow the design of complex "\ 307"pipelines and operators managing this list of images, in a very flexible way: You can insert or remove images "\ 308"in the list, rearrange image order, process images (individually or grouped), merge image data together, "\ 309"display and output image files, etc."\n\ 310"* Such a pipeline can define a new custom G'MIC command (stored in a user command file), and re-used "\ 311"afterwards as a regular command, in a larger pipeline if necessary." 312 313 _section "Image Definition and Terminology" 314 _text \ 315"* In \\G'MIC, each image is modeled as a 1D, 2D, 3D or 4D array of scalar values, uniformly "\ 316"discretized on a rectangular/parallelepipedic domain."\n\ 317"* The four dimensions of this array are respectively denoted by:"\n\ 318" - `width`, the number of image columns (size along the `x-axis`)."\n\ 319" - `height`, the number of image rows (size along the `y-axis`)."\n\ 320" - `depth`, the number of image slices (size along the `z-axis`). "\ 321"The depth is equal to '1' for usual color or grayscale 2D images."\n\ 322" - `spectrum`, the number of image channels (size along the `c-axis`). "\ 323"The spectrum is respectively equal to '3' and '4' for usual `RGB` and `RGBA` color images."\n\ 324\n\ 325"* There are no hard limitations on the size of the image along each dimension. For instance, the number of image "\ 326"slices or channels can be of arbitrary size within the limits of the available memory."\n\ 327"* The `width`, `height` and `depth` of an image are considered as spatial dimensions, while the `spectrum` has a "\ 328"multi-spectral meaning. Thus, a 4D image in G'MIC should be most often regarded as a 3D dataset of multi-spectral "\ 329"voxels. Most of the G'MIC commands will stick with this idea (e.g. command ''blur'' blurs images only along the "\ 330"spatial `xyz`-axes)."\n\ 331"* G'MIC stores all the image data as buffers of `float` values (32 bits, value range '[-3.4E38,+3.4E38]'. "\ 332"It performs all its image processing operations with floating point numbers. Each image pixel takes "\ 333"then 32bits/channel (except if double-precision buffers have been enabled during the compilation of the software, "\ 334"in which case 64bits/channel can be the default)."\n\ 335"* Considering `float`-valued pixels ensure to keep the numerical precision when executing image processing "\ 336"pipelines. For image input/output operations, you may want to prescribe the image datatype to be different than "\ 337"`float` (like `bool`, `char`, `int`, etc.). This is possible by specifying it as a file option when using "\ 338"I/O commands. (see section ''Input/Output Properties'' to learn more about file options)." 339 340 _section "Items of a Processing Pipeline" 341 _text \ 342"* In \\G'MIC, an image processing pipeline is described as a sequence of items separated by the "\ 343"space character. Such items are interpreted and executed from the left to the right. For instance, the expression:"\n\ 344"~~~\nfilename.jpg blur 3,0 sharpen 10 resize 200%,200% output file_out.jpg\n~~~\n"\ 345"defines a valid pipeline composed of nine G'MIC items."\n\n\ 346"* Each G'MIC item is a string that is either a __command__, a list of command __arguments__, "\ 347"a __filename__ or a special __input string__."\n\ 348"* Escape characters '\\' and double quotes '\"' can be used to define items containing spaces or "\ 349"other special characters. For instance, the two strings `single\\ item` and `\"single item\"` "\ 350"both define the same single item, with a space in it." 351 352 _section "Input Data Items" 353 _text \ 354"* If a specified \\G'MIC item appears to be an existing filename, the corresponding image data "\ 355"are loaded and inserted at the end of the image list (which is equivalent to the use of `input filename`). "\n\ 356"* Special filenames `-` and `-.ext` stand for the standard input/output streams, optionally "\ 357"forced to be in a specific 'ext' file format (e.g. `-.jpg` or `-.png`). "\n\ 358"* The following special input strings may be used as G'MIC items to create and insert new "\ 359"images with prescribed values, at the end of the image list:"\n\ 360" - '[selection]' or '[selection]xN': Insert 1 or N copies of already existing images. "\ 361"'selection' may represent one or several images (see section ''Command Items and Selections'' to learn more "\ 362"about selections)."\n\ 363" - 'width[%],_height[%],_depth[%],_spectrum[%],_values[xN]': Insert one or N images with specified "\ 364"size and values (adding '%' to a dimension means __\"percentage of the size along the same axis\"__, "\ 365"taken from the last image '[-1]'). Any specified dimension can be also written as "\ 366"'[image]', and is then set to the size (along the same axis) of the existing specified image "\ 367"'[image]'. 'values' can be either a sequence of numbers separated by commas ',', "\ 368"or a mathematical expression, as e.g. in input item '256,256,1,3,[x,y,128]' which "\ 369"creates a `256x256` RGB color image with a spatial shading on the red and green channels. "\ 370"(see section ''Mathematical Expressions'' to learn more about mathematical expressions). "\n\ 371" - '(v1,v2,..)[xN]': Insert one or `N` new images from specified prescribed values. Value separator "\ 372"inside parentheses can be ',' (column separator), ';' (row separator), '/' (slice separator) or "\ 373"'^' (channel separator). For instance, expression '(1,2,3;4,5,6;7,8,9)' creates a 3x3 matrix (scalar image), "\ 374"with values running from 1 to 9. "\n\ 375" - '(\\'string\\'[:delimiter])[xN]': Insert one or N new images from specified string, by filling "\ 376"the images with the character codes composing the string. When specified, 'delimiter' tells about "\ 377"the main orientation of the image. Delimiter can be 'x' (eq. to ',' which is the default), "\ 378"'y' (eq. to ';'), 'z' (eq. to '/') or 'c' (eq. to '^'). "\ 379"When specified delimiter is ',', ';', '/' or '^', the expression is actually equivalent to "\ 380"'({\\'string\\'[:delimiter]})[xN]' (see section ''Substitution Rules'' for more information on the syntax)."\n\ 381" - '0[xN]': Insert one or N new `empty` images, containing no pixel data. "\ 382"Empty images are used only in rare occasions."\n\ 383\n\ 384"* Input item 'name=value' declares a new variable 'name', or assign a new string value to an existing variable. "\ 385"Variable names must use the character set `[a-zA-Z0-9_]` and cannot start with a number. "\n\ 386"* A variable definition is always local to the current command except when it starts by the underscore "\ 387"character '_'. In that case, it becomes also accessible by any command invoked outside the current command "\ 388"scope (global variable)."\n\ 389"* If a variable name starts with two underscores `__`, the global variable is also shared among different threads "\ 390"and can be read/set by commands running in parallel (see command ''parallel'' for this purpose). "\ 391"Otherwise, it remains local to the thread that defined it."\n\ 392"* Numerical variables can be updated with the use of these special operators: "\ 393"'+=' (addition), '-=' (subtraction), '*=' (multiplication), '/=' (division), '%=' (modulo), '&=' (bitwise and), "\ 394"'|=' (bitwise or), '^=' (power), '<<=' and '>>' (bitwise left and right shifts). For instance, 'foo=1' 'foo+=3'."\n\ 395"* Input item 'name.=string' appends specified `string` at the end of variable 'name'."\n\ 396"* Input item 'name..=string' prepends specified `string` at the beginning of variable 'name'."\n\ 397"* Multiple variable assignments and updates are allowed, with expressions: 'name1,name2,...,nameN=value' or "\ 398"'name1,name2,...,nameN=value1,value2,...,valueN' where assignment operator '=' can be replaced by one of the "\ 399"allowed operators (e.g. '+=')."\n\ 400"* Variables usually store numbers or strings. Use command ''store'' to assign variables from image data "\ 401"(and syntax `input $variable` to bring them back on the image list afterwards)." 402 403 _section "Command Items and Selections" 404 _text \ 405"* A \\G'MIC item that is not a filename nor a special input string designates a 'command' "\ 406"most of the time. Generally, commands perform image processing operations on one or several available images "\ 407"of the list."\n\ 408"* Reccurent commands have two equivalent names ('regular' and 'short'). For instance, command names "\ 409"'resize' and 'r' refer to the same image resizing action."\n\ 410"* A G'MIC command may have mandatory or optional __arguments__. Command arguments must be specified "\ 411"in the next item on the command line. Commas ',' are used to separate multiple arguments of a single command, "\ 412"when required."\n\ 413"* The execution of a G'MIC command may be restricted only to a __subset__ of the image list, by "\ 414"appending '[selection]' to the command name. Examples of valid syntaxes for 'selection' are: "\n\ 415" - 'command[-2]': Apply command only on the penultimate image '[-2]' of the list."\n\ 416" - 'command[0,1,3]': Apply command only on images '[0]', '[1]' and '[3]'."\n\ 417" - 'command[3-6]': Apply command only on images '[3]' to '[6]' (i.e, '[3]', '[4]', '[5]' and '[6]')."\n\ 418" - 'command[50%-100%]': Apply command only on the second half of the image list."\n\ 419" - 'command[0,-4--1]': Apply command only on the first image and the last four images."\n\ 420" - 'command[0-9:3]': Apply command only on images '[0]' to '[9]', with a step of 3 "\ 421"(i.e. on images '[0]', '[3]', '[6]' and '[9]')."\n\ 422" - 'command[0-9:25%]': Apply command only on images '[0]' to '[9]', with a step of 25% "\ 423"(i.e. on images '[0]', '[3]', '[6]' and '[9]')."\n\ 424" - 'command[0--1:2]': Apply command only on images of the list with even indices. "\n\ 425" - 'command[0,2-4,50%--1]': Apply command on images '[0]', '[2]', '[3]', '[4]' and on the second half of "\ 426"the image list."\n\ 427" - 'command[^0,1]': Apply command on all images except the first two."\n\ 428" - 'command[name1,name2]': Apply command on named images 'name1' and 'name2'."\n\ 429\n\ 430"* Indices in selections are always sorted in increasing order, and duplicate indices are "\ 431"discarded. For instance, selections '[3-1,1-3]' and '[1,1,1,3,2]' are both equivalent to "\ 432"'[1-3]'. If you want to repeat a single command multiple times on an image, use a "\ 433"'repeat..done' loop instead. Inverting the order of images for a command is achieved by "\ 434"explicitly inverting the order of the images in the list, with command 'reverse[selection]'."\n\ 435"* Command selections '[-1]', '[-2]' and '[-3]' are so often used they have their own shortcuts, respectively "\ 436"'.', '..' and '...'. For instance, command 'blur..' is equivalent to 'blur[-2]'. "\ 437"These shortcuts work also when specifying command arguments."\n\ 438"* G'MIC commands invoked without '[selection]' are applied on all images of the list, i.e. the "\ 439"default selection is '[0--1]' (except for command ''input'' whose default selection is '[-1]'')."\n\ 440"* Prepending a single hyphen '-' to a G'MIC command is allowed. This may be useful to recognize "\ 441"command items more easily in a one-liner pipeline (typically invoked from a shell). "\n\ 442"* A G'MIC command prepended with a plus sign '+' does not act __in-place__ but inserts its result as one or "\ 443"several new images at the end of the image list."\n\ 444"* There are two different types of commands that can be run by the G'MIC interpreter:"\n\ 445" - __Built-in commands__ are the hard-coded functionalities in the interpreter core. They are thus compiled as "\ 446"binary code and run fast, most of the time. Omitting an argument when invoking a built-in command is not permitted, "\ 447"except if all following arguments are also omitted. "\ 448"For instance, invoking 'plasma 10,,5' is invalid but 'plasma 10' is correct. "\n\ 449" - __Custom commands__, are defined as G'MIC pipelines of built-in or other custom commands. "\ 450"They are parsed by the G'MIC interpreter, and thus run a bit slower than built-in commands. "\ 451"Omitting arguments when invoking a custom command is permitted. For instance, expressions "\ 452"`flower ,,,100,,2` or `flower ,` are correct. "\n\ 453\n\ 454"* Most of the existing commands in G'MIC are actually defined as __custom commands__. "\n\ 455"* A user can easily add its own custom commands to the G'MIC interpreter (see section "\ 456" ''Adding Custom Commands'' for more details). New built-in commands cannot be added (unless you modify the "\ 457"G'MIC interpreter source code and recompile it)." 458 459 _section "Input/Output Properties" 460 _text \ 461"* \\G'MIC is able to read/write most of the classical image file formats, including:"\n\ 462" - 2D grayscale/color files: `.png`, `.jpeg`, `.gif`, `.pnm`, `.tif`, `.bmp`, ..."\n\ 463" - 3D volumetric files: `.dcm`, `.hdr`, `.nii`, `.cube`, `.pan`, `.inr`, `.pnk`, ..."\n\ 464" - Video files: `.mpeg`, `.avi`, `.mp4`, `.mov`, `.ogg`, `.flv`, ..."\n\ 465" - Generic text or binary data files: `.gmz`, `.cimg`, `.cimgz`, `flo`, `ggr`, `gpl`, `.dlm`, `.asc`, "\ 466"`.pfm`, `.raw`, `.txt`, `.h`."\n\ 467" - 3D mesh files: `.off`, `.obj` (output only)"\n\ 468\n\ 469"* When dealing with color images, G'MIC generally reads, writes and displays data using the usual "\ 470"sRGB color space."\n\ 471"* When loading a `.png` and `.tiff` file, the bit-depth of the input image(s) is returned to the status."\n\ 472"* G'MIC is able to manage __3D objects__ that may be read from files or generated by G'MIC commands. "\ 473"A 3D object is stored as a one-column scalar image containing the object data, in the "\ 474"following order: { magic_number; sizes; vertices; primitives; colors; opacities }. "\ 475"These 3D representations can be then processed as regular images (see command ''split3d'' for accessing "\ 476"each of these 3D object data separately)."\n\ 477"* Be aware that usual file formats may be sometimes not adapted to store all the available image "\ 478"data, since G'MIC uses float-valued image buffers. For instance, saving an image that was "\ 479"initially loaded as a 16bits/channel image, as a `.jpg` file will result in a loss of "\ 480"information. Use the G'MIC-specific file extension `.gmz` to ensure that all data "\ 481"precision is preserved when saving images."\n\ 482"* Sometimes, file options may/must be set for file formats:"\n\ 483" - __Video files:__ Only sub-frames of an image sequence may be loaded, using the input expression "\ 484"'filename.ext,[first_frame[,last_frame[,step]]]'. Set 'last_frame==-1' to tell it must be "\ 485"the last frame of the video. Set 'step' to '0' to force an opened video file to be "\ 486"opened/closed. Output framerate and codec can be also set by using the output expression "\ 487"'filename.avi,_fps,_codec,_keep_open' where 'keep_open' can be { 0 | 1 }. 'codec' is a 4-char string "\ 488"(see <http://www.fourcc.org/codecs.php> ) or '0' for the default codec. 'keep_open' "\ 489"tells if the output video file must be kept open for appending new frames afterwards."\n\ 490" - `.cimg[z]` __files:__ Only crops and sub-images of .cimg files can be loaded, using the input "\ 491"expressions 'filename.cimg,N0,N1', 'filename.cimg,N0,N1,x0,x1', "\ 492"'filename.cimg,N0,N1,x0,y0,x1,y1', 'filename.cimg,N0,N1,x0,y0,z0,x1,y1,z1' or "\ 493"'filename.cimg,N0,N1,x0,y0,z0,c0,x1,y1,z1,c1'. "\ 494"Specifying '-1' for one coordinates stands for the maximum possible value. Output expression "\ 495"'filename.cimg[z][,datatype]' can be used to force the output pixel type. 'datatype' can be "\ 496"{ auto | bool | uchar | char | ushort | short | uint | int | uint64 | int64 | float | double }. "\n\ 497" - `.raw` __binary files:__ Image dimensions and input pixel type may be specified when loading `.raw` "\ 498"files with input expression 'filename.raw[,datatype][,width][,height[,depth[,dim[,offset]]]]]'. If no dimensions are "\ 499"specified, the resulting image is a one-column vector with maximum possible height. Pixel "\ 500"type can also be specified with the output expression 'filename.raw[,datatype]'. "\ 501"'datatype' can be the same as for `.cimg[z]` files. "\n\ 502" - `.yuv` __files:__ Image dimensions must be specified when loading, and only sub-frames of an image "\ 503"sequence may be loaded, using the input expression "\ 504"'filename.yuv,width,height[,chroma_subsampling[,first_frame[,last_frame[,step]]]'. "\ 505"'chroma_subsampling' can be { 420 | 422 | 444 }. "\ 506"When saving, chroma subsampling mode can be specified with output expression "\ 507"'filename.yuv[,chroma_subsampling]'. "\n\ 508" - `.tiff` __files:__ Only sub-images of multi-pages tiff files can be loaded, using the input "\ 509"expression 'filename.tif,_first_frame,_last_frame,_step'. "\ 510"Output expression 'filename.tiff,_datatype,_compression,_force_multipage,_use_bigtiff' can be used "\ 511"to specify the output pixel type, as well as the compression method. "\ 512"'datatype' can be the same as for `.cimg[z]` files. 'compression' can be "\ 513" { none (default) | lzw | jpeg }. 'force_multipage' can be { 0=no (default) | 1=yes }. "\ 514"'use_bigtiff' can be { 0=no | 1=yes (default) }."\n\ 515" - `.pdf` __files:__ When loading a file, the rendering resolution can be specified using the input expression "\ 516"'filename.pdf,resolution', where 'resolution' is an unsigned integer value."\n\ 517" - `.gif` __files:__ Animated gif files can be saved, using the input expression "\ 518"'filename.gif,fps>0,nb_loops'. Specify 'nb_loops=0' to get an infinite number of animation "\ 519"loops (this is the default behavior)."\n\ 520" - `.jpeg` __files:__ The output quality may be specified (in %), using the output expression "\ 521"'filename.jpg,30' (here, to get a 30% quality output). '100' is the default."\n\ 522" - `.mnc` __files:__ The output header can set from another file, using the output expression "\ 523"'filename.mnc,header_template.mnc'. "\n\ 524" - `.pan`, `.cpp`, `.hpp`, `.c` and `.h` __files:__ The output datatype can be selected with output expression "\ 525"'filename[,datatype]'. 'datatype' can be the same as for `.cimg[z]` files."\n\ 526" - `.gmic` __files:__ These filenames are assumed to be G'MIC custom commands files. Loading such a "\ 527"file will add the commands it defines to the interpreter. Debug information can be "\ 528"enabled/disabled by the input expression 'filename.gmic[,add_debug_info' where 'debug_info' can be "\ 529"{ 0=false | 1=true }. "\n\ 530" - Inserting 'ext:' on the beginning of a filename (e.g. 'jpg:filename') forces G'MIC to "\ 531"read/write the file as it would have been done if it had the specified extension `.ext`."\n\ 532\n\ 533"* Some input/output formats and options may not be supported, depending on the configuration "\ 534"flags that have been set during the build of the G'MIC software." 535 536 _section "Substitution Rules" 537 _text \ 538"* \\G'MIC items containing '$' or '{}' are substituted before being interpreted. Use these "\ 539"substituting expressions to access various data from the interpreter environment."\n\ 540"* '$name' and '${name}' are both substituted by the value of the specified named variable "\ 541"(set previously by the item 'name=value'). If this variable has not been already set, the "\ 542"expression is substituted by the highest positive index of the named image '[name]'. If no "\ 543"image has this name, the expression is substituted by the value of the OS environment variable "\ 544"with same name (it may be thus an empty string if it is not defined). "\n\ 545"* The following reserved variables are predefined by the G'MIC interpreter: "\n\ 546" - '$!': The current number of images in the list."\n\ 547" - '$>' and '$<': The increasing/decreasing index of the latest (currently running) "\ 548"'repeat...done' loop. '$>' goes from `0` (first loop iteration) to `nb_iterations - 1` (last iteration). "\ 549"'$<' does the opposite. "\n\ 550" - '$/': The current call stack. Stack items are separated by slashes '/'."\n\ 551" - '$|': The current value (expressed in seconds) of a millisecond precision timer."\n\ 552" - '$^': The current verbosity level."\n\ 553" - '$_cpus': The number of computation cores available on your machine."\n\ 554" - '$_flags': The list of enabled flags when G'MIC interpreter has been compiled."\n\ 555" - '$_host': A string telling about the host running the G'MIC interpreter (e.g. `cli` or `gimp`)."\n\ 556" - '$_os': A string describing the running operating system."\n\ 557" - '$_path_rc': The path to the G'MIC folder used to store configuration files (its value is OS-dependent)."\n\ 558" - '$_path_user': The path to the G'MIC user file `.gmic` or `user.gmic` (its value is OS-dependent)."\n\ 559" - '$_path_commands': A list of all imported command files (stored as a list-valued variable)."\n\ 560" - '$_pid': The current process identifier, as an integer."\n\ 561" - '$_pixeltype': The type of image pixels (default: 'float')."\n\ 562" - '$_prerelease': For pre-releases, the date of the pre-release as `yymmdd`. "\ 563"For stable releases, this variable is set to `0`."\n\ 564" - '$_version': A 3-digits number telling about the current version of the G'MIC interpreter "\ 565" (e.g. '"$_version"'). "\n\ 566" - '$_vt100': Set to `1` if colored text output is allowed on the console. Otherwise, set to `0`."\n\ 567\n\ 568"* '$$name' and '$${name}' are both substituted by the G'MIC script code of the specified named "\ 569"`custom command`, or by an empty string if no custom command with specified name exists. "\n\ 570"* '${\"-pipeline\"}' is substituted by the __status value__ after the execution of the specified "\ 571"G'MIC pipeline (see command ''status''). Expression '${}' thus stands for the current status value."\n\ 572"* '{``string}' (starting with two backquotes) is substituted by a double-quoted version of the specified string."\n\ 573"* '{/string}' is substituted by the escaped version of the specified string."\n\ 574"* '{\\'string\\'[:delimiter]}' (between single quotes) is substituted by the sequence of character codes "\ 575"that composes the specified string, separated by specified delimiter. Possible delimiters are "\ 576"',' (default), ';', '/', '^' or ' '. For instance, item '{'foo'}' is substituted by '102,111,111' and "\ 577"'{'foo':;}' by '102;111;111'."\n\ 578"* '{image,feature[:delimiter]}' is substituted by a specific feature of the image '[image]'. "\ 579"'image' can be either an image number or an image name. It can be also eluded, in which case, "\ 580"the last image '[-1]' of the list is considered for the requested feature. "\ 581"Specified 'feature' can be one of:"\n\ 582" - 'b': The image basename (i.e. filename without the folder path nor extension)."\n\ 583" - 'f': The image folder name."\n\ 584" - 'n': The image name or filename (if the image has been read from a file)."\n\ 585" - 't': The text string from the image values regarded as character codes."\n\ 586" - 'x': The image extension (i.e the characters after the last `.` in the image name)."\n\ 587" - '^': The sequence of all image values, separated by commas `,`."\n\ 588" - '@subset': The sequence of image values corresponding to the specified subset, and separated by commas `,`. "\n\ 589" - Any other 'feature' is considered as a __mathematical expression__ associated to the image '[image]' and is "\ 590"substituted by the result of its evaluation (float value). For instance, expression '{0,w+h}' is substituted by "\ 591"the sum of the width and height of the first image (see section ''Mathematical Expressions'' for more details). "\ 592"If a mathematical expression starts with an underscore `_`, the resulting value is truncated to a readable format. "\ 593"For instance, item '{_pi}' is substituted by '3.14159' (while '{pi}' is substituted by '3.141592653589793')."\n\ 594" - A 'feature' delimited by backquotes is replaced by a string whose character codes correspond to the list of "\ 595"values resulting from the evaluation of the specified mathematical expression. For instance, item "\ 596"'{`[102,111,111]`}' is substituted by 'foo' and item '{`vector8(65)`}' by 'AAAAAAAA'."\n\ 597\n\ 598"* '{*}' is substituted by the visibility state of the instant display window '#0' "\ 599"(can be { 0=closed | 1=visible }."\n\ 600"* '{*[index],feature1,...,featureN[:delimiter]}' is substituted by a specific set of features of the instant display "\ 601"window '#0' (or '#index', if specified). Requested 'features' can be:"\n\ 602" - 'u': screen width (actually independent on the window size)."\n\ 603" - 'v': screen height (actually independent on the window size)."\n\ 604" - 'uv': screen width x screen height."\n\ 605" - 'd': window width (i.e. width of the window widget)."\n\ 606" - 'e': window height (i.e. height of the window widget)."\n\ 607" - 'de': window width x window height."\n\ 608" - 'w': display width (i.e. width of the display area managed by the window)."\n\ 609" - 'h': display height (i.e. height of the display area managed by the window)."\n\ 610" - 'wh': display width x display height."\n\ 611" - 'i': X-coordinate of the display window."\n\ 612" - 'j': Y-coordinate of the display window."\n\ 613" - 'n': current normalization type of the instant display."\n\ 614" - 't': window title of the instant display."\n\ 615" - 'x': X-coordinate of the mouse position (or -1, if outside the display area)."\n\ 616" - 'y': Y-coordinate of the mouse position (or -1, if outside the display area)."\n\ 617" - 'b': state of the mouse buttons { 1=left-but. | 2=right-but. | 4=middle-but. }."\n\ 618" - 'o': state of the mouse wheel."\n\ 619" - 'k': decimal code of the pressed key if any, 0 otherwise."\n\ 620" - 'c': boolean (0 or 1) telling if the instant display has been closed recently."\n\ 621" - 'r': boolean telling if the instant display has been resized recently."\n\ 622" - 'm': boolean telling if the instant display has been moved recently."\n\ 623" - Any other 'feature' stands for a keycode name (in capital letters), and is substituted "\ 624"by a boolean describing the current key state { 0=pressed | 1=released }."\n\ 625" - You can also prepend a hyphen '-' to a 'feature' (that supports it) to flush the "\ 626"corresponding event immediately after reading its state (works for keys, mouse and window events)."\n\ 627\n\ 628"* Item substitution is __never__ performed in items between double quotes. One must break the quotes "\ 629"to enable substitution if needed, as in '\"3+8 kg = \"{3+8}\" kg\"'. Using double quotes is then "\ 630"a convenient way to disable the substitutions mechanism in items, when necessary."\n\ 631"* One can also disable the substitution mechanism on items outside double quotes, by escaping the "\ 632"`{`, `}` or `$` characters, as in `\\{3+4\\}\\ doesn\47t\\ evaluate`." 633 634 _section "Mathematical Expressions" 635 _text \ 636"* \\G'MIC has an embedded __mathematical parser__, used to evaluate (possibly complex) math expressions "\ 637"specified inside braces '{}', or formulas in commands that may take one as an argument (e.g. ''fill'' or ''eval'')."\n\ 638"* When the context allows it, a formula is evaluated __for each pixel__ of the selected images "\ 639"(e.g. ''fill'' or ''eval'')."\n\ 640"* A math expression may return a __scalar__ or a __vector-valued__ result (with a fixed number of components)."\n\ 641"The mathematical parser understands the following set of functions, operators and variables:"\n\ 642"## Usual operators:"\n\ 643"'||' (logical or), '&&' (logical and), '|' (bitwise or), '&' (bitwise and), "\ 644"'!=', '==', '<=', '>=', '<', '>', '<<' (left bitwise shift), '>>' (right bitwise shift), '-', '+', '*', '/', "\ 645"'%' (modulo), '^' (power), '!' (logical not), '~' (bitwise not), '++', '--', '+=', '-=', '*=', '/=', '%=', "\ 646"'&=', '|=', '^=', '>>', '<<=' (in-place operators)."\n\ 647"## Usual math functions:"\n\ 648"'abs()', 'acos()', 'acosh()', 'arg()', 'arg0()', 'argkth()', 'argmax()', 'argmaxabs()', "\ 649"'argmin()', 'argminabs()', 'asin()', 'asinh()', 'atan()', 'atan2()', 'atanh()', 'avg()', 'bool()', 'cbrt()', "\ 650"'ceil()', 'cos()', 'cosh()', 'cut()', 'deg2rad()', 'erf()', 'erfinv()', 'exp()', 'fact()', 'fibo()', 'floor()', "\ 651"'gauss()', 'gcd()', 'int()', 'isnan()', 'isnum()', 'isinf()', 'isint()', 'isbool()', 'isexpr()', 'isfile()', "\ 652"'isdir()', 'isin()', 'kth()', 'log()', 'log2()', 'log10()', 'max()', 'maxabs()', 'med()', 'min()', 'minabs()', "\ 653"'narg()', 'prod()', 'rad2deg()', 'rol()' (left bit rotation), 'ror()' (right bit rotation), 'round()', 'sign()', "\ 654"'sin()', 'sinc()', 'sinh()', 'sqrt()', 'std()', 'srand(_seed)', 'sum()', 'tan()', 'tanh()', 'var()', 'xor()'."\n\ 655\n\ 656"* 'atan2(y,x)' is the version of 'atan()' with two arguments 'y' and 'x' (as in C/C++)."\n\ 657"* 'permut(k,n,with_order)' computes the number of permutations of 'k' objects from a set of 'n' objects."\n\ 658"* 'gauss(x,_sigma,_is_normalized)' returns `exp(-x^2/(2*s^2))/(is_normalized?sqrt(2*pi*sigma^2):1)`."\n\ 659"* 'cut(value,min,max)' returns 'value' if it is in range '[min,max]', or 'min' or 'max' otherwise."\n\ 660"* 'narg(a_1,...,a_N)' returns the number of specified arguments (here, 'N')."\n\ 661"* 'arg(i,a_1,..,a_N)' returns the `i`-th argument 'a_i'."\n\ 662"* 'isnum()', 'isnan()', 'isinf()', 'isint()', 'isbool()' test the type of the given number or expression, "\ 663"and return '0' (false) or '1' (true)."\n\ 664"* 'isfile(\\'path\\')' (resp. 'isdir('path')') returns '0' (false) or '1' (true) whether its string argument is a "\ 665"path to an existing file (resp. to a directory) or not."\n\ 666"* 'isvarname(\\'str\\')' returns '0' (false) or '1' (true) whether its string argument would be a valid to name "\ 667"a variable or not."\n\ 668"* 'isin(v,a_1,...,a_n)' returns '0' (false) or '1' (true) whether the first value 'v' appears in the set of other "\ 669"values 'a_i'."\n\ 670"* 'inrange(value,m,M,include_m,include_M)' returns '0' (false) or '1' (true) whether the specified value lies in "\ 671"range '[m,M]' or not ('include_m' and 'includeM' tells how boundaries 'm' and 'M' are considered)."\n\ 672"* 'argkth()', 'argmin()', 'argmax()', 'argminabs()', 'argmaxabs()'', 'avg()', 'kth()', 'min()', 'max()', 'minabs()', "\ 673"'maxabs()', 'med()', 'prod()', 'std()', 'sum()' and 'var()' can be called with an arbitrary number of scalar/vector "\ 674"arguments."\n\ 675"* 'vargkth()', 'vargmin()', 'vargmax()', 'vargminabs()', 'vargmaxabs()', 'vavg()', 'vkth()', 'vmin()', "\ 676"'vmax()', 'vminabs()', 'vmaxabs()', 'vmed()', 'vprod()', 'vstd()', 'vsum()' and 'vvar()' are the versions of the "\ 677"previous function with vector-valued arguments."\n\ 678"* 'round(value,rounding_value,direction)' returns a rounded value. 'direction' can be "\ 679"{ -1=to-lowest | 0=to-nearest | 1=to-highest }."\n\ 680"* 'lerp(a,b,t)' returns 'a*(1-t)+b*t'."\n\ 681"* 'swap(a,b)' swaps the values of the given arguments."\n\ 682"## Variable names:"\n\ 683"Variable names below are pre-defined. They can be overridden."\n\ 684"* 'l': length of the associated list of images."\n\ 685"* 'k': index of the associated image, in '[0,l-1]'."\n\ 686"* 'w': width of the associated image, if any ('0' otherwise)."\n\ 687"* 'h': height of the associated image, if any ('0' otherwise)."\n\ 688"* 'd': depth of the associated image, if any ('0' otherwise)."\n\ 689"* 's': spectrum of the associated image, if any ('0' otherwise)."\n\ 690"* 'r': shared state of the associated image, if any ('0' otherwise)."\n\ 691"* 'wh': shortcut for width x height."\n\ 692"* 'whd': shortcut for width x height x depth."\n\ 693"* 'whds': shortcut for width x height x depth x spectrum (i.e. number of image values)."\n\ 694"* 'im', 'iM', 'ia', 'iv', 'is', 'ip', 'ic', 'in': Respectively the minimum, maximum, average, variance, sum, "\ 695"product, median value and L2-norm of the associated image, if any ('0' otherwise)."\n\ 696"* 'xm', 'ym', 'zm', 'cm': The pixel coordinates of the minimum value in the associated image, "\ 697"if any ('0' otherwise)."\n\ 698"* 'xM', 'yM', 'zM', 'cM': The pixel coordinates of the maximum value in the associated image, "\ 699"if any ('0' otherwise)."\n\ 700"* All these variables are considered as __constant values__ by the math parser (for optimization purposes) "\ 701"which is indeed the case most of the time. Anyway, this might not be the case, if function 'resize(#ind,..)' "\ 702"is used in the math expression. If so, it is safer to invoke functions 'l()', 'w(_#ind)', 'h(_#ind)', ... 's(_#ind)' "\ 703"and 'in(_#ind)' instead of the corresponding named variables."\n\ 704"* 'i': current processed pixel value (i.e. value located at `(x,y,z,c)`) in the associated image, "\ 705"if any ('0' otherwise)."\n\ 706"* 'iN': N-th channel value of current processed pixel (i.e. value located at `(x,y,z,N)` in the associated image, "\ 707"if any ('0' otherwise). 'N' must be an integer in range '[0,9]'."\n\ 708"* 'R', 'G', 'B' and 'A' are equivalent to 'i0', 'i1', 'i2' and 'i3' respectively."\n\ 709"* 'I': current vector-valued processed pixel in the associated image, if any ('0' otherwise). "\ 710"The number of vector components is equal to the number of image channels (e.g. 'I' = `[ R,G,B ]` for a "\ 711"`RGB` image)."\n\ 712"* You may add '#ind' to any of the variable name above to retrieve the information for any "\ 713"numbered image '[ind]' of the list (when this makes sense). For instance 'ia#0' denotes the average value of the "\ 714"first image of the list)."\n\ 715"* 'x': current processed column of the associated image, if any ('0' otherwise)."\n\ 716"* 'y': current processed row of the associated image, if any ('0' otherwise)."\n\ 717"* 'z': current processed slice of the associated image, if any ('0' otherwise)."\n\ 718"* 'c': current processed channel of the associated image, if any ('0' otherwise)."\n\ 719"* 't': thread id when an expression is evaluated with multiple threads ('0' means __master thread__)."\n\ 720"* 'n': maximum number of threads when expression is evaluated in parallel (so that 't' goes from '0' to 'n-1')."\n\ 721"* 'e': value of e, i.e. `2.71828...`."\n\ 722"* 'pi': value of pi, i.e. `3.1415926...`."\n\ 723"* 'u': a random value between '[0,1]', following a uniform distribution."\n\ 724"* 'g': a random value, following a gaussian distribution of variance 1 (roughly in '[-6,6]')."\n\ 725"* 'interpolation': value of the default interpolation mode used when reading pixel values with the pixel access "\ 726"operators (i.e. when the interpolation argument is not explicitly specified, see below for more details on pixel "\ 727"access operators). Its initial default value is '0'."\n\ 728"* 'boundary': value of the default boundary conditions used when reading pixel values with the pixel access "\ 729"operators (i.e. when the boundary condition argument is not explicitly specified, see below for more details "\ 730"on pixel access operators). Its initial default value is '0'."\n\ 731"* The last image of the list is always associated to the evaluations of 'expressions', e.g. G'MIC sequence "\ 732"\n~~~\n256,128 fill {w}\n~~~\n will create a 256x128 image filled with value 256."\n\ 733"## Vector calculus:"\n\ 734"Most operators are also able to work with vector-valued elements."\n\ 735"* '[a0,a1,...,aN-1]' defines a 'N'-dimensional vector with scalar coefficients 'ak'."\n\ 736"* 'vectorN(a0,a1,,...,aN-1)' does the same, with the 'ak' being repeated periodically if only a few are specified."\n\ 737"* 'vector(#N,a0,a1,,...,aN-1)' does the same, and can be used for any constant expression 'N'."\n\ 738"* In previous expressions, the 'ak' can be vectors themselves, to be concatenated into a single vector."\n\ 739"* The scalar element 'ak' of a vector 'X' is retrieved by 'X[k]'."\n\ 740"* The sub-vector '[X[p],X[p+s]...X[p+s*(q-1)]]' (of size 'q') of a vector 'X' is retrieved by 'X[p,q,s]'."\n\ 741"* 'expr(formula,_w,_h,_d,_s)' outputs a vector of size 'w*h*d*s' with values generated from "\ 742"the specified formula, as if one were filling an image with dimensions '(w,h,d,s)'."\n\ 743"* Equality/inequality comparisons between two vectors is done with operators '==' and '!='."\n\ 744"* Some vector-specific functions can be used on vector values: "\ 745"'cross(X,Y)' (cross product), 'dot(X,Y)' (dot product), 'size(X)' (vector dimension), "\ 746"'sort(X,_is_increasing,_nb_elts,_size_elt)' (sorted values), 'reverse(A)' (reverse order of components), "\ 747"'shift(A,_length,_boundary_conditions)' and 'same(A,B,_nb_vals,_is_case_sensitive)' (vector equality test)."\n\ 748"* Function 'normP(u1,...,un)' computes the LP-norm of the specified vector ('P' being an `unsigned integer` constant "\ 749"or 'inf'). If 'P' is omitted, the L2 norm is calculated."\n\ 750"* Function 'resize(A,size,_interpolation,_boundary_conditions)' returns a resized version of a vector 'A' with "\ 751"specified interpolation mode. 'interpolation' can be "\ 752"{ -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | 4=grid | 5=bicubic | 6=lanczos }, and "\ 753"'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }."\n\ 754"* Function 'resize(A,ow,oh,od,os,nw,_,nh,_nd,_ns,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac)' is an "\ 755"extended version of the previous function. It allows to resize the vector 'A', seen as an image of size "\ 756"'ow x oh x od x os' as a new image of size 'nw x nh x nd x ns', with specified resizing options."\n\ 757"* Function 'find(A,B,_starting_index,_search_step)' returns the index where sub-vector 'B' appears in vector 'A', "\ 758"(or '-1' if 'B' is not contained in 'A'). Argument 'A' can be also replaced by an image index '#ind'."\n\ 759"* A `2`-dimensional vector may be seen as a complex number and used in those particular functions/operators: "\ 760"'**' (complex multiplication), '//' (complex division), '^^' (complex exponentiation), "\ 761"'**=' (complex self-multiplication), '//=' (complex self-division), '^^=' (complex self-exponentiation), "\ 762"'cabs()' (complex modulus), 'carg()' (complex argument), 'cconj()' (complex conjugate), "\ 763"'cexp()' (complex exponential), 'clog()' (complex logarithm), 'ccos()' (complex cosine), "\ 764"'csin()' (complex sine), 'ctan()' (complex tangent), 'ccosh()' (complex hyperpolic cosine), "\ 765"'csinh()' (complex hyperbolic sine) and 'ctanh()' (complex hyperbolic tangent)."\n\ 766"* A `MN`-dimensional vector may be seen as a `M` x `N` matrix and used in those particular functions/operators: "\ 767"'*' (matrix-vector multiplication), 'det(A)' (determinant), 'diag(V)' (diagonal matrix from a vector), "\ 768"'eig(A)' (eigenvalues/eigenvectors), 'eye(n)' (n x n identity matrix), 'invert(A,_solver)' (matrix inverse), "\ 769"'mul(A,B,_nb_colsB)' (matrix-matrix multiplication), 'pseudoinvert(A,_nb_colsA,_solver)', "\ 770"'rot(u,v,w,angle)' (3D rotation matrix), 'rot(angle)' (2D rotation matrix), "\ 771"'solve(A,B,_nb_colsB)' (solver of linear system A.X = B), 'svd(A,_nb_colsA)' (singular value decomposition), "\ 772"'trace(A)' (matrix trace) and 'transpose(A,nb_colsA)' (matrix transpose). Argument 'nb_colsB' may be omitted if "\ 773"it is equal to `1`".\n\ 774"* 'mproj(S,nb_colsS,D,nb_colsD,method,max_iter,max_residual)' projects a matrix 'S' onto a dictionary (matrix) "\ 775"'D'. Equivalent to command ''mproj'' but inside the math evaluator."\n\ 776"* Specifying a vector-valued math expression as an argument of a command that operates on image values "\ 777"(e.g. 'fill') modifies the whole spectrum range of the processed image(s), for each spatial coordinates `(x,y,z)`. "\ 778"The command does not loop over the `c`-axis in this case."\n\ 779"## String manipulation:"\n\ 780"Character strings are defined and managed as vectors objects. "\ 781"Dedicated functions and initializers to manage strings are:"\n\ 782"* `['string']` and `'string'` define a vector whose values are the character codes of the "\ 783"specified `character string` (e.g. `'foo'` is equal to `[ 102,111,111 ]`)."\n\ 784"* `_'character'` returns the (scalar) byte code of the specified character (e.g. `_'A'` is equal to '65')."\n\ 785"* A special case happens for __empty__ strings: Values of both expressions `['']` and `''` are '0'."\n\ 786"* Functions 'lowercase()' and 'uppercase()' return string with all string characters lowercased or uppercased."\n\ 787"* Function 'stov(str,_starting_index,_is_strict)' parses specified string 'str' and returns the value contained "\ 788"in it."\n\ 789"* Function 'vtos(expr,_nb_digits,_siz)' returns a vector of size 'siz' which contains the character representation "\ 790"of values described by expression 'expr'. "\ 791"'nb_digits' can be { -1=auto-reduced | 0=all | >0=max number of digits }."\n\ 792"* Function 'echo(str1,str2,...,strN)' prints the concatenation of given string arguments on the console."\n\ 793"* Function 'string(_#siz,str1,str2,...,strN)' generates a vector corresponding to the concatenation of given "\ 794"string/number arguments."\n\ 795"## Dynamic arrays:"\n\ 796"A dynamic array is defined as a one-column (or empty) image '[ind]' in the image list. "\ 797"It allows elements to be added or removed, each element having the same dimension "\ 798"(which is actually the number of channels of image '[ind]'). "\ 799"Dynamic arrays adapt their size to the number of elements they contain."\n\n\ 800"A dynamic array can be manipulated in a math expression, with the following functions:"\n\ 801"* 'da_size(_#ind)': Return the number of elements in dynamic array '[ind]'."\n\ 802"* 'da_back(_#ind)': Return the last element of the dynamic array '[ind]'."\n\ 803"* 'da_insert(_#ind,pos,elt_1,_elt_2,...,_elt_N)': Insert 'N' new elements 'elt_k' starting from index 'pos' "\ 804"in dynamic array '[ind]'."\n\ 805"* 'da_push(_#ind,elt1,_elt2,...,_eltN)': Insert 'N' new elements 'elt_k' at the end of dynamic array '[ind]'."\n\ 806"* 'da_pop(_#ind)': Same as 'da_back()' but also remove last element from the dynamic array '[ind]'."\n\ 807"* 'da_remove(_#ind,_start,_end)': Remove elements located between indices 'start' and 'end' (included) "\ 808"in dynamic array '[ind]'."\n\ 809"* The value of the k-th element of dynamic array '[ind]' is retrieved with 'i[_#ind,k]' (if the element is a "\ 810"scalar value), or 'I[_#ind,k]' (if the element is a vector)."\n\n\ 811"In the functions above, argument '#ind' may be omitted in which case it is assumed to be '#-1'."\n\ 812"## Special operators:"\n\ 813"* ';': expression separator. The returned value is always the last encountered expression. "\ 814"For instance expression '1;2;pi' is evaluated as 'pi'."\n\ 815"* '=': variable assignment. Variables in mathematical parser can only refer to numerical "\ 816"values (vectors or scalars). Variable names are case-sensitive. Use this operator in conjunction with ';' to define "\ 817"more complex evaluable expressions, such as \n~~~\nt = cos(x); 3*t^2 + 2*t + 1\n~~~\n"\ 818"These variables remain __local__ to the mathematical parser and cannot be accessed outside the evaluated "\ 819"expression."\n\ 820"* Variables defined in math parser may have a __constant__ property, by specifying keyword 'const' before the "\ 821"variable name (e.g. 'const foo = pi/4;'). The value set to such a variable must be indeed a __constant scalar__. "\ 822"Constant variables allows certain types of optimizations in the math JIT compiler."\n\ 823\ 824"## Specific functions:"\n\ 825"* 'addr(expr)': return the pointer address to the specified expression 'expr'. "\n\ 826"* 'fill(target,expr)' or 'fill(target,index_name,expr)' fill the content of the specified target "\ 827"(often vector-valued) using a given expression, e.g. `V = vector16(); fill(V,k,k^2 + k + 1);`. "\ 828"For a vector-valued target, it is basically equivalent to: "\ 829"`for (index_name = 0, index_name<size(target), ++index_name, target[index_name] = expr);`."\n\ 830"* 'u(max)' or 'u(min,max)': return a random value between '[0,max]' or '[min,max]', following a uniform "\ 831"distribution."\n\ 832"* 'f2ui(value)' and 'ui2f(value)': Convert a large unsigned integer as a negative floating point value "\ 833"(and vice-versa), so that 32bits floats can be used to store large integers while keeping a unitary precision."\n\ 834"* 'i(_a,_b,_c,_d,_interpolation_type,_boundary_conditions)': return the value of the pixel located at position "\ 835"`(a,b,c,d)` in the associated image, if any ('0' otherwise). "\ 836"'interpolation_type' can be { 0=nearest neighbor | 1=linear | 2=cubic }. "\ 837"'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. "\ 838"Omitted coordinates are replaced by their default values which are respectively 'x', 'y', 'z', 'c', 'interpolation' "\ 839"and 'boundary'. For instance command \n~~~\nfill 0.5*(i(x+1)-i(x-1))\n~~~\n will estimate the X-derivative of an "\ 840"image with a classical finite difference scheme."\n\ 841"* 'j(_dx,_dy,_dz,_dc,_interpolation_type,_boundary_conditions)' does the same for the pixel located at position "\ 842"`(x+dx,y+dy,z+dz,c+dc)` (pixel access relative to the current coordinates)."\n\ 843"* 'i[offset,_boundary_conditions]' returns the value of the pixel located at specified 'offset' in the associated "\ 844"image buffer (or '0' if offset is out-of-bounds)."\n\ 845"* 'j[offset,_boundary_conditions]' does the same for an offset relative to the current pixel coordinates "\ 846"`(x,y,z,c)`."\n\ 847"* 'i(#ind,_x,_y,_z,_c,_interpolation,_boundary_conditions)', "\ 848"'j(#ind,_dx,_dy,_dz,_dc,_interpolation,_boundary_conditions)', 'i[#ind,offset,_boundary_conditions]' and "\ 849"'i[offset,_boundary_conditions]' are similar expressions used to access pixel values for any numbered image '[ind]' "\ 850"of the list."\n\ 851"* 'I/J[offset,_boundary_conditions]' and 'I/J(#ind,_x,_y,_z,_interpolation,_boundary_conditions)' do the same as "\ 852"'i/j[offset,_boundary_conditions]' and 'i/j(#ind,_x,_y,_z,_c,_interpolation,_boundary_conditions)' but return a "\ 853"vector instead of a scalar (e.g. a vector `[ R,G,B ]` for a pixel at `(a,b,c)` in a color image)."\n\ 854"* 'crop(_#ind,_x,_y,_z,_c,_dx,_dy,_dz,_dc,_boundary_conditions)' returns a vector whose values come from the "\ 855"cropped region of image '[ind]' (or from default image selected if 'ind' is not specified). Cropped region starts "\ 856"from point `(x,y,z,c)` and has a size of `dx x dy x dz x dc`. Arguments for coordinates and sizes can be omitted "\ 857"if they are not ambiguous (e.g. 'crop(#ind,x,y,dx,dy)' is a valid invocation of this function)."\n\ 858"* 'draw(_#ind,S,x,y,z,c,dx,_dy,_dz,_dc,_opacity,_M,_max_M)' draws a sprite 'S' in image '[ind]' "\ 859"(or in default image selected if 'ind' is not specified) at coordinates `(x,y,z,c)`. "\ 860"The size of the sprite `dx x dy x dz x dc` must be specified. You can also specify a corresponding opacity mask "\ 861"'M' if its size matches 'S'."\n\ 862"* 'polygon(_#ind,nb_vertices,coords,_opacity,_color)' draws a filled polygon in image '[ind]' (or in default image "\ 863"selected if 'ind' is not specified) at specified coordinates. It draws a single line if 'nb_vertices' is set to 2."\n\ 864"* 'polygon(_#ind,-nb_vertices,coords,_opacity,_pattern,_color)' draws a outlined polygon in image '[ind]' (or in "\ 865"default image selected if 'ind' is not specified) at specified coordinates and with specified line pattern. "\ 866"It draws a single line if 'nb_vertices' is set to 2."\n\ 867"* 'ellipse(_#ind,xc,yc,radius1,_radius2,_angle,_opacity,_color)' draws a filled ellipse in image '[ind]' "\ 868"(or in default image selected if 'ind' is not specified) with specified coordinates."\n\ 869"* 'ellipse(_#ind,xc,yc,-radius1,-_radius2,_angle,_opacity,_pattern,_color)' draws an outlined ellipse in image "\ 870"'[ind]' (or in default image selected if 'ind' is not specified)."\n\ 871"* 'resize(#ind,w,_h,_d,_s,_interp,_boundary_conditions,_cx,_cy,_cz,_cc)' resizes an image of the associated list "\ 872"with specified dimension and interpolation method. When using this function, you should consider retrieving the "\ 873"(non-constant) image dimensions using the dynamic functions 'w(_#ind)', 'h(_#ind)', 'd(_#ind)', 's(_#ind)', "\ 874"'wh(_#ind)', 'whd(_#ind)' and 'whds(_#ind)' instead of the corresponding constant variables."\n\ 875"* 'if(condition,expr_then,_expr_else)': return value of 'expr_then' or 'expr_else', depending on the value of "\ 876"'condition' { 0=false | other=true }. 'expr_else' can be omitted in which case '0' is returned if the condition "\ 877"does not hold. Using the ternary operator 'condition?expr_then[:expr_else]' gives an equivalent expression. "\ 878"For instance, G'MIC commands \n~~~\nfill if(x%10==0,255,i)\n~~~\n and \n~~~\nfill x%10?i:255\n~~~\n both draw blank "\ 879"vertical lines on every 10th column of an image."\n\ 880"* 'do(expression,_condition)' repeats the evaluation of 'expression' until 'condition' vanishes "\ 881"(or until 'expression' vanishes if no 'condition' is specified). For instance, the expression: "\ 882"\n~~~\nif(N<2,N,n=N-1;F0=0;F1=1;do(F2=F0+F1;F0=F1;F1=F2,n=n-1))\n~~~\n returns the N-th value of the Fibonacci "\ 883"sequence, for 'N>=0' (e.g., '46368' for 'N=24'). 'do(expression,condition)' always evaluates the specified "\ 884"expression at least once, then check for the loop condition. When done, it returns the last value of 'expression'."\n\ 885"* 'for(init,condition,_procedure,body)' first evaluates the expression 'init', then iteratively evaluates 'body' "\ 886"(followed by 'procedure' if specified) while 'condition' holds (i.e. not zero). It may happen that no iterations are "\ 887"done, in which case the function returns 'nan'. Otherwise, it returns the last value of 'body'. "\ 888"For instance, the expression: \n~~~\nif(N<2,N,for(n=N;F0=0;F1=1,n=n-1,F2=F0+F1;F0=F1;F1=F2))\n~~~\n "\ 889"returns the 'N'-th value of the Fibonacci sequence, for 'N>=0' (e.g., '46368' for 'N=24')."\n\ 890"* 'while(condition,expression)' is exactly the same as 'for(init,condition,expression)' without the specification of "\ 891"an initializing expression."\n\ 892"* 'repeat(nb_iters,expr)' or 'fill(nb_iters,iter_name,expr)' run 'nb_iters' iterations of the specified expression "\ 893"'expr', e.g. `V = vector16(); repeat(16,k,V[k] = k^2 + k + 1);`. "\ 894"It is basically equivalent to: "\ 895"`for (iter_name = 0, iter_name<nb_iters, ++iter_name, expr);`."\n\ 896"* 'break()' and 'continue()' respectively breaks and continues the current running bloc "\ 897"(loop, init or main environment)."\n\ 898"* 'fsize('filename')' returns the size of the specified 'filename' (or '-1' if file does not exist)."\n\ 899"* 'date(attr,'path')' returns the date attribute for the given 'path' (file or directory), "\ 900"with 'attr' being { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second }, or a vector "\ 901"of those values."\n\ 902"* 'date(_attr)' returns the specified attribute for the current (locale) date (attributes being "\ 903"{ 0...6=same meaning as above | 7=milliseconds })."\n\ 904"* 'print(expr1,expr2,...)' or 'print(#ind)' prints the value of the specified expressions (or image information) "\ 905"on the console, and returns the value of the last expression (or 'nan' in case of an image). "\ 906"Function 'prints(expr)' also prints the string composed of the character codes defined by the vector-valued "\ 907"expression (e.g. 'prints('Hello')')."\n\ 908"* 'debug(expression)' prints detailed debug info about the sequence of operations done by the math parser to "\ 909"evaluate the expression (and returns its value)."\n\ 910"* 'display(_X,_w,_h,_d,_s)' or 'display(#ind)' display the contents of the vector 'X' (or specified image) and "\ 911"wait for user events. if no arguments are provided, a memory snapshot of the math parser environment is displayed "\ 912"instead."\n\ 913"* 'begin(expression)' and 'end(expression)' evaluates the specified expressions only once, respectively at the "\ 914"beginning and end of the evaluation procedure, and this, even when multiple evaluations are required "\ 915"(e.g. in 'fill \">begin(foo = 0); ++foo\"')."\n\ 916"* 'copy(dest,src,_nb_elts,_inc_d,_inc_s,_opacity)' copies an entire memory block of 'nb_elts' elements starting "\ 917"from a source value 'src' to a specified destination 'dest', with increments defined by 'inc_d' and 'inc_s' "\ 918"respectively for the destination and source pointers."\n\ 919"* 'stats(_#ind)' returns the statistics vector of the running image '[ind]', i.e the vector "\ 920"`[ im,iM,ia,iv,xm,ym,zm,cm,xM,yM,zM,cM,is,ip ]` (14 values)."\n\ 921"* 'ref(expr,a)' references specified expression 'expr' as variable name 'a'."\n\ 922"* 'unref(a,b,...)' destroys references to the named variable given as arguments."\n\ 923"* 'breakpoint()' inserts a possible computation breakpoint (useless with the cli interface)."\n\ 924"* '_(comment) expr' just returns expression 'expr' (useful for inserting inline comments in math expressions)."\n\ 925"* 'run('pipeline')' executes the specified G'MIC pipeline as if it was called outside the currently evaluated "\ 926"expression."\n\ 927"* 'set(A,\\'variable_name\\')' set the G'MIC variable '$variable_name' with the value of expression 'A'. If 'A' is"\ 928" a vector-valued variable, it is assumed to encode a string."\n\ 929"* 'store(A,\\'variable_name\\',_w,_h,_d,_s,_is_compressed)' transfers the data of vector 'A' as a "\ 930"`w x h x d x s` image to the G'MIC variable '$variable_name'. Thus, the data becomes available outside the math "\ 931"expression (that is equivalent to using the regular command ''store'', but directly in the math expression)."\n\ 932"* 'get(\\'variable_name\\',_size,_return_as_string)' returns the value of the specified variable, as a vector of "\ 933"'size' values, or as a scalar (if 'size' is zero or not specified)."\n\ 934"* 'name(_#ind,size)' returns a vector of size 'size', whose values are the characters codes of the name of image "\ 935"'[ind]' (or default image selected if 'ind' is not specified)."\n\ 936"* 'correlate(I,wI,hI,dI,sI,K,wK,hK,dK,sK,_boundary_conditions,_is_normalized,_channel_mode,_xcenter,_ycenter,"\ 937"_zcenter,_xstart,_ystart,_zstart,_xend,_yend,_zend,_xstride,_ystride,_zstride,_xdilation,_ydilation,_zdilation,"\ 938"_interpolation_type)' returns the correlation, unrolled as a vector, of the `wI x hI x dI x sI`-sized image 'I' "\ 939"with the `wK x hK x dK x sK`-sized kernel 'K' (the meaning of the other arguments are the same as in command "\ 940"'correlate'). Similar function 'convolve(...)' is also defined for computing the convolution between 'I' and 'K'."\n\ 941\ 942"## User-defined macros:"\n\ 943"* Custom macro functions can be defined in a math expression, using the assignment operator "\ 944"'=', e.g. \n~~~\nfoo(x,y) = cos(x + y); result = foo(1,2) + foo(2,3)\n~~~\n"\n\ 945"* Trying to override a built-in function (e.g. 'abs()') has no effect."\n\ 946"* Overloading macros with different number of arguments is possible. Re-defining a previously defined macro with "\ 947"the same number of arguments discards its previous definition."\n\ 948"* Macro functions are indeed processed as __macros__ by the mathematical evaluator. You should avoid invoking them "\ 949"with arguments that are themselves results of assignments or self-operations. "\ 950"For instance, \n~~~\nfoo(x) = x + x; z = 0; foo(++z)\n~~~\n returns '4' rather than expected value '2'."\n\ 951"* When substituted, macro arguments are placed inside parentheses, except if a number sign "\ 952"'#' is located just before or after the argument name. For instance, expression \n"\ 953"~~~\nfoo(x,y) = x*y; foo(1+2,3)\n~~~\n "\ 954"returns '9' (being substituted as '(1+2)*(3)'), while expression \n~~~\nfoo(x,y) = x#*y#; foo(1+2,3)\n~~~\n "\ 955"returns '7' (being substituted as '1+2*3')."\n\ 956"* Number signs appearing between macro arguments function actually count for __empty__ separators. They may be used "\ 957"to force the substitution of macro arguments in unusual places, e.g. as in \n~~~\nstr(N) = ['I like N#'];\n~~~\n"\ 958\ 959"## Multi-threaded and in-place evaluation:"\n\ 960"* If your image data are large enough and you have several CPUs available, it is likely that the math expression "\ 961"passed to a 'fill', 'eval' or 'input' commands is evaluated in parallel, using multiple computation threads."\n\ 962"* Starting an expression with ':' or '*' forces the evaluations required for an image to be run in parallel, "\ 963"even if the amount of data to process is small (beware, it may be slower to evaluate in this case!). "\ 964"Specify ':' (rather than '*') to avoid possible image copy done before evaluating the expression "\ 965"(this saves memory, but do this only if you are sure this step is not required!)"\n\ 966"* If the specified expression starts with '>' or '<', the pixel access operators 'i()', 'i[]', 'j()' and 'j[]' "\ 967"return values of the image being currently modified, in forward ('>') or backward ('<') order. "\ 968"The multi-threading evaluation of the expression is disabled in this case."\n\ 969"* Function 'critical(expr)' forces the execution of the given expression in a single thread at a time."\n\ 970"* 'begin_t(expr)' and 'end_t(expr)' evaluates the specified expression once for each running thread "\ 971"(so possibly several times) at the beginning and the end of the evaluation procedure."\n\ 972"* 'merge(variable,operator)' tells to merge the local variable value computed by threads, with the specified "\ 973"operator, when all threads have finished computing."\n\ 974"* Expressions 'i(_#ind,x,_y,_z,_c)=value', 'j(_#ind,x,_y,_z,_c)=value', 'i[_#ind,offset]=value' and "\ 975"'j[_#ind,offset]=value' set a pixel value at a different location than the running one in the image '[ind]' "\ 976"(or in the associated image if argument '#ind' is omitted), either with global coordinates/offsets "\ 977"(with 'i(...)' and 'i[...]'), or relatively to the current position `(x,y,z,c)` (with 'j(...)' and 'j[...]'). "\ 978"These expressions always return 'value'." 979 980 _section "Image and Data Viewers" 981 _text \ 982"* \\G'MIC has some very handy embedded __visualization modules__, for 1D signals (command ''plot''), "\ 983"1D/2D/3D images (command ''display'') and 3D vector objects (command ''display3d''). It manages interactive views "\ 984"of the selected image data."\n\ 985"* The following actions are available in the interactive viewers:"\n\ 986" - `(mousewheel)`: Zoom in/out."\n\ 987" - `ESC`: Close window."\n\ 988" - `CTRL+D`: Increase window size."\n\ 989" - `CTRL+C`: Decrease window size."\n\ 990" - `CTRL+R`: Reset window size."\n\ 991" - `CTRL+F`: Toggle fullscreen mode."\n\ 992" - `CTRL+S`: Save current view as a numbered file 'gmic_xxxx.ext'."\n\ 993" - `CTRL+O`: Save copy of the viewed data, as a numbered file 'gmic_xxxx.ext'."\n\ 994\n\ 995"* Actions specific to the __1D/2D image viewer__ (command ''display'') are:"\n\ 996" - `Left mouse button`: Create an image selection and zoom into it."\n\ 997" - `Middle mouse button`, or `CTRL+left mouse button`: Move image."\n\ 998" - `Mouse wheel` or `PADD+/-`: Zoom in/out."\n\ 999" - `Arrow keys`: Move image left/right/up/down."\n\ 1000" - `CTRL+A`: Enable/disable transparency (show alpha channel)."\n\ 1001" - `CTRL+N`: Change normalization mode (can be { none | normal | channel-by-channel })."\n\ 1002" - `CTRL+SPACE`: Reset view."\n\ 1003" - `CTRL+X`: Show/hide axes."\n\ 1004" - `CTRL+Z`: Hold/release aspect ratio."\n\ 1005\n\ 1006"* Actions specific to the __3D volumetric image viewer__ (command ''display'') are:"\n\ 1007" - `CTRL+P`: Play z-stack of frames as a movie."\n\ 1008" - `CTRL+V`: Show/hide 3D view on bottom right zone."\n\ 1009" - `CTRL+X`: Show/hide axes."\n\ 1010" - `CTRL+(mousewheel)`: Go up/down."\n\ 1011" - `SHIFT+(mousewheel)`: Go left/right."\n\ 1012" - `Numeric PAD`: Zoom in/out (`+`/`-`) and move through zoomed image (digits)."\n\ 1013" - `BACKSPACE`: Reset zoom scale."\n\ 1014\n\ 1015"* Actions specific to the __3D object viewer__ (command ''display3d'') are:"\n\ 1016" - `(mouse)+(left mouse button)`: Rotate 3D object."\n\ 1017" - `(mouse)+(right mouse button)`: Zoom 3D object."\n\ 1018" - `(mouse)+(middle mouse button)`: Shift 3D object."\n\ 1019" - `F1 ... F6`: Toggle between different 3D rendering modes."\n\ 1020" - `F7/F8`: Decrease/increase focale."\n\ 1021" - `F9`: Select animation mode."\n\ 1022" - `F10`: Select animation speed."\n\ 1023" - `SPACE`: Start/stop animation."\n\ 1024" - `CTRL+A`: Show/hide 3D axes."\n\ 1025" - `CTRL+B`: Switch between available background."\n\ 1026" - `CTRL+G`: Save 3D object, as numbered file 'gmic_xxxx.obj'."\n\ 1027" - `CTRL+L`: Show/hide outline."\n\ 1028" - `CTRL+P`: Print current 3D pose on stderr."\n\ 1029" - `CTRL+T`: Switch between single/double-sided 3D modes."\n\ 1030" - `CTRL+V`: Start animation with video output."\n\ 1031" - `CTRL+X`: Show/hide 3D bounding box."\n\ 1032" - `CTRL+Z`: Enable/disable z-buffered rendering." 1033 1034 _section "Adding Custom Commands" 1035 _text \ 1036"* New custom commands can be added by the user, through the use of \\G'MIC __custom commands files__."\n\ 1037"* A command file is a simple text file, where each line starts either by "\ 1038"\n~~~\ncommand_name: command_definition\n~~~\n or \n~~~\ncommand_definition (continuation)\n~~~\n"\n\ 1039"* At startup, G'MIC automatically includes user's command file '$HOME/.gmic' (on __Unix__) or "\ 1040"'%APPDATA%/user.gmic' (on __Windows__). The CLI tool 'gmic' automatically runs the command "\ 1041"'cli_start' if defined."\n\ 1042"* Custom command names must use character set `[a-zA-Z0-9_]` and cannot start with a number."\n\ 1043"* Any `# comment` expression found in a custom commands file is discarded by the G'MIC parser, "\ 1044"wherever it is located in a line."\n\ 1045"* In a custom command, the following '$-expressions' are recognized and substituted:"\n\ 1046" - '$""\*' is substituted by a copy of the specified string of arguments."\n\ 1047" - '$\"*\"' is substituted by a copy of the specified string of arguments, each being double-quoted."\n\ 1048" - '$""#' is substituted by the maximum index of known arguments (either specified by the user or set to a default "\ 1049"value in the custom command)."\n\ 1050" - '$""[]' is substituted by the list of selected image indices that have been specified in the command "\ 1051"invocation."\n\ 1052" - '$""?' is substituted by a printable version of '$""[]' to be used in command descriptions."\n\ 1053" - '$i' and '${i}' are both substituted by the `i`-th specified argument. Negative indices such as '${-j}' are "\ 1054"allowed and refer to the `j`-th latest argument. '$""0' is substituted by the custom command name."\n\ 1055" - '${i=default}' is substituted by the value of '$i' (if defined) or by its new value set to 'default' otherwise "\ 1056"('default' may be a `$-expression` as well)."\n\ 1057" - '${subset}' is substituted by the argument values (separated by commas ',') of a specified argument subset. "\ 1058"For instance expression '$""{2--2}' is substituted by all specified command arguments except the first and the last "\ 1059"one. Expression '$""{^0}' is then substituted by all arguments of the invoked command (eq. to '$""*' if all "\ 1060"arguments have been indeed specified)."\n\ 1061" - '$""=var' is substituted by the set of instructions that will assign each argument '$i' to the named variable "\ 1062"'var$i' (for i in '[0...$""#]'. This is particularly useful when a custom command want to manage variable numbers "\ 1063"of arguments. Variables names must use character set `[a-zA-Z0-9_]` and cannot start with a number."\n\ 1064\n\ 1065"* These particular `$-expressions` for custom commands are __always substituted__, even in "\ 1066"double-quoted items or when the dollar sign '$' is escaped with a backslash '\\$'. To avoid substitution, place an "\ 1067"empty double quoted string just after the '$' (as in '$\"\"1')."\n\ 1068"* Specifying arguments may be skipped when invoking a custom command, by replacing them by commas ',' as in "\ 1069"expression \n~~~\nflower ,,3\n~~~\n Omitted arguments are set to their default values, which must be thus explicitly "\ 1070"defined in the code of the corresponding custom command (using default argument expressions as '$""{1=default}')."\n\ 1071"* If one numbered argument required by a custom command misses a value, an error is thrown by the G'MIC "\ 1072"interpreter."\n\ 1073"* It is possible to specialize the invokation of a '+command' by defining it as "\ 1074"\n~~~\n+command_name: command_definition\n~~~\n"\ 1075"* A +-specialization takes priority over the regular command definition when the command is invoked with a "\ 1076"prepended '+'."\n\ 1077"* When only a +-specialization of a command is defined, invoking 'command' is actually equivalent to '+command'." 1078 1079 _section "List of Commands" 1080 _text \ 1081"All available \\G'MIC commands are listed below, by categories. An argument specified between '[]' "\ 1082"or starting by '_' is optional except when standing for an existing image '[image]', where 'image' "\ 1083"can be either an index number or an image name. In this case, the '[]' characters are mandatory when writing the "\ 1084"item. Note that all images that serve as illustrations in this reference documentation are normalized in "\ 1085"range `[0,255]` before being displayed. You may need to do this explicitly (command `normalize 0,255`) if you want "\ 1086"to save and view images with the same aspect than those illustrated in the example codes." 1087 1088 # Insert list of commands. 1089 l reference_list_of_commands_$1 onfail endl 1090 1091 # Insert additional sections if specified. 1092 xfolder="$2" 1093 if "['$1']=='html' && ['$2']==0" xfolder=$HOME/work/src/gmic-community/reference fi 1094 1095 if ['$xfolder']!=0 1096 files $xfolder/*.gmd files=${} 1097 repeat narg({/$files}) 1098 arg 1+$>,$files file=${} 1099 l[] it $file s={b} t={t} rm endl 1100 _section {/$s} 1101 _text {/$t} 1102 done 1103 fi 1104 1105 _section "Examples of Use" 1106 _text \ 1107"`gmic` is a generic image processing tool which can be used in a wide variety of situations. "\ 1108"The few examples below illustrate possible uses of this tool:"\n\ 1109"### View a list of images: "\n\ 1110"\n~~~\n$ gmic file1.bmp file2.jpeg\n~~~"\n\n\ 1111"### Convert an image file: "\n\ 1112"\n~~~\n$ gmic input.bmp output output.jpg\n~~~"\n\n\ 1113"### Create a volumetric image from a movie sequence: "\n\ 1114"\n~~~\n$ gmic input.mpg append z output output.hdr\n~~~"\n\n\ 1115"### Compute image gradient norm: "\n\ 1116"\n~~~\n$ gmic input.bmp gradient_norm\n~~~"\n\n\ 1117"### Denoise a color image: "\n\ 1118"\n~~~\n$ gmic image.jpg denoise 30,10 output denoised.jpg\n~~~"\n\n\ 1119"### Compose two images using overlay layer blending: "\n\ 1120"\n~~~\n$ gmic image1.jpg image2.jpg blend overlay output blended.jpg\n~~~"\n\n\ 1121"### Evaluate a mathematical expression: "\n\ 1122"\n~~~\n$ gmic echo \"cos(pi/4)^2+sin(pi/4)^2={cos(pi/4)^2+sin(pi/4)^2}\"\n~~~"\n\n\ 1123"### Plot a 2D function: "\n\ 1124"\n~~~\n$ gmic 1000,1,1,2 fill \"X=3*(x-500)/500;X^2*sin(3*X^2)+if(c==0,u(0,-1),cos(X*10))\" plot\n~~~"\n\ 1125"===\n![](../img/example_plot.png)\n==="\n\n\ 1126"### Plot a 3D elevated function in random colors: "\n\ 1127"\n~~~\n$ gmic 128,128,1,3,\"u(0,255)\" plasma 10,3 blur 4 sharpen 10000 n 0,255 "\ 1128"elevation3d[-1] \"'X=(x-64)/6;Y=(y-64)/6;100*exp(-(X^2+Y^2)/30)*abs(cos(X)*sin(Y))'\"\n~~~"\n\n\ 1129"===\n![](../img/example_elevation3d.png)\n==="\n\n\ 1130"### Plot the isosurface of a 3D volume: "\n\ 1131"\n~~~\n$ gmic mode3d 5 moded3d 5 double3d 0 isosurface3d \"'x^2+y^2+abs(z)^abs(4*cos(x*y*z*3))'\",3\n~~~"\n\ 1132"===\n![](../img/example_isosurface3d.png)\n==="\n\n\ 1133"### Render a G'MIC 3D logo: "\n\ 1134"\n~~~\n$ gmic 0 text G\\\47MIC,0,0,53,1,1,1,1 expand_xy 10,0 blur 1 normalize 0,100 +plasma 0.4 add blur 1 "\ 1135"elevation3d -0.1 moded3d 4\n~~~"\n\ 1136"===\n![](../img/example_logo.png)\n==="\n\n\ 1137"### Generate a 3D ring of torii: "\n\ 1138"\n~~~\n$ gmic repeat 20 torus3d 15,2 color3d[-1] \"{u(60,255)},{u(60,255)},{u(60,255)}\" *3d[-1] 0.5,1 if \"{$>%2}\" "\ 1139"rotate3d[-1] 0,1,0,90 fi add3d[-1] 70 add3d rotate3d 0,0,1,18 done moded3d 3 mode3d 5 double3d 0\n~~~"\n\ 1140"===\n![](../img/example_torii.png)\n==="\n\n\ 1141"### Create a vase from a 3D isosurface: "\n\ 1142"\n~~~\n$ gmic moded3d 4 isosurface3d \"'x^2+2*abs(y/2)*sin(2*y)^2+z^2-3',0\" sphere3d 1.5 sub3d[-1] 0,5 "\ 1143"plane3d 15,15 rotate3d[-1] 1,0,0,90 center3d[-1] add3d[-1] 0,3.2 color3d[-1] 180,150,255 color3d[-2] 128,255,0 "\ 1144"color3d[-3] 255,128,0 add3d\n~~~"\n\ 1145"===\n![](../img/example_vase.png)\n==="\n\n\ 1146"### Launch a set of interactive demos: "\n\ 1147"\n~~~\n$ gmic demos\n~~~\n" 1148 1149 l reference_footer_$1 reference_end_$1 onfail endl 1150 um _section,_text 1151 rm 1152 1153# 1154# Implement output mode 'ascii' for command 'reference'. 1155# 1156reference_begin_ascii : 1157 use_vt100 1158 if !narg($_shell_cols) _shell_cols={${-shell_cols}-5} fi 1159 _section=0 1160 +e[] "" 1161 1162reference_header_ascii : 1163 if $_prerelease strprerelease=" (pre-release ""#"$_prerelease")" else strprerelease="" fi 1164 str=\n\ 1165 " "${_vt100_b}"gmic: GREYC\'s Magic for Image Computing:"$_vt100_n" command-line interface"\n\ 1166 " "${_vt100_c}${_vt100_b}"Version "${-strver}$strprerelease$_vt100_n\n\ 1167 " "$_vt100_g$_vt100_u"(https://gmic.eu)"$_vt100_n\n\ 1168 \n\ 1169 " Copyright (c) Since 2008, David Tschumperlé / GREYC / CNRS."\n\ 1170 " "$_vt100_g$_vt100_u"(https://www.greyc.fr)"$_vt100_n 1171 +e[] $str 1172 1173reference_section_ascii : 1174 _section+=1 1175 +e[] "" 1176 ('$_section." "') ('"$*"') +f.. {'" "'} +f.. {'-'} a[-4,-3] x a[-2,-1] x 1177 +e[] " "$_vt100_r$_vt100_b{-2,t}$_vt100_n 1178 +e[] " "$_vt100_r{t}$_vt100_n\n 1179 rm[-2,-1] 1180 1181reference_text_ascii : 1182 l[] 1183 ('"$*"') 1184 gmd2ascii $_shell_cols,1 1185 1186 # Ensure output text contains no more than two consecutive newlines. 1187 # Also add a 2-chars left margin on each line. 1188 s +,{'\n'} 1189 eval "repeat (l,p, 1190 i(#p)==_'\n' && h(#p)>2?resize(#p,1,2,1,1,0): 1191 (resize(#p,1,h#p + 2,1,1,0,0,0,1); copy(i[#p,0],_' ',2,1,0)))" 1192 a y 1193 +e[] {/{t}} 1194 rm 1195 endl 1196 1197reference_list_of_commands_ascii : 1198 l 1199 if !$! it $_path_rc/update$_version.gmic fi 1200 parse_cli ascii 1201 onfail 1202 rm 1203 +e[] \n" "$_vt100_r${_vt100_b}"No command descriptions available!"$_vt100_n 1204 +e[] " "${_vt100_r}"Try updating your command files, with command "$_vt100_b"'update'."$_vt100_n 1205 endl 1206 1207reference_footer_ascii : 1208 +e[] \n" "$_vt100_r$_vt100_b"** G\47MIC comes with ABSOLUTELY NO WARRANTY; "\ 1209 "for details visit: https://gmic.eu **"$_vt100_n 1210 1211# 1212# Implement output mode 'html' for command 'reference'. 1213# 1214reference_section_html : 1215 name="$*" 1216 reference_end_section_html 1217 ('"<!DOCTYPE html>"\n\ 1218"<html lang=\"en\">"\n\ 1219" <head>"\n\ 1220" <meta charset=\"utf-8\">"\n\ 1221" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 1222" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 1223"- "$name"</title>"\n\ 1224" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 1225" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 1226" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 1227" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\ 1228" </head>"\n\n\ 1229" <body>"\n\ 1230" <div id=\"include_header\"></div>"\n\n\ 1231" <div class=\"section_title\"><a href=\"index.html\"><p>Reference</p></a></div><div class=\"section_content\">"\n\ 1232" <a name=\"top\"></a>"\n\ 1233"<!-- ref_navigation_top -->"\n\n\ 1234"<!-- begin_content -->"\n\n\ 1235" <h1 class=\"ref_h1\">"$name"</h1>"\n':y) 1236 nm. $name 1237 1238reference_end_section_html : 1239 if $! # End previous section 1240 ('" <br/>"\n\n\ 1241 "<!-- end_content -->"\n\n\ 1242 "<!-- ref_navigation_bottom -->"\n\ 1243 " </div><div class=\"section_end\"></div>"\n\ 1244 " <div id=\"include_footer\"></div>"\n\ 1245 " </body>"':y) 1246 a[-2,-1] y 1247 fi 1248 1249reference_text_html : 1250 ('"$*"':y) gmd2html. 0 1251 if $!>1 a[-2,-1] y fi 1252 1253reference_footer_html : 1254 reference_end_section_html 1255 1256reference_finalize_html : 1257 1258 # Generate table of contents. 1259 if $_prerelease strprerelease=" (pre-release ""#"$_prerelease")" else strprerelease="" fi 1260 html="<!DOCTYPE html>"\n\ 1261"<html lang=\"en\">"\n\ 1262" <head>"\n\ 1263" <meta charset=\"utf-8\">"\n\ 1264" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 1265" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 1266"- Table of Contents</title>"\n\ 1267" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 1268" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 1269" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 1270" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 1271" </head>"\n\n\ 1272" <body>"\n\ 1273" <div id=\"include_header\"></div>"\n\n\ 1274" <div class=\"section_title\"><a href=\"index.html\"><p>Reference</p></a></div><div class=\"section_content\">"\n\n\ 1275" <a name=\"top\"></a>"\n\ 1276"<!-- ref_navigation_top -->"\n\n\ 1277"<!-- begin_content -->"\n\n\ 1278" <h1 class=\"ref_h1\">Preamble</h1>"\n\ 1279" <ul><li>This document is distributed under the "\ 1280"<a target=\"_blank\" href=\"http://www.gnu.org/licenses/fdl-1.3.txt\">GNU Free Documentation License</a>, "\ 1281"version 1.3.</li>"\n\ 1282" <li>A <a href=\"gmic_reference.pdf\">.pdf version</a> of this document is available.</li>"\n 1283 1284 if !0$_pdf_output 1285 html.=" <li>Quick access to the <a class=\"ref_loc\" "\ 1286 "href=\"https://gmic.eu/reference/list_of_commands.html\">"\ 1287 "List of Commands</a>.</li>"\n 1288 fi 1289 1290 html.="</ul>"\n\ 1291" <h1 class=\"ref_h1\">Version</h1>"\n\ 1292" <div class=\"ref_header\">"\n\ 1293" <span class=\"gmd_gmic\">G'MIC</span>: "\ 1294"<span class=\"gmd_monospace\">GREYC's Magic for Image Computing</span><br/>"\n\ 1295" <a href=\"https://gmic.eu\">https://gmic.eu</a><br/>"\n\ 1296" Version <b>"${-strver}"</b>"$strprerelease"<br/><br/>"\n\ 1297" Copyright © Since 2008, "\ 1298"<a target=\"_blank\" href=\"https://tschumperle.users.greyc.fr/\">David Tschumperlé</a> / "\ 1299"<a target=\"_blank\" href=\"https://www.greyc.fr\">GREYC</a> / "\ 1300"<a target=\"_blank\" href=\"http://www.cnrs.fr/en\">CNRS</a><br/>"\n\ 1301" <a target=\"_blank\" href=\"https://www.greyc.fr\">https://www.greyc.fr</a><br/>"\n\ 1302" </div>"\n\ 1303" <h1 class=\"ref_h1\">Table of Contents</h1>"\n\ 1304" <ul>"\n 1305 1306 ind_loc=${"-nmd 1,\"List of Commands\""} 1307 if narg($ind_loc) 1308 repeat $! l[$>] 1309 name={n} strvar $name url=${}.html 1310 if $>==$ind_loc 1311 html.="<li><a class=\"ref_loc\" href=\""$url"#top\">"$name"</a></li>" 1312 else 1313 html.="<li><a href=\""$url"#top\">"$name"</a></li>" 1314 fi 1315 endl done 1316 html.="\n </ul>"\n\n\ 1317 "<!-- end_content -->"\n\n\ 1318 "<!-- ref_navigation_bottom -->"\n\ 1319 " </div><div class=\"section_end\"></div>"\n\ 1320 " <div id=\"include_footer\"></div>"\n\ 1321 " </body>" 1322 1323 i[0] ({'$html'}:y) nm[0] "Table of Contents" 1324 ind_loc+=1 1325 if narg($ind_loc)" && "isfile('list_of_commands.html') # Merge with existing 'List of commands' page if it exists 1326 it list_of_commands.html 1327 if find(crop(),'"<!-- merged_content -->"')<0 l[$ind_loc,-1] 1328 s[0] -,{'"<!-- end_content -->"'} 1329 s. -,{'"<!-- begin_content -->"'} 1330 i[1] ('"<!-- merged_content -->"':y) 1331 k[0,1,-1] a y 1332 endl else nm. "List of Commands" rv[$ind_loc,-1] rm. fi 1333 fi 1334 fi 1335 1336 # Insert top and bottom navigation bar into pages. 1337 if !0$_pdf_output 1338 repeat $! 1339 current={$>,n} strvar[] $current url_current=${}.html 1340 if $>>1 previous={{$>-1},n} strvar[] $previous url_previous=${}.html else previous= fi 1341 if $< next={{$>+1},n} strvar[] $next url_next=${}.html else next= fi 1342 html_top=" <table class=\"ref_navigation_top\"><tr><td>"\ 1343 "<a href=\"index.html\">Table of Contents</a>" 1344 if $> html_top.=" ▸ <a href=\""$url_current"#top\">"$current"</a>" fi 1345 html_top.="</td><td>" 1346 if ['$previous']!=0 html_top.="<a href=\""$url_previous"#top\">◀ "$previous"</a>" fi 1347 if ['$previous']!=0" && "['$next']!=0 html_top.=" | " fi 1348 if ['$next']!=0 html_top.="<a href=\""$url_next"#top\">"$next" ▶</a>" fi 1349 html_top.="</td></tr></table>" 1350 1351 html_bottom="<div class=\"ref_navigation_bottom\">" 1352 if ['$previous']!=0 html_bottom.="<a href=\""$url_previous"#top\">◀ "$previous"</a>" fi 1353 if ['$previous']!=0" && "['$next']!=0 html_bottom.=" | " fi 1354 if ['$next']!=0 html_bottom.="<a href=\""$url_next"#top\">"$next" ▶</a>" fi 1355 html_bottom.="</div>" 1356 1357 replace_str[$>] "<!-- ref_navigation_top -->",$html_top 1358 replace_str[$>] "<!-- ref_navigation_bottom -->",$html_bottom 1359 done 1360 fi 1361 1362reference_end_html : 1363 reference_finalize_html 1364 1365 # Save html pages. 1366 repeat $! l[$>] strvar {n} ot ${}.html endl done 1367 if isfile('table_of_contents.html') x "ln -fs table_of_contents.html index.html" fi 1368 rm 1369 1370# 1371# Implement output mode 'man' for command 'reference'. 1372# (It is based on the 'ascii' output with some tricks to generate a roff file). 1373# 1374reference_begin_man : 1375 _section=0 1376 +e[] ".TH G\47MIC 1\n\ 1377 .SH NAME\n\ 1378 gmic \\- Perform image processing operations using the G\47MIC framework.\n\ 1379 \n\ 1380 .SH HELP\n" 1381 1382reference_header_man : 1383 _vt100_b="\\fB" 1384 _vt100_c="\\fB" 1385 _vt100_g="\\fB" 1386 _vt100_m= 1387 _vt100_n="\\fR" 1388 _vt100_r="\\fB" 1389 _vt100_u="\\fI" 1390 _prerelease= 1391 reference_header_ascii 1392 1393reference_section_man : 1394 reference_section_ascii "$*" 1395 1396reference_text_man : 1397 reference_text_ascii "$*" 1398 1399reference_list_of_commands_man : 1400 _vt100_c= 1401 reference_list_of_commands_ascii 1402 _vt100_m="\\fB" 1403 _vt100_b= 1404 1405reference_footer_man : 1406 reference_footer_ascii "$*" 1407 1408# 1409# Implement output mode 'pdf' for command 'reference'. 1410# (It is based on the 'html' output with some tricks to generate a pdf file with 'wkhtmltopdf'). 1411# 1412reference_begin_pdf : 1413 _pdf_output=1 1414 1415reference_section_pdf : 1416 reference_section_html "$*" 1417 1418reference_text_pdf : 1419 reference_text_html "$*" 1420 1421reference_footer_pdf : 1422 reference_end_section_html 1423 1424reference_end_pdf : 1425 1024,4,1,3 o. reference_pdf.png rm. 1426 reference_finalize_html 1427 1428 # Load existing html page for each command. 1429 l[] 1430 it ../../src/gmic_stdlib.gmic +parse_cli. list loc=${} 1431 parse_cli html 1432 repeat narg($loc) 1433 command=${"arg "1+$>","$loc} 1434 l[] if ['$command'][0]!=_'_' it $command.html fi onfail endl 1435 done 1436 sort_list +,n 1437 endl 1438 s +,{'"<!-- begin_content -->"'} 1439 s +,{'"<!-- end_content -->"'} 1440 k[2--1:5] 1441 1442 # Add specific header and footer. 1443 if $_prerelease strprerelease=" (pre-release ""#"$_prerelease")" else strprerelease="" fi 1444 i[0] ('"<!DOCTYPE html>"\n\ 1445"<html lang=\"en\">"\n\ 1446" <head>"\n\ 1447" <meta charset=\"utf-8\">"\n\ 1448" <link rel=\"stylesheet\" href=\"style.css\">"\n\ 1449" <title>reference_pdf</title>"\n\ 1450" <style>"\n\ 1451" body { background-color: white; font-size: 22px; }"\n\ 1452" .gmd_code_block { font-size: 1em; }"\n\ 1453" </style>"\n\ 1454" </head>"\n\n\ 1455" <body>"\n\ 1456" <div style=\"border: 3px solid black; text-align: center; width: 100%; margin-left: auto; "\ 1457"margin-right: auto; margin-top: 9cm; break-after: page\">"\n\ 1458" <img style=\"width: 98%\" src=\"../img/gmic_banner.jpg\" />"\n\ 1459" <h1 class=\"ref_h1\">The Handbook</h1>"\n\ 1460" <h3>Version "${strver[]}$strprerelease"</h3>"\n\ 1461" <p>© David Tschumperlé / GREYC / CNRS</p>"\n\ 1462" <p>"{date(0)}"/"{date(1)}"/"{date(2)}"</p>"\n\ 1463" </div>"':y) 1464 ('"<img style=\"margin-top: 2em; width: 100%;\" src=\"reference_pdf.png\"/>"\n\ 1465 "<p style=\"text-align: center;\">□ End of document</p>"\n\ 1466 "</body>"':y) a y 1467 ot reference_pdf.html 1468 rm 1469 1470 # Copy css to current folder. 1471 it ../style.css ot. style.css rm 1472 1473 # Use 'wkhtmltopdf' to convert html to a pdf file. 1474 # (There is a bug in wkhtmltopdf that prevents all images to appear in the generated document! 1475 # I have to print the .pdf manually 'in a file' first). 1476 delete reference_pdf.pdf 1477 v 0 e[] " > Waiting for file 'reference_pdf.pdf'." 1478 for !isfile('reference_pdf.pdf') wait 5000 done 1479 e[] " > Removing links in file 'reference_pdf.pdf'." 1480 x "pdfjam reference_pdf.pdf" 1481 e[] " > Compressing file 'reference_pdf.pdf' to 'gmic_reference.pdf'." 1482 x "gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=gmic_reference.pdf reference_pdf-pdfjam.pdf" 1483 e[] " > Clean temporary files." 1484 delete style.css,reference_pdf.html,reference_pdf.png,reference_pdf.pdf,reference_pdf-pdfjam.pdf 1485 e[] " > Upload file 'gmic_reference.pdf' to G'MIC server." 1486 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"put -O /www/gmic/reference gmic_reference.pdf; "\ 1487 "quit\" >/dev/null" 1488 1489# use_vt100 1490# This command defines some global variables used to output colored text on VT100 terminals. 1491use_vt100 : 1492 if !0$_vt100" || "['$_vt100_n']!=0 return fi 1493 _vt100_b="\33[1m" # Bold 1494 _vt100_c="\33[0;36;59m" # Cyan 1495 _vt100_g="\33[0;32;59m" # Green 1496 _vt100_i="\33[3m" # Italic 1497 _vt100_m="\33[0;35;59m" # Magenta 1498 _vt100_n="\33[0;0;0m" # Normal 1499 _vt100_r="\33[0;31;59m" # Red 1500 _vt100_s="\33[9m" # Strikethrough 1501 _vt100_u="\33[4m" # Underline 1502 1503#@cli version 1504#@cli : Display current version number on stdout. 1505version : 1506 use_vt100 1507 reference_header_ascii[] 1508 if !0$_cli_noarg +e[] "\n" fi 1509 1510v : # Allow 'gmic +v' to get the version number. 1511 version 1512 1513#------------------------------- 1514# 1515#@cli :: Input / Output 1516# 1517#------------------------------- 1518 1519#@cli camera : _camera_index>=0,_nb_frames>0,_skip_frames>=0,_capture_width>=0,_capture_height>=0 : (+) 1520#@cli : Insert one or several frames from specified camera. 1521#@cli : When 'nb_frames==0', the camera stream is released instead of capturing new images. 1522#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 1523#@cli : Default values: 'camera_index=0' (default camera), 'nb_frames=1', 'skip_frames=0' and \ 1524# 'capture_width=capture_height=0' (default size). 1525 1526#@cli clut : "clut_name",_resolution>0,_cut_and_round={ 0=no | 1=yes } 1527#@cli : Insert one of the 958 pre-defined CLUTs at the end of the image list.\n 1528#@cli : 'clut_name' can be { 2-strip-process | 60s | 60s_faded | 60s_faded_alt | 7drk_21 | action_magenta_01 | \ 1529# action_red_01 | adventure_1453 | agfa_apx_100 | agfa_apx_25 | agfa_precisa_100 | agfa_ultra_color_100 | \ 1530# agfa_vista_200 | agressive_highligjtes_recovery_5 | alberto_street | alien_green | amstragram | amstragram+ | \ 1531# analog_film_1 | analogfx_anno_1870_color | analogfx_old_style_i | analogfx_old_style_ii | analogfx_old_style_iii | \ 1532# analogfx_sepia_color | analogfx_soft_sepia_i | analogfx_soft_sepia_ii | anime | apocalypse_this_very_moment | \ 1533# aqua | aqua_and_orange_dark | arabica_12 | atomic_pink | autumn | ava_614 | avalanche | azrael_93 | bboyz_2 | \ 1534# bc_darkum | beach_aqua_orange | beach_faded_analog | berlin_sky | black_and_white | black_star | black_white_01 | \ 1535# black_white_02 | black_white_03 | black_white_04 | black_white_05 | black_white_06 | blade_runner | bleach_bypass | \ 1536# bleachbypass_1 | bleachbypass_2 | bleachbypass_3 | bleachbypass_4 | bleech_bypass_green | bleech_bypass_yellow_01 | \ 1537# blue_cold_fade | blue_dark | blue_house | blue_ice | blue_mono | blue_shadows_01 | blues | bob_ford | bourbon_64 | \ 1538# bright_green_01 | bright_teal_orange | bright_warm | brightgreen | brown_mobster | brownbm | brownish | bw_1 | \ 1539# bw_10 | bw_2 | bw_3 | bw_4 | bw_5 | bw_6 | bw_7 | bw_8 | bw_9 | bw_but_yellow | byers_11 | candlelight | caribe | \ 1540# chemical_168 | chrome_01 | cineblue | cinebm_4k | cinema | cinema_2 | cinema_3 | cinema_4 | cinema_5 | \ 1541# cinema_noir | cinematic-1 | cinematic-10 | cinematic-2 | cinematic-3 | cinematic-4 | cinematic-5 | cinematic-6 | \ 1542# cinematic-7 | cinematic-8 | cinematic-9 | cinematic_01 | cinematic_02 | cinematic_03 | cinematic_for_flog | \ 1543# cinematic_forest | cinematic_lady_bird | cinematic_mexico | city | city_7 | city_dust | classic_films_01 | \ 1544# classic_films_02 | classic_films_03 | classic_films_04 | classic_films_05 | classic_teal_and_orange | clayton_33 | \ 1545# clear_teal_fade | clouseau_54 | cobi_3 | coffee_44 | cold_clear_blue | cold_clear_blue_1 | cold_ice | \ 1546# cold_simplicity_2 | color_rich | colorful_0209 | colornegative | conflict_01 | contrail_35 | \ 1547# contrast_with_highlights_protection | contrasty_afternoon | contrasty_green | crispromance | crispwarm | \ 1548# crispwinter | cross_process_cp_130 | cross_process_cp_14 | cross_process_cp_15 | cross_process_cp_16 | \ 1549# cross_process_cp_18 | cross_process_cp_3 | cross_process_cp_4 | cross_process_cp_6 | crushin | cubicle_99 | d_o_1 | \ 1550# dark_blues_in_sunlight | dark_green_02 | dark_green_1 | dark_man_x | dark_orange_teal | dark_place_01 | darkness | \ 1551# date_39 | day_4nite | day_for_night | day_to_night_kings_blue | deep | deep_blue | deep_dark_warm | \ 1552# deep_high_contrast | deep_teal_fade | deep_warm_fade | deepskintones_2 | deepskintones_3 | delicatessen | \ 1553# denoiser_simple_40 | desert_gold_37 | dimension | directions_23 | django_25 | domingo_145 | dream_1 | dream_85 | \ 1554# drop_green_tint_14 | dropblues | duotone_blue_red | earth_tone_boost | edgyember | elegance_38 | enchanted | \ 1555# eterna_for_flog | expired_69 | expired_fade | expired_polaroid | extreme | fade | fade_to_green | faded | \ 1556# faded_47 | faded_alt | faded_analog | faded_extreme | faded_green | faded_pink-ish | faded_print | faded_retro_01 | \ 1557# faded_retro_02 | faded_vivid | fadedlook | fallcolors | faux_infrared | faux_infrared_bw_1 | \ 1558# faux_infrared_color_p_2 | faux_infrared_color_p_3 | faux_infrared_color_r_0a | faux_infrared_color_r_0b | \ 1559# faux_infrared_color_yp_1 | fgcinebasic | fgcinebright | fgcinecold | fgcinedrama | fgcinetealorange_1 | \ 1560# fgcinetealorange_2 | fgcinevibrant | fgcinewarm | film_0987 | film_9879 | film_gb-19 | film_high_contrast | \ 1561# film_print_01 | film_print_02 | filmic | flat_30 | flat_blue_moon | flavin | foggynight | folger_50 | formula_b | \ 1562# french_comedy | frosted | frostedbeachpicnic | fuji_160c | fuji_160c_+ | fuji_160c_++ | fuji_160c_- | \ 1563# fuji_3510_constlclip | fuji_3510_constlmap | fuji_3510_cuspclip | fuji_3513_constlclip | fuji_3513_constlmap | \ 1564# fuji_3513_cuspclip | fuji_400h | fuji_400h_+ | fuji_400h_++ | fuji_400h_- | fuji_800z | fuji_800z_+ | \ 1565# fuji_800z_++ | fuji_800z_- | fuji_astia_100_generic | fuji_astia_100f | fuji_fp-100c | fuji_fp-100c_+ | \ 1566# fuji_fp-100c_++ | fuji_fp-100c_+++ | fuji_fp-100c_++_alt | fuji_fp-100c_- | fuji_fp-100c_-- | fuji_fp-100c_alt | \ 1567# fuji_fp-100c_cool | fuji_fp-100c_cool_+ | fuji_fp-100c_cool_++ | fuji_fp-100c_cool_- | fuji_fp-100c_cool_-- | \ 1568# fuji_fp-100c_negative | fuji_fp-100c_negative_+ | fuji_fp-100c_negative_++ | fuji_fp-100c_negative_+++ | \ 1569# fuji_fp-100c_negative_++_alt | fuji_fp-100c_negative_- | fuji_fp-100c_negative_-- | fuji_fp-3000b | \ 1570# fuji_fp-3000b_+ | fuji_fp-3000b_++ | fuji_fp-3000b_+++ | fuji_fp-3000b_- | fuji_fp-3000b_-- | fuji_fp-3000b_hc | \ 1571# fuji_fp-3000b_negative | fuji_fp-3000b_negative_+ | fuji_fp-3000b_negative_++ | fuji_fp-3000b_negative_+++ | \ 1572# fuji_fp-3000b_negative_- | fuji_fp-3000b_negative_-- | fuji_fp-3000b_negative_early | fuji_fp_100c | fuji_hdr | \ 1573# fuji_neopan_1600 | fuji_neopan_1600_+ | fuji_neopan_1600_++ | fuji_neopan_1600_- | fuji_neopan_acros_100 | \ 1574# fuji_provia_100_generic | fuji_provia_100f | fuji_provia_400f | fuji_provia_400x | fuji_sensia_100 | \ 1575# fuji_superia_100 | fuji_superia_100_+ | fuji_superia_100_++ | fuji_superia_100_- | fuji_superia_1600 | \ 1576# fuji_superia_1600_+ | fuji_superia_1600_++ | fuji_superia_1600_- | fuji_superia_200 | fuji_superia_200_xpro | \ 1577# fuji_superia_400 | fuji_superia_400_+ | fuji_superia_400_++ | fuji_superia_400_- | fuji_superia_800 | \ 1578# fuji_superia_800_+ | fuji_superia_800_++ | fuji_superia_800_- | fuji_superia_hg_1600 | fuji_superia_reala_100 | \ 1579# fuji_superia_x-tra_800 | fuji_velvia_100_generic | fuji_velvia_50 | fuji_xtrans_iii_acros | \ 1580# fuji_xtrans_iii_acros+g | fuji_xtrans_iii_acros+r | fuji_xtrans_iii_acros+ye | fuji_xtrans_iii_astia | \ 1581# fuji_xtrans_iii_classic_chrome | fuji_xtrans_iii_mono | fuji_xtrans_iii_mono+g | fuji_xtrans_iii_mono+r | \ 1582# fuji_xtrans_iii_mono+ye | fuji_xtrans_iii_pro_neg_hi | fuji_xtrans_iii_pro_neg_std | fuji_xtrans_iii_provia | \ 1583# fuji_xtrans_iii_sepia | fuji_xtrans_iii_velvia | fusion_88 | futuristicbleak_1 | futuristicbleak_2 | \ 1584# futuristicbleak_3 | futuristicbleak_4 | going_for_a_walk | golden | golden_bright | golden_fade | golden_mono | \ 1585# golden_night_softner_43 | golden_sony_37 | golden_vibrant | goldengate | goldentime | goldfx_bright_spring_breeze | \ 1586# goldfx_bright_summer_heat | goldfx_hot_summer_heat | goldfx_perfect_sunset_01min | goldfx_perfect_sunset_05min | \ 1587# goldfx_perfect_sunset_10min | goldfx_spring_breeze | goldfx_summer_heat | good_morning | green_15 | green_2025 | \ 1588# green_action | green_afternoon | green_and_orange | green_blues | green_conflict | green_day_01 | green_day_02 | \ 1589# green_g_09 | green_indoor | green_light | green_mono | green_yellow | greenish_contrasty | greenish_fade | \ 1590# greenish_fade_1 | gremerta | hackmanite | hallowen_dark | happyness_133 | hard_teal_orange | harsh_day | \ 1591# harsh_sunset | helios | herderite | heulandite | hiddenite | highlights_protection | hilutite | hitman | hlg_1_1 | \ 1592# honey_light | hong_kong | horrorblue | howlite | hydracore | hyla_68 | hypersthene | hypnosis | hypressen | \ 1593# ilford_delta_100 | ilford_delta_3200 | ilford_delta_3200_+ | ilford_delta_3200_++ | ilford_delta_3200_- | \ 1594# ilford_delta_400 | ilford_fp_4_plus_125 | ilford_hp_5 | ilford_hp_5_+ | ilford_hp_5_++ | ilford_hp_5_- | \ 1595# ilford_hp_5_plus_400 | ilford_hps_800 | ilford_pan_f_plus_50 | ilford_xp_2 | indoor_blue | industrial_33 | \ 1596# infrared_-_dust_pink | instantc | justpeachy | jwick_21 | k_tone_vintage_kodachrome | kh_1 | kh_10 | kh_2 | kh_3 | \ 1597# kh_4 | kh_5 | kh_6 | kh_7 | kh_8 | kh_9 | killstreak | kodak_2383_constlclip | kodak_2383_constlmap | \ 1598# kodak_2383_cuspclip | kodak_2393_constlclip | kodak_2393_constlmap | kodak_2393_cuspclip | kodak_bw_400_cn | \ 1599# kodak_e-100_gx_ektachrome_100 | kodak_ektachrome_100_vs | kodak_ektachrome_100_vs_generic | kodak_ektar_100 | \ 1600# kodak_elite_100_xpro | kodak_elite_chrome_200 | kodak_elite_chrome_400 | kodak_elite_color_200 | \ 1601# kodak_elite_color_400 | kodak_elite_extracolor_100 | kodak_hie_hs_infra | kodak_kodachrome_200 | \ 1602# kodak_kodachrome_25 | kodak_kodachrome_64 | kodak_kodachrome_64_generic | kodak_portra_160 | kodak_portra_160_+ | \ 1603# kodak_portra_160_++ | kodak_portra_160_- | kodak_portra_160_nc | kodak_portra_160_nc_+ | kodak_portra_160_nc_++ | \ 1604# kodak_portra_160_nc_- | kodak_portra_160_vc | kodak_portra_160_vc_+ | kodak_portra_160_vc_++ | \ 1605# kodak_portra_160_vc_- | kodak_portra_400 | kodak_portra_400_+ | kodak_portra_400_++ | kodak_portra_400_- | \ 1606# kodak_portra_400_nc | kodak_portra_400_nc_+ | kodak_portra_400_nc_++ | kodak_portra_400_nc_- | \ 1607# kodak_portra_400_uc | kodak_portra_400_uc_+ | kodak_portra_400_uc_++ | kodak_portra_400_uc_- | \ 1608# kodak_portra_400_vc | kodak_portra_400_vc_+ | kodak_portra_400_vc_++ | kodak_portra_400_vc_- | kodak_portra_800 | \ 1609# kodak_portra_800_+ | kodak_portra_800_++ | kodak_portra_800_- | kodak_portra_800_hc | kodak_t-max_100 | \ 1610# kodak_t-max_3200 | kodak_t-max_400 | kodak_tmax_3200 | kodak_tmax_3200_+ | kodak_tmax_3200_++ | kodak_tmax_3200_- | \ 1611# kodak_tmax_3200_alt | kodak_tri-x_400 | kodak_tri-x_400_+ | kodak_tri-x_400_++ | kodak_tri-x_400_- | \ 1612# kodak_tri-x_400_alt | korben_214 | landscape_01 | landscape_02 | landscape_03 | landscape_04 | landscape_05 | \ 1613# landscape_1 | landscape_10 | landscape_2 | landscape_3 | landscape_4 | landscape_5 | landscape_6 | landscape_7 | \ 1614# landscape_8 | landscape_9 | lateafternoonwanderlust | latesunset | lc_1 | lc_10 | lc_2 | lc_3 | lc_4 | lc_5 | \ 1615# lc_6 | lc_7 | lc_8 | lc_9 | lenox_340 | life_giving_tree | light_blown | lomo | lomography_redscale_100 | \ 1616# lomography_x-pro_slide_200 | london_nights | louetta | low_contrast_blue | low_key_01 | lucky_64 | \ 1617# lushgreensummer | magenta_day | magenta_day_01 | magenta_dream | magenta_yellow | magentacoffee | matrix | \ 1618# mckinnon_75 | memories | metropolis | milo_5 | minimalistcaffeination | modern_film | modern_films_01 | \ 1619# modern_films_02 | modern_films_03 | modern_films_04 | modern_films_05 | modern_films_06 | modern_films_07 | \ 1620# mono_tinted | monochrome | monochrome_1 | monochrome_2 | moody_1 | moody_10 | moody_2 | moody_3 | moody_4 | \ 1621# moody_5 | moody_6 | moody_7 | moody_8 | moody_9 | moonlight | moonlight_01 | moonrise | morning_6 | morroco_16 | \ 1622# mostly_blue | moviz_1 | moviz_10 | moviz_11 | moviz_12 | moviz_13 | moviz_14 | moviz_15 | moviz_16 | moviz_17 | \ 1623# moviz_18 | moviz_19 | moviz_2 | moviz_20 | moviz_21 | moviz_22 | moviz_23 | moviz_24 | moviz_25 | moviz_26 | \ 1624# moviz_27 | moviz_28 | moviz_29 | moviz_3 | moviz_30 | moviz_31 | moviz_32 | moviz_33 | moviz_34 | moviz_35 | \ 1625# moviz_36 | moviz_37 | moviz_38 | moviz_39 | moviz_4 | moviz_40 | moviz_41 | moviz_42 | moviz_43 | moviz_44 | \ 1626# moviz_45 | moviz_46 | moviz_47 | moviz_48 | moviz_5 | moviz_6 | moviz_7 | moviz_8 | moviz_9 | mute_shift | \ 1627# muted_01 | muted_fade | mysticpurplesunset | nah | natural_vivid | nemesis | neon_770 | neutral_pump | \ 1628# neutral_teal_orange | neutral_warm_fade | newspaper | night_01 | night_blade_4 | night_king_141 | night_spy | \ 1629# nightfromday | nightlife | nostalgiahoney | nostalgic | nw-1 | nw-10 | nw-2 | nw-3 | nw-4 | nw-5 | nw-6 | nw-7 | \ 1630# nw-8 | nw-9 | old_west | once_upon_a_time | only_red | only_red_and_blue | operation_yellow | orange_dark_4 | \ 1631# orange_dark_7 | orange_dark_look | orange_tone | orange_underexposed | oranges | paladin | paladin_1875 | \ 1632# pasadena_21 | passing_by | pink_fade | pitaya_15 | pmcinematic_01 | pmcinematic_02 | pmcinematic_03 | \ 1633# pmcinematic_04 | pmcinematic_05 | pmcinematic_06 | pmcinematic_07 | pmnight_01 | pmnight_02 | pmnight_03 | \ 1634# pmnight_04 | pmnight_05 | polaroid_664 | polaroid_665 | polaroid_665_+ | polaroid_665_++ | polaroid_665_- | \ 1635# polaroid_665_-- | polaroid_665_negative | polaroid_665_negative_+ | polaroid_665_negative_- | \ 1636# polaroid_665_negative_hc | polaroid_667 | polaroid_669 | polaroid_669_+ | polaroid_669_++ | polaroid_669_+++ | \ 1637# polaroid_669_- | polaroid_669_-- | polaroid_669_cold | polaroid_669_cold_+ | polaroid_669_cold_- | \ 1638# polaroid_669_cold_-- | polaroid_672 | polaroid_690 | polaroid_690_+ | polaroid_690_++ | polaroid_690_- | \ 1639# polaroid_690_-- | polaroid_690_cold | polaroid_690_cold_+ | polaroid_690_cold_++ | polaroid_690_cold_- | \ 1640# polaroid_690_cold_-- | polaroid_690_warm | polaroid_690_warm_+ | polaroid_690_warm_++ | polaroid_690_warm_- | \ 1641# polaroid_690_warm_-- | polaroid_polachrome | polaroid_px-100uv+_cold | polaroid_px-100uv+_cold_+ | \ 1642# polaroid_px-100uv+_cold_++ | polaroid_px-100uv+_cold_+++ | polaroid_px-100uv+_cold_- | polaroid_px-100uv+_cold_-- | \ 1643# polaroid_px-100uv+_warm | polaroid_px-100uv+_warm_+ | polaroid_px-100uv+_warm_++ | polaroid_px-100uv+_warm_+++ | \ 1644# polaroid_px-100uv+_warm_- | polaroid_px-100uv+_warm_-- | polaroid_px-680 | polaroid_px-680_+ | polaroid_px-680_++ | \ 1645# polaroid_px-680_- | polaroid_px-680_-- | polaroid_px-680_cold | polaroid_px-680_cold_+ | polaroid_px-680_cold_++ | \ 1646# polaroid_px-680_cold_++_alt | polaroid_px-680_cold_- | polaroid_px-680_cold_-- | polaroid_px-680_warm | \ 1647# polaroid_px-680_warm_+ | polaroid_px-680_warm_++ | polaroid_px-680_warm_- | polaroid_px-680_warm_-- | \ 1648# polaroid_px-70 | polaroid_px-70_+ | polaroid_px-70_++ | polaroid_px-70_+++ | polaroid_px-70_- | polaroid_px-70_-- | \ 1649# polaroid_px-70_cold | polaroid_px-70_cold_+ | polaroid_px-70_cold_++ | polaroid_px-70_cold_- | \ 1650# polaroid_px-70_cold_-- | polaroid_px-70_warm | polaroid_px-70_warm_+ | polaroid_px-70_warm_++ | \ 1651# polaroid_px-70_warm_- | polaroid_px-70_warm_-- | polaroid_time_zero_expired | polaroid_time_zero_expired_+ | \ 1652# polaroid_time_zero_expired_++ | polaroid_time_zero_expired_- | polaroid_time_zero_expired_-- | \ 1653# polaroid_time_zero_expired_--- | polaroid_time_zero_expired_cold | polaroid_time_zero_expired_cold_- | \ 1654# polaroid_time_zero_expired_cold_-- | polaroid_time_zero_expired_cold_--- | portrait_1 | portrait_10 | portrait_2 | \ 1655# portrait_3 | portrait_4 | portrait_5 | portrait_6 | portrait_7 | portrait_8 | portrait_9 | progressen | \ 1656# protect_highlights_01 | prussian_blue | pseudogrey | purple | purple_2 | red_afternoon_01 | red_day_01 | \ 1657# red_dream_01 | redblueyellow | reds | reds_oranges_yellows | reeve_38 | remy_24 | rest_33 | retro | \ 1658# retro_brown_01 | retro_magenta_01 | retro_summer_3 | retro_yellow_01 | rollei_ir_400 | rollei_ortho_25 | \ 1659# rollei_retro_100_tonal | rollei_retro_80s | rotate_muted | rotate_vibrant | rotated | rotated_crush | \ 1660# saturated_blue | saving_private_damon | science_fiction | sea | serenity | seringe_4 | serpent | \ 1661# seventies_magazine | sevsuz | shade_kings_ink | shadow_king_39 | shine | skin_tones | smart_contrast | smokey | \ 1662# smooth_clear | smooth_cromeish | smooth_fade | smooth_green_orange | smooth_sailing | smooth_teal_orange | \ 1663# soft_fade | softwarming | solarized_color | solarized_color_2 | springmorning | sprocket_231 | spy_29 | street | \ 1664# studio_skin_tone_shaper | subtle_blue | subtle_green | subtle_yellow | summer | summer_alt | sunlightlove | sunny | \ 1665# sunny_alt | sunny_rich | sunny_warm | sunset_aqua_orange | sunset_intense_violet_blue | sunset_violet_mood | \ 1666# super_warm | super_warm_rich | sutro_fx | sweet_bubblegum | sweet_gelatto | taiga | tarraco | teal_fade | \ 1667# teal_moonlight | tealmagentagold | tealorange | tealorange_1 | tealorange_2 | tealorange_3 | \ 1668# technicalfx_backlight_filter | teigen_28 | tensiongreen_1 | tensiongreen_2 | tensiongreen_3 | tensiongreen_4 | \ 1669# terra_4 | the_matrices | thriller_2 | toastedgarden | trent_18 | true_colors_8 | turkiest_42 | tweed_71 | \ 1670# ultra_water | undeniable | undeniable_2 | unknown | urban_01 | urban_02 | urban_03 | urban_04 | urban_05 | \ 1671# urban_cowboy | uzbek_bukhara | uzbek_marriage | uzbek_samarcande | velvetia | very_warm_greenish | vfb_21 | \ 1672# vibrant | vibrant_alien | vibrant_contrast | vibrant_cromeish | victory | vintage | vintage_01 | vintage_02 | \ 1673# vintage_03 | vintage_04 | vintage_05 | vintage_163 | vintage_alt | vintage_brighter | vintage_chrome | \ 1674# vintage_mob | vintage_warmth_1 | violet_taste | vireo_37 | warm | warm_dark_contrasty | warm_fade | warm_fade_1 | \ 1675# warm_highlight | warm_neutral | warm_sunset_red | warm_teal | warm_vintage | warm_yellow | well_see | western | \ 1676# westernlut_2 | whiter_whites | winterlighthouse | wipe | wooden_gold_20 | yellow_55b | yellow_film_01 | \ 1677# yellowstone | you_can_do_it | zed_32 | zeke_39 | zilverfx_bw_solarization | zilverfx_infrared | \ 1678# zilverfx_vintage_bw }#@cli : Default values: 'resolution=33' and 'cut_and_round=1'. 1679#@cli : $ clut summer clut alien_green,17 clut orange_dark4,48 1680+clut : check "isnum(${2=33}) && $2>0 && isbool(${3=1})" 1681 to_clutname "$1" name=${} l[] 1682 e[^-1] "Input CLUT '"$name"' with resolution $2." 1683 path_clut=${-path_cache} 1684 if isfile(['{/${path_clut}clut_$name.cimgz}']) i ${path_clut}clut_$name.cimgz fi 1685 if $!"!=1 || w<$2 || h<$2 || d<$2" # Decompression needed 1686 rm input_cached gmic_cluts.gmz k[${"nmd 1,"$name}] 1687 if $!!=1 1688 rm i https://gmic.eu/gmic_cluts.gmz o ${path_clut}gmic_cluts.gmz # Try getting newest version of the CLUTs file 1689 repeat $! if ['{$>,n}']==['$name'] k[$>] break fi done 1690 if $!!=1 1691 error[0--5] "Command '$0': Unknown CLUT name '"$name"'." 1692 fi 1693 fi 1694 decompress_clut $2,$2,$2 1695 if $3 round c 0,255 to_rgb fi 1696 o. ${path_clut}clut_$name.cimgz 1697 elif "w>$2 || h>$2 || d>$2" r $2,$2,$2,3,2 # Downsize from higher resolution 1698 fi 1699 nm $name k. 1700 endl 1701 1702# [Internal] Use this command to 'clean' a .gmz file that represents CLUT keypoints. 1703# What it does is: 1704# 1705# - Standardize CLUT name. 1706# - Convert RGB CLUTs to Grayscale when possible. 1707# - Remove duplicates and sort by lexicographic order. 1708# - Display list of CLUTs to ease documentation update of command 'clut'. 1709# 1710clean_cluts : 1711 e[^-1] "Clean CLUT dataset.\n" 1712 round c 0,255 1713 1714 # Standardize names. 1715 repeat $! l[$>] 1716 nm={n} 1717 1718 # Standardize names for 'Moviz'. 1719 if "str = lowercase(['"$nm"*']); 1720 find(str,'tpf_-_cinematica_')==0" l[] 1721 if !narg($tpf) tpf=1 fi 1722 ('moviz_$tpf') 1723 tpf+=1 1724 nm={t} rm 1725 endl fi 1726 if "str = lowercase(['"$nm"*']); 1727 find(str,'_-_standard-vk')>=0" l[] 1728 if !narg($tpf) tpf=1 fi 1729 ('moviz_$tpf') 1730 tpf+=1 1731 nm={t} rm 1732 endl fi 1733 1734 # Standardize names for 'SmallHD MovieLook'. 1735 if "str = lowercase(['"$nm"*']); 1736 find(str,'_-_rec_709*')>=0" l[] 1737 ('$nm') z. 0,{w-11} 1738 nm={t} rm 1739 endl fi 1740 1741 # Standardize names for 'SmallHD MovieLook'. 1742 if "str = lowercase(['"$nm"']); 1743 find(str,'smallhd_movielook_')==0" l[] 1744 ('$nm') z. 18,100% 1745 replace_str "apocalypsethisverymoment","apocalypse_this_very_moment" 1746 replace_str "bobford","bob_ford" 1747 replace_str "lifegivingtree","life_giving_tree" 1748 replace_str "savingprivatedamon","saving_private_damon" 1749 replace_str "thematrices","the_matrices" 1750 nm={t} rm 1751 endl fi 1752 1753 # Standardize names for 'Fuji XTrans III'. 1754 if "str = lowercase(['"$nm"']); 1755 find(str,'fuji_xtrans_iii')==0" l[] 1756 ('$nm') 1757 replace_str "_-_","_" nm={t} rm 1758 endl fi 1759 1760 # Standardize names for 'RawTherapee'. 1761 if "str = lowercase(['"$nm"']); 1762 find(str,'kodak')==0 || 1763 find(str,'polaroid')==0 || 1764 find(str,'fuji')==0 || 1765 find(str,'ilford')==0" l[] 1766 ({'$nm'},{'*'}) 1767 replace_str " ","_" 1768 replace_str "xp_2","xp2" 1769 replace_str "hp_5","hp5" 1770 repeat 8 n={1+$>} 1771 replace_str "_"${n}"_+","_+" 1772 replace_str "_"${n}"_-","_-" 1773 replace_str "_"${n}"_alt","_alt" 1774 replace_str "_"${n}"_Alt","_alt" 1775 replace_str "_"${n}"*","*" 1776 done 1777 = 0,0,100% nm={t} rm 1778 endl fi 1779 1780 to_clutname $nm nm=${} 1781 1782 # Standardize names for 'PictureFX'. 1783 if "str = lowercase(['"$nm"']); 1784 find(str,'technicalfx')==0 || 1785 find(str,'picturefx')==0 || 1786 find(str,'analogfx')==0 || 1787 find(str,'goldfx')==0 || 1788 find(str,'zilverfx')==0" l[] 1789 ('$nm') 1790 replace_str "-","_" nm={t} rm 1791 endl fi 1792 1793 # Other name changes. 1794 l[] 1795 ({'$nm'},{'*'}) 1796 replace_str "_v_2*","*" 1797 replace_str "_v_1*","*" 1798 replace_str "_*","*" 1799 replace_str "_b_w","_bw" 1800 replace_str "&","" 1801 replace_str "rec_709_-_","rec709_" 1802 replace_str "s-log","slog" 1803 replace_str "__","_" 1804 replace_str "action_-_","action_" 1805 replace_str "-version-","" 1806 replace_str "picturefx_","" 1807 = 0,0,100% nm={t} rm 1808 endl 1809 nm $nm 1810 endl done 1811 1812 # Convert RGB CLUTs to Grayscale when possible. 1813 repeat $! l[$>] 1814 if "ref(crop(#0,0,0,0,3,1,h,1,1),R); 1815 ref(crop(#0,0,0,0,4,1,h,1,1),G); 1816 ref(crop(#0,0,0,0,5,1,h,1,1),B); 1817 R==G && G==B?1:0" 1818 channels 0,3 1819 fi 1820 endl done 1821 1822 # Search for duplicates and sort. 1823 p=0 for $p<$! 1824 nm0={$p,n} 1825 e[] "\r- Search duplicates for ["$p"] = '"$nm0"' " 1826 q={$p+1} for $q<$! 1827 nm={$q,n} 1828 if ['$nm0']==['$nm'] 1829 e[] " > Found duplicate ["$q"] -> Original 1x"{$p,h}", new 1x"{$q,h}"\n" 1830 rv[$p,$q] rm[$q] 1831 else q+=1 1832 fi 1833 done 1834 p+=1 1835 done 1836 sort_list +,n 1837 1838 # Display all clut names. 1839 doc="#@cli clut : \"clut_name\",_resolution>0,_cut_and_round={ 0=no | 1=yes }\n"\ 1840 "#@cli : Insert one of the "$!" pre-defined CLUTs at the end of the image list.\\n\n"\ 1841 "#@cli : 'clut_name' can be {" sep="|" 1842 nbc=28 1843 repeat $! l[$>] 1844 if !$< sep="}" fi 1845 str=" "{n}" "$sep 1846 s_str={size(['$str'])} 1847 nbc+=$s_str 1848 if $nbc<118 1849 doc=${doc}${str} 1850 else 1851 doc=${doc}" \\\n#"${str} 1852 nbc={1+$s_str} 1853 fi 1854 endl done 1855 1856 doc=${doc}"\n"\ 1857 "#@cli : Default values: 'resolution=33' and 'cut_and_round=1'.\n"\ 1858 "#@cli : $ clut summer clut alien_green,17 clut orange_dark4,48\n" 1859 e[] "\n"$doc 1860 1861#@cli m : eq. to 'command'. : (+) 1862 1863#@cli command : _add_debug_info={ 0 | 1 },{ filename | http[s]://URL | "string" } : (+) 1864#@cli : Import G'MIC custom commands from specified file, URL or string. 1865#@cli : (eq. to 'm').\n 1866#@cli : Imported commands are available directly after the 'command' invocation. 1867#@cli : Default value: 'add_debug_info=1'. 1868#@cli : $ image.jpg command "foo : mirror y deform $""1" +foo[0] 5 +foo[0] 15 1869 1870# compress_gmic 1871# Compress .gmic custom command files for compressing update files a little bit, 1872# by removing empty lines, and useless comments. 1873compress_gmic : 1874 merge_multiline_comments 1875 merge_multiline 1876 eval " # Remove useless comments 1877 p = 0; 1878 while (p<h, 1879 q = find(#-1,_'\n',p)%h; 1880 p==q?++p:( 1881 i[p]==_'#'?( # Line starts with a '#' 1882 ref(crop(0,p,1,5),cr); 1883 cr!='#@gui' && cr!='#@cli' && cr!='#@web'?copy(i[p],-1,q-p+1,1,0); # Remove comment line 1884 ):( # Line doesn't start with a '#' -> look for comment at line end 1885 l = find(#-1,_'#',p); 1886 l>=0 && l<q && i[l-1]<=_' '?( 1887 while (i[--l]<=_' ',0); 1888 copy(i[l+1],-1,q-l-1,1,0); 1889 ); 1890 0; 1891 ); 1892 p = q + 1; 1893 ); 1894 )" 1895 discard -1 1896 autocrop. {_'\n'} 1897 eval. "* # Merge consecutive line feeds 1898 i==_'\n' && j[1]==_'\n'?(i()=-1)" 1899 discard. -1 1900 eval. "* # Remove leading spaces on each line 1901 i<=_' ' && i!=_'\n' && j[-1]==_'\n'?( 1902 for (p = 1, j[p] && j[p]<=_' ' && j[p]!=_'\n', ++p); copy(i(),-1,p,1,0))" 1903 discard. -1 1904 1905#@cli cursor : _mode = { 0=hide | 1=show } : (+) 1906#@cli : Show or hide mouse cursor for selected instant display windows. 1907#@cli : Command selection (if any) stands for instant display window indices instead of image indices. 1908#@cli : Default value: 'mode=1'. 1909 1910# csv2ts : _output_locale 1911# Convert selected buffers from .csv format to .ts format (translation files for G'MIC-Qt). 1912# Default value: 'output_locale=fr'. 1913csv2ts : skip "${1=fr}" 1914 e[^-1] "Convert buffer$? from .csv format to .ts format (in '$1' locale)." 1915 repeat $! l[$>] if w>1 1916 ('"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\n\n\ 1917 "<!DOCTYPE TS>"\n\ 1918 "<TS version=\"2.1\" language=\"$1\">"\n\ 1919 "<context>"\n\ 1920 " <name>FilterTextTranslator</name>"\n\n':y) 1921 repeat h#0 1922 str={0,`I(0,$>)`} 1923 tr={0,`I(1,$>)`} 1924 if s=['$tr'];s!=0" && norm(s-=_' ')" 1925 ({'$str'}) autocrop. {'" "'} _gmd_ascii2html. str={t} rm. 1926 ({'$tr'}) autocrop. {'" "'} _gmd_ascii2html. tr={t} rm. 1927 1928 if {0,!i(2,$>)} # Global translation 1929 ('" <message>"\n\ 1930 " <source>"$str"</source>"\n\ 1931 " <translation>"$tr"</translation>"\n\ 1932 " </message>"\n\n':y) 1933 else # Filter specialization 1934 i=2 1935 for {0,i($i,$>)} 1936 path={0,`I($i,$>)`} {('$path')} autocrop. {'" "'} _gmd_ascii2html. path={t} rm. 1937 ('" <message>"\n\ 1938 " <source>"$str"</source>"\n\ 1939 " <comment>"{0,`I($i,$>)`}"</comment>"\n\ 1940 " <translation>"$tr"</translation>"\n\ 1941 " </message>"\n':y) 1942 i+=1 1943 done 1944 r. 1,{h+1},1,1,0,1 # Last item has two endl 1945 fi 1946 fi 1947 done 1948 ('"</context>\n</TS>"\n':y) 1949 a[^0] y k. 1950 fi endl done 1951 1952#@cli delete : filename1[,filename2,...] : (+) 1953#@cli : Delete specified filenames on disk. Multiple filenames must be separated by commas. 1954 1955#@cli d : eq. to 'display'. : (+) 1956 1957#@cli display : _X[%]>=0,_Y[%]>=0,_Z[%]>=0,_exit_on_anykey={ 0 | 1 } : (+) 1958#@cli : Display selected images in an interactive viewer (use the instant display window [0] if opened). 1959#@cli : (eq. to 'd').\n 1960#@cli : Arguments 'X','Y','Z' determine the initial selection view, for 3D volumetric images. 1961#@cli : Default value: 'X=Y=Z=0' and 'exit_on_anykey=0'. 1962#@cli : $$ https://gmic.eu/oldtutorial/_display 1963 1964#@cli d0 : eq. to 'display0'. 1965d0 : 1966 _gmic_s="$?" v + _display2d 0,0 1967 1968#@cli display0 1969#@cli : Display selected images without value normalization. 1970#@cli : (eq. to 'd0'). 1971display0 : 1972 _gmic_s="$?" v + _display2d 0,0 1973 1974#@cli d2d : eq. to 'display2d'. 1975d2d : 1976 _gmic_s="$?" v + _display2d 0,1 1977 1978_d2d_core : 1979 _gmic_s="$?" _d2d_core=1 v + _display2d $1,1 1980 1981#@cli display2d 1982#@cli : Display selected 2d images in an interactive window. 1983#@cli : (eq. to 'd2d'). 1984#@cli : This command is used by default by command 'display' when displaying 2d images. 1985#@cli : If selected image is a volumetric image, each slice is displayed on a separate display 1986#@cli : window (up to 10 images can be displayed simultaneously this way), with synchronized moves. 1987#@cli : When interactive window is opened, the following actions are possible: 1988#@cli : * Left mouse button: Create an image selection and zoom into it. 1989#@cli : * Middle mouse button, or CTRL+left mouse button: Move image. 1990#@cli : * Mouse wheel or PADD+/-: Zoom in/out. 1991#@cli : * Arrow keys: Move image left/right/up/down. 1992#@cli : * `CTRL + A`: Enable/disable transparency (show/hide alpha channel). 1993#@cli : * `CTRL + C`: Decrease window size. 1994#@cli : * `CTRL + D`: Increase window size. 1995#@cli : * `CTRL + F`: Toggle fullscreen mode. 1996#@cli : * `CTRL + N`: Change normalization mode (can be { none | normal | channel-by-channel }). 1997#@cli : * `CTRL + O`: Save a copy of the input image, as a numbered file 'gmic_xxxxxx.gmz'. 1998#@cli : * `CTRL + R`: Reset both window size and view. 1999#@cli : * `CTRL + S`: Save a screenshot of the current view, as a numbered file 'gmic_xxxxxx.png'. 2000#@cli : * `CTRL + SPACE`: Reset view. 2001#@cli : * `CTRL + X`: Show/hide axes. 2002#@cli : * `CTRL + Z`: Hold/release aspect ratio. 2003display2d : 2004 _gmic_s="$?" v + _$0 0,1 2005 2006# $1 = exit_on_single_click?, can be { 0=no | 1=yes }. 2007# $2 = default window normalization for display window #0. 2008_display2d : check "isbool(${1=0}) && isint(${2=1}) && $2>=0" 2009 e[0--3] "Start interactive display of 2d image"$_gmic_s"." 2010 m "_d2d_format : 2011 if $""#>=8 u {_([$""*])[0,4]:\\ }\\ ...\\ {_([$""*])[$""#-4,4]:\\ } 2012 else ('\"$""*\"') replace. {','},32 u {t} rm. 2013 fi" 2014 p 2015 repeat $! l[$>] 2016 ('{n}') if s=crop();find(s,_'.',size(s)-1,-1)>0 nm={-2,b}.{-2,x} else nm={-2,b} fi rm. 2017 nm img 2018 2019 if !w v - d v + break fi 2020 if d>10 2021 error[0--6] "Command 'display2d': Input image has "{d}" slices, cannot manage more than 10 simultaneous views." 2022 fi 2023 is_multiview={d>1} 2024 is_moderate_ratio={0,D=[w,h];max(D)/min(D)<6} 2025 may_have_alpha={s==2||s>=4} 2026 alpha_mode,axes_mode,fullscreen_mode,ratio_mode={s==1||s==3},1,0,$is_moderate_ratio 2027 normalization_mode={{*}?!!{*,n}:$2} 2028 posx,posy,sizx,sizy={0,[0,0,w,h]} 2029 is_bottom_text,wait_event,mx,my,omb=0,1,-1,-1,0 2030 xsel0,ysel0,xsel1,ysel1,notification= 2031 wnormalization0={*,n} 2032 fontsize,fontsize_notif= 2033 2034 if $is_multiview" && "!${-is_macos} 2035 if d==2 if {*,u}/w>={*,v}/h wsiz0={r={*,u}*0.48;round([r,r*h/w])} else wsiz0={r={*,v}*0.40;round([r*w/h,r])} fi 2036 elif d<=4 wsiz0=${fitscreen\ .,,45%} 2037 else wsiz0=${fitscreen\ .,,30%} 2038 fi 2039 wsiz0=${fitscreen\ $wsiz0,1,,90%} 2040 else wsiz0=${fitscreen\ .} 2041 fi 2042 2043 if $is_multiview 2044 if narg($_d2d_names) l[] $_d2d_names repeat $! wname$>={$>,t} done rm endl fi 2045 com_iskey,com_flushkey,com_isvisible,com_isresized,com_idisp,sep= 2046 repeat {img,d} 2047 if narg($_d2d_names) w$>[] {{*$>,w}?[-1,-1]:[$wsiz0]},0,${wname$>}" ("{w}x{h}x{d}x{s}")" 2048 else w$>[] {{*$>,w}?[-1,-1]:[$wsiz0]},0,$nm" ("{w}x{h}x{d}x{s}")-#"$> 2049 fi 2050 com_iskey.=$sep"{*"$>",$""1}" 2051 com_flushkey.=$sep"{*"$>",-$""1}" 2052 com_isvisible.=$sep"{*"$>"}" 2053 com_isresized.=$sep"{*"$>",r}" 2054 com_idisp.=$sep"{*"$>",x}" 2055 sep=, 2056 done 2057 m "iskey : u {max("$com_iskey")}"\n\ 2058 "flushkey : skip "$com_flushkey\n\ 2059 "isvisible : u {min("$com_isvisible")}"\n\ 2060 "isresized : u {max("$com_isresized")}"\n\ 2061 "idisp : u {argmax("$com_idisp")}" 2062 2063 # Auto-arrange display window layout in multi-view mode. 2064 if !${-is_macos} 2065 ww,wh={[$wsiz0]+[8,40]} 2066 if d==2 2067 if {*,u}/$ww>{*,v}/$wh # Horizontal alignment 2068 ox,oy={round([max(0,{*,u}-2*$ww),max(0,{*,v}-$wh)]/2)} 2069 w0[] -1,-1,-1,-1,$ox,$oy 2070 w1[] -1,-1,-1,-1,{$ox+$ww},$oy 2071 else # Vertical alignment 2072 ox,oy={round([{*,u}-$ww,{*,v}-2*$wh]/2)} 2073 w0[] -1,-1,-1,-1,$ox,$oy 2074 w1[] -1,-1,-1,-1,$ox,{$oy+$wh} 2075 fi 2076 elif d<=4 2077 ox,oy={round([max(0,{*,u}-2*$ww),max(0,{*,v}-2*$wh)]/2)} 2078 ww,wh+=$ox,$oy 2079 w0[] -1,-1,-1,-1,$ox,$oy 2080 w1[] -1,-1,-1,-1,$ww,$oy 2081 w2[] -1,-1,-1,-1,$ox,$wh 2082 if d==4 w3[] -1,-1,-1,-1,$ww,$wh fi 2083 else 2084 ox,oy={round([max(0,{*,u}-3*$ww),max(0,{*,v}-(d>6?3:2)*$wh)]/2)} 2085 ww2,wh2={2*[$ww,$wh]+[$ox,$oy]} 2086 ww,wh+=$ox,$oy 2087 w0[] -1,-1,-1,-1,$ox,$oy 2088 w1[] -1,-1,-1,-1,$ww,$oy 2089 w2[] -1,-1,-1,-1,$ww2,$oy 2090 w3[] -1,-1,-1,-1,$ox,$wh 2091 w4[] -1,-1,-1,-1,$ww,$wh 2092 if d>5 w5[] -1,-1,-1,-1,$ww2,$wh fi 2093 if d>6 w6[] -1,-1,-1,-1,$ox,$wh2 fi 2094 if d>7 w7[] -1,-1,-1,-1,$ww,$wh2 fi 2095 if d>8 w8[] -1,-1,-1,-1,$ww2,$wh2 fi 2096 fi 2097 fi 2098 2099 else 2100 w[] {{*,w}?[-1,-1]:[$wsiz0]},0,$nm" ("{w}x{h}x{d}x{s}")" 2101 m "iskey : u {*,$""1}"\n\ 2102 "flushkey : skip {*,-$""1}"\n\ 2103 "isvisible : u {*}"\n\ 2104 "isresized : u {*,r}"\n\ 2105 "idisp : u 0" 2106 fi 2107 2108 repeat {img,d} cursor[$>] 0 done 2109 2110 # Start event loop. 2111 for ${-isvisible}" && "!${"iskey ESC"}" && "!((${"iskey CTRLLEFT"}" || "${"iskey CTRLRIGHT"})" && "${"iskey W"}) 2112 2113 # Correct aspect ratio while centering image. 2114 if $ratio_mode" && "$sizx>16" && "$sizy>16 2115 nposx,nposy,nsizx,nsizy=$posx,$posy,$sizx,$sizy 2116 repeat 2 2117 if {*,w}/$sizx<{*,h}/$sizy 2118 nposy,nsizy={nsizy=$nsizx*{*,h}/{*,w};round([$nposy-(nsizy-$nsizy)/2,nsizy])} 2119 else 2120 nposx,nsizx={nsizx=$nsizy*{*,w}/{*,h};round([$nposx-(nsizx-$nsizx)/2,round(nsizx)])} 2121 fi 2122 if $<" && "$nsizx>w#0" && "$nsizy>h#0 nposx,nposy,nsizx,nsizy={[0,0,w#0,h#0]} fi 2123 done 2124 if [$nposx,$nposy,$nsizx,$nsizy]!=[$posx,$posy,$sizx,$sizy] 2125 posx,posy,sizx,sizy=$nposx,$nposy,$nsizx,$nsizy 2126 rmn baseview 2127 fi 2128 fi 2129 2130 # Generate baseview. 2131 if !narg($baseview) 2132 2133 # Get view corresponding to position and zoom factor. 2134 ($posx,{$posx+$sizx}) ($posy;{$posy+$sizy}) r[-2,-1] 2,2 a[-2,-1] c 2135 r. {[{*,w,h}]+1},1,2,3 z. 0,0,{[w,h]-2} round. 1,-1 ind_warp={$!-1} 2136 +channels[0] {0,[0,min(3,s-1)]} warp. ..,0,0,1 2137 if $is_multiview repeat {img,d-1} +slices[img] {1+$>} warp. [$ind_warp],0,0,1 done a[-{img,d}--1] z fi 2138 rm.. 2139 2140 if s>($alpha_mode?4:3) channels. 0,{$alpha_mode?3:2} fi # Discard useless channels 2141 2142 # Check if image potentially contain inf or nan values. 2143 +r[0] 1,1,1,1,2 is_infnan={isnan(i)||isinf(i)} rm. 2144 2145 if $normalization_mode 2146 if $is_infnan 2147 # Find min and max values that are not nan of inf. 2148 eval[0] "*begin(m = inf; M = -inf); 2149 !isinf(i) && !isnan(i)?(m = min(i,m); M = max(i,M)); 2150 end( 2151 merge(m,min); 2152 merge(M,max); 2153 run('im,iM=',m,',',M) 2154 )" 2155 vim,viM={[$im-abs($im),$iM+abs($iM)]} 2156 f. "isnan(i)?"$vim":isinf(i)?(i<0?"$vim":"$viM"):i" 2157 else 2158 im,iM={0,[im,iM]} 2159 fi 2160 2161 else 2162 im,iM=0,255 2163 if $is_infnan f. "isnan(i)?"$im":isinf(i)?(i<0?"$im":"$iM"):i" fi 2164 fi 2165 2166 # Normalize view. 2167 if $normalization_mode==1 2168 sh. 0,{s-($alpha_mode" && "$may_have_alpha?2:1)} 2169 if $is_multiview repeat {img,d} +slices. $> n. 0,255 j.. .,0,0,$> rm. done else n. 0,255 fi 2170 rm. 2171 elif $normalization_mode==2 2172 sh. 0,{s-($alpha_mode" && "$may_have_alpha?2:1)} 2173 if $is_multiview repeat d*s z,c={[$>%d,int($>/d)]} sh. $z,$z,$c n. 0,255 rm. done 2174 else repeat s sh. $> n. 0,255 rm. done 2175 fi 2176 fi 2177 if $posx<0" || "$posy<0" || "$posx+$sizx>=w#0" || "$posy+$sizy>=h#0 2178 100%,100% 2179 rectangle. {A=-[$posx,$posy]*[w,h]/[$sizx,$sizy];\ 2180 B=A+[w#0,h#0]*[w,h]/[$sizx,$sizy]-1;\ 2181 [ceil(A),floor(B)]},1,1 2182 *[-2,-1] 2183 fi 2184 2185 # Add alpha channel if necessary. 2186 if $alpha_mode 2187 coords={A=-[$posx,$posy]*[w,h]/[$sizx,$sizy];\ 2188 B=A+[w#0,h#0]*[w,h]/[$sizx,$sizy]-1;\ 2189 [ceil(A),floor(B)]} 2190 if !$may_have_alpha # Alpha mode without alpha channel -> Add alpha channel 2191 100%,100%,1,1,64 rectangle. $coords,1,255 r. 100%,100%,.. a[-2,-1] c 2192 else # Alpha mode with alpha channel 2193 sh. 100% 100%,100%,1,1,64 rectangle. $coords,1,0 r. 100%,100%,.. +[-2,-1] rm. 2194 fi 2195 fi 2196 2197 # Render image with transparency pattern. 2198 if $alpha_mode 2199 (128,160;160,128) r. 32,32,1,{-2,s-1} r. ..,..,..,100%,0,2,0.5,0.5 sh.. 100% j.. ...,0,0,0,0,1,.,255 rm[-3,-1] 2200 elif s==1 r. 100%,100%,100%,3 2201 elif s==2 r. 100%,100%,100%,3,0 2202 fi 2203 nm. baseview 2204 rmn view 2205 fi 2206 2207 # Manage notifications. 2208 if narg($notification) 2209 wait_event=0 2210 if !isnum($notification) # Create notification gfx 2211 rmn notification_gfx 2212 ofs,fs={narg($fontsize_notif)?0$fontsize_notif:32} 2213 do 2214 0 t. {``$notification},0,0,$fs,1,255 2215 if narg($fontsize_notif) break 2216 elif {baseview,"(w#-1>0.7*w || h#-1>0.25*h) && "$fs>13" && "$ofs>=$fs} 2217 ofs,fs=$fs,{max(13,round($fs/1.25))} rm. 2218 elif {baseview,"w#-1<0.3*w && h#-1<0.25*h && "$fs<64" && "$ofs<=$fs} 2219 ofs,fs=$fs,{min(64,round($fs*1.25))} rm. 2220 else 2221 fontsize_notif=$fs break 2222 fi 2223 while 1 2224 2225 r. {[w+12,h+8]},1,1,0,0,0.5,0.5 rectangle. 0,0,100%,100%,1,0xFFFFFFFF,255 to_rgb. 2226 nm. notification_gfx 2227 notification=$| 2228 else 2229 if $|>$notification+1 rm[notification_gfx] wait_event=1 notification= fi 2230 rmn view 2231 fi 2232 fi 2233 2234 # Generate view. 2235 if !narg($view) 2236 [baseview] 2237 if $mx>=0 2238 posmx,posmy={floor([$posx,$posy]+[$mx,$my]*[$sizx,$sizy]/[{*,w,h}])} 2239 is_selection_a_point={[0$xsel0,0$ysel0]==[0$xsel1,0$ysel1]} 2240 2241 if narg($xsel0)" && "!$is_selection_a_point 2242 dselx,dsely={[$xsel1-$xsel0,$ysel1-$ysel0]} 2243 ofs,fs={narg($fontsize)?0$fontsize:32} 2244 do 2245 0 t. " Box ( "{``{[min($xsel0,$xsel1),min($ysel0,$ysel1)]}}" ) - "\ 2246 "( "{``{[max($xsel0,$xsel1),max($ysel0,$ysel1)]}}" ) \n"\ 2247 " Size = ( "{``{abs([$dselx,$dsely]+1)}}" ), "\ 2248 "Length = "{_norm($dselx,$dsely)}" \n"\ 2249 " Angle = "{_atan2($dsely,$dselx)*180/pi}"\260 ",1,0,$fs,1,1 2250 if narg($fontsize) break 2251 elif {baseview,"(w#-1>0.7*w || h#-1>0.45*h) && "$fs>13" && "$ofs>=$fs} 2252 ofs,fs=$fs,{max(13,round($fs/1.25))} rm. 2253 elif {baseview,"w#-1<0.3*w && h#-1<0.45*h && "$fs<64" && "$ofs<=$fs} 2254 ofs,fs=$fs,{min(64,round($fs*1.25))} rm. 2255 else 2256 fontsize=$fs break 2257 fi 2258 while 1 2259 n. 0,255 +dilate. 3 *. -1 n. 0,80 +[-2,-1] r. 100%,100%,..,.. 2260 j.. .,0,$is_bottom_text~,0,0,0.85 rm. 2261 fi 2262 2263 if $mx>=0 2264 if $posmx>=0" && "$posmx<w#0" && "$posmy>=0" && "$posmy<h#0 2265 if !narg($xsel0)" || "$is_selection_a_point 2266 repeat {img,d} 2267 if {img,P=I($posmx,$posmy,$>);(s>=1" || "s<=4)" && "min(isint(P))" && "min(P)>=0" && "max(P)<=255} 2268 hexstr="= \#"\ 2269 {img,`"digit(x) = (x<10?_'0' + x:_'A' + x - 10);\ 2270 P = I("$posmx,$posmy,$>");\ 2271 [ digit(P[0]>>4),digit(P[0]&15),\ 2272 s<2?0:digit(P[1]>>4),s<2?0:digit(P[1]&15),\ 2273 s<3?0:digit(P[2]>>4),s<3?0:digit(P[2]&15),\ 2274 s<4?0:digit(P[3]>>4),s<4?0:digit(P[3]&15) ]"`}" " 2275 else hexstr= fi 2276 ofs,fs={narg($fontsize)?0$fontsize:32} 2277 do 2278 0 t. " Point ( "$posmx","$posmy" ) = [ "${_d2d_format\ {img,_I($posmx,$posmy,$>)}}" ] "$hexstr,\ 2279 1,0,$fs,1,1 2280 if narg($fontsize) break 2281 elif {baseview,"(w#-1>0.7*w || h#-1>0.15*h) && "$fs>13" && "$ofs>=$fs} 2282 _ofs,fs=$fs,{max(13,round($fs/1.25))} rm. 2283 elif {baseview,"w#-1<0.3*w && h#-1<0.15*h && "$fs<64" && "$ofs<=$fs} 2284 ofs,fs=$fs,{min(64,round($fs*1.25))} rm. 2285 else 2286 fontsize=$fs break 2287 fi 2288 while 1 2289 2290 n. 0,255 +dilate. 3 *. -1 n. 0,80 +[-2,-1] r. 100%,100%,1,.. 2291 j.. .,0,$is_bottom_text~,$>,0,0.85 rm. 2292 done 2293 fi 2294 x0,y0,x1,y1={[round([$posmx-$posx,$posmy-$posy]*[{*,w,h}]/[$sizx,$sizy]),\ 2295 round([$posmx-$posx+1,$posmy-$posy+1]*[{*,w,h}]/[$sizx,$sizy])-1]} 2296 if $x1-$x0>=8" && "$y1-$y0>=8 # Draw pixel contour when zoomed-in 2297 repeat d==1?1:d*s if d==1 sh. else sh. {z=$>%d;[z,z,int($>/d)]} fi 2298 rectangle. $x0,$y0,$x1,$y1,1,0x55555555,0 2299 rectangle. $x0,$y0,$x1,$y1,1,0xAAAAAAAA,255 2300 rm. 2301 done 2302 fi 2303 fi 2304 if $axes_mode # Draw horizontal/vertical axes 2305 repeat d==1?1:d*s if d==1 sh. else sh. {z=$>%d;[z,z,int($>/d)]} fi 2306 line. $mx,0,$mx,100%,0.5,0xFF00FF00,255 2307 line. $mx,0,$mx,100%,0.5,0x00FF00FF,0 2308 line. 0,$my,100%,$my,0.5,0xFF00FF00,255 2309 line. 0,$my,100%,$my,0.5,0x00FF00FF,0 2310 rm. 2311 done 2312 fi 2313 fi 2314 2315 if narg($xsel0) # Draw rectangular selection 2316 x0,y0,x1,y1={xm=min($xsel0,$xsel1);xM=max($xsel0,$xsel1);\ 2317 ym=min($ysel0,$ysel1);yM=max($ysel0,$ysel1);\ 2318 [[xm-$posx,ym-$posy]*[{*,w,h}]/[$sizx,$sizy],\ 2319 [xM+1-$posx,yM+1-$posy]*[{*,w,h}]/[$sizx,$sizy]-1]} 2320 repeat d==1?1:d*s if d==1 sh. else sh. {z=$>%d;[z,z,int($>/d)]} fi 2321 rectangle. $x0,$y0,$x1,$y1,0.2,0 2322 rectangle. $x0,$y0,$x1,$y1,0.9,0x55555555,0 2323 rectangle. $x0,$y0,$x1,$y1,0.9,0xAAAAAAAA,255 2324 rm. 2325 done 2326 if $xsel0>$xsel1 x0,x1=$x1,$x0 fi 2327 if $ysel0>$ysel1 y0,y1=$y1,$y0 fi 2328 if $xsel0!=$xsel1" && "$ysel0!=$ysel1 2329 x0,y0,x1,y1={[(0.5+[$xsel0-$posx,$ysel0-$posy])*[{*,w,h}]/[$sizx,$sizy],\ 2330 (0.5+[$xsel1-$posx,$ysel1-$posy])*[{*,w,h}]/[$sizx,$sizy]]} 2331 repeat d==1?1:d*s if d==1 sh. else sh. {z=$>%d;[z,z,int($>/d)]} fi 2332 line. $x0,$y0,$x1,$y1,0.9,0x33333333,0 2333 line. $x0,$y0,$x1,$y1,0.9,0xCCCCCCCC,255 2334 rm. 2335 done 2336 fi 2337 fi 2338 fi 2339 2340 if $notification_gfx 2341 +r[notification_gfx] 100%,100%,. j.. .,{[w#-2-w-4,4]},0,0,{sqrt(max(0,1-($|-$notification)))} rm. 2342 fi 2343 2344 nm. view 2345 if $is_multiview repeat d +slices[view] $> w$>. rm. done else w. fi 2346 fi 2347 2348 # Manage user events. 2349 if $wait_event wait else wait 40 fi 2350 idisp=${-idisp} # Index of 'active' display window 2351 wait_event=1 2352 2353 old_mx,old_my=$mx,$my 2354 nposx,nposy,nsizx,nsizy=$posx,$posy,$sizx,$sizy 2355 is_CTRL,mb,mx,my,mo={${"iskey CTRLLEFT"}" || "${"iskey CTRLRIGHT"}},{*$idisp,b,x,y,-o} 2356 2357 # Test end of pan shift. 2358 if !($mb&4)" && "!($is_CTRL" && "($mb&1)) pan_mx,pan_my,pan_posx,pan_posy= fi 2359 2360 # Test if text must be displayed at the bottom. 2361 if {view,$my<0" || "$my>=h-16} is_bottom_text=0 2362 elif $my<16 is_bottom_text=1 2363 fi 2364 2365 # Events related to window resizing. 2366 if ${-isresized} # One of the display windows has been resized 2367 repeat {img,d},w if {*$w,r} 2368 w$w[] {*$w,d,e} 2369 if $is_multiview repeat {img,d} w$>[] {*$w,w,h} done fi 2370 if $nsizx>w#0" && "$nsizy>h#0 nposx,nposy,nsizx,nsizy={[0,0,w#0,h#0]} fi 2371 break 2372 fi done 2373 fontsize,fontsize_notif= 2374 rmn baseview 2375 elif $is_CTRL" && "${"iskey D"}" && "{*$idisp,d}<{*$idisp,u}" && "{*$idisp,e}<{*$idisp,v} # Increase window size 2376 w$idisp[] {round([{*$idisp,w,h}]*1.25)} 2377 if $is_multiview repeat {img,d} w$>[] {*$idisp,w,h} done fi 2378 notification="Increase Window Size" 2379 fontsize,fontsize_notif= 2380 flushkey D rmn baseview 2381 elif $is_CTRL" && "${"iskey C"}" && "{*$idisp,d}>64" && "{*$idisp,e}>64 # Decrease window size 2382 w$idisp[] {round([{*$idisp,w,h}]/1.25)} 2383 if $is_multiview repeat {img,d} w$>[] {*$idisp,w,h} done fi 2384 notification="Decrease Window Size" 2385 fontsize,fontsize_notif= 2386 flushkey C rmn baseview 2387 elif $is_CTRL" && "${"iskey R"} # Reset window size (and view) 2388 nposx,nposy,nsizx,nsizy={0,[0,0,w,h]} 2389 repeat {img,d} w$>[] $wsiz0 done 2390 notification="Reset Window Size" 2391 fontsize,fontsize_notif= 2392 flushkey R rmn baseview 2393 fi 2394 2395 # Events related to image selection. 2396 if !$is_CTRL" && "$mb&1" && "$mx>0 2397 xsel,ysel={X=[$nposx,$nposy]+[$mx,$my]*[$nsizx,$nsizy]/[{*,w,h}];\ 2398 floor([max(0,min(X[0],w#0-1)),max(0,min(X[1],h#0-1))])} 2399 if !narg($xsel0)" && "!($omb&1) xsel0,ysel0,xsel1,ysel1=$xsel,$ysel,$xsel,$ysel 2400 elif narg($xsel0) xsel1,ysel1=$xsel,$ysel 2401 fi 2402 if $mx<=16 nposx-={$nsizx/64} wait_event=0 xzoom,yzoom= 2403 elif $mx>={*,w}-17 nposx+={$nsizx/64} wait_event=0 xzoom,yzoom= 2404 fi 2405 if $my<=16 nposy-={$nsizy/64} wait_event=0 xzoom,yzoom= 2406 elif $my>{*,h}-17 nposy+={$nsizx/64} wait_event=0 xzoom,yzoom= 2407 fi 2408 wait_event=0 2409 rmn view 2410 elif !($mb&1) 2411 if narg($xsel0) 2412 2413 if "p0 = ["$xsel0,$ysel0]"; p1 = ["$xsel1,$ysel1"]; # One px selection -> reset view or exit. 2414 siz = max("$sizx,$sizy"); 2415 p0==p1 || (siz>128 && norm1(p1-p0)<=siz/100)" 2416 if $1" && "$nsizx>=w#0" && "$nsizy>=h#0 break fi 2417 nposx,nposy,nsizx,nsizy={0,[0,0,w,h]} 2418 else # Otherwise, zoom in 2419 nposx,nposy,nsizx,nsizy={[min($xsel0,$xsel1),min($ysel0,$ysel1),abs([$xsel1-$xsel0,$ysel1-$ysel0])+1]} 2420 fi 2421 xzoom,yzoom= mb={$mb&6} 2422 rmn view 2423 fi 2424 xsel0,ysel0,xsel1,ysel1= 2425 fi 2426 2427 # Events related to image displacement and mode changes. 2428 if ${"iskey ARROWLEFT"} nposx-={$nsizx/($is_CTRL?4:16)} xzoom,yzoom= # Go left 2429 elif ${"iskey ARROWRIGHT"} nposx+={$nsizx/($is_CTRL?4:16)} xzoom,yzoom= # Go right 2430 elif ${"iskey ARROWUP"} nposy-={$nsizy/($is_CTRL?4:16)} xzoom,yzoom= # Go up 2431 elif ${"iskey ARROWDOWN"} nposy+={$nsizy/($is_CTRL?4:16)} xzoom,yzoom= # Go down 2432 elif $is_CTRL" && "${"iskey O"} # Save copy 2433 n=0 do filename gmic.gmz,$n n+=1 while isfile(['{/${}}']) 2434 if $is_multiview +slices[img] $idisp o. ${} rm. else o[img] ${} fi 2435 notification="Save Copy:\n"${} 2436 flushkey O 2437 elif $is_CTRL" && "${"iskey S"} # Save screenshot 2438 n=0 do filename gmic.png,$n n+=1 while isfile(['{/${}}']) 2439 if $is_multiview +slices[baseview] $idisp o. ${} rm. else o[baseview] ${} fi 2440 notification="Save Screenshot:\n"${} 2441 flushkey S 2442 elif $is_CTRL" && "${"iskey SPACE"} # Center view 2443 nposx,nposy,nsizx,nsizy={0,[0,0,w,h]} 2444 notification="Center View" 2445 flushkey SPACE 2446 elif $is_CTRL" && "${"iskey N"} # Change normalization mode 2447 normalization_mode={($normalization_mode+1)%3} 2448 notification=${"s0=Disable s1=Enable s2=\"Enable C.by.C\" u ${s"$normalization_mode"}"}" Normalization" 2449 flushkey N rmn baseview 2450 elif $is_CTRL" && "${"iskey A"} # Toggle alpha mode 2451 alpha_mode={!$alpha_mode} 2452 notification=${"s0=Disable s1=Enable u ${s"$alpha_mode"}"}" Alpha" 2453 flushkey A rmn baseview 2454 elif $is_CTRL" && "${"iskey F"} # Toggle fullscreen mode 2455 fullscreen_mode={!$fullscreen_mode} 2456 if $fullscreen_mode 2457 fullscreen_wsize={*,w,h} fullscreen_params=$nposx,$nposy,$nsizx,$nsizy 2458 w[] {*,u,v},0,1 2459 else 2460 nposx,nposy,nsizx,nsizy=$fullscreen_params 2461 w[] $fullscreen_wsize,0,0 2462 fi 2463 repeat {img,d} cursor[$>] {!$axes_mode} done 2464 notification=${"s0=Disable s1=Enable u ${s"$fullscreen_mode"}"}" Fullscreen" 2465 flushkey F rmn baseview 2466 elif $is_CTRL" && "${"iskey X"} # Toggle axes mode 2467 repeat {img,d} cursor[$>] $axes_mode done axes_mode={!$axes_mode} 2468 notification=${"s0=Hide s1=Show u ${s"$axes_mode"}"}" Axes" 2469 flushkey X rmn view 2470 elif $is_CTRL" && "${"iskey Z"}" && "$is_moderate_ratio # Toggle aspect-ratio mode 2471 ratio_mode={!$ratio_mode} 2472 notification=${"s0=Release s1=Hold u ${s"$ratio_mode"}"}" Aspect Ratio" 2473 if !$ratio_mode nposx,nposy,nsizx,nsizy={0,[0,0,w,h]} fi 2474 flushkey Z rmn baseview 2475 elif $mx>=0" && "($mb&4" || "($is_CTRL" && "$mb&1)) # Pan (middle mouse button) 2476 if !narg($pan_mx) pan_mx,pan_my,pan_posx,pan_posy=$mx,$my,$posx,$posy fi 2477 nposx,nposy={shiftx=($mx-$pan_mx)*$nsizx/{*,w};\ 2478 shifty=($my-$pan_my)*$nsizy/{*,h};\ 2479 [$pan_posx-shiftx,$pan_posy-shifty]} 2480 xzoom,yzoom= 2481 elif ${"iskey PADSUB"}" || "($mx>=0" && "$mo<0) # Zoom out 2482 if $nsizx>=w#0" && "$nsizy>=h#0 2483 nposx,nposy,nsizx,nsizy={[$nposx/2,$nposy/2,w#0,h#0]} 2484 else 2485 if !narg($xzoom) 2486 xzoom,yzoom={X=$mx<0?[$nposx,$nposy]+[$nsizx,$nsizy]/2:\ 2487 [$nposx,$nposy]+[$mx,$my]*[$nsizx,$nsizy]/[{*,w,h}];\ 2488 [max(0,min(X[0],w#0-1)),max(0,min(X[1],h#0-1))]} 2489 fi 2490 nposx,nposy,nsizx,nsizy={[[$xzoom,$yzoom]+[$nposx-$xzoom,$nposy-$yzoom]/0.75,\ 2491 min(w#0,round($nsizx/0.75)),\ 2492 min(h#0,round($nsizy/0.75))]} 2493 if $nsizx>w#0" && "$nsizy>h#0 nsizx,nsizy={[w#0,h#0]} fi 2494 fi 2495 elif ($nsizx>2" || "$nsizy>2)" && "(${"iskey PADADD"}" || "($mx>=0" && "$mo>0)) # Zoom in 2496 xzoom,yzoom={X=$mx<0?[$nposx,$nposy]+[$nsizx,$nsizy]/2:\ 2497 [$nposx,$nposy]+[$mx,$my]*[$nsizx,$nsizy]/[{*,w,h}];\ 2498 [max(0,min(X[0],w#0-1)),max(0,min(X[1],h#0-1))]} 2499 nposx,nposy,nsizx,nsizy={[[$xzoom,$yzoom]+0.75*[$nposx-$xzoom,$nposy-$yzoom],round(0.75*[$nsizx,$nsizy])]} 2500 fi 2501 2502 # Constrain image displacement. 2503 if $nposx>=w#0-0.5*$nsizx nposx={w#0-1-0.5*$nsizx} 2504 elif $nposx<=-0.5*$nsizx nposx={1-0.5*$nsizx} 2505 fi 2506 if $nposy>=h#0-0.5*$nsizy nposy={h#0-1-0.5*$nsizy} 2507 elif $nposy<=-0.5*$nsizy nposy={1-0.5*$nsizy} 2508 fi 2509 2510 if [$nposx,$nposy,$nsizx,$nsizy]!=[$posx,$posy,$sizx,$sizy] 2511 posx,posy,sizx,sizy=$nposx,$nposy,$nsizx,$nsizy 2512 rmn baseview 2513 fi 2514 if [$mx,$my]!=[$old_mx,$old_my] rmn view fi 2515 omb=$mb 2516 2517 done 2518 k[0] 2519 if narg($_d2d_core) w[] -1,-1,$wnormalization0 2520 else 2521 if $is_multiview repeat d w$>[] 0 done else w[] 0 fi 2522 fi 2523 nm $nm um iskey,flushkey,isvisible,isresized,idisp endl done 2524 um _d2d_format v -1 d[] 2525 2526#@cli d3d : eq. to 'display3d'. 2527d3d : skip "${1=},${2=0}" 2528 l[] is_image_arg=${"is_image_arg $1"} is_arg={$is_image_arg" || isnum($1)"} onfail is_arg=0 endl 2529 if $is_arg arg=$is_image_arg,$2 if $is_image_arg pass$1 1 _d3d_wh={[w,h]} store. _d3d_background fi 2530 else arg=0,0 noarg fi 2531 v + _display3d $arg 2532 2533#@cli display3d : _[background_image],_exit_on_anykey={ 0 | 1 } : _exit_on_anykey={ 0 | 1 } 2534#@cli : Display selected 3D objects in an interactive viewer (use the instant display window [0] if opened). 2535#@cli : (eq. to 'd3d'). 2536#@cli : Default values: '[background_image]=(default)' and 'exit_on_anykey=0'. 2537display3d : skip "${1=},${2=0}" 2538 l[] is_image_arg=${"is_image_arg $1"} is_arg={$is_image_arg" || isnum($1)"} onfail is_arg=0 endl 2539 if $is_arg arg=$is_image_arg,$2 if $is_image_arg pass$1 1 _d3d_wh={[w,h]} store. _d3d_background fi 2540 else arg=0,0 noarg fi 2541 v + _$0 $arg 2542 2543# $1 = is_user_background? 2544# $2 = exit_on_any_key? 2545_display3d : 2546 is_user_background,exit_on_anykey=$1,$2 2547 if !$! e[0--3] "Display 3D object []." return fi 2548 2549 repeat $! l[$>] 2550 l. check3d 0 2551 onfail l[] ({'${}'}) s +,{'"'check3d': "'} k. msg={t} rm endl error[] "Command 'display3d': "$msg 2552 endl 2553 nm={n} nbv,nbp={f2ui([i[6],i[7]])} 2554 e[0--5] "Display 3D object ["{arg(1+$>,$[])}"] = '"$nm"' ("$nbv" vertices, "$nbp" primitives)." 2555 2556 # Init display window and variables. 2557 disp_title=$nm" ("$nbv" vertices, "$nbp" primitives)" 2558 if !{*} 2559 if narg($_d3d_wh) w[] ${fitscreen\ $_d3d_wh,1},0,$disp_title 2560 else w[] {0.7*[{*,u,v}]},0,$disp_title 2561 fi 2562 else disp_normalization={*,n} w[] -1,-1,0,$disp_title fi 2563 disp_size0={*,w,h} 2564 2565 (1,0,0,0;0,1,0,0;0,0,1,0) store. pose3d 2566 posx,posy,zoomfactor=50,50,1 2567 is_fullscreen,is_zbuffer,is_axes3d,is_outline,is_boundingbox,is_animate,is_outvideo={*,f},1,1,0,0,0,0 2568 mode_render=4 2569 mode_drender={$nbp<2048?$mode_render:-1} 2570 mode_background={$is_user_background?7:3} 2571 mode_orientation=2 2572 mode_animate=1 2573 speed_animate=1 2574 focale=800 2575 mx0,my0,mx1,my1= 2576 notification= fontsize_notif= 2577 wait_event=1 2578 2579 # Create 3D axes. 2580 axes3d 40,40,40,20,X,Y,Z,0 col3d. 0,255,0 l. s3d a[0-3] y off_axes={0,h} a y endl nm. axes3d 2581 2582 # Start interactive loop. 2583 do 2584 is_motion={narg($mx0)} 2585 if $is_animate" || "$is_outvideo rmn render fi 2586 2587 # Init background image. 2588 if !narg($background) 2589 if $mode_background<3 {*,w,h},1,3,{arg(1+$mode_background,0,255,128)} 2590 elif $mode_background==3 3,2,1,1,"32,32,64,64,116,96" permute. cyzx r. {*,w,h},1,3,3 round. 2591 elif $mode_background==4 3,2,1,1,"0,0,0,0,64,96" permute. cyzx r. {*,w,h},1,3,3 round. 2592 elif $mode_background==5 3,2,1,1,"8,0,0,160,90,0" permute. cyzx r. {*,w,h},1,3,3 round. 2593 elif $mode_background==6 2,2,1,1,110,90,90,110 r. 64,64,1,3 r. {*,w,h},1,3,0,2,0.5,0.5 2594 else $_d3d_background r. {*,w,h},1,3,1 2595 fi 2596 w. nm. background 2597 rmn object3d 2598 fi 2599 2600 # Init normalized 3D object. 2601 if !narg($object3d) 2602 +c3d[0] n3d. *3d. {background,$zoomfactor*0.65*min(w,h)} 2603 if $mode_orientation==1 rv3d. fi 2604 rmn boundingbox3d 2605 if $is_boundingbox +boundingbox3d. o3d. 0.35 nm. boundingbox3d +3d.. . rv[-2,-1] fi 2606 nm. object3d 2607 rmn render 2608 fi 2609 2610 # Render 3D object. 2611 if !narg($render) 2612 $pose3d 2613 if $is_animate" || "$is_outvideo l. 2614 da={$speed_animate*($is_animate?20*($|-$time_animate):1)} 2615 if $mode_animate==0 rotation3d 1,0,0,$da rv 2616 elif $mode_animate==1 rotation3d 0,1,0,$da rv 2617 elif $mode_animate==2 rotation3d 0,0,1,$da rv 2618 else 2619 dax,day,daz={[0.75,0.82,0.97]*$da} 2620 rotation3d 0,1,0,$dax rotation3d 1,0,0,$day rotation3d 0,0,1,$daz rv 2621 fi 2622 m* 1,3,1,1 j.. .,3 rm. +store. pose3d 2623 time_animate=$| 2624 endl fi 2625 p={^} rm. 2626 m={$is_motion?$mode_drender:$mode_render} 2627 [background] nm. render 2628 if $m<0 2629 if !narg($boundingbox3d) +boundingbox3d[object3d] o3d. 0.35 nm. boundingbox3d fi 2630 +pose3d[boundingbox3d] $p 2631 j3d[render] .,$posx%,$posy%,0,1,1,0,0,$focale rm. 2632 else 2633 +pose3d[object3d] $p 2634 if $is_outline 2635 {render,[w,h]},1,3,-1 2636 j3d. ..,$posx%,$posy%,0,1,$m,{$mode_orientation==2},$is_zbuffer,$focale 2637 +channels. 0 !=. -1 2638 +dilate. 5 r. 100%,100%,1,3 j[render] .,0,0,0,0,0.8,. rm. 2639 j[render] ..,0,0,0,0,1,. rm[-2,-1] 2640 else j3d[render] .,$posx%,$posy%,0,1,$m,{$mode_orientation==2},$is_zbuffer,$focale 2641 fi 2642 rm. 2643 fi 2644 if $is_axes3d 2645 +pose3d[axes3d] $p 2646 eval " # Colorize axes depending on their Z-sign 2647 const off = "$off_axes"; 2648 ref([ 255,0,0 ],col); 2649 i[13]>0?copy(i[off],col,3); 2650 i[19]>0?copy(i[off + 3],col,3); 2651 i[25]>0?copy(i[off + 6],col,3); 2652 " 2653 j3d[render] .,50,{-2,h-50},0,0.75,1,0,0,$focale rm. 2654 fi 2655 rmn view 2656 2657 if $is_outvideo 2658 o[render] $filename_outvideo,20,0,1 2659 nb_frames={int(360/$speed_animate)} 2660 if $is_outvideo>=$nb_frames 2661 o[] $filename_outvideo,20,0,0 # Close video stream 2662 is_outvideo=0 2663 notification="Output Video:\nDone!" 2664 else 2665 is_outvideo+=1 2666 notification="Output Video:\nFrame "{$is_outvideo+1}/$nb_frames 2667 fi 2668 fi 2669 fi 2670 2671 # Manage notifications. 2672 if narg($notification) 2673 wait_event=0 2674 if !isnum($notification) # Create notification gfx 2675 rmn notification_gfx 2676 ofs,fs={narg($fontsize_notif)?0$fontsize_notif:32} 2677 do 2678 0 t. {``$notification},0,0,$fs,1,255 2679 if narg($fontsize_notif) break 2680 elif {background,"(w#-1>0.7*w || h#-1>0.25*h) && "$fs>13" && "$ofs>=$fs} 2681 ofs,fs=$fs,{max(13,round($fs/1.25))} rm. 2682 elif {background,"w#-1<0.3*w && h#-1<0.25*h && "$fs<64" && "$ofs<=$fs} 2683 ofs,fs=$fs,{min(64,round($fs*1.25))} rm. 2684 else 2685 fontsize_notif=$fs break 2686 fi 2687 while 1 2688 r. {[w+12,h+8]},1,1,0,0,0.5,0.5 rectangle. 0,0,100%,100%,1,0xFFFFFFFF,255 to_rgb. 2689 nm. notification_gfx 2690 notification=$| 2691 else 2692 if $|>$notification+1 rm[notification_gfx] wait_event=1 notification= fi 2693 rmn view 2694 fi 2695 fi 2696 2697 # Refresh window view. 2698 if !narg($view) 2699 if $notification_gfx 2700 +j[render] [notification_gfx],0.99~,5,0,0,{sqrt(max(0,1-($|-$notification)))} 2701 else [render] 2702 fi 2703 nm. view w. -1,-1,0,$is_fullscreen,$disp_title 2704 fi 2705 2706 if $is_motion" || "$is_animate wait_event=0 fi 2707 if $wait_event wait elif !$is_outvideo wait 20 fi 2708 2709 # Manage user-events 2710 if $exit_on_anykey" && "{*,k} break fi 2711 if $is_outvideo continue fi # Skip user event management 2712 mx,my,mb={*,x,y,b} 2713 is_CTRL={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 2714 if {*,-F1} # Render: Dots 2715 mode_render,mode_drender={M=0;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2716 notification="Render: Dots" if $mode_drender<0 notification.=" + Box" fi 2717 rmn render 2718 elif {*,-F2} # Render: Wireframe 2719 mode_render,mode_drender={M=1;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2720 notification="Render: Wireframe" if $mode_drender<0 notification.=" + Box" fi 2721 rmn render 2722 elif {*,-F3} # Render: Flat 2723 mode_render,mode_drender={M=2;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2724 notification="Render: Flat" if $mode_drender<0 notification.=" + Box" fi 2725 rmn render 2726 elif {*,-F4} # Render: Flat-shaded 2727 mode_render,mode_drender={M=3;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2728 notification="Render: Flat-Shaded" if $mode_drender<0 notification.=" + Box" fi 2729 rmn render 2730 elif {*,-F5} # Render: Gouraud-shaded 2731 mode_render,mode_drender={M=4;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2732 notification="Render: Gouraud-Shaded" if $mode_drender<0 notification.=" + Box" fi 2733 rmn render 2734 elif {*,-F6} # Render: Phong-shaded 2735 mode_render,mode_drender={M=5;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2736 notification="Render: Phong-Shaded" if $mode_drender<0 notification.=" + Box" fi 2737 rmn render 2738 elif {*,-F7}" && "($focale>100" || "!$focale) # Decrease focale 2739 if !$focale focale=2000 else focale-=100 fi 2740 notification="Focale: "$focale 2741 rmn render 2742 elif {*,-F8}" && "$focale # Increase focale 2743 if $focale>=2000 focale=0 notification="Focale: Inf" else focale+=100 notification="Focale: "$focale fi 2744 rmn render 2745 elif {*,-F9} # Choose animation mode 2746 mode_animate={($mode_animate+1)%4} 2747 n0,n1,n2,n3="X-Axis","Y-Axis","Z-Axis","XYZ-Axes" notification="Animation Mode: "${n$mode_animate} 2748 rmn render 2749 elif {*,-F10} # Choose animation speed 2750 speed_animate={max(1,($speed_animate+1)%9)} 2751 notification="Animation Speed: X"$speed_animate 2752 elif {*,-SPACE} # Start/stop animation 2753 is_animate,time_animate={!$is_animate},$| 2754 n0,n1="Off","On" notification="Animation: "${n$is_animate} 2755 rmn render 2756 fi 2757 if $is_CTRL 2758 if {*,-A} # Show/hide 3D axes 2759 is_axes3d={!$is_axes3d} 2760 n0,n1="Off","On" notification="3D Axes: "${n$is_axes3d} 2761 rmn render 2762 elif {*,-B} # Change background 2763 mode_background={($mode_background+1)%($is_user_background?8:7)} 2764 n0,n1,n2,n3,n4,n5,n6,n7=\ 2765 "Black","White","Gray","Gradient \#1","Gradient \#2","Gradient \#3","Checkerboard","User-Defined" 2766 notification="Background: "${n$mode_background} 2767 rmn background 2768 elif {*,-C}" && "{*,w}>128" && "{*,h}>128 w[] {0.8*[{*,w,h}]} # Decrease window size 2769 notification="Decrease Window Size" fontsize_notif= 2770 rmn background 2771 elif {*,-D}" && "{*,w}<0.8*{*,u}" && "{*,h}<0.8*{*,v} w[] {1.25*[{*,w,h}]} # Increase window size 2772 notification="Increase Window Size" fontsize_notif= 2773 rmn background 2774 elif {*,-F} # Toggle fullscreen 2775 is_fullscreen={!$is_fullscreen} 2776 if $is_fullscreen w[] {*,u,v} else w[] {0.75*[{*,u,v}]} fi 2777 n0,n1="Off","On" notification="Fullscreen: "${n$is_fullscreen} fontsize_notif= 2778 rmn background 2779 elif {*,-G} # Save object as a .obj file 2780 n=0 do filename gmic.obj,$n n+=1 while isfile(['{/${}}']) 2781 notification="Save Copy:\n"${} 2782 o[0] ${} 2783 elif {*,-L} # Show/hide outline 2784 is_outline={!$is_outline} 2785 n0,n1="Off","On" notification="Outline: "${n$is_outline} 2786 rmn render 2787 elif {*,-O} # Save object as a .gmz file 2788 n=0 do filename gmic.gmz,$n n+=1 while isfile(['{/${}}']) 2789 o[0] ${} 2790 notification="Save Copy:\n"${} 2791 elif {*,-P} # Print 3D pose on console 2792 $pose3d v 0 e[] " > 3D Pose = [ "{^}" ]." rm. 2793 elif {*,-R} # Reset window 2794 w[] $disp_size0 2795 notification="Reset Window Size" fontsize_notif= 2796 rmn background 2797 elif {*,-S} # Save screenshot 2798 n=0 do filename gmic.png,$n n+=1 while isfile(['{/${}}']) 2799 o[render] ${} 2800 notification="Save Screenshot:\n"${} 2801 elif {*,-T} # Change orientation mode 2802 mode_orientation={($mode_orientation+1)%3} 2803 n0,n1,n2="Forward","Backward","Double-Sided" notification="Orientation: "${n$mode_orientation} 2804 if $mode_orientation rv3d[object3d] fi 2805 rmn render 2806 elif {*,-V} # Start/stop output video 2807 is_outvideo={!$is_outvideo} 2808 is_animate=0 2809 n=0 do filename gmic.mp4,$n n+=1 while isfile(['{/${}}']) 2810 filename_outvideo=${} 2811 elif {*,-X} # Show/hide bounding box 2812 is_boundingbox={!$is_boundingbox} 2813 n0,n1="Off","On" notification="Bounding Box: "${n$is_boundingbox} 2814 rmn object3d 2815 elif {*,-Z} # Enable/disable Z-buffer 2816 is_zbuffer={!$is_zbuffer} 2817 n0,n1="Off","On" notification="Z-Buffer: "${n$is_zbuffer} 2818 rmn render 2819 fi 2820 fi 2821 if {*,-r} rmn background fontsize_notif= fi 2822 2823 if $mx>=0 # Manage mouse-drag 2824 if $mb 2825 if !narg($mx0) mx0,my0,mx1,my1=$mx,$my,$mx,$my else mx1,my1=$mx,$my fi 2826 else 2827 if narg($mx0) rmn render fi 2828 mx0,my0,mx1,my1= 2829 fi 2830 fi 2831 2832 # Estimate new 3D pose from motion. 2833 if narg($mx1)" && "($mx0!=$mx1" || "$my0!=$my1) 2834 rmn render 2835 if $mb&1" && "!$is_CTRL # Rotation 2836 rotation3d[] {" 2837 const w2 = "{*,w}"/2; 2838 const h2 = "{*,h}"/2; 2839 const R = 0.375*min("{*,w,h}"); 2840 const u0 = "$mx0" - w2; 2841 const v0 = "$my0" - h2; 2842 const u1 = "$mx1" - w2; 2843 const v1 = "$my1" - h2; 2844 n0 = norm(u0,v0); 2845 nu0 = n0>R?u0*R/n0:u0; 2846 nv0 = n0>R?v0*R/n0:v0; 2847 nw0 = sqrt(max(0,R^2 - nu0^2 - nv0^2)); 2848 n1 = norm(u1,v1); 2849 nu1 = n1>R?u1*R/n1:u1; 2850 nv1 = n1>R?v1*R/n1:v1; 2851 nw1 = sqrt(max(0,R^2 - nu1^2 - nv1^2)); 2852 u = nv0*nw1 - nw0*nv1; 2853 v = nw0*nu1 - nu0*nw1; 2854 w = nv0*nu1 - nu0*nv1; 2855 n = norm(u,v,w); 2856 [ u,v,w,-asin(n/R^2)*180/pi ]"} 2857 $pose3d m*[-2,-1] store. pose3d 2858 mx0,my0=$mx1,$my1 2859 elif $mb&4" || "($mb&1" && "$is_CTRL) # Pan 2860 posx,posy={" 2861 const px = "$mx1-$mx0+$posx*{*,w}%"; 2862 const py = "$my1-$my0+$posy*{*,h}%"; 2863 cut([ px*100/"{*,w}", py*100/"{*,h}" ],0,100)"} 2864 mx0,my0=$mx1,$my1 2865 elif $mb&2 # Zoom with mouse button 2866 fact={1+($my0-$my1)/100} 2867 zoomfactor*=$fact 2868 *3d[object3d] $fact if narg($boundingbox3d) *3d[boundingbox3d] $fact fi 2869 mx0,my0=$mx1,$my1 2870 fi 2871 fi 2872 if {*,o} # Zoom with mousewheel 2873 fact={1+{*,-o}/10} 2874 zoomfactor*=$fact 2875 *3d[object3d] $fact if narg($boundingbox3d) *3d[boundingbox3d] $fact fi 2876 rmn render 2877 fi 2878 2879 while {*}" && "!{*,ESC}" && "!($is_CTRL" && "{*,W}) 2880 k[0] 2881 endl done 2882 if narg($disp_normalization) w[] -1,-1,$disp_normalization else w[] 0 fi 2883 v -1 d[] 2884 2885#@cli da : eq. to 'display_array'. 2886da : 2887 _gmic_s="$?" v + _display_array $* 2888 2889#@cli display_array : _width>0,_height>0 2890#@cli : Display images in interactive windows where pixel neighborhoods can be explored. 2891#@cli : Default values: 'width=13' and 'height=width'. 2892display_array : 2893 _gmic_s="$?" v + _$0 $* 2894 2895_display_array : check ${1=13}>0" && "${2=$1}>0 2896 e[0--3] "Display $1x$2 array of pixel values for image"$_gmic_s"." 2897 2898 dxb={round($1/2,1,1)} dxf={$1-1-$dxb} 2899 dyb={round($2/2,1,1)} dyf={$2-1-$dyb} 2900 2901 repeat $! l[$>] 2902 if w<128" && "h<128 r 128,128,100%,100%,0,0,0.5,0.5 fi # Manage cases of small and large images. 2903 x0=0 y0=0 w={w} h={h} 2904 wmax={0.9*{*,u}} hmax={0.9*{*,v}} 2905 do 2906 if w>=$wmax" || "h>=$hmax 2907 n={n} nm. "Image "'{b}.{x}'" is too large, please select a sub-image." 2908 +select. 2 x0={i[0]} y0={i[1]} w={1+i[3]-i[0]} h={1+i[4]-i[1]} 2909 rm. nm. $n 2910 fi 2911 +z. $x0,$y0,0,{$x0+$w-1},{$y0+$h-1},0 round. 1 n. 0,255 2912 while w>=$wmax" || "h>=$hmax 2913 2914 x1=-1 y1=-1 c1=0 ox1=-1 oy1=-1 oc1=-1 2915 x2=-1 y2=-1 c2=0 ox2=-1 oy2=-1 oc2=-1 2916 x3=-1 y3=-1 c3=0 ox3=-1 oy3=-1 oc3=-1 2917 c0=0 oxm=-1 oym=-1 2918 w. -1,-1,0,0,{-2,b}.{-2,x} 2919 do # Enter event loop. 2920 2921 # Manage user interactions. 2922 wait[0-3] 2923 oc0=$c0 2924 repeat 4 2925 if $>" && "!{*$>}" && "${x$>}>=0 w$> 0 x$>=-1 y$>=-1 c$>=0 fi 2926 if {*$>,o} c$>={(${c$>}+sign({*$>,o}))%s} wait[$>] -1 fi 2927 if {*$>,SPACE}" || "{*$>,ENTER}" || "{*$>,ARROWRIGHT}" || "{*$>,ARROWDOWN} c$>={(${c$>}+1)%s} wait[$>] -1 fi 2928 if {*$>,BACKSPACE}" || "{*$>,ARROWLEFT}" || "{*$>,ARROWUP} c$>={(${c$>}-1)%s} wait[$>] -1 fi 2929 done 2930 if $oc0!=$c0 c1=$c0 c2=$c0 c3=$c0 fi 2931 xm={*,x} ym={*,y} 2932 if $xm>=0" && "{*,b}&1 x1=$xm y1=$ym fi 2933 if $xm>=0" && "{*,b}&2 x2=$xm y2=$ym fi 2934 if $xm>=0" && "{*,b}&4 x3=$xm y3=$ym fi 2935 2936 # Generate main image view. 2937 if $xm>=0" && "($oxm!=$xm" || "$oym!=$ym) w[] -1,-1,{-2,b}.{-2,x}" - ("$xm,$ym")" fi 2938 if $x1!=$ox1" || "$y1!=$oy1" || "$x2!=$ox2" || "$y2!=$oy2" || "$x3!=$ox3" || "$y3!=$oy3 2939 . 2940 if $x1>=0 2941 xb={$x1-$dxb} yb={$y1-$dyb} xe={$x1+$dxf} ye={$y1+$dyf} 2942 rectangle. $xb,$yb,$xe,$ye,0.2,0,255,255 2943 rectangle. $xb,$yb,$xe,$ye,1,0xFFFFFFFF,0,255,255 2944 fi 2945 if $x2>=0 2946 xb={$x2-$dxb} yb={$y2-$dyb} xe={$x2+$dxf} ye={$y2+$dyf} 2947 rectangle. $xb,$yb,$xe,$ye,0.2,255,32,255 2948 rectangle. $xb,$yb,$xe,$ye,1,0xFFFFFFFF,255,32,255 2949 fi 2950 if $x3>=0 2951 xb={$x3-$dxb} yb={$y3-$dyb} xe={$x3+$dxf} ye={$y3+$dyf} 2952 rectangle. $xb,$yb,$xe,$ye,0.2,255,255,0 2953 rectangle. $xb,$yb,$xe,$ye,1,0xFFFFFFFF,255,255,0 2954 fi 2955 w. {-2,w},{-2,h} rm. oxm=$xm oym=$ym 2956 fi 2957 2958 # Generate zoomed views. 2959 if $x1>=0" && "($ox1!=$x1" || "$oy1!=$y1" || "$oc1!=$c1) 2960 +z.. {$x1-$dxb},{$y1-$dyb},0,$c1,{$x1+$dxf},{$y1+$dyf},0,$c1 2961 +z.. {$x1-$dxb},{$y1-$dyb},0,{$x1+$dxf},{$y1+$dyf},0 2962 __display_array[-2,-1] $1,$2,0,255,255 2963 w1. {w},{h},0,0,{-3,b}" - ("$x1,$y1,c=$c1")" 2964 rm. ox1=$x1 oy1=$y1 oc1=$c1 2965 fi 2966 if $x2>=0" && "($ox2!=$x2" || "$oy2!=$y2" || "$oc2!=$c2) 2967 +z.. {$x2-$dxb},{$y2-$dyb},0,$c2,{$x2+$dxf},{$y2+$dyf},0,$c2 2968 +z.. {$x2-$dxb},{$y2-$dyb},0,{$x2+$dxf},{$y2+$dyf},0 2969 __display_array[-2,-1] $1,$2,255,32,255 2970 w2. {w},{h},0,0,{-3,b}" - ("$x2,$y2,c=$c2")" 2971 rm. ox2=$x2 oy2=$y2 oc2=$c2 2972 fi 2973 if $x3>=0" && "($ox3!=$x3" || "$oy3!=$y3" || "$oc3!=$c3) 2974 +z.. {$x3-$dxb},{$y3-$dyb},0,$c3,{$x3+$dxf},{$y3+$dyf},0,$c3 2975 +z.. {$x3-$dxb},{$y3-$dyb},0,{$x3+$dxf},{$y3+$dyf},0 2976 __display_array[-2,-1] $1,$2,255,255,0 2977 w3. {w},{h},0,0,{-3,b}" - ("$x3,$y3,c=$c3")" 2978 rm. ox3=$x3 oy3=$y3 oc3=$c3 2979 fi 2980 while {*}" && "\ 2981 !{*,ESC}" && "!{*,Q}" && "\ 2982 !{*1,ESC}" && "!{*1,Q}" && "\ 2983 !{*2,ESC}" && "!{*2,Q}" && "\ 2984 !{*3,ESC}" && "!{*3,Q} 2985 k[0] w 0 w1 0 w2 0 w3 0 2986 endl done 2987 2988__display_array : 2989 round.. 1 c.. 0,999 r. 100%,100%,1,3,{s==1} 2990 +luminance. r.. {$1*24},{$2*24} grid.. {100/$1}%,{100/$2}%,0,0,1,0 2991 xb={24*int($1/2)} yb={24*int($2/2)} xe={$xb+24} ye={$yb+24} 2992 rectangle.. $xb,$yb,$xe,$ye,1,0xFFFFFFFF,$3,$4,$5 2993 repeat $2,yg 2994 repeat $1,xg 2995 t.. {-3,i($xg,$yg)},{5+$xg*24},{5+$yg*24},13,0.8,{i($xg,$yg)>128?0:255} 2996 done 2997 done 2998 rm[-3,-1] 2999 3000#@cli dc : eq. to 'display_camera'. 3001dc : check_opencv $0 3002 v + _display_camera 3003 3004#@cli display_camera 3005#@cli : Open camera viewer. 3006#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 3007display_camera : check_opencv $0 3008 v + _$0 3009 3010_display_camera : 3011 e[0--3] "Open camera stream viewer." 3012 3013 # Initialize camera and get resolution. 3014 l[] camera 3015 onfail 3016 use_vt100 3017 e[0--4] ${_vt100_r}${_vt100_b}"Command 'display_camera': Unable to read camera stream. Exiting."$_vt100_n 3018 return 3019 endl 3020 3021 wc,hc={[w,h]} 3022 3023 # Open interactive window. 3024 w ${"fitscreen "$wc,$hc},0,"G'MIC Camera Stream Viewer" 3025 wnfs,hnfs={*,w,h} 3026 angle,fullscreen,brightness,contrast=0 3027 do 3028 3029 # Display frame from camera. 3030 ww,wh={*,w,h} 3031 camera 3032 if $angle rotate. {90*$angle} fi 3033 if $brightness +. {10*$brightness} c. 0,255 fi 3034 if $contrast /. 255 *. {1.2^$contrast} *. 255 c. 0,255 fi 3035 rr2d. $ww,$wh,2,1 w. 3036 rm 3037 wait 30 3038 3039 # Manage user events. 3040 if {*,r} w[] {*,d,e} 3041 elif {*,-R}" || "{*,-SPACE} angle={($angle+1)%4} 3042 elif {*,-ARROWUP} brightness={min(5,$brightness+1)} 3043 elif {*,-ARROWDOWN} brightness={max(-5,$brightness-1)} 3044 elif {*,-ARROWRIGHT} contrast={min(5,$contrast+1)} 3045 elif {*,-ARROWLEFT} contrast={max(-5,$contrast-1)} 3046 elif {*,-F}" || "{*,-ENTER}" || "{*,-F5} 3047 fullscreen={1-$fullscreen} 3048 if $fullscreen 3049 wwnfs,whnfs={*,w,h} 3050 w[] {*,u,v},0,1 3051 else 3052 w[] $wwnfs,$whnfs,0,0 3053 fi 3054 fi 3055 3056 while {*}" && "!{*,ESC} 3057 camera 0,0 w[] 0 3058 3059#@cli dfft : eq. to 'display_fft'. 3060dfft : 3061 v + _display_fft 3062 3063#@cli display_fft 3064#@cli : Display fourier transform of selected images, with centered log-module and argument. 3065#@cli : (eq. to 'dfft'). 3066#@cli : $ image.jpg +display_fft 3067display_fft : 3068 v + _$0 3069 3070_display_fft : 3071 e[0--3] "Render fourier transform of image$? with centered log-module and argument." 3072 repeat $! l[$>] fftpolar +.. 1 log.. n 0,255 a x endl done s x,2 3073 3074#@cli dg : eq. to 'display_graph'. 3075dg : check "${1=0}>=0 && ${2=0}>=0" skip ${3=1},${4=0},${5=0},${6=0},${7=0},${8=0},"${9=x-axis}","${10=y-axis}" 3076 _display_graph ${1-8},"$9","$10" 3077 3078#@cli display_graph : _width>=0,_height>=0,_plot_type,_vertex_type,_xmin,_xmax,_ymin,_ymax,_xlabel,_ylabel 3079#@cli : Render graph plot from selected image data. 3080#@cli : 'plot_type' can be { 0=none | 1=lines | 2=splines | 3=bar }. 3081#@cli : 'vertex_type' can be { 0=none | 1=points | 2,3=crosses | 4,5=circles | 6,7=squares }. 3082#@cli : 'xmin','xmax','ymin','ymax' set the coordinates of the displayed xy-axes. 3083#@cli : if specified 'width' or 'height' is '0', then image size is set to half the screen size. 3084#@cli : Default values: 'width=0', 'height=0', 'plot_type=1', 'vertex_type=1', 'xmin=xmax=ymin=ymax=0 (auto)', \ 3085# 'xlabel="x-axis"' and 'ylabel="y-axis"'. 3086#@cli : $ 128,1,1,1,'cos(x/10+u)' +display_graph 400,300,3 3087display_graph : check "${1=0}>=0 && ${2=0}>=0" 3088 skip ${3=1},${4=0},${5=0},${6=0},${7=0},${8=0},"${9=x-axis}","${10=y-axis}" 3089 _display_graph ${1-8},"$9","$10" 3090 3091_display_graph : check "${1=0}>=0 && ${2=0}>=0" 3092 skip ${3=1},${4=0},${5=0},${6=0},${7=0},${8=0},"${9=x-axis}","${10=y-axis}" 3093 e[0--3] "Render $1x$2 graph plot from data of image$?." 3094 3095 repeat $! l[$>] nm={0,n} 3096 3097 # Determine output size. 3098 if $1>0" && "$2>0 w,h=$1,$2 else w,h={{*,u}/2},{{*,v}/2} fi 3099 w,h={[max($w,33),max($h,33)]} 3100 3101 # Determine xmin,xmax/ymin,ymax. 3102 one={$3!=3} siz={w*h*d} 3103 if $5==$6 xmin=0 xmax={$siz-$one} else xmin={min($5,$6)} xmax={max($5,$6)} fi 3104 if $7==$8 ymin={im-(iM-im)/20} ymax={iM+(iM-im)/20} else ymin={min($7,$8)} ymax={max($7,$8)} fi 3105 dx={$xmax-$xmin} dy={$ymax-$ymin} 3106 3107 # Determine number of axes tick marks. 3108 u=${"_axes[] "$xmin,$xmax",{0.3*"$w"/14}"} offx={arg(1,$u)} deltax={arg(2,$u)} 3109 u=${"_axes[] "$ymin,$ymax",{0.3*"$h"/14}"} offy={arg(1,$u)} deltay={arg(2,$u)} 3110 3111 # Create plot canvas. 3112 gw={$w-32} gh={$h-32} gg={($gw-$one)/($siz-$one)} 3113 $gw,$gh,1,3,255 3114 3115 grid. {$deltax*$gw/$dx},{$deltay*$gh/$dy},{($offx-$xmin)*$gw/$dx},{$gh-($offy-$ymin)*$gh/$dy},0.25,0xCCCCCCCC,0 3116 3117 # Define color palette for curves. 3118 if s#-2==1 (120,120,200) 3119 elif s#-2<=3 (220,10,10;10,220,10;10,10,220) 3120 else 3121 (0,255) r. 256,1,1,1,3 map. 2 z. 2,100% permute. cxyz r. 3,{-3,max(3,s)},1,1,0,2 3122 sh. 0,2,0,0 f. 255,0,0,0,255,0,0,0,255 rm. 3123 fi 3124 3125 # Draw plot for each channel. 3126 repeat s#-3 sh... $> graph... .,$3,$4,$ymax,$ymin,1,{-2,@0-2} rm. shift. 0,-1 done 3127 rm[-3,-1] 3128 line. 0,0,100%,0,1,110 line. 100%,0,100%,100%,1,110 3129 line. 100%,100%,0,100%,1,255 line. 0,100%,0,0,1,255 3130 3131 100%,100%,1,1,255 3132 axes. $xmin,$xmax,$ymax,$ymin,14,1,0 3133 if $xmin>0 axes. 0,0,$ymax,$ymin,14,1,160 fi 3134 if $xmax<0 axes. {w-1},{w-1},$ymax,$ymin,14,1,160 fi 3135 if $ymin>0 axes. $xmin,$xmax,{h-1},{h-1},14,1,160 fi 3136 if $ymax<0 axes. $xmin,$xmax,0,0,14,1,160 fi 3137 +erode. 3 !=. 255 r.. 100%,100%,1,3 j... ..,0,0,0,0,1,.,1 rm[-2,-1] 3138 frame. 16,16,220 3139 0 t. "$9",0,0,14,1,-220,-220,-220 j.. .,{({-2,w}-w)/2},{{-2,h}-16},0,0,-1 rm. 3140 0 t. "$10",0,0,14,1,-220,-220,-220 rotate. -90 j.. .,2,{({-2,h}-h)/2},0,0,-1 rm. 3141 3142 nm $nm endl done c 0,255 3143 3144#@cli dh : eq. to 'display_histogram'. 3145dh : 3146 _gmic_s="$?" v + _display_histogram $"*" 3147 3148#@cli display_histogram : _width>=0,_height>=0,_clusters>0,_min_value[%],_max_value[%],_show_axes={ 0 | 1 },_expression. 3149#@cli : Render a channel-by-channel histogram. 3150#@cli : If selected images have several slices, the rendering is performed for all input slices. 3151#@cli : 'expression' is a mathematical expression used to transform the histogram data for visualization purpose. 3152#@cli : (eq. to 'dh'). 3153#@cli : if specified 'width' or 'height' is '0', then image size is set to half the screen size. 3154#@cli : Default values: 'width=0', 'height=0', 'clusters=256', 'min_value=0%', 'max_value=100%', 'show_axes=1' \ 3155# and 'expression=i'. 3156#@cli : $ image.jpg +display_histogram 512,300 3157display_histogram : 3158 _gmic_s="$?" v + _$0 $"*" 3159 3160_display_histogram : check "${1=0}>=0 && ${2=0}>=0 && ${3=256}>0" skip ${4=0%},${5=100%},${6=1},"${7=i}" 3161 e[0--3] "Render $1x$2 channel-by-channel histogram of image"$_gmic_s", with $3 clusters, minimum value $4 3162 and maximum value $5." 3163 repeat $! l[$>] nm={0,n} 3164 if ${is_percent\ $4} m={im+(iM-im)*$4} else m=$4 fi 3165 if ${is_percent\ $5} M={im+(iM-im)*$5} else M=$5 fi 3166 s={s} s c 3167 repeat $s l[{-1-$>}] s z histogram $3,$m,$M a z endl done 3168 a c f '"${7--1}"' vM={iM} s z 3169 repeat $! l[$>] 3170 if $1>0" && "$2>0 wh=$1,$2 else wh={{*,u}/2},{{*,v}/2} fi 3171 $wh,1,{s},-255 3172 repeat s sh[-2,-1] $> graph. ..,3,0,$vM,0,1,0 rm[-2,-1] done 3173 rm.. + 255 3174 if $6 3175 100%,100% 3176 axes. $m,$M,$vM,0,14,1,255 3177 if $m>0 axes. 0,0,$vM,0,14,1,200 fi 3178 if $M<0 axes. {w-1},{w-1},$vM,0,14,1,200 fi 3179 +dilate. 3 ri.. ... j... ..,0,0,0,0,1,.,255 rm[-2,-1] 3180 fi 3181 endl done 3182 a z nm $nm 3183 endl done 3184 3185#@cli display_parametric : _width>0,_height>0,_outline_opacity,_vertex_radius>=0,_is_antialiased={ 0 | 1 },\ 3186# _is_decorated={ 0 | 1 },_xlabel,_ylabel 3187#@cli : Render 2D or 3D parametric curve or point clouds from selected image data. 3188#@cli : Curve points are defined as pixels of a 2 or 3-channel image. 3189#@cli : If the point image contains more than 3 channels, additional channels define the (R,G,B) color for each vertex. 3190#@cli : If 'outline_opacity>1', the outline is colored according to the specified vertex colors and 3191#@cli : 'outline_opacity-1' is used as the actual drawing opacity. 3192#@cli : Default values: 'width=512', 'height=width', 'outline_opacity=3', 'vertex_radius=0', 'is_antialiased=1',\ 3193# 'is_decorated=1', 'xlabel="x-axis"' and 'ylabel="y-axis"'. 3194#@cli : $ 1024,1,1,2,'t=x/40;if(c==0,sin(t),cos(t))*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)' display_parametric 512,512 3195#@cli : $ 1000,1,1,2,u(-100,100) quantize 4,1 noise 12 channels 0,2 +normalize 0,255 append c \ 3196# display_parametric 512,512,0.1,8 3197display_parametric : check "${1=512}>0 && ${2=$1}>0 && ${4=0}>=0" skip ${3=3},${5=1},${6=1},"${7=x-axis}","${8=y-axis}" 3198 s0="no " s1="" o0="" o1="colored " 3199 e[^-1] "Render $1x$2 parametric graph plot from data of image$?, with "${o{$3>1}}"outline opacity "\ 3200 {$3>1?$3-1:$3}", vertex radius $4, "${s{$5!=0}}"antialiasing and "${s{$6!=0}}"decoration." 3201 repeat $! l[$>] 3202 nm={0,n} N={w*h*d} 3203 i[0] ('CImg3d') +[0] 0.5 i[1] ($N;$N) # Header + nb of vertices/primitives. 3204 3205 # Calibrate colors of vertices. 3206 if s==4 +channels. 3,3 r. 100%,100%,1,2 a[-2,-1] c is_grayscale=1 3207 else is_grayscale={s<4} channels. 0,5 3208 fi 3209 3210 # Manage coordinates of vertices. 3211 sh. 0 xm={im} xM={iM} rm. 3212 sh. 1 ym={im} yM={iM} rm. 3213 sh. 2 zm={im} zM={iM} rm. 3214 permute. cxyz s. x,2 3215 i.. (1,0;1,{$N-1}) r.. 2,$N,1,1,3 round.. 1,$N,1,1,1 # Primitives, colors and opacities. 3216 y a y c3d n3d *3d 1,-1,1 3217 3218 {if($6,max(1,$1-32),$1)},{if($6,max(1,$2-32),$2)},1,{if($is_grayscale,1,3)},255 3219 *3d[0] {0.96*min(w,h)} 3220 if $6 L={0.1*max($1,$2)} grid[1] $L,$L,0,0,0.25,0xCCCCCCCC,0 fi 3221 3222 if $5 # Anti-aliased. 3223 r[1] 200%,200%,1,100%,1 *3d[0] 2 3224 if $4 +circles3d[0] {2*$4} j3d[1] [2],50%,50%,0,1,3,0,0 rm[2] fi 3225 elif $4 # Aliased. 3226 +circles3d[0] $4 j3d[1] [2],50%,50%,0,1,3,0,0 rm[2] 3227 fi 3228 3229 # Convert point cloud to connected segments. 3230 if $3 l[0] s3d f[1] 'i-y' rm[3] i[3] (2,0,1;2,{$N-2},{$N-1}) r[3] 3,{$N-1},1,1,3 round[3] 3231 r[5] 1,{h-1},1,1,0 3232 if $3>1 r[4] 3,{4,h/3},1,1,-1 r[4] 3,{4,h-1},1,1,2 else rm[4] i[4] 3,{$N-1} fi 3233 y a y endl j3d[1] [0],50%,50%,0,{if($3>1,$3-1,$3)},2,0,0 3234 fi 3235 3236 rm[0] 3237 if $5 r. 50%,50%,1,100%,2 fi 3238 3239 if $6 # Add decoration. 3240 xc={0.5*($xm+$xM)} yc={0.5*($ym+$yM)} dx={0.5*($xM-$xm)/0.96} dy={0.5*($yM-$ym)/0.96} 3241 xm={$xc-$dx} xM={$xc+$dx} ym={$yc-$dy} yM={$yc+$dy} 3242 100%,100%,1,1,255 axes. $xm,$xM,$yM,$ym,14,1,0 3243 if $xm>0 axes. 0,0,$yM,$ym,14,1,160 fi 3244 if $xM<0 axes. {w-1},{w-1},$yM,$ym,14,1,160 fi 3245 if $ym>0 axes. $xm,$xM,{h-1},{h-1},14,1,160 fi 3246 if $yM<0 axes. $xm,$xM,0,0,14,1,160 fi 3247 +erode. 3 !=. 255 r.. 100%,100%,1,3 j... ..,0,0,0,0,1,.,1 rm[-2,-1] 3248 frame 1,1,128 frame 15,15,220 3249 0 t. "$7",0,0,14,1,-220,-220,-220 j.. .,{({-2,w}-w)/2},{{-2,h}-16},0,0,-1 rm. 3250 0 t. "$8",0,0,14,1,-220,-220,-220 rotate. -90 j.. .,2,{({-2,h}-h)/2},0,0,-1 rm. 3251 fi 3252 nm. $nm 3253 endl done 3254 3255#@cli dp : eq. to 'display_parallel'. 3256dp : 3257 _gmic_s="$?" v + _display_parallel 1 3258 3259#@cli display_parallel 3260#@cli : Display each selected image in a separate interactive display window. 3261#@cli : (eq. to 'dp'). 3262display_parallel : 3263 _gmic_s="$?" v + _$0 1 3264 3265# $1 = Normalization used for display window. 3266_display_parallel : check ${1=0}>=0 3267 e[0--3] "Display image$? in parallel." 3268 print 3269 is_d2d_compatible={"res = l<=10; repeat (l,k, res&=(w#k==w && h#k==h && d#k==1 && s#k==s))"} 3270 if $is_d2d_compatible 3271 N=$! 3272 repeat $! 3273 if s=['{$>,n}'];find(s,_'.',size(s)-1,-1)>0 nm={$>,b}.{$>,x} else nm={$>,b} fi 3274 ('$nm':;) 3275 done 3276 store[-$N--1] _d2d_names 3277 a z _display2d 0,$1 s z 3278 _d2d_names= 3279 else 3280 if $!<=1 v - d v + return fi 3281 14,$! eval. "!x?copy(i(),[[',d['],vtos(y,10,10),_']'])" =. 0 discard. 0 str={t} rm. 3282 m "__dp : parallel "$str __dp um __dp 3283 fi 3284 v -1 d[] 3285 3286#@cli dp0 : eq. to 'display_parallel0'. 3287dp0 : 3288 _gmic_s="$?" v + _display_parallel 0 3289 3290#@cli display_parallel0 3291#@cli : Display each selected image in a separate interactive display window, without value normalization. 3292#@cli : (eq. to 'dp0'). 3293display_parallel0 : 3294 _gmic_s="$?" v + _display_parallel 0 3295 3296#@cli display_polar : _width>32,_height>32,_outline_type,_fill_R,_fill_G,_fill_B,_theta_start,_theta_end,_xlabel,_ylabel 3297#@cli : Render polar curve from selected image data. 3298#@cli : 'outline_type' can be { r<0=dots with radius -r | 0=no outline | r>0=lines+dots with radius r }. 3299#@cli : 'fill_color' can be { -1=no fill | R,G,B=fill with specified color }. 3300#@cli : Default values: 'width=500', 'height=width', 'outline_type=1', 'fill_R=fill_G=fill_B=200', 'theta_start=0', \ 3301# 'theta_end=360', 'xlabel="x-axis"' and 'ylabel="y-axis"'. 3302#@cli : $ 300,1,1,1,'0.3+abs(cos(10*pi*x/w))+u(0.4)' display_polar 512,512,4,200,255,200 3303#@cli : $ 3000,1,1,1,'x^3/1e10' display_polar 400,400,1,-1,,,0,{15*360} 3304display_polar : check "${1=500}>32 && ${2=$1}>32" 3305 skip ${3=1},${4=200},${5=$4},${6=$5},${7=0},${8=360},"${9=x-axis}","${10=y-axis}" 3306 e[^-1] "Render $1x$2 polar graph plot from data of image"$_gmic_s", with outline $4 and fill color ($4,$5,$6)." 3307 repeat $! l[$>] nm={0,n} 3308 3309 # Compute (x,y) coordinates of the polar curve points. 3310 M={max(abs(iM),abs(im))} 3311 * {0.48*min($1,$2)/$M} 3312 y ({$7*pi/180};{-$8*pi/180}) r. 1,..,1,1,3 3313 +sin. cos.. *. ... *[-3,-2] 3314 a[-2,-1] x N={h} 3315 nm. coords 3316 3317 # Generate 3D object for curve outline. 3318 if $3 3319 ('CImg3d') +. 0.5 ($N,$N) 3320 +z[coords] 0,2 3321 1,$N,1,1,2 1,$N,1,1,'y' ++. 1 a[-3--1] x =. 0,2,100% 3322 3,$N,1,1,0 1,$N,1,1,1 y[-6--1] a[-6--1] y 3323 nm. _plot_polar_outline 3324 fi 3325 3326 # Generate 3D object for filling. 3327 if "$4>=0 && $5>=0 && $6>=0" 3328 ('CImg3d') +. 0.5 ({$N+1},$N) 3329 +z[coords] 0,-1,2,100% z. 0,2 3330 1,$N,1,1,3 1,$N 1,$N,1,1,'1+y' ++. 1 a[-4--1] x =. 1,3,100% 3331 3,$N,1,1,$4,$5,$6 1,$N,1,1,1 3332 y[-6--1] a[-6--1] y 3333 nm. _plot_polar_fill 3334 fi 3335 rm[coords] # Remove original curve coordinates. 3336 3337 # Render graph image. 3338 {$1-32},{$2-32},1,3,255 3339 L={0.1*max($1,$2)} grid. $L,$L,0,0,0.25,0xCCCCCCCC,0 # Draw background grid 3340 if "$4>=0 && $5>=0 && $6>=0" # Draw curve filling 3341 j3d. [_plot_polar_fill],50%,50%,0,1,2,1,0 3342 rm[_plot_polar_fill] 3343 fi 3344 if $3 3345 if $3>=0 # Draw curve outline 3346 j3d. [_plot_polar_outline],50%,50%,0,1,1,0,0 3347 fi 3348 if $3!=0 # Draw curve vertices 3349 if abs($3)>1 circles3d[_plot_polar_outline] {abs($3)} fi 3350 j3d. [_plot_polar_outline],50%,50%,0,0.2,2,0,0 3351 fi 3352 rm[_plot_polar_outline] 3353 fi 3354 3355 # Draw axes and frame. 3356 nM={$M/0.96} 3357 100%,100%,1,1,255 axes. {-$nM},$nM,$nM,{-$nM},14,1,0 3358 +erode. 3 !=. 255 r.. 100%,100%,1,3 j... ..,0,0,0,0,1,.,1 rm[-2,-1] 3359 frame. 1,1,128 frame. 15,15,220 3360 0 t. "$9",0,0,13,1,-220,-220,-220 j.. .,{({-2,w}-w)/2},{{-2,h}-16},0,0,-1 rm. 3361 0 t. "$10",0,0,13,1,-220,-220,-220 rotate. -90 j.. .,2,{({-2,h}-h)/2},0,0,-1 rm. 3362 3363 nm $nm endl done 3364 3365#@cli dq : eq. to 'display_quiver'. 3366dq : 3367 _gmic_s="$?" v + _display_quiver $* 3368 3369#@cli display_quiver : _size_factor>0,_arrow_size>=0,_color_mode={ 0=monochrome | 1=grayscale | 2=color } 3370#@cli : Render selected images of 2D vectors as a field of 2D arrows. 3371#@cli : (eq. to 'dq'). 3372#@cli : Default values: 'size_factor=16', 'arrow_size=1.5' and 'color_mode=1'. 3373#@cli : $ image.jpg +luminance gradient[-1] xy rv[-2,-1] *[-2] -1 a[-2,-1] c crop 60,10,90,30 +display_quiver[1] , 3374display_quiver : 3375 _gmic_s="$?" v + _$0 $* 3376 3377_display_quiver : check "${1=16}>0 && ${2=1.5}>=0 && isint(${3=2}) && $3>=0 && $3<=2" 3378 e[0--3] "Render field of 2D arrows from image"$_gmic_s", with size factor $1, arrow size $2 in "\ 3379 ${arg\ 1+$3,monochrome,grayscale,color}" mode." 3380 repeat $! l[$>] 3381 +norm. /.. {max(1e-6,iM)} rm. # Normalize vector values. 3382 {$1*w},{$1*h},1,{"1<<cut($3,0,2)"} 3383 eval.. " 3384 begin(ref(resize([255],s#1,1),C)); 3385 "${-math_lib}" 3386 len = norm2(I(x,y)); 3387 ang = atan2(i(x,y,0,1),i(x,y,0,0))*180/pi; 3388 P = [ -0.5,-0.05, 0.3,-0.05, 0.2,-0.25, 0.5,0, 0.2,0.25, 0.3,0.05, -0.5,0.05 ]; 3389 P*=$1*$2*len; 3390 X = resize([(x+0.5)*w#1/w,(y+0.5)*h#1/h],size(P),0,2); 3391 X+=mul(P,rot(-ang°),2); 3392 if ($3, 3393 v = min(1,max(0.5,3*len)); 3394 if ($3==1, 3395 C = [ 255*v,255 ], 3396 C = [ hsv2rgb([ ang,1,v ]), 255 ]; 3397 ); 3398 ); 3399 repeat (3,k, 3400 i0 = arg(k + 1,0,2,4); 3401 i1 = arg(k + 1,2,10,6); 3402 i2 = arg(k + 1,12,12,8); 3403 polygon(#1,3,X[i0,2],X[i1,2],X[i2,2],1,C); 3404 ); I" 3405 rm.. 3406 endl done 3407 3408#@cli drgba : eq. to 'display_rgba'. 3409drgba : skip "${1=none},${2=$1},${3=$1}" 3410 _gmic_s="$?" v + _display_rgba ${^0} v - 3411 if !${} noarg fi 3412 3413#@cli display_rgba : _background_RGB_color 3414#@cli : Render selected RGBA images over a checkerboard or colored background. 3415#@cli : (eq. to 'drgba'). 3416#@cli : Default values: 'background_RGB_color=undefined' (checkerboard). 3417#@cli : $ image.jpg +norm threshold[-1] 40% blur[-1] 3 normalize[-1] 0,255 append c display_rgba 3418display_rgba : skip "${1=none},${2=$1},${3=$1}" 3419 _gmic_s="$?" v + _$0 ${^0} v - 3420 if !${} noarg fi 3421 3422_display_rgba : skip "${1=},${2=$1},${3=$1}" 3423 l[] is_rgb={"isnum($1)"} onfail is_rgb=0 endl 3424 if $is_rgb e[0--4] "Render RGBA image"$_gmic_s" over RGB background ($*)." 3425 else e[0--4] "Render RGBA image"$_gmic_s" over a checkerboard background." 3426 fi 3427 repeat $! l[$>] if s==2" || "s==4 3428 if $is_rgb i[0] 100%,100%,1,3 fc[0] {[$*]} 3429 else i[0] (160,128;128,160) r[0] 16,16 r[0] [1],[1],1,{s-1},0,2 3430 fi 3431 nm[0] {1,n} 3432 sh. {s-1} j[0] [1],0,0,0,0,1,[2],255 k[0] 3433 fi endl done to_rgb u $is_rgb 3434 3435#@cli dt : eq. to 'display_tensors'. 3436dt : 3437 _gmic_s="$?" v + _display_tensors $* 3438 3439#@cli display_tensors : _size_factor>0,_ellipse_size>=0,_color_mode={ 0=monochrome | 1=grayscale | 2=color },_outline>=0 3440#@cli : Render selected images of tensors as a field of 2D ellipses. 3441#@cli : (eq. to 'dt'). 3442#@cli : Default values: 'size_factor=16', 'ellipse_size=1.5', 'color_mode=2' and 'outline=2'. 3443#@cli : $ image.jpg +diffusiontensors 0.1,0.9 resize2dx. 32 +display_tensors. 64,2 3444#@cli : $$ https://gmic.eu/oldtutorial/_display_tensors 3445display_tensors : 3446 _gmic_s="$?" v + _$0 $* 3447 3448_display_tensors : check "${1=16}>0 && ${2=1.5}>=0 && isint(${3=2}) && $3>=0 && $3<=2 && ${4=2}>=0" 3449 e[0--3] "Render field of 2x2 tensors from image"$_gmic_s", with size factor $1, ellipse size $2 in "\ 3450 ${arg\ 1+$3,monochrome,grayscale,color}" mode and outline $4." 3451 repeat $! l[$>] 3452 * {($2*$1/2)/max(abs(im),abs(iM))} # Normalize tensor values. 3453 {$1*w},{$1*h},1,{"1<<cut($3,0,2)"} 3454 f.. " 3455 begin(C = resize([255],s#1,1); Co = resize([0],s#1,1); Co[s#1 - 1] = $3?255:0); 3456 "${-math_lib}" 3457 X = ([ x,y ]+=0.5)*$1; 3458 T = [ R, G, G, B ]; 3459 E = eig(T); 3460 r1 = E[0]; 3461 r2 = E[1]; 3462 ang = atan2(E[3],E[2])*180/pi; 3463 if ($3, 3464 v = min(1,max(0.5,3*r1/($1*$2))); 3465 if ($3==1, 3466 C = [ 255*v,255 ], 3467 C = [ hsv2rgb([ 2*ang,1-r2/r1,v ]), 255 ]; 3468 ); 3469 ); 3470 for (k = 1, k>=0, --k, ellipse(#1,X,r1 + k*$4,r2 + k*$4,ang°,1,arg(k + 1,C,Co))); 3471 I" 3472 rm.. 3473 endl done 3474 3475#@cli dw : eq. to 'display_warp'. 3476dw : 3477 _gmic_s="$?" v + _display_warp $* 3478 3479#@cli display_warp : _cell_size>0 3480#@cli : Render selected 2D warping fields. 3481#@cli : (eq. to 'dw'). 3482#@cli : Default value: 'cell_size=15'. 3483#@cli : $ 400,400,1,2,'x=x-w/2;y=y-h/2;r=sqrt(x*x+y*y);a=atan2(y,x);5*sin(r/10)*[cos(a),sin(a)]' +display_warp 10 3484display_warp : 3485 _gmic_s="$?" v + _$0 $* 3486 3487_display_warp : check "${1=15}>0" 3488 e[0--3] "Render 2D warping field"$_gmic_s", with cell size $1." 3489 repeat $! l[$>] 3490 if d!=1" || "s!=2 3491 error[0--3] "Command 'display_warp': Invalid image ["{$!-$>-1}"]: Dimensions "{w}","{h}","{d}","{s}" 3492 does not represent a 2D field of 2D vectors." 3493 fi 3494 i[0] 100%,100%,1,1,1 grid[0] $1,$1 nm[0] {1,n} 3495 warp[0] [1],1,1,0 rm[1] 3496 endl done * 255 3497 3498#@cli e : eq. to 'echo'. : (+) 3499 3500#@cli echo : message : (+) 3501#@cli : Output specified message on the error output. 3502#@cli : (eq. to 'e').\n 3503#@cli : Command selection (if any) stands for displayed call stack subset instead of image indices. 3504#@cli : When invoked with a '+' prefix (i.e. '+echo'), the command output its message on stdout rather than stderr. 3505 3506#@cli echo_file : filename,message 3507#@cli : Output specified message, appending it to specified output file. 3508#@cli : (similar to 'echo' for specified output file stream). 3509echo_file : skip "${2='\n'}" 3510 ('"${2--1}\n"') ot. $1 rm. 3511 3512#@cli function1d : 0<=smoothness<=1,x0>=0,y0,x1>=0,y1,...,xn>=0,yn 3513#@cli : Insert continuous 1D function from specified list of keypoints (xk,yk) 3514#@cli : in range [0,max(xk)] (xk are positive integers). 3515#@cli : $ function1d 1,0,0,10,30,40,20,70,30,80,0 +display_graph 400,300 3516+function1d : 3517 e[^-1] "Input continuous 1D function, with smoothness $1 and keypoints (${2--1})." 3518 l[] 3519 3520 # Sort and normalize input keypoints. 3521 smoothness={max(0,min(1,$1))} 3522 (${2--1}) r 2,{int(w/2)},1,1,-1 3523 sort +,y s x size={0,iM>=0?1+int(iM):0} 3524 if !$size rm 0 break fi 3525 a x 3526 3527 # Compute slopes for splines. 3528 +f '0.5*(j(0,1,0,0,0,1)-j(0,-1,0,0,0,1))' s. x max.. 0.01 /. .. rm.. a x 3529 3530 # Determine spline coefficients for each part of the curve. 3531 $size,1,1,1,-1 3532 repeat h#0-1 3533 x0={0,i(0,$>)} y0={0,i(1,$>)} x1={0,i(0,$>+1)} y1={0,i(1,$>+1)} 3534 slope={($y1-$y0)/max(0.01,$x1-$x0)} 3535 yp0={0,i(2,$>)*$smoothness+(1-$smoothness)*$slope} 3536 yp1={0,i(2,$>+1)*$smoothness+(1-$smoothness)*$slope} 3537 i={round($x0,1,1)} j={round($x1,1,0)} 3538 line[1] $i,0,$j,0,1,$> 3539 if $j-$i<=1 # Linear interpolation for very close points. 3540 ({$y0-$x0*$slope}^{$slope}^0^0) 3541 else # Cubic interpolation otherwise. 3542 (1,$x0,{($x0)^2},{($x0)^3};\ 3543 1,$x1,{($x1)^2},{($x1)^3};\ 3544 0,1,{2*$x0},{3*($x0)^2};\ 3545 0,1,{2*$x1},{3*($x1)^2}) 3546 ($y0;$y1;$yp0;$yp1) 3547 invert.. mmul[-2,-1] y. c 3548 fi 3549 done 3550 a[2--1] x map.. . rm. 3551 3552 # Render final curve. 3553 100%,1,1,1,1 3554 (0,{w-1}) r. {-2,w},1,1,1,3 round. 3555 +sqr. +*[-2,-1] a[-4--1] c *[-2,-1] s. c +[-4--1] rm.. 3556 endl 3557 3558#@cli i : eq. to 'input'. : (+) 3559 3560#@cli input : \ 3561# [type:]filename : \ 3562# [type:]http://URL : \ 3563# [selection]x_nb_copies>0 : \ 3564# { width>0[%] | [image_w] },{ _height>0[%] | [image_h] },{ _depth>0[%] | [image_d] },{ _spectrum>0[%] \ 3565# | [image_s] },_{ value1,_value2,... | 'formula' } : \ 3566# (value1{,|;|/|^}value2{,|;|/|^}...[:{x|y|z|c|,|;|/|^}]) : \ 3567# 0 : (+) 3568#@cli : Insert a new image taken from a filename or from a copy of an existing image [index], 3569#@cli : or insert new image with specified dimensions and values. Single quotes may be omitted in 3570#@cli : 'formula'. Specifying argument '0' inserts an 'empty' image. 3571#@cli : (eq. to 'i' | (no arg)). 3572#@cli : Default values: 'nb_copies=1', 'height=depth=spectrum=1' and 'value1=0'. 3573#@cli : $ input image.jpg 3574#@cli : $ input (1,2,3;4,5,6;7,8,9^9,8,7;6,5,4;3,2,1) 3575#@cli : $ image.jpg (1,2,3;4,5,6;7,8,9) (255^128^64) 400,400,1,3,'(x>w/2?x:y)*c' 3576#@cli : $$ 3577 3578#@cli input_565 : filename,width>0,height>0,reverse_endianness={ 0 | 1 } 3579#@cli : Insert image data from a raw RGB-565 file, at the end of the list. 3580#@cli : Default value: 'reverse_endianness=0'. 3581+input_565 : check "isint($2) && $2>0 && isint($3) && $3>0 && isbool(${4=0})" 3582 e[^-1] "Input raw RGB-565 file '$1', with size $2x$3." 3583 l[] raw:"$1",ushort if $4 endian ushort fi 3584 r $2,$3,1,1,-1 +>> 5 &. 63 +&.. 31 >>... 11 *[-3,-1] 8 *.. 4 a c endl 3585 3586#@cli input_csv : "filename",_read_data_as={ 0=numbers | 1=strings | _variable_name } 3587#@cli : Insert number of string array from specified .csv file. 3588#@cli : If 'variable_name' is provided, the string of each cell is stored in a numbered variable '_variable_name_x_y', \ 3589# where 'x' and 'y' are the indices of the cell column and row respectively (starting from '0'). 3590#@cli : Otherwise, a 'WxH' image is inserted at the end of the list, with each vector-valued pixel 'I(x,y)' encoding \ 3591# the number or the string of each cell. 3592#@cli : This command returns the 'W,H' dimension of the read array, as the status. 3593#@cli : Default value: 'read_data_as=1'. 3594+input_csv : check "isvarname('${2=1}') || isin($2,0,1,2)" 3595 l[] 3596 is_var={"s=['$2'];s!='0'&&s!='1'"} 3597 if $is_var # Read data as new variables 3598 e[0--4] "Input string array from file '$1', in variable '$2'." 3599 it "$1" replace {'" "'},255 s -,{'\n'} 3600 W,H=0,$! 3601 repeat $! _input_csv_var[] $2,$>,${u\ {$>,t}} W={max($W,${})} done 3602 rm u $W,$H 3603 else # Read data as a new image 3604 s0,s1="number","string" 3605 e[0--4] "Input "${s$2}" array from file '$1'." 3606 it "$1" s -,{'\n'} replace {'" "'},255 3607 if $2 repeat $! _input_csv_str[] ${u\ {$>,t}} rv[$>,-1] rm. done a y replace 255,{'" "'} # Read as strings 3608 else repeat $! _input_csv_val[] ${u\ {$>,t}} rv[$>,-1] rm. done a y # Read as values 3609 fi 3610 nm "$1" u {[w,h]} 3611 fi 3612 endl 3613 3614_input_csv_var : 3615 $=arg 3616 W={$#-2} 3617 repeat $W 3618 arg=${arg{3+$>}} 3619 if ['$arg']!=0 ({'${arg{3+$>}}'}) replace. 255,{'" "'} $1_$>_$2={t} rm. else $1_$>_$2= fi 3620 done 3621 u $W 3622 3623_input_csv_str : 3624 $=arg 3625 repeat $# 3626 arg=${arg{1+$>}} 3627 if ['$arg']!=0 ({'$arg'}:c) else (0) fi 3628 done 3629 a x 3630 3631_input_csv_val : 3632 $=arg 3633 repeat $# 3634 arg=${arg{1+$>}} 3635 if ['$arg']!=0 ({stov(['$arg'])}) else (nan) fi 3636 done 3637 a x 3638 3639#@cli input_cube : "filename",_convert_1d_cluts_to_3d={ 0 | 1 }. 3640#@cli : Insert CLUT data from a .cube filename (Adobe CLUT file format). 3641#@cli : Default value: 'convert_1d_cluts_to_3d=1'. 3642+input_cube : skip ${2=1} 3643 e[^-1] "Input CLUT from file '$1'" 3644 l[] 3645 it[] "$1" f "i<_' ' && i!=10?_' ':i" s -,10 3646 i[0] 0 3647 range={" 3648 ref(vector128(),line); 3649 dmin = [ 0,0,0 ]; 3650 dmax = [ 1,1,1 ]; 3651 dim = size = 0; 3652 target = 0; 3653 for (k = 1, k<l, ++k, 3654 linesiz = min(size(line)-1,h#k); 3655 copy(line[0],i[#k,0],linesiz); 3656 copy(line[linesiz],0,size(line) - linesiz,1,0); 3657 same(line,'LUT_1D_SIZE ',12)?( 3658 copy(line[0],line[12],size(line) - 12); 3659 size = stov(line); 3660 dim = 1; 3661 resize(#0,3,size,1,1,0); 3662 ):same(line,'LUT_3D_SIZE ',12)?( 3663 copy(line[0],line[12],size(line) - 12); 3664 size = stov(line); 3665 dim = 3; 3666 resize(#0,3,size,size,size,0); 3667 ):same(line,'DOMAIN_MIN ',11)?( 3668 copy(line[0],line[11],size(line) - 11); 3669 dmin[0] = stov(line); 3670 ind = find(line,_' '); 3671 copy(line[0],line[ind + 1],size(line) - ind); 3672 dmin[1] = stov(line); 3673 ind = find(line,_' '); 3674 copy(line[0],line[ind + 1],size(line) - ind); 3675 dmin[2] = stov(line); 3676 ):same(line,'DOMAIN_MAX ',11)?( 3677 copy(line[0],line[11],size(line) - 11); 3678 dmax[0] = stov(line); 3679 ind = find(line,_' '); 3680 copy(line[0],line[ind + 1],size(line) - ind); 3681 dmax[1] = stov(line); 3682 ind = find(line,_' '); 3683 copy(line[0],line[ind + 1],size(line) - ind); 3684 dmax[2] = stov(line); 3685 ):( 3686 val = stov(line); 3687 !isnan(val)?do ( 3688 i[#0,target++] = val; 3689 ind = find(line,_' '); 3690 ind<0?break(); 3691 copy(line[0],line[ind + 1],size(line) - ind); 3692 val = stov(line); 3693 ,_(while); !isnan(val)); 3694 ); 3695 ); 3696 [dmin,dmax];"} 3697 3698 k[0] 3699 permute yzcx 3700 if [$range]!=[0,0,0,1,1,1] 3701 f "begin( 3702 range = ["$range"]; 3703 dmin = range[0,3]; 3704 dmax = range[3,3]; 3705 delta = dmax - dmin; 3706 ); 3707 (I - dmin)*255/delta" 3708 else * 255 3709 fi 3710 if "w>1 && h==1 && d==1 && $2" size={w} s c y.. y. z r $size,$size,$size a c fi 3711 nm "$1" 3712 endl 3713 3714#@cli input_flo : "filename" 3715#@cli : Insert optical flow data from a .flo filename (vision.middlebury.edu file format). 3716+input_flo : 3717 e[^-1] "Input optical flow from file '$1'." 3718 l[] 3719 i raw:"$1",float 3720 if i!=202021.25 endian. fi 3721 if i!=202021.25 error[0--3] "Command 'input_flo': Filename '$1' is not a valid .flo file." return fi 3722 +rows 1,2 cast. float,uint w,h={^} rm. 3723 rows 3,100% r 2,$w,$h,1,-1 permute yzcx 3724 endl 3725 3726#@cli ig : eq. to 'input_glob'. 3727+ig : 3728 v + _input_glob "$*" 3729 3730#@cli input_glob : pattern 3731#@cli : Insert new images from several filenames that match the specified glob pattern. 3732#@cli : (eq. to 'ig'). 3733+input_glob : 3734 _input_glob "$*" 3735 3736_input_glob : 3737 e[0--3] "Input all files that match glob pattern '$*'." 3738 files 3,"$*" 3739 N=$! 3740 m "_ig : $""=arg repeat $""# i ${arg{1+$>}} done" 3741 _ig ${} um _ig 3742 if $N==$! error[0--3] "Command 'input_glob': No matching filenames for pattern '$*'." fi 3743 3744#@cli input_gpl : filename 3745#@cli : Input specified filename as a .gpl palette data file. 3746+input_gpl : 3747 e[^-1] "Input .gpl palette file '$*'." 3748 l[] 3749 it[] "$*" discard 13 replace 9,32 s -,10 3750 colors=0 3751 repeat $! l[$>] 3752 s -,32 3753 if $!>=3" && "isint({0,t})" && "isint({1,t})" && "isint({2,t}) colors=$colors;{0,t},{1,t},{2,t} fi 3754 rm 0 3755 onfail rm 0 endl done 3756 rm ($colors) rows 1,100% nm "$1" permute yzcx 3757 endl 3758 3759#@cli input_cached : "basename.ext",_try_downloading_from_gmic_server={ 0 | 1 } 3760#@cli : Input specified filename, assumed to be stored in one of the G'MIC resource folder. 3761#@cli : If file not found and 'try_downloading=1', file is downloaded from the G'MIC server and stored 3762#@cli : in the '${-path_cache}' folder. 3763#@cli : Default value: 'try_downloading_from_gmic_server=1'. 3764+input_cached : check "isbool(${2=1})" 3765 basename "$1" basename=${} 3766 e[^-1] "Input cached file '"$basename"'." 3767 if ['$GMIC_SYSTEM_PATH']!=0 g_path_unix=$GMIC_SYSTEM_PATH/ else g_path_unix=/usr/lib/gimp/2.0/plug-ins/ fi 3768 path_test0=${-path_cache} 3769 path_test1=$_path_rc 3770 path_test2=${-path_gimp}plug-ins/ 3771 path_test3=${-path_gimp}plug-ins/gmic_gimp_qt/ 3772 path_test4=$g_path_unix 3773 file_found=0 3774 repeat 5 3775 file=${path_test$>}$basename 3776 l[] i $file file_found=1 onfail endl 3777 if $file_found break fi 3778 done 3779 if !$file_found" && $2" # Try downloading from the G'MIC server 3780 url=https://gmic.eu/"$1" 3781 l[] i $url o ${-path_cache}$basename file_found=1 is_change 1 3782 onfail 3783 endl 3784 fi 3785 if !$file_found 3786 error[0--3] "Command 'input_cached': Unknown filename '$1'." 3787 fi 3788 3789#@cli it : eq. to 'input_text'. 3790+it : 3791 v + _input_text "$*" 3792 3793#@cli input_text : filename 3794#@cli : Input specified text-data filename as a new image. 3795#@cli : (eq. to 'it'). 3796+input_text : 3797 v + _$0 "$*" 3798 3799_input_text : 3800 e[0--3] "Input text-data file '$*'." 3801 i raw:"$*",uchar 3802 if i[0]==239" && "i[1]==187" && "i[2]==191 rows. 3,100% fi # Remove BOM 3803 discard. {'\r'} # Remove CR 3804 3805#@cli lorem : _width>0,_height>0 3806#@cli : Input random image of specified size, retrieved from Internet. 3807#@cli : Default values: 'width=height=800'. 3808+lorem : check "isint(${1=800}) && $1>0 && isint(${2=$1}) && $2>0" 3809 e[^-1] "Input random image of size $1x$2." 3810 i "https://picsum.photos/$1/$2" 3811 3812# Merge multi-lines (lines continued by backslash before NL) in a string image. 3813merge_multiline : 3814 eval[^] "*i==_'\\' && j[-1]!=_'\\' && j[+1]==_'\n'?( 3815 for (p = 2, j[p] && j[p]<=_' ' && j[p]!=_'\n', ++p); copy(i(),-1,p,1,0))" 3816 discard -1 3817 3818# Merge multi-line comments in a string image. 3819merge_multiline_comments : 3820 eval[^] "*i==_'\\' && j[-1]!=_'\\' && j[+1]==_'\n' && j[+2]==_'#'?( 3821 for (p = 3, j[p] && j[p]<=_' ' && j[p]!=_'\n', ++p); copy(i(),-1,p,1,0))" 3822 discard -1 3823 3824#@cli network : mode={ -1=disabled | 0=enabled w/o timeout | >0=enabled w/ specified timeout in seconds } : (+) 3825#@cli : Enable/disable load-from-network and set corresponding timeout. 3826#@cli : (Default mode is 'enabled w/o timeout'). 3827 3828#@cli o : eq. to 'output'. : (+) 3829 3830#@cli output : [type:]filename,_format_options : (+) 3831#@cli : Output selected images as one or several numbered file(s). 3832#@cli : (eq. to 'o'). 3833#@cli : Default value: 'format_options'=(undefined). 3834 3835#@cli output_565 : "filename",reverse_endianness={ 0=false | 1=true } 3836#@cli : Output selected images as raw RGB-565 files. 3837#@cli : Default value: 'reverse_endianness=0'. 3838output_565 : check "isbool(${2=0})" 3839 e[^-1] "Output image$? as raw RGB-565 file '$1'." 3840 N=$! repeat $N +l[$>] 3841 s c c 0,255 /[-3,-1] 8 /.. 4 round 3842 bsl... 11 bsl.. 5 + 3843 if $N>1 fn=${"filename \"$1\",$>"} else fn="$1" fi 3844 if $2 endian ushort fi 3845 o raw:$fn,ushort rm 3846 endl done is_change 0 3847 3848#@cli output_cube : "filename" 3849#@cli : Output selected CLUTs as a .cube file (Adobe CLUT format). 3850output_cube : 3851 e[^-1] "Output CLUT$? as file '$1'." 3852 N=$! repeat $N +l[$>] to_rgb 3853 l={round((w*h*d)^(1/3))} 3854 if w*h*d!=$l^3 error "Command '$0': CLUT '"{n}"' has invalid dimensions "({w},{h},{d},{s}). fi 3855 r $l,$l,$l,3,-1 permute cxyz / 255 3856 if $N>1 fn=${"filename \"$1\",$>"} else fn="$1" fi 3857 o dlm:$fn rm it[] $fn replace {','},32 3858 0 nm. $fn basename={b} rm. 3859 header="\# Created by: G'MIC (https://gmic.eu)\n"\ 3860 "TITLE \""$basename"\"\n\n"\ 3861 "# LUT size\n"\ 3862 "LUT_3D_SIZE "$l"\n\n"\ 3863 "# Data domain\n"\ 3864 "DOMAIN_MIN 0.0 0.0 0.0\n"\ 3865 "DOMAIN_MAX 1.0 1.0 1.0\n\n"\ 3866 "# LUT data points\n" 3867 i[0] ('$header') 3868 y a y ot $fn rm 3869 endl done is_change 0 3870 3871#@cli output_flo : "filename" 3872#@cli : Output selected optical flow as a .flo file (vision.middlebury.edu file format). 3873output_flo : 3874 e[^-1] "Output optical flow$? as file '$1'." 3875 N=$! repeat $N +l[$>] 3876 w,h={[w,h]} 3877 channels 0,1 permute cxyz i[0] (202021.25) i[1] ($w,$h) cast[1] uint,float y a y 3878 if $N>1 fn=${"filename \"$1\",$>"} else fn="$1" fi 3879 o raw:$fn,float rm 3880 endl done is_change 0 3881 3882#@cli output_ggr : filename,_gradient_name 3883#@cli : Output selected images as .ggr gradient files (GIMP). 3884#@cli : If no gradient name is specified, it is deduced from the filename. 3885output_ggr : skip "${2=}" 3886 e[^-1] "Output image$? as .ggr gradient file '$1'." 3887 N=$! 3888 repeat $N +l[$>] r 1,{w*h*d},1,100%,-1 to_rgba / 255 3889 if narg("$2") name="$2" 3890 else l[] 1 nm. "$1" ('{b}') f "if(x==0 && i>=_'a' && i<=_'z',i-_'a'+_'A',i)" name={t} rm endl 3891 fi 3892 ('"GIMP Gradient\nName: "$name\n{0,h}\n') 3893 repeat h#0 3894 start={_$>/{0,h}} 3895 end={_($>+1)/{0,h}} 3896 mid={_0.5*($start+$end)} 3897 rgba={0,I(0,$>)} 3898 r={arg(1,$rgba)} g={arg(2,$rgba)} b={arg(3,$rgba)} a={arg(4,$rgba)} 3899 ('$start" "$mid" "$end" "$r" "$g" "$b" "$a" "$r" "$g" "$b" "$a" 0 0\n"') 3900 done 3901 rm[0] a x 3902 if $N>1 ot ${"filename \"$1\",$>"} else ot "$1" fi 3903 rm 3904 endl done is_change 0 3905 3906#@cli output_gmz : filename,_datatype 3907#@cli : Output selected images as .gmz files (G'MIC native file format). 3908#@cli : 'datatype' can be { bool | uchar | char | ushort | short | uint | int | uint64 | int64 | float | double }. 3909output_gmz : skip ${2=auto} 3910 e[^-1] "Output image$? as gmz file '$1', with pixel type '$2'." 3911 1,64 3912 eval " 3913 draw([_'G',_'M',_'Z'],0,0,0,0,1,3); 3914 pos = 4; 3915 repeat (l - 1,k, 3916 ref(name(#k,1026),nam); 3917 len = find(nam,0); 3918 len>=0?( 3919 pos + len>=h?resize(#-1,1,2*h + len,1,1,0); 3920 len>0?draw(nam,0,pos,0,0,1,len); 3921 pos+=1 + len; 3922 ); 3923 ); 3924 resize(#-1,1,pos,1,1,0)" 3925 o cimgz:$1,$2 3926 rm. 3927 3928#@cli output_obj : filename,_save_materials={ 0=no | 1=yes } 3929#@cli : Output selected 3D objects as Wavefront 3D object files. 3930#@cli : Set 'save_materials' to '1' to produce a corresponding material file (`.mtl`) and eventually texture files. 3931#@cli : Beware, the export to `.obj` files may be quite slow for large 3D objects. 3932#@cli : Default value: 'save_materials=1'. 3933output_obj : check "isbool(${2=1})" check3d 0 3934 s0,s1=out, 3935 e[^-1] "Output 3D object$? as Wavefront 3D object file '$1' (with"${s$2}" materials)." 3936 N=$! repeat $N nm={$>,n} +l[$>] 3937 nb_materials,nb_primitives,nb_textures,nb_tcoords=0 3938 3939 # Generate basename, file header and eval macros. 3940 if $N>1 filename=${"filename \"$1\",$>"} else filename="$1" fi 3941 0 nm. $filename basename={b} folder={f} ext={x} if narg($ext) ext=.$ext fi rm. 3942 fnobj="begin(out = 0); 3943 tos(x) = vtos(x,6); 3944 write(ind,s) = ( 3945 l_s = find(s,0); 3946 l_s<=0?(l_s = size(s)); 3947 out + l_s>h(#ind)?resize(#ind,1,2*h(#ind) + l_s,1,1,0); 3948 copy(i[#ind,out],s,l_s); 3949 out+=l_s)" 3950 3951 # Decompose into vertices, primitives and colors. 3952 s3d 0 nb_vertices,nbp={1,f2ui([i[0],i[1]])} rm[0,1,5] 3953 e[] " > File '"$folder$basename$ext"' ("$nb_vertices" vertices, "$nbp" primitives)." 3954 3955 # Generate vertex output. 3956 l[0] 3957 e[] " - Export vertices." 3958 r 3,{h/3},1,1,-1 permute zycx 3959 0 nm. out_obj 3960 eval.. ">"$fnobj"; 3961 !(y%10000)?run('e[] \"\r - Export vertices: ',round(100*y/h),' % \"'); 3962 ref(string('v ',tos(i0),' ',tos(i1),' ',tos(i2),'\n'),str); 3963 write(#"$out_obj",str); I; 3964 end(resize(#"$out_obj",1,out,1,1,0))" 3965 rm[0] i[0] ('"\n# Vertices.\n"':y) a y nm out_obj 3966 e[] "\r - Export vertices: Done." 3967 endl 3968 3969 # Generate material output. 3970 if $2 l. 3971 e[] " - Export materials." 3972 256,256,256 nm. materials_rgb 3973 1,$nbp,1,3 nm. materials 3974 0 nm. out_mtl 3975 mv[0] $! 3976 eval $fnobj"; 3977 const nbp = "$nbp"; 3978 off = nb_materials = nb_textures = 0; 3979 repeat (nbp,p, 3980 !(p%10000)?run('e[] \"\r - Export materials: ',round(100*p/nbp),' % \"'); 3981 3982 i[off]!=-128?( # RGB color 3983 ref(cut(round(crop(0,off,1,3)),0,255),rgb); 3984 m = i(#"$materials_rgb",rgb); 3985 !m?( 3986 ++nb_materials; 3987 ref(string('newmtl m',nb_materials,'\n', 3988 'Kd ',tos(rgb[0]/255),' ',tos(rgb[1]/255),' ',tos(rgb[2]/255),'\n'),str); 3989 write(#"$out_mtl",str); 3990 m = i(#"$materials_rgb",rgb) = nb_materials; 3991 ); 3992 i[#"$materials",p] = m; 3993 off+=3; 3994 3995 ):i[off + 2]?( # Non-shared texture 3996 ++nb_materials; ++nb_textures; 3997 wt = i[off + 1]; ht = i[off + 2]; st = i[off + 3]; 3998 run('+rows. ',off + 4,',',off + 3 + wt*ht*st,' r. ',wt,',',ht,',1,',st,',-1 tfn=$folder${basename}_t', 3999 nb_textures,'.png o. $tfn rm.'); 4000 tfile = get('tfn',1024,1); 4001 ref(string('newmtl m',nb_materials,'\n', 4002 'map_Kd ',get('tfn',1024,1),'\n'),str); 4003 write(#"$out_mtl",str); 4004 I[#"$materials",p] = [ nb_materials,wt,ht ]; 4005 off+=4 + wt*ht*st; 4006 4007 ):( # Shared texture 4008 tind = i[off + 1]; 4009 I[#"$materials",p] = I[#"$materials",tind]; 4010 off+=4; 4011 4012 ); 4013 ); 4014 resize(#"$out_mtl",1,out,1,1,0); 4015 run('nb_materials,nb_textures=',nb_materials,',',nb_textures)" 4016 e[] "\r - Export materials: Done." 4017 k[materials,out_mtl] 4018 endl fi 4019 4020 # Generate primitive output. 4021 e[] " - Export primitives." 4022 0 nm. out_prim 4023 mv[1] $! 4024 eval $fnobj"; 4025 const materials = 0"$materials"; 4026 const nbp = "$nbp"; 4027 off = p_material = material = nb_primitives = nb_tcoords = 0; 4028 repeat (nbp,p, 4029 !(p%10000)?run('e[] \"\r - Export primitives: ',round(100*p/nbp),' % \"'); 4030 4031 type = i[off]; 4032 $2?material = i[#materials,p]; 4033 material!=p_material?ref(string('usemtl m',material,'\n'),str_mtl); 4034 4035 type==1?( # Colored point 4036 ref(string('p ',f2ui(i[off + 1] + 1),'\n'),str); 4037 write(#"$out_prim",str); 4038 ++nb_primitives; 4039 4040 ):type==2?( # Colored or textured segment 4041 ref(string('l ',f2ui(i[off + 1]) + 1,' ',f2ui(i[off + 2]) + 1,'\n'),str); 4042 write(#"$out_prim",str); 4043 ++nb_primitives; 4044 4045 ):type==3 || (type==9 && !$2)?( # Colored triangle 4046 $2 && material!=p_material?write(#"$out_prim",str_mtl); 4047 ref(string('f ',f2ui(i[off + 1]) + 1,' ',f2ui(i[off + 2]) + 1,' ',f2ui(i[off + 3]) + 1,'\n'),str); 4048 write(#"$out_prim",str); 4049 ++nb_primitives; 4050 4051 ):type==4 || (type==12 && !$2)?( # Colored quadrangle 4052 $2 && material!=p_material?write(#"$out_prim",str_mtl); 4053 ref(string('f ',f2ui(i[off + 1]) + 1,' ',f2ui(i[off + 2]) + 1,' ', 4054 f2ui(i[off + 3]) + 1,' ',f2ui(i[off + 4]) + 1,'\n'),str); 4055 write(#"$out_prim",str); 4056 ++nb_primitives; 4057 4058 ):type==9?( # Textured triangle 4059 material!=p_material?write(#"$out_prim",str_mtl); 4060 wt = i(#materials,0,p,0,1); ht = i(#materials,0,p,0,2); 4061 ref(string('vt ',tos(i[off + 4]/wt),' ',tos(1 - i[off + 5]/ht),'\n', 4062 'vt ',tos(i[off + 6]/wt),' ',tos(1 - i[off + 7]/ht),'\n', 4063 'vt ',tos(i[off + 8]/wt),' ',tos(1 - i[off + 9]/ht),'\n', 4064 'f ',f2ui(i[off + 1]) + 1,'/',nb_tcoords + 1,' ',f2ui(i[off + 2]) + 1,'/',nb_tcoords + 2, 4065 ' ',f2ui(i[off + 3]) + 1,'/',nb_tcoords + 3,'\n'),str); 4066 write(#"$out_prim",str); 4067 nb_tcoords+=3; 4068 ++nb_primitives; 4069 4070 ):type==12?( # Textured quadrangle 4071 material!=p_material?write(#"$out_prim",str_mtl); 4072 wt = i(#materials,0,p,0,1); ht = i(#materials,0,p,0,2); 4073 ref(string('vt ',tos(i[off + 5]/wt),' ',tos(1 - i[off + 6]/ht),'\n', 4074 'vt ',tos(i[off + 7]/wt),' ',tos(1 - i[off + 8]/ht),'\n', 4075 'vt ',tos(i[off + 9]/wt),' ',tos(1 - i[off + 10]/ht),'\n', 4076 'vt ',tos(i[off + 11]/wt),' ',tos(1 - i[off + 12]/ht),'\n', 4077 'f ',f2ui(i[off + 1]) + 1,'/',nb_tcoords + 1,' ',f2ui(i[off + 2]) + 1,'/',nb_tcoords + 2, 4078 ' ',f2ui(i[off + 3]) + 1,'/',nb_tcoords + 3,' ',f2ui(i[off + 4]) + 1,'/',nb_tcoords + 4,'\n'),str); 4079 write(#"$out_prim",str); 4080 nb_tcoords+=4; 4081 ++nb_primitives; 4082 4083 ):( # Unsupported primitive 4084 run(['warn[] \"Command 'output_obj': Cannot convert primitive \#'],p,'/',nbp - 1, 4085 ' (size ',type,'). Ignoring it.\"'); 4086 ); 4087 4088 off+=type + 1; 4089 p_material = material; 4090 ); 4091 resize(#"$out_prim",1,out,1,1,0); 4092 run('nb_primitives=',nb_primitives)" 4093 e[] "\r - Export primitives: Done." 4094 l[out_obj,out_prim] i[1] ('"\n# Primitives.\n"':y) a y endl 4095 if $2 k[out_mtl,out_obj] else k[out_obj] fi 4096 4097 # Generate file header. 4098 header="# Object name: "$nm\n\ 4099 "# Vertices: "$nb_vertices\n\ 4100 "# Primitives: "$nb_primitives\n\ 4101 "# Materials: "$nb_materials\n\ 4102 "# Textures: "$nb_textures\n\ 4103 {`"d2(x) = (s = date(x); s>9?vtos(s,-1,2):[0,s]+_'0'); 4104 string('# Generated on ',d2(0),'/',d2(1),'/',d2(2),' at ',d2(4),':',d2(5),':',d2(6), 4105 ' by G\47MIC (https://gmic.eu).\n')"`} 4106 4107 # Save object geometry (.obj file). 4108 l[out_obj] 4109 i[0] ('"# File: "$folder$basename$ext\n$header':y) 4110 if $2 i[1] ('"\n# Materials.\n\ 4111 mtllib "$folder$basename$ext".mtl\n"':y) fi 4112 a y 4113 o raw:$folder$basename$ext,uchar 4114 endl 4115 4116 # Save object materials (.mtl file). 4117 if $2 l[out_mtl] 4118 i[0] ('"# File: "$folder$basename$ext.mtl\n$header\n':y) 4119 a y 4120 o raw:$folder$basename$ext.mtl,uchar 4121 endl fi 4122 4123 rm 4124 endl done is_change 0 4125 4126#@cli ot : eq. to 'output_text'. 4127ot : 4128 _gmic_s="$?" v + _output_text "$*" 4129 4130#@cli output_text : filename 4131#@cli : Output selected images as text-data filenames. 4132#@cli : (eq. to 'ot'). 4133output_text : 4134 _gmic_s="$?" v + _$0 "$1" 4135 4136_output_text : 4137 e[0--3] "Output image"$_gmic_s" as text-data file '$1'." 4138 o raw:"$1",uchar 4139 4140#@cli on : eq. to 'outputn'. 4141on : 4142 _gmic_s="$?" v + _outputn $* 4143 4144#@cli outputn : filename,_index 4145#@cli : Output selected images as automatically numbered filenames in repeat...done loops. 4146#@cli : (eq. to 'on'). 4147outputn : 4148 _gmic_s="$?" v + _$0 $* 4149 4150_outputn : skip "${2=}" 4151 if $#==1 filename=${filename\ "$1",$>} 4152 else filename=${filename\ "$1",$2} 4153 fi 4154 e[0--3] "Output image"$_gmic_s" as file '"$filename"'." 4155 o $filename 4156 4157#@cli op : eq. to 'outputp'. 4158op : 4159 _gmic_s="$?" v + _outputp $* 4160 4161#@cli outputp : prefix 4162#@cli : Output selected images as prefixed versions of their original filenames. 4163#@cli : (eq. to 'op'). 4164#@cli : Default value: 'prefix=_'. 4165outputp : 4166 _gmic_s="$?" v + _$0 $* 4167 4168_outputp : skip ${1="_"} 4169 if $!>1 e[0--4] "Output image"$_gmic_s" as their initial locations, prefixed by '$1'." 4170 else e[0--4] "Output image"$_gmic_s" as its initial location, prefixed by '$1'." 4171 fi 4172 repeat $! o[$>] {$>,f}$1{$>,b}.{$>,x} done 4173 4174#@cli ow : eq. to 'outputw'. 4175ow : 4176 _gmic_s="$?" v + _outputw 4177 4178#@cli outputw 4179#@cli : Output selected images by overwriting their original location. 4180#@cli : (eq. to 'ow'). 4181outputw : 4182 _gmic_s="$?" v + _$0 $* 4183 4184_outputw : 4185 if $!>1 e[0--4] "Output image"$_gmic_s" as their initial location." 4186 else e[0--4] "Output image"$_gmic_s" as its initial location." 4187 fi 4188 repeat $! o[$>] {$>,n} done 4189 4190#@cli ox : eq. to 'outputx'. 4191ox : 4192 _gmic_s="$?" v + _outputx $* 4193 4194#@cli outputx : extension1,_extension2,_...,_extensionN,_output_at_same_location={ 0 | 1 } 4195#@cli : Output selected images with same base filenames but for N different extensions. 4196#@cli : (eq. to 'ox'). 4197#@cli : Default value: 'output_at_same_location=0'. 4198outputx : 4199 _gmic_s="$?" v + _$0 $* 4200 4201_outputx : 4202 $=arg 4203 is_last_arg=0 is_same_location=0 4204 if isnum($-1) is_last_arg={isint($-1)" && "$-1>=0" && "$-1<=1} is_same_location=$-1 fi 4205 N={$#-$is_last_arg} s0= s1=s 4206 if !$N e[0--3] "Output image"$_gmic_s" at same location, with same base filename but extension '' 4207 (skipped, no extension provided)." return 4208 fi 4209 if $is_same_location 4210 if $is_last_arg 4211 e[0--4] "Output image"$_gmic_s" at same location, with same base filename but extension"${s{$N>1}}"' ${^-1}'." 4212 else 4213 e[0--4] "Output image"$_gmic_s" at same location, with same base filename but extension"${s{$N>1}}" '$*'." 4214 fi 4215 repeat $! l[$>] 4216 repeat $N ext=${arg{1+$>}} if ext=lowercase(['$ext']);ext=='jpg'||ext=='jpeg' ext.=,85 fi o {0,f}{0,b}.$ext done 4217 endl done 4218 else 4219 if $is_last_arg e[0--4] "Output image"$_gmic_s" with same base filename but extension"${s{$N>1}}"' ${^-1}'." 4220 else e[0--4] "Output image"$_gmic_s" with same base filename but extension"${s{$N>1}}" '$*'." 4221 fi 4222 repeat $! l[$>] 4223 repeat $N ext=${arg{1+$>}} if ext=lowercase(['$ext']);ext=='jpg'||ext=='jpeg' ext.=,85 fi o {0,b}.$ext done 4224 endl done 4225 fi 4226 4227#@cli parse_cli : _output_mode,_{ * | command_name } 4228#@cli : Parse definition of '#@cli'-documented commands and output info about them in specified output mode. 4229#@cli : 'output_mode' can be { ascii | bashcompletion | html | images | print }. 4230#@cli : Default values: 'output_mode=print' and 'command_name=*'. 4231parse_cli : skip "${1=print},${2=*}" 4232 e[^-1] "Parse '#@cli' command(s) '$2' and output in '$1' mode." 4233 4234 # Check that specified output mode is actually implemented. 4235 l[] ({'$$parse_cli_$1'}) rm 4236 onfail error[0--2] "Command 'parse_cli': Invalid output mode '$1'." 4237 endl 4238 4239 if !$! l[] it ${_path_rc}update$_version.gmic onfail endl fi 4240 if !$! return fi 4241 i[0] ('\n') y a y 4242 merge_multiline_comments 4243 4244 # Split commands/section into different blocs. 4245 eval " 4246 for (p = 0, p<h, 4247 4248 # Find next occurrence of line starting with '#@cli'. 4249 q = find(#0,'\n#@cli',p); 4250 q<0?(copy(i[p],0,h - p,1,0); break()); 4251 for (r = q + 6, r<h && (c=i[r])<=_' ' && c!=_'\n', ++r); 4252 r>=h || i[r]=='\n'?(copy(i[p],0,r - p,1,0); p = r; continue()); 4253 4254 (i[r]==_':' && i[r + 1]==_':')?( # Category 4255 r = find(#0,_'\n',r)%h; 4256 4257 ):i[r]!=_':'?do( # Command 4258 r = find(#0,_'\n',r)%h; 4259 crop(0,r,1,6)=='\n#@cli'?( 4260 for (s = r + 6, s<h && (c=i[s])<=_' ' && c!='_\n', ++s); 4261 s<h && i[s]==':' && i[s + 1]!=':'?(r = s):break(); 4262 ):break(),1 4263 4264 ):( # Unexpected '#@cli' line -> Display warning 4265 r = find(#0,_'\n',r)%h; 4266 ref(vector1024(),line); 4267 copy(line,i[q + 1],min(size(line),r - q - 1)); 4268 run('warn[0--3] \"Unexpected line: \'',line,'\'.\"'); 4269 copy(i[p],0,r - p,1,0); p = r; continue() 4270 ); 4271 copy(i[p],0,q - p + 1,1,0); # Set values to discard 4272 p = r)" 4273 s -,0 4274 4275 # Keep only command blocs and name them. 4276 if $! 4277 $!,1,1,1,"> 4278 begin( 4279 ref(vector1024(),command); 4280 ref(vector1024(),category); 4281 ); 4282 for (p = 5, p<h#x && (c=i[#x,p])<=_' ' && c!=_'\n', ++p); 4283 p>=h#x || i[#x,p]==_'\n'?(run('nm[',x,'] __to_discard__'); break()); 4284 4285 i[#x,p]==_':' && i[#x,p + 1]==_':'?( # Category 4286 for (p+=2, i[#x,p]<=_' ', ++p); 4287 for (q = h#x - 1, i[#x,q]<=_' ', --q); 4288 copy(category,i[#x,p],l = min(q - p + 1,size(category) - 1)); 4289 category[l] = 0; 4290 run('nm[',x,'] __to_discard__'); 4291 ):( # Command 4292 for (q = p, q<h#x && (c=i[#x,q])!=_':' && c>_' ', ++q); 4293 copy(command,i[#x,p],l = min(q - p,size(command) - 1)); 4294 command[l] = 0; 4295 run('nm[',x,'] \"',string(command,'@',category),'\"'); 4296 )" 4297 rm. rmn __to_discard__ 4298 l parse_cli_trigger_$1 $2 onfail endl 4299 fi 4300 parse_cli_$1 4301 4302# Return 1 if last of the selected bloc describes a shortcut command, 0 otherwise. 4303parse_cli_is_eqto : 4304 nbl={"n = 1; for (p = 0, (q = find(#-1,_'\n',p))>=0, ++n, p = ++q); n"} 4305 u {$nbl"==1 && find(#-1,'eq. to \'')>=0"} 4306 4307# 4308# Implements 'bashcompletion' mode for command 'parse_cli'. 4309# 4310parse_cli_bashcompletion : 4311 v 0 use_vt100 4312 sort_list +,n 4313 +e[] "#"\n\ 4314"# Bash completion rules for 'gmic'."\n\ 4315"#"\n\ 4316"# This file has been generated automatically."\n\ 4317"# Do not edit!"\n\ 4318"#"\n\ 4319"# This file should be copied/renamed in '/usr/share/bash-completion/completions/gmic'."\n\ 4320"#"\n\n\ 4321"_gmic()"\n\ 4322"{"\n\ 4323" local cur prev opts coms"\n\ 4324" if type -t _init_completion >/dev/null; then"\n\ 4325" _init_completion -n = || return"\n\ 4326" else"\n\ 4327" COMPREPLY=()"\n\ 4328" cur=\"${COMP_WORDS[COMP_CWORD]}\""\n\ 4329" prev=\"${COMP_WORDS[COMP_CWORD-1]}\""\n\ 4330" fi" 4331 coms=" coms=\"" c= 4332 4333 # Extract list of available commands. 4334 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4335 ('{n}') l. s -,{'@'} name={0,t} rm endl nm $name 4336 coms.=$c$name c=" " 4337 endl done 4338 +e[] $coms"\""\n\ 4339" opts=$(echo \"$coms\" | sed \"s: \\([^ ]\\+\\): \\1 -\\1 \\+\\1:g\")"\n 4340 4341 # Duplicate list of arguments for command shortcuts. 4342 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi 4343 name={$>,n} 4344 if ${parse_cli_is_eqto[$>]} 4345 +l[$>] s -,{'"eq. to "'} k. s -,39 eqto={0,t} rm endl 4346 l[$>] pass[$eqto] 0 k. nm $name 4347 onfail 4348 warn[] "Warning: Ignoring shortcut '"$_vt100_c$name$_vt100_m$_vt100_b"', "\ 4349 "links to unknown command '"$_vt100_c$eqto$_vt100_m$_vt100_b"'." 4350 nm __to_discard__ 4351 endl 4352 fi 4353 done 4354 rmn __to_discard__ 4355 4356 # Extract list of arguments. 4357 +e[] " case \"${prev}\" in" 4358 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4359 name={n} 4360 if n=['$name'];"n[0]!=_'_' && find(n,'input') && find(n,'output') && "\ 4361 "n!='i' && n!='o' && n!='m' && n!='it' && n!='ot'" 4362 if s=['$name'];s=='help'||s=='h' 4363 +e[] " \""$name"\" | \"-"$name"\" | \"+"$name"\")" 4364 +e[] " COMPREPLY=( $(compgen -W \"$coms\" -- \"$cur\") ); return 0;;" 4365 else 4366 s -,{'\n'} k[0] discard {'#@cli'} max {'" "'} autocrop {'" "'} 4367 s -,{':'} autocrop {'" "'} rm[0] replace {'" "'},{'_'} 4368 n_args=0 args,c= repeat $! if ['{/{$>,t}}']!='(+)' args.=$c{$>,t} c=" " n_args+=1 fi done 4369 if $n_args==1 args="> "$args fi 4370 if ['$args']!=0 4371 +e[] " \""$name"\" | \"-"$name"\" | \"+"$name"\")" 4372 +e[] " COMPREPLY=( $(compgen -W \""{/{/$args}}"\") ); return 0;;" 4373 fi 4374 fi 4375 rm 0 4376 fi 4377 endl done 4378 4379 +e[] " esac"\n\n\ 4380" COMPREPLY=( $(compgen -W \"$opts\" -- \"$cur\") )"\n\ 4381" if type -t _filedir >/dev/null; then"\n\ 4382" _filedir"\n\ 4383" else"\n\ 4384" comptopt -o filenames 2>/dev/null"\n\ 4385" COMPREPLY=( $(compgen -f -- ${cur}) )"\n\ 4386" fi"\n\ 4387"}"\n\ 4388"complete -F _gmic -o filenames gmic" 4389 rm 4390 4391parse_cli_trigger_bashcompletion : 4392 parse_cli_trigger_print $* 4393 4394# 4395# Implements 'ascii' mode for command 'parse_cli'. 4396# 4397parse_cli_ascii : 4398 use_vt100 4399 if !narg($_shell_cols) _shell_cols={${-shell_cols}-5} fi 4400 category= n_category=0 4401 if !narg($_section) _section=1 fi 4402 4403 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4404 4405 # Detect and display new category. 4406 if !0$_no_categories 4407 ('{n}') l. s -,{'@'} if $!>1 cat={t} fi rm endl 4408 if ['$cat']!=['$category'] 4409 n_category+=1 4410 category=$cat 4411 ('$_section.$n_category." "') ('$category') +f.. {'" "'} +f.. {'-'} a[-4,-3] x a[-2,-1] x 4412 +e[] \n" "$_vt100_r$_vt100_b{-2,t}$_vt100_n 4413 +e[] " "$_vt100_r{t}$_vt100_n 4414 rm[-2,-1] 4415 fi 4416 fi 4417 4418 # Parse command declaration. 4419 s -,{'\n'} discard {'#@cli'} max {'" "'} autocrop {'" "'} 4420 +l[0] 4421 s -,{'": "'} autocrop {'" "'} 4422 name={0,t} rm[0] 4423 is_builtin=0 4424 if $! 4425 is_builtin={"find(#-1,'(+)')>=0"} 4426 if $is_builtin rm. fi 4427 fi 4428 +e[] "\n "$_vt100_m$_vt100_b$name${"s1,s0=\" (+)\", u $s"$is_builtin}:$_vt100_n 4429 repeat $! l[$>] 4430 if ${parse_cli_is_eqto.} 4431 s -,39 eqto={1,t} k[0] 4432 +e[] " "${_vt100_i}"Shortcut for command '"$_vt100_m$_vt100_b$eqto$_vt100_n"'." 4433 else 4434 eqto= 4435 l. _gmd2ascii_cut $_shell_cols,8 if $!>1 i[1--2] ('"\\\\\n "':y) a y fi endl 4436 str=" "{t}${"if "$<" u \" |\" else u \"\" fi"} 4437 +e[] ${_vt100_c}$str$_vt100_n 4438 fi 4439 endl done 4440 rm 4441 endl 4442 rm[0] 4443 4444 # Parse command description. 4445 n_example=0 nl="\n" 4446 repeat $! if {$>,i==_':'} l[$>] 4447 if "h==1 || (h==2 && i[-1,2]==_' ')" rm ('": "':y) fi # Empty description lines 4448 rows {1+(i[1]==_'" "')},100% 4449 if "find(#0,'(eq. to ')>=0" # Found 'Eq. to' description. 4450 +l s -,{'\47'} shortcut={1,t} rm onfail shortcut="(unknown)" rm endl 4451 +e[] $nl" ("${_vt100_i}"equivalent to shortcut command '"$_vt100_m$_vt100_b$shortcut$_vt100_n"')." nl="\n" 4452 elif "find(#0,'Default value:')>=0 || find(#0,'Default values:')>=0" # Found 'Default value(s):' description 4453 if !0$_no_default_values 4454 s +,{':'} 4455 if $!>2" && "h#1==1" && "i("#1")==_':' 4456 i[0] ('$_vt100_b':y) i[2] ('$_vt100_n':y) 4457 fi 4458 a y gmd2ascii $_shell_cols,5 4459 if $!>1 i[1--2] ('"\n "':y) a y fi autocrop {'\n'} 4460 +e[] "\n "{/{t}} nl= 4461 fi 4462 elif i==_'$'" && "i[1]!=_'$' # Found example description 4463 if !0$_no_examples 4464 rows 1,100% autocrop {'" "'} 4465 _gmd2ascii_cut {$_shell_cols-8},7 4466 if $!>1 i[1--2] ('"\\\\\n "':y) a y fi autocrop {'\n'} 4467 example={/{t}} 4468 n_example+=1 4469 if $n_example==1 example_str=${_vt100_b}"Example:"$_vt100_n"\n "[#$n_example] nl="\n" 4470 else example_str=" "[#$n_example] 4471 fi 4472 +e[] $nl" "$example_str" "$_vt100_c$example$_vt100_n nl= 4473 fi 4474 elif i==_'$'" && "i[1]==_'$' # Found link to tutorial page 4475 if !0$_no_tutorial_link 4476 if h==2 4477 url=https://gmic.eu/tutorial/$name 4478 else 4479 rows 2,100 autocrop {'" "'} url={t} 4480 fi 4481 +e[] "\n "${_vt100_b}"Tutorial: "$_vt100_n$_vt100_u$url$_vt100_n nl= 4482 fi 4483 else # Other kind of description line 4484 parse_cli_text_ascii. 4485 if w +e[] $nl{/{t}} nl= fi 4486 fi 4487 4488 endl fi done 4489 rm 0 4490 endl done rm u $eqto 4491 4492parse_cli_text_ascii : 4493 if !narg($_shell_cols) _shell_cols={${-shell_cols}-5} fi 4494 replace_str "\\n","\n" gmd2ascii $_shell_cols,0 4495 4496 # Ensure output text contains no more than two consecutive newlines. 4497 # Also add a 4-chars left margin on each line. 4498 if w 4499 s +,{'\n'} 4500 if {i==_'\n'} rm. fi # Remove last newline. 4501 eval "repeat (l,p, 4502 i(#p)==_'\n'?( 4503 h(#p)>2?resize(#p,1,1,1,1,0) 4504 ):( 4505 resize(#p,1,h#p + 4,1,1,0,0,0,1); 4506 copy(i[#p,0],_' ',4,1,0)) 4507 )" 4508 a y 4509 fi 4510 4511parse_cli_trigger_ascii : 4512 if "['$1']!='*'" 4513 1,$!,1,1," 4514 begin(ref([lowercase(['$1']),_'@'],str)); 4515 ref(lowercase(name(#y)),nm); 4516 !find(nm,str)?y:-1" 4517 discard. -1 if h k[{i}] else rm fi 4518 fi 4519 4520# 4521# Implements 'html' mode for command 'parse_cli'. 4522# 4523parse_cli_html : 4524 v 0 use_vt100 e[] "" 4525 4526 # Sort by categories. 4527# repeat $! ('{$>,n}') l. s +,{'@'} rv a y nm={t} endl rm. nm[$>] $nm done # Rename as 'category@name' 4528# sort_list +,n # Sort by categories 4529# repeat $! ('{$>,n}') l. s +,{'@'} rv a y nm={t} endl rm. nm[$>] $nm done # Rename as 'name@category' 4530 4531 # Generate html page 'List of Commands'. 4532 html="<!DOCTYPE html>"\n\ 4533"<html lang=\"en\">"\n\ 4534" <head>"\n\ 4535" <meta charset=\"utf-8\">"\n\ 4536" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 4537" <link rel=\"stylesheet\" href=\"../highslide/highslide.css\"/>"\n\ 4538" <link rel=\"stylesheet\" href=\"https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css\">"\n\n\ 4539" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 4540"- Reference Documentation</title>"\n\ 4541" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 4542" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 4543" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 4544" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 4545" </head>"\n\n\ 4546" <body>"\n\ 4547" <div id=\"include_header\"></div>"\n\n\ 4548" <div class=\"section_title\"><a href=\"index.html\"><p>Reference</p></a></div><div class=\"section_content\">"\n\n\ 4549" <a name=\"top\"></a>"\n\n\ 4550"<!-- begin_content -->"\n\n\ 4551"<!-- list_of_categories -->"\n 4552 4553 list_categories,c= 4554 category,p_category= n,is_tr,is_table,row=0 4555 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4556 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4557 if ['$category']!=['$p_category'] 4558 strvar $category category_id=${} 4559 if $is_tr 4560 if $n%5" && "$row>1 html.=" <td colspan=\""{5-$n%5}"\"></td>"\n fi 4561 html.=" </tr>"\n is_tr=0 4562 fi 4563 if $is_table html.=" </table><br/>"\n is_table=0 fi 4564 html.="\n <h1 class=\"ref_h1\"><a name=\""$category_id"\"></a>"$category":</h1>"\n\ 4565 " <table class=\"ref_table_category\">"\n 4566 4567 ('$category') replace_str. ",","," lcategory={t} rm. 4568 list_categories.=$c$lcategory c=, 4569 is_table=1 4570 n,row=0 4571 fi 4572 if !${parse_cli_is_eqto.} 4573 is_builtin={"find(#-1,'(+)')>=0"} 4574 if !($n%5) 4575 if $is_tr html.=" </tr>"\n fi 4576 html.=" <tr>"\n 4577 is_tr=1 row+=1 4578 fi 4579 if ['$name']=='index' url_name=_index.html else url_name=$name.html fi 4580 if $is_builtin 4581 html.=" <td><a href=\""$url_name"#top\"><span class=\"gmd_monospace\" >"$name"</span></a></td>"\n 4582 else 4583 html.=" <td><a href=\""$url_name"#top\">"$name"</a></td>"\n 4584 fi 4585 n+=1 4586 fi 4587 p_category=$category 4588 endl done 4589 if $is_tr 4590 if $n%5" && "$row>1 html.=" <td colspan=\""{5-$n%5}"\"></td>"\n fi 4591 html.=" </tr>"\n 4592 fi 4593 if $is_table html.=" </table>"\n fi 4594 4595 # Add 'Shortcuts' category. 4596 html.="\n <h1 class=\"ref_h1\"><a name=\"shortcuts\"></a>Command Shortcuts:</h1>"\n\ 4597 " <table class=\"ref_table_shortcuts\">"\n\ 4598 " <tr style=\"background-color: \#d8dcea;\"><td><b>Shortcut name</b></td><td>"\ 4599 "<b>Equivalent command name</b></td></tr>"\n 4600 4601 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4602 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4603 if ${parse_cli_is_eqto.} 4604 is_builtin={"find(#-1,'(+)')>=0"} 4605 +l s -,{'"eq. to \47"'} k. s -,{'\47'} k[0] autocrop {'" "'} eqto={t} rm endl 4606 ('$name') replace_str. ">",">" replace_str. "<","<" html_name={t} rm. 4607 html.=" <tr><td><a href=\""$eqto.html"#top\"><b>"$html_name"</b></a></td>" 4608 if $is_builtin 4609 html.="<td><a href=\""$eqto.html"#top\"><span class=\"gmd_monospace\">"$eqto"</span></a></td>" 4610 else 4611 html.="<td><a href=\""$eqto.html"#top\">"$eqto"</a></td>" 4612 fi 4613 html.="</tr>"\n 4614 n+=1 4615 fi 4616 endl done 4617 if $is_table html.=" </table>"\n fi 4618 4619 html.=\n\ 4620"<!-- end_content -->"\n\n\ 4621"<!-- ref_navigation_bottom -->"\n\ 4622" </div><div class=\"section_end\"></div>"\n\ 4623" <div id=\"include_footer\"></div>"\n\ 4624" </body>" 4625 ({'$html'}:y) 4626 4627 # Insert TOC for categories. 4628 toc_html=" <h1 class=\"ref_h1\">Categories:</h1><ul>"\n 4629 repeat narg({/$list_categories}) 4630 arg 1+$>,{/$list_categories} category=${} 4631 ('$category') replace_str. ",","," category={t} rm. 4632 strvar $category category_id=${} 4633 toc_html.=" <li><a href=\"#"$category_id"\">"$category"</a></li>"\n 4634 done 4635 toc_html.=" <li><a href=\"#shortcuts\">Command Shortcuts</a></li>"\n 4636 toc_html.=" </ul>" 4637 4638 replace_str. "<!-- list_of_categories -->",$toc_html 4639 ot. list_of_commands.html 4640 if !isfile('index.html') x "ln -fs list_of_commands.html index.html" fi 4641 rm. 4642 4643 # Retrieve full list of commands and discard those starting with '_'. 4644 repeat $! if s=['{$<,n}'];s[0]==_'_' rm[$<] else l[$<] 4645 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4646 is_eqto=${parse_cli_is_eqto.} 4647 if !$is_eqto _is_$name=1 else rm fi 4648 endl fi done 4649 4650 # Generate html page for each command. 4651 repeat $! l[$>] 4652 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4653 e[] "\r > "$_vt100_c[#{1+$>}]$_vt100_n" "{`copy(vector48(_'" "'),['$category" / "$name'])`} 4654 4655 # Find previous and next commands. 4656 if !$> previous= else pass[{$>-1}] 1 ('{n}') discard. {'_c1'} previous={t} rm[-2,-1] fi 4657 if !$< next= else pass[{$>+1}] 1 ('{n}') l. s -,{'@'} next={0,t} rm endl rm. fi 4658 if ['$name']=='index' url_name=_index.html else url_name=$name.html fi 4659 if ['$previous']=='index' url_previous=_index.html else url_previous=$previous.html fi 4660 if ['$next']=='index' url_next=_index.html else url_next=$next.html fi 4661 4662 strvar[] $category category_id=${} 4663 4664 html="<!DOCTYPE html>"\n\ 4665"<html lang=\"en\">"\n\ 4666" <head>"\n\ 4667" <meta charset=\"utf-8\">"\n\ 4668" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 4669" <link rel=\"stylesheet\" href=\"../highslide/highslide.css\"/>"\n\ 4670" <link rel=\"stylesheet\" href=\"https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css\">"\n\n\ 4671" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 4672"- Reference Documentation - "$name"</title>"\n\ 4673" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 4674" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 4675" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 4676" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 4677" <script src=\"../highslide/highslide-full.js\"></script>"\n\ 4678" <script>"\n\ 4679" hs.graphicsDir = '../highslide/graphics/';"\n\ 4680" hs.wrapperClassName = 'wide-border';"\n\ 4681" hs.showCredits = 'false';"\n\ 4682" </script>"\n\ 4683" </head>"\n\n\ 4684" <body>"\n\ 4685" <div id=\"include_header\"></div>"\n\n\ 4686" <div class=\"section_title\"><a href=\"index.html\"><p>Reference</p></a></div>"\ 4687"<div class=\"section_content\" style=\"padding-top: 0;\">"\n\n\ 4688" <a name=\"top\"></a>"\n\n\ 4689"<!-- begin_content -->"\n\n 4690 4691 if !0$_pdf_output 4692 html.=" <table class=\"ref_navigation_top\"><tr><td>"\ 4693"<a href=\"index.html\">Table of Contents</a> ▸ "\ 4694"<a href=\"list_of_commands.html#top\">List of Commands</a> ▸ "\ 4695"<a href=\"list_of_commands.html#"$category_id"\">"$category"</a> ▸ "\ 4696"<a href=\""$url_name"#top\"><samp>"$name"</samp></a></td>" 4697 if narg($previous)" || "narg($next) 4698 html.="<td>" 4699 if narg($previous) html.="<a href=\""$url_previous"#top\">◀ <samp>"$previous"</samp></a>" fi 4700 if narg($previous)" && "narg($next) html.=" | " fi 4701 if narg($next) html.="<a href=\""$url_next"#top\"><samp>"$next"</samp> ▶</a>" fi 4702 html.="</td>"\n 4703 fi 4704 html.=" </tr></table>\n" 4705 4706 else 4707 html.="<img style=\"margin-top: 2em; width: 100%;\" src=\"reference_pdf.png\"/>"\n 4708 fi 4709 4710 # Parse command declaration. 4711 s -,{'\n'} discard {'#@cli'} max {'" "'} autocrop {'" "'} 4712 +l[0] 4713 s -,{'": "'} autocrop {'" "'} rm[0] 4714 is_builtin=0 4715 if $!" && find(#-1,'(+)')>=0" is_builtin=1 rm. fi 4716 if $is_builtin 4717 html.=" <table class=\"ref_h1_builtin\"><tr><td><h1 class=\"ref_h1\" style=\"margin-bottom: 0;\">"\ 4718 $name"</h1></td><td><span class=\"ref_builtin_command\">Built-in command</span></td></tr></table>"\n 4719 else 4720 html.=" <h1 class=\"ref_h1\">"$name"</h1>"\n 4721 fi 4722 if $! 4723 html.="\n <h2>Arguments:</h2>\n <ul>"\n 4724 if $!>1 or=" or" else or= fi 4725 repeat $! l[$>] 4726 if !$< or= fi 4727 html.=" <li><span class=\"gmd_monospace\">"{t}"</span>"$or"</li>"\n 4728 endl done 4729 html.=" </ul>"\n 4730 else 4731 html.="\n <h3>No arguments</h2>"\n 4732 fi 4733 rm 4734 endl 4735 rm[0] 4736 4737 # Parse command description. 4738 html.="\n <h2>Description:</h2>"\n 4739 line=0 4740 n_example=0 4741 nb_examples=0 4742 is_tutorial_tag=0 4743 tutorial_html= 4744 4745 repeat $! if {$>,i==_':'} l[$>] 4746 if "h==1 || (h==2 && i[-1,2]==_' ')" rm ('": "':y) fi # Empty description lines 4747 rows {1+(i[1]==_'" "')},100% 4748 if i==_'$'" && "i[1]!=_'$' nb_examples+=1 fi 4749 endl fi done 4750 4751 repeat $! l[$>] 4752 if "find(#0,'(eq. to ')>=0" 4753 4754 # Found 'Eq. to' description. 4755 +l s -,{'\47'} 4756 replace_str[1] "&","&" 4757 replace_str[1] "<","<" 4758 replace_str[1] ">",">" 4759 shortcut={1,t} 4760 rm 4761 onfail 4762 shortcut="(unknown)" 4763 rm 4764 endl 4765 html.=" <p>(<em>equivalent to shortcut command</em> <span class=\"gmd_monospace\">"$shortcut\ 4766 "</span>).</p>"\n 4767 4768 elif "find(#0,'See also:')>=0" 4769 4770 # Found 'See also:' description. 4771 s +,{':'} autocrop {'" "'} 4772 if $!>2" && "h#1==1" && "i("#1")==_':' 4773 html.="\n <h2>See also:</h2>"\n 4774 rm[0,1] 4775 fi 4776 a y 4777 gmd2html 0 4778 html.=" "{t}\n 4779 4780 elif "find(#0,'Default value:')>=0 || find(#0,'Default values:')>=0" 4781 4782 # Found 'Default value(s):' description 4783 s +,{':'} autocrop {'" "'} 4784 if $!>2" && "h#1==1" && "i("#1")==_':' 4785 html.="\n<h2>Default values:</h2>"\n 4786 rm[0,1] 4787 fi 4788 a y 4789 gmd2html 0 4790 html.="<p style=\"word-wrap:break-word\">"{t}"</p>"\n 4791 4792 elif i==_'$'" && "i[1]!=_'$' 4793 4794 # Found 'Example of use' description. 4795 rows 1,100% autocrop {'" "'} 4796 if !0$_pdf_output 4797 replace_str "image.jpg","<a href=\"image.jpg\" class=\"highslide\" onclick=\"return hs.expand(this)\">"\ 4798 "image.jpg</a>" 4799 fi 4800 example={/{t}} 4801 n_example+=1 4802 if $n_example>1 basename=${name}_$n_example.jpg else basename=${name}.jpg fi 4803 if $n_example==1 4804 if !$is_tutorial_tag html.="<tutorial_tag>" is_tutorial_tag=1 fi 4805 html.="\n <h2>Example"${"if "$nb_examples">1 u s else u \"\" fi"}" of use:</h2>"\n fi 4806 if $nb_examples!=1 html.=" <h3>• Example \#"$n_example"</h3>"\n fi 4807 html.=" <div class=\"gmd_code_block\">$ gmic "$example"</div><br/>"\n 4808 4809 if 0$_pdf_output html.="<div style=\"text-align: center;\">"\n fi 4810 if isfile('img/f_$basename') # Single output image 4811 if !0$_pdf_output 4812 html.=" <span><a href=\"img/"f_$basename"\" class=\"highslide\" onclick=\"return hs.expand(this)\">"\ 4813 "<img class=\"center_image\" src=\"img/"t_$basename"\"/></a>"\ 4814 "<div class=\"highslide-caption\">Command: <b>"$example"</b></div></span>"\n 4815 else 4816 html.="<img style=\"max-width:45%\" src=\"img/"t_$basename"\"/>"\n 4817 fi 4818 elif isfile('img/f0_$basename') # Multiple output images 4819 i=0 4820 html.=" <div class=\"center\">" 4821 for isfile('img/f${i}_$basename') 4822 if !0$_pdf_output 4823 html.=" <span><a href=\"img/"f${i}_$basename"\" class=\"highslide\" "\ 4824 "onclick=\"return hs.expand(this)\">"\ 4825 "<img src=\"img/"t${i}_$basename"\"/></a>"\ 4826 "<div class=\"highslide-caption\">Command: <b>"$example"</b></div></span>"\n 4827 else 4828 html.="<img style=\"max-width:45%\" src=\"img/"t${i}_$basename"\"/>"\n 4829 fi 4830 i+=1 4831 done 4832 html.=" </div>" 4833 fi 4834 if 0$_pdf_output html.="</div>"\n fi 4835 4836 elif i==_'$'" && "i[1]==_'$' 4837 4838 # Found link to tutorial page. 4839 if !$is_tutorial_tag html.="<tutorial_tag>" is_tutorial_tag=1 fi 4840 if h==2 4841 url=https://gmic.eu/tutorial/$name 4842 l[] it $url if "find(#-1,'404 Not Found')>=0" url=https://gmic.eu/oldtutorial/_$name fi rm endl 4843 else 4844 rows 2,100 autocrop {'" "'} url={t} 4845 fi 4846 4847 tutorial_html.=" <p>This command has a <span class=\"ref_tutorial_button\"><a href=\""$url"\">"\ 4848 "tutorial page</a></span>.</p>" 4849 else 4850 4851 # Other kind of description line 4852 +autocrop {"' '"} is_list={isin(i,_'*',_'-',_'.')} rm. 4853 ('\n') a y 4854 replace_str "\\n","\n" gmd2html 0 4855 if $line==1" && "!$is_list html.=" <br/>"\n fi 4856 html.={t} 4857 if i[-1,2]!=_'\n' html.="\n" fi 4858 line+=1 4859 fi 4860 endl done 4861 4862 # Generate page. 4863 html.=\n\ 4864"<!-- end_content -->"\n\n\ 4865"<!-- ref_navigation_bottom -->"\n\ 4866" </div><div class=\"section_end\"></div>"\n\ 4867" <div id=\"include_footer\"></div>"\n\ 4868" </body>" 4869 rm ({'$html'}:y) 4870 replace_str. "<tutorial_tag>",$tutorial_html # Insert tutorial button 4871 nm $name ot $url_name 4872 endl done 4873 rm 4874 e[] "\r > "${_vt100_g}{`copy(vector64(_'" "'),'"Parsing done!"')`}$_vt100_n 4875 4876parse_cli_trigger_html : 4877 parse_cli_trigger_print $* 4878 4879# 4880# Implements 'image' mode for command 'parse_cli'. 4881# 4882parse_cli_images : 4883 v 0 use_vt100 e[] "" 4884 old_category,category= n_category,n_example=0 4885 if !isfile('image.jpg') l[] sp bottles,640 onfail testimage2d 500 endl o. image.jpg rm. fi 4886 n_global=0 4887 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4888 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4889 4890 if ['$category']!=['$old_category'] 4891 n_category+=1 4892 e[] $_vt100_r"\n ** Section \#"$n_category": "$category"."$_vt100_n"\n" 4893 fi 4894 s -,{'\n'} discard {'#@cli'} max {'" "'} autocrop {'" "'} 4895 n_example=0 4896 4897 repeat $! l[$>] 4898 if "i==_':' && ( 4899 for (p = 1, p<h && i[p]<=_' ', ++p); 4900 i[p]==_'$' && i[p+1]!=_'$')" 4901 4902 s +,{'$'} rm[0,1] a y autocrop {'" "'} example={/{t}} 4903 n_example+=1 4904 n_global+=1 4905 if $n_example>1 4906 basename=${name}_$n_example.jpg 4907 else 4908 basename=${name}.jpg 4909 fi 4910 e[] $_vt100_c[$n_global]$_vt100_n" Command '"$_vt100_g$name$_vt100_n"': $ "$example 4911 skip_rendering={"['"$name"'][0]==_'_' || "\ 4912 "(isfile(['"{/${_parse_cli_images_path}f_$basename}"']) &&"\ 4913 " isfile(['"{/${_parse_cli_images_path}t_$basename}"'])) || "\ 4914 "(isfile(['"{/${_parse_cli_images_path}f0_$basename}"']) && "\ 4915 "isfile(['"{/${_parse_cli_images_path}t0_$basename}"']))"} 4916 4917 if !$skip_rendering # Generate picture only if the file doesn't yet exist 4918 m "run_example : "$example 4919 l[] 4920 reset etime=$| 4921 run_example 4922 etime="done in "$_vt100_n{_round($|-$etime,0.01)}"s"$_vt100_m 4923 _parse_cli_images 4924 if $! 4925 if $!>1 repeat $! o[$>] ${_parse_cli_images_path}f$>_$basename,85 done 4926 else o ${_parse_cli_images_path}f_$basename,85 fi 4927 rr2d 480,320,0,2 4928 if $!>1 repeat $! o[$>] ${_parse_cli_images_path}t$>_$basename,75 done 4929 else o ${_parse_cli_images_path}t_$basename,75 fi 4930 rm 4931 fi 4932 onfail 4933 rm gui_error_preview "Unable to generate preview image" 4934 o ${_parse_cli_images_path}f_$basename,85 4935 rr2d 480,320,0,2 4936 o ${_parse_cli_images_path}t_$basename,75 4937 rm 4938 etime="failed" 4939 endl 4940 um run_example 4941 else etime="skipped" 4942 fi 4943 e[] "\r"$_vt100_c[$n_global]$_vt100_n" Command '"$_vt100_g$name$_vt100_n"': $ "\ 4944 $example" "${_vt100_m}"("$etime")."$_vt100_n 4945 fi 4946 endl done 4947 old_category=$category 4948 rm 0 4949 endl done rm 4950 4951# Generate a single image from a list of images, for the reference documentation. 4952_parse_cli_images : 4953 if !$! rm return fi 4954 W,H={[640,480]} 4955 4956 repeat $! l[$>] nm={n} 4957 label=[$>]:" "'$nm' 4958 if ${-is_3d} # 3D vector object 4959 label2="("{i[6]}" vert., "{i[7]}" prim.)" 4960 r3d 1,1,0,-80 r3d 0,1,0,80 snapshot3d {max($W,$H)} 4961 else # Regular 1D,2D or 3D image 4962 label2="("{w}x{h}x{d}x{s}")" 4963 r 100%,100%,100%,3,{s==1?1:0} 4964 if d>1 # Volumetric image -> Render as a 2D image 4965 +slices 50% 4966 +z[0] 50%,0,0,50%,100%,100% permute. zyxc 4967 +z[0] 0,50%,0,100%,50%,100% permute. xzyc 4968 rr2d... $W,$H,0,2 4969 r2dy.. {-3,h},1 4970 r2dx. {-3,w},1 4971 s={min(w#-2,h)} 4972 if $s>64 projections3d[0] 50%,50%,50%,1 mv[0] $! r3d. 1,1,0,-80 r3d. 0,1,0,80 snapshot3d. $s 4973 else rm[0] 0 4974 fi 4975 4976 eW,eH={[w#0+w#1,h#0+h#2]} 4977 if $eW>$W" || "$eH>$H fact={min($W/$eW,$H/$eH)*100} r $fact%,$fact%,1,100%,2 fi 4978 n 0,255 4979 4980 fs={0,max(w,h)*7%} 4981 if {0,h>1.5*$fs} to[0] XY,4,2,$fs fi 4982 if {1,h>1.5*$fs} to[1] XZ,4,2,$fs fi 4983 if {2,h>1.5*$fs} to[2] YZ,4,2,$fs fi 4984 if w to[3] 3D,4,2,$fs frame[3] 1,1,200 fi 4985 frame[0-2] 1,1,200 4986 a[0,1] x a[1,2] x a y 4987 fi 4988 fi 4989 4990 if w>5*h r $W,{$H/3},1,100%,1 4991 elif h>5*w r {$W/3},$H,1,100%,1 4992 else rr2d $W,$H,0,{w<$W&&h<$H?1:2} 4993 fi 4994 n 0,255 4995 4996 r {[w,h]+2},1,100%,0,0,0.5,0.5 4997 - 245 r {[w+10,h+5]},1,100%,0,0,0.5,0.5 r 100%,{h+1},1,100%,0,0,0,1 + 245 4998 4999 0 t. $label" "$label2,5,0,32,1,1 5000 if w>w#0" || "h>h#0 5001 rm. 0 t. $label\n$label2,5,0,32,1,1 5002 if w>w#0" || "h>h#0 rr2d. {0,[w,h]},0,2 fi 5003 fi 5004 *. -1 n. 0,255 to_rgb. 5005 - 245 a y,0.5 + 245 5006 5007 endl done 5008 c 0,255 5009 5010parse_cli_trigger_images : 5011 parse_cli_trigger_print $* 5012 5013# 5014# Implements 'list' mode for command 'parse_cli'. 5015# (return a list of all commands, separated by commas). 5016# 5017parse_cli_list : 5018 res= 5019 repeat $! ('{$>,n}') l. s -,{'@'} res.=$c{0,t} c=, rm endl done 5020 rm u $res 5021 5022# 5023# Implements 'print' mode for command 'parse_cli'. 5024# 5025parse_cli_print : 5026 v 0 e[] "" 5027 sort_list +,n 5028 repeat $! l[$>] 5029 ('{n}') l. s -,{'@'} name={0,t} rm endl 5030 +e[] $name 5031 endl done rm 5032 5033parse_cli_trigger_print : 5034 if "['$1']!='*'" 5035 1,$!,1,1," 5036 begin(ref(lowercase(['$1']),str)); 5037 ref(lowercase(name(#y)),nm); 5038 arobace = find(nm,_'@'); 5039 inrange(find(nm,str),0,arobace - 1)?y:-1" 5040 discard. -1 k[{^}] 5041 fi 5042 5043#@cli parse_gmd 5044#@cli : Parse and tokenize selected images, viewed as text strings formatted with the G'MIC markdown syntax. 5045parse_gmd : 5046 e[^-1] "Parse and tokenize images$? viewed as text strings formatted with the G\47MIC markdown syntax." 5047 y 1 a[^-1] .,y rm. 5048 eval[^] ">"${-_gmd_tokens}" 5049 begin( 5050 section = subsection = subsubsection = subsubsubsection = anchor = 5051 bullet = subbullet = subsubbullet = center = right = table = blockquote = detail_block = code_block = 5052 shell = bold_italic_a = bold_italic_u = bold_a = bold_u = italic_a = italic_u = strikethrough = underline = 5053 monospace = value_set = word_highlight = url = page_link = text_link1 = text_link2 = img1 = img2 = pipeline = 5054 formula = opening_offset = -1; 5055 5056 blank(c) = isin(c,_' ',_'\n',s_whitespace,s_tab,0); 5057 semiblank(c) = isin(c,_' ',_'\n',_'.',_',',_';',_':',_'!',_'?', 5058 _')',_'(',_'[',_']',_'|',_'-',s_whitespace,s_tab,0); 5059 newline(c) = isin(c,_'\n',0); 5060 reset(c) = (#c = -1); 5061 res = crop(); 5062 ); 5063 5064 pc = j[-1]; c = i; nc = j[1]; ac = j[2]; 5065 ym1 = y - 1; y1 = y + 1; y2 = y + 2; 5066 linestart = newline(pc); 5067 5068 is_raw = max(blockquote,code_block,shell,monospace,url,page_link,text_link2,img2,pipeline,formula)>=0; 5069 non_escaped = is_raw || (pc!=_'\\'); 5070 5071 # Manage document layout. 5072 #------------------------ 5073 5074 # Escaped character. 5075 !non_escaped && 5076 isin(c,_'%',_'$',_'\\',_'\'',_'`',_'*',_'_',_'{',_'}',_'[',_']',_'<',_'>',_'(',_')',_'#',_'+',_'-',_'.',_'!')?( 5077 res[ym1] = i[ym1] = 0; 5078 ): 5079 5080 # Section: '# Section name'. 5081 linestart && c==_'#' && nc==_' '?( # Opening 5082 section = y; 5083 ): 5084 section>=0 && newline(c)?( # Closing 5085 opening_offset = section; 5086 res[section++] = s_section; 5087 while (blank(res[section]), res[section++] = 0); # Remove leading whitespaces 5088 res[y] = e_section; 5089 for (p = opening_offset - 1, p>=0 && res[p]==_'\n', res[p--] = 0); # Remove newlines preceding 5090 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 5091 for (p = y1, p<size(res) && blank(res[p]), res[p++] = 0); # Remove newlines following 5092 ): 5093 5094 # Subsection: '## Subsection name'. 5095 linestart && c==_'#' && nc==c && ac==_' '?( # Opening 5096 subsection = y; 5097 ): 5098 subsection>=0 && newline(c)?( # Closing 5099 opening_offset = subsection; 5100 res[subsection++] = s_subsection; res[subsection++] = 0; 5101 while (blank(res[subsection]), res[subsection++] = 0); # Remove leading whitespaces 5102 res[y] = e_subsection; 5103 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 5104 for (p = y1, p<size(res) && res[p] && blank(res[p]), res[p] = 0); # Remove newlines following 5105 ): 5106 5107 # Subsubsection: '### Subsubsection name'. 5108 linestart && c==_'#' && nc==c && ac==c && j[3]==_' '?( # Opening 5109 subsubsection = y; 5110 ): 5111 subsubsection>=0 && newline(c)?( # Closing 5112 opening_offset = subsubsection; 5113 res[subsubsection++] = s_subsubsection; copy(res[subsubsection],0,2,1,0); subsubsection+=2; 5114 while (blank(res[subsubsection]), res[subsubsection++] = 0); # Remove leading whitespaces 5115 res[y] = e_subsubsection; 5116 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 5117 for (p = y1, p<size(res) && res[p] && blank(res[p]), res[p] = 0); # Remove newlines following 5118 ): 5119 5120 # Subsubsubsection: '#### Subsubsubsection name'. 5121 linestart && c==_'#' && nc==c && ac==c && j[3]==c && j[4]==_' '?( # Opening 5122 subsubsubsection = y; 5123 ): 5124 subsubsubsection>=0 && newline(c)?( # Closing 5125 opening_offset = subsubsubsection; 5126 res[subsubsubsection++] = s_subsubsubsection; copy(res[subsubsubsection],0,3,1,0); subsubsubsection+=3; 5127 while (blank(res[subsubsubsection]), res[subsubsubsection++] = 0); # Remove leading whitespaces 5128 res[y] = e_subsubsubsection; 5129 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 5130 for (p = y1, p<size(res) && res[p] && blank(res[p]), res[p] = 0); # Remove blanks following 5131 ): 5132 5133 # Anchor: '= Anchor name'. 5134 linestart && c==_'=' && nc==_' '?( # Opening 5135 anchor = y; 5136 ): 5137 anchor>=0 && newline(c)?( # Closing 5138 opening_offset = anchor; 5139 res[anchor++] = s_anchor; 5140 while (blank(res[anchor]), res[anchor++] = 0); # Remove leading whitespaces 5141 res[y] = e_anchor; 5142 res[y1]==_'\n'?(res[y1] = 0); 5143 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 5144 ): 5145 5146 # List bullet: '* List item'. 5147 linestart && isin(c,_'-',_'*',_'+') && nc==_' ' && bullet<0?( # Opening 5148 bullet = y; 5149 ): 5150 bullet>=0 && newline(c)?( # Closing 5151 opening_offset = bullet; 5152 res[bullet++] = s_bullet; res[bullet] = 0; 5153 res[y] = e_bullet; 5154 ): 5155 5156 # Sublist bullet: ' * Sub-list item'. 5157 linestart && c==_' ' && nc==_' ' && isin(ac,_'-',_'*',_'+') && j[3]==_' ' && subbullet<0?( # Opening 5158 subbullet = y; 5159 ): 5160 subbullet>=0 && newline(c)?( # Closing 5161 opening_offset = subbullet; 5162 res[subbullet++] = s_subbullet; copy(res[subbullet],0,2,1,0); 5163 res[y] = e_subbullet; 5164 ): 5165 5166 # Subsublist bullet: ' * Subsub-list item'. 5167 linestart && c==_' ' && nc==_' ' && ac==_' ' && j[3]==_' ' && isin(j[4],_'-',_'*',_'+') && j[5]==_' ' && 5168 subsubbullet<0?( # Opening 5169 subsubbullet = y; 5170 ): 5171 subsubbullet>=0 && newline(c)?( # Closing 5172 opening_offset = subsubbullet; 5173 res[subsubbullet++] = s_subsubbullet; copy(res[subsubbullet],0,4,1,0); 5174 res[y] = e_subsubbullet; 5175 ): 5176 5177 # Centered block: '\n===\n Centered text\n===\n'. 5178 linestart && c==_'=' && nc==c && ac==c && newline(j[3])?( 5179 center<0?( # Opening 5180 center = y; 5181 ): 5182 center>=0 && y>center + 3?( # Closing 5183 opening_offset = center; 5184 res[center++] = s_center; copy(res[center],0,3,1,0); center+=3; 5185 newline(res[ym1])?(res[ym1] = 0); 5186 res[y] = e_center; copy(res[y + 1],0,3,1,0); 5187 ); 5188 ): 5189 5190 # Right block: '\n>>>\n Right-aligned text\n>>>\n'. 5191 linestart && c==_'>' && nc==c && ac==c && newline(j[3])?( 5192 right<0?( # Opening 5193 right = y; 5194 ): 5195 right>=0 && y>right + 3?( # Closing 5196 opening_offset = right; 5197 res[right++] = s_right; copy(res[right],0,3,1,0); right+=3; 5198 newline(res[ym1])?(res[ym1] = 0); 5199 res[y] = e_right; copy(res[y + 1],0,3,1,0); 5200 ); 5201 ): 5202 5203 # Table : '\n| foo | bar\n' (with first delimiter '||', '|+' or '|-'). 5204 table<0 && linestart && c==_'|'?( # Opening 5205 table = y; 5206 ): 5207 table>=0 && newline(c) && nc!=_'|'?( # Closing 5208 opening_offset = table; 5209 d = i[table + 1]; 5210 d==_'|'?(res[table++] = s_htable; res[table++] = 0): 5211 d==_'-'?(res[table++] = s_vtable; res[table++] = 0): 5212 d==_'+'?(res[table++] = s_hvtable; res[table++] = 0):(res[table++] = s_table); 5213 5214 i[table]==_' '?(res[table++] = 0); 5215 newline(i[table]) && i[table + 1]==_'|'?(copy(res[table],0,2,1,0); table+=2); 5216 for (p = table, p<y, ++p, # Find column / line separators inside table 5217 i[p]==_'|'?( 5218 res[p] = newline(i[p - 1]) || newline(i[p + 1])?0:m_table; 5219 i[p - 1]==_' '?(res[p - 1] = 0); 5220 i[p + 1]==_' '?(res[p + 1] = 0); 5221 ):newline(i[p])?( 5222 res[p] = n_table; 5223 ); 5224 ); 5225 res[y] = e_table; 5226 ): 5227 5228 # Blockquote : '\n> line1\n> line2'. 5229 code_block<0 && blockquote<0 && linestart && c==_'>' && blank(nc)?( # Opening 5230 blockquote = y; 5231 ): 5232 blockquote>=0 && newline(c) && (nc!=_'>' || !blank(ac))?( # Closing 5233 opening_offset = blockquote; 5234 res[blockquote++] = s_blockquote; res[blockquote] = 0; 5235 # Remove leading '>' when multi-lines: 5236 for (p = blockquote, p<y, ++p, newline(res[p - 1]) && res[p]==_'>'?copy(res[p],0,res[p + 1]==_' '?2:1,1,0)); 5237 res[y] = e_blockquote; 5238 ): 5239 5240 # Detail block: '\n??? Details:\nDetail block\n???\n'. 5241 linestart && c==_'?' && nc==c && ac==c && blank(j[3])?( 5242 detail_block<0?( # Opening 5243 detail_block = y; 5244 ): 5245 detail_block>=0 && y>detail_block + 3 && newline(j[3])?( # Closing 5246 opening_offset = detail_block; 5247 res[detail_block++] = s_detail_block; copy(res[detail_block],0,2,1,0); 5248 res[ym1] = e_detail_block; copy(res[y],0,4,1,0); 5249 ); 5250 ): 5251 5252 # Code block: '\n~~~\n Code block\n~~~\n'. 5253 linestart && isin(c,_'~','`') && nc==c && ac==c && newline(j[3])?( 5254 code_block<0?( # Opening 5255 code_block = y; 5256 ): 5257 code_block>=0 && y>code_block + 3?( # Closing 5258 opening_offset = code_block; 5259 res[code_block++] = s_code_block; copy(res[code_block],0,3,1,0); code_block+=3; 5260 copy(res[code_block],i[code_block],y - code_block); # Cancel tokens found inside 5261 for (p = code_block, p<y, ++p, res[p]==_' '?(res[p] = s_whitespace)); # Keep leading whitespaces. 5262 res[ym1] = e_code_block; copy(res[y],0,4,1,0); 5263 ); 5264 ): 5265 5266 # Shell command: '\n"""\n Shell command\n"""\n'. 5267 linestart && c==_'\"' && nc==c && ac==c && newline(j[3])?( 5268 shell<0?( # Opening 5269 shell = y; 5270 ): 5271 shell>=0 && y>shell + 3?( # Closing 5272 opening_offset = shell; 5273 res[shell++] = s_shell; copy(res[shell],0,3,1,0); shell+=3; 5274 copy(res[shell],i[shell],y - shell); # Cancel tokens found inside 5275 res[ym1] = e_shell; copy(res[y],0,4,1,0); 5276 ); 5277 ): 5278 5279 # Horizontal rule: '---', '___' or '***'. 5280 linestart && isin(c,_'-','_','*') && nc==c && ac==c && newline(j[3])?( 5281 res[y] = s_hrule; 5282 copy(res[y1],0,3,1,0); 5283 ): 5284 5285 # Manage text style. 5286 #------------------- 5287 5288 # Bold italic (asterisk): '***bold italic text***'. 5289 non_escaped && c==_'*' && nc==c && ac==c?( # Opening 5290 bold_italic_a<0?( 5291 bold_italic_a = y; 5292 ): 5293 bold_italic_a>=0 && y>bold_italic_a + 3 && j[3]!=_'*'?( # Closing 5294 opening_offset = bold_italic_a; 5295 res[bold_italic_a++] = s_bold_italic_a; res[bold_italic_a++] = 0; res[bold_italic_a] = 0; 5296 res[y] = e_bold_italic_a; res[y1] = res[y2] = 0; 5297 ); 5298 ): 5299 5300 # Bold italic (underscore): '___bold italic text___'. 5301 non_escaped && c==_'_' && nc==c && ac==c?( 5302 bold_italic_u<0 && semiblank(pc)?( # Opening 5303 bold_italic_u = y; 5304 ): 5305 bold_italic_u>=0 && y>bold_italic_u + 3 && semiblank(j[3])?( # Closing 5306 opening_offset = bold_italic_u; 5307 res[bold_italic_u++] = s_bold_italic_u; res[bold_italic_u++] = 0; res[bold_italic_u] = 0; 5308 res[y] = e_bold_italic_u; res[y1] = res[y2] = 0; 5309 ); 5310 ): 5311 5312 # Bold (asterisk): '**bold text**'. 5313 non_escaped && c==_'*' && nc==c?( # Opening 5314 bold_a<0?( 5315 bold_a = y; 5316 ): 5317 bold_a>=0 && y>bold_a + 2 && ac!=_'*'?( # Closing 5318 opening_offset = bold_a; 5319 res[bold_a++] = s_bold_a; res[bold_a] = 0; 5320 res[y] = e_bold_a; res[y1] = 0; 5321 ); 5322 ): 5323 5324 # Bold (underscore): '__bold text__'. 5325 non_escaped && c==_'_' && nc==c?( 5326 bold_u<0 && semiblank(pc)?( # Opening 5327 bold_u = y; 5328 ): 5329 bold_u>=0 && y>bold_u + 2 && semiblank(ac)?( # Closing 5330 opening_offset = bold_u; 5331 res[bold_u++] = s_bold_u; res[bold_u] = 0; 5332 res[y] = e_bold_u; res[y1] = 0; 5333 ); 5334 ): 5335 5336 # Italic (asterisk): '*italic text*'. 5337 non_escaped && c==_'*' && pc!=c?( # Opening 5338 italic_a<0?( 5339 italic_a = y; 5340 ): 5341 italic_a>=0 && y>italic_a + 1 && ac!=_'*'?( # Closing 5342 opening_offset = italic_a; 5343 res[italic_a] = s_italic_a; 5344 res[y] = e_italic_a; 5345 ); 5346 ): 5347 5348 # Italic (underscore): '_italic text_'. 5349 non_escaped && c==_'_' && pc!=c?( 5350 italic_u<0 && semiblank(pc)?( # Opening 5351 italic_u = y 5352 ): 5353 italic_u>=0 && y>italic_u + 1 && semiblank(nc)?( # Closing 5354 opening_offset = italic_u; 5355 res[italic_u] = s_italic_u; 5356 res[y] = e_italic_u; 5357 ); 5358 ): 5359 5360 # Strikethrough: '~~strikethrough text~~'. 5361 non_escaped && c==_'~' && nc==c && pc!=c?( # Opening 5362 strikethrough<0?( 5363 strikethrough = y; 5364 ): 5365 strikethrough>=0 && y>strikethrough + 2?( # Closing 5366 opening_offset = strikethrough; 5367 res[strikethrough++] = s_strikethrough; res[strikethrough] = 0; 5368 res[y] = e_strikethrough; res[y1] = 0; 5369 ); 5370 ): 5371 5372 # Underline: '==strikethrough text=='. 5373 non_escaped && c==_'=' && nc==c && pc!=c?( # Opening 5374 underline<0?( 5375 underline = y; 5376 ): 5377 underline>=0 && y>underline + 2?( # Closing 5378 opening_offset = underline; 5379 res[underline++] = s_underline; res[underline] = 0; 5380 res[y] = e_underline; res[y1] = 0; 5381 ); 5382 ): 5383 5384 # Monospace: '`monospace text`'. 5385 non_escaped && c==_'`'?( 5386 monospace<0?( # Opening 5387 monospace = y; 5388 ): 5389 monospace>=0 && y>monospace + 1?( # Closing 5390 opening_offset = monospace; 5391 res[monospace++] = s_monospace; 5392 copy(res[monospace],i[monospace],y - monospace); # Cancel tokens found inside 5393 for (p = monospace, p<y, ++p, res[p]==_' '?(res[p] = s_whitespace)); # Keep leading whitespaces. 5394 res[y] = e_monospace; 5395 ); 5396 ): 5397 5398 # Value Set: '{ value1 | value2 | value3 }'. 5399 non_escaped && c==_'{' && value_set<0 && semiblank(pc)?( # Opening 5400 value_set = y; 5401 ): 5402 non_escaped && c==_'}' && value_set>=0 && y>value_set + 1 && semiblank(nc)?( # Closing 5403 opening_offset = value_set; 5404 res[value_set++] = s_value_set; 5405 copy(res[value_set],i[value_set],y - value_set); # Cancel tokens found inside 5406 res[y] = e_value_set; 5407 ): 5408 5409 # Word highlight: ' 'word_highlight' '. 5410 non_escaped && c=='\'' && nc!=c?( 5411 word_highlight<0 && semiblank(pc)?( # Opening 5412 word_highlight = y; 5413 ): 5414 word_highlight>=0 && y>word_highlight + 1 && semiblank(nc)?( # Closing 5415 opening_offset = word_highlight; 5416 res[word_highlight++] = s_word_highlight; 5417 copy(res[word_highlight],i[word_highlight],y - word_highlight); # Cancel tokens found inside 5418 res[y] = e_word_highlight; 5419 ); 5420 ): 5421 5422 # URL: '<https://url.com>'. 5423 non_escaped && c==_'<' && url<0 && 5424 (crop(0,y1,1,8)=='https://' || crop(0,y1,1,7)=='http://' || crop(0,y1,1,6)=='ftp://')?( # Opening 5425 url = y; 5426 ): 5427 non_escaped && c==_'>' && url>=0 && y>url + 1?( # Closing 5428 opening_offset = url; 5429 res[url++] = s_url; 5430 copy(res[url],i[url],y - url); # Cancel tokens found inside 5431 res[y] = e_url; 5432 ): 5433 5434 # Page link (command or reference): ' ''command or page name'' ' (not a URL!). 5435 non_escaped && c==_'\'' && nc==c?( 5436 page_link<0 && semiblank(pc)?( # Opening 5437 page_link = y; 5438 ): 5439 page_link>=0 && y>page_link + 2 && semiblank(ac)?( # Closing 5440 opening_offset = page_link; 5441 res[page_link++] = s_page_link; res[page_link++] = 0; 5442 copy(res[page_link],i[page_link],y - page_link); # Cancel tokens found inside 5443 res[y] = e_page_link; res[y1] = 0; 5444 ); 5445 ): 5446 5447 # Text link: '[link text](https://url.com)'. 5448 non_escaped && c==_'[' && text_link1<0 && text_link2<0 && img1<0?( # Opening 5449 text_link1 = y; 5450 ): 5451 non_escaped && c==_']' && nc==_'(' && text_link1>=0 && text_link2<0 && img1<0?( # Middle 5452 text_link2 = y; 5453 ): 5454 non_escaped && c==_')' && text_link2>=0 && img1<0?( # Closing 5455 opening_offset = text_link1; 5456 res[text_link1] = s_text_link; 5457 res[text_link2++] = m_text_link; res[text_link2++] = 0; 5458 copy(res[text_link2],i[text_link2],y - text_link2); # Cancel tokens found inside 5459 res[y] = e_text_link; 5460 ): 5461 5462 # Image: '![alt caption](https://url.com/image.png)'. 5463 non_escaped && c==_'!' && nc==_'[' && img1<0 && img2<0?( # Opening 5464 img1 = y; 5465 ): 5466 non_escaped && c==_']' && nc==_'(' && img1>=0 && img2<0?( # Middle 5467 img2 = y; 5468 ): 5469 non_escaped && c==_')' && img2>=0?( # Closing 5470 opening_offset = img1; 5471 res[img1++] = s_img; res[img1++] = 0; 5472 res[img2++] = m_img; res[img2++] = 0; 5473 copy(res[img1],i[img1],img2 - img1 - 2); copy(res[img2],i[img2],y - img2); # Cancel tokens found inside 5474 res[y] = e_img; 5475 ): 5476 5477 # G'MIC pipeline (image): '%% G'MIC pipeline %%'. 5478 non_escaped && c==_'%' && nc==c?( 5479 pipeline<0 && semiblank(pc)?( # Opening 5480 pipeline = y; 5481 ): 5482 pipeline>=0 && y>pipeline + 2 && semiblank(ac)?( # Closing 5483 opening_offset = pipeline; 5484 res[pipeline++] = s_pipeline; res[pipeline++] = 0; 5485 copy(res[pipeline],i[pipeline],y - pipeline); # Cancel tokens found inside 5486 while (blank(i[pipeline]), res[pipeline++] = 0); # Remove leading blanks 5487 for (p = ym1, blank(res[p]), res[p--] = 0); # Remove trailing blanks 5488 res[y] = e_pipeline; res[y1] = 0; 5489 ); 5490 ): 5491 5492 # Formula in LaTeX: '$$ x = cos(x + 2) $$`'. 5493 non_escaped && c==_'$' && nc==c?( 5494 formula<0 && semiblank(pc)?( # Opening 5495 formula = y; 5496 ): 5497 formula>=0 && y>formula + 2 && semiblank(ac)?( # Closing 5498 opening_offset = formula; 5499 res[formula++] = s_formula; res[formula++] = 0; 5500 copy(res[formula],i[formula],y - formula); # Cancel tokens found inside 5501 while (blank(i[formula]), res[formula++] = 0); # Remove leading blanks 5502 for (p = ym1, blank(res[p]), res[p--] = 0); # Remove trailing blanks 5503 res[y] = e_formula; res[y1] = 0; 5504 ); 5505 ): 5506 5507 # G'MIC word: '\G'MIC'. 5508 semiblank(pc) && c==_'\\' && nc==_'G' && ac==_'\'' && j[3]==_'M' && j[4]==_'I' && j[5]==_'C' && semiblank(j[6])?( 5509 res[y] = s_gmic; 5510 copy(res[y1],0,4,1,0); 5511 res[y + 5] = e_gmic; 5512 ): 5513 5514 # Whitespaces. 5515 c==_' '?( 5516 5517 # Keep consecutive whitespaces. 5518 c==_' ' && (linestart || pc==c)?( 5519 res[y] = s_whitespace; 5520 ); 5521 5522 # Reset tokens that cannot contain whitespace. 5523 reset(word_highlight); 5524 reset(url); 5525 text_link2>=0?(reset(text_link1); reset(text_link2)); 5526 img2>=0?(reset(img1); reset(img2)); 5527 ): 5528 5529 # Escaped newline. 5530 c==_'\\' && nc==_'n'?( 5531 res[y] = _'\n'; res[y + 1] = 0; 5532 ): 5533 5534 # Tab. 5535 c==_'\t'?( 5536 res[y] = s_tab; 5537 ): 5538 5539 # Newline. 5540 c==_'\n'?( 5541 5542 # Reset tokens that cannot contain newlines. 5543 reset(bold_italic_a); 5544 reset(bold_italic_u); 5545 reset(bold_u); 5546 reset(bold_a); 5547 reset(italic_a); 5548 reset(italic_u); 5549 reset(strikethrough); 5550 reset(underline); 5551 reset(monospace); 5552 reset(word_highlight); 5553 reset(url); 5554 reset(page_link); 5555 text_link2>=0?(reset(text_link1); reset(text_link2)); 5556 img2>=0?(reset(img1); reset(img2)); 5557 ); 5558 5559 # Cancel opened tokens starting after the opening offset of the latest closed token. 5560 #------------------------------------------------------------------------------------ 5561 opening_offset>=0?( 5562 section>=opening_offset ? reset(section); 5563 subsection>=opening_offset ? reset(subsection); 5564 subsubsection>=opening_offset ? reset(subsubsection); 5565 subsubsubsection>=opening_offset ? reset(subsubsubsection); 5566 anchor>=opening_offset ? reset(anchor); 5567 bullet>=opening_offset ? reset(bullet); 5568 subbullet>=opening_offset ? reset(subbullet); 5569 subsubbullet>=opening_offset ? reset(subsubbullet); 5570 center>=opening_offset ? reset(center); 5571 right>=opening_offset ? reset(right); 5572 table>=opening_offset ? reset(table); 5573 blockquote>=opening_offset ? reset(blockquote); 5574 detail_block>=opening_offset ? reset(detail_block); 5575 code_block>=opening_offset? reset(code_block); 5576 shell>=opening_offset? reset(shell); 5577 bold_italic_a>=opening_offset ? reset(bold_italic_a); 5578 bold_italic_u>=opening_offset ? reset(bold_italic_u); 5579 bold_a>=opening_offset ? reset(bold_a); 5580 bold_u>=opening_offset ? reset(bold_u); 5581 italic_a>=opening_offset ? reset(italic_a); 5582 italic_u>=opening_offset ? reset(italic_u); 5583 strikethrough>=opening_offset ? reset(strikethrough); 5584 underline>=opening_offset ? reset(underline); 5585 monospace>=opening_offset ? reset(monospace); 5586 value_set>=opening_offset ? reset(value_set); 5587 word_highlight>=opening_offset ? reset(word_highlight); 5588 url>=opening_offset ? reset(url); 5589 page_link>=opening_offset ? reset(page_link); 5590 text_link1>=opening_offset || text_link2>=opening_offset ? (reset(text_link1); reset(text_link2)); 5591 img1>=opening_offset || img2>=opening_offset ? (reset(img1); reset(img2)); 5592 pipeline>=opening_offset ? reset(pipeline); 5593 formula>=opening_offset ? reset(formula); 5594 opening_offset = -1; 5595 ); 5596 5597 end(copy(i[0],res))" 5598 discard 0 5599 5600#@cli gmd2html : _include_default_header_footer={ 0=none | 1=Reference | 2=Tutorial | 3=News } : (no arg) 5601#@cli : Convert selected gmd-formatted text images to html format. 5602#@cli : Default values: 'include_default_header_footer=1'. 5603gmd2html : skip "${1=}" 5604 l[] is_arg={isint("$1")} onfail is_arg=0 endl 5605 if $is_arg embed_html=$1 else embed_html=1 noarg fi 5606 5607 parse_gmd 5608 s_section,e_section={${-_gmd_tokens}"[s_section,e_section]"} 5609 repeat $! l[$>] nm$>={b} strvar ${nm$>} fnm=${} 5610 if "i=="$s_section" && find(#-1,"$e_section")>0" 5611 +rows 1,{"find(#-1,"$e_section")-1"} title$>={t} rm. 5612 else title$>= 5613 fi 5614 . # [0] = Output, [1] = Input 5615 eval. "> 5616 begin("${-_gmd_tokens}${-_gmd_write}"); 5617 c = i; 5618 c>0?( 5619 c==_'\n' ? write('<br/>\n'): 5620 c==_'&' ? write('&'): 5621 c==_'\47' ? write('''): 5622 c==_'>' ? write('>'): 5623 c==_'\"' ? write('"'): 5624 c==_'<' ? write('<'): 5625 write(c); 5626 ):( 5627 isin(c,e_bold_a,e_bold_u,e_bold_italic_a,e_bold_italic_u,e_italic_a,e_italic_u, 5628 e_monospace,e_strikethrough,e_underline,e_word_highlight) ? write('</span>'): 5629 isin(c,e_bullet,e_subbullet,e_subsubbullet) ? write('</div>\n'): 5630 isin(c,e_section,e_subsection,e_subsubsection,e_subsubsubsection) ? write('</div>\n'): 5631 5632 c==s_section ? ( 5633 ind_e = find(#1,e_section,y); 5634 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5635 ref(get('_gmd_name',1024,1),str_nam); 5636 write_nl(); 5637 write('<a name=\"'); 5638 len = find(str_nam,0); 5639 write(str_nam,len); 5640 write('\"></a><div class=\"gmd_section\">'); 5641 ): 5642 c==s_subsection ? ( 5643 ind_e = find(#1,e_subsection,y); 5644 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5645 ref(get('_gmd_name',1024,1),str_nam); 5646 write_nl(); 5647 write('<a name=\"'); 5648 len = find(str_nam,0); 5649 write(str_nam,len); 5650 write('\"></a><div class=\"gmd_subsection\">'); 5651 ): 5652 c==s_subsubsection ? ( 5653 ind_e = find(#1,e_subsubsection,y); 5654 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5655 ref(get('_gmd_name',1024,1),str_nam); 5656 write_nl(); 5657 write('<a name=\"'); 5658 len = find(str_nam,0); 5659 write(str_nam,len); 5660 write('\"></a><div class=\"gmd_subsubsection\">'); 5661 ): 5662 c==s_subsubsubsection ? ( 5663 ind_e = find(#1,e_subsubsubsection,y); 5664 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5665 ref(get('_gmd_name',1024,1),str_nam); 5666 write_nl(); 5667 write('<a name=\"'); 5668 len = find(str_nam,0); 5669 write(str_nam,len); 5670 write('\"></a><div class=\"gmd_subsubsubsection\">'); 5671 ): 5672 c==s_anchor ? ( 5673 ind_e = find(#1,e_anchor,y); 5674 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5675 ref(get('_gmd_name',1024,1),str_nam); 5676 write('<a name=\"'); 5677 len = find(str_nam,0); 5678 write(str_nam,len); 5679 write('\"></a>\n'); 5680 copy(i[y],0,ind_e - y + 1,1,0); 5681 ): 5682 c==s_bullet ? write('<div class=\"gmd_bullet\">'): 5683 c==s_subbullet ? write('<div class=\"gmd_subbullet\">'): 5684 c==s_subsubbullet ? write('<div class=\"gmd_subsubbullet\">'): 5685 c==s_center ? write('<div class=\"gmd_center\">\n'): 5686 c==e_center ? (write_nl(); write('</div>')): 5687 c==s_right ? write('<div class=\"gmd_right\">\n'): 5688 c==e_right ? (write_nl(); write('</div>')): 5689 c==s_table ? (write_nl(); write('<table class=\"gmd_table\">\n<tr><td>')): 5690 c==s_htable ? (write_nl(); write('<table class=\"gmd_htable\">\n<tr><td>')): 5691 c==s_vtable ? (write_nl(); write('<table class=\"gmd_vtable\">\n<tr><td>')): 5692 c==s_hvtable ? (write_nl(); write('<table class=\"gmd_hvtable\">\n<tr><td>')): 5693 c==m_table ? write('</td><td>'): 5694 c==n_table ? write('</td></tr>\n<tr><td>'): 5695 c==e_table ? write('</td></tr>\n</table>\n'): 5696 c==s_blockquote ? (write_nl(); write('<blockquote class=\"gmd_blockquote\">\n')): 5697 c==e_blockquote ? (write('\n</blockquote>\n')): 5698 c==s_detail_block ? ( 5699 write_nl(); 5700 write('<details class=\"gmd_details\">\n<summary>'); 5701 ny = y + 1; 5702 nc = j[1]; 5703 nc!=e_detail_block?( 5704 j[1] = 0; 5705 ind_e = find(#1,e_detail_block,ny); 5706 nc==_' '?( # Has a title 5707 ind_nl = find(#1,_'\n',ny); 5708 ind_nl<0 || ind_nl>ind_e?(ind_nl = ind_e); 5709 write(#1,y + 2,ind_nl - y - 2); 5710 copy(i[ny],0,ind_nl - y - 1,1,0); 5711 i[ind_nl]!=e_detail_block?(i[ind_nl] = 0); 5712 ):write('Details:'); 5713 write('</summary>\n'); 5714 ) 5715 ): 5716 c==e_detail_block ? (write_nl(); write('</details>\n')): 5717 c==s_code_block ? write('<div class=\"gmd_code_block\">'): 5718 c==e_code_block ? write('</div>\n'); 5719 5720 c==s_shell ? ( 5721 ind_e = find(#1,e_shell,y); 5722 run('_gmd2html_shell. ',y + 1,',',ind_e - 1); 5723 ref(get('_gmd_command',1024,1),str_com); 5724 write('<div class=\"gmd_code_block\">$ '); 5725 len = find(str_com,0); 5726 write(str_com,len); 5727 write('<br/><br/>\n'); 5728 write(#-1,0,h(#-1)); 5729 run('rm.'); 5730 write('</div>\n'); 5731 copy(i[y],0,ind_e - y + 1,1,0); 5732 ): 5733 c==s_hrule ? (write_nl(); write('<hr/>\n')): 5734 5735 c==s_bold_italic_a ? write('<span class=\"gmd_bold_italic_a\">'): 5736 c==s_bold_italic_u ? write('<span class=\"gmd_bold_italic_u\">'): 5737 c==s_bold_a ? write('<span class=\"gmd_bold_a\">'): 5738 c==s_bold_u ? write('<span class=\"gmd_bold_u\">'): 5739 c==s_italic_a ? write('<span class=\"gmd_italic_a\">'): 5740 c==s_italic_u ? write('<span class=\"gmd_italic_u\">'): 5741 c==s_strikethrough? write('<span class=\"gmd_strikethrough\">'): 5742 c==s_underline? write('<span class=\"gmd_underline\">'): 5743 c==s_monospace ? write('<span class=\"gmd_monospace\">'): 5744 c==s_value_set ? write('<span class=\"gmd_value_set\">{'): 5745 c==e_value_set ? write('}</span>'): 5746 c==s_word_highlight ? write('<span class=\"gmd_word_highlight\">'): 5747 5748 c==s_url ? ( 5749 ind_e = find(#1,e_url,y); 5750 write('<a href=\"'); 5751 write(#1,y + 1,ind_e - y - 1); 5752 write('\" target=\"_blank\">'); 5753 ): 5754 c==e_url ? write('</a>'): 5755 5756 c==s_page_link ? ( 5757 ind_e = find(#1,e_page_link,y); 5758 run('_gmd2html_page_link. ',y + 1,',',ind_e - 1); 5759 ref(get('_gmd_link',1024,1),str_link); 5760 ref(get('_gmd_text',1024,1),str_text); 5761 write('<span class=\"gmd_page_link\"><a href=\"'); 5762 len = find(str_link,0); 5763 write(str_link,len); 5764 write('\">'); 5765 len = find(str_text,0); 5766 write(str_text,len); 5767 write('</a></span>'); 5768 copy(i[y],0,ind_e - y + 1,1,0); 5769 ): 5770 5771 c==s_text_link ? ( 5772 ind_m = find(#1,m_text_link,y); 5773 ind_e = find(#1,e_text_link,ind_m); 5774 write('<a href=\"'); 5775 write(#1,ind_m + 1,ind_e - ind_m - 1); 5776 i[ind_m + 1]==_'#' || crop(#1,0,ind_m + 1,1,15)=='https://gmic.eu'? 5777 write('\">'): # Local link 5778 write('\" target=\"_blank\">'); 5779 ): 5780 c==m_text_link ? ( 5781 ind_e = find(#1,e_text_link,y); 5782 copy(i[y],0,ind_e - y + 1,1,0); 5783 write('</a>'); 5784 ): 5785 5786 c==s_img ? ( 5787 ind_m = find(#1,m_img,y); 5788 ind_e = find(#1,e_img,ind_m); 5789 ind_d = find(#1,_'.',ind_e - 1,-1); 5790 is_video = 0; 5791 ind_d>ind_m?( # Check for a video 5792 ref(crop(#1,0,ind_d + 1,1,3),ext3); 5793 ref(crop(#1,0,ind_d + 1,1,4),ext4); 5794 is_video = ext3=='mp4' || ext3=='ogg' || ext4=='webm' 5795 ); 5796 is_video?( 5797 write('<video controls loop autoplay muted src=\"'); 5798 write(#1,ind_m + 1,ind_e - ind_m - 1); 5799 write('\">'); 5800 ):( 5801 write('<img class=\"gmd_image\" src=\"'); 5802 write(#1,ind_m + 1,ind_e - ind_m - 1); 5803 write('\" alt=\"'); 5804 write(#1,y + 1,ind_m - y - 1); 5805 write('\" title=\"'); 5806 ); 5807 ): 5808 c==m_img ? ( 5809 ind_e = find(#1,e_img,y); 5810 copy(i[y],0,ind_e - y + 1,1,0); 5811 is_video?write('</video>'):write('\"/>'); 5812 ): 5813 5814 c==s_pipeline ? ( 5815 ind_e = find(#1,e_pipeline,y); 5816 run('_gmd2html_pipeline. ',y + 1,',',ind_e - 1)?( # If output images 5817 ref(get('_gmd_command',1024,1),str_com); 5818 ref(get('_gmd_filename',1024,1),str_fil); 5819 write('<img class=\"gmd_image\" src=\"'); 5820 len = find(str_fil,0); 5821 write(str_fil,len); 5822 write('\" alt=\"'); 5823 len = find(str_com,0); 5824 write(str_com,len); 5825 write('\"/>'); 5826 ); 5827 copy(i[y],0,ind_e - y + 1,1,0); 5828 ): 5829 5830 c==s_formula ? ( 5831 ind_e = find(#1,e_formula,y); 5832 run('_gmd2html_formula. ',y + 1,',',ind_e - 1); 5833 ref(get('_gmd_filename',1024,1),str_fil); 5834 write('<img class=\"gmd_formula\" src=\"'); 5835 len = find(str_fil,0); 5836 write(str_fil,len); 5837 write('\" alt=\"'); 5838 ): 5839 c==e_formula ? write('\"/>'): 5840 5841 c==s_gmic ? write('<span class=\"gmd_gmic\">G'MIC</span>'): 5842 c==s_whitespace ? write(' '): 5843 c==s_tab ? write(' '); 5844 ); 5845 end(resize(#0,1,_write_off,1,1,0))" 5846 k[0] autocrop 0 nm $fnm.html 5847 endl done 5848 5849 # Embed with header and footer if needed. 5850 if $embed_html 5851 section_title=${"arg "$embed_html",Reference,Tutorial,News"} 5852 repeat $! l[$>] nm={b} nm0=${nm$>} 5853 if ['${title$>}']!=0 title=${title$>} else title=$nm0 fi 5854 if isfile('../style.css') style="../style.css" else style="https://gmic.eu/style.css" fi 5855 i[0] ('"<!DOCTYPE html>"\n\ 5856"<html lang=\"en\">"\n\ 5857" <head>"\n\ 5858" <meta charset=\"utf-8\">"\n\ 5859" <link rel=\"stylesheet\" href=\""$style"\">"\n\ 5860" <title>"$title"</title>"\n\ 5861" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 5862" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 5863" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 5864" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\ 5865" </head>"\n\n\ 5866" <body>"\n\ 5867" <div id=\"include_header\"></div>"\n\n\ 5868" <div class=\"section_title\"><p>"$section_title"</p></div><div class=\"section_content\">"\n\n\ 5869"<!-- begin_content -->"\n\n':y) 5870 ('\n\n\ 5871"<!-- end_content -->"\n\n\ 5872" </div><div class=\"section_end\"></div>"\n\n\ 5873" <div id=\"include_footer\"></div>"\n\ 5874" </body>"':y) 5875 a y nm $nm.html 5876 endl done 5877 fi 5878 5879# Manage sections / subsections / subsubsections / subsubsubsections. 5880_gmd2html_section : 5881 +rows. $1,$2 strvar {t} _gmd_name=${} rm. 5882 5883# Manage page links. 5884_gmd2html_page_link : 5885 +rows. $1,$2 5886 if i==_'-' # Force link to a G'MIC reference page 5887 rows. 1,100% _gmd_text={t} strvar {t} varname=${} 5888 if ['$varname']=='index' varname=_index fi 5889 _gmd_link=https://gmic.eu/reference/$varname.html 5890 else 5891 basename {t} _gmd_text=${} strvar $_gmd_text varname=${} 5892 if ['$varname']=='index' varname=_index fi 5893 _gmd_link=$varname.html 5894 fi 5895 rm. 5896 5897# Manage pipeline execution and result saving. 5898_gmd2html_pipeline : 5899 +rows. $1,$2 5900 _gmd_command={t} rm. 5901 strcasevar $_gmd_command 5902 _gmd_filename=img/${}.png 5903 is_output={fsize(['$_gmd_filename'])} 5904 if !isfile(['$_gmd_filename']) l[] 5905 l[] 5906 run $_gmd_command a x 5907 if !$!" || "($!==1" && "!h) is_output=0 fi 5908 onfail 5909 rm error[] "Command '"$_gmd_command"': "${} 5910 endl 5911 if $! 5912 if !isdir('img') x "mkdir -p img" fi 5913 o. $_gmd_filename rm. 5914 fi 5915 endl fi 5916 ({'$_gmd_command'}) 5917 _gmd_ascii2html. 5918 _gmd_command={t} rm. 5919 u $is_output 5920 5921# Convert formula to image (using LaTeX). 5922_gmd2html_formula : 5923 +rows. $1,$2 replace. {'\n'},{'" "'} j.. .,0,$1 5924 formula={/{t}} rm. 5925 strcasevar $formula varname=${} 5926 _gmd_filename=img/$varname.png 5927 if !isfile(['$_gmd_filename']) l[] 5928 ({'"\\documentclass[preview]{standalone}"\n\ 5929 "\\usepackage{amsmath,amssymb,amsfonts}"\n\ 5930 "\\pagestyle{empty}"\n\ 5931 "\\begin{document}"\n\ 5932 "\\begin{align*}"\n\ 5933 $formula\n\ 5934 "\\end{align*}"\n\ 5935 "\\end{document}"'}) 5936 path_tmp=${-path_tmp} 5937 ot. ${path_tmp}$varname.tex rm. 5938 x "cd "$path_tmp"; rm -f "$varname".pdf; pdflatex -interaction=nonstopmode "$varname".tex >/dev/null" 5939 if isfile(['${path_tmp}$varname.pdf']) 5940 i ${path_tmp}$varname.pdf,800 5941 autocrop. lt. 128 r2dy. 20% n. 0,255 channels. -3,0 5942 if !isdir('img') x "mkdir -p img" fi 5943 o. $_gmd_filename 5944 fi 5945 rm 5946 endl fi 5947 5948# Manage shell execution. 5949_gmd2html_shell : 5950 _gmd_shell. $* 5951 _gmd_ascii2html. 5952 5953_gmd2ascii_shell : 5954 _gmd_shell. $* 5955 5956_gmd_shell : 5957 +rows. $1,$2 _gmd_command={t} rm. 5958 path_tmp=${-path_tmp} 5959 strcasevar $_gmd_command 5960 filename=$path_tmp${}.log 5961 x $_gmd_command" > "$filename" 2>&1" 5962 if isfile(['$filename']) it $filename else 0 fi 5963 autocrop. {'\n'} 5964 5965# Convert an ascii buffer into html. 5966_gmd_ascii2html : 5967 repeat $! l[$>] 5968 . # [0] = Output, [1] = Input 5969 eval. "> 5970 begin("${-_gmd_write}${-_gmd_vt100}" spans = 0); 5971 c = i; 5972 c==_'&'?write('&'): 5973 c==_'\"'?write('"'): 5974 c==_'\''?write('''): 5975 c==_'<'?write('<'): 5976 c==_'>'?write('>'): 5977 c==_'\n'?write('<br/>\n'): 5978 c==_'\33' && j[1]==_'['?( # VT100 sequence 5979 ref(crop(0,y,1,8),C); 5980 same(C,vt100_b,size(vt100_b))?( 5981 write('<span class=\"gmd_bold_a\">'); 5982 copy(i[y],0,size(vt100_b),1,0); 5983 ++spans 5984 ):same(C,vt100_c,size(vt100_c))?( 5985 write('<span style=\"color: darkcyan\">'); 5986 copy(i[y],0,size(vt100_c),1,0); 5987 ++spans 5988 ): 5989 same(C,vt100_g,size(vt100_g))?( 5990 write('<span style=\"color: darkgreen\">'); 5991 copy(i[y],0,size(vt100_g),1,0); 5992 ++spans 5993 ): 5994 same(C,vt100_i,size(vt100_i))?( 5995 write('<span class=\"gmd_italic_a\">'); 5996 copy(i[y],0,size(vt100_i),1,0); 5997 ++spans 5998 ): 5999 same(C,vt100_m,size(vt100_m))?( 6000 write('<span style=\"color: darkmagenta\">'); 6001 copy(i[y],0,size(vt100_m),1,0); 6002 ++spans 6003 ): 6004 same(C,vt100_n,size(vt100_n))?( 6005 repeat (spans,write('</span>')); 6006 copy(i[y],0,size(vt100_n),1,0); 6007 spans = 0 6008 ): 6009 same(C,vt100_r,size(vt100_r))?( 6010 write('<span style=\"color: darkred\">'); 6011 copy(i[y],0,size(vt100_r),1,0); 6012 ++spans 6013 ): 6014 same(C,vt100_s,size(vt100_s))?( 6015 write('<span class=\"gmd_strikethrough\">'); 6016 copy(i[y],0,size(vt100_s),1,0); 6017 ++spans 6018 ): 6019 same(C,vt100_u,size(vt100_u))?( 6020 write('<span class=\"gmd_underline\">'); 6021 copy(i[y],0,size(vt100_u),1,0); 6022 ++spans 6023 ): 6024 write(c) 6025 ):write(c); 6026 " 6027 k[0] discard 0 6028 endl done 6029 6030#@cli gmd2ascii : _max_line_length>0,_indent_forced_newlines>=0 : (no arg) 6031#@cli : Convert selected gmd-formatted text images to ascii format. 6032#@cli : Default values: 'max_line_length=80' and 'indent_forced_newline=0'. 6033gmd2ascii : 6034 is_arg=1 l[] check "isint(${1=80}) && $1>0 && isint(${2=0}) && $2>=0" onfail is_arg=0 endl 6035 max_line_length,indent_forced_newline=${1-2} 6036 if !$is_arg 6037 if !narg($_shell_cols) _shell_cols={${-shell_cols}-5} fi 6038 max_line_length,indent_newline=$_shell_cols,0 noarg 6039 fi 6040 6041 use_vt100 parse_gmd 6042 repeat $! l[$>] nm={b} strvar $nm fnm=${} 6043 . # [0] = Output, [1] = Input 6044 eval. "> 6045 begin("${-_gmd_tokens}${-_gmd_write}${-_gmd_vt100}" 6046 is_blockquote = is_code_block = is_center = is_right = 0; 6047 ref(vector1024(),tmp); 6048 const nbcols = "${-shell_cols}"; 6049 ref(vector(#nbcols,_' '),whiteline); 6050 ); 6051 c = i; 6052 6053 c==_'\n'?( 6054 is_blockquote ? write([vt100_n,'\n > ',vt100_m]): 6055 is_code_block ? write('\n '): 6056 write(c); 6057 is_center ? write(whiteline,nbcols/4): 6058 is_right ? write(whiteline,nbcols/2); 6059 ): 6060 c>0?write(c): 6061 ( 6062 isin(c,e_bold_a,e_bold_u,e_bold_italic_a,e_bold_italic_u,e_italic_a,e_italic_u, 6063 e_strikethrough,e_underline,e_url,e_page_link,e_formula) ? write(vt100_n): 6064 isin(c,e_bullet,e_subbullet,e_subsubbullet) ? write(_'\n'): 6065 isin(c,e_section,e_subsection,e_subsubsection,e_subsubsubsection) ? write([vt100_n,'\n\n']): 6066 6067 c==s_section ? (write_nl(); write([_'\n',vt100_r,vt100_b,'# '])): 6068 c==s_subsection ? (write_nl(); write([_'\n',vt100_r,vt100_b,'## '])): 6069 c==s_subsubsection ? (write_nl(); write([_'\n',vt100_r,vt100_b,'### '])): 6070 c==s_subsubsubsection ? (write_nl(); write([_'\n',vt100_r,vt100_b,'#### '])): 6071 c==s_anchor ? ( 6072 ind_e = find(#1,e_anchor,y); 6073 copy(i[y],0,ind_e - y + 1,1,0); 6074 ): 6075 c==s_bullet ? write(' * '): 6076 c==s_subbullet ? write(' - '): 6077 c==s_subsubbullet ? write(' + '): 6078 c==s_center ? (write(whiteline,nbcols/4); is_center = 1): 6079 c==e_center ? (write(_'\n'); is_center = 0): 6080 c==s_right ? (write(whiteline,nbcols/2); is_right = 1): 6081 c==e_right ? (write(_'\n'); is_right = 0): 6082 c==s_tab ? write(whiteline,4): 6083 isin(c,s_table,s_htable,s_vtable,s_hvtable,n_table) ? (write_nl(); write([vt100_r,' | ',vt100_n])): 6084 c==m_table ? write([vt100_r,' | ',vt100_n]): 6085 c==s_blockquote ? (write([[' > '],vt100_m]); is_blockquote = 1): 6086 c==e_blockquote ? (write([vt100_n,'\n']); is_blockquote = 0): 6087 c==s_detail_block ? ( 6088 ny = y + 1; 6089 nc = j[1]; 6090 nc!=e_detail_block?( 6091 j[1] = 0; 6092 ind_e = find(#1,e_detail_block,ny); 6093 nc==_' '?( # Has a title 6094 ind_nl = find(#1,_'\n',ny); 6095 ind_nl<0 || ind_nl>ind_e?(ind_nl = ind_e); 6096 write([vt100_c,vt100_b,'+ ']); 6097 write(#1,y + 2,ind_nl - y - 2); 6098 write([vt100_n,vt100_c,'\n\n']); 6099 copy(i[ny],0,ind_nl - y - 1,1,0); 6100 i[ind_nl]!=e_detail_block?(i[ind_nl] = 0); 6101 ):write([vt100_c,vt100_b,'Details:',vt100_n,vt100_c,'\n\n']); 6102 ) 6103 ): 6104 c==e_detail_block ? write([vt100_n,'\n']): 6105 c==s_code_block ? (_write_off?write(_'\n'); write([[' '],vt100_c]); is_code_block = 1): 6106 c==e_code_block ? (write([vt100_n,'\n\n']); is_code_block = 0): 6107 c==s_shell ? ( 6108 ind_e = find(#1,e_shell,y); 6109 run('_gmd2ascii_shell. ',y + 1,',',ind_e - 1); 6110 ref(get('_gmd_command',1024,1),str_com); 6111 write('$ '); 6112 len = find(str_com,0); 6113 write(str_com,len); 6114 write('\n\n'); 6115 write(#-1,0,h(#-1)); 6116 run('rm.'); 6117 write(_'\n'); 6118 copy(i[y],0,ind_e - y + 1,1,0); 6119 ): 6120 c==s_hrule ? (write_nl(); write('+------------------------------+\n')): 6121 6122 c==s_bold_italic_a ? write([vt100_m,vt100_b,vt100_i]): 6123 c==s_bold_italic_u ? write([vt100_b,vt100_i]): 6124 c==s_bold_a ? write([vt100_m,vt100_b]): 6125 c==s_bold_u ? write(vt100_b): 6126 c==s_italic_a ? write([vt100_m,vt100_i]): 6127 c==s_italic_u ? write(vt100_i): 6128 c==s_strikethrough? write(vt100_s): 6129 c==s_underline? write(vt100_u): 6130 c==s_monospace ? write([_'\47',vt100_c]): 6131 c==e_monospace ? write([vt100_n,_'\47']): 6132 c==s_value_set ? write([vt100_g,vt100_i,_'{']): 6133 c==e_value_set ? write([_'}',vt100_n]): 6134 c==s_word_highlight ? write([_'\47',vt100_g]): 6135 c==e_word_highlight ? write([vt100_n,_'\47']): 6136 6137 isin(c,s_url,s_page_link,s_text_link) ? write(vt100_u): 6138 c==m_text_link ? ( 6139 ind = find(#1,e_text_link,y); 6140 copy(i[y],0,ind - y + 1,1,0); 6141 write(vt100_n); 6142 ): 6143 c==s_img ? ( 6144 ind_m = find(#1,m_img,y); 6145 ind_e = find(#1,e_img,ind_m); 6146 write(vt100_u); 6147 write(#1,ind_m + 1,ind_e - ind_m -1); 6148 write([vt100_n,_' ',vt100_g,vt100_i,'[image: \'']); 6149 ): 6150 c==m_img ? ( 6151 ind = find(#1,e_img,y); 6152 copy(i[y],0,ind - y + 1,1,0); 6153 write([['\']'],vt100_n]); 6154 ): 6155 c==s_pipeline ? ( 6156 ind = find(#1,e_pipeline); 6157 write([vt100_g,vt100_i,'[image]',vt100_n]); 6158 copy(i[y],0,ind - y + 1,1,0); 6159 ): 6160 c==s_formula ? write(vt100_g); 6161 6162 c==s_gmic ? ( 6163 write([vt100_b,'G\47MIC',vt100_n]); 6164 ): 6165 c==s_whitespace ? write(_' '); 6166 ); 6167 end(resize(#0,1,_write_off,1,1,0))" 6168 k[0] discard 0 6169 _gmd2ascii_cut $max_line_length,$indent_forced_newline 6170 nm $fnm.txt 6171 6172 endl done 6173 6174# Cut long ascii lines in selected text images (ignoring the VT100 codes for the length). 6175# $1: Max length of each line >0. 6176# $2: Indentation put after each forced newline. 6177_gmd2ascii_cut : 6178 repeat $! l[$>] 6179 . # [0] = Output, [1] = Input 6180 eval ${-_gmd_write}" 6181 const N = max(8,$1); 6182 ref(vector(#$2+1,_' '),nl); nl[0] = _'\n'; 6183 6184 # p = pos of block start, q = pos of latest endable (>=p), l = text length in block (w/o VT100 codes). 6185 p = q = r = 0; l = 1; 6186 while (r<h, 6187 i[r]=='\33' && i[r + 1]==_'['?( # VT100-code -> ignore 6188 while (i[r++]!=_'m', 0); 6189 ):i[r]==_'\n'?( 6190 len = r - p + 1; 6191 write(#1,p,len); 6192 p = q = r + 1; 6193 l = 0; 6194 ):l>N?( 6195 q - p<0.6*N?(q = r - 1); 6196 len = q - p + 1; 6197 write(#1,p,len); 6198 write(nl); 6199 p = r = ++q; 6200 l = size(nl) - 1; 6201 ):( 6202 isin(i[r],_',',_' ')?(q = r); 6203 ); 6204 ++r; ++l; 6205 ); 6206 p<h?(len = h - p; write(#1,p,len))" 6207 6208 k[0] autocrop 0 6209 endl done 6210 6211# Define variables associated to markdown tokens, for the math parser. 6212_gmd_tokens : 6213 u "const s_section = -1; 6214 const e_section = -2; 6215 const s_subsection = -3; 6216 const e_subsection = -4; 6217 const s_subsubsection = -5; 6218 const e_subsubsection = -6; 6219 const s_subsubsubsection = -7; 6220 const e_subsubsubsection = -8; 6221 const s_anchor = -9; 6222 const e_anchor = -10; 6223 const s_bullet = -11; 6224 const e_bullet = -12; 6225 const s_subbullet = -13; 6226 const e_subbullet = -14; 6227 const s_subsubbullet = -15; 6228 const e_subsubbullet = -16; 6229 const s_center = -17; 6230 const e_center = -18; 6231 const s_right = -19; 6232 const e_right = -20; 6233 const s_table = -21; 6234 const s_htable = -22; 6235 const s_vtable = -23; 6236 const s_hvtable = -24; 6237 const m_table = -25; 6238 const n_table = -26; 6239 const e_table = -27; 6240 const s_blockquote = -28; 6241 const e_blockquote = -29; 6242 const s_detail_block = -30; 6243 const e_detail_block = -31; 6244 const s_code_block = -32; 6245 const e_code_block = -33; 6246 const s_shell = -34; 6247 const e_shell = -35; 6248 const s_hrule = -36; 6249 6250 const s_bold_italic_a = -37; 6251 const e_bold_italic_a = -38; 6252 const s_bold_italic_u = -39; 6253 const e_bold_italic_u = -40; 6254 const s_bold_a = -41; 6255 const e_bold_a = -42; 6256 const s_bold_u = -43; 6257 const e_bold_u = -44; 6258 const s_italic_a = -45; 6259 const e_italic_a = -46; 6260 const s_italic_u = -47; 6261 const e_italic_u = -48; 6262 const s_strikethrough = -49; 6263 const e_strikethrough = -50; 6264 const s_underline = -51; 6265 const e_underline = -52; 6266 const s_monospace = -53; 6267 const e_monospace = -54; 6268 const s_value_set = -55; 6269 const e_value_set = -56; 6270 const s_word_highlight = -57; 6271 const e_word_highlight = -58; 6272 6273 const s_url = -59; 6274 const e_url = -60; 6275 const s_page_link = -61; 6276 const e_page_link = -62; 6277 const s_text_link = -63; 6278 const m_text_link = -64; 6279 const e_text_link = -65; 6280 const s_img = -66; 6281 const m_img = -67; 6282 const e_img = -68; 6283 const s_pipeline = -69; 6284 const e_pipeline = -70; 6285 const s_formula = -71; 6286 const e_formula = -72; 6287 6288 const s_gmic = -73; 6289 const e_gmic = -74; 6290 const s_whitespace = -75; 6291 const s_tab = -76;" 6292 6293# Define variables corresponding to VT100 sequences, for the math parser. 6294_gmd_vt100 : 6295 use_vt100 6296 u "ref('"$_vt100_b"',vt100_b); 6297 ref('"$_vt100_c"',vt100_c); 6298 ref('"$_vt100_g"',vt100_g); 6299 ref('"$_vt100_i"',vt100_i); 6300 ref('"$_vt100_m"',vt100_m); 6301 ref('"$_vt100_n"',vt100_n); 6302 ref('"$_vt100_r"',vt100_r); 6303 ref('"$_vt100_s"',vt100_s); 6304 ref('"$_vt100_u"',vt100_u);" 6305 6306# Define variables and functions to write strings and characters in a streamed way for the math parser. 6307_gmd_write : 6308 u "write(str) = write(str,0); 6309 write(str,len) = ( 6310 ref(str,_str); unref(_siz); const _siz = size(_str); ref(len,_len); 6311 _siz?( # String 6312 l = _len?_len:_siz; 6313 _write_off + l>h(#0)?resize(#0,1,8 + l + 5*h(#0)/3,1,1,0); 6314 copy(i[#0,_write_off],_str,l); 6315 _write_off+=l; 6316 ):( # Character 6317 _write_off>=h(#0)?resize(#0,1,8 + 5*h(#0)/3,1,1,0); 6318 i[#0,_write_off++] = _str; 6319 ) 6320 ); 6321 write(ind,start,len) = ( 6322 ref(len,_len); 6323 _write_off + _len>h(#0)?resize(#0,1,8 + _len + 5*h(#0)/3,1,1,0); 6324 copy(i[#0,_write_off],i[#ind,start],_len); 6325 _write_off+=_len; 6326 ); 6327 write_nl() = ( # Force newline 6328 i[#0,_write_off -1 ]!=_'\n'?write(_'\n'); 6329 ); 6330 _write_off = 0;" 6331 6332#@cli parse_gui : _outputmode,_{ * | filter_name} 6333#@cli : Parse selected filter definitions and generate info about filters in selected output mode. 6334#@cli : 'outputmode' can be { gmicol | json | list | print | ts | update | zart }.\n 6335#@cli : It is possible to define a custom output mode, by implementing the following commands 6336#@cli : ('outputmode' must be replaced by the name of the custom user output mode): 6337#@cli : . 'parse_gui_outputmode' : A command that outputs the parsing information with a custom format. 6338#@cli : . 'parse_gui_parseparams_outputmode' (optional): A simple command that returns 0 or 1. It tells the parser \ 6339# whether parameters of matching filter must be analyzed (slower) or not. 6340#@cli : . 'parse_gui_trigger_outputmode' (optional): A command that is called by the parser just before parsing \ 6341# the set of each matching filters.\n 6342#@cli : Here is the list of global variables set by the parser, accessible in command 'parse_gui_outputmode':\n 6343#@cli : '$_nbfilters': Number of matching filters. 6344#@cli : '$_nongui' (stored as an image): All merged lines in the file that do not correspond to '#@gui' lines.\n 6345#@cli : For each filter `\#F` ('F' in range `[0,$_nbfilters-1]`): 6346#@cli : * '$_fF_name' : Filter name. 6347#@cli : * '$_fF_path' : Full path. 6348#@cli : * '$_fF_locale' : Filter locale (empty, if not specified). 6349#@cli : * '$_fF_command' : Filter command. 6350#@cli : * '$_fF_commandpreview' : Filter preview command (empty, if not specified). 6351#@cli : * '$_fF_zoomfactor' : Default zoom factor (empty, if not specified). 6352#@cli : * '$_fF_zoomaccurate' : Is preview accurate when zoom changes ? (can be { 0=false | 1=true }). 6353#@cli : * '$_fF_inputmode' : Default preferred input mode (empty, if not specified). 6354#@cli : * '$_fF_hide' : Path of filter hid by current filter (for localized filters, empty if not specified). 6355#@cli : * '$_fF_nbparams' : Number of parameters.\n 6356#@cli : For each parameter `\#P` of the filter \#F ('P' in range `[0,$_fF_nbparams-1]`): 6357#@cli : * '$_fF_pP_name' : Parameter name. 6358#@cli : * '$_fF_pP_type' : Parameter type. 6359#@cli : * '$_fF_pP_responsivity' : Parameter responsivity (can be { 0 | 1 }). 6360#@cli : * '$_fF_pP_visibility' : Parameter visibility. 6361#@cli : * '$_fF_pP_propagation' : Propagation of the parameter visibility. 6362#@cli : * '$_fF_pP_nbargs' : Number of parameter arguments.\n 6363#@cli : For each argument `\#A` of the parameter \#P ('A' in range `[0,$_fF_pP_nbargs-1]`): 6364#@cli : * '$_fF_pP_aA' : Argument value\n 6365#@cli : Default parameters: 'filter_name=*' and 'output_format=print'. 6366parse_gui : skip "${1=print},${2=*}" 6367 e[^-1] "Parse '#@gui' filters '$2' and output in '$1' mode." 6368 6369 # Check that specified output mode is actually implemented. 6370 l[] ({'$$parse_gui_$1'}) rm 6371 onfail error[0--2] "Command 'parse_gui': Invalid output mode '$1'." 6372 endl 6373 6374 # Input .gmic data. 6375 use_vt100 6376 if !$! l[] it ${_path_rc}update$_version.gmic onfail endl fi 6377 if !$! return fi 6378 y a y merge_multiline_comments 6379 6380 # Extract all filter chunks with full path. 6381 e[] "" 6382 e[] "\r > Extract filter chunks." 6383 macros=" 6384 is_blank(p) = ((_c=source[p])<=_' ' && _c!=_'\n'); 6385 skip_blank(p) = (while (is_blank(p), ++p)); 6386 clean(name) = ( 6387 _l = find(name,0); 6388 _l>0?( 6389 _p = 0; while (1, 6390 _p = find(name,_'<',_p); 6391 _p<0 || _p>=_l?break(); 6392 isin(name[_p+1],_'b',_'i') && name[_p+2]==_'>'?( # Opening tag 6393 copy(name[_p],name[_p+3],_l-_p-2); 6394 _l-=3; 6395 ):name[_p+1]==_'/' && isin(name[_p+2],_'b',_'i') && name[_p+3]==_'>'?( # Closing tag 6396 copy(name[_p],name[_p+4],_l-_p-3); 6397 _l-=4; 6398 ):++_p; 6399 ); 6400 _p = 0; while (1, _p = find(name,_'/',_p); _p<0 || _p>=_l?break(); name[_p++] = _'-'); # Replace '/' by '-' 6401 ); 6402 );" 6403 6404 eval $macros" 6405 store_block(p,q,path,name,hide) = ( 6406 run('+rows[0] ',p,',',q,' discard. -1 autocrop. 10 autocrop. 32 nm. \"',path,'/',name,'\"'); 6407 6408 # Insert hide() info at the end of the chunk, with magic number '-2'. 6409 hide[0]?run([40,45,50,44,123,39,34],hide,[34,39,125,41],' y. a[-2,-1] y'); 6410 ); 6411 6412 # Init variables. 6413 #---------------- 6414 ref(crop(),source); 6415 path = prev_path = name = prev_name = hide = prev_hide = vector1024(); 6416 6417 # Start parsing. 6418 #--------------- 6419 prev_p0 = p0 = p = 0; 6420 while (p<size(source), 6421 p = find(source,'#@gui',p)%size(source); 6422 6423 !p || (p>0 && source[p - 1]==_'\n')?( # Found line starting with '#@gui' 6424 p0 = p; # Remember starting position of line 6425 p+=5; 6426 source[p]==_'_' && (l = find(source,_' ',++p))>=0?(p = l + 1); # Skip locale 6427 6428 # Detect new filter, folder or hide() directive. 6429 #----------------------------------------------- 6430 skip_blank(p); 6431 source[p]!=_':'?( 6432 hide[0] = 0; 6433 q = find(source,_':',p)%size(source); 6434 r = find(source,_'\n',p)%size(source); 6435 is_hide = q>r && (l=find(source,'hide(',p)%size(source))<r; 6436 r<q && !is_hide?( 6437 6438 # Definition of a new folder. 6439 #---------------------------- 6440 r0 = r; while (is_blank(--r),0); 6441 copy(name,source[p],r-p+1); name[r-p+1] = 0; 6442 for (levelup = 0, name[levelup]==_'_', ++levelup); 6443 levelup?( 6444 copy(name,name[levelup],r-p+2-levelup); # Clean folder name 6445 while (levelup--, # Update path 6446 lp = find(path,0); l = max(0,find(path,_'/',lp-1,0)); path[l] = 0; 6447 ); 6448 ); 6449 clean(name); 6450 name[0]?( 6451 ln = find(name,0); # Update path 6452 lp = find(path,0); 6453 lp?(path[lp] = _'/'; copy(path[lp+1],name,ln); path[lp+ln+1] = 0):(copy(path,name,ln); path[ln] = 0); 6454 ); 6455 copy(i[#0,p0],-1,r0-p0+1,1,0); # Discard folder definition line (will be removed later) 6456 p = r0 + 1; 6457 ):!is_hide?( 6458 6459 # Definition of a new filter. 6460 #---------------------------- 6461 while (is_blank(--q),0); 6462 copy(name,source[p],q-p+1); name[q-p+1] = 0; 6463 clean(name); 6464 store_block(prev_p0,p0-1,prev_path,prev_name,prev_hide); 6465 6466 prev_p0 = p0; 6467 prev_path = path; 6468 prev_name = name; 6469 prev_hide = hide; 6470 p = q + 1; 6471 ):( 6472 6473 # Manage hide() directive. 6474 #-------------------------- 6475 l0 = l + 5; l = find(source,_')',l0); 6476 l<r?( 6477 copy(hide,source[l0],l-l0); hide[l-l0] = 0; 6478 copy(i[#0,p0],-1,r-p0+1,1,0); 6479 ); 6480 p = r + 1; 6481 ) 6482 ) 6483 ):++p 6484 ); 6485 prev_p0!=p0?store_block(prev_p0,size(source)-1,prev_path,prev_name,prev_hide) # Insert last block 6486 " 6487 rm[0] 6488 6489 # Isolate only requested filters. 6490 if "['$2']!='*'" 6491 1,$!,1,1," 6492 begin(ref(lowercase(['$2']),str)); 6493 ref(lowercase(name(#y)),nm); 6494 find(nm,str)>=0?y:-1" 6495 discard. -1 k[{^}] 6496 fi 6497 l parse_gui_trigger_$1 onfail endl # Allow global pre-processing before parsing each filter. 6498 6499 # Parse each filter. 6500 nbchunks=$! 6501 f=0 repeat $nbchunks,c _f${f}_path={$>,f} if {$>,h} l[$>] 6502 if crop(0,0,1,5)!='#@gui' # Non-gui : merge code and skip chunk 6503 autocrop {'\n'} store nongui$c 0 continue 6504 fi 6505 6506 # Init variables. 6507 _f${f}_locale= 6508 _f${f}_commandpreview= 6509 _f${f}_zoomfactor= 6510 _f${f}_zoomaccurate= 6511 _f${f}_inputmode= 6512 _f${f}_nbparams=0 6513 _f${f}_hide= 6514 6515 # Detect locale. 6516 if crop(0,0,1,6)=='#@gui_' _f${f}_locale={`crop(0,6,1,2)`} fi 6517 6518 # Detect hid filter. 6519 p={"find(#0,-2,h-1,0)"} 6520 if $p>=0 +rows. {$p+1},100% _f${f}_hide={t} rm. fi 6521 6522 # Separate '#@gui' lines from other lines, and merge them. 6523 eval $macros" 6524 ref(crop(),source); 6525 is_first = 1; 6526 p = 0; 6527 while (p<size(source), 6528 p = find(source,'#@gui',p)%size(source); 6529 !p || (p>0 && source[p - 1]==_'\n')?( # Found line starting with '#@gui' 6530 p0 = p; # Remember starting position of line 6531 p+=5; 6532 source[p]==_'_' && (l = find(source,_' ',++p))>=0?(p = l + 1); # Skip locale 6533 skip_blank(p); 6534 source[p]==_':'?(++p; skip_blank(p)); 6535 r = find(source,_'\n',p)%size(source); # Find end of line 6536 run('+rows[0] ',p,',',r); 6537 source[r]==_'\n'?(i[#-1,h(#-1)-1] = is_first?0:_' '); 6538 copy(i[#0,p0],-1,min(r,size(source)-1)-p0+1,1,0); # Part to be discarded 6539 p = r + 1; 6540 is_first = 0; 6541 ):++p 6542 )" 6543 a[^0] y discard.. -1 6544 autocrop[0] {'\n'} store[0] nongui$c 6545 s -,0 # Split in two images : definition and parameters 6546 f "max(_' ',i)" # Replace all blank characters by space 6547 6548 # Parse filter definition. 6549 l[0] 6550 _f${f}_zoomaccurate=0 6551 s -,{':'} autocrop {'" "'} 6552 _f${f}_name={`$macros" name=[['"{0,t}"'],0]; clean(name); name"`} rm[0] # Filter name 6553 if $! l[0] 6554 s -,{','} autocrop {'" "'} 6555 _f${f}_command={0,t} # Filter command 6556 if $!>1 l[1] 6557 s -,{'('} 6558 _f${f}_commandpreview={0,t} # Filter preview command 6559 if $!>1 l[1] 6560 s +,{'+'} 6561 discard[0] {')'} 6562 _f${f}_zoomfactor={0,t} # Default zoom factor 6563 if $!>1" && "i[0]==_'+' _f${f}_zoomaccurate=1 fi # Is zoom accurate ? 6564 endl fi 6565 endl fi 6566 rm 6567 endl fi 6568 if $! _f${f}_inputmode={0,t} fi # Default input mode 6569 rm 6570 endl 6571 e[] "\r > "$_vt100_c[#$f]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 6572 6573 # Parse filter parameters. 6574 parseparams=1 6575 l[] parseparams=${-parse_gui_parseparams_$1} onfail endl 6576 6577 if !$!" || "!$parseparams _f${f}_nbparams=0 6578 else 6579 eval $macros" 6580 ref(crop(),source); 6581 ref(vector256(),name); 6582 ref(vector256(),type); 6583 ref(vector65536(),argument); 6584 6585 p = nbparams = 0; 6586 while (p<size(source), 6587 q = find(source,_'=',p)%size(source); 6588 source[q]==_'='?( # Found new parameter 6589 skip_blank(p); 6590 r = q + 1; skip_blank(r); 6591 while (is_blank(--q),0); 6592 copy(name,source[p],q-p+1); name[q-p+1] = 0; # Parameter name 6593 store(name,'tmparg',q-p+1); 6594 p = r; 6595 q = min(find(source,_'(',p)%size(source), 6596 find(source,_'{',p)%size(source), 6597 find(source,_'[',p)%size(source)); 6598 c = source[q]==_'('?_')':source[q]==_'{'?_'}':_']'; 6599 r = q + 1; skip_blank(r); 6600 while (is_blank(--q),0); 6601 6602 responsivity = 1; 6603 source[p]==_'_'?(responsivity = 0; ++p); 6604 copy(type,source[p],q-p+1); type[q-p+1] = 0; # Parameter type 6605 for (i = 0, type[i], ++i, type[i] = lowercase(type[i])); # Force lowercase 6606 run('$tmparg _f"${f}"_p',nbparams,'_name={t} rm. _f"${f}"_p',nbparams,'_type=', 6607 type,' _f"${f}"_p',nbparams,'_responsivity=',responsivity); 6608 6609 # Parse list of arguments. 6610 p = r; 6611 r = find(source,c,p)%size(source); 6612 nbargs = 0; 6613 6614 type[0,5]==[['bool'],0] || 6615 type[0,7]==[['button'],0] || 6616 type[0,6]==[['value'],0] || 6617 type[0,7]==[['filein'],0] || 6618 type[0,8]==[['fileout'],0] || 6619 type[0,7]==[['folder'],0] || 6620 type[0,5]==[['note'],0] || 6621 type[0,10]==[['separator'],0]?( # Single-argument parameter 6622 p!=r?( 6623 skip_blank(p); 6624 pe = r; 6625 while (is_blank(--pe),0); 6626 copy(argument,source[p],pe-p+1); argument[pe-p+1] = 0; # Parameter argument 6627 store(argument,'tmparg',1,pe-p+1); run('$tmparg _f"${f}"_p',nbparams,'_a0={t} rm.'); 6628 nbargs = 1; 6629 ):(argument[0] = 0); 6630 p = r + 1; 6631 ):( # Multiple-arguments parameter -> parse list of arguments 6632 while (p<r, 6633 skip_blank(p); 6634 pe = q = min(r,find(source,_',',p)%size(source)); 6635 while (is_blank(--pe),0); 6636 copy(argument,source[p],pe-p+1); argument[pe-p+1] = 0; # Parameter argument 6637 store(argument,'tmparg',1,pe-p+1); run('$tmparg _f"${f}"_p',nbparams,'_a',nbargs,'={t} rm.'); 6638 ++nbargs; 6639 p = q + 1; 6640 ); 6641 ); 6642 run('_f"${f}"_p',nbparams,'_nbargs=',nbargs); 6643 6644 # Extract visibility state. 6645 p = r + 1; 6646 p<size(source) && source[p]==_'_' && isin(source[p+1],_'0',_'1',_'2')?( 6647 r = p + 1; 6648 run('_f"${f}"_p',nbparams,'_visibility=',source[r]-_'0'); 6649 isin(source[r+1],_'+',_'-',_'*')?run('_f"${f}"_p',nbparams,'_propagation=',[source[++r]]); 6650 ); 6651 6652 p = r + 1; 6653 skip_blank(p); 6654 source[p]==_','?++p; 6655 ++nbparams; 6656 ):++p; 6657 ); 6658 run('_f"${f}"_nbparams=',nbparams)" 6659 fi 6660 if !$! 0 fi 6661 f+=1 6662 endl fi done 6663 _nbfilters=$f rm 6664 6665 # Merge all non-gui code. 6666 repeat $nbchunks if narg(${nongui$>}) ${nongui$>} if !w rm. fi fi done 6667 if $! ('\n') a[^-1] .,y rm. a y else 0 fi 6668 store. _nongui 6669 6670 # Done! 6671 e[] "\r > "${_vt100_g}{`copy(vector64(_'" "'),'"Parsing done!"')`}$_vt100_n 6672 v + parse_gui_$1 # Output result of the parsing. 6673 6674# 6675# Implements 'print' mode for command 'parse_gui' (default output mode). 6676# 6677parse_gui_parseparams_print : u 0 # Tell parser to not parse filter parameters 6678parse_gui_trigger_print : sort_list +,n 6679parse_gui_print : 6680 e[] "\r"${_vt100_g}{`vector68(_'" "')`}$_vt100_n 6681 e[] " > "${_vt100_g}"List of matching filters:"$_vt100_n"\n\n" 6682 repeat $_nbfilters 6683 +e[] " [#"{1+$>}"] "${_f$>_path}${_f$>_name} 6684 done 6685 6686# Implements 'thumbnails' mode for command 'parse_gui'. 6687parse_gui_parseparams_thumbnails : u 1 # Tell parser to parse filter parameters 6688parse_gui_thumbnails : 6689 e[] " >> Generate output, in 'thumbnails' mode.\n" 6690 if !isdir('thumbnails') x "mkdir -p thumbnails" fi 6691 sp landscape r2dy 256 r 256,256,1,3,0,0,0.5,0.5 store img 6692 _preview_width,_preview_height=256 6693 6694 repeat $_nbfilters,f 6695 nb$f=${_f${f}_nbparams} 6696 done 6697 6698 repeat $_nbfilters,f 6699 command=${_f${f}_commandpreview} 6700 if ['$command']==0 command=${_f${f}_command} fi 6701 pipeline= 6702 c= 6703 if s='$command';s!='_none_'&&s!='fx_whatsnew_preview' 6704 pipeline.=$command" " 6705 repeat ${_f${f}_nbparams},p 6706 type=${_f${f}_p${p}_type} 6707 arg0=${_f${f}_p${p}_a0} 6708 if s='$type';s=='file'||s=='filein'||s=='fileout'||s=='folder'||s=='value' 6709 if !${_f{$f}_p${p}_nbargs} pipeline.=$c\"\" 6710 else 6711 args= ac= 6712 repeat ${_f${f}_p${p}_nbargs},a args.=$ac${_f${f}_p${p}_a${a}} ac=, done 6713 s=\" 6714 if ['$args']==0 s=\" elif ['$args'][0]==_'\"' s= fi 6715 pipeline.=$c$s$args$s 6716 fi 6717 c=, 6718 elif s='$type';s=='text' 6719 val,off=0 6720 N=${_f${f}_p${p}_nbargs} 6721 l[] if isint($arg0) val=$arg0 N-=1 off=1 fi onfail endl 6722 args= ac= 6723 repeat $N,a na={$a+$off} args.=$ac${_f${f}_p${p}_a${na}} ac=, done 6724 s=\" 6725 if ['$args']==0 s=\" elif ['$args'][0]==_'\"' s= fi 6726 pipeline.=$c$s$args$s 6727 c=, 6728 elif s='$type';s=='float'||s=='int' 6729 pipeline.=$c$arg0 c=, 6730 elif s='$type';s=='button' 6731 pipeline.=${c}0 c=, 6732 elif s='$type';s=='bool' 6733 val=0 6734 if s='$arg0';s==1||s=='true' val=1 fi 6735 pipeline.=$c$val c=, 6736 elif s='$type';s=='choice' 6737 val=0 6738 l[] if isint($arg0) val=$arg0 fi onfail endl 6739 pipeline.=$c$val c=, 6740 elif s='$type';s=='color' 6741 if ${_f${f}_p${p}_nbargs}==1" && "['$arg0'][0]==_'#' # Convert colors specified as '#RRGGBB[AA]' 6742 l[] ('$arg0') autocrop. {'#'} s x,-2 _f${f}_p${p}_nbargs=$! 6743 repeat $!,a hex2dec {$>,t} _f${f}_p${p}_a${a}=${} done rm 6744 endl 6745 fi 6746 repeat ${_f${f}_p${p}_nbargs},a pipeline.=$c${_f${f}_p${p}_a${a}} c=, done 6747 elif s='$type';s=='point' 6748 pipeline.=$c$arg0,${_f${f}_p${p}_a1} c=, 6749 fi 6750 done 6751 fi 6752 +e[] ${_vt100_c}" [#"{1+$>}"] "${_vt100_n}${_f${f}_name}": "${_vt100_g}$pipeline${_vt100_n} 6753 if ['$pipeline']!=0 6754 filename thumbnails/thumb.png,$f file_out=${} 6755 l[] 6756 $img run $pipeline gui_merge_layers r2din 200,200,2 6757 onfail 6758 e[] "Error "$_vt100_r${}$_vt100_n"\n" 6759 rm 6760 endl 6761 fi 6762 6763 if !$! $img gui_no_preview , fi 6764 c. 0,255 r2din. 200,200,2 r. 100%,100%,1,{min(s,4)} to_rgba. r. 200,200,1,4,0,0,0.5,0.5 6765 if {*} w. ${"fitscreen ."} fi 6766 o. $file_out rm. 6767 6768 done 6769 e[] " >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 6770 6771# 6772# Implements 'whatsnew' mode for command 'parse_gui'. 6773# 6774parse_gui_parseparams_whatsnew : u 0 # Tell parser to not parse filter parameters 6775parse_gui_whatsnew : 6776 e[] " >> Generate output, in 'whatsnew' mode.\n" 6777 l[] if $_nbfilters 6778 1,1,1,1x$_nbfilters 6779 repeat $! nm[$>] -${_f$>_path}${_f$>_name} f[$>] $> done 6780 sort_list +,n a x 6781 repeat w n={0,i[$>]} ('${_f${n}_path}" "${_f${n}_name}\n') done 6782 rm[0] 6783 fi endl 6784 y a y 6785 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 6786 6787# 6788# Implements 'list' mode for command 'parse_gui'. 6789# 6790parse_gui_parseparams_list : u 0 # Tell parser to not parse filter parameters 6791parse_gui_list : 6792 e[] " >> Generate output, in 'list' mode.\n" 6793 ('"*** List of filters in the G\47MIC plug-in ("$_nbfilters" filters, on "\ 6794 {`v=date(1);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}"/"\ 6795 {`v=date(2);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}", "\ 6796 {`v=date(4);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}":"\ 6797 {`v=date(5);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}") ***\n\n"') 6798 6799 ('"* List of filters, sorted by path:\n\n"') 6800 l[] 6801 1,1,1,1x$_nbfilters 6802 repeat $! nm[$>] -${_f$>_path}${_f$>_name} f[$>] $> done 6803 sort_list +,n a x 6804 repeat w n={0,i[$>]} 6805 ('${_f${n}_path}${_f${n}_name}" (command: '"${_f${n}_command}"')\n"') 6806 done 6807 rm[0] 6808 endl 6809 6810 ('"\n* List of filters, sorted alphabetically:\n\n"') 6811 l[] 6812 1,1,1,1x$_nbfilters 6813 repeat $! nm[$>] -${_f$>_name} f[$>] $> done 6814 sort_list +,n a x 6815 repeat w n={0,i[$>]} 6816 ('${_f${n}_name}" (in '"${_f${n}_path}"')\n"') 6817 done 6818 rm[0] 6819 endl 6820 6821 ('"\n*** End of list ***\n"') 6822 y a y 6823 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 6824 6825# 6826# Implements 'update' mode for command 'parse_gui'. 6827# 6828parse_gui_parseparams_update : u 1 # Tell parser to parse filter parameters 6829parse_gui_update : 6830 e[] " >> Generate output, in 'update' mode.\n" 6831 path=/ 6832 N={$_nbfilters-1} 6833 is_af={date([1,2])==[4,1]" && "(date(4)%2)} # April fool mode ? 6834 repeat $_nbfilters,f 6835 e[] "\r >> "$_vt100_c[#$f/$N]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 6836 6837 # Insert directives to change folder if necessary. 6838 if ;['$path']!=['${_f${f}_path}'] 6839 command_path={`" 6840 src = ['"$path"']; 6841 dest = ['"${_f${f}_path}'"]; 6842 ref(vector1024(),command); 6843 for (p = 0, p<min(size(src),size(dest)) && src[p]==dest[p], ++p); # Find common base 6844 while (p>0 && src[p]!=_'/' && dest[p]!=_'/', --p); 6845 6846 nb_levelup = 0; 6847 for (q = p + 1, q<size(src), ++nb_levelup, q = find(src,_'/',q) + 1); 6848 nb_levelup?(copy(command,'#@gui '); copy(command[6],_'_',nb_levelup,1,0)); 6849 6850 is_testing = !find(dest,'Testing/'); 6851 is_about = !find(dest,'About/'); 6852 6853 dest[p]==_'/'?++p; 6854 while (p<size(dest), 6855 q = find(dest,_'/',p)%size(dest); 6856 eoc = find(command,0); 6857 !eoc || command[eoc-1]!=_'_'?(copy(command[eoc],'#@gui '); eoc+=6); 6858 is_italic = (is_testing && find(dest,'Testing/',p)<0) || is_about; 6859 copy(command[eoc],is_italic?'<i>':'<b>'); 6860 copy(command[eoc + 3],dest[p],q-p); 6861 copy(command[eoc + 3 + q - p],is_italic?'</i>\n':'</b>\n'); 6862 p = q + 1; 6863 ); command"`} 6864 ('$command_path\n') 6865 fi 6866 6867 path=${_f${f}_path} 6868 6869 if narg(${_f${f}_commandpreview}) commandpreview=,${_f${f}_commandpreview} else commandpreview= fi 6870 if narg(${_f${f}_locale}) locale=_${_f${f}_locale} else locale= fi 6871 if narg(${_f${f}_zoomfactor}) zoomfactor=(${_f${f}_zoomfactor}) else zoomfactor= fi 6872 if ${_f${f}_zoomaccurate} zoomaccurate=+ else zoomaccurate= fi 6873 if narg(${_f${f}_inputmode}) inputmode=" : "${_f${f}_inputmode} else inputmode= fi 6874 strcapitalize ${_f${f}_name} name=${} 6875 6876 if ['${_f${f}_hide}']!=0 ('"#@gui"$locale" hide("${_f${f}_hide}")\n"') fi 6877 ('"#@gui"$locale" "$name:${_f${f}_command}$commandpreview$zoomfactor$zoomaccurate$inputmode\n') 6878 6879 repeat ${_f${f}_nbparams},p 6880 responsivity,visibility= 6881 if !${_f${f}_p${p}_responsivity} responsivity=_ fi 6882 if narg(${_f${f}_p${p}_visibility}) visibility=_${_f${f}_p${p}_visibility}${_f${f}_p${p}_propagation} fi 6883 is_choice={['${_f${f}_p${p}_type}']=='choice'} 6884 is_color={['${_f${f}_p${p}_type}']=='color'} 6885 6886 # Build list of arguments. 6887 args= c= 6888 if $is_choice # Capitalize arguments of choice() 6889 repeat ${_f${f}_p${p}_nbargs},a 6890 if $is_af straprilfool ${_f${f}_p${p}_a${a}} 6891 else strcapitalize ${_f${f}_p${p}_a${a}} 6892 fi 6893 args.=$c${} c=, done 6894 elif $is_color # Force html color code for color() 6895 if inrange(${_f${f}_p${p}_nbargs},3,4)" && "\ 6896 inrange(${_f${f}_p${p}_a0},0,255)" && "\ 6897 inrange(${_f${f}_p${p}_a1},0,255)" && "\ 6898 inrange(${_f${f}_p${p}_a2},0,255)" && "\ 6899 (${_f${f}_p${p}_nbargs}==3" || "inrange(${_f${f}_p${p}_a3},0,255)) 6900 args=# 6901 repeat ${_f${f}_p${p}_nbargs},a 6902 args.={`"tab = [ _'0',_'1',_'2',_'3',_'4',_'5',_'6',_'7',_'8',_'9',_'a',_'b',_'c',_'d',_'e',_'f' ]; 6903 const v = "${_f${f}_p${p}_a${a}}"; [ tab[(v>>4)&15],tab[v&15] ]"`} 6904 done 6905 else repeat ${_f${f}_p${p}_nbargs},a args.=$c${_f${f}_p${p}_a${a}} c=, done 6906 fi 6907 else 6908 repeat ${_f${f}_p${p}_nbargs},a args.=$c${_f${f}_p${p}_a${a}} c=, done 6909 fi 6910 sep1,sep2={`" 6911 s = ['"$args"']; 6912 size(s)?( 6913 find(s,_'(')<0 && find(s,_')')<0?[_'(',_',',_')']: 6914 find(s,_'{')<0 && find(s,_'}')<0?[_'{',_',',_'}']: 6915 [_'[',_',',_']'] 6916 ):[_'(',_',',_')']; 6917 "`} 6918 if s=['${_f${f}_p${p}_type}'];"s=='link' || s=='note' || s=='separator' || s=='value'" name=_ 6919 else strcapitalize ${_f${f}_p${p}_name} name=${} 6920 fi 6921 ('"#@gui"$locale" :"{/$name}=$responsivity${_f${f}_p${p}_type}{``$sep1}{``{/$args}}{``$sep2}$visibility\n') 6922 6923 done 6924 done 6925# repeat $! l[$>] utf82html endl done 6926 $_nongui y a y 6927 6928 # Clean generated output, add footer and header. 6929 compress_gmic. 6930 i[0] ('"#@gmic"\n\ 6931 "#"\n\ 6932 "# File : update"$_version".gmic"\n\ 6933 "# ( G\47MIC command file )"\n\ 6934 "#"\n\ 6935 "# Description : Update file for G\47MIC commands and filters (for version "${-strver}")."\n\ 6936 "# ( https://gmic.eu )"\n\ 6937 "#"\n\ 6938 "# License : CeCILL v2.1"\n\ 6939 "# ( https://cecill.info/licences/Licence_CeCILL_V2.1-en.html )"\n\ 6940 "#"\n\ 6941 "# Generated on : "\ 6942 {date(0)}"/"\ 6943 {`v=date(1);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}"/"\ 6944 {`v=date(2);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}", "\ 6945 {`v=date(4);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}":"\ 6946 {`v=date(5);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}\n\ 6947 "#"\n') 6948 ('"\n# Local Variables:"\n\ 6949 "# mode: sh"\n\ 6950 "# End:"\n\ 6951 "#"\n\ 6952 "# (End of G\47MIC update file)"') 6953 y a y 6954 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 6955 6956# April Fool version! 6957straprilfool : skip "${1=}" 6958 if ['"$1"']==0 u "" return fi 6959 l[] ('{/"$1"}') 6960 f "(i<=_' ' || i==_'_') && i!=_'\n'?_' ':i" # Replace blank characters and underscores 6961 f "x%2?lowercase(i):uppercase(i)" 6962 f "c = lowercase(i); 6963 c==_'o'?_'0': 6964 c==_'i'?_'1': 6965 c==_'e'?_'3': 6966 c==_'a'?_'4': 6967 c==_'s'?_'5': 6968 c==_'t'?_'7': 6969 c==_'b'?_'8': 6970 i" 6971 u {t} rm endl 6972 6973# 6974# Implements 'json' mode for command 'parse_gui'. 6975# 6976parse_gui_parseparams_json : u 1 # Tell parser to parse filter parameters 6977parse_gui_trigger_json : 6978 repeat $! l[$>] # Keep only 1-level folders 6979 nm {`s=[['{n}'],0];p=find(s,_'/',size(s)-1,0);p>=0?(p=find(s,_'/',p-1,0);p>0?copy(s,s[p+1],size(s)-p));s`} 6980 endl done 6981 sort_list +,n 6982 6983parse_gui_json : 6984 e[] " >> Generate output, in 'json' mode.\n" 6985 ('"{\n \"format_version\": \"gmic_json_1.0\",\n \"gmic_version\": \""${-strver}"\",\n \"categories\": [\n"') 6986 6987 current_category= 6988 N={$_nbfilters-1} 6989 repeat $_nbfilters,f 6990 e[] "\r >> "$_vt100_c[#$f/$N]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 6991 6992 # Manage categories. 6993 0 nm. {`s=['${_f${f}_path}'];s[0,size(s)-1]`} _parse_gui_json[] {b} path=${} rm. 6994 if ['$current_category']!=['$path'] 6995 if ['$current_category']!=0 ('" ]\n },\n"') fi 6996 ('" {\n"') 6997 ('" \"name\": \""$path"\", \"filters\": [\n"') 6998 current_category=$path 6999 else 7000 if i[-1,2]==_'\n' z. 0,{w-2} fi 7001 ('",\n"') 7002 fi 7003 7004 # Filter definition. 7005 _parse_gui_json[] ${_f${f}_name} fname=${} 7006 7007 locale=en 7008 if narg(${_f${f}_locale}) locale=${_f${f}_locale} fi 7009 7010 ('" {\n \"name\": \""$fname"\", \"lang\": \""$locale"\", \"command\": \""${_f${f}_command}"\", "\ 7011 "\"command_preview\": \""${_f${f}_commandpreview}"\", \"parameters\": [\n"') 7012 7013 sepf={`$<?_',':0`} 7014 ppos=1 7015 repeat ${_f${f}_nbparams},p 7016 _parse_gui_json ${_f${f}_p{$p}_name} name={/${}} 7017 type=${_f${f}_p{$p}_type} 7018 nbargs=${_f${f}_p{$p}_nbargs} 7019 arg0= repeat $nbargs ('${_f${f}_p${p}_a$>}') autocrop. {'\"'} _parse_gui_json {t} arg$>=${} rm. done 7020 sepp={`$<?_',':0`} 7021 if narg(${_f${f}_p{$p}_visibility}) 7022 visibility=", \"visibility\": \""${_f${f}_p{$p}_visibility}"\"" 7023 else 7024 visibility= 7025 fi 7026 7027 if ['$type']=='bool' 7028 if lowercase(['$arg0'])=='false' arg0=0 elif lowercase(['$arg0'])=='true' arg0=1 elif !isnum($arg0) arg0=0 fi 7029 ('" { \"type\": \"bool\", \"name\": \""$name"\", \"default\": \""$arg0"\", \"pos\": "\ 7030 "\""$ppos"\""$visibility" }"$sepp\n') 7031 ppos+=1 7032 7033 elif ['$type']=='button' 7034 if narg($arg0) alignment=", \"alignment\": \""$arg0"\"" else alignment= fi 7035 ('" { \"type\": \"button\", \"name\": \""$name"\""$alignment", \"pos\": \""$ppos"\""$visibility" }"\ 7036 $sepp\n') 7037 ppos+=1 7038 7039 elif ['$type']=='choice' 7040 default=0 n=0 choices= 7041 l[] if isnum($arg0)&&isint($arg0) default=$arg0 n+=1 fi onfail endl 7042 c= repeat $nbargs-$n,a choices.=${c}"\""$>"\": \""${arg{$n+$a}}"\"" c=", " done 7043 ('" { \"type\": \"choice\", \"name\": \""$name"\", \"default\": \""$default"\", \"pos\": \""$ppos"\", "\ 7044 "\"choices\": { "$choices" }"$visibility" }"$sepp\n') 7045 ppos+=1 7046 7047 elif ['$type']=='color' 7048 if $nbargs==1" && "['$arg0'][0]==_'#' # Convert colors specified as '#RRGGBB[AA]' 7049 l[] ('$arg0') autocrop. {'#'} s x,-2 nbargs=$! repeat $!,a hex2dec {$>,t} arg$a=${} done rm endl 7050 fi 7051 args= c= repeat $nbargs,a args.=$c${arg$a} c="," done 7052 ('" { \"type\": \"color\", \"name\": \""$name"\", \"default\": \""$args"\", \"pos\": "\ 7053 "\""$ppos"\""$visibility" }"$sepp\n') 7054 ppos+=$nbargs 7055 7056 elif s=['$type'];s=='int' 7057 ('" { \"type\": \"int\", \"name\": \""$name"\", \"default\": \""$arg0"\", \"min\": \""$arg1"\", "\ 7058 "\"max\": \""$arg2"\", \"pos\": \""$ppos"\""$visibility" }"$sepp\n') 7059 ppos+=1 7060 7061 elif s=['$type'];s=='float' 7062 ('" { \"type\": \"float\", \"name\": \""$name"\", \"default\": \""$arg0"\", \"min\": \""$arg1"\", "\ 7063 "\"max\": \""$arg2"\", \"pos\": \""$ppos"\""$visibility" }"$sepp\n') 7064 ppos+=1 7065 7066 elif ['$type']=='file'" || "['$type']=='filein'" || "['$type']=='fileout' 7067 ('" { \"type\": \"file\", \"name\": \""$name"\", \"default\": \""{/$arg0}"\", \"pos\": "\ 7068 "\""$ppos"\""$visibility" }"$sepp\n') 7069 ppos+=1 7070 7071 elif ['$type']=='folder' 7072 ('" { \"type\": \"folder\", \"name\": \""$name"\", \"default\": \""{/$arg0}"\", \"pos\": "\ 7073 "\""$ppos"\""$visibility" }"$sepp\n') 7074 ppos+=1 7075 7076 elif ['$type']=='link' 7077 align=-1 name= url= n=0 7078 l[] if isnum($arg0) align=$arg0 n+=1 fi onfail endl 7079 if $nbargs-$n>1 name=${arg$n} url=${arg{$n+1}} 7080 else url,name=${arg$n} 7081 fi 7082 if $align==0 align=left elif $align==1 align=right else align=center fi 7083 ('" { \"type\": \"link\", \"name\": \""$name"\", \"url\": \""{/$url}"\", \"align\": "\ 7084 "\""$align"\""$visibility" }"$sepp\n') 7085 7086 elif ['$type']=='note' 7087 ('" { \"type\": \"note\", \"text\": \""{/$arg0}"\""$visibility" }"$sepp\n') 7088 7089 elif ['$type']=='point' 7090 ('" { \"type\": \"point\", \"name\": \""$name"\", \"position\": \""$arg0,$arg1"\", \"pos\": "\ 7091 "\""$ppos"\""$visibility" }"$sepp\n') 7092 ppos+=2 7093 7094 elif ['$type']=='separator' 7095 ('" { \"type\": \"separator\""$visibility" }"$sepp\n') 7096 7097 elif ['$type']=='text' 7098 ('" { \"type\": \"text\", \"name\": \""$name"\", \"default\": \""{/$arg0}"\", \"pos\": "\ 7099 "\""$ppos"\""$visibility" }"\ 7100 $sepp\n') 7101 ppos+=1 7102 7103 elif ['$type']=='value' 7104 ('" { \"type\": \"value\", \"value\": \""{/$arg0}"\", \"pos\": \""$ppos"\""$visibility" }"$sepp\n') 7105 ppos+=1 7106 7107 else # Unknown parameter 7108 ('" { \"type\": \"unknown\", \"name\": \""$name"\""$visibility" }"$sepp\n') 7109 fi 7110 7111 done 7112 ('" ]\n }\n"') 7113 done 7114 if ['$current_category']!=0 ('" ]\n }\n"') fi 7115 ('" ]\n}\n"') 7116 y a y html2utf8 7117 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 7118 7119_parse_gui_json : 7120 l[] 7121 ('{/"$*"}') 7122 replace_str "\\","\\\\" 7123 replace_str "\n","\\n" 7124 replace_str "\r","\\r" 7125 replace_str "\"","\\\"" 7126 replace_str "&","&" 7127 replace_str " "," " 7128 replace_str. "<i>","" 7129 replace_str. "</i>","" 7130 replace_str. "<b>","" 7131 replace_str. "</b>","" 7132 replace_str. "<small>","" 7133 replace_str. "</small>","" 7134 u {t} rm. 7135 onfail u "" endl 7136 7137# 7138# Implements 'gmicol' mode for command 'parse_gui'. 7139# 7140parse_gui_parseparams_gmicol : u 1 # Tell parser to parse filter parameters 7141parse_gui_trigger_gmicol : 7142 repeat $! l[$>] # Keep only 1-level folders 7143 nm {`s=[['{n}'],0];p=find(s,_'/',size(s)-1,0);p>=0?(p=find(s,_'/',p-1,0);p>0?copy(s,s[p+1],size(s)-p));s`} 7144 endl done 7145 sort_list +,n 7146 7147parse_gui_gmicol : 7148 e[] " >> Generate output, in 'gmicol' mode.\n" 7149 ('"<?xml version=\"1.0\"?>\n\n<categories>\n"') 7150 7151 current_category= 7152 N={$_nbfilters-1} 7153 repeat $_nbfilters,f 7154 e[] "\r >> "$_vt100_c[#$f/$N]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 7155 7156 # Manage categories. 7157 0 nm. {`s=['${_f${f}_path}'];s[0,size(s)-1]`} ('{b}') _gmd_ascii2html. path={t} rm[-2,-1] 7158 if ['$current_category']!=['$path'] 7159 if ['$current_category']!=0 ('"\n</category>\n"') fi 7160 ('"\n<!-- Category: "$path" -->\n<category name=\""$path"\">\n"') 7161 current_category=$path 7162 fi 7163 7164 # Filter definition. 7165 ('${_f${f}_name}') _gmd_ascii2html. fname={t} rm. 7166 7167 locale=en 7168 if narg(${_f${f}_locale}) locale=${_f${f}_locale} fi 7169 zoom_factor= 7170 if narg(${_f${f}_zoomfactor}) zoom_factor=" zoom_factor=\""${_f${f}_zoomfactor}"\"" fi 7171 zoom_accurate= 7172 if ${_f${f}_zoomaccurate}!=0 zoom_accurate=" zoom_accurate=\""${_f${f}_zoomaccurate}"\"" fi 7173 7174 ('"\n <!-- Filter: "$fname" -->\n"\ 7175 " <filter name=\""$fname"\" command=\""${_f${f}_command}"\" preview_command=\""${_f${f}_commandpreview}"\""\ 7176 $zoom_factor" "$zoom_accurate\ 7177 ">\n"') 7178 7179 sepf={`$<?_',':0`} 7180 repeat ${_f${f}_nbparams},p 7181 ({'${_f${f}_p{$p}_name}'}) _gmd_ascii2html. name={t} rm. 7182 type=${_f${f}_p{$p}_type} 7183 nbargs=${_f${f}_p{$p}_nbargs} 7184 arg0= repeat $nbargs ('${_f${f}_p${p}_a$>}') autocrop. {'\"'} _gmd_ascii2html. arg$>={/{t}} rm. done 7185 sepp={`$<?_',':0`} 7186 7187 visibility=${_f${f}_p{$p}_visibility} 7188 if !narg($visibility) visibility=1 fi 7189 if $visibility!=1 visibility=" visibility=\""$visibility"\"" else visibility= fi 7190 7191 responsivity=${_f${f}_p{$p}_responsivity} 7192 if !narg($responsivity) responsivity=1 fi 7193 if $responsivity!=1 responsivity=" responsivity=\""$responsivity"\"" else responsivity= fi 7194 7195 if ['$type']=='bool' 7196 if lowercase(['$arg0'])=='false' arg0=0 elif lowercase(['$arg0'])=='true' arg0=1 elif !isnum($arg0) arg0=0 fi 7197 ('" <bool name=\""$name"\" value=\""$arg0"\""$responsivity$visibility"/>\n"') 7198 7199 elif ['$type']=='button' 7200 if !$nbargs arg0=0.5 fi 7201 ('" <button name=\""$name"\" alignment=\""$arg0"\""$responsivity$visibility"/>\n"') 7202 7203 elif ['$type']=='choice' 7204 default=0 n=0 choices= 7205 l[] if isnum($arg0)&&isint($arg0) default=$arg0 n+=1 fi onfail endl 7206 ('" <choice name=\""$name"\" value=\""$default"\""$responsivity$visibility">\n"') 7207 repeat $nbargs-$n,a 7208 choice=${arg{$n+$a}} 7209 ('" <item name=\""$choice"\"/>\n"') 7210 done 7211 ('" </choice>\n"') 7212 7213 elif ['$type']=='color' 7214 if $nbargs==1" && "['$arg0'][0]==_'#' # Convert colors specified as '#RRGGBB[AA]' 7215 l[] ('$arg0') autocrop. {'#'} s x,-2 nbargs=$! repeat $!,a hex2dec {$>,t} arg$a=${} done rm endl 7216 fi 7217 if $nbargs>3 7218 ('" <rgba name=\""$name"\" red=\""$arg0"\" green=\""$arg1"\" blue=\""$arg2"\" alpha=\""$arg3"\""\ 7219 $responsivity$visibility"/>\n"') 7220 else 7221 ('" <rgb name=\""$name"\" red=\""$arg0"\" green=\""$arg1"\" blue=\""$arg2"\""\ 7222 $responsivity$visibility"/>\n"') 7223 fi 7224 7225 elif s=['$type'];s=='int' 7226 ('" <int name=\""$name"\" value=\""$arg0"\" min=\""$arg1"\" max=\""$arg2"\""\ 7227 $responsivity$visibility"/>"\n') 7228 7229 elif s=['$type'];s=='float' 7230 ('" <float name=\""$name"\" value=\""$arg0"\" min=\""$arg1"\" max=\""$arg2"\""\ 7231 $responsivity$visibility"/>"\n') 7232 7233 elif ['$type']=='file'" || "['$type']=='filein'" || "['$type']=='fileout' 7234 ('" <file name=\""$name"\" value=\""$arg0"\""$responsivity$visibility"/>\n"') 7235 7236 elif ['$type']=='folder' 7237 ('" <folder name=\""$name"\" value=\""$arg0"\""$responsivity$visibility"/>\n"') 7238 7239 elif ['$type']=='link' 7240 align=0 name= url= n=0 7241 l[] if isnum($arg0) align=$arg0 n+=1 fi onfail endl 7242 if $nbargs-$n>1 name=${arg$n} url=${arg{$n+1}} 7243 else url,name=${arg$n} 7244 fi 7245 ('" <link name=\""$name"\" href=\""$url"\" alignment=\""$align"\""$visibility"/>\n"') 7246 7247 elif ['$type']=='note' 7248 ('" <note name=\""$name"\""$visibility">\n"$arg0"\n </note>"\n') 7249 7250 elif ['$type']=='point' 7251 if narg($arg2) removable=" removable=\""$arg2"\"" else removable= fi 7252 if narg($arg3) burst=" burst=\""$arg3"\"" else burst= fi 7253 if narg($arg4) red=" red=\""$arg4"\"" else red= fi 7254 if narg($arg5) green=" green=\""$arg5"\"" else green= fi 7255 if narg($arg6) blue=" blue=\""$arg6"\"" else blue= fi 7256 if narg($arg7) alpha=" alpha=\""$arg7"\"" else alpha= fi 7257 if narg($arg8) radius=" radius=\""$arg8"\"" else radius= fi 7258 ('" <point name=\""$name"\" x=\""$arg0"\" y=\""$arg1"\""$removable$burst$red$green$blue$alpha\ 7259 $responsivity$visibility"/>\n"') 7260 7261 elif ['$type']=='separator' 7262 ('" <separator"$visibility"/>\n"') 7263 7264 elif ['$type']=='text' 7265 multiline=0 n=0 7266 l[] if isnum($arg0) multiline=$arg0 n+=1 fi onfail endl 7267 ('" <text name=\""$name"\" multiline=\""$multiline"\""\ 7268 $responsivity$visibility">"') 7269 if ['${arg$n}']!=0 7270 if $multiline ('\n${arg$n}\n</text>\n') else ('${arg$n}</text>\n') fi 7271 else ('"</text>\n"') fi 7272 7273 elif ['$type']=='value' 7274 ('" <value name=\""$name"\" value=\""$arg0"\"/>\n"') 7275 7276 else # Unknown parameter 7277 ('" <unknown name=\"$name\"/>\n"') 7278 fi 7279 7280 done 7281 ('" </filter>\n"') 7282 done 7283 if ['$current_category']!=0 ('"\n</category>\n"') fi 7284 ('"\n</categories>"') 7285 y a y html2utf8 7286 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 7287 7288# 7289# Implements 'strings' mode for command 'parse_gui'. 7290# (Extract all strings from filters, for translation purpose, and put them in a .csv file format). 7291# 7292parse_gui_strings : 7293 e[] " >> Generate output, in 'strings' mode.\n" 7294 N={$_nbfilters-1} 7295 repeat $_nbfilters,f 7296 if !narg(${_f${f}_locale})" && "find(['${_f${f}_path}'],'Testing/')<0 # Consider only English, non-Testing filters 7297 e[] "\r >> "$_vt100_c[#$f/$N]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 7298 _parse_gui_strings ${_f${f}_name} 7299 repeat ${_f${f}_nbparams},p 7300 type=${_f${f}_p${p}_type} 7301 if s=['$type'];s!='link'&&s!='note'&&s!='separator'&&s!='value' _parse_gui_strings ${_f${f}_p${p}_name} fi 7302 if ['$type']==['choice'] 7303 repeat ${_f${f}_p${p}_nbargs},a 7304 arg=${_f${f}_p${p}_a${a}} 7305 l[] if !isnum($arg) ({'$arg'}) discard. {'\"'} arg={t} rm. _parse_gui_strings $arg fi onfail endl 7306 done 7307 fi 7308 done 7309 fi 7310 done 7311 # Sort strings and remove duplicates. 7312 sort_list +,N repeat $!-1 i,ni={[$<,$<+1]} if ['{$i,n}']==['{$ni,n}'] +[$i,$ni] fi done sort_list -,i 7313 7314 # Generate output in commented .ts format. 7315 repeat $! l[$>] 7316 nm={n} 7317 ({'$nm" , "'}:y) k. nm $nm 7318 endl done 7319 if $! y i[1--1] (10) a y else 0 fi 7320 7321_parse_gui_strings : 7322 str="$*" 7323 if size(['$str'])>2 l[] 7324 if !isexpr($str) 7325 ({'$str'}) replace_str. "---","-" replace_str. "--","-" str={t} rm. 7326 (1) nm. $str 7327 fi 7328 onfail endl fi 7329 7330#@cli pass : _shared_state={ -1=status only | 0=non-shared (copy) | 1=shared | 2=adaptive } : (+) 7331#@cli : Insert images from parent context of a custom command or a local environment. 7332#@cli : Command selection (if any) stands for a selection of images in the parent context. 7333#@cli : By default (adaptive shared state), selected images are inserted in a shared state if they do not belong 7334#@cli : to the context (selection) of the current custom command or local environment as well. 7335#@cli : Typical use of command 'pass' concerns the design of custom commands that take images as arguments. 7336#@cli : This commands return the list of corresponding indices in the status. 7337#@cli : Default value: 'shared_state=2'. 7338#@cli : $ command "average : pass$""1 add[^-1] [-1] remove[-1] div 2" sample ? +mirror y +average[0] [1] 7339 7340#@cli plot : _plot_type,_vertex_type,_xmin,_xmax,_ymin,_ymax,_exit_on_anykey={ 0 | 1 } : \ 7341# 'formula',_resolution>=0,_plot_type,_vertex_type,_xmin,xmax,_ymin,_ymax,_exit_on_anykey={ 0 | 1 } : (+) 7342#@cli : Display selected images or formula in an interactive viewer (use the instant display window [0] if opened). 7343#@cli : 'plot_type' can be { 0=none | 1=lines | 2=splines | 3=bar }. 7344#@cli : 'vertex_type' can be { 0=none | 1=points | 2,3=crosses | 4,5=circles | 6,7=squares }. 7345#@cli : 'xmin', 'xmax', 'ymin', 'ymax' set the coordinates of the displayed xy-axes. 7346#@cli : Default values: 'plot_type=1', 'vertex_type=1', 'xmin=xmax=ymin=ymax=0 (auto)' and 'exit_on_anykey=0'. 7347 7348#@cli p : eq. to 'print'. : (+) 7349 7350#@cli print : (+) 7351#@cli : Output information on selected images, on the standard error (stderr). 7352#@cli : (eq. to 'p'). 7353#@cli : When invoked with a '+' prefix (i.e. '+print'), the command output its message on stdout rather than stderr. 7354 7355#@cli random_pattern : _width>0,_height>0,_min_detail_level>=0 7356#@cli : Insert a new RGB image of specified size at the end of the image list, rendered with a random pattern. 7357#@cli : Default values: 'width=height=512' and 'min_detail_level=2'. 7358#@cli : $ repeat 6 random_pattern 256 done 7359+random_pattern : check "isint(${1=512}) && $1>0 && isint(${2=$1}) && $2>0 && ${3=2}>=0" 7360 e[^-1] "Generate a RGB image $1x$2, with a random pattern." 7361 m "rgb2rgb:" 7362 7363 # Generate the 3 channels independently. 7364 repeat 3 7365 do 7366 expr="z = [ "{u(20)}"*((x+0.5)/w-0.5), "{u(20)}"*((y+0.5)/h-0.5) + 0.5/h ]; "${-_random_pattern_expr} 7367 {round([$1,$2]*128/min($1,$2))},1,2,*$expr 7368 replace_naninf. 0 norm. n. 0,255 equalize. 256 c. 0,255 7369 cond=${-_random_pattern_check_image.\ $3} 7370 if !$cond rm. fi 7371 while !$cond 7372 rm. $1,$2,1,2,*$expr 7373 replace_naninf. 0 norm. n. 0,255 equalize. 256 c. 0,255 7374 done 7375 a[-3--1] c 7376 7377 # Convert result from random colorspace to RGB. 7378 ${"arg "{1+int(u(6))%6}",ycbcr2rgb,hsi82rgb,hsl82rgb,hsv82rgb,lab82rgb,rgb2rgb"}. 7379 7380 # Local normalization in random colorspace. 7381 ac. "normalize_local {[u(2,15),u(2,max(w,h)/2)]}",${"arg "{1+int(u(4))%4}",lab_l,ycbcr_y,hsl_l,rgb"} 7382 7383 # Random color balance. 7384 ac. "*. '[{u([0.25,0.25,0.25],[2,2,2])}]'",${"arg "{1+int(u(6))%6}",lab,ycbcr,hsi,hsl,hsv,rgb"} 7385 7386 # Equalize 7387 +equalize. 256 j.. .,0,0,0,0,{u(0.25,1)} rm. n. 0,255 7388 um rgb2rgb nm random_pattern 7389 7390# $1 : probability of a termination node in [0,1] 7391# $2 : level of recursion (avoid stack overflow due to recursivity) 7392_random_pattern_expr : skip "${1=0},${2=0}" 7393 nl={$2+1} 7394 if (u<$1" && "$2>1)" || "$2>6 # Termination node 7395 r={u} 7396 if $r<0.75 u z 7397 else u [{_round(u([-1,-1],[1,1]),0.1)}] 7398 fi 7399 else # Function or operator 7400 p1,p2={[$1,$1]+u([0.2,0.2])} 7401 r={u(27)} 7402 if $r<1 u ccos(${$0\ $p1,$nl}) 7403 elif $r<2 u csin(${$0\ $p1,$nl}) 7404 elif $r<3 u ctan(${$0\ $p1,$nl}) 7405 elif $r<4 u ccosh(${$0\ $p1,$nl}) 7406 elif $r<5 u csinh(${$0\ $p1,$nl}) 7407 elif $r<6 u ctanh(${$0\ $p1,$nl}) 7408 elif $r<7 u cexp(${$0\ $p1,$nl}) 7409 elif $r<8 u clog(${$0\ $p1,$nl}) 7410 elif $r<9 u [cabs(${$0\ $p1,$nl}),0] 7411 elif $r<10 u [0,cabs(${$0\ $p1,$nl})] 7412 elif $r<11 u [carg(${$0\ $p1,$nl}),0] 7413 elif $r<12 u [0,carg(${$0\ $p1,$nl})] 7414 elif $r<13 u cconj(${$0\ $p1,$nl}) 7415 elif $r<14 u (${$0\ $p1,$nl})+(${$0\ $p2,$nl}) 7416 elif $r<15 u (${$0\ $p1,$nl})-(${$0\ $p2,$nl}) 7417 elif $r<16 u ${$0\ $p1,$nl}**${$0\ $p2,$nl} 7418 elif $r<17 u ${$0\ $p1,$nl}//${$0\ $p2,$nl} 7419 elif $r<18 u (${$0\ $p1,$nl})^^0.5 7420 elif $r<19 u (${$0\ $p1,$nl})^^2 7421 elif $r<20 u (${$0\ $p1,$nl})^^3 7422 elif $r<21 u ${$0\ $p1,$nl}*${$0\ $p2,$nl} 7423 elif $r<22 u ${$0\ $p1,$nl}/(0.01+cabs(${$0\ $p2,$nl})) 7424 elif $r<23 u abs(${$0\ $p1,$nl})^0.5 7425 elif $r<24 u (${$0\ $p1,$nl})^2 7426 elif $r<25 u [(${$0\ $p1,$nl})[0],0] 7427 elif $r<26 u [0,(${$0\ $p1,$nl})[1]] 7428 else u (${$0\ $p1,$nl})^3 7429 fi 7430 fi 7431 7432# Check that rendered image has enough details in it. 7433# $1 = Minimum detail level. 7434_random_pattern_check_image : 7435 cond=1 7436 +s. xy,4 7437 l[^0] 7438 repeat $! if $cond l[$>] 7439 gradient_norm. 7440 if ic<$1 cond=0 fi 7441 endl fi done 7442 rm 7443 endl 7444 u $cond 7445 7446#@cli screen : _x0[%],_y0[%],_x1[%],_y1[%] : (+) 7447#@cli : Take screenshot, optionally grabbed with specified coordinates, and insert it 7448#@cli : at the end of the image list. 7449 7450#@cli select : feature_type,_X[%]>=0,_Y[%]>=0,_Z[%]>=0,_exit_on_anykey={ 0 | 1 },_is_deep_selection={ 0 | 1 } : (+) 7451#@cli : Interactively select a feature from selected images (use the instant display window [0] if opened). 7452#@cli : 'feature_type' can be { 0=point | 1=segment | 2=rectangle | 3=ellipse }. 7453#@cli : Arguments 'X','Y','Z' determine the initial selection view, for 3D volumetric images. 7454#@cli : The retrieved feature is returned as a 3D vector (if 'feature_type==0') or as a 6d vector 7455#@cli : (if 'feature_type!=0') containing the feature coordinates. 7456#@cli : Default values: 'X=Y=Z=(undefined)', 'exit_on_anykey=0' and 'is_deep_selection=0'. 7457 7458#@cli serialize : _datatype,_is_compressed={ 0 | 1 },_store_names={ 0 | 1 } : (+) 7459#@cli : Serialize selected list of images into a single image, optionnally in a compressed form. 7460#@cli : 'datatype' can be { auto | uchar | char | ushort | short | uint | int | uint64 | int64 | float | double }. 7461#@cli : Specify 'datatype' if all selected images have a range of values constrained to a particular datatype, 7462#@cli : in order to minimize the memory footprint. 7463#@cli : The resulting image has only integers values in [0,255] and can then be saved as a raw image of 7464#@cli : unsigned chars (doing so will output a valid .cimg[z] or .gmz file). 7465#@cli : If 'store_names' is set to '1', serialization uses the .gmz format to store data in memory 7466#@cli : (otherwise the .cimg[z] format). 7467#@cli : Default values: 'datatype=auto', 'is_compressed=1' and 'store_names=1'. 7468#@cli : $ image.jpg +serialize uchar +unserialize[-1] 7469 7470#@cli shape_circle : _size>=0 7471#@cli : Input a 2D circle binary shape with specified size. 7472#@cli : Default value: 'size=512'. 7473#@cli : $ shape_circle , 7474+shape_circle : check "${1=512}>=0" 7475 e[^-1] "Input a $1x$1 circle binary shape." 7476 ir={round($1)} 7477 if !$ir 0 7478 elif $ir<2 $ir,$ir,1,1,1 7479 else 7480 {int($ir/2)+($ir%2)},{int($ir/2)+($ir%2)} =. 1,100%,100% 7481 distance. 1 <=. {(i+0.4)/sqrt(2)} 7482 +mirror. x 7483 if $ir>1" && "($ir%2) r. {w-1},100%,1,1,0,0,1 fi 7484 a[-2,-1] x +mirror. y 7485 if $ir>1" && "($ir%2) r. 100%,{h-1},1,1,0,0,0,1 fi 7486 a[-2,-1] y 7487 fi 7488 nm. "[2D circle shape]" 7489 7490#@cli shape_cupid : _size>=0 7491#@cli : Input a 2D cupid binary shape with specified size. 7492#@cli : Default value: 'size=512'. 7493#@cli : $ shape_cupid , 7494+shape_cupid : check "${1=512}>=0" 7495 e[^-1] "Input a $1x$1 cupid binary shape." 7496 ir={round($1)} 7497 if !$ir 0 7498 else 7499 base642img[] \ 7500"MiBzaG9ydCBsaXR0bGVfZW5kaWFuCjEgMjMwMSAxIDEgIzI2NDQKeJx1mOl3lEUWxm+n6aS7IUSQRQQEFA37FtkFVFAEBxHZEoKACwRQEUHU0fGM58y"\ 7501"Zxa9z5i9AFBAhAZKwg8qACMM6CDgZIIQ9Kx0CmAHqzq/u2yR80A91nue5daveWm5tb2moNBSSkAiptCoq9RqToa6p3NVmMtyli2pzecp1IHWUke6R30"\ 7502"wjyB9hfh0o97AMIw11D8kQ0mDXRga6VpLlWsoA10L6uQzpQ909XVy6u6hkulTp6lJkyamw1GhTGc33b2iGHHYR+RT8RVvIUReThKbI3+H/0wflGD512"\ 7503"kT+oa3EaRt0M7mlEanFZ4X2QqdTLiLX8flK+5i+rWn36eb0MYqOyErT7eBp8rX2gz8Ej9H3iGww3Y5vZRg/QztvaqMuox13tAvpAdMX3JO0J+CX3AuG"\ 7504"l904wytuvOFV9yLYF5wgG8Fy9xK6j1S4iWBvcBL23lLpXkH3kio3Bd1Tqt10sIdcczOkULtLws0Eu4GzwEypdbPJfxx8S3aC190i2aWPge+iu0idW4r"\ 7505"uJDfcMvARuek+Ajsa7tT24O9lB33zuE3b4rdY1mtrw3zGPFtTZbm+K9/Qv+mM1Re6iPFKl2mM1Qp9R1Yxd1NJX8FXYptCDK2Ef0m5yfitgtcy7qsNMy"\ 7506"i7iLY9IGsMW1Cvx5aylm94XGfYSgp0seF6w9aMyWLKt6HP76HbShFYCxaDCXCTYTvZqksYq4fp01KwA31dKjXE6ff6PthZ9uoyxrSL7AOr3KNyQD9gz"\ 7507"B+Tg2CFe1yOGHaTf4Plrrv8BNYRq7eZi1OUqSN+7zJPJfCDGpJu6tdNXzmDPqRh6aHPShn8MDHXQ5+Ti8bD0l3HyiXa4u3ddZxcpT2ed9PxUtHAX5RK"\ 7508"fA4Z/51UJXkmvJp+HYQ/Aa+BH2J8M3WCXKPfB+GPUzbgacYTxmNWNsGYHqSdmWb3vBn1jIcvop4IcZzKfKbKSdp1Td+2b9ajsyl/ClsC22H8/NrKoew"\ 7509"p+pLQt8x2kzSDeT6lz1N2ofWjDlsue8hJ+p/QBeZXR30ziaEy2ndXx7BmA3st9le1JWPzstmOoBPYX2WNXzHbfPOrwT6LuKzQSazT+dbGauqaTcxW6S"\ 7510"vUH/hVYZtDPNckbUewVZjtYeoNbEepqxzba8R/gvoCW4Q5iWLrQP3etoAYiMhlK8v60Yn2XW+7ZGUfZe+ZSPvyiJGIXKDOOdqVcXuJdr0hJ7CVYZvNG"\ 7511"r3DHFToa4xRRErN70O+P0d+hp81/QHfno2OEEdpDboE/V+rY5lpz0tMv8/YzEJHrIzXl3Wm6VM2TkvJD/RJ00tMn0afsDFbgn8uuokct/F/j/wZfDsV"\ 7512"nYZenNQROYYtlzi5ojmWf9Ri4B3ak2Nt9/P1BvFdT4xc1Wwr42NzHrFzhxgpT/p5W55+zDjk2Bj8i7RAPyHefX6EdRjoqqT/ftJC/QPzOMP8f2zQgf8"\ 7513"+2vkW+lpS7yXf60SyfKA/RU+3Nv2zIT+Vto4z2+5knSU60vq2O9mGEh1h+rsGPczG8lvrwyeM21Cbi2+tn38iHoaY3kWb5uqf6fNg0ztIb+pf6GOjfl"\ 7514"3/RhsCvd3m/nNibbDVv83m5nPiKsj3eib+9ejT6C2kHP0r6yf4ntfT9VvL22zzcMD4JvvuAfPZRB3zdCfnZ5rpYjAPfRheZHyH7QGFxrfbPN3j3mej8"\ 7515"W3GN1hdW22drbe+brH59/xN3ZTkUfpY1GCfpRtsvRVYXwosnvLh2bqWtRTwV3QVa8jzKGdJAeOdZvbp1FkKrjP/rbae1uGTQ9sumD3K3rPL1uhaUo5+"\ 7516"RwymwqP4f0+sRThfPP/B5t3bp+t+1nLApzJGt5I+U+D1ST4Jfsd4TCbC1fxj8rz+aPgcuA4co/usnjGmozIazDfcT39jhuvBZ8ENGpdnwI3oUfgVgk9"\ 7517"RvhgcqLuZv7hk0eYt6CzdQ2x4/IEz2tv3c341Bc/JfwyvyDn24QFazvmSDlYRcxnST6tZHy05XyroV2swHuqhTUMlrPOpmh46Q53Z2jp0mTpytHPoOn"\ 7518"t0rj4Rus39aoYOD03WJqGb+gTndkqoWjszJimh89QzWUOhMvZjj+eo/2VV5iVDxuovrLV0xuMW6yVOf2/anvU02IbUWuukhV6TGO2N6iVJ1YvSRM9Lm"\ 7519"BTSUql3P8stt4+7Uzr3j48Z8xhzlsk5wz3PfWjzcZF23EDXOn9OtSD2s8kPs889wNqPc89qTmxPw5ZCrMe5fzWFT6P/IcY2Lhe5a966Tx/nPnXP99e4"\ 7520"n4+fXHbSPyYnuHcFPjE56XIb/Eu4f93zP+3mWJu8zxn3GmUD/7PudePe55x7Ax74lLk3OTe9PSrn3dwkj9HWeQ38ksuDh83H8xtJ+xU3v4FfdQuMF+F"\ 7521"T7hbCw2avuI9Xci+sS/r/Fq9yb8ODtnl+Pdn+Knxqf4VX41OL/+Yk93f0+/kWxqcGfs14jLhPI969DnM/8+unOfW8TaymmB5LTG1J6m2UHUfMbeXsqM"\ 7522"bfr4Px+hD2Rj2BM3o7ugr/Hfjncj9u1DH2md7gQvbdMOsnxnnWp0Hvwn8W97VGHUP3x28BayiFPT3OHjwgqcOcAT7f6/nsLWHWoc/PQuex76SgfX6j3"\ 7523"m35T1JvHudCmHPH5z9JvXnEclj2WHsGYl8g5/G/p/fR/zL0Xmv/IM7DRaZ/QOey3x/izC2l/I/W3zGss0Wm96NzuHuVcmafxX+/rfEXqHsxazKFemKs"\ 7524"/Qj311Gc4Uuwhbn/xeUFzrxK7g1eH0I/j67mnnGaMofRY/BPcE/xdRxBP82ZeF0/Mv9j6BE6nJj5mG+G2cfjMpgz6iZno/c/jh5An3/hbPX+J9D90PW"\ 7525"cx2dt7TaVPujb+kfrw8/oXui7+pn1we9xPbTYfE+zz3WDe78zdm8tMn4Wn65w7+/3wke10Ph59pLOcO9zEXtH3Wj8Mrw93Ptcxacd55Ln5fC2ut54Jb"\ 7526"wV3PvXEKMtOYu8PQHP0Hzj19n30nWd8Trs8SS/RdlUzjTP6+Fh/cbafwcuugb+oDj3NdhCbrvVYHP2vlVgnHfLV2CU9fOl3V0qDbmPui/AJuxxcxmrI"\ 7527"cYv2v4yyOo+z9vvBrHj+Tn2plp4Kd8/w15Ww3hudZPpU5Zs5s15mRgu5k16gVjf4J6hTD/Jd8MY676y1vVlzvvIN64r8dhb1vCe2swbdDXvsULePavY"\ 7528"YwvAlbx91rLWVrgmvON6yATXm/MsLMvdAOI5zf4jrOQtvIc+3WF+VruBxHMz+5+wxg0iljvyrcGG+W4IeR2lwA1Fd6JNw5I4FHsnKXTDkziM+h4x3I1"\ 7529"/Efj9fVgMfsd+UES5Xdzni8Gd3PWLqH8774BivreV/aOI72/WNobFnGVFtG0j+04h7d0AFoEFnCke19HeIpfFG7UZ5bN4z0bx6897N9X0cuZhEzgN36"\ 7530"mkALNkiqX+Msn1I/WViYzPBNdTXuQdOc5lyljel8/x1hzN+/MZ0tOuk4wijWzA4J9K8D+lvf1PCf6ltLU0iPdvkO7Xngf/XIbw/r2H98r4fzD9eWf3Z"\ 7531"u5GVv4foPOEnDEgMjAgMSAxICMzOQp4nHNn8GWIYmBgSGfIZchkSGaIZzCAQj0gLxMoms5QBZQHAHyqBfY=" 7532 decompress_rle. r. $ir,$ir,1,1,5 if $ir>480 b. 0.2% fi >=. 40% 7533 fi 7534 nm. "[2D cupid shape]" 7535 7536#@cli shape_diamond : _size>=0 7537#@cli : Input a 2D diamond binary shape with specified size. 7538#@cli : Default value: 'size=512'. 7539#@cli : $ shape_diamond , 7540+shape_diamond : check "${1=512}>=0" 7541 e[^-1] "Input a $1x$1 diamond binary shape." 7542 ir={round($1)} 7543 if !$ir 0 7544 elif $ir<2 $ir,$ir,1,1,1 7545 else 7546 {int($ir/2)+($ir%2)},{int($ir/2)+($ir%2)} =. 1,100%,100% 7547 distance. 1,1 <=. {i/2} 7548 +mirror. x 7549 if $ir>1" && "($ir%2) r. {w-1},100%,1,1,0,0,1 fi 7550 a[-2,-1] x +mirror. y 7551 if $ir>1" && "($ir%2) r. 100%,{h-1},1,1,0,0,0,1 fi 7552 a[-2,-1] y 7553 fi 7554 nm. "[2D diamond shape]" 7555 7556#@cli shape_dragon : _size>=0,_recursion_level>=0,_angle 7557#@cli : Input a 2D Dragon curve with specified size. 7558#@cli : Default value: 'size=512', 'recursion_level=18' and 'angle=0'. 7559#@cli : $ shape_dragon , 7560+shape_dragon : check "${1=512}>=0 && ${2=18}>=0" skip "${3=0}" 7561 e[^-1] "Input a $1x$1 Dragon curve, with recursion level $2 and angle $3." 7562 ir={round($1)} 7563 if !$ir 0 7564 else l[] 7565 (0,1^0,0) ind=1 7566 repeat $2 +f "begin(C = I["$ind"]; R = rot(90°)); R*(I - C) + C" ind={2*h} a y done 7567 s c -.. {-2,ia} -. {ia} a c / {max(abs(im),abs(iM))} 7568 angle={$3-atan2(i1,i0)*180/pi} f. "begin(R = rot("$angle"°)); R*I" 7569 n 0,{$1-1} round $1,$1,1,1 eval.. "!x?polygon(#1,2,I(0,y),I(1,y),1,1); I" k. 7570 endl fi 7571 nm. "[2D dragon shape]" 7572 7573#@cli shape_fern : _size>=0,_density[%]>=0,_angle,0<=_opacity<=1,\ 7574# _type={ 0=Asplenium adiantum-nigrum | 1=Thelypteridaceae } 7575#@cli : Input a 2D Barnsley fern with specified size. 7576#@cli : Default value: 'size=512', 'density=50%', 'angle=30', 'opacity=0.3' and 'type=0'. 7577#@cli : $ shape_fern , 7578+shape_fern : check "${1=512}>=0 && ${2=50%}>=0 && isnum(${3=30}) && ${4=0.3}>=0 && $4<=1 && isnum(${5=0})" 7579 e[^-1] "Input a $1x$1 Barnsley fern, with density $2, angle $3 and opacity $4." 7580 ir={round($1)} 7581 if !$ir 0 7582 else l[] 7583 N={${"is_percent $2"}?$ir^2*$2:$2} 7584 $N,1,1,2 7585 eval " 7586 if ($5==0, 7587 # Type 0: Asplenium adiantum-nigrum. 7588 f1 = [ 0,0,0,0.16 ]; g1 = [ 0,0 ]; 7589 f2 = [ 0.2,-0.26,0.23,0.22 ]; g2 = [ 0,1.6 ]; 7590 f3 = [ -0.15,0.28,0.26,0.24 ]; g3 = [ 0,0.44 ]; 7591 f4 = [ 0.85,0.04,-0.04,0.85 ]; g4 = [ 0,1.6 ], 7592 7593 # Type 1: Thelypteridaceae. 7594 f1 = [ 0,0,0,0.25 ]; g1 = [ 0,-0.4 ]; 7595 f2 = [ 0.035,-0.2,0.16,0.04 ]; g2 = [ -0.09,0.02 ]; 7596 f3 = [ -0.04,0.2,0.16,0.04 ]; g3 = [ 0.12,0.07 ]; 7597 f4 = [ 0.95,0.005,-0.005,0.93 ]; g4 = [ -0.002,0.5 ]; 7598 ); 7599 xy = [ 0,0 ]; 7600 repeat ("$N",n, 7601 r = u(100); 7602 xy = r<=1?((f1*xy)+=g1): 7603 r<=8?((f2*xy)+=g2): 7604 r<=15?((f3*xy)+=g3):((f4*xy)+=g4); 7605 I[n] = xy 7606 )" 7607 permute xczy 7608 i.. 2,2,1,1,{"R=rot(-$3°); R[2] = -R[2]; R[3] = -R[3]; R"} m* 7609 repeat 2 sh. $>,$>,0,0 -. {im} rm. done n 0,{$ir-1} 7610 pointcloud -$4 r $ir,$ir,1,1,0,0,0.5,0.5 7611 endl fi 7612 nm. "[2D Barnsley fern]" 7613 7614#@cli shape_gear : _size>=0,_nb_teeth>0,0<=_height_teeth<=100,0<=_offset_teeth<=100,0<=_inner_radius<=100 7615#@cli : Input a 2D gear binary shape with specified size. 7616#@cli : Default value: 'size=512', 'nb_teeth=12', 'height_teeth=20', 'offset_teeth=0' and 'inner_radius=40'. 7617#@cli : $ shape_gear , 7618+shape_gear : check "${1=512}>=0 && isint(${2=12}) && $2>0 && ${3=20}>=0 && $3<=100 && ${4=0}>=0 && $4<=100 && 7619 ${5=40}>=0 && $5<=100" 7620 e[^-1] "Input a $1x$1 gear binary shape with $2 teeth, teeth height $3, teeth offset $4 and inner radius $5." 7621 ir={round($1)} 7622 if !$ir 0 7623 else l[] 7624 $ir,$ir 7625 polygon {" 7626 const nb_teeth = $2; 7627 const height_teeth = $3%; 7628 const offset_teeth = 2*$4%; 7629 ref(vector2048(),pts); 7630 for (i = 0, i<size(pts), 7631 a = i*2*pi/size(pts); 7632 r = 1 - height_teeth + height_teeth*(int(a*nb_teeth/pi + 2*nb_teeth - offset_teeth)%2); 7633 pts[i++] = round(w/2*(1 + r*cos(a))); 7634 pts[i++] = round(h/2*(1 + r*sin(a))); 7635 ); 7636 [size(pts)/2,pts]; 7637 "},1,1 7638 if $5 circle. 50%,50%,{0.5*w*$5%},1,0 fi 7639 endl fi 7640 nm. "[2D gear shape]" 7641 7642#@cli shape_heart : _size>=0 7643#@cli : Input a 2D heart binary shape with specified size. 7644#@cli : Default value: 'size=512'. 7645#@cli : $ shape_heart , 7646+shape_heart : check "${1=512}>=0" 7647 e[^-1] "Input a $1x$1 heart binary shape." 7648 ir={round($1)} 7649 if !$ir 0 7650 else l[] 7651 2048,1,1,1,"t = x*2*pi/w; 16*sin(t)^3" 7652 2048,1,1,1,"t = x*2*pi/w; 13*cos(t) - 5*cos(2*t) - 2*cos(3*t) - cos(4*t)" 7653 a c display_parametric $ir,$ir,1,0,0,0 7654 flood 50%,50%,0,0,0,1,0 ==. 0 7655 endl 7656 fi 7657 nm. "[2D heart shape]" 7658 7659#@cli shape_polygon : _size>=0,_nb_vertices>=3,_angle 7660#@cli : Input a 2D polygonal binary shape with specified geometry. 7661#@cli : Default value: 'size=512', 'nb_vertices=5' and 'angle=0'. 7662#@cli : $ repeat 6 shape_polygon 256,{3+$>} done 7663+shape_polygon : check "${1=512}>=0 && isint(${2=5}) && $2>=3" skip ${3=0} 7664 e[^-1] "Input a $1x$1 polygon binary shape, with $2 vertices and angle $3 deg." 7665 ir={round($1)} 7666 if !$ir 0 7667 else l[] 7668 (0;{2*pi}) + {($3-90)*pi/180} r. 1,{$2+1},1,1,3 rows. 0,{h-2} 7669 ir2={round($ir/2)} 7670 +sin. cos.. 7671 a x n 0,{$ir-1} s x +.. {-2,0.5*($ir-im-iM)} +. {-1,0.5*($ir-im-iM)} a x 7672 $ir,$ir polygon. $2,{-2,^},1,1 rm.. 7673 endl 7674 fi 7675 nm. "[2D $2-polygon shape]" 7676 7677#@cli shape_snowflake : size>=0,0<=_nb_recursions<=6 7678#@cli : Input a 2D snowflake binary shape with specified size. 7679#@cli : Default values: 'size=512' and 'nb_recursions=5'. 7680#@cli : $ repeat 6 shape_snowflake 256,$> done 7681+shape_snowflake : check "${1=512}>=0 && isint(${2=5}) && $2>=0 && $2<=6" 7682 e[^-1] "Input a $1x$1 snowflake binary shape, with $2 recursions." 7683 ir={round($1)} 7684 if !$ir 0 7685 else l[] 7686 $ir,$ir (0;120;240) *. {pi/180} +sin. cos.. a[-2,-1] c 7687 repeat $2 7688 1,{4*h},1,2 7689 f.. " 7690 p0 = I; 7691 p1 = I[(y+1)%h]; 7692 t = (p1 - p0)/3; 7693 pm = (p0 + p1)/2 - 0.866*[ -t[1], t[0] ]; 7694 k = 4*y; 7695 I[#-1,k++] = p0; 7696 I[#-1,k++] = p0 + t; 7697 I[#-1,k++] = pm; 7698 I[#-1,k] = p1 - t; 7699 " 7700 rm.. 7701 done 7702 *. {0.5*$1} +. {$1/2} permute. cyzx polygon.. {h},{^},1,1 rm. 7703 endl fi 7704 nm. "[2D snowflake shape]" 7705 7706#@cli shape_star : _size>=0,_nb_branches>0,0<=_thickness<=1 7707#@cli : Input a 2D star binary shape with specified size. 7708#@cli : Default values: 'size=512', 'nb_branches=5' and 'thickness=0.38'. 7709#@cli : $ repeat 9 shape_star 256,{$>+2} done 7710+shape_star : check "${1=512}>=0 && ${2=5}>0 && ${3=0.5}>=0 && $3<=1" 7711 e[^-1] "Input a $1x$1 star binary shape, with $2 branches and thickness $3." 7712 ir={round($1)} 7713 if !$ir 0 7714 else l[] 7715 star3d $2,$3 col3d 1 c3d n3d *3d $1,$1 7716 $1,$1 j3d. ..,50%,50%,0,1,2 rm.. 7717 endl 7718 fi 7719 nm. "[2D star shape]" 7720 7721#@cli sh : eq. to 'shared'. : (+) 7722 7723#@cli shared : x0[%],x1[%],y[%],z[%],c[%] : y0[%],y1[%],z[%],c[%] : z0[%],z1[%],c[%] : c0[%],c1[%] : c0[%] : \ 7724# (no arg) : (+) 7725#@cli : Insert shared buffers from (opt. points/rows/planes/channels of) selected images. 7726#@cli : Shared buffers cannot be returned by a command, nor a local environment. 7727#@cli : (eq. to 'sh'). 7728#@cli : $ image.jpg shared 1 blur[-1] 3 remove[-1] 7729#@cli : $ image.jpg repeat s shared 25%,75%,0,$> mirror[-1] x remove[-1] done 7730#@cli : $$ https://gmic.eu/oldtutorial/_shared 7731 7732#@cli sp : eq. to 'sample'. 7733+sp : skip "${1=?}",${2=0} 7734 v + _sample[] "$1",${2--1} v - 7735 if !${} noarg fi 7736 7737#@cli sample : _name1={ ? | apples | balloons | barbara | boats | bottles | butterfly | cameraman | car | cat | \ 7738# cliff | chick | colorful | david | dog | duck | eagle | elephant | earth | flower | fruits | gmicky | \ 7739# gmicky_mahvin | gmicky_wilber | greece | gummy | house | inside | landscape | leaf | lena | leno | lion | \ 7740# mandrill | monalisa | monkey | parrots | pencils | peppers | portrait0 | portrait1 | portrait2 | portrait3 | \ 7741# portrait4 | portrait5 | portrait6 | portrait7 | portrait8 | portrait9 | roddy | rooster | rose | square | swan | \ 7742# teddy | tiger | tulips | wall | waterfall | zelda },_name2,...,_nameN,_width={ >=0 | 0 (auto) },\ 7743# _height = { >=0 | 0 (auto) } : (no arg) 7744#@cli : Input a new sample RGB image (opt. with specified size). 7745#@cli : (eq. to 'sp').\n 7746#@cli : Argument 'name' can be replaced by an integer which serves as a sample index. 7747#@cli : $ repeat 6 sample done 7748+sample : skip "${1=?}",${2=0} 7749 v + _sample[] "$1",${2--1} v - 7750 if !${} noarg fi 7751 7752__sample : 7753 u apples,balloons,barbara,boats,bottles,butterfly,cameraman,car,cat,chick,cliff,colorful,\ 7754 david,dog,duck,eagle,elephant,earth,flower,fruits,gmicky,gmicky_mahvin,gmicky_wilber,greece,gummy,house,\ 7755 inside,landscape,leaf,lena,leno,lion,mandrill,monalisa,monkey,parrots,pencils,peppers,\ 7756 portrait0,portrait1,portrait2,portrait3,portrait4,portrait5,portrait6,portrait7,portrait8,portrait9,\ 7757 roddy,rooster,rose,square,swan,teddy,tiger,tulips,wall,waterfall,zelda 7758 7759_sample : 7760 l[] 7761 if "$#>=3 && isnum($-2) && isint($-2) && $-2>=0 && isnum($-1) && isint($-1) && $-1>=0" # W and H specified. 7762 N={$#-2} W=$-2 H=$-1 7763 elif "$#>=2 && isnum($-1) && isint($-1) && $-1>=0" # Only W specified. 7764 N={$#-1} W=$-1 H=0 7765 else # No dimensions specified 7766 N={$#} W,H=0 7767 fi 7768 onfail N={$#} W,H=0 7769 endl 7770 7771 # Check validity of given arguments. 7772 $=arg 7773 samples=${-__sample} 7774 M=${"arg2var _sp_name",$samples} 7775 is_arg=1 7776 repeat $N 7777 arg=${arg{1+$>}} is_rand{1+$>}=0 7778 if ['$arg']=='?' arg={round(u(1,$M))} is_rand{1+$>}=1 7779 elif !isnum($arg)" || "!isint($arg) 7780 repeat $M name=${_sp_name{1+$>}} 7781 if '$name'!=0" && "'$name'==['$arg'] arg={1+$>} break fi 7782 done 7783 else arg={($arg%$M)+1} fi 7784 if !isnum($arg)" || "!isint($arg) is_arg=0 break fi 7785 arg{1+$>}=$arg 7786 done 7787 if !$is_arg N=1 W=0 H=0 arg1={round(u(1,$M))} fi 7788 7789 # Input sample images. 7790 repeat $N 7791 name=${_sp_name${arg{1+$>}}} 7792 7793 # Retrieve image data. 7794 l[] input_cached img/sample_$name.png 7795 onfail testimage2d {m=max($W,$H);m>0?m:400} 7796 endl 7797 7798 # Resize to desired dimensions. 7799 if $W>0" && "$H==0 r2dx. $W round. 7800 elif $W==0" && "$H>0 r2dy. $H round. 7801 elif $W>0" && "$H>0 7802 if w/$W>h/$H r2dy. $H else r2dx. $W fi 7803 r. $W,$H,1,100%,0,0,0.5,0.5 round. 7804 fi 7805 nm. $name 7806 e[0--4] "Input sample image '"{n}"' (1 image "{w}x{h}x{d}x{s}")." 7807 done 7808 +. 0 u $is_arg 7809 7810#@cli srand : value : (no arg) : (+) 7811#@cli : Set random generator seed. 7812#@cli : If no argument is specified, a random value is used as the random generator seed. 7813 7814#@cli store : _is_compressed={ 0 | 1 },variable_name1,_variable_name2,... : (+) 7815#@cli : Store selected images into one or several named variables. 7816#@cli : Selected images are transferred to the variables, and are so removed from the image list. 7817#@cli : (except if the prepended variant of the command '+store[selection]' is used). 7818#@cli : If a single variable name is specified, all images of the selection are assigned 7819#@cli : to the named variable. Otherwise, there must be as many variable names as images 7820#@cli : in the selection, and each selected image is assigned to each specified named variable. 7821#@cli : Use command `input $variable_name` to bring the stored images back in the list. 7822#@cli : Default value: 'is_compressed=0'. 7823#@cli : $ sample eagle,earth store img1,img2 input $img2 $img1 7824#@cli : $$ 7825 7826#@cli testimage2d : _width>0,_height>0,_spectrum>0 7827#@cli : Input a 2D synthetic image. 7828#@cli : Default values: 'width=512', 'height=width' and 'spectrum=3'. 7829#@cli : $ testimage2d 512 7830+testimage2d : check "${1=512}>0 && ${2=$1}>0 && ${3=3}>0" 7831 e[^-1] "Input 2D synthetic image of size $1x$2x$3." 7832 Dmax2={0.15*min($1,$2)^2} 7833 $1,$2,1,$3," 7834 X = x - w/2; 7835 Y = y - h/2; 7836 a = atan2(Y,X); 7837 if (X^2 + Y^2<="$Dmax2",255*abs(cos(c+200*(x/w-0.5)*(y/h-0.5))),850*(a%(0.1*(c+1))))" 7838 polygon. 4,20%,20%,60%,20%,70%,70%,35%,45%,0.9,0,255,0 7839 torus3d {$1/7},{$1/20} r3d. 0,1,1,-80 col3d. 128,200,255 7840 j3d.. .,30%,70%,0,1,5,0,0 rm. round. 1 7841 nm. "[2D test image]" 7842 7843#@cli um : eq. to 'uncommand'. 7844um : 7845 v + uncommand $* v - 7846 7847#@cli uncommand : command_name[,_command_name2,...] : * : (+) 7848#@cli : Discard definition of specified custom commands. 7849#@cli : Set argument to '*' for discarding all existing custom commands. 7850#@cli : (eq. to 'um'). 7851 7852#@cli uniform_distribution : nb_levels>=1,spectrum>=1 7853#@cli : Input set of uniformly distributed spectrum-d points in [0,1]^spectrum. 7854#@cli : $ uniform_distribution 64,3 * 255 +distribution3d circles3d[-1] 10 7855+uniform_distribution : check "isint($1) && $1>0 && isint($2) && $2>0" 7856 e[^1] "Input set of $1 uniformly distributed $2-d points in [0,1]^$2." 7857 l[] 7858 dim=$2 7859 (0;1^$1;0) 7860 repeat $dim 7861 0 7862 eval " 7863 repeat (da_size(#0),s, 7864 V = I[#0,s]; 7865 N = V[size(V) - 1]; # Number of elts in Sk 7866 off = V[size(V) - 2]; # Position offset of elts in subsets of Sk 7867 M = round(N^(1/$dim)); # Number of subsets 7868 n = ceil(N/M); # Number of max elts in subsets of Sk 7869 k0 = 0; 7870 repeat (M,k, 7871 k1 = round(lerp(0,N,(k + 1)/M)); 7872 m = k1 - k0; 7873 V[size(V) - 1] = m; 7874 V[size(V) - 2] = (n - m)/2; 7875 da_push(#-1,[ k + off,V ]); 7876 k0 = k1; 7877 ); 7878 )" 7879 rv[0,-1] rm. dim-=1 7880 done 7881 r {[1,da_size(),1,s-2]},0 s c n 0,1 a c transpose 7882 endl 7883 7884#@cli unserialize : : (+) 7885#@cli : Recreate lists of images from serialized image buffers, obtained with command 'serialize'. 7886 7887#@cli up : eq. to 'update'. 7888up : 7889 v + _update 7890 7891#@cli update 7892#@cli : Update commands from the latest definition file on the G'MIC server. 7893#@cli : (eq. to 'up'). 7894update : 7895 v + _$0 7896 7897_update : 7898 out=${_path_rc}update$_version.gmic 7899 e[0--3] "Update command definition file '"{/$out}"' from the G\47MIC server." 7900 l[] cimgz:https://gmic.eu/update$_version.gmic 7901 if h>7" && "same([{^}],'#@gmic',6) ot $out fi 7902 rm 7903 onfail error[0--3] "Command 'update' : Unreachable update file." 7904 endl 7905 m $out 7906 7907# Function that inserts a new 'Update information' filter for a previous version number, 7908# passed as an argument. 7909update_deprecate : check "isint($1) && $1>0 && $1<999" 7910 e[^-1] "Deprecate filter updates for G'MIC version $1." 7911 l[] 7912 file=${_path_rc}update$1.gmic 7913 i cimgz:"https://gmic.eu/update$1.gmic",uchar 7914 +l. s +,{'"UPDATE"" INFORMATION"'} is_deprecated={$!>1} rm endl # Check if deprecation has not been already done. 7915 if $is_deprecated 7916 e[0--4] " > Version $1 already deprecated -> Removing deprecation." 7917 off1={"ref(crop(),data); find(data,'\n#@gui !<b><i>>> UPDATE"" INFORMATION</i></b>')"} 7918 if $off1>0 7919 +rows $off1,100% rows[0] 0,{$off1-1} 7920 off2={"ref(crop(),data); find(data,'\n\n')"} 7921 if $off2>0 7922 rows. {$off2+2},100% a y 7923 o cimgz:$file,uchar 7924 _upload[] $file 7925 e[0--6] " > Done! Version $1 is not deprecated anymore." 7926 fi 7927 fi 7928 else 7929 s +,{'"#@cli :: "'} 7930 i[1] ('"\n\ 7931 \#@gui !<b><i>>> UPDATE"" INFORMATION</i></b> : _none_, _none_\n\ 7932 \#@gui : note = note{\"A <b>new version</b> of the <i>G\47MIC</i> plug-in is available!\\n\\n\n\ 7933 \#@gui : You are strongly encouraged to upgrade your version, 7934 by visiting our <i>Download page</i>:\\n\\n\"}\n\ 7935 \#@gui : url = link{\"Visit G\47MIC Download Page\",\"https://gmic.eu/download.html\"}\n\ 7936 \#@gui : note = note{\"\\nOf course, your plug-in will continue to work, but please note that we 7937 won\47t be able\n\ 7938 \#@gui : to provide filter updates anymore for your current plug-in version.\\n\\n\n\ 7939 \#@gui : Best regards,\\n\\n <i>The G\47MIC team.</i>\"}\n\n"') 7940 y[1] a y 7941 o cimgz:$file,uchar 7942 _upload[] $file 7943 e[0--4] " > Done! Version $1 is now deprecated." 7944 fi 7945 rm endl 7946 7947# update_download_version. 7948# Update file versions on G'MIC download page, with specified version number. 7949# $1 = version number (e.g. '3.0.0'). 7950update_download_version : check " 7951 is_digit(c)=(c>=_'0' && c<=_'9'); 7952 ver = ['${1=undefined}']; 7953 size(ver)==5 && is_digit(ver[0]) && ver[1]==_'.' && is_digit(ver[2]) && ver[3]==_'.' && is_digit(ver[4])" 7954 e[^-1] "Replace version number on G'MIC download page to '$1'." 7955 rm filename=$HOME/work/src/gmic/html/download.html it[] $filename 7956 eval " 7957 is_digit(c) = (c>=_'0' && c<=_'9'); 7958 ver = ['$1']; 7959 ref(crop(),data); 7960 p = stop = N = 0; 7961 while (!stop, 7962 p = find(data,'?dwl=gmic_',p); 7963 p<0?(stop=1):( 7964 str = data[p + 10,5]; 7965 is_digit(str[0]) && str[1]==_'.' && is_digit(str[2]) && str[3]=='.' && is_digit(str[4])?( 7966 copy(data[p + 10],ver,size(ver)); 7967 ++N; 7968 ); 7969 ++p; 7970 ); 7971 ); 7972 p = find(data,'/source/gmic_',0); 7973 p>0?( 7974 str = data[p + 13,5]; 7975 is_digit(str[0]) && str[1]==_'.' && is_digit(str[2]) && str[3]=='.' && is_digit(str[4])?( 7976 copy(data[p + 13],ver,size(ver)); 7977 ++N; 7978 ); 7979 ); 7980 copy(i[0],data,size(data)); 7981 echo(' -> ',N,' occurrences found.'); 7982 " 7983 ot $filename 7984 7985# Generate images used in the G'MIC installer for Windows (InnoSetup). 7986update_instimg : 7987 sp gmicky,600 7988 7989 # Large image. 7990 +l 7991 r2dx 164 7992 0 t. "G'MIC-Qt for GIMP",0,0,96,1,1 7993 0 t. "(version "${-strver}")",0,0,64,1,1 7994 a[-2,-1] y,0.5 rows. -5,100% 7995 *. -1 n. 0,255 to_rgb. r2dx. {0,0.95*w} 7996 - 255 a y,0.5 + 255 7997 - 255 r 164,314,1,3,0,0,0.5,0.25 + 255 7998 o $HOME/work/src/gmic/resources/gmic_instimg.bmp 7999 rm 8000 endl 8001 8002 # Small image. 8003 r2dx 55 - 255 r 55,55,1,3,0,0,0.5,0.5 + 255 8004 o $HOME/work/src/gmic/resources/gmic_instimg_small.bmp 8005 rm 8006 8007# Generate Color Presets page for the G'MIC website. 8008# Input images : samples you want to generate 8009# $1 = upload to G'MIC server, can be { 0 | 1 }. 8010update_color_presets_html : check "isbool(${1=0})" 8011 use_vt100 8012 path_current=${-path_current} path_ok=$HOME/work/src/gmic/html/color_presets/ 8013 if ['$path_current']!=['$path_ok'] 8014 error[0--3] "Command 'update_color_presets_html: Command run from wrong path: '"$path_current"', "\ 8015 "should be '"$path_ok"'." 8016 fi 8017 8018 # Load default set of images if none selected. 8019 if !$! 8020 files ../img/color_presets_sample* files=${} 8021 repeat narg($files) arg 1+$>,$files ${} done 8022 fi 8023 8024 # Init variables. 8025 jpeg_quality=70 # Set JPEG quality of output images. 8026 thumb_width=180 # Set thumbnail width. 8027 thumb_height=90 # Set mini thumbnail height. 8028 categories=creative,picturefx,pixlsus,abigailgonzalez,alexjordan,berat,ericellerbrock,inavision,jtsemple,\ 8029 kylerholland,ohadperetz,shamoonabbasi,youssefhossam,others,\ 8030 bw,instant_consumer,instant_pro,fujixtransiii,negative_color,negative_new,negative_old,print,colorslide 8031 category_names="Creative Pack",\ 8032 "PictureFX",\ 8033 "PIXLS.US",\ 8034 "Abigail Gonzalez's CLUTs",\ 8035 "Alex Jordan's CLUTs",\ 8036 "Berat's CLUTs",\ 8037 "Eric Ellerbrock's CLUTs",\ 8038 "InAvision's CLUTs",\ 8039 "J.T. Semple's CLUTs",\ 8040 "Kyler Holland's CLUTs",\ 8041 "Ohad Peretz's CLUTs",\ 8042 "Shamoon Abbasi's CLUTs",\ 8043 "Youssef Hossam's CLUTs",\ 8044 "Others",\ 8045 "Films: Black and White",\ 8046 "Films: Instant [Consumer]",\ 8047 "Films: Instant [Pro]",\ 8048 "Films: Fuji XTrans III",\ 8049 "Films: Negative [Color]",\ 8050 "Films: Negative [New]",\ 8051 "Films: Negative [Old]",\ 8052 "Films: Print Films",\ 8053 "Films: Slide [Color]" 8054 category_authors="RawTherapee",\ 8055 "Marc Roovers",\ 8056 "PIXLS.US contributors",\ 8057 "Abigail Gonzalez",\ 8058 "Alex Jordan",\ 8059 "Berat",\ 8060 "Eric Ellerbrock",\ 8061 "InAvision",\ 8062 "J.T. Semple",\ 8063 "Kyler Holland",\ 8064 "Ohad Peretz",\ 8065 "Shamoon Abbasi",\ 8066 "Youssef Hossam",\ 8067 0,\ 8068 "Pat David",\ 8069 "Pat David",\ 8070 "Pat David",\ 8071 "Stuart Sowerby",\ 8072 "Pat David",\ 8073 "Pat David",\ 8074 "Pat David",\ 8075 "Juan Melara",\ 8076 "Pat David" 8077 category_authors_url="https://rawpedia.rawtherapee.com/Film_Simulation",\ 8078 "https://marcrphoto.wordpress.com/specials/698-2/",\ 8079 "https://discuss.pixls.us/t/help-to-create-a-set-of-pixls-us-color-luts",\ 8080 "https://www.abigailgonzalez.com/",\ 8081 "https://freshluts.com/users/1",\ 8082 "https://freshluts.com/users/10185",\ 8083 "https://www.facebook.com/eric.ellerbrockom",\ 8084 "https://freshluts.com/users/64078",\ 8085 "https://freshluts.com/users/120",\ 8086 "https://sellfy.com/p/SGnG/",\ 8087 "https://freshluts.com/users/992",\ 8088 "https://www.facebook.com/shamoon",\ 8089 "https://freshluts.com/users/52679",\ 8090 0,\ 8091 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 8092 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 8093 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 8094 "http://blog.sowerby.me/fuji-film-simulation-profiles",\ 8095 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 8096 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 8097 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 8098 "http://juanmelara.com.au/print-film-emulation-luts-for-download",\ 8099 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html" 8100 8101 m "_thumb : frame 3%,3%,255 to_rgba drop_shadow 2,2,3 repeat $! l[$>] i[0] 100%,100%,1,3,245 blend alpha endl done" 8102 m "_title : ('\"$""*\"') replace_str. \"_\",\" \" replace_str. \"iii\",\"III\" f. \"(!y || j(0,-1)==32) && 8103 i>=_'a' && i<=_'z'?uppercase(i):i\" u {t} rm." 8104 8105 nb_presets=0 8106 repeat narg($categories) 8107 category=${arg\ {1+$>},$categories} 8108 presets=${-_fx_cluts_$category} 8109 nb_presets+={narg({/$presets})} 8110 done 8111 8112 e[] "\n > Update 'Color Presets' pages, for "$!" image samples and "$nb_presets" presets." 8113 8114 # Prepare folder structure. 8115 e[] $_vt100_g"\n * Prepare folder structure."$_vt100_n 8116 x "mkdir -p img" 8117 8118 # Generate thumbnails. 8119 e[] $_vt100_g"\n * Generate thumbnails from samples.\n"$_vt100_n 8120 x "mkdir -p original" 8121 nb_samples=$! 8122 to_rgb repeat $nb_samples l[$<] 8123 nm[0] sample_{1+$<} 8124 basename={0,b} basename$<=$basename 8125 e[] " - "$basename 8126 +r2dx $thumb_width 8127 +to[0] "Reference",4,{0,h-28},20,2 frame. 1,1,0 8128 o. original/$basename.jpg,$jpeg_quality rm. 8129 +_thumb[1] o. original/thumb_$basename.jpg,$jpeg_quality rm. 8130 +r2dy[0] $thumb_height r. {h},{h},1,100%,0,0,0.5,0.5 _thumb. 8131 o. original/minithumb_$basename.jpg,$jpeg_quality rm. 8132 endl done 8133 8134 # Generate color grading data and rendering on each input sample. 8135 ind_preset=0 8136 repeat narg($categories) 8137 category=${arg\ {1+$>},$categories} 8138 presets=${-_fx_cluts_$category} 8139 8140 e[] $_vt100_g"\n * Category ""#"{1+$>}": "$_vt100_b$category"\n"$_vt100_n 8141 x "mkdir -p "$category 8142 x "mkdir -p "$category/clut 8143 8144 repeat narg({/$presets}) 8145 preset=${arg\ {1+$>},$presets} 8146 e[] " - "$preset 8147 clut $preset,64 to_rgb. 8148 s={sqrt(w*h*d)} +r. $s,$s,1,3,-1 8149 if iM<=255 *. 257 fi # Force PNG to be saved in 16bits. 8150 o. $category/clut/$preset.png # Save as HaldCLUT 8151 rm. 8152 8153 +r3dx. 13 8154 o. $category/clut/$preset.cube # Save as .cube 8155 x 0,"rm -f "$category/clut/$preset.zip 8156 x 0,"zip -j -9 "$category/clut/$preset.zip" "$category/clut/$preset.cube 8157 rm. 8158 8159 repeat $nb_samples l[{2*$>},{2*$>+1},-1] 8160 basename={0,b} 8161 if !isfile(['{/$category/$basename/$preset.jpg}']) 8162 x "mkdir -p \""$category/$basename"\"" 8163 +map_clut[^-1] . 8164 _title $preset 8165 to.. ${},4,{-2,h-28},20,2 frame.. 1,1,0 8166 o.. $category/$basename/$preset.jpg,$jpeg_quality 8167 _thumb. o. $category/$basename/thumb_$preset.jpg,$jpeg_quality 8168 rm[-2,-1] 8169 fi 8170 endl done 8171 8172 rm. 8173 8174 ind_preset+=1 8175 done 8176 x 0,"zip -rj9 "$category/${category}_cube.zip" "$category/clut/*.cube 8177 x 0,"zip -rj9 "$category/${category}_haldclut.zip" "$category/clut/*.png 8178 done 8179 8180 rm[1--1:2] # Remove thumbnails. 8181 8182 # Generate html gallery code. 8183 e[] "\n * Generate html code.\n" 8184 8185 repeat narg($categories) 8186 category=${arg\ {1+$>},$categories} 8187 arg {1+$>},$category_names 8188 category_name=${} 8189 presets=${-_fx_cluts_$category} 8190 x 0,"rm -f "$category/clut/"*.cube" 8191 8192 repeat $nb_samples 8193 width={$>,64+w} height={$>,64+h} 8194 basename={$>,b} 8195 e[] " - "$category_name" / "$basename 8196 8197 ('"<!DOCTYPE html>"\n\ 8198"<html lang=\"en\">"\n\ 8199" <head>"\n\ 8200" <meta charset=\"utf-8\">"\n\ 8201" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 8202" <link rel=\"stylesheet\" href=\"../highslide/highslide.css\"/>"\n\ 8203" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 8204"- Color Presets</title>"\n\ 8205" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 8206" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 8207" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 8208" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 8209" <script src=\"../highslide/highslide-full.js\"></script>"\n\ 8210" <script>"\n\ 8211" hs.graphicsDir = '../highslide/graphics/';"\n\ 8212" hs.wrapperClassName = 'wide-border';"\n\ 8213" hs.showCredits = 'false';"\n\ 8214" </script>"\n\ 8215" </head>"\n\n\ 8216" <body>"\n\ 8217" <div id=\"include_header\"></div>"\n\n\ 8218" <div class=\"section_title\"><p>Color Presets</p></div><div class=\"section_content\">"\n\n\ 8219" <p>Among all features available in <span class=\"gmd_gmic\">G'MIC</span>, our <b>Color Presets</b> and "\ 8220"<b>Simulate Film</b> filters are able to apply various pre-defined <b>color CLUTs</b> on your images "\ 8221"(<b>600+</b> color CLUTs available).</p>"\n\ 8222" <p>Below, you can navigate through the different proposed presets and see how they modify the colors "\ 8223"of some sample images."\n\ 8224" You can also download each color preset separately as its corresponding "\ 8225"<a href=\"http://www.quelsolaar.com/technology/clut.html\">HaldCLUT</a> file (in <b>.png</b> format), to use it in "\ 8226" other software that support this feature.</p>"\n\n\ 8227" <p><b>Image credits:</b> Sample images below have been borrowed from "\ 8228"<a href=\"https://www.flickr.com/photos/patdavid/\">Patrick David</a>, "\ 8229"<a href=\"https://www.flickr.com/photos/davelau/\">Chi King</a>, "\ 8230"<a href=\"https://pixabay.com/en/tulips-tulip-field-tulpenbluete-3359902/\">Capri23auto</a> "\ 8231"and <a href=\"https://pixabay.com/en/girl-face-colorful-colors-artistic-2696947/\">ivanovgood</a>,"\n\ 8232" distributed a minima under "\ 8233"<a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-by-SA 2.0</a>.</p>"\n\n\ 8234" <p class=\"colorpresets_disclaimer\"><b>Disclaimer:</b><br/>"\n\ 8235" The trademarked names which may appear in the filenames of the HaldCLUT images are there for "\ 8236"informational purposes only. They serve only to inform the user which film stock the given HaldCLUT image"\n\ 8237" is designed to approximate. As there is no way to convey this information other than by using the "\ 8238"trademarked name, we believe this constitutes fair use. Neither the publisher nor the authors are affiliated"\n\ 8239" with or endorsed by the companies that own the trademarks.</p>"\n\n\ 8240"<!-- end_content -->"\n\n\ 8241" </div><div class=\"section_end\"></div>"\n\n\ 8242" <a name="browse"></a><div class=\"section_title\"><p>Browse</p></div><div class=\"section_content\">"\n\n\ 8243" <table><tr>"\n\ 8244" <td style=\"width: 400px\">Select category:"\n\ 8245" <ul>\n"') 8246 repeat narg($categories) 8247 _category=${arg\ {1+$>},$categories} 8248 arg {1+$>},$category_names 8249 _category_name=${} 8250 8251 arg {1+$>},$category_authors_url 8252 if isnum(${}) _category_author_url_start= _category_author_url_end= 8253 else _category_author_url_start="<a href=\""${}"\">" _category_author_url_end="</a>" 8254 fi 8255 8256 arg {1+$>},$category_authors 8257 if isnum(${}) _category_author="" 8258 else _category_author=$_category_author_url_start${}$_category_author_url_end 8259 fi 8260 8261 if narg($_category_author) 8262 _category_author="<span class=\"smaller\">(by "$_category_author")</span>" 8263 fi 8264 8265 if ['$_category']==['$category'] 8266 ('" <li><span class=\"gmd_bold_a\"><b>"$_category_name"</b> "\ 8267 $_category_author"</span></li>"\n') 8268 else 8269 ('" <li><a href=\""${_category}_$basename.html"#browse\">"$_category_name"</a> "\ 8270 $_category_author"</li>\n"') 8271 fi 8272 done 8273 8274 ('" </ul>\n"\ 8275 " </td>"\n\ 8276 " <td>Select sample image:<br/><br/>\n"') 8277 repeat $nb_samples 8278 _basename=${basename$>} 8279 if ['$_basename']==['$basename'] 8280 ('" <a href=\""${category}_$_basename.html"#browse\">"\ 8281 "<img alt=\"\" style=\"border: 3px solid \#cc7700\" "\ 8282 "src=\""original/minithumb_$_basename.jpg"\"/></a>\n"') 8283 else 8284 ('" <a href=\""${category}_$_basename.html"#browse\"><img alt=\"\" "\ 8285 "src=\""original/minithumb_$_basename.jpg"\"/></a>\n"') 8286 fi 8287 done 8288 ('" </td>"\n\ 8289 " </tr></table>"\n\ 8290 " </div><div class=\"section_end\"></div>"\n\n') 8291 ('" <div class=\"section_title\"><p>Presets</p></div><div class=\"section_content\">"\n\n\ 8292 " <table class=\"colorpresets_table\">"\n\ 8293 " <tr><td>"\n\ 8294 " <div><a href=\"original/"$basename".jpg\" class=\"highslide\" "\ 8295 "onclick=\"return hs.expand(this)\"><img alt=\"\" "\ 8296 "src=\"original/thumb_"$basename".jpg\" /></a>"\n\ 8297 " <div class=\"highslide-caption\"><b>Reference Image</b></div></div>"\n\ 8298 " </td><td colspan=\"3\"></td></tr>"\n\ 8299 " <tr><td><b>Reference Image</b></td><td colspan=\"3\"></td></tr>"\n\n') 8300 8301 repeat narg({/$presets}) 8302 preset=${arg\ {1+$>},$presets} 8303 8304 ('$preset') replace_seq. 39,"92,92,39" preset_esc={t} rm. 8305 _title $preset title=${} 8306 if $>%4==0 if $> ('" </tr>\n"') fi ('" <tr>\n"') fi 8307 8308 ('" <td><table>"\n\ 8309 " <tr><td>"\n\ 8310 " <div><a href=\"#\" onclick=\"return hs.htmlExpand(this, "\ 8311 "{ width: "$width", height: "$height" })\">"\n\ 8312 " <img alt=\"\" src=\""$category/$basename/thumb_$preset".jpg\" /></a>"\n\ 8313 " <div class=\"highslide-maincontent\" style=\"text-align: center\">"\n\ 8314 " <img alt=\"\" src=\""$category/$basename/$preset.jpg"\" "\ 8315 "onclick=\"hs.close()\" "\ 8316 "onmouseover=\"javascript:this.src='"$category/$basename/$preset_esc.jpg"';\" "\ 8317 "onmouseout=\"javascript:this.src='original/"$basename".jpg';\" /></div>"\n\ 8318 " <div class=\"highslide-caption\"><b>Preset:</b> <i>"$title"</i> "\ 8319 "[<a href=\""$category/clut/$preset.png"\">Download .png HaldCLUT</a>] "\ 8320 "or [<a href=\""$category/clut/$preset.zip"\">Download .cube</a>]"\ 8321 "</div></div>"\n\ 8322 " </td></tr>"\n\ 8323 " <tr><td><span class=\"smaller\">"$title"</span></td></tr>"\n\ 8324 " </table></td>\n\n"') 8325 done 8326 r={narg({/$presets})%4} 8327 if $r%4 ('" <td colspan=\""{4-$r}"\"></td>\n"') fi 8328 ('" </tr></table>"\n\n\ 8329 " <hr/><p style=\"text-align: center\">"\n\ 8330 " <a href=\""$category/${category}_cube.zip"\"><img src=\"../img/menu_download.png\" /></a> "\ 8331 "<span class=\"gmd_bold_a\">Get the Full Pack "<i>"${category_name}"</i>":</span> "\ 8332 "[<b><a href=\""$category/${category}_haldclut.zip"\">Download .png HaldCLUT</a></b>] "\ 8333 "or [<b><a href=\""$category/${category}_cube.zip"\">Download .cube</a></b>]"\ 8334 " <a href=\""$category/${category}_cube.zip"\"><img src=\"../img/menu_download.png\" /></a>"\n\ 8335 " </p><hr/>"\n\ 8336 "<!-- end_content -->"\n\n\ 8337 " </div><div class=\"section_end\"></div>"\n\ 8338 " <div id=\"include_footer\"></div>"\n\ 8339 " </body>"') 8340 a[$nb_samples--1] x ot. ${category}_$basename.html rm. 8341 done 8342 8343 done 8344 8345 # All done, exiting. 8346 rm 8347 category=${arg\ 1,$categories} 8348 x "ln -fs "${category}_$basename0.html" index.html" 8349 if $1 8350 e[] "\n * Transfer color presets on G'MIC server.\n" 8351 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"mirror -eRL . /www/gmic/color_presets ; quit\"" 8352 fi 8353 e[] "\n > All done, for "$nb_presets" presets.\n" 8354 8355# Generate gallery page for the G'MIC website. 8356# $1 = upload to G'MIC server, can be { 0 | 1 }. 8357update_gallery_html : check "isbool(${1=0})" 8358 e[^-1] "Generate gallery pages for the G'MIC website." 8359 use_vt100 8360 path_current=${-path_current} path_ok=$HOME/work/src/gmic/html/gallery/ 8361 if ['$path_current']!=['$path_ok'] 8362 error[0--3] "Command 'update_gallery_html: Command run from wrong path: '"$path_current"', "\ 8363 "should be '"$path_ok"'." 8364 fi 8365 x "rm -rf img && mkdir -p img" 8366 8367 # Define categories and sample pictures. 8368 categories=arrays,artistic,blackandwhite,colors,deformations,filtering,patterns,3dmeshes,stylization,codesamples 8369 nb_categories={narg($categories)} 8370 commands_arrays=_gallery_arrays,array,array_fade,array_mirror,frame_blur,frame_cube,frame_painting,img2ascii,\ 8371 imagegrid,rotate_tiles,vignette,tunnel 8372 commands_artistic=_gallery_artistic,boxfitting,cartoon,cubism,draw_whirl,fractalize,halftone,sketchbw,light_relief,\ 8373 mosaic,linify,polaroid,polygonize,poster_hope,rodilius,stencil,stained_glass 8374 commands_blackandwhite=_gallery_blackandwhite,pencilbw,old_photo,sepia 8375 commands_colors=_gallery_colors,solarize,hsv2rgb,transfer_rgb 8376 commands_deformations=_gallery_deformations,deform,map_sphere,seamcarve,spherize,twirl,warp_perspective,water,wave 8377 commands_filtering=_gallery_filtering,blur_angular,blur_linear,blur_radial,glow,smooth,bilateral,dog,deriche,\ 8378 distance,gradient_norm,normalize_local,sharpen,solidify 8379 commands_patterns=_gallery_patterns,tsp,chessboard,mandelbrot,maze_mask,plasma,shape_fern,shape_snowflake,\ 8380 sierpinski,syntexturize_matchpatch,truchet,turbulence,watermark_visible,weave 8381 commands_3dmeshes=_gallery_3dmeshes,add3d,distribution3d,elevation3d,gmic3d,imageblocks3d,imagerubik3d,\ 8382 skeleton3d,spherical3d,tensors3d,text3d,torus3d,weird3d 8383 commands_stylization=_gallery_stylization 8384 commands_codesamples=_gallery_codesamples 8385 8386 pics=apples,bottles,butterfly,car,cat,cliff,david,dog,duck,eagle,elephant,earth,flower,fruits,greece,gummy,inside,\ 8387 landscape,leaf,leno,lion,mandrill,monalisa,parrots,pencils,rooster,rose,square,teddy,tiger,wall,waterfall,zelda 8388 8389 # Generate html pages. 8390 it[] $HOME/work/src/gmic/src/gmic_stdlib.gmic 8391 merge_multiline_comments. s -,10 8392 ('\n') a[0--3] .,y rm. a y 8393 nb_cols=3 8394 8395 repeat $nb_categories,ncat 8396 category=${arg\ 1+$>,$categories} 8397 if isfile('{/$category.html}') continue fi 8398 e[] "\n * Process category '"$_vt100_b$category$_vt100_n"'." 8399 8400 commands=${commands_$category} 8401 nb_commands={narg($commands)} 8402 col,nex=0 8403 8404 repeat $nb_categories 8405 cat=${arg\ 1+$>,$categories} 8406 if '$cat'=='$category' td_$cat="<td style=\"background-color: \#dddddd\">" 8407 else td_$cat="<td>" 8408 fi 8409 done 8410 8411 html="<!DOCTYPE html>"\n\ 8412"<html lang=\"en\">"\n\ 8413" <head>"\n\ 8414" <meta charset=\"utf-8\">"\n\ 8415" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 8416" <link rel=\"stylesheet\" href=\"../highslide/highslide.css\"/>"\n\ 8417" <link rel=\"stylesheet\" href=\"https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css\">"\n\n\ 8418" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 8419"- Gallery</title>"\n\ 8420" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 8421" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 8422" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 8423" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 8424" <script src=\"https://code.jquery.com/jquery-1.12.4.js\"></script>"\n\ 8425" <script src=\"https://code.jquery.com/ui/1.12.1/jquery-ui.js\"></script>"\n\n\ 8426" <script src=\"../highslide/highslide-full.js\"></script>"\n\ 8427" <script>"\n\ 8428" hs.graphicsDir = '../highslide/graphics/';"\n\ 8429" hs.wrapperClassName = 'wide-border';"\n\ 8430" hs.showCredits = 'false';"\n\ 8431" </script>"\n\ 8432" </head>"\n\n\ 8433" <body>"\n\ 8434" <div id=\"include_header\"></div>"\n\n\ 8435" <div class=\"section_title\"><p>Image Gallery</p></div><div class=\"section_content\">"\n\n\ 8436" <p>This gallery gives a quick overview of the kind of features and generic filters available in the "\ 8437"<span class=\"gmd_gmic\">G'MIC</span> open-source image processing framework.</p>"\n\ 8438" <p>All the images below have been processed by the CLI interface "\ 8439"<samp><a href=\"reference/\">gmic</a></samp>"\ 8440" of G'MIC, from a set of initial 2D color images."\n\ 8441" Click on an image to enlarge it and display the G'MIC command-line "\ 8442"used for the processing (<i>note: to reproduce this, you may have to escape some characters, "\ 8443"according to the type of shell you use!</i>).</p>"\n\ 8444" <p>Remember, G'MIC lets you define your own image pipelines through"\ 8445"custom <a href=\"https://gmic.eu/gmic_stdlib.gmic\">command files</a>."\n\ 8446" Your custom filters can be easily added afterwards in the plug-in for "\ 8447"<a href=\"http://www.gimp.org\">GIMP</a> or <a href=\"http://www.krita.org\">Krita</a>.</p>"\n\ 8448" <p>For more details, visit the <a href=\"https://gmic.eu/tutorial\">tutorial pages</a> as well as the "\ 8449"<a href=\"https://gmic.eu/reference/\">technical reference</a> to get a full documentation on this "\ 8450"software.</p>"\n 8451 8452 html_menu=" <table class=\"gallery_navigation\"><tr>\n "\ 8453 $td_arrays"<a href=\"arrays.html#menu\">Arrays & Frames</a></td>"\ 8454 $td_artistic"<a href=\"artistic.html#menu\">Artistic</a></td>"\ 8455 $td_blackandwhite"<a href=\"blackandwhite.html#menu\">B&W</a></td>"\ 8456 $td_colors"<a href=\"colors.html#menu\">Colors</a></td>"\ 8457 $td_deformations"<a href=\"deformations.html#menu\">Deformations</a></td>"\ 8458 $td_filtering"<a href=\"filtering.html#menu\">Filtering</a></td>"\ 8459 $td_patterns"<a href=\"patterns.html#menu\">Patterns</a></td>"\ 8460 $td_3dmeshes"<a href=\"3dmeshes.html#menu\">3D Meshes</a></td>"\ 8461 $td_stylization"<a href=\"stylization.html#menu\">Stylization</a></td>"\ 8462 $td_codesamples"<a href=\"codesamples.html#menu\">Code samples</a></td>"\n\ 8463 " </tr></table><br/>\n\n" 8464 8465 html=${html}${html_menu}" <table class=\"gallery_table\">\n" 8466 8467 repeat $nb_commands 8468 command=${"arg "1+$>,$commands} 8469 is_stylization={['$command']=='_gallery_stylization'} 8470 8471 e[] $_vt100_m" - Command '"$_vt100_b$command$_vt100_n"' ["{1+$>}/$nb_commands"]." 8472 +l # Parse command definition and examples 8473 s -,{'"#@cli "$command" :"'} 8474 if $!<2 s -,{'"#@cli "$command"\n"'} i[1] ('\n') a[-2,-1] y fi 8475 if $!<2 warn[] " ** Command '"$command"' not found! **" 8476 else 8477 k. 8478 eval " 8479 ref(crop(#-1),str); 8480 ind = 0; 8481 while ((ind = find(str,'\n#@cli ',ind))>=0, 8482 ++ind; 8483 str[ind+6]!=_':' ? break() : 8484 str[ind+7]==_' ' && str[ind+8]==_'$' && str[ind+9]==_' '?( 8485 beg = ind + 10; 8486 end = find(str,_'\n',beg) - 1; 8487 ref(vector1024(0),com); 8488 run('+rows[0] ',beg,',',end); 8489 ); 8490 ); 8491 "; 8492 rm[0] 8493 8494 nb_examples=$! 8495 repeat $nb_examples # For each example found 8496 example$nex={$>,t} 8497 8498 e[] $_vt100_g" $ "${example$nex}$_vt100_n 8499 sample=${"arg 1+"{($nex+8*$ncat)%narg($pics)},$pics} 8500 is_codesample=0 8501 8502 l[] # Create a html representation of the command 8503 ('${example$nex}') y 8504 is_input={"find(#-1,'image.jpg')>=0"} 8505 8506 if !$is_input" && find(#-1,'sample ')>=0" 8507 s +,{'"sample "'} 8508 if {0,crop()=='"sample "'" && "$!>1} l[1] 8509 s +,{'" "'} 8510 if "find(#0,_',')==-1" sample={0,t} is_input=1 fi 8511 a y 8512 endl fi 8513 a y 8514 fi 8515 replace_str. "image.jpg",\ 8516 "<a href=\"../img/sample_"$sample".png\" target=\"_blank\">"$sample".png</a>" 8517 replace_str. "_output_mode=1","" 8518 # Discard '_fps=?' and '_label=?' 8519 l. s +,{'" "'} repeat $! if {$<,crop(0,0,1,5)=='_fps='||crop(0,0,1,7)=='_label='} 8520 rm[$<] 8521 fi done a y endl 8522 l. s +,{'" "'} repeat $! if {$<,crop(0,0,1,8)=='https://'} l[$<] # Add hyperlink 8523 if crop(0,0,1,24)=='https://gmic.eu/samples/' 8524 is_codesample=1 8525 basename_codesample={`crop(0,24,1,h-24)`} 8526 filename_codesample="../../resources/samples"/$basename_codesample 8527 url_codesample="https://gmic.eu/samples/"$basename_codesample 8528 if $1 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"put -O /www/gmic/samples \\\""\ 8529 $filename_codesample"\\\"; quit\" >/dev/null" fi 8530 i[0] ('"<a onclick=\"javascript:$( '\#dialog"$nex"' ).dialog( 'open' );\" 8531 style=\"cursor: pointer;\">"') 8532 else i[0] ('"<a href=\""{$<,t}"\" target=\"_blank\">"') 8533 fi 8534 ('</a>') y a y 8535 endl fi done a y endl 8536 replaced_example$nex={t} rm 8537 endl 8538 ('${example$nex}') replace_str. "https://gmic.eu/samples/","../../resources/samples/" example$nex={t} rm. 8539 m "_run : _preview_width,_preview_height=450,300 "${example$nex} 8540 8541 if $is_input sample_=${sample}_ else sample_= fi 8542 filename_original=img/${category}_${sample_}original_$nex.jpg 8543 filename_thumb_original=img/${category}_${sample_}thumb_original_$nex.jpg 8544 if "find(['"${example$nex}"'],' _fps=')>=0" 8545 filename_full=img/${category}_${sample_}full_$nex.gif 8546 filename_thumb=img/${category}_${sample_}thumb_$nex.gif 8547 _is_animated=1 8548 else 8549 filename_full=img/${category}_${sample_}full_$nex.jpg 8550 filename_thumb=img/${category}_${sample_}thumb_$nex.jpg 8551 _is_animated=0 8552 fi 8553 8554 etime= 8555 _label= 8556 if !isfile('{/$filename_thumb}') l[] 8557 if $is_input sp $sample,600 o image.jpg rm fi 8558 8559 db3d m3d md3d f3d l3d sl3d ss3d 0.8 srand 512 8560 etime=$| _run etime={_round($|-$etime,0.01)} 8561 8562 if $is_stylization 8563 +l _gallery o $filename_full,70 rm endl k. 8564 _gallery 8565 width,height={[w,h]} 8566 else 8567 _gallery 8568 width,height={[w,h]} 8569 if $_is_animated o $filename_full,$_fps else o $filename_full,70 fi 8570 fi 8571 e[] "\r"$_vt100_g" $ "${example$nex}" (done in "$_vt100_n${etime}"s"$_vt100_g")."$_vt100_n 8572 8573 crop 5,5,{w-6},{h-6} # Remove frame added by '_gallery' 8574 frame 3%,3%,255 rr2d 440,440,0,3 drop_shadow 2,2,2 8575 if $_is_animated rr2d 230,230,0,3 else rr2d 300,300,0,3 fi 8576 100%,100%,1,3,245 blend[^-1] .,alpha,1,1 rm. 8577 if $_is_animated o $filename_thumb,$_fps else o $filename_thumb,60 fi 8578 rm 8579 8580 if $is_input 8581 image.jpg _gallery 8582 rr2d $width,$height,0,5 c 0,255 8583 to "Input",2%,2%,6% 8584 - 255 r $width,$height,1,3,0,0,0.5,0.5 + 255 8585 o $filename_original,60 8586 8587 crop 5,5,{w-6},{h-6} # Remove frame added by '_gallery' 8588 frame 3%,3%,255 rr2d 440,440,0,3 drop_shadow 2,2,2 8589 if $_is_animated rr2d 230,230,0,3 else rr2d 300,300,0,3 fi 8590 100%,100%,1,3,245 blend[^-1] .,alpha,1,1 rm. 8591 o $filename_thumb_original,60 8592 rm 8593 fi 8594 endl fi 8595 8596 is_samesize=0 8597 l[] 8598 $filename_full 8599 width,height={round([w,h]*(max(w,h)<300?1.75:1))} 8600 if isfile(['{/${filename}_original}']) $filename_original is_samesize={w==w#0" && "h==h#0} fi 8601 rm 8602 endl 8603 if !$is_samesize filename_original=$filename_full fi 8604 if !($col%$nb_cols) html=${html}" <tr>\n" fi 8605 if $nb_examples==1 counter= 8606 else counter=" <span class=\"gallery_caption\">"[{$>+1}/$nb_examples]"</span>" 8607 fi 8608 html_etime= 8609 if narg($etime) html_etime="<br/><span class=\"gallery_caption\">(generated in "${etime}"s)</span>" fi 8610 8611 html_codesample= 8612 if $is_codesample 8613 html_codesample="\n <div id=\"dialog"$nex"\" title=\""samples/$basename_codesample"\">"\ 8614 "\n <pre class>\n" 8615 it[] $url_codesample html_codesample=${html_codesample}{t} rm. 8616 html_codesample=${html_codesample}"\n</pre></div>\n"\ 8617 "<br/><script>$( function() { $( \"#dialog"$nex"\" )."\ 8618 "dialog({ autoOpen: false, width:600 }); } );</script>\n 8619 <a onclick=\"javascript:$( '#dialog"$nex"' ).dialog( 'open' );\" 8620 style=\"cursor: pointer;\"><span class=\"gallery_caption\">[ Source code ]</p></a>\n" 8621 fi 8622 if ['$_label']==0 _label=$command$counter else ('$_label') replace_str. "~"," " _label={t} rm. fi 8623 if $is_input 8624 html=${html}\ 8625 " <td><div><a href=\"#\" onclick=\"return hs.htmlExpand(this, { width: "{$width+64}","\ 8626 "height: "{$height+64}" })\">\n"\ 8627 " <img alt=\""gallery_$command$nex"\" src=\""$filename_thumb"\" "\ 8628 "onmouseover=\"javascript:this.src='"$filename_thumb_original"';\" 8629 onmouseout=\"javascript:this.src='"$filename_thumb"';\"/><br/><b>"\ 8630 ${_label}${html_codesample}"</b></a>\n"\ 8631 " <div class=\"highslide-maincontent\">\n"\ 8632 " <img alt=\""gallery_$command$nex"\" width=\""$width"\" "\ 8633 "src=\""$filename_full"\" 8634 onclick=\"hs.close()\" onmouseover=\"javascript:this.src='"$filename_full"';\" 8635 onmouseout=\"javascript:this.src='"$filename_original"';\"/>\n"\ 8636 " </div>\n"\ 8637 " <div class=\"highslide-caption\">Command: "\ 8638 "<samp>$ gmic "${replaced_example$nex}"</samp>"\ 8639 ${html_etime}"</div></div></td>\n" 8640 else 8641 html=${html}\ 8642 " <td><div><a href=\"#\" onclick=\"return hs.htmlExpand(this, { width: "{$width+64}","\ 8643 "height: "{$height+64}" })\">\n"\ 8644 " <img alt=\""gallery_$command$nex"\" src=\""$filename_thumb"\" />"\ 8645 "<br/><b>"\ 8646 ${_label}${html_codesample}"</b></a>\n"\ 8647 " <div class=\"highslide-maincontent\">\n"\ 8648 " <img alt=\""gallery_$command$nex"\" width=\""$width"\" "\ 8649 "src=\""$filename_full"\" onclick=\"hs.close()\" />\n"\ 8650 " </div>\n"\ 8651 " <div class=\"highslide-caption\">Command: "\ 8652 "<samp>$ gmic "${replaced_example$nex}"</samp>"\ 8653 ${html_etime}"</div></div></td>\n" 8654 fi 8655 nex+=1 8656 col={($col+1)%$nb_cols} 8657 if !$col html=${html}" </tr>\n" fi 8658 done 8659 fi 8660 rm 8661 endl 8662 done 8663 if $col html=${html}" <td colspan=\""{$nb_cols-$col}"\"></td></tr>\n" fi 8664 html=${html}" </table><br/>\n"\ 8665 ${html_menu}\ 8666 " </div><div class=\"section_end\"></div>"\n" <div id=\"include_footer\"></div>"\n" </body>" 8667 ('$html') ot. $category.html rm. 8668 done 8669 rm 8670 8671 # Transfer on G'MIC server 8672 x "ln -fs artistic.html index.html" 8673 if $1 8674 e[] "\n * Transfer gallery on G'MIC server.\n" 8675 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"mirror -eRL . /www/gmic/gallery ; quit\"" 8676 fi 8677 e[] " * All done!\n" 8678 8679# Generate a single image from a list of images, for the gallery. 8680_gallery : 8681 repeat $! l[$>] W$>={w} H$>={h} D$>={d} S$>={s} IS_3D$>=${-_is_3d} endl done 8682 repeat $! l[$>] 8683 if ${IS_3D$>} r3d 1,1,0,-80 r3d 0,1,0,80 snapshot3d 400 8684 else if w>8192 z 0,8191 elif h>8192 rows 0,8191 fi n 0,255 8685 fi 8686 endl done 8687 8688 if !$_is_animated 8689 +__gallery 8690 if w>1024 r={round(1024*100/w,0.1)} r[^-1] $r%,$r%,1,100%,2 fi rm. 8691 fi 8692 8693 repeat $! l[$>] 8694 if s==1 r {w},{h},1,3 8695 elif s==4 drgba 8696 else r {w},{h},1,3,0 fi 8697 if w<=h" && "h<256 r2dy 256,2 elif h<=w" && "w<256 r2dx 256,2 fi 8698 if w<=h" && "h>620 r2dy 620,2 elif h<=w" && "w>620 r2dx 620,2 fi 8699 if h<48 r 100%,48 fi 8700 if w<48 r 48,100% fi 8701 if $_is_animated" && "(w>480" || "h>480) rr2d 480,480,0,2 fi 8702 frame 1,1,0 frame 4,4,255 8703 endl done 8704 8705 if $_is_animated 8706 - 255 r ${-max_wh},1,3,0,0,0.5,0.5 + 255 8707 else 8708 - 255 __gallery + 255 8709 if w<256 - 255 r 256,100%,1,100%,0,0,0.5,0.5 + 255 fi 8710 if h<256 - 255 r 100%,256,1,100%,0,0,0.5,0.5 + 255 fi 8711 fi 8712 8713__gallery : 8714 if $!==2 if w>h a y else a x fi 8715 else montage A # append_tiles 2 8716 fi 8717 8718# Generate data files for the G'MIC Online website. 8719update_gmicol : 8720 e[^-1] "Generate XML file and thumbnails for the G'MIC Online website." 8721 filename=$_path_rc/update$_version.gmic 8722 if !isfile('$filename') up fi 8723 rm it $filename 8724 8725 # Generate XML file. 8726 m "parse_gui_trigger_gmicol : _update_gmicol $*" 8727 v + +parse_gui. gmicol v - 8728 um parse_gui_trigger_gmicol 8729 ot. gmicol.xml 8730 rm. 8731 8732 # Generate thumbnails. 8733 m "parse_gui_trigger_thumbnails : _update_gmicol $*" 8734 v + w[] parse_gui thumbnails v - 8735 um parse_gui_trigger_thumbnails 8736 8737_update_gmicol : # Keep only a subset of existing filters 8738 nmd 3,\ 8739 "About/♥ Support Us ! ♥",\ 8740 "About/About G'MIC",\ 8741 "About/Friends Hall of Fame",\ 8742 "Arrays & Tiles/Annular Steiner Chain Round Tile",\ 8743 "Arrays & Tiles/Array [Faded]",\ 8744 "Arrays & Tiles/Array [Mirrored]",\ 8745 "Arrays & Tiles/Array [Random Colors]",\ 8746 "Arrays & Tiles/Array [Random]",\ 8747 "Arrays & Tiles/Array [Regular]",\ 8748 "Arrays & Tiles/Ascii Art",\ 8749 "Arrays & Tiles/Chessboard",\ 8750 "Arrays & Tiles/Dices",\ 8751 "Arrays & Tiles/Grid [Cartesian]",\ 8752 "Arrays & Tiles/Grid [Hexagonal]",\ 8753 "Arrays & Tiles/Grid [Triangular]",\ 8754 "Arrays & Tiles/Ministeck",\ 8755 "Arrays & Tiles/Puzzle",\ 8756 "Arrays & Tiles/Taquin",\ 8757 "Arrays & Tiles/Tiled Isolation",\ 8758 "Arrays & Tiles/Tiled Normalization",\ 8759 "Arrays & Tiles/Tiled Parameterization",\ 8760 "Arrays & Tiles/Tiled Random Shifts",\ 8761 "Arrays & Tiles/Tiled Rotation",\ 8762 "Artistic/Angoisse Anguish",\ 8763 "Artistic/Aurora",\ 8764 "Artistic/Blockism",\ 8765 "Artistic/Bokeh",\ 8766 "Artistic/Cartoon",\ 8767 "Artistic/Circle Abstraction",\ 8768 "Artistic/Color Abstraction Paint",\ 8769 "Artistic/Colored Pencils",\ 8770 "Artistic/Comic Book",\ 8771 "Artistic/Cubism",\ 8772 "Artistic/Cutout",\ 8773 "Artistic/Diffusion Tensors",\ 8774 "Artistic/Dream Smoothing",\ 8775 "Artistic/Ellipsionism",\ 8776 "Artistic/Felt Pen",\ 8777 "Artistic/Finger Paint",\ 8778 "Artistic/Fractalize",\ 8779 "Artistic/Ghost",\ 8780 "Artistic/Graphic Boost",\ 8781 "Artistic/Graphic Novel",\ 8782 "Artistic/Hard Sketch",\ 8783 "Artistic/Highlight Bloom",\ 8784 "Artistic/Hope Poster",\ 8785 "Artistic/Hough Sketch",\ 8786 "Artistic/Illustration Look",\ 8787 "Artistic/Kuwahara",\ 8788 "Artistic/Lylejk's Painting",\ 8789 "Artistic/Make Squiggly",\ 8790 "Artistic/Morphology Painting",\ 8791 "Artistic/Paint With Brush",\ 8792 "Artistic/Painting",\ 8793 "Artistic/Pen Drawing",\ 8794 "Artistic/Photoillustration",\ 8795 "Artistic/Polygonize [Delaunay]",\ 8796 "Artistic/Polygonize [Energy]",\ 8797 "Artistic/Poster Edges",\ 8798 "Artistic/Posterize",\ 8799 "Artistic/Posterized Dithering",\ 8800 "Artistic/Quadtree Variations",\ 8801 "Artistic/Rodilius",\ 8802 "Artistic/Sharp Abstract",\ 8803 "Artistic/Simple Noise Canvas",\ 8804 "Artistic/Skeletik",\ 8805 "Artistic/Sketch",\ 8806 "Artistic/Smooth Abstract",\ 8807 "Artistic/Stylize",\ 8808 "Artistic/Vector Painting",\ 8809 "Artistic/Warhol",\ 8810 "Artistic/Whirl Drawing",\ 8811 "Black & White/B&W Stencil",\ 8812 "Black & White/Black & White",\ 8813 "Black & White/Charcoal",\ 8814 "Black & White/Colorize [with Colormap]",\ 8815 "Black & White/Colorize Lineart [Auto-Fill]",\ 8816 "Black & White/Colorize Lineart [Smart Coloring]",\ 8817 "Black & White/Desaturate Norm",\ 8818 "Black & White/Dithering",\ 8819 "Black & White/Emboss",\ 8820 "Black & White/Engrave",\ 8821 "Black & White/Freaky B&W",\ 8822 "Black & White/Ink Wash",\ 8823 "Black & White/Multi-Layer Etch",\ 8824 "Black & White/Pencil",\ 8825 "Black & White/Pencil Portrait",\ 8826 "Black & White/Stamp",\ 8827 "Black & White/Threshold Etch",\ 8828 "Colors/Abstraction",\ 8829 "Colors/Auto Balance",\ 8830 "Colors/Basic Adjustments",\ 8831 "Colors/Boost Chromaticity",\ 8832 "Colors/Boost-Fade",\ 8833 "Colors/Brightness",\ 8834 "Colors/Channel Processing",\ 8835 "Colors/CMYK Tone",\ 8836 "Colors/Color Balance",\ 8837 "Colors/Color Blindness",\ 8838 "Colors/Color Grading",\ 8839 "Colors/Color Presets",\ 8840 "Colors/Color Temperature",\ 8841 "Colors/Colormap",\ 8842 "Colors/Contrast",\ 8843 "Colors/Customize CLUT",\ 8844 "Colors/Dark Sky",\ 8845 "Colors/Equalize HSI-HSL-HSV",\ 8846 "Colors/Equalize HSV",\ 8847 "Colors/HSL Adjustment",\ 8848 "Colors/HSV Select",\ 8849 "Colors/Hue Lighten-Darken",\ 8850 "Colors/LMS Adjustment",\ 8851 "Colors/Local Contrast",\ 8852 "Colors/Metallic Look",\ 8853 "Colors/Mixer [CMYK]",\ 8854 "Colors/Mixer [HSV]",\ 8855 "Colors/Mixer [Lab]",\ 8856 "Colors/Mixer [PCA]",\ 8857 "Colors/Mixer [RGB]",\ 8858 "Colors/Mixer [YCbCr]",\ 8859 "Colors/Normalize Brightness",\ 8860 "Colors/Retinex",\ 8861 "Colors/Retro Fade",\ 8862 "Colors/RGB Tone",\ 8863 "Colors/Saturation EQ",\ 8864 "Colors/Select-Replace Color",\ 8865 "Colors/Selective Desaturation",\ 8866 "Colors/Sepia",\ 8867 "Colors/Simulate Film",\ 8868 "Colors/Softlight",\ 8869 "Colors/Specific Saturation",\ 8870 "Colors/Temperature Balance",\ 8871 "Colors/Tone Presets",\ 8872 "Colors/Tune HSV Colors",\ 8873 "Colors/User-Defined",\ 8874 "Colors/Vintage Style",\ 8875 "Colors/Zone System",\ 8876 "Contours/Convolve",\ 8877 "Contours/Curvature",\ 8878 "Contours/Difference of Gaussians",\ 8879 "Contours/Distance Transform",\ 8880 "Contours/Edge",\ 8881 "Contours/Edges",\ 8882 "Contours/Edges Offsets",\ 8883 "Contours/Gradient Norm",\ 8884 "Contours/Gradient RGB",\ 8885 "Contours/Isophotes",\ 8886 "Contours/Laplacian",\ 8887 "Contours/Local Orientation",\ 8888 "Contours/Morphological Filter",\ 8889 "Contours/Segmentation",\ 8890 "Contours/Skeleton",\ 8891 "Contours/Super-Pixels",\ 8892 "Contours/Thin Edges",\ 8893 "Deformations/Breaks",\ 8894 "Deformations/Cartesian Transform",\ 8895 "Deformations/Circle Transform",\ 8896 "Deformations/Conformal Maps",\ 8897 "Deformations/Continuous Droste",\ 8898 "Deformations/Crease",\ 8899 "Deformations/Distort Lens",\ 8900 "Deformations/Drop Water",\ 8901 "Deformations/Equirectangular to Nadir-Zenith",\ 8902 "Deformations/Euclidean - Polar",\ 8903 "Deformations/Fish-Eye",\ 8904 "Deformations/Flower",\ 8905 "Deformations/Kaleidoscope [Blended]",\ 8906 "Deformations/Kaleidoscope [Polar]",\ 8907 "Deformations/Kaleidoscope [Reptorian-Polar]",\ 8908 "Deformations/Kaleidoscope [Symmetry]",\ 8909 "Deformations/Logarithmic Distortion",\ 8910 "Deformations/Moon2panorama",\ 8911 "Deformations/Perspective",\ 8912 "Deformations/Pixel Push",\ 8913 "Deformations/Point Warp",\ 8914 "Deformations/Polar Transform",\ 8915 "Deformations/Quadrangle",\ 8916 "Deformations/Raindrops",\ 8917 "Deformations/Random",\ 8918 "Deformations/Reflection",\ 8919 "Deformations/Ripple",\ 8920 "Deformations/Seamcarve",\ 8921 "Deformations/Sinusoidal Water Distortion",\ 8922 "Deformations/Sphere",\ 8923 "Deformations/Spherize",\ 8924 "Deformations/Square to Circle",\ 8925 "Deformations/Stereographic Projection",\ 8926 "Deformations/Symmetrize",\ 8927 "Deformations/Textured Glass",\ 8928 "Deformations/Twirl",\ 8929 "Deformations/Water",\ 8930 "Deformations/Wave",\ 8931 "Deformations/Wind",\ 8932 "Deformations/Zoom",\ 8933 "Degradations/Add Grain",\ 8934 "Degradations/Blur [Angular]",\ 8935 "Degradations/Blur [Bloom]",\ 8936 "Degradations/Blur [Depth-Of-Field]",\ 8937 "Degradations/Blur [Gaussian]",\ 8938 "Degradations/Blur [Glow]",\ 8939 "Degradations/Blur [Linear]",\ 8940 "Degradations/Blur [Multidirectional]",\ 8941 "Degradations/Blur [Radial]",\ 8942 "Degradations/Blur [Splinter]",\ 8943 "Degradations/Chromatic Aberrations",\ 8944 "Degradations/CRT Sub-Pixels",\ 8945 "Degradations/Dirty",\ 8946 "Degradations/Flip & Rotate Blocs",\ 8947 "Degradations/Fragment Blur",\ 8948 "Degradations/JPEG Artefacts",\ 8949 "Degradations/Lomo",\ 8950 "Degradations/Mess with Bits",\ 8951 "Degradations/Noise [Additive]",\ 8952 "Degradations/Noise [Perlin]",\ 8953 "Degradations/Noise [Spread]",\ 8954 "Degradations/Old-Movie Stripes",\ 8955 "Degradations/Oldschool 8bits",\ 8956 "Degradations/Pixel Sort",\ 8957 "Degradations/Rain & Snow",\ 8958 "Degradations/Random Shade Stripes",\ 8959 "Degradations/Rebuild From Similar Blocs",\ 8960 "Degradations/Scanlines",\ 8961 "Degradations/Self Glitching",\ 8962 "Degradations/Streak",\ 8963 "Degradations/UltraWarp++++",\ 8964 "Degradations/Visible Watermark",\ 8965 "Degradations/Warp by Intensity",\ 8966 "Details/Constrained Sharpen",\ 8967 "Details/DCP Dehaze",\ 8968 "Details/Details Equalizer",\ 8969 "Details/Dynamic Range Increase",\ 8970 "Details/Easy Skin Retouch",\ 8971 "Details/Emboss-Relief",\ 8972 "Details/Equalize Local Histograms",\ 8973 "Details/Freaky Details",\ 8974 "Details/High Pass",\ 8975 "Details/Local Contrast Enhancement",\ 8976 "Details/Local Normalization",\ 8977 "Details/Local Processing",\ 8978 "Details/Local Variance Normalization",\ 8979 "Details/Magic Details",\ 8980 "Details/Make Up",\ 8981 "Details/Mighty Details",\ 8982 "Details/Portrait Retouching",\ 8983 "Details/Pyramid Processing",\ 8984 "Details/Quick Tonemap",\ 8985 "Details/Sharpen [Deblur]",\ 8986 "Details/Sharpen [Gold-Meinel]",\ 8987 "Details/Sharpen [Gradient]",\ 8988 "Details/Sharpen [Hessian]",\ 8989 "Details/Sharpen [Inverse Diffusion]",\ 8990 "Details/Sharpen [Multiscale]",\ 8991 "Details/Sharpen [Octave Sharpening]",\ 8992 "Details/Sharpen [Richardson-Lucy]",\ 8993 "Details/Sharpen [Shock Filters]",\ 8994 "Details/Sharpen [Texture]",\ 8995 "Details/Sharpen [Tones]",\ 8996 "Details/Sharpen [Unsharp Mask]",\ 8997 "Details/Sharpen [Whiten]",\ 8998 "Details/Simple Local Contrast",\ 8999 "Details/Spotify",\ 9000 "Details/Texture",\ 9001 "Details/Texture Enhance",\ 9002 "Details/Tone Enhance",\ 9003 "Details/Tone Mapping",\ 9004 "Details/Tone Mapping [Fast]",\ 9005 "Details/YAG Effect",\ 9006 "Frames/Droste",\ 9007 "Frames/Frame [Blur]",\ 9008 "Frames/Frame [Cube]",\ 9009 "Frames/Frame [Fuzzy]",\ 9010 "Frames/Frame [Mirror]",\ 9011 "Frames/Frame [Painting]",\ 9012 "Frames/Frame [Pattern]",\ 9013 "Frames/Frame [Regular]",\ 9014 "Frames/Frame [Round]",\ 9015 "Frames/Frame [Smooth]",\ 9016 "Frames/Old Photograph",\ 9017 "Frames/Polaroid",\ 9018 "Frames/Tunnel",\ 9019 "Frames/Vignette",\ 9020 "Frequencies/Bandpass",\ 9021 "Frequencies/Fourier Analysis",\ 9022 "Frequencies/Fourier Transform",\ 9023 "Frequencies/Fourier Watermark",\ 9024 "Lights & Shadows/Burn",\ 9025 "Lights & Shadows/Contrast Swiss Mask",\ 9026 "Lights & Shadows/Dodge and Burn",\ 9027 "Lights & Shadows/Drop Shadow",\ 9028 "Lights & Shadows/Drop Shadow 3D",\ 9029 "Lights & Shadows/Equalize Light",\ 9030 "Lights & Shadows/Equalize Shadow",\ 9031 "Lights & Shadows/Guided Light Rays",\ 9032 "Lights & Shadows/Illuminate 2D Shape",\ 9033 "Lights & Shadows/Light Glow",\ 9034 "Lights & Shadows/Light Leaks",\ 9035 "Lights & Shadows/Light Patch",\ 9036 "Lights & Shadows/Light Rays",\ 9037 "Lights & Shadows/Pop Shadows",\ 9038 "Lights & Shadows/Relief Light",\ 9039 "Lights & Shadows/Shadow Patch",\ 9040 "Patterns/Bayer Filter",\ 9041 "Patterns/Box Fitting",\ 9042 "Patterns/Camouflage",\ 9043 "Patterns/Canvas",\ 9044 "Patterns/Canvas Texture",\ 9045 "Patterns/Clouds",\ 9046 "Patterns/Cracks",\ 9047 "Patterns/Crystal",\ 9048 "Patterns/Crystal Background",\ 9049 "Patterns/Denim Texture",\ 9050 "Patterns/Fibers",\ 9051 "Patterns/Freqy Pattern",\ 9052 "Patterns/Halftone",\ 9053 "Patterns/Halftone Shapes",\ 9054 "Patterns/Hearts",\ 9055 "Patterns/Hedcut (Experimental)",\ 9056 "Patterns/Lava",\ 9057 "Patterns/Marble",\ 9058 "Patterns/Maze",\ 9059 "Patterns/Mineral Mosaic",\ 9060 "Patterns/Mosaic",\ 9061 "Patterns/Op Art",\ 9062 "Patterns/Paper Texture",\ 9063 "Patterns/Periodic Dots",\ 9064 "Patterns/Plaid",\ 9065 "Patterns/Polka Dots",\ 9066 "Patterns/Random Color Ellipses",\ 9067 "Patterns/Random Pattern",\ 9068 "Patterns/Rays",\ 9069 "Patterns/Reptile",\ 9070 "Patterns/Resynthetize Texture [FFT]",\ 9071 "Patterns/Resynthetize Texture [Patch-Based]",\ 9072 "Patterns/Rorschach",\ 9073 "Patterns/Satin",\ 9074 "Patterns/Seamless Deco",\ 9075 "Patterns/Seamless Turbulence",\ 9076 "Patterns/Shock Waves",\ 9077 "Patterns/Soft Random Shades",\ 9078 "Patterns/Sponge",\ 9079 "Patterns/Stained Glass",\ 9080 "Patterns/Stars",\ 9081 "Patterns/Stencil",\ 9082 "Patterns/Strip",\ 9083 "Patterns/Tetris",\ 9084 "Patterns/Triangular Pattern",\ 9085 "Patterns/Truchet",\ 9086 "Patterns/Turbulent Halftone",\ 9087 "Patterns/Voronoi",\ 9088 "Patterns/Weave",\ 9089 "Patterns/Whirls",\ 9090 "Rendering/3D Blocks",\ 9091 "Rendering/3D Colored Object",\ 9092 "Rendering/3D Elevation",\ 9093 "Rendering/3D Extrusion",\ 9094 "Rendering/3D Image Object",\ 9095 "Rendering/3D Lathing",\ 9096 "Rendering/3D Random Objects",\ 9097 "Rendering/Ball",\ 9098 "Rendering/Circle Art",\ 9099 "Rendering/Construction Material Texture",\ 9100 "Rendering/Disco",\ 9101 "Rendering/Equation Plot [Parametric]",\ 9102 "Rendering/Equation Plot [Y=f(X)]",\ 9103 "Rendering/Gradient [Corners]",\ 9104 "Rendering/Gradient [Custom Shape]",\ 9105 "Rendering/Gradient [from Line]",\ 9106 "Rendering/Gradient [Linear]",\ 9107 "Rendering/Gradient [Radial]",\ 9108 "Rendering/Gradient [Random]",\ 9109 "Rendering/Hair Locks",\ 9110 "Rendering/Hypotrochoid",\ 9111 "Rendering/Kitaoka Spin Illusion",\ 9112 "Rendering/Lightning",\ 9113 "Rendering/Lissajous",\ 9114 "Rendering/Mandelbrot - Julia Sets",\ 9115 "Rendering/Nebulous",\ 9116 "Rendering/Neon Lightning",\ 9117 "Rendering/Newton Fractal",\ 9118 "Rendering/Plasma",\ 9119 "Rendering/Popcorn Fractal",\ 9120 "Rendering/Pseudorandom Noise",\ 9121 "Rendering/Pythagoras Tree",\ 9122 "Rendering/Quick Copyright",\ 9123 "Rendering/Rainbow",\ 9124 "Rendering/Shade Bobs",\ 9125 "Rendering/Sine Curve",\ 9126 "Rendering/Snowflake 2",\ 9127 "Rendering/Spiral",\ 9128 "Rendering/Spiral RGB",\ 9129 "Rendering/Superformula",\ 9130 "Rendering/Symmetric 2D Shape",\ 9131 "Rendering/Thorn Fractal - Secant Sea",\ 9132 "Rendering/Tree",\ 9133 "Rendering/Turbulence",\ 9134 "Rendering/Twisted Rays",\ 9135 "Rendering/Wiremap",\ 9136 "Repair/Anti Alias",\ 9137 "Repair/Banding Denoise",\ 9138 "Repair/Bayer Reconstruction",\ 9139 "Repair/Clean Text",\ 9140 "Repair/Compression Blur",\ 9141 "Repair/Deinterlace",\ 9142 "Repair/Deinterlace2x",\ 9143 "Repair/Denoise",\ 9144 "Repair/Denoise Smooth",\ 9145 "Repair/Denoise Smooth Alt",\ 9146 "Repair/Descreen",\ 9147 "Repair/Despeckle",\ 9148 "Repair/Iain Noise Reduction 2019",\ 9149 "Repair/Iain's Fast Denoise",\ 9150 "Repair/Inpaint [Holes]",\ 9151 "Repair/Inpaint [Morphological]",\ 9152 "Repair/Inpaint [Multi-Scale]",\ 9153 "Repair/Inpaint [Patch-Based]",\ 9154 "Repair/Inpaint [Transport-Diffusion]",\ 9155 "Repair/JPEG Smooth",\ 9156 "Repair/Local Similarity Mask",\ 9157 "Repair/Moire Removal",\ 9158 "Repair/Pixel Denoise",\ 9159 "Repair/Recursive Median",\ 9160 "Repair/Red-Eye Attenuation",\ 9161 "Repair/Remove Hot Pixels",\ 9162 "Repair/Repair Scanned Document",\ 9163 "Repair/Smooth [Anisotropic]",\ 9164 "Repair/Smooth [Antialias]",\ 9165 "Repair/Smooth [Bilateral]",\ 9166 "Repair/Smooth [Block PCA]",\ 9167 "Repair/Smooth [Diffusion]",\ 9168 "Repair/Smooth [Geometric-Median]",\ 9169 "Repair/Smooth [Guided]",\ 9170 "Repair/Smooth [IUWT]",\ 9171 "Repair/Smooth [Mean-Curvature]",\ 9172 "Repair/Smooth [Median]",\ 9173 "Repair/Smooth [NL-Means]",\ 9174 "Repair/Smooth [Patch-Based]",\ 9175 "Repair/Smooth [Patch-PCA]",\ 9176 "Repair/Smooth [Perona-Malik]",\ 9177 "Repair/Smooth [Selective Gaussian]",\ 9178 "Repair/Smooth [Skin]",\ 9179 "Repair/Smooth [Thin Brush]",\ 9180 "Repair/Smooth [Total Variation]",\ 9181 "Repair/Smooth [Wavelets]",\ 9182 "Repair/Smooth [Wiener]",\ 9183 "Repair/Solidify",\ 9184 "Repair/Unpurple",\ 9185 "Repair/Unquantize [JPEG Smooth]",\ 9186 "Repair/Unstrip",\ 9187 "Repair/Upscale [DCCI2x]",\ 9188 "Repair/Upscale [Diffusion]",\ 9189 "Repair/Upscale [Edge]",\ 9190 "Repair/Upscale [Scale2x]" 9191 k[${}] 9192 9193# Generate reference documentation pages for the G'MIC website. 9194# $1 = upload to G'MIC server, can be { 0 | 1 }. 9195update_reference_html : check "isbool(${1=0})" 9196 path_current=${-path_current} path_ok=$HOME/work/src/gmic/html/reference/ 9197 if ['$path_current']!=['$path_ok'] 9198 error[0--3] "Command 'update_reference_html: Command run from wrong path: '"$path_current"', "\ 9199 "should be '"$path_ok"'." 9200 fi 9201 x "rm -f *.pdf" 9202 9203 rm 9204 e[^-1] "Generate reference documentation pages for the G'MIC website." 9205 it $HOME/work/src/gmic/src/gmic_stdlib.gmic 9206 a y 9207 9208 # Generate image of examples. 9209 x "mkdir -p img" 9210 _parse_cli_images_path="img/" 9211 +parse_cli images 9212 parse_cli html 9213 9214 # Generate reference pages in html. 9215 rm 9216 x "cp -rf "$HOME/work/src/gmic-community/reference/images" ." 9217 reference html,$HOME/work/src/gmic-community/reference 9218 9219 # Upload to G'MIC server. 9220 if $1 9221 e[] "\n > Transfer reference documentation on G'MIC server.\n" 9222 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"mirror -RL . /www/gmic/reference ; quit\"" 9223 fi 9224 e[] "\n > All done.\n" 9225 9226# Generate tutorial pages for the G'MIC website. 9227# $1 = upload to G'MIC server, can be { 0 | 1 }. 9228update_tutorial_html : check "isbool(${1=0})" 9229 path_current=${-path_current} path_ok=$HOME/work/src/gmic/html/tutorial/ 9230 if ['$path_current']!=['$path_ok'] 9231 error[0--3] "Command 'update_tutorial_html: Command run from wrong path: '"$path_current"', "\ 9232 "should be '"$path_ok"'." 9233 fi 9234 9235 rm 9236 e[^-1] "Generate tutorial pages for the G'MIC website." 9237 path_tutorial=$HOME/work/src/gmic-community/tutorial 9238 use_vt100 9239 9240 # Build directory structure. 9241 e[] " > Build directory structure." 9242 x "mkdir -p images scripts" 9243 files 5,$path_tutorial/* 9244 l[] 9245 ({'${}'}:y) s -,{','} 9246 for $! 9247 file={0,t} rm[0] 9248 basename $file basename=${} 0 nm. $basename ext={`lowercase(['{x}'])`} rm. 9249 if ['$basename']!='img' 9250 if isdir(['$file']) files 5,$file/* ({'${}'}:y) s. -,{','} # Folder -> Recursively add files 9251 elif s=['$ext'];s=='png'||s=='jpg'||s=='jpeg'||s=='gif'||s=='mp4'||s=='svg' 9252 x "cp -f \""$file"\" images/" # Image/videos: Copy to sub-folder 'images/' 9253 elif s=['$ext'];s=='gmic' 9254 x "cp -f \""$file"\" scripts/" # Scripts: Copy to sub-folder 'scripts/' 9255 elif s=['$ext'];s=='gmd' # G'MIC Markdown -> Copy to current folder './' 9256 it[] $file 9257 ot. $basename rm. 9258 fi 9259 fi 9260 done 9261 endl 9262 9263 # Generate html pages. 9264 files 0,*.gmd files=${} 9265 repeat narg({/$files}) 9266 arg0 $>,$files file=${} 9267 e[] " > Generate '"$_vt100_c$file$_vt100_n"'." 9268 t0=$| 9269 it $file 9270 replace_str. "../listmanip/","" 9271 gmd2html 2 9272 ot {n} rm. 9273 t1=$| 9274 e[] "\r > Generate '"$_vt100_c$file$_vt100_n"' (done in "$_vt100_g{_round($t1-$t0,0.1)}"s"$_vt100_n")." 9275 done 9276 x "rm -f *.gmd" 9277 9278 # Upload to G'MIC server. 9279 if $1 9280 e[] "\n > Transfer tutorial pages on G'MIC server.\n" 9281 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"mirror -RL . /www/gmic/tutorial ; quit\"" 9282 fi 9283 e[] "\n > All done.\n" 9284 9285# string2ts : ts_file.ts,strings_en.txt,strings_fr.txt 9286# Regenerate .ts file from new translated strings (separated by newline in files strings_*). 9287# Specified .ts file can be an empty argument (""). 9288strings2ts : skip "${1=}" 9289 e[^-1] "Regenerate translation file by merging file '$1' and source/translated strings '$2/$3'." 9290 9291 # Import data and extract original/translated strings. 9292 if narg($1) 9293 l[] it "$1" 9294 lang={`" 9295 lang = vector256(); 9296 p = find(#-1,'language=\"'); 9297 p>=0?( 9298 p+=10; 9299 q = find(#-1,'\">',p); 9300 q>=0?copy(lang,i[p],q - p); 9301 ); lang"`} 9302 e[] " > File '$1', detected language : "$lang. 9303 s -,10 9304 N0=0 9305 repeat $! l[$>] 9306 autocrop {'" "'} 9307 if s=crop();find(s,'<source>')>=0" && "find(s,'</source>')>=0 9308 discard {'<source>'} discard {'</source>'} src$N0={t} 9309 elif s=crop();find(s,'<translation>')>=0" && "find(s,'</translation>')>=0 9310 discard {'<translation>'} discard {'</translation>'} dest$N0={t} 9311 N0+=1 9312 fi 9313 endl done 9314 rm 9315 endl 9316 else N0=0 lang= 9317 fi 9318 if $N0 e[] " > File '$1' contains "$N0" strings." fi 9319 l[] it "$2" s -,10 N1=$! repeat $! nsrc$>={$>,t} done rm endl 9320 l[] it "$3" replace_str " ;",";" s -,10 N2=$! repeat $! ndest$>={$>,t} done rm endl 9321 if $N1!=$N2 error[0--3] "Command 'strings2ts': Number of lines do not match in files '$2' and '$3'." fi 9322 e[] " > Files '$2' and '$3' contain "$N1" strings." 9323 9324 # Merge all strings together (set higher priority to strings that were already in the .ts file). 9325 l[] repeat $N1 ({'${ndest$>}'}) nm. ${nsrc$>} done y endl 9326 repeat $N0 rmn ${src$>} done # Discard already-translated strings in the .ts file 9327 if $N0 i[0] 0 l[0] rm repeat $N0 i ({'${dest$>}'}) nm. ${src$>} done y endl fi 9328 repeat $! l[$<] src={n} dest={t} 9329 if lowercase(['$src'])==lowercase(['$dest']) rm fi 9330 endl done 9331 sort_list +,n 9332 e[] " > "$!" strings remain after cleaning/merging ("{$!-$N0}" new)." 9333 9334 # Generate .ts file. 9335 repeat $! l[$>] 9336 _strings2ts_src {n} src=${} 9337 _strings2ts_dest {t} dest=${} 9338 rm 9339 ({'" <message>"\n\ 9340 " <source>"$src"</source>"\n\ 9341 " <translation>"$dest"</translation>"\n\ 9342 " </message>"\n\n'}) 9343 endl done 9344 i[0] ({'"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\n\ 9345 "<!DOCTYPE TS>"\n\ 9346 "<TS version=\"2.1\" language=\""$lang"\">"\n\ 9347 " <context>"\n\ 9348 " <name>FilterTextTranslator</name>"\n\n'}) 9349 ({'" </context>"\n\ 9350 "</TS>"\n'}) 9351 y a y 9352 9353_strings2ts_src : 9354 ({'"$*"'}) 9355 replace_str. "°","°" 9356 replace_str. "à","à" 9357 replace_str. "&","&" 9358 replace_str. "<","<" 9359 replace_str. ">",">" 9360 replace_str. "\"",""" 9361 replace_str. "'","'" 9362 u {t} 9363 rm. 9364 9365_strings2ts_dest : 9366 ({'"$*"'}) html2utf8. 9367 replace_str. "°","°" 9368 replace_str. "à","à" 9369 replace_str. "&","&" 9370 replace_str. "<","<" 9371 replace_str. ">",">" 9372 replace_str. "\"",""" 9373 replace_str. "'","'" 9374 u {t} 9375 rm. 9376 9377# 9378# Output mode 'zart' (output in stdout). 9379# 9380parse_gui_parseparams_zart : u 1 # Tell parser to parse filter parameters 9381parse_gui_trigger_zart : 9382 repeat $! l[$>] # Keep only 1-level folders 9383 nm {`s=[['{n}'],0];p=find(s,_'/',size(s)-1,0);p>=0?(p=find(s,_'/',p-1,0);p>0?copy(s,s[p+1],size(s)-p));s`} 9384 endl done 9385 sort_list +,n 9386 9387parse_gui_zart : 9388 e[] " >> Generate output, in 'zart' mode.\n" 9389 +e[] "<?xml version=\"1.0\" ?>" 9390 +e[] "<document name=\"Presets\">\n" 9391 9392 current_group= 9393 N={$_nbfilters-1} 9394 repeat $_nbfilters,f 9395 e[] "\r >> "$_vt100_c[#$f/$N]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 9396 9397 # Manage groups. 9398 0 nm. {`s=['${_f${f}_path}'];s[0,size(s)-1]`} path={b} rm. 9399 if ['$current_group']!=['$path'] 9400 if ['$current_group']!=0 +e[] "</preset_group>\n" fi 9401 +e[] "<!-- ******** \n\n "$path"\n\n ******** -->" 9402 +e[] "<preset_group name=\""$path"\">\n" 9403 current_group=$path 9404 fi 9405 9406 # Filter definition. 9407 _parse_gui_zart[] ${_f${f}_name} fname=${} 9408 9409 +e[] "<!-- "$path/$fname" -->" 9410 +e[] "<preset name=\""$fname"\">" 9411 +e[] " <command>"${_f${f}_commandpreview}" $""*</command>" 9412 repeat ${_f${f}_nbparams},p 9413 _parse_gui_zart ${_f${f}_p{$p}_name} name=${} 9414 type=${_f${f}_p{$p}_type} 9415 nbargs=${_f${f}_p{$p}_nbargs} 9416 arg0= repeat $nbargs ('${_f${f}_p${p}_a$>}') autocrop. {'\"'} _parse_gui_zart {t} arg$>=${} rm. done 9417 9418 if ['$type']=='bool' 9419 if lowercase(['$arg0'])=='false' arg0=0 elif lowercase(['$arg0'])=='true' arg0=1 elif !isnum($arg0) arg0=0 fi 9420 +e[] " <bool name=\""$name"\" default=\""$arg0"\" />" 9421 9422 elif ['$type']=='choice' 9423 default=0 n=0 args= 9424 l[] if isint($arg0) default=$arg0 n+=1 fi onfail endl 9425 c= repeat $nbargs-$n,a args.=${c}"choice"$>"=\""${arg{$n+$a}}"\"" c=" " done 9426 +e[] " <choice name=\""$name"\" default=\""$default"\" "$args" />" 9427 9428 elif ['$type']=='color' 9429 if $nbargs==1" && "['$arg0'][0]==_'#' # Convert colors specified as '#RRGGBB[AA]' 9430 l[] ('$arg0') autocrop. {'#'} s x,-2 nbargs=$! repeat $!,a hex2dec {$>,t} arg$a=${} done rm endl 9431 fi 9432 args= c= repeat $nbargs,a args.=$c${arg$a} c="," done 9433 +e[] " <color name=\""$name"\" default=\""$args"\" />" 9434 9435 elif s=['$type'];s=='int'" || "s=='float' 9436 +e[] " <"$type" name=\""$name"\" default=\""$arg0"\" min=\""$arg1"\" max=\""$arg2"\" />" 9437 9438 elif ['$type']=='file'" || "['$type']=='filein'" || "['$type']=='fileout' 9439 +e[] " <file name=\""$name"\" default=\""$arg0"\" />" 9440 9441 elif ['$type']=='folder' 9442 +e[] " <folder name=\""$name"\" default=\""$arg0"\" />" 9443 9444 elif ['$type']=='link' 9445 align=-1 name= url= n=0 9446 l[] if isnum($arg0) align=$arg0 n+=1 fi onfail endl 9447 if $nbargs-$n>1 name=${arg$n} url=${arg{$n+1}} 9448 else url,name=${arg$n} 9449 fi 9450 if $align==0 align=left elif $align==1 align=right else align=center fi 9451 +e[] " <link name=\""$name"\" url=\""$url"\" align=\""$align"\" />" 9452 9453 elif ['$type']=='note' 9454 text={/$arg0} 9455 +e[] " <note text=\""$text"\" />" 9456 9457 elif ['$type']=='point' 9458 +e[] " <point name=\""$name"\" position=\""$arg0,$arg1"\" />" 9459 9460 elif ['$type']=='separator' 9461 +e[] " <separator />" 9462 9463 elif ['$type']=='text' 9464 +e[] " <text name=\""$name"\" default=\""$arg0"\" />" 9465 9466 elif ['$type']=='value' 9467 +e[] " <value value=\""$arg0"\" />" 9468 9469 else # Unsupported parameter 9470 +e[] " <value value=\""$arg0"\" />" 9471 fi 9472 9473 done 9474 +e[] "</preset>\n" 9475 done 9476 if narg($current_group) +e[] "</preset_group>" fi 9477 +e[] "</document>" 9478 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 9479 9480_parse_gui_zart : 9481 l[] 9482 ('"$*"') 9483 replace_str "&","#amp;" 9484 replace_str. "&","&" 9485 replace_str. "<","<" 9486 replace_str. ">",">" 9487 replace_str. "\"",""" 9488 replace_str "#amp;","&" 9489 u {t} rm. 9490 onfail u "" endl 9491 9492# Convert last ascii buffer with html codes (e.g. 配), as an UTF-8 encoded buffer. 9493html2utf8 : 9494 if h 9495 eval " 9496 ref(crop(),source); 9497 ref(vector8(),svalue); 9498 p = 0; 9499 while (1, 9500 p = p0 = find(source,'&#',p); 9501 p<0?break(); 9502 p+=2; 9503 p>=size(source)?break(); 9504 q = find(source,';',p); 9505 q>p && q<=p+8 && !isnan(val=stov(source,p))?( 9506 copy(svalue,source[p],q-p); svalue[q-p] = 0; 9507 val = stov(svalue,0,1); 9508 !isnan(val) && isint(val) && val>0?( 9509 9510 # Encode in UTF-8. 9511 val<=0x007f?( # 7 bits or less -> 1 byte 9512 i[p0++] = val; 9513 ):val<=0x07ff?( # 11 bits or less -> 2 bytes 9514 i[p0++] = (val>>6)|0xc0; 9515 i[p0++] = (val&0x3f)|0x80; 9516 ):val<=0xffff?( # 16 bits or less -> 3 bytes 9517 i[p0++] = (val>>12)|0xe0; 9518 i[p0++] = ((val>>6)&0x3f)|0x80; 9519 i[p0++] = (val&0x3f)|0x80; 9520 ):( # 21 bits or less -> 4 bytes 9521 i[p0++] = (val>>18)|0xf0; 9522 i[p0++] = ((val>>12)&0x3f)|0x80; 9523 i[p0++] = ((val>>6)&0x3f)|0x80; 9524 i[p0++] = (val&0x3f)|0x80; 9525 ); 9526 copy(i[p0],-1,q-p0+1,1,0); 9527 p = q + 1; 9528 ); 9529 ); 9530 )" 9531 discard. -1 9532 fi 9533 9534# Convert last UTF-8 encoded buffer to ascii buffer with html codes. 9535utf82html : 9536 if h 9537 eval " 9538 write_seq() = ( copy(res[q],'&#'); q+=2; s = vtos(val); l = find(s,0); copy(res[q],s,l); q+=l; res[q++]=_';' ); 9539 ref(vector(#4*wh),res); 9540 q = 0; 9541 repeat (wh,p, 9542 i = i[p]; 9543 !(i&0x80)?( # 1-byte 9544 res[q++] = i; 9545 ):(i&0xe0)==0xc0?( # 2-bytes 9546 val = (i&0x1f)<<6; i = i[p + 1]; val|= (i&0x3f); 9547 write_seq(); 9548 ):(i&0xf0)==0xe0?( # 3-bytes 9549 val = (i&0xf)<<12; i = i[p + 1]; val|= (i&0x3f)<<6; i = i[p + 2]; val|= (i&0x3f); 9550 write_seq(); 9551 ):(i&0xf8)==0xf0?( # 4-bytes 9552 val = (i&0x7)<<18; i = i[p + 1]; val|= (i&0x3f)<<12; i = i[p + 2]; val|= (i&0x3f)<<6; 9553 i = i[p + 3]; val|= (i&0x3f); 9554 write_seq(); 9555 ); 9556 ); 9557 store(res,'res',1,q)" 9558 rm. $res 9559 fi 9560 9561# Force certain filters to move from one path to another. 9562_upload_filters_move : 9563 m "move_filter : skip \"${""2=}\" nmd 3,\"$""1\" ind=${} 9564 if $ind basename \"$""1\" nm[$ind] \"$""2\"/${} 9565 else v 0 e[0--4] \"Cannot move unknown filter '\"${_vt100_r}\"$""1\"${_vt100_n}\"' 9566 to '\"${_vt100_g}\"$""2\"${_vt100_n}\"'\" fi" 9567 9568 sort_list +,n 9569 move_filter "Testing/Garagecoder/Anti Alias","Repair" 9570 move_filter "Testing/Garagecoder/Auto Balance","Colors" 9571 move_filter "Testing/Garagecoder/LMS Adjustment","Colors" 9572 move_filter "Testing/Garagecoder/Compression Blur","Repair" 9573 move_filter "Testing/Garagecoder/Emboss","Black & White" 9574 move_filter "Testing/Garagecoder/JPEG Smooth","Repair" 9575 move_filter "Testing/Garagecoder/Quick Tonemap","Details" 9576 move_filter "Testing/Garagecoder/Normalize Brightness","Colors" 9577 move_filter "Testing/Garagecoder/Sharpen [Gradient]","Details" 9578 move_filter "Testing/Garagecoder/Sharpen [Tones]","Details" 9579 move_filter "Testing/Garagecoder/Temperature Balance","Colors" 9580 move_filter "Testing/Garagecoder/Unquantize [JPEG Smooth]","Repair" 9581 move_filter "Testing/Garagecoder/Upscale [Edge]","Repair" 9582 move_filter "Testing/Garagecoder/Wiremap","Rendering" 9583 move_filter "Testing/Garagecoder/Smooth [Geometric-Median]","Repair" 9584 move_filter "Testing/Gmic Tutorials/Hedcut (Experimental)","Patterns" 9585 move_filter "Testing/Iain Fergusson/Easy Skin Retouch","Details" 9586 move_filter "Testing/Iain Fergusson/Moire Removal","Repair" 9587 move_filter "Testing/Iain Fergusson/Halftone Shapes","Patterns" 9588 move_filter "Testing/Iain Fergusson/Simple Local Contrast","Details" 9589 move_filter "Testing/Iain Fergusson/Turbulent Halftone","Patterns" 9590 move_filter "Testing/Joan Rake/Deformations/Ultrawarp++++","Degradations" 9591 move_filter "Testing/Naggobot/Blockism","Artistic" 9592 move_filter "Testing/Reptorian/Blur [Splinter]","Degradations" 9593 move_filter "Testing/Reptorian/Construction Material Texture","Rendering" 9594 move_filter "Testing/Reptorian/Emboss-Relief","Details" 9595 move_filter "Testing/Reptorian/Fragment Blur","Degradations" 9596 move_filter "Testing/Reptorian/Kaleidoscope [Reptorian-Polar]","Deformations" 9597 move_filter "Testing/Reptorian/Logarithmic Distortion","Deformations" 9598 move_filter "Testing/Reptorian/Nebulous","Rendering" 9599 move_filter "Testing/Reptorian/Pixel Push","Deformations" 9600 move_filter "Testing/Reptorian/Point Warp","Deformations" 9601 move_filter "Testing/Reptorian/Popcorn Fractal","Rendering" 9602 move_filter "Testing/Reptorian/Pseudorandom Noise","Rendering" 9603 move_filter "Testing/Reptorian/Sinusoidal Water Distortion","Deformations" 9604 move_filter "Testing/Samj/Arrays & Tiles/Annular Steiner Chain Round Tile","Arrays & Tiles" 9605 move_filter "Testing/Samj/Arrays & Tiles/Reptile","Patterns" 9606 move_filter "Testing/Samj/Artistic/Angoisse Anguish","Artistic" 9607 move_filter "Testing/Samj/Artistic/Chalk It Up [Fr]","Artistic" 9608 move_filter "Testing/Samj/Artistic/Barbouillage Paint Daub","Artistic" 9609 move_filter "Testing/Samj/Artistic/Skeletik","Artistic" 9610 move_filter "Testing/Samj/Patterns/Denim Texture","Patterns" 9611 move_filter "Testing/Samj/Patterns/Soft Random Shades","Patterns" 9612 move_filter "Testing/Samj/Rendering/Pythagoras Tree","Rendering" 9613 move_filter "Testing/Samj/Rendering/Snowflake 2","Rendering" 9614 move_filter "Testing/Samj/Rendering/Twisted Rays","Rendering" 9615 move_filter "Testing/Souphead/Disco","Rendering" 9616 move_filter "Testing/Souphead/Moon2panorama","Deformations" 9617 move_filter "Testing/Souphead/Spiral RGB","Rendering" 9618 move_filter "Testing/Souphead/Kitaoka Spin Illusion","Rendering" 9619 move_filter "Testing/Zonderr/Spiral","Rendering" 9620 um move_filter 9621 9622upload_filters : 9623 e[^-1] "Upload filter definition file on G'MIC server.\n" 9624 rm 9625 9626 # Be sure to get the latest version of filters. 9627 x "cd "$HOME"/work/src/gmic && git pull" 9628 x "cd "$HOME"/work/src/gmic-community && git pull" 9629 9630 # Define the list of compatible versions. 9631 (300,$_version) store. compat 9632 9633 # Import filters from stdlib and community. 9634 files $HOME/work/src/gmic-community/include/*.gmic 9635 files=${},$HOME/work/src/gmic/src/gmic_stdlib.gmic 9636 repeat narg($files) l[] 9637 file=${"arg 1+$>,"$files} 9638 it[] $file 9639 basename $file basename=${} 9640 if ['$basename']=='sylvie_alexandre.gmic' 9641 s +,{'"#@gui <b>"'} i[1--2:2] ('"#@gui ________<b>Testing<b>\n#@gui <i>Samj</i>\n"') y a y 9642 elif s=['$basename'];s=='template.gmic' 9643 rm 0 9644 fi 9645 endl done 9646 i[1--2] ('"#@gui _________________\n"') y a y 9647 9648 # Create update file. 9649 +l. 9650 e[] "** Generate filter update file." 9651 m "parse_gui_trigger_update : _upload_filters_move" 9652 v + parse_gui. update v - 9653 um parse_gui_trigger_update 9654 9655 # Upload filter files on G'MIC server. 9656 e[] "** Upload filter update." 9657 ot ${_path_rc}update$_version.gmic 9658 if "d = date(3); h = date(4); h>=7 && d>=1 && d<=5" url=http://bit.ly/2CmhX65 # url=http://bit.ly/2uaBRMB 9659 else url=https://bit.ly/33lRzX4 # https://bit.ly/2WeKVPv url=http://bit.ly/2uaBRMB # 9660 fi 9661 replace_str "<i>David Tschumperlé</i>","<i><a href=\""$url"\">David Tschumperlé</a></i>" 9662 o cimgz:/tmp/update$_version.gmic,uchar 9663 9664 $compat 9665 repeat w 9666 v={i[$>]} 9667 _upload[] ${_path_rc}update$_version.gmic,plain_update$v.gmic,1 9668 _upload[] /tmp/update$_version.gmic,update$v.gmic,1 9669 done 9670 rm 9671 endl 9672 9673 # Create JSON file. 9674 +l. 9675 e[] "** Generate JSON filters file." 9676 v + parse_gui. json v - 9677 9678 # Upload filter files on G'MIC server. 9679 e[] "** Upload JSON filters." 9680 ot ${_path_rc}/update$_version.json 9681 9682 $compat 9683 repeat w 9684 v={i[$>]} 9685 _upload[] ${_path_rc}/update$_version.json,update$v.json,1 9686 done 9687 rm 9688 endl 9689 9690 # Create filter listing. 9691 +l. 9692 e[] "** Generate filter listing." 9693 v + parse_gui. list v - 9694 ot /tmp/gui_filters.txt 9695 rm 9696 endl 9697 rm 9698 9699_upload : skip "${2=""}","${3=0}" 9700 if narg("$2") out="$2" else basename "$1" out=${} fi 9701 if !narg($GMIC_LOGIN) 9702 GMIC_LOGIN=${"gmic_ftp 0"} 9703 GMIC_PASSWD=${"gmic_ftp 1"} 9704 GMIC_FTP=${"gmic_ftp 2"} 9705 fi 9706 if narg($GMIC_LOGIN) 9707 x $3,"lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"put -O /www/gmic/ \\\"$1\\\" -o \\\""$out"\\\"; 9708 quit\" >/dev/null" 9709 fi 9710 9711# Upload or list released binaries on the G'MIC web server. 9712# $1=version number (e.g "1.6.7_pre") 9713# $2={ 0=print list of URLs | 1=upload files } 9714upload_binaries : check "isbool(${2=1})" 9715 is_pre=${"strcontains $1,_pre"} 9716 N=0 9717 file$N=gmic_$1_debian9-2_stretch_amd64.deb N+=1 9718 file$N=gmic_$1_debian10_buster_amd64.deb N+=1 9719 file$N=gmic_$1_ubuntu18-10_cosmic_amd64.deb N+=1 9720 file$N=gmic_$1_ubuntu19-04_disco_amd64.deb N+=1 9721 file$N=gmic_$1_ubuntu19-10_eoan_amd64.deb N+=1 9722 file$N=gmic_$1_ubuntu20-04_focal_amd64.deb N+=1 9723 file$N=gmic_$1_ubuntu20-10_groovy_amd64.deb N+=1 9724 file$N=gmic_$1_ubuntu21-04_hirsute_amd64.deb N+=1 9725 file$N=gmic_$1_ubuntu21-10_impish_amd64.deb N+=1 9726 9727 file$N=gmic_$1_gimp2.8_debian9-2_stretch_amd64.zip N+=1 9728 file$N=gmic_$1_gimp2.10_debian10_buster_amd64.zip N+=1 9729 file$N=gmic_$1_gimp2.10_ubuntu18-10_cosmic_amd64.zip N+=1 9730 file$N=gmic_$1_gimp2.10_ubuntu19-04_disco_amd64.zip N+=1 9731 file$N=gmic_$1_gimp2.10_ubuntu19-10_eoan_amd64.zip N+=1 9732 file$N=gmic_$1_gimp2.10_ubuntu20-04_focal_amd64.zip N+=1 9733 file$N=gmic_$1_gimp2.10_ubuntu20-10_groovy_amd64.zip N+=1 9734 file$N=gmic_$1_gimp2.10_ubuntu21-04_hirsute_amd64.zip N+=1 9735 file$N=gmic_$1_gimp2.10_ubuntu21-10_impish_amd64.zip N+=1 9736 9737 file$N=gmic_$1_krita_debian9-2_stretch_amd64.zip N+=1 9738 file$N=gmic_$1_krita_debian10_buster_amd64.zip N+=1 9739 file$N=gmic_$1_krita_ubuntu18-10_cosmic_amd64.zip N+=1 9740 file$N=gmic_$1_krita_ubuntu19-04_disco_amd64.zip N+=1 9741 file$N=gmic_$1_krita_ubuntu19-10_eoan_amd64.zip N+=1 9742 file$N=gmic_$1_krita_ubuntu20-04_focal_amd64.zip N+=1 9743 file$N=gmic_$1_krita_ubuntu20-10_groovy_amd64.zip N+=1 9744 file$N=gmic_$1_krita_ubuntu21-04_hirsute_amd64.zip N+=1 9745 file$N=gmic_$1_krita_ubuntu21-10_impish_amd64.zip N+=1 9746 9747 file$N=gmic_$1_cli_win64.zip N+=1 9748 file$N=gmic_$1_lib_win64.zip N+=1 9749 file$N=gmic_$1_qt_win64.zip N+=1 9750 file$N=gmic_$1_gimp2.10_win64.zip N+=1 9751 file$N=gmic_$1_gimp2.10_win64.exe N+=1 9752 file$N=gmic_$1_krita_win64.zip N+=1 9753 9754 if !$2 # Only get list of URLs 9755 e[0--3] "List URLs of released binaries ($1) from the G'MIC web server.\n" 9756 repeat $N 9757 file=${file$>} 9758 is_win=${strcontains[]" "$file,win} 9759 if $is_win folder="windows" else folder="linux" fi 9760 e[] "http://gmic.eu/files/"$folder/$file 9761 done 9762 e[] "" 9763 9764 else # Upload files 9765 e[0--3] "Upload released binaries ($1) on the G'MIC web server." 9766 9767 t0=$| n=0 t=0 9768 e[] "- Waiting for binary files to be build." 9769 do 9770 repeat $N 9771 file=${file$>} 9772 if isfile(['{/$file}']) 9773 strreplace $file,_$1_,_ 9774 file_short=${} 9775 is_win=${strcontains[]" "$file,win} 9776 if $is_win folder="windows" else folder="linux" fi 9777 e[] "- Upload file '"$file"' to 'https://gmic.eu/files/prerelease/"$file_short"'." 9778 _upload[] $file,"files/prerelease/"$file_short 9779 if !$is_pre 9780 e[] "- Upload file '"$file"' to 'https://gmic.eu/files/"$folder/$file"'." 9781 _upload[] $file,"files/"$folder/$file 9782 fi 9783 9784 file$>= n+=1 9785 fi 9786 done 9787 if $n<$N 9788 if !($t%4) 9789 remaining= sep= 9790 repeat $N if narg(${file$>}) remaining.=${sep}${file$>} sep=", " fi done 9791 e[] "- Waiting for files: "$remaining"." 9792 fi 9793 wait 30000 t+=1 9794 fi 9795 while $n<$N" && "$|<$t0+60*60*6 9796 if $n<$N e[] "- Partial uploads done (timeout reached)." 9797 else e[] "- All uploads done !" 9798 fi 9799 fi 9800 9801# Update version number in html header file. 9802# (works both for CImg and G'MIC !) 9803# $1 = filename 9804# $2 = version number 9805# $3 = is_prerelease = { 0 | 1 } 9806_update_header_html : check "narg(${1=}) && ${2=0}>0 && isbool(${3=0})" 9807 filename="$1" 9808 l[] 9809 it[] $filename 9810 s +,{'\n'} 9811 repeat $! if {$>,h>=64} l[$>] 9812 +autocrop {'" "'} autocrop. {'\t'} 9813 if "find(#0,['Latest stable version: '])>=0" 9814 is_gmic={"find(#-1,'gmic.eu')>=0"} 9815 is_cimg={"find(#-1,'cimg.eu')>=0"} 9816 if !$is_gmic" && "!$is_cimg error "Cannot determine CImg or G'MIC header file." fi 9817 9818 # Retrieve latest stable version specified in the header file. 9819 +l. s -,{'>'} 9820 if {2,"i[0]>=_'0' && i[0]<=_'9' && i[1]==_'.' && i[2]>=_'0' && i[2]<=_'9' && 9821 i[3]==_'.' && i[4]>=_'0' && i[4]<=_'9'"} 9822 sta={2,`crop(0,0,1,5)`} 9823 fi 9824 if $3 pre=${strver\ $2} else sta=${strver\ $2} fi 9825 rm endl 9826 rm[0] 9827 if $is_gmic 9828 i[0] ('" Latest stable version: <b>"\ 9829 "<a href=\"https://gmic.eu/download.html\">"$sta"</a></b>"') 9830 if $3 9831 i[1] ('" "\ 9832 "Current pre-release: <b><a href=\"https://gmic.eu/files/prerelease\">"$pre"</a></b>"') 9833 fi 9834 else 9835 i[0] ('" Latest stable version: "\ 9836 "<b><a href=\"http://cimg.eu/files/CImg_"$sta".zip\">"$sta"</a></b>"') 9837 if $3 9838 i[1] ('" "\ 9839 "Current pre-release: <b><a href=\"http://cimg.eu/files/CImg_latest.zip\">"$pre"</a></b>"') 9840 fi 9841 fi 9842 y 9843 fi 9844 rm. 9845 endl fi done 9846 a y 9847 ot $filename 9848 rm 9849 endl 9850 9851#@cli v : eq. to 'verbose'. : (+) 9852 9853#@cli verbose : level : { + | - } : (+) 9854#@cli : Set or increment/decrement the verbosity level. Default level is 0. 9855#@cli : (eq. to 'v').\n 9856#@cli : When 'level'>0, G'MIC log messages are displayed on the standard error (stderr). 9857#@cli : Default value: 'level=1'. 9858 9859#@cli wait : delay : (no arg) : (+) 9860#@cli : Wait for a given delay (in ms), optionally since the last call to 'wait'. 9861#@cli : or wait for a user event occurring on the selected instant display windows. 9862#@cli : 'delay' can be { <0=delay+flush events | 0=event | >0=delay }. 9863#@cli : Command selection (if any) stands for instant display window indices instead of image indices. 9864#@cli : If no window indices are specified and if 'delay' is positive, the command results 9865#@cli : in a 'hard' sleep during specified delay. 9866#@cli : Default value: 'delay=0'. 9867 9868#@cli warn : _force_visible={ 0 | 1 },_message : (+) 9869#@cli : Print specified warning message, on the standard error (stderr). 9870#@cli : Command selection (if any) stands for displayed call stack subset instead of image indices. 9871 9872#@cli w : eq. to 'window'. : (+) 9873 9874#@cli window : _width[%]>=-1,_height[%]>=-1,_normalization,_fullscreen,_pos_x[%],_pos_y[%],_title : (+) 9875#@cli : Display selected images into an instant display window with specified size, normalization type, 9876#@cli : fullscreen mode and title. 9877#@cli : (eq. to 'w').\n 9878#@cli : If 'width' or 'height' is set to -1, the corresponding dimension is adjusted to the window 9879#@cli : or image size. 9880#@cli : Specify 'pos_x' and 'pos_y' arguments only if the window has to be moved to the specified 9881#@cli : coordinates. Otherwise, they can be avoided. 9882#@cli : 'width'=0 or 'height'=0 closes the instant display window. 9883#@cli : 'normalization' can be { -1=keep same | 0=none | 1=always | 2=1st-time | 3=auto }. 9884#@cli : 'fullscreen' can be { -1=keep same | 0=no | 1=yes }. 9885#@cli : You can manage up to 10 different instant display windows by using the numbered variants 9886#@cli : 'w0' (default, eq. to 'w'),'w1',...,'w9' of the command 'w'. 9887#@cli : Invoke 'window' with no selection to make the window visible, if it has been closed by the user. 9888#@cli : Default values: 'width=height=normalization=fullscreen=-1' and 'title=(undefined)'. 9889 9890#--------------------------------- 9891# 9892#@cli :: List Manipulation 9893# 9894#--------------------------------- 9895 9896#@cli k : eq. to 'keep'. : (+) 9897 9898#@cli keep : (+) 9899#@cli : Keep only selected images. 9900#@cli : (eq. to 'k'). 9901#@cli : $ image.jpg split x keep[0-50%:2] append x 9902#@cli : $ image.jpg split x keep[^30%-70%] append x 9903 9904#@cli mv : eq. to 'move'. : (+) 9905 9906#@cli move : position[%] : (+) 9907#@cli : Move selected images at specified position. 9908#@cli : (eq. to 'mv'). 9909#@cli : $ image.jpg split x,3 move[1] 0 9910#@cli : $ image.jpg split x move[50%--1:2] 0 append x 9911 9912#@cli nm : eq. to 'name'. : (+) 9913 9914#@cli name : "name1","name2",... : (+) 9915#@cli : Set names of selected images. 9916#@cli : - If the selection contains a single image, then it is assumed the command has a single name 9917#@cli : argument (possibly containing multiple comas). 9918#@cli : - If the selection contains more than one image, each command argument defines a single image 9919#@cli : name for each image of the selection. 9920#@cli : (eq. to 'nm'). 9921#@cli : $ image.jpg name image blur[image] 2 9922#@cli : $$ 9923 9924#@cli rm : eq. to 'remove'. : (+) 9925 9926#@cli remove : (+) 9927#@cli : Remove selected images. 9928#@cli : (eq. to 'rm'). 9929#@cli : $ image.jpg split x remove[30%-70%] append x 9930#@cli : $ image.jpg split x remove[0-50%:2] append x 9931 9932#@cli remove_duplicates 9933#@cli : Remove duplicates images in the selected images list. 9934#@cli : $ (1,2,3,4,2,4,3,1,3,4,2,1) split x remove_duplicates append x 9935remove_duplicates : 9936 e[^-1] "Remove duplicates images in selected list of image$?." 9937 repeat $!,base 9938 off=0 9939 repeat $!-$>-1 9940 comp={$base+1+$>-$off} 9941 if $comp>=$! break fi 9942 +-[$base,$comp] abs. is_duplicate={!is} rm. 9943 if $is_duplicate rm[$comp] off+=1 fi 9944 done 9945 done 9946 9947#@cli remove_empty 9948#@cli : Remove empty images in the selected image list. 9949remove_empty : 9950 e[^-1] "Remove empty images in selected list of image$?." 9951 $!,1,1,1,"!w#x?x:-1" discard. -1 rm[{^},-1] 9952 9953#@cli rmn : eq. to 'remove_named'. 9954rmn : 9955 e[^-1] "Remove images named '$*'." 9956 nmd $"*" rm[${}] 9957 9958#@cli remove_named : "name1","name2",... 9959#@cli : Remove all images with specified names from the list of images. 9960#@cli : Does nothing if no images with those names exist. 9961#@cli : (eq. to 'rmn'). 9962remove_named : 9963 e[^-1] "Remove images named '$*'." 9964 nmd $"*" rm[${}] 9965 9966#@cli rv : eq. to 'reverse'. : (+) 9967 9968#@cli reverse : (+) 9969#@cli : Reverse positions of selected images. 9970#@cli : (eq. to 'rv'). 9971#@cli : $ image.jpg split x,3 reverse[-2,-1] 9972#@cli : $ image.jpg split x,-16 reverse[50%-100%] append x 9973 9974#@cli sort_list : _ordering={ + | - },_criterion 9975#@cli : Sort list of selected images according to the specified image criterion. 9976#@cli : Default values: 'ordering=+', 'criterion=i'. 9977#@cli : $ (1;4;7;3;9;2;4;7;6;3;9;1;0;3;3;2) split y sort_list +,i append y 9978sort_list : skip ${1=+},${2=i} 9979 s0="descending" s1="ascending" 9980 e[^-1] "Sort list of image$? in "${s{_'+'=='$1'}}" order, according to the image criterion '$2'." 9981 if $! 9982 if '$2'=='n'||'$2'=='N' # Special case : lexicographic order from image names (n: ignore case, N: consider case) 9983 op={`;'$1'=='-'?_'>':_'<'`} 9984 if '$2'=='n' fn=lowercase else fn= fi 9985 $!,1,1,1,"n = name(#x,1024); find(n,0)%1025" slen={iM} rm. # Largest name length. 9986 eval " 9987 const lm1 = l - 1; 9988 const slen = "$slen"; 9989 strcmp(n0,n1) = (for (k = 0, k<slen && !(diff = "$fn"(n0[k]) - "$fn"(n1[k])), ++k); diff); 9990 quicksort(lo0,hi0) = ( 9991 stack = vector(#2*l); 9992 stacksize = 0; 9993 push(elt0,elt1) = (stack[stacksize++] = elt0; stack[stacksize++] = elt1); 9994 pop() = (_s1 = stack[--stacksize]; _s0 = stack[--stacksize]; [_s0,_s1]); 9995 push(lo0,hi0); 9996 while (stacksize>0, 9997 range = pop(); 9998 lo = range[0]; 9999 hi = range[1]; 10000 pivot = int((lo + hi)/2); 10001 ref(name(#pivot,slen),npivot); 10002 while (lo<hi, 10003 while ((ref(name(#lo,slen),nlo);strcmp(nlo,npivot)<0), ++lo); 10004 while ((ref(name(#hi,slen),nhi);strcmp(npivot,nhi)<0), --hi); 10005 lo<=hi?(lo!=hi?run('rv[',lo,',',hi,']'); ++lo; --hi); 10006 ); 10007 if (range[0]<hi,push(range[0],hi)); 10008 if (lo<range[1],push(lo,range[1])); 10009 ) 10010 ); 10011 quicksort(0,lm1)" 10012 10013 else # Generic case 10014 i=$! repeat $! ({$>,$2}) done a[$i--1] y +f. 'y' a[-2,-1] x sort. $1,y z. 1,1 10015 repeat h nm$>={$>,n} nm[$>] sortlist$> done 10016 repeat h mv[sortlist{i(0,$>)}] -1 done 10017 repeat h nm[$>] ${nm{i(0,$>)}} done 10018 rm. 10019 fi 10020 fi 10021 10022#--------------------------------- 10023# 10024#@cli :: Mathematical Operators 10025# 10026#--------------------------------- 10027 10028#@cli abs : (+) 10029#@cli : Compute the pointwise absolute values of selected images. 10030#@cli : $ image.jpg +sub {ia} abs[-1] 10031#@cli : $ 300,1,1,1,'cos(20*x/w)' +abs display_graph 400,300 10032 10033#@cli acos : (+) 10034#@cli : Compute the pointwise arccosine of selected images. 10035#@cli : $ image.jpg +normalize -1,1 acos[-1] 10036#@cli : $ 300,1,1,1,'cut(x/w+0.1*u,0,1)' +acos display_graph 400,300 10037#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 10038 10039#@cli acosh : (+) 10040#@cli : Compute the pointwise hyperbolic arccosine of selected images. 10041 10042#@cli + : eq. to 'add'. : (+) 10043 10044#@cli add : value[%] : [image] : 'formula' : (no arg) : (+) 10045#@cli : Add specified value, image or mathematical expression to selected images, \ 10046# or compute the pointwise sum of selected images. 10047#@cli : (eq. to '+'). 10048#@cli : $ image.jpg +add 30% cut 0,255 10049#@cli : $ image.jpg +blur 5 normalize 0,255 add[1] [0] 10050#@cli : $ image.jpg add '80*cos(80*(x/w-0.5)*(y/w-0.5)+c)' cut 0,255 10051#@cli : $ image.jpg repeat 9 +rotate[0] {$>*36},1,0,50%,50% done add div 10 10052 10053#@cli & : eq. to 'and'. : (+) 10054 10055#@cli and : value[%] : [image] : 'formula' : (no arg) : (+) 10056#@cli : Compute the bitwise AND of selected images with specified value, image or mathematical \ 10057# expression, or compute the pointwise sequential bitwise AND of selected images. 10058#@cli : (eq. to '&'). 10059#@cli : $ image.jpg and {128+64} 10060#@cli : $ image.jpg +mirror x and 10061 10062#@cli argmax 10063#@cli : Compute the argmax of selected images. Returns a single image 10064#@cli : with each pixel value being the index of the input image with maximal value. 10065#@cli : $ image.jpg sample lena,lion,square +argmax 10066argmax : 10067 e[^-1] "Compute argmax of image$?." 10068 if !$! return fi 10069 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 10070 ${-max_whds},"argmax("$str")" k. nm [argmax] 10071 10072#@cli argmaxabs 10073#@cli : Compute the argmaxabs of selected images. Returns a single image 10074#@cli : with each pixel value being the index of the input image with maxabs value. 10075argmaxabs : 10076 e[^-1] "Compute argmaxabs of image$?." 10077 if !$! return fi 10078 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 10079 ${-max_whds},"argmaxabs("$str")" k. nm [argmaxabs] 10080 10081#@cli argmin 10082#@cli : Compute the argmin of selected images. Returns a single image 10083#@cli : with each pixel value being the index of the input image with minimal value. 10084#@cli : $ image.jpg sample lena,lion,square +argmin 10085argmin : 10086 e[^-1] "Compute argmin of image$?." 10087 if !$! return fi 10088 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 10089 ${-max_whds},"argmin("$str")" k. nm [argmin] 10090 10091#@cli argminabs 10092#@cli : Compute the argminabs of selected images. Returns a single image 10093#@cli : with each pixel value being the index of the input image with minabs value. 10094argminabs : 10095 e[^-1] "Compute argminabs of image$?." 10096 if !$! return fi 10097 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 10098 ${-max_whds},"argminabs("$str")" k. nm [argminabs] 10099 10100#@cli asin : (+) 10101#@cli : Compute the pointwise arcsine of selected images. 10102#@cli : $ image.jpg +normalize -1,1 asin[-1] 10103#@cli : $ 300,1,1,1,'cut(x/w+0.1*u,0,1)' +asin display_graph 400,300 10104#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 10105 10106#@cli asinh : (+) 10107#@cli : Compute the pointwise hyperbolic arcsine of selected images. 10108 10109#@cli atan : (+) 10110#@cli : Compute the pointwise arctangent of selected images. 10111#@cli : $ image.jpg +normalize 0,8 atan[-1] 10112#@cli : $ 300,1,1,1,'4*x/w+u' +atan display_graph 400,300 10113#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 10114 10115#@cli atan2 : [x_argument] : (+) 10116#@cli : Compute the pointwise oriented arctangent of selected images. 10117#@cli : Each selected image is regarded as the y-argument of the arctangent function, while the 10118#@cli : specified image gives the corresponding x-argument. 10119#@cli : $ (-1,1) (-1;1) resize 400,400,1,1,3 atan2[1] [0] keep[1] mod {pi/8} 10120#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 10121 10122#@cli atanh : (+) 10123#@cli : Compute the pointwise hyperbolic arctangent of selected images. 10124 10125#@cli << : eq. to 'bsl'. : (+) 10126 10127#@cli bsl : value[%] : [image] : 'formula' : (no arg) : (+) 10128#@cli : Compute the bitwise left shift of selected images with specified value, image or \ 10129# mathematical expression, or compute the pointwise sequential bitwise left shift of \ 10130# selected images. 10131#@cli : (eq. to '<<'). 10132#@cli : $ image.jpg bsl 'round(3*x/w,0)' cut 0,255 10133 10134#@cli >> : eq. to 'bsr'. : (+) 10135 10136#@cli bsr : value[%] : [image] : 'formula' : (no arg) : (+) 10137#@cli : Compute the bitwise right shift of selected images with specified value, image or \ 10138# mathematical expression, or compute the pointwise sequential bitwise right shift of \ 10139# selected images. 10140#@cli : (eq. to '>>'). 10141#@cli : $ image.jpg bsr 'round(3*x/w,0)' cut 0,255 10142 10143#@cli cos : (+) 10144#@cli : Compute the pointwise cosine of selected images. 10145#@cli : $ image.jpg +normalize 0,{2*pi} cos[-1] 10146#@cli : $ 300,1,1,1,'20*x/w+u' +cos display_graph 400,300 10147#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 10148 10149#@cli cosh : (+) 10150#@cli : Compute the pointwise hyperbolic cosine of selected images. 10151#@cli : $ image.jpg +normalize -3,3 cosh[-1] 10152#@cli : $ 300,1,1,1,'4*x/w+u' +cosh display_graph 400,300 10153 10154#@cli deg2rad 10155#@cli : Convert pointwise angle values of selected images, from degrees to radians (apply 'i*pi/180'). 10156deg2rad : 10157 e[^-1] "Convert pointwise angle values of image$?, from degrees to radians." 10158 * 0.017453292519943295 10159 10160#@cli / : eq. to 'div'. : (+) 10161 10162#@cli div : value[%] : [image] : 'formula' : (no arg) : (+) 10163#@cli : Divide selected images by specified value, image or mathematical expression, \ 10164# or compute the pointwise quotient of selected images. 10165#@cli : (eq. to '/'). 10166#@cli : $ image.jpg div '1+abs(cos(x/10)*sin(y/10))' 10167#@cli : $ image.jpg +norm add[-1] 1 +div 10168 10169#@cli div_complex : [divider_real,divider_imag],_epsilon>=0 10170#@cli : Perform division of the selected complex pairs (real1,imag1,...,realN,imagN) of images by 10171#@cli : specified complex pair of images (divider_real,divider_imag). 10172#@cli : In complex pairs, the real image must be always located before the imaginary image in the image list. 10173#@cli : Default value: 'epsilon=1e-8'. 10174div_complex : check ${3=1e-8}>=0 10175 e[^-1] "Divide complex pair$? by complex pair "${"pass$1,$2 -1"}" (with epsilon $3)." 10176 repeat int($!/2) pass${1,2} 0 l[$>,{$>+1},-2,-1] 10177 +*[1,2] +*[0,3] -[-2,-1] # bc-ad 10178 *[0] [2] *[1] [3] +[0,1] # ac+bd 10179 sqr[1,2] +[1,2] +[1] $3 # c^2+d^2 10180 /[2] [1] /[0,1] 10181 endl done 10182 10183#@cli == : eq. to 'eq'. : (+) 10184 10185#@cli eq : value[%] : [image] : 'formula' : (no arg) : (+) 10186#@cli : Compute the boolean equality of selected images with specified value, image or \ 10187# mathematical expression, or compute the boolean equality of selected images. 10188#@cli : (eq. to '=='). 10189#@cli : $ image.jpg round 40 eq {round(ia,40)} 10190#@cli : $ image.jpg +mirror x eq 10191 10192#@cli erf : (+) 10193#@cli : Compute the pointwise error function of selected images. 10194#@cli : $ image.jpg +normalize 0,2 erf[-1] 10195#@cli : $ 300,1,1,1,'7*x/w-3.5+u' +erf display_graph 400,300 10196 10197#@cli exp : (+) 10198#@cli : Compute the pointwise exponential of selected images. 10199#@cli : $ image.jpg +normalize 0,2 exp[-1] 10200#@cli : $ 300,1,1,1,'7*x/w+u' +exp display_graph 400,300 10201 10202#@cli >= : eq. to 'ge'. : (+) 10203 10204#@cli ge : value[%] : [image] : 'formula' : (no arg) : (+) 10205#@cli : Compute the boolean 'greater or equal than' of selected images with specified value, image 10206#@cli : or mathematical expression, or compute the boolean 'greater or equal than' of selected images. 10207#@cli : (eq. to '>='). 10208#@cli : $ image.jpg ge {ia} 10209#@cli : $ image.jpg +mirror x ge 10210 10211#@cli > : eq. to 'gt'. : (+) 10212 10213#@cli gt : value[%] : [image] : 'formula' : (no arg) : (+) 10214#@cli : Compute the boolean 'greater than' of selected images with specified value, image or \ 10215# mathematical expression, or compute the boolean 'greater than' of selected images. 10216#@cli : (eq. to '>'). 10217#@cli : $ image.jpg gt {ia} 10218#@cli : $ image.jpg +mirror x gt 10219 10220#@cli <= : eq. to 'le'. : (+) 10221 10222#@cli le : value[%] : [image] : 'formula' : (no arg) : (+) 10223#@cli : Compute the boolean 'less or equal than' of selected images with specified value, image or \ 10224# mathematical expression, or compute the boolean 'less or equal than' of selected images. 10225#@cli : (eq. to '<='). 10226#@cli : $ image.jpg le {ia} 10227#@cli : $ image.jpg +mirror x le 10228 10229#@cli < : eq. to 'lt'. : (+) 10230 10231#@cli lt : value[%] : [image] : 'formula' : (no arg) : (+) 10232#@cli : Compute the boolean 'less than' of selected images with specified value, image or \ 10233# mathematical expression, or compute the boolean 'less than' of selected images. 10234#@cli : (eq. to '<'). 10235#@cli : $ image.jpg lt {ia} 10236#@cli : $ image.jpg +mirror x lt 10237 10238#@cli log : (+) 10239#@cli : Compute the pointwise base-e logarithm of selected images. 10240#@cli : $ image.jpg +add 1 log[-1] 10241#@cli : $ 300,1,1,1,'7*x/w+u' +log display_graph 400,300 10242 10243#@cli log10 : (+) 10244#@cli : Compute the pointwise base-10 logarithm of selected images. 10245#@cli : $ image.jpg +add 1 log10[-1] 10246#@cli : $ 300,1,1,1,'7*x/w+u' +log10 display_graph 400,300 10247 10248#@cli log2 : (+) 10249#@cli : Compute the pointwise base-2 logarithm of selected images 10250#@cli : $ image.jpg +add 1 log2[-1] 10251#@cli : $ 300,1,1,1,'7*x/w+u' +log2 display_graph 400,300 10252 10253#@cli max : value[%] : [image] : 'formula' : (no arg) : (+) 10254#@cli : Compute the maximum between selected images and specified value, image or \ 10255# mathematical expression, or compute the pointwise maxima between selected images. 10256#@cli : $ image.jpg +mirror x max 10257#@cli : $ image.jpg max 'R=((x/w-0.5)^2+(y/h-0.5)^2)^0.5;255*R' 10258 10259#@cli maxabs : value[%] : [image] : 'formula' : (no arg) : (+) 10260#@cli : Compute the maxabs between selected images and specified value, image or \ 10261# mathematical expression, or compute the pointwise maxabs between selected images. 10262 10263#@cli m/ : eq. to 'mdiv'. : (+) 10264 10265#@cli mdiv : value[%] : [image] : 'formula' : (no arg) : (+) 10266#@cli : Compute the matrix division of selected matrices/vectors by specified value, image or \ 10267# mathematical expression, or compute the matrix division of selected images. 10268#@cli : (eq. to 'm/'). 10269 10270#@cli med 10271#@cli : Compute the median of selected images. 10272#@cli : $ image.jpg sample lena,lion,square +med 10273med : 10274 e[^-1] "Compute median of image$?." 10275 if !$! return fi 10276 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 10277 ${-max_whds},"med("$str")" k. nm [med] 10278 10279#@cli min : value[%] : [image] : 'formula' : (no arg) : (+) 10280#@cli : Compute the minimum between selected images and specified value, image or \ 10281# mathematical expression, or compute the pointwise minima between selected images. 10282#@cli : $ image.jpg +mirror x min 10283#@cli : $ image.jpg min 'R=((x/w-0.5)^2+(y/h-0.5)^2)^0.5;255*R' 10284 10285#@cli minabs : value[%] : [image] : 'formula' : (no arg) : (+) 10286#@cli : Compute the minabs between selected images and specified value, image or \ 10287# mathematical expression, or compute the pointwise minabs between selected images. 10288 10289#@cli % : eq. to 'mod'. : (+) 10290 10291#@cli mod : value[%] : [image] : 'formula' : (no arg) : (+) 10292#@cli : Compute the modulo of selected images with specified value, image or mathematical \ 10293# expression, or compute the pointwise sequential modulo of selected images. 10294#@cli : (eq. to '%'). 10295#@cli : $ image.jpg +mirror x mod 10296#@cli : $ image.jpg mod 'R=((x/w-0.5)^2+(y/h-0.5)^2)^0.5;255*R' 10297 10298#@cli m* : eq. to 'mmul'. : (+) 10299 10300#@cli mmul : value[%] : [image] : 'formula' : (no arg) : (+) 10301#@cli : Compute the matrix right multiplication of selected matrices/vectors by specified value, image or \ 10302# mathematical expression, or compute the matrix right multiplication of selected images. 10303#@cli : (eq. to 'm*'). 10304#@cli : $ (0,1,0;0,0,1;1,0,0) (1;2;3) +mmul 10305 10306#@cli * : eq. to 'mul'. : (+) 10307 10308#@cli mul : value[%] : [image] : 'formula' : (no arg) : (+) 10309#@cli : Multiply selected images by specified value, image or mathematical expression, \ 10310# or compute the pointwise product of selected images. 10311#@cli : (eq. to '*'). 10312#@cli : See also: ''add'', ''sub'', ''div''. 10313#@cli : $ image.jpg +mul 2 cut 0,255 10314#@cli : $ image.jpg (1,2,3,4,5,6,7,8) ri[-1] [0] mul[0] [-1] 10315#@cli : $ image.jpg mul '1-3*abs(x/w-0.5)' cut 0,255 10316#@cli : $ image.jpg +luminance negate[-1] +mul 10317 10318#@cli mul_channels : value1,_value2,...,_valueN 10319#@cli : Multiply channels of selected images by specified sequence of values. 10320#@cli : $ image.jpg +mul_channels 1,0.5,0.8 10321mul_channels : 10322 e[^-1] "Multiply channels of image$? by value sequence ($*)." 10323 $=arg repeat $#,i 10324 fact=${arg{1+($>%$#)}} 10325 repeat $! if {$>,$i<s} sh[$>] $i *. $fact rm. fi done 10326 done 10327 10328#@cli mul_complex : [multiplier_real,multiplier_imag] 10329#@cli : Perform multiplication of the selected complex pairs (real1,imag1,...,realN,imagN) of images by 10330#@cli : specified complex pair of images (multiplier_real,multiplier_imag). 10331#@cli : In complex pairs, the real image must be always located before the imaginary image in the image list. 10332mul_complex : 10333 e[^-1] "Multiply complex pair$? by complex pair "${"pass$1,$2 -1"}"." 10334 repeat int($!/2) pass${1,2} 0 l[$>,{$>+1},-2,-1] 10335 +*[0,3] +*[1,2] +[-2,-1] # ad+bc 10336 *[0,2] *[1,2] -[0,1] # ac-bd 10337 endl done 10338 10339#@cli != : eq. to 'neq'. : (+) 10340 10341#@cli neq : value[%] : [image] : 'formula' : (no arg) : (+) 10342#@cli : Compute the boolean inequality of selected images with specified value, image or \ 10343# mathematical expression, or compute the boolean inequality of selected images. 10344#@cli : (eq. to '!='). 10345#@cli : $ image.jpg round 40 neq {round(ia,40)} 10346 10347#@cli | : eq. to 'or'. : (+) 10348 10349#@cli or : value[%] : [image] : 'formula' : (no arg) : (+) 10350#@cli : Compute the bitwise OR of selected images with specified value, image or mathematical \ 10351# expression, or compute the pointwise sequential bitwise OR of selected images. 10352#@cli : (eq. to '|'). 10353#@cli : $ image.jpg or 128 10354#@cli : $ image.jpg +mirror x or 10355 10356#@cli ^ : eq. to 'pow'. : (+) 10357 10358#@cli pow : value[%] : [image] : 'formula' : (no arg) : (+) 10359#@cli : Raise selected images to the power of specified value, image or mathematical \ 10360# expression, or compute the pointwise sequential powers of selected images. 10361#@cli : (eq. to '^'). 10362#@cli : $ image.jpg div 255 +pow 0.5 mul 255 10363#@cli : $ image.jpg gradient pow 2 add pow 0.2 10364 10365#@cli rad2deg 10366#@cli : Convert pointwise angle values of selected images, from radians to degrees (apply 'i*180/pi'). 10367rad2deg : 10368 e[^-1] "Convert pointwise angle values of image$?, from radians to degrees." 10369 * 57.295779513082323 10370 10371#@cli rol : value[%] : [image] : 'formula' : (no arg) : (+) 10372#@cli : Compute the bitwise left rotation of selected images with specified value, image or \ 10373# mathematical expression, or compute the pointwise sequential bitwise left rotation of \ 10374# selected images. 10375#@cli : $ image.jpg rol 'round(3*x/w,0)' cut 0,255 10376 10377#@cli ror : value[%] : [image] : 'formula' : (no arg) : (+) 10378#@cli : Compute the bitwise right rotation of selected images with specified value, image or \ 10379# mathematical expression, or compute the pointwise sequential bitwise right rotation of \ 10380# selected images. 10381#@cli : $ image.jpg ror 'round(3*x/w,0)' cut 0,255 10382 10383#@cli sign : (+) 10384#@cli : Compute the pointwise sign of selected images. 10385#@cli : $ image.jpg +sub {ia} sign[-1] 10386#@cli : $ 300,1,1,1,'cos(20*x/w+u)' +sign display_graph 400,300 10387 10388#@cli sin : (+) 10389#@cli : Compute the pointwise sine of selected images. 10390#@cli : $ image.jpg +normalize 0,{2*pi} sin[-1] 10391#@cli : $ 300,1,1,1,'20*x/w+u' +sin display_graph 400,300 10392#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 10393 10394#@cli sinc : (+) 10395#@cli : Compute the pointwise sinc function of selected images. 10396#@cli : $ image.jpg +normalize {-2*pi},{2*pi} sinc[-1] 10397#@cli : $ 300,1,1,1,'20*x/w+u' +sinc display_graph 400,300 10398 10399#@cli sinh : (+) 10400#@cli : Compute the pointwise hyperbolic sine of selected images. 10401#@cli : $ image.jpg +normalize -3,3 sinh[-1] 10402#@cli : $ 300,1,1,1,'4*x/w+u' +sinh display_graph 400,300 10403 10404#@cli sqr : (+) 10405#@cli : Compute the pointwise square function of selected images. 10406#@cli : $ image.jpg +sqr 10407#@cli : $ 300,1,1,1,'40*x/w+u' +sqr display_graph 400,300 10408 10409#@cli sqrt : (+) 10410#@cli : Compute the pointwise square root of selected images. 10411#@cli : $ image.jpg +sqrt 10412#@cli : $ 300,1,1,1,'40*x/w+u' +sqrt display_graph 400,300 10413 10414#@cli - : eq. to 'sub'. : (+) 10415 10416#@cli sub : value[%] : [image] : 'formula' : (no arg) : (+) 10417#@cli : Subtract specified value, image or mathematical expression to selected images, \ 10418# or compute the pointwise difference of selected images. 10419#@cli : (eq. to '-'). 10420#@cli : $ image.jpg +sub 30% cut 0,255 10421#@cli : $ image.jpg +mirror x sub[-1] [0] 10422#@cli : $ image.jpg sub 'i(w/2+0.9*(x-w/2),y)' 10423#@cli : $ image.jpg +mirror x sub 10424 10425#@cli tan : (+) 10426#@cli : Compute the pointwise tangent of selected images. 10427#@cli : $ image.jpg +normalize {-0.47*pi},{0.47*pi} tan[-1] 10428#@cli : $ 300,1,1,1,'20*x/w+u' +tan display_graph 400,300 10429#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 10430 10431#@cli tanh : (+) 10432#@cli : Compute the pointwise hyperbolic tangent of selected images. 10433#@cli : $ image.jpg +normalize -3,3 tanh[-1] 10434#@cli : $ 300,1,1,1,'4*x/w+u' +tanh display_graph 400,300 10435 10436#@cli xor : value[%] : [image] : 'formula' : (no arg) : (+) 10437#@cli : Compute the bitwise XOR of selected images with specified value, image or mathematical \ 10438# expression, or compute the pointwise sequential bitwise XOR of selected images. 10439#@cli : $ image.jpg xor 128 10440#@cli : $ image.jpg +mirror x xor 10441 10442#--------------------------------- 10443# 10444#@cli :: Values Manipulation 10445# 10446#--------------------------------- 10447 10448#@cli apply_curve : 0<=smoothness<=1,x0,y0,x1,y1,x2,y2,...,xN,yN 10449#@cli : Apply curve transformation to image values. 10450#@cli : Default values: 'smoothness=1', 'x0=0', 'y0=100'. 10451#@cli : $ image.jpg +apply_curve 1,0,0,128,255,255,0 10452apply_curve : check "${1=1}>=0 && $1<=1" skip ${2=0},${3=100} 10453 e[^-1] "Apply intensity curve with smoothness $1 and keypoints (${2--1}) on image$?." 10454 10455 # Determine value mapping. 10456 (${^0,1}) r. 2,{w/2},1,1,-1 +z. 0,0 vm,vM={[im,iM]} n. 0,8191 j.. . function1d[] $1,{-2,^} rm[-3,-2] 10457 10458 # Apply value mapping. 10459 -[^-1] $vm *[^-1] {8191/($vM-$vm)} map[^-1] .,1 rm. 10460 10461#@cli apply_gamma : gamma>=0 10462#@cli : Apply gamma correction to selected images. 10463#@cli : $ image.jpg +apply_gamma 2 10464apply_gamma : check $1>=0 10465 e[^-1] "Apply Gamma-correction to image$?, with gamma $1." 10466 if $1==1 return fi 10467 repeat $! l[$>] mM={[im,iM]} n 0,1 ^ {1/$1} n $mM endl done 10468 10469#@cli balance_gamma : _ref_color1,... 10470#@cli : Compute gamma-corrected color balance of selected image, with respect to specified reference color. 10471#@cli : Default value: 'ref_color1=128'. 10472#@cli : $ image.jpg +balance_gamma 128,64,64 10473balance_gamma : check "isnum(${1=128})" 10474 e[^-1] "Apply gamma-corrected color balance of image$?, with reference color ("${^0}")." 10475 repeat $! l[$>] 10476 (${^0}) r. {-2,s},1,1,1,0,1 s.. c /. 255 10477 repeat $!-1 /[$>] 255 ^[$>] {log({@$>})/log({$>,ia})} *[$>] 255 done 10478 rm. a c c 0,255 10479 endl done 10480 10481#@cli cast : datatype_source,datatype_target 10482#@cli : Cast datatype of image buffer from specified source type to specified target type. 10483#@cli : 'datatype_source' and 'datatype_target' can be \ 10484# { uchar | char | ushort | short | uint | int | uint64 | int64 | float | double }. 10485cast : 10486 e[^-1] "Cast datatype of image buffer$? from '$1' to '$2'." 10487 stype="$1" 10488 if s='$stype';s[0]==_'u'" && "s[1]!=_'n' stype="unsigned_"{`s='$stype';s[1,size(s)-1]`} 10489 elif s='$stype';s[0]==_'u'" && "s[0,9]=='"unsigned "' stype="unsigned_"{`s='$stype';s[9,size(s)-9]`} 10490 fi 10491 dtype="$2" 10492 if s='$dtype';s[0]==_'u'" && "s[1]!=_'n' dtype="unsigned_"{`s='$dtype';s[1,size(s)-1]`} 10493 elif s='$dtype';s[0]==_'u'" && "s[0,9]=='"unsigned "' dtype="unsigned_"{`s='$dtype';s[9,size(s)-9]`} 10494 fi 10495 ssize={s='$stype';s=='"unsigned_char"'||s=='char'?1:s=='"unsigned_short"'||s=='short'?2:s=='"unsigned_int"'||\ 10496 s=='int'||s=='float'?4:8} 10497 dsize={s='$dtype';s=='"unsigned_char"'||s=='char'?1:s=='"unsigned_short"'||s=='short'?2:s=='"unsigned_int"'||\ 10498 s=='int'||s=='float'?4:8} 10499 repeat $! l[$>] 10500 w,h,d,s={[w,h,d,s]} 10501 serialize $1,0,0 10502 s -,{'\n$w\ $h\ $d\ $s\n'} 10503 i[1] ('\n1\ {int($w*$h*$d*$s*$ssize/$dsize)}\ 1\ 1\n') y[1] 10504 replace_str[0] $stype,$dtype 10505 a y unserialize 10506 endl done 10507 10508#@cli complex2polar 10509#@cli : Compute complex to polar transforms of selected images. 10510#@cli : $ image.jpg +fft complex2polar[-2,-1] log[-2] shift[-2] 50%,50%,0,0,2 remove[-1] 10511complex2polar : 10512 e[^-1] "Compute complex to polar transforms of image$?." 10513 repeat int($!/2) l[{2*$>},{2*$>+1}] 10514 ri[1] [0],3 +atan2[1] [0] nm. {1,n} sqr[-3,-2] +[-3,-2] sqrt.. 10515 endl done 10516 10517#@cli compress_clut : _max_error>0,_avg_error>0,_max_nbpoints>=8 | 0 (unlimited),\ 10518# _error_metric={ 0=L2-norm | 1=deltaE_1976 | 2=deltaE_2000 },_reconstruction_colorspace={ 0=srgb | 1=rgb | 2=lab },\ 10519# _try_rbf_first={ 0 | 1 } 10520#@cli : Compress selected color LUTs as sequences of colored keypoints. 10521#@cli : Default values: 'max_error=1.5', 'avg_error=0.75', 'max_nb_points=2048', 'error_metric=2', \ 10522# 'reconstruction_colorspace=0' and 'try_rbf_first=1'. 10523compress_clut : check "${1=1.5}>0 && ${2=0.75}>0 && isint(${3=2048}) && (!$3 || $3>=8) && isin(${4=2},0,1,2) && "\ 10524 "isin(${5=0},0,1,2) && isbool(${6=1})" 10525 e[^-1] "Compress color LUT$? as a set of colored keypoints, with maximum error $1, average error $2, "\ 10526 "$3 maximum keypoints, "${"s0,s1,s2=L2-RGB,DeltaE_1976,DeltaE_2000 u $s$4"}" metric and "\ 10527 ${"s0,s1,s2=srgb,rgb,lab u $s$5"}" colorspace for reconstruction." 10528 v 0 10529 max_error,avg_error,max_keypoints,metric,colorspace,try_rbf=${1-6} 10530 if $try_rbf method=rbf else method=pde fi 10531 repeat $! l[$>] nm={b} 10532 if iM>1024 / 257 fi # When input is 16bits 10533 if d==1 S={round(cbrt(wh))} r $S,$S,$S,100%,-1 fi # When input is a 2D haldclut image 10534 e[] "\n* Process CLUT '"$nm"' ("{w}"x"{h}"x"{d}")." 10535 10536 # Detect B&W cluts. 10537 if "s==3 && 10538 crop(0,0,0,0,w,h,d,1)==crop(0,0,0,1,w,h,d,1) && 10539 crop(0,0,0,0,w,h,d,1)==crop(0,0,0,2,w,h,d,1)" 10540 channels 0 10541 fi 10542 10543 _metric={s==3?$metric:0} 10544 if $_metric +srgb2lab fi 10545 10546 # Initialize keypoints (corners of the RGB cube). 10547 1,8,1,{s+3} 10548 eval " 10549 coords = [ 0,0,0, 255,0,0, 255,255,0, 0,255,0, 0,0,255, 255,0,255, 255,255,255, 0,255,255 ]; 10550 repeat (size(coords)/3,k, 10551 P = coords[3*k,3]; 10552 I[k] = [ P, I(#0,round(P*([w#0,h#0,d#0]-1)/255)) ] 10553 )" 10554 10555 # Iteratively add keypoints. 10556 sep="\n" 10557 do 10558 +decompress_clut_$method. {0,[w,h,d]},$colorspace 10559 if !$_metric -. [0] norm. else srgb2lab. deltaE. [1],{$_metric-1}," " fi 10560 emax,eavg={[iM,ia]} 10561 e[] "\r"$sep" > Add [#"{-2,h}"] Max_Err = "{_$emax}", Avg_Err = "{_$eavg}" " sep="" 10562 if $emax<=$max_error" && "$eavg<=$avg_error rm. break fi 10563 1,1,1,{0,s+3},{"P = [ xM,yM,zM ]; [ P*255/[max(1,w#0-1),max(1,h#0-1),max(1,d#0-1)], I(#0,P) ]"} rm.. 10564 a[-2,-1] y 10565 if $max_keypoints" && "h>=320" && "'$method'=='rbf' method=pde rows. 0,7 fi # RBF failed, switch to PDE method. 10566 while h<($max_keypoints?$max_keypoints:inf) 10567 10568 # Iteratively remove keypoints. 10569 if h>8 10570 if $_metric max_rounding,avg_rounding=0.1,0.025 10571 else max_rounding,avg_rounding=1,0.25 10572 fi 10573 if $emax>$max_error" || "$eavg>$avg_error 10574 max_error=round($max_error,$max_rounding,1) 10575 avg_error=round($avg_error,$avg_rounding,1) 10576 fi 10577 index=8 sep="\n" 10578 do 10579 +l. s y rm[$index] a y endl # Remove kth keypoint 10580 +decompress_clut_$method. {0,[w,h,d]},$colorspace 10581 if $_metric==0 -. [0] norm. else srgb2lab. deltaE. [1],{$_metric-1}," " fi 10582 emax,eavg={[iM,ia]} rm. 10583 10584 if $emax<=$max_error" && "$eavg<=$avg_error rv[-2,-1] else index+=1 fi 10585 e[] "\r"$sep" > Rem [#"{min($index,h-1)}"/"{h}"] Max_Err = "{_$emax}", Avg_Err = "{_$eavg}" " 10586 sep="" 10587 rm. 10588 while $index<h 10589 fi 10590 k. 10591 10592 # Sort keypoints in lexicographic order (increasing order for RBF, decreasing for PDE). 10593 1,100%,1,1,"P = I(#0); P[0]*65536 + P[1]*256 + P[2]" rv a x sort {`'$method'=='rbf'?_'+':_'-'`},y z. 1,100% 10594 10595 to_clutname $nm nm ${} 10596 endl done 10597 10598# compress_cluts : {"file_pattern" | "file_list.txt"},_max_error>0,_avg_error>0,_max_nb_points>=8 10599# Batch compress CLUT files. 10600compress_cluts : check "${2=1.5}>0 && ${3=0.75}>0 && isint(${4=2048}) && $4>8" 10601 rm 10602 if isfile(['{/"$1"}']) it[] "$1" s -,{'\n'} 10603 else files "$1" ('${}') s -,{','} 10604 fi 10605 rv 10606 repeat $! l[$<] 10607 filename={t} 0 nm. $filename ext={x} rm 10608 basename $filename 10609 l[] ('${}') replace_str .$ext,"" basename={t} rm endl 10610 need_compression=1 10611 cclut=cclut_$basename.gmz 10612 10613 if isfile(['{/$cclut}']) 10614 i $cclut 10615 if "dat = (date(5) + 60*(date(4) + date(2)*24)); 10616 fdat = (date(5,'"{/$cclut}"') + 60*(date(4,'"{/$cclut}"') + date(2,'"{/$cclut}"')*24)); 10617 !h && dat-fdat<30" 10618 e[] "* Skip file '"$filename"' (CLUT already being compressed)." 10619 need_compression=0 10620 elif h>0" && "h!=2048 10621 e[] "* Skip file '"$filename"' (CLUT already compressed)." 10622 need_compression=0 10623 fi 10624 rm. 10625 fi 10626 10627 if $need_compression 10628 0 o. $cclut rm. # Lock current file 10629 if lowercase(['$ext'])=='cube' input_cube $filename c. 0,255 10630 elif lowercase(['$ext'])=='png' i $filename S={round(cbrt(wh))} r $S,$S,$S,100%,-1 10631 else e[] "* Skip file '"$filename"' (unknown CLUT format)." continue 10632 fi 10633 10634 e[] "* Compress file '"$filename"'." 10635 if w>33 r3dx 33 fi 10636 to_rgb 10637 tic compress_clut $2,$3,$4 toc 10638 o $cclut 10639 fi 10640 rm 10641 endl done 10642 10643# cluts2libclut : "compressed_CLUT_collection.gmz" 10644# Convert specified compressed CLUT collection for C++ 'libclut' 10645# (https://framagit.org/dtschump/libclut) 10646cluts2libclut : skip ${1=$HOME/work/src/gmic/resources/gmic_cluts.gmz} 10647 e[] "Convert compressed CLUT collection '$1' to .png/.ppm/.txt for C++ libclut." 10648 l[] 10649 i $1 10650 0 nm. "$1" basename={b} rm. 10651 list= 10652 repeat $! l[$>] if s<6 r 100%,100%,1,6,0,1 fi transpose list.={n}"\n" endl done s c,2 a y 10653 o. $basename.png 10654 o. $basename.ppm 10655 ('$list') ot. $basename.txt 10656 rm 10657 endl 10658 10659#@cli compress_rle : _is_binary_data={ 0 | 1 },_maximum_sequence_length>=0 10660#@cli : Compress selected images as 2xN data matrices, using RLE algorithm. 10661#@cli : Set 'maximum_sequence_length=0' to disable maximum length constraint. 10662#@cli : Default values: 'is_binary_data=0' and 'maximum_sequence_length=0'. 10663#@cli : $ image.jpg resize2dy 100 quantize 4 round +compress_rle , +decompress_rle[-1] 10664compress_rle : check "isbool(${1=0}) && isint(${2=0}) && $2>=0" 10665 s0=" for binary data" s1="" 10666 if $2 s=", with maximal sequence length "$2 else s="" fi 10667 e[^-1] "Compress image$? using RLE algorithm"${s{!$1}}$s"." 10668 repeat $! l[$>] nm={0,n} im={im} header={w};{h};{d};{s};$im;{$1!=0} 10669 - $im y x ({{0,@-1}+1}) a x r 100%,3 10670 f '>!y?i:y==1?(i(x,0)==i(x+1,0)?-1:x):(i(x-1,1)==-1?i(x-1,2)+1:1)' 10671 if $2 # Constrain maximum sequence length. 10672 transpose mirror x 10673 f. '>x==2?i:!x?(j(0,-1)==$2?1:i!=1?j(0,-1)+1:1):(i==-1&&j(-1)==$2?y:i)' 10674 mirror x transpose 10675 fi 10676 z 0,{w-2} s y,3 y[1] discard[1] -1 warp[0,2] [1],0,0 rm[1] 10677 if $1 # Encode for binary data. 10678 !=[0] 0 *[0] 2 -[0] 1 * 10679 else # Encode for arbitrary data. 10680 *. -1 rv a x y discard -1 f '>i(0,y-1)<0&&i==0&&i(0,y+1)<0?-1:i' discard -1 10681 fi 10682 i[0] ($header) a y nm $nm 10683 endl done 10684 10685#@cli cumulate : { x | y | z | c }...{ x | y | z | c } : (no arg) : (+) 10686#@cli : Compute the cumulative function of specified image data, optionally along the specified axes. 10687#@cli : $ image.jpg +histogram 256 +cumulate[-1] display_graph[-2,-1] 400,300,3 10688 10689#@cli c : eq. to 'cut'. : (+) 10690 10691#@cli cut : { value0[%] | [image0] },{ value1[%] | [image1] } : [image] : (+) 10692#@cli : Cut values of selected images in specified range. 10693#@cli : (eq. to 'c').\n 10694#@cli : $ image.jpg +add 30% cut[-1] 0,255 10695#@cli : $ image.jpg +cut 25%,75% 10696 10697#@cli decompress_clut : _width>0,_height>0,_depth>0,_reconstruction_colorspace={ 0=srgb | 1=rgb | 2=lab } 10698#@cli : Decompress selected colored keypoints into 3D CLUTs, using a mixed RBF/PDE approach. 10699#@cli : Default values: 'width=height=depth=33' and 'reconstruction_colorspace=0'. 10700decompress_clut : check "isint(${1=33}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=$1}) && $3>0 && "\ 10701 "isin(${4=0},0,1,2)" 10702 e[^-1] "Decompress colored keypoint$? into $1x$2x$3 CLUTs, using "\ 10703 ${"s0,s1=srgb,rgb u $s$4"}" colorspace for reconstruction." 10704 repeat $! l[$>] 10705 if "h>=320 || (P0 = I[0]; P1 = I[h - 1]; val(P) = (P[0]*65536 + P[1]*256 + P[2]); val(P0)>val(P1))" 10706 decompress_clut_pde. ${1-4} 10707 else 10708 decompress_clut_rbf. ${1-4} 10709 fi 10710 endl done 10711 10712#@cli decompress_clut_rbf : _width>0,_height>0,_depth>0,_reconstruction_colorspace={ 0=srgb | 1=rgb | 2=lab } 10713#@cli : Decompress selected colored keypoints into 3D CLUTs, using RBF thin plate spline interpolation. 10714#@cli : Default value: 'width=height=depth=33' and 'reconstruction_colorspace=0'. 10715decompress_clut_rbf : check "isint(${1=33}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=$1}) && $3>0 && "\ 10716 "isin(${4=0},0,1,2)" 10717 e[^-1] "Decompress colored keypoint$? into $1x$2x$3 CLUTs (RBF approach), using "\ 10718 ${"s0,s1,s2=srgb,rgb,lab u $s$4"}" colorspace for reconstruction." 10719 repeat $! l[$>] 10720 if $4 s c,-3 srgb2${"arg $4,rgb,lab"}. a c fi 10721 rbf $1,$2,$3,0,0,0,255,255,255 10722 if $4 ${"arg $4,rgb,lab"}2srgb fi 10723 endl done 10724 10725#@cli decompress_clut_pde : _width>0,_height>0,_depth>0,_reconstruction_colorspace={ 0=srgb | 1=rgb | 2=lab } 10726#@cli : Decompress selected colored keypoints into 3D CLUTs, using multiscale diffusion PDE's. 10727#@cli : Default values: 'width=height=depth=33' and 'reconstruction_colorspace=0'. 10728decompress_clut_pde : check "isint(${1=33}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=$1}) && $3>0 && "\ 10729 "isin(${4=0},0,1,2)" 10730 e[^-1] "Decompress colored keypoint$? into $1x$2x$3 CLUTs (PDE approach), using "\ 10731 ${"s0,s1,s2=srgb,rgb,lab u $s$4"}" colorspace for reconstruction." 10732 repeat $! l[$>] nm={n} 10733 if $4 s c,-3 srgb2${"arg $4,rgb,lab"}. a c fi 10734 2,2,2,{s-3} 10735 do 10736 +f. 0 .,.,.,1 10737 eval[0] "begin(fact = ([w#1,h#1,d#1] - 1)/255); PC = I; P = PC[0,3]; X = round(P*fact); 10738 I(#2,X)+=PC[3,s-3]; ++i(#3,X); I" 10739 f. "*i?(I(#2)/=i;1):0" 10740 if im rm[-3,-1] # No missing data so far 10741 else # Reconstruct missing data by anisotropic diffusion scheme 10742 +distance. 1 .,.,.,3 10743 eval.. "* # Specific gradient discretization for distance function 10744 const boundary = 1; 10745 maxabs(a,b) = (abs(a)>abs(b)?a:b); 10746 I(#-1) = [ maxabs(j(1) - i,i - j(-1)), 10747 maxabs(j(0,1) - i,i - j(0,-1)), 10748 maxabs(j(0,0,1) - i,i - j(0,0,-1)) ]" 10749 orientation. rm.. 10750 repeat 20 10751 j[-4] ...,0,0,0,0,1,.. 10752 +warp[-4] .,1,2,1 *.. -1 warp[-5] ..,1,2,1 +[-5,-1] /[-4] 2 10753 done 10754 j[-4] ...,0,0,0,0,1,.. k[0,1] 10755 fi 10756 if "w<$1 || h<$2 || d<$3" r. {[min($1,2*w),min($2,2*h),min($3,2*d)]},100%,3 else break fi 10757 while 1 10758 k. 10759 if $4 ${"arg $4,rgb,lab"}2srgb fi 10760 nm $nm 10761 endl done 10762 um srgb2srgb 10763 10764#@cli decompress_rle 10765#@cli : Decompress selected data vectors, using RLE algorithm. 10766decompress_rle : 10767 e[^-1] "Decompress data vector$?, using RLE algorithm." 10768 repeat $! l[$>] 10769 10770 # Retrieve original data dimension and min value. 10771 y whds={0,@0-3} im={0,@4} is_binary_data={0,@5} rows 6,100% 10772 10773 # Transform RLE data to list of pairs {nb_occurrences,value}. 10774 if $is_binary_data # Decode for binary data. 10775 +>= 0 abs[0] a x 10776 else # Decode for arbitrary data 10777 +<. 0 10778 (0;1;1) 10779 erode.. .,0 rm. -. 1 a x discard -1 # Get back compressed '0' (minimum) values. 10780 +< 0 (0;1;1) dilate.. . rm. *. -2 +. 1 # Get back singletons. 10781 rv abs. a x discard -1 10782 r 2,{h/2},1,1,-1 10783 fi 10784 10785 # Decompress, using 3D objects. 10786 s y,-256 10787 repeat $! l[$>] 10788 i[0] ('CImg3d') +[0] 0.5 10789 i[1] ({2*h};{h}) 10790 s. x,2 cumulate.. siz={-2,@-1} 10791 +shift.. 0,1 -... 1 rv[-3,-1] z[-3,-1] 0,2 a[-3,-1] x 10792 i[3] (2,0,1;2,{2*h-2},{2*h-1}) r[3] 3,{h},1,1,3 round[3] 10793 r[4] 3 1,100%,1,1,1 y a y 10794 $siz j3d. ..,0,0,0,1,2,0,0 rm.. 10795 endl done 10796 a x r $whds,-1 + $im 10797 endl done 10798 10799#@cli discard : _value1,_value2,... : { x | y | z | c}...{ x | y | z | c},_value1,_value2,... : (no arg) : (+) 10800#@cli : Discard specified values in selected images or discard neighboring duplicate values, 10801#@cli : optionally only for the values along the first of a specified axis. 10802#@cli : If no arguments are specified, neighboring duplicate values are discarded. 10803#@cli : If all pixels of a selected image are discarded, an empty image is returned. 10804#@cli : $ (1;2;3;4;3;2;1) +discard 2 10805#@cli : $ (1,2,2,3,3,3,4,4,4,4) +discard x 10806 10807#@cli eigen2tensor 10808#@cli : Recompose selected pairs of eigenvalues/eigenvectors as 2x2 or 3x3 tensor fields. 10809#@cli : $$ 10810eigen2tensor : 10811 e[^-1] "Recompose pairs in eigen field$? as 2x2 or 3x3 tensor fields." 10812 repeat $!/2 l[$>,{$>+1}] nm={0,n} 10813 if s==2 # 2D tensors. 10814 s. c 10815 +sqr. *.. ... sqr... # u^2 uv v^2 10816 sh. +*... -1 10817 sh[-5] # v^2 -uv u^2 10818 a[-3--1] c a[-4--2] c 10819 sh... 0 *[-3,-1] # l1*(u^2;uv;v^2) 10820 sh... 1 *[-2,-1] # l2*(v^2;-uv;u^2) 10821 rm... +[-2,-1] 10822 elif s==6 # 3D tensors. 10823 s. c 10824 l[-6--4] +sqr.. +*[-2,-3] +sqr... *[-5] [-6] *[-4] [-6] sqr[-6] a c endl 10825 l[-3--1] +sqr.. +*[-2,-3] +sqr... *[-5] [-6] *[-4] [-6] sqr[-6] a c endl 10826 s... c 10827 -[-5] ... -[-4] ... *.. [-5] *. [-4] 10828 (1^0^0^1^0^1) ri. ... *. [-4] rm[-6--4] +[-3--1] 10829 else error[0--3] "Command '$0': Invalid image ["{$!-$>-1}"] : Dimensions "{w}","{h}","{d}","{s}" does 10830 not represent a field of 2D or 3D eigenvectors." 10831 fi 10832 nm $nm endl done 10833 10834#@cli endian : _datatype : (+) 10835#@cli : Reverse data endianness of selected images, eventually considering the pixel being of the specified datatype. 10836#@cli : 'datatype' can be { bool | uchar | char | ushort | short | uint | int | uint64 | int64 | float | double }. 10837#@cli : This command does nothing for 'bool', 'uchar' and 'char' datatypes. 10838 10839#@cli equalize : _nb_levels>0[%],_value_min[%],_value_max[%] : (+) 10840#@cli : Equalize histograms of selected images. 10841#@cli : If value range is specified, the equalization is done only for pixels in the specified 10842#@cli : value range. 10843#@cli : Default values: 'nb_levels=256', 'value_min=0%' and 'value_max=100%'. 10844#@cli : $ image.jpg +equalize 10845#@cli : $ image.jpg +equalize 4,0,128 10846 10847#@cli f : eq. to 'fill'. : (+) 10848 10849#@cli fill : value1,_value2,... : [image] : 'formula' : (+) 10850#@cli : Fill selected images with values read from the specified value list, existing image 10851#@cli : or mathematical expression. Single quotes may be omitted in 'formula'. 10852#@cli : (eq. to 'f'). 10853#@cli : $ 4,4 fill 1,2,3,4,5,6,7 10854#@cli : $ 4,4 (1,2,3,4,5,6,7) fill[-2] [-1] 10855#@cli : $ 400,400,1,3 fill "X=x-w/2; Y=y-h/2; R=sqrt(X^2+Y^2); a=atan2(Y,X); \ 10856# if(R<=180,255*abs(cos(c+200*(x/w-0.5)*(y/h-0.5))),850*(a%(0.1*(c+1))))" 10857#@cli : $$ 10858 10859#@cli index : { [palette] | palette_name },0<=_dithering<=1,_map_palette={ 0 | 1 } : (+) 10860#@cli : Index selected vector-valued images by specified vector-valued palette. 10861#@cli : 'palette_name' can be { default | hsv | lines | hot | cool | jet | flag | cube | rainbow | algae | amp |\ 10862# balance | curl | deep | delta | dense | diff | haline | ice | matter | oxy | phase | rain | solar | speed | tarn |\ 10863# tempo | thermal | topo | turbid | aurora | hocuspocus | srb2 | uzebox } 10864#@cli : Default values: 'dithering=0' and 'map_palette=0'. 10865#@cli : $ image.jpg +index 1,1,1 10866#@cli : $ image.jpg (0;255;255^0;128;255^0;0;255) +index[-2] [-1],1,1 10867#@cli : $$ https://gmic.eu/tutorial/gindex 10868index : check "${2=0}>=0 && $2<=1 && isbool(${3=0})" 10869 names=${-_palette_names} N={narg($names)} 10870 l[] if isint("$1") name=${"arg 1+($1%"$N"),"$names} else name="$1" fi onfail name="$1" endl 10871 e[^-1] "Index values in image$? by color LUT '"$name"', with dithering level $2." 10872 palette $1 index[^-1] .,$2,$3 rm. 10873 10874#@cli ir : eq. to 'inrange'. 10875ir : check "isbool(${3=1}) && isbool(${4=$3})" 10876 _gmic_s="$?" v + _inrange $* 10877 10878#@cli inrange : min[%],max[%],_include_min_boundary={ 0=no | 1=yes },_include_max_boundary={ 0=no | 1=yes } 10879#@cli : Detect pixels whose values are in specified range `[min,max]`, in selected images. 10880#@cli : (eq. to 'ir'). 10881#@cli : Default value: 'include_min_boundary=include_max_boundary=1'. 10882#@cli : $ image.jpg +inrange 25%,75% 10883inrange : check "isbool(${3=1}) && isbool(${4=$3})" 10884 _gmic_s="$?" v + _$0 $* 10885 10886_inrange : skip "${3=1},${4=$3}" 10887 v={$3+2*$4} 10888 s=${"arg 1+"$v",out,\" min\",\" max\",\" min and max\""} 10889 if $v%3 b="y" else b="ies" fi 10890 e[0--3] "Extract pixel values in range [$1,$2] in image"$_gmic_s", with"$s" boundar"$b" included." 10891 repeat $! l[$>] 10892 m=$1 M=$2 10893 if ${is_percent\ $1} m={im+(iM-im)*$1} fi 10894 if ${is_percent\ $2} M={im+(iM-im)*$2} fi 10895 f. inrange(i,$m,$M,$3) 10896 endl done 10897 10898#@cli map : [palette],_boundary_conditions : palette_name,_boundary_conditions : (+) 10899#@cli : Map specified vector-valued palette to selected indexed scalar images. 10900#@cli : 'palette_name' can be { default | hsv | lines | hot | cool | jet | flag | cube | rainbow | algae | amp | \ 10901# balance | curl | deep | delta | dense | diff | gray | haline | ice | matter | oxy | phase | rain | solar | speed | \ 10902# tarn | tempo | thermal | topo | turbid | aurora | hocuspocus | srb2 | uzebox } 10903#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 10904#@cli : Default value: 'boundary_conditions=0'. 10905#@cli : $ image.jpg +luminance map[-1] 3 10906#@cli : $ image.jpg +rgb2ycbcr split[-1] c (0,255,0) resize[-1] 256,1,1,1,3 map[-4] [-1] remove[-1] append[-3--1] c \ 10907# ycbcr2rgb[-1] 10908#@cli : $$ 10909map : check "isint(${2=0}) && $2>=0 && $2<=3" 10910 s0,s1,s2,s3=dirichlet,neumann,periodic,mirror boundary=${s$2} 10911 names=${-_palette_names} N={narg($names)} 10912 l[] if isint("$1") name=${"arg 1+($1%"$N"),"$names} else name="$1" fi onfail name="$1" endl 10913 e[^-1] "Map color LUT '"$name"' on image$?, with "$boundary" boundary conditions." 10914 palette $1 map[^-1] .,$2 rm. 10915 10916#@cli mix_channels : (a00,...,aMN) : [matrix] 10917#@cli : Apply specified matrix to channels of selected images. 10918#@cli : $ image.jpg +mix_channels (0,1,0;1,0,0;0,0,1) 10919mix_channels : 10920 e[^-1] "Apply matrix $1 to channels of image$?." 10921 if ${"is_image_arg $1"} pass$1 1 else i ${^0} fi 10922 repeat $!-1 l[$>] nm={n} 10923 whd={[w,h,d]} r. {[whd,s]},1,1,-1 10924 pass. 0 mv. 0 m* r $whd,{h},-1 10925 nm $nm endl done rm. 10926 10927#@cli negate : base_value : (no arg) 10928#@cli : Negate image values. 10929#@cli : Default value: 'base_value=(undefined)'. 10930#@cli : $ image.jpg +negate 10931negate : skip "${1=,}" 10932 if isnum("$*") 10933 e[0--3] "Negate values of image$?, according to base value $*." 10934 - {"$*"} * -1 10935 else 10936 e[0--3] "Negate values of image$?." 10937 repeat $! -[$>] {$>,iM} done * -1 10938 if ['"$1"']!=',' noarg fi 10939 fi 10940 10941#@cli noise : std_deviation>=0[%],_noise_type : (+) 10942#@cli : Add random noise to selected images. 10943#@cli : 'noise_type' can be { 0=gaussian | 1=uniform | 2=salt&pepper | 3=poisson | 4=rice }. 10944#@cli : Default value: 'noise_type=0'. 10945#@cli : $ image.jpg +noise[0] 50,0 +noise[0] 50,1 +noise[0] 10,2 cut 0,255 10946#@cli : $ 300,300,1,3 [0] noise[0] 20,0 noise[1] 20,1 +histogram 100 display_graph[-2,-1] 400,300,3 10947 10948#@cli noise_perlin : _scale_x[%]>0,_scale_y[%]>0,_scale_z[%]>0,_seed_x,_seed_y,_seed_z 10949#@cli : Render 2D or 3D Perlin noise on selected images, from specified coordinates. 10950#@cli : The Perlin noise is a specific type of smooth noise, 10951#@cli : described here : <https://en.wikipedia.org/wiki/Perlin_noise>. 10952#@cli : Default values: 'scale_x=scale_y=scale_z=16' and 'seed_x=seed_y=seed_z=0'. 10953#@cli : $ 500,500,1,3 noise_perlin , 10954noise_perlin : check "${1=16}>0 && ${2=$1}>0 && ${3=$1}>0 && isnum(${4=0}) && isnum(${5=0}) && isnum(${6=0})" 10955 e[^-1] "Render Perlin noise on image$?, with scales (${1-3}) and seeds (${4-6})." 10956 10957 init="permutation = [ 151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240, 10958 21,10,23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88, 10959 237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231, 10960 83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1, 10961 216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198, 10962 173,186,3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47, 10963 16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167, 10964 43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251, 10965 34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31, 10966 181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,93,222,114,67,29, 10967 24,72,243,141,128,195,78,66,215,61,156,180 ]; 10968 p = [ permutation,permutation ]; 10969 fade(t) = (t*t*t*(t*(t*6 - 15) + 10)); 10970 _lerp(t,a,b) = lerp(a,b,t); 10971 pcmod255 = vectors(); repeat (s,k,pcmod255[k] = p[k%255]); 10972 sx = ['$1']; is_px = sx[size(sx) - 1]==_'%'; 10973 sy = ['$2']; is_py = sy[size(sy) - 1]==_'%'; 10974 sz = ['$3']; is_pz = sz[size(sz) - 1]==_'%'; 10975 x0 = $4; 10976 y0 = $5; 10977 z0 = $6; 10978 x1 = x0 + (is_px?1/$1:w/$1); 10979 y1 = y0 + (is_py?1/$2:h/$2); 10980 z1 = z0 + (is_pz?1/$3:d/$3); 10981 fw = (x1 - x0)/max(w - 1,1); 10982 fh = (y1 - y0)/max(h - 1,1); 10983 fd = (z1 - z0)/max(d - 1,1);" 10984 10985 repeat $! if {$>,d>1} # 3D version 10986 f[$>] "*begin("$init" 10987 grad(hash,x,y,z) = ( gh = hash&15; gu = gh<8?x:y; gv = gh<4?y:gh==12 || gh==14?x:z; 10988 (!(gh&1)?gu:-gu) + (!(gh&2)?gv:-gv)) 10989 ); 10990 x = x0 + x*fw + pcmod255[c]; y = y0 + y*fh + pcmod255[c]; z = z0 + z*fd + pcmod255[c]; 10991 ix = floor(x); iy = floor(y); iz = floor(z); 10992 X = ix&255; Y = iy&255; Z = iz&255; 10993 fx = x - ix; fy = y - iy; fz = z - iz; 10994 u = fade(fx); v = fade(fy); w = fade(fz); 10995 A = p[X] + Y; AA = p[A] + Z; AB = p[A + 1] + Z; 10996 B = p[X + 1] + Y; BA = p[B] + Z; BB = p[B + 1] + Z; 10997 fx1 = fx - 1; fy1 = fy - 1; fz1 = fz - 1; 10998 lerp(lerp(lerp(grad(p[AA],fx,fy,fz), 10999 grad(p[BA],fx1,fy,fz),u), 11000 lerp(grad(p[AB],fx,fy1,fz), 11001 grad(p[BB],fx1,fy1,fz),u),v), 11002 lerp(lerp(grad(p[AA + 1],fx,fy,fz1), 11003 grad(p[BA + 1],fx1,fy,fz1,u), 11004 lerp(grad(p[AB + 1],fx,fy1,fz1), 11005 grad(p[BB+1],fx1,fy1,fz1),u),v),w)" 11006 else # 2D version 11007 f[$>] "*begin("$init" 11008 grad(hash,x,y) = ( gh = hash&15; gu = gh<8?x:y; gv = gh<4?y:gh==12 || gh==14?x:0; 11009 (!(gh&1)?gu:-gu) + (!(gh&2)?gv:-gv)) 11010 ); 11011 x = x0 + x*fw + pcmod255[c]; y = y0 + y*fh + pcmod255[c]; 11012 ix = floor(x); iy = floor(y); 11013 X = ix&255; Y = iy&255; 11014 fx = x - ix; fy = y - iy; 11015 u = fade(fx); v = fade(fy); 11016 A = p[X] + Y; B = p[X + 1] + Y; 11017 fx1 = fx - 1; fy1 = fy - 1; 11018 lerp(lerp(grad(p[A],fx,fy), 11019 grad(p[B],fx1,fy),u), 11020 lerp(grad(p[A + 1],fx,fy1), 11021 grad(p[B + 1],fx1,fy1),u),v)" 11022 fi done 11023 11024#@cli noise_poissondisk : _radius[%]>0,_max_sample_attempts>0 11025#@cli : Add poisson disk sampling noise to selected images. 11026#@cli : Implements the algorithm from the article "Fast Poisson Disk Sampling in Arbitrary Dimensions", 11027#@cli : by Robert Bridson (SIGGRAPH'2007). 11028#@cli : Default values: 'radius=8' and 'max_sample_attempts=30'. 11029#@cli : $ 300,300 noise_poissondisk 8 11030##### : Original G'MIC code by Garagecoder (Andy Kelday) 11031noise_poissondisk : check "${1=8}>0 && ${2=30}>0" 11032 e[^-1] "Add poisson disk sampling points to image$?, with radius $1 and max sample attempts $2." 11033 repeat $! l[$>] 11034 R={${"is_percent $1"}?max(w,h,d)*$1:$1} # [0] input image to draw samples on 11035 dim={d>1?3:h>1?2:1} cw={0.999*$R/sqrt($dim)} # dimensions, grid cell width 11036 ({[w,h,d,1]}) y. c # [1] image dimensions vector 11037 {[ceil(I/$cw)]} # [2] "accelerator" grid/cells 11038 r[1] 1,1,1,$dim,-1 # keep only used dimensions in [1] 11039 1,1,1,$dim 1,1,1,1 # [3] samples list, [4] active list 11040 {vector$dim(2*ceil(sqrt($dim))+1)} r. 100%,100%,100%,2 # [5] cell proximity kernel 11041 f. "P=[x,y,z]-int([w/2,h/2,d/2]);[sum(sqr(P)),dot(P,[1,w#2,w#2*h#2])]" 11042 r. {[whd,s,1,1,-1]} sort. +,x z. 0,1,100%,100% y. c # sort kernel by distance 11043 nm[1] dims nm[2] grid nm[3] samples nm[4] active nm[5] prox 11044 eval " 11045 begin( 11046 dotoff = resize([ 1,w#2,w#2*h#2 ],d#2>1?3:h#2>1?2:1,0); 11047 ); 11048 const N = "$dim"; 11049 const radius = "$R"; 11050 const grid_cw = "$cw"; 11051 const max_sample_attempts = $2; 11052 const value = iM#0 + (im#0==iM#0); 11053 mag2(vec) = sum(sqr(vec)); 11054 prox = I#5; 11055 lim = I#1; 11056 11057 da_push(#3,I#1); # Dummy sample to simplify bounds checks 11058 da_push(#3,u(I#1)); # Add initial sample to list 11059 da_push(#4,1); # Add its index to active list 11060 I(#2,int(I[#3,1]/grid_cw)) = 1; # Add its index to grid cell 11061 I(#0,I[#3,1]) = value; # Draw the point 11062 11063 while (da_size(#4)>0, 11064 R = int(u(da_size(#4) - 1e-4)); # Choose a random active list index 11065 P = i[#4,R]; # Get the index of that sample 11066 T = I[#3,P]; # Position vector of that sample 11067 11068 repeat (max_sample_attempts,attempts, 11069 do (S = 4*(u(vectorN(1)) - 0.5); M = mag2(S), M <= 1 || M > 4); 11070 11071 X = T + radius * S; # Potential sample from annulus around T 11072 if (min(X)<0 || min(lim-X)<0, continue()); # Check within bounds 11073 11074 # check proximity of surrounding points 11075 G = int(X/grid_cw); # Grid cell position vector 11076 GI = dot(G,dotoff); # Grid cell direct buffer index 11077 11078 for (K = 0; rejected = 0, K<size(prox), ++K, 11079 V = i[#2,GI+prox[K]]; # Sample index from grid to check 11080 if (V>0 && mag2(I[#3,V]-X)<sqr(radius), rejected = 1; break()) 11081 ); 11082 11083 if (!rejected, 11084 Q = da_size(#3); # Sample found, get new index 11085 da_push(#3,X); # Insert into samples list 11086 da_push(#4,Q); # Insert its index into active 11087 I(#2,G) = Q; # Insert its index into grid 11088 I(#0,X) = value; # Draw the point 11089 break(); 11090 ); 11091 ); 11092 if (attempts==max_sample_attempts, da_remove(#4,R)); 11093 )" 11094 k[0] 11095 endl done 11096 11097#@cli normp : p>=0 11098#@cli : Compute the pointwise Lp-norm norm of vector-valued pixels in selected images. 11099#@cli : Default value: 'p=2'. 11100#@cli : $ image.jpg +normp[0] 0 +normp[0] 1 +normp[0] 2 +normp[0] inf 11101normp : check "isnum(${1==2}) && $1>=0" 11102 e[^-1] "Compute pointwise L"$1"-norm of vectors, in image$?." 11103 if $1==0 != 0 compose_channels + 11104 elif $1==1 abs compose_channels + 11105 elif $1==2 norm 11106 elif $1==inf abs compose_channels max 11107 else ^ $1 compose_channels + ^ {1/$1} 11108 fi 11109 11110#@cli norm 11111#@cli : Compute the pointwise euclidean norm of vector-valued pixels in selected images. 11112#@cli : $ image.jpg +norm 11113#@cli : $$ 11114norm : 11115 e[^-1] "Compute pointwise euclidean norm of vectors, in image$?." 11116 sqr compose_channels + sqrt 11117 11118#@cli n : eq. to 'normalize'. : (+) 11119 11120#@cli normalize : { value0[%] | [image0] },{ value1[%] | [image1] },_constant_case_ratio : [image] : (+) 11121#@cli : Linearly normalize values of selected images in specified range. 11122#@cli : (eq. to 'n'). 11123#@cli : $ image.jpg split x,2 normalize[-1] 64,196 append x 11124#@cli : $$ 11125 11126#@cli normalize_l2 11127#@cli : Normalize selected images such that they have a unit L2 norm. 11128normalize_l2 : 11129 e[^-1] "Normalize image$?, s.t they have a unit L2 norm." 11130 repeat $! /[$>] {norm={$>,in};if(norm!=0,norm,1)} done 11131 11132#@cli normalize_sum 11133#@cli : Normalize selected images such that they have a unit sum. 11134#@cli : $ image.jpg +histogram 256 normalize_sum[-1] display_graph[-1] 400,300 11135normalize_sum : 11136 e[^-1] "Normalize image$?, s.t they have a unit sum." 11137 repeat $! /[$>] {sum={$>,is};if(sum!=0,sum,1)} done 11138 11139#@cli not 11140#@cli : Apply boolean not operation on selected images. 11141#@cli : $ image.jpg +ge 50% +not[-1] 11142not : 11143 e[^-1] "Apply boolean not operation on image$?." 11144 == 0 11145 11146#@cli orientation 11147#@cli : Compute the pointwise orientation of vector-valued pixels in selected images. 11148#@cli : $ image.jpg +orientation +norm[-2] negate[-1] mul[-2] [-1] reverse[-2,-1] 11149#@cli : $$ 11150orientation : 11151 e[^-1] "Compute pointwise orientation vectors, in image$?." 11152 repeat $! +norm[$>] replace. 0,1 /[$>,-1] done 11153 11154#@cli oneminus 11155#@cli : For each selected image, compute one minus image. 11156#@cli : $ image.jpg normalize 0,1 +oneminus 11157oneminus : 11158 e[^-1] "Compute one minus selected images$?." 11159 * -1 + 1 11160 11161#@cli otsu : _nb_levels>0 11162#@cli : Hard-threshold selected images using Otsu's method. 11163#@cli : The computed thresholds are returned as a list of values in the status. 11164#@cli : Default value: 'nb_levels=256'. 11165#@cli : $ image.jpg luminance +otsu , 11166otsu : check "isint(${1=256}) && $1>0" 11167 e[^-1] "Hard-threshold image$? using Otsu\47s method, with $1 histogram levels." 11168 repeat $! l[$>] 11169 imM={[im,iM]} +histogram $1,$imM 11170 otsu={" 11171 sum = sumB = wB = best_variance = best_t = 0; 11172 repeat (w,t,sum+=t*i[t]); 11173 repeat (w,t, 11174 wB+=i[t]; 11175 if (!wB, continue()); 11176 wF = whds#-2 - wB; 11177 if (!wF, break()); 11178 sumB+=t*i[t]; 11179 mB = sumB/wB; 11180 mF = (sum - sumB)/wF; 11181 variance = wB*wF*(mB - mF)^2; 11182 if (variance>best_variance, best_variance = variance; best_t = t); 11183 ); 11184 imM = ["$imM"]; 11185 imM[0] + best_t*(imM[1] - imM[0])/(w - 1)"} 11186 rm. >=. $otsu 11187 if $> u ${},$otsu else u $otsu fi 11188 endl done 11189 11190#@cli polar2complex 11191#@cli : Compute polar to complex transforms of selected images. 11192polar2complex : 11193 e[^-1] "Compute polar to complex transforms of image$?." 11194 repeat int($!/2) l[{2*$>},{2*$>+1}] 11195 ri[1] [0],3 +sin. cos.. *. ... *[-3,-2] 11196 endl done 11197 11198#@cli quantize : nb_levels>=1,_keep_values={ 0 | 1 },_quantization_type={ -1=median-cut | 0=k-means | 1=uniform } 11199#@cli : Quantize selected images. 11200#@cli : Default value: 'keep_values=1' and 'quantization_type=0'. 11201#@cli : $ image.jpg luminance +quantize 3 11202#@cli : $ 200,200,1,1,'cos(x/10)*sin(y/10)' +quantize[0] 6 +quantize[0] 4 +quantize[0] 3 +quantize[0] 2 11203quantize : check "isint($1) && $1>=1 && isbool(${2=1}) && isint(${3=0}) && $3>=-1 && $3<=1" 11204 e[^-1] "Quantize image$? using $1 levels, "${arg\ 1+!$2,with,without}" keeping value range." 11205 repeat $! l[$>] 11206 if $3==1 # Uniform quantization. 11207 if s==1 # Greyscale image. 11208 if $2 mM={[im,iM]} n 0,$1 round 1,-1 min {$1-1} n $mM 11209 else n 0,$1 round 1,-1 min {$1-1} fi 11210 else mM={[im,iM]} uniform_distribution $1,{s} n. $mM index.. .,0,$2 rm. 11211 fi 11212 else +colormap $1,{!$3},1 index.. .,0,$2 rm. # Non-uniform quantization. 11213 fi 11214 endl done 11215 11216#@cli quantize_area : _min_area>0 11217#@cli : Quantize selected images such that each flat region has an area greater or equal to 'min_area'. 11218#@cli : Default value: 'min_area=10'. 11219#@cli : $ image.jpg quantize 3 +blur 1 round[-1] +quantize_area[-1] 2 11220quantize_area : check "${1=10}>0" 11221 e[^-1] "Quantize image$? by regions of areas greater than $1." 11222 if $1==1 return fi 11223 repeat $! l[$>] 11224 if s>1 +f. "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm. round. 0.01 else [0] fi 11225 area. 0,0 <. $1 11226 do 11227 [0] 11228 f.. "* 11229 begin( 11230 const boundary = 1; 11231 offx = [ -1,1,0,0,0,0 ]; 11232 offy = [ 0,0,-1,1,0,0 ]; 11233 offz = [ 0,0,0,0,-1,1 ]; 11234 nb_offs = d>1?6:h>1?4:2; 11235 ); 11236 is_neighbor = j(-1) && j(-1); 11237 if (h>1, is_neighbor&=j(1,0) && j(0,1)); 11238 if (d>1, is_neighbor&=j(0,0,-1) && j(0,0,1)); 11239 is_neighbor = !is_neighbor; 11240 i && is_neighbor?( 11241 col0 = I(#0); 11242 kmin = -1; 11243 distmin = inf; 11244 repeat (nb_offs,k, 11245 p = offx[k]; 11246 q = offy[k]; 11247 r = offz[k]; 11248 if (!j(p,q,r), 11249 col = J(#0,p,q,r); 11250 dist = norm(col-=col0); 11251 if (dist<distmin, distmin = dist; kmin = k); 11252 ); 11253 ); 11254 if (kmin>=0, 11255 I(#-1) = J(#0,offx[kmin],offy[kmin],offz[kmin]); 11256 0, 11257 1 11258 ); 11259 ):i" 11260 rv[0,-1] rm. 11261 while iM 11262 rm. 11263 endl done 11264 11265#@cli rand : { value0[%] | [image0] },_{ value1[%] | [image1] } : [image] : (+) 11266#@cli : Fill selected images with random values uniformly distributed in the specified range. 11267#@cli : $ 400,400,1,3 rand -10,10 +blur 10 sign[-1] 11268 11269#@cli replace : source,target 11270#@cli : Replace pixel values in selected images. 11271#@cli : $ (1;2;3;4) +replace 2,3 11272replace : 11273 e[^-1] "Replace pixel values $1 with $2 in image$?." 11274 f "i==$1?$2:i" 11275 11276#@cli replace_inf : _expression 11277#@cli : Replace all infinite values in selected images by specified expression. 11278#@cli : $ (0;1;2) log +replace_inf 2 11279replace_inf : 11280 e[^-1] "Replace all infinite values in image$? by expression '$1'." 11281 f "isinf(i)?$1:i" 11282 11283#@cli replace_nan : _expression 11284#@cli : Replace all NaN values in selected images by specified expression. 11285#@cli : $ (-1;0;2) sqrt +replace_nan 2 11286replace_nan : 11287 e[^-1] "Replace all NaN values in images$? by expression '$1'." 11288 f "isnan(i)?$1:i" 11289 11290#@cli replace_naninf : _expression 11291#@cli : Replace all NaN and infinite values in selected images by specified expression. 11292replace_naninf : 11293 e[^-1] "Replace all NaN and infinite values in images$? by expression '$1'." 11294 f "isnan(i) || isinf(i)?$1:i" 11295 11296#@cli replace_seq : "search_seq","replace_seq" 11297#@cli : Search and replace a sequence of values in selected images. 11298#@cli : $ (1;2;3;4;5) +replace_seq "2,3,4","7,8" 11299replace_seq : skip "${2=''}" 11300 e[^-1] "Replace value sequence '$1' by value sequence '${2--1}' in image$?." 11301 y repeat $! l[$>] nm={n} 11302 1,100% 11303 eval "ref([ $1 ],str1); 11304 ref([ ${2--1} ],str2); 11305 copy_bloc(pd,src,len) = ( 11306 l = len; 11307 pd + l>=h#1?resize(#1,1,h(#1) + 3*l,1,1,0); 11308 copy(i[pd],src,l); 11309 pd+=l; 11310 ); 11311 for (ps = pd = 0, ps<h#0 && (qs = find(#0,str1,ps))>=0, 11312 qs>ps?copy_bloc(pd,i[#0,ps],qs - ps); 11313 copy_bloc(pd,str2,size(str2)); 11314 ps = qs + size(str1); 11315 ); 11316 ps<h#0?copy_bloc(pd,i[#0,ps],h#0 - ps); 11317 resize(#1,1,pd,1,1,0)" 11318 k. nm $nm 11319 endl done 11320 11321#@cli replace_str : "search_str","replace_str" 11322#@cli : Search and replace a string in selected images (viewed as strings, i.e. sequences of character codes). 11323#@cli : $ ('"Hello there, how are you ?"') +replace_str "Hello there","Hi David" 11324replace_str : skip "${2=}" 11325 e[^-1] "Replace string '$1' by string '${2--1}' in image$?." 11326 replace_seq {``{'"$1"'}},{'"${2--1}"'} 11327 11328#@cli round : rounding_value>=0,_rounding_type : (no arg) : (+) 11329#@cli : Round values of selected images. 11330#@cli : 'rounding_type' can be { -1=backward | 0=nearest | 1=forward }. 11331#@cli : Default value: 'rounding_type=0'. 11332#@cli : $ image.jpg +round 100 11333#@cli : $ image.jpg mul {pi/180} sin +round 11334 11335#@cli roundify : gamma>=0 11336#@cli : Apply roundify transformation on float-valued data, with specified gamma. 11337#@cli : Default value: 'gamma=0'. 11338#@cli : $ 1000 fill '4*x/w' repeat 5 +roundify[0] {$>*0.2} done append c display_graph 400,300 11339roundify : check $1>=0 11340 e[^-1] "Roundify image$?, with gamma $1." 11341 if $1==1 return fi 11342 repeat $! l[$>] 11343 +round 1 -.. . +*.. 2 abs. ^. $1 sign... *[-3,-1] *.. 0.5 + 11344 endl done 11345 11346#@cli = : eq. to 'set'. : (+) 11347 11348#@cli set : value,_x[%],_y[%],_z[%],_c[%] : (+) 11349#@cli : Set pixel value in selected images, at specified coordinates. 11350#@cli : (eq. to '=').\n 11351#@cli : If specified coordinates are outside the image bounds, no action is performed. 11352#@cli : Default values: 'x=y=z=c=0'. 11353#@cli : $ 2,2 set 1,0,0 set 2,1,0 set 3,0,1 set 4,1,1 11354#@cli : $ image.jpg repeat 10000 set 255,{u(100)}%,{u(100)}%,0,{u(100)}% done 11355 11356#@cli threshold : value[%],_is_soft={ 0 | 1 } : 11357#@cli : Threshold values of selected images. 11358#@cli : 'soft' can be { 0=hard-thresholding | 1=soft-thresholding }. 11359#@cli : Default value: 'is_soft=0'. 11360#@cli : $ image.jpg +threshold[0] 50% +threshold[0] 50%,1 11361#@cli : $$ 11362threshold : check "isexpr($1) && isbool(${2=0})" 11363 e[^-1] ${"arg 1+!$2,Soft,Hard"}"-threshold image$? by $1." 11364 if $2 # Soft thresholding 11365 f "begin( 11366 str = ['$1']; 11367 value = str[size(str)-1]==_'%'?im + (iM-im)*$1:$1 11368 ); 11369 i>=value?i - value: 11370 i<=-value?i + value:0" 11371 else ge $1 11372 fi 11373 11374#@cli vector2tensor 11375#@cli : Convert selected vector fields to corresponding tensor fields. 11376vector2tensor : 11377 e[^-1] "Convert vector field$? to tensor field$?." 11378 repeat $! l[$>] 11379 s c 11380 if $!==2 +sqr. *.. ... sqr... 11381 elif $!==3 +sqr.. +*... .. +sqr... *[-5,-4] [-6] sqr[-6] 11382 else error[0--4] "Command '$0': Invalid image ["{$!-$>-1}"] : Dimensions "{w}","{h}","{d}","{s}" does not 11383 represent a field of 2D or 3D vectors." 11384 fi 11385 a c 11386 endl done 11387 11388#--------------------------------- 11389# 11390#@cli :: Colors 11391# 11392#--------------------------------- 11393 11394#@cli adjust_colors : -100<=_brightness<=100,-100<=_contrast<=100,-100<=_gamma<=100,-100<=_hue_shift<=100,\ 11395# -100<=_saturation<=100,_value_min,_value_max 11396#@cli : Perform a global adjustment of colors on selected images. 11397#@cli : Range of correct image values are considered to be in [value_min,value_max] (e.g. [0,255]). 11398#@cli : If 'value_min==value_max==0', value range is estimated from min/max values of selected images. 11399#@cli : Processed images have pixel values constrained in [value_min,value_max]. 11400#@cli : Default values: 'brightness=0', 'contrast=0', 'gamma=0', 'hue_shift=0', 'saturation=0', 'value_min=value_max=0'. 11401#@cli : $ image.jpg +adjust_colors 0,30,0,0,30 11402adjust_colors : check "${1=0}>=-100 && $1<=100 && ${2=0}>=-100 && $2<=100 && ${3=0}>=-100 && $3<=100 && 11403 ${4=0}>=-100 && $4<=100 && ${5=0}>=-100 && $5<=100" skip ${6=0},${7=0} 11404 e[^-1] "Adjust colors of image$?, with brightness $1, contrast $2, gamma $3, hue shift $4, saturation $5 and 11405 value range [$6,$7]." 11406 repeat $! l[$>] split_opacity l[0] 11407 range={"$6==$7 && $6==0?[im,iM]:[min($6,$7),max($6,$7)]"} 11408 m={arg(1,$range)} M={arg(2,$range)} fact={255/max(1e-5,$M-$m)} 11409 - $m * $fact 11410 if $4" || "$5 # Adjust Hue/Saturation 11411 to_rgb[0] rgb2hsv[0] 11412 sh[0] 0 +. {$4*1.8} rm. 11413 sh[0] 1 +. {($5%)^(1+($5>0))} c. 0,1 rm. 11414 hsv2rgb[0] 11415 fi 11416 if $3 # Adjust Gamma 11417 /[0] 255 ^[0] {10^-($3%)} *[0] 255 11418 fi 11419 if $2 # Adjust Contrast 11420 -[0] 128 *[0] {exp($2/64)} +[0] 128 11421 fi 11422 +[0] {$1*2} # Adjust Brightness 11423 /[0] $fact +[0] $m c[0] $range # Renormalize values. 11424 a c 11425 endl a c endl done 11426 11427#@cli ac : eq. to 'apply_channels'. 11428ac : 11429 _gmic_s="$?" v + _apply_channels $"*" 11430 11431#@cli apply_channels : "command",color_channels,_value_action={ 0=none | 1=cut | 2=normalize } 11432#@cli : Apply specified command on the chosen color channel(s) of each selected images. 11433#@cli : (eq. to 'ac').\n 11434#@cli : Argument 'color_channels' refers to a colorspace, and can be basically one of 11435#@cli : { all | rgba | [s]rgb | ryb | lrgb | ycbcr | lab | lch | hsv | hsi | hsl | cmy | cmyk | yiq }. 11436#@cli : You can also make the processing focus on a few particular channels of this colorspace, 11437#@cli : by setting 'color_channels' as 'colorspace_channel' (e.g. 'hsv_h' for the hue). 11438#@cli : All channel values are considered to be provided in the [0,255] range. 11439#@cli : Default value: 'value_action=0'. 11440#@cli : $ image.jpg +apply_channels "equalize blur 2",ycbcr_cbcr 11441apply_channels : 11442 _gmic_s="$?" v + _$0 $"*" 11443 11444_apply_channels : check "isint(${3=0}) && $3>=0 && $3<=2" 11445 channels=${"_ac_list \"$2\""} 11446 e[^-1] "Apply command '$1' on channels '"$channels"' of image"$_gmic_s"." 11447 ('$/') id={h=0;for(k=0,k<w,((h*=31)+=i[k++])%=1048576)} rm. 11448 _ac_$channels m _ac_precond$id:$_p m _ac_forward$id:$_f m _ac_backward$id:$_b 11449 repeat $! l[$>] 11450 _ac_precond$id is_alpha={s==2" || "s==4} 11451 if $is_alpha s c,{1-s} fi 11452 _ac_forward$id[0] a c 11453 sh $_s _ac. "$1" 11454 if $3==1 c. 0,255 elif $3==2 n. 0,255 fi 11455 rm. 11456 if $is_alpha s c,{1-s} fi 11457 _ac_backward$id[0] a c 11458 endl done 11459 um _ac_precond$id,_ac_forward$id,_ac_backward$id 11460 11461_ac_list : 11462 if isnum("$1") 11463 arg 1+round($1),all,rgba,rgb,rgb_r,rgb_g,rgb_b,rgba_a,\ 11464 lrgb,lrgb_r,lrgb_g,lrgb_b,\ 11465 ycbcr_y,ycbcr_cbcr,ycbcr_cb,ycbcr_cr,ycbcr_cg,\ 11466 lab_l,lab_ab,lab_a,lab_b,\ 11467 lch_ch,lch_c,lch_h,\ 11468 hsv_h,hsv_s,hsv_v,hsi_i,hsl_l,\ 11469 cmyk_c,cmyk_m,cmyk_y,cmyk_k,\ 11470 yiq_y,yiq_iq,ryb,ryb_r,ryb_y,ryb_b 11471 else u "$1" fi 11472 11473_ac : 11474 whds={w},{h},{d},{s} ${1--1} k[0] r $whds,0 11475 11476_ac_all : _p="" _f="" _b="" _s=0,100% 11477 11478_ac_rgba : _p="to_rgba" _f="" _b="" _s=0,3 11479_ac_rgba_r : _p="to_color" _f="" _b="" _s=0 11480_ac_rgba_g : _p="to_color" _f="" _b="" _s=1 11481_ac_rgba_b : _p="to_color" _f="" _b="" _s=2 11482_ac_rgba_a : _p="to_rgba" _f="" _b="" _s=3 11483 11484_ac_rgb : _p="to_color" _f="" _b="" _s=0,2 11485_ac_rgb_r : _ac_rgba_r 11486_ac_rgb_g : _ac_rgba_g 11487_ac_rgb_b : _ac_rgba_b 11488 11489_ac_srgb : _ac_rgb 11490_ac_srgb_r : _ac_rgb_r 11491_ac_srgb_g : _ac_rgb_g 11492_ac_srgb_b : _ac_rgb_b 11493 11494_ac_lrgb : _p="to_color" _f="srgb2rgb" _b="rgb2srgb" _s=0,2 11495_ac_lrgb_r : _p="to_color" _f="srgb2rgb" _b="rgb2srgb" _s=0 11496_ac_lrgb_g : _p="to_color" _f="srgb2rgb" _b="rgb2srgb" _s=1 11497_ac_lrgb_b : _p="to_color" _f="srgb2rgb" _b="rgb2srgb" _s=2 11498 11499_ac_ryb : _p="to_color" _f="rgb2ryb" _b="ryb2rgb" _s=0,2 11500_ac_ryb_r : _p="to_color" _f="rgb2ryb" _b="ryb2rgb" _s=0 11501_ac_ryb_y : _p="to_color" _f="rgb2ryb" _b="ryb2rgb" _s=1 11502_ac_ryb_b : _p="to_color" _f="rgb2ryb" _b="ryb2rgb" _s=2 11503 11504_ac_ycbcr : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=0,2 11505_ac_ycbcr_y : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=0 11506_ac_ycbcr_cbcr : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=1,2 11507_ac_ycbcr_cb : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=1 11508_ac_ycbcr_cr : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=2 11509_ac_ycbcr_cg : _p="to_color" _f="sh 0,1 mirror. c rm. rgb2ycbcr" _b="ycbcr2rgb sh 0,1 mirror. c rm." _s=2 11510 11511_ac_lab : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=0,2 11512_ac_lab_l : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=0 11513_ac_lab_ab : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=1,2 11514_ac_lab_a : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=1 11515_ac_lab_b : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=2 11516 11517_ac_lch : _p="to_color" _f="srgb2rgb rgb2lch8" _b="lch82rgb rgb2srgb" _s=0,2 11518_ac_lch_l : _ac_lab_l 11519_ac_lch_ch : _p="to_color" _f="srgb2rgb rgb2lch8" _b="lch82rgb rgb2srgb" _s=1,2 11520_ac_lch_c : _p="to_color" _f="srgb2rgb rgb2lch8" _b="lch82rgb rgb2srgb" _s=1 11521_ac_lch_h : _p="to_color" _f="srgb2rgb rgb2lch8" _b="lch82rgb rgb2srgb" _s=2 11522 11523_ac_hsv : _p="to_color" _f="rgb2hsv8" _b="hsv82rgb" _s=0,2 11524_ac_hsv_h : _p="to_color" _f="rgb2hsv8" _b="hsv82rgb" _s=0 11525_ac_hsv_s : _p="to_color" _f="rgb2hsv8" _b="hsv82rgb" _s=1 11526_ac_hsv_v : _p="to_color" _f="rgb2hsv8" _b="hsv82rgb" _s=2 11527 11528_ac_hsi : _p="to_color" _f="rgb2hsi8" _b="hsi82rgb" _s=0,2 11529_ac_hsi_h : _p="to_color" _f="rgb2hsi8" _b="hsi82rgb" _s=0 11530_ac_hsi_s : _p="to_color" _f="rgb2hsi8" _b="hsi82rgb" _s=1 11531_ac_hsi_i : _p="to_color" _f="rgb2hsi8" _b="hsi82rgb" _s=2 11532 11533_ac_hsl : _p="to_color" _f="rgb2hsl8" _b="hsl82rgb" _s=0,2 11534_ac_hsl_h : _p="to_color" _f="rgb2hsl8" _b="hsl82rgb" _s=0 11535_ac_hsl_s : _p="to_color" _f="rgb2hsl8" _b="hsl82rgb" _s=1 11536_ac_hsl_l : _p="to_color" _f="rgb2hsl8" _b="hsl82rgb" _s=2 11537 11538_ac_cmy : _p="to_color" _f="rgb2cmy" _b="cmy2rgb" _s=0,2 11539_ac_cmy_c : _p="to_color" _f="rgb2cmy" _b="cmy2rgb" _s=0 11540_ac_cmy_m : _p="to_color" _f="rgb2cmy" _b="cmy2rgb" _s=1 11541_ac_cmy_y : _p="to_color" _f="rgb2cmy" _b="cmy2rgb" _s=2 11542 11543_ac_cmyk : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=0,3 11544_ac_cmyk_c : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=0 11545_ac_cmyk_m : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=1 11546_ac_cmyk_y : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=2 11547_ac_cmyk_k : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=3 11548 11549_ac_yiq : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=0,2 11550_ac_yiq_y : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=0 11551_ac_yiq_iq : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=1,2 11552_ac_yiq_i : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=1 11553_ac_yiq_q : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=2 11554 11555#@cli autoindex : nb_colors>0,0<=_dithering<=1,_method={ 0=median-cut | 1=k-means } 11556#@cli : Index selected vector-valued images by adapted colormaps. 11557#@cli : Default values: 'dithering=0' and 'method=1'. 11558#@cli : $ image.jpg +autoindex[0] 4 +autoindex[0] 8 +autoindex[0] 16 11559autoindex : check "isint($1) && $1>0 && ${2=0}>=0" skip ${3=1} 11560 e[^-1] "Index colors in images$? by adapted colormap with $1 entries, dithering level $2 and "\ 11561 ${arg\ 1+!$3,k-means,median-cut}" method." 11562 repeat $! l[$>] 11563 if w>h if w>256 +r2dx 256 else [0] fi 11564 else if h>256 +r2dy 256 else [0] fi 11565 fi 11566 colormap[1] $1,$3,0 11567 index[0] [1],$2,1 rm[1] 11568 endl done 11569 11570#@cli bayer2rgb : _GM_smoothness,_RB_smoothness1,_RB_smoothness2 11571#@cli : Transform selected RGB-Bayer sampled images to color images. 11572#@cli : Default values: 'GM_smoothness=RB_smoothness=1' and 'RB_smoothness2=0.5'. 11573#@cli : $ image.jpg rgb2bayer 0 +bayer2rgb 1,1,0.5 11574bayer2rgb : skip ${1=1},${2=1},${3=0.5} 11575 e[^-1] "Transform RGB-Bayer image$? to color images, with smoothness ($1,$2,$3)." 11576 channels 0 repeat $! l[$>] 11577 11578 # Expand image size to avoid problems with borders. 11579 expand_x {"2 + 4*$1"},0 expand_y {"2 + 4*$1"},0 11580 11581 # Compute green-magenta chromaticity. 11582 (-1,1;1,-1) r. ..,..,1,1,0,2 11583 +*.. . 11584 11585 (0.25,0.5,0.25) convolve.. . transpose. convolve.. . rm. 11586 b. $1 11587 11588 *.. . 11589 -[-3,-2] 11590 11591 # Compute red-blue chromaticity. 11592 (1,-1) r. ..,..,1,1,0,2 # Horizontal estimate 11593 *. ... 11594 (0.25,0.5,0.25) convolve.. . transpose. convolve.. . rm. 11595 blur_y. $2 blur_x. $3 11596 11597 (1;-1) r. ..,..,1,1,0,2 # Vertical estimate 11598 *. [-4] 11599 (0.25,0.5,0.25) convolve.. . transpose. convolve.. . rm. 11600 blur_x. $2 blur_y. $3 11601 11602 +[-2,-1] /. 2 11603 11604 # Luminance reconstruction. 11605 (2,0;0,-2) r. ..,..,1,1,0,2 11606 *. .. 11607 -[-4,-1] 11608 11609 # RGB reconstruction. 11610 a[-3--1] c 11611 mix_rgb. 1,-1,2,1,1,0,1,-1,-2 11612 11613 # Shrink to original image size. 11614 shrink_x {"2 + 4*$1"},0 shrink_y {"2 + 4*$1"},0 11615 c 0,255 11616 11617 endl done 11618 11619#@cli deltaE : [image],_metric={ 0=deltaE_1976 | 1=deltaE_2000 },"_to_Lab_command" 11620#@cli : Compute the CIE DeltaE color difference between selected images and specified [image]. 11621#@cli : Argument 'to_Lab_command' is a command able to convert colors of [image] into a Lab representation. 11622#@cli : Default values: 'metric=1' and 'to_Lab_command="srgb2lab"'. 11623#@cli : $ image.jpg +blur 2 +deltaE[0] [1],1,srgb2lab 11624deltaE : check ${"is_image_arg $1"}" && isbool(${2=1})" skip "${3=srgb2lab}" 11625 e[^-1] "Compute the CIE DeltaE_"${"s0,s1=1976,2000 u $s$2"}" color difference between image$? and image$1, "\ 11626 "with to_Lab command '$3'." 11627 pass$1 1 11628 needs_to_lab={"s = ['$3']; s!=0 && s!=' '"} 11629 if $needs_to_lab m "_deltaE_to_lab : $3" +_deltaE_to_lab. rm.. fi 11630 repeat $!-1 l[$>,-1] nm={0,n} 11631 if $needs_to_lab _deltaE_to_lab[0] fi 11632 if !$2 -.. . norm.. # DeltaE_1976 11633 else 100%,100%,100%,1,${-math_lib}"deltaE00(I#0,I#1)" rv[0,-1] rm. # DeltaE_2000 11634 fi 11635 nm[0] $nm endl done 11636 rm. um _deltaE_to_lab 11637 11638#@cli cmy2rgb 11639#@cli : Convert color representation of selected images from CMY to RGB. 11640cmy2rgb : 11641 e[^-1] "Convert color representation of image$? from CMY to RGB." 11642 rgb2cmy 11643 11644#@cli cmyk2rgb 11645#@cli : Convert color representation of selected images from CMYK to RGB. 11646cmyk2rgb : 11647 e[^-1] "Convert color representation of image$? from CMYK to RGB." 11648 repeat $! l[$>] 11649 s c +/. -255 +. 1 *[0-2] . rm. +[0-2] . rm. 11650 a c cmy2rgb 11651 endl done 11652 11653#@cli colorblind : type={ 0=protanopia | 1=protanomaly | 2=deuteranopia | 3=deuteranomaly | \ 11654# 4=tritanopia | 5=tritanomaly | 6=achromatopsia | 7=achromatomaly } 11655#@cli : Simulate color blindness vision. 11656#@cli : Simulation method of Vienot, Brettel & Mollon 1999, \ 11657# "Digital video colourmaps for checking the legibility of displays by dichromats". 11658#@cli : The dichromacy matrices of the paper were adapted to sRGB (RGB->XYZ). 11659#@cli : Anomalous trichromacy simulated via linear interpolation with the identity and a factor of 0.6. 11660#@cli : $ image.jpg +colorblind 0 11661colorblind : check "isint($1) && $1>=0 && $1<=7" 11662 s0="protanopia" s1="protanomaly" s2="deuteranopia" s3="deuteranomaly" s4="tritanopia" 11663 s5="tritanomaly" s6="achromatopsia" s7="achromatomaly" 11664 e[^-1] "Simulate color blindness of type '"${s$1}"' on image$?." 11665 type0=(0.10889,0.89111,0;0.10889,0.89111,0;0.00447,-0.00447,1.0) 11666 type1=(0.46533,0.53467,0;0.06533,0.93467,0;0.00268,-0.00268,1) 11667 type2=(0.29031,0.70969,0;0.29031,0.70969,0;-0.02197,0.02197,1) 11668 type3=(0.57418,0.42582,0;0.17418,0.82582,0;-0.01318,0.01318,1) 11669 type4=(1,0.15236,-0.15236;0,0.86717,0.13283;0,0.86717,0.13283) 11670 type5=(1,0.09142,-0.09142;0,0.92030,0.07970;0,0.52030,0.47970) 11671 type6=(0.299,0.587,0.114;0.299,0.587,0.114;0.299,0.587,0.114) 11672 type7=(0.618,0.320,0.062;0.163,0.775,0.062;0.163,0.320,0.516) 11673 repeat $! l[$>] split_opacity l[0] to_rgb srgb2rgb mix_channels ${type$1} rgb2srgb endl a c endl done 11674 11675#@cli colormap : nb_levels>=0,_method={ 0=median-cut | 1=k-means },_sort_vectors 11676#@cli : Estimate best-fitting colormap with 'nb_colors' entries, to index selected images. 11677#@cli : Set 'nb_levels==0' to extract all existing colors of an image. 11678#@cli : 'sort_vectors' can be { 0=unsorted | 1=by increasing norm | 2=by decreasing occurrence }. 11679#@cli : Default value: 'method=1' and 'sort_vectors=1'. 11680#@cli : $ image.jpg +colormap[0] 4 +colormap[0] 8 +colormap[0] 16 11681#@cli : $$ https://gmic.eu/oldtutorial/_colormap 11682colormap : check "isint($1) && $1>=0" skip ${2=1},${3=1} 11683 if $1 e[0--3] "Estimate colormap with $1 entries for image$?, by "${arg\ 1+!$2,k-means,median-cut}" method." 11684 else e[0--3] "Estimate full colormap for image$?." 11685 fi 11686 repeat $! l[$>] nm={b} is_half=${-is_half} 11687 11688 if $1 # Estimate quantized colormap. 11689 r {whd},1,1,100%,-1 11690 if !$2 +_colormap $1 # Just run the median-cut algorithm 11691 else 11692 +_colormap $1 11693 max_diff={(iM-im+1)/8192} 11694 do 11695 +index.. . # Find nearest cluster for each color 11696 if $is_half 11697 ..,1,1,{1,s} 11698 eval " 11699 ref(vector(#w*s#0),csum); 11700 ref(vector(#w,0),cocc); 11701 repeat (w#2,k, 11702 val = i[#2,k]; 11703 repeat (s#0,c,csum[val + c*w]+=i(#0,k,0,0,c)); 11704 ++cocc[val]; 11705 ); 11706 off = 0; 11707 repeat (s#0,c, 11708 repeat (w,k,occ = cocc[k]; occ?(csum[off++]/=occ)); 11709 ); 11710 draw(#3,csum,0,0,0,0)" 11711 rm.. 11712 else 11713 ..,1,1,{1,s+1} 11714 f.. ">I[#3,i]+=[ I[#0,x],1 ]" rm.. 11715 f. "s = i(x,0,0,s-1); s?I/s:[ I[#1,x], 0 ]" 11716 fi 11717 +-.. . abs. diff={iM/w} rm. # Compute colormap difference 11718 j.. . rm. 11719 while $diff>$max_diff 11720 fi 11721 if $3 index.. .,0,0 histogram.. {[w,0,w-1]} a y sort -,x rows 1 # Sort by decreasing occurrence 11722 else rm.. 11723 fi 11724 11725 else # Extract full colormap. 11726 11727 # Compute map of hashcodes. 11728 +n. 0,255 f. "ret = vectors(); H = 0; repeat (s,p,(H*=31)+=j(0,0,0,p)); ret[0] = H%2048; ret" 11729 channels. 0 equalize. 2048 n. 0,2047 round. 11730 11731 # Find single occurrence of each color/vector. 11732 1,1,1,.. .x2047 11733 eval[0] "> 11734 begin( ret = vectors(); col_r = vectors() ); 11735 col_s = I; 11736 H = 2 + i#1; 11737 sH = da_size(#H); 11738 is_found = 0; 11739 repeat (sH,p, 11740 copy(col_r,i[#H,p],s#0,1,h(#H)); 11741 col_r==col_s?(is_found = 1; break()); 11742 ); 11743 !is_found?da_push(#H,col_s); 11744 ret; 11745 end(repeat (l - 2,p, resize(#2 + p,1,da_size(#2 + p),1,s#0,0)))" 11746 a[2--1] y transpose. k. 11747 fi 11748 11749 if $3==1 +norm rv a c sort +,x channels 1,100% fi # Sort colors by increasing norm. 11750 nm "[colormap of "$nm"]" 11751 endl done 11752 11753_colormap : # Implementation of the median-cut algorithm. 11754 m "__colormap : repeat s sh[$""1] $> =.. {iv},$""1,0,0,$> rm. done" 11755 1,1,1,{s} __colormap 0 # Initialize image of box variances 11756 repeat $1-1 11757 b,a={[xM,cM]} # b = box with highest variance, a = axis with highest variance 11758 shift[$b] 0,0,0,{-$a},2 sort[$b] +,x shift[$b] 0,0,0,$a,2 11759 if {$b,w>1} s[$b] x,2 else 1 fi # Split selected box along its median axis 11760 mv[$b] -1 r. {w+1},1,1,100%,0 11761 __colormap $b __colormap {$!-2} # Update box variances 11762 done 11763 rm. r 1,1,1,100%,2 a x # Average value in each box and append as final colormap 11764 um __colormap 11765 11766#@cli compose_channels 11767#@cli : Compose all channels of each selected image, using specified arithmetic operator (+,-,or,min,...). 11768#@cli : Default value: '1=+'. 11769#@cli : $ image.jpg +compose_channels and 11770#@cli : $$ 11771compose_channels : skip ${1="+"} 11772 e[^-1] "Compose all channels of image$?, with operator '$1'." 11773 repeat $! l[$>] 11774 sh 0 11775 repeat s#-2-1 sh.. {$>+1} l[-2,-1] $1 endl done 11776 rm. r 100%,100%,100%,1,-1 11777 endl done 11778 11779#@cli direction2rgb 11780#@cli : Compute RGB representation of selected 2D direction fields. 11781#@cli : $ image.jpg luminance gradient append c blur 2 orientation +direction2rgb 11782direction2rgb : 11783 e[^-1] "Compute RGB representation of 2D direction field$?." 11784 channels 0,1 repeat $! l[$>] nm={0,n} 11785 s c complex2polar round.. 0.001 11786 *. {180/pi} %. 360 100%,100%,1,1,1 mv... $! 11787 if im!=iM n. 0,1 else f. 1 fi 11788 a c hsv2rgb 11789 nm $nm endl done 11790 11791#@cli ditheredbw 11792#@cli : Create dithered B&W version of selected images. 11793#@cli : $ image.jpg +equalize ditheredbw[-1] 11794ditheredbw : 11795 e[^-1] "Create dithered B&W version of image$?." 11796 repeat $! l[$>] split_opacity 11797 luminance[0] n[0] 0,255 (0,255) index[0] .,1,1 rm. 11798 a c endl done 11799 11800#@cli fc : eq. to 'fill_color'. 11801fc : 11802 _gmic_s="$?" v + _fill_color $* 11803 11804#@cli fill_color : col1,...,colN 11805#@cli : Fill selected images with specified color. 11806#@cli : (eq. to 'fc'). 11807#@cli : $ image.jpg +fill_color 255,0,255 11808#@cli : $$ https://gmic.eu/oldtutorial/_fill_color 11809fill_color : 11810 _gmic_s="$?" v + _$0 $* 11811 11812_fill_color : 11813 e[0--3] "Fill image"$_gmic_s" with color (${^0})." 11814 repeat $! l[$>] 11815 repeat s sh[0] $> f. {arg(1+$>,${^0})} done k[0] 11816 nm {n} endl done 11817 11818#@cli gradient2rgb : _is_orientation={ 0 | 1 } 11819#@cli : Compute RGB representation of 2D gradient of selected images. 11820#@cli : Default value: 'is_orientation=0'. 11821#@cli : $ image.jpg +gradient2rgb 0 equalize[-1] 11822gradient2rgb : check "isbool(${1=0})" 11823 arg 1+!$1,"orientation ","" 11824 e[^-1] "Compute RGB representation of 2D gradient "${}"of image$?." 11825 norm repeat $! l[$>] 11826 if $1 gradient_orientation 2 else g xy fi 11827 a c direction2rgb 11828 endl done 11829 11830#@cli hcy2rgb 11831#@cli : Convert color representation of selected images from HCY to RGB. 11832hcy2rgb : 11833 e[^-1] "Convert color representation of image$? from HCY to RGB." 11834 to_color f " 11835 H = (R/60)%6; 11836 X = G*(1 - abs(H%2 - 1)); 11837 RGB = arg(1 + int(H),[G,X,0],[X,G,0],[0,G,X],[0,X,G],[X,0,G],[G,0,X]); 11838 m = B - 0.3*RGB[0] - 0.59*RGB[1] - 0.11*RGB[2]; 11839 cut((RGB+=m)*=255,0,255)" 11840 11841#@cli hsi2rgb 11842#@cli : Convert color representation of selected images from HSI to RGB. 11843hsi2rgb : 11844 e[^-1] "Convert color representation of image$? from HSI to RGB." 11845 to_color 11846 f " 11847 H = (R/60)%6; 11848 S = G; 11849 I = B; 11850 Z = 1 - abs((H%2) - 1); 11851 C = I*S/(1 + Z); 11852 X = C*Z; 11853 m = I*(1 - S)/3; 11854 RGB = arg(1 + int(H),[C,X,0],[X,C,0],[0,C,X],[0,X,C],[X,0,C],[C,0,X]); 11855 (RGB+=m)*=3*255" 11856 11857#@cli hsi82rgb 11858#@cli : Convert color representation of selected images from HSI8 to RGB. 11859hsi82rgb : 11860 e[^-1] "Convert color representation of image$? from HSI8 to RGB." 11861 _hsx82rgb hsi2rgb 11862 11863#@cli hsl2rgb 11864#@cli : Convert color representation of selected images from HSL to RGB. 11865hsl2rgb : 11866 e[^-1] "Convert color representation of image$? from HSL to RGB." 11867 to_color 11868 f " 11869 H = (R/60)%6; 11870 S = G; 11871 L = B; 11872 C = (1 - abs(2*L - 1))*S; 11873 X = C*(1 - abs(H%2 - 1)); 11874 m = L - C/2; 11875 RGB = arg(1 + int(H),[C,X,0],[X,C,0],[0,C,X],[0,X,C],[X,0,C],[C,0,X]); 11876 (RGB+=m)*=255" 11877 11878#@cli hsl82rgb 11879#@cli : Convert color representation of selected images from HSL8 to RGB. 11880hsl82rgb : 11881 e[^-1] "Convert color representation of image$? from HSL8 to RGB." 11882 _hsx82rgb hsl2rgb 11883 11884#@cli hsv2rgb 11885#@cli : Convert color representation of selected images from HSV to RGB. 11886#@cli : $ (0,360;0,360^0,0;1,1^1,1;1,1) resize 400,400,1,3,3 hsv2rgb 11887hsv2rgb : 11888 e[^-1] "Convert color representation of image$? from HSV to RGB." 11889 to_color 11890 f " 11891 H = (R/60)%6; 11892 S = G; 11893 V = B; 11894 C = V*S; 11895 X = C*(1 - abs(H%2 - 1)); 11896 m = V - C; 11897 RGB = arg(1 + int(H),[C,X,0],[X,C,0],[0,C,X],[0,X,C],[X,0,C],[C,0,X]); 11898 (RGB+=m)*=255" 11899 11900#@cli hsv82rgb 11901#@cli : Convert color representation of selected images from HSV8 to RGB. 11902hsv82rgb : 11903 e[^-1] "Convert color representation of image$? from HSV8 to RGB." 11904 _hsx82rgb hsv2rgb 11905 11906_hsx82rgb : 11907 repeat $! 11908 sh[$>] 0 /. 0.708333 rm. 11909 sh[$>] 1,2 /. 255 rm. 11910 done 11911 11912#@cli int2rgb 11913#@cli : Convert color representation of selected images from INT24 to RGB. 11914int2rgb : 11915 e[^-1] "Convert color representation of image$? from INT24 scalars to RGB." 11916 round repeat $! l[$>] 11917 +>> 8 &[1] 255 +&[0] 255 >>[0] 16 a c 11918 endl done 11919 11920#@cli jzazbz2rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11921#@cli : Convert color representation of selected images from RGB to Jzazbz. 11922#@cli : Default value: 'illuminant=2'. 11923jzazbz2rgb : skip "${1=,}" 11924 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 11925 e[^-1] "Convert color representation of image$? from Jzazbz to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11926 jzazbz2xyz xyz2rgb $illu 11927 11928#@cli jzazbz2xyz 11929#@cli : Convert color representation of selected images from RGB to XYZ. 11930jzazbz2xyz : 11931 e[^-1] "Convert color representation of image$? from Jzazbz to XYZ." 11932 repeat $! l[$>] split_opacity 11933 f[0] ${-_jzazbz_const}" 11934 tmp = i0 + Jzazbz_d0; 11935 Iz = tmp/(1 + Jzazbz_d - Jzazbz_d*tmp); 11936 azz = i1; 11937 bzz = i2; 11938 Lp = Iz + 0.138605043271539*azz + 0.0580473161561189*bzz; 11939 Mp = Iz - 0.138605043271539*azz - 0.0580473161561189*bzz; 11940 Sp = Iz - 0.0960192420263189*azz - 0.811891896056039*bzz; 11941 tmp = Lp^(1/Jzazbz_p); 11942 L = peakLum*((Jzazbz_c1 - tmp)/(Jzazbz_c3*tmp-Jzazbz_c2))^(1/Jzazbz_n); 11943 tmp = Mp^(1/Jzazbz_p); 11944 M = peakLum*((Jzazbz_c1 - tmp)/(Jzazbz_c3*tmp-Jzazbz_c2))^(1/Jzazbz_n); 11945 tmp = Sp^(1/Jzazbz_p); 11946 S = peakLum*((Jzazbz_c1 - tmp)/(Jzazbz_c3*tmp-Jzazbz_c2))^(1/Jzazbz_n); 11947 Xp = 1.92422643578761*L - 1.00479231259537*M + 0.037651404030618*S; 11948 Yp = 0.350316762094999*L + 0.726481193931655*M - 0.065384422948085*S; 11949 Zp = -0.0909828109828476*L - 0.312728290523074*M + 1.52276656130526*S; 11950 X = (Xp + (Jzazbz_b - 1)*Zp)/Jzazbz_b; 11951 Y = (Yp + (Jzazbz_g - 1)*X)/Jzazbz_g; 11952 Z = Zp; 11953 [ X,Y,Z ]/255" 11954 a c endl done 11955 11956# The XYZ<->Jzazbz conversion code has been written by Alan Gibson, 11957# and published on this page: <http://im.snibgo.com/jzazbz.htm> 11958_jzazbz_const : 11959 u "const Jzazbz_b = 1.15; 11960 const Jzazbz_g = 0.66; 11961 const Jzazbz_c1 = 3424/4096; 11962 const Jzazbz_c2 = 2413/128; 11963 const Jzazbz_c3 = 2392/128; 11964 const Jzazbz_n = 2610/16384; 11965 const Jzazbz_p = 1.7*2523/32; 11966 const Jzazbz_d = -0.56; 11967 const Jzazbz_d0 = 1.6295499532821566e-11; 11968 const peakLum = 10000;" 11969 11970#@cli lab2lch 11971#@cli : Convert color representation of selected images from Lab to Lch. 11972lab2lch : 11973 e[^-1] "Convert color representation of image$? from Lab to Lch." 11974 repeat $! l[$>] 11975 to_color s c complex2polar[1,2] a c 11976 endl done 11977 11978#@cli lab2rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11979#@cli : Convert color representation of selected images from Lab to RGB. 11980#@cli : Default value: 'illuminant=2'. 11981#@cli : $ (50,50;50,50^-3,3;-3,3^-3,-3;3,3) resize 400,400,1,3,3 lab2rgb 11982lab2rgb : skip "${1=,}" 11983 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 11984 e[^-1] "Convert color representation of image$? from Lab to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11985 lab2xyz $illu xyz2rgb $illu 11986 11987#@cli lab2srgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11988#@cli : Convert color representation of selected images from Lab to sRGB. 11989#@cli : Default value: 'illuminant=2'. 11990#@cli : $ (50,50;50,50^-3,3;-3,3^-3,-3;3,3) resize 400,400,1,3,3 lab2rgb 11991lab2srgb : skip "${1=,}" 11992 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 11993 e[^-1] "Convert color representation of image$? from Lab to sRGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11994 lab2rgb $illu rgb2srgb 11995 11996#@cli lab82srgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11997#@cli : Convert color representation of selected images from Lab8 to sRGB. 11998#@cli : Default value: 'illuminant=2'. 11999#@cli : $ (50,50;50,50^-3,3;-3,3^-3,-3;3,3) resize 400,400,1,3,3 lab2rgb 12000lab82srgb : skip "${1=,}" 12001 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12002 e[^-1] "Convert color representation of image$? from Lab8 to sRGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12003 lab82rgb $illu rgb2srgb 12004 12005#@cli lab2xyz : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12006#@cli : Convert color representation of selected images from Lab to XYZ. 12007#@cli : Default value: 'illuminant=2'. 12008lab2xyz : skip "${1=,}" 12009 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12010 e[^-1] "Convert color representation of image$? from Lab to XYZ, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12011 to_color 12012 f " 12013 begin( 12014 const epsilon = 216/24389; 12015 const kappa = 24389/27; 12016 D65 = [ 0.4124564, 0.3575761, 0.1804375, 12017 0.2126729, 0.7151522, 0.0721750, 12018 0.0193339, 0.1191920, 0.9503041 ]; 12019 D50 = [ 0.43603516, 0.38511658, 0.14305115, 12020 0.22248840, 0.71690369, 0.06060791, 12021 0.01391602, 0.09706116, 0.71392822 ]; 12022 E = [ 0.488718,0.3106803,0.2006017, 12023 0.1762044,0.8129847,0.0108109, 12024 0,0.0102048,0.9897952 ]; 12025 white = ("$illu"==2?E:"$illu"==1?D65:D50)*[ 1,1,1 ]; 12026 ); 12027 12028 fy = (i0 + 16)/116; 12029 fz = fy - i2/200; 12030 fx = i1/500 + fy; 12031 fx3 = fx^3; 12032 fz3 = fz^3; 12033 XYZ = [ fx3>epsilon?fx3:(116*fx - 16)/kappa, 12034 i0>kappa*epsilon?((i0+16)/116)^3:i0/kappa, 12035 fz3>epsilon?fz3:(116*fz - 16)/kappa ]; 12036 XYZ*=white" 12037 12038#@cli lab82rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12039#@cli : Convert color representation of selected images from Lab8 to RGB. 12040#@cli : Default value: 'illuminant=2'. 12041lab82rgb : skip "${1=,}" 12042 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12043 e[^-1] "Convert color representation of image$? from Lab8 to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12044 repeat $! 12045 sh[$>] 0 /. 2.55 rm. 12046 sh[$>] 1 /. 0.85 -. 127 rm. 12047 sh[$>] 2 /. 0.836 -. 149 rm. 12048 done lab2rgb $illu c 0,255 12049 12050#@cli lch2lab 12051#@cli : Convert color representation of selected images from Lch to Lab. 12052lch2lab : 12053 e[^-1] "Convert color representation of image$? from Lch to Lab." 12054 repeat $! l[$>] 12055 to_color s c polar2complex[1,2] a c 12056 endl done 12057 12058#@cli lch2rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12059#@cli : Convert color representation of selected images from Lch to RGB. 12060#@cli : Default value: 'illuminant=2'. 12061lch2rgb : skip "${1=,}" 12062 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12063 e[^-1] "Convert color representation of image$? from Lch to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12064 lch2lab lab2rgb $illu 12065 12066#@cli lch82rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12067#@cli : Convert color representation of selected images from Lch8 to RGB. 12068#@cli : Default value: 'illuminant=2'. 12069lch82rgb : skip "${1=,}" 12070 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12071 e[^-1] "Convert color representation of image$? from Lch8 to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12072 pi,facth={[pi,255/(2*pi)]} 12073 repeat $! 12074 sh[$>] 0 /. 2.55 rm. 12075 sh[$>] 1 /. 1.1086 rm. 12076 sh[$>] 2 /. $facth -. $pi rm. 12077 done lch2rgb $illu c 0,255 12078 12079#@cli luminance 12080#@cli : Compute luminance of selected sRGB images. 12081#@cli : $ image.jpg +luminance 12082#@cli : $$ 12083luminance : 12084 e[^-1] "Compute luminance of image$?." 12085 remove_opacity srgb2rgb 12086 repeat $! l[$>] 12087 if s==3 sh 0 sh[0] 1 sh[0] 2 *[1] 0.22248840 *[2] 0.71690369 *[3] 0.06060791 +[1-3] rm[1] 12088 elif s!=1 norm n 0,255 12089 fi endl done 12090 channels 0 rgb2srgb 12091 12092#@cli lightness 12093#@cli : Compute lightness of selected sRGB images. 12094#@cli : $ image.jpg +lightness 12095lightness : 12096 e[^-1] "Compute lightness of image$?." 12097 remove_opacity srgb2rgb 12098 if s==3 srgb2lab channels 0 * {255/100} elif s!=1 norm n 0,255 rgb2srgb fi 12099 12100#@cli lut_contrast : _nb_colors>1,_min_rgb_value 12101#@cli : Generate a RGB colormap where consecutive colors have high contrast. 12102#@cli : This function performs a specific score maximization to generate the result, so 12103#@cli : it may take some time when 'nb_colors' is high. 12104#@cli : Default values: 'nb_colors=256' and 'min_rgb_value=64'. 12105lut_contrast : check "isint(${1=256}) && $1>=1 && isnum(${2=48})" 12106 e[^-1] "Generate high-contrast RGB colormap with $1 colors and min RGB value $2." 12107 l[] 12108 12109 # Initialization by farthest point sampling of the RGB cube. 12110 64,64,64,1 eval "repeat (8,k, x = !!(k&1); y = !!(k&2); z = !!(k&4); i([x,y,z]*(w-1)) = 1)" 12111 N={is} 12112 e[] "" 12113 do 12114 +neq. 0 distance. 1 xyzM={[xM,yM,zM]} rm. 12115 col={round([$xyzM]*255/(w-1))} 12116 if max($col)>=$2 =. 1,$xyzM N+=1 else =. -1,$xyzM fi 12117 e[] "\r [ Init ] > Colors \#"$N 12118 while $N<$1 12119 >. 0 {is},1,1,3 12120 eval.. ">begin(k = 0); i>0?(I[#-1,k++] = round([ x,y,z ]*255/63))" 12121 k. 12122 12123 N0=5 # 5 first colors to be preserved. 12124 s x repeat $! 12125 if {$>,I==[0,0,0]} rv[$>,0] fi 12126 if {$>,I==[255,255,255]} rv[$>,1] fi 12127 if {$>,I==[255,0,0]} rv[$>,2] fi 12128 if {$>,I==[0,255,0]} rv[$>,3] fi 12129 if {$>,I==[0,0,255]} rv[$>,4] fi 12130 done a x 12131 12132 # Functional optimization. 12133 e[] "" 12134 +srgb2lab a c 12135 energy_max=${-_lut_contrast.} 12136 nb_attempts=1000 12137 do 12138 e[] "\r [ Optim ] > Score = "{_$energy_max}", Attempts = "$nb_attempts" " 12139 . eval " 12140 do( 12141 k0 = round(u("$N0",w-1)); 12142 k1 = round(u("$N0",w-1)), 12143 k0==k1); 12144 tmp = I[k0]; I[k0] = I[k1]; I[k1] = tmp" 12145 energy=${-_lut_contrast.} 12146 if $energy>$energy_max energy_max=$energy k. nb_attempts=1000 else rm. nb_attempts-=1 fi 12147 while $nb_attempts>0 12148 12149 channels 0,2 12150 endl 12151 12152_lut_contrast : 12153 100%,1,1,1,"> 12154 const N = 10; 12155 dist = 0; sumw = 0; 12156 RGB0 = (I[#0,x])[3,3]; 12157 kmin = max(x-N,0); 12158 kmax = min(x+N,w-1); 12159 for (k = kmin, k<=kmax, ++k, 12160 RGB = (I[#0,k])[3,3]; 12161 w = (1 + N - abs(k-x))^1.5; 12162 dist+= w*norm(RGB - RGB0); 12163 sumw+=w; 12164 ); 12165 dist/=sumw" 12166 u {is} rm. 12167 12168#@cli map_clut : [clut] | "clut_name" 12169#@cli : Map specified RGB color LUT to selected images. 12170#@cli : $ image.jpg uniform_distribution {2^6},3 mirror[-1] x +map_clut[0] [1] 12171map_clut : 12172 e[^-1] "Map color LUT $1 on image$?." 12173 if !$! return fi 12174 to_color 12175 if ${"is_image_arg $1"} pass$1 0 to_rgb. else clut "$1" fi 12176 l={round((w*h*d)^(1/3))} 12177 if w*h*d!=$l^3 error "Command '$0': Specified CLUT $1 has invalid dimensions "({w},{h},{d},{s}). fi 12178 r. $l,$l,$l,3,-1 12179 repeat $!-1 l[$>,-1] nm={0,n} split_opacity[0] /[0] {256/$l} 12180 +warp. [0],0,1,1 12181 rm[0] mv. 0 a[^-1] c nm[0] $nm 12182 endl done rm. 12183 12184#@cli mix_rgb : a11,a12,a13,a21,a22,a23,a31,a32,a33 12185#@cli : Apply 3x3 specified matrix to RGB colors of selected images. 12186#@cli : Default values: 'a11=1', 'a12=a13=a21=0', 'a22=1', 'a23=a31=a32=0' and 'a33=1'. 12187#@cli : $ image.jpg +mix_rgb 0,1,0,1,0,0,0,0,1 12188#@cli : $$ 12189mix_rgb : skip ${1=1},${2=0},${3=0},${4=0},${5=1},${6=0},${7=0},${8=0},${9=1} 12190 e[^-1] "Apply matrix [ $1 $2 $3 ; $4 $5 $6 ; $7 $8 $9 ] to RGB colors of image$?." 12191 to_color repeat $! sh[$>] 0,2 mix_channels. (${1-3};${4-6};${7-9}) rm. done 12192 12193#@cli oklab2rgb 12194#@cli : Convert color representation of selected images from OKlab to RGB. 12195#@cli : (see colorspace definition at: <https://bottosson.github.io/posts/oklab/> ). 12196#@cli : See also: ''rgb2oklab''. 12197oklab2rgb : 12198 e[^-1] "Convert color representation of image$? from Oklab to RGB." 12199 repeat $! l[$>] split_opacity to_rgb[0] 12200 f[0] " 12201 l = (i0 + 0.3963377774*i1 + 0.2158037573*i2)^3; 12202 m = (i0 - 0.1055613458*i1 - 0.0638541728*i2)^3; 12203 s = (i0 - 0.0894841775*i1 - 1.2914855480*i2)^3; 12204 [ 4.0767245293*l - 3.3072168827*m + 0.2307590544*s, 12205 -1.2681437731*l + 2.6093323231*m - 0.3411344290*s, 12206 -0.0041119885*l - 0.7034763098*m + 1.7068625689*s ]" 12207 * 255 12208 a c endl done 12209 12210#@cli palette : palette_name | palette_number 12211#@cli : Input specified color palette at the end of the image list. 12212#@cli : 'palette_name' can be { default | hsv | lines | hot | cool | jet | flag | cube | rainbow | \ 12213# parula | spring | summer | autumn | winter | bone | copper | pink | vga | \ 12214# algae | amp | balance | curl | deep | delta | dense | diff | gray | haline | ice | \ 12215# matter | oxy | phase | rain | solar | speed | tarn | tempo | thermal | topo | turbid | aurora | hocuspocus | srb2 | \ 12216# uzebox | amiga7800 | amiga7800mess | fornaxvoid1 } 12217#@cli : $ palette hsv 12218+palette : 12219 names=${-_palette_names} N={narg($names)} 12220 l[] if isint("$1") name=${"arg 1+($1%"$N"),"$names} else name="$1" fi onfail name="$1" endl 12221 e[^-1] "Input color palette '"$name"'." 12222 _palette_$name 12223 nm. $name 12224 12225_palette_names : 12226 u default,hsv,lines,hot,cool,jet,flag,cube,rainbow,\ 12227 parula,spring,summer,autumn,winter,bone,copper,pink,vga,\ 12228 algae,amp,balance,curl,deep,delta,dense,diff,gray,haline,ice,\ 12229 matter,oxy,phase,rain,solar,speed,tarn,tempo,thermal,topo,turbid,aurora,hocuspocus,srb2,uzebox,\ 12230 amiga7800,amiga7800mess,fornaxvoid1 12231 12232_palette2code : # Convert a set of input palettes 12233 sort_list +,n 12234 repeat $! l[$>] 12235 r {whd},1,1,100%,-1 12236 img2base64 0,0 12237 e[] "_palette_"{n}" : " 12238 b64=\"${}\" 12239 l[] ('$b64') s x,-119 ('\\\\\n') a[0--3] .,x rm. a x b64={t} rm endl # No more than 120 char / lines 12240 e[] " base642img \\\n"$b64"\n" 12241 endl done 12242 12243# The color palettes below comes from the CImg library 'http://cimg.eu/'. 12244_palette_default : 12245 256,1,1,3,[16+32*int(x>>5),16+32*int((x>>2)&7),32+64*int(x&3)] 12246 12247_palette_hsv : 12248 256,1,1,3,[x*359/(w-1),1,1] hsv2rgb. round. 12249 12250_palette_lines : 12251 base642img \ 12252"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2MTcKeJwNkhGgu1AYxT8YDP4QDB4Eg+BKEATBYBAEQXDhQhAMHgweBBeuXB\ 12253gMgmAwCIIgCIJBEAQPguBKEASDwWDwYDD4/tGx75zf+Q4gAuhCPFVzM0CgvUXFmr0plIpkB2KwW4bppr16aMgRzge16wbwTbxW0L6Y0IxsjiFyZyQvAISoD\ 12254PFMYgWlnTUI/M4bsllO+I5M0GuoWm+LP6kImrtktjhu8sxjaJ9V6zwNDy0FijoRcloRzGvghbDTAiO+Z8/Hv9JoKRbRr79JjwXqpOfBGxRasEejCH2kHyhr\ 12255uCHk2jXJ5xkgGFdjPgp/4IZ4HDTk4LTjXrAED56dzkIskRGG8Gwh9FdqTh8bkMgp0+JG9tb+xXpLf58ugHG/GoPG6ZmnSGh+Bn1OyCkX23dUAjon753DhyT\ 12256JuhiCaxcy8acf79DuuwbQNo/NItIqXXWF491E8R0ECNOppKlesjlaK8wsIqpKwL3QJwnhCygGtbCWbgbvJ0W4GFMOSrgnpIQ9rZHDYMyVS261dE1U1B/hkU\ 12257InqiU/44MDQ/m4BMtHV9Wq5bgqjtJ6laFWKUDtOwsRFvaMLvSAZbHj+u9o/u0itAN5xHX85KSu4GblHN0BJgEHfPGtksZjK4JkzFY1AvkIMTEJBX7tO4HCF\ 122586Hov85VvUXaEWosOIqirYUDkWW/OH7FGP18B9h0jjs49tyukEYSKYiZTjCmPnkxI7neAWkOOTxrs4A3blzFEhvJsgMXqmsicxgRGMFil7o5wS3HuIZmAGcc\ 12259g8wvlM8UfPWXpfJN5JTPj+YlnxB6QD6tvGmdD9oUxoBrWc3mf8h5fjM=" 12260 12261_palette_flag : 12262 base642img \ 12263"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICMyNAp4nPv/n4Hh/wjGDCMeD4JIGEAMAH3RPtA=" 12264 12265_palette_cube : 12266 base642img \ 12267"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjMxIDEgMSAzICMzMzgKeJxj5BCQkFfXN7Nz8wuLS80trWnpmTJn8erNuw6dunTr0cuPP39/e/f83v\ 12268Xzxw/s2LBy4cyJnY1VRVnJ0cHezjYmOqqyoryszFxCUoqahhaOHgER8en55XVtfdPmLV27dc+RM1fuPH79+ffvL2+e3Ll69ui+beuWz5ve395QUZCRGBHo6\ 12269WhlpKUsLczNwsIjIqOsbWzt7BUUlZhZWNnYMWHGguXrt+87fu7avadvv/759enVo1uXTx/es2XNkjlTe1vryvLS4sL83e0tDDQUJQQ5Wdj4xGRVdU1tXX1C\ 12270YpKzi6ubuybNWrhy486DJy/cePD8/fd/DIQAE6eghKKGgYW9u39YXFpeWV1r79Q5S9Zs2XP49OVbj159+vWf9oCQN5kI+oIOgIVbWFpZy8jK0TMwIjGjoKK\ 12271hvX/6vOXrtu07evbqnSdvvvymQ0ABAC/raR8=" r. 256,1,1,3,3 round. 12272 12273_palette_rainbow : 12274 base642img \ 12275"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjI1IDEgMSAzICM1NjcKeJxj5ublE+DnF5KQUVBWU9fS0tHV0dXVAVL6RiZm5haWFpaWVpZWVtbW1i\ 12276BsbWMDJq3BwMrK0sLMWF9LRYqLkYGRAQygFAYbG2DkVrH2iUjNq2zpnTp3+eadB09fvvXo+dvPP/7+//v375/fv37++PH9+7dvX799/fr1GwQAWV+/ACEUA\ 12277Bmf3796+uDW1XMnD+3dum75wpkTOhvK81Ii/Z3NDbSUxNhZuPkEhISFhMWl5RRV1LV09AyMjE1MLWwcnJxd3T29vH18/fz9AwIDg4JDQCA0DAjCI0BkRGRk\ 12278dExsQnJaZm5ReW1T54Tp85au3rBp8+ZNmzZt3Lhxw4YN69euXbd2zWpMABTfsHHTpq3bd+7ae+Dg4eMnTp+9cPnC2RNHDuzatnH10gWzJvW01JUXZCbHhvt\ 122795OttbW5gYGepDgJ6enq6OjpaWpoa6mqqKorysnJy8goKCopKSopKigrycrLSkuIggHy+/kJCQAB8PFzOHiIyKnqm9R0BYbHJmXmlVY2tn38SpM2bPmTd/wc\ 12280JFi5csWbZ82dJly5avWLFiJRCsAoPVYGL1GqBDN27eugPoyqMnz1+/++gxMCRPH9mzdd3KhbOn9rU3VBZmxEcEByGD4BAwPzgoMDAgwM/P19vT093d1dnJ3\ 12281trK3NhIX0dDTVUJ5GCgi5VVVIFpSkdXT9/A0AAGQH7U1dXW1gJ5UA2E1NTUNdQ1NDTU1dXUVJQU5WQkxYT4efkFhIQE+Xm5mAHNkQH/" 12282 r. 256,1,1,3,3 round. 12283 12284# The color palettes below have been converted from 12285# 'https://stackoverflow.com/questions/33273340/matlab-set-color-map-color-range'. 12286_palette_parula : 12287 base642img \ 12288"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNjQgMSAxIDMgIzIwMwp4nAHAAD//NTY2NDAoHAwDAwUJDhETFBQSEAwJBwYGBggLEBYdJS44Qk1ZZX\ 12289F7hpGbpK22v8fP2N/n7/b8//79+/j29fX2+C0zOT9FTVZeZGlucnZ6foKGio+UmZ2hpKeprK6xs7W3ubu8vb6/v7+/v76+vby8u7q5ubm7vsLHzNLX3OLp8\ 12290PiMmKWyvsvX3uHh4N7c2tjW1NPS0tHPzcrGwr65tK+ppJ6Yko2HgXx4dHBsaGVhXlpXU09LRj85NDAsKCMfGhUQJK9mpg==" r. 256,1,1,3,3 round. 12291 12292_palette_jet : 12293 base642img \ 12294"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNzYgMSAxIDMgIzEzMQp4nGNgwA24JFSN7H2i0ksa+2av3Hb4wr3XP/9jgt/vH145tnPN/ImtMH1MvN\ 12295Iapk7+sVnlLRPnrdl57PLDd7+xaPz55t7Fw9tWzulrKkmP8rU3UpXgYoTbPWXh+j0nrz35+BeLxm8vb587sHnZzO76wpRwLxt9JVF2PL5gYAAAc+1twA==" 12296 r. 256,1,1,3,3 round. 12297 12298_palette_hot : 12299 base642img \ 12300"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTI0IDEgMSAzICMxNDEKeJzjFRKXVdLQNTK3dXb3DY6IS87IK66oa+nsmzJz3pKV67fu2n/k1IWrt+\ 123014/ff3+66//1AUMpABGdl5BcRlFdZBTndx9g0BOzS2urGvuADl18cr1W3buP3LyPMipr4BO/UdNu0kEjFxC0kpaRtbO3kHRydnFNS3dk2cvXr1lz5EzV+88e\ 12302fP1LwA796yq" r. 256,1,1,3,3 round. 12303 12304_palette_cool : 12305 base642img \ 12306"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMzIgMSAxIDMgIzc4CnicY+ERkVHRMbFx8QmJSckpqWnpmTJnyZote46cuXLnyZsvf/58efPkzpUzR/\ 12307ZsWbNkzpSelpqSnJSYEB8XGxMdFRkRHpb/BAAAHuY/4Q==" r. 256,1,1,3,3 round. 12308 12309_palette_spring : 12310 base642img \ 12311"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjggMSAxIDMgIzcxCnic+/8fN2DhFVPQNLJ28Q1LyCyqbumdtmDlpt1Hzl578PLT79+fXj64dvbI7k\ 123120rF0zrbakuykwI83WxNtJUEONlAQDKiDfN" r. 256,1,1,3,3 round. 12313 12314_palette_summer : 12315 base642img \ 12316"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjggMSAxIDMgIzcxCnicY+EVU9A0snbxDUvILKpu6Z22YOWm3UfOXnvw8tPvprbuCVNmzl20bPX6LT\ 12317v2Hjx26vyVm3cfPXv94cvPv2l4AACR+i4M" r. 256,1,1,3,3 round. 12318 12319_palette_autumn : 12320 base642img \ 12321"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjYgMSAxIDMgIzQyCnic+/8fF2Dhk1DSMXPwDI5NL6xu6ZuxaM22Aycv333+8TcDTgAAaHcm2w==" 12322 r. 256,1,1,3,3 round. 12323 12324_palette_winter : 12325 base642img \ 12326"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMzEgMSAxIDMgIzc5CnicY2DAC1h4RGRUdU1t3fzC4tLzyxs6JsxYuHLjzkOnLt16/Prz778/v358+/\ 12327Lpwzs3rlw4ffzw/t3bN69bvXzxvFnTJvV1tTUBACEGJp4=" r. 256,1,1,3,3 round. 12328 12329_palette_bone : 12330 base642img \ 12331"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KOTkgMSAxIDMgIzI1Mgp4nGNkZuXg4uETFBaVkJKRU1BWVdfU0TMwNjG3tLZzcHJx9/T28w8KCY+Mjk\ 12332tISk3PzM4rKCwpq6iqbWhqaevs7p0wccq0GbPnzl+4ZNnKtRu3bN+9/9Cxk2cuXLl+696jpy/ffPj8/dc/RmKsCI2IiU9KzcjJLyqtqK5rbGnv6ps4Zfqsu\ 12333QsWAw3esHnbzr37Dx09cfrM+YtXrt24fef+w8fPnr968+7j56/ff/35x8TKwcMvJCopLa+koq6lZ2hibmXnCDTZNyA4PDI2ITktE2hwSVlldV1DU2t7Z3cf\ 123342N2zwO5esXrtho1btu3YvXf/wSPHcFoBAJTokrQ=" r. 256,1,1,3,3 round. 12335 12336_palette_copper : 12337 base642img \ 12338"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTE1IDEgMSAzICMzMzkKeJxj4+TmExQWk5SWU1RW09TRNzKxsLK1d3b18PINCA6NiI5LSE7LyM4rKC\ 123396rqK5rbGnv7O2fNGX6rLnzFy1dvmrthk1bd+zee+DQ0ROnz164fO3mnXsPnzx7+eb9xy/ff/359x87YGFl5+Dm5RMQFBYVk5CSlpVXVFZRU9fU1tEzMDIxN\ 12340be0trG1d3R2dfP08vH1DwwKCY2Iio6NT0hKTk3PyMrJKygsLi2rqKyurW9sam1r7+zu7eufOGXa9Jmz5sybv3DxkmUrVq1Zu37Dpi1bt+/avXffgUOHjx5j\ 12341YgZZysnFzcPLxy8oJCwiIiYuISklLSMrp6CopKyiqqauoakFdIG+gaGRsYmpmbmFpZWNrZ29g6OTs4ubu4ent4+vn39AYFBwaFh4RGRUdExsXHxCYnJKalp\ 123426RmZWdm5uXn5BUXFJaVl5RWVVTW1dPQCk5ZAs" r. 256,1,1,3,3 round. 12343 12344_palette_pink : 12345 base642img \ 12346"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTIxIDEgMSAzICMzMDUKeJxT1DG1cfbwC46ISUzNzC0sraiub2rr7O6bOGX6zDnzFy5ZtnL1ug2bt2\ 123477fuXvvgUOHDx85euz4iZOnTp85e+7c+QsXL12+cuXqtes3bt66ffvO3Xv37j94+PDR4ydPnj57/uLFy1evX799++79hw8fP33+8uXr12/ff/z49ev37z9//\ 12348/37zyoso6SurW9sZmVr7+Tq7uXjHxQSFh4ZHRuflJyanpGVnZtfWFRSWl5RWV1b39Ta0d0PddLiZSvXIJx05NiJU2fOXbh89fqNW3fu3X/0BGgzFS1uaGxq\ 12349aW1r7+zu6e2bMHHS5CnTps+YOWv2nHnzFy5avGTpsuUrVq5avWbtuvUbNm4COmn3vgOHj504fRbonhu3795/+OTZi1dv33/68u3Hrz//AH2168E=" 12350 r. 256,1,1,3,3 round. 12351 12352_palette_vga : 12353 base642img \ 12354"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICMxNzgKeJz7/+fn10/vXz9/8uDOjasXzpw4sv/IiTMXrt648+DJ89fvP339+ec/Bv\ 12355jx8dXj25dOHdi2ZsGU1tIEVwbCwDWhtHXKgjXbDpy6dPvxq48/MM2Q0zF3cPcLiYpPycgtLK2saSAMaipLC3MzUuKjQvzcHcx15IhwB4Yt/zH8v2vr+pWL5\ 1235607r72goz00KdTPEdDthQEYIYbgMw3c0CSEi/E9G7JIRQoT9T0YYEgYAJsphWQ==" 12357 12358# The color palettes below have been converted from 'https://matplotlib.org/cmocean/'. 12359_palette_algae : 12360 base642img \ 12361"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNTAgMSAxIDMgIzE2MQp4nAGWAGn/1M3Hwbq0raegmZKLhH11bWVcU0k+MygeFg8JBwYICg0PEhQVFx\ 12362gZGRkZGRkYFxYVExL38u7p5ODc19PPy8fEwLy4tbGtqqainpqWko2JhH96dnFtaGRfW1ZRTUlEQDw3My4qJczFvbavqKGak42GgHp0bmhjX1pXVFJRUFBPT\ 12363k1MS0lIRkRCPz07ODUyLywpJiMgHBkV1p88Lw==" r. 256,1,1,3,3 round. 12364 12365_palette_amp : 12366 base642img \ 12367"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNjEgMSAxIDMgIzE5NAp4nAG3AEj/8O3r6ejm5OLh397c29nY1tXU0tHPzszLycjGxMPBv728uri1s7\ 12368CtqqainpqVkIuFgHp0b2lkXlhTTkhDPurm4dzX0s3Iw765tLCrpqGcmJOOiYSAe3ZxbGdiXVhTTklDPTgyLSgjHhkWEhAODg0ODg4ODg4NDQwLCgnq5N7Y0\ 12369szGwLq0rqihnJWPiYN9eHJsZmBbVU9KRUA7NjIuKygmJCQkJCUmJicoKSkpKCcmJSMhHxwaGBUS64BWpQ==" r. 256,1,1,3,3 round. 12370 12371_palette_balance : 12372 base642img \ 12373"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTIxIDEgMSAzICMzNzQKeJwBawGU/hgaHB4gIiMlJigoKSkoJyQgGhMNCgoMERYcIictMzg+Q0lOVV\ 12374thaG51fIKJkJado6mwtrzDyc7V2+Dm7PDu7Oro5+Xj4t/e3dva2NfW1NLR0M7Ny8rIxsXDwcC+vLq4tbOwraqno56alZCLhYB6dG9pY15YU01IQj0dICImK\ 12375CsuMDM2OTs/QUVJTFFVW19kaGxxdHh8gISHi46SlZmcoKOmqqyvs7a5vL/CxcnMz9PW2t3h5ens6OPe2dTPysXAu7axraijnpmVkIuGgXx3cm1pY15ZVE9K\ 12376RD45My4oIx8aFhMQDw4NDg4ODg4ODQ0MCwoJREpRWF5lbHN7goqSmqGpsLa7vb69vby8u7u6urm5ubm5ubq6uru8vL2+v8HDxcbIys3P0dXX2t3f4ubp6+f\ 12377h2tXPyMK9trCqpJ6YkYuGf3l0bWhiXFZQS0ZBPDczLisoJiQkJCQlJSYnKCkpKSgnJiQiIR4cGhcVEqaTs4c=" r. 256,1,1,3,3 round. 12378 12379_palette_curl : 12380 base642img \ 12381"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTI0IDEgMSAzICMzODEKeJwTFROXkJCUkpKWlpaRARJSkuJiosJCggKCwmLSCup6Znbu/uHx6fnldW\ 1238229U2YtXLF+6+6DJ85duXn/6euP3/78+fn96+eP79++efXy+bOnjx89uH/3zu2b169duXT+7KkTRw/u271984Y1K5YsmDN9Ul9nS31VaUF2anxUqL+Xi72Vq\ 12383ZySmpaekZmVraOrp29gSERMQnJGTkFxeXV9U3tX38SpM2bPW7h0xaq1GzZv27F738Ejx0+dvXDl+q27D5+8ePPhy+d3r57cv3X1wumjB/ds37hm+UKgHb0d\ 12384TbUVxXmZKQnR4UF+Xq6OtlZmxvraGqpKCrJgn4kIg/wmwMfr4ubh7esfFBIWGR2bkJSSnpWTV1BUXFpeUVVdU1tXV9/Q2NTc2tbR1Tth8rRZcxcuXbVu846\ 123859h0+cvQz2+cfXT+5eO3/i4O4ta5cvnD21v6u1obq8uCA3KyMtJTkpMSEhIT4+PgEG4uPjYqMjw0OD/L09nO2tzACwu7nF" r. 256,1,1,3,3 round. 12386 12387_palette_deep : 12388 base642img \ 12389"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNDkgMSAxIDMgIzE1OAp4nAGTAGz/+e7j2M7Dt6yhlYqAdm5mYVxYVVJPTUtKSEZEQ0FAPz49PT0+P0\ 12390BBQT8+Ozk2MzAsKfv38/Ds6OXh3dnV0czIw764s66po56Yk46Ig396dG9qZF5ZU05IQz46NjIvKycjHxvJw724s6+rqKWko6Kjo6Ojo6OjoqKhoJ+dnJuam\ 12391ZeWlZSTkY+Mh4B4b2ZeVU1FPTYvM2JJnA==" r. 256,1,1,3,3 round. 12392 12393_palette_delta : 12394 base642img \ 12395"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM3NzAKeJwTEBIWEROXkJSWkZWTV1BUUlZRVVUDAlVlJUV5OVlZGWlpKRCQlp\ 12396aWASmBqFFT19DU0tHVNzA0NjWzsLKxc3Bycff08Q8Ki4xNSMnIKSipqGlo6ejpnzx91rxFS1euWb952869Bw4fP3X2wuVrN+8+ePzs5Zv3n7/9/Pvv7+9fP\ 1239779/+/r508f37968fvXi2dPHjx7cu3PrxrUrl86fPX3i6OEDe3dt37Jx3arlSxbMnTVtcn9PR2tjXVV5cUFORmpibFRYkL+3u4uDraWZkb62hqqSvIykuIiQ\ 12398AB8vDzcXFzc3Dw8vH7+AINCbIqJiYuLiEhISkmAAZIiLi8srKCmrqqlramnr6ukbGBmbmJpbWFqDPeTm4e3rHxgcFhEVE5eQlJKWkZWTV1BUUlZRWV1b39j\ 12399c2t7Z3ds3YdKUaTNmzZk7f+HipctXrFqzdv3GTVu2bt+xc/eeffsPHjpy9NiJk6fPnLtw8fKVa9dv3r5z78Gjx0+fv3z99t2HT1++/fj15+f3L58+vH398t\ 12400mTR/fv3r55/eqlC+fOnDp5/Ojhgwf27dm9c8e2rZs3bVy/bu2aVStXLF+2ZPGihQvmzZ0ze+aM6dOmTp40sb+vt7urs72tpbmxoa62uqqirLS4sCAvJyszP\ 12401TU5MT4uJioiLCQowM/H29Pd1dnR3tba0tzUxMhAT0dLQ01F2d7JFRJvMQnJ6dl5RWVVtY2tnb0TgL6aOWv27Dlz5gLBvHnz5s+fv2DBgoULFy5atHjxkiVL\ 12402ly5dtmz58hUrVq5ctWr16jVr1q5dt27d+vUbNmzYuHHT5s1btm4DhsEuUCAcOHj4yNHjJ04BQ+H8xUtXrl6/cQsYDPcfPHz0+MnTp6ePH96/e9umdSuXLpw\ 12403zY0p/d3tTXVVpYW5GSkJ0eDAwYp3trS1MDHS11JUVZKUlRIUF+Hi4ONjZWIGAjZ2Dk5uHj18QlIIlpYCpE5J+gYkTmDq1tLV14EBbW1tLS1NDQ11NVQWYsB\ 12404Xk5WSkpSTERUWEAGwPYP8=" 12405 12406_palette_dense : 12407 base642img \ 12408"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNzQgMSAxIDMgIzIyNAp4nHt878alM8cO7N66YfXSBbOnT+rram9uqKmqKCstKQaBktLSsvLyioqKys\ 12409pKIFleDpIoLMjLyc5MS0mKj4kMC/L38XBxsDF//+bV8ycP792+ce3ShTMnjx3ev3fXts3r16xYsmDOjCkTejpaGmoqivOz05Pjo8NDAnw8XB3trMyNDfW0N\ 12410FSVFGSlJcXFRISFhQQF+Pnev3398sWzp0+ePH4EA48fP34CBo8fP3p4/+7tm9euXDh78tihfbu2bly7YvG8mVP6u1rqK0vyMpJjwwN93BxtzI30NFUBgy55\ 12411hg==" r. 256,1,1,3,3 round. 12412 12413_palette_diff : 12414 base642img \ 12415"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTQzIDEgMSAzICM0NDAKeJwBrQFS/gcJCw0ODxESFBYWGBseIiYqLjI2Oj5CRUlNUVRYXF9jZmtvcn\ 12416Z5fYCEiYyQk5ebn6Onq66yt7q/wsfLz9PX3N/k5+vu8fP19fX08e/s6ebi39zZ1dLOy8jEwr67uLWyr6yppqOgnZqYlZKPjIqHhIF+fHl2c3Bua2hkYF1ZV\ 12417lJPS0hFQT47NzQwLSomIyAdIyYpLC8zNTk7P0JFSEtNUFNVWFteYGNmaGtucHN2eXx+gYSHioyPkpWYm56hpKeqrbC0trq+wMTHy8/R1djc3+Pm6ezu8PHx\ 124188O/s6ufj4NzZ1dLOy8fDwLy5trKvq6mlop+bmJWSj4yJhoOAfXp3dHFubGhmY2BeW1hWU1FOTEpHRUI/PTs4NTIwLSooJSJAQ0dKTlFUWFteYWRmaGpsbnB\ 12419yc3V4enx9gIKEhoiKjY+Rk5aYmpyfoaSnqauusLO2uLu+wcTGyszP0tXY29/i5efq7O7v8PDv7Onm4t3Z1dDLxsK9ubSvq6einZqVkY2IhIB8d3Nva2djX1\ 12420tXU09LR0RAOzg0MS0qJyQiISAeHRsbGRgWFRQSEA4ODAoIBjEs26k=" r. 256,1,1,3,3 round. 12421 12422_palette_gray : 12423 256,1,1,1,x r. 100%,1,1,3 12424 12425_palette_haline : 12426 base642img \ 12427"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNDYgMSAxIDMgIzE0OQp4nAGKAHX/KiwuLSgiGxQPDAwPEhcbICUpLTA0Nzo8QEJGSU5TWF9mb3mEkJ\ 124286sucXR2+bw+RgaHB8mMDlBSE9VW19laW5zeHyBhouQlZqfpKmus7i9wsbLztLV2Nrd4OPm6e1xfoyZoaKfnJiVkpCOjIuKiYmIiIiHh4aFhIOBfnt4dHBrZ\ 124292JeW1xgZW12gIqU7TdADQ==" r. 256,1,1,3,3 round. 12430 12431_palette_ice : 12432 base642img \ 12433"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTA5IDEgMSAzICMzMzgKeJwBRwG4/gQGBwoMDhETFRgaHB4gIiQmKCorLS8wMjQ1Nzg5Ojs8PD0+Pj\ 124344+Pj4+Pj4+Pj4+Pj4+Pz9AQUJDREVGSEpLTE9QUlRWWFpcXmFjZWhqbXBzdnl8f4OGio6Slpqfo6essLS5vsLGy8/T2Nzg5OkGCAkMDhASFBYYGRwdHyEjJ\ 12435CYoKSwtLzEzNDc4Ojw+QEJER0lLTlBSVVhaXWBiZWdqbW9ydXd6fX+ChIaJjI6Rk5WYmp2goqSnqayvsbS2uLu9v8LEx8rLzdDS1NfZ293f4eTm6evt8PL0\ 124369/n7ExYaHSAkJyouMTU5PEBDR0pOUlZZXWFlaW1xdHh8gISIjI+Tlpmcn6KkpqiqrK6vsLKztLW2t7i5urq7vL2+v8DAwcLDxMXGx8jJysvMzc3P0NDS09P\ 12437V1tfY2dvc3t/h4+Xn6evt7/L09fj6/ETzn2w=" r. 256,1,1,3,3 round. 12438 12439_palette_matter : 12440 base642img \ 12441"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNjQgMSAxIDMgIzIwMwp4nAHAAD///fz8+/v6+vn4+Pf29fTz8vHw7+3s6ujn5eLg3drX1NDNycXAvL\ 12442ezrqmkn5qVkIqFgHt1cGplYFpVUEpFQDs2Mevl4NrUz8nEvrmzrqijnZiSjYiCfXdybGdiXVhTTkpGQj46NzMwLSsoJiQiIB8dHBsaGhkYGBcXFhYVFBMSE\ 12443Q+uqKOemJOPioWBfHh0cGxpZWJfXFpYVlRTUlJSU1NUVVdYWVtcXV5fYGFiYmNjY2NiYWBfXVxaV1VST0xJRkM/PV5d6A==" r. 256,1,1,3,3 round. 12444 12445_palette_oxy : 12446 base642img \ 12447"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2NTYKeJyzd3RydnP39PL18w8MDg2LiIqJjUtMSknNyMzOyS8oKi4rr6iqqa\ 12448tvaG5pbevo7Oru6e0LDAgMDA4JCQ0Pj4iMigaqj09ISEpOTklLS8/IzMrOyc3LLygsKi4uLSsvr6yqrq6tq2tobGoCGgAzoX/CxEmTp0ydNn3mzFmz586bP\ 124493/hosVLli5bvmLV6jVr163fsHHzlq3btu/YuXvP3n0HDh46dOToseMnT50+c+78hYuXr1y9duPmrdt3791/8Ojxk6fPX7x89ebt+w+fPn/5/u3L54/v3719\ 12450/frVq1cvIeAFEDx//vzZs2dPnz558uTx40ePHj18+ODB/fv37t29e+cOKxCwQQE7DED5rGDAwgJSws7Bxc3HLygkKibh6x8QGBQcEhoWHhERFR0dEwcMgMS\ 12451k5JTUtPT0zKys7Ny8vPxCYACUAgOgAhgANbV1DcAAaAGFIDAAenp7+4D+nwTy/wyg/+cAAwDo/8Vg/wMDAOT/TZu3QP2/dz8wAAj7/937T5+//vv75/fPH6\ 12452BQ+PTh3ZvXL58/ffLowb27d25ev3b10sXz586cOnni6JFDB/fv3bN7x/ZtWzdt3LAO4n92dg4OTk4uLi5ubh4eHl4g4AMCfhAAMYB8Hm5uLk5OTg4OdnZvs\ 12453P+DQ8LC4AkgPjEpKTk1FSUBFJWUlpVVVFZW1dTW1jc0NgJTUGt7R2cnSgIABsCcuXPnLYAmgJXAAAAlgE2bNoMSwK7de/bsAwbAYWAAnAAGwNlz585fvHT5\ 12454yrXrN27evnP3HigAngED4DUwAD58fJSRlpIYExUe4uft4epgZ2NlYWZqYmRooK+ro6OtqamhrqaqqqKspKSoIC8vJysrIyMlJSkJADQjlG8=" 12455 12456_palette_phase : 12457 base642img \ 12458"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTA2IDEgMSAzICMzMjkKeJwBPgHB/qissLO2uby/wsTHyczO0dPU1tjZ29zd3d7e3t7d3NvZ19XSz8\ 12459zJxcG9ubWxrKeinpiTjYeBe3VuaGFbVE1HQTs1MCsnIyEeHBkXFRMRDw0MCwsOEhgeJS01PkdQWWJqcXh/hIqPlJidoqZ2dHJwbmtoZWNhXVtYVVJPTElFQ\ 12460j47NzQwLSsoJiUlJicpLC8zNjo/Q0dLT1NXW19iZmltcHN2eXx+gYOGiIqLjY6PkJGSk5OUlZWWlpeXmJiZmZmampmZmZiXlpSSkI6MioiGhIF/fXp4DhIX\ 12461Gx4iJiouMjY6PkNHTFFXXGJobnV8g4qSmaGor7e+xMvQ1tvf4+fq7O/w8vPz9PPz8vHv7ero5eHd2dTPysbBu7axrKejnpqVkIyHgnx3cWtlXlhRSUI5Mio\ 12462jHRcTEA8ODQ0NDQ0NDPDwmdk=" r. 256,1,1,3,3 round. 12463 12464_palette_rain : 12465 base642img \ 12466"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTE1IDEgMSAzICMzNDIKeJx7++bVy2dPHz96eP/e3Tu3b928cf3q5Yvnz5w8dmjf7u2b169evmTBnB\ 12467lTJvZ2tjbWVpYU5makxEeHBfq4O9taGOtpqirIiIsI8nJxsLGyMDMzs7CwcXBy8woIiYhJSEnLyikoKCopq6ioqIIAkFZRVlZSUnzz6vnTRw/u3bl57cqlC\ 124682dPnzh25NCBfXt37dyxfduWzZs2rl+3ds2qlSuWL12yeOGC+fPmzJ41Y/q0qZMnTZzQ19Pd1dHW0txYX1tdWVFaXJifm52ZnpqcGB8bFREWEhTg5+Pl7urs\ 12469aG9rbWluYmSgr6OloaaiKC8r/fHdq+ePH9y9efXimZNHDgA9tm7V0oVzZ06bPLG/p6sTZGZTQ31dbU1VZUV5aWlJcVFhQX5+Xl4uDORBAYidk5OTnZWVmZm\ 12470enpaanJSYEBcTHRkRGgy23RNovZMD0H4rSwDxo6Ac" r. 256,1,1,3,3 round. 12471 12472_palette_solar : 12473 base642img \ 12474"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMzUgMSAxIDMgIzExNgp4nAFpAJb/N0BJUltkbXZ/h46VnKGnrLG1ur7BxcjMztHU1tja3N3f3+AVGB\ 12475odHyIlJysvNDpARk5VXGRrc3uDi5OcpK22v8jR2+Xu+RkcHyEjJCQkIiAeHBoYFhQTExITFBUXGh0gJCgsMDU6PkNIm9UqlA==" 12476 r. 256,1,1,3,3 round. 12477 12478_palette_speed : 12479 base642img \ 12480"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNDkgMSAxIDMgIzE1OAp4nAGTAGz//fn28+/r5+Pf2tXOyMG5samgl46FfHJpYFZNQzoxKCAZEg4LCg\ 12481wOEBMVFxgZGRkYF/rz7efh29bQy8bCvbm1sq6rqKWinpuYlZKOi4eDf3t3c25pZWBbVlFMSEI9ODMvKSTIvbKnnJCFeW5jWE1COS8nHxgRDAcFBQgLDxQYG\ 12482x8iJScpKywsLCwrKiknJCIfGxgUF7w7kA==" r. 256,1,1,3,3 round. 12483 12484_palette_tarn : 12485 base642img \ 12486"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTA1IDEgMSAzICMzMjYKeJwBOwHE/hcaHiEjJyktMDU8Q0lQV11kanF4f4aNk5uiqbG4v8XKzc/S1N\ 12487bY2t3f4uPm6evu8PT2+vv8+/j08Ovn4tzWzsa+t6+ooJmSioR9dm5nX1dPRz84MSolIh8eHRwaGRcUExAOCwoICQsODyQoLTE1OT5CRklMT1JVWFpdYGNlZ\ 124882psb3F0dnl7fYCEiY6Ump+lq7C2vMHHzdLY3uTq7/T39vPu6eTf2tXRzcrGwr66trOvq6ekoJyZlpKOi4eDf3t3cm5qZGFcV1NOSkVBPTgzLikkIA0ODw8Q\ 12489Dw8ODQwNEBETFhgbHR8hIyUnKisuMTQ3O0FIUlpia3N8hI2Vnqavt8DJ0dri6/H18uzj29HJwLewq6ikop+dm5mXlJKPjYuJh4WEgoF/fnx7enh2c3JvbWt\ 12490paGZkYmFfXVpVUfhNmgM=" r. 256,1,1,3,3 round. 12491 12492_palette_tempo : 12493 base642img \ 12494"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTEyIDEgMSAzICMzNDcKeJwBUAGv/v369/Tx7uvn5OHe29fU0c3Kx8PAvLm1sq+rp6OgnJiVkI2JhY\ 12495B9eHRwa2hjX1pVUUxIQz86NTEtKSUhHhsYFhMSEREQEBEREhMUFBUWFxcYGRkaGhsbGxscHBwcHBsbGxsbGhoaGRkZGBgXFxYWFRX08vDu7Oro5eTi4N7c2\ 12496tjW1dPRz87MysnHxcPCwL+9u7q4t7W0srGvrqyqqaempKKhn52cmpiWlZKQj42KiYeEgoB+fHp4dXNxb21raWZkYmBeXFpXVVNRT01LSEZFQ0A+PDo4NjQx\ 12497Ly4rKSclIiAe8+/s6eXi3tvY1dLOy8jFwr+9ure0sa+sqqelo6CenJqYlpSSkY+OjIuKiIeGhYSDg4KBgYGAgH9/fn5+fXx8e3t6eXh4d3Z1dHNycXBvbm1\ 12498samloZmVkY2FgX11cW1pYV1ZUU1JQT05MS0pIR0ZFRA7PoM4=" r. 256,1,1,3,3 round. 12499 12500_palette_thermal : 12501 base642img \ 12502"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTA3IDEgMSAzICMzMjUKeJxjYWFhZWVj5+Ti4RcUkZBRUNUyMLWyd/HwCQiJiI5PSsvMyS8qq6ypb2\ 12503rr7J0wefqseQuXrlizYfP2XfsOHj155vzla7fuPnj07MXrt+8/fv7y7fuPn79+/YaAX79+/vzx/dvXL58/fXz/7s2rF8qq6hpa2jp6+gaGRkbGYACkTMzML\ 12504aysbe0dnJxd3T28vH39/AODgkNCwyMio6JjY+MTEpOSU1LTMjKzcnLzC4pKyiqraxua2zp7JkyeNmveoqUr127cumPPgSMnzly4cuPOgycv3nz8+tPE0tbJ\ 125053ScwPCYpI6+0urGjb8qM2fPmz58/b+6c2bNmzpg2dcrkSRMn9Pf39fb2dHd1drS3tbY0NzXU11RXlpcWFeRlZ6QmJcREhgUH+nl7uLk6Odrb2dqAgK2tHdS\ 12506lQIcGBoeGRwIArFub1Q==" r. 256,1,1,3,3 round. 12507 12508_palette_topo : 12509 base642img \ 12510"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2OTEKeJxT19TS1tXTNzQyNjE1s7C0sraxtbWzt3dwcAQBBwcHe3s7OztbCA\ 12511Cy7MFyTk7Ozi6urm7u7h6enl7e3j6+fn7+AYFBwSGhYRGR0TFxCUkp6Zk5+UVllbWNrZ29E6fOmrd4+eoNW3bsPXj05LlL127de/Ts9fvP33/z8vELCAoJC\ 125124uIiolLSEpKScvIysopKCqpqGvpGhibWVrbOTq7eXr7BQaHRUbHJSSnZWTnFRSXVVTXNTS3dXT3TZg8bebseQuXLF+5Zv2mrTt27zt46PDRY8dPnDx1+szZ\ 12513c+cvXLp85eq16zdu3rp95979Bw8fPX767PmLV6/fvHv/8dPnr99/SEmDrFNWUVMHB4SBobGJmbmllY2tvaOzq5uHt69/YHBoRBTYR2mZ2bn5hcWl5ZXVtfW\ 12514NTS1tHV09fRMmTZk2Y9ac+QsXL12+cvXa9Rs3b92+c/fe/QcPHz1+8tSZcxcuXr567cZNkPVg21+8fP3m7fsPQMu//fj5+4+qmoaWDjD8jYGhD7HVxc3DC2\ 12515htQCAwMMMjIqNiYuPiE5OSU1LTMzKzcnLz8guLikvKyisqq2tq6xoam5pb29o7urp7+vonTJw0ZSrIMfMWLFoCdcy2Hbv27AO5BeSUy1ev37pz78Hjp89fv\ 12516Xn/8fO3H7/+6ugZmphb2tg7uXp4+wWFRkTHJ6UCI664rLKmvqm1vbO7F2zupMmTp0yZOnXatGnTp8+YMXPmzFmzZs+eM2fu3Lnz5s2fv2DBgoULFwHBYgwA\ 12517FVyyZOmy5StWrlq9dt0GRAgdO3EKGPHAmAdHvZS0tLQMMPqBCQAM5MHxoqEJS59m5uagBGptYwNLiSjADgIcXDx8/IPDomITUzKywQmwoaW9u2/S1JlzFix\ 12518evmrdxq079xw4fPzUuUtXb9558AQAVgJv5Q==" 12519 12520_palette_turbid : 12521 base642img \ 12522"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTI2IDEgMSAzICMzNzAKeJx78fzpk8ePHj64f+/undu3bt64fu3qlcuXLl28cP7c2TOnT506cfzY0S\ 12523OHDx08sH/f3j27d+7Yvm3L5k0b1q9ds2rl8mVLFi2YN2fWzOlTJ0/s7+3p6mhraWqoq6mqKC0uzM/NzkxPTU6Ii4kMDw0O9Pf19nR3dXa0t7W2NDc1NtTX1\ 12524dZUV1X+8unD29cvnz15dP/u7RvXrlw6f/b0yWNHDh3Yu3vn9q2bNqxbvXI5xI4Z06ZMmtAHsaKxvra6sqKsBGRJTlZmelpKcmJCXGxMVGREWGhIcGCAv5+P\ 12525t5enh7uri5Ojg72djbWVpYW5qYmxkaG+nq6OlqaGuqqKsqKC/KrlSxbOmz1j6qT+3s72lsa6msryksL8nCyguxPjY6IiQkOCAvx8vb083N1cXZyBZgENs7O\ 125261tbWxsbEGASsYsIQACyAwNzc3MzMzNTUxMQbaZ2hgoK8HtFNHW0sTaK2aqoqKshLQZjlZGWkAeF+paA==" 12527 r. 256,1,1,3,3 round. 12528 12529# The color palettes below comes from the LoSpec palette list 'https://lospec.com/palette-list'. 12530_palette_aurora : 12531 base642img \ 12532"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2ODYKeJxt0kFo01AYB/B3qYwwaDbCaEG6aS4T3ME4qJrgVpCiLUqolEgYbI\ 12533QirIce9kQLknXbZSplWaGMSaeUYWU0g21QD0XbFLaasimMQqmUOiyBHiyOemgZZfpMql7Ew/v43vtOv+//QN/5yze89x89eZ58++HzMQJjQJnXizmktH4gh\ 12534JSQN6SgbqO/bgHgfnfwejYwG88d1hqtdivEwSVZ1U60PQnSDiitv1Er31R5Cd5zWkmapTnok9ZrKXmRNdtI2ifJalbekDiONg/Stzj4UJIPNVmCHOOckWS5\ 12535gbRaWS3suqnhcSFRKaEWaqNyJRWfvCuEN3fqCBViK9DPDA/1EhghuoHpbH//GTDC+CNesQc3DZgBBSzktGuZzwZdAoMDspedWlzLpMvlkzqqZDJh3uegvPE\ 12536CQp3TemY1Av7xG9iuXz/zOaMjxkLGo/KnilvJeHQhMB18FkumCzVAO7xQkovqS8iN/PVralYSWRvL+fRRTv10cqylxGl9rG/qe1FNG2Cr4Q/o/opmrIOkxj\ 12537kOblbVdFwS+eEBzGIhhjwML2QSsQDvplhhLrpTKn1FzWphIzDqnFgp11EznwpfWd07avxEjXr5aI2/aHf5PP7gi1fb+XSAdzBncfwcjlMOIZLYfQ89Qxdww\ 12538kIAzGoFrD9+zYaPEv/zG0xWzx8ddP3GJhS9GPnrAeSeLkcXpyZnHojh2FYR0Yzhr8iQowdJmvPqMaqy5OWuU2Y7zeoRL0jrnf380qSTdHb9Ta2qqhIc0b+G\ 12539lNzXvw4yrr/zr7W0YjYdj9hJWx/AcBdGCZcYMwZMBAZ4gPG4y+G0mkyEqafXhGGQJ9g71FzEv5H4iFCzdDThEddW2pnqrk7oNFG7VclEb24fFg1S5xShLyi\ 12540ffewTnPaFoJJPh4NXb9t/Aejmgpc=" 12541 12542_palette_hocuspocus : 12543 base642img \ 12544"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2MzQKeJxjk3x5buu8lopLu5f0lsV5mHk7WxlpKkrINhWlhnla6iotmtpakR\ 12545Ht7b5oUlNRUpCT+anN87qK4jzteqtz4/wdjVRfXNy1pK880UdUiJ+Xi52VyUJTXpSPg1ns57Vt08sjLGTeHp5bFW2vovrr3qFVfWVRLk9Ob53TmhMW8OT0p\ 12546tlNOUF2DASAqIiwkKAAPx8vDzcXFycH+9PrZw5uW71g+uJpnQ1lWQkRMGW/Hp3aNKspK1wUAjR/3Tu2blpdWsDzFy9fv3n3/uOHG4fXz2orjGfklTN0DEwq\ 12547bZ26bOfJm6/+MIg83t2fZq1amRUb6GiqIQu0go2NlUVgamtpWpibuUZ+Upifq6WBfn1xerSfk5n29LaytDB3c8OOyowoL0sdhRktxUlBrqYWx3fPbczwMZD\ 12548ePK0ywdtcWevjkRnFweYy3Dc29GT7mcrIf9ndGW+rxM0Mda/AgcWdBVHuRqpk+n9qX3NFYWZ8eKCosCAfDxcHO5Dm5+XmZP9258jKSeUJEcBwnt9ZHOt5cP\ 12549Oymf1NpSncvHwCgkIiouj+F5adluOmIchflwfyhqbslb3LJlQm+bismNJSkOBjo1eQHO4P9L/pjiVTmvPj/ewXT2goiPGxNN+zfEp9TpiLcU9lZoyPvZGqi\ 12550CAo+pkZfz29sHvZxJriO1vA/uZ+cnhZZ7afoQjMP0yioiIiIsLCwkJCQoKCggLK3z69evbo3q1rl86dOnZo365tm9YuWzRv1rRJfV1tTXVVZc115cX52enJ\ 125518dHhwf7e7s6/P715/vDOtQtH9+3avnn9mhVPz+9cPLE61R/mf3h6gMY/AyMzCxs7hxyu+AcA2aYUlw==" 12552 12553_palette_srb2 : 12554 base642img \ 12555"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM0OTcKeJz7//398/vXzx/fv3398vnT+9vry/PT48P93e3N9dXlxfnZGcAS0/\ 12556ra6kpzU2NDfJz3b169eDZIXXZ8sLe9sfZ/GIAYdBrG/fz0xul9G5dMh8ufX9+f76/P///19cPrZ7cXw4Tf3z+/f/38/vr8eH97fXn+/5+f3z69f/NyqIWh5\ 12557QWZiVFB3s42prpqckD33Du+dmpNipcRAxT8/39///z6ePuXR+aWhzjqSV/dv2pqQ1Yo2Pkg+efH1vYUBxlKMKCB89vnt+eH26v/J+T/5QtmTOhsrCzKSooK\ 12558BjrDuLo4Pzs5PjzY390ZqEZb+fXj25eB2neDgmVyd3P9uzund66Y3gZ2vK+rrRmG/2/vnl0d7awNcbY8uru2L+6vzo72t9dTV5AU4mZl+P/hwYUDGxZMaCh\ 12559ICHAwUOD//+TE2knlUfZQb8vnQ/XB/P/x9eO7186f2D+3vzx+P1ABDv//h4c3If/3dzRUFILiwMvJ2lhbRdob6G9rc2N9bXVleWlxYf77l4/v3rx89uTm6u\ 12560Ls5Ohg/zs7p5eGmknCbXoP9TeMXxzurC8vzM5AwP8wvr+3m6ONuZGuhrKcpAg/F8uKKQ3ZES4Gsujx//nhud3Lm2NMYKENEgX5Hx78z89tndOSHeRvb64uz\ 125618/+Hxb/ADJVV38=" 12562 12563_palette_uzebox : 12564 base642img \ 12565"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM1Mwp4nGNQ8ciduO3Wf4aRSkOBChR4QEEuFEyEgm1QcAsK/kPBcNFPLgilEK\ 12566yiEPynEAAA16V90A==" 12567 12568_palette_amiga7800 : 12569 base642img \ 12570"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM1MzMKeJxjEFQydglNK++YuWr3mbvv/v////3Z1SObF01syI/ztdGWMnQKTiltm7\ 125715i56nbb/7+h4CfL64f27pkclNhgr+dfUBiUfOUpduO33j5Cyr9/93dM7tXzewoTwt1MZbVcwhMKm6Zumz7iZsvfwMlP9w/t3fN7K7KjHA3UxVhJgYGDkkta\ 125725/YvPoJCzcdvvIUTRIM2MQ1LL2ic2r75m84eGD9vN6a7ChPC3UxVqg0g4CikXNIaln7jJW7Tj+8sH/d3J7qrEgPczVRFqAkn7yBY1BySeu05TtO3nr95///\ 12573b0+vHN60cEJ9XqyPtZYkA5r/v399cvnQxgX9dbkx3laaEuwoll96/AVFMwfYen4FpEC6cXzb0inNRYkB9nqyPJjOu4MUdLoy3EBZLmkdW7/4gsZJi7ccvfb\ 125748x/8fz68d3bJ4UmNBvJ+tjjSXlLaNb1x+w8RFm49cffYdHLwoIahu4RmVXdM7b/2Bi48+Q4L//b2ze1bP6qxID3M1UUZ1PVAW3X9o/p/eDIl3TgZkAHVk65\ 12575xNt46sm9FcnBTooC/HC5Jh5peGu/DEvfdfPr97+QRug4+jaUxGCSTyX71+/eb1+y8/voPBJ0g81RZm1EDi/dt/ZAB1ZGWyr5pNUAay9/5+fApPnhZKAtw8g\ 12576mLS8BDcvP/04undVZkR7maqIsJAIMDFzgEGvHL6oHTY1DetCdV/ADmMewY=" 12577 12578_palette_amiga7800mess : 12579 base642img \ 12580"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM3MTQKeJxj1LONLG9ZsP3sjbsPXn349v//PyAEgxu7Z5aHOLoXLdh84smf/2jg7+\ 12581fnV/ZvmFsV712/+cT9t7//QDVBNP9+/+T6qd2rpjame3nGpFZNmrts454j567euvfw2dkDG+bPmNBQmBrl76LKycbKo2DmFp6YW905ce7yTbsPX75weP3sy\ 12582b0FYb6exrKycrKyTEyMTEDMKG2XWtY1e+PxCye2LWqrLQ7yM9eQ5GdhYBCTUdbQs3IPjC1s7Z2+dMfOTy9unzu0Y/W87sqcBA9XSx03n9DcCWsOXbz//N33\ 12583vyD3AcGfn28fXti/dXVvYYQjI7r////88uzGhaOrJzZk+JtrKEjKqVoGZjX1zFx35Oixa0+e37p4aNOSGV2VeUl+ZvraKvLiUrKKqjZBCQX1E+at2nni1I7\ 125841S+f21hWlR/na6kowMzIys/ApW7v6R6XmljVPmLNq2+XT+zatWjCpuTQjysfWQE2OQ8bQKTg2s7y1d8aS9TsOXnz78sn9OzeObVs5q60wxtNC0ye2oGXm6j\ 125853n7zx8/urth88gB/5/8/jm2V1LJteXZod4OASnVfTMWLp+9/nHr7+CJP+8f3jtzP5N83vrC8OCXEyt7N0iynoWbth37OytZ59+/rxy+tjB7WsXTG4tTwm0U\ 12586pWXQvf/mpkVYYG+NsCwF5cQYGNkYBGUU1RSkFfVtQiJzO1YtPrikc3zumszQ73ttVX4BXj5WHjFJWUsQxOT6/rnr9137t6bVy+ePbp17jDQA50lCd7muR0T\ 12587l+07eenuiw8/QYGPlITe3rt6amlzZe/izUfO33rx/R807YAiCMh6c/P88TWTy2Oi8lvmbDt19ws0Xf6Dxb+vuTo4/hkYGBkZeCSV9Z3D4zOnTZ++ujInJNj\ 12588TRl+GixEkycDJxcnJwa2gb+vqm1q75OiVGc2FCTGRfi5WBurywhyszABUd6ys" 12589 12590_palette_fornaxvoid1 : 12591 base642img \ 12592"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM1MjkKeJyrKi3ISU+OiwwN8HF3srM01Te3d/MLi03NLalp6Z48exEDO6+IlIK6ro\ 12593mVg7tvSFTChwcXDmxYMKGhICHAwUBBgOH/p2e3zh3aunLuxNaKnIQQj8/Pb184snPtwmld9cXpMQGu/6HgwYEFDQlAHTeObJjbWZrkZ6UuzAAC/9/dPbN71\ 12594cyO8rRQF2MlQQYGVk5eITEpOWV1bX0TCxsHRkYGFIChXkBez9YnOquqc8bybUevPP7/6enNM0AXNoDcp6EgsGzT3hOX77388v/Wtom5HioMjy8f2bpsekdl\ 12595ZpS3ja4cP4Oqlr6xhY2jm5d/cERsYlrWvWvnju3btm7ZvGl9bXVleWlnDu/auGLB9L7WmpLspMgAjw8vH925eu7EwV1b1i5bMHNSD7r/+zqaasoKslLiIoJ\ 1259683BysTG8cWjMN6HG4+9H9r62hpqKkICcjKS4qLMjPy43u//8fHl46vGXptI7KrGgfWz2FBXNnz5w+dfLEvp6ujraWpgYGTiFpFV0ze4/AqOSc0rq2A2tmth\ 12597UnGDDgAuj+/48GXn/6icI/c+Hy9Vt3Hz558frdp68///zH8D+RABb//79/ePHw5qVTh3dvWTuxLNrh/7d3T+9eOXN496ZVC2dO6GhgEFQydglNK++YuWr3m\ 12598bvv/qP7n6B6KHhx4QA4Cfy/v39+fby9PAOXsIyqnjlGeAIAmOWLbw==" 12599 12600# Command that tries to compress a smooth-enough palette. 12601compress_palette : 12602 N={w} 12603 do 12604 N-=1 12605 +r. $N,1,1,3,2 round. 12606 ri. ..,3 round. 12607 deltaE. .. 12608 dEavg,dEmax={[ia,iM]} rm. 12609 e[] "N = "$N", dEavg = "$dEavg", dEmax = "$dEmax 12610 while $dEavg<0.75" && "$dEmax<1.25 12611 N+=1 12612 r $N,1,1,3,2 round. 12613 e[] "" 12614 img2base64 0,0 rm 12615 str=\"${}\" 12616 ('$str') s. x,-119 ('\\\n') if $!>2 a[0--3] .,x fi rm. 12617 i[0] ('" base642img \\\n"') 12618 ('"\n r. 256,1,1,3,3 round.\n"') 12619 a x 12620 ot pal.txt 12621 12622#@cli pseudogray : _max_increment>=0,_JND_threshold>=0,_bits_depth>0 12623#@cli : Generate pseudogray colormap with specified increment and perceptual threshold. 12624#@cli : If 'JND_threshold' is 0, no perceptual constraints are applied. 12625#@cli : Default values: 'max_increment=5', 'JND_threshold=2.3' and 'bits_depth=8'. 12626#@cli : $ pseudogray 5 12627pseudogray : check "isint(${1=5}) && $1>=0 && ${2=2.3}>=0 && isint(${3=8}) && $3>0" 12628 e[^-1] "Generate pseudogray colormap with increment $1, JND threshold $2 and $3 bits depth." 12629 12630 # Generate all possible sRGB colors with given increments. 12631 {round(2^$3)},1,1,3,'x' 12632 if !$1 n. 0,255 return fi 12633 {$1+1},{$1+1},{$1+1},1,'x' +f. 'y' +f. 'z' a[-3--1] c r. {w*h*d},1,1,3,-1 12634 f. 'R=i(x,0,0,0);G=i(x,0,0,1);B=i(x,0,0,2);if(min(R,G,B),-1,i)' 12635 permute. cxyz discard. -1 r. 3,{h/3},1,1,-1 permute. yzcx 12636 r.. {w*100}% ri. ..,0,2 +[-2,-1] 12637 f. 'R=i(x,0,0,0);G=i(x,0,0,1);B=i(x,0,0,2);if(max(R,G,B)>2^$3-1,-1,i)' 12638 permute. cxyz discard. -1 r. 3,{h/3},1,1,-1 permute. yzcx 12639 n. 0,255 12640 +srgb2lab. rv[-2,-1] a[-2,-1] y sort. +,x # Sort by increasing lightness. 12641 if !$2 rows. 1 12642 else # Add perceptual constraint if requested. 12643 12644 # Constraint 1 : keep colors close enough to equivalent 'pure' grays. 12645 s. y rv[-2,-1] . sh. 1,2 f. 0 rm. -[-2,-1] norm. 12646 <=. $2 *. 'x+1' discard. 0 -. 1 map. .. rm.. 12647 12648 # Constraint 2 : remove neighboring colors that are above the JND. 12649 repeat 10000 12650 +srgb2lab. +shift. 0,{1-2*($>%2)},0,0,1 -[-2,-1] norm. 12651 <=. $2 12652 if im rm. break fi 12653 *. 'y+1' discard. 0 -. 1 map. .. rm.. 12654 done 12655 transpose. 12656 fi 12657 nm. pseudogray$1 12658 12659#@cli replace_color : tolerance[%]>=0,smoothness[%]>=0,src1,src2,...,dest1,dest2,... 12660#@cli : Replace pixels from/to specified colors in selected images. 12661#@cli : $ image.jpg +replace_color 40,3,204,153,110,255,0,0 12662replace_color : check "$1>=0 && $2>=0" 12663 l[] (${3--1}) y c s c,2 col1={0,^} col2={1,^} rm endl 12664 e[^-1] "Replace color ("$col1") by color ("$col2") in image$?, with tolerance $1 and smoothness $2." 12665 repeat $! l[$>] 12666 1,1,1,100%,$col1 ri[1] [0] 12667 if $1 -[1] [0] norm[1] <=[1] $1 else ==[1] [0] l[1] s c & endl fi 12668 b[1] $2 12669 1,1,1,{0,s},$col2 ri[2] [0] j[0] [2],0,0,0,0,1,[1] k[0] 12670 endl done 12671 12672#@cli retinex : _value_offset>0,_colorspace={ hsi | hsv | lab | lrgb | rgb | ycbcr },\ 12673# 0<=_min_cut<=100,0<=_max_cut<=100,_sigma_low>0,_sigma_mid>0,_sigma_high>0 12674#@cli : Apply multi-scale retinex algorithm on selected images to improve color consistency. 12675#@cli : (as described in the page <http://www.ipol.im/pub/art/2014/107/>). 12676#@cli : Default values: 'offset=1', 'colorspace=hsv', 'min_cut=1', 'max_cut=1', 'sigma_low=15','sigma_mid=80' \ 12677# and 'sigma_high=250'. 12678retinex : check "${1=5}>0 && ${3=1}>=0 && $3<=100 && ${4=1}>=0 && $4<=100 && ${5=15}>0 && ${6=80}>0 && ${7=250}>0" 12679 skip "${2=hsv}" 12680 e[^-1] "Apply Retinex color consistency algorithm on image$?, with value offset $1, colorspace '$2', cuts ($3,$4) 12681 and sigmas (${5-7})." 12682 if '$2'=='hsi' mode=hsi_i 12683 elif '$2'=='hsv' mode=hsv_v 12684 elif '$2'=='lab' mode=lab_l 12685 elif '$2'=='rgb' mode=rgb 12686 elif '$2'=='lrgb' mode=lrgb 12687 elif '$2'=='ycbcr' mode=ycbcr_y 12688 else error[0--2] "Command '$0': Invalid colorspace argument '$2'." 12689 fi 12690 ac "_retinex $1,${3--1}",$mode 12691 12692_retinex : 12693 - {im-$1} {[w,h,d,s]},1 12694 repeat 3 +b[0] {arg(1+$>,${4-6})} +/[0,-1] rm.. *[1,-1] done 12695 rm[0] log c $2%,{100-$3}% n 0,255 12696 12697#@cli rgb2bayer : _start_pattern=0,_color_grid=0 12698#@cli : Transform selected color images to RGB-Bayer sampled images. 12699#@cli : Default values: 'start_pattern=0' and 'color_grid=0'. 12700#@cli : $ image.jpg +rgb2bayer 0 12701rgb2bayer : skip ${1=0},${2=0} 12702 e[^-1] "Transform image$? to a RGB-Bayer "${arg\ 1+!$2,color,monochrome}" grid, starting from pattern '$1'." 12703 to_rgb repeat $! l[$>] 12704 _rgb2bayer$1 ri[1] [0],0,2 * if !$2 s c + fi 12705 endl done 12706 12707_rgb2bayer0 : (1,0;0,0^0,1;1,0^0,0;0,1) 12708_rgb2bayer1 : (0,0;0,1^0,1;1,0^1,0;0,0) 12709_rgb2bayer2 : (0,1;0,0^1,0;0,1^0,0;1,0) 12710_rgb2bayer3 : (0,0;1,0^1,0;0,1^0,1;0,0) 12711 12712#@cli rgb2cmy 12713#@cli : Convert color representation of selected images from RGB to CMY. 12714#@cli : $ image.jpg rgb2cmy split c 12715rgb2cmy : 12716 e[^-1] "Convert color representation of image$? from RGB to CMY." 12717 to_rgb * -1 + 255 c 0,255 12718 12719#@cli rgb2cmyk 12720#@cli : Convert color representation of selected images from RGB to CMYK. 12721#@cli : $ image.jpg rgb2cmyk split c 12722#@cli : $ image.jpg rgb2cmyk split c fill[3] 0 append c cmyk2rgb 12723rgb2cmyk : 12724 e[^-1] "Convert color representation of image$? from RGB to CMYK." 12725 rgb2cmy repeat $! l[$>] 12726 s c +min -[0-2] . +/. 255 -. 1 *. -1 +==. 0 +[-2,-1] 12727 /[0-2] . rm. a c 12728 endl done 12729 12730#@cli rgb2hcy 12731#@cli : Convert color representation of selected images from RGB to HCY. 12732#@cli : $ image.jpg rgb2hcy split c 12733rgb2hcy : 12734 e[^-1] "Convert color representation of image$? from RGB to HCY." 12735 to_color f " 12736 M = max(R,G,B); 12737 C = M - min(R,G,B); 12738 H = 60*(C==0?0:M==R?((G-B)/C)%6:M==G?(B-R)/C+2:(R-G)/C+4); 12739 Y = 0.299*R + 0.587*G + 0.114*B; 12740 [ H,C/255,Y/255 ]" 12741 12742#@cli rgb2hsi 12743#@cli : Convert color representation of selected images from RGB to HSI. 12744#@cli : $ image.jpg rgb2hsi split c 12745rgb2hsi : 12746 e[^-1] "Convert color representation of image$? from RGB to HSI." 12747 to_color 12748 f " 12749 m = min(R,G,B); 12750 M = max(R,G,B); 12751 C = M - m; 12752 sum = R + G + B; 12753 H = 60*(C==0?0:M==R?((G - B)/C)%6:M==G?(B - R)/C + 2:(R - G)/C + 4); 12754 S = sum<=0?0:1 - 3*m/sum; 12755 I = sum/(3*255); 12756 [ H, S, I ]" 12757 12758#@cli rgb2hsi8 12759#@cli : Convert color representation of selected images from RGB to HSI8. 12760#@cli : $ image.jpg rgb2hsi8 split c 12761rgb2hsi8 : 12762 e[^-1] "Convert color representation of image$? from RGB to HSI8." 12763 rgb2hsi _rgb2hsx8 12764 12765#@cli rgb2hsl 12766#@cli : Convert color representation of selected images from RGB to HSL. 12767#@cli : $ image.jpg rgb2hsl split c 12768#@cli : $ image.jpg rgb2hsl +split c add[-3] 100 mod[-3] 360 append[-3--1] c hsl2rgb 12769rgb2hsl : 12770 e[^-1] "Convert color representation of image$? from RGB to HSL." 12771 to_color 12772 f " 12773 m = min(R,G,B); 12774 M = max(R,G,B); 12775 C = M - m; 12776 H = 60*(C==0?0:M==R?((G - B)/C)%6:M==G?(B - R)/C + 2:(R - G)/C + 4); 12777 L = 0.5*(m + M)/255; 12778 S = L==1 || L==0?0:C/(1 - abs(2*L - 1))/255; 12779 [ H, S, L ]" 12780 12781#@cli rgb2hsl8 12782#@cli : Convert color representation of selected images from RGB to HSL8. 12783#@cli : $ image.jpg rgb2hsl8 split c 12784rgb2hsl8 : 12785 e[^-1] "Convert color representation of image$? from RGB to HSL8." 12786 rgb2hsl _rgb2hsx8 12787 12788#@cli rgb2hsv 12789#@cli : Convert color representation of selected images from RGB to HSV. 12790#@cli : $ image.jpg rgb2hsv split c 12791#@cli : $ image.jpg rgb2hsv +split c add[-2] 0.3 cut[-2] 0,1 append[-3--1] c hsv2rgb 12792rgb2hsv : 12793 e[^-1] "Convert color representation of image$? from RGB to HSV." 12794 to_color 12795 f " 12796 M = max(R,G,B); 12797 C = M - min(R,G,B); 12798 H = 60*(C==0?0:M==R?((G - B)/C)%6:M==G?(B - R)/C + 2:(R - G)/C + 4); 12799 S = M<=0?0:C/M; 12800 [ H, S, M/255 ]" 12801 12802#@cli rgb2hsv8 12803#@cli : Convert color representation of selected images from RGB to HSV8. 12804#@cli : $ image.jpg rgb2hsv8 split c 12805rgb2hsv8 : 12806 e[^-1] "Convert color representation of image$? from RGB to HSV8." 12807 rgb2hsv _rgb2hsx8 12808 12809_rgb2hsx8 : 12810 repeat $! 12811 sh[$>] 0 *. 0.708333 rm. 12812 sh[$>] 1,2 *. 255 rm. 12813 done 12814 12815#@cli rgb2int 12816#@cli : Convert color representation of selected images from RGB to INT24 scalars. 12817#@cli : $ image.jpg rgb2int 12818rgb2int : 12819 e[^-1] "Convert color representation of image$? from RGB to INT24 scalars." 12820 to_rgb round repeat $! l[$>] 12821 s c <<[0] 16 <<[1] 8 + 12822 endl done 12823 12824#@cli rgb2jzazbz : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12825#@cli : Convert color representation of selected images from RGB to Jzazbz. 12826#@cli : Default value: 'illuminant=2'. 12827rgb2jzazbz : skip "${1=,}" 12828 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12829 e[^-1] "Convert color representation of image$? from RGB to Jzazbz, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12830 rgb2xyz $illu xyz2jzazbz 12831 12832#@cli rgb2lab : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12833#@cli : Convert color representation of selected images from RGB to Lab. 12834#@cli : Default value: 'illuminant=2'. 12835rgb2lab : skip "${1=,}" 12836 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12837 e[^-1] "Convert color representation of image$? from RGB to Lab, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12838 rgb2xyz $illu xyz2lab $illu 12839 12840#@cli rgb2lab8 : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12841#@cli : Convert color representation of selected images from RGB to Lab8. 12842#@cli : Default value: 'illuminant=2'. 12843#@cli : $ image.jpg rgb2lab8 split c 12844rgb2lab8 : skip "${1=,}" 12845 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12846 e[^-1] "Convert color representation of image$? from RGB to Lab8, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12847 rgb2lab $illu repeat $! 12848 sh[$>] 0 *. 2.55 rm. 12849 sh[$>] 1 +. 127 *. 0.85 rm. 12850 sh[$>] 2 +. 149 *. 0.836 rm. 12851 done c 0,255 12852 12853#@cli rgb2lch : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12854#@cli : Convert color representation of selected images from RGB to Lch. 12855#@cli : Default value: 'illuminant=2'. 12856#@cli : $ image.jpg rgb2lch split c 12857rgb2lch : skip "${1=,}" 12858 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12859 e[^-1] "Convert color representation of image$? from RGB to Lch, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12860 rgb2lab $illu lab2lch 12861 12862#@cli rgb2lch8 : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12863#@cli : Convert color representation of selected images from RGB to Lch8. 12864#@cli : Default value: 'illuminant=2'. 12865#@cli : $ image.jpg rgb2lch8 split c 12866rgb2lch8 : skip "${1=,}" 12867 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12868 e[^-1] "Convert color representation of image$? from RGB to Lch8, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12869 pi,facth={[pi,255/(2*pi)]} 12870 rgb2lch $illu repeat $! 12871 sh[$>] 0 *. 2.55 rm. 12872 sh[$>] 1 *. 1.1086 rm. 12873 sh[$>] 2 +. $pi *. $facth rm. 12874 done c 0,255 12875 12876#@cli rgb2luv 12877#@cli : Convert color representation of selected images from RGB to LUV. 12878#@cli : $ image.jpg rgb2luv split c 12879rgb2luv : 12880 e[^-1] "Convert color representation of image$? from RGB to LUV." 12881 repeat $! l[$>] 12882 +rgb2xyz rgb2lab.. channels.. 0 s. c 12883 *. 3 +*.. 15 +[-2,-1] +. ... +. 1e-8 # Z <- X+15Y+3Z 12884 *... 4 *.. 9 /[-3,-2] . rm. 12885 -.. 0.2009 -. 0.4610 12886 +*... 13 *... . *[-2,-1] a c 12887 endl done 12888 12889#@cli rgb2oklab 12890#@cli : Convert color representation of selected images from RGB to Oklab. 12891#@cli : (see colorspace definition at: <https://bottosson.github.io/posts/oklab/> ). 12892#@cli : See also: ''oklab2rgb''. 12893rgb2oklab : 12894 e[^-1] "Convert color representation of image$? from RGB to Oklab." 12895 repeat $! l[$>] split_opacity to_rgb[0] /[0] 255 12896 f[0] " 12897 l = cbrt(0.4121656120*R + 0.5362752080*G + 0.0514575653*B); 12898 m = cbrt(0.2118591070*R + 0.6807189584*G + 0.1074065790*B); 12899 s = cbrt(0.0883097947*R + 0.2818474174*G + 0.6302613616*B); 12900 [ 0.2104542553*l + 0.7936177850*m - 0.0040720468*s, 12901 1.9779984951*l - 2.4285922050*m + 0.4505937099*s, 12902 0.0259040371*l + 0.7827717662*m - 0.8086757660*s ]" 12903 a c endl done 12904 12905#@cli rgb2ryb 12906#@cli : Convert color representation of selected images from RGB to RYB. 12907#@cli : $ image.jpg rgb2ryb split c 12908rgb2ryb : 12909 e[^-1] "Convert color representation of image$? from RGB to RYB." 12910 to_color 12911 f "red = R; 12912 green = G; 12913 blue = B; 12914 white = min(red,green,blue); 12915 red-=white; 12916 green-=white; 12917 blue-=white; 12918 maxgreen = max(red,green,blue); 12919 yellow = min(red,green); 12920 red-=yellow; 12921 green-=yellow; 12922 blue>0 && green>0?(blue/=2; green/=2); 12923 yellow+=green; 12924 blue+=green; 12925 maxyellow = max(red,yellow,blue); 12926 maxyellow>0?( 12927 N = maxgreen/maxyellow; 12928 red*=N; 12929 yellow*=N; 12930 blue*=N; 12931 ); 12932 red+=white; 12933 yellow+=white; 12934 blue+=white; 12935 [ red,yellow,blue ]" 12936 12937#@cli rgb2srgb 12938#@cli : Convert color representation of selected images from linear RGB to sRGB. 12939rgb2srgb : 12940 e[^-1] "Convert color representation of image$? from linear RGB to sRGB." 12941 f "val = i/255; sval = val<=0.0031308?val*12.92:1.055*val^0.416667 - 0.055; cut(255*sval,0,255)" 12942 12943#@cli rgb2xyz : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12944#@cli : Convert color representation of selected images from RGB to XYZ. 12945#@cli : Default value: 'illuminant=2'. 12946#@cli : $ image.jpg rgb2xyz split c 12947rgb2xyz : skip "${1=,}" 12948 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12949 e[^-1] "Convert color representation of image$? from RGB to XYZ, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12950 if $illu==2 # E 12951 mix_rgb {[0.488718,0.3106803,0.2006017,\ 12952 0.1762044,0.8129847,0.0108109,\ 12953 0,0.0102048,0.9897952]/255} 12954 elif $illu==1 # D65 12955 mix_rgb {[0.4124564,0.3575761,0.1804375,\ 12956 0.2126729,0.7151522,0.0721750,\ 12957 0.0193339,0.1191920,0.9503041]/255} 12958 else # D50 12959 mix_rgb {[0.43603516,0.38511658,0.14305115,\ 12960 0.22248840,0.71690369,0.06060791,\ 12961 0.01391602,0.09706116,0.71392822]/255} 12962 fi 12963 12964#@cli rgb2xyz8 : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12965#@cli : Convert color representation of selected images from RGB to XYZ8. 12966#@cli : Default value: 'illuminant=2'. 12967#@cli : $ image.jpg rgb2xyz8 split c 12968rgb2xyz8 : skip "${1=,}" 12969 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 12970 e[^-1] "Convert color representation of image$? from RGB to XYZ8, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12971 rgb2xyz $illu repeat $! 12972 sh[$>] 0 *. 255 rm. 12973 sh[$>] 1 *. 255 rm. 12974 sh[$>] 2 *. 231.8182 rm. 12975 done 12976 12977#@cli rgb2yiq 12978#@cli : Convert color representation of selected images from RGB to YIQ. 12979#@cli : $ image.jpg rgb2yiq split c 12980rgb2yiq : 12981 e[^-1] "Convert color representation of image$? from RGB to YIQ." 12982 mix_rgb 0.299,0.587,0.114,\ 12983 0.595716,-0.274453,-0.321263,\ 12984 0.211456,-0.522591,0.311135 12985 12986#@cli rgb2yiq8 12987#@cli : Convert color representation of selected images from RGB to YIQ8. 12988#@cli : $ image.jpg rgb2yiq8 split c 12989rgb2yiq8 : 12990 e[^-1] "Convert color representation of image$? from RGB to YIQ." 12991 rgb2yiq 12992 repeat $! 12993 sh[$>] 1 +. 151.908 *. 0.8393238012481239 rm. 12994 sh[$>] 2 +. 133.261 *. 0.9567690472081104 rm. 12995 done 12996 12997#@cli rgb2ycbcr 12998#@cli : Convert color representation of selected images from RGB to YCbCr. 12999#@cli : $ image.jpg rgb2ycbcr split c 13000rgb2ycbcr : 13001 e[^-1] "Convert color representation of image$? from RGB to YCbCr." 13002 mix_rgb 66,129,25,-38,-74,112,112,-94,-18 13003 repeat $! 13004 sh[$>] 0,2 +. 128 /. 256 rm. 13005 sh[$>] 0 +. 16 rm. 13006 sh[$>] 1,2 +. 128 rm. 13007 done 13008 13009#@cli rgb2yuv 13010#@cli : Convert color representation of selected images from RGB to YUV. 13011#@cli : $ image.jpg rgb2yuv split c 13012rgb2yuv : 13013 e[^-1] "Convert color representation of image$? from RGB to YUV." 13014 mix_rgb {[0.299,0.587,0.114,\ 13015 -0.14713,-0.28886,0.436,\ 13016 0.615,-0.51498,-0.10001]/255} 13017 13018#@cli rgb2yuv8 13019#@cli : Convert color representation of selected images from RGB to YUV8. 13020#@cli : $ image.jpg rgb2yuv8 split c 13021rgb2yuv8 : 13022 e[^-1] "Convert color representation of image$? from RGB to YUV8." 13023 rgb2yuv repeat $! 13024 sh[$>] 0 *. 255 rm. 13025 sh[$>] 1 +. 0.44 *. 289.773 rm. 13026 sh[$>] 2 +. 0.62 *. 205.645 rm. 13027 done 13028 13029#@cli remove_opacity 13030#@cli : Remove opacity channel of selected images. 13031remove_opacity : 13032 e[^-1] "Remove opacity channel of image$?." 13033 repeat $! l[$>] 13034 if s==2 channels 0 13035 elif s==4 channels 0,2 13036 fi 13037 nm {n} endl done 13038 13039#@cli ryb2rgb 13040#@cli : Convert color representation of selected images from RYB to RGB. 13041ryb2rgb : 13042 e[^-1] "Convert color representation of image$? from RYB to RGB." 13043 to_color 13044 f "red = R; 13045 yellow = G; 13046 blue = B; 13047 white = min(red,yellow,blue); 13048 red-=white; 13049 yellow-=white; 13050 blue-=white; 13051 maxyellow = max(red,yellow,blue); 13052 green = min(yellow,blue); 13053 yellow-=green; 13054 blue-=green; 13055 blue>0 && green>0?(blue*=2; green*=2); 13056 red+=yellow; 13057 green+=yellow; 13058 maxgreen = max(red,green,blue); 13059 maxgreen>0?( 13060 N = maxyellow/maxgreen; 13061 red*=N; 13062 green*=N; 13063 blue*=N; 13064 ); 13065 red+=white; 13066 green+=white; 13067 blue+=white; 13068 [ red,green,blue ]" 13069 13070#@cli select_color : tolerance[%]>=0,col1,...,colN 13071#@cli : Select pixels with specified color in selected images. 13072#@cli : $ image.jpg +select_color 40,204,153,110 13073#@cli : $$ https://gmic.eu/oldtutorial/_select_color 13074select_color : skip ${1=0} 13075 e[^-1] "Select color (${2--1}) in image$?, with tolerance $1." 13076 repeat $! l[$>] 13077 +fc ${2--1} - norm <= $1 13078 endl done 13079 13080#@cli sepia 13081#@cli : Apply sepia tones effect on selected images. 13082#@cli : $ image.jpg sepia 13083sepia : 13084 e[^-1] "Apply sepia tones effect on image$?." 13085 (0,44,115,143,196,244^0,20,84,119,184,235^0,5,44,73,144,200) r. 256,1,1,3,3 13086 repeat $!-1 l[$>,-1] split_opacity luminance[0] map[0] . a[^-1] c endl done 13087 rm. 13088 13089#@cli solarize 13090#@cli : Solarize selected images. 13091#@cli : $ image.jpg solarize 13092solarize : 13093 e[^-1] "Solarize image$?." 13094 luminance n 0,128 map 1 13095 13096#@cli split_colors : _tolerance>=0,_max_nb_outputs>0,_min_area>0 13097#@cli : Split selected images as several image containing a single color. 13098#@cli : One selected image can be split as at most 'max_nb_outputs' images. 13099#@cli : Output images are sorted by decreasing area of extracted color regions and have an additional alpha-channel. 13100#@cli : Default values: 'tolerance=0', 'max_nb_outputs=256' and 'min_area=8'. 13101#@cli : $ image.jpg quantize 5 +split_colors , display_rgba 13102split_colors : check "${1=0}>=0 && isint(${2=256}) && $2>0 && ${3=8}>=1" 13103 e[^-1] "Split image$? as single color outputs, with tolerance $1, $2 maximal outputs and minimal color area $3." 13104 repeat $! l[$>] 13105 +label 0,1 norm. area. 0,1 13106 13107 # Loop over biggest color regions. 13108 repeat $2-1 13109 coordsM={1,[xM,yM,zM,cM]} 13110 if {1,i($coordsM)<$3} break fi 13111 color={0,I($coordsM)} 13112 +select_color[0] $1,$color 13113 ==. 0 *[1] . ==. 0 13114 done 13115 if iM#1 !=[1] 0 mv[1] $! # Residual mask, if any. 13116 else rm[1] fi 13117 r[^0] [0],[0],[0],{0,s+1} 13118 N={$!-1} 13119 sh[^0] 0,{s-2} *[-$N--1] [0] rm[-$N--1] 13120 sh[^0] 100% *[-$N--1] 255 rm[0,-$N--1] 13121 13122 endl done 13123 13124#@cli split_opacity 13125#@cli : Split color and opacity parts of selected images. 13126split_opacity : 13127 e[^-1] "Split color and opacity parts of image$?." 13128 repeat $! l[$<] s c,{s==4?-3:s==2?-1:-s} endl done 13129 13130#@cli srgb2lab : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 13131#@cli : Convert color representation of selected images from sRGB to Lab. 13132#@cli : Default value: 'illuminant=2'. 13133#@cli : $ image.jpg srgb2lab split c 13134#@cli : $ image.jpg srgb2lab +split c mul[-2,-1] 2.5 append[-3--1] c lab2srgb 13135srgb2lab : skip "${1=,}" 13136 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 13137 e[^-1] "Convert color representation of image$? from sRGB to Lab, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 13138 srgb2rgb rgb2lab $illu 13139 13140#@cli srgb2lab8 : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 13141#@cli : Convert color representation of selected images from sRGB to Lab8. 13142#@cli : Default value: 'illuminant=2'. 13143srgb2lab8 : skip "${1=,}" 13144 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 13145 e[^-1] "Convert color representation of image$? from sRGB to Lab8, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 13146 srgb2rgb rgb2lab8 $illu 13147 13148#@cli srgb2rgb 13149#@cli : Convert color representation of selected images from sRGB to linear RGB. 13150srgb2rgb : 13151 e[^-1] "Convert color representation of image$? from sRGB to linear RGB." 13152 f "sval = i/255; val = sval<=0.04045?sval/12.92:((sval + 0.055)/(1.055))^2.4; cut(255*val,0,255)" 13153 13154#@cli to_a 13155#@cli : Force selected images to have an alpha channel. 13156to_a : 13157 e[^-1] "Force image$? to have an alpha channel." 13158 repeat $! l[$>] 13159 if s==1||s==3 channels 0,{s} sh. {s-1} f. 255 rm. fi 13160 endl done 13161 13162#@cli to_color 13163#@cli : Force selected images to be in color mode (RGB or RGBA). 13164to_color : 13165 e[^-1] "Force image$? to be in color mode." 13166 repeat $! l[$>] 13167 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 13168 elif s==2 r 100%,100%,1,4,0,1,0,0,0,1 13169 elif s==1 r 100%,100%,1,3,1 13170 fi 13171 endl done 13172 13173#@cli to_colormode : mode={ 0=adaptive | 1=G | 2=GA | 3=RGB | 4=RGBA } 13174#@cli : Force selected images to be in a given color mode. 13175#@cli : Default value: 'mode=0'. 13176to_colormode : skip ${1=0} 13177 if $1==1 to_gray 13178 elif $1==2 to_graya 13179 elif $1==3 to_rgb 13180 elif $1==4 to_rgba 13181 else 13182 is_rgb=0 is_alpha=0 13183 repeat $! 13184 if {$>,!s||s>4} error "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 13185 elif {$>,s==2} is_alpha=1 13186 elif {$>,s==3} is_rgb=1 13187 elif {$>,s==4} is_rgb=1 is_alpha=1 13188 fi 13189 done 13190 to_colormode {if($is_rgb,3,1)+$is_alpha} 13191 fi 13192 13193#@cli to_gray 13194#@cli : Force selected images to be in GRAY mode. 13195#@cli : $ image.jpg +to_gray 13196to_gray : 13197 e[^-1] "Force image$? to be in GRAY mode." 13198 repeat $! l[$>] 13199 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 13200 elif s>=3 channels 0,2 luminance 13201 elif s==2 r 100%,100%,100%,1,0 13202 fi 13203 endl done 13204 13205#@cli to_graya 13206#@cli : Force selected images to be in GRAYA mode. 13207to_graya : 13208 e[^-1] "Force image$? to be in GRAYA mode." 13209 repeat $! l[$>] 13210 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 13211 elif s==4 +channels 3 channels.. 0,2 luminance.. a c 13212 elif s==3 luminance channels 0,1 sh. 1 f. 255 rm. 13213 elif s==1 channels 0,1 sh. 1 f. 255 rm. 13214 fi 13215 endl done 13216 13217#@cli to_pseudogray : _max_step>=0,_is_perceptual_constraint={ 0 | 1 },_bits_depth>0 13218#@cli : Convert selected scalar images ([0-255]-valued) to pseudo-gray color images. 13219#@cli : Default values: 'max_step=5', 'is_perceptual_constraint=1' and 'bits_depth=8'. 13220#@cli : The original pseudo-gray technique has been introduced by Rich Franzen <http://r0k.us/graphics/pseudoGrey.html>. 13221#@cli : Extension of this technique to arbitrary increments for more tones, has been done by David Tschumperlé. 13222to_pseudogray : check "isint(${1=5}) && $1>=0 && isint(${3=8}) && $3>0" skip ${2=1} 13223 e[^-1] "Convert scalar image$? to pseudo-gray color images, with steps $1." 13224 channels 0 srgb2rgb pseudogray $1,{2.3*$2},$3 13225 13226 # Compute colormap with 65336 entries, to have match corresponding lightness. 13227 +srgb2lab. channels. 0 *. {65535/100} round. rows. 0,2 13228 rv[-2,-1] permute. xcyz +. 1 a[-2,-1] y pointcloud. 0 13229 +norm. !=. 0 distance. 1 *. -1 watershed.. . rm. -. 1 13230 13231 # Map colormap to images, with lightness preservation. 13232 repeat $!-1 13233 to_rgb[$>] rgb2lab[$>] channels[$>] 0 *[$>] {65535/100} round[$>] c[$>] 0,65535 13234 map[$>] . 13235 done rm. 13236 13237#@cli to_rgb 13238#@cli : Force selected images to be in RGB mode. 13239to_rgb : 13240 e[^-1] "Force image$? to be in RGB mode." 13241 repeat $! l[$>] 13242 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 13243 elif s==4 channels 0,2 13244 elif s==2 channels 0,0 r 100%,100%,100%,3 13245 elif s==1 r 100%,100%,100%,3 13246 fi 13247 endl done 13248 13249#@cli to_rgba 13250#@cli : Force selected images to be in RGBA mode. 13251to_rgba : 13252 e[^-1] "Force image$? to be in RGBA mode." 13253 repeat $! l[$>] 13254 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 13255 elif s==3 channels 0,3 sh. 3 f. 255 rm. 13256 elif s==2 r 100%,100%,100%,4 sh. 2 f. .. rm. 13257 elif s==1 r 100%,100%,100%,4 sh. 3 f. 255 rm. 13258 fi 13259 endl done 13260 13261#@cli transfer_histogram : [reference_image],_nb_levels>0,_color_channels 13262#@cli : Transfer histogram of the specified reference image to selected images. 13263#@cli : Argument 'color channels' is the same as with command 'apply_channels'. 13264#@cli : Default value: 'nb_levels=256' and 'color_channels=all'. 13265#@cli : $ image.jpg 100,100,1,3,"u([256,200,100])" +transfer_histogram[0] [1] 13266transfer_histogram : check ${"is_image_arg $1"}" && ${2=1024}>0" skip "${3=0}" 13267 channels=${"_ac_list \"$3\""} 13268 e[^-1] "Transfer histogram from image ["${"pass$1 -1"}"] to image$?, "\ 13269 "with $2 levels, for channels '"$channels"'." 13270 pass$1 1 sref={s} rm. 13271 to_colormode $sref 13272 if ['$channels']!='all' 13273 pass$1 {$sref==3?2:0} 13274 to_color 13275 ac. "+store _transfer_histogram_reference",$channels rm. 13276 ac "_transfer_histogram $2",$channels,1 13277 else 13278 pass$1 13279 store. _transfer_histogram_reference 13280 repeat $! _transfer_histogram[$>] $2 done 13281 fi 13282 _transfer_histogram_reference= 13283 13284_transfer_histogram : 13285 $_transfer_histogram_reference 13286 repeat min(s#0,s#1) 13287 sh $> 13288 +histogram[-2,-1] $1 cumulate[-2,-1] /.. {-2,i[-1,2]} /. {i[-1,2]} 13289 f.. "* 13290 const w1 = w -1; 13291 val = i; X = x; 13292 val<i[#-1,X]?( 13293 step = int(X/2); 13294 while (X && step>=1, nX = max(0,X - step); val<i[#-1,nX]?(X = nX):(step = int(step/2))); 13295 X?(vc = i[#-1,X]; vp = i[#-1,X - 1]; (vc - val)>(val - vp)?--X); # Rounding 13296 ):( 13297 step = int((w1 - X)/2); 13298 while (X<w1 && step>=1, nX = min(w1,X + step); val>i[#-1,nX]?(X = nX):(step = int(step/2))); 13299 X<w1?(vc = i[#-1,X]; vn = i[#-1,X + 1]; (val - vc)>(vn - val)?++X); # Rounding 13300 ); 13301 im#-3 + (iM#-3 - im#-3)*X/w1" 13302 n[-4] 0,{w-1} round[-4] map[-4] .. 13303 k[0,1] 13304 done 13305 rm. 13306 13307#@cli transfer_pca : [reference_image],_color_channels 13308#@cli : Transfer mean and covariance matrix of specified vector-valued reference image to selected images. 13309#@cli : Argument 'color channels' is the same as with command 'apply_channels'. 13310#@cli : Default value: 'color_channels=all'. 13311#@cli : $ sample lena,earth +transfer_pca[0] [1] 13312transfer_pca : check ${"is_image_arg $1"} skip "${2=all}" 13313 channels=${"_ac_list \"$2\""} 13314 e[^-1] "Transfer mean vector and covariance matrix from image ["${"pass$1 -1"}"] to image$?, "\ 13315 "for channels '"$channels"'." 13316 pass$1 1 sref={s} rm. 13317 to_colormode[^-1] $sref 13318 if $sref==1 # Scalar case can to be solved more easily 13319 pass$1 13320 var_ref,avg_ref={[iv,ia]} rm. 13321 repeat $! l[$>] - {ia} * {sqrt($var_ref/iv)} + $avg_ref endl done 13322 elif ['$channels']!='all' 13323 pass$1 {$sref==3?2:0} 13324 to_color 13325 ac. "+store _transfer_pca_reference",$channels rm. 13326 ac "_transfer_pca",$channels,1 13327 else 13328 pass$1 13329 store. _transfer_pca_reference 13330 repeat $! _transfer_pca[$>] done 13331 fi 13332 _transfer_pca_reference= 13333 13334_transfer_pca : 13335 $_transfer_pca_reference 13336 f.. "*begin( 13337 cov = [ "${"covariance_colors[0] _avg"}" ]; 13338 avg = [ "$_avg" ]; 13339 eig = eig(cov); 13340 lambda = 1/sqrt(1e-6 + eig[0,s]); 13341 rot = mul(diag(lambda),eig[s,s*s],s); 13342 13343 cov_ref = [ "${"covariance_colors[1] _avg_ref"}" ]; 13344 avg_ref = [ "$_avg_ref" ]; 13345 eig_ref = eig(cov_ref); 13346 lambda_ref = sqrt(eig_ref[0,s]); 13347 rot_ref = mul(transpose(eig_ref[s,s*s],s),diag(lambda_ref),s); 13348 13349 M = mul(rot_ref,rot,s); 13350 ); 13351 avg_ref + M*(I - avg)" 13352 rm. 13353 13354#@cli transfer_rgb : [target],_gamma>=0,_regularization>=0,_luminosity_constraints>=0,_rgb_resolution>=0,\ 13355# _is_constraints={ 0 | 1 } 13356#@cli : Transfer colors from selected source images to selected reference image (given as argument). 13357#@cli : 'gamma' determines the importance of color occurrences in the matching process (0=none to 1=huge). 13358#@cli : 'regularization' determines the number of guided filter iterations to remove quantization effects. 13359#@cli : 'luminosity_constraints' tells if luminosity constraints must be applied on non-confident matched colors. 13360#@cli : 'is_constraints' tells if additional hard color constraints must be set (opens an interactive window). 13361#@cli : Default values: 'gamma=0.3','regularization=8', 'luminosity_constraints=0.1', 'rgb_resolution=64' and \ 13362# 'is_constraints=0'. 13363#@cli : $ sample pencils,wall +transfer_rgb[0] [1],0,0.01 13364transfer_rgb : check "${2=0.3}>=0 && ${3=8}>=0 && ${4=0.15}>=0 && ${5=64}>=0 && isint(${6=0})" 13365 e[^-1] "Transfer colors of image $1 to image$?." 13366 sigma=1.5 13367 repeat $! pass$1 0 l[$>,-1] 13368 nm_source={0,b} nm_target={1,b} 13369 nm[0] source nm[1] target 13370 13371 # Generate matching functions from 3D RGB features. 13372 +_transfer_rgb[source,target] $2,$sigma,$5 13373 nm.. fsource nm. ftarget 13374 n[fsource,ftarget] 0,255 13375 13376 # Manage color constraints. 13377 if $6 13378 h0={2*{*,v}/3} ws0={source,max(1,w*$h0/h)} wt0={target,max(1,w*$h0/h)} 13379 w1={2*{*,u}/3} hs1={source,max(1,h*$w1/w)} ht1={target,max(1,h*$w1/w)} 13380 if abs($ws0+$wt0-$w1)<abs($hs1+$ht1-$h0) # Append along X. 13381 +r2dy[source,target] $h0 +b[-2,-1] 0.5% a[-4,-3] x a[-2,-1] x 13382 else # Append along Y. 13383 +r2dx[source,target] $w1 +b[-2,-1] 0.5% a[-4,-3] y a[-2,-1] y 13384 fi 13385 if w>$w1 r2dx[-2,-1] $w1 fi 13386 if h>$h0 r2dy[-2,-1] $h0 fi 13387 nm.. visu nm. both 13388 13389 w[visu] -1,-1 13390 N=0 do 13391 w[] -1,-1,"[G'MIC] Add Color Guide (Constraint ""#"{1+$N}")" 13392 +select[$visu] 1 if i==-1 rm. break fi 13393 line[$visu] {i[0]},{i[1]},{i[3]},{i[4]},1,0xF0F0F0F0,0 13394 line[$visu] {i[0]},{i[1]},{i[3]},{i[4]},1,0x0F0F0F0F,255 13395 circle[$visu] {i[0]},{i[1]},5,1,0,0,0 circle[$visu] {i[0]},{i[1]},3,1,255,0,0 13396 circle[$visu] {i[3]},{i[4]},5,1,0,0,0 circle[$visu] {i[3]},{i[4]},3,1,0,255,0 13397 s. y,2 rows[-2,-1] 0,1 a[-2,-1] x permute. xczy 13398 +warp[$both] .,0,0 rm.. 13399 *. {($5-1)/255} s. x,2 13400 -. .. *. -1 a[-2,-1] c 13401 N+=1 13402 while {*} 13403 if $N a[-$N--1] x permute. xczy nm. constraints fi 13404 rm[$visu,$both] w 0 13405 fi 13406 13407 # Estimate warping field. 13408 if $constraints 13409 +pointcloud. 0 r. ...,...,...,3,0 +compose_channels. + a[-2,-1] c 13410 displacement[fsource] [ftarget],0.001,5,0,10000,1,. rm[ftarget,constraints,-1] 13411 else 13412 displacement[fsource] [ftarget],0.005 rm[ftarget] 13413 fi 13414 nm[fsource] displacement 13415 13416 # Generate video of matching. 13417 # if videos 13418 # N=$! 13419 # [displacement],[displacement],[displacement],1,x +f. y +f. z a[-3--1] c *. {255/(w-1)} +. 1 13420 # +_transfer_rgb[source] 0,$sigma,{w} *.. . distance. 1 *. -1 watershed.. . rm. 13421 # +_transfer_rgb[source] 0,$sigma,{w} a[-2,-1] c 13422 13423 # [displacement],[displacement],[displacement],1,x +f. y +f. z a[-3--1] c *. {255/(w-1)} +. 1 13424 # +_transfer_rgb[target] 0,$sigma,{w} *.. . distance. 1 *. -1 watershed.. . rm. 13425 # +_transfer_rgb[target] 0,$sigma,{w} a[-2,-1] c 13426 # warp. [displacement],1,1,1,48 13427 13428 # l[$N--1] 13429 # f3d 1200 13430 # ap "s. c,-3 view_func. 6,.. rm.." 13431 # ap "makefig" 13432 # append[^0] [0],x rm[0] 13433 # r2dx 1024 13434 # [-1]x20 13435 # o videos/video_${nm_source}_to_${nm_target}.mp4,10 13436 # rm 13437 # endl 13438 # fi 13439 13440 # Estimate confidence of the color mapping. 13441 +_transfer_rgb[target] 0,$sigma,{displacement,w} 13442 warp. [displacement],1,1,1 c. 0,100% nm. fconfidence 13443 +map_clut[source] . nm. confidence 13444 13445 # Generate transfer CLUT. 13446 [displacement],[displacement],[displacement],1,x +f. y +f. z a[-3--1] c *. {255/(w-1)} +. 1 13447 +_transfer_rgb[target] 0,0,{w} *.. . 13448 warp[-2,-1] [displacement],1,0,1 13449 distance. 1 *. -1 watershed.. . rm. -. 1 13450 nm. clut 13451 b[clut] $sigma% 13452 13453 # Enforce luminosity constraint for non-confident colors. 13454 if $4>0 13455 ^[fconfidence] {$4/10} *[fconfidence] -1 +[fconfidence] 1 13456 +f[fconfidence] x +f. y +f. z a[-3--1] c *. {255/(w-1)} 13457 rgb2hsv[clut,-1] channels. 100% 13458 j[clut] .,0,0,0,2,1,[fconfidence] rm. 13459 hsv2rgb[clut] 13460 fi 13461 13462 # Map CLUT to get result. 13463 +map_clut[source] [clut] nm. res_noregul 13464 13465 # Apply guided smoothing to remove quantization artifacts. 13466 if !$3 13467 nm[res_noregul] res 13468 else 13469 l[source,res_noregul] 13470 rgb2ycbcr # Perform regularization in YCbCr to avoid creation of false colors. 13471 +-[1] [0] repeat $3 guided. [0],5,5 done +. [0] c. 0,255 13472 ycbcr2rgb 13473 endl 13474 nm. res 13475 j[res] [res_noregul],0,0,0,0,1,[confidence] 13476 rm[res_noregul] 13477 fi 13478 13479 k[res] 13480 endl done 13481 13482# _transfer_rgb : _gamma>=0,_smoothness>=0,_resolution>0 13483# Convert selected images into 3D volumetric scalar function for color matching. 13484_transfer_rgb : l[] check "${1=0}>=0 && ${2=1.5}>=0 && ${3=128}>0" gamma=$1 smoothness=$2 res=$3 13485 onfail noarg gamma=0 smoothness=1.5 res=128 endl 13486 e[^-1] "Convert image$? as 3D volumetric scalar functions for color matching, with gamma "$gamma", 13487 smoothness "$smoothness" and resolution "$res"." 13488 to_rgb repeat $! l[$>] 13489 b 0.3% 13490 r {w*h},3,1,1,-1 * {($res-1)/255} 13491 pointcloud 1,$res,$res,$res f 'if(i,i^$gamma,0)' b $smoothness% n 0,1 13492 endl done 13493 13494#@cli xyz2jzazbz 13495#@cli : Convert color representation of selected images from XYZ to RGB. 13496xyz2jzazbz : 13497 e[^-1] "Convert color representation of image$? from XYZ to Jzazbz." 13498 repeat $! l[$>] split_opacity 13499 f[0] ${-_jzazbz_const}" 13500 X = i0*255; 13501 Y = i1*255; 13502 Z = i2*255; 13503 Xp = Jzazbz_b*X - (Jzazbz_b - 1)*Z; 13504 Yp = Jzazbz_g*Y - (Jzazbz_g - 1)*X; 13505 Zp = Z; 13506 L = 0.41478972*Xp + 0.579999*Yp + 0.0146480*Zp; 13507 M = -0.2015100*Xp + 1.120649*Yp + 0.0531008*Zp; 13508 S = -0.0166008*Xp + 0.264800*Yp + 0.6684799*Zp; 13509 tmp = (L/peakLum)^Jzazbz_n; 13510 Lp = ((Jzazbz_c1 + Jzazbz_c2*tmp)/(1 + Jzazbz_c3*tmp))^Jzazbz_p; 13511 tmp = (M/peakLum)^Jzazbz_n; 13512 Mp = ((Jzazbz_c1 + Jzazbz_c2*tmp)/(1 + Jzazbz_c3*tmp))^Jzazbz_p; 13513 tmp = (S/peakLum)^Jzazbz_n; 13514 Sp = ((Jzazbz_c1 + Jzazbz_c2*tmp)/(1 + Jzazbz_c3*tmp))^Jzazbz_p; 13515 Iz = 0.5*Lp + 0.5*Mp; 13516 az = 3.52400*Lp - 4.066708*Mp + 0.542708*Sp; 13517 bz = 0.199076*Lp + 1.096799*Mp - 1.295875*Sp; 13518 Jz = (1 + Jzazbz_d)*Iz/(1 + Jzazbz_d*Iz) - Jzazbz_d0; 13519 [ Jz,az,bz ]" 13520 a c endl done 13521 13522#@cli xyz2lab : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 13523#@cli : Convert color representation of selected images from XYZ to Lab. 13524#@cli : Default value: 'illuminant=2'. 13525xyz2lab : skip "${1=,}" 13526 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 13527 e[^-1] "Convert color representation of image$? from XYZ to Lab, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 13528 to_color 13529 f " 13530 begin( 13531 const epsilon = 216/24389; 13532 const kappa = 24389/27; 13533 lab(x) = (x>epsilon?cbrt(x):(x*kappa + 16)/116); 13534 D65 = [ 0.4124564, 0.3575761, 0.1804375, 13535 0.2126729, 0.7151522, 0.0721750, 13536 0.0193339, 0.1191920, 0.9503041 ]; 13537 D50 = [ 0.43603516, 0.38511658, 0.14305115, 13538 0.22248840, 0.71690369, 0.06060791, 13539 0.01391602, 0.09706116, 0.71392822 ]; 13540 E = [ 0.488718,0.3106803,0.2006017, 13541 0.1762044,0.8129847,0.0108109, 13542 0,0.0102048,0.9897952 ]; 13543 white = ("$illu"==2?E:"$illu"==1?D65:D50)*[ 1,1,1 ]; 13544 ); 13545 xr = i0/white[0]; 13546 yr = i1/white[1]; 13547 zr = i2/white[2]; 13548 fx = lab(xr); 13549 fy = lab(yr); 13550 fz = lab(zr); 13551 [ cut(116*fy - 16,0,100), 500*(fx - fy), 200*(fy - fz) ]" 13552 13553#@cli xyz2rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 13554#@cli : Convert color representation of selected images from XYZ to RGB. 13555#@cli : Default value: 'illuminant=2'. 13556xyz2rgb : skip "${1=,}" 13557 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 13558 e[^-1] "Convert color representation of image$? from XYZ to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 13559 if $illu==2 # E 13560 mix_rgb {[2.3706743,-0.9000405,-0.4706338,\ 13561 -0.513885,1.4253036,0.0885814,\ 13562 0.0052982,-0.0146949,1.0093968]*255} 13563 elif $illu # D65 13564 mix_rgb {[3.2404542,-1.5371385,-0.4985314,\ 13565 -0.9692660,1.8760108,0.0415560,\ 13566 0.0556434,-0.2040259,1.0572252]*255} 13567 else # D50 13568 mix_rgb {[3.134274799724,-1.617275708956,-0.490724283042,\ 13569 -0.978795575994,1.916161689117,0.033453331711,\ 13570 0.071976988401,-0.228984974402,1.405718224383]*255} 13571 fi 13572 c 0,255 13573 13574#@cli xyz82rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 13575#@cli : Convert color representation of selected images from XYZ8 to RGB. 13576#@cli : Default value: 'illuminant=2'. 13577xyz82rgb : skip "${1=,}" 13578 l[] if isnum("$1") illu={"$1>1?2:$1>0?1:0"} else if ["'$1'"]!=',' noarg fi illu=2 fi onfail noarg illu=2 endl 13579 e[^-1] "Convert color representation of image$? from XYZ8 to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 13580 repeat $! 13581 sh[$>] 0 /. 255 rm. 13582 sh[$>] 1 /. 255 rm. 13583 sh[$>] 2 /. 231.8182 rm. 13584 done xyz2rgb $illu 13585 13586#@cli ycbcr2rgb 13587#@cli : Convert color representation of selected images from YCbCr to RGB. 13588ycbcr2rgb : 13589 e[^-1] "Convert color representation of image$? from YCbCr to RGB." 13590 repeat $! 13591 sh[$>] 0 -. 16 rm. 13592 sh[$>] 1,2 -. 128 rm. 13593 sh[$>] 0,2 mix_rgb. 298,0,409,\ 13594 298,-100,-208,\ 13595 298,516,0 13596 +. 128 /. 256 c. 0,255 rm. 13597 done 13598 13599#@cli yiq2rgb 13600#@cli : Convert color representation of selected images from YIQ to RGB. 13601yiq2rgb : 13602 e[^-1] "Convert color representation of image$? from YIQ to RGB." 13603 mix_rgb 1,0.9563,0.6210,\ 13604 1,-0.2721,-0.6474,\ 13605 1,-1.1070,1.7046 13606 c 0,255 13607 13608#@cli yiq82rgb 13609#@cli : Convert color representation of selected images from YIQ8 to RGB. 13610yiq82rgb : 13611 e[^-1] "Convert color representation of image$? from YIQ8 to RGB." 13612 repeat $! 13613 sh[$>] 1 /. 0.8393238012481239 -. 151.908 rm. 13614 sh[$>] 2 /. 0.9567690472081104 -. 133.261 rm. 13615 done 13616 mix_rgb 1,0.9563,0.6210,\ 13617 1,-0.2721,-0.6474,\ 13618 1,-1.1070,1.7046 13619 c 0,255 13620 13621#@cli yuv2rgb 13622#@cli : Convert color representation of selected images from YUV to RGB. 13623yuv2rgb : 13624 e[^-1] "Convert color representation of image$? from YUV to RGB." 13625 mix_rgb {[1,0,1.13983,\ 13626 1,-0.39465,-0.5806,\ 13627 1,2.03211,0]*255} 13628 c 0,255 13629 13630#@cli yuv82rgb 13631#@cli : Convert selected images from YUV8 to RGB color bases. 13632yuv82rgb : 13633 e[^-1] "Convert color representation of image$? from YUV8 to RGB." 13634 repeat $! 13635 sh[$>] 0 /. 255 rm. 13636 sh[$>] 1 /. 289.773 -. 0.44 rm. 13637 sh[$>] 2 /. 205.645 -. 0.62 rm. 13638 done yuv2rgb 13639 13640#--------------------------------- 13641# 13642#@cli :: Geometry Manipulation 13643# 13644#--------------------------------- 13645 13646#@cli a : eq. to 'append' : (+) 13647 13648#@cli append : [image],axis,_centering : axis,_centering : (+) 13649#@cli : Append specified image to selected images, or all selected images together, along specified axis. 13650#@cli : (eq. to 'a').\n 13651#@cli : 'axis' can be { x | y | z | c }. 13652#@cli : Usual 'centering' values are { 0=left-justified | 0.5=centered | 1=right-justified }. 13653#@cli : Default value: 'centering=0'. 13654#@cli : $ image.jpg split y,10 reverse append y 13655#@cli : $ image.jpg repeat 5 +rows[0] 0,{10+18*$>}% done remove[0] append x,0.5 13656#@cli : $ image.jpg append[0] [0],y 13657 13658#@cli append_tiles : _M>=0,_N>=0,0<=_centering_x<=1,0<=_centering_y<=1 13659#@cli : Append MxN selected tiles as new images. 13660#@cli : If 'N' is set to 0, number of rows is estimated automatically. 13661#@cli : If 'M' is set to 0, number of columns is estimated automatically. 13662#@cli : If 'M' and 'N' are both set to '0', auto-mode is used. 13663#@cli : If 'M' or 'N' is set to 0, only a single image is produced. 13664#@cli : 'centering_x' and 'centering_y' tells about the centering of tiles when they have different sizes. 13665#@cli : Default values: 'M=0', 'N=0', 'centering_x=centering_y=0.5'. 13666#@cli : $ image.jpg split xy,4 append_tiles , 13667append_tiles : check "isint(${1=0}) && isint(${2=0}) && ${3=0}>=0 && $3<=1 && ${4=$3}>=0 && $4<=1" 13668 if !$! 13669 e[0--3] "Append image$? as a 0x0-tiled image." 13670 return 13671 elif !$1" && "!$2 # Auto-mode 13672 N={int(sqrt($!))} M={ceil($!/$N)} 13673 e[0--3] "Append image$? as a "${M}x${N}"-tiled image (auto-mode)." 13674 elif !$2 # Auto-rows 13675 M=$1 N={round($!/$1,1,1)} 13676 e[0--3] "Append image$? as a "${M}x${N}"-tiled image." 13677 elif !$1 # Auto-columns 13678 M={round($!/$2,1,1)} N=$2 13679 e[0--3] "Append image$? as a "${M}x${N}"-tiled image." 13680 else 13681 e[0--3] "Append image$?, as $1x$2-tiled images." 13682 M=$1 N=$2 13683 fi 13684 W,H=${-max_wh} rr2d $W,$H,2,1 13685 MN={$M*$N} if $!%$MN 0x{$MN-($!%$MN)} fi 13686 repeat $!/$MN l[$>-{$>+$MN-1}] 13687 repeat $!/$M a[$>-{$>+$M-1}] x,$3 done a y,$4 13688 endl done 13689 13690#@cli apply_scales : "command",number_of_scales>0,_min_scale[%]>=0,_max_scale[%]>=0,_scale_gamma>0,_interpolation 13691#@cli : Apply specified command on different scales of selected images. 13692#@cli : 'interpolation' can be { 0=none | 1=nearest | 2=average | 3=linear | 4=grid | 5=bicubic | 6=lanczos }. 13693#@cli : Default value: 'min_scale=25%', 'max_scale=100%' and 'interpolation=3'. 13694#@cli : $ image.jpg apply_scales "blur 5 sharpen 1000",4 13695apply_scales : check "isint($2) && $2>0 && ${3=25%}>=0 && ${4=100%}>=0 && ${5=1}>0 && isint(${6=3}) && $6>=0" 13696 skip "${1=}" 13697 s0="no" s1="nearest-neighbor" s2="average" s3="linear" s4="grid" s5="bicubic" s6="lanczos" 13698 e[^-1] "Apply command '$1' on image$? for $2 scales ($3 -> $4) and "${s{min(6,$6)}}" interpolation." 13699 repeat $! l[$<] nm={0,n} 13700 scale0={if(${"is_percent $3"},$3*max(w,h,d),$3)} 13701 scale1={if(${"is_percent $4"},$4*max(w,h,d),$4)} 13702 repeat $2 13703 scale={$scale0+($scale1-$scale0)*($>/max(1,$2-1))^$5} 13704 w={0,w==1?1:max(1,round($scale*w/max(w,h,d)))} 13705 h={0,h==1?1:max(1,round($scale*h/max(w,h,d)))} 13706 d={0,d==1?1:max(1,round($scale*d/max(w,h,d)))} 13707 +r[0] $w,$h,$d,100%,$6 13708 if narg("$1") l. $1 endl fi 13709 done 13710 rm[0] nm $nm 13711 endl done 13712 13713#@cli autocrop : value1,value2,... : (no arg) : (+) 13714#@cli : Autocrop selected images by specified vector-valued intensity. 13715#@cli : If no arguments are provided, cropping value is guessed. 13716#@cli : $ 400,400,1,3 fill_color 64,128,255 ellipse 50%,50%,120,120,0,1,255 +autocrop 13717 13718#@cli autocrop_components : _threshold[%],_min_area[%]>=0,_is_high_connectivity={ 0 | 1 },\ 13719# _output_type={ 0=crop | 1=segmentation | 2=coordinates } 13720#@cli : Autocrop and extract connected components in selected images, according to a mask given as the last channel of 13721#@cli : each of the selected image (e.g. alpha-channel). 13722#@cli : Default values: 'threshold=0%', 'min_area=0.1%', 'is_high_connectivity=0' and 'output_type=1'. 13723#@cli : $ 256,256 noise 0.1,2 eq 1 dilate_circ 20 label_fg 0,1 normalize 0,255 +neq 0 *[-1] 255 append c \ 13724# +autocrop_components , 13725autocrop_components : skip ${1=0%} check "${2=0.1%}>=0 && isbool(${3=0}) && isint(${4=1}) && $4>=0 && $4<=2" 13726 e[^-1] "Autocrop connected components from image$?, with threshold $1, minimal area $2, "\ 13727 ${arg\ 1+$3,low,high}" connectivity "\ 13728 "and output type set to '"${arg\ 1+$4,crop,segmentation,coordinates}"'.\n" 13729 repeat $! l[$>] 13730 min_area={max(1,round(if(${is_percent\ $2},$2*w*h,$2)))} 13731 +channels 100% >. $1 area_fg. 0,$3 >=. $min_area # Discard background and small objects. 13732 +area. 0,1 <. $min_area -|[-2,-1] label_fg. 0,1 # Fill small holes in objects. 13733 13734 # Extract detected objects. 13735 N={iM} repeat iM 13736 n={1+$>} 13737 e[] "\r > "$n/$N 13738 rprogress {100*$n/$N} 13739 +==[1] $n +*[0,-1] rm.. 13740 if $4==0 coords=${autocrop_coords.\ auto} rm. +z[0] $coords 13741 elif $4==1 autocrop. 13742 else coords=${autocrop_coords.\ auto} rm. ($coords) y. 13743 fi 13744 done 13745 rm[0,1] 13746 if !$! 0 fi 13747 if $4==2 a x fi 13748 endl done 13749 13750#@cli autocrop_seq : value1,value2,... | auto 13751#@cli : Autocrop selected images using the crop geometry of the last one by specified vector-valued intensity, 13752#@cli : or by automatic guessing the cropping value. 13753#@cli : Default value: auto mode. 13754#@cli : $ image.jpg +fill[-1] 0 ellipse[-1] 50%,50%,30%,20%,0,1,1 autocrop_seq 0 13755autocrop_seq : skip ${1=auto} 13756 e[^-1] "Auto-crop image$? using crop geometry of last image by vector '$*'." 13757 if !$! return fi 13758 is_auto={['"$1"']=='auto'} 13759 if $!==1 _autocrop$is_auto ${1--1} return fi 13760 coords=${autocrop_coords.\ ${1--1}} 13761 x0={arg(1,$coords)} y0={arg(2,$coords)} z0={arg(3,$coords)} 13762 x1={arg(4,$coords)} y1={arg(5,$coords)} z1={arg(6,$coords)} 13763 if $x0>$x1" || "$y0>$y1" || "$z0>$z1 i[0--2] 0 rm[1--1:2] 13764 else z $x0,$y0,$z0,$x1,$y1,$z1 13765 fi 13766 13767#@cli channels : c0[%],_c1[%] 13768#@cli : Keep only specified channels of selected images. 13769#@cli : Dirichlet boundary is used when specified channels are out of range. 13770#@cli : Default value: 'c1=c0'. 13771#@cli : $ image.jpg channels 0,1 13772#@cli : $ image.jpg luminance channels 0,2 13773channels : skip ${2=$1} 13774 e[^-1] "Keep channels $1...$2 of image$?." 13775 z 0,0,0,$1,100%,100%,100%,$2 13776 13777#@cli columns : x0[%],_x1[%] 13778#@cli : Keep only specified columns of selected images. 13779#@cli : Dirichlet boundary is used when specified columns are out of range. 13780#@cli : Default value: 'x1=x0'. 13781#@cli : $ image.jpg columns -25%,50% 13782columns : skip ${2=$1} 13783 e[^-1] "Keep columns $1...$2 of image?." 13784 z $1,$2 13785 13786#@cli z : eq. to 'crop'. : (+) 13787 13788#@cli crop : x0[%],x1[%],_boundary_conditions : x0[%],y0[%],x1[%],y1[%],_boundary_conditions : \ 13789# x0[%],y0[%],z0[%],x1[%],y1[%],z1[%],_boundary_conditions : \ 13790# x0[%],y0[%],z0[%],c0[%],x1[%],y1[%],z1[%],c1[%],_boundary_conditions : (+) 13791#@cli : Crop selected images with specified region coordinates. 13792#@cli : (eq. to 'z').\n 13793#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13794#@cli : Default value: 'boundary_conditions=0'. 13795#@cli : $ image.jpg +crop -230,-230,280,280,1 crop[0] -230,-230,280,280,0 13796#@cli : $ image.jpg crop 25%,25%,75%,75% 13797 13798#@cli diagonal 13799#@cli : Transform selected vectors as diagonal matrices. 13800#@cli : $ 1,10,1,1,'y' +diagonal 13801diagonal : 13802 e[^-1] "Transform vector$? as diagonal matrix." 13803 y repeat $! r[$>] {$>,h+1},100%,1,1,0 r[$>] {$>,h},100%,1,1,-1 done 13804 13805# downsize_aliased : 100<=factor<=0 13806# Downsize selected images with a specific algorithm to better render anti-aliased rendering 13807# over transparent background (from aliased transparent images, manage transparent border pixels with more care). 13808downsize_aliased : check "${1=50}>=0 && $1<=100" 13809 if $1==100 return elif !$1 r 1,1,1,100%,2 return fi 13810 N={ceil(1+100/$1)} 13811 repeat $! l[$>] 13812 split_opacity 13813 if $!==1 continue fi 13814 +dilate.. $N +==.. 0 13815 j[0] ..,0,0,0,0,1,. rm[-2,-1] 13816 a c 13817 r $1%,$1%,$1%,100%,2 13818 endl done 13819 13820#@cli elevate : _depth,_is_plain={ 0 | 1 },_is_colored={ 0 | 1 } 13821#@cli : Elevate selected 2D images into 3D volumes. 13822#@cli : Default values: 'depth=64', 'is_plain=1' and 'is_colored=1'. 13823elevate : check "${1=64}>0" skip ${2=1},${3=1} 13824 e[^-1] "Elevate 2D image$? into $1-slices volume(s)." 13825 r 100%,100%,1,100% 13826 repeat $! l[$>] nm={0,n} 13827 +norm 100%,100%,$1,{if($3,{0,s},1)} 13828 m={-2,im} d={-2,iM-$m} 13829 repeat $1 13830 if $2 +>=[1] {$m+$d*($>+1)/$1} 13831 else +ir[1] {$m+$d*$>/$1},{$m+$d*($>+1)/$1} 13832 fi 13833 r. 100%,100%,1,.. if $3 *. [0] fi 13834 j.. .,0,0,$> rm. 13835 done 13836 rm[0,1] nm $nm endl done 13837 13838#@cli expand_x : size_x>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 13839#@cli : Expand selected images along the x-axis. 13840#@cli : Default value: 'boundary_conditions=1'. 13841#@cli : $ image.jpg expand_x 30,0 13842expand_x : check "$1>=0 && ${2=1}>=0 && $2<=3" 13843 e[^-1] "Expand image$? along the x-axis with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 13844 boundary conditions." 13845 repeat $! r[$>] {$>,w+2*$1},100%,100%,100%,0,$2,0.5,0.5,0.5 done 13846 13847#@cli expand_xy : size>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 13848#@cli : Expand selected images along the xy-axes. 13849#@cli : Default value: 'boundary_conditions=1'. 13850#@cli : $ image.jpg expand_xy 30,0 13851expand_xy : check "$1>=0 && ${2=1}>=0 && $2<=3" 13852 e[^-1] "Expand image$? along the xy-axes with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 13853 boundary conditions." 13854 repeat $! r[$>] {$>,w+2*$1},{$>,h+2*$1},100%,100%,0,$2,0.5,0.5,0.5 done 13855 13856#@cli expand_xyz : size>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 13857#@cli : Expand selected images along the xyz-axes. 13858#@cli : Default value: 'boundary_conditions=1'. 13859expand_xyz : check "$1>=0 && ${2=1}>=0 && $2<=3" 13860 e[^-1] "Expand image$? along the xyz-axes with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 13861 boundary conditions." 13862 repeat $! r[$>] {$>,w+2*$1},{$>,h+2*$1},{$>,d+2*$1},100%,0,$2,0.5,0.5,0.5 done 13863 13864#@cli expand_y : size_y>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 13865#@cli : Expand selected images along the y-axis. 13866#@cli : Default value: 'boundary_conditions=1'. 13867#@cli : $ image.jpg expand_y 30,0 13868expand_y : check "$1>=0 && ${2=1}>=0 && $2<=3" 13869 e[^-1] "Expand image$? along the y-axis with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 13870 boundary conditions." 13871 repeat $! r[$>] 100%,{$>,h+2*$1},100%,100%,0,$2,0.5,0.5,0.5 done 13872 13873#@cli expand_z : size_z>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 13874#@cli : Expand selected images along the z-axis. 13875#@cli : Default value: 'boundary_conditions=1'. 13876expand_z : check "$1>=0 && ${2=1}>=0 && $2<=3" 13877 e[^-1] "Expand image$? along the z-axis with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 13878 boundary conditions." 13879 repeat $! r[$>] 100%,100%,{$>,d+2*$1},100%,0,$2,0.5,0.5,0.5 done 13880 13881#@cli extract : "condition",_output_type={ 0=xyzc-coordinates | 1=xyz-coordinates | 2=scalar-values | 3=vector-values } 13882#@cli : Extract a list of coordinates or values from selected image, where 13883#@cli : specified mathematical condition holds. 13884#@cli : For N coordinates matching, result is a 1xNx1x4 image. 13885#@cli : Default values: 'output_type=0'. 13886#@cli : $ sp lena +extract "norm(I)>128",3 13887extract : check "isin(${2=0},0,1,2,3)" 13888 s0,s1,s2,s3=xyzc-coordinates,xyz-coordinates,scalar-values,vector-values 13889 e[^-1] "Extract "$s$2" from image$? verifying condition '$1'." 13890 str=">begin(run('1,32,1,',arg(1+$2,4,3,1,s)));($1)?(" 13891 if $2==0 str.="da_push([x,y,z,c]));i" 13892 elif $2==1 str.="da_push([x,y,z]));I" 13893 elif $2==2 str.="da_push(i));i" 13894 else str.="da_push(I));I" 13895 fi 13896 str.=";end(resize(#-1,1,da_size(),1,s(#-1),0))" 13897 repeat $! nm={$>,n} eval[$>] $str nm. $nm rv[$>,-1] rm. done 13898 13899#@cli extract_region : [label_image],_extract_xyz_coordinates={ 0 | 1 },_label_1,...,_label_M 13900#@cli : Extract all pixels of selected images whose corresponding label in '[label_image]' is equal to 'label_m', 13901#@cli : and output them as M column images. 13902#@cli : Default value: 'extract_xyz_coordinates=0'. 13903#@cli : $ image.jpg +blur 3 quantize. 4,0 +extract_region[0] [1],0,1,3 13904extract_region : check ${"is_image_arg $1"}" && isnum(${2=0})" 13905 if $#<3 e[0--3] "Extract pixels of image$? for labels [] in image $1, with"${"arg 1+!!$2,out"}" coordinates 13906 -> no labels provided, ignoring." return fi 13907 e[^-1] "Extract pixels of image$? for labels {${3--1}} in image $1, with"${"arg 1+!!$2,out"}" coordinates." 13908 pass$1 mv. 0 repeat $!-1 l[0,{1+$<}] nm={n} 13909 1,16,1,{s+($2?3:0)} if $#>3 .x{$#-3} fi 13910 f[0] "> 13911 begin( 13912 const N = iM + 1; # Number of labels 13913 R = [ ${3--1} ]; # Requested labels 13914 hash = vectorN(0); # Correspondence table 13915 repeat (size(R),k, hash[R[k]] = k + 2); 13916 ); 13917 (ind = hash[i])>0?( 13918 $2?da_push(#ind,[ I(#1),x,y,z ]):da_push(#ind,I(#1)); 13919 ); i; 13920 end( 13921 repeat (l - 2,k, resize(#k + 2,1,da_size(#k + 2),1,-100,0)) 13922 )" 13923 rm[1] nm $nm 13924 endl done rm[0] 13925 13926#@cli montage : "_layout_code",_montage_mode={ 0<=centering<=1 | 2<=scale+2<=3 },\ 13927# _output_mode={ 0=single layer | 1=multiple layers },"_processing_command" 13928#@cli : Create a single image montage from selected images, according to specified layout code : 13929#@cli : - 'X' to assemble all images using an automatically estimated layout. 13930#@cli : - 'H' to assemble all images horizontally. 13931#@cli : - 'V' to assemble all images vertically. 13932#@cli : - 'A' to assemble all images as an horizontal array. 13933#@cli : - 'B' to assemble all images as a vertical array. 13934#@cli : - 'Ha:b' to assemble two blocks 'a' and 'b' horizontally. 13935#@cli : - 'Va:b' to assemble two blocks 'a' and 'b' vertically. 13936#@cli : - 'Ra' to rotate a block 'a' by 90 deg. ('RRa' for 180 deg. and 'RRRa' for 270 deg.). 13937#@cli : - 'Ma' to mirror a block 'a' along the X-axis ('MRRa' for the Y-axis). 13938#@cli : A block 'a' can be an image index (treated periodically) or a nested layout expression 'Hb:c','Vb:c','Rb' or 13939#@cli : 'Mb' itself. 13940#@cli : For example, layout code 'H0:V1:2' creates an image where image [0] is on the left, and images [1] and [2] 13941#@cli : vertically packed on the right. 13942#@cli : Default values: 'layout_code=X', 'montage_mode=2', output_mode='0' and 'processing_command=""'. 13943#@cli : $ image.jpg sample ? +plasma[0] shape_cupid 256 normalize 0,255 frame 3,3,0 frame 10,10,255 to_rgb \ 13944# +montage A +montage[^-1] H1:V0:VH2:1H0:3 13945montage : check "isnum(${2=2}) && $2>=0 && $2<=3" skip "${1=X}",${3=0},"${4=}" 13946 if $2<=1 e[0--3] "Create aligned montage from image$?, with layout code '$1' and centering $2." 13947 else e[0--3] "Create scaled montage from image$?, with layout code '$1' and scale "{$2-2}"." 13948 fi 13949 to_colormode 0 13950 13951 # Manage automatic layout. 13952 if lowercase('"$1"')=='x' +l 13953 repeat $! nm[$>] $> done 13954 repeat $!-1 13955 if {-2,w>h}" && "w>h mode=V # Both landscape. 13956 elif {-2,h>w}" && "h>w mode=H # Both portrait. 13957 elif {-2,w>h}" && "h>w # Landscape - portrait. 13958 if {-2,h/w}<(w/h) mode=V else mode=H fi 13959 else # Portrait - landscape. 13960 if {-2,w/h}<(h/w) mode=H else mode=V fi 13961 fi 13962 name=$mode{-2,n}:{n} 13963 montage[-2,-1] $mode,$2 13964 mv. 0 nm[0] $name 13965 done 13966 layout={0,n} 13967 rm endl montage $layout,$2,$3,"$4" 13968 13969 else # Non-automatic layout. 13970 13971 # Format and check validity of layout code. 13972 N=$! 13973 l[] _scode="$1" _mode=$2 13974 if lowercase('"$1"')=='h' if $N>1 {$N-1},1,1,1,-1 $N,1,1,1,x a x y else return fi # Simple horizontal montage. 13975 elif lowercase('"$1"')=='v' if $N>1 {$N-1},1,1,1,-2 $N,1,1,1,x a x y else return fi # Simple vertical montage. 13976 elif s=lowercase('"$1"');s=='a'||s=='b' # Montage as an array. 13977 if $N<2 return fi 13978 nr={round(sqrt($N))} nc={round($N/$nr,1,1)} # Horizontal array. 13979 if lowercase('"$1"')=='b' n=$nr nr=$nc nc=$n fi # Vertical array. 13980 $N,1,1,1,x s x,-{round(w/$nr,1,1)} repeat $! l[$>] if w>1 i[0] {w-1},1,1,1,-1 a x fi endl done a x 13981 if $nr>1 i[0] {$nr-1},1,1,1,-2 a x fi y 13982 else # Other complex montage. 13983 ('"$1"') f "if(i==72 || i==104,-1, 13984 if(i==86 || i==118,-2, 13985 if(i==82 || i==114,-3, 13986 if(i==77 || i==109,-4, 13987 if(i>=48 && i<=57,i-48,-5)))))" 13988 s +,-1 s +,-2 s +,-3 s +,-4 s +,-5 13989 repeat $! l[$>] if im>=0 ++. 48 =.. {t} rm. rows 0 fi endl done a y discard -5 13990 fi 13991 f 'if(i<0,i,i%$N)' 13992 endl 13993 if $!==$N rm return fi # Empty layout code. 13994 nm[^-1] 0 repeat h c={i[$>]} # Duplicate multiple references. 13995 if $c>=0 if {$c,n} i.. [$c] i={$!-2} =. $i,0,$> ref$i=$c else nm[$c] 1 ref$c=$c fi fi 13996 done 13997 _code={^} _lcode={narg($_code)} rm. 13998 13999 # Determine image positions and sizes. 14000 N=$! repeat $N ($>,0,0,{$>,w},{$>,h},0,0,0) done 14001 l[$N--1] _p=1 k[${-_montage}] w={i[3]} h={i[4]} f 'if(i(0,y)<0,-1,i)' discard -1 y r 8,{h/8},1,1,-1 14002 onfail error[0--3] "Too many input images." 14003 endl 14004 14005 # Render montage. 14006 if narg("$4") m "__montage : $4 k[0]" 14007 else m "__montage : if $""7%2 mirror x fi if $""8%2 mirror y fi rotate {90*$""6} 14008 r {max(1,round($""4,1,1))},{max(1,round($""5,1,1))},1,100%,3" 14009 fi 14010 14011 s=${max_s[^-1]} 14012 repeat h 14013 i={i(0,$>)} xi={i(1,$>)} yi={i(2,$>)} wi={i(3,$>)} hi={i(4,$>)} ai={i(5,$>)} mxi={i(6,$>)} myi={i(7,$>)} 14014 if $3||!$> i.. $w,$h,1,$s fi 14015 __montage[$i] ${ref$i},$xi,$yi,{max(1,$wi)},{max(1,$hi)},$ai,$mxi,$myi 14016 j.. [$i],$xi,$yi 14017 done 14018 um __montage 14019 rm[0-{$N-1},-1] 14020 14021 fi 14022 nm "[Montage '$1']" 14023 14024_montage : 14025 if $_p>$_lcode error "Command 'montage': Incomplete layout code '"$_scode"'." fi 14026 c={arg($_p,$_code)} 14027 if $c>=0 _p+=1 u $c # Single index. 14028 elif $c==-4 # Mirror. 14029 _p+=1 l=${-_montage} f[$l] 'a=i(5,y)%2;if((x==7&&a)||(x==6&&!a),!i,if(x==1,i(3,0)-i(3,y)-i,i))' u $l 14030 elif $c==-3 # Rotation. 14031 _p+=1 l=${-_montage} l[$l] s x +[2] [4] rv[1,2] *[1] -1 +[1] {4,@0} rv[3,4] +[5] 1 a x endl u $l 14032 else # Merge. 14033 _p+=1 14034 l=${-_montage} lw={$l,@3} lh={$l,@4} 14035 r=${-_montage} rw={$r,@3} rh={$r,@4} 14036 14037 if $c==-1 # Horizontal merge. 14038 if $_mode<2 14039 h={max($lh,$rh)} 14040 +[$l] '0,0,{($h-$lh)*min(1,$_mode)},0,0,0,0,0' 14041 +[$r] '0,$lw,{($h-$rh)*min(1,$_mode)},0,0,0,0,0' 14042 else 14043 h={($_mode-2)*max($lh,$rh)+(3-$_mode)*min($lh,$rh)} 14044 lf={$h/$lh} rf={$h/$rh} lw={$lw*$lf} rw={$rw*$rf} 14045 *[$l] '1,$lf,$lf,$lf,$lf,1,1,1' *[$r] '1,$rf,$rf,$rf,$rf,1,1,1' +[$r] '0,$lw,0,0,0,0,0,0' 14046 fi 14047 i[$l] (-1,0,0,{$lw+$rw},$h,0,0,0) a[$l,{$l+1}] y a[$l] [$r],y r[$r] 1,1,1,1,0 14048 14049 else # Vertical merge. 14050 if $_mode<2 14051 w={max($lw,$rw)} 14052 +[$l] '0,{($w-$lw)*min(1,$_mode)},0,0,0,0,0,0' 14053 +[$r] '0,{($w-$rw)*min(1,$_mode)},$lh,0,0,0,0,0' 14054 else 14055 w={($_mode-2)*max($lw,$rw)+(3-$_mode)*min($lw,$rw)} 14056 lf={$w/$lw} rf={$w/$rw} lh={$lh*$lf} rh={$rh*$rf} 14057 *[$l] '1,$lf,$lf,$lf,$lf,1,1,1' *[$r] '1,$rf,$rf,$rf,$rf,1,1,1' +[$r] '0,0,$lh,0,0,0,0,0' 14058 fi 14059 i[$l] (-1,0,0,$w,{$lh+$rh},0,0,0) a[$l,{$l+1}] y a[$l] [$r],y r[$r] 1,1,1,1,0 14060 fi 14061 u $l 14062 fi 14063 14064#@cli mirror : { x | y | z }...{ x | y | z } : (+) 14065#@cli : Mirror selected images along specified axes. 14066#@cli : $ image.jpg +mirror y +mirror[0] c 14067#@cli : $ image.jpg +mirror x +mirror y append_tiles 2,2 14068 14069#@cli permute : permutation_string : (+) 14070#@cli : Permute selected image axes by specified permutation. 14071#@cli : 'permutation' is a combination of the character set {x|y|z|c}, 14072#@cli : e.g. 'xycz', 'cxyz', ... 14073#@cli : $ image.jpg permute yxzc 14074 14075#@cli r : eq. to 'resize'. : (+) 14076 14077#@cli resize : {[image_w] | width>0[%]},_{[image_h] | height>0[%]},_{[image_d] | depth>0[%]},\ 14078# _{[image_s] | spectrum>0[%]},_interpolation,_boundary_conditions,_ax,_ay,_az,_ac : (+) 14079#@cli : Resize selected images with specified geometry. 14080#@cli : (eq. to 'r').\n 14081#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14082# 4=grid | 5=bicubic | 6=lanczos }. 14083#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14084#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14085#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14086#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14087#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0 or 4' 14088#@cli : (set to '0' by default, must be defined in range [0,1]). 14089#@cli : Default values: 'interpolation=1', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14090#@cli : $ image.jpg +resize[-1] 256,128,1,3,2 +resize[-1] 120%,120%,1,3,0,1,0.5,0.5 \ 14091# +resize[-1] 120%,120%,1,3,0,0,0.2,0.2 +resize[-1] [0],[0],1,3,4 14092 14093#@cli ri : eq. to 'resize_as_image'. 14094ri : skip "${2=1},${3=0},${4=0},${5=0},${6=0},${7=0}" # Faster than the non-shortcut version of the command 14095 pass$1 r[^-1] .,.,.,.,${2--1} rm. 14096 14097#@cli resize_as_image : [reference],_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14098#@cli : Resize selected images to the geometry of specified [reference] image. 14099#@cli : (eq. to 'ri'). 14100#@cli : Default values: 'interpolation=1', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14101#@cli : $ image.jpg sample duck +resize_as_image[-1] [-2] 14102resize_as_image : check ${"is_image_arg $1"}" && isint(${2=1}) && $2>=-1 && $2<=6 && "\ 14103 "isint(${3=0}) && $3>=0 && $3<=3 && isnum(${4=0}) && isnum(${5=0}) && isnum(${6=0}) && isnum(${7=0})" 14104 pass$1 r[^-1] .,.,.,.,${2--1} rm. 14105 14106#@cli resize_mn : width[%]>=0,_height[%]>=0,_depth[%]>=0,_B_value,_C_value 14107#@cli : Resize selected images with Mitchell-Netravali filter (cubic). 14108#@cli : For details about the method, see: <https://de.wikipedia.org/wiki/Mitchell-Netravali-Filter>. 14109#@cli : Default values: 'height=100%', 'depth=100%', 'B=0.3333' and 'C=0.3333'. 14110#@cli : $ image.jpg resize2dx 32 resize_mn 800%,800% 14111resize_mn : check "${2=100%}>=0 && ${3=100%}>=0" skip "${4=0.333},${5=0.333}" 14112 e[^-1] "Resize image$? to $1x$2x$3 using Mitchell-Netravali filter (B=$4, C=$5)." 14113 lib="const B = $4; const C = $5; const boundary = 1; const interp = 0; 14114 mn(P0,P1,P2,P3,d) = ( ( (-B/6-C)*P0 + (-3*B/2-C+2)*P1 + (3*B/2+C-2)*P2 + (B/6+C)*P3 )*d^3 14115 + ( (B/2+2*C)*P0 + (2*B+C-3)*P1 + (-5*B/2-2*C+3)*P2 -C*P3)*d^2 14116 + ( (-B/2-C)*P0 + (B/2+C)*P2)*d 14117 + B/6*P0 + (-B/3+1)*P1 + B/6*P2);" 14118 repeat $! l[$>] nm={n} 14119 nw={${"is_percent $1"}?max(1,round($1*w)):round($1)} 14120 nh={${"is_percent $2"}?max(1,round($2*h)):round($2)} 14121 nd={${"is_percent $3"}?max(1,round($3*d)):round($3)} 14122 if !$nw" || "!$nh" || "!$nd rm 0 14123 elif !w rm $nw,$nh,$nd,1 14124 else 14125 if w==1||$nw<w r $nw,100%,100%,100%,{w==1?1:2} 14126 elif $nw>w 14127 $nw,100%,100%,100%,${lib}"X = x*(w#-1-1)/(w-1); d = X - int(X); P0 = I(#-1,X-1); P1 = I(#-1,X); 14128 P2 = I(#-1,X+1); P3 = I(#-1,X+2); mn(P0,P1,P2,P3,d);" k. 14129 fi 14130 if h==1||$nh<h 14131 r 100%,$nh,100%,100%,{h==1?1:2} 14132 elif $nh!=h 14133 100%,$nh,100%,100%,${lib}"Y = y*(h#-1-1)/(h-1); d = Y - int(Y); P0 = I(#-1,x,Y-1); P1 = I(#-1,x,Y); 14134 P2 = I(#-1,x,Y+1); P3 = I(#-1,x,Y+2); mn(P0,P1,P2,P3,d);" k. 14135 fi 14136 if d==1" || "$nd<d 14137 r 100%,100%,$nd,100%,{d==1?1:2} 14138 elif $nd!=d 14139 100%,100%,$nd,100%,${lib}"Z = z*(d#-1-1)/(d-1); d = Z - int(Z); P0 = I(#-1,x,y,Z-1); P1 = I(#-1,x,y,Z); 14140 P2 = I(#-1,x,y,Z+1); P3 = I(#-1,x,y,Z+2); mn(P0,P1,P2,P3,d);" k. 14141 fi 14142 fi 14143 nm $nm 14144 endl done 14145 14146#@cli resize_pow2 : _interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14147#@cli : Resize selected images so that each dimension is a power of 2. 14148#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14149# 4=grid | 5=bicubic | 6=lanczos }. 14150#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14151#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14152#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14153#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14154#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14155#@cli : (set to '0' by default, must be defined in range [0,1]). 14156#@cli : Default values: 'interpolation=0', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14157#@cli : $ image.jpg +resize_pow2[-1] 0 14158resize_pow2 : check "isint(${1=0}) && $1>=-1 && $1<=6" skip ${2=0},${3=0},${4=0},${5=0},${6=0} 14159 e[^-1] "Resize image$? so that each dimension is a power of 2." 14160 repeat $! 14161 r[$>] {$>,2^(round(log2(w),1,1))},{$>,2^(round(log2(h),1,1))},{$>,2^(round(log2(d),1,1))},100%,${1-6} 14162 done 14163 14164#@cli rr2d : eq. to 'resize_ratio2d'. 14165rr2d : 14166 _gmic_s="$?" v + _resize_ratio2d $* 14167 14168#@cli resize_ratio2d : width>0,height>0,_mode={ 0=inside | 1=outside | 2=padded },0=<_interpolation<=6 14169#@cli : Resize selected images while preserving their aspect ratio. 14170#@cli : (eq. to 'rr2d'). 14171#@cli : Default values: 'mode=0' and 'interpolation=6'. 14172resize_ratio2d : 14173 _gmic_s="$?" v + _$0 $* 14174 14175_resize_ratio2d : check "$1>0 && $2>0 && ${3=0}>=0 && $3<=2 && ${4=6}>=0 && $4<=6" 14176 e[0--3] "Resize 2D image"$_gmic_s" to $1x$2 with ratio-"${arg\ 1+$3,inside,outside,padded}\ 14177 " mode and interpolation type $4." 14178 repeat $! 14179 ratio={$>,if($3==1,max($1/w,$2/h),min($1/w,$2/h))} 14180 r[$>] {$>,[max(1,round(w*$ratio)),max(1,round(h*$ratio))]},100%,100%,$4 14181 done 14182 if $3==2 r $1,$2,100%,100%,0,0,0.5,0.5 fi 14183 14184#@cli r2din : eq. to 'resize2din' 14185r2din : 14186 _gmic_s="$?" v + _resize2din $* 14187 14188#@cli resize2din : width[%]>0,_height[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14189#@cli : Resize selected images so the size is not larger than 'width'x'height' while preserving 2D ratio. 14190#@cli : (eq. to r2din).\n 14191#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14192# 4=grid | 5=bicubic | 6=lanczos }. 14193#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14194#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14195#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14196#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14197#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14198#@cli : (set to '0' by default, must be defined in range [0,1]). 14199#@cli : Default values: 'height=100%', 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14200#@cli : $ image.jpg +resize2din 100,100 append x 14201resize2din : 14202 _gmic_s="$?" v + _$0 $* 14203 14204_resize2din : check "$1>0 && ${2=100%}>0 && ${3=3}>=0 && $3<=6 && ${4=0}>=0 && $4<=3 && "\ 14205 "${5=0}>=0 && $5<=1 && ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1 && ${8=0}>=0 && $8<=1" 14206 e[0--3] "Resize image"$_gmic_s" so the size is not larger than $1x$2, while preserving 2D ratio." 14207 eval "repeat (l,k, 14208 W = "${"is_percent $1"}"?w#k*$1:$1; 14209 H = "${"is_percent $2"}"?h#k*$2:$2; 14210 dims = round(min(W/w#k,H/h#k)*[w#k,h#k]); 14211 resize(#k,max(1,dims[0]),max(1,dims[1]),d#k,s#k,${3-8}); 14212 )" 14213 14214#@cli r3din : eq. to 'resize3din' 14215r3din : 14216 _gmic_s="$?" v + _resize3din $* 14217 14218#@cli resize3din : width[%]>0,_height[%]>0,_depth[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14219#@cli : Resize selected images so the size is not larger than 'width'x'height'x'depth' while preserving 3D ratio. 14220#@cli : (eq. to r3din).\n 14221#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14222# 4=grid | 5=bicubic | 6=lanczos }. 14223#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14224#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14225#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14226#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14227#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14228#@cli : (set to '0' by default, must be defined in range [0,1]). 14229#@cli : Default values: 'height=100%', 'depth=100%', 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14230resize3din : 14231 _gmic_s="$?" v + _$0 $* 14232 14233_resize3din : check "$1>0 && ${2=100%}>0 && ${3=100%}>0 && ${4=3}>=0 && $4<=6 && ${5=0}>=0 && $5<=3 && "\ 14234 "${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1 && ${8=0}>=0 && $8<=1 && ${9=0}>=0 && $9<=1" 14235 e[0--3] "Resize image"$_gmic_s" so the size is not larger than $1x$2x$3, while preserving 3D ratio." 14236 eval "repeat (l,k, 14237 W = "${"is_percent $1"}"?w#k*$1:$1; 14238 H = "${"is_percent $2"}"?h#k*$2:$2; 14239 D = "${"is_percent $3"}"?d#k*$3:$3; 14240 dims = round(min(W/w#k,H/h#k,D/d#k)*[w#k,h#k,d#k]); 14241 resize(#k,max(1,dims[0]),max(1,dims[1]),max(1,dims[2]),s#k,${4-9}); 14242 )" 14243 14244#@cli r2dout : eq. to 'resize2dout' 14245r2dout : 14246 _gmic_s="$?" v + _resize2dout $* 14247 14248#@cli resize2dout : width[%]>0,_height[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14249#@cli : Resize selected images so the size is not smaller than 'width'x'height' while preserving 2D ratio. 14250#@cli : (eq. to r2dout).\n 14251#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14252# 4=grid | 5=bicubic | 6=lanczos }. 14253#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14254#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14255#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14256#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14257#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14258#@cli : (set to '0' by default, must be defined in range [0,1]). 14259#@cli : Default values: 'height=100%', 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14260#@cli : $ image.jpg +resize2dout 100,100 append x 14261resize2dout : 14262 _gmic_s="$?" v + _$0 $* 14263 14264_resize2dout : check "$1>0 && ${2=100%}>0 && ${3=3}>=0 && $3<=6 && ${4=0}>=0 && $4<=3 && "\ 14265 "${5=0}>=0 && $5<=1 && ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1 && ${8=0}>=0 && $8<=1" 14266 e[0--3] "Resize image"$_gmic_s" so the size is not larger than $1x$2, while preserving 2D ratio." 14267 eval "repeat (l,k, 14268 W = "${"is_percent $1"}"?w#k*$1:$1; 14269 H = "${"is_percent $2"}"?h#k*$2:$2; 14270 dims = round(max(W/w#k,H/h#k)*[w#k,h#k]); 14271 resize(#k,max(1,dims[0]),max(1,dims[1]),d#k,s#k,${3-8}); 14272 )" 14273 14274#@cli r3dout : eq. to 'resize3dout' 14275r2dout : 14276 _gmic_s="$?" v + _resize3dout $* 14277 14278#@cli resize3dout : width[%]>0,_height[%]>0,_depth[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14279#@cli : Resize selected images so the size is not smaller than 'width'x'height'x'depth' while preserving 3D ratio. 14280#@cli : (eq. to r3dout).\n 14281#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14282# 4=grid | 5=bicubic | 6=lanczos }. 14283#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14284#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14285#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14286#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14287#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14288#@cli : (set to '0' by default, must be defined in range [0,1]). 14289#@cli : Default values: 'height=100%', 'depth=100%', 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14290resize3dout : 14291 _gmic_s="$?" v + _$0 $* 14292 14293_resize3dout : check "$1>0 && ${2=100%}>0 && ${3=100%}>0 && ${4=3}>=0 && $4<=6 && ${5=0}>=0 && $5<=3 && "\ 14294 "${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1 && ${8=0}>=0 && $8<=1 && ${9=0}>=0 && $9<=1" 14295 e[0--3] "Resize image"$_gmic_s" so the size is not larger than $1x$2x$3, while preserving 3D ratio." 14296 eval "repeat (l,k, 14297 W = "${"is_percent $1"}"?w#k*$1:$1; 14298 H = "${"is_percent $2"}"?h#k*$2:$2; 14299 D = "${"is_percent $3"}"?d#k*$3:$3; 14300 dims = round(max(W/w#k,H/h#k,D/d#k)*[w#k,h#k,d#k]); 14301 resize(#k,max(1,dims[0]),max(1,dims[1]),max(1,dims[2]),s#k,${4-9}); 14302 )" 14303 14304#@cli r2dx : eq. to 'resize2dx'. 14305r2dx : 14306 _gmic_s="$?" v + _resize2dx $* 14307 14308#@cli resize2dx : width[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14309#@cli : Resize selected images along the x-axis, while preserving 2D ratio. 14310#@cli : (eq. to 'r2dx').\n 14311#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14312# 4=grid | 5=bicubic | 6=lanczos }. 14313#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14314#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14315#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14316#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14317#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14318#@cli : (set to '0' by default, must be defined in range [0,1]). 14319#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14320#@cli : $ image.jpg +resize2dx 100,2 append x 14321resize2dx : 14322 _gmic_s="$?" v + _$0 $* 14323 14324_resize2dx : check "$1>0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 14325 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 14326 e[0--3] "Resize 2D image"$_gmic_s" to $1 pixels along the x-axis, while preserving 2D ratio." 14327 repeat $! l[$>] 14328 size={if(${is_percent\ $1},$1*w,$1)} 14329 r {max(1,$size)},{max(1,h*$size/w)},100%,100%,${2-7} 14330 endl done 14331 14332#@cli r2dy : eq. to 'resize2dy'. 14333r2dy : 14334 _gmic_s="$?" v + _resize2dy $* 14335 14336#@cli resize2dy : height[%]>=0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14337#@cli : Resize selected images along the y-axis, while preserving 2D ratio. 14338#@cli : (eq. to 'r2dy').\n 14339#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14340# 4=grid | 5=bicubic | 6=lanczos }. 14341#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14342#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14343#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14344#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14345#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14346#@cli : (set to '0' by default, must be defined in range [0,1]). 14347#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14348#@cli : $ image.jpg +resize2dy 100,2 append x 14349resize2dy : 14350 _gmic_s="$?" v + _$0 $* 14351 14352_resize2dy : check "$1>=0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 14353 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 14354 e[0--3] "Resize 2D image"$_gmic_s" to $1 pixels along the y-axis, while preserving 2D ratio." 14355 repeat $! l[$>] 14356 size={if(${is_percent\ $1},$1*h,$1)} 14357 r {max(1,w*$size/h)},{max(1,$size)},100%,100%,${2-7} 14358 endl done 14359 14360#@cli r3dx : eq. to 'resize3dx'. 14361r3dx : 14362 _gmic_s="$?" v + _resize3dx $* 14363 14364#@cli resize3dx : width[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14365#@cli : Resize selected images along the x-axis, while preserving 3D ratio. 14366#@cli : (eq. to 'r3dx').\n 14367#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14368# 4=grid | 5=bicubic | 6=lanczos }. 14369#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14370#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14371#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14372#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14373#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14374#@cli : (set to '0' by default, must be defined in range [0,1]). 14375#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14376resize3dx : 14377 _gmic_s="$?" v + _$0 $* 14378 14379_resize3dx : check "$1>0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 14380 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 14381 e[0--3] "Resize 3D image"$_gmic_s" to $1 pixels along the x-axis, while preserving 3D ratio." 14382 repeat $! l[$>] 14383 size={if(${is_percent\ $1},$1*w,$1)} 14384 r {max(1,$size)},{max(1,h*$size/w)},{max(1,d*$size/w)},100%,${2-7} 14385 endl done 14386 14387#@cli r3dy : eq. to 'resize3dy'. 14388r3dy : 14389 _gmic_s="$?" v + _resize3dy $* 14390 14391#@cli resize3dy : height[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14392#@cli : Resize selected images along the y-axis, while preserving 3D ratio. 14393#@cli : (eq. to 'r3dy').\n 14394#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14395# 4=grid | 5=bicubic | 6=lanczos }. 14396#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14397#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14398#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14399#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14400#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14401#@cli : (set to '0' by default, must be defined in range [0,1]). 14402#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14403resize3dy : 14404 _gmic_s="$?" v + _$0 $* 14405 14406_resize3dy : check "$1>0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 14407 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 14408 e[0--3] "Resize 3D image"$_gmic_s" to $1 pixels along the y-axis, while preserving 3D ratio." 14409 repeat $! l[$>] 14410 size={if(${is_percent\ $1},$1*h,$1)} 14411 r {max(1,w*$size/h)},{max(1,$size)},{max(1,d*$size/h)},100%,${2-7} 14412 endl done 14413 14414#@cli r3dz : eq. to 'resize3dz'. 14415r3dz : 14416 _gmic_s="$?" v + _resize3dz $* 14417 14418#@cli resize3dz : depth[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 14419#@cli : Resize selected images along the z-axis, while preserving 3D ratio. 14420#@cli : (eq. to 'r3dz').\n 14421#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 14422# 4=grid | 5=bicubic | 6=lanczos }. 14423#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 14424#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 14425#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14426#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 14427#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 14428#@cli : (set to '0' by default, must be defined in range [0,1]). 14429#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 14430resize3dz : 14431 _gmic_s="$?" v + _$0 $* 14432 14433_resize3dz : check "$1>0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 14434 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 14435 e[0--3] "Resize 3D image"$_gmic_s" to $1 pixels along the z-axis, while preserving 3D ratio." 14436 repeat $! l[$>] 14437 size={if(${is_percent\ $1},$1*d,$1)} 14438 r[$>] {max(1,w*$size/d)},{max(1,h*$size/d)},{max(1,$size)},100%,${2-7} 14439 endl done 14440 14441#@cli rotate : angle,_interpolation,_boundary_conditions,_center_x[%],_center_y[%] : \ 14442# u,v,w,angle,interpolation,boundary_conditions,_center_x[%],_center_y[%],_center_z[%] : (+) 14443#@cli : Rotate selected images with specified angle (in deg.), and optionally 3D axis (u,v,w). 14444#@cli : 'interpolation' can be { 0=none | 1=linear | 2=bicubic }. 14445#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14446#@cli : When a rotation center (cx,cy,_cz) is specified, the size of the image is preserved. 14447#@cli : Default values: 'interpolation=1', 'boundary_conditions=0' and 'center_x=center_y=(undefined)'. 14448#@cli : $ image.jpg +rotate -25,1,2,50%,50% rotate[0] 25 14449 14450#@cli rotate_tileable : angle,_max_size_factor>=0 14451#@cli : Rotate selected images by specified angle and make them tileable. 14452#@cli : If resulting size of an image is too big, the image is replaced by a 1x1 image. 14453#@cli : Default values: 'max_size_factor=8'. 14454rotate_tileable : check ${2=8}>=0 14455 e[^-1] "Rotate image$? with angle $1 deg. and make them tileable." 14456 14457 # Reduce angle to known fraction. 14458 angle={$1%360} 14459 if $angle>=270 rotate 270 angle-=270 14460 elif $angle>=180 rotate 180 angle-=180 14461 elif $angle>=90 rotate 90 angle-=90 14462 fi 14463 # List of known fractions. 14464 (0,1;1,8;1,7;1,6;1,5;1,4;1,5;1,3;2,5;1,2;2,5;3,5;2,3;3,4;4,5;1,1;5,4;7,5;3,2;8,5;9,5;2,1;3,1;4,1;5,1;6,1;7,1;8,1) 14465 s. x,2 +/[-2,-1] atan. *. {180/pi} # Compute corresponding angles. 14466 ($angle) index. .. rm.. 14467 p={-3,@{^}} q={-2,@{^}} rm[-3--1] # Find nearest fraction p/q to atan(angle). 14468 if !$p||!$q return fi 14469 14470 repeat $! l[$>] 14471 # Compute width and height of tile. 14472 theta={atan2($p,$q)} 14473 gcd=${gcd" "{h*$q},{w*$p}} 14474 pw={h*$q/$gcd} 14475 nw={round($pw*w/cos($theta))} 14476 gcd=${gcd" "{h*$p},{w*$q}} 14477 qh={w*$q/$gcd} 14478 nh={round($qh*h/cos($theta))} 14479 14480 # Rotate and make tileable (may result in very large images!). 14481 if !$2" || "($nw<$2*w" && "$nh<$2*h) 14482 r {1.5*$nw},{1.5*$nh},1,100%,0,2 14483 rotate {$theta*180/pi},1,2,50%,50% 14484 r $nw,$nh,1,100%,0,2,0.5,0.5 14485 else error[0--4] "Command '$0': Invalid image dimension "({w},{h},{d},{s}). 14486 fi 14487 endl done 14488 14489#@cli rows : y0[%],_y1[%] 14490#@cli : Keep only specified rows of selected images. 14491#@cli : Dirichlet boundary conditions are used when specified rows are out of range. 14492#@cli : Default value: 'y1=y0'. 14493#@cli : $ image.jpg rows -25%,50% 14494rows : skip ${2=$1} 14495 e[^-1] "Keep rows $1...$2 of image$?." 14496 z 0,$1,100%,$2 14497 14498#@cli scale2x 14499#@cli : Resize selected images using the Scale2x algorithm. 14500#@cli : $ image.jpg threshold 50% resize 50%,50% +scale2x 14501scale2x : 14502 e[^-1] "Double xy-dimensions of image$?, using Scale2x algorithm." 14503 repeat $! l[$>] 14504 r 200%,200% 14505 f "dx=x&1;dy=y&1;A=j(0,-2,0,0,0,1);B=j(2,0,0,0,0,1);C=j(-2,0,0,0,0,1);D=j(0,2,0,0,0,1); 14506 !dy*(!dx*if(C==A&&C!=D&&A!=B,A,i) + dx*if(A==B&&A!=C&&B!=D,B,i)) + 14507 dy*(dx*if(B==D&&B!=A&&D!=C,D,i) + !dx*if(D==C&&D!=B&&C!=A,C,i))" 14508 endl done 14509 14510#@cli scale3x 14511#@cli : Resize selected images using the Scale3x algorithm. 14512#@cli : $ image.jpg threshold 50% resize 33%,33% +scale3x 14513scale3x : 14514 e[^-1] "Triple xy-dimensions of image$?, using Scale3x algorithm." 14515 repeat $! l[$>] 14516 r 300%,300% 14517 f "dx=x%3;dy=y%3;c0=!dx;c1=(dx==1);c2=(dx==2); 14518 A=j(-3,-3,0,0,0,1);B=j(0,-3,0,0,0,1);C=j(3,-3,0,0,0,1); 14519 D=j(-3,0,0,0,0,1);F=j(3,0,0,0,0,1); 14520 G=j(-3,3,0,0,0,1);H=j(0,3,0,0,0,1);I=j(3,3,0,0,0,1); 14521 !dy*(c0*if(D==B&&D!=H&&B!=F,D,i) + c1*if((D==B&&D!=H&&B!=F&&i!=C)||(B==F&&B!=D&&F!=H&&i!=A),B,i) + 14522 c2*if(B==F&&B!=D&&F!=H,F,i)) + 14523 (dy==1)*(c0*if((H==D&&H!=F&&D!=B&&i!=A)||(D==B&&D!=H&&B!=F&&i!=G),D,i) + c1*i + 14524 c2*if((B==F&&B!=D&&F!=H&&i!=I)||(F==H&&F!=B&&H!=D&&i!=C),F,i)) + 14525 (dy==2)*(c0*if(H==D&&H!=F&&D!=B,D,i) + c1*if((F==H&&F!=B&&H!=D&&i!=G)||(H==D&&H!=F&&D!=B&&i!=I),H,i) + 14526 c2*if(F==H&&F!=B&&H!=D,F,i))" 14527 endl done 14528 14529#@cli scale_dcci2x : _edge_threshold>=0,_exponent>0,_extend_1px={ 0=false | 1=true } 14530#@cli : Double image size using directional cubic convolution interpolation, 14531#@cli : as described in <https://en.wikipedia.org/wiki/Directional_Cubic_Convolution_Interpolation>. 14532#@cli : Default values: 'edge_threshold=1.15', 'exponent=5' and 'extend_1px=0'. 14533#@cli : $ image.jpg +scale_dcci2x , 14534scale_dcci2x : check "${1=1.15}>=0 && ${2=5}>=0" skip ${3=0} 14535 e[^-1] "Double xy-dimensions of image$?, using DCCI2x algorithm." 14536 repeat $! l[$>] 14537 r {2*w-(!$3)},{2*h-(!$3)},1,100%,4 14538 14539 # Estimate diagonal values. 14540 f "begin( 14541 const threshold = $1; 14542 const exponent = $2; 14543 interpolation = 0; 14544 boundary = 1; 14545 j1(x,y) = P[7*y + x + 24]; # eq. to 'j(x,y)', but faster 14546 j2(x,y) = P[7*x - y + 24]; # eq. to 'j(-y,x)', but faster 14547 interp(k) = -k#(-3,-3) + 9*k#(-1,-1) + 9*k#(1,1) - k#(3,3); 14548 d(k) = sum(abs([ 14549 k#(-1,-3) - k#(-3,-1), k#(1,-3) - k#(-1,-1), k#(3,-3) - k#(1,-1), 14550 k#(-1,-1) - k#(-3,1), k#(1,-1) - k#(-1,1), k#(3,-1) - k#(1,1), 14551 k#(-1,1) - k#(-3,3), k#(1,1) - k#(-1,3), k#(3,1) - k#(1,3) 14552 ])); 14553 ); 14554 if (!((x*y)%2),i, 14555 ref(crop(x - 3,y - 3,0,c,7,7,1,1),P); 14556 d1 = d(j1); 14557 d2 = d(j2); 14558 ratio = (1 + d1)/(1 + d2); 14559 value = ratio>threshold ? interp(j1): # Up-right edge 14560 ratio<(1/threshold) ? interp(j2): # Down-right edge 14561 (w1 = 1/(1 + d1^exponent); w2 = 1/(1 + d2^exponent); 14562 (interp(j1)*w1 + interp(j2)*w2)/(w1 + w2)); # Smooth area 14563 value/=16)" 14564 14565 # Estimate remaining values. 14566 f "begin( 14567 const threshold = $1; 14568 const exponent = $2; 14569 interpolation = 0; 14570 boundary = 1; 14571 j1(x,y) = P[7*y + x + 24]; # eq. to 'j(x,y)', but faster 14572 j2(x,y) = P[7*x - y + 24]; # eq. to 'j(-y,x)', but faster 14573 interp(k) = -k#(0,-3) + 9*k#(0,-1) + 9*k#(0,1) - k#(0,3); 14574 d(k) = sum(abs([ 14575 k#(-1,-2) - k#(1,-2), 14576 k#(-2,-1) - k#(0,-1), k#(0,-1) - k#(2,-1), 14577 k#(-3,0) - k#(-1,0), k#(-1,0) - k#(1,0), k#(1,0) - k#(3,0), 14578 k#(-2,1) - k#(0,1), k#(0,1) - k#(2,1), 14579 k#(-1,2) - k#(1,2) 14580 ])); 14581 ); 14582 if ((x%2) + (y%2)!=1,i, 14583 ref(crop(x - 3,y - 3,0,c,7,7,1,1),P); 14584 d1 = d(j1); 14585 d2 = d(j2); 14586 ratio = (1 + d1)/(1 + d2); 14587 value = ratio>threshold ? interp(j1) : # Horizontal edge 14588 ratio<(1/threshold) ? interp(j2) : # Vertical edge 14589 (w1 = 1/(1 + d1^exponent); w2 = 1/(1 + d2^exponent); 14590 (interp(j1)*w1 + interp(j2)*w2)/(w1 + w2)); # Smooth area 14591 value/=16)" 14592 endl done 14593 14594#@cli seamcarve : _width[%]>=0,_height[%]>=0,_is_priority_channel={ 0 | 1 },_is_antialiasing={ 0 | 1 },\ 14595# _maximum_seams[%]>=0 14596#@cli : Resize selected images with specified 2D geometry, using the seam-carving algorithm. 14597#@cli : Default values: 'height=100%', 'is_priority_channel=0', 'is_antialiasing=1' and 'maximum_seams=25%'. 14598#@cli : $ image.jpg seamcarve 60% 14599# The main code of this algorithm has been done by Andy (Garagecoder). 14600seamcarve : check "${2=100%}>=0 && ${5=25%}>=0" skip ${3=0},${4=1} 14601 e[^-1] "Resize image$? to $1x$2 using seam-carving algorithm, "${arg\ 1+!$3,with,without}" priority channel, "\ 14602 ${arg\ 1+!$4,with,without}" anti-aliasing and maximum seams $5." 14603 repeat $! l[$>] 14604 nw={max(1,round(if(${is_percent\ $1},$1*w,$1)))} 14605 nh={max(1,round(if(${is_percent\ $2},$2*h,$2)))} 14606 if $nw!=w _seamcarve $nw,$3,$4,$5 fi 14607 if $nh!=h transpose _seamcarve $nh,$3,$4,$5 transpose fi 14608 endl done 14609 14610# Subroutine to remove/add vertical seams/ 14611# $1 = desired width. 14612# $2 = is_priority_channel={ 0 | 1 } 14613# $3 = is_antialiasing={ 0 | 1 } 14614# $4 = max number of seams added/removed at once. 14615_seamcarve : 14616 do 14617 max_seams={max(1,round(if(${is_percent\ $4},$4*w,$4)))} 14618 ssms={max(min(round($1-w),w),1-w)} 14619 sms={min($max_seams,abs($ssms))} 14620 14621 # Compute potential map. 14622 if $2 s[0] c,{1-s} /. 256 fi 14623 +gradient[0] a[-2,-1] c abs. compose_channels. + n. 0,1 14624 if $2 +. .. a[0,1] c fi 14625 14626 # Add x-coordinates channel for anti-aliasing. 14627 if $3 100%,1,1,1,x r. [0],[0] a[0,-1] c fi 14628 14629 # Calculate low matrix (backwards propagation). 14630 . 14631 repeat h 14632 +rows. {$<+1} erode. 3 14633 j.. .,0,$<,0,0,-1 rm. 14634 done 14635 14636 # Initialise seams, top matrix. 14637 100%,100% +rows[1] 0 14638 nm[1] grad nm[2] low nm[3] seam nm[4] top 14639 14640 repeat h#0-1 nr={$>+1} 14641 +rows[low] $nr 14642 14643 # Find optimum matches between two 1D matrices. 14644 +*[4,5] +shift[4] 1 *. [5] +shift[5] 1 *. [4] 14645 +[-2,-1] j[5] [4] a[-3--1] c 14646 f. ">if(c,i,max(j(-1)+j(0,0,0,1),j(-2)+j(0,0,0,2)))" 14647 s. c shift... 1 +.. ... shift... 1 +[-3,-1] 14648 >[-2,-1] f. "<if(j(1)<0,1,-i)" 14649 14650 # Add matched row to seams. 14651 j[seam] .,0,$> 14652 14653 # Distribute matched pixels in top matrix. 14654 a[-2,-1] c f. "j(i,0,0,-1)" channels. 1 14655 14656 # Add next energy row to top matrix. 14657 +rows[grad] $nr +[top,-1] 14658 done 14659 14660 # Add / remove seams. 14661 max={iM*2} repeat $sms =. $max,{xm} done 14662 j[grad] .,0,100% rm[low,top] a[-2,-1] c 14663 f. "<if(c,i,j(j(0,0,0,1),1,0,0,0,1))" channels. 0 14664 +[0] 0.1 !=. $max 14665 w={w} h={h} s={0,s} 14666 if $ssms<0 * discard 0 r {$w-$sms},$h,1,$s,-1 # Remove seams. 14667 elif $ssms>0 # Add seams. 14668 -. 2 s[0] c 14669 repeat $s if $><($s-1) . fi a[$>,-1] c done 14670 permute cxyz a c discard -1 f "if(i<0,j(0,-1),i)" 14671 r {$w+$sms},$h,1,$s,-1 14672 fi 14673 14674 # Perform anti-aliasing step. 14675 if $3 14676 s c,{1-s} g. x,1 round !=. 1 14677 (0.5,0.5) +convolve[0] . rm.. 14678 j[0] .,0,0,0,0,1,[1] rm[-2,-1] 14679 fi 14680 14681 rprogress {a=w/$1;if(a<1,a*100,100/a)} 14682 while w!=$1 14683 14684#@cli shift : vx[%],_vy[%],_vz[%],_vc[%],_boundary_conditions,_interpolation={ 0=nearest_neighbor | 1=linear } : (+) 14685#@cli : Shift selected images by specified displacement vector. 14686#@cli : Displacement vector can be non-integer in which case linear interpolation should be chosen. 14687#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14688#@cli : Default value: 'boundary_conditions=0' and 'interpolation=0'. 14689#@cli : $ image.jpg +shift[0] 50%,50%,0,0,0 +shift[0] 50%,50%,0,0,1 +shift[0] 50%,50%,0,0,2 14690 14691#@cli shrink_x : size_x>=0 14692#@cli : Shrink selected images along the x-axis. 14693#@cli : $ image.jpg shrink_x 30 14694shrink_x : check "$1>=0" 14695 e[^-1] "Shrink image$? along the x-axis with size $1." 14696 repeat $! z[$>] $1,{$>,w-$1-1} done 14697 14698#@cli shrink_xy : size>=0 14699#@cli : Shrink selected images along the xy-axes. 14700#@cli : $ image.jpg shrink_xy 30 14701shrink_xy : check "$1>=0" 14702 e[^-1] "Shrink image$? along the xy-axes with size $1." 14703 repeat $! z[$>] $1,$1,{$>,w-$1-1},{$>,h-$1-1} done 14704 14705#@cli shrink_xyz : size>=0 14706#@cli : Shrink selected images along the xyz-axes. 14707shrink_xyz : check "$1>=0" 14708 e[^-1] "Shrink image$? along the xyz-axes with size $1." 14709 repeat $! z[$>] $1,$1,$1,{$>,w-$1-1},{$>,h-$1-1},{$>,d-$1-1} done 14710 14711#@cli shrink_y : size_y>=0 14712#@cli : Shrink selected images along the y-axis. 14713#@cli : $ image.jpg shrink_y 30 14714shrink_y : check "$1>=0" 14715 e[^-1] "Shrink image$? along the y-axis with size $1." 14716 repeat $! z[$>] 0,$1,100%,{$>,h-$1-1} done 14717 14718#@cli shrink_z : size_z>=0 14719#@cli : Shrink selected images along the z-axis. 14720shrink_z : check "$1>=0" 14721 e[^-1] "Shrink image$? along the z-axis with size $1." 14722 repeat $! z[$>] 0,0,$1,100%,100%,{$>,d-$1-1} done 14723 14724#@cli slices : z0[%],_z1[%] 14725#@cli : Keep only specified slices of selected images. 14726#@cli : Dirichlet boundary conditions are used when specified slices are out of range. 14727#@cli : Default value: 'z1=z0'. 14728slices : skip ${2=$1} 14729 e[^-1] "Keep slices $1...$2 of image$?." 14730 z 0,0,$1,100%,100%,$2 14731 14732#@cli sort : _ordering={ + | - },_axis={ x | y | z | c } : (+) 14733#@cli : Sort pixel values of selected images. 14734#@cli : If 'axis' is specified, the sorting is done according to the data of the first column/row/slice/channel 14735#@cli : of selected images. 14736#@cli : Default values: 'ordering=+' and 'axis=(undefined)'. 14737#@cli : $ 64 rand 0,100 +sort display_graph 400,300,3 14738 14739#@cli s : eq. to 'split'. : (+) 14740 14741#@cli split : { x | y | z | c }...{ x | y | z | c },_split_mode : \ 14742# keep_splitting_values={ + | - },_{ x | y | z | c }...{ x | y | z | c },value1,_value2,... : (no arg) : (+) 14743#@cli : Split selected images along specified axes, or regarding to a sequence of scalar values 14744#@cli : (optionally along specified axes too). 14745#@cli : (eq. to 's').\n 14746#@cli : 'split_mode' can be { 0=split according to constant values | >0=split in N parts | \ 14747# <0=split in parts of size -N }. 14748#@cli : Default value: 'split_mode=-1'. 14749#@cli : $ image.jpg split c 14750#@cli : $ image.jpg split y,3 14751#@cli : $ image.jpg split x,-128 14752#@cli : $ 1,20,1,1,"1,2,3,4" +split -,2,3 append[1--1] y 14753#@cli : $ (1,2,2,3,3,3,4,4,4,4) +split x,0 append[1--1] y 14754 14755#@cli split_tiles : M!=0,_N!=0,_is_homogeneous={ 0 | 1 } 14756#@cli : Split selected images as a MxN array of tiles. 14757#@cli : If M or N is negative, it stands for the tile size instead. 14758#@cli : Default values: 'N=M' and 'is_homogeneous=0'. 14759#@cli : $ image.jpg +local split_tiles 5,4 blur 3,0 sharpen 700 append_tiles 4,5 endlocal 14760split_tiles : skip ${2=$1},${3=0} 14761 if $3 e[^-1] "Split image$? as a $1x$2 array of homogeneous tiles." 14762 else e[^-1] "Split image$? as a $1x$2 array of tiles." 14763 fi 14764 repeat $! l[$<] s y,$2 s x,$1 if $3 r [0],[0],100%,100%,0 fi endl done 14765 14766#@cli undistort : -1<=_amplitude<=1,_aspect_ratio,_zoom,_center_x[%],_center_y[%],_boundary_conditions 14767#@cli : Correct barrel/pincushion distortions occurring with wide-angle lens. 14768#@cli : References: 14769#@cli : [1] Zhang Z. (1999). Flexible camera calibration by viewing a plane from unknown orientation. 14770#@cli : [2] Andrew W. Fitzgibbon (2001). Simultaneous linear estimation of multiple view geometry and lens distortion. 14771#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14772#@cli : Default values: 'amplitude=0.25', 'aspect_ratio=0', 'zoom=0', 'center_x=center_y=50%' \ 14773# and 'boundary_conditions=0'. 14774undistort : check "${1=0.1}>=-1 && $1<=1 && ${6=0}>=0 && $6<=3" skip ${2=0},${3=0},${4=50%},${5=50%} 14775 e[^-1] "Undistort barrel/pincushion effect in image$?, with amplitude $1, aspect ratio $2, zoom factor $3, 14776 center ($4,$5) and "${"arg 1+$6,dirichlet,neumann,periodic,mirror"}" boundary conditions." 14777 repeat $! l[$>] 14778 center_x={${"is_percent $4"}?w*$4:$4} 14779 center_y={${"is_percent $5"}?h*$5:$5} 14780 f " 14781 const interpolation = 1; 14782 const boundary = $6; 14783 const center_x = "$center_x"; 14784 const center_y = "$center_y"; 14785 const alpha = cut($1,-0.999,0.999); 14786 const ratio = $2>=0?1+$2:1/(1-$2); 14787 const zoom = $3>=0?1+$3:1/(1-$3); 14788 const M = max(w,h); 14789 x = 2*(x - center_x)/(zoom*ratio*M); 14790 y = 2*(y - center_y)/(zoom*M); 14791 r = norm(x,y); 14792 nr = r/(1 - alpha*r^2); 14793 if (r>0, 14794 nx = nr/r*x; ny = nr/r*y, 14795 nx = x; ny = y 14796 ); 14797 x = 0.5*nx*ratio*M + center_x; 14798 y = 0.5*ny*M + center_y; 14799 I(x,y)" 14800 endl done 14801 14802#@cli y : eq. to 'unroll'. : (+) 14803 14804#@cli unroll : _axis={ x | y | z | c } : (+) 14805#@cli : Unroll selected images along specified axis. 14806#@cli : (eq. to 'y'). 14807#@cli : Default value: 'axis=y'. 14808#@cli : $ (1,2,3;4,5,6;7,8,9) +unroll y 14809 14810#@cli upscale_smart : width[%],_height[%],_depth,_smoothness>=0,_anisotropy=[0,1],sharpening>=0 14811#@cli : Upscale selected images with an edge-preserving algorithm. 14812#@cli : Default values: 'height=100%', 'depth=100%', 'smoothness=2', 'anisotropy=0.4' and 'sharpening=10'. 14813#@cli : $ image.jpg resize2dy 100 +upscale_smart 500%,500% append x 14814upscale_smart : skip ${2=100%},${3=100%} check "${4=2}>=0 && ${5=0.4}>=0 && $5<=1 && ${6=10}>=0" 14815 e[^-1] "Upscale image$? to $1x$2x$3, with smoothness $4, anisotropy $5 and sharpening $6." 14816 repeat $! l[$>] 14817 w={w} h={h} 14818 +r. $1,$2,$3,1,0 # Compute desired dimensions. 14819 if w<$w" && "h<$h # Test for downscaling 14820 rm. r. $1,$2,$3,100%,2 14821 else 14822 rm. +diffusiontensors 0,$5,1.2,1.2 14823 r[-2,-1] $1,$2,$3,100%,5 14824 smooth.. .,$4 rm. 14825 ac "sharpen. $6,10",ycbcr_y 14826 fi 14827 endl done 14828 14829#@cli warp : [warping_field],_mode,_interpolation,_boundary_conditions,_nb_frames>0 : (+) 14830#@cli : Warp selected images with specified displacement field. 14831#@cli : 'mode' can be { 0=backward-absolute | 1=backward-relative | 2=forward-absolute | 3=forward-relative }. 14832#@cli : 'interpolation' can be { 0=nearest-neighbor | 1=linear | 2=cubic }. 14833#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14834#@cli : Default values: 'mode=0', 'interpolation=1', 'boundary_conditions=1' and 'nb_frames=1'. 14835#@cli : $ image.jpg 100%,100%,1,2,'X=x/w-0.5;Y=y/h-0.5;R=(X*X+Y*Y)^0.5;A=atan2(Y,X);130*R*if(c==0,cos(4*A),sin(8*A))' \ 14836# warp[-2] [-1],1,1,0 quiver[-1] [-1],10,1,1,1,100 14837#@cli : $$ https://gmic.eu/oldtutorial/_warp 14838 14839#@cli warp_patch : [warping_field],patch_width>=1,_patch_height>=1,_patch_depth>=1,_std_factor>0,_boundary_conditions. 14840#@cli : Patch-warp selected images, with specified 2D or 3D displacement field (in backward-absolute mode). 14841#@cli : Argument 'std_factor' sets the std of the gaussian weights for the patch overlap, 14842#@cli : equal to 'std = std_factor*patch_size'. 14843#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14844#@cli : Default values: 'std_factor=0.3' and 'boundary_conditions=3'. 14845warp_patch : check ${is_image_arg\ $1}" && isint(${2=3}) && $2>=1 && isint(${3=$2}) && $3>=1 && 14846 isint(${4=1}) && $4>=1 && isnum(${5=0.3}) && $5>0 && isint(${6=3}) && $6>=0 && $6<=3" 14847 e[^-1] "Patch-warp image$? with backward-absolute displacement field $1, using $2x$3x$4 patches, std factor $5 14848 and "${"arg 1+$6,dirichlet,neumann,periodic,mirror"}" boundary conditions." 14849 if $2<=1 pass$1 warp[^-1] .,0 rm. return fi 14850 repeat $! pass$1 l[$>,-1] nm={0,n} 14851 [0],[0],[0],1,1 a[0,-1] c # Add weighting channel 14852 100%,100%,100%,{0,s} 14853 14854 if s#1>=3 # 3D version 14855 eval[1] "> 14856 begin( 14857 const pw = $2; 14858 const ph = $3; 14859 const pd = $4; 14860 const stdf = $5; 14861 const boundary = $6; 14862 const pw1 = int(pw/2); 14863 const pw2 = pw - pw1 - 1; 14864 const ph1 = int(ph/2); 14865 const ph2 = ph - ph1 - 1; 14866 const pd1 = int(pd/2); 14867 const pd2 = pd - pd1 - 1; 14868 const pwhd = pw*ph*pd; 14869 return = vector(s); 14870 14871 # Pre-compute gaussian weights. 14872 if (stdf<5, 14873 ref(vectorpwhd(),weights); 14874 offw = 0; 14875 for (zw = -pd1, zw<=pd2, ++zw, 14876 for (yw = -ph1, yw<=ph2, ++yw, 14877 for (xw = -pw1, xw<=pw2, ++xw, 14878 weights[offw++] = exp(-xw^2/(2*(stdf*pw)^2) - yw^2/(2*(stdf*ph)^2) - zw^2/(2*(stdf*pd)^2)); 14879 ); 14880 ); 14881 ); 14882 ); 14883 ); 14884 u = i(x,y,z,0); 14885 v = i(x,y,z,1); 14886 w = i(x,y,z,2); 14887 ref(crop(#0,u - pw1, v - ph1,w - pd1,pw,ph,pd,boundary),patch); 14888 stdf<5? 14889 draw(#2,patch,x - pw1,y - ph1,z - pd1,0,pw,ph,pd,s#0,-1,weights): 14890 draw(#2,patch,x - pw1,y - ph1,z - pd1,0,pw,ph,pd,s#0,-1); 14891 return" 14892 else # 2D version 14893 eval[1] "> 14894 begin( 14895 const pw = $2; 14896 const ph = $3; 14897 const stdf = $5; 14898 const boundary = $6; 14899 14900 const pw1 = int(pw/2); 14901 const pw2 = pw - pw1 - 1; 14902 const ph1 = int(ph/2); 14903 const ph2 = ph - ph1 - 1; 14904 const pwh = pw*ph; 14905 return = vector(s); 14906 14907 # Pre-compute gaussian weights. 14908 if (stdf<5, 14909 ref(vectorpwh(),weights); 14910 offw = 0; 14911 for (yw = -ph1, yw<=ph2, ++yw, 14912 for (xw = -pw1, xw<=pw2, ++xw, 14913 weights[offw++] = exp(-xw^2/(2*(stdf*pw)^2) - yw^2/(2*(stdf*ph)^2)); 14914 ); 14915 ); 14916 ); 14917 ); 14918 u = i(x,y,z,0); 14919 v = i(x,y,z,1); 14920 ref(crop(#0,u - pw1, v - ph1,pw,ph,boundary),patch); 14921 stdf<5? 14922 draw(#2,patch,x - pw1,y - ph1,0,0,pw,ph,1,s#0,-1,weights): 14923 draw(#2,patch,x - pw1,y - ph1,0,0,pw,ph,1,s#0,-1); 14924 return" 14925 fi 14926 s. c,-{0,s-1} /[-2,-1] k. nm $nm 14927 endl done 14928 14929#@cli warp_rbf : xs0[%],ys0[%],xt0[%],yt0[%],...,xsN[%],ysN[%],xtN[%],ytN[%] 14930#@cli : Warp selected images using RBF-based interpolation. 14931#@cli : Each argument (xsk,ysk)-(xtk,ytk) corresponds to the coordinates of a keypoint 14932#@cli : respectively on the source and target images. The set of all keypoints define the overall image deformation. 14933#@cli : $ image.jpg +warp_rbf 0,0,0,0,100%,0,100%,0,100%,100%,100%,100%,0,100%,0,100%,50%,50%,70%,50%,25%,25%,25%,75% 14934warp_rbf : 14935 e[^-1] "Warp image$? using RBF interpolation, with keypoints ($*)." 14936 $=arg N={$#/4} 14937 if int($N)!=$N error[0--2] "Command 'warp_rbf': Wrong number of arguments ($#)." fi 14938 repeat $! l[$>] 14939 # Retrieve absolute keypoints coordinates. 14940 4,$N 14941 repeat wh a=${arg{1+$>}} isp=${"is_percent "$a} eval i[$>]=$isp?($>%2?w#0:h#0)*$a:$a done 14942 s. x,2 -. .. a[-2,-1] x permute. yzcx 14943 14944 # Generate warping field by RBF interpolation. 14945 rbf. {0,[w,h]} warp[0] .,1,1,3 rm. 14946 endl done 14947 14948#--------------------------------- 14949# 14950#@cli :: Filtering 14951# 14952#--------------------------------- 14953 14954#@cli bandpass : _min_freq[%],_max_freq[%] 14955#@cli : Apply bandpass filter to selected images. 14956#@cli : Default values: 'min_freq=0' and 'max_freq=20%'. 14957#@cli : $ image.jpg bandpass 1%,3% 14958#@cli : $$ https://gmic.eu/oldtutorial/_bandpass 14959bandpass : skip ${1=0},${2=20%} 14960 e[^-1] "Apply bandpass filter [$1,$2] to image$?." 14961 repeat $! l[$>] 14962 100%,100%,100% f. "sqrt((x/w-0.5)^2 + (y/h-0.5)^2 + (z/d-0.5)^2)" 14963 n. 0,1 ir. $1,$2 shift. {int(w/2)},{int(h/2)},{int(d/2)},0,2 14964 fft.. *... . *[-2,-1] ifft rm. 14965 endl done 14966 14967#@cli bilateral : [guide],std_deviation_s[%]>=0,std_deviation_r[%]>=0,_sampling_s>=0,_sampling_r>=0 : \ 14968# std_deviation_s[%]>=0,std_deviation_r[%]>=0,_sampling_s>=0,_sampling_r>=0 : (+) 14969#@cli : Blur selected images by anisotropic (eventually joint/cross) bilateral filtering. 14970#@cli : If a guide image is provided, it is used for drive the smoothing filter. 14971#@cli : A guide image must be of the same xyz-size as the selected images. 14972#@cli : Set 'sampling' arguments to '0' for automatic adjustment. 14973#@cli : $ image.jpg repeat 5 bilateral 10,10 done 14974 14975#@cli b : eq. to 'blur'. : (+) 14976 14977#@cli blur : std_deviation>=0[%],_boundary_conditions,_kernel : \ 14978# axes,std_deviation>=0[%],_boundary_conditions,_kernel : (+) 14979#@cli : Blur selected images by a deriche or gaussian filter (recursive implementation). 14980#@cli : (eq. to 'b').\n 14981#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14982#@cli : 'kernel' can be { 0=deriche | 1=gaussian }. 14983#@cli : When specified, argument 'axes' is a sequence of { x | y | z | c }. 14984#@cli : Specifying one axis multiple times apply also the blur multiple times. 14985#@cli : Default values: 'boundary_conditions=1' and 'kernel=1'. 14986#@cli : $ image.jpg +blur 5,0 +blur[0] 5,1 14987#@cli : $ image.jpg +blur y,10% 14988#@cli : $$ https://gmic.eu/oldtutorial/_blur 14989 14990#@cli blur_angular : amplitude[%],_center_x[%],_center_y[%] 14991#@cli : Apply angular blur on selected images. 14992#@cli : Default values: 'center_x=center_y=50%'. 14993#@cli : $ image.jpg blur_angular 2% 14994#@cli : $$ https://gmic.eu/oldtutorial/_blur_angular 14995blur_angular : skip ${2=50%},${3=50%} 14996 e[^-1] "Apply angular blur on image$?, with amplitude $1 and center point ($2,$3)." 14997 euclidean2polar $2,$3,1.3,1 14998 repeat $! l[$>] 1,100% =. 1,50%,50% b. y,$1 convolve_fft.. . rm. endl done 14999 polar2euclidean $2,$3,1.3,1 15000 15001#@cli blur_bloom : _amplitude>=0,_ratio>=0,_nb_iter>=0,_blend_operator={ + | max | min },\ 15002# _kernel={ 0=deriche | 1=gaussian | 2=box | 3=triangle | 4=quadratic },\ 15003# _normalize_scales={ 0 | 1 },_axes 15004#@cli : Apply a bloom filter that blend multiple blur filters of different radii, 15005#@cli : resulting in a larger but sharper glare than a simple blur. 15006#@cli : When specified, argument 'axes' is a sequence of { x | y | z | c }. 15007#@cli : Specifying one axis multiple times apply also the blur multiple times. 15008#@cli : Reference: Masaki Kawase, "Practical Implementation of High Dynamic Range Rendering", GDC 2004. 15009#@cli : Default values: 'amplitude=1', 'ratio=2', 'nb_iter=5', 'blend_operator=+', 'kernel=1', 'normalize_scales=0' \ 15010# and 'axes=(all)' 15011#@cli : $ image.jpg blur_bloom , 15012blur_bloom : check "${1=1}>=0 && ${2=2}>=0 && isint(${3=5}) && $3>=0 && isint(${5=1}) && $5>=0 && $5<=4 && 15013 isnum(${6=0})" skip "${4=+},${7=}" 15014 e[^-1] "Apply bloom effect on image$?, with amplitude $1, ratio $2, $3 iterations, blend operator '$4' and "\ 15015 ${"arg 1+!$6,\"\",\"no \""}"scale normalization." 15016 if narg("$7") axes=$7, fi 15017 m "_bloom0 : b "$axes"$""1" 15018 m "_bloom1 : b "$axes"$""1,1,1" 15019 m "_bloom2 : boxfilter "$axes"{1+2*$""1},0,1" 15020 m "_bloom3 : boxfilter "$axes"{1+2*$""1},0,1,2" 15021 m "_bloom4 : boxfilter "$axes"{1+2*$""1},0,1,3" 15022 repeat $! l[$>] nm={n} mM={[im,iM]} 15023 [0] repeat $3 sigma={$1*($2^$>)} +_bloom$5[0] $sigma 15024 if $6 n. $mM fi 15025 -$4[1,-1] 15026 done 15027 n. $mM k. nm $nm 15028 endl done 15029 um _bloom0,_bloom1,_bloom2,_bloom3,_bloom4 15030 15031#@cli blur_linear : amplitude1[%],_amplitude2[%],_angle,_boundary_conditions={ 0=dirichlet | 1=neumann } 15032#@cli : Apply linear blur on selected images, with specified angle and amplitudes. 15033#@cli : Default values: 'amplitude2=0', 'angle=0' and 'boundary_conditions=1'. 15034#@cli : $ image.jpg blur_linear 10,0,45 15035#@cli : $$ https://gmic.eu/oldtutorial/_blur_linear 15036blur_linear : skip ${2=0},${3=0},${4=1} 15037 e[^-1] "Apply linear blur on image$?, with angle $3 deg. and amplitudes ($1,$2)." 15038 std1={if(${is_percent\ $1},$1*max(w,h),$1)} 15039 std2={if(${is_percent\ $2},$2*max(w,h),$2)} 15040 stdM={round(1.25*max($std1,$std2))} 15041 if $stdM<=0 return fi 15042 repeat $! l[$>] 15043 expand_xy $stdM,{$4!=0} 15044 {2*$stdM},{2*$stdM} gaussian. $1,$2,$3 normalize_sum. 15045 convolve_fft[0] [1] rm. shrink_xy $stdM 15046 endl done 15047 15048#@cli blur_radial : amplitude[%],_center_x[%],_center_y[%] 15049#@cli : Apply radial blur on selected images. 15050#@cli : Default values: 'center_x=center_y=50%'. 15051#@cli : $ image.jpg blur_radial 2% 15052#@cli : $$ https://gmic.eu/oldtutorial/_blur_radial 15053blur_radial : skip ${2=50%},${3=50%} 15054 e[^-1] "Apply radial blur on image$?, with amplitude $1 and center point ($2,$3)." 15055 euclidean2polar $2,$3,5,1 blur_x $1 polar2euclidean $2,$3,5,1 15056 15057#@cli blur_selective : sigma>=0,_edges>0,_nb_scales>0 15058#@cli : Blur selected images using selective gaussian scales. 15059#@cli : Default values: 'sigma=5', 'edges=0.5' and 'nb_scales=5'. 15060#@cli : $ image.jpg noise 20 cut 0,255 +local[-1] repeat 4 blur_selective , done endlocal 15061#@cli : $$ https://gmic.eu/oldtutorial/_blur_selective 15062blur_selective : check "${1=5}>=0 && ${2=0.5}>=0 && isint(${3=5}) && $3>0" 15063 e[^-1] "Blur image$? using $3 selective gaussian scales, with sigma $1 and edges $2." 15064 repeat $! l[$>] nm={0,n} 15065 +gradient_norm +. 1 ^. {-max(0.01,$2)} quantize. {$3+1},0,1 min. {$3-1} ri. .. 15066 repeat $3 +==. $> *. ... +[-2,-1] b.. {$1/($3+1)} done 15067 rm.. nm $nm endl done 15068 15069#@cli blur_x : amplitude[%]>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 15070#@cli : Blur selected images along the x-axis. 15071#@cli : Default value: 'boundary_conditions=1'. 15072#@cli : $ image.jpg +blur_x 6 15073#@cli : $$ https://gmic.eu/oldtutorial/_blur_x 15074blur_x : check "isint(${2=1}) && inrange($2,0,3)" 15075 e[^-1] "Blur image$? along the x-axis, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 15076 deriche $1,0,x,$2 15077 15078#@cli blur_xy : amplitude_x[%],amplitude_y[%],_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 15079#@cli : Blur selected images along the X and Y axes. 15080#@cli : Default value: 'boundary_conditions=1'. 15081#@cli : $ image.jpg +blur_xy 6 15082#@cli : $$ https://gmic.eu/oldtutorial/_blur_y 15083blur_xy : skip ${2=$1} check "isint(${3=1}) && inrange($3,0,3)" 15084 e[^-1] "Blur image$? along the xy-axes, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 15085 deriche $1,0,x,$3 deriche $2,0,y,$3 15086 15087#@cli blur_xyz : amplitude_x[%],amplitude_y[%],amplitude_z,\ 15088# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 15089#@cli : Blur selected images along the X, Y and Z axes. 15090#@cli : Default value: 'boundary_conditions=1'. 15091#@cli : $$ https://gmic.eu/oldtutorial/_blur_xyz 15092blur_xyz : skip ${2=$1},${3=$1} check "isint(${4=1}) && inrange($4,0,3)" 15093 e[^-1] "Blur image$? along the xyz-axes, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 15094 deriche $1,0,x,$4 deriche $2,0,y,$4 deriche $3,0,z,$4 15095 15096#@cli blur_y : amplitude[%]>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 15097#@cli : Blur selected images along the y-axis. 15098#@cli : Default value: 'boundary_conditions=1'. 15099#@cli : $ image.jpg +blur_y 6 15100#@cli : $$ https://gmic.eu/oldtutorial/_blur_y 15101blur_y : check "isint(${2=1}) && inrange($2,0,3)" 15102 e[^-1] "Blur image$? along the y-axis, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 15103 deriche $1,0,y,$2 15104 15105#@cli blur_z : amplitude[%]>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 15106#@cli : Blur selected images along the z-axis. 15107#@cli : Default value: 'boundary_conditions=1'. 15108#@cli : $$ https://gmic.eu/oldtutorial/_blur_z 15109blur_z : check "isint(${2=1}) && inrange($2,0,3)" 15110 e[^-1] "Blur image$? along the z-axis, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 15111 deriche $1,0,z,$2 15112 15113#@cli boxfilter : size>=0[%],_order,_boundary_conditions,_nb_iter>=0 : \ 15114# axes,size>=0[%],_order,_boundary_conditions,_nb_iter>=0 : (+) 15115#@cli : Blur selected images by a box filter of specified size (fast recursive implementation). 15116#@cli : 'order' can be { 0=smooth | 1=1st-derivative | 2=2nd-derivative }. 15117#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15118#@cli : When specified, argument 'axes' is a sequence of { x | y | z | c }. 15119#@cli : Specifying one axis multiple times apply also the blur multiple times. 15120#@cli : Default values: 'order=0', 'boundary_conditions=1' and 'nb_iter=1'. 15121#@cli : $ image.jpg +boxfilter 5% 15122#@cli : $ image.jpg +boxfilter y,3,1 15123 15124#@cli bump2normal 15125#@cli : Convert selected bumpmaps to normalmaps. 15126#@cli : $ 300,300 circle 50%,50%,128,1,1 blur 5% bump2normal 15127bump2normal : 15128 e[^-1] "Convert bumpmap$? to normalmap." 15129 repeat $! l[$>] 15130 channels 0 g xy,1 +f. 1 a c orientation 15131 * 127 + 128 round c 0,255 15132 endl done 15133 15134#@cli compose_freq 15135#@cli : Compose selected low and high frequency parts into new images. 15136#@cli : $ image.jpg split_freq 2% mirror[-1] x compose_freq 15137compose_freq : 15138 e[^-1] "Compose low and high frequency part$? into new images." 15139 repeat int($!/2) +[$>,{$>+1}] done 15140 15141#@cli convolve : [mask],_boundary_conditions,_is_normalized={ 0 | 1 },_channel_mode,\ 15142# _xcenter,_ycenter,_zcenter,_xstart,_ystart,_zstart,_xend,_yend,_zend,_xstride,_ystride,_zstride,\ 15143# _xdilation,_ydilation,_zdilation,interpolation_type : (+) 15144#@cli : Convolve selected images by specified mask. 15145#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15146#@cli : 'channel_mode' can be { 0=sum input channels | 1=one-for-one | 2=expand }. 15147#@cli : 'interpolation_type' can be { 0=nearest-neighbor | 1=linear }. 15148#@cli : Default values: 'boundary_conditions=1', 'is_normalized=0', 'channel_mode=1', \ 15149# 'xcenter=ycenter=zcenter=-1' (-1=centered), 'xstart=ystart=zstart=0', 'xend=yend=zend=(max-coordinates)', \ 15150# 'xstride=ystride=zstride=1', 'xdilation=ydilation=zdilation=1' and 'interpolation_type=0'. 15151#@cli : $ image.jpg (0,1,0;1,-4,1;0,1,0) convolve[-2] [-1] keep[-2] 15152#@cli : $ image.jpg (0,1,0) resize[-1] 130,1,1,1,3 +convolve[0] [1] 15153#@cli : $$ https://gmic.eu/oldtutorial/_convolve 15154 15155#@cli convolve_fft : [mask],_boundary_conditions 15156#@cli : Convolve selected images with specified mask, in the fourier domain. 15157#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15158#@cli : $ image.jpg 100%,100% gaussian[-1] 20,1,45 +convolve_fft[0] [1] 15159convolve_fft : check ${is_image_arg\ $1}" && isin(${2=2},0,1,2,3)" 15160 e[^-1] "Convolve image$? with mask $1, in the fourier domain." 15161 pass$1 store. kernel 15162 repeat $! l[$>] if w 15163 w0,h0,d0={[w,h,d]} 15164 $kernel 15165 if $2!=2 r[0] {[w#0,h#0,d#0]+2*round([w#1>1?w#1:0,h#1>1?h#1:0,d#1>1?d#1:0]/2)},100%,0,$2,0.5,0.5 fi 15166 r ${-max_whd},100%,0,0,0.5,0.5 r 100%,100%,100%,${-max_s} 15167 fft[1] fft[0] 15168 +*[1,2] +*[0,3] +[-2,-1] *[1,3] *[0,2] -[0,1] 15169 ifft rm. 15170 shift {-int(([w,h,d]-1)/2)},0,2 15171 r $w0,$h0,$d0,100%,0,0,0.5,0.5 15172 fi endl done 15173 15174#@cli correlate : [mask],_boundary_conditions,_is_normalized={ 0 | 1 },_channel_mode,\ 15175# _xcenter,_ycenter,_zcenter,_xstart,_ystart,_zstart,_xend,_yend,_zend,_xstride,_ystride,_zstride,\ 15176# _xdilation,_ydilation,_zdilation,interpolation_type : (+) 15177#@cli : Correlate selected images by specified mask. 15178#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15179#@cli : 'channel_mode' can be { 0=sum input channels | 1=one-for-one | 2=expand }. 15180#@cli : 'interpolation_type' can be { 0=nearest-neighbor | 1=linear }. 15181#@cli : Default values: 'boundary_conditions=1', 'is_normalized=0', 'channel_mode=1', \ 15182# 'xcenter=ycenter=zcenter=-1' (-1=centered), 'xstart=ystart=zstart=0', 'xend=yend=zend=(max-coordinates)', \ 15183# 'xstride=ystride=zstride=1', 'xdilation=ydilation=zdilation=1' and 'interpolation_type=0'. 15184#@cli : $ image.jpg (0,1,0;1,-4,1;0,1,0) correlate[-2] [-1] keep[-2] 15185#@cli : $ image.jpg +crop 40%,40%,60%,60% +correlate[0] [-1],0,1 15186 15187#@cli cross_correlation : [mask] 15188#@cli : Compute cross-correlation of selected images with specified mask. 15189#@cli : $ image.jpg +shift -30,-20 +cross_correlation[0] [1] 15190cross_correlation : check ${is_image_arg\ $1} 15191 e[^-1] "Compute cross-correlation of image$? with mask $1." 15192 repeat $! pass$1 0 l[$>,-1] 15193 norm fft.. fft. [-2,-1] *.. [-5] *. [-6] 15194 -[-2,-1] *[-5,-3] *[-3,-2] +[-3,-2] ifft rm. 15195 endl done 15196 15197#@cli curvature 15198#@cli : Compute isophote curvatures on selected images. 15199#@cli : $ image.jpg blur 10 curvature 15200curvature : 15201 e[^-1] "Compute isophote curvatures on image$?." 15202 repeat $! l[$>] 15203 if d==1 15204 +g xy,0 hessian... xxxyyy # ixx ixy iyy ix iy 15205 *... .. *[-4] . *[-4] -2 # ixx -2iyixy ixiyy ix iy 15206 +[-4,-3] *... .. # ixx -2ixiyixy+ix^2iyy ix iy 15207 sqr[-2,-1] *[-4] . +[-4,-3] # iy^2ixx-2ixiyixy+ix^2iyy ix^2 iy^2 15208 +[-2,-1] +. 0.1 ^. 1.5 / # (iy^2ixx+2ixiyixy+ix^2iyy)/(ix^2+iy^2) 15209 else 15210 +inn +gradient_norm.. laplacian... # inn+iee inn in 15211 -[-3,-2] +. 0.1 /[-2,-1] # iee in 15212 +inn. laplacian.. - # iee/in 15213 fi 15214 endl done 15215 15216#@cli dct : _{ x | y | z }...{ x | y | z } : (no arg) 15217#@cli : Compute the discrete cosine transform of selected images, optionally along the specified axes only. 15218#@cli : Output images are always evenly sized, so this command may change the size of the selected images. 15219#@cli : Default values: (no arg) 15220#@cli : See also: ''idct''. 15221#@cli : $ image.jpg +dct +idct[-1] abs[-2] +[-2] 1 log[-2] 15222#@cli : $$ https://gmic.eu/oldtutorial/_dct-and-idct 15223dct : skip ${1=0} 15224 ('"$1"') 15225 is_axes={im>=_'x'" && "iM<=_'z'} 15226 if $is_axes 15227 e[0--3] "Compute discrete cosine transform of image$? along axes '$1'." 15228 repeat w 15229 axis={i[$>]} 15230 if $axis==_'x' repeat $!-1 l[$>] if w>1 _dct fi endl done 15231 elif $axis==_'y' repeat $!-1 l[$>] if h>1 permute yxzc _dct permute yxzc fi endl done 15232 elif $axis==_'z' repeat $!-1 l[$>] if d>1 permute zxyc _dct permute yzxc fi endl done 15233 fi 15234 done 15235 rm. 15236 else 15237 rm. 15238 e[0--3] "Compute discrete cosine transform of image$?." 15239 noarg 15240 repeat $! l[$>] 15241 if w>1 _dct fi 15242 if h>1 permute yxzc _dct permute yxzc fi 15243 if d>1 permute zxyc _dct permute yzxc fi 15244 endl done 15245 fi 15246 15247# 1D direct transform (DCT-II) along the x-axis, for a single image. 15248_dct : 15249 if w%2 r {w+1},100%,100%,100%,0,1 fi 15250 s x l[1--1:2] a x mirror x endl mv[1] $! a x 15251 fft x 15252 100%,1,1,1,2*cos(-x*pi/(2*w)) *[0,2] 15253 100%,1,1,1,2*sin(-x*pi/(2*w)) *[1,2] 15254 - 15255 +z[0] 0,0 /. {sqrt(2)} j.. .,0,0,0 rm. * {sqrt(2/w)} # Make the transform orthogonal. 15256 15257#@cli deblur : amplitude[%]>=0,_nb_iter>=0,_dt>=0,_regul>=0,_regul_type={ 0=Tikhonov | 1=meancurv. | 2=TV } 15258#@cli : Deblur image using a regularized Jansson-Van Cittert algorithm. 15259#@cli : Default values: 'nb_iter=10', 'dt=20', 'regul=0.7' and 'regul_type=1'. 15260#@cli : $ image.jpg blur 3 +deblur 3,40,20,0.01 15261deblur : check "${2=10}>=0 && ${3=20}>=0 && ${4=0.7}>=0" skip ${5=1} 15262 e[^-1] "Deblur image$? with a regularized Jansson-Van Cittert algorithm, with sigma $1, $2 iterations, 15263 time step $3 and regularization $4." 15264 repeat $! l[$>] nm={0,n} 15265 [0] 15266 repeat $2 15267 if $5>=2 +curvature. # TV regularization. 15268 elif $5>=1 +iee. # Meancurv. regularization. 15269 else +laplacian. # Tikhonov regularization. 15270 fi 15271 *. $4 15272 +b.. $1 -. [-4] # Data fidelity term. 15273 -[-2,-1] 15274 *. {$3/(0.0001+max(abs(im),abs(iM)))} # Adaptive time step. 15275 +[-2,-1] # Update image. 15276 done 15277 rm.. 15278 nm $nm endl done 15279 15280#@cli deblur_goldmeinel : sigma>=0,_nb_iter>=0,_acceleration>=0,_kernel_type={ 0=deriche | 1=gaussian }. 15281#@cli : Deblur selected images using Gold-Meinel algorithm 15282#@cli : Default values: 'nb_iter=8', 'acceleration=1' and 'kernel_type=1'. 15283#@cli : $ image.jpg +blur 1 +deblur_goldmeinel[-1] 1 15284###### : (contribution from Jérôme Boulanger). 15285deblur_goldmeinel : check "$1>=0 && ${2=8}>=0 && ${3=1}>=0" skip ${4=1} 15286 e[^-1] "Deblur image$? using Gold-Meinel algorithm, with sigma $1, $2 iterations, acceleration $3 and "\ 15287 ${arg\ 1+!$4,"",quasi-}"gaussian kernel." 15288 repeat $! l[$>] 15289 [0] repeat $2 15290 +b. $1,1,$4 +/[0,-1] rm.. ^. $3 *[-1,-2] # u *= f / Hu 15291 done rm[0] 15292 endl done 15293 15294#@cli deblur_richardsonlucy : sigma>=0, nb_iter>=0, _kernel_type={ 0=deriche | 1=gaussian }. 15295#@cli : Deblur selected images using Richardson-Lucy algorithm. 15296#@cli : Default values: 'nb_iter=50' and 'kernel_type=1'. 15297#@cli : $ image.jpg +blur 1 +deblur_richardsonlucy[-1] 1 15298###### : (contribution from Jérôme Boulanger). 15299deblur_richardsonlucy : check "$1>=0 && ${2=50}>=0" skip ${3=1} 15300 e[^-1] "Deblur image$? using Richardson-Lucy algorithm, with sigma $1, $2 iterations and "\ 15301 ${arg\ 1+!$3,"",quasi-}"gaussian kernel." 15302 repeat $! l[$>] 15303 [0] repeat $2 15304 +b. $1,1,{$3!=0} max. 1e-6 +/[0,-1] rm.. b. $1,1,{$3!=0} *[-1,-2] # u *= H ( f / Hu ) 15305 done rm[0] 15306 endl done 15307 15308#@cli deconvolve_fft : [kernel],_regularization>=0 15309#@cli : Deconvolve selected images by specified mask in the fourier space. 15310#@cli : Default value: 'regularization>=0'. 15311#@cli : $ image.jpg +gaussian 5 +convolve_fft[0] [1] +deconvolve_fft[-1] [1] 15312deconvolve_fft : check ${is_image_arg\ $1}" && ${2=.001}>=0" 15313 e[^-1] "Deconvolve image$? with mask $1 and regularization $2, in the fourier domain." 15314 repeat $! pass$1 0 l[$>,-1] 15315 w2={0,int(w/2)} h2={0,int(h/2)} d2={0,int(d/2)} 15316 r[1] [0],[0],[0],1,0,0,0.5,0.5,0.5,0.5 shift[1] -$w2,-$h2,-$d2,0,2 15317 fft[0] fft[2] # a b a' b' 15318 +l[-1,-2] sqr + + $2 endl # a b a' b' (a'^2+b'^2+eps) 15319 +*[-4] ... # a b a' b' (a'^2+b'^2) ba' 15320 +*[-6] ... # a b a' b' (a'^2+b'^2) ba' ab' 15321 -[-2,-1] # a b a' b' (a'^2+b'^2) ba'-ab' 15322 *[-6,-4] # aa' b b' (a'^2+b'^2) ba'-ab' 15323 *[-4,-3] # aa' bb' (a'^2+b'^2) ba'-ab' 15324 +[-4,-3] # aa'+bb' (a'^2+b'^2) ba'-ab' 15325 /. .. /[-3,-2] # divide (aa'+bb') and (ba'-ab') by (a'^2+b'^2) 15326 ifft rm. 15327 endl done 15328 15329#@cli deinterlace : _method={ 0 | 1 } 15330#@cli : Deinterlace selected images ('method' can be { 0=standard or 1=motion-compensated }). 15331#@cli : Default value: 'method=0'. 15332#@cli : $ image.jpg +rotate 3,1,1,50%,50% resize 100%,50% resize 100%,200%,1,3,4 shift[-1] 0,1 add +deinterlace 1 15333deinterlace : skip ${1=0} 15334 e[^-1] "Deinterlace image$? with "${arg\ 1+!$1,motion-compensated,standard}" method." 15335 repeat $! l[$>] 15336 wh={w},{h} 15337 s y a[0--1:2] y a[^0] y ri.. .,0 r 100%,200%,1,100%,5 15338 if $1!=0 +displacement. ..,0.05 warp... .,1,1,1 rm. fi 15339 + / 2 c 0,255 r $wh 15340 endl done 15341 15342#@cli denoise : [guide],std_deviation_s[%]>=0,_std_deviation_r[%]>=0,_patch_size>0,_lookup_size>0,_smoothness,\ 15343# _fast_approx={ 0 | 1 } : \ 15344# std_deviation_s[%]>=0,_std_deviation_r[%]>=0,_patch_size>0,_lookup_size>0,_smoothness,\ 15345# _fast_approx={ 0 | 1 } : (+) 15346#@cli : Denoise selected images by non-local patch averaging. 15347#@cli : Default values: 'std_deviation_p=10', 'patch_size=5', 'lookup_size=6' and 'smoothness=1'. 15348#@cli : $ image.jpg +denoise 5,5,8 15349 15350#@cli denoise_haar : _threshold>=0,_nb_scales>=0,_cycle_spinning>0 15351#@cli : Denoise selected images using haar-wavelet thresholding with cycle spinning. 15352#@cli : Set 'nb_scales==0' to automatically determine the optimal number of scales. 15353#@cli : Default values: 'threshold=1.4', 'nb_scale=0' and 'cycle_spinning=10'. 15354#@cli : $ image.jpg noise 20 cut 0,255 +denoise_haar[-1] 0.8 15355denoise_haar : check "${1=1.4}>=0 && isint(${2=0}) && $2>=0 && isint(${3=10}) && $3>0" 15356 e[^-1] "Denoise image$? using haar-wavelet thresholding, with threshold $1, "\ 15357 ${arg\ 1+($2>0),auto,$2}" scales and $3 spinning cycles." 15358 repeat $! l[$>] nm={0,n} 15359 nb_scales={min(if($2,$2,32),int(log2(min(w,h))-1))} 15360 w={w} h={h} d={d} sigma=${-std_noise} 15361 r {round(w,2^($nb_scales+1),1)},{round(h,2^($nb_scales+1),1)},{if(d==1,1,round(d,2^($nb_scales+1),1))},100%,0,0 15362 +f 0 15363 repeat $3 15364 dx={round(u(0,{4*$nb_scales}))} 15365 dy={round(u(0,{4*$nb_scales}))} 15366 dz={if($d==1,0,round(u(0,{4*$nb_scales})))} 15367 +shift[0] $dx,$dy,$dz,0,2 15368 haar. $nb_scales 15369 threshold. {$1*$sigma},1 15370 ihaar. $nb_scales 15371 shift. {-$dx},{-$dy},{-$dz},0,2 15372 +[-2,-1] 15373 done 15374 rm[0] / $3 r $w,$h,$d,100%,0 15375 nm $nm endl done 15376 15377#@cli denoise_cnn : _noise_type={ 0=soft | 1=heavy | 2=heavy (faster) | 3=poisson+gaussian },_patch_size>0 15378#@cli : Denoise selected images using a convolutional neural network (CNN). 15379#@cli : Input value range should be [0,255]. Output value range is [0,255]. 15380#@cli : Default value: 'patch_size=64'. 15381#@cli : $ image.jpg noise 20 cut 0,255 +denoise_cnn 15382denoise_cnn : skip "${1=0},${2=64}" 15383 N=$! 15384 if isint($1)" && "inrange($1,0,3) check "isint($2) && $2>0" type=$1 else type=0 noarg fi 15385 s0,s1,s2,s3=soft,heavy,heavy,poisson+gaussian 15386 e[^-1] "Denoise image$? using a convolutional neural network (for "${s$type}"-noise), with patch size $2." 15387 15388 # Load denoising network. 15389 if 0${_is_denoise_cnn_$type} ${_denoise_cnn_$type} 15390 else l[] 15391 l[] input_cached gmic_denoise_cnn.gmz 15392 onfail error[0--5] "Command 'denoise_cnn': Unable to load network file 'gmic_denoise_cnn.gmz'." 15393 endl 15394 k[$type] unserialize +store _denoise_cnn_$type _is_denoise_cnn_$type=1 15395 endl fi 15396 ps=$2 replace_str. "nn_layer_input X,32,32,1,3","nn_layer_input X,"$ps","$ps",1,3" # Set patch size 15397 run {t} rm[-2,-1] 15398 15399 # Process images. 15400 repeat $N l[$>,$N--1] to_color[0] 15401 if $type==3 srgb2rgb[0] fi 15402 15403 # Extract overlapping psxps tiles. 15404 nx,ny={0,ceil([w,h]/($ps-6))} 15405 {0,[$ps,$ps,$nx*$ny,s]} 15406 1,1,{d},1,": 15407 ix = z%$nx; 15408 iy = int(z/$nx); 15409 X = $nx<2?-2:round(lerp(-2,w#0 - $ps + 2,ix/($nx - 1))); 15410 Y = $ny<2?-2:round(lerp(-2,h#0 - $ps + 2,iy/($ny - 1))); 15411 V = crop(#0,X,Y,0,0,$ps,$ps,1,3,3); 15412 draw(#-1,V,0,0,z,0,$ps,$ps,1,3)" 15413 rm. 15414 15415 # Denoise tiles. 15416 1,1,{d},1,*${-nn_lib}"X = crop(#-1,0,0,z,0,$ps,$ps,1,3);"${_nn_forward}"draw(#-1,OUT0_out,0,0,z,0,$ps,$ps,1,3);0" 15417 rm. c. 0,255 15418 15419 # Reconstruct image from overlapping tiles. 15420 {0,[w,h,1,4]} 15421 1,1,{-2,d},1,">begin( 15422 mask = convolve(vector(#($ps - 4)*($ps - 4),1), 15423 $ps - 4,$ps - 4,1,1, 15424 [1],1,1,1,1, 15425 0,0,1, 15426 0,0,0, 15427 -2,-2,0,$ps - 4 - 1 + 2,$ps - 4 - 1 + 2,0); 15428 ); 15429 ix = z%$nx; 15430 iy = int(z/$nx); 15431 X = $nx<2?-2:round(lerp(-2,w#0 - $ps + 2,ix/($nx - 1))); 15432 Y = $ny<2?-2:round(lerp(-2,h#0 - $ps + 2,iy/($ny - 1))); 15433 V = crop(#-2,0,0,z,0,$ps,$ps,1,3); 15434 draw(#-1,V,X,Y,0,0,$ps,$ps,1,3,-1,mask); 15435 draw(#-1,mask,X,Y,0,3,$ps,$ps,1,1,-1,mask)" 15436 rm[-3,-1] 15437 l. s c,-3 max. 1 / if $type==3 rgb2srgb. fi c 0,255 endl 15438 j[0] . rm. 15439 15440 endl done 15441 rm[$N--1] 15442 15443#@cli denoise_patchpca : _strength>=0,_patch_size>0,_lookup_size>0,_spatial_sampling>0 15444#@cli : Denoise selected images using the patch-pca algorithm. 15445#@cli : Default values: 'patch_size=7', 'lookup_size=11', 'details=1.8' and 'spatial_sampling=5'. 15446#@cli : $ image.jpg +noise 20 cut[-1] 0,255 +denoise_patchpca[-1] , 15447denoise_patchpca : check "${1=1.8} && $1>=0 && isint(${2=7}) && $2>0 && isint(${3=11}) && $3>0 && isint(${4=5}) && $4>0" 15448 e[^-1] "Denoise image$? using patch-pca, with strength $1, patch size $2, lookup size $3 and spatial sampling $4." 15449 repeat $! l[$>] nm={n} 15450 N2={$2*$2} M2={$3*$3} stdnoise=${-std_noise} 15451 100%,100%,1,100% nm. aggreg 15452 100%,100% nm. weights 15453 f[0] "* 15454 begin( 15455 n1 = int($2/2); n2 = $2 - n1 - 1; 15456 m1 = int($3/2); m2 = $3 - m1 - 1; 15457 patch(x,y) = crop(x - n1,y - n1,0,c,$2,$2,1,1,1); 15458 ngauss(x) = exp(-x*x/(2*n1*n1)); 15459 ref(vector"$N2"(0),zero); 15460 ref(vector"$N2"(0),mask); 15461 for (l = 0; q = -n1, q<=n2, ++q, 15462 for (p = -n1, p<=n2, ++p, mask[l++] = ngauss(p)*ngauss(q) 15463 ) 15464 ) 15465 ); 15466 15467 if (!(x%$4) && !(y%$4), # Sub-sampling 15468 ref(patch(x,y),X); 15469 15470 # Build correlation matrix for PCA. 15471 ref(vector"{$N2*$N2}"(0),M); 15472 for (q = -m1, q<=m2, ++q, 15473 for (p = -m1, p<=m2, ++p, 15474 ref(patch(x + p,y + q) - X,Xk); 15475 M += mul(Xk,Xk,"$N2"); 15476 ) 15477 ); 15478 M/="$M2"; 15479 eig = eig(M); 15480 lambda = sqrt(abs(eig[0,"$N2"])); 15481 15482 # Determine number of lambdas to keep and project neighboring patches. 15483 for (k = 0, k<size(lambda) && lambda[k]>=$1*"$stdnoise", ++k); 15484 Qt = eig["$N2","{$N2*$N2}"]; 15485 Q = transpose(Qt,"$N2"); 15486 for (q = -m1, q<=m2, ++q, 15487 for (p = -m1, p<=m2, ++p, 15488 pY = Qt*(patch(x + p,y + q) - X); 15489 copy(pY[k],zero[0],size(pY) - k); 15490 (Y = Q*pY)+=X; 15491 draw(#"$aggreg",Y,x + p - n1,y + q - n1,0,c,$2,$2,1,1,-1,mask); 15492 draw(#"$weights",mask,x + p - n1,y + q - n1,0,c,$2,$2,1,1,-1); 15493 ) 15494 ); 15495 0);0" 15496 max[weights] 0.01 /[aggreg,weights] k[aggreg] nm $nm 15497 endl done 15498 15499#@cli deriche : std_deviation>=0[%],order={ 0 | 1 | 2 },axis={ x | y | z | c },_boundary_conditions : (+) 15500#@cli : Apply Deriche recursive filter on selected images, along specified axis and with 15501#@cli : specified standard deviation, order and boundary conditions. 15502#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15503#@cli : Default value: 'boundary_conditions=1'. 15504#@cli : $ image.jpg deriche 3,1,x 15505#@cli : $ image.jpg +deriche 30,0,x deriche[-2] 30,0,y add 15506#@cli : $$ https://gmic.eu/oldtutorial/_deriche 15507 15508#@cli dilate : size>=0 : size_x>=0,size_y>=0,size_z>=0 : \ 15509# [kernel],_boundary_conditions,_is_real={ 0=binary-mode | 1=real-mode } : (+) 15510#@cli : Dilate selected images by a rectangular or the specified structuring element. 15511#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15512#@cli : Default values: 'size_z=1', 'boundary_conditions=1' and 'is_real=0'. 15513#@cli : $ image.jpg +dilate 10 15514 15515#@cli dilate_circ : _size>=0,_boundary_conditions,_is_normalized={ 0 | 1 } 15516#@cli : Apply circular dilation of selected images by specified size. 15517#@cli : Default values: 'boundary_conditions=1' and 'is_normalized=0'. 15518#@cli : $ image.jpg +dilate_circ 7 15519dilate_circ : check $1>=0 skip ${2=1},${3=0} 15520 e[^-1] "Apply circular dilation of image$? by size $1, boundary conditions $2 and is_normalized $3." 15521 if $1<2 return fi 15522 shape_circle $1 dilate[^-1] .,$2,$3 rm. 15523 15524#@cli dilate_oct : _size>=0,_boundary_conditions,_is_normalized={ 0 | 1 } 15525#@cli : Apply octagonal dilation of selected images by specified size. 15526#@cli : Default values: 'boundary_conditions=1' and 'is_normalized=0'. 15527#@cli : $ image.jpg +dilate_oct 7 15528dilate_oct : check $1>=0 skip ${2=1},${3=0} 15529 e[^-1] "Apply octagonal dilation of image$? by size $1, boundary conditions $2 and is_normalized $3." 15530 if $1<2 return fi 15531 if $1&1 ss={$1} else ss={$1+1} fi 15532 i[0] (0,1,0;1,1,1;0,1,0) i[1] (1,1,1;1,1,1;1,1,1) 15533 repeat $!-2 15534 r={round(($ss-1)*sqrt(2)/(1+sqrt(2))/2)} 15535 q={round(($ss-1)/(1+sqrt(2))/2)} 15536 if $r>0 repeat $r dilate. [0],$2,$3 done fi 15537 if $q>0 repeat $q dilate. [1],$2,$3 done fi 15538 mv. 2 done rm[0,1] 15539 15540_kr_circle : 15541 if $1%2==0 2,2,1,1,1 else 1,1,1,1,1 fi r. $1,$1,1,1,0,0,0.5,0.5 15542 distance. 1 round. 0.5 ir. 0,{$1/2} 15543 15544_jf_circle : 15545 {round($1)},{round($1)} 15546 center={0.5*(w-1)} 15547 f. 'sqrt((x-$center)^2+(y-$center)^2)' 15548 if !(w%2) 15549 round. 0.0001,-1 15550 t1={sqrt(((round($1)-1)/2)^2+0.25)} 15551 t2={sqrt(((round($1)+1)/2)^2+0.25)} 15552 k={$1-round($1)+0.5} 15553 t={$t1+($t2-$t1)*$k} 15554 ir. 0,$t 15555 else ir. 0,{$1/2-0.25} 15556 fi 15557 15558#@cli dilate_threshold : size_x>=1,size_y>=1,size_z>=1,_threshold>=0,_boundary_conditions 15559#@cli : Dilate selected images in the (X,Y,Z,I) space. 15560#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15561#@cli : Default values: 'size_y=size_x', 'size_z=1', 'threshold=255' and 'boundary_conditions=1'. 15562dilate_threshold : check "isint($1) && $1>=1 && isint(${2=$1}) && $2>=1 && isint(${3=1}) && $3>=1 && ${4=255}>=0 && 15563 isint(${5=1}) && $5>=0" 15564 e[^-1] "Dilate image$? with mask $1x$2x$3, threshold $4 and "${arg\ $5,dirichlet,neumann}" boundary conditions." 15565 l[] 15566 dx1={int($1/2)} dx2={$1-$dx1-1} 15567 dy1={int($2/2)} dy2={$2-$dy1-1} 15568 dz1={int($3/2)} dz2={$3-$dz1-1} 15569 (-$dx1,$dx1) (-$dy1;$dy1) (-$dz1/$dz1) r $1,$2,$3,1,3 a c round r {w*h*d},3,1,1,-1 transpose. 15570 i.. 1,100%,1,1,254 1,100%,1,1,255 a x 15571 ('{^}') rm.. replace_str "254,","(v=j(" replace_str ",255",",0,0,$5);if(abs(v-i)<=$4,v,-1e20))" list={t} 15572 rm 15573 endl 15574 f 'max($list)' 15575 15576#@cli divergence 15577#@cli : Compute divergence of selected vector fields. 15578#@cli : $ image.jpg luminance +gradient append[-2,-1] c divergence[-1] 15579divergence : 15580 e[^-1] "Compute divergence of vector field$?." 15581 repeat $! l[$>] 15582 if s==1 g x,0 15583 elif s==2 s c g.. x,0 g. y,0 + 15584 elif s==3 s c g... x,0 g.. y,0 g. z,0 + 15585 else error[] "Command '$0': Cannot compute divergence of image ["$>"] (has "{s}">3 channels)." 15586 fi 15587 endl done 15588 15589#@cli dog : _sigma1>=0[%],_sigma2>=0[%] 15590#@cli : Compute difference of gaussian on selected images. 15591#@cli : Default values: 'sigma1=2%' and 'sigma2=3%'. 15592#@cli : $ image.jpg dog 2,3 15593dog : check "${1=2%}>=0 && ${2=3%}>=0" 15594 e[^-1] "Compute difference of gaussian on image$?, with standard deviations $1 and $2." 15595 repeat $! l[$>] 15596 [0] parallel "b[0] $1","b[1] $2" - abs 15597 endl done 15598 15599#@cli diffusiontensors : _sharpness>=0,0<=_anisotropy<=1,_alpha[%],_sigma[%],is_sqrt={ 0 | 1 } 15600#@cli : Compute the diffusion tensors of selected images for edge-preserving smoothing algorithms. 15601#@cli : Default values: 'sharpness=0.7', 'anisotropy=0.3', 'alpha=0.6', 'sigma=1.1' and 'is_sqrt=0'. 15602#@cli : $ image.jpg diffusiontensors 0.8 abs pow 0.2 15603#@cli : $$ https://gmic.eu/oldtutorial/_diffusiontensors 15604diffusiontensors : check "${1=0.7}>=0 && ${2=0.3}>=0 && $2<=1" skip ${3=0.6},${4=1.1},${5=0} 15605 e[^-1] "Compute diffusion tensors for image$?, with sharpness $1, anisotropy $2, alpha $3 and sigma $4." 15606 p1={if($5,0.5,1)*max($1,1e-2)} 15607 p2={$p1/(1e-7+1-$2)} 15608 b $3 n 0,255 structuretensors 0 b $4 15609 repeat $! l[$>] 15610 eigen max.. 0 15611 if s==2 s.. c +[-3,-2] +.. 1 +^.. -$p1 ^... -$p2 a[-3,-1] c # 2D 15612 else s.. c +[-4--2] +.. 1 +^.. -$p1 r. 100%,100%,100%,2 ^... -$p2 a[-3,-1] c # 3D 15613 fi 15614 eigen2tensor 15615 endl done 15616 15617#@cli edges : _threshold[%]>=0 15618#@cli : Estimate contours of selected images. 15619#@cli : Default value: 'edges=15%' 15620#@cli : $ image.jpg +edges 15% 15621edges : skip ${1=15%} 15622 e[^-1] "Estimate image contours of image$?, with threshold $1." 15623 gradient_norm b 0.5 >= $1 distance 0 equalize negate c 30%,70% n 0,1 15624 15625#@cli erode : size>=0 : size_x>=0,size_y>=0,_size_z>=0 : \ 15626# [kernel],_boundary_conditions,_is_real={ 0=binary-mode | 1=real-mode } : (+) 15627#@cli : Erode selected images by a rectangular or the specified structuring element. 15628#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15629#@cli : Default values: 'size_z=1', 'boundary_conditions=1' and 'is_real=0'. 15630#@cli : $ image.jpg +erode 10 15631 15632#@cli erode_circ : _size>=0,_boundary_conditions,_is_normalized={ 0 | 1 } 15633#@cli : Apply circular erosion of selected images by specified size. 15634#@cli : Default values: 'boundary_conditions=1' and 'is_normalized=0'. 15635#@cli : $ image.jpg +erode_circ 7 15636erode_circ : check $1>=0 skip ${2=1},${3=0} 15637 e[^-1] "Apply circular erosion of image$? by size $1, boundary conditions $2 and is_normalized $3." 15638 if $1<2 return fi 15639 shape_circle $1 erode[^-1] .,$2,$3 rm. 15640 15641#@cli erode_oct : _size>=0,_boundary_conditions,_is_normalized={ 0 | 1 } 15642#@cli : Apply octagonal erosion of selected images by specified size. 15643#@cli : Default values: 'boundary_conditions=1' and 'is_normalized=0'. 15644#@cli : $ image.jpg +erode_oct 7 15645erode_oct : check $1>=0 skip ${2=1},${3=0} 15646 e[^-1] "Apply octagonal erosion of image$? by size $1, boundary conditions $2 and is_normalized $3." 15647 if $1<2 return fi 15648 if $1&1 ss={$1} else ss={$1+1} fi 15649 i[0] (0,1,0;1,1,1;0,1,0) i[1] (1,1,1;1,1,1;1,1,1) 15650 repeat $!-2 15651 r={round(($ss-1)*sqrt(2)/(1+sqrt(2))/2)} 15652 q={round(($ss-1)/(1+sqrt(2))/2)} 15653 if $r>0 repeat $r erode. [0],$2,$3 done fi 15654 if $q>0 repeat $q erode. [1],$2,$3 done fi 15655 mv. 2 done rm[0,1] 15656 15657#@cli erode_threshold : size_x>=1,size_y>=1,size_z>=1,_threshold>=0,_boundary_conditions 15658#@cli : Erode selected images in the (X,Y,Z,I) space. 15659#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15660#@cli : Default values: 'size_y=size_x', 'size_z=1', 'threshold=255' and 'boundary_conditions=1'. 15661erode_threshold : check "isint($1) && $1>=1 && isint(${2=$1}) && $2>=1 && isint(${3=1}) && $3>=1 && ${4=255}>=0 && 15662 isint(${5=1}) && $5>=0" 15663 e[^-1] "Erode image$? with mask $1x$2x$3, threshold $4 and "${arg\ $5,dirichlet,neumann}" boundary conditions." 15664 l[] 15665 dx1={int($1/2)} dx2={$1-$dx1-1} 15666 dy1={int($2/2)} dy2={$2-$dy1-1} 15667 dz1={int($3/2)} dz2={$3-$dz1-1} 15668 (-$dx1,$dx1) (-$dy1;$dy1) (-$dz1/$dz1) r $1,$2,$3,1,3 a c round r {w*h*d},3,1,1,-1 transpose. 15669 i.. 1,100%,1,1,254 1,100%,1,1,255 a x 15670 ('{^}') rm.. replace_str "254,","(v=j(" replace_str ",255",",0,0,$5);if(abs(v-i)<=$4,v,1e20))" list={t} 15671 rm 15672 endl 15673 f 'min($list)' 15674 15675#@cli fft : _{ x | y | z }...{ x | y | z } : (+) 15676#@cli : Compute the direct fourier transform (real and imaginary parts) of selected images, 15677#@cli : optionally along the specified axes only. 15678#@cli : See also: ''ifft''. 15679#@cli : $ image.jpg luminance +fft append[-2,-1] c norm[-1] log[-1] shift[-1] 50%,50%,0,0,2 15680#@cli : $ image.jpg w2={int(w/2)} h2={int(h/2)} fft shift $w2,$h2,0,0,2 ellipse $w2,$h2,30,30,0,1,0 \ 15681# shift -$w2,-$h2,0,0,2 ifft remove[-1] 15682#@cli : $$ https://gmic.eu/oldtutorial/_fft 15683 15684#@cli g : eq. to 'gradient'. : (+) 15685g : 15686 _gmic_s="$?" axes,scheme,boundary,is_noarg=${"_gradient_get_args $*"} 15687 v + _gradient $axes,$scheme,$boundary v - 15688 if $is_noarg noarg fi 15689 15690#@cli gradient : { x | y | z | c }...{ x | y | z | c },_scheme,_boundary_conditions : (no arg) 15691#@cli : Compute the gradient components (first derivatives) of selected images, along specified axes. 15692#@cli : (eq. to 'g').\n 15693#@cli : 'scheme' can be { -1=backward | 0=centered | 1=forward | 2=sobel | 3=rotation-invariant (default) | \ 15694# 4=deriche | 5=vanvliet }. 15695#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15696#@cli : (no arg) compute all significant components. 15697#@cli : Default values: 'scheme=0' and 'boundary_conditions=1'. 15698#@cli : $ image.jpg gradient 15699#@cli : $$ https://gmic.eu/oldtutorial/_gradient 15700gradient : 15701 _gmic_s="$?" axes,scheme,boundary,is_noarg=${"_gradient_get_args $*"} 15702 v + _gradient $axes,$scheme,$boundary v - 15703 if $is_noarg noarg fi 15704 15705# Parse and check arguments. 15706_gradient_get_args : skip "${1=},${2=},${3=}" 15707 is_noarg=0 15708 l[] 15709 if ['$1']==0 axes,scheme,boundary=,0,1 is_noarg=1 # No 1st arg 15710 else 15711 is_axes={"s=['$1'];fill(s,k,isin(s[k],'xyzc'));min(s)"} 15712 if !$is_axes axes,scheme,boundary=,0,1 is_noarg=1 # Invalid 1st arg 15713 elif ['$2']==0 axes,scheme,boundary=$1,0,1 # No 2nd arg 15714 else 15715 is_scheme={"isint($2) && inrange($2,-1,5)"} 15716 if !$is_scheme axes,scheme,boundary=,0,1 is_noarg=1 # Invalid 2nd arg 15717 elif ['$3']==0 axes,scheme,boundary=$1,$2,1 # No 3rd arg 15718 else 15719 is_boundary={"isint($3) && inrange($3,0,3)"} 15720 if !$is_boundary axes,scheme,boundary=,0,1 is_noarg=1 # Invalid 3rd arg 15721 else axes,scheme,boundary=${1-3} 15722 fi 15723 fi 15724 fi 15725 fi 15726 onfail axes,scheme,boundary=,0,1 is_noarg=1 # Invalid arguments 15727 endl 15728 u $axes,$scheme,$boundary,$is_noarg 15729 15730# Main command. 15731_gradient : 15732 axes,scheme,boundary=${1=},${2=},${3=} 15733 15734 # Display log message. 15735 if '$axes'!=0 s_axes=" along axes '"$axes"'" fi 15736 s0,s1,s2,s3,s4,s5,s6=backward,centered,forward,sobel,rotation-invariant,deriche,vanvliet 15737 s_scheme=${s{$scheme+1}} 15738 s0,s1,s2,s3=dirichlet,neumann,periodic,mirror 15739 s_boundary=${s$boundary} 15740 e[0--3] "Compute gradient of image"$_gmic_s$s_axes", with "$s_scheme" scheme and "$s_boundary" boundary conditions." 15741 sx,sy,sz,sc=",",;,/,^ 15742 15743 # Process images. 15744 repeat $! l[$<] nm={n} 15745 laxes=$axes if '$laxes'==0 if d>1 laxes=xyz else laxes=xy fi fi 15746 ('$laxes') 15747 repeat w 15748 a={`i[#1,$>]`} s=${s$a} 15749 if 0${gradient_$a}>0 [gradient_$a] 15750 elif $scheme==-1 # Backward 15751 (-1${s}1${s}0) +correlate[0] .,$boundary rm.. 15752 elif $scheme==0 # Centered 15753 (-0.5${s}0${s}0.5) +correlate[0] .,$boundary rm.. 15754 elif $scheme==1 # Forward 15755 (0${s}-1${s}1) +correlate[0] .,$boundary rm.. 15756 elif $scheme==2 # Sobel 15757 if _'$a'==_'x' (-1,0,1;-2,0,2;-1,0,1) 15758 elif _'$a'==_'y' (-1,-2,-1;0,0,0;1,2,1) 15759 else (-0.5${s}0${s}0.5) 15760 fi 15761 +correlate[0] .,$boundary rm.. 15762 elif $scheme==3 # Rotation-invariant 15763 A,B={[0.25*(2-sqrt(2)),0.5*(sqrt(2)-1)]} 15764 if _'$a'==_'x' (-$A,0,$A;-$B,0,$B;-$A,0,$A) 15765 elif _'$a'==_'y' (-$A,-$B,-$A;0,0,0;$A,$B,$A) 15766 else (-0.5${s}0${s}0.5) 15767 fi 15768 +correlate[0] .,$boundary rm.. 15769 else # Deriche/Vanvliet 15770 s4,s5=deriche,vanvliet com=${s$scheme} 15771 if $boundary<2 +$com[0] 0,1,$a,$boundary 15772 else 15773 if _'$a'==_'x' +r[0] {0,[w+2,h,d,s]},0,$boundary,0.5 $com. 0,1,$a shrink_x. 1 15774 elif _'$a'==_'y' +r[0] {0,[w,h+2,d,s]},0,$boundary,0,0.5 $com. 0,1,$a shrink_y. 1 15775 elif _'$a'==_'z' +r[0] {0,[w,h,d+2,s]},0,$boundary,0,0,0.5 $com. 0,1,$a shrink_z. 1 15776 fi 15777 fi 15778 fi 15779 nm. gradient_$a 15780 done 15781 rm[0,1] nm $nm 15782 endl done 15783 u $is_noaarg 15784 15785#@cli gradient_norm 15786#@cli : Compute gradient norm of selected images. 15787#@cli : $ image.jpg gradient_norm equalize 15788#@cli : $$ https://gmic.eu/oldtutorial/_gradient_norm 15789gradient_norm : 15790 e[^-1] "Compute gradient norm of image$?." 15791 repeat $! l[$>] g sqr s c + sqrt endl done 15792 15793#@cli gradient_orientation : _dimension={1,2,3} 15794#@cli : Compute N-d gradient orientation of selected images. 15795#@cli : Default value: 'dimension=3'. 15796#@cli : $ image.jpg +gradient_orientation 2 15797gradient_orientation : check "${1=3}==1 || $1==2 || $1==3" 15798 e[^-1] "Compute $1-d gradient orientation of image$?." 15799 repeat $! l[$<] 15800 if $1==1 g x +abs. +. 1e-8 -/ 15801 elif $1==2 g xy +sqr +[-2,-1] +. 1e-8 sqrt. /... . /[-2,-1] 15802 else g xyz +sqr +[-3--1] +. 1e-8 sqrt. /[-4,-3] . /[-2,-1] 15803 fi 15804 endl done 15805 15806#@cli guided : [guide],radius[%]>=0,regularization[%]>=0 : radius[%]>=0,regularization[%]>=0 : (+) 15807#@cli : Blur selected images by guided image filtering. 15808#@cli : If a guide image is provided, it is used to drive the smoothing process. 15809#@cli : A guide image must be of the same xyz-size as the selected images. 15810#@cli : This command implements the filtering algorithm described in: 15811#@cli : He, Kaiming; Sun, Jian; Tang, Xiaoou, "Guided Image Filtering", 15812#@cli : IEEE Transactions on Pattern Analysis and Machine Intelligence, vol.35, no.6, pp.1397,1409, June 2013 15813#@cli : $ image.jpg +guided 5,400 15814 15815#@cli haar : scale>0 15816#@cli : Compute the direct haar multiscale wavelet transform of selected images. 15817#@cli : See also: ''ihaar''. 15818#@cli : $$ https://gmic.eu/oldtutorial/_haar 15819haar : check "isint(${1=1}) && $1>=0" 15820 e[^-1] "Compute haar transform of image$? with $1 scales." 15821 repeat $! l[$>] 15822 _haar 15823 repeat $1-1 15824 w={max(0,round(w/2^(1+$>))-1)} 15825 h={max(0,round(h/2^(1+$>))-1)} 15826 d={max(0,round(d/2^(1+$>))-1)} 15827 +z 0,0,0,$w,$h,$d _haar. j.. . rm. 15828 done 15829 endl done 15830 15831_haar : # Mono-scale direct haar transform. 15832 _haar_x _haar_y _haar_z 15833 15834_haar_x : # Direct haar transform along the x-axis. 15835 if w<=1 return fi 15836 if w%2 error[0--6] "Command 'haar': Invalid image width="{w}" (is not even)." fi 15837 +shift -1 r 50% +-[1] [0] +[0,1] / {sqrt(2)} a x 15838 15839_haar_y : # Direct haar transform along the y-axis. 15840 if h<=1 return fi 15841 if h%2 error[0--6] "Command 'haar': Invalid image height="{h}" (is not even)." fi 15842 +shift 0,-1 r 100%,50% +-[1] [0] +[0,1] / {sqrt(2)} a y 15843 15844_haar_z : # Direct haar transform along the z-axis. 15845 if d<=1 return fi 15846 if d%2 error[0--6] "Command 'haar': Invalid image depth="{h}" (is not even)." fi 15847 +shift 0,0,-1 r 100%,100%,50% +-[1] [0] +[0,1] / {sqrt(2)} a z 15848 15849#@cli heat_flow : _nb_iter>=0,_dt,_keep_sequence={ 0 | 1 } 15850#@cli : Apply iterations of the heat flow on selected images. 15851#@cli : Default values: 'nb_iter=10', 'dt=30' and 'keep_sequence=0'. 15852#@cli : $ image.jpg +heat_flow 20 15853heat_flow : skip ${1=10},${2=30},${3=0} 15854 e[^-1] "Apply $1 iterations of the heat flow on image$?, with time step $2." 15855 pde_flow $1,$2,laplacian,$3 15856 15857#@cli hessian : { xx | xy | xz | yy | yz | zz }...{ xx | xy | xz | yy | yz | zz },_boundary_conditions : (no arg) : 15858#@cli : Compute the hessian components (second derivatives) of selected images along specified axes. 15859#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 15860#@cli : (no arg) compute all significant components. 15861#@cli : Default value: 'boundary_conditions=1'. 15862#@cli : $ image.jpg hessian 15863hessian : skip "${1=},${2=}" 15864 15865 # Parse arguments. 15866 l[] 15867 if ['$1']==0 axes,boundary=,1 noarg # No 1st arg 15868 else 15869 is_axes={"s=['$1'];fill(s,k,isin(s[k],'xyz'));min(s)"} 15870 if !$is_axes axes,boundary=,1 noarg # Invalid 1st arg 15871 elif ['$2']==0 axes,boundary=$1,1 # No 2nd arg 15872 else 15873 is_boundary={"isint($2) && inrange($2,0,3)"} 15874 if !$is_boundary axes,boundary=,1 noarg # Invalid 2nd arg 15875 else axes,boundary=$1,$2 15876 fi 15877 fi 15878 fi 15879 onfail axes,boundary=,1 noarg # Invalid arguments 15880 endl 15881 15882 # Display log message. 15883 if '$axes'!=0 s_axes=" along axes '"$axes"'" fi 15884 s0,s1,s2,s3=dirichlet,neumann,periodic,mirror 15885 s_boundary=${s$boundary} 15886 e[^-1] "Compute hessian of image$?"$s_axes", with "$s_boundary" boundary conditions." 15887 15888 # Process images. 15889 repeat $! l[$<] nm={n} 15890 laxes=$axes if '$laxes'==0 if d>1 laxes=xxxyxzyyyzzz else laxes=xxxyyy fi fi 15891 ('$laxes') 15892 repeat int(w/2) 15893 a1,a2={`i[#1,2*$>]`},{`i[#1,2*$>+1]`} 15894 if _'$a1'>_'$a2' a1,a2=$a2,$a1 fi 15895 if 0${hessian_$a1$a2}>0 [hessian_$a1$a2] 15896 elif _'$a1'==_'x'" && "_'$a2'==_'x' (1,-2,1) +correlate[0] .,$boundary rm.. 15897 elif _'$a1'==_'x'" && "_'$a2'==_'y' (0.25,0,-0.25;0,0,0;-0.25,0,0.25) +correlate[0] .,$boundary rm.. 15898 elif _'$a1'==_'x'" && "_'$a2'==_'z' (0.25,0,-0.25/0,0,0/-0.25,0,0.25) +correlate[0] .,$boundary rm.. 15899 elif _'$a1'==_'y'" && "_'$a2'==_'y' (1;-2;1) +correlate[0] .,$boundary rm.. 15900 elif _'$a1'==_'y'" && "_'$a2'==_'z' (0.25;0;-0.25/0;0;0/-0.25;0;0.25) +correlate[0] .,$boundary rm.. 15901 elif _'$a1'==_'z'" && "_'$a2'==_'z' (1/-2/1) +correlate[0] .,$boundary rm.. 15902 fi 15903 nm. hessian_$a1$a2 15904 done 15905 rm[0,1] nm $nm 15906 endl done 15907 u $is_noaarg 15908 15909#@cli idct : _{ x | y | z }...{ x | y | z } : (no arg) 15910#@cli : Compute the inverse discrete cosine transform of selected images, optionally along the specified axes only. 15911#@cli : Output images are always evenly sized, so this command may change the size of the selected images. 15912#@cli : (dct images obtained with the 'dct' command are evenly sized anyway). 15913#@cli : Default values: (no arg) 15914#@cli : See also: ''dct''. 15915#@cli : $$ https://gmic.eu/oldtutorial/_dct-and-idct 15916idct : skip ${1=0} 15917 ('"$1"') 15918 is_axes={im>=_'x'" && "iM<=_'z'} 15919 if $is_axes 15920 e[0--3] "Compute inverse discrete cosine transform of image$? along axes '$1'." 15921 repeat w 15922 axis={i[$>]} 15923 if $axis==_'x' repeat $!-1 l[$>] if w>1 _idct fi endl done 15924 elif $axis==_'y' repeat $!-1 l[$>] if h>1 permute yxzc _idct permute yxzc fi endl done 15925 elif $axis==_'z' repeat $!-1 l[$>] if d>1 permute zxyc _idct permute yzxc fi endl done 15926 fi 15927 done 15928 rm. 15929 else 15930 rm. 15931 e[0--3] "Compute inverse discrete cosine transform of image$?." 15932 noarg 15933 repeat $! l[$>] 15934 if w>1 _idct fi 15935 if h>1 permute yxzc _idct permute yxzc fi 15936 if d>1 permute zxyc _idct permute yzxc fi 15937 endl done 15938 fi 15939 15940# 1D inverse transform (DCT-III) along the x-axis, for a single image. 15941_idct : 15942 if w%2 r {w+1},100%,100%,100%,0,0 fi 15943 / {sqrt(2/w)} +z[0] 0,0 *. {sqrt(2)} j.. .,0,0,0 rm. # Make the transform orthogonal. 15944 +mirror x shift. 1 *. -1 15945 100%,1,1,1,cos(x*pi/(2*w)) 15946 100%,1,1,1,sin(x*pi/(2*w)) 15947 +*[0,3] +*[1,2] +[-2,-1] 15948 *[0,2] *[1,2] -[0,1] 15949 ifft x k[0] / 2 15950 s x,2 mirror. x 15951 r[0] 200%,100%,100%,100%,4,0,0 15952 r[1] 200%,100%,100%,100%,4,0,1 15953 + 15954 15955#@cli iee 15956#@cli : Compute gradient-orthogonal-directed 2nd derivative of image(s). 15957#@cli : $ image.jpg iee 15958iee : 15959 e[^-1] "Compute gradient-orthogonal-directed 2nd derivative of image$?." 15960 repeat $! l[$>] 15961 if d==1 15962 +g xy,0 hessian... xxxyyy # ixx ixy iyy ix iy 15963 *... .. *[-4] . *[-4] -2 # ixx -2iyixy ixiyy ix iy 15964 +[-4,-3] *... .. # ixx -2ixiyixy+ix^2iyy ix iy 15965 sqr[-2,-1] *[-4] . +[-4,-3] # iy^2ixx-2ixiyixy+ix^2iyy ix^2 iy^2 15966 +[-2,-1] +. 1e-8 / # (iy^2ixx+2ixiyixy+ix^2iyy)/(ix^2+iy^2) 15967 else 15968 +inn laplacian.. - 15969 fi 15970 endl done 15971 15972#@cli ifft : _{ x | y | z }...{ x | y | z } : (+) 15973#@cli : Compute the inverse fourier transform (real and imaginary parts) of selected images. 15974#@cli : optionally along the specified axes only. 15975#@cli : See also: ''fft''. 15976#@cli : $$ https://gmic.eu/oldtutorial/_fft 15977 15978#@cli ihaar : scale>0 15979#@cli : Compute the inverse haar multiscale wavelet transform of selected images. 15980#@cli : See also: ''haar''. 15981#@cli : $$ https://gmic.eu/oldtutorial/_haar 15982ihaar : check "isint(${1=1}) && $1>=0" 15983 e[^-1] "Compute inverse haar transform of image$? with $1 scales." 15984 repeat $! l[$>] 15985 repeat $1-1 15986 w={max(0,round(w/2^(1+$<))-1)} 15987 h={max(0,round(h/2^(1+$<))-1)} 15988 d={max(0,round(d/2^(1+$<))-1)} 15989 +z 0,0,0,$w,$h,$d _ihaar. j.. . rm. 15990 done 15991 _ihaar 15992 endl done 15993 15994_ihaar : # Mono-scale inverse haar transform. 15995 _ihaar_x _ihaar_y _ihaar_z 15996 15997_ihaar_x : # Inverse haar transform along the x-axis. 15998 if w<=1 return fi 15999 if w%2 error[0--6] "Command 'ihaar': Invalid image width="{w}" (is not even)." fi 16000 s x,2 r 200% (-1,1) *[-2,-1] + / {sqrt(2)} 16001 16002_ihaar_y : # Inverse haar transform along the y-axis. 16003 if h<=1 return fi 16004 if h%2 error "Command 'ihaar': Invalid image height="{h}" (is not even)." fi 16005 s y,2 r 100%,200% (-1;1) r. {-2,w} *[-2,-1] + / {sqrt(2)} 16006 16007_ihaar_z : # Inverse haar transform along the z-axis. 16008 if d<=1 return fi 16009 if d%2 error "Command 'ihaar': Invalid image depth="{h}" (is not even)." fi 16010 s z,2 r 100%,100%,200% (-1/1) r. {-2,w},{-2,h} *[-2,-1] + / {sqrt(2)} 16011 16012#@cli ilaplacian : { nb_iterations>0 | 0 },_[initial_estimate] 16013#@cli : Invert selected Laplacian images. 16014#@cli : If given 'nb_iterations' is '0', inversion is done in Fourier space (single iteration), 16015#@cli : otherwise, by applying 'nb_iterations' of a Laplacian-inversion PDE flow. 16016#@cli : Note that the resulting inversions are just estimation of possible/approximated solutions. 16017#@cli : Default values: 'nb_iterations=0' and '[initial_estimated]=(undefined)'. 16018#@cli : $ image.jpg +laplacian +ilaplacian[-1] 0 16019ilaplacian : check "${1=0}>=0" skip "${2=}" 16020 is_estimate=${"is_image_arg $2"} nb_iter={round($1)} 16021 if !$nb_iter # Inversion in Fourier space 16022 if $is_estimate 16023 e[0--4] "Invert Laplacian image$? in Fourier space, with initial estimate $2." 16024 pass$2 1 ia=${-average_colors} rm. 16025 else 16026 e[0--4] "Invert Laplacian image$? in Fourier space." 16027 ia=0 16028 fi 16029 repeat $! l[$>] 16030 fft 100%,100%,1,1,"2*(cos(x*2*pi/w) + cos(y*2*pi/h)) - 4" =. 1 16031 /[-3,-2] . rm. 16032 = 0 ifft rm. 16033 endl done + '"begin(S = resize(["$ia"],s,0)); S"' 16034 16035 else # Inversion with PDE-flow 16036 if $is_estimate 16037 e[0--4] "Invert Laplacian image$? using $1 iterations of PDE flow and 16038 initial estimate $2." 16039 repeat $! pass$2 0 l[$>,-1] 16040 *[0] 5 i[1] (0,5,0;5,0,5;0,5,0) 16041 repeat $1 +convolve. [1] -. [0] +[-2,-1] /. 21 done k. # Optimized semi-implicit scheme, with dt=5 16042 endl done 16043 else 16044 e[0--4] "Invert Laplacian image$? using $1 iterations of PDE flow." 16045 repeat $! l[$>] 16046 * 5 (0,5,0;5,0,5;0,5,0) +f.. 0 16047 repeat $1 +convolve. [1] -. [0] +[-2,-1] /. 21 done k. # Optimized semi-implicit scheme, with dt=5 16048 endl done 16049 fi 16050 fi 16051 16052#@cli inn 16053#@cli : Compute gradient-directed 2nd derivative of image(s). 16054#@cli : $ image.jpg inn 16055inn : 16056 e[^-1] "Compute gradient-directed 2nd derivative of image$?." 16057 repeat $! l[$>] 16058 if d==1 16059 +g xy,0 hessian... xxxyyy # ixx ixy iyy ix iy 16060 *[-5] .. *[-4] . *[-4] 2 # ixixx 2iyixy iyy ix iy 16061 +[-5,-4] *[-4] .. # ix^2ixx+2ixiyixy iyy ix iy 16062 sqr[-2,-1] *... . +[-4,-3] # ix^2ixx+2ixiyixy+iy^2iyy ix^2 iy^2 16063 +[-2,-1] +. 1e-8 / # (ix^2ixx+2ixiyixy+iy^2iyy)/(ix^2+iy^2) 16064 else 16065 +g xyz,0 hessian[-4] xxxyxzyyyzzz # ixx ixy ixz iyy iyz izz ix iy iz 16066 *[-9] ... *[-8] .. *[-8] 2 *[-7] . *[-7] 2 # ixixx 2iyixy 2izixz iyy iyz izz ix iy iz 16067 +[-9--7] *[-7] ... # ix^2ixx+2ixiyixy+2ixizixy iyy iyz izz ix iy iz 16068 *[-6] .. *[-5] . *[-5] 2 # ix^2ixx+2ixiyixy+2ixizixy iyiyy 2iziyz izz ix iy iz 16069 +[-6,-5] *[-5] .. +[-6,-5] # ix^2ixx+2ixiyixy+2ixizixy+iy^2iyy+2iyiziyz izz ix iy iz 16070 sqr[-3--1] *[-4] . +[-5,-4] # ix^2ixx+2ixiyixy+2ixizixy+iy^2iyy+2iyiziyz+iz^2izz ix^2 iy^2 iz^2 16071 +[-3--1] +. 1e-8 / # (ix^2ixx+2ixiyixy+2ixizixy+iy^2iyy+2iyiziyz+iz^2izz)/(ix^2+iy^2+iz^2) 16072 fi 16073 endl done 16074 16075#@cli inpaint : [mask] : [mask],0,_fast_method : \ 16076# [mask],_patch_size>=1,_lookup_size>=1,_lookup_factor>=0,_lookup_increment!=0,_blend_size>=0,\ 16077# 0<=_blend_threshold<=1,_blend_decay>=0,_blend_scales>=1,_is_blend_outer={ 0 | 1 } : (+) 16078#@cli : Inpaint selected images by specified mask. 16079#@cli : If no patch size (or 0) is specified, inpainting is done using a fast average or median algorithm. 16080#@cli : Otherwise, it used a patch-based reconstruction method, that can be very time consuming. 16081#@cli : 'fast_method' can be { 0=low-connectivity average | 1=high-connectivity average | 2=low-connectivity median | \ 16082# 3=high-connectivity median }. 16083#@cli : Default values: 'patch_size=0', 'fast_method=1', 'lookup_size=22', 'lookup_factor=0.5', 'lookup_increment=1', \ 16084# 'blend_size=0', 'blend_threshold=0', 'blend_decay=0.05', 'blend_scales=10' and 'is_blend_outer=1'. 16085#@cli : $ image.jpg 100%,100% ellipse 50%,50%,30,30,0,1,255 ellipse 20%,20%,30,10,0,1,255 +inpaint[-2] [-1] remove[-2] 16086#@cli : $ image.jpg 100%,100% circle 30%,30%,30,1,255,0,255 circle 70%,70%,50,1,255,0,255 \ 16087# +inpaint[0] [1],5,15,0.5,1,9,0 remove[1] 16088 16089#@cli inpaint_pde : [mask],_nb_scales[%]>=0,_diffusion_type={ 0=isotropic | 1=Delaunay-guided | \ 16090# 2=edge-guided | 3=mask-guided },_diffusion_iter>=0 16091#@cli : Inpaint selected images by specified mask using a multiscale transport-diffusion algorithm. 16092#@cli : If 'diffusion type==3', non-zero values of the mask (e.g. a distance function) are used 16093#@cli : to guide the diffusion process. 16094#@cli : Default values: 'nb_scales=75%', 'diffusion_type=1' and 'diffusion_iter=20'. 16095#@cli : $ image.jpg 100%,100% ellipse[-1] 30%,30%,40,30,0,1,255 +inpaint_pde[0] [1] 16096inpaint_pde : check ${is_image_arg\ $1}" && ${2=75%}>=0 && isint(${3=1}) && $3>=0 && $3<=3 && ${4=20}>=0" 16097 s0="isotropic" s1="Delaunay-guided" s2="edge-guided" s3="mask-guided" 16098 e[^-1] "Inpaint image$? by mask $1, using a multiscale diffusion algorithm with $2 scales 16099 and $4 iterations of "${s$3}" diffusion." 16100 repeat $! nm={n} pass$1 l[$>,-1] 16101 nb_scalesM={ceil(log2(max(w,h,d)))} 16102 nb_scales={round(${"is_percent $2"}?$nb_scalesM*$2:$2)} 16103 nb_scales={max(1,min($nb_scales,$nb_scalesM))} 16104 nb_iter={max(5,$4)} 16105 16106 repeat $nb_scales 16107 {0,"S = 2^"$<"; round([ max(1,w/S), max(1,h/S), max(1,d/S), s ])"} 16108 100%,100%,100% 16109 eval[1] "const wl1 = w#-1 - 1; const hl1 = h#-1 - 1; const dl1 = d#-1 - 1; 16110 const w1 = max(1,w - 1); const h1 = max(1,h - 1); const d1 = max(1,d - 1); 16111 !i?( 16112 X = round(x*wl1/w1); Y = round(y*hl1/h1); Z = round(z*dl1/d1); 16113 I(#-2,X,Y,Z) += I(#0,x,y,z); 16114 ++i(#-1,X,Y,Z) 16115 );I" 16116 +max. 1 /[-3,-1] !=. 0 16117 16118 if !$> # First scale: Initialize by value propagation 16119 im={-2,im} +-.. {$im-1} *. .. 16120 +distance.. 1 *. -1 watershed.. . rm. 16121 +. {$im-1} mv. -3 16122 fi 16123 16124 if $>>0" || "$nb_scales==1 16125 16126 # Apply diffusion iterations. 16127 ri... ..,3 16128 if $3==0 # Isotropic diffusion 16129 repeat $nb_iter j... ..,0,0,0,0,1,. b... 0.5 done 16130 16131 elif $3==1 # Delaunay-guided 16132 +distance. 1 100%,100%,100%,{d==1?2:3} 16133 eval.. "* # Apply specific gradient scheme for distance function 16134 const boundary = 1; 16135 maxabs(a,b) = (abs(a)>abs(b)?a:b); 16136 ix = maxabs(j(1) - i,i - j(-1)); 16137 iy = maxabs(j(0,1) - i,i - j(0,-1)); 16138 d>1?( 16139 iz = maxabs(j(0,0,1) - i,i - j(0,0,-1)); 16140 copy(I(#-1),[ ix,iy,iz ],3,whd); 16141 ):copy(I(#-1),[ ix,iy ],2,whd)" 16142 rm.. orientation. 16143 repeat $nb_iter 16144 j[-4] ...,0,0,0,0,1,.. 16145 +warp[-4] .,1,2,1 *.. -1 warp[-5] ..,1,2,1 +[-5,-1] /[-4] 2 16146 done 16147 rm. 16148 16149 elif $3==2 # Edge-guided 16150 repeat $nb_iter 16151 +diffusiontensors... 0,1,1.5,0.5 16152 j[-4] ...,0,0,0,0,1,.. 16153 smooth[-4] .,1,10,0 rm. 16154 done 16155 16156 else # Mask-guided 16157 +r[1] .,2 g. a[-{d==1?2:3}--1] c orientation. 16158 repeat $nb_iter 16159 j[-4] ...,0,0,0,0,1,.. 16160 +warp[-4] .,1,2,1 *.. -1 warp[-5] ..,1,2,1 +[-5,-1] /[-4] 2 16161 done rm. 16162 fi 16163 j... ..,0,0,0,0,1,. 16164 fi 16165 rm[-2,-1] 16166 done 16167 nm. $nm rv[0,-1] rm. 16168 endl rm. done 16169 16170#@cli inpaint_flow : [mask],_nb_global_iter>=0,_nb_local_iter>=0,_dt>0,_alpha>=0,_sigma>=0 16171#@cli : Apply iteration of the inpainting flow on selected images. 16172#@cli : Default values: 'nb_global_iter=10', 'nb_local_iter=100', 'dt=5', 'alpha=1' and 'sigma=3'. 16173#@cli : $ image.jpg 100%,100% ellipse[-1] 30%,30%,40,30,0,1,255 inpaint_flow[0] [1] 16174inpaint_flow : check ${is_image_arg\ $1}" && ${2=10}>=0 && ${3=100}>=0 && ${4=5}>0 && ${5=1}>=0 && ${6=3}>=0" 16175 e[^-1] "Apply $2x$3 iterations of the inpainting flow on image$?, with mask $1, time step $4, alpha $5 and sigma $6." 16176 repeat $! pass$1 0 l[$>,-1] 16177 r. [0],[0],[0],1,0 inpaint.. [1] 16178 repeat $2 16179 progress {100*$>/($2-1)} 16180 +diffusiontensors.. 0,1,$5,$6,0 *. .. smooth... .,$3,$4,0 rm. 16181 done 16182 progress 100 16183 endl rm. done 16184 16185#@cli inpaint_holes : maximal_area[%]>=0,_tolerance>=0,_is_high_connectivity={ 0 | 1 } 16186#@cli : Inpaint all connected regions having an area less than specified value. 16187#@cli : Default values: 'maximal_area=4', 'tolerance=0' and 'is_high_connectivity=0'. 16188#@cli : $ image.jpg noise 5%,2 +inpaint_holes 8,40 16189inpaint_holes : check "${1=4}>=0 && ${2=0}>=0" skip ${3=0} 16190 e[^-1] "Inpaint holes with area less than $1 pixels in image$?, with tolerance $2 and "\ 16191 ${arg\ 1+!$3,high,low}" connectivity." 16192 repeat $! l[$>] 16193 100%,100%,100% 16194 area={if(${is_percent\ $1},$1*w*h*d,$1)} 16195 repeat s#0 sh[0] $> +area. $2,$3 <=. $1 -|[1,-1] rm. done 16196 if im k[0] whd={w},{h},{d} r 1,1,1,100%,2 r $whd,100% 16197 else inpaint[0] [1],0,{2*!$2+!!$3} k[0] fi 16198 endl done 16199 16200#@cli inpaint_morpho : [mask] 16201#@cli : Inpaint selected images by specified mask using morphological operators. 16202#@cli : $ image.jpg 100%,100% ellipse[-1] 30%,30%,40,30,0,1,255 +inpaint_morpho[0] [1] 16203inpaint_morpho : check ${is_image_arg\ $1} 16204 e[^-1] "Inpaint image$? by mask $1, using morphological operators." 16205 repeat $! pass$1 0 l[$>,-1] 16206 nm={0,n} im={0,im} iM={0,iM} im1={$im-1} iM1={$iM+1} 16207 channels. 0 ==. 0 16208 +f[0] $im1 j. [0],0,0,0,0,1,.. 16209 do 16210 +dilate. 3 16211 replace.. $im1,$iM1 16212 erode.. 3 16213 replace.. $iM1,$im1 16214 +[-2,-1] /. 2 16215 j. ...,0,0,0,0,1,.. 16216 while im==$im1 16217 k. nm $nm 16218 endl done 16219 16220#@cli inpaint_matchpatch : [mask],_nb_scales={ 0=auto | >0 },_patch_size>0,_nb_iterations_per_scale>0,\ 16221# _blend_size>=0,_allow_outer_blending={ 0 | 1 },_is_already_initialized={ 0 | 1 } 16222#@cli : Inpaint selected images by specified binary mask, using a multi-scale matchpatch algorithm. 16223#@cli : Default values: 'nb_scales=0', 'patch_size=9', 'nb_iterations_per_scale=10', 'blend_size=5',\ 16224# 'allow_outer_blending=1' and 'is_already_initialized=0'. 16225#@cli : $ image.jpg 100%,100% ellipse[-1] 30%,30%,40,30,0,1,255 +inpaint_matchpatch[0] [1] 16226inpaint_matchpatch : check ${is_image_arg\ $1}"&& ${2=0}>=0 && isint(${3=9}) && $3>0 && isint(${4=10}) && $4>0 && 16227 isint(${5=5}) && $5>=0" skip ${6=1},${7=0} 16228 e[^-1] "Inpaint image$? with mask $1, using a multiscale patch-matching algorithm with "\ 16229 ${"if $2 u \"$2 \" else u auto- fi"}\ 16230 "scales, $3x$3 patches, $4 iterations per scale and blending size $5." 16231 repeat $! pass$1 0 l[$>,-1] nm={0,n} 16232 16233 # Init variables and images. 16234 nm={0,n} nm img,mask 16235 nb_scales={max(1,round(if($2,$2,log2(min(w,h)/16)),1,1))} 16236 visu_size=${fitscreen[]" "{0,[w,h,1]},25%,50%} 16237 slices[img] 0 r[mask] [img],[img],1,1,0 !=[mask] 0 16238 if !$7 inpaint_pde[img] [mask],75% fi # Quick first estimate. 16239 im={img,im} -[img] $im 16240 16241 first_iter=1 iter=0 16242 repeat $nb_scales 16243 scale={100*(0.5^$<)} 16244 e[] "> Process scale "{1+$>}"/"$nb_scales" -> "$scale% 16245 progress {100*$>/max(1,$nb_scales-1)} 16246 16247 # Compute image and mask at current scales. 16248 +r[img,mask] $scale%,$scale%,1,100%,2 nm[-2,-1] scaled_img,scaled_mask 16249 >=[scaled_mask] 0.95 16250 if {scaled_mask,!iM} rm[scaled_img,scaled_mask] continue fi # Skip scale (if too low). 16251 +f[scaled_img] -4096 +j[scaled_img] .,0,0,0,0,1,[scaled_mask] rm.. nm. scaled_reference 16252 16253 coef={0.5^($nb_scales-$iter)} 16254 patch_size={v=round(max(min($3,5),$3*$coef));v+(1-(v%2))} 16255 patch_size={min(w,h,$patch_size)} 16256 blend_size={v=if($5,round(max(3,$5*$coef)));v+(1-(v%2))} 16257 iter+=1 16258 ==[scaled_mask] 0 16259 16260 if $first_iter # First iteration. 16261 16262 # Estimate initial correspondence map. 16263 100%,100%,1,1,x +f. y mv[scaled_mask] $! a[-3--1] c 16264 matchpatch[scaled_img] [scaled_reference],$patch_size,$patch_size,1,4,4,0,0,. 16265 rm[scaled_reference,-1] 16266 nm. correspondence 16267 first_iter=0 16268 16269 else # Standard iteration. 16270 16271 # Upscale correspondence map from previous scale. 16272 *[correspondence] 2 r[correspondence] 200%,200%,1,2 r[correspondence] [scaled_img],[scaled_img],1,2,0,1 16273 100%,100%,1,1,x +f. y a[-2,-1] c 16274 f[scaled_mask] "*if(i,1, 16275 upc = i(#"$correspondence",x-1,y,0,0); vpc = i(#"$correspondence",x-1,y,0,1); 16276 ucp = i(#"$correspondence",x,y-1,0,0); vcp = i(#"$correspondence",x,y-1,0,1); 16277 ucc = i(#"$correspondence",x,y,0,0); vcc = i(#"$correspondence",x,y,0,1); 16278 i(#-1,x,y,0,0) = (ucc==upc && vcc==vpc)?upc + 1:ucc; 16279 i(#-1,x,y,0,1) = (ucc==ucp && vcc==vcp)?vcp + 1:vcc; 16280 0)" 16281 rm[correspondence] nm. correspondence 16282 a[correspondence] [scaled_mask],c 16283 16284 # Refine correspondence map iteratively with matchpatch. 16285 nbs1={max(1,$nb_scales-1)} 16286 nb_iter={round(max(1,$4*(($<+1)/$nbs1)^2))} 16287 16288 repeat $nb_iter 16289 _inpaint_matchpatch[scaled_img] [correspondence],[scaled_mask],$blend_size,$6 16290 +matchpatch[scaled_img] [scaled_reference],$patch_size,$patch_size,1,4,4,0,0,[correspondence] 16291 j[correspondence] . rm. 16292 if {*1} w1[scaled_img] $visu_size,0 fi 16293 if {*2} w2[correspondence] $visu_size,1 fi 16294 done 16295 rm[scaled_img,scaled_mask,scaled_reference] channels[correspondence] 0,1 16296 fi 16297 16298 done 16299 progress 100 16300 16301 # Generate final result. 16302 if $correspondence 16303 ==[mask] 0 16304 _inpaint_matchpatch[img] [correspondence],[mask],$5,$6 16305 rm[correspondence] 16306 fi 16307 +[img] $im 16308 nm[0] $nm 16309 endl rm[mask] done 16310 16311# _inpaint_matchpatch : [correspondence_map],[mask],blend_size>0,_allow_outer_blending={ 0 | 1 } 16312_inpaint_matchpatch : 16313 pass$1 1 pass$2 {!$3" || "!$4} 16314 if !$3 16315 warp[0] [1],0,0,1 16316 else 16317 if $4 erode. $3 fi 16318 f[0] "*begin( 16319 boundary = 1; 16320 const patch_size = $3; 16321 const p2 = int(patch_size/2); 16322 const p1 = patch_size - p2 - 1; 16323 avg = resize([0],s#0); 16324 16325 # Pre-compute gaussian kernel for patch blending. 16326 wpq = resize([0],patch_size^2); 16327 g = 0; 16328 for (q = -p1, q<=p2, ++q, 16329 for (p = -p1, p<=p2, ++p, 16330 wpq[g++] = exp(-(p^2 + q^2)/(2*(0.3*patch_size)^2)); 16331 ); 16332 ); 16333 ); 16334 if (i#2,I, 16335 g = 0; 16336 avg = 0; 16337 norm = 0; 16338 for (q = -p1, q<=p2, ++q, 16339 for (p = -p1, p<=p2, ++p, 16340 U = I(#1,x + p,y + q); 16341 w = wpq[g++]; 16342 norm+=w; 16343 avg+=w*I(#0,U[0,2] - [p,q]); 16344 ); 16345 ); 16346 avg/norm)" 16347 fi 16348 k[0] 16349 16350# _inpaint_warping2d : fill-in zero-valued vectors in absolute 2d warping field (works even when 'spectrum>2'). 16351_inpaint_warping2d : 16352 repeat $! l[$>] 16353 100%,100%,100%,2,"> begin(const S = s#0; zero0 = vectorS(); zero1 = [0,0]; N = 0); I(#-1)==zero0?zero1:[++N,1]" 16354 s. c distance. 1 *. -1 16355 watershed.. . rm. 16356 16357 # Propagate offsets in each distinct voronoi cell. 16358 repeat 2 16359 f.. ">i?I:( # Forward propagation 16360 nP = vectors(); 16361 const sP = size(nP); 16362 r = i(#-1); 16363 (P = J(-1,-1))[0] && j(#-1,-1,-1)==r?(nP[0] = ++P[0]; nP[1] = ++P[1]; sP>2?copy(nP[2],P[2],sP-2)): 16364 (P = J(0,-1))[0] && j(#-1,0,-1)==r ?(nP[0] = P[0]; nP[1] = ++P[1]; sP>2?copy(nP[2],P[2],sP-2)): 16365 (P = J(1,-1))[0] && j(#-1,1,-1)==r ?(nP[0] = --P[0]; nP[1] = ++P[1]; sP>2?copy(nP[2],P[2],sP-2)): 16366 (P = J(-1,0))[0] && j(#-1,-1,0)==r ?(nP[0] = ++P[0]; nP[1] = P[1]; sP>2?copy(nP[2],P[2],sP-2)); 16367 nP)" 16368 f.. "<i?I:( # Backward propagation 16369 nP = vectors(); 16370 const sP = size(nP); 16371 r = i(#-1); 16372 (P = J(1,1))[0] && j(#-1,1,1)==r ?(nP[0] = --P[0]; nP[1] = --P[1]; sP>2?copy(nP[2],P[2],sP-2)): 16373 (P = J(0,1))[0] && j(#-1,0,1)==r ?(nP[0] = P[0]; nP[1] = --P[1]; sP>2?copy(nP[2],P[2],sP-2)): 16374 (P = J(-1,1))[0] && j(#-1,-1,1)==r?(nP[0] = ++P[0]; nP[1] = --P[1]; sP>2?copy(nP[2],P[2],sP-2)): 16375 (P = J(1,0))[0] && j(#-1,1,0)==r ?(nP[0] = --P[0]; nP[1] = P[1]; sP>2?copy(nP[2],P[2],sP-2)); 16376 nP)" 16377 done 16378 rm. 16379 endl done 16380 16381#@cli kuwahara : size>0 16382#@cli : Apply Kuwahara filter of specified size on selected images. 16383#@cli : $ image.jpg kuwahara 9 16384kuwahara : check $1>0 16385 e[^-1] "Apply Kuwahara filter of size $1 on image$?." 16386 repeat $! l[$>] 16387 s={s} 16388 +dilate $1 compose_channels. min 16389 +erode[0] $1 compose_channels. max 16390 -[-2,-1] 16391 $1,1,1,1,{1/$1} convolve[0] . transpose. convolve[0] . rm. 16392 p={int($1/2)} 16393 a[-2,-1] c 16394 f "v1=i(x-"$p",y-"$p",0,"$s",0,1); \ 16395 v2=i(x+"$p",y-"$p",0,"$s",0,1); \ 16396 v3=i(x-"$p",y+"$p",0,"$s",0,1); \ 16397 v4=i(x+"$p",y+"$p",0,"$s",0,1); \ 16398 vm=min(v1,v2,v3,v4); \ 16399 if(c>="$s",i, \ 16400 if(vm==v1,i(x-"$p",y-"$p",0,c,0,1), 16401 if(vm==v2,i(x+"$p",y-"$p",0,c,0,1), 16402 if(vm==v3,i(x-"$p",y+"$p",0,c,0,1), 16403 i(x+"$p",y+"$p",0,c,0,1)))))" 16404 channels 0,{s-2} 16405 endl done 16406 16407#@cli laplacian 16408#@cli : Compute Laplacian of selected images. 16409#@cli : $ image.jpg laplacian 16410laplacian : 16411 e[^-1] "Compute Laplacian of image$?." 16412 repeat $! l[$>] 16413 hessian ${arg\ 1+(d==1),xxyyzz,xxyy} + 16414 endl done 16415 16416#@cli lic : _amplitude>0,_channels>0 16417#@cli : Render LIC representation of selected vector fields. 16418#@cli : Default values: 'amplitude=30' and 'channels=1'. 16419#@cli : $ 400,400,1,2,'if(c==0,x-w/2,y-h/2)' +lic 200,3 quiver[-2] [-2],10,1,1,1,255 16420lic : skip ${1=30},${2=1} 16421 e[^-1] "Render LIC representation of 2D vector field$?, with amplitude $1 and $2 channel(s)." 16422 repeat $! l[$>] nm={0,n} 16423 channels 0,1 / {max(abs(im),abs(iM))} vector2tensor 16424 100%,100%,100%,$2 rand. 0,255 smooth. ..,$1 rm.. 16425 equalize 16426 nm $nm endl done 16427 16428#@cli map_tones : _threshold>=0,_gamma>=0,_smoothness>=0,nb_iter>=0 16429#@cli : Apply tone mapping operator on selected images, based on Poisson equation. 16430#@cli : Default values: 'threshold=0.1', 'gamma=0.8', 'smoothness=0.5' and 'nb_iter=30'. 16431#@cli : $ image.jpg +map_tones , 16432map_tones : skip ${1=0.1},${2=0.8},${3=0.5},${4=30} 16433 e[^-1] "Apply tone mapping operator on image$?, with threshold $1, gamma $2, smoothness $3 and $4 iterations." 16434 repeat $! l[$>] 16435 16436 # Estimate target divergence for each channel. 16437 +l s c repeat $! l[$>] 16438 g xy,1 a c +norm orientation.. 16439 m={im} M={iM} b. $3 n. $m,$M 16440 *. 'alpha=$1*iM;(alpha/(1e-10+i))*(i/(1e-10+alpha))^$2' 16441 * s c g.. x,-1 g. y,-1 + 16442 endl done a c * 0.25 endl 16443 16444 # Start Poisson-PDE iterations 16445 repeat $4 +laplacian.. *. 0.25 +. ... -. .. *. 800 +[-3,-1] /.. 801 c.. 0,255 done rm. 16446 16447 endl done 16448 16449#@cli map_tones_fast : _radius[%]>=0,_power>=0 16450#@cli : Apply fast tone mapping operator on selected images. 16451#@cli : Default values: 'radius=3%' and 'power=0.3'. 16452#@cli : $ image.jpg +map_tones_fast , 16453map_tones_fast : check "${1=3%}>=0 && ${2=0.3}>=0" 16454 e[^-1] "Apply fast tone mapping operator on image$?, with radius $1 and power $2." 16455 repeat $! l[$>] 16456 +luminance b. $1 n 0,1 16457 +*. 2 -. 1 abs. *. {$2*log(10)} exp. 16458 <=.. 0.5 ri. ... 16459 +*... -1 +. 1 ^. .. *. -1 +. 1 *. ... 16460 ^[-4,-2] ==.. 0 *[-3,-2] + 16461 endl done n 0,255 16462 16463#@cli meancurvature_flow : _nb_iter>=0,_dt,_keep_sequence={ 0 | 1 } 16464#@cli : Apply iterations of the mean curvature flow on selected images. 16465#@cli : Default values: 'nb_iter=10', 'dt=30' and 'keep_sequence=0'. 16466#@cli : $ image.jpg +meancurvature_flow 20 16467meancurvature_flow : skip ${1=10},${2=30},${3=0} 16468 e[^-1] "Apply $1 iterations of the mean curvature flow on image$?, with time step $2." 16469 pde_flow $1,$2,iee,$3 16470 16471#@cli median : size>=0,_threshold>0 : (+) 16472#@cli : Apply (opt. thresholded) median filter on selected images with structuring element size x size. 16473#@cli : $ image.jpg +median 5 16474 16475#@cli nlmeans : [guide],_patch_radius>0,_spatial_bandwidth>0,_tonal_bandwidth>0,_patch_measure_command : \ 16476# _patch_radius>0,_spatial_bandwidth>0,_tonal_bandwidth>0,_patch_measure_command 16477#@cli : Apply non local means denoising of Buades et al, 2005. on selected images. 16478#@cli : The patch is a gaussian function of 'std_patch_radius'. 16479#@cli : The spatial kernel is a rectangle of radius 'spatial_bandwidth'. 16480#@cli : The tonal kernel is exponential (`exp(-d^2/_tonal_bandwidth^2)`) 16481#@cli : with `d` the euclidean distance between image patches. 16482#@cli : Default values: 'patch_radius=4', 'spatial_bandwidth=4', 'tonal_bandwidth=10' and 'patch_measure_command=-norm'. 16483#@cli : $ image.jpg +noise 10 nlmeans[-1] 4,4,{0.6*${-std_noise}} 16484nlmeans: 16485 if ${"is_image_arg $1"} 16486 16487 # Guided-filtering 16488 check "${2=4}>0 && ${3=4}>0 && ${4=10}>0" skip "${5=-norm}" 16489 e[^-1] "Apply non-local means denoising on image$?, with guide $1, patch size $2, spatial bandwidth $3, 16490 tonal bandwidth $4 and patch measure command '$5'." 16491 pass$1 0 l. $5 k[0] endl # [1] preprocessed image used to compute weights. 16492 repeat $!-1 l[$>,-1] 16493 100%,100%,100%,100%,{-1.0/($4*$4)} # [2] compute a scaling. 16494 nlmeans_core[0] [1],[2],$2,$3 rm. # Apply the NLM denoising with image 1 and 2 as parameter. 16495 endl done 16496 rm. 16497 16498 else 16499 16500 # Non-guided filtering 16501 check "${1=4}>0 && ${2=4}>0 && ${3=10}>0" skip "${4=-norm}" 16502 e[^-1] "Apply non-local means denoising on image$?, with patch size $1, spatial bandwidth $2, 16503 tonal bandwidth $3 and patch measure command '$4'." 16504 repeat $! l[$>] 16505 +l $4 k[0] endl # [1] preprocessed image used to compute weights. 16506 100%,100%,100%,100%,{-1.0/($3*$3)} # [2] compute a scaling. 16507 nlmeans_core[0] [1],[2],$1,$2 k[0] # Apply the NLM denoising with image 1 and 2 as parameter. 16508 endl done 16509 fi 16510 16511#@cli nlmeans_core: _reference_image,_scaling_map,_patch_radius>0,_spatial_bandwidth>0 16512#@cli : Apply non local means denoising using a image for weight and a map for scaling 16513nlmeans_core : check ${is_image_arg\ $1}" && "${is_image_arg\ $2}" && $3>0 && $4>0" 16514 e[^-1] "Apply non-local means denoising using weight images $1, scaling map $2, patch size $3 and 16515 spatial bandwidth $4." 16516 pass$1 0 pass$2 0 16517 repeat $!-2 l[$>,-1,-2] 16518 # [0] original, [1] weights, [2] scaling [3] sum(weights * patch), [4] sum(weights), [5] max(weights) 16519 100%,100%,100%,{0,s},0 100%,100%,100%,{1,s},0 100%,100%,100%,{1,s},1e-6 16520 if d#0==1 16521 repeat 2*$4+1 j={$>-$4} repeat 2*$4+1 i={$>-$4} 16522 if $i!=0||$j!=0 16523 # Compute shifted images [6] and weight [7] 16524 +shift[0,1] $i,$j,0,0,2 -[7] [1] 16525 sqr[7] b[7] $3 *[7] [2] exp[7] 16526 # Accumulate weights 16527 *[6] [7] max[5] [7] +[4,7] +[3,6] 16528 fi 16529 done done 16530 else 16531 repeat 2*$4+1 k={$>-$4} repeat 2*$4+1 j={$>-$4} repeat 2*$4+1 i={$>-$4} 16532 if $i!=0||$j!=0||$k!=0 16533 # Compute shifted images [6] and weight [7] 16534 +shift[0,1] $i,$j,0,0,2 -[7] [1] 16535 sqr[7] b[7] $3 *[7] [2] exp[7] 16536 # Accumulate weights 16537 *[6] [7] max[5] [7] +[4,7] +[3,6] 16538 fi 16539 done done done 16540 fi 16541 rm[1,2] 16542 *[0] [3] +[1,0] +[1,2] # Add central patch 16543 / # Normalize 16544 endl done 16545 16546#@cli normalize_local : _amplitude>=0,_radius>0,_n_smooth>=0[%],_a_smooth>=0[%],_is_cut={ 0 | 1 },_min=0,_max=255 16547#@cli : Normalize selected images locally. 16548#@cli : Default values: 'amplitude=3', 'radius=16', 'n_smooth=4%', 'a_smooth=2%', 'is_cut=1', 'min=0' and 'max=255'. 16549#@cli : $ image.jpg normalize_local 8,10 16550normalize_local : 16551 check "${1=3}>=0 && ${2=16}>0 && isbool(${5=1})" skip ${3=4%},${4=2%},${6=0},${7=255} 16552 e[^-1] "Normalize image$? locally, with amplitude $1, radius $2, neighborhood smoothness $3 and 16553 average smoothness $4." 16554 repeat $! l[$>] 16555 +l erode {2*$2+1} s c min endl 16556 +l.. dilate {2*$2+1} s c max endl 16557 +b... $4 b[-3,-2] $3 16558 +-.. ... +. 0.01 -[-5] [-4] /[-5,-1] 16559 *[-3,-2] {$1+1} *. -$1 +... . +[-2,-1] 16560 if $5 max.. $6 min. $7 fi 16561 -. .. *[-3,-1] + 16562 if $5 c $6,$7 fi 16563 endl done 16564 16565#@cli normalized_cross_correlation : [mask] 16566#@cli : Compute normalized cross-correlation of selected images with specified mask. 16567#@cli : $ image.jpg +shift -30,-20 +normalized_cross_correlation[0] [1] 16568normalized_cross_correlation : check ${is_image_arg\ $1} 16569 e[^-1] "Compute normalized cross-correlation of image$? with mask $1." 16570 pass$1 0 norm repeat $!-1 . l[$>,-1] 16571 fft.. fft. [-2,-1] *.. [-5] *. [-6] 16572 -[-2,-1] *[-5,-3] *[-3,-2] +[-3,-2] [-2,-1] a[-2,-1] c norm. 16573 /... . /[-2,-1] ifft rm. 16574 endl done rm. 16575 16576#@cli percentile : [mask],0<=_min_percentile[%]<=100,0<=_max_percentile[%]<=100. 16577#@cli : Apply percentile averaging filter to selected images. 16578#@cli : Default values: 'min_percentile=0' and 'max_percentile=100'. 16579#@cli : $ image.jpg shape_circle 11,11 +percentile[0] [1],25,75 16580percentile : check ${"is_image_arg $1"}" && inrange(${2=0},0,100) && inrange(${3=100},0,100) && $2<=$3" 16581 vmin,vmax={_[${"is_percent $2"}?100*$2:$2,${"is_percent $3"}?100*$3:$3]} 16582 e[^-1] "Apply percentile averaging filter to image$?, with mask $1, "\ 16583 "min percentile "$vmin"% and max percentile "$vmax"%." 16584 16585 # Generate code for masking. 16586 pass$1 0 !=. 0 N={is} if !$N rm. return fi 128,$N 16587 eval.. "> 16588 begin( 16589 p = 0; 16590 const w2 = int(w/2); 16591 const h2 = int(h/2); 16592 ); 16593 i?( 16594 out = string('N[',p,']=j(',x - w2,',',y - h2,');'); 16595 copy(i(#-1,0,p++),out,size(out)); 16596 )" 16597 discard. 0 code={t} rm[-2,-1] 16598 16599 # Apply filter. 16600 f " 16601 begin( N = vector"$N"() ); 16602 const boundary = 1; 16603 const sS = size(N) - 1; 16604 const s0 = round(sS*"$vmin"%); 16605 const s1 = round(sS*"$vmax"%); 16606 const ds = 1 + s1 - s0; 16607 "$code" 16608 S = sort(N); 16609 res = 0; for (s = s0, s<=s1, ++s, res+=S[s]); res/=ds" 16610 16611#@cli peronamalik_flow : K_factor>0,_nb_iter>=0,_dt,_keep_sequence={ 0 | 1 } 16612#@cli : Apply iterations of the Perona-Malik flow on selected images. 16613#@cli : Default values: 'K_factor=20', 'nb_iter=5', 'dt=5' and 'keep_sequence=0'. 16614#@cli : $ image.jpg +heat_flow 20 16615peronamalik_flow : check "${1=20}>0 && ${2=5}>=0" skip ${3=5},${4=0} 16616 e[^-1] "Apply $2 iterations of the Perona-Malik flow on image$?, with K factor $1 and time step $3." 16617 m "_peronamalik_flow : 16618 +gradient xy,0 a[-2,-1] c norm. b. 0.8 /. $1 sqr. *. -1 exp. a[-2,-1] c 16619 f. '\"s1=s-1; 16620 C=i(x,y,z,s-1); 16621 if(c>=s1,0, 16622 (C+i(x+1,y,z,s-1,0,1))*(j(1,0,0,0,0,1)-i) - 16623 (C+i(x-1,y,z,s-1,0,1))*(i-j(-1,0,0,0,0,1)) + 16624 (C+i(x,y+1,z,s-1,0,1))*(j(0,1,0,0,0,1)-i) - 16625 (C+i(x,y-1,z,s-1,0,1))*(i-j(0,-1,0,0,0,1)))\"'" 16626 pde_flow $2,$3,_peronamalik_flow,$4 16627 um _peronamalik_flow 16628 16629#@cli phase_correlation : [destination] 16630#@cli : Estimate translation vector between selected source images and specified destination. 16631#@cli : $ image.jpg +shift -30,-20 +phase_correlation[0] [1] unroll[-1] y 16632phase_correlation : check ${"is_image_arg $1"} 16633 e[^-1] "Estimate shift between source image$? and destination $1." 16634 pass$1 16635 repeat $!-1 16636 normalized_cross_correlation[$>] . 16637 l[$>] eval " 16638 store([xM>=w/2?xM - w:xM, 16639 yM>=h/2?yM - h:yM, 16640 zM>=d/2?zM - d:zM]*=-1,'res',1,1,1,3)" 16641 endl 16642 $res nm. "[phase correlation]" rv[$>,-1] rm. 16643 done rm. 16644 16645#@cli pde_flow : _nb_iter>=0,_dt,_velocity_command,_keep_sequence={ 0 | 1 } 16646#@cli : Apply iterations of a generic PDE flow on selected images. 16647#@cli : Default values: 'nb_iter=10', 'dt=30', 'velocity_command=laplacian' and 'keep_sequence=0'. 16648#@cli : $ image.jpg +pde_flow 20 16649pde_flow : skip ${1=10},${2=30},${3=laplacian},${4=0} 16650 e[^-1] "Apply $1 iterations of the velocity flow '$3' on image$?, with time step $2." 16651 repeat $! l[$<] 16652 repeat $1 16653 +$3. *. {$2/(0.01+max(abs(im),abs(iM)))} 16654 if $4 +. .. else +[-2,-1] fi 16655 done 16656 if $4 rm[0] fi 16657 a x 16658 endl done 16659 if $4 s x,$1 fi 16660 16661#@cli periodize_poisson 16662#@cli : Periodize selected images using a Poisson solver in Fourier space. 16663#@cli : $ image.jpg +periodize_poisson array 2,2,2 16664periodize_poisson : 16665 e[^-1] "Periodize image$? using Poisson solver in Fourier space." 16666 repeat $! l[$>] 16667 s c repeat $! l[$>] 16668 mM={[im,iM]} sum={0,ia} 16669 laplacian ilaplacian 0 + $sum c $mM 16670 endl done a c 16671 endl done 16672 16673#@cli rbf : dx,_x0,_x1,_phi(r) : dx,dy,_x0,_y0,_x1,_y1,_phi(r) : dx,dy,dz,x0,y0,z0,x1,y1,z1,phi(r) 16674#@cli : Reconstruct 1D/2D or 3D image from selected sets of keypoints, by RBF-interpolation. 16675#@cli : A set of keypoints is represented by a vector-valued image, where each pixel represents a single keypoint. 16676#@cli : Vector components of a keypoint have the following meaning: 16677#@cli : - For 1D reconstruction: [ x_k, f1(k),...fN(k) ]. 16678#@cli : - For 2D reconstruction: [ x_k,y_k, f1(k),...,fN(k) ]. 16679#@cli : - For 3D reconstruction: [ x_k,y_k,z_k, f1(k),...,fN(k) ]. 16680#@cli : Values 'x_k','y_k' and 'z_k' are the spatial coordinates of keypoint 'k'. 16681#@cli : Values 'f1(k),..,fN(k)' are the 'N' components of the vector value of keypoint 'k'. 16682#@cli : The command reconstructs an image with specified size 'dx'x'dy'x'dz', with 'N' channels. 16683#@cli : Default values: 'x0=y0=z0=0', 'x1=dx-1', 'y1=dy-1', 'z1=dz-1', 'phi(r)=r^2*log(1e-5+r)'. 16684#@cli : $ sp colorful r2dx 400 100%,100% noise_poissondisk. 10 1,{is},1,5 \ 16685# eval[-2] "begin(p=0);i?(I[#-1,p++]=[x,y,I(#0)])" to_rgb[1] mul[0,1] dilate_circ[0] 5 +rbf[-1] {0,[w,h]} c[-1] 0,255 16686#@cli : $ 32,1,1,5,u([400,400,255,255,255]) rbf 400,400 c 0,255 16687rbf : 16688 $=a d_phi_r=r^2*log(1e-5+r) 16689 if isin($#,1,3,4) # 1D reconstruction 16690 dx,x0,x1=$a1,{$#>1?[$a2,$a3]:[0,$a1-1]} 16691 phi_r={`$#>3?['$a4']:'$d_phi_r'`} 16692 check $dx>0 16693 e[^-1] "Reconstruct 1D image from keypoint set$?, with size "$dx", "\ 16694 "from ("$x0") to ("$x1") and phi(r) = "$phi_r. 16695 repeat $! l[$>] nm={n} if !w $dx elif whd==1 channels. 1,100% r. $dx,1,1,100% else 16696 r 1,{whd},1,100%,-1 permute. cyzx 16697 $dx,1,1,{w-1},"* 16698 begin( 16699 phi(r) = ("$phi_r"); 16700 ref(crop(#0,0,0,0,0,1,h#0,1,1),X); 16701 ref(crop(#0,1,0,0,0,s,h#0,1,1,1),F); 16702 ref(vector(#h#0^2),M); 16703 repeat (h#0,k, 16704 for (l = 0, l<=k, ++l, 16705 r = abs(X[k] - X[l]); 16706 M[k*h#0 + l] = M[l*h#0 + k] = phi(r); 16707 ) 16708 ); 16709 ref(solve(M,F,s),W); 16710 const fx = ("$x1-$x0")/(w-1); 16711 ); 16712 ref(vectors(),res); x = (x - "$x0")*fx; 16713 repeat (h#0,k, r = abs(x - X[k]); res+=W[s*k,s]*phi(r))" 16714 k. nm $nm 16715 fi endl done 16716 16717 elif isin($#,2,6,7) # 2D reconstruction 16718 dx,dy,x0,y0,x1,y1=$a1,$a2,{$#>2?[$a3,$a4,$a5,$a6]:[0,0,[$a1,$a2]-1]} 16719 phi_r={`$#>6?['$a7']:'$d_phi_r'`} 16720 check $dx>0" && "$dy>0 16721 e[^-1] "Reconstruct 2D image from keypoint set$?, with size "$dx,$dy", "\ 16722 "from ("$x0,$y0") to ("$x1,$y1") and phi(r) = "$phi_r. 16723 repeat $! l[$>] nm={n} if !w $dx,$dy elif whd==1 channels 2,100% r. $dx,$dy,1,100% else 16724 r 1,{whd},1,100%,-1 permute. cyzx 16725 $dx,$dy,1,{w-2},"* 16726 begin( 16727 phi(r) = ("$phi_r"); 16728 ref(crop(#0,0,0,0,0,1,h#0,1,1),X); 16729 ref(crop(#0,1,0,0,0,1,h#0,1,1),Y); 16730 ref(crop(#0,2,0,0,0,s,h#0,1,1,1),F); 16731 ref(vector(#h#0^2),M); 16732 repeat (h#0,k, 16733 for (l = 0, l<=k, ++l, 16734 r = norm(X[k] - X[l],Y[k] - Y[l]); 16735 M[k*h#0 + l] = M[l*h#0 + k] = phi(r); 16736 ) 16737 ); 16738 ref(solve(M,F,s),W); 16739 const fx = ("$x1-$x0")/(w-1); 16740 const fy = ("$y1-$y0")/(h-1); 16741 ); 16742 ref(vectors(),res); x = (x - "$x0")*fx; y = (y - "$y0")*fy; 16743 repeat (h#0,k, r = norm(x - X[k], y - Y[k]); res+=W[s*k,s]*phi(r))" 16744 k. nm $nm 16745 fi endl done 16746 16747 elif isin($#,3,9,10) # 3D reconstruction 16748 dx,dy,dz,x0,y0,z0,x1,y1,z1=$a1,$a2,$a3,{$#>3?[$a4,$a5,$a6,$a7,$a8,$a9]:[0,0,0,[$a1,$a2,$a3]-1]} 16749 phi_r={`$#>9?['$arg10']:'$d_phi_r'`} 16750 check $dx>0" && "$dy>0" && "$dz>0 16751 e[^-1] "Reconstruct 3D image from keypoint set$?, with size "$dx,$dy,$dz", "\ 16752 "from ("$x0,$y0,$z0") to ("$x1,$y1,$z1") and phi(r) = "$phi_r. 16753 repeat $! l[$>] nm={n} if !w $dx,$dy,$dz elif whd==1 channels 3,100% r. $dx,$dy,$dz,100% else 16754 r 1,{whd},1,100%,-1 permute. cyzx 16755 $dx,$dy,$dz,{w-3},"* 16756 begin( 16757 phi(r) = ("$phi_r"); 16758 ref(crop(#0,0,0,0,0,1,h#0,1,1),X); 16759 ref(crop(#0,1,0,0,0,1,h#0,1,1),Y); 16760 ref(crop(#0,2,0,0,0,1,h#0,1,1),Z); 16761 ref(crop(#0,3,0,0,0,s,h#0,1,1,1),F); 16762 ref(vector(#h#0^2),M); 16763 repeat (h#0,k, 16764 for (l = 0, l<=k, ++l, 16765 r = norm(X[k] - X[l],Y[k] - Y[l],Z[k] - Z[l]); 16766 M[k*h#0 + l] = M[l*h#0 + k] = phi(r); 16767 ) 16768 ); 16769 ref(solve(M,F,s),W); 16770 const fx = ("$x1-$x0")/(w - 1); 16771 const fy = ("$y1-$y0")/(h - 1); 16772 const fz = ("$z1-$z0")/(d - 1); 16773 ); 16774 ref(vectors(),res); x = (x - "$x0")*fx; y = (y - "$y0")*fy; z = (z - "$z0")*fz; 16775 repeat (h#0,k, r = norm(x - X[k], y - Y[k], z - Z[k]); res+=W[s*k,s]*phi(r))" 16776 k. nm $nm 16777 fi endl done 16778 16779 else error[0--2] "Command 'rbf': invalid arguments '$*'." 16780 fi 16781 16782#@cli red_eye : 0<=_threshold<=100,_smoothness>=0,0<=attenuation<=1 16783#@cli : Attenuate red-eye effect in selected images. 16784#@cli : Default values: 'threshold=75', 'smoothness=3.5' and 'attenuation=0.1'. 16785#@cli : $ image.jpg +red_eye , 16786red_eye : skip ${1=75},${2=3.5},${3=0.1} 16787 e[^-1] "Attenuate red-eye effect in image$?, with threshold $1, smoothness $2 and attenuation $3." 16788 to_rgb rgb2ycbcr repeat $! l[$>] 16789 s c -. 128 +>=. $1% b. $2 sqrt. *. -1 +. 1 16790 n. $3,1 *[-2,-1] +. 128 a c ycbcr2rgb 16791 endl done 16792 16793#@cli remove_hotpixels : _mask_size>0, _threshold[%]>0 16794#@cli : Remove hot pixels in selected images. 16795#@cli : Default values: 'mask_size=3' and 'threshold=10%'. 16796#@cli : $ image.jpg noise 10,2 +remove_hotpixels , 16797remove_hotpixels : check ${1=3}>0 skip ${2=10%} 16798 e[^-1] "Remove hot pixels in image$?, with mask size $1 and threshold $2." 16799 repeat $! l[$>] 16800 +median $1 +- abs. >=. $2 16801 *.. . ==. 0 *[-3,-1] + 16802 endl done 16803 16804#@cli remove_pixels : number_of_pixels[%]>=0 16805#@cli : Remove specified number of pixels (i.e. set them to 0) from the set of non-zero pixels in selected images. 16806#@cli : $ image.jpg +remove_pixels 50% 16807remove_pixels : check "$1>=0" 16808 e[^-1] "Remove $1 of the non-zero pixels in image$?." 16809 repeat $! l[$>] 16810 +norm !=. 0 16811 N={is} # Number of non-zero pixels. 16812 n={round(if(${"is_percent $1"},$N*$1,$1))} # Number of pixels to remove. 16813 if $n<=0 rm. # No pixels to remove. 16814 elif $n>=$N rm. f 0 # All pixels to remove. 16815 elif $n>int($N/2) # More pixels to remove than to keep. 16816 remove_pixels. {$N-$n} ==. 0 * 16817 else # Less pixels to remove than to keep. 16818 d={d} r 100%,{d*h},1,100%,-1 # Force image to be in 2D. 16819 16820 # Retrieve coordinates of all non-zero pixels. 16821 100%,1,1,1,x 1,{-2,h},1,1,y +[-2,-1] 1 r[-2,-1] ..,. 16822 *[-2,-1] ... rm... 16823 y[-2,-1] a[-2,-1] x discard. y,0 16824 16825 # Generate a 1xN vector with at least n non-zero pixels. 16826 do 16827 1,100%,1,1 rand. 0,{h} <=. {$n*1.25} 16828 if is>=$n break else rm. fi 16829 while 1 16830 16831 # Generate a 1xn vector of coordinates to 'remove'. 16832 r. 2 *[-2,-1] discard. y,0 16833 i.. 1,100% rand.. 0,1 a[-2,-1] x sort. +,y 16834 rows. 0,{$n-1} -. 1 z. 1,3 16835 16836 # Set those pixels to 0 using a 3D object. 16837 i.. ({'CImg3d'},{h},{h}) 16838 1,100%,1,1,1 1,100%,1,1,y a[-2,-1] x 16839 3,100% 1,100%,1,1,1 y[-5--1] a[-5--1] y 16840 if s#0<=3 j3d.. .,0,0,0,1,0,0,0,0 16841 else [0],[0],1,1,1 j3d. ..,0,0,0,1,0,0,0,0 *[0,-1] 16842 fi 16843 rm. 16844 16845 r 100%,{h/$d},$d,100%,-1 # Resize to original dimension (eventually 3D). 16846 fi 16847 endl done 16848 16849#@cli rolling_guidance : std_deviation_s[%]>=0,std_deviation_r[%]>=0,_precision>=0 16850#@cli : Apply the rolling guidance filter on selected image. 16851#@cli : Rolling guidance filter is a fast image abstraction filter, described in: 16852#@cli : "Rolling Guidance Filter", Qi Zhang Xiaoyong, Shen Li, Xu Jiaya Jia, ECCV'2014. 16853#@cli : Default values: 'std_deviation_s=4', 'std_deviation_r=10' and 'precision=0.5'. 16854#@cli : $ image.jpg +rolling_guidance , +- 16855rolling_guidance : check "${1=4}>=0 && ${2=10}>=0 && ${3=0.5}>=0" 16856 e[^-1] "Apply rolling guidance filter on image$?, with standard deviations ($1,$2) and precision $3." 16857 precision={2^-$3} 16858 repeat $! l[$>] 16859 +b $1 16860 repeat 100 16861 if c>1 +norm. +bilateral... .,$1,$2 rm.. 16862 else +bilateral.. .,$1,$2 16863 fi 16864 -.. . std={-2,sqrt(iv)} rm.. 16865 if $std<$precision break fi 16866 done 16867 k. 16868 endl done 16869 16870#@cli sharpen : amplitude>=0 : amplitude>=0,edge>=0,_alpha[%],_sigma[%] 16871#@cli : Sharpen selected images by inverse diffusion or shock filters methods. 16872#@cli : 'edge' must be specified to enable shock-filter method. 16873#@cli : Default values: 'edge=0', 'alpha=0' and 'sigma=0'. 16874#@cli : $ image.jpg sharpen 300 16875#@cli : $ image.jpg blur 5 sharpen 300,1 16876sharpen : check "$1>=0 && ${2=0}>=0 && ${3=0}>=0 && ${4=0}>=0" 16877 if $2>0 # Shock filters 16878 e[0--3] "Sharpen image$? with shock filters, amplitude $1, edge $2, alpha $3 and sigma $4." 16879 repeat $! l[$>] 16880 im,iM={[im,iM]} 16881 +b $3 structuretensors. 0 b. $4 eigen. l.. max 0 s c + + 1 ^ {-0.5*$2} *. -1 +. 1 endl 16882 if {0,d>1} # 3D 16883 +f[0] "const boundary = 1; 16884 minmod(a,b) = (a*b<=0?0:minabs(a,b)); 16885 u = i(#-1,x,y,z,0); 16886 v = i(#-1,x,y,z,1); 16887 w = i(#-1,x,y,z,2); 16888 amp = i(#-2,x,y,z,0); 16889 Ippp = j(-1,-1,-1); Icpp = j(0,-1,-1); Inpp = j(1,-1,-1); 16890 Ipcp = j(-1,0,-1); Iccp = j(0,0,-1); Incp = j(1,0,-1); 16891 Ipnp = j(-1,1,-1); Icnp = j(0,1,-1); Innp = j(1,1,-1); 16892 Ippc = j(-1,-1,0); Icpc = j(0,-1,0); Inpc = j(1,-1,0); 16893 Ipcc = j(-1,0,0); Iccc = i; Incc = j(1,0,0); 16894 Ipnc = j(-1,1,0); Icnc = j(0,1,0); Innc = j(1,1,0); 16895 Ippn = j(-1,-1,1); Icpn = j(0,-1,1); Inpn = j(1,-1,1); 16896 Ipcn = j(-1,0,1); Iccn = j(0,0,1); Incn = j(1,0,1); 16897 Ipnn = j(-1,1,1); Icnn = j(0,1,1); Innn = j(1,1,1); 16898 ixx = Incc + Ipcc - 2*Iccc; 16899 ixy = 0.25*(Innc + Ippc - Inpc - Ipnc); 16900 ixz = 0.25*(Incn + Ipcp - Incp - Ipcn); 16901 iyy = Icnc + Icpc - 2*Iccc; 16902 iyz = 0.25*(Icnn + Icpp - Icnp - Icpn); 16903 izz = Iccn + Iccp - 2*Iccc; 16904 ixf = Incc - Iccc; 16905 ixb = Iccc - Ipcc; 16906 iyf = Icnc - Iccc; 16907 iyb = Iccc - Icpc; 16908 izf = Iccn - Iccc; 16909 izb = Iccc - Iccp; 16910 itt = u^2*ixx + v^2*iyy + w^2*izz + 2*u*v*ixy + 2*u*w*ixz + 2*v*w*iyz; 16911 it = u*minmod(ixf,ixb) + v*minmod(iyf,iyb) + w*minmod(izf,izb); 16912 amp*sign(itt)*abs(it)" 16913 16914 else # 2D 16915 +f[0] "const boundary = 1; 16916 minmod(a,b) = (a*b<=0?0:minabs(a,b)); 16917 u = i(#-1,x,y,z,0); 16918 v = i(#-1,x,y,z,1); 16919 amp = i(#-2,x,y,z,0); 16920 Ipp = j(-1,-1); Icp = j(0,-1); Inp = j(1,-1); 16921 Ipc = j(-1,0); Icc = i; Inc = j(1,0); 16922 Ipn = j(-1,1); Icn = j(0,1); Inn = j(1,1); 16923 ixx = Inc + Ipc - 2*Icc; 16924 ixy = 0.25*(Ipp + Inn - Ipn - Inp); 16925 iyy = Icn + Icp - 2*Icc; 16926 ixf = Inc - Icc; 16927 iyf = Icn - Icc; 16928 ixb = Icc - Ipc; 16929 iyb = Icc - Icp; 16930 itt = u^2*ixx + v^2*iyy + 2*u*v*ixy; 16931 it = y*minmod(ixf,ixb) + v*minmod(iyf,iyb); 16932 amp*sign(itt)*abs(it)" 16933 fi 16934 *. {$1/abs(maxabs(im,iM))} rm[-3,-2] - c $im,$iM 16935 endl done 16936 else # Inverse diffusion 16937 e[0--3] "Sharpen image$? with inverse diffusion and amplitude $1." 16938 repeat $! l[$>] 16939 im,iM={[im,iM]} +laplacian *. {$1/abs(maxabs(im,iM))} - c $im,$iM 16940 endl done 16941 fi 16942 16943#@cli smooth : amplitude[%]>=0,_sharpness>=0,0<=_anisotropy<=1,_alpha[%],_sigma[%],_dl>0,_da>0,\ 16944# _precision>0,_interpolation,_fast_approx={ 0 | 1 } : \ 16945# nb_iterations>=0,_sharpness>=0,_anisotropy,_alpha,_sigma,_dt>0,0 : [tensor_field],_amplitude>=0,_dl>0,_da>0,\ 16946# _precision>0,_interpolation,_fast_approx={ 0 | 1 } : \ 16947# [tensor_field],_nb_iters>=0,_dt>0,0 : (+) 16948#@cli : Smooth selected images anisotropically using diffusion PDE's, with specified field of 16949#@cli : diffusion tensors. 16950#@cli : 'interpolation' can be { 0=nearest | 1=linear | 2=runge-kutta }. 16951#@cli : Default values: 'sharpness=0.7', 'anisotropy=0.3', 'alpha=0.6', 'sigma=1.1', 'dl=0.8', 'da=30', \ 16952# 'precision=2', 'interpolation=0' and 'fast_approx=1'. 16953#@cli : $ image.jpg repeat 3 smooth 40,0,1,1,2 done 16954#@cli : $ image.jpg 100%,100%,1,2 rand[-1] -100,100 repeat 2 smooth[-1] 100,0.2,1,4,4 done warp[0] [-1],1,1 16955#@cli : $$ https://gmic.eu/oldtutorial/_smooth 16956 16957#@cli split_freq : smoothness>0[%] 16958#@cli : Split selected images into low and high frequency parts. 16959#@cli : $ image.jpg split_freq 2% 16960split_freq : 16961 e[^-1] "Split image$? into low and high frequency parts, with smoothness $1." 16962 repeat $! l[$>] +b $1 -[0] [1] rv endl done 16963 16964#@cli solve_poisson : "laplacian_command",_nb_iterations>=0,_time_step>0,_nb_scales>=0 16965#@cli : Solve Poisson equation so that applying 'laplacian[n]' is close to the result of 'laplacian_command[n]'. 16966#@cli : Solving is performed using a multi-scale gradient descent algorithm. 16967#@cli : If 'nb_scales=0', the number of scales is automatically determined. 16968#@cli : Default values: 'nb_iterations=60', 'dt=5' and 'nb_scales=0'. 16969#@cli : $ image.jpg command "foo : gradient x" +solve_poisson foo +foo[0] +laplacian[1] 16970solve_poisson : check "${2=60}>=0 && ${3=5}>0 && ${4=0}>=0" 16971 e[^-1] "Solve Poisson equation for image$?, for laplacian command '$1', with $2 iterations, time step $3 and "\ 16972 ${arg\ 1+($4==0),$4,auto}" scales." 16973 repeat $! l[$>] 16974 [0] 16975 repeat if($4,$4,int(max(log2(max(w,h))-1,1))) 16976 f={2^$<} 16977 r[1] {0,max(1,w/$f)},{0,max(1,h/$f)},1,100%,3 16978 +ri[0] [1],2 l. -$1 k[0] endl 16979 repeat $2 +laplacian.. -. .. *. {$3/max(1e-8,abs(im),abs(iM))} +[-3,-1] done 16980 rm. 16981 done 16982 rm[0] 16983 endl done 16984 16985#@cli split_details : _nb_scales>0,_base_scale[%]>=0,_detail_scale[%]>=0 16986#@cli : Split selected images into 'nb_scales' detail scales. 16987#@cli : If 'base_scale'=='detail_scale'==0, the image decomposition is done with 'a trous' wavelets. 16988#@cli : Otherwise, it uses laplacian pyramids with linear standard deviations. 16989#@cli : Default values: 'nb_scales=4', 'base_scale=0' and 'detail_scale=0'. 16990#@cli : $ image.jpg split_details , 16991split_details : check "isint(${1=4}) && $1>0 && ${2=0}>=0 && ${3=0}>=0" 16992 if ($2)==0" && "($3)==0 16993 e[^-1] "Split image$? using $1 spatial scales and 'a trous' wavelets." 16994 repeat $! l[$<] 16995 repeat $1-1 16996 +f. "begin(interpolation = 0; boundary = 1; d = 2^"$>"; d2 = d*2); 16997 i(x - d2) + i(x + d2) + 4*i(x - d) + 4*i(x + d) + 6*i;" 16998 /. 16 16999 if h>1 17000 f. "begin(interpolation = 0; boundary = 1; d = 2^"$>"; d2 = d*2); 17001 i(x,y - d2) + i(x,y + d2) + 4*i(x,y - d) + 4*i(x,y + d) + 6*i;" 17002 /. 16 17003 fi 17004 if d>1 17005 f. "begin(interpolation = 0; boundary = 1; d = 2^"$>"; d2 = d*2); 17006 i(x,y,z - d2) + i(x,y,z + d2) + 4*i(x,y,z - d) + 4*i(x,y,z + d) + 6*i;" 17007 /. 16 17008 fi 17009 -.. . 17010 done rv 17011 endl done 17012 else 17013 e[^-1] "Split image$? using $1 spatial scales with base scale $2 and detail scale $3." 17014 repeat $! l[$<] 17015 ss={max(0.3,if(${is_percent\ $2},$2*max(w,h),$2))} 17016 se={max(0.3,if(${is_percent\ $3},$3*max(w,h),$3))} 17017 ds={$se-$ss} 17018 repeat $1-1 +b. {$ss+$>*$ds/max(1,$1-2)} -.. . rv[-2,-1] done 17019 endl done 17020 fi 17021 17022#@cli structuretensors : _scheme={ 0=centered | 1=forward/backward } : (+) 17023#@cli : Compute the structure tensor field of selected images. 17024#@cli : Default value: 'scheme=1'. 17025#@cli : $ image.jpg structuretensors abs pow 0.2 17026#@cli : $$ https://gmic.eu/oldtutorial/_structuretensors 17027 17028#@cli solidify : _smoothness[%]>=0,_diffusion_type={ 0=isotropic | 1=Delaunay-guided | 2=edge-oriented },\ 17029# _diffusion_iter>=0 17030#@cli : Solidify selected transparent images. 17031#@cli : Default values: 'smoothness=75%', 'diffusion_type=1' and 'diffusion_iter=20'. 17032#@cli : $ image.jpg 100%,100% circle[-1] 50%,50%,25%,1,255 append c +solidify , display_rgba 17033solidify : check "${1=75%}>=0 && isint(${2=1}) && $2>=0 && $2<=2 && ${3=20}>=0" 17034 s0="isotropic" s1="Delaunay-guided" s2="edge-oriented" 17035 e[^-1] "Solidify transparent image$? with smoothness $1 and $3 iterations of "${s$2}" diffusion." 17036 repeat $! l[$>] split_opacity 17037 if $!>1 <=. 128 inpaint_pde.. [1],${1-3} rm. c 0,255 fi 17038 endl done 17039 17040#@cli syntexturize : _width[%]>0,_height[%]>0 17041#@cli : Resynthetize 'width'x'height' versions of selected micro-textures by phase randomization. 17042#@cli : The texture synthesis algorithm is a straightforward implementation of the method described in : 17043#@cli : <http://www.ipol.im/pub/art/2011/ggm_rpn/>. 17044#@cli : Default values: 'width=height=100%'. 17045#@cli : $ image.jpg crop 2,282,50,328 +syntexturize 320,320 17046syntexturize : check "${1=100%}>0 && ${2=$1}>0" 17047 e[^-1] "Resynthetize $1x$2 versions of texture$? by phase randomization." 17048 repeat $! l[$>] 17049 17050 # Prepare input image data. 17051 mM={[im,iM]} repeat s sh. $> sum$>={is} var$>={iv} rm. done # Retrieve some stats for post-normalization. 17052 nw={if(${is_percent\ $1},$1*w,$1)} 17053 nh={if(${is_percent\ $2},$2*h,$2)} 17054 repeat s sum$>*={$nw*$nh/(w*h)} done # Re-estimate output (0,0) frequency. 17055 17056 if $nw>w||$nh>h # Spot extension required when rendering on bigger image. 17057 periodize_poisson 17058 100%,100% rectangle. 5,5,{w-6},{h-6},1,1 b. 2 n. 0,1 17059 $nw,$nh,1,{-2,s} fc. ${average_colors...} 17060 j. ...,{(w-{-2,w})/2},{(h-{-2,h})/2},0,0,1,.. 17061 rm[-3,-2] 17062 else 17063 r $nw,$nh,1,100%,0,0,0.5,0.5 17064 periodize_poisson 17065 fi 17066 fft 17067 17068 # Compute coherent random phase. 17069 100%,100% rand. {-pi},{pi} 17070 =. 0 17071 if !(w%2) =. {(u<0.5)*pi},{int(w/2)} fi 17072 if !(h%2) =. {(u<0.5)*pi},0,{int(h/2)} fi 17073 if !(h%2)&&!(h%2) =. {(u<0.5)*pi},{int(w/2)},{int(h/2)} fi 17074 17075 # Add random phase to fft of input image. 17076 +sin. cos.. 17077 +*[-4,-1] +*[-4,-3] +[-2,-1] 17078 *[-5,-3] *[-3,-2] -[-3,-2] 17079 17080 # Get synthetized result and normalize it. 17081 repeat s =.. ${sum$>},0,0,0,$> =. 0,0,0,0,$> done 17082 ifft rm. 17083 repeat s sh. $> avg={ia} -. $avg *. {sqrt(${var$>}/if(iv,iv,1))} +. $avg rm. done 17084 c $mM 17085 17086 endl done 17087 17088#@cli syntexturize_matchpatch : _width[%]>0,_height[%]>0,_nb_scales>=0,_patch_size>0,_blending_size>=0,_precision>=0 17089#@cli : Resynthetize 'width'x'height' versions of selected micro-textures using a patch-matching algorithm. 17090#@cli : If 'nbscales==0', the number of scales used is estimated from the image size. 17091#@cli : Default values: 'width=height=100%', 'nb_scales=0', 'patch_size=7', 'blending_size=5' and 'precision=1'. 17092#@cli : $ image.jpg crop 25%,25%,75%,75% syntexturize_matchpatch 512,512 17093syntexturize_matchpatch : check "${1=100%}>0 && ${2=$1}>0 && isint(${3=0}) && $3>=0 && isint(${4=7}) && $4>0 && 17094 ${5=5}>=0 && ${6=1}>=0" 17095 e[^-1] "Resynthetize $1x$2 version(s) of texture$? using a patch-matching algorithm with "\ 17096 ${"if $3 u \"$3 \" else u auto- fi"}"scales, $4x$4 patches, blending size $5 and precision $6." 17097 repeat $! l[$>] 17098 nb_scales={round(if($3,$3,log2(min(w,h)/16)),1,1)} 17099 width={if(${"is_percent $1"},round(w*$1,1,1),$1)} 17100 height={if(${"is_percent $2"},round(h*$2,1,1),$2)} 17101 17102 repeat $nb_scales 17103 scale={100*(0.5^$<)} 17104 +r[0] $scale%,$scale%,1,3,2 17105 17106 if !$> 17107 17108 # Initialization. 17109 {1+round(w*$width/{0,w},1,1)},{1+round(h*$height/{0,h},1,1)},1,1 17110 17111 noise. 0.2,2 ==. 1 +distance. 1 *. -1 17112 label_fg.. 0 watershed.. . rm. 17113 17114 100%,100%,1,1,x +f. y a[-2,-1] c channels. 0,2 17115 +blend. ..,shapeaverage -.. . rm. 17116 channels. 0,1 17117 17118 {-2,iM+1} rand. 0,{-4,w} +rand. 0,{-4,h} a[-2,-1] c 17119 map... . rm. +[-2,-1] round. 17120 s. c %.. {-3,w} %. {-3,h} a[-2,-1] c 17121 17122 else 17123 17124 # Upscale. 17125 rv[-2,-1] channels. 0,1 17126 *. 2 r. 200%,200%,1,2,1 17127 f. "*upc = i(x - 1,y,0,0); 17128 vpc = i(x - 1,y,0,1); 17129 ucp = i(x,y - 1,0,0); 17130 vcp = i(x,y - 1,0,1); 17131 ucc = i(x,y,0,0); 17132 vcc = i(x,y,0,1); 17133 if (ucc==upc && vcc==vpc && c==0, upc + 1, 17134 if (ucc==ucp && vcc==vcp && c==1, vcp + 1,i))" 17135 fi 17136 17137 # Synthesis. 17138 psize={-2,min(w,h,$4)} 17139 repeat 1+$6*$< 17140 psynth={int(max(3,$5*$scale%))} 17141 +warp_patch.. .,$psynth 17142 matchpatch. ...,$psize,$psize,1,4,4,0,0,.. rm.. 17143 done 17144 rm.. 17145 17146 done 17147 warp_patch.. .,$5 17148 rm. r $width,$height,1,100%,0,0,0.5,0.5 17149 endl done 17150 17151# _syntexturize_matchpatch : [correspondence_map],blend_size>0 17152_syntexturize_matchpatch : check ${is_image_arg\ $1}" && isint(${2=3}) && $2>=0" 17153 if $2<=1 pass$1 warp[^-1] .,0 rm. 17154 else repeat $! pass$1 l[$>,-1] 17155 [1],[1],1,[0] 17156 f. "*begin( 17157 boundary = 1; 17158 const patch_size = $2; 17159 const p2 = int(patch_size/2); 17160 const p1 = patch_size - p2 - 1; 17161 avg = resize([0],s#0); 17162 17163 # Pre-compute gaussian kernel. 17164 wpq = resize([0],patch_size^2); 17165 g = 0; 17166 for (q = -p1, q<=p2, ++q, 17167 for (p = -p1, p<=p2, ++p, 17168 wpq[g++] = exp(-(p^2 + q^2)/(2*(0.3*patch_size)^2)); 17169 ); 17170 ); 17171 ); 17172 g = 0; 17173 avg = 0; 17174 norm = 0; 17175 for (q = -p1, q<=p2, ++q, 17176 for (p = -p1, p<=p2, ++p, 17177 U = I(#1,x + p,y + q); 17178 w = wpq[g++]; 17179 avg+=w*I(#0,U - [p,q]); 17180 norm+=w; 17181 ); 17182 ); 17183 avg/norm" 17184 k. 17185 endl done fi 17186 17187#@cli tv_flow : _nb_iter>=0,_dt,_keep_sequence={ 0 | 1 } 17188#@cli : Apply iterations of the total variation flow on selected images. 17189#@cli : Default values: 'nb_iter=10', 'dt=30' and 'keep_sequence=0'. 17190#@cli : $ image.jpg +tv_flow 40 17191tv_flow : skip ${1=10},${2=30},${3=0} 17192 e[^-1] "Apply $1 iterations of the total variation flow on image$?, with time step $2." 17193 pde_flow $1,$2,curvature,$3 17194 17195#@cli unsharp : radius[%]>=0,_amount>=0,_threshold[%]>=0 17196#@cli : Apply unsharp mask on selected images. 17197#@cli : Default values: 'amount=2' and 'threshold=0'. 17198#@cli : $ image.jpg blur 3 +unsharp 1.5,15 cut 0,255 17199unsharp : check "${2=2}>=0" skip ${3=0} 17200 e[^-1] "Apply unsharp mask on image$?, with radius $1, amount $2 and threshold $3." 17201 repeat $! 17202 +b[$>] $1 -. [$>] 17203 if $3 +norm. >=. $3 *[-2,-1] fi 17204 *. $2 -[$>,-1] 17205 done 17206 17207#@cli unsharp_octave : _nb_scales>0,_radius[%]>=0,_amount>=0,threshold[%]>=0 17208#@cli : Apply octave sharpening on selected images. 17209#@cli : Default values: 'nb_scales=4', 'radius=1', 'amount=2' and 'threshold=0'. 17210#@cli : $ image.jpg blur 3 +unsharp_octave 4,5,15 cut 0,255 17211unsharp_octave : check "${1=4}>0 && ${3=2}>=0" skip ${2=1},${4=0} 17212 e[^-1] "Apply octave sharpening on image$?, with $1 scales, radius $2, amount $3 and threshold $4." 17213 repeat $! l[$>] nm={0,n} 17214 +f 0 weight=0 17215 repeat $1 17216 +unsharp[0] {$2*2^-$<},$3,$4 *. {2^-$>} 17217 weight+={2^-$>} 17218 +[1,-1] 17219 done 17220 rm[0] / $weight 17221 nm $nm endl done 17222 17223#@cli vanvliet : std_deviation>=0[%],order={ 0 | 1 | 2 | 3 },axis={ x | y | z | c },_boundary_conditions : (+) 17224#@cli : Apply Vanvliet recursive filter on selected images, along specified axis and with 17225#@cli : specified standard deviation, order and boundary conditions. 17226#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 17227#@cli : Default value: 'boundary_conditions=1'. 17228#@cli : $ image.jpg +vanvliet 3,1,x 17229#@cli : $ image.jpg +vanvliet 30,0,x vanvliet[-2] 30,0,y add 17230 17231#@cli voronoi 17232#@cli : Compute the discrete Voronoi diagram of non-zero pixels in selected images. 17233#@cli : $ 400,400 noise 0.2,2 eq 1 +label_fg 0 voronoi[-1] +gradient[-1] xy,1 append[-2,-1] c \ 17234# norm[-1] ==[-1] 0 map[-2] 2,2 mul[-2,-1] normalize[-2] 0,255 dilate_circ[-2] 4 reverse max 17235voronoi : 17236 e[^-1] "Compute the discrete Voronoi diagram of non-zero pixels in image$?." 17237 repeat $! l[$>] s c repeat $! l[$>] 17238 +!=. 0 distance. 1 *. -1 17239 watershed.. . rm. 17240 endl done a c endl done 17241 17242#@cli watermark_fourier : text,_size>0 17243#@cli : Add a textual watermark in the frequency domain of selected images. 17244#@cli : Default value: 'size=33'. 17245#@cli : $ image.jpg +watermark_fourier "Watermarked!" +display_fft remove[-3,-1] normalize 0,255 \ 17246# append[-4,-2] y append[-2,-1] y 17247watermark_fourier : check ${2=33}>0 17248 e[^-1] "Add textual watermark '$1' with size $2 in the frequency domain of image$?." 17249 i[0] 0 t[0] "$1",0,0,$2,1,1 >=[0] 0.5 autocrop[0] 0 17250 repeat $!-1 w2={int(w/2)} h2={int(h/2)} 17251 fft. 17252 shift[-2,-1] $w2,$h2,0,0,2 17253 [0],[0],1,{s} 17254 j[-3,-2] .,3,3,0,0,1,[0] 17255 mirror[0] x 17256 j[-3,-2] .,{{-2,w}-2-{0,w}},3,0,0,1,[0] 17257 mirror[0] y 17258 j[-3,-2] .,{{-2,w}-2-{0,w}},{{-2,h}-2-{0,h}},0,0,1,[0] 17259 mirror[0] x 17260 j[-3,-2] .,3,{{-2,h}-2-{0,h}},0,0,1,[0] 17261 mirror[0] y 17262 rm. 17263 shift[-2,-1] -$w2,-$h2,0,0,2 17264 ifft[-2,-1] rm. 17265 mv. 1 done 17266 rm[0] 17267 17268#@cli watershed : [priority_image],_is_high_connectivity={ 0 | 1 } : (+) 17269#@cli : Compute the watershed transform of selected images. 17270#@cli : Default value: 'is_high_connectivity=1'. 17271#@cli : $ 400,400 noise 0.2,2 eq 1 +distance 1 mul[-1] -1 label[-2] watershed[-2] [-1] mod[-2] 256 map[-2] 0 reverse 17272 17273#--------------------------------- 17274# 17275#@cli :: Features Extraction 17276# 17277#--------------------------------- 17278 17279#@cli area : tolerance>=0,is_high_connectivity={ 0 | 1 } 17280#@cli : Compute area of connected components in selected images. 17281#@cli : Default values: 'is_high_connectivity=0'. 17282#@cli : $ image.jpg luminance stencil[-1] 1 +area 0 17283#@cli : $$ https://gmic.eu/oldtutorial/_area 17284area : check "$1>=0" skip ${2=0} 17285 e[^-1] "Compute area of connected components in image$?, with tolerance $1 and "\ 17286 ${arg\ 1+!$2,high,low}" connectivity." 17287 repeat $! l[$>] s c 17288 repeat $! label[$>] $1,$2 nb={$>,1+iM} +histogram[$>] $nb,0,{$nb-1} map[$>] . rm. done 17289 a c endl done 17290 17291#@cli area_fg : tolerance>=0,is_high_connectivity={ 0 | 1 } 17292#@cli : Compute area of connected components for non-zero values in selected images. 17293#@cli : Similar to 'area' except that 0-valued pixels are not considered. 17294#@cli : Default values: 'is_high_connectivity=0'. 17295#@cli : $ image.jpg luminance stencil[-1] 1 +area_fg 0 17296area_fg : check "$1>=0" skip ${2=0} 17297 e[^-1] "Compute area of foreground connected components in image$?, with tolerance $1 and "\ 17298 ${arg\ 1+!$2,high,low}" connectivity." 17299 repeat $! l[$>] s c 17300 repeat $! label_fg[$>] $1,$2 nb={$>,1+iM} +histogram[$>] $nb,0,{$nb-1} =. 0 map[$>] . rm. done 17301 a c endl done 17302 17303#@cli at_line : x0[%],y0[%],z0[%],x1[%],y1[%],z1[%] 17304#@cli : Retrieve pixels of the selected images belonging to the specified line (x0,y0,z0)-(x1,y1,z1). 17305#@cli : $ image.jpg +at_line 0,0,0,100%,100%,0 line[0] 0,0,100%,100%,1,0xFF00FF00,255,0,0 17306at_line : check ${7=100%}>=0 17307 e[^-1] "Retrieve pixels of image$?, belonging to line ($1,$2,$3)-($4,$5,$6)." 17308 repeat $! l[$>] 17309 x0={if(${is_percent\ $1},(w-1)*$1,$1)} 17310 y0={if(${is_percent\ $2},(h-1)*$2,$2)} 17311 z0={if(${is_percent\ $3},(d-1)*$3,$3)} 17312 x1={if(${is_percent\ $4},(w-1)*$4,$4)} 17313 y1={if(${is_percent\ $5},(h-1)*$5,$5)} 17314 z1={if(${is_percent\ $6},(d-1)*$6,$6)} 17315 ($x0,$x1^$y0,$y1^$z0,$z1) 17316 r. {1+max(abs($x1-$x0),abs($y1-$y0),abs($z1-$z0))},1,1,3,3 17317 round. 1 warp[0] .,0,0,0 rm. 17318 endl done 17319 17320#@cli at_quadrangle : x0[%],y0[%],x1[%],y1[%],x2[%],y2[%],x3[%],y3[%],_interpolation,_boundary_conditions : \ 17321# x0[%],y0[%],z0[%],x1[%],y1[%],z1[%],x2[%],y2[%],z2[%],x3[%],y3[%],z3[%],_interpolation,_boundary_conditions 17322#@cli : Retrieve pixels of the selected images belonging to the specified 2D or 3D quadrangle. 17323#@cli : 'interpolation' can be { 0=nearest-neighbor | 1=linear | 2=cubic }. 17324#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 17325#@cli : $ image.jpg params=5%,5%,95%,5%,60%,95%,40%,95% +at_quadrangle $params polygon.. 4,$params,0.5,255 17326at_quadrangle : check "$#>=8 && $#<=14 && $#!=11" 17327 _at_quadrangle{$#<12?2:3} $* 17328 17329_at_quadrangle2 : check "${9=1}>=0 && $9<=2 && ${10=0}>=0 && $10<=3" 17330 repeat $! l[$>] 17331 x0={round(${"is_percent $1"}?(w-1)*$1:$1)} 17332 y0={round(${"is_percent $2"}?(h-1)*$2:$2)} 17333 x1={round(${"is_percent $3"}?(w-1)*$3:$3)} 17334 y1={round(${"is_percent $4"}?(h-1)*$4:$4)} 17335 x2={round(${"is_percent $5"}?(w-1)*$5:$5)} 17336 y2={round(${"is_percent $6"}?(h-1)*$6:$6)} 17337 x3={round(${"is_percent $7"}?(w-1)*$7:$7)} 17338 y3={round(${"is_percent $8"}?(h-1)*$8:$8)} 17339 ($x0,$x1;$x3,$x2^$y0,$y1;$y3,$y2) 17340 r. {P0=[$x0,$y0];P1=[$x1,$y1];P2=[$x2,$y2];P3=[$x3,$y3];\ 17341 1+round([max(norm(P1-P0),norm(P3-P2)),max(norm(P3-P0),norm(P2-P1))])},1,2,3 17342 warp.. .,0,$9,$10 rm. 17343 endl done 17344 17345_at_quadrangle3 : check "${13=1}>=0 && $13<=2 && ${14=0}>=0 && $14<=3" 17346 repeat $! l[$>] 17347 x0={round(${"is_percent $1"}?(w-1)*$1:$1)} 17348 y0={round(${"is_percent $2"}?(h-1)*$2:$2)} 17349 z0={round(${"is_percent $3"}?(h-1)*$3:$3)} 17350 x1={round(${"is_percent $4"}?(w-1)*$4:$4)} 17351 y1={round(${"is_percent $5"}?(h-1)*$5:$5)} 17352 z1={round(${"is_percent $6"}?(h-1)*$6:$6)} 17353 x2={round(${"is_percent $7"}?(w-1)*$7:$7)} 17354 y2={round(${"is_percent $8"}?(h-1)*$8:$8)} 17355 z2={round(${"is_percent $9"}?(h-1)*$9:$9)} 17356 x3={round(${"is_percent $10"}?(w-1)*$10:$10)} 17357 y3={round(${"is_percent $11"}?(h-1)*$11:$11)} 17358 z3={round(${"is_percent $12"}?(h-1)*$12:$12)} 17359 ($x0,$x1;$x3,$x2^$y0,$y1;$y3,$y2^$z0,$z1;$z3,$z2) 17360 r. {P0=[$x0,$y0,$z0];P1=[$x1,$y1,$z1];P2=[$x2,$y2,$z2];P3=[$x3,$y3,$z2];\ 17361 1+round([max(norm(P1-P0),norm(P3-P2)),max(norm(P3-P0),norm(P2-P1))])},1,3,3 17362 warp.. .,0,$13,$14 rm. 17363 endl done 17364 17365#@cli barycenter 17366#@cli : Compute the barycenter vector of pixel values. 17367#@cli : $ 256,256 ellipse 50%,50%,20%,20%,0,1,1 deform 20 +barycenter +ellipse[-2] {@0,1},5,5,0,10 17368barycenter : 17369 e[^-1] "Compute the barycenter vector of pixel values of image$?." 17370 norm repeat $! l[$>] nm={0,b} 17371 sum={is} 17372 if $sum>0 17373 if d>1 +* 'z' z={is} rm. else z=0 fi 17374 if h>1 +* 'y' y={is} rm. else y=0 fi 17375 * 'x' x={is} rm. 17376 ({$x/$sum};{$y/$sum};{$z/$sum}) 17377 else ({w/2},{h/2},{d/2}) rm.. 17378 fi 17379 nm "[barycenter of '"$nm"']" endl done 17380 17381#@cli delaunay : _output_type={ 0=image | 1=coordinates/triangles } 17382#@cli : Generate discrete 2D Delaunay triangulation of non-zero pixels in selected images. 17383#@cli : Input images must be scalar. 17384#@cli : Each pixel of the output image is a triplet (a,b,c) meaning the pixel belongs to 17385#@cli : the Delaunay triangle 'ABC' where 'a','b','c' are the labels of the pixels 'A','B','C'. 17386#@cli : $ 400,400 rand 32,255 100%,100% noise. 0.4,2 eq. 1 mul +delaunay 17387#@cli : $ image.jpg 100%,100% noise. 2,2 eq. 1 delaunay. +blend shapeaverage0 17388delaunay : skip "${1=0}" 17389 mode=0 if s=['"$1"'];s=='0'||s=='1' mode=$1 else mode=0 noarg fi 17390 s0,s1=image,coordinates 17391 e[^-1] "Generate discrete 2D Delaunay triangulation of non-zero pixels in image$?, in "${s$mode}" mode." 17392 repeat $! l[$<] bnm={b} nm={n} 17393 17394 # Extract and label non-zero pixels. 17395 1,64,1,2 =. 1,0,100% 17396 f.. "begin(N = 0); I!=0?(da_push([x,y]);++N):0; end(resize(#-1,1,da_size(),1,2,0))" 17397 17398 # Construct discrete voronoi diagram. 17399 +neq.. 0 distance. 1 *. -1 watershed... . rm. 17400 17401 # Extract Delaunay triangles from discrete voronoi. 17402 1,64,1,3 17403 eval... " 17404 V = crop(x,y,2,2); 17405 min(V)?( 17406 V[1]==V[0] && V[2]!=V[0] && V[3]!=V[0] && V[3]!=V[2]?( # [ a,a,b,c ] 17407 da_push([ V[0],V[2],V[3] ]); 17408 ):(V[2]==V[0] && V[1]!=V[0] && V[3]!=V[0] && V[3]!=V[1]) || # [ a,b,a,c ] 17409 (V[1]==V[2] && V[0]!=V[1] && V[3]!=V[0] && V[3]!=V[1])?( # [ a,b,b,c ] 17410 da_push([ V[0],V[1],V[3] ]); 17411 ):(V[3]==V[0] && V[1]!=V[0] && V[2]!=V[0] && V[2]!=V[1]) || # [ a,b,c,a ] 17412 (V[1]==V[3] && V[0]!=V[1] && V[2]!=V[0] && V[2]!=V[1]) || # [ a,b,c,b ] 17413 (V[2]==V[3] && V[0]!=V[1] && V[0]!=V[2] && V[1]!=V[2]) ?( # [ a,b,c,c ] 17414 da_push([ V[0],V[1],V[2] ]); 17415 ):V[0]!=V[1] && V[0]!=V[2] && V[0]!=V[3] && V[1]!=V[2] && V[1]!=V[3] && V[2]!=V[3]?( # [ a,b,c,d ] 17416 da_push([ V[0],V[1],V[2] ]); 17417 da_push([ V[1],V[3],V[2] ]); 17418 ); 17419 end(resize(#-1,1,da_size(),1,3,0)); 17420 )" 17421 17422 # Return output in expected mode. 17423 if $mode k[-2,-1] nm.. ${bnm}_points nm. ${bnm}_faces 17424 else {0,[w,h,1,3]} eval.. "polygon(#-1,3,I[#1,i0],I[#1,i1],I[#1,i2],1,i0,i1,i2)" k. nm $nm fi 17425 endl done 17426 17427#@cli detect_skin : 0<=tolerance<=1,_skin_x,_skin_y,_skin_radius>=0 17428#@cli : Detect skin in selected color images and output an appartenance probability map. 17429#@cli : Detection is performed using CbCr chromaticity data of skin pixels. 17430#@cli : If arguments 'skin_x', 'skin_y' and 'skin_radius' are provided, skin pixels are learnt 17431#@cli : from the sample pixels inside the circle located at ('skin_x','skin_y') with radius 'skin_radius'. 17432#@cli : Default value: 'tolerance=0.5' and 'skin_x=skiny=radius=-1'. 17433detect_skin : check "${1=0.5}>=0 && $1<=1" skip ${2=-1},${3=-1},${4=-1} 17434 if $2<0||$3<=0||$4<=0 17435 e[0--3] "Detect skin in image$?, using tolerance $1." 17436 m0=120.9292108800069 17437 m1=142.5745272918084 17438 A=0.09749985486268997 17439 B=0.06388871371746063 17440 C=0.05250053107738495 17441 to_rgb srgb2rgb rgb2ycbcr channels 1,2 17442 repeat $! l[$>] 17443 whd={w},{h},{d} r {w*h*d},2,1,1,-1 17444 s y -[0] $m0 -[1] $m1 a y 17445 i[0] ($A,$B;$B,$C) +m* rm[0] 17446 * s y + *. {$1-1} exp. 17447 r $whd,1,-1 17448 endl done 17449 else 17450 e[0--3] "Detect skin in image$?, using tolerance $1 and target circle at ($2,$3) with radius $4." 17451 to_rgb srgb2rgb rgb2ycbcr channels 1,2 17452 repeat $! l[$>] 17453 100%,100% circle[1] $2,$3,$4,1,1 +f[1] 'if(i,y,-1)' f[1] 'if(i,x,-1)' discard[1,2] -1 a[1,2] c 17454 +warp[0] [1],0,0 rm[1] 17455 s[1] c 17456 m0={1,ia} -[1] $m0 17457 m1={2,ia} -[2] $m1 17458 M={h} a[1,2] x +transpose[1] rv[1,2] m*[1,2] /[1] $M invert[1] 17459 rv whd={w},{h},{d} r[1] {w*h*d},2,1,1,-1 17460 s[1] y -[1] $m0 -[2] $m1 a[1,2] y +m* rm[0] 17461 * s y + *. {$1-1} exp. 17462 r $whd,1,-1 17463 endl done 17464 fi 17465 17466#@cli displacement : [source_image],_smoothness,_precision>=0,_nb_scales>=0,_iteration_max>=0,is_backward={ 0 | 1 },\ 17467# _[guide] : (+) 17468#@cli : Estimate displacement field between specified source and selected target images. 17469#@cli : If 'smoothness>=0', regularization type is set to isotropic, else to anisotropic. 17470#@cli : If 'nbscales==0', the number of scales used is estimated from the image size. 17471#@cli : Default values: 'smoothness=0.1', 'precision=5', 'nb_scales=0', 'iteration_max=10000', 'is_backward=1' \ 17472# and '[guide]=(unused)'. 17473#@cli : $ image.jpg +rotate 3,1,0,50%,50% +displacement[-1] [-2] quiver[-1] [-1],15,1,1,1,{1.5*iM} 17474 17475#@cli distance : isovalue[%],_metric : isovalue[%],[metric],_method : (+) 17476#@cli : Compute the unsigned distance function to specified isovalue, opt. according to a custom metric. 17477#@cli : 'metric' can be { 0=chebyshev | 1=manhattan | 2=euclidean | 3=squared-euclidean }. 17478#@cli : 'method' can be { 0=fast-marching | 1=low-connectivity dijkstra | 2=high-connectivity dijkstra | \ 17479# 3=1+return path | 4=2+return path }. 17480#@cli : Default value: 'metric=2' and 'method=0'. 17481#@cli : $ image.jpg threshold 20% distance 0 pow 0.3 17482#@cli : $ 400,400 set 1,50%,50% +distance[0] 1,2 +distance[0] 1,1 distance[0] 1,0 mod 32 threshold 16 append c 17483#@cli : $$ https://gmic.eu/oldtutorial/_distance 17484 17485#@cli fftpolar 17486#@cli : Compute fourier transform of selected images, as centered magnitude/phase images. 17487#@cli : $ image.jpg fftpolar ellipse 50%,50%,10,10,0,1,0 ifftpolar 17488fftpolar : 17489 e[^-1] "Compute fourier transform of image$?, as centered magnitude/phase images." 17490 repeat $! l[$<] 17491 fft complex2polar shift {-round(w/2)},{-round(h/2)},{-round(d/2)},0,2 17492 endl done 17493 17494#@cli histogram : nb_levels>0[%],_min_value[%],_max_value[%] : (+) 17495#@cli : Compute the histogram of selected images. 17496#@cli : If value range is set, the histogram is estimated only for pixels in the specified 17497#@cli : value range. Argument 'max_value' must be specified if 'min_value' is set. 17498#@cli : Default values: 'min_value=0%' and 'max_value=100%'. 17499#@cli : $ image.jpg +histogram 64 display_graph[-1] 400,300,3 17500 17501#@cli histogram_nd : nb_levels>0[%],_value0[%],_value1[%] 17502#@cli : Compute the 1D,2D or 3D histogram of selected multi-channels images (having 1,2 or 3 channels). 17503#@cli : If value range is set, the histogram is estimated only for pixels in the specified 17504#@cli : value range. 17505#@cli : Default values: 'value0=0%' and 'value1=100%'. 17506#@cli : $ image.jpg channels 0,1 +histogram_nd 256 17507histogram_nd : check $1>0 skip ${2=0%},${3=100%} 17508 e[^-1] "Compute histogram of multi-channels image$?, using $1 levels in range [$1,$2]." 17509 percent_nblevels=${"is_percent $1"} 17510 percent_min=${"is_percent $2"} 17511 percent_max=${"is_percent $3"} 17512 repeat $! l[$>] s={s} 17513 r {w*h*d},{min(3,s)},1,1,-1 17514 vmin=$2 vmax=$3 17515 if $percent_min||$percent_max 17516 im={im} iM={iM} 17517 vmin={if($percent_min,$im+($iM-$im)*$2,$2)} 17518 vmax={if($percent_max,$im+($iM-$im)*$3,$3)} 17519 fi 17520 dv={$vmax-$vmin} 17521 nb_levels={max(1,round(if($percent_nblevels,$1*(1+$vmax-$vmin),$1)))} 17522 f 'if(i>=$vmin&&i<=$vmax,if(i==$vmax,$nb_levels-1,int((i-$vmin)*$nb_levels/($vmax-$vmin))),-1)' 17523 pointcloud 1,$nb_levels,{if($s>1,$nb_levels,1)},{if($s>2,$nb_levels,1)} 17524 endl done 17525 17526#@cli histogram_cumul : _nb_levels>0,_is_normalized={ 0 | 1 },_val0[%],_val1[%] 17527#@cli : Compute cumulative histogram of selected images. 17528#@cli : Default values: 'nb_levels=256', 'is_normalized=0', 'val0=0%' and 'val1=100%'. 17529#@cli : $ image.jpg +histogram_cumul 256 histogram[0] 256 display_graph 400,300,3 17530histogram_cumul : check ${1=256}>0 skip ${2=0},${3=0%},${4=100%} 17531 arg 1+!$2,"normalized ","" 17532 e[^-1] "Compute "${}"cumulative histogram of image$?, using $1 levels." 17533 histogram $1,$3,$4 cumulate if $2 repeat $! /[$>] {$>,iM} done fi 17534 17535#@cli histogram_pointwise : nb_levels>0[%],_value0[%],_value1[%] 17536#@cli : Compute the histogram of each vector-valued point of selected images. 17537#@cli : If value range is set, the histogram is estimated only for values in the specified 17538#@cli : value range. 17539#@cli : Default values: 'value0=0%' and 'value1=100%'. 17540histogram_pointwise : skip ${2=0%},${3=100%} 17541 e[^-1] "Compute the pointwise histogram of vector-valued points in image$?, with $1 levels." 17542 repeat $! l[$>] nm={0,n} 17543 nb_levels={round(if(${is_percent\ $1},(iM-im)*$1,$1))} 17544 value0={if(${is_percent\ $2},im+(iM-im)*$2,$2)} 17545 value1={if(${is_percent\ $3},im+(iM-im)*$3,$3)} 17546 - $value0 * {$nb_levels/max(1,abs($value1-$value0))} c 0,{$nb_levels-1} round 17547 w={w} h={h} d={d} r {w*h*d},{s},1,1,-1 17548 i.. (0,{w-1}) r.. .,.,1,1,3 round.. 17549 r[-2,-1] 300%,100%,1,1,4 shift. 1 +[-2,-1] y. 17550 i.. ({'CImg3d'},{h/3},{h/3}) 17551 (1,0;1,{h/3-1}) r. 2,{-2,h/3},1,1,3 round. 17552 3,100%,1,1,1 1,100%,1,1,-1 y[-5,-3,-2] a[-5--1] y 17553 {$w*$h*$d},$nb_levels j3d. ..,0,0,0,1,0,0,0 rm.. 17554 r $w,$h,$d,$nb_levels,-1 17555 nm $nm endl done 17556 17557#@cli hough : _width>0,_height>0,gradient_norm_voting={ 0 | 1 } 17558#@cli : Compute hough transform (theta,rho) of selected images. 17559#@cli : Default values: 'width=512', 'height=width' and 'gradient_norm_voting=1'. 17560#@cli : $ image.jpg +blur 1.5 hough[-1] 400,400 blur[-1] 0.5 add[-1] 1 log[-1] 17561hough : check "${1=512}>0 && ${2=$1}>0" skip ${3=1} 17562 e[^-1] "Compute $1x$2 hough transform of image$?, "${arg\ 1+!$3,with,without}" gradient norm voting." 17563 slices 50% luminance repeat $! l[$>] nm={0,n} 17564 rhomax={sqrt(w^2+h^2)/2} 17565 g (0,{w-1}) (0;{{-2,h}-1}) r[-2,-1] {-3,w},{-3,h},1,1,3 -.. {w/2} -. {h/2} 17566 complex2polar[-4--1] -. ... polar2complex[-2,-1] rm. 17567 +<. 0 *. {pi} +[-3,-1] abs. %.. {2*pi} 17568 *. {$2/$rhomax} *.. {0.5*$1/pi} 17569 y[-3--1] x {w} mv[-4] $! if !$3 f. 1 fi 17570 a y pointcloud 1 r $1,$2,1,1,0 17571 nm $nm endl done 17572 17573#@cli ifftpolar 17574#@cli : Compute inverse fourier transform of selected images, from centered magnitude/phase images. 17575ifftpolar : 17576 e[^-1] "Compute inverse fourier transform of image$?, from centered magnitude/phase images." 17577 repeat int($!/2) l[$>,{$>+1}] 17578 shift {round(w/2)},{round(h/2)},{round(d/2)},0,2 polar2complex ifft rm. 17579 endl done 17580 17581#@cli isophotes : _nb_levels>0 17582#@cli : Render isophotes of selected images on a transparent background. 17583#@cli : Default value: 'nb_levels=64' 17584#@cli : $ image.jpg blur 2 isophotes 6 dilate_circ 5 display_rgba 17585isophotes : skip ${1=64} 17586 e[^-1] "Render isophote maps from images$?, with $1 levels." 17587 to_rgba repeat $! l[$>] 17588 +luminance repeat $1 +isoline3d[1] {$>*255/($1-1)} done rm[1] +3d[^0] col3d. 1 17589 [0],[0] j3d. ..,0,0,0,1,0,0,0 rm.. * 17590 endl done 17591 17592#@cli label : _tolerance>=0,is_high_connectivity={ 0 | 1 },_is_L2_norm={ 0 | 1 } : (+) 17593#@cli : Label connected components in selected images. 17594#@cli : Default values: 'tolerance=0', 'is_high_connectivity=0' and 'is_L2_norm=1'. 17595#@cli : $ image.jpg luminance threshold 60% label normalize 0,255 map 0 17596#@cli : $ 400,400 set 1,50%,50% distance 1 mod 16 threshold 8 label mod 255 map 2 17597#@cli : $$ https://gmic.eu/oldtutorial/_label 17598 17599#@cli label_fg : tolerance>=0,is_high_connectivity={ 0 | 1 } 17600#@cli : Label connected components for non-zero values (foreground) in selected images. 17601#@cli : Similar to 'label' except that 0-valued pixels are not labeled. 17602#@cli : Default value: 'is_high_connectivity=0'. 17603label_fg : check "$1>=0" skip ${2=0} 17604 e[^-1] "Label foreground connected components on image [1], with tolerance $1 and "\ 17605 ${arg\ 1+!$2,high,low}" connectivity." 17606 repeat $! l[$>] 17607 if d>1 +z -1,-1,-1,100%,100%,100% label. $1,$2 z. 1,1,1,100%,100%,100% 17608 else +z -1,-1,100%,100% label. $1,$2 z. 1,1,100%,100% 17609 fi 17610 norm.. !=.. 0 * +histogram {1+iM} =. 0 17611 >. 0 cumulate. map.. . rm. 17612 endl done 17613 17614#@cli laar 17615#@cli : Extract the largest axis-aligned rectangle in non-zero areas of selected images. 17616#@cli : Rectangle coordinates are returned in status, as a sequence of numbers x0,y0,x1,y1. 17617#@cli : $ shape_cupid 256 coords=${-laar} normalize 0,255 to_rgb rectangle $coords,0.5,0,128,0 17618laar : 17619 e[^-1] "Extract the largest axis-aligned rectangle in non-zero areas of image$?." 17620 res= sep= 17621 repeat $! l[$>] 17622 +channels 0 gt. 0 nm. shape 17623 +cumulate[shape] xy nm. cumul 17624 val={i[-1,2]} 17625 if !$val res.=-1,-1,-1,-1 # All black 17626 elif $val==wh res.=0,0,{[w,h]-1} # All white 17627 else 17628 17629 # Step 1: Compute largest square. 17630 Rin,Rout=0,{min(w,h)+1} 17631 P0,P= 17632 do 17633 Rmid={int(($Rin+$Rout)/2)} 17634 Q=${_laar\ $Rmid,$Rmid,$P} 17635 if narg($Q) Rin=$Rmid P0=$Q P=$Q else Rout=$Rmid P= fi 17636 while $Rin!=$Rout-1 17637 if $Rin==1 P=${_laar\ 1,1} fi 17638 17639 # Step 2: Compute largest rectangle, for W>H. 17640 maxA,maxW,maxH=0 maxcoords= 17641 P=$P0 W,H=$Rin 17642 for $H>0 17643 A={$W*$H} if $A>$maxA maxA,maxW,maxH=$A,$W,$H maxP={[$P][0,2]} fi 17644 nW={$W+1} 17645 Q=${_laar\ $nW,$H,$P} 17646 if narg($Q) W=$nW P=$Q 17647 elif $H>1 17648 pH={$H-1} 17649 Q=${_laar\ $nW,$pH} 17650 if narg($Q) W,H=$nW,$pH P=$Q 17651 else H-=2 P= 17652 fi 17653 else break 17654 fi 17655 done 17656 17657 # Step 3: Compute largest rectangle, for H>W. 17658 P=$P0 W,H=$Rin 17659 for $W>0 17660 A={$W*$H} if $A>$maxA maxA,maxW,maxH=$A,$W,$H maxP={[$P][0,2]} fi 17661 nH={$H+1} 17662 Q=${_laar\ $W,$nH,$P} 17663 if narg($Q) H=$nH P=$Q 17664 elif $W>1 17665 pW={$W-1} 17666 Q=${_laar\ $pW,$nH} 17667 if narg($Q) W,H=$pW,$nH P=$Q 17668 else W-=2 P= 17669 fi 17670 else break 17671 fi 17672 done 17673 17674 res.=$sep$maxP,{[$maxP]+[$maxW,$maxH]-1} sep=, 17675 fi 17676 rm[shape,cumul] 17677 endl done u $res 17678 17679# $1,$2: Rectangle width and height. 17680# ${3--1}: Coordinates of candidate locations. If empty, full-search is done. 17681# Return the list of upper-left rectangle coordinates that fit. 17682# Images [shape] and [cumul] must be defined. 17683_laar : skip "${3=}" 17684 fn="cumul(x0,y0,x1,y1) = ( 17685 _px0 = x0 - 1; 17686 _py0 = y0 - 1; 17687 i(#"$cumul,"x1,y1) + i(#"$cumul",_px0,_py0) - i(#"$cumul",x1,_py0) - i(#"$cumul",_px0,y1); 17688 );" 17689 res= 17690 if narg($3) # Test suggested locations 17691 (${3--1}) r. 2,{w/2},1,1,-1 s. x a[-2,-1] c 17692 f. ${fn}"x1 = i0 + $1 - 1; y1 = i1 + $2 - 1; 17693 i(#"$shape",i0,i1) && x1<w#"$shape" && y1<h#"$shape" && cumul(i0,i1,x1,y1)==$1*$2?I:[-1,-1]" 17694 l. discard y,-1 if w s c a x res={^} fi rm endl 17695 else # Test all shape points 17696 +f[cumul] *${fn}"x1 = x + $1 - 1; y1 = y + $2 - 1; 17697 i(#"$shape",x,y) && x1<w#"$shape" && y1<h#"$shape" && cumul(x,y,x1,y1)==$1*$2" 17698 if iM 100%,100%,1,2,"i(#-1)?[x,y]:[-1,-1]" discard. -1 if w s. y,2 a[-2,-1] x res={^} fi rm. fi 17699 rm. 17700 fi 17701 u $res 17702 17703#@cli max_patch : _patch_size>=1 17704#@cli : Return locations of maximal values in local patch-based neighborhood of given size for selected images. 17705#@cli : Default value: 'patch_size=16'. 17706#@cli : $ image.jpg norm +max_patch 16 17707max_patch : check "isint(${1=16}) && $1>=1" 17708 e[^-1] "Return locations of maximal values in local patch neighborhood of size $1, in image$?." 17709 repeat $! +dilate[$>] $1 ==[$>,-1] done 17710 17711#@cli min_patch : _patch_size>=1 17712#@cli : Return locations of minimal values in local patch-based neighborhood of given size for selected images. 17713#@cli : Default value: 'patch_size=16'. 17714#@cli : $ image.jpg norm +min_patch 16 17715min_patch : check "isint(${1=16}) && $1>=1" 17716 e[^-1] "Return locations of minimal values in local patch neighborhood of size $1, in image$?." 17717 repeat $! +erode[$>] $1 ==[$>,-1] done 17718 17719#@cli minimal_path : x0[%]>=0,y0[%]>=0,z0[%]>=0,x1[%]>=0,y1[%]>=0,z1[%]>=0,_is_high_connectivity={ 0 | 1 } 17720#@cli : Compute minimal path between two points on selected potential maps. 17721#@cli : Default value: 'is_high_connectivity=0'. 17722#@cli : $ image.jpg +gradient_norm fill[-1] 1/(1+i) minimal_path[-1] 0,0,0,100%,100%,0 pointcloud[-1] 0 *[-1] 280 \ 17723# to_rgb[-1] ri[-1] [-2],0 or 17724minimal_path : check "$1>=0 && $2>=0 && $3>=0" skip ${7=0} 17725 e[^-1] "Compute minimal path between points ($1,$2,$3) and ($4,$5,$6) for potential map$?, with "\ 17726 ${arg\ 1+$7,low,high}" connectivity." 17727 repeat $! l[$>] nm={0,n} 17728 - {im} + {iM/100} 17729 100%,100% = 1,${4-6} distance. 1,[0],{if($7,4,3)} k. channels. 1 17730 i[0] 0 17731 eval " 17732 is_percent(str) = (unref(_is_pct); _is_pct=['#str']; _is_pct[size(_is_pct) - 1]==_'%'); 17733 x = round(is_percent($1)?$1*(w - 1):$1); 17734 y = round(is_percent($2)?$2*(h - 1):$2); 17735 z = round(is_percent($3)?$3*(d - 1):$3); 17736 da_push(#0,[x,y,z]); 17737 do ( 17738 p = i(x,y,z); 17739 p&1?--x:p&2?++x; 17740 p&4?--y:p&8?++y; 17741 p&16?--z:p&32?++z; 17742 da_push(#0,[x,y,z]), 17743 _(while) p); 17744 resize(#0,1,da_size(#0),1,3,0)" 17745 rm. nm $nm endl done 17746 17747#@cli mse 17748#@cli : Compute MSE (Mean-Squared Error) matrix between selected images. 17749#@cli : $ image.jpg +noise 30 +noise[0] 35 +noise[0] 38 cut. 0,255 mse 17750mse : 17751 e[^-1] "Compute the "$!x$!" matrix of MSE values, for image$?." 17752 +mse k. 17753 17754+mse : 17755 e[^-1] "Compute the "$!x$!" matrix of MSE values, for image$?." 17756 N=$! $N,$N 17757 repeat $N,q 17758 repeat $q,p 17759 if "const p = "$p"; const q = "$q"; [w#p,h#p,d#p,s#p]!=[w#q,h#q,d#q,s#q]" 17760 error[0--4] "Image ["$p"] = '"{$p,n}"' ("{$p,[w,h,d,s]}") and ["$q"] = '"{$q,n}"' ("{$q,[w,h,d,s]}") "\ 17761 "have different sizes." 17762 fi 17763 +-[$p,$q] sqr. mse={ia} rm. 17764 =. $mse,$p,$q =. $mse,$q,$p 17765 done 17766 done 17767 17768#@cli patches : patch_width>0,patch_height>0,patch_depth>0,x0,y0,z0,_x1,_y1,_z1,...,_xN,_yN,_zN 17769#@cli : Extract N+1 patches from selected images, centered at specified locations. 17770#@cli : $ image.jpg +patches 64,64,1,153,124,0,184,240,0,217,126,0,275,38,0 17771patches : check "isint($1) && $1>0 && isint($2) && $2>0 && isint($3) && $3>0" 17772 e[^-1] "Extract $1x$2x$3 patches from image$?, at locations (${4--1})." 17773 (${4--1}) r. 3,{w/3},1,1,-1 permute. yzcx N={w} 17774 H={int(sqrt(w))} W={round(w/$H,1,1)} r. {$W*$H},1,1,3,0 r. $W,$H,1,3,-1 17775 r. {w*$1},{h*$2},{d*$3} 17776 $1,$2,$3,1,x-{int($1/2)} +f. y-{int($2/2)} +f. z-{int($3/2)} a[-3--1] c ri. ..,0,2 +[-2,-1] 17777 repeat $!-1 warp[$>] .,0,0,0 done rm. 17778 repeat $! l[$<] s y,$H s x,$W k[0-{$N-1}] endl done 17779 17780#@cli matchpatch : [patch_image],patch_width>=1,_patch_height>=1,_patch_depth>=1,_nb_iterations>=0,\ 17781# _nb_randoms>=0,_patch_penalization,_output_score={ 0 | 1 },_[guide] : (+) 17782#@cli : Estimate correspondence map between selected images and specified patch image, using 17783#@cli : a patch-matching algorithm. 17784#@cli : Each pixel of the returned correspondence map gives the location (p,q) of the closest patch in 17785#@cli : the specified patch image. If 'output_score=1', the third channel also gives the corresponding 17786#@cli : matching score for each patch as well. 17787#@cli : If 'patch_penalization' is >=0, SSD is penalized with patch occurrences. 17788#@cli : If 'patch_penalization' is <0, SSD is inf-penalized when distance between patches are less \ 17789# than '-patch_penalization'. 17790#@cli : Default values: 'patch_height=patch_width', 'patch_depth=1', 'nb_iterations=5', 'nb_randoms=5', \ 17791# 'patch_penalization=0', 'output_score=0' and 'guide=(undefined)'. 17792#@cli : $ image.jpg sample colorful +matchpatch[0] [1],3 +warp[-2] [-1],0 17793 17794#@cli plot2value 17795#@cli : Retrieve values from selected 2D graph plots. 17796#@cli : $ 400,300,1,1,'if(y>300*abs(cos(x/10+2*u)),1,0)' +plot2value +display_graph[-1] 400,300 17797plot2value : 17798 e[^-1] "Retrieve values from 2D graph plot$?." 17799 repeat $! l[$>] 17800 s c >= 50% 17801 repeat $! l[$>] (1,{w}) ri[1] [0],3 * histogram {w},1,{w} endl done 17802 a c 17803 endl done 17804 17805#@cli pointcloud : _type = { -X=-X-opacity | 0=binary | 1=cumulative | 2=label | 3=retrieve coordinates },\ 17806# _width,_height>0,_depth>0 17807#@cli : Render a set of point coordinates, as a point cloud in a 1D/2D or 3D binary image 17808#@cli : (or do the reverse, i.e. retrieve coordinates of non-zero points from a rendered point cloud). 17809#@cli : Input point coordinates can be a NxMx1x1, Nx1x1xM or 1xNx1xM image, where 'N' is the number of points, 17810#@cli : and M the point coordinates. 17811#@cli : If 'M'>3, the 3-to-M components sets the (M-3)-dimensional color at each point. 17812#@cli : Parameters 'width','height' and 'depth' are related to the size of the final image : 17813#@cli : - If set to 0, the size is automatically set along the specified axis. 17814#@cli : - If set to N>0, the size along the specified axis is N. 17815#@cli : - If set to N<0, the size along the specified axis is at most N. 17816#@cli : Points with coordinates that are negative or higher than specified ('width','height','depth') 17817#@cli : are not plotted. 17818#@cli : Default values: 'type=0' and 'max_width=max_height=max_depth=0'. 17819#@cli : $ 3000,2 rand 0,400 +pointcloud 0 dilate[-1] 3 17820#@cli : $ 3000,2 rand 0,400 {w} {w},3 rand[-1] 0,255 append y +pointcloud 0 dilate[-1] 3 17821pointcloud : check "${1=0}<=3 && ${2=0}>=0 && ${3=0}>=0 && ${4=0}>=0" 17822 e[^-1] "Convert image$? to point clouds, in "${arg\ 2+($1>=0)*$1-($1<0),{-$1}-opacity,binary,cumulative,labeling}\ 17823 " mode, with dimensions $2x$3x$4." 17824 repeat $! l[$>] nm={0,n} 17825 if $1!=3 # Render point cloud image from set of point coordinates 17826 17827 # Force input data to be of size Nx1x1xM. 17828 if "d>1 || (w>1 && h>1 && s>1)" 17829 error "Command '$0': Invalid input image "{w}x{h}x{d}x{s}". Should be NxMx1x1, Nx1x1xM or 1xNx1xM." 17830 fi 17831 if "w>1 && h>1 && s==1" r 100%,1,1,{h},-1 # NxMx1x1 -> Nx1x1xM 17832 elif "w==1 && h>1 && s>1" r {h},1,1,{s},-1 # 1xNx1xM -> Nx1x1xM 17833 fi 17834 17835 # Retrieve coordinates and color info. 17836 if s<3 channels 0,2 fi 17837 if s<4 100%,1,1,1,1 a[-2,-1] c fi 17838 sh. 0 round. siz_x={!$2?iM+1:$2} 17839 sh.. 1 round. siz_y={!$3?iM+1:$3} 17840 sh... 2 round. siz_z={!$4?iM+1:$4} 17841 rm[-3--1] 17842 17843 # Draw point cloud. 17844 $siz_x,$siz_y,$siz_z,{$1!=2?s-3:1} 17845 if $1<0 # -X-opacity 17846 f.. ">V = I; P = V[0,3]; C = V[3,size(V) - 3]; I(#-1,P) = (1+$1)*I(#-1,P) - $1*C; V" 17847 elif $1==0 # Binary 17848 f.. ">V = I; P = V[0,3]; C = V[3,size(V) - 3]; I(#-1,P) = C; V" 17849 elif $1==1 # Cumulative 17850 f.. ">V = I; P = V[0,3]; C = V[3,size(V) - 3]; I(#-1,P) += C; V" 17851 else # Label 17852 f.. ">begin(l = 0); V = I; P = V[0,3]; C = V[3,size(V) - 3]; I(#-1,P) = ++l; V" 17853 fi 17854 17855 else # Retrieve set of point coordinates from rendered point cloud image 17856 16,1,1,{s+3} 17857 f.. "> 17858 begin(N = 0; zero = vectors(0)); 17859 I!=zero?I[#-1,N++] = [ x,y,z,I ]; 17860 N>=w(#-1)?resize(#-1,1.5*w(#-1),1,1,s#-1,0); 17861 end(resize(#-1,N,1,1,s#-1,0)); 17862 I" 17863 fi 17864 k. nm $nm endl done 17865 17866#@cli psnr : _max_value 17867#@cli : Compute PSNR (Peak Signal-to-Noise Ratio) matrix between selected images. 17868#@cli : Default value: 'max_value=255'. 17869#@cli : $ image.jpg +noise 30 +noise[0] 35 +noise[0] 38 cut[-1] 0,255 psnr 255 replace_inf 0 17870+psnr : skip "${1=}" 17871 if isnum("$1") 17872 e[0--3] "Compute the "$!x$!" matrix of PSNR values, from image$? with maximum value $1." 17873 if $! +mse f. ">x==y?inf:y>x?i(y,x):10*log10(($1)^2/i)" else 0 fi 17874 else 17875 e[0--3] "Compute the "$!x$!" matrix of PSNR values, from image$?." 17876 noarg 17877 if $! $!,1,1,1,iM#x +mse[^-1] f. ">x==y?inf:y>x?i(y,x):10*log10(max(i[#-2,x],i[#-2,y])^2/i)" rm.. else 0 fi 17878 fi 17879 nm. [PSNR] 17880 17881psnr : skip "${1=}" 17882 if isnum("$1") 17883 e[0--3] "Compute the "$!x$!" matrix of PSNR values, from image$? with maximum value $1." 17884 +psnr $1 17885 else 17886 e[0--3] "Compute the "$!x$!" matrix of PSNR values, from image$?." 17887 noarg +psnr 17888 fi 17889 k. 17890 17891#@cli segment_watershed : _threshold>=0 17892#@cli : Apply watershed segmentation on selected images. 17893#@cli : Default values: 'threshold=2'. 17894#@cli : $ image.jpg segment_watershed 2 17895segment_watershed : check "${1=2}>=0" 17896 e[^-1] "Apply watershed segmentation on image$?, with edge threshold $1." 17897 repeat $! l[$>] 17898 min={im} 17899 + {1+$min} +gradient_norm 17900 +f. "i<$1 && i<j(1) && i<j(-1) && i<j(0,1) && i<j(0,-1) && (d<=1?1:i<j(0,0,1) && i<j(0,0,-1))" 17901 *[-3,-1] *. -1 watershed.. . rm. 17902 - {1+$min} 17903 endl done 17904 17905#@cli shape2bump : _resolution>=0,0<=_weight_avg_max_avg<=1,_dilation,_smoothness>=0 17906#@cli : Estimate bumpmap from binary shape in selected images. 17907#@cli : Default value: 'resolution=256', 'weight_avg_max=0.75', 'dilation=0' and 'smoothness=100'. 17908shape2bump : check "isint(${1=256}) && $1>=0 && ${2=0.75}>=0 && $2<=1 && isnum(${3=0}) && ${4=100}>=0" 17909 e[^-1] "Estimate bumpmap from binary shape in image$?, using "\ 17910 ${"if $1 u \"resolution $1\" else u \"full resolution\" fi"}", avg/max weight $2, dilation $3 17911 and smoothness $4." 17912 repeat $! 17913 +l[$>] 17914 norm > 0 17915 siz={[w,h]} 17916 17917 # Generate skeleton. 17918 distance 0 + $3 17919 +f. "const boundary = 1; 17920 (i>j(-1)&&i>j(1)) || (i>j(0,-1)&&i>j(0,1)) || (i>j(-1,-1)&&i>j(1,1)) || (i>j(-1,1)&&i>j(1,-1))" 17921 17922 # Downsize for faster computation. 17923 is_resized=0 17924 if $1" && "max(w,h)>$1 rr2d $1,$1,0,2 gt. 0 thinning. 1 *.. {$1/max($siz)} is_resized=1 fi 17925 17926 # Generate z-map. 17927 +f. 0 .x2 17928 f[1] "*if (i, 17929 r = i(#0,x,y); 17930 ir = floor(r); 17931 r2 = r^2; 17932 for (q = -ir, q<=ir, ++q, 17933 Y = y + q; 17934 for (p = -ir, p<=ir, ++p, 17935 X = x + p; 17936 dist = norm(p,q); 17937 if (dist<r, 17938 elev = sqrt(r2 - dist^2); 17939 i(#2,X,Y) = max(i(#2,X,Y),elev); 17940 if ($2<1, i(#3,X,Y) += elev; ++i(#4,X,Y)); 17941 ); 17942 ) 17943 ); 17944 ); i" 17945 17946 if $2<1 M={-3,iM} max. 1 /[-2,-1] n. 0,$M j. ..,0,0,0,0,$2 17947 else rm[-2,-1] 17948 fi 17949 k. 17950 if $is_resized *. {max([$siz]/[w,h])} r $siz,1,1,5 c 0,100% fi 17951 endl 17952 if $4 M={iM} (1^0^1) r. [0],[0] !=[0] 0 *. [0] smooth.. .,$4,0.1,0 rm. b. 0.5 n. 0,$M fi # Smooth bumpmap 17953 k. 17954 done 17955 17956#@cli skeleton : _boundary_conditions={ 0=dirichlet | 1=neumann } 17957#@cli : Compute skeleton of binary shapes using distance transform and constrained thinning. 17958#@cli : Default value: 'boundary_conditions=1'. 17959#@cli : $ shape_cupid 320 +skeleton 0 17960skeleton : check "!isnum(${1=1}) || ($1>=0 && $1<=1)" 17961 if isnum($1) bc=$1 else bc=1 noarg fi 17962 e[^-1] "Compute skeleton of binary image$? with "${"arg 1+"$bc",dirichlet,neumann"}" boundary conditions." 17963 repeat $! l[$>] s c repeat $! l[$>] 17964 # [0] = 2D binary shape 17965 1,16,1,2 # [1] = List of boundary pixels 17966 1,16,1,2 # [2] = List of boundary pixels (next iteration) 17967 17968 # [3] = Pixels on median axis. 17969 +distance[0] 0 17970 f. "const boundary = 1; 17971 (i>j(-1)&&i>j(1)) || (i>j(0,-1)&&i>j(0,1)) || (i>j(-1,-1)&&i>j(1,1)) || (i>j(-1,1)&&i>j(1,-1))" 17972 17973 # Extract boundary pixels. 17974 f[0] ">const boundary = "$bc"; 17975 i && (!j(-1) || !j(1) || !j(0,-1) || !j(0,1))?da_push(#1,[x,y]); i;" 17976 17977 # Run thinning algorithm. 17978 eval " 17979 const boundary = "$bc"; 17980 17981 # Lookup tables for detecting the simple points. 17982 is_removable = [ 0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,1,1,1,0,1,1,1,0, 17983 1,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 17984 0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,1,1,1,0,1,1, 17985 1,0,1,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,1,1,1,0,1,1,1,0,1,1,1,0,0,1,1,1,1,0,0,0,0, 17986 0,0,0,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,1,1,0,0,1,1,0, 17987 1,1,1,0,1,1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,0 ]; 17988 dotm = [ 128,64,32,16,0,8,4,2,1 ]; 17989 is_removed = 1; 17990 17991 # Start thinning iterations. 17992 while (is_removed, 17993 is_removed = 0; 17994 N = da_size(#1); 17995 repeat (N,n, 17996 xc = i(#1,0,n,0,0); 17997 yc = i(#1,0,n,0,1); 17998 icc = i(#0,xc,yc); 17999 (icc && !i(#3,xc,yc))?( 18000 xp = xc - 1; yp = yc - 1; 18001 xn = xc + 1; yn = yc + 1; 18002 ref(crop(#0,xp,yp,3,3),V); 18003 val = dot(dotm,V>0); 18004 is_removable[val]?( 18005 i(#0,xc,yc) = 0; 18006 is_removed = 1; 18007 V[3]==1?(da_push(#2,[xp,yc]); i(#0,xp,yc) = 2); 18008 V[5]==1?(da_push(#2,[xn,yc]); i(#0,xn,yc) = 2); 18009 V[1]==1?(da_push(#2,[xc,yp]); i(#0,xc,yp) = 2); 18010 V[7]==1?(da_push(#2,[xc,yn]); i(#0,xc,yn) = 2); 18011 ):(da_push(#2,[xc,yc]); i(#0,xc,yc) = 2); 18012 ) 18013 ); 18014 resize(#1,1,h(#2),1,2,0); 18015 copy(i(#1),i(#2),2*h(#2)); 18016 i[#2,h(#2)-1] = 0; 18017 );" 18018 k[0] > 0 thinning 18019 endl done a c endl done 18020 18021skeleton_v236 : check ${1=0}>=0 18022 e[^-1] "Compute skeleton of binary image$?." 18023 distance 0 b $1 sharpen 1e10 >= 100% 18024 repeat $! +erode[$>] 2 -[$>,-1] done 18025 18026#@cli slic : size>0,_regularity>=0,_nb_iterations>0 18027#@cli : Segment selected 2D images with superpixels, using the SLIC algorithm (Simple Linear Iterative Clustering). 18028#@cli : Scalar images of increasingly labeled pixels are returned. 18029#@cli : Reference paper: Achanta, R., Shaji, A., Smith, K., Lucchi, A., Fua, P., & Susstrunk, S. (2010). \ 18030# SLIC Superpixels (No. EPFL-REPORT-149300). 18031#@cli : Default values: 'size=16', 'regularity=10' and 'nb_iterations=10'. 18032#@cli : $ image.jpg +srgb2lab slic[-1] 16 +blend shapeaverage f[-2] "j(1,0)==i && j(0,1)==i" *[-1] [-2] 18033slic : check "${1=16}>0 && ${2=10}>=0 && ${3=10}>0" 18034 e[^-1] "Segment image$? using SLIC superpixels, with size $1, regularity $2 and $3 iterations." 18035 S,m,nb_iter=${1-3} 18036 repeat $! l[$>] slices 50% 18037 18038 # Initialize superpixel centers Ck. 18039 {[max(1,round(w/$S)),max(1,round(h/$S))]},1,2,"round(([x,y]+=0.5)*="$S")" 18040 18041 # Perturb the Ck towards low gradient positions. 18042 if $S>=3 18043 +b[0] 0.7 g. xy,1 a[-2,-1] c norm. # Gradient norm with forward differences 18044 f.. " 18045 const n = round("$S"/3); 18046 const n1 = int(n/2); 18047 pos = argmin(crop(#-1,i0 - n1,i1 - n1,n,n,1)); 18048 dxy = [pos%n,int(pos/n)] - n1; 18049 [ cut(i0 + dxy[0],0,w#0-1), cut(i1 + dxy[1],0,h#0-1) ]" 18050 rm. 18051 fi 18052 r. {wh},1,1,2,-1 18053 100%,1,1,{0,s},"I(#0,I#1)" a[-2,-1] c # Add superpixels colors 18054 [0],[0],1,2 eval.. "I(#-1,i0,i1) = [ x + 1,1 ]; I" s. c distance. 1 *. -1 watershed.. . rm. channels. 0,1 18055 18056 # Start iteration loop. 18057 repeat $nb_iter 18058 18059 # Assign best superpixel to each pixel. 18060 sh[2] 1 f. inf rm. 18061 eval[1] " 18062 const m = "$m"; 18063 const S = "$S"; 18064 k = x; 18065 xk = i0; 18066 yk = i1; 18067 Ik = (I)[2,s#0]; 18068 x0 = max(xk - S,0); 18069 x1 = min(xk + S,w#0 - 1); 18070 y0 = max(yk - S,0); 18071 y1 = min(yk + S,h#0 - 1); 18072 for (y = y0, y<=y1, ++y, 18073 for (x = x0, x<=x1, ++x, 18074 delta_c = norm(I(#0,x,y) - Ik); 18075 delta_s = norm(x - xk, y - yk); 18076 delta = delta_c + m/S*delta_s; 18077 if (delta<i(#-1,x,y,0,1), 18078 I(#-1,x,y) = [ k,delta ]; 18079 ); 18080 ) 18081 ); 18082 I" 18083 18084 # Update superpixels. 18085 f[1] 0 channels[1] 0,{-2,s} 18086 eval[2] "I[#1,i0]+=[ x,y,I#0,1 ];I" 18087 s[1] c,-{1,s-1} max[2] 1 /[1,2] 18088 18089 done 18090 18091 # Remove small and isolated regions (surrounded by pixels all having the same label). 18092 k[2] channels 0 label. 0,0 18093 +area 0,0 <. {$S^2/8} 18094 {0,iM+1},1,1,1,x 18095 eval[0] "> 18096 const boundary = 1; 18097 if (i[#-1,i]>=0, 18098 N = [ j(-1,0),j(0,-1),j(1,0),j(0,1) ]; 18099 repeat (size(N),k, 18100 if (N[k]!=i, 18101 i[#-1,i] = i[#-1,i]==i || i[#-1,i]==N[k]?N[k]:-1 18102 ); 18103 ); 18104 ); 18105 i" 18106 f. "i<0?0:1" +map[0] . rm.. or[-2,-1] 18107 18108 +[0] 1 100%,100% j[0] .,0,0,0,0,1,.. rm. 18109 distance. 0 *. -1 watershed.. . rm. 18110 label. 0,0 18111 endl done 18112 18113#@cli ssd_patch : [patch],_use_fourier={ 0 | 1 },_boundary_conditions 18114#@cli : Compute fields of SSD between selected images and specified patch. 18115#@cli : Argument 'boundary_conditions' is valid only when 'use_fourier=0'. 18116#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 18117#@cli : Default value: 'use_fourier=0' and 'boundary_conditions=0'. 18118#@cli : $ image.jpg +crop 20%,20%,35%,35% +ssd_patch[0] [1],0,0 18119ssd_patch : check ${is_image_arg\ $1} skip ${2=0},${3=0} 18120 e[^-1] "Compute field of SSD between image$? and patch $1 using "${arg\ 1+!$2,fourier,spatial}" mode." 18121 repeat $! pass$1 0 l[$>,-1] 18122 r 100%,100%,100%,${-max_s} s c 18123 repeat $!/2 l[$>,{-1-$<}] 18124 +sqr[1] val={is} rm. # Sum J(p,q)^2 18125 +sqr[0] +f[1] 1 18126 if $2 18127 convolve_fft.. . rm. # Sum I(x+p,y+q)^2 18128 mirror[1] xyz convolve_fft[0] [1] rm[1] # Sum I(x+p,y+q).J(p,q) 18129 else 18130 correlate.. .,$3 rm. # Sum I(x+p,y+q)^2 18131 correlate[0] [1],$3 rm[1] # Sum I(x+p,y+q).J(p,q) 18132 fi 18133 *[0] -2 +[0,1] + $val 18134 endl done + 18135 endl done 18136 18137#@cli thinning : _boundary_conditions={ 0=dirichlet | 1=neumann } 18138#@cli : Compute skeleton of binary shapes using morphological thinning 18139#@cli : (beware, this is a quite slow iterative process) 18140#@cli : Default value: 'boundary_conditions=1'. 18141#@cli : $ shape_cupid 320 +thinning 18142thinning : check "!isnum(${1=1}) || ($1>=0 && $1<=1)" 18143 if isnum($1) bc=$1 else bc=1 noarg fi 18144 e[^-1] "Apply morphological thinning to binary image$? with "\ 18145 ${"arg 1+"$bc",dirichlet,neumann"}" boundary conditions." 18146 repeat $! l[$>] s c repeat $! l[$>] 18147 # [0] = 2D binary shape (current iteration) 18148 1,16,1,2 # [1] = List of boundary pixels (current iteration) 18149 1,16,1,2 # [2] = List of pixels to remove (current iteration) 18150 1,16,1,2 # [3] = List of boundary pixels (for next iteration) 18151 18152 # Extract boundary pixels. 18153 f[0] ">const boundary = "$bc"; 18154 i && (!j(-1) || !j(1) || !j(0,-1) || !j(0,1))?da_push(#1,[x,y]); i;" 18155 18156 # Run thinning algorithm. 18157 eval " 18158 const boundary = "$bc"; 18159 18160 # Lookup tables for detecting the 8 3x3 hit&miss. 18161 hm_and = [ 231,189,231,189,122,91,94,218 ]; 18162 hm_eq = [ 7,148,224,41,18,80,72,10 ]; 18163 18164 # Start thinning iterations. 18165 dotm = [ 128,64,32,16,0,8,4,2,1 ]; 18166 is_removed = vector8(0); 18167 ind = 1; 18168 nind = 3; 18169 it = 0; 18170 do ( 18171 N = da_size(#ind); 18172 it8 = it%8; 18173 is_removed[it8] = 0; 18174 18175 # Find removable contour points. 18176 repeat (N,n, 18177 xc = i(#ind,0,n,0,0); 18178 yc = i(#ind,0,n,0,1); 18179 icc = i(#0,xc,yc); 18180 icc?( 18181 xp = xc - 1; yp = yc - 1; 18182 xn = xc + 1; yn = yc + 1; 18183 ref(crop(#0,xp,yp,3,3),V); 18184 val = dot(dotm,V>0); 18185 (val & hm_and[it8])==hm_eq[it8]?( 18186 da_push(#2,[xc,yc]); 18187 is_removed[it8] = 1; 18188 V[3]==1?(da_push(#nind,[xp,yc]); i(#0,xp,yc) = 2); 18189 V[5]==1?(da_push(#nind,[xn,yc]); i(#0,xn,yc) = 2); 18190 V[1]==1?(da_push(#nind,[xc,yp]); i(#0,xc,yp) = 2); 18191 V[7]==1?(da_push(#nind,[xc,yn]); i(#0,xc,yn) = 2); 18192 ):(da_push(#nind,[xc,yc]); i(#0,xc,yc) = 2); 18193 ); 18194 ); 18195 18196 # Re-assign value '1' to contour points. 18197 N = da_size(#nind); 18198 repeat (N,n, i(#0,i[#nind,n],i[#nind,n + h(#nind)]) = 1); 18199 _tmp = ind; ind = nind; nind = _tmp; 18200 i[#nind,h(#nind)-1] = 0; 18201 18202 # Remove matching contour points. 18203 N = da_size(#2); 18204 repeat (N,n, i(#0,I[#2,n]) = 0); 18205 i[#2,h(#2)-1] = 0; 18206 ++it; 18207 _(while), max(is_removed) 18208 );" 18209 k[0] 18210 endl done a c endl done 18211 18212#@cli tones : N>0 18213#@cli : Get N tones masks from selected images. 18214#@cli : $ image.jpg +tones 3 18215tones : check $1>0 18216 e[^-1] "Get $1 tones masks from image$?." 18217 norm n 0,{$1-1} round 1 repeat $! l[$<] 18218 repeat $1-1 +==[0] {1+$>} done ==[0] 0 18219 endl done 18220 18221#@cli topographic_map : _nb_levels>0,_smoothness 18222#@cli : Render selected images as topographic maps. 18223#@cli : Default values: 'nb_levels=16' and 'smoothness=2'. 18224#@cli : $ image.jpg topographic_map 10 18225topographic_map : check "isint(${1=16}) && $1>0" skip ${2=2} 18226 e[^-1] "Render topographic maps from image$?, with $1 levels and smoothness $2." 18227 repeat $! l[$>] 18228 +b $2 isophotes. $1 compose_channels. + ==. 0 blend shapeaverage0 18229 endl done 18230 18231#@cli tsp : _precision>=0 18232#@cli : Try to solve the 'travelling salesman' problem, using a combination of greedy search and 2-opt algorithms. 18233#@cli : Selected images must have dimensions Nx1x1xC to represent N cities each with C-dimensional coordinates. 18234#@cli : This command re-order the selected data along the x-axis so that the point sequence becomes a shortest path. 18235#@cli : Default values: 'precision=256'. 18236#@cli : $ 256,1,1,2 rand 0,512 tsp , 512,512,1,3 repeat w#0 circle[-1] {0,I[$>]},2,1,255,255,255 \ 18237# line[-1] {0,boundary=2;[I[$>],I[$>+1]]},1,255,128,0 done keep[-1] 18238tsp : check "${1=256}>=0" 18239 e[^-1] "Try to solve the 'travelling salesman' problem for pointcloud$?, with precision $1." 18240 repeat $! l[$>] n={n} 18241 if h>1" || "d>1 error[0--4] "Selected image '"{n}"' has invalid dimensions ("{[w,h,d,s]}")." fi 18242 18243 # Find initial estimate, using greedy nearest neighbor algorithm. 18244 eval " 18245 is_used = vectorw(0); 18246 next = vectorw(-1); 18247 n_initial = n_current = round(u(0,w-1)); 18248 do ( 18249 is_used[n_current] = 1; 18250 P_current = I[n_current]; 18251 n_next = -1; dmin = inf; 18252 repeat (w,n, 18253 if (!is_used[n], 18254 d = norm(I[n] - P_current); 18255 if (d<dmin, dmin = d; n_next = n); 18256 ); 18257 ); 18258 if (n_next<0, next[n_current] = n_initial; break()); 18259 next[n_current] = n_next; 18260 n_current = n_next; 18261 _(while), 1 18262 ); 18263 resize(#-1,w,1,1,s+1,0); 18264 copy(i(0,0,0,s),next,w)" 18265 100%,1,1,{s-1},">begin(ind = 0); val = I[#0,ind]; ind = val[s]; val" rm.. 18266 18267 # Improving initial estimate iteratively by 2-opt algorithm. 18268 eval " 18269 is_improved = 1; 18270 while (is_improved, 18271 is_improved = 0; 18272 nb_try = $1*w; 18273 repeat (nb_try,try, 18274 r = round(max(8,0.5*w*(try/nb_try)^0.25)); 18275 i = round(u(0,w-1)); 18276 ni = (i+1)%w; 18277 pi = (i-1)%w; 18278 do (j = (i + round(u(-r,r)))%w; _(while), j==i || j==ni || j==pi); 18279 nj = (j+1)%w; 18280 P_i = I[i]; 18281 P_ni = I[ni]; 18282 P_j = I[j]; 18283 P_nj = I[nj]; 18284 dist_ini = norm(P_ni - P_i); 18285 dist_jnj = norm(P_nj - P_j); 18286 dist_ij = norm(P_j - P_i); 18287 dist_ninj = norm(P_nj - P_ni); 18288 if (dist_ij + dist_ninj<dist_ini + dist_jnj, 18289 mi = (min(i,j) + 1)%w; 18290 mj = max(i,j); 18291 oi = min(mi,mj); 18292 oj = max(mi,mj); 18293 delta = oj - oi + 1; 18294 repeat (s,c, copy(i(oi,0,0,c),i(oj,0,0,c),delta,1,-1)); # Reverse path between nodes. 18295 is_improved = 1; 18296 ); 18297 ); 18298 )" 18299 nm $n 18300 endl done 18301 18302#@cli variance_patch : _patch_size>=1 18303#@cli : Compute variance of each images patch centered at (x,y), in selected images. 18304#@cli : Default value: 'patch_size=16' 18305#@cli : $ image.jpg +variance_patch 18306variance_patch : check "isint(${1=16}) && $1>=1" 18307 e[^-1] "Compute variance of image patches in image$?, with patch size $1." 18308 $1,$1,1,1,1 normalize_sum. 18309 repeat $!-1 l[$>,-1] 18310 +sqr[0] convolve[0,2] [1] 18311 sqr[0] rv[0,2] -[0,2] max[0] 0 18312 endl done rm. 18313 18314#--------------------------------- 18315# 18316#@cli :: Image Drawing 18317# 18318#--------------------------------- 18319 18320#@cli arrow : x0[%],y0[%],x1[%],y1[%],_thickness[%]>=0,_head_length[%]>=0,_head_thickness[%]>=0,_opacity,\ 18321# _pattern,_color1,... 18322#@cli : Draw specified arrow on selected images. 18323#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 18324#@cli : even if a color is specified. If a pattern is specified, the arrow is 18325#@cli : drawn outlined instead of filled. 18326#@cli : Default values: 'thickness=1%', 'head_length=10%', 'head_thickness=3%', 'opacity=1', 'pattern=(undefined)' \ 18327# and 'color1=0'. 18328#@cli : $ 400,400,1,3 repeat 100 arrow 50%,50%,{u(100)}%,{u(100)}%,3,20,10,0.3,${-rgb} done 18329arrow : check "${5=1%}>=0 && ${6=10%}>=0 && ${7=3%}" skip ${8=1} 18330 e[^-1] "Draw arrow in image$?, from ($1,$2) to ($3,$4), with thickness $5, head length $6, 18331 head_thickness $7 and opacity $8." 18332 repeat $! l[$>] 18333 polygon. 7,{" 18334 x0 = "${"is_percent $1"}"?(w-1)*$1:$1; 18335 y0 = "${"is_percent $2"}"?(h-1)*$2:$2; 18336 x1 = "${"is_percent $3"}"?(w-1)*$3:$3; 18337 y1 = "${"is_percent $4"}"?(h-1)*$4:$4; 18338 p0 = [x0,y0]; 18339 dp = [x1,y1]-=p0; 18340 l = norm2(dp); # arrow length 18341 t = "${"is_percent $5"}"?l*$5:$5; # thickness 18342 hl = "${"is_percent $6"}"?l*$6:$6; # head length 18343 ht = "${"is_percent $7"}"?l*$7:$7; # head thickness 18344 lmhl = l - hl; 18345 X = mul([0,-t,lmhl,-t,lmhl,-ht,l,0,lmhl,ht,lmhl,t,0,t],rot(-atan2(dp[1],dp[0])),2); 18346 X+=[p0,p0,p0,p0,p0,p0,p0]"},${8--1} 18347 endl done 18348 18349#@cli axes : x0,x1,y0,y1,_font_height>=0,_opacity,_pattern,_color1,... 18350#@cli : Draw xy-axes on selected images. 18351#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 18352#@cli : even if a color is specified. 18353#@cli : To draw only one x-axis at row Y, set both 'y0' and 'y1' to Y. 18354#@cli : To draw only one y-axis at column X, set both 'x0' and 'x1' to X. 18355#@cli : Default values: 'font_height=14', 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 18356#@cli : $ 400,400,1,3,255 axes -1,1,1,-1 18357axes : check "isint(${5=14}) && $5>=0 && ${6=1}>=0" skip ${7=0},${8=0} 18358 if ${"is_pattern \"$7\""} 18359 e[0--3] "Draw xy-axes on image$?, with x-range ($1,$2), y-range ($3,$4), font height $5, opacity $6, 18360 pattern $7 and color (${8--1})." 18361 pattern=$7 color=${8--1} 18362 else 18363 e[0--3] "Draw xy-axes on image$?, with x-range ($1,$2), y-range ($3,$4), font height $5, opacity $6 18364 and color (${7--1})." 18365 pattern=0xFFFFFFFF color=${7--1} 18366 fi 18367 if !$5" || "!$6 return fi 18368 mx={min($1,$2)} Mx={max($1,$2)} 18369 my={min($3,$4)} My={max($3,$4)} 18370 18371 # Start drawing axes on selected images. 18372 repeat $! l[$>] 18373 w1={0,w-1} h1={0,h-1} 18374 18375 # Determine number of axes tick marks. 18376 if $1!=$2 u=${"_axes[] $1,$2,{0.3*w/$5}"} offx={arg(1,$u)} deltax={arg(2,$u)} fi 18377 if $3!=$4 u=${"_axes[] $3,$4,{0.3*h/$5}"} offy={arg(1,$u)} deltay={arg(2,$u)} fi 18378 18379 # Draw x-axis. 18380 is_0x=0 18381 if $3==$4 y0=$3 else y0={v=-($my)*$h1/($My-$my);if($4>=$3,v,$h1-v)} fi 18382 sty={if($y0>$h1-$5,-1,1)} 18383 18384 if $1!=$2" && "$y0>=0" && "$y0<=$h1 18385 line 0,$y0,$w1,$y0,$6,$pattern,$color 18386 4,4,1,1,x<=y +mirror. y rows. 1,3 a[-2,-1] y .,.,1,[0] fc. $color 18387 if $2>=$1 j[0] .,{$w1-3},{$y0-3},0,0,$6,.. 18388 else mirror.. x j[0] .,0,{$y0-3},0,0,$6,.. 18389 fi 18390 rm[-2,-1] 18391 18392 i=0 do 18393 val={_$offx+$i*$deltax} i+=1 18394 if $val>=$mx" && "$val<=$Mx 18395 x={v=($val-$mx)*$w1/($Mx-$mx);if($2>=$1,v,$w1-v)} 18396 line $x,{$y0-1},$x,{$y0+1},$6,$pattern,$color 18397 if $val 18398 0 t. $val,0,0,$5,1,1 100%,100%,1,[0] fc. $color 18399 j[0] .,{max(0,min($w1-w,$x-w/2))},{if($sty>0,$y0+3,$y0-h-3)},0,0,$6,.. rm[-2,-1] 18400 else is_0x=1 18401 fi 18402 fi 18403 while $val<$Mx 18404 fi 18405 18406 # Draw y-axis. 18407 is_0y=0 18408 if $1==$2 x0=$1 else x0={v=-($mx)*$w1/($Mx-$mx);if($2>=$1,v,$w1-v)} fi 18409 stx={if($x0>$w1-$5,-1,1)} 18410 18411 if $3!=$4" && "$x0>=0" && "$x0<=$w1 18412 line $x0,0,$x0,$h1,$6,$pattern,$color 18413 4,4,1,1,x>=y +mirror. x z. 1,3 a[-2,-1] x .,.,1,[0] fc. $color 18414 if $4>=$3 j[0] .,{$x0-3},{$h1-3},0,0,$6,.. 18415 else mirror.. y j[0] .,{$x0-3},0,0,0,$6,.. 18416 fi 18417 rm[-2,-1] 18418 18419 i=0 do 18420 val={_$offy+$i*$deltay} i+=1 18421 if $val>=$my" && "$val<=$My 18422 y={v=($val-$my)*$h1/($My-$my);if($4>=$3,v,$h1-v)} 18423 line {$x0-1},$y,{$x0+1},$y,$6,$pattern,$color 18424 if $val 18425 0 t. $val,0,0,$5,1,1 100%,100%,1,[0] fc. $color 18426 j[0] .,{if($stx>0,$x0+6,$x0-w-6)},{max(0,min($h1-h,$y-h/2))},0,0,$6,.. rm[-2,-1] 18427 else is_0y=1 18428 fi 18429 fi 18430 while $val<$My 18431 fi 18432 18433 # Draw origin, if necessary. 18434 if $is_0x" || "$is_0y 18435 0 t. 0,0,0,$5,1,1 100%,100%,1,[0] fc. $color 18436 j[0] .,{if($stx>0,$x0+6,$x0-w-6)},{if($sty>0,$y0+3,$y0-h-3)},0,0,$6,.. rm[-2,-1] 18437 fi 18438 18439 endl done 18440 18441# Return optimal (offset0,scale) to display input (min,max) values. 18442# $1 = min value, $2 = max value, $3 = max number of tags(>=1). 18443_axes : 18444 n={max(1,round($3))} 18445 d={abs($2-$1)/($n-1)} 18446 s={10^round(log10($d))} 18447 m={round(min($1,$2),$s,-1)} 18448 M={round(max($1,$2),$s,1)} 18449 do N={1+round(($M-$m)/$s,1,1)} s={2*$s} while $N>$n 18450 u $m,{$s/2} 18451 18452#@cli ball : _size>0, _R,_G,_B,0<=_specular_light<=8,0<=_specular_size<=8,_shadow>=0 18453#@cli : Input a 2D RGBA colored ball sprite. 18454#@cli : Default values: 'size=64', 'R=255', 'G=R', 'B=R', 'specular_light=0.8', 'specular_size=1' and 'shading=1.5'. 18455#@cli : $ repeat 9 ball {1.5^($>+2)},${-rgb} done append x 18456+ball : check "${1=64}>0 && ${5=0.8}>=0 && $5<=8 && ${6=1}>=0 && $6<=8 && ${7=1.5}>=0" skip ${2=255},${3=$2},${4=$3} 18457 e[^-1] "Input $1x$1 ball with color (${2-4}), specular light $5, specular size $6 and shadow factor $7." 18458 l[] 18459 {2*$1},{2*$1} = 1,65%,30% distance 1 * -1 18460 +n 0,1 ^[1] $7 *[1] 1.4 +*[1] $3 +*[1] $4 *[1] $2 a[^0] c 18461 >=[0] {100-10*$6}% b[0] {3*$6}% n[0] 0,{$5*255} rv + c 0,255 18462 100%,100% circle[1] 50%,50%,34%,1,1 *[0] [1] *. 255 a c 18463 r $1,$1,1,4,2 18464 endl 18465 18466# chromeball64x64 : Output a 64x64 GreyA chrome ball sprite. 18467# ${1-3} = R,G,B 18468chromeball64x64 : 18469 base642img[] \ 18470"MiB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNjQgNjQgMSAyICMzMzY0CnicxZl5VJNnvsfT0mM7ntPp9N7paefe6ZzOmWlnemfGmTpzer0dO1W"\ 18471"RnQCBQPZ9TwhhDQkYwyKQAAlbEjZBthgRRBahFamAggp1KS7QIgKyk7DIpoCQd54XtComyPLH/f7xvn/k/Xyf3/N7n+X35EUgLOqN9z/DHcqtaW69cq"\ 18472"EmK8z7s3csP2ZZO/7ILGzpHhwaHBzoHxgA9/vt55M8fvPaxuh37NOu9AyNjBpNY+PjE+OmkYGuOzfb73XURu1589X0zx2PXu8ZMo0Dbnh41DQxMT5mH"\ 18473"O7vam/v7O5sUH35Cgebvyiaf+g3jRuHB/oGjeMPpqamHkyMDvb3g3iG+7tvnjm8a71e/Af+5PXOYdPo4MCwaWr24cO5ubnZ2ekHY6PDgwNDRtNQT9u3"\ 18474"mRirqXztt5Laa10jo0N9fcaZ+UWghflHwGBudnpywjTUNzjcd/faN3kBH1vGX98VWdd6b2B4oKt3fH7JbF5+vDC/ADQPm0xPTRr779/vuNZUdUzyT0t"\ 18475"9eON/5Webb3f8eOdqW9/Eo2XI/Gh6auYxbAMMHsIO48OD/TcvnCvNltjbvIz/I/RMXVPTlaa6xrauwbG55eU5wAObpZmJialpoJnpSZCZ63WV+rRgxz"\ 18476"fW9n0Xr/RsZVX1mdOV9a237o3OLT+amJw3Q9DS3IRxdNQ4NmYcn4YN7l8+U5ybIDq4pgsf4fPrjhcWFhScqL54vWt0Zn5++sHcotkMLc1OjptGR4yjw"\ 18477"6MPZqbBu+yoLyvURfjueQF/z1V98YRGo8vWV128PTTzeGlpeWkZtA5B5sVHczNTD4CmZ+Zmp8b6Oy7XFB9NDOV+8hz+1j7Jt9+kKVIyC0433DItmiHz"\ 18478"CvtEZvPSit/j+bnpsYGbF6tL8tIiRfRn4+C1PzGKWwuVCRm5xWevDS5CVmRemp0Y6m1rqCrOT1eKBS4/peA/XZKu1mkVKVn5ZQ0/TJmt8dDSeO8PNy6"\ 18479"fK9fnZqllIu4fnuA2u4VnO0rU8WmZheUN9x5ZxaHFwatN9bVnSgtzstKOBAkIO1b595007W25CQkpmUUwb7V981T3pXM1VWXFBUcztcpQIWfX6rj9G6"\ 18480"nqXotGmZCUDvjO2cWFhWXL/OTdK9/WlJ8yFORkalXhIt5qAL/4l/hSz8UUhVKlKyiv7xibmRibsxzDo77vL56tKDXk52TqUuQiAetTmP/USXm1pzFZo"\ 18481"VADvuHOkGlocGzJIr881tlaV1kC+KwMXZS/gI0Er+DNL7zUV+9d1CgUqvTC8gsdIyO9vabHljMwP3S7sbr0eN7R7KN5sf4CLu2XIHv7MXFX7rZmg/jT"\ 18482"CysutBuNvT2j81Yy+OBea22ZIe9YblFpPOAZuxGIXQd9ws/fbTMoFIm6/NPfXu8Z6e8bsZIAEMCtxqoSvf54WbUK5pEIm332nsJTP7RXqRSJaTkl3zS"\ 18483"13e3pG5mxnABoebKrpe5MWXllXXUc4JnEn73tZo+kpH9/u+FofGJSpr6ytvlGR49VHloytrfW19bVXy6RifgcJuXXv8E6OKIP1d9oOa1JUGtyT5yuvX"\ 18484"yza8gqDz0e6/zuUvOVCxkhfjwOk/znv1Id7d0Z+ZcvNeiTEsEELK6qb7kzMG2Vh5ZMP95ovXIqOsCXx2aQ93zFdbZz8ZKX19bX5CSqtbmG01+f/+6u0"\ 18485"eokBKNo4PZ3X6cG+/G5LDrZ1t3fzdbBjZqgLz97KkOdmlVUUl7deKN7fNHqNFgauX0+O9zfl8dh0chIfCjazs4ZxY07WlxWlKXRZBcYSmsab9wzPlxc"\ 18486"smzxeKhFHx0oFHDZTBoJxZARHA46ItG86IxCg/5Yhi47/3hpdX1L293eQdP0/Mse5ocdlUlhAQKQPTqV6MmNYSDt7J3d0dzIjAKDoSA3J6/wRGlV9df"\ 18487"nGi5dvdU1MDa9ZjbO99bnxAGey2bQyHiUUCVEO9k5unp4sw9r8/XHiwoLi/T6E8XFJWUV1bUXWm/c6TbNLS4/DWN5prvpZDrMc1gMKgmHZGskZHdHey"\ 18488"ekhxctVJVTdBzIcBy20RtOlFR8Xdf43Z2eQePk9KPHy0vzk73f158u0MaGBwhA78lErAMxK5qHQdo7OiM90ARfeVoewE+A5oEMer3hZFnVuebrt37s6"\ 18489"ukb6Ou80VRbebIgKzkmPIDPolNJeMy/XHJVEgba2cEJGHhhqP6RqcdAwydLTpVXlJWcMBiKSyrONjRdam48X1dzSl+QBy8d8VHSAB6LRiHhvP/+xVHN"\ 18490"kQCKm5PjioEPjuYXrtTmFukNJWWnSk8CA8PJU2WlhsLcrAxtilqVmJAQHxd9ONSfx6BRyVj0xx+mZKkihBgXJydnFzcPT28snswSSaMTkjOOFR4HPSg"\ 18491"qKsjNTE2Ii4mOlB+WyQ7LwfWQNNiPS6fRKViv99+JyNaqZCwvV8C7url7on2weBKFwRUGS+VH4hRKpTI2SiYVBwXCCgoODgkJDg4KFAk4DCabhkHtQH"\ 18492"DS0zPigyhebq6urkg3d5SXNwZHIJKpNPAAl8fj8/krFz5fIPAV+MISCAQ8LpvN51N99iMQX4J9QxslJPt4uiNh3tMLhIDDE0kUKpVGpzOYLBaLvSIOE"\ 18493"HxnsZhMFs8vwI/s80cE4r9CFGk6VbiAjPP2RHl4oFBeXmhvDHAgEElkMmxCg22eiQ7E5PmFSPwIaHgPJUmOJCVGifl08Dp90F5eIABvHwwWi3tqQQEm"\ 18494"K6I9EZ3FFYllMi7uILz+/40TEBkXJfXns8GIIOJxGB9v72cGRBKRBExgARtgRaMzuQJ/SUS0mIb9aGXzxzOE4TIJWE/4YErCrxW4AAEcTyAQSLBWcAq"\ 18495"VQgX54Pj6B4VHxcoFBORqFfQ5nswPDPL35cLpFfBXXOg0Gtzac4JRFofL9w2UhMuiFTEhVPyTQvAtNAbDEAj5bI6vn5/IPyAwQOQH+/B4XM5q5tnwKw"\ 18496"Ao+DU4TB4dHaOIk7II7k+LsD97uLmTWWwGnSMQ+geGhIaKxWCYgMESFBTgD8tPKBSKwA8SqVQep1QqYqOlXCLuw6f1h42DowMSR6WQaWy+UBQUKpWAB"\ 18497"8ElFHYSiyVhEnCXyCIjo6JiVMlqRbRczCUTv3pWP/3C1fagiw/INoXJEwiD4KclUglMAwupTA4GvTwyVhGfqErVpSnB7GGTSd4/e64A+/jg/v0O7j44"\ 18498"YMDhCQNDACgGAx0oRCyVRUYdiYlVqlN1uvRMTZxUxKURiPj/fqEA3PPVflsndx8Chc7h8EXB0jAgqXjFAPBH4hLUKdrMLF1aYmQwj0HCk6l/ebH+tLH"\ 18499"be8DBHUOiMUCeRSHhh+UR0dERMqBDkXHxquRUjS5dl5oYLRawqAQsjbMXsUav79t7wBlNoIM3xfUNORyjUCYmJ6mTU5ISkmBUk5qckhgVyqdRiBgMU2"\ 18500"T7cgX/+sEvv3JGE+nwdBNKY1O06ZnpWm16SoIqJS01Me5IpCyYSyHgfbywfMna6nlV/2e31xlLptEoZDpfHJWoyy3ILyjIzdKoosOCgvxYVCyYFyhPi"\ 18501"lj+hSUa6BOXvUgKk4rxROMYAWFH1FpNSnJ8ZFiwL5OC9/ZCodAoT4JYEfuJFRyBeNfDwZnEpHq7ubhj6Twhn8nkMYk+aA83Dx8Sm0OlsMK12ohPreJA"\ 18502"n5FcPMg0vJu9vbMXDuPh5unuam9r6+BJF/n5R6Tk5aei3loPRyB22vliUHgqztV23wEHuwOObo62SAyJzpfEZxflpBI/WJ+G9ZZdmIxL9EG5OhzYb4c"\ 18503"kEJnCUHmMUp2uVXj/6tX0iv6Hmp6nUYaHHkrUKmLjlOq0rOwU6u4dG6RX9ME+ukydW1FZXl6kCafs+91mWKCdu7Hqijvj8JY9dadajf3w1cgzvUutWV"\ 18504"hbdnQl/XOD9J9y5iwXTp2itzdAF1s+PKxoTPoKh7eTXwr8RZlo6+H7e9anYTX82hptE7FO6M80ibKM7yzfCA1kllvC32veIA5U+PL5/722jeMWDHY2b"\ 18505"gaHoGNr+JLN4RAU/gIeulkcMiOfwz9/xaixJNOzcfDmzc3jEHTmJ/7QVnAI8n6CfzC7Nb7vyZ9pmVvDIUi4OnK2kLwnAaysiJFbxSEInsw2A1vnLwF+"\ 18506"39ZxCALLcvp2eAkCsY3wIagJ8fvt4NDCTuy2eGifent8YMX2eN2mlq2XdXZwe/w2m4d6/r/5DW1Z6/DbDKClZXt8RfH2eHXE9nim2/b43e9tC596HbG"\ 18507"lveepKhGIbSWACgq2beAL74IF+PrW+TJ4/2BtnbeH+R19W8VbVvfPgK3yzk/Kh+6t4c1P6wfUlvCF3T8VIKVb4ROe1U+/7N88fu3549CXm64hJv+AeF"\ 18508"6CTeILTmsK0NhN4WYmYq02Y2DmvIQjEHLrH37WBk+1gCMQRCtfHdZq0s4ijkD8tXMj+P2PrODg+JXx6u3kzLpH8C+urU93e69HA9ng2q3TfbwNfIFGO"\ 18509"Fda7sUF0kZP8L8S1K05Ay80hP52g/CqdnzOTa1o6QFqqdb57dlp7bl/A5UFagkxIDQ1IDEgMSAjNTIKeJxz941i0M/Iz03VTykpTs4ozS3Qd0ktzi7J"\ 18510"L9BPzigCiscXF2SkFqXqFeSlMwAAcSYQbQ==" 18511 s. c +apply_gamma.. 0.05 b. 3 n. 0,150 n... 0,1 i[-4] 100%,100%,1,3 fc[-4] ${1-3} *[-4,-3] +[-3,-1] 18512 c.. 0,255 a[-2,-1] c 18513 18514#@cli chessboard : size1>0,_size2>0,_offset1,_offset2,_angle,_opacity,_color1,...,_color2,... 18515#@cli : Draw chessboard on selected images. 18516#@cli : Default values: 'size2=size1', 'offset1=offset2=0', 'angle=0', 'opacity=1', 'color1=0' and 'color2=255'. 18517#@cli : $ image.jpg chessboard 32,32,0,0,25,0.3,255,128,0,0,128,255 18518chessboard : check "$1>0 && ${2=$1}>0" skip ${3=0},${4=0},${5=0},${6=1},${7=0},${8=255} 18519 e[^-1] "Draw chessboard on image$?, with sizes ($1,$2), offsets ($3,$4), angle $5 deg., opacity $6 and 18520 colors (${7--1})." 18521 i[0] (${7--1}) r[0] {{0,w}/2},1,1,2,-1 permute[0] cyzx 18522 repeat $!-1 18523 w={w} h={h} theta={$5*pi/180} 18524 ($3,{$3+$w-1};$3,{$3+$w-1}^$4,$4;{$4+$h-1},{$4+$h-1}) r. $w,$h,1,2,3 18525 r. {$w*$h},2,1,1,-1 18526 i.. ({cos($theta)},{-sin($theta)};{sin($theta)},{cos($theta)}) m*[-2,-1] 18527 r. $w,$h,1,2,-1 18528 %. {$1+$2} >=. $1 s. c xor[-2,-1] map. [0] r. 100%,100%,1,.. 18529 j.. .,0,0,0,0,$6 rm. 18530 mv. 1 done rm[0] 18531 18532#@cli cie1931 18533#@cli : Draw CIE-1931 chromaticity diagram on selected images. 18534#@cli : $ 500,400,1,3 cie1931 18535cie1931 : 18536 e[^-1] "Draw CIE-1931 chromaticity diagram on image$?." 18537 18538 # Generate convex hull of visible colors, as a 3D object. 18539 (67.5;73.5;109.5;103.5;51.5;100.5;37;36) # Header 18540 (280,420,0;171,829,0;158,820,0;153,816,0;147,811,0;140,804,0;132,794,0;121,776,0;106,747,0;88,701,0;\ # Vertices. 18541 65,633,0;42,539,0;20,421,0;5,295,0;0,179,0;4,115,0;10,83,0;16,61,0;25,38,0;35,21,0;47,10,0;58,3,0;\ 18542 71,0,0;92,1,0;111,7,0;151,28,0;189,52,0;226,79,0;262,109,0;298,141,0;334,175,0;370,209,0;405,244,0;\ 18543 441,279,0;475,313,0;509,347,0;731,568,0) 18544 xM=731 yM=829 18545 2,{h-1},1,1,3,0 1,{h},1,1,'y' ++. 1 %. {h} +[-2,-1] 1 a[-3--1] x # Primitives. 18546 3,{h},1,1,160 1,{h},1,1,1 # Colors + opacities. 18547 y[-4--2] a[-5--1] y mv. 0 18548 18549 # Generate RGB triangle of displayable colors. 18550 xR=636 yR=504 xG=297 yG=234 xB=147 yB=774 18551 512,512,1,3 triangle_shade. 0,0,{w-1},0,0,{h-1},""255,0,0,""0,255,0,""0,0,255 rgb2srgb. 18552 +compose_channels. max +. 1e-8 /[-2,-1] *. 255 18553 i.. (67.5;73.5;109.5;103.5;51.5;100.5;3;1;$xR;$yR;-0.01;$xG;$yG;-0.01;$xB;$yB;-0.01;\ 18554 9;0;1;2;0;0;511;0;0;511;-128;512;512;3) 18555 y. (1) a[-3--1] y mv. 1 18556 18557 # Draw chroma diagram. 18558 repeat $!-2 18559 to_rgb. fc. 255,255,255 grid. 10%,10%,0,0,0.3,0xCCCCCCCC,1,0 18560 100%,100%,1,3 18561 +*3d[0,1] {(w-8)/$xM},{(h-32)/$yM} 18562 j3d... .,2,30,0,1,2 18563 +!=... 0 distance. 1 *. -1 watershed[-4] . rm. /... 1.5 18564 j3d... .,2,30,0,1,2 18565 p3d. 1 p3d. 2 col3d. 128 j3d... .,2,30,0,1,1 rm. 18566 {-2,w},{-2,h} j3d. ..,2,30,0,1,2 rm.. 18567 +erode. 4 -. .. ==. 0 *[-3,-1] 18568 a[-2,-1] c blend[-2,-1] alpha 18569 100%,100%,1,1,255 axes. 0,0.75,0.85,0,14,1 +erode. 3 negate. to_rgb.. 18570 j... ..,0,0,0,0,1,.,400 rm[-2,-1] 18571 mv. 2 done rm[0,1] 18572 18573#@cli circle : x[%],y[%],R[%],_opacity,_pattern,_color1,... 18574#@cli : Draw specified colored circle on selected images. 18575#@cli : A radius of '100%' stands for 'sqrt(width^2+height^2)'. 18576#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 18577#@cli : even if a color is specified. If a pattern is specified, the circle is 18578#@cli : drawn outlined instead of filled. 18579#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 18580#@cli : $ image.jpg repeat 300 circle {u(100)}%,{u(100)}%,{u(30)},0.3,${-rgb} done circle 50%,50%,100,0.7,255 18581circle : skip ${4=1},${5=0},${6=0} 18582 if ${"is_pattern \"$5\""} 18583 e[0--3] "Draw outlined circle at ($1,$2) with radius $3 on image$?, with opacity $4, pattern $5 and 18584 color (${6--1})." 18585 else 18586 e[0--3] "Draw filled circle at ($1,$2) with radius $3 on image$?, with opacity $4 and color (${5--1})." 18587 fi 18588 ellipse $1,$2,$3,$3,0,${4--1} 18589 18590#@cli close_binary : 0<=_endpoint_rate<=100,_endpoint_connectivity>=0,_spline_distmax>=0,_segment_distmax>=0,\ 18591# 0<=_spline_anglemax<=180,_spline_roundness>=0,_area_min>=0,_allow_self_intersection={ 0 | 1 } 18592#@cli : Automatically close open shapes in binary images (defining white strokes on black background). 18593#@cli : Default values: 'endpoint_rate=75', 'endpoint_connectivity=2', 'spline_distmax=80', 'segment_distmax=20', \ 18594# 'spline_anglemax=90', 'spline_roundness=1','area_min=100', 'allow_self_intersection=1'. 18595close_binary : 18596 check "${1=75}>=0 && $1<=100 && ${2=2}>=0 && ${3=80}>=0 && ${4=20}>=0 && ${5=90}>=0 && $5<=180 && ${6=1}>=0 && 18597 ${7=100}>=0 && isnum(${8=1})" 18598 e[^-1] "Close open shapes in binary image$?, with endpoint rate $1, endpoint connectivity $2, spline max distance $3, 18599 segment max distance $4, spline max angle $5, spline roundness $6, area min $7 and self intersections "\ 18600 ${"arg 1+!$8,allowed,\"not allowed\""}"." 18601 18602 # Set algorithm parameters. 18603 endpoint_threshold={100-$1} # in [0,100] 18604 endpoint_connectivity={round($2)} 18605 spline_distmax=$3 # in px 18606 segment_distmax=$4 # in px 18607 spline_anglemax=$5 # in deg 18608 spline_roundness=$6 18609 area_min=$7 # in px 18610 allow_self_intersections={!!$8} # 0 or 1 18611 18612 # Define useful functions to navigate through edgels. 18613 _edgel_lib=" 18614 begin( 18615 pn = [ 0,1,1,1,-1,0,-1,1,0,-1,-1,-1,1,0,1,-1 ]; 18616 pp = [ 0,-1,1,-1,1,0,1,1,0,1,-1,1,-1,0,-1,-1 ]; 18617 ); 18618 18619 next(img,p) = ( # Used when shape is made of '!=0' (in 8-connexity) 18620 p0 = p#[0,2] + pn[4*p#[2],2]; 18621 p1 = p#[0,2] + pn[4*p#[2] + 2,2]; 18622 case = !!i(#img,p0[0],p0[1],0,0) + 2*!!i(#img,p1[0],p1[1],0,0); 18623 !case?[ p[0],p[1],(p[2]+1)%4 ]:case==1?[ p0[0],p0[1],p[2] ]:[ p1[0],p1[1],(p[2]-1)%4 ]; 18624 ); 18625 18626 previous(img,p) = ( # Used when shape is made of '!=0' (in 8-connexity) 18627 p0 = p#[0,2] + pp[4*p#[2],2]; 18628 p1 = p#[0,2] + pp[4*p#[2] + 2,2]; 18629 case = !!i(#img,p0[0],p0[1],0,0) + 2*!!i(#img,p1[0],p1[1],0,0); 18630 !case?[ p[0],p[1],(p[2]-1)%4 ]:case==1?[ p0[0],p0[1],p[2] ]:[ p1[0],p1[1],(p[2]+1)%4 ]; 18631 ); 18632 18633 next2(img,p) = ( # Used when shape is made of '{ 0 | 4 }' (in 4-connexity) 18634 p0 = p#[0,2] + pn[4*p#[2],2]; 18635 p1 = p#[0,2] + pn[4*p#[2] + 2,2]; 18636 case = !(i(#img,p0[0],p0[1],0,0)&3) + 2*!(i(#img,p1[0],p1[1],0,0)&3); 18637 case==1?[ p0[0],p0[1],p[2] ]:case==3?[ p1[0],p1[1],(p[2]-1)%4 ]:[ p[0],p[1],(p[2]+1)%4 ]; 18638 ); 18639 18640 next3(img,p) = ( # Used when shape is made of '{ 1 | 2 }' (in 4-connexity) 18641 p0 = p#[0,2] + pn[4*p#[2],2]; 18642 p1 = p#[0,2] + pn[4*p#[2] + 2,2]; 18643 val1 = i(#img,p0[0],p0[1],0,0); 18644 val2 = i(#img,p1[0],p1[1],0,0); 18645 case = (val1==1 || val1==2) + 2*(val2==1 || val2==2); 18646 case==1?[ p0[0],p0[1],p[2] ]:case==3?[ p1[0],p1[1],(p[2]-1)%4 ]:[ p[0],p[1],(p[2]+1)%4 ]; 18647 ); 18648 18649 vec(p) = ( 18650 ang = i(p[0],p[1],0,p[2])*pi/180; 18651 [ cos(ang), sin(ang) ]; 18652 );" 18653 18654 repeat $! l[$>] nm={n} 18655 18656 # Ensure input is a 2D binary image. 18657 slices 50% channels 0 > 0 18658 nm. strokes 18659 18660 # Extract primary edgel normals. 18661 100%,100%,1,4," 18662 ref(crop(#"$strokes",x - 1,y - 1,0,0,3,3,1,1,1),N); 18663 N[4]?[ N[5]?-2:0, N[7]?-2:90, N[3]?-2:180, N[1]?-2:270 ]:[-2,-2,-2,-2]; 18664 " nm. e_normals 18665 18666 # Smooth edgel normals. 18667 f[e_normals] $_edgel_lib" 18668 const boundary = 1; 18669 i<-1?-2:( 18670 ppos = npos = pos = [ x,y,c ]; 18671 u = vec(pos); 18672 for (t = 1, t<=5, ++t, 18673 ppos = previous(#"$strokes",ppos); 18674 npos = next(#"$strokes",npos); 18675 if (ppos==npos, break()); 18676 w = exp(-t^2/30); 18677 u+=w*vec(ppos); 18678 u+=w*vec(npos); 18679 ); 18680 ang = (atan2(u[1],u[0])*180/pi)%360; 18681 )" 18682 18683 # Estimate edgel curvatures. 18684 +f[e_normals] $_edgel_lib" 18685 const boundary = 1; 18686 i<-1?-2:( 18687 pos = [ x,y,c ]; 18688 ppos = previous(#"$strokes",pos); 18689 npos = next(#"$strokes",pos); 18690 pu = vec(ppos); 18691 nu = vec(npos); 18692 du = (nu - pu)/2; 18693 cr = cross([vec(pos),0],[du,0]); 18694 norm(du)*sign(cr[2]); 18695 )" 18696 nm. e_curvatures 18697 18698 # Smooth edgel curvatures. 18699 +f[e_curvatures] $_edgel_lib" 18700 const boundary = 1; 18701 i<-1?-2:( 18702 ppos = npos = pos = [ x,y,c ]; 18703 val = i; sumw = 1; 18704 for (t = 1, t<=5, ++t, 18705 ppos = previous(#"$strokes",ppos); 18706 npos = next(#"$strokes",npos); 18707 if (ppos==npos, break()); 18708 w = exp(-t^2/30); 18709 val+=w*i(ppos[0],ppos[1],0,ppos[2]); 18710 val+=w*i(npos[0],npos[1],0,npos[2]); 18711 sumw+=2*w; 18712 ); 18713 val/sumw; 18714 )" 18715 nm. e_smooth_curvatures 18716 18717 # Estimate stroke radius. 18718 +distance[strokes] 0 18719 f. " 18720 i<1-0.01||i>1+0.01?0:( 18721 p = x; q = y; d = 1; 18722 for (is_better = 1, is_better && d<32, 18723 next_p = p; 18724 next_q = q; 18725 is_better = 0; 18726 pp = p - 1; 18727 np = p + 1; 18728 pq = q - 1; 18729 nq = q + 1; 18730 (nd = i(pp,pq))>d?(d = nd; next_p = pp; next_q = pq; is_better = 1); 18731 (nd = i(p, pq))>d?(d = nd; next_p = p; next_q = pq; is_better = 1); 18732 (nd = i(np,pq))>d?(d = nd; next_p = np; next_q = pq; is_better = 1); 18733 (nd = i(pp,q))>d?(d = nd; next_p = pp; next_q = q; is_better = 1); 18734 (nd = i(np,q))>d?(d = nd; next_p = np; next_q = q; is_better = 1); 18735 (nd = i(pp,nq))>d?(d = nd; next_p = pp; next_q = nq; is_better = 1); 18736 (nd = i(p, nq))>d?(d = nd; next_p = p; next_q = nq; is_better = 1); 18737 (nd = i(np,nq))>d?(d = nd; next_p = np; next_q = nq; is_better = 1); 18738 p = next_p; 18739 q = next_q; 18740 ); 18741 d)" 18742 nm. stroke_radii 18743 18744 # Detect end points. 18745 compose_channels[e_smooth_curvatures] max nm[e_smooth_curvatures] smooth_curvatures 18746 +compose_channels[e_curvatures] max nm. curvatures 18747 18748 f. "i(#"$smooth_curvatures")>=("$endpoint_threshold"%)/(max(1,i(#"$stroke_radii"))) || 18749 i>=max(0.25,"$endpoint_threshold"%)" 18750 label_fg. 0,1 nm. keypoints 18751 if iM>0 18752 {iM},1,1,3,-1 nm. keycoords 18753 f[keypoints] "> # Keep only a single point on connected regions of high curvatures. 18754 ret = 0; 18755 if (i, 18756 j = i - 1; 18757 old_max = I[#"$keycoords",j]; 18758 kappa = i(#"$smooth_curvatures"); 18759 if (kappa>old_max[2], 18760 I[#"$keycoords",j] = [ x,y,kappa ]; 18761 i(#"$keypoints",old_max[0],old_max[1]) = 0; 18762 ret = 1; 18763 ); 18764 ); ret" 18765 channels[keycoords] 0,3 # Channels 2,3 = number of connexions and normal angle for each keypoint. 18766 fi 18767 rm[smooth_curvatures,stroke_radii,keypoints] 18768 18769 # Estimate point normals. 18770 if !narg($keycoords) 18771 rm[e_normals,e_curvatures] [strokes] nm. new_strokes 18772 else 18773 f[keycoords] " 18774 P = (I)[0,2]; 18775 angles = I(#"$e_normals",P); 18776 U = [ 0,0 ]; 18777 repeat (size(angles),k, 18778 if (angles[k]>=0, 18779 w = max(1e-8,i(#"$e_curvatures",P[0],P[1],0,k))^2; 18780 ang = angles[k]*pi/180; 18781 U += w*[ cos(ang),sin(ang) ]; 18782 ); 18783 ); 18784 [ P,0,(atan2(U[1],U[0])*180/pi)%360 ]" 18785 rm[e_normals,e_curvatures] 18786 18787 # Detect pairs of keypoints preserving the spline constraints. 18788 256,1,1,3 nm. keypairs 18789 f[keycoords] "> 18790 begin(ind = 0); 18791 for (nx = x + 1, nx<w, ++nx, 18792 const cosmin = cos("$spline_anglemax"*pi/180); 18793 Ic = I[x]; 18794 In = I[nx]; 18795 S = Ic[0,2]; 18796 T = In[0,2]; 18797 angS = Ic[3]*pi/180; 18798 angT = In[3]*pi/180; 18799 NS = [ cos(angS),sin(angS) ]; 18800 NT = [ cos(angT),sin(angT) ]; 18801 ST = T - S; 18802 dist = norm(ST); 18803 cosN = dot(NS,-NT); 18804 angN = acos(cosN)*180/pi; 18805 quality = max(0,1 - dist/"$spline_distmax") * max(0,dot(NS,ST) - dot(NT,ST))/dist * max(0,cosN - cosmin); 18806 if (quality>0, 18807 if (ind>=w(#"$keypairs"), resize(#"$keypairs",2*ind,1,1,3,0)); 18808 I[#"$keypairs",ind++] = [ quality,x,nx ]; 18809 ); 18810 ); 18811 end(resize(#"$keypairs",ind,1,1,3,0)); 18812 I" 18813 if {keypairs,w} sort[keypairs] -,x 18814 else rm[keypairs] 18815 fi 18816 18817 # Find and connect splines. 18818 [strokes] nm. new_strokes 18819 ind_strokes={$allow_self_intersections?$strokes:$new_strokes} 18820 18821 if narg($keypairs) 18822 f[keypairs] ">"$_edgel_lib" 18823 for_spline(code) = for (t = 0, t<=1, t+=dt, 18824 t3 = t*(t2 = t*t); 18825 P = round(mul([t3,t2,t,1],C,2)); 18826 code#; 18827 dP = abs(mul([3*t2,2*t,1,0],C,2)) + 1e-8; 18828 dt = min(dtmin,0.75/max(dP)); 18829 ); 18830 18831 Ic = I; 18832 indS = Ic[1]; 18833 indT = Ic[2]; 18834 if (i(#"$keycoords",indS,0,0,2)<"$endpoint_connectivity" && 18835 i(#"$keycoords",indT,0,0,2)<"$endpoint_connectivity", 18836 S = I(#"$keycoords",indS)[0,2]; 18837 T = I(#"$keycoords",indT)[0,2]; 18838 angS = i(#"$keycoords",indS,0,0,3)*pi/180; 18839 angT = i(#"$keycoords",indT,0,0,3)*pi/180; 18840 ST = T - S; 18841 dist = "$spline_roundness"*norm(ST); 18842 NS = [ cos(angS),sin(angS) ]; 18843 NT = [ cos(angT),sin(angT) ]; 18844 tmax = max(abs(ST)); 18845 is_cond = 1; 18846 C = mul([ 2,-2,1,1,-3,3,-2,-1,0,0,1,0,1,0,0,0 ],[ S,T,dist*NS,-dist*NT ],2); 18847 dt = dtmin = 1/max(abs(T - S)); 18848 current_val = 1; 18849 nb_switches = 0; 18850 for_spline( 18851 if (i(#"$ind_strokes",P,0,0)!=current_val, ++nb_switches; current_val=!current_val); 18852 if (nb_switches>2, is_cond = 0; break()) 18853 ); 18854 if (is_cond, 18855 18856 # Check that the new spline did not create small closed regions. 18857 const area_max_threshold = "$area_min"; 18858 const area_min_threshold = 5; 18859 const max_edgels = 2*(area_max_threshold + 1); 18860 18861 if (area_max_threshold<=0, 18862 for_spline(i(#"$new_strokes",P)=1); 18863 , #else 18864 for_spline(i(#"$new_strokes",P)|=2); 18865 for_spline( 18866 if (i(#"$new_strokes",P[0] + 1,P[1])==0, 18867 edgels = area = 0; Q0 = Q = [ P[0] + 1,P[1],2 ]; 18868 do ( 18869 i(#"$new_strokes",Q[0],Q[1]) = 4; 18870 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 18871 Q = next2(#"$new_strokes",Q), 18872 Q!=Q0 && ++edgels<=max_edgels); 18873 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 18874 is_cond = 0; break() 18875 ); 18876 ); 18877 if (i(#"$new_strokes",P[0],P[1] + 1)==0, 18878 edgels = area = 0; Q0 = Q = [ P[0],P[1] + 1,3 ]; 18879 do ( 18880 i(#"$new_strokes",Q[0],Q[1]) = 4; 18881 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 18882 Q = next2(#"$new_strokes",Q), 18883 Q!=Q0 && ++edgels<=max_edgels); 18884 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 18885 is_cond = 0; break() 18886 ); 18887 ); 18888 if (i(#"$new_strokes",P[0] - 1,P[1])==0, 18889 edgels = area = 0; Q0 = Q = [ P[0] - 1,P[1],0 ]; 18890 do ( 18891 i(#"$new_strokes",Q[0],Q[1]) = 4; 18892 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 18893 Q = next2(#"$new_strokes",Q), 18894 Q!=Q0 && ++edgels<=max_edgels); 18895 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 18896 is_cond = 0; break() 18897 ); 18898 ); 18899 if (i(#"$new_strokes",P[0],P[1] - 1)==0, 18900 edgels = area = 0; Q0 = Q = [ P[0],P[1] - 1,1 ]; 18901 do ( 18902 i(#"$new_strokes",Q[0],Q[1]) = 4; 18903 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 18904 Q = next2(#"$new_strokes",Q), 18905 Q!=Q0 && ++edgels<=max_edgels); 18906 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 18907 is_cond = 0; break() 18908 ); 18909 ); 18910 0); 18911 18912 # Set or unset spline, and clean temp points used for local area estimations. 18913 for_spline( 18914 if (i(#"$new_strokes",P[0] + 1,P[1])==4, 18915 edgels = 0; Q0 = Q = [ P[0] + 1,P[1],2 ]; 18916 do (i(#"$new_strokes",Q[0],Q[1]) = 0; Q = next2(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 18917 ); 18918 if (i(#"$new_strokes",P[0],P[1] + 1)==4, 18919 edgels = 0; Q0 = Q = [ P[0],P[1] + 1,3 ]; 18920 do (i(#"$new_strokes",Q[0],Q[1]) = 0; Q = next2(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 18921 ); 18922 if (i(#"$new_strokes",P[0] - 1,P[1])==4, 18923 edgels = 0; Q0 = Q = [ P[0] - 1,P[1],0 ]; 18924 do (i(#"$new_strokes",Q[0],Q[1]) = 0; Q = next2(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 18925 ); 18926 if (i(#"$new_strokes",P[0],P[1] - 1)==4, 18927 edgels = 0; Q0 = Q = [ P[0],P[1] - 1,1 ]; 18928 do (i(#"$new_strokes",Q[0],Q[1]) = 0; Q = next2(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 18929 ); 18930 0); 18931 for_spline(i(#"$new_strokes",P) = is_cond?1:(i(#"$new_strokes",P)&1)); 18932 if (is_cond, 18933 ++i(#"$keycoords",indS,0,0,2); 18934 ++i(#"$keycoords",indT,0,0,2); 18935 ); 18936 ); 18937 ); 18938 ); I" 18939 rm[keypairs] 18940 fi 18941 18942 # Find and connect segments. 18943 ==[new_strokes] 0 # Negate values to consider boundary pixels (0) as strokes. 18944 18945 f[keycoords] ">"$_edgel_lib" 18946 for_segment(code) = for (t = 0, t<=tmax, ++t, 18947 P = round(S + t*ST); 18948 code#; 18949 ); 18950 18951 if (i(#"$keycoords",x,0,0,2)<"$endpoint_connectivity", 18952 S = I(#"$keycoords",x)[0,2]; 18953 angS = i(#"$keycoords",x,0,0,3)*pi/180; 18954 NS = [ cos(angS),sin(angS) ]; 18955 ST = round(NS*"$segment_distmax"); 18956 tmax = max(abs(ST)); 18957 ST/=tmax; 18958 is_cond = 0; 18959 current_val = 0; 18960 nb_switches = 0; 18961 for_segment( 18962 if (i(#"$new_strokes",P,0,0)!=current_val, ++nb_switches; current_val=1 - current_val); 18963 if (nb_switches==2,is_cond = 1; break();); 18964 ); 18965 tmax = t; 18966 if (is_cond, 18967 18968 # Check that the new segment did not create small closed regions. 18969 const area_max_threshold = "$area_min"; 18970 const area_min_threshold = 5; 18971 const max_edgels = 2*(area_max_threshold + 1); 18972 if (area_max_threshold<=0, 18973 for_segment(i(#"$new_strokes",P)=0); 18974 , #else 18975 for_segment(i(#"$new_strokes",P)|=4); 18976 for_segment( 18977 if (i(#"$new_strokes",P[0] + 1,P[1])==1, 18978 edgels = area = 0; Q0 = Q = [ P[0] + 1,P[1],2 ]; 18979 do ( 18980 i(#"$new_strokes",Q[0],Q[1]) = 2; 18981 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 18982 Q = next3(#"$new_strokes",Q), 18983 Q!=Q0 && ++edgels<=max_edgels); 18984 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 18985 is_cond = 0; break() 18986 ); 18987 ); 18988 if (i(#"$new_strokes",P[0],P[1] + 1)==1, 18989 edgels = area = 0; Q0 = Q = [ P[0],P[1] + 1,3 ]; 18990 do ( 18991 i(#"$new_strokes",Q[0],Q[1]) = 2; 18992 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 18993 Q = next3(#"$new_strokes",Q), 18994 Q!=Q0 && ++edgels<=max_edgels); 18995 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 18996 is_cond = 0; break() 18997 ); 18998 ); 18999 if (i(#"$new_strokes",P[0] - 1,P[1])==1, 19000 edgels = area = 0; Q0 = Q = [ P[0] - 1,P[1],0 ]; 19001 do ( 19002 i(#"$new_strokes",Q[0],Q[1]) = 2; 19003 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 19004 Q = next3(#"$new_strokes",Q), 19005 Q!=Q0 && ++edgels<=max_edgels); 19006 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 19007 is_cond = 0; break() 19008 ); 19009 ); 19010 if (i(#"$new_strokes",P[0],P[1] - 1)==1, 19011 edgels = area = 0; Q0 = Q = [ P[0],P[1] - 1,1 ]; 19012 do ( 19013 i(#"$new_strokes",Q[0],Q[1]) = 2; 19014 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 19015 Q = next3(#"$new_strokes",Q), 19016 Q!=Q0 && ++edgels<=max_edgels); 19017 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 19018 is_cond = 0; break() 19019 ); 19020 ); 19021 0); 19022 19023 # Set or unset segment, and clean temp points used for local area estimations. 19024 for_segment( 19025 if (i(#"$new_strokes",P[0] + 1,P[1])==2, 19026 edgels = 0; Q0 = Q = [ P[0] + 1,P[1],2 ]; 19027 do (i(#"$new_strokes",Q[0],Q[1]) = 1; Q = next3(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 19028 ); 19029 if (i(#"$new_strokes",P[0],P[1] + 1)==2, 19030 edgels = 0; Q0 = Q = [ P[0],P[1] + 1,3 ]; 19031 do (i(#"$new_strokes",Q[0],Q[1]) = 1; Q = next3(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 19032 ); 19033 if (i(#"$new_strokes",P[0] - 1,P[1])==2, 19034 edgels = 0; Q0 = Q = [ P[0] - 1,P[1],0 ]; 19035 do (i(#"$new_strokes",Q[0],Q[1]) = 1; Q = next3(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 19036 ); 19037 if (i(#"$new_strokes",P[0],P[1] - 1)==2, 19038 edgels = 0; Q0 = Q = [ P[0],P[1] - 1,1 ]; 19039 do (i(#"$new_strokes",Q[0],Q[1]) = 1; Q = next3(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 19040 ); 19041 0); 19042 for_segment(i(#"$new_strokes",P) = is_cond?0:i(#"$new_strokes",P)&3); 19043 if (is_cond, ++i(#"$keycoords",x,0,0,2)); 19044 ); 19045 ); 19046 ); I" 19047 ==[new_strokes] 0 19048 if !0$_keep_keycoords rm[keycoords] fi # Small hack used by the plug-in preview. 19049 fi 19050 rm[strokes] 19051 nm[new_strokes] $nm 19052 endl done 19053 19054#@cli ellipse : x[%],y[%],R[%],r[%],_angle,_opacity,_pattern,_color1,... : (+) 19055#@cli : Draw specified colored ellipse on selected images. 19056#@cli : A radius of '100%' stands for 'sqrt(width^2+height^2)'. 19057#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 19058#@cli : even if a color is specified. If a pattern is specified, the ellipse is 19059#@cli : drawn outlined instead of filled. 19060#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 19061#@cli : $ image.jpg repeat 300 ellipse {u(100)}%,{u(100)}%,{u(30)},{u(30)},{u(180)},0.3,${-rgb} done \ 19062# ellipse 50%,50%,100,100,0,0.7,255 19063 19064#@cli flood : x[%],_y[%],_z[%],_tolerance>=0,_is_high_connectivity={ 0 | 1 },_opacity,_color1,... : (+) 19065#@cli : Flood-fill selected images using specified value and tolerance. 19066#@cli : Default values: 'y=z=0', 'tolerance=0', 'is_high_connectivity=0', 'opacity=1' and 'color1=0'. 19067#@cli : $ image.jpg repeat 1000 flood {u(100)}%,{u(100)}%,0,20,0,1,${-rgb} done 19068 19069#@cli gaussian : _sigma1[%],_sigma2[%],_angle 19070#@cli : Draw a centered gaussian on selected images, with specified standard deviations and orientation. 19071#@cli : Default values: 'sigma1=3', 'sigma2=sigma1' and 'angle=0'. 19072#@cli : $ 400,400 gaussian 100,30,45 19073#@cli : $$ https://gmic.eu/oldtutorial/_gaussian 19074gaussian : skip ${1=3},${2=$1},${3=0} 19075 e[^-1] "Draw centered gaussian on image$? with standard deviations ($1,$2) and angle $3 deg." 19076 u={cos($3*pi/180)} 19077 v={sin($3*pi/180)} 19078 dmax={max(w,h)} 19079 if isnum($1) l1=$1 else l1={${1}10000*$dmax/100} fi 19080 if isnum($2) l2=$2 else l2={${2}10000*$dmax/100} fi 19081 l1={1/(2*max(1/3,$l1)^2)} 19082 l2={1/(2*max(1/3,$l2)^2)} 19083 A={$l1*$u*$u+$l2*$v*$v} 19084 B={($l1-$l2)*$u*$v} 19085 C={$l1*$v*$v+$l2*$u*$u} 19086 repeat $! l[$>] nm={0,n} 19087 w={w} h={h} ds={d},{s} rm 19088 $w,$h,1,1,'X=x-{($w-1)/2};Y=y-{($h-1)/2};$A*X*X+2*$B*X*Y+$C*Y*Y' 19089 * -1 exp r $w,$h,$ds 19090 nm $nm endl done 19091 19092#@cli graph : [function_image],_plot_type,_vertex_type,_ymin,_ymax,_opacity,_pattern,_color1,... : \ 19093# 'formula',_resolution>=0,_plot_type,_vertex_type,_xmin,xmax,_ymin,_ymax,_opacity,_pattern,_color1,... : (+) 19094#@cli : Draw specified function graph on selected images. 19095#@cli : 'plot_type' can be { 0=none | 1=lines | 2=splines | 3=bar }. 19096#@cli : 'vertex_type' can be { 0=none | 1=points | 2,3=crosses | 4,5=circles | 6,7=squares }. 19097#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 19098#@cli : even if a color is specified. 19099#@cli : Default values: 'plot_type=1', 'vertex_type=1', 'ymin=ymax=0 (auto)', 'opacity=1', 'pattern=(undefined)' 19100#@cli : and 'color1=0'. 19101#@cli : $ image.jpg +rows 50% blur[-1] 3 split[-1] c div[0] 1.5 graph[0] [1],2,0,0,0,1,255,0,0 \ 19102# graph[0] [2],2,0,0,0,1,0,255,0 graph[0] [3],2,0,0,0,1,0,0,255 keep[0] 19103 19104#@cli grid : size_x[%]>=0,size_y[%]>=0,_offset_x[%],_offset_y[%],_opacity,_pattern,_color1,... 19105#@cli : Draw xy-grid on selected images. 19106#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 19107#@cli : even if a color is specified. 19108#@cli : Default values: 'offset_x=offset_y=0', 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 19109#@cli : $ image.jpg grid 10%,10%,0,0,0.5,255 19110#@cli : $ 400,400,1,3,255 grid 10%,10%,0,0,0.3,0xCCCCCCCC,128,32,16 19111grid : check "$1>=0 && $2>=0" skip ${3=0},${4=0},${5=1},${6=0},${7=$6} 19112 if ${"is_pattern \"$6\""} 19113 e[0--3] "Draw xy-grid on image$?, with sizes ($1,$2), offsets ($3,$4), opacity $5, pattern $6 and color (${7--1})." 19114 pattern=$6 color=${7--1} 19115 else 19116 e[0--3] "Draw xy-grid on image$?, with sizes ($1,$2), offsets ($3,$4), opacity $5, and color (${6--1})." 19117 pattern=0xFFFFFFFF color=${6--1} 19118 fi 19119 eval " 19120 is_percent(str) = (unref(_is_pct); _is_pct=['#str']; _is_pct[size(_is_pct) - 1]==_'%'); 19121 repeat (l,k, 19122 19123 # Horizontal lines. 19124 size = is_percent($1)?max(1,w#k*$1):$1; 19125 size>=1?( 19126 off = (is_percent($3)?size*$3:$3)%size; 19127 for (x = off, x<w#k, x+=size, polygon(#k,-2,x,0,x,h - 1,$5,"$pattern","$color")); 19128 ); 19129 19130 # Vertical lines. 19131 size = is_percent($2)?max(1,h#k*$2):$2; 19132 size>=1?( 19133 off = (is_percent($4)?size*$4:$4)%size; 19134 for (y = off, y<h#k, y+=size, polygon(#k,-2,0,y,w - 1,y,$5,"$pattern","$color")); 19135 ) 19136 )" 19137 19138#@cli j : eq. to 'image'. : (+) 19139 19140#@cli image : [sprite],_x[%|~],_y[%|~],_z[%|~],_c[%|~],_opacity,_[opacity_mask],_max_opacity_mask : (+) 19141#@cli : Draw specified sprite image on selected images. 19142#@cli : (eq. to 'j').\n 19143#@cli : If one of the x,y,z or c argument ends with a '~', its value is expected to be 19144#@cli : a centering ratio (in [0,1]) rather than a position. 19145#@cli : Usual centering ratio are { 0=left-justified | 0.5=centered | 1=right-justified }. 19146#@cli : Default values: 'x=y=z=c=0', 'opacity=1', 'opacity_mask=(undefined)' and 'max_opacity_mask=1'. 19147#@cli : $ image.jpg +crop 40%,40%,60%,60% resize[-1] 200%,200%,1,3,5 frame[-1] 2,2,0 image[0] [-1],30%,30% keep[0] 19148 19149#@cli line : x0[%],y0[%],x1[%],y1[%],_opacity,_pattern,_color1,... : (+) 19150#@cli : Draw specified colored line on selected images. 19151#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 19152#@cli : even if a color is specified. 19153#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 19154#@cli : $ image.jpg repeat 500 line 50%,50%,{u(w)},{u(h)},0.5,${-rgb} done line 0,0,100%,100%,1,0xCCCCCCCC,255 \ 19155# line 100%,0,0,100%,1,0xCCCCCCCC,255 19156 19157#@cli linethick : x0[%],y0[%],x1[%],y1[%],_thickness,_opacity,_color1 19158#@cli : Draw specified colored thick line on selected images. 19159#@cli : Default values: 'thickness=2', 'opacity=1' and 'color1=0'. 19160#@cli : $ 400,400,1,3 repeat 100 linethick {u([w,h,w,h,5])},0.5,${-rgb} done 19161linethick : check "${5=2}>=0 && isnum(${6=1}) && isnum(${7=0})" 19162 e[^-1] "Draw thick line ($1,$2) - ($3,$4) on image$?, with thickness $5, opacity $6 and color (${7--1})." 19163 if !$5 line ${1-4},${6--1} 19164 else repeat $! l[$>] 19165 x0={${"is_percent $1"}?(w-1)*$1:$1} 19166 y0={${"is_percent $2"}?(h-1)*$2:$2} 19167 x1={${"is_percent $3"}?(w-1)*$3:$3} 19168 y1={${"is_percent $4"}?(h-1)*$4:$4} 19169 coords={" 19170 const th = "$5"; 19171 P0 = [ "$x0","$y0" ]; 19172 P1 = [ "$x1","$y1" ]; 19173 dP = P1 - P0; 19174 n = [ -dP[1],dP[0] ]/max(1e-8,norm(dP))*th/2; 19175 round([ P0 - n, P0 + n, P1 + n, P1 - n ]); 19176 "} 19177 polygon 4,$coords,${6--1} 19178 endl done fi 19179 19180#@cli mandelbrot : z0r,z0i,z1r,z1i,_iteration_max>=0,_is_julia={ 0 | 1 },_c0r,_c0i,_opacity : (+) 19181#@cli : Draw mandelbrot/julia fractal on selected images. 19182#@cli : Default values: 'iteration_max=100', 'is_julia=0', 'c0r=c0i=0' and 'opacity=1'. 19183#@cli : $ 400,400 mandelbrot -2.5,-2,2,2,1024 map 0 +blur 2 elevation3d[-1] -0.2 19184 19185#@cli marble : _image_weight,_pattern_weight,_angle,_amplitude,_sharpness>=0,_anisotropy>=0,_alpha,_sigma,\ 19186# _cut_low>=0,_cut_high>=0 19187#@cli : Render marble like pattern on selected images. 19188#@cli : Default values: 'image_weight=0.2', 'pattern_weight=0.1', 'angle=45', 'amplitude=0', 'sharpness=0.4' \ 19189# and 'anisotropy=0.8', 19190#@cli : 'alpha=0.6', 'sigma=1.1' and 'cut_low=cut_high=0'. 19191#@cli : $ image.jpg +marble , 19192marble : skip ${1=0.2},${2=0.1},${3=45},${4=0},${5=0.4},${6=0.8},${7=0.6},${8=1.1},${9=0%},${10=100%} 19193 e[^-1] "Render marble like pattern on image$?, with image weight $1, pattern weight $2, angle $3 deg., 19194 amplitude $4, sharpness $5, anisotropy $6, alpha $7, sigma $8, and cut ($9,$10)." 19195 sx={$2*sin($3*pi/180)} sy={$2*cos($3*pi/180)} f sin(x*$sx+y*$sy+i*$1) 19196 if $4 smooth $4,$5,$6,$7,$8 fi 19197 c $9,$10 n 0,255 19198 19199#@cli maze : _width>0,_height>0,_cell_size>0 19200#@cli : Input maze with specified size. 19201#@cli : $ maze 30,20 negate normalize 0,255 19202+maze : check "isint(${1=15}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=24}) && $3>0" 19203 e[^-1] "Input $1x$2 maze." 19204 ({round(u($1-1))},{round(u($2-1))}) # Starting cell. 19205 $1,$2,1,1,15 +f. 0 a[-2,-1] c # Starting maze data. 19206 _generate_maze $1,$2 19207 _render_maze. $3 nm. [maze] 19208 19209_generate_maze : 19210 19211 # Start opening walls. 19212 do 19213 x={-2,@-2} y={-2,@-1} # Coords of the current cell. 19214 =. 1,$x,$y,0,1 # Mark current cell as visited. 19215 19216 # Check for neighboring cells that are candidate for opening wall, and select one random. 19217 is_candidate=0 19218 up=-1 if i($x,$y)&8" && "$y>0" && "!i($x,$y-1,0,1) up=$x,{$y-1},8 is_candidate=1 fi # Up. 19219 down=-1 if i($x,$y)&4" && "$y<$2-1" && "!i($x,$y+1,0,1) down=$x,{$y+1},4 is_candidate=1 fi # Down. 19220 left=-1 if i($x,$y)&2" && "$x>0" && "!i($x-1,$y,0,1) left={$x-1},$y,2 is_candidate=1 fi # Left. 19221 right=-1 if i($x,$y)&1" && "$x<$1-1" && "!i($x+1,$y,0,1) right={$x+1},$y,1 is_candidate=1 fi # Right. 19222 if $is_candidate 19223 ($up,$down,$left,$right) y. discard. -1 r. 3,{h/3},1,1,-1 shift. 0,{round(u(4))},0,0,2 rows. 0,0 mv. -2 19224 fi 19225 19226 # Remove wall between the current and chosen neighboring cells. 19227 if $is_candidate 19228 if {-2,@-1}==8 =. {i($x,$y)&7},$x,$y =. {i($x,$y-1)&11},$x,{$y-1} # Remove up wall. 19229 elif {-2,@-1}==4 =. {i($x,$y)&11},$x,$y =. {i($x,$y+1)&7},$x,{$y+1} # Remove down wall. 19230 elif {-2,@-1}==2 =. {i($x,$y)&13},$x,$y =. {i($x-1,$y)&14},{$x-1},$y # Remove left wall. 19231 else =. {i($x,$y)&14},$x,$y =. {i($x+1,$y)&13},{$x+1},$y # Remove right wall. 19232 fi 19233 z.. 0,1 a[-3,-2] y # Add neighboring cell to stack of cells to explore. 19234 else # No candidate : remove current cell from cells to explore. 19235 if h#-2==1 break fi 19236 rows.. 0,{{-2,h}-2} 19237 fi 19238 while 1 19239 rm.. channels. 0 19240 19241_render_maze : 19242 # Create the 16 configurations of walls. 19243 i[0] $1,$1 i[1] [0]x15 19244 line[8-15] 0,0,100%,0,1,1 19245 line[4-7,12-15] 0,100%,100%,100%,1,1 19246 line[2-3,6-7,10-11,14-15] 0,0,0,100%,1,1 19247 line[1-15:2] 100%,0,100%,100%,1,1 19248 # Map the wall data with them. 19249 a[0-15] x r. {w*$1},{h*$1} *. $1 channels. 0,1 19250 $1,$1,1,1,x $1,$1,1,1,y a[-2,-1] c r. ..,..,1,2,0,2 +[-2,-1] 19251 warp.. .,0,0,0 rm. 19252 19253#@cli maze_mask : _cellsize>0 19254#@cli : Input maze according to size and shape of selected mask images. 19255#@cli : Mask may contain disconnected shapes. 19256#@cli : $ 0 text "G'MIC",0,0,53,1,1 dilate 3 autocrop 0 frame 1,1,0 maze_mask 8 dilate 3 negate mul 255 19257maze_mask : check "isint(${1=24}) && $1>0" 19258 e[^-1] "Input masked maze from image$? with cell size $1." 19259 compose_channels + >= 50% repeat $! l[$>] 19260 do 19261 +rand[0] 0,1 *. [0] ({[xM,yM]}) rm.. # Select one starting point in the mask. 19262 +flood[0] {^},0,0,0,1,2 >=. 2 +negate. *.. 15 a[-2,-1] c 19263 flood[0] {-2,^},0,0,0,1,0 19264 _generate_maze {w},{h} 19265 while iM#0 19266 rm[0] + _render_maze. $1 nm. [maze] 19267 endl done 19268 19269#@cli newton_fractal : z0r,z0i,z1r,z1i,_angle,0<=_descent_method<=2,_iteration_max>=0,_convergence_precision>0,\ 19270# _expr_p(z),_expr_dp(z),_expr_d2p(z) 19271#@cli : Draw newton fractal on selected images, for complex numbers in range (z0r,z0i) - (z1r,z1i). 19272#@cli : Resulting images have 3 channels whose meaning is [ last_zr, last_zi, nb_iter_used_for_convergence ]. 19273#@cli : 'descent_method' can be { 0=secant | 1=newton | 2=householder }. 19274#@cli : Default values: 'angle=0', 'descent_method=1', 'iteration_max=200', 'convergence_precision=0.01', \ 19275# 'expr_p(z)=z^^3-1', 'expr_dp(z)=3*z^^2' and 'expr_d2z(z)=6*z'. 19276#@cli : $ 400,400 newton_fractal -1.5,-1.5,1.5,1.5,0,2,200,0.01,"z^^6 + z^^3 - 1","6*z^^5 + 3*z^^2","30*z^^4 + 6*z" \ 19277# f "[ atan2(i1,i0)*90+20,1,cut(i2/30,0.2,0.7) ]" hsl2rgb 19278newton_fractal : check "isin(${6=1},0,1,2) && ${7=200}>=0 && ${8=0.01}>0" 19279 skip "${4=0},${9=z^^3-1},${10=3*z^^2},${11=6*z}" 19280 m0,m1,m2=secant,newton,householder 19281 e[^-1] "Draw newton fractal on image$?, for complex range ($1,$2)-($3,$4), with angle $5, $7 max "${m$6}" "\ 19282 "iterations, precision $8, and expressions 'p(z)=$9', 'dp(z)=$10' and 'd2p(z)=$11'." 19283 channels 0,2 19284 f "* 19285 begin( 19286 const dx = abs($3 - $1); 19287 const dy = abs($4 - $2); 19288 const angle = $5; 19289 const method = $6; 19290 const itermax = $7; 19291 const precision = $8; 19292 19293 zc = [ $1 + $3, $2 + $4 ]/2; 19294 R = rot(-angle°); 19295 ); 19296 19297 p(z) = ($9); 19298 dp(z) = ($10); 19299 d2p(z) = ($11); 19300 19301 zn = [ $1 + x*dx/(w-1), $2 + y*dy/(h-1) ]; 19302 angle?(zn = (R*(zn-=zc)+=zc)); 19303 19304 !method?(znm1 = zn + [ precision,0 ]); 19305 repeat (itermax,iter, 19306 pzn = p(zn); 19307 method==0?( 19308 znp1 = zn - pzn**(zn - znm1)//(pzn - p(znm1)); # secant 19309 znm1 = zn; 19310 ):method==1?( 19311 dpzn = dp(zn); 19312 znp1 = zn - pzn//dpzn; # newton 19313 ):( # householder 19314 dpzn = dp(zn); 19315 d2pzn = d2p(zn); 19316 hn = (pzn**d2pzn)//(2*dpzn^^2); 19317 znp1 = zn - pzn//dpzn**([1,0] + hn); 19318 ); 19319 norm(znp1 - zn)<precision?break(); 19320 zn = znp1; 19321 ); 19322 cabs(zn)<2?[ zn,iter ]:[ 0,0,iter ]" 19323 19324#@cli j3d : eq. to 'object3d'. : (+) 19325 19326#@cli object3d : [object3d],_x[%],_y[%],_z,_opacity,_rendering_mode,_is_double_sided={ 0 | 1 },\ 19327# _is_zbuffer={ 0 | 1 },_focale,_light_x,_light_y,_light_z,_specular_lightness,_specular_shininess : (+) 19328#@cli : Draw specified 3D object on selected images. 19329#@cli : (eq. to 'j3d').\n 19330#@cli : 'rendering_mode' can be { 0=dots | 1=wireframe | 2=flat | 3=flat-shaded | 4=gouraud-shaded | 5=phong-shaded }. 19331#@cli : Default values: 'x=y=z=0', 'opacity=1' and 'is_zbuffer=1'. All other arguments take their default values 19332#@cli : from the 3D environment variables. 19333#@cli : $ image.jpg torus3d 100,10 cone3d 30,-120 add3d[-2,-1] rotate3d. 1,1,0,60 object3d[0] [-1],50%,50% keep[0] 19334 19335#@cli pack_sprites : _nb_scales>=0,0<=_min_scale<=100,_allow_rotation={ 0=0 deg. | 1=180 deg. | 2=90 deg. | 3=any },\ 19336# _spacing,_precision>=0,max_iterations>=0 19337#@cli : Try to randomly pack as many sprites as possible onto the 'empty' areas of an image. 19338#@cli : Sprites can be eventually rotated and scaled during the packing process. 19339#@cli : First selected image is the canvas that will be filled with the sprites. 19340#@cli : Its last channel must be a binary mask whose zero values represent potential locations for drawing the sprites. 19341#@cli : All other selected images represent the sprites considered for packing. 19342#@cli : Their last channel must be a binary mask that represents the sprite shape (i.e. a 8-connected component). 19343#@cli : The order of sprite packing follows the order of specified sprites in the image list. 19344#@cli : Sprite packing is done on random locations and iteratively with decreasing scales. 19345#@cli : 'nb_scales' sets the number of decreasing scales considered for all specified sprites to be packed. 19346#@cli : 'min_scale' (in %) sets the minimal size considered for packing (specified as a percentage of the 19347#@cli : original sprite size). 19348#@cli : 'spacing' can be positive or negative. 19349#@cli : 'precision' tells about the desired number of failed trials before ending the filling process. 19350#@cli : Default values: 'nb_scales=5', 'min_scale=25', 'allow_rotation=3', 'spacing=1', 'precision=7' \ 19351# and 'max_iterations=256'. 19352#@cli : $ 512,512,1,3,"min(255,y*c/2)" 100%,100% circle 50%,50%,100,1,255 append c image.jpg resize2dy[-1] 24 \ 19353# to_rgba pack_sprites 3,25 19354pack_sprites : check "isint(${1=5}) && $1>=0 && ${2=25}>=0 && $2<=100 && isint(${3=3}) && $3>=0 && $3<=3 && 19355 isint(${4=1}) && isint(${5=7}) && $5>=0 && isint(${6=256}) && $6>=0" 19356 e[^-1] "Randomly pack image$? with $1 scales, minimum scale $2%, "${arg\ 1+$3,no,180\"\ \"deg.,90\"\ \"deg.,any}\ 19357 " rotation, spacing $4, precision $5 and $6 maximum iterations." 19358 N={$!-1} is_first_time=1 19359 repeat $! r[$>] 100%,100%,1,{$>,max(2,s)} done # Ensure all images have a binary shape mask. 19360 19361 # Start iterations over scales. 19362 repeat $1 19363 rprogress {$>*100/$1} 19364 nb_attempts=0 19365 19366 # Generate all sprites for current scale. 19367 ratio={if($1>1,$2+(100-$2)*$</($1-1),100)}% 19368 repeat $N +l[{1+$>}] 19369 w={w*$ratio} h={h*$ratio} 19370 if $w<1||$h<1 rm 19371 else r $w,$h,1,100%,2 sh. 100% !=. 0 area{1+$>}={is} rm. 19372 fi 19373 endl done 19374 19375 # Pack rescaled sprites together. 19376 l[0,{$N+1}--1] repeat $6 19377 19378 # Compute reference sprite. 19379 ind={1+($>%$N)} area=${area$ind} 19380 if $3==0 [$ind] 19381 elif $3==1 +rotate[$ind] {round(u)*180} 19382 elif $3==2 +rotate[$ind] {round(u(3))*90} 19383 else +rotate[$ind] {u*360} sh. 100% !=. 0 area={is} rm. 19384 fi 19385 19386 # Get binary map of possible locations. 19387 +channels[0] 100% ==. 0 19388 if $4>1 erode. {2*$4-1} 19389 elif $4<1 dilate. {-2*$4+3} 19390 fi 19391 19392 # Generate random skeleton-oriented point cloud. 19393 +rectangle. 0,0,100%,100%,1,0xFFFFFFFF,0 19394 if $is_first_time noise. 0.1,2 ==. 1 fi 19395 distance. 0 noise. 1,1 19396 max_patch. {$ind,round(1.5*max(w,h))} 19397 *. .. pointcloud3d. 19398 19399 # Subdivide point cloud if multiple sprites. 19400 if $N>1 l. 19401 s3d /[1] $N round[1] max[1] 1 n={1,@0} 19402 r[2] 3,{{2,h}/3},1,1,-1 19403 i[2] 1,{2,h} rand[2] 0,1 a[2,3] x sort[2] +,y z[2] 1,3 r[2] 3,$n,1,1 y[2] 19404 r[3] 1,{2*$n},1,1,0 r[4] 1,{3*$n},1,1,0 r[5] 1,$n,1,1,0 a y 19405 endl fi 19406 19407 # Create 3D cloud of sprites. 19408 n={@7} 19409 if $n 19410 s3d. rm[-2,-1] 19411 if $3==0 # No rotation allowed. 19412 [-6] i.. (-128;{w};{h};{s}) 19413 if $n>1 4,{$n-1},1,1,-128,0,0,0 fi 19414 +channels.. 100% i.. (-128;{w};{h};{s}) 19415 if $n>1 ... fi 19416 elif $3==1 # 180 deg. rotation allowed. 19417 +rotate[-6] {round(u(1))*180} i.. (-128;{w};{h};{s}) 19418 if $n>1 +rotate. 180 i.. (-128;{w};{h};{s}) fi 19419 if $n>2 4,{$n-2},1,1,-128,0,0,0 1,100% rand. 0,1 round. 1 j.. .,1 rm. fi 19420 +channels[-4] 100% i.. (-128;{w};{h};{s}) 19421 if $n>1 +channels[-4] 100% i.. (-128;{w};{h};{s}) fi 19422 if $n>2 [-5] fi 19423 else # 90 deg. rotation (or more) allowed. 19424 +rotate[-6] {round(u(3))*90} i.. (-128;{w};{h};{s}) 19425 if $n>1 +rotate. 90 i.. (-128;{w};{h};{s}) fi 19426 if $n>2 +rotate. 90 i.. (-128;{w};{h};{s}) fi 19427 if $n>3 +rotate. 90 i.. (-128;{w};{h};{s}) fi 19428 if $n>4 4,{$n-4},1,1,-128,0,0,0 1,100% rand. 0,3 round. 1 j.. .,1 rm. fi 19429 +channels[-8] 100% i.. (-128;{w};{h};{s}) 19430 if $n>1 +channels[-8] 100% i.. (-128;{w};{h};{s}) fi 19431 if $n>2 +channels[-8] 100% i.. (-128;{w};{h};{s}) fi 19432 if $n>3 +channels[-8] 100% i.. (-128;{w};{h};{s}) fi 19433 if $n>4 [-9] fi 19434 fi 19435 y[{$N+3}--1] a[{$N+3}--1] y 19436 fi 19437 rm... # Delete reference sprite. 19438 19439 # Draw cloud and detect non-intersecting sprites. 19440 [0] sh. 100% f. 1 -. [-4] 19441 j3d.. ...,0,0,0,1,2,0,0 rm[-3,-1] 19442 sh. 100% area_fg. 0,1 ==. $area 19443 *. ... rm... sh.. 0,{-2,s-2} *. .. rm. 19444 19445 # Draw selected sprites on rendering image. 19446 if iM j[0] ..,0,0,0,0,1,. rm[-2,-1] 19447 else 19448 rm[-2,-1] 19449 nb_attempts+=1 19450 if $nb_attempts>$5 break else continue fi 19451 fi 19452 19453 done k[0] endl 19454 19455 done k[0] 19456 19457#@cli piechart : label_height>=0,label_R,label_G,label_B,"label1",value1,R1,G1,B1,...,"labelN",valueN,RN,GN,BN 19458#@cli : Draw pie chart on selected (RGB) images. 19459#@cli : $ image.jpg piechart 25,0,0,0,"Red",55,255,0,0,"Green",40,0,255,0,"Blue",30,128,128,255,"Other",5,128,128,128 19460piechart : check $1>=0 19461 e[^-1] "Draw pie chart on image$?, with label height $1 and color ($2,$3,$4)." 19462 $=arg repeat $! l[$>] 19463 ellipse 50%,50%,{w/2-1},{h/2-1},0,1,1 19464 ellipse 50%,50%,{w/2-1},{h/2-1},0,1,0xFFFFFFFF 19465 (${6--1:5}) normalize_sum. 19466 theta=0 19467 if w>1 repeat w 19468 xe={0.5*{-2,w}*(1+cos($theta))} 19469 ye={0.5*{-2,h}*(1+sin($theta))} 19470 line.. 50%,50%,$xe,$ye 19471 theta-={2*pi*i($>)} 19472 done fi 19473 theta=0 19474 repeat w if i($>) 19475 ntheta={$theta-2*pi*i($>)} 19476 xc={0.5*{-2,w}*(1+0.5*cos(0.5*($ntheta+$theta)))} 19477 yc={0.5*{-2,h}*(1+0.5*sin(0.5*($ntheta+$theta)))} 19478 xf={0.5*{-2,w}*(1+0.8*cos(0.5*($ntheta+$theta)))} 19479 yf={0.5*{-2,h}*(1+0.8*sin(0.5*($ntheta+$theta)))} 19480 flood.. $xf,$yf,0,0,0,1,${arg{7+5*$>}},${arg{8+5*$>}},${arg{9+5*$>}} 19481 if abs($ntheta-$theta)>0.1 19482 0 t. ${arg{5+5*$>}},0,0,$1,1,1 19483 ($2^$3^$4) r. ..,..,1,3 *. .. 19484 j[-4] .,{$xc-w/2},{$yc-h/2},0,0,1,.. 19485 rm[-2,-1] 19486 fi 19487 theta=$ntheta 19488 fi done 19489 rm. 19490 endl done 19491 19492#@cli plasma : _alpha,_beta,_scale>=0 : (+) 19493#@cli : Draw a random colored plasma fractal on selected images. 19494#@cli : This command implements the so-called 'Diamond-Square' algorithm. 19495#@cli : Default values: 'alpha=1', 'beta=1' and 'scale=8'. 19496#@cli : $ 400,400,1,3 plasma 19497#@cli : $$ https://gmic.eu/oldtutorial/_plasma 19498 19499#@cli point : x[%],_y[%],_z[%],_opacity,_color1,... : (+) 19500#@cli : Set specified colored pixel on selected images. 19501#@cli : Default values: 'z=0', 'opacity=1' and 'color1=0'. 19502#@cli : $ image.jpg repeat 10000 point {u(100)}%,{u(100)}%,0,1,${-rgb} done 19503 19504#@cli polka_dots : diameter>=0,_density,_offset1,_offset2,_angle,_aliasing,_shading,_opacity,_color,... 19505#@cli : Draw dots pattern on selected images. 19506#@cli : Default values: 'density=20', 'offset1=offset2=50', 'angle=0', 'aliasing=10', 'shading=1', 'opacity=1' \ 19507# and 'color=255'. 19508#@cli : $ image.jpg polka_dots 10,15,0,0,20,10,1,0.5,0,128,255 19509polka_dots : check $1>=0 skip ${2=20},${3=50},${4=50},${5=0},${6=10},${7=1},${8=1},${9=255} 19510 e[^-1] "Draw polka dots on image$?, with diameter $1, density $2, angle $3 deg., shift ($4,$5), aliasing $6 and 19511 shading $7." 19512 theta={$5*pi/180} ct={cos($theta)} st={sin($theta)} mid1={$1/2} mid2={$2/2} 19513 i[0] (${9--1}) y[0] c 19514 repeat $!-1 19515 WH={max(w,h)} 19516 100%,100%,100%,1,"xn = 100*x/"$WH"-$3; yn = 100*y/"$WH"-$4; \ 19517 xr = xn*"$ct"-yn*"$st"; yr = xn*"$st"+yn*"$ct"; \ 19518 xc = xr%$2-"$mid2"; yc = yr%$2-"$mid2"; \ 19519 "$mid1"-sqrt(xc*xc+yc*yc)" 19520 *. $6 c. 0,$7 n. 0,$8 (${9--1}) y. c r. ..,..,.. 19521 j... .,0,0,0,0,1,.. rm[-2,-1] 19522 mv. 1 done rm[0] 19523 19524#@cli polygon : N>=1,x1[%],y1[%],...,xN[%],yN[%],_opacity,_pattern,_color1,... : (+) 19525#@cli : Draw specified colored N-vertices polygon on selected images. 19526#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 19527#@cli : even if a color is specified. If a pattern is specified, the polygon is 19528#@cli : drawn outlined instead of filled. 19529#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 19530#@cli : $ image.jpg polygon 4,20%,20%,80%,30%,80%,70%,20%,80%,0.3,0,255,0 \ 19531# polygon 4,20%,20%,80%,30%,80%,70%,20%,80%,1,0xCCCCCCCC,255 19532#@cli : $ image.jpg 2,16,1,1,'u(if(x,{h},{w}))' polygon[-2] {h},{^},0.6,255,0,255 remove[-1] 19533 19534#@cli quiver : [function_image],_sampling[%]>0,_factor>=0,_is_arrow={ 0 | 1 },_opacity,_color1,... 19535#@cli : Draw specified 2D vector/orientation field on selected images. 19536#@cli : Default values: 'sampling=5%', 'factor=1', 'is_arrow=1', 'opacity=1', 'pattern=(undefined)' 19537#@cli : and 'color1=0'. 19538#@cli : $ 100,100,1,2,'if(c==0,x-w/2,y-h/2)' 500,500,1,3,255 quiver[-1] [-2],10 19539#@cli : $ image.jpg +resize2dy 600 luminance[0] gradient[0] mul[1] -1 reverse[0,1] append[0,1] c \ 19540# blur[0] 8 orientation[0] quiver[1] [0],20,1,1,0.8,255 19541quiver : check ${"is_image_arg $1"}" && ${2=5%}>0 && ${3=1}>=0 && isbool(${4=1})" skip "${5=1},${6=0}" 19542 e[^-1] "Draw 2D vector field $1 on image$?, with sampling $2, factor $3, arrows "${"arg 1+$4,disabled,enabled"}", 19543 opacity $5 and color (${6--1})." 19544 pass$1 repeat $!-1 l[$>,-1] 19545 eval ${-math_lib}" 19546 s_sampling = ['$2']; 19547 sampling = s_sampling[size(s_sampling) - 1 ]==_'%'?min(w#0,h#0)*$2:$2; 19548 vmax = max(abs(im),abs(iM)); 19549 vmax = vmax?vmax:1; 19550 fact = $3*sampling/vmax; 19551 for (y = sampling/2, y<h#0, y+=sampling, 19552 for (x = sampling/2, x<w#0, x+=sampling, 19553 X = round(x*w/w#0); Y = round(y*h/h#0); 19554 u = i(X,Y,0,0)*fact; v = i(X,Y,0,1)*fact; 19555 if ($4, 19556 arrow(#0,[x,y],[x + u,y + v],45,sampling/4,$5,[${6--1}]), 19557 polygon(#0,2,[x - 0.5*u,y - 0.5*v],[x + 0.5*u,y + 0.5*v],$5,[${6--1}]); 19558 ); 19559 ); 19560 ); 19561 " 19562 endl done rm. 19563 19564#@cli rectangle : x0[%],y0[%],x1[%],y1[%],_opacity,_pattern,_color1,... 19565#@cli : Draw specified colored rectangle on selected images. 19566#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 19567#@cli : even if a color is specified. If a pattern is specified, the rectangle is 19568#@cli : drawn outlined instead of filled. 19569#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 19570#@cli : $ image.jpg repeat 30 rectangle {u(100)}%,{u(100)}%,{u(100)}%,{u(100)}%,0.3,${-rgb} done 19571rectangle : skip ${5=1},${6=0},${7=$6} 19572 if ${"is_pattern \"$5\""} 19573 e[0--3] "Draw outlined rectangle from ($1,$2) to ($3,$4) on image$?, with opacity $5 and color (${7--1})." 19574 else 19575 e[0--3] "Draw filled rectangle from ($1,$2) to ($3,$4) on image$?, with opacity $5 and color (${6--1})." 19576 fi 19577 polygon 4,$1,$2,$3,$2,$3,$4,$1,$4,${5--1} 19578 19579#@cli rorschach : 'smoothness[%]>=0','mirroring={ 0=none | 1=x | 2=y | 3=xy } 19580#@cli : Render rorschach-like inkblots on selected images. 19581#@cli : Default values: 'smoothness=5%' and 'mirroring=1'. 19582#@cli : $ 400,400 rorschach 3% 19583rorschach : check "${1=5%}>=0 && isint(${2=1}) && $2>=0 && $2<=3" 19584 e[^-1] "Render rorschach-like inkblots on image$?, with smoothness $1 and "${arg\ 1+$2,no,x,y,xy}"-mirroring." 19585 if $2==0 # No mirroring. 19586 rand -1,1 b $1 >= 0 19587 elif $2==1 # X-mirroring. 19588 repeat $! l[$>] 19589 w={w} 19590 columns 0,{w/2-1} rand -1,1 b $1 >= 0 19591 +mirror x if $w%2 columns. 1,100% fi a x 19592 endl done 19593 elif $2==2 # Y-mirroring. 19594 repeat $! l[$>] 19595 h={h} 19596 rows 0,{h/2-1} rand -1,1 b $1 >= 0 19597 +mirror y if $h%2 rows. 1,100% fi a y 19598 endl done 19599 elif $2==3 # XY-mirroring. 19600 repeat $! l[$>] 19601 w={w} h={h} 19602 z 0,0,{w/2-1},{h/2-1} rand -1,1 b $1 >= 0 19603 +mirror x if $w%2 columns. 1,100% fi a x 19604 +mirror y if $h%2 rows. 1,100% fi a y 19605 endl done 19606 fi 19607 19608#@cli sierpinski : recursion_level>=0 19609#@cli : Draw Sierpinski triangle on selected images. 19610#@cli : Default value: 'recursion_level=7'. 19611#@cli : $ image.jpg sierpinski 7 19612sierpinski : check ${1=7}>=0 skip ${2=50},${3=0},${4=0},${5=100},${6=100},${7=100} 19613 e[^-1] "Draw Sierpinski triangle of degree $1 on image$?." 19614 _sierpinski ${2-7},$1 19615 19616_sierpinski : 19617 if $7<=0 polygon 3,$1%,$2%,$3%,$4%,$5%,$6%,1,255 return fi 19618 _sierpinski $1,$2,{($1+$3)/2},{($2+$4)/2},{($1+$5)/2},{($2+$6)/2},{$7-1} 19619 _sierpinski {($1+$3)/2},{($2+$4)/2},$3,$4,{($3+$5)/2},{($4+$6)/2},{$7-1} 19620 _sierpinski {($1+$5)/2},{($2+$6)/2},$5,$6,{($3+$5)/2},{($4+$6)/2},{$7-1} 19621 19622#@cli spiralbw : width>0,_height>0,_is_2dcoords={ 0 | 1 } 19623#@cli : Input a 2D rectangular spiral image with specified size. 19624#@cli : Default values: 'height=width' and 'is_2dcoords=0'. 19625#@cli : $ spiralbw 16 19626#@cli : $ image.jpg spiralbw {[w,h]},1 +warp[0] [1],0 +warp[2] [1],2 19627+spiralbw : check "$1>=1 && ${2=$1}>=1 && isbool(${3=0})" 19628 e[^-1] "Input 2D rectangular spiral image of size $1x$2." 19629 main="alpha = min(x,y,w - 1 - x,h - 1 - y); 19630 t0 = alpha*2*(w + h) - 4*alpha^2; 19631 X = x - alpha; 19632 Y = y - alpha; 19633 W = w - 2*alpha; 19634 H = h - 2*alpha; 19635 t = t0 + (Y==0?X: 19636 X==W - 1?W - 1 + Y: 19637 Y==H - 1?2*W + H - 3 - X: 19638 2*(W + H - 2) - Y);" 19639 if $3 $1,$2,1,2,$main"[ t%w, int(t/w) ]" else $1,$2,1,1,$main fi 19640 19641#@cli spline : x0[%],y0[%],u0[%],v0[%],x1[%],y1[%],u1[%],v1[%],_opacity,_color1,... 19642#@cli : Draw specified colored spline curve on selected images (cubic hermite spline). 19643#@cli : Default values: 'opacity=1' and 'color1=0'. 19644#@cli : $ image.jpg repeat 30 spline {u(100)}%,{u(100)}%,{u(-600,600)},{u(-600,600)},{u(100)}%,{u(100)}%,\ 19645# {u(-600,600)},{u(-600,600)},0.6,255 done 19646spline : skip ${9=1},${10=0} 19647 e[^-1] "Draw spline from ($1,$2) [$3,$4] to ($5,$6) [$7,$8] on image$?, with opacity $9 and color (${10--1})." 19648 repeat $! l[$>] 19649 x0={if(${"is_percent $1"},$1*(w-1),$1)} 19650 y0={if(${"is_percent $2"},$2*(h-1),$2)} 19651 u0={if(${"is_percent $3"},$3*(w-1),$3)} 19652 v0={if(${"is_percent $4"},$4*(h-1),$4)} 19653 x1={if(${"is_percent $5"},$5*(w-1),$5)} 19654 y1={if(${"is_percent $6"},$6*(h-1),$6)} 19655 u1={if(${"is_percent $7"},$7*(w-1),$7)} 19656 v1={if(${"is_percent $8"},$8*(h-1),$8)} 19657 eval ${-math_lib}"spline(#0,["$x0","$y0"],["$u0","$v0"],["$x1","$y1"],["$u1","$v1"],$9,[${10--1}])" 19658 endl done 19659 19660#@cli tetraedron_shade : x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3,R0,G0,B0,...,R1,G1,B1,...,R2,G2,B2,...,R3,G3,B3,... 19661#@cli : Draw tetraedron with interpolated colors on selected (volumetric) images. 19662tetraedron_shade : 19663 e[^-1] "Draw tetraderon ($1,$2,$3)-($4,$5,$6)-($7,$8,$9)-($10,$11,$12) with interpolated colors in image$?." 19664 19665 # Find bounding box. 19666 xm={round(min($1,$4,$7,$10),1,-1)} xM={round(max($1,$4,$7,$10),1,1)} 19667 ym={round(min($2,$5,$8,$11),1,-1)} yM={round(max($2,$5,$8,$11),1,1)} 19668 zm={round(min($3,$6,$9,$12),1,-1)} zM={round(max($3,$6,$9,$12),1,1)} 19669 19670 # Find color mapping coefficients for each vertex. 19671 l[] (${1-3},1;${4-6},1;${7-9},1;${10-12},1) (${13--1}) r. {w/4},4,1,1,-1 s. x solve[^0] [0] rm[0] a c endl 19672 19673 # Draw tetraedron on selected images. 19674 f[^-1] "* 19675 begin( 19676 x0 = $1; y0 = $2; z0 = $3; 19677 x1 = $4; y1 = $5; z1 = $6; 19678 x2 = $7; y2 = $8; z2 = $9; 19679 x3 = $10; y3 = $11; z3 = $12; 19680 u01 = x1 - x0; v01 = y1 - y0; w01 = z1 - z0; 19681 u02 = x2 - x0; v02 = y2 - y0; w02 = z2 - z0; 19682 u03 = x3 - x0; v03 = y3 - y0; w03 = z3 - z0; 19683 u12 = x2 - x1; v12 = y2 - y1; w12 = z2 - z1; 19684 u13 = x3 - x1; v13 = y3 - y1; w13 = z3 - z1; 19685 u23 = x3 - x2; v23 = y3 - y2; w23 = z3 - z2; 19686 nx012 = v01*w02 - w01*v02; ny012 = w01*u02 - u01*w02; nz012 = u01*v02 - v01*u02; 19687 if (nx012*u03 + ny012*v03 + nz012*w03<0, nx012*=-1; ny012*=-1; nz012*=-1); 19688 nx013 = v01*w03 - w01*v03; ny013 = w01*u03 - u01*w03; nz013 = u01*v03 - v01*u03; 19689 if (nx013*u02 + ny013*v02 + nz013*w02<0, nx013*=-1; ny013*=-1; nz013*=-1); 19690 nx023 = v02*w03 - w02*v03; ny023 = w02*u03 - u02*w03; nz023 = u02*v03 - v02*u03; 19691 if (nx023*u01 + ny023*v01 + nz023*w01<0, nx023*=-1; ny023*=-1; nz023*=-1); 19692 nx123 = v12*w13 - w12*v13; ny123 = w12*u13 - u12*w13; nz123 = u12*v13 - v12*u13; 19693 if (-nx123*u01 - ny123*v01 - nz123*w01<0, nx123*=-1; ny123*=-1; nz123*=-1); 19694 ); 19695 if (x<"$xm" || x>"$xM" || y<"$ym" || y>"$yM" || z<"$zm" || z>"$zM",i, 19696 dx0 = x - x0; dy0 = y - y0; dz0 = z - z0; 19697 dx1 = x - x1; dy1 = y - y1; dz1 = z - z1; 19698 is_in = dx0*nx012 + dy0*ny012 + dz0*nz012>=0 && 19699 dx0*nx013 + dy0*ny013 + dz0*nz013>=0 && 19700 dx0*nx023 + dy0*ny023 + dz0*nz023>=0 && 19701 dx1*nx123 + dy1*ny123 + dz1*nz123>=0; 19702 is_in? i(#-1,0,0,0)*x + i(#-1,0,1,0)*y + i(#-1,0,2,0)*z + i(#-1,0,3,0) :i 19703 ) 19704" 19705 rm. 19706 19707#@cli t : eq. to 'text'. : (+) 19708 19709#@cli text : text,_x[%|~],_y[%|~],_font_height[%]>=0,_opacity,_color1,... : (+) 19710#@cli : Draw specified colored text string on selected images. 19711#@cli : (eq. to 't').\n 19712#@cli : If one of the x or y argument ends with a '~', its value is expected to be 19713#@cli : a centering ratio (in [0,1]) rather than a position. 19714#@cli : Usual centering ratio are { 0=left-justified | 0.5=centered | 1=right-justified }. 19715#@cli : Sizes '13' and '128' are special and correspond to binary fonts (no-antialiasing). 19716#@cli : Any other font size is rendered with anti-aliasing. 19717#@cli : Specifying an empty target image resizes it to new dimensions such that the image contains 19718#@cli : the entire text string. 19719#@cli : Default values: 'x=y=0.01~', 'font_height=16', 'opacity=1' and 'color1=0'. 19720#@cli : $ image.jpg resize2dy 600 y=0 repeat 30 text {2*$>}" : This is a nice text, isn't it ?",10,$y,{2*$>},0.9,255 \ 19721# y+={2*$>} done 19722#@cli : $ 0 text "G'MIC",0,0,23,1,255 19723 19724#@cli to : eq. to 'text_outline'. 19725to : skip "${1=}",${2=0.01~},${3=0.01~} check "${4=7.5%}>0 && ${5=2}>=0 && isnum(${6=1}) && isnum(${7=255}) && "\ 19726 "isnum(${8=$7}) && isnum(${9=$7}) && isnum(${10=255})" 19727 _text_outline $"*" 19728 19729#@cli text_outline : text,_x[%|~],_y[%|~],_font_height[%]>0,_outline>=0,_opacity,_color1,... 19730#@cli : Draw specified colored and outlined text string on selected images. 19731#@cli : If one of the x or y argument ends with a '~', its value is expected to be 19732#@cli : a centering ratio (in [0,1]) rather than a position. 19733#@cli : Usual centering ratio are { 0=left-justified | 0.5=centered | 1=right-justified }. 19734#@cli : Default values: 'x=y=0.01~', 'font_height=7.5%', 'outline=2', 'opacity=1', 'color1=color2=color3=255' \ 19735# and 'color4=255'. 19736#@cli : $ image.jpg text_outline "Hi there!",10,10,63,3 19737text_outline : skip "${1=}",${2=0.01~},${3=0.01~} 19738 check "${4=7.5%}>0 && ${5=2}>=0 && isnum(${6=1}) && isnum(${7=255}) && "\ 19739 "isnum(${8=$7}) && isnum(${9=$7}) && isnum(${10=255})" 19740 _text_outline $"*" 19741 19742_text_outline : skip "${1=}" 19743 e[0--3] "Draw outlined text '$1' at position ($2,$3) on image$?, with font height $4, outline $5, opacity $6 and 19744 color ${7--1}." 19745 if ['"$1"']==0 return fi 19746 sepx,sepy={"sx=['$2']; sy=['$3']; [sx[size(sx)-1], sy[size(sy)-1]]"} 19747 is_fontpercent=${"is_percent $4"} 19748 xpos={`s=['"$2"'];$sepx==_'~'||$sepx==_'%'?s[0,size(s)-1]:s`} 19749 ypos={`s=['"$3"'];$sepy==_'~'||$sepy==_'%'?s[0,size(s)-1]:s`} 19750 repeat $! l[$>] 19751 0 t. "$1",0,0,{-2,$is_fontpercent?h*$4:$4},1,1 expand_xy. {1+$5},0 19752 +dilate. {2*$5+1} 19753 i[-3] (${7--1}) r... {s#0},1,1,1,0,2 y... c r... .,.,1,100% 19754 if $5 *[-3,-2] else rm.. fi 19755 if w#0 19756 j... ..,{[($sepx==_'~'?(w#0-1-w):$sepx==_'%'?(w#0-1)%:1)*$xpos,\ 19757 ($sepy==_'~'?(h#0-1-h):$sepy==_'%'?(h#0-1)%:1)*$ypos]},0,0,$6,. 19758 k[0] 19759 else k[1] 19760 fi 19761 endl done 19762 19763#@cli triangle_shade : x0,y0,x1,y1,x2,y2,R0,G0,B0,...,R1,G1,B1,...,R2,G2,B2,... 19764#@cli : Draw triangle with interpolated colors on selected images. 19765#@cli : $ image.jpg triangle_shade 20,20,400,100,120,200,255,0,0,0,255,0,0,0,255 19766triangle_shade : 19767 e[^-1] "Draw triangle ($1,$2)-($3,$4)-($5,$6) with interpolated colors on image$?." 19768 # Find color mapping coefficients for each vertex. 19769 l[] ($1,$2,1;$3,$4,1;$5,$6,1) (${7--1}) r. {w/3},3,1,1,-1 s. x solve[^0] [0] rm[0] a c endl 19770 19771 # Pre-compute coefs to test point inside triangle. 19772 invarea={(-$4*$5+$2*(-$3+$5)+$1*($2-$6)+$3*$6)^-1} 19773 s1={$2*$5-$1*$6} s2={$6-$2} s3={$1-$5} 19774 t1={$1*$4-$2*$3} t2={$2-$4} t3={$3-$1} 19775 19776 # Begin drawing on each selected image. 19777 repeat $!-1 l[$>,-1] repeat s#0 19778 a={i(0,0,0,$>)} b={i(0,1,0,$>)} c={i(0,2,0,$>)} 19779 sh[0] $> 19780 f. "s = "$invarea"*("$s1" + "$s2"*x + "$s3"*y); 19781 t = "$invarea"*("$t1" + "$t2"*x + "$t3"*y); 19782 s>=0 && t>=0 && t+s<=1 ? "$a"*x+"$b"*y+"$c":i" 19783 rm. 19784 done endl done 19785 rm. 19786 19787#@cli truchet : _scale>0,_radius>=0,_pattern_type={ 0=straight | 1=curved } 19788#@cli : Fill selected images with random truchet patterns. 19789#@cli : Default values: 'scale=32', 'radius=5' and 'pattern_type=1'. 19790#@cli : $ 400,300 truchet , 19791truchet : check "isint(${1=32}) && $1>0 && ${2=3}>=0" skip ${3=1} 19792 e[^-1] "Render "${arg\ 1+!$3,curved,straight}" truchet patterns in image$?, with scale $1 and radius $2." 19793 repeat $! l[$>] nm={0,n} 19794 w={w} h={h} s={s} rm 19795 $1,$1 = 1,0,0 = 1,100%,100% distance 1,{1+$3} M={int(iM/2)} # Generate truchet pattern and its mirrored version. 19796 ir {$M-$2/2-($1%2)},{$M+$2/2} +mirror y a x 19797 {round($w/$1,1,1)},{round($h/$1,1,1)} rand. 0,1 >=. 50% r. {w*$1},{h*$1} *. $1 19798 channels. 0,1 (0,{$1-1}) r. $1,$1,1,1,3 +transpose. a[-2,-1] c ri. ..,0,2 +[-2,-1] 19799 warp.. . rm. >= 50% r $w,$h,1,1,0 r 100%,100%,1,$s 19800 nm $nm endl done 19801 19802#@cli turbulence : _radius>0,_octaves={1,2,3...,12},_alpha>0,_difference={-10,10},_mode={0,1,2,3} 19803#@cli : Render fractal noise or turbulence on selected images. 19804#@cli : Default values: 'radius=32', 'octaves=6', 'alpha=3', 'difference=0' and 'mode=0'. 19805#@cli : $ 400,400,1,3 turbulence 16 19806#@cli : $$ https://gmic.eu/oldtutorial/_turbulence 19807turbulence : check "${1=32}>0 && ${2=6}>0" skip ${3=3},${4=0},${5=0} 19808 e[^-1] "Render fractal noise or turbulence on image$?, with radius $1, octaves $2, damping per octave $3, 19809 difference $4 and mode $5." 19810 repeat $! l[$>] nm={0,n} 19811 if $4 . fi 19812 f. 0 +noise. 10,0 b. $1,0 19813 if $5==0||$5==1 -. {ia} abs. 19814 elif $5==3||$5==4 ^. 2 19815 elif $5==5 ^. 3 19816 fi 19817 repeat $2-1 19818 +noise.. 10,0 b. {$1/2^$>},0 19819 if $5==0 -. {ia} abs. 19820 elif $5==4 ^. 2 19821 elif $5==5 ^. 3 19822 fi 19823 *.. $3 +[-2--1] 19824 done 19825 n. 0,255 19826 rm.. 19827 if $4 *. $4 mv.. 2 - n. 0,255 fi 19828 nm $nm endl done 19829 19830#@cli yinyang 19831#@cli : Draw a yin-yang symbol on selected images. 19832#@cli : $ 400,400 yinyang 19833yinyang : 19834 e[^-1] "Draw yin-yang symbol on image$?." 19835 f 0 repeat $! l[$>] 19836 s={s} channels 0 19837 r={round(0.95*min(w,h)/4)} 19838 +line 50%,0,50%,50%,1,2 ellipse. 50%,{h/2-$r},$r,$r,0,1,2 19839 line. 50%,50%,50%,100%,1,1 ellipse. 50%,{h/2+$r},$r,$r,0,1,1 19840 flood. {w/2-$r},50%,0,0,0,1,2 19841 flood. {w/2+$r},50%,0,0,0,1,1 19842 ellipse.. 50%,50%,{2*$r},{2*$r},0,1,1 19843 * 19844 ellipse. 50%,{h/2-$r},{$r/3},{$r/3},0,1,1 19845 ellipse. 50%,{h/2+$r},{$r/3},{$r/3},0,1,2 19846 r 100%,100%,1,$s 19847 endl done 19848 19849#--------------------------------- 19850# 19851#@cli :: Matrix Computation 19852# 19853#--------------------------------- 19854 19855#@cli dijkstra : starting_node>=0,ending_node>=0 : (+) 19856#@cli : Compute minimal distances and paths from specified adjacency matrices by the Dijkstra algorithm. 19857 19858#@cli eigen : (+) 19859#@cli : Compute the eigenvalues and eigenvectors of selected symmetric matrices or matrix fields. 19860#@cli : If one selected image has 3 or 6 channels, it is regarded as a field of 2x2 or 3x3 symmetric matrices, 19861#@cli : whose eigen elements are computed at each point of the field. 19862#@cli : $ (1,0,0;0,2,0;0,0,3) +eigen 19863#@cli : $ image.jpg structuretensors blur 2 eigen split[0] c 19864#@cli : $$ https://gmic.eu/oldtutorial/_eigen 19865 19866#@cli invert : solver={ 0=SVD | 1=LU } : (+) 19867#@cli : Compute the inverse of the selected matrices. 19868#@cli : SVD solver is slower but less numerically instable than LU. 19869#@cli : Default value: 'solver=1'. 19870#@cli : $ (0,1,0;0,0,1;1,0,0) +invert 19871 19872#@cli orthogonalize : _mode = { 0=orthogonalize | 1=orthonormalize } 19873#@cli : Orthogonalize or orthonormalize selected matrices, using Modified Gram-Schmidt process. 19874#@cli : Default value: 'mode=0'. 19875orthogonalize : 19876 if isbool($1) mode=$1 else mode=0 noarg fi 19877 u0,u1,v0,v1=Orthogonalize,Orthonormalize,x,ce 19878 e[^-1] ${u$mode}" matri"${v{$!!=1}}"$?, using Modified Gram-Schmidt process." 19879 repeat $! l[$>] 19880 eval "> 19881 proj(u,v) = (dot(u,v)/dot(u,u)*u); 19882 for (p = 1, p<w, ++p, 19883 ref(crop(p,0,1,h),v); 19884 repeat (p,q, 19885 ref(crop(q,0,1,h),u); 19886 v-=proj(u,v); 19887 ); 19888 draw(v,p,0,0,0,1,h); 19889 )" 19890 if $mode 19891 eval. "*!y?( 19892 ref(crop(x,0,1,h),v); 19893 n = norm(v); 19894 v/=n?norm(v):1; 19895 draw(v,x,0,0,0,1,h); 19896 )" 19897 fi 19898 endl done 19899 19900#@cli meigen : m>=1 19901#@cli : Compute an approximation of the 'm' largest eigenvalues and eigenvectors of selected symmetric matrices, 19902#@cli : using the Arnoldi iteration method (https://en.wikipedia.org/wiki/Arnoldi_iteration). 19903#@cli : A larger 'm' goes with better numerical precision. 19904#@cli : $ (1,0,0;0,2,0;0,0,3) +meigen 3 19905meigen : check "isint($1) && $1>0" 19906 if $!!=1 s="ce" else s="x" fi 19907 e[^-1] "Compute $1 largest eigen-values of matri"$s"$?." 19908 repeat $! l[$>] nm={n} 19909 if w!=h" || "d!=1" || "s!=1 v 1 error[0--5] "Command 'meigen': Image '"$nm"' is not a square matrix." fi 19910 eval ${-math_lib}" store(meig(crop(),$1,h),'val',1,min($1,h))" $val k. nm $nm 19911 endl done 19912 19913#@cli mproj : [dictionary],_method,_max_iter={ 0=auto | >0 },_max_residual>=0 : (+) 19914#@cli : Find best matching projection of selected matrices onto the span of an over-complete 19915#@cli : dictionary D, using the orthogonal projection or Matching Pursuit algorithm. 19916#@cli : Selected images are 2D-matrices in which each column represent a signal to project. 19917#@cli : '[dictionary]' is a matrix in which each column is an element of the dictionary D. 19918#@cli : 'method' tells what projection algorithm must be applied. It can be: 19919#@cli : \ - 0 = orthogonal projection (least-squares solution using LU-based solver). 19920#@cli : \ - 1 = matching pursuit. 19921#@cli : \ - 2 = matching pursuit, with a single orthogonal projection step at the end. 19922#@cli : \ - >=3 = orthogonal matching pursuit where an orthogonal projection step is performed 19923#@cli : \ every 'method-2' iterations. 19924#@cli : 'max_iter' sets the max number of iterations processed for each signal. 19925#@cli : If set to '0' (default), 'max_iter' is equal to the number of columns in D. 19926#@cli : (only meaningful for matching pursuit and its variants). 19927#@cli : 'max_residual' gives a stopping criterion on signal reconstruction accuracy. 19928#@cli : (only meaningful for matching pursuit and its variants). 19929#@cli : For each selected image, the result is returned as a matrix W 19930#@cli : whose columns correspond to the weights associated to each column of D, 19931#@cli : such that the matrix product D*W is an approximation of the input matrix. 19932#@cli : Default values: 'method=0', 'max_iter=0' and 'max_residual=1e-6'. 19933 19934#@cli solve : [image] : (+) 19935#@cli : Solve linear system AX = B for selected B-matrices and specified A-matrix. 19936#@cli : If the system is under- or over-determined, the least squares solution is returned 19937#@cli : (using SVD-based solver). 19938#@cli : $ (0,1,0;1,0,0;0,0,1) (1;2;3) +solve[-1] [-2] 19939 19940#@cli svd : (+) 19941#@cli : Compute SVD decomposition of selected matrices. 19942#@cli : $ 10,10,1,1,'if(x==y,x+u(-0.2,0.2),0)' +svd 19943 19944#@cli transpose 19945#@cli : Transpose selected matrices. 19946#@cli : $ image.jpg +transpose 19947transpose : 19948 e[^-1] "Transpose image$?." 19949 permute yxzc 19950 19951#@cli trisolve : [image] : (+) 19952#@cli : Solve tridiagonal system AX = B for selected B-vectors and specified tridiagonal A-matrix. 19953#@cli : Tridiagonal matrix must be stored as a 3 column vector, where 2nd column contains the 19954#@cli : diagonal coefficients, while 1st and 3rd columns contain the left and right coefficients. 19955#@cli : $ (0,0,1;1,0,0;0,1,0) (1;2;3) +trisolve[-1] [-2] 19956 19957#--------------------------------- 19958# 19959#@cli :: 3D Meshes 19960# 19961#--------------------------------- 19962 19963#@cli +3d : eq. to 'add3d'. : (+) 19964 19965#@cli add3d : tx,_ty,_tz : [object3d] : (no arg) : (+) 19966#@cli : Shift selected 3D objects with specified displacement vector, or merge them with specified 19967#@cli : 3D object, or merge all selected 3D objects together. 19968#@cli : (eq. to '+3d'). 19969#@cli : Default values: 'ty=tz=0'. 19970#@cli : $ sphere3d 10 repeat 5 +add3d[-1] 10,{u(-10,10)},0 color3d[-1] ${-rgb} done add3d 19971#@cli : $ repeat 20 torus3d 15,2 color3d[-1] ${-rgb} mul3d[-1] 0.5,1 if $>%2 rotate3d[-1] 0,1,0,90 fi add3d[-1] 70 \ 19972# add3d rotate3d[-1] 0,0,1,18 done double3d 0 19973 19974#@cli animate3d : nb_frames>0,_step_angle_x,_step_angle_y,_step_angle_z,_zoom_factor,0<=_fake_shadow_level<=100,\ 19975# _[background] 19976#@cli : Generate 3D animation frames of rotating 3D objects. 19977#@cli : Frames are stacked along the z-axis (volumetric image). 19978#@cli : Frame size is the same as the size of the '[background]' image (or 800x800 if no background specified). 19979#@cli : Default values: 'filename=(undefined)'. 19980animate3d : check "isint($1) && $1>0 && isnum(${2=0}) && isnum(${3=5}) && isnum(${4=0}) && ${5=1}>0 && "\ 19981 "inrange(${6=50},0,100)" skip "${7=}" 19982 e[^-1] "Generate 3D animation frames from 3D object$?, with $1 frames, angle steps (${2-4}), zoom factor $5 "\ 19983 "and $6% fake shadow." 19984 if ${"is_image_arg $7"} pass$7 19985 else 3,2,1,1,"32,32,64,64,116,96" permute. cyzx r. 800,800,1,3,3 round. 19986 fi 19987 nm. anim3d_bg 19988 repeat {$!-1} l[$>,-1] check ${-is_3d..} nm={0,n} bn={0,b} 19989 e[] " * Object '"$bn"': 0/$1" 19990 c3d[0] n3d[0] *3d[0] {1,$5*min(w,h)/2} 19991 repeat $1 19992 e[] "\r * Object '"$bn"': "{1+$>}"/$1" 19993 +r3d[0] 0,0,1,{$>*$4} r3d. 0,1,0,{$>*$3} r3d. 1,0,0,{$>*$2} 19994 {1,[w,h,d,4]},-1 j3d. ..,50%,50%,0,1 19995 sh. 0,{s-2} sh.. 100% !=. -1 mul.. . mul. 255 rm[-2,-1] 19996 if $6 sh. 100% +b. 2% shift. {m=min(w,h)*2%;[m,m]} -. {255-$6*255%} c. 0,255 max[-2,-1] rm. fi # Add fake shadow 19997 +blend[1,-1] alpha rm[-3,-2] 19998 if {*} w. -1,-1,0 fi 19999 done 20000 a[2--1] z 20001 rv[0,-1] rm. 20002 endl nm[$>] $nm done 20003 rm. 20004 20005#@cli apply_camera3d : pos_x,pos_y,pos_z,target_x,target_y,target_z,up_x,up_y,up_z 20006#@cli : Apply 3D camera matrix to selected 3D objects. 20007#@cli : Default values: 'target_x=0', 'target_y=0', 'target_z=0', 'up_x=0', 'up_y=-1' and 'up_z=0'. 20008apply_camera3d : skip ${4=0},${5=0},${6=0},${7=0},${8=-1},${9=0} 20009 e[^-1] "Apply 3D camera matrix to 3D object$?, with camera position ($1,$2,$3), target position ($4,$5,$6) and 20010 up-vector ($7,$8,$9)." 20011 ({$4-$1}^{$5-$2}^{$6-$3}) # f. 20012 ($7^$8^$9) # up. 20013 orientation[-2,-1] # f/|f| and up/|up|. 20014 _cross3d {-2,^},{^} # s = f x up 20015 _cross3d {^},{-3,^} # u = s x f 20016 rm... y[-3--1] x mv[-2,-1] -3 20017 a[-3--1] y z. 0,3 # Rotation matrix R. 20018 -3d[^-1] $1,$2,$3 pose3d[^-1] {^} rm. -3d 0,0,800 20019 20020_cross3d : 20021 ({$2*$6-$3*$5}^{$3*$4-$1*$6}^{$1*$5-$2*$4}) orientation. y. 20022 20023#@cli apply_matrix3d : a11,a12,a13,...,a31,a32,a33 20024#@cli : Apply specified 3D rotation matrix to selected 3D objects. 20025#@cli : $ torus3d 10,1 +apply_matrix3d {mul(rot(1,0,1,-15°),[1,0,0,0,2,0,0,0,8],3)} double3d 0 20026apply_matrix3d : 20027 e[^-1] "Apply 3x3 matrix (${1-3};${4-6};${7-9}) to 3D object$?." 20028 repeat $! l[$>] 20029 nbp={i[6]} sh 8,{8+3*$nbp-1},0,0 r. 3,$nbp,1,1,-1 3,3,1,1,$* transpose. m*[-2,-1] rm. 20030 endl done 20031 20032#@cli array3d : size_x>=1,_size_y>=1,_size_z>=1,_offset_x[%],_offset_y[%],_offset_y[%] 20033#@cli : Duplicate a 3D object along the X,Y and Z axes. 20034#@cli : Default values: 'size_y=1', 'size_z=1' and 'offset_x=offset_y=offset_z=100%'. 20035#@cli : $ torus3d 10,1 +array3d 5,5,5,110%,110%,300% 20036array3d : check "isint($1) && $1>0 && isint(${2=1}) && $2>0 && isint(${3=1}) && $3>0" 20037 skip ${4=100%},${5=100%},${6=100%} 20038 e[^-1] "Duplicate 3D object$? along X,Y,Z axes with factors ($1,$2,$3) and offsets ($4,$5,$6)." 20039 repeat $! l[$>] 20040 20041 # Retrieve object dimensions. 20042 +rows 8,{8+3*i[6]} r. 3,{h/3},1,1,-1 s. x,3 20043 dx={-3,if(${is_percent\ $4},$4*(iM-im),$4)} 20044 dy={-2,if(${is_percent\ $5},$5*(iM-im),$5)} 20045 dz={if(${is_percent\ $6},$6*(iM-im),$6)} 20046 rm[-3--1] 20047 20048 # Duplicate along X. 20049 off=0 repeat int(log2($1)) 20050 ++3d. {2^$>*$dx} +3d. .. 20051 if !($1&(2^$>)) rm.. else +3d.. $off off+={2^$>*$dx} fi 20052 done +3d. $off +3d 20053 20054 # Duplicate along Y. 20055 off=0 repeat int(log2($2)) 20056 ++3d. 0,{2^$>*$dy} +3d. .. 20057 if !($2&(2^$>)) rm.. else +3d.. 0,$off off+={2^$>*$dy} fi 20058 done +3d. 0,$off +3d 20059 20060 # Duplicate along Z. 20061 off=0 repeat int(log2($3)) 20062 ++3d. 0,0,{2^$>*$dz} +3d. .. 20063 if !($3&(2^$>)) rm.. else +3d.. 0,0,$off off+={2^$>*$dz} fi 20064 done +3d. 0,0,$off +3d 20065 endl done 20066 20067#@cli arrow3d : x0,y0,z0,x1,y1,z1,_radius[%]>=0,_head_length[%]>=0,_head_radius[%]>=0 20068#@cli : Input 3D arrow with specified starting and ending 3D points. 20069#@cli : Default values: 'radius=5%', 'head_length=25%' and 'head_radius=15%'. 20070#@cli : $ repeat 10 a={$>*2*pi/10} arrow3d 0,0,0,{cos($a)},{sin($a)},-0.5 done +3d 20071+arrow3d : check "${7=5%}>=0 && ${8=25%}>=0 && ${9=15%}>=0" 20072 e[^-1] "Input 3D arrow, from (${1-3}) to (${4-6}), with radius $7, head length $8 and head radius $9." 20073 20074 # Create 3D object. 20075 L={sqrt(($4-$1)^2+($5-$2)^2+($6-$3)^2)} 20076 R={if(${is_percent\ $7},$7*$L,$7)} 20077 l={if(${is_percent\ $8},$8*$L,$8)} 20078 r={if(${is_percent\ $9},$9*$L,$9)} 20079 L-=$l cylinder3d $R,$L cone3d $r,$l +3d. 0,0,$L +3d[-2,-1] 20080 20081 # Compute rotation matrix for arrow orientation. 20082 ({$4-$1}^{$5-$2}^{$6-$3}) (0.01^-0.02^0.03) orientation[-2,-1] 20083 _cross3d {-2,^},{^} _cross3d {^},{-3,^} rm... y[-3--1] x mv[-2,-1] -3 20084 a[-3--1] y 20085 20086 # Rotate and translate the arrow at specified coordinates. 20087 s3d.. r[-5] 3,{-5,h/3},1,1,-1 m*[-5,-1] 20088 y[-4] a[-6--1] y +3d. ${1-3} rv3d. 20089 20090#@cli axes3d : _size_x,_size_y,_size_z,_font_size>0,_label_x,_label_y,_label_z,_is_origin={ 0=no | 1=yes } 20091#@cli : Input 3D axes with specified sizes along the x,y and z orientations. 20092#@cli : Default values: 'size_x=size_y=size_z=1', 'font_size=23', 'label_x=X', 'label_y=Y', 'label_z=Z' and \ 20093# 'is_origin=1' 20094#@cli : $ axes3d , 20095+axes3d : check "${4=23}>0 && isbool(${8=1})" skip ${1=1},${2=$1},${3=$2},"${5=X},${6=Y},${7=Z}" 20096 e[^-1] "Input 3D axes with sizes ($1,$2,$3)." 20097 l[] 20098 m={max(abs($1),abs($2),abs($3))/40} m2={2*$m} m3={1.2*$m2} 20099 if $1 line3d 0,0,0,$1,0,0 fi 20100 if $2 line3d 0,0,0,0,$2,0 fi 20101 if $3 line3d 0,0,0,0,0,$3 fi 20102 if $1 20103 cone3d $m,{2*$m},16 r3d. 0,1,0,90 +3d. {$1-$m2},0,0 20104 _axes3d "$5",$4 +3d. {$1+$m3},0,0 20105 fi 20106 if $2 20107 cone3d $m,{2*$m},16 r3d. 1,0,0,-90 +3d. 0,{$2-$m2},0 20108 _axes3d "$6",$4 +3d. 0,{$2+$m3},0 20109 fi 20110 if $3 20111 cone3d $m,{2*$m},16 +3d. 0,0,{$3-$m2} 20112 _axes3d "$7",$4 +3d. 0,0,{$3+$m3} 20113 fi 20114 if $8 _axes3d "O",$4 -3d. $m3,$m3,$m3 fi 20115 +3d nm [3d\ axes] 20116 endl 20117 20118_axes3d : 20119 0 t. "$1",2,0,$2,1,1 +dilate. 3 *.. 255 r.. 100%,100%,1,3 20120 i... (67.5;73.5;109.5;103.5;51.5;100.5;1;1;0;0;0;1;0;-128;{w};{h};3) 20121 i.. (-128;{w};{h};1) y[-3,-1] a[-4--1] y 20122 20123#@cli boundingbox3d 20124#@cli : Replace selected 3D objects by their 3D bounding boxes. 20125#@cli : $ torus3d 100,30 +boundingbox3d +3d[-1] [-2] 20126boundingbox3d : 20127 e[^-1] "Replace 3D object$? by their 3D bounding boxes." 20128 repeat $! l[$>] 20129 nbv={f2ui(i[6])} rows 8,{8+3*$nbv} r. 3,$nbv,1,1,-1 s. x 20130 xc,yc,zc,sx,sy,sz={"[ (im#0 + iM#0)/2, (im#1 + iM#1)/2, (im#2 + iM#2)/2, iM#0 - im#0,iM#1 - im#1, iM#2 - im#2 ]"} 20131 rm box3d $sx,$sy,$sz c3d +3d $xc,$yc,$zc p3d. 1 20132 endl done 20133 20134#@cli box3d : _size_x,_size_y,_size_z 20135#@cli : Input 3D box at (0,0,0), with specified geometry. 20136#@cli : Default values: 'size_x=1' and 'size_z=size_y=size_x'. 20137#@cli : $ box3d 100,40,30 +primitives3d 1 color3d[-2] ${-rgb} 20138+box3d : skip ${1=1},${2=$1},${3=$2} 20139 e[^-1] "Input 3D box, with size ($1,$2,$3)." 20140 1,86,1,1,\ 20141 67.5,73.5,109.5,103.5,51.5,100.5,8,6,\ 20142 0,0,0,$1,0,0,$1,$2,0,0,$2,0,\ 20143 0,0,$3,$1,0,$3,$1,$2,$3,0,$2,$3,\ 20144 4,0,3,2,1,4,4,5,6,7,4,0,1,5,4,4,3,7,6,2,4,0,4,7,3,4,1,2,6,5,\ 20145 200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,\ 20146 1,1,1,1,1,1 20147 nm. [3D\ box] 20148 20149#@cli c3d : eq. to 'center3d'. 20150c3d : 20151 _center3d 20152 20153#@cli center3d 20154#@cli : Center selected 3D objects at (0,0,0). 20155#@cli : (eq. to 'c3d'). 20156#@cli : $ repeat 100 circle3d {u(100)},{u(100)},{u(100)},2 done add3d color3d[-1] 255,0,0 +center3d \ 20157# color3d[-1] 0,255,0 add3d 20158center3d : 20159 _$0 20160 20161_center3d : 20162 e[0--3] "Center 3D object$?." 20163 check3d 0 repeat $! l[$>] 20164 if i[6] 20165 s3d r[2] 3,{2,h/3},1,1,-1 s[2] x 20166 -[2] {2,(iM+im)/2} -[3] {3,(iM+im)/2} -[4] {4,(iM+im)/2} 20167 a[2-4] x y[2] a y 20168 fi 20169 endl done 20170 20171#@cli circle3d : _x0,_y0,_z0,_radius>=0 20172#@cli : Input 3D circle at specified coordinates. 20173#@cli : Default values: 'x0=y0=z0=0' and 'radius=1'. 20174#@cli : $ repeat 500 a={$>*pi/250} circle3d {cos(3*$a)},{sin(2*$a)},0,{$a/50} color3d[-1] ${-rgb},0.4 done add3d 20175+circle3d : skip ${1=0},${2=0},${3=0},${4=1} 20176 e[^-1] "Input 3D circle at position ($1,$2,$3) with radius $4." 20177 r={$4/sqrt(3)} 20178 1,24,1,1,\ 20179 67.5,73.5,109.5,103.5,51.5,100.5,2,1,\ 20180 {$1-$r},{$2-$r},{$3-$r},\ 20181 {$1+$r},{$2+$r},{$3+$r},\ 20182 5,0,1,0,0,0,200,200,200,1 20183 nm. [3D\ circle] 20184 20185#@cli circles3d : _radius>=0,_is_wireframe={ 0 | 1 } 20186#@cli : Convert specified 3D objects to sets of 3D circles with specified radius. 20187#@cli : Default values: 'radius=1' and 'is_wireframe=1'. 20188#@cli : $ image.jpg luminance resize2dy 40 threshold 50% * 255 pointcloud3d color3d[-1] 255,255,255 circles3d 0.7 20189circles3d : check "${1=1}>=0 && isbool(${2=0})" 20190 e[^-1] "Convert 3D object$? to sets of 3D "${arg\ 1+$2,filled,wireframe}" circles with radius $1." 20191 p3d 0 repeat $! l[$>] 20192 -3d {$1/2},0,0 ++3d $1,0,0 +3d[1] [0] 20193 s3d # Two 3d objects decomposed here! 20194 rows[7] 0 j[1] [7] # Number of points 20195 rv[2,8] # Points 20196 rv[3,9] l[3] r 2,{h/2},1,1,-1 z 1,1 s y,2 i[0] 1,100%,1,1,5 1,100%,1,1,$2 2,100% a x y endl # Primitives 20197 k[0-5] a y 20198 endl done 20199 20200#@cli col3d : eq. to 'color3d'. : (+) 20201 20202#@cli color3d : R,_G,_B,_opacity : (no arg) : (+) 20203#@cli : Set color and opacity of selected 3D objects. 20204#@cli : (eq. to 'col3d'). 20205#@cli : Default value: 'B=G=R' and 'opacity=(undefined)'. 20206#@cli : $ torus3d 100,10 double3d 0 repeat 7 +rotate3d[-1] 1,0,0,20 color3d[-1] ${-rgb} done add3d 20207 20208#@cli colorcube3d 20209#@cli : Input 3D color cube. 20210#@cli : $ colorcube3d mode3d 2 +primitives3d 1 20211+colorcube3d : 20212 e[^-1] "Input 3D RGB-color cube." 20213 (67.5;73.5;109.5;103.5;51.5;100.5;8;6) 20214 (0;0;0;\ 20215 255;0;0;\ 20216 255;255;0;\ 20217 0;255;0;\ 20218 0;0;255;\ 20219 255;0;255;\ 20220 255;255;255;\ 20221 0;255;255) 20222 (12;0;3;2;1;0;0;0;63;63;63;63;0;\ 20223 12;1;2;6;5;0;0;0;63;63;63;63;0;\ 20224 12;0;4;7;3;0;0;63;0;63;63;0;63;\ 20225 12;4;5;6;7;0;0;63;0;63;63;0;63;\ 20226 12;0;1;5;4;0;0;63;0;63;63;0;63;\ 20227 12;3;7;6;2;0;0;0;63;63;63;63;0) 20228 (0,255;0,255^0,0;255,255^0,0;0,0) 20229 (255,255;255,255^0,0;255,255^0,255;0,255) 20230 (0,0;0,0^0,0;255,255^0,255;0,255) 20231 (0,255;0,255^0,0;255,255^255,255;255,255) 20232 (0,255;0,255^0,0;0,0^0,0;255,255) 20233 (0,255;0,255^255,255;255,255^0,0;255,255) 20234 r[-6--1] 64,64,1,3,3 round[-6--1] y[-6--1] i[-7--2] (-128;64;64;3) 20235 (1;1;1;1;1;1) 20236 a[-16--1] y nm. [3D\ colorcube] 20237 20238#@cli cone3d : _radius,_height,_nb_subdivisions>0 20239#@cli : Input 3D cone at (0,0,0), with specified geometry. 20240#@cli : Default value: 'radius=1','height=1' and 'nb_subdivisions=24'. 20241#@cli : $ cone3d 10,40 +primitives3d 1 color3d[-2] ${-rgb} 20242+cone3d : check ${3=24}>0 skip ${1=1},${2=1} 20243 e[^-1] "Input 3D cone, with radius $1, height $2 and $3 subdivisions." 20244 # Header. 20245 (67.5;73.5;109.5;103.5;51.5;100.5) 20246 ({$3+2};{2*$3}) 20247 20248 # Vertices. 20249 (0,0,0;0,0,$2) 20250 (0;{2*pi}) r. 1,{$3+1},1,1,3 rows. 0,{$3-1} +sin. cos.. *[-2,-1] $1 a[-2,-1] x z. 0,2 a[-2,-1] y 20251 20252 # Primitives. 20253 1,$3,1,1,'y' +shift. 0,-1 +[-2,-1] 2 20254 2,$3,1,1,3,0 .. [-4] a[-3--1] x 20255 i[-4] 2,$3,1,1,3,1 a[-4--2] x 20256 a[-2,-1] y 20257 20258 # Colors / opacities. 20259 3,{h},1,1,200 20260 1,{h},1,1,1 20261 y[-4--2] a[-6--1] y nm. [3D\ cone] 20262 20263#@cli cubes3d : _size>=0 20264#@cli : Convert specified 3D objects to sets of 3D cubes with specified size. 20265#@cli : Default value: 'size=1'. 20266#@cli : $ image.jpg luminance resize2dy 40 threshold 50% * 255 pointcloud3d color3d[-1] 255,255,255 cubes3d 1 20267cubes3d : check ${1=1}>=0 20268 e[^-1] "Convert 3D object$? to sets of 3D cubes with size $1." 20269 p3d 0 repeat $! l[$>] 20270 nbv={@6} nbp={@7} 20271 if $nbv&&$nbp 20272 s3d 20273 l[1] = {8*i[0]} = {6*i[1]},0,1 endl # Header. 20274 l[2] r 3,{h/3},1,1,-1 # Vertices. 20275 half={$1/2} 20276 - '$half,0,0' ++ '$1,0,0' a x 20277 - '0,$half,0' ++ '0,$1,0' a x 20278 - '0,0,$half' ++ '0,0,$1' a x 20279 endl 20280 l[3] r 2,{h/2},1,1,-1 # Primitives. 20281 z 1,1 * 8 r 4,100% i[0] 1,100%,1,1,4 a x [-1]x5 a x 20282 + '"0,0,2,3,1, 0,4,5,7,6, 0,0,1,5,4, 0,2,6,7,3, 0,0,4,6,2, 0,1,3,7,5"' 20283 endl 20284 l[4] r 3,{h/3},1,1,-1 r 18,100%,1,1,0,2 endl r[5] 6,100% # Colors & opacities. 20285 y a y 20286 fi 20287 endl done 20288 20289#@cli cup3d : _resolution>0 20290#@cli : Input 3D cup object. 20291#@cli : Default value: 'resolution=128'. 20292#@cli : $ cup3d , 20293+cup3d : check ${1=128}>0 20294 e[^-1] "Input 3D cup, with resolution $1." 20295 100,200 20296 ellipse. 0%,0%,40%,40%,0,1,1 20297 ellipse. 0,0,35%,35%,0,1,0 20298 polygon. 4,0,45%,8%,45%,20%,90%,0,90%,1,1 20299 ellipse. 0%,100%,30%,10%,0,1,1 b. 0.1% 20300 lathe3d. $1,2 nm. [3D\ cup] 20301 20302#@cli cylinder3d : _radius,_height,_nb_subdivisions>0 20303#@cli : Input 3D cylinder at (0,0,0), with specified geometry. 20304#@cli : Default value: 'radius=1','height=1' and 'nb_subdivisions=24'. 20305#@cli : $ cylinder3d 10,40 +primitives3d 1 color3d[-2] ${-rgb} 20306+cylinder3d : check ${3=24}>0 skip ${1=1},${2=1} 20307 e[^-1] "Input 3D cylinder, with radius $1, height $2 and $3 subdivisions." 20308 l[] 20309 N={round($3)} 20310 nbv,nbp={[2*$N+2,3*$N]} 20311 ({0.5+[{'CImg3d'}]}) 20312 ($nbv,$nbp) 20313 1,$nbv,1,3,"Z = (y<="$N"?0:$2); ang = ((y%("$N"+1))-1)*2*pi/"$N"; 20314 !(y%("$N"+1))?[0,0,Z]:[$1*cos(ang),$1*sin(ang),Z]" 20315 1,$N,1,13,"i1 = 1 + y; i2 = 1 + (i1%"$N"); const j0 = "$N" + 1; j1 = j0 + i1; j2 = j0 + i2; 20316 [ 3,0,i2,i1, 3,j0,j1,j2, 4,i1,i2,j2,j1 ]" 20317 permute[^0,1] "cyzx" 1,$nbp,1,3,200 1,$nbp,1,1,1 y a y 20318 nm. [3D\ cylinder] endl 20319 20320#@cli delaunay3d 20321#@cli : Generate 3D Delaunay triangulations from selected images. 20322#@cli : One assumes that the selected input images are binary images containing the set of points to mesh. 20323#@cli : The output 3D object is a mesh composed of non-oriented triangles. 20324#@cli : $ 500,500 noise 0.05,2 eq 1 * 255 +delaunay3d color3d[1] 255,128,0 dilate_circ[0] 5 to_rgb[0] \ 20325# +object3d[0] [1],0,0,0,1,1 max[-1] [0] 20326delaunay3d : 20327 e[^-1] "Generate 3D Delaunay triangulation from image$?." 20328 repeat $! l[$>] 20329 channels 0 != 0 20330 20331 # Label each point separately 20332 whd={w},{h},{d} +r 1,{w*h*d},1,1,-1 cumulate. *. .. r. $whd,1,-1 20333 20334 # Compute voronoi diagram of point cloud. 20335 +distance[0] 1 *[2] -1 watershed[1] [2] rm[2] 20336 20337 # Get redondant set of Delaunay triangles from the voronoi diagram. 20338 r[1] 100%,100%,100%,3 20339 if d>1 # Add detection cases for 3D images. 20340 +_delaunay3d[1] 1,0,0,0,0,1 +_delaunay3d[1] -1,0,0,0,0,-1 20341 +_delaunay3d[1] 0,1,0,0,0,1 +_delaunay3d[1] 0,-1,0,0,0,-1 20342 fi 20343 +_delaunay3d[1] 1,0,0,0,1,0 _delaunay3d[1] -1,0,0,0,-1,0 # 2D detection. 20344 a[^0] x transpose. -. 1 20345 20346 # Build 3D mesh. 20347 pointcloud3d[0] 20348 s3d[0] rm[3-5] i.. 1,100%,1,1,3 a[-2,-1] x 20349 3,100%,1,1,200 1,100%,1,1,1 =[1] {h},0,1 y a y 20350 endl done 20351 20352_delaunay3d : 20353 f. "A=j($1,$2,$3,0,0,1); B=j($4,$5,$6,0,0,1); 20354 if(i!=A && i!=B && A!=B, kth(1+c,i,A,B),0)" 20355 discard. 0 r. {h/3},3,1,1,-1 20356 20357#@cli distribution3d 20358#@cli : Get 3D color distribution of selected images. 20359#@cli : $ image.jpg distribution3d colorcube3d primitives3d[-1] 1 add3d 20360distribution3d : 20361 e[^-1] "Get 3D color distribution of image$?." 20362 to_rgb permute "cxyz" y 20363 repeat $! l[$>] 20364 nbp={round(h/3)} 20365 i.. (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 20366 $nbp;$nbp) # Number of vertices and primitives. 20367 1,$nbp,1,1,1 +f. y a[-2,-1] x y. # Primitives. 20368 .. # Colors. 20369 1,$nbp,1,1,1 # Opacities. 20370 a y nm. [3D\ distribution] # Build 3D object. 20371 endl done 20372 20373#@cli /3d : eq. to 'div3d'. : (+) 20374 20375#@cli div3d : factor : factor_x,factor_y,_factor_z : (+) 20376#@cli : Scale selected 3D objects isotropically or anisotropically, with the inverse of specified 20377#@cli : factors. 20378#@cli : (eq. to '/3d'). 20379#@cli : Default value: 'factor_z=0'. 20380#@cli : $ torus3d 5,2 repeat 5 +add3d[-1] 12,0,0 div3d[-1] 1.2 color3d[-1] ${-rgb} done add3d 20381 20382#@cli db3d : eq. to 'double3d'. : (+) 20383 20384#@cli double3d : _is_double_sided={ 0 | 1 } : (+) 20385#@cli : Enable/disable double-sided mode for 3D rendering. 20386#@cli : (eq. to 'db3d'). 20387#@cli : Default value: 'is_double_sided=1'. 20388#@cli : $ mode3d 1 repeat 2 torus3d 100,30 rotate3d[-1] 1,1,0,60 double3d $> snapshot3d[-1] 400 done 20389 20390#@cli elevation3d : { z-factor | [elevation_map] | 'formula' },base_height={ -1 | >=0 } : (no arg) 20391#@cli : Generate 3D elevation of selected images, opt. with a specified elevation map. 20392#@cli : When invoked with (no arg) or 'z-factor', the elevation map is computed as the pointwise L2 norm of the 20393#@cli : pixel values. Otherwise, the elevation map is taken from the specified image or formula. 20394#@cli : $ image.jpg +blur 5 elevation3d. 0.75 20395#@cli : $ 128,128,1,3,u(255) plasma 10,3 blur 4 sharpen 10000 n 0,255 \ 20396# elevation3d[-1] 'X=(x-64)/6;Y=(y-64)/6;-100*exp(-(X^2+Y^2)/30)*abs(cos(X)*sin(Y))' 20397elevation3d : skip "${1=_noarg}" check "${2=-1}==-1 || $2>=0" 20398 if $2>=0 base_str=" and base height $2" else base_str= fi 20399 if isnum($1) 20400 e[^-1] "Generate 3D elevation of image$?, with z-factor $1"$base_str. argtype,zfactor=0,$1 20401 elif ${"is_image_arg $1"} 20402 e[^-1] "Generate 3D elevation of image$?, from elevation $1"$base_str. argtype=2 20403 pass$1 0 if s>1 norm. fi store. elevation_img 20404 elif isexpr($1) 20405 e[^-1] "Generate 3D elevation of image$?, with formula '$1'"$base_str. argtype=1 20406 else 20407 e[^-1] "Generate 3D elevation of image$?." argtype,zfactor=0,1 20408 fi 20409 is_base={$2>=0} 20410 20411 repeat $! l[$>] nm={n} 20412 to_rgb M,N={[w,h]} 20413 20414 # Generate vertices. 20415 100%,100%,1,2,[x,y] 20416 if !$argtype +norm[0] *. $zfactor # with z-factor 20417 elif $argtype==1 [0],[0],1,1,"$1" # with formula 20418 else $elevation_img # from [image] 20419 fi 20420 a[-2,-1] c 20421 20422 if $is_base . sh. 100% f. {-sign($1)*$2} rm. a[-2,-1] y fi 20423 r. {wh},1,1,3,-1 permute. cxyz nbv={h} 20424 20425 # Generate primitives. 20426 header="const M = "$M"; const N = "$N"; const MN = M*N" 20427 {[$M,$N]-1},1,5,$header"; # Rear 20428 i0 = M*y + x; i1 = i0 + MN; 20429 [ 4,ui2f(i0),ui2f(i0 + M),ui2f(i0 + 1 + M),ui2f(i0 + 1) ]" 20430 r. 1,{wh},1,100%,-1 nbp={h} 20431 20432 if $is_base # Add base primitives if necessary 20433 {[$M,$N]-1},1,5,$header"; # Front 20434 i0 = M*y + x; i1 = i0 + MN; 20435 [ 4,ui2f(i1),ui2f(i1 + 1),ui2f(i1 + 1 + M),ui2f(i1 + M) ]" 20436 r. 1,{wh},1,100%,-1 nbp+={h} 20437 {$M-1},1,1,10,$header" ; # Top and bottom 20438 i0 = x; i1 = i0 + MN; i2 = i0 + M*(N - 1); i3 = i2 + MN; 20439 [ 4,ui2f(i0),ui2f(i0 + 1),ui2f(i1 + 1),ui2f(i1), 20440 4,ui2f(i2),ui2f(i3),ui2f(i3 + 1),ui2f(i2 + 1) ]" 20441 r. 1,{wh},1,100%,-1 s. c,2 nbp+={2*h} 20442 {$N-1},1,1,10,$header"; # Left and right 20443 i0 = M*x; i1 = i0 + MN; i2 = i0 + M - 1; i3 = i2 + MN; 20444 [ 4,ui2f(i0),ui2f(i1),ui2f(i1 + M),ui2f(i0 + M), 20445 4,ui2f(i2),ui2f(i2 + M),ui2f(i3 + M),ui2f(i3) ]" 20446 r. 1,{wh},1,100%,-1 s. c,2 nbp+={2*h} 20447 permute[-6--1] cyxz -a[-6--1] y 20448 else permute. cyxz 20449 fi 20450 20451 # Generate colors / opacities. 20452 mv[0] $! r. {[w,h]-1},1,3,0 r. {wh},1,1,3,-1 permute. cxyz 20453 if $is_base 3,{$nbp-h},1,1,200 fi 20454 1,$nbp,1,1,1 20455 20456 # Add header and merge object. 20457 i[0] ('CImg3d':y) +[0] 0.5 i[1] ({ui2f([$nbv,$nbp]):;}) y a y 20458 nm $nm 20459 endl done 20460 20461#@cli empty3d 20462#@cli : Input empty 3D object. 20463#@cli : $ empty3d 20464+empty3d : 20465 e[^-1] "Input empty 3D object." 20466 (67.5;73.5;109.5;103.5;51.5;100.5;0;0) nm. [3D\ empty] 20467 20468#@cli extrude3d : _depth>0,_resolution>0,_smoothness[%]>=0 20469#@cli : Generate extruded 3D object from selected binary XY-profiles. 20470#@cli : Default values: 'depth=16', 'resolution=1024' and 'smoothness=0.5%'. 20471#@cli : $ image.jpg threshold 50% extrude3d 16 20472extrude3d : check "${1=16}>0 && ${2=1024}>0 && ${3=0.5%}>=0" 20473 e[^-1] "Generate extruded 3D object from XY-profile$?, with depth $1, resolution $2 and smoothness $3." 20474 norm n 0,1 autocrop 0 repeat $! l[$>] nm={0,n} 20475 wr={round(max(1,if(w>h,min($2,w),min($2,h)*w/h)))} 20476 hr={round(max(1,if(w>h,min($2,w)*h/w,min($2,h))))} 20477 fact={$1/max(w/$wr,h/$hr)} 20478 b $3,0 r $wr,$hr,1,1,2 expand_xyz 1,0 20479 isosurface3d 50% *3d 1,1,$fact rv3d 20480 nm $nm endl done 20481 20482#@cli f3d : eq. to 'focale3d'. : (+) 20483 20484#@cli focale3d : focale : (+) 20485#@cli : Set 3D focale. 20486#@cli : (eq. to 'f3d').\n 20487#@cli : Set 'focale' to 0 to enable parallel projection (instead of perspective). 20488#@cli : Set negative 'focale' will disable 3D sprite zooming. 20489#@cli : Default value: 'focale=700'. 20490#@cli : $ repeat 5 torus3d 100,30 rotate3d[-1] 1,1,0,60 focale3d {$<*90} snapshot3d[-1] 400 done remove[0] 20491 20492#@cli gaussians3d : _size>0,_opacity 20493#@cli : Convert selected 3D objects into set of 3D gaussian-shaped sprites. 20494#@cli : $ image.jpg r2dy 32 distribution3d gaussians3d 20 colorcube3d primitives3d[-1] 1 +3d 20495gaussians3d : check "${1=32}>0" skip ${2=0.3} 20496 e[^-1] "Convert 3D object$? into sets of gaussian-shaped 3D sprites, with size $1 and opacity $2." 20497 p3d 2 p3d 0 repeat $! l[$>] nm={0,n} s3d 20498 nbv={h} rm. (-128;$1;$1;1) 20499 $1,$1 gaussian. 35%,35%,0 c. 30%,100% n. 0,$2 y. a[-2,-1] y # First opacity is generated. 20500 if $nbv>1 4,{$nbv-1},1,1,-128,0,0,0 y[-2,-1] a[-2,-1] y fi # Other ones are shared copies of the first one. 20501 a y 20502 nm $nm endl done 20503 20504#@cli gmic3d 20505#@cli : Input a 3D G'MIC logo. 20506#@cli : $ gmic3d +primitives3d 1 20507+gmic3d : 20508 e[^-1] "Input 3D G\47MIC logo." 20509 text3d G,60,20,2 col3d. 16,64,255 20510 text3d \',60,20,2 +3d. 40 col3d. 64,128,255 20511 text3d M,60,20,2 +3d. 50 col3d. 96,196,255 20512 text3d I,60,20,2 +3d. 90 col3d. 64,128,255 20513 text3d C,60,20,2 +3d. 100 col3d. 16,64,255 20514 sphere3d 8 +3d. 102,-3,20 col3d. 192,128,255 20515 +3d[-6--1] c3d. 20516 repeat 30 20517 box3d {min(3+$</2,10)} col3d. {30*$>},{20+80*$>},{10*$>},0.5 20518 r3d. 1,1,1,{$>*12} 20519 +3d. {80*cos(0.5+1.02*$>*12*pi/180)},{30*sin(0.8+$>*12*pi/180)},{2*$>-60} 20520 done 20521 +3d[-30--1] +3d. 0,5,30 +3d[-2--1] nm. [3d\ gmic] 20522 20523#@cli gyroid3d : _resolution>0,_zoom 20524#@cli : Input 3D gyroid at (0,0,0), with specified resolution. 20525#@cli : Default values: 'resolution=32' and 'zoom=5'. 20526#@cli : $ gyroid3d 48 +primitives3d 1 20527+gyroid3d : check ${1=32}>0 skip ${2=5} 20528 e[^-1] "Input 3D gyroid, with resolution $1 and range $2." 20529 isosurface3d "'0.49*(\ 20530 cos( 2*x + y + z - pi) + cos( 2*x - y + z - pi)\ 20531 + cos(- 2*x + y - z - pi) + cos(- 2*x - y - z - pi)\ 20532 + cos( x + 2*y + z - pi) + cos( x + 2*y - z - pi)\ 20533 + cos(- x - 2*y + z - pi) + cos(- x - 2*y - z - pi)\ 20534 + cos( x + y + 2*z - pi) + cos(- x + y + 2*z - pi)\ 20535 + cos( x - y - 2*z - pi) + cos(- x - y - 2*z - pi)\ 20536 + cos(- 2*x + y + z) + cos( 2*x + y - z)\ 20537 + cos(- 2*x - y + z) + cos( 2*x - y - z)\ 20538 + cos(- x + 2*y + z) + cos( x - 2*y + z)\ 20539 + cos(- x + 2*y - z) + cos( x - 2*y - z)\ 20540 + cos( x - y + 2*z) + cos( x + y - 2*z)\ 20541 + cos(- x - y + 2*z) + cos(- x + y - 2*z)\ 20542 ) + 0.27*( \ 20543 cos(- 2*x + 2*y - pi) + cos( 2*x - 2*y - pi)\ 20544 + cos( 2*x + 2*y - pi) + cos(- 2*x - 2*y - pi)\ 20545 + cos(- 2*y + 2*z - pi) + cos( 2*y - 2*z - pi)\ 20546 + cos( 2*y + 2*z - pi) + cos(- 2*y - 2*z - pi)\ 20547 + cos(- 2*z + 2*x - pi) + cos( 2*z - 2*x - pi)\ 20548 + cos( 2*z + 2*x - pi) + cos(- 2*z - 2*x - pi)\ 20549 ) - 0.69'",0,{-$2},{-$2},{-$2},$2,$2,$2,$1,$1,$1 20550 c3d. n3d. nm. [3D\ gyroid] 20551 20552#@cli histogram3d 20553#@cli : Get 3D color histogram of selected images. 20554#@cli : $ image.jpg resize2dx 64 histogram3d circles3d 3 opacity3d. 0.75 colorcube3d primitives3d[-1] 1 add3d 20555histogram3d : 20556 e[^-1] "Get 3D color histogram of image$?." 20557 to_rgb repeat $! l[$>] 20558 r {wh},3,1,1,-1 pointcloud 1 n 0,255 palette hot point. 0,0,0,1,0 map.. . rm. pointcloud3d nm "[3D histogram]" 20559 endl done 20560 20561#@cli image6cube3d 20562#@cli : Generate 3D mapped cubes from 6-sets of selected images. 20563#@cli : $ image.jpg animate flower,"30,0","30,5",6 image6cube3d 20564image6cube3d : 20565 e[^-1] "Generate 3D mapped cubes from image$?." 20566 M={max(${-max_wh})} r $M,$M,1,3 imageplane3d n3d c3d 20567 repeat int($!/6) l[$>-{$>+5}] 20568 +3d[0] 0,0,-0.5 20569 r3d[1] 0,1,0,90 +3d[1] -0.5,0,0 20570 r3d[2] 0,1,0,180 +3d[2] 0,0,0.5 20571 r3d[3] 0,1,0,270 +3d[3] 0.5,0,0 20572 r3d[4] 1,0,0,90 +3d[4] 0,0.5,0 20573 r3d[5] 1,0,0,270 +3d[5] 0,-0.5,0 20574 +3d nm "[3D image cube]" 20575 endl done 20576 20577#@cli imageblocks3d : _maximum_elevation,_smoothness[%]>=0 20578#@cli : Generate 3D blocks from selected images. 20579#@cli : Transparency of selected images is taken into account. 20580#@cli : Default values: 'maximum_elevation=10' and 'smoothness=0'. 20581#@cli : $ image.jpg resize2dy 32 imageblocks3d -20 mode3d 3 20582imageblocks3d : check ${2=0}>=0 skip ${1=10},${3=0} 20583 e[^-1] "Generate 3D blocks from image$?, with maximum elevation $1 and smoothness $2." 20584 repeat $! l[$>] 20585 w={w} h={h} 20586 split_opacity to_rgb[0] is_opacity={$!==2} 20587 20588 # Create 3D object template. 20589 l[] box3d 1,1,0 20590 repeat $w-1 ++3d. 1,0,0 done +3d 20591 repeat $h-1 ++3d. 0,1,0 done +3d 20592 endl 20593 s3d. 20594 20595 # Set vertex altitudes. 20596 +norm[0] b. $2 20597 y. n. 0,$1 20598 r[-5] 24,{-5,round(w*h/24)},1,1,-1 20599 if $1<0 j[-5] .,2 j[-5] .,5 j[-5] .,8 j[-5] .,11 20600 else j[-5] .,14 j[-5] .,17 j[-5] .,20 j[-5] .,23 20601 fi 20602 rm. y[-4] 20603 20604 # Set primitive colors. 20605 rm.. r[0] {0,wh},1,1,100%,-1 permute[0] cxyz r[0] 600%,100%,1,1,0,2 y[0] mv[0] -1 20606 20607 # Set primitive opacities. 20608 if $is_opacity rm. mv[0] $! /. 255 y. r. 6,100%,1,1 y. fi 20609 20610 a y 20611 endl done 20612 20613#@cli imagecube3d 20614#@cli : Generate 3D mapped cubes from selected images. 20615#@cli : $ image.jpg imagecube3d 20616imagecube3d : 20617 e[^-1] "Generate 3D mapped cubes from image$?." 20618 slices 50% to_rgb repeat $! l[$>] nm={0,n} 20619 i.. (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 20620 8;6;\ # Number of vertices and primitives. 20621 -0.5;-0.5;-0.5;\ # Vertex coordinates. 20622 0.5;-0.5;-0.5;\ 20623 0.5;0.5;-0.5;\ 20624 -0.5;0.5;-0.5;\ 20625 -0.5;-0.5;0.5;\ 20626 0.5;-0.5;0.5;\ 20627 0.5;0.5;0.5;\ 20628 -0.5;0.5;0.5;\ 20629 12;0;3;2;1;0;0;0;{h};{w};{h};{w};0;\ # Primitives description. 20630 12;1;2;6;5;0;0;0;{h};{w};{h};{w};0;\ 20631 12;5;6;7;4;0;0;0;{h};{w};{h};{w};0;\ 20632 12;4;7;3;0;0;0;0;{h};{w};{h};{w};0;\ 20633 12;4;0;1;5;0;0;0;{h};{w};{h};{w};0;\ 20634 12;3;7;6;2;0;0;0;{h};{w};{h};{w};0;\ 20635 -128;{w};{h};{s}) # Texture map for the first face. 20636 y. 20637 (-128;0;0;0;-128;0;0;0;-128;0;0;0;-128;0;0;0;-128;0;0;0;1;1;1;1;1;1) # Other faces and opacities. 20638 a y 20639 nm $nm endl done 20640 20641#@cli imageplane3d 20642#@cli : Generate 3D mapped planes from selected images. 20643#@cli : $ image.jpg imageplane3d 20644imageplane3d : 20645 e[^-1] "Generate 3D mapped planes from image$?." 20646 slices 50% to_color repeat $! l[$>] nm={0,n} 20647 i.. (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 20648 4;1;\ # Number of vertices and primitives. 20649 0;0;0;\ # Vertex coordinates. 20650 {w};0;0;\ 20651 {w};{h};0;\ 20652 {0};{h};0;\ 20653 12;0;3;2;1;0;0;0;{h};{w};{h};{w};0;\ # Primitives description. 20654 -128;{w};{h};{s}) # Texture map. 20655 y. 20656 (1) # Opacity. 20657 a y 20658 nm $nm endl done 20659 20660#@cli imagepyramid3d 20661#@cli : Generate 3D mapped pyramids from selected images. 20662#@cli : $ image.jpg imagepyramid3d 20663imagepyramid3d : 20664 e[^-1] "Generate 3D mapped pyramids from image$?." 20665 to_rgb repeat $! l[$>] nm={0,n} 20666 w2={w/2} 20667 i.. (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 20668 5;5;\ # Number of vertices and primitives. 20669 -0.5;-0.5;-0.5;\ # Vertex coordinates. 20670 0.5;-0.5;-0.5;\ 20671 0.5;0.5;-0.5;\ 20672 -0.5;0.5;-0.5;\ 20673 0;0;0.5;\ 20674 12;0;3;2;1;0;0;0;{h};{w};{h};{w};0;\ # Primitives description. 20675 9;0;4;3;0;{h};$w2;0;{w};{h};\ 20676 9;1;4;0;0;{h};$w2;0;{w};{h};\ 20677 9;2;4;1;0;{h};$w2;0;{w};{h};\ 20678 9;3;4;2;0;{h};$w2;0;{w};{h};\ 20679 -128;{w};{h};{s}) # Texture map for the first face. 20680 y. 20681 (-128;0;0;0;-128;0;0;0;-128;0;0;0;-128;0;0;0;1;1;1;1;1) # Other faces and opacities. 20682 a y 20683 nm $nm endl done 20684 20685#@cli imagerubik3d : _xy_tiles>=1,0<=xy_shift<=100,0<=z_shift<=100 20686#@cli : Generate 3D mapped rubik's cubes from selected images. 20687#@cli : Default values: 'xy_tiles=3', 'xy_shift=5' and 'z_shift=5'. 20688#@cli : $ image.jpg imagerubik3d , 20689imagerubik3d : check "${1=3}>=1 && ${2=5}>=0 && $2<=100 && ${3=5}>=0 && $3<=100" 20690 e[^-1] "Generate 3D mapped rubik\47s cubes from image$? with $1 xy-tiles, xy-shift $2 and z-shift $3." 20691 repeat $! l[$>] nm={0,n} 20692 # Generate primary 3D side. 20693 ('CImg3d') +. 0.5 20694 (8,5) 20695 (0,0,0;\ 20696 100,0,0;\ 20697 100,100,0;\ 20698 0,100,0;\ 20699 $2,$2,{-$3};\ 20700 {100-$2},$2,{-$3};\ 20701 {100-$2},{100-$2},{-$3};\ 20702 $2,{100-$2},{-$3}) 20703 (4,4,7,6,5;\ 20704 4,0,4,5,1;\ 20705 4,3,2,6,7;\ 20706 4,0,3,7,4;\ 20707 4,1,5,6,2) 20708 3,5,1,1,200 20709 1,5,1,1,1 20710 y[-6--1] a[-6--1] y 20711 repeat $1-1 ++3d. 100 done +3d[-$1--1] # Duplicate along X 20712 repeat $1-1 ++3d. 0,100 done +3d[-$1--1] # Duplicate along Y 20713 t3d. .. rm.. 20714 /3d. $1 -3d. 50,50,50 20715 +r3d. 0,1,0,-90 +r3d. 0,1,0,-90 +r3d. 0,1,0,-90 # Generate the 5 other sides. 20716 +r3d. 0,0,1,-90 +r3d. 0,0,1,180 20717 +3d 20718 nm $nm endl done 20719 20720#@cli imagesphere3d : _resolution1>=3,_resolution2>=3 20721#@cli : Generate 3D mapped sphere from selected images. 20722#@cli : Default values: 'resolution1=32' and 'resolutions2=16'. 20723#@cli : $ image.jpg imagesphere3d 32,16 20724imagesphere3d : check "${1=32}>=3 && ${2=16}>=3" 20725 e[^-1] "Generate 3D mapped sphere from image$?, with resolutions ($1,$2)." 20726 to_rgb repeat $! l[$>] nm={0,n} 20727 20728 # Generate object header. 20729 tw={w-1} th={h-1} # Maximum texture xy-coordinates. 20730 nbv={2+$1*($2-2)} # Number of vertices. 20731 nbp={$1*($2-1)} # Number of primitives. 20732 (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 20733 $nbv;$nbp) # Number of vertices and primitives. 20734 20735 # Define sphere vertices. 20736 (0;0;1) (0;0;-1) (0,{2*pi};0,{2*pi}^0,0;{pi},{pi}) 20737 r. {$1+1},$2,1,2,3 z. 0,1,{w-2},{h-2} s. c 20738 +sin. +sin... *[-2,-1] +cos.. sin... cos[-4] *[-4,-3] 20739 a[-3--1] c permute. cxyz y. a[-3--1] y 20740 20741 # Define sphere primitives (triangles and quadrangles). 20742 repeat $1,v 20743 tx0={$v*$tw/$1} tx1={($v+1)*$tw/$1} ty1={$th/($2-1)} 20744 (9;0;{2+$v};{2+($v+1)%$1};{$tw/2};0;$tx0;$ty1;$tx1;$ty1) # Textured triangle from 1st pole. 20745 repeat $2-3,u 20746 ty0=$ty1 ty1={($u+2)*$th/($2-1)} i0={2+$u*$1+$v} i1={2+$u*$1+($v+1)%$1} 20747 (12;$i0;{$i0+$1};{$i1+$1};$i1;$tx0;$ty0;$tx0;$ty1;$tx1;$ty1;$tx1;$ty0) # Textured quadrangle. 20748 done 20749 (9;1;{2+$1*($2-3)+($v+1)%$1};{2+$1*($2-3)+$v};{$tw/2};$th;$tx1;$ty1;$tx0;$ty1) # Textured triangle from 2nd pole. 20750 done 20751 a[-$nbp--1] y 20752 20753 # Define sphere textures, opacities and generate object. 20754 mv[-4] $! i.. (-128;{w};{h};3) y. 1,{4*($nbp-1)},1,1,-128,0,0,0 1,$nbp,1,1,1 a y 20755 nm $nm endl done 20756 20757#@cli isoline3d : isovalue[%] : 'formula',value,_x0,_y0,_x1,_y1,_size_x>0[%],_size_y>0[%] : (+) 20758#@cli : Extract 3D isolines with specified value from selected images or from specified formula. 20759#@cli : Default values: 'x0=y0=-3', 'x1=y1=3' and 'size_x=size_y=256'. 20760#@cli : $ image.jpg blur 1 isoline3d 50% 20761#@cli : $ isoline3d 'X=x-w/2;Y=y-h/2;(X^2+Y^2)%20',10,-10,-10,10,10 20762 20763#@cli isosurface3d : isovalue[%] : 'formula',value,_x0,_y0,_z0,_x1,_y1,_z1,_size_x>0[%],_size_y>0[%],_size_z>0[%] : (+) 20764#@cli : Extract 3D isosurfaces with specified value from selected images or from specified formula. 20765#@cli : Default values: 'x0=y0=z0=-3', 'x1=y1=z1=3' and 'size_x=size_y=size_z=32'. 20766#@cli : $ image.jpg resize2dy 128 luminance threshold 50% expand_z 2,0 blur 1 isosurface3d 50% mul3d 1,1,30 20767#@cli : $ isosurface3d 'x^2+y^2+abs(z)^abs(4*cos(x*y*z*3))',3 20768 20769#@cli label3d : "text",font_height>=0,_opacity,_color1,... 20770#@cli : Generate 3D text label. 20771#@cli : Default values: 'font_height=13', 'opacity=1' and 'color=255,255,255'. 20772+label3d : check ${2=13}>=0 skip ${3=1},${4=255},${5=$4},${6=$5} 20773 e[^-1] "Generate 3D label '$1' with font height $2, opacity $3 and color (${4--1})." 20774 l[] 0 t "$1",0,0,$2,1,${4--1},255 sprite3d endl 20775 20776#@cli label_points3d : _label_size>0,_opacity 20777#@cli : Add a numbered label to all vertices of selected 3D objects. 20778#@cli : Default values: 'label_size=13' and 'opacity=0.8'. 20779#@cli : $ torus3d 100,40,6,6 label_points3d 23,1 mode3d 1 20780label_points3d : check ${1=13}>0 skip ${2=0.8} 20781 e[^-1] "Label vertices of 3D object$?." 20782 repeat $! 20783 +p3d[$>] 0 l. s3d rm[-3--1] 20784 nbp={-2,@0} =.. $nbp,0,1 # Set correct number of primitives 20785 (1,0;1,{$nbp-1}) r. 2,$nbp,1,1,3 r. 1,{2*h},1,1,-1 # Create new primitive data 20786 repeat $nbp # Create texture labels as primitive colors. 20787 0 t. $>,0,0,$1,1,255,255,255 autocrop. 0 20788 i.. (-128;{w};{h};3) y. 20789 done 20790 repeat $nbp # Create texture masks as primitive opacities. 20791 0 t. $>,0,0,$1,1,$2 autocrop. 0 20792 i.. (-128;{w};{h};1) y. 20793 done 20794 a y # Merge final object data. 20795 endl 20796 +3d[$>,-1] 20797 done 20798 20799#@cli lathe3d : _resolution>0,_smoothness[%]>=0,_max_angle>=0 20800#@cli : Generate 3D object from selected binary XY-profiles. 20801#@cli : Default values: 'resolution=128', 'smoothness=0.5%' and 'max_angle=361'. 20802#@cli : $ 300,300 rand -1,1 blur 40 sign normalize 0,255 lathe3d , 20803lathe3d : check "${1=128}>0 && ${2=0.5%}>=0 && ${3=361}>=0" 20804 e[^-1] "Generate lathed 3D object from XY-profile$?, with resolution $1, smoothness $2 and maximum angle $3 deg." 20805 tmax={($3-180)*pi/180} norm n 0,1 autocrop 0 20806 repeat $! l[$>] 20807 wr={max(1,w2=2*w;if(w2>h,min($1,w2),min($1,h)*w2/h))} 20808 hr={max(1,w2=2*w;if(w2>h,min($1,w2)*h/w2,min($1,h)))} 20809 rmax={sqrt(($wr)^2+($hr)^2)/2} 20810 $wr,1,$wr,1,"xc = x - w/2; zc = z - d/2; t = atan2(zc,xc); if(t>"$tmax","$rmax",sqrt(xc*xc+zc*zc))" 20811 *. {2*({-2,w}-1)/(w-1)} r. $wr,$hr,$wr 20812 (0;{{-2,h}-1}) r. $wr,$hr,$wr,1,3 a[-2--1] c 20813 warp.. .,0,1,0 rm. 20814 expand_xyz 10,0 b $2 isosurface3d 50% rv3d 20815 endl done 20816 20817#@cli l3d : eq. to 'light3d'. : (+) 20818 20819#@cli light3d : position_x,position_y,position_z : [texture] : (no arg) : (+) 20820#@cli : Set the light coordinates or the light texture for 3D rendering. 20821#@cli : (eq. to 'l3d').\n 20822#@cli : (no arg) resets the 3D light to default. 20823#@cli : $ torus3d 100,30 double3d 0 specs3d 1.2 repeat 5 light3d {$>*100},0,-300 +snapshot3d[0] 400 done remove[0] 20824 20825#@cli line3d : x0,y0,z0,x1,y1,z1 20826#@cli : Input 3D line at specified coordinates. 20827#@cli : $ repeat 100 a={$>*pi/50} line3d 0,0,0,{cos(3*$a)},{sin(2*$a)},0 color3d. ${-rgb} done add3d 20828+line3d : 20829 e[^-1] "Input 3D line (${1-3})-(${4-6})." 20830 1,21,1,1,67.5,73.5,109.5,103.5,51.5,100.5,2,1,${1-6},2,0,1,200,200,200,1 nm. [3D\ line] 20831 20832#@cli lissajous3d : resolution>1,a,A,b,B,c,C 20833#@cli : Input 3D lissajous curves __(x(t)=sin(a*t+A*2*pi), y(t)=sin(b*t+B*2*pi), z(t)=sin(c*t+C*2*pi))__. 20834#@cli : Default values: 'resolution=1024', 'a=2', 'A=0', 'b=1', 'B=0', 'c=0' and 'C=0'. 20835#@cli : $ lissajous3d , 20836+lissajous3d : check ${1=1024}>1 skip ${2=2},${3=0},${4=1},${5=0},${6=0},${7=0} 20837 e[^-1] "Input 3D lissajous curve, with resolution $1, (a,A)=($2,$3), (b,B)=($4,$5) and (c,C)=($6,$7)." 20838 res={round($1)} 20839 20840 # Define object header and vertices. 20841 (67.5;73.5;109.5;103.5;51.5;100.5;$res;{$res-1}) 20842 (0,{2*pi}) r. $res,1,1,1,3 [-1]x2 20843 *... $2 +... {$3*2*pi} *.. $4 +.. {$5*2*pi} *. $6 +. {$7*2*pi} 20844 a[-3--1] y sin. transpose. r. 1,{w*h},1,1,-1 20845 20846 # Define object primitives, colors and opacities. 20847 1,{$res-1},1,1,2 (0;{$res-2}) r. 1,{$res-1},1,1,3 ++. 1 a[-3--1] x round. 1 r. 1,{w*h},1,1,-1 20848 1,{3*($res-1)},1,1,200 1,{$res-1},1,1,1 a[-5--1] y nm. [3D\ lissajou] 20849 20850#@cli m3d : eq. to 'mode3d'. : (+) 20851 20852#@cli mode3d : _mode : (+) 20853#@cli : Set static 3D rendering mode. 20854#@cli : (eq. to 'm3d').\n 20855#@cli : 'mode' can be { -1=bounding-box | 0=dots | 1=wireframe | 2=flat | 3=flat-shaded | 4=gouraud-shaded | \ 20856# 5=phong-shaded }."); 20857#@cli : Bounding-box mode ('mode==-1') is active only for the interactive 3D viewer. 20858#@cli : Default value: 'mode=4'. 20859#@cli : $ (0,1,2,3,4,5) double3d 0 repeat w torus3d 100,30 rotate3d[-1] 1,1,0,60 mode3d {0,@$>} \ 20860# snapshot3d[-1] 300 done remove[0] 20861 20862#@cli md3d : eq. to 'moded3d'. : (+) 20863 20864#@cli moded3d : _mode : (+) 20865#@cli : Set dynamic 3D rendering mode for interactive 3D viewer. 20866#@cli : (eq. to 'md3d').\n 20867#@cli : 'mode' can be { -1=bounding-box | 0=dots | 1=wireframe | 2=flat | 3=flat-shaded | 4=gouraud-shaded | \ 20868# 5=phong-shaded }. 20869#@cli : Default value: 'mode=-1'. 20870 20871#@cli *3d : eq. to 'mul3d'. : (+) 20872 20873#@cli mul3d : factor : factor_x,factor_y,_factor_z : (+) 20874#@cli : Scale selected 3D objects isotropically or anisotropically, with specified factors. 20875#@cli : (eq. to '*3d'). 20876#@cli : Default value: 'factor_z=0'. 20877#@cli : $ torus3d 5,2 repeat 5 +add3d[-1] 10,0,0 mul3d[-1] 1.2 color3d[-1] ${-rgb} done add3d 20878 20879#@cli n3d : eq. to 'normalize3d'. 20880n3d : 20881 _normalize3d 20882 20883#@cli normalize3d 20884#@cli : Normalize selected 3D objects to unit size. 20885#@cli : (eq. to 'n3d'). 20886#@cli : $ repeat 100 circle3d {u(3)},{u(3)},{u(3)},0.1 done add3d color3d[-1] 255,0,0 +normalize3d[-1] \ 20887# color3d[-1] 0,255,0 add3d 20888normalize3d : 20889 _$0 20890 20891_normalize3d : 20892 e[0--3] "Normalize size of 3D object$?." 20893 check3d 0 repeat $! l[$>] 20894 if i[6] 20895 s3d r[2] 3,{2,h/3},1,1,-1 s[2] x 20896 factor={v=max({2,iM-im},{3,iM-im},{4,iM-im});if(v,v,1)} 20897 a[2-4] x /[2] $factor y[2] a y 20898 fi 20899 endl done 20900 20901#@cli o3d : eq. to 'opacity3d'. : (+) 20902 20903#@cli opacity3d : _opacity : (+) 20904#@cli : Set opacity of selected 3D objects. 20905#@cli : (eq. to 'o3d'). 20906#@cli : Default value: 'opacity=1'. 20907#@cli : $ torus3d 100,10 double3d 0 repeat 7 +rotate3d[-1] 1,0,0,20 opacity3d[-1] {u} done add3d 20908 20909#@cli parametric3d : _x(a,b),_y(a,b),_z(a,b),_amin,_amax,_bmin,_bmax,_res_a>0,_res_b>0,_res_x>0,_res_y>0,_res_z>0,\ 20910# _smoothness>=0,_isovalue>=0 20911#@cli : Input 3D object from specified parametric surface `(a,b) ⟶ (x(a,b),y(a,b),z(a,b))`. 20912#@cli : Default values: 'x=(2+cos(b))*sin(a)', 'y=(2+cos(b))*cos(a)', 'c=sin(b)', 'amin=-pi', 'amax=pi', \ 20913# 'bmin=-pi', 'bmax=pi', \ 20914# 'res_a=512', 'res_b=res_a', 'res_x=64', 'res_y=res_x', 'res_z=res_y', 'smoothness=2%' and 'isovalue=10%'. 20915#@cli : $ parametric3d , 20916+parametric3d : skip "${1=(2+cos(b))*sin(a)}","${2=(2+cos(b))*cos(a)}","${3=sin(b)}" 20917 skip ${4={-pi}},${5={pi}},${6={-pi}},${7={pi}} 20918 check "${8=512}>0 && ${9=$8}>0 && ${10=64}>0 && ${11=$10}>0 && ${12=$11}>0 && \ 20919 ${13=2%}>=0 && ${14=10%}>=0" 20920 e[^-1] "Input 3D object from parametric surface ($1,$2,$3)." 20921 # Compute (x(a,b),y(a,b),z(a,b)) and normalize it. 20922 ($4,$5;$4,$5^$6,$6;$7,$7) r. $8,$9,1,2,3 channels. 0,2 20923 f. "a=i(x,y,0,0);b=i(x,y,0,1);if(c==0,$1,if(c==1,$2,$3))" 20924 sh. 0 xmin={im} xmax={iM} n. 16,{$10-17} rm. 20925 sh. 1 ymin={im} ymax={iM} n. 16,{$11-17} rm. 20926 sh. 2 zmin={im} zmax={iM} n. 16,{$12-17} rm. 20927 r. {w*h},3,1,1,-1 20928 20929 # Extract 3D surface. 20930 pointcloud. 1 r. $10,$11,$12,1,0 b. $13,0 20931 isosurface3d. $14 20932 c3d. n3d. *3d. {$xmax-$xmin},{$ymax-$ymin},{$zmax-$zmin} nm. [3D\ parametric] 20933 20934#@cli pca_patch3d : _patch_size>0,_M>0,_N>0,_normalize_input={ 0 | 1 },_normalize_output={ 0 | 1 },_lambda_xy 20935#@cli : Get 3D patch-pca representation of selected images. 20936#@cli : The 3D patch-pca is estimated from M patches on the input image, and displayed as a cloud of N 3D points. 20937#@cli : Default values: 'patch_size=7', 'M=1000', 'N=3000', 'normalize_input=1', 'normalize_output=0', \ 20938# and 'lambda_xy=0'. 20939#@cli : $ image.jpg pca_patch3d 7 20940pca_patch3d : check "isint(${1=7}) && $1>0 && isint(${2=1000}) && $2>0 && isint(${3=3000}) && $3>0" 20941 skip ${4=1},${5=0},${6=0} 20942 e[^-1] "Get 3D patch-pca representation"${arg\ 1+($!>1),s,""}" of image$?, from $2 $1x$1 input patches, 20943 with $3 output patches, input normalization "${arg\ 1+!$4,enabled,disabled}", output normalization "\ 20944 ${arg\ 1+!$5,enabled,disabled}" and lambda_xy $6." 20945 P1={int($1/2)} # Backward half-patch size. 20946 P2={$1-$P1-1} # Forward half-patch size. 20947 20948 n 0,255 round 1 20949 repeat $! l[$>] nm={0,n} 20950 s={s} 20951 20952 # Pick set of M random located patches. 20953 1,$2 rand. 0,{0,w-1} +rand. 0,{0,h-1} +f. 0 a[-3--1] x round. 1 +patches[0] $1,$1,1,{^} y[2--1] a[2--1] x 20954 z[1] 0,1 transpose[1] *[1] $6 a[1,2] y s[^0] x 20955 20956 # Normalize patch coordinates by using average and standard deviation. 20957 ++[^0] /. $2 -[1--2] . rm. 20958 a[^0] x 20959 if $4 l. s y / 'sqrt(1e-8+iv)' a y endl fi 20960 20961 # Do PCA for dimension reduction. 20962 +transpose. m*[-2,-1] 20963 eigen. rows.. 0,2 columns. 0,2 transpose. 20964 if $5 sqrt.. /.. {-2,iM} ri.. . /. .. fi 20965 rm.. 20966 20967 # Pick set of N random located patches. 20968 repeat $3 20969 x={round(u({0,w}))} 20970 y={round(u({0,h}))} 20971 ({$6*$x};{$6*$y}) 20972 +z[0] {$x-$P1},{$y-$P1},{$x+$P2},{$y+$P2},1 20973 y. a[-2,-1] y 20974 done 20975 20976 # Generate 3D representation of the projected patch set. 20977 +a[2--1] x m*[1,-1] transpose[1] # Vertex coordinates. 20978 rows[2--1] 2,100% # Colors 20979 if $s!=3 20980 r[2--1] $1,$1,1,{min(3,$s)},-1 20981 r[2--1] $1,$1,1,3,{if($s!=1,0,1)} 20982 y[2--1] 20983 fi 20984 i[2--2] (-128;$1;$1;3) a[2--1] y 20985 rm[0] # Remove input image (now useless). 20986 i[0] ('CImg3d') # Header. 20987 i[1] ($3;$3) # Geometry. 20988 i[3] 2,$3,1,1,if(x==0,1,y) # Primitives. 20989 1,$3,1,1,1 # Opacities. 20990 y a[-6--1] y # Merge as a 3D object. 20991 20992 nm $nm endl done 20993 20994#@cli plane3d : _size_x,_size_y,_nb_subdivisions_x>0,_nb_subdisivions_y>0 20995#@cli : Input 3D plane at (0,0,0), with specified geometry. 20996#@cli : Default values: 'size_x=1', 'size_y=size_x' and 'nb_subdivisions_x=nb_subdivisions_y=24'. 20997#@cli : $ plane3d 50,30 +primitives3d 1 color3d[-2] ${-rgb} 20998+plane3d : check "${3=24}>0 && ${4=24}>0" skip ${1=1},${2=$1} 20999 e[^-1] "Input 3D plane, with size (${1,2}) and subdivisions (${3,4})." 21000 {$3+1},{$4+1} elevation3d. 0 *3d. {$1/$3},{$2/$4} col3d. 200 nm. [3D\ plane] 21001 21002#@cli point3d : x0,y0,z0 21003#@cli : Input 3D point at specified coordinates. 21004#@cli : $ repeat 1000 a={$>*pi/500} point3d {cos(3*$a)},{sin(2*$a)},0 color3d[-1] ${-rgb} done add3d 21005+point3d : 21006 e[^-1] "Input 3D point ($1,$2,$3)." 21007 1,17,1,1,67.5,73.5,109.5,103.5,51.5,100.5,1,1,${1-3},1,0,200,200,200,1 nm. [3D\ point] 21008 21009#@cli pointcloud3d 21010#@cli : Convert selected planar or volumetric images to 3D point clouds. 21011#@cli : $ image.jpg luminance resize2dy 100 threshold 50% mul 255 pointcloud3d color3d[-1] 255,255,255 21012pointcloud3d : 21013 e[^-1] "Convert image$? to 3D point cloud." 21014 repeat $! l[$>] nm={0,n} 21015 s z repeat $! l[$>] 21016 +norm !=. 0 21017 i.. (1,{w};1,{w}^1,1;{h},{h}) r.. .,.,1,2,3 *[-2,-1] round. permute. cxyz 21018 l. s -,0 a y is_points=$! endl 21019 if $is_points 21020 -. 1 r. 2,{h/2},1,1,-1 permute. cyzx +warp.. .,0,0 rm... 21021 permute.. cyzx i.. 1,{h},1,1,$> a[-3,-2] x # Coordinates. 21022 i... ('CImg3d') i... ({h},{h}) # Header and size. 21023 i.. 1,{h},1,1,1 i.. 1,{h},1,1,y a[-3,-2] x # Primitives. 21024 permute. cyzx # Colors. 21025 if w==1 r. 3,{h},1,1 21026 elif w>3 i.. 4,{h},1,1,-128,1,1,{w} a[-2,-1] x 21027 else r. 3,{h},1,1,0 21028 fi 21029 1,{h},1,1,1 # Opacities. 21030 y[-6--1] a[-6--1] y 21031 else rm empty3d 21032 fi 21033 endl done 21034 +3d 21035 nm $nm endl done 21036 21037#@cli pose3d : p1,...,p12 21038#@cli : Apply 3D pose matrix to selected 3D objects. 21039#@cli : $ torus3d 100,20 pose3d 0.152437,1.20666,-0.546366,0,-0.535962,0.559129,1.08531,0,1.21132,0.0955431,\ 21040# 0.548966,0,0,0,-206,1 snapshot3d 400 21041pose3d : 21042 e[^-1] "Apply 3D pose matrix [ $1,$2,$3,$4; $5,$6,$7,$8; $9,$10,$11,$12 ] to 3D object$?." 21043 repeat $! l[$>] if ${-_is_3d} 21044 s3d r[2] 3,{2,h/3},1,1,-1 i[3] 1,{2,h},1,1,1 a[2,3] x 21045 i[3] ($1,$5,$9;$2,$6,$10;$3,$7,$11;$4,$8,$12) m*[2,3] 21046 r[2] 1,{2,3*h},1,1,-1 a y 21047 else error "Command '$0': Image ["{$!-$>-1}"] does not represent a 3D object." 21048 fi endl done 21049 21050#@cli p3d : eq. to 'primitives3d'. 21051p3d : check "isint($1) && $1>=0 && $1<=2" 21052 _primitives3d $* 21053 21054#@cli primitives3d : mode 21055#@cli : Convert primitives of selected 3D objects. 21056#@cli : (eq. to 'p3d').\n 21057#@cli : 'mode' can be { 0=points | 1=outlines | 2=non-textured }. 21058#@cli : $ sphere3d 30 primitives3d 1 torus3d 50,10 color3d[-1] ${-rgb} add3d 21059primitives3d : check "isint($1) && $1>=0 && $1<=2" 21060 _$0 $* 21061 21062_primitives3d : 21063 e[0--3] "Convert primitives of 3D object$? to "${"arg 1+$1,points,outlines,non-textured"}"." 21064 repeat $! l[$>] 21065 s3d 1,64 .x2 21066 eval " 21067 const mode = $1; 21068 21069 # Read a RGBA color from the current primitive material. 21070 get_RGBA(tx,ty,goto_next) = ( 21071 R = i[#4,pc]; 21072 R!=-128?( # RGB color 21073 G = i[#4,pc+1]; 21074 B = i[#4,pc+2]; 21075 goto_next?(pc+=3); 21076 ):( # Texture 21077 W = i[#4,pc+1]; H = i[#4,pc+2]; S = i[#4,pc+3]; WH = W*H; 21078 WH?( # Non-shared texture 21079 off = pc + (ty%H)*W + (tx%W) + 4; 21080 goto_next?(pc+=WH*S + 4); 21081 ):( # Shared texture 21082 off = pcol[W]; 21083 i[#4,off]==-128?( 21084 ++off; 21085 W = i[#4,off++]; H = i[#4,off++]; S = i[#4,off++]; WH = W*H; 21086 off += (ty%H)*W + (tx%W); 21087 ):(WH=1); 21088 goto_next?(pc+=4); 21089 ); 21090 R = i[#4,off]; 21091 S==1?(G = B = R):( 21092 G = i[#4,off + WH]; 21093 S==2?(B = 0):( 21094 B = i[#4,off + 2*WH]; 21095 ); 21096 ); 21097 ); 21098 21099 A = i[#5,po]; 21100 A!=-128?( # Scalar 21101 goto_next?(po+=1); 21102 ):( # Texture 21103 W = i[#5,po+1]; H = i[#5,po+2]; S = i[#5,po+3]; WH = W*H; 21104 WH?( # Non-shared texture 21105 off = po + (ty%H)*W + (tx%W) + 4; 21106 goto_next?(po+=WH*S + 4); 21107 ):( # Shared texture 21108 off = popa[W]; 21109 i[#5,off]==-128?( 21110 ++off; 21111 W = i[#5,off++]; H = i[#5,off++]; S = i[#5,off++]; WH = W*H; 21112 off += (ty%H)*W + (tx%W); 21113 ); 21114 goto_next?(po+=4); 21115 ); 21116 A = i[#5,off]; 21117 ); 21118 ); 21119 21120 # Copy material of current primitives 'nb' times. 21121 copy_material(nb) = ( 21122 R = i[#4,pc++]; G = i[#4,pc++]; B = i[#4,pc++]; 21123 R!=-128?( # RGB color 21124 unref(data); data = [ R,G,B ]; 21125 repeat (nb, copy(i[#-2,qc],data,3); qc+=3); 21126 ):( 21127 W = G; H = B; S = i[#4,pc++]; WHS = W*H*S; 21128 WHS?( # Non-shared texture 21129 qc + WHS + 4*nb>=h(#-2)?resize(#-2,1,int(1.5*qc + WHS + 4*nb),1,1,0,0); 21130 copy(i[#-2,qc],i[#4,pc-4],WHS+4); 21131 pc+=WHS; qc+=WHS+4; 21132 unref(data); data = [-128,nq,0,0]; 21133 for (k = 1, k<nb, ++k, copy(i[#-2,qc],data,4); qc+=4); 21134 ):( # Shared texture 21135 unref(data); data = [-128,pref[W],0,0]; 21136 repeat (nb, copy(i[#-2,qc],data,4); qc+=4); 21137 ); 21138 ); 21139 21140 A = i[#5,po++]; 21141 A!=-128?( # Opacity value 21142 repeat (nb, i[#-1,qo++] = A); 21143 ):( # Texture 21144 W = i[#5,po++]; H = i[#5,po++]; S = i[#5,po++]; WHS = W*H*S; 21145 WHS?( # Non-shared texture 21146 qo + WHS + 4*nb>=h(#-1)?resize(#-1,1,int(1.5*qo + WHS + 4*nb),1,1,0,0); 21147 copy(i[#-1,qo],i[#5,po-4],WHS+4); 21148 po+=WHS; qo+=WHS+4; 21149 unref(data); data = [-128,nq,0,0]; 21150 for (k = 1, k<nb, ++k, copy(i[#-1,qo],data,4); qo+=4); 21151 ):( # Shared texture 21152 unref(data); data = [ -128,pref[W],0,0 ]; 21153 repeat (nb, copy(i[#-1,qo],data,4); qo+=4); 21154 ); 21155 ); 21156 ); 21157 21158 # Add a new colored point primitive. 21159 add_point(ind,R,G,B,A) = ( 21160 copy(i[#-3,qp],[1,ind],2); qp+=2; 21161 copy(i[#-2,qc],[R,G,B],3); qc+=3; 21162 i[#-1,qo++] = A; 21163 ++nq; 21164 ); 21165 21166 # Add a new colored segment primitive. 21167 add_segment(ind0,ind1,R,G,B,A) = ( 21168 copy(i[#-3,qp],[2,ind0,ind1],3); qp+=3; 21169 copy(i[#-2,qc],[R,G,B],3); qc+=3; 21170 i[#-1,qo++] = A; 21171 ++nq; 21172 ); 21173 21174 pcol = popa = pref = vector"{i[#1,1]}"(); 21175 for (pp = pc = po = qp = qc = qo = np = nq = 0, pp<h#3, ++np, 21176 qp + 28>=h(#-3)?resize(#-3,1,int(1.5*qp + 28),1,1,0,0); 21177 qc + 16>=h(#-2)?resize(#-2,1,int(1.5*qc + 16),1,1,0,0); 21178 qo + 4>=h(#-1)?resize(#-1,1,int(1.5*qo + 4),1,1,0,0); 21179 N = i[#3,pp++]; 21180 pcol[np] = pc; 21181 popa[np] = po; 21182 pref[np] = nq; 21183 21184 N==1?( # Colored point 21185 v0 = i[#3,pp++]; 21186 get_RGBA(0,0,1); 21187 add_point(v0,R,G,B,A); 21188 21189 ):N==2?( # Colored segment 21190 v0 = i[#3,pp++]; v1 = i[#3,pp++]; 21191 get_RGBA(0,0,1); 21192 mode==0?( 21193 add_point(v0,R,G,B,A); 21194 add_point(v1,R,G,B,A); 21195 ):( 21196 add_segment(v0,v1,R,G,B,A); 21197 ); 21198 21199 ):N==3?( # Colored triangle 21200 v0 = i[#3,pp++]; v1 = i[#3,pp++]; v2 = i[#3,pp++]; 21201 get_RGBA(0,0,1); 21202 mode==0?( 21203 add_point(v0,R,G,B,A); 21204 add_point(v1,R,G,B,A); 21205 add_point(v2,R,G,B,A); 21206 ):mode==1?( 21207 add_segment(v0,v1,R,G,B,A); 21208 add_segment(v1,v2,R,G,B,A); 21209 add_segment(v2,v0,R,G,B,A); 21210 ):( 21211 copy(i[#-3,qp],i[#3,pp-4],4); qp+=4; 21212 copy(i[#-2,qc],i[#4,pc-3],3); qc+=3; 21213 i[#-1,qo++] = A; 21214 ++nq; 21215 ); 21216 21217 ):N==4?( # Colored quadrangle 21218 v0 = i[#3,pp++]; v1 = i[#3,pp++]; v2 = i[#3,pp++]; v3 = i[#3,pp++]; 21219 get_RGBA(0,0,1); 21220 mode==0?( 21221 add_point(v0,R,G,B,A); 21222 add_point(v1,R,G,B,A); 21223 add_point(v2,R,G,B,A); 21224 add_point(v3,R,G,B,A); 21225 ):mode==1?( 21226 add_segment(v0,v1,R,G,B,A); 21227 add_segment(v1,v2,R,G,B,A); 21228 add_segment(v2,v3,R,G,B,A); 21229 add_segment(v3,v0,R,G,B,A); 21230 ):( 21231 copy(i[#-3,qp],i[#3,pp-5],5); qp+=5; 21232 copy(i[#-2,qc],i[#4,pc-3],3); qc+=3; 21233 i[#-1,qo++] = A; 21234 ++nq; 21235 ); 21236 21237 ):N==5?( # Colored sphere 21238 v0 = i[#3,pp++]; v1 = i[#3,pp++]; i[#3,pp++] = (mode==1); v2 = i[#3,pp++]; v3 = i[#3,pp++]; 21239 get_RGBA(0,0,1); 21240 mode==0?( 21241 x0 = i[#2,3*v0]; y0 = i[#2,3*v0+1]; z0 = i[#2,3*v0+2]; 21242 x1 = i[#2,3*v1]; y1 = i[#2,3*v1+1]; z1 = i[#2,3*v1+2]; 21243 copy(i[#2,3*v0],([ x0,y0,z0 ] + [ x1,y1,z1 ])/2,3); 21244 add_point(v0,R,G,B,A); 21245 ):( 21246 copy(i[#-3,qp],i[#3,pp-6],6); qp+=6; 21247 copy(i[#-2,qc],i[#4,pc-3],3); qc+=3; 21248 i[#-1,qo++] = A; 21249 ++nq; 21250 ); 21251 21252 ):N==6?( # Textured segment 21253 v0 = i[#3,pp++]; v1 = i[#3,pp++]; 21254 tx0 = i[#3,pp++]; ty0 = i[#3,pp++]; tx1 = i[#3,pp++]; ty1 = i[#3,pp++]; 21255 mode==0?( 21256 get_RGBA(tx0,ty0,0); add_point(v0,R,G,B,A); 21257 get_RGBA(tx1,ty1,1); add_point(v1,R,G,B,A); 21258 ):mode==1?( 21259 copy(i[#-3,qp],i[#3,pp-7],7); qp+=7; 21260 copy_material(1); 21261 ++nq; 21262 ):( 21263 get_RGBA(tx0,ty0,0); R0 = R; G0 = G; B0 = B; A0 = A; 21264 get_RGBA(tx1,ty1,1); (R0+=R)/=2; (G0+=G)/=2; (B0+=B)/=2; (A0+=A)/=2; 21265 add_segment(v0,v1,R0,G0,B0,A0); 21266 ); 21267 21268 ):N==9?( # Textured triangle 21269 v0 = i[#3,pp++]; v1 = i[#3,pp++]; v2 = i[#3,pp++]; 21270 tx0 = i[#3,pp++]; ty0 = i[#3,pp++]; 21271 tx1 = i[#3,pp++]; ty1 = i[#3,pp++]; 21272 tx2 = i[#3,pp++]; ty2 = i[#3,pp++]; 21273 mode==0?( 21274 get_RGBA(tx0,ty0,0); add_point(v0,R,G,B,A); 21275 get_RGBA(tx1,ty1,0); add_point(v1,R,G,B,A); 21276 get_RGBA(tx2,ty2,1); add_point(v2,R,G,B,A); 21277 ):mode==1?( 21278 copy(i[#-3,qp],[ 6,v0,v1,tx0,ty0,tx1,ty1, 21279 6,v1,v2,tx1,ty1,tx2,ty2, 21280 6,v2,v0,tx2,ty2,tx0,ty0 ],21); qp+=21; 21281 copy_material(3); 21282 nq+=3; 21283 ):( 21284 get_RGBA(tx0,ty0,0); R0 = R; G0 = G; B0 = B; A0 = A; 21285 get_RGBA(tx1,ty1,0); R0+=R; G0+=G; B0+=B; A0+=A; 21286 get_RGBA(tx2,ty2,2); (R0+=R)/=3; (G0+=G)/=3; (B0+=B)/=3; (A0+=A)/=3; 21287 copy(i[#-3,qp],[ 3,v0,v1,v2 ],4); qp+=4; 21288 copy(i[#-2,qc],[ R,G,B ],3); qc+=3; 21289 i[#-1,qo++] = A; 21290 ++nq; 21291 ); 21292 21293 ):N==12?( # Textured quadrangle 21294 v0 = i[#3,pp++]; v1 = i[#3,pp++]; v2 = i[#3,pp++]; v3 = i[#3,pp++]; 21295 tx0 = i[#3,pp++]; ty0 = i[#3,pp++]; 21296 tx1 = i[#3,pp++]; ty1 = i[#3,pp++]; 21297 tx2 = i[#3,pp++]; ty2 = i[#3,pp++]; 21298 tx3 = i[#3,pp++]; ty3 = i[#3,pp++]; 21299 mode==0?( 21300 get_RGBA(tx0,ty0,0); add_point(v0,R,G,B,A); 21301 get_RGBA(tx1,ty1,0); add_point(v1,R,G,B,A); 21302 get_RGBA(tx2,ty2,0); add_point(v2,R,G,B,A); 21303 get_RGBA(tx3,ty3,1); add_point(v3,R,G,B,A); 21304 ):mode==1?( 21305 copy(i[#-3,qp],[ 6,v0,v1,tx0,ty0,tx1,ty1, 21306 6,v1,v2,tx1,ty1,tx2,ty2, 21307 6,v2,v3,tx2,ty2,tx3,ty3, 21308 6,v3,v0,tx3,ty3,tx0,ty0 ],28); qp+=28; 21309 copy_material(4); 21310 nq+=4; 21311 ):( 21312 get_RGBA(tx0,ty0,0); R0 = R; G0 = G; B0 = B; A0 = A; 21313 get_RGBA(tx1,ty1,0); R0+=R; G0+=G; B0+=B; A0+=A; 21314 get_RGBA(tx2,ty2,0); R0+=R; G0+=G; B0+=B; A0+=A; 21315 get_RGBA(tx3,ty3,2); (R0+=R)/=4; (G0+=G)/=4; (B0+=B)/=4; (A0+=A)/=4; 21316 copy(i[#-3,qp],[ 4,v0,v1,v2,v3 ],5); qp+=5; 21317 copy(i[#-2,qc],[ R,G,B ],3); qc+=3; 21318 i[#-1,qo++] = A; 21319 ++nq; 21320 ); 21321 ); 21322 ); 21323 resize(#-3,1,qp,1,1,0,0); 21324 resize(#-2,1,qc,1,1,0,0); 21325 resize(#-1,1,qo,1,1,0,0); 21326 i[#1,1] = nq" 21327 21328 rm[3-5] a y 21329 endl done 21330 21331#@cli projections3d : _x[%],_y[%],_z[%],_is_bounding_box={ 0 | 1 } 21332#@cli : Generate 3D xy,xz,yz projection planes from specified volumetric images. 21333projections3d : skip ${1=50%},${2=50%},${3=50%},${4=1} 21334 e[^-1] "Generate 3D xy,xz,yz projection planes from image$?." 21335 n 0,255 repeat $! l[$>] 21336 w={w} h={h} d={d} 21337 x={if(${is_percent\ $1},$1*w,$1)} 21338 y={if(${is_percent\ $2},$2*h,$2)} 21339 z={if(${is_percent\ $3},$3*d,$3)} 21340 +rows $2,$2 r. {w},{d},1,100%,-1 21341 +columns.. $1,$1 permute. zyxc 21342 slices... $3,$3 r[-3--1] 100%,100%,1,3 21343 imageplane3d[-3--1] 21344 r3d. 0,1,0,-90 r3d.. 1,0,0,90 21345 +3d... 0,0,$z +3d.. 0,$y,0 +3d. $x,0,0 21346 +3d[-3--1] o3d. 0.8 21347 if $4 box3d $w,$h,$d p3d. 1 o3d. 0.4 +3d[-2,-1] fi 21348 endl done 21349 21350#@cli pyramid3d : width,height 21351#@cli : Input 3D pyramid at (0,0,0), with specified geometry. 21352#@cli : $ pyramid3d 100,-100 +primitives3d 1 color3d[-2] ${-rgb} 21353+pyramid3d : 21354 e[^-1] "Input new 3D pyramid, with width $1 and height $2." 21355 (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 21356 5;5;\ # Number of vertices and primitives. 21357 {-$1/2};{-$1/2};{-$2/2};\ # Vertex coordinates. 21358 {$1/2};{-$1/2};{-$2/2};\ 21359 {$1/2};{$1/2};{-$2/2};\ 21360 {-$1/2};{$1/2};{-$2/2};\ 21361 0;0;{$2/2};\ 21362 4;0;3;2;1;\ # Primitives description. 21363 3;0;4;3;\ 21364 3;1;4;0;\ 21365 3;2;4;1;\ 21366 3;3;4;2) 21367 1,15,1,1,200 1,5,1,1,1 a[-3--1] y nm. [3D\ pyramid] 21368 21369#@cli quadrangle3d : x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3 21370#@cli : Input 3D quadrangle at specified coordinates. 21371#@cli : $ quadrangle3d -10,-10,10,10,-10,10,10,10,10,-10,10,10 repeat 10 +rotate3d[-1] 0,1,0,30 \ 21372# color3d[-1] ${-rgb},0.6 done add3d mode3d 2 21373+quadrangle3d : 21374 e[^-1] "Input 3D quadrangle ($1,$2,$3)-($4,$5,$6)-($7,$8,$9)-($10,$11,$12)." 21375 1,29,1,1,67.5,73.5,109.5,103.5,51.5,100.5,4,1,${1-12},4,0,1,2,3,200,200,200,1 nm. [3D\ quadrangle] 21376 21377#@cli random3d : nb_points>=0 21378#@cli : Input random 3D point cloud in [0,1]^3. 21379#@cli : $ random3d 100 circles3d 0.1 opacity3d 0.5 21380+random3d : check "$1>=0" 21381 e[^-1] "Input random 3D point cloud, with $1 points." 21382 if $1<0.5 empty3d 21383 else l[] 21384 N={round($1)} 21385 ({'CImg3d'},$N,$N) 21386 3,$N rand. 0,1 21387 1,$N,1,1,1 1,$N,1,1,y a[-2,-1] x 21388 3,$N,1,1,200 1,$N,1,1,1 21389 y a y 21390 endl fi 21391 nm. [3D\ random\ pointcloud] 21392 21393#@cli rv3d : eq. to 'reverse3d'. : (+) 21394 21395#@cli reverse3d : (+) 21396#@cli : Reverse primitive orientations of selected 3D objects. 21397#@cli : (eq. to 'rv3d'). 21398#@cli : $ torus3d 100,40 double3d 0 +reverse3d 21399 21400#@cli r3d : eq. to 'rotate3d'. : (+) 21401 21402#@cli rotate3d : u,v,w,angle : (+) 21403#@cli : Rotate selected 3D objects around specified axis with specified angle (in deg.). 21404#@cli : (eq. to 'r3d'). 21405#@cli : $ torus3d 100,10 double3d 0 repeat 7 +rotate3d[-1] 1,0,0,20 done add3d 21406 21407#@cli rotation3d : u,v,w,angle 21408#@cli : Input 3x3 rotation matrix with specified axis and angle (in deg). 21409#@cli : $ rotation3d 1,0,0,0 rotation3d 1,0,0,90 rotation3d 1,0,0,180 21410rotation3d : 21411 e[^-1] "Input 3D rotation matrix around axis ($1,$2,$3) with angle $4 deg." 21412 3,3,1,1,{"rot(${1-4}°)"} nm. [3D\ rotation] 21413 21414#@cli sierpinski3d : _recursion_level>=0,_width,_height 21415#@cli : Input 3d Sierpinski pyramid. 21416#@cli : $ sierpinski3d 3,100,-100 +primitives3d 1 color3d[-2] ${-rgb} 21417+sierpinski3d : check ${1=4}>=0 skip ${2=1},${3=1} 21418-e[^-1] "Input 3D Sierpinski pyramid of degree $1, with width $2 and height $3." 21419 l[] 21420 _sierpinski3d {-$2/2},{-$2/2},{-$3/2},{$2/2},{-$2/2},{-$3/2},\ 21421 {$2/2},{$2/2},{-$3/2},{-$2/2},{$2/2},{-$3/2},\ 21422 0,0,{$3/2},$1 21423 +3d endl 21424 nm. [3D\ sierpinski] 21425 21426_sierpinski3d : 21427 if $16<=0 21428 (67.5;73.5;109.5;103.5;51.5;100.5;\ 21429 5;5;\ 21430 $1;$2;$3;\ 21431 $4;$5;$6;\ 21432 $7;$8;$9;\ 21433 $10;$11;$12;\ 21434 $13;$14;$15;\ 21435 4;0;3;2;1;\ 21436 3;0;4;3;\ 21437 3;1;4;0;\ 21438 3;2;4;1;\ 21439 3;3;4;2) 21440 1,15,1,1,200 1,5,1,1,1 a[-3--1] y 21441 return fi 21442 _sierpinski3d $1,$2,$3,\ 21443 {($1+$4)/2},{($2+$5)/2},{($3+$6)/2},\ 21444 {($1+$4+$7+$10)/4},{($2+$5+$8+$11)/4},{($3+$6+$9+$12)/4},\ 21445 {($1+$10)/2},{($2+$11)/2},{($3+$12)/2},\ 21446 {($1+$13)/2},{($2+$14)/2},{($3+$15)/2},\ 21447 {$16-1} 21448 _sierpinski3d {($1+$4)/2},{($2+$5)/2},{($3+$6)/2},\ 21449 $4,$5,$6,\ 21450 {($4+$7)/2},{($5+$8)/2},{($6+$9)/2},\ 21451 {($1+$4+$7+$10)/4},{($2+$5+$8+$11)/4},{($3+$6+$9+$12)/4},\ 21452 {($4+$13)/2},{($5+$14)/2},{($6+$15)/2},\ 21453 {$16-1} 21454 _sierpinski3d {($1+$4+$7+$10)/4},{($2+$5+$8+$11)/4},{($3+$6+$9+$12)/4},\ 21455 {($4+$7)/2},{($5+$8)/2},{($6+$9)/2},\ 21456 $7,$8,$9,\ 21457 {($7+$10)/2},{($8+$11)/2},{($9+$12)/2},\ 21458 {($7+$13)/2},{($8+$14)/2},{($9+$15)/2},\ 21459 {$16-1} 21460 _sierpinski3d {($1+$10)/2},{($2+$11)/2},{($3+$12)/2},\ 21461 {($1+$4+$7+$10)/4},{($2+$5+$8+$11)/4},{($3+$6+$9+$12)/4},\ 21462 {($7+$10)/2},{($8+$11)/2},{($9+$12)/2},\ 21463 $10,$11,$12,\ 21464 {($10+$13)/2},{($11+$14)/2},{($12+$15)/2},\ 21465 {$16-1} 21466 _sierpinski3d {($1+$13)/2},{($2+$14)/2},{($3+$15)/2},\ 21467 {($4+$13)/2},{($5+$14)/2},{($6+$15)/2},\ 21468 {($7+$13)/2},{($8+$14)/2},{($9+$15)/2},\ 21469 {($10+$13)/2},{($11+$14)/2},{($12+$15)/2},\ 21470 $13,$14,$15,\ 21471 {$16-1} 21472 21473#@cli size3d 21474#@cli : Return bounding box size of the last selected 3D object. 21475size3d : 21476 +rows. 8,{8+3*i[6]} r. 3,{h/3},1,1,-1 s. x,3 21477 u {-3,iM-im},{-2,iM-im},{iM-im} 21478 rm[-3--1] 21479 21480#@cli skeleton3d : _metric,_frame_type={ 0=squares | 1=diamonds | 2=circles | 3=auto },_skeleton_opacity,\ 21481# _frame_opacity,_is_frame_wireframe={ 0 | 1 } 21482#@cli : Build 3D skeletal structure object from 2d binary shapes located in selected images. 21483#@cli : 'metric' can be { 0=chebyshev | 1=manhattan | 2=euclidean }. 21484#@cli : Default values: 'metric=2', 'bones_type=3', 'skeleton_opacity=1' and 'frame_opacity=0.1'. 21485#@cli : $ shape_cupid 480 +skeleton3d , 21486skeleton3d : check "isint(${1=2}) && $1>=0 && $1<=2 && isint(${2=3}) && $2>=0 && $2<=3" skip ${3=1},${4=0.1},${5=1} 21487 e[^-1] "Build 3D skeletal structure object from image$?, with "${arg\ 1+$1,chebyshev,manhattan,euclidean}" metric, "\ 21488 ${arg\ 1+$2,squares,diamonds,circles,auto}" bones, skeleton opacity $3 and frame opacity $4 ." 21489 repeat $! l[$>] channels 0 21490 21491 # Construct skeleton representation. 21492 +distance 0,$1 21493 +f. "(i>j(-1)&&i>j(1)) || (i>j(0,-1)&&i>j(0,1)) || (i>j(-1,-1)&&i>j(1,1)) || (i>j(-1,1)&&i>j(1,-1))" 21494 if $3 +slices. -1,0 isosurface3d. 0.5 o3d. $3 col3d. 255,0,0 fi 21495 *[0-2] pointcloud3d[0] 21496 21497 # Construct bones from skeleton. 21498 if $4 l[0] s3d 0 21499 n={1,@0} 21500 if $n 21501 r[2] 3,$n,1,1,-1 r[3] 2,$n,1,1,-1 r[4] 3,$n,1,1,-1 21502 21503 if $2==0" || "($2==3" && "$1==0) # Frame with squares. 21504 =[1] {4*$n} 21505 i[3] [2]x3 +z.. 0,1 z. 0,2 -[2] . +[4] . 21506 s. x *.. -1 a[-3--1] x +[3] . -[5,-1] a[2-5] x 21507 rm[3] 1,$n,1,1,4 +f. 4*y ++. 1 ++. 1 ++. 1 rv[-3,-1] a[-5--1] x mv. 3 21508 21509 elif $2==1" || "($2==3" && "$1==1) # Frame with diamonds. 21510 =[1] {4*$n} 21511 i[3] [2]x3 +z.. 0,0 z. 0,2 -[2] . +[4] . 21512 shift. 1,0 -[3] . +[5,-1] a[2-5] x 21513 rm[3] 1,$n,1,1,4 +f. 4*y ++. 1 ++. 1 ++. 1 rv[-3,-1] a[-5--1] x mv. 3 21514 21515 elif $2==2" || "($2==3" && "$1==2) # Frame with circles. 21516 =[1] {2*$n} 21517 +z[4] 0,0 z. 0,2 ++[2,-1] -[2,-2] a[2,-1] x 21518 rm[3] 1,$n,1,1,5 +f. 2*y ++. 1 3,100% a[-4--1] x mv. 3 21519 fi 21520 y a y o3d $4 if $5 p3d 1 fi col3d 200 21521 else rm empty3d fi 21522 endl else rm[0] fi 21523 +3d 21524 endl done 21525 21526#@cli snapshot3d : _size>0,_zoom>=0,_backgroundR,_backgroundG,_backgroundB,_backgroundA : [background_image],zoom>=0 21527#@cli : Take 2d snapshots of selected 3D objects. 21528#@cli : Set 'zoom' to 0 to disable object auto-scaling. 21529#@cli : Default values: 'size=512', 'zoom=1' and '[background_image]=(default)'. 21530#@cli : $ torus3d 100,20 rotate3d 1,1,0,60 snapshot3d 400,1.2,128,64,32 21531#@cli : $ torus3d 100,20 rotate3d 1,1,0,60 sample ? +snapshot3d[0] [1],1.2 21532snapshot3d : check "${2=1}>=0" skip ${1=512},${3=""} 21533 if ${"is_image_arg $1"} # Background image specified. 21534 e[0--3] "Take $1x$1 snapshot$? of 3D object$?, with zoom factor $2 and background image $3." 21535 pass$1 0 to_color. 21536 elif isnum($3) # Background color specified. 21537 e[0--3] "Take $1x$1 snapshot$? of 3D object$?, with zoom factor $2 and background color ${3--1}." 21538 (${3--1}) y. c r. $1,$1 to_color. 21539 else # Default background color. 21540 e[0--3] "Take $1x$1 snapshot$? of 3D object$?, with zoom factor $2 and default background." 21541 1,2,1,3,32,64,32,116,64,96 r. $1,$1,1,3,3 21542 fi 21543 repeat $!-1 . l[$>,-1] 21544 if $2!=0 c3d[0] n3d[0] *3d[0] {3*min(w,h)*$2/4} fi 21545 if s>3 # RGBA rendering. 21546 100%,100%,1,3,-1 j3d. [0],50%,50%,0,1 21547 to_rgba. replace_color. 0,0,-1,-1,-1,255,0,0,0,0 blend[-2,-1] alpha 21548 else # RGB rendering. 21549 j3d[1] [0],50%,50%,0,1 21550 fi 21551 nm[1] {-2,n} rm[0] 21552 endl done rm. 21553 21554#@cli sl3d : eq. to 'specl3d'. : (+) 21555 21556#@cli specl3d : value>=0 : (+) 21557#@cli : Set lightness of 3D specular light. 21558#@cli : (eq. to 'sl3d'). 21559#@cli : Default value: 'value=0.15'. 21560#@cli : $ (0,0.3,0.6,0.9,1.2) repeat w torus3d 100,30 rotate3d[-1] 1,1,0,60 color3d[-1] 255,0,0 specl3d {0,@$>} \ 21561# snapshot3d[-1] 400 done remove[0] 21562 21563#@cli ss3d : eq. to 'specs3d'. : (+) 21564 21565#@cli specs3d : value>=0 : (+) 21566#@cli : Set shininess of 3D specular light. 21567#@cli : (eq. to 'ss3d'). 21568#@cli : Default value: 'value=0.8'. 21569#@cli : $ (0,0.3,0.6,0.9,1.2) repeat w torus3d 100,30 rotate3d[-1] 1,1,0,60 color3d[-1] 255,0,0 specs3d {0,@$>} \ 21570# snapshot3d[-1] 400 done remove[0] 21571 21572#@cli sphere3d : radius,_nb_recursions>=0 : (+) 21573#@cli : Input 3D sphere at (0,0,0), with specified geometry. 21574#@cli : Default value: 'nb_recursions=3'. 21575#@cli : $ sphere3d 100 +primitives3d 1 color3d[-2] ${-rgb} 21576 21577#@cli spherical3d : _nb_azimuth>=3,_nb_zenith>=3,_radius_function(phi,theta) 21578#@cli : Input 3D spherical object at (0,0,0), with specified geometry. 21579#@cli : Default values: 'nb_zenith=nb_azimut=64' and 'radius_function="abs(1+0.5*cos(3*phi)*sin(4*theta))"'. 21580#@cli : $ spherical3d 64 +primitives3d 1 21581+spherical3d : check "${1=64}>=3 && ${2=$1}>=3" skip "${3=abs(1+0.5*cos(3*phi)*sin(4*theta))}" 21582 e[^-1] "Input 3D spherical object, with subdivisions ($1,$2) and height function '$3'." 21583 ('CImg3d':y) # Magic number. 21584 n1={round($1)} n2={round($2)} 21585 21586 # Define 3D vertices. 21587 $n1,{$n2-1},1,3,"phi = 2*pi*(x+0.5)/w;\ 21588 theta = -pi/2+pi*(y+0.5)/h;\ 21589 cp = cos(phi);\ 21590 sp = sin(phi);\ 21591 ct = cos(theta);\ 21592 ($3)*if(c==0,ct*cp,if(c==1,ct*sp,sin(theta)))" 21593 r. {w*h},3,1,1,-1 permute. yxzc 21594 i.. (0,0,{phi=0;theta=-pi/2;-$3};0,0,{phi=0;theta=pi/2;$3}) a[-2,-1] y # Add the two poles. 21595 nbv={h} y. 21596 21597 # Define 3D primitives. 21598 $n1,{$n2-2},1,4,"nx=(x+1)%w;ny=(y+1);2+if(c==0,x+y*"$n1",if(c==1,nx+y*"$n1",if(c==2,nx+ny*"$n1",x+ny*"$n1")))" 21599 r. {w*h},4,1,1,-1 permute. yxzc i.. 1,{h},1,1,4 a[-2,-1] x 21600 2,$n1,1,1,3,0 1,$n1,1,1,'y' ++. 1 %. {h} 2,$n1,1,1,3,1 [-3,-2] # Connect the two poles. 21601 +[-5,-4] 2 rv[-5,-4] +[-2,-1] {$nbv-$n1} a[-3--1] x a[-4--2] x 21602 nbp={h+{-2,h}+{-3,h}} 21603 y[-3--1] a[-3--1] y 21604 21605 # Define other object information (properties, colors and opacities). 21606 i... ($nbv;$nbp) 21607 1,{3*$nbp},1,1,200 1,$nbp,1,1,1 a[-2,-1] y 21608 21609 # Append as a 3D object. 21610 a[-5--1] y nm. "[3D spherical surface '$3']" 21611 21612#@cli spline3d : x0[%],y0[%],z0[%],u0[%],v0[%],w0[%],x1[%],y1[%],z1[%],u1[%],v1[%],w1[%],_nb_vertices>=2 21613#@cli : Input 3D spline with specified geometry. 21614#@cli : Default values: 'nb_vertices=128'. 21615#@cli : $ repeat 100 spline3d {u},{u},{u},{u},{u},{u},{u},{u},{u},{u},{u},{u},128 color3d[-1] ${-rgb} done \ 21616# box3d 1 primitives3d[-1] 1 add3d 21617+spline3d : check ${13=128}>=2 21618 e[^-1] "Input new 3D spline from (${1-3}) [${4-6}] to (${7-9}) [${10-12}] with $13 vertices." 21619 ('CImg3d') +. 0.5 # Header. 21620 ($13;{$13-1}) # Nb vertices / primitives. 21621 # Define vertices. 21622 1,$13,1,1,1 (0;1) r. 1,$13,1,1,3 +sqr. +*[-2,-1] a[-4--1] x 21623 +*. '$2,$5,{3*(($8)-($2))-2*($5)-($11)},{($5)+($11)+2*(($2)-($8))}' l. s x + endl 21624 +*.. '$3,$6,{3*(($9)-($3))-2*($6)-($12)},{($6)+($12)+2*(($3)-($9))}' l. s x + endl 21625 *... '$1,$4,{3*(($7)-($1))-2*($4)-($10)},{($4)+($10)+2*(($1)-($7))}' l... s x + endl 21626 a[-3--1] x 21627 1,{$13-1},1,1,2 (0,1;{$13-2},{$13-1}) r. 2,..,1,1,3 round. a[-2,-1] x # Primitives. 21628 1,{3*($13-1)},1,1,200 1,{$13-1},1,1,1 # Colors / opacities. 21629 y[-3,-4,-6] a[-6--1] y 21630 21631#@cli s3d : eq. to 'split3d'. : (+) 21632 21633#@cli split3d : _full_split={ 0 | 1 } : (+) 21634#@cli : Split selected 3D objects into feature vectors : 21635#@cli : * If 'full_split==0', { header, sizes, vertices, primitives, colors, opacities }. 21636#@cli : * If 'full_split==1', { header, sizes, vertices, p0,...,pP, c0,...,cP, o0,...,oP }. 21637#@cli : (eq. to 's3d').\n 21638#@cli : To recreate the 3D object, append all produced images along the y-axis. 21639#@cli : Default value: 'full_split=0'. 21640#@cli : $ box3d 100 +split3d 21641 21642#@cli sprite3d 21643#@cli : Convert selected images as 3D sprites. 21644#@cli : Selected images with alpha channels are managed. 21645#@cli : $ image.jpg sprite3d 21646sprite3d : 21647 e[^-1] "Convert image$? as 3D sprites." 21648 repeat $! l[$>] nm={0,n} 21649 split_opacity 21650 i[0] (67.5;73.5;109.5;103.5;51.5;100.5;1;1;0;0;0;1;0;-128;{w};{h};{0,s}) y[1] 21651 if $!==2 (1) a y 21652 else /. 255 i.. (-128;{w};{h};{s}) y. 21653 fi 21654 a y 21655 nm $nm endl done 21656 21657#@cli sprites3d : [sprite],_sprite_has_alpha_channel={ 0 | 1 } 21658#@cli : Convert selected 3D objects as a sprite cloud. 21659#@cli : Set 'sprite_has_alpha_channel' to 1 to make the last channel of the selected sprite be a transparency mask. 21660#@cli : Default value: 'mask_has_alpha_channel=0'. 21661#@cli : $ torus3d 100,20 image.jpg resize2dy[-1] 64 100%,100% gaussian[-1] 30%,30% *[-1] 255 append[-2,-1] c \ 21662# +sprites3d[0] [1],1 display_rgba[-2] 21663sprites3d : check ${is_image_arg\ $1} skip ${2=0} 21664 e[^-1] "Convert image$? as 3D sprites clouds, using sprite $1 ("${"arg {1+!$2},with,without"}" alpha-channel)." 21665 repeat $! 21666 if !{$>,i(0,7)} continue fi # Do nothing if 3D object is empty. 21667 pass$1 0 21668 if !w empty3d rv[$>,-1] nm[$>] {n} rm. continue fi 21669 l[$>,-1] 21670 s3d[0] N={1,@0} =[1] $N,0,1 21671 rm[3-5] i[3] (1,0;1,{$N-1}) r[3] 2,$N,1,1,3 round[3] 21672 if $2 # With alpha-channel. 21673 if s==1 # Only alpha-channel. 21674 i.. 3,$N,1,1,200 /. 255 21675 i.. (-128;{w};{h};1) 21676 if $N>1 1,{4*($N-1)},1,1,-128,0,0,0 fi 21677 else # Image + alpha. 21678 s. c,-{s-1} /. 255 21679 i... (-128;{w};{h};{-2,s}) 21680 if $N>1 i.. 1,{4*($N-1)},1,1,-128,0,0,0 fi 21681 i.. (-128;{w};{h};1) 21682 if $N>1 1,{4*($N-1)},1,1,-128,0,0,0 fi 21683 fi 21684 else # Without alpha-channel. 21685 i.. (-128;{w};{h};{s}) y[-3,-1] 21686 if $N>1 1,{4*($N-1)},1,1,-128,0,0,0 fi 21687 1,$N,1,1,1 21688 fi 21689 y a y 21690 endl done 21691 21692#@cli star3d : _nb_branches>0,0<=_thickness<=1 21693#@cli : Input 3D star at position `(0,0,0)`, with specified geometry. 21694#@cli : Default values: 'nb_branches=5' and 'thickness=0.38'. 21695#@cli : $ star3d , +primitives3d 1 color3d[-2] ${-rgb} 21696+star3d : check "${1=5}>0 && ${2=0.38}>=0 && $2<=1" 21697 e[^-1] "Input 3D star, with $1 branches and thickness $2." 21698 N={2*$1} ('CImg3d') +. 0.5 ({$N+1};$N) 21699 ({-pi/2};{3*pi/2}) r. 1,{$N+1},1,1,3 rows. 0,{h-2} +sin. cos.. a[-2,-1] x 21700 (1,1;$2,$2) *[-2,-1] z. 0,2 r. 3,{h+1},1,1,0 21701 (3,$N,1,0;3,$N,$N,{$N-1}) r. 4,$N,1,1,3 round. =. 0,2,100% 21702 3,$N,1,1,200 1,$N,1,1,1 y[-6,-4--2] a[-6--1] y nm. [3D\ star] 21703 21704#@cli streamline3d : x[%],y[%],z[%],_L>=0,_dl>0,_interpolation,_is_backward={ 0 | 1 },_is_oriented={ 0 | 1 } : \ 21705# 'formula',x,y,z,_L>=0,_dl>0,_interpolation,_is_backward={ 0 | 1 },_is_oriented={ 0 | 1 } : (+) 21706#@cli : Extract 3D streamlines from selected vector fields or from specified formula. 21707#@cli : 'interpolation' can be { 0=nearest integer | 1=1st-order | 2=2nd-order | 3=4th-order }. 21708#@cli : Default values: 'dl=0.1', 'interpolation=2', 'is_backward=0' and 'is_oriented=0'. 21709#@cli : $ 100,100,100,3 rand -10,10 blur 3 repeat 300 +streamline3d[0] {u(100)},{u(100)},{u(100)},1000,1,1 \ 21710# color3d[-1] ${-rgb} done remove[0] box3d 100 primitives3d[-1] 1 add3d 21711 21712#@cli -3d : eq. to 'sub3d'. : (+) 21713 21714#@cli sub3d : tx,_ty,_tz : (+) 21715#@cli : Shift selected 3D objects with the opposite of specified displacement vector. 21716#@cli : (eq. to '3d'). 21717#@cli : Default values: 'ty=tz=0'. 21718#@cli : $ sphere3d 10 repeat 5 +sub3d[-1] 10,{u(-10,10)},0 color3d[-1] ${-rgb} done add3d 21719 21720#@cli superformula3d : resolution>1,m>=1,n1,n2,n3 21721#@cli : Input 2D superformula curve as a 3D object. 21722#@cli : Default values: 'resolution=1024', 'm=8', 'n1=1', 'n2=5' and 'n3=8'. 21723#@cli : $ superformula3d , 21724+superformula3d : check "${1=1024}>1 && ${2=8}>=1" skip ${3=1},${4=5},${5=8} 21725 e[^-1] "Input 2D superformula curve, with resolution $1, m=$2 and (n1,n2,n3)=($3,$4,$5)." 21726 res={round($1)} 21727 21728 # Define object header and vertices. 21729 (67.5;73.5;109.5;103.5;51.5;100.5;$res;{$res-1}) 21730 (0,{2*pi}) r. $res,1,1,1,3 . 21731 21732 *. {$2/4} +sin. cos.. abs[-2,-1] 21733 ^.. $4 ^. $5 +[-2,-1] ^. {-1/$3} 21734 +sin.. cos... *. .. *[-3,-2] n[-2,-1] -1,1 21735 a[-2,-1] y rows. 0,2 transpose. r. 1,{w*h},1,1,-1 21736 21737 # Define object primitives, colors and opacities. 21738 1,{$res-1},1,1,2 (0;{$res-2}) r. 1,{$res-1},1,1,3 ++. 1 a[-3--1] x round. 1 r. 1,{w*h},1,1,-1 21739 1,{3*($res-1)},1,1,200 1,{$res-1},1,1,1 a[-5--1] y nm. [3D\ superformula] 21740 21741#@cli tensors3d : _radius_factor>=0,_shape={ 0=box | >=N=ellipsoid },_radius_min>=0 21742#@cli : Generate 3D tensor fields from selected images. 21743#@cli : when 'shape'>0, it gives the ellipsoid shape precision. 21744#@cli : Default values: 'radius_factor=1', 'shape=2' and 'radius_min=0.05'. 21745#@cli : $ 6,6,6,9,"U = [x,y,z] - [w,h,d]/2; U/=norm(U); mul(U,U,3) + 0.3*eye(3)" tensors3d 0.8 21746tensors3d : check "${1=1}>=0 && isint(${2=2}) && $2>=0 && ${3=0.05}>=0" 21747 e[^-1] "Generate 3D tensor field(s) from image$?, with radius factor $1, "\ 21748 ${"if $2 u ellipsoid else u box fi"}" shape and radius min $3." 21749 repeat $! l[$>] 21750 21751 # Check input image format. 21752 if s==1 100%,100%,100%,6,"[i#0,0,0,i#0,0,i#0]" k. 21753 elif s==3 100%,100%,100%,6,"[R#0,G#0,0,B#0,0,0]" k. 21754 elif s==4 100%,100%,100%,6,"[R#0,G#0,0,A#0,0,0]" k. 21755 elif s==9 100%,100%,100%,6,"I=I#0;[I[0],I[1],I[2],I[4],I[5],I[8]]" k. 21756 fi 21757 if s!=6 error[0--4] "Command '$0': Image '"{n}"' has an invalid size (spectrum="{s}")." fi 21758 21759 # Estimate eigenvalues/eigenvectors. 21760 100%,100%,100%,12," 21761 T = I(#0); 21762 M = [ T[0], T[1], T[2], T[1], T[3], T[4], T[2], T[4], T[5] ]; 21763 eig = eig(M); 21764 if (det(eig[3,9])<0, eig[3]*=-1; eig[4]*=-1; eig[5]*=-1); 21765 eig[0] = max(0,eig[0]); 21766 eig[1] = max(0,eig[1]); 21767 eig[2] = max(0,eig[2]); 21768 eig" 21769 k. 21770 21771 # Create 3D object. 21772 if $2 sphere3d 1,{$2-1} else box3d 1 fi 21773 N,P={[i[6],i[7]]} siz={h} n3d. c3d. .x{0,whd-1} 21774 f[0] " 21775 const N = "$N"; 21776 const P = "$P"; 21777 const siz = "$siz"; 21778 eig = I; 21779 const d = size(eig); 21780 ind = 1 + x + w*y + wh*z; 21781 L = eig[0,3]; 21782 if (max(L)==0, # Empty tensor -> do not display 21783 i[#ind,6] = i[#ind,7] = 0; 21784 resize(#ind,1,8,1,1,0); 21785 _(else), 21786 L*=$1; 21787 L[0] = max($3,L[0]); 21788 L[1] = max($3,L[1]); 21789 L[2] = max($3,L[2]); 21790 R = eig[3,9]; 21791 anisotropy = sqrt(((L[0] - L[1])^2 + (L[1] - L[2])^2 + (L[2] - L[0])^2)/(2*(L[0]^2 + L[1]^2 + L[2]^2))); 21792 21793 ref(crop(#ind,0,8,0,0,1,3*N,1,1),pts); 21794 pts *= resize(L,size(pts),0,2); 21795 pts = mul(pts,R,3); 21796 pts += resize([x,y,z],size(pts),0,2); 21797 draw(#ind,pts,0,8,0,0,1,size(pts),1,1); 21798 21799 col0 = cut(255*anisotropy*abs([ R[0],R[1],R[2] ]) + (1 - anisotropy)*200,0,255); 21800 col = resize(col0,3*P,0,2); 21801 const off = siz - 4*P; 21802 draw(#ind,col,0,off,0,0,1,size(col),1,1); 21803 0); I" 21804 rm[0] +3d 21805 endl done 21806 21807#@cli text_pointcloud3d : _"text1",_"text2",_smoothness 21808#@cli : Input 3D text pointcloud from the two specified strings. 21809#@cli : Default values: 'text1="text1"', 'text2="text2"' and 'smoothness=1'. 21810#@cli : $ text_pointcloud3d "G'MIC","Rocks!" 21811+text_pointcloud3d : skip "${1=text1}","${2=text2}",${3=1} 21812 e[^-1] "Input 3D pointcloud text object from strings '$1' and '$2', with smoothness $3." 21813 0 t. "$1",0,0,53,1,1 21814 0 t. "$2",0,0,53,1,1 mirror. y 21815 autocrop[-2,-1] 0 21816 expand_xy[-2,-1] 2,0 dilate[-2,-1] 2 21817 permute. zyxc r[-2,-1] ${-max_whd} &[-2,-1] 21818 21819 100%,100% rand. 0,{{-2,d}-1} round. ri. .. f. 'if(z==i,1,0)' 21820 distance. 1 +. 1 +f. 1 rv[-2,-1] /[-2,-1] *. .. 21821 +dilate. 0,0,{d} ==[-2,-1] *. .. 21822 21823 1,100%,100% rand. 0,{{-2,w}-1} round. ri. .. f. 'if(x==i,1,0)' 21824 distance. 1 +. 1 +f. 1 rv[-2,-1] /[-2,-1] *. ... 21825 +dilate. 0,0,{d} ==[-2,-1] *[-3,-1] 21826 21827 -|[-2,-1] 21828 21829 b. $3 isosurface3d. 25% 21830 c3d. n3d. nm. "[3D text pointcloud]" 21831 21832#@cli text3d : text,_font_height>0,_depth>0,_smoothness 21833#@cli : Input a 3D text object from specified text. 21834#@cli : Default values: 'font_height=53', 'depth=10' and 'smoothness=1.5'. 21835#@cli : $ text3d "G'MIC as a\n3D logo!" 21836+text3d : skip ${2=53},${3=10},${4=1.5} 21837 e[^-1] "Input 3D text object '$1' with size $2, depth $3 and smoothness $4." 21838 0 t. "$1",0,0,$2,1,1 autocrop. 0 r. 100%,100%,$3 expand_xyz. 10,0 21839 b. $4 isosurface3d. 40% rv3d. nm. "[3D text '$1']" 21840 21841#@cli t3d : eq. to 'texturize3d'. 21842t3d : check ${"is_image_arg $1"}" && (!narg(${2=}) || "${"is_image_arg $2"}")" 21843 e[^-1] "Texturize 3D object$? with texture $1"\ 21844 ${"if narg($2) u \" and texture coordinates $2\" else u \"\" fi"}"." 21845 pass$1 0 slices. 0 if s==1 to_rgb. else channels. 0,2 fi 21846 if narg($2) pass$2 else 0 fi 21847 v + _texturize3d 21848 21849#@cli texturize3d : [ind_texture],_[ind_coords] 21850#@cli : Texturize selected 3D objects with specified texture and coordinates. 21851#@cli : (eq. to 't3d').\n 21852#@cli : When '[ind_coords]' is omitted, default XY texture projection is performed. 21853#@cli : Default value: 'ind_coords=(undefined)'. 21854#@cli : $ image.jpg torus3d 100,30 texturize3d[-1] [-2] keep[-1] 21855texturize3d : check ${"is_image_arg $1"}" && (!narg(${2=}) || "${"is_image_arg $2"}")" 21856 e[^-1] "Texturize 3D object$? with texture $1"\ 21857 ${"if narg($2) u \" and texture coordinates $2\" else u \"\" fi"}"." 21858 pass$1 0 slices. 0 if s==1 to_rgb. else channels. 0,2 fi 21859 if narg($2) pass$2 else 0 fi 21860 v + _$0 21861 21862_texturize3d : 21863 repeat $!-2 l[$>,-2,-1] 21864 np={f2ui(i[7])} 21865 s3d[0] 21866 21867 # Retrieve texture coordinates for each vertex. 21868 if !w 21869 +r[2] 3,{2,round(h/3)},1,1,-1 s. x,3 rm. 21870 n.. 0,{6,w-1} n. 0,{6,h-1} a[-2,-1] x 21871 mv. -2 21872 fi 21873 21874 # Texturize 3D object 21875 1,{5,2*h} 21876 1,{5,3*h} 21877 1,{5,h},1,1,1 21878 eval " 21879 add_material() = ( 21880 ind_tex>=0?( # Shared texture 21881 copy(i[#-2,qc],[ -128,ind_tex,0,0 ],4); qc+=4 21882 ):( # Non-shared texture 21883 qc + whds#6 + 4>=h(#-2)?resize(#-2,1,int(1.5*qc + whds#6 + 4),1,1,0,0); 21884 copy(i[#-2,qc],[ -128,w#6,h#6,s#6 ],4); qc+=4; 21885 copy(i[#-2,qc],i(#6),whds#6); qc+=whds#6; 21886 ind_tex = np; 21887 ); 21888 ); 21889 21890 ind_tex = -1; 21891 for (pp = pc = qp = qc = np = 0, pp<h#3, ++np, 21892 qp + 13>=h(#-3)?resize(#-3,1,int(1.5*qp + 13),1,1,0,0); 21893 qc + 3>=h(#-2)?resize(#-2,1,int(1.5*qc + 3),1,1,0,0); 21894 N = i[#3,pp++]; 21895 21896 N==1?( # Colored point 21897 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 21898 R = i(#6,tx0,ty0,0,0); G = i(#6,tx0,ty0,0,1); B = i(#6,tx0,ty0,0,2); 21899 copy(i[#-3,qp],[ 1,v0 ],2); qp+=2; 21900 copy(i[#-2,qc],[ R,G,B ],3); qc+=3; 21901 21902 ):(N==2 || N==6)?( # Colored segment 21903 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 21904 v1 = i[#3,pp++]; tx1 = i(#7,0,v1); ty1 = i(#7,1,v1); 21905 N==6?(pp+=4); 21906 copy(i[#-3,qp],[ 6,v0,v1,tx0,ty0,tx1,ty1 ],7); qp+=7; 21907 add_material(); 21908 21909 ):(N==3 || N==9)?( # Colored triangle 21910 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 21911 v1 = i[#3,pp++]; tx1 = i(#7,0,v1); ty1 = i(#7,1,v1); 21912 v2 = i[#3,pp++]; tx2 = i(#7,0,v2); ty2 = i(#7,1,v2); 21913 N==9?(pp+=6); 21914 copy(i[#-3,qp],[ 9,v0,v1,v2,tx0,ty0,tx1,ty1,tx2,ty2 ],10); qp+=10; 21915 add_material(); 21916 21917 ):(N==4 || N==12)?( # Colored quadrangle 21918 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 21919 v1 = i[#3,pp++]; tx1 = i(#7,0,v1); ty1 = i(#7,1,v1); 21920 v2 = i[#3,pp++]; tx2 = i(#7,0,v2); ty2 = i(#7,1,v2); 21921 v3 = i[#3,pp++]; tx3 = i(#7,0,v3); ty3 = i(#7,1,v3); 21922 N==12?(pp+=8); 21923 copy(i[#-3,qp],[ 12,v0,v1,v2,v3,tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3 ],13); qp+=13; 21924 add_material(); 21925 21926 ):N==5?( # Colored sphere 21927 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 21928 v1 = i[#3,pp++]; tx1 = i(#7,0,v1); ty1 = i(#7,1,v1); 21929 v2 = i[#3,pp++]; pp+=2; 21930 (tx0+=tx1)/=2; (ty0+=ty1)/=2; 21931 R = i(#6,tx0,ty0,0,0); G = i(#6,tx0,ty0,0,1); B = i(#6,tx0,ty0,0,2); 21932 copy(i[#-3,qp],[ 5,v0,v1,v2,0,0 ],6); qp+=6; 21933 copy(i[#-2,qc],[ R,G,B ],3); qc+=3; 21934 21935 ); 21936 ); 21937 resize(#-3,1,qp,1,1,0,0); 21938 resize(#-2,1,qc,1,1,0,0)" 21939 21940 rm[3-5] mv[-3--1] 3 21941 if !w rm.. fi 21942 a[0-5] y 21943 endl done rm[-2,-1] 21944 21945#@cli torus3d : _radius1,_radius2,_nb_subdivisions1>2,_nb_subdivisions2>2 21946#@cli : Input 3D torus at (0,0,0), with specified geometry. 21947#@cli : Default values: 'radius1=1', 'radius2=0.3', 'nb_subdivisions1=24' and 'nb_subdivisions2=12'. 21948#@cli : $ torus3d 10,3 +primitives3d 1 color3d[-2] ${-rgb} 21949+torus3d : check "${3=24}>2 && ${4=12}>2" skip ${1=1},${2=0.3} 21950 e[^-1] "Input 3D torus, with radii ($1,$2) and subdivisions ($3,$4)." 21951 # Header. 21952 nbp={$3*$4} 21953 1,8,1,1,67.5,73.5,109.5,103.5,51.5,100.5,$nbp,{$4*$3} 21954 21955 # Vertices. 21956 (0;{2*pi}) +y. x 21957 r.. 1,{$3+1},1,1,3 z.. 0,0,0,{$3-1} 21958 r. {$4+1},1,1,1,3 z. 0,{$4-1} 21959 +sin[-2,-1] cos[-4,-3] r[-4--1] $4,$3 21960 *... $2 +... $1 *. $2 *[-4] ... *[-3,-2] 21961 y[-3--1] a[-3--1] x 21962 21963 # Primitives. 21964 1,$3,1,1,'y' *. $4 +shift. 0,-1 $4,1,1,1,'x' +shift. -1 r[-4--1] $4,$3 21965 ++[-4,-1] +.. [-4] +[-5] ... +[-4,-3] y[-4--1] i[-5] 1,{h},1,1,4 a[-5--1] x 21966 21967 # Colors / opacities. 21968 3,{h},1,1,200 1,{h},1,1,1 y[-4--2] a[-5--1] y 21969 nm. [3D\ torus] 21970 21971#@cli triangle3d : x0,y0,z0,x1,y1,z1,x2,y2,z2 21972#@cli : Input 3D triangle at specified coordinates. 21973#@cli : $ repeat 100 a={$>*pi/50} triangle3d 0,0,0,0,0,3,{cos(3*$a)},{sin(2*$a)},0 color3d[-1] ${-rgb} done add3d 21974+triangle3d : 21975 e[^-1] "Input 3D triangle ($1,$2,$3)-($4,$5,$6)-($7,$8,$9)." 21976 1,25,1,1,67.5,73.5,109.5,103.5,51.5,100.5,3,1,${1-9},3,0,1,2,200,200,200,1 nm. [3D\ triangle] 21977 21978#@cli volume3d 21979#@cli : Transform selected 3D volumetric images as 3D parallelepipedic objects. 21980#@cli : $ image.jpg animate blur,0,5,30 append z volume3d 21981volume3d : 21982 e[^-1] "Transform image$? as 3D parallelepipedic objects." 21983 repeat $! l[$>] 21984 w={w} h={h} d={d} 21985 +slices[0] 0 21986 +columns[0] 0 permute. zyxc mirror. x 21987 +slices[0] 100% mirror. x 21988 +columns[0] 100% permute. zyxc 21989 +rows[0] 100% permute. xzyc 21990 +rows[0] 0 permute. xzyc mirror. y 21991 rm[0] image6cube3d *3d $w,$h,$d 21992 endl done 21993 21994#@cli weird3d : _resolution>0 21995#@cli : Input 3D weird object at (0,0,0), with specified resolution. 21996#@cli : Default value: 'resolution=32'. 21997#@cli : $ weird3d 48 +primitives3d 1 color3d[-2] ${-rgb} 21998+weird3d : skip ${1=32} 21999 e[^-1] "Input 3D weird object, with resolution $1." 22000 isosurface3d '" 22001 T = 1.61803399; 22002 2 - (cos(x + T*y) + cos(x - T*y) + cos(y + T*z) + cos(y - T*z) + cos(z - T*x) + cos(z + T*x))"',\ 22003 0,-4.7,-4.7,-4.7,4.7,4.7,4.7,$1,$1,$1 22004 c3d. n3d. nm. [3D\ weird] 22005 22006#------------------------------- 22007# 22008#@cli :: Control Flow 22009# 22010#------------------------------- 22011 22012#@cli ap : eq. to 'apply_parallel'. 22013ap : 22014 _gmic_s="$?" v + _apply_parallel "$*" 22015 22016#@cli apply_parallel : "command" 22017#@cli : Apply specified command on each of the selected images, by parallelizing it for all image of the list. 22018#@cli : (eq. to 'ap'). 22019#@cli : $ image.jpg +mirror x +mirror y apply_parallel "blur 3" 22020apply_parallel : 22021 _gmic_s="$?" v + _$0 "$*" 22022 22023_apply_parallel : 22024 e[0--3] "Apply command '$*' on all image"$_gmic_s" in parallel, using "$_cpus" threads." 22025 if $!" && "narg("$*") 22026 m "_ap : repeat $! l[$>] $* if $! k[0] else 0 fi endl done" 22027 N={min($!,$_cpus)} 22028 commands= sep= repeat $N commands=$commands${sep}_ap[$>--1:$N] sep=, done 22029 parallel $commands 22030 um _ap 22031 fi 22032 22033#@cli apc : eq. to 'apply_parallel_channels'. 22034apc : 22035 _gmic_s="$?" v + _apply_parallel_channels "$*" 22036 22037#@cli apply_parallel_channels : "command" 22038#@cli : Apply specified command on each of the selected images, by parallelizing it for all channel 22039#@cli : of the images independently. 22040#@cli : (eq. to 'apc'). 22041#@cli : $ image.jpg apply_parallel_channels "blur 3" 22042apply_parallel_channels : 22043 _gmic_s="$?" v + _$0 "$*" 22044 22045_apply_parallel_channels : 22046 e[0--3] "Apply command '$*' on all channels of image"$_gmic_s" in parallel, using "$_cpus" threads." 22047 N=$! repeat $N s$>={$>,s} done s c 22048 ap "$1" 22049 repeat $N a[$>-{$>+${s$>}-1}] c done 22050 22051#@cli apo : eq. to 'apply_parallel_overlap'. 22052apo : check "${2=0}>=0 && isint(${3=0}) && $3>=0" 22053 _gmic_s="$?" v + _apply_parallel_overlap "$1",${2--1} 22054 22055#@cli apply_parallel_overlap : "command",overlap[%],nb_threads={ 0=auto | 1 | 2 | 4 | 8 | 16 } 22056#@cli : Apply specified command on each of the selected images, by parallelizing it on 'nb_threads' 22057#@cli : overlapped sub-images. 22058#@cli : (eq. to 'apo').\n 22059#@cli : 'nb_threads' must be a power of 2. 22060#@cli : Default values: 'overlap=0','nb_threads=0'. 22061#@cli : $ image.jpg +apply_parallel_overlap "smooth 500,0,1",1 22062apply_parallel_overlap : check "${2=0}>=0 && isint(${3=0}) && $3>=0" 22063 _gmic_s="$?" v + _$0 "$1",${2--1} 22064 22065_apply_parallel_overlap : check "${2=0}>=0 && isint(${3=0}) && $3>=0" 22066 N={if($3,max(1,round($3)),$_cpus)} N={2^int(log2(min(16,$N)))} 22067 e[0--3] "Apply parallelized command '$1' on image"$_gmic_s", with overlap $2 and "$N" threads." 22068 __apo_exception="" 22069 m "_check1 : if $!!=1 rm 0 __apo_exception=\"Command 'apply_parallel_overlap': Specified command '$1' changes the 22070 size of the image stack.\" fi" 22071 repeat $! l[$>] 22072 _apply_parallel_overlap$N "$1",$2 22073 endl done 22074 um _check1 22075 22076_apply_parallel_overlap1 : 22077 $1 22078 if narg($__apo_exception) error[0--12] $__apo_exception fi 22079 22080_apply_parallel_overlap2 : 22081 if w>=h 22082 ovx={round(if(${"is_percent $2"},w*$2,$2))} w2={int(w/2)} 22083 +z[0] {$w2-$ovx},100% z[0] 0,{$w2+$ovx-1} 22084 parallel "l[0] $1 _check1 endl","l[1] $1 _check1 endl" 22085 if narg($__apo_exception) error[0--12] $__apo_exception fi 22086 z[0] 0,{0,w-1-$ovx} z[1] $ovx,100% a x 22087 else 22088 ovy={round(if(${"is_percent $2"},h*$2,$2))} h2={int(h/2)} 22089 +rows[0] {$h2-$ovy},100% rows[0] 0,{$h2+$ovy-1} 22090 parallel "l[0] $1 _check1 endl","l[1] $1 _check1 endl" 22091 if narg($__apo_exception) error[0--12] $__apo_exception fi 22092 rows[0] 0,{0,h-1-$ovy} rows[1] $ovy,100% a y 22093 fi 22094 22095_apply_parallel_overlap4 : 22096 if max(w,h)/min(w,h)>=3 22097 _apply_parallel_overlap2 "_apply_parallel_overlap2 \"$1\",$2",$2 22098 else 22099 ovx={round(if(${"is_percent $2"},w*$2,$2))} w2={int(w/2)} 22100 ovy={round(if(${"is_percent $2"},h*$2,$2))} h2={int(h/2)} 22101 +z[0] {$w2-$ovx},0,100%,{$h2+$ovy-1} +z[0] 0,{$h2-$ovy},{$w2+$ovx-1},100% 22102 +z[0] {$w2-$ovx},{$h2-$ovy},100%,100% z[0] 0,0,{$w2+$ovx-1},{$h2+$ovy-1} 22103 parallel "l[0] $1 _check1 endl","l[1] $1 _check1 endl","l[2] $1 _check1 endl","l[3] $1 _check1 endl" 22104 if narg($__apo_exception) error[0--12] $__apo_exception fi 22105 z[0] 0,0,{0,w-1-$ovx},{0,h-1-$ovy} z[1] $ovx,0,100%,{1,h-1-$ovy} 22106 z[2] 0,$ovy,{2,w-1-$ovx},100% z[3] $ovx,$ovy,100%,100% 22107 a[0,1] x a[1,2] x a y 22108 fi 22109 22110_apply_parallel_overlap8 : 22111 _apply_parallel_overlap2 "_apply_parallel_overlap4 \"$1\",$2",$2 22112 22113_apply_parallel_overlap16 : 22114 _apply_parallel_overlap2 "_apply_parallel_overlap8 \"$1\",$2",$2 22115 22116#@cli at : eq. to 'apply_tiles'. 22117at : check "${2=10%}>0 && ${3=10%}>0 && ${4=10%}>0 && ${5=0}>=0 && ${6=0}>=0 && ${7=0}>=0 && 22118 isint(${8=1}) && $8>=0 && $8<=3" 22119 _gmic_s="$?" v + _apply_tiles "$1",${2--1} 22120 22121#@cli apply_tiles : "command",_tile_width[%]>0,_tile_height[%]>0,_tile_depth[%]>0,_overlap_width[%]>=0,\ 22122# _overlap_height[%]>=0,_overlap_depth[%]>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 22123#@cli : Apply specified command on each tile (neighborhood) of the selected images, eventually with overlapping tiles. 22124#@cli : (eq. to 'at'). 22125#@cli : Default values: 'tile_width=tile_height=tile_depth=10%','overlap_width=overlap_height=overlap_depth=0' \ 22126# and 'boundary_conditions=1'. 22127#@cli : $ image.jpg +equalize[0] 256 +apply_tiles[0] "equalize 256",16,16,1,50%,50% 22128apply_tiles : check "${2=10%}>0 && ${3=10%}>0 && ${4=10%}>0 && ${5=0}>=0 && ${6=0}>=0 && ${7=0}>=0 && 22129 isint(${8=1}) && $8>=0 && $8<=3" 22130 _gmic_s="$?" v + _$0 "$1",${2--1} 22131 22132_apply_tiles : 22133 e[0--3] "Apply command '$1' on $2x$3x$4 tiles of image$?, with overlaps ($5,$6,$7) and "\ 22134 ${"arg 1+$8,dirichlet,neumann,periodic,mirror"}" boundary conditions." 22135 repeat $! l[$>] 22136 bw={cut(round(${"is_percent $2"}?w*$2:$2),1,w)} 22137 bh={cut(round(${"is_percent $3"}?h*$3:$3),1,h)} 22138 bd={cut(round(${"is_percent $4"}?d*$4:$4),1,d)} 22139 ow={round(${"is_percent $5"}?$bw*$5:$5)} 22140 oh={round(${"is_percent $6"}?$bh*$6:$6)} 22141 od={round(${"is_percent $7"}?$bd*$7:$7)} 22142 sw={cut($bw-$ow,1,$bw)} 22143 sh={cut($bh-$oh,1,$bh)} 22144 sd={cut($bd-$od,1,$bd)} 22145 100%,100%,100%,{s+1} # Reconstructed image + weights 22146 if $ow>0" || "$oh>0" || "$od>0 l[] # Generate gaussian weight in case of overlap 22147 $bw,1,1 1,$bh,1 1,1,$bd 22148 = 1,50%,50%,50% distance 1 22149 /[0] {0.3*$bw} /[1] {0.3*$bh} /[2] {0.3*$bd} 22150 sqr * -1 exp r $bw,$bh,$bd,1 * 22151 endl else $bw,$bh,$bd,1,1 22152 fi 22153 $bw,$bh,$bd,[0] 22154 m "__at : $1 k. r "$bw,$bh,$bd,{0,s},0 22155 eval " 22156 ref(crop(#2),mask); 22157 for (z = 0, z<d#0, z+="$sd", 22158 for (y = 0, y<h#0, y+="$sh", 22159 for (x = 0, x<w#0, x+="$sw", 22160 draw(crop(#0,x,y,z,w,h,d,$8),0,0,0,0,w,h,d); 22161 run('__at.'); 22162 breakpoint(); 22163 draw(#1,crop(#-1),x,y,z,0,w,h,d,s#0,-1,mask); 22164 draw(#1,mask,x,y,z,s#0,w,h,d,1,-1); 22165 ) 22166 ) 22167 )" 22168 rm[-2,-1] 22169 s. c,-{0,s} /[-2,-1] k. 22170 um __at 22171 endl done 22172 22173#@cli apply_timeout : "command",_timeout={ 0=no timeout | >0=with specified timeout (in seconds) } 22174#@cli : Apply a command with a timeout. 22175#@cli : Set variable '$_is_timeout' to '1' if timeout occurred, '0' otherwise. 22176#@cli : Default value: 'timeout=20'. 22177apply_timeout : check "${2=20}>=0" 22178 if $2<=0 22179 e[0--3] "Apply command '$1' on image$?, with no timeout." 22180 $1 22181 _is_timeout=0 22182 else 22183 e[0--3] "Apply command '$1' on image$?, with a timeout of $2 seconds." 22184 l[] ('$/') id={is} rm endl 22185 l 22186 +store initial 22187 __done$id=0 __is_timeout$id=0 22188 parallel "$1 __done"$id"=1",\ 22189 "l[] do if $|-"$|">$2 __is_timeout"$id"=1 error \"\" elif $__done"$id" break fi wait 100 while 1 endl" 22190 onfail 22191 rm $initial 22192 _is_timeout=0 22193 if ${__is_timeout$id} _is_timeout=1 error[0--5] "Command '$0': Time out ($2 seconds) for command '$1'." 22194 else error[0--5] "Command '$0': "${} 22195 fi 22196 endl 22197 fi 22198 22199#@cli check : condition : (+) 22200#@cli : Evaluate specified condition and display an error message if evaluated to false. 22201 22202#@cli check3d : _is_full_check={ 0 | 1 } : (+) 22203#@cli : Check validity of selected 3D vector objects, and display an error message 22204#@cli : if one of the selected images is not a valid 3D vector object. 22205#@cli : Full 3D object check is slower but more precise. 22206#@cli : Default value: 'is_full_check=1'. 22207 22208# check_display : calling_command_name 22209# Check if a display is available, and throw an error otherwise. 22210check_display : skip "${1=check_display}" 22211 if !{*,u} error[0--3] "Command '$1': No display available." fi 22212 22213# check_opencv : calling_command_name 22214# Check is OpenCV features are available, and throw an error otherwise. 22215check_opencv : skip "${1=check_opencv}" 22216 l[] check_opencv.mp4,0,0,1 rm 22217 onfail if find(['${}'],'-Dcimg_use_opencv')>0 22218 error[0--4] "Command '$1': No OpenCV features available. "\ 22219 "Your G'MIC interpreter has not been compiled with OpenCV support." 22220 fi rm endl 22221 22222#@cli continue : (+) 22223#@cli : Go to end of current 'repeat...done', 'do...while' or 'local...endlocal' block. 22224#@cli : $ image.jpg repeat 10 blur 1 if 1==1 continue fi deform 10 done 22225 22226#@cli break : (+) 22227#@cli : Break current 'repeat...done', 'do...while' or 'local...endlocal' block. 22228#@cli : $ image.jpg repeat 10 blur 1 if 1==1 break fi deform 10 done 22229 22230#@cli do : (+) 22231#@cli : Start a 'do...while' block. 22232#@cli : $ image.jpg luminance i={ia+2} do set 255,{u(100)}%,{u(100)}% while ia<$i 22233 22234#@cli done : (+) 22235#@cli : End a 'repeat/for...done' block, and go to associated 'repeat/for' position, if iterations remain. 22236 22237#@cli elif : condition : (+) 22238#@cli : Start a 'elif...[else]...fi' block if previous 'if' was not verified 22239#@cli : and test if specified condition holds 22240#@cli : 'condition' is a mathematical expression, whose evaluation is interpreted as { 0=false | other=true }.. 22241#@cli : $$ https://gmic.eu/tutorial/iffi 22242 22243#@cli else : (+) 22244#@cli : Execute following commands if previous 'if' or 'elif' conditions failed. 22245#@cli : $$ https://gmic.eu/tutorial/iffi 22246 22247#@cli fi : (+) 22248#@cli : End a 'if...[elif]...[else]...fi' block. 22249#@cli : (eq. to 'fi').\n 22250#@cli : $$ https://gmic.eu/tutorial/iffi 22251 22252#@cli endl : eq. to 'endlocal'. : (+) 22253 22254#@cli endlocal : (+) 22255#@cli : End a 'local...endlocal' block. 22256#@cli : (eq. to 'endl'). 22257 22258#@cli error : message : (+) 22259#@cli : Print specified error message on the standard error (stderr) and exit interpreter, except 22260#@cli : if error is caught by a 'onfail' command. 22261#@cli : Command selection (if any) stands for displayed call stack subset instead of image indices. 22262 22263#@cli eval : expression : (+) 22264#@cli : Evaluate specified math expression. 22265#@cli : - If no command selection is specified, the expression is evaluated once and its result is set to status. 22266#@cli : - If command selection is specified, the evaluation is looped over selected images. Status is not modified. 22267#@cli : (in this latter case, 'eval' is similar to 'fill' without assigning the image values). 22268 22269#@cli x : eq. to 'exec'. : (+) 22270 22271#@cli exec : _is_verbose={ 0 | 1 },"command" : (+) 22272#@cli : Execute external command using a system call. 22273#@cli : The status value is then set to the error code returned by the system call. 22274#@cli : If 'is_verbose=1', the executed command is allowed to output on stdout/stderr. 22275#@cli : (eq. to 'x'). 22276#@cli : Default value: 'is_verbose=1'. 22277 22278#@cli xo : eq. to 'exec_out'. 22279xo : 22280 v + _exec_out $"*" 22281 22282#@cli exec_out : _mode,"command" 22283#@cli : Execute external command using a system call, and return resulting `stdout` and/or `stderr`. 22284#@cli : 'mode' can be { 0=stdout | 1=stderr | 2=stdout+stderr }. 22285exec_out : 22286 v + _exec_out $"*" 22287 22288_exec_out : 22289 l[] 22290 if "isint($1) && isin($1,0,1,2)" mode=$1 command="${2--1}" 22291 else mode=0 command="$*" 22292 fi 22293 onfail mode=0 command="$*" endl 22294 s0,s1,s2=stdout,stderr,stdout+stderr 22295 e[0--3] "Execute external command '"$command"', and return "${s$mode}" output." 22296 file_rand filename=${} 22297 if $mode==0 x $command" > "$filename 22298 elif $mode==1 x $command" 2> "$filename 22299 else x $command" >"$filename" 2>&1" 22300 fi 22301 it $filename u {t} rm. delete $filename 22302 22303#@cli for : condition : (+) 22304#@cli : Start a 'for...done' block. 22305#@cli : $ image.jpg resize2dy 32 400,400,1,3 x=0 for $x<400 image[1] [0],$x,$x x+=40 done 22306 22307#@cli if : condition : (+) 22308#@cli : Start a 'if...[elif]...[else]...fi' block and test if specified condition holds. 22309#@cli : 'condition' is a mathematical expression, whose evaluation is interpreted as { 0=false | other=true }. 22310#@cli : $ image.jpg if ia<64 add 50% elif ia<128 add 25% elif ia<192 sub 25% else sub 50% fi cut 0,255 22311#@cli : $$ https://gmic.eu/tutorial/iffi 22312 22313#@cli l : eq. to 'local'. : (+) 22314 22315#@cli local : (+) 22316#@cli : Start a 'local...[onfail]...endlocal' block, with selected images. 22317#@cli : (eq. to 'l'). 22318#@cli : $ image.jpg local[] 300,300,1,3 rand[0] 0,255 blur 4 sharpen 1000 endlocal 22319#@cli : $ image.jpg +local repeat 3 deform 20 done endlocal 22320#@cli : $$ https://gmic.eu/oldtutorial/_local 22321 22322#@cli mutex : index,_action={ 0=unlock | 1=lock } : (+) 22323#@cli : Lock or unlock specified mutex for multi-threaded programming. 22324#@cli : A locked mutex can be unlocked only by the same thread. All mutexes are unlocked by default. 22325#@cli : 'index' designates the mutex index, in [0,255]. 22326#@cli : Default value: 'action=1'. 22327 22328#@cli noarg : (+) 22329#@cli : Used in a custom command, 'noarg' tells the command that its argument list have not been used 22330#@cli : finally, and so they must be evaluated next in the G'MIC pipeline, just as if the custom 22331#@cli : command takes no arguments at all. 22332#@cli : Use this command to write a custom command which can decide if it takes arguments or not. 22333 22334#@cli onfail : (+) 22335#@cli : Execute following commands when an error is encountered in the body of the 'local...endlocal' block. 22336#@cli : The status value is set with the corresponding error message. 22337#@cli : $ image.jpg +local blur -3 onfail mirror x endlocal 22338 22339#@cli parallel : _wait_threads,"command1","command2",... : (+) 22340#@cli : Execute specified commands in parallel, each in a different thread. 22341#@cli : Parallel threads share the list of images. 22342#@cli : 'wait_threads' can be { 0=when current environment ends | 1=immediately }. 22343#@cli : Default value: 'wait_threads=1'. 22344#@cli : $ image.jpg [0] parallel "blur[0] 3","mirror[1] c" 22345 22346# The implementation below allows to use parallel as a regular command with selections. 22347parallel : skip "${1=},${2=},${3=},${4=},${5=},${6=},${7=},${8=},${9=},${10=},${11=},${12=},${13=},${14=},${15=}" 22348 if $1==0||$1==1||$1==2 e[0--3] "Execute "{$#-1}" commands '${2--1}' in parallel on image$?." 22349 else e[0--3] "Execute "$#" commands '$*' in parallel on image$?." 22350 fi 22351 parallel $"*" 22352 22353#@cli progress : 0<=value<=100 : -1 : (+) 22354#@cli : Set the progress index of the current processing pipeline. 22355#@cli : This command is useful only when G'MIC is used by an embedding application. 22356 22357#@cli q : eq. to 'quit'. : (+) 22358 22359#@cli quit : (+) 22360#@cli : Quit G'MIC interpreter. 22361#@cli : (eq. to 'q'). 22362 22363#@cli repeat : nb_iterations,_variable_name : (+) 22364#@cli : Start 'nb_iterations' iterations of a 'repeat...done' block. 22365#@cli : 'nb_iterations' is a mathematical expression that will be evaluated. 22366#@cli : $ image.jpg split y repeat $!,n shift[$n] $<,0,0,0,2 done append y 22367#@cli : $ image.jpg mode3d 2 repeat 4 imagecube3d rotate3d 1,1,0,40 snapshot3d 400,1.4 done 22368#@cli : $$ https://gmic.eu/oldtutorial/_repeat 22369 22370#@cli return : (+) 22371#@cli : Return from current custom command. 22372 22373#@cli rprogress : 0<=value<=100 | -1 | "command",0<=value_min<=100,0<=value_max<=100 22374#@cli : Set the progress index of the current processing pipeline (relatively to 22375#@cli : previously defined progress bounds), or call the specified command with 22376#@cli : specified progress bounds. 22377rprogress : skip ${2=""} 22378 if !narg($_progress_bounds) _progress_bounds=0,100 fi 22379 m={arg(-2,$_progress_bounds)} M={arg(-1,$_progress_bounds)} 22380 if $#==2&&!narg($2) # 1 argument -> Set progress bar. 22381 e[0--3] "Set relative progress index to $1%." 22382 progress {if($1<0,-1,min(100,max(0,$m+($M-$m)*$1%)))} 22383 elif $#==3 # 3 arguments -> Call command with specified bounds. 22384 nm={min($2,$-1)} nM={max($2,$-1)} 22385 e[0--3] "Call command '$1' with progress bounds ["$nm,$nM"]." 22386 progress $m _progress_bounds=$_progress_bounds,{$m+$nm*($M-$m)/100},{$m+$nM*($M-$m)/100} # Push new bounds. 22387 run "$1" 22388 progress $M ($_progress_bounds) _progress_bounds={@0--3} rm. # Pop bounds. 22389 else error[0--3] "Command '$0': Invalid argument '$*'." 22390 fi 22391 22392#@cli run : "G'MIC pipeline" 22393#@cli : Run specified G'MIC pipeline. 22394#@cli : This is only useful when used from a shell, e.g. to avoid shell substitutions to happen in argument. 22395run : 22396 $* 22397 22398#@cli skip : item : (+) 22399#@cli : Do nothing but skip specified item. 22400 22401#@cli u : eq. to 'status'. : (+) 22402 22403#@cli status : status_string : (+) 22404#@cli : Set the current status. Used to define a returning value from a function. 22405#@cli : (eq. to 'u'). 22406#@cli : $ image.jpg command "foo : u0=Dark u1=Bright status ${u{ia>=128}}" text_outline ${-foo},2,2,23,2,1,255 22407 22408#@cli while : condition : (+) 22409#@cli : End a 'do...while' block and go back to associated 'do' if specified condition holds. 22410#@cli : 'condition' is a mathematical expression, whose evaluation is interpreted as { 0=false | other=true }. 22411 22412#------------------------- 22413# 22414#@cli :: Neural Networks 22415# 22416#------------------------- 22417 22418#@cli nn_lib : 22419#@cli : Return the list of library functions that has to be included in a math expression,\ 22420# in order to use the neural network library. 22421nn_lib : 22422 u " 22423 #--------------------------------------------------------------------------- 22424 # Definition of the library environment variables and convenience functions. 22425 #--------------------------------------------------------------------------- 22426 begin( 22427 const nn_nb_threads_max = n; 22428 ); 22429 22430 begin_t( 22431 nn_thread = t; 22432 nn_nb_threads_used = nn_thread + 1; 22433 nn_nb_samples = 0; 22434 ); 22435 22436 ++nn_nb_samples; 22437 22438 end( 22439 merge(nn_nb_threads_used,max); 22440 merge(nn_nb_samples,+); 22441 ); 22442 22443 nn_display(L) = display(L#_out,L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum); 22444 nn_display_deriv(L) = display(L#_deriv_out,L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum); 22445 22446 #-------------------------------------------- 22447 # Activation functions and their derivatives. 22448 #-------------------------------------------- 22449 _nn_activate_pointwise(Z,activation) = (fill(#Z,k,nn_activation_#activation(#Z[k]))); 22450 nn_activate(Z,activation) = nn_activate_#activation(#Z); 22451 22452 # ELU: Exponential Linear Unit. 22453 #------------------------------- 22454 nn_activation_elu(z) = (z<0?exp(z) - 1:z); 22455 nn_activation_deriv_elu(z) = (z<0?exp(z):1); 22456 nn_activate_elu(Z) = _nn_activate_pointwise(Z,elu); 22457 nn_activate_deriv_elu(Z) = _nn_activate_pointwise(Z,deriv_elu); 22458 22459 # GELU: Gaussian Error Linear Unit. 22460 #----------------------------------- 22461 nn_activation_gelu(z) = (0.5*z*(1 + erf(z/sqrt(2)))); 22462 nn_activation_deriv_gelu(z) = (0.5 + 0.5*erf(z/sqrt(2)) + z*exp(-z^2/2)/sqrt(2*pi)); 22463 nn_activate_gelu(Z) = _nn_activate_pointwise(Z,gelu); 22464 nn_activate_deriv_gelu(Z) = _nn_activate_pointwise(Z,deriv_gelu); 22465 22466 # LeakyRELU: Leaky Rectified Linear Unit. 22467 #----------------------------------------- 22468 nn_activation_leakyrelu(z) = (z<0?0.05*z:z); 22469 nn_activation_deriv_leakyrelu(z) = (z<0?0.05:1); 22470 nn_activate_leakyrelu(Z) = _nn_activate_pointwise(Z,leakyrelu); 22471 nn_activate_deriv_leakyrelu(Z) = _nn_activate_pointwise(Z,deriv_leakyrelu); 22472 22473 # Linear. 22474 #-------- 22475 nn_activate_linear(Z) = (0); 22476 nn_activate_deriv_linear(Z) = (#Z = 1); 22477 22478 # RELU: Rectified Linear Unit. 22479 #------------------------------ 22480 nn_activation_relu(z) = (z<0?0:z); 22481 nn_activation_deriv_relu(z) = (z<0?0:1); 22482 nn_activate_relu(Z) = _nn_activate_pointwise(Z,relu); 22483 nn_activate_deriv_relu(Z) = _nn_activate_pointwise(Z,deriv_relu); 22484 22485 # Sigmoid. 22486 #--------- 22487 nn_activation_sigmoid(z) = (0.5 + 0.5*tanh(z/2)); 22488 nn_activation_deriv_sigmoid(z) = (_nn_sig = nn_activation_sigmoid(z); _nn_sig*(1-_nn_sig)); 22489 nn_activate_sigmoid(Z) = _nn_activate_pointwise(Z,sigmoid); 22490 nn_activate_deriv_sigmoid(Z) = _nn_activate_pointwise(Z,deriv_sigmoid); 22491 22492 # Sqr: Square. 22493 #------------- 22494 nn_activate_sqr(Z) = (Z*=Z); 22495 nn_activate_deriv_sqr(Z) = (Z*=2); 22496 22497 # Sqrt: sqrt(|z|). 22498 #----------------- 22499 nn_activation_sqrt(z) = (sqrt(abs(z))); 22500 nn_activation_deriv_sqrt(z) = (0.5*sign(x)/sqrt(max(1e-8,abs(z)))); 22501 nn_activate_sqrt(Z) = _nn_activate_pointwise(Z,sqrt); 22502 nn_activate_deriv_sqrt(Z) = _nn_activate_pointwise(Z,deriv_sqrt); 22503 22504 # Swish. 22505 #-------- 22506 nn_activation_swish(z) = (z*nn_activation_sigmoid(z)); 22507 nn_activation_deriv_swish(z) = ( 22508 _nn_sig = nn_activation_sigmoid(z); 22509 _nn_swi = z*_nn_sig; 22510 _nn_swi + _nn_sig*(1 - _nn_swi) 22511 ); 22512 nn_activate_swish(Z) = _nn_activate_pointwise(Z,swish); 22513 nn_activate_deriv_swish(Z) = _nn_activate_pointwise(Z,deriv_swish); 22514 22515 # Tanh. 22516 #------ 22517 nn_activation_tanh(z) = (tanh(z)); 22518 nn_activation_deriv_tanh(z) = (1 - tanh(z)^2); 22519 nn_activate_tanh(Z) = _nn_activate_pointwise(Z,tanh); 22520 nn_activate_deriv_tanh(Z) = _nn_activate_pointwise(Z,deriv_tanh); 22521 22522 #--------- 22523 # Trainer. 22524 #--------- 22525 nn_trainer_init_backward(T,L,O,S) = ( 22526 const T#_ind = $T#; 22527 nn_iteration = i[##T#_ind,0]; 22528 nn_learning_rate = i[##T#_ind,1]; 22529 nn_learning_rate0 = i[##T#_ind,2]; 22530 nn_previous_loss = i[##T#_ind,3]; 22531 nn_best_loss = i[##T#_ind,4]; 22532 22533 const nn_optimizer = O; 22534 const nn_scheduler = S; 22535 nn_scheduler==3?nn_scheduler_adaptive_init(#T); 22536 nn_optimizer==1?nn_optimizer_rmsprop_init(): 22537 nn_optimizer==2?nn_optimizer_adam_init(): 22538 nn_optimizer==3?nn_optimizer_adamax_init(); 22539 ); 22540 22541 nn_trainer_update(T,L) = ( 22542 nn_scheduler==1?nn_scheduler_linear_update(): 22543 nn_scheduler==2?nn_scheduler_exponential_update(): 22544 nn_scheduler==3?nn_scheduler_adaptive_update(#T,#L); 22545 i[##T#_ind,0] = ++nn_iteration; 22546 i[##T#_ind,1] = nn_learning_rate; 22547 i[##T#_ind,3] = L#_out; 22548 i[##T#_ind,4] = min(nn_best_loss,L#_out); 22549 ); 22550 22551 #------------- 22552 # Schedulers. 22553 #------------- 22554 22555 # Linear Decrease. 22556 #----------------- 22557 nn_scheduler_linear_update() = ( 22558 nn_learning_rate = lerp(nn_learning_rate0,1e-8,min(1,nn_iteration/1000)); 22559 ); 22560 22561 # Exponential Decrease. 22562 #---------------------- 22563 nn_scheduler_exponential_update() = ( 22564 nn_learning_rate*=0.999; 22565 ); 22566 22567 # Adaptive Learning Rate. 22568 #------------------------ 22569 nn_scheduler_adaptive_init(T) = ( 22570 nn_adaptive_trend_moment = i(##T#_ind,0,2,0,0); 22571 nn_adaptive_nb_decreases = i(##T#_ind,1,2,0,0); 22572 nn_adaptive_nb_increases = i(##T#_ind,2,2,0,0); 22573 ); 22574 22575 nn_scheduler_adaptive_update(T,L) = ( 22576 nn_iteration?( 22577 # Compute trend: percentage of loss decrease(<0) or increase(>0). 22578 nn_adaptive_trend = (L#_out - nn_previous_loss)/max(1e-8,nn_previous_loss); 22579 nn_adaptive_trend_moment = lerp(sign(nn_adaptive_trend),nn_adaptive_trend_moment,0.75); 22580 22581 # Adapt strategy regarding to trend. 22582 nn_adaptive_trend>=0.3?( # Large local loss increase -> drastically reduce learning rate 22583 nn_learning_rate = max(0.25*nn_learning_rate,1e-11); 22584 nn_adaptive_nb_increases = nn_adaptive_nb_decreases = 0; 22585 ):nn_adaptive_trend_moment>=0?( # Global loss increase 22586 ++nn_adaptive_nb_increases; 22587 nn_adaptive_nb_decreases = 0; 22588 nn_adaptive_nb_increases>=2?( # Global loss increase -> slightly reduce learning rate 22589 nn_learning_rate = max(0.75*nn_learning_rate,1e-11); 22590 nn_adaptive_nb_increases = 0; 22591 ); 22592 ):nn_adaptive_trend_moment<0?( # Global loss decrease 22593 ++nn_adaptive_nb_decreases; 22594 nn_adaptive_nb_decreases>=4?( # Global loss decrease -> slightly increase learning rate 22595 nn_learning_rate = min(nn_learning_rate*1.15,0.1); 22596 nn_adaptive_nb_decreases = 0; 22597 ); 22598 ); 22599 ); 22600 copy(i(##T#_ind,0,2,0,0),[ nn_adaptive_trend_moment,nn_adaptive_nb_decreases,nn_adaptive_nb_increases ]); 22601 ); 22602 22603 #------------ 22604 # Optimizers. 22605 #------------ 22606 nn_optimizer_update_layer(L,dL) = ( 22607 !nn_optimizer?nn_optimizer_sgd_update_layer(#L,#dL): # Stochastic gradient descent 22608 nn_optimizer==1?nn_optimizer_rmsprop_update_layer(#L,#dL): # RMSprop 22609 nn_optimizer==2?nn_optimizer_adam_update_layer(#L,#dL): # Adam 22610 nn_optimizer==3?nn_optimizer_adamax_update_layer(#L,#dL); # Adamax 22611 ); 22612 22613 # Stochastic gradient descent. 22614 #----------------------------- 22615 nn_optimizer_sgd_update_layer(L_params,dL_params) = ( 22616 L_params#-=nn_learning_rate*#dL_params; 22617 ); 22618 22619 # RMSprop optimizer. 22620 #------------------- 22621 nn_optimizer_rmsprop_init() = ( 22622 const nn_optimizer_rmsprop_beta = 0.9; 22623 ); 22624 22625 nn_optimizer_rmsprop_update_layer(L_params,dL_params) = ( 22626 dL_params#_name_g2 = '_nn_#dL_params#_g2'; 22627 !nn_iteration || isnan($_nn_#dL_params#_g2)?( 22628 dL_params#_g2 = vector(#size(dL_params)); 22629 ):( 22630 dL_params#_g2 = get(dL_params#_name_g2,size(dL_params)); 22631 ); 22632 dL_params#_g2 = lerp(dL_params^2,dL_params#_g2,nn_optimizer_rmsprop_beta); 22633 store(dL_params#_g2,dL_params#_name_g2,size(dL_params)); 22634 L_params#-=nn_learning_rate*dL_params/sqrt(1e-8 + dL_params#_g2); 22635 ); 22636 22637 # Adam optimizer. 22638 #---------------- 22639 nn_optimizer_adam_init() = ( 22640 begin( 22641 const nn_optimizer_adam_beta1 = 0.9; 22642 const nn_optimizer_adam_beta2 = 0.999; 22643 nn_optimizer_adam_beta1_t = nn_iteration>200?0:nn_optimizer_adam_beta1^(nn_iteration + 1); 22644 nn_optimizer_adam_beta2_t = nn_iteration>200?0:nn_optimizer_adam_beta2^(nn_iteration + 1); 22645 nn_optimizer_adam_alpha_t = sqrt(1 - nn_optimizer_adam_beta2_t)/(1 - nn_optimizer_adam_beta1_t); 22646 ); 22647 ); 22648 22649 nn_optimizer_adam_update_layer(L_params,dL_params) = ( 22650 dL_params#_name_m = '_nn_#dL_params#_m'; 22651 dL_params#_name_v = '_nn_#dL_params#_v'; 22652 !nn_iteration || isnan($_nn_#dL_params#_m)?( 22653 dL_params#_m = dL_params#_v = vector(#size(dL_params)); 22654 ):( 22655 dL_params#_m = get(dL_params#_name_m,size(dL_params)); 22656 dL_params#_v = get(dL_params#_name_v,size(dL_params)); 22657 ); 22658 dL_params#_m = lerp(dL_params,dL_params#_m,nn_optimizer_adam_beta1); 22659 dL_params#_v = lerp(dL_params^2,dL_params#_v,nn_optimizer_adam_beta2); 22660 store(dL_params#_m,dL_params#_name_m,size(dL_params)); 22661 store(dL_params#_v,dL_params#_name_v,size(dL_params)); 22662 L_params#-=nn_learning_rate*nn_optimizer_adam_alpha_t*dL_params#_m/sqrt(1e-8 + dL_params#_v); 22663 ); 22664 22665 # Adamax optimizer. 22666 #------------------ 22667 nn_optimizer_adamax_init() = ( 22668 begin( 22669 const nn_optimizer_adamax_beta1 = 0.9; 22670 const nn_optimizer_adamax_beta2 = 0.999; 22671 const nn_optimizer_adamax_ombeta1_t = nn_iteration>200?1:(1 - nn_optimizer_adamax_beta1^(nn_iteration + 1)); 22672 ); 22673 ); 22674 22675 nn_optimizer_adamax_update_layer(L_params,dL_params) = ( 22676 dL_params#_name_m = '_nn_#dL_params#_m'; 22677 dL_params#_name_v = '_nn_#dL_params#_v'; 22678 !nn_iteration || isnan($_nn_#dL_params#_m)?( 22679 dL_params#_m = dL_params#_v = vector(#size(dL_params)); 22680 ):( 22681 dL_params#_m = get(dL_params#_name_m,size(dL_params)); 22682 dL_params#_v = get(dL_params#_name_v,size(dL_params)); 22683 ); 22684 dL_params#_m = lerp(dL_params,dL_params#_m,nn_optimizer_adamax_beta1); 22685 dL_params#_v = vmax(abs(dL_params),nn_optimizer_adamax_beta2*dL_params#_v); 22686 store(dL_params#_m,dL_params#_name_m,size(dL_params)); 22687 store(dL_params#_v,dL_params#_name_v,size(dL_params)); 22688 22689 L_params#-=(nn_learning_rate/nn_optimizer_adamax_ombeta1_t)*dL_params#_m/sqrt(1e-8 + dL_params#_v); 22690 ); 22691 22692 #---------------- 22693 # Network layers. 22694 #---------------- 22695 22696 # add: Add two inputs. 22697 #--------------------- 22698 nn_layer_add_init_forward(L,IN) = ( 22699 const L#_out_width = IN#_out_width; 22700 const L#_out_height = IN#_out_height; 22701 const L#_out_depth = IN#_out_depth; 22702 const L#_out_spectrum = IN#_out_spectrum; 22703 ); 22704 22705 nn_layer_add_forward(L,IN0,IN1) = ( 22706 L#_out = IN0#_out + IN1#_out; 22707 ); 22708 22709 nn_layer_add_backward(L,IN0,IN1) = ( 22710 IN0#_deriv_out = IN1#_deriv_out = L#_deriv_out/2; 22711 ); 22712 22713 # append: Append two inputs as a new output. 22714 #-------------------------------------------- 22715 nn_layer_append_init_forward(L,IN0,IN1) = ( 22716 const L#_out_width = IN0#_out_width; 22717 const L#_out_height = IN0#_out_height; 22718 const L#_out_depth = IN0#_out_depth; 22719 const L#_out_spectrum = IN0#_out_spectrum + IN1#_out_spectrum; 22720 ); 22721 22722 nn_layer_append_forward(L,IN0,IN1) = ( 22723 L#_out = vector(#size(IN0#_out) + size(IN1#_out)); 22724 copy(L#_out,IN0#_out,size(IN0#_out)); 22725 copy(L#_out[size(IN0#_out)],IN1#_out,size(IN1#_out)); 22726 ); 22727 22728 nn_layer_append_backward(L,IN0,IN1) = ( 22729 IN0#_deriv_out = L#_deriv_out[0,size(IN0#_out)]; 22730 IN1#_deriv_out = L#_deriv_out[size(IN0#_out),size(IN1#_out)]; 22731 ); 22732 22733 # avgpool2d : 2D average pooling. 22734 #-------------------------------- 22735 nn_layer_avgpool2d_init_forward(L,IN) = ( 22736 const L#_out_width = int(IN#_out_width/2); 22737 const L#_out_height = int(IN#_out_height/2); 22738 const L#_out_depth = IN#_out_depth; 22739 const L#_out_spectrum = IN#_out_spectrum; 22740 nn_avgpool2d_kernel_forward = vector4(0.25); 22741 nn_avgpool2d_kernel_backward = [ 1,0,0,0 ]; 22742 ); 22743 22744 nn_layer_avgpool2d_forward(L,IN) = ( 22745 L#_out = correlate(IN#_out, 22746 IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum, 22747 nn_avgpool2d_kernel_forward,2,2,1,1, 22748 1,0,1, 22749 0,0,0, 22750 0,0,0, 22751 L#_out_width - 1,L#_out_height - 1,L#_out_depth - 1, 22752 2,2,1); 22753 ); 22754 22755 nn_layer_avgpool2d_backward(L,IN) = ( 22756 IN#_deriv_out = correlate(L#_deriv_out, 22757 L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 22758 nn_avgpool2d_kernel_backward,2,2,1,1, 22759 0,0,1, 22760 0,0,0, 22761 0,0,0, 22762 IN#_out_width - 1,IN#_out_height - 1,IN#_out_depth - 1, 22763 0.5,0.5,1, 22764 1,1,1, 22765 0); 22766 ); 22767 22768 # batchnorm: Batch-normalization layer. 22769 #--------------------------------------- 22770 nn_layer_batchnorm_init_forward(L,IN) = ( 22771 const L#_ind = $L#; 22772 const L#_out_width = IN#_out_width; 22773 const L#_out_height = IN#_out_height; 22774 const L#_out_depth = IN#_out_depth; 22775 const L#_out_spectrum = IN#_out_spectrum; 22776 const L#_out_whd = L#_out_width*L#_out_height*L#_out_depth; 22777 L#_mu = crop(##L#_ind,0,0,1,h##L#_ind); 22778 L#_sigma = crop(##L#_ind,1,0,1,h##L#_ind); 22779 L#_gamma = crop(##L#_ind,2,0,1,h##L#_ind); 22780 L#_beta = crop(##L#_ind,3,0,1,h##L#_ind); 22781 L#_out = vector(#size(IN#_out)); 22782 L#_mu_whds = resize(L#_mu,size(L#_out),1); 22783 L#_sigma_whds = resize(sqrt(L#_sigma + 1e-9),size(L#_out),1); 22784 L#_gamma_whds = resize(L#_gamma,size(L#_out),1); 22785 L#_beta_whds = resize(L#_beta,size(L#_out),1); 22786 ); 22787 22788 nn_layer_batchnorm_forward(L,IN) = ( 22789 L#_xhat = IN#_out; 22790 L#_xhat-=L#_mu_whds; 22791 L#_xhat/=L#_sigma_whds; 22792 L#_out = L#_gamma_whds*L#_xhat; 22793 L#_out+=L#_beta_whds; 22794 ); 22795 22796 nn_layer_batchnorm_init_backward(L) = ( 22797 L#_threads_nbs = vector(#nn_nb_threads_max); 22798 L#_threads_mus = vector(#nn_nb_threads_max*L#_out_spectrum); 22799 L#_threads_sigmas = vector(#nn_nb_threads_max*L#_out_spectrum); 22800 L#_batch_deriv_gamma = vector(##L#_out_spectrum); 22801 L#_batch_deriv_beta = vector(##L#_out_spectrum); 22802 ); 22803 22804 nn_layer_batchnorm_backward(L,IN,learning_mode) = ( 22805 L#_nb1 = L#_threads_nbs[nn_thread]; 22806 L#_mu1 = L#_threads_mus[nn_thread*L#_out_spectrum,L#_out_spectrum]; 22807 L#_sigma1 = L#_threads_sigmas[nn_thread*L#_out_spectrum,L#_out_spectrum]; 22808 L#_mu2 = vector(##L#_out_spectrum); 22809 L#_sigma2 = vector(##L#_out_spectrum); 22810 repeat (L#_out_spectrum,_k, 22811 L#_feature = IN#_out[_k*L#_out_whd,L#_out_whd]; 22812 L#_mu2[_k] = avg(L#_feature); 22813 L#_sigma2[_k] = var(L#_feature); 22814 ); 22815 L#_nbc = ++L#_threads_nbs[nn_thread]; 22816 L#_in_mean = L#_mu1 + (L#_mu2 - L#_mu1)/L#_nbc; 22817 L#_in_variance = L#_sigma1 + (L#_sigma2 - L#_sigma1 + 22818 L#_nb1*(L#_mu1 - L#_in_mean)^2 + (L#_mu2 - L#_in_mean)^2)/L#_nbc; 22819 copy(L#_threads_mus[nn_thread*L#_out_spectrum],L#_in_mean); 22820 copy(L#_threads_sigmas[nn_thread*L#_out_spectrum],L#_in_variance); 22821 22822 learning_mode&1?( # Learn gamma 22823 L#_tmp = L#_deriv_out*L#_xhat; 22824 repeat(L#_out_spectrum,_k,L#_batch_deriv_gamma[_k]+=sum(L#_tmp[_k*L#_out_whd,L#_out_whd])); 22825 ); 22826 learning_mode&2?( # Learn beta 22827 repeat(L#_out_spectrum,_k,L#_batch_deriv_beta[_k]+=sum(L#_deriv_out[_k*L#_out_whd,L#_out_whd])); 22828 ); 22829 22830 IN#_deriv_out = L#_deriv_out*L#_gamma_whds; 22831 IN#_deriv_out/=L#_sigma_whds; 22832 ); 22833 22834 nn_layer_batchnorm_end_backward(L) = ( 22835 merge(L#_batch_deriv_gamma,+); 22836 merge(L#_batch_deriv_beta,+); 22837 L#_batch_deriv_gamma/=nn_nb_samples; 22838 L#_batch_deriv_beta/=nn_nb_samples; 22839 22840 merge(L#_threads_nbs,+); 22841 merge(L#_threads_mus,+); 22842 merge(L#_threads_sigmas,+); 22843 L#_nbc = 0; 22844 L#_in_mean = 0; 22845 L#_in_variance = 0; 22846 repeat (size(L#_threads_nbs),_k, 22847 L#_nb1 = L#_nbc; 22848 L#_mu1 = L#_in_mean; 22849 L#_sigma1 = L#_in_variance; 22850 L#_nb2 = L#_threads_nbs[_k]; 22851 L#_mu2 = L#_threads_mus[_k*size(L#_mu2),size(L#_mu2)]; 22852 L#_sigma2 = L#_threads_sigmas[_k*size(L#_mu2),size(L#_mu2)]; 22853 L#_nbc = L#_nb1 + L#_nb2; 22854 L#_in_mean = (L#_nb1*L#_mu1 + L#_nb2*L#_mu2)/L#_nbc; 22855 L#_in_variance = (L#_nb1*(L#_sigma1 + (L#_mu1 - L#_in_mean)^2) + 22856 L#_nb2*(L#_sigma2 + (L#_mu2 - L#_in_mean)^2))/L#_nbc; 22857 ); 22858 ); 22859 22860 nn_layer_batchnorm_update(L,learning_mode) = ( 22861 L#_momentum = lerp(1,1e-5,tanh(nn_iteration/100)); 22862 draw(##L#_ind,L#_in_mean,0,0,0,0,1,h##L#_ind,1,1,L#_momentum); 22863 draw(##L#_ind,L#_in_variance,1,0,0,0,1,h##L#_ind,1,1,L#_momentum); 22864 learning_mode&1?( 22865 nn_optimizer_update_layer(L#_gamma,L#_batch_deriv_gamma); 22866 draw(##L#_ind,L#_gamma,2,0,0,0,1,h##L#_ind); 22867 ); 22868 learning_mode&2?( 22869 nn_optimizer_update_layer(L#_beta,L#_batch_deriv_beta); 22870 draw(##L#_ind,L#_beta,3,0,0,0,1,h##L#_ind); 22871 ); 22872 ); 22873 22874 # clone: Duplicate input as two new outputs. 22875 #------------------------------------------- 22876 nn_layer_clone_init_forward(L0,L1,IN) = ( 22877 const L0#_out_width = IN#_out_width; 22878 const L0#_out_height = IN#_out_height; 22879 const L0#_out_depth = IN#_out_depth; 22880 const L0#_out_spectrum = IN#_out_spectrum; 22881 const L1#_out_width = IN#_out_width; 22882 const L1#_out_height = IN#_out_height; 22883 const L1#_out_depth = IN#_out_depth; 22884 const L1#_out_spectrum = IN#_out_spectrum; 22885 ); 22886 22887 nn_layer_clone_forward(L0,L1,IN) = ( 22888 L0#_out = IN#_out; 22889 L1#_out = IN#_out; 22890 ); 22891 22892 nn_layer_clone_backward(L0,L1,IN) = ( 22893 IN#_deriv_out = L0#_deriv_out + L1#_deriv_out; 22894 ); 22895 22896 # conv2d: 2D convolutional layer. 22897 #-------------------------------- 22898 nn_layer_conv2d_init_forward(L,IN,size,stride,dilation) = ( 22899 const L#_ind = $L#; 22900 const L#_out_width = max(1,int(IN#_out_width/stride)); 22901 const L#_out_height = max(1,int(IN#_out_height/stride)); 22902 const L#_out_depth = IN#_out_depth; 22903 const L#_out_spectrum = h##L#_ind; 22904 const L#_kernel_size = size; 22905 const L#_kernel_center = L#_kernel_size - 1 - int(L#_kernel_size/2); 22906 const L#_stride = stride; 22907 const L#_dilation = dilation; 22908 L#_weights = crop(##L#_ind,0,0,w##L#_ind - 1,h##L#_ind); 22909 L#_biases = crop(##L#_ind,w##L#_ind - 1,0,1,h##L#_ind); 22910 L#_out = vector(##L#_out_width*L#_out_height*L#_out_depth*h##L#_ind); 22911 ); 22912 22913 nn_layer_conv2d_forward(L,IN) = ( 22914 unref(_sizl); 22915 const _sizl = size(L#_out)/L#_out_spectrum; # Size of output plane 22916 L#_out = convolve(IN#_out, 22917 IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum, 22918 L#_weights, 22919 L#_kernel_size,L#_kernel_size,1,IN#_out_spectrum*L#_out_spectrum, 22920 1,0,2, 22921 L#_kernel_center,L#_kernel_center,0, 22922 0,0,0, 22923 L#_out_width - 1,L#_out_height - 1,L#_out_depth - 1, 22924 L#_stride,L#_stride,1, 22925 L#_dilation,L#_dilation,1); 22926 repeat (L#_out_spectrum,_l, 22927 copy(L#_out[_l*_sizl],L#_biases[_l],_sizl,1,0,-1); # Add biases 22928 ); 22929 ); 22930 22931 nn_layer_conv2d_init_backward(L,IN) = ( 22932 L#_batch_deriv_weights = vector(#size(L#_weights)); 22933 L#_batch_deriv_biases = vector(#size(L#_biases)); 22934 ); 22935 22936 nn_layer_conv2d_backward(L,IN) = ( 22937 unref(_sizk,_sizl,_sizw); 22938 const _sizk = size(IN#_out)/IN#_out_spectrum; # Size of input plane 22939 const _sizl = size(L#_out)/L#_out_spectrum; # Size of output plane 22940 const _sizw = L#_kernel_size^2; # Size of kernel^2 22941 22942 # Compute dL/dxk(x,y). 22943 L#_weights_mirrored = vector(#size(L#_weights)); 22944 repeat (IN#_out_spectrum,_k, 22945 repeat (L#_out_spectrum,_l, 22946 copy(L#_weights_mirrored[_k*L#_out_spectrum*_sizw + _l*_sizw + _sizw - 1], 22947 L#_weights[_l*(w##L#_ind - 1) + _k*_sizw],_sizw,-1,1); 22948 ); 22949 ); 22950 IN#_deriv_out = convolve(L#_deriv_out, 22951 L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 22952 L#_weights_mirrored, 22953 L#_kernel_size,L#_kernel_size,1,L#_out_spectrum*IN#_out_spectrum, 22954 0,0,2, 22955 L#_kernel_size - 1 - L#_kernel_center, 22956 L#_kernel_size - 1 - L#_kernel_center,0, 22957 0,0,0,IN#_out_width - 1,IN#_out_height - 1,IN#_out_depth - 1, 22958 1/L#_stride,1/L#_stride,1, 22959 L#_dilation/L#_stride,L#_dilation/L#_stride,1); 22960 22961 # Compute dL/dbl. 22962 L#_deriv_biases = vector(#size(L#_biases)); 22963 fill(L#_deriv_biases,_l,sum(L#_deriv_out[_l*_sizl,_sizl])); 22964 L#_batch_deriv_biases+=L#_deriv_biases; 22965 22966 # Compute dL/dwlk. 22967 L#_xk_mirrored = vector(#_sizk); 22968 L#_deriv_weights = vector(#size(L#_weights)); 22969 repeat (L#_out_spectrum,_l, 22970 repeat (IN#_out_spectrum,_k, 22971 copy(L#_xk_mirrored[_sizk - 1],IN#_out[_k*_sizk],_sizk,-1,1); 22972 L#_dwlk = convolve(L#_xk_mirrored, 22973 IN#_out_width,IN#_out_height,IN#_out_depth,1, 22974 L#_deriv_out[_l*_sizl,_sizl], 22975 L#_out_width,L#_out_height,L#_out_depth,1, 22976 0,0,1, 22977 1/L#_stride*(IN#_out_width - 1 - L#_dilation*L#_kernel_center), 22978 1/L#_stride*(IN#_out_height - 1 - L#_dilation*L#_kernel_center),0, 22979 0,0,0,L#_kernel_size - 1,L#_kernel_size - 1,0, 22980 L#_dilation,L#_dilation,1, 22981 L#_stride,L#_stride,1); 22982 copy(L#_deriv_weights[_l*(w##L#_ind - 1) + _k*_sizw],L#_dwlk,_sizw); 22983 ); 22984 ); 22985 L#_batch_deriv_weights+=L#_deriv_weights; 22986 ); 22987 22988 nn_layer_conv2d_end_backward(L) = ( 22989 merge(L#_batch_deriv_weights,+); 22990 merge(L#_batch_deriv_biases,+); 22991 L#_batch_deriv_weights/=nn_nb_samples; 22992 L#_batch_deriv_biases/=nn_nb_samples; 22993 ); 22994 22995 nn_layer_conv2d_update(L) = ( 22996 nn_optimizer_update_layer(L#_weights,L#_batch_deriv_weights); 22997 nn_optimizer_update_layer(L#_biases,L#_batch_deriv_biases); 22998 draw(##L#_ind,L#_weights,0,0,0,0,w##L#_ind - 1,h##L#_ind); 22999 draw(##L#_ind,L#_biases,w##L#_ind - 1,0,0,0,1,h##L#_ind); 23000 ); 23001 23002 # crop : Crop layer. 23003 #-------------------- 23004 nn_layer_crop_init_forward(L,IN,x0,y0,z0,x1,y1,z1) = ( 23005 const L#_out_width = abs(x1 - x0) + 1; 23006 const L#_out_height = abs(y1 - y0) + 1; 23007 const L#_out_depth = abs(z1 - z0) + 1; 23008 const L#_out_spectrum = IN#_out_spectrum; 23009 ); 23010 23011 nn_layer_crop_forward(L,IN,x0,y0,z0,x1,y1,z1) = ( 23012 L#_out = convolve(IN#_out,IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum, 23013 [1],1,1,1,1, 23014 0,0,1, 23015 0,0,0, 23016 x0,y0,z0, 23017 x1,y1,z1); 23018 ); 23019 23020 nn_layer_crop_backward(L,IN,x0,y0,z0,x1,y1,z1) = ( 23021 IN#_deriv_out = convolve(L#_deriv_out,L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 23022 [1],1,1,1,1, 23023 0,0,1, 23024 0,0,0, 23025 -x0,-y0,-z0, 23026 -x0 + IN#_out_width - 1,-y0 + IN#_out_height - 1,-z0 + IN#_out_depth - 1); 23027 ); 23028 23029 # fc: Fully-connected layer. 23030 #--------------------------- 23031 nn_layer_fc_init_forward(L) = ( 23032 const L#_ind = $L#; 23033 const L#_out_width = 1; 23034 const L#_out_height = 1; 23035 const L#_out_depth = 1; 23036 const L#_out_spectrum = h##L#_ind; 23037 L#_weights = crop(##L#_ind,0,0,w##L#_ind - 1,h##L#_ind); 23038 L#_biases = crop(##L#_ind,w##L#_ind - 1,0,1,h##L#_ind); 23039 ); 23040 23041 nn_layer_fc_forward(L,IN) = ( 23042 L#_out = mul(L#_weights,IN#_out); 23043 L#_out+=L#_biases; 23044 ); 23045 23046 nn_layer_fc_init_backward(L) = ( 23047 L#_batch_deriv_weights = vector(#size(L#_weights)); 23048 L#_batch_deriv_biases = vector(#size(L#_biases)); 23049 ); 23050 23051 nn_layer_fc_backward(L,IN) = ( 23052 IN#_deriv_out = mul(transpose(L#_weights,size(IN#_out)),L#_deriv_out); 23053 L#_deriv_weights = mul(L#_deriv_out,IN#_out,size(IN#_out)); 23054 L#_batch_deriv_weights+=L#_deriv_weights; 23055 L#_batch_deriv_biases+=L#_deriv_out; 23056 ); 23057 23058 nn_layer_fc_end_backward(L) = ( 23059 merge(L#_batch_deriv_weights,+); 23060 merge(L#_batch_deriv_biases,+); 23061 L#_batch_deriv_weights/=nn_nb_samples; 23062 L#_batch_deriv_biases/=nn_nb_samples; 23063 ); 23064 23065 nn_layer_fc_update(L) = ( 23066 nn_optimizer_update_layer(L#_weights,L#_batch_deriv_weights); 23067 nn_optimizer_update_layer(L#_biases,L#_batch_deriv_biases); 23068 draw(##L#_ind,L#_weights,0,0,0,0,w##L#_ind - 1,h##L#_ind); 23069 draw(##L#_ind,L#_biases,w##L#_ind - 1,0,0,0,1,h##L#_ind); 23070 ); 23071 23072 # input: Input image or vector data. 23073 #----------------------------------- 23074 nn_layer_input_init_forward(L,w,h,d,s) = ( 23075 const L#_out_width = w; 23076 const L#_out_height = h; 23077 const L#_out_depth = d; 23078 const L#_out_spectrum = s; 23079 ref(#L,L#_out); 23080 ); 23081 23082 # maxpool2d : 2D max pooling. 23083 #---------------------------- 23084 nn_layer_maxpool2d_init_forward(L,IN) = ( 23085 const L#_out_width = int(IN#_out_width/2); 23086 const L#_out_height = int(IN#_out_height/2); 23087 const L#_out_depth = IN#_out_depth; 23088 const L#_out_spectrum = IN#_out_spectrum; 23089 nn_avgpool2d_kernel_forward = [ 0.25,0.25,0.25,0.25 ]; 23090 nn_avgpool2d_kernel_backward = [ 1,0,0,0 ]; 23091 ); 23092 23093 nn_layer_maxpool2d_forward(L,IN) = ( 23094 L#_out = vector(##L#_out_width*L#_out_height*L#_out_depth*L#_out_spectrum); 23095 L#_from = vector(#size(L#_out)); 23096 repeat (size(L#_out),_l, 23097 _x = _l%L#_out_width; 23098 _y = int(_l/L#_out_width)%L#_out_height; 23099 _z = int(_l/(L#_out_width*L#_out_height))%L#_out_depth; 23100 _c = int(_l/(L#_out_width*L#_out_height*L#_out_depth)); 23101 _k = 2*_x + IN#_out_width*(2*_y + IN#_out_height*(_z + IN#_out_depth*_c)); 23102 _k+=arg0(argmax([ IN#_out[_k,2],IN#_out[_k + IN#_out_width,2] ]),0,1,IN#_out_width,IN#_out_width + 1); 23103 L#_from[_l] = _k; 23104 L#_out[_l] = IN#_out[_k]; 23105 ); 23106 ); 23107 23108 nn_layer_maxpool2d_backward(L,IN) = ( 23109 IN#_deriv_out = vector(#size(IN#_out),0); 23110 repeat (size(L#_out),_l, 23111 IN#_deriv_out[L#_from[_l]] = L#_deriv_out[_l]; 23112 ); 23113 ); 23114 23115 # nl: Non-linearity. 23116 #------------------- 23117 nn_layer_nl_init_forward(L,IN) = ( 23118 const L#_out_width = IN#_out_width; 23119 const L#_out_height = IN#_out_height; 23120 const L#_out_depth = IN#_out_depth; 23121 const L#_out_spectrum = IN#_out_spectrum; 23122 ); 23123 23124 nn_layer_nl_forward(L,IN,activation) = ( 23125 L#_out = IN#_out; 23126 nn_activate(L#_out,#activation); 23127 ); 23128 23129 nn_layer_nl_backward(L,IN,activation) = ( 23130 IN#_deriv_out = IN#_out; 23131 nn_activate(IN#_deriv_out,deriv_#activation); 23132 IN#_deriv_out*=L#_deriv_out; 23133 ); 23134 23135 # rename: Rename input. 23136 #---------------------- 23137 nn_layer_rename_init_forward(L,IN) = ( 23138 const L#_out_width = IN#_out_width; 23139 const L#_out_height = IN#_out_height; 23140 const L#_out_depth = IN#_out_depth; 23141 const L#_out_spectrum = IN#_out_spectrum; 23142 ref(IN#_out,L#_out); 23143 ); 23144 23145 nn_layer_rename_backward(L,IN) = ( 23146 ref(L#_deriv_out,IN#_deriv_out); 23147 ); 23148 23149 # reshape: Reshape input to output with compatible size. 23150 #------------------------------------------------------- 23151 nn_layer_reshape_init_forward(L,IN,w,h,d,s) = ( 23152 const L#_out_width = w; 23153 const L#_out_height = h; 23154 const L#_out_depth = d; 23155 const L#_out_spectrum = s; 23156 ref(IN#_out,L#_out); 23157 ); 23158 23159 nn_layer_reshape_init_backward(L,IN) = ( 23160 ref(L#_deriv_out,IN#_deriv_out); 23161 ); 23162 23163 # resize: Resize input. 23164 #---------------------- 23165 nn_layer_resize_init_forward(L,IN,w,h,d,s) = ( 23166 const L#_out_width = w; 23167 const L#_out_height = h; 23168 const L#_out_depth = d; 23169 const L#_out_spectrum = s; 23170 ); 23171 23172 nn_layer_resize_forward(L,IN,interpolation) = ( 23173 L#_out = resize(IN#_out, 23174 IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum, 23175 L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 23176 interpolation); 23177 ); 23178 23179 nn_layer_resize_backward(L,IN) = ( 23180 IN#_deriv_out = resize(L#_deriv_out, 23181 L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 23182 IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum, 23183 3); 23184 ); 23185 23186 # run: Transform input with G'MIC command. 23187 #----------------------------------------- 23188 nn_layer_run_init_forward(L,IN,command,w,h,d,s) = ( 23189 const L#_out_width = w; 23190 const L#_out_height = h; 23191 const L#_out_depth = d; 23192 const L#_out_spectrum = s; 23193 L#_varname = 'nn_#L#_out'; 23194 L#_pipeline = string('l[] $nn_#IN#_out ',command,' k. r ', 23195 L#_out_width,',',L#_out_height,',',L#_out_depth,',',L#_out_spectrum, 23196 ',3 k. store ',L#_varname,' endl'); 23197 ); 23198 23199 nn_layer_run_forward(L,IN) = ( 23200 critical( 23201 store(IN#_out,'nn_#IN#_out',IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum); 23202 run(L#_pipeline); 23203 L#_out = get(L#_varname,L#_out_width*L#_out_height*L#_out_depth*L#_out_spectrum); 23204 ); 23205 ); 23206 23207 nn_layer_run_backward(L,IN) = ( 23208 IN#_deriv_out = resize(L#_deriv_out, 23209 L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 23210 IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum, 23211 3); 23212 ); 23213 23214 # split: Split input as two outputs. 23215 #----------------------------------- 23216 nn_layer_split_init_forward(L0,L1,IN,nb_channels0) = ( 23217 const L0#_out_width = IN#_out_width; 23218 const L0#_out_height = IN#_out_height; 23219 const L0#_out_depth = IN#_out_depth; 23220 const L0#_out_spectrum = nb_channels0; 23221 const L1#_out_width = IN#_out_width; 23222 const L1#_out_height = IN#_out_height; 23223 const L1#_out_depth = IN#_out_depth; 23224 const L1#_out_spectrum = IN#_out_spectrum - nb_channels0; 23225 ); 23226 23227 nn_layer_split_forward(L0,L1,IN) = ( 23228 unref(_siz0); 23229 const siz0 = L0#_out_width*L0#_out_height*L0#_out_depth*L0#_out_spectrum; 23230 L0#_out = IN#_out[0,siz0]; 23231 L1#_out = IN#_out[siz0,L1#_out_width*L1#_out_height*L1#_out_depth*L1#_out_spectrum]; 23232 ); 23233 23234 nn_layer_split_backward(L0,L1,IN) = ( 23235 IN#_deriv_out = vector(#size(IN#_out)); 23236 copy(IN#_deriv_out,L0#_deriv_out,size(L0#_out)); 23237 copy(IN#_deriv_out[size(L0#_out)],L1#_deriv_out,size(L1#_out)); 23238 ); 23239 23240 #---------------- 23241 # Loss functions. 23242 #---------------- 23243 23244 # mse : Mean-squared error. 23245 #-------------------------- 23246 nn_loss_mse_init_backward(L) = ( 23247 L#_batch_out = 0; 23248 ); 23249 23250 nn_loss_mse_backward(L,IN,TRUTH) = ( 23251 IN#_deriv_out = 2*(IN#_out - TRUTH); 23252 L#_out = norm(IN#_deriv_out/2)^2/size(IN#_deriv_out); 23253 L#_batch_out+=L#_out; 23254 ); 23255 23256 nn_loss_mse_end_backward(L) = ( 23257 merge(L#_batch_out,+); 23258 L#_batch_out/=nn_nb_samples; 23259 L#_out = L#_batch_out; 23260 ); 23261 " 23262 23263#@cli nn_init 23264#@cli : Initialize a new network. 23265nn_init : 23266 e[^-1] "[nn_lib] Initialize new network." 23267 _nn_forward,_nn_backward,_nn_parameters= 23268 _nn_init="$0 " 23269 23270#@cli nn_check_layer : name 23271#@cli : Check that the layer with specified name exists in the network. 23272nn_check_layer : 23273 if !isvarname('"$1"') 23274 error[0--3] "nn_check_layer: Invalid layer name '$1'." 23275 elif narg($_nn_$1_out_size)!=4 23276 error[0--3] "nn_check_layer: Layer with name '$1' does not exist." 23277 fi 23278 23279#@cli nn_layer_input : name,width,_height,_depth,_spectrum 23280#@cli : Add an 'input' layer to the network. 23281#@cli : Default values: 'height=1', 'depth=1' and 'spectrum=1'. 23282nn_layer_input : check "isvarname('$1') && isint($2) && $2>0 && isint(${3=1}) && $3>0 && isint(${4=1}) && $4>0 && "\ 23283 "isint(${5=1}) && $5>0" 23284 e[^-1] "[nn_lib] Add input layer '$1', with size ($2,$3,$4,$5)." 23285 _nn_$1_out_size=$2,$3,$4,$5 23286 _nn_forward.="begin(nn_layer_input_init_forward($1,$2,$3,$4,$5));" 23287 _nn_init.="$0 $* " 23288 23289#@cli nn_layer_add : name,in0,in1 23290#@cli : Add an 'add' layer to the network. 23291nn_layer_add : nn_check_layer "$2" nn_check_layer "$3" check "isvarname('$1') && [$_nn_$2_out_size]==[$_nn_$3_out_size]" 23292 e[^-1] "[nn_lib] Add 'add' layer '$1', with inputs '$2' and '$3'." 23293 _nn_$1_out_size=$_nn_$2_out_size 23294 _nn_forward.="begin(nn_layer_add_init_forward($1,$2));"\ 23295 "nn_layer_add_forward($1,$2,$3);" 23296 _nn_backward..="nn_layer_add_backward($1,$2,$3);" 23297 _nn_init.="$0 $* " 23298 23299#@cli nn_layer_append : name,in0,in1 23300#@cli : Add an 'append' layer to the network. 23301nn_layer_append : check "isvarname('$1')" nn_check_layer "$2" nn_check_layer "$3" 23302 e[^-1] "[nn_lib] Add 'append' layer '$1', with inputs '$2' and '$3'." 23303 if s1=[$_nn_$2_out_size];s2=[$_nn_$3_out_size];s1[0,3]!=s2[0,3] 23304 error "nn_layer_append: Cannot append inputs $2("$_nn_$2_out_size") and $3("$_nn_$3_out_size") together." 23305 fi 23306 _nn_$1_out_size={[$_nn_$2_out_size]+[0,0,0,[$_nn_$3_out_size][3]]} 23307 _nn_forward.="begin(nn_layer_append_init_forward($1,$2,$3));"\ 23308 "nn_layer_append_forward($1,$2,$3);" 23309 _nn_backward..="nn_layer_append_backward($1,$2,$3);" 23310 _nn_init.="$0 $* " 23311 23312#@cli nn_layer_avgpool2d : name,in 23313#@cli : Add a 'avgpool2d' layer (2d average pooling) to the network. 23314nn_layer_avgpool2d : check "isvarname('$1')" nn_check_layer "$2" 23315 e[^-1] "[nn_lib] Add 'avgpool2d' layer '$1', with input '$2'." 23316 _nn_$1_out_size={s=[$_nn_$2_out_size];[int(s[0,2]/2),s[2,2]]} 23317 _nn_forward.="begin(nn_layer_avgpool2d_init_forward($1,$2));"\ 23318 "nn_layer_avgpool2d_forward($1,$2);" 23319 _nn_backward..="nn_layer_avgpool2d_backward($1,$2);" 23320 _nn_init.="$0 $* " 23321 23322#@cli nn_layer_batchnorm : name,in,_learning_mode. 23323#@cli : Add a 'batchnorm' layer to the network. 23324#@cli : 'learning_mode' can be { 0=learn no parameters | 1=learn gamma | 2=learn beta | 3=learn gamma and beta}. 23325#@cli : Default value: 'learning_mode=3'. 23326nn_layer_batchnorm : nn_check_layer "$2" check "isvarname('$1') && isint(${3=3}) && inrange($3,0,3)" 23327 s0,s1,s2,s3="no parameters","gamma-only","beta-only","gamma & beta" 23328 e[^-1] "[nn_lib] Add 'batchnorm' layer '$1' to the network, with input '$2' and learning mode '"${s$3}"'." 23329 _nn_$1_out_size=$_nn_$2_out_size 23330 if !isint($$1) 4,{[$_nn_$2_out_size][3]} f. 0,1,1,0 nm. $1 fi 23331 _nn_forward.="begin(nn_layer_batchnorm_init_forward($1,$2));"\ 23332 "nn_layer_batchnorm_forward($1,$2);" 23333 _nn_backward..="begin(nn_layer_batchnorm_init_backward($1));"\ 23334 "nn_layer_batchnorm_backward($1,$2,$3);"\ 23335 "end(nn_layer_batchnorm_end_backward($1));" 23336 _nn_update..="end(nn_layer_batchnorm_update($1,$3));" 23337 _nn_init.="$0 $* " 23338 _nn_parameters.="$1," 23339 23340#@cli nn_layer_clone : name0,name1,in 23341#@cli : Add a 'clone' layer to the network. 23342nn_layer_clone : nn_check_layer "$3" check "isvarname('$1') && isvarname('$2')" 23343 e[^-1] "[nn_lib] Add 'clone' layer with input '$3' and outputs '$1' and '$2'." 23344 _nn_$1_out_size=$_nn_$3_out_size 23345 _nn_$2_out_size=$_nn_$3_out_size 23346 _nn_forward.="begin(nn_layer_clone_init_forward($1,$2,$3));"\ 23347 "nn_layer_clone_forward($1,$2,$3);" 23348 _nn_backward..="nn_layer_clone_backward($1,$2,$3);" 23349 _nn_init.="$0 $* " 23350 23351#@cli nn_layer_conv2d : name,in,nb_channels>0,_kernel_size>0,_stride>0,_dilation,_is_updated={ 0 | 1 } 23352#@cli : Add a 'conv2d' layer (2D convolutional layer) to the network. 23353#@cli : Default values: 'kernel_size=3', 'stride=1', 'dilation=1' and 'is_updated=1'. 23354nn_layer_conv2d : nn_check_layer "$2" check "isvarname('$1') && isint($3) && $3>0 && isint(${4=3}) && $4>0 && "\ 23355 "${5=1}>0 && isbool(${7=1})" skip "${6=1}" 23356 e[^-1] "[nn_lib] Add 'conv2d' layer '$1', with input '$2', $3 channels, $4x$4 kernels, stride $5 and dilation $6." 23357 _nn_$1_out_size={s=[$_nn_$2_out_size];[max(1,int(s[0]/$5)),max(1,int(s[1]/$5)),s[2],$3]} 23358 if !isint($$1) {[$_nn_$2_out_size][3]*$4^2+1},$3 if $4>1 f. 4*g/(w-1) else f. 1 fi nm. $1 fi 23359 _nn_forward.="begin(nn_layer_conv2d_init_forward($1,$2,$4,$5,$6));"\ 23360 "nn_layer_conv2d_forward($1,$2);" 23361 _nn_backward..="begin(nn_layer_conv2d_init_backward($1,$2));"\ 23362 "nn_layer_conv2d_backward($1,$2);"\ 23363 "end(nn_layer_conv2d_end_backward($1));" 23364 if $7 _nn_update..="end(nn_layer_conv2d_update($1));" fi 23365 _nn_init.="$0 $* " 23366 _nn_parameters.="$1," 23367 23368#@cli nn_layer_conv2dbnnl : name,in,nb_channels>0,_kernel_size>0,_stride>0,_dilation>0,_activation,\ 23369# _is_updated={ 0 | 1 } 23370#@cli : Add a 'con2dbnnl' (2D convolutional layer followed by a batchnorm, then a non-linearity), to the network. 23371#@cli : Default values: 'kernel_size=3', 'stride=1', 'dilation=1', 'activation=leakyrelu' and 'is_updated=1'. 23372nn_layer_conv2dbnnl : nn_check_layer "$2" 23373 check "isvarname('$1') && isint($3) && $3>0 && isint(${4=3}) && $4>0 && ${5=1}>0 && "\ 23374 "isbool(${8=1})" 23375 skip "${6=1}","${7=leakyrelu}" 23376 e[^-1] "[nn_lib] Add 'conv2d+bn+nl' layer '$1', with input '$2', $3 channels, $4x$4 kernels, "\ 23377 "stride $5, dilation $6 and '$7' activation." 23378 nn_layer_conv2d $1_0,$2,$3,$4,$5,$6,$8 23379 nn_layer_batchnorm $1_1,$1_0 23380 nn_layer_nl $1,$1_1,$7 23381 23382#@cli nn_layer_conv2dnl : name,in,nb_channels>0,_kernel_size>0,_stride>0,_dilation>0,_activation,\ 23383# _is_updated={ 0 | 1 } 23384#@cli : Add a 'con2dnl' (2D convolutional layer followed by a non-linearity), to the network. 23385#@cli : Default values: 'kernel_size=3', 'stride=1', 'dilation=1', 'activation=leakyrelu' and 'is_updated=1'. 23386nn_layer_conv2dnl : nn_check_layer "$2" 23387 check "isvarname('$1') && isint($3) && $3>0 && isint(${4=3}) && $4>0 && ${5=1}>0 && isbool(${8=1})" 23388 skip "${6=1}","${7=leakyrelu}" 23389 e[^-1] "[nn_lib] Add 'conv2d+nl' layer '$1', with input '$2', $3 channels, $4x$4 kernels, "\ 23390 "stride $5, dilation $6 and '$7' activation." 23391 nn_layer_conv2d $1_0,$2,$3,$4,$5,$6,$8 23392 nn_layer_nl $1,$1_0,$7 23393 23394#@cli nn_layer_crop : name,in,x0,y0,z0,x1,y1,z1 23395#@cli : Add a 'crop' layer to the network. 23396nn_layer_crop : nn_check_layer "$2" check "min(isint([${3-8}]))" 23397 e[^1] "[nn_lin] Add 'crop' layer '$1', with input '$2' and coordinates (${3-5})-(${6-8})." 23398 cmin={vmin([${3-5}],[${6-8}])} 23399 cmax={vmax([${3-5}],[${6-8}])} 23400 _nn_$1_out_size={[[$cmax]-[$cmin]+1,arg(4,$_nn_$2_out_size)]} 23401 _nn_forward.="begin(nn_layer_crop_init_forward($1,$2,${3-8}));"\ 23402 "nn_layer_crop_forward($1,$2,${3-8});" 23403 _nn_backward..="nn_layer_crop_backward($1,$2,${3-8});" 23404 _nn_init.="$0 $* " 23405 23406#@cli nn_layer_fc : name,in,nb_channels>0,_is_updated={ 0 | 1 } 23407#@cli : Add a 'fc' layer (fully connected layer) to the network. 23408#@cli : Default value: 'is_updated=1'. 23409nn_layer_fc : nn_check_layer "$2" check "isvarname('$1') && isint($3) && $3>0 && isbool(${4=1})" 23410 e[^-1] "[nn_lib] Add 'fc' layer '$1', with input '$2' and $3 channels." 23411 _nn_$1_out_size=1,1,1,$3 23412 if !isint($$1) {prod($_nn_$2_out_size)+1},$3 f. 4*g/(w-1) nm. $1 fi 23413 _nn_forward.="begin(nn_layer_fc_init_forward($1));"\ 23414 "nn_layer_fc_forward($1,$2);" 23415 _nn_backward..="begin(nn_layer_fc_init_backward($1));"\ 23416 "nn_layer_fc_backward($1,$2);"\ 23417 "end(nn_layer_fc_end_backward($1));" 23418 if $4 _nn_update..="end(nn_layer_fc_update($1));" fi 23419 _nn_init.="$0 $* " 23420 _nn_parameters.="$1," 23421 23422#@cli nn_layer_fcbnnl : name,in,nb_neurons>0,_activation,_is_updated={ 0 | 1 } 23423#@cli : Add a 'fcbnnl' layer (fully connected layer followed by batchnorm, then a non-linearity), to the network. 23424#@cli : Default value: 'activation=leakyrelu' and 'is_updated=1'. 23425nn_layer_fcbnnl : nn_check_layer "$2" check "isvarname('$1') && isint($3) && $3>0 && isbool(${5=1})" skip ${4=leakyrelu} 23426 e[^-1] "[nn_lib] Add 'fc+bn+nl' layer '$1' to the network, with input '$2', $3 channels and '$4' activation." 23427 nn_layer_fc $1_0,$2,$3,$5 23428 nn_layer_batchnorm $1_1,$1_0 23429 nn_layer_nl $1,$1_1,$4 23430 23431#@cli nn_layer_fcnl : name,in,nb_neurons>0,_activation,_is_updated={ 0 | 1 } 23432#@cli : Add a 'fcnl' layer (fully connected layer followed by a non-linearity), to the network. 23433#@cli : Default value: 'activation=leakyrelu' and 'is_updated=1'. 23434nn_layer_fcnl : nn_check_layer "$2" check "isvarname('$1') && isint($3) && $3>0 && isbool(${5=1})" skip ${4=leakyrelu} 23435 e[^-1] "[nn_lib] Add 'fc+nl' layer '$1' to the network, with input '$2', $3 channels and '$4' activation." 23436 nn_layer_fc $1_0,$2,$3,$5 23437 nn_layer_nl $1,$1_0,$4 23438 23439#@cli nn_layer_maxpool2d : name,in 23440#@cli : Add a 'maxpool2d' layer (2d max pooling) to the network. 23441nn_layer_maxpool2d : nn_check_layer "$2" check "isvarname('$1')" 23442 e[^-1] "[nn_lib] Add 'maxpool2d' layer '$1', with input '$2'." 23443 _nn_$1_out_size={s=[$_nn_$2_out_size];[int(s[0,2]/2),s[2,2]]} 23444 _nn_forward.="begin(nn_layer_maxpool2d_init_forward($1,$2));"\ 23445 "nn_layer_maxpool2d_forward($1,$2);" 23446 _nn_backward..="nn_layer_maxpool2d_backward($1,$2);" 23447 _nn_init.="$0 $* " 23448 23449#@cli nn_layer_nl : name,in,_activation 23450#@cli : Add a 'nl' layer (non-linearity) to the network. 23451#@cli : Default value: 'activation=leakyrelu'. 23452nn_layer_nl : nn_check_layer "$2" check "isvarname('$1')" skip ${3=leakyrelu} 23453 e[^-1] "[nn_lib] Add 'nl' layer '$1', with input '$2' and '$3' activation." 23454 _nn_$1_out_size=$_nn_$2_out_size 23455 _nn_forward.="begin(nn_layer_nl_init_forward($1,$2));"\ 23456 "nn_layer_nl_forward($1,$2,$3);" 23457 _nn_backward..="nn_layer_nl_backward($1,$2,$3);" 23458 _nn_init.="$0 $* " 23459 23460#@cli nn_layer_rename : name,in 23461#@cli : Add a 'rename' layer to the network. 23462nn_layer_rename : nn_check_layer "$2" check "isvarname('$1')" 23463 e[^-1] "[nn_lib] Add 'rename' layer '$1', with input '$2'." 23464 _nn_$1_out_size=$_nn_$2_out_size 23465 _nn_forward.="begin(nn_layer_rename_init_forward($1,$2));" 23466 _nn_backward..="nn_layer_rename_backward($1,$2);" 23467 _nn_init.="$0 $* " 23468 23469#@cli nn_layer_reshape : name,in,width>0,height>0,depth>0,spectrum>0 23470#@cli : Add a 'reshape' layer to the network. 23471nn_layer_reshape : nn_check_layer "$2" check "isvarname('$1')" 23472 e[^-1] "[nn_lib] Add 'reshape' layer '$1', with input '$2' and size ($3,$4,$5,$6)." 23473 _nn_$1_out_size=$3,$4,$5,$6 23474 if prod($_nn_$1_out_size)!=prod($_nn_$2_out_size) 23475 error "nn_layer_reshape: Cannot reshape input ("$_nn_$2_out_size") to output ("$_nn_$1_out_size")." 23476 fi 23477 _nn_forward.="begin(nn_layer_reshape_init_forward($1,$2,$3,$4,$5,$6));" 23478 _nn_backward..="begin(nn_layer_reshape_init_backward($1,$2));" 23479 _nn_init.="$0 $* " 23480 23481#@cli nn_layer_resize : name,in,width[%]>0,_height[%]>0,_depth[%]>0,_spectrum[%]>0,_interpolation 23482#@cli : Add a 'resize' layer to the network. 23483#@cli : Default values: 'height=depth=spectrum=100%'. 23484nn_layer_resize : nn_check_layer "$2" check "isvarname('$1') && $3>0 && ${4=100%}>0 && ${5=100%}>0 && ${6=100%}>0" 23485 skip ${7=3} 23486 if ${"is_percent $3"} w={max(1,round([$_nn_$2_out_size][1]*$3))} else w=$3 fi 23487 if ${"is_percent $4"} h={max(1,round([$_nn_$2_out_size][1]*$4))} else h=$4 fi 23488 if ${"is_percent $5"} d={max(1,round([$_nn_$2_out_size][2]*$5))} else d=$5 fi 23489 if ${"is_percent $6"} s={max(1,round([$_nn_$2_out_size][3]*$6))} else s=$6 fi 23490 e[^-1] "[nn_lib] Add 'resize' layer '$1', with input '$2' and output size ("$w","$h","$d","$s")." 23491 _nn_$1_out_size=$w,$h,$d,$s 23492 _nn_forward.="begin(nn_layer_resize_init_forward($1,$2,"$w","$h","$d","$s"));"\ 23493 "nn_layer_resize_forward($1,$2,$7);" 23494 _nn_backward..="nn_layer_resize_backward($1,$2);" 23495 _nn_init.="$0 $* " 23496 23497#@cli nn_layer_run : name,in,"command",_width[%]>0,_height[%]>0,_depth[%]>0,_spectrum[%]>0 23498#@cli : Add a 'run' layer to the network. 23499#@cli : Default values: 'width=height=depth=spectrum=100%'. 23500nn_layer_run : nn_check_layer "$2" check "isvarname('$1') && ${4=100%}>0 && ${5=100%}>0 && ${6=100%}>0 && ${7=100%}>0" 23501 if ${"is_percent $4"} w={max(1,round([$_nn_$2_out_size][0]*$4))} else w=$4 fi 23502 if ${"is_percent $5"} h={max(1,round([$_nn_$2_out_size][1]*$5))} else h=$5 fi 23503 if ${"is_percent $6"} d={max(1,round([$_nn_$2_out_size][2]*$6))} else d=$6 fi 23504 if ${"is_percent $7"} s={max(1,round([$_nn_$2_out_size][3]*$7))} else s=$7 fi 23505 e[^-1] "[nn_lib] Add 'run' layer '$1', with input '$2', command '$3' and output size ("$w","$h","$d","$s")." 23506 _nn_$1_out_size=$w,$h,$d,$s 23507 _nn_forward.="begin(nn_layer_run_init_forward($1,$2,'$3',"$w","$h","$d","$s"));"\ 23508 "nn_layer_run_forward($1,$2);" 23509 _nn_backward..="nn_layer_run_backward($1,$2);" 23510 _nn_init.="$0 $* " 23511 23512#@cli nn_layer_split : name0,name1,in,nb_channels0 23513#@cli : Add a 'split' layer to the network. 23514nn_layer_split : nn_check_layer "$3" check "isvarname('$1') && isvarname('$2')" 23515 e[^-1] "[nn_lib] Add 'split' layer, with input '$3' and outputs '$1' and '$2'." 23516 _nn_$1_out_size={[[$_nn_$3_out_size][0,3],$4]} 23517 _nn_$2_out_size={[$_nn_$3_out_size]-[0,0,0,$4]} 23518 _nn_forward.="begin(nn_layer_split_init_forward($1,$2,$3,$4));"\ 23519 "nn_layer_split_forward($1,$2,$3);" 23520 _nn_backward..="nn_layer_split_backward($1,$2,$3);" 23521 _nn_init.="$0 $* " 23522 23523#@cli nn_loss_mse : name,in,ground_truth 23524#@cli : Add a 'mse' loss to the network. 23525#@cli : Default value: 'learning_rate=1e-6' and 'learning_rate_scheduler=adaptive'. 23526nn_loss_mse : nn_check_layer "$2" check "isvarname('$1') && isvarname('$3')" 23527 e[^-1] "[nn_lib] Add MSE loss '$1', with input '$2' and ground truth '$3'." 23528 _nn_$1_out_size=1,1,1,1 23529 _nn_backward..="begin(nn_loss_mse_init_backward($1));"\ 23530 "nn_loss_mse_backward(${1-3});"\ 23531 "end(nn_loss_mse_end_backward($1));" 23532 _nn_init.="$0 $* " 23533 23534#@cli nn_trainer : name,loss,_learning_rate>0,_optimizer,_scheduler 23535#@cli : Add a network trainer to the network. 23536#@cli : 'optimizer' can be { sgd | rmsprop | adam | adamax }. 23537#@cli : 'scheduler' can be { constant | linear | exponential | adaptive }. 23538#@cli : Default value: 'learning_rate=1e-6', 'optimizer=adam' and 'scheduler=constant'. 23539nn_trainer : nn_check_layer "$2" 23540 check "isvarname('$1') && ${3=1e-6}>0 && isvarname('${4=adam}') && isvarname('${5=constant}')" 23541 e[^-1] "[nn_lib] Add trainer '$1' for loss '$2', with learning rate '$3', $4 optimizer and $5 scheduler." 23542 _nn_$1_out_size=0,0,0,0 23543 if !isint($$1) 23544 # (iteration,learning_rate,initial_learning_rate,previous_loss,best_loss; 23545 # {optimizer variables}; 23546 # {scheduler variables}) 23547 l[] (0,$3,$3,inf,inf) _nn_optimizer_$4 _nn_scheduler_$5 a y nm $1 endl 23548 fi 23549 o_sgd,o_rmsprop,o_adam,o_adamax=0,1,2,3 23550 s_constant,s_linear,s_exponential,s_adaptive=0,1,2,3 23551 _nn_backward..="begin(nn_trainer_init_backward($1,$2,"${o_$4},${s_$5}"));" 23552 _nn_update.="end(nn_trainer_update($1,$2));" # <- Keep this as the last thing done in an 'end()' bloc! 23553 _nn_init.="$0 $* " 23554 _nn_parameters.="$1," 23555 23556_nn_optimizer_sgd : 1 23557_nn_optimizer_rmsprop : 1 23558_nn_optimizer_adam : 1 23559_nn_optimizer_adamax : 1 23560 23561_nn_scheduler_constant : 1 23562_nn_scheduler_linear : 1 23563_nn_scheduler_exponential : 1 23564_nn_scheduler_adaptive : (0,0,0) 23565 23566#@cli nn_load : 'filename.gmz' 23567#@cli : Load and initialize network saved as a .gmz file. 23568#@cli : Neural network files can be only loaded in .gmz format. 23569nn_load : check "s=['$1']; find(s,'.gmz')==size(s) - 4" 23570 e[^-1] "[nn_lib] Load network from file '$1'." 23571 i "$1" run {t} rm. 23572 23573#@cli nn_save : 'filename.gmz' 23574#@cli : Save current network as a .gmz file. 23575#@cli : Neural network files can be only saved in .gmz format. 23576nn_save : check "s=['$1']; find(s,'.gmz')==size(s) - 4" 23577 e[^-1] "[nn_lib] Save current network as file '$1'." 23578 ('$_nn_parameters') autocrop. {','} sel={t} rm. 23579 ('$_nn_init') autocrop. {'" "'} 23580 nm. _nn_init 23581 o[$sel,-1] "$1" 23582 rm. 23583 23584#---------------------------------- 23585# 23586#@cli :: Arrays, Tiles and Frames 23587# 23588#---------------------------------- 23589 23590#@cli array : M>0,_N>0,_expand_type={ 0=min | 1=max | 2=all } 23591#@cli : Create MxN array from selected images. 23592#@cli : Default values: 'N=M' and 'expand_type=0'. 23593#@cli : $ image.jpg array 3,2,2 23594array : check "isint($1) && $1>0 && isint(${2=$1}) && $2>0" skip ${3=0} 23595 e[^-1] "Create $1x$2 array from image$?, with expand type $3." 23596 r0={100/max($1,$2)} r1={100/min($1,$2)} r2=100 23597 r ${r$3}%,${r$3}%,1,100%,2 r {$1*100}%,{$2*100}%,1,100%,0,2 23598 23599#@cli array_fade : M>0,_N>0,0<=_fade_start<=100,0<=_fade_end<=100,_expand_type={0=min | 1=max | 2=all} 23600#@cli : Create MxN array from selected images. 23601#@cli : Default values: 'N=M', 'fade_start=60', 'fade_end=90' and 'expand_type=1'. 23602#@cli : $ image.jpg array_fade 3,2 23603array_fade : skip ${2=$1},${3=60},${4=90},${5=1} 23604 e[^-1] "Create $1x$2 array of ($3%,$4%) faded tiles from image$?, with expand type $5." 23605 repeat $! l[$>] . shift.. {round(w/2)},{round(h/2)},1,1,2 fade_diamond $3,$4 endl done 23606 array $1,$2,$5 23607 23608#@cli array_mirror : N>=0,_dir={ 0=x | 1=y | 2=xy | 3=tri-xy },_expand_type={ 0 | 1 } 23609#@cli : Create 2^Nx2^N array from selected images. 23610#@cli : Default values: 'dir=2' and 'expand_type=0'. 23611#@cli : $ image.jpg array_mirror 2 23612array_mirror : skip ${2=2},${3=0} 23613 e[^-1] "Create a 2^$1x2^$1 mirrored-array from image$?, with expand type $2." 23614 repeat $1 23615 if $3==0 23616 if $2>=3 r 33%,33%,100%,100%,2 23617 else r 50%,50%,100%,100%,2 23618 fi 23619 fi 23620 repeat $! l[$>] 23621 if $2==0 +mirror x a x 23622 elif $2==1 +mirror y a y 23623 else +mirror x a x +mirror y a y if $2==3 r 150%,150%,1,100%,0,2,1,1 fi 23624 fi 23625 endl done 23626 done 23627 23628#@cli array_random : Ms>0,_Ns>0,_Md>0,_Nd>0 23629#@cli : Create MdxNd array of tiles from selected MsxNs source arrays. 23630#@cli : Default values: 'Ns=Ms', 'Md=Ms' and 'Nd=Ns'. 23631#@cli : $ image.jpg +array_random 8,8,15,10 23632array_random : skip ${2=$1},${3=$1},${4=$2} 23633 e[^-1] "Create $3x$4 array of tiles from $1x$2 array$?." 23634 repeat $! l[$>] nm={0,n} 23635 split_tiles $1,$2 23636 repeat $3 repeat $4 [{u($1*$2-1)}] done done 23637 rm[0-{$1*$2-1}] append_tiles $3,$4 23638 nm $nm endl done 23639 23640#@cli frame : eq. to 'frame_xy'. 23641frame : skip ${2=$1}>=0,${3=255},${4=$3},${5=$4},${6=255} 23642 _gmic_s="$?" v + _frame_xy ${1--1} 23643 23644#@cli frame_blur : _sharpness>0,_size>=0,_smoothness,_shading,_blur 23645#@cli : Draw RGBA-colored round frame in selected images. 23646#@cli : Default values: 'sharpness=10', 'size=30', 'smoothness=0', 'shading=1' and 'blur=3%'. 23647#@cli : $ image.jpg frame_blur 3,30,8,10% 23648frame_blur : skip ${1=10},${2=30},${3=0},${4=1},${5=3%} 23649 e[^-1] "Draw round frame on image$?, with sharpness $1, size $2, smoothness $3, shading $4 and blur $5." 23650 to_rgba repeat $! l[$>] nm={0,n} 23651 100%,100%,1,1,"-(abs(x/w-0.5)^$1 + abs(y/h-0.5)^$1)^(1/$1)" >=. $2% 23652 if $4 distance. 1 n. 0,1 *. -1 +. 1 ^. {1/$4} fi 23653 b. $3 +b.. $5 mv. -3 blend_fade[0,1] . rm. 23654 nm $nm endl done 23655 23656#@cli frame_cube : _depth>=0,_centering_x,_centering_y,_left_side={0=normal | 1=mirror-x | 2=mirror-y | 3=mirror-xy},\ 23657# _right_side,_lower_side,_upper_side 23658#@cli : Insert 3D frames in selected images. 23659#@cli : Default values: 'depth=1', 'centering_x=centering_y=0' and 'left_side=right_side,lower_side=upper_side=0'. 23660#@cli : $ image.jpg frame_cube , 23661frame_cube : check "${1=1}>=0" skip ${2=0},${3=0},${4=0},${5=0},${6=0},${7=0} 23662 e[^-1] "Insert 3D frame in image$?, with depth $1, centering point ($2,$3) and orientations (${4--1})." 23663 repeat $! l[$>] nm={0,n} split_opacity 23664 if $!==2 frame_cube ${1--1} a c # Manage image with alpha-channel. 23665 else 23666 m={max(w,h)} w={w} h={h} s={s} 23667 imageplane3d c3d /3d. $w,$h,1 23668 +_frame_cube[0] $4 r3d. 0,1,0,-90 +3d. -0.5,0,-0.5 # Left side. 23669 +_frame_cube[0] $5 r3d. 0,1,0,90 +3d. 0.5,0,-0.5 # Right side. 23670 +_frame_cube[0] $6 r3d. 1,0,0,-90 +3d. 0,0.5,-0.5 # Lower side. 23671 +_frame_cube[0] $7 r3d. 1,0,0,90 +3d. 0,-0.5,-0.5 # Upper side. 23672 +3d 0,0,1 +3d *3d $w,$h,$m # Append sides together. 23673 f=1000 23674 cx=$2*$w/2*($f+$m*$1)/$f 23675 cy=$3*$h/2*($f+$m*$1)/$f 23676 s3d r[2] 3,{{2,h}/3},1,1,-1 23677 f[2] "if(i(2,y)<0.5,i,i+if(x==0,"$cx",if(x==1,"$cy",($1-1)*"$m")))" 23678 y[2] a y 23679 *3d 2 {2*$w},{2*$h},1,$s f3d {2*$f} 23680 j3d. ..,50%,50%,0,1,2,0,0 rm.. 23681 r $w,$h,1,100%,2 23682 fi 23683 nm $nm endl done 23684 23685_frame_cube : 23686 if $1==1 r3d. 0,1,0,180 rv3d. 23687 elif $1==2 r3d. 1,0,0,180 rv3d. 23688 elif $1==3 r3d. 0,0,1,180 23689 fi 23690 23691#@cli frame_fuzzy : size_x[%]>=0,_size_y[%]>=0,_fuzzyness>=0,_smoothness[%]>=0,_R,_G,_B,_A 23692#@cli : Draw RGBA-colored fuzzy frame in selected images. 23693#@cli : Default values: 'size_y=size_x', 'fuzzyness=5', 'smoothness=1' and 'R=G=B=A=255'. 23694#@cli : $ image.jpg frame_fuzzy 20 23695frame_fuzzy : skip ${2=$1},${3=5},${4=1},${5=255},${6=$5},${7=$6},${8=255} 23696 e[^-1] "Draw $1x$2 fuzzy frame on image$?, with fuzzyness $3, smoothness $4 and RGBA color ($5,$6,$7,$8)." 23697 to_rgba repeat $! l[$>] 23698 100%,100%,1,1,1 23699 padx={if(${"is_percent $1"},$1*(w-1)/2,$1)} 23700 pady={if(${"is_percent $2"},$2*(h-1)/2,$2)} 23701 rectangle. $padx,$pady,{w-1-$padx},{h-1-$pady} 23702 spread. $3 b. $4 100%,100%,1,4 fc. ${5-8} 23703 j[0] [2],0,0,0,0,1,[1] k[0] 23704 endl done 23705 23706#@cli frame_painting : _size[%]>=0,0<=_contrast<=1,_profile_smoothness[%]>=0,_R,_G,_B,_vignette_size[%]>=0,\ 23707# _vignette_contrast>=0,_defects_contrast>=0,0<=_defects_density<=100,_defects_size>=0,_defects_smoothness[%]>=0,\ 23708# _serial_number 23709#@cli : Add a painting frame to selected images. 23710#@cli : Default values: 'size=10%', 'contrast=0.4', 'profile_smoothness=6%', 'R=225', 'G=200', 'B=120', \ 23711# 'vignette_size=2%', 'vignette_contrast=400', 'defects_contrast=50', 'defects_density=10', 'defects_size=1', \ 23712# 'defects_smoothness=0.5%' and 'serial_number=123456789'. 23713#@cli : $ image.jpg frame_painting , 23714frame_painting : 23715 check "${1=10%}>=0 && ${2=0.4}>=0 && $2<=1 && ${3=6%}>=0 && ${7=2%}>=0 && ${8=400}>=0 && ${9=50}>=0 && 23716 ${10=10}>=0 && $10<=100 && ${11=1}>=0 && ${12=0.5%}>=0" 23717 skip ${4=225},${5=200},${6=120},${13=123456789} 23718 e[^-1] "Add painting frame to image$?, with size $1, contrast $2, profile smoothness $3, color (${4-6}), 23719 vignette size $7, vignette strength $8, defects contrast $9, defects density $10, defects size $11, 23720 defects smoothness $12 and serial number $13." 23721 if !$1 return fi 23722 repeat $! l[$>] 23723 $1,$1 s={max(w,h)} rm. # Determine size of the frame 23724 ('${dec2bin\ $13}') -. {'0'} r. $s # Generate frame profile from serial number 23725 transpose. b. $3 n. {1-$2},{1+$2} 23726 +r. {{-2,w}+2*$s},100%,1,1 # Upper frame 23727 +mirror. y # Lower frame 23728 mv... $! transpose. r. 100%,{-4,h+2*$s},1,1 # Left frame 23729 +mirror. x # Right frame 23730 ...,...,1,1,1 23731 polygon. 3,0,0,{$s-1},{$s-1},0,{$s-1},1,0 23732 polygon. 3,100%,0,{w-$s},100%,100%,100%,1,0 # Upper/lower mask 23733 ..,..,1,1,1 23734 polygon. 3,1,0,100%,{$s-2},100%,0 23735 polygon. 3,1,100%,100%,{h-$s+1},100%,100%,1,0 # Left/right mask 23736 _frame_painting[-6--3] ${4-6},${9-12} # Add colors + defects 23737 23738 # Build full frame picture. 23739 {-7,w+2*$s},{-7,h+2*$s},1,3 23740 j. [-7],0,0,0,0,1,...,1 rm[-7] mirror... y 23741 j. [-6],0,{h-$s},0,0,1,...,1 rm[-6,-3] 23742 j. [-4],0,0,0,0,1,..,1 rm[-4] mirror.. x 23743 j. ...,{w-$s},0,0,0,1,..,1 rm[-3,-2] 23744 ..,..,1,1,-255 r. ..,..,1,1,0,0,0.5,0.5 +. 255 +b. $7 n. 0,$8 max[-2,-1] c. 0,255 # Frame opacity. 23745 a[-2--1] c 23746 r.. .,.,1,100%,0,0,0.5,0.5 blend alpha # Insert initial image into frame picture. 23747 endl done 23748 23749_frame_painting : # Add color + texture to each frame part. 23750 repeat $! l[$>] 23751 +*. $2 +*.. $3 *... $1 a[-3--1] c 23752 100%,100% 23753 i=0 do rand. 0,1 remove_pixels. {100-$5}% b. $6 >=. 50% i+=1 while "m=$5/200;(ia<m-0.2 || ia>m+0.2) && "$i"<10" 23754 b. $7 g. +[-2,-1] n. -$4,$4 23755 +[-2,-1] c. 0,255 23756 endl done 23757 23758#@cli frame_pattern : M>=3,_constrain_size={ 0 | 1 } : M>=3,_[frame_image],_constrain_size={ 0 | 1 } 23759#@cli : Insert selected pattern frame in selected images. 23760#@cli : Default values: 'pattern=0' and 'constrain_size=0'. 23761#@cli : $ image.jpg frame_pattern 8 23762frame_pattern : check $1>=3 skip "${2=0},${3=}" 23763 to_colormode 0 23764 if ${"is_image_arg $2"} # Frame from specified image. 23765 e[^-1] "Insert $1x$1 pattern frame on image$?, using frame image$2." 23766 pass$2 0 repeat $!-1 l[$>,-1] 23767 wh={0,w},{0,h} 23768 +r[1] {0,max(1,w/($1-2))},{0,max(1,h/($1-2))},1,100%,2 23769 r[0] {{0,w}+2*w},{{0,h}+2*h},1,100%,0,0,0.5,0.5 23770 [-1]x{$1+2} a[{-$1-2}--1] x j[0] .,0,0 j[0] .,0,{{0,h}-1-h} rm. 23771 [-1]x{$1+1} a[{-$1-2}--1] y j[0] .,0,0 j[0] .,{{0,w}-1-w} rm. 23772 if $3 r[0] $wh,1,100%,2 fi 23773 endl done rm. 23774 else # Self-frame. 23775 e[^-1] "Insert $1x$1 self-pattern frame on image$?." 23776 repeat $! l[$>] 23777 wh={w},{h} 23778 +r {max(1,w/($1-2))},{max(1,h/($1-2))},1,100%,2 r.. {$1*w},{$1*h},1,100%,0,0,0.5,0.5 23779 [-1]x{$1+2} a[{-$1-2}--1] x j... .,0,0 j... .,0,{{-3,h}-1-h} rm. 23780 [-1]x{$1+1} a[{-$1-2}--1] y j.. .,0,0 j.. .,{{-2,w}-1-w} rm. 23781 if $3 r $wh,1,100%,2 fi 23782 endl done 23783 fi 23784 23785#@cli frame_round : _sharpness>0,_size>=0,_smoothness,_shading,_R,_G,_B,_A 23786#@cli : Draw RGBA-colored round frame in selected images. 23787#@cli : Default values: 'sharpness=10', 'size=10', 'smoothness=0', 'shading=0' and 'R=G=B=A=255'. 23788#@cli : $ image.jpg frame_round 10 23789frame_round : skip ${1=10},${2=10},${3=0},${4=0},${5=255},${6=$5},${7=$6},${8=255} 23790 e[^-1] "Draw round frame on image$?, with sharpness $1, size $2, smoothness $3, shading $4 and 23791 RGBA color ($5,$6,$7,$8)." 23792 to_rgba repeat $! l[$>] nm={0,n} 23793 100%,100%,1,1,"-(abs(x/w-0.5)^$1 + abs(y/h-0.5)^$1)^(1/$1)" >=. $2% 23794 if $4 distance. 1 n. 0,1 *. -1 +. 1 ^. {1/$4} fi 23795 b. $3 i... 100%,100%,1,4 fc... $5,$6,$7,$8 blend_fade[0,1] . rm. 23796 nm $nm endl done 23797 23798#@cli frame_seamless : frame_size>=0,_patch_size>0,_blend_size>=0,\ 23799# _frame_direction={ 0=inner (preserve image size) | 1=outer } 23800#@cli : Insert frame in selected images, so that tiling the resulting image makes less visible seams. 23801#@cli : Default values: 'patch_size=7', 'blend_size=5' and 'frame_direction=1'. 23802#@cli : $ image.jpg +frame_seamless 30 array 2,2 23803frame_seamless : check "$1>=0 && isint(${2=7}) && $2>0 && isint(${3=5}) && $3>=0" skip ${4=1} 23804 s0="inner" s1="outer" 23805 e[^-1] "Insert "${s{!!$4}}" seamless frame in image$?, with size $1, patch size $2 and blend size $3." 23806 repeat $! l[$>] 23807 w2={round(w/2)} h2={round(h/2)} 23808 w4={round(w/4)} h4={round(h/4)} 23809 if !$4 r {max(1,w-$1)},{max(1,h-$1)},1,100%,0,0,0.5,0.5 fi 23810 100%,100%,1,1,-1 r[-2,-1] {w+$1},{h+$1},1,100%,0,0,0.5,0.5 n. 0,1 23811 shift -$w2,-$h2,0,0,2 23812 inpaint_matchpatch.. [1],0,$2,10,$3 23813 rectangle. $1,$1,{w-1-$1},{h-1-$1} 23814 shift -$w4,-$h4,0,0,2 23815 inpaint_matchpatch.. [1],0,$2,10,$3 23816 rm. 23817 shift {$w4+$w2},{$h4+$h2},0,0,2 23818 endl done 23819 23820#@cli frame_x : size_x[%],_col1,...,_colN 23821#@cli : Insert colored frame along the x-axis in selected images. 23822#@cli : Default values: 'col1=col2=col3=255' and 'col4=255'. 23823#@cli : $ image.jpg frame_x 20,255,0,255 23824frame_x : skip ${2=255},${3=$2},${4=$3},${5=255} 23825 e[^-1] "Insert $1 outer frame in image$? along the x-axis, with color (${2--1})." 23826 _frame $1,0,0,${2--1} 23827 23828#@cli frame_xy : size_x[%],_size_y[%],_col1,...,_colN 23829#@cli : Insert colored frame along the x-axis in selected images. 23830#@cli : Default values: 'size_y=size_x', 'col1=col2=col3=255' and 'col4=255'. 23831#@cli : (eq. to 'frame'). 23832#@cli : $ image.jpg frame_xy 1,1,0 frame_xy 20,10,255,0,255 23833frame_xy : skip ${2=$1},${3=255},${4=$3},${5=$4},${6=255} 23834 _gmic_s="$?" v + _$0 ${1--1} 23835 23836_frame_xy : 23837 e[0--3] "Insert $1x$2 outer frame in image"$_gmic_s" along the xy-axes, with color (${3--1})." 23838 _frame $1,$2,0,${3--1} 23839 23840#@cli frame_xyz : size_x[%],_size_y[%],_size_z[%]_col1,...,_colN 23841#@cli : Insert colored frame along the x-axis in selected images. 23842#@cli : Default values: 'size_y=size_x=size_z', 'col1=col2=col3=255' and 'col4=255'. 23843frame_xyz : skip ${2=$1},${3=$2},${4=255},${5=$4},${6=$5},${7=255} 23844 e[^-1] "Insert $1x$2x$3 outer frame in image$? along the xyz-axes, with color (${4--1})." 23845 _frame $1,$2,$3,${4--1} 23846 23847#@cli frame_y : size_y[%],_col1,...,_colN 23848#@cli : Insert colored frame along the y-axis in selected images. 23849#@cli : Default values: 'col1=col2=col3=255' and 'col4=255'. 23850#@cli : $ image.jpg frame_y 20,255,0,255 23851frame_y : skip ${2=255},${3=$2},${4=$3},${5=255} 23852 e[^-1] "Insert $1 outer frame in image$? along the y-axis, with color (${2--1})." 23853 _frame 0,$1,0,${2--1} 23854 23855_frame : 23856 repeat $! l[$>] 23857 nm={0,n} 23858 w={round($1*if(${is_percent\ $1},w,1))} 23859 h={round($2*if(${is_percent\ $2},h,1))} 23860 d={round($3*if(${is_percent\ $3},d,1))} 23861 {w+2*$w},{h+2*$h},{d+2*$d},100% fc[1] ${4--1} 23862 j[1] [0],$w,$h,$d rm[0] nm $nm 23863 endl done 23864 23865#@cli img2ascii : _charset,_analysis_scale>0,_analysis_smoothness[%]>=0,_synthesis_scale>0,_output_ascii_filename 23866#@cli : Render selected images as binary ascii art. 23867#@cli : This command returns the corresponding the list of widths and heights (expressed as a number of characters) 23868#@cli : for each selected image. 23869#@cli : Default values: 'charset=[ascii charset]', 'analysis_scale=16', 'analysis_smoothness=20%', \ 23870# 'synthesis_scale=16' and '_output_ascii_filename=[undefined]'. 23871#@cli : $ image.jpg img2ascii , 23872img2ascii : check "${2=16}>0 && ${3=20%}>=0 && ${4=16}>0" 23873 skip "${1= !\042#$%&\047()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\133\\\135^_\140abcdefghijk"\ 23874 "lmnopqrstuvwxyz\173|\174~}","${5=}" 23875 e[^-1] "Render image$? as binary ascii art, with charset '$1', analysis scale $2, analysis smoothness $3, 23876 synthesis scale $4 and output ascii filename '$5'." 23877 is_multi={$!>1} 23878 23879 # Generate dictionaries for image analysis and synthesis. 23880 l[] 23881 ('"$1"') repeat w 23882 C={`92`}${dec2oct\ {0,@$>}} 23883 0 t. $C,0,0,$2,1,1 23884 0 t. $C,0,0,$4,1,1 23885 done rm[0] 23886 = -1 = -1,0,100% autocrop = 0 = 0,0,100% 23887 l[0--2:2] r {${-max_w}+1},100%,1,1,0,0,0.5 b $3 n 0,255 a z endl 23888 l[1--1] r {${-max_w}+1},100%,1,1,0,0,0.5 a z endl 23889 endl 23890 w={-2,w} h={-2,h} 23891 23892 # Transform selected images to ascii art. 23893 repeat $!-2 l[$>,-2,-1] 23894 luminance[0] n[0] 0,255 23895 nw={0,round(w/$w,1,1)} 23896 nh={0,round(h/$h,1,1)} 23897 if $> list_wh=$list_wh,$nw,$nh else list_wh=$nw,$nh fi 23898 23899 s[0] y,-$h s[0--3] x,-$w r[0--3] $w,$h,1,1,0,0 23900 repeat $!-2 l[$>,-2,-1] 23901 rprogress {$>*100/($!-2)} 23902 ri[0] [1] -[0] [1] sqr[0] r[0] 1,1,100%,1,2 y[0] 23903 C={0,ym} rm[0] 23904 +slices[1] $C mv. 0 23905 if narg("$5") +f[0] $C a[0,-1] c fi 23906 endl done 23907 append_tiles[0--2] $nw,$nh 23908 23909 if narg("$5") s[0] c l[1] # Export as text file. 23910 r $nw,$nh,1,1,1 23911 ('"$1"') map[0] . k[0] 23912 s y i[1-$!] ('\n') 23913 a x 23914 if $is_multi filename=${filename\ "$5",$>} else filename="$5" fi 23915 ot $filename rm 23916 endl fi 23917 23918 endl done 23919 rm[-2,-1] u $list_wh 23920 23921#@cli imagegrid : M>0,_N>0 23922#@cli : Create MxN image grid from selected images. 23923#@cli : Default value: 'N=M'. 23924#@cli : $ image.jpg imagegrid 16 23925imagegrid : skip ${2=$1} 23926 e[^-1] "Create $1x$2 image grid from image$?." 23927 repeat $! l[$>] 23928 ({w},{h}) ($1,$2) /[-2,-1] round. 1 r.. {^},..,..,2 rm. 23929 ({w},{h}) ($1,$2) *[-2,-1] r.. {^},..,..,2 rm. 23930 $1,$2,1,.,1 shift. 1,1 ri. ..,0,2 * 23931 endl done 23932 23933#@cli imagegrid_hexagonal : _resolution>0,0<=_outline<=1 23934#@cli : Create hexagonal grids from selected images. 23935#@cli : Default values: 'resolution=32', 'outline=0.1' and 'is_antialiased=1'. 23936#@cli : $ image.jpg imagegrid_hexagonal 24 23937imagegrid_hexagonal : check "isint(${1=32}) && $1>0 && ${2=0.1}>=0 && $2<=1" 23938 e[^-1] "Create hexagonal grid(s) from image$?, with resolution $1 and outline $2." 23939 repeat $! l[$>] 23940 23941 # Generate hexagonal grid. 23942 l[] 23943 # Generate hexagon. 23944 ({'CImg3d'},6,6) 23945 (0;{2*pi}) -. {pi/2} r. 1,7,1,1,3 +sin. cos.. a[-2,-1] x rows. 0,5 z. 0,2 23946 2,6,1,1,3,0 1,100%,1,1,y ++. 1 %. 6 rv[-2,-1] a[-3--1] x 23947 3,100%,1,1,1 1,100%,1,1,1 y a y 23948 *3d. {1-$2} 23949 23950 # Generate minimal pattern (2x2 hexagons). 23951 ++3d {sqrt(3)} ++3d {sqrt(3)/2},1.5 23952 col3d... 2 col3d.. 3 col3d. 4 +3d 23953 /3d 1.5 23954 endl 23955 23956 # Duplicate it to get a grid with correct size. 23957 ny={1+round(0.5*$1,1,1)} 23958 nx={0,1+round($1*w/h*3/(sqrt(3)*4),1,1)} 23959 array3d. $nx,$ny,1,{4*sqrt(3)/3},2 23960 c3d. *3d. {0,h/$1} 23961 23962 # Fill grid with image colors. 23963 [0],[0] j3d. ..,50%,50%,0,1,2,0,0 rm.. 23964 blend shapeaverage0 23965 23966 endl done 23967 23968#@cli imagegrid_triangular : pattern_width>=1,_pattern_height>=1,_pattern_type,0<=_outline_opacity<=1,\ 23969# _outline_color1,... 23970#@cli : Create triangular grids from selected images. 23971#@cli : 'pattern type' can be { 0=horizontal | 1=vertical | 2=crossed | 3=cube | 4=decreasing | 5=increasing }. 23972#@cli : Default values: 'pattern_width=24', 'pattern_height=pattern_width', 'pattern_type=0', 'outline_opacity=0.1' \ 23973# and 'outline_color1=0'. 23974#@cli : $ image.jpg imagegrid_triangular 6,10,3,0.5 23975imagegrid_triangular : check "$1>=1 && ${2=$1}>=1 && isint(${3=0}) && $3>=0 && $3<=5" skip ${4=0},${5=0} 23976 s0="horizontal" s1="vertical" s2="crossed" s3="cube" 23977 e[^-1] "Create triangular grid(s) from image$?, with pattern width $1, height $2, pattern type '"${s$3}"', "\ 23978 "outline opacity $4 and outline color (${5--1})." 23979 23980 # Create triangular patterns and outlines (always square!). 23981 M={max($1,$2)} 23982 if $3==4" || "$3==5 # Decreasing/Increasing. 23983 $M,$M,1,1,x>y ++. 2 a[-2,-1] x ++. 4 a[-2,-1] y 23984 $M,$M,1,1,"!x || !y || x==y" r. 200%,200%,1,1,0,2 23985 a[-2,-1] c 23986 if $3==5 mirror. y fi 23987 elif $3==3 # Cube. 23988 $M,$M,1,1,x>y 100%,100%,1,1,w-1-x>=y a[-2,-1] x ++. 2 mirror. y a[-2,-1] y 23989 ++. 4 =. 4,50%,50% =.. 2 a[-2,-1] x label. 0,0 23990 (2,2,2,0,1,2,1,1,3,3,3,1,1,0) map.. . rm. 23991 100%,100%,1,1 23992 line. 0,0,{$M-1},{$M-1},1,1 line. {$M-1},$M,0,100%,1,1 23993 line. {$M-1},{$M-1},{3*$M-1},{$M-1},1,1 line. {2*$M},0,0,0,1,1 23994 line. {2*$M},0,100%,100%,1,1 line. {2*$M},100%,100%,0,1,1 23995 a[-2,-1] c 23996 elif $3==2 # Horizontal + vertical. 23997 $M,$M,1,1,x>y ++. 2 mirror. x a[-2,-1] x ++. 4 mirror. y a[-2,-1] y 23998 100%,100%,1,1,"!x || !y || x==int(w/2) || y==int(h/2) || x==y || w-1-x==y" 23999 a[-2,-1] c 24000 elif $3==1 # Vertical. 24001 $M,$M,1,1,x>y 100%,100%,1,1,w-1-x<=y a[-2,-1] y ++. 2 mirror. x a[-2,-1] x 24002 100%,100%,1,1,"!x || x==int(w/2) || x==y || w-1-x==y" 24003 a[-2,-1] c 24004 else # Horizontal. 24005 $M,$M,1,1,x>y 100%,100%,1,1,w-1-x>=y a[-2,-1] x ++. 2 mirror. y a[-2,-1] y 24006 100%,100%,1,1,"!y || y==int(h/2) || x==y || w-1-x==y" 24007 a[-2,-1] c 24008 fi 24009 24010 # Apply grid on images. 24011 repeat $!-1 24012 wh={$>,w},{$>,h} 24013 if $1>$2 r[$>] 100%,{$>,$1*h/$2} elif $1<$2 r[$>] {$>,$2*w/$1} fi 24014 +r. [$>],[$>],1,2,0,2,0.5,0.5 24015 s. c 24016 blend[$>,-2] shapeaverage 24017 +fc[$>] ${5--1} j[$>] .,0,0,0,0,$4,.. rm[-2,-1] 24018 r[$>] $wh,1,100%,2 24019 done 24020 rm. 24021 24022#@cli linearize_tiles : M>0,_N>0 24023#@cli : Linearize MxN tiles on selected images. 24024#@cli : Default value: 'N=M'. 24025#@cli : $ image.jpg +linearize_tiles 16 24026linearize_tiles : check "$1>0 && ${2=$1}>0" 24027 e[^-1] "Linearize $1x$2 tiles on image$?." 24028 repeat $! l[$>] nm={0,n} 24029 s={s} split_tiles $1,$2 s c # Split as tiles for all channels. 24030 repeat $! l[$>] 24031 wh={w},{h} 24032 +f x +f. y +f. 1 y a[^0] x solve.. . rm. 24033 $wh,1,1,{@0}"*x + "{@1}"*y + "{@2} rm.. 24034 endl done 24035 repeat int($!/$s) a[-$s--1] c mv. 0 done append_tiles $1,$2 24036 nm $nm endl done 24037 24038#@cli map_sprites : _nb_sprites>=1,_allow_rotation={ 0=none | 1=90 deg. | 2=180 deg. } 24039#@cli : Map set of sprites (defined as the 'nb_sprites' latest images of the selection) to other selected images, 24040#@cli : according to the luminosity of their pixel values. 24041#@cli : $ image.jpg resize2dy 48 repeat 16 ball {8+2*$>},${-rgb} mul[-1] {(1+$>)/16} done map_sprites 16 24042map_sprites : check "isint($1) && $1>0 && isint(${2=0}) && $2>=0 && $2<=2" 24043 e[^-1] "Map set of $1 sprites to image selection$?." 24044 norm[0--{$1+1}] quantize[0--{$1+1}] $1,0,1 24045 slices[-$1--1] 0 r[-$1--1] ${max_wh[-$1--1]},1,100%,0,0,0.5,0.5 24046 if $2==1 24047 N={4*$1} 24048 repeat $!-$1 *[$>] 4 +rand[$>] 0,3 round. +[$>,-1] done 24049 repeat $1 l[{1+$<}] +mirror xy +rotate 90 endl done 24050 elif $2==2 24051 N={2*$1} 24052 repeat $!-$1 *[$>] 2 +rand[$>] 0,1 round. +[$>,-1] done 24053 repeat $1 l[{1+$<}] +mirror xy endl done 24054 else N=$1 fi 24055 r[-$N--1] 100%,100%,1,${max_s[-$N--1]} w={w} h={h} a[-$N--1] x 24056 r[^-1] ${w}00%,${h}00%,1,1 *[^-1] $w 24057 (0,{$w-1};0,{$w-1}^0,0;{$h-1},{$h-1}) r. $w,$h,1,2,3 round. 24058 repeat $!-2 +r. [$>],[$>],1,2,0,2 r[$>] 100%,100%,1,2,0 +[$>,-1] +warp.. [$>],0,0 rv[$>,-1] rm. done rm[-2,-1] 24059 24060#@cli pack : is_ratio_constraint={ 0 | 1 },_sort_criterion 24061#@cli : Pack selected images into a single image. 24062#@cli : The returned status contains the list of new (x,y) offsets for each input image. 24063#@cli : Parameter 'is_ratio_constraint' tells if the resulting image must tend to a square image. 24064#@cli : Default values: 'is_ratio_constraint=0' and 'sort_criterion=max(w,h)'. 24065#@cli : $ image.jpg repeat 10 +resize2dx[-1] 75% balance_gamma[-1] ${-rgb} done pack 0 24066pack : skip ${1=0},${2=max(w,h)} 24067 e[^-1] "Pack image$? into a single image." 24068 if $!<2 return fi 24069 if ${-max_d}>1 error[0--3] "Command '$0': Selected images contain at least one volumetric image (depth>1). 24070 Should all be 2D." fi 24071 nm={0,n} to_colormode 0 24072 24073 # Sort images by decreasing size. 24074 repeat $! nm$>={$>,n} nm[$>] ${nm$>}:$> done 24075 m "_pack : ('{n}') l. s +,{':'} u {t} rm endl" 24076 if ['$2']=='n' sort_list +,n else sort_list -,"$2" fi 24077 24078 # Start packing 24079 offsets${-_pack[0]}=0,0 24080 N=$! 24081 i[0] 0 # List of empty slots. 24082 24083 do l[0,1,2] 24084 w1,h1,w2,h2={[w#1,h#1,w#2,h#2]} 24085 24086 # Search an empty slot that fits. 24087 slot,min_slot_area=-1,inf 24088 repeat h#0 24089 x,y,w,h={0,crop(0,$>,4,1)} 24090 slot_area={$w*$h} 24091 if $w>=$w2" && "$h>=$h2" && "$slot_area<=$min_slot_area # Found a fit. 24092 slot,min_slot_area=$>,$slot_area 24093 fi 24094 done 24095 24096 if $slot>=0 # Empty slot found -> Use it. 24097 x,y,w,h={0,crop(0,$slot,4,1)} 24098 j[1] [2],$x,$y offsets${-_pack[2]}=$x,$y 24099 l[0] 24100 s y rm[$slot] 24101 area1={max(($w-$w2)*$h,$w2*($h-$h2))} 24102 area2={max(($w-$w2)*$h2,$w*($h-$h2))} 24103 if $area1>=$area2 # Split - type1 24104 if $w2<$w i[$slot] ({$x+$w2},$y,{$w-$w2},$h) fi 24105 if $h2<$h i[$slot] ($x,{$y+$h2},$w2,{$h-$h2}) fi 24106 else # Split - type 2 24107 if $w2<$w i[$slot] ({$x+$w2},$y,{$w-$w2},$h2) fi 24108 if $h2<$h i[$slot] ($x,{$y+$h2},$w,{$h-$h2}) fi 24109 fi 24110 a y if !$! 0 fi 24111 endl 24112 rm[2] 24113 24114 else # Empty slot not found -> Append horizontally or vertically. 24115 if $1 24116 metric_h={abs($w1+$w2-max($h1,$h2))} 24117 metric_v={abs($h1+$h2-max($w1,$w2))} 24118 else 24119 metric_h={if($h2<$h1,$w2*($h1-$h2),$w1*($h2-$h1))} 24120 metric_v={if($w2<$w1,($w1-$w2)*$h2,($w2-$w1)*$h1)} 24121 fi 24122 24123 if $metric_h<=$metric_v # Append horizontally. 24124 offsets${-_pack[2]}=$w1,0 24125 a[1,2] x,0 24126 if $h2<$h1 ($w1,$h2,$w2,{$h1-$h2}) a[0,-1] y 24127 elif $h2>$h1 (0,$h1,$w1,{$h2-$h1}) a[0,-1] y 24128 fi 24129 else # Append vertically. 24130 offsets${-_pack[2]}=0,$h1 24131 a[1,2] y,0 24132 if $w2<$w1 ($w2,$h1,{$w1-$w2},$h2) a[0,-1] y 24133 elif $w2>$w1 ($w1,0,{$w2-$w1},$h1) a[0,-1] y 24134 fi 24135 fi 24136 fi 24137 24138 endl while $!>2 24139 rm[0] 24140 24141 # Return offsets. 24142 status= 24143 repeat $N if narg($status) status=$status,${offsets$>} else status=${offsets$>} fi done 24144 nm $nm u $status 24145 um _pack 24146 24147#@cli puzzle : _width>0,_height>0,_M>=1,_N>=1,_curvature,_centering,_connectors_variability,_resolution>=1 24148#@cli : Input puzzle binary mask with specified size and geometry. 24149#@cli : Default values: 'width=height=512', 'M=N=5', 'curvature=0.5', 'centering=0.5', 'connectors_variability=0.5' \ 24150# and 'resolution=64'. 24151#@cli : $ puzzle , 24152puzzle : check "isint(${1=512}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=5}) && $3>0 && 24153 isint(${4=$3}) && $4>0 && isint(${8=64}) && $8>0" 24154 skip ${5=0.5},${6=0.5},${7=0.5} 24155 e[^-1] "Draw $3x$4 puzzle pattern on image$?, with curvature $5, centering $6, connectors variability $7 24156 and resolution $8." 24157 l[] 24158 if $4>=2 _puzzle[] $3,{$4-1},${5-8} +3d. 0,1 fi 24159 if $3>=2 _puzzle[] $4,{$3-1},${5-8} r3d. 0,0,1,-90 +3d. 1,$4 fi 24160 *3d {$1/$3},{$2/$4} quadrangle3d 0,0,0,{$1-1},0,0,{$1-1},{$2-1},0,0,{$2-1},0 p3d. 1 +3d col3d 1 24161 $1,$2 j3d. ..,0,0,0,1,1,0,0 rm.. 24162 endl 24163 24164_puzzle : 24165 R={$6*$1} 24166 repeat $2 24167 ({'CImg3d'},$R,{$R-1}) 24168 repeat $1 24169 sign={if(u<=0.5,-1,1)} 24170 center={$4*u(-0.25,0.25)} 24171 knob={$5*u(-0.05,0.12)} 24172 ($>,0;\ 24173 {0.2+$center+$>},{-$sign*$3*0.1};\ 24174 {0.4+$center+$>},0;\ 24175 {0.35+$center+$>},{0.1*$sign};\ 24176 {0.45+$center+$>},{(0.15+$knob)*$sign};\ 24177 {0.55+$center+$>},{(0.15+$knob)*$sign};\ 24178 {0.65+$center+$>},{0.1*$sign};\ 24179 {0.6+$center+$>},0;\ 24180 {0.8+$center+$>},{-$sign*$3*0.1}) 24181 done 24182 ($1,0) a[-{$1+1}--1] y r. 2,$R,1,1,5 z. 0,2 24183 (2,0,1;2,{$R-2},{$R-1}) r. 3,{$R-1},1,1,3 round. 24184 3,{h},1,1,255 1,{h},1,1,255 y[-5--1] y a[-5--1] y +3d. 0,$> 24185 done +3d 24186 24187#@cli quadratize_tiles : M>0,_N>0 24188#@cli : Quadratize MxN tiles on selected images. 24189#@cli : Default value: 'N=M'. 24190#@cli : $ image.jpg +quadratize_tiles 16 24191quadratize_tiles : check "$1>0 && ${2=$1}>0" 24192 e[^-1] "Quadratize $1x$2 tiles on image$?." 24193 repeat $! l[$>] nm={0,n} 24194 s={s} split_tiles $1,$2 s c # Split as tiles for all channels. 24195 repeat $! l[$>] 24196 wh={w},{h} 24197 +f x^2 +f. y^2 +f. x*y +f. x +f. y +f. 1 y a[^0] x 24198 solve.. . rm. 24199 $wh,1,1,{@0}"*x^2 + "{@1}"*y^2 + "{@2}"*x*y +"{@3}"*x + "{@4}"*y + "{@5} rm.. 24200 endl done 24201 repeat int($!/$s) a[-$s--1] c mv. 0 done append_tiles $1,$2 24202 nm $nm endl done 24203 24204#@cli rotate_tiles : angle,_M>0,N>0 24205#@cli : Apply MxN tiled-rotation effect on selected images. 24206#@cli : Default values: 'M=8' and 'N=M'. 24207#@cli : $ image.jpg to_rgba rotate_tiles 10,8 drop_shadow 10,10 display_rgba 24208rotate_tiles : skip ${2=8},${3=$2} 24209 e[^-1] "Apply $2x$3 tiled-rotation effect on image$?, with angle $1 deg." 24210 split_tiles $2,$3,1 rotate $1 append_tiles $2,$3 24211 24212#@cli shift_tiles : M>0,_N>0,_amplitude 24213#@cli : Apply MxN tiled-shift effect on selected images. 24214#@cli : Default values: 'N=M' and 'amplitude=20'. 24215#@cli : $ image.jpg +shift_tiles 8,8,10 24216shift_tiles : check "${2=$1}>=0" skip ${3=20} 24217 e[^-1] "Apply $1x$2 tiled-shift effect on image$?, with amplitude $3." 24218 repeat $! l[$>] 24219 $1,$2,1,2 noise. $3 r. ..,..,1,2 warp.. .,1,1,0 rm. 24220 endl done 24221 24222#@cli taquin : M>0,_N>0,_remove_tile={ 0=none | 1=first | 2=last | 3=random },_relief,_border_thickness[%],\ 24223# _border_outline[%],_outline_color 24224#@cli : Create MxN taquin puzzle from selected images. 24225#@cli : Default value: 'N=M', 'relief=50', 'border_thickness=5', 'border_outline=0' and 'remove_tile=0'. 24226#@cli : $ image.jpg +taquin 8 24227taquin : check "isint($1) && $1>0 & isint(${2=$1}) && $2>0" 24228 skip ${3=0},${4=50},${5=5%},${6=0},${7=0},${8=$7},${9=$8},${10=255} 24229 e[^-1] "Create $1x$2 taquin puzzle from image$?, with relief $4, border thickness $5, border outline $6 and 24230 outline color (${7--1})." 24231 repeat $! l[$>] nm={0,n} 24232 split_tiles $1,$2 r ${-min_wh},100%,100%,0 24233 100%,100%,1,1,1 24234 if ${"is_percent $5"} rectangle. {100*$5/2}%,{100*$5/2}%,{100-50*$5}%,{100-50*$5}%,1,0 24235 else rectangle. $5,$5,{w-1-$5},{h-1-$5},1,0 fi 24236 *. '1-2*(x/w<y/h)' *. $4 24237 repeat $!-1 l[$>,-1] split_opacity[0] +[0] . a[^-1] c endl done rm. c 0,255 24238 frame $6,$6,${7-10} 24239 if $3==3 f. 0 fi 24240 repeat $! mv[$>] {u($!)} done 24241 if $3==1 f[0] 0 elif $3==2 f. 0 fi 24242 append_tiles $1,$2 24243 nm $nm endl done 24244 24245#@cli tunnel : _level>=0,_factor>0,_centering_x,_centering_y,_opacity,_angle 24246#@cli : Apply tunnel effect on selected images. 24247#@cli : Default values: 'level=9', 'factor=80%', 'centering_x=centering_y=0.5', 'opacity=1' and 'angle=0' 24248#@cli : $ image.jpg tunnel 20 24249tunnel : check "${1=9}>=0 && ${2=80%}>0" skip ${3=0.5},${4=0.5},${5=0.1},${6=0} 24250 e[^-1] "Apply tunnel effect on image$?, with depth $1, factor $2, centering ($3,$4), opacity $5 and angle $6." 24251 repeat $! l[$>] 24252 repeat $1 +r. $2,$2,1,100%,5 24253 if $6 100%,100%,1,1,1 rotate[-2,-1] $6,1,0 erode. 3 j... ..,{({-3,w}-w)*$3},{({-3,h}-h)*$4},0,0,$5,. rm[-2,-1] 24254 else j.. .,{({-2,w}-w)*$3},{({-2,h}-h)*$4},0,0,$5 rm. fi 24255 done 24256 endl done c 0,255 24257 24258#----------------------------- 24259# 24260#@cli :: Artistic 24261# 24262#----------------------------- 24263 24264#@cli boxfitting : _min_box_size>=1,_max_box_size>=0,_initial_density>=0,_nb_attempts>=1 24265#@cli : Apply box fitting effect on selected images, as displayed the web page: 24266#@cli : <http://www.complexification.net/gallery/machines/boxFittingImg/>. 24267#@cli : Default values: 'min_box_size=1', 'max_box_size=0', 'initial_density=0.1' and 'nb_attempts=3'. 24268#@cli : $ image.jpg boxfitting , 24269boxfitting : check "isint(${1=3}) && $1>=1 && isint(${2=0}) && $2>=0 && ${3=0.1}>=0 && isint(${4=3}) && $4>=1" 24270 e[^-1] "Apply box fitting effect on image$?, with box sizes ($1,$2), density $3 and $4 attempts." 24271 min_size=$1 24272 max_size={if($2,$2,max(w,h))} 24273 repeat $! l[$>] 24274 nb_attempts=0 prec=5 24275 100%,100% 24276 repeat 1e8 24277 24278 # Add random non-intersecting squares with min size. 24279 if $><1 # Takes random points for the first iteration. 24280 100%,100% noise. {max(1e-3,$3)},2 ==. 1 24281 else # Then, try to take points near the median axis of the distance function otherwise. 24282 +distance. 1 +rand. 0,1 *[-2,-1] max_patch. {round($prec*$min_size)} 24283 prec={max(1,$prec*0.9)} 24284 fi 24285 24286 # Discard new squares that intersect something. 24287 dilate. $min_size area_fg. 0,1 ==. {($min_size)^2} 24288 +dilate.. 3 ==. 0 *[-2,-1] area_fg. 0,1 ==. {($min_size)^2} 24289 if !iM nb_attempts+=1 if $nb_attempts>$4 rm. break fi # If no new squares have been placed. 24290 else nb_attempts=0 fi 24291 +[-2,-1] 24292 24293 # Make current squares grown until max square size is reached. 24294 repeat int(($max_size-$min_size)/2) 24295 +dilate. 3 area_fg. 0,1 ==. {($min_size+2*$>+2)^2} 24296 if !iM rm. break fi # No more squares to grow. 24297 -|[-2,-1] 24298 done 24299 24300 done 24301 blend shapeaverage0 24302 endl done 24303 24304#@cli brushify : [brush],_brush_nb_sizes>=1,0<=_brush_min_size_factor<=1,_brush_nb_orientations>=1,\ 24305# _brush_light_type,0<=_brush_light_strength<=1,_brush_opacity,_painting_density[%]>=0,\ 24306# 0<=_painting_contours_coherence<=1,0<=_painting_orientation_coherence<=1,_painting_coherence_alpha[%]>=0,\ 24307# _painting_coherence_sigma[%]>=0,_painting_primary_angle,0<=_painting_angle_dispersion<=1 24308#@cli : Apply specified brush to create painterly versions of specified images. 24309#@cli : 'brush_light_type' can be { 0=none | 1=flat | 2=darken | 3=lighten | 4=full }. 24310#@cli : Default values: 'brush_nb_sizes=3', 'brush_min_size_factor=0.66', 'brush_nb_orientations=12', \ 24311# 'brush_light_type=0', 'brush_light_strength=0.25', 'brush_opacity=0.8', 'painting_density=20%', \ 24312# 'painting_contours_coherence=0.9', 'painting_orientation_coherence=0.9', 'painting_coherence_alpha=1', \ 24313# 'painting_coherence_sigma=1', 'painting_primary_angle=0', 'painting_angle_dispersion=0.2' 24314#@cli : $ image.jpg 40,40 gaussian[-1] 10,4 spread[-1] 10,0 brushify[0] [1],1 24315brushify : check ${"is_image_arg $1"}" &&"\ # $1: [brush] 24316 "isint(${2=4}) && $2>=1 &&"\ # $2: brush_nb_sizes 24317 "${3=0.25}>=0 && $3<=1 &&"\ # $3: brush_min_size_factor 24318 "isint(${4=12}) && $4>=1 &&"\ # $4: brush_nb_orientations 24319 "isint(${5=4}) && $5>=0 &&"\ # $5: brush_light_type 24320 "${6=0.07}>=0 && $6<=1 &&"\ # $6: brush_light_strength 24321 "isnum(${7=0.75}) &&"\ # $7: brush_opacity 24322 "${8=40%}>=0 && $8>=0 &&"\ # $8: painting_density[%] 24323 "${9=0.7}>=0 && $9<=1 &&"\ # $9: painting_contours_coherence 24324 "${10=1}>=0 && $10<=1 &&"\ # $10: painting_orientation_coherence 24325 "${11=1}>=0 && ${12=0.5%}>=0 &&"\ # $11 and $12: painting_coherence_alpha and sigma 24326 "isnum(${13=45}) &&"\ # $13: painting_primary_angle 24327 "${14=0.2}>=0 && $14<=1" # $14: painting_angle_dispersion 24328 e[^-1] "Brushify image$?, with brush $1." 24329 24330 # Precompute the set of oriented/resized brushes. 24331 pass$1 0 l. 24332 slices 0 max 1e-8 norm n 0,1 threshold 0.1,1 autocrop. 24333 repeat $4 +rotate[0] {360*$>/$4} done 24334 rm[0] n 0,1 threshold 0.1,1 24335 autocrop r ${-max_wh},1,1,0,0,0.5,0.5 24336 a z nm brush 24337 wb={w} hb={h} whb={wh} ls={255*$6} 24338 if $5==0 +f. 0 24339 elif $5==1 +n. -$ls,0 24340 elif $5==2 +g xy +[-2,-1] min. 0 n. -$ls,0 24341 elif $5==3 +g xy +[-2,-1] max. 0 n. 0,$ls 24342 else +g xy +[-2,-1] n. -$ls,$ls 24343 fi 24344 nm. brushlight 24345 24346 repeat $2-1 24347 ratio={v=(1+$>)/max(1,$2-1);100*((1-v)+$3*v)}% 24348 +r[brush,brushlight] $ratio,$ratio,100%,1,2 24349 ri[-2,-1] [brush],0,0,0.5,0.5 24350 done 24351 a[^:2] z a[^0] z 24352 endl 24353 24354 # Generate images with brushes. 24355 repeat $!-2 l[$>,brush,brushlight] 24356 s={0,s} nm={0,n} to_rgb[0] nm[0] img 24357 24358 # Generate set of random points with orientations. 24359 +diffusiontensors[img] $9,$10,$11,$12 nm. geometry 24360 +channels[geometry] 0 sh[geometry] 2 +[-2,-1] ^. 0.3 quantize. $2,0 *. -1 +. $2 -. 1 nm. contours 24361 1,{img,max(1,${"is_percent $8"}?wh*$8:$8)} rand. 0,{img,w-1} +rand. 0,{img,h-1} a[-2,-1] c nm. pts 24362 +to_rgba[img] nm. res 24363 24364 # Render filter. 24365 f[pts] "* 24366 begin( 24367 S2 = round(0.5*["$wb","$hb"]); 24368 brush_r = brush_g = brush_b = brush_a = vector"$whb"(255); 24369 ang = $13*pi/180; 24370 cu = [ cos(ang),sin(ang) ]; 24371 cv = [ -cu[1],cu[0] ]; 24372 T = mul(cu,cu,2) + $14*mul(cv,cv,2); 24373 ); 24374 P = I; 24375 G = I(#"$geometry",P); 24376 ang = u(pi); 24377 V = [ G[0],G[1],G[1],G[2] ]*(T*[ cos(ang),sin(ang) ]); 24378 amp = i(#"$contours",P); #cut($2-round(5*$2*sqrt(G[0] + G[2])),0,$2-1); 24379 ang = round(((atan2(V[1],V[0])%(2*pi))*$4/(2*pi)))%$4; 24380 col = I(#"$img",P); 24381 ind = amp*$4 + ang; 24382 ref(crop(#"$brush",0,0,ind,0,"$wb","$hb",1,1),brush); 24383 ref(crop(#"$brushlight",0,0,ind,0,"$wb","$hb",1,1),brushlight); 24384 brush_r = cut(col[0] + brushlight,0,255); 24385 brush_g = cut(col[1] + brushlight,0,255); 24386 brush_b = cut(col[2] + brushlight,0,255); 24387 draw(#"$res",[brush_r,brush_g,brush_b,brush_a],P - S2,"$wb","$hb",1,4,$7,brush,1); 24388 P" 24389 k[res,brush,brushlight] mv[res] 0 nm[0] $nm to_colormode[0] {$s+($s%2)} 24390 endl done rm[brush,brushlight] 24391 24392#@cli cartoon : _smoothness,_sharpening,_threshold>=0,_thickness>=0,_color>=0,quantization>0 24393#@cli : Apply cartoon effect on selected images. 24394#@cli : Default values: 'smoothness=3', 'sharpening=150', 'threshold=20', 'thickness=0.25', 'color=1.5' \ 24395# and 'quantization=8'. 24396#@cli : $ image.jpg cartoon 3,50,10,0.25,3,16 24397cartoon : skip ${1=3},${2=150},${3=20},${4=0.25},${5=1.5},${6=8} 24398 e[^-1] "Apply cartoon effect on image$?, with smoothness $1, sharpening $2, threshold $3, thickness $4, color $5 24399 and quantization $6." 24400 repeat $! l[$>] split_opacity l[0] to_rgb 24401 b $1 sharpen $2,1 c 0,255 n 0,255 24402 if $4 +edges $3 b. $4 >=. 0.9 else 100%,100%,1,1,1 fi 24403 rgb2lab.. s.. c *[-3,-2] $5 a[-4--2] c lab2rgb.. 24404 quantize.. $6,1,-1 24405 n.. 0,255 * 24406 endl a c endl done 24407 24408#@cli color_ellipses : _count>0,_radius>=0,_opacity>=0 24409#@cli : Add random color ellipses to selected images. 24410#@cli : Default values: 'count=400', 'radius=5' and 'opacity=0.1'. 24411#@cli : $ image.jpg +color_ellipses ,,0.15 24412color_ellipses : skip ${1=1400},${2=5},${3=0.1} 24413 e[^-1] "Add $1 random color ellipses to image$?, with maximum radius $2 and opacity $1." 24414 repeat $1 24415 ellipse {u(0,100)}%,{u(0,100)}%,{u(0,$2)}%,{u(0,$2)}%,{u(0,360)},$3,{u(60,255)},{u(60,255)},{u(60,255)},255 24416 done 24417 24418#@cli cubism : _density>=0,0<=_thickness<=50,_max_angle,_opacity,_smoothness>=0 24419#@cli : Apply cubism effect on selected images. 24420#@cli : Default values: 'density=50', 'thickness=10', 'max_angle=75', 'opacity=0.7' and 'smoothness=0'. 24421#@cli : $ image.jpg cubism , 24422cubism : check "${1=50}>=0 && ${2=10}>=0 && $2<=50 && ${5=0}>=0" skip ${3=75},${4=0.7} 24423 e[^-1] "Apply cubism effect on image$?, with density $1, thickness $2, maximum angle $3 deg., opacity $4 and 24424 smoothness $5." 24425 if "!$1 || !$2 || !$3 || !$4" return fi 24426 repeat $! l[$>] 24427 w={w} h={h} s={s} 24428 P={round($2*max(w,h)/200)} 24429 N={round(1.5*$1*w*h/(4*$P)/100)} 24430 24431 # Define Header + nb vertices / primitives. 24432 ('CImg3d') +. 0.5 ({4*$N};$N) 24433 24434 # Generate list of random points. 24435 1,$N rand. $P,{$w-1-$P} +rand. $P,{$h-1-$P} a[-2,-1] x round. 24436 24437 # Generate list of primitives. 24438 ++. '-$P,-$P' ++.. '$P,-$P' ++... '$P,$P' ++[-4] '-$P,$P' 24439 a[-4--1] x i.. (12,0,1,2,3;12,{4*($N-1)},{4*($N-1)+1},{4*($N-1)+2},{4*($N-1)+3}) 24440 r.. 5,$N,1,1,3 round.. 1 a[-2,-1] x 24441 24442 # Generate list of vertices. 24443 1,$N rand. {225-$3},{225+$3} *. {pi/180} 24444 +sin. cos.. +*. -1 ... a[-4--3] x a[-2,-1] x z[-4,-2,-1] 0,2 +*[-2,-1] -1 a[-4--1] x *. {sqrt(2)*$P} 24445 r... 400%,100%,1,1,0,2 +[-3,-1] 24446 24447 # Generate materials. 24448 (-128;$w;$h;$s) +b[0] $5 24449 if $N>1 4,{$N-1},1,1,-128,0,0,0 fi 24450 1,$N,1,1,1 24451 24452 # Apply effect on current image. 24453 y[1--1] a[1--1] y rv3d. 24454 if $4>=1 j3d[0] [1],0,0,0,1,2,0,0 rm[1] 24455 else +j3d[0] [1],0,0,0,1,2,0,0 rm[1] blend alpha,$4 24456 fi 24457 24458 endl done 24459 24460#@cli draw_whirl : _amplitude>=0 24461#@cli : Apply whirl drawing effect on selected images. 24462#@cli : Default value: 'amplitude=100'. 24463#@cli : $ image.jpg draw_whirl , 24464draw_whirl : skip ${1=100} 24465 e[^-1] "Apply whirl drawing effect on image$? with amplitude $1." 24466 repeat $! l[$>] 24467 100%,100% noise. 70,2 ==. 1 *. 255 ri. .. &[-1,-2] smooth. $1,0,1,2,2 24468 sqrt. n. 0,255 equalize. 24469 endl done 24470 24471#@cli drawing : _amplitude>=0 24472#@cli : Apply drawing effect on selected images. 24473#@cli : Default value: 'amplitude=200'. 24474#@cli : $ image.jpg +drawing , 24475drawing : skip ${1=200} 24476 e[^-1] "Apply drawing effect on image$? with amplitude $1." 24477 repeat $! l[$>] split_opacity l[0] to_rgb 24478 smooth $1,0.2,1,3,3 b 2 sharpen 1000 [0] 24479 r[0] 20,20,1,3,2 equalize[0] index[1] [0],1,1 24480 nm[1] {0,n},1 rm[0] 24481 endl a c endl done 24482 24483#@cli drop_shadow : _offset_x[%],_offset_y[%],_smoothness[%]>=0,0<=_curvature<=1,_expand_size={ 0 | 1 } 24484#@cli : Drop shadow behind selected images. 24485#@cli : Default values: 'offset_x=20', 'offset_y=offset_x', 'smoothness=5', 'curvature=0' and 'expand_size=1'. 24486#@cli : $ image.jpg drop_shadow 10,20,5,0.5 expand_xy 20,0 display_rgba 24487drop_shadow : check "${3=5}>=0 && ${4=0}>=0 && $4<=1" skip ${1=20},${2=$1},${5=1} 24488 e[^-1] "Drop shadow behind image$?, with offsets ($1,$2), smoothness $3 and curvature $4." 24489 to_a repeat $! l[$>] 24490 nm={0,n} 24491 dx={if(${is_percent\ $1},w*$1,$1)} 24492 dy={if(${is_percent\ $2},h*$2,$2)} 24493 sigma={if(${is_percent\ $3},min(w,h)*$3,$3)} 24494 w,h,s={[w,h,s]} sh. 100% coords=${autocrop_coords.\ 0} rm. z $coords # Crop part with opaque pixels. 24495 r {w+abs($dx)},{h+abs($dy)},1,100%,0,0,{if($dx>0,0,1)},{if($dy>0,0,1)} 24496 r. {w+4*$sigma},{h+4*$sigma},1,100%,0,0,0.5,0.5 24497 +channels. 100% 24498 if !$4 shift. $dx,$dy # Flat shadow. 24499 else # Curved shadow. 24500 (0;{pi}) ri. ..,3 sin. *. -$4 +. 1 *. $dx 24501 (0,{pi}) ri. ..,3 sin. *. -$4 +. 1 *. $dy 24502 a[-2,-1] c warp.. .,1,0,0 rm. 24503 fi 24504 b. $sigma,0 24505 r. 100%,100%,1,2,0,0,0,0,0,1 mv. 0 blend alpha 24506 +channels. 100% >=. 1 * autocrop 0 24507 if !$5 $w,$h,1,$s j. ..,{arg(1,$coords)},{arg(2,$coords)} rm.. fi 24508 nm $nm 24509 endl done 24510 24511#@cli ellipsionism : _R>0[%],_r>0[%],_smoothness>=0[%],_opacity,_outline>0,_density>0 24512#@cli : Apply ellipsionism filter to selected images. 24513#@cli : Default values: 'R=10', 'r=3', 'smoothness=1%', 'opacity=0.7', 'outline=8' and 'density=0.6'. 24514#@cli : $ image.jpg ellipsionism , 24515ellipsionism : check "${1=10}>0 && ${2=3}>0 && ${5=8}>0 && ${6=0.6}>0" skip ${3=1%},${4=0.7} 24516 e[^-1] "Apply ellipsionism filter to image$?, with radii ($1,$2), smoothness $3, opacity $4 and outline $5." 24517 repeat $! l[$>] to_color 24518 24519 # Compute contour angle. 24520 +luminance g. xy a[-2,-1] c b. $3 orientation. 24521 sh. 0 sh.. 1 atan2. .. *. {180/pi} +. 90 rm[-2,-1] channels. 1,1 24522 24523 # Render ellipses. 24524 100%,100%,1,4 24525 eval " 24526 const interpolation = 1; 24527 const N = $6*wh/max($1,$2); 24528 repeat (N,n, 24529 x = round(u(w-1)); y = round(u(h-1)); 24530 ellipse(x,y,$1,$2,i(#-2,x,y)°,$4,I(#0,x,y),255); 24531 ellipse(x,y,-$1,-$2,i(#-2,x,y)°,$4,0xFFFFFFFF,I(#0,x,y)/$5,255); 24532 )" 24533 rm.. blend alpha 24534 endl done 24535 24536#@cli fire_edges : _edges>=0,0<=_attenuation<=1,_smoothness>=0,_threshold>=0,_nb_frames>0,_starting_frame>=0,\ 24537# frame_skip>=0 24538#@cli : Generate fire effect from edges of selected images. 24539#@cli : Default values: 'edges=0.7', 'attenuation=0.25', 'smoothness=0.5', 'threshold=25', 'nb_frames=1', \ 24540# 'starting_frame=20' and 'frame_skip=0'. 24541#@cli : $ image.jpg fire_edges , 24542fire_edges : check "${1=0.7}>=0 && ${2=0.25}>=0 && $2<=1 && ${3=0.5}>=0 && ${4=25}>=0 && ${5=1}>0 && 24543 ${6=20}>=0 && ${7=0}>=0" 24544 e[^-1] "Generate fire effect from edges of image$?, with edges $1, attenuation $2, smoothness $3, threshold $4, 24545 $5 frames, starting frame $6 and frame skip $7." 24546 repeat $! l[$>] nm={0,n} 24547 norm +gradient_norm n. 0,1 roundify. $1 f[0] 0 24548 (0,0,0;0,0,0;1,1,1;0,1,0) *. {(1-$2^4)/4} 24549 repeat $5*(1+$7)+$6 24550 {0,w},{0,h} rand. 0,255 *. [1] 24551 b. $3 24552 if $4 >=. $4% else equalize. fi 24553 n. 0,255 24554 j[0] .,0,0,0,0,1,[1],1 rm. 24555 correlate[0] [2] 24556 if $>>=$6" && "($>-$6)%($7+1)==0 [0] fi 24557 done rm[0-2] 24558 nm $nm endl done 24559 (0,255,255,255,255^0,0,255,255,255^0,0,0,128,255) r. 256,1,1,3,3 24560 map[^-1] . rm. 24561 24562#@cli fractalize : 0<=detail_level<=1 24563#@cli : Randomly fractalize selected images. 24564#@cli : Default value: 'detail_level=0.8' 24565#@cli : $ image.jpg fractalize , 24566fractalize : check "${1=0.8}>=0 && $1<=1" 24567 e[^-1] "Randomly fractalize image$?, with detail level $1." 24568 xc=0.4433 24569 yc=0.2645 24570 delta=0.1 24571 c0r=0.317 24572 c0i=0.03 24573 repeat $! l[$>] nm={0,n} 24574 luminance equalize 256 b 0.25% n 0,255 24575 100%,100% 24576 dx={$delta*w/max(w,h)} 24577 dy={$delta*h/max(w,h)} 24578 x0={$xc-$dx/2} 24579 y0={$yc-$dy/2} 24580 x1={$xc+$dx/2} 24581 y1={$yc+$dy/2} 24582 mandelbrot. $x0,$y0,$x1,$y1,256,1,$c0r,$c0i 24583 +==. 0 inpaint.. . rm. 24584 n. 0,256 24585 16,1,1,3 rand. 0,255 r. 256,1,1,3,3 map.. . rm. 24586 s. c 24587 i[2,3] [0] 24588 s={0.1*(1-$1)} 24589 parallel "register_nonrigid[1] [0],"$s",5","register_nonrigid[3] [2],"$s",5","register_nonrigid[5] [4],"$s",5" 24590 rm[0,2,4] a c nm $nm 24591 endl done 24592 24593#@cli glow : _amplitude>=0 24594#@cli : Add soft glow on selected images. 24595#@cli : Default value: 'amplitude=1%'. 24596#@cli : $ image.jpg glow , 24597glow : skip ${1=1%} 24598 e[^-1] "Add soft glow on image$?, with amplitude $1." 24599 repeat $! l[$>] split_opacity +b[0] $1 n. [0] blend_edges[0,-1] 1 a c endl done 24600 24601#@cli halftone : nb_levels>=2,_size_dark>=2,_size_bright>=2,_shape={ 0=square | 1=diamond | 2=circle | \ 24602# 3=inv-square | 4=inv-diamond | 5=inv-circle },_smoothness[%]>=0 24603#@cli : Apply halftone dithering to selected images. 24604#@cli : Default values: 'nb_levels=5', 'size_dark=8', 'size_bright=8', 'shape=5' and 'smoothnesss=0'. 24605#@cli : $ image.jpg halftone , 24606halftone : check "${1=5}>=2 && ${2=8}>=2 && ${3=8}>=2 && ${5=0}>=0" skip ${4=5} 24607 s0="square" s1="diamond" s2="circle" s3="inv-square" s4="inv-diamond" s5="inv-circle" 24608 e[^-1] "Apply halftone dithering to image$?, with $1 levels, dark size $3, bright size $4, "\ 24609 ${s$4}" shape and smoothness $5." 24610 repeat $! l[$>] s c repeat $! l[$>] 24611 (0,255) a y quantize $1,0 rows 0,{h-2} 24612 repeat $1 24613 s={round(($2*$<+$3*$>)/($1-1))} 24614 $s,$s =. 1,50%,50% distance. 1,{$4%3} +shift. {round(w/2)},{round(h/2)},0,0,2 min[-2,-1] 24615 if $4>=3 <. {100*$</($1-1.1)}% *. {-255} +. {255-$>} 24616 else <. {100*$>/($1-1.1)}% *. 255 -. $> 24617 fi 24618 ri. ..,0,2 b. $5 +==.. $> *[-2,-1] +[-2,-1] 24619 done endl done a c 24620 endl done 24621 24622#@cli hardsketchbw : _amplitude>=0,_density>=0,_opacity,0<=_edge_threshold<=100,_is_fast={ 0 | 1 } 24623#@cli : Apply hard B&W sketch effect on selected images. 24624#@cli : Default values: 'amplitude=1000', 'sampling=3', 'opacity=0.1', 'edge_threshold=20' and 'is_fast=0'. 24625#@cli : $ image.jpg +hardsketchbw 200,70,0.1,10 median[-1] 2 +local reverse blur[-1] 3 blend[-2,-1] overlay endlocal 24626hardsketchbw : skip ${1=300},${2=50},${3=0.1},${4=20},${5=0} 24627 e[^-1] "Apply hard B&W sketch effect on image$?, with amplitude $1, density $2, opacity $3 and edge threshold $4." 24628 if !$2 channels 0 f 255 return fi 24629 luminance n 0,1 24630 24631 if $5 # Fast version. 24632 repeat $! l[$>] nm={0,n} 24633 g xy rv *.. -1 a c 24634 if $4 +norm >=. $4% * fi 24635 100%,100%,1,1,255 quiver. ..,{max(1,10-$2/6)},$1,0,$3 rm.. 24636 nm $nm endl done 24637 24638 else # Slower version. 24639 repeat $! l[$>] nm={0,n} 24640 24641 # Isolate starting points and tangents. 24642 w={w} h={h} g xy rv *.. -1 a c * $1 24643 +norm >=. $4% 100%,100% noise. $2,2 ==. 1 *[-2,-1] 24644 24645 # Retrieve points coordinates and corresponding tangents. 24646 pointcloud3d. s3d. rm[-6--5,-3--1] r. 3,{h/3},1,1,-1 s. x rm. a[-2,-1] c 24647 warp.. .,0,0 +-. .. +[-3,-2] s[-2,-1] c 24648 24649 # Convert as a 3d object and render on white background. 24650 i... 1,{h} 1,{h} a[-6--1] x 24651 i.. ('CImg3d') i.. ({2*h},{h}) 24652 1,{h},1,1,2 1,{h},1,1,2*y ++. 1 a[-3--1] x 24653 3,{h} 1,{h},1,1,$3 y[-6--1] a[-6--1] y 24654 $w,$h,1,1,255 j3d. ..,0,0,0,1,1,0,0 rm.. 24655 nm $nm endl done 24656 fi 24657 24658#@cli hearts : _density>=0 24659#@cli : Apply heart effect on selected images. 24660#@cli : Default value: 'density=10'. 24661#@cli : $ image.jpg hearts , 24662hearts : skip ${1=10} 24663 e[^-1] "Apply heart filter on image$?, with density $1." 24664 repeat $! l[$>] 24665 100%,100%,1 noise. $1,2 ==. 1 ri. .. n. 0,1 *[-1,-2] _heart9x7 24666 dilate.. . rm. 24667 endl done 24668 24669_heart9x7 : 24670 (9,7,1,1,0,1,-1,2,-3,2,-1,4,-1,13,-1,7,-3,5,-5,3,-7,1,-4) 24671 decompress_rle. 24672 24673#@cli houghsketchbw : _density>=0,_radius>0,0<=_threshold<=100,0<=_opacity<=1,_votesize[%]>0 24674#@cli : Apply hough B&W sketch effect on selected images. 24675#@cli : Default values: 'density=100', 'radius=3', 'threshold=100', 'opacity=0.1' and 'votesize=100%'. 24676#@cli : $ image.jpg +houghsketchbw , 24677houghsketchbw : check "${1=100}>=0 && ${2=3}>=0 && ${3=100}>=0 && $3<=100 && ${4=0.1}>=0 && $4<=1 && ${5=100%}>0" 24678 e[^-1] "Apply hough B&W sketch effect on image$?, with density $1, radius $2, threshold $3, opacity $4 24679 and votesize $5." 24680 luminance repeat $! l[$>] nm={0,n} 24681 24682 # Compute normalized Hough transform. 24683 res={round(if(${is_percent\ $5},$5*max(w,h),$5))} w={w} h={h} rhomax={sqrt(w^2+h^2)/2} 24684 hough $res,$res n 0,255 24685 24686 # Retrieve coordinates of maximas in hough space. 24687 normalize_local. $1,$2 >=. $3% pointcloud3d. 24688 s3d. rm[-6--5,-3--1] r. 3,{h/3},1,1,-1 columns. 0,1 24689 24690 # Convert to (x0,y0)-(x1,y1) line coordinates. 24691 s. x,2 24692 *.. {2*pi/$res} # theta 24693 *. {$rhomax/$res} # rho 24694 +cos.. *. .. +. {$w/2} # x 24695 +sin... *. ... +. {$h/2} # y 24696 rm... # Remove rho 24697 i... ... 24698 cos[-4] sin... *[-4,-3] 10000 # cos(t) sin(t) 24699 ++.. ... # x + sin(t) 24700 +-.. [-5] # y - cos(t) 24701 -[-4] [-5] # x - sin(t) 24702 +... [-6] # y + cos(t) 24703 rm[-6,-5] 24704 24705 # Transform as a 3D object. 24706 i... 1,{h} 1,{h} a[-6--1] x # Vertices 24707 i.. ('CImg3d') i.. ({2*h},{h}) # Header and size. 24708 1,{h},1,1,2 1,{h},1,1,2*y ++. 1 a[-3--1] x # Primitives. 24709 3,{h},1,1,0 1,{h},1,1,$4 # Colors and opacities 24710 y[-6--1] a[-6--1] y 24711 24712 # Render on a white image. 24713 $w,$h,1,1,255 j3d. ..,0,0,0,1,1,0,0 rm.. 24714 nm $nm endl done 24715 24716#@cli lightrays : 100<=_density<=0,_center_x[%],_center_y[%],_ray_length>=0,_ray_attenuation>=0 24717#@cli : Generate ray lights from the edges of selected images. 24718#@cli : Default values: 'density=50%', 'center_x=50%', 'center_y=50%', 'ray_length=0.9' and 'ray_attenuation=0.5'. 24719#@cli : $ image.jpg +lightrays , + cut 0,255 24720lightrays : check "${1=50}>=0 && $1<=100 && ${4=1}>=0 && ${5=1}>=0" skip ${2=50%},${3=50%} 24721 e[^-1] "Generate ray lights from image$?, with density $1, center point ($2,$3), ray length $4 and attenuation $5." 24722 repeat $! l[$>] 24723 gradient_norm >= $1% euclidean2polar $2,$3 24724 repeat log2(w) +shift. {2^$>} +[-2,-1] done 24725 function1d 0.5,0,1,{$4*w},1,{1+($4+1-$5)*w},0 r. {-2,w},1,1,1,0 24726 (1,{w}) r. {-2,w},1,1,1,3 /[-2,-1] 24727 ri. .. *[-2,-1] polar2euclidean $2,$3 n 0,255 24728 endl done 24729 24730#@cli light_relief : _ambient_light,_specular_lightness,_specular_size,_darkness,_light_smoothness,_xl,_yl,_zl,\ 24731# _zscale,_opacity_is_heightmap={ 0 | 1 } 24732#@cli : Apply relief light to selected images. 24733#@cli : Default values(s) : 'ambient_light=0.3', 'specular_lightness=0.5', 'specular_size=0.2', 'darkness=0', \ 24734# 'xl=0.2', 'yl=zl=0.5', 24735#@cli : 'zscale=1', 'opacity=1' and 'opacity_is_heightmap=0'. 24736#@cli : $ image.jpg blur 2 light_relief 0.3,4,0.1,0 24737light_relief : skip ${1=0.3},${2=0.5},${3=0.2},${4=0},${5=0.2},${6=0.5},${7=0.5},${8=1},${9=1},${10=0} 24738 e[^-1] "Apply relief light to image$?." 24739 repeat $! l[$>] 24740 ({-$6},{1-$6};{-$6},{1-$6}^{-$7},{-$7};{1-$7},{1-$7}^$8,$8;$8,$8) r. ..,..,1,3,3 # Create light vector field. 24741 if $10 +channels.. 3 to_rgb... else +to_rgb.. norm. fi 24742 b. $5% g. xy 100%,100%,1,1,$9 a[-3--1] c # Create normal vector field. 24743 orientation[-2,-1] *[-2,-1] s. c +[-3--1] # Normalized scalar product. 24744 100%,100% =. 1,{$6*100}%,{$7*100}% distance. 1 sqr. *. -1 # Compute specular attenuation. 24745 /. {($3*max(w,h))^2} exp. *. $2 +. $1 24746 *[-2,-1] -. $4 *. {-2,iM} 24747 split_opacity[0] +[0,-1] a c c 0,255 24748 endl done 24749 24750#@cli linify : 0<=_density<=100,_spreading>=0,_resolution[%]>0,_line_opacity>=0,_line_precision>0,\ 24751# _mode={ 0=subtractive | 1=additive } 24752#@cli : Apply linify effect on selected images. 24753#@cli : The algorithm is inspired from the one described on the webpage <http://linify.me/about>. 24754#@cli : Default values: 'density=50', 'spreading=2', 'resolution=40%', 'line_opacity=10', 'line_precision=24' \ 24755# and 'mode=0'. 24756#@cli : $ image.jpg linify 60 24757linify : check "${1=40}>=0 && $1<=100 && ${2=2}>=0 && ${3=40%}>0 && ${4=10}>=0 && isint(${5=24}) && $5>0 && 24758 isbool(${6=0})" 24759 e[^-1] "Apply linify effect on image$?, with density $1, spreading $2, resolution $3, line opacity $4, 24760 line precision $5 and "${"-arg 1+$6,subtractive,additive"}" mode." 24761 repeat $! l[$>] remove_opacity nm={n} 24762 100%,100%,1,{s},$6?0:255 24763 if {0,w>h} r2dx[0] {${"-is_percent $3"}?max(1,$3*w):min(w,$3)} 24764 else r2dy[0] {${"-is_percent $3"}?max(1,$3*h):min(h,$3)} 24765 fi 24766 n[0] 0,100 24767 if narg($_debug)" && "!{*,w} w[] ${-fitscreen[]\ {1,[w,h]}} fi 24768 eval " 24769 is_in(ind,P) = (P[0]>=0 && P[0]<w#ind && P[1]>=0 && P[1]<h#ind); 24770 const add = $6; 24771 const density = add?100 - $1:$1; 24772 const spreading = max(0.1,$2); 24773 const opacity = $4; 24774 const precision = $5; 24775 const om2add = 1 - 2*add; 24776 24777 fact = [ w/w#0, h/h#0,1,1 ]; 24778 nb_lines = 0; 24779 ref0 = add?iM#0:im#0; 24780 do ( 24781 S = stats(#0); 24782 P0 = add?[ S[8],S[9],0,S[11] ]:[ S[4],S[5],0,S[7] ]; # coords of min or max intensity 24783 ref = S[add]; 24784 best_ang = best_avg = add?0:inf; 24785 repeat (precision,k, 24786 ang = u(360)*pi/180; 24787 dP = [ cos(ang), sin(ang),0,0 ]; 24788 dP/=max(abs(dP)); 24789 N = avg = 0; 24790 P = P0; while (is_in(#0,P), avg+=i(#0,P); ++N; P+=dP); 24791 P = P0; while (is_in(#0,P), avg+=i(#0,P); ++N; P-=dP); 24792 avg/=N; 24793 if (add?(avg>best_avg):(avg<best_avg), best_avg = avg; best_ang = ang); 24794 ); 24795 dP = [ cos(best_ang), sin(best_ang),0,0 ]; 24796 dP/=max(abs(dP)); 24797 P = P0; while (is_in(#0,P), i(#0,P)+=om2add*spreading; P+=dP); 24798 P = P0; while (is_in(#0,P), i(#0,P)+=om2add*spreading; P-=dP); 24799 P = P0*fact; while (is_in(#1,P), i(#1,P)-=om2add*opacity*spreading; P+=dP); 24800 P = P0*fact; while (is_in(#1,P), i(#1,P)-=om2add*opacity*spreading; P-=dP); 24801 if (!(nb_lines%250), 24802 progress = density==ref0?100:round(100*(ref - ref0)/(density - ref0)); 24803 run('progress ',vtos(progress)); 24804 if (narg("$_debug"), 24805 run('+c[1] 0,255 r. {*,w},{*,h},1,3,2 to. ',vtos(progress),'%,1%,1%,5%,1 w. -1,-1,0 rm.') 24806 ); 24807 ); 24808 ++nb_lines; 24809 breakpoint(); 24810 _(while), add?(ref>density):(ref<density))" 24811 k. c 0,255 nm $nm 24812 endl done 24813 24814#@cli mosaic : 0<=_density<=100 24815#@cli : Create random mosaic from selected images. 24816#@cli : Default values: 'density=30'. 24817#@cli : $ image.jpg mosaic , +fill "I!=J(1) || I!=J(0,1)?[0,0,0]:I" 24818mosaic : check "${1=30}>=0" 24819 e[^-1] "Apply mosaic effect on image$?, with density $1." 24820 repeat $! l[$>] 24821 100%,100%,1,2,'u<0.25*($1%)^4?[u,1]' s. c 24822 distance. 1 *. -1 watershed.. . rm. 24823 blend shapeaverage 24824 endl done 24825 24826#@cli old_photo 24827#@cli : Apply old photo effect on selected images. 24828#@cli : $ image.jpg old_photo 24829old_photo : 24830 e[^-1] "Apply old photo effect on image$?." 24831 noise 20 bilateral 30,60 b 2 sharpen 100 frame_fuzzy 8%,8%,6,3 to_rgb shadow_patch 0.75 n 0,255 sepia 24832 24833#@cli pencilbw : _size>=0,_amplitude>=0 24834#@cli : Apply B&W pencil effect on selected images. 24835#@cli : Default values: 'size=0.3' and 'amplitude=60'. 24836#@cli : $ image.jpg pencilbw , 24837pencilbw : skip ${1=0.3},${2=60} 24838 e[^-1] "Apply B&W pencil effect on image$?, with size $1 and amplitude $2." 24839 repeat $! l[$>] split_opacity l[0] 24840 norm b $1 sharpen 4000 smooth $2,0,1 equalize sqrt n 0,255 24841 endl a c endl done 24842 24843#@cli pixelsort : _ordering={ + | - },_axis={ x | y | z | xy | yx },_[sorting_criterion],_[mask] 24844#@cli : Apply a 'pixel sorting' algorithm on selected images, as described in the page : 24845#@cli : <http://satyarth.me/articles/pixel-sorting/>. 24846#@cli : Default values: 'ordering=+', 'axis=x' and 'sorting_criterion=mask=(undefined)'. 24847#@cli : $ image.jpg +norm +ge[-1] 30% +pixelsort[0] +,y,[1],[2] 24848pixelsort : check "(str1='${1=+}'; str1=='+' || str1=='-') && "\ 24849 "(str2='${2=x}'; str2=='x' || str2=='y' || str2=='z' || str2=='xy' || str2=='yx') && "\ 24850 "('${3=}'==0 || "${"is_image_arg $3"}") && "\ 24851 "('${4=}'==0 || "${"is_image_arg $4"}")" 24852 s0="descending" s1="ascending" 24853 if '$3'!=0" && "'$4'!=0 24854 e[^-1] "Apply 'pixelsort' effect to image$? in "${s{['$1']=='+'}}" order, along axis $2, 24855 with sorting criterion $3 and mask $4." 24856 elif '$3'!=0" && "'$4'==0 24857 e[^-1] "Apply 'pixelsort' effect to image$? in "${s{['$1']=='+'}}" order, along axis $2, 24858 with sorting criterion $3." 24859 elif '$3'==0" && "'$4'!=0 24860 e[^-1] "Apply 'pixelsort' effect to image$? in "${s{['$1']=='+'}}" order, along axis $2, 24861 with mask $4." 24862 else 24863 e[^-1] "Apply 'pixelsort' effect to image$? in "${s{['$1']=='+'}}" order, along axis $2." 24864 fi 24865 repeat $! 24866 if '$3'!=0 pass$3 0 else +compose_channels[$>] + fi 24867 if '$4'!=0 pass$4 0 else [$>],[$>],[$>],1,1 fi 24868 l[$>,-2,-1] 24869 nm={0,n} >=. 50% mv.. 0 a c 24870 if '$2'=='x'; 24871 _pixelsort $1 channels 1,{s-2} 24872 elif '$2'=='y'; 24873 permute yxzc _pixelsort $1 channels 1,{s-2} permute yxzc 24874 elif '$2'=='z'; 24875 permute zxyc _pixelsort $1 channels 1,{s-2} permute yzxc 24876 elif '$2'=='xy'; 24877 _pixelsort $1 permute yxzc _pixelsort $1 channels 1,{s-2} permute yxzc 24878 elif '$2'=='yx'; 24879 permute yxzc _pixelsort $1 permute yxzc _pixelsort $1 channels 1,{s-2} 24880 fi 24881 nm $nm 24882 endl 24883 done 24884 24885_pixelsort : 24886 eval. ">begin(ret = [ 0 ]; const m = s - 1); 24887 i(x,y,z,m) && !i(#-1,x - 1,y,z,m)?( 24888 for (x1 = x + 1, x1<w && i(x1,y,z,m), ++x1); 24889 --x1>x?run('+z[0] ',x,',',y,',',z,',',0,',',x1,',',y,',',z,',',m - 1,' sort. $1,x j.. .,',x,',',y,' rm.'); 24890 ); ret" 24891 24892#@cli polaroid : _size1>=0,_size2>=0 24893#@cli : Create polaroid effect in selected images. 24894#@cli : Default values: 'size1=10' and 'size2=20'. 24895#@cli : $ image.jpg to_rgba polaroid 5,30 rotate 20 drop_shadow , drgba 24896polaroid : check "${1=10}>=0 && ${2=20}>=0" 24897 e[^-1] "Create polaroid effect in image$?, with borders sizes $1 and $2." 24898 - 255 r {100+$1}%,{100+$1}%,1,100%,0,0,0.5,0.5 r 100%,{100+$2}%,1,100%,0,0,0 + 255 24899 24900#@cli polygonize : _warp_amplitude>=0,_smoothness[%]>=0,_min_area[%]>=0,_resolution_x[%]>0,_resolution_y[%]>0 24901#@cli : Apply polygon effect on selected images. 24902#@cli : Default values: 'warp_amplitude=300', 'smoothness=2%', 'min_area=0.1%', 'resolution_x=resolution_y=10%'. 24903#@cli : $ image.jpg image.jpg polygonize 100,10 +fill "I!=J(1) || I!=J(0,1)?[0,0,0]:I" 24904polygonize : check "${1=300}>=0 && ${2=2%}>=0 && ${3=0.1%}>=0 && ${4=10%}>0 && ${5=$4}>0" 24905 e[^-1] "Polygonize image$? with warp amplitude $1, smoothness $2, minimal area $3 and resolutions ($4,$5)." 24906 repeat $! l[$>] 24907 +b $2 gradient_norm. g. a[-2,-1] c channels. 0,2 *. {1/0.1+max(abs(im),abs(iM))} 24908 resx={max(1,round(if(${is_percent\ $4},w*$4,w/$4)-1))} 24909 resy={max(1,round(if(${is_percent\ $5},h*$5,h/$5)-1))} 24910 plane3d 1,1,$resx,$resy *3d. {0,w-1},{0,h-1},1 24911 s3d. rm.. i.. (0;{h-1}) r.. 3,{h},1,1,3 round.. y.. 24912 [-4] a[-7--2] y r. 3,{h/3},1,1,-1 z. 0,1 permute. yzcx 24913 repeat $1 +warp[1] .,0,0 +[-2,-1] done 24914 permute. cxyz z. 0,2 y. j[2] .,0,8 rm[-3,-1] 24915 [0],[0] j3d. [1],0,0,0,1,2 rm[1] 24916 if $3>0 24917 min_area={0,if(${is_percent\ $3},$3*w*h,$3)} 24918 +area. 0,1 >=. $min_area +.. 1 *.. . distance. 1 *. -1 watershed.. . rm. 24919 fi 24920 blend shapeaverage 24921 endl done 24922 24923#@cli poster_edges : 0<=_edge_threshold<=100,0<=_edge_shade<=100,_edge_thickness>=0,_edge_antialiasing>=0,\ 24924# 0<=_posterization_level<=15,_posterization_antialiasing>=0 24925#@cli : Apply poster edges effect on selected images. 24926#@cli : Default values: 'edge_threshold=40', 'edge_shade=5', 'edge_thickness=0.5', 'edge_antialiasing=10', \ 24927# 'posterization_level=12' and 'posterization_antialiasing=0'. 24928#@cli : $ image.jpg poster_edges , 24929poster_edges : check "${1=40}>=0 && $1<=100 && ${2=5}>=0 && $2<=100 && ${3=0.5}>=0 && ${4=10}>=0 && 24930 ${5=12}>=0 && $5<=15 && ${6=0}>=0" 24931 e[^-1] "Apply poster edge on image$?, with edge threshold $1, edge shade $2, edge thickness $3, 24932 edge antialiasing $4, $5 level of posterization and posterization antialiasing $6." 24933 repeat $! l[$>] split_opacity l[0] 24934 +g xy,1 a[-2,-1] c norm. b. $3 n. 0,255 24935 apply_curve. 1,0,1,{max(0,(100-($1%)^0.1*100)*255%)},0.99,{min(255,(101-($1%)^0.1*100+$2)*255%)},0.01,255,0 c. 0,1 24936 if $4 smooth. {min(50,$4)},0,1,{$4/40},{$4/40},0.8,90 fi 24937 if $5 autoindex[0] {round((4-sqrt($5+1))*32+2)} fi 24938 if $6 smooth[0] {min(50,$6)},0,1,{$6/40},{$6/40},0.8,90 fi 24939 * 24940 endl a c endl done 24941 24942#@cli poster_hope : _smoothness>=0 24943#@cli : Apply Hope stencil poster effect on selected images. 24944#@cli : Default value: 'smoothness=3'. 24945#@cli : $ image.jpg poster_hope , 24946poster_hope : check "${1=3}>=0" 24947 e[^-1] "Apply Hope stencil poster effect on image$?, with smoothness $1." 24948 repeat $! l[$>] to_rgb 24949 apc "smooth 200,0,1,$1,1" 24950 quantize 7,0 f 'if(i!=5,i,i+1-2*(y%2))' 24951 (0,32,47;0,32,47;209,1,23;209,1,23;90,141,145;-1,-1,-1;253,221,138) permute. yzcx 24952 map[0] [1] rm[1] 24953 endl done 24954 24955#@cli rodilius : 0<=_amplitude<=100,_0<=thickness<=100,_sharpness>=0,_nb_orientations>0,_offset,\ 24956# _color_mode={ 0=darker | 1=brighter } 24957#@cli : Apply rodilius (fractalius-like) filter on selected images. 24958#@cli : Default values: 'amplitude=10', 'thickness=10', 'sharpness=400', 'nb_orientations=7', 'offset=0' \ 24959# and 'color_mode=1'. 24960#@cli : $ image.jpg rodilius 12,10,300,10 normalize_local 10,6 24961#@cli : $ image.jpg normalize_local 10,16 rodilius 10,4,400,16 smooth 60,0,1,1,4 normalize_local 10,16 24962rodilius : check "${1=10}>=0 && $1<=200 && ${2=10}>=0 && $2<=100 && ${3=400}>=0 && ${4=7}>0" skip ${5=0},${6=1} 24963 e[^-1] "Apply rodilius filter on image$? with amplitude $1, thickness $2, sharpness $3, $4 orientations, 24964 offset $5 and "${arg\ 1+!$6,brighter,darker}" color mode." 24965 repeat $! l[$>] split_opacity rv 24966 if !$6 negate. fi 24967 +f. 0 nm. {-2,n} 24968 repeat round($4) 24969 angle={$5+$>*180/round($4)} 24970 +blur_linear.. $1%,{$1*$2/100}%,$angle,1 b. 0.7 sharpen. $3 max[-2,-1] 24971 done rm.. 24972 if !$6 negate. fi 24973 rv a c endl done 24974 24975#@cli sketchbw : _nb_angles>0,_start_angle,_angle_range>=0,_length>=0,_threshold>=0,_opacity,_bgfactor>=0,\ 24976# _density>0,_sharpness>=0,_anisotropy>=0,_smoothness>=0,_coherence>=0,_is_boost={ 0 | 1 },_is_curved={ 0 | 1 } 24977#@cli : Apply sketch effect to selected images. 24978#@cli : Default values: 'nb_angles=2', 'start_angle=45', 'angle_range=180', 'length=30', 'threshold=3', \ 24979# 'opacity=0.03', 'bgfactor=0', 'density=0.6', 'sharpness=0.1', 'anisotropy=0.6', 'smoothness=0.25', 'coherence=1', \ 24980# 'is_boost=0' and 'is_curved=1'. 24981#@cli : $ image.jpg +sketchbw 1 reverse blur[-1] 3 blend[-2,-1] overlay 24982sketchbw : 24983 check "${1=2}>0 && ${3=180}>=0 && ${4=30}>=0 && ${5=3}>=0 && ${7=0}>=0 && ${8=0.6}>0 && ${9=0.1}>=0 && 24984 ${10=0.6}>=0 && ${11=0.25}>=0 && ${12=1}>=0" 24985 skip ${2=45},${6=0.03},${13=0},${14=0} 24986 e[^-1] "Apply B&W sketch effect on image$?." 24987 nb_angles,start_angle,angle_range,length,threshold,opacity,bgfactor,density,sharpness,\ 24988 anisotropy,smoothness,coherence,is_boost,is_curved=${1-14} 24989 length={max($length,1)} 24990 repeat $! l[$>] 24991 {0,[w,h,1,1,0]} # [1] = canvas to draw onto 24992 +gradient_norm[0] sqrt. 24993 diffusiontensors[0] $sharpness,$anisotropy,$smoothness,$coherence 24994 a[0,-1] c # [0] = field of stroke tensors + gradient norm 24995 1,{$density*wh/sqrt($length)},1,2,round(u([w#0,h#0]-1)) # [2] = set of random points 24996 24997 repeat $nb_angles 24998 24999 # Compute vector field for considered orientation. 25000 [0],[0],1,2," 25001 const angle = ("$start_angle" + "$>"*"$angle_range"/"$nb_angles")*pi/180; 25002 const ca = cos(angle); 25003 const sa = sin(angle); 25004 T = I(#0); 25005 U = [ T[0]*ca + T[1]*sa, T[1]*ca + T[2]*sa ]; 25006 if ("$is_boost",U/=(1e-8 + norm(U))); 25007 U" 25008 25009 # Draw curved or straight strokes. 25010 if $is_curved 25011 f[2] "* 25012 oub = ovb = ouf = ovf = 0; 25013 oixb = xb = xf = i0; 25014 oiyb = yb = yf = i1; 25015 oixf = oiyf = -1; 25016 op = "$opacity" * (i(#0,xf,yf,0,3)<"$threshold"?"$bgfactor":1); 25017 omop = 1 - op; 25018 25019 if (op>0, repeat ("$length",dl, 25020 25021 # Forward 25022 ixf = round(xf); 25023 iyf = round(yf); 25024 if (ixf!=oixf || iyf!=oiyf, (i(#1,ixf,iyf)*=omop)+=op; oixf = ixf; oiyf = iyf); 25025 uf = i(#-1,xf,yf,0,0,1,1); 25026 vf = i(#-1,xf,yf,0,1,1,1); 25027 if (ouf*uf + ovf*vf<0, uf*=-1; vf*=-1); 25028 xf+=uf; 25029 yf+=vf; 25030 ouf = uf; 25031 ovf = vf; 25032 25033 # Backward 25034 ub = i(#-1,xb,yb,0,0,1,1); 25035 vb = i(#-1,xb,yb,0,1,1,1); 25036 if (oub*ub + ovb*vb<0, ub*=-1; vb*=-1); 25037 xb-=ub; 25038 yb-=vb; 25039 oub = ub; 25040 ovb = vb; 25041 ixb = round(xb); 25042 iyb = round(yb); 25043 if (ixb!=oixb || iyb!=oiyb, (i(#1,ixb,iyb)*=omop)+=op; oixb = ixb; oiyb = iyb); 25044 )); 25045 I" 25046 else 25047 f[2] "* 25048 const l = "$length"; 25049 x = i0; 25050 y = i1; 25051 u = i(#-1,x,y,0,0); 25052 v = i(#-1,x,y,0,1); 25053 op = "$opacity" * (i(#0,x,y,0,3)<"$threshold"?"$bgfactor":1); 25054 omop = 1 - op; 25055 polygon(#1,2,x - l*u,y - l*v,x + l*u,y + l*v,op,1); 25056 I" 25057 fi 25058 rm. 25059 done 25060 k.. * -1 n 0,255 25061 endl done 25062 25063#@cli sponge : _size>0 25064#@cli : Apply sponge effect on selected images. 25065#@cli : Default value: 'size=13'. 25066#@cli : $ image.jpg sponge , 25067sponge : skip ${1=13} 25068 e[^-1] "Apply sponge filter on image$?, with brush size $1." 25069 repeat $! l[$>] 25070 100%,100%,1,1 noise. 20,2 ==. 1 ri. .. n. 0,1 *[-1,-2] 25071 _circle $1 dilate.. . rm. 25072 endl done 25073 25074_circle : 25075 if $1%2==0 2,2 else 1 fi 25076 +. 1 r. $1,$1,1,1,0,0,0.5,0.5 distance. 1 n. 0,1 sqrt. c. 0.85,0.86 *. -1 n. 0,1 25077 25078#@cli stained_glass : _edges[%]>=0, shading>=0, is_thin_separators={ 0 | 1 } 25079#@cli : Generate stained glass from selected images. 25080#@cli : Default values: 'edges=40%', 'shading=0.2' and 'is_precise=0'. 25081#@cli : $ image.jpg stained_glass 20%,1 cut 0,20 25082stained_glass : check "${1=40%}>=0 && ${2=0.2}>=0" skip ${3=0} 25083 e[^-1] "Apply stained glass effect on image$?, with edges $1, shading $2 and thin-separators "\ 25084 ${arg\ 1+!$3,enabled,disabled}"." 25085 repeat $! l[$>] 25086 im={im-1} - $im # Ensure strict positiveness of image labels. 25087 +gradient_norm >=. $1 *.. . 25088 distance. 1 sharpen. 1e10 !=. 0 25089 if $3 skeleton. 0 fi 25090 distance. 1 watershed.. . +.. $im 25091 n. 0,1 ^. $2 * 25092 endl done 25093 25094#@cli stars : _density[%]>=0,_depth>=0,_size>0,_nb_branches>=1,0<=_thickness<=1,_smoothness[%]>=0,_R,_G,_B,_opacity 25095#@cli : Add random stars to selected images. 25096#@cli : Default values: 'density=10%', 'depth=1', 'size=32', 'nb_branches=5', 'thickness=0.38', 'smoothness=0.5', \ 25097# 'R=G=B=200' and 'opacity=1'. 25098#@cli : $ image.jpg stars , 25099stars : check "${1=10%}>=0 && ${2=1}>=0 && ${3=32}>0 && ${4=5}>=1 && ${5=0.38}>=0 && $5<=1 && ${6=0.5}>=0" 25100 skip ${7=200},${8=$7},${9=$8},${10=1} 25101 e[^-1] "Add $1 random stars to image$?, with depth $2, size $3, $4 branches, thickness $5, smoothness $6, 25102 color ($7,$8,$9) and opacity $10." 25103 if !$1 return fi 25104 25105 # Generate star sprites. 25106 star3d $4,$5 col3d. 255 *3d. $3 25107 l. repeat 4 {round(2*$3)},{round(2*$3)} j3d. [0],50%,50%,0,1,2,0,0 r3d[0] 0,0,1,-90 done rm[0] endl 25108 autocrop[-4--1] 0 r2dy[-4--1] $3 b[-4--1] $6,0 r[-4--1] 100%,100%,1,4 25109 repeat 4 sh[{-1-$>}] 0,2 fc. $7,$8,$9 rm. done 25110 25111 # Draw stars on selected images. 25112 repeat $!-1 [-4--1] l[$>,-4--1] 25113 N={round(if(${is_percent\ $1},w*h*$1,$1)/4,1,1)} 25114 repeat 4 25115 2,$N rand. -1,1 1,$N rand. 0,1 a[-2,-1] x 25116 i.. ('CImg3d') +.. 0.5 i.. ($N;$N) 25117 (1,0;1,{$N-1}) r. 2,$N,1,1,3 round. 4,$N,1,1,1 y[-5,-3--1] a[-5--1] y 25118 rv[-2,-1] sprites3d.. .,1 rm. *3d. {0.75*{0,w}},{0.75*{0,h}},{1000*$2} 25119 j3d[0] .,50%,50%,0,$10,0,0,0 rm. 25120 done 25121 endl done 25122 rm[-4--1] 25123 25124#@cli stencil : _radius[%]>=0,_smoothness>=0,_iterations>=0 25125#@cli : Apply stencil filter on selected images. 25126#@cli : Default values: 'radius=3', 'smoothness=1' and 'iterations=8'. 25127#@cli : $ image.jpg +norm stencil. 2,1,4 +mul rm[0] 25128stencil : check "${1=3}>=0 && ${2=1}>=0 && ${3=8}>=0" 25129 e[^-1] "Apply stencil filter on image$?, with radius $1, smoothness $2 and $3 iterations." 25130 n 0,1 repeat $3 b $1 unsharp {$1+$2},1000 c 0,255 done 25131 25132#@cli stencilbw : _edges>=0,_smoothness>=0 25133#@cli : Apply B&W stencil effect on selected images. 25134#@cli : Default values: 'edges=15' and 'smoothness=10'. 25135#@cli : $ image.jpg +stencilbw 40,4 25136stencilbw : skip ${1=15},${2=10} 25137 e[^-1] "Apply B&W stencil effect on image$?, with edges $1 and smoothness $2." 25138 repeat $! l[$>] split_opacity luminance[0] n[0] 0,255 25139 +edges[0] $1 quantize[0] 3,0,1 b[0] $2 25140 sharpen[0] 1000000 n[0] 0,1 *[0,-1] n[0] 0,255 25141 a c endl done 25142 25143#@cli stylize : [style_image],_fidelity_finest,_fidelity_coarsest,_fidelity_smoothness_finest>=0,\ 25144# _fidelity_smoothnes_coarsest>=0,0<=_fidelity_chroma<=1,_init_type,_init_resolution>=0,init_max_gradient>=0,\ 25145# _patchsize_analysis>0,_patchsize_synthesis>0,_patchsize_synthesis_final>0,_nb_matches_finest>=0,\ 25146# _nb_matches_coarsest>=0,_penalize_repetitions>=0,_matching_precision>=0,_scale_factor>1,_skip_finest_scales>=0,\ 25147# _"image_matching_command" 25148#@cli : Transfer colors and textures from specified style image to selected images, using a multi-scale \ 25149# patch-mathing algorithm. 25150#@cli : If instant display window[0] is opened, the steps of the image synthesis are displayed on it. 25151#@cli : 'init_type' can be { 0=best-match | 1=identity | 2=randomized }. 25152#@cli : Default values: 'fidelity_finest=0.5', 'fidelity_coarsest=2', 'fidelity_smoothness_finest=3', \ 25153# 'fidelity_smoothness_coarsest=0.5', 'fidelity_chroma=0.1', 'init_type=0', 'init_resolution=16', \ 25154# 'init_max_gradient=0', 'patchsize_analysis=5', 'patchsize_synthesis=5', 'patchsize_synthesis_final=5', \ 25155# 'nb_matches_finest=2', 'nb_matchesc_coarsest=30', 'penalize_repetitions=2', 'matching_precision=2', \ 25156# 'scale_factor=1.85', 'skip_finest_scales=0' and \ 25157# 'image_matching_command'="s c,-3 transfer_pca[0] [2] b[0,2] xy,0.7 n[0,2] 0,255 n[1,2] 0,200 \ 25158# a[0,1] c a[1,2] c"'. 25159stylize : 25160 check ${"is_image_arg $1"}" && isnum(${2=0.5}) && isnum(${3=2}) && ${4=3}>=0 && ${5=0.5}>=0 && ${6=0.1}>=0 && "\ 25161 "$6<=1 && isint(${7=0}) && $7>=0 && $7<=3 && isint(${8=16}) && $8>=0 && ${9=0}>=0 && isint(${10=5}) && "\ 25162 "$10>0 && isint(${11=5}) && $11>0 && isint(${12=$11}) && $12>0 && isint(${13=2}) && isint(${14=30}) && "\ 25163 "${15=2}>=0 && ${16=2}>=0 && ${17=1.85}>1 && isint(${18=0})>=0" 25164 skip "${19=s c,-3 transfer_pca[0] [2] b[0,2] xy,0.7 n[0,2] 0,255 n[1,2] 0,200 a[0,1] c a[1,2] c}" 25165 e[^-1] "Stylize image$? with style image $1." 25166 fidelity_finest,\ # $2 25167 fidelity_coarsest,\ # $3 25168 fidelity_smoothness_finest,\ # $4 25169 fidelity_smoothness_coarsest,\ # $5 25170 fidelity_chroma,\ # $6 25171 init_type,\ # $7 25172 init_resolution,\ # $8 25173 init_max_gradient,\ # $9 25174 patchsize_analysis,\ # $10 25175 patchsize_synthesis,\ # $11 25176 patchsize_synthesis_final,\ # $12 25177 nb_matches_finest,\ # $13 25178 nb_matches_coarsest,\ # $14 25179 penalize_repetitions,\ # $15 25180 matching_precision,\ # $16 25181 scale_factor,\ # $17 25182 skip_finest_scales=${2-18} \ # $18 25183 m "stylize_match : $19" 25184 25185 init_resolution={max(2*$patchsize_analysis,$init_resolution)} 25186 mprec0={round(2+1.5*$matching_precision)} 25187 mprec1={1+round(4*$matching_precision)} 25188 is_window={*} 25189 25190 pass$1 repeat $!-1 l[$>,-1] 25191 to_colormode.. {s} 25192 nb_scales={1+round(log(min(w#0,h#0,w#1,h#1)/$init_resolution)/log($scale_factor),1,-1)} 25193 if {*} wsiz=${"fitscreen "{0,[w,h]}} w[0] $wsiz,0,"[G'MIC Stylize]" fi 25194 25195 repeat $nb_scales,scale 25196 size_factor={100/($scale_factor^$<)} 25197 if !$scale 25198 25199 # Initialization. 25200 +r[0,1] $size_factor%,$size_factor%,100%,100%,2 ws,hs={-2,[w,h]} 25201 +to_color[0,1] channels[-2,-1] 0,2 gradient_norm[-2,-1] 25202 r. [-3],[-3],[-3],1,2 r.. [-4],[-4],[-4],1,2 25203 a[-3,-1] c a[-3,-1] c # Append gradient information as last channel 25204 stylize_match[-2,-1] 25205 if $init_type==0 25206 +matchpatch.. .,3,3,1,{2*$mprec0},{2*$mprec1},$penalize_repetitions # Initial image match with 3x3 patches 25207 else 25208 ..,..,1,2,"round([x,y]*([w#-1,h#-1]-1)/([w,h]-1))" # Identity 25209 if d#-2>1 channels. 0,2 fi 25210 if $init_type==2 eval. ">P = u([w,h]-1); tmp = I(P); I(P) = I; I() = tmp" fi # Randomize 25211 fi 25212 rm[-3,-2] 25213 if $init_max_gradient>0 # Keep only high gradients of target image 25214 +gradient_norm[0] r. ..,..,1,1,2 gt. $init_max_gradient 25215 +.. 1 *[-2,-1] _inpaint_warping2d. --. 1 25216 fi 25217 if $is_window" && "!{*} break fi 25218 25219 else 25220 25221 # Upscale. 25222 factor={1-($scale-1)/max(1,$nb_scales-2)} # Linear scale factor from 1 to 0 25223 +r[0,1] $size_factor%,$size_factor%,100%,100%,2 25224 +to_color[-2,-1] channels[-2,-1] 0,2 gradient_norm[-2,-1] 25225 25226 a[-3,-1] c a[-3,-1] c # Append gradient information as last channel 25227 stylize_match[-2,-1] mv[-2,-1] -3 25228 sh. 0 *. {-3,w/$ws} rm. sh. 1 *. {-3,h/$hs} rm. round. 25229 25230 # Smart upscale of displacement field. 25231 +. 1 r. ...,...,1,100%,4 -. 1 25232 do 25233 f. "begin(const boundary = 1; nx = ny = vectors(); nx[0] = ny[1] = 1); 25234 i>=0?I:( 25235 j(-1)>=0?J(-1) + nx: 25236 j(0,-1)>=0?J(0,-1) + ny: 25237 j(1)>0?J(1) - nx: 25238 j(0,1)>0?J(0,1) - ny:I)" 25239 while im<0 25240 ws,hs={-2,[w,h]} 25241 25242 if $<<$skip_finest_scales rm[-3,-2] continue fi # Skip finest scales 25243 +warp_patch.. .,$patchsize_synthesis,$patchsize_synthesis,1 25244 if {*} w. fi 25245 25246 # Inject gradients from target (in Lab colorspace). 25247 fidelity={max(0,$fidelity_finest+($fidelity_coarsest-$fidelity_finest)*$factor)} 25248 fidelity_smoothness={$fidelity_smoothness_finest+\ 25249 ($fidelity_smoothness_coarsest-$fidelity_smoothness_finest)*$factor} 25250 25251 if $fidelity>0.1 25252 sh. 0,2 sh[-5] 0,2 +gradient_norm[-2,-1] rm[-4,-3] # Gradient norm on colors only 25253 *. $fidelity argmax[-2,-1] b. xy,$fidelity_smoothness n. 0,{min(1,$fidelity)} 25254 sh[-5,-2] 0,2 srgb2lab[-2,-1] rm[-2,-1] 25255 +*. $fidelity_chroma r. 100%,100%,1,2,1 a[-2,-1] c j.. [-5],0,0,0,0,1,. rm. 25256 sh. 0,2 lab2srgb. rm. 25257 fi 25258 rm[-4] 25259 25260 # Iterate patch-matching steps. 25261 nb_matches={max(0,round($nb_matches_finest+($nb_matches_coarsest-$nb_matches_finest)*$factor^2))} 25262 nb_scales1={$nb_scales-1} 25263 nb_matches1={$nb_matches-1} 25264 if {*} +r. $wsiz,1,100% to. "Scale "$scale/$nb_scales1": 0%",5,2,24 w. -1,-1,0 rm. fi 25265 25266 repeat $nb_matches 25267 matchpatch. ...,$patchsize_analysis,$patchsize_analysis,1,$mprec0,$mprec1,$penalize_repetitions,0,.. 25268 -.. . abs.. diff={-2,ia} rm.. 25269 +warp_patch.. .,$patchsize_synthesis,$patchsize_synthesis,1 25270 if {*}" && "(!($>%5)" || "$nb_matches<=10) 25271 +r. $wsiz,1,100% 25272 to. "Scale "$scale/$nb_scales1": "{round(100*($>+1)/$nb_matches)}%,5,2,24 w. -1,-1,0 rm. 25273 fi 25274 if $is_window" && "!{*} break fi 25275 if $diff<1 break fi 25276 done 25277 rm[-3,-1] 25278 fi 25279 if $is_window" && "!{*} break fi 25280 done 25281 if $is_window" && "!{*} k[0,1] break fi 25282 25283 # Do final rendering. 25284 +warp_patch[1] .,$patchsize_synthesis_final,$patchsize_synthesis_final,1 c. 0,255 25285 rv[0,-1] rm[-2,-1] 25286 endl done rm. 25287 um stylize_match 25288 25289#@cli tetris : _scale>0 25290#@cli : Apply tetris effect on selected images. 25291#@cli : Default value: 'scale=10'. 25292#@cli : $ image.jpg +tetris 10 25293tetris : skip ${1=10} 25294 e[^-1] "Apply tetris effect on image$?, with scale $1." 25295 repeat $! l[$>] 25296 wh={w},{h},1,{s} r $1%,$1%,$1%,100%,2 n 0,255 quantize 10,1,0 r $wh b 2 sharpen 300,1 25297 endl done 25298 25299#@cli warhol : _M>0,_N>0,_smoothness>=0,_color>=0 25300#@cli : Create MxN Andy Warhol-like artwork from selected images. 25301#@cli : Default values: 'M=3', 'N=M', 'smoothness=2' and 'color=20'. 25302#@cli : $ image.jpg warhol 3,3,3,40 25303warhol : skip ${1=3},${2=$1},${3=2},${4=20} 25304 e[^-1] "Create $1x$2 Andy Warhol-like artwork from image$?." 25305 r0={100/max($1,$2)} 25306 repeat $! l[$>] 25307 norm b $3 r $r0%,$r0%,1,100%,2 quantize 6 n 0,5 round 1 25308 repeat $1 repeat $2 25309 (0,1,2,3,4,5) n. 32,224 6,1,1,2,128 noise. $4,0 c. 0,255 a[-2,-1] c ycbcr2rgb. +map[0] . rm.. 25310 done done append_tiles[^0] $1,$2 nm[1] {0,n} rm[0] 25311 endl done 25312 25313#@cli weave : _density>=0,0<=_thickness<=100,0<=_shadow<=100,_shading>=0,_fibers_amplitude>=0,_fibers_smoothness>=0,\ 25314# _angle,-1<=_x_curvature<=1,-1<=_y_curvature<=1 25315#@cli : Apply weave effect to the selected images. 25316#@cli : 'angle' can be { 0=0 deg. | 1=22.5 deg. | 2=45 deg. | 3=67.5 deg. }. 25317#@cli : Default values: 'density=6', 'thickness=65', 'shadow=40', 'shading=0.5', 'fibers_amplitude=0', _\ 25318# 'fibers_smoothness=0', 'angle=0' and 'curvature_x=curvature_y=0' 25319#@cli : $ image.jpg weave , 25320weave : check "${1=6}>=0 && ${2=65}>=0 && $2<=100 && ${3=40}>=0 && $3<=100 && ${4=0.5}>=0" 25321 check "${5=0}>=0 && ${6=0}>=0 && ${7=0}>=0 && $7<=3 && ${8=0}>=-1 && $8<=1 && ${9=0}>=-1 && $9<=1" 25322 e[^-1] "Apply weave effect to image$?, with $1 strips, thickness $2, shadow $3, shading $4, "\ 25323 "fibers amplitude $5 and fibers smoothness $6, angle "{$7*22.5}" deg. and curvatures ($8,$9)." 25324 repeat $! l[$>] split_opacity l[0] 25325 w={round(max(w,h)/$1,1,1)} h=$w s={(100-$3)*255%} p={max(0.01,$4)} 25326 25327 # Create patterns. 25328 1,$h =. 1,0,50% distance. 1 ^. $p c. 50%,100% r. {max(1,round($2*$w%))},100% 25329 $w,1 =. 1,50% distance. 1 ^. $p c. 50%,100% *. -1 r. 100%,{max(1,round($2*$h%))} 25330 +*. -1 +*... -1 n[-4,-2] 0,$s n[-3,-1] $s,255 25331 {w},1 1,... rand[-2,-1] 0,1 b[-2,-1] $6% n[-2,-1] -$5,$5 ri. [-4] +[-5] . +[-4,-1] +[-5] . +[-2,-1] 25332 +f... 255 a[-4,-1] c +f. 255 a[-2,-1] c 25333 25334 amp_x={$8*($w-w)/2} amp_y={$9*($w-w)/2} 25335 r[-4--1] $w,$h,1,100%,0,0,0.5,0.5 25336 f[-4] 'i(x+$amp_x*sin(y/h*pi),y,0,c,1,2)' f. 'i(x-$amp_x*sin(y/h*pi),y,0,c,1,2)' 25337 f... 'i(x,y+$amp_y*sin(x/w*pi),0,c,1,2)' f.. 'i(x,y-$amp_y*sin(x/w*pi),0,c,1,2)' 25338 blend[-4,-3] alpha blend[-2,-1] alpha c[-2,-1] 0,255 25339 25340 # Render full pattern and merge. 25341 /[-2,-1] 255 . ... a[-4,-2] x a[-2,-1] x a[-2,-1] y rotate_tileable. {$7*22.5} 25342 r. ..,..,1,1,0,2 *[-2,-1] 25343 endl a c endl done 25344 25345#@cli whirls : _texture>=0,_smoothness>=0,_darkness>=0,_lightness>=0 25346#@cli : Add random whirl texture to selected images. 25347#@cli : Default values: 'texture=3', 'smoothness=6', 'darkness=0.5' and 'lightness=1.8'. 25348#@cli : $ image.jpg whirls , 25349whirls : skip ${1=3},${2=6},${3=0.5},${4=1.8} 25350 e[^-1] "Add random whirl texture to image$?, with texture $1, smoothness $2, darkness $3 and lightness $4." 25351 repeat $! l[$>] 25352 100%,100% noise. 0.3,2 ==. 1 repeat $1 b. $2 +. 0.1 gradient_norm. ^. 0.2 done 25353 n. $3,$4 ri. .. * c 0,255 25354 endl done 25355 25356#------------------------------------ 25357# 25358#@cli :: Warpings 25359# 25360#------------------------------------ 25361 25362#@cli deform : _amplitude>=0,_interpolation 25363#@cli : Apply random smooth deformation on selected images. 25364#@cli : 'interpolation' can be { 0=none | 1=linear | 2=bicubic }. 25365#@cli : Default value: 'amplitude=10'. 25366#@cli : $ image.jpg +deform[0] 10 +deform[0] 20 25367deform : skip ${1=10},${2=1} 25368 e[^-1] "Apply random smooth deformation on image$?, with amplitude $1." 25369 repeat $! l[$>] 25370 2%,2%,1,2 noise. $1 r. ..,..,1,2,5 warp.. .,1,$2,1 rm. 25371 endl done 25372 25373#@cli euclidean2polar : _center_x[%],_center_y[%],_stretch_factor>0,\ 25374# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 25375#@cli : Apply euclidean to polar transform on selected images. 25376#@cli : Default values: 'center_x=center_y=50%', 'stretch_factor=1' and 'boundary_conditions=1'. 25377#@cli : $ image.jpg +euclidean2polar , 25378euclidean2polar : skip ${1=50%},${2=50%} check "${3=1}>0 && isint(${4=1}) && $4>=0 && $4<=3" 25379 e[^-1] "Apply euclidean to polar transform on image$?, with center point ($1,$2), stretch factor $3 and "\ 25380 ${"arg 1+$4,dirichlet,neumann,periodic,mirror"}" boundary conditions." 25381 repeat $! l[$>] 25382 cx={if(${is_percent\ $1},$1*(w-1),$1)} 25383 cy={if(${is_percent\ $2},$2*(h-1),$2)} 25384 R={sqrt(max($cx^2,(w-1-$cx)^2)+max($cy^2,(h-1-$cy)^2))} 25385 f 'r=$R*(x/(w-1))^$3;a=y*2*pi/(h-1);i($cx+r*cos(a),$cy+r*sin(a),z,c,1,$4)' 25386 endl done 25387 25388#@cli equirectangular2nadirzenith 25389#@cli : Transform selected equirectangular images to nadir/zenith rectilinear projections. 25390equirectangular2nadirzenith : 25391 e[^-1] "Transform equirectangular image$? to nadir/zenith rectilinear projections." 25392 repeat $! l[$>] 25393 100%,100%,1,2 25394 sh. 100% 25395 f. " 25396 X = 2*x/(w-1) - 1; 25397 Y = y/(h-1) - 0.5; 25398 if (X<0, 25399 sinphi1 = 1; X+=0.5, 25400 sinphi1 = -1; X-=0.5 25401 ); 25402 rr = sqrt(X*X + Y*Y); 25403 cc = atan(2*rr); 25404 phi = rr==0?0:asin(cos(cc)*sinphi1); 25405 X = atan2(X,-Y*sinphi1)/pi; 25406 Y = phi/pi; 25407 (++X)*=0.5*w; 25408 (Y+=0.5)*=h; 25409 i(#-2) = X; Y;" 25410 warp[0] [1],0,0,1 k... 25411 endl done 25412 25413#@cli fisheye : _center_x,_center_y,0<=_radius<=100,_amplitude>=0 25414#@cli : Apply fish-eye deformation on selected images. 25415#@cli : Default values: 'x=y=50', 'radius=50' and 'amplitude=1.2'. 25416#@cli : $ image.jpg +fisheye , 25417fisheye : skip ${1=50},${2=50},${3=50},${4=1.2} 25418 e[^-1] "Apply Fish-eye effect on image$?, centered at ($1%,$2%) with radius $3% and amplitude $4." 25419 if $4==0 return fi 25420 repeat $! l[$>] 25421 100%,100%,1,1 =. 1,$1%,$2% distance. 1 c. 0,$3% *. -1 n. 0,1 ^. {1/$4} 25422 i.. ({-$1/100},{1-$1/100};{-$1/100},{1-$1/100}^{-$2/100},{-$2/100};{1-$2/100},{1-$2/100}) r.. .,.,1,2,3 25423 n. 0,{max(w,h)} *[-2,-1] 25424 warp.. .,1,1,1 rm. 25425 endl done 25426 25427#@cli flower : _amplitude,_frequency,_offset_r[%],_angle,_center_x[%],_center_y[%],\ 25428# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror} 25429#@cli : Apply flower deformation on selected images. 25430#@cli : Default values: 'amplitude=30', 'frequency=6', 'offset_r=0', 'angle=0', 'center_x=center_y=50%' \ 25431# and 'boundary_conditions=3'. 25432#@cli : $ image.jpg +flower , 25433flower : skip ${1=30},${2=6},${3=0},${4=0},${5=50%},${6=50%},${7=3} 25434 e[^-1] "Apply flower deformation on image$?, with amplitude $1, frequency $2, offset $3, angle $4 deg. and 25435 center point ($1,$2)." 25436 if ${"is_percent $3"} 25437 transform_polar "r + (R*$3) + R*$1/100*cos(a*$2+$4*pi/180)","a",$5,$6,$7 25438 else 25439 transform_polar "r + $3 + R*$1/100*cos(a*$2+$4*pi/180)","a",$5,$6,$7 25440 fi 25441 25442#@cli kaleidoscope : _center_x[%],_center_y[%],_radius,_angle,\ 25443# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 25444#@cli : Create kaleidoscope effect from selected images. 25445#@cli : Default values: 'center_x=center_y=50%', 'radius=100', 'angle=30' and 'boundary_conditions=3'. 25446#@cli : $ image.jpg kaleidoscope , 25447kaleidoscope : skip ${1=50%},${2=50%},${3=100},${4=30},${5=3} 25448 e[^-1] "Create kaleidoscope effect from image$?, with center point ($1,$2), radius $3, angle $4 deg." 25449 euclidean2polar $1,$2,1,$5 repeat $! l[$>] 25450 +columns 0,$3% rows. 0,$4% ri. ..,0,2 nm[1] {0,n} rm[0] 25451 endl done polar2euclidean $1,$2,1,$5 25452 25453#@cli map_sphere : _width>0,_height>0,_radius,_dilation>0,_fading>=0,_fading_power>=0 25454#@cli : Map selected images on a sphere. 25455#@cli : Default values: 'width=height=512', 'radius=100', 'dilation=0.5', 'fading=0' and 'fading_power=0.5'. 25456#@cli : $ image.jpg map_sphere , 25457map_sphere : check "${1=512}>0 && ${2=512}>0 && ${5=0}>=0 && ${6=0.5}>=0" skip ${3=100},${4=0.5} 25458 e[^-1] "Map image$? on spheres in $1x$2 images, with radius $3, dilation $4 and fading $5." 25459 r2={($3*min($1,$2)/200)^2} # Compute squared radius. 25460 repeat $! l[$>] 25461 i.. 100%,1,1,100%,0 nm[0] {1,n} a y # Add one border line to have a sphere exterior. 25462 ({-$1/2},{$1/2}) ({-$2/2};{$2/2}) r[-2,-1] $1,$2,1,1,3 atan2. .. rm.. # Compute theta angle. 25463 $1,$2 =. 1,50%,50% distance. 1,3 /. $r2 sqrt. c. 0,1 25464 asin. # Compute phi angle. 25465 +.. {pi} *.. {({-3,w}-1)/(2*pi)} # Normalize theta to X-coordinates 25466 *. {2/pi} ^. $4 *. {{-3,h}-1} *. -1 +. {{-3,h}-1} # Normalize phi to Y-coordinates 25467 if $5 +>=. 1 distance. 1 c. 0,$5% n. 0,1 ^. $6 c.. 1,100% -[-2,-1] fi 25468 r[-1,-2] 100%,100%,{-3,d} 25469 +f. z a[-3--1] c 25470 warp.. .,0,1,1 rm. # Apply image warping 25471 endl done 25472 25473#@cli nadirzenith2equirectangular 25474#@cli : Transform selected nadir/zenith rectilinear projections to equirectangular images. 25475nadirzenith2equirectangular : 25476 e[^-1] "Transform nadir/zenith rectilinear projection$? to equirectangular images." 25477 repeat $! l[$>] 25478 100%,100%,1,2 25479 sh. 100% 25480 f. " 25481 X = 2*x/(w-1) - 1; 25482 Y = y/(h-1) - 0.5; 25483 output = 1; 25484 if (Y>0.125, 25485 sinphi1 = 1; xc = -0.5, 25486 if (Y<-0.125, 25487 sinphi1 = -1; xc = 0.5, 25488 output = 0 25489 )); 25490 cosc = sinphi1*sin(Y*pi); 25491 xx = cos(Y*pi)*sin(X*pi)/cosc; 25492 yy = -sinphi1*cos(Y*pi)*cos(X*pi)/cosc; 25493 if (abs(xx)>1, output=0); 25494 (xx*=0.5)+=xc; 25495 yy*=0.5; 25496 if (!output, xx = yy = -1); 25497 (++xx)*=0.5*w; 25498 (yy+=0.5)*=h; 25499 i(#-2) = xx; yy;" 25500 to_a[0] warp[0] [1],0,0,0 k... 25501 endl done 25502 25503#@cli polar2euclidean : _center_x[%],_center_y[%],_stretch_factor>0,\ 25504# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 25505#@cli : Apply euclidean to polar transform on selected images. 25506#@cli : Default values: 'center_x=center_y=50%', 'stretch_factor=1' and 'boundary_conditions=1'. 25507#@cli : $ image.jpg +euclidean2polar , 25508polar2euclidean : skip ${1=50%},${2=50%} check "${3=1}>0 && isint(${4=1}) && $4>=0 && $4<=3" 25509 e[^-1] "Apply polar to euclidean transform on image$?, with center point ($1,$2), stretch factor $3 and "\ 25510 ${"arg 1+$4,dirichlet,neumann,periodic,mirror"}" boundary conditions." 25511 repeat $! l[$>] 25512 cx={if(${is_percent\ $1},$1*(w-1),$1)} 25513 cy={if(${is_percent\ $2},$2*(h-1),$2)} 25514 R={sqrt(max($cx^2,(w-1-$cx)^2)+max($cy^2,(h-1-$cy)^2))} 25515 f "X = sqrt((x-"$cx")^2+(y-"$cy")^2); 25516 tmp = atan2((y-"$cy"),(x-"$cx")); 25517 Y = if(tmp<0,tmp+2*pi,tmp); 25518 i((X/"$R")^(1/$3)*(w-1),Y*(h-1)/(2*pi),z,c,1,$4)" 25519 endl done 25520 25521#@cli raindrops : _amplitude,_density>=0,_wavelength>=0,_merging_steps>=0 25522#@cli : Apply raindrops deformation on selected images. 25523#@cli : Default values: 'amplitude=80','density=0.1', 'wavelength=1' and 'merging_steps=0'. 25524#@cli : $ image.jpg +raindrops , 25525raindrops : check "${2=0.1}>=0 && ${3=1}>=0 && isint(${4=0}) && $4>=0" skip ${1=80} 25526 e[^-1] "Apply raindrops deformation on image$?, with amplitude $1, density $2, wavelength $3 and $4 merging steps." 25527 repeat $! l[$>] 25528 100%,100% noise. $2,2 ==. 1 distance. 1 f. 'cos(i)/(1+i/(1e-8+$3))' 25529 if $4 25530 i.. (0,1,0;1,0,1;0,1,0) /.. 2 . 25531 repeat $4 +convolve. ...,1 -. ... rm... done rm[-3,-2] 25532 fi 25533 g. a[-2,-1] c *. {$1/(1e-5+max(abs(im),abs(iM)))} 25534 warp.. .,1 rm. 25535 endl done 25536 25537#@cli ripple : _amplitude,_bandwidth,_shape={ 0=bloc | 1=triangle | 2=sine | 3=sine+ | 4=random },_angle,_offset 25538#@cli : Apply ripple deformation on selected images. 25539#@cli : Default values: 'amplitude=10', 'bandwidth=10', 'shape=2', 'angle=0' and 'offset=0'. 25540#@cli : $ image.jpg +ripple , 25541ripple : skip ${1=10},${2=20},${3=2},${4=0},${5=0} 25542 e[^-1] "Apply ripple deformation on image$?, with amplitude $1, bandwidth $2, shape $3, angle $4 deg. and offset $5." 25543 theta={$4*pi/180} C={cos($theta)} S={-sin($theta)} 25544 repeat $! l[$>] 25545 100%,100%,1,1,"x" -. {w/2} 100%,100%,1,1,'y' 25546 -. {h/2-$5} *.. $S *. $C +[-2,-1] # Generate rotated Y. 25547 _ripple$3. $1,$2 # Generate warp field. 25548 +*. {-$S} *.. $C a[-2,-1] c # Rotate warp field. 25549 warp.. .,1 rm. 25550 endl done 25551 25552_ripple0 : f {$1/2}*"(1-2*(i%"{2*$2}"<$2))" 25553_ripple1 : f "I=(i%$2)/$2;$1*(2*if(I<0.5,I,1-I)-0.5)" 25554_ripple2 : f {-$1/2}*"cos(i*"{2*pi/$2}")" 25555_ripple3 : f {-$1/2}*"abs(cos(i*"{2*pi/$2}"))" 25556_ripple4 : skip $* n 0,{h-1} 1,{h} rand. {-$1/2},{$1/2} m={im} M={iM} b. {$2/10} n. $m,$M map.. . rm. 25557 25558#@cli rotoidoscope : _center_x[%],_center_y[%],_tiles>0,_smoothness[%]>=0,\ 25559# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 25560#@cli : Create rotational kaleidoscope effect from selected images. 25561#@cli : Default values: 'center_x=center_y=50%', 'tiles=10', 'smoothness=1' and 'boundary_conditions=3'. 25562#@cli : $ image.jpg +rotoidoscope , 25563rotoidoscope : skip ${1=50%},${2=50%},${5=1} check "${3=10}>0 && ${4=3}>=0" 25564 e[^-1] "Create rotational kaleidoscope effect from image$?, with center point ($1,$2), $3 tiles and smoothness $4." 25565 repeat $! l[$>] 25566 repeat $3 +rotate[0] {360/$3},1,$5,$1,$2 blend_edges $4 done 25567 endl done 25568 25569#@cli spherize : _radius[%]>=0,_strength,_smoothness[%]>=0,_center_x[%],_center_y[%],_ratio_x/y>0,_angle,\ 25570# _interpolation 25571#@cli : Apply spherize effect on selected images. 25572#@cli : Default values: 'radius=50%', 'strength=1', 'smoothness=0', 'center_x=center_y=50%', 'ratio_x/y=1', \ 25573# 'angle=0' and 'interpolation=1'. 25574#@cli : $ image.jpg grid 5%,5%,0,0,0.6,255 spherize , 25575spherize : check "${1=50%}>=0 && ${3=0}>=0 && ${6=1}>0 && isint(${8=1}) && $8>=0 && $8<=2" 25576 skip "${2=1},${4=50%},${5=50%},${7=0}" 25577 e[^-1] "Apply spherize effect on image$?, with radius $1, strength $2, smoothness $3, center ($4,$5), 25578 x/y-ratio $6, angle $7 and "${"arg 1+$8,nearest-neighbor,linear,cubic"}" interpolation." 25579 if !$1||!$2 return fi 25580 repeat $! l[$>] 25581 rmax={${"is_percent $1"}?0.5*sqrt((w-1)^2+(h-1)^2)*$1:$1} 25582 centerx={${"is_percent $4"}?(w-1)*$4:$4} 25583 centery={${"is_percent $5"}?(h-1)*$5:$5} 25584 strength={$2>0?$2:1-exp($2/5)} 25585 100%,100%,1,2," 25586 begin( 25587 center = [ "$centerx","$centery" ]; 25588 wh1 = [ w,h ] - 1; 25589 m2wh1 = 0.5*max(wh1); 25590 rmax = "$rmax"/m2wh1; 25591 const f = 1/"$strength"; 25592 const ratio = $6; 25593 rotf = rot($7°); 25594 rotb = rot(-$7°); 25595 ); 25596 xy = ([x,y] - center)/m2wh1; 25597 xy = rotf*xy; 25598 ratio>=1?(xy[1]*=ratio):(xy[0]/=ratio); 25599 r = norm2(xy); 25600 z = r<rmax?sign($2)*sqrt(rmax^2 - r^2):0; 25601 ratio>=1?(xy[1]/=ratio):(xy[0]*=ratio); 25602 xy = rotb*xy; 25603 xy = center + f*xy/(f + z)*m2wh1" 25604 b. $3 25605 warp.. .,0,$8,1 rm. 25606 endl done 25607 25608#@cli symmetrize : _x[%],_y[%],_angle,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror },\ 25609# _is_antisymmetry={ 0 | 1 },_swap_sides={ 0 | 1 } 25610#@cli : Symmetrize selected images regarding specified axis. 25611#@cli : Default values: 'x=y=50%', 'angle=90', 'boundary_conditions=3', 'is_antisymmetry=0' and 'swap_sides=0'. 25612#@cli : $ image.jpg +symmetrize 50%,50%,45 +symmetrize[-1] 50%,50%,-45 25613symmetrize : skip ${1=50%},${2=50%},${3=90},${4=3},${5=0},${6=0} 25614 e[^-1] "Symmetrize image$?, regarding axis ($1,$2,$3 deg.)." 25615 theta={$3*pi/180} u={cos($theta)} v={sin($theta)} 25616 if $6 symmetry_cond=A<0 else symmetry_cond=A>0 fi 25617 repeat $! l[$>] 25618 x0={if(${is_percent\ $1},w*$1,$1)} 25619 y0={if(${is_percent\ $2},h*$2,$2)} 25620 if $5 f 'A=($y0-y)*$u-($x0-x)*$v;X=x+2*($x0-x);Y=y+2*($y0-y);if($symmetry_cond,i(X,Y,z,c,1,$4),i)' 25621 else f 'A=($y0-y)*$u-($x0-x)*$v;X=x-2*$v*A;Y=y+2*$u*A;if($symmetry_cond,i(X,Y,z,c,1,$4),i)' 25622 fi 25623 endl done 25624 25625#@cli transform_polar : "expr_radius",_"expr_angle",_center_x[%],_center_y[%],\ 25626# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 25627#@cli : Apply user-defined transform on polar representation of selected images. 25628#@cli : Default values: 'expr_radius=R-r', 'expr_rangle=a', 'center_x=center_y=50%' and 'boundary_conditions=1'. 25629#@cli : $ image.jpg +transform_polar[0] R*(r/R)^2,a +transform_polar[0] r,2*a 25630transform_polar : skip "${1=R-r}","${2=a}",${3=50%},${4=50%},${5=1} 25631 e[^-1] "Apply custom polar transform with 'new_r = $1', 'new_a = $2', center point ($3%,$4%)." 25632 repeat $! l[$>] 25633 cx={if(${is_percent\ $3},$3*(w-1),$3)} 25634 cy={if(${is_percent\ $4},$4*(h-1),$4)} 25635 R={sqrt(max($cx^2,(w-1-$cx)^2)+max($cy^2,(h-1-$cy)^2))} 25636 f "R ="$R"; 25637 r = sqrt((x-"$cx")^2 + (y-"$cy")^2); 25638 a = atan2(y-"$cy",x-"$cx"); 25639 nr = ($1); 25640 na = ($2); 25641 i("$cx" + nr*cos(na), "$cy" + nr*sin(na), z, c,1,$5)" 25642 endl done 25643 25644#@cli twirl : _amplitude,_center_x[%],_center_y[%],\ 25645# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 25646#@cli : Apply twirl deformation on selected images. 25647#@cli : Default values: 'amplitude=1', 'center_x=center_y=50%' and 'boundary_conditions=3'. 25648#@cli : $ image.jpg twirl 0.6 25649twirl : skip ${1=1},${2=50%},${3=50%},${4=3} 25650 e[^-1] "Apply twirl deformation on image$?, with amplitude $1 and center point at ($2%,$3%)." 25651 euclidean2polar $2,$3,1,$4 repeat $! 25652 [$>],[$>],1,1,$1*x channels. -1,0 warp[$>] .,1,1,2 rm. 25653 done polar2euclidean $2,$3,1,1 25654 25655#@cli warp_perspective : _x-angle,_y-angle,_zoom>0,_x-center,_y-center,\ 25656# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 25657#@cli : Warp selected images with perspective deformation. 25658#@cli : Default values: 'x-angle=1.5', 'y-angle=0', 'zoom=1', 'x-center=y-center=50' and 'boundary_conditions=2'. 25659#@cli : $ image.jpg warp_perspective , 25660warp_perspective : skip ${1=1.5},${2=0},${3=1},${4=50},${5=50},${6=2} 25661 e[^-1] "Apply perspective warp on image$?, with angles ($1 deg.,$2 deg.), zoom $3 and offsets ($4,$5)." 25662 repeat $! l[$>] 25663 (0,100) -. $4 /. 100 (0;100) -. $5 /. 100 r[-2,-1] ...,...,...,1,3 25664 +*.. $2 +*.. $1 +[-2,-1] +. $3 /... . /[-2,-1] 25665 *.. 100 +.. $4 /.. 100 *.. {-3,w} 25666 *. 100 +. $5 /. 100 *. {-3,h} 25667 a[-2,-1] c warp.. .,0,1,$6 rm. 25668 endl done 25669 25670#@cli water : _amplitude,_smoothness>=0,_angle 25671#@cli : Apply water deformation on selected images. 25672#@cli : Default values: 'amplitude=30', 'smoothness=1.5' and 'angle=45'. 25673#@cli : $ image.jpg water , 25674water : check ${2=1.5}>=0 skip ${1=30},${3=1},${4=45} 25675 e[^-1] "Apply water deformation on image$?, with amplitude $1, smoothness $2 and angle $3." 25676 repeat $! l[$>] 25677 25%,25%,25%,1 noise. $1 g. xy *.. {-sin($3*pi/180)} *. {cos($3*pi/180)} +[-2,-1] b. $2 *. 2 25678 r. ..,..,1,2,3 warp.. .,1 rm. 25679 endl done 25680 25681#@cli wave : _amplitude>=0,_frequency>=0,_center_x,_center_y 25682#@cli : Apply wave deformation on selected images. 25683#@cli : Default values: 'amplitude=4', 'frequency=0.4' and 'center_x=center_y=50'. 25684#@cli : $ image.jpg wave , 25685wave : skip ${1=4},${2=0.4},${3=50},${4=50} 25686 e[^-1] "Apply wave deformation on image$?, with amplitude $1, frequency $2 and center point at ($3%,$4%)." 25687 repeat $! l[$>] 25688 100%,100% =. 1,$3%,$4% distance. 1 25689 *. $2 +sin. cos.. a[-2,-1] c *. $1 25690 warp.. .,1 rm. 25691 endl done 25692 25693#@cli wind : _amplitude>=0,_angle,0<=_attenuation<=1,_threshold 25694#@cli : Apply wind effect on selected images. 25695#@cli : Default values: 'amplitude=20', 'angle=0', 'attenuation=0.7' and 'threshold=20'. 25696#@cli : $ image.jpg +wind , 25697wind : check "isint(${1=20}) && $1>=0 && ${3=0.7}>=0 && $3<=1" skip "${2=0},${4=20}" 25698 e[^-1] "Apply wind effect on image$?, with amplitude $1, angle "{round($2/45)*45}" deg., attenuation $3 25699 and threshold $4." 25700 if !$1 return fi 25701 dxdy=${-_wind{round($2/45)%8}} 25702 fact={(1-$3)^(1/$1)} 25703 repeat $! l[$>] 25704 +gradient_norm >=. $4% 25705 r. 100%,100%,1,.. *. .. 25706 repeat $1 25707 shift. $dxdy,0,0,0 max.. . *. $fact 25708 remove_pixels. {100/$1}% 25709 done rm. 25710 endl done 25711 25712_wind0 : u 1,0 25713_wind1 : u 1,1 25714_wind2 : u 0,1 25715_wind3 : u -1,1 25716_wind4 : u -1,0 25717_wind5 : u -1,-1 25718_wind6 : u 0,-1 25719_wind7 : u 1,-1 25720 25721#@cli zoom : _factor,_cx,_cy,_cz,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 25722#@cli : Apply zoom factor to selected images. 25723#@cli : Default values: 'factor=1', 'cx=cy=cz=0.5' and 'boundary_conditions=0'. 25724#@cli : $ image.jpg +zoom[0] 0.6 +zoom[0] 1.5 25725zoom : skip ${1=2},${2=0.5},${3=0.5},${4=0.5},${5=0} 25726 e[^-1] "Apply zoom effect on image$?, with factor $1 and center ($2,$3)." 25727 repeat $! l[$>] 25728 if d==1 # 2D image. 25729 ({(w-1)*$2*(1-1/$1)},{(w-1)*($2+(1-$2)/$1)}) 25730 ({({-2,h}-1)*$3*(1-1/$1)};{({-2,h}-1)*($3+(1-$3)/$1)}) 25731 r[-2--1] ...,...,1,1,3 a[-2--1] c warp.. .,0,1,$5 25732 else # 3D image. 25733 ({(w-1)*$2*(1-1/$1)},{(w-1)*($2+(1-$2)/$1)}) 25734 ({({-2,h}-1)*$3*(1-1/$1)};{({-2,h}-1)*($3+(1-$3)/$1)}) 25735 ({({-3,d}-1)*$4*(1-1/$1)}/{({-3,d}-1)*($4+(1-$4)/$1)}) 25736 r[-3--1] [-4],[-4],[-4],1,3 a[-3--1] c warp.. .,0,1,$5 25737 fi 25738 rm. 25739 endl done 25740 25741#----------------------------- 25742# 25743#@cli :: Degradations 25744# 25745#----------------------------- 25746 25747#@cli cracks : 0<=_density<=100,_is_relief={ 0 | 1 },_opacity,_color1,... 25748#@cli : Draw random cracks on selected images with specified color. 25749#@cli : Default values: 'density=25', 'is_relief=0', 'opacity=1' and 'color1=0'. 25750#@cli : $ image.jpg +cracks , 25751cracks : check "${1=25}>=0" skip ${2=0},${3=1},${4=0} 25752 e[^-1] "Add random cracks to image$?, with density $1, opacity $3 and color (${4--1})." 25753 repeat $! l[$>] cut={[im,iM]} 25754 100%,100%,1,2,'u<0.25*($1%)^4?[u,1]:[0,0]' 25755 s. c distance. 1 *. -1 watershed.. . rm. 25756 +dilate. 3 -[-2,-1] !=. 0 # thinning. 1 25757 if $2 25758 f. "i?i:j(1)?2:j(-1)?0.5:i" n. 0,1 25759 +fc.. ${4--1} *. .. !=.. 0 j... .,0,0,0,0,$3,.. 25760 else 25761 +fc.. ${4--1} j... .,0,0,0,0,$3,.. 25762 fi 25763 k[0] 25764 endl done 25765 25766#@cli light_patch : _density>0,_darkness>=0,_lightness>=0 25767#@cli : Add light patches to selected images. 25768#@cli : Default values: 'density=10', 'darkness=0.9' and 'lightness=1.7'. 25769#@cli : $ image.jpg +light_patch 20,0.9,4 25770light_patch : skip ${1=10},${2=0.9},${3=1.7} 25771 e[^-1] "Apply light patches to image$?, with density $1, darkness $2 and lightness $3." 25772 repeat $! l[$>] 25773 n 0,255 $1,$1 noise. 40 ri. ..,5 c. 0,255 25774 n. $2,$3 * c 0,255 25775 endl done 25776 25777#@cli noise_hurl : _amplitude>=0 25778#@cli : Add hurl noise to selected images. 25779#@cli : Default value: 'amplitude=10'. 25780#@cli : $ image.jpg +noise_hurl , 25781noise_hurl : skip ${1=10} 25782 e[^-1] "Add hurl noise to image$?, with amplitude $1%." 25783 repeat $! l[$>] 25784 +f 0 noise. 10 n. {-2,[im,iM]} 100%,100% 25785 noise. $1,2 >. 0 ri. .. 25786 *.. . *. -1 +. 1 *[-3,-1] + 25787 endl done 25788 25789#@cli pixelize : _scale_x>0,_scale_y>0,_scale_z>0 25790#@cli : Pixelize selected images with specified scales. 25791#@cli : Default values: 'scale_x=20' and 'scale_y=scale_z=scale_x'. 25792#@cli : $ image.jpg +pixelize , 25793pixelize : skip ${1=20},${2=$1},${3=$1} 25794 e[^-1] "Pixelize image$? with scales ($1%,$2%,$3%)." 25795 repeat $! l[$>] whd={w},{h},{d} r $1%,$2%,$3%,100%,2 r $whd endl done 25796 25797#@cli scanlines : _amplitude,_bandwidth,_shape={ 0=bloc | 1=triangle | 2=sine | 3=sine+ | 4=random },_angle,_offset 25798#@cli : Apply ripple deformation on selected images. 25799#@cli : Default values: 'amplitude=60', 'bandwidth=2', 'shape=0', 'angle=0' and 'offset=0'. 25800#@cli : $ image.jpg +scanlines , 25801scanlines : skip ${1=60},${2=2},${3=0},${4=0},${5=0} 25802 e[^-1] "Apply scanlines effect on image$?, with amplitude $1, bandwidth $2, shape $3, angle $4 deg. and offset $5." 25803 theta={$4*pi/180} C={cos($theta)} S={-sin($theta)} 25804 repeat $! l[$>] 25805 100%,100%,1,1,"x" -. {w/2} 100%,100%,1,1,'y' 25806 -. {h/2-$5} *.. $S *. $C +[-2,-1] # Generate rotated Y. 25807 _ripple$3. $1,$2 # Generate warp field. 25808 n. {-$1},$1 25809 + cut 0,255 25810 endl done 25811 25812#@cli shade_stripes : _frequency>=0,_direction={ 0=horizontal | 1=vertical },_darkness>=0,_lightness>=0 25813#@cli : Add shade stripes to selected images. 25814#@cli : Default values: 'frequency=5', 'direction=1', 'darkness=0.8' and 'lightness=2'. 25815#@cli : $ image.jpg +shade_stripes 30 25816shade_stripes : skip ${1=5},${2=1},${3=0.8},${4=2} 25817 e[^-1] "Add "${arg\ 1+!$2,vertical,horizontal}" shaded stripes to image$?, with frequency $1, darkness $3 and 25818 lightness $4." 25819 n 0,255 repeat $! l[$>] 25820 {max(1,w*($2!=0))},{max(1,h*($2==0))} noise. $1,2 ==. 1 distance. 1 ri. .. n. $3,$4 * c 0,255 25821 endl done 25822 25823#@cli shadow_patch : _opacity>=0 25824#@cli : Add shadow patches to selected images. 25825#@cli : Default value: 'opacity=0.7'. 25826#@cli : $ image.jpg +shadow_patch 0.4 25827shadow_patch : skip ${1=0.7} 25828 e[^-1] "Apply shadow patches to image$?, with opacity $1." 25829 repeat $! l[$>] 25830 100%,100%,1,1 shift. -2,-2 shift. 1,1 25831 plasma. 3,0.3,8 abs. b. 1 c. 3%,15% ri. .. 25832 n. $1,1 * 25833 endl done 25834 25835#@cli spread : _dx>=0,_dy>=0,_dz>=0 25836#@cli : Spread pixel values of selected images randomly along x,y and z. 25837#@cli : Default values: 'dx=3', 'dy=dx' and 'dz=0'. 25838#@cli : $ image.jpg +spread 3 25839spread : skip ${1=3},${2=$1},${3=0} 25840 e[^-1] "Spread pixel of image$? randomly, with amplitudes ($1,$2,$3)." 25841 repeat $! l[$>] 25842 100%,100%,100%,3 25843 sh. 0 rand. {-$1},$1 rm. 25844 sh. 1 rand. {-$2},$2 rm. 25845 sh. 2 rand. {-$3},$3 rm. 25846 warp.. .,1 rm. 25847 endl done 25848 25849#@cli stripes_y : _frequency>=0 25850#@cli : Add vertical stripes to selected images. 25851#@cli : Default value: 'frequency=10'. 25852#@cli : $ image.jpg +stripes_y , 25853stripes_y : skip ${1=10} 25854 e[^-1] "Add vertical stripes to image$?, with frequency $1." 25855 repeat $! l[$>] 25856 100% noise. $1,2 ==. 1 *. 255 ri. .. 25857 *. 0.15 + c 0,255 25858 endl done 25859 25860#@cli texturize_canvas : _amplitude>=0,_fibrousness>=0,_emboss_level>=0 25861#@cli : Add paint canvas texture to selected images. 25862#@cli : Default values: 'amplitude=20', 'fibrousness=3' and 'emboss_level=0.6'. 25863#@cli : $ image.jpg +texturize_canvas , 25864texturize_canvas : check "${1=20}>=0 && ${2=3}>=0 && ${3=0.6}>=0 && ${4=80}" 25865 e[^-1] "Add canvas texture to image$?, with amplitude $1, fibrousness $2 and emboss level $3." 25866 repeat $! l[$>] 25867 {w},{h} rand. 0,255 +blur_x. $2 blur_y.. $2 +[-2,-1] g. a[-2,-1] c 25868 +compose_channels. + orientation.. compose_channels.. + n.. $3,1 n. 0,255 25869 sharpen. 80 *[-2,-1] n. -$1,$1 + c 0,255 25870 endl done 25871 25872#@cli texturize_paper 25873#@cli : Add paper texture to selected images. 25874#@cli : $ image.jpg +texturize_paper 25875texturize_paper : 25876 e[^-1] "Add paper texture to image$?." 25877 repeat $! l[$>] 25878 . 30%,30% noise. 1,2 ==. 1 r. ..,..,..,1,0 ifft. 25879 rm. shift. {round(w/2)},{round(h/2)},{round(d/2)},0,2 sharpen. 1 n. 1,1.2 ri. .. 25880 *[-2,-1] c. ..,.. rm.. 25881 endl done 25882 25883#@cli vignette : _strength>=0,0<=_radius_min<=100,0<=_radius_max<=100 25884#@cli : Add vignette effect to selected images. 25885#@cli : Default values: 'strength=100', 'radius_min=70' and 'radius_max=90'. 25886#@cli : $ image.jpg vignette , 25887vignette : check "${1=100}>=0 && ${2=70}>=0 && $2<=100 && ${3=90}>=0 && $3<=100" 25888 e[^-1] "Add vignette effect to image$?, with strength $1 and size $2." 25889 repeat $! l[$>] 25890 mM={[im,iM]} d={max(w,h)} 25891 $d,$d =. 1,50%,50% distance. 1 ri. ..,2 25892 c. $2%,$3% n. 0,$1 - c $mM 25893 endl done 25894 25895#@cli watermark_visible : _text,0<_opacity<1,_size>0,_angle,_mode={ 0=remove | 1=add },_smoothness>=0 25896#@cli : Add or remove a visible watermark on selected images (value range must be [0,255]). 25897#@cli : Default values: 'text=(c) G'MIC', 'opacity=0.3', 'size=53', 'angle=25', 'mode=1' and 'smoothness=0'. 25898#@cli : $ image.jpg watermark_visible ,0.7 25899watermark_visible : check "${2=0.3}>0 && $2<1 && ${3=53}>0 && ${6=0.5}>=0" 25900 skip "${1=\251\ G\47MIC}",${4=25},${5=1} 25901 e[^-1] ${arg\ 1+!$5,Add,Remove}" visible watermark '$1' on image$?, with opacity $2, size $3, angle $4 deg." 25902 repeat $! l[$>] 25903 0 t. "$1",0,0,$3,1,255 rotate. $4,0,0 b. $6 n. 0,255 25904 ri. ..,0,2 +. .. c. 0,255 # Generate opaque watermark image 25905 if $5 *. $2 *.. {1-$2} + # Add watermark 25906 else *. $2 - / {1-$2} # Remove watermark 25907 fi 25908 c 0,255 25909 endl done 25910 25911#-------------------------------------- 25912# 25913#@cli :: Blending and Fading 25914# 25915#-------------------------------------- 25916 25917#@cli blend : [layer],blending_mode,_opacity[%],_selection_is={ 0=base-layers | 1=top-layers } : \ 25918# blending_mode,_opacity[%] 25919#@cli : Blend selected G,GA,RGB or RGBA images by specified layer or blend all selected images together, 25920#@cli : using specified blending mode. 25921#@cli : 'blending_mode' can be { add | alpha | and | average | blue | burn | darken | difference | 25922#@cli : divide | dodge | edges | exclusion | freeze | grainextract | grainmerge | green | hardlight | 25923#@cli : hardmix | hue | interpolation | lchlightness | lighten | lightness | linearburn | linearlight | luminance | 25924#@cli : multiply | negation | or | overlay | pinlight | red | reflect | saturation | seamless | seamless_mixed | 25925#@cli : screen | shapeareamax | shapeareamax0 | shapeareamin | shapeareamin0 | shapeaverage | shapeaverage0 | 25926#@cli : shapemedian | shapemedian0 | shapemin | shapemin0 | shapemax | shapemax0 | softburn | softdodge | 25927#@cli : softlight | stamp | subtract | value | vividlight | xor }. 25928#@cli : 'opacity' should be in '[0,1]', or '[0,100]' if expressed with a '%'. 25929#@cli : Default values: 'blending_mode=alpha', 'opacity=1' and 'selection_is=0'. 25930#@cli : $ image.jpg +drop_shadow , resize2dy[-1] 200 rotate[-1] 20 +blend alpha display_rgba[-2] 25931#@cli : $ image.jpg testimage2d {w},{h} blend overlay 25932#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 25933# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 25934# ex add,alpha,and,average,blue,burn,darken 25935#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 25936# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 25937# ex difference,divide,dodge,exclusion,freeze,grainextract,grainmerge 25938#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 25939# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 25940# ex green,hardlight,hardmix,hue,interpolation,lighten,lightness 25941#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 25942# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 25943# ex linearburn,linearlight,luminance,multiply,negation,or,overlay 25944#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 25945# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 25946# ex pinlight,red,reflect,saturation,screen,shapeaverage,softburn 25947#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 25948# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 25949# ex softdodge,softlight,stamp,subtract,value,vividlight,xor 25950blend : skip ${1=alpha},${2=1},${3=1},${4=0} 25951 if ${"is_image_arg $1"} 25952 n={narg($*)} mode=${arg\ 1+($n>=2),alpha,$2} 25953 e[^-1] "Blend image$? with "${arg\ 1+$4,base,top}" layer $1, using '"$mode"' mode and opacity $3." 25954 repeat $! pass$1 l[$>,-1] if $4 rv fi blend $mode,$3 endl done return 25955 fi 25956 e[^-1] "Blend all image$? together, using '$1' mode and opacity $2." 25957 repeat $!-1 l[0,1] 25958 r[1] [0],[0],[0],100%,0,0,0.5,0.5 25959 s={"s0 = s#0<3?1:3; s1 = s<3?1:3; max(s0,s1)"} # Target color format (G or RGB). 25960 to_colormode[0] {$s+1-(s#0%2)} # Target format (G,GA,RGB or RGBA). 25961 to_colormode[1] {$s+1-(s%2)} # Mask format (G,GA,RGB or RGBA). 25962 if {0,"s==2 || s==4"} # Target has alpha. 25963 if "s==2 || s==4" # Mask has alpha. 25964 sh[0,1] 0,{s-2} _blend_$1[2,3] rm[2,3] 25965 if ['"$1"']=='alpha' # Special blending code for alpha-mode. 25966 sh[0,1] 0,{{0,s}-2} sh[0,1] 100% *[2,4] *[3,4] rm[2,3] 25967 +channels[1] 100% sh[1] 100% f[3] 255 rm[3] 25968 j[0] [1],0,0,0,0,{max(0,min(1,$2))},[2],255 rm[1,2] 25969 sh[0] 0,{s-2} sh[0] 100% +[2] 1e-10 /[1,2] rm[1] c 0,255 25970 else 25971 sh[1] 0,{s-2} sh[1] 100% j[0] [2],0,0,0,0,{max(0,min(1,$2))},[3],255 rm[^0] 25972 fi 25973 else # Mask has no alpha. 25974 sh[0] 0,{{0,s}-2} rv[1,2] _blend_$1[1,2] j[1] [2],0,0,0,0,{max(0,min(1,$2))} rm[^0] 25975 fi 25976 else # Target has no alpha. 25977 if "s==2 || s==4" # Mask has alpha. 25978 sh[1] 0,{s-2} _blend_$1[0,2] rm[2] 25979 sh[1] 100% j[0] [1],0,0,0,0,{max(0,min(1,$2))},[2],255 rm[^0] 25980 else # Mask has no alpha. 25981 _blend_$1 j[0] [1],0,0,0,0,{max(0,min(1,$2))} rm[1] 25982 fi 25983 fi 25984 endl done 25985 25986_blend_alpha : 25987_blend_normal : 25988_blend_and : 25989 &[1] [0] 25990_blend_add : 25991 +[1] [0] c[1] 0,255 25992_blend_average : 25993 +[1] [0] /[1] 2 25994_blend_blue : 25995 sh[0] 0,1 j[1] [2] rm[2] 25996_blend_burn : 25997 +-[0] 255 +[1] 0.1 /[2] [1] rm[1] +[1] 1 *[1] 255 c[1] 0,255 25998_blend_darken : 25999 min[1] [0] 26000_blend_difference : 26001 -[1] [0] abs[1] 26002_blend_divide : 26003 +[1] 0.1 ^[1] -1 *[1] [0] *[1] 255 c[1] 0,255 26004_blend_dodge : 26005 -[1] 255.1 ^[1] -1 *[1] [0] *[1] -255 c[1] 0,255 26006_blend_edges : 26007 +blend_edges 0.5 rm[1] 26008_blend_exclusion : 26009 +*[0,1] /[2] -127.5 +[1,2] +[1] [0] 26010_blend_freeze : 26011 *[1] -255 -[1] 0.1 +-[0] 255 sqr[2] /[2] [1] rm[1] +[1] 1 *[1] 255 c[1] 0,255 26012_blend_grainextract : 26013 -[1] [0] *[1] -1 +[1] 128 c[1] 0,255 26014_blend_grainmerge : 26015 +[1] [0] -[1] 128 c[1] 0,255 26016_blend_green : 26017 sh[0] 0 sh[0] 2 j[1] [2] j[1] [3],0,0,0,2 rm[2,3] 26018_blend_hardlight : 26019 +*[0,1] /[2] 127.5 ++[0,1] *[3] 2 -[3] 255 -[3] [2] >[1] 128 26020 j[2] [3],0,0,0,0,1,[1] rm[1,3] c[1] 0,255 26021_blend_hardmix : 26022 +[1] [0] >=[1] 255 *[1] 255 26023_blend_hue : 26024 to_color sh 0,2 rgb2hsv[2,3] sh[2] 1,2 j[1] [4],0,0,0,1 rm[4] hsv2rgb[2,3] rm[2,3] 26025_blend_interpolation : 26026 +*[0] {pi/255} *[1] {pi/255} cos[1,2] +[1,2] -[1] 2 *[1] -63.75 c[1] 0,255 26027_blend_lighten : 26028 max[1] [0] 26029_blend_lightness : 26030 to_color sh 0,2 rgb2lab[2,3] sh[2] 1,2 j[1] [4],0,0,0,1 rm[4] lab2rgb[2,3] rm[2,3] 26031_blend_lchlightness : 26032 _blend_lightness 26033_blend_luminance : 26034 to_color sh 0,2 rgb2ycbcr[2,3] sh[2] 1,2 j[1] [4],0,0,0,1 rm[4] ycbcr2rgb[2,3] rm[2,3] 26035_blend_linearburn : 26036 +[1] [0] -[1] 255 c. 0,255 26037_blend_linearlight : 26038 *[1] 2 +[1] [0] -[1] 255 c[1] 0,255 26039_blend_multiply : 26040 *[1] [0] /[1] 255 26041_blend_negation : 26042 +[1] [0] -[1] 255 abs[1] *[1] -1 +[1] 255 26043_blend_or : 26044 -|[1] [0] 26045_blend_overlay : 26046 +*[0,1] /[2] 127.5 +[1] [0] *[1] 2 -[1] 255 -[1] [2] +<[0] 128 j[1] [2],0,0,0,0,1,[3] rm[2,3] c[1] 0,255 26047_blend_pinlight : 26048 *[1] 2 +blend darken -[1] 256 +blend[0,1] lighten >=[1] 0 26049 j[2] [3],0,0,0,0,1,[1] rm[1,3] 26050_blend_reflect : 26051 -[1] 255.1 *[1] -1 +sqr[0] /[2] [1] rm[1] c[1] 0,255 26052_blend_red : 26053 sh[0] 1,100% j[1] [2],0,0,0,1 rm[2] 26054_blend_seamless : 26055 +blend_seamless 0 rm[1] 26056_blend_seamless_mixed : 26057 +blend_seamless 1 rm[1] 26058_blend_saturation : 26059 to_color sh 0,2 rgb2hsv[2,3] shift[2,3] 0,0,0,-1,2 sh[2] 1,2 j[1] [4],0,0,0,1 rm[4] shift[2,3] 0,0,0,1,2 26060 hsv2rgb[2,3] rm[2,3] 26061_blend_screen : 26062 +-[0] 255 -[1] 255 *[1,2] /[1] 255 *[1] -1 +[1] 255 26063_blend_shapeareamax : 26064 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[1] round[1] 0.01 label[1] 0 26065 +f[0] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[2] round[2] 0.01 area[2] 0,0 26066 {1,iM+1},1,1,{0,s+1} 26067 f[1] ">area = i(#2); best = I[#3,i]; if (area>best[size(best) - 1], I[#3,i] = [ I(#0),area ]);i" 26068 rm[2] channels[2] 0,{s-2} map[1] [2] rm[2] 26069_blend_shapeareamax0 : 26070 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I!=0?I+A:I" norm[1] round[1] 0.01 label_fg[1] 0 26071 +f[0] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[2] round[2] 0.01 area[2] 0,0 26072 {1,iM+1},1,1,{0,s+1} 26073 f[1] ">area = i(#2); best = I[#3,i]; if (area>best[size(best) - 1], I[#3,i] = [ I(#0),area ]);i" 26074 rm[2] channels[2] 0,{s-2} point[2] 0,0,0,1,0 map[1] [2] rm[2] 26075_blend_shapeareamin : 26076 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[1] round[1] 0.01 label[1] 0 26077 +f[0] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[2] round[2] 0.01 area[2] 0,0 26078 {1,iM+1},1,1,{0,s+1},inf 26079 f[1] ">area = i(#2); best = I[#3,i]; if (area<best[size(best) - 1], I[#3,i] = [ I(#0),area ]);i" 26080 rm[2] channels[2] 0,{s-2} map[1] [2] rm[2] 26081_blend_shapeareamin0 : 26082 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I!=0?I+A:I" norm[1] round[1] 0.01 label_fg[1] 0 26083 +f[0] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[2] round[2] 0.01 area[2] 0,0 26084 {1,iM+1},1,1,{0,s+1},inf 26085 f[1] ">area = i(#2); best = I[#3,i]; if (area<best[size(best) - 1], I[#3,i] = [ I(#0),area ]);i" 26086 rm[2] channels[2] 0,{s-2} point[2] 0,0,0,1,0 map[1] [2] rm[2] 26087_blend_shapeaverage : 26088 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[1] round[1] 0.01 label[1] 0 {iM+1},1,1,{0,s} 26089 f[0] ">i(#2,i(#1,x,y,z,0),0,0,c)+=i;i" 26090 +histogram[1] {w},0,{w-1} /[-2,-1] map[1] . rm. 26091_blend_shapeaverage0 : 26092 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I!=0?I+A:I" norm[1] round[1] 0.01 label_fg[1] 0 {iM+1},1,1,{0,s} 26093 f[0] ">i(#2,i(#1,x,y,z,0),0,0,c)+=i;i" 26094 +histogram[1] {w},0,{w-1} /[-2,-1] point. 0,0,0,1,0 map[1] . rm. 26095_blend_shapemedian : 26096 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[1] round[1] 0.01 label[1] 0 26097 N={iM+1} $N,1,1,{s#0} $N,8,1,{s#0} s. x 26098 f[1] "> 26099 begin(siz = vector"$N"()); 26100 k = i; 26101 k3 = k + 3; 26102 hk3 = h(#k3); 26103 copy(i[#k3,siz[k]++],I(#0),s#0,hk3,whd#0); 26104 if (siz[k]>=hk3,resize(#k3,1,round(1.5*hk3+1),1,s#0,0,0)); 26105 end(repeat (size(siz),k, resize(#k+3,1,siz[k],1,s#0,0,0))); 26106 i" 26107 repeat s#0 sh[3--1] $> $N,1,1,1,"ic(#"$N"+3+x)" j[2] .,0,0,0,$> rm[-{$N+1}--1] done 26108 map[1] [2] k[0,1] 26109_blend_shapemedian0 : 26110 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I!=0?I+A:I" norm[1] round[1] 0.01 label_fg[1] 0 26111 N={iM} {$N+1},1,1,{s#0} $N,8,1,{s#0} s. x 26112 f[1] "> 26113 begin(siz = vector"$N"()); 26114 k = i; 26115 if (k, 26116 k1 = k - 1; 26117 k2 = k + 2; 26118 hk2 = h(#k2); 26119 copy(i[#k2,siz[k1]++],I(#0),s#0,hk2,whd#0); 26120 if (siz[k1]>=hk2,resize(#k2,1,round(1.5*hk2+1),1,s#0,0,0)); 26121 ); 26122 end(repeat (size(siz),k, resize(#k+3,1,siz[k],1,s#0,0,0))); 26123 i" 26124 repeat s#0 sh[3--1] $> $N,1,1,1,"ic(#"$N"+3+x)" j[2] .,1,0,0,$> rm[-{$N+1}--1] done 26125 map[1] [2] k[0,1] 26126_blend_shapemin : 26127 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[1] round[1] 0.01 label[1] 0 {iM+1},1,1,{0,s},inf 26128 f[0] ">i(#2,i(#1,x,y,z,0),0,0,c) = min(i(#2,i(#1,x,y,z,0),0,0,c),i);i" 26129 map[1] [2] rm. 26130_blend_shapemin0 : 26131 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I!=0?I+A:I" norm[1] round[1] 0.01 label_fg[1] 0 {iM+1},1,1,{0,s},inf 26132 f[0] ">i(#2,i(#1,x,y,z,0),0,0,c) = min(i(#2,i(#1,x,y,z,0),0,0,c),i);i" 26133 point. 0,0,0,1,0 map[1] [2] rm. 26134_blend_shapemax : 26135 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[1] round[1] 0.01 label[1] 0 {iM+1},1,1,{0,s},-inf 26136 f[0] ">i(#2,i(#1,x,y,z,0),0,0,c) = max(i(#2,i(#1,x,y,z,0),0,0,c),i);i" 26137 map[1] [2] rm. 26138_blend_shapemax0 : 26139 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I!=0?I+A:I" norm[1] round[1] 0.01 label_fg[1] 0 {iM+1},1,1,{0,s},-inf 26140 f[0] ">i(#2,i(#1,x,y,z,0),0,0,c) = max(i(#2,i(#1,x,y,z,0),0,0,c),i);i" 26141 point. 0,0,0,1,0 map[1] [2] rm. 26142_blend_softburn : 26143 +-[0] 255.1 ^[2] -1 *[2] [1] *[2] -127.5 +-[0] 255 ++[1] 0.1 /[3,4] *[3] 127.5 +[3] 255 +[1] [0] >[1] 255 26144 j[2] [3],0,0,0,0,1,[1] rm[1,3] c[1] 0,255 26145_blend_softdodge : 26146 +-[1] 255.1 ^[2] -1 *[2] [0] *[2] -127.5 +-[1] 255 ++[0] 0.1 /[3,4] *[3] 127.5 +[3] 255 +[1] [0] >[1] 255 26147 j[2] [3],0,0,0,0,1,[1] rm[1,3] c[1] 0,255 26148_blend_softlight : 26149 +/[0] 255 /[1] 255 +sqr. *[2] [1] *[1] [3] *[1] -2 *[2] 2 +[1-3] *[1] 255 c[1] 0,255 26150_blend_stamp : 26151 *[1] 2 +[1] [0] -[1] 255 c[1] 0,255 26152_blend_subtract : 26153 -[1] [0] *[1] -1 c[1] 0,255 26154_blend_value : 26155 to_color sh 0,2 rgb2hsv[2,3] sh[2] 0,1 j[1] [4] rm[4] hsv2rgb[2,3] rm[2,3] 26156_blend_vividlight : 26157 *[1] 2 +blend burn -[1] 256 +blend[0,1] dodge >=[1] 0 26158 j[2] [3],0,0,0,0,1,[1] rm[1,3] 26159_blend_xor : 26160 xor[1] [0] 26161 26162#@cli blend_edges : smoothness[%]>=0 26163#@cli : Blend selected images togethers using 'edges' mode. 26164#@cli : $ image.jpg testimage2d {w},{h} +blend_edges 0.8 26165blend_edges : check {$1>=0} 26166 e[^-1] "Blend image$? using 'edges' mode, with smoothness $1." 26167 if $!>1 to_rgb ri[^0] [0],0,0,0.5,0.5 repeat $! l[$>] 26168 +gradient_norm +. 1 b. $1 n. 1,10 sqr. s.. c *[-4--2] . a[-4--1] c 26169 endl done ri[^0] [0],0,0,0.5,0.5 + s. c /[-4--2] . rm. a[-3--1] c fi 26170 26171#@cli blend_fade : [fading_shape] 26172#@cli : Blend selected images together using specified fading shape. 26173#@cli : $ image.jpg testimage2d {w},{h} 100%,100%,1,1,'cos(y/10)' normalize[-1] 0,1 +blend_fade[0,1] [2] 26174blend_fade : 26175 e[^-1] "Blend image$? together using fading pattern $1." 26176 r ${-max_whds},0 26177 pass$1 0 r. [0],[0],[0],100%,1 max. 0 min. {$!-2} 26178 repeat $!-1 +-. $> abs. -. 1 *. -1 max. 0 *[$>,-1] done rm. 26179 + 26180 26181_fade : 26182 ri.. ...,5 ri. ..,3 c. $1%,$2% n. 0,1 j... ..,0,0,0,0,1,. rm[-2,-1] 26183 26184#@cli blend_median 26185#@cli : Blend selected images together using 'median' mode. 26186#@cli : $ image.jpg testimage2d {w},{h} +mirror[0] y +blend_median 26187blend_median : 26188 e[^-1] "Blend image$? using 'median' mode." 26189 if $!<2 return fi 26190 to_colormode 0 r ${-max_whd},100%,0,0,0.5,0.5,0.5 26191 if $!==2 + / 2 26192 else 26193 whds={w},{h},{d},{s} r 100%,100%,{d*s},1,-1 a c 26194 100%,100%,100%,1,"med(I(#0))" k. r $whds,-1 26195 fi 26196 26197#@cli blend_seamless : _is_mixed_mode={ 0 | 1 },_inner_fading[%]>=0,_outer_fading[%]>=0 26198#@cli : Blend selected images using a seamless blending mode (Poisson-based). 26199#@cli : Default values: 'is_mixed=0', 'inner_fading=0' and 'outer_fading=100%'. 26200blend_seamless : check "${2=0}>=0 && ${3=100%}>=0" skip ${1=0} 26201 s0="non-mixed" s1="mixed" 26202 e[^-1] "Blend image$? using seamless mode (Poisson-based), in "${s{$1!=0}}" mode with inner fading $2 and 26203 outer fading $3." 26204 to_a[^0] r {0,w+32},{0,h+32},1,100%,0,0,0.5,0.5 # Avoid periodic boundaries problems. 26205 26206 if ['$3']!='100%' # With outer fading. 26207 repeat $!-1 l[0,1] 26208 +blend_seamless $1,$2,100% channels.. 100% !=.. 0 distance.. 1 26209 iM={-2,iM} ic={if(${is_percent\ $3},2*$3*$iM,1+$3)} 26210 if $ic<=$iM c.. 0,{max(1,$ic)} n.. 0,1 26211 else n.. 0,{max(0,2-$ic/$iM)} 26212 fi 26213 *.. -1 +.. 1 26214 j[0] [2],0,0,0,0,1,[1] rm[1,2] 26215 endl done 26216 else # Without outer fading. 26217 26218 repeat $!-1 l[0,1] 26219 26220 # Get background average color. 26221 +r[0] 1,1,1,100%,2 avg={^} rm. 26222 26223 # Compute mixed gradients of background and top layer. 26224 split_opacity. !=. 0 *.. . erode. 3 26225 g[0,1] xy,1 26226 *[-3,-2] . 26227 26228 # Modify mask if 'mixed' mode selected. 26229 if $1 26230 +a[0,1] c +a[2,3] c norm[-2,-1] 26231 <[-2,-1] *[-2,-1] 26232 fi 26233 26234 # Compute the desired gradient map. 26235 if $2 26236 distance. 0 26237 iM={iM} ic={if(${is_percent\ $2},2*$2*$iM,1+$2)} 26238 if $ic<=$iM c. 0,{max(1,$ic)} n. 0,1 26239 else n. 0,{max(0,2-$ic/$iM)} 26240 fi 26241 fi 26242 26243 j[-5] ...,0,0,0,0,1,. 26244 j[-4] ..,0,0,0,0,1,. 26245 rm[-3--1] 26246 26247 # Compute divergence (right-hand term of Poisson eq.) 26248 g[0] x,-1 g[1] y,-1 + 26249 26250 # Inverse Laplacian and renormalize 26251 ilaplacian 0 26252 +fc. $avg 26253 +[-2,-1] 26254 c 0,255 26255 26256 endl done 26257 fi 26258 z 16,16,{w-17},{h-17} 26259 26260#@cli fade_diamond : 0<=_start<=100,0<=_end<=100 26261#@cli : Create diamond fading from selected images. 26262#@cli : Default values: 'start=80' and 'end=90'. 26263#@cli : $ image.jpg testimage2d {w},{h} +fade_diamond 80,85 26264fade_diamond : skip ${1=70},${2=90} 26265 e[^-1] "Create ($1%,$2%) diamond-shaped fading from image$?." 26266 repeat int($!/2) l[$>,{$>+1}] 26267 (0,1,0;1,1,1;0,1,0) _fade $1,$2 26268 endl done 26269 26270#@cli fade_linear : _angle,0<=_start<=100,0<=_end<=100 26271#@cli : Create linear fading from selected images. 26272#@cli : Default values: 'angle=45', 'start=30' and 'end=70'. 26273#@cli : $ image.jpg testimage2d {w},{h} +fade_linear 45,48,52 26274fade_linear : skip ${1=45},${2=30},${3=70} 26275 e[^-1] "Create ($2%,$3%) linear fading from image$?, with angle $1 deg." 26276 repeat int($!/2) l[$>,{$>+1}] 26277 64,64,1,1,"x*cos($1*pi/180) + y*sin($1*pi/180)" _fade $2,$3 26278 endl done 26279 26280#@cli fade_radial : 0<=_start<=100,0<=_end<=100 26281#@cli : Create radial fading from selected images. 26282#@cli : Default values: 'start=30' and 'end=70'. 26283#@cli : $ image.jpg testimage2d {w},{h} +fade_radial 30,70 26284fade_radial : skip ${1=30},${2=70} 26285 e[^-1] "Create ($1%,$2%) radial fading from image$?." 26286 repeat int($!/2) l[$>,{$>+1}] 26287 100%,100% =. 1,50%,50% distance. 1 _fade $1,$2 26288 endl done 26289 26290#@cli fade_x : 0<=_start<=100,0<=_end<=100 26291#@cli : Create horizontal fading from selected images. 26292#@cli : Default values: 'start=30' and 'end=70'. 26293#@cli : $ image.jpg testimage2d {w},{h} +fade_x 30,70 26294fade_x : skip ${1=30},${2=70} 26295 e[^-1] "Create ($1%,$2%) horizontal fading from image$?." 26296 repeat int($!/2) l[$>,{$>+1}] (0,1) _fade $1,$2 endl done 26297 26298#@cli fade_y : 0<=_start<=100,0<=_end<=100 26299#@cli : Create vertical fading from selected images. 26300#@cli : Default values: 'start=30' and 'end=70'. 26301#@cli : $ image.jpg testimage2d {w},{h} +fade_y 30,70 26302fade_y : skip ${1=30},${2=70} 26303 e[^-1] "Create ($1%,$2%) vertical fading from image$?." 26304 repeat int($!/2) l[$>,{$>+1}] (0;1) _fade $1,$2 endl done 26305 26306#@cli fade_z : 0<=_start<=100,0<=_end<=100 26307#@cli : Create transversal fading from selected images. 26308#@cli : Default values: 'start=30' and 'end=70'. 26309fade_z : skip ${1=30},${2=70} 26310 e[^-1] "Create ($1%,$2%) transversal fading from image$?." 26311 repeat int($!/2) l[$>,{$>+1}] (0/1) _fade $1,$2 endl done 26312 26313#@cli sub_alpha : [base_image],_opacity_gain>=1 26314#@cli : Compute the minimal alpha-channel difference (opposite of alpha blending) between the selected images 26315#@cli : and the specified base image. 26316#@cli : The alpha difference A-B is defined as the image having minimal opacity, such that alpha_blend(B,A-B) = A. 26317#@cli : Default value: 'opacity_gain=1'. 26318#@cli : $ image.jpg testimage2d {w},{h} +sub_alpha[0] [1] display_rgba 26319sub_alpha : check "${2=1}>=1 && "${"is_image_arg $1"} 26320 e[^-1] "Compute minimal alpha-channel difference between image$? and base image $1, with opacity gain $2." 26321 remove_opacity repeat $! pass$1 0 l[$>,-1] 26322 to_colormode 0 r ${-max_whd},100%,0,0,0.5,0.5 # Normalize image dimensions. 26323 26324 # Estimate minimal alpha-channel. 26325 +>[0,1] *[2] 255 26326 -[0,2] [1] replace[2] 0,1 26327 i[2] [0] /[2,3] 26328 compose_channels[2] max 26329 *[2] $2 c[2] 0,1 26330 26331 # Synthetize alpha-difference image. 26332 +replace[2] 0,1 /[0,3] +[0,1] *[1] 255 a c 26333 26334 endl done 26335 26336#--------------------------------------------- 26337# 26338#@cli :: Image Sequences and Videos 26339# 26340#--------------------------------------------- 26341 26342#@cli animate : filter_name,"param1_start,...,paramN_start","param1_end,...,paramN_end",nb_frames>=0,\ 26343# _output_frames={ 0 | 1 },_output_filename : delay>0,_back and forth={ 0 | 1 } 26344#@cli : Animate filter from starting parameters to ending parameters or animate selected images 26345#@cli : in a display window. 26346#@cli : Default value: 'delay=30'. 26347#@cli : $ image.jpg animate flower,"0,3","20,8",9 26348animate : skip ${1=30},${2=0},${3=""},${4=10},${5=1},"${6=}" 26349 if "isnum($1)" 26350 e[0--3] "Animate image$?, with a delay of $1 ms"${"if $2 u \", in back-and-forth mode\" else u \"\" fi"}. 26351 if !$! return fi 26352 speed,pause,direction,scale,frame=$1,-1,1,1,0 26353 is_same_size={"res = 1; s = [ w#0,h#0 ]; for (k = 1, k<l && res, ++k, res = (s==[ w#k,h#k ]))"} 26354 26355 w[0] ${fitscreen[]\ {0,[w,h]}},1,0,{0,b}.{0,x} 26356 do 26357 title={$frame,b}{`narg({$frame,x})?_'.':0`}{$frame,x} 26358 if $is_same_size 26359 w[$frame] -1,-1,1,0,$title 26360 else 26361 w[$frame] {$scale*[${fitscreen[]\ {$frame,[w,h]}}]},1,0,$title 26362 fi 26363 frame+=$direction 26364 if $2 26365 if $frame==-1 frame=0 direction=1 26366 elif $frame==$! frame={$!-1} direction=-1 26367 fi 26368 else frame%=$! 26369 fi 26370 wait $speed 26371 26372 # Increase window size. 26373 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} scale*=1.5 wait -1 fi 26374 26375 # Decrease window size. 26376 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} scale/=1.5 wait -1 fi 26377 26378 # Reset window size. 26379 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} scale=1 wait -1 fi 26380 if {*,o} speed={min(500,max(10,$speed-10*{*,o}))} wait -1 fi 26381 if {*,SPACE} 26382 if $pause>=0 direction=$pause pause=-1 26383 else pause=$direction direction=0 fi 26384 wait -1 26385 fi 26386 26387 while {*}" && "!{*,Q}" && "!{*,ESC} w 0 26388 else 26389 e[0--3] "Compute animated version of filter '$1', from parameters $2 to $3 with $4 frames." 26390 if !($5||narg("$6")) return fi 26391 ($2) ($3) y[-2,-1] x a[-2,-1] y r. 100%,$4,1,1,3 mv. 0 rprogress 0 26392 repeat $!-1,u 26393 e[] " > Animate image ["$>"]" 26394 repeat $4 +l[0,1] 26395 -$1. {0,@{$>*{0,w}}-{($>+1)*{0,w}-1}} rm[0] 26396 if narg("$6") o ${filename\ "$6",$u,$>} fi 26397 if !$5 rm fi 26398 rprogress {100*($>+1)/$4} 26399 e[] "\r > Animate image ["$u"] : Frame "{$>+1}"/$4 " 26400 endl done 26401 rm[1] done rm[0] 26402 fi 26403 26404#@cli apply_camera : _"command",_camera_index>=0,_skip_frames>=0,_output_filename 26405#@cli : Apply specified command on live camera stream, and display it on display window [0]. 26406#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 26407#@cli : Default values: 'command=""', 'camera_index=0' (default camera), 'skip_frames=0' and 'output_filename=""'. 26408apply_camera : check_opencv $0 skip "${1=},${4=}" check "${2=0}>=0 && ${3=0}>=0" 26409 e[^-1] "Apply command '$1' on camera stream ""#$2, with $3 frames skip and output filename '$4'." 26410 is_ext "$4",avi is_outavi=${} 26411 is_ext "$4",mp4 is_outmp4=${} 26412 l[] i=0 do 26413 camera $2,1,$3 $1 w. -1,-1,"[G'MIC] Camera ""#$2 ("{w}x{h}")" 26414 if narg("$4") if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o. "$4",25,mp4v,1 else o. ${filename\ "$4",$i} i+=1 fi fi 26415 if {*,S} o. gmic_camera.png fi 26416 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 26417 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 26418 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 26419 rm. 26420 while {*}" && "!{*,ESC}" && "!{*,Q} camera $2,0 endl 26421 26422#@cli apply_files : "filename_pattern",_"command",_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,\ 26423# _output_filename 26424#@cli : Apply a G'MIC command on specified input image files, in a streamed way. 26425#@cli : If a display window is opened, rendered frames are displayed in it during processing. 26426#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image file 26427#@cli : extension (saved as a sequence of images). 26428#@cli : Default values: 'command=(undefined)', 'first_frame=0', 'last_frame=-1', 'frame_step=1' \ 26429# and 'output_filename=(undefined)'. 26430apply_files : check "isint(${3=0}) && $3>=0 && isint(${4=-1}) && ($4>=0 || $4==-1) && ${5=1}>=1" skip "${2=},${6=}" 26431 e[^-1] "Apply command '$2' on input image files '$1', with first frame $3, last frame $4, frame step $5 and 26432 output filename '$6'.\n" 26433 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} v + _apply_stream[] "${_file{$frame+1}}","$2",${3-5},"$6" 26434 26435#@cli apply_video : video_filename,_"command",_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,\ 26436# _output_filename 26437#@cli : Apply a G'MIC command on all frames of the specified input video file, in a streamed way. 26438#@cli : If a display window is opened, rendered frames are displayed in it during processing. 26439#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 26440#@cli : file extension (saved as a sequence of images). 26441#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 26442#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1' and 'output_filename=(undefined)'. 26443apply_video : check_opencv $0 check "isint(${3=0}) && $3>=0 && isint(${4=-1}) && ($4>=0 || $4==-1) && ${5=1}>=1" 26444 skip "${2=},${6=}" 26445 e[^-1] "Apply command '$2' on input video file '$1', with first frame $3, last frame $4, frame step $5 and 26446 output filename '$6'.\n" 26447 _N= v + _apply_stream[] "\"$1\",$frame","$2",${3-5},"$6" 26448 26449_apply_stream : skip "${2=},${6=}" 26450 is_ext "$6",avi is_outavi=${} 26451 is_ext "$6",mp4 is_outmp4=${} 26452 frame=$3 i=0 go_on=1 26453 do 26454 l[] $1 onfail go_on=0 endl 26455 if $go_on 26456 e[] "\r > Frame ""#"$frame$_N" " 26457 frame+=$5 26458 l $2 onfail error[0--5] "Command 'apply_stream': Specified command errored: "${} endl 26459 if !$! continue fi 26460 if narg("$6") 26461 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o. "$6",25,mp4v,1 else o. ${filename\ "$6",$i} i+=1 fi 26462 fi 26463 if {*} 26464 title="[G'MIC] Frame ""#"$frame 26465 if !narg($wh) wh=${fitscreen[]\ {[w,h]}} w. $wh,0,$title 26466 else w. -1,-1,0,$title 26467 fi 26468 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 26469 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 26470 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 26471 fi 26472 rm. 26473 fi 26474 while $go_on" && "($4==-1" || "$frame<=$4) 26475 if $is_outavi||$is_outmp4 o[] "$6",25,mp4v,0 fi 26476 26477#@cli average_files : "filename_pattern",_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,_output_filename 26478#@cli : Average specified input image files, in a streamed way. 26479#@cli : If a display window is opened, rendered frames are displayed in it during processing. 26480#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 26481#@cli : file extension (saved as a sequence of images). 26482#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1' and 'output_filename=(undefined)'. 26483average_files : check "isint(${2=0}) && $2>=0 && isint(${3=-1}) && ($3>=0 || $3==-1) && ${4=1}>=1" skip "${5=}" 26484 e[^-1] "Average input image files '$1', with first frame $2, last frame $3, frame step $4 and 26485 output filename '$5'.\n" 26486 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} v + _average_stream[] "${_file{$frame+1}}",${2-4},"$5" 26487 26488#@cli average_video : video_filename,_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,_output_filename 26489#@cli : Average frames of specified input video file, in a streamed way. 26490#@cli : If a display window is opened, rendered frames are displayed in it during processing. 26491#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 26492#@cli : file extension (saved as a sequence of images). 26493#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 26494#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1' and 'output_filename=(undefined)'. 26495average_video : check_opencv $0 check "isint(${2=0}) && $2>=0 && isint(${3=-1}) && ($3>=0 || $3==-1) && ${4=1}>=1" 26496 skip "${5=}" 26497 e[^-1] "Average frames of input video file '$1', with first frame $2, last frame $3, frame step $4 and 26498 output filename '$5'.\n" 26499 _N= v + _average_stream[] "\"$1\",$frame",${2-4},"$5" 26500 26501_average_stream : skip "${5=}" 26502 is_ext "$5",avi is_outavi=${} 26503 is_ext "$5",mp4 is_outmp4=${} 26504 frame=$2 i=0 go_on=1 N=0 26505 imM=inf,-inf 26506 do 26507 l[] $1 onfail go_on=0 endl 26508 if $go_on 26509 e[] "\r > Frame ""#"$frame$_N" " 26510 imM={v=[$imM];[min(im,v[0]),max(iM,v[1])]} 26511 N+=1 26512 if $!>1 r ${-max_whds} + fi 26513 if narg("$5") 26514 +/. $N c. $imM 26515 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o. "$5",25,mp4v,1 else o. ${filename\ "$5",$i} i+=1 fi 26516 rm. 26517 fi 26518 if {*} 26519 title="[G'MIC] Frame ""#"$frame 26520 +n 0,255 26521 if !narg($wh) wh=${fitscreen[]\ {[w,h]}} w. $wh,0,$title 26522 else w. -1,-1,0,$title 26523 fi 26524 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 26525 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 26526 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 26527 rm. 26528 fi 26529 frame+=$4 26530 fi 26531 while $go_on" && "($3==-1" || "$frame<=$3) 26532 / $N c $imM 26533 if $is_outavi||$is_outmp4 o[] "$5",25,mp4v,0 fi 26534 26535#@cli fade_files : "filename_pattern",_nb_inner_frames>0,_first_frame>=0,_last_frame={ >=0 | -1=last },\ 26536# _frame_step>=1,_output_filename 26537#@cli : Generate a temporal fading from specified input image files, in a streamed way. 26538#@cli : If a display window is opened, rendered frames are displayed in it during processing. 26539#@cli : The output filename may have extension 'avi' or 'mp4' (saved as a video), or any other usual image 26540#@cli : file extension (saved as a sequence of images). 26541#@cli : Default values: 'nb_inner_frames=10', 'first_frame=0', 'last_frame=-1', 'frame_step=1' \ 26542# and 'output_filename=(undefined)'. 26543fade_files : check "isint(${2=10}) && $2>0 && isint(${3=0}) && $3>=0 && 26544 isint(${4=-1}) && ($4>=0 || $4==-1) && ${5=1}>=1" skip "${6=}" 26545 e[^-1] "Fade input image files '$1', with $2 inner frames, first frame $3, last frame $4, frame step $5 and 26546 output filename '$6'.\n" 26547 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} v + _fade_stream[] "${_file{$frame+1}}",${2-5},"$6" 26548 26549#@cli fade_video : video_filename,_nb_inner_frames>0,_first_frame>=0,_last_frame={ >=0 | -1=last },\ 26550# _frame_step>=1,_output_filename 26551#@cli : Create a temporal fading sequence from specified input video file, in a streamed way. 26552#@cli : If a display window is opened, rendered frames are displayed in it during processing. 26553#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 26554#@cli : Default values: 'nb_inner_frames=10', 'first_frame=0', 'last_frame=-1', 'frame_step=1' \ 26555# and 'output_filename=(undefined)'. 26556fade_video : check_opencv $0 check "isint(${2=10}) && $2>0 && isint(${3=0}) && $3>=0 && 26557 isint(${4=-1}) && ($4>=0 || $4==-1) && ${5=1}>=1" skip "${6=}" 26558 e[^-1] "Fade frames of input video file '$1', with $2 inner frames, first frame $3, last frame $4, frame step $5 and 26559 output filename '$6'.\n" 26560 _N= v + _fade_stream[] "\"$1\",$frame",${2-5},"$6" 26561 26562_fade_stream : skip "${6=}" 26563 is_ext "$6",avi is_outavi=${} 26564 is_ext "$6",mp4 is_outmp4=${} 26565 frame=$3 i=0 go_on=1 26566 26567 l $1 onfail go_on=0 endl # Load first image. 26568 if !$go_on return fi 26569 w={w} h={h} s={s} 26570 if {*} w. ${fitscreen\ $w,$h},0,"[G'MIC]" fi 26571 pframe=$frame frame+=$5 26572 do 26573 l[] $1 onfail go_on=0 endl 26574 if !$go_on break fi 26575 to_colormode. $s r. $w,$h 26576 repeat $2+2 if $< 26577 title="[G'MIC] Frame ""#"$pframe" -> ""#"$frame$_N" ("{1+$>}/$2")" 26578 e[] "\r - "$title 26579 +j[0] [1],0,0,0,0,{$>/($2+1)} 26580 if narg("$6") 26581 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o. "$6",25,mp4v,1 else filename "$6",$i i+=1 o. ${} fi 26582 fi 26583 if {*} 26584 w. -1,-1,0,$title 26585 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 26586 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 26587 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 26588 fi 26589 rm. 26590 fi done 26591 rm[0] pframe=$frame frame+=$5 26592 while $go_on" && "($4==-1" || "$frame<=$4) 26593 26594 # Output last frame. 26595 if narg("$6") 26596 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o[] "$6",25,mp4v,0 else filename "$6",$i o. ${} fi 26597 fi 26598 rm 26599 26600#@cli files2video : "filename_pattern",_output_filename,_fps>0,_codec 26601#@cli : Convert several files into a single video file. 26602#@cli : Default values: 'output_filename=output.mp4', 'fps=25' and 'codec=mp4v'. 26603files2video : check "isint(${3=25}) && $3>0" skip "${2=output.mp4}",${4=mp4v} 26604 files=${"files \"$1\""} arg2var _file,$files nb_files=${} 26605 ('$files') if w>128 z. 0,127 s_files={t}... else s_files=$files fi rm. 26606 e[^-1] "Convert image files '"$s_files"' into frames of output video '$2', with $3 fps and $4 codec.\n" 26607 repeat $nb_files l[] 26608 file=${_file{$>+1}} 26609 _file=${basename\ $file} 26610 e[] "\r - Image "{1+$>}/$nb_files" ["$_file"] -> [$2] " 26611 i $file o "$2",$3,$4,1 26612 rm 26613 onfail e[] "\n - Error occurred on input file '"$file"'.\n" 26614 endl done 26615 o $"$2",0,0,0 26616 26617#@cli median_files : "filename_pattern",_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,\ 26618# _frame_rows[%]>=1,_is_fast_approximation={ 0 | 1 } 26619#@cli : Compute the median frame of specified input image files, in a streamed way. 26620#@cli : If a display window is opened, rendered frame is displayed in it during processing. 26621#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1', 'frame_rows=20%' \ 26622# and 'is_fast_approximation=0'. 26623median_files : check "isint(${2=0}) && $2>=0 && isint(${3=-1}) && ($3>=0 || $3==-1) && 26624 ${4=1}>=1 && ${5=20%}>0 && isnum(${6=0})" 26625 s0="fast" s1="precise" 26626 e[^-1] "Compute median of input image files '$1', with first frame $2, last frame $3, frame step $4, 26627 frame rows $5, using "${s{!$6}}" algorithm." 26628 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} 26629 l[] 26630 ${_file{$frame+1}} nm. res f. 0 26631 v + _median_stream "${_file{$frame+1}}",${2-6} v - 26632 endl 26633 26634#@cli median_video : video_filename,_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,\ 26635# _frame_rows[%]>=1,_is_fast_approximation={ 0 | 1 } 26636#@cli : Compute the median of all frames of an input video file, in a streamed way. 26637#@cli : If a display window is opened, rendered frame is displayed in it during processing. 26638#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 26639#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1', 'frame_rows=100%' \ 26640# and 'is_fast_approximation=1'. 26641median_video : check_opencv $0 check "isint(${2=0}) && $2>=0 && isint(${3=-1}) && ($3>=0 || $3==-1) && 26642 ${4=1}>=1 && ${5=100%}>0 && isnum(${6=1})" 26643 s0="fast" s1="precise" 26644 e[^-1] "Compute median frame of input video file '$1', with first frame $2, last frame $3, frame step $4, 26645 frame rows $5, using "${s{!$6}}" algorithm." 26646 _N= 26647 l[] 26648 "$1",0 nm. res f. 0 26649 v + _median_stream "\"$1\",$frame",${2-6} v - 26650 endl 26651 26652_median_stream : 26653 26654 # Retrieve min/max values of all frames when fast method is used. 26655 if $6 26656 e[] "- Retrieve min/max values of all frames.\n" 26657 frame=$2 go_on=1 26658 imM=inf,-inf 26659 do 26660 l[] $1 onfail go_on=0 endl 26661 if $go_on 26662 e[] "\r > Frame ""#"$frame$_N" " 26663 imM={v=[$imM];[min(im,v[0]),max(iM,v[1])]} 26664 if {*} 26665 title="[G'MIC] Frame ""#"$frame 26666 if !narg($wh) wh=${fitscreen[]\ {[w,h]}} w. $wh,1,$title 26667 else w. -1,-1,1,$title 26668 fi 26669 fi 26670 rm. 26671 frame+=$4 26672 fi 26673 while $go_on" && "($3==-1" || "$frame<=$3) 26674 _N=/{$frame-$4} 26675 fact={v=[$imM];dv=v[1]-v[0];dv<=0?0:255/dv} 26676 fi 26677 26678 # Start median computation. 26679 h1={h-1} drows={round(${is_percent\ $5}?$5*h:$5)} 26680 nb_iter={round(h/$drows,1,1)} 26681 repeat $nb_iter 26682 row0={$drows*$>} row1={0,min(h,$row0+$drows-1)} 26683 e[] "- Iteration \#"{$>+1}/$nb_iter": Load rows "$row0-$row1/$h1".\n" 26684 frame=$2 go_on=1 26685 26686 if $6 26687 # Fast method : compute median frame using streamed histogram computation. 26688 N=0 26689 {w},$drows,256,{s} nm. hist 26690 do 26691 l[] $1 nm. img onfail go_on=0 endl 26692 if $img 26693 e[] "\r > Frame ""#"$frame$_N" " 26694 if {*}" && "!$> 26695 title="[G'MIC] Frame ""#"$frame 26696 if !narg($wh) wh=${fitscreen[]\ {img,[w,h]}} w[img] $wh,1,$title 26697 else w[img] -1,-1,1,$title 26698 fi 26699 fi 26700 rows[img] $row0,$row1 f[img] ":++i(#-2,x,y,round(i*"$fact"),c)" 26701 rm[img] 26702 frame+=$4 N+=1 26703 fi 26704 while $go_on" && "($3==-1" || "$frame<=$3) 26705 cumulate[hist] z 26706 N2={int($N/2)} 26707 [hist],[hist],1,[hist] 26708 if $N%2 # Odd number of frames. 26709 f. ":go_on = 1; for (z = 0, i(#"$hist",x,y,z,c)<"$N2" && z<256, ++z); z" 26710 else # Even number of frames. 26711 f. ":begin(N2p = "$N2"; N2n = N2p + 1); 26712 go_on = 1; 26713 for (zp = 0, i(#"$hist",x,y,zp,c)<N2p && zp<256, ++zp); 26714 for (zn = zp, i(#"$hist",x,y,zn,c)<N2n && zn<256, ++zn); 26715 0.5*(zn + zp);" 26716 fi 26717 rm.. 26718 /. $fact c. $imM 26719 26720 else 26721 # Slow method : compute median frame using temporal quicksort. 26722 l[] 26723 do 26724 l[] $1 nm. img onfail go_on=0 endl 26725 if $go_on 26726 e[] "\r > Frame ""#"$frame$_N" " 26727 if {*}" && "!$> 26728 title="[G'MIC] Frame ""#"$frame 26729 if !narg($wh) wh=${fitscreen[]\ {[w,h]}} w. $wh,1,$title 26730 else w. -1,-1,1,$title 26731 fi 26732 fi 26733 rows. $row0,$row1 26734 frame+=$4 26735 fi 26736 while $go_on" && "($3==-1" || "$frame<=$3) 26737 e[] "\r > Compute median blending of "$!" frames." 26738 __median_stream 26739 endl 26740 fi 26741 26742 _N=/{$frame-$4} 26743 j[res] .,0,$row0 26744 if {*} w[res] -1,-1,1,"[G'MIC] Iteration ""#"$> fi 26745 rm. 26746 26747 done 26748 e[] "- Done!" 26749 26750# Median blending optimized to deal with a lot of input frames. 26751__median_stream : 26752 if $!<2 return 26753 elif $!==2 + / 2 26754 else 26755 f. ": 26756 stack = vector"{0,2*$!}"(); 26757 stacksize = 0; 26758 push(elt0,elt1) = (stack[stacksize++] = elt0; stack[stacksize++] = elt1); 26759 pop() = (_s1 = stack[--stacksize]; _s0 = stack[--stacksize]; [_s0,_s1]); 26760 push(0,"$!" - 1); 26761 while (stacksize>0, 26762 range = pop(); 26763 lo = range[0]; 26764 hi = range[1]; 26765 pivot = i(#int((lo + hi)/2)); 26766 while (lo<=hi, 26767 while (i(#lo)<pivot, ++lo); 26768 while (pivot<i(#hi), --hi); 26769 if (lo<=hi, _tmp = i(#lo); i(#lo++) = i(#hi); i(#hi--) = _tmp); 26770 ); 26771 if (range[0]<hi,push(range[0],hi)); 26772 if (lo<range[1],push(lo,range[1])); 26773 )" 26774 if $!%2 k[{int($!/2)}] 26775 else k[{int($!/2-1)},{$!/2}] + / 2 26776 fi 26777 fi 26778 26779#@cli morph : nb_inner_frames>=1,_smoothness>=0,_precision>=0 26780#@cli : Create morphing sequence between selected images. 26781#@cli : Default values: 'smoothness=0.1' and 'precision=4'. 26782#@cli : $ image.jpg +rotate 20,1,1,50%,50% morph 9 26783morph : check "$1>=0.5 && ${2=0.1}>=0 && ${3=4}>=0" 26784 nbf={round($1)} 26785 e[^-1] "Create morphing sequence between image$?, with "$nbf" inner frames, smoothness $2 and precision $3.\n" 26786 nchan=${-max_s} if $nchan<=4 to_colormode $nchan else channels 0,{$nchan-1} fi 26787 ri[^0] [0],3 26788 repeat $!-1 nm={$>,n} l[$<,{$<+1}] 26789 e[] "\r > Morph image "$>" to image "{$>+1}". " 26790 +equalize[0,1] n[-2,-1] 0,255 26791 +displacement[3] [2],$2,$3 +displacement[2] [3],$2,$3 rm[-4,-3] 26792 repeat $nbf+2 if $>&&$< 26793 t={$>/($nbf+1)} omt={1-$t} 26794 +*[2] $t +warp[0] .,1,1,1 rm.. *. $omt 26795 +*[3] {1-$t} +warp[1] .,1,1,1 rm.. *. $t 26796 +[-2,-1] 26797 fi done 26798 rm[2,3] mv[2--1] 1 nm $nm 26799 endl done 26800 26801#@cli morph_files : "filename_pattern",_nb_inner_frames>0,_smoothness>=0,_precision>=0,\ 26802# _first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,_output_filename 26803#@cli : Generate a temporal morphing from specified input image files, in a streamed way. 26804#@cli : If a display window is opened, rendered frames are displayed in it during processing. 26805#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 26806#@cli : file extension (saved as a sequence of images). 26807#@cli : Default values: 'nb_inner_frames=10', 'smoothness=0.1', 'precision=4', 'first_frame=0', 'last_frame=-1', \ 26808# 'frame_step=1' and 'output_filename=(undefined)'. 26809morph_files : check "isint(${2=10}) && $2>0 && ${3=0.1}>=0 && ${4=4}>=0 && 26810 isint(${5=0}) && $5>=0 && isint(${6=-1}) && ($6>=0 || $6==-1) && ${7=1}>=1" skip "${8=}" 26811 e[^-1] "Morph input image files '$1', with $2 inner frames, smoothness $3, precision $4, first frame $5, 26812 last frame $6, frame step $7 and output filename '$8'.\n" 26813 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} _morph_stream[] "${_file{$frame+1}}",${2-7},"$8" 26814 26815#@cli morph_rbf : nb_inner_frames>=1,xs0[%],ys0[%],xt0[%],yt0[%],...,xsN[%],ysN[%],xtN[%],ytN[%] 26816#@cli : Create morphing sequence between selected images, using RBF-based interpolation. 26817#@cli : Each argument (xsk,ysk)-(xtk,ytk) corresponds to the coordinates of a keypoint 26818#@cli : respectively on the source and target images. The set of all keypoints define the overall image deformation. 26819morph_rbf : check "$1>=0.5" 26820 nbf={round($1)} 26821 e[^-1] "Create morphing sequence between image$? using RBF interpolation, "\ 26822 "with "$nbf" inner frames and keypoints ($*)." 26823 $=arg N={($#-1)/4} 26824 if int($N)!=$N error[0--2] "Command 'morph_rbf': Wrong number of arguments ($#)." fi 26825 ri[^0] [0],3 26826 repeat $!-1 nm={$>,n} l[$<,{$<+1}] 26827 e[] "\r > Morph image "$>" to image "{$>+1}". " 26828 26829 # Retrieve absolute keypoints coordinates. 26830 4,$N 26831 repeat wh a=${arg{2+$>}} isp=${"is_percent "$a} eval i[$>]=$isp?($>%2?w#0:h#0)*$a:$a done 26832 permute. yzcx 26833 26834 # Generate forward and backward warping fields. 26835 +f. "[i0,i1,i2-i0,i3-i1]" 26836 f.. "[i2,i3,i0-i2,i1-i3]" 26837 rbf[-2,-1] {0,[w,h]} 26838 26839 # Compute morphing sequence. 26840 repeat $nbf+2 if $>&&$< 26841 [0],[0],1,[0]," 26842 const interpolation = 1; 26843 const boundary = 3; 26844 const t = "$>"/("$nbf"+1); 26845 const omt = 1 - t; 26846 begin(print([t,omt])); 26847 ub = i(#2,x,y,0,0); 26848 vb = i(#2,x,y,0,1); 26849 uf = i(#3,x,y,0,0); 26850 vf = i(#3,x,y,0,1); 26851 omt*I(#0,x - t*uf,y - t*vf) + t*I(#1,x - omt*ub,y - omt*vb)" 26852 fi done 26853 rm[2,3] mv[2--1] 1 nm $nm 26854 endl done 26855 26856#@cli morph_video : video_filename,_nb_inner_frames>0,_smoothness>=0,_precision>=0,\ 26857# _first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,_output_filename 26858#@cli : Generate a temporal morphing from specified input video file, in a streamed way. 26859#@cli : If a display window is opened, rendered frames are displayed in it during processing. 26860#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 26861#@cli : file extension (saved as a sequence of images). 26862#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 26863#@cli : Default values: 'nb_inner_frames=10', 'smoothness=0.1', 'precision=4', 'first_frame=0', 'last_frame=-1', \ 26864# 'frame_step=1' and 'output_filename=(undefined)'. 26865morph_video : check_opencv $0 check "isint(${2=10}) && $2>0 && ${3=0.1}>=0 && ${4=4}>=0 && 26866 isint(${5=0}) && $5>=0 && isint(${6=-1}) && ($6>=0 || $6==-1) && ${7=1}>=1" skip "${8=}" 26867 e[^-1] "Morph frames of input video file '$1', with $2 fading frames, smoothness $3, precision $4, first frame $5, 26868 last frame $6, frame step $7 and output filename '$8'.\n" 26869 _N= v + _morph_stream[] "\"$1\",$frame",${2-7},"$8" 26870 26871_morph_stream : skip "${8=}" 26872 is_ext "$8",avi is_outavi=${} 26873 is_ext "$8",mp4 is_outmp4=${} 26874 frame=$5 i=0 go_on=1 26875 26876 l $1 onfail go_on=0 endl # Load first image. 26877 if !$go_on return fi 26878 w={w} h={h} s={s} 26879 if {*} w. ${fitscreen\ $w,$h},0,"[G'MIC]" fi 26880 pframe=$frame frame+=$7 26881 do 26882 l[] $1 onfail go_on=0 endl 26883 if !$go_on break fi 26884 to_colormode. $s r. $w,$h 26885 cutvals={[min(im#0,im#1),max(iM#0,iM#1)]} 26886 e[] "\r - Frame ""#"$pframe" -> ""#"$frame" " 26887 +equalize[0,1] n[-2,-1] 0,255 26888 +displacement[3] [2],$3,$4 +displacement[2] [3],$3,$4 rm[-4,-3] 26889 repeat $2+2 if $< 26890 title="Frame ""#"$pframe" -> ""#"$frame" ("$>/$2") " 26891 e[] "\r - "$title 26892 t={$>/($2+1)} omt={1-$t} 26893 +*[2] $t +warp[0] .,1,1,1 rm.. *. $omt 26894 +*[3] {1-$t} +warp[1] .,1,1,1 rm.. *. $t 26895 +[-2,-1] c. $cutvals 26896 if narg("$8") 26897 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o. "$8",25,mp4v,1 else filename "$8",$i i+=1 o. ${} fi 26898 fi 26899 if {*} 26900 w. -1,-1,0,$title 26901 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 26902 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 26903 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 26904 fi 26905 rm. 26906 fi done 26907 rm[0,-2,-1] pframe=$frame frame+=$7 26908 while $go_on" && "($6==-1" || "$frame<=$6) 26909 26910 # Output last frame. 26911 if narg("$8") 26912 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o[] "$8",25,mp4v,0 else filename "$8",$i o. ${} fi 26913 fi 26914 rm 26915 26916#@cli register_nonrigid : [destination],_smoothness>=0,_precision>0,_nb_scale>=0 26917#@cli : Register selected source images with specified destination image, using non-rigid warp. 26918#@cli : Default values: 'smoothness=0.2', 'precision=6' and 'nb_scale=0(auto)'. 26919#@cli : $ image.jpg +rotate 20,1,1,50%,50% +register_nonrigid[0] [1] 26920register_nonrigid : check ${is_image_arg\ $1}" && ${2=0.2}>=0 && ${3=5}>0 && ${4=0}>=0" 26921 e[^-1] "Register source image$? with destination image $1, using non-rigid warp with smoothness $2, 26922 precision $3 and $4 scale(s)." 26923 pass$1 0 equalize. n. 0,255 26924 repeat $!-1 26925 +equalize[$>] n. 0,255 +displacement.. .,$2,$3,$4 rm.. 26926 warp[$>] .,1,1,1 rm. 26927 done rm. 26928 26929#@cli register_rigid : [destination],_smoothness>=0,\ 26930# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 26931#@cli : Register selected source images with specified destination image, using rigid warp (shift). 26932#@cli : Default values: 'smoothness=0.1%' and 'boundary_conditions=0'. 26933#@cli : $ image.jpg +shift 30,20 +register_rigid[0] [1] 26934register_rigid : check ${is_image_arg\ $1}" && ${2=0.1%}>=0 && isint(${3=0}) && $3>=0 && $3<=3" 26935 e[^-1] "Register source image$? with destination image $1, using rigid warp with smoothness $2." 26936 m "_register_rigid : b $2 equalize 256 n 0,1" 26937 pass$1 0 W,H,D,S={[w,h,d,s]} 26938 f={max(w,h)/1024} 26939 if $f<=1 # Small image: one-step registration 26940 _register_rigid. 26941 repeat $!-1 26942 if {$>,w!=$W||h!=$H||d!=$D} 26943 error[0--4] "Images have incompatible sizes ("{$>,[w,h,d,s]}") and ("{[$W,$H,$D,$S]}")." 26944 fi 26945 +_register_rigid[$>] phase_correlation. .. shift[$>] {^},0,$3 rm. 26946 done 26947 rm. 26948 else # Large image: two-steps registration 26949 +r. {[min(w,1024),min(h,1024),min(d,1024)]},100%,0,0,0.5,0.5 26950 rr2d.. 1024,1024,0,2 26951 _register_rigid[-2,-1] 26952 repeat $!-2 26953 if {$>,w!=$W||h!=$H||d!=$D} 26954 error[0--4] "Images have incompatible sizes ("{$>,[w,h,d,s]}") and ("{[$W,$H,$D,$S]}")." 26955 fi 26956 26957 # Low scale. 26958 +rr2d[$>] 1024,1024,0,2 _register_rigid. 26959 phase_correlation. ... 26960 s={$f*crop()} rm. 26961 26962 # High scale. 26963 +shift[$>] $s,0,$3 26964 r. {[min(w,1024),min(h,1024),min(d,1024)]},100%,0,0,0.5,0.5 _register_rigid. 26965 phase_correlation. .. 26966 s={[$s]+crop()} rm. 26967 26968 shift[$>] $s,0,$3 26969 done 26970 rm[-2,-1] 26971 fi 26972 um _register_rigid 26973 26974#@cli transition : [transition_shape],nb_added_frames>=0,100>=shading>=0,_single_frame_only={ -1=disabled | >=0 } 26975#@cli : Generate a transition sequence between selected images. 26976#@cli : Default values: 'shading=0' and 'single_frame_only=-1'. 26977#@cli : $ image.jpg +mirror c 100%,100% plasma[-1] 1,1,6 transition[0,1] [2],5 26978transition : check ${is_image_arg\ $1}" && $2>=0 && ${3=0}>=0 && $3<=100" skip ${4=-1} 26979 frame={round($4)} s0=" and shading $3" s1=", shading $3 and single-frame-only "$frame 26980 e[^-1] "Create transition sequence between image$? with $2 added frames, transition shape $1"${s{$4>0}}"." 26981 if $!<2" || "!$2 return fi 26982 to_colormode 0 r ${-max_whd},100%,0,0,0.5,0.5 26983 pass$1 0 norm. r. [0],[0],[0],1,3 n. 0,1 mv. 0 26984 repeat $!-2 l[0,{$<+1},{$<+2}] 26985 nm0={1,n} 26986 if $3 repeat $2 if $4<0" || "$>==$frame 26987 val0={($>+0.5)/$2-$3%} 26988 val1={($>+0.5)/$2+$3%} 26989 +f[0] '(i-$val0)/($val1-$val0)' c. 0,1 26990 +j[2] [1],0,0,0,0,1,. rm.. 26991 nm. $nm0\ ""#{1+$>} 26992 fi done else repeat $2 if $4<0" || "$>==$frame 26993 +>=[0] {($>+0.5)/$2} 26994 +j[2] [1],0,0,0,0,1,. rm.. 26995 nm. $nm0\ ""#{1+$>} 26996 fi done fi 26997 mv[2] $! 26998 endl done rm[0] 26999 27000#@cli transition3d : _nb_frames>=2,_nb_xtiles>0,_nb_ytiles>0,_axis_x,_axis_y,_axis_z,_is_antialias={ 0 | 1 } 27001#@cli : Create 3D transition sequence between selected consecutive images. 27002#@cli : 'axis_x', 'axis_y' and 'axis_z' can be set as mathematical expressions, depending on 'x' and 'y'. 27003#@cli : Default values: 'nb_frames=10', 'nb_xtiles=nb_ytiles=3', 'axis_x=1', 'axis_y=1', 'axis_z=0' \ 27004# and 'is_antialias=1'. 27005#@cli : $ image.jpg +blur 5 transition3d 9 display_rgba 27006transition3d : check "isint(${1=10}) && $1>=2 && isint(${2=3}) && $2>0 && isint(${3=$2}) && $3>0" 27007 skip ${4=1},${5=1},${6=0},${7=1} 27008 e[^-1] "Create 3D transition sequence between image$?, with $1 frames, $2x$3 tiles and rotation axis ($4,$5,$6).\n" 27009 if $!<2 return fi 27010 slices 0 to_rgb r ${-max_whds},3 27011 off=0 repeat $!-1 l[{$>+$off},{$>+$off+1}] 27012 e[] "\r > Generate transition from image "$>" to image "{$>+1}". " 27013 27014 # Create 3D rotation vectors. 27015 $2,$3,1,1,'$4' 27016 $2,$3,1,1,'$5' 27017 $2,$3,1,1,'$6' 27018 a[-3--1] z 27019 permute. zxyc r. 3,{$2*$3},1,1,-1 27020 repeat h rot$>={@0-2} shift. 0,-1,0,0 done 27021 rm. 27022 27023 # Create 3D tiles. 27024 +split_tiles[-2,-1] $2,$3 mv[0,1] $! 27025 N={$2*$3} i=0 y=0 27026 repeat $3 27027 x=0 27028 repeat $2 27029 lw={$i,w} lh={$i,h} 27030 imageplane3d[$i] imageplane3d[$N] r3d[$N] ${rot$i},180 c3d[$i,$N] +3d[$i,$N] 27031 x$i=$x y$i=$y x+=$lw i+=1 27032 done 27033 y+=$lh 27034 done 27035 27036 # Generate intermediate animation frames. 27037 repeat $1-2 27038 repeat $N r3d[$>] ${rot$>},{180/(1-$1)} ++3d[$>] ${x$>},${y$>},0 done 27039 +3d[-$N--1] c3d. 27040 27041 if $7 # Antialiased rendering. 27042 i... {-2,2*[w,h]},1,3,-1 27043 *3d. 2 j3d... .,50%,50%,0,1,2,0,0 rm. 27044 to_rgba.. replace_color.. 0,0,-1,-1,-1,255,0,0,0,0 27045 downsize_aliased.. 50 27046 else # Standard rendering. 27047 i... {-2,w},{-2,h},1,3,-1 j3d... .,50%,50%,0,1,2,0,0 rm. 27048 to_rgba.. replace_color.. 0,0,-1,-1,-1,255,0,0,0,0 27049 fi 27050 27051 done 27052 rm[0-{$N-1}] 27053 nm[1--2] {0,n} 27054 off+={$1-2} 27055 endl done 27056 27057#@cli video2files : input_filename,_output_filename,_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1 27058#@cli : Split specified input video file into image files, one for each frame. 27059#@cli : First and last frames as well as step between frames can be specified. 27060#@cli : Default values: 'output_filename=frame.png', 'first_frame=0', 'last_frame=-1' and 'frame_step=1'. 27061video2files : check "isint(${3=0}) && $3>=0 && isint(${4=-1}) && ($4>=0 || $4==-1) && isint(${5=1}) && $5>=1" 27062 skip ${2="frame.png"} 27063 e[^-1] "Split input video file '$1' into image frames '$2', with first frame $3, last frame $4, and frame step $5.\n" 27064 frame=$3 stopflag=0 27065 do l[] 27066 i "$1",$frame 27067 if $! 27068 o ${"filename \"$2\","$frame} rm 27069 e[] "\r > Frame ""#"$frame 27070 frame+=$5 27071 else stopflag=1 27072 fi 27073 onfail stopflag=1 27074 endl while !$stopflag" && "($frame<=$4" || "$4==-1) 27075 27076#------------------------------ 27077# 27078#@cli :: Convenience Functions 27079# 27080#------------------------------ 27081 27082#@cli alert : _title,_message,_label_button1,_label_button2,... 27083#@cli : Display an alert box and wait for user's choice. 27084#@cli : If a single image is in the selection, it is used as an icon for the alert box. 27085#@cli : Default values: 'title=[G'MIC Alert]' and 'message=This is an alert box.'. 27086alert : skip "${1=[G"{`39`}"MIC Alert]},${2=This is an alert box.},${3=OK}" 27087 if $!==1 27088 e[0--3] "Display alert box, with image$?, title '$1', message '$2' and buttons '${3--1}'." 27089 else 27090 e[0--3] "Display alert box, with title '$1', message '$2' and buttons '${3--1}'." 27091 fi 27092 27093 if $!==1 logo= else logo=[] fi 27094 +l$logo 27095 27096 # Manage alert icon. 27097 if $!==1 to_rgb 27098 else # No logo provided, generate default logo (alert). 27099 64,64 polygon 3,50%,10%,10%,90%,90%,90%,1,1 b 3 >= 50% 27100 +erode. 5 -. .. ==. 0 27101 polygon. 4,47%,43%,53%,43%,53%,66%,47%,66%,1,0 circle. 50%,76%,2,1,0 27102 +*[0] 255 . 100%,100% a[-3--1] c -. '3*(y-h/2)' 27103 *. .. rm.. *[0] 255 rv a c 27104 drop_shadow 3,3,1 i[0] 100%,100%,1,3,200 blend alpha 27105 fi 27106 channels -1,2 27107 27108 # Create buttons graphics. 27109 $=arg 27110 repeat $#-2 label=${arg{$>+3}} 0 t. $label,0,0,16,1,-200 done 27111 r[^0] {min(128,max(64,${max_w[^0]}+12))},{min(48,max(24,${max_h[^0]}+12))},1,1,0,0,0.5,0.5 27112 +[^0] 200 to_rgb[^0] 27113 mv[0] $! 27114 [0],[0],1,1,'(y-h/2)' *. -2 c. -30,30 +[0--3] . rm. c[^-1] 0,255 # Add shading to buttons. 27115 27116 repeat $!-1 l[$<] 27117 27118 # Create selected buttons. 27119 +rectangle 0,0,100%,100%,1,0xFFFFFFFF,0 27120 rectangle. 1,1,{w-2},{h-2},1,0xFFFFFFFF,0 27121 line. 2,{h-3},{w-3},{h-3},1,150 line. {w-3},{h-3},{w-3},2,1,150 27122 line. 1,1,{w-3},1,1,255 line. 1,1,1,{h-3},1,255 27123 rectangle. 4,4,{w-5},{h-5},1,0xAAAAAAAA,0 27124 27125 # Create clicked buttons. 27126 +shift.. 1,1,0,0,2 27127 rectangle. 0,0,100%,100%,1,0xFFFFFFFF,0 27128 rectangle. 1,1,{w-2},{h-2},1,0xFFFFFFFF,150 27129 rectangle. 4,4,{w-5},{h-5},1,0xAAAAAAAA,0 27130 27131 # Create default aspect. 27132 rectangle... 0,0,100%,100%,1,0xFFFFFFFF,0 27133 line... 1,{h-2},{w-2},{h-2},1,150 line... {w-2},{h-2},{w-2},1,1,150 27134 line... 0,0,{w-2},0,1,255 line... 0,0,0,{h-2},1,255 27135 27136 # Create coordinates image. 27137 i[0] 100%,100% =[0] 1,0,0 27138 27139 a c endl done 27140 27141 27142 # Render alert box graphics. 27143 +l 27144 channels 0,3 sh 1,100% -[50%--1] 200 rm[50%--1] frame 8,8,0 27145 if $!<6 a[^-1] x else append_tiles[^-1] , fi 27146 0 t. "$2",0,0,16,1,0,-200,-200,-200 r. {w+16},{h+8},1,4,0 27147 a[-2,-1] x,0.5 rv a y,0.5 27148 sh 1,100% +. 200 rm. 27149 rectangle 0,0,100%,100%,1,0xFFFFFFFF,0 27150 line 0,0,{w-2},0,1,0,255,255,255 line 0,0,0,{h-2},1,0,255,255,255 27151 endl 27152 rm.. 27153 +channels. 0 27154 27155 # Retrieve (x,y) coordinates of the buttons and fill active area. 27156 (0,{w-1}) (0;{-2,h-1}) ri[-2,-1] ...,3 a[-2,-1] c round. rv[-2,-1] *[-2,-1] 27157 discard. 0 y. r. {h/2},2,1,1,-1 27158 channels.. 1,3 rv[-2,-1] 27159 100%,100% repeat w#-3 x0={-3,i($>,0)} y0={-3,i($>,1)} rectangle. $x0,$y0,{$x0+{0,w}-1},{$y0+{0,h}-1},1,{1+$>} done 27160 a[-2,-1] c 27161 27162 # Enter event loop. 27163 repeat 9 if !{*$>} disp=$> break fi done # Find available display window. 27164 if !narg($disp) error[0--4] "Command '$0': Cannot open display window for alert box." fi 27165 27166 selected={if($#==3,0,-1)} clicked=-1 27167 do 27168 27169 # Render current view. 27170 +channels. 0,2 27171 if $clicked>=0 27172 x0={-3,i($clicked,0)} y0={-3,i($clicked,1)} 27173 sh[$clicked] 7,9 27174 j.. .,$x0,$y0 rm. 27175 elif $selected>=0 27176 x0={-3,i($selected,0)} y0={-3,i($selected,1)} 27177 sh[$selected] 4,6 27178 j.. .,$x0,$y0 rm. 27179 fi 27180 w$disp. 100%,100%,0,"$1" rm. wait 27181 27182 # Handle user interactions. 27183 xm={*$disp,x} ym={*$disp,y} bm={{*$disp,b}&1} val={i($xm,$ym,0,3)} 27184 if $bm" && "$val clicked={$val-1} 27185 elif $bm" && "!$val" && "$clicked>=0 selected=$clicked clicked=-1 27186 elif !$bm" && "$clicked>=0" && "$clicked==$val-1 break 27187 fi 27188 if {*$disp,ARROWRIGHT} selected={($selected+1)%{-2,w}} wait -1 27189 elif {*$disp,ARROWLEFT} selected={($selected-1)%{-2,w}+($selected==-1)} wait -1 27190 elif $selected>=0" && "{*$disp,ENTER} clicked=$selected break 27191 fi 27192 27193 while {*$disp}" && "!{*$disp,ESC} 27194 27195 # Return result (index of clicked button or '-1'). 27196 w$disp 0 rm u $clicked 27197 endl 27198 27199#@cli arg : n>=1,_arg1,...,_argN 27200#@cli : Return the n-th argument of the specified argument list. 27201arg : check "isint($1) && ($1)>0" 27202 $=arg u ${arg{1+($1)}} 27203 27204#@cli arg0 : n>=0,_arg0,...,_argN 27205#@cli : Return the n-th argument of the specified argument list (where 'n' starts from '0'). 27206arg0 : check "isint($1) && ($1)>=0" 27207 $=arg u ${arg{2+($1)}} 27208 27209#@cli arg2img : argument_1,...,argument_N 27210#@cli : Split specified list of arguments and return each as a new image (as a null-terminated string). 27211arg2img : 27212 $=arg repeat $# ({'${arg{1+$>}}'},0) done 27213 27214#@cli arg2var : variable_name,argument_1,...,argument_N 27215#@cli : For each i in [1...N], set 'variable_name$i=argument_i'. 27216#@cli : The variable name should be global to make this command useful (i.e. starts by an underscore). 27217arg2var : 27218 $=arg u {$#-1} repeat ${} $1{1+$>}=${arg{2+$>}} done 27219 27220#@cli autocrop_coords : value1,value2,... | auto 27221#@cli : Return coordinates (x0,y0,z0,x1,y1,z1) of the autocrop that could be performed on the latest 27222#@cli : of the selected images. 27223#@cli : Default value: 'auto' 27224autocrop_coords : skip ${1=auto} 27225 is_auto={['"$1"']=='auto'} 27226 w={w} h={h} d={d} 27227 value={i(w-1,h-1,d-1)} +=. {1+$value},100%,100%,100% _autocrop$is_auto. ${1--1} =. $value,100%,100%,100% 27228 x0={$w-w} y0={$h-h} z0={$d-d} rm. 27229 +_autocrop$is_auto. ${1--1} 27230 x1={$x0+w-1} y1={$y0+h-1} z1={$z0+d-1} rm. 27231 u $x0,$y0,$z0,$x1,$y1,$z1 27232 27233_autocrop0 : autocrop $* 27234_autocrop1 : skip $* autocrop 27235 27236#@cli average_colors 27237#@cli : Return the average vector-value of the latest of the selected images. 27238average_colors : 27239 res="" 27240 repeat s-1 sh. {1+$>} res=$res,{ia} rm. done 27241 sh. 0 u {ia}$res rm. 27242 27243#@cli base642img : "base64_string" 27244#@cli : Decode given base64-encoded string as a newly inserted image at the end of the list. 27245#@cli : The argument string must have been generated using command 'img2base64'. 27246base642img : 27247 base642uchar "$1" unserialize. 27248 27249#@cli base642uchar : "base64_string" 27250#@cli : Decode given base64-encoded string as a newly inserted 1-column image at the end of the list. 27251#@cli : The argument string must have been generated using command 'uchar2base64'. 27252base642uchar : 27253 0 27254 eval " 27255 ref(vector256(),hash); 27256 for (k = _'A', k<=_'Z', ++k, hash[k] = k - _'A'); 27257 for (k = _'a', k<=_'z', ++k, hash[k] = k - _'a' + 26); 27258 for (k = _'0', k<=_'9', ++k, hash[k] = k - _'0' + 52); 27259 hash[_'+'] = hash[_'-'] = 62; 27260 hash[_'/'] = hash[_'_'] = 63; 27261 s = ['$1']; 27262 const ss = size(s); 27263 ss>=2?( 27264 resize(#-1,1,ss*3/4 - (s[ss-1]==_'=') - (s[ss-2]==_'='),1,1); 27265 od = 0; 27266 for (os = 0, os<size(s), 27267 c1 = hash[s[os++]]; 27268 c2 = hash[s[os++]]; 27269 c3 = hash[s[os++]]; 27270 c4 = hash[s[os++]]; 27271 i[#-1,od++] = (c1<<2) | (c2>>4); 27272 i[#-1,od++] = ((c2&15)<<4) | (c3>>2); 27273 i[#-1,od++] = ((c3&3)<<6) | c4; 27274 ) 27275 )" 27276 nm. "[unnamed]" 27277 27278#@cli basename : file_path,_variable_name_for_folder 27279#@cli : Return the basename of a file path, and opt. its folder location. 27280#@cli : When specified 'variable_name_for_folder' must starts by an underscore 27281#@cli : (global variable accessible from calling function). 27282basename : skip ${2=unused} 27283 l[] ({"'$1'"}) replace 92,47 s +,47 27284 if i==47 a y $2={t} u "" 27285 elif $!==1 u {t} $2="" 27286 else a[^-1] y u {t} $2={-2,t} 27287 fi 27288 rm endl 27289 27290#@cli bin : binary_int1,... 27291#@cli : Print specified binary integers into their octal, decimal, hexadecimal and string representations. 27292bin : 27293 dec=${bin2dec\ ${^0}} 27294 e[^-1] "Convert binary integer"${arg\ 1+($#>1),"",s}" '${^0}' to octal '"${dec2oct\ $dec}"', 27295 decimal '"$dec"', hexadecimal '"${dec2hex\ $dec}"' and string '"${dec2str\ $dec}"'." 27296 27297#@cli bin2dec : binary_int1,... 27298#@cli : Convert specified binary integers into their decimal representations. 27299bin2dec : 27300 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 27301 27302_bin2dec : 27303 u {"str = vtos(abs($1)); 27304 for (k = val = 0, str[k], ++k, 27305 c = str[k]; 27306 (val<<=1)+=(c==_'0'?0:c==_'1'?1:nan); 27307 isnan(val)?break() 27308 ); sign($1)*val"} 27309 27310# Command to check what lines of G'MIC sources are larger than 120 columns. 27311_check120 : 27312 use_vt100 27313 it[] "$1" s +,10 27314 1,$!,1,2,">begin(line = 1); is_lines=i[#y,0]==10; line+=is_lines?h#y:0; [is_lines || h#y<=120?-1:y,line]" 27315 lines={{@-1}-1} f. "I = I; if(I[0]<0,I[1]=-1); I" 27316 discard. -1 27317 if w 27318 r. 1,{h/2},1,2,-1 27319 repeat h 27320 l,L={I[$>]} 27321 e[] $_vt100_c" - [Line "$_vt100_b$L$_vt100_n$_vt100_c", "\ 27322 $_vt100_b{$l,h}$_vt100_n$_vt100_c" chars]: "$_vt100_n{$l,t} 27323 done 27324 fi 27325 rm 27326 _total_lines+=$lines 27327 e[] " - Scanned : "${lines}" lines" 27328 27329check120 : 27330 _total_lines=0 27331 files 0,*.h c={`narg($files)?',':0`} if narg(${}) files=$files$c${} fi 27332 files 0,*.cpp c={`narg($files)?',':0`} if narg(${}) files=$files$c${} fi 27333 files 0,*.c c={`narg($files)?',':0`} if narg(${}) files=$files$c${} fi 27334 files 0,*.gmic c={`narg($files)?',':0`} if narg(${}) files=$files$c${} fi 27335 repeat narg($files) 27336 arg 1+$>,$files file=${} 27337 e[] " * File '"$file"'." 27338 v + _check120 $file v - 27339 done 27340 e[] " - Total scanned : "${_total_lines}" lines" 27341 27342#@cli covariance_colors : _avg_outvarname 27343#@cli : Return the covariance matrix of the vector-valued colors in the latest of the selected images 27344#@cli : (for arbitrary number of channels). 27345#@cli : Parameter 'avg_outvarname' is used as a variable name that takes the value of the average vector-value. 27346covariance_colors : skip "${1=avg}" 27347 $1=${-average_colors} 27348 f ">begin( avg = [ "$""$1" ]; const S2 = s^2; C = vectorS2(0); ); 27349 mI = I - avg; C+=mul(mI,mI,s); 27350 end( C/=whd - 1; run('u ',vtos(C)) ); 27351 I" 27352 27353#@cli dec : decimal_int1,... 27354#@cli : Print specified decimal integers into their binary, octal, hexadecimal and string representations. 27355dec : 27356 e[^-1] "Convert decimal integer"${arg\ 1+($#>1),"",s}" '${^0}' to binary '"${dec2bin\ ${^0}}"',"\ 27357 " octal '"${dec2oct\ ${^0}}"', hexadecimal '"${dec2hex\ ${^0}}"' and string '"${dec2str\ ${^0}}"'." 27358 27359#@cli dec2str : decimal_int1,... 27360#@cli : Convert specifial decimal integers into its string representation. 27361dec2str : 27362 u {`[${^0}]`} 27363 27364#@cli dec2bin : decimal_int1,... 27365#@cli : Convert specified decimal integers into their binary representations. 27366dec2bin : 27367 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 27368 27369_dec2bin : 27370 u {`"const sgn = sign($1); 27371 const N = (isinf($1) || isnan($1)?1:1 + floor(log2(max(1,abs($1))))) + (sgn>=0?0:1); 27372 res = vectorN(); 27373 sgn>=0?0:(res[0] = _'-'); 27374 for (val = abs($1); k = size(res) - 1, k>=(sgn<0?1:0), --k, res[k] = _'0' + (val&1); val>>=1); res"`} 27375 27376#@cli dec2hex : decimal_int1,... 27377#@cli : Convert specified decimal integers into their hexadecimal representations. 27378dec2hex : 27379 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 27380 27381_dec2hex : 27382 u {`"begin(tab = [ _'0',_'1',_'2',_'3',_'4',_'5',_'6',_'7',_'8',_'9',_'a',_'b',_'c',_'d',_'e',_'f' ]); 27383 const sgn = sign($1); 27384 const N = (isinf($1) || isnan($1)?1:1 + floor(log2(max(1,abs($1)))/4)) + (sgn>=0?0:1); 27385 res = vectorN(); 27386 sgn>=0?0:(res[0] = _'-'); 27387 for (val = abs($1); k = size(res) - 1, k>=(sgn<0?1:0), --k, res[k] = tab[val&15]; val>>=4); res"`} 27388 27389#@cli dec2oct : decimal_int1,... 27390#@cli : Convert specified decimal integers into their octal representations. 27391dec2oct : 27392 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 27393 27394_dec2oct : 27395 u {`"const sgn = sign($1); 27396 const N = (isinf($1) || isnan($1)?1:1 + floor(log2(max(1,abs($1)))/3)) + (sgn>=0?0:1); 27397 res = vectorN(); 27398 sgn>=0?0:(res[0] = _'-'); 27399 for (val = abs($1); k = size(res) - 1, k>=(sgn<0?1:0), --k, res[k] = _'0' + (val&7); val>>=3); res"`} 27400 27401#@cli fact : value 27402#@cli : Return the factorial of the specified value. 27403fact : check isint($1) 27404 res=1 repeat $1 res*={($>+1)} done u $res 27405 27406#@cli fibonacci : N>=0 27407#@cli : Return the Nth number of the Fibonacci sequence. 27408#@cli : $ echo ${"fibonacci 10"} 27409#@cli : \n~~~\n[gmic]-0./ Start G'MIC interpreter.\n[gmic]-0./ 55\n[gmic]-0./ End G'MIC interpreter.\n~~~\n 27410fibonacci : check "$1>=0" 27411 u {N=$1;if(N<2,N,for(n=N;F0=0;F1=1,n=n-1,F2=F0+F1;F0=F1;F1=F2))} 27412 27413#@cli file_mv : filename_src,filename_dest 27414#@cli : Rename or move a file from a location $1 to another location $2. 27415file_mv : 27416 e[^-1] "Move file '$1' to location '$2'." 27417 if ${-is_windows} x "move "$1" "$2 else x "mv "$1" "$2 fi 27418 27419#@cli file_rand 27420#@cli : Return a random filename for storing temporary data. 27421file_rand : 27422 do filename=${-path_tmp}gmic$_pid{`round(u(vector6(_'0'),vector6(_'9')))`} 27423 while isfile(['{/$filename}']) 27424 u $filename 27425 27426#@cli filename : filename,_number1,_number2,...,_numberN 27427#@cli : Return a filename numbered with specified indices. 27428filename : skip "${1=default}" 27429 if $#==1 u "$1" 27430 else 27431 (${2--1}) nm. "$1" u {f}{b} 27432 repeat w 27433 u ${}_{int(i/100000)%10}{int(i/10000)%10}{int(i/1000)%10}{int(i/100)%10}{int(i/10)%10}{i%10} 27434 shift. -1 27435 done 27436 if narg({'{x}'}) u ${}.{x} fi 27437 rm. 27438 fi 27439 27440#@cli files : _mode,path : (+) 27441#@cli : Return the list of files and/or subfolders from specified path. 27442#@cli : 'path' can be eventually a matching pattern. 27443#@cli : 'mode' can be { 0=files only | 1=folders only | 2=files + folders }. 27444#@cli : Add '3' to 'mode' to return full paths instead of filenames only. 27445#@cli : Default value: 'mode=5'. 27446 27447#@cli files2img : _mode,path 27448#@cli : Insert a new image where each vector-valued pixel is a string encoding the filenames returned by \ 27449# command ''files''. 27450#@cli : Useful to manage list of filenames containing characters that have a special meaning in the G'MIC language,\ 27451# such as spaces or commas. 27452+files2img : 27453 if ['$$_$0_f2i']==0 m "_$0_f2i: $""=arg repeat $""# ({'${arg{1+$>}}'}:^) done a y" fi 27454 files $"*" l[] _$0_f2i[] ${} if !$! 0 fi endl 27455 27456#@cli fitratio_wh : min_width,min_height,ratio_wh 27457#@cli : Return a 2D size 'width,height' which is bigger than 'min_width,min_height' and has the specified w/h ratio. 27458fitratio_wh : 27459 if $3*$2>$1 u {int($3*$2)},$2 else u $1,{int($1/$3)} fi 27460 27461#@cli fitscreen : width,height,_depth,_minimal_size[%],_maximal_size[%] : [image],_minimal_size[%],_maximal_size[%] 27462#@cli : Return the 'ideal' size WxH for a window intended to display an image of specified size on screen. 27463#@cli : Default values: 'depth=1', 'minimal_size=128' and 'maximal_size=85%'. 27464fitscreen : skip "${2=},${3=},${4=},${5=}" 27465 if ${"is_image_arg $1"} 27466 l$1 W,H,D={[w,h,d]} endl if narg($2) m=$2 else m=25% fi if narg($3) M=$3 else M=85% fi 27467 else 27468 W,H=${1-2} if narg($3) D=$3 else D=1 fi if narg($4) m=$4 else m=25% fi if narg($5) M=$5 else M=85% fi 27469 fi 27470 eval " 27471 is_percent(str) = (unref(_is_pct); _is_pct=['#str']; _is_pct[size(_is_pct) - 1]==_'%'); 27472 const u = "{*,u}"; 27473 const v = "{*,v}"; 27474 ms = round(is_percent("$m")?[ u,v ]*"$m":[ "$m,$m" ]); 27475 Ms = round(is_percent("$M")?[ u,v ]*"$M":[ "$M,$M" ]); 27476 s = [ "$W,$H" ]; 27477 "$D">1?(s+="$D"); 27478 s[0]<ms[0]?(s = [ ms[0],s[1]*ms[0]/s[0] ]); 27479 s[1]<ms[1]?(s = [ s[0]*ms[1]/s[1],ms[1] ]); 27480 s[0]>Ms[0]?(s = [ Ms[0],s[1]*Ms[0]/s[0] ]); 27481 s[1]>Ms[1]?(s = [ s[0]*Ms[1]/s[1],Ms[1] ]); 27482 s[0] = max(1,s[0],ms[0]); 27483 s[1] = max(1,s[1],ms[1]); 27484 round(s)" 27485 27486#@cli fontchart 27487#@cli : Insert G'MIC font chart at the end of the image list. 27488#@cli : $ fontchart 27489+fontchart : 27490 e[^-1] "Generate G'MIC font chart." 27491 l[] 27492 repeat 256 27493 if $>==92 char=\\ else char={`max(1,(c=$>;c>=23&&c<=28?32:c))`} fi 27494 0 t. {``$char},0,0,50,1,255 27495 done 27496 a z,0.5 27497 s z 27498 repeat $! 27499 t[$>] $>,1,-1,13,1,200 27500 0 t. \\${dec2oct\ $>},1,-1,13,1,1 27501 100%,100%,1,1,200 j[$>] .,{$>,[w,h]-[w#-1,h#-1]},0,0,1,.. rm[-2,-1] 27502 done 27503 frame 1,1,128 append_tiles , 27504 endl 27505 27506# font2cimgh 27507# Encode a font image as a C-style string for CImg.h. 27508font2cimgh : 27509 e[^-1] "Encode font image$? as a C-style string for CImg.h." 27510 repeat $! l[$>] bnm={0,b} 27511 e[] " > Encode font '"$bnm"'." 27512 W,H={[w/256,h]} 27513 if !isint($W) error[0--4] "Font image '"$bnm"' has wrong dimensions ("{[w,h,d,s]}")." fi 27514 +f "i==im || i==iM" is_binary={im==1} rm. 27515 27516 # Find best parameters for RLE compression. 27517 Mm=0 MM=100 27518 do 27519 M={floor(($Mm+$MM)/2)} 27520 +compress_rle $is_binary,$M rows. 6,100% +. {32-im} iM={iM} 27521 if iM<126 Mm=$M rm. elif iM>126 MM=$M rm. fi 27522 while $iM!=126 27523 k. nb_chunks={1+int(h/65536)} 27524 27525 e[] "\r > Encode font '"$bnm"' -> W = "$W", H = "$H", M = "$M", is_binary = "$is_binary", 27526 nb_chunks = "$nb_chunks"." 27527 27528 # Generate C-style string for storing font data. 27529 replace_str "\\","\\\\" 27530 replace_str "\"","\\\"" 27531 s y,-111 27532 repeat $! 27533 if {$>,i[h-1]==_'\\'&&i[h-2]!=_'\\'} rows[$>] 0,{$>,h-2} rows[{$>+1}] -1,100% =[{$>+1}] {'\\'} fi 27534 l[$>] 27535 i[0] ('" \""') ('\"') 27536 if !$< ('" };"') fi 27537 ('\n') 27538 y a y 27539 endl 27540 done 27541 repeat $nb_chunks-1 ind={int($!*($>+1)/$nb_chunks)} l[$ind] = {','},0,100% ('\n') y a y endl done 27542 i[0] ('" static const char *const data_font"${W}x${H}"[] = {"\n') 27543 y a y ot $bnm.h 27544 27545 endl done 27546 27547#@cli fps 27548#@cli : Return the number of time this function is called per second, or -1 if this info is not yet available. 27549#@cli : Useful to display the framerate when displaying animations. 27550fps : 27551 if narg($_fps_fps) 27552 dt={$|-$_fps_time} 27553 if $dt>1 _fps_fps={round($_fps_nbframes/$dt)} _fps_time=$| _fps_nbframes=0 fi 27554 u $_fps_fps 27555 _fps_nbframes+=1 27556 else _fps_nbframes=0 _fps_time=$| _fps_fps=-1 u -1 27557 fi 27558 27559#@cli gcd : a,b 27560#@cli : Return the GCD (greatest common divisor) between a and b. 27561gcd : check "isint($1) && isint($2) && $1*$2!=0" 27562 _gcd {max(abs($1),abs($2))},{min(abs($1),abs($2))} 27563 27564_gcd : 27565 r={$1%$2} if $r u ${_gcd\ $2,$r} else u $2 fi 27566 27567#@cli hex : hexadecimal_int1,... 27568#@cli : Print specified hexadecimal integers into their binary, octal, decimal and string representations. 27569hex : 27570 dec=${hex2dec\ ${^0}} 27571 e[^-1] "Convert hexadecimal integer"${arg\ 1+($#>1),s,""}" '${^0}' to binary '"${dec2bin\ $dec}"', 27572 octal '"${dec2oct\ $dec}"', decimal '"$dec"' and string '"${dec2str\ $dec}"'." 27573 27574#@cli hex2dec : hexadecimal_int1,... 27575#@cli : Convert specified hexadecimal integers into their decimal representations. 27576hex2dec : 27577 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 27578 27579_hex2dec : 27580 u {"str = ['$1']; str[0]==_'-'?-stov([['0x'],str[1,max(1,size(str)-1)]]):stov([['0x'],str])"} 27581 27582#@cli hex2img : "hexadecimal_string" 27583#@cli : Insert new image 1xN at the end of the list with values specified by the given hexadecimal-encoded string. 27584+hex2img : 27585 ('"$1"') 1,{w/2} 27586 f. "* 27587 from_char(x) = x>=48 && x<=57?x - 48:x-87; 27588 off = 2*y; 27589 from_char(i[#-2,off])*16 + from_char(i[#-2,off + 1])" 27590 rm.. 27591 27592#@cli hex2str : hexadecimal_string 27593#@cli : Convert specified hexadecimal string into a string. 27594#@cli : See also: ''str2hex''. 27595hex2str : skip ${1=""} 27596 if !narg("$1") u "" return fi 27597 ('$*') if w<2 rm. u "" return fi 27598 f. 'v=i-if(i>=97,87,48);if(x%2,v,v*16)' r. 2,{int(w/2)},1,1,-1 cumulate. x z. 1,1 27599 u {t} rm. 27600 27601#@cli img2base64 : _encoding={ 0=base64 | 1=base64url },_store_names={ 0 | 1 } 27602#@cli : Encode selected images as a base64-encoded string. 27603#@cli : The images can be then decoded using command 'base642img'. 27604#@cli : Default values: 'encoding=0'. 27605img2base64 : check "isbool(${1=0}) && isbool(${2=1})" 27606 if isnum("$1") encoding=$1 else encoding=0 noarg fi 27607 +serialize auto,1,$2 u ${uchar2base64\ $encoding} rm. 27608 27609#@cli img2hex 27610#@cli : Return representation of last image as an hexadecimal-encoded string. 27611#@cli : Input image must have values that are integers in [0,255]. 27612img2hex : 27613 whds={w},{h},{d},{s} y. 2,{h} 27614 f.. "* 27615 to_char(x) = x>=0 && x<=9?48 + x:87 + x; 27616 i(#-1,0,y) = to_char(int(i/16)); 27617 i(#-1,1,y) = to_char(i%16); 27618 i" 27619 u {t} rm. r. $whds,-1 27620 27621#@cli img2str 27622#@cli : Return the content of the latest of the selected images as a special G'MIC input string. 27623img2str : 27624 i[-2] 256 27625 eval. ">begin(off = 0); 27626 sep = x==w - 1?(y==h - 1?(z==d - 1?(c==s - 1?0:_'^'):_'/'):_';'):_','; 27627 it = vtos(i); 27628 off + size(it) + 1>=w(#-2)?resize(#-2,round(1.5*w(#-2)),1,1,1,0); 27629 for (k = 0, k<size(it) && it[k], ++k, i[#-2,off++] = it[k]); 27630 i[#-2,off++] = sep" 27631 u {-2,t} rm.. 27632 27633#@cli img2text : _line_separator 27634#@cli : Return text contained in a multi-line image. 27635#@cli : Default value: 'line_separator= '. 27636img2text : skip "${1= }" 27637 +l s y s -,0 y x if $!>1 i[1--2] ('"$1"') fi a x u {0,t} rm endl 27638 27639#@cli img82hex 27640#@cli : Convert selected 8bits-valued vectors into their hexadecimal representations (ascii-encoded). 27641img82hex : 27642 e[^-1] "Convert 8bits-valued vector$? into hexadecimal representations (ascii-encoded)." 27643 % 256 y 27644 repeat $! 27645 +f[$>] 'v=int(i)&15;v+if(v<10,48,87)' # Lower digit 27646 f[$>] 'v=int(i)>>4;v+if(v<10,48,87)' # Higher digit 27647 a[$>,-1] x 27648 done 27649 27650#@cli hex2img8 27651#@cli : Convert selected hexadecimal representations (ascii-encoded) into 8bits-valued vectors. 27652hex2img8 : 27653 e[^-1] "Convert hexadecimal representation$? (ascii-encoded) into 8bits-valued vectors." 27654 repeat $! 27655 s. x,2 f[-2,-1] 'if(i>=97,i-87,i-48)' *.. 16 +[-2,-1] 27656 mv. 0 done 27657 27658#@cli is_3d 27659#@cli : Return 1 if all of the selected images are 3D objects, 0 otherwise. 27660is_3d : 27661 u 1 l check3d 1 onfail u 0 endl 27662 27663# Faster version. 27664_is_3d : 27665 u {"h>6 && int(i[0])==67 && int(i[1])==73 && int(i[2])==109 && int(i[3])==103 && int(i[4])==51 && int(i[5])==100"} 27666 27667#@cli is_change : _value={ 0=false | 1=true } 27668#@cli : Set or unset the 'is_change' flag associated to the image list. 27669#@cli : This flag tells the interpreter whether or not the image list should be displayed when the pipeline ends. 27670#@cli : Default value: 'value=1'. 27671is_change : 27672 l[] check "isbool(${1=1})" arg=$1 onfail noarg arg=1 endl 27673 if $arg 0 rm. else w9[] 0 fi 27674 27675#@cli is_half 27676#@cli : Return 1 if the type of image pixels is limited to half-float. 27677is_half : 27678 (2049) u {i==2048} rm. 27679 27680#@cli is_ext : filename,_extension 27681#@cli : Return 1 if specified filename has a given extensioin. 27682is_ext : skip "${2=}" 27683 0 nm. "_$1" u {"lowercase(['"{x}"'])==lowercase(['$2'])"} rm. 27684 27685#@cli is_image_arg : string 27686#@cli : Return 1 if specified string looks like '[ind]'. 27687is_image_arg : skip "${1=;}" 27688 u {"str = ['$1']; 27689 s1 = size(str) - 1; 27690 (str[0]==_'[' && str[s1]==_']') || (str[0]=='.' && str[s1]=='.') && min(str)>=45 && max(str)<=122"} 27691 27692#@cli is_pattern : string 27693#@cli : Return 1 if specified string looks like a drawing pattern '0x......'. 27694is_pattern : skip "${1=;}" 27695 u {"str = ['$1']; size(str)>2 && same(str,'0x',2)"} 27696 27697#@cli is_percent : string 27698#@cli : Return 1 if specified string ends with a '%', 0 otherwise. 27699is_percent : 27700 u {"s=['$1'];s[size(s)-1]==_'%'"} 27701 27702#@cli is_videofilename 27703#@cli : Return 1 if extension of specified filename is typical from video files. 27704is_videofilename : skip "${1=}" 27705 0 nm. "_$1" u {" 27706 ext = lowercase(['"{x}"']); 27707 ext=='avi' || ext=='mov' || ext=='asf' || ext=='divx' || ext=='flv' || ext=='mpg' || 27708 ext=='m1v' || ext=='m2v' || ext=='m4v' || ext=='mjp' || ext=='mp4' || ext=='mkv' || 27709 ext=='mpe' || ext=='movie' || ext=='ogm' || ext=='ogg' || ext=='ogv' || ext=='qt' || ext=='rm' || 27710 ext=='vob' || ext=='wmv' || ext=='xvid' || ext=='mpeg'"} 27711 rm. 27712 27713#@cli is_macos 27714#@cli : Return 1 if current computer OS is Darwin (MacOS), 0 otherwise. 27715is_macos : 27716 if !narg($_is_macos) l[] 27717 if ${-is_windows} _is_macos=0 27718 else 27719 file=${-path_tmp}gmic_uname 27720 x "uname >"{/$file} 27721 it[] $file 27722 _is_macos={same(crop(),'Darwin',6,0)} 27723 rm 27724 fi 27725 onfail _is_macos=0 rm 27726 endl fi 27727 u $_is_macos 27728 27729#@cli is_windows 27730#@cli : Return 1 if current computer OS is Windows, 0 otherwise. 27731is_windows : 27732 if !narg($_is_windows) _is_windows={['$OS']!=0" && "['$WINDIR']!=0} fi 27733 u $_is_windows 27734 27735#@cli math_lib 27736#@cli : Return string that defines a set of several useful macros for the embedded math evaluator. 27737math_lib : 27738 u " 27739 27740 # Return number of elements in min-heap #ind. 27741 heap_size(ind) = i[#ind,whd(#ind)-1]; 27742 27743 # Insert new element 'elt' into min-heap #ind. 27744 heap_insert(ind,elt) = ( 27745 _heap_siz = heap_size(#ind); 27746 _heap_siz>=h(#ind) - 1?resize(#ind,1,_heap_siz*2 + 2,1,s#ind,0); 27747 hind = h(#ind); 27748 unref(_heap_elt); 27749 _heap_elt = [ elt ]; 27750 _heap_eltsiz = max(1,size(_heap_elt)); 27751 27752 copy(i[#ind,_heap_siz],_heap_elt[0],_heap_eltsiz,hind,1); 27753 for (_heap_pos = _heap_siz, 27754 _heap_pos && (_heap_par = int((_heap_pos + 1)/2) - 1; _heap_elt[0]<i[#ind,_heap_par]), 27755 _heap_pos = _heap_par, 27756 copy(i[#ind,_heap_pos],i[#ind,_heap_par],_heap_eltsiz,hind,hind); 27757 copy(i[#ind,_heap_par],_heap_elt,_heap_eltsiz,hind,1); 27758 ); 27759 (heap_size(#ind)) = ++_heap_siz; 27760 ); 27761 27762 # Remove root element from min-heap #ind. 27763 heap_remove(ind) = ( 27764 _heap_siz = heap_size(#ind) - 1; 27765 hind = h(#ind); 27766 _heap_eltsiz = max(1,s#ind); 27767 27768 copy(i[#ind,0],i[#ind,_heap_siz],_heap_eltsiz,hind,hind); 27769 _heap_pos = 0; 27770 do ( 27771 _heap_left = 2*_heap_pos + 1; 27772 _heap_right = _heap_left + 1; 27773 value = i[#ind,_heap_pos]; 27774 _heap_right<_heap_siz && value>i[#ind,_heap_right]?( 27775 _heap_swap = i[#ind,_heap_left]<i[#ind,_heap_right]?_heap_left:_heap_right; 27776 ):_heap_left<_heap_siz && value>i[#ind,_heap_left]?( 27777 _heap_swap = _heap_left; 27778 ):break(); 27779 copy(i[#ind,_heap_siz],i[#ind,_heap_swap],_heap_eltsiz,hind,hind); # Use previous last elt as temporary for swap. 27780 copy(i[#ind,_heap_swap],i[#ind,_heap_pos],_heap_eltsiz,hind,hind); 27781 copy(i[#ind,_heap_pos],i[#ind,_heap_siz],_heap_eltsiz,hind,hind); 27782 _heap_pos = _heap_swap; 27783 ); 27784 (heap_size(#ind)) = _heap_siz; 27785 ); 27786 27787 # Return number of elements in dynamic array #ind. 27788 dar_size(ind) = i[#ind,h(#ind) - 1]; 27789 27790 # Return last element of a dynamic array 27791 dar_Back(ind) = I[#ind,dar_size(#ind) - 1]; 27792 dar_back(ind) = i[#ind,dar_size(#ind) - 1]; 27793 27794 # Inserts new element 'elt' into dynamic array #ind, at index [pos] ('pos' must be in [0,dar_size(#ind)]). 27795 dar_insert(ind,elt,pos) = ( 27796 ref(pos,_dar_pos); 27797 ref(elt,_dar_elt); 27798 _dar_siz = dar_size(#ind); 27799 ref(max(1,s(#ind),size(_dar_elt)),_dar_sizelt); 27800 if (_dar_pos<=_dar_siz, 27801 _dar_siz>=h(#ind) - 1?resize(#ind,1,_dar_siz*2 + 2,1,_dar_sizelt,0); 27802 for (_dar_c = 0, _dar_c<_dar_sizelt, ++_dar_c, 27803 copy(i(#ind,_dar_pos + 1,0,0,_dar_c),i(#ind,_dar_pos,0,0,_dar_c),_dar_siz - _dar_pos) 27804 ); 27805 copy(i[#ind,_dar_pos],_dar_elt,_dar_sizelt,h(#ind),1); 27806 i[#ind,h(#ind) - 1] = ++_dar_siz; 27807 ); 27808 ); 27809 27810 # Inserts new element 'elt' at the end of dynamic array #ind. 27811 dar_insert(ind,elt) = ( 27812 ref(elt,_dar_elt); 27813 _dar_siz = dar_size(#ind); 27814 ref(max(1,s(#ind),size(_dar_elt)),_dar_sizelt); 27815 _dar_siz>=h(#ind) - 1?resize(#ind,1,_dar_siz*2 + 2,1,_dar_sizelt,0); 27816 copy(i[#ind,_dar_siz],_dar_elt,_dar_sizelt,h(#ind),1); 27817 i[#ind,h(#ind) - 1] = ++_dar_siz; 27818 ); 27819 27820 # Remove element from dynamic array #ind, at index [pos] ('pos' must be in [0,dar_size(#ind) - 1]). 27821 dar_remove(ind,pos) = ( 27822 ref(pos,_dar_pos); 27823 _dar_siz = dar_size(#ind); 27824 if (_dar_pos<_dar_siz, 27825 _dar_siz = --dar_size(#ind); 27826 for (_dar_c = 0, _dar_c<s(#ind), ++_dar_c, 27827 copy(i(#ind,_dar_pos,0,0,_dar_c),i(#ind,_dar_pos + 1,0,0,_dar_c),_dar_siz - _dar_pos) 27828 ); 27829 ) 27830 ); 27831 27832 # Remove last element from dynamic array #ind. 27833 dar_remove(ind) = ( 27834 _dar_siz = dar_size(#ind); 27835 _dar_siz>0?--dar_size(#ind); 27836 ); 27837 27838 # Distance from point A to point B 27839 dist(A,B) = ( 27840 norm(B - A); 27841 ); 27842 27843 # Distance from point X to segment [A,B] 27844 dist(X,A,B) = ( 27845 AB = B - A; 27846 P = A + dot(X - A,B - A)/max(1e-8,dot(AB,AB))*AB; 27847 dot(P - A,P - B)<=0?norm(P - X):min(norm(A - X),norm(B - X)); 27848 ); 27849 27850 # Distance from segment [A,B] to segment [C,D] 27851 dist(A,B,C,D) = ( 27852 min(dist(A,C,D),dist(B,C,D),dist(C,A,B),dist(D,A,B)); 27853 ); 27854 27855 # Return the 'm' largest eigenvalues of a (large) square matrix A, 27856 # using the Arnoldi iteration method (https://en.wikipedia.org/wiki/Arnoldi_iteration). 27857 # A larger 'm' goes with better numerical precision. 27858 meig(A,m,n) = ( 27859 unref(meig_m,meig_n); 27860 const meig_n = n; 27861 const meig_m = min(m,meig_n); 27862 27863 # Initialize data. 27864 ref(vector(#meig_m*meig_n),meig_V); 27865 ref(vector(#meig_m^2),meig_H); 27866 ref(expr('u(-1,1)',1,meig_n),meig_vj); meig_vj/=norm(meig_vj); 27867 27868 # Iteration loop. 27869 repeat (meig_m,meig_j, 27870 copy(meig_V[meig_j*meig_n],meig_vj,meig_n); 27871 meig_vj = A*meig_vj; 27872 for (meig_i = 0, meig_i<=meig_j, ++meig_i, 27873 ref(meig_V[meig_i*meig_n,meig_n],meig_vi); 27874 meig_d = dot(meig_vj,meig_vi); 27875 meig_H[meig_j*meig_m + meig_i] = meig_d; 27876 meig_vj-=meig_d*meig_vi; 27877 ); 27878 meig_nvj = norm(meig_vj); 27879 meig_H[meig_j*meig_m + meig_j + 1] = meig_nvj; 27880 meig_nvj<1e-12?break(); 27881 meig_vj/=meig_nvj; 27882 ); 27883 eig(meig_H)[0,m]; 27884 ); 27885 27886 # Dichotomic search : Find x in [xmin,xmax] s.a f(x) = target, with a epsilon-precision 27887 search_dichotomic(fn_x,target,epsilon,xmin,xmax) = ( 27888 # fn_x must be a strictly monotonic function ! 27889 # if 'xmin = xmax = nan', range of 'x' is auto-detected. 27890 _dicho_fn(x) = _dicho_sgn*(fn_x); 27891 _dicho_epsilon = epsilon; 27892 _dicho_m = xmin; 27893 _dicho_M = xmax; 27894 _dicho_sgn = 1; 27895 _dicho_autom = isnan(_dicho_m); 27896 _dicho_autoM = isnan(_dicho_M); 27897 if (_dicho_autom, _dicho_m = -1); 27898 if (_dicho_autoM, _dicho_M = 1); 27899 _dicho_sgn = _dicho_fn(_dicho_m)>_dicho_fn(_dicho_M)?-1:1; 27900 _dicho_res = nan; 27901 _dicho_target = _dicho_sgn*target; 27902 _dicho_nb_attempts = 30; 27903 _dicho_autom?do ( 27904 _dicho_fm = _dicho_fn(_dicho_m); 27905 _dicho_fm<_dicho_target?break(); 27906 _dicho_m*=2; 27907 _(while), --_dicho_nb_attempts); 27908 _dicho_nb_attempts?( 27909 _dicho_autoM?do ( 27910 _dicho_fM = _dicho_fn(_dicho_M); 27911 _dicho_fM>_dicho_target?break(); 27912 _dicho_M*=2; 27913 _(while), --_dicho_nb_attempts); 27914 _dicho_nb_attempts?( 27915 _dicho_nb_attempts = 100; 27916 do ( 27917 _dicho_c = (_dicho_m + _dicho_M)/2; 27918 _dicho_fc = _dicho_fn(_dicho_c); 27919 abs(_dicho_fc - _dicho_target)<_dicho_epsilon?(_dicho_res = _dicho_c; break()): 27920 _dicho_fc<_dicho_target?(_dicho_m = _dicho_c): 27921 (_dicho_M = _dicho_c); 27922 _(while), --_dicho_nb_attempts 27923 ); 27924 ); 27925 ); 27926 _dicho_res; 27927 ); 27928 search_dichotomic(fn_x,target,epsilon) = search_dichotomic(fn_x,target,1e-3,nan,nan); 27929 search_dichotomic(fn_x,target) = search_dichotomic(fn_x,target,1e-3); 27930 search_dichotomic(fn_x) = search_dichotomic(fn_x,0); 27931 27932 arrow(ind,P0,P1,angle,length,opacity,color) = ( # Draw an arrow from P0 to P1 on image #ind 27933 unref(_da_color); 27934 _opacity = opacity; 27935 _da_color = color; 27936 _P0 = P0; 27937 _P1 = P1; 27938 _P0P1 = _P1; 27939 _P0P1-=_P0; 27940 if (length<0, _P0P1*=-length/100, _P0P1*=length/norm2(_P0P1)); 27941 coords = [ _P0,_P1,_P1,_P1 - rot(angle°)*_P0P1,_P1,_P1 - rot(-angle°)*_P0P1 ]; 27942 repeat (3,_k, polygon(#ind,2,coords[4*_k,2],coords[4*_k+2,2],_opacity,_da_color)); 27943 ); 27944 27945 spline(ind,P0,T0,P1,T1,opacity,color) = ( # Draw spline P0-P1 with tangents T0,T1 on image #ind 27946 unref(_ds_color); 27947 _P0 = P0; 27948 _P1 = P1; 27949 _opacity = opacity; 27950 _ds_color = resize(color,s#ind)*=abs(_opacity); 27951 _omopacity = 1 - max(_opacity,0); 27952 _C = mul([ 2,-2,1,1,-3,3,-2,-1,0,0,1,0,1,0,0,0 ],[ _P0,P1,T0,T1 ],2); 27953 _dt = _dtmin = 1/max(abs(_P1 - _P0)); 27954 _P0 = inf; 27955 for (_t = 0, _t<=1, _t+=_dt, 27956 _P = round(mul([_t^3,_t^2,_t,1],_C,2)); 27957 _dP = abs(mul([3*_t^2,2*_t,1,0],_C,2)); 27958 _dt = min(_dtmin,0.75/max(_dP)); 27959 if (_P0!=_P, I(#ind,_P) = _ds_color + _omopacity*I(#ind,_P)); 27960 _P0 = _P; 27961 ); 27962 nan; 27963 ); 27964 27965 triangle(ind,P0,P1,P2,opacity,color0,color1,color2) = ( # Draw a shaded triangle P0-P1-P2 on image #ind 27966 unref(_dt_color); 27967 unref(_dt_color0); 27968 unref(_dt_color1); 27969 unref(_dt_color2); 27970 _opacity = opacity; 27971 _dt_color0 = resize(color0,s#ind); 27972 _dt_color1 = resize(color1,s#ind); 27973 _dt_color2 = resize(color2,s#ind); 27974 _A = round(P0); 27975 _B = round(P1); 27976 _C = round(P2); 27977 _xmin = max(0,min(_A[0],_B[0],_C[0])); 27978 _xmax = min(w#ind-1,max(_A[0],_B[0],_C[0])); 27979 _ymin = max(0,min(_A[1],_B[1],_C[1])); 27980 _ymax = min(h#ind-1,max(_A[1],_B[1],_C[1])); 27981 _M = transpose([_A,1,_B,1,_C,1],3); 27982 for (_y = _ymin, _y<_ymax, ++_y, 27983 for (_x = _xmin, _x<_xmax, ++_x, 27984 _L = round(solve(_M,[_x,_y,1]),1e-5); 27985 if (min(_L)>=0, 27986 _dt_color = _L[0]*_dt_color0 + _L[1]*_dt_color1 + _L[2]*_dt_color2; 27987 copy(i(#ind,_x,_y,0,0),_dt_color,size(_dt_color),whd#ind,1,_opacity); 27988 ); 27989 ); 27990 ); 27991 nan; 27992 ); 27993 27994 hsv2rgb(I) = ( # Convert HSV vector to RGB 27995 ref(I,_I); 27996 _I[0]%=360; 27997 _I[1] = cut(_I[1],0,1); 27998 _I[2] = cut(_I[2],0,1); 27999 _c = _I[2]*_I[1]; 28000 _x = _c*(1-abs((_I[0]/60)%2-1)); 28001 (arg(1 + int(_I[0]/60),[_c,_x,0],[_x,_c,0],[0,_c,_x],[0,_x,_c],[_x,0,_c],[_c,0,_x])+=_I[2] - _c)*=255; 28002 ); 28003 28004 rgb2hsv(I) = ( # Convert RGB vector to HSV 28005 ref(I,_I); 28006 _M = max(_I); 28007 _C = _M - min(_I); 28008 [ 60*(_C==0?0:_M==_I[0]?((_I[1] - _I[2])/_C)%6:_M==_I[1]?(_I[2] - _I[0])/_C + 2:(_I[0] - _I[1])/_C + 4), 28009 _M<=0?0:_C/_M, _M/255 ]; 28010 ); 28011 28012 is_intriangle(P,A,B,C) = ( # Test if a point is inside a triangle 28013 _v0 = C - A; 28014 _v1 = B - A; 28015 _v2 = P - A; 28016 _dot00 = dot(_v0,_v0); 28017 _dot01 = dot(_v0,_v1); 28018 _dot02 = dot(_v0,_v2); 28019 _dot11 = dot(_v1,_v1); 28020 _dot12 = dot(_v1,_v2); 28021 _invDenom = 1/(_dot00*_dot11 - _dot01*_dot01); 28022 _u = (_dot11*_dot02 - _dot01*_dot12)*_invDenom; 28023 _v = (_dot00*_dot12 - _dot01*_dot02)*_invDenom; 28024 _u>=0 && _v>=0 && _u + _v<1); 28025 28026 is_inquadrilateral(P,A,B,C,D) = ( # Test if a point is inside a quadrilateral 28027 is_intriangle(P,A,B,D) || is_intriangle(P,B,C,D); 28028 ); 28029 28030 is_percent(str) = (unref(_is_pct); _is_pct=['#str']; _is_pct[size(_is_pct) - 1]==_'%'); 28031 28032 length_spline(P0,T0,P1,T1) = ( # Compute the length of a spline P0-P1 with tangents T0,T1 28033 _P0 = P0; 28034 _P1 = P1; 28035 _C = mul([ 2,-2,1,1,-3,3,-2,-1,0,0,1,0,1,0,0,0 ],[ _P0,_P1,T0,T1 ],2); 28036 _l = norm(_P1 - _P0); 28037 if (_l, 28038 _nl = _l + 1; 28039 _dt = 1/_l; 28040 while (_nl - _l>=0.01, 28041 _l = _nl; 28042 _nl = 0; 28043 __P0 = _P0; 28044 for (_t = 0, _t<=1, _t+=_dt, 28045 __P = mul([_t^3,_t^2,_t,1],_C,2); 28046 _nl+=norm(__P - __P0); 28047 __P0 = __P; 28048 ); 28049 _dt = 1/max(1,_nl); 28050 ); 28051 ); 28052 _l 28053 ); 28054 28055 pexp(x) = ( # Good polynomial approximation of 'exp(-x^2)' for |x|<2 28056 _pexp_x = abs(x); 28057 _pexp_x<2?-0.110353*_pexp_x^4 + 0.683221*_pexp_x^3 -1.17282*_pexp_x^2 + 1:0 28058 ); 28059 28060 proj(X,A,B) = ( # Projection of point X onto line (A,B) 28061 _AB = B - A; 28062 P = A + dot(X - A,_AB)/max(1e-8,dot(_AB,_AB))*_AB; 28063 ); 28064 28065 # CIE DeltaE_2000 color difference function. 28066 # (code adapted from https://github.com/gfiumara/CIEDE2000). 28067 deltaE00(lab1,lab2) = ( 28068 _deltaE00_deg2rad(deg) = (deg*pi/180); 28069 unref(_deltaE00_lab1); _deltaE00_lab1 = lab1; 28070 unref(_deltaE00_lab2); _deltaE00_lab2 = lab2; 28071 unref(_deltaE00_k_L); const _deltaE00_k_L = 1; 28072 unref(_deltaE00_k_C); const _deltaE00_k_C = 1; 28073 unref(_deltaE00_k_H); const _deltaE00_k_H = 1; 28074 unref(_deltaE00_deg360inrad); const _deltaE00_deg360inrad = _deltaE00_deg2rad(360); 28075 unref(_deltaE00_deg180inrad); const _deltaE00_deg180inrad = _deltaE00_deg2rad(180); 28076 unref(_deltaE00_pow25to7); const _deltaE00_pow25to7 = 25^7; 28077 28078 # Step 1 28079 _deltaE00_C1 = norm(_deltaE00_lab1[1,2]); 28080 _deltaE00_C2 = norm(_deltaE00_lab2[1,2]); 28081 _deltaE00_barC = (_deltaE00_C1 + _deltaE00_C2)/2; 28082 _deltaE00_G = 0.5*(1 - sqrt(_deltaE00_barC^7/(_deltaE00_barC^7 + _deltaE00_pow25to7))); 28083 _deltaE00_a1prime = (1 + _deltaE00_G)*_deltaE00_lab1[1]; 28084 _deltaE00_a2prime = (1 + _deltaE00_G)*_deltaE00_lab2[1]; 28085 _deltaE00_Cprime1 = norm(_deltaE00_a1prime,_deltaE00_lab1[2]); 28086 _deltaE00_Cprime2 = norm(_deltaE00_a2prime,_deltaE00_lab2[2]); 28087 28088 _deltaE00_lab1[2]==0 && _deltaE00_a1prime==0?( 28089 _deltaE00_hprime1 = 0; 28090 ):( 28091 _deltaE00_hprime1 = atan2(_deltaE00_lab1[2],_deltaE00_a1prime); 28092 _deltaE00_hprime1<0?(_deltaE00_hprime1+=_deltaE00_deg360inrad); 28093 _deltaE00_lab2[2]==0 && _deltaE00_a2prime==0?( 28094 _deltaE00_hprime2 = 0; 28095 ):( 28096 _deltaE00_hprime2 = atan2(_deltaE00_lab2[2],_deltaE00_a2prime); 28097 _deltaE00_hprime2<0?(_deltaE00_hprime2+=_deltaE00_deg360inrad); 28098 ); 28099 ); 28100 28101 # Step 2 28102 _deltaE00_deltaLprime = _deltaE00_lab2[0] - _deltaE00_lab1[0]; 28103 _deltaE00_deltaCprime = _deltaE00_Cprime2 - _deltaE00_Cprime1; 28104 _deltaE00_CprimeProduct = _deltaE00_Cprime1*_deltaE00_Cprime2; 28105 _deltaE00_CprimeProduct==0?( 28106 _deltaE00_deltahprime = 0; 28107 ):( 28108 _deltaE00_deltahprime = _deltaE00_hprime2 - _deltaE00_hprime1; 28109 _deltaE00_deltahprime<-_deltaE00_deg180inrad?( 28110 _deltaE00_deltahprime += _deltaE00_deg360inrad; 28111 ):_deltaE00_deltahprime>_deltaE00_deg180inrad?( 28112 _deltaE00_deltahprime -= _deltaE00_deg360inrad; 28113 ); 28114 ); 28115 _deltaE00_deltaHprime = 2*sqrt(_deltaE00_CprimeProduct)*sin(_deltaE00_deltahprime/2); 28116 28117 # Step 3 28118 _deltaE00_barLprime = (_deltaE00_lab1[0] + _deltaE00_lab2[0])/2; 28119 _deltaE00_barCprime = (_deltaE00_Cprime1 + _deltaE00_Cprime2)/2; 28120 _deltaE00_hprimeSum = _deltaE00_hprime1 + _deltaE00_hprime2; 28121 _deltaE00_Cprime1*_deltaE00_Cprime2==0?( 28122 _deltaE00_barhprime = _deltaE00_hprimeSum; 28123 ):( 28124 abs(_deltaE00_hprime1 - _deltaE00_hprime2)<=_deltaE00_deg180inrad?( 28125 _deltaE00_barhprime = _deltaE00_hprimeSum/2; 28126 ):( 28127 _deltaE00_hprimeSum<_deltaE00_deg360inrad?( 28128 _deltaE00_barhprime = (_deltaE00_hprimeSum + _deltaE00_deg360inrad)/2; 28129 ):( 28130 _deltaE00_barhprime = (_deltaE00_hprimeSum - _deltaE00_deg360inrad)/2; 28131 ); 28132 ); 28133 ); 28134 28135 _deltaE00_T = 1.0 - (0.17*cos(_deltaE00_barhprime - _deltaE00_deg2rad(30))) + 28136 (0.24*cos(2*_deltaE00_barhprime)) + 28137 (0.32*cos(3*_deltaE00_barhprime + _deltaE00_deg2rad(6))) - 28138 (0.2*cos(4*_deltaE00_barhprime - _deltaE00_deg2rad(63))); 28139 _deltaE00_deltaTheta = _deltaE00_deg2rad(30)* 28140 exp(-((_deltaE00_barhprime - _deltaE00_deg2rad(275)) / _deltaE00_deg2rad(25))^2); 28141 28142 _deltaE00_R_C = 2*sqrt(_deltaE00_barCprime^7/(_deltaE00_barCprime^7 + _deltaE00_pow25to7)); 28143 _deltaE00_S_L = 1 + 0.015*(_deltaE00_barLprime - 50)^2/sqrt(20 + (_deltaE00_barLprime - 50)^2); 28144 _deltaE00_S_C = 1 + 0.045*_deltaE00_barCprime; 28145 _deltaE00_S_H = 1 + 0.015*_deltaE00_barCprime*_deltaE00_T; 28146 _deltaE00_R_T = -sin(2*_deltaE00_deltaTheta)* _deltaE00_R_C; 28147 28148 sqrt((_deltaE00_deltaLprime/(_deltaE00_k_L*_deltaE00_S_L))^2 + 28149 (_deltaE00_deltaCprime/(_deltaE00_k_C*_deltaE00_S_C))^2 + 28150 (_deltaE00_deltaHprime/(_deltaE00_k_H*_deltaE00_S_H))^2 + 28151 _deltaE00_R_T*_deltaE00_deltaCprime/(_deltaE00_k_C*_deltaE00_S_C)* 28152 _deltaE00_deltaHprime/(_deltaE00_k_H*_deltaE00_S_H)); 28153 );" 28154 28155#@cli mad 28156#@cli : Return the MAD (Maximum Absolute Deviation) of the last selected image. 28157#@cli : The MAD is defined as MAD = med_i|x_i-med_j(x_j)| 28158mad : 28159 if $! +-. {ic} abs. u {1.4826*ic} rm. else u 0 fi 28160 28161#@cli max_w 28162#@cli : Return the maximal width between selected images. 28163max_w : 28164 _minmax_whds max,0,1 28165 28166#@cli max_h 28167#@cli : Return the maximal height between selected images. 28168max_h : 28169 _minmax_whds max,1,1 28170 28171#@cli max_d 28172#@cli : Return the maximal depth between selected images. 28173max_d : 28174 _minmax_whds max,2,1 28175 28176#@cli max_s 28177#@cli : Return the maximal spectrum between selected images. 28178max_s : 28179 _minmax_whds max,3,1 28180 28181#@cli max_wh 28182#@cli : Return the maximal wxh size of selected images. 28183max_wh : 28184 _minmax_whds max,0,2 28185 28186#@cli max_whd 28187#@cli : Return the maximal wxhxd size of selected images. 28188max_whd : 28189 _minmax_whds max,0,3 28190 28191#@cli max_whds 28192#@cli : Return the maximal wxhxdxs size of selected images. 28193max_whds : 28194 _minmax_whds max,0,4 28195 28196#@cli median_color 28197#@cli : Return the median color value of the last selected image. 28198median_color : 28199 u {"expr('med(crop(#-1,0,0,0,y,w#-1,h#-1,d#-1,1))',1,3)"} 28200 28201#@cli min_w 28202#@cli : Return the minimal width between selected images. 28203min_w : 28204 _minmax_whds min,0,1 28205 28206#@cli min_h 28207#@cli : Return the minimal height between selected images. 28208min_h : 28209 _minmax_whds min,1,1 28210 28211#@cli min_d 28212#@cli : Return the minimal depth between selected images. 28213min_d : 28214 _minmax_whds min,2,1 28215 28216#@cli min_s 28217#@cli : Return the minimal s size of selected images. 28218min_s : 28219 _minmax_whds min,3,1 28220 28221#@cli min_wh 28222#@cli : Return the minimal wxh size of selected images. 28223min_wh : 28224 _minmax_whds min,0,2 28225 28226#@cli min_whd 28227#@cli : Return the minimal wxhxd size of selected images. 28228min_whd : 28229 _minmax_whds min,0,3 28230 28231#@cli min_whds 28232#@cli : Return the minimal wxhxdxs size of selected images. 28233min_whds : 28234 _minmax_whds min,0,4 28235 28236_minmax_whds : 28237 u {" 28238 mw = w; mh = h; md = d; ms = s; 28239 repeat (l,k, 28240 mw = $1(mw,w#k); 28241 mh = $1(mh,h#k); 28242 md = $1(md,d#k); 28243 ms = $1(ms,s#k); 28244 ); 28245 ([mw,mh,md,ms])[$2,$3]"} 28246 28247 28248#@cli nmd : eq. to 'named' : (+) 28249 28250#@cli named : _mode,"name1","name2",... : (+) 28251#@cli : Return the set of indices corresponding to images of the selection with specified names. 28252#@cli : After this command returns, the status contains a list of indices (unsigned integers), 28253#@cli : separated by commas (or an empty string if no images with those names have been found). 28254#@cli : (eq. to 'nmd'). 28255#@cli : 'mode' can be { 0=all indices (default) | 1=lowest index | 2=highest index | \ 28256# 3 = all indices (case insensitive) | 4 = lowest index (case insensitive) | 5 = highest index (case insensitive)} 28257 28258#@cli normalize_filename : filename 28259#@cli : Return a "normalized" version of the specified filename, without spaces and capital letters. 28260normalize_filename : 28261 ('"$1"') f. 'if(i>=65&&i<=90,i+32,if(i==32,95,i))' u {t} rm. 28262 28263#@cli oct : octal_int1,... 28264#@cli : Print specified octal integers into their binary, decimal, hexadecimal and string representations. 28265oct : 28266 dec=${oct2dec\ ${^0}} 28267 e[^-1] "Convert octal integer"${arg\ 1+($#>1),"",s}" '${^0}' to binary '"${dec2bin\ $dec}"', decimal '"$dec"', 28268 hexadecimal '"${dec2hex\ $dec}"' and string '"${dec2str\ $dec}"'." 28269 28270#@cli oct2dec : octal_int1,... 28271#@cli : Convert specified octal integers into their decimal representations. 28272oct2dec : 28273 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 28274 28275_oct2dec : 28276 u {"str = vtos(abs($1)); 28277 for (k = val = 0, str[k], ++k, 28278 c = str[k]; 28279 (val<<=3)+=(c>=_'0' && c<=_'7'?c - _'0':nan); 28280 isnan(val)?break() 28281 ); sign($1)*val"} 28282 28283#gmic ovh2stats : logfile_globname 28284#gmic : Generate statistics on the usage of G'MIC-Qt from OVH server logfiles. 28285#gmic : logfiles must be located in current directory. 28286#gmic : Default value: 'logfile_globname=gmic.eu-*-*-*.log.gz" 28287ovh2stats : skip "${1=gmic.eu-*-*-*.log.gz}" 28288 e[^-1] "Generate statistics on the usage of G'MIC-Qt from OVH server logfiles '$1'." 28289 use_vt100 28290 28291 # Load log files. 28292 files "$1" files=${} 28293 e[] "* Load log files." 28294 if !narg(${}) error[0--2] "No OVH logfiles matching name '$1' have been found." fi 28295 28296 repeat narg(${}) 28297 arg0 $>,$files file=${} 28298 day,month,year={"str = ['"$file"']; 28299 t1 = find(str,_'-') + 1; 28300 t2 = find(str,_'-',t1) + 1; 28301 t3 = find(str,_'-',t2) + 1; 28302 t1>0 && t2>t1 && t3>t2?( 28303 day = stov(str,t1); 28304 month = stov(str,t2); 28305 year = stov(str,t3); 28306 [ day,month,year ]; 28307 ):[0,0,0]"} 28308 if !$day&&!$month&&!$year day,month,year=n.a fi 28309 e[] " > "$year/$month/$day:" "$_vt100_g$file$_vt100_n 28310 it $file 28311 nm. ${year}_${month}_${day} 28312 done 28313 28314 # Keep only lines containing 'G'MIC-Qt'. 28315 repeat $! nm={$>,n} l[$>] s -,{'\n'} 28316 eval " 28317 str = ['G'MIC-Qt']; 28318 to_keep = vectorl(); 28319 p = 0; 28320 repeat (l,k, find(#k,str)>=0?(to_keep[p++] = k)); 28321 store(to_keep,'to_keep',p); 28322 run('$to_keep k[{^}]')" 28323 if $!>1 i[1--2] ('\n') fi 28324 a y nm $nm endl done 28325 28326 # Analyze log files. 28327 e[] "\n* Analyze log files (day by day)." 28328 +_ovh2stats # Display stats, day by day. 28329 28330 e[] "\n* Analyze log files (all days)." 28331 a y _ovh2stats # Display stats, all days. 28332 28333 28334_ovh2stats : 28335 v + N=$! repeat $! l[$>] ('{n}') replace. {'_'},{'^'} ({t}) 28336 date={`[vtos(i0,0,4),_'/',i1<10?[_'0',i1+_'0']:vtos(i1,0,2),_'/',i2<10?[_'0',i2+_'0']:vtos(i2,0,2)]`} 28337 s -,{'\n'} 28338 28339 # Name each image by the IP address. 28340 eval " 28341 name = vector256(); 28342 repeat (l,k, 28343 p = find(#k,_' '); 28344 copy(name,i[#k,0],p); 28345 name[p] = 0; 28346 run('name[',k,'] ',name); 28347 )" 28348 28349 # Discard IP duplicates. 28350 eval " 28351 const N = "$!"; 28352 ref(vector(#2*N),tab); 28353 repeat (N,k, 28354 ref(name(#k,256),nam); 28355 for (i = j = 0, i<size(nam) && nam[i], ++i, nam[i]!=_'.'?(nam[j++] = nam[i])); nam[j] = 0; 28356 tab[2*k] = stov(nam); 28357 tab[2*k + 1] = k; 28358 ); 28359 tab = sort(tab,1,N,2); 28360 for (i = 0, i<size(tab) - 1, ++i, tab[2*i]==tab[2*i + 2]?tab[2*i] = tab[2*i + 1] = -1); 28361 store(tab,'tab')" 28362 $tab discard. -1 r. 2,{h/2},1,1,-1 z. 1,1 k[{^}] 28363 28364 # Analyze G'MIC version, host software and OS. 28365 eval " 28366 gimp = krita = _8bf = paintdotnet = digikam = standalone = 0; 28367 linux = windows = macos = bsd = unknown = 0; 28368 versions = vector400(); 28369 prereleases = 0; 28370 ips = 0; 28371 repeat (l,k, 28372 ref(lowercase(crop(#k,0,0,0,0,1,256,1,1)),str); 28373 find(str,'gimp')>=0?++gimp: 28374 find(str,'krita')>=0?++krita: 28375 find(str,'8bf')>=0?++_8bf: 28376 find(str,'paint.net')>=0?++paintdotnet: 28377 find(str,'digikam')>=0?++digikam: 28378 ++standalone; 28379 28380 find(str,'windows')>=0?++windows: 28381 find(str,'linux')>=0?++linux: 28382 find(str,'mac os')>=0?++macos: 28383 find(str,'bsd')>=0?++bsd: 28384 ++unknown; 28385 28386 (eos = find(str,0))<0?(eos = size(str)); 28387 space = find(str,_' ',eos,-1); 28388 ver = sum(([ str[space + 1],str[space + 3],str[space + 5] ] - _'0')*[ 100,10,1 ]); 28389 ++versions[ver]; 28390 find(str,'_pre#')>=0?++prereleases; 28391 28392 ++ips; 28393 ); 28394 store([ips,gimp,krita,_8bf,paintdotnet,digikam,standalone,windows,linux,macos,bsd,unknown,prereleases], 28395 'features'); 28396 store(versions,'versions')" 28397 rm $features 28398 ips,gimp,krita,_8bf,paintdotnet,digikam,standalone,windows,linux,macos,bsd,unknown,prereleases={^} 28399 $versions 28400 a y 28401 28402 if $N>1 28403 e[] " > "$date": "\ 28404 ${_vt100_b}"Unique IPs"${_vt100_n}" = "$ips" (100%)," 28405 e[] " "\ 28406 ${_vt100_m}${_vt100_b}"GIMP"${_vt100_n}" = "$gimp" ("{_round($gimp/$ips*100,0.1)}"%), "\ 28407 ${_vt100_c}${_vt100_b}"Krita"${_vt100_n}" = "$krita" ("{_round($krita/$ips*100,0.1)}"%), "\ 28408 ${_vt100_g}${_vt100_b}"8bf"${_vt100_n}" = "$_8bf" ("{_round($_8bf/$ips*100,0.1)}"%), "\ 28409 ${_vt100_r}${_vt100_b}"Paint.NET"${_vt100_n}" = "$paintdotnet" ("{_round($paintdotnet/$ips*100,0.1)}"%), "\ 28410 ${_vt100_m}${_vt100_b}"Digikam"${_vt100_n}" = "$digikam" ("{_round($digikam/$ips*100,0.1)}"%), "\ 28411 ${_vt100_c}${_vt100_b}"Standalone"${_vt100_n}" = "$standalone" ("{_round($standalone/$ips*100,0.1)}"%)." 28412 e[] " "\ 28413 ${_vt100_r}${_vt100_b}"Windows"${_vt100_n}" = "$windows" ("{_round($windows/$ips*100,0.1)}"%), "\ 28414 ${_vt100_g}${_vt100_b}"Linux"${_vt100_n}" = "$linux" ("{_round($linux/$ips*100,0.1)}"%), "\ 28415 ${_vt100_m}${_vt100_b}"Mac OS"${_vt100_n}" = "$macos" ("{_round($macos/$ips*100,0.1)}"%), "\ 28416 ${_vt100_c}${_vt100_b}"BSD"${_vt100_n}" = "$bsd" ("{_round($bsd/$ips*100,0.1)}"%), "\ 28417 ${_vt100_c}${_vt100_b}"Unknown"${_vt100_n}" = "$unknown" ("{_round($unknown/$ips*100,0.1)}"%)." 28418 e[] " "\ 28419 ${_vt100_b}"Prereleases"${_vt100_n}" = "$prereleases" ("{_round($prereleases/$ips*100,0.1)}"%)." 28420 _ovh2stats_versions 28421 fi 28422 endl done 28423 + / $N round. 28424 +z. 0,0,12,0 ips,gimp,krita,_8bf,paintdotnet,digikam,standalone,windows,linux,macos,bsd,unknown,prereleases={^} rm. 28425 summary0,summary1="Total: ","Average: " 28426 e[] " > "${summary{$N>1}}\ 28427 ${_vt100_b}"Unique IPs"${_vt100_n}" = "$ips" (100%)," 28428 e[] " "\ 28429 ${_vt100_m}${_vt100_b}"GIMP"${_vt100_n}" = "$gimp" ("{_round($gimp/$ips*100,0.1)}"%), "\ 28430 ${_vt100_c}${_vt100_b}"Krita"${_vt100_n}" = "$krita" ("{_round($krita/$ips*100,0.1)}"%), "\ 28431 ${_vt100_g}${_vt100_b}"8bf"${_vt100_n}" = "$_8bf" ("{_round($_8bf/$ips*100,0.1)}"%), "\ 28432 ${_vt100_r}${_vt100_b}"Paint.NET"${_vt100_n}" = "$paintdotnet" ("{_round($paintdotnet/$ips*100,0.1)}"%), "\ 28433 ${_vt100_m}${_vt100_b}"Digikam"${_vt100_n}" = "$digikam" ("{_round($digikam/$ips*100,0.1)}"%), "\ 28434 ${_vt100_c}${_vt100_b}"Standalone"${_vt100_n}" = "$standalone" ("{_round($standalone/$ips*100,0.1)}"%)." 28435 e[] " "\ 28436 ${_vt100_r}${_vt100_b}"Windows"${_vt100_n}" = "$windows" ("{_round($windows/$ips*100,0.1)}"%), "\ 28437 ${_vt100_g}${_vt100_b}"Linux"${_vt100_n}" = "$linux" ("{_round($linux/$ips*100,0.1)}"%), "\ 28438 ${_vt100_m}${_vt100_b}"Mac OS"${_vt100_n}" = "$macos" ("{_round($macos/$ips*100,0.1)}"%), "\ 28439 ${_vt100_c}${_vt100_b}"BSD"${_vt100_n}" = "$bsd" ("{_round($bsd/$ips*100,0.1)}"%), "\ 28440 ${_vt100_c}${_vt100_b}"Unknown"${_vt100_n}" = "$unknown" ("{_round($unknown/$ips*100,0.1)}"%)." 28441 e[] " "\ 28442 ${_vt100_b}"Prereleases"${_vt100_n}" = "$prereleases" ("{_round($prereleases/$ips*100,0.1)}"%)." 28443 _ovh2stats_versions 28444 rm 28445 28446_ovh2stats_versions : 28447 v + +rows. 100% l. ips={is} 28448 +f x a y sort -,x eo0={min(9,find(crop(),0))} 28449 if $eo0 28450 str= v=0 c= 28451 for i($v,0)>0" && "$v<9 28452 str.=$c${_vt100_b}{i($v,1)}${_vt100_n}" ("{i($v,0)}": "{_round(i($v,0)/$ips*100,0.1)}"%)" 28453 v+=1 c=", " 28454 done 28455 e[] " "${_vt100_c}${_vt100_b}"Version"${_vt100_n}" = "$str".\n" 28456 fi 28457 rm 28458 endl 28459 28460#@cli padint : number,_size>0 28461#@cli : Return a integer with 'size' digits (eventually left-padded with '0'). 28462padint : check "isint($1)" skip ${2=4} 28463 u "" repeat $2 u ${}{int($1/10^$<)%10} done 28464 28465#@cli path_cache 28466#@cli : Return a path to store G'MIC data files for one user (whose value is OS-dependent). 28467path_cache : 28468 if !narg({'$_path_cache'}) 28469 _path_cache=$_path_rc 28470 if ['$GMIC_CACHE_PATH']!=0 _patch_cache=$GMIC_CACHE_PATH 28471 elif !${-is_windows} 28472 if isdir(['{/$HOME/.cache}']) _path_cache=$HOME/.cache/gmic/ 28473 elif ['$XDG_CACHE_HOME']!=0 _path_cache=$XDG_CACHE_HOME/gmic/ 28474 fi 28475 if !isdir('{/$_path_cache}') x "mkdir -p "$_path_cache fi 28476 fi 28477 fi 28478 u $_path_cache 28479 28480#@cli path_current 28481#@cli : Return current folder from where G'MIC has been run. 28482path_current : 28483 if !${-is_windows} 28484 filename=${-path_tmp}gmic_pwd 28485 l[] x "pwd > "$filename it $filename autocrop {'\n'} autocrop {'" "'} u {t}/ rm onfail u "./" endl 28486 else u "./" 28487 fi 28488 28489#@cli path_gimp 28490#@cli : Return a path to store GIMP configuration files for one user (whose value is OS-dependent). 28491path_gimp : 28492 if !narg({'$_path_gimp'}) 28493 if narg({'${GIMP2_DIRECTORY}'}) _path_gimp=${GIMP2_DIRECTORY} 28494 elif narg({'${USERPROFILE}'}) _path_gimp=${USERPROFILE} 28495 elif narg({'${HOME}'}) _path_gimp=${HOME} 28496 fi 28497 if ${-is_windows} sep={`92`} else sep=/ fi 28498 if isdir(['{/$_path_gimp${sep}AppData${sep}Roaming${sep}GIMP${sep}2.10}']) 28499 _path_gimp=$_path_gimp${sep}AppData${sep}Roaming${sep}GIMP${sep}2.10${sep} 28500 elif isdir(['{/$_path_gimp${sep}AppData${sep}Roaming${sep}GIMP${sep}2.8}']) 28501 _path_gimp=$_path_gimp${sep}AppData${sep}Roaming${sep}GIMP${sep}2.8${sep} 28502 elif isdir(['{/$_path_gimp${sep}.config${sep}GIMP${sep}2.10}']) 28503 _path_gimp=$_path_gimp${sep}.config${sep}GIMP${sep}2.10${sep} 28504 elif isdir(['{/$_path_gimp${sep}.gimp-2.8}']) 28505 _path_gimp=$_path_gimp${sep}.gimp-2.8${sep} 28506 elif isdir(['{/$_path_gimp${sep}.gimp-2.6}']) 28507 _path_gimp=$_path_gimp${sep}.gimp-2.6${sep} 28508 else 28509 _path_gimp=${-path_tmp} 28510 fi 28511 fi 28512 u $_path_gimp 28513 28514#@cli path_tmp 28515#@cli : Return a path to store temporary files (whose value is OS-dependent). 28516path_tmp : 28517 if !narg({'$_path_tmp'}) 28518 if narg({'${TMP}'}) _path_tmp=${TMP} 28519 elif narg({'${TEMP}'}) _path_tmp=${TEMP} 28520 elif narg({'${TMPDIR}'}) _path_tmp=${TMPDIR} 28521 elif narg({'${HOME}'}) _path_tmp="/tmp" 28522 fi 28523 if ${-is_windows} _path_tmp=$_path_tmp{`92`} else _path_tmp=$_path_tmp/ fi 28524 fi 28525 u $_path_tmp 28526 28527#@cli remove_copymark : "image_name" 28528#@cli : Remove copy mark from names of selected images. 28529remove_copymark : 28530 u {`"name = ['$1']; 28531 i = find(name,'_c'); 28532 i>=0 && i<size(name) - 2 && (c=name[i+2])>=_'1' && c<=_'9'?( 28533 ext = ['"{$>,x}"']; 28534 size(ext)?copy(name[i],[_'.',ext,0]):(name[i]=0); 28535 ); name"`} 28536 28537# render_donations: Parse the PayPal .CSV file and generate 'latest-months' donation gfx. 28538# $1 = filename.csv 28539# $2 = number of latest months. 28540render_donations : skip "${1="$HOME"/work/src/private_tschumperle/gmic_donations.csv}",${2=0} 28541 use_vt100 28542 nb_months={$2?$2:4} 28543 l[] 28544 # Parse CSV data. 28545 "$1" 28546 eur2usd={1/0.7988} # Change rate from EUR to USD (Paypal conversion rate). 28547 nb_entries={h} 28548 repeat $nb_entries,e 28549 date_$e={`I(0,$e)`} 28550 name_$e={`I(1,$e)`} 28551 type_$e={`I(2,$e)`} 28552 currency_$e={`lowercase(I(3,$e))`} 28553 donation_$e={{`I(4,$e)`}} 28554 charge_paypal_$e={{`I(5,$e)`}} 28555 charge_lila_$e={{`I(6,$e)`}} 28556 mail_$e={`I(7,$e)`} 28557 message_$e={`I(8,$e)`} 28558 28559 # Deduced values. 28560 l[] 28561 ('${date_$e}') s -,{'/'} day_$e,month_$e,year_$e={0,t},{1,t},{2,t} rm 28562 edate_$e={${day_$e}+100*(${month_$e}+100*${year_$e})} 28563 endl 28564 donation_charged_$e={${donation_$e}+${charge_paypal_$e}+${charge_lila_$e}} 28565 28566 if '${currency_$e}'=='eur' 28567 donation_eur_$e=${donation_$e} 28568 donation_charged_eur_$e=${donation_charged_$e} 28569 donation_usd_$e={${donation_$e}*$eur2usd} 28570 donation_charged_usd_$e={${donation_charged_$e}*$eur2usd} 28571 else 28572 donation_usd_$e=${donation_$e} 28573 donation_charged_usd_$e=${donation_charged_$e} 28574 donation_eur_$e={${donation_$e}/$eur2usd} 28575 donation_charged_eur_$e={${donation_charged_$e}/$eur2usd} 28576 fi 28577 28578 # Print infos. 28579 if ${donation_$e}>=15 col=$_vt100_r else col= fi 28580 e[] "- ["$_vt100_c$_vt100_b"#"$e$_vt100_n" - "$_vt100_c${date_$e}$_vt100_n"] "\ 28581 $col$_vt100_b{_${donation_$e}}" "${currency_$e}$_vt100_n\ 28582 " (paypal: "{_${charge_paypal_$e}}" "${currency_$e},\ 28583 " lila: "{_${charge_lila_$e}}" "${currency_$e}" ->"\ 28584 " "{_${donation_charged_$e}}" "${currency_$e}" ="\ 28585 " "{_${donation_charged_eur_$e}}" eur),"\ 28586 " from "${name_$e}" ("${mail_$e}") : '"$_vt100_b${message_$e}$_vt100_n"'" 28587 done 28588 rm 28589 28590 # Compute image for donations of the last months. 28591 e[] "" 28592 all_eur,all_usd,all_charged_eur,all_charged_usd,asep_eur,asep_usd= 28593 repeat $nb_months 28594 edate={y=date(0);m=date(1)-1-$>;while(m<=0,--y;m+=12);100*y+m} 28595 s_month=${"arg "$edate%100",January,February,March,April,May,June,July,August,\ 28596 September,October,November,December"} 28597 s_year={int($edate/100)} 28598 28599 month_eur,month_charged_eur,month_usd,month_charged_usd,msep_eur,msep_usd= 28600 nb_sponsors=0 28601 repeat $nb_entries,e if $edate==int(${edate_$e}/100) 28602 currency=${currency_$e} 28603 val_eur=${donation_eur_$e} 28604 val_charged_eur=${donation_charged_eur_$e} 28605 val_usd=${donation_usd_$e} 28606 val_charged_usd=${donation_charged_usd_$e} 28607 nb_sponsors+=1 28608 28609 if '${currency_$e}'=='eur' 28610 all_eur.=$asep_eur$val_eur 28611 all_charged_eur.=$asep_eur$val_charged_eur 28612 month_eur.=$msep_eur$val_eur 28613 month_charged_eur.=$msep_eur$val_charged_eur 28614 asep_eur=, msep_eur=, 28615 else 28616 all_usd.=$asep_usd$val_usd 28617 all_charged_usd.=$asep_usd$val_charged_usd 28618 month_usd.=$msep_usd$val_usd 28619 month_charged_usd.=$msep_usd$val_charged_usd 28620 asep_usd=, msep_usd=, 28621 fi 28622 fi done 28623 28624 month_sum_eur={sum(0$month_eur)+sum(0$month_usd)/$eur2usd} 28625 month_sum_charged_eur={sum(0$month_charged_eur)+sum(0$month_charged_usd)/$eur2usd} 28626 28627 e[] "* "$_vt100_c$_vt100_b$s_month" "$s_year": "$_vt100_n\ 28628 $_vt100_b{_$month_sum_eur}" eur"$_vt100_n" (charged: "{_$month_sum_charged_eur}" eur)"\ 28629 " = "{_sum(0$month_eur)}" eur"$_vt100_n" (charged: "{_sum(0$month_charged_eur)}" eur)"\ 28630 " + "{_sum(0$month_usd)}" usd (charged: "{_sum(0$month_charged_usd)}" usd)" 28631 28632 600,30,1,3,'x<$month_sum_eur?[139,181,173]+(y>h/2?0:40):[220,230,240]' r. 500,30,1,3 c. 0,255 28633 shape_circle 24 s. x,2 s[-2,-1] y,2 28634 ri[-4] [-5],0,1,0,0 ri[-3] [-5],0,1,0,1 ri[-2] [-5],0,1,1,0 ri[-1] [-5],0,1,1,1 min[-4--1] 28635 channels. 0 *.. . *. 255 a[-2,-1] c 28636 r. {[w,h]+4},1,100%,0,0,0.5,0.5 28637 sh. 100% dilate_circ. 3 b. 1 rm. 28638 28639 t. $s_month" "$s_year,0.02~,0.5~,24,0.5,0,0,0,255 28640 t. {_round($month_sum_eur)}" \37 = "{_round($month_sum_eur*$eur2usd)}" $",0.5~,0.5~,24,1,0,0,0,255 28641 t. $nb_sponsors" sponsor"${"if "$nb_sponsors"!=1 u s else u \"\" fi"},0.97~,0.5~,24,0.5,0,0,0,255 28642 done 28643 rv 28644 28645 all_max={max($all_eur,[$all_usd]/$eur2usd)} 28646 all_min={min($all_eur,[$all_usd]/$eur2usd)} 28647 all_sum_eur={sum($all_eur)} 28648 all_sum_usd={sum($all_usd)} 28649 all_sum_charged_eur={sum($all_charged_eur)} 28650 all_sum_charged_usd={sum($all_charged_usd)} 28651 all_avg={avg($all_eur,[$all_usd]/$eur2usd)} 28652 all_med={med($all_eur,[$all_usd]/$eur2usd)} 28653 28654 0 t. "Avg: "{_round($all_avg,0.1)}"\37 / "\ 28655 "Med: "{_round($all_med,0.1)}"\37 / "\ 28656 "Min: "{_round($all_min,0.1)}"\37 / "\ 28657 "Max: "{_round($all_max,0.1)}"\37",0,0,24,1,1 28658 *. 200 i[-2] 100%,100%,1,3 a[-2,-1] c 28659 28660 rows -5,100% a y,0.5 r2dx 480 28661 if $2==0 o $HOME/work/src/gmic/html/img/donations_latest_months.png fi 28662 endl 28663 28664 total_eur={$all_sum_eur+$all_sum_usd/$eur2usd} 28665 total_charged_eur={$all_sum_charged_eur+$all_sum_charged_usd/$eur2usd} 28666 e[] "\n==> "$_vt100_c${_vt100_b}"TOTAL : "$_vt100_n\ 28667 $_vt100_b{_floor($total_eur)}" eur"$_vt100_n" (charged : "{_floor($total_charged_eur)}" eur)"\ 28668 " = "{_floor($all_sum_eur)}" eur (charged: "{_floor($all_sum_charged_eur)}" eur)"\ 28669 " + "{_floor($all_sum_usd)}" usd (charged: "{_floor($all_sum_charged_usd)}" usd)\n" 28670 28671 # Generate report image for Twitter. 28672 sp gmicky,{h} 28673 l[-2,-1] 28674 rgb={I(w-1)} to_rgba rv 28675 frame 10,10,0,0,0,0 28676 drgba $rgb a x 28677 shape_heart 82 +r. 100%,100%,1,3 hsv2rgb. rv[-2,-1] *. 255 a[-2,-1] c 28678 r. ..,..,1,100%,0,0,0.23,0.15 drop_shadow. 3,3,2,0,0 28679 blend alpha,0.7 r2dx 500 28680 if $2==0 o $HOME/Desktop/donations_latest_months.jpg,85 rm return fi 28681 endl 28682 28683 # Generate coin graphics. 28684 l[] 28685 $HOME/work/src/gmic/html/img/icon_coin.png 28686 N=0 28687 text$N,r$N,g$N,b$N,file$N="2 \37",32,48,32,"don_2eur.png" N+=1 28688 text$N,r$N,g$N,b$N,file$N="5 \37",200,200,200,"don_5eur.png" N+=1 28689 text$N,r$N,g$N,b$N,file$N="10 \37",190,100,100,"don_10eur.png" N+=1 28690 text$N,r$N,g$N,b$N,file$N="+ \37",255,128,0,"don_moreeur.png" N+=1 28691 text$N,r$N,g$N,b$N,file$N="2 $",32,48,32,"don_2usd.png" N+=1 28692 text$N,r$N,g$N,b$N,file$N="5 $",200,200,200,"don_5usd.png" N+=1 28693 text$N,r$N,g$N,b$N,file$N="10 $",190,100,100,"don_10usd.png" N+=1 28694 text$N,r$N,g$N,b$N,file$N="+ $",255,128,0,"don_moreusd.png" N+=1 28695 repeat $N +l[0] 28696 frame. 10,10,0,0,0,0 28697 sh. 0,2 28698 (${r$>}^${g$>}^${b$>}) rgb2hsl[-2,-1] H,S={[R,G]} rm. 28699 l. s c -[0] {ia#0-$H} %[0] 360 -[1] {ia#1-$S} +[2] 0.1 /[1] 2 c[1,2] 0,1 a c endl 28700 hsl2rgb. rm. 28701 sh. 100% dilate_circ. 10 rm. 28702 28703 100%,100% t. ${text$>},0.5~,0.5~,45%,1,255 dilate_circ. 10 +dilate_circ. 15 to_rgb.. a[-2,-1] c 28704 blend[-2,-1] alpha drop_shadow. 1,1 r2dx. 48 frame 10,5,0,0,0,0 28705 outfile=$HOME/work/src/gmic/html/img/${file$>} 28706 if !isfile('$outfile') o. $outfile fi 28707 rm. 28708 endl done 28709 rm[0] 28710 endl 28711 28712#@cli reset 28713#@cli : Reset global parameters of the interpreter environment. 28714reset : 28715 e[^-1] "Reset global parameters of the interpreter environment." 28716 db3d m3d md3d f3d l3d sl3d ss3d 28717 28718#@cli rgb 28719#@cli : Return a random int-valued RGB color. 28720rgb : 28721 u {round(u(255))},{round(u(255))},{round(u(255))} 28722 28723RGB : rgb 28724 28725#@cli rgba 28726#@cli : Return a random int-valued RGBA color. 28727rgba : 28728 u {round(u(255))},{round(u(255))},{round(u(255))},{round(u(255))} 28729 28730RGBA : rgba 28731 28732#@cli shell_cols 28733#@cli : Return the estimated number of columns of the current shell. 28734shell_cols : 28735 if ${-is_windows} u 80 28736 else 28737 file_rand filename=${} 28738 l[] cols=80 x "tput cols > "$filename it $filename if isint({t}) cols={{t}} fi rm onfail cols=80 rm endl 28739 delete $filename 28740 u $cols 28741 fi 28742 28743#@cli size_value 28744#@cli : Return the size (in bytes) of an image value. 28745size_value : 28746 u {str=['$_pixeltype'];echo(str);str=='float'?4:str=='double'?8:0} 28747 28748 28749#@cli std_noise 28750#@cli : Return the estimated noise standard deviation of the last selected image. 28751std_noise : 28752 if $! +laplacian. -. {ic} abs. u {1.4826*ic/sqrt(d==1?20:42)} rm. else u 0 fi 28753 28754#@cli str : string 28755#@cli : Print specified string into its binary, octal, decimal and hexadecimal representations. 28756str : skip $1 28757 dec={'$*'} 28758 e[^-1] "Convert string '$*' to binary '"${dec2bin\ $dec}"', octal '"${dec2oct\ $dec}"', decimal '"$dec"' and 28759 hexadecimal '"${dec2hex\ $dec}"'." 28760 28761#@cli str2hex : "string" 28762#@cli : Convert specified string argument into a sequence of hexadecimal values (returned as a string). 28763#@cli : See also: ''hex2str''. 28764#@cli : $ hex=${"str2hex \"Hello my friends\""} echo $hex 28765#@cli : \n~~~\n[gmic]-0./ Start G'MIC interpreter.\n[gmic]-0./ 48656c6c6f206d7920667269656e6473\n\ 28766# [gmic]-0./ End G'MIC interpreter.\n~~~\n 28767str2hex : 28768 ('"$*"') y. r. 2,100% f. 'v=if(x,i%16,int(i/16));if(v<=9,48+v,87+v)' u {t} rm. 28769 28770#@cli strcapitalize : string 28771#@cli : Capitalize specified string. 28772strcapitalize : 28773 l[] ('{/"$1"}') 28774 f "(i<=_' ' || i==_'_') && i!=_'\n'?_' ':i" # Replace blank characters and underscores 28775 f "> 28776 t(s) = ( unref(ss); const ss = size(s); lowercase(crop(x,ss))!=s || j[ss]!=_' '); 28777 !x || (p=j[-1])==_'.' || p==_':' || p==_';' || p==_'\"' || (find(#0,_' ',x)<0 && p==_' ') || 28778 (p==_' ' || p==_'-') && 28779 t('a') && t('an') && t('and') && t('as') && t('at') && t('but') && t('by') && t('for') && t('from') && 28780 t('in') && t('into') && t('like') && t('near') && t('nor') && t('of') && t('off') && t('on') && 28781 t('onto') && t('or') && t('over') && t('past') && t('per') && t('than') && t('the') && t('to') && 28782 t('up') && t('upon') && t('via') && t('with')?uppercase(i):i" 28783 u {t} rm endl 28784 28785#@cli strcontains : string1,string2 28786#@cli : Return 1 if the first string contains the second one. 28787strcontains : 28788 u {"find(['$1'],['$2'])>=0"} 28789 28790#@cli strlen : string1 28791#@cli : Return the length of specified string argument. 28792strlen : skip "${1=}" 28793 u {narg({'"$1"'})} 28794 28795#@cli strreplace : string,search,replace 28796#@cli : Search and replace substrings in an input string. 28797strreplace : skip "${3=}" 28798 if narg("$3") 28799 ls=${strlen\ "$2"} 28800 lr={${strlen\ "$3"}-1} 28801 l[] ('"$1"':y) s +,{'"$2"'} s y,-$ls 28802 repeat $! if [{$>,^}]==['"$2"'] rows[$>] 0,$lr f[$>] {'"$3"'} fi done 28803 a y u {t} rm endl 28804 else 28805 l[] ('"$1"') s -,{'"$2"'} a y u {t} rm endl 28806 fi 28807 28808#@cli strlowercase : string 28809#@cli : Return a lower-case version of the specified string. 28810strlowercase : 28811 ('"$*"') u {`lowercase([{^}])`} rm. 28812 28813#@cli struppercase : string 28814#@cli : Return an upper-case version of the specified string. 28815struppercase : 28816 ('"$*"') u {`uppercase([{^}])`} rm. 28817 28818#@cli strvar : "string" 28819#@cli : Return a simplified version of the specified string, that can be used as a variable name. 28820#@cli : (version that creates a lowercase result, no longer than 128 chars). 28821strvar : 28822 _strvar_fn="lowercase(c)" _strvar "$*" 28823 28824#@cli strcasevar : "string" 28825#@cli : Return a simplified version of the specified string, that can be used as a variable name. 28826#@cli : (version that keeps original case of specified string, no longer than 128 chars). 28827strcasevar : 28828 _strvar_fn="c" _strvar "$*" 28829 28830_strvar : 28831 l[] 28832 ('"$*"':y) f. "c = i; inrange(c,_'0',_'9') || inrange(c,_'a',_'z') || 28833 inrange(c,_'A',_'Z') || c==_'_'?"$_strvar_fn":_'_'" 28834 rows. 0,{min(h,128)-1} autocrop. {'_'} 28835 if inrange(i,_'0',_'9') i.. ('_') a[-2,-1] y fi 28836 do h={h} replace_str. "__","_" while h!=$h 28837 u {t} rm 28838 endl 28839 28840#@cli strver : _version 28841#@cli : Return the specified version number of the G'MIC interpreter, as a string. 28842#@cli : Default value: 'version=$_version'. 28843strver : skip "${1=}" 28844 if isnum("$1")" && $1>0" ver="$1" else ver=$_version noarg fi 28845 ('$ver') r. {2*w-1} f. 'if(x%2,_'.',i)' u {t} rm. 28846 28847#@cli tic 28848#@cli : Initialize tic-toc timer. 28849#@cli : Use it in conjunction with 'toc'. 28850tic : 28851 e[^-1] "Initialize timer." 28852 if !narg($_ticpos) _ticpos=0 fi _tic$_ticpos=$| _ticpos+=1 28853 28854#@cli toc 28855#@cli : Display elapsed time of the tic-toc timer since the last call to 'tic'. 28856#@cli : This command returns the elapsed time in the status value. 28857#@cli : Use it in conjunction with 'tic'. 28858toc : 28859 v=$^ _ticpos-=1 u {_$|-${_tic$_ticpos}} 28860 v 0 e[^-1] "Elapsed time: "${}" s". v $v 28861 28862#@cli to_clutname : "string" 28863#@cli : Return simplified name that can be used as a CLUT name, from specified input string. 28864to_clutname : 28865 0 nm. "$1" nm={b} rm. 28866 u {`"ss = lowercase([['"{/$nm}"'],0]); 28867 const N = 2*size(ss); 28868 sd = vectorN(); 28869 for (ps = pd = 0, ss[ps], ++ps, 28870 ss[ps]<=_' '?(sd[pd++] = _'_'): 28871 (ss[ps]==_'(' || ss[ps]==_')' || 28872 ss[ps]==_'{' || ss[ps]==_'}' || 28873 ss[ps]==_'[' || ss[ps]==_']' || 28874 ss[ps]==_'\'' || ss[ps]==_'\"')?0: 28875 (ps && ss[ps]>=_'0' && ss[ps]<=_'9' && ss[ps-1]>=_'a' && ss[ps-1]<=_'z')?(sd[pd++] = _'_'; sd[pd++] = ss[ps]): 28876 (sd[pd++] = ss[ps]); 28877 ); sd[pd] = 0; sd"`} 28878 28879#@cli uchar2base64 : _encoding={ 0=base64 | 1=base64url } 28880#@cli : Encode the values of the latest of the selected images as a base64-encoded string. 28881#@cli : The string can be decoded using command 'base642uchar'. 28882#@cli : Selected images must have values that are integers in [0,255]. 28883#@cli : Default values: 'encoding=0'. 28884uchar2base64 : skip "${1=0}" 28885 if isnum("$1") encoding=$1 else encoding=0 noarg fi 28886 {ceil(whds*4/3)+([0,2,1])[whds%3]} 28887 eval " 28888 hash = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 28889 "$encoding"?(hash[62] = _'-'; hash[63] = _'_'); 28890 od = ov = n = 0; 28891 for (os = 0, os<whds#-2, 28892 v = i[#-2,os++]&255; 28893 n==0?(i[#-1,od++] = hash[v>>2]; ov = v; n = 1): 28894 n==1?(i[#-1,od++] = hash[((ov&3)<<4) | (v>>4)]; ov = v; n = 2): 28895 (i[#-1,od++] = hash[((ov&15)<<2) | (v>>6)]; i[#-1,od++] = hash[v&63]; n = 0); 28896 ); 28897 n==1?(i[#-1,od++] = hash[((ov&3)<<4)]; copy(i[#-1,od],_'=',2,1,0); od+=2): 28898 n==2?(i[#-1,od++] = hash[((ov&15)<<2)]; i[#-1,od++] = _'='); 28899 " 28900 u {t} rm. 28901 28902#------------------------------------- 28903# 28904#@cli :: Other Interactive Commands 28905# 28906#------------------------------------- 28907 28908#@cli demos : _run_in_parallel={ 0=no | 1=yes | 2=auto } 28909#@cli : Show a menu to select and view all G'MIC interactive demos. 28910demos : check "isint(${1=2}) && $1>=0 && $1<=2" check_display $0 28911 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 28912 strver=${-strver} 28913 if $_prerelease strver=${strver}_pre#$_prerelease fi 28914 e[] "\n 28915------ "${g}"G\47MIC demos"$n" ------------------\n 28916----\n 28917---- "${c}"Mouse button"$n" to select a demo.\n 28918---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 28919---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 28920---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 28921----\n 28922-------------------------------------" 28923 l[] 28924 entries="2048 game","Blobs Editor","Bouncing Balls","Connect Four","Fire Effect","Fireworks","Fish-Eye Effect",\ 28925 "Fourier Filtering","Tower of Hano\357","Histogram Demo","Hough Transform","Jawbreaker","Virtual Landscape",\ 28926 "The Game of Life","Light Effect","Mandelbrot Explorer","3D Metaballs","Minesweeper","Minimal Path",\ 28927 "Pacman","Paint","Plasma Effect","RGB Quantization","3D Reflection","3D Rubber Object","Shade Bobs",\ 28928 "Spline Editor","3D Starfield","Tetris","Tic-Tac-Toe","Image Waves","Fractal Whirls","Color Curves" 28929 commands=x_2048,x_blobs,x_bouncing,x_connect4,x_fire,x_fireworks,x_fisheye,\ 28930 x_fourier,x_hanoi,x_histogram,x_hough,x_jawbreaker,x_landscape,x_life,\ 28931 x_light,x_mandelbrot,x_metaballs3d,x_minesweeper,x_minimal_path,x_pacman,x_paint,\ 28932 x_plasma,x_quantize_rgb,x_reflection3d,x_rubber3d,x_shadebobs,x_spline,x_starfield3d,\ 28933 x_tetris,x_tictactoe,x_waves,x_whirl,_demo_color_curves 28934 nb_entries={narg($entries)} 28935 parallel_mode={1-if($1!=2,$1,$_cpus>=2)} 28936 strver=${-strver} 28937 if $_prerelease strver.=_pre#$_prerelease fi 28938 28939 # Generate menu graphics. 28940 l[] 28941 repeat $nb_entries 28942 arg 1+$>,$entries entry=${} 28943 0 t. $entry,0,0,24,1,1 28944 done 28945 r ${-max_wh},1,1,0,0,0.5,0.5 28946 frame 12,6,0 a z 28947 +n[0] 0,255 28948 +shift[0] 1,3,0,0 max[0,-1] 28949 +f[0] z+1 28950 1,1,100%,3,u(128,255) r. 1,[0],[0],3 *. 'y/(h-1)' r. [0],[0],[0],3,3 28951 28952 100%,100%,1,1,"x = min(x,w-1-x); y = min(y,h-1-y); (x*y/wh)^0.7>0.01" 28953 +dilate. 3 xor.. . 28954 +[0] .. 28955 *.. 100 +[1,-2] 28956 *[2,3] . 28957 rm. 28958 frame 4,4,0 28959 a c s z 28960 append_tiles 3 s c 28961 to_rgb[1] a[3-5] c 28962 28963 0 t. "G\'MIC demos",2,2,32,1,1,1,1 28964 if $_prerelease 0 t. "Version:\n"$strver,40,1,18,1,1,1,1 rows. 2,100% 28965 else 0 t. "Version: "$strver,40,1,18,1,1,1,1 rows. -2,100% 28966 fi 28967 a[-2,-1] x,0.5 28968 b. 0.5 n. 0,1 28969 (32;255^255;255^0;0) r. ..,..,1,3,3 *[-2,-1] round. 1,-1 +!=. 0 channels. 1 28970 28971 s=8 28972 r[^-2,-1] 100%,{h+h#0+2*$s+6},1,100%,0,0,0,1 28973 rectangle[0] 0,$s,100%,{$s+6+h-1},1,0.6 28974 rectangle[1] 0,$s,100%,{$s+6+h-1},1,120,120,32 28975 j[0] .,{(w#0-w)/2},{$s+3},0,0,-1 28976 j[1] ..,{(w#0-w)/2},{$s+3},0,0,1,. rm[-2,-1] 28977 c[0] 0,1 28978 nm menu_opac,menu_fgcol,menu_ind,menu_bgcol 28979 endl 28980 28981 # Generate 3D cursors. 28982 arrow3d 20,20,0,0,0,0,20%,40%,40% col3d. 255,128,0 nm. cursor3d 28983 28984 # Generate 3D background object. 28985 l[] 28986 n=16 28987 chromeball64x64[] 200,100,64 n. 0,230 s. c,-3 28988 rgb2hsv.. r.. 100%,100%,$n,3 f.. "[z*360/d,G,B]" hsv2rgb.. 28989 N={6*$n} P={2*$N-1} 28990 i[0] ('CImg3d') i[1] ($N,$P) i[2] 3,$N # Header, points 28991 i[3] 2,$N,1,1,"x?y:1" i[4] 3,{$N-1},1,1,"x==0?2:x==1?y:y+1" y[3,4] a[3,4] y # Primitives 28992 l[4] # Colors 28993 s z i[0--2] (-128,{w},{h},3) 4,{$N-$n},1,1,'x==0?-128:x==1?y%$n:0' # Colors 28994 3,{$P-$N},1,1,200 y a y 28995 endl 28996 l[5] # Opacities 28997 n 0,0.5 i[0] (-128,{w},{h},1) 4,{$N-1},1,1,-128,0,0,0 28998 1,{$P-$N},1,1,0.25 y a y 28999 endl 29000 y a y 29001 nm background3d 29002 endl 29003 29004 # Generate background. 29005 {menu_fgcol,[w,h]},1,3 +plasma. 1,1,5 n. 0,230 water. 100 29006 (0.1;0.03^0;0.1^0.2;0.1) ri. ..,3 *[-2,-1] 29007 (0;1) r. ..,..,1,1,3 pow. 1.5 n. 0.2,1.15 *[-2,-1] n. 0,128 29008 nm. background 29009 w. -1,-1,0,"[G'MIC - "$strver"]" cursor 0 w[] -1,-1,0,0,{([{*,u,v}]-[{*,w,h}])/2} 29010 29011 # Enter event loop. 29012 omb,ind_clicked,cfx,cfy,cfz,alpha=0 29013 nfx,nfy,nfz={[g,g,g]} time0={$|-4} 29014 do 29015 mx,my,mb={menu_fgcol,x={*,x};y={*,y};[x<0?-1:x*(w-1)/({*,w}-1),y<0?-1:y*(h-1)/({*,h}-1),{*,b}]} 29016 ind={menu_ind,i($mx,$my)} 29017 if $mb" && "!$ind_clicked ind_clicked=$ind fi 29018 29019 # Render current view. 29020 [background] 29021 29022 3,$N,1,1,"const t = 0.8*"$|"; const a = "$alpha"; const oma = 1 - a; 29023 x==0?oma*cos("$cfx"*y + t) + a*cos("$nfx"*y + t): 29024 x==1?oma*sin("$cfy"*y + t) + a*sin("$nfy"*y + t): 29025 oma*sin("$cfz"*y + t) + a*sin("$nfz"*y + t)" 29026 y. 29027 j[background3d] .,0,8 rm. 29028 +r3d[background3d] 1,2,3,{20*$|} *3d. {menu_fgcol,[w,h]/2-30},300 +3d. 0,0,300 29029 j3d.. .,50%,50%,0,1,1,0,0,200 rm. 29030 if $|-$time0>5 alpha+=0.02 fi 29031 if $alpha>1 alpha-=1 cfx,cfy,cfz=$nfx,$nfy,$nfz nfx,nfy,nfz={[g,g,g]} time0={$|-u*3} fi 29032 29033 if $ind>0 +==[menu_ind] # Draw selection background 29034 $ind j.. [menu_bgcol],0,0,0,0,{$mb" && "$ind_clicked==$ind?0.6:1},. rm. 29035 fi 29036 j. [menu_fgcol],0,0,0,0,1,[menu_opac] 29037 29038 if $mx>0 29039 +r3d[cursor3d] 1,1.3,0.6,{50*cos($|)} 29040 j3d.. .,$mx,$my,0,1,4,0,0,800,{-2,[w,h]/2},-1000,0.7 rm. 29041 fi 29042 29043 w. -1,-1,0 29044 if {*,CTRLLEFT}" && "{*,D} w. 150%,150% elif {*,CTRLLEFT}" && "{*,C} w. 100%,100% fi 29045 rm. 29046 29047 # Manage user selection. 29048 if !$mb" && "$omb" && "$ind_clicked" && "$ind_clicked==$ind 29049 m "com : v 1 "${arg\ $ind,$commands} parallel $parallel_mode,"l[] com rm endl" um com 29050 elif !$mb ind_clicked=0 29051 fi 29052 omb=$mb 29053 29054 wait 20 29055 while {*}" && "!{*,ESC}" && "!{*,Q} 29056 rm w 0 endl v 0 e[] "" 29057 29058_demo_color_curves : 29059 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29060 if !narg($__demo_color_curve) 29061 e[] "\n 29062------ "${g}"Color curves"$n" ----------------------------------------------------------------------------\n 29063----\n 29064---- "${c}"Left mouse button"$n" on a curve creates a new control point (or moves an existing one).\n 29065---- "${c}"Right mouse button"$n" on a control point deletes it.\n 29066---- "${c}"Left mouse button"$n" on the main image window shows the initial image until button is released.\n 29067---- "${c}"Right mouse button"$n" on the main image window adds a keypoint to all curves from picked color.\n 29068---- Key '"${c}"R"$n"' on a curve resets it.\n 29069---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 29070---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 29071---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 29072---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' close the current window.\n 29073----\n 29074------------------------------------------------------------------------------------------------" 29075 __demo_color_curve=1 l[] do rm sp ? while s!=3 endl x_color_curves rgb __demo_color_curve= 29076 else 29077 e[] "\n 29078------ "${g}"Color curves"$n" ----------------------------------------------------------------------------\n 29079----\n 29080---- Only "${c}"one session"$n" allowed at the same time !\n 29081----\n 29082------------------------------------------------------------------------------------------------" 29083 fi 29084 29085#@cli tixy : "expression" 29086#@cli : Animate specified mathematical expression with a 16x16 grid of circles, \ 29087# using the rules described at <https://tixy.land>. 29088tixy : skip "${1=sin(t-sqrt((x-8)^2+(y-8)^2))}" check_display $0 29089 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r b=$_vt100_b 29090 if narg("$*") expr="$*" else expr="$1" fi 29091 l[] ('$expr') 29092 replace_str "%","%25" 29093 replace_str "&","%26" 29094 replace_str "(","%28" 29095 replace_str ")","%29" 29096 replace_str "+","%2B" 29097 replace_str ",","%2C" 29098 replace_str ";","%2C" 29099 replace_str "/","%2F" 29100 replace_str "[","%5B" 29101 replace_str "]","%5D" 29102 replace_str "|","%7C" 29103 replace_str "^","**" 29104 replace_str " ","+" 29105 url=https://tixy.land?code={t} 29106 rm endl 29107 29108 e[] "\n 29109------ "${g}"tixy"$n" ------------------------------------------------------------------------------------\n 29110----\n 29111---- tixy - creative code golfing: "${g}"https://tixy.land"$n"\n 29112----\n 29113---- "$r${b}"Expression:"$n" "$expr"\n 29114----\n 29115---- "$r${b}"Corresponding URL:"$n" "$url"\n 29116----\n 29117---- "$r${b}"Rules:"$n"\n 29118---- . Specified expression depends on 4 variables "${g}"(t,i,x,y)"$n" and is rendered as an animation.\n 29119---- . Variables "${g}"x"$n" and "${g}"y"$n", in range "${c}"[0,15]"$n", are the spatial position of each dot.\n 29120---- . Variable "${g}"i"$n", in range "${c}"[0,255]"$n", is the dot index, i.e. "${c}"i = x + 16*y"$n".\n 29121---- . Variable "${g}"t>=0"$n" is the (decimal) number of elapsed seconds.\n 29122---- . Specified expression "${g}"func(t,i,x,y)"$n" must return a complex value "${c}"c"$n".\n 29123---- . Variable "${g}"z"$n" can be used as a shortcut for "${g}"[ x,y ]"$n".\n 29124---- . Variable "${g}"j"$n" is the complex imaginary number "${g}"[ 0,1 ]"$n".\n 29125---- . "${c}"cabs(c)"$n" in "${g}"[0,1]"$n" determines the radius of each dot at "${c}"(x,y)"$n".\n 29126---- . "${c}"carg(c)"$n" in "${g}"[-pi,pi]"$n" determine the color of each dot at "${c}"(x,y)"$n".\n 29127----\n 29128---- Key '"${c}"SPACE"$n"' starts/stops recording animation as video file '"${c}"out.mp4"$n"'.\n 29129---- Key '"${c}"ENTER"$n"' takes a screenshot of current image.\n 29130---- Key '"${c}"A"$n"' enables/disables anti-aliasing.\n 29131---- Key '"${c}"F"$n"' displays formula on the image.\n 29132---- Key '"${c}"R"$n"' resets time.\n 29133---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 29134---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 29135---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 29136---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' close the current window.\n 29137------------------------------------------------------------------------------------------------" 29138 w[] 400,400,0,"[G'MIC] tixy: "$expr 29139 t0=$| is_recording=0 is_antialias=1 is_screenshot=0 is_formula=0 nb_frames=0 29140 360,1,1,3,[x,abs(cos(x/w*pi))^0.5,1] hsv2rgb. shift. -180,0,0,0,2 nm. cmap 29141 strvar $expr basename=${} 29142 29143 do 29144 29145 # Manage user-events. 29146 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 29147 if $is_ctrl" && "{*,-D} w[] {1.25*[{*,w,h}]} rmn formula,mformula 29148 elif $is_ctrl" && "{*,-C} w[] {0.8*[{*,w,h}]} rmn formula,mformula 29149 elif $is_ctrl" && "{*,R} w[] 400,400 rmn formula,mformula 29150 elif {*,-A} is_antialias={!$is_antialias} 29151 elif {*,-F} is_formula={!$is_formula} 29152 elif {*,R} t0=$| 29153 elif {*,-SPACE} 29154 if $is_recording o[] $basename.mp4,15,0,0 nb_frames=0 29155 else t0=$| fi 29156 is_recording={!$is_recording} 29157 elif {*,-ENTER} is_screenshot=1 29158 fi 29159 29160 # Render animation frame. 29161 m={min({*,w,h})} _is_antialias={$is_antialias" && "$m<512} 29162 {m=$m*($_is_antialias?2:1);[m,m]},1,3 29163 29164 16,16,1,1,">begin( 29165 const b = w#-1/16; 29166 const t = "$|-$t0"; 29167 j = [ 0,1 ]; 29168 ); 29169 i = x + 16*y; 29170 ref([ x,y ],z); 29171 val = ("$expr"); 29172 n = cabs(val); 29173 r = floor(0.48*b*cut(n,0,1)); 29174 a = (360+carg(val)*180/pi)%360; 29175 c = I[#"$cmap",a]; 29176 r>1?ellipse(#-1,b*(x + 0.5),b*(y + 0.5),r,r,0,1,c): 29177 r>0?ellipse(#-1,b*(x + 0.5),b*(y + 0.5),1,1,0,0.5,c)" 29178 rm. 29179 29180 if $_is_antialias r. 50%,50%,1,3,2 fi 29181 if {*,w}!={*,h} -. 128 r. {*,w,h},1,3,0,0,0.5,0.5 +. 128 fi 29182 if $is_formula 29183 if !narg($formula) 29184 0 t. {``$expr},0,0,48,1,255 frame. 5,5,0 +dilate. 11 max. 128 to_rgb.. 29185 if w>0.75*{*,w} r2dx[-2,-1] {0.75*{*,w}} fi 29186 mv[-2,-1] 0 nm[0,1] formula,mformula 29187 fi 29188 j. [formula],0.5~,1~,0,0,1,[mformula],255 29189 fi 29190 if $is_screenshot o. $basename.png is_screenshot=0 fi 29191 if $is_recording o. $basename.mp4,15,0,1 nb_frames+=1 to. "Recording video\n[Frame \#"$nb_frames"]",0,0,5% fi 29192 w. rm. wait 40 29193 while {*}" && "!{*,ESC}" && "!{*,Q} 29194 rmn cmap,formula,mformula 29195 w[] 0 29196 29197#@cli x_2048 29198#@cli : Launch the 2048 game. 29199x_2048 : check_display $0 29200 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29201 e[] "\n 29202------ "${g}"2048"$n" -----------------------------------------------\n 29203----\n 29204---- Join the numbers and get to the "${g}"2048"$n" tile!\n 29205----\n 29206---- Use your "${c}"arrow keys"$n" to move the tiles. When two tiles\n 29207---- with the same number touch, they merge into one!\n 29208---- This command is a port of the '"${c}"2048"$n"' game originally\n 29209---- designed by "${c}"Gabriele Cirulli"$n", and available at:\n 29210---- "${g}"http://gabrielecirulli.github.io/2048/"$n"\n 29211----\n 29212---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29213----\n 29214--------------------------------------------------------------" 29215 l[] 29216 score=0 f3d 50 m3d 0 29217 m "_x_2048_setrandom : +==[0] 0 f. 'if(i,4*y+x,-1)' discard. -1 29218 off={i[round(u(h-1))]} rm. x={$off&3} y={$off>>2} n={if(u<0.75,1,2)} 29219 =[0] $n,$x,$y [{2+$n}] c3d. 29220 repeat 6 j3d[1] .,{78+$x*121},{190+$y*121},{10*$<},{(1+$>)/6} w[1] wait 20 done 29221 rm." 29222 m "_x_2048_object3d : +f[0] 'if(i,i*16+4*y+x,-1)' discard. -1 29223 N={h} repeat h v={-{1+$>},@$>} ++3d[{2+($v>>4)}] {$v&3},{($v>>2)&3} done 29224 +3d[-$N--1] rm.." 29225 i[0] 4,4 29226 29227 # Pre-render game canvas and numbered titles. 29228 b0=204,192,179 b1=238,228,218 b2=237,224,200 b3=242,177,121 29229 b4=245,149,99 b5=246,124,95 b6=246,94,59 b7=237,207,114 29230 c0=119,110,101 c1=249,246,242 s0=" " 29231 520,630,1,3 fc. 250,248,239 29232 t. "2048",20,10,86,1,$c0 29233 t. "Join the numbers and get to the 2048 tile!",20,90,20,1,$c0 29234 rectangle. 422,20,501,75,1,187,173,160 t. "SCORE",439,25,15,1,238,228,218 29235 repeat 12 29236 107,107,1,3 fc. ${b{min($>,7)}} +fc. ${c{$>>2}} 29237 s1={2^$>} 0 t. ${s{$>>0}},0,0,52,1,1 29238 r. ..,..,1,1,0,0,0.5,0.5 dilate_circ. 3 b. 0.5 29239 j... ..,0,0,0,0,1,.,1 rm[-2,-1] 29240 done 29241 frame_round[2--1] 10,5,1,0.5,187,173,160 frame[2--1] 7,7,187,173,160 to_rgb[2--1] 29242 r[2] 400%,400%,1,3,0,2 j[1] [2],18,130 29243 sprite3d[3--1] 29244 29245 # Run game. 29246 w[1] 100%,100%,0,"[G"{`39`}"MIC] 2048" insert_new=1 29247 repeat 2 _x_2048_setrandom done 29248 do 29249 29250 # Render game graphics at current iteration. 29251 if $insert_new 29252 _x_2048_object3d *3d. 121 j[1] [2],18,130 j3d[1] .,78,190 rm. 29253 80,25,1,3 fc. $c1 0 t. $score,0,0,25,1,1,1,1 ri. ..,0,0,0.5,0.8 29254 rectangle[1] 422,45,501,69,1,187,173,160 j[1] ..,422,45,0,0,1,. rm[-2,-1] 29255 w[1] insert_new=0 29256 fi 29257 29258 # Check for the end of the game. 29259 ++[0] 1 f. 'j(-1)==i||j(1)==i||j(0,-1)==i||j(1,0)==i||i==1' 29260 if {0,iM==11} # Game won. 29261 alert "Game Over","\nCongratulations! You got the 2048 title!\n\n Your score: "$score,"OK" 29262 break 29263 elif !iM # Game lost. 29264 alert "Game Over","\nBad luck! You lost the game!\n\n Your score: "$score,"OK" 29265 break 29266 fi 29267 rm. 29268 29269 # Manage user events. 29270 wait 29271 is_shift=0 um shift2048,ishift2048,vshift2048 29272 if {*,ARROWLEFT} 29273 m "shift2048:" m "ishift2048:" m "vshift2048:" 29274 is_shift=1 29275 elif {*,ARROWRIGHT} 29276 m "shift2048: rotate 180" m "ishift2048: rotate 180" 29277 m "vshift2048: s3d l[2] r 3,{h/3},1,1,-1 s x -[0,1] 3 *[0,1] -1 a x y endl a y" 29278 is_shift=1 29279 elif {*,ARROWUP} 29280 m "shift2048: rotate -90" m "ishift2048: rotate 90" 29281 m "vshift2048: s3d l[2] r 3,{h/3},1,1,-1 s x rv[0,1] -[0] 3 *[0] -1 a x y endl a y" 29282 is_shift=1 29283 elif {*,ARROWDOWN} 29284 m "shift2048: rotate 90" m "ishift2048: rotate -90" 29285 m "vshift2048: s3d l[2] r 3,{h/3},1,1,-1 s x rv[0,1] -[1] 3 *[1] -1 a x y endl a y" 29286 is_shift=1 29287 fi 29288 if {*,r} w[1] 100%,100% fi 29289 29290 # Manage tile shifts and fusions. 29291 if $is_shift 29292 wait -1 29293 shift2048[0] 29294 repeat 2 29295 29296 # Tile shifts. 29297 _x_2048_object3d 29298 +s[0] y discard[-4--1] 0 y[-4--1] x r[-4--1] 4,1,1,1,0,0 a[-4--1] y 29299 +==[0,-1] insert_new={$insert_new||!im} rm. 29300 +f[0,-1] 'if(i,x,-1)' discard[-2,-1] -1 rv[-2,-1] -[-2,-1] rv[0,-2] rm.. 29301 29302 if (im||iM)&&!{*,k} # Render animation for shift. 29303 /. 5 z. 0,2 y. 29304 repeat 5 29305 j.. .,0,8,0,0,-1 29306 j[1] [2],18,130 +vshift2048.. *3d. 121 j3d[1] .,78,190 rm. 29307 w[1] wait 20 29308 done 29309 fi 29310 rm[-2,-1] 29311 29312 # Tile fusions. 29313 if !$> dscore=0 29314 [0] +f[0] 'if(i,i*16+4*y+x,-1)' discard. -1 29315 repeat h 29316 x={i[$>]&3} y={(i[$>]>>2)&3} n={i[$>]>>4} 29317 if $x>0" && "{0,i($x-1,$y)}==$n 29318 =[0] 0,$x,$y =[0] {$n+1},{$x-1},$y =.. 0,$x,$y insert_new=1 dscore+={2^($n+1)} 29319 else =. -1,0,$> 29320 fi 29321 done 29322 score+=$dscore 29323 29324 if iM<0 rm[-2,-1] 29325 else # At least one tile fusions. 29326 discard. -1 29327 rv[0,-2] _x_2048_object3d rv[0,-3] vshift2048. *3d. 121 # Only tiles that do not move in this step. 29328 j[1] [2],18,130 j3d[1] .,78,190 rm[-3,-1] 29329 N={h} repeat h v={-{1+$>},@$>} ++3d[{2+($v>>4)}] {$v&3},{($v>>2)&3} done # Only tiles that move. 29330 +3d[-$N--1] rm.. 29331 0 t. +$dscore,0,0,33,1,1 100%,100%,1,3 fc. $c0 29332 repeat 6 # Render animation for fusion. 29333 +vshift2048... *3d. 121 +j3d[1] .,78,190 29334 j. ...,440,{40-3*$>},0,0,{min(1,$</3)},[-4] 29335 w. rm[-2,-1] -3d... {1/6},0,0 wait 20 29336 done 29337 rm[-3--1] 29338 fi 29339 29340 fi 29341 done 29342 ishift2048[0] 29343 29344 # Insert new tile. 29345 if $insert_new _x_2048_setrandom fi 29346 fi 29347 29348 while {*}" && "!{*,ESC}" && "!{*,Q} 29349 rm w 0 endl um _x_2048_setrandom,_x_2048_object3d 29350 29351#@cli x_blobs 29352#@cli : Launch the blobs editor. 29353#@cli : ![x_blobs](../img/x_blobs.jpg) 29354x_blobs : check_display $0 29355 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29356 e[] "\n 29357------ "${g}"Blobs editor"$n" --------------------------\n 29358----\n 29359---- "${c}"Mouse"$n" to insert/move/delete blobs.\n 29360---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 29361---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 29362---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29363----\n 29364-----------------------------------------------------" 29365 29366 # Create background image [0]. 29367 l[] (0;0^0;128^0;255) r. 450,450,1,3,3 flower. 30,8,0,0,50%,50%,1 water. 20 29368 w {f=h<0.5*{*,v}?1.5:1;[w,h]*=f},0,0,"[G"{`39`}"MIC] Blobs Editor" 29369 29370 # Start event loop. 29371 moving=-1 29372 do 29373 x={{*,x}*{0,w}/{*,w}} 29374 y={{*,y}*{0,h}/{*,h}} 29375 b={*,b} nearest=-1 29376 fps=${-fps} 29377 29378 # Render image of blobs and find nearest blob to mouse pointer. 29379 if $!>1 29380 {0,[w,h]},1,2 29381 repeat h#1 29382 r={1,i[2]*(1+i[3]*cos(i[4]+i[5]*$|*1000))} 29383 ellipse. {1,@0,1},$r,$r,0,1,{1,@6-7} 29384 d={sqrt(($x-{1,@0})^2+($y-{1,@1})^2)} 29385 if $d<$r nearest=$> fi 29386 shift[1] 0,-1,0,0,2 done 29387 b. 15 29388 +norm. +>=. 50 <=.. 40 *[-3,-1] 29389 +*[0,-1] rm.. rv[-2,-1] *. 1.6 c. 0,255 +[-2,-1] 29390 if $fps>0 to. $fps" fps",5,{h-29},24,2,0.2 fi 29391 w. 29392 if {*,CTRLLEFT}" && "{*,D} w[] {2*[w,h]} elif {*,CTRLLEFT}" && "{*,C} w[] {[w,h]} fi 29393 rm. 29394 else 29395 +to[0] "G\47MIC Blobs Editor",75,100,35,3,1,200,128,255 29396 to. "* Left mouse button : Create and move blobs.\n\n\ 29397 * Right mouse button : Remove blob.\n\n\ 29398 * Middle mouse button : Remove all blobs.\n\n\ 29399 * Key 'ESC' or 'Q' : Quit.\n\n\ 29400 * Colors and sizes of appearing blobs are\n chosen randomly",\ 29401 50,180,18,1,1,255 29402 w. 29403 if {*,CTRLLEFT}" && "{*,D} w[] {1.5*[w,h]} elif {*,CTRLLEFT}" && "{*,C} w[] {[w,h]} fi 29404 rm. 29405 fi 29406 wait 20 29407 29408 # Manage blob insertion, removal or move. 29409 if $x<0||$y<0 continue fi 29410 if $b&1 29411 if $nearest>=0" || "$moving>=0 # Move existing blob. 29412 if $moving<0 moving=$nearest fi 29413 =[1] $x,0,$moving =[1] $y,1,$moving 29414 else # Insert new blob. 29415 ($x,$y,{u(20,50)},{u(-0.3,0.3)},{u(0,pi/2)},{u(0,0.009)},{u(64,255)},{u(64,255)}) a[^0] y 29416 moving={h-1} 29417 fi 29418 elif $b&2 # Remove existing blob. 29419 if $nearest>=0 l[1] s y rm[$nearest] a y endl nearest=-1 fi 29420 elif $b&4 # Remove all blobs. 29421 k[0] 29422 else 29423 moving=-1 29424 fi 29425 29426 while {*}" && "!{*,ESC}" && "!{*,Q} 29427 rm w 0 endl 29428 29429#@cli x_bouncing 29430#@cli : Launch the bouncing balls demo. 29431x_bouncing : check_display $0 29432 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29433 e[] "\n 29434------ "${g}"Bouncing balls"$n" ------------------------------\n 29435----\n 29436---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 29437---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 29438---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29439----\n 29440-----------------------------------------------------" 29441 l[] 29442 520,320,1,3 plasma 1,1,9 n 0,220 29443 N=12 29444 repeat $N 29445 ball[] {round(u(32,80))},${-rgb} 29446 t$>={u(200)} x$>={0,u(10,w-10)} h$>={u(150,300)} vx$>={if(u<0.5,1,-1)*u(1,8)} 29447 done 29448 mv[0] $! 29449 w. {f=w<0.5*{*,u}?1.5:1;[w,h]*=f},0,"[G"{`39`}"MIC] Bouncing Balls" 29450 (0;0.7;1) r. {-2,w},70,1,1,3 29451 29452 do 29453 [$N] 29454 repeat $N 29455 bw={$>,w} bh={$>,h} 29456 y={${h$>}*abs(cos(${t$>}*pi/60))-$bh/2} 29457 dt=1 29458 if $y<0 d={-$y} y=0 bh-=$d bw+=$d dt={max(0.2,1-($d/$bh)^2)} else dt=1 fi 29459 if ${x$>}+$bw/2>w 29460 d={${x$>}+$bw/2-w} bw-=$d bh+={0.5*$d} 29461 if ${x$>}+$bw/4>w vx$>={-${vx$>}} fi 29462 fi 29463 if ${x$>}-$bw/2<0 29464 d={$bw/2-${x$>}} bw-=$d bh+={0.5*$d} 29465 if ${x$>}-$bw/4<0 vx$>={-${vx$>}} fi 29466 fi 29467 +r[$>] $bw,$bh,1,4,3 s. c,-3 29468 j... ..,{max(0,min({$N,w-$bw},${x$>}-$bw/2))},{{$N,h}-{h}-$y-70},0,0,1,.,255 rm[-2,-1] 29469 t$>+=$dt 29470 x$>+={$dt*${vx$>}} 29471 done 29472 29473 +rows. {h-2*70},{h-1-70} mirror. y *. [{$N+1}] 29474 j.. .,0,{-2,h-71},0,0,0.5 rm. 29475 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-29},24,2,0.2 fi 29476 if {*,CTRLLEFT}" && "{*,D} w[] {1.5*w},{1.5*h} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 29477 w. rm. wait 20 29478 while {*}" && "!{*,ESC}" && "!{*,Q} 29479 w 0 rm endl 29480 29481#@cli x_color_curves : _colorspace={ rgb | cmy | cmyk | hsi | hsl | hsv | lab | lch | ycbcr | last } 29482#@cli : Apply color curves on selected RGB[A] images, using an interactive window. 29483#@cli : Set 'colorspace' to 'last' to apply last defined color curves without opening interactive windows. 29484#@cli : Default value: 'colorspace=rgb'. 29485x_color_curves : skip ${1=rgb} 29486 if ['"$1"']!='last'&&!{*,u} error[0--3] "Command '$0': No display available." return fi 29487 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29488 e[^-1] "Apply color curves of image$?, in the '$1' colorspace." 29489 if ['"$1"']=='last' 29490 if !narg($_xcc_colorbase) return fi 29491 __x_color_curves[] $_xcc_colorbase 29492 else 29493 e[] "\n 29494------------------------------------------------------------------------------------------------\n 29495----\n 29496---- "${c}"Left mouse button"$n" on a curve creates a new control point (or moves an existing one).\n 29497---- "${c}"Right mouse button"$n" on a control point deletes it.\n 29498---- "${c}"Left mouse button"$n" on the main image window shows the initial image until button is released.\n 29499---- "${c}"Right mouse button"$n" on the main image window adds a keypoint to all curves from picked color.\n 29500---- Key '"${c}"R"$n"' on a curve resets it.\n 29501---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 29502---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 29503---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 29504---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' close the current window.\n 29505----\n 29506------------------------------------------------------------------------------------------------" 29507 __x_color_curves[] $1 _xcc_colorbase=$1 29508 fi 29509 29510 to_color repeat $! l[$>] 29511 29512 if ['"$1"']!='last' # Open interactive windows to set color curves. 29513 +r[0] ${fitscreen[]\ {0,[w,h,1]},128,70%},1,100%,3 29514 +l. # Compute additional info for each image channel (histogram and color axis). 29515 xcc_goto s c histogram 256,0,255 xcc_info 29516 endl 29517 __C0= __C1= __C2= __C3= __C4= 29518 if narg($__xcc_C0) __C0=$__xcc_C0 fi 29519 if narg($__xcc_C1) __C1=$__xcc_C1 fi 29520 if narg($__xcc_C2) __C2=$__xcc_C2 fi 29521 if narg($__xcc_C3) __C3=$__xcc_C3 fi 29522 if narg($__xcc_C4) __C4=$__xcc_C4 fi 29523 29524 x={1,({*,u}-560-w)/2} y={1,({*,v}-h)/2} 29525 if $!==5 # 3 channels. 29526 parallel "w[] 256,256,0,0,"$x","$y",\"Curve: "$_title0"\" x_select_function1d... __C0,"$_color0"",\ 29527 "w[] 256,256,0,0,"{$x+280}","$y",\"Curve: "$_title1"\" x_select_function1d.. __C1,"$_color1"",\ 29528 "w[] 256,256,0,0,"$x","{$y+300}",\"Curve: "$_title2"\" x_select_function1d. __C2,"$_color2"",\ 29529 "w. 100%,100%,0,0,"{$x+560}","$y" _x_color_curves[-4]" 29530 elif $!==6 # 4 channels. 29531 parallel "w[] 256,256,0,0,"$x","$y",\"Curve: "$_title0"\" x_select_function1d[-4] __C0,"$_color0"",\ 29532 "w[] 256,256,0,0,"{$x+280}","$y",\"Curve: "$_title1"\" x_select_function1d... __C1,"$_color1"",\ 29533 "w[] 256,256,0,0,"$x","{$y+300}",\"Curve: "$_title2"\" x_select_function1d.. __C2,"$_color2"",\ 29534 "w[] 256,256,0,0,"{$x+280}","{$y+300}",\"Curve: "$_title3"\" x_select_function1d. __C3,"$_color3"",\ 29535 "w. 100%,100%,0,0,"{$x+560}","$y" _x_color_curves[-5]" 29536 elif $!==7 # 5 channels. 29537 parallel "w[] 256,256,0,0,"$x","$y",\"Curve: "$_title0"\" x_select_function1d[-5] __C0,"$_color0"",\ 29538 "w[] 256,256,0,0,"{$x+280}","$y",\"Curve: "$_title1"\" x_select_function1d[-4] __C1,"$_color1"",\ 29539 "w[] 256,256,0,0,"$x","{$y+300}",\"Curve: "$_title2"\" x_select_function1d... __C2,"$_color2"",\ 29540 "w[] 256,256,0,0,"{$x+280}","{$y+300}",\"Curve: "$_title3"\" x_select_function1d.. __C3,"$_color3"",\ 29541 "w[] 256,256,0,0,"{$x+280}","{$y+600}",\"Curve: "$_title4"\" x_select_function1d. __C4,"$_color4"",\ 29542 "w. 100%,100%,0,0,"{$x+560}","$y" _x_color_curves[-6]" 29543 fi 29544 k[0] 29545 fi 29546 29547 # Apply color curves on fullres image. 29548 xcc_goto 29549 repeat s function1d[] 1,${__xcc_C$>} *. {255%} r. 256,1,1,1,5 c. 0,255 sh[0] $> map. .. rm[-2,-1] done 29550 xcc_backto 29551 29552 endl done 29553 um xcc_goto,xcc_backto,xcc_info 29554 29555_x_color_curves : 29556 title={0,b} if narg({'{0,x}'}) title=$title.{0,x} fi ('$title') discard. {'~'} title={t} rm. 29557 +drgba. w. 100%,100%,0,"[G"{`39`}"MIC] Image: "$title rm. 29558 xcc_goto. . 29559 29560 oC0= oC1= oC2= oC3= oC4= viewmode=0 29561 do 29562 wait 100 need_refresh=0 29563 29564 # Manage user events. 29565 oviewmode=$viewmode is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} x={*,x} y={*,y} 29566 if {*,r} need_refresh=1 # Window resize. 29567 elif $is_ctrl" && "{*,-D} w[] {{*,w}*125%},{{*,h}*125%} need_refresh=1 # Increase window size. 29568 elif $is_ctrl" && "{*,-C} w[] {{*,w}*80%},{{*,h}*80%} need_refresh=1 # Decrease window size. 29569 elif $is_ctrl" && "{*,-R} w[] {w},{h} need_refresh=1 # Reset window size. 29570 elif {*,b}&1 viewmode={x={*,x};if(x<w/3,1,if(x<2*w/3,2,3))} # Change viewmode. 29571 elif {*,b}&2" && "$x>=0" && "$y>=0 # Add control point from picked color. 29572 xc={$x*w/{*,w}} yc={$y*h/{*,h}} +z[0] $xc,$yc,$xc,$yc 29573 repeat s (${__C$>},{i[$>]/255%},{i[$>]/255%}) r. 2,{w/2},1,1,-1 sort. +,y __C$>={^} rm. done 29574 rm. wait -1 29575 else viewmode=0 29576 fi 29577 need_refresh={$need_refresh||$oviewmode!=$viewmode} 29578 29579 # Update result. 29580 repeat s if ['_${oC$>}']!=['_${__C$>}'] # Channel must be updated. 29581 function1d[] 1,${__C$>} *. {255%} r. 256,1,1,1,5 c. 0,255 29582 +channels[0] $> map. .. j[1] .,0,0,0,$> rm[-2,-1] 29583 need_refresh=1 oC$>=${__C$>} 29584 fi done 29585 29586 # Display view. 29587 if $need_refresh 29588 if $viewmode==0 # Modified view. 29589 +xcc_backto[1] 29590 elif $viewmode%2 # Split view. 29591 w2={0,int(w/2)} b={$viewmode==1} +z[{!$b}] 0,{$w2-1} +z[$b] $w2,100% 29592 xcc_backto.. xcc_backto. a[-2,-1] x line. 50%,0,50%,100%,1,0 29593 else # Original view. 29594 +xcc_backto[0] 29595 fi 29596 if s>3 drgba. fi w. rm. refresh=0 29597 fi 29598 29599 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,SPACE}" && "!{*,ENTER} 29600 w 0 29601 29602 # Transfer curves to output variable and request curve widgets to close. 29603 repeat 5 if narg(${__C$>}) __xcc_C$>=${__C$>} __C$>=-1 fi done 29604 29605# Define colorspace conversion functions. 29606__x_color_curves : 29607 if ['"$1"']=='rgb' 29608 _color0="255,180,180" _color1="180,255,180" _color2="180,180,255" _color3="220,220,220" 29609 _title0=Red _title1=Green _title2=Blue _title3=Alpha 29610 m "xcc_goto:" m "xcc_backto:" 29611 m "xcc_info: (0,255;0,0;0,0) (0,0;0,255;0,0) (0,0;0,0;0,255) r[-3--1] 256,3,1,1,3 29612 a[0,-3] y a[1,-2] y a[2,-1] y" 29613 elif ['"$1"']=='cmy' 29614 _color0="180,255,255" _color1="255,180,255" _color2="255,255,100" _color3="220,220,220" 29615 _title0=Cyan _title1=Magenta _title2=Yellow _title3=Alpha 29616 m "xcc_goto: s c,-3 rgb2cmy[0] a c" m "xcc_backto: s c,-3 cmy2rgb[0] a c" 29617 m "xcc_info: (255,0;255,255;255,255) (255,255;255,0;255,255) (255,255;255,255;255,0) r[-3--1] 256,3,1,1,3 29618 a[0,-3] y a[1,-2] y a[2,-1] y" 29619 elif ['"$1"']=='cmyk' 29620 _color0="180,255,255" _color1="255,180,255" _color2="255,255,100" _color3="180,180,180" _color4="220,220,220" 29621 _title0=Cyan _title1=Magenta _title2=Yellow _title3=Key _title4=Alpha 29622 m "xcc_goto: s c,-3 rgb2cmyk[0] a c" m "xcc_backto: s c,-4 cmyk2rgb[0] a c" 29623 m "xcc_info: (255,0;255,255;255,255) (255,255;255,0;255,255) (255,255;255,255;255,0) (255,0) r[-4--1] 256,3,1,1,3 29624 a[0,-4] y a[1,-3] y a[2,-2] y a[3,-1] y" 29625 elif ['"$1"']=='hsi' 29626 _color0="255,220,220" _color1="220,220,220" _color2="180,180,180" _color3="220,220,220" 29627 _title0=Hue _title1=Saturation _title2=Intensity _title3=Alpha 29628 m "xcc_goto: s c,-3 rgb2hsi8[0] a c" m "xcc_backto: s c,-3 hsi82rgb[0] a c" 29629 m "xcc_info: 256,1,1,3,if(!c,x,128) 256,1,1,3,if(!c,0,if(c==1,x,128)) 256,1,1,3,if(!c,0,if(c==1,0,x)) 29630 hsi82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 29631 elif ['"$1"']=='hsl' 29632 _color0="255,220,220" _color1="220,220,220" _color2="180,180,180" _color3="220,220,220" 29633 _title0=Hue _title1=Saturation _title2=Lightness _title3=Alpha 29634 m "xcc_goto: s c,-3 rgb2hsl8[0] a c" m "xcc_backto: s c,-3 hsl82rgb[0] a c" 29635 m "xcc_info: 256,1,1,3,if(!c,x,128) 256,1,1,3,if(!c,0,if(c==1,x,128)) 256,1,1,3,if(!c,0,if(c==1,0,x)) 29636 hsl82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 29637 elif ['"$1"']=='hsv' 29638 _color0="255,220,220" _color1="220,220,220" _color2="180,180,180" _color3="220,220,220" 29639 _title0=Hue _title1=Saturation _title2=Value _title3=Alpha 29640 m "xcc_goto: s c,-3 rgb2hsv8[0] a c" m "xcc_backto: s c,-3 hsv82rgb[0] a c" 29641 m "xcc_info: 256,1,1,3,if(!c,x,255) 256,1,1,3,if(!c,0,if(c==1,x,128)) 256,1,1,3,if(!c,0,if(c==1,0,x)) 29642 hsv82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 29643 elif ['"$1"']=='lab' 29644 _color0="180,180,180" _color1="220,180,220" _color2="220,220,180" _color3="220,220,220" 29645 _title0=Lightness _title1=Chroma-A _title2=Chroma-B _title3=Alpha 29646 m "xcc_goto: s c,-3 srgb2rgb[0] apo[0] rgb2lab8,0,4 a c" m "xcc_backto: s c,-3 apo[0] lab82rgb,0,4 rgb2srgb[0] a c" 29647 m "xcc_info: 256,1,1,3,if(!c,x,128) 256,1,1,3,if(!c,240,if(c==1,x,128)) 256,1,1,3,if(!c,240,if(c==1,128,x)) 29648 lab82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 29649 elif ['"$1"']=='lch' 29650 _color0="180,180,180" _color1="220,180,220" _color2="255,220,220" _color3="220,220,220" 29651 _title0=Lightness _title1=Chroma _title2=Hue _title3=Alpha 29652 m "xcc_goto: s c,-3 srgb2rgb[0] apo[0] rgb2lch8[0],0,4 a c" m "xcc_backto: s c,-3 apo[0] lch82rgb[0],0,4 29653 rgb2srgb[0] a c" 29654 m "xcc_info: 256,1,1,3,if(!c,x,0) 256,1,1,3,if(!c,255,if(c==1,x,128)) 256,1,1,3,if(!c,220,if(c==1,128,x)) 29655 lch82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 29656 elif ['"$1"']=='ycbcr' 29657 _color0="180,180,180" _color1="220,220,255" _color2="255,220,220" _color3="220,220,220" 29658 _title0=Luma _title1=Blue\ chroma _title2=Red\ chroma _title3=Alpha 29659 m "xcc_goto: s c,-3 rgb2ycbcr[0] a c" m "xcc_backto: s c,-3 ycbcr2rgb[0] a c" 29660 m "xcc_info: 256,1,1,3,if(!c,x,128) 256,1,1,3,if(!c,128,if(c==1,x,128)) 256,1,1,3,if(!c,128,if(c==1,128,x)) 29661 ycbcr2rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 29662 else error[0--3] "Command 'x_color_curves': Unknown specified color space '$1'." 29663 fi 29664 29665#@cli x_colorize : _is_lineart={ 0 | 1 },_max_resolution={ 0 | >=128 },_multichannels_output={ 0 | 1 },\ 29666# _[palette1],_[palette2],_[grabber1] 29667#@cli : Colorized selected B&W images, using an interactive window. 29668#@cli : When >0, argument 'max_resolution' defines the maximal image resolution used in the interactive window. 29669#@cli : Default values: 'is_lineart=1', 'max_resolution=1024' and 'multichannels_output=0'. 29670x_colorize : skip ${1=0},${3=0},${4=0},${5=0},${6=0} check "${2=1024}==0 || $2>=128" check_display $0 29671 s0="image" s1="lineart" s2="multichannel" s3="merged" use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29672 e[^-1] "Colorize selected B&W "${s{!$1}}"$? interactively, with maximum resolution $2 and "${s{2+!$3}}" output." 29673 e[] "\n 29674--------------------------------------------------------------------------------------\n 29675----\n 29676---- "${c}"Left mouse button"$n" creates a new colored control point (or moves an existing one).\n 29677---- "${c}"Right mouse button"$n" or key '"${c}"X"$n"' over a control point deletes it.\n 29678---- "${c}"Right mouse button"$n" or key '"${c}"P"$n"' anywhere else picks a color from the image.\n 29679---- "${c}"Mouse wheel"$n", or keys '"${c}"CTRL+arrows UP/DOWN"$n"' zoom view in/out.\n 29680---- '"${c}"CTRL+mouse wheel"$n"', '"${c}"SHIFT+mouse wheel"$n"' or "${c}"arrow keys"$n" move image in zoomed view.\n 29681---- Key '"${c}"SPACE"$n"' updates the extrapolated color field.\n 29682---- Key '"${c}"TAB"$n"' toggles between markers view modes.\n 29683---- Key '"${c}"BACKSPACE"$n"' deletes the last control point added.\n 29684---- Key '"${c}"PAGE UP"$n"' increases image contrast.\n 29685---- Key '"${c}"PAGE DOWN"$n"' decreases image contrast.\n 29686---- Key '"${c}"R"$n"' toggles color replace mode.\n 29687---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 29688---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 29689---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 29690---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' exit the interactive window.\n 29691----\n 29692--------------------------------------------------------------------------------------" 29693 N=$! 29694 thread_main="_x_colorize[0] ${1--1}" 29695 thread_color="w[] 400,320,0,\"Palette: main\" x_select_color[] __color,255,255,255" 29696 29697 is_palette1=${"is_image_arg[] $4"} 29698 if $is_palette1 29699 pass$4 1 ('{b}') discard. {'~'} palette_title1={t} rm. 29700 thread_palette1="w[] 400,400,0,\"Palette: "$palette_title1"\" x_select_palette["{$!-1}"] __color" 29701 fi 29702 29703 is_palette2=${"is_image_arg[] $5"} 29704 if $is_palette2 29705 pass$5 1 ('{b}') discard. {'~'} palette_title2={t} rm. 29706 thread_palette2="w[] 400,400,0,\"Palette: "$palette_title2"\" x_select_palette["{$!-1}"] __color" 29707 fi 29708 29709 is_grabber=${"is_image_arg[] $6"} 29710 if $is_grabber 29711 pass$6 1 ('{b}') discard. {'~'} palette_grabber={t} rm. 29712 thread_grabber="w[] ${\"fitscreen[] {[w,h,1]},128,50%\"},0,\"Grabber: "$palette_grabber"\" 29713 x_grab_color["{$!-1}"] __color" 29714 fi 29715 29716 __color=255,255,255 29717 29718 if !$is_palette1" && "!$is_palette2" && "!$is_grabber 29719 repeat $N l[$>] 29720 parallel $thread_main,$thread_color 29721 endl done 29722 else 29723 repeat $N l[$>,$N--1] 29724 parallel $thread_main,$thread_color,$thread_palette1,$thread_palette2,$thread_grabber 29725 endl done 29726 fi 29727 k[0-{$N-1}] 29728 29729_x_colorize : 29730 29731 # Init variables and images. 29732 name={n} title={b} if narg({x}) title=$title.{x} fi 29733 w={w} h={h} 29734 29735 if $1 # Line-art. 29736 if s==4 sh. 3 if abs(im-iM)>64 +*. -1 rm.. +. 255 else rm. sh. 0 fi 29737 else sh. 0 29738 fi 29739 n 0,255 29740 else # Regular image. 29741 if s==1 sh. 0 29742 else +luminance. 29743 fi 29744 fi 29745 29746 nm. img 29747 29748 fdim=${fitscreen[]\ $w,$h} ww={arg(1,$fdim)} wh={arg(2,$fdim)} x0=0 y0=0 x1={w-1} y1={h-1} 29749 selection=-1 view_markers=2 contrast=9 xpan=-1 ypan=-1 replace_color= current_replace_color= 29750 29751 if narg($_gui_control_points)>=6 # Import list of control points from plug-in GUI. 29752 ($_gui_control_points) r. {w/6},6,1,1,-1 29753 else 0 # Empty list of control points. 29754 fi 29755 nm. points 29756 29757 # Compute potential map. 29758 if $2>0 if $w>$h +r2dx[img] {min($2,$w)},2 else +r2dy[img] {min($2,$h)},2 fi else [img] fi 29759 __x_colorize. $1 29760 pw={potential,w} ph={potential,h} 29761 29762 # Start event loop. 29763 do 29764 29765 # Handle user events for zoom/navigation/resizing. 29766 if narg($replace_color)" && "{*,x}<0" && "{*,y}<0 wait 200 else wait fi 29767 x={*,x} y={*,y} b={*,b} o={*,-o} 29768 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 29769 is_shift={{*,SHIFTLEFT}" || "{*,SHIFTRIGHT}} 29770 is_mouseout={$x<0" || "$y<0} 29771 x={$x0+$x*($x1-$x0+1)/$ww} y={$y0+$y*($y1-$y0+1)/$wh} 29772 oww=$ww owh=$wh ox0=$x0 oy0=$y0 ox1=$x1 oy1=$y1 29773 29774 if {*,r} # When window resized. 29775 nww={*,d} nwh={*,e} m={min($nww,$nwh)} 29776 cx={($x0+$x1)/2} cy={($y0+$y1)/2} dx={$nww*($x1-$x0+1)/$ww} dy={$nwh*($y1-$y0+1)/$wh} 29777 x0={$cx-$dx/2} x1={$cx+$dx/2} 29778 y0={$cy-$dy/2} y1={$cy+$dy/2} 29779 ww=$nww wh=$nwh 29780 elif $is_ctrl" && "{*,-D} # Increase window size. 29781 nww={min({*,u},$ww*1.25)} nwh={min({*,v},$wh*1.25)} m={min($nww,$nwh)} 29782 if $m==$nww ww=$m wh={$h*$m/$w} else ww={$w*$m/$h} wh=$m fi 29783 elif $is_ctrl" && "{*,-C} # Decrease window size. 29784 nww={$ww/1.25} nwh={$wh/1.25} 29785 if min($nww,$nwh)>=64 ww=$nww wh=$nwh fi 29786 elif $is_ctrl" && "{*,R} # Reset window size. 29787 fdim=${fitscreen[]\ $w,$h} ww={arg(1,$fdim)} wh={arg(2,$fdim)} 29788 x0=0 y0=0 x1={$w-1} y1={$h-1} 29789 elif ($is_shift" && "$o<0)" || "{*,ARROWLEFT} # Go left. 29790 dx={($x1-$x0)/6} x0-=$dx x1-=$dx 29791 elif ($is_shift" && "$o>0)" || "{*,ARROWRIGHT} # Go right. 29792 dx={($x1-$x0)/6} x0+=$dx x1+=$dx 29793 elif ($is_ctrl" && "$o>0)" || "({*,ARROWUP}" && "!$is_ctrl) # Go up. 29794 dy={($y1-$y0)/6} y0-=$dy y1-=$dy 29795 elif ($is_ctrl" && "$o<0)" || "({*,ARROWDOWN}" && "!$is_ctrl) # Go down. 29796 dy={($y1-$y0)/6} y0+=$dy y1+=$dy 29797 elif $o>0" || "($is_ctrl" && "{*,ARROWUP}) # Zoom in. 29798 if $x1-$x0>16" && "$y1-$y0>16 29799 cx={if($x>=0" && "!{*,ARROWUP},$x,($x0+$x1)/2)} 29800 cy={if($y>=0" && "!{*,ARROWUP},$y,($y0+$y1)/2)} 29801 x0={$cx+($x0-$cx)*0.75} y0={$cy+($y0-$cy)*0.75} 29802 x1={$cx+($x1-$cx)*0.75} y1={$cy+($y1-$cy)*0.75} 29803 fi 29804 elif $o<0" || "($is_ctrl" && "{*,ARROWDOWN}) # Zoom out. 29805 zfactor={max(($x1-$x0+1)/$w,($y1-$y0+1)/$h)} 29806 if $zfactor<1.3 29807 cx={if($x>=0" && "!{*,ARROWDOWN},$x,($x0+$x1)/2)} 29808 cy={if($y>=0" && "!{*,ARROWDOWN},$y,($y0+$y1)/2)} 29809 x0={$cx+($x0-$cx)/0.75} y0={$cy+($y0-$cy)/0.75} 29810 x1={$cx+($x1-$cx)/0.75} y1={$cy+($y1-$cy)/0.75} 29811 dx={$zfactor^2*($w-$x0-$x1)/2} dy={$zfactor^2*($h-$y0-$y1)/2} 29812 x0+=$dx x1+=$dx y0+=$dy y1+=$dy 29813 else 29814 dx={($w-$x0-$x1)/2} dy={($h-$y0-$y1)/2} 29815 x0+=$dx x1+=$dx y0+=$dy y1+=$dy 29816 fi 29817 elif $b&4" && "!$is_mouseout # Pan. 29818 if $panx<0" && "$pany<0 panx=$x pany=$y 29819 else dx={round($panx-$x)} dy={round($pany-$y)} x0+=$dx y0+=$dy x1+=$dx y1+=$dy 29820 fi 29821 else panx=-1 pany=-1 29822 fi 29823 if $ww!=$oww" || "$wh!=$owh" || "$ox0!=$x0" || "$oy0!=$y0" || "$ox1!=$x1" || "$oy1!=$y1 rm[baseview] fi 29824 29825 # Handle events related to control points management. 29826 N={points,w} 29827 if narg($baseview)" && "($b&3" || "{*,X}" || "{*,P})" && "$x>=0" && "$y>=0" && "$x<$w" && "$y<$h 29828 if $selection==-1" && "$N # Check for selection of an existing point. 29829 ($x;$y) r. $N,2 -. [points] *. {max($ww,$wh)/max($x1-$x0,$y1-$y0)} sqr. s. y +[-2,-1] 29830 dmin={im} selection={if($dmin>25,-1,xm)} rm. 29831 fi 29832 if narg($replace_color) # Go back from 'Replace color' mode. 29833 replace_color= wait -1 29834 elif $selection>=0 29835 if $b&1" && "$view_markers # Move existing point. 29836 +columns[points] $selection ox={i[0]} oy={i[1]} =. $x =. $y,0,1 j[points] .,$selection rm. 29837 rm[view] 29838 elif ($b&2" || "{*,X})" && "$view_markers # Remove existing point. 29839 if $N>1 +z[points] {$selection+1},100% j[points] .,$selection rm. r[points] {$N-1},100%,1,1,0 29840 else rm[points] 0 nm. points fi 29841 wait -1 rm[view] 29842 fi 29843 elif $b&1 # Add new point 29844 ($x;$y;0) ($__color) y. y +. 1 a[-2,-1] y a[points,-1] x selection=$N 29845 if !$view_markers view_markers=2 fi 29846 rm[view] 29847 elif $b&2" || "{*,P} # Pick color from image. 29848 __color={colors,I($x*$pw/$w,$y*$ph/$h)} 29849 fi 29850 else selection=-1 29851 if {*,-SPACE}" && "narg($colors) replace_color= rm[colors] # Update color map. 29852 elif {*,-TAB} view_markers={($view_markers-1)%3} rm[view] wait -1 # Toggle markers. 29853 elif !$is_ctrl" && "{*,-R} # Switch color replace mode. 29854 if narg($replace_color) replace_color= else replace_color=$__color fi 29855 rm[baseview] wait -1 29856 elif {*,PAGEDOWN} contrast={max(0,$contrast-1)} rm[view] wait -1 # Decrease contrast. 29857 elif {*,PAGEUP} contrast={min(9,$contrast+1)} rm[view] wait -1 # Increase contrast. 29858 elif {*,BACKSPACE}" && "$N # Remove last point. 29859 if $N>1 z[points] 0,{$N-2} else i=$points rm[points] i[$i] 0 nm[$i] points fi 29860 rm[view] wait -1 29861 fi 29862 fi 29863 29864 # Manage zoomed view bounds. 29865 w2={round(($x1-$x0)/2)} h2={round(($y1-$y0)/2)} 29866 if $x0<-$w2 x1-={$x0+$w2} x0=-$w2 fi 29867 if $y0<-$h2 y1-={$y0+$h2} y0=-$h2 fi 29868 if $x1>=$w+$w2 x0+={$w-1+$w2-$x1} x1={$w-1+$w2} fi 29869 if $y1>=$h+$h2 y0+={$h-1+$h2-$y1} y1={$h-1+$h2} fi 29870 29871 # Render color map. 29872 if !narg($colors) 29873 N={points,w} 29874 if narg($view) to[view] "Processing...",5,5,20,2 w[view] fi 29875 if $N 29876 [points] 29877 sh. 0,0,0,0 *. {$pw/$w} rm. 29878 sh. 1,1,0,0 *. {$ph/$h} rm. 29879 pointcloud. -1,$pw,$ph 29880 29881 # Additional term that depends on marker's positions. 29882 +compose_channels. max !=. 0 distance. 1 *. 0.02 +. 1 ^. -1 +. [potential] 29883 if !$1 dilate.. 3 fi 29884 watershed.. . rm. -. 1 29885 else [potential],[potential],1,3,255 29886 fi 29887 nm. colors 29888 if narg($baseview) rm[baseview] fi 29889 fi 29890 29891 # Manage replace color mode. 29892 if !narg($replace_color)" && "narg($points_replaced) 29893 rm[points,colors,view] nm[colors_replaced] colors nm[points_replaced] points current_replace_color= 29894 elif narg($replace_color)" && "['$__color']!=['$current_replace_color'] 29895 if narg($colors_replaced) rm[colors_replaced,points_replaced] fi 29896 current_replace_color=$__color 29897 if {points,w} 29898 +replace_color[colors] 0,0,$replace_color,$current_replace_color 29899 +rows[points] 3,5 permute. xzcy -. 1 29900 replace_color. 0,0,$replace_color,$current_replace_color 29901 +. 1 permute. xcyz +j[points] .,0,3 rm.. 29902 else 0 0 29903 fi 29904 nm.. colors_replaced 29905 nm. points_replaced 29906 if narg($baseview) rm[baseview] fi 29907 fi 29908 29909 # Render base image. 29910 if !narg($baseview) 29911 nx0={$x0*$pw/$w} ny0={$y0*$ph/$h} 29912 nx1={$x1*$pw/$w} ny1={$y1*$ph/$h} 29913 +z[img] $x0,$y0,$x1,$y1 29914 r. $ww,$wh,1,100%,{if($ww<w" && "$wh<h,2,1)} 29915 if narg($replace_color)" && "{points,w} icolors=$colors_replaced else icolors=$colors fi 29916 +z[$icolors] $nx0,$ny0,$nx1,$ny1 29917 r. $ww,$wh,1,100%,{if($ww<w" && "$wh<h,2,3)} 29918 if $1 *.. -1 +.. 255 channels.. -3,0 blend. ..,alpha rm.. 29919 else rgb2ycbcr. j. ..,0,0,0,0 rm.. ycbcr2rgb. 29920 fi 29921 nm. baseview 29922 if narg($view) rm[view] fi 29923 fi 29924 29925 # Render view. 29926 if !narg($view) 29927 [baseview] r. 100%,100%,1,3 29928 if $contrast<9 /. {10-$contrast} +. {128*(1-1/(10-$contrast))} fi 29929 if $view_markers 29930 if $view_markers==2 rad1=5 rad2=3 else rad1=3 rad2=2 fi 29931 if narg($replace_color)" && "{points,w} ipoints=$points_replaced else ipoints=$points fi 29932 repeat w#$ipoints 29933 +columns[$ipoints] $> 29934 x={(i[0]-$x0)*$ww/(1+$x1-$x0)} 29935 y={(i[1]-$y0)*$wh/(1+$y1-$y0)} 29936 col={i[3]-1},{i[4]-1},{i[5]-1} 29937 rm. 29938 circle. $x,$y,$rad1,1,0 circle. $x,$y,$rad2,1,$col 29939 done 29940 fi 29941 29942 if narg($replace_color) 29943 to. "Replace by",5,5,20,2 29944 rectangle. 80,8,111,25,1,0 rectangle. 82,10,109,23,1,$replace_color 29945 rectangle. 150,8,181,25,1,0 rectangle. 152,10,179,23,1,$current_replace_color 29946 fi 29947 29948 nm. view 29949 w[view] $ww,$wh,0,$title 29950 fi 29951 29952 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,ENTER} 29953 29954 # Recompute colors at full resolution. 29955 if narg($view) to[view] "Processing fullres...",5,5,20,2 w[view] fi 29956 k[0,img,points] 29957 N={points,w} status= 29958 if $N 29959 status={points,^} 29960 [img] __x_colorize. $1 29961 pointcloud[points] -1,$w,$h 29962 +compose_channels[points] max !=. 0 distance. 1 *. 0.02 +. 1 ^. -1 +[potential,-1] 29963 if !$1 zfact={{img,max(w,h)}/{potential,max(w,h)}} dilate[points] {int(3*$zfact)} fi 29964 watershed[points] [potential] -[points] 1 nm[points] colors 29965 else [img],[img],1,3,255 nm. colors 29966 fi 29967 29968 if $3 # Multichannels output. 29969 k[0,colors] a c 29970 else # Merge for single layer output. 29971 k[0,img,colors] 29972 if $1 +*[img] -1 +. 255 channels. -3,0 blend[colors,-1] alpha rm[0,img] 29973 else rgb2ycbcr[colors] j[colors] [img],0,0,0,0 rm[0,img] ycbcr2rgb[colors] 29974 fi 29975 fi 29976 a c nm $name 29977 29978 __color=-1 # Force color selectors to close. 29979 u $status # Return control points. 29980 w 0 29981 29982# Compute potential function. 29983__x_colorize : 29984 if $1 # Potential for lineart. 29985 n. 0,1 ^. 5 repeat 4 +b. 0.5% min done 29986 else # Potential for generic grayscale image. 29987 gradient_norm. n. 0,255 normalize_local. 3,3 *. -1 n. 0,255 29988 b. 0.05% n. 0,1 sqr. +b. 0.5% n[-2,-1] 0,1 min[-2,-1] 29989 fi 29990 nm. potential 29991 29992#@cli x_connect4 29993#@cli : Launch the Connect Four game. 29994x_connect4 : check_display $0 29995 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29996 e[] "\n 29997------ "${g}"Connect Four"$n" --------------------------------------------\n 29998----\n 29999---- Connect four tokens in a row, column or diagonally\n 30000---- to win the game.\n 30001----\n 30002---- "${c}"Left mouse button"$n" on a column inserts a new token.\n 30003---- Keys '"${c}"SPACE"$n"' or '"${c}"ENTER"$n"' lets the computer play the turn\n 30004---- (or restart game when it's over).\n 30005---- Key '"${c}"ENTER"$n"' also enables autoplay for the current player.\n 30006---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' close the window.\n 30007----\n 30008----------------------------------------------------------------" 30009 l[] 30010 30011 # Create sprite graphics. 30012 7,6 nm. board 30013 R={board,u={*,u};v={*,v};int(0.5*min(u/w,v/h))} 30014 30015 {2*$R},{2*$R} circle. 50%,50%,32%,1,1 b. 2% g. xy +[-2,-1] n. 0,1 30016 +n. -1,0.5 abs. negate. +f. 200 rv[-3--1] a[-3--1] c hsv2rgb. 30017 to_rgba. circle. 50%,50%,27%,1,0 30018 30019 {4*$R},{4*$R} circle. 50%,50%,20%,1,1 b. 1% g. xy +[-2,-1] n. 0,1 negate. 30020 pow. 0.5 +n. -1,0.8 abs. negate. +f. 10 rv[-3--1] a[-3--1] c 30021 . sh. 0 f. 60 rm. hsv2rgb[-2,-1] 30022 100%,100% circle. 50%,50%,30%,1,255 a[-3,-2] .,c rm. 30023 30024 r2dx[-3--1] $R s[-3--1] c,-3 rm... 30025 n[^0] 0,255 round[^0] nm[^0] cache,cachem,token0,token1,tokenm 30026 +b[cachem] 2% shift. 1%,1%,0,0,2 max[cachem,-1] 30027 r[cache,cachem] 100%,{board,h*100}%,1,100%,0,2 30028 30029 # Define board evaluation function. 30030 evalf="const op = 3 - p; 30031 case(dx,dy) = ( 30032 pgood = pbad = 0; 30033 for (k = -2, k<2, ++k, 30034 X = x + k*dx; 30035 Y = y + k*dy; 30036 if (X>=0 && X<w && Y>=0 && Y<h, 30037 val = i(X,Y); 30038 if (pgood>=0 && val==op, pgood = -1, pgood+=!!val); 30039 if (pbad>=0 && val==p, pbad = -1, pbad+=!!val); 30040 ); 30041 ); 30042 pgood = arg(2+pgood,0,1,2,4,100,1e8); 30043 pbad = arg(2+pbad,0,1,2,4,10000,1e8); 30044 pgood - pbad; 30045 ); 30046 case(1,0) + case(0,1) + case(1,1) + case(1,-1)" 30047 30048 # Start game. 30049 do 30050 30051 # Initialize game. 30052 if !narg($visu) 30053 {board,[w,h]*$R},1,3,64 30054 repeat h#$board,y repeat w#$board,x 30055 val={board,i($x,$y)} if $val j. [token{$val-1}],{$x*$R},{$y*$R},0,0,1,[tokenm],255 fi 30056 done done 30057 +r[cache,cachem] {board,[w,h]*$R},1,100%,0,2 a[-2,-1] c blend[-2,-1] alpha 30058 nm. visu w[visu] 100%,100%,0,"[G'MIC] Connect Four" 30059 turn=0 is_falling=0 x=-1 yv=0 dyv=0 winner= 30060 autoplayer0=0 autoplayer1=0 30061 fi 30062 30063 # Estimate ymax for each column. 30064 if !narg($ymax) 30065 {board,w},1,1,1,"y = -1; repeat (h#"$board",k, if(!i(#"$board",x,k),y = k)); y" nm. ymax 30066 if iM<0 winner=-1,-1,-1 fi # Draw game 30067 fi 30068 30069 if narg($winner) # End of game animation 30070 [visu] nm. tmpvisu 30071 x={arg(1,$winner)} y={arg(2,$winner)} c={arg(3,$winner)} 30072 if $x<0 # Draw game 30073 if !narg($text) 30074 0 t. "Draw game",0,0,57,1,1 r2dx. {tmpvisu,w/2} expand_xy. 3,0 +dilate. 5 n.. 0,255 to_rgb.. 30075 nm[-2,-1] text,textm 30076 fi 30077 j[tmpvisu] [text],{tmpvisu,([w,h]-[w#$text,h#$text])/2},0,0,{0.7+0.3*sin(5*$|)},[textm] 30078 else 30079 repeat 4 30080 [token$turn] 30081 rgb2hsv. sh. 1,2 +. {0.4*sin(5*$|)} c. 0,1 rm. hsv2rgb. 30082 j. [cache],0,0,0,0,1,[cachem],255 30083 j[tmpvisu] .,{$R*[$x,$y]},0,0,1 rm. 30084 x+={$c!=2?1:0} y+={$c==1?0:$c==4?-1:1} 30085 done 30086 fi 30087 w[tmpvisu] 100%,100% rm[tmpvisu] wait 20 30088 30089 if {*,-SPACE}" || "{*,-ENTER} # Restart new game 30090 rm[visu,ymax] f[board] 0 winner= 30091 fi 30092 30093 elif !$is_falling # Manage column selection 30094 30095 if !${autoplayer$turn} 30096 x={visu,X={*,x};X<0?X:int(X*w#$board/w)} 30097 yM={i("#"$ymax,$x)} 30098 if {board,$x<0" || "$x>=w} w[visu] 100%,100% 30099 else 30100 [visu] $R,100%,1,3,($yM>=0?1:0)*($turn?[255,255,0]:[255,0,0]) 30101 j.. .,{$x*$R},0,0,0,{$yM>=0?0.15:0.3} rm. 30102 w. 100%,100% rm. 30103 fi 30104 wait 30105 fi 30106 30107 if {*,-b}&1" && "$yM>=0" && "$x>=0 is_falling=1 yv=0 dyv=1 # Manual play 30108 elif ${autoplayer$turn}" || "{*,-SPACE}" || "{*,ENTER} # Computer play 30109 if {*,-ENTER} autoplayer$turn=1 fi 30110 max_score=-inf max_col= 30111 repeat w#$board,move1 30112 yM1={i("#"$ymax,$move1)} 30113 if $yM1>=0 30114 +=[board] {1+$turn},$move1,$yM1 nm. board1 30115 {board,w},1,1,1,"y = -1; repeat (h#"$board1",k, if(!i(#"$board1",x,k),y = k)); y" nm. ymax1 30116 opp_max_score=-inf opp_max_board={board,^} 30117 opp_turn={($turn+1)%2} 30118 repeat w#$board,move2 30119 yM2={i("#"$ymax1,$move2)} 30120 if $yM2>=0 30121 +=[board1] {1+$opp_turn},$move2,$yM2 30122 +f. "const p = 1 + "$opp_turn"; "$evalf score={is+u} rm. 30123 if $score>$opp_max_score opp_max_score=$score opp_max_board={^} fi 30124 rm. 30125 fi 30126 done 30127 rm[board1,ymax1] 30128 30129 {board,[w,h,1,1]},$opp_max_board 30130 f. "const p = 1 + "$turn"; "$evalf score={is+u} rm. 30131 if $score>$max_score max_score=$score max_col=$move1 fi 30132 fi 30133 done 30134 x=$max_col is_falling=1 yv=0 dyv=1 30135 fi 30136 30137 else # Manage token falling animation 30138 if !narg($column) 30139 $R,{board,h*$R},1,3,64 30140 repeat h#$board v={board,i($x,$>)} if $v j. [token{$v-1}],0,{$>*$R},0,0,1,[tokenm],255 fi done 30141 nm. column 30142 fi 30143 30144 yM={i("#"$ymax,$x)} 30145 [column] 30146 j. [token$turn],0,$yv,0,0,1,[tokenm],255 30147 j. [cache],0,0,0,0,1,[cachem],255 30148 [visu] nm. tmpvisu 30149 j[tmpvisu] ..,{$R*$x},0,0,0 rm.. w[tmpvisu] 100%,100% 30150 if $yv>=$yM*$R 30151 j[visu] [tmpvisu] is_falling=0 30152 =[board] {$turn+1},$x,$yM 30153 rm[ymax,column] 30154 30155 # Check end of game. 30156 +f[board] "if (!i,0, 30157 case_h = i==j(1) && i==j(2) && i==j(3); 30158 case_v = i==j(0,1) && i==j(0,2) && i==j(0,3); 30159 case_d1 = i==j(1,1) && i==j(2,2) && i==j(3,3); 30160 case_d2 = i==j(1,-1) && i==j(2,-2) && i==j(3,-3); 30161 case_h?1:case_v?2:case_d1?3:case_d2?4)" 30162 if iM winner={[xM,yM,i(xM,yM)]} # Player won ! 30163 else turn={($turn+1)%2} 30164 fi 30165 rm. 30166 fi 30167 rm[tmpvisu] 30168 yv={min($yM*$R,$yv+$dyv)} dyv+={visu,h/100} 30169 wait 20 30170 fi 30171 30172 while {*}" && "!{*,ESC}" && "!{*,Q} 30173 rm w 0 endl 30174 30175#@cli xz : eq. to 'x_crop' 30176xz : 30177 _gmic_s="$?" v + _x_crop 30178 30179#@cli x_crop 30180#@cli : Crop selected images interactively. 30181#@cli : (eq. to 'xz'). 30182x_crop : 30183 _gmic_s="$?" v + _$0 30184 30185_x_crop : 30186 e[0--3] "Crop image"$_gmic_s" interactively." 30187 repeat $! l[$>] 30188 w ${"fitscreen "{[w,h,d]}},1,"[G'MIC] "{n}" - Interactive crop" 30189 +select 2,{round([w,h,d]/2)},0,1 u={^} z.. $u rm. 30190 w[] 0 is_change 30191 endl done u $u 30192 30193#@cli x_cut 30194#@cli : Cut selected images interactively. 30195x_cut : 30196 e[^-1] "Cut image"$_gmic_s" interactively." 30197 repeat $! l[$>] 30198 wsiz0=${"fitscreen ."} 30199 value0,value1=-1,-1 30200 w[] $wsiz0,0,"[G'MIC] "{n}" - Interactive cut" 30201 0 30202 for {*}" && "!{*,ESC} 30203 30204 if [w#1,h#1]!=[{*,w,h}] # Generate image view 30205 rm[1] +slices[0] 50% r. {*,w,h},1,100%,1 w. 30206 fi 30207 30208 mx,my,mb={*,x,y,b} 30209 if $mb" && "$mx>=0" && "$my>=0 30210 value0,value1={"dw1 = "{*,w}" - 1; value0 = "$mx"*100/dw1; 30211 dh1 = "{*,h}" - 1; value1 = "$my"*100/dh1; 30212 [ value0,value1 ];"} 30213 update_view=1 30214 fi 30215 30216 if $update_view 30217 if $value0>=0" && "$value1>=0 30218 +c[1] $value0%,$value1% n. 0,255 30219 to. "Min: "{_round($value0,0.1)}%"\n"\ 30220 "Max: "{_round($value1,0.1)}%,1%,1%,{max(13,3.5*h%)} 30221 w. rm. 30222 else w. 30223 fi 30224 update_view=0 30225 fi 30226 30227 wait 30228 if {*,r} update_view=1 fi 30229 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} 30230 w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 update_view=1 30231 fi 30232 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} 30233 w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 update_view=1 30234 fi 30235 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} 30236 w[] $wsiz0 wait -1 update_view=1 30237 fi 30238 done 30239 w[] 0 rm. u $value0%,$value1% c ${} 30240 endl done 30241 30242#@cli x_fire 30243#@cli : Launch the fire effect demo. 30244x_fire : skip "${1=G\47MIC}" check_display $0 30245 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30246 e[] "\n 30247------ "${g}"Fire effect"$n" ------------------------\n 30248----\n 30249---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 30250---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 30251---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30252----\n 30253-------------------------------------------" 30254 30255 # Init image data. 30256 i[0] 100,32 w[0] {[4.5*w,6.75*h]},0,"[G"{`39`}"MIC] Fire Effect" 30257 if {*,w}<0.5*{*,u} w[] {[{*,w},{*,h}]*1.5} fi 30258 i[1] (0,255,255,255,255^0,0,255,255,255^0,0,0,128,255) r[1] 256,1,1,3,3 30259 i[2] (0,0,0;0,0,0;1,1,1;0,1,0) *[2] 0.21 30260 text3d "$1",33,3,1 30261 mv. 3 c3d[3] n3d[3] *3d[3] 320 col3d[3] 255,205,130 db3d 0 f3d 300 30262 100,100 rand. 0,255 ellipse. 50%,50%,5,5,0,1,300 b. 10 30263 sharpen. 1000 shrink_xy. 1 n. 0,255 to_rgb. light3d . rm. 30264 30265 # Start animation loop. 30266 angle=0 30267 do 30268 correlate[0] [2] # Apply fire effect. 30269 {0,w},1 rand. 128,256 j[0] .,0,{{0,h}-1} rm. # Add new random values at the bottom line. 30270 +r[0] 400,200,1,1,3 map. [1] # Map fire palette 30271 +r3d[3] 0,1,0,$angle j3d.. .,50%,50%,0,1,5,0,0 # Draw 3D object. 30272 *3d. 0.25,0.16,1 j3d[0] .,50%,50%,0,1,3,0,0 30273 rm. 30274 angle+=3 # Update 3D angle. 30275 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-22},16,1,0.2 fi 30276 w. 30277 if {*,CTRLLEFT}" && "{*,D} w[] {1.5*[w,h]} elif {*,CTRLLEFT}" && "{*,C} w[] {[w,h]} fi 30278 rm. wait 40 30279 while {*}" && "!{*,ESC}" && "!{*,Q} 30280 30281 # Exit properly. 30282 rm[0-3] w 0 30283 30284#@cli x_fireworks 30285#@cli : Launch the fireworks demo. 30286x_fireworks : check_display $0 30287 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30288 e[] "\n 30289------ "${g}"Fireworks"$n" --------------------------\n 30290----\n 30291---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 30292---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 30293---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30294----\n 30295--------------------------------------------" 30296 l[] 30297 (16;64^64;32^128;32) r 320,160,1,3,3 # [-2] = Background (color gradient). 30298 . # [-1] = Rendered image. 30299 w. {1.5*w},{1.5*h},0,"[G"{`39`}"MIC] Fireworks" # Display window. 30300 time=0 30301 do # Start animation loop. 30302 time-=1 30303 if $!==2\ ||\ $time<0 # Insert new rocket. 30304 i[0] ({u(w)},\ # X-position 30305 {h},\ # Y-position 30306 {u(-3,3)},\ # X-velocity 30307 {u(2)-5},\ # Y-velocity 30308 {30+u(20)},\ # Time of explosion 30309 1.5,\ # Radius 30310 255,255,255) # Color 30311 time={u(20)} # Elapsed time until next rocket. 30312 fi 30313 *. 0.99 # Create fading effect with previous frames. 30314 j. ..,0,0,0,0,0.2 # Add background. 30315 i=0 30316 repeat $!-2 30317 to_be_removed=0 30318 radius={if({$i,@4}>0,{$i,@5}/3,{$i,@5}*(1+2*({$i,@4}+2)/120))} 30319 ellipse. {$i,@0},{$i,@1},{$i,@5},{max(1,$radius)},{atan2({$i,@3},{$i,@2})*180/pi},0.6,{$i,@6-8} # Draw rocket. 30320 ({$i,@2},{$i,@3},0,0.09,-1,0,0,0,0) +[$i,-1] # Compute new position of the rocket. 30321 if {$i,@0}<0\ ||\ {$i,@0}>=w\ ||\ {$i,@1}>=h\ ||\ $radius<0 to_be_removed=1 fi # Discard if rocket disappear. 30322 if {$i,@4}<0\ &&\ {$i,@4}>=-1 # In case of explosion -> Split current rocket into several colorful rockets. 30323 color={min(255,80+u(200))},{min(255,80+u(200))},{min(255,80+u(200))} 30324 radius={u(10)} 30325 N={5+u(10)} 30326 repeat $N 30327 angle={$>*2*pi/$N} 30328 i... ({$i,@0,1},{2*cos($angle)+{$i,@2}/1.5},{2*sin($angle)+{$i,@3}/1.5},-2,$radius,$color) 30329 done 30330 to_be_removed=1 30331 fi 30332 if $to_be_removed rm[$i] else i+=1 fi # If processed rocket has to be removed. 30333 done 30334 fps=${-fps} if $fps>0 to. $fps" fps",3,{h-20},14,1,0.2 fi 30335 w. wait 20 # Display rendered frame. 30336 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 30337 while {*}" && "!{*,ESC}" && "!{*,Q} 30338 rm w 0 endl 30339 30340#@cli x_fisheye 30341#@cli : Launch the fish-eye effect demo. 30342x_fisheye : check_display $0 30343 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30344 e[] "\n 30345------ "${g}"Fish-eye effect"$n" --------------------\n 30346----\n 30347---- "${c}"Mouse pointer"$n" moves fish-eye center.\n 30348---- "${c}"Mouse buttons"$n" set fish-eye size.\n 30349---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 30350---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 30351---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30352----\n 30353-------------------------------------------" 30354 30355 if $!>0 a x n 0,255 r2dy 220 else 30356 120,90,1,3 rand. 0,255 plasma. 0.3,3 n 0,255 30357 t " G\47MIC\nFISH-EYE\n EFFECT",20,13,23,1,255 scale3x b 5 sharpen 1000 30358 f i+150-3*abs(y-h/2) c. 0,255 frame_fuzzy. 15,10,15,1.5,0 to_rgb. 30359 fi 30360 torus3d 20,6 col3d. {u(30,255)},{u(30,255)},{u(30,255)} +r3d. 1,0,0,90 30361 col3d. {u(30,255)},{u(30,255)},{u(30,255)} +3d. 15 +3d[-2,-1] *3d. 4 db3d 0 c3d. 30362 R=30 30363 w.. {1.25*{-2,w}},{1.25*{-2,h}},0,"[G"{`39`}"MIC] Fish-Eye Effect" 30364 do 30365 wait 40 30366 if {*,b}==1 R={min(80,$R+8)} fi 30367 if {*,b}==2 R={max(3,$R-8)} fi 30368 +j3d.. .,{50+30*cos($|*2.5)}%,{50+30*sin($|*1.6)}%,{80+230*sin($|*2.6)},0.7,3,0,0 r3d.. 1,0.2,0.6,3 30369 if {*,x}>=0 30370 fisheye. {{*,x}*100/{*,w}},{{*,y}*100/{*,h}},$R 30371 fi 30372 w. 30373 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 30374 rm. 30375 if {*}==0" || "{*,ESC}" || "{*,Q} rm[-2,-1] w 0 return fi 30376 while 1 30377 30378#@cli x_fourier 30379#@cli : Launch the fourier filtering demo. 30380x_fourier : check_display $0 30381 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30382 e[] "\n 30383------ "${g}"Fourier-filtering"$n" ----------------------------------------\n 30384----\n 30385---- "${c}"Mouse buttons"$n" on the right image to set min/max frequencies.\n 30386---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 30387---- Keys '"${c}"CTRL+C"$n"' to decrease window size.\n 30388---- Keys '"${c}"CTRL+R"$n"' to reset window size.\n 30389---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30390----\n 30391-----------------------------------------------------------------" 30392 30393 if !$! sp ? r2dx 400 fi 30394 30395 repeat $! l[$>] 30396 30397 # Init variables. 30398 need_update=1 # need_update (boolean) 30399 freqmin=0 # min freq. (in %) 30400 freqmax=100 # max freq. (in %) 30401 30402 if w>3*{*,u}/5 r2dx. {3*{*,u}/10} fi # Reduce image size if necessary. 30403 if h>3*{*,v}/5 r2dy. {3*{*,v}/5} fi 30404 30405 # Compute fourier transform. 30406 +fft. nm.. real nm. imag 30407 30408 # Generate log-magnitude image. 30409 +sqr[real,imag] +[-2,-1] sqrt. +. 1 log. 30410 n. 0,255 shift. {round(w/2)},{round(h/2)},0,0,2 to_colormode. {-2,s} 30411 nm. logmag 30412 30413 +r2dy. 128 frame. 1,1,0 nm. thumb 30414 w[0,-2] -1,-1,0,"[G"{`39`}"MIC] Fourier Filtering" 30415 30416 l 30417 if !narg($first_time) 30418 parallel 0,"alert[thumb] \"[G"{`39`}"MIC Fourier Filtering]\",\ 30419 \"The G\47MIC Fourier filtering demo illustrates the effect\n\ 30420 of bandpass frequency filtering on an image. Use your mouse\n\ 30421 buttons to select low and high bounds for the frequencies\n\ 30422 displayed on the Fourier representation of the image\n\ 30423 (right image).\",\ 30424 \"OK\"" 30425 first_time=0 30426 fi 30427 30428 # Enter user event-loop. 30429 do 30430 30431 if $need_update # If image must be updated. 30432 30433 # Generated filtering mask. 30434 [logmag],[logmag] nm. mask 30435 r={sqrt(w^2+h^2)*$freqmax/200} ellipse[mask] 50%,50%,$r,$r,0,1,1 30436 r={max(0,sqrt(w^2+h^2)*$freqmin/200-1)} if $r ellipse[mask] 50%,50%,$r,$r,0,1,0 fi 30437 30438 # Compute filtered log-magnitude. 30439 +*[logmag] [mask] +. [mask] /. 2 n. 0,255 30440 30441 # Compute filtered fourier representation. 30442 shift[mask] -{mask,round(w/2)},-{mask,round(h/2)},0,0,2 30443 +*[real,imag] [mask] 30444 rm[mask] 30445 30446 # Compute filtered image by inverse fourier. 30447 ifft[-2,-1] rm. n. 0,255 30448 30449 # Display filtered image. 30450 rv[-2,-1] 30451 if {*} r[-2,-1] {{*,w}/2},{*,h} fi 30452 t. "Freq. Min/Max = "{int($freqmin)}"% / "{int($freqmax)}"%",5,5,13,1,255 30453 w[-2,-1] rm[-2,-1] 30454 need_update=0 30455 30456 fi 30457 30458 wait 30459 30460 if {*,b}" && "{*,x}>={*,w}/2 # If mouse button pressed on the right pane. 30461 r={200*sqrt(({*,x}-3*{*,w}/4)^2+({*,y}-{*,h}/2)^2)/\ # Compute selected radius (in %). 30462 sqrt(({*,w}/2)^2+{*,h}^2)} 30463 if {*,b}&1 freqmax=$r # Update max freq. if left button. 30464 else freqmin={max(0,$r-3)} # Update min freq. if other button. 30465 fi 30466 if $freqmin>=$freqmax freqmin=$freqmax fi # Check that the min/max freq. are ordered. 30467 need_update=1 # Tell that the image must be updated. 30468 fi 30469 30470 if {*,r} need_update=1 fi 30471 30472 # Increase window size. 30473 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} need_update=1 fi 30474 30475 # Decrease window size. 30476 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} need_update=1 fi 30477 30478 # Reset window size. 30479 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {2*{0,w}},{0,h} need_update=1 fi 30480 30481 while {*}" && "!{*,ESC}" && "!{*,Q} 30482 w 0 30483 endl 30484 rm[^0] # Clean images and window. 30485 endl done rm 30486 30487#@cli x_grab_color : _variable_name 30488#@cli : Open a color grabber widget from the first selected image. 30489#@cli : Argument 'variable_name' specifies the variable that contains the selected color values at any time. 30490#@cli : Assigning '-1' to it forces the interactive window to close. 30491#@cli : Default values: 'variable_name=xgc_variable'. 30492x_grab_color : skip ${1=xgc_variable} check_display $0 30493 if !$! error[0--3] "Command '$0': Missing specified input image." fi 30494 l[0] nm={n} nm. img 30495 e[^-1] "Open "${arg\ {0,s},GRAY,GRAYA,RGB,RGBA}" color grabber widget for image$?, with variable name '$1'." 30496 30497 if !{*} w[] ${fitscreen[]\ {[w,h,1]},128,50%},0,0,-1,-1,"Grab a color" fi 30498 _x_grab_color +dilate. 3 nm. icon_mask *.. 255 to_rgb.. nm.. icon_sprite 30499 30500 xc=5 yc=5 o$1=$$1 30501 30502 cursor[0] 0 30503 do 30504 if !narg($visu0) 30505 +r[img] {*,w},{*,h},1,100%,2 drgba. w. nm. visu0 30506 fi 30507 30508 x={*,x} y={*,y} b={*,b} mouse_over={$x>=0" && "$y>=0} 30509 hc={narg($$1)?40:24} 30510 yc={visu0,nhc=h-$hc-8;!$mouse_over?$yc:$y<$hc||$yc+$hc>=h?nhc:$y>=nhc?5:$yc} 30511 30512 if [0$ox,0$oy,0$ob,0$ohc,0$oyc,0$ocolor,0${o$1}]!=[$x,$y,$b,$hc,$yc,0$color,0$$1] 30513 [visu0] nm. visu 30514 if narg($color) 30515 24,$hc,1,[img] fc. $color 30516 if narg($$1) rectangle. 0,24,100%,100%,1,$$1 line. 0,24,100%,24,1,0 fi 30517 drgba. frame. 1,1,0 frame. 1,1,255 j[visu] .,$xc,$yc rm. 30518 0 30519 if narg($$1) 30520 t. "Position ("$X","$Y")\nColor ("{``$color}")\nSelected ("{``$$1}")",1,0,15,1,255 30521 else 30522 t. "Position ("$X","$Y")\nColor ("{``$color}")",1,0,15,1,255 30523 fi 30524 +dilate. 5 r.. 100%,100%,1,3 30525 j[visu] ..,{30+$xc},$yc,0,0,0.85,.,255 rm[-2,-1] 30526 fi 30527 30528 if $mouse_over 30529 X={img,round($x*(w-1)/({*,w}-1))} 30530 Y={img,round($y*(h-1)/({*,h}-1))} 30531 color={img,round(I($X,$Y))} 30532 j[visu] [icon_sprite],$x,{icon_sprite,$y-h+1},0,0,1,[icon_mask] 30533 if $b&1 $1=$color fi 30534 fi 30535 w[visu] rm[visu] 30536 30537 ox=$x oy=$y ob=$b ohc=$hc oyc=$yc ocolor=$color o$1=$$1 30538 fi 30539 30540 if arg(1,{'$1'})==_'_'" && "arg(2,{'$1'})==_'_' wait 50 else wait fi 30541 if {*,r} w[] -1 rm[visu0] yc=5 fi 30542 if ['$$1']=='-1' break fi # Close request 30543 30544 while {*}" && "!{*,ESC}" && "!{*,Q} 30545 w 0 k[img] nm $nm endl 30546 u $color 30547 30548# Define color grabber icon. 30549_x_grab_color : 30550 base642img[] \ 30551"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMSAzMzcgMSAxICMyNzcKeJyNiNlOwlAYBi9IDDcaY+LGpiJbj7tBKEbglTQE7dcbkZS1gfNXFCx"\ 30552"lK6WE83w+gDaaeG0mmWTm67NSea5s1Pz6Ot80tnrb/d3BnhkYBq3QKDyOTA5nmfqDnW2W5nK77Mj60yLXgZvrqm6Oq47MYWc4ZhnCJE2wrgjmBWFwRm"\ 30553"r/hNQ3ZqivKQIlCN0YQZdeQGgxzXOD1T3XWEMhVWMtz1Wmw4h1QHEOShogqQc67YPOBwpdmgpdWzDSY9DNFJS1wWUH/NZF926FTl4oel48tgui3C6KU"\ 30554"rMo7rWCYCvJg4k/fvp/5/dJq9QyuUy48UXMOZ5H7ah9ND2YRMbhUXgUsoLDgOnxsf++0/TX1zRf1fcNa0iPgw==" 30555 -. 127 decompress_rle. 30556 frame. 10,10,0 30557 r2dx. 24 30558 30559#@cli x_hanoi 30560#@cli : Launch the Tower of Hanoi game. 30561x_hanoi : check_display $0 30562 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30563 e[] "\n 30564------ "${g}"Tower of Hanoï"$n" ---------------------\n 30565----\n 30566---- "${c}"Left button"$n" and "${c}"mouse"$n" to move a disk.\n 30567---- "${c}"Right button"$n" to rotate 3D view.\n 30568---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 30569---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 30570---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30571----\n 30572-------------------------------------------" 30573 l[] 30574 l[] # Create 3D rods 30575 cylinder3d 1,10 r3d 1,0,0,90 30576 ++3d 10,0,0 +-3d.. 10,0,0 30577 box3d 30,1,10 -3d. 15,0,5 30578 +3d nm rods3d 30579 400,400 noise. 1 fftpolar. f.. 'r=sqrt((x-w/2)^2+.01*(y-h/2)^2);i/(1+r)' ifftpolar[-2,-1] n. 0,31 30580 (86,50,50;132,36,12;218,109,66;231,207,180;255,193,140) permute. yzcx r. 32,1,1,3,3 30581 map.. . rm. b. 2% b. x,1% sharpen. 100 c. 0,255 30582 r3d.. 1,0,0,-90 texturize3d.. . r3d.. 1,0,0,90 rm. 30583 endl 30584 30585 l[] # Create 3D disks 30586 6,1,1,3,'[360*x/w,0.9*(1-(x/w)^0.5),0.9]' hsi2rgb. 30587 ytop0=0 30588 repeat w#0 30589 R,r={3-0.3*$>},{1.6-0.22*$>} 30590 torus3d $R,$r,36,10 30591 300,300 plasma. 1,1,3 b. 20 sharpen. 300 n. 150,255 1,1,1,3,{0,I[$>]} r. ..,..,1,3 rv[-2,-1] blend[-2,-1] 30592 luminance,0.75 # Marble texture 30593 texturize3d.. . rm. 30594 /3d. 1,1,{0.3+$r} r3d. 1,0,0,90 -3d. 0,0.8,0 30595 a$>,x$>,y$>,h$>=0,0,$ytop0,{1.8*$r/(0.3+$r)} 30596 ytop0+=${h$>} 30597 nm. disk3d$> 30598 done 30599 rm[0] 30600 endl 30601 30602 w[] 640,400,0,"[G"{`39`}"MIC] Tower of Hano\357" 30603 1,3,1,3,'y==0?[32,128,100]:y==1?[64,16,0]:[0,0,0]' r. {*,w},{*,h},1,3,3 nm. background 30604 nb_moves,buttons,motion3d_x,motion3d_y=0 30605 x,rod,rod_source,rod_target,selected=-1 30606 fading=$| error=0 30607 do 30608 30609 # Display 3D view for current game state. 30610 repeat 6 +r3d[disk3d$>] 1,1,1,${a$>} +3d. {10*(${x$>}-1)},-${y$>},0 done +3d[-6--1] +3d. [rods3d] 30611 r3d. 1,0,0,20 30612 if !($buttons&2) r3d. 0,1,0.3,{5*cos(1.5*$|)} r3d. 0.3,0,1,{3*sin(0.8*$|)} fi 30613 r3d. 1,0,0,$motion3d_y r3d. 0,-1,0,$motion3d_x *3d. 20 30614 [background] j3d. ..,50%,70%,10,1,5,0,1,800,200,0,-3000,0.15,0.2 30615 t. "#Moves: "$nb_moves,2%,92%,20,1,255 30616 30617 if $error (255^0^0) ri. .. j.. .,0,0,0,0,$error error={max(0,$error-0.2)} rm. fi 30618 if $|-$fading<1 *. {$|-$fading} fi 30619 w. wait 40 30620 if {*,CTRLLEFT}" && "{*,D} w[] {w*1.5},{h*1.5} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 30621 rm[-2,-1] 30622 30623 # Get index of top disk for each rod. 30624 top0,top1,top2,ytop0,ytop1,ytop2=-1 30625 repeat 6 30626 rod={round(${x$>})} 30627 if $selected!=$>" && "${y$>}+${h$>}>${ytop$rod} ytop$rod={${y$>}+${h$>}} top$rod=$> fi 30628 done 30629 30630 # Manage user events. 30631 prev_buttons=$buttons 30632 mouse_x,mouse_y,buttons={*,x},{*,y},{*,b} 30633 if $mouse_x>=0 x={2.6*($mouse_x/{*,w}-0.5)+1} rod={round($x)} fi 30634 30635 if $mouse_x>=0" && "$buttons&2 # Right mouse button 30636 motion3d_x,motion3d_y={([$mouse_x,$mouse_y]/[{*,w},{*,h}]-0.5)*90} 30637 30638 elif $mouse_x>=0" && "$buttons&1 # Left mouse button 30639 if $selected<0 # Select a disk 30640 selected=${top$rod} 30641 rod_source={$selected<0?-1:$rod} 30642 fi 30643 if $selected>=0" && "$rod>=0 # Move a selected disk 30644 if ${y$selected}<11 y$selected={min(11,${y$selected}+3)} 30645 else 30646 x$selected+={d=$rod-${x$selected};sign(d)*min(0.3,abs(d))} 30647 y$selected={x=${x$selected};11+1.5*sin(pi*abs(x-round(x)))} 30648 a$selected={x=${x$selected};45*sin(pi*abs(x-round(x)))} 30649 fi 30650 fi 30651 30652 elif !$buttons # No mouse button 30653 if $rod>=0" && "$selected>=0 30654 if $rod_target<0 30655 if ${top$rod}<$selected rod_target=$rod nb_moves+={$rod_target!=$rod_source} # Allowed move 30656 else rod_target=$rod_source error=0.8 # Forbidden move 30657 fi 30658 fi 30659 x$selected=$rod_target 30660 a$selected=0 30661 ytop={max(0,${ytop$rod_target})} 30662 if ${y$selected}>$ytop y$selected={max($ytop,${y$selected}-3)} 30663 else x,rod,rod_source,rod_target,selected=-1 30664 fi 30665 fi 30666 fi 30667 30668 if !($buttons&2) # Slowly go back to initial 3D view 30669 motion3d_x-={sign($motion3d_x)*min(1,abs($motion3d_x))} 30670 motion3d_y-={sign($motion3d_y)*min(1,abs($motion3d_y))} 30671 fi 30672 30673 while {*}" && "!{*,ESC}" && "!{*,Q} 30674 w[] 0 rm endl 30675 30676#@cli x_histogram 30677#@cli : Launch the histogram demo. 30678x_histogram : check_display $0 30679 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30680 e[] "\n 30681------ "${g}"Histogram demo"$n" -------------------------------\n 30682----\n 30683---- "${c}"Mouse"$n" to set parameters.\n 30684---- "${c}"Right button"$n" or key '"${c}"SPACE"$n"' to reset.\n 30685---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30686----\n 30687-----------------------------------------------------" 30688 30689 if !$! sp ? to_rgb 30690 else k[0] to_rgb r2dy 300,2 if w>800 r 800,100%,1,3,2 fi n 0,255 30691 fi 30692 30693 # Prepare image layout. 30694 +frame. 1,1,0 30695 300,{h},1,3,220 30696 30697 t. "Gamma :",5,0,16,1,0 30698 t. "Contrast :",5,50,16,1,0 30699 t. "Brightness :",5,100,16,1,0 30700 t. "Smoothness :",5,150,16,1,0 30701 t. "Sharpness :",5,200,16,1,0 30702 t. "Clusters :",5,250,16,1,0 30703 a[-2,-1] x 30704 {w},200,1,3,255 30705 grid. 10%,10%,0,0,0.3,0xCCCCCCCC,0 30706 rectangle. 0,0,100%,100%,1,0xFFFFFFFF,0 30707 axes. 0,255,1,0,13,1,0 30708 frame[-2,-1] 5,5,220 30709 a[-2,-1] y 30710 30711 # Initialize variables. 30712 clusters=64 sharpness=0 smoothness=0 contrast=1 brightness=0 gamma=1 30713 30714 # Start event loop. 30715 do 30716 30717 # Render corrected image and insert it in canvas. 30718 [0] 30719 ia={ia} 30720 if $gamma /. 255 ^. {1/$gamma} *. 255 fi 30721 -. $ia *. $contrast +. $brightness +. $ia 30722 b. $smoothness 30723 sharpen. $sharpness 30724 c. 0,255 30725 +j.. .,6,6 30726 30727 # Render parameter sliders. 30728 sx={{0,w}+12} 30729 _x_histogram. {$gamma*100/4} j.. .,$sx,25 rm. 30730 _x_histogram. {$contrast*100/4} j.. .,$sx,75 rm. 30731 _x_histogram. {($brightness+128)*100/256} j.. .,$sx,125 rm. 30732 _x_histogram. {$smoothness*100/10} j.. .,$sx,175 rm. 30733 _x_histogram. {$sharpness*100/2000} j.. .,$sx,225 rm. 30734 _x_histogram. {$clusters*100/256} j.. .,$sx,275 rm. 30735 30736 # Render corresponding histogram. 30737 +s.. c histogram[-3--1] $clusters,0,255 /[-3--1] {6*{0,wh}/$clusters} rm[-5] 30738 +z[-4] 5,{0,h+16},{{-4,w}-5},{{-4,h}-6} 30739 graph. [-4],3,0,1,0,0.2,255,0,0 30740 graph. ...,3,0,1,0,0.2,0,255,0 30741 graph. ..,3,0,1,0,0.2,0,0,255 30742 rm[-4--2] 30743 j.. .,5,{0,h+16} rm. 30744 30745 if {*,b}&1\ &&\ {*,x}<{0,w}\ &&\ {*,y}<{0,h} 30746 j. [0],6,6 to. Original,10,10,16 30747 fi 30748 30749 # Display rendering. 30750 w. {w},{h},0,"[G"{`39`}"MIC] Histogram Demo" rm. 30751 wait 30752 30753 # Manage user interactions. 30754 if {*,b}&1\ &&\ {*,x}>={0,w}-10 30755 if {*,y}>=25\ &&\ {*,y}<=42 30756 gamma={max(0,min(4,({*,x}-$sx)*4/280))} 30757 elif {*,y}>=75\ &&\ {*,y}<=92 30758 contrast={max(0,min(4,({*,x}-$sx)*4/280))} 30759 elif {*,y}>=125\ &&\ {*,y}<=142 30760 brightness={max(-128,min(128,({*,x}-$sx)*256/280-128))} 30761 elif {*,y}>=175\ &&\ {*,y}<=192 30762 smoothness={max(0,min(10,({*,x}-$sx)*10/280))} 30763 elif {*,y}>=225\ &&\ {*,y}<=242 30764 sharpness={max(0,min(2000,({*,x}-$sx)*2000/280))} 30765 elif {*,y}>=275\ &&\ {*,y}<=292 30766 clusters={max(2,min(256,({*,x}-$sx)*256/280))} 30767 fi 30768 fi 30769 if {*,b}&2\ ||\ {*,SPACE} clusters=64 sharpness=0 smoothness=0 contrast=1 brightness=0 gamma=1 fi 30770 while {*}" && "!{*,ESC}" && "!{*,Q} 30771 w 0 rm 30772 30773_x_histogram : 30774 val={max(0,min(100,$1))} 30775 280,2,1,3,255 line. 0,0,$val%,0,1,0,255,0 line. 0,1,$val%,1,1,240,255,62 r. 100%,16,1,3,3 30776 0 t. {round($val)}%,0,0,14,1,1 +*. -255 +. 255 r. 100%,100%,1,3 30777 j... .,{(280-w)/2},{(16-h)/2},0,0,1,.. rm[-2,-1] 30778 r. {w+2},{h+2},1,3,0,0,0.5,0.5 30779 30780#@cli x_hough 30781#@cli : Launch the hough transform demo. 30782x_hough : check_display $0 30783 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30784 e[] "\n 30785------ "${g}"Hough-transform"$n" -----------------------------------------\n 30786----\n 30787---- "${c}"Mouse buttons"$n" on the vote image to draw corresponding line.\n 30788---- "${c}"Mouse buttons"$n" on the image to vote for all lines crossing.\n 30789---- the clicked point.\n 30790---- Key '"${c}"SPACE"$n"' to reset the hough window.\n 30791---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30792----\n 30793-----------------------------------------------------------------" 30794 30795 if !$! l[] sp greece onfail testimage2d 400 endl fi 30796 n 0,255 30797 30798 repeat $! l[$>] 30799 r. ${fitscreen\ {[w,h]}},1,100%,3 # Resize to fit screen if necessary. 30800 if !narg($first_time) 30801 parallel 0,"+l[0] r2dy 128 frame 1,1,0 \ 30802 alert \"[G"{`39`}"MIC Hough Transform]\",\ 30803 \"The G\47MIC Hough transform demo illustrates the application\n\ 30804 of the Hough transform to detect lines in an image. Use your\n\ 30805 mouse buttons to explore the transform image and see how\n\ 30806 lines in images are represented by points in the transform.\",\ 30807 \"OK\" \ 30808 rm endl" 30809 first_time=0 30810 fi 30811 30812 rhomax={sqrt(w^2+h^2)/2} 30813 +b. 1.5 hough. 512,400 b. 0.5 +. 1 log. n. 0,255 30814 w.. -1,-1,0,"[G"{`39`}"MIC] Image" w1. -1,-1,0,"[G"{`39`}"MIC] Hough Transform" 30815 30816 do 30817 wait 30818 30819 if {*,b} # When clicking on the image. 30820 x0={{*,x}-{*,w}/2} 30821 y0={{*,y}-{*,h}/2} 30822 rho0={sqrt(($x0)^2+($y0)^2)} 30823 theta0={atan2($y0,$x0)} 30824 (0,{2*pi}) ($theta0,{$theta0-2*pi}) 30825 r[-2,-1] {-3,w},1,1,1,3 30826 cos. *. $rho0 +<. 0 abs.. 30827 *. {pi} +[-3,-1] %.. {2*pi} 30828 *.. {0.5*{-3,w}/pi} *. {{-3,h}/$rhomax} 30829 a[-2,-1] y 30830 repeat w point.. {i($>,0)},{i($>,1)},0,0.3,255 done 30831 rm. w1. 30832 30833 elif {*1,x}>=0" && "{*1,b} # When clicking on the vote window. 30834 theta={{*1,x}*2*pi/{*1,w}} 30835 rho={{*1,y}*$rhomax/{*1,h}} 30836 x={{-2,w}/2+$rho*cos($theta)} 30837 y={{-2,h}/2+$rho*sin($theta)} 30838 x0={$x+1000*sin($theta)} 30839 y0={$y-1000*cos($theta)} 30840 x1={$x-1000*sin($theta)} 30841 y1={$y+1000*cos($theta)} 30842 .. 30843 line. $x0,$y0,$x1,$y1,1,0x0F0F0F0F,255 30844 line. {$x0+1},$y0,$x1,$y1,1,0x0F0F0F0F,255 30845 line. $x0,{$y0+1},$x1,$y1,1,0x0F0F0F0F,255 30846 line. $x0,$y0,$x1,$y1,1,0xF0F0F0F0,0 30847 line. {$x0+1},$y0,$x1,$y1,1,0xF0F0F0F0,0 30848 line. $x0,{$y0+1},$x1,$y1,1,0xF0F0F0F0,0 30849 w. rm. 30850 30851 elif {*,SPACE}" || "{*1,SPACE} 30852 rm. +b. 1.5 hough. 512,400 b. 0.5 +. 1 log. n. 0,255 30853 w1. -1,-1,0,"Hough Transform" 30854 30855 elif {*,r} w.. 30856 elif {*1,r} w1. 30857 fi 30858 30859 while {*}" && "{*1}" && "!{*,ESC}" && "!{*,Q}" && "!{*1,ESC}" && "!{*1,Q} 30860 w 0 w1 0 30861 rm. endl 30862 if !{*}" || "!{*1} break fi 30863 done rm 30864 30865#@cli x_jawbreaker : 0<_width<20,0<_height<20,0<_balls<=8 30866#@cli : Launch the Jawbreaker game. 30867x_jawbreaker : check "${1=12}>0 && $1<20 && ${2=13}>0 && $2<20 && ${3=5}>0 && $3<=8" check_display $0 30868 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30869 e[] "\n 30870------ "${g}"Jawbreaker"$n" --------------------------------------------\n 30871----\n 30872---- The goal of the game is to "${c}"remove the maximum number of\n 30873---- balls on the board"$n", simply by clicking on them. But a\n 30874---- colored ball can disappear only if it is grouped with at\n 30875---- least one ball of the same color. The score is higher if\n 30876---- you destroy larger sets of connected colored balls.\n 30877----\n 30878---- "${c}"Left mouse button"$n" to select/destroy balls on board.\n 30879---- Key '"${c}"BACKSPACE"$n"' or '"${c}"SPACE"$n"' to undo the last move.\n 30880---- Key '"${c}"S"$n"' to save snapshot of the current view.\n 30881---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30882----\n 30883--------------------------------------------------------------" 30884 30885 # Init images and variables. 30886 $1,$2 nm. board rand[board] 1,$3 round[board] 1 30887 . nm. undo 30888 40,40,1,4 nm. balls _x_jawbreaker_ball. 30889 autocrop. 0 expand_xy. 1,0 *. 1.5 c. 0,255 r. {{board,w}*w},{{board,h}*h},1,1,0,2 /. 255 30890 {w},{h},1,3 nm. back l. 30891 rand 0,255 blur_xy 6,20 equalize 100,0,255 blur_xy 2,4 30892 sh 0 sh.. 1 sh... 2 /... 4 /.. 8 /. 2 rm[-3--1] 30893 endl 30894 [back] nm. visu 30895 score=0 30896 undoscore=0 30897 render_board=1 30898 shapescorey=0 30899 shapescore=0 30900 30901 # Enter user-event loop. 30902 do 30903 30904 # Render board graphics. 30905 if $render_board 30906 +abs[board] -. 1 *. {360/$3} +>=[board] 0 *. 0.9 +!=[board] 0 30907 ri[-3--1] [balls] [balls] *[-2,-1] a[-3--1] c hsv2rgb. 30908 +compose_channels. + >. 0 dilate. 3 30909 j[visu] [back] j[visu] ..,0,0,0,0,1,. rm[-2,-1] 30910 if !$shapescorey w[visu] {back,w},{back,h},0,"[G"{`39`}"MIC] Jawbreaker (Score : "$score")" fi 30911 render_board=0 30912 fi 30913 30914 # Add shape score sprite if necessary. 30915 if $shapescorey 30916 +t[visu] "+"$shapescore,{*,x},{{*,y}-64+$shapescorey},32,{($shapescorey-1)/31},255 30917 shapescorey={max(0,$shapescorey-1)} 30918 w. {back,w},{back,h},0,"[G"{`39`}"MIC] Jawbreaker (Score : "$score")" rm. wait 25 30919 else wait fi 30920 30921 # Check for the end of the game. 30922 +f[board] "if(i,j(-1)==i || j(1)==i || j(0,1)==i || j(0,-1)==i,0)" 30923 if !is rm. break fi rm. 30924 30925 # Manage user-events 30926 if {*,r} render_board=1 # Will resize window to initial size, if resized. 30927 elif {*,S} o[visu] gmic_jawbreaker.png # Save snapshot if requested. 30928 elif {*,BACKSPACE}" || "{*,SPACE} # Manage undo move. 30929 abs[undo] j[board] [undo] 30930 score=$undoscore 30931 render_board=1 30932 30933 elif {*,x}>=0" && "{*,b} # Manage button click. 30934 30935 # Retrieve board coordinates. 30936 wait -1 30937 x={"int("{*,x}"*"{board,w}"/"{*,w}")"} 30938 y={"int("{*,y}"*"{board,h}"/"{*,h}")"} 30939 30940 # When selecting a ball -> display selection and init new shape score sprite. 30941 if {{board,i($x,$y)}>0} 30942 abs[board] flood[board] $x,$y,0,0,0,1,-{board,i($x,$y)} 30943 +>=[board] 0 -. 1 30944 shapescore={(is+1)^2} shapescorey={if($shapescore,32,0)} rm. 30945 30946 # When confirming selection of a ball -> remove set of connected balls. 30947 elif {board,i($x,$y)} 30948 30949 +flood[board] $x,$y,0,0,0,1,-1 ==. -1 30950 if is>1 # If selected ball is connected to at least one ball. 30951 30952 # Save undo state. 30953 j[undo] [board] 30954 undoscore=$score 30955 30956 # Manage board shifts (vertical and horizontal). 30957 flood[board] $x,$y,0,0,0,1,0 30958 repeat w#$board 30959 +columns[board] $> mirror. y 30960 h={board,h} l. s -,0 a y if $! r 1,$h,1,1,0 mirror y else i 1,$h fi endl 30961 j[board] .,$> rm. 30962 done 30963 rows[board] -1,100% f[board] "if(y==0,if(i(x,h-1),x,w),i)" sort[board] +,x rows[board] 1,100% 30964 30965 # Update score. 30966 score+={int((is-1)^2)} 30967 30968 fi 30969 rm. # Remove selection mask. 30970 30971 else abs[board] # Remove previous selection if clicked outside balls. 30972 fi 30973 30974 render_board=1 30975 fi 30976 30977 while {*}" && "!{*,Q}" && "!{*,ESC} 30978 30979 # Game over. 30980 if {*}" && "!{*,ESC} 30981 w[] {visu,w},{visu,h},0,"[G"{`39`}"MIC] Jawbreaker (Final Score : "$score")" 30982 260,85 nm. gameover t. "Game Over!",3,0,53,1,1 t. "Score : "$score,23,53,32,1,1 30983 +dilate. 5 nm. "mgameover" *.. 255 r.. 100%,100%,1,3 30984 repeat 25 30985 +r[gameover,mgameover] {400-12*($>+1)}%,{400-12*($>+1)}% 30986 +j[visu] ..,{({visu,w}-w)/2},{({visu,h}-h)/2},0,0,{$>/25},. 30987 w. rm[-3--1] wait 25 30988 done 30989 do 30990 wait if {*,r} w[] {*,w},{*,h} wait -1 fi 30991 while {*}" && "!{*,Q}" && "!{*,ESC}" && "!{*,b} 30992 rm[gameover,mgameover] 30993 fi 30994 30995 # End properly. 30996 rm[board,undo,balls,back,visu] 30997 w 0 30998 30999_x_jawbreaker_ball : 31000 mwh={min(w,h)} 31001 sh 3 f. 0 rm. 31002 ellipse {0.5*$mwh},{0.5*$mwh},{0.5*$mwh-4},{0.5*$mwh-4},0,1,240,240,240,1 31003 sh 0,2 *. '($mwh+y-x)/(2*w)' rm. 31004 sh 3 *.. . dilate. 5 rm. 31005 sh 0,2 +. 'if(i&&(!j(-1)||!j(1)||!j(0,-1)||!j(0,1)),240/6,0)' rm. 31006 ellipse {$mwh*0.7},{$mwh*0.3},{min(30,$mwh*$mwh/512)},{min(30,$mwh*$mwh/512)},0,{min($mwh/64,1)},255,255,255,1 31007 31008#@cli x_landscape 31009#@cli : Launch the virtual landscape demo. 31010x_landscape : check_display $0 31011 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31012 e[] "\n 31013------ "${g}"Virtual landscape"$n" -------------------------------------\n 31014----\n 31015---- Enjoy the view!\n 31016----\n 31017---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 31018---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 31019---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31020----\n 31021--------------------------------------------------------------" 31022 l[] 31023 W=150 H=350 31024 31025 # Generate global map + colors. 31026 900,900 plasma. 1,1,6 b. 0.07% n. 0,255 nm. map 31027 +g. *. 0.5 +[-2,-1] n. 0,1 ^. 2 n. -150,330 31028 equalize[map] 256 n[map] -400,160 c[map] 0,100% # Add water. 31029 (0,102,51;149,175,124;102,42,0;255,255,255) permute. yzcx srgb2rgb. r. 256,1,1,3,3 rgb2srgb. 31030 +n[map] 0,255 map. .. rm.. 31031 +. .. rm.. c. 0,255 nm. colors # Colors. 31032 31033 # Pre-compute some images used on each frame. 31034 $W,$H,1,1,'x' y. x nm. x # Increasing x. 31035 $W,$H,1,1,'1+x+y*w' y. x nm. offsets # Offsets (+1). 31036 $W,$H,1,1,'0.5*y' nm. gmap Mgmap={iM} # Z-increment for altitude map. 31037 $W,$H,1,3 fc. 60,80,135 nm. ccolors # Color for the horizon. 31038 $W,$H,1,1,'(y/$H)^2' nm. mcolors # Mask for the horizon. 31039 $W,400,1,1,'b=h-1-$Mgmap;if(y>=b,256+(y-b)*255/(h-1-b),y*255/b)' round. # Background. 31040 31041 (96^16^128) (0^200^255) a[-2,-1] x r. 256,1,1,3,3 31042 (0^32^0) (0^64^128) a[-2,-1] x r. 256,1,1,3,3 31043 a[-2,-1] x map.. . rm. 31044 31045 nm. background 31046 quadrangle3d[] -0.45,0,0,0.45,0,0,0.55,1,0,-0.55,1,0 *3d. {$W/2},{$H/2} nm. viewrange3d # View range. 31047 (64^16^0) r. $W nm. groundcolor # Ground color. 31048 31049 # Start animation. 31050 w[] 600,400,0,"[G"{`39`}"MIC] Virtual Landscape" 31051 do 31052 31053 # Get part of the map to display. 31054 t={$|*0.03} 31055 xm={map,w/2+(w-$H/2)/2*cos(3.1*$t)} 31056 ym={map,h/2+(h-$H/2)/2*sin(2.8*$t)} 31057 u={map,(w-$H/2)*cos(2.5*$t)} 31058 v={map,(h-$H/2)*sin(9.7*$t)} 31059 a={atan2($v,$u)*180/pi} 31060 +r3d[viewrange3d] 0,0,1,$a y. x 31061 ({$xm+i[8]},{$xm+i[11]};{$xm+i[17]},{$xm+i[14]}^{$ym+i[9]},{$ym+i[12]};{$ym+i[18]},{$ym+i[15]}) rm.. 31062 r. $W,$H,1,2,3 +warp[map,colors] .,0,1,0 rm... 31063 nm.. lmap nm. lcolors 31064 31065 # Add color shading and altitude to local maps. 31066 +!=[lmap] 0 nm. ground 31067 +[lmap] [gmap] 31068 j[lcolors] [ccolors],0,0,0,0,1,[mcolors] 31069 j[lcolors] [groundcolor] 31070 +round[lmap] f. '>m=abs(j(0,-1));i>m?i:-m' nm. y0 # Compute visible top points. 31071 +shift. 0,1 abs. +. 1 nm. y1 # Compute visible bottom points. 31072 *[y0,y1] [ground] rm[ground] 31073 r[lcolors,y0,y1] {$W*$H},1,1,100%,-1 31074 31075 # Keep only visible primitives. 31076 +>[y0] 0 *. [offsets] discard. 0 y. 31077 if h # There is something to display (ground). 31078 -. 1 +warp[x] .,0,0,0 nm. lx 31079 warp[lcolors,y0,y1] ..,0,0,0 rm.. 31080 31081 # Generate 3D object. 31082 N={h} ({'CImg3d'},{2*$N},$N) 31083 +a[lx] [y0],x rm[y0] +a[lx] [y1],x rm[lx,y1] a[-2,-1] y z. 0,2 31084 1,$N,1,1,2 +f. y ++. $N a[-3--1] x 31085 mv[lcolors] $! permute. cyzx 31086 1,$N,1,1,1 31087 y[-5--1] y a[-5--1] y *3d. -1,-1 31088 +j3d[background] .,{background,w-1},{background,h},0,1,1,0,0,0 rm[-3,-2] 31089 else # Case of nothing to display (only water). 31090 rm[-5--1] [background] 31091 fi 31092 31093 r. {*,w},{*,h},1,3 31094 fps=${-fps} if $fps>0 to. $fps" fps",5,5,24,2,0.2 fi 31095 w. -1,-1,0 rm. 31096 if {*,CTRLLEFT}" && "{*,D} w[] 900,600 elif {*,CTRLLEFT}" && "{*,C} w[] 600,400 fi 31097 wait 20 31098 while {*}" && "!{*,ESC}" && "!{*,Q} 31099 rm w 0 endl 31100 31101#@cli x_life 31102#@cli : Launch the game of life. 31103x_life : check_display $0 31104 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31105 e[] "\n 31106------ "${g}"The game of life"$n" --------------------------------------\n 31107----\n 31108---- The goal is to create the "${c}"biggest possible biological\n 31109---- system"$n". You start with a stock of cells which you can\n 31110---- spread over the board. For each new cells created\n 31111---- simultaneously and spontaneously by your system, you\n 31112---- gain more new cells to scatter.\n 31113----\n 31114---- "${c}"Left mouse button"$n" to scatter cells in stock.\n 31115---- "${c}"Right mouse button"$n" to reset game.\n 31116---- Key '"${c}"S"$n"' to save snapshot of the current view.\n 31117---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31118----\n 31119--------------------------------------------------------------" 31120 31121 i[0] 90,90,1,1,0 # Image[0] = game state. 31122 i[1] [0] f[1] 0 # Image[1] = generation counter. 31123 i[2] 400,400,1,3 # Image[2] = visualization. 31124 i[3] 1 # Image[3] = colormap (to be initialized). 31125 iteration=0 # Iteration counter. 31126 score=0 # Current score. 31127 bestscore=0 # Best score. 31128 stock=500 # Remaining cells. 31129 w[0] 400,400,0,"[G"{`39`}"MIC] The Game of Life" # Initialize display window. 31130 cursor[0] 0 31131 31132 # Start user-event loop. 31133 do 31134 (1,1,1;1,0,1;1,1,1) +correlate[0] .,0 rm.. # Count numbers of neighboring living cells. 31135 +ir. 2,2 &. [0] ir.. 3,3 -|[-2,-1] # Make the game evolve (kill or create cells). 31136 rv[0,-1] # Update game state. 31137 if {*,x}>0" && "{*,b}==1" && "$stock>0 # Add random cells to the game if mouse button pressed. 31138 nb={u*7} 31139 repeat $nb 31140 x={{*,x}/{*,w}*{0,w}+u(-4,4)} 31141 y={{*,y}/{*,h}*{0,h}+u(-3,3)} 31142 =[0] 1,$x,$y 31143 =[1] $iteration,$x,$y 31144 point[2] {$x*{2,w}/{0,w}},{$y*{2,h}/{0,h}},0,0.8,255 31145 done 31146 stock={round(max(0,$stock-$nb))} 31147 fi 31148 31149 -. [0] *. -1 # Compute difference between consecutive states. 31150 stock-={2*(min(0,int(is/16*$score/150)))} # Increment available cells if the evolution is fast. 31151 +[1] [0] # Increment generation counter for still existing cells. 31152 min. 0 +. 1 *[1,-1] # Reset generation counter for died cells. 31153 31154 if {*,b}==2 # Reset game if right mouse button has been pressed. 31155 f[0-2] 0 iteration=0 score=0 bestscore=0 stock=500 rm[3] i[3] 1 31156 fi 31157 31158 if {3,w}==1 # Create color palette if necessary. 31159 rm[3] i[3] {u(3,12)},1,1,3,u(100,255) 31160 r[3] {u(100,300)}%,1,1,3,4 31161 point[3] 0,0,0,1,0 31162 r[3] {u(100,600)}%,1,1,3,5 c[3] 0,255 31163 fi 31164 31165 +r[1] {2,w},{2,h} &. 7 b. {1+$score*0.05} # Render colored image of the game and display it. 31166 n. 0,{3,w} map. [3] *. 0.1 +[2,-1] /[2] 1.1 31167 [2] if {*,x}>0 # Add a small target icon at the mouse position. 31168 opac={0.7*min(1,$stock/500)} r={min(500,$stock)*cos($iteration)/100} 31169 ellipse. {*,x},{*,y},{15+$r},{15+$r},0,$opac,0,196,0 31170 ellipse. {*,x},{*,y},{10+$r},{10+$r},0,$opac,32,64,16 31171 ellipse. {*,x},{*,y},{5+$r},{5+$r},0,$opac,255,230,0 31172 fi 31173 t. "Living cells : "$score"\n"\ # Add score description. 31174 "Stock : "$stock"\n"\ 31175 "Score : "$bestscore,5,3,22,0.7,255 31176 w. {*,w},{*,h} 31177 if {*,S} o. gmic_life.png fi # Save snapshot if requested. 31178 rm. 31179 31180 if !($iteration%10) # Re-compute current and best scores, every 10th iterations 31181 score={0,is} bestscore={max($score,$bestscore)} 31182 fi 31183 wait 60 31184 iteration+=1 31185 while {*}" && "!{*,ESC}" && "!{*,Q} 31186 31187 # End game and quit properly. 31188 rm[0-3] w 0 31189 31190#@cli x_light 31191#@cli : Launch the light effect demo. 31192x_light : check_display $0 31193 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31194 e[] "\n 31195------ "${g}"Light effect"$n" ------------------------\n 31196----\n 31197---- Move light position with "${c}"mouse"$n".\n 31198---- "${c}"Mouse buttons"$n" fade light in/out.\n 31199---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 31200---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 31201---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31202----\n 31203-------------------------------------------" 31204 31205 # Create warping and color images. 31206 0 t. " G\47MIC\nLight effect",0,0,80,1,255 expand_xy. 15,0 b. 3 31207 . n.. 0,1 r.. 100%,100%,1,3 31208 sh.. 0 *. 120 rm. 31209 sh.. 1 *. 70 rm. 31210 sh.. 0,50%,0,2 *. 120 rm. 31211 25%,25%,1,1 rand. -20,20 smooth. 10,0,1,1,4 ri. ..,3 b. 3 n. -100,100 31212 +[-2,-1] g. xy a[-2,-1] c n. -150,150 31213 w[] {1.5*{-2,w}},{1.5*{-2,h}},0,"[G"{`39`}"MIC] Light Effect" # Init display window. 31214 cursor[0] 0 31215 31216 # Create a large light image. 31217 light=70 31218 640,640 gaussian. $light n. 0,255 31219 t=0 31220 31221 # Start animation. 31222 do 31223 31224 # Manage light position and intensity. 31225 if {*,x}>=0 31226 X={round((w-{*,x})/2)} 31227 Y={round((h-{*,y})/2)} 31228 else 31229 X={round((w-{-2,w}*(1+cos(2*$t)))/2)} 31230 Y={round((h-{-2,h}*(1+sin(2.5*$t)))/2)} 31231 t+=0.02 31232 fi 31233 if {*,b}&1 light={min(200,$light+10)} gaussian. $light n. 0,255 fi 31234 if {*,b}&2 light={max(10,$light-10)} gaussian. $light n. 0,255 fi 31235 31236 # Render lightened image. 31237 +z. $X,$Y,{$X+{-2,w}-1},{$Y+{-2,h}-1} 31238 warp. ...,1,0,1 31239 r. 100%,100%,1,3 +. [-4] c. 0,255 31240 fps=${-fps} if $fps>0 to. $fps" fps",5,5,16,1,0.2 fi 31241 w. 31242 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 31243 rm. if {*,x}>=0" && "!{*,b} wait else wait 20 fi 31244 while {*}" && "!{*,ESC}" && "!{*,Q} 31245 w[] 0 rm[-3--1] 31246 31247#@cli x_mandelbrot : _julia={ 0 | 1 },_c0r,_c0i 31248#@cli : Launch Mandelbrot/Julia explorer. 31249x_mandelbrot : skip ${1=0},${2=0.317},${3=0.03} check_display $0 31250 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31251 e[] "\n 31252------ "${g}"Mandelbrot/Julia explorer"$n" -----------------\n 31253----\n 31254---- Select zooming region with "${c}"mouse"$n".\n 31255---- "${c}"Click once"$n" to reset zoom factor.\n 31256---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31257---- Key '"${c}"C"$n"' to print current fractal coordinates.\n 31258----\n 31259--------------------------------------------------" 31260 31261 # Init variables and display. 31262 rm w 512,512,0 _x_mandelbrot_coords $1 _x_mandelbrot_palette 31263 31264 # Start event loop. 31265 do 31266 siz={min({*,w},{*,h})} # Desired window dimension. 31267 $siz,$siz mandelbrot. {0,^},256,$1,{if($1,$2,0)},{if($1,$3,0)} map. [1] # Render fractal. 31268 if $1 w. $siz,$siz,0,"[G"{`39`}"MIC] Julia Set c=("{0,@0-1}")-("{0,@2-3}"), c0=($2,$3)" # Display on window. 31269 else w. $siz,$siz,0,"[G"{`39`}"MIC] Mandelbrot Set c=("{0,@0-1}")-("{0,@2-3}")" fi 31270 w={w} h={h} round. select. 2,0,0,0,1 # Get the user selection. 31271 if i[0]>0 # If valid selection found. 31272 M={max(i[3]-i[0],i[4]-i[1])} # Compute max dimension of selected rectangle. 31273 if $M<5 _x_mandelbrot_coords $1 rm[1] _x_mandelbrot_palette mv. 1 # If selection too small, reset the view, 31274 else ({{0,@0}+{@0}*({0,@2}-{0,@0})/$w};\ # Else compute new fractal coordinates. 31275 {{0,@1}+{@1}*({0,@3}-{0,@1})/$h};\ 31276 {{0,@0}+({@0}+$M)*({0,@2}-{0,@0})/$w};\ 31277 {{0,@1}+({@1}+$M)*({0,@3}-{0,@1})/$h}) 31278 fi 31279 rm[0] mv. 0 # Validate new coordinates. 31280 fi 31281 rm. # Delete latest rendering. 31282 if {*,C} # If 'C' key has been pressed. 31283 if $1 e[] "Julia set, at c = ("{0,@0-1}")-("{0,@2-3}"), with c0 = ($2,$3)." 31284 else e[] "Mandelbrot set, at c = ("{0,@0-1}")-("{0,@2-3}")." 31285 fi 31286 fi 31287 if !{*}" || "{*,ESC}" || "{*,Q} break fi 31288 wait -1 31289 while 1 rm w 0 31290 31291_x_mandelbrot_coords : 31292 if $1 (-2;-2;2;2) else (-2.1;-1.5;1.2;1.5) fi 31293 31294_x_mandelbrot_palette : 31295 6,1,1,3 rand. 20,255 r. 32,1,1,3,3 r. 1024,1,1,3,0,2 =. 0,0,0,0,0 =. 0,0,0,0,1 =. 0,0,0,0,2 31296 31297#@cli x_mask_color : _colorspace={ all | rgb | lrgb | ycbcr | lab | lch | hsv | hsi | hsl | cmy | cmyk | yiq },\ 31298# _spatial_tolerance>=0,_color_tolerance>=0 31299#@cli : Interactively select a color, and add an alpha channel containing the corresponding color mask. 31300#@cli : Argument 'colorspace' refers to the color metric used to compute color similarities, and can be basically 31301#@cli : one of { rgb | lrgb | ycbcr | lab | lch | hsv | hsi | hsl | cmy | cmyk | yiq }. 31302#@cli : You can also select one one particular channel of this colorspace, by setting 'colorspace' as 31303#@cli : 'colorspace_channel' (e.g. 'hsv_h' for the hue). 31304#@cli : Default values: 'colorspace=all', 'spatial_tolerance=5' and 'color_tolerance=5'. 31305x_mask_color : check "${2=5}>=0 && ${3=5}>=0" skip ${1=all} check_display $0 31306 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31307 e[^-1] "Interactively create color mask for image$?, with color space $1, spatial tolerance $2 and 31308 color tolerance $3." 31309 e[] "\n 31310----------------------------------------------------------------------------------------------------\n 31311----\n 31312---- "${c}"Left mouse button"$n" adds a wanted color to the selection.\n 31313---- "${c}"Right mouse button"$n" adds an unwanted colors to the selection.\n 31314---- "${c}"Middle mouse button"$n" or key '"${c}"R"$n"' resets color mask.\n 31315---- Key '"${c}"SPACE"$n"' or '"${c}"TAB"$n"' toggles view modes (masked RGB or mask).\n 31316---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 31317---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 31318---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 31319---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' exit the interactive window.\n 31320----\n 31321----------------------------------------------------------------------------------------------------" 31322 l[] _ac_$1 onfail error[0--3] "Command '$0' : Invalid colorspace '$*'." endl 31323 m _ac_forward:$_f 31324 repeat $! l[$>] slices 0 basename {0,n} nm=${} 31325 wh=${fitscreen\ {[w,h,1]},128,1024} 31326 +r $wh,1,100%,2 31327 +_ac_forward. channels. $_s 31328 if {1,s>3} channels[1] 0,2 fi to_rgb[1] 31329 31330 w[1] 100%,100%,0,$nm 31331 colors_add=-1 colors_sub=-1 visumode=0 31332 is_clicked=0 time=0 delay=0.1 31333 do 31334 31335 # Manage user events. 31336 time={$is_clicked?$time:$|} 31337 wait 31338 x={2,round({*,x}*(w-1)/({*,w}-1))} 31339 y={2,round({*,y}*(h-1)/({*,h}-1))} 31340 b={*,b} 31341 c=$x,$y,{2,I($x,$y)} 31342 is_add={arg(1,$colors_add)>=0} 31343 is_sub={arg(1,$colors_sub)>=0} 31344 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 31345 is_resized=0 31346 refresh=0 31347 31348 if $x>=0" && "$b&1 # Add a color 31349 if $is_add colors_add=$colors_add,$c else colors_add=$c fi 31350 is_clicked=1 31351 refresh={$|-$time>$delay} 31352 elif $x>=0" && "$b&2 # Subtract a color 31353 if $is_sub colors_sub=$colors_sub,$c else colors_sub=$c fi 31354 is_clicked=1 31355 refresh={$|-$time>$delay} 31356 elif $b&4" || "{*,R} # Reset colors 31357 colors_add=-1 colors_sub=-1 refresh=1 is_clicked=1 31358 elif !$b 31359 refresh={$is_clicked==1} 31360 is_clicked=0 31361 fi 31362 if {*,-TAB}" || "{*,-SPACE} visumode={($visumode+1)%3} refresh=1 fi # Change visu mode 31363 if {*,r} is_resized=1 31364 elif $is_ctrl" && "{*,-D} w[] {1,1.25*[w,h]} is_resized=1 31365 elif $is_ctrl" && "{*,-C} w[] {1,0.8*[w,h]} is_resized=1 31366 elif $is_ctrl" && "{*,R} w[] ${fitscreen\ {0,[w,h,1]},128,1024} is_resized=1 31367 fi 31368 if $is_resized rm[1,2] +r {*,d},{*,e},1,3,2 +_ac_forward. channels. $_s refresh=1 fi 31369 31370 # Refresh view. 31371 if $refresh 31372 _x_mask_color[2] {$2*w#2/w#0},$3,{``$colors_add},{``$colors_sub} delay=${} 31373 if $visumode==0 +. 64 c. 0,255 +a[1,-1] c drgba. w. -1,-1,$nm" [half-masked]" rm. 31374 elif $visumode==1 +a[1,-1] c drgba. w. -1,-1,$nm" [masked]" rm. 31375 else w. -1,-1,$nm" [mask]" 31376 fi 31377 rm. 31378 time=$| 31379 fi 31380 31381 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,ENTER} 31382 31383 # Rescale to original image dimensions. 31384 if arg(1,$colors_add)>=0 ($colors_add) 31385 r. {2+s#2},{w/(2+s#2)},1,1,-1 +z. 0,1 *. '{(w#0-1)/(w#2-1)},{(h#0-1)/(h#2-1)}' 31386 j.. . colors_add={-2,^} rm[-2,-1] 31387 fi 31388 if arg(1,$colors_sub)>=0 ($colors_sub) 31389 r. {2+s#2},{w/(2+s#2)},1,1,-1 +z. 0,1 *. '{(w#0-1)/(w#2-1)},{(h#0-1)/(h#2-1)}' 31390 j.. . colors_sub={-2,^} rm[-2,-1] 31391 fi 31392 rm[-2,-1] +_ac_forward channels. $_s 31393 _x_mask_color. $2,$3,{``$colors_add},{``$colors_sub} 31394 rm.. a c 31395 31396 endl done 31397 um _ac_forward 31398 31399_x_mask_color : # Estimate color mask image. 31400 100%,100% 31401 is_add={arg(1,$3)>=0} 31402 is_sub={arg(1,$4)>=0} 31403 t0=$| 31404 if $is_add" || "$is_sub 31405 if $is_add 31406 ($3) r. {2+s#0},{w/(2+s#0)},1,1,-1 31407 N_add={h} M_add={"M = vectorw(); fill(M,k,med(crop(k,1)));M"} rm. 31408 fi 31409 if $is_sub 31410 ($4) r. {2+s#0},{w/(2+s#0)},1,1,-1 31411 N_sub={h} M_sub={"M = vectorw(); fill(M,k,med(crop(k,1)));M"} rm. 31412 fi 31413 f. "begin( 31414 invert(A,nA) = inv(A,nA); # For <v.2.9.2 31415 const is_add = "$is_add"; 31416 const is_sub = "$is_sub"; 31417 const ss = sqrt(2)*$1; 31418 const sc = sqrt(2)*$2; 31419 colors_add = [ $3 ]; 31420 colors_sub = [ $4 ]; 31421 M_add = [ 0"$M_add"]; 31422 M_sub = [ 0"$M_sub"]; 31423 const N_add = 0"$N_add"; 31424 const N_sub = 0"$N_sub"; 31425 const siz = 2 + s#0; 31426 const siz2 = sqr(siz); 31427 sigma = vectorsiz(sc); 31428 sigma[0] = sigma[1] = ss; 31429 31430 tensor(op) = ( 31431 T = vectorsiz2(); 31432 if (is_#op, 31433 for (k = 0, k<size(colors_#op), k+=siz, C = colors_#op[k,siz]-=M_#op; C*=sigma; T+=mul(C,C,siz)); 31434 T/=1e-8 + N_#op; 31435 T+=eye(siz); 31436 T = invert(T); 31437 ); T 31438 ); 31439 31440 T_add = tensor(add); 31441 T_sub = tensor(sub); 31442 ); 31443 P = [ x,y,I#0 ]; 31444 pot_add = is_add?(C = P - M_add; exp(-dot(C,T_add*C))):1; 31445 pot_sub = is_sub?(C = P - M_sub; exp(-dot(C,T_sub*C))):0; 31446 pot_add - pot_sub" 31447 c. 0,1 n. 0,512 c. 0,255 31448 else f. 255 31449 fi 31450 u {$|-$t0} 31451 31452#@cli x_metaballs3d 31453#@cli : Launch the 3D metaballs demo. 31454x_metaballs3d : check_display $0 31455 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31456 e[] "\n 31457------ "${g}"3D metaballs"$n" ---------------------------------------\n 31458----\n 31459---- "${c}"Mouse button"$n" or '"${c}"SPACE"$n"' key to toggle rendering mode.\n 31460---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 31461---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 31462---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31463----\n 31464-----------------------------------------------------------" 31465 l[] 31466 100,100 noise. 100,1 plasma. 1,0,10 r. 512,320,1,3 n. 0,1 b. 4,0 n. 0,255 31467 mix_channels. (0.7,0,0;0,0.9,0;0,0,1.2) c. 0,255 l3d 31468 0 31469 24,24,24,1,'X=x-w/2;Y=y-h/2;Z=z-d/2;exp(-(X*X+Y*Y+Z*Z)/100)' 31470 72,72,72 M=8 mode=3 31471 s0=Dots s1=Wireframe s2=Flat s3=Flat-shaded s4=Gouraud-shaded s5=Phong-shaded 31472 repeat $M fx$>={2*g} fy$>={2*g} fz$>={2*g} done 31473 w[0] -1,-1,0,"[G"{`39`}"MIC] 3D Metaballs" 31474 do 31475 repeat $M 31476 x$>={w/2+0.5*(w-{2,w}-4)*cos(${fx$>}*$|)} 31477 y$>={h/2+0.5*(h-{2,h}-4)*sin(${fy$>}*$|)} 31478 z$>={d/2+0.5*(d-{2,d}-4)*sin(${fz$>}*$|)} 31479 done 31480 f[3] 0 repeat $M j[3] [2],{${x$>}-{2,w/2}},{${y$>}-{2,h/2}},{${z$>}-{2,d/2}},0,-1 done 31481 +r[3] 28,28,28,1,2 isosurface3d. 0.4 -3d. 12,12,12 *3d. 13 rv3d. 31482 r3d. 1,2,1,{100*$|} 31483 N={i[7]} (255,255,150;200,96,164;50,150,230) r. 3,$N,1,1,3 y. j.. .,0,{{-2,h}-4*$N} # Do some color tweaks. 31484 if !$mode circles3d.. 4 fi 31485 if !{1,w} 31486 0 t. ${s$mode},5,5,23,0.5,255,255,255 r. {w+5},100%,1,3,0 b. 0.7 n. 0,255 31487 +dilate. 3 +j[0] ..,5,3,0,0,1,.,255 mv. 1 rm[2,-2,-1] 31488 fi 31489 +j3d[1] ..,50%,50%,0,1,{if(!$mode,3,$mode)},0,0,300,0,0,-500,0.1,1.5 31490 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-22},16,2,0.2 fi 31491 w. 31492 if {*,CTRLLEFT}" && "{*,D} w[] {2*w},{2*h} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 31493 rm[-3--1] wait 20 31494 if {*,b}" || "{*,SPACE} mode={($mode+if({*,b}&2,-1,1))%6} wait -1 rm[1] i[1] 0 fi 31495 while {*}" && "!{*,ESC}" && "!{*,Q} 31496 rm w 0 endl 31497 31498#@cli x_minesweeper : 8<=_width=<20,8<=_height<=20 31499#@cli : Launch the Minesweeper game. 31500x_minesweeper : check "${1=20}>=8 && $1<=30 && ${2=$1}>=8 && $2<=30" check_display $0 31501 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31502 e[] "\n 31503------ "${g}"Minesweeper"$n" -------------------------------------------\n 31504----\n 31505---- The goal is to "${c}"clear the minefield"$n" without detonating a\n 31506---- mine.\n 31507----\n 31508---- "${c}"Left mouse button"$n" to try clearing one square.\n 31509---- "${c}"Right mouse button"$n" to flag or unflag a square.\n 31510---- "${c}"Middle mouse button"$n" to reset mine field.\n 31511---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31512----\n 31513--------------------------------------------------------------\n" 31514 31515 # Generate random mine field and player board. 31516 # Labels : 0=mine, 1=empty, 2='1-near', 3='2-near', ..., 9='8-near', 10=still unknown. 31517 $1,$2 noise. 30,2 ==. 1 nb_mines={is} (1,1,1;1,0,1;1,1,1) +convolve.. .,0 rm.. +. 1 ==.. 0 *[-2,-1] nm. field 31518 do x={round(u(w-1))} y={round(u(h-1))} while i($x,$y)!=1 # Find a good starting point. 31519 +f[field] 11 =. 12,$x,$y nm. board 31520 31521 # Generate sprite graphics. 31522 24,24,1,3,200 fc. 255,180,130 31523 ellipse. 12,12,4,4 line. 6,12,18,12 line. 12,6,12,18 line. 13,10,14,10,1,255 line. 13,11,14,11,1,255 31524 z. 1,1,{w-2},{h-2} frame. 1,1,0 31525 +fc. 230,250,255 31526 +t. "1",10,5,13,1,0,196,0 +t.. "2",9,5,13,1,0,128,0 +t... "3",9,5,13,1,0,0,255 31527 +t[-4] "4",9,5,13,1,255,0,0 +t[-5] "5",9,5,13,1,200,0,0 +t[-6] "6",9,5,13,1,150,0,0 31528 +t[-7] "7",9,5,13,1,128,0,0 +t[-8] "8",9,5,13,1,64,0,0 31529 +f. 'if(x<=1||y<=1||x>=w-2||y>=h-2,if(x<y,128,255),160+2*(y+x))' 31530 +polygon. 4,13,15,11,15,6,18,17,18,1,0 line. 12,15,12,6,1,255,0,0 polygon. 3,12,6,6,9,12,12,1,220,0,0 31531 rv[-2,-1] 31532 . 100%,100%,1,3 line. 6,14,10,18,1,0,200,0 line. 10,18,16,6,1,0,200,0 dilate. 2 31533 +channels. 1 n. 0,0.7 dilate. 3 j... ..,0,0,0,0,1,. rm[-2,-1] 31534 a[-13--1] x nm. sprites 31535 31536 # Pre-calculate offsets and canvas for faster board rendering. 31537 (0,23;0,23^0,0;23,23) r. 24,24,1,2,3 r. {board,w*24},{board,h*24},1,2,0,2 nm. offsets 31538 .,.,1,3,255 frame. 1,1,0 frame. 23,23,255 31539 0 t. "Number of mines : "$nb_mines,0,0,18,1,100,200,255 negate. j.. .,{({-2,w}-w)/2},{{-2,h}-h-2} rm. 31540 nm. canvas 31541 31542 # Start user interaction loop. 31543 failed=0 succeeded=0 nb_flags=0 started=0 31544 do 31545 31546 # Render board. 31547 +*[board] 24 r. [offsets],[offsets] channels. 0,1 +. [offsets] +warp[sprites] .,0,0 rm.. 31548 j[canvas] .,24,24 rm. 31549 31550 # Wait for user's selection. 31551 wait -1 31552 if $failed 31553 0 t. "Game\nOver!",3,3,38,1,255 r. 100%,100%,1,4 sh. 3 dilate. 5 /. 2 rm. 31554 drop_shadow. 5,5,1 blend[canvas,-1] alpha 31555 0 t. "Boom! You failed!",0,0,18,1,100,255,255 r. {canvas,w},100%,1,3,0,0,0.5,0.5 negate. j[canvas] .,0,3 rm. 31556 do w[canvas] {w},{h} wait while {*}" && "!{*,ESC}" && "!{*,Q} 31557 elif $succeeded 31558 0 t. "Success!",3,3,38,1,255 r. 100%,100%,1,4 sh. 3 dilate. 5 /. 2 rm. 31559 drop_shadow. 5,5,1 blend[canvas,-1] alpha 31560 0 t. "Congratulations! ("{round($|-$tic)}" s)",0,0,18,1,255,100,255 r. {canvas,w},100%,1,3,0,0,0.5,0.5 31561 negate. j[canvas] .,0,3 rm. 31562 do w[canvas] {w},{h} wait while {*}" && "!{*,ESC}" && "!{*,Q} 31563 else 31564 +==[board] 10 nb_flags={is} rm. 31565 do 31566 if !$started tic=$| fi 31567 0 t. "Elapsed time : "{round($|-$tic)}" s / Flags : "$nb_flags,0,0,18,1,255,200,0 31568 r. {canvas,w},100%,1,3,0,0,0.5,0.5 31569 negate. j[canvas] .,0,3 rm. 31570 wait 50 31571 x={int(({*,x}-24)/24)} y={int(({*,y}-24)/24)} b={*,b} 31572 w[canvas] {w},{h},0,"[G"{`39`}"MIC] Minesweeper" 31573 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!$b 31574 fi 31575 31576 # Manage selected square. 31577 if $x>=0\ &&\ $y>=0\ &&\ $x<{board,w}\ &&\ $y<{board,h} 31578 if $b&1 # Try to clean square. 31579 started=1 val={field,i($x,$y)} 31580 if $val==0 +==[field] 0 j[board] [field],0,0,0,0,1,. rm. failed=1 # Found a mine -> boom! 31581 elif $val==1 # Found an empty area 31582 +flood[field] $x,$y,0,0,1,1,-1 ==. -1 dilate. 3 j[board] [field],0,0,0,0,1,. rm. 31583 else =[board] $val,$x,$y # Close to one or several mines 31584 fi 31585 elif n={board,i($x,$y)};$b&2" && "n>=10" && "n<=11 31586 =[board] {if({board,i($x,$y)}==11,10,11)},$x,$y # Flag or unflag a square. 31587 elif $b&4 f[board] 10 # Reset minefield. 31588 fi 31589 fi 31590 31591 if $nb_mines==$nb_flags\ &&\ {board,iM}!=11 succeeded=1 fi # Check if board is cleared. 31592 while {*}" && "!{*,ESC}" && "!{*,Q} 31593 w 0 31594 31595#@cli x_minimal_path 31596#@cli : Launch the minimal path demo. 31597x_minimal_path : check_display $0 31598 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31599 e[] "\n 31600------ "${g}"Minimal path"$n" ------------------------------------------\n 31601----\n 31602---- "${c}"Click on two points"$n" to compute and display the minimal\n 31603---- path between those points. The ending point is then\n 31604---- chosen as the next starting point for another path.\n 31605---- Key '"${c}"S"$n"' to save snapshot of the current view.\n 31606---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31607----\n 31608--------------------------------------------------------------" 31609 31610 if !$! sp ? fi 31611 n 0,200 round 1 31612 repeat $! l[$>] 31613 w[0] -1,-1,0,"[G"{`39`}"MIC] Select Starting Point P0" 31614 31615 if !narg($first_time) 31616 parallel 0,"+l[0] r2dy 128 frame 1,1,0 \ 31617 alert \"[G"{`39`}"MIC Minimal Path]\",\ 31618 \"The G\47MIC minimal path demo illustrates how minimal paths\n\ 31619 can be computed in images to detect and track edge points.\n\ 31620 Use your mouse to select desired starting and ending points,\n\ 31621 and see what is the minimal path computed between these points.\",\ 31622 \"OK\" \ 31623 rm endl" 31624 first_time=0 31625 fi 31626 31627 +gradient_norm b. 1 f. exp(-i/10) 31628 to_rgb[0] +select[0] 0 P0={^} 31629 ellipse[0] {@0,1},3,3,0,1,255,0,255 31630 ellipse[0] {@0,1},3,3,0,1,0xFFFFFFFF,255,255,255 31631 rm. 31632 if min($P0)>=0 31633 p=1 31634 do 31635 w[0] -1,-1,0,"[G"{`39`}"MIC] Select Ending Point P"$p 31636 +select[0] 0 31637 if {*,S} 31638 rm. 31639 +to[0] "Saving snapshot...",5,5,13,1,1,255,255,255 w. rm. 31640 o[0] gmic_minimal_path.png 31641 wait -1 31642 else 31643 P1={^} 31644 ellipse[0] {@0,1},3,3,0,1,255,0,255 31645 ellipse[0] {@0,1},3,3,0,1,0xFFFFFFFF,255,255,255 31646 rm. 31647 if min($P1)>=0 31648 +to[0] "Processing...",5,5,13,1,1,255,255,255 w. rm. 31649 +minimal_path[1] $P0,$P1,1 transpose. 31650 pointcloud. 0 *. 255 r. 100%,100%,1,[0],0,0,0,0,0,0.5 ri. [0],0 -|[0,-1] 31651 P0=$P1 p+=1 31652 fi 31653 fi 31654 while {*}" && "!{*,ESC}" && "!{*,Q} 31655 fi 31656 rm[1] w 0 31657 endl done 31658 31659#@cli x_morph : _nb_frames>=2,_preview_fidelity={ 0=coarsest | 1=coarse | 2=normal | 3=fine | 4=finest } 31660#@cli : Launch the interactive image morpher. 31661#@cli : Default values: 'nb_frames=16' and 'preview_fidelity=3'. 31662x_morph : check "isint(${1=16}) && isint(${2=3}) && $2>=0 && $2<=4" check_display $0 31663 if $!<2 error[0--3] "Command '$0': Requires at least two input images!" return fi 31664 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r b=$_vt100_b 31665 e[] "\n 31666------ "${g}"Interactive image morpher"$n" ---------------------------\n 31667----\n 31668---- "${b}"Source/target window:"$n"\n 31669---- "${c}"Left mouse button"$n": Add new keypoint on current image\n 31670---- and move it on the other one.\n 31671---- "${c}"Right mouse button"$n": Add/move keypoint on current image.\n 31672---- Key '"${c}"DELETE"$n"' or "${c}"middle mouse button"$n": Delete keypoint.\n 31673---- Key '"${c}"SPACE"$n"' or "${c}"mouse wheel"$n": Toggle source/target.\n\n 31674---- "${b}"In-between window:"$n"\n 31675---- "${c}"Mouse wheel"$n": Change morphing time, from 0 to 1.\n 31676---- "${c}"Left mouse button"$n": Reset morphing time to 0.5.\n\n 31677---- "${b}"Both windows:"$n"\n 31678---- Key '"${c}"TAB"$n"': Change keypoint radius.\n 31679---- Key '"${c}"ENTER"$n"': Play/stop in-between animation.\n 31680---- Key '"${c}"R"$n"': Reset keypoints.\n 31681---- Key '"${c}"K"$n"': Show/hide keypoints.\n 31682---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"': Process fullres and exit.\n 31683----\n 31684-----------------------------------------------------------" 31685 31686 offset=0 31687 radius_keypoints=3 31688 repeat $!-1 l[{[$>,$>+1]+$offset}] nm0={0,n} nm1={1,n} 31689 to_colormode 0 31690 rr2d ${-max_wh},2 31691 nm img0,img1 31692 256,1,1,1,"x>=4?x-2:1" map. 2 nm. colormap 31693 31694 # Start interactive window. 31695 selected_keypoint=-1 31696 view_keypoints=1 31697 time_inbetween=0.5 31698 animate_inbetween=0 31699 move_other=0 31700 frame=0 31701 31702 do 31703 # Generate set of keypoints (x0,y0,x1,y1,index_color) 31704 if !narg($keypoints) 31705 if narg($__x_morph_keypoints) ($__x_morph_keypoints) r. 1,{w/5},1,5,-1 31706 else 1,4,1,5,"p = y%2; q = int(y/2); [ [ p,q,p,q ]*100,y ]" 31707 fi 31708 N0={h} nm. keypoints 31709 rmn warp0,warp1 31710 fi 31711 31712 # Generate base images. 31713 if !narg($imgb0)" || "!narg($imgb1) 31714 if {*} wdims=${"fitscreen "{*,d},{img0,{*,d}*h/w}} 31715 else wdims=${"fitscreen "{img0,[w,h,1]},128,50%} 31716 fi 31717 w[] $wdims,0,"[G'MIC] Interactive Morph" 31718 repeat 2 +to_color[img$>] r. $wdims,1,100%,2 n. 0,255 nm. imgb$> done 31719 rmn imgr,warp0,warp1 31720 fi 31721 31722 # Generate warp fields. 31723 if (!narg($warp0)" || "!narg($warp1)) 31724 subsamp={arg(1+$2,8,6,4,2,1)} 31725 +_x_warp_rbf[keypoints] {imgb0,round([w,h]/$subsamp)} 31726 +l[keypoints] s c,-2 rv[0,1] a c endl +_x_warp_rbf. {imgb0,round([w,h]/$subsamp)} rm.. 31727 *[-2,-1] $subsamp 31728 r[-2,-1] {imgb0,[w,h]},1,100%,3 31729 nm[-2,-1] warp0,warp1 31730 rmn imgm 31731 fi 31732 31733 # Render visualization. 31734 if !narg($imgr) 31735 [imgb$frame] nm. imgr 31736 if s==4 drgba. fi 31737 if $view_keypoints 31738 eval[keypoints] "* 31739 begin( 31740 fact = ([ w#"$imgb0",h#"$imgb0" ] - 1)/100; 31741 const radius1 = "$radius_keypoints"; 31742 const radius2 = radius1 + 2; 31743 const opacity = min(1,3/"($radius_keypoints-1)"); 31744 ); 31745 X = round((I)[2*"$frame",2]*fact); 31746 y=="$selected_keypoint"?(ellipse(#-1,X,radius2+2,radius2+2,0,1,255)); 31747 ellipse(#-1,X,radius2,radius2,0,opacity,0); 31748 ellipse(#-1,X,radius1,radius1,0,opacity,I[#"$colormap",i4]); I" 31749 fi 31750 w. -1,-1,0,"[G'MIC] Interactive Morph ("${"s0=Source s1=Target u ${s"$frame"}"}")" 31751 fi 31752 31753 # Generate morph image 31754 if !narg($imgm) 31755 t,onemt={t=$animate_inbetween?0.5*(1+sin(2*($time_inbetween+$|-$animate_inbetween))):$time_inbetween;[t,1-t]} 31756 +*[warp1] $t *. -1 +warp[imgb0] .,1,2,3 rm.. *. $onemt 31757 +*[warp0] $onemt *. -1 +warp[imgb1] .,1,2,3 rm.. *. $t 31758 +[-2,-1] c. 0,255 nm. imgm 31759 w1. -1,-1,0,"[G'MIC] Interactive Morph (In-between)" 31760 fi 31761 31762 # Manage user interaction 31763 if $animate_inbetween wait 40 else wait fi 31764 mb={*,b} mxy={[{*,x,y}]*100/([{*,w,h}]-1)} mouse_over={{*,x}>=0} 31765 31766 if $mouse_over" && "($mb" || "{*,DELETE})" && "$selected_keypoint<0" && "h#$keypoints>0 31767 31768 # Determine selected keypoint. 31769 selected_keypoint={keypoints,"dmin = inf; kmin = -1; fact = ([w#"$imgr",h#"$imgr"]-1)%; 31770 repeat (h,k, 31771 dist = norm(((I[k])[2*"$frame",2] - ["$mxy"])*fact); 31772 dist<dmin?(dmin = dist; kmin = k) 31773 ); 31774 kmin>=0 && dmin<"max(8,1.5*$radius_keypoints)"?kmin:-1"} 31775 fi 31776 31777 if {*,-o}" || "{*,-SPACE}" || "{*1,-SPACE} frame={!$frame} rmn imgr fi # Swap frames 31778 if {*,-K}" || "{*1,-K} view_keypoints={!$view_keypoints} rmn imgr fi # Show/hide keypoints 31779 if {*,-R}" || "{*1,-R} rmn keypoints,imgr __x_morph_keypoints= fi # Reset keypoints 31780 if {*,-TAB}" || "{*1,-TAB} # Change keypoint radius 31781 radius_keypoints={max(2,($radius_keypoints+2)%8)} view_keypoints=1 rmn imgr 31782 fi 31783 if {*,-ENTER}" || "{*1,-ENTER} animate_inbetween={$animate_inbetween?0:$|} fi # Start in-between animation 31784 if {*,r} rmn imgb0,imgb1 fi # Window resize 31785 if {*1,r} rmn imgm fi 31786 if {*1,o} # Change time of in-between 31787 time_inbetween={max(0,min(1,$time_inbetween+0.05*{*1,-o}))} animate_inbetween=0 rmn imgm 31788 fi 31789 if {*1,-b} time_inbetween=0.5 animate_inbetween=0 rmn imgm fi # Reset in-between time 31790 31791 if $mouse_over" && "($mb==1" || "$mb==2)" && "$selected_keypoint<0 # Add keypoint 31792 if $mb==1" && "!$move_other frame={!$frame} move_other=1 fi # Move on other window 31793 ({keypoints,[$mxy,$mxy,h]}) 31794 permute. zycx a[keypoints,-1] y 31795 selected_keypoint={keypoints,h-1} 31796 rmn imgr 31797 31798 elif $mouse_over" && "($mb==1" || "$mb==2)" && "$selected_keypoint>=0 # Move keypoint 31799 if $mb==1" && "!$move_other frame={!$frame} move_other=1 fi # Move on other window 31800 ({[$mxy]}) permute. zycx j[keypoints] .,0,$selected_keypoint,0,{2*$frame} rm. 31801 rmn imgr 31802 31803 elif $mouse_over" && "$selected_keypoint>=0" && ("{*,-DELETE}" || "$mb==4") && "h#$keypoints>4 # Delete keypoint 31804 1,1,1,5,-1 j[keypoints] .,0,$selected_keypoint rm. discard[keypoints] -1 r[keypoints] 1,{keypoints,h/5},1,5,-1 31805 N0-={$selected_keypoint<$N0?1:0} selected_keypoint=-1 31806 rmn warp0,warp1,imgr 31807 31808 elif !{*,b}" && "$selected_keypoint>=0 31809 if $move_other frame={!$frame} move_other=0 fi 31810 selected_keypoint=-1 31811 rmn warp0,warp1,imgr 31812 fi 31813 31814 if $animate_inbetween rmn imgm fi 31815 while {*}" && "!{*,ESC}" && "!{*,Q}" && "{*1}" && "!{*1,ESC}" && "!{*1,Q} 31816 if !$< __x_morph_keypoints={keypoints,^} fi 31817 31818 # Render fullres morphing. 31819 rmn colormap,imgb0,imgb1,warp0,warp1,imgr,imgm 31820 +_x_warp_rbf[keypoints] {img0,[w,h]} 31821 +l[keypoints] s c,-2 rv[0,1] a c endl +_x_warp_rbf. {img0,[w,h]} rm.. 31822 nm[-2,-1] warp0,warp1 31823 31824 repeat $1 31825 t,onemt={t=$>/max(1,$1-1);[t,1-t]} 31826 +*[warp1] $t *. -1 +warp[img0] .,1,2,3 rm.. *. $onemt 31827 +*[warp0] $onemt *. -1 +warp[img1] .,1,2,3 rm.. *. $t 31828 +[-2,-1] c. 0,255 nm. ${nm0}_$> 31829 if {*}" && "{*1} w1 0 fi 31830 if {*}" || "{*1} 31831 text="Processing frame \#"$>"/"{$1-1}"..." 31832 if {*} +r. {*,d,e},1,100%,2 to. $text,5,5,20,2 w. rm. fi 31833 if {*1} +r. {*1,d,e},1,100%,2 to. $text,5,5,20,2 w1. rm. fi 31834 fi 31835 done 31836 nm. $nm1 k[-$1--1] 31837 offset+={$!-2} 31838 endl done w0 0 w1 0 31839 31840#@cli x_pacman 31841#@cli : Launch pacman game. 31842x_pacman : check_display $0 31843 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31844 e[] "\n 31845------ "${g}"Pacman"$n" -----------------------------------------------\n 31846----\n 31847---- This is a G\47MIC implementation of the "${g}"pacman"$n" game.\n 31848----\n 31849---- Move the pacman to eat all pacdots on the different levels.\n 31850---- Eating a pacgum makes pacman invincible for "${c}"10 seconds"$n",\n 31851---- which mean pacman can eat ghosts during this time.\n 31852---- Eating a ghost earns "${c}"100 pts"$n".\n 31853---- Eating a cherry earns "${c}"10 pts"$n".\n 31854---- Eating a strawberry earns "${c}"100 pts"$n".\n 31855---- Eating an orange earns "${c}"1000 pts"$n".\n 31856---- Eating a banana earns "${c}"5000 pts"$n".\n 31857----\n 31858---- "${c}"Arrow keys"$n" to control pacman.\n 31859---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 31860---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 31861---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31862----\n 31863--------------------------------------------------------------" 31864 l[] 31865 31866 # Initialize characters gfx. 31867 m "_pacman_ghost_base_gfx : 31,19 circle. 15,15,15,1,1 31,12,1,1,'y<4+8*abs(cos(x*0.3+0.25*pi*$""1))' a[-2,-1] y" 31868 repeat 4 31869 _pacman_ghost_standard_gfx 255,0,0,$> nm. ghost0_$> 31870 _pacman_ghost_standard_gfx 0,255,222,$> nm. ghost1_$> 31871 _pacman_ghost_standard_gfx 255,184,222,$> nm. ghost2_$> 31872 _pacman_ghost_standard_gfx 255,184,71,$> nm. ghost3_$> 31873 _pacman_ghost_afraid_gfx $> nm. ghosta_$> 31874 _pacman_ghost_base_gfx $> r. 16,16,1,1,2 nm. ghostm_$> 31875 _pacman_ghost_standard_gfx 0,0,0,$> nm. ghostd_$> 31876 _pacman_pacman_gfx $> nm.. pacman_$> nm. pacmanm_$> 31877 done 31878 +channels[ghostd_0] 0 !=. 0 nm. ghostdm 31879 _pacman_cherry_gfx nm. fruit0 _pacman_strawberry_gfx nm. fruit1 31880 _pacman_orange_gfx nm. fruit2 _pacman_banana_gfx nm. fruit3 31881 20,2,1,3,200 nm. gate 31882 score0,score1,score2,score3,score4=10,100,1000,5000,"Argh!" 31883 repeat 5 31884 0 t. ${score$>},0,0,13,1,255,255,255 autocrop. 0 expand_xy. 1,0 +dilate. 3 31885 nm. scorem$> nm.. score$> 31886 done 31887 time4=255,255,255 time3=255,255,32 time2=255,128,32 time1=255,32,32 31888 repeat 11 0 t. $<" s",0,0,23,1,${time{min(4,round(($<+1)/2))}} nm. time$< done 31889 0 t. "Get Ready!",0,0,32,1,255 autocrop. 0 expand_xy. 4,0 +dilate. 8 r.. 100%,100%,1,3 31890 nm.. get_ready nm. get_readym 31891 0 t. "Game\nOver!",0,0,53,1,255 autocrop. 0 expand_xy. 4,0 +dilate. 8 r.. 100%,100%,1,3 31892 nm.. game_over nm. game_overm 31893 31894 # Start game. 31895 score=0 level=-1 lives=3 is_quit=0 31896 do 31897 31898 # Build new level if necessary. 31899 if $level<0 31900 _rlevel=33 _glevel=33 _blevel=255 31901 _pacman_map_level{((-$level-1)%6)+1} mw={w} mh={h} mw2={int(w/2)} mh2={int(h/2)} 31902 if $level<-6 replace. 3,2 fi 31903 . nm[-2,-1] map0,map 31904 31905 # Precompute valid directions on each map point, and shortest path to the ghost's home. 31906 +shift[map] -1,0 +shift[map] 0,-1 +shift[map] 1,0 +shift[map] 0,1 a[-4--1] z !=. 1 nm. can_go 31907 +==[map] 1 100%,100% =. 1,$mw2,$mh2 distance. 1,..,3 channels. 100% 31908 f. 'if(i==2,0,if(i==8,1,if(i==1,2,if(i==4,3,i))))' nm. path 31909 +==[map] 2 pacdots={is} rm. 31910 level={-$level} 31911 fi 31912 31913 # Render board gfx. 31914 f[map] 'if(i>=4,0,i)' +==[map] 1 expand_xy. 1,0 r. 1600%,1600% erode. 9 b. 2 31915 g. xy abs[-2,-1] +[-2,-1] >=. 80% b. 2 n. 0,1 shrink_xy. 16 31916 +*. $_glevel +*.. $_blevel *... $_rlevel a[-3--1] c 31917 16,16,1,1,'x' +-[map] 1 max. 0 *. 16 r. 1600%,1600% 31918 16,16,1,1,'y' ri[-3,-1] ..,0,2 +[-2,-1] a[-2,-1] c 31919 16,16,1,3 _pacman_pacdots_gfx _pacman_pacgum_gfx a[-3--1] y 31920 warp. ..,0,0 rm.. -|[-2,-1] r. 100%,{h+24},1,3,0,0,0,1 31921 t. "Lives :",10,0,24,1,255 t. "Score :",{w-140},0,24,1,255 31922 if $lives +r[pacman_2] 12,12,1,4,2 r. {100*$lives}%,100%,1,4,0,2 j.. .,90,7 rm. fi 31923 nm. visu 31924 w[visu] {visu,f=h<0.5*{*,v}?1.5:1;[w,h]*=f},0,"[G"{`39`}"MIC] Pacman" cursor[0] 0 31925 0 t. "Level "$level,0,0,64,1,1 autocrop. 0 expand_xy. 4,0 (0,255^0,255^0,0) +map.. . rm.. dilate.. 8 31926 nm. level_N nm.. levelm_N 31927 31928 repeat 4 xg$>={16*$mw2} yg$>={16*$mh2+4*$>} dg$>=3 mg$>=0 done 31929 xp={16*10} yp={16*21} dp=-1 pacgum_timer=-1 fruit_timer=$| dying_pacman=0 is_get_ready=1 31930 xscore=0 yscore=0 nscore=0 oscore=0 31931 31932 # Start game interaction. 31933 do 31934 31935 # Display board graphics. 31936 t={int(6*$|)%4} left={if($pacgum_timer>=0,10-$|+$pacgum_timer,-1)} 31937 [visu] 31938 repeat 4 31939 mg=${mg$>} xg=${xg$>} yg={${yg$>}+24} 31940 if $mg==0 j. [ghost$>_$t],$xg,$yg,0,0,1,[ghostm_$t] 31941 elif $mg==1 t2={if($left>7,$t,if($left>3,int(12*$|)%4,int(24*$|)%4))} j. [ghosta_$t2],$xg,$yg,0,0,1,[ghostm_$t] 31942 elif $mg==2 j. [ghostd_$t],$xg,$yg,0,0,0.8,[ghostdm] 31943 else j. [ghost$>_$t],$xg,$yg,0,0,{$mg-2},[ghostm_$t] j. [ghostd_$t],$xg,$yg,0,0,1,[ghostdm] 31944 fi 31945 done 31946 if $dying_pacman 31947 _pacman_pacman_gfx {$dying_pacman/2} rotate[-2,-1] {90*(abs($dp)-1)} j... ..,$xp,{24+$yp},0,0,1,.,255 rm[-2,-1] 31948 dying_pacman+=1 31949 if $dying_pacman>64 31950 if $lives!=1 rm. break fi 31951 j. [game_over],{(w-{game_over,w})/2},{12+(h-{game_over,h})/2},0,0,{min(1,($dying_pacman-64)/50)},\ 31952 [game_overm],255 31953 rectangle. 90,7,101,18,1,0 31954 fi 31955 else 31956 +rotate[pacman_$t,pacmanm_$t] {90*(abs($dp)-1)} j... ..,$xp,{24+$yp},0,0,1,.,255 rm[-2,-1] 31957 if $left>=0" && "($left>=5" || "$t<=2) j. [time{round($left)}],{(w-{time0,w})/2-10},1 fi 31958 fi 31959 t. $score,{w-60},3,20,1,255 31960 if $is_get_ready 31961 j. [level_N],{(w-{level_N,w})/2},{12+(h-1.5*{level_N,h})/2},0,0,1,[levelm_N] 31962 if int($|*4)%2 j. [get_ready],{(w-{get_ready,w})/2},{24+(h+{get_ready,h})/2},0,0,1,[get_readym],255 fi 31963 fi 31964 if $oscore>0 j. [score$nscore],$xscore,$yscore,0,0,$oscore,[scorem$nscore],255 oscore-=0.04 yscore-=1 fi 31965 j. [gate],158,223,0,0,0.6 31966 w. 31967 if {*,CTRLLEFT}" && "{*,D} w[] {2*w},{2*h} 31968 elif {*,CTRLLEFT}" && "{*,C} w[] {f=h<0.5*{*,v}?1.5:1;[w,h]*=f} 31969 fi 31970 rm. 31971 31972 # Manage ghosts displacements and collisions. 31973 repeat 4 31974 xg=${xg$>} yg=${yg$>} dg=${dg$>} mg=${mg$>} 31975 31976 if max(abs($xg-$xp),abs($yg-$yp))<=8 # Test collision between ghost and pacman. 31977 if $mg==0" && "!$dying_pacman dying_pacman=1 # Was in normal mode -> dying pacman. 31978 xscore=$xp yscore={$yp+12} oscore=1 nscore=4 31979 elif $mg==1 mg=2 mg$>=$mg score+=100 # Was in invicibility mode -> dying ghost. 31980 xscore=$xp yscore={$yp+12} oscore=1 nscore=1 31981 fi 31982 fi 31983 if $mg>=2" && "($xg>>4)==$mw2" && "($yg>>4)==$mh2 # Check if dying ghost has returned to home. 31984 mg+=0.01 31985 if $mg>=3 mg=0 xg&=-2 yg&=-2 fi 31986 mg$>=$mg 31987 fi 31988 31989 if !($xg&15)" && "!($yg&15) # Check if ghost can take a new direction. 31990 ({u},{u},{u},{u};0,1,2,3) 31991 if $mg<2 # Try to chase or escape pacman 31992 =. {u(0.6,1)},{if($mg==0,dX0=$xp-$xg;dY0=$yp-$yg;if(abs(dX0)>abs(dY0),if(dX0>0,0,2),if(dY0>0,1,3)),\ 31993 dX1=$xp-$xg;dY1=$yp-$yg;if(abs(dX1)<abs(dY1),if(dX1>0,2,0),if(dY1>0,3,1)))} 31994 =. 0,{($dg+2)%4} 31995 if $is_get_ready =. 0.8,{path,i({$xg>>4},{$yg>>4})} fi 31996 else =. 1,{path,i({$xg>>4},{$yg>>4})} # If dying ghost, follow the best path to home. 31997 fi 31998 sort. -,x 31999 repeat 4 d={i($>,1)} # Try directions until it matches. 32000 if {can_go,i({$xg>>4},{$yg>>4},$d)} dg=$d break fi 32001 done rm. 32002 dg$>=$d 32003 fi 32004 u={D=${dg$>};(D==0)-(D==2)} 32005 v={D=${dg$>};(D==1)-(D==3)} 32006 xg$>={($xg+$u*(1+($mg==0)))%(16*$mw)} 32007 yg$>={($yg+$v*(1+($mg==0)))%(16*$mh)} 32008 done 32009 32010 wait 22 32011 32012 # Manage pacman displacement. 32013 if !$dying_pacman 32014 d={if({*,ARROWRIGHT},1,if({*,ARROWDOWN},2,if({*,ARROWLEFT},3,if({*,ARROWUP},4,$dp))))} 32015 if !($xp&15)" && "!($yp&15) 32016 i={map,i({$xp>>4},{$yp>>4})} 32017 if $i==2 score+=10 pacdots-=1 # Pacdot eaten. 32018 elif $i==3 pacgum_timer=$| repeat 4 if !${mg$>} mg$>=1 dg$>={(${dg$>}+2)%4} fi done # Pacgum eaten. 32019 elif $i>=4 score+={${score{$i-4}}} xscore=$xp yscore={$yp+12} oscore=1 nscore={$i-4} # Fruit eaten. 32020 fi 32021 =[map] 0,{$xp>>4},{$yp>>4} 32022 16,16,1,3 j[visu] .,$xp,{24+$yp} rm. 32023 d={if({can_go,i({$xp>>4},{$yp>>4},{abs($d)-1})},$d,$dp)} 32024 d={if({can_go,i({$xp>>4},{$yp>>4},{abs($d)-1})},$d,-abs($dp))} 32025 dp=$d 32026 else dp={if(abs($d-$dp)==2,$d,$dp)} # Allow to turn back on non-integer locations. 32027 fi 32028 is_get_ready={if($dp>0,0,$is_get_ready)} 32029 u={($dp==1)-($dp==3)} 32030 v={($dp==2)-($dp==4)} 32031 xp={($xp+2*$u)%(16*$mw)} 32032 yp={($yp+2*$v)%(16*$mh)} 32033 32034 if $pacgum_timer>=0" && "$|>$pacgum_timer+10 # Check if pacgum still has some effect. 32035 repeat 4 xg$>&=-2 yg$>&=-2 mg$>={if(${mg$>}==1,0,${mg$>})} done 32036 pacgum_timer=-1 32037 fi 32038 32039 if !$is_get_ready" && "($|-$fruit_timer)>=10 32040 x={round(u(0,{map0,w}))} 32041 y={round(u(0,{map0,h}))} 32042 if !{map,i($x,$y)}" && "{map0,i($x,$y)}==2 32043 n={min(3,int(abs(g*1.7)))} =[map] {4+$n},$x,$y j[visu] [fruit$n],{16*$x},{16*$y+24} fruit_timer=$| 32044 fi 32045 fi 32046 32047 fi 32048 if !{*}" || "{*,Q}" || "{*,ESC} is_quit=1 fi 32049 32050 while !$is_quit" && "$pacdots 32051 32052 if $is_quit break # Player asked to quit 32053 elif $pacdots # Player lost a life 32054 lives-=1 32055 else # Player achieved level 32056 level={-$level-1} wait[0] -1 32057 rm[map0,map,can_go,path] 32058 fi 32059 rm[visu,level_N,levelm_N] 32060 while $lives 32061 rm w 0 endl 32062 32063# The functions below create the various sprite gfx. 32064_pacman_ghost_standard_gfx : 32065 _pacman_ghost_base_gfx $4 (0,$1^0,$2^0,$3) map.. . rm. 32066 ellipse. 10,11,3,4,0,1,255 ellipse. 20,11,3,4,0,1,255 32067 r. 16,16,1,3,2 point. 5,{7-($4>=2)},0,1,1 point. 10,{7-($4>=2)},0,1,1 32068 32069_pacman_ghost_afraid_gfx : 32070 _pacman_ghost_base_gfx $1 32071 if $1<2 col=255,255,255 (0,0^0,0^0,208) else col=255,0,0 (0,248^0,248^0,248) fi 32072 map.. . rm. r. 16,16,1,3,2 32073 line. 4,4,6,6,1,$col,255 line. 4,6,6,4,1,$col,255 32074 line. 9,4,11,6,1,$col,255 line. 9,6,11,4,1,$col,255 32075 f. 'if(y>=9&&y<=10&&x>=2&&x<=13&&((int((x+1)/2)+y)%2),arg(c+1,$col),i)' 32076 32077_pacman_pacman_gfx : 32078 32,32,1,1,'X=x-15;Y=y-15;A=atan2(Y,X);R=sqrt(X^2+Y^2);R<15.5&&abs(A)>0.8*0.33*$1' 32079 (0,255^0,255^0,0^0,255) map.. . rm. r. 16,16,1,4,2 s. c,-3 32080 32081_pacman_pacdots_gfx : 32082 (255^184^151) r. 4,4,1,3 r. 16,16,1,3,0,0,0.5,0.5 32083 32084_pacman_pacgum_gfx : 32085 64,64,1,3 circle. 31,31,31,1,255,128,64 r2dx. 16 32086 32087_pacman_cherry_gfx : 32088 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KNzYgMSAxIDEgIzU5CnicFYpBCgAxDALVXvv/p5ZtmsgmIMoM7k0Cx/ySYYIXrE5qOgTmE1KGl"\ 32089 "oUW1pp1qVUqmkt3Hj9Whx3SMSAyMCAxIDEgIzI2Cnicc/eNYkjPzUyONwACveTM3PQqBgA+VQX2" 32090 decompress_rle. (0,0,255,255^0,173,0,255^0,0,0,255) map.. . rm. r2dy. 14 r. 16,16,1,3,0,0,0.5,0.5 32091 32092_pacman_strawberry_gfx : 32093 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KNzIgMSAxIDEgIzYwCnicJYlJDoAwEMOyHOH/H+UANJ0RBaRIlp1tJ4HAd9HFaoUtTNWC1yIPW"\ 32094 "T5ew5em+lT994guKHgAoIoa8zEgMjAgMSAxICMyNgp4nHP3jWJIz81MjjcAAr3kzNz0KgYAPlUF9g==" 32095 decompress_rle. (0,0,255,255^0,173,0,255^0,0,0,255) map.. . rm. r2dy. 14 r. 16,16,1,3,0,0,0.5,0.5 32096 32097_pacman_orange_gfx : 32098 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KNDQgMSAxIDEgIzQ2CnicBcHBDQAgDAOxXPjC/gsxU4VKi7DnAukKPU6SYjTVptxhbSv8wpVuf"\ 32099 "UwDEZ4xIDIwIDEgMSAjMjYKeJxz941iSM/NTI43AAK95Mzc9CoGAD5VBfY=" 32100 decompress_rle. (0,0,255,255^0,173,173,255^0,0,0,255) map.. . rm. r2dy. 14 r. 16,16,1,3,0,0,0.5,0.5 32101 32102_pacman_banana_gfx : 32103 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KNzAgMSAxIDEgIzQ4CnicNcqxDQAgDMTANx0S++8aIC9ShObceC6QQoSJ5Ai5vWW2WTI6xr+bv"\ 32104 "LU/BnUW3jEgMjAgMSAxICMyNgp4nHP3jWJIz81MjjcAAr3kzNz0KgYAPlUF9g==" 32105 decompress_rle. (0,255,255^0,173,255^0,0,255) map.. . rm. r2dy. 14 r. 16,16,1,3,0,0,0.5,0.5 32106 32107_pacman_map_level1 : 32108 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjAxIDEgMSAxICM5Nwp4nGWOUQ6AMAhDKX56Be9/QnWJArEM9MdsGa9QYOsGiOy4FaZYHAo1a"\ 32109 "MezIJ+QJnszLsq2aRaf9Q9GiaBnGmEZhSe8wLOdVqO+My+cFdJj9OpVQ0vzRm8l/L954AHE9jnsMSAyMCAxIDEgIzI2Cnicc/eNYk"\ 32110 "jPzUyONwACveTM3PQqBgA+VQX2" 32111 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 32112 _rlevel=33 _glevel=33 _blevel=255 32113 32114_pacman_map_level2 : 32115 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjA4IDEgMSAxICMxMDAKeJxljkEOAzEIAxn32C/0/y+MdlUloAKJemgvjAOG+PkCs8ElHsjRQ"\ 32116 "k0iycwS+/2jcuJlnhhhf3SxPKWw9DaJmYsbmLOqmyaXn92UsVV9Y+sweOvb7YB1vQPPDnV4a/ABHS45BDEgMjAgMSAxICMyNgp4nH"\ 32117 "P3jWJIz81MjjcAAr3kzNz0KgYAPlUF9g==" 32118 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 32119 _rlevel=200 _glevel=33 _blevel=33 32120 32121_pacman_map_level3 : 32122 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjA5IDEgMSAxICMxMDEKeJxVTlsOwDAIAve5K+z+N+zStGomeyTdjwIKYT9IoHGAbpOgdQ3n1"\ 32123 "i1ZinHdnO+20FuKg3nf4WIO3YolP8QEQ75CEkoKaUIDT3K95w8OZbp4lDcMj1PNUjXyDg+u4LTGC5LiOwAxIDIwIDEgMSAjMjYKeJ"\ 32124 "xz941iSM/NTI43AAK95Mzc9CoGAD5VBfY=" 32125 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 32126 _rlevel=33 _glevel=200 _blevel=255 32127 32128_pacman_map_level4 : 32129 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjEwIDEgMSAxICM5MAp4nHVPQQ6AMAhr8egX/P8TN+cGGSy6TBMTQgqlUPaDBDINLBJZbMQHq"\ 32130 "mwq7e40eahgy8i/jDKB1QhlRWBzcPH09Rnr9ALTrHSOuN5N+IFF9LIY9uOPDitcQvExIDIwIDEgMSAjMjYKeJxz941iSM/NTI43AA"\ 32131 "K95Mzc9CoGAD5VBfY=" 32132 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 32133 _rlevel=200 _glevel=200 _blevel=33 32134 32135_pacman_map_level5 : 32136 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjA3IDEgMSAxICMxMDAKeJxdjlEKxCAMRPOmn3uF3v+ELXRrDE2qwrIgzPB8Mn52MDv4ihBbQ"\ 32137 "yjQyuRBz96RF8NmSYAb98s65j95Wd0bFqxG1MNV/s1ealMujRHdI5wtf9X0WnWmFWO/7JmJXScPVxI1CjEgMjAgMSAxICMyNgp4nH"\ 32138 "P3jWJIz81MjjcAAr3kzNz0KgYAPlUF9g==" 32139 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 32140 _rlevel=200 _glevel=255 _blevel=33 32141 32142_pacman_map_level6 : 32143 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMTgzIDEgMSAxICM5Mgp4nGVO0QqAQAhz67Ff6P+/sK66TNqJUBCozDHn5gUwW9EIBnhi2nmBP"\ 32144 "QmHCeMwDbuzBNCH1oZeDBEiPSWiAoXU8Yfhn4PyiNc1X3i99NwUJPMoVyVs3PAASqEr4jEgMjAgMSAxICMyNgp4nHP3jWJIz81Mjj"\ 32145 "cAAr3kzNz0KgYAPlUF9g==" 32146 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 32147 _rlevel=255 _glevel=130 _blevel=233 32148 32149#@cli x_paint 32150#@cli : Launch the interactive painter. 32151x_paint : check_display $0 32152 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32153 e[] "\n 32154------ "${g}"Interactive painter"$n" -----------------------\n 32155----\n 32156---- Use "${c}"mouse"$n" to select color and brush.\n 32157---- "${c}"Left button"$n" draws a colored stroke.\n 32158---- "${c}"Right button"$n" fills a colored region.\n 32159---- "${c}"Arrow keys"$n" or '"${c}"SPACE"$n"' and '"${c}"BACKSPACE"$n"' to swap\n 32160---- between available images.\n 32161---- Key '"${c}"S"$n"' to save snapshot of the current view.\n 32162---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 32163----\n 32164--------------------------------------------------" 32165 to_rgb 32166 if !$! i[0] 512,512,1,3,255 nm[0] "[New image]" else k[0] fi 32167 1 # Brush image [-1] 32168 parallel "_x_paint[]","w[] 400,320,0,Palette x_select_color[] __color,0,0,0" k[0] 32169 32170_x_paint : 32171 32172 # Init variables. 32173 pass[-2,-1] 1 ('{-2,n}') discard. {'_c1'} nm... {t} rm. 32174 __color={0,if(ia<128,vector3(255),vector3(0))} 32175 brushsize=1 32176 brushopacity=0 32177 brushangle=90 32178 brushthickness=1 32179 image=0 32180 refresh_image=1 32181 refresh_brush=1 32182 ox1=-1 32183 oy1=-1 32184 32185 # Start user event loop. 32186 do 32187 32188 # Open/refresh brush window. 32189 if $refresh_brush 32190 rm. (32,64;64,32) r. 16,16,1,3,1 r. {8*48},{4*48},1,3,0,2 32191 repeat 4,y repeat 8 32192 ellipse. {48*$>+24},{48*$y+24},{2*$>+1},{(2*$>+1)*$brushthickness},$brushangle,{1-$y/4},255 32193 done done 32194 rectangle. {$brushsize*48},{$brushopacity*48},\ 32195 {$brushsize*48+47},{$brushopacity*48+47},\ 32196 1,0xFFFFFFFF,255,128,128 32197 {w},16,1,3 line. 0,50%,100%,50%,1,0x55555555,128,64,128 32198 bx={$brushangle*w/180} 32199 rectangle. {$bx-16},20%,{$bx+16},80%,1,128 32200 line. {$bx-16},20%,{$bx+16},20%,1,255 line. {$bx+16},20%,{$bx+16},80%,1,255 32201 line. {$bx-16},80%,{$bx+16},80%,1,64 line. {$bx-16},20%,{$bx-16},80%,1,64 32202 a[-2,-1] y 32203 16,{h-16},1,3 line. 50%,0,50%,100%,1,0x55555555,128,64,128 32204 by={$brushthickness*(h-16)} 32205 rectangle. 20%,{$by-16},80%,{$by+16},1,128 32206 line. 20%,{$by-16},80%,{$by-16},1,255 line. 80%,{$by-16},80%,{$by+16},1,255 32207 line. 20%,{$by-16},20%,{$by+16},1,64 line. 20%,{$by+16},80%,{$by+16},1,64 32208 a[-2,-1] x 32209 w3. {w},{h},0,"Brush" 32210 refresh_brush=0 32211 fi 32212 32213 # Open/refresh image window. 32214 if $refresh_image 32215 w1[$image] {$image,w},{$image,h},0,"Image "\#$image" : "{$image,b}.{$image,x} 32216 refresh_image=0 32217 fi 32218 32219 # Manage user events. 32220 x1={*1,x} y1={*1,y} 32221 x2={*2,x} y2={*2,y} 32222 x3={*3,x} y3={*3,y} 32223 32224 if $x1>=0 # Event in the image window. 32225 if {*1,b}&1 # Left button -> draw brush stroke. 32226 ox1={if($ox1<0,$x1,$ox1)} 32227 oy1={if($oy1<0,$y1,$oy1)} 32228 delta={max(abs($x1-$ox1),abs($y1-$oy1))} 32229 r1={2*$brushsize+1} 32230 r2={$r1*$brushthickness} 32231 dx={2*($x1-$ox1)/max(1,$delta)} 32232 dy={2*($y1-$oy1)/max(1,$delta)} 32233 o={1-($brushopacity/4)^0.04} 32234 repeat max(1,($delta+1)/2) 32235 ellipse[$image] {$ox1+$>*$dx},{$oy1+$>*$dy},$r1,$r2,$brushangle,$o,$__color 32236 done 32237 ox1=$x1 oy1=$y1 32238 refresh_image=1 32239 else 32240 ox1=-1 oy1=-1 32241 if {*1,b}&2 # Right button -> fill region. 32242 flood[$image] $x1,$y1,0,10,0,1,$__color 32243 refresh_image=1 32244 fi 32245 fi 32246 fi 32247 32248 if {*1,ARROWRIGHT}" || "{*2,ARROWRIGHT}" || "{*3,ARROWRIGHT}" || "\ # Manage image selection. 32249 {*1,ARROWUP}" || "{*2,ARROWUP}" || "{*3,ARROWUP}" || "\ 32250 {*1,SPACE}" || "{*2,SPACE}" || "{*3,SPACE} 32251 image={($image+1)%($!-2)} refresh_image=1 32252 elif {*1,ARROWLEFT}" || "{*2,ARROWLEFT}" || "{*3,ARROWLEFT}" || "\ 32253 {*1,ARROWDOWN}" || "{*2,ARROWDOWN}" || "{*3,ARROWDOWN}" || "\ 32254 {*1,BACKSPACE}" || "{*2,BACKSPACE}" || "{*3,BACKSPACE} 32255 image={($image-1)%($!-2)} refresh_image=1 32256 fi 32257 32258 if {*1,S} o[$image] gmic_paint.png fi # Save snapshot if requested. 32259 32260 if {*3,b}" && "$x3>=0 # Manage brush selection. 32261 if $x3<384" && "$y3>=192 brushangle={$x3*180/(w-16)} # Bottom slider -> select brush angle. 32262 elif $x3>=384" && "$y3<192 brushthickness={$y3/(h-16)} # Right slider -> select brush thickness. 32263 elif $x3<384" && "$y3<192 brushsize={int($x3*8/(w-16))} brushopacity={int($y3*4/(h-16))} 32264 fi 32265 refresh_brush=1 32266 fi 32267 wait 32268 while {*1}" && "!{*1,Q}" && "!{*1,ESC} 32269 32270 # Exit properly. 32271 __color=-1 w1[] 0 w2[] 0 w3[] 0 rm[-2,-1] 32272 32273#@cli x_plasma 32274#@cli : Launch the plasma effect demo. 32275x_plasma : check_display $0 32276 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32277 e[] "\n 32278------ "${g}"Plasma effect"$n" ----------------------\n 32279----\n 32280---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 32281---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 32282---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 32283----\n 32284-------------------------------------------" 32285 l[] 32286 32287 # Init plasma backgrounds. 32288 N=8 32289 repeat $N 32290 320,200,1,3 rand. 0,255 plasma. 1,0,7 n. 0,255 32291 amp={u(-40,40)} freq={round(u(2,6))} dir$>={if(u<0.5,-1,1)*round(u(1,2))} 32292 100%,100%,1,1,'$amp*cos(y*2*pi*$freq/h)' 32293 done 32294 32295 {w+2},100%,1,1,'x' 100%,100%,1,1,'Y=(y-80+15*cos(x/30)+10*sin(x/22));if(Y<0||Y>=50,-1,Y)' a[-2,-1] c 32296 0 t. "** Welcome to G\47MIC, a powerful image processing framework **",0,0,50,1,255 32297 b. 0.5 n. 0,255 32298 M={w} 32299 32300 # Start animation loop. 32301 w[] {0,f=1.5*h<0.5*{*,v}?3:1.5;[w,h]*=f},0,"[G"{`39`}"MIC] Plasma Effect" 32302 t=0 tt={-1.5*{0,w}} 32303 32304 do 32305 tic=$| 32306 32307 # Render interpolated background between two successive plasmas. 32308 a={int($t)} a2={2*$a} a21={$a2+1} 32309 b={($a+1)%$N} b2={2*$b} b21={$b2+1} 32310 +warp[$a2] [$a21],1,0,2 32311 +warp[$b2] [$b21],1,0,2 32312 j.. .,0,0,0,0,{$t-$a} rm. 32313 32314 shift[$a21] 0,${dir$a},0,0,2 # Animate plasma background. 32315 shift[$b21] 0,${dir$b},0,0,2 32316 if int($t+0.005)>int($t) dir$a={if(u<0.5,-1,1)*round(u(1,3))} fi 32317 t={($t+max(0.005,($|-$tic)))%$N} 32318 32319 # Render text scrolling. 32320 +z.. $tt,{$tt+w-1+2} 32321 warp. [-4],0,0,0 32322 r. 100%,100%,1,3 32323 +*. -1 +. 255 32324 j... .,0,0,0,0,1,..,255 rm. 32325 j.. .,-2,-2,0,0,1,.,255 rm. 32326 32327 tt+={max(2,($|-$tic)*250)} # Animate scrolling. 32328 if $tt>=$M tt={-1.5*{0,w}} fi 32329 32330 # Display rendered frame. 32331 fps=${-fps} if $fps>0 to. $fps" fps",5,5,16,1,0.2 fi 32332 w. 32333 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 32334 rm. wait 20 32335 while {*}" && "!{*,ESC}" && "!{*,Q} 32336 rm[{-2*$N-2}--1] w[] 0 endl 32337 32338#@cli x_quantize_rgb : _nbcolors>=2 32339#@cli : Launch the RGB color quantization demo. 32340x_quantize_rgb : check "isint(${1=16}) && $1>1" check_display $0 32341 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32342 e[] "\n 32343------ "${g}"RGB Quantization"$n" --------------------------------------\n 32344----\n 32345---- This demo shows how RGB colors can be quantified using\n 32346---- the "${c}"k-means algorithm"$n".\n 32347----\n 32348---- "${c}"Left mouse button"$n" on 3D view rotates the color cube.\n 32349---- "${c}"Right mouse button"$n" on 3D view toggles colors/clusters mode.\n 32350---- "${c}"Left mouse button"$n" on image toggles dithering mode,\n 32351---- "${c}"Left mouse button"$n" on colormap adds a random color.\n 32352---- "${c}"Right mouse button"$n" on colormap removes a color.\n 32353---- Key '"${c}"R"$n"' init colormap with random values.\n 32354---- Key '"${c}"U"$n"' init colormap with uniform sampling.\n 32355---- Key '"${c}"M"$n"' init colormap with median-cut algorithm.\n 32356---- Key '"${c}"SPACE"$n"' does a single iteration of k-means and pauses.\n 32357---- Key '"${c}"ENTER"$n"' runs k-means algorithm.\n 32358---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 32359---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 32360---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 32361----\n 32362--------------------------------------------------------------" 32363 32364 if !$! sp ? fi 32365 k[0] to_rgb if h>300 r2dy 300 round 1 fi nm. img # Resize input image if necessary. 32366 +r {w*h},1,1,3,-1 r. {min(w,8192)},1,1,3 nm. colors # Get reduced set of image colors. 32367 $1,1,1,3 rand. 0,255 round. 1 nm. centroids # Initialize random centroids. 32368 _x_quantize_rgb_3d (1,0,0,0;0,1,0,0;0,0,1,0) nm. pose3d # Init 3D object. 32369 _x_quantize_rgb_text "Colors",clustering0 32370 _x_quantize_rgb_text "Clusters",clustering1 32371 _x_quantize_rgb_text "Dithering: off",dithering0 32372 _x_quantize_rgb_text "Dithering: on",dithering1 32373 if {img,h<300} +r2dy[img] 300,1 else [img] fi # Generate visualization canvas. 32374 {w+315},365,1,3,255 rm.. 32375 rectangle. 4,4,305,305,1,0xFFFFFFFF,0 32376 rectangle. 309,4,{w-5},305,1,0xFFFFFFFF,0 32377 rectangle. 4,309,{w-5},360,1,0xFFFFFFFF,0 32378 .,. 32379 rectangle. 310,5,{w-6},305,1,1 32380 rectangle. 5,310,{w-6},360,1,2 32381 300,300,1,1,'(y<<11)+(x<<2)+3' j.. .,5,5 rm. 32382 a[-2,-1] c nm. visu 32383 32384 # Start k-means iterations. 32385 dithering=0 clustering=0 pause=1 s0=off s1=on 32386 do 32387 32388 # Create and display visualization. 32389 if !narg($visu_3d) # Update 3D vizualization. 32390 +-[centroids] 2 ++[centroids] 2 a[-2,-1] x permute. cxyz y. -. 128 32391 j[obj3d] .,0,8 rm. # Update centroids position in 3D object. 32392 [obj3d] 32393 if $clustering 32394 if {colors,iM}<256 # Estimate nearest centroids for all colors. 32395 +index[colors] [centroids] *. 256 +[colors,-1] 32396 fi 32397 +channels[colors] 0 >>. 8 map. 2 permute. cxyz y. j.. .,0,{{-2,h}-$_N-h} rm. 32398 fi 32399 32400 pose3d. {pose3d,^} 300,300,1,3 j3d. ..,50%,50%,100,1,2,0,0,300 rm.. 32401 j. [clustering$clustering],2,0,0,0,1,[mclustering$clustering],255 32402 nm. visu_3d j[visu] [visu_3d],5,5 32403 fi 32404 32405 if !narg($visu_img) # Update indexed image. 32406 +index[img] [centroids],{0.7*$dithering},1 if h<300 r2dy. 300,1 fi 32407 j. [dithering$dithering],2,0,0,0,1,[mdithering$dithering],255 32408 nm. visu_img j[visu] [visu_img],310,5 32409 fi 32410 32411 if !narg($visu_centroids) # Update colormap. 32412 +luminance[centroids] a. [centroids],y sort. +,x rows. 1 r. {visu,w-10},50,1,3 32413 0 t. "Colors: "{centroids,w},2,0,16,1,255,255,255 +dilate. 3 j... ..,2,2,0,0,1,.,255 32414 rm[-2,-1] nm. visu_centroids j[visu] [visu_centroids],5,310 32415 fi 32416 l[visu] 32417 w -1,-1,0,"[G"{`39`}"MIC] RGB Quantization" 32418 if {*,CTRLLEFT}" && "{*,D} w[] {2*w},{2*h} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 32419 endl 32420 32421 # Check for user's interactions. 32422 x={int({*,x}*{visu,w}/{*,w})} 32423 y={int({*,y}*{visu,h}/{*,h})} 32424 b={*,b} 32425 i={visu,i($x,$y,0,3)} 32426 if $b&1" && "$i==1 # Toggle dithering. 32427 dithering={!$dithering} rm[visu_img] wait -1 32428 elif $b&1" && "$i==2 # Add new color. 32429 (${-rgb}) y. c a[centroids,-1] x _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 32430 pause=1 wait 100 32431 elif $b&2" && "$i==2" && "{centroids,w}>2 # Remove color. 32432 r[centroids] {centroids,w-1} _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 32433 pause=1 wait 100 32434 elif $b&2" && "$i>=3 # Toggle clusters/colors mode. 32435 clustering={!$clustering} rm[visu_3d] wait -1 32436 elif {*,M} # Init colormap with median-cut. 32437 +&[colors] 255 colormap. {centroids,w},0,0 rm[centroids] nm. centroids 32438 _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 32439 pause=1 wait -1 32440 elif {*,R} # Init colormap with random values. 32441 rand[centroids] 0,255 round[centroids] 1 32442 _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 32443 pause=1 wait -1 32444 elif {*,U} # Init colormap with uniform sampling. 32445 uniform_distribution {centroids,w},3 *. 255 rm[centroids] nm. centroids 32446 _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 32447 pause=1 wait -1 32448 elif {*,ENTER} # Start k-means iterations. 32449 pause=0 32450 elif $b&1" && "$i>=3 # Manage 3D view rotation. 32451 coords={visu,i($x,$y,0,3)-3} u1={(($coords>>2)&511)-150} v1={($coords>>11)-150} 32452 if !narg($u0) u0=$u1 v0=$v1 fi 32453 if $u0!=$u1" || "$v0!=$v1 32454 n0={sqrt(($u0)^2+($v0)^2)} 32455 nu0={if($n0>135,$u0*135/$n0,$u0)} nv0={if($n0>135,$v0*135/$n0,$v0)} nw0={sqrt(max(0,18225-($nu0)^2-($nv0)^2))} 32456 n1={sqrt(($u1)^2+($v1)^2)} 32457 nu1={if($n1>135,$u1*135/$n1,$u1)} nv1={if($n1>135,$v1*135/$n1,$v1)} nw1={sqrt(max(0,18225-($nu1)^2-($nv1)^2))} 32458 u={$nv0*$nw1-$nw0*$nv1} v={$nw0*$nu1-$nu0*$nw1} w={$nv0*$nu1-$nu0*$nv1} n={sqrt(($u)^2+($v)^2+($w)^2)} 32459 rotation3d[] $u,$v,$w,{-asin($n/18225)*180/pi} mv[pose3d] $! m*[-2,-1] nm. pose3d 32460 u0=$u1 v0=$v1 rm[visu_3d] 32461 fi 32462 elif !($b&1) u0= 32463 fi 32464 32465 if !$pause" || "{*,SPACE} # Do one iteration of k-means. 32466 pause={*,-SPACE} 32467 32468 # Estimate new centroids positions. 32469 &[colors] 255 +index[colors] [centroids] *. 256 +[colors,-1] # Estimate nearest centroids for all colors. 32470 repeat s#$colors # Recompute centroid positions. 32471 sh[colors] $> +histogram. {centroids,w*256},0,{centroids,w*256-1} rm.. 32472 i.. 256,1,1,1,'x' r.. {w},1,1,1,0,2 *.. . r[-2,-1] {centroids,w},1,1,1,2 max. 0.01 /[-2,-1] 32473 done a[-{colors,s}--1] c 32474 rm[centroids] nm. centroids 32475 32476 # Reassign unused centroids. 32477 +>>[colors] 8 channels. 0 histogram. {centroids,w},0,{centroids,w-1} 32478 cmax={xM} 32479 repeat w if !i($>) point[centroids] $>,0,0,1,{centroids,I($cmax)} point[centroids] $>,0,0,-0.001,${-rgb} fi done 32480 rm. c[centroids] 0,255 32481 32482 if $visu_3d rm[visu_3d] fi 32483 if $visu_img rm[visu_img] fi 32484 if $visu_centroids rm[visu_centroids] fi 32485 wait 20 32486 32487 else if $visu_img wait fi 32488 fi 32489 32490 while {*}" && "!{*,Q}" && "!{*,ESC} 32491 rm w 0 32492 32493 _x_quantize_rgb_3d : 32494 if $obj3d rm[obj3d] fi 32495 +distribution3d[centroids] circles3d. 5 col3d. 255 # Pre-compute 3D object. 32496 colorcube3d p3d. 1 32497 +&[colors] 255 distribution3d. circles3d. 3 o3d. 0.25 +3d[-3--1] 32498 -3d. 128,128,128 nm. obj3d _N={i[7]} 32499 32500_x_quantize_rgb_text : 32501 0 t. "$1",0,0,16,1,255 r. {w+2},15,1,1,0,0,0.5,0.5 +dilate. 3 to_rgb.. 32502 nm.. $2 nm. m$2 32503 32504#@cli x_reflection3d 32505#@cli : Launch the 3D reflection demo. 32506x_reflection3d : check_display $0 32507 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32508 e[] "\n 32509------ "${g}"3D reflection"$n" ----------------------\n 32510----\n 32511---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 32512---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 32513---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 32514----\n 32515-------------------------------------------" 32516 32517 # Render background. 32518 128,256,1,3 rand. 0,255 plasma. 1,100 blur_xy. 30,2 32519 sh. 0 n. 0,90 rm. sh. 1 n. 0,60 rm. sh. 2 n. 0,180 rm. 32520 +mirror. x [-2,-1] a[-4--1] x 32521 +luminance. mirror. x b. 2 n. 0,255 32522 32523 # Create 3D objects. 32524 torus3d 30,10 col3d. 255,200,0 32525 spherical3d 47,34,"80+20*abs(cos(2*theta))" s3d. rm.. i.. 3,{h},1,1,150,220,255,200,255,255 y.. a[-6--1] y 32526 spherical3d 47,34,"100*abs(1+0.6*cos(3*phi)*sin(4*theta))" 32527 r3d[-2,-1] 0,1,0,90 db3d 0 32528 32529 # Start animation loop. 32530 xb,xl,anim=0 32531 w[] 400,400,0,"[G"{`39`}"MIC] 3D Reflection" 32532 do 32533 32534 tic=$| 32535 # Recreate 3D interpolated background object. 32536 +rows. 8,{8+3*i[6]-1} +j... .,0,8,0,0,{if($anim<250,0,0.5-0.5*cos(($anim-250)/100))} rm.. 32537 32538 # Render 3D background object (with flat colors). 32539 +z[-6] $xb,0,{$xb+255},255 j3d. ..,75%,50%,0,1,3,0,0 32540 32541 # Render light reflection map. 32542 +z[-6] $xl,0,{$xl+255},255 32543 xf={min(30,$anim-70)+20*cos(1.8*$|)} 32544 yf={50+20*sin(2.7*$|)} 32545 j3d. [-6],{20+$xf}%,$yf%,0,1,4,0,0 32546 32547 # Add light reflection to 3D background object. 32548 l3d . rm. +j3d. ..,75%,50%,0,1,5,0,0 j.. .,0,0,0,0,0.6 rm[-3,-1] 32549 32550 # Add 3D foreground object. 32551 j3d. [-4],$xf%,$yf%,0,1,4,0,0 32552 32553 # Display frame and update animation variables. 32554 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-19},13,1,0.2 fi 32555 w. rm. 32556 32557 if {*,CTRLLEFT}" && "{*,D} w[] 800,800 elif {*,CTRLLEFT}" && "{*,C} w[] 400,400 fi 32558 xb={($xb+6)&255} 32559 xl={($xl-6)&255} 32560 anim+=1 32561 r3d[-2,-1] {sin(0.5*$|)},{cos($|)},1,{max(0.005,$|-$tic)*33} 32562 r3d... -1,0.3,0.8,{max(0.005,$|-$tic)*100} 32563 wait 20 32564 while {*}" && "!{*,ESC}" && "!{*,Q} 32565 rm[-5--1] w[] 0 32566 32567#@cli x_rubber3d 32568#@cli : Launch the 3D rubber object demo. 32569x_rubber3d : check_display $0 32570 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32571 e[] "\n 32572------ "${g}"3D rubber object"$n" -------------------\n 32573----\n 32574---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 32575---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 32576---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 32577----\n 32578-------------------------------------------" 32579 rm 32580 sphere3d 150,0 torus3d 70,15 cylinder3d 20,40 32581 col3d... 200,200,200,0.3 col3d.. 128,200,76 col3d. 200,128,76 32582 c3d[-3--1] r3d. 1,0,0,70 +3d[-3--1] +3d. 10,-8,20 *3d. 1.5 32583 400,400,64,3 32584 {w},{h},1,3,'if(c==0,x,if(c==1,y,y*{1,d}/h))' 32585 {w},{h},1,3 32586 w[] {w},{h},0,"[G"{`39`}"MIC] 3D Rubber Object" 32587 frame=0 32588 do 32589 fps=${-fps} 32590 {w},{h},1,3 fc. 16,32,32 j3d. [0],50%,50%,0,1,3,0,0 j[1] .,0,0,$frame rm. 32591 r3d[0] 0.1,1,0.6,{3*cos($|*1.25)} r3d[0] 1,0.2,0.6,-1 32592 +warp[1] [2],0,0 *[3] 0.8 *. 0.2 +[3] . rm. 32593 if $fps>0 to. $fps" fps",5,{h-29},24,2,0.2 fi 32594 w. 32595 if {*,CTRLLEFT}" && "{*,D} w[] {2*w},{2*h} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 32596 wait[0] 20 32597 sh[2] 2 -. 1 &. {{1,d}-1} rm. 32598 frame={($frame-1)%{1,d}} 32599 while {*}" && "!{*,ESC}" && "!{*,Q} 32600 rm w 0 32601 32602#@cli x_segment : _max_resolution={ 0 | >=128 } 32603#@cli : Segment foreground from background in selected opaque RGB images, interactively. 32604#@cli : Return RGBA images with binary alpha-channels. 32605#@cli : Default value: 'max_resolution=1024'. 32606x_segment : check "${1=1024}==0 || $1>=128" check_display $0 32607 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32608 e[^-1] "Extract foreground from background in image$? interactively, with maximum resolution $1." 32609 e[] "\n 32610----------------------------------------------------------------------------------------------------\n 32611----\n 32612---- "${c}"Left mouse button"$n" or key '"${c}"F"$n"' create a new foreground control point 32613 (or move an existing one).\n 32614---- "${c}"Right mouse button"$n" or key '"${c}"B"$n"' create a new background control point 32615 (or move an existing one).\n 32616---- "${c}"Mouse wheel"$n", or keys '"${c}"CTRL+arrows UP/DOWN"$n"' zoom view in/out.\n 32617---- '"${c}"CTRL+mouse wheel"$n"', '"${c}"SHIFT+mouse wheel"$n"' or "${c}"arrow keys"$n" move image in zoomed view.\n 32618---- Key '"${c}"SPACE"$n"' updates the extraction mask.\n 32619---- Key '"${c}"TAB"$n"' toggles background view modes.\n 32620---- Key '"${c}"M"$n"' toggles marker view modes.\n 32621---- Key '"${c}"BACKSPACE"$n"' deletes the last control point added.\n 32622---- Key '"${c}"PAGE UP"$n"' increases background opacity.\n 32623---- Key '"${c}"PAGE DOWN"$n"' decreases background opacity.\n 32624---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 32625---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 32626---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 32627---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' exit the interactive window.\n 32628----\n 32629----------------------------------------------------------------------------------------------------" 32630 repeat $! l[$>] 32631 32632 # Init variables and images. 32633 name={0,n} title={0,b} if narg({0,x}) title=$title.{0,x} fi 32634 w={w} h={h} fdim=${fitscreen[]\ $w,$h} ww={arg(1,$fdim)} wh={arg(2,$fdim)} x0=0 y0=0 x1={w-1} y1={h-1} 32635 selection=-1 marker_mode=2 xpan=-1 ypan=-1 bg_mode=0 opacity=64 32636 to_rgb nm img 32637 32638 if narg($_gui_control_points)>=4 # Import list of control points from plug-in GUI. 32639 ($_gui_control_points) r. {w/4},4,1,1,-1 32640 else 0 # Empty list of control points. 32641 fi 32642 nm. points 32643 32644 # Compute potential map. 32645 if $1>0 if $w>$h +r2dx[img] {min($1,$w)},2 else +r2dy[img] {min($1,$h)},2 fi else [img] fi 32646 _x_segment. 32647 pw={potential,w} ph={potential,h} 32648 32649 # Start event loop. 32650 do 32651 32652 # Handle user events for zoom/navigation/resizing. 32653 wait 32654 x={*,x} y={*,y} b={*,b} o={*,-o} 32655 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 32656 is_shift={{*,SHIFTLEFT}" || "{*,SHIFTRIGHT}} 32657 is_mouseout={$x<0" || "$y<0} 32658 x={$x0+$x*($x1-$x0+1)/$ww} y={$y0+$y*($y1-$y0+1)/$wh} 32659 oww=$ww owh=$wh ox0=$x0 oy0=$y0 ox1=$x1 oy1=$y1 32660 32661 if {*,r} # When window resized. 32662 nww={*,d} nwh={*,e} m={min($nww,$nwh)} 32663 cx={($x0+$x1)/2} cy={($y0+$y1)/2} dx={$nww*($x1-$x0+1)/$ww} dy={$nwh*($y1-$y0+1)/$wh} 32664 x0={$cx-$dx/2} x1={$cx+$dx/2} 32665 y0={$cy-$dy/2} y1={$cy+$dy/2} 32666 ww=$nww wh=$nwh 32667 elif $is_ctrl" && "{*,-D} # Increase window size. 32668 nww={min({*,u},$ww*1.25)} nwh={min({*,v},$wh*1.25)} m={min($nww,$nwh)} 32669 if $m==$nww ww=$m wh={$h*$m/$w} else ww={$w*$m/$h} wh=$m fi 32670 elif $is_ctrl" && "{*,-C} # Decrease window size. 32671 nww={$ww/1.25} nwh={$wh/1.25} 32672 if min($nww,$nwh)>=64 ww=$nww wh=$nwh fi 32673 elif $is_ctrl" && "{*,-R} # Reset window size. 32674 fdim=${fitscreen[]\ $w,$h} ww={arg(1,$fdim)} wh={arg(2,$fdim)} 32675 x0=0 y0=0 x1={$w-1} y1={$h-1} 32676 elif ($is_shift" && "$o<0)" || "{*,ARROWLEFT} # Go left. 32677 dx={($x1-$x0)/6} x0-=$dx x1-=$dx 32678 elif ($is_shift" && "$o>0)" || "{*,ARROWRIGHT} # Go right. 32679 dx={($x1-$x0)/6} x0+=$dx x1+=$dx 32680 elif ($is_ctrl" && "$o>0)" || "({*,ARROWUP}" && "!$is_ctrl) # Go up. 32681 dy={($y1-$y0)/6} y0-=$dy y1-=$dy 32682 elif ($is_ctrl" && "$o<0)" || "({*,ARROWDOWN}" && "!$is_ctrl) # Go down. 32683 dy={($y1-$y0)/6} y0+=$dy y1+=$dy 32684 elif $o>0" || "($is_ctrl" && "{*,ARROWUP}) # Zoom in. 32685 if $x1-$x0>16" && "$y1-$y0>16 32686 cx={if($x>=0" && "!{*,ARROWUP},$x,($x0+$x1)/2)} 32687 cy={if($y>=0" && "!{*,ARROWUP},$y,($y0+$y1)/2)} 32688 x0={$cx+($x0-$cx)*0.75} y0={$cy+($y0-$cy)*0.75} 32689 x1={$cx+($x1-$cx)*0.75} y1={$cy+($y1-$cy)*0.75} 32690 fi 32691 elif $o<0" || "($is_ctrl" && "{*,ARROWDOWN}) # Zoom out. 32692 zfactor={max(($x1-$x0+1)/$w,($y1-$y0+1)/$h)} 32693 if $zfactor<1.3 32694 cx={if($x>=0" && "!{*,ARROWDOWN},$x,($x0+$x1)/2)} 32695 cy={if($y>=0" && "!{*,ARROWDOWN},$y,($y0+$y1)/2)} 32696 x0={$cx+($x0-$cx)/0.75} y0={$cy+($y0-$cy)/0.75} 32697 x1={$cx+($x1-$cx)/0.75} y1={$cy+($y1-$cy)/0.75} 32698 dx={$zfactor^2*($w-$x0-$x1)/2} dy={$zfactor^2*($h-$y0-$y1)/2} 32699 x0+=$dx x1+=$dx y0+=$dy y1+=$dy 32700 else 32701 dx={($w-$x0-$x1)/2} dy={($h-$y0-$y1)/2} 32702 x0+=$dx x1+=$dx y0+=$dy y1+=$dy 32703 fi 32704 elif $b&4" && "!$is_mouseout # Pan. 32705 if $panx<0" && "$pany<0 panx=$x pany=$y 32706 else dx={round($panx-$x)} dy={round($pany-$y)} x0+=$dx y0+=$dy x1+=$dx y1+=$dy 32707 fi 32708 else panx=-1 pany=-1 32709 fi 32710 if $ww!=$oww" || "$wh!=$owh" || "$ox0!=$x0" || "$oy0!=$y0" || "$ox1!=$x1" || "$oy1!=$y1 rm[baseview] fi 32711 32712 # Handle events related to control points management. 32713 N={points,w} 32714 is_left_button={$b&1" || "{*,F}} is_right_button={$b&2" || "{*,B}} 32715 is_button={$is_left_button" || "$is_right_button} 32716 if narg($baseview)" && "$is_button" && "$x>=0" && "$y>=0" && "$x<$w" && "$y<$h 32717 if $selection==-1" && "$N # Check for selection of an existing point. 32718 ($x;$y) r. $N,2 -. [points] *. {max($ww,$wh)/max($x1-$x0,$y1-$y0)} sqr. s. y +[-2,-1] 32719 dmin={im} selection={if($dmin>25,-1,xm)} rm. 32720 fi 32721 if $selection>=0 32722 if $marker_mode # Move existing point. 32723 +columns[points] $selection ox={i[0]} oy={i[1]} 32724 =. $x =. $y,0,1 =. {1+$is_left_button},0,3 32725 j[points] .,$selection rm. rm[view] 32726 fi 32727 else # Add new foreground or background point. 32728 ($x;$y;0;{1+$is_left_button}) a[points,-1] x selection=$N if !$marker_mode marker_mode=2 fi rm[view] 32729 fi 32730 else selection=-1 32731 if {*,SPACE}" && "narg($labels) rm[labels] # Update labels. 32732 elif {*,TAB}" && "narg($baseview) # Toggle background view modes 32733 bg_mode={($bg_mode+1)%6} rm[baseview] wait -1 32734 elif {*,M}" && "narg($view) # Toggle markers view modes 32735 marker_mode={($marker_mode-1)%3} rm[view] wait -1 32736 elif {*,PAGEDOWN}" && "narg($baseview) # Decrease background opacity 32737 opacity={max(0,$opacity-32)} rm[baseview] wait -1 32738 elif {*,PAGEUP}" && "narg($baseview) # Increase background opacity 32739 opacity={min(255,$opacity+32)} rm[baseview] wait -1 32740 elif {*,BACKSPACE}" && "$N # Remove last point. 32741 if $N>1 z[points] 0,{$N-2} 32742 else i=$points rm[points] i[$i] 0 nm[$i] points 32743 fi rm[view] wait -1 32744 fi 32745 fi 32746 32747 # Manage zoomed view bounds. 32748 w2={round(($x1-$x0)/2)} h2={round(($y1-$y0)/2)} 32749 if $x0<-$w2 x1-={$x0+$w2} x0=-$w2 fi 32750 if $y0<-$h2 y1-={$y0+$h2} y0=-$h2 fi 32751 if $x1>=$w+$w2 x0+={$w-1+$w2-$x1} x1={$w-1+$w2} fi 32752 if $y1>=$h+$h2 y0+={$h-1+$h2-$y1} y1={$h-1+$h2} fi 32753 32754 # Render labels. 32755 if !narg($labels) 32756 N={points,w} 32757 if narg($view) to[view] "Processing...",5,5,20,2 w[view] fi 32758 if $N 32759 [points] 32760 sh. 0,0,0,0 *. {$pw/$w} rm. 32761 sh. 1,1,0,0 *. {$ph/$h} rm. 32762 pointcloud. -1,$pw,$ph dilate. 3 32763 watershed. [potential] -. 1 32764 else [potential],[potential],1,1,1 32765 fi 32766 nm. labels 32767 if narg($baseview) rm[baseview] fi 32768 fi 32769 32770 # Render base image. 32771 if !narg($baseview) 32772 nx0={$x0*$pw/$w} ny0={$y0*$ph/$h} 32773 nx1={$x1*$pw/$w} ny1={$y1*$ph/$h} 32774 +z[img] $x0,$y0,$x1,$y1 32775 r. $ww,$wh,1,100%,{if($ww<w" && "$wh<h,2,1)} 32776 +z[labels] $nx0,$ny0,$nx1,$ny1 32777 r. $ww,$wh,1,100%,{if($ww<w" && "$wh<h,2,3)} 32778 if $bg_mode>=3 *. -1 +. 1 fi 32779 *. {255-$opacity} +. $opacity a[-2,-1] c 32780 if $bg_mode%3>=1 i.. 100%,100%,1,3,{(($bg_mode-1)%3)*255} blend[-2,-1] alpha 32781 else drgba. 32782 fi 32783 nm. baseview 32784 if narg($view) rm[view] fi 32785 fi 32786 32787 # Render view. 32788 if !narg($view) 32789 [baseview] r. 100%,100%,1,3 32790 if $marker_mode 32791 if $marker_mode==2 rad1=5 rad2=3 opa=1 else rad1=3 rad2=2 opa=0.8 fi 32792 col0=255,0,0 col1=0,255,0 32793 repeat w#$points 32794 +columns[points] $> x={(i[0]-$x0)*$ww/(1+$x1-$x0)} y={(i[1]-$y0)*$wh/(1+$y1-$y0)} l={i[3]-1} rm. 32795 circle. $x,$y,$rad1,1,0 circle. $x,$y,$rad2,$opa,${col$l} 32796 done 32797 fi 32798 32799 nm. view 32800 w[view] $ww,$wh,0,$title 32801 fi 32802 32803 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,ENTER} 32804 32805 # Recompute labels at full resolution. 32806 if narg($view) to[view] "Processing fullres...",5,5,20,2 w[view] fi 32807 k[img,points] 32808 N={points,w} status= 32809 if $N 32810 status={points,^} 32811 [img] _x_segment. pointcloud[points] -1,$w,$h 32812 zfact={{img,max(w,h)}/{potential,max(w,h)}} dilate[points] {int(3*$zfact)} 32813 watershed[points] [potential] -[points] 1 k[img,points] 32814 *. 255 32815 else k[img] [img],[img],1,1,255 32816 fi 32817 a c nm $name 32818 32819 endl done 32820 u $status # Return control points of last image. 32821 w 0 32822 32823# Compute potential function. 32824_x_segment : 32825 b. 0.2% gradient_norm. f. '1/(1+i^2)' 32826 nm. potential 32827 32828#@cli x_select_color : _variable_name 32829#@cli : Display a RGB or RGBA color selector. 32830#@cli : Argument 'variable_name' specifies the variable that contains the selected color values (as R,G,B,[A]) 32831#@cli : at any time. 32832#@cli : Its value specifies the initial selected color. Assigning '-1' to it forces the interactive window to close. 32833#@cli : Default value: 'variable_name=xsc_variable'. 32834x_select_color : skip ${1=xsc_variable} check_display $0 32835 rm 32836 n={narg($$1)} if !$n $1=0,0,0 fi 32837 rgba_mode={$n>=4} R={arg(1,$$1)} G={arg(2,$$1)} B={arg(3,$$1)} A={if($rgba_mode,arg(4,$$1),255)} 32838 e[^-1] "Open "${arg\ 1+$rgba_mode,RGB,RGBA}" color selector widget, with variable '$1' and starting color "\ 32839 ($$1)"." 32840 if !{*} w[] {400+24*$rgba_mode},400,0,"Select a color" fi 32841 update_view=1 is_sv=0 is_h=0 is_a=0 colordb=0 is_thread_variable={arg(1,{'$1'})==_'_'" && "arg(2,{'$1'})==_'_'} 32842 32843 # Manage color presets. 32844 m "add_preset : if !narg($_xsc_preset$""1) _xsc_preset$""1=$""2,$""3,$""4 fi" 32845 add_preset 0,0,0,0,0 add_preset 1,255,255,255 add_preset 2,255,0,0 add_preset 3,0,255,0 32846 add_preset 4,0,0,255 add_preset 5,255,255,0 add_preset 6,255,0,255 add_preset 7,0,255,255 32847 add_preset 8,50,50,50 add_preset 9,100,100,100 add_preset 10,150,150,150 add_preset 11,200,200,200 32848 um add_preset 32849 if !narg($_xsc_preset) _xsc_preset=11 fi 32850 ($R^$G^$B) c. 0,255 rgb2hsv. H={i[0]} S={i[1]} V={i[2]} rm. 32851 32852 # Start event loop. 32853 do 32854 w={*,d} h={*,e} x={*,x} y={*,y} b={*,b} 32855 32856 # Update base image. 32857 if !$! 32858 $w,$h,1,3,200 32859 if $rgba_mode x1={w-89} y1={h-57} x2={w-80} else x1={w-49} y1={h-57} x2={w-40} fi 32860 x0=8 y0=8 x3={$x2+31} x4={w-40} x5={$x4+31} x6={max($x0+232+32*$rgba_mode,w-152)} y6={$y1+7} 32861 rectangle {$x0-1},{$y0-1},{$x1+1},{$y1+1},1,0xFFFFFFFF,232 32862 line {$x0-1},{$y0-1},{$x1+1},{$y0-1},1,128 32863 line {$x0-1},{$y0-1},{$x0-1},{$y1+1},1,128 32864 (1;0) (0,1) r[-2,-1] {$x1-$x0+1},{$y1-$y0+1},1,1,3 i... 100%,100%,1,1,$H a[-3--1] c hsv2rgb. j.. .,$x0,$y0 rm. 32865 rectangle {$x2-1},{$y0-1},{$x3+1},{$y1+1},1,0xFFFFFFFF,232 32866 line {$x2-1},{$y0-1},{$x3+1},{$y0-1},1,128 32867 line {$x2-1},{$y0-1},{$x2-1},{$y1+1},1,128 32868 (359;0^1;1^1;1) r. {$x3-$x2+1},{$y1-$y0+1},1,3,3 hsv2rgb. j.. .,$x2,$y0 rm. 32869 if $rgba_mode 32870 rectangle {$x4-1},{$y0-1},{$x5+1},{$y1+1},1,0xFFFFFFFF,232 32871 line {$x4-1},{$y0-1},{$x5+1},{$y0-1},1,128 32872 line {$x4-1},{$y0-1},{$x4-1},{$y1+1},1,128 32873 (1;0) r. {$x5-$x4+1},{$y1-$y0+1},1,4,3 *. 255 drgba. j.. .,$x4,$y0 rm. 32874 fi 32875 t. "Current",$x0,{$y1+12},14,1,0 32876 if narg($_xsc_old) 32877 t. "Old",$x0,{$y1+34},14,1,0 32878 ($_xsc_old) y. c r. 48,16 drgba. r. {w+2},{h+2},1,3,0,0,0.5,0.5 j.. .,{$x0+55},{$y1+32} rm. 32879 fi 32880 repeat 12 32881 (${_xsc_preset$>}) -. 255 r. 4,1,1,1,0 +. 255 32882 y. c r. 18,18 drgba. frame. 1,1,{255*($>==$_xsc_preset)} 32883 j.. .,{$x6+($>%6)*25},{$y6+($>>=6)*25} rm. 32884 done 32885 update_view=1 32886 fi 32887 32888 # Update view. 32889 if $update_view 32890 . 32891 cx={$x0+$V*($x1-$x0)} cy={$y0+(1-$S)*($y1-$y0)} 32892 if $cx>$x0 line. {$cx-1},$y0,{$cx-1},$y1,1,200 fi 32893 if $cx<$x1 line. {$cx+1},$y0,{$cx+1},$y1,1,200 fi 32894 if $cy>$y0 line. $x0,{$cy-1},$x1,{$cy-1},1,200 fi 32895 if $cy<$y1 line. $x0,{$cy+1},$x1,{$cy+1},1,200 fi 32896 line. $x0,$cy,$x1,$cy,1,0 line. $cx,$y0,$cx,$y1,1,0 32897 cy={$y0+(359-$H)*($y1-$y0)/359} 32898 if $cy>$y0 line. $x2,{$cy-1},$x3,{$cy-1},1,200 fi 32899 if $cy<$y1 line. $x2,{$cy+1},$x3,{$cy+1},1,200 fi 32900 line. $x2,$cy,$x3,$cy,1,0 32901 if $rgba_mode 32902 cy={$y0+(255-$A)*($y1-$y0)/255} 32903 if $cy>$y0 line. $x4,{$cy-1},$x5,{$cy-1},1,200 fi 32904 if $cy<$y1 line. $x4,{$cy+1},$x5,{$cy+1},1,200 fi 32905 line. $x4,$cy,$x5,$cy,1,0 32906 fi 32907 ($H^$S^$V^$A) sh. 0,2 hsv2rgb. rm. round. R={i[0]} G={i[1]} B={i[2]} 32908 r. 48,16 drgba. r. {w+2},{h+2},1,3,0,0,0.5,0.5 j.. .,{$x0+55},{$y1+10} rm. 32909 t. "HSV ("{round($H)}","{round($S*255)}","{round($V*255)}")",{$x0+115},{$y1+24},14,1,0 32910 if $rgba_mode t. "RGBA ("$R","$G","$B","{round($A)}")",{$x0+115},{$y1+8},14,1,0 32911 else t. "RGB ("$R","$G","$B")",{$x0+115},{$y1+8},14,1,0 32912 fi 32913 ('${dec2hex\ {$R*65536+$G*256+$B}}') -. {'0'} r. 6,1,1,1,0,0,1,0 +. {'0'} 32914 f. if(i>=_'a'" && "i<=_'z',i+_'A'-_'a',i) 32915 t.. "html ""#"{t},{$x0+115},{$y1+40},14,1,0 rm. 32916 w. 100%,100%,0 rm. 32917 if $rgba_mode $1=$R,$G,$B,$A else $1=$R,$G,$B fi 32918 update_view=0 32919 fi 32920 if $is_thread_variable wait 50 else wait fi 32921 32922 # Manage window size. 32923 ww={*,w} wh={*,h} 32924 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 32925 if {*,r} ww={*,d} wh={*,e} 32926 elif $is_ctrl" && "{*,-D} ww={1.25*$ww} wh={1.25*$wh} 32927 elif $is_ctrl" && "{*,-C} ww={0.8*$ww} wh={0.8*$wh} 32928 elif $is_ctrl" && "{*,R} ww={400+24*$rgba_mode} wh=400 32929 fi 32930 ww={max(200,$ww)} wh={max(200,$wh)} 32931 if $ww!={*,w}" || "$wh!={*,h} w[] $ww,$wh rm fi 32932 32933 # Manage user events. 32934 if $b&1" && "$x>=0" && "$y>=0 32935 if !$is_h" && "!$is_a" && "($is_sv" || "($x>=$x0" && "$x<=$x1" && "$y>=$y0" && "$y<=$y1)) # SV selection 32936 S={max(0,min(1,1-($y-$y0)/($y1-$y0)))} V={max(0,min(1,($x-$x0)/($x1-$x0)))} 32937 update_view=1 colordb=0 is_sv=1 k[0] 32938 elif !$is_sv" && "!$is_a" && "($is_h" || "($x>=$x2" && "$x<=$x3" && "$y>=$y0" && "$y<=$y1)) # H selection 32939 H={max(0,min(359,359-($y-$y0)*359/($y1-$y0)))} 32940 colordb=0 is_h=1 rm 32941 elif !$is_sv" && "!$is_h" && "($is_a" || "($x>=$x4" && "$x<=$x5" && "$y>=$y0" && "$y<=$y1)) # A selection 32942 A={round(max(0,min(255,255-($y-$y0)*255/($y1-$y0))))} 32943 colordb=0 is_a=1 update_view=1 k[0] 32944 elif !$is_sv" && "!$is_h" && "!$is_a" && "{narg($_xsc_old)}" && "$x>=$x0+55" && "$x<=$x0+102" && "\ 32945 $y>=$y1+32" && "$y<=$y1+47 # Old color 32946 ($_xsc_old) y. c sh. 0,2 rgb2hsv. rm. H={i[0]} S={i[1]} V={i[2]} A={i[3]} 32947 colordb=0 rm 32948 elif !$is_sv" && "!$is_h" && "!$is_a" && "$x>=$x6" && "$x<=$x5" && "$y>=$y6" && "$y<=$y6+50" && "\ 32949 ($x-$x6)%25<=20" && "($y-$y6)%25<=20 # Preset. 32950 p={int(($x-$x6)/25)+6*int(($y-$y6)/25)} (${_xsc_preset$p}) -. 255 r. 4,1,1,1,0 +. 255 y. c sh. 0,2 rgb2hsv. rm. 32951 H={i[0]} S={i[1]} V={i[2]} A={i[3]} 32952 colordb=0 rm 32953 elif !$is_sv" && "!$is_h" && "!$is_a" && "$x>=$x0+55" && "$x<=$x0+102" && "$y>=$y1+10" && "$y<=$y1+27 32954 # Add current as old and/or preset. 32955 _xsc_old=$R,$G,$B,$A colordb={($colordb+1)%2} 32956 if !$colordb # Double-click to add to preset. 32957 _xsc_preset$_xsc_preset=$R,$G,$B,$A _xsc_preset={($_xsc_preset-1)%12} 32958 fi 32959 rm wait -1 32960 else colordb=0 32961 fi 32962 elif !$b is_sv=0 is_h=0 is_a=0 32963 fi 32964 if {*,ARROWUP} colordb=0 S={min(1,$S+1/256)} update_view=1 k[0] wait -1 32965 elif {*,ARROWDOWN} colordb=0 S={max(0,$S-1/256)} update_view=1 k[0] wait -1 32966 elif {*,ARROWRIGHT} colordb=0 V={min(1,$V+1/256)} update_view=1 k[0] wait -1 32967 elif {*,ARROWLEFT} colordb=0 V={max(0,$V-1/256)} update_view=1 k[0] wait -1 32968 elif {*,PAGEUP} colordb=0 H={min(359,$H+1)} rm wait -1 32969 elif {*,PAGEDOWN} colordb=0 H={max(0,$H-1)} rm wait -1 32970 fi 32971 32972 # Check RGB variable modification from another thread. 32973 if ['$$1']=='-1' break fi # Close request 32974 if (($rgba_mode" && "['$$1']!='$R,$G,$B,$A')" || "(!$rgba_mode" && "['$$1']!='$R,$G,$B'))" && "\ 32975 $x<0" && "$y<0" && "!$is_sv" && "!$is_h" && "!$is_a 32976 ($$1) y. c -. 255 r. 1,1,1,4,0 +. 255 sh. 0,2 rgb2hsv. rm. 32977 H={i[0]} S={i[1]} V={i[2]} A={i[3]} rm 32978 fi 32979 32980 while {*}" && "!{*,ESC}" && "!{*,Q} 32981 rm w 0 32982 if $rgba_mode u $R,$G,$B,$A else u $R,$G,$B fi 32983 _xsc_old=${} 32984 32985#@cli x_select_function1d : _variable_name,_background_curve_R,_background_curve_G,_background_curve_B 32986#@cli : Open an interactive window, where the user can defined its own 1D function. 32987#@cli : If an image is selected, it is used to display additional information : 32988#@cli : - The first row defines the values of a background curve displayed on the window (e.g. an histogram). 32989#@cli : - The 2nd, 3rd and 4th rows define the R,G,B color components displayed beside the X and Y axes. 32990#@cli : Argument 'variable_name' specifies the variable that contains the selected function keypoints at any time. 32991#@cli : Assigning '-1' to it forces the interactive window to close. 32992#@cli : Default values: 'variable_name=xsf_variable', 'background_curve_R=220', \ 32993# 'background_curve_G=background_curve_B=background_curve_T'. 32994x_select_function1d : skip ${1=xsf_variable},${2=220},${3=$2},${4=$2} check_display $0 32995 e[^-1] "Open 1D function widget, with variable name '$1'." 32996 if $! k[0] fi 32997 is_additional_data=$! 32998 if !{*} w[] 400,400,0,"Create a 1D function" fi 32999 reset_w={*,w} reset_h={*,h} 33000 if !narg($$1) $1=0,0,100,100 fi 33001 ($$1) nm. points y. x r. 2,{w/2},1,1,-1 33002 is_thread_variable={arg(1,{'$1'})==_'_'" && "arg(2,{'$1'})==_'_'} selected=-1 X=-1 Y=-1 33003 do 33004 33005 # Update base view. 33006 if !narg($baseview) 33007 {{*,d}-48},{{*,e}-48},1,3,255 33008 if $is_additional_data # Render background graph. 33009 100%,100% +rows[0] 0 graph.. .,3,0,0,0,1,1 rm. c. 0,1 33010 +fc.. ${2-4} j... .,0,0,0,0,1,.. rm[-2,-1] 33011 fi 33012 grid. {(w-1)/8},{(h-1)/8},0,0,0.2,0xCCCCCCCC,0 33013 line. 0,100%,100%,0,0.2,0 33014 frame. 24,24,200 33015 rectangle. 23,23,{w-24},{h-24},1,0xFFFFFFFF,232 line. 23,23,23,{h-24},1,128 line. 23,23,{w-24},23,1,128 33016 if $is_additional_data" && "{0,h}>1 # Render colored X-axis guide. 33017 if {0,h}>2 +rows[0] 1,3 else +rows[0] 1 r. 100%,3 fi 33018 r. {-2,w-48},3,1,1,3 permute. xzcy r. 100%,8 frame. 1,1,0 33019 j.. .,23,{-2,h-19} rotate. -90 j.. .,{-2,w-19},23 rm. 33020 fi 33021 nm. baseview 33022 l rm[view] onfail endl 33023 fi 33024 33025 # Update view. 33026 if !narg($view) 33027 +z[baseview] 24,24,{baseview,w-25},{baseview,h-25} r. 200%,200% 33028 33029 # Draw curve. 33030 function1d[] 1,{points,^} 33031 l. c 0,100 transpose 33032 i[0] ({'CImg3d'},{h},{h-1}) 33033 i.. 1,100%,1,1,y 1,100% a[-3--1] x 33034 1,{h-1},1,1,2 +f. y ++. 1 a[-3--1] x 33035 4,100%,1,1,1 y a y col3d 0 33036 endl 33037 *3d. {-2,(w-1)/100},{-2,(1-h)/100} 33038 j3d.. .,0,100%,0,1,1,0,0 rm. 33039 33040 # Draw control points. 33041 repeat h#$points 33042 x={points,i(0,$>)} y={100-{points,i(1,$>)}} 33043 circle. $x%,$y%,6,1,0xFFFFFFFF,0 33044 done 33045 if $selected>=0 33046 x={points,i(0,$selected)} y={100-{points,i(1,$selected)}} 33047 circle. $x%,$y%,3,1,0 33048 fi 33049 33050 r. 50%,50%,1,3,2 33051 +j[baseview] .,24,24 rm.. 33052 33053 # Draw current coordinates. 33054 if $X>=0" && "$Y>=0 t. "X: "{min(255,round(255*$X/100))}" Y: "{min(255,round(255*$Y/100))},24,6,12,1 fi 33055 nm. view 33056 w[view] 33057 fi 33058 33059 if $is_thread_variable wait 50 else wait fi 33060 33061 # Manage user events. 33062 x={*,x} y={*,y} b={*,b} is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 33063 X={($x-24)*100/({*,w}-49)} Y={100-($y-24)*100/({*,h}-49)} 33064 oww={*,w} owh={*,h} ww=$oww wh=$owh 33065 if {*,r} ww={*,d} wh={*,e} # Resize window. 33066 elif $is_ctrl" && "{*,-D} ww={view,w*125%} wh={view,h*125%} # Increase window size. 33067 elif $is_ctrl" && "{*,-C} ww={view,w*75%} wh={view,h*75%} # Decrease window size. 33068 elif $is_ctrl" && "{*,R} ww=$reset_w wh=$reset_h # Reset window size. 33069 elif !$is_ctrl" && "{*,R} rm[points] (0,0;100,100) nm. points $1={points,^} rm[view] # Reset keypoints. 33070 elif $b&3 # Add/move/delete point. 33071 is_inside={$X>=0" && "$Y>=0" && "$X<=100" && "$Y<=100} 33072 33073 # Check for a point selection. 33074 if $selected<0 +f[points] 'sqrt((i-$X)^2+(j(1)-$Y)^2)*{*,w}%' z. 0,0 selected={if(im>8,-1,ym)} rm. fi 33075 33076 if $x>=0" && "$b&1" && "$selected>=0 # Move an existing point. 33077 if {*,SHIFTLEFT}" || "{*,SHIFTRIGHT} X={points,i(0,$selected)} fi 33078 if {*,CTRLLEFT}" || "{*,CTRLRIGHT} Y={points,i(1,$selected)} fi 33079 if {points,$selected>0" && "$selected<h-1} 33080 =[points] {points,max(min($X,i(0,$selected+1)-0.5),i(0,$selected-1)+0.5)},0,$selected 33081 fi 33082 =[points] {min(100,max(0,$Y))},1,$selected $1={points,^} rm[view] 33083 33084 elif $b&1" && "$is_inside # Create new point. 33085 ($X,$Y) a[points,-1] y sort[points] +,y 33086 +f[points] 'sqrt((i-$X)^2+(j(1)-$Y)^2)*{*,w}%' z. 0,0 selected={if(im>8,-1,ym)} $1={points,^} rm[view,-1] 33087 elif $b&2" && "$selected>0" && "$selected<{points,h-1}" && "$is_inside # Delete an existing point. 33088 l[points] s y rm[$selected] a y endl wait -1 selected=-1 $1={points,^} rm[view] 33089 fi 33090 elif !($b&1) selected=-1 33091 fi 33092 33093 # Manage window size. 33094 ww={min(90%*{*,u},max(200,$ww))} 33095 wh={min(90%*{*,v},max(200,$wh))} 33096 if $oww!=$ww" || "$owh!=$wh w[] $ww,$wh rm[baseview,view] fi 33097 33098 # Check points variable modification from another thread. 33099 if ['$$1']=='-1' break fi # Close request 33100 if ['$$1']!=['{points,^}'] # Keypoints changed 33101 rm[points] ($$1) nm. points y. x r. 2,{w/2},1,1,-1 l rm[view] onfail endl 33102 fi 33103 33104 while {*}" && "!{*,ESC}" && "!{*,Q} 33105 w[] 0 u {points,^} 33106 if $is_additional_data rm[^0] else rm fi 33107 33108#@cli x_select_palette : _variable_name,_number_of_columns={ 0=auto | >0 } 33109#@cli : Open a RGB or RGBA color selector widget from a palette. 33110#@cli : The palette is given as a selected image. 33111#@cli : Argument 'variable_name' specifies the variable that contains the selected color values (as R,G,B,[A]) 33112#@cli : at any time. 33113#@cli : Assigning '-1' to it forces the interactive window to close. 33114#@cli : Default values: 'variable_name=xsp_variable' and 'number_of_columns=2'. 33115x_select_palette : skip ${1=xsp_variable},${2=0} check_display $0 33116 if !$! error[0--3] "Command '$0': Missing specified palette image." fi 33117 k[0] +r {w*h*d},1,1,{s},-1 to_color. rgba_mode={s==4} to_rgba. nm. palette 33118 e[^-1] "Open "${arg\ 1+$rgba_mode,RGB,RGBA}" color selector widget for palette$?, with variable name '$1'." 33119 33120 if w>1024 error[0--3] "Command '$0': Too much colors ("{w}") in selected palette." fi 33121 if !{*} w[] 400,400,0,0,-1,-1,"Palette: "{0,b} fi 33122 33123 selected=-1 oselected=-1 33124 do 33125 ww={*,w} wh={*,h} 33126 R={palette,round(i($selected,0,0,0))} G={palette,round(i($selected,0,0,1))} 33127 B={palette,round(i($selected,0,0,2))} A={palette,round(i($selected,0,0,3))} 33128 33129 # Update color in specified variable. 33130 if $selected>=0" && "$oselected!=$selected 33131 if $rgba_mode $1=$R,$G,$B,$A else $1=$R,$G,$B fi 33132 fi 33133 33134 # Check close request from external thread. 33135 if ['$$1']=='-1' break fi 33136 33137 # Create base view. 33138 if !narg($baseview) l[palette] 33139 {w},1,1,1,x +. 1 33140 s. x append_tiles[^0] $2 33141 M={w} N={h} 100%,100%,1,1,1 33142 +r. {$ww-17},100%,1,1,4 33143 r.. 100%,{$wh-57},1,1,4 33144 r[-2,-1] .,.. -|[-2,-1] 33145 line. 100%,0,100%,100%,1,1 33146 line. 0,100%,100%,100%,1,1 33147 -. 1 *. -1 33148 r.. .,.,1,1,1 -.. 1 33149 +map.. [0],0 drgba. 33150 rv[-2,-1] *[-2,-1] 33151 +!=.. -1 dilate. 3 33152 mv... $! +. 1 a[-3--1] c 33153 nm. baseview 33154 endl 33155 if narg($view) rm[view] fi 33156 fi 33157 33158 # Create and display view. 33159 if !narg($view) 33160 $ww,$wh,1,3,200 33161 if $selected<0 sh[baseview] 0,2 33162 else 33163 +channels[baseview] 0,2 +channels[baseview] 4,4 33164 !=. {$selected+1} rectangle. 0,0,100%,100%,1,0xFFFFFFFF,1 33165 +dilate. 5 -[-2,-1] *. -1 +dilate. 5 *.. 255 33166 r.. 100%,100%,1,3 j... ..,0,0,0,0,1,. rm[-2,-1] 33167 if $rgba_mode t.. "RGBA ("$R","$G","$B","$A")",8,{$wh-45},14,1,0 33168 else t.. "RGB ("$R","$G","$B")",8,{$wh-45},14,1,0 33169 fi 33170 ($R^$G^$B) rgb2hsv. H={round(i[0])} S={round(i[1]*255)} V={round(i[2]*255)} rm. 33171 t.. "HSV ("$H","$S","$V")",8,{$wh-31},14,1,0 33172 ('${dec2hex\ {$R*65536+$G*256+$B}}') -. {'0'} r. 6,1,1,1,0,0,1,0 +. {'0'} 33173 f. if(i>=_'a'" && "i<=_'z',i+_'A'-_'a',i) 33174 t... "html ""#"{t},8,{$wh-17},14,1,0 rm. 33175 fi 33176 sh[baseview] 3 j... ..,8,8,0,0,1,. rm[-2,-1] 33177 nm. view w[view] 33178 fi 33179 33180 if arg(1,{'$1'})==_'_'" && "arg(2,{'$1'})==_'_' wait 50 else wait fi 33181 33182 # Manage window size. 33183 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 33184 if {*,r} ww={*,d} wh={*,e} 33185 elif $is_ctrl" && "{*,-D} ww={1.25*$ww} wh={1.25*$wh} 33186 elif $is_ctrl" && "{*,-C} ww={0.8*$ww} wh={0.8*$wh} 33187 elif $is_ctrl" && "{*,R} ww=400 wh=400 33188 fi 33189 ww={max(200,$ww)} wh={max(200,$wh)} 33190 if ($ww!={*,w}" || "$wh!={*,h})" && "narg($baseview) w[] $ww,$wh rm[baseview] fi 33191 33192 # Handle user events. 33193 oselected=$selected 33194 if narg($baseview) 33195 x={*,x} y={*,y} b={*,b} 33196 if $b&1" && "$x>=0" && "$y>=0 # Select color. 33197 if {baseview,i($x-8,$y-8,0,4)} selected={baseview,i($x-8,$y-8,0,4)-1} else selected=-1 fi 33198 rm[view] wait -1 33199 elif {*,ARROWUP}" && "$selected>=$M selected-=$M rm[view] wait -1 33200 elif {*,ARROWDOWN}" && "$selected<{0,w-$M} selected+=$M rm[view] wait -1 33201 elif {*,ARROWRIGHT}" && "$selected<{0,w-1} selected+=1 rm[view] wait -1 33202 elif {*,ARROWLEFT}" && "$selected>0 selected-=1 rm[view] wait -1 33203 fi 33204 fi 33205 33206 while {*}" && "!{*,ESC}" && "!{*,Q} 33207 w 0 k[0] 33208 if $selected>=0 if $rgba_mode u $R,$G,$B,$A else u $R,$G,$B fi else u -1 fi 33209 33210#@cli x_shadebobs 33211#@cli : Launch the shade bobs demo. 33212x_shadebobs : check_display $0 33213 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 33214 e[] "\n 33215------ "${g}"Shade bobs"$n" -------------------------------\n 33216----\n 33217---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 33218---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 33219---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 33220----\n 33221-------------------------------------------------" 33222 rm t=100 w 512,512,0,"[G"{`39`}"MIC] Shade Bobs" 33223 33224 # Start animation loop. 33225 do 33226 t+=0.015 33227 if $t>4*pi" || "{*,b} # Reset motions variables if necessary. 33228 rx={u(-1,1)} ry={u(-1,1)} rz={u(-1,1)} rt={u(-1,1)} rcx={u(-0.6*0.6)} t=0 33229 N={20+round(u(80))} R={(2+round(u(40)))*min({*,w},{*,h})/300} 33230 if $obj3d rm[colormap,img,obj3d] fi 33231 {4+round(u(12))},1,1,3 noise[0] 255,2 ==. 1 r[0] 256,1,1,3,3 *[0] 255 shift[0] 1 nm. colormap 33232 (67.5;73.5;109.5;103.5;51.5;100.5;{2*$N};$N) 3,{2*$N},1,1,0 33233 1,$N,1,1,5 2,$N,1,1,'y+x*$N' a[-2--1] x z. 0,5 33234 4,$N,1,1,1 y[-3--1] a[-4--1] y nm. obj3d 33235 {*,w},{*,h} nm. img 33236 wait -1 33237 fi 33238 33239 # Compute bobs coordinates. 33240 r={$ry+$rx*cos(6*$rz*$t)+(1-$rx)*sin(6*$rt*$t)} 33241 (0;{30*$ry*($N-1)}) ($t;{2*pi*($N-1)/$N+$t}) r[-2,-1] 1,$N,1,1,3 33242 +.. {360*sin($rz*$t)} *.. {pi/180} 33243 +sin[-2,-1] cos[-4,-3] *[-4,-2] $r *[-3,-1] $rcx +[-4,-3] +[-2,-1] 33244 *.. {{*,w}/2} *. {{*,h}/2} a[-2,-1] x 33245 ++. $R -.. $R a[-2,-1] y z. 0,2 y. j[obj3d] .,0,8 rm. 33246 33247 # Draw bobs, map colors and display. 33248 j3d[img] [obj3d],50%,50%,0,-1,2,0,0 33249 &[img] 255 +map[img] [colormap] w. rm. wait 20 33250 if {*,CTRLLEFT}" && "{*,D} w[] 1024,1024 elif {*,CTRLLEFT}" && "{*,C} w[] 512,512 fi 33251 while {*}" && "!{*,ESC}" && "!{*,Q} 33252 rm w 0 33253 33254#@cli x_spline 33255#@cli : Launch spline curve editor. 33256x_spline : check_display $0 33257 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 33258 e[] "\n 33259------ "${g}"Spline curve editor"$n" --------------------------\n 33260----\n 33261---- "${c}"Mouse"$n" to insert/move/delete points.\n 33262---- Key '"${c}"R"$n"' to reset the curve.\n 33263---- Key '"${c}"SPACE"$n"' to shows/hide spline curve.\n 33264---- Key '"${c}"P"$n"' to shows/hide control points.\n 33265---- Key '"${c}"ENTER"$n"' to shows/hide control polygon.\n 33266---- Key '"${c}"T"$n"' to shows/hide point tangents.\n 33267---- Key '"${c}"I"$n"' to shows/hide point indices.\n 33268---- Key '"${c}"C"$n"' to shows/hide point coordinates.\n 33269---- Keys '"${c}"+"$n"' and '"${c}"-"$n"' to increase/decrease roundness.\n 33270---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 33271----\n 33272-----------------------------------------------------" 33273 33274 # Init display and variables. 33275 if $! a x n 0,255 to_rgb else (0;0^0;128^0;0) r. 512,512,1,3,3 nm. "[G"{`39`}"MIC] Spline Editor" fi 33276 w[0] {0,w},{0,h},0,0,{n} r[0] {*,w},{*,h},1,3,1 33277 i[1] 1 # Point coordinates 33278 roundness=0.5 # Curve roundness 33279 visuflags=23 # Visualisation flags 33280 nearest=-1 # Nearest point 33281 active=-1 # Active point 33282 33283 # Start event loop. 33284 do 33285 33286 # Init coordinates [1] if necessary. 33287 if {1,whds}==1 33288 rm[1] roundness=0.5 nearest=-1 active=-1 33289 i[1] ({0.2*w},{0.2*h};\ 33290 {0.2*w},{0.8*h};\ 33291 {0.8*w},{0.8*h};\ 33292 {0.8*w},{0.2*h}) 33293 fi 33294 33295 # Estimate screen-normalized coordinates [2], curve tangents [3] and tangent orientations [4]. 33296 [1] ({{*,w}/{0,w}},{{*,h}/{0,h}}) *[-2,-1] # Normalized coordinates. 33297 +shift[2] 0,-1,0,0,2 +shift[2] 0,1,0,0,2 -[-2,-1] *. $roundness # Curve tangents. 33298 +s. x sqr[-2,-1] +[-2,-1] sqrt. r. 2 +/[-2,-1] rm.. # Tangent orientations. 33299 33300 # Display curve, control points, polygon and tangents. 33301 +r[0] {*,w},{*,h},1,3 33302 if $visuflags&4 polygon. {2,h},{2,^},0.3,128,200,255 fi 33303 repeat h#1 33304 line. {2,@0-3},0.3,255,255,0 33305 if $visuflags&1 spline. {2,@0-1},{3,@0-1},{2,@2-3},{3,@2-3},1,255 fi 33306 if $visuflags&8 line. {{2,@0}-{4,@0}*20},{{2,@1}-{4,@1}*20},{{2,@0}+{4,@0}*20},{{2,@1}+{4,@1}*20},1,0,255,0 fi 33307 if $visuflags&16 t. $>,{{2,@0}-3},{{2,@1}-18},13,1,255,255,0 fi 33308 if $visuflags&32 t. "("{round({1,@0})}","{round({1,@1})}")",{{2,@0}-16},{{2,@1}+10},13,1,100,200,255 fi 33309 shift[1-4] 0,-1,0,0,2 33310 done 33311 if $visuflags&2 repeat h#1 33312 ellipse. {2,@0-1},4,4,0,1,0,0,0 ellipse. {2,@0-1},2,2,0,1,255,100,155 shift[2] 0,1,0,0,2 33313 done fi 33314 w. rm[3,4,-1] wait 33315 33316 # Handle key events. 33317 if {*,SPACE} visuflags+={if($visuflags&1,-1,1)} wait -1 fi # Show/hide spline 33318 if {*,P} visuflags+={if($visuflags&2,-2,2)} wait -1 fi # Show/hide points 33319 if {*,ENTER} visuflags+={if($visuflags&4,-4,4)} wait -1 fi # Show/hide polygon 33320 if {*,T} visuflags+={if($visuflags&8,-8,8)} wait -1 fi # Show/hide tangents 33321 if {*,I} visuflags+={if($visuflags&16,-16,16)} wait -1 fi # Show/hide indices 33322 if {*,C}" && "!{*,CTRLLEFT}" && "!{*,CTRLRIGHT} # Show/hide coordinates 33323 visuflags+={if($visuflags&32,-32,32)} wait -1 fi 33324 if {*,PADADD}" && "$roundness<1 roundness*=1.1 wait -1 fi # Increase roundness 33325 if {*,PADSUB}" && "$roundness>0.1 roundness*=0.9 wait -1 fi # Decrease roundness 33326 if {*,R}" && "!{*,CTRLLEFT}" && "!{*,CTRLRIGHT} rm. i[1] 1 wait -1 fi # Reset curve 33327 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} fi # Increase window size 33328 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} fi # Decrease window size 33329 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} fi # Reset window size 33330 if {*,r} w[] fi # Resize window if necessary. 33331 33332 # Set/unset active point. 33333 if {*,b}==0 active=-1 # Unset active point if mouse button is released 33334 elif {*,x}>=0" && "{*,b}" && "$active==-1 # Find new active point 33335 [2] ({*,x},{*,y}) -[-2,-1] sqr. s. x +[-2,-1] # Compute distance vector to points 33336 nearest={ym} # Set nearest point 33337 if im<64 active=$nearest fi # Set it as active point, if near enough 33338 rm. 33339 fi 33340 rm[2] 33341 33342 # Move active point. 33343 if {*,b}&1" && "{*,x}>=0" && "$active!=-1 33344 =[1] {{*,x}*{0,w}/{*,w}},0,$active 33345 =[1] {{*,y}*{0,h}/{*,h}},1,$active 33346 33347 # Delete nearest point. 33348 elif {*,b}&2" && "{*,x}>=0" && "{1,h}>3 33349 l[1] s y rm[$nearest] a y endl wait -1 33350 33351 # Insert new active point. 33352 elif {*,b}&1" && "{*,x}>=0 33353 xy=({{*,x}*{0,w}/{*,w}},{{*,y}*{0,h}/{*,h}}) # Point coordinates in the image basis 33354 +shift[1] 0,-1,0,0,2 +. [1] /. 2 # Compute center of segments 33355 $xy -[-2,-1] sqr. s. x +[-2,-1] # Compute distance vector to segments 33356 ns={ym} rm. # Get nearest segment 33357 l[1] s y i[{$ns+1}] $xy a y endl # Insert new point at right position 33358 active={$ns+1} # Set new active point as newly inserted 33359 fi 33360 33361 while {*}" && "!{*,ESC}" && "!{*,Q} 33362 33363 # Render spline as a tertiary mask for output. 33364 +shift[1] 0,-1,0,0,2 +shift[1] 0,1,0,0,2 -[-2,-1] *. $roundness 33365 [0],[0],1,1,2 rm[0] 33366 repeat h#1 spline. {0,@0-1},{1,@0-1},{0,@2-3},{1,@2-3},1,1 shift[0] 0,-1,0,0,2 shift[1] 0,-1,0,0,2 done 33367 flood. 0,0,0,0,0,1,0 33368 33369 # Exit properly. 33370 rm[0,1] w 0 33371 33372#@cli x_starfield3d 33373#@cli : Launch the 3D starfield demo. 33374x_starfield3d : check_display $0 33375 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 33376 e[] "\n 33377------ "${g}"3D starfield"$n" ---------------------------------------\n 33378----\n 33379---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 33380----\n 33381-----------------------------------------------------------" 33382 l[] 33383 ('G\47MIC') s x 33384 x=0 N=$! repeat $N 0 t. {$>,t},0,0,48,1,1 x$>=$x y$>=0 z$>={-3200-150*$>} x={$x+w+8} done k[50%--1] 33385 expand_xy 6,0 dilate_circ 5 b 0.5 expand_z 1,0 isosurface3d 10% *3d 1,1,5 rv3d 33386 repeat $N col3d[$>] ${-rgb} done 33387 0 t. "Version "${-strver},0,0,48,1,1 r2dy. 18 +f. 255 to_rgb. 33388 random3d 2500 col3d. 255 *3d. 320,200,1000 -3d. 160,100 33389 l3d 0,0,-600 33390 w[] 640,400,0,"[G"{`39`}"MIC] 3D Starfield" 33391 t0=0 t=0 33392 33393 do 33394 320,200,1,3 33395 33396 # Starfield. 33397 l.. s3d 33398 r[2] 3,{2,h/3},1,1,-1 s[2] x %[4] 1000 33399 +/[4] 1000 *. -1 n. 0,2 c. 0,1 sqr. j.. . rm. 33400 a[2-4] x 33401 y a y 33402 endl 33403 j3d. ..,50%,50%,-600,1,0,0,0,240 -3d.. 0,0,{min(12,$t0/10-4)} 33404 33405 # Torus. 33406 torus3d 100,30 col3d. 255,64,255 33407 +col3d. 64,64,255 r3d. 1,0,0,-90 +3d. 65,0,0 33408 +3d[-2,-1] c3d. 33409 r3d. 1,1,0,{-6*$t} r3d. 0,0,1,{2*$t} 33410 j3d.. .,{($t-200)*2}%,50%,0,0.25,3,0,0 rm. 33411 33412 # Letters. 33413 repeat $N 33414 +r3d[$>] 1,{$>%4},1,{-${z$>}/2} 33415 j3d.. .,{90+${x$>}},{60+${y$>}},${z$>},1,4,0,0 rm. 33416 z$>={tl=280+6*$<;if($t<tl,min(0,${z$>}+20),-20*($t-tl))} 33417 done 33418 33419 # Presents. 33420 if $t<280 op={max(0,min(1,($t-200)/20))} 33421 else op={max(0,1-($t-280)/20)} 33422 fi 33423 j. ...,{(w-{-3,w})/2},120,0,0,$op,[-4] 33424 33425 w. wait 30 rm. 33426 t0+=1 t={$t0%350} 33427 if !$t x=0 repeat 5 z$>={-3200-150*$>} done fi 33428 33429 while {*}" && "!{*,ESC}" && "!{*,Q} 33430 w[] 0 rm endl 33431 33432#@cli x_tetris 33433#@cli : Launch tetris game. 33434x_tetris : check_display $0 33435 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 33436 e[] "\n 33437------ "${g}"Tetris"$n" --------------------------------------------\n 33438----\n 33439---- This is a G\47MIC implementation of the "${g}"Tetris"$n" game.\n 33440----\n 33441---- "${c}"Arrow keys"$n" to move/rotate the triominos.\n 33442---- Key '"${c}"SPACE"$n"' to make the current triomino falling.\n 33443---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 33444----\n 33445----------------------------------------------------------" 33446 rm 33447 33448 # Init board and triominos shapes. 33449 4,1,1,1,1,1,1,1 33450 3,2,1,1,1,0,0,1,1,1 33451 3,2,1,1,0,0,1,1,1,1 33452 2,2,1,1,1,1,1,1 33453 3,2,1,1,0,1,1,1,1,0 33454 3,2,1,1,0,1,0,1,1,1 33455 3,2,1,1,1,1,0,0,1,1 33456 nm[-7--1] m0,m4,m8,m12,m16,m20,m24 33457 33458 if u<0.25 # Enable extended set. 33459 i 2,1,1,1,1,1 33460 i 2,2,1,1,1,1,0,1 33461 i 3,1,1,1,1,1,1 33462 i 1,1,1,1,1 33463 i 3,2,1,1,1,1,1,1,0,1 33464 i 3,3,1,1,1,1,1,1,0,1,1,1,1 33465 nm[-6--1] m28,m32,m36,m40,m44,m48 33466 fi 33467 repeat $! i={4*$>} l[m$i] repeat 3 +rotate[0] {90*($>+1)} nm. m{$i+$>+1} done endl done 33468 N=$! 33469 33470 # Render triomino colored sprites. 33471 3,$N,1,1,'u(16,224)' r. 3,400% nm. colors 33472 (0,-1,0;1,0,-1;0,1,0) *. 120 nm. mask 33473 repeat $N 33474 +r[m$>] 500%,500%,1,3 +correlate. [mask],0 r. 200%,200%,1,1,3 ri.. . *[-2,-1] c. 30%,100% 33475 +r[m$>] .,.,1,3 +replace_color. 0,0,1,1,1,{colors,@{3*$>}-{3*$>+2}} rv[-3,-1] +[-3,-1] c.. 0,255 33476 channels. 0 *. 255 a[-2,-1] c nm. s$> 33477 done 33478 rm[colors,mask] 33479 fact={{s0,w}/{m0,w}} 33480 33481 # Generate board and background. 33482 W=12 H=20 33483 $W,$H . nm[-2,-1] board,curr_board 33484 {$fact*$W},{$fact*$H},1,3 . nm[-2,-1] render,curr_render +channels. 0 nm. curr_render_mask 33485 +rows[render] 0,50% plasma. 1,2 noise. 20 blur_y. 40%,1 +mirror. y a[-2,-1] y ri. [render] 33486 n. 0,64 blur_x. 1 100%,100% noise. 0.5,2 ==. 1 b. 1 *. 300 +[-2,-1] c. 0,255 nm. background 33487 33488 # Start game. 33489 time=$| score=0 fall_mode=0 gameover=0 n=-1 nn={round(u(0,$N-1))} 33490 do 33491 wait {if($fall_mode,-1,-20)} 33492 33493 # In case of game over. 33494 if $gameover 33495 +j[background] [curr_render],0,0,0,0,0.7,[curr_render_mask],255 33496 to. "Game\nOver!",22,30%,32,2,1,255 w. rm. 33497 continue 33498 fi 33499 33500 # Check for completed lines and select new random triomino. 33501 if $n<0 33502 l[board] s y i=-1 repeat $! if {$<,im} i=$<,$i fi done 33503 0 rm[$i] a y score+={2^(narg($i)-1)-1} r $W,$H,1,1,0,0,0,1 nm board endl 33504 if narg($i)>1 l[render] s y,$H 0 rm[$i] a y r {$fact*$W},{$fact*$H},1,3,0,0,0,1 nm render endl fi 33505 n=$nn nn={round(u(0,$N-1))} x={$W/2} y=0 do_render=1 fall_mode=0 33506 fi 33507 33508 # Render board at current time. 33509 if $do_render 33510 rm[curr_board,curr_render,curr_render_mask] 33511 [board] nm. curr_board j[curr_board] [m$n],{$x-int({m$n,w}/2)},$y,0,0,1,[m$n] 33512 [render] nm. curr_render sh[s$n] 3 j[curr_render] [s$n],{$fact*($x-int({m$n,w}/2))},{$fact*$y},0,0,1,.,255 rm. 33513 +*[curr_board] 255 r. [curr_render],[curr_render] nm. curr_render_mask 33514 0 t. "Score : "$score" Next :",4,0,25,1,200 r. 50%,50%,1,3,2 +!=. 0 *. 255 33515 j[curr_render] ..,0,0,0,0,1,.,255 j[curr_render_mask] .,0,0,0,0,1,.,255 rm[-2,-1] 33516 +*[m$nn] 196 r. 300%,300%,1,3 j[curr_render,curr_render_mask] .,{{curr_render,w}-w-4},3,0,0,1,.,196 rm. 33517 do_render=0 33518 fi 33519 33520 +shift[background] 0,{round(-13*$|*1.04^$score)},0,0,2 33521 j. [curr_render],0,0,0,0,1,[curr_render_mask],255 33522 w. {2.25*w},{2.25*h},0,"[G"{`39`}"MIC] Tetris" rm. cursor[0] 0 33523 33524 # Manage user interactions. 33525 if {*,SPACE} fall_mode=1 fi 33526 if {*,ARROWUP}" || "{*,ARROWLEFT}" || "{*,ARROWRIGHT} 33527 an={if({*,ARROWUP},n=$n+1;if(n%4,n,n-4),$n)} 33528 nx={w2=int({m$an,w}/2);max(w2,min($x-{*,ARROWLEFT}+{*,ARROWRIGHT},$W-({m$an,w}%2)-w2))} 33529 +j[board] [m$an],{$nx-int({m$an,w}/2)},$y,0,0,-1,[m$an] 33530 if iM==1 x=$nx n=$an fi 33531 rm. 33532 do_render=1 33533 fi 33534 33535 if {*,ARROWDOWN}" || "$|-$time>0.9^int($score/2)" || "$fall_mode # Piece goes down. 33536 y+=1 33537 +j[board] [m$n],{$x-int({m$n,w}/2)},$y,0,0,-1,[m$n] 33538 if iM>1" || "$y+{m$n,h}>$H 33539 if $y<=1 gameover=1 fi # Game over! 33540 j[board] [curr_board] j[render] [curr_render] n=-1 33541 fi 33542 rm. 33543 time=$| do_render=1 33544 fi 33545 33546 while {*}" && "!{*,ESC}" && "!{*,Q} 33547 rm w 0 33548 33549#@cli x_threshold 33550#@cli : Threshold selected images interactively. 33551x_threshold : 33552 e[^-1] "Threshold image"$_gmic_s" interactively." 33553 repeat $! l[$>] 33554 wsiz0=${"fitscreen ."} 33555 value=-1 33556 w[] $wsiz0,0,"[G'MIC] "{n}" - Interactive threshold" 33557 0 33558 for {*}" && "!{*,ESC} 33559 33560 if [w#1,h#1]!=[{*,w,h}] # Generate image view 33561 rm[1] +slices[0] 50% r. {*,w,h},1,100%,1 w. 33562 fi 33563 33564 mx,my,mb={*,x,y,b} 33565 if $mb" && "$mx>=0" && "$my>=0 33566 value={"w>h?( dw1 = "{*,w}" - 1; val = (dw1 - "$mx")*100/dw1; ): 33567 ( dh1 = "{*,h}" - 1; val = (dh1 - "$my")*100/dh1; )"} 33568 update_view=1 33569 fi 33570 33571 if $update_view 33572 if $value>=0 33573 +ge[1] $value% *. 255 33574 to. "Threshold: "{_round($value,0.1)}%,1%,1%,{max(13,3.5*h%)} 33575 w. rm. 33576 else w. 33577 fi 33578 update_view=0 33579 fi 33580 33581 wait 33582 if {*,r} update_view=1 fi 33583 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} 33584 w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 update_view=1 33585 fi 33586 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} 33587 w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 update_view=1 33588 fi 33589 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} 33590 w[] $wsiz0 wait -1 update_view=1 33591 fi 33592 done 33593 w[] 0 rm. u $value% ge ${} 33594 endl done 33595 33596#@cli x_tictactoe 33597#@cli : Launch tic-tac-toe game. 33598x_tictactoe : check_display $0 33599 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 33600 e[] "\n 33601------ "${g}"Tic-Tac-Toe game"$n" -----------------\n 33602----\n 33603---- Use "${c}"mouse"$n" to select positions of the\n 33604---- symbols. Close window to exit game.\n 33605----\n 33606-----------------------------------------" 33607 33608 # Allocate variables. 33609 message=0 # [-7] : State message. 33610 counter=0 # [-6] : Turn counter (0 to 8). 33611 player=0 # [-5] : Current player (0 or 1). 33612 state=0 # [-4] : Board state. 33613 tmp3=0 # [-3] : Temporary variable 3. 33614 tmp2=0 # [-2] : Temporary variable 2. 33615 tmp1=0 # [-1] : Temporary variable 1. 33616 _x_tictactoe2 # Generate board. 33617 w. -1,-1,0," " # Init display window. 33618 33619 # Start main loop. 33620 do 33621 33622 # Set state message depending on the current player. 33623 if $player message="Tic-Tac-Toe (O to play)" 33624 else message="Tic-Tac-Toe (X to play)" 33625 fi 33626 33627 # Select position by the user. 33628 do # Enter event loop. 33629 w[] {w},{h},0,"[G"{`39`}"MIC] "$message wait # Wait for events and force window size if necessary. 33630 if !{*}" || "{*,ESC}" || "{*,Q} w[] 0 rm return fi # Quit properly if window has been closed. 33631 if {*,b}&1" && "{*,x}>20" && "{*,y}>20" && "{*,x}<400" && "{*,y}<400 # If mouse button pressed on the board area. 33632 tmp3={int(({*,x}-15)/130)} # X of the selected position (0,1 or 2). 33633 tmp2={int(({*,y}-15)/130)} # Y of the selected position (0,1 or 2). 33634 tmp1={4^($tmp2*3+$tmp3)} # Get state code of the selected position. 33635 if int($state/$tmp1)%4 tmp1=-1 fi # Check availability of position. 33636 else tmp1=-1 fi # If no mouse button, do nothing but loop. 33637 while $tmp1<0 # Go on until a valid position selected. 33638 33639 # Draw symbol on selected position and update board state. 33640 _x_tictactoe{$player%2} # Generate the symbol sprite and his mask. 33641 j... ..,{"130*"$tmp3" + 15+u(-5,5)"},\ # Draw symbol (with some fuzzyness). 33642 {"130*"$tmp2" + 15+u(-5,5)"},0,0,1,. 33643 rm[-2--1] # Delete sprite and mask. 33644 w. # Update display window. 33645 state+={(1+$player)*$tmp1} # Update the board state. 33646 33647 # Check for a winning configuration. 33648 (21,1344,86016,4161,16644,66576,65793,4368;\ # The list of winning configurations. 33649 0,0,0,0,1,2,0,0;\ # Corresponding X coords for the stroke. 33650 0,1,2,0,0,0,0,0;\ # Corresponding Y coords for the stroke. 33651 3,3,3,4,4,4,5,6) # Corresponding index of the stroke sprite. 33652 repeat w # Start to check configurations. 33653 tmp1={@$>} # Save the current configuration code. 33654 if ($state&$tmp1)==$tmp1||($state&(2*$tmp1))==2*$tmp1 # If a winner has been found. 33655 _x_tictactoe{i($>,3)} # Generate the stroke symbol and his mask. 33656 j[-4] ..,{130*{-3,i($>,1)}+u(-5,5)},\ # And display it on the board. 33657 {130*{-3,i($>,2)}+u(-5,5)},0,0,1,. rm[-2--1] 33658 if ($state&$tmp1)==$tmp1 w.. -1,-1,0,"Tic-Tac-Toe (X won!)" 33659 else w.. -1,-1,0,"Tic-Tac-Toe (O won!)" # Update display window. 33660 fi 33661 do wait 33662 if {*} w[] {*,w},{*,h} fi 33663 while {*}" && "!{*,ESC}" && "!{*,Q} # Wait for the window to be closed. 33664 rm w[] 0 return # And return properly. 33665 fi 33666 done # Go on until all configurations checked. 33667 rm. # Delete winning configuration data. 33668 33669 player={($player+1)%2} # Select next player. 33670 counter+=1 # Increment turn counter. 33671 while $counter<9 # Loop to next move until all positions filled. 33672 33673 # Here, the game has been ended without winners. 33674 w[] -1,-1,0,0,"Tic-Tac-Toe (Tied game!)" # Change window title. 33675 do wait 33676 if {*} w[] {*,w},{*,h} fi 33677 while {*}" && "!{*,ESC}" && "!{*,Q} # Wait for the window to be closed. 33678 w[] 0 rm # Return properly. 33679 33680# Generate Tic-Tac-Toe graphics. 33681_x_tictactoe : # Apply a hand-drawing effect. 33682 spread. 4 b. 6,1,0 sharpen. 0.8 n. 0,1 33683 33684__x_tictactoe : # Apply color to last image and generate corresponding opacity mask. 33685 +f. 1-i +n.. $2,255 +n... $3,255 n[-4] $1,255 a[-4,-2,-1] c 33686 33687_x_tictactoe0 : # Generate a 'X' and his mask. 33688 128,128,1,1,1 line. 15%,15%,85%,85%,1,0 line. 15%,85%,85%,15%,1,0 erode. 12 33689 _x_tictactoe deform. 4 33690 __x_tictactoe 40,40,160 33691 33692_x_tictactoe1 : # Generate a 'O' and his mask. 33693 128,128,1,1,1 ellipse. 50%,50%,22%,22%,0,1,0 ellipse. 50%,50%,15%,15%,0,1,1 33694 _x_tictactoe deform. 4 33695 __x_tictactoe 160,40,160 33696 33697_x_tictactoe2 : # Generate the board. 33698 391,391,1,1,"!(x%130) || !(y%130)" r. 421,421,1,1,0,0,0.5,0.5 dilate. 3 _x_tictactoe f. 1-i 33699 100%,100% noise. 10 b. 8,0 sharpen. 1.5 n. 220,255 *[-2,-1] to_rgb. 33700 33701_x_tictactoe3 : # Generate an horizontal stroke and his mask. 33702 421,130,1,1,1 line. 10%,60%,90%,60%,1,0 erode. 6 33703 _x_tictactoe rotate. {u(-6,6)},1,1,50%,50% 33704 __x_tictactoe 180,10,10 33705 33706_x_tictactoe4 : # Generate a vertical stroke and his mask. 33707 _x_tictactoe3 transpose[-2--1] 33708 33709_x_tictactoe5 : # Generate a ++ diagonal stroke and his mask. 33710 421,421,1,1,1 line. 10%,10%,90%,90%,1,0 erode. 6 33711 _x_tictactoe 33712 __x_tictactoe 180,10,10 33713 33714_x_tictactoe6 : # Generate a +- diagonal stroke and his mask. 33715 421,421,1,1,1 line. 10%,90%,90%,10%,1,0 erode. 6 _x_tictactoe __x_tictactoe 180,10,10 33716 33717#@cli x_warp : _nb_keypoints_xgrid>=2,_nb_keypoints_ygrid>=2,_nb_keypoints_contours>=0,\ 33718# _preview_fidelity={ 0=coarsest | 1=coarse | 2=normal | 3=fine | 4=finest },\ 33719# _[background_image],0<=_background_opacity<=1 33720#@cli : Launch the interactive image warper. 33721#@cli : Default values: 'nb_keypoints_xgrid=nb_keypoints_ygrid=2', 'nb_keypoints_contours=0' and 'preview_fidelity=1'. 33722x_warp : check "isint(${1=2}) && $1>=2 && isint(${2=$1}) && $2>=2 && isint(${3=0}) && $3>=0 && 33723 isint(${4=1}) && $4>=0 && $4<=4 && ${6=0.5}>=0 && $6<=1" skip "${5=}" check_display $0 33724 if !$! error[0--3] "Command '$0': Requires at least one input image!" return fi 33725 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 33726 e[] "\n 33727------ "${g}"Interactive image warper"$n" -----------------------------\n 33728----\n 33729---- "${c}"Left mouse button"$n": Add and move keypoint.\n 33730---- "${c}"Right mouse button"$n": Delete keypoint.\n 33731---- Key '"${c}"SPACE"$n"' or "${c}"middle mouse button"$n": Show/hide keypoints.\n 33732---- Key '"${c}"TAB"$n"': Change keypoint radius.\n 33733---- Key '"${c}"SHIFT"$n"': Toggle to original image.\n 33734---- Key '"${c}"R"$n"': Reset keypoints.\n 33735---- Keys '"${c}"ESC"$n"', '"${c}"ENTER"$n"' or '"${c}"Q"$n"': Process fullres and exit.\n 33736----\n 33737-------------------------------------------------------------" 33738 33739 if ${"is_image_arg $5"} pass$5 store. background fi 33740 radius_keypoints=4 33741 33742 repeat $! l[$>] nm={n} 33743 nm img 33744 if narg($background) $background rr2d. {-2,[w,h]},2,3 store. rbackground fi 33745 33746 # Start interactive window. 33747 selected_keypoint=-1 33748 view_keypoints=1 33749 do 33750 33751 # Generate base image. 33752 if !narg($imgb) 33753 if {*} wdims=${"fitscreen "{*,d},{img,{*,d}*h/w}} 33754 else wdims=${"fitscreen "{img,[w,h,1]},128,60%} 33755 fi 33756 w[] $wdims,0,"[G'MIC] Interactive Warp" 33757 +to_color[img] r. $wdims,1,100%,2 n. 0,255 nm. imgb 33758 rmn warp,imgw,imgr 33759 fi 33760 33761 # Generate set of keypoints. 33762 if !narg($keypoints) 33763 if narg($__x_warp_keypoints) ($__x_warp_keypoints) r. 1,{w/4},1,4,-1 33764 else 33765 33766 # Keypoints located on regular grid. 33767 nbp,nbq=$1,$2 33768 1,{$nbp*$nbq},1,4,"const nbp = "$nbp"; const nbq = "$nbq"; 33769 p = y%nbp; 33770 q = int(y/nbp); 33771 x = p*100/(nbp - 1); 33772 y = q*100/(nbq - 1); 33773 [ x,y,x,y ]" 33774 33775 # Keypoints located on contours. 33776 nbc=$3 33777 if $nbc>0 33778 +b[imgb] 0.5 gradient_norm. sqrt. {round([w,h]/4)} gaussian. 20% 33779 1,$nbc,1,4,"> 33780 begin(ref(crop(#-1),gauss)); 33781 st = stats(#-2); 33782 iM = st[1]; 33783 xM = st[8]; 33784 yM = st[9]; 33785 img = vector(#w#-1*h#-1,-iM); 33786 draw(#-2,img,xM - w#-1/2,yM - h#-1/2,0,0,w#-1,h#-1,1,1,-1,gauss); 33787 nxyM = [ xM,yM ]*100/([w#-2,h#-2]-1); 33788 [ nxyM,nxyM ]" 33789 rm[-3,-2] 33790 a[-2,-1] y 33791 fi 33792 fi 33793 N0={h} nm. keypoints 33794 rmn warp,imgw,imgr 33795 fi 33796 33797 # Generate warp field. 33798 if !narg($warp) 33799 subsamp={arg(1+$4,8,6,4,2,1)} 33800 +_x_warp_rbf[keypoints] {imgb,round([w,h]/$subsamp)} *. $subsamp 33801 r. {imgb,[w,h]},1,100%,3 +. '[x,y]' 33802 nm. warp 33803 rmn imgw,imgr 33804 fi 33805 33806 # Generate warped image. 33807 if !narg($imgw) 33808 +warp[imgb] [warp],0,1,3 nm. imgw 33809 rmn imgr 33810 fi 33811 33812 # Render visualization. 33813 if !narg($imgr) 33814 [imgw] 33815 if narg($rbackground) $rbackground ri. .. j.. .,0,0,0,0,$6 rm. fi 33816 nm. imgr 33817 33818 if s==4 drgba. fi 33819 if $view_keypoints 33820 eval[keypoints] "* 33821 begin( 33822 col1 = [ 64,200,255 ]; 33823 col2 = [ 255,255,255 ]; 33824 fact = ([ w#"$imgw",h#"$imgw" ] - 1)/100; 33825 const radius1 = "$radius_keypoints"; 33826 const radius2 = radius1 + 2; 33827 const opacity = min(1,3/"($radius_keypoints-1)"); 33828 ); 33829 X = round((I)[0,2]*fact); 33830 ellipse(#-1,X,radius2,radius2,0,opacity,0); 33831 ellipse(#-1,X,radius1,radius1,0,opacity,y<"$N0"?col1:col2); I" 33832 fi 33833 w. 33834 fi 33835 33836 # Manage user interaction 33837 wait 33838 mb={*,b} mxy={[{*,x,y}]*100/([{*,w,h}]-1)} mouse_over={{*,x}>=0} 33839 33840 if $mouse_over" && "$mb" && "$selected_keypoint<0" && "h#$keypoints>0 # Determine selected keypoint 33841 selected_keypoint={keypoints,"dmin = inf; kmin = -1; fact = ([w#"$imgr",h#"$imgr"]-1)%; 33842 repeat (h,k, 33843 dist = norm(((I[k])[0,2] - ["$mxy"])*fact); 33844 dist<dmin?(dmin = dist; kmin = k) 33845 ); 33846 kmin>=0 && dmin<"max(8,1.5*$radius_keypoints)"?kmin:-1"} 33847 fi 33848 33849 if {*,-SPACE}" || "$mb==4 view_keypoints={!$view_keypoints} rmn imgr fi # Show/hide keypoints 33850 33851 if {*,-R} rmn keypoints __x_warp_keypoints= fi # Reset keypoints 33852 33853 if {*,-TAB} # Change keypoint radius 33854 radius_keypoints={max(2,($radius_keypoints+2)%16)} view_keypoints=1 rmn imgr 33855 fi 33856 33857 if {*,SHIFTLEFT}" || "{*,SHIFTRIGHT} # View original 33858 if {imgb,s==4} +drgba[imgb] w. rm. else w[imgb] fi 33859 do wait while {*,SHIFTLEFT}" || "{*,SHIFTRIGHT} rmn imgr 33860 fi 33861 33862 if {*,r} rmn imgb fi # Window resize 33863 33864 if $mouse_over" && "$mb==1" && "$selected_keypoint<0 # Add keypoint 33865 wxy={warp,I([$mxy]*([w,h]-1)/100,1)*100/([w,h]-1)} 33866 ({"[ "$mxy,$wxy" ]"}) permute. zycx a[keypoints,-1] y 33867 selected_keypoint={keypoints,h-1} 33868 rmn warp 33869 33870 elif $mouse_over" && "$mb==1" && "$selected_keypoint>=0 # Move keypoint 33871 ({"[ "$mxy" ]"}) permute. zycx j[keypoints] .,0,$selected_keypoint rm. 33872 rmn warp 33873 33874 elif $mouse_over" && "$mb==2" && "$selected_keypoint>=0" && "h#$keypoints>4 # Remove keypoint 33875 1,1,1,4,-1 j[keypoints] .,0,$selected_keypoint rm. discard[keypoints] -1 r[keypoints] 1,{keypoints,h/4},1,4,-1 33876 N0-={$selected_keypoint<$N0?1:0} selected_keypoint=-1 33877 rmn warp 33878 33879 elif !$mb selected_keypoint=-1 33880 fi 33881 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,ENTER} 33882 if !$< __x_warp_keypoints={keypoints,^} fi 33883 33884 +drgba[imgw] to. "Processing fullres...",5,5,20,2 w. rm. 33885 k[img,keypoints] 33886 _x_warp_rbf[keypoints] {img,[w,h]} +. '[x,y]' 33887 warp[img] .,0,2,3 rm. nm $nm 33888 endl done c 0,255 w 0 33889 33890# Generate 2d warping field from set of keypoints, using RBF reconstruction. 33891# $1,$2 = width,height 33892_x_warp_rbf : 33893 if !h $1,$2,1,2,[x,y] return fi 33894 $1,$2,1,2,"* 33895 begin( 33896 fact = ([w,h] - 1)/100; 33897 xy(p) = (I[#0,p])[0,2]*fact; 33898 const N = h#0; 33899 ref(vector(#N*N),A); 33900 ref(vector(#N*2),B); 33901 repeat (N,p, 33902 repeat (N,q, A[q + N*p] = A[p + N*q] = norm(xy(p) - xy(q))); 33903 copy(B[2*p],(I[#0,p])[2,2]*fact - xy(p),2); 33904 ); 33905 W = solve(A,B,2); 33906 ); 33907 res = [ 0,0 ]; 33908 repeat (N,p,res += W[2*p,2]*(norm([x,y] - xy(p))));" 33909 k. 33910 33911#@cli x_waves 33912#@cli : Launch the image waves demo. 33913x_waves : check_display $0 33914 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 33915 e[] "\n 33916------ "${g}"Image waves"$n" --------------------------\n 33917----\n 33918---- "${c}"Left mouse button"$n" to drop balls.\n 33919---- "${c}"Right mouse button"$n" to rotate view.\n 33920---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 33921---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 33922---- Keys '"${c}"CTRL+F"$n"' to switch fullscreen mode.\n 33923---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 33924----\n 33925---------------------------------------------" 33926 33927 if !$! l[] # Generate fractal image 33928 200,200 x={-1.06-u*0.1} y={-0.26-u*0.1} 33929 mandelbrot $x,$y,{$x+0.1},{$y+0.1},256 33930 16,1,1,3,u r. 256,1,1,3,3 shift. 1 33931 map[0] . rm. r2dx 100 33932 +mirror y +mirror x + n 0,128 33933 shape_fern {2*w},70%,25 r2dx. {-2,3*w/4} to_rgb. ri. ..,0,0,0.5,0.5 n. 0,196 +[-2,-1] c. 0,255 33934 endl else k[0] r[0] 100,100,1,3,2 fi 33935 i[0] (20;80;0^20;80;0^20;80;0) r[0] 400,300,1,3,3 water[0] 100,2 33936 w[0] {0,1.25*w},{0,1.25*h},0,"[G"{`39`}"MIC] Image Waves" 33937 w={w} elevation3d. 0 rv3d. 33938 sh. 8,{7+3*i[6]},0,0 r. 3,{h/3},1,1,-1 33939 (0,1,0;1,0,1;0,1,0) /. 2 33940 ball[] 20,200,255,128,1,0.7,3.5 33941 33942 0 $w,$w . 33943 l3d {$w/2},-200,-1000 sl3d 0.4 ss3d 0.8 f3d 500 time0=$| 33944 do 33945 +convolve. [3],1 -. ... rm... b. 0.8 -. {ia} # Update height map. 33946 r. 1,{$w*$w},1,1,-1 j[2] .,2,0 r. $w,$w,1,1,-1 # Set 3D object coordinates. 33947 [1] 33948 if {5,h} +l[5] rows 0,2 33949 nb={w} 33950 i[0] ('CImg3d') i[1] ($nb,$nb) transpose[2] 33951 (1,0;1,{$nb-1}) r. 2,$nb,1,1,3 round. 33952 1,{4*$nb},1,1,1 y a y 33953 endl [4] sprites3d.. .,1 rm. +3d[-2,-1] fi 33954 -3d. {$w/2},{$w/2} *3d. {0,0.9*max(w,h)/$w} # Center and scale 3D object. 33955 r3d. 0,0,1,{if({*,b}&2,{*,x}*360/{*,w},$|*30)} r3d. 1,0,0,120 # Get rotated 3D object. 33956 +j3d[0] .,50%,65%,30,1,3,0,0 33957 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-22},16,2,0.2 fi 33958 w. 33959 if {*,CTRLLEFT}" && "{*,D} w[] {2.25*w},{2.25*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.25*w},{1.25*h} 33960 elif {*,CTRLLEFT}" && "{*,F} 33961 if !narg($is_fs) is_fs={*,w},{*,h} fw={min({*,u}*h/w,{*,v}*w/h)} w[] $fw,{$fw*h/w},0,1 33962 else w[] $is_fs,0,0 is_fs="" 33963 fi 33964 fi 33965 33966 rm[-2,-1] wait 20 33967 if {*,b}&1||($|-$time0)>1 ({u*$w};{u*$w};70;0) a[5,-1] x time0={$|-u} fi # Insert new ball. 33968 if {5,h} l[5,-1] # Manage ball motion and collision. 33969 sh[0] 2,2,0,0 sh[0] 3,3,0,0 -.. . +. 0.2 rm[-2,-1] 33970 s[0] x repeat $!-1 coords={$<,@0-1} if {$<,@2}<i($coords) =. {80+{i($coords)}},$coords rm[$<] fi done 33971 if $!==1 i[0] 0 else a[0--2] x fi 33972 endl 33973 fi 33974 while {*}" && "!{*,ESC}" && "!{*,Q} 33975 rm w 0 33976 33977#@cli x_whirl : _opacity>=0 33978#@cli : Launch the fractal whirls demo. 33979#@cli : Default values: 'opacity=0.2'. 33980x_whirl : check "${1=0.2}>=0" check_display $0 33981 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 33982 e[] "\n 33983------ "${g}"Fractal whirls"$n" ----------------------------\n 33984----\n 33985---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 33986---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 33987---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 33988----\n 33989--------------------------------------------------" 33990 33991 5,5,1,3 256,256,1,3 [-1] w. 384,384,0,"[G"{`39`}"MIC] Fractal Whirls" 33992 tangle=0 tzoom=0 xc={(w-{-3,w})/2} yc={(h-{-3,h})/2} 33993 do 33994 rand... 0,255 j.. [-3],$xc,$yc,0,0 33995 f.. "*begin(R = rot(8*sin(-"$tangle")°)/(1.03+0.02*sin("$tzoom")); C=[w,h]/2); I((R*([x,y]-=C))+=C,0,0)" 33996 tangle+=0.001 33997 tzoom+=0.02 33998 j. [-2],0,0,0,0,$1 w. 33999 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 34000 wait 20 34001 while {*}" && "!{*,ESC}" && "!{*,Q} 34002 rm[-3,-2] w[] 0 34003 34004#------------------------------------- 34005# 34006# Define menu entries for 34007# the G'MIC plug-in 34008# 34009#------------------------------------- 34010 34011# Function that returns the list of external sources to be included in the plug-in. 34012# This command can be superseded on the user '.gmic' file to add sources for the plug-in. 34013# $1 = try network update 34014# $2 = try 'gui_filter_sources' defined in local update file. 34015gui_filter_sources : skip ${1=0},${2=1} 34016 34017 # Try to update the command 'gui_filter_sources' itself. 34018 if $2 34019 local=${_path_rc}update$_version.gmic 34020 if isfile(['{/$local}']) m $local fi 34021 if isfile(['{/$_path_user}']) m $_path_user fi 34022 gui_filter_sources $1,0 34023 fi 34024 34025 # Try to clean older update files to save disk space. 34026 if u>0.95 l[] 34027 files=${"files "$_path_rc"/update*.gmic"} 34028 repeat narg($files) 34029 file=${arg\ 1+$>,$files} 34030 ('$file') z. {[w-8,w-6]} ver={t} rm. 34031 if isnum($ver)" && "$ver<$_version delete $file rm. fi 34032 done 34033 onfail 34034 endl fi 34035 34036 # Build list of filter sources. 34037 ({'https://gmic.eu/update$_version.gmic'},1) # Include stdlib update (last 1 -> Override default filters). 34038 l[] _gui_filter_sources $1 onfail rm endl # Invoke custom command to include other filter sources. 34039 l[] i cimgz:${_path_rc}gui_filter_sources onfail endl # Include other user-defined filters sources. 34040 ('{/$_path_user}') # Include local '.gmic' (or 'user.gmic') file. 34041 34042# Function that always returns a valid preview size. 34043gui_preview_wh : 34044 u {0$_preview_width?[0$_preview_width,0$_preview_height]:[400,400]} 34045 34046# Function used for filters based on parallelization with spatial splitting. 34047gui_parallel_overlap : 34048 apo "$1",$3,{if($2,2^($2-1),0)} 34049 34050# Function that renders a single preview image from multiple preview images. 34051# Pre-cond : Number of image is $!>1. 34052gui_preview : 34053 frame 1,1,0,0,0,255 montage B 34054 34055# Return name of a layer. 34056gui_layer_name : 34057 u ${"_gui_merge_layers[0] name,[unnamed]"} 34058 34059# Return blending mode of a layer. 34060gui_layer_mode : 34061 u ${"_gui_merge_layers[0] mode,alpha"} 34062 34063# Return opacity of a layer. 34064gui_layer_opacity : 34065 u ${"_gui_merge_layers[0] opacity,100"} 34066 34067# Return (x,y) position of a layer. 34068gui_layer_pos : 34069 u ${"_gui_merge_layers[0] pos,0,0"} 34070 34071# Set name of a layer. 34072gui_set_layer_name : 34073 repeat $! l[$>] 34074 opacity=${-gui_layer_opacity} mode=${-gui_layer_mode} pos=${-gui_layer_pos} 34075 nm "name($1),mode("$mode"),opacity("$opacity"),pos("$pos")" 34076 endl done 34077 34078# Set blending mode of a layer. 34079gui_set_layer_mode : 34080 repeat $! l[$>] 34081 name=${-gui_layer_name} opacity=${-gui_layer_opacity} pos=${-gui_layer_pos} 34082 nm "name("$name"),mode($1),opacity("$opacity"),pos("$pos")" 34083 endl done 34084 34085# Set opacity of a layer. 34086gui_set_layer_opacity : 34087 repeat $! l[$>] 34088 name=${-gui_layer_name} mode=${-gui_layer_mode} pos=${-gui_layer_pos} 34089 nm "name("$name"),mode("$mode"),opacity($1),pos("$pos")" 34090 endl done 34091 34092# Set position of a layer. 34093gui_set_layer_pos : 34094 repeat $! l[$>] 34095 name=${-gui_layer_name} mode=${-gui_layer_mode} opacity=${-gui_layer_opacity} 34096 nm "name("$name"),mode("$mode"),opacity("$opacity"),pos("{round("$1")},{round("$2")}")" 34097 endl done 34098 34099# Flatten list of input layers according to their blending modes, opacities and positions, 34100# set in each layer name by the G'MIC plug-in. 34101gui_merge_layers : 34102 if !$! return fi 34103 mode0=${"_gui_merge_layers. mode,alpha"} 34104 opacity0=${"_gui_merge_layers. opacity,100"} 34105 pos0=${"_gui_merge_layers. pos,0,0"} 34106 if $opacity0<100" || "['$pos0']!='0,0' 100%,100%,1,4 fi 34107 wh0={w},{h} 34108 wh=${-max_wh} r. $wh,1,100%,0 34109 repeat $!-1 l[-2,-1] rv 34110 mode=${"_gui_merge_layers[1] mode,alpha"} 34111 opacity=${"_gui_merge_layers[1] opacity,100"} 34112 pos=${"_gui_merge_layers[1] pos,0,0"} 34113 to_a[1] r[1] $wh,1,100%,0 34114 shift[1] ${u\ $pos},0,0 34115 to_colormode[0,1] 0 34116 blend $mode,{max(0,min(1,$opacity/100))} 34117 endl done 34118 r $wh0,1,100%,0 34119 34120_gui_merge_layers : 34121 u {`" 34122 str = ["{'{n}'}"]; const sstr = size(str); 34123 def = ['${2--1}']; 34124 ker = ['$1(']; const sker = size(ker); 34125 const N = max(size(str),size(def)); 34126 ref(vectorN(0),res); 34127 p = q = find(str,ker); 34128 p>=0?( 34129 q+=sker; 34130 r = find(str,'),',q); 34131 q = r>=0?r:(str[sstr-1]==_')'?sstr-1:-1); 34132 ); 34133 q>=0?copy(res,str[p + sker],q - p - sker):(def = ['${2--1}']; copy(res,def,size(def))); 34134 res"`} 34135 34136# gui_split_preview : "command",_split_type,_split_posx,_split_posy 34137# 'split_type' can be { 0=no split | 1=forw. horiz. | 2=forw. vert. | 3=back. horiz. | 4=back. vert. | 34138# 5=dupl. left | 6=dupl. top | 7=dupl. bottom | 8=dupl. right | 9=dupl. horiz.l | 10=dupl. vert. | 34139# 11=checkered | 12=checkered inv. } 34140# if 'posx' or 'posy' are equal to 'nan', splitting is done at the middle, and moving is not possible. 34141# 'compute_entire_image' can be { 0=no | 1=yes }. 34142gui_split_preview : check "isint(${2=0}) && $2>=0 && $2<=12 && ${5=0}>=0" skip "${3=nan},${4=nan}" 34143 __split_preview="$1" m "_split_preview : run $__split_preview k[0]" 34144 is_movable={!isnan($3)" && "!isnan($4)} 34145 posx,posy={$is_movable?cut([$3,$4],0,100):[50,50]} 34146 pw,ph=${-gui_preview_wh} 34147 repeat $! l[$>] 34148 is_failed=0 34149 +l 34150 apply_timeout _split_preview,0$_preview_timeout 34151 onfail 34152 if 0$_is_timeout gui_timeout_preview 34153 else gui_error_preview ${} 34154 fi 34155 is_failed=1 34156 endl 34157 34158 if $is_failed" || "!$2 k. 34159 else 34160 drgba rr2d $pw,$ph,0,2 34161 r {[max(w#0,w#1),max(h#0,h#1)]},1,100%,0,0,0.5,0.5 34162 posx,posy={round([$posx,$posy]*([w,h]-1)%)} 34163 34164 if $2==1" || "$2==3 # Forward/backward horizontal 34165 1,[0],1,1,'y>=$posy?($2==1):($2==3)' r. [0],[0],1,1 j[0] [1],0,0,0,0,1,. 34166 elif $2==2" || "$2==4 # Forward/backward vertical 34167 [0],1,1,1,'x>=$posx?($2==2):($2==4)' r. [0],[0],1,1 j[0] [1],0,0,0,0,1,. 34168 elif $2==5 # Duplicate top 34169 j[0] [1],0,$posy 34170 elif $2==6 # Duplicate left 34171 j[0] [1],$posx 34172 elif $2==7 # Duplicate bottom 34173 j[0] [1],0,{$posy-h} 34174 elif $2==8 # Duplicate right 34175 j[0] [1],{$posx-w} 34176 elif $2==9 # Duplicate horizontal 34177 if !$posy k. elif $posy>=h k.. else r[0] 100%,$posy,1,100%,0,0,0,0.5 r[1] 100%,{h-$posy},1,100%,0,0,0,0.5 a y fi 34178 elif $2==10 # Duplicate vertical 34179 if !$posx k. elif $posx>=h k.. else r[0] $posx,100%,1,100%,0,0,0.5 r[1] {w-$posx},100%,1,100%,0,0,0.5 a x fi 34180 elif $2==11 # Checkered 34181 1,[0],1,1,'y>=$posy' [0],1,1,1,'x>=$posx' r[-2,-1] [0],[0],1,1 xor[-2,-1] 34182 j[0] [1],0,0,0,0,1,. 34183 elif $2==12 # Checkered reverse 34184 1,[0],1,1,'y<=$posy' [0],1,1,1,'x>=$posx' r[-2,-1] [0],[0],1,1 xor[-2,-1] 34185 j[0] [1],0,0,0,0,1,. 34186 fi 34187 k[0] 34188 34189 dir=0 34190 if isin($2,1,3,5,7,9,11,12) 34191 dir+=1 34192 line 0,$posy,100%,$posy,0.75,0xF0F0F0F0,255 line 0,$posy,100%,$posy,0.75,0x0F0F0F0F,0 34193 if $is_movable 34194 coords={p=[$posx,$posy];[p+[-10,-1],p+[10,-1],p+[0,-11]]} 34195 polygon 3,$coords,0.7,255 34196 polygon 3,$coords,0.7,0xFFFFFFFF,0 34197 coords={p=[$posx,$posy];[p+[-10,1],p+[10,1],p+[0,11]]} 34198 polygon 3,$coords,0.7,255 34199 polygon 3,$coords,0.7,0xFFFFFFFF,0 34200 fi 34201 fi 34202 if isin($2,2,4,6,8,10,11,12) 34203 dir+=2 34204 line $posx,0,$posx,100%,0.75,0xF0F0F0F0,255 line $posx,0,$posx,100%,0.75,0x0F0F0F0F,0 34205 if $2!=9" && "$is_movable 34206 coords={p=[$posx,$posy];[p+[-1,-10],p+[-1,10],p+[-11,0]]} 34207 polygon 3,$coords,0.7,255 34208 polygon 3,$coords,0.7,0xFFFFFFFF,0 34209 coords={p=[$posx,$posy];[p+[1,-10],p+[1,10],p+[11,0]]} 34210 polygon 3,$coords,0.7,255 34211 polygon 3,$coords,0.7,0xFFFFFFFF,0 34212 fi 34213 fi 34214 l[] 34215 0 +t. "After",0,0,20,1,255 t.. "Before",0,0,20,1,255 34216 autocrop 0 z[0] {0,[-1,-1,w,h]} z[1] {1,[-1,-1,w,h]} 34217 if isin($2,3,4,7,8,12) rv fi 34218 +dilate[-2,-1] 3 /[-2,-1] 255 r[-4,-3] 100%,100%,1,3 34219 endl 34220 34221 if {-4,"const c1 = "$posx">w+2; const c2 = "$posy">h+2; arg("$dir",c2,c1,c1&&c2)"} 34222 j[0] [-4],2,2,0,0,1,.. 34223 fi 34224 if {-3,"const c1 = "$posx"<w#0-w-3; const c2 = $2<11?("$posy"<h#0-h-3):("$posy">h+2); arg("$dir",c2,c1,c1&&c2)"} 34225 j[0] [-3],{[w#0-3-w,isin($2,11,12)?2:h#0-3-h]},0,0,1,. 34226 fi 34227 k[0] 34228 fi 34229 endl done 34230 um _split_preview 34231 34232# Command to display text on a the G'MIC plug-in preview. 34233# $1 : header message 34234# $2 : header font size. 34235# $3 : main message 34236# $4 : main font size. 34237gui_print_preview : skip "${1=},${3=}" check "${2=32}>=0 && ${4=20}>=0" 34238 34239 # Resize image to output resolution. 34240 if $! k[0] fi 34241 drgba 34242 siz={0$_preview_width?[0$_preview_width,0$_preview_height]:[${fitscreen\ {[max(w,1),max(h,1),1]},400}]} 34243 sizw={arg(1,$siz)-8} 34244 if $! rr2d $siz,2,3 drgba else $siz,1,3,128 fi 34245 (1;0.5^1;0.5^0;1) 34246 (0,0.5,0;0.5,1,0.5;0,0.5,0) *. 0.65 34247 ri[-2,-1] ...,3 * c 0,255 34248 34249 # Render title. 34250 l[] 34251 0 t. "$1",0,0,$2,1,255 i.. 100%,100%,1,3 fc.. 255,200,120 a[-2,-1] c r2dx. {min(w,arg(1,$sizw)-8)} 34252 r. 100%,140%,1,100%,0,0 34253 onfail rm 34254 endl 34255 34256 # Render message. 34257 l[] 34258 0 t. "$3",0,0,$4,1,255 i.. 100%,100%,1,3,255 a c 34259 ('"$3"') is_err={"crop(0,4)=='*** '"} rm. 34260 34261 if $is_err 34262 x={"ref(crop(0,0,0,3,32,h,1,1),T); 34263 for (c = 32, c<w, ++c, crop(c,0,0,3,32,h,1,1)==T?break()); 34264 c<w?for (0, c<w, ++c, max(crop(#-1,c-2,0,0,3,5,h,1,1))<=0?break()); 34265 c<w?c:0"} 34266 if $x +z. {$x+1},100% z.. 0,$x sh.. 0,2 fc. 0,255,0 rm. i.. 1,10 fi 34267 fi 34268 34269 repeat $! l[$<] 34270 for w>$sizw 34271 x={"const c0 = "$sizw"-1; 34272 const c02 = c0/2; 34273 for (c = c0, c>=c02, --c, max(crop(#-1,c-2,0,0,3,5,h,1,1))<=0?break()); 34274 c<c02?for (c = c0, c>=c02, --c, max(crop(#-1,c,0,0,3,1,h,1,1))<=0?break()); 34275 c<c02?c0:c"} 34276 +z. {$x+1},100% z.. 0,$x 34277 done 34278 endl done 34279 a y,0 34280 onfail rm 34281 endl 34282 34283 a[^0] y,0.5 34284 r. [0],[0],1,100%,0,0,0.5,0.5 34285 blend alpha 34286 34287gui_no_preview : skip "$*" 34288 gui_print_preview "",0,"No preview available",32 34289 34290gui_timeout_preview : 34291 gui_print_preview "",0,"Preview timeout",32 34292 34293gui_warning_preview : 34294 gui_print_preview "Preview warning:",32,"$*",22 34295 34296gui_error_preview : 34297 gui_print_preview "Preview error:",32,"$*",20 34298 34299gui_check_version : 34300 if $_version<$1 34301 gui_error_preview "This filter requires at least version *"${"strver $1"}"* of the G'MIC framework.\n\n"\ 34302 "https://gmic.eu/download.html" 34303 u 0 34304 else u 1 34305 fi 34306 34307# Function to auto-crop layers and set their positions. 34308gui_autocrop_layers : 34309 repeat $! l[$>] 34310 nm=${-gui_layer_name} 34311 mode=${-gui_layer_mode} 34312 opacity=${-gui_layer_opacity} 34313 coords=${autocrop_coords\ auto} 34314 z $coords 34315 nm mode($mode),opacity($opacity),pos({arg(1,$coords)},{arg(2,$coords)}),name($nm) 34316 endl done 34317 34318 34319#@gui ____<i>About</i> 34320#--------------------- 34321 34322#@gui ♥ Support Us ! ♥ : _none_,fx_support_us 34323#@gui : note = note{"<center><a href="https://gmic.eu"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAA\ 34324# BXCAMAAACJMYjxAAAAXVBMVEX+/v4cO0s7OU4wPnEiJSju6+qiqrCMlZu3u8BufoHd3+FDY2JRLzljS2bLz9Lp9vrteR34lyZqHE3puI3S7/hbX6GUW4z\ 34325# wza97QiOaYUa6mqTdfz25i22+VxzqoGYqrht5AAAWRklEQVR42uyabZfiKBCFFYUCDDg7TqIh0f//M7duBSEx2p09Z18+7NzTPUYaE/J4qyjI7H7rt/5m\ 34326# nXe/9VtfS+vdb21U7Me/hNbblPzu/6czEs/Y39LmT/jU36C0+7/p/OvXeaf7S3+7bkQ19uN4uVzGG3/i31X0/3GyEFjXnu+991sCMN36dIGu479tLR9Cl\ 34327# +J/ll3PLMBKbJXbipbW+nq9Lgan2U/cl8V/4Tz3r8r+hEKMu/9CDCrDStdLz7RKXDGly+MxTBqZjM4hyJ3GR4Y1/suwOoHVuf8EFmgxK6YFWMyBI0yaGd\ 34328# Two+qPH8PwuDAvLX36fiyw/oFKRcdEHYuS9UtXB4GVSP/9HLw15JwjMtGfzx/jELwyLCjp3fUx/AEBUzlgYI8rh6oItBCGl+/TjH975Rj9p5QI+4gaVug\ 34329# YWPnQxOrvN5an0yFrv9+rE9m3oz7zD5xlxyviEBpHRiV+KqQgHAzoIeLAxAe+nw2tifq88pKn5P3bUTccZqzC69g0nc0f7f4ZY3l3OLQioQUdTsb/eu0W\ 34330# /RSKu8iwsrXuHHWvKsju2Vlgde3774cd2dxRe0s2xjI4psEhtl5ZpvAzdIVVNVgQXDo8jaWJQ9RGCdLtgeZjtAi26BftBqgyrCrg0suqxdvcoEdm1fdgx\ 34331# Uiqo1YOuxdjbasc6DmO1j5haeqgkLxe5e9uxQpid/EdpoYPA5FGxwYi+55WtCzDIlaMku6EgFL7gzJ2Hvbu0BKrsKq07KKfib/K150uOQoZzicVWr0E4a\ 34332# 3XG2AZMhgGw/LzcollzeLzuiu2Wotj0YcmG8sz6aYBMPM+fSl1UECzVyxjcEnFDS2i7HCYw9KnfQukS1Lod2ILzg1oTfTPW/DjBOtebPVKaUZrFFa3DYl\ 34333# WOzLmgKGbikaH0DIr8i+Z/QXVglqiCD6pMxwFAqthWDTjXRWVaqkFLdx1hnUgk3OStTNWh/YV1WmC5cwsN6K+MtZH87QW0wKrAmjOavq3RGJ/vT5uN7sp\ 34334# dz7tbWNtVbCWNFSljmml9POtGjaUt10TkN2TIBVrBeN3azlmxbBYFRY72+QmYxcxiAEKo6JWPjY3FiZBS9YXJ/N67zGxenwOQ2hAJG5k1eLKIuNrs7E2d\ 34335# fB0VQwpMau3MZgzlY+J/bVLPRJeppXsGzerYLquPYSDaILVSjZol7DoUPP66XQCMMkYMBbRnBVEZA35PLVzgr8Lq8vlBRfauLHQYlQbqgYGUFmpEP0MVp\ 34336# QEUBU7NhZ+wwoU+CWHzjryffq+76q1yOxWsgod2swqCCxdqVRYtrDKtFrhJZnNOL+Edf4VnTPGABZ07X9kLqBVA5KboFrV3/uL3jBZW6SJIoql3NJ4lbm\ 34337# wZrEEUBlV6JKoe2b3TpjggxptcBYnLT56F4cyfTzDsM2wGN0rLH+qrNDTiMidOK85fAsra52MLcGphwGskL3FRiVjXbIeBdYGVlKmE3+1eTjB+o/rHNsh\ 34338# BGEWqEsO8wIlFrCwscqH/E9+3zMxwFrFYc2IXeCJMKgShqDxhGLnQVjKKoOLEpEAY2OtYJ396eScezrrDmMB1eUKWktjQUOGdU+bHmboGC2PrQWq0JqPh\ 34339# HUnsEJmRS7q536ssYnZ2YoCjPpeWCEO3eqsRmAFwOLL5jD0cqzmzvJBWO0zK0dRT9eMfFGy690ZnPp0Utlyo0ShFPLjDNYPbuJlRz+D9dFaZ1zK4BuyXg\ 34340# LOU2gxYMvKCN4ZC4KHEHNUawrhZRPpJSx0E3EcpvgahSqwlKgmeD5+gUXzIKQCPQPT7zaUz+HIbtWzlDU2Y2qa8TJz1tiH4/EYZrDub/O7NxzvEM/IJlq\ 34341# pryPKQH4X/eddziCsWAp371531crIK6wGKvNhsfKEBcZ6AwuqsHQ7M5Yj0lv2SO2xCYrw9oLCgac6e22OxwbOyrQefeIW1fRDhTW+OR0dGBOEuGcjTTmK\ 34342# z26snnWrL1m2EVaN8MqFc+2Onh9gsRWbzujF+QhRWKz1ARab3s6NhRT1LSzQcrBWRBRKlXUftQ4Mq6+whhEtoPWjwOr96mwtk5LrE5lqBm0dWHnnQDDGC\ 34343# IMtAThJMpAKKDu/2vjygMRgWRlbiuhUunHiE1TfwNJUWSEOdltgcZzg4o4v2Aus4bo7O0ZzGzIrNHmGtVfuNoO1SvEGrKRWIDsnqWUNaLFIZFkogViRlr\ 34344# oo3yAS1lznNSyo0mpSwr3nE8rdFFisAmuvFrCe6X2/0ViSs1gEa1meC5+wrFNHNYel6XRUh1PqMyvWsIrDYixeKmj9mnK8td5r7JIYsqGbP3mwKvwEK9F\ 34345# 6t+r8AuvYzMVLnuRn/nPcxD6tsMISViuw5KLFWOC5VVodQwhaYLEuu2idc/0cliEub91lmMHq9RtYeTxEbrXXiCmZnCDpQkewUt7Vo9Bx5DQKCmS/WUFV\ 34346# TjXFV6Y6iLPU2lnsCGzRnDIsUihSJ4DOxbwP+oWtOGGJDJ8oULrdp9WOzNZpnIfh1aAeyLDu0GO13rHTOgHI2N5tG5zxHknKskzX5jsIiiFxW2JcTUD0c\ 34347# NleYJHzfxEWth7qTRrZilZvYYFVmQ15NO0hwzKoeeVHz3iti9KcFNlaamRYU6Glr8yKYZUEz0V9onTlakJYyXpnlbR0ttbkbqQDHLYQv1VZoTOWlZg+Xm\ 34348# yEGQIytmr4l0hvhFUVbAW8NlYNQ2EFeja/z3WDMjQRgfjlLatKKx4bsleeDbGl/ED9joUgU2IBliyBuHHIrADrNr6eMeLiUFs8VqWODArFFyhFryGplQF\ 34349# LyQ0GFk9Lm2Dd5rSsnf9VWK1z1mQslWHF4/4QcnpHg6ACj/fOmmDlN2TxPLUfhMZDuNwHNhQzY1x3pgUN8NRkrsdlvafsY766WGlBCqBkp9eua9MISp3t\ 34350# Al7IboA1Lo01W/KkEF5ZlZ1SNa/gLb/l99NwKWZWrC+sVdo1i601INCYDfYXJlbyoJXh8KF4amKFh/1xt6ZFe/7GXtUSMwIopK8YnERNlT2q4iyi+D2s/\ 34351# trfFrCaso8YXmDBS7MELw0Cy4BjzllTnnzCOn/I7/gLDsCq0GIhhXPsZY0XpgUNhdXt8X4DXsdIbYXUGgk6cPI+GpkKwyotGYEl6Yxh+e9h3fopDsfQZC\ 34352# Uz+SEWVqbQqrBYBRbhgOGV/H6usM7vH0aDE5gJLAnEsgU/cAAKKn6Qwz4rAkjeg+8/bJT6aCFjJ0X8IjWRUxDGR+YTLAG5ARaDAi2imuJ1jsJMy5njN7A\ 34353# wOeYwRH6vzvpsrHOOxgLrxt7KsC5PVgKrosLj6C+egmmfgcXImKKhVsbUYnABG7avOZxU0SZYRc7WFB/zTk92lnErWDUuAcsdi7P2Aqsm+PPnyVAOsrPw\ 34354# KJBpAcqAnA5cMjMWWBOqy4b/+BaJKK8mltPinsdaVBYQrLCCpckVAQfkb002FvupxCFZuWZZNNl3sMISFqZGHt9+goUYg/jwa1jnJ6x0Y2sJLZ4KJ00lA\ 34355# 5rQeAeqccsGvJ0/tMRx0SusKWKCc2tY6lj0/IuvK8OQahwaL1GYa1tHQX3tLJKL7iGEIaQ/FfGCaOI00cxR2PR4ajGwYCxgkRfOX9CIRu6QNmwqWzCCch\ 34356# lRZa3Wi55SW/OQD29gcdZvBJYrsIpCSuUYAHRN71tgIWWJDGUoAuxLWKwCK/AUAx4PcdTY31h9P/KxmExQjVHvNsiAi7B6kVnDkoG70wqW54bUHdewssi\ 34357# EfCSzhi2wyLyDFWqCFztzBIqmi+pC6nMYZmkA6dnfNyZ1haRBlN9PpvK7bTLqhdXzKBirX4pSZLa9fOmO/CwWvMIzH0ahlmFYCRFeGixtTdy55mksZ9ew\ 34358# JDPu1T4Xpcc/STe7JSdCIArLCDQ97OCFVZaxtnz/x7RPA2kGknEsj7pGFoT56NPLTyKdbgZLDXYLFhTEakiaHw/kJQix1d71h5ACKQTVTZFHMhhZ4Tdep\ 34359# Cln7QJJB67r/NLt8E1h0Q/W5x5hCRMABKyi3/NAkvYeO0ehfZth1fDdXIO1g1I7AscMic0uYInqOsti67tsI/LHQ7K46PMTyATWdymvhvz8l0+osHdu9S\ 34360# BglTQ1wATXBLJlzf5BWSkskeSsGRbiSURpP8DKq/MSFmp4ySUBlptguZbQNWcFvK6spKDU1eaF1rgLvz4O2tVvKknsYkqQgnCSfF8H4hyimdZkQ3BVXJv\ 34361# IUQxQxbVL+DQABsvj9A9FgBWifAtcDk4kVTU+iUqosNwJVjt1UFjfssFyKDAat5GVoid0WMdUXHCfkoIeTLHs98JLYBmfZ4Q5PXoOq2Mx45DBUht6ZBqV\ 34362# RZZHDuuVi7oQKnwIANCKHELF5s42bCldo5eciaTGLVZjkk+Uh5XNQ9VYiR/l3gfF2Evsd05fDZYh02hLU/OCvFu1HbFYaFnmGWBhCB0Wznd0TKKUcw2nL\ 34363# M/eYTlL8K6haqvi5A3WelF7eQIIUoy+vOkDYSVSVhBgVW3HJa8e9i/k5HcqpyEALLrGL03UQVUja8ubW2E1gQrJv7UG91Umc6mw6hT0yAIm9A4bosANSu\ 34364# WfYEVMS84SWabP7w0X1qi/DVaLr8sOkt9ew+ozawo7t8gCF05liCy4cIK1mWCfIiOWlmNC59BhbQYLL5VV6z+wM3EKtz5cUWkxYjgzyVeLLGwOdSPd3kE\ 34365# zwNqgdLlyyPkNrK+Uzldde3FQfd4eWl/GyHIjLH+CFTKG02BDWUs396RlsKAO61u8H1q2iAeruLHg4lTGpHUAkpyatn2jhNaHsVJdTEc+udCNtPJ5HkMI\ 34366# AsC5nmMyQgsVDJYbYdXeUZaVOnzYLdddqClT9Tz8m374KT5TnvNo2FcDthPAmGMUDxIx3OiruO5xoF1pPc6s/ArL0pDHuF7JidrIbEeW9HFt4KEvSl2H5\ 34367# aacpZ5VWMVXyL15REXg7wUtZ3VWHVZgb7A8lzAMKWFC12zVLjSqDTNYVeHdDsdD94Vd338aKQ/F91GbBlYrrjgHPZ7NlKPSUlgZjzzDciOskFuyao0p2n\ 34368# 84wvLKqsGCihvk8/OisxCcTeXFogGs4GC1/ihXE9cvoVRhsT/puLI5e4WVF1D6hdIC17tRWI+LSAKrP4zB6qGFWu08rBuzubDD+noJCyk+D7g2pogT3ea\ 34369# eF2nsuT8MkbPwaTnL9MGfDwGW6BhLN06X+RDDtgvqSS4ve8ydR1q+yWV7mBFWNx3FZ4ScXGg5C3QGWF8NFhpml+deTWbEFRYiTXhx9quwvxhB0d821LEm\ 34370# 3RlUv632UzpF1nInSXNBknONDQNjNrSyb1nBmAtf2vDJzvkOK0Rnsn67Ynp7hQ9YUGEkrEWW2incOXLoUQ9ABsrpnaL3a4jv5CcnGirIs8GC3UZYZC3hw\ 34371# hVWAKxngVHYyUpN/pnFymqZad21H6qtHxqdJN+If2cVEtbvdSJNHVx2jAx/acRVRH1vZFQpPvlV6bHXfVihcG26yox4+VnNwIdpm1jdg6WbELcIsNQoGL\ 34372# 7pYuAmP8Lq9Sh9OfvQbxR12idYAbC8wbrq1GDd2AX9NyyoxNwAQQZL1wX1jGalRRe0PNsKXoXHabBCREGtxQWwQoWlf3yNLG+KaezU+TewMnG6AevHD4N\ 34373# 1y4arSoq8GaSmzDFiO/PGvDE3XNgVTWmXDFZXjpbHqhxqIbJGpP2noTVLp07f+v7ChpY88NnJ/4SFOcNCibNrws4zTqjWJrSt0ZWdd0wU57tEijFNZZGG\ 34374# EmplKZ6bUUxTp1NwecwqMZalN2CB1ltY9OWmQr/KF9W/UtnDdd/gi6A4jZuJmPqZUIhkKj08qMpqpakWCqzS0mluy6xOCqjCHQMd17D4Hiq7yy9JoI1vg\ 34375# 7/GFYUGtvW5hgEpqWHkwbQWDj2b1mZnhd4pVDu8iP/l0xzM/BoWDpj+tHN2u23DMBSObfBXG32Tvf+r7hxaabu18RJsHXYxAi4tRTSlLyRttU3kc79oS4\ 34376# pTf5GTcPxDc9in0xePTzi09V51n/WxLp8tu2Rm4WAU/DWBM7p8yuTrAevuY/xqv/N2quf5AHakvG2p5W3gp0vKU058nbDu7njiBH5FWIqbOrZRUGrlxJO\ 34377# aqRF+jeEvEFw+xherypvWMuwnj6n56Jry0VLdUks8lTcBWBEBWPfkq5/Uu3WM8LFCe8YCHYal77HaWMYY9gorl6FCtf38mQoQz9cWjOrdmiwfXP2g6CO0\ 34378# XBNohz/BqsBqwno+tBJs1LWwPgWVAClFKyq3wQBxVw1Xc2lYvWRtWKWK3KOqynSX7iEr3wZa2a/vVX1f9CUyq0yvr3ZXKlP3lN21ZuQFSLk7wri7Kt386\ 34379# kajKp6zD5eH08B0kuaean5clM2L/Dqw7sP6cje0fA2HEswwdbFgTInY6rZg1kQj6YwwK8ICBgTOtkXagJQ4foKpDhWGRDhmGhimxYgtgaKHhhVbS/+Vyb\ 34380# axvZpnQIM0JDuq9sseS3fFyhHrgBEuDG2JyHVkhGr/cWBE1cLLaBbVaVr6OmGhvj8fWgbnByzfcR6LeSXiDSx0GX4Dam7eaXhAWSwdhKCip3s7VXV+FnY\ 34381# bhrw+1rGiN2+wQgHJdH1vDlOGYw+sozwMM3jjVYPnMIqFQ5U8d5gU2swJL0DTMcpWqsizW2GzOof1ZdV7YWkyYXF6sSwMBOFvh3va8832LCGsGIypI/yz\ 34382# 5zv8ipcdPWAr0hfjV40wFXXV2qImg6QvrhnwfzIPrHZgRA9stdNT4YihbXSg1UxYHbBMjPNoWFHUNqzH32UV6yOw8GCadyIL11b47z1zsWYxhoq5cYO1O\ 34383# xYyYcXwMQwTTR3s9aExRgHW621p375Vt9i7de+MLKxxM3GsPZXJTHOD2/nsf8BqtTOGZRCnXgBBJqx+5wb0hCVywMrWDMaTeq9kdVqyzp+1dDUhMRBYzY\ 34384# HektEhDJMxXjdyI6phKcaFYXIsUAByjU5N3ybbvWGNyg0Bou9gXRrWBnOk4zbNScEKIh3GhwEjBE4OWOsLLKnlPiwxFMqTu649BIvyMSxG+gFLbXh2gSc\ 34385# e1isbrEBEJ9kReKRAVxss3glLtzDPC2F9iwKrCWv/9g3H9jGstc3txVyUYZTSxjGKHnVRHDOylglr9jWXhqU/Rhbv5XW2h57lnVl4JncqvOgIG13PK47i\ 34386# EVYXWUcx4q3LRJjh9IBly1BlZEV0Gm6DFdyPkm/hcsAivgDxn9Nw1qxCBNzM6YGTCG/UhfMIB5F2SljxAot91CyurGMc9zYNIWfPc6LY7JwG1vlTaSo9K\ 34387# JdZYWywfO4WIFaBRpRoKxbIqMRRQTRcoBpUELTJVedUD2NlpqVYZLuhSejOgfnOPOkpfOY8vRqctNPDSIU+Y/QwtGkWyQ638MT5ruHK7hNakDTgWk8fHF\ 34388# ROzOfnmRJwvAWnO9vo4EvHECi0S3ik144+x/gRWjas5jBYQcrl1pI+B0BvswtN5Y35gPkaKdUeWrKUlrMrcToNBSDQJ+CJEe4ihYHlKY6ghA5OhHXlTMR\ 34389# jPdnrnG8d9sc3vHsfrWbjGsPiw80Jx/F4Z/1Wprkxd0926Tcd7ej+Fa3vhiw455Ia64dPDNyTfp4cGWE5574/bz5T9yFLDz+HYEe9eECk+h9aXzn1feqT\ 34390# halb8huwnzGXXwyVdH9qySJZkPz/XfH/5b/88/IdcfPxH+J0LVIAAAAASUVORK5CYII="/></a></center>"} 34391#@gui : note = note{"<center>is proposed to you by</center>"} 34392#@gui : note = note("<center><a href="https://tschumperle.users.greyc.fr/"><img src="data:image/png;base64,iVBORw0KGgo\ 34393# AAAANSUhEUgAAAEAAAABBCAMAAABW61JJAAADAFBMVEX27vz06viVWEaZZlbz5/Tv3urwxMeFXE2icmuBUT7w4u7QzeKaaFqRVUPs5vWKVEKBRyvr4vKR\ 34394# WEfSj4d/aGWuaVjkqqaca1+ATjnAfHCVWkh7UD/z6Pbv1d6DVUSGUT2TY1ONWUji1ubv0NiHeoaLd3zEgHW8d2qQYFCOX0+LUDri2uvcnpeQen+md3GKY\ 34395# laYYlGXXk3p3u3Z0uTFyN7nr62Aa2uoaFehYE93Tz/tvb7su7yYf4XIhHqgb2WRZVieY1KKXk/u1+Lvys/uwcPPi4KkZ1eiZladXk2ZW0nn2unXxNHpwM\ 34396# XqtrXntLPfr7DhpqKtk5yHdXuEcXSoc2uSbWeeZlaIWUjj3u/uzdPTvsrdu8LHrrmjipKQfYZ2ZWalbF9zYF+TaV6gaVurZ1aCYFakYlF9WEyJW0uDWUm\ 34397# PUz5yTDyETDTd1efSyNrRt8HOtsG8pK7go52IgpTMlJCbhY+rbF2QXEt7U0RiSTxXQjJ1PiLv5/bx4/Hw2+Xfztvmxs6WpMLlvMHNsbvCp7CalqqkjpuR\ 34398# h5iefX+iene3eW23c2VhXGWpbmKLZl2wa1unZFN0U0hrT0U/OzlRPC5aPCsrKyrKzOHCw9nnzdffx9K3u9KvudKnsszAtca+r76tqL2UnLfcqqp6iqiGj\ 34399# KWxmKK5mZ7VnZmbipbZmpLUlo68jY1rdY3JioC7f3eveXGfdG6wdmxpY2yIbGqxc2ZRTVNkUk9LQTt6STGFSjBHOS8qJR4gHhkWFxLd2ey5wNjGvM2Jmr\ 34400# mvobGCka+mnK6Pk6zZpKNpgaJ+g5mtjJB4eo6UgYu4hYHBh3+ZeHl2anBsV1RwSDM9MytmPig7IxPSz+ShsM3lubvetbl4k7TOq7LFoqnSpqd1hKLHnZ9\ 34401# paXmVcm6FaWRMU2F7XVZDRUpeRTZTMBxgMReaqsezrcC8n6mklaKfkaC/l5pbcY+nhoqvhYNMY4Cnfnx3b3xbY3eOc3W1cGFcWGBiVVZbTEliS0O4qbjS\ 34402# oKBQaYhBSFRDMiYCeYKqAAAKU0lEQVRYw42WBVhaaxjH4XDOoUREUhBEBQRFBLu7u2N2TqdzttO56czN3Kauu7u77rq7u7fb3X2/g9db3OeBv/Dg83D+P\ 34403# /7v+d7vPR8OhmE8Jhx4GSLsSuytFYyHceD9l/+fiPFrwD9/0/FjiHEM3tiYMXaZ9vt/+rVULNxfoHE39oH5MTcex8DhYB03EDCmL+z6+NTPVStWLj+xPA\ 34404# oGtH+GGxNAjPPB57/lOPNS/74D+18m7d7d359/3btTCAj/QowVB0LouLGvnbd+8/2Bw7cOHz584Kf9+3+4keSdMAXRvQxE0Amvzb/ss1f7h5tv3Rr5/ff\ 34405# Dzc0/zct/kZ2QMAHWJWgpugu17Mt9Tc0HRppHm0dGR9++bX7blP8y4aMOoc5CG4M/XRkv+/LNyEhzU/lUUVrARKKDQ/GNn35smnVxymKK7sX/V8Hdz74f\ 34406# fjdKLi1tJBBS85KTe32uSH840OSQKTTXTWv8P7yH3+w/cFBOAApzcxvY2ysLYSqz9428zqQY1qrOX/7wI9FI6w8NbRjYa2MWwuTEf/5jQSZiEIBx/rf9x\ 34407# SQMkOof6ubG7sMANS5xl1OqFxkEeO/X/te+JMyv9ncLZbP7zMyYTE6MV/vG9Y8M2m4Pn+c7+HIJav9UcAfC3NhsGzOmkhODCk90P55hgP/4+eusAl9QQV\ 34408# hqqFtDQ2gD20bG5Lh4oojd2exoAxIseOq6hwQAqeAWlLiFjiXgeAajCLKkPhM24BY83UMikQYVRAGZrvEPCy3SAoJRAKD2PKLoByzbmkIicec2jb7//m0\ 34409# yFD6nKLShoXfbhlg0EGntemwA4IPnJBWpeG75zZu3D5LpUAm7kJDWVB6wY3MQJfJUpwGAmbt3qmbtKSb67fDzOGgLsWXbjSx5Nz3SemMojmc+MgBwMufa\ 34410# i8+/HSwOMJo41YOn+S7u2UTBQQuaenvcDMrZ9QYA1vTv/Mo75fU8oHKBwK8vfhaoR6D29fklg7JqPWxACf2k2df2TJw7r7z8puBguE2NN2tu01uLbXVxb\ 34411# cKVj/QCjFf2sJJJvgUOxLKpHqIyD3ez2E7XufNul+/d4rIoavlivN4usJ+VsgPsJEVpY5qInkYrkcU8uvhyIj2sZvXqzJ+r2/QCloEm2EEqJKghuoUF3R\ 34412# SaI4uPjd+yk7tXpryfuXij/k78QOWbDABhBD5EmwRB4SV9yuDVzO1m25gcNIOS5WmtL8LSr/J2qUh5oe4REA2CNCVFQ/FI9BYwEWqCUSEyIUGmD7Bw1sC\ 34413# u2aS8VPdwQACvkqJN94VbGmxC4tEg6xkZCdtgfXvRPg8DhLlH8EEJ797R2HmjVwfY3/nUoNbW1tHrz+lLcFySl0wiFWIl2NraVlTQbOp2MZPDi8yUwRnW\ 34414# 1pkbMvQ++2eqVMmkwtQICAIEMrlizjaO57PC8O+YMWhG0ON4/Z1ot+KiimTkD4EloNF5PAtan9Kz/aI/2ycWRdEn7doK9N7HnVwN1gOgFeg0/lBI7P3Hu\ 34415# 9x8OGhQUHQgzgDdrVUZhdPJPBML3qFDkyLYPkrlFzsIZvEAYA0bkoCxlsRVQ4BQMc3E5BDE3hx/pUAcZlaDZgSO+/VM99OkQjUEKjA1nUQDvczxav80ZQ\ 34416# CUkAGPGVsWdnbM+BuhC5v5woig4YM+VJta0N3BAnrGbfFhuqBjBeDxH9SqZLGANX5i021newJB3Qjx1RpL8sEKdkgs+uDJBiUHHdsHeOcLKYShDfBfBz1\ 34417# dQPoF8FhpbOTz+TSybbgN08WrPY7DcUG1sc0ZJ7+Va4qYQlhrNsebm//PTQAPRjkxjUa3oEUMhShdUM/ouDgvdLr2YHX3aQqB7w4AY348rAvArykAE4Uo\ 34418# IpN5FlCJjdIlGkWjY70QGPPjl1wqEPPdNyEw5ofxxuYtuhuq1k8sJhInepDJZAtoKORce3Bb8APwk1rAUkmBBhriAABsDsPGeGNYdxXsxfIAAJgqwAjuv\ 34419# XWrH7Q/CMJjUUHiBbVG/PC+GCwB3MLAw/8F4BlLan3VmlIsgQfIwKMXXa17sjpa+OdpFLa7QIhwt8EA5uCkyzBnMIBpvL9aIiuXbH3lQNBAjUTR1LkeHg\ 34420# IyT6BW1f0SgyIUBA8DAmy3JiVijpknBYbh6S3TGY7gsA1WogWhWFm1RmV19fT8Np8M8fmNpSKBQHCTTBaQ1bvqXLxiAx0roygYIP00FyrZ5oVMh7VuR0d\ 34421# HnFNr1ASgqhWf5OS4SoeP3qZBfFNLOkYANYgK6+I80csJFKvjkaAKSvoabvicTVgiBoNh55iezsBNAerI6ly3MTExKTf36LE7h2iQKd80TUTmlfMEctBI\ 34422# KPrxDSF1uqMdSEC9IIaKNnkhiB0jMjLdzsrODldVVZXVvTGhW+LqmpSbf+TYHZMKGoSFEIl4ZNO9Sk8UDTrzZrWTFeVuZIvxaVeyRYQsVohgXiuryZOtc\ 34423# Fkd1R9vrM++LGW5uubemH/s2DSTCjCQTC1NIRotXAYGOprRtefqs+qsrI4JCy8Npvn3bj7XBqxO4AWE6zy1rt47J8dbwmK5sjDA+yYmk0ACrcAo8vIK/v\ 34424# QayTc5WUXaqbpy5eoGl/uZ0dZWVKoV1cmJSnXCJdRftgfyTsQA+fNvHQUAWzpkSoNABnaIC4cDxqQvF6iggEtKlm2KRgIXzYCXfeh4nIoJJ5FIpVJ7b3v\ 34425# pdUDInX/k6DsT8FyEsIliCRUx489tAac2LtihRlyuEbeQa8MxpyAIbunZVvMxQE99vSRJai+1T8rPZwHAkTsmh2xtaYBgSYfmMDfXzeYSjLTy8xODUeHu\ 34426# EwgjM6Y7nZxCXagFdHd3f5KTKJV6S3YXu+4ePnLrzjQTW1ADEI3G9pEpr2lP3sCuKA5QyBXQ3hgKskgYebJj5konZ2olrn7FihVnahMT7bt357KuDx89C\ 34427# gAmFSCCRgNBYQ1mLi8xO8FPEUAEe0xhaem/yTqwdfHi89UPOxnOzlSc9/qoyhMf1kq9O7bmsr59M3/fkWKyCbYQ7AECBJWEfDWSJldYitJ4PB65jEgUiS\ 34428# CzGCRwwpTn1acDcZOdnXE52YuWUyvPSj+PWvM1K2ff4a3De1hTsYluI/NtpLtvfk0QK0rp4LwzelsgArtcpOj1QiitWd+cWgkz0gFgbXbb2irqPUm29Um\ 34429# Jq/T7fScubEzCCJPMNs8qtXD3zzMCBWAjoqwMBAgQc7c/80QolMpLH0Y5Uo2PO+POZEedX9e6tKfe+t7axKTrw9Vbq2pZL/wqbIdqvnCg204jgFvvJ5dj\ 34430# Q6ZULh64uiGuLRBBKJEnVlktWMrAOePWfVL19LJwydps6/fWSpKS3kz49Yvll1gklT+bOTuAZzJNQxAPOsjFAQqxQk4gpPadC0LwAECx6oq8t9IRPxnn3\ 34431# fPRWUnWkq51Ue+tkiQmvqr+LP/TrueslO2y7XLgt9wpHhx0cCBiUmBrwAxGhEIEyGrBw+WRduk4+5yEVZL1lavOLHZeJZEmvlp3vn/2qa9zWbOvXCsDgC\ 34432# dfOwz6OWgJZZallnS+j+eitqBABHTjvTWVTlTGH/5VIUZ4CClbAAAAAElFTkSuQmCC" /> David Tschumperlé</a> and 34433#@gui : <a href="https://foureys.users.greyc.fr/"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAM\ 34434# AAACdt4HsAAAC/VBMVEW3xMQAAADUqJoDAwEICALFmozFqIwGBQG1jYA7O0EfICUdHiMPDAoODASth3svLzYFBQQoKS8LCQM1NTwaGx0SDg0bHSEHBgYJ\ 34435# DQTRpZfCmIpuVk4XFxh5XlU3N0C+lIemgnaif3OPcGZ2XFM/P0clJSoXHAoUFQfAloi4kINrVE0QFAgJCAece3BZRj9WQz03LCYODw8UFRjNo5WXdmuEa\ 34436# F6AY1plTkYpKysuJSEYGBwlHhsYFRELEAWotbWxin2ffXEyMzlPPjhMOzVHODMkJi4yJyILCQi0wcGTnp6CZlxPVVVDQ1VxWE9oUUopKzQsLTJDNC8iIy\ 34437# UrIh9nbm6LbWRZWGOGaWBJU15eS0IxMT0gJCkgGhYSEhUUEg8XFguyv7+Ejo7Ep4u7koWphHibeW6ZeG2VdGqJa2JzWlJERE00O0NSQjouMzkhGxkfJgo\ 34438# cFgkQEARBQUk3P0diU0ZBREQxNj4uLzoqMDZAMyoyKSY1PyEQERMcIQ8LCwwiGwgYEgYSDwSturqfqqrKoJOvlX2UfmpXW1tJSVFHR1BIT087O0hhTEVZ\ 34439# S0UiHxsoIA8nMA6wvLyMlpZ+iIh9YVhPT1hFT1h7aVc6QUlHR0c3OEVdRz86PDwxMzMpJyQnIR4qLxoeGBMcHAocIwjHnZDCpYpubXpvdnZvcnJkZG9XV\ 34440# myTc2leXWhWVWBOTk5LS0srKzA/Ni47LyovNRofIBQkKxEQGwq8oIVcYmJcXl5RUVtWV1dMS1VHPzgrKRSXoqJhY3iljHVbWnGbhG5naWVQW2WIc2BNTW\ 34441# BTUl0+P0xFSkk4OTZ6hIR4gYFze3ungHFQUGVjYmGDb1xoXlVdWVA+SFBAQFA9QEE4MjIuLy80Lyo5LRmFhJG6k4d1dIC0mX9vbm5UU2eNd2NJSVtGSi0\ 34442# 4RBYyPRQ6LQ+lsbGapaWAf4tsb4Z5eIVYY299aWlDSlN0Y1JvX09RSEBMQz5CPz4/SxinrKyVmZmNjIufeWF2Z12ObFYuJgeXgXY+PimhEuIiAAAMWklE\ 34443# QVRYw7yTX2hSURzHPZ57UeIqcvE2/IdOiZz5Z+OqUxRnc/iXDUrHGJhOlpuDMIN8mA+p0xJGU2a9jDlXIRgEjUYPG6PtZU+tFVHQ/hD0EKxeeqgoiIqu+\ 34444# 1Mrrce+cO49f+75nO/5/X6X9h808O/lMcvfVjKumjIZT3HsX4C3RRrN2eDYR7enNrjE1tbHucTG4rXJ0F995KouZ7XOxcraxw/laDlh8psD0Y1o28yZ23\ 34445# 8DHPGUxkJ/enT52ogNP4SEFygJwDFjDliyvMk0BAjX45bxT79fovgxYOZgsw6oNI4qIXaTg2EQlnIrDQEGD3fhczF0eOrN3GmHIOJ1MxX6qLHrqk5hw0x\ 34446# +AGYsjQHjuaXqo98cWB4qFWQky6PzeJJmhUqalbrJl60AxC2NAa9y48Xf9zsUZ3t5Ffq+Xko7SOrZa1YWnZb6hHnGF0vVMdehMPowQUXWjUoPALzs3ksV\ 34447# zQ08ri+J0NTdBd9YaPUnemWzhxSPnqWTJP0PWVcbVdTjtuq4J+OJHxTKpIGI8BQROr1Zsntuyy9Atmu1AeDFyczk5NuFjPMAIGwdtSp0tQjubrpDQX5aW\ 34448# GtQCty7S5MZn8+zvnIAGNX0yw8Zp8K3F4MKKdM8qg/i2sy19Zm7S4uPB/YBs9PRTt5hAG8vGJUIaRVw6zP5HBoMU9y5tYMYWPJGwka2qLL0OvE7JVt/An\ 34449# y055e4r0qbc679n9DlafLrjFKyIiLrAD32ygMK4Mw497+lkl+irT4vx59Oeaq1SeeAL795U0u6+3gkX7Vr//BltApFIrRwO3Qst1CdHHAVPZeowqCVVg2\ 34450# LL3IzPgpgcVXj5bI3q4tIVa1aZm1PM/uwhYr6jA84hADi5pnNo7OngXDFQ1szTJWE3IcLb9/QckueYlnozarYIjMw6/v6OujkvgPenb5aZkYuxQN5IlbY\ 34451# 3i4AvMAAwOygGcvxMnZm3VdcsVwz5F5wgDc7JOoSCLqvtzq8CrK3km05Zzun9tpPySlAk8GfD2zfYuDpGJ5kJHGHktYUJHAEaVMKuaeFTW2Y0pEYmieIU\ 34452# 10Jqa5HOMJDeb3XE8b3l7/NG9UUgPPgCwZYOzvpFJLGWTuxJItmBgDHY0kGUH6/ceOGn0jkmzp7ulVqAnb15LF+Se+dL1cmavpgktBHsGf3TIBRSMfArW\ 34453# QhCWMpQLOD4wAGWRAoX7++HyBknd3XO1qmNRrO1jNp74h/3mS6N/EuqmwavWgy2bTGAHSkYoVYGsdBOgVvAkCj2p5uvl7ehq3t04RdEtaEZecmnmkiNuZ\ 34454# gpJ1te/dudjpiPyuax6IExmDFGAA5j4DkDmRRAFATQvXMy4UglMkEmLq7Y1DhZrL1IzKvGB02Dl2fmNA163SivmbbVZGdEWQdh6kLt1iprxCnABACKh0Q\ 34455# AYXtWAz49e6AWn1V6pZq+eI+tUksVykEeiYTbRmShZvl7m6RLQU5QQAhA0my0pACpBCIBzngAtgV8eRJoF9uVQgEonBYpjGKmV2Doqtn+WK2VNRuZfcLh\ 34456# qNgXwiCfK1dgWrgxv0TjAPAtEOAarUoKrcyVWa7uOWcTDrUYu206SUSvs6mkAEIaoLwAkgjNQdBanSLFYMIYw9wyjSI8vkoynSjEuMwija3C6xsvlgsR9\ 34457# lhk1qur3llMBgsiOMQT1OAPLXt/vJyAUGOU732jlOz4kE+WhM/3MMcVqHtw2zm7jgik/Uz7YASC+5eASJpqpB+sFQ2IUqEYRyfl/eVmUCHYSt8UQcdrRl\ 34458# nRx0NP1piUFxxwVAwMxEqCb8SpMGFDrUNdSk6SAjZIaIvpSA2otbVW12KDtWlCIqIiKg9dIqgQ3TpHet3GIYXnv888/z/zwyacWCzVjtrQ9BKzwVkVZ4X\ 34459# MJl00O22MGrdMof1tDKCFdA2MAfSEk0UKKQhSYREdcFKhO2F4tFK/FrU7Y67k8XlYpzpX+P9Fj/pJzbstDZaVrKKCIDeAqDRuYWRDVCTrW+DgaTBmlSDg\ 34460# KzYzrzP39m3L1zOlxL5kvVEqcwKbJ6xMMEU0+onreTRBJpkyNbrIShRmqSL+tYWtiFAqEn2ht/h57vHPdalnSuZdNpZDW2UU4V4pxLzt6os6YDkEAEagg\ 34461# Uk2UCPAhCLhoIh+I+d9fvqFn89tJLrqDmejzqj+bjcXWowwXTscBb2SCmBXMjUEXFBGejKE2KANUCOFmjI5YjhQsoZVePxYW69HE9Z8jud6rrF4k62AxD\ 34462# UaKDR/6YooXM0oNBYMaSRSHMcGQ+EHLgZDVa8+X5TCPed/VKp0FrMqnJIIInwdlEPmOGh//tAxggoHSARYGIE0nVNH+NZoOBsMJmkW24W98VzsWFiI1Rg\ 34463# TIE6exhIpl+kXsEaNCXMV9BmmjLDioY1DWJzkmHWwWQc3mjQE1oOrKSvNRx1byxJglDeCfB870ww/ndHYaRhPJvNtKORCJ4ZSFRE35BJy6lKxuNgvd6kz\ 34464# DgYdZElM8gAhMF/FwDqQWhDCFEAcBo5VeDJy69cylQUp8al4w5vnlUTxfbGkA8XCkIydpptNBJ28A+MTZ3BVP9FIkTdIkwVZQIjr465ADD1Nh+32KjcZs\ 34465# LZ5cCyM7GeYCu8pameDq9IY4I+GG8NpoNfv6a6CEVqjfB1bbImGq4XR0j9Gdeex4+dAsmCp+KRfesCry42u4ybf37h/JufNzYREgfit2+SJo7GYm+MKQN\ 34466# CaEynhkE+ChC+2//g84Mdp085vUmhWiqwQaERdft9xTr/5cfShQ+rn+6u7lrdZud0BU0MGkqiQhlmCxOMUGTTRf57By+/DB3OJoqynBTasQRbDfssjlCx\ 34467# 8+VOeOnp+107rnzfdv/jvUNXIpGjoydPJkQAcByHJ2uTva+fXd2z48Dlt7//3M5mni+m2zmmwjc8cpPxpLtf7twJP6puX3149+HFQ9/v7vr+8eO967vRa\ 34468# C7wt6ayCW0aDsN4RCzm/xfTP4kpaA0eEhDxq0Fwxh2MGi8GEouWmFjBXoTUeGhr20npraVd1Yu0q1URD461tm47FWuFtqNrK6hzuokgzrGjil/gB17MBH\ 34469# /393ne530Or8uVvPHg0cQlsRi31HNXn/8Z3nS6PnN0+v7mzee3bVy36/zhx7MBR/3xi4M1b7nJ8SaLr0KW3+WzZ+3XduP9i0cTLx5xghGlw+jck9/7nWv\ 34470# uphztO8Ondq3fuP3QvgPDtn878msikc28/fguDzPVqm+8AbkpUP2IY7ceTg6h1wzo1xi6q8UvPdty89iZg18DgZnIhU0njl05Ox2Zvee4F7n9EOpUtWaa\ 34471# RSZcZHNsbnm5NRhkxrHjbpgh+zhrIXf8U7AIT04c2ToyMhZwBJaW0mPz6XTKYZN6+fMNIng2iVpdujColJTeoqCaZCOEsURTzTA0Ho2rYAHQweT1oZGRv\ 34472# XvvOQLz7bELewKOf/PTvyY5hrGPqHygmVxFknOyXFSrPuYjNi4KUBV8FKHQyHDdjtOj1717926YrQcCS/PtmVWBQGp68pIR7FUk2I9+HsC5FkBRXQZ4iD\ 34473# HLWI0RcC8xjnhe6vqHRqkSGL3+fWRDZEfd8Z/Uq8kbKEfKHbgTfYrmvKUWSBpSh1Y1/F0ZIxmzLzTIMmuAIE0kaDgHnpz7dvd0atV76XSkbuf/8cA1V4J\ 34474# zDFqrFTslmJPXUD2dgTWg9msYp2bjkunJQpcnGPYwxJSuJ0afnrw2vbpBfWa2PT8TGeL1SrArkoSzEPsAPSvyWkCQeeQjCZLF8q6MXQNu22tEMpGFMQU0\ 34475# p+DDB7vbY6tEvqYj1NTKSicXRAS91hYQhF6MJgS/iji7liZGSXiIoqNRCLUoT3hdJGMgnFtz8UL6y90NZ76mD1/DG6GerNe8Ccbr0oTlxVIlyQJfk8jbv\ 34476# fqqmCto1TjNWIiDoEYRIuFnOUjGPUn/cGQs/eXOxZ1ixvtZIX0myWQF65PSEphlvMHhoawPiawdwSTDMLxgRAsgXOAJXZY4WpQVxIeAy3V5WJEInGM/A1\ 34477# +ZdJMiwAuxFX+PMxEtIicNRESSGBJBtBi3V0gYQYHhdcMUqVJUkaBVXLCCMUlnGI4uNTiax1XCFlAkmcapAZ53rnGzXreFAcPSDAXGw0OEpWYggfwxmZc\ 34478# lq4AoIRyWlQrQKyLbcIfjRYvktDBoDZrqYg6nPHzflzU5DAF/AqeUboxPJCQ9V4LOWMW/KFmwKcbU7KKkzHWE/DjhmSpoCcLZ1fQO7uMId1VI+rM4zXr/\ 34479# AnoH9FcRhS6kAAAAAElFTkSuQmCC" /> Sébastien Fourey</a></center>") 34480#@gui : url = link{"( IMAGE Team / GREYC Laboratory - CNRS UMR 6072 )","https://www.greyc.fr/?page_id=443&lang=en"} 34481#@gui : note = note{"\nIf you appreciate what we do on <b>G'MIC</b> and want to help us maintaining and \ 34482# developing this piece of software, please consider <a href="https://libreart.info/en/projects/gmic"> \ 34483# making a donation</a>!\n\n"} 34484#@gui : note = note{<center><a href="https://libreart.info/en/projects/gmic"><img src="data:image/png;base64,iVBORw0K\ 34485# GgoAAAANSUhEUgAAALAAAAAwCAMAAACG2QC0AAAC+lBMVEV7e3uQkJAAAAAMDAyIiIhdXl68vr0rKytmZmZsbGy7vb0mJiZxcXF+fn6NjY17e3u1tbV0d\ 34486# HRzc3OEhISbm5u8vLy2t7Z4eHh6enp3d3eVlZWUlJSdnZ1vb2+4uLiamprOzs5XV1ezs7NpaWmHh4etra1eXl6Dg4NtbW2np6eDg4O9vb2YmJgrgnFwz7\ 34487# xqzbn6/fxlZWVsbGwvNjRtzrtuzrt00b5iy7Z0y7pky7b3/Ptxz7z2/Pr5/PtbyLI9ppFnzLd2zLtyy7lozLhz0L3z+/ny+vhmy7dvb2++6eBszbrB6uH\ 34488# a8+3W8ettzrr1+/nd8+/S8Orm9vN20b9SUlLo9/St49gqfGwuWVHj9fG5596G1sZcXFwyMjLw+fdopprk9fLP7+htxrRBkoLu+ffs+PbN7ufG7ORajIIs\ 34489# g3Lf9PC76N9+1MNpp5teo5VboZPU8Ouv5Nmr4te12tJ40r9ku6pmsaNZp5hNmInq9/W25tyZ3c+B1cR+tak4jn0thXRdXV1QUFDR7+mz5dup4tam4dWj4\ 34490# NSQ2suN2cp60sGZx79frJxlppljpZjY8ezK7OW649qb3dCU281808KFyrxqvq1NnY09k4Ivi3lOTk7E6+PI5+G43tag3tKk1cqK2MhPsp4+kIA4jHwzjH\ 34491# vE5d2t2tGp186MxbpWq5pWoZJAmIdFlYYyk383inpWV1fQ6eOx5dqo3dKd3tGw1s+oz8eYy8F20b5pzblvyLaDwbWDv7N5vLCIurBwr6Nrr6FFrplEqJR\ 34492# OopJSno81iXkrg3JaY2FDSEfV8eve7+ud2MyizcWSzcBtyLVfyrRww7NzvK50tahZtaJksaJol45EnItdj4VUioAziHdbdXArfW0qeGlTbmlkaGdiYmJg\ 34493# YGAmYVU3W1RQVFMoXFJIU1E+Pj7T6+aY1MiOz8KG0MGOzMCNy75owrB7s6hknZFBo5BEoY9DoY5UnI41mYVjgnxfgns9cWcnZ1o+X1k1TUg5QD4sPjsfP\ 34494# zgzMzMkKilq0aUXAAAALXRSTlMdvgAO0AmQAv33kAjy38w1MBPu1rJ4bibm5MS8uKqJdV9ZEv20nJORfGVUPh6rD+f7AAAHWUlEQVRo3mJgggJuhsEMBJ\ 34495# lgAOpgAQ1ZacZBDFTUtJSQHCwoKsyjbDiYAQenpIg2O9TB7PwinIZHvzg6EQcsqAYciQcXjhpyCIlxgx3MLi7C0XBbj6bA2gUFmJmZuegBSbwgGAJg3Lc\ 34496# 37vBocoMczCzHGXP7DB7baOR8M+JAMMzhwZfvCPODHMzP23BjqqkevYE1DBDrcrNtRznVuZkYuEU5Pk81oaODMZ2OHyC8FW/Ix8/EwCxz77KeqaneIAfW\ 34497# ZmbWO2IkFIEO5mu4agIFpkAwONxuHVxSYoae7s+E8IixMzCzwB2McPWAu7yjwC00OwdFyMVlR6MHFyvIwRleXiYowAsIQE4fOLcXuhkYuEVtQxVMavRgA\ 34498# zkYQE0Z7KYNBAH03o+BOdSsdu1dIRnbMiYlsQQSdoUaiYQq+BAQl9jcIAQujYBTK0X8QpRD8wk99dqf6E901osDjhWlx+QdGHZmdubZB3/+Wi7XFZkwJg\ 34499# 788+6fUrQir/V8zLKvs+wzAH4UHqTywkUy4SLF1v/sqReyL+7YHgPSudlnngm/NZIzJXzwxG9aeHLK0Jd/C9+J8PLWAMSK6+9D+FPQBIT7ia7rWlEYP2v\ 34500# VqimT1Wo1Depkqqj+qFDOyvtkvlmNUKFQxWC+NO7w1qoLEt5ygyC4Xy0xbSrh79kbptSRUIyV1TQYDIJ2UteuXW+kOc545LrXzs+Z67qe58YP2LYceh4e\ 34501# B9OEIk71po134vlGjlh7niwG92vN0YZ4R4JhrebX5LSy4yzbrnuHO6P5dOC68Wyx2++YSYeDMmaSq7iSpvPCKYSgiteyGGeG7df0E4AjndLJEcA5jU7Uj\ 34502# OZZQGl4rA6WP6LIrGMbDCunCxwxVcsMqzMv6x14YkhTxjjtpJyOYD8oXZz2mgynds/VfhrFHQaHcH9NkbwwQeQFonsWR12DcauSEyZSOC1Ad05wm+zinF\ 34503# +tCJ315B2GP40wFeZpH7+olC4M7Ep7jTYuQJQwUcIkvDTSIuPHqkxWNoc89pwgO+EPqfAfkrG8Qsmksr32LvWaFC4Rshc+N0OvB6wvhQ3vcdG3oRmQ7Rf\ 34504# O/XiR9A0s1QgKt8JS8gs3jQkyaYE1JIpM+JEQJXzXBeZtxzftfp8o7gx4Ru9hJ6zthUVGpYdai6gkkLoULguxwRW3YiyFhYgawG7FBIVdIUIfjIEY2WCP\ 34505# sP93A8DfiHsUjsjGBTjTBRKhcFs8oUthInAEqooHG1gcbh739dVzYd6YCDndNM2/O+F/1NNLaxNRFMDxT3TgrBQu9zKruSJNmRicagpOIpO0JDKpbakmC\ 34506# xOIrQXTxKBpUrTGJrHvqpRasK19F+wDrJZCv4BvxBe4905m2kqTxm39LwYuzJzzW8x9+lva720QkUYcZ+/eG5AG4gI8IEm9VxEfSB1xwV48/VBFmpZeO8\ 34507# Rz8UyXD+UhaZCyYK8k6mbIe6VWRF/rrSY/kssDkuiFC+W8dLjhqgAvSuYIkpYyfmSyq761+5RklzkKJlfEGNHS0tKPd9Y/fP4i7Bf9oKGIcef0qm6CdYC\ 34508# EWPEYrl9GdD9vdlHkW3BNbFsfuqMSps7Ac8Ke9YFohCINBRrQiqbm9kDU4UX5NhwUNsFPoDyiH5bTShnlq38DVjcqwI3fwO7CpQrwWm7YwZlJ9mcqwFbK\ 34509# lXFzmxUfzJXBE5Vg7+wq/BMcCw+6y2SW2jkGTIcmjgeL9vTsZDwiJtzXBdFpglOHYCK7G3Rzm3UIPowCbFKmzgFArI2h1mKC1fl+RD45VhUs7oJDgBecJ\ 34510# higqCcaUxoybesYsH94rQY4HJzRC6XSggvxTqGOYWQ0Gr0hDuky+AHYCTBtB7thH1OmCsXouIrMuWKCXS3gYOifj1UBj99nqIaj0VkVySC8PNdTiJaK0x\ 34511# ry6WPAkVmoBVZk59nuu00c6UZfRkZ0tHU6CSozNcAjzwjyeNdNNyLP52ywuE0YTFQBlz6KqfVtDUGC2hy8pNqr1ke3UgrzblcHM/d2TbCMVkrTd8jWKfu\ 34512# HQA0wzDuINZv3Z8EGP9mUkTT/qgTDaLNNUupAgNGKT05UB9P0bi1wrsvpkxnhwXwiBn3Xp7wyIdzbsAO1wLDQrHJCNedQFvbBsHKOoPypEiymtrvMqe7O\ 34513# BMBIo1ujjPocw8tQHcw/Qy1wbKwl2WN4ki25NRDpoR6Ppyc0FgMohgxDOKwKIcPzEw4KZMV74iMdQEgNI1kEWB31GMaoOOeShicMfzduTw0I/W4o6TH39\ 34514# YHdV/nIneutCj45LXfGIwwPe1864WCIxSY2Hq9zhRJCqBzMwEkHl8t+yU+1i/Idgf8D/GdIYIg7mGvUwbQE4X/ADuZb90B3aICbT4SAw63cqve+39IdEu\ 34515# BbCC9wQJtdgfPYfd0hAf5ySIsDJ2XEpRoeDIkgfvSQR54d6GBuBYl1P27qDnrw6BiHjA54JlRQjifm8W/dwQ3u/3p4V1gAOtcsKMrL0fD4p/EgBsfW3eW\ 34516# UEmCHz+YLyPIKcRoNYsAjyScPmc4HAHFPJOZJDzOgAAAAAElFTkSuQmCC"/></a>} 34517#@gui : url = link("Go to the donation page","https://libreart.info/en/projects/gmic") 34518#@gui : sep = separator() 34519#@gui : note = note{"\n<b>G'MIC</b> officially collaborates with <b>LILA</b> (<i>"Libre comme l'Art"</i>), 34520#@gui : a French non-profit organization, which promotes Arts and Artists as well as access to technics and 34521#@gui : knowledge for everyone.\n 34522#@gui : <span color="#EE5500"><b>LILA</b> collects donations to help developing <b>G'MIC</b>."} 34523#@gui : note = note{"<a href="https://libreart.info/en/projects/gmic"><img src="data:image/png;base64,iVBORw0KGgoAAAA\ 34524# NSUhEUgAAAJYAAAAyCAMAAACJUtIoAAABd1BMVEX///8iHCSKb5H+/f7KyMrz8vTw7fGfiaWag6DNwdA5NDu8rMDm4OiOdJWgiqb8/P2hi6fv7+93c3i7\ 34525# ubx/fIAwKzL49/j18/U4Mzr7+/v39ffJvc36+fq0oriUfJvs6O0oIyrb2tzVy9hBPEPy7/Po4+mCf4Pp5evZ0NvHusrDtcbBs8WvnLPu6u/c1d7Ft8iRe\ 34526# JiPdpbj4uOwnrWrmLCmkauempuCfX1hW1s6MzPOw9G5qb23pru1pLpybW1DPT3l3+fi2+Tf2OHe1uDAsMO2pbuyoLaXlJTt7O3TydbQxdO3tbeppqichq\ 34527# JVUFZKREQsJi7v7PDa0t3DwcKjjqmIhIc0LzYkHiby8fLT0dO/vb6olK6WfZxaVVhMR0vYz9vGxca7q7+yr7KtmrI+OD8nISnr5uywnbSsqqyal5uYlZe\ 34528# McpONiYx0b3LY19iqlq+koqWhnqF1cXZpZGhjX2JdWF5RTE4yKysuJycmHh7Pzc6QjZHw7PF1dNCuAAAF40lEQVRYw+2Z+VfaQBDHh26JWKupWpPmABRR\ 34529# LgFRaAuoBUSqKNb7vm21rdr7bv/4zmysUgM+fMY+fuj3h52Z3XnJJ7uzZKPwX1fUvuMq8sE/UsOtq+guGJL9jFspFYyQVYrBbZEcfSI6xx0QI8FGFa06y\ 34530# kM2OktGbkS5yckBSS1GcyJ3IgzUXBlW870atXGOFXCEuW3SMvyuWj4TEQkvrmWH8oww8ums34uOe9C4f8sYdUtzocIcdfc4ee96KnuoAaX1e8DtLMNqYV\ 34531# CbGs+w9HVPiDvOoshtKGrYOby3UqJJsjco2J5jFVMJmTv+IDcGVjFEwCqlxQ9918XyR/WESo7gXM+RldOJbUYpAQAWpwrMHLJyLGVfTmlmrNAENgsCTwv\ 34532# v370eFus73C35DddX0rkVWqh2ttM4Wy00LbMLYjnWXceuc0ExYTVGceoxn9KYp3ARS1d5IEmMKZIq0RVFSVUVHGK6hFLKsYR1rzdSYDQngrtBorsKwkKY\ 34533# LpDY9gacvLb2Na9PPsPKe7ze/bsmLGFhVGjKMyNN7LuI9X6TB8cjTF2IHbnWMwATrqPmUkCEWYcLFSjH6sEyVxp1wKSxoaxRU2NzjK9mdCylGI8YcDYJ1\ 34534# DNBkCmEz/L19hk70+vhRgiNTYhwmvbLcwHr6TMePHrMZJfW40+47KA5RiOh5iALxzS/339whvVvZMaK4BM1Z0HDrcR2HWI41kND9YCVa/YRFpK46gbLGU\ 34535# 270iJhiXLiLS7icCgU1MuxJnt7e3+qYNJAL+rNabCH/jFcqpeY8p7ViHUvnojFZdBi6wnXhg/CsUQ83ieVY9232WwPWsGk2zZU+2nQhn7HpVQrM5jSOVD\ 34536# 7ItodedBcwaZmP4BpES3DemUjLbKascAZp0Vk6ZJ0c1hqN8daWqkZS25I85L3bgTYjWFN2gy9uwTr68jISNs4xxoMph0uYycyrV8Nx+LDw8Mh0Wos5dMp\ 34537# 1hepKlb7CMd6+Zrpob63g4FZgAiRSGNZ+5ATlbcc602nzbZMV7LdroZVi6zG6sXxzfHn2I6w+sEav4Pje2yRsgbqB+slDt+xQ1cn2lfVsfQeqjzxQKZIF\ 34538# UUVDTY89Lp1q7HEaeMnS/mMdkuqhiVGM14AVswFZIyiuVyAnz2VuEJhRrUaa5Vmqet01pZ3qmEpGgVMY9kM2pSmFdG4A9GgzI+2ktVYdIlpuvFKB3on1b\ 34539# CYFhGw9cxpKmH1+FJofFkP/4wKjAoWY9mXcHSK3/iE8sar1ZYi6JTklSjAhqyigCKiVb1W19YeDs4YLGs2IqyLncio0D8avn6Hr2c9YA0s4+DkabBIRd9\ 34540# VD1ivyy+w+gKjY1YJa36RB0UPFdYj/hyewtu+qADuYa4gsxBL38KxD38ikaJuvRLWwyc8GNzFZuf7FuX0lXadGxvug0Jh4ahQyFuJtUp5a2Vzh9q5BGss\ 34541# BMBGPn3/QVhDAF5HEw56+q1dREZv6ecrZ3HXDE0eq44VbARwJ29vPjrFgkL8BrDsdCxtO4/FTYyXWqtjuQWAqSfiVHLFwNLvpW8Aa95GGN3n6qCOvepYh\ 34542# P54EQ6+tSNWIhVI9PvAeqwPtkr6JF6GNfC1vbV184RBX3/DRiwD1mONP6iI1TFwGdbU92Qy+S3ZSosYdmnWYxmfFp1/6QX/1LgM6/HH+fn5vW9riIUg/Y\ 34543# L1WB+psla7yrVDXNOiGSs5OTnZLgP0fKXfE/blxCj5ButL3kcF3sagXArtxZkuE9ZUEvUEV7d9i7/XH36RhvJotx2I6i9ZiTVFSfMXOh9S52sTltRKEtF\ 34544# ZMY7QraKk82Mz9imqhVj88LCkV3p3b4nXf1Uvrd3+SxWxZv7OWRURoJPWsOLR/sWb62KZNFMBy6TndoD3aJfXKv+Z5Gc5VmlWqE1RC7D4tDxQzScw2ovd\ 34545# rAzrVnONOrIAixdRG5jECNe2eq3/+RzfMamb+n+QNw+GFs1J0zJMkd0Bs97RwKuzMNB0FQlAkuxm8cIlRwGoliQzo1cEsxQaUKGO9Rt9fgZfvm2LPQAAA\ 34546# ABJRU5ErkJggg==/></a>"} 34547#@gui : sep = separator() 34548#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/03/13</i>.</small>") 34549fx_support_us : 34550 if $!>0 k[0] fi 34551 gui_print_preview "" 34552 l[] 34553 filename=${-path_tmp}gmic_donations.png 34554 need_update={"Y = date(0); M = date(1); D = date(2); date_current = Y*365 + M*31 + D; 34555 Y = date(0,'"{/$filename}"'); M = date(1,'"{/$filename}"'); 34556 D = date(2,'"{/$filename}"'); date_file = Y*365 + M*31 + D; 34557 date_current - date_file>=15"} 34558 if $need_update i https://gmic.eu/img/donations_latest_months.png o. $filename 34559 else i $filename 34560 fi 34561 0 t. "Latest donations to the G'MIC project:",0,0,24,1,1 rows. 0,120% *. 255 channels. -3,0 34562 rv a y,0.5 drgba 200 frame 4,4,200 frame 2,2,0 to_rgba 34563 onfail rm 34564 endl 34565 if w>w#0" || "h>h#0 rr2d. {-2,[w,h]},0 fi 34566 j.. .,{([w#0,h#0]-[w,h])/2},0,0,0.85 34567 34568#@gui About G'MIC : _none_, _none_ 34569#@gui : note = note{"<center><a href="https://gmic.eu"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAA\ 34570# BXCAMAAACJMYjxAAAAXVBMVEX+/v4cO0s7OU4wPnEiJSju6+qiqrCMlZu3u8BufoHd3+FDY2JRLzljS2bLz9Lp9vrteR34lyZqHE3puI3S7/hbX6GUW4z\ 34571# wza97QiOaYUa6mqTdfz25i22+VxzqoGYqrht5AAAWRklEQVR42uyabZfiKBCFFYUCDDg7TqIh0f//M7duBSEx2p09Z18+7NzTPUYaE/J4qyjI7H7rt/5m\ 34572# nXe/9VtfS+vdb21U7Me/hNbblPzu/6czEs/Y39LmT/jU36C0+7/p/OvXeaf7S3+7bkQ19uN4uVzGG3/i31X0/3GyEFjXnu+991sCMN36dIGu479tLR9Cl\ 34573# +J/ll3PLMBKbJXbipbW+nq9Lgan2U/cl8V/4Tz3r8r+hEKMu/9CDCrDStdLz7RKXDGly+MxTBqZjM4hyJ3GR4Y1/suwOoHVuf8EFmgxK6YFWMyBI0yaGd\ 34574# Two+qPH8PwuDAvLX36fiyw/oFKRcdEHYuS9UtXB4GVSP/9HLw15JwjMtGfzx/jELwyLCjp3fUx/AEBUzlgYI8rh6oItBCGl+/TjH975Rj9p5QI+4gaVug\ 34575# YWPnQxOrvN5an0yFrv9+rE9m3oz7zD5xlxyviEBpHRiV+KqQgHAzoIeLAxAe+nw2tifq88pKn5P3bUTccZqzC69g0nc0f7f4ZY3l3OLQioQUdTsb/eu0W\ 34576# /RSKu8iwsrXuHHWvKsju2Vlgde3774cd2dxRe0s2xjI4psEhtl5ZpvAzdIVVNVgQXDo8jaWJQ9RGCdLtgeZjtAi26BftBqgyrCrg0suqxdvcoEdm1fdgx\ 34577# Uiqo1YOuxdjbasc6DmO1j5haeqgkLxe5e9uxQpid/EdpoYPA5FGxwYi+55WtCzDIlaMku6EgFL7gzJ2Hvbu0BKrsKq07KKfib/K150uOQoZzicVWr0E4a\ 34578# 3XG2AZMhgGw/LzcollzeLzuiu2Wotj0YcmG8sz6aYBMPM+fSl1UECzVyxjcEnFDS2i7HCYw9KnfQukS1Lod2ILzg1oTfTPW/DjBOtebPVKaUZrFFa3DYl\ 34579# WOzLmgKGbikaH0DIr8i+Z/QXVglqiCD6pMxwFAqthWDTjXRWVaqkFLdx1hnUgk3OStTNWh/YV1WmC5cwsN6K+MtZH87QW0wKrAmjOavq3RGJ/vT5uN7sp\ 34580# dz7tbWNtVbCWNFSljmml9POtGjaUt10TkN2TIBVrBeN3azlmxbBYFRY72+QmYxcxiAEKo6JWPjY3FiZBS9YXJ/N67zGxenwOQ2hAJG5k1eLKIuNrs7E2d\ 34581# fB0VQwpMau3MZgzlY+J/bVLPRJeppXsGzerYLquPYSDaILVSjZol7DoUPP66XQCMMkYMBbRnBVEZA35PLVzgr8Lq8vlBRfauLHQYlQbqgYGUFmpEP0MVp\ 34582# QEUBU7NhZ+wwoU+CWHzjryffq+76q1yOxWsgod2swqCCxdqVRYtrDKtFrhJZnNOL+Edf4VnTPGABZ07X9kLqBVA5KboFrV3/uL3jBZW6SJIoql3NJ4lbm\ 34583# wZrEEUBlV6JKoe2b3TpjggxptcBYnLT56F4cyfTzDsM2wGN0rLH+qrNDTiMidOK85fAsra52MLcGphwGskL3FRiVjXbIeBdYGVlKmE3+1eTjB+o/rHNsh\ 34584# BGEWqEsO8wIlFrCwscqH/E9+3zMxwFrFYc2IXeCJMKgShqDxhGLnQVjKKoOLEpEAY2OtYJ396eScezrrDmMB1eUKWktjQUOGdU+bHmboGC2PrQWq0JqPh\ 34585# HUnsEJmRS7q536ssYnZ2YoCjPpeWCEO3eqsRmAFwOLL5jD0cqzmzvJBWO0zK0dRT9eMfFGy690ZnPp0Utlyo0ShFPLjDNYPbuJlRz+D9dFaZ1zK4BuyXg\ 34586# LOU2gxYMvKCN4ZC4KHEHNUawrhZRPpJSx0E3EcpvgahSqwlKgmeD5+gUXzIKQCPQPT7zaUz+HIbtWzlDU2Y2qa8TJz1tiH4/EYZrDub/O7NxzvEM/IJlq\ 34587# pryPKQH4X/eddziCsWAp371531crIK6wGKvNhsfKEBcZ6AwuqsHQ7M5Yj0lv2SO2xCYrw9oLCgac6e22OxwbOyrQefeIW1fRDhTW+OR0dGBOEuGcjTTmK\ 34588# z26snnWrL1m2EVaN8MqFc+2Onh9gsRWbzujF+QhRWKz1ARab3s6NhRT1LSzQcrBWRBRKlXUftQ4Mq6+whhEtoPWjwOr96mwtk5LrE5lqBm0dWHnnQDDGC\ 34589# IMtAThJMpAKKDu/2vjygMRgWRlbiuhUunHiE1TfwNJUWSEOdltgcZzg4o4v2Aus4bo7O0ZzGzIrNHmGtVfuNoO1SvEGrKRWIDsnqWUNaLFIZFkogViRlr\ 34590# oo3yAS1lznNSyo0mpSwr3nE8rdFFisAmuvFrCe6X2/0ViSs1gEa1meC5+wrFNHNYel6XRUh1PqMyvWsIrDYixeKmj9mnK8td5r7JIYsqGbP3mwKvwEK9F\ 34591# 6t+r8AuvYzMVLnuRn/nPcxD6tsMISViuw5KLFWOC5VVodQwhaYLEuu2idc/0cliEub91lmMHq9RtYeTxEbrXXiCmZnCDpQkewUt7Vo9Bx5DQKCmS/WUFV\ 34592# TjXFV6Y6iLPU2lnsCGzRnDIsUihSJ4DOxbwP+oWtOGGJDJ8oULrdp9WOzNZpnIfh1aAeyLDu0GO13rHTOgHI2N5tG5zxHknKskzX5jsIiiFxW2JcTUD0c\ 34593# NleYJHzfxEWth7qTRrZilZvYYFVmQ15NO0hwzKoeeVHz3iti9KcFNlaamRYU6Glr8yKYZUEz0V9onTlakJYyXpnlbR0ttbkbqQDHLYQv1VZoTOWlZg+Xm\ 34594# yEGQIytmr4l0hvhFUVbAW8NlYNQ2EFeja/z3WDMjQRgfjlLatKKx4bsleeDbGl/ED9joUgU2IBliyBuHHIrADrNr6eMeLiUFs8VqWODArFFyhFryGplQF\ 34595# LyQ0GFk9Lm2Dd5rSsnf9VWK1z1mQslWHF4/4QcnpHg6ACj/fOmmDlN2TxPLUfhMZDuNwHNhQzY1x3pgUN8NRkrsdlvafsY766WGlBCqBkp9eua9MISp3t\ 34596# Al7IboA1Lo01W/KkEF5ZlZ1SNa/gLb/l99NwKWZWrC+sVdo1i601INCYDfYXJlbyoJXh8KF4amKFh/1xt6ZFe/7GXtUSMwIopK8YnERNlT2q4iyi+D2s/\ 34597# trfFrCaso8YXmDBS7MELw0Cy4BjzllTnnzCOn/I7/gLDsCq0GIhhXPsZY0XpgUNhdXt8X4DXsdIbYXUGgk6cPI+GpkKwyotGYEl6Yxh+e9h3fopDsfQZC\ 34598# Uz+SEWVqbQqrBYBRbhgOGV/H6usM7vH0aDE5gJLAnEsgU/cAAKKn6Qwz4rAkjeg+8/bJT6aCFjJ0X8IjWRUxDGR+YTLAG5ARaDAi2imuJ1jsJMy5njN7A\ 34599# wOeYwRH6vzvpsrHOOxgLrxt7KsC5PVgKrosLj6C+egmmfgcXImKKhVsbUYnABG7avOZxU0SZYRc7WFB/zTk92lnErWDUuAcsdi7P2Aqsm+PPnyVAOsrPw\ 34600# KJBpAcqAnA5cMjMWWBOqy4b/+BaJKK8mltPinsdaVBYQrLCCpckVAQfkb002FvupxCFZuWZZNNl3sMISFqZGHt9+goUYg/jwa1jnJ6x0Y2sJLZ4KJ00lA\ 34601# 5rQeAeqccsGvJ0/tMRx0SusKWKCc2tY6lj0/IuvK8OQahwaL1GYa1tHQX3tLJKL7iGEIaQ/FfGCaOI00cxR2PR4ajGwYCxgkRfOX9CIRu6QNmwqWzCCch\ 34602# lRZa3Wi55SW/OQD29gcdZvBJYrsIpCSuUYAHRN71tgIWWJDGUoAuxLWKwCK/AUAx4PcdTY31h9P/KxmExQjVHvNsiAi7B6kVnDkoG70wqW54bUHdewssi\ 34603# EfCSzhi2wyLyDFWqCFztzBIqmi+pC6nMYZmkA6dnfNyZ1haRBlN9PpvK7bTLqhdXzKBirX4pSZLa9fOmO/CwWvMIzH0ahlmFYCRFeGixtTdy55mksZ9ew\ 34604# JDPu1T4Xpcc/STe7JSdCIArLCDQ97OCFVZaxtnz/x7RPA2kGknEsj7pGFoT56NPLTyKdbgZLDXYLFhTEakiaHw/kJQix1d71h5ACKQTVTZFHMhhZ4Tdep\ 34605# Cln7QJJB67r/NLt8E1h0Q/W5x5hCRMABKyi3/NAkvYeO0ehfZth1fDdXIO1g1I7AscMic0uYInqOsti67tsI/LHQ7K46PMTyATWdymvhvz8l0+osHdu9S\ 34606# BglTQ1wATXBLJlzf5BWSkskeSsGRbiSURpP8DKq/MSFmp4ySUBlptguZbQNWcFvK6spKDU1eaF1rgLvz4O2tVvKknsYkqQgnCSfF8H4hyimdZkQ3BVXJv\ 34607# IUQxQxbVL+DQABsvj9A9FgBWifAtcDk4kVTU+iUqosNwJVjt1UFjfssFyKDAat5GVoid0WMdUXHCfkoIeTLHs98JLYBmfZ4Q5PXoOq2Mx45DBUht6ZBqV\ 34608# RZZHDuuVi7oQKnwIANCKHELF5s42bCldo5eciaTGLVZjkk+Uh5XNQ9VYiR/l3gfF2Evsd05fDZYh02hLU/OCvFu1HbFYaFnmGWBhCB0Wznd0TKKUcw2nL\ 34609# M/eYTlL8K6haqvi5A3WelF7eQIIUoy+vOkDYSVSVhBgVW3HJa8e9i/k5HcqpyEALLrGL03UQVUja8ubW2E1gQrJv7UG91Umc6mw6hT0yAIm9A4bosANSu\ 34610# WfYEVMS84SWabP7w0X1qi/DVaLr8sOkt9ew+ozawo7t8gCF05liCy4cIK1mWCfIiOWlmNC59BhbQYLL5VV6z+wM3EKtz5cUWkxYjgzyVeLLGwOdSPd3kE\ 34611# zwNqgdLlyyPkNrK+Uzldde3FQfd4eWl/GyHIjLH+CFTKG02BDWUs396RlsKAO61u8H1q2iAeruLHg4lTGpHUAkpyatn2jhNaHsVJdTEc+udCNtPJ5HkMI\ 34612# AsC5nmMyQgsVDJYbYdXeUZaVOnzYLdddqClT9Tz8m374KT5TnvNo2FcDthPAmGMUDxIx3OiruO5xoF1pPc6s/ArL0pDHuF7JidrIbEeW9HFt4KEvSl2H5\ 34613# aacpZ5VWMVXyL15REXg7wUtZ3VWHVZgb7A8lzAMKWFC12zVLjSqDTNYVeHdDsdD94Vd338aKQ/F91GbBlYrrjgHPZ7NlKPSUlgZjzzDciOskFuyao0p2n\ 34614# 84wvLKqsGCihvk8/OisxCcTeXFogGs4GC1/ihXE9cvoVRhsT/puLI5e4WVF1D6hdIC17tRWI+LSAKrP4zB6qGFWu08rBuzubDD+noJCyk+D7g2pogT3ea\ 34615# eF2nsuT8MkbPwaTnL9MGfDwGW6BhLN06X+RDDtgvqSS4ve8ydR1q+yWV7mBFWNx3FZ4ScXGg5C3QGWF8NFhpml+deTWbEFRYiTXhx9quwvxhB0d821LEm\ 34616# 3RlUv632UzpF1nInSXNBknONDQNjNrSyb1nBmAtf2vDJzvkOK0Rnsn67Ynp7hQ9YUGEkrEWW2incOXLoUQ9ABsrpnaL3a4jv5CcnGirIs8GC3UZYZC3hw\ 34617# hVWAKxngVHYyUpN/pnFymqZad21H6qtHxqdJN+If2cVEtbvdSJNHVx2jAx/acRVRH1vZFQpPvlV6bHXfVihcG26yox4+VnNwIdpm1jdg6WbELcIsNQoGL\ 34618# 7pYuAmP8Lq9Sh9OfvQbxR12idYAbC8wbrq1GDd2AX9NyyoxNwAQQZL1wX1jGalRRe0PNsKXoXHabBCREGtxQWwQoWlf3yNLG+KaezU+TewMnG6AevHD4N\ 34619# 1y4arSoq8GaSmzDFiO/PGvDE3XNgVTWmXDFZXjpbHqhxqIbJGpP2noTVLp07f+v7ChpY88NnJ/4SFOcNCibNrws4zTqjWJrSt0ZWdd0wU57tEijFNZZGG\ 34620# EmplKZ6bUUxTp1NwecwqMZalN2CB1ltY9OWmQr/KF9W/UtnDdd/gi6A4jZuJmPqZUIhkKj08qMpqpakWCqzS0mluy6xOCqjCHQMd17D4Hiq7yy9JoI1vg\ 34621# 7/GFYUGtvW5hgEpqWHkwbQWDj2b1mZnhd4pVDu8iP/l0xzM/BoWDpj+tHN2u23DMBSObfBXG32Tvf+r7hxaabu18RJsHXYxAi4tRTSlLyRttU3kc79oS4\ 34622# pTf5GTcPxDc9in0xePTzi09V51n/WxLp8tu2Rm4WAU/DWBM7p8yuTrAevuY/xqv/N2quf5AHakvG2p5W3gp0vKU058nbDu7njiBH5FWIqbOrZRUGrlxJO\ 34623# aqRF+jeEvEFw+xherypvWMuwnj6n56Jry0VLdUks8lTcBWBEBWPfkq5/Uu3WM8LFCe8YCHYal77HaWMYY9gorl6FCtf38mQoQz9cWjOrdmiwfXP2g6CO0\ 34624# XBNohz/BqsBqwno+tBJs1LWwPgWVAClFKyq3wQBxVw1Xc2lYvWRtWKWK3KOqynSX7iEr3wZa2a/vVX1f9CUyq0yvr3ZXKlP3lN21ZuQFSLk7wri7Kt386\ 34625# kajKp6zD5eH08B0kuaean5clM2L/Dqw7sP6cje0fA2HEswwdbFgTInY6rZg1kQj6YwwK8ICBgTOtkXagJQ4foKpDhWGRDhmGhimxYgtgaKHhhVbS/+Vyb\ 34626# axvZpnQIM0JDuq9sseS3fFyhHrgBEuDG2JyHVkhGr/cWBE1cLLaBbVaVr6OmGhvj8fWgbnByzfcR6LeSXiDSx0GX4Dam7eaXhAWSwdhKCip3s7VXV+FnY\ 34627# bhrw+1rGiN2+wQgHJdH1vDlOGYw+sozwMM3jjVYPnMIqFQ5U8d5gU2swJL0DTMcpWqsizW2GzOof1ZdV7YWkyYXF6sSwMBOFvh3va8832LCGsGIypI/yz\ 34628# 5zv8ipcdPWAr0hfjV40wFXXV2qImg6QvrhnwfzIPrHZgRA9stdNT4YihbXSg1UxYHbBMjPNoWFHUNqzH32UV6yOw8GCadyIL11b47z1zsWYxhoq5cYO1O\ 34629# xYyYcXwMQwTTR3s9aExRgHW621p375Vt9i7de+MLKxxM3GsPZXJTHOD2/nsf8BqtTOGZRCnXgBBJqx+5wb0hCVywMrWDMaTeq9kdVqyzp+1dDUhMRBYzY\ 34630# HektEhDJMxXjdyI6phKcaFYXIsUAByjU5N3ybbvWGNyg0Bou9gXRrWBnOk4zbNScEKIh3GhwEjBE4OWOsLLKnlPiwxFMqTu649BIvyMSxG+gFLbXh2gSc\ 34631# e1isbrEBEJ9kReKRAVxss3glLtzDPC2F9iwKrCWv/9g3H9jGstc3txVyUYZTSxjGKHnVRHDOylglr9jWXhqU/Rhbv5XW2h57lnVl4JncqvOgIG13PK47i\ 34632# EVYXWUcx4q3LRJjh9IBly1BlZEV0Gm6DFdyPkm/hcsAivgDxn9Nw1qxCBNzM6YGTCG/UhfMIB5F2SljxAot91CyurGMc9zYNIWfPc6LY7JwG1vlTaSo9K\ 34633# JdZYWywfO4WIFaBRpRoKxbIqMRRQTRcoBpUELTJVedUD2NlpqVYZLuhSejOgfnOPOkpfOY8vRqctNPDSIU+Y/QwtGkWyQ638MT5ruHK7hNakDTgWk8fHF\ 34634# ROzOfnmRJwvAWnO9vo4EvHECi0S3ik144+x/gRWjas5jBYQcrl1pI+B0BvswtN5Y35gPkaKdUeWrKUlrMrcToNBSDQJ+CJEe4ihYHlKY6ghA5OhHXlTMR\ 34635# jPdnrnG8d9sc3vHsfrWbjGsPiw80Jx/F4Z/1Wprkxd0926Tcd7ej+Fa3vhiw455Ia64dPDNyTfp4cGWE5574/bz5T9yFLDz+HYEe9eECk+h9aXzn1feqT\ 34636# halb8huwnzGXXwyVdH9qySJZkPz/XfH/5b/88/IdcfPxH+J0LVIAAAAASUVORK5CYII="/></a></center>"} 34637#@gui : note = note{"<center>is proposed to you by</center>"} 34638#@gui : note = note("<center><a href="https://tschumperle.users.greyc.fr/"><img src="data:image/png;base64,iVBORw0KGgo\ 34639# AAAANSUhEUgAAAEAAAABBCAMAAABW61JJAAADAFBMVEX27vz06viVWEaZZlbz5/Tv3urwxMeFXE2icmuBUT7w4u7QzeKaaFqRVUPs5vWKVEKBRyvr4vKR\ 34640# WEfSj4d/aGWuaVjkqqaca1+ATjnAfHCVWkh7UD/z6Pbv1d6DVUSGUT2TY1ONWUji1ubv0NiHeoaLd3zEgHW8d2qQYFCOX0+LUDri2uvcnpeQen+md3GKY\ 34641# laYYlGXXk3p3u3Z0uTFyN7nr62Aa2uoaFehYE93Tz/tvb7su7yYf4XIhHqgb2WRZVieY1KKXk/u1+Lvys/uwcPPi4KkZ1eiZladXk2ZW0nn2unXxNHpwM\ 34642# XqtrXntLPfr7DhpqKtk5yHdXuEcXSoc2uSbWeeZlaIWUjj3u/uzdPTvsrdu8LHrrmjipKQfYZ2ZWalbF9zYF+TaV6gaVurZ1aCYFakYlF9WEyJW0uDWUm\ 34643# PUz5yTDyETDTd1efSyNrRt8HOtsG8pK7go52IgpTMlJCbhY+rbF2QXEt7U0RiSTxXQjJ1PiLv5/bx4/Hw2+Xfztvmxs6WpMLlvMHNsbvCp7CalqqkjpuR\ 34644# h5iefX+iene3eW23c2VhXGWpbmKLZl2wa1unZFN0U0hrT0U/OzlRPC5aPCsrKyrKzOHCw9nnzdffx9K3u9KvudKnsszAtca+r76tqL2UnLfcqqp6iqiGj\ 34645# KWxmKK5mZ7VnZmbipbZmpLUlo68jY1rdY3JioC7f3eveXGfdG6wdmxpY2yIbGqxc2ZRTVNkUk9LQTt6STGFSjBHOS8qJR4gHhkWFxLd2ey5wNjGvM2Jmr\ 34646# mvobGCka+mnK6Pk6zZpKNpgaJ+g5mtjJB4eo6UgYu4hYHBh3+ZeHl2anBsV1RwSDM9MytmPig7IxPSz+ShsM3lubvetbl4k7TOq7LFoqnSpqd1hKLHnZ9\ 34647# paXmVcm6FaWRMU2F7XVZDRUpeRTZTMBxgMReaqsezrcC8n6mklaKfkaC/l5pbcY+nhoqvhYNMY4Cnfnx3b3xbY3eOc3W1cGFcWGBiVVZbTEliS0O4qbjS\ 34648# oKBQaYhBSFRDMiYCeYKqAAAKU0lEQVRYw42WBVhaaxjH4XDOoUREUhBEBQRFBLu7u2N2TqdzttO56czN3Kauu7u77rq7u7fb3X2/g9db3OeBv/Dg83D+P\ 34649# /7v+d7vPR8OhmE8Jhx4GSLsSuytFYyHceD9l/+fiPFrwD9/0/FjiHEM3tiYMXaZ9vt/+rVULNxfoHE39oH5MTcex8DhYB03EDCmL+z6+NTPVStWLj+xPA\ 34650# oGtH+GGxNAjPPB57/lOPNS/74D+18m7d7d359/3btTCAj/QowVB0LouLGvnbd+8/2Bw7cOHz584Kf9+3+4keSdMAXRvQxE0Amvzb/ss1f7h5tv3Rr5/ff\ 34651# Dzc0/zct/kZ2QMAHWJWgpugu17Mt9Tc0HRppHm0dGR9++bX7blP8y4aMOoc5CG4M/XRkv+/LNyEhzU/lUUVrARKKDQ/GNn35smnVxymKK7sX/V8Hdz74f\ 34652# fjdKLi1tJBBS85KTe32uSH840OSQKTTXTWv8P7yH3+w/cFBOAApzcxvY2ysLYSqz9428zqQY1qrOX/7wI9FI6w8NbRjYa2MWwuTEf/5jQSZiEIBx/rf9x\ 34653# SQMkOof6ubG7sMANS5xl1OqFxkEeO/X/te+JMyv9ncLZbP7zMyYTE6MV/vG9Y8M2m4Pn+c7+HIJav9UcAfC3NhsGzOmkhODCk90P55hgP/4+eusAl9QQV\ 34654# hqqFtDQ2gD20bG5Lh4oojd2exoAxIseOq6hwQAqeAWlLiFjiXgeAajCLKkPhM24BY83UMikQYVRAGZrvEPCy3SAoJRAKD2PKLoByzbmkIicec2jb7//m0\ 34655# yFD6nKLShoXfbhlg0EGntemwA4IPnJBWpeG75zZu3D5LpUAm7kJDWVB6wY3MQJfJUpwGAmbt3qmbtKSb67fDzOGgLsWXbjSx5Nz3SemMojmc+MgBwMufa\ 34656# i8+/HSwOMJo41YOn+S7u2UTBQQuaenvcDMrZ9QYA1vTv/Mo75fU8oHKBwK8vfhaoR6D29fklg7JqPWxACf2k2df2TJw7r7z8puBguE2NN2tu01uLbXVxb\ 34657# cKVj/QCjFf2sJJJvgUOxLKpHqIyD3ez2E7XufNul+/d4rIoavlivN4usJ+VsgPsJEVpY5qInkYrkcU8uvhyIj2sZvXqzJ+r2/QCloEm2EEqJKghuoUF3R\ 34658# SaI4uPjd+yk7tXpryfuXij/k78QOWbDABhBD5EmwRB4SV9yuDVzO1m25gcNIOS5WmtL8LSr/J2qUh5oe4REA2CNCVFQ/FI9BYwEWqCUSEyIUGmD7Bw1sC\ 34659# u2aS8VPdwQACvkqJN94VbGmxC4tEg6xkZCdtgfXvRPg8DhLlH8EEJ797R2HmjVwfY3/nUoNbW1tHrz+lLcFySl0wiFWIl2NraVlTQbOp2MZPDi8yUwRnW\ 34660# 1pkbMvQ++2eqVMmkwtQICAIEMrlizjaO57PC8O+YMWhG0ON4/Z1ot+KiimTkD4EloNF5PAtan9Kz/aI/2ycWRdEn7doK9N7HnVwN1gOgFeg0/lBI7P3Hu\ 34661# 9x8OGhQUHQgzgDdrVUZhdPJPBML3qFDkyLYPkrlFzsIZvEAYA0bkoCxlsRVQ4BQMc3E5BDE3hx/pUAcZlaDZgSO+/VM99OkQjUEKjA1nUQDvczxav80ZQ\ 34662# CUkAGPGVsWdnbM+BuhC5v5woig4YM+VJta0N3BAnrGbfFhuqBjBeDxH9SqZLGANX5i021newJB3Qjx1RpL8sEKdkgs+uDJBiUHHdsHeOcLKYShDfBfBz1\ 34663# dQPoF8FhpbOTz+TSybbgN08WrPY7DcUG1sc0ZJ7+Va4qYQlhrNsebm//PTQAPRjkxjUa3oEUMhShdUM/ouDgvdLr2YHX3aQqB7w4AY348rAvArykAE4Uo\ 34664# IpN5FlCJjdIlGkWjY70QGPPjl1wqEPPdNyEw5ofxxuYtuhuq1k8sJhInepDJZAtoKORce3Bb8APwk1rAUkmBBhriAABsDsPGeGNYdxXsxfIAAJgqwAjuv\ 34665# XWrH7Q/CMJjUUHiBbVG/PC+GCwB3MLAw/8F4BlLan3VmlIsgQfIwKMXXa17sjpa+OdpFLa7QIhwt8EA5uCkyzBnMIBpvL9aIiuXbH3lQNBAjUTR1LkeHg\ 34666# IyT6BW1f0SgyIUBA8DAmy3JiVijpknBYbh6S3TGY7gsA1WogWhWFm1RmV19fT8Np8M8fmNpSKBQHCTTBaQ1bvqXLxiAx0roygYIP00FyrZ5oVMh7VuR0d\ 34667# HnFNr1ASgqhWf5OS4SoeP3qZBfFNLOkYANYgK6+I80csJFKvjkaAKSvoabvicTVgiBoNh55iezsBNAerI6ly3MTExKTf36LE7h2iQKd80TUTmlfMEctBI\ 34668# KPrxDSF1uqMdSEC9IIaKNnkhiB0jMjLdzsrODldVVZXVvTGhW+LqmpSbf+TYHZMKGoSFEIl4ZNO9Sk8UDTrzZrWTFeVuZIvxaVeyRYQsVohgXiuryZOtc\ 34669# Fkd1R9vrM++LGW5uubemH/s2DSTCjCQTC1NIRotXAYGOprRtefqs+qsrI4JCy8Npvn3bj7XBqxO4AWE6zy1rt47J8dbwmK5sjDA+yYmk0ACrcAo8vIK/v\ 34670# QayTc5WUXaqbpy5eoGl/uZ0dZWVKoV1cmJSnXCJdRftgfyTsQA+fNvHQUAWzpkSoNABnaIC4cDxqQvF6iggEtKlm2KRgIXzYCXfeh4nIoJJ5FIpVJ7b3v\ 34671# pdUDInX/k6DsT8FyEsIliCRUx489tAac2LtihRlyuEbeQa8MxpyAIbunZVvMxQE99vSRJai+1T8rPZwHAkTsmh2xtaYBgSYfmMDfXzeYSjLTy8xODUeHu\ 34672# EwgjM6Y7nZxCXagFdHd3f5KTKJV6S3YXu+4ePnLrzjQTW1ADEI3G9pEpr2lP3sCuKA5QyBXQ3hgKskgYebJj5konZ2olrn7FihVnahMT7bt357KuDx89C\ 34673# gAmFSCCRgNBYQ1mLi8xO8FPEUAEe0xhaem/yTqwdfHi89UPOxnOzlSc9/qoyhMf1kq9O7bmsr59M3/fkWKyCbYQ7AECBJWEfDWSJldYitJ4PB65jEgUiS\ 34674# CzGCRwwpTn1acDcZOdnXE52YuWUyvPSj+PWvM1K2ff4a3De1hTsYluI/NtpLtvfk0QK0rp4LwzelsgArtcpOj1QiitWd+cWgkz0gFgbXbb2irqPUm29Um\ 34675# Jq/T7fScubEzCCJPMNs8qtXD3zzMCBWAjoqwMBAgQc7c/80QolMpLH0Y5Uo2PO+POZEedX9e6tKfe+t7axKTrw9Vbq2pZL/wqbIdqvnCg204jgFvvJ5dj\ 34676# Q6ZULh64uiGuLRBBKJEnVlktWMrAOePWfVL19LJwydps6/fWSpKS3kz49Yvll1gklT+bOTuAZzJNQxAPOsjFAQqxQk4gpPadC0LwAECx6oq8t9IRPxnn3\ 34677# fPRWUnWkq51Ue+tkiQmvqr+LP/TrueslO2y7XLgt9wpHhx0cCBiUmBrwAxGhEIEyGrBw+WRduk4+5yEVZL1lavOLHZeJZEmvlp3vn/2qa9zWbOvXCsDgC\ 34678# dfOwz6OWgJZZallnS+j+eitqBABHTjvTWVTlTGH/5VIUZ4CClbAAAAAElFTkSuQmCC" /> David Tschumperlé</a> and 34679#@gui : <a href="https://foureys.users.greyc.fr/"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAM\ 34680# AAACdt4HsAAAC/VBMVEW3xMQAAADUqJoDAwEICALFmozFqIwGBQG1jYA7O0EfICUdHiMPDAoODASth3svLzYFBQQoKS8LCQM1NTwaGx0SDg0bHSEHBgYJ\ 34681# DQTRpZfCmIpuVk4XFxh5XlU3N0C+lIemgnaif3OPcGZ2XFM/P0clJSoXHAoUFQfAloi4kINrVE0QFAgJCAece3BZRj9WQz03LCYODw8UFRjNo5WXdmuEa\ 34682# F6AY1plTkYpKysuJSEYGBwlHhsYFRELEAWotbWxin2ffXEyMzlPPjhMOzVHODMkJi4yJyILCQi0wcGTnp6CZlxPVVVDQ1VxWE9oUUopKzQsLTJDNC8iIy\ 34683# UrIh9nbm6LbWRZWGOGaWBJU15eS0IxMT0gJCkgGhYSEhUUEg8XFguyv7+Ejo7Ep4u7koWphHibeW6ZeG2VdGqJa2JzWlJERE00O0NSQjouMzkhGxkfJgo\ 34684# cFgkQEARBQUk3P0diU0ZBREQxNj4uLzoqMDZAMyoyKSY1PyEQERMcIQ8LCwwiGwgYEgYSDwSturqfqqrKoJOvlX2UfmpXW1tJSVFHR1BIT087O0hhTEVZ\ 34685# S0UiHxsoIA8nMA6wvLyMlpZ+iIh9YVhPT1hFT1h7aVc6QUlHR0c3OEVdRz86PDwxMzMpJyQnIR4qLxoeGBMcHAocIwjHnZDCpYpubXpvdnZvcnJkZG9XV\ 34686# myTc2leXWhWVWBOTk5LS0srKzA/Ni47LyovNRofIBQkKxEQGwq8oIVcYmJcXl5RUVtWV1dMS1VHPzgrKRSXoqJhY3iljHVbWnGbhG5naWVQW2WIc2BNTW\ 34687# BTUl0+P0xFSkk4OTZ6hIR4gYFze3ungHFQUGVjYmGDb1xoXlVdWVA+SFBAQFA9QEE4MjIuLy80Lyo5LRmFhJG6k4d1dIC0mX9vbm5UU2eNd2NJSVtGSi0\ 34688# 4RBYyPRQ6LQ+lsbGapaWAf4tsb4Z5eIVYY299aWlDSlN0Y1JvX09RSEBMQz5CPz4/SxinrKyVmZmNjIufeWF2Z12ObFYuJgeXgXY+PimhEuIiAAAMWklE\ 34689# QVRYw7yTX2hSURzHPZ57UeIqcvE2/IdOiZz5Z+OqUxRnc/iXDUrHGJhOlpuDMIN8mA+p0xJGU2a9jDlXIRgEjUYPG6PtZU+tFVHQ/hD0EKxeeqgoiIqu+\ 34690# 1Mrrce+cO49f+75nO/5/X6X9h808O/lMcvfVjKumjIZT3HsX4C3RRrN2eDYR7enNrjE1tbHucTG4rXJ0F995KouZ7XOxcraxw/laDlh8psD0Y1o28yZ23\ 34691# 8DHPGUxkJ/enT52ogNP4SEFygJwDFjDliyvMk0BAjX45bxT79fovgxYOZgsw6oNI4qIXaTg2EQlnIrDQEGD3fhczF0eOrN3GmHIOJ1MxX6qLHrqk5hw0x\ 34692# +AGYsjQHjuaXqo98cWB4qFWQky6PzeJJmhUqalbrJl60AxC2NAa9y48Xf9zsUZ3t5Ffq+Xko7SOrZa1YWnZb6hHnGF0vVMdehMPowQUXWjUoPALzs3ksV\ 34693# zQ08ri+J0NTdBd9YaPUnemWzhxSPnqWTJP0PWVcbVdTjtuq4J+OJHxTKpIGI8BQROr1Zsntuyy9Atmu1AeDFyczk5NuFjPMAIGwdtSp0tQjubrpDQX5aW\ 34694# GtQCty7S5MZn8+zvnIAGNX0yw8Zp8K3F4MKKdM8qg/i2sy19Zm7S4uPB/YBs9PRTt5hAG8vGJUIaRVw6zP5HBoMU9y5tYMYWPJGwka2qLL0OvE7JVt/An\ 34695# y055e4r0qbc679n9DlafLrjFKyIiLrAD32ygMK4Mw497+lkl+irT4vx59Oeaq1SeeAL795U0u6+3gkX7Vr//BltApFIrRwO3Qst1CdHHAVPZeowqCVVg2\ 34696# LL3IzPgpgcVXj5bI3q4tIVa1aZm1PM/uwhYr6jA84hADi5pnNo7OngXDFQ1szTJWE3IcLb9/QckueYlnozarYIjMw6/v6OujkvgPenb5aZkYuxQN5IlbY\ 34697# 3i4AvMAAwOygGcvxMnZm3VdcsVwz5F5wgDc7JOoSCLqvtzq8CrK3km05Zzun9tpPySlAk8GfD2zfYuDpGJ5kJHGHktYUJHAEaVMKuaeFTW2Y0pEYmieIU\ 34698# 10Jqa5HOMJDeb3XE8b3l7/NG9UUgPPgCwZYOzvpFJLGWTuxJItmBgDHY0kGUH6/ceOGn0jkmzp7ulVqAnb15LF+Se+dL1cmavpgktBHsGf3TIBRSMfArW\ 34699# QhCWMpQLOD4wAGWRAoX7++HyBknd3XO1qmNRrO1jNp74h/3mS6N/EuqmwavWgy2bTGAHSkYoVYGsdBOgVvAkCj2p5uvl7ehq3t04RdEtaEZecmnmkiNuZ\ 34700# gpJ1te/dudjpiPyuax6IExmDFGAA5j4DkDmRRAFATQvXMy4UglMkEmLq7Y1DhZrL1IzKvGB02Dl2fmNA163SivmbbVZGdEWQdh6kLt1iprxCnABACKh0Q\ 34701# AYXtWAz49e6AWn1V6pZq+eI+tUksVykEeiYTbRmShZvl7m6RLQU5QQAhA0my0pACpBCIBzngAtgV8eRJoF9uVQgEonBYpjGKmV2Doqtn+WK2VNRuZfcLh\ 34702# qNgXwiCfK1dgWrgxv0TjAPAtEOAarUoKrcyVWa7uOWcTDrUYu206SUSvs6mkAEIaoLwAkgjNQdBanSLFYMIYw9wyjSI8vkoynSjEuMwija3C6xsvlgsR9\ 34703# lhk1qur3llMBgsiOMQT1OAPLXt/vJyAUGOU732jlOz4kE+WhM/3MMcVqHtw2zm7jgik/Uz7YASC+5eASJpqpB+sFQ2IUqEYRyfl/eVmUCHYSt8UQcdrRl\ 34704# nRx0NP1piUFxxwVAwMxEqCb8SpMGFDrUNdSk6SAjZIaIvpSA2otbVW12KDtWlCIqIiKg9dIqgQ3TpHet3GIYXnv888/z/zwyacWCzVjtrQ9BKzwVkVZ4X\ 34705# MJl00O22MGrdMof1tDKCFdA2MAfSEk0UKKQhSYREdcFKhO2F4tFK/FrU7Y67k8XlYpzpX+P9Fj/pJzbstDZaVrKKCIDeAqDRuYWRDVCTrW+DgaTBmlSDg\ 34706# KzYzrzP39m3L1zOlxL5kvVEqcwKbJ6xMMEU0+onreTRBJpkyNbrIShRmqSL+tYWtiFAqEn2ht/h57vHPdalnSuZdNpZDW2UU4V4pxLzt6os6YDkEAEagg\ 34707# Uk2UCPAhCLhoIh+I+d9fvqFn89tJLrqDmejzqj+bjcXWowwXTscBb2SCmBXMjUEXFBGejKE2KANUCOFmjI5YjhQsoZVePxYW69HE9Z8jud6rrF4k62AxD\ 34708# UaKDR/6YooXM0oNBYMaSRSHMcGQ+EHLgZDVa8+X5TCPed/VKp0FrMqnJIIInwdlEPmOGh//tAxggoHSARYGIE0nVNH+NZoOBsMJmkW24W98VzsWFiI1Rg\ 34709# TIE6exhIpl+kXsEaNCXMV9BmmjLDioY1DWJzkmHWwWQc3mjQE1oOrKSvNRx1byxJglDeCfB870ww/ndHYaRhPJvNtKORCJ4ZSFRE35BJy6lKxuNgvd6kz\ 34710# DgYdZElM8gAhMF/FwDqQWhDCFEAcBo5VeDJy69cylQUp8al4w5vnlUTxfbGkA8XCkIydpptNBJ28A+MTZ3BVP9FIkTdIkwVZQIjr465ADD1Nh+32KjcZs\ 34711# LZ5cCyM7GeYCu8pameDq9IY4I+GG8NpoNfv6a6CEVqjfB1bbImGq4XR0j9Gdeex4+dAsmCp+KRfesCry42u4ybf37h/JufNzYREgfit2+SJo7GYm+MKQN\ 34712# CaEynhkE+ChC+2//g84Mdp085vUmhWiqwQaERdft9xTr/5cfShQ+rn+6u7lrdZud0BU0MGkqiQhlmCxOMUGTTRf57By+/DB3OJoqynBTasQRbDfssjlCx\ 34713# 8+VOeOnp+107rnzfdv/jvUNXIpGjoydPJkQAcByHJ2uTva+fXd2z48Dlt7//3M5mni+m2zmmwjc8cpPxpLtf7twJP6puX3149+HFQ9/v7vr+8eO967vRa\ 34714# C7wt6ayCW0aDsN4RCzm/xfTP4kpaA0eEhDxq0Fwxh2MGi8GEouWmFjBXoTUeGhr20npraVd1Yu0q1URD461tm47FWuFtqNrK6hzuokgzrGjil/gB17MBH\ 34715# /393ne530Or8uVvPHg0cQlsRi31HNXn/8Z3nS6PnN0+v7mzee3bVy36/zhx7MBR/3xi4M1b7nJ8SaLr0KW3+WzZ+3XduP9i0cTLx5xghGlw+jck9/7nWv\ 34716# uphztO8Ondq3fuP3QvgPDtn878msikc28/fguDzPVqm+8AbkpUP2IY7ceTg6h1wzo1xi6q8UvPdty89iZg18DgZnIhU0njl05Ox2Zvee4F7n9EOpUtWaa\ 34717# RSZcZHNsbnm5NRhkxrHjbpgh+zhrIXf8U7AIT04c2ToyMhZwBJaW0mPz6XTKYZN6+fMNIng2iVpdujColJTeoqCaZCOEsURTzTA0Ho2rYAHQweT1oZGRv\ 34718# XvvOQLz7bELewKOf/PTvyY5hrGPqHygmVxFknOyXFSrPuYjNi4KUBV8FKHQyHDdjtOj1717926YrQcCS/PtmVWBQGp68pIR7FUk2I9+HsC5FkBRXQZ4iD\ 34719# HLWI0RcC8xjnhe6vqHRqkSGL3+fWRDZEfd8Z/Uq8kbKEfKHbgTfYrmvKUWSBpSh1Y1/F0ZIxmzLzTIMmuAIE0kaDgHnpz7dvd0atV76XSkbuf/8cA1V4J\ 34720# zDFqrFTslmJPXUD2dgTWg9msYp2bjkunJQpcnGPYwxJSuJ0afnrw2vbpBfWa2PT8TGeL1SrArkoSzEPsAPSvyWkCQeeQjCZLF8q6MXQNu22tEMpGFMQU0\ 34721# p+DDB7vbY6tEvqYj1NTKSicXRAS91hYQhF6MJgS/iji7liZGSXiIoqNRCLUoT3hdJGMgnFtz8UL6y90NZ76mD1/DG6GerNe8Ccbr0oTlxVIlyQJfk8jbv\ 34722# fqqmCto1TjNWIiDoEYRIuFnOUjGPUn/cGQs/eXOxZ1ixvtZIX0myWQF65PSEphlvMHhoawPiawdwSTDMLxgRAsgXOAJXZY4WpQVxIeAy3V5WJEInGM/A1\ 34723# +ZdJMiwAuxFX+PMxEtIicNRESSGBJBtBi3V0gYQYHhdcMUqVJUkaBVXLCCMUlnGI4uNTiax1XCFlAkmcapAZ53rnGzXreFAcPSDAXGw0OEpWYggfwxmZc\ 34724# lq4AoIRyWlQrQKyLbcIfjRYvktDBoDZrqYg6nPHzflzU5DAF/AqeUboxPJCQ9V4LOWMW/KFmwKcbU7KKkzHWE/DjhmSpoCcLZ1fQO7uMId1VI+rM4zXr/\ 34725# AnoH9FcRhS6kAAAAAElFTkSuQmCC" /> Sébastien Fourey</a></center>") 34726#@gui : url = link{"( IMAGE Team / GREYC Laboratory - CNRS UMR 6072 )","https://www.greyc.fr/?page_id=443&lang=en"} 34727#@gui : note = note{"\n 34728#@gui : This plug-in is based on our open-source libraries <b>G'MIC</b> and 34729#@gui : <b>CImg</b> (C++ Template Image Processing Library), 34730#@gui : available at:"} 34731#@gui : note = note(<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA/CAMAAABnwz74AAAC/VBMVEUCA\ 34732# wMBAQEDBgcPExQIDQ4KFBcGCwwQGRsPISjxhycoS1YZNT7rgCEkP0g2PTiOVzXidSJ4OxgXGBg3XGkTLDQbEw4eHRxCa3gyGw0aHB/uchSHPxlYVlNwNx\ 34733# kdHRtNKhNNeYgvMT8XEAnvn2vhjkjQfUi2hGWMZEo1SkzXbiQjISAmIiAcGRlnjZoTExM/IArWw7TnhWfti0igTjYmJzKlVizpcyeoqqOoRhfIZR8jIiB\ 34734# mMxQqJyqFpa9VLxhhhI8mIyno3cC8vJqJiHvkqGzujWbukle5e1CBRyyEn6I7XGN/RSJBPj0iICFnOR1aY2SgVBl5nKciIyFEJhRcLg7DvK7nqH3vr22l\ 34735# Z0qsY0TeZT1kOSerSyKTRiHg3NeESSd5VT6PsLuLr7tGRESFiIN0OBM+TlwyGgwODQ1XMhM6QVprSDzSdjloj5suMy6lfWE6VVxxSC2QPROUcFePbVSJj\ 34736# ojTx720zdXDazPGurA2U12bgnFybWhjW1YkISAnJCNFM1Tzdx32exgyNzMhHx75liH7nyH4jiFMM1UtMi/5kiDpfS/ZrowrKSf0ih/2za9JRkX8pB+aXj\ 34737# 9EQD8rLirteR3ncxz68Obz1sD1wZjUo4DBjWlRNVg6K0D6mSP3hRxsNxe/URb56t7muprtvZjhr4lqa2gyLy70jinwgx/1gBvpx6/uxKbzyKXztITcqYB\ 34738# KcH1mT3hmRGpgOVxOM0w+NzV5QiTuciCmUB/8qhzfZhbVWRP65NPgwp3btJn4yYrOoILBkXL7yW7QjmxaNlZOTEpBLknxjDkvKDLQZSDgbR59ao11XYT3\ 34739# xH14dXNycG/Wm25RP2fCiGCKblw7V1yhdlVtXVJEMVBTUE+daky5ckkyQkFVRz/5oC3CWiKwyL2Rsbn0xai+o47714byp31kYmGvfl1fXV36uVrmmFR2W\ 34740# kayYzSXSCJJMSG1ThfW5+PE1tL72pPmvopxWH9WS3adg3FYT1v7s00+OUX7rDJkj5mrlYVSaG9uaWbbdTHVCtkHAAAAfnRSTlMDAQkhFRoPLij+Vj7+Sf\ 34741# 7+/v53aTRHm3pkXf79/LSsqIh4PP7+/v38+/v5zb2ahk7+/v7+/v7+/Pz38uXBr56QU/7+/v7+/v7+/f368N3Yx7enkYtw/v7+/v7+/vzp5uPMu7u3sJu\ 34742# XcGZd/v7+9uzo5OLg39zb2NXUy62ggmXEYn5YAAAF/0lEQVRIx+2UVVAbURSGl92NJ00guBeKFau7u7u7u7tmG0KSxiGQYC0ORQu0RVociksp7nV39053\ 34743# aR+g02VgOn3r95DcmTvny7n/PTfAf/7zbyD9TTGBCOhM2Yy7DRqYzRo+H8CH6MgGR0k1df64qQHo782WZkiZ+rh+MpFKA9aEKIdbAL+ALJy3OkO/ts2Sf\ 34744# KVhobFSM9z+R5OpbGh/jF+gJvYj8II5Q9VqdXExy27OAggAZ2kqrf3CfGIzRgF4wATztbQD3tKkQM350Ea6XC6WC/n+4kh1pJw1Z5RRUlIgM85HkY13BM\ 34745# YGCCQxYBNvaUOgptFQuUql4kZFBbhwVfJIVqSqOEUzMFDpo1AwYZwEBr/YgH3rp1cqNTVb5WKBQBCACoQCd4HAn66KSkYNfgrFfTOcesLsly+x+Im77xs\ 34746# ZPQ8Q+IsDAtwvowjkqki5MEDlkpzCjFFkDyfgjA9bb+qLg1h3OtZ+KZGClk/u7kJ3d1QhEPP5LREBUVyu+mlNw3ASzgRQR46cPfXmJhAzrC7yb8m5k/OJ\ 34747# zxegCjn/Q1lmWYELl8ttnW4G480AzXw0dc/NnW1+Z7r/w1ev7uS0qNAc+OoPdzIzM8uiuC4uV1ai44QDpE0jGFR/1cXWJmL/nNc1NWUP6f4Cf35kTpxNV\ 34748# VhmASooHuLc2TsggQ4ebhaoK0gc8aj2tsfjh3Q+Cn2CTWKhR5gE6+C5CYAPw5FMktXbA8CCVD6fOXbwgEIrihiFMrnPgAEftw/CBEErYHwBRIUB3cR6LQ\ 34749# 2TVDG/l9cNXiETFQiFFN+FogHbqpJRQWrQE338p0rEhnlY3gzCviAhJhg/3iZCiEKRjguPj49D6w1TgxpxzwAxqNir23LOWNcoiCWMSB87bnAlJpBTKtD\ 34750# lwsVY/ZWg3NUA3hzMHcnAhsB+fJ+MoXZ01uL0dKkVvd+kXgWSXq9j00MfqQ1TDQ2HxE0n4hi09cy1sX+NE17BaZPpdIrdI0s7yd1bdy0nFrB2TJhgVaS+\ 34751# 4mIY9MR3Fu4l0kgwAGsTDwV7eXk/oURESFgsy74TJ/bNDe1lV1Sk5nLRS0yR2mzGSRAmUEkQzJ5LW+WFCu4PlFAoFMn5RX3Rep8KFhelKOXp0rgaM9xJZ\ 34752# juyCSBDj3w0ODgtuoo5cJBEIjnvc36RT6xPxaDk5ORBQxt9s5jzAdwERq5ypMIgDJwMDg7uk+jn12jVzzLU13p5Q25W2PlJkyzjQrJsRpHwh0DbfK0eBG\ 34753# AcV4TWNjdnh8TExipirPv375+lUNyKkVqv0cfyxxeQ9cjkn+utR6Y3Nw9sbfTLkoaEWC3zjQnLbphiAmn8BNcAQG2fbcD28yDnjSsHKpV+vrm+S5ICjYY\ 34754# MQQWdGjAIZAYBe++gjpPpzN4cjmz5EqVSyZyStGKZpPjZMHtTLQugUwXZfK42oGFh2qO6iSfyRDgc16rKyUv7P22V9OsnecZBPEW8XbokPAGBBjPWHWYT\ 34755# 502znTY1vkmEIKjhS0hFZcYt9DYLUAEHEfF4PXpo/dkAstcxyFQ9Glx9Mz7+xmdbHtYBp09oWIi3d1pa2t3vCCJrq+cNwxEwHGkgDAEaWtOabOOrm3qg8\ 34756# HjGtY9vR0dHe3tHP0Y8eSgiz2EGOGcACSCRTUNDgpxsRSJbT5FIhAXhmvjuXUb07VqOTOQpQzgznQidhAiPpgKogTzaoOexmTJXV1eOazuQwhEGELYP4E\ 34757# ME23qByNrmPS9cuHj10qX8s23k558+c/1tT6DLgNCYhISECxcvXj1z+hTGaRwBPmPelJaihvaChG4JDEpLSt78JtjUHYHW+5KS0vaC03Uf13dHYJr34MH\ 34758# 7Syh1dXX5aJSFCEdmDHa9Hp5hHH7P7RzCaQfiNqYbJ3C7dy0cE7Tn3PpuNJAXfi3c4zeBLK/LLeh6GF8rf+Dh2VGA8GaDXbxDD/QE5fWJMk5HZG5dHIUR\ 34759# HvXh5d/ceMhvAuTcvC7Va5BGuIWXG2MRdKS3E9g1gQagMyLPLVGGdCzXhYBuAGk59G5fba9FALoL0WKLk6mDg4OprpYOEfgPPj8AH7GtomieWx8AAAAAS\ 34760# UVORK5CYII=" /> <a href="https://gmic.eu/">https://gmic.eu</a> and 34761#@gui : <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA/CAMAAABnwz74AAADAFBMVEUAAAD8+/v77u/9+/v8/Pz47\ 34762# vT25Of04+aYbXL03eD+/fzx2tz89/v99/n98PHDn6ns4OnQtLqshov88PP/8/T51NT46evz4evguLmlYWn56PDgwMK7govXp6u0YG/CjZWUd5Dt1tqTXG\ 34763# WIWWLx0eLl0NrAcnnIeYDw4Onlxtf54e3z1+Xs0d/rzNvz5+704ev33ejt2ePdv87vt7ngqqyoconZpqSoUlpwPFndxdHgsbTGorHDm6zMg4XBbHPPaGq\ 34764# jOUW0NUTxzN/jv9PSl7PMj46zYWmfTFv+/P7YvcjuwMLOsLzmvrq1i5/WjZe3Z22oRk6UQk359vf77/TuutbkuM/brsPQqLrXuLXMpbXrrbCxbYi3cHaq\ 34765# WGOEQ2LDT1e8RU+YLDykLDqPHDD17/Lgs8nWqr70oKi+kqa0gpnKf43AdoWVXnvMc3qSU3DEYWTNXGKSQ1WbSVScP0uAJDj66fLrxt3sxNfw2dbqvtPdu\ 34766# svfxcPWoLnKkqq+i57hhZHTfYSpZoK8enqsbnauXGv66ez93N7qzNbrycjJkZ6xeJLTiZHDiIm/gYSxeICjYXudWHfCYG+OUGl6QmB/N1a5T1WvQVCsMj\ 34767# 9eHzz0x9/wwNr8zc/VtMPhnaPsmqHYlKHVnp27mZy9fJKYYoSld3yLWXmET3GEXGyZVFqGOU+PNki8g5zkkpvRlJiihI7Xh4yLaHqYb3nbbnFlMU2pP0l\ 34768# xLUn44t7rttDKhpXhkZCaeoavZXSjZ22AS2iXX2ezU2GPTlq7HjH61unt1M/irMuMcoGfWm+bT2mlUWa5WF3psc7/q7fXm6yrfIuzhInfe4Sjb4LafHb9\ 34769# 8vrm0MvgpMPBiafLn5+ieZW/kZGXcYueZoeQZG2OQ2OiXWKJRFR8Lz+cIjH5zuXhtNP9t7zSnqWUf46kaY17OkX91dj+xMGsjZTth5GFOT5RFjGGEybjx\ 34770# sz7wMjks8H5r7HMrarJgqHjoJhvDinu4NrWjn7NgXOhO12uTFzKaYJvHzpyRElCABtwx6DiAAAAJHRSTlMA/pTZ66c8G5RtyJC8rw7PnpSQfSTMUfTllM\ 34771# /Ev6+U7Ojg3lN8FIp+AAANFUlEQVRIx5SUaYhSURzFm4pWKlopiqB4+hz35ZW4jFuluTsjjUuZa2pOpqVONlZO5VYThZFKuLRQUUMRyCRtYBZUUmBT0AI\ 34772# tQn0oilbaC7pWEEHrvV/el/fjnPP/nztgfhsRQ8KSiCRiwKYePGjU+ElDB/zXaWqyETEYEgaLJRIDAaLNZmtrGzV8yL9TmuY3qUlkFANFDpBI0WhUrY6+\ 34773# DV4LnQtOHD5h6L8CsAQGSyyOM3BkHCkQjZbOyZDd8+btZiLPJw4fOvrvgKsBfBebynqWo1IZDBQeFUzI9CdOvHe7e32tBzfuZk4cPvqPGcy/GsB1saXSu\ 34774# JjKQDGaUahn2tmv373r7+da6vxMqsoRoo/MZk4c+RtDg9vagIK4VEqNSxlUMZCASsgA4H0/l5vJ8DN8L9dT4xYKwkUb5s2ePHLCLwA2GwlHwOGwZBQFJQ\ 34775# YaxN8BHq4lw+ebvEWvscjl1rj9bg6cP/Jg8tThE34GXFWTCRCOTMZRMJgoMUokBSXI6/fcfi/XwjfxTUVwU7Uat1blcAo1hwJ9Z7fk2Ywx44f8UIAld86\ 34776# R5iAsNkAkkjCkaCyrf30COChmgAdjQ8FjT/fjWjfncPhxOBx2oyWlEFusDs2cNm4IADTWoNPudOp0bDEZhcJSsDEJonjXX+QWLXxwvF6jN9XvDnMO5/NK\ 34777# pbs7XDs8O1R6FlNLOpLhg8MGDJ5vowjmtMvtTl2XLicVU6Xirk1bWtwej7cByFhMIIKiJ4k+qqfRnm84fCn5mE47F4xKEzHFY751CgA0BQhdGjkbAFgEq\ 34778# pQq7tKs27qIrkoZjfV6I0RwTSn3iRZEwpQ87KGXU+H7D2OhZ4novEzFAgBt8wNQczOLpdGwdAxxjioW6zZtRQtTRpPRWgcCjOAjk3KvhPOIJMt83uFL1+\ 34779# 4jDyQS3cNsvWKZDjJoImJw+LNnsTiIQkGh8GJqbh0AqFIpk9ViMaWNANHnKbsPL5qt1Say2TvJpGNDXu/qyDoqlToAgDpT8DgIwoJJYkkULBYbZx5xcar\ 34780# VlNds5qV5fV6eiefhhIV3dstC50pBJp3j0AsdPc8vWSoNC4NAnYnYs805AoQnYzBqUgPw4Djs8XC5X/9PeXjpZBKNRu+SyELBUCmWF74s+OFHDiu/UvGP\ 34781# HDCozRbFE3LyWXa2XNecyzFY1FUvNvXASo+nmE4DAM9hNnpVwpY8IpMltKVSKbbxudLfq79kqlTMtIEAACycXdW+dA1b49SwWFKpxr53I5qu6uNxLWZeX\ 34782# 5/qcR9QAPeAemuvnwuGrgUfKI7eo8Xo9UolnAWApiY1WbC6/coap12+wM6ya+z2y4tgukpVNVqt5ow53e3pU3E2tMxDZt+UyWSht+C12CjLxgpWS12vBQ\ 34783# AbhoKDBAvk7Ro5a06OlWPp2h9shQ1gEbwWqyVj4Z3wqHxHWza0HDmyezYTSVy7ppU8TJQeRqxWh+QcyICIAVNEQZ0QhIdwBDw+3ryaedylLFf7uDyruW5\ 34784# WHe2mG2B40aKefB7Zpadd1wIXz2JZvzXtkES/KYDwBAIoJJglmQxqHX9xWdHidnP7eT4QAd3RQleiOUL46CmXS7HrCMIMXgvGafetfEf+YfxriBSwiasW\ 34785# CATNAogAEORVLy73wG530cNT+T76Vr58Xz0BRzifPn24ePHQva3MxLVgjIl+DABbJHFgYf5VEkSw3zrgdN6yy+Xs9j063daNLoMqBSyYfb1ldMtr+lEDP\ 34786# enzv+ldETn9PBE6Jzvd4Xj6NFM4gkgHAsB8NRlaNXd5+5qlc+V2uY5tX7vpVKRVxUtVn75pvWeAnxTovarkB/+HD2/8EdorbQg5H770lP/0koJ2Mza2AQ\ 34787# hQCF26ZWvsm9cs1TjbWRrnplMdIrq5Wu31X1xpQCtfCn2f/G8+fOr1H9rFZO5JZA+G39SemmFaNqH9qiCKau7S7LfrbrCdJ9k5to51ZaNLtNLn8/haRfc\ 34788# MPSsLSrT/jf/zvQuHjh+fvU8meSQqm3lW/0s9DQkNHDCiqY2EwxM6d67u7OyEGq8jBEJUuNAwp1vUGllhUHYbOi7cu33o0IUzrl278gjt0f1I2ZyuXtIj\ 34789# 93ftGdkAEPGEuEAggCBCM+jk2bNzXjxQuODublgkuigyRJStC2/vWHzhwpmN+gJaqXikv6/ipY28S3n9S/SDsQCgjuLjccGSnau7Vgk6VwkIAqDgOAxGD\ 34790# 9NFEZGho+PgofXHlm87cxc53PqkzDnhKFvNaevTw4oejgH5CiDh57Q7t69bN2udRi7XyZ1rNp8/taK17BP6ey9+6bzcQ5OKozgewaKo6AUVPSgoXfaedu\ 34791# 1WGpHXrefKUltdE6KsTBO02rLUpkY15yuVUHv6dtlMEXM5Nam9sJRRura5LVa01Wj/1KA/osdPiCDoQX25f104n3M4v985v3OEL+wmsylsNptfsI6sP1l\ 34792# 2bjWZfHnDgQcHPt24cbe3vhDBrt2LllH2qAw+lQxCfFzpUdlRe0uj6MSnnQ9OioTCPrYpDL7P4bo72PXV1Xewd28cP/jg8qcbd4rJVOKlQhLBRbLSJeyc\ 34793# KteOSLmIzCepSbQIaZevXD5JE8pNsBEOGcPhOl4pDXvnRvWO44/PndhZLTqCvU5ddeEeAGwCr7uYI40jkIvLJG1fx+VyZO1Koaj003FaUmcwup8DAD+Uv\ 34794# EnbX333/v0d6x/f9dbVJ2sJ+251fPg4HgAOYXAUirjK+vBhVWWVpb/fwmRKGzQ8HqgeHjcYaO6Co56gJx3zsooBgFX8+Hoi1qElrFq7dtvp06NHTQC1AB\ 34795# 71h2cebsQt3Gixbux/WMUh1dgzGo1aq00Hml+/bg4EAtGhoFOrBlOHun5fR8Zms21ZW1FxoQJEMGF5oStTzjDFnL0cDukwh7SOeTQtcwJlnEE/sPe/9vv\ 34796# 9tuiQf8hm6yASCQTb0Afb1rMVFR8enf4IIlhUgqEwSXx+OwRBKgjazk3L0u3pYDDvzAQBoLkQQrM/Gh2K+jOdnWrqrY50dN2QreLsow/3nm0GgJI1eA5T\ 34797# KlDp5XYdxIW4XK5M1p4J5vNarTMf9bwONDd7SEFPwB90ao6do1LrO50AXbPtQoXt3rNHAHBo+eJKSc7gE0A+HZRu50KQ1KfTJhKxmFprb3c97wp0RbcHA\ 34798# kP+fIxXfY5892bCmcgr6+s7nJltbyqmjpqwa/eSqqac0QipDEfXbV8n3rOHIZE22Btqy8sbUb4j8BxonScYzeeTCWwx9g5rUBvLJM8r1J2dV7d4CoBTJR\ 34799# QGI5Wiiy1Vy0BPAx36MCJrsJcfq21EHS5Xt+P5c09B7eB2rS5dT1YMJnvPHyvX9N4i9MbGjpq4e8XCjRRGhG6JWMXi/v6N/RZ6BHlyE+WVFreajHA8Hne\ 34800# 5XSEY9kAtwv2rsaW1VEJisJdXo1YSropYU0dNLMHgGJamVDabQp48gVTS7m7IwG6pqytrEwnDRiMMO9wudwiADJ+FIixZoSYStwwm9l3tUL+NiWrHjipa\ 34801# tNTSn0XYbD1qQuWoQSVHdXp9S2udsIzWZmYbBaEQ7BowwiDFfWU77lA16lvEbQkl4RLx7Vsv9nwBsFCczY6YULbdgOpQvRyVy3UCua6v9XYbb3gAdoMQu\ 34802# nNcd7evRVSGPULWqNW31mqUhLWxV69oJwBg4tNTliwyYrL3SA2o3MFX8XU+Pl9q1zXwykf0Pr6D73IP5LrdcYNQVFZaW8sqDJzEmFJDxr5/t5oFAIdWVk\ 34803# YkqDksRxy5FJ0eSUXodElO+qQBdED9gANyGd3xeAg2ht+JRPt3lO8AI+stgtf7glb97t3+5FQAWNJPjzQ1NUWs1hTdQgfnEYk0IYj0ZtuxRrPAPGwOhcx\ 34804# G2BwO006sXs9i7fD2Ulft03jf9ZG9ClpjIQcYPIPBsVotVrqVHrHSU1kJJLC3DJbdvl33VcBmmz3Dbjg0zAY/VpM1peRiBXUfgapOeoV9XuUXAFgB2gGD\ 34805# wwH2OUQq0CNyA2pgG0yDdW2324b1PewQbObDIbiv7Hxp8X2qQqHRaIhE4pdEYs7YBYUBvgizhoITM6FheY/A1KrvsaMCVCDQ64BDYYs5zh9wG0EW2YY+0\ 34806# N/J5RqFQtn5YebsaWN+DNyTMSVLlzFk8LC+VWfqkfeMjAhUbDYqTzbuP2YXOLoH+G6Xgxvvaz3fyFJmOifNHTdm1E8qOlWy9CKnCTHLe/QmvUkgkaoQnw\ 34807# +paSg/dlMFzPl8h6OrK55Pz5s091cLHQAsXojjZEfCOj3bJ5VJrHQxg8OUPKkBSnc7XIFAV9f8SVOA299o8qIllS9TWUTVBOqxiiG2VlLObN2zh0SqsZH\ 34808# 8Uf/2SX9cmAoAXGXlS3ANXnIYFMY1PIWCB9Pyta1bt66ZUfTd7V8AJRsrXxZEweHOnMFv3roGU7Ji1rQf297fAZilOByFcwaPW4MHtjOKpgPbf9HoRUtx\ 34809# eDwes3TRLHC4wPZfVbTp6fIZRYVl+T81fdwY4Pb/9Q3i0ArjHjdFFQAAAABJRU5ErkJggg==" /> <a href="http://cimg.eu/">htt\ 34810# p://cimg.eu</a></center>) 34811#@gui : note = note{"\n 34812#@gui : If you appreciate <b>G'MIC</b>, you are welcome to send us a nice postcard from your place, at:\n\n 34813#@gui : <small><samp>David Tschumperlé,\n Laboratoire GREYC (CNRS UMR 6072), Equipe Image,\n 34814#@gui : 6 Bd du Maréchal Juin,\n 14050 Caen Cedex / France.</samp></small>"} 34815#@gui : note = note{"Postcards senders automatically enter the <i>Friends Hall of Fame</i> :) !\n\ 34816# You may also consider <a href="https://libreart.info/en/projects/gmic">making a donation</a>!"} 34817 34818#@gui Contributors : _none_, _none_ 34819#@gui : note = note{" 34820#@gui : We would like to thank all these people who contributed to <b>G'MIC</b> in one way or another. 34821#@gui : A big hug to : \n\n 34822#@gui : <b> -</b> <i>Sylvie Alexandre</i> <small>(packaging, testing & filters)</small> 34823#@gui : <b> -</b> <i>Partha Bagchi</i> <small>(packaging)</small> 34824#@gui : <b> -</b> <i>Daniel P. Berrangé</i> <small>(packaging)</small> 34825#@gui : <b> -</b> <i>Sébastien Bougleux</i> <small>(debugging)</small> 34826#@gui : <b> -</b> <i>Jérome Boulanger</i> <small>(testing & code)</small> 34827#@gui : <b> -</b> <i>Claude Bulin</i> <small>(packaging)</small> 34828#@gui : <b> -</b> <i>Aurélien Ceyden</i> <small>(packaging)</small> 34829#@gui : <b> -</b> <i>François Collard</i> <small>(testing)</small> 34830#@gui : <b> -</b> <i>Patrick David</i> <small>(testing & filters)</small> 34831#@gui : <b> -</b> <i>Maxime Daisy</i> <small>(code & testing)</small> 34832#@gui : <b> -</b> <i>Frédéric Devernay</i> <small>(code)</small> 34833#@gui : <b> -</b> <i>Iain Fergusson</i> <small>(filters)</small> 34834#@gui : <b> -</b> <i>Tobias Fleischer</i> <small>(testing & code)</small> 34835#@gui : <b> -</b> <i>Roberto Ferramosca</i> <small>(packaging)</small> 34836#@gui : <b> -</b> <i>Jérome Ferrari</i> <small>(testing, code & tutorials)</small> 34837#@gui : <b> -</b> <i>Andrea Ferrero</i> <small>(testing, code)</small> 34838#@gui : <b> -</b> <i>Chris Fiedler</i> <small>(gfx)</small> 34839#@gui : <b> -</b> <i>Sébastien Fourey</i> <small>(G'MIC-Qt, ZArt code & G'MIC online)</small> 34840#@gui : <b> -</b> <i>Gentlemanbeggar</i> <small>(filters)</small> 34841#@gui : <b> -</b> <i>David Gowers</i> <small>(testing)</small> 34842#@gui : <b> -</b> <i>Claes Holmerson</i> <small>(tutorials)</small> 34843#@gui : <b> -</b> <i>Arto Huotari</i> <small>(filters)</small> 34844#@gui : <b> -</b> <i>Dan Leinir Turthra Jensen</i> <small>(debugging)</small> 34845#@gui : <b> -</b> <i>Tom Keil</i> <small>(testing, filters & tutorials)</small> 34846#@gui : <b> -</b> <i>Andy Kelday</i> <small>(testing & filters)</small> 34847#@gui : <b> -</b> <i>Alan Kwan</i> (afre) <small>(testing & filters)</small> 34848#@gui : <b> -</b> <i>Angelo Lama</i> <small>(testing & EKD integration)</small> 34849#@gui : <b> -</b> <i>John Lakkas</i> <small>(filters)</small> 34850#@gui : <b> -</b> <i>Stéphane de la Linuxerie</i> <small>(design)</small> 34851#@gui : <b> -</b> <i>Mark</i> <small>(translation)</small> 34852#@gui : <b> -</b> <i>Mahvin</i> <small>(testing & design)</small> 34853#@gui : <b> -</b> <i>MareroQ</i> <small>(translation)</small> 34854#@gui : <b> -</b> <i>Ramon Miranda</i> <small>(translation)</small> 34855#@gui : <b> -</b> <i>Tou Omiya</i> <small>(translation)</small> 34856#@gui : <b> -</b> <i>Mauro Quercia</i> <small>(translation)</small> 34857#@gui : <b> -</b> <i>PhotoComiX</i> <small>(testing, translation & filters)</small> 34858#@gui : <b> -</b> <i>Garry Osgood</i> <small>(documentation & filters)</small> 34859#@gui : <b> -</b> <i>Jehan Pages</i> <small>(testing & code)</small> 34860#@gui : <b> -</b> <i>Andreas Påhlsson</i> <small>(filters)</small> 34861#@gui : <b> -</b> <i>James Prichard</i> <small>(testing & filters)</small> 34862#@gui : <b> -</b> <i>Guilherme Razgriz</i> <small>(translation)</small> 34863#@gui : <b> -</b> <i>Karsten Rodenacker</i> <small>(packaging & code)</small> 34864#@gui : <b> -</b> <i>Marc Roovers</i> <small>(clut data)</small> 34865#@gui : <b> -</b> <i>Dani Sardà</i> <small>(translation)</small> 34866#@gui : <b> -</b> <i>Yuri Shemanin</i> <small>(debugging)</small> 34867#@gui : <b> -</b> <i>Silvio Grosso</i> <small>(debugging)</small> 34868#@gui : <b> -</b> <i>Stepanekos</i> <small>(translation)</small> 34869#@gui : <b> -</b> <i>Thorsten "otto" Stettin</i> <small>(packaging)</small> 34870#@gui : <b> -</b> <i>Lukas Tvrdy</i> <small>(Krita integration)</small> 34871#@gui : <b> -</b> <i>Martin Wolff</i> <small>(testing & filters)</small> 34872#@gui : <b> -</b> <i>Bernd Zeimetz</i> <small>(packaging)</small> 34873#@gui : <b> -</b> <i>Matthias Zepper</i> <small>(testing)</small> 34874#@gui : <b> -</b>"} 34875 34876#@gui Download External Data : gui_download_all_data, gui_no_preview(1) 34877#@gui : note = note{"This filter will download all external data files used by some filters of the <i>G'MIC</i> 34878#@gui : plug-in (<i>Color Grading</i>, <i>Light Leaks</i>, <i>Grain</i>, etc...), 34879#@gui : and will install them as persistent files on your hard drive. After this operation, you won't need a permanent 34880#@gui : internet connection anymore in order to use some of the G'MIC filters."} 34881#@gui : note = note() 34882#@gui : note = note{"<b><span color="#EE5500">Warning:</span></b> A <b>lot of data</b> will be downloaded. 34883#@gui : This can take a long time !"} 34884#@gui : sep = separator() 34885#@gui : Force re-Download from Scratch = _bool(0) 34886#@gui : sep = separator() 34887#@gui : note = note{"<b><span color="#EE5500">Alternative (manual) method:</span></b>\nIf, for any reasons, 34888#@gui : your plug-in is unable to retrieve data from the Internet, you can download all 34889#@gui : those data files manually (as a single .zip file) at this address :"} 34890#@gui : url = link{"https://gmic.eu/gmic_all_data.zip"} 34891#@gui : note = note{"You must then decompress all files contained in this archive at the following location:\n 34892#@gui : - for <b>Unix</b>-like systems : <span color="blue"><samp>$HOME/.cache/gmic/</samp></span>\n 34893#@gui : - for <b>Windows</b> systems : <span color="blue"><samp>%APPDATA/gmic/</samp></span> 34894#@gui : "} 34895#@gui : sep = separator() 34896#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/16/04</i>.</small>") 34897gui_download_all_data : 34898 34899 # Color Presets. 34900 l[] clut foo rm onfail rm endl 34901 34902 # Grain. 34903 _filenames_grain=${-_fx_simulate_grain} 34904 _url_grain=https://gmic.eu/data_film_presets 34905 _prefix_grain=grain_ 34906 _ext_grain=cimgz 34907 34908 # Light leaks. 34909 _filenames_lightleak=${-_fx_light_leaks} 34910 _url_lightleak=https://gmic.eu/data_lightleaks 34911 _prefix_lightleak= 34912 _ext_lightleak=cimgz 34913 34914 # Sample images. 34915 _filenames_sample=${-__sample} 34916 _url_sample=https://gmic.eu/img 34917 _prefix_sample=sample_ 34918 _ext_sample=png 34919 34920 # Demo thumbnails. 34921 _filenames_demos=gmic_demos 34922 _url_demos=https://gmic.eu/img 34923 _prefix_demos= 34924 _ext_demos=cimgz 34925 34926 # Manage downloads. 34927 _n=0 34928 _N={narg($_filenames_grain,$_filenames_lightleak,$_filenames_logo,$_filenames_sample)} 34929 progress 0 34930 _gui_download_all_data[] grain,$1 34931 _gui_download_all_data[] lightleak,$1 34932 _gui_download_all_data[] logo,$1 34933 _gui_download_all_data[] sample,$1 34934 _gui_download_all_data[] demos,$1 34935 progress 100 34936 34937_gui_download_all_data : 34938 repeat narg(${_filenames_$1}) 34939 filename=${_prefix_$1}${arg\ 1+$>,${_filenames_$1}}.${_ext_$1} 34940 e[] "Download "$filename 34941 if $2" || "!isfile(['{/${-path_cache}$filename}']) l[] 34942 ${_url_$1}/$filename o ${-path_cache}$filename rm onfail 34943 endl fi 34944 progress {100*$_n/$_N} 34945 _n+=1 34946 done 34947 34948#@gui Filter Design : _none_, _none_ 34949#@gui : note = note{" 34950#@gui : <b>G'MIC</b> is an <b>open</b> image processing framework. Thus, including 34951#@gui : <b>user-defined filters</b> into this plug-in is possible.\n\n 34952#@gui : To do so, you need to create a <span foreground="purple" style="italic">.gmic</span> 34953#@gui : file in your <i>$HOME/</i> folder (or <i>%APPDATA%/user.gmic</i> on Windows). 34954#@gui : It will be read each time the plug-in is launched, or when the <i>Refresh</i> 34955#@gui : button (under the central pane) is pressed. It must be a regular text file, containing the declarations and 34956#@gui : implementations of the filters (written in the <b>G'MIC</b> language) that will be added 34957#@gui : to the list of available ones."} 34958#@gui : note = note{" 34959#@gui : Existing filters are already defined this way. 34960#@gui : Writing a filter from scratch in <b>G'MIC</b> requires some skills, but 34961#@gui : can be generally done in very few lines.\n\n 34962#@gui : <span foreground="purple" underline="single">Example of a valid <i>.gmic</i> entry :</span>"} 34963#@gui : note = note{"<samp>#@gui My effect : my_effect, my_effect</samp>"} 34964#@gui : note = note{"<samp>#@gui : Sigma = float(2,0,10)</samp>"} 34965#@gui : note = note{"<samp>my_effect :\n +blur $1 n 0,255 xor</samp>"} 34966#@gui : note = note{" 34967#@gui : Look at the reference documentation and the tutorial whose links are given below, to learn more. 34968#@gui : By the way, you are encouraged to share your nice custom filters with us on our forums, 34969#@gui : for inclusion into next releases of <b>G'MIC</b>. 34970#@gui : "} 34971#@gui : sep = separator() 34972#@gui : url = link(0,"[1] G'MIC reference documentation","https://gmic.eu/reference/") 34973#@gui : url = link(0,"[2] G'MIC scripting tutorial","https://gmic.eu/tutorial/index.shtml") 34974#@gui : url = link(0,"[3] G'MIC filter template","https://gmic.eu/template.gmic") 34975 34976#@gui Friends Hall of Fame : _none_, fx_friends 34977#@gui : note = note{"\n<span foreground="purple" underline="single">Supporters:</span>"} 34978#@gui : note = note{" <b>-</b> A big hug goes to these friends who supported the project:"} 34979#@gui : note = note{"<i> 34980#@gui : Christian Stenner, 34981#@gui : Daniel Balle, 34982#@gui : Matthias Fuchs, 34983#@gui : <a href="https://www.augustus5star.fr/">Alban Bourrat</a>, 34984#@gui : <a href="http://viewbug.com/photo/65310796">Elizabeth Hayman</a>, 34985#@gui : Nicolas Künzler, 34986#@gui : Mikael Wargh, 34987#@gui : Giovanni Bianchessi, 34988#@gui : Job van der Zwan, 34989#@gui : <a href="http://espitallier.net/">Laurent Espitallier</a>, 34990#@gui : Mark van der Grijp, 34991#@gui : Patrick Wauters, 34992#@gui : <a href="https://pocketvj.com">Marc-André Gasser</a>, 34993#@gui : <a href="http://www.flickr.com/photos/ssshupe/">Steven Shupe</a>, 34994#@gui : Mika Yrjölä, 34995#@gui : <a href="https://www.silviogrosso.com/">Silvio Grosso</a>, 34996#@gui : Marek Kubica, 34997#@gui : <a href="http://www.flickr.com/newmikey">Mike Bing</a>, 34998#@gui : <a href="http://pixby.com/">Dave Allen</a>, 34999#@gui : Margaret Wong, 35000#@gui : Adrian Bottomley, 35001#@gui : Pamela Young, 35002#@gui : <a href="http://chrisbowness.com/">Chris Bowness</a>, 35003#@gui : Peter Howarth, 35004#@gui : Marlon Montalvo, 35005#@gui : Christian Freiherr von Malchus, 35006#@gui : Nolan Tyrrell, 35007#@gui : Gilles Bouquerel, 35008#@gui : Mihail Balabanov, 35009#@gui : Rolf Niepraschk, 35010#@gui : Volkmar Geske, 35011#@gui : Menno Tjoelker, 35012#@gui : <a href="https://borkarabhijeet05.blogspot.com/p/about-me.html">Abhijeet Borkar</a>, 35013#@gui : <a href="https://www.behance.net/kontaktarl1e0a">Arleta Lesniewska</a>, 35014#@gui : Nicola Giaccobe, 35015#@gui : Helmut Mühleisen, 35016#@gui : Paul Buckley, 35017#@gui : Olivier Lecarme, 35018#@gui : Edward Ingram, 35019#@gui : <a href="http://www.gus-verlag.de/verlag/Artelier/">Stefan Städtler-Ley</a>, 35020#@gui : Michel Pastor, 35021#@gui : Sz.U, 35022#@gui : Sven Kraft, 35023#@gui : Frederik Elwert, 35024#@gui : Jessica Leonard, 35025#@gui : <a href="https://www.viewbug.com/member/KennZaney">Kenneth Simons</a>, 35026#@gui : <a href="https://www.flickr.com/photos/114936163@N05/">Milos Ciuk</a>, 35027#@gui : Manlio Barolo, 35028#@gui : John Lewandowski, 35029#@gui : <a href="http://mediaklan.com/">Didier Lima</a>, 35030#@gui : Žygimantas Tauras, 35031#@gui : Massimo Ferri, 35032#@gui : <a href="https://github.com/sina-ht">Hiroshi Takekawa</a>, 35033#@gui : Freelance writer, 35034#@gui : <a href="https://www.flickr.com/photos/49284009@N04/">Elaine Hutchings</a>, 35035#@gui : András Somogyi, 35036#@gui : <a href="https://www.flickr.com/photos/tonurics">Jason Dora</a>, 35037#@gui : Boris Hajdukovic, 35038#@gui : <a href="https://mappish.com/pages/about-us">Jeff Combs / Mappish</a>, 35039#@gui : <a href="http://flickr.com/photos/btraven">BTraven</a>, 35040#@gui : <a href="https://500px.com/spodeworld">Steven Brener</a>, 35041#@gui : Susanne Gabrielski, 35042#@gui : Andrea Correani, 35043#@gui : Mads Thomsen, 35044#@gui : Djek Eykhout, 35045#@gui : Michael Calabrese, 35046#@gui : Joachim Steiert 35047#@gui : Christian Dubettier, 35048#@gui : J. Casseur, 35049#@gui : <a href="http://www.gnomelibre.fr/">Okki</a>, 35050#@gui : Dariusz Duma, 35051#@gui : <a href="http://www.mahvin.com/">Mahvin</a>, 35052#@gui : Elleen Hennessy, 35053#@gui : BluffStuffPlus, 35054#@gui : <a href="http://www.bertrandchan.eu">Bertrand Chan</a>, 35055#@gui : Mirella Scotto, 35056#@gui : <a href="http://www.photopablo.com">Paul Sauve</a>, 35057#@gui : <a href="https://darktablemaster.de">Lars Mielke</a>, 35058#@gui : Devin Sorell, 35059#@gui : <a href="http://www.quesepuedehacerenlinux.net">Pepe Baeza</a>, 35060#@gui : <a href=" http://www.lesnoy-tanets.com">Andrey Pivovarova</a>, 35061#@gui : <a href="http://doliver.co.uk/">David Oliver</a>, 35062#@gui : <a href="https://ello.co/errore">errore</a>, 35063#@gui : <a href="http://www.anudai.de">Anudai</a>, 35064#@gui : James Stalnaker, 35065#@gui : <a href="https://plus.google.com/u/0/b/117441237982283011318/112547676857320288448/about">Paolo Finetti</a>, 35066#@gui : Luigi Scarselli, 35067#@gui : <a href="https://patdavid.net/">Pat David</a>, 35068#@gui : Juan Jose Rodriguez Vela, 35069#@gui : Thomas Jakob, 35070#@gui : Kim Bartholomew, 35071#@gui : <a href="http://www.captivemoment.com">Sudi</a>, 35072#@gui : Michael Prostka, 35073#@gui : Arkadi Gelfond, 35074#@gui : <a href="https://joeysl.wordpress.com/">Sabine Schäfers</a>, 35075#@gui : <a href="http://www.viewbug.com/member/KennZaney">Bull O'Woods</a>, 35076#@gui : Jost Jakob Schaper, 35077#@gui : Dominik Wefers, 35078#@gui : Frank McLaughlin, 35079#@gui : <a href="https://29a.ch/">Jonas Wagner</a>, 35080#@gui : <a href="www.ixaarii.com">Void lon iXaarii</a>, 35081#@gui : Mark Boadey, 35082#@gui : Laura Haglund, 35083#@gui : Lee Elliott, 35084#@gui : Bernard Desenclos, 35085#@gui : Randy Gordon-Gilmore, 35086#@gui : Eddie Dedrick, 35087#@gui : <a href="http://mindprints.org/">Greg FitzPatrick</a>, 35088#@gui : Zsolt Szabo, 35089#@gui : Daniel Hanna, 35090#@gui : Peter Bengtsson, 35091#@gui : Diego Nassetti, 35092#@gui : William Tweedy, 35093#@gui : Shawnee Horn, 35094#@gui : Stephan Munsch, 35095#@gui : <a href="http://www.mysticali3n-wear.com">MysticAli3n-Wear</a>, 35096#@gui : Mika Mantere, 35097#@gui : Christian Beuschel, 35098#@gui : Tore Busch, 35099#@gui : Douc McGregor. 35100#@gui : Marcel Dahm, 35101#@gui : Susan Voitel, 35102#@gui : <a href="https://www.flickr.com/photos/henkkoning">Henk Koning</a>, 35103#@gui : Arnie Jordan, 35104#@gui : Carol Jennings, 35105#@gui : Sébastien Huart, 35106#@gui : <a href="http://www.jessstryker.com/">Jess Stryker</a>, 35107#@gui : Rui Luis, 35108#@gui : <a href="https://www.flickr.com/photos/sallesrenato/">Renato Salles</a>, 35109#@gui : <a href="http://www.viewbug.com/member/alef0"> Petr Zagalak</a>, 35110#@gui : <a href="http://www.antonio.cat">Antonio Vicién Faure</a>, 35111#@gui : Vincent Bermel, 35112#@gui : Christian Stocco, 35113#@gui : <a href="https://www.flickr.com/photos/136307651@N04/">Richard Benedict</a>, 35114#@gui : Dr. Helmut Jarausch, 35115#@gui : <a href="http://www.michaeljamesbeck.com">Michael Beck</a>, 35116#@gui : <a href="http://rickleone.tumblr.com/">Riccardo Leone</a>, 35117#@gui : Gisela Looram, 35118#@gui : <a href="https://plus.google.com/u/0/+FrankTegtmeyer/posts">Frank Tegtmeyer</a>, 35119#@gui : David Kettrey, 35120#@gui : <a href="https://www.youtube.com/user/kncpt1">Peter Hoge</a>, 35121#@gui : Alexander Heitmann, 35122#@gui : <a href="http://harlequin.webcomics.fr/page/episode-1-page-1">Olivier Larski</a>, 35123#@gui : <a href="http://victorfandrey.blogspot.ca">Victor Fandrey</a>, 35124#@gui : Stefan Peter, 35125#@gui : <a href="https://plus.google.com/u/0/+DimitriosPsychogios">Dimitrios Psychogios</a>, 35126#@gui : <a href="https://plus.google.com/+AnttiLuoma">Antti Luoma</a>, 35127#@gui : <a href="https://twitter.com/jeyoung">Eddy Young Tie Yang</a>, 35128#@gui : Thomas Elfstrom, 35129#@gui : Valentine Boyce, 35130#@gui : George Harnett, 35131#@gui : Darius Manka, 35132#@gui : Chris Knox, 35133#@gui : <a href="http://tomtappingphotoblog.blogspot.fr/">Thomas Tapping</a>, 35134#@gui : Phillip R Ziesemer, 35135#@gui : Jean Francois. 35136#@gui : Franz Ziereis, 35137#@gui : Alessandro Renzi, 35138#@gui : Tsuda Koshi, 35139#@gui : <a href="http://www.boxrec.com">Boxrec Ltd</a>, 35140#@gui : <a href="http://www.wolfgangschweizer.com/">Wolfgang Schweizer</a>, 35141#@gui : <a href="http://www.ramonmiranda.com/">Ramon Miranda</a>, 35142#@gui : Volker Bradley, 35143#@gui : <a href="http://plus.google.com/+MarcoZara">Marco Zara</a>, 35144#@gui : <a href="http://plus.google.com/+MarcoTedaldi">Marco Tedaldi</a>, 35145#@gui : <a href="http://cybertographer.com">Rodney Lee</a>, 35146#@gui : Konstantinos Blatzonis, 35147#@gui : Simon Chanson, 35148#@gui : Herbert Malle, 35149#@gui : <a href="http://www.matthias-zepper.de/">Matthias Zepper</a>, 35150#@gui : Christian Mariucci, 35151#@gui : M. R., 35152#@gui : Mark Link, 35153#@gui : <a href="http://blog.meetthegimp.org/">Rolf Steinort</a>, 35154#@gui : <a href="https://plus.google.com/112357088505488756823/posts">Daniel Tauro</a>, 35155#@gui : <a href="http://geniisoft.com/">Ben Langhinrichs</a>, 35156#@gui : <a href="http://www.openlabs.it/">Paolo Pedaletti</a>, 35157#@gui : <a href="http://blog.photomontager.com">Ricardo Corin</a>, 35158#@gui : <a href="https://plus.google.com/115953666279509959258">James Prichard</a>, 35159#@gui : <a href="https://plus.google.com/116658221461047313647">Matt Jones</a>, 35160#@gui : <a href="http://www.flickr.com/people/twekkel/">Eddy Vervest</a>, 35161#@gui : <a href="http://www.flaviocdc.net/wiki/">Flavio Casadei Della Chiesa</a>, 35162#@gui : <a href="http://www.artwanted.com/artist.cfm?artid=10918">Lyle Kroll</a>. 35163#@gui : </i>"} 35164#@gui : sep = separator() 35165#@gui : note = note{"\n<span foreground="purple" underline="single">Postcard senders:</span>"} 35166#@gui : note = note{" <b>-</b> We've received <b>46</b> postcards from <b>G'MIC</b> enthusiasts so far. 35167#@gui : You could be the <b>47rd</b> sender :)"} 35168#@gui : note = note{" <b>-</b> A big hug goes to these postcard senders (recently received first) :"} 35169#@gui : note = note{"<i> 35170#@gui : <a href="https://cimg.eu/img/postcard73.jpg">Benjamin Russell</a> (Portsmouth/USA), 35171#@gui : <a href="https://cimg.eu/img/postcard72.jpg">Andreas Weissenburger</a> (Bochum/Germany), 35172#@gui : <a href="https://cimg.eu/img/postcard70.jpg">Patrick Wanters</a> (USA), 35173#@gui : <a href="https://cimg.eu/img/postcard69.jpg">Josep Febrer</a> (Pregonda/Menorca), 35174#@gui : <a href="https://cimg.eu/img/postcard68.jpg">Richard Gledson</a> (Newcastle upon tyne/England), 35175#@gui : <a href="https://cimg.eu/img/postcard67.jpg">James Jaworski</a> (Winnipeg/Canada), 35176#@gui : <a href="https://cimg.eu/img/postcard66.jpg">Powlux</a> (France), 35177#@gui : <a href="https://cimg.eu/img/postcard65.jpg">Volker Doebel</a> (Haldern/Germany), 35178#@gui : <a href="https://cimg.eu/img/postcard64.jpg">Patrick Wauters</a> (Bilbao/Spain), 35179#@gui : <a href="https://cimg.eu/img/postcard63.jpg">Sebastien Fourey</a> (Konstanz/Germany), 35180#@gui : <a href="https://cimg.eu/img/postcard62.jpg">David Revoy</a> (Toulouse/France), 35181#@gui : <a href="https://cimg.eu/img/postcard61.jpg">Giulio Canevari</a> (Pavia/Italy), 35182#@gui : <a href="https://cimg.eu/img/postcard60.jpg">Bruno Steinbach</a> (Pondicherry/India), 35183#@gui : <a href="https://cimg.eu/img/postcard59.jpg">Steve Gillow</a> (Fort Worth/Texas/USA), 35184#@gui : <a href="https://cimg.eu/img/postcard58.jpg">Peter Neave</a> (Sydney/Australia), 35185#@gui : <a href="https://cimg.eu/img/postcard57.jpg">Andrea [Photoflow]</a> (Italy), 35186#@gui : <a href="https://cimg.eu/img/postcard56.jpg">Garry R. Osgood</a> (New York/USA), 35187#@gui : <a href="https://cimg.eu/img/postcard55.jpg">Justin Pletzfeld</a> (Germany), 35188#@gui : <a href="https://cimg.eu/img/postcard54.jpg">Werner Meier</a> (Germany), 35189#@gui : <a href="https://cimg.eu/img/postcard53.jpg">Patrick Wauters</a> (Roma/Italy), 35190#@gui : <a href="https://cimg.eu/img/postcard52.jpg">Marc Lis</a> (Belgium), 35191#@gui : <a href="https://cimg.eu/img/postcard51.jpg">ZondeR</a> (France), 35192#@gui : <a href="https://cimg.eu/img/postcard50.jpg">Bill C.</a> (USA), 35193#@gui : <a href="https://cimg.eu/img/postcard49.jpg">Michael T.</a> (France), 35194#@gui : <a href="https://cimg.eu/img/postcard48.jpg">Patrick Wauters</a> (Lisboa), 35195#@gui : <a href="https://cimg.eu/img/postcard47.jpg">Akky [Gimpchat]</a> (Australia), 35196#@gui : <a href="https://cimg.eu/img/postcard45.jpg">Michel Thomas</a> (Germany), 35197#@gui : <a href="https://cimg.eu/img/postcard44.jpg">Pierre-Yves</a> (Ile de Batz/France), 35198#@gui : <a href="https://cimg.eu/img/postcard43.jpg">Family Hamacher</a> (Trier/Germany), 35199#@gui : <a href="https://cimg.eu/img/postcard41.jpg">Benoit Gauzere and Francois Lozes</a> (Hokusai/Japan), 35200#@gui : <a href="https://cimg.eu/img/postcard40.jpg">Dr. Rainer Teubner</a> (Seligenstadt/Germany), 35201#@gui : <a href="https://cimg.eu/img/postcard39.jpg">Mauro Mitrino</a> (Mantova/Italy), 35202#@gui : <a href="https://cimg.eu/img/postcard37.jpg">Werner Meier</a> (Mettlach/Germany), 35203#@gui : <a href="https://cimg.eu/img/postcard36.jpg">Arto Huotari</a> (Helsinki/Finland), 35204#@gui : <a href="https://cimg.eu/img/postcard33.jpg">Benoit Gauzere</a> (California/USA), 35205#@gui : <a href="https://cimg.eu/img/postcard30.jpg">Arkadi Gelfond</a> (Foster City - California/USA), 35206#@gui : <a href="https://cimg.eu/img/postcard29.jpg">Corinne Masimann</a> (Neuchatel/Switzerland), 35207#@gui : <a href="https://cimg.eu/img/postcard27.jpg">Mahvin</a> (Portland/USA), 35208#@gui : <a href="https://cimg.eu/img/postcard26.jpg">Vincent Roullier</a> (Caen/France), 35209#@gui : <a href="https://cimg.eu/img/postcard24.jpg">M????</a> (Munich/Germany), 35210#@gui : <a href="https://cimg.eu/img/postcard23.jpg">F. Albior</a> (Jaca/Spain), 35211#@gui : <a href="https://cimg.eu/img/postcard22.jpg">PhotoComIX</a> (Frascati/Italy), 35212#@gui : <a href="https://cimg.eu/img/postcard21.jpg">Guy Poizat</a> (Cabestany/France), 35213#@gui : <a href="https://cimg.eu/img/postcard20.jpg">Institut for Biomathematik und Biometrie</a> (Neuherberg/Germany), 35214#@gui : <a href="https://cimg.eu/img/postcard15.jpg">Jean-Michel Webbe</a> (Guadeloupe/France), 35215#@gui : <a href="https://cimg.eu/img/postcard14.jpg">Jaime</a> (Barcelona/Spain). 35216#@gui : </i>"} 35217#@gui : sep = separator() 35218#@gui : note = note{"\nMay the force be with you!"} 35219fx_friends : 35220 if $! ratio={w/h} else ratio=1 fi 35221 rm _heart80x73 scale3x r 150%,150%,1,1,0,0,0.5,0.5 35222 +*. 70 +*.. 110 +*... 255 *[-4] 255 a c 35223 blur_radial 4 sharpen 300 35224 i.. ${fitratio_wh\ {w},{h},$ratio},1,3 35225 rand.. 0,255 sh.. 1,2 /. 2 rm. 35226 blur_radial.. 20 sharpen.. 50 35227 r. ..,..,1,4,0,0,0.5,0.5 blend alpha 35228 143,80,1,1,0 t. "Greetings to\n all G\47MIC\n friends!",2,-2,27,1,1 35229 +dilate. 3 *.. 255 to_rgb.. j... ..,{[w#-3-w#-2,h#-3-h#-2]/2},0,0,1,. 35230 rm[-2,-1] 35231 35232_heart80x73 : 35233 40,73,1,1,0 ellipse 22,22,20,20,0,1,1 polygon 3,7,37,42,72,42,27,1,1 +mirror x a x 35234 35235#@gui Gmicky - Roddy : fx_gmicky, fx_gmicky_preview 35236#@gui : Mascot Image = choice{"Gmicky (by Deevad)","Gmicky (by Mahvin)","Gmicky & Wilber (by Mahvin)", 35237#@gui : "Roddy (by Mahvin)"} 35238#@gui : sep = separator() 35239#@gui : note = note{"<b><i>Gmicky</i></b> is the name of the <b>G'MIC</b> mascot. 35240#@gui : He is a small and cute tiger who knows how to do magic. 35241#@gui : <b><i>Gmicky</i></b> is a tiger, i.e. fast, agile and elegant, just as the <b>G'MIC</b> code is :). 35242#@gui : As many magicians, <b><i>Gmicky</i></b> knows lot of <b>gimmicks</b>, 35243#@gui : and he is a direct and friendly companion of 35244#@gui : the ImageMagick's wizard, or the GraphicMagick's frog."} 35245#@gui : note = note{"<b><i>Roddy</i></b> is another mascot designed specifically for the 35246#@gui : <i>Artistic / Rodilius</i> filter of <b>G'MIC</b>.\n"} 35247#@gui : note = note{"<b><i>Gmicky</i></b> and <b><i>Roddy</i></b> have been both created and drawn by "} 35248#@gui : url = link("Mahvelous Mahvin","http://www.mahvin.com/") 35249#@gui : note = note{"and"} 35250#@gui : url = link{"David Revoy (Deevad)","http://www.davidrevoy.com/"} 35251fx_gmicky : 35252 rm 35253 if $1==0 sp gmicky nm "name(Gmicky)" 35254 elif $1==1 sp gmicky_mahvin nm "name(Gmicky)" 35255 elif $1==2 sp gmicky_wilber nm "name(Gmicky & Wilber)" 35256 else sp roddy nm "name(Roddy)" 35257 fi 35258 35259fx_gmicky_preview : 35260 fx_gmicky $* rr2d $_preview_width,$_preview_height,0,2 35261 35262#@gui Privacy Notice : _none_, _none_ 35263#@gui : note = note{"This plugin may download up-to-date filter definitions from the 35264#@gui : <a href="https://gmic.eu">gmic.eu</a> server.\n\n 35265#@gui : It is the case when first launched after a fresh installation, and periodically 35266#@gui : with a frequency which can be set in the settings dialog. 35267#@gui : The user should be aware that the following information may be retrieved 35268#@gui : from the server logs: <i>IP address of the client; date and time of the request;</i> 35269#@gui : as well as a short string, supplied through the HTTP protocol <i>"User Agent"</i> header 35270#@gui : field, which describes the full plugin version as shown in the window title 35271#@gui : (e.g. "<i>G'MIC-Qt for GIMP 2.8 - Linux 64 bits - 2.2.1_pre#180301</i>").\n\n 35272#@gui : Note that this information may solely be used for purely anonymous 35273#@gui : statistical purposes. 35274#@gui : "} 35275#@gui : sep = separator() 35276#@gui : note = note("<small>Author: <i>Sébastien Fourey</i>. Latest Update: <i>2018/03/01</i>.</small>") 35277 35278#@gui Release Notes : _none_, _none_ 35279#@gui : note = note{" 35280#@gui : - <b>2009/01/13</b> : version <i>1.3.0</i> (initial plug-in release).\n 35281#@gui : - <b>2010/09/03</b> : version <i>1.4.0</i>.\n 35282#@gui : - <b>2011/07/07</b> : version <i>1.5.0</i>.\n 35283#@gui : - <b>2014/08/20</b> : version <i>1.6.0</i>.\n 35284#@gui : - <b>2016/03/25</b> : version <i>1.7.0</i>.\n 35285#@gui : - <b>2017/05/29</b> : version <i>2.0.0</i>.\n 35286#@gui : - <b>2017/10/09</b> : version <i>2.1.0</i>.\n 35287#@gui : - <b>2018/02/15</b> : version <i>2.2.0</i>.\n 35288#@gui : - <b>2018/06/21</b> : version <i>2.3.0</i>.\n 35289#@gui : - <b>2018/10/04</b> : version <i>2.4.0</i>.\n 35290#@gui : - <b>2019/03/15</b> : version <i>2.5.0</i>.\n 35291#@gui : - <b>2019/04/29</b> : version <i>2.6.0</i>.\n 35292#@gui : - <b>2019/08/14</b> : version <i>2.7.0</i>.\n 35293#@gui : - <b>2019/12/04</b> : version <i>2.8.0</i>.\n 35294#@gui : - <b>2020/03/28</b> : version <i>2.9.0</i>.\n 35295#@gui : - <span foreground="purple"><b>2021/12/09</b> : version <i>3.0.0</i> (Current stable).</span>\n 35296##@gui : - <b>2021/10/05</b> : version <i>3.0.0</i> (Current pre-release).\n 35297#@gui : "} 35298#@gui : sep = separator() 35299##@gui : url = link{"View changelog to upcoming major version (3.0)","https://discuss.pixls.us/t/on-the-road-to-3-0"} 35300##@gui : url = link{"View latest minor changelog (2.9)","https://discuss.pixls.us/t/release-of-gmic-2-9"} 35301#@gui : url = link{"View latest major changelog (3.0)","https://discuss.pixls.us/t/release-of-gmic-3-0-0"} 35302 35303#@gui What's New? : _none_,fx_whatsnew_preview 35304#@gui : note = note("Here you'll find a list of filter additions and deletions in the plug-in, since your last visit. 35305#@gui : When you have seen what's new, press the <b>Got It!</b> button to reset the list of changes.") 35306#@gui : sep = separator() 35307#@gui : nochange = value(0)_0+ 35308#@gui : note = note("\nThere have been no changes since your last visit.\n\n") 35309#@gui : New Filters = text(1,"")_0 35310#@gui : Removed Filters = text(1,"")_0 35311#@gui : Got it! = button(0.5)_0+ 35312#@gui : sep = separator() 35313#@gui : note = note("<small>Authors: <i>David Tschumperlé</i>. 35314#@gui : Latest Update: <i>2021/01/18</i>.</small>") 35315fx_whatsnew_preview : skip "$*" 35316 file=${-path_cache}whatsnew.txt 35317 l[] 35318 parse_gui whatsnew 35319 if isfile(['{/$file}']) it $file date={date([0,1,2],['{/$file}']):/} else 0 date={date([0,1,2]):/} fi 35320 utf82html.. utf82html. 35321 if $4 ot.. $file newfilters,delfilters= is_changes=0 35322 else 35323 35324 # Check for changes. 35325 newfilters,delfilters= 35326 +- is_changes={max(abs(im),abs(iM))!=0} rm. 35327 35328 if !w # First call to the filter 35329 rm. s -,10 35330 repeat $! newfilters.=" - "{$>,t}{`10`} done 35331 35332 elif $is_changes # Estimate changes 35333 eval " 35334 ref(vector256(),str0); 35335 ref(vector256(),str1); 35336 for (s0 = s1 = 0, s0<h#0 && s1<h#1, 35337 e0 = find(#0,_'\n',s0)%h#0; 35338 e1 = find(#1,_'\n',s1)%h#1; 35339 str0 = 0; copy(str0,i[#0,s0],e0 - s0); 35340 str1 = 0; copy(str1,i[#1,s1],e1 - s1); 35341 ref(lowercase(str0) - lowercase(str1),diff); 35342 for (l = 0, l<size(diff) && !diff[l], ++l); 35343 cmp = diff[l]; 35344 !cmp?( # Same strings 35345 s0 = e0 + 1; 35346 s1 = e1 + 1; 35347 ):cmp<0?( # Added filter 35348 run('(\'\"',str0,'\"\') html2utf8. newfilters.=\" - \"{t}{`10`} rm.'); 35349 s0 = e0 + 1; 35350 ):( # Deleted filter 35351 run('(\'\"',str1,'\"\') html2utf8. delfilters.=\" - \"{t}{`10`} rm.'); 35352 s1 = e1 + 1; 35353 ); 35354 )" 35355 fi 35356 fi 35357 rm 35358 endl 35359 u "{0}"_{$is_changes?0:2}\ 35360 "{"{``$newfilters}"}"_{['$newfilters']!=0?2:0}\ 35361 "{"{``$delfilters}"}"_{['$delfilters']!=0?2:0}\ 35362 "{0}_2" 35363 35364#@gui ____<b>Arrays & Tiles</b> 35365#------------------------------- 35366 35367#@gui Array [Faded] : fx_array_fade, fx_array_fade_preview(1) 35368#@gui : X-Tiles = int(2,1,10) 35369#@gui : Y-Tiles = int(2,1,10) 35370#@gui : X-Offset (%) = float(0,0,100) 35371#@gui : Y-Offset (%) = float(0,0,100) 35372#@gui : Fade Start (%) = float(80,1,100) 35373#@gui : Fade End (%) = float(90,1,100) 35374#@gui : Mirror = choice("None","X-Axis","Y-Axis","XY-Axes") 35375#@gui : Size = _choice("Shrink", "Expand", "Repeat [Memory Consuming!]") 35376#@gui : sep = separator() 35377#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35378fx_array_fade : 35379 if $7&1 mirror x fi if $7>1 mirror y fi 35380 array_fade $1,$2,$5,$6,$8 35381 shift -$3%,-$4%,0,0,2 35382 35383fx_array_fade_preview : 35384 fx_array_fade $1,$2,$3,$4,$5,$6,$7,0 35385 35386#@gui Array [Mirrored] : fx_array_mirror, fx_array_mirror_preview(1) 35387#@gui : Iterations = int(1,1,10) 35388#@gui : X-Offset (%) = float(0,0,100) 35389#@gui : Y-Offset (%) = float(0,0,100) 35390#@gui : Array Mode = choice(2,"X-Axis","Y-Axis","XY-Axes","2XY-Axes") 35391#@gui : Initialization = choice("Original","Mirror X","Mirror Y","Rotate 90 deg.","Rotate 180 deg.","Rotate 270 deg.") 35392#@gui : Expand Size = _bool(false) 35393#@gui : Crop (%) = int(0,0,100) 35394#@gui : sep = separator() 35395#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35396fx_array_mirror : skip ${7=0} 35397 if $5==1 mirror x 35398 elif $5==2 mirror y 35399 elif $5==3 rotate 90 35400 elif $5==4 rotate 180 35401 elif $5==5 rotate 270 35402 fi 35403 if $7 35404 if $4==0 columns 0,{100-$7}% 35405 elif $4==1 rows 0,{100-$7}% 35406 elif $4==2 z 0,0,{100-$7}%,{100-$7}% 35407 elif $4==3 z {$7/2}%,{$7/2}%,{100-$7/2}%,{100-$7/2}% 35408 fi 35409 fi 35410 shift -$2%,-$3%,0,0,2 35411 array_mirror $1,$4,$6 35412 35413fx_array_mirror_preview : 35414 fx_array_mirror $1,$2,$3,$4,$5,0,$7 35415 35416#@gui Array [Random] : array_random, array_random(1) 35417#@gui : Source X-Tiles = int(5,1,20) 35418#@gui : Source Y-Tiles = int(5,1,20) 35419#@gui : Destination X-Tiles = int(7,1,20) 35420#@gui : Destination Y-Tiles = int(7,1,20) 35421#@gui : sep = separator() 35422#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35423 35424#@gui Array [Random Colors] : fx_array_color, fx_array_color(1) 35425#@gui : X-Tiles = int(5,1,20) 35426#@gui : Y-Tiles = int(5,1,20) 35427#@gui : Opacity = float(0.5,0,1) 35428#@gui : sep = separator() 35429#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35430fx_array_color : 35431 repeat $! l. 35432 $1,$2,1,3 rand. 0,255 to_colormode. {-2,s} ri. .. *. $3 *.. {1-$3} +[-2,-1] 35433 endl mv. 0 done 35434 35435#@gui Array [Regular] : fx_array, fx_array_preview(1) 35436#@gui : X-Tiles = int(2,1,10) 35437#@gui : Y-Tiles = int(2,1,10) 35438#@gui : X-Offset (%) = float(0,0,100) 35439#@gui : Y-Offset (%) = float(0,0,100) 35440#@gui : Mirror = choice("None","X-Axis","Y-Axis","XY-Axes") 35441#@gui : Size = _choice("Shrink", "Expand", "Repeat [Memory Consuming!]") 35442#@gui : sep = separator() 35443#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35444fx_array : 35445 shift -$3%,-$4%,0,0,2 35446 if $5&1 mirror x fi if $5>1 mirror y fi 35447 array $1,$2,$6 35448 35449fx_array_preview : 35450 fx_array $1,$2,$3,$4,$5,0 35451 35452#@gui Ascii Art : fx_asciiart, fx_asciiart_preview(0)+ 35453#@gui : Charset = choice(5,"Custom","Binary Digits","Digits","Lowercase Letters","Uppercase Letters", 35454#@gui : "Ascii","Card Suits","Math Symbols") 35455#@gui : Custom Dictionary = text{" .oO0"} 35456#@gui : Analysis Scale = int(16,8,103) 35457#@gui : Analysis Smoothness = float(15,0,100) 35458#@gui : Synthesis Scale = int(16,8,103) 35459#@gui : Result Type = choice(2,"White on Black","Black on White","Colored on Black","Colored on Transparent") 35460#@gui : sep = separator() 35461#@gui : Gamma = float(0,-3,3) 35462#@gui : Smoothness = float(0.2,0,5) 35463#@gui : Colors = choice("Full Colors","2 Colors","3 Colors","4 Colors","8 Colors","12 Colors","16 Colors", 35464#@gui : "Grayscale","2 Grays","3 Grays","4 Grays","8 Grays","12 Grays","16 Grays") 35465#@gui : sep = separator() 35466#@gui : Output Ascii File = _bool(0) 35467#@gui : Output Folder = _folder() 35468#@gui : Output Filename = _text("gmic_asciiart.txt") 35469#@gui : sep = separator() 35470#@gui : url = link("Click here for a detailed description of this filter.",\ 35471# "http://www.gimpchat.com/viewtopic.php?f=28&t=10047") 35472#@gui : sep = separator() 35473#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/27/03</i>.</small>") 35474fx_asciiart : skip "${10=},${11=},${12=}" 35475 repeat $! l[$>] to_rgb 35476 apply_gamma {10^$7} b $8% n 0,255 35477 if $1==0 dict="$2" 35478 elif $1==1 35479 dict=" 01" 35480 elif $1==2 35481 dict=" 0123456789" 35482 elif $1==3 35483 dict=" abcdefghijklmnopqrstuvwxyz" 35484 elif $1==4 35485 dict=" ABCDEFGHIJKLMNOPQRSTUVWXYZ" 35486 elif $1==5 35487 dict=" !\042#$%&\047()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\133\\\135^_\140abcdefghijklmnopqrstu"\ 35488 "vwxyz\173|\174~" 35489 elif $1==6 35490 dict=" \16\17\20\21" 35491 elif $1==7 35492 dict=" \200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231" 35493 fi 35494 if $6==1 negate fi 35495 if $-3 +img2ascii $dict,$3,$4%,$5,"$-2"/"$-1" 35496 else +img2ascii $dict,$3,$4%,$5 35497 fi 35498 wh=${} 35499 if $6==0 k. n 0,255 35500 elif $6==1 k. negate n 0,255 35501 elif $6==2" || "$6==3 35502 r[0] $wh,1,100%,1 35503 if $9>=7 luminance[0] fi 35504 if $9%7 quantize[0] {arg($9%7,2,3,4,8,12,16)-1},1,0 fi 35505 r[0] [1],[1],1,100% *[0] [1] 35506 if $6==2 rm[1] 35507 else *[1] 255 a c 35508 fi 35509 fi 35510 endl done 35511 35512fx_asciiart_preview : 35513 repeat $! l[$>] 35514 w={w} h={h} 35515 fx_asciiart $1,"$2",${3-9},0,foo,foo 35516 r $w,$h,1,100%,0,0,0.5,0.5 35517 endl done 35518 35519#@gui Chessboard : fx_chessboard, fx_chessboard_preview(0) 35520#@gui : First Size = int(64,1,512) 35521#@gui : Second Size = int(64,1,512) 35522#@gui : First Offset = int(0,0,512) 35523#@gui : Second Offset = int(0,0,512) 35524#@gui : Angle = float(0,0,180) 35525#@gui : Opacity = float(0.5,0,1) 35526#@gui : First Color = color(0,0,0,255) 35527#@gui : Second Color = color(255,255,255,255) 35528#@gui : sep = separator() 35529#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35530#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35531#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35532#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35533#@gui : sep = separator() 35534#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35535fx_chessboard : 35536 to_rgba chessboard ${1-14} 35537 35538fx_chessboard_preview : 35539 gui_split_preview "fx_chessboard $*",${-3--1} 35540 35541#@gui Dices : fx_dices, fx_dices(0) 35542#@gui : Resolution = float(2,1,10) 35543#@gui : Size = int(24,8,64) 35544#@gui : Color Model = choice(1,"Black Dices","White Dices","Dices with Colored Numbers","Dices with Colored Sides") 35545#@gui : sep = separator() 35546#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/06</i>.</small>") 35547fx_dices : 35548 35549 # Create dice patterns. 35550 repeat 6 {2*$2},{2*$2} _dice$> done 35551 if $3%2 negate[-6--1] fi 35552 frame_round[-6--1] 10,10,0,0,128,128,128,0 35553 r2dy[-6--1] $2 a[-6--1] x 35554 35555 repeat $!-1 l[$>,-1] 35556 35557 # Prepare input images. 35558 +luminance[0] rv[1,2] r[0,1] {100*$1/$2}%,{100*$1/$2}%,1,100%,2 quantize[1] 6,0 35559 35560 # Convert input image to dices pattern. 35561 *.. $2 channels.. 0,1 r.. {$2*100}%,{$2*100}% 35562 $2,$2,1,2,'if(c,y,x)' r. ...,...,1,2,0,2 +[-3,-1] +warp. ..,0,0 rm... 35563 35564 if $3<2 rm[0] mv. 0 35565 else r[0] [2],[2],1,100% rv[0,-1] blend[0,-1] multiply 35566 fi 35567 35568 endl done rm. 35569 35570_dice0 : ellipse. 50%,50%,5.2%,5.2%,0,1,255 35571_dice1 : ellipse. 25%,25%,5.2%,5.2%,0,1,255 ellipse. 75%,75%,5.2%,5.2%,0,1,255 35572_dice2 : _dice1 _dice0 35573_dice3 : _dice1 ellipse. 25%,75%,5.2%,5.2%,0,1,255 ellipse. 75%,25%,5.2%,5.2%,0,1,255 35574_dice4 : _dice3 _dice0 35575_dice5 : _dice3 ellipse. 25%,50%,5.2%,5.2%,0,1,255 ellipse. 75%,50%,5.2%,5.2%,0,1,255 35576 35577#@gui Drawn Montage : fx_drawn_montage, fx_drawn_montage_preview(1) : * 35578#@gui : Layer = choice("1st","2nd","3rd","4th","5th","6th","7th","8th","9th","10th","11th","12th", 35579#@gui : "13th","14th","15th","16th") 35580#@gui : Associated Color = color(0,0,0) 35581#@gui : Zoom = float(-10,0,10) 35582#@gui : X-Centering (%) = float(50,0,100) 35583#@gui : Y-Centering (%) = float(50,0,100) 35584#@gui : Angle = choice("0 deg.","90 deg.","180 deg.","270 deg.") 35585#@gui : Pargs = value(-1) 35586#@gui : Args0 = value(0:0:0:0:50:50:0) 35587#@gui : Args1 = value(0:0:0:0:50:50:0) 35588#@gui : Args2 = value(0:0:0:0:50:50:0) 35589#@gui : Args3 = value(0:0:0:0:50:50:0) 35590#@gui : Args4 = value(0:0:0:0:50:50:0) 35591#@gui : Args5 = value(0:0:0:0:50:50:0) 35592#@gui : Args6 = value(0:0:0:0:50:50:0) 35593#@gui : Args7 = value(0:0:0:0:50:50:0) 35594#@gui : Args8 = value(0:0:0:0:50:50:0) 35595#@gui : Args9 = value(0:0:0:0:50:50:0) 35596#@gui : Args10 = value(0:0:0:0:50:50:0) 35597#@gui : Args11 = value(0:0:0:0:50:50:0) 35598#@gui : Args12 = value(0:0:0:0:50:50:0) 35599#@gui : Args13 = value(0:0:0:0:50:50:0) 35600#@gui : Args14 = value(0:0:0:0:50:50:0) 35601#@gui : Args15 = value(0:0:0:0:50:50:0) 35602#@gui : sep = separator() 35603#@gui : note = note{"<small><b>Note:</b> 35604#@gui : This filter requires a top layer containing the desired montage layout defined as free-form shapes 35605#@gui : of different colors. You can then assign each layer to a layout color to create the montage. 35606#@gui : </small>"} 35607#@gui : sep = separator() 35608#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/29</i>.</small>") 35609_fx_drawn_montage : 35610 nb_layers={min(16,$!-1)} 35611 35612 if !$nb_layers 35613 error="A top layout layer is missing for this filter to make it work properly!" 35614 if $-1 gui_warning_preview $error return 35615 else error $error 35616 fi 35617 fi 35618 35619 # Manage parameter changes. 35620 pargs,args0,args1,args2,args3,args4,args5,args6,args7,args8,args9,args10,args11,args12,args13,args14,args15=${9-25} 35621 if $1!=$pargs # Get back saved parameters for selected layer 35622 ('${args$1}') replace. {':'},{','} arg_R,arg_G,arg_B,arg_zoom,arg_xcenter,arg_ycenter,arg_angle=${u\ {t}} rm. 35623 else # Set new parameters for selected #L 35624 arg_R,arg_G,arg_B,arg_zoom,arg_xcenter,arg_ycenter,arg_angle=${2-8} 35625 fi 35626 args$1=$arg_R:$arg_G:$arg_B:$arg_zoom:$arg_xcenter:$arg_ycenter:$arg_angle 35627 status=\{$1\}\{$arg_R,$arg_G,$arg_B\}\{$arg_zoom\}\{$arg_xcenter\}\{$arg_ycenter\}\{$arg_angle\}\{$1\}\{$args0\}\ 35628 \{$args1\}\{$args2\}\{$args3\}\{$args4\}\{$args5\}\{$args6\}\{$args7\}\{$args8\}\{$args9\}\{$args10\}\ 35629 \{$args11\}\{$args12\}\{$args13\}\{$args14\}\{$args15\} 35630 35631 # Read parameters for all layers. 35632 c= repeat $nb_layers 35633 ('${args$>}') replace. {':'},{','} R$>,G$>,B$>,zoom$>,xcenter$>,ycenter$>,angle$>=${u\ {t}} 35634 cols=$cols$c${R$>},${G$>},${B$>} c=, rm. rotate[{1+$>}] {90*${angle$>}} 35635 done 35636 35637 # Get bounding boxes for each associated color in layout layer, as well as labeled layout layer. 35638 to_rgb[0] to_rgba[^0] $nb_layers,1,1,4,[inf,inf,-inf,-inf] [0],[0] 35639 f[0] " 35640 begin(colors = [ "$cols" ]); 35641 repeat ("$nb_layers",l, 35642 I==colors[3*l,3]?( 35643 if (x<i(#-2,l,0,0,0), i(#-2,l,0,0,0) = x); 35644 if (y<i(#-2,l,0,0,1), i(#-2,l,0,0,1) = y); 35645 if (x>i(#-2,l,0,0,2), i(#-2,l,0,0,2) = x); 35646 if (y>i(#-2,l,0,0,3), i(#-2,l,0,0,3) = y); 35647 i(#-1,x,y) = l + 1; 35648 ); 35649 ); I" 35650 35651 thumbnail=0 boundaries=0 35652 if $-1 35653 35654 # Render thumbnail of current layer, for preview. 35655 l={1+$1} 35656 if $l<=$nb_layers 35657 if {$l,w>h} +r2dx[$l] {(0$_preview_width?0$_preview_width:400)/6} 35658 else +r2dy[$l] {(0$_preview_height?0$_preview_height:400)/6} fi 35659 frame. 1,1,0,0,0,255 drgba. to. "#"$l,0,-2,13 to_rgba. 35660 mv. -3 35661 thumbnail=1 35662 fi 35663 35664 # Render region boundaries of layout layer, for preview. 35665 +f. "const boundaries = 1; ref(crop(x - 2,y - 2,5,5),V); if (min(V)==max(V),0,i)" 35666 (0,0,0,$cols) r. 3,{$nb_layers+1},1,1,-1 1,100%,1,1,y?255:0 a[-2,-1] x permute. yzcx map.. . rm. 35667 35668 repeat $nb_layers 35669 xmin,ymin,xmax,ymax={-3,I[$>]} 35670 if !isinf($xmin)" && "!isinf($ymin)" && "!isinf($xmax)" && "!isinf($ymax) 35671 xc$>,yc$>={0,0.5*([$xmin,$ymin]+[$xmax,$ymax]-6)*100/[w,h]} 35672 else xc$>,yc$>=-1024 35673 fi 35674 done 35675 35676 mv. -3 35677 boundaries=1 35678 fi 35679 35680 # Render montage. 35681 if iM>0 35682 35683 # Resize layers to fit proposed layout. 35684 repeat $nb_layers 35685 l={$>+1} xmin,ymin,xmax,ymax={-2,I[$>]} 35686 if !isinf($xmin)" && "!isinf($ymin)" && "!isinf($xmax)" && "!isinf($ymax) 35687 dx={$xmax-$xmin+1} 35688 dy={$ymax-$ymin+1} 35689 nw,nh={$l,round(min(w/$dx,h/$dy)*[$dx,$dy]/(1+3*(${zoom$>}/10)^2))} 35690 r[$l] $nw,$nh,1,100%,0,0,{(100-${xcenter$>})%},{(100-${ycenter$>})%} # Centered crop 35691 r[$l] $dx,$dy,1,100%,6 # Resize 35692 else r[$l] 1,1 # Save a bit of memory! 35693 fi 35694 done 35695 35696 # Draw image pixels over layout layer. 35697 to_rgba[0] 35698 f[0] " 35699 l = i#-1; 35700 l1 = l - 1; 35701 l<=0?I:( 35702 xmin = i(#-2,l1,0,0,0); 35703 ymin = i(#-2,l1,0,0,1); 35704 rx = x - xmin; 35705 ry = y - ymin; 35706 crop(#l,rx,ry,0,0,1,1,1,4); 35707 )" 35708 fi 35709 rm[-2,-1] 35710 35711 # Manage preview. 35712 if $boundaries blend[0,-1] alpha fi # Add shape boundaries. 35713 if $thumbnail # Add current layer thumbnail over preview 35714 drgba[0] rr2d[0] ${-gui_preview_wh} 35715 j[0] .,3,3,0,0,0.75 35716 rm. 35717 fi 35718 if $-1 repeat $nb_layers 35719 to "#"{1+$>},${xc$>}%,${yc$>}%,13,1,0.75 35720 done fi 35721 35722 35723 k[0] c 0,255 35724 u $status 35725 35726fx_drawn_montage : 35727 _fx_drawn_montage $*,0 35728 35729fx_drawn_montage_preview : 35730 _fx_drawn_montage $*,1 35731 35732#@gui Extract Objects : fx_extract_objects, fx_extract_objects_preview(1) 35733#@gui : Background Point (%) = point(0,0) 35734#@gui : sep = separator() 35735#@gui : Color Tolerance = int(20,0,256) 35736#@gui : Opacity Threshold (%) = int(50,0,100) 35737#@gui : Minimal Area = float(0.3,0,5) 35738#@gui : Connectivity = choice("Low","High") 35739#@gui : Output As = _choice(0,"Crop","Segmentation") 35740#@gui : sep = separator() 35741#@gui : Preview Guides = bool(1) 35742#@gui : sep = separator() 35743#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/23/02</i>.</small>") 35744#@gui : url = link("Filter explained here","http://gimpchat.com/viewtopic.php?f=28&t=7905") 35745fx_extract_objects : 35746 if $5 min_area=$5% else min_area=6 fi 35747 repeat $! l[$<] to_rgba 35748 nm=${-gui_layer_name} 35749 w={w} h={h} 35750 x={$1%*(w-1)} 35751 y={$2%*(h-1)} 35752 color={I($x,$y)} 35753 if $7==0 # Output: Crop. 35754 +replace_color $3,0,$color,0,0,0,0 autocrop_components. $4%,$min_area,$6,2 35755 repeat w 35756 +z[0] {1,i($>,0)},{1,i($>,1)},{1,i($>,3)},{1,i($>,4)} 35757 nm. pos({1,i($>,0)},{1,i($>,1)}),name($nm" "[$>]) 35758 done rm[0,1] 35759 elif $7==1 # Output: Segmentation. 35760 replace_color $3,0,$color,0,0,0,0 35761 +autocrop_components[0] $4%,$min_area,$6,2 35762 autocrop_components[0] $4%,$min_area,$6,1 35763 repeat w nm[$>] pos({i($>,0)},{i($>,1)}),name($nm" "[$>]) done rm. 35764 fi 35765 $w,$h,1,4 fc. $color nm. name($nm" [background]") 35766 endl done 35767 35768fx_extract_objects_preview : 35769 x0,y0=${1,2} 35770 if $5 min_area=$5% else min_area=5 fi 35771 repeat $! l[$>] to_rgba 35772 x={$x0%*(w-1)} 35773 y={$y0%*(h-1)} 35774 color={I($x,$y)} 35775 +replace_color $3,0,$color,0,0,0,0 35776 autocrop_components. $4%,$min_area,$6,2 35777 repeat w 35778 xycoords={1,i($>,0)},{1,i($>,1)},{1,i($>,3)},{1,i($>,4)} 35779 rectangle[0] $xycoords,0.3,0,0,255,255 35780 rectangle[0] $xycoords,1,0xFFFFFFFF,0,0,0,255 35781 done 35782 drgba[0] 35783 to[0] {w}" objects",2,2,13,2,0.3,255,255,255,255 35784 k[0] 35785 if $8 35786 line 0,$y0%,100%,$y0%,0.5,0xF0F0F0F0,255 line 0,$y0%,100%,$y0%,0.5,0x0F0F0F0F,0 35787 line $x0%,0,$x0%,100%,0.5,0xF0F0F0F0,255 line $x0%,0,$x0%,100%,0.5,0x0F0F0F0F,0 35788 fi 35789 circle $x,$y,3,1,0,255,0 circle $x,$y,3,1,0xFFFFFFFF,0 35790 endl done 35791 35792#@gui Grid [Cartesian] : fx_imagegrid, fx_imagegrid(0) 35793#@gui : X-Size = int(10,2,512) 35794#@gui : Y-Size = int(10,2,512) 35795#@gui : sep = separator() 35796#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35797fx_imagegrid : 35798 imagegrid $1,$2 35799 35800#@gui Grid [Hexagonal] : fx_imagegrid_hexagonal, fx_imagegrid_hexagonal(1) 35801#@gui : Resolution = int(32,1,128) 35802#@gui : Outline = float(0.1,0,0.5) 35803#@gui : Anti-Aliasing = bool(1) 35804#@gui : sep = separator() 35805#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/12/01</i>.</small>") 35806fx_imagegrid_hexagonal : 35807 repeat $! l[$>] 35808 if $3 r 200%,200%,1,100% fi 35809 imagegrid_hexagonal $1,$2 35810 if $3 r 50%,50%,1,100%,2 fi 35811 endl done 35812 35813#@gui Grid [Triangular] : fx_imagegrid_triangular, fx_imagegrid_triangular(0) 35814#@gui : Pattern Width = int(10,8,128) 35815#@gui : Pattern Height = int(18,8,128) 35816#@gui : Pattern Type = choice(0,"Horizontal","Vertical","Crossed","Cube","Decreasing","Increasing") 35817#@gui : Outline Color = color(255,255,255,128) 35818#@gui : sep = separator() 35819#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/08/07</i>.</small>") 35820fx_imagegrid_triangular : 35821 repeat $! l[$>] split_opacity l[0] to_rgb 35822 imagegrid_triangular ${1-3},{$7/255},${4-6} 35823 endl a c endl done 35824 35825#@gui Make Seamless [Diffusion] : fx_make_seamless, fx_make_seamless_preview(1) 35826#@gui : Equalize Light = float(0,0,100) 35827#@gui : sep = separator() 35828#@gui : Preview Original = bool(0) 35829#@gui : Tiled Preview = choice(3,"None","2x1","1x2","2x2","3x3","4x4") 35830#@gui : sep = separator() 35831#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35832#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35833#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35834#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35835#@gui : sep = separator() 35836#@gui : note = note{"<small><b>Note:</b> This filter helps in converting your input pattern as a <b>seamless</b> 35837#@gui : (a.k.a periodic) texture.</small>"} 35838#@gui : sep = separator() 35839#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/24/02</i>.</small>") 35840fx_make_seamless : 35841 repeat $! l[$>] 35842 if $1 +b {20.5-$1/50}% -[0] [1] fc. ${average_colors.} + fi 35843 endl done 35844 periodize_poisson c 0,255 35845 35846fx_make_seamless_preview : 35847 u={arg($3,2,1,2,3,4)} v={arg($3,1,2,2,3,4)} 35848 gui_split_preview "if !$2 fx_make_seamless $* fi if $3 array "$u","$v" fi",${-3--1} 35849 35850#@gui Make Seamless [Patch-Based] : fx_frame_seamless, fx_frame_seamless_preview(0) 35851#@gui : Frame Size = int(32,0,256) 35852#@gui : Patch Size = int(9,3,64) 35853#@gui : Blend Size = int(0,0,64) 35854#@gui : Frame Type = choice(1,"Inner","Outer") 35855#@gui : Equalize Light = float(100,0,100) 35856#@gui : sep = separator() 35857#@gui : Preview Original = bool(0) 35858#@gui : Tiled Preview = choice(3,"None","2x1","1x2","2x2","3x3","4x4") 35859#@gui : sep = separator() 35860#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35861#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35862#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35863#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35864#@gui : sep = separator() 35865#@gui : note = note{"<small><b>Note:</b> This filter helps in converting your input pattern as a <b>seamless</b> 35866#@gui : (a.k.a periodic) texture.</small>"} 35867#@gui : sep = separator() 35868#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/15/12</i>.</small>") 35869fx_frame_seamless : 35870 repeat $! l[$>] 35871 if $5 +b {20.5-$5/50}% -[0] [1] fc. ${average_colors.} + fi 35872 endl done 35873 frame_seamless ${1-4} c 0,255 35874 35875fx_frame_seamless_preview : 35876 u={arg($7,2,1,2,3,4)} v={arg($7,1,2,2,3,4)} 35877 gui_split_preview "if !$6 fx_frame_seamless $* fi if $7 array "$u","$v" fi",${-3--1} 35878 35879#@gui Ministeck : fx_ministeck, fx_ministeck_preview(1) 35880#@gui : Number of Colors = int(8,2,24) 35881#@gui : Resolution (px) = int(64,16,256) 35882#@gui : Piece Size (px) = int(8,1,64) 35883#@gui : Piece Complexity = int(2,1,10) 35884#@gui : Relief Amplitude = float(100,0,256) 35885#@gui : Relief Size = float(0.3,0,1) 35886#@gui : Add 1px Outline = bool(0) 35887#@gui : sep = separator() 35888#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/14/01</i>.</small>") 35889fx_ministeck : 35890 repeat $! l[$>] 35891 if w>h r2dx {min($2,w)} else r2dy {min($2,h)} fi 35892 split_opacity l[0] 35893 +colormap. $1 index.. . 35894 [0],[0],1,1 rand[2] 0,1 dilate[2] $4 +[0,2] 35895 r[0] $3""00%,$3""00% 35896 +g[0] xy,1 !=[-2,-1] 0 +f[0] 'i(x+1,y+1)-i(x,y)' !=[-3--1] 0 -|[-3--1] 35897 z[0,-1] 0,0,{w-2},{h-2} 35898 if $7 . fi 35899 +shift. 1,1 *.. -1 +[-2,-1] b. {$6*$3/5} n. -$5,$5 35900 map[0] [1] rm[1] +[0,-1] 35901 if $7 ==[1] 0 * fi 35902 endl r. [0],[0],1,100% a c 35903 endl done 35904 c 0,255 35905 35906fx_ministeck_preview : 35907 repeat $! l[$>] 35908 w={w} h={h} 35909 fx_ministeck $* 35910 r $w,$h,1,100%,0,0,0.5,0.5 35911 endl done 35912 35913#@gui Montage : fx_montage, fx_montage_preview(1) : * 35914#@gui : Montage Type = choice("Auto","Custom Layout","Horizontal","Vertical","Horizontal Array","Vertical Array") 35915#@gui : Custom Layout = text{"V(H(0,1),H(2,V(3,4)))"} 35916#@gui : Merging Mode = choice(1,"Aligned","Scaled") 35917#@gui : Centering / Scale = float(0.5,0,1) 35918#@gui : Padding (px) = int(0,0,128) 35919#@gui : sep = separator() 35920#@gui : Frame (px) = int(0,0,128) 35921#@gui : Frame Color = color(0,0,0,255) 35922#@gui : sep = separator() 35923#@gui : Angle = float(0,0,360) 35924#@gui : Angle Variations = float(0,0,180) 35925#@gui : sep = separator() 35926#@gui : Cycle Layers = int(0,-255,255) 35927#@gui : Revert Layer Order = bool() 35928#@gui : Output As = _choice("Single Layer","Multiple Layers") 35929#@gui : sep = separator() 35930#@gui : note = note{"<small><b>Instructions:</b>\n 35931#@gui : - Don't forget to set the <i>Input layers...</i> option on the left if you have multiple input layers 35932#@gui : for your montage.\n 35933#@gui : - The <i>Custom layout</i> parameter is only active when <i>Montage type</i> is set to <i>Custom layout</i>. 35934#@gui : This is basically a string containing expressions such as:\n 35935#@gui : \n . <i>H(a,b)</i> or <i>V(a,b)</i> stand respectively for an horizontal and vertical merge of two 35936#@gui : blocks <i>a</i> and <i>b</i>. 35937#@gui : \n . <i>R(a)</i>, stands for a 90-deg. rotated version of a block <i>a</i>. Use <i>RR(a)</i> and 35938#@gui : <i>RRR(a)</i> for resp. 180-deg and 270-deg. rotations. 35939#@gui : \n . <i>M(a)</i>, stands for a X-mirrored version of a block <i>a</i>. Use <i>MRR(a)</i> for a Y-mirrored 35940#@gui : version of <i>a</i>.\n\n 35941#@gui : - A block <i>a</i> can be a layer index or a nested montage expression itself.\n 35942#@gui : - Layer indices start from <i>0 (top layer)</i> and are treated periodically. 35943#@gui : </small>"} 35944#@gui : url = link("Click here for a tutorial","https://patdavid.net/2014/05/gmic-montage.html") 35945#@gui : url = link("+ video tutorial","http://www.youtube.com/watch?v=iM42vx22gwg") 35946#@gui : sep = separator() 35947#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/22/12</i>.</small>") 35948fx_montage : skip "${2=A}" 35949 if !$! return fi 35950 code0=X code1="$2" code2=H code3=V code4=A code5=B 35951 if $3==1" && "$4<0.5 r {max(10,$4*200)}%,{max(10,$4*200)}%,1,100%,2 fi 35952 to_rgba if $14 rv fi if $13%$! mv[{$13%$!}--1] 0 fi 35953 if $11" || "$12 repeat $! rotate[$>] {$11+u(-$12,$12)},1,0 done fi 35954 montage ${code$1},{if($3==0,$4,2+max(0,$4-0.5))},$15,\ 35955 "if $""7%2 mirror x fi if $""8%2 mirror y fi "\ 35956 "rotate {90*$""6} "\ 35957 "if $5||$6 "\ 35958 "r {max(1,$""4-2*($5+$6))},{max(1,$""5-2*($5+$6))},1,100%,2 "\ 35959 "frame $6,$6,${7-10} "\ 35960 "r {w+2*$5},{h+2*$5},1,100%,0,0,0.5,0.5 "\ 35961 "else r $""4,$""5,1,100%,2 fi " 35962 if $15 gui_autocrop_layers fi 35963 gui_set_layer_name "[Montage]" 35964 35965fx_montage_preview : skip "${2=A}" 35966 if !$! return fi 35967 w={w} h={h} 35968 if $3==1" && "$4<0.5 r {max(10,$4*200)}%,{max(10,$4*200)}%,1,100%,2 fi 35969 drgba 35970 code0=X code1="$2" code2=H code3=V code4=A code5=B 35971 to_rgba if $14 rv fi if $13%$! mv[{$13%$!}--1] 0 fi 35972 if $11" || "$12 repeat $! rotate[$>] {$11+u(-$12,$12)},1,0 done fi 35973 montage ${code$1},{if($3==0,$4,2+max(0,$4-0.5))},0,\ 35974 "if $""7%2 mirror x fi if $""8%2 mirror y fi 35975 rotate {90*$""6} 35976 if $5||$6 35977 r {max(1,$""4-2*($5+$6))},{max(1,$""5-2*($5+$6))},1,100%,2 fs={min(53,max(w,h)/3)} 35978 frame $6,$6,${7-10} 35979 r {w+2*$5},{h+2*$5},1,100%,0,0,0.5,0.5 35980 0 t. \\\#$""1,0,0,$fs,1,255 expand_xy. 3,0 [-1]x3 a[-4--2] c 35981 dilate. {3+2*$fs/20} a.. .,c j[0] [1],{5+$5+$6},{$5+$6},0,0,1,[2],255 k[0] 35982 else 35983 r $""4,$""5,1,100%,2 fs={min(53,max(w,h)/3)} 35984 0 t. \\\#$""1,0,0,$fs,1,255 expand_xy. 3,0 [-1]x3 a[-4--2] c 35985 dilate. {3+2*$fs/20} a.. .,c j[0] [1],5,0,0,0,1,[2],255 k[0] 35986 fi " 35987 nw={w} nh={h} 35988 resize_ratio2d $w,{$h-16},2,2 35989 drgba 35990 i[0] 100%,15,1,3,240 t[0] "Estimated size : "{round(100*$nw/$w)}%" x "{round(100*$nh/$h)}%,2,0,16 r[0] 100%,16,1,3,0 35991 a y 35992 35993#@gui Puzzle : fx_puzzle, fx_puzzle_preview(1) 35994#@gui : note = note("<small><b>Pattern parameters:</b></small>") 35995#@gui : X-Tiles = int(5,2,32) 35996#@gui : Y-Tiles = int(5,2,32) 35997#@gui : Curvature = float(0.5,0,1.5) 35998#@gui : Connectors Centering = float(0,0,1) 35999#@gui : Connectors Variability = float(0,0,2) 36000#@gui : sep = separator() 36001#@gui : note = note("<small><b>Blending parameters:</b></small>") 36002#@gui : Relief Smoothness = float(0.3,0,3) 36003#@gui : Relief Contrast = float(100,0,255) 36004#@gui : Outline Smoothness = float(0.2,0,3) 36005#@gui : Outline Contrast = float(255,0,255) 36006#@gui : sep = separator() 36007#@gui : note = note("<small><b>Recomposition parameters:</b></small>") 36008#@gui : Scale = float(100,0,150) 36009#@gui : Scale Variations = float(0,0,100) 36010#@gui : Angle = float(0,-180,180) 36011#@gui : Angle Variations = float(0,0,180) 36012#@gui : Shuffle Pieces = bool(0) 36013#@gui : Additional Outline = bool(0) 36014#@gui : Output Each Piece on a Different Layer = _bool(0) 36015#@gui : sep = separator() 36016#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/06/01</i>.</small>") 36017fx_puzzle : 36018 repeat $! l[$<] 36019 w={w} h={h} to_rgb 36020 puzzle $w,$h,$1,$2,$3,$4,$5 36021 +b. $6%,0 g. xy +[-2,-1] n. -$7,$7 +[0,-1] # Relief. 36022 +b. $8%,0 n. 0,1 *. -1 +. 1 n. {(255-$9)/255},1 *[0,-1] c 0,255 # Outline. 36023 36024 if $10!=100||$11||$12||$13||$14||$15||$16 36025 36026 # Decompose puzzle into set of pieces. 36027 +-. 1 label_fg. 0 36028 +area_fg. 0,0 <. 50% -|... . ==. 0 *[-2,-1] 36029 distance.. 0 *.. -1 watershed. .. rm.. label. 0,0 36030 36031 repeat iM+1 36032 +==[1] $> 36033 coords=${autocrop_coords.\ 0} 36034 +z[0] $coords z.. $coords rv[-2,-1] *.. . *. 255 a[-2,-1] c 36035 x$>={arg(1,$coords)+round(w/2)} y$>={arg(2,$coords)+round(h/2)} 36036 done 36037 rm[0,1] 36038 36039 # Recompose puzzle. 36040 if $14 sort_list +,u fi 36041 36042 if $16 # One piece by layer. 36043 repeat $! l[$<] 36044 r2dy {max(0.1,$10+$11*u(-1,1))}% rotate {$12+$13*u(-1,1)} 36045 if $15 expand_xy 1,0 fi 36046 cx={round(w/2)} cy={round(h/2)} 36047 sh 100% if $15 dilate. 3 fi 36048 i[0] $w,$h,1,4 36049 j[0] ..,{${x$<}-$cx},{${y$<}-$cy},0,0,1,.,255 rm[-2,-1] 36050 endl done 36051 36052 else # All pieces on the same layer. 36053 i[0] $w,$h,1,{s} 36054 repeat $!-1 36055 r2dy. {max(0.1,$10+$11*u(-1,1))}% rotate. {$12+$13*u(-1,1)} 36056 if $15 expand_xy. 1,0 fi 36057 cx={round(w/2)} cy={round(h/2)} 36058 sh. 100% if $15 dilate. 3 fi 36059 j[0] ..,{${x$<}-$cx},{${y$<}-$cy},0,0,1,.,255 rm[-2,-1] 36060 done 36061 fi 36062 36063 else rm. 36064 fi 36065 endl done 36066 36067fx_puzzle_preview : 36068 fx_puzzle ${1-15},0 36069 36070#@gui Taquin : fx_taquin, fx_taquin(1) 36071#@gui : X-Tiles = int(7,1,20) 36072#@gui : Y-Tiles = int(7,1,20) 36073#@gui : Remove Tile = choice("None","First","Last","Random") 36074#@gui : sep = separator() 36075#@gui : Relief = float(50,0,255) 36076#@gui : Border Thickness (%) = float(5,0,100) 36077#@gui : Border Outline = int(0,0,16) 36078#@gui : Ouline Color = color(0,0,0,255) 36079#@gui : sep = separator() 36080#@gui : Random Seed = int(0,0,65535) 36081#@gui : sep = separator() 36082#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/13/01</i>.</small>") 36083fx_taquin : 36084 to_a repeat $! l[$>] srand $11 taquin $1,$2,$3,$4,$5%,$6,${7-10} endl done 36085 36086#@gui Tileable Rotation : fx_rotate_tileable, fx_rotate_tileable_preview(1) 36087#@gui : Angle = float(45,0,360) 36088#@gui : Maximum Size Factor = int(8,0,20) 36089#@gui : Array Mode = choice(0,"None","x-axis","y-axis","xy-axes","2xy-axes") 36090#@gui : sep = separator() 36091#@gui : note = note("<small><b>Note:</b> This filter implements the tileable rotation technique described by 36092#@gui : <b>Peter Yu</b>, at:</small>") 36093#@gui : url = link("[Peter Yu] Create rotated tileable patterns", 36094#@gui : "http://www.peteryu.ca/tutorials/gimp/rotate_tileable_patterns") 36095#@gui : sep = separator() 36096#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/26/05</i>.</small>") 36097fx_rotate_tileable : 36098 if $3 array_mirror 1,{$3-1},1 fi 36099 rotate_tileable $1,{if($3==0,$2,$2/2)} 36100 36101fx_rotate_tileable_preview : 36102 l fx_rotate_tileable $* 36103 onfail gui_warning_preview "Invalid image size" endl 36104 36105#@gui Tiled Rotation : fx_rotate_tiles, fx_rotate_tiles(1) 36106#@gui : X-Tiles = int(5,1,80) 36107#@gui : Y-Tiles = int(5,1,80) 36108#@gui : Angle = float(15,0,360) 36109#@gui : X-Shadow = float(3,-20,20) 36110#@gui : Y-Shadow = float(3,-20,20) 36111#@gui : Smoothness = float(1.8,0,5) 36112#@gui : sep = separator() 36113#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36114fx_rotate_tiles : 36115 to_rgba rotate_tiles $3,$1,$2 drop_shadow $4%,$5%,$6% 36116 36117#@gui Tiled Normalization : fx_normalize_tiles, fx_normalize_tiles(1) 36118#@gui : X-Tiles = int(25,1,80) 36119#@gui : Y-Tiles = int(25,1,80) 36120#@gui : Minimal Value = float(0,0,255) 36121#@gui : Maximal Value = float(255,0,255) 36122#@gui : sep = separator() 36123#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 36124#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 36125#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 36126#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 36127#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 36128#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 36129#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 36130#@gui : sep = separator() 36131#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36132_fx_normalize_tiles : 36133 repeat $! l. split_tiles $1,$2 n $3,$4 append_tiles $1,$2 endl mv. 0 done 36134 36135fx_normalize_tiles : 36136 ac "_fx_normalize_tiles ${1-4}",$-1 36137 36138#@gui Tiled Random Shifts : fx_shift_tiles, fx_shift_tiles(1) 36139#@gui : X-Tiles = int(10,1,30) 36140#@gui : Y-Tiles = int(10,1,30) 36141#@gui : Amplitude = float(10,0,100) 36142#@gui : Opacity = float(1,0,1) 36143#@gui : sep = separator() 36144#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36145fx_shift_tiles : 36146 to_rgba shift_tiles $1,$2,$3 36147 if $4<1 repeat $! s. c *. $4 a[-4--1] c mv. 0 done fi 36148 36149#@gui Tiled Parameterization : fx_parameterize_tiles, fx_parameterize_tiles(1) 36150#@gui : X-Tiles = int(10,1,30) 36151#@gui : Y-Tiles = int(10,1,30) 36152#@gui : Fitting Function = choice("Linear","Quadratic") 36153#@gui : sep = separator() 36154#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36155fx_parameterize_tiles : 36156 if $3 36157 quadratize_tiles $1,$2 36158 else 36159 linearize_tiles $1,$2 36160 fi 36161 c 0,255 36162 36163#@gui Tiled Isolation : fx_isolate_tiles, fx_isolate_tiles(0) 36164#@gui : X-Size = float(10,0,100) 36165#@gui : Y-Size = float(10,0,100) 36166#@gui : X-Border = float(5,0,100) 36167#@gui : Y-Border = float(5,0,100) 36168#@gui : Keep Tiles Square = bool(1) 36169#@gui : Keep Borders Square = bool(1) 36170#@gui : sep = separator() 36171#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/13/04</i>.</small>") 36172fx_isolate_tiles : 36173 repeat $! l[$>] to_rgba 36174 if $5 sx={round(min(w,h)*max($1,$2)/100)} sy=$sx else sx={round(w*$1/100)} sy={round(h*$2/100)} fi 36175 if $6 bx={max($3,$4)} by=$bx else bx=$3 by=$4 fi 36176 s x,-$sx 36177 repeat $! l[$>] s y,-$sy r 100%,{100+$by}%,1,100%,0,0,0.5,0.5 a y endl done 36178 r {100+$bx}%,100%,1,100%,0,0,0.5,0.5 a x 36179 endl done 36180 36181 36182#@gui ____<b>Artistic</b> 36183#------------------------- 36184 36185#@gui Bokeh : fx_bokeh, fx_bokeh_preview(1) 36186#@gui : Number of Scales = int(3,1,10) 36187#@gui : Shape = choice(8,"Triangle","Square","Diamond","Pentagon","Hexagon","Octogon","Decagon","Star","Circular") 36188#@gui : Random Seed = int(0,0,65535) 36189#@gui : sep = separator() 36190#@gui : note = note{"<small><b>Starting parameters:</b></small>"} 36191#@gui : Density = int(30,1,256) 36192#@gui : Radius (%) = float(8,0,50) 36193#@gui : Outline (%) = float(4,0,100) 36194#@gui : Inner Shade = float(0.3,0,1) 36195#@gui : Smoothness = float(0.2,0,8) 36196#@gui : Color = color(210,210,80,160) 36197#@gui : Color Dispersion = float(0.7,0,1) 36198#@gui : sep = separator() 36199#@gui : note = note{"<small><b>Ending parameters:</b></small>"} 36200#@gui : Density = int(30,1,256) 36201#@gui : Radius (%) = float(20,0,50) 36202#@gui : Outline (%) = float(20,0,100) 36203#@gui : Inner Shade = float(1,0,1) 36204#@gui : Smoothness = float(2,0,8) 36205#@gui : Color = color(170,130,20,110) 36206#@gui : Color Dispersion = float(0.15,0,1) 36207#@gui : sep = separator() 36208#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36209#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36210#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36211#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36212#@gui : sep = separator() 36213#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/02/07</i>.</small>") 36214fx_bokeh : 36215 _shape=$2 36216 srand $3 36217 repeat $! l[$<] nm=${-gui_layer_name} pos=${-gui_layer_pos} 36218 100%,100%,1,3 36219 (${4-13};${14-23}) if $1>2 r. 100%,$1,1,1,3 fi 36220 repeat $1 36221 +rows. $> _fx_bokeh... {^} rm. 36222 done 36223 rm. nm. name($nm),opacity(100),mode(screen),pos($pos) 36224 rv 36225 if 0$_output_mode==0 gui_merge_layers 36226 elif 0$_output_mode<2 rm. 36227 fi 36228 endl done 36229 36230_fx_bokeh0 : shape_star $1,3 # Triangle. 36231_fx_bokeh1 : $1,$1,1,1,1 # Square. 36232_fx_bokeh2 : shape_diamond $1 # Diamond. 36233_fx_bokeh3 : shape_polygon $1,5,45 # Pentagon. 36234_fx_bokeh4 : shape_polygon $1,6,45 # Hexagon. 36235_fx_bokeh5 : shape_polygon $1,8,45 # Octogon. 36236_fx_bokeh6 : shape_polygon $1,10,45 # Decagon. 36237_fx_bokeh7 : shape_star $1,5 # Star. 36238_fx_bokeh8 : shape_circle $1 # Circle. 36239 36240fx_bokeh_preview : 36241 gui_split_preview "_output_mode=0 fx_bokeh $*",${-3--1} 36242 36243# [internal] Draw one step of bokeh with specified geometry on last image. 36244# $1=density, $2=size(in %), $3=outline(in %), $4=shade (in [0,1]), $5=smoothness (in %), 36245# $6,$7,$8,$9=RGBA (in [0,255]), $10 = color dispersion (in [0,1]) 36246_fx_bokeh : 36247 radius1={r=max(w,h)*$2%;r+1-(r%2)} 36248 radius2={r=$radius1-($radius1*$3%);r+1-(r%2)} 36249 36250 random3d $1 *3d. {-2,w},{-2,h},0 36251 _fx_bokeh$_shape $radius1 36252 if $radius2>=1 _fx_bokeh$_shape $radius2 ri. ..,0,0,0.5,0.5 *. {max(0,min(1,1-$4))} -[-2,-1] fi 36253 sigma={-3,$5%*w} 36254 r. {w+5*$sigma},{h+5*$sigma},1,1,0,0,0.5,0.5 36255 b. $sigma,0 n. 0,255 36256 sprites3d[1] [2],1 rm[2] 36257 l. 36258 s3d r.. 3,{-2,h/3},1,1,-1 s.. x 36259 d={$10*255} 36260 rand[-4] {$6-$d},{$6+$d} 36261 rand... {$7-$d},{$7+$d} 36262 rand.. {$8-$d},{$8+$d} 36263 a[-4--2] x c.. 0,255 y a y 36264 endl 36265 j3d[0] [1],0,0,0,{$9/255},1,0,0 rm[1] 36266 36267#@gui Brushify : fx_brushify, fx_brushify_preview(0) 36268#@gui : note = note("<small><b>Brush parameters:</b></small>") 36269#@gui : Shape = choice(7,"Bottom layer","Top layer","Rectangle","Diamond","Pentagon","Hexagon","Octogon", 36270#@gui : "Ellipse","Gaussian","Star","Heart") 36271#@gui : Ratio = float(0.25,0,1) 36272#@gui : Number of Sizes = int(4,1,16) 36273#@gui : Maximal Size = int(64,1,128) 36274#@gui : Minimal Size (%)= float(25,0,100) 36275#@gui : Number of Orientations = int(12,1,24) 36276#@gui : Fuzzyness = float(0,0,10) 36277#@gui : Smoothness = float(2,0,10) 36278#@gui : Light Type = choice(4,"None","Flat","Darken","Lighten","Full") 36279#@gui : Light Strength = float(0.2,0,1) 36280#@gui : Opacity = float(0.5,0,1) 36281#@gui : sep = separator() 36282#@gui : note = note("<small><b>Painting parameters:</b></small>") 36283#@gui : Density (%) = float(30,0,100) 36284#@gui : Contour Coherence = float(1,0,1) 36285#@gui : Orientation Coherence = float(1,0,1) 36286#@gui : Gradient Smoothness = float(1,0,10) 36287#@gui : Structure Smoothness = float(5,0,10) 36288#@gui : Primary Angle = float(0,-180,180) 36289#@gui : Angle Dispersion = float(0.2,0,1) 36290#@gui : sep = separator() 36291#@gui : Preview Brush = bool(1) 36292#@gui : sep = separator() 36293#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/22/04</i>.</small>") 36294fx_brushify : 36295 _fx_brushify $* 36296 s0=0--3 s1=1--2 s2=0--2 36297 l[${s{$1==0?0:$1==1?1:2}},-1] brushify[^-1] .,$3,{$5%},$6,$9,$10,$11,$12%,$13,$14,$15,$16,$17,$18 rm. endl 36298 36299_fx_brushify : # Insert brush at the end of the list 36300 N={0.9*$4} 36301 if $1==0 +autocrop. i.. 100%,100%,1,3,1 blend[-2,-1] alpha rr2d. $N,$N,0,3 36302 elif $1==1 +autocrop[0] i.. 100%,100%,1,3,1 blend[-2,-1] alpha rr2d. $N,$N,0,3 36303 elif $1==2 $4,$4 rectangle. 10%,10%,90%,90%,1,1 36304 elif $1==3 shape_diamond. $N 36305 elif $1==4 shape_polygon $N,5 36306 elif $1==5 shape_polygon $N,6 36307 elif $1==6 shape_polygon $N,8 36308 elif $1==7 shape_circle. $N 36309 elif $1==8 $4,$4 gaussian. 30%,30%,0 36310 elif $1==9 shape_star $N 36311 elif $1==10 shape_heart $N 36312 fi 36313 norm. r. 100%,{max(0.01,100*$2)}%,1,1,2 r. $4,$4,1,1,0,0,0.5,0.5 36314 spread. $7 b. $8% n. 0,1 36315 36316fx_brushify_preview : 36317 if $1<2" && "$!<2 36318 gui_error_preview "When a custom brush (bottom or top layer) is specified, at least two layers are required 36319 for this filter to work.In this case, don't forget to set the 'Input layers' option!" 36320 return 36321 fi 36322 fx_brushify $* 36323 if $19 36324 _fx_brushify $* 36325 if $1==0 rm.. elif $1==1 rm[0] fi 36326 rr2d. {0,max(1,w/5)},{0,max(1,h/5)},0,2 n. 0,255 36327 frame. 3,3,0 frame. 1,1,255 frame. 1,1,0 36328 to_rgb. to. "Brush",4,2,13,2,1,255,255,0 to_a. 36329 j[^-1] .,2,2 rm. 36330 else 36331 if $1==0 rm. elif $1==1 rm[0] fi 36332 fi 36333 36334#@gui Cartoon : cartoon, fx_cartoon_preview(0) 36335#@gui : Smoothness = float(3,0,10) 36336#@gui : Sharpening = float(200,0,400) 36337#@gui : Edge Threshold = float(20,1,30) 36338#@gui : Edge Thickness = float(0.25,0,1) 36339#@gui : Color Strength = float(1.5,0,3) 36340#@gui : Color Quantization = int(8,2,256) 36341#@gui : sep = separator() 36342#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36343#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36344#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36345#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36346#@gui : sep = separator() 36347#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36348fx_cartoon_preview : 36349 gui_split_preview "cartoon $*",${-3--1} 36350 36351#@gui Circle Abstraction : fx_circle_abstraction, fx_circle_abstraction_preview(1) 36352#@gui : Number of Colors = int(8,2,16) 36353#@gui : Density = int(5,1,100) 36354#@gui : Opacity = float(0.8,0,1) 36355#@gui : Smoothness = float(0,0,4) 36356#@gui : Filled Circles = bool(1) 36357#@gui : Fill Transparent Holes = bool(1) 36358#@gui : Normalize Colors = bool(1) 36359#@gui : sep = separator() 36360#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36361#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36362#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36363#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36364#@gui : sep = separator() 36365#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/16/06</i>.</small>") 36366fx_circle_abstraction : 36367 repeat $! l[$>] 36368 b $4% 36369 +colormap $1 index[0] [1],0,0 36370 [0],[0],1,4,0 36371 36372 repeat $1 36373 rprogress {$>*100/$1} 36374 +==[0] $> 36375 skeleton3d. 2,2,0,1,0 36376 if {@7} # Process only non empty objects. 36377 s3d. l[-6--1] 36378 r[2] 3,{2,h/3},1,1,-1 36379 1,{2,h/2*$2%},1,1,1 r. 1,{2,h/2},1,1,4 r. 3,200% *[2,-1] y 36380 endl 36381 a[-6--1] y col3d. {1,I($>)} 36382 36383 [0],[0],1,4,0 36384 j3d. ..,0,0,0,1,{1+$5},0,0 36385 sh. 3 col3d... 255 j3d. ...,0,0,0,$3,{1+$5},0,0 rm. 36386 rm.. 36387 blend[2,-1] alpha 36388 fi 36389 done 36390 k[2] 36391 if $6 +channels 3 <. 1 inpaint[0] [1],0,1 rm. channels. 0,2 fi 36392 if $7 n 0,255 fi 36393 rprogress 100 36394 endl done 36395 36396fx_circle_abstraction_preview : 36397 gui_split_preview "fx_circle_abstraction $*",${-3--1} 36398 36399#@gui Cubism : fx_cubism, fx_cubism_preview(1) 36400#@gui : Iterations = int(2,0,10) 36401#@gui : Density = float(50,0,200) 36402#@gui : Thickness = float(10,0,50) 36403#@gui : Angle = float(90,0,360) 36404#@gui : Opacity = float(0.7,0.01,1) 36405#@gui : Smoothness = float(0,0,5) 36406#@gui : sep = separator() 36407#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36408#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36409#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36410#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36411#@gui : sep = separator() 36412#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/05/06</i>.</small>") 36413fx_cubism : 36414 repeat $1 cubism ${2--1} done 36415 36416fx_cubism_preview : 36417 gui_split_preview "fx_cubism $*",${-3--1} 36418 36419#@gui Cutout : fx_cutout, fx_cutout_preview(1) 36420#@gui : Number of Levels = int(4,2,32) 36421#@gui : Edge Simplicity = float(0.5,0,3) 36422#@gui : Edge Fidelity = int(4,0,10) 36423#@gui : Normalize = bool(1) 36424#@gui : sep = separator() 36425#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36426#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36427#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36428#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36429#@gui : sep = separator() 36430#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Garagecoder</i> 36431#@gui : Latest Update: <i>2014/03/06</i>.</small>") 36432fx_cutout : 36433 repeat $! l[$>] split_opacity l[0] 36434 median {10-$3} 36435 quantize $1 36436 +luminance. round. area. 0,1 med={ic} rm. 36437 inpaint_holes {$med*$2%},0,1 36438 if $4 n 0,255 fi 36439 endl a c endl done 36440 36441fx_cutout_preview : 36442 gui_split_preview "fx_cutout $*",${-3--1} 36443 36444#@gui Doodle : fx_doodle, gui_no_preview(0) 36445#@gui : Precision (%) = float(30,0,100) 36446#@gui : Smoothness = float(2,0,10) 36447#@gui : Coherence = float(2,0,10) 36448#@gui : Contour Threshold = float(1.5,0,10) 36449#@gui : Spacing = int(2,0,20) 36450#@gui : Minimal Stroke Length = float(70,0,255) 36451#@gui : Preview Progression While Running = _bool(1) 36452#@gui : sep = separator() 36453#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/07/08</i>.</small>") 36454fx_doodle : skip "$*" 36455 repeat $! l[$>] 36456 b $2 n 0,255 structuretensors b $3 36457 100%,100%,1,1,100 36458 if $7 w. ${"fitscreen ."},"[G'MIC] Doodle" fi 36459 36460 _stopflag=0 36461 eval " 36462 const dt = 0.5; 36463 nb_strokes = nb_consecutive_fails = 0; 36464 36465 while (nb_consecutive_fails<500*$1%, 36466 run('+store. canvas'); 36467 36468 P0 = u([w,h] - 1); 36469 length = 0; 36470 36471 repeat (2,dir, 36472 P = P0; 36473 oiP = iP = round(P); 36474 C = I(#0,P); E = eig([ C[0], C[1], C[1], C[2] ]); oV = V = (dir?1:-1)*E[4,2]; 36475 36476 while (E[0]>$4^2 && (i(iP)>$5 || oiP==iP), 36477 i(iP) = 0; 36478 oiP = iP; 36479 P+=dt*V; 36480 iP = round(P); 36481 C = I(#0,P,1); E = eig([ C[0], C[1], C[1], C[2] ]); V = E[4,2]; 36482 dot(oV,V)<0?(V*=-1); 36483 oV = V; 36484 iP!=oiP?++length; 36485 ); 36486 ); 36487 length<$6?(run('rm. $canvas'); ++nb_consecutive_fails):( 36488 !(++nb_strokes%15)?run('distance. 0'); 36489 nb_consecutive_fails = 0; 36490 $7 && !(nb_strokes%30)?( 36491 nb_consecutive_fails = run('if !{*} u inf else +neq. 0 r. {*,w,h},1,1,2 w. rm. u 0 fi') 36492 ); 36493 ) 36494 )" 36495 k. != 0 * 255 36496 endl done 36497 36498#@gui Diffusion Tensors : fx_diffusiontensors, fx_diffusiontensors_preview(0) 36499#@gui : Resolution (%) = float(10,0,20) 36500#@gui : Size = float(5,0,16) 36501#@gui : Color Mode = choice(3,"Monochrome","Grayscale","Orientation","Color") 36502#@gui : Outline = int(1,0,16) 36503#@gui : sep = separator() 36504#@gui : Sharpness = float(0.15,0,1) 36505#@gui : Anisotropy = float(1,0,1) 36506#@gui : Gradient Smoothness = float(0,0,10) 36507#@gui : Tensor Smoothness = float(3,0,10) 36508#@gui : sep = separator() 36509#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36510#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36511#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36512#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36513#@gui : sep = separator() 36514#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/19/10</i>.</small>") 36515fx_diffusiontensors : 36516 repeat $! l[$>] 36517 wh={[w,h]} 36518 +diffusiontensors ${5-8} 36519 r2dx. {max(1,w*$1%)} 36520 dt. {round(125/max(1,$1))},$2,{$3<3?$3:0},$4 36521 if $3==3 36522 remove_opacity.. r.. .,.,1,100%,3 blend[0] [1],shapeaverage0 dilate. {1+2*$4} a c 36523 else k. fi 36524 r. $wh,1,100%,2 36525 endl done 36526 36527fx_diffusiontensors_preview : 36528 gui_split_preview "fx_diffusiontensors $*",${-3--1} 36529 36530#@gui Ellipsionism : fx_ellipsionism, fx_ellipsionism_preview(0) 36531#@gui : Primary Radius = float(20,1,100) 36532#@gui : Secondary Radius = float(10,1,100) 36533#@gui : Smoothness = float(0.5,0,10) 36534#@gui : Opacity = float(0.7,0,1) 36535#@gui : Outline = float(3,1,3) 36536#@gui : Density = float(0.5,0.1,2) 36537#@gui : sep = separator() 36538#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36539#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36540#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36541#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36542#@gui : sep = separator() 36543#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36544fx_ellipsionism : 36545 ellipsionism ${^0} 36546 36547fx_ellipsionism_preview : 36548 gui_split_preview "fx_ellipsionism $*",${-3--1} 36549 36550#@gui Felt Pen : fx_feltpen, fx_feltpen_preview(0) 36551#@gui : Amplitude = float(300,0,4000) 36552#@gui : Density = float(50,0,100) 36553#@gui : Smoothness = float(1,0,10) 36554#@gui : Opacity = float(0.1,0,1) 36555#@gui : Edge = float(20,0,100) 36556#@gui : Thickness = int(5,2,32) 36557#@gui : sep = separator() 36558#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36559#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36560#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36561#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36562#@gui : sep = separator() 36563#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/25/10</i>.</small>") 36564fx_feltpen : 36565 repeat $! l[$>] +fx_hardsketchbw ${1-5},0,0 blend hardlight erode_oct $6 endl done 36566 36567fx_feltpen_preview : 36568 gui_split_preview "fx_feltpen $*",${-3--1} 36569 36570#@gui Fractalize : fractalize, fractalize(1) 36571#@gui : Detail Level = float(0.8,0,1) 36572#@gui : sep = separator() 36573#@gui : note = note("<small><b>Note:</b> This filter uses lot of random values to generate its result, 36574#@gui : so running it twice will give you different results !</small>") 36575#@gui : sep = separator() 36576#@gui : url = link("Click here for a detailed description of this filter.",\ 36577# "http://www.gimpchat.com/viewtopic.php?f=28&t=10036") 36578#@gui : sep = separator() 36579#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/25/04</i>.</small>") 36580 36581#@gui Ghost : fx_ghost, fx_ghost_preview(0) 36582#@gui : note = note("<small><b>Ghost Effect:</b></small>") 36583#@gui : Amplitude = float(200,0,1000) 36584#@gui : Smoothness = float(2,0,10) 36585#@gui : Coherence = float(2,0,10) 36586#@gui : Gamma = float(1,-3,3) 36587#@gui : sep = separator() 36588#@gui : note = note("<small><b>Normalization:</b></small>") 36589#@gui : Amplitude = float(3,0,10) 36590#@gui : Radius = float(16,1,64) 36591#@gui : Invert = bool(0) 36592#@gui : sep = separator() 36593#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36594#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36595#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36596#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36597#@gui : sep = separator() 36598#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/01/30</i>.</small>") 36599fx_ghost : 36600 repeat $! l[$>] split_opacity l[0] 36601 diffusiontensors. 1,1,$2,$3 eigen. compose_channels.. + sqrt.. n.. 1,100 pow.. $4 n.. 0,$1 36602 100%,100% 36603 eval.. "* 36604 ca = i(x,y,0,0); 36605 sa = i(x,y,0,1); 36606 N = i(#-3,x,y); 36607 x0 = x + N*ca; 36608 y0 = y + N*sa; 36609 x1 = x - N*ca; 36610 y1 = y - N*sa; 36611 polygon(#-1,2,x0,y0,x1,y1,-1,1); 36612 I" 36613 k. normalize_local $5,$6 36614 n 0,255 if $7 negate fi 36615 endl a c endl done 36616 36617fx_ghost_preview : 36618 gui_split_preview "fx_ghost $*",${-3--1} 36619 36620#@gui Hard Sketch : fx_hardsketchbw, fx_hardsketchbw_preview(0) 36621#@gui : Amplitude = float(300,0,4000) 36622#@gui : Density = float(50,0,100) 36623#@gui : Smoothness = float(1,0,10) 36624#@gui : Opacity = float(0.1,0,1) 36625#@gui : Edge = float(20,0,100) 36626#@gui : Fast Approximation = bool(0) 36627#@gui : Color Model = choice(4,"Black on white","White on black","Black on transparent white", 36628#@gui : "White on transparent black","Color on white") 36629#@gui : sep = separator() 36630#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36631#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36632#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36633#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36634#@gui : sep = separator() 36635#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36636fx_hardsketchbw : 36637 b $3 36638 if $7==4 repeat $! l[$>] +hardsketchbw $1,$2,$4,$5,$6 blend hardlight endl done return fi 36639 hardsketchbw $1,$2,$4,$5,$6 36640 if $7&1 negate fi 36641 if $7==2 r 100%,100%,1,4 repeat $! sh[$>] 3 *. -2 +. {2*255} c. 0,255 rm. done 36642 elif $7==3 r 100%,100%,1,4 repeat $! sh[$>] 3 *. 2 c. 0,255 rm. done 36643 fi 36644 36645fx_hardsketchbw_preview : 36646 gui_split_preview "fx_hardsketchbw $*",${-3--1} 36647 36648#@gui Highlight Bloom : fx_highlight_bloom, fx_highlight_bloom_preview(0) 36649#@gui : Details Strength (%) = float(90,0,400) 36650#@gui : Details Scale = float(60,0,255) 36651#@gui : Smoothness = float(60,0,255) 36652#@gui : Highlight (%) = int(30,0,100) 36653#@gui : Contrast (%) = float(20,0,100) 36654#@gui : sep = separator() 36655#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36656#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36657#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36658#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36659#@gui : sep = separator() 36660#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/24/10</i>.</small>") 36661#@gui : sep = separator() 36662#@gui : note = note("This effect has been inspired by:") 36663#@gui : url = link("This tutorial by Sebastien Guyader and Patrick David", 36664#@gui : "https://pixls.us/articles/highlight-bloom-and-photoillustration-look/") 36665fx_highlight_bloom : 36666 repeat $! l[$>] split_opacity l[0] 36667 +smooth $2,0.3,0.8,1,2 36668 -.. . 36669 amp=$3 do smooth. {min(50,$amp)},0.1,1,1,2 amp-=50 while $amp>0 36670 +retinex. 16,lab,0,15 j.. .,0,0,0,0,{$4%} rm. 36671 ac. "normalize_local {$5%},5",lab_l 36672 *.. {$1%} 36673 + c 0,255 36674 endl a c endl done 36675 36676fx_highlight_bloom_preview : 36677 gui_split_preview "fx_highlight_bloom $*",${-3--1} 36678 36679#@gui Hope Poster : fx_poster_hope, fx_poster_hope_preview(0)+ 36680#@gui : Gamma = float(0,-3,3) 36681#@gui : Smoothness = float(3,0,20) 36682#@gui : sep = separator() 36683#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36684#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36685#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36686#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36687#@gui : sep = separator() 36688#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/07/11</i>.</small>") 36689fx_poster_hope : 36690 repeat $! l[$>] split_opacity l[0] 36691 apply_gamma {10^$1} poster_hope $2 36692 endl a c endl done 36693 36694fx_poster_hope_preview : 36695 gui_split_preview "fx_poster_hope $*",${-3--1} 36696 36697#@gui Hough Sketch : fx_houghsketchbw, fx_houghsketchbw_preview(0) 36698#@gui : Smoothness = float(1.25,0,10) 36699#@gui : Density = float(10,0,70) 36700#@gui : Radius = int(5,0,30) 36701#@gui : Threshold = float(80,0,100) 36702#@gui : Opacity = float(0.1,0,1) 36703#@gui : Color Model = choice(4,"Black on white","White on black","Black on transparent white", 36704#@gui : "White on transparent black","Color on white") 36705#@gui : sep = separator() 36706#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36707#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36708#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36709#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36710#@gui : sep = separator() 36711#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/05</i>.</small>") 36712fx_houghsketchbw : 36713 b $1 n 0,255 36714 if $6==4 repeat $! l[$>] +houghsketchbw ${2-5} blend hardlight endl done return fi 36715 houghsketchbw ${2-5} 36716 if $6&1 negate fi 36717 if $6==2 r 100%,100%,1,4 repeat $! sh[$>] 3 *. -2 +. {2*255} c. 0,255 rm. done 36718 elif $6==3 r 100%,100%,1,4 repeat $! sh[$>] 3 *. 2 c. 0,255 rm. done 36719 fi 36720 36721fx_houghsketchbw_preview : 36722 gui_split_preview "fx_houghsketchbw $*",${-3--1} 36723 36724#@gui Kuwahara : fx_kuwahara, fx_kuwahara_preview(0) 36725#@gui : Iterations = int(2,1,20) 36726#@gui : Radius = int(5,1,30) 36727#@gui : sep = separator() 36728#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 36729#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 36730#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 36731#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 36732#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 36733#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 36734#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 36735#@gui : Value Action = choice("None","Cut","Normalize") 36736#@gui : sep = separator() 36737#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36738#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36739#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36740#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36741#@gui : sep = separator() 36742#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/31/05</i>.</small>") 36743fx_kuwahara : 36744 ac "repeat $1 kuwahara $2 done",$3,$4 36745 36746fx_kuwahara_preview : 36747 gui_split_preview "fx_kuwahara $*",${-3--1} 36748 36749#@gui Linify : fx_linify, fx_linify_preview(0) 36750#@gui : Density = float(40,0,100) 36751#@gui : Spreading = float(2,0,10) 36752#@gui : Resolution (%) = float(40,0,100) 36753#@gui : Line Opacity = float(10,0,30) 36754#@gui : Line Precision = int(24,1,128) 36755#@gui : Color Mode = choice(0,"Subtractive","Additive") 36756#@gui : sep = separator() 36757#@gui : Preview Progression While Running = _bool(1) 36758#@gui : sep = separator() 36759#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36760#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36761#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36762#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36763#@gui : sep = separator() 36764#@gui : note = note{"<b>Note:</b>\n\n 36765#@gui : - This filter is our own implementation of the nice algorithm proposed on the webpage 36766#@gui : <a href="http://linify.me">http://linify.me</a>.\n 36767#@gui : - This is a quite resource-demanding filter, so please be patient when running it.\n 36768#@gui : - It actually renders better when applied on small images (<1024). 36769#@gui : "} 36770#@gui : sep = separator() 36771#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/11/21</i>.</small>") 36772fx_linify : 36773 repeat $! l[$>] 36774 if $7 _debug=1 w ${-fitscreen\ {[w,h]}},0,"[Preview] G'MIC: Linify" fi 36775 linify $1,$2,$3%,$4,$5,$6 36776 endl done 36777 36778fx_linify_preview : 36779 gui_split_preview "fx_linify ${1-6},0",${-3--1} 36780 36781#@gui Lylejk's Painting : fx_lylejk_painting, fx_lylejk_painting_preview(0) 36782#@gui : Iterations = int(10,1,20) 36783#@gui : Abstraction = int(2,1,20) 36784#@gui : Radius = int(4,1,30) 36785#@gui : Canvas = float(10,0,100) 36786#@gui : sep = separator() 36787#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36788#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36789#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36790#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36791#@gui : sep = separator() 36792#@gui : note = note("<small>Authors: <i>Lyle Kroll</i> and <i>David Tschumperlé</i>. 36793#@gui : Latest Update: <i>2015/23/02</i>.</small>") 36794#@gui : url = link("Filter Explained here","http://www.gimpchat.com/viewtopic.php?f=10&t=2624") 36795fx_lylejk_painting : 36796 repeat $! l[$>] 36797 nm={0,n} 36798 +l repeat $1 b 0.75 unsharp 0.75,10.49 c 0,255 mv. 0 done endl 36799 smooth. 300,0.26,1,0,7 36800 . rv[-3--1] 36801 blend[-2,-1] lighten,0.5 36802 blend[-2,-1] grainmerge,1 36803 fx_kuwahara. $2,$3,0,0 36804 texturize_canvas. $4,4 36805 nm $nm 36806 endl done 36807 36808fx_lylejk_painting_preview : 36809 gui_split_preview "fx_lylejk_painting $*",${-3--1} 36810 36811#@gui Paint With Brush : fx_paint_with_brush, fx_paint_with_brush_preview(0) 36812#@gui : Predefined style = choice("Default","Felt Spots","Colored Edges","Circles","Dreamy","Fuzzy", 36813#@gui : "Whirls","Smooth") 36814#@gui : previous_style = value(-1) 36815#@gui : sep = separator() 36816#@gui : note = note("<span color="#EE5500"><small><b>Global Settings:</b></small></span>") 36817#@gui : Painting Order = choice(1,"Random","Coarse to Fine","Fine to Coarse") 36818#@gui : Number of Iterations = int(16,1,128) 36819#@gui : Precision (%) = float(30,0,100) 36820#@gui : Details (%) = float(100,0,100) 36821#@gui : Background (%) = float(100,0,100) 36822#@gui : Sharpness (%) = float(10,0,100) 36823#@gui : Anisotropy (%) = float(80,0,100) 36824#@gui : Smoothness = float(0.5,0,8) 36825#@gui : Coherence = float(3,0,16) 36826#@gui : Twist Angle (°) = int(45,-1,360) 36827#@gui : note = note{"<small>(<b>-1</b> means '<i>Random Angle</i>').</small>"} 36828#@gui : Twist strength (%) = int(0,-1,100) 36829#@gui : note = note{"<small>(<b>-1</b> means '<i>Angle Shift</i>').</small>"} 36830#@gui : Init Canvas = choice(6,"Black","Gray","White","Self","Blur","Kuwahara","Vector Painting") 36831#@gui : sep = separator() 36832#@gui : note = note("<span color="#EE5500"><small><b>Brush for Details:</b></small></span>") 36833#@gui : Brush Diameter (px) = float(2,0,100) 36834#@gui : Stroke Length (px) = float(10,0,100) 36835#@gui : Hue Randomness (%) = float(0,0,100) 36836#@gui : Saturation Randomness (%) = float(0,0,100) 36837#@gui : Value Randomness (%) = float(0,0,100) 36838#@gui : Opacity (%) = float(60,0,100) 36839#@gui : sep = separator() 36840#@gui : note = note("<span color="#EE5500"><small><b>Brush for Background:</b></small></span>") 36841#@gui : Brush Diameter (px) = float(20,0,100) 36842#@gui : Stroke Length (px) = float(1,0,100) 36843#@gui : Hue Randomness (%) = float(0,0,100) 36844#@gui : Saturation Randomness (%) = float(0,0,100) 36845#@gui : Value Randomness (%) = float(0,0,100) 36846#@gui : Opacity (%) = float(30,0,100) 36847#@gui : sep = separator() 36848#@gui : note = note("<span color="#EE5500"><small><b>Brush Dynamics:</b></small></span>") 36849#@gui : Brush Diameter = float(15,0,255) 36850#@gui : Stroke Length = float(15,0,255) 36851#@gui : Hue Randomness = float(15,0,255) 36852#@gui : Saturation Randomness = float(15,0,255) 36853#@gui : Value Randomness = float(15,0,255) 36854#@gui : Opacity = float(15,0,255) 36855#@gui : Spatial Step = float(1,0,3) 36856#@gui : Angular Step (°) = float(45,0,90) 36857#@gui : sep = separator() 36858#@gui : Preview Progression While Running = _bool(0) 36859#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36860#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36861#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36862#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36863#@gui : sep = separator() 36864#@gui : note = note("<small>Author: <i>David Tschumperlé</i>.\nLatest Update: <i>2021/08/30</i>.</small>") 36865fx_paint_with_brush : 36866 predefined_style,previous_style,\ 36867 painting_order,nb_iterations,precision,details_threshold,background_threshold,\ 36868 sharpness,anisotropy,smoothness,coherence,twist_angle,twist_strength,init_canvas,\ 36869 brush_diameter_details,stroke_length_details,\ 36870 hue_randomness_details,saturation_randomness_details,value_randomness_details,opacity_details,\ 36871 brush_diameter_background,stroke_length_background,\ 36872 hue_randomness_background,saturation_randomness_background,value_randomness_background,opacity_background,\ 36873 brush_diameter_dynamics,stroke_length_dynamics,\ 36874 hue_randomness_dynamics,saturation_randomness_dynamics,value_randomness_dynamics,opacity_dynamics,\ 36875 spatial_step,angular_step,preview_progression,preview_type,preview_splitx,preview_splity=${1-38} 36876 36877 # Define parameters for predefined styles. 36878 style0=1,16,50,100,100,10,80,0.5,3,0,0,6,2,10,0,0,0,60,20,1,0,0,0,30,15,15,15,15,15,15,1,45 36879 style1=1,16,4,100,100,1,30,0.5,3,0,0,2,3,1,0,0,0,80,10,1,0,0,0,30,8,15,15,15,15,15,1,45 36880 style2=2,16,30,100,20,10,100,0.5,3,45,0,4,4,10,80,0,0,60,20,1,0,0,0,30,10,15,15,15,15,15,1,45 36881 style3=1,16,6.6,100,100,0,0,1.7,3,0,0,2,3,1,0,0,50,80,30,1,0,0,50,20,15,15,15,15,15,15,1,45 36882 style4=1,16,50,100,80,5,80,0.5,1.5,45,0,4,1,20,0,0,0,10,5,1,0,0,0,30,15,15,15,15,15,15,1,45 36883 style5=0,16,10,100,100,10,80,0.5,3,135,50,6,1,20,0,0,0,90,3,10,0,0,0,30,0,15,15,15,15,15,1,45 36884 style6=1,16,30,100,100,0,95,0.5,8,-1,-1,2,2,30,0,0,0,100,20,1,0,0,0,30,0,0,0,0,0,0,1,45 36885 style7=1,16,50,100,100,10,80,0.5,3,0,0,6,1,10,0,0,0,6,20,1,0,0,0,100,17.34,15,15,15,15,20,1,45 36886 36887 if $predefined_style!=$previous_style" && "$previous_style>=0 36888 painting_order,nb_iterations,precision,details_threshold,background_threshold,\ 36889 sharpness,anisotropy,smoothness,coherence,twist_angle,twist_strength,init_canvas,\ 36890 brush_diameter_details,stroke_length_details,\ 36891 hue_randomness_details,saturation_randomness_details,value_randomness_details,opacity_details,\ 36892 brush_diameter_background,stroke_length_background,\ 36893 hue_randomness_background,saturation_randomness_background,value_randomness_background,opacity_background,\ 36894 brush_diameter_dynamics,stroke_length_dynamics,\ 36895 hue_randomness_dynamics,saturation_randomness_dynamics,value_randomness_dynamics,opacity_dynamics,\ 36896 spatial_step,angular_step=${style$predefined_style} 36897 fi 36898 36899 # Process images. 36900 repeat $! l[$>] to_color 36901 36902 # Determine painting geometry. 36903 +diffusiontensors {[$sharpness,$anisotropy]%},$smoothness,$coherence 36904 if $twist_strength>0 # Attract to twist angle 36905 if $twist_angle>=0 36906 f. "begin(Id = eye(2)); 36907 T = [ i0,i1,i1,i2 ]; 36908 eig = eig(T); 36909 const ang = $twist_angle°; 36910 U = lerp(eig[2,2],[ cos(ang),sin(ang) ],$twist_strength%); 36911 U/=max(1e-8,norm(U)); 36912 UUt = mul(U,U,2); 36913 T = eig[0]*UUt + eig[1]*(Id - UUt); 36914 [ T[0],T[1],T[3] ]" 36915 else 36916 100%,100%,1,2 rand. -1,1 b. $coherence orientation. 36917 f.. "begin(Id = eye(2)); 36918 T = [ i0,i1,i1,i2 ]; 36919 eig = eig(T); 36920 U = lerp(eig[2,2],I(#-1),$twist_strength%); 36921 UUt = mul(U,U,2); 36922 T = eig[0]*UUt + eig[1]*(Id - UUt); 36923 [ T[0],T[1],T[3] ]" 36924 rm. 36925 fi 36926 elif $twist_strength<0 # Shift with twist angle 36927 if $twist_angle>=0 36928 f. "R = rot($twist_angle°); 36929 Rt = transpose(R,2); 36930 T = mul(mul(Rt,[ i0,i1,i1,i2 ],2),R,2); 36931 [ T[0],T[1],T[3] ]" 36932 else 36933 100%,100%,1,2 rand. -1,1 b. $coherence orientation. 36934 f.. "ang = atan2(i(#-1,x,y,0,1),i(#-1,x,y,0,0)); 36935 R = rot(ang); 36936 Rt = transpose(R,2); 36937 T = mul(mul(Rt,[ i0,i1,i1,i2 ],2),R,2); 36938 [ T[0],T[1],T[3] ]" 36939 rm. 36940 fi 36941 fi 36942 36943 # Compute contour map and sequence of brush strokes. 36944 +gradient_norm.. 100%,100%,1,2,[x,y] a[-2,-1] c r. {wh},1,1,3,-1 sort. +,x 36945 r. {max(0.01,$precision)}%,1,1,3 z. {(100-$background_threshold)*$details_threshold%}%,$details_threshold% 36946 if $painting_order==0 100% rand. 0,100 rv[-2,-1] a[-2,-1] c sort. +,x channels. 1,100% 36947 elif $painting_order==2 mirror. x 36948 fi 36949 36950 # Initialize canvas. 36951 arg0 $init_canvas,"+f[0] 0","+f[0] 128","+f[0] 255","[0]","+b[0] 1%","+kuwahara[0] 10","+fx_vector_painting[0] 9" 36952 run ${} 36953 36954 # Paint brush strokes. 36955 ind=0 36956 repeat inf,t 36957 progress {$ind*100/w#2} 36958 36959 100%,100%,1,{s#0+1} 36960 nb_strokes={max(1,w#2/$nb_iterations)} 36961 $nb_strokes,1,1,1,:${-math_lib}" 36962 begin(color_random = vector(#s#0)); 36963 lambda(tau) = min(1,edge/(1e-8+tau)); 36964 36965 const brush_diameter_background = $brush_diameter_background; 36966 const brush_diameter_details = $brush_diameter_details; 36967 const brush_diameter_dynamics = $brush_diameter_dynamics; 36968 const stroke_length_background = $stroke_length_background; 36969 const stroke_length_details = $stroke_length_details; 36970 const stroke_length_dynamics = $stroke_length_dynamics; 36971 const opacity_background = 255*$opacity_background%; 36972 const opacity_details = 255*$opacity_details%; 36973 const opacity_dynamics = $opacity_dynamics; 36974 const hue_randomness_background = $hue_randomness_background%; 36975 const hue_randomness_details = $hue_randomness_details%; 36976 const hue_randomness_dynamics = $hue_randomness_dynamics; 36977 const saturation_randomness_background = $saturation_randomness_background%; 36978 const saturation_randomness_details = $saturation_randomness_details%; 36979 const saturation_randomness_dynamics = $saturation_randomness_dynamics; 36980 const value_randomness_background = $value_randomness_background%; 36981 const value_randomness_details = $value_randomness_details%; 36982 const value_randomness_dynamics = $value_randomness_dynamics; 36983 const spatial_step = max($spatial_step,0.1); 36984 const angular_step = max($angular_step,1); 36985 36986 stroke = $ind + x; 36987 stroke<w#2?( 36988 P = I[#2,stroke]; 36989 edge = P[0]; 36990 X0 = P[1,2]; 36991 brush_size = max(0.5,lerp(brush_diameter_background,brush_diameter_details, 36992 lambda(brush_diameter_dynamics))); 36993 stroke_length = lerp(stroke_length_background,stroke_length_details, 36994 lambda(stroke_length_dynamics)); 36995 hue_randomness = lerp(hue_randomness_background,hue_randomness_details, 36996 lambda(hue_randomness_dynamics)); 36997 saturation_randomness = lerp(saturation_randomness_background,saturation_randomness_details, 36998 lambda(saturation_randomness_dynamics)); 36999 value_randomness = lerp(value_randomness_background,value_randomness_details, 37000 lambda(value_randomness_dynamics)); 37001 opacity = lerp(opacity_background,opacity_details, 37002 lambda(opacity_dynamics)); 37003 37004 val = I(#0,X0); 37005 HSV = rgb2hsv(val[0,3]); 37006 HSV[0] = (HSV[0] + 180*hue_randomness*0.35*g)%360; 37007 HSV[1] = cut(HSV[1] + saturation_randomness*0.35*abs(g),0,1); 37008 HSV[2] = cut(HSV[2] + value_randomness*0.35*g,0,1); 37009 RGB = hsv2rgb(HSV); 37010 copy(val,RGB,3); 37011 color = [ val,opacity ]; 37012 37013 for (a = 0, a<360, a+=angular_step, 37014 X = X0; 37015 U = [ cos(a°), sin(a°) ]; 37016 for (l = 0, l<stroke_length, l+=spatial_step, 37017 C = I(#1,X,1); 37018 T = [ C[0],C[1],C[1],C[2] ]; 37019 eig = eig(T); 37020 U = T*U; 37021 ellipse(#-1,X[0],X[1],brush_size,brush_size*(1 - eig[0] + eig[1]),atan2(U[1],U[0]),1,color); 37022 X+=spatial_step*U; 37023 U/=max(1e-9,norm(U)); 37024 ); 37025 ); 37026 );" rm. 37027 37028 sh. 100% j[3] ..,0,0,0,0,1,.,255 rm[-2,-1] 37029 37030 if !0$_is_preview" && "$preview_progression 37031 if !{*} w. ${"fitscreen ."},0 else w. -1,-1,0 fi 37032 if !{*} break fi 37033 fi 37034 37035 ind+=$nb_strokes 37036 if $ind>=w#2 break fi 37037 37038 done 37039 k. 37040 endl done 37041 37042 # Set style parameters if new style has been selected. 37043 if $predefined_style!=$previous_style 37044 u "{"$predefined_style"}{"$predefined_style"}"\ 37045 "{"$painting_order"}{"$nb_iterations"}{"$precision"}{"$details_threshold"}{"$background_threshold"}"\ 37046 "{"$sharpness"}{"$anisotropy"}{"$smoothness"}{"$coherence"}{"$twist_angle"}{"$twist_strength"}{"$init_canvas"}"\ 37047 "{"$brush_diameter_details"}{"$stroke_length_details"}"\ 37048 "{"$hue_randomness_details"}{"$saturation_randomness_details"}{"$value_randomness_details"}{"$opacity_details"}"\ 37049 "{"$brush_diameter_background"}{"$stroke_length_background"}"\ 37050 "{"$hue_randomness_background"}{"$saturation_randomness_background"}{"$value_randomness_background"}"\ 37051 "{"$opacity_background"}"\ 37052 "{"$brush_diameter_dynamics"}{"$stroke_length_dynamics"}"\ 37053 "{"$hue_randomness_dynamics"}{"$saturation_randomness_dynamics"}{"$value_randomness_dynamics"}"\ 37054 "{"$opacity_dynamics"}"\ 37055 "{"$spatial_step"}{"$angular_step"}{"$preview_progression"}{"$preview_type"}{"$preview_splitx,$preview_splity"}" 37056 fi 37057 37058fx_paint_with_brush_preview : 37059 _is_preview=1 37060 gui_split_preview "fx_paint_with_brush $*",${-3--1} 37061 37062#@gui Painting : fx_painting, fx_painting_preview(0)+ 37063#@gui : Abstraction = int(5,1,10) 37064#@gui : Details Scale = float(2.5,0,5) 37065#@gui : Color = float(1.5,0,4) 37066#@gui : Smoothness = float(50,0,1000) 37067#@gui : Sharpen Shades = bool(1) 37068#@gui : sep = separator() 37069#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37070#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37071#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37072#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37073#@gui : sep = separator() 37074#@gui : note = note("<small>Authors: <i>Lyle Kroll</i>, <i>Angelo Lama</i> and <i>David Tschumperlé</i>. 37075#@gui : \nLatest Update: <i>2011/28/02</i>.</small>") 37076fx_painting : skip ${4=0},${5=0} 37077 repeat $! l[$>] 37078 to_colormode {max(3,s)} split_opacity rv 37079 repeat $1 fx_normalize_local. 10,6,5,20,1,11 done 37080 fx_smooth_anisotropic. {100*$2},0.2,1,$2,{2*$2},0.8,90,2,0,1,1,2,1,16 37081 fx_mix_lab. 1,0,0,$3,0,0.5,$3,0,0.5,0,2,0 37082 if $5 fx_segment_watershed. 10,1,0 fi 37083 smooth. $4,0,1,1,1 37084 rv a c 37085 endl done 37086 37087fx_painting_preview : 37088 gui_split_preview "fx_painting $*",${-3--1} 37089 37090#@gui Pen Drawing : fx_pen_drawing, fx_pen_drawing_preview(0)+ 37091#@gui : Amplitude = float(10,0,30) 37092#@gui : sep = separator() 37093#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37094#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37095#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37096#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37097#@gui : sep = separator() 37098#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 37099fx_pen_drawing : 37100 drawing $1 37101 37102fx_pen_drawing_preview : 37103 gui_split_preview "fx_pen_drawing $*",${-3--1} 37104 37105#@gui Polygonize [Delaunay] : fx_polygonize_delaunay, fx_polygonize_delaunay_preview(0) 37106#@gui : Density (%) = float(40,0,100) 37107#@gui : Edges = float(5,0,100) 37108#@gui : Boundaries (%) = float(75,0,100) 37109#@gui : Smoothness = float(0.5,0,8) 37110#@gui : Filling = choice(3,"Black","White","Random","Average","Linear") 37111#@gui : Outline (%) = float(50,0,100) 37112#@gui : Outline Color = color(0,0,0,255) 37113#@gui : Anti-Aliasing = bool(1) 37114#@gui : sep = separator() 37115#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37116#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37117#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37118#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37119#@gui : sep = separator() 37120#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/06/05</i>.</small>") 37121fx_polygonize_delaunay : 37122 repeat $! l[$>] to_rgba 37123 wh={[w,h]} if $11 r 150%,150%,1,100%,3 fi 37124 37125 # Compute Delaunay triangulation. 37126 mM={[im,iM]} b $4 n $mM 37127 +to_rgb. gradient_norm. ge. $2 37128 f. "!x || !y || x==w-1 || y==h-1?(u^0.25<$3%):(u^0.25<$1%?i:0)" 37129 {is+1},1,1,2 f.. ">begin(p = 0); i?(I[#-1,++p] = [x,y];p):0" 37130 delaunay.. 0 37131 37132 # Render filling. 37133 if $5==4 # Linear 37134 +f[0] 0 f... "*i?( 37135 p = I(#1); P0 = I[#2,p[0]]; P1 = I[#2,p[1]]; P2 = I[#2,p[2]]; 37136 W = solve([P0[0],P1[0],P2[0],P0[1],P1[1],P2[1],1,1,1],[x,y,1]); 37137 I(#-1) = cut(W[0]*I(#0,P0) + W[1]*I(#0,P1) + W[2]*I(#0,P2),0,255); 37138 );I" 37139 elif $5==3 # Average 37140 +f[0] 0 f... "*i?( 37141 p = I(#1); P0 = I[#2,p[0]]; P1 = I[#2,p[1]]; P2 = I[#2,p[2]]; 37142 I(#-1) = (I(#0,P0) + I(#0,P1) + I(#0,P2))/3; 37143 );I" 37144 elif $5==2 # Random 37145 +norm[1] label_fg. 0 {iM+1},1,1,3 rand. 0,255 to_rgba. point. 0 map.. . rm. 37146 else # Black or white 37147 +norm[1] !=. 0 *. 255 channels. -3,0 37148 if $5 sh. 0,2 f. 255 rm. fi 37149 fi 37150 rm[0,2] 37151 37152 # Render outlines. 37153 if $6 37154 norm[0] f[0] "i!=j(1) || i!=j(0,1)" # thinning[0] 1 37155 +fc. ${7-10} j.. .,0,0,0,0,{$6%},... rm. 37156 fi 37157 37158 k. 37159 if $11 r $wh,1,100%,2 fi 37160 37161 endl done 37162 37163fx_polygonize_delaunay_preview : 37164 gui_split_preview "fx_polygonize_delaunay $*",${-3--1} 37165 37166#@gui Polygonize [Energy] : fx_polygonize, fx_polygonize_preview(0) 37167#@gui : Amplitude = int(300,0,2000) 37168#@gui : Smoothness = float(10,0,100) 37169#@gui : Minimal Area = float(10,0,100) 37170#@gui : X-Resolution = float(10,1,256) 37171#@gui : Y-Resolution = float(10,1,256) 37172#@gui : Outline Color = color(0,0,0,255) 37173#@gui : sep = separator() 37174#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37175#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37176#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37177#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37178#@gui : sep = separator() 37179#@gui : url = link("Click here for a detailed description of this filter.",\ 37180# "http://www.gimpchat.com/viewtopic.php?f=28&t=9174") 37181#@gui : sep = separator() 37182#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/02/12</i>.</small>") 37183fx_polygonize : 37184 polygonize $1,$2,{$3^2},$4,$5 37185 if $9 repeat $! l[$>] # has outline. 37186 +norm g. xy,1 !=[-2,-1] 0 -|[-2,-1] r. 100%,100%,1,4 37187 replace_color. 0,0,1,1,1,1,$6,$7,$8,$9 37188 blend alpha 37189 endl done fi 37190 37191fx_polygonize_preview : 37192 gui_split_preview "fx_polygonize $*",${-3--1} 37193 37194#@gui Poster Edges : fx_poster_edges, fx_poster_edges_preview(0) 37195#@gui : Image Smoothness = float(20,0,100) 37196#@gui : Edge Threshold = float(60,0,100) 37197#@gui : Edge Shade = float(5,0,30) 37198#@gui : Edge Thickness = float(0,0,5) 37199#@gui : Edge Antialiasing = float(10,0,100) 37200#@gui : Posterization Level = int(0,0,15) 37201#@gui : Posterization Antialiasing = float(0,0,100) 37202#@gui : sep = separator() 37203#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37204#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37205#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37206#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37207#@gui : sep = separator() 37208#@gui : url = link("Click here for a detailed description of this filter.",\ 37209# "http://www.davidrevoy.com/article147/gmic-new-filter-poster-edges") 37210#@gui : sep = separator() 37211#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>David Revoy</i>. 37212#@gui : Latest Update: <i>2012/30/11</i>.</small>") 37213fx_poster_edges : 37214 if $1 bilateral 10,$1 fi 37215 poster_edges ${2-7} 37216 37217fx_poster_edges_preview : 37218 gui_split_preview "fx_poster_edges $*",${-3--1} 37219 37220#@gui Posterize : fx_posterize, fx_posterize_preview(0) 37221#@gui : Smoothness = float(150,0,800) 37222#@gui : Edges (%) = float(30,0,100) 37223#@gui : Paint = float(1,0,10) 37224#@gui : Colors = int(12,2,32) 37225#@gui : Minimal Area = int(0,0,64) 37226#@gui : Outline (%) = float(0,0,100) 37227#@gui : Normalize Colors = bool(0) 37228#@gui : sep = separator() 37229#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37230#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37231#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37232#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37233#@gui : sep = separator() 37234#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/25/10</i>.</small>") 37235fx_posterize : 37236 repeat $! l[$>] split_opacity l[0] 37237 . amp=$1 do smooth. {min(50,$amp)},{$2%},1,$3,{2*$3} amp-=50 while $amp>0 37238 bilateral.. .,5,10 rm. 37239 srgb2rgb +colormap $4 rgb2srgb 37240 index.. .,0,0 37241 if $5 37242 +area.. 0,0 <. $5 inpaint... .,0,3 rm. 37243 fi 37244 map.. . rm. 37245 if $6 37246 +norm (0,1,0;1,1,1;0,1,0) +dilate.. . rm.. -[-2,-1] !=. 0 100%,100%,1,{0,s} j... .,0,0,0,0,{$6%},.. rm[-2,-1] 37247 fi 37248 if $7 n 0,255 fi 37249 endl a c endl done 37250 37251fx_posterize_preview : 37252 gui_split_preview "fx_posterize $*",${-3--1} 37253 37254#@gui Quadtree Variations : fx_quadtree, fx_quadtree_preview(1) 37255#@gui : Mode = choice("Squares","Sierpinksi Design","Ellipse Painting") 37256#@gui : Precision = int(1024,2,4096) 37257#@gui : Homogeneity = float(0.5,0,2) 37258#@gui : Outline = int(0,0,4) 37259#@gui : sep = separator() 37260#@gui : note = note{"<small><b>For 'Ellipse painting' only:</b></small>"} 37261#@gui : Primary Radius = float(3,0,5) 37262#@gui : Secondary Radius = float(1.5,0,5) 37263#@gui : Anisotropy = float(1,0,4) 37264#@gui : Only Leafs = bool(1) 37265#@gui : sep = separator() 37266#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37267#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37268#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37269#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37270#@gui : sep = separator() 37271#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/15/06</i>.</small>") 37272fx_quadtree : 37273 mode,precision,homogeneity,outline,radius1,radius2,anisotropy,only_leafs=${1-8} 37274 m "_qt : sh 3 u {w>1&&h>1?iv*(w*h)^"$homogeneity":-0.1} k[0]" # Function used to split quads 37275 repeat $! l[$>] 37276 to_rgb 37277 37278 # Decompose image with quadtree. 37279 keep_only_leafs={$mode!=2" || "$only_leafs} 37280 +norm. a c 37281 _qt ({d=max(w,h);[0,0,d-1,d-1]},0,${}) 37282 repeat $precision 37283 +columns. 100% n={yM} rm. 37284 x0,y0,x1,y1,level={crop(0,$n,5,1)} 37285 xc={round(($x1+$x0)/2)} yc={round(($y1+$y0)/2)} 37286 xc1,yc1={[$xc,$yc]-1} 37287 level1={$level+1} 37288 B0=$x0,$y0,$xc1,$yc1 +crop[0] $B0,3 _qt. B0.=,$level1,${} rm. 37289 B1=$xc,$y0,$x1,$yc1 +crop[0] $B1,3 _qt. B1.=,$level1,${} rm. 37290 B2=$x0,$yc,$xc1,$y1 +crop[0] $B2,3 _qt. B2.=,$level1,${} rm. 37291 B3=$xc,$yc,$x1,$y1 +crop[0] $B3,3 _qt. B3.=,$level1,${} rm. 37292 if $keep_only_leafs 37293 sh. $n,$n,0,0 f. $B0 rm. 37294 ($B1;$B2;$B3) a[-2,-1] y # Insert new leafs 37295 else 37296 =. -1,5,$n # Mark as not terminal leaf anymore 37297 ($B0;$B1;$B2;$B3) a[-2,-1] y # Insert new leafs 37298 else 37299 fi 37300 done 37301 shift. 2,0,0,0,2 sort. +,y levelmax={i(0,h-1)} shift. -2,0,0,0,2 # Sort by quadtree level order 37302 37303 # Estimate data average in each quad. 37304 channels[0] 0,2 +structuretensors[0] a[0,-1] c 37305 r. {w+6},100%,1,1,0 37306 repeat h 37307 x0,y0,x1,y1={crop(0,$>,4,1)} 37308 +crop[0] $x0,$y0,$x1,$y1,3 r. 1,1,1,100%,2 y. x 37309 j.. .,{-2,w-6},$> rm. 37310 done 37311 37312 # Synthetize image. 37313 permute. cyzx 37314 channels[0] 0,3 f[0] 0 37315 37316 if $mode==0 # Squares 37317 f. "> 37318 rectangle(ind,P0,P1,opacity,color) = ( 37319 _P0 = P0; 37320 _P2 = P1; 37321 _P1 = [ _P2[0], _P0[1] ]; 37322 _P3 = [ _P0[0], _P2[1] ]; 37323 polygon(#ind,4,_P0,_P1,_P2,_P3,opacity,color); 37324 ); 37325 begin(colo = [ 0,0,0,255 ]); 37326 P = I; 37327 Xpp = P[0,2]; 37328 Xnn = P[2,2]; 37329 col = [ P[6,3],255 ]; 37330 if ("$outline"<=0, 37331 rectangle(#0,Xpp,Xnn,1,col); 37332 _(else), 37333 rectangle(#0,Xpp,Xnn,1,colo); 37334 rectangle(#0,Xpp + "$outline",Xnn - "$outline",1,col); 37335 ); 37336 I" 37337 37338 elif $mode==1 # Sierpinski design 37339 f. "> 37340 P = I; 37341 Xpp = P[0,2]; 37342 Xnn = P[2,2]; 37343 Xnp = [ Xnn[0],Xpp[1] ]; 37344 Xpn = [ Xpp[0],Xnn[1] ]; 37345 col1 = [ P[6,3],255 ]; 37346 col2 = [ P[6,3],64 ]; 37347 T = [ P[9],P[10],P[10],P[11] ]; 37348 eig = eig(T); 37349 angle = atan2(eig[5],eig[4])*180/pi; 37350 if ((angle>=0 && angle<90) || angle<-90, 37351 polygon(#0,3,Xpp,Xnp,Xnn,1,col1); 37352 polygon(#0,3,Xpp,Xnn,Xpn,1,col2); 37353 _(else), 37354 polygon(#0,3,Xnp,Xnn,Xpn,1,col1); 37355 polygon(#0,3,Xnp,Xpp,Xpn,1,col2) 37356 ); 37357 I" 37358 37359 else # Ellipse painting 37360 f. "> 37361 begin(colo = [ 0,0,0,255 ]); 37362 P = I; 37363 Xpp = P[0,2]; 37364 Xnn = P[2,2]; 37365 Xcc = (Xpp + Xnn)/2; 37366 R = (Xnn[0] - Xpp[0])/2; 37367 col = [ P[6,3],255 ]; 37368 r = "$radius2"*R; 37369 R*="$radius1"; 37370 T = [ P[9],P[10],P[10],P[11] ]; 37371 eig = eig(T); 37372 anisotropy = (1 + eig[1])/(1 + eig[0]); 37373 r*=anisotropy^"$anisotropy"; 37374 angle = atan2(eig[5],eig[4])*180/pi; 37375 if ("$outline">0, ellipse(#0,Xcc,R,r,angle°,1,colo)); 37376 ellipse(#0,Xcc,R - "$outline",r - "$outline",angle°,1,col); 37377 I" 37378 if !$outline sh[0] 100% if !im solidify[0] 10% fi fi 37379 fi 37380 k[0] 37381 endl done 37382 um _qt 37383 37384fx_quadtree_preview : 37385 gui_split_preview "fx_quadtree $*",${-3--1} 37386 37387#@gui Rodilius : fx_rodilius, fx_rodilius_preview(1) 37388#@gui : Amplitude = float(10,0,30) 37389#@gui : Thickness = float(10,0,100) 37390#@gui : Sharpness = float(300,0,1000) 37391#@gui : Orientations = int(5,2,36) 37392#@gui : Offset = float(30,0,180) 37393#@gui : Smoothness = int(0,0,5) 37394#@gui : Color Mode = choice(1,"Darker","Lighter") 37395#@gui : sep = separator() 37396#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 37397#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 37398#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 37399#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 37400#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 37401#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 37402#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 37403#@gui : Value Action = choice("None","Cut","Normalize") 37404#@gui : sep = separator() 37405#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37406#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37407#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37408#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37409#@gui : url = link("Click here for a video tutorial","http://www.youtube.com/watch?v=RC07VUpzwGc") 37410#@gui : sep = separator() 37411#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Rod/GimpChat</i>. 37412#@gui : Latest Update: <i>2013/05/03</i>.</small>") 37413fx_rodilius : 37414 ac "rodilius ${1-5,7} repeat $6 smooth 10,0,1,1,1,0.8,45 sharpen 30 done c 0,255",$8,$9 37415 37416fx_rodilius_preview : 37417 gui_split_preview "fx_rodilius $*",${-3--1} 37418 37419#@gui Shapeism : fx_shapeism, fx_shapeism_preview(0)+ 37420#@gui : Shape = choice(2,"Squares","Triangles","Circles","Diamond","Hexagon","Octagon","Stars","Custom") 37421#@gui : Branches = int(7,3,16) 37422#@gui : Thickness = float(0.38,0,1) 37423#@gui : Angle = float(0,0,360) 37424#@gui : note = note("<small><b>Note:</b> Parameters <i>Branches</i>, <i>Thickness</i> and <i>Angle</i> are 37425#@gui : used only for <i>Custom</i> shapes.</small>") 37426#@gui : Antialiasing = bool(1) 37427#@gui : sep = separator() 37428#@gui : Scales = int(5,1,16) 37429#@gui : Maximal Size = int(32,1,256) 37430#@gui : Minimal Size = int(8,1,256) 37431#@gui : Allow Angle = choice(3,"0 deg.","180 deg.","90 deg.","Any") 37432#@gui : Spacing = int(1,-5,5) 37433#@gui : Precision = int(5,1,10) 37434#@gui : Edges = float(0.5,0,2) 37435#@gui : Smoothness = float(1,0,10) 37436#@gui : Background = color(0,0,0,255) 37437#@gui : sep = separator() 37438#@gui : url = link("Click here for a detailed description of this filter.",\ 37439# "http://gimpchat.com/viewtopic.php?f=28&t=7500&sid=5b483979826903b8f8fc8fdaf1767dae") 37440#@gui : sep = separator() 37441#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/11/06</i>.</small>") 37442fx_shapeism : 37443 repeat $! l[$>] 37444 to_rgb 37445 +gradient_norm b. $13% ^. $12 quantize. $6,0,0 37446 100%,100%,1,2 37447 repeat $6 37448 37449 # Create map of possible locations. 37450 +channels[2] 100% +>[1] $> !=.. 0 -|[-2,-1] a[2,-1] c 37451 37452 # Create shape at given scale. 37453 size={if($6<=1,$7,$7+($8-$7)*$>/($6-1))} 37454 if $size<1 break fi 37455 if $5 {2*$size},{2*$size} _fx_shapeism$1. ${2-4} r2dy. $size 37456 else $size,$size _fx_shapeism$1. ${2-4} 37457 fi 37458 +!=. 0 expand_xy[-2,-1] 1,0 n[-2,-1] 0,1 37459 if $10<1 dilate. 3 fi 37460 . a[-3--1] c 37461 37462 # Pack sprites for given scale 37463 rprogress "pack_sprites[-2,-1] 1,100,$9,$10,$11",{$>*100/$6},{($>+1)*100/$6} 37464 channels. 0,1 37465 37466 done 37467 37468 rprogress 97 37469 rm[1] 37470 channels. 0 +!=. 0 blend[0,-1] shapeaverage0 *[1] 255 a c 37471 i[0] 100%,100%,1,4 fc[0] $14,$15,$16,$17 37472 blend alpha 37473 rprogress 100 37474 endl done 37475 37476fx_shapeism_preview : 37477 gui_print_preview "" 37478 50%,50% _fx_shapeism$1. ${2-4} frame. 1,1,0 >=. 50% n. 0,255 r. 100%,100%,1,4 37479 ri. [0],0,0,0.5,0.5 -| 37480 37481_fx_shapeism0 : # Square 37482 f 255 skip $* 37483 37484_fx_shapeism1 : # Triangle 37485 polygon 3,50%,0,0,100%,100%,100%,1,1 skip $* 37486 37487_fx_shapeism2 : # Circle 37488 shape_circle {w} rm.. skip $* 37489 37490_fx_shapeism3 : # Diamond 37491 shape_diamond {w} rm.. skip $* 37492 37493_fx_shapeism4 : # Hexagon 37494 star3d 3,1 *3d. {0,min(w,h)/2} j3d[0] .,50%,50%,0,1,2,0 k[0] skip $* 37495 37496_fx_shapeism5 : # Octogon 37497 star3d 4,1 *3d. {0,min(w,h)/2} j3d[0] .,50%,50%,0,1,2,0 k[0] skip $* 37498 37499_fx_shapeism6 : # Star 37500 star3d 5 *3d. {0,min(w,h)/2} j3d[0] .,50%,50%,0,1,2,0 k[0] skip $* 37501 37502_fx_shapeism7 : # Custom 37503 star3d $1,$2 *3d. {0,min(w,h)/2} r3d. 0,0,1,$3 j3d[0] .,50%,50%,0,1,2,0 k[0] 37504 37505#@gui Sharp Abstract : fx_sharp_abstract, fx_sharp_abstract_preview(0) 37506#@gui : Spatial Scale = float(4,0,32) 37507#@gui : Value Scale = float(10,0,16) 37508#@gui : Precision = float(0.5,0,2) 37509#@gui : sep = separator() 37510#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 37511#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 37512#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 37513#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 37514#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 37515#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 37516#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 37517#@gui : sep = separator() 37518#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37519#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37520#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37521#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37522#@gui : sep = separator() 37523#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/09</i>.</small>") 37524fx_sharp_abstract : 37525 ac "rolling_guidance ${1-3}",$4 37526 37527fx_sharp_abstract_preview : 37528 gui_split_preview "fx_sharp_abstract $*",${-3--1} 37529 37530#@gui Sketch : fx_sketchbw, fx_sketchbw_preview(0) 37531#@gui : Number of Orientations = int(3,1,16) 37532#@gui : Starting Angle = float(45,0,180) 37533#@gui : Angle Range = float(180,0,180) 37534#@gui : Stroke Length = float(30,0,1000) 37535#@gui : Contour Threshold = float(1.75,0,10) 37536#@gui : Opacity = float(0.02,0,0.3) 37537#@gui : Background Intensity = float(0.5,0,2) 37538#@gui : Density = float(0.75,0,5) 37539#@gui : Sharpness = float(0.1,0,1) 37540#@gui : Anisotropy = float(0.7,0,1) 37541#@gui : Smoothness = float(3,0,10) 37542#@gui : Coherence = float(6,0,10) 37543#@gui : Boost Stroke = bool(0) 37544#@gui : Curved Stroke = bool(1) 37545#@gui : Color Model = choice(4,"Black on white","White on black","Black on transparent white", 37546#@gui : "White on transparent black","Color on white") 37547#@gui : Random Seed = int(0,0,65535) 37548#@gui : sep = separator() 37549#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37550#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37551#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37552#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37553#@gui : sep = separator() 37554#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/05/11</i>.</small>") 37555fx_sketchbw : skip ${16=0} 37556 srand $16 37557 if $15==4 repeat $! l[$>] +sketchbw ${1-14} blend hardlight endl done return fi 37558 sketchbw ${1-14} 37559 if $15&1 negate fi 37560 if $15==2 r 100%,100%,1,4 repeat $! sh[$>] 3 *. -2 +. {2*255} c. 0,255 rm. done 37561 elif $15==3 r 100%,100%,1,4 repeat $! sh[$>] 3 *. 2 c. 0,255 rm. done 37562 fi 37563 37564fx_sketchbw_preview : 37565 gui_split_preview "fx_sketchbw $*",${-3--1} 37566 37567#@gui Smooth Abstract : fx_smooth_abstract, fx_smooth_abstract_preview(0) 37568#@gui : Smoothness (%) = float(75,0,100) 37569#@gui : Regularization = choice(0,"Isotropic","Delaunay-Guided","Edge-Oriented") 37570#@gui : Regularization Iterations = int(20,0,100) 37571#@gui : Geometry = float(1,0,5) 37572#@gui : Details = float(30,0,50) 37573#@gui : sep = separator() 37574#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37575#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37576#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37577#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37578#@gui : sep = separator() 37579#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/06/04</i>.</small>") 37580fx_smooth_abstract : 37581 repeat $! l[$>] split_opacity l[0] 37582 srgb2rgb 37583 mM={[im,iM]} +b $4 n. $mM gradient_norm. <=. {50-$5} 37584 inpaint_pde[0] [1],$1%,$2,$3 rm. 37585 rgb2srgb c 0,255 37586 endl a c endl done 37587 37588fx_smooth_abstract_preview : 37589 gui_split_preview "fx_smooth_abstract $*",${-3--1} 37590 37591#@gui Stylize : fx_stylize,fx_stylize_preview 37592#@gui : Style = choice{0,"Custom Style (Top Layer)","Custom Style (Bottom Layer)", 37593#@gui : "Braque: Landscape near Antwerp", 37594#@gui : "Braque: Le Viaduc à l'Estaque", 37595#@gui : "Braque: Little Bay at La Ciotat", 37596#@gui : "Braque: The Mandola", 37597#@gui : "Christine Garner: Black Colour Pencil", 37598#@gui : "Christine Garner: Colour Pencil Sepia", 37599#@gui : "Christine Garner: Dark Coloured Pencil", 37600#@gui : "Christine Garner: Pencil", 37601#@gui : "Christine Garner: Sketching Pastel", 37602#@gui : "Christine Garner: Willow Charcoal", 37603#@gui : "Delaunay: Windows Open Simultaneously", 37604#@gui : "Delaunay: Portrait de Metzinger", 37605#@gui : "Hokusai: The Great Wave", 37606#@gui : "Kandinsky: Squares with Concentric Circles", 37607#@gui : "Kandinsky: Yellow-Red-Blue", 37608#@gui : "Klee: Death and Fire", 37609#@gui : "Klee: In the Style of Kairouan", 37610#@gui : "Klee: Oriental Pleasure Garden Anagoria", 37611#@gui : "Klee: Polyphony 2", 37612#@gui : "Klee: Red waistcoat", 37613#@gui : "Klimt: The Kiss", 37614#@gui : "Mondrian: Composition in Red-Yellow-Blue", 37615#@gui : "Mondrian: Evening; Red Tree", 37616#@gui : "Mondrian: Gray Tree", 37617#@gui : "Monet: San Giorgio Maggiore at Dusk", 37618#@gui : "Monet: Water-Lily Pond", 37619#@gui : "Monet: Wheatstacks - End of Summer", 37620#@gui : "Munch: The Scream", 37621#@gui : "Picabia: Udnie", 37622#@gui : "Picasso: Les Demoiselles d'Avignon", 37623#@gui : "Picasso: Seated Woman", 37624#@gui : "Picasso: The Reservoir - Horta de Ebro", 37625#@gui : "Pollock: Convergence", 37626#@gui : "Pollock: Summertime Number 9A", 37627#@gui : "Van Gogh: Almond Blossom", 37628#@gui : "Van Gogh: Irises", 37629#@gui : "Van Gogh: The Starry Night", 37630#@gui : "Van Gogh: Wheat Field with Crows"} 37631#@gui : Scale Style to Fit Target Resolution = choice(5,"No rescaling","10%","20%","30%","50%","75%","100%","150%", 37632#@gui : "200%","250%","300%") 37633#@gui : Style Variations = choice("None","All XY-flips","All 90° rotations","All 45° rotations") 37634#@gui : Preview Progression While Running = bool(1) 37635#@gui : sep = separator(), note = note{"<small><b><span color="blue">Style/Target Parameters:</span></b></small>"} 37636#@gui : Fidelity to Target (Finest) = float(0.5,0,5) 37637#@gui : Fidelity to Target (Coarsest) = float(2,0,5) 37638#@gui : Fidelity Smoothness (Finest) = float(3,0,5) 37639#@gui : Fidelity Smoothness (Coarsest) = float(0.5,0,5) 37640#@gui : Fidelity Chromaticity = float(0.1,0,1) 37641#@gui : sep = separator(), note = note{"<small><b><span color="blue">Image Matching Parameters:</span></b></small>"} 37642#@gui : Match Colors With = choice(3,"Nothing","Gamma Balance","Histogram Transfer","PCA transfer") 37643#@gui : Colorspace = choice{3,"sRGB","Linear RGB","YCbCr","YCbCr (Luma/Chroma),"YCbCr (Luma Only)", 37644#@gui : "YCbCr (Chroma Only)","Lab","Lab (Luma/Chroma)","Lab (Luma Only)","Lab (Chroma Only)"} 37645#@gui : Keep Color Channels = choice{"All","Luminance Only (YCbCr)","Luminance Only (Lab)","Chrominances Only (CbCr)", 37646#@gui : "Chrominances Only (ab)"} 37647#@gui : Smoothness = float(0.7,0,5) 37648#@gui : Also Match Gradients = float(1,0,5) 37649#@gui : sep = separator(), note = note{"<small><b><span color="blue">Advanced Parameters:</span></b></small>"} 37650#@gui : Init. Type = choice("Best Match","Identity","Randomized") 37651#@gui : Init. Resolution = choice(1,"8px","16px","32px","64px","128px","256px") 37652#@gui : Init. With High Gradients Only = float(0,0,100) 37653#@gui : Patch Size for Analysis = int(5,2,16) 37654#@gui : Patch Size for Synthesis = int(5,2,16) 37655#@gui : Patch Size for Synthesis (Final) = int(7,2,16) 37656#@gui : Number of Matches (Finest) = int(1,0,10) 37657#@gui : Number of Matches (Coarsest) = int(30,0,200) 37658#@gui : Penalize Patch Repetitions = int(2,0,300) 37659#@gui : Matching Precision (Smaller is Faster) = float(2,0,10) 37660#@gui : Scale Factor = float(1.85,1.1,4) 37661#@gui : Skip Finest Scales = int(0,0,3) 37662#@gui : sep = separator() 37663#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/03/23</i>.</small>") 37664fx_stylize : 37665 init_resolution={arg(1+$16,8,16,32,64,128,256)} 37666 37667 # Define image matching function 37668 colorspace=${"arg 1+$11,all,lrgb,ycbcr,ycbcr,ycbcr_y,ycbcr_cbcr,lab,lab,lab_l,lab_ab"} 37669 match_colors="s c,-3 mv[1] 3 b[-2,-1] 1% negate[-2,-1] n[-2,-1] 0,1" 37670 luma,chroma= 37671 if $11==3" || "$11==7 # Chroma/Luma conversion for YCbCr or Lab 37672 luma=_${"arg 1+($11==7),y,l"} 37673 chroma=_${"arg 1+($11==7),cbcr,ab"} 37674 fi 37675 if $10==1 37676 match_colors=$match_colors" ac[0,1] \"balance_gamma ,\","$colorspace$luma 37677 if narg($chroma) match_colors=$match_colors" ac[0,1] \"balance_gamma ,\","$colorspace$chroma fi 37678 elif $10==2 37679 match_colors=$match_colors" transfer_histogram[0] [1],256,"$colorspace$luma 37680 if narg($chroma) match_colors=$match_colors" transfer_histogram[0] [1],256,"$colorspace$chroma fi 37681 elif $10==3 37682 match_colors=$match_colors" transfer_pca[0] [1],"$colorspace$luma" c[0] 0,255" 37683 if narg($chroma) match_colors=$match_colors" transfer_pca[0] [1],"$colorspace$chroma" c[0] 0,255" fi 37684 fi 37685 if $12==1 match_colors=$match_colors" rgb2ycbcr[0,1] sh[0,1] 1,2 f[-2,-1] 128 rm[-2,-1] ycbcr2rgb[0,1]" 37686 elif $12==2 match_colors=$match_colors" srgb2lab[0,1] sh[0,1] 1,2 f[-2,-1] 0 rm[-2,-1] lab2srgb[0,1]" 37687 elif $12==3 match_colors=$match_colors" rgb2ycbcr[0,1] sh[0,1] 0 f[-2,-1] 128 rm[-2,-1] ycbcr2rgb[0,1]" 37688 elif $12==4 match_colors=$match_colors" srgb2lab[0,1] sh[0,1] 0 f[-2,-1] 50 rm[-2,-1] lab2srgb[0,1]" 37689 fi 37690 match_colors=$match_colors\ 37691 " b[0,1] xy,$13 repeat 2 l[$>] s c n 0,255 a c endl done *[-2,-1] {$14*255} a[0,-2] c a[1,-1] c" 37692 37693 patch_penalization=$23 37694 37695 # Insert style image at the end of the list. 37696 if $1<2 # Custom style (top or bottom layer) 37697 if $!<2 error "At least two layers are required in this mode." fi 37698 ind_first={$1==0?1:0} ind_style={$1==0?0:-1} N={$!-1} sh[$ind_style] 37699 else 37700 ind_first=0 N=$! ind_style= _fx_stylize {$1-2} 37701 fi 37702 37703 # Process layers. 37704 is_window=0 37705 repeat $N l[{$ind_first+$>},-1] nm={0,n} 37706 if $2 +rr2d[1] {0,[w,h]*arg($2,0.1,0.2,0.3,0.5,0.75,1,1.5,2,2.5,3)},1,2 fi 37707 if $3==1 . +mirror. x +mirror[-2,-1] y a[-4--1] z 37708 elif $3==2 +l. r {u={max(w,h)};[u,u]},1,100%,0,3,0.5,0.5 repeat 3 +rotate[0] {90*$>},1,3,50%,50% done a z endl 37709 elif $3==3 +l. r {u={max(w,h)};[u,u]},1,100%,0,3,0.5,0.5 repeat 7 +rotate[0] {45*$>},1,3,50%,50% done a z endl 37710 fi 37711 if $4 wsiz=${"fitscreen "{0,[w,h]}} w[0] $wsiz is_window={*} fi 37712 stylize[0] .,${5-9},$15,$init_resolution,${17-22},$patch_penalization,${24-26},$match_colors 37713 k[0,1] nm[0] $nm 37714 if $is_window" && "!{*} break fi 37715 endl done 37716 rm. # Remove style image 37717 if 0$_output_mode 37718 if narg($ind_style) rm[$ind_style] fi # Do not duplicate style layer if output mode -> new layers 37719 if $is_window" && "!{*} rm fi # In case user closed the window, does not output new layers. 37720 fi 37721 37722fx_stylize_preview : 37723 if $1<2 # Custom style (top or bottom layer) 37724 if $!<2 gui_warning_preview "At least two layers are required when specifying a custom style." return fi 37725 ind_first={$1==0?1:0} ind_style={$1==0?0:-1} N={$!-1} sh[$ind_style] 37726 else 37727 ind_first=0 N=$! ind_style= _fx_stylize {$1-2} 37728 fi 37729 repeat $N l[{$ind_first+$>},-1] 37730 gui_no_preview[0] , 37731 +rr2d[1] {0,[w,h]*2/3},0,2 frame. 1,1,255 frame. 1,1,0,0,0,255 j[0] .,1%,30 rm. to[0] "Style:",1%,0,24 37732 endl done rm. 37733 if narg($ind_style) rm[$ind_style] fi 37734 37735_fx_stylize : # Download pre-defined style image 37736 if isnum($1) 37737 name=${"arg 1+$1",\ 37738 "landscapenearantwerp,leviaducalestaque,littlebayatlaciotat,themandola",\ 37739 "blackcolourpencil,colourpencilsepia,darkcolouredpencil,pencil,sketchingpastel,willowcharcoal",\ 37740 "windowsopensimultaneously,portraitdemetzinger,greatwave,squareswithconcentriccircles,yellowredblue",\ 37741 "deathandfire,inthestyleofkairouan,orientalpleasuregardenanagoria,polyphony2,redwaistcoat,thekiss",\ 37742 "compositionredyellowblue,redtree,graytree,sangiorgiomaggioreatdusk,waterlilypond,wheatstacksendofsummer",\ 37743 "scream,udnie,lesdemoisellesdavignon,seatedwoman,reservoirhortadeebro,convergence,summertime9a",\ 37744 "almondblossom,irises,starrynight,wheatfieldwithcrows"} 37745 else name="$1" 37746 fi 37747 input_cached img/style_$name.png 37748 37749#@gui Vector Painting : fx_vector_painting, fx_vector_painting_preview(1) 37750#@gui : Details = float(9,0,10) 37751#@gui : sep = separator() 37752#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37753#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37754#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37755#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37756#@gui : sep = separator() 37757#@gui : note = note("<small>Author: <i>David Tschumperlé</i>.\nLatest Update: <i>2015/25/08</i>.</small>") 37758fx_vector_painting : 37759 repeat $! l[$>] 37760 +luminance b. {10-$1}%,1,1 37761 f. "dmax = -1; nmax = 0; 37762 for (n = 0, ++n<=8, 37763 p = arg(n,-1,0,1,-1,1,-1,0,1); 37764 q = arg(n,-1,-1,-1,0,0,1,1,1); 37765 d = (j(p,q,0,0,0,1) - i)^2; 37766 d>dmax?(dmax = d; nmax = n):nmax; 37767 )" 37768 blend shapeaverage 37769 endl done 37770 37771fx_vector_painting_preview : 37772 gui_split_preview "fx_vector_painting $*",${-3--1} 37773 37774#@gui Warhol : warhol, warhol(1) 37775#@gui : X-Tiles = int(3,1,10) 37776#@gui : Y-Tiles = int(3,1,10) 37777#@gui : Smoothness = float(2,0,10) 37778#@gui : Color = float(40,0,60) 37779#@gui : sep = separator() 37780#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 37781 37782#@gui Whirl Drawing : fx_draw_whirl, fx_draw_whirl_preview(0) 37783#@gui : Amplitude = float(20,0,100) 37784#@gui : sep = separator() 37785#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37786#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37787#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37788#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37789#@gui : sep = separator() 37790#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 37791fx_draw_whirl : 37792 repeat $! l[$>] split_opacity draw_whirl[0] $* a c endl done 37793 37794fx_draw_whirl_preview : 37795 gui_split_preview "fx_draw_whirl $*",${-3--1} 37796 37797#@gui ____<b>Black & White</b> 37798#------------------------------- 37799 37800#@gui Black & White : fx_blackandwhite, fx_blackandwhite_preview(1)+ 37801#@gui : Red Level = float(0.299,0,1) 37802#@gui : Red Smoothness = float(0,0,10) 37803#@gui : Green Level = float(0.587,0,1) 37804#@gui : Green Smoothness = float(0,0,10) 37805#@gui : Blue Level = float(0.114,0,1) 37806#@gui : Blue Smoothness = float(0,0,10) 37807#@gui : sep = separator() 37808#@gui : Brightness (%) = float(0,-100,100) 37809#@gui : Contrast (%) = float(0,-100,100) 37810#@gui : Gamma (%) = float(0,-100,100) 37811#@gui : Hue (%) = float(0,-100,100) 37812#@gui : Saturation (%) = float(0,-100,100) 37813#@gui : sep = separator() 37814#@gui : Grain (Shadows) = float(0,0,200) 37815#@gui : Grain (Midtones) = float(0,0,200) 37816#@gui : Grain (Highlights) = float(0,0,200) 37817#@gui : Grain Tone Fading = float(2,0,10) 37818#@gui : Grain Scale = float(0,0,3) 37819#@gui : Grain Type = choice("Gaussian","Uniform","Salt and Pepper","Poisson") 37820#@gui : sep = separator() 37821#@gui : Local Contrast = float(0,0,60) 37822#@gui : Radius = int(16,1,512) 37823#@gui : Contrast Smoothness = float(4,0,10) 37824#@gui : sep = separator() 37825#@gui : Pseudo-Gray Dithering = int(0,0,5) 37826#@gui : Use Maximum Tones = bool(false) 37827#@gui : sep = separator() 37828#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37829#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37830#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37831#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37832#@gui : sep = separator() 37833#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/20/02</i>.</small>") 37834fx_blackandwhite : 37835 repeat $! 37836 l. split_opacity rv to_rgb. s. c # Isolate opacity 37837 *... $1 b... $2% # Red level + smoothness 37838 *.. $3 b.. $4% # Green level + smoothness 37839 *. $5 b. $6% # Blue level + smoothness 37840 +[-3--1] /. {$1+$3+$5} c. 0,255 # (R,G,B) -> B&W 37841 adjust_colors ${7-11},0,255 37842 if $12||$13||$14 37843 100%,100% [-1]x2 # Create noise for shadows, midtones and highlights. 37844 noise... 100,$17 b... $16% n... -$12,$12 # Scaled grain on shadows. 37845 noise.. 100,$17 b.. $16% n.. -$13,$13 # Scaled grain on midtones. 37846 noise. 100,$17 b. $16% n. -$14,$14 # Scaled grain on highlights. 37847 +tones[-4] 3 b[-3--1] $15% # Get smoothed tones. 37848 *[-6,-3] *[-4,-2] *[-2,-1] # Get noisy tones. 37849 +[-4--1] c. 0,255 # Compose them with the B&W image. 37850 fi 37851 rv a c endl mv. 0 done # Re-compose opacity and loop to next image. 37852 if $18 normalize_local $18,$19,$20,2%,1,0,255 fi 37853 if $22 n 0,255 fi 37854 if $21 to_pseudogray $21,1 fi 37855 37856fx_blackandwhite_preview : 37857 gui_split_preview "fx_blackandwhite $*",${-3--1} 37858 37859#@gui B&W Stencil : fx_stencilbw, fx_stencilbw_preview(0) 37860#@gui : Threshold = float(10,0,30) 37861#@gui : Smoothness = float(10,0,30) 37862#@gui : Hue = float(0,0,360) 37863#@gui : Saturation = float(0,0,1) 37864#@gui : sep = separator() 37865#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37866#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37867#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37868#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37869#@gui : sep = separator() 37870#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 37871fx_stencilbw : 37872 stencilbw $1,$2 37873 if $3||$4 repeat $! l[$>] split_opacity 37874 /[0] 255 i[0] 100%,100%,1,1,$4 i[0] 100%,100%,1,1,$3 a[0-2] c hsv2rgb[0] 37875 a c endl done fi 37876 37877fx_stencilbw_preview : 37878 gui_split_preview "fx_stencilbw $*",${-3--1} 37879 37880#@gui Charcoal : fx_charcoal, fx_charcoal_preview(0) 37881#@gui : Granularity = int(65,0,800) 37882#@gui : Lowlights Crossover Point = int(70,0,255) 37883#@gui : Highlights Crossover Point = int(170,0,255) 37884#@gui : Boost Contrast = bool(0) 37885#@gui : Resize Image for Optimum Effect = bool(1) 37886#@gui : Add Chalk Highlights = bool(0) 37887#@gui : Minimal Highlights = int(50,0,255) 37888#@gui : Maximal Highlights = int(70,0,255) 37889#@gui : Background Color = color(255,255,255) 37890#@gui : Foreground Color = color(0,0,0) 37891#@gui : Invert Background / Foreground = bool(0) 37892#@gui : sep = separator() 37893#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37894#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37895#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37896#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37897#@gui : sep = separator() 37898#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/17/03</i>.</small>") 37899#@gui : note = note("<small>Inspired from the Charcoal script by <i>micomicon</i> :</small>") 37900#@gui : url = link("http://registry.gimp.org/node/25078") 37901fx_charcoal : 37902 repeat $! l[$>] split_opacity l[0] 37903 compose_channels max 37904 w={w} h={h} 37905 if $5 r. 150%,150%,1,1,6 fi 37906 if $4 equalize. n. 0,255 fi 37907 sharpen {$1*3} cut 0,255 37908 if $6 +ir $7,$8 fi # Add highlights layer if required. 37909 ir[0] $2,$3 37910 if !$15 ==[0] 0 fi 37911 -| 37912 +*[0] $10 +*[0] $11 *[0] $9 37913 a[-3--1] c replace_color 0,0,0,0,0,$12,$13,$14 37914 r $w,$h,1,100%,2 37915 endl a c endl done 37916 37917fx_charcoal_preview : 37918 gui_split_preview "fx_charcoal $*",${-3--1} 37919 37920#@gui Colorize [Interactive] : fx_colorize_interactive, fx_colorize_interactive_preview 37921#@gui : Input Type = _choice("B&W Photograph","Lineart") 37922#@gui : Output Type = _choice{"Colorized Image (1 Layer)","Colors Only (1 Layer)","Image + Colors (2 Layers)", 37923#@gui : "Image + Colors (Multi-Layers)"} 37924#@gui : View Resolution = _choice{1,"Small (Faster)","Medium","High (Slower)","Very High (Even Slower)"} 37925#@gui : 1st Additional Palette (.gpl) = _filein() 37926#@gui : 2nd Additional Palette (.gpl) = _filein() 37927#@gui : Image to Grab Color from (.png) = _filein() 37928#@gui : sep = separator() 37929#@gui : note = note{"<small><b>Description:</b>\n 37930#@gui : This filter allows to quickly colorize a B&W image or lineart. 37931#@gui : Click on the <i>Apply</i> or <i>OK</i> buttons below to open the G'MIC interactive window and 37932#@gui : start adding color control points. When you're done, exit the interactive window: your colored 37933#@gui : result will be transferred back to the host software.\n\n 37934#@gui : If you are not satisfied with the result, <i>Undo it (CTRL+Z)</i>, and click on <i>Apply</i> once 37935#@gui : again to modify your control points defined previously. 37936#@gui : To clear all control points, click on the <i>Reset</i> button above. 37937#@gui : </small>"} 37938#@gui : Clear Control Points = button(0.5) 37939#@gui : Last Image Size = value(0,0) 37940#@gui : Control Points = value(-1) 37941#@gui : sep = separator() 37942#@gui : note = note{"<small><b>Interactions:</b>\n 37943#@gui : Use the following actions in the interactive window to manage your colorization :\n\n 37944#@gui : - <b>Left mouse button</b> creates a new color control point (or move an existing one).\n 37945#@gui : - <b>Right mouse button</b> or key <b>X</b> over a control point deletes it.\n 37946#@gui : - <b>Right mouse button</b> or key <b>P</b> anywhere else picks a color from the image.\n 37947#@gui : - <b>Mouse wheel</b>, or keys <b>CTRL+arrows up/down</b> zoom view in/out.\n 37948#@gui : - <b>CTRL+mouse wheel</b>, <b>SHIFT+wheel</b> or arrow keys move image in zoomed view.\n 37949#@gui : - Key <b>SPACE</b> updates the extrapolated color field.\n 37950#@gui : - Key <b>TAB</b> toggles markers view modes.\n 37951#@gui : - Key <b>BACKSPACE</b> deletes the last control point added.\n 37952#@gui : - Key <b>PAGE UP</b> increases image contrast.\n 37953#@gui : - Key <b>PAGE DOWN</b> decreases image contrast.\n 37954#@gui : - Key <b>R</b> enters/exits color replace mode.\n 37955#@gui : - Keys <b>CTRL+D</b> increase window size.\n 37956#@gui : - Keys <b>CTRL+C</b> decrease window size.\n 37957#@gui : - Keys <b>CTRL+R</b> resets window size.\n 37958#@gui : - Keys <b>ESC</b>, <b>Q</b> or <b>ENTER</b> exit the interactive window. 37959#@gui : </small>"} 37960#@gui : sep = separator() 37961#@gui : note = note("<small>You can find more information on how to use this filter here :</small>") 37962#@gui : url = link("David Revoy's G'MIC Colorization Page", 37963#@gui : "http://www.davidrevoy.com/article240/gmic-line-art-colorization") 37964#@gui : sep = separator() 37965#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/12/07</i>.</small>") 37966fx_colorize_interactive : skip "${4=},${5=},${6=}" 37967 N=$! nm={n} 37968 resolution={arg(1+$3,512,1024,2048,0)} 37969 nm "[G"{`39`}"MIC] Colorize" 37970 if [$9][0]==-1" || "[$8]!=[w,h] _gui_control_points= else _gui_control_points=$9 fi 37971 N=$! 37972 37973 arg_palette1=0 l[] 37974 0 nm. "$4" ext={x} rm 37975 if same(['$ext'],'gpl',-1,0) 37976 input_gpl "$4" arg_palette1=1 fi 37977 onfail rm endl 37978 if $arg_palette1 arg_palette1=[{$!-1}] fi 37979 37980 arg_palette2=0 l[] 37981 0 nm. "$5" ext={x} rm 37982 if same(['$ext'],'gpl',-1,0) 37983 input_gpl "$5" arg_palette2=1 fi 37984 onfail rm endl 37985 if $arg_palette2 arg_palette2=[{$!-1}] fi 37986 37987 arg_grabber=0 l[] 37988 0 nm. "$6" ext={x} rm 37989 i "$6" to_rgb arg_grabber=1 37990 onfail rm endl 37991 if $arg_grabber arg_grabber=[{$!-1}] fi 37992 37993 repeat $N 37994 status=${x_colorize[$>]\ $1,$resolution,$2,$arg_palette1,$arg_palette2,$arg_grabber} 37995 done 37996 k[0-{$N-1}] 37997 37998 if $2==1 repeat $! l[$<] # Output : colors only (1 layer). 37999 channels {s-3},{s-1} 38000 endl done 38001 elif $2>=2 repeat $! l[$<] # Output : Lineart + Colors (2 layers). 38002 +channels {s-3},{s-1} channels.. 0,{0,s-4} 38003 endl done 38004 if $2>=3 split_colors[1] 0,256,8 fi # Split colors into layers. 38005 fi 38006 nm $nm 38007 if !narg($status) status=-1 fi 38008 u \{$1\}\{$2\}\{$3\}\{"$4"\}\{"$5"\}\{"$6"\}\{0\}\{{w},{h}\}\{$status\} 38009 38010fx_colorize_interactive_preview : skip "${4=},${5=},${6=}" 38011 if $7 # Clear control points. 38012 gui_print_preview "No preview\n available",,"(Control points cleared)" 38013 u \{$1\}\{$2\}\{$3\}\{"$4"\}\{"$5"\}\{"$6"\}\{0\}\{{w},{h}\}\{-1\} 38014 else gui_no_preview , 38015 fi 38016 38017#@gui Colorize [Photographs] : fx_recolorize, fx_recolorize_preview(1) 38018#@gui : Smoothness = int(2,0,6) 38019#@gui : Anisotropy = float(0.2,0,1) 38020#@gui : Output Mode = choice("Merge Brightness / Colors","Split Brightness / Colors") 38021#@gui : sep = separator() 38022#@gui : note = note{"<small><b>Note:</b> This filter needs two layers to work properly. 38023#@gui : The bottom layer must be a B&W image, while the top layer contains color patches that will 38024#@gui : be extrapolated in a smart way (edge-directed) to fill the entire image. At the end, 38025#@gui : you get a completely recolored image.</small>"} 38026#@gui : sep = separator() 38027#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/16/01</i>.</small>") 38028fx_recolorize : 38029 repeat int($!/2) 38030 if $3 s=$>,{$>+1} else s={2*$>},{2*$>+1} fi 38031 l[$s] rv[0,1] 38032 channels[0] 0 to_rgb.. # Convert to pure gray. 38033 to_rgba. split_opacity. !=. 0 # Retrieve mask of color patches. 38034 srgb2rgb[-3,-2] rgb2lab8[-3,-2] channels... 0 channels.. 1,2 # Now, list is [0]=lightness / [1]=chroma / [2]=mask. 38035 +.. 1 *.. . +gradient_norm... *. -1 watershed... . rm. -.. 1 # Get first estimate for the color interpolation. 38036 +diffusiontensors... $2,1,0.5,0.5 ==.. 0 *. .. rm.. 38037 smooth.. .,{$1*80},0.8,60 rm. 38038 a[-2,-1] c lab82rgb. rgb2srgb. 38039 if $3 rgb2hsv. s. c i[2] 100%,100%,1,1,1 i[3] 100%,100%,1,2,0 a[0-2] c a[^0] c hsv2rgb rv fi 38040 endl 38041 done 38042 38043fx_recolorize_preview : 38044 fx_recolorize $* a x 38045 38046#@gui Colorize [with Colormap] : fx_bwrecolorize, fx_bwrecolorize_preview 38047#@gui : Brightness (%) = float(0,-100,100) 38048#@gui : Contrast (%) = float(0,-100,100) 38049#@gui : Gamma (%) = float(0,-100,100) 38050#@gui : Normalize Input = bool(0) 38051#@gui : sep = separator() 38052#@gui : Gradient Preset = choice("User-Defined","Black to White","White to Black","Sepia","Solarize") 38053#@gui : Interpolation Type = choice(1,"Nearest","Linear","Cubic","Lanczos") 38054#@gui : Preserve Initial Brightness = bool(0) 38055#@gui : sep = separator() 38056#@gui : note = note("<small><u>User-defined gradient :</u></small>") 38057#@gui : Number of Tones = int(5,2,8) 38058#@gui : 1st Tone = color(0,0,0,255) 38059#@gui : 2nd Tone = color(43,25,55,255) 38060#@gui : 3rd Tone = color(158,137,189,255) 38061#@gui : 4th Tone = color(224,191,228,255) 38062#@gui : 5th Tone = color(255,255,255,255) 38063#@gui : 6th Tone = color(255,255,255,255) 38064#@gui : 7th Tone = color(255,255,255,255) 38065#@gui : 8th Tone = color(255,255,255,255) 38066#@gui : sep = separator() 38067#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38068#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38069#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38070#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38071#@gui : sep = separator() 38072#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 38073fx_bwrecolorize : 38074 remove_opacity 38075 if $4 n 0,255 fi 38076 if $5==0 # User-defined gradient 38077 (${9--2}) r. 4,$8,1,1,-1 permute. yzcx 38078 elif $5==1 # Black to white 38079 (0,255^0,255^0,255^255,255) 38080 elif $5==2 # White to black 38081 (255,0^255,0^255,0^255,255) 38082 elif $5==3 # Sepia 38083 (0,44,115,143,196,244^0,20,84,119,184,235^0,5,44,73,144,200^255,255,255,255,255,255) 38084 else # Solarize 38085 (0,359^1,1^1,1^255,255) r. 256,1,1,4,3 sh. 0,2 hsv2rgb. rm. 38086 fi 38087 if $6==0 r. 256,1,1,4,1 38088 elif $6==1 r. 256,1,1,4,3 38089 elif $6==2 r. 256,1,1,4,5 c. 0,255 38090 else r. 256,1,1,4,6 38091 fi 38092 if $7==1 sh. 0,2 rgb2hsv. sh. 2 f. x/w hsv2rgb.. rm[-2,-1] fi 38093 l[^-1] luminance adjust_colors ${1-3} endl map[^-1] . rm. 38094 38095fx_bwrecolorize_preview : 38096 gui_split_preview "fx_bwrecolorize ${^0}",${-3--1} 38097 38098#@gui Colorize Lineart [Auto-Fill] : fx_autofill_lineart, fx_autofill_lineart_preview(0) 38099#@gui : Contour Threshold (%) = float(90,0,100) 38100#@gui : Contour Normalization = bool(1) 38101#@gui : Minimal Region Area = int(8,0,256) 38102#@gui : Tolerance to Gaps = int(0,0,10) 38103#@gui : Preview Type = choice("Lineart + Colors","Colors Only") 38104#@gui : sep = separator() 38105#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/12/11</i>.</small>") 38106fx_autofill_lineart : 38107 repeat $! l[$>] nm=${-gui_layer_name} 38108 38109 # Format input lineart to expected format. 38110 is_alpha={s==2||s==4} 38111 if $is_alpha sh 100% is_alpha={im<128&&iM>128} rm. fi # Check is alpha-channel contains lineart 38112 if $is_alpha +channels 100% negate. 38113 else +norm fi 38114 n. 0,255 38115 l. 38116 38117 # Start multi-scale filling. 38118 repeat 1+$4 38119 fact={2^-$<} 38120 nw={0,max(1,round(w*$fact))} 38121 nh={0,max(1,round(h*$fact))} 38122 +r[0] $nw,$nh,1,1,2 if $2 normalize_local. , fi +>=. {min(99.5,$1)}% 38123 38124 if $colors 38125 scale2x[colors] r[colors] .,1 *[colors,-1] rv[-2,-1] 38126 fi 38127 38128 label_fg. 0,1 b.. 0.8 watershed. .. rm.. nm. colors 38129 done 38130 38131 # Inpaint regions that are too small. 38132 +area. 0,1 label_maxarea={"P=[xM,yM];i(#-2,P)-1"} 38133 if $3>1 38134 >. {$3*sqrt($3)} *[-2,-1] 38135 b.. 0.8 watershed. .. 38136 else 38137 rm. 38138 fi 38139 rm.. 38140 38141 # Colorize regions. 38142 N={iM} 38143 if $N 38144 -. 1 38145 srand 0 {iM+1},1,1,3,">[j(-1) + u(135,225),u(0,0.7),u(0.4,0.9)]" 38146 hsv2rgb. round. point. $label_maxarea,0,0,1,255 38147 map.. . rm. 38148 fi 38149 endl 38150 38151 # Format output layers. 38152 if !$is_alpha gui_set_layer_mode.. multiply fi 38153 gui_set_layer_name. $nm" [colors]" 38154 endl done 38155 38156fx_autofill_lineart_preview : 38157 repeat $! l[$>] 38158 fx_autofill_lineart ${1-4} 38159 if $5 k. else rv blend multiply fi 38160 endl done 38161 38162#@gui Colorize Lineart [Smart Coloring] : fx_colorize_lineart_smart, fx_colorize_lineart_smart_preview(0) 38163#@gui : Colorize Mode = choice("Generate Random-Colors Layer","Extrapolate Color Spots on Transparent Top Layer", 38164#@gui : "Auto-Clean Bottom Color Layer") 38165#@gui : sep = separator() 38166#@gui : note = note{"<small><b>Global geometry parameters:</b></small>"} 38167#@gui : Contour Detection (%) = float(95,0,100) 38168#@gui : Discard Contour Guides = bool(0) 38169#@gui : note = note{"<small>Add strokes with a saturated color having value 255 (e.g. pure red) on your lineart 38170#@gui : allows to guide the colorization algorithm with virtual contours.</small>"} 38171#@gui : Output Region Delimiters = _bool(0) 38172#@gui : sep = separator() 38173#@gui : note = note{"<small><b>For <i>Random colors</i> mode only:</b></small>"} 38174#@gui : Make Hue Depends on Region Size = float(1,0,1) 38175#@gui : Maximal Color Saturation = int(24,0,255) 38176#@gui : Minimal Color Intensity = int(200,0,255) 38177#@gui : sep = separator() 38178#@gui : note = note{"<small><b>For <i>color spots</i> mode only:</b></small>"} 38179#@gui : Color Shading (%) = int(0,0,100) 38180#@gui : sep = separator() 38181#@gui : note = note{"<small><b>Connection parameters:</b></small>"} 38182#@gui : End Point Rate (%) = float(75,0,100) 38183#@gui : End Point Connectivity = int(2,1,5) 38184#@gui : Spline Max Length (px) = float(60,0,256) 38185#@gui : Segment Max Length (px) = float(20,0,256) 38186#@gui : Spline Max Angle (deg) = float(90,0,180) 38187#@gui : Spline Roundness = float(1,0,2) 38188#@gui : Minimal Region Area = float(10,0,100) 38189#@gui : Allow Self Intersections = bool(1) 38190#@gui : sep = separator() 38191#@gui : Preview Type = choice(0,"Colored geometry","Colored regions","Colored lineart") 38192#@gui : sep = separator() 38193#@gui : note = note("<small>Authors: <i>David Tschumperlé</i>, <i>Sébastien Fourey</i> and 38194#@gui : <i>David Revoy</i>. Latest Update: <i>2018/11/09</i>.</small>") 38195fx_colorize_lineart_smart : 38196 _fx_colorize_lineart_smart $*,-1 round 38197 38198fx_colorize_lineart_smart_preview : 38199 if $1==1" && "$!<2 gui_warning_preview "A top layer with color spots is missing, for this colorization mode." return 38200 elif $1==2" && "$!<2 gui_warning_preview "A bottom color layer is missing, for this colorization mode." return 38201 fi 38202 _fx_colorize_lineart_smart ${1-3},0,${5--1} 38203 38204_fx_colorize_lineart_smart : 38205 if $1==1" && "$!<2 error "A top layer with color strokes is missing, for this colorization mode." 38206 elif $1==2" && "$!<2 error "A bottom color layer is missing, for this colorization mode." 38207 fi 38208 min_color_area={$15^2} 38209 38210 repeat $1?1:$! inds=${arg\ 1+!!$1,$<,0--1} l[$inds] 38211 38212 ind_lineart={$1==1?1:0} 38213 nm=${gui_layer_name[$ind_lineart]} nm[$ind_lineart] lineart 38214 38215 if $!>1 ind_colors={$1==1?0:1} nmc={$ind_colors,n} nm[$ind_colors] colors fi 38216 if $!>=3 rm[2--1] fi # Delete old color and added contour layers if any 38217 38218 # Constrain input lineart to be a binary, single channel image. 38219 [lineart] 38220 is_alpha={s==2||s==4} 38221 if $is_alpha sh. 100% is_alpha={iM-im>64} rm. fi 38222 if $is_alpha channels. 100% 38223 else luminance. negate. fi 38224 >. {255*(1-$2%)} 38225 nm. strokes 38226 38227 # Retrieve closed binary shape. 38228 _keep_keycoords={$-1==0} 38229 [strokes] close_binary. ${9-14},$min_color_area,$16 nm. new_strokes 38230 38231 if $-1==0 # Render estimated geometry 38232 +negate[strokes] *. 255 to_rgb. 38233 +-[new_strokes] [strokes] dilate. 2 38234 100%,100%,1,3,[0,128,255] j... .,0,0,0,0,1,.. rm[-2,-1] 38235 if narg($keycoords) f[keycoords] "ellipse(#-1,(I)[0,2],3,3,0,1,[255,0,0]);I" rm[keycoords] fi 38236 nm. geometry 38237 fi 38238 38239 # Label color regions and inpaint strokes. 38240 if $1==1 # Mode: Color spots-guided colorization 38241 to_rgba[$colors] [colors],[colors] 38242 f[colors] "i(#-1) = A<255?0:norm(R,G+0.3,B+0.6);I" 38243 label_fg. 0 {1+iM},1,1,{colors,s+1} 38244 f.. ">I[#-1,i]+=[ I(#"$colors"),1 ];I" 38245 s. c,{-s+1} /[-2,-1] 38246 +l[new_strokes] * -1 + 1 +b 1% b.. 1 min endl 38247 watershed... .,0 rm. map.. . rm. 38248 38249 if !$8 rm[strokes] # No color shading 38250 else # Shade colors 38251 j[strokes] [new_strokes] distance[strokes] 0 *[strokes] -1 38252 eq[new_strokes] 0 label_fg[new_strokes] 0,0 38253 if $min_color_area +area_fg[new_strokes] 0,0 >. $min_color_area *[new_strokes,-1] fi 38254 watershed[new_strokes] [strokes],0 rm[strokes] 38255 srgb2rgb. guided. [new_strokes],{1+$8/5},0 rgb2srgb. 38256 fi 38257 rm[new_strokes] 38258 nm. new_colors 38259 38260 elif $1==2 # Mode: Clean color layer 38261 j[strokes] [new_strokes] distance[strokes] 0 *[strokes] -1 38262 eq[new_strokes] 0 label_fg[new_strokes] 0,0 38263 if $min_color_area +area_fg[new_strokes] 0,0 xy_bg={[xM,yM]} >. $min_color_area *[new_strokes,-1] fi 38264 watershed[new_strokes] [strokes],0 rm[strokes] 38265 to_color[colors] sh[colors] 0,2 rgb2hsv8. rm. blend[colors,new_strokes] shapemedian sh[colors] 0,2 hsv82rgb. rm. 38266 nm[colors] new_colors 38267 38268 else # Mode: Random colorization 38269 j[strokes] [new_strokes] distance[strokes] 0 *[strokes] -1 38270 eq[new_strokes] 0 label_fg[new_strokes] 0,0 38271 if $min_color_area +area_fg[new_strokes] 0,0 xy_bg={[xM,yM]} >. $min_color_area *[new_strokes,-1] fi 38272 watershed[new_strokes] [strokes],0 rm[strokes] 38273 label[new_strokes] 0,0 38274 +histogram[new_strokes] {new_strokes,[iM+1,0,iM]} equalize. 1024 n. 0,240 38275 ind_bg={xM} 38276 channels. 0,2 srand 0 38277 f. "[i,u(1,max(3,$6))/255,u(min(252,$7),255)/255]" 38278 . sh. 0 rand. 0,360 rm. 38279 hsi2rgb[-2,-1] *.. $5 *. {1-$5} +[-2,-1] round. 38280 point. $ind_bg,0,0,1,255 point. 0,0,0,1,255 38281 38282 map[new_strokes] . rm. 38283 nm[new_strokes] new_colors 38284 fi 38285 38286 # Final rendering 38287 ind_lineart=$lineart 38288 ind_colors=$new_colors 38289 38290 if $4 # Output region delimiters 38291 100%,100%,1,1,"const boundary = 1; 38292 J(#"$new_colors",1)!=I(#"$new_colors") || J(#"$new_colors",0,1)!=I(#"$new_colors")" 38293 *. 255 channels. -3,0 sh. 0,2 fc. 255,0,0 rm. 38294 gui_set_layer_name. $nm" [region delimiters]" 38295 mv. {$lineart+1} 38296 fi 38297 if !narg($nmc) gui_set_layer_name[$ind_colors] $nm" [colors]" fi 38298 gui_set_layer_name[$ind_lineart] $nm 38299 38300 if $-1==-1 # Rendering : Lineart and color layers 38301 if !$is_alpha gui_set_layer_mode[$ind_lineart] multiply fi 38302 if $3 l[{$1==1?1:0}] # Discard contour guides 38303 if $is_alpha 38304 100%,100%,1,3,255 blend. [0],alpha,1 rgb2hsv. channels. 2 *. 255 negate. 38305 channels.. 0,{0,s-2} s={0,s} luminance[0] to_colormode[0] $s a c 38306 else 38307 s={s} to_rgb rgb2hsv channels 2 * 255 to_colormode $s 38308 fi 38309 endl fi 38310 38311 elif $-1==0 # Preview : Colored geometry 38312 if $is_alpha channels[$ind_lineart] 100% negate[$ind_lineart] fi to_rgb[$ind_lineart] 38313 n[$ind_lineart] 180,255 38314 blend[$ind_lineart,$ind_colors] multiply 38315 +select_color[geometry] 0,255,255,255 ==. 0 j[$ind_lineart] [geometry],0,0,0,0,1,. k[$ind_lineart] 38316 elif $-1==1 # Preview : Colored regions 38317 k[$ind_colors] 38318 else # Preview : Colored lineart 38319 if $is_alpha channels[$ind_lineart] 100% negate[$ind_lineart] fi to_rgb[$ind_lineart] 38320 if $3 l[$ind_lineart] s={s} to_rgb rgb2hsv channels 2 * 255 to_colormode $s endl fi 38321 blend[$ind_lineart,$ind_colors] multiply k[$ind_lineart] 38322 fi 38323 38324 endl done 38325 38326#@gui Colorize Lineart [Propagation] : fx_colorize_lineart, fx_colorize_lineart_preview(1) 38327#@gui : note = note("<b>Layers ordering:</b>") 38328#@gui : Input Layers = choice{0,"Color Spots + Lineart","Lineart + Color Spots", 38329#@gui : "Color Spots + Extrapolated Colors + Lineart","Lineart + Color Spots + Extrapolated Colors"} 38330#@gui : Output Layers = _choice{1,"Single (Merged)","Extrapolated Colors + Lineart", 38331#@gui : "Lineart + Extrapolated Colors","Color Spots + Extrapolated Colors + Lineart", 38332#@gui : "Lineart + Color Spots + Extrapolated Colors"} 38333#@gui : Extrapolate Colors As = choice("One Layer","Two Layers","Three Layers","Four Layers","Five Layers", 38334#@gui : "Six Layers","Seven Layers","Eight Layers","Nine Layers","Ten Layers","One Layer per Single Color", 38335#@gui : "One Layer per Single Region") 38336#@gui : sep = separator() 38337#@gui : Smoothness = float(0.05,0,1) 38338#@gui : sep = separator() 38339#@gui : note = note{"<small><b>Note:</b> You probably need to select <i>All</i> for the <i>Input layers</i> option 38340#@gui : on the left.\n 38341#@gui : <i>Color Spots</i> = your layer with color indications.\n 38342#@gui : <i>Lineart</i> = your layer with line-art (B&W or transparent).\n 38343#@gui : <i>Extrapolated Colors</i> = the G'MIC generated layer with flat colors.\n\n 38344#@gui : <b>Warnings:</b> 38345#@gui : \n - Do not rely too much on the preview, it is probably not accurate ! 38346#@gui : \n - Activate option <i>Extrapolate color as one layer per single color/region</i> only if you have 38347#@gui : <i>a lot</i> of available memory ! 38348#@gui : </small>"} 38349#@gui : sep = separator() 38350#@gui : url = link("Click here for a detailed description of this filter.",\ 38351# "http://www.gimpchat.com/viewtopic.php?f=28&t=7567") 38352#@gui : sep = separator() 38353#@gui : note = note("<small>Authors: <i>David Tschumperlé</i>, <i>Timothée Giet</i> and <i>David Revoy</i>. 38354#@gui : Latest Update: <i>2013/19/06</i>.</small>") 38355fx_colorize_lineart : 38356 if $!<2 return fi 38357 if $1<2 selection=0,1 else selection=0,1,2 fi 38358 l[$selection] 38359 38360 # Format input layers. 38361 if $1==0 # Color strokes + drawing 38362 elif $1==1 rv # Drawing + color strokes 38363 elif $1==2 rm[1] # Color strokes + extrapolated colors + drawing 38364 elif $1==3 rm[2] rv # Drawing + color strokes + extrapolated colors. 38365 fi 38366 38367 # Here we have only 'color strokes + drawing' -> process. 38368 +to_rgba[0] split_opacity. +.. 1 !=. 0 *[-2,-1] # Map of color labels to spread. 38369 +norm[1] n. 0,1 +histogram. 2,0,1 38370 if i(0)>i(1) *.. -1 +.. 1 fi rm. # Determine color model of the drawing. 38371 b. $4% watershed.. . rm. # Priority map. 38372 -. 1 38373 # Here we have 'color strokes + drawing + extrapolated colors'. 38374 38375 # Format output layers. 38376 if $2==0 rm[0] rv blend[0,1] multiply ind=-1 38377 elif $2==1 rm[0] rv ind=0 38378 elif $2==2 rm[0] ind=1 38379 elif $2==3 rv[1,2] ind=1 38380 elif $2==4 rv[0,1] ind=2 38381 fi 38382 38383 # Separate extrapolated colors as multiple layers. 38384 if $3" && "$ind>=0 l[$ind] 38385 +mix_channels (65536,256,1) 38386 if $3==10 do # Split by colors. 38387 iM={1,iM} 38388 if $iM>=0 38389 +==[1] $iM area={is} replace[1] $iM,-1 38390 +r. 100%,100%,1,3 *. [0] 38391 rv[-2,-1] *. 255 a[-2,-1] c nm. $area 38392 fi 38393 while $iM>=0 else # Split by disconnected regions. 38394 label. 38395 if $3<10 %. {$3+1} fi 38396 repeat iM+1 +==[1] $< area={is} +r. 100%,100%,1,[0] *. [0] rv[-2,-1] *. 255 a[-2,-1] c nm. $area done 38397 fi 38398 rm[0,1] 38399 sort_list +,n 38400 endl fi 38401 38402 endl 38403 38404fx_colorize_lineart_preview : 38405 fx_colorize_lineart $1,0,$3,$4 38406 38407#@gui Dithering : fx_ditheredbw, fx_ditheredbw_preview(0) 38408#@gui : Brightness (%) = float(0,-100,100) 38409#@gui : Contrast (%) = float(0,-100,100) 38410#@gui : Gamma (%) = float(0,-100,100) 38411#@gui : Hue = float(0,0,360) 38412#@gui : Saturation (%) = float(0,0,100) 38413#@gui : Smoothness = float(0,0,10) 38414#@gui : sep = separator() 38415#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38416#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38417#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38418#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38419#@gui : sep = separator() 38420#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 38421fx_ditheredbw : 38422 repeat $! l[$>] split_opacity l[0] 38423 luminance adjust_colors ${1-3} b $6 38424 ditheredbw 38425 if $4" || "$5 / 255 i[0] 100%,100%,1,2 fc[0] $4,{$5%} a c hsv2rgb fi 38426 endl a c endl done 38427 38428fx_ditheredbw_preview : 38429 gui_split_preview "fx_ditheredbw $*",${-3--1} 38430 38431#@gui Engrave : fx_engrave, fx_engrave_preview(0) 38432#@gui : note = note("<small><b>Black & White foreground:</b></small>") 38433#@gui : Radius = float(0.5,0,2) 38434#@gui : Density = float(50,0,200) 38435#@gui : Edges = float(0,0,10) 38436#@gui : Coherence = float(8,0,40) 38437#@gui : Threshold (%) = float(40,0,100) 38438#@gui : Minimal Area = int(0,-256,256) 38439#@gui : Flat Regions Removal = float(0,0,10) 38440#@gui : sep = separator() 38441#@gui : note = note("<small><b>Color background:</b></small>") 38442#@gui : Add Color Background = bool() 38443#@gui : Quantization = float(10,0,40) 38444#@gui : Shading = int(1,0,5) 38445#@gui : Hue = float(0,-180,180) 38446#@gui : Saturation (%) = float(0,-100,100) 38447#@gui : Lightness (%) = float(0,-100,100) 38448#@gui : sep = separator() 38449#@gui : Anti-Aliasing = choice(1,"Disabled","x1.5","x2","x3") 38450#@gui : sep = separator() 38451#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38452#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38453#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38454#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38455#@gui : sep = separator() 38456#@gui : note = note("<small>Authors: <i>Lyle Kroll</i> and <i>David Tschumperlé</i>. 38457#@gui : Latest Update: <i>03/13/2015</i>.</small>") 38458fx_engrave : 38459 f={arg(1+$14,1,1.5,2,3)} 38460 r={$f*(0.2+$1)} 38461 repeat $! l[$<] 38462 nm=${-gui_layer_name} pos=${-gui_layer_pos} 38463 if $8 [0] fi # Keep copy for color background. 38464 l[0] split_opacity l[0] 38465 wh={w},{h} 38466 norm 38467 if $14 r {100*$f}%,{100*$f}%,1,1,3 fi 38468 if $7>0 [0] fi # Keep copy for flat regions removal. 38469 l[0] 38470 amount={(0.5+$2)^2} 38471 repeat 5 b $r unsharp $r,{1+$2} c 0,255 done 38472 smooth 100,0.1,1,{$f*$3},{$f*$4} 38473 >= {100-$5}% 38474 endl 38475 if $7>0 # Flat region removal. 38476 gradient_norm[1] b[1] $3 <[1] $7 max[0,1] 38477 fi 38478 if $6<0 area_fg 0,0 > {$f*$6*$6} 38479 elif $6>0 == 0 area_fg 0,0 > {$f*$6*$6} == 0 38480 fi 38481 * 255 38482 if $14 r $wh,1,1,2 fi 38483 endl a c endl 38484 38485 # Process color background. 38486 if $!>1 38487 l[1] split_opacity l[0] 38488 f={arg(1+$14,1,1.5,2,3)} 38489 if $14 r {100*$f}%,{100*$f}%,1,100%,3 fi 38490 b {$f*$9} segment_watershed 5 38491 if $14 r $wh,1,100%,2 fi 38492 repeat $10 guided 10,{$10*80} done 38493 rgb2hsv s c +... $11 +.. {$12%} +. $13% a c hsv2rgb 38494 endl a c endl 38495 nm[0] mode(darken),name($nm),pos($pos) 38496 nm[1] name($nm" [colors]"),pos($pos) 38497 fi 38498 38499 endl done 38500 38501fx_engrave_preview : 38502 repeat $! l[$<] 38503 gui_split_preview "nm foo fx_engrave $* gui_merge_layers",${-3--1} 38504 endl done 38505 38506#@gui Freaky B&W : fx_freaky_bw, fx_freaky_bw_preview 38507#@gui : Strength (%) = float(90,0,100) 38508#@gui : Oddness (%) = float(20,0,100) 38509#@gui : Brightness (%) = float(0,-100,100) 38510#@gui : Contrast (%) = float(0,-100,100) 38511#@gui : Gamma (%) = float(0,-100,100) 38512#@gui : sep = separator() 38513#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38514#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38515#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38516#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38517#@gui : sep = separator() 38518#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/30/09</i>.</small>") 38519fx_freaky_bw : 38520 repeat $! l[$>] split_opacity l[0] 38521 to_rgb 38522 38523 # Estimate gradient field of B&W result. 38524 +expand_xy 1,0 channels. 0,4 38525 f. ">if (c!=4,i, 38526 Rx = i(x+1,y,0,0) - i(x,y,0,0); 38527 Ry = i(x,y+1,0,0) - i(x,y,0,0); 38528 Rn = Rx^2 + Ry^2; 38529 Gx = i(x+1,y,0,1) - i(x,y,0,1); 38530 Gy = i(x,y+1,0,1) - i(x,y,0,1); 38531 Gn = Gx^2 + Gy^2; 38532 Bx = i(x+1,y,0,2) - i(x,y,0,2); 38533 By = i(x,y+1,0,2) - i(x,y,0,2); 38534 Bn = Bx^2 + By^2; 38535 n = 1e-5 + max(Rn,Gn,Bn)^"{$2%}"; 38536 val = 0; 38537 if (Rn>=Gn && Rn>=Bn, 38538 i(x,y,0,3) = Rx/n; val=Ry/n, 38539 if (Gn>=Rn && Gn>=Bn, 38540 i(x,y,0,3) = Gx/n; val=Gy/n, 38541 i(x,y,0,3) = Bx/n; val=By/n)); 38542 val 38543 )" 38544 channels. 3,4 38545 luminance[0] ia={0,ia} 38546 38547 # Estimate laplacian of final image and invert it. 38548 s. c 38549 f.. "i - i(x-1,y,0,0)" 38550 f. "i - i(x,y-1,0,0)" 38551 +[-2,-1] 38552 ilaplacian. 0 38553 shrink_xy. 1 +. $ia n. 0,255 38554 38555 # Merge result with original color image. 38556 j[0] [1],0,0,0,0,{$1%} rm. 38557 adjust_colors ${3-5} 38558 endl a c endl done 38559 38560fx_freaky_bw_preview : 38561 gui_split_preview "fx_freaky_bw $*",${-3--1} 38562 38563#@gui Ink Wash : fx_ink_wash, fx_ink_wash(0) 38564#@gui : note = note("Ink wash controls") 38565#@gui : Size = float(0.14,0,4) 38566#@gui : Amplitude = float(23,0,200) 38567#@gui : sep = separator() 38568#@gui : note = note("Check if you wish visual control on this step") 38569#@gui : Skip All Other Steps = bool(false) 38570#@gui : note = note ("UNcheck to reactivate the other controls") 38571#@gui : sep = separator() 38572#@gui : Smoother Sharpness = float(0.5,0,2) 38573#@gui : Smoother Edge Protection = float(0.54,0,1) 38574#@gui : Smoother Softness = float(2.25,0,10) 38575#@gui : sep = separator() 38576#@gui : Stretch Contrast = choice("None","Automatic","Automatic & Contrast Mask","Manual Controls") 38577#@gui : note = note ("To activate the sliders below chose 'Manual Controls'") 38578#@gui : sep = separator() 38579#@gui : LN Amplitude = float(2,0,60) 38580#@gui : LN Size = float(6,0,64) 38581#@gui : LN Neightborhood-Smoothness = float(5,0,40) 38582#@gui : LN Average-Smoothness = float(20,0,40) 38583#@gui : sep = separator() 38584#@gui : note = note("<small>Author: <i>PhotoComiX</i>. 38585#@gui : Latest Update: <i>2011/05/04</i>.</small>") 38586#@gui : url = link(0,"Forum thread about the filter discussion","http://gimpchat.com/viewtopic.php?f=10&t=914") 38587fx_ink_wash : 38588 repeat $! l[$>] split_opacity l[0] 38589 fx_pencilbw. $1,$2,0,0,0 38590 if $3==1 continue 38591 elif $3==0 fx_smooth_anisotropic. 60,$4,$5,$6,1.1,0.8,30,2,0,1,1,0,1,16 38592 fi 38593 if $7==1 normalize_local. 2,6,5,24,1,0,255 38594 elif $7==2 normalize_local. 2,6,5,24,1,0,255 fx_contrast_swm 2,0,0.512 38595 elif $7==3 fx_normalize_local. $8,$9,$10,$11,1,3,0 38596 fi 38597 endl a c endl done 38598 38599#@gui Pencil : fx_pencilbw, fx_pencilbw_preview(0) 38600#@gui : Size = float(0.3,0,5) 38601#@gui : Amplitude = float(60,0,200) 38602#@gui : Hue = float(0,0,360) 38603#@gui : Saturation = float(0,0,1) 38604#@gui : sep = separator() 38605#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38606#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38607#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38608#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38609#@gui : sep = separator() 38610#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/05/03</i>.</small>") 38611fx_pencilbw : 38612 pencilbw $1,$2 38613 if $3" || "$4 repeat $! l[$>] split_opacity 38614 /[0] 255 i[0] 100%,100%,1,1,$4 i[0] 100%,100%,1,1,$3 a[0-2] c hsv2rgb[0] 38615 a c endl done fi 38616 38617fx_pencilbw_preview : 38618 gui_split_preview "fx_pencilbw $*",${-3--1} 38619 38620#@gui Pencil Portrait : fx_pencil_portraitbw, fx_pencil_portraitbw_preview(0) 38621#@gui : Stroke Length = float(30,0,500) 38622#@gui : Stroke Angle = float(120,0,180) 38623#@gui : Contour Threshold = float(1,0,10) 38624#@gui : Opacity = float(0.5,0,1) 38625#@gui : Color = color(144,79,21) 38626#@gui : sep = separator() 38627#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38628#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38629#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38630#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38631#@gui : sep = separator() 38632#@gui : note = note("<small>Authors: <i>Jamac4k</i> and <i>David Tschumperlé</i>. 38633#@gui : Latest Update: <i>2015/29/06</i>.</small>") 38634fx_pencil_portraitbw : 38635 repeat $! l[$>] split_opacity l[0] 38636 +b 2% 38637 +blend divide rm.. luminance. 38638 fx_ink_wash.. 0,167,0,0.5,0.54,2.25,0,2,6,5,20 38639 +fx_hardsketchbw. 80,32,1.89,0.21,31.46,0,0 38640 +fx_sketchbw.. 1,$2,180,$1,$3,0.03,0,0.6,0.1,0.6,0.25,1,0,1,0 38641 blend[0,1] darken 38642 blend[0,1] multiply,0.5 38643 blend[0,1] lighten,$4 38644 normalize_local , 38645 to_rgb +fc ${5-7} blend softlight 38646 endl a c endl done 38647 38648fx_pencil_portraitbw_preview : 38649 gui_split_preview "fx_pencil_portraitbw $*",${-3--1} 38650 38651#@gui Stamp : fx_stamp, fx_stamp_preview(0) 38652#@gui : Auto-Threshold = bool(1) 38653#@gui : Threshold = int(50,0,100) 38654#@gui : Smoothness = float(0,0,10) 38655#@gui : Sharpening = float(0,0,30) 38656#@gui : Grain = float(0,0,100) 38657#@gui : Negative = bool() 38658#@gui : Anti-Aliasing = bool(1) 38659#@gui : sep = separator() 38660#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38661#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38662#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38663#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38664#@gui : sep = separator() 38665#@gui : note = note("<small>Authors: <i>Antaron</i>, <i>Mahvin</i> and <i>David Tschumperlé</i>. 38666#@gui : Latest Update: <i>2015/16/03</i>.</small>") 38667fx_stamp : 38668 repeat $! l[$>] split_opacity l[0] 38669 wh={w},{h} 38670 norm 38671 if $7 r 150%,150%,1,1,3 fi 38672 noise $5 38673 if $1 otsu 256 else >= $2% fi 38674 b {if($7,1.5,1)*$3},0 sharpen $4 n 0,255 38675 apply_curve 1,0,0,101,33,170,229,255,255 38676 if $7 r $wh,1,1,2 fi 38677 if $6 negate fi 38678 endl a c endl done 38679 38680fx_stamp_preview : 38681 gui_split_preview "fx_stamp $*",${-3--1} 38682 38683 38684#@gui ____<b>Colors</b> 38685#---------------------- 38686 38687#@gui Abstraction : fx_color_abstraction, fx_color_abstraction_preview(0) 38688#@gui : Smoothness = float(1,0,10) 38689#@gui : Levels = int(10,2,100) 38690#@gui : Contrast = float(0.2,0.01,1) 38691#@gui : sep = separator() 38692#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38693#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38694#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38695#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38696#@gui : sep = separator() 38697#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/19/10</i>.</small>") 38698fx_color_abstraction : 38699 repeat $! l[$>] split_opacity l[0] to_rgb 38700 b $1 s c quantize $2,1,0 area 0 ^ $3 n 0,255 38701 endl a c endl done 38702 38703fx_color_abstraction_preview : 38704 gui_split_preview "fx_color_abstraction $*",${-3--1} 38705 38706#@gui Apply External CLUT : fx_apply_haldclut, fx_apply_haldclut_preview(1)+ 38707#@gui : Specify HaldCLUT As = choice(2,"Top Layer","Bottom Layer","Filename") 38708#@gui : HaldCLUT Filename = filein() 38709#@gui : note = note("<small><b>Note:</b> Do not forget to set the <i>Input layers</i> option if you select 38710#@gui : <i>Top layer</i> or <i>Bottom layer</i>.</small>") 38711#@gui : sep = separator() 38712#@gui : Strength (%) = float(100,0,100) 38713#@gui : Brightness (%) = float(0,-100,100) 38714#@gui : Contrast (%) = float(0,-100,100) 38715#@gui : Gamma (%) = float(0,-100,100) 38716#@gui : Hue (%) = float(0,-100,100) 38717#@gui : Saturation (%) = float(0,-100,100) 38718#@gui : Normalize Colors = choice("None","Pre-Normalize","Post-Normalize","Both") 38719#@gui : sep = separator() 38720#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38721#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38722#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38723#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38724#@gui : sep = separator() 38725#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/02/08</i>.</small>") 38726fx_apply_haldclut : skip "${2=}" 38727 mode=$1 38728 filename="$2" 38729 strength,brightness,contrast,gamma,hue,saturation,normalize=${3-9} 38730 38731 if $mode<2 # CLUT as a layer 38732 if $!<2 gui_warning_preview "Input layer with HaldCLUT is missing" return fi 38733 ind_clut={$mode?$!-1:0} 38734 else # CLUT as a file 38735 l 38736 0 nm. "$2" ext={x} rm. 38737 if lowercase(['$ext'])=='cube' input_cube "$2" 38738 else i "$2" 38739 fi 38740 ind_clut={$!-1} 38741 onfail gui_warning_preview "Specified HaldCLUT filename not found" return 38742 endl 38743 fi 38744 if {$ind_clut,iM>512} /[$ind_clut] 255 fi # Possibly a 16bits HaldCLUT. 38745 38746 if $normalize==1" || "$normalize==3 # Pre-normalization 38747 repeat $! if $>!=$ind_clut l[$>] split_opacity balance_gamma[0] , a c endl fi done 38748 fi 38749 repeat $! if $>!=$ind_clut +map_clut[$>] [$ind_clut] j[$>] .,0,0,0,0,{$strength%} rm. fi done rm[$ind_clut] 38750 adjust_colors $brightness,$contrast,$gamma,$hue,$saturation,0,255 38751 if $normalize==2" || "$normalize==3 # Post-normalization 38752 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done 38753 fi 38754 38755fx_apply_haldclut_preview : skip "${2=}" 38756 if $1<2 gui_warning_preview "No preview available in this mode" return fi 38757 gui_split_preview "fx_apply_haldclut $1,\"$2\",${3--2}",${-3--1} 38758 38759#@gui Basic Adjustments : fx_adjust_colors, fx_adjust_colors_preview 38760#@gui : Brightness (%) = float(0,-100,100) 38761#@gui : Contrast (%) = float(0,-100,100) 38762#@gui : Gamma (%) = float(0,-100,100) 38763#@gui : Hue (%) = float(0,-100,100) 38764#@gui : Saturation (%) = float(0,-100,100) 38765#@gui : sep = separator() 38766#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38767#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38768#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38769#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38770#@gui : sep = separator() 38771#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/16/06</i>.</small>") 38772fx_adjust_colors : 38773 adjust_colors ${1-5},0,255 38774 38775fx_adjust_colors_preview : 38776 gui_split_preview "fx_adjust_colors $*",${-3--1} 38777 38778#@gui Boost Chromaticity : fx_boost_chroma, fx_boost_chroma_preview(1) 38779#@gui : Amplitude (%) = float(50,0,100) 38780#@gui : Color Space = choice{"YCbCr (Distinct)","YCbCr (Mixed)","Lab (Distinct)","Lab (Mixed)"} 38781#@gui : sep = separator() 38782#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38783#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38784#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38785#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38786#@gui : sep = separator() 38787#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/19/07</i>.</small>") 38788fx_boost_chroma : 38789 repeat $! l[$>] split_opacity l[0] 38790 +to_rgb 38791 if $2>=2 38792 srgb2rgb rgb2lab. 38793 if $2==2 sh. 1 sh.. 2 equalize[-2,-1] rm[-2,-1] 38794 else sh. 1,2 equalize. rm. 38795 fi 38796 lab2rgb. rgb2srgb 38797 else 38798 rgb2ycbcr. 38799 if $2==0 sh. 1 sh.. 2 equalize[-2,-1] rm[-2,-1] 38800 else sh. 1,2 equalize. rm. 38801 fi 38802 ycbcr2rgb. 38803 fi 38804 j.. .,0,0,0,0,{$1%} rm. 38805 endl a c endl done 38806 38807fx_boost_chroma_preview : 38808 gui_split_preview "fx_boost_chroma $*",${-3--1} 38809 38810#@gui Boost-Fade : fx_boost_fade, fx_boost_fade_preview 38811#@gui : Amplitude = float(5,0,10) 38812#@gui : Chromaticity From = choice("YCbCr","Lab") 38813#@gui : sep = separator() 38814#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38815#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38816#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38817#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38818#@gui : sep = separator() 38819#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/11/26</i>.</small>") 38820fx_boost_fade : 38821 repeat $! l[$>] 38822 100%,100%,1,3 rand. 0,1 b. {10-10*($1/10)^0.5} n. 0,255 38823 to_colormode 0 a z 38824 ac "s z transfer_histogram.. . rm.",${"arg 1+$2,ycbcr_cbcr,lab_ab"} 38825 endl done 38826 38827fx_boost_fade_preview : 38828 gui_split_preview "fx_boost_fade $1,$2",${-3--1} 38829 38830#@gui Channel Processing : fx_channel_processing, fx_channel_processing_preview(1) 38831#@gui : Brightness (%) = float(0,-100,100) 38832#@gui : Contrast (%) = float(0,-100,100) 38833#@gui : Gamma (%) = float(0,-100,100) 38834#@gui : Smoothness = float(0,0,10) 38835#@gui : Value Action = choice("None","Cut","Cut & Normalize","Normalize","Threshold") 38836#@gui : Low Value = float(0,0,100) 38837#@gui : High Value = float(100,0,100) 38838#@gui : Quantization = int(256,1,256) 38839#@gui : Equalization = bool(0) 38840#@gui : Negation = bool(0) 38841#@gui : sep = separator() 38842#@gui : Tones Range = choice("All tones","Shadows","Mid-Tones","Highlights") 38843#@gui : Tones Smoothness = float(2,0,10) 38844#@gui : sep = separator() 38845#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 38846#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 38847#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 38848#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 38849#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 38850#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 38851#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 38852#@gui : sep = separator() 38853#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38854#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38855#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38856#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38857#@gui : sep = separator() 38858#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 38859_fx_channel_processing : 38860 adjust_colors ${1-3} b. $4% 38861 if $5==1 c. $6%,$7% 38862 elif $5==2 c. $6%,$7% n. 0,255 38863 elif $5==3 n. $6%,$7% 38864 elif $5==4 ir. $6%,$7% *. 255 38865 fi 38866 if $8!=256 quantize. $8,1,0 fi 38867 if $9 equalize. fi 38868 if $10 negate. fi 38869 38870fx_channel_processing : 38871 repeat $! l. split_opacity rv to_rgb. 38872 fx_start_mix $11,$12 38873 ac. "_fx_channel_processing $1,$2,$3,$4,$5,$6,$7,$8,$9,$10",$13,1 38874 fx_end_mix $11 38875 if $!!=3 rv a c fi endl mv. 0 done 38876 38877fx_channel_processing_preview : 38878 gui_split_preview "fx_channel_processing $*",${-3--1} 38879 38880#@gui Channels to Layers : fx_channels2layers, fx_channels2layers_preview 38881#@gui : Colorspace = choice("RGB","CMY","HSV") 38882#@gui : sep = separator() 38883#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/15/07</i>.</small>") 38884fx_channels2layers : 38885 repeat $! l[$<] nm=${-gui_layer_name} to_rgb 38886 if $1==0 # RGB 38887 s[0] c 38888 r[0] 100%,100%,1,3,0,0,0,0,0,0 nm[0] name($nm" "[red]),mode(add) 38889 r[1] 100%,100%,1,3,0,0,0,0,0,0.5 nm[1] name($nm" "[green]),mode(add) 38890 r[2] 100%,100%,1,3,0,0,0,0,0,1 nm[2] name($nm" "[blue]),mode(add) 38891 elif $1==1 # CMY 38892 rgb2cmy[0] -[0] 255 s[0] c 38893 r[0] 100%,100%,1,3,0,0,0,0,0,0 nm[0] name($nm" "[cyan]),mode(difference) 38894 r[1] 100%,100%,1,3,0,0,0,0,0,0.5 nm[1] name($nm" "[magenta]),mode(difference) 38895 r[2] 100%,100%,1,3,0,0,0,0,0,1 nm[2] name($nm" "[yellow]),mode(difference) 38896 +[0-2] 255 38897 i[0] 100%,100%,1,3,255 nm[0] name($nm" "[base]),mode(difference) 38898 else # HSV 38899 rgb2hsv[0] s[0] c,-2 38900 r[0] 100%,100%,1,3,0,0 sh[0] 2 f. 1 rm. nm[0] name($nm" "[color]),mode(normal) 38901 r[1] 100%,100%,1,3,0,0,0,0,0,1 nm[1] name($nm" "[value]),mode(value) 38902 hsv2rgb[0,1] rv[0,1] 38903 fi 38904 endl done 38905 38906fx_channels2layers_preview : 38907 repeat $! l[$>] 38908 fx_channels2layers $* 38909 repeat $! l[$>] to "#"{1+$>},1,1,43,7,1,255 endl done 38910 frame 1,1,0 frame 3,3,255 append_tiles , 38911 endl done 38912 38913#@gui Color Balance : fx_balance_gamma, fx_balance_gamma_preview 38914#@gui : Neutral Color = color(128,128,128) 38915#@gui : Stretch Colors = bool(1) 38916#@gui : sep = separator() 38917#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38918#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38919#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38920#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38921#@gui : sep = separator() 38922#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/01/07</i>.</small>") 38923fx_balance_gamma : 38924 repeat $! l[$>] split_opacity 38925 if $!>1 +!=. 0 *[0,-1] fi 38926 l[0] 38927 balance_gamma ${1-3} 38928 if $4 n 0,255 fi 38929 endl 38930 a c endl 38931 done 38932 38933fx_balance_gamma_preview : 38934 gui_split_preview "fx_balance_gamma $*",${-3--1} 38935 38936#@gui Color Blindness : colorblind, fx_colorblind_preview 38937#@gui : Blindness Type = choice("Protanopia","Protanomaly","Deuteranopia","Deuteranomaly","Tritanopia", 38938#@gui : "Tritanomaly","Achromatopsia","Achromatomaly") 38939#@gui : sep = separator() 38940#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38941#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38942#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38943#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38944#@gui : sep = separator() 38945#@gui : note = note{"<small><b>Note:</b> 38946#@gui : This filter simulates different types of colorblindness vision. 38947#@gui : </small>"} 38948#@gui : sep = separator() 38949#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/04</i>.</small>") 38950fx_colorblind_preview : 38951 gui_split_preview "colorblind $*",${-3--1} 38952 38953#@gui Color Presets : fx_color_presets, fx_color_presets_preview(1)+ 38954#@gui : LUTs Pack = choice{19,"Abigail Gonzalez (21)","Alex Jordan (81)","Berat (10)","Cinematic (8)", 38955#@gui : "Cinematic Travel (29)","Creative Pack (33)","Eric Ellerbrock (14)","FilterGrade Cinematic (8)", 38956#@gui : "InAvision (15)","J.T. Semple (14)","Kyler Holland (10)","Lutify.Me (7)","Michael Ezra (2)","Moviz (48)", 38957#@gui : "Ohad Peretz (7)","Olivio Sarikas (19)","ON1 Photography (90)","PictureFX (25)","Pixelmator (45)", 38958#@gui : "PIXLS.US (31)","Purple11 (12)","RocketStock (35)","Shamoon Abbasi (25)","SmallHD Movie Look (7)", 38959#@gui : "Youssef Hossam (5)","Others (69)"} 38960 38961##### Abigail Gonzales 38962#@gui : Preset = choice{1,"All [Collage]","None", 38963#@gui : "Blade Runner","Blue House","Blue Ice","Caribe","Cinema","Cinema 2","Cinema 3","Cinema 4","Cinema 5", 38964#@gui : "Cinema Noir","Cinematic for Flog","Day4Nite","Eterna for Flog","Filmic","Fuji HDR", 38965#@gui : "Golden Gate","Matrix","Monochrome 1","Monochrome 2","Old West","Science Fiction"}_0 38966 38967##### Alex Jordan 38968#@gui : Preset = choice{1,"All [Collage]","None", 38969#@gui : "Action Magenta 01","Action Red 01","Adventure 1453","Aggressive Highlights Recovery 5", 38970#@gui : "Bleech Bypass Green","Bleech Bypass Yellow 01","Blue Dark","Blue Shadows 01","Bright Green 01", 38971#@gui : "Brownish","Colorful 0209","Conflict 01","Contrast with Highlights Protection","Contrasty Afternoon", 38972#@gui : "Contrasty Green","Cross Process CP 130","Cross Process CP 14","Cross Process CP 15", 38973#@gui : "Cross Process CP 16","Cross Process CP 18","Cross Process CP 3","Cross Process CP 4", 38974#@gui : "Cross Process CP 6","Dark Green 02","Dark Green 1","Dark Place 01","Dream 1","Dream 85", 38975#@gui : "Faded Retro 01","Faded Retro 02","Film 0987","Film 9879","Film Highlight Contrast","Flat 30", 38976#@gui : "Green 2025","Green Action","Green Afternoon","Green Conflict","Green Day 01","Green Day 02", 38977#@gui : "Green G09","Green Indoor","Green Light","Harsh Day","Harsh Sunset","Highlights Protection", 38978#@gui : "Indoor Blue","Low Contrast Blue","Low Key 01","Magenta Day","Magenta Day 01","Magenta Dream", 38979#@gui : "Memories","Moonlight 01","Mostly Blue","Muted 01","Night 01","Only Red","Only Red and Blue", 38980#@gui : "Operation Yellow","Orange Dark 4","Orange Dark 7","Orange Dark Look","Orange Underexposed", 38981#@gui : "Protect Highlights 01","Red Afternoon 01","Red Day 01","Red Dream 01","Retro Brown 01", 38982#@gui : "Retro Magenta 01","Retro Yellow 01","Saturated Blue","Smart Contrast","Subtle Blue", 38983#@gui : "Subtle Green","Yellow 55B","Yellow Film 01"}_0 38984 38985##### Berat 38986#@gui : Preset = choice{1,"All [Collage]","None", 38987#@gui : "Brown BM","Cine Blue","Cine BM4k","Golden Time","Green and Orange","Monochrome","Sevsuz","Sunlight Love", 38988#@gui : "Western","Western Lut 2"}_0 38989 38990##### Cinematic 38991#@gui : Preset = choice{1,"All [Collage]","None", 38992#@gui : "Deep","Dimension","Enchanted","Flavin","Frosted","Shine","Ultra Water","Wipe"}_0 38993 38994##### Cinematic Travel 38995#@gui : Preset = choice{1,"All [Collage]","None", 38996#@gui : "Blue Cold Fade","Bright Teal Orange","Bright Warm","Clear Teal Fade","Cold Clear Blue","Cold Clear Blue 1", 38997#@gui : "Deep Blue","Deep Dark Warm","Deep High Contrast","Deep Teal Fade","Deep Warm Fade","Faded Green", 38998#@gui : "Greenish Contrasty","Greenish Fade","Greenish Fade 1","Hard Teal Orange","Neutral Teal Orange", 38999#@gui : "Neutral Warm Fade","Smooth Clear","Smooth Green Orange","Smooth Teal Orange","Teal Fade","Very Warm Greenish", 39000#@gui : "Warm Dark Contrasty","Warm Fade","Warm Fade 1","Warm Neutral","Warm Sunset Red","Warm Teal"}_0 39001 39002##### Creative Pack 39003#@gui : Preset = choice{1,"All [Collage]","None", 39004#@gui : "Anime","Bleach Bypass 1","Bleach Bypass 2","Bleach Bypass 3","Bleach Bypass 4","Candle Light", 39005#@gui : "Color Negative","Crisp Warm","Crip Winter","Drop Blues","Edgy Ember","Fall Colors","Foggy Night", 39006#@gui : "Futuristic Bleak 1","Futuristic Bleak 2","Futuristic Bleak 3","Futuristic Bleak 4","Horror Blue", 39007#@gui : "Late Sunset","Moonlight","Night From Day","Red Blue Yellow","Smokey","Soft Warming","Teal Magenta Gold", 39008#@gui : "Teal Orange","Teal Orange 1","Teal Orange 2","Teal Orange 3","Tension Green 1","Tension Green 2", 39009#@gui : "Tension Green 3","Tension Green 4"}_0 39010 39011##### Eric Ellerbrock 39012#@gui : Preset = choice{1,"All [Collage]","None", 39013#@gui : "Avalanche","Black Star","Helios","Hydracore","Hypnosis","Killstreak","Nemesis","Night Blade 4", 39014#@gui : "Paladin","Seringe 4","Serpent","Terra 4","Victory","Yellowstone"}_0 39015 39016##### FilterGrade Cinematic 39017#@gui : Preset = choice{1,"All [Collage]","None", 39018#@gui : "Cine Basic","Cine Bright","Cine Cold","Cine Drama","Cine Teal Orange 1","Cine Teal Orange 2", 39019#@gui : "Cine Vibrant","Cine Warm"}_0 39020 39021##### InAvision 39022#@gui : Preset = choice{1,"All [Collage]","None", 39023#@gui : "7Drk21","BC Darkum","Brown Mobster","Cold Ice","Dark Man X","Film GB-19","Formula B","Gremerta", 39024#@gui : "Hitman","J. Wick 21","London Nights","Louetta","Nightlife","VFB 21","Vintage Mob"}_0 39025 39026##### J.T. Semple 39027#@gui : Preset = choice{1,"All [Collage]","None", 39028#@gui : "Bright Green","Crisp Romance","Crushin","Frosted Beach Picnic","Just Peachy","Late Afternoon Wanderlust", 39029#@gui : "Lush Green Summer","Magenta Coffee","Minimalist Caffeination","Mystic Purple Sunset","Nostalgia Honey", 39030#@gui : "Spring Morning","Toasted Garden","Winter Lighthouse"}_0 39031 39032##### Kyler Holland 39033#@gui : Preset = choice{1,"All [Collage]","None", 39034#@gui : "KH 1","KH 2","KH 3","KH 4","KH 5","KH 6","KH 7","KH 8","KH 9","KH 10"}_0 39035 39036##### Lutify.Me 39037#@gui : Preset = choice{1,"All [Collage]","None", 39038#@gui : "Hackmanite","Herderite","Heulandite","Hiddenite","Hilutite","Howlite","Hypersthene"}_0 39039 39040##### Michael Ezra 39041#@gui : Preset = choice{1,"All [Collage]","None", 39042#@gui : "Deep Skin Tones 2","Deep Skin Tones 3"}_0 39043 39044##### Moviz 39045#@gui : Preset = choice{1,"All [Collage]","None", 39046#@gui : "Moviz 1","Moviz 2","Moviz 3","Moviz 4","Moviz 5","Moviz 6","Moviz 7","Moviz 8","Moviz 9","Moviz 10", 39047#@gui : "Moviz 11","Moviz 12","Moviz 13","Moviz 14","Moviz 15","Moviz 16","Moviz 17","Moviz 18","Moviz 19","Moviz 20", 39048#@gui : "Moviz 21","Moviz 22","Moviz 23","Moviz 24","Moviz 25","Moviz 26","Moviz 27","Moviz 28","Moviz 29","Moviz 30", 39049#@gui : "Moviz 31","Moviz 32","Moviz 33","Moviz 34","Moviz 35","Moviz 36","Moviz 37","Moviz 38","Moviz 39","Moviz 40", 39050#@gui : "Moviz 41","Moviz 42","Moviz 43","Moviz 44","Moviz 45","Moviz 46","Moviz 47","Moviz 48"}_0 39051 39052##### Ohad Peretz 39053#@gui : Preset = choice{1,"All [Collage]","None", 39054#@gui : "Cold Simplicity 2","D and O 1","Retro Summer 3","Subtle Yellow","Teal Moonlight","True Colors 8", 39055#@gui : "Vintage Warmth 1"}_0 39056 39057#### Olivio Sarikas 39058#@gui : Preset = choice{1,"All [Collage]","None", 39059#@gui : "Analog Film 1","Atomic Pink","Beach Aqua Orange","Beach Faded Analog","BW but Yellow","City Dust", 39060#@gui : "Dark Orange Teal","Day to Night King's Blue","DuoTone Blue Red","Faded Pink-ish","Flat Blue Moon", 39061#@gui : "Honey Light","Infrared - Dust Pink","Neutral Pump","Shade King's Ink","Sunset Aqua Orange", 39062#@gui : "Sunset Intense Violet Blue","Sunset Violet Mood","Violet Taste"}_0 39063 39064##### ON1 Photography 39065#@gui : Preset = choice{1,"All [Collage]","None", 39066#@gui : "2-Strip Process","Aqua","Aqua and Orange Dark","Berlin Sky","Blues", 39067#@gui : "Black & White-1","Black & White-2","Black & White-3","Black & White-4","Black & White-5", 39068#@gui : "Black & White-6","Black & White-7","Black & White-8","Black & White-9","Black & White-10","Chrome 01", 39069#@gui : "Cinematic-1","Cinematic-2","Cinematic-3","Cinematic-4","Cinematic-5","Cinematic-6","Cinematic-7", 39070#@gui : "Cinematic-8","Cinematic-9","Cinematic-10","Classic Teal and Orange","Earth Tone Boost","Fade to Green", 39071#@gui : "Film Print 01","Film Print 02","French Comedy","Green Blues","Green Yellow","Landscape-1","Landscape-2", 39072#@gui : "Landscape-3","Landscape-4","Landscape-5","Landscape-6","Landscape-7","Landscape-8","Landscape-9", 39073#@gui : "Landscape-10","Lifestyle & Commercial-1","Lifestyle & Commercial-2","Lifestyle & Commercial-3", 39074#@gui : "Lifestyle & Commercial-4","Lifestyle & Commercial-5","Lifestyle & Commercial-6","Lifestyle & Commercial-7", 39075#@gui : "Lifestyle & Commercial-8","Lifestyle & Commercial-9","Lifestyle & Commercial-10","Moody-1","Moody-2", 39076#@gui : "Moody-3","Moody-4","Moody-5","Moody-6","Moody-7","Moody-8","Moody-9","Moody-10","Nature & Wildlife-1", 39077#@gui : "Nature & Wildlife-2","Nature & Wildlife-3","Nature & Wildlife-4","Nature & Wildlife-5","Nature & Wildlife-6", 39078#@gui : "Nature & Wildlife-7","Nature & Wildlife-8","Nature & Wildlife-9","Nature & Wildlife-10","Oranges","Portrait-1", 39079#@gui : "Portrait-2","Portrait-3","Portrait-4","Portrait-5","Portrait-6","Portrait-7","Portrait-8","Portrait-9", 39080#@gui : "Portrait10","Purple","Reds","Reds Oranges Yellows","Studio Skin Tone Shaper","Vintage Chrome"}_0 39081 39082##### Picture FX 39083#@gui : Preset = choice{1,"All [Collage]","None", 39084#@gui : "AnalogFX - Anno 1870 Color","AnalogFX - Old Style I","AnalogFX - Old Style II","AnalogFX - Old Style III", 39085#@gui : "AnalogFX - Sepia Color","AnalogFX - Soft Sepia I","AnalogFX - Soft Sepia II", 39086#@gui : "PictureFX - Faux Infrared B&W1","PictureFX - Faux Infrared Color P2","PictureFX - Faux Infrared Color P3", 39087#@gui : "PictureFX - Faux Infrared R0a","PictureFX - Faux Infrared R0b","PictureFX - Faux Infrared YP1", 39088#@gui : "GoldFX - Bright Spring Breeze","GoldFX - Bright Summer Heat","GoldFX - Hot Summer Heat", 39089#@gui : "GoldFX - Perfect Sunset 01min","GoldFX - Perfect Sunset 05min","GoldFX - Perfect Sunset 10min", 39090#@gui : "GoldFX - Spring Breeze","GoldFX - Summer Heat", 39091#@gui : "TechnicalFX - Backlight Filter","ZilverFX - B&W Solarization","ZilverFX - InfraRed", 39092#@gui : "ZilverFX - Vintage B&W"}_0 39093 39094##### Pixelmator 39095#@gui : Preset = choice{1,"All [Collage]","None", 39096#@gui : "Black & White 01","Black & White 02","Black & White 03","Black & White 04","Black & White 05",\ 39097# "Black & White 06", 39098#@gui : "Cinematic 01","Cinematic 02","Cinematic 03","Cinematic 04","Cinematic 05","Cinematic 06","Cinematic 07", 39099#@gui : "Classic Films 01","Classic Films 02","Classic Films 03","Classic Films 04","Classic Films 05", 39100#@gui : "Landscape 01","Landscape 02","Landscape 03","Landscape 04","Landscape 05", 39101#@gui : "Modern Films 01","Modern Films 02","Modern Films 03","Modern Films 04","Modern Films 05","Modern Films 06",\ 39102# "Modern Films 07", 39103#@gui : "Night 01","Night 02","Night 03","Night 04","Night 05", 39104#@gui : "Urban 01","Urban 02","Urban 03","Urban 04","Urban 05", 39105#@gui : "Vintage 01","Vintage 02","Vintage 03","Vintage 04","Vintage 05"}_0 39106 39107##### PIXLS.US 39108#@gui : Preset = choice{1,"All [Collage]","None", 39109#@gui : "Amstragram","Amstragram+","Autumn","Cinematic Lady Bird","Cinematic Mexico","Dark Blues in Sunlight", 39110#@gui : "Delicatessen","Expired 69","Faded Look","Faded Print","Hypressen","Magenta Yellow","Metropolis", 39111#@gui : "Modern Film","Newspaper","Night Spy","Progressen","Prussian Blue","Seventies Magazine","Street", 39112#@gui : "Sweet Bubblegum","Sweet Gelatto","Taiga","Tarraco","Unknown","Uzbek Bukhara","Uzbek Marriage", 39113#@gui : "Uzbek Samarcande","Velvetia","Warm Vintage","Whiter Whites"}_2 39114 39115##### Purple11 39116#@gui : Preset = choice{1,"All [Collage]","None", 39117#@gui : "Going for a Walk","Good Morning","Nah","Once Upon a Time","Passing By","Serenity", 39118#@gui : "Smooth Sailing","Undeniable","Undeniable 2","Urban Cowboy","We'll See","You Can Do It"}_0 39119 39120##### RocketStock 39121#@gui : Preset = choice{1,"All [Collage]","None", 39122#@gui : "Arabica 12","Ava 614","Azrael 93","Bourbon 64","Byers 11","Chemical 168","Clayton 33","Clouseau 54", 39123#@gui : "Cobi 3","Contrail 35","Cubicle 99","Django 25","Domingo 145","Faded 47","Folger 50","Fusion 88", 39124#@gui : "Hyla 68","Korben 214","Lenox 340","Lucky 64","McKinnon 75","Milo 5","Neon 770","Paladin 1875","Pasadena 21", 39125#@gui : "Pitaya 15","Reeve 38","Remy 24","Sprocket 231","Teigen 28","Trent 18","Tweed 71","Vireo 37","Zed 32", 39126#@gui : "Zeke 39"}_0 39127 39128##### Shamoon Abbasi 39129#@gui : Preset = choice{1,"All [Collage]","None", 39130#@gui : "City 7","Coffee 44","Date 39","Day for Night","Denoise Simple 40","Desert Gold 37","Directions 23", 39131#@gui : "Drop Green Tint 14","Elegance 38","Golden Night Softner 43","Golden Sony 37","Green 15","Happyness 133", 39132#@gui : "HLG 1","Industrial 33","Morning 6","Morroco 16","Night King 141","Rest 33","Shadow King 39","Spy 29", 39133#@gui : "Thriller 2","Turkiest 42","Vintage 163","Wooden Gold 20"}_0 39134 39135##### SmallHD Movie Look 39136#@gui : Preset = choice{1,"All [Collage]","None", 39137#@gui : "Apocalypse This Very Moment","B-Boyz 2","Bob Ford","Life Giving Tree","Moonrise","Saving Private Damon", 39138#@gui : "The Matrices"}_0 39139 39140##### Youssef Hossam 39141#@gui : Preset = choice{1,"All [Collage]","None", 39142#@gui : "Cinematic Forest","City","Darkness","Hallowen Dark","Sea"}_0 39143 39144##### Others 39145#@gui : Preset = choice{1,"All [Collage]","None", 39146#@gui : "60's","60's (faded)","60's (faded alt)","Alien green","Black & White","Bleach bypass","Blue mono", 39147#@gui : "Cinematic-01","Cinematic-02","Cinematic-03", 39148#@gui : "Color (rich)","Faded","Faded (alt)","Faded (analog)","Faded (extreme)","Faded (vivid)","Expired (fade)", 39149#@gui : "Expired (polaroid)","Extreme","Fade","Faux infrared","Golden","Golden (bright)","Golden (fade)", 39150#@gui : "Golden (mono)","Golden (vibrant)","Green mono","Hong Kong","Instant-C","K-Tone Vintage Kodachrome", 39151#@gui : "Light (blown)","Lomo","Mono tinted","Muted fade", 39152#@gui : "Mute shift","Natural (vivid)","Nostalgic","Orange tone","Pink fade","Purple","Retro","Rotate (muted)", 39153#@gui : "Rotate (vibrant)","Rotated","Rotated (crush)","Smooth crome-ish","Smooth fade","Soft fade","Solarize color", 39154#@gui : "Solarized color2","Summer","Summer (alt)","Sunny","Sunny (alt)","Sunny (warm)","Sunny (rich)","Super warm", 39155#@gui : "Super warm (rich)","Sutro FX","Vibrant","Vibrant (alien)","Vibrant (contrast)","Vibrant (crome-ish)", 39156#@gui : "Vintage","Vintage (alt)","Vintage (brighter)","Warm","Warm (highlight)","Warm (yellow)"}_0 39157 39158#@gui : Thumbnail Size = int(512,0,1024)_1 39159#@gui : sep = separator() 39160#@gui : Strength (%) = float(100,0,100) 39161#@gui : Brightness (%) = float(0,-100,100) 39162#@gui : Contrast (%) = float(0,-100,100) 39163#@gui : Gamma (%) = float(0,-100,100) 39164#@gui : Hue (%) = float(0,-100,100) 39165#@gui : Saturation (%) = float(0,-100,100) 39166#@gui : Normalize Colors = choice("None","Pre-Normalize","Post-Normalize","Both") 39167#@gui : sep = separator() 39168#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39169#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39170#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39171#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39172#@gui : sep = value(0)_2+ 39173#@gui : sep = separator() 39174#@gui : note = note("<b>Note:</b> The color LUTs proposed in this category comes from:\n") 39175 39176#@gui : sep = value(0)_0+ 39177#@gui : note = note{"<center><img src="data:image/png;base64,\ 39178# iVBORw0KGgoAAAANSUhEUgAAABoAAAAgCAMAAAA7dZg3AAADAFBMVEUAAAAGBgYwHyUFBAQMDAwuHSMQDg8+LTMICAg2JStDMTfmu5gKBgfs6evgs5Di\ 39179# popINz06KS/tzrnnuarUmGxSQEVHOTE4JyNHIxggEBMVCg4NBwj29fXmx8Pu0rzoyrPlyLHoxKzgtKTdr5/pvpzjuY7ep4ritIjbooXgpYTgtYPcn4PA\ 39180# lYPZnIHYmn7NkHS6iXS7gGevc1mOVUhVRUiWW0GHSjM4Jy0+LyscGB4TCQkoBwk2Cgju7e7z1NDuzcjnx8bqzMXn0b/lxbvotaPit5PlsZLYrYvnqouY\ 39181# jInmrYXjq3/cnH/NkH/iqHzTl3zfpHnanHneona+kXCignDGimvHhWvVi2Z+Z2bMkWW3el6ldl3RflzAgli4bFadXlRrXVNvVlOoak+vY09hU0tYRkuh\ 39182# W0NOPUNZSUB+Tz5URDp2RzVcQDVqPi5yOy5WNihHLyAdFxcrChNCGA4aCQphCAjw6unry9HyzMrrxL/wxbfuyrLIr6/iqqWspqXnvaTtwqDnt5/mtpjl\ 39183# r5jbqpbfrY/ftYvFm4e5mYWWf4HYoYDEi3uPg3nGm3jYjXTEkXHOi3GFdXDDjm/ThW+6e2+vfWzSlGnakWmzdWiZc2fOi2PGe2HCh1uoaVt2Y1iZa1fB\ 39184# dlZ4VFOIXlFbSlCUWEyHWEhmS0aST0WBRDmPSzhvQjJaPCl3QChmNii6EiiiFyY0ISGQEB+bCxswHBlcDxh3CRIgDBEzEQ7g3Nzc3Nzu4tbevcPw1L7S\ 39185# yL3TrqzUq5mamJnCp5XCp5TZpJDroonQlYXon4S+hoOJgYPqnX3clHzAlHqBdHbboHTBgnTYnXG+f3FxZm+6j216YGnLhWfUg2WlcmSzcGSWa2N3ZmPE\ 39186# iV3IeliJXFW2e1HKdFGmVVGSYEyGU0toTUugaEqsYUpwVEqhYEh5V0Z7U0bIYUOQYUN/KUNIPkKGTD9vQzyJQjppPDhWOTWZMC7AGC0qJyhfLyRdLyA/\ 39187# IBgKBxgwJhcvIRcsEhdFKRSCDRRICw5SCAxjV0wNAAADGElEQVQoz23NBUxbYRAH8O9JX1+FlrrhMIa7O8PGcN1wBgx3xtzdBXd3GQ5zd3d3d3d/Lcmy\ 39188# LLvkkrv/L5cD9nIJqbF8MguGYZIgORkmwZbkjZ5TklpWgmlrvvJjrWC+FQmGE9YkUGGYRTYza0yaMgnMSxVZ8QdYG80oMCzg95JIMIVFpVLlCfKMPV4j\ 39189# gGFLEkyEFBJJamQyVd7ME2yx35FqRaFQWNKdSiZbUiyJQT6JNwnIKRy6/jL9TUtN8Iq9e1YYm9Q21NdPvsLj8SYDua1HJq7za7iopqKswlZ119TW2jd3\ 39190# 55yV5xoJGjfxyQVmxC62Enscez5jkdtCzkxFJ6dtepeB/azImwFaZ1W2KykvXLreJDxoCcdZcfp0R06B9CpybFCQipIqw+NYxO1m8zg/jouiotPcOiDn\ 39191# rH1Qe+1aZSVVLcMDh8+UW8SFaKrrFdemGIE5b33Ga2hoqLKV3Zeu8lle1J6oubg4SyjM0wPPvt3Zr0Fzmz97Ns1jlWFoUVzoIjXT7C+f7PSAnWhA352h\ 39192# 47ZgAc1D08/QUH/xLE5zRuf3vAIwbJPtPWECgzZmLJOppau7xMVxhpppZkZ38HIgpqcH+MtoPJPpfdTVwcFR3byrK2XzNCBBOku4XsukpO29odDV2WGm\ 39193# +kMLi2AFBYAiwmsV/jq0MTq+3POF61xdZqipJ7a/uLubIMg2MbLUl7FM5wQ3QFfXIISpv9rcIoslP4+gqd3RpYFeXr5cAwMDfZ+Tp8ti0l7nWL9/DlCc\ 39194# PtIWdSrQPzAsJHTDeqOy6hjTjF4Ms7YGGHGWZ14Rxi2JqqqLvx9/KcY0LTsHQzFMSnRb4b0bYVejqioro2+1ZnZ8HBajECQGOIqi4qnCpybG4eHR8a2v\ 39195# 2jI/iDAUgXARQHAcsxHTR9IiVhsZmzR1ZAls6CiOQLk9ACAQKpFAuERQbmRc3ZSSboNDOA5Bg+8AABAKAQhCEIz34NHj5BxIVrl9mwgiYqKBtFAMQmRC\ 39196# /9UvJYAgyKjIFpnYDfX3/In+NsQ2/0ff4L8w+sAufyhX9F+S/My3/Wz9Gwm+5rUIT8ACAAAAAElFTkSuQmCC"/> \ 39197# <a href="https://www.abigailgonzalez.com/">Abigail Gonzalez - FreshLUTs</a></center>"} 39198 39199#@gui : sep = value(0)_0+ 39200#@gui : note = note{"<center><img src="data:image/png;base64,\ 39201# iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEXU1NTV0cfT0MXNyb6fmo7V0cvX08i2trza1tDX083UzsHQx7YSDxHW1NTb19PM\ 39202# ysjKxb68uKqdnJ1MRUjO0dnKzdna2NfBws3BwcnTz8fOycHIwLXEu6+hn6BkWVdBPD8uKCvU1+DX1NHT0dHIydDZ1c3PzMu9vsm9vcPQzcLJxsK1tcG4\ 39203# uMDTzL3Iw73OyLvLw7nNwK+sqau+tqmZl595dntoZWZsWlpVUVNVTUxIQ0M6NDclJCchICQgHh8dHB4FBAXW2+TRz8/Y1MnKyMXNxr3JwrjOxbe2tLOs\ 39204# rLLIwKyjpKzFuqq7tai5s6SNi4+emI2clIiLgH1zcHt8dHJxbXJ4Yl1ZS0hQR0gtIiUYFxoNCwzh4+bQzs24ucXV0MTRzMSws8TIwrrTyrmurrjMxLXF\ 39205# vrSxsLTLw7KoqbKlpKien6jHvKePjpmZmJaWkpCIhYySjYuOiIaZjYWIgYOCfHungHiTfXB3cXB2aGKDa1xnUlFUREh3T0MzLzM5LzA6JigoHR8ZFRfP\ 39206# 0t3f3dvCx9jT0tbEx9TT09G7vs/Fxs24vM2jqsbKxru7ubaxra60r6eop6ehoKa5qZqVk5qblZWlmpPGto6dloqjlIaAf4OcgHqWe3mBd3h3bWuMcmqD\ 39207# cGZqYWBaV1uDYVN4X1NfTk5tVUo6OT5ZQD1MPDpANDNILCvm6u3i5urR1N3W1tbKzNPU0M6wts7LyMvDwcPSy7+xsru+urWqqK/AtqyamqzOrqq8rqm7\ 39208# pqjayafDvKW3rqG7vJ+zqp+upp/Ir5ivpJetoZewlZSJipSymI24kYuvi4iTin6RhXqvg3iScnFtaG+YfG5hYWqXcWRuZWR9ZmGMb2BhXFuKYFlzXVho\ 39209# W1RaVVJhTEJOQ0JIPj9nQz3s7+7Dy925wdq+x9nBvb24srbYyq63s66rq63Qv6i9qKTZxqKqn6LFup3Lu5esr5aej5bjx4yDgoyqnoeig4a7qYCfjoCb\ 39210# i3qkiHh5amagcWN/XmNKS1mEXExqRkNuRDpq42GmAAAD9klEQVQ4y0XRZVRTYRzH8YfpHBtzzAUbsQIcsEA21w0ijXSjlHR3p510d5fd3d3d3d3ddxw9\ 39211# ft/+Pud/zz0PSElJwaWeOJGZ6eXV5Ok5/n+enp5NXl5ewMnJafm+g/v37dkzw93dfdLfpkK5u8+AAhtYLPutU7eaxBg7LFs27l9ToBwdo6Pj4oC9vr69\ 39212# iYmxzfRxVlYwWEy6b0aVoY4ODAZDobjcKD09wGIy9bW7kRVMB87Ku3xdcj0dOWGCDoTCUFwI2M+cyYpxgHZDOBJJ6aBKZTKp9WTktGmQCUONAbtI6IB2\ 39213# 1zWtz/wqkcnwj3V1J0+eBp0Jm6IH9O3sIh1sjLQ7Zm3l9mOdVwvxVZh/AmUFAbNIh+nhcKQpxsB0/fZjp84XyBowkNAC6DNA38zMOtIoHA7tc9fuPHw8\ 39214# 51LBtR2Y8Og4Fxc3N7cpcAgstF5mZGhqYDA31G5nW2th4dWL4RiHR7sO8FxckkyQWoDFjoH5hIeHPxz3P93lv1nX5vnbp4de73WBABNoAdxg/nqSBb/9\ 39215# 4umiInE/hb85apfe+727eW5wMBMALJYZSjAnW8ya7SH+XiSn+XngKpebJO1O4r2CgNlEgGWFhhJJi8nkWQJqEQ3vc0ZIiXV64hQdx0uaqgPAxInWTMZK\ 39216# 4mJzS/NZbB+xWPguTeCMQCQkxBgbG48zHANzCSuJa9ZYkjikbf5ZyYIt0D47gWINC4PeTAuwd+bYziOYW3LI5hHJiRwEYgsC4VpNWY6CggFIrF4xhzhv\ 39217# 1WIOmWy5yZVjsYDEdmW78nHVXC5340YIrF7BWDBvCXRhQ32qd3osAvqbxNnOfBxfz9HR0QaA+bYM0oJFi+YQLCy98096p1NiN8UnxnNicdW1tZ+aDwFg\ 39218# e/d+xKIlEbYEEqIjv6E+D+fs7Jp2hF2Do3xuPlhQAJg72OuWLl1HtCVa1Hg/qEwVCeLjhXSVpKYOFxXFG+gDz3Jaty29t4TBILJ9qb77M0QeAgFNHRxc\ 39219# l5z6srGxbwAcPdv2JuJICmMVOZsaIM/PvixMSxsMRquTPYS1Hxu/nAWtnW0vqlr4CXmBtJISekC3RCQS9SiUNJ8WYW7u0QM80OmdleEbKJUGyvuHRuSB\ 39220# eLG/f++AQlE6iu++MZTb2wHEed1U/K1bN/tzTn37WUyT3i4u/j2sVKvKy+hB5ddunAGBFy5QAwKaL13JOX+l+HZQRdnoaBm9RKGoGBkevtmVKwM+Pnh8\ 39221# aUB+V2lhX++voSANGh2iQSuVwWjqycymBj8V+JHooZS2l44Eo4PKystDNJqQkBB0j192VkZWtm+7Ag0GW+okSppcTqfTg1TqCnSFWqVSlwxKzp3z8xP1\ 39222# aDR/AFuiV5UIiV63AAAAAElFTkSuQmCC"/> \ 39223# <a href="https://freshluts.com/users/1">Alex Jordan - FreshLUTs</a></center>"} 39224 39225#@gui : sep = value(0)_0+ 39226#@gui : note = note{"<center><a href="https://freshluts.com/users/10185">Berat - FreshLUTs</a></center>"} 39227 39228#@gui : sep = value(0)_0+ 39229#@gui : note = note{"<center><a href="http://fixthephoto.com/free-cinematic-luts">Free Cinematic LUTs</a></center>"} 39230 39231#@gui : sep = value(0)_0+ 39232#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAAAgCAMAAACfHyDkAAAC9FBMVEUUI\ 39233# TIXITMfITUcITQfIzYhITYZIDNBMHbKPi/HKE3HLkPGKn9BL3PIMj/JODXJOjLHJ1TKRC3HJXxrOIfIJnZFLm/HKFzHK0fKPDDHJ23HJ2XINDzJNTnKQ\ 39234# S7FLoJpPXYmJUgiJEEeIjrJNzcrJDTKSS7KQy1xOot1QIdiNIRWMH1KMHlFL3UuJlAmIjbNXTWKR5GFRpB8QY52PYtmNYbFMoRdMoHHJ357QHpPL3pdO\ 39235# HZQMHUpJ08cIz7MXDzNYTdKJjbKQC7ENYbHLYBfNH1TMHpaNHlVNHZKMHJGLnJCLGrHKGrHKGHFT1YrIju+NzfNVDXKRDUzKTVaLDLLTDCRSZKBRJCCR\ 39236# InGVYZuPYR+QYJyP37IJXrIJ3NQMnE8LW2FR2nIT2bHKklCI0MqJkHOWDfIO4FnOYBYMH9qPHyXSXpjOnnBJ3Z2QXJbM3FML2WUTGMzKl7BKFktKlg0K\ 39237# Fg2KFJkJVJALU/KSU68KE7IM0szKkouJUeLJUXIQELMUDsZIzmuVDifUDiXLzh+QzeNSTZLMTaZSZJ8Q4vJToe+NIbKSIOyMX7BKX2kTHqsLnrLSXdvP\ 39238# nZUM3BvNm9gOGyNSWtWNGtLLWuFMGc4LGeUK2evKWdyNWS7UGBXM2A/Kl/JPV5IMVt3JFmqVVSjMUy9WEbLVkO3LkJsJEE1JEDJPz08Ijk1IzZjOTU+L\ 39239# TWGMTPMUTLJQDB/NjCgOS+/QC6kSI+HRYqZR4e4QIe1UoasT4G8MYB1PHqGOnfFUnWSOnWaMHTILnDJO2/KRm22KWynS2qlLWqeS2hnMmfIL2ClJ16EM\ 39240# VlOL1m4VlO3LFKvJlLJQE2zWExfN0vMVUq/LUZ6JkTEXUDLST2uND2VTjnDXji4VzhvQDZaNzVpODS1QC6sPYefP4KfP4FzNni2Jne6UnOkR3GqNHBqM\ 39241# XCuT2WIJGBlKlyxUlmMQFjHK1aIJVWdS1StTU+RM05VJE5zP0WCJEJYI0BTIzzFWTSmNzHHTC7FQC5jTTRlAAAEvUlEQVQ4y6XTdVRTcRTAcd7e3htjU\ 39242# 8E5kBkLN2ADBgiyMWCEdJdSSiMCEkqISimK3d1SAlIidnd3d3d3/uP9bXAQD/qHfv/hnnv4vPvgbBqUzqN2EtGh/5A4jncCCaEwKKjx1s2JN4PUyu/8t\ 39243# WsNQSpS+3HCpFIpSKiDCWosvXV74qQJ4687ODiYmY1vRHD0inMwTwInPRlz2czsa8MvkqAGlTYgceMGGLPEgPUhISEi0ffbCMoXOqwXie4AXCWvMBOJR\ 39244# BtAoqSlEyeMVyqViYmJASBEOn36GBgY6KjaQFBHb5ZXBahG6YLQGGWIjs7GYLXkn69SFhVdCQwMbG7uqYlycuoDIb8xmDouIiJTKYLRkTi5ObIiUcfAo\ 39245# EVIaJAkbur1du26fv26orqhekKaKPAtwoTI0LRzAU5OzU3C0aERMZdDnJx+BFMoIE3Z7HeFvaDevXv3gwcg73/Vv5UHU1dZRGYqAzU17zj6RYbOrQiAZ\ 39246# YsQSYGXJ/tVoVYXFPDqyvcnVsx/+mBPoOr6N+E4IyNuVRGMTUSZRWTMWtj7w0mQdibGnosq9bRUnWAyaTQTYxvr/lsK0Xn/YGLRlORM+GO6+tcnwDNOF\ 39247# cG2RKiWTGMbj6On4/Sgi0fVUsIa/KwQvX0JnAxPO3UF5iYiY0pyzIV1MDpS2qSra9SKMXQ6PS6ucrWpHY+/WmyY4tsF8nfE041SMy/AeLUuPzmc+zIPx\ 39248# hIKDmmQfJDDXaOWjNKmQ5+kJPzPxJaH8rSgEjzfMGmu71kYL1EyLFMX+o7V0qp2xNUSH2lsM9zaPX2ZrjY0pgYncS9xhO/YOHh5R8G8cMWRvLF6etX1C\ 39249# awk7so82BZIWyUpiAYpdks/7OOjq6s76jPOk1gd8qVDBdIcVmrayrMw1lAyWAo4SaePgZOtkuR5SqzFVm7zl3M4Pj4+Z+KXSnbGrkH3v1DmJSmOxL7W1\ 39250# j5Tn+/iwl2JtgVEq8Qgno21mMVym39Q39vbm3M83eVx7DE4X4DnWLmlxa6BF6khFlspUtD2dB3eJlHZErGVIUuxa8TQofr6+k9m7T7A4XBG1QlsXdxnH\ 39251# fDmcI778cRu3Ef74aUuEaQ6tRSstrZiGYan7hnRAxo6Z84+fX3vN5QcF3f57v0w5uKLrd1T0HZ5PNkmIUQXg7Q04u7tjhoyBPzBeL6tq2L7dHjScsJUY\ 39252# ssNGwZjOd4u1ZTvBrK/0dzZMplMrZ9TsofbysMGdh8yIlfgJYlKmcqA0Y/sKKF8F5CDp8hnMFTJHvrZ29q6b5vOkMmW+cHJnWHDGLKZ5STWllqiclggL\ 39253# UJ37RgIMRjlWLarhxx+nTHzA+lpEzVrKiwP12KdSCzDEKS5+f0BfaHZtXy2R9T26TAuo5raeCjChvXtOzOX7FQKFln2tzAfNHmr84ABO3LhQ8metw3GG\ 39254# fH2Xh5s7lQY9xJYJxLiJyE5aNNWZ+clhL2JJ9sjYprzjBdUUxM22/3etGmz47GOsr2E8MHmcHTT3SVUjZEmbPRVZWdjxUxPJg1GLx72R4mNS0avu2UVV\ 39255# cM+mkmDou0wDR5NNS7lY3+UkKBswYKyBNgWL6XRmNEj7WHHZ6LRrhj7q2zPPivLDhyKl5XFK4afv8l/7iccu3t+6IPmuwAAAABJRU5ErkJggg=="/>&n\ 39256# bsp; <a href="https://911templates.com/30travel_presets">30 Cinematic Travel Color</a></center>"} 39257 39258#@gui : sep = value(0)_0+ 39259#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAgCAMAAABAUVr7AAAC91BMVEUh\ 39260# ISH9DA39+QAhJCkpKSElJSElJDMxMCJFQCE4NyEIXKcmPyIqNSH80gUTJrp8HLEmJ04fOEgzJ0EiLDUhMi8hIib8ahT1phACygX5xwQFsdYbJKUjLj8gN\ 39261# TlfIiw2KyJfWB5oWx38gBhCSdiIG7tyGqsUH6TzEJnsEY49J00dRUr8Nzr31DA+JTAu5i8hKC78xyEzRh/3tBj3rBcArwYFvwRr0gEq1vEBgtEBo8wDcL\ 39262# 4TJKxsGqPnEoPlGn/kE3cZVF9HK0ovJjYsLS4xIitTJicqIiYhSiL5mCE+PiFgOSFIRSBWUB/6vB78jBuEcBkHtQj5ywOT3gAAxOAAu9sueMsCZ7UUIbA\ 39263# EU50yN5cdO1dWJUFKJTexKS4nMCr68icvKiNBLSJIMSEiWSBRSSBgSx/76R1lZRyUjhf8dBZg0wj37QMBuAKk4gF81wEBqcyLPskCecj4Q6buOZnWO5Ic\ 39264# SXghJXOdJmhoKVptIUgbVz5SJT79jTd59C1HJSv9/Cjg2ya9aSZTMyK/uCEffyAfah5PWh6UGx40Uh00YhuDfRl0dRj6Uhf83QZazgTt9QGD2wAAzOadS\ 39265# OKURNcCrdABw80ksMYtbbgTVLZVHa0bmKtwH6u0FqkLv6CkFpVnM5QZWZPPEocdK4YtNIMacYFjH3BPJ2ruLmkcNWFEJF01JVdTKlUfL1RaJ00HpkH1DT\ 39266# 47JzzyijrlfjUfPzL16S7gzSv8fivetijNpSRz7COARSKBJCKXeSGgKCGskyBFkiD3CyBtOB8+VB39+RfU0RbGwxZMbBYMkxFxjQz82gjx1Af43gRGyQE\ 39267# sseIXvN1dStM3aNCGNMYCkMQkbr4DhrhwHrh+PLfBPrNQKbAApq85IK4mZ6MJkp0OaYXxEHgpxHITZmoBtmgZTmD0TzyeFzQ62y1p3Cpm1ypixidXuiXS\ 39268# 4yObYSOSUCLLhx5LVx6R7B37nhx9XxyNWBs+dhpA0RlYfRn8MxEUnw3l8gaOywaizgW15gMlxgLHnPo6AAAA/XRSTlP9/f39/f39/f39/f39/f39/f39/\ 39269# f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f\ 39270# 39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3\ 39271# 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39wCUWrAAAA0ZJREFUOMt103k803Ecx/GFbLNpmTW1\ 39272# piHLJmoSMxlmreauoQO5ReQoldwlUpR03/fpzH3kKDfRfd/3fd/nH31+3x8P80evv5+P9+f72EHoa+i0aVNNU1NlYyCZLCiQE6A2lKAUCAC+Pj71WfOgx\ 39273# vpmp/QgTsAgg0BC/JLj41FPyleeckoP5MCQkkhKiI9bHHd8CGpddXIZoKABM2JqadLyJYvjbO3szuCEyaxOLn+LmT6hTpeAACAWn0SEuYDJZCaXvQklEd\ 39274# Vw4cA/FnvD1s5WLOYh8t3AYAEguUlDqCMRO6XqQM+/vnn3Plsxj8e7j+64uQEy0DGpcg8hq6Ez/P2baDbcfTyekZER9hgDORg3cx0dk1p9Z5hRVacf23z\ 39275# Jhsul7QFx8GlWVuNKuVz+0XWSuc4kkwYXshrcgZHdNlwazXDPwfgE+HCdmj+/Mxe4umIzNfokIkGdXhAbi4Qh7ejy4iRfmSw99FOtQIDPwGsI6sOXXbi5\ 39276# kwvC8GhhYbGPb2pgICnUvQYnlU0ujkAOjx09bvTtndds8vkSicTUlMMhh+g3CQSjIP9VeiQgc4FMmT1s2KECPl9S6iANCCCS9LK7uzU1Z46aX6WvTJYNp\ 39277# 9PpDlKplEh21nM/ux6RFYNJEZutrS3186M6uvyHHDqhxdbVZvhRYSQsvAcnbYgcxsgOayvrpd5augwgZu/DctpVIiN7NGfiz2WfuLhDY5b1IiurA4+NgV\ 39278# AoZqtzwiNVsCL9w/XIBFV20XYvDdzcszeuANHS0dWmgmqtzA4Boq211EtjDmZYHncfJgYHr+3o+v1nAyJp7WHORILqRLb39itzwIg8Nm7cWtLZ+eNXVJQ\ 39279# iCjOt/uHY1ziif+ayp6eHx9aRUF6UQpGnAJO2Kgz7MaCZA14aV7ewWJ6eezHSq8iLtrSM/pm2IgcbgWDG+845ligG0CML6G80iNzcD6+zV+M/THTKfpvw\ 39280# vEgUE1OyEJphaRmRG5Hy/BuI/r/ARF1j+11CIUt0azKqNyKiLuXllxYzKhLoFGaObBMK91rMgCy+1qW8OL12DYUKV5SMFqBdDyagnr0CABMDAn8PoMTEz\ 39281# MyMjIzM4OA1ZpTBAh9iMBgVlOlYFApVCfwDpbUmiFdSYzcAAAAASUVORK5CYII="/> <a href="https://rawpedia.rawtherapee.c\ 39282# om/Film_Simulation">RawTherapee Film Simulation</a></center>"} 39283 39284#@gui : sep = value(0)_0+ 39285#@gui : note = note{"<center><img src="data:image/png;base64,\ 39286# iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAC91BMVEX+/v78/f4nKTn+/f4nKzspLTxJQkQlJzh3odlzndQyM0EsLzwlKDUlJzD6/f6X\ 39287# xvmUwfWItuuFsuh9p907OkExMjw2MzUrKS/v/f6PvPGMue6CreNuls5wXVpaT01SR0c1N0Y5OD0mKDcoKzUiJDX2/f2cwfWXu++KfXOHdW+UdWiDcWeQ\ 39288# cWSEa2JxZmF9ZlxpXVhtWVRUUVJGS1A9PkdDP0BAPEA/OjwrLTsmKTosLjgiJS/R9v3B6P2byv2lyPv6+/pvmtBskstNVGRnX116ZFx1X1hGSFdaVFFh\ 39289# U1BOR0xBR0xeTkovMEBFPDw+OTkxLzcpKzen1v6j0v6gzv6ozP6t0f2fy/3I7fvr7O2Ltet/q+J9p996o91rkcZpjcVlisJfhbxhdY5oeo2ejYBbX29o\ 39290# bW57YVlfXFdlWlR3XFNlU0xoUEtLTkotL0hTRkQ2NUIsM0ErLkFFRj8vLjO23f6s2v6x1f7c/f3h/P274P2w3/yQtuyEr+VwmtJwj7uJna1ogaWYnZtr\ 39291# gJt1hYthboN5gYBvdn2WhntaZXpda3lsd3NPXG12bGl7b2aKb2R9bGN5ZmOAaF9NUVpgV1dPV1ZUWVJTTkxXSklbSkZNRkQ1NTs7NTY0MDEoKzG32v7X\ 39292# +/2exficw/iUu/D28+7Y3N/t5NyNstrH1dh0n9fZ19XEzM7u28FiisFbgbhZfLSzrKSlpqDLtpi9qJW4oY2Ulo17hYhbbIaki39jaHlMXXeulHVDVmxP\ 39293# XGluZmRrYl87SV9YYF5bX1tiXlVnVU8tNkpGR0dFQUY1O0FZRz83OzhEOTfo/P7n/P3l/P3o/fzy+fr8+vKo0/Hx8e+cwezc5+ql0er17t2gx9210Nyc\ 39294# udyyzNPT0dKbtc56oM6Kq83z6MyEocqDpMOGnr3izryhrq7Vx62eoKuCj5x5hpvGsZpWdJqil5KomYazloKOeXKPhHGMc2tWWmsqV2qffWZxbWZdZmGE\ 39295# Z2A2QlpUXVmBaViAZlMyOlJoAiFnAAADzElEQVQ4yy2TZViaURTHL/i+sIG4OYkVIKAbDOkWN91AWsBtujZm94x1d9jdrru7u7u7u7vjw+6L/j/c++H3\ 39296# O/ec5zzPBRs3boiPi4vp171v+3YjhvtNnT596uShQydNWtrTk0lgQ3x8XGxM9yntV4/w83t7KJemNJt3Pu7Yo0ePxUvgsRTEr4+L7Qd5uxHDYn55e3vz\ 39297# 3I3Uk4aZ10JDo0JDBy1eAtbHxni437AHx/V6PYVB5ygJisqkO9Fjo6OjokJBLNZ9NeST91D0FArD7co/kaWQW15NGL1w4djoKNA2XbdO3XIplJaCZheb\ 39298# xaqVp1btGNy794TRo8cCyLHyTr5TeXpKAd3FljLFTOZBY/HzkBDMARjv1snXt+tIHoVRcKbByjSVlwmFQv6azuMXQQV4+NCuXbsYWuCAOcdM4RVCwad5\ 39299# iR9WhAV2HhcyGLQbjvEuHVfWn2U0c+RMcblIwE/c+mLdMhzO5+K4EAC5L+QdnmaeduXX19XKjWX8XVufXcZ5AeADuwCsP+QdkjKtBGm4Kc0iFfN3bbmJ\ 39300# AzC4wPPjQCvvs9ImY9WlSCRHU48eFMx78ygMM7zgEwCOB/nAh8aMBodEJLSkphlL+O+3rFvWKlwAEEM+4L6RoGJJSoMq0lIPFAvmJW7bdBUTAs8BWD5o\ 39301# 4ID+08Q2p0MS1KvX5zJxyUf+9hmbw+AMuMDOwIPHXJkrPqlmhUOhl0giKhVsnzEE1yYMgnjijfnFUpWmDgpBonKmNVxwD+PQ8AkEEE+8VUSqkqmobGZF\ 39302# qcnCYrOk7+AWsMBdgSfTdx46TiZT0wicBllKSobVwbZUrWnlwAve/7LRSC6PnCtnczSyn+np6cdkKcIVONihLdnZeWStFv26T6Th2GSm9Myc+sRNa1dd\ 39303# D/MoXjiQl52HomRtrrLWSWtUEwiEnMxtcwrnTFvlWSVYDlAUjSCTecGjqBp6k4vDURP+7k0+kjztro8XDO4lIOpQMh7VQoPmzFGpCBpC0N4f1b9n3b4U\ 39304# NmTI8rW7ARFBETyKx0fSSG4H25HhzPhWcthePWvujrkLEmbO3A3weAQPg2hH0YKDqeo/p63S6sN2e2FhQsKC2SNHzgZ4LjR0eIQ0KpgX6VZqmlroarld\ 39305# qagxmxULEqBA5OoQBNGS/EnwW0WSaU59AZ126kR+lmJ/TY1h33wQoCPqiBH+/v4kLhS8kbMMKuOU/fuZLMX8I/lmwx4QEEAkQoEEBYTLRfD0ZhW1slFN\ 39306# z1Imb042fCnChABiXgTJPyKAFozoUHcTg5pkq7QdmPN6RtL+WUX/AdPoMUu7nvi/AAAAAElFTkSuQmCC"/> \ 39307# <a href="https://www.facebook.com/eric.ellerbrockom">Eric Ellerbrock - FreshLUTs</a></center>"} 39308 39309#@gui : sep = value(0)_0+ 39310#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJsAAAAgCAMAA\ 39311# AAysvoIAAAAz1BMVEUAAAD///9AQEDQ0NCFhYU+Pj4EBAT+/v6ioqLk5OTi4uL29vYKCgrr6+t7e3v7+/sGBgYnJye8vLxcXFxVVVVra2v09PQ1NTXu7u\ 39312# 6srKyoqKghISHLy8u2traysrKdnZ1zc3Pd3d0cHBz4+PhgYGBFRUUrKyu/v7+YmJiIiIiBgYEVFRURERHx8fHp6emOjo5nZ2czMzMvLy/19fXGxsagoKC\ 39313# UlJR4eHhSUlLV1dWEhIRKSko5OTnm5ubY2NjOzs5qampNTU3BwcFtbW0lJSWTtii3AAADCklEQVRYw+2XaXPaMBCG9w2OxWHikDRgwBAIR7hvCFfu/v/f\ 39314# 1NUiDKFM6TD5QDs8H+JIWsnP7GoHIJwuZ7fj3QoXp0fBuF3S6XF5dju7HcG3uP0IrZkQhUL+NVEuFHog5ioU8EF0EwyqOkR4nAxoRbWRf/XTbw5pTNxNP\ 39315# UsrKjxK0wqzc1x2gqUV4d/c7rAmR6QQ4x1RIEHMBAEeUSQYLHWIIfZGTCtTgtD5QUwQ2X4nIcf/u30SYFDxguQmCPb3uRXDQmHX7ZYnR8AzP2rilg4LWQ\ 39316# nJh8OZIstxFh/4qYq5XBwoleX1boZXnwGvRUxCzMekMYt5Pk6NV27RsNDY53ZPhh038QNuiBG3BzLoEF0v5xWwiD44YVM97Lqhhbw+ds2PJkf1iOkC6ST\ 39317# aLeOW1Iv2VQmqLG55MnyrG9WBDC0USqZgKaKNG2XEnOw4StU8UNi4yV6F4kG31yvh4qBbV+KergM32wfqVNOCARs3x+StDIxoAbx8dWtx4rLa7eVKeP9D\ 39318# L3QPuRmGTQnJ1Gr3MwV3QI/Ana5cWlhdqXteLQJtjiUfKOv9qrLtJjMX2s2wt09jcWF+0M2TuKi4GZKfpN10t84gbPepp2/h0oXHNnMg/9XNg1pqt1Jcm\ 39319# OxzC9sCHXSrmkAJKc48wNeBpqbh0ch3jZt6mbXZRS7omI9IpVK3CsPstlvfhWppt5wtfGMvJOjSRTKrz1NwK6S5bhs3PoZdoi3drW0E1LfcbE734zF9Or\ 39320# A1u26J7bxlJSOPph+H9YTjDCaciqAXblZX6AkbOra4tWzbqfi8KUVH5K0T0Qx23HhW01+7NTtQPZ2uvAJcz9N/64FbdQh3QVTkF6Q0lSRwKwV/jkR0bKx\ 39321# M4haLCLm/czOkdtwMy7UbfSp4Uuhe0QXj+hUK3KgLRJ13BfcnCWlgFDSKiuWqhz6z+pY1DdzmVkNXwTI0iaqWVSZBZgW2KViWYyYrJPR7jUY5QYIlx5A9\ 39322# t6zU1LIKtGLA8w5ZQmFqLm8iOLb3T31HOjHObv+v2yn/dj5Vzm7H8Qt/zkuzg1TiwQAAAABJRU5ErkJggg=="/> <a href="https://f\ 39323# iltergrade.com/free-cinematic-luts-video-editing/">FilterGrade Free Cinematic LUTs Pack</a></center>"} 39324 39325#@gui : sep = value(0)_0+ 39326#@gui : note = note{"<center><img src="data:image/png;base64,\ 39327# iVBORw0KGgoAAAANSUhEUgAAACIAAAApCAIAAADf4mxWAAAKkklEQVRYhV1XTYxdR1b+zqmq+959P91td7fdjp3EsZOZJNaAEjEjmAi2CCFAGjQLZsVi\ 39328# diPEAokFYsNqtiCEGFhPpAFpAEUIxI8gIghBEqE4E0JiO7GdxG33z3vd/d677/5U1flYvG6PmaPSlUqnqr7zW/cruXh+jSQhpIiICmOM6nqwTGQAqmoZ\ 39329# oiRJEwpWQmYBeDYxCqAGKEBmwAAAutJ7MSTLFBicJTiaiApSNjrniWRmFIAEBGJnO01ESAIQkVOdnc3FAQLAzEQEgDeB88HMet6VI2dSqLHtFlE0G0GC\ 39330# TpSnZlMhICmiK3tXp5y6JCLQMwsAQIiV2huZjJLsucvbX3vlyxvPvlyqvvPOWzd/9MnJrA7e5aQZ5igAZOUWV7YqQNIewzgRAwU/Bn4smkGngaRaWh/o\ 39331# 9vZ2v6eSUuGVzEwGmMA9uUdEACVPvyRBPqHCWWJAAcUopk4ASaIUp73B0Lte7JqubYXmnRM4YSZJMSJzVScigJ2N0zwLAZiQjzEAiJzCqxDCRGEoB2ub\ 39332# F4eD9a5uLJqqmpkZnNPH2YYYxER/fJaIKOQM+9QPgcHI09pEBhWidIHJMS6HozVfhNQem2TAU+h9Z3DeOhV5HJOcsxr11FYznFaz8HTQnJytV4KkCiAE\ 39333# SfFhMBg5J03T5JxVIVBAieycO2uPswpWWU1NTn2i4GwYlCRXASOphBcz5xyZvSsG4/NJbFkvVF3wCgDiBBRR587idgYGqqpmJlGQRiPIU7zHFQEQEBG/\ 39334# QgPgQlGO1xcns6ZpiqLo91eNqaKSDHYa9Cd8AgAEURgBoRBnGcog1JkaqSBJ6mq9iPhQDIbnEOt62Ybgt86vJcIEOWcz2BNCgCuwbKvIqMA77TlXhlAE\ 39335# 3/M+eA3qgrrgvXfOq6qqA6DBF/1h7qqmSf1B2e+NLUMKJMtBC4o4QgmqOOcIWKIKDAYhIA50KipUwKAEM5lXuQU8xRmFFFXvQ1kvj9smPvXsJbFeSkYx\ 39336# gVKMJCAkxUAlAYWtGkNFvKBQUcFKQwglGySZJRCi3gwilixDJBT9ZTWLZufPbxxPmpSSGbzvp5RWoQdgZkwEoISHd6IK9FQLFUcIIeLESWeg2spbFXgn\ 39337# KRtgor4sZLactYxy8cL2wwe3Vb1naDWH4MycqQR1UUh0AwhQWO6cFN5b4VhCvXphciKWQ0/YJBqdeN9Y9CbiCBFCnNAmR7u9EltbG/PZTFUz1dq4rBdG\ 39338# Z5oVaAmV0FlUQc+HHpLz6Pl1r64Y2rpfK3WwkKqqsplBXRW7wqtPmYUKmZ0LTHW1aPuDwXh8rlrUIYiBX3v1xa+/+qU0ui6aNFbLRbVc5Gpx3DWT9mh6\ 39339# 0rmQm3UUIetgbbh1eaev5f7ew8n+0d7kcFZXA6+VZW+r+xw5hF5THU+my9HautMiNtkHzTk+f3XzV3/5Z6/+zG90kTTnNGWaifm4m/Zu3b93a/LFybIj\ 39340# jGuDzfXLLxVr5+689+6bf/XG8bH2QxG7xtG8emdMJIog86ODRTV78YWnhblqaqW1WdB13vUXi4g0hxslOLMmSZFwqXfh0uWNy888+8X0we5sEU2KcqM3\ 39341# 3Dp346uvHtz68PbdT51zJFW8V6GZgBIkV7Np23U7l7abpk6pA1TMeiFsX77uR6Ucvt1V2a+/EEZb4gqhNS1l+NMcP/fMU/vN4afLWZVyk/bvpKb66s/d\ 39342# +Pe33757/7Do9eu69jlHQRBxqV0cTQ/axi7vPH00mbrgVSGA9zLcerqpln/9gzfe/Z9bt+/ONst+Ebh15crvffd7IVg53Pnh9/7y337wF+vr66/90qs3\ 39343# vvLMYlaPzunLN57/6M6u82Vi8kKDqIhrFkdHh5PQKy5evPjfn30izq3+jCGE0eZTszvv3/70k7sPjm5+dM8lXTT1jRvTjdJ1Ohr0yzv37r35Xzevbl37\ 39344# +Nbd7/7Rbz17bbxc1Jvb52KM5j1WlIdi6tzJcbN7OOv39Pzm8OH+pO8D0Weue+UaZG1+MrHsRr2B9EIYluNhOR6Pp/f+AbwHMy/FYKypxO7e9ESu7Lzy\ 39345# 81deulquh3lCQk6EFxFVOEXXtccnJ1tbO2UxnB8dlz1HpAz0hwNBrGaTxWK5vbkBQ7IULSfjP/7TW1fPf/Dar/xa0xzGLMSxcD4eXkDxU8Xlq9h4r7LY\ 39346# Z5HR82ZGJrNUNfXJfH5p5+kU25PJxPtCNGeBK88Jw3TvQU649qWnCgmUlBPVhf29+Wd3duvuZPeTj2r0Z11hZeE3lAJwnLDWCqL6SPOqzkG1KGhaLXnt\ 39347# y9cXTZsRisGIKTqouJEAB3uPIO7K0xcLCcmiKAEs5vXB8cnN/x09mlUs0LRdQzIEoBMU0VynoYpdZ+aVSogZDg6PF9Vs/+hvf/g3/zo/qdt4NCiL2NSu\ 39348# cJB4cHBQjobjjXHbtiEYU3LKxbJqq3S0OKqPzayrgsfMtQ9v8ivPd3KhJUl6DZ0mLyJCEe/rmJuufTS5HxOchixxY9RnRq8XECcPH00uXNgO6qpqvrk9\ 39349# UtXgpE3N0aJmr0ySiCKbpJ57+63/7IfFy699s8+lGQwZSB5GY3JeRJV0DuiXvdgmXxRmJlBIaBfTw4Pj69dfqKsGUIorfBFCuP7SC58+fGd+dHgcq2nK\ 39350# A8tlP9z//ODNf36/OV4+uPMeIBEZTB4AkUU8YRmE0xQbBbMpnO9I7/3+g0/qqt3eOncyXxRlH+q6yF45/O3f/Z3ndr7/xt+9GRv21StjJOYp3nqwF3O6\ 39351# ffc2NFmC076KiPfeCMsk1cxM1RB8Uue8CDU2+3uPmjZubG/vHU2UKtHlvs5n8fDzz7/x7d/8/T/4zvnNdabsvF8rtK4Ws1ne3T+cL0JpqhQi62OysxIv\ 39352# KkZVBcCUlGjr+e7nDyjh/Lmdw4MT8c7gveuT6U//5M++/8d/eHFnsHVlPdGyCcIgEfP5o8N5dTSfaJE1uJyz/0nqbsxmlAzSNKn4anH0MKXhqPTeT6ez\ 39353# 0PMiatkVXg/2Zx9+cPdHH955eHffeUZGy7Hw5d78OGubDckgKUoWPSPVBCCWBc57f8q1AKo7OHy4t3dwfms95a6qKjjrUlS48XAQG8zgPv74sDpuxSwm\ 39354# QNpvffMXvv7KtVzXdd264MUVIk6fQMHqdAKGTEFMJqqH08n+3vTS5Uuz2axtojqSKcUaaNrYsF5Gyx068Y4SoDJaC9/59q9/6xu/uDEqSUU2E9OfCJqZ\ 39355# pZRMICIxw3mZz6rp0ezSzpXDvalFQzZ1yWknmlJeSpKubjKRjYzLcbn2+uv/8uev//2LLz5z+cqF1HWCrI5P5EYIQhyQ4VUsw7FnqOezhk53dnbufPwR\ 39356# SOdC19Q5x6IY9PvhcNH46JlU1TufBr3e/rR+6/3/uH3/7he7E69wznVd/H/eiAhWfI60lL0WzNY0yWkYrJXH08nG2jjHzEiFu/XR/b39+fG02z1Y1BZF\ 39357# LYs8ms2alHx0736wd/+zaRFKy6JSyPZoDA9VTTmvnkunTNwHiwlAEVxZ9EbjUuBi200mU6gIXJdTjFGUKt45pw5Q5JxzzE57BkJqVW/ZZetkc22oqhAx\ 39358# swyG1VPs9C2mZGY2VWWOJL33q3YmmWgASJNVuYpAGHNWSuqyCwXRkGLZmaX/A0GLBDxi5LN0AAAAAElFTkSuQmCC"/> \ 39359# <a href="https://freshluts.com/users/64078">InAvision - FreshLUTs</a></center>"} 39360 39361#@gui : sep = value(0)_0+ 39362#@gui : note = note{"<center><img src="data:image/png;base64,\ 39363# iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAC/VBMVEUEAwju6+4FBAnv7O8FBgoIDxju5+oPERcICQ8HCA0GBwwLEBkRFR/u6e05SFU6\ 39364# PkYzO0YSFx8MEx0HDRYOCQ1aXmcpOEcgLToJCxFHT1lFTFUtPUwsOUUhMD0YHCcTGCEKERvt5OdrcHZdYmpUX2dSWmNKVWBQVl9EVF4/T1o9S1c3RVEz\ 39365# RFEzPkomNUMlM0AqMTwdIysKDhUGCxPu6evDtLh0eH1ta25XXWVOXGVNVF1JUVtMUFo/R1ExQE0vPEkqNkIyOUEfKzgjKzYqKzIiKTIgJS0SFhwdFxsQ\ 39366# DhMLCg/ZxsjIu8DIuLq+sLO5rLGwpKZ7foSThIBjaHFpaG1lZWtZW2NLWmNTWV9QVFpNTFA6Qk1MRUk3PEksPEkuNkJBPUEoLjobJTMmKC4rICUgICUV\ 39367# GCI2ISAgGh4QFB3m2t3d0NLVwsPOv8O7sbnOtbLIsLG3oJ2mm5yYk5bPnZKGh4l8dnm6eXJwb3JmaG5ZYmlVWWOIY2FKWV9DT1pATFiKW1Y7RVG4YUqP\ 39368# UEE4NjscKTcdKDRwODAeJjBFKSoTGyQoGh4xGhkgExQUDRDTwMTLvcK4tMGvr7zKtLSvqK63qaver6rAq6q1pqepoKGXlqC5op+zmZOVkJKrlpHKl4yB\ 39369# gIXfj32JeXxtdHh0dHZwcnSmfnJobXJoa3DEeWxeY2xnYWhSXGWfa2G0dV+4bV6ybl2QZFqZX1m2Z1WBWFR5U1CRVk5GRk5lQEFWP0ExNjx3QzhbOTc2\ 39370# LTFOMTBfNC0XICwdHyo1JSc+Hx04GxsWFBns4OLp3N+/ucXAt77MurzQuLjRsanFqqmfnKbQrKW9qKWqoKLCpJzZp5qfl5nFopi4m5WHi5WgkpHfl4y7\ 39371# kYWch4WYhYF8fX+DfX6Jfn24gnt/fnunfHpeaneRenWqenKCcnKkeXBYZ27BhW2Xbm3Kf2yTZmZyYmRhYmN2ZGJuX2C/clxKTlqqalhYTE4+Rko9QEpv\ 39372# SUaBTkU2OUFNNzY8LzJaMSoaIyUoFRRPuIDSAAAD7UlEQVQ4y0WQY3RjURSF77y+l4ekQeM0TdJYbZPO1HabqW1zbBt1O7Zt27Zt2zbW3FmZtWb/uD/u\ 39373# +dY+ex8QUSoMDAxiMn0Xzu3RgUajtXN0dGxjl0MbBwcH0Li3KCfIzdmk8knv097VTvwfQyCCLcnOczeq+Bk+N0627+D6D3CEAIQgEBakyx7uru2fnt4v\ 39374# 9dL5rtAEInYLO1AUmufm7MzUZKgy0udf7tEj0avjYWhDo7nS7EBJkZu7i8DIzxzIV/VPndl9StduiV6dxhyL79y5oyv0AaVCFw93qWmokck06nxuzp7R\ 39375# dUq3pKTELl4JCfHtj3ToCGqlppBQaQhcE8zUqvqlzp5xduqkSRMTJyR4He80ZuxYYAmWuki1ZmdBodkwWD1gyb3ePadNm5qcnNRtwuQTCfHxoFYoFIa6\ 39376# ObsLgs2GLPXgLL+nix6+efs4tXuvUxfOeHWZDmpHh4fDGIKQQrPWb2WWXq/ZWBVbHtu07tnMXnOSrriAvaWjw11gzsJgU4BGbdDrc1t4vNhDtt0jF6++\ 39377# 3uVBISgNFwo9BAIBc6hRO4Q5RG9k2XitzVVVLSNXj1g8btx4YHELDWFmqf1DpAKDQZmi9sttInktv3/W7Rm5Krnz0fEgIlxq0gebhvqp56YYFviZzeyd\ 39378# X3c0HzxQt667d8rpidNBvcVjdKjH8AXKnhfP9Z6lFK+YP2jzmrU79jzq1DNsyEptCpBFscXeqt6zvG/3ueozCufNeb5+zbu1H570Sc4JioqSMUB9hHjA\ 39379# ALHmjs+i1ywSAWDQtvUbRsx7UUXimRYZ7ikCubmSwADvpUsXZn+KAVCxW5dtGFF3AKGI6PdicaAvSBNn5ATcUmoirFYUIAio3Hpt3rKDCEoSeGAmP00J\ 39380# lvfr7z04m8W2NsbABQixj7d/1bA4gJKUiDWQr/QF7C1hkrBoOYfD8fwLMHD4ogSgCJT4rOMv8Qf1siiWNQanxzBEMAHPhsRFHqJq4AqEYOmW83VAVsmo\ 39381# lFVyoEg4v3u/vLqsjEVQNhQCA9MkvoAhp3PkcjlHzkABqO77cr8nhX1DCZJCyDBNWh4fMBg1jBqc7kkXwQrf+w5rwHFPGYB9EHS7vy87E9TQ6QwnOr0t\ 39382# RsC/TX0bmnCRaNcPkiQpKjpAZ8kBXC7mBAG6ApZANm3+0ozvHjZ5G4qiFFUi8S+RAC6mwLgYxuU6VVTj5a0AKd85qFcriiJoDDvI31IAuG0xblsoLLL4\ 39383# 4/biONGujQ35r/KrAYJGF+QFsEsAxlVgmEKByUflR0b/Yo0qjgUVKyqK8wEqiiqQFFmBAlM4/VVjZJm1rMIWBw9JbImM4wGEwtnDC/b9AdM3HYNA1prq\ 39384# AAAAAElFTkSuQmCC"/> \ 39385# <a href="https://freshluts.com/users/120">J.T. Semple - FreshLUTs</a></center>"} 39386 39387#@gui : sep = value(0)_0+ 39388#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAmCAMAAACf4xmcAAACMVBMVEULF\ 39389# iILFyEOGSMJFSEOGyQOGCELGCITHykLGCELFh8JFh8NFyEQHSYSHicUISoNFyINGSULGCQWICoJFiMhKzQbJS8mMToKFSIdKDEZIy0RHSchLTgZJi8XI\ 39390# iwTGyQQGiMpMzsbKDQYJTAKFiQ4Qkg0PkYlLzgeKjQNFh8yPUQfLDcXIy0RHisQHCkWGyRUXmojLzkjLTYTIC0PGyceHyTr7/jK2eyhssZIVWFDTlo3Q\ 39391# 047RksvOkIuOEEtNz8pNj8nMz4eKTMaJzITGSEQFyHe6PTV4O7D1+vE1+a+0OTH1uPCzt6VsNGdrL2PlKNhfJxqd4ZocX4+SVQ6RlA3QUgtOkclMTwXJ\ 39392# C8aHybl6PLT4fLQ3uzM2erR1+O5zOOvxNysvtSEps2jtcqNqsiAocecp7hohaR+jaJyfolSaodLYn6DdX1kcHtnZ3RZZG9JWG1LWWVPWWM3TGMyP01GR\ 39393# EgqN0QxNEAjMT8aKTdFNzEdJSkzKicXHyHk7fbG3vbN3PTW4PHM3PDn5Oq2z+rC0Oa0yd2sxN2ivdy6yNrLy9avvs6otsmTrMmmrsCUpsB7lbd5krOMn\ 39394# q/VuJmFj5lsgJlYdJSDhZF7fo2ciIxvfIuMg4Z8cYCDbndeanZCWnNiYW85UW9OVWlhYmRrWWSJdmNiWmFQU15LT1xXT1oxRFo8SldQR0snN0oyPUdTT\ 39395# UQ4OkRoT0EeLD5IRD0uLTcyNTVWPzIfIzA7MC4sKCsgJCokISPHXUUCAAAD5klEQVQ4y0WSBXfbMBRGnxRbppniLJx0gSZpk6w0bFfumJmZmZmZmZmZG\ 39396# X7dnqLBPZKPYl19T1IM4PMB/YcBGd0gHhCZ2kTTDJtWJfv22/2LW/ylLDQZdM02dCA45ppKq/r2+3BpN6CFGiI80Bo/lgjouFBHTZZR+7qzH/g4clITo\ 39397# gzu+vVvMkBsaggNi+7s15dreqawR0Nsm9KQ83B1vUcAqA18b6h1f+/uAUDNy+g+7gNCb9/ZohKqyVgZV2Jc949kD86GdJ/nAeLjXX3x+JvnUkNiPkIMo\ 39398# jJmzNBs1CCkY9hfqp5+Lm1udChzfCoxDAMrJ2XUMA47j0LfrTt5Y/Xa0acm9LYzoPlIIdlTmFFlaKihI7ale+6Evf0PzZx7YM7ARjmEe9YL5pdPM6pk1\ 39399# IDHAYe4U8cO7d9/7sxhC5bvcDyZkUKg77snj3r+pglCGTZw3ohZJ4YOX3lllQNJanfv+vl6yx7ZIMAlnsbJeAMPzh95es6YB+fukRDB7WuFAj9GCAjhj\ 39400# sBlAxcdPTJq+PFVs1+Cx0+laTpCdNR0DiAE1KULRgwYNm/MyoubPJfoREMIERpHJSri0rGjhw2YdezC1UWbXFtV+aWhhirIMpUrMMYcZ/mooQNGLj4/f\ 39401# ulElzJbNiqgDZQjNOpIN2f3HzF/4Zjx97cx8VZggEp4OLUqRZ3ma6OHn1mycPzaXY6NcQSNCkAQzeyt65X/iz0/O2DxsiXLroeT+IufUcA1zNMqd+yBv\ 39402# e3WuP2H9417z+wMIEQgNB0712wA69m4USPHTpzM+Ecl5jjAs4iKI57mQeOGDVOb8oO220zHGd6EpqoMG2PYwXUdZcKgmLN1Ui3gxH8IUCoJKB9Rc/Kgd\ 39403# NO6urxDKWNiNQ+CaNQ0eeuFmKaU2Di1nB60rrHp71Jhg1+gKKap4ENpHRxT2qelTL6Mi8KFSCSSSCT4g8t+q94pK1asCQsoJvcEEO6NhMPhThxEEv743\ 39404# eaS1T74bVkRYGpFCwgaGgKBMHrxNZPjVmzFYMvycwktoQVzuYaGXC4XzDVwr7NuRcKyJq75k/UnjEIw2CdY6blAJy9/eVLAsgbXFYUnwvAIfThtbX2Cs\ 39405# Xw43jsS2DgpGPHXNVuWhZY4BJMY1LS1ttZks63B2q54vFicvjnvN3s1x5rEBVmYho1CS3ZKtjpb01bfmS4Wi+lXZWASje7Y7jBGJSVuYWGJMWhpaclWV\ 39406# 9e019em0tPT6S5L6RVV0ltLrhS1FKzMs7Bodkp19ZAhQ9qnxWK1qVRXKh+bXnKcUpcLUI5iZUlCD/c2pQa9jo5pHR31tSjmU/l4vAwcH7gsKjHqMvob3\ 39407# PCdJnRHhgoAAAAASUVORK5CYII="/> \ 39408# <a href="https://sellfy.com/p/SGnG/">Kyler Holland 10 Free CLUTs</a></center>"} 39409 39410#@gui : sep = value(0)_0+ 39411#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIMAAAAWCAMAAADU6N+kAAAANlBMVEUA\ 39412# AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAABH0wLDAAAAEHRSTlMAv0Dfn4CP78+vIDBgcFAQ4LAwBQAAA\ 39413# opJREFUSMeVlVmy4yAMRcFMNuA47H+z/TQgMSSp6vsRhAT4IAQxoBMUill1gdCd/Z+sTagI4iG5ettQztrbmOpAV1+h4oQX2uUF6pFy3BEUqHs00r0yoD\ 39414# dZe7ZduE5cImdlwzIh9RIwPQ5tMEuww5wMI2Nr7/ebJz4ehLg3+BvrLSJvzdGtARQaiRgsdml7nlcLl6xIMUy0oy4xVCIvnQ1iu1qLSQFE3cMML/mQA4T\ 39415# OOc9DhtJGhkDkHnfx/qrmZgBJ0cjgpO8uwcN2ZYgTg2Xcxzzt/xl6mzilOprsnYHOwvWoJXaO9CU4qke+M0h6+0rEcCrDNHhZr+ih8b3ovdLZ8FfyuDNQ\ 39416# cS+1Wem6qWcMTugJhnphyGNxlFsPUKzrOIRBvfZPMwNeq2v0zQxq00siS3mj8K1V+cYJvr522MlQJ3bGhOYFQUplcDNDkaUqMejCPM572Ttcm8+VNZ69f\ 39417# /CC7Qz7TGII+oGFQXaVWrd+MWg9AoKW+n59NwYrRxFAyiC5K2PBXP2AvjPU/Cc+1P3jc+HMDKplZpAS8UYZoFXhxRAL5KJ+c2p7w0qVGVTKoJmV1OSRQR\ 39418# PF0t5cTiLuqpeQV4b9CXEvKJE+Whnu8fk/ve764sCSF3sLw6RfDJ32MMLgJgbbD+iG9ET5o2BLGW6zFPtvhv0dC/pkEIMXhu5EyZejWJK9kaF9ZIirUw+\ 39419# Sn60yMlTsKEOcGVJWhkZQwtAWBmXMnbjLcou1gEqtCcNDNjA0bJmB3UGsi1vDyrymnas1HTydwzGAsk/UrX164Dh2Lurkg1rGrGDj81QaqdrWM8mYHpSL\ 39420# ayobMwVfAVSz+arDgwrt5wDlbgjnCaqAY0EvUwLo+bAaK/fYPzbBi89MLkUDAAAAAElFTkSuQmCC"/> <a href="https://lutify.me\ 39421# /free-luts/">Lutify.Me Free LUTs</a></center>"} 39422 39423#@gui : sep = value(0)_0+ 39424#@gui : note = note{"<center><a href="https://michaelezra.com">Michael Ezra</a>\ 39425# </center>"} 39426 39427#@gui : sep = value(0)_0+ 39428#@gui : note = note{"<center>Moviz LUTs</center>"} 39429 39430#@gui : sep = value(0)_0+ 39431#@gui : note = note{"<center><a href="https://freshluts.com/users/992">Ohad Peretz - FreshLUTs</a></center>"} 39432 39433#@gui : sep = value(0)_0+ 39434#@gui : #@gui : note = note{"<center><img src="data:image/png;base64,\ 39435# iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAC/VBMVEX9AEL7AUL9AUP8AED9AUH6AkL4AkP6A0L4A0H7AUT6AkD7AUD2BEP6AkT+AUX0B\ 39436# UL+AUD4+Pj0BkT9AUTxBkL3A0D9+fv2BUb5Az79+/r/AEL6+fr6/Pf81uPlD0b4BEXuCUT6/f32+/j8+Pjv8O/bGEnhE0frC0T2BUL++/38/fn98/f96v\ 39437# HML1XXH03oDUX+8/z99fr38fby8vH83+nk4uT50d/4us/uVn7tPWrrM2DqGVHSI1DoEUjzCEXxB0X5+f397vj88vTy7PP58vH65+z62ur84+jn6Of5x9j\ 39438# a19bTztD0sce0r7HncozkPGywVGvrNmTkLmDQNFnCN1fZKVbRJ1TsEkzyDEjpDUfyBz77Aj7sCz39/f3/8vn29/X79vT39vL19PL77u/96O7t6+vs3975\ 39439# ztzOz8/TyMj2sMPzqcLzpb31oLrDtbnNsrm7u7f1l7P1ka7xkqvvgqOtnZ+0m53ndJPtbY30ZIazeoWodYPmWHylb3inZ3euZnboSXTuRnG6Smm3RWDaM\ 39440# mDrLlvFNVrsJ1rlIlfLKlTqH1TvGk/bIk7pGUv5A0niDUP/AUPnC0HuCEH05ens5eXb3tz6y9vtz9fk1Nbt0dT3rsvQwsbIxcXqrcLGvL3Pt7r0m7byob\ 39441# XFra6xqqzOnqqtpKPtjKKolaDJj53udpvahZmkkpbvbpauj5PwaY/lZI2egoi+dIToVIS8boLFYHvjXHu6YXboRXS1WnHjRnC9T2+vXW7KUW7XRWzoQWy\ 39442# +QmCyTF/mK169PVvtIVPdIFLjHk/jE03tDErZHUn0BTz2+fr+5/Xz6uru6Oju2Nvv19vh2dn2xNPW09L4xdLY0ND3tczjv8jhxcfWwMbhtL71rL69t72+\ 39443# vLrSt7rfq7nqp7fMq7DVoK7jmq68oaXelKTgi52nm5rMkprNhpa/hJTngJTmYIvgboquhYmmf4jqY4KxdIG8aYGcdn3YZX3QaXvZX3vnTHfrT3WqWmvjN\ 39444# WjOOmPJOF/GM1XYIFXtDUL6xIL1AAAFQklEQVRIx6XWA3QcQRgA4J2ZNc527KRtnDRJbdu2bdu2bdu2bdu2XueS9vU2TfX6v3f7bubm239v5p+5IwAgCM\ 39445# JC/HWkB/8ewB2e7QzGyEawLA0YiPugQjsMut/8HgBGoJQRfln79y8T7p+ipH8eb7H8ACSJoOjoU6zz4pszpl5uOuv+qtIBGi3uJjIMEo/f/7nHssIFfNU\ 39446# +matUCTFXjRw3a3MSY0K/+r7KoTueXMpXc0zzJW+Kvi8aN79BVDWfkTd6aTIGAEp+71rXyVGoe9lkmoNaQIvD+y6yqw/U7SaiDAji9fs6N8s55u0IAIAg\ 39447# CAQSBEQYd88JNYd20ul/FiDQr0uzyEIDRB4CAiHkfpEWzhnwNG9Q3rUigjDdzKLhxQrnnDDARA2RBATAtyLgJE2l1bWCYvoByMkAx4ml7kTm7xfIA47j9\ 39448# w/33zcoPNzPX6dQQP2XIpkM01IAR3pOr4Lzf3Gi5hanRAHgLB+2rkObJk2mzLj72qiAApM02RoSzylkgHCWmlm9eQVuCACUf7GFBX19zEGV1d55XRxEgm\ 39449# bzqGzTjQB5AMA6uozO3ZungIWM6FLY1yfqdONGhexZco8QAL6F45ZPre16eUmWaV21kYsXAMmGtfY1Ty9Rjg7UJXZrrOPdQLnpULV2ckBvnZQ5jnIXq25\ 39450# jAYM9iSEtSE+LLr0bACbrGduFSjIQsWZ0VD8thFDheuYbNFkHaKgSAEWlDaIc87zzDJYtg//jGrEpTggJ6OqgrhxTlhPx2n+vYsDqntcI7S0D4W3U02ga\ 39451# A0Jck8uQ+UFSMsC91HfAbDicubvskbI2CWqrJyGEDDtovNWr2tVeAXqa/ZYC8HSpY+Y44FFPVNikoKWpgGCVq3N7mW11FvTaywhEGgBU2Clze8YTfKpnW\ 39452# GFSuQHD6jpFmYPVVY8u2CWyAKUSqXR9qxyULGhYwavSCo5M3t0yr9rLZhvbqZKe4oEbhNU3tAfpwMOK5LcHYHhlQota3gav3EWUPOXukfrUt8alA9a2pj\ 39453# RAQECamJTijUK8vA4WZxgIgUTvqGftTiDPWZpobilJGAAAIIRYcXuLhHgZmgdCAovAHgVCE2Tr4HfN1kBJYyBgkBpGTfkr3sHHyxEQA93GfHkGEp7hmGe\ 39454# zl00DNEwlTo1upW9w/nKp2tHRN9YlyzBiVWT2eMm9mY2lXSLExyRkhnasHdzASCuGQSZrG59WogxQH+rYWikx4CNW3i65J9kppfj1nK32aZcKlFunVFkr\ 39455# yQC967yt7mCEABvRocaR68vXbejacWY+dd1EmsY1PLRrdP6yWhlgNa+yqJfQIq0sv7x6cHD12qPyRVbOFtubggQUNaVmZ1lkFJHnnqaYQWO97QMlmtKUb\ 39456# pE/KkdISGieCUsTWdJCQMa/cwF7Isd5AkAxmke5srUsx0Atp4zYWTw+PmFnQAUTj/BnAdsK52pn5LSyUwMAsKdhtixtKwgizgJ4nmXdVwAgUann3JwNk6\ 39457# BWm/5spUvEeNcsUt6owIcXoVKpIL7i/RTQc2F0zHYJKhTpAGnSrR9pzTEncQjHQQInTy0QjV+xudF5EjSSFjfThYDoLTFq6/iX4Q4W4AxIUDrCty27mPN\ 39458# kAoM1Bj8FYvo2zuGd6+y9TR/DypTp36dH18XNokNbDFCSMGOA7xoQF5vZoK497tzUpk0n1ovOkr1hfIWKLPELQJJICHQVbxVrz54JR3Z7ofl9dYGy9crg\ 39459# d4hkxeTBJYp2W1+0xEAnRapY8If/ATxLEUJFk8lUUYUsBCmwiIC/JQhhRgAc35sY/FP8L/gKJ0Uj1jCuNAUAAAAASUVORK5CYII=\"/> \ 39460# <a href="https://gumroad.com/sarikasat">Olivio Sarikas - Free LUT Packs</a></center>"} 39461 39462#@gui : sep = value(0)_0+ 39463#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAClFBMVEUA\ 39464# AABzk3pTeVfj8PHk7u3Q39rp9PW1x726zcSUrJt4l3/Y7fLq5Ojt9PTv9fPn9Pbp8fHk7+/h7u66zMO5y8JtjnRxkXdkhmlnim7R6/Hc7/Ln9fbn8PDq8\ 39465# O/n9Pbt9PPR4Nvn7ezg6+zO3di3y8K2yL64zMOZs6KYsaF1lXyu3vDq2d/o5url5uru9PPo9vfm8/Xn8PC2yL+3y8G3ysCkuqtmim1oi2/0PVwAsO7m8f\ 39466# MBru33O1kGqe3r8/QKrO32PFrp8vT5PFjzO1r3N1YIp+zyOln0NFbnydHn8fLB4/ABrO4Npez2PVv1OFdNTU3j9PQRoesFq+0LpuwQouvpvMaCgoLzZX1\ 39467# SUlK95PG03vB4ze9Rve4ZsO4HpOwVnermx9C9wMHyc4jwbINra2vV6/Kl2PGs3e9aw+4gsu4Ire4vse0Mre1AsewRqewVn+samuoZl+nn3uPW2drstMDo\ 39468# tb+nq6ztjZ6HiIjucIbySmX0P11YWFj6OFT3MlLs9Pbm8/Xn8fTu8vPh8fPB5fG34/Gl2/GQ1fGb1PGf2vBox+5vxO5Uwu7k6+0TsO3n6exRsewDqezh5\ 39469# +kSmenc4+TqxM7rt8Lsp7XwkqOen6DshpmRkZKAgYHvXnbwWHFnZ2fzRmP0QmBVVVX3NlX5NVL5L07j8vPe8PPM6fJsyfGDyPCs3u+Dzu9gw+9Hvu49uu\ 39470# 5duu1Que1KrO1Ku+xJtewmrey/1+ssoOodnuoTkOjj4eXM1eTS1OLa39/k2N7Y29zbztnl0NfjzNPsusS3ubrrrbm1uLjnrLixsrLmpLGur6+urq/snqz\ 39471# olaTvip2WmJjxfZHsfZCLjY3raIB9fn7uYXjxUGryTWj1O1r4PVn6PFdLSkoQ11vXAAAAOHRSTlMAGwXd07u0iIRHJv796eTi4tjXiG8eGQ8M/vvp3dnU\ 39472# 1L+6urmBdGxCQRj+/vv76+rn2oWCgmwODToLEi0AAAKySURBVDjLZdNlW9tQFAfwFCiluDOc4XPf2hQyUqF0pe3oVvcWdxhuw204A4YPm7u7u7t+mSW5G\ 39473# S0Pv1d5zvkn5ya5F7JaExftGO7uGe4YHbcHWo3itC0oS5N9tbVbczYoxIkCrWQX69aa3SdkMns6WExhX4/KLdbOtr8uyiVbyMTkq3RMnFAbSLV5iLODOo\ 39474# eoszTdTJJuvYPz8v0OWfmgmtOWy/wvt8uBQs6PUpN9YdcFplVuFhWsY1dLDgu42C5k2dAF+uJ9/63lp0F9sC1v7wpaN3yI05OlRzop1peeR2EgYx+gyvD\ 39475# Bvp99db2iY1AqlRZmCMjAqcJEQBuyG4rf9PvP4tO8xETeORQmoRoeCBS60KGdsiU2u0adystrESAIIkBRBEFPXucR9JnbIcdj9Wz24jutvh01yafkpvGK\ 39476# yW/P0E79AZz+yFoozMzG1N69hgxJ0ifTlXXKV+l/7yMFqYTLoZCHAg/Uf26Ej0oqDr9Rzj9E5JJDsCrtIK7AHQsk4LiPBXjgrXJ+thkLCNBLaTgsEGZOI\ 39477# HxvHJLMfsFG1DVPYU+YvnfLUFRUNBCKLZJLBBrKUVNVVZVp/CP6Qt77ssF8ZthgMGCL3CFrSCL87MVfE8bfFOmvSeIabxYXD2fSoPiNIhBYeN8Ek5oquU\ 39478# kJM5klxSUudOxTm7mAuBQmPRCLRKKF51dKBjwDsJ/lakwB7uwnnICrf2EBRs2N22oa/ruDLckkDuGHjM/AiSs7N/tBGN/SOYYNfvkMeXW8PwZsOapMbBN\ 39479# QvBaTybIIcuv7e5dZE+KUWrI/5kVZ3vbesjkOKHMmJsBVbZm3s825o5Za+GCuMZm4XbEhgrLi6PluGalm8Dn8sa8MDp9hGQmOAfOt/HzsXUcrPxmnLR9G\ 39480# Xe19/KDVAui0SC9PD69IGj3AWv0HukgIS3/cZL8AAAAASUVORK5CYII="/> <a href="https://www.on1.com/free/lut-packs/">\ 39481# ON1 Free Photography LUTs</a></center>"} 39482 39483#@gui : sep = value(0)_0+ 39484#@gui : note = note{"<center><a href="https://marcrphoto.wordpress.com/specials/698-2/">PictureFX \ 39485# - A Free HaldCLUT Set</a></center>"} 39486 39487#@gui : sep = value(0)_0+ 39488#@gui : note = note{"<center><img src="data:image/png;base64,\ 39489# iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAC+lBMVEUAAAAAAAAAAADw8O8AAABiYmLv7+84ODgAAAAaGhoJCQjs7OwmDwjQ0NDu7u7k5\ 39490# OSPj4/s7Oy2trYAAAAAAACpqanv7+/Z2dnHx8fl5eWRkZFsbGzCwsLg4ODi4uLPz8/s7Ozn5+dfX1/v7++oqKgyGA0uIBseCwTb29vS0tIdDwzy8vLt7e\ 39491# zHxsb+rB26urrr6urz2sGTc63vUQPn5+fk5ORYkczWbo4kJCT9pBrY3N1YsJjVKAfkMQToRQCwsLCZe7CPaqZZMGX8pir3ggvd4d/y5tjT09Pz0q2am5v\ 39492# SZIJKHEakFBn7lBXkKA6xFQ7MHwL1awHzZQDyWwDbOgDy7eVZm9OTk5ZasYp/gYJZOXVsbnEZNmr3sGGzNVKzK0P6mzdNFjeEGjNeFC0dHiH9pQ/6jQje\ 39493# SAPgYADX19fOzs5hjcXYn7yoqKh2VJIeQ4v0xIlbs3/GTWq7Q2LyZlH5q05hIkovMkKtHzDt1gLt2+Feo9eBpsSqqqrRfZ7QdJmJiotnRYRDVX72uHJJJ\ 39494# FpdK1cVOVVKRk83Hk9yKE36qEBxFS6eGyz8nB32dw3XHwGek7eFhLSQeLFCa6/zzqN7XZvzx5ZKopXGVnVMLGkRXl5rMl6UNE1aGz66KC6UVSfY0wdmJA\ 39495# TCFwQ+EgStbADqWQDv19niyNdqncmvyb1Wf7jj3bOQkrKGda9YqqmZu6Xt5aBBbZlusYbzhoD0vX7w33pfRXlqOG9HRW5bYWSLNl6eJUByHjyQGC7rTir\ 39496# +sSX2nwHNwgDJYgDBUABvks3E28y0wcyNrsi1rMKyoreOdK7Kw6tyqaGXX5OGd3Pma3OXd2xTWWctRWIpb2AoIl73mVDFrzgmLTNbjRJ3OBHQpgC/hQDa\ 39497# hABgoNGlvtDgts7yzMzuwb6cg7qipqmkpKS4gJ+JtJs/gpuDdpdWcI44kIYnZ36rjn0eTnt9V3p3RHovjHEnhG9sdWoigmXweFRcglMtekwkF0qkc0Lh1\ 39498# z3VRDurkQCLhADNWgC0rmDQAAAAK3RSTlMABRL+FyPzRw0IIuj+Ou7HXtmKNi0Y5aqgl3lULNTPwKxuN82+rJCPjmZXgENtfQAABTVJREFUWMPtl2dUUm\ 39499# EYx4NLBmju9t7jBUFFAyQxxdSMUjRNwTRzlZlarkzLnC0tLRtmVrb33mV777333nvXOT0X7XTuvcTl5Nf+XzzH1//v/p5HDrzU+Z9/TP3mteybtmLUps+\ 39500# xkFqya9FnNBEOMf8boEGb1u0aGmFId4xMLVq3aV4fSQVcju56EwzRBxMNac9i6NxNQ2RIMCm/KVtn3wgZFNEQuU5AA8rzsX49bT1te1IFHjg017VbXfWE\ 39501# nIshtoTfgoBAjsw4VAHS/qAO/ZDksKgwAoEn5cd5IFSfItCF0vecNj0nOaxQCQSiQCAPoc4M8qurEdFf298YMiFMqYyKCvP8I+DOj5PDTzPyGtlmRAFbz\ 39502# +kJG0NwgcLIyD1uCWs3rcWgjgtkucMfGFMAFgRAT8/pG3NCJrgVSqCuUETtmTdy5KZ+mFbAC+FhkgBMYwLANiEnJHmCm0RiExlV5KvyvXENCGt5mMhDEO\ 39503# iB8NTVC8Cm4XU3iY1NpMJXpfJVxdzYO2/kJlwgMwtVAxgkgClhghyo20Cg7+fnp1LF7AOFFQgX4P8FYESYILm6L4ny9bO3t/cDwPW9XzFcIIhnCGDabht\ 39504# tX1nkZ+/s7LxoEQ5YgYQeAi8BogWk31mcsBsIEolSoYJ+dLTzopj9Cy8hngM/LkhIC0jfkLThokQiKVQqYQHOzv7+/tE4oFpAjmgBi08nJSUVKRSKoiJf\ 39505# GKA7DogGAQwEMoNE9IB+G5KSqqrstYG+TCbzj/658MdxrUAcogegux+q+vTpXhOZj4+Pf8z3K1d4GL4BBwMAwqGnv8n6aDMZ4uMji/7y8dMaJBwsCPRC9\ 39506# ID0oWO6Da+o9JFBoF1ZWVlRvjk7WwQCme9OGACAfq/hoX1r0rt370nls4O3rsRAwOv8aqdldID00d0AMKAiDapQ3hUeHj5+tutWKQjIt52f4dR/GQ3g9h\ 39507# gtILQiLS1t0qTwiYMm7hyf5/oE44FAftkbJ6f+7voB+AQzRwwIDYX+romDIDiAjwuczS97DwqPeIYBduyCxw+EzElJeYULBObnl70FwHqpXsCS0TABAHZ\ 39508# Afc4cb28t4SgmAgFNftkzJ6fExIN6AcKhWsCO8J0pKSl5ed548oS4gEajeQ4Cievd9QLwfwOMUD4edg/JzfUeN64ga7BAvlWjefl4df/ExDWYfgAM0WtE\ 39509# +fbZW7ZsCXZ1nZWbCwAP9WW1Jj5+3WpcwAHRAIAwc/v212PHbg4OnjUrd9zn1Cy+OCI1Pn5q7Ik1yw6KEBlAfVNd/PDkyWHDcAIgLlwo4G8TR0D/QEb19\ 39510# PQAJL3n0qN0GKS0dGx2dtB9ccS5qVNjD0iRoQA0pcSuR3VKl2dnFogjlsfGxmYgwwEOq0rsID3s7Ipj1UHiiHWOjo5LD+kHWCCCwqpjOMHFpfipV6r4si\ 39511# MOQISwyAAz4nkxEKDvslKtrhYIOEw4N2aSP1wbEQHC4pIS6B8NzEoVpzoGBATclBLOW1IAloiUI1NWTjniELQNNgj9URnE08ZsEoDTFkOU8JBcnSo+Nwq\ 39512# ylHRMuaoyWI0QNfyrC0zEhw5nZNwiHbSk3jTZbU0pfeHcufNNCoRUMGbOBABZwZwyxHEcoOZRAZYsjo5LPLcp+ar64ur8BSYC6vMtuTqvumxus1ZEiTPQ\ 39513# P0URaNGMy2boAjA4LOtmjc2MsT8A6BPLpi0am1uzCH0Cgs3iWltZ1fudDiYd6xFiZWXNZTEJ81Ms2EwmqybcTl25LEKYTDabwaD/TlMTDhdkCaEpUnUYd\ 39514# f7HgPwCbcV8KluLH2kAAAAASUVORK5CYII="/> \ 39515# <a href="https://www.pixelmator.com/pro/free-luts/">Pixelmator Free LUTs</a></center>"} 39516 39517#@gui : sep = value(0)_2+ 39518#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAA5FBMVEX///\ 39519# 8AAABJSUnMzMzKysr39/fW1tb9/f3u7u7w8PD6+vrn5+d9fX2VlZXy8vKSkpKHh4e3t7eMjIz8/Pz7+/t2dnZra2tQUFD5+fn09PTq6urj4+PU1NSpqam\ 39520# amprt7e3c3NzY2NjR0dHDw8O/v7+vr6+ioqKDg4NFRUXOzs7GxsY1NTUqKioGBga5ubmmpqaenp56enphYWFcXFxNTU09PT3g4ODe3t61tbWxsbGrq6uP\ 39521# j49vb29lZWVXV1dCQkIKCgrAwMC8vLx+fn5zc3M5OTloaGgyMjIjIyMZGRkTExMeHh4Ueor/AAADBElEQVRYw+2X53LaQBSF74IaoghVQIjei023Daa4x\ 39522# 3be/31yV7vYBKyMCPlhe3JmgHMumk+rvbArATlRQM4iJ+gMARE4QZHvCxDFowFlwZcHkLtN9wl5NGo5YJIEpqyfVJ6kPUCS+LLF+Svh6tUYIMFzzE8pnh\ 39523# IfAzJjsqNr6zgA19mylZhxghwaUNV1jY2hlsIoX7b8VEcv6ANqNTax2QIN97pw2IUoP4xLp/FHyvfnaMfsG9lA76APAJjwJv+8V8wv0Bpv3EgMAgHwruw\ 39524# U84R5WeOwCh1WHMIA+EWUmDdxTl4rUJrhJEsQEuDSQpUH8Z6QjbvEShfCAkxaON+m2IqQn1hoQGgATHcBoET8NsERgKffARmCujwGQHYBWYdQTZXwgBwt\ 39525# dHgwDQwP+FrlQgMkWnB5KKC3rSG+t6ywgCLmNvd19JsYWDZ+JuVwAPcGc4F5j6DKtJm0M/NQAHX0/kPM99DeMdtHWwsGdLZJNGhcsAau0Wp84F30L14gg\ 39526# BiSiD5V95u+ov528UT9kK8HixmGXqERBEBNRmtulOAl7SYAsKulAscDRmSrx7oFfwEA5VZzHGc0qKrAVYkysYLKUycIEFr/Af8eoBuGQwGGYdxBKAVvrs\ 39527# UvClDib1I+w13atwOIirxXieUOABpZtycSOESDq+eN67afhVq/TXcCudHPZPJoPJrj7Z5Xstu9orkHUIkIlZkMBL2QMOV0FyAdBZQ0ToGQiQPP0SZcN0B\ 39528# NFz8ApIjpA6Co1zV5CxBGMlgVcQdwj/BS/gDQrbWawABiZpqDLSC3fqgrADuAzkuyasEB4K5WBg7ITsb8jD5O0Ppzaq45AFx9lYl/cAmwBQwbV0MOUEuK\ 39529# ApD31/RGne5sBTWugjxI/gFQtS050WGAfGLQknF2YqYoe7YJcsuLRQQAXdsDNNhG3iRziD7aimJvKl7ETiYfElkn0RwXoIyDGDrJJR5W6RWTs8s9wIXkV\ 39530# 8rSBbiSJIqSpCgSCnO2KlwA5CQLx1P1J78kdGJf67/w6QEnP3yfqF/1kj/apHwTgAAAAABJRU5ErkJggg=="/> \ 39531# <a href="https://discuss.pixls.us/t/help-to-create-a-set-of-pixls-us-color-luts">PIXLS.US Contributors</a></center>"} 39532 39533#@gui : sep = value(0)_0+ 39534#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAZlBMVEX18v\ 39535# ny7PauecS0g8jt5PPr4fHz7vju5/Tm2e7IptjXv+Pw6fXo2++wfMXMrdrj1OusdsPq3/C3icu6jc2yf8fdyOfUueDEn9Xl1u3ezOjaxeXStt/BmdK8ks/\ 39536# h0OrPst2mbL6lar0clnGlAAABY0lEQVQ4y5WT2ZqDIAyFhbIp++JWt5n3f8kBtVorc1Eu+ID8JCcJFF8NwimlnPxn5oJZO9d1xzDImIGwXRmgmzyUbW9v\ 39537# bijT/tHQbb3AVvOrHQkl6zd3cUcv9zs/XuP2pnojgHbLZ0xmnucVMam7am30kZ/yubQHh/ZVZ9DKNUr1qVxPpZp04IZdQVmubkzZDLAgFRybZr2iH5tOH\ 39538# EScjOKRhUUYbTx74OQKil1vLFvd4sWDCBhe+W4DCjeTxM0hzvOvVBBF4Me0U7UDUw/WIoS1ltFvAigpyhfgNE3qLFwj7UAcByDxCmDJ8wCXOFmAHes88G\ 39539# wFSCJFPeaBqWdbJwBEOQBBirde46HNAeUgyN5MHvQdEBLj13NgDKJPAISekeNBiWdAV8B6xVIKJwH1BZDlZj8JLVt4An45/B86cGMiAABnrioYJrdvh1h\ 39540# HgJNSutIWJPszYyOZYMyi3ZyFCCm+HH88KhF9A33HkAAAAABJRU5ErkJggg=="/> \ 39541# <a href="https://purple11.com/free-luts/">Purple11 - Free LUTs</a></center>"} 39542 39543#@gui : sep = value(0)_0+ 39544#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAgCAMAAAAynjhNAAAA1VBMVEX+\ 39545# /v4ODg4DAwP7+/sQEBD5+flRUVFubm7z8/Pw8PCioqJSUlKAgIC3t7dqamo6Ojrk5OTn5+elpaU/Pz8iIiIYGBjh4eHa2trX19eysrKtra1eXl5YWFg9P\ 39546# T0tLS0kJCT29vb09PSJiYlwcHBgYGBVVVVMTExCQkIyMjInJycUFBTt7e3U1NTR0dHOzs6+vr66urqRkZFzc3NJSUkgICAICAjJycnFxcWvr6+cnJx3d3\ 39547# dlZWXp6em/v7+1tbWWlpZ7e3s3Nzfc3Nynp6eEhIR8fHxaWlqIUZ+rAAABlklEQVQoz4WT13KrMBRFZUsCgwFhegdjinFvcb1p997k/z8pJJa7ZrIeNGd\ 39548# maaTzsDdoXvFk6PFT8xrQbJxZBZ7lHVaNCxeNVrlmQ4BVzY/Rg0YkHWPwDXbmZHCrzXdp0gInWqOUmBeN+spsCMEFOHxe9AdUV4HXweAW+Gd7qFCtUbGz\ 39549# IGCg7nKzCcJx92ch4UyL3u5O2g3AHefNnueVXq9XH+mmS1fkEdVQI1wYZYoSxsWSc5N7LXLeG2cL68K37AU3ftBtWWqrdi+YQbjVXczSYync1v/OdI+ll\ 39550# 3PyfwihkJZr1uNGFCmS9JZxosDUhFSryiDiEDBXs5ws/vRLF7N1Bz8v9xPl4DD0S60B3hXiNNhbD3r5qnAdAKyPQlv0xdad9kr93a81dIIyjPIJvNFAnc\ 39551# ryOqkHPJrJ8lQ9ad1JjhHDGB4fwnRMRnkDoFxTAYvOP9+sw4SizGWE6YWPBqco8lMBXkthQ6NIg0xSJznb7t95aN7WYKDPR7QG9mtpPpYoDmiJsuquRBT\ 39552# Dd1VXMa4r+EuBvwA2hClvJ4GaGgAAAABJRU5ErkJggg=="/> <a href="https://www.rocketstock.com/free-after-effects-t\ 39553# emplates/35-free-luts-for-color-grading-videos/">RocketStock 35 Free LUTs for Color Grading</a></center>"} 39554 39555#@gui : sep = value(0)_0+ 39556#@gui : note = note{"<center><img src="data:image/png;base64,\ 39557# iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAC91BMVEVLNHxKKWxjXKBTO4Pr6nZoYqXWemJON4BNLnVtbqzRa19aUZeILkrJIyaQ69Nd\ 39558# V5vr6YyUaoPs63qIY3pKL3nag2QzHFnXc1jlnk9zQk1TFUdoMT1XxK9saKjv36BZS5Xi6JDq64TEb3bikW/hhmvSdWLe41pqOFjgaVI5GkmOEzHJQiu8\ 39559# Fh5u5NOD58dq18Viw8J357/l2bxt3LaqmK1dU5/o657p6pNZSJFWQY7X2oxUQ4lFNYatdX+khXybbni1b3Xm2HB4V25TKm6SXW24ZmmiYWeGVGadUGBe\ 39560# JGBIHFqGSlnJZVhVFVLQalFtIE/PXUlVKEi/QEbjxkWtMETi40GdOD+SJTx4JzuoHjjcMDdIFDK5GyufECS9IB2A69zHwsiT8L7s5rRy5a3Y7qPGsqKC\ 39561# mpuBeZVRdJLHzYnTm4nIh4aJcIJVXHvh5nrlmHrmv3Xl623gdGO/cmPFXE1MLE3TgErhgElGQEeEO0ciGEdJG0PlcUKHHEDJVz65JD3fPDhlFzDULSnC\ 39562# LSWDzOGm0dt81dBe1Lea8bCH7bDSvq6Nf6qF36fPyqXNjqJqhqE6QqB2d5muiJjJ5pWjmJFShJB90Y+xu4lmV4nW4oRSNnjJqHLNdXGqdmiHNWXd42Ti\ 39563# 1WNlOWLGX2GyVFy2ZlvJV1pSOlrXW1nmkFU2LlLoslCORk6tRE15NEvlp0rlXEo7Y0eWNUVdPEBkHTzgTznSNTnMJTfTRC2wHyPC79mUu8Sqs8Oqn790\ 39564# q7ZdqLWNl7WzrbOMnq+DtKtydaedw6WprZzij5dfzZPDvo6ZeI5qZ4XQwH7FnHt6WXk0N3dsPnTlzWy0mGxnLWztiWooF2pEZ2nkxWc4JWW4iWPewl/M\ 39565# R1/YnF1DQViYKlaOY1Xfr0ujgj8bMjGJJS53DieS2Liai6k4W6bc3Z9gwZmKgJDxrI7zqIyl1IttQYVajoCMhnyWYHpYU2rgrmeOkmWpLGDOk17YiVrF\ 39566# LVXm2lHdp0W4cjZMJjAgVhoxthLEAAAEA0lEQVQ4yy2RZVTaURjGr4LIGDAQAREFJEbZ3d3dCfbsmt3Oud7sdnZ317q7u7u7ex/2F/c7771fnt957jn3\ 39567# BZl2+HPbjtXRaJHa4Rs37t6zt3JjdeyRIyuWUFZWlgG9lnhrWry29sHT/UN3kw/FxFXur4zdrrycy8hIgxAzPF6fFt6kWFoUUBQUdO5AfVxybJO0zDLS\ 39568# 0qC37WON9p7+kCdisUikKhajD1Qn42FQsswq4GpnqxvOfSIOxWCgwSwKxrY/I7RI6+mtkrAStDJt9zpgFueD160LDg6eDxII7m3XldLTWymBbgimbU/p\ 39569# Wkz4e1H9vb29R734BR5FM45dRnp0QzqdbmhoBLL4+Wav4p5XXZWXancyJTm7uV0u8rZuoRuaGJmYGMFggMAdwl+LS25y43eVdOW7KSoqerT3EWyMTGAm\ 39570# MBhMVhZQKf1Jk5O5fHDVcXbqPD8EEtDdFk6ykhQ6gOJAqJn+O3m+aiVqIvRdlfOFyx4BrWZOSFlTU1MAZAEIzM09VffoUf4N+ze8OdGFfBKpXZCR6GQD\ 39571# lS9hCubzqC7hFS7oktTX6bO3S77e+1EykpDgZiMP/iPq8X9skeA50N1qNzBVMBMYNBdw/2yCkw1SHtkiEfz9A0tdEpm2tvYuFK8Qr4JS3wDzm5e4zlJI\ 39572# JFIeQEOhUKf/mFs4BFo6otHomZCxQPRohu7pIZKUPFRigwS5dz992LaG4MI8XsG87RuE9uAKVBdqNuyqdpaSAMrLjQ1o22KTLC3tRxwfB4wVcFUxC3Ua\ 39573# YbsdSDckghwcLodbs8bawt6uezQvj5slUF2/LkZTbVP6cWs+ieQMOlavhavspJknmVky7RwpWb4iSNinqaHmeuUKOxGfBVZLBKu0+4QkB4K1l2+wKma9\ 39574# t6bmZrWMwpycVPNDYHUHHK5y5uKtO70UKnVqbn1oaFmZvabGZjXzwpzBtvr3ACqQw5252GmVVihcmBAulgmFwhglSDhcODj47Vr9kgDHnUyz6ryV7c7j\ 39575# CYuLPXmZm5R0dLQ2ZSsoKNz5AjpSUlJwJ3dadV7/ziYXu5PJnrw2rJKWuk7YpeFhhXEfkMKIxxlrZ6Rd/5xd7IlIZZPJvGMSQf3o+PD4Lx/AaGQYG0f2\ 39576# sFgshKc7KxVBZBOfYpWwWupa6tATD3xAI8OgERfZgyIi3N3JLCKRxT6rs+sldmtEVNjNnOwHfqDWIN5YRd9sIB2BQBARHOg6vCO6IWLrlqiwmNnfPn6A\ 39577# wYhXgf7aN53DRnA4KA654ugO/bc7tmyN0NhX9hASDJqb5eBykSN9KFdXFArFSTwY3aBfe2JLFFZpQ+nDn34gulkFWpdBeV6fa2YmCsXUfVHbEK1/IiIK\ 39578# u3+DItXK7x94612QcMazZgAAAABJRU5ErkJggg=="/> \ 39579# <a href="https://www.facebook.com/shamoon">Shamoon Abbasi - FreshLUTs</a></center>"} 39580 39581#@gui : sep = value(0)_0+ 39582#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAAgCAQAAAAWXYa8AAAG3UlEQVRY\ 39583# he3WaYyV1RkH8N/cWa7AzCiCIiMuSBW3AtagYLQWitpQa7VVazRgMLbEiEuitqRRa6WgRUxFTRfjiMaoVGuNQm1IaajLB7WKbcS2Am5RtDDDNsyd5c7c+\ 39584# /TDe+879w5D0v2T//PhPec5zznvc/7Pck6NMr6f9rarxCqfGAqzHTak/N/HmLR3e/Kpq5ydbtI/ZVcZ/337dltZMaoybsapPy13O6BjDL4J2kvyd8ASd8\ 39585# IfNNDutHSD1Y4GJ6SSnej2WsVPRlbNDcK1VaMq44p27a1fjSNAxuegSxcjjEtnh5sw5KqTfZgeD5+3w5YhFfP7No7T3aRNrbqWlz2o4Bj3F8q7/sLbrvb\ 39586# D0qjenW7Q4nJ3GOVh39DHNLIWu9FUtyekNT9hbTNaLPSxY/Elvmo5rJar+nk1bVXGFWF/a92Helf5gVsNt97CVKWlRBxl8hocgTrjLPATUGMCmqyzFGMs\ 39587# cqrFcKHnNZVXdyefakdV07Y3c2X0uc/awcKWtHfx4HUvmaZliPTZar5VTrSBYyHrJK/oKYArbAKrdQ5tRaZqtDNtjipHRbdu3Z7z3NAbJKi3yCKaZGXRo\ 39588# 8c663xEeMCF0ACTNWnxXnnZmIryMQT2Yu5kl6g13pG+C45zCdjsdRxVGlE/sPRVI9nQtMOZXqjebLMW/uTSVDDb8ybb5hZLTTF+36RhMHPo1G6rjVv2bJ\ 39589# m3RafOPjk5Ob2gPMrJiYFFO3XyI99TDzUV270s351vyJfjabfXjNHuU42m2VPTWam7FwaYy2o0hneSWNvypDvNtMNmq+D4ROmjZMSwrMvLK8eWf/yYq+o\ 39590# fkFhYwnwOtQ3eTA7XpNlmpzjBbusM092gxlwTMHpfxk11tYOqZvpef2rC1B0HqwXnlaXqcWaF3jTZMv+Pe8avyyTNKit8xctwpAsadDvaWw7pru3ett8X\ 39591# nOYlWFxRKaEoXKdQNi7jEaPJ+pITZaz2Lr6ceXhsQto5RnrX06DWGWrQoCmpDMOgxQywzlIHOgCcrh4jzLfAVH9Ei6IjrJcd9mI37VrU6WUcTS4wwe7yd\ 39592# Vh1K45VVJwa2yJBPu6Px/I394mT4pPoL0k/iNnxUL458lFGV/wyfh5iTBSiEjNiZjwYuyokb4QQcyOiKw4PIS+3PZfLNeQUxfHxUUmvEPdHbcGzib/SmE\ 39593# vIa7XGIa41yvW21jHPWO3u8r5p5mjzM5B3s35jzXWxe7DLSpd6Ja2MH8hZ4yIstwd8mvIwzG2uGJSIrcZZaaWxbnJYZaKVmRsbxdgVmRCiMUaEvJgYfdE\ 39594# Vk0MIMTKEfHPkozOyIcQ5EfFiCLEwIu4u6ZVbW0S0VEnmRsTfIx/Hh4JCmbn9ohj50o63xP4hZS49QU6vRnNk0CnHNi5S5yl/hnZtO9u0oVhqJT6GGxId\ 39595# Q4t5XMaiKkmfPerNV4s+u+kloS81rkOrWiusd2Xyw0OZTJJP3WaZaKKJ6Y4Z9nM93kpFX7TMMsvMJr0nby3JRqRa7VY5P6bVqElSiYLlwnIbLNAIw5xl/\ 39596# IDxzbpFXTwTOyMi4uOYGUKsiYgLQngk1cs3F/KFQmFDvB27ImJbHJO6tYw7QmhL3FrGQalbfxwnRX9xbVGxvZjLNeTkRCZuKGl3xXlJCCwYYK5DK/1eNd\ 39597# 5NPnaoZxyMPRgFF5luuukDj8iMJvvb5GQb0xM+aooppri3wmVnl2Q7Kih/05NmmqmDLIiiu413jfcMszJ5ElbcHJclcbQwhGiOv0XEpSFui4gVyUn6y62\ 39598# 5kC90FrIxKnZEX5IsxSESom1fCXFXiKOLPfHbeDVy0RAKCgrJ/PB4PSIWhHBNVcwxr6apRON7JdN/peBbCV21aqfX1tQOaG+3TF3yWh/qftzrKqrEJq3O\ 39599# qniBzckcCLq8W7VdWucu06pLj81Ocbac32ODFa60zj0+cIZvW+JWkrdYQf29FjjHrLS6TXJVqfeCv5R6c+0Gea2V1hUX1841TheY7WFtHvBXk5yv15pBR\ 39600# 7lMcWTxifQu2BVfLzkiGw+l1X9zTA79zfl8vjOfzQuxICLeiMyghIj4Tlrnyuiocqt+sTii5NbGQmv0lfR6Y07y52sGXHKZR1GzxIcO8Knf2E5BT1IBjj\ 39601# NDk02e10Ohrvg1RasU80Y0OFeN3+kw0YkVZ13vfZxbinfo9ywON9VGb9GpsdlZ+j0nisgcaZbRtjrBjeSFSQOZNtIT+sXCyvDdZaGHyqGatnzaOgfN/Cv\ 39602# trop+Tt/AaGEIveYkZg1E3xLmJa/mfVb3/xQ595HziY2OSYUTspnrkrwcTaOb4cZkauCx2cGK/5VV1XjawMWSdV2vpUm/Z7DiQCnZ+n8w6zN8Bv4Bs+PS\ 39603# zRd3ZU8AAAAASUVORK5CYII="/> <a href="https://www.smallhd.com/community/movie-looks-download">SmallHD Free \ 39604# Movie Look Pack</a></center>"} 39605 39606#@gui : sep = value(0)_0+ 39607#@gui : note = note{"<center><a href="https://freshluts.com/users/52679">Youssef Hossam</a></center>"} 39608 39609#@gui : sep = value(0)_2+ 39610#@gui : sep = separator() 39611#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. 39612#@gui : Latest Update: <i>2019/10/11</i>.</small>") 39613fx_color_presets : 39614 category=${arg\ 1+$1,abigailgonzalez,alexjordan,berat,cinematic,cinematic_travel,creative,ericellerbrock,filtergrade,\ 39615 inavision,jtsemple,kylerholland,lutifyme,michaelezra,moviz,ohadperetz,oliviosarikas,on1,\ 39616 picturefx,pixelmator,pixlsus,purple11,rocketstock,shamoonabbasi,smallhd,youssefhossam,others} 39617 presets=${-_fx_cluts_$category} 39618 index={arg(1+$1,${2-27})} 39619 thumbsize,strength,brightness,contrast,gamma,hue,saturation,normalize=${28-35} 39620 39621 if $normalize==1" || "$normalize==3 # Pre-normalization 39622 repeat $! l[$>] split_opacity balance_gamma[0] , a c endl done 39623 fi 39624 if $index>=2 # Apply CLUT 39625 path_clut=${-path_cache} 39626 name=${arg\ 1+$index-2,$presets} 39627 clut $name,{0$_is_preview" && "!isfile(['{/${path_clut}clut_$name.cimgz}'])?17:48} 39628 repeat $!-1 if $strength<100 +map_clut[$>] . j[$>] .,0,0,0,0,{$strength%} rm. else map_clut[$>] . fi done 39629 rm. 39630 adjust_colors $brightness,$contrast,$gamma,$hue,$saturation,0,255 39631 if $normalize==2" || "$normalize==3 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done fi # Post-normalization 39632 39633 elif $index==1 # "None" 39634 adjust_colors $brightness,$contrast,$gamma,$hue,$saturation,0,255 39635 if $normalize==2" || "$normalize==3 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done fi # Post-normalization 39636 39637 else # Collage 39638 repeat $! l[$>] if max(w,h)>$thumbsize rr2d $thumbsize,$thumbsize,0,2 fi endl done 39639 N=$! +to "Original",1%,1%,7.5%,2,0.5 39640 Np={narg($presets)} repeat $Np 39641 clut_name=${arg\ 1+$>,$presets} 39642 clut $clut_name mv. $N 39643 repeat $N 39644 if $strength<100 [$>] +map_clut. [$N] j.. .,0,0,0,0,{$strength%} rm. else +map_clut[$>] [$N] fi 39645 adjust_colors. $brightness,$contrast,$gamma,$hue,$saturation,0,255 39646 if $normalize==2" || "$normalize==3 l. split_opacity n[0] 0,255 a c endl fi # Post-normalization 39647 strcapitalize $clut_name clut_name=${} 39648 to. $clut_name,0.01~,0.01~,7.5%,1 39649 done 39650 rm[$N] 39651 progress {$>*100/($Np-1)} 39652 done 39653 k[$N--1] frame 1,1,0,0,0,255 - 128 append_tiles {s=floor(sqrt($!));w>h?[s,0]:[0,s]} + 128 39654 fi 39655 39656fx_color_presets_preview : 39657 _is_preview=1 39658 index={arg(1+$1,${2-27})} 39659 if !$index gui_warning_preview "Preview disabled in 'Collage' mode" 39660 else gui_split_preview "fx_color_presets $*",${36-38} 39661 fi 39662 u "{$1}{$2}_"{2*($1==0)}\ 39663 "{$3}_"{2*($1==1)}\ 39664 "{$4}_"{2*($1==2)}\ 39665 "{$5}_"{2*($1==3)}\ 39666 "{$6}_"{2*($1==4)}\ 39667 "{$7}_"{2*($1==5)}\ 39668 "{$8}_"{2*($1==6)}\ 39669 "{$9}_"{2*($1==7)}\ 39670 "{$10}_"{2*($1==8)}\ 39671 "{$11}_"{2*($1==9)}\ 39672 "{$12}_"{2*($1==10)}\ 39673 "{$13}_"{2*($1==11)}\ 39674 "{$14}_"{2*($1==12)}\ 39675 "{$15}_"{2*($1==13)}\ 39676 "{$16}_"{2*($1==14)}\ 39677 "{$17}_"{2*($1==15)}\ 39678 "{$18}_"{2*($1==16)}\ 39679 "{$19}_"{2*($1==17)}\ 39680 "{$20}_"{2*($1==18)}\ 39681 "{$21}_"{2*($1==19)}\ 39682 "{$22}_"{2*($1==20)}\ 39683 "{$23}_"{2*($1==21)}\ 39684 "{$24}_"{2*($1==22)}\ 39685 "{$25}_"{2*($1==23)}\ 39686 "{$26}_"{2*($1==24)}\ 39687 "{$27}_"{2*($1==25)}\ 39688 "{$28}_"{1+!$index}\ 39689 "{$29}{$30}{$31}{$32}{$33}{$34}{$35}{$36}{$37,$38}"\ 39690 "{0}_"{2*($1!=24)}\ 39691 "{0}_"{2*($1==0)}\ 39692 "{0}_"{2*($1==1)}\ 39693 "{0}_"{2*($1==2)}\ 39694 "{0}_"{2*($1==3)}\ 39695 "{0}_"{2*($1==4)}\ 39696 "{0}_"{2*($1==5)}\ 39697 "{0}_"{2*($1==6)}\ 39698 "{0}_"{2*($1==7)}\ 39699 "{0}_"{2*($1==8)}\ 39700 "{0}_"{2*($1==9)}\ 39701 "{0}_"{2*($1==10)}\ 39702 "{0}_"{2*($1==11)}\ 39703 "{0}_"{2*($1==12)}\ 39704 "{0}_"{2*($1==13)}\ 39705 "{0}_"{2*($1==14)}\ 39706 "{0}_"{2*($1==15)}\ 39707 "{0}_"{2*($1==16)}\ 39708 "{0}_"{2*($1==17)}\ 39709 "{0}_"{2*($1==18)}\ 39710 "{0}_"{2*($1==19)}\ 39711 "{0}_"{2*($1==20)}\ 39712 "{0}_"{2*($1==21)}\ 39713 "{0}_"{2*($1==22)}\ 39714 "{0}_"{2*($1==23)}\ 39715 "{0}_"{2*($1==24)}\ 39716 "{0}" 39717 39718_fx_cluts_abigailgonzalez : 39719 u blade_runner,blue_house,blue_ice,caribe,cinema,cinema_2,cinema_3,\ 39720 cinema_4,cinema_5,cinema_noir,cinematic_for_flog,day_4nite,eterna_for_flog,filmic,\ 39721 fuji_hdr,goldengate,matrix,monochrome_1,monochrome_2,old_west,science_fiction 39722 39723_fx_cluts_alexjordan : 39724 u action_magenta_01,action_red_01,adventure_1453,agressive_highligjtes_recovery_5,bleech_bypass_green,\ 39725 bleech_bypass_yellow_01,blue_dark,blue_shadows_01,bright_green_01,brownish,colorful_0209,conflict_01,\ 39726 contrast_with_highlights_protection,contrasty_afternoon,contrasty_green,cross_process_cp_130,cross_process_cp_14,\ 39727 cross_process_cp_15,cross_process_cp_16,cross_process_cp_18,cross_process_cp_3,cross_process_cp_4,\ 39728 cross_process_cp_6,dark_green_02,dark_green_1,dark_place_01,dream_1,dream_85,faded_retro_01,faded_retro_02,\ 39729 film_0987,film_9879,film_high_contrast,flat_30,green_2025,green_action,green_afternoon,\ 39730 green_conflict,green_day_01,green_day_02,green_g_09,green_indoor,green_light,harsh_day,harsh_sunset,\ 39731 highlights_protection,indoor_blue,low_contrast_blue,low_key_01,magenta_day,magenta_day_01,magenta_dream,\ 39732 memories,moonlight_01,mostly_blue,muted_01,night_01,only_red,only_red_and_blue,operation_yellow,orange_dark_4,\ 39733 orange_dark_7,orange_dark_look,orange_underexposed,protect_highlights_01,red_afternoon_01,red_day_01,red_dream_01,\ 39734 retro_brown_01,retro_magenta_01,retro_yellow_01,saturated_blue,smart_contrast,subtle_blue,subtle_green,yellow_55b,\ 39735 yellow_film_01 39736 39737_fx_cluts_berat : 39738 u brownbm,cineblue,cinebm4k,goldentime,green_and_orange,monochrome,sevsuz,sunlightlove,western,westernlut2 39739 39740_fx_cluts_cinematic : 39741 u deep,dimension,enchanted,flavin,frosted,shine,ultra_water,wipe 39742 39743_fx_cluts_cinematic_travel : 39744 u blue_cold_fade,bright_teal_orange,bright_warm,clear_teal_fade,cold_clear_blue,cold_clear_blue_1,deep_blue,\ 39745 deep_dark_warm,deep_high_contrast,deep_teal_fade,deep_warm_fade,faded_green,greenish_contrasty,greenish_fade,\ 39746 greenish_fade_1,hard_teal_orange,neutral_teal_orange,neutral_warm_fade,smooth_clear,smooth_green_orange,\ 39747 smooth_teal_orange,teal_fade,very_warm_greenish,warm_dark_contrasty,warm_fade,warm_fade_1,warm_neutral,\ 39748 warm_sunset_red,warm_teal 39749 39750_fx_cluts_creative : 39751 u anime,bleachbypass_1,bleachbypass_2,bleachbypass_3,bleachbypass_4,candlelight,colornegative,crispwarm,crispwinter,\ 39752 dropblues,edgyember,fallcolors,foggynight,futuristicbleak_1,futuristicbleak_2,futuristicbleak_3,futuristicbleak_4,\ 39753 horrorblue,latesunset,moonlight,nightfromday,redblueyellow,smokey,softwarming,tealmagentagold,tealorange,\ 39754 tealorange_1,tealorange_2,tealorange_3,tensiongreen_1,tensiongreen_2,tensiongreen_3,tensiongreen_4 39755 39756_fx_cluts_ericellerbrock : 39757 u avalanche,black_star,helios,hydracore,hypnosis,killstreak,nemesis,night_blade_4,paladin,seringe_4,serpent,terra_4,\ 39758 victory,yellowstone 39759 39760_fx_cluts_filtergrade : 39761 u fgcinebasic,fgcinebright,fgcinecold,fgcinedrama,fgcinetealorange_1,fgcinetealorange_2,fgcinevibrant,fgcinewarm 39762 39763_fx_cluts_inavision : 39764 u 7drk_21,bc_darkum,brown_mobster,cold_ice,dark_man_x,film_gb-19,formula_b,gremerta,hitman,jwick_21,london_nights,\ 39765 louetta,nightlife,vfb_21,vintage_mob 39766 39767_fx_cluts_jtsemple : 39768 u brightgreen,crispromance,crushin,frostedbeachpicnic,justpeachy,lateafternoonwanderlust,lushgreensummer,\ 39769 magentacoffee,minimalistcaffeination,mysticpurplesunset,nostalgiahoney,springmorning,toastedgarden,\ 39770 winterlighthouse 39771 39772_fx_cluts_kylerholland : 39773 u kh1,kh2,kh3,kh4,kh5,kh6,kh7,kh8,kh9,kh10 39774 39775_fx_cluts_lutifyme : 39776 u hackmanite,herderite,heulandite,hiddenite,hilutite,howlite,hypersthene 39777 39778_fx_cluts_michaelezra : 39779 u deepskintones2,deepskintones3 39780 39781_fx_cluts_moviz : 39782 u moviz_1,moviz_2,moviz_3,moviz_4,moviz_5,moviz_6,moviz_7,moviz_8,moviz_9,moviz_10,\ 39783 moviz_11,moviz_12,moviz_13,moviz_14,moviz_15,moviz_16,moviz_17,moviz_18,moviz_19,moviz_20,\ 39784 moviz_21,moviz_22,moviz_23,moviz_24,moviz_25,moviz_26,moviz_27,moviz_28,moviz_29,moviz_30,\ 39785 moviz_31,moviz_32,moviz_33,moviz_34,moviz_35,moviz_36,moviz_37,moviz_38,moviz_39,moviz_40,\ 39786 moviz_41,moviz_42,moviz_43,moviz_44,moviz_45,moviz_46,moviz_47,moviz_48 39787 39788_fx_cluts_ohadperetz : 39789 u cold_simplicity_2,d_o_1,retro_summer_3,subtle_yellow,teal_moonlight,true_colors_8,vintage_warmth_1 39790 39791_fx_cluts_oliviosarikas : 39792 u analog_film_1,atomic_pink,beach_aqua_orange,beach_faded_analog,bw_but_yellow,city_dust,dark_orange_teal,\ 39793 day_to_night_kings_blue,duotone_blue_red,faded_pink-ish,flat_blue_moon,honey_light,infrared_-_dust_pink,neutral_pump,\ 39794 shade_kings_ink,sunset_aqua_orange,sunset_intense_violet_blue,sunset_violet_mood,violet_taste 39795 39796_fx_cluts_on1 : 39797 u 2-strip-process,aqua,aqua_and_orange_dark,berlin_sky,blues,\ 39798 bw_1,bw_2,bw_3,bw_4,bw_5,bw_6,bw_7,bw_8,bw_9,bw_10,chrome_01,\ 39799 cinematic-1,cinematic-2,cinematic-3,cinematic-4,cinematic-5,cinematic-6,cinematic-7,cinematic-8,\ 39800 cinematic-9,cinematic-10,\ 39801 classic_teal_and_orange,earth_tone_boost,fade_to_green,film_print_01,film_print_02,french_comedy,green_blues,\ 39802 green_yellow,\ 39803 landscape_1,landscape_2,landscape_3,landscape_4,landscape_5,landscape_6,landscape_7,landscape_8,landscape_9,\ 39804 landscape_10,\ 39805 lc_1,lc_2,lc_3,lc_4,lc_5,lc_6,lc_7,lc_8,lc_9,lc_10,\ 39806 moody_1,moody_2,moody_3,moody_4,moody_5,moody_6,moody_7,moody_8,moody_9,moody_10,\ 39807 nw-1,nw-2,nw-3,nw-4,nw-5,nw-6,nw-7,nw-8,nw-9,nw-10,oranges,\ 39808 portrait_1,portrait_2,portrait_3,portrait_4,portrait_5,portrait_6,portrait_7,portrait_8,portrait_9,portrait_10,\ 39809 purple_2,reds,reds_oranges_yellows,studio_skin_tone_shaper,vintage_chrome 39810 39811_fx_cluts_picturefx : 39812 u analogfx_anno_1870_color,analogfx_old_style_i,analogfx_old_style_ii,analogfx_old_style_iii,\ 39813 analogfx_sepia_color,analogfx_soft_sepia_i,analogfx_soft_sepia_ii,\ 39814 faux_infrared_bw_1,faux_infrared_color_p2,faux_infrared_color_p3,faux_infrared_color_r0a,\ 39815 faux_infrared_color_r0b,faux_infrared_color_yp1,\ 39816 goldfx_bright_spring_breeze,goldfx_bright_summer_heat,goldfx_hot_summer_heat,\ 39817 goldfx_perfect_sunset_01min,goldfx_perfect_sunset_05min,goldfx_perfect_sunset_10min,\ 39818 goldfx_spring_breeze,goldfx_summer_heat,technicalfx_backlight_filter,\ 39819 zilverfx_bw_solarization,zilverfx_infrared,zilverfx_vintage_bw 39820 39821_fx_cluts_pixelmator : 39822 u black_white_01,black_white_02,black_white_03,black_white_04,black_white_05,black_white_06,\ 39823 pmcinematic_01,pmcinematic_02,pmcinematic_03,pmcinematic_04,pmcinematic_05,pmcinematic_06,pmcinematic_07,\ 39824 classic_films_01,classic_films_02,classic_films_03,classic_films_04,classic_films_05,\ 39825 landscape_01,landscape_02,landscape_03,landscape_04,landscape_05,\ 39826 modern_films_01,modern_films_02,modern_films_03,modern_films_04,modern_films_05,modern_films_06,modern_films_07,\ 39827 pmnight_01,pmnight_02,pmnight_03,pmnight_04,pmnight_05,\ 39828 urban_01,urban_02,urban_03,urban_04,urban_05,\ 39829 vintage_01,vintage_02,vintage_03,vintage_04,vintage_05 39830 39831_fx_cluts_pixlsus : 39832 u amstragram,amstragram+,autumn,cinematic_lady_bird,cinematic_mexico,dark_blues_in_sunlight,delicatessen,expired_69,\ 39833 fadedlook,faded_print,hypressen,magenta_yellow,metropolis,modern_film,newspaper,night_spy,progressen,prussian_blue,\ 39834 seventies_magazine,street,sweet_bubblegum,sweet_gelatto,taiga,tarraco,unknown,uzbek_bukhara,\ 39835 uzbek_marriage,uzbek_samarcande,velvetia,warm_vintage,whiter_whites 39836 39837_fx_cluts_purple11 : 39838 u good_morning,going_for_a_walk,nah,once_upon_a_time,serenity,passing_by,smooth_sailing,undeniable,undeniable2,\ 39839 urban_cowboy,well_see,you_can_do_it 39840 39841_fx_cluts_rocketstock : 39842 u arabica_12,ava_614,azrael_93,bourbon_64,byers_11,chemical_168,clayton_33,clouseau_54,cobi_3,contrail_35,\ 39843 cubicle_99,django_25,domingo_145,\ 39844 faded_47,folger_50,fusion_88,hyla_68,korben_214,lenox_340,lucky_64,mckinnon_75,milo_5,neon_770,paladin_1875,\ 39845 pasadena_21,pitaya_15,reeve_38,remy_24,sprocket_231,teigen_28,trent_18,tweed_71,vireo_37,zed_32,zeke_39 39846 39847_fx_cluts_shamoonabbasi : 39848 u city_7,coffee_44,date_39,day_for_night,denoiser_simple_40,desert_gold_37,directions_23,drop_green_tint_14,\ 39849 elegance_38,golden_night_softner_43,golden_sony_37,green_15,happyness_133,hlg_1_1,industrial_33,morning_6,\ 39850 morroco_16,night_king_141,rest_33,shadow_king_39,spy_29,thriller_2,turkiest_42,vintage_163,wooden_gold_20 39851 39852_fx_cluts_smallhd : 39853 u apocalypse_this_very_moment,bboyz_2,bob_ford,life_giving_tree,moonrise,saving_private_damon,the_matrices 39854 39855_fx_cluts_others : 39856 u 60s,60s_faded,60s_faded_alt,alien_green,black_and_white,bleach_bypass,blue_mono,\ 39857 cinematic_01,cinematic_02,cinematic_03,\ 39858 color_rich,faded,faded_alt,faded_analog,faded_extreme,faded_vivid,expired_fade,expired_polaroid,extreme,fade,\ 39859 faux_infrared,golden,golden_bright,golden_fade,golden_mono,golden_vibrant,green_mono,hong_kong,instantc,\ 39860 k_tone_vintage_kodachrome,light_blown,lomo,mono_tinted,\ 39861 muted_fade,mute_shift,natural_vivid,nostalgic,orange_tone,pink_fade,purple,retro,rotate_muted,\ 39862 rotate_vibrant,rotated,rotated_crush,\ 39863 smooth_cromeish,smooth_fade,soft_fade,solarized_color,solarized_color_2,summer,summer_alt,sunny,sunny_alt,\ 39864 sunny_warm,\ 39865 sunny_rich,super_warm,super_warm_rich,sutro_fx,vibrant,vibrant_alien,vibrant_contrast,vibrant_cromeish,\ 39866 vintage,vintage_alt,vintage_brighter,warm,warm_highlight,warm_yellow 39867 39868_fx_cluts_youssefhossam : 39869 u cinematic_forest,city,darkness,hallowen_dark,sea 39870 39871#@gui Colorful Blobs : fx_colorful_blobs, fx_colorful_blobs_preview 39872#@gui : Colorspace = choice(1,"sRGB","Linear RGB","Lab") 39873#@gui : Background Color = color(200,200,200,0) 39874#@gui : Display Blob Controls = bool(1) 39875#@gui : sep = separator() 39876#@gui : Blob 1 = point(25,25,1,1,0,0,0,0,5) 39877#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39878#@gui : Blob 1 Color = color(255,0,0) 39879#@gui : Previous = value(-1,-1,-1,-1) 39880#@gui : sep = separator() 39881#@gui : Blob2 = point(75,25,1,1,0,0,0,0,5) 39882#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39883#@gui : Blob 2 Color = color(0,255,0) 39884#@gui : Previous = value(-1,-1,-1,-1) 39885#@gui : sep = separator() 39886#@gui : Blob 3 = point(50,75,1,1,0,0,0,0,5) 39887#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39888#@gui : Blob 3 Color = color(0,0,255) 39889#@gui : Previous = value(-1,-1,-1,-1) 39890#@gui : sep = separator() 39891#@gui : Blob 4 = point(5,90,-1,1,0,0,0,0,5) 39892#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39893#@gui : Blob 4 Color = color(255,255,0) 39894#@gui : Previous = value(-1,-1,-1,-1) 39895#@gui : sep = separator() 39896#@gui : Blob 5 = point(5,90,-1,1,0,0,0,0,5) 39897#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39898#@gui : Blob 5 Color = color(255,0,255) 39899#@gui : Previous = value(-1,-1,-1,-1) 39900#@gui : sep = separator() 39901#@gui : Blob 6 = point(5,90,-1,1,0,0,0,0,5) 39902#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39903#@gui : Blob 6 Color = color(0,255,255) 39904#@gui : Previous = value(-1,-1,-1,-1) 39905#@gui : sep = separator() 39906#@gui : Blob 7 = point(5,90,-1,1,0,0,0,0,5) 39907#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39908#@gui : Blob 7 Color = color(255,255,255) 39909#@gui : Previous = value(-1,-1,-1,-1) 39910#@gui : sep = separator() 39911#@gui : Blob 8 = point(5,90,-1,1,0,0,0,0,5) 39912#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39913#@gui : Blob 8 Color = color(0,0,0) 39914#@gui : Previous = value(-1,-1,-1,-1) 39915#@gui : sep = separator() 39916#@gui : Blob 9 = point(5,90,-1,1,0,0,0,0,5) 39917#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39918#@gui : Blob 9 Color = color(255,128,64) 39919#@gui : Previous = value(-1,-1,-1,-1) 39920#@gui : sep = separator() 39921#@gui : Blob 10 = point(5,90,-1,1,0,0,0,0,5) 39922#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39923#@gui : Blob 10 Color = color(255,64,128) 39924#@gui : Previous = value(-1,-1,-1,-1) 39925#@gui : sep = separator() 39926#@gui : Blob 11 = point(5,90,-1,1,0,0,0,0,5) 39927#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39928#@gui : Blob 11 Color = color(128,64,255) 39929#@gui : Previous = value(-1,-1,-1,-1) 39930#@gui : sep = separator() 39931#@gui : Blob 12 = point(5,90,-1,1,0,0,0,0,5) 39932#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 39933#@gui : Blob 12 Color = color(64,128,255) 39934#@gui : Previous = value(-1,-1,-1,-1) 39935#@gui : sep = separator() 39936#@gui : note = note("This filter can be used to create custom palettes with given color shades. 39937#@gui : It has been inspired by 39938#@gui : <a href="https://research.adobe.com/project/playful-palette-an-interactive-parametric-color-mixer-for-artists/"> 39939#@gui : Adobe's Playful Palette</a>.") 39940#@gui : sep = separator() 39941#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/08/26</i>.</small>") 39942fx_colorful_blobs : 39943 N=12 39944 colorspace,bgR,bgG,bgB,bgA,display_controls,\ 39945 x0,y0,rx0,ry0,R0,G0,B0,p_x0,p_y0,p_rx0,p_ry0,\ 39946 x1,y1,rx1,ry1,R1,G1,B1,p_x1,p_y1,p_rx1,p_ry1,\ 39947 x2,y2,rx2,ry2,R2,G2,B2,p_x2,p_y2,p_rx2,p_ry2,\ 39948 x3,y3,rx3,ry3,R3,G3,B3,p_x3,p_y3,p_rx3,p_ry3,\ 39949 x4,y4,rx4,ry4,R4,G4,B4,p_x4,p_y4,p_rx4,p_ry4,\ 39950 x5,y5,rx5,ry5,R5,G5,B5,p_x5,p_y5,p_rx5,p_ry5,\ 39951 x6,y6,rx6,ry6,R6,G6,B6,p_x6,p_y6,p_rx6,p_ry6,\ 39952 x7,y7,rx7,ry7,R7,G7,B7,p_x7,p_y7,p_rx7,p_ry7,\ 39953 x8,y8,rx8,ry8,R8,G8,B8,p_x8,p_y8,p_rx8,p_ry8,\ 39954 x9,y9,rx9,ry9,R9,G9,B9,p_x9,p_y9,p_rx9,p_ry9,\ 39955 x10,y10,rx10,ry10,R10,G10,B10,p_x10,p_y10,p_rx10,p_ry10,\ 39956 x11,y11,rx11,ry11,R11,G11,B11,p_x11,p_y11,p_rx11,p_ry11,\ 39957 =$* 39958 if !0$_is_preview display_controls=0 fi 39959 if $1==1 srgb2cs=srgb2rgb cs2srgb=rgb2srgb 39960 elif $1==2 srgb2cs=srgb2lab cs2srgb=lab2srgb 39961 fi 39962 39963 {0,s=min(w,h);[s,s]},1,4 k. 100%,100%,1,1,1e-8 39964 39965 repeat $N 39966 # If center point has been moved -> Update radius point. 39967 rx$>,ry$>={"P = ["${x$>},${y$>}"]; 39968 R = ["${rx$>},${ry$>}"]; 39969 oP = ["${p_x$>},${p_y$>}"]; 39970 oP==[-1,-1]?P + [10,0]:P!=oP?R + P - oP:R"} 39971 39972 if !isnan(${x$>}) 39973 x,y,rx,ry,R,G,B={"const w1 = (w - 1)%; const h1 = (h -1)%; "\ 39974 round([${x$>}*w1,${y$>}*h1,${rx$>}*w1,${ry$>}*h1,${R$>},${G$>},${B$>}])} 39975 r={max(1,round(norm($x-$rx,$y-$ry)))} 39976 if $1 ($R^$G^$B) $srgb2cs. R,G,B={^} rm. fi 39977 f. "* 39978 pexp(x) = x<2?(res = 1; px = x^2; res+=-1.17282*px; px*=x; res+=0.683221*px; px*=x; res+=-0.110353*px):0; 39979 const r = 1.2*"($r)"; 39980 dist = norm(x-"$x",y-"$y")/r; 39981 w = pexp(dist); 39982 j(#0,0,0,0) += w*"$R"; 39983 j(#0,0,0,0,1) += w*"$G"; 39984 j(#0,0,0,0,2) += w*"$B"; 39985 i + w; 39986 " 39987 fi 39988 done 39989 sh[0] 0,2 /. [1] if $1 $cs2srgb. fi 39990 f[0] "*begin(bg = [ "$bgR,$bgG,$bgB,$bgA" ]); i(#1)<0.5?bg:[R,G,B,255]" k[0] 39991 39992 repeat $N 39993 if !isnan(${x$>})" && "$display_controls 39994 x,y,rx,ry,R,G,B={"const w1 = (w - 1)%; const h1 = (h -1)%; "\ 39995 round([${x$>}*w1,${y$>}*h1,${rx$>}*w1,${ry$>}*h1,${R$>},${G$>},${B$>}])} 39996 circle $x,$y,3,0.85,0xFFFFFFFF,{v=avg(crop($x-3,$y-3,7,7))>128?0:255;[v,v,v,255]} 39997 rectangle {"const x = "$rx"; const y = "$ry"; [x-2,y-2,x+2,y+2]"},0.85,0xFFFFFFFF,\ 39998 {v=avg(crop($rx-3,$ry-3,7,7))>128?0:255;[v,v,v,255]} 39999 line $x,$y,$rx,$ry,0.5,0xF0F0F0F0,255 line $x,$y,$rx,$ry,0.5,0x0F0F0F0F,0,0,0,255 40000 fi 40001 done 40002 40003 if 0$_is_preview 40004 u \{$colorspace\}\{$bgR,$bgG,$bgB,$bgA\}\{$display_controls\}\ 40005 \{$x0,$y0\}\{$rx0,$ry0\}\{$R0,$G0,$B0\}\{$x0,$y0,$rx0,$ry0\}\ 40006 \{$x1,$y1\}\{$rx1,$ry1\}\{$R1,$G1,$B1\}\{$x1,$y1,$rx1,$ry1\}\ 40007 \{$x2,$y2\}\{$rx2,$ry2\}\{$R2,$G2,$B2\}\{$x2,$y2,$rx2,$ry2\}\ 40008 \{$x3,$y3\}\{$rx3,$ry3\}\{$R3,$G3,$B3\}\{$x3,$y3,$rx3,$ry3\}\ 40009 \{$x4,$y4\}\{$rx4,$ry4\}\{$R4,$G4,$B4\}\{$x4,$y4,$rx4,$ry4\}\ 40010 \{$x5,$y5\}\{$rx5,$ry5\}\{$R5,$G5,$B5\}\{$x5,$y5,$rx5,$ry5\}\ 40011 \{$x6,$y6\}\{$rx6,$ry6\}\{$R6,$G6,$B6\}\{$x6,$y6,$rx6,$ry6\}\ 40012 \{$x7,$y7\}\{$rx7,$ry7\}\{$R7,$G7,$B7\}\{$x7,$y7,$rx7,$ry7\}\ 40013 \{$x8,$y8\}\{$rx8,$ry8\}\{$R8,$G8,$B8\}\{$x8,$y8,$rx8,$ry8\}\ 40014 \{$x9,$y9\}\{$rx9,$ry9\}\{$R9,$G9,$B9\}\{$x9,$y9,$rx9,$ry9\}\ 40015 \{$x10,$y10\}\{$rx10,$ry10\}\{$R10,$G10,$B10\}\{$x10,$y10,$rx10,$ry10\}\ 40016 \{$x11,$y11\}\{$rx11,$ry11\}\{$R11,$G11,$B11\}\{$x11,$y11,$rx11,$ry11\} 40017 fi 40018 40019fx_colorful_blobs_preview : 40020 _is_preview=1 40021 rm {s=min($_preview_width,$_preview_height)/2;[s,s]},1,1 40022 fx_colorful_blobs $* 40023 40024#@gui Colormap : fx_colormap,fx_colormap_preview 40025#@gui : Colormap = choice{2,"Adaptive","Custom","Standard (256)","HSV (256)","Lines (256)","Hot (256)", 40026#@gui : "Cool (256)","Jet (256)","Flag (256)","Cube (256)"} 40027#@gui : Dithering = float(1,0,1) 40028#@gui : sep = separator() 40029#@gui : Number of Tones = int(32,2,256)_0 40030#@gui : Number of Colors = int(8,2,8)_0 40031#@gui : 1st Color = color(0,0,0)_0 40032#@gui : 2nd Color = color(255,255,255)_0 40033#@gui : 3rd Color = color(255,0,0)_0 40034#@gui : 4th Color = color(0,255,0)_0 40035#@gui : 5th Color = color(0,0,255)_0 40036#@gui : 6th Color = color(255,255,0)_0 40037#@gui : 7th Color = color(255,0,255)_0 40038#@gui : 8th Color = color(0,255,255)_0+ 40039#@gui : sep = separator() 40040#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40041#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40042#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40043#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40044#@gui : sep = separator() 40045#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/27/12</i>.</small>") 40046fx_colormap : 40047 repeat $! l[$>] split_opacity to_rgb[0] 40048 if $1>=2 # Pre-defined colormap. 40049 index[0] {$1-2},$2,1 40050 elif $1==1 # Custom colormap. 40051 (${5-28}) z. 0,{3*$4-1} 40052 r. 3,{w/3},1,1,-1 permute. yzcx r. $3,1,1,3,3 40053 index[0] .,$2,1 rm. 40054 else # Adaptive colormap. 40055 autoindex[0] $3,$2,{if($3<=32,1,0)} 40056 fi 40057 a c 40058 endl done 40059 40060fx_colormap_preview : 40061 gui_split_preview "fx_colormap $*",${-3--1} 40062 is_ad,is_cu={2*[$1==0||$1==1,$1==1]} 40063 u "{$1}{$2}"\ 40064 "{$3}_"$is_ad\ 40065 "{$4}_"$is_cu\ 40066 "{${5-7}}_"$is_cu\ 40067 "{${8-10}}_"$is_cu\ 40068 "{${11-13}}_"$is_cu\ 40069 "{${14-16}}_"$is_cu\ 40070 "{${17-19}}_"$is_cu\ 40071 "{${20-22}}_"$is_cu\ 40072 "{${23-25}}_"$is_cu\ 40073 "{${26-28}}_"$is_cu\ 40074 "{$29}{$30,$31}" 40075 40076#@gui Color Mask [Interactive] : fx_mask_color, gui_no_preview 40077#@gui : Color Metric = _choice(13,"RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","Linear RGB [All]", 40078#@gui : "Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 40079#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [red chrominance]", 40080#@gui : "YCbCr [green chrominance]","Lab [all]","Lab [lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 40081#@gui : "Lab [b-Chrominance]","Lch [all]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]", 40082#@gui : "HSV [all]","HSV [hue]","HSV [saturation]","HSV [value]","HSI [all]","HSI [intensity]","HSL [all]", 40083#@gui : "HSL [lightness]","CMYK [cyan]","CMYK [magenta]","CMYK [yellow]","CMYK [key]","YIQ [luma]","YIQ [chromas]") 40084#@gui : Spatial Tolerance = _float(10,0,100) 40085#@gui : Color Tolerance = _float(5,0,100) 40086#@gui : sep = separator() 40087#@gui : Output Mode = _choice(0,"Masked image","Color mask") 40088#@gui : sep = separator() 40089#@gui : note = note{"<small><b>Note:</b> This filter is CPU consuming, so use it at least with 4+ cores 40090#@gui : (or reduce the size of the interactive window to speed up computation).</small>"} 40091#@gui : note = note{"<small><b>Interactions:</b>\n 40092#@gui : Use the following actions in the interactive window to build your color mask :\n\n 40093#@gui : - <b>Left mouse button</b> make the color pointed by the mouse wanted for the mask.\n 40094#@gui : - <b>Right mouse button</b> make the color pointed by the mouse unwanted for the mask.\n 40095#@gui : - <b>Middle mouse button</b> or key <b>R</b> resets color mask.\n 40096#@gui : - Key <b>SPACE</b> or <b>TAB</b> toggles view modes (half/full-masked RGB or color mask).\n 40097#@gui : - Keys <b>CTRL+D</b> increase window size.\n 40098#@gui : - Keys <b>CTRL+C</b> decrease window size.\n 40099#@gui : - Keys <b>CTRL+R</b> resets window size.\n 40100#@gui : - Keys <b>ESC</b>, <b>Q</b> or <b>ENTER</b> exit the interactive window. 40101#@gui : </small>"} 40102#@gui : sep = separator() 40103#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>01/20/2017</i>.</small>") 40104fx_mask_color : 40105 cs=rgb,rgb_r,rgb_g,rgb_b,lrgb,lrgb_r,lrgb_g,lrgb_b,ycbcr_y,ycbcr_cbcr,ycbcr_cb,ycbcr_cr,ycbcr_cg,\ 40106 lab,lab_l,lab_ab,lab_a,lab_b,lch,lch_c,lch_h,hsv,hsv_h,hsv_s,hsv_v,hsi,hsi_i,hsl,hsl_l,\ 40107 cmyk_c,cmyk_m,cmyk_y,cmyk_k,yiq_y,yiq_iq 40108 repeat $! l[$<] to_rgb nm={n} nm ${-gui_layer_name} 40109 +x_mask_color ${arg\ 1+$1,$cs},$2,$3 40110 if $4==1 channels. 100% fi 40111 nm $nm rv 40112 endl done 40113 40114#@gui Curves : fx_curves_interactive, fx_curves_interactive_preview 40115#@gui : Colorspace = choice{"RGB","CMY","CMYK","HSI","HSL","HSV","Lab","Lch","YCbCr"} 40116#@gui : Output Preset as a HaldCLUT Layer = _choice("Disable","Lowres CLUT","Highres CLUT") 40117#@gui : Apply Transformation From = _choice("New Curves [Interactive]","Curves Previously Defined") 40118#@gui : Colorspace = value(0) 40119#@gui : Keypoints = value(0,0,100,100,-1,0,0,100,100,-1,0,0,100,100,-1,0,0,100,100,-1,0,0,100,100) 40120#@gui : sep = separator() 40121#@gui : note = note{"<small><b>Description:</b>\n 40122#@gui : This filter allows to apply color curves on your images, in many different colorspaces. 40123#@gui : Click on the <i>Apply</i> or <i>OK</i> buttons below to open the G'MIC interactive windows and 40124#@gui : start building your color curves. 40125#@gui : When you're done, exit the main image window: your modified result will be transferred back to the 40126#@gui : host software.\n\n 40127#@gui : Once you've set curves, you can save them by pressing the <b>Add to faves</b> button below the filter tree. 40128#@gui : To clear control points for your curves, click on the <i>Reset</i> button above. 40129#@gui : </small>"} 40130#@gui : sep = separator() 40131#@gui : note = note{"<small><b>Interactions:</b>\n 40132#@gui : Use the following actions in the interactive windows to manage your colorization :\n\n 40133#@gui : - <b>Left mouse button</b> on a curve creates a new color control point (or move an existing one).\n 40134#@gui : - <b>Right mouse button</b> on a control point deletes it.\n 40135#@gui : - <b>Left mouse button</b> on the main image window shows the initial image until button is released.\n 40136#@gui : - <b>Right mouse button</b> on the main image window adds a keypoint to all curves from picked color.\n 40137#@gui : - Key <b>R</b> on a curve resets it.\n 40138#@gui : - Keys <b>CTRL+D</b> increase window size.\n 40139#@gui : - Keys <b>CTRL+C</b> decrease window size.\n 40140#@gui : - Keys <b>CTRL+R</b> resets window size.\n 40141#@gui : - Keys <b>ESC</b>, <b>Q</b> or <b>ENTER</b> close the current window. 40142#@gui : </small>"} 40143#@gui : sep = separator() 40144#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>09/28/2014</i>.</small>") 40145fx_curves_interactive : 40146 nm "Color curves" 40147 repeat 4 __xcc_C$>=0,0,100,100 done 40148 if $4==$1 l[] ($5) s -,-1 repeat $! __xcc_C$>={$>,^} done rm endl fi 40149 if $3 # Apply transformation from previously defined curves 40150 _xcc_colorbase=${arg\ {$4+1},rgb,cmy,cmyk,hsi,hsl,hsv,lab,lch,ycbcr} x_color_curves last 40151 else # Run interactive curve builder 40152 x_color_curves ${arg\ {$1+1},rgb,cmy,cmyk,hsi,hsl,hsv,lab,lch,ycbcr} 40153 u "{$1}{$2}{$3}{$1}{"$__xcc_C0,-1,$__xcc_C1,-1,$__xcc_C2,-1,$__xcc_C3,-1,$__xcc_C4"}" 40154 fi 40155 if $2 # Add HaldCLUT layer 40156 (0,255) (0;255) (0/255) r[-3--1] 2,2,2 a[-3--1] c 40157 if $2==2 r. 256,256,256,3,3 r. 4096,4096,1,3,-1 # High-res HaldCLUT 40158 else r. 64,64,64,3,3 r. 512,512,1,3,-1 # Low-res HaldCLUT 40159 fi 40160 x_color_curves. last 40161 fi 40162 40163fx_curves_interactive_preview : 40164 fx_curves_interactive $1,0,1,$4,"$5" 40165 40166#@gui Customize CLUT : fx_customize_clut,fx_customize_clut_preview(1)+ 40167#@gui : Keypoint Influence (%) = float(100,0,100) 40168#@gui : Lock Uniform Sampling = choice{0,"None","8 Keypoints (RGB Corners)","27 Keypoints","64 Keypoints", 40169#@gui : "125 Keypoints","216 Keypoints","343 Keypoints"}, 40170#@gui : Spatial Regularization = int(10,0,30) 40171#@gui : sep = separator() 40172#@gui : note = note("<small><b>Global correction:</b></small>") 40173#@gui : Brightness (%) = float(0,-100,100) 40174#@gui : Contrast (%) = float(0,-100,100) 40175#@gui : Gamma (%) = float(0,-100,100) 40176#@gui : Hue (%) = float(0,-100,100) 40177#@gui : Saturation (%) = float(0,-100,100) 40178#@gui : Post-Normalize = bool(0) 40179#@gui : sep = separator() 40180#@gui : Output Corresponding CLUT = _choice("Disable","512x512 Layer","4096x4096 Layer") 40181#@gui : Preview Type = choice{8,"Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40182#@gui : "Backward Vertical","Duplicate Horizontal","Duplicate Vertical","HaldCLUT","3D CLUT (Fast)","3D CLUT (Precise)"} 40183#@gui : CLUT Opacity = float(0.5,0,1) 40184#@gui : sep = separator() 40185#@gui : note = note("<small><b>Color correspondences:</b></small>") 40186#@gui : Action #1 = choice(1,"Ignore","Lock Source","Replace Source by Target") 40187#@gui : Source Color #1 = color(0,0,0), Target Color #1 = color(0,0,0) 40188#@gui : sep = separator() 40189#@gui : Action #2 = choice(1,"Ignore","Lock Source","Replace Source by Target") 40190#@gui : Source Color #2 = color(255,255,255), Target Color #2 = color(255,196,128) 40191#@gui : sep = separator() 40192#@gui : Action #3 = choice("Ignore","Lock Source","Replace Source by Target") 40193#@gui : Source Color #3 = color(0,0,0), Target Color #3 = color(0,0,0) 40194#@gui : sep = separator() 40195#@gui : Action #4 = choice("Ignore","Lock Source","Replace Source by Target") 40196#@gui : Source Color #4 = color(0,0,0), Target Color #4 = color(0,0,0) 40197#@gui : sep = separator() 40198#@gui : Action #5 = choice("Ignore","Lock Source","Replace Source by Target") 40199#@gui : Source Color #5 = color(0,0,0), Target Color #5 = color(0,0,0) 40200#@gui : sep = separator() 40201#@gui : Action #6 = choice("Ignore","Lock Source","Replace Source by Target") 40202#@gui : Source Color #6 = color(0,0,0), Target Color #6 = color(0,0,0) 40203#@gui : sep = separator() 40204#@gui : Action #7 = choice("Ignore","Lock Source","Replace Source by Target") 40205#@gui : Source Color #7 = color(0,0,0), Target Color #7 = color(0,0,0) 40206#@gui : sep = separator() 40207#@gui : Action #8 = choice("Ignore","Lock Source","Replace Source by Target") 40208#@gui : Source Color #8 = color(0,0,0), Target Color #8 = color(0,0,0) 40209#@gui : sep = separator() 40210#@gui : Action #9 = choice("Ignore","Lock Source","Replace Source by Target") 40211#@gui : Source Color #9 = color(0,0,0), Target Color #9 = color(0,0,0) 40212#@gui : sep = separator() 40213#@gui : Action #10 = choice("Ignore","Lock Source","Replace Source by Target") 40214#@gui : Source Color #10 = color(0,0,0), Target Color #10 = color(0,0,0) 40215#@gui : sep = separator() 40216#@gui : Action #11 = choice("Ignore","Lock Source","Replace Source by Target") 40217#@gui : Source Color #11 = color(0,0,0), Target Color #11 = color(0,0,0) 40218#@gui : sep = separator() 40219#@gui : Action #12 = choice("Ignore","Lock Source","Replace Source by Target") 40220#@gui : Source Color #12 = color(0,0,0), Target Color #12 = color(0,0,0) 40221#@gui : sep = separator() 40222#@gui : Action #13 = choice("Ignore","Lock Source","Replace Source by Target") 40223#@gui : Source Color #13 = color(0,0,0), Target Color #13 = color(0,0,0) 40224#@gui : sep = separator() 40225#@gui : Action #14 = choice("Ignore","Lock Source","Replace Source by Target") 40226#@gui : Source Color #14 = color(0,0,0), Target Color #14 = color(0,0,0) 40227#@gui : sep = separator() 40228#@gui : Action #15 = choice("Ignore","Lock Source","Replace Source by Target") 40229#@gui : Source Color #15 = color(0,0,0), Target Color #15 = color(0,0,0) 40230#@gui : sep = separator() 40231#@gui : Action #16 = choice("Ignore","Lock Source","Replace Source by Target") 40232#@gui : Source Color #16 = color(0,0,0), Target Color #16 = color(0,0,0) 40233#@gui : sep = separator() 40234#@gui : Action #17 = choice("Ignore","Lock Source","Replace Source by Target") 40235#@gui : Source Color #17 = color(0,0,0), Target Color #17 = color(0,0,0) 40236#@gui : sep = separator() 40237#@gui : Action #18 = choice("Ignore","Lock Source","Replace Source by Target") 40238#@gui : Source Color #18 = color(0,0,0), Target Color #18 = color(0,0,0) 40239#@gui : sep = separator() 40240#@gui : Action #19 = choice("Ignore","Lock Source","Replace Source by Target") 40241#@gui : Source Color #19 = color(0,0,0), Target Color #19 = color(0,0,0) 40242#@gui : sep = separator() 40243#@gui : Action #20 = choice("Ignore","Lock Source","Replace Source by Target") 40244#@gui : Source Color #20 = color(0,0,0), Target Color #20 = color(0,0,0) 40245#@gui : sep = separator() 40246#@gui : Action #21 = choice("Ignore","Lock Source","Replace Source by Target") 40247#@gui : Source Color #21 = color(0,0,0), Target Color #21 = color(0,0,0) 40248#@gui : sep = separator() 40249#@gui : Action #22 = choice("Ignore","Lock Source","Replace Source by Target") 40250#@gui : Source Color #22 = color(0,0,0), Target Color #22 = color(0,0,0) 40251#@gui : sep = separator() 40252#@gui : Action #23 = choice("Ignore","Lock Source","Replace Source by Target") 40253#@gui : Source Color #23 = color(0,0,0), Target Color #23 = color(0,0,0) 40254#@gui : sep = separator() 40255#@gui : Action #24 = choice("Ignore","Lock Source","Replace Source by Target") 40256#@gui : Source Color #24 = color(0,0,0), Target Color #24 = color(0,0,0) 40257#@gui : sep = separator() 40258#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/14/06</i>.</small>") 40259fx_customize_clut : 40260 40261 # Build CLUT. 40262 if !narg($_N) N=64 else N=$_N fi N1={$N-1} 40263 $N,$N,$N,4 40264 40265 if $2 # Lock uniform sampling 40266 uniform_distribution {(1+$2)^3},3 40267 repeat w point.. {round($N1*I[$>])},1,{255*I[$>]},1 done rm. 40268 fi 40269 40270 $=arg # Add user-defined color correspondences 40271 repeat 24 40272 mode=${arg{13+7*$<}} 40273 if $mode 40274 sr=${arg{14+7*$<}} sg=${arg{15+7*$<}} sb=${arg{16+7*$<}} 40275 tr=${arg{17+7*$<}} tg=${arg{18+7*$<}} tb=${arg{19+7*$<}} 40276 xyz={round(($N1/255)*[$sr,$sg,$sb])} 40277 point. $xyz,1,{$mode==2?[$tr,$tg,$tb]:[$sr,$sg,$sb]},1 40278 fi 40279 done 40280 40281 s c,-3 40282 if $1<100 # Need to compute a weighting map. 40283 +distance. 1 40284 if $1 ^. {1/(0.05+4*$1%)} else f. 0 fi 40285 n. 0,1 nm. influence mv. -3 40286 fi 40287 ==. 0 inpaint_pde.. .,100%,1,20 rm. c. 0,255 40288 40289 if $influence 40290 100%,100%,100%,3,[x,y,z] n. 0,255 40291 j. ..,0,0,0,0,1,... 40292 rm[-3,-2] 40293 fi 40294 40295 # Apply CLUT on input layers + global color corrections. 40296 if !$3 map_clut[^-1] . # w/o spatial regularization 40297 else repeat $!-1 # w/ spatial regularization 40298 +luminance[$>] +map_clut[$>] .. -. [$>] 40299 repeat $3 guided. ..,2,50 done +[$>,-1] rm. 40300 done fi 40301 adjust_colors ${4-8},0,255 40302 if $9 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done fi 40303 if $10 40304 if $10==2 r. 256,256,256,3,5 c. 0,255 fi 40305 siz={w^1.5} r. $siz,$siz,1,3,-1 40306 mv. 0 40307 else rm. 40308 fi 40309 40310fx_customize_clut_preview : 40311 if $11<7 gui_split_preview "fx_customize_clut ${1-9},0,0,${12--1}",$11 40312 elif $11==7 # HaldCLUT preview 40313 rm fx_customize_clut ${1-9},1,0,${12--1} 40314 elif $11>=8 # 3D CLUT preview 40315 _N={$11>=9?64:32} 40316 k[0] to_rgb w={w} h={h} 40317 +fx_customize_clut ${1-9},1,0,${12--1} mv. 1 40318 r. $_N,$_N,$_N,3,-1 pointcloud3d. o3d. $12 40319 l[] 40320 if $2 # Lock uniform sampling 40321 uniform_distribution {(1+$2)^3},3 40322 repeat w circle3d {0,round($_N*I[$>])},0.75 col3d. {0,255*I[$>]} done rm[0] 40323 fi 40324 $=arg # Add user-defined color correspondences 40325 repeat 24 40326 mode=${arg{13+7*$<}} 40327 if $mode 40328 sr=${arg{14+7*$<}} sg=${arg{15+7*$<}} sb=${arg{16+7*$<}} 40329 tr=${arg{17+7*$<}} tg=${arg{18+7*$<}} tb=${arg{19+7*$<}} 40330 xy={round(($_N/255)*[$sr,$sg])} 40331 z={round(($_N/255)*$sb)-0.1} 40332 circle3d $xy,$z,0.75 col3d. {$mode==2?[$tr,$tg,$tb]:[$sr,$sg,$sb]} 40333 fi 40334 done 40335 colorcube3d *3d. {$_N/255} o3d. 0.5 col3d. 0 p3d. 1 40336 endl 40337 +3d[2--1] 40338 pose3d. 5.10656,2.04904,2.723,-316.115,-0.0815767,4.97762,-3.59262,-41.7094,\ 40339 -3.40685,2.95212,4.16756,-118.811,0,0,203,1 40340 40341 # Try to find the best layout for displaying preview. 40342 if $w>$h # Landscape mode 40343 r2dx[0,1] {0,round(w/2)} 40344 to[0] "Before",2,0,13,1,0.75 40345 to[1] "After",2,0,13,1,0.75 40346 a[0,1] y r[0] 100%,$h,1,3,0 40347 else # Portrait mode. 40348 r2dy[0,1] {0,round(h/2)} 40349 to[0] "Before",2,0,13,1,0.75 40350 to[1] "After",2,0,13,1,0.75 40351 a[0,1] x r[0] $w,100%,1,3,0 40352 fi 40353 40354 snapshot3d. {0,1.1*min(w,h)},1.2,64,64,64 40355 autocrop. -. 64 r. {0,max(w,$w-w)},{0,max(h,$h-h)},1,3,0,0,0.5,0.5 +. 64 40356 to. "RGB CLUT",2,0,13,1,0.75 40357 a {`$w>$h?_'x':_'y'`} 40358 fi 40359 40360#@gui Decompose Channels : fx_decompose_channels, fx_decompose_channels_preview 40361#@gui : Color Basis = choice(7,"RGB","HSV","HSL","HSI","YUV","YCbCr","XYZ","Lab","Lch","CMY","CMYK","YIQ") 40362#@gui : Action = choice("Decompose","Recompose") 40363#@gui : Output Multiple Layers = _bool(0) 40364#@gui : Include Opacity Layer = bool(1) 40365#@gui : sep = separator() 40366#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/19/07</i>.</small>") 40367fx_decompose_channels : 40368 if !$2 # Decompose 40369 if $4 to_rgba else to_rgb fi 40370 repeat $! l[$<] nm={0,n} 40371 split_opacity 40372 _s3=A _s4=A 40373 _fx_decompose_channels$1[0] 40374 s[0] c 40375 if !$3 a x nm $nm 40376 else nm=${-gui_layer_name} repeat $! gui_set_layer_name[$>] {``$nm}" ["${_s$>}"]" done 40377 fi 40378 endl done 40379 else # Recompose 40380 channels 0 nbc={3+($1==10)} nb={$nbc+$4} 40381 if $3 repeat int($!/$nb) l[0-{$nb-1}] 40382 a[0-{$nbc-1}] c _fx_recompose_channels$1[0] a c 40383 endl mv. 0 done 40384 else repeat $! l[$>] 40385 s x,$nb a[0-{$nbc-1}] c _fx_recompose_channels$1[0] a c 40386 endl mv. 0 done fi 40387 fi 40388 40389fx_decompose_channels_preview : 40390 repeat $! l[$<] 40391 _s3=A _s4=A 40392 fx_decompose_channels $1,$2,1,$4 40393 if !$2 40394 fs={round(min(w,h)*15%)} 40395 repeat $! to[$>] ${_s$>},5,3,$fs,{max(2,round($fs/15))} done 40396 to_rgba 40397 fi 40398 endl done 40399 append_tiles , 40400 40401_fx_decompose_channels0 : _s0=R _s1=G _s2=B 40402_fx_decompose_channels1 : rgb2hsv8 _s0=H _s1=S _s2=V 40403_fx_decompose_channels2 : rgb2hsl8 _s0=H _s1=S _s2=L 40404_fx_decompose_channels3 : rgb2hsi8 _s0=H _s1=S _s2=I 40405_fx_decompose_channels4 : rgb2yuv8 _s0=Y _s1=U _s2=V 40406_fx_decompose_channels5 : rgb2ycbcr _s0=Y _s1=Cb _s2=Cr 40407_fx_decompose_channels6 : rgb2xyz8 _s0=X _s1=Y _s2=Z 40408_fx_decompose_channels7 : rgb2lab8 _s0=L _s1=a _s2=b 40409_fx_decompose_channels8 : rgb2lch8 _s0=L _s1=c _s2=h 40410_fx_decompose_channels9 : rgb2cmy _s0=C _s1=M _s2=Y 40411_fx_decompose_channels10 : rgb2cmyk _s0=C _s1=M _s2=Y _s3=K 40412_fx_decompose_channels11 : rgb2yiq8 _s0=Y _s1=I _s2=Q 40413 40414_fx_recompose_channels0 : 40415_fx_recompose_channels1 : hsv82rgb 40416_fx_recompose_channels2 : hsl82rgb 40417_fx_recompose_channels3 : hsi82rgb 40418_fx_recompose_channels4 : yuv82rgb 40419_fx_recompose_channels5 : ycbcr2rgb 40420_fx_recompose_channels6 : xyz82rgb 40421_fx_recompose_channels7 : lab82rgb 40422_fx_recompose_channels8 : lch82rgb 40423_fx_recompose_channels9 : cmy2rgb 40424_fx_recompose_channels10 : cmyk2rgb 40425_fx_recompose_channels11 : yiq82rgb 40426 40427#@gui Detect Skin : fx_detect_skin, fx_detect_skin_preview(1) 40428#@gui : Skin Estimation = choice(1,"Manual","Automatic") 40429#@gui : sep = separator() 40430#@gui : Tolerance = float(0.5,0,1) 40431#@gui : Smoothness = float(0.5,0,5) 40432#@gui : Threshold = float(1,0,10) 40433#@gui : Pre-Normalize Image = bool(1) 40434#@gui : sep = separator() 40435#@gui : note = note("<small><b>Manual estimation:</b>\n 40436#@gui : Use the sliders below to target as much skin pixels as you can.</small>") 40437#@gui : X-Coordinate = float(50,0,100) 40438#@gui : Y-Coordinate = float(50,0,100) 40439#@gui : Radius = float(5,0,25) 40440#@gui : sep = separator() 40441#@gui : Output Mode = choice(1,"Probability Map","Opaque Skin","Transparent Skin") 40442#@gui : sep = separator() 40443#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40444#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40445#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40446#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40447#@gui : sep = separator() 40448#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/03/01</i>.</small>") 40449fx_detect_skin : 40450 to_rgb 40451 m "_fx_detect_skin : 40452 if $5 balance_gamma 128,128,128 fi 40453 if $1 detect_skin $2 else detect_skin $2,$6%,$7%,$8% fi 40454 M={iM} b $3% * {255*$M/iM} * $4 c 0,255" 40455 repeat $! l[$>] 40456 if $9 # Opaque/transparent skin. 40457 +_fx_detect_skin a c 40458 if $9>1 sh 100% *. -1 +. 255 rm. fi 40459 else _fx_detect_skin # Probability mask. 40460 fi 40461 endl done 40462 um _fx_detect_skin 40463 40464fx_detect_skin_preview : 40465 gui_split_preview "fx_detect_skin $*",${-3--1} 40466 to_rgba 40467 if !$1 40468 circle $6%,$7%,$8%,0.3,0,255,0,255 40469 circle $6%,$7%,$8%,1,0xFFFFFFFF,0,255,0,255 40470 line {$6-0.25*$8}%,{$7-0.25*$8}%,{$6+0.25*$8}%,{$7+0.25*$8}%,1,255,255,0,255 40471 line {$6+0.25*$8}%,{$7-0.25*$8}%,{$6-0.25*$8}%,{$7+0.25*$8}%,1,255,255,0,255 40472 fi 40473 40474#@gui Equalize HSV : fx_hsv_equalizer, fx_hsv_equalizer_preview 40475#@gui : Preview Bands = bool(false) 40476#@gui : sep = separator() 40477#@gui : Hue Band = float(180,0,360) 40478#@gui : Band Width = float(40,1,360) 40479#@gui : Hue Shift = float(0,-180,180) 40480#@gui : Saturation Correction = float(0,-0.99,0.99) 40481#@gui : Value Correction = float(0,-0.99,0.99) 40482#@gui : sep = separator() 40483#@gui : Hue Band = float(180,0,360) 40484#@gui : Band Width = float(40,1,360) 40485#@gui : Hue Shift = float(0,-180,180) 40486#@gui : Saturation Correction = float(0,-0.99,0.99) 40487#@gui : Value Correction = float(0,-0.99,0.99) 40488#@gui : sep = separator() 40489#@gui : Hue Band = float(180,0,360) 40490#@gui : Band Width = float(40,1,360) 40491#@gui : Hue Shift = float(0,-180,180) 40492#@gui : Saturation Correction = float(0,-0.99,0.99) 40493#@gui : Value Correction = float(0,-0.99,0.99) 40494#@gui : sep = separator() 40495#@gui : note = note("<small>Author: <i>Jérome Ferrari</i>. 40496#@gui : Latest Update: <i>01/14/2011</i>.</small>") 40497#@gui : url = link("Filter explained here","http://www.flickr.com/groups/gmic/discuss/72157625798533482") 40498fx_hsv_equalizer : 40499 repeat $! l[$>] 40500 to_rgb rgb2hsv s c 40501# From now on 0,1,2 are H,S,V 40502#3 masks: 40503 +f[0] if(abs(i-$2)<$3/2|abs(i-$2-360)<$3/2|abs(i-$2+360)<$3/2,1,0) 40504 +f[0] if(abs(i-$7)<$8/2|abs(i-$7-360)<$8/2|abs(i-$7+360)<$8/2,1,0) 40505 +f[0] if(abs(i-$12)<$13/2|abs(i-$12-360)<$13/2|abs(i-$12+360)<$13/2,1,0) 40506# From now on 3,4,5 are Masks 40507 +threshold[1,2] 0.01 *[-1,-2] [-1]x2 *[-1,3] *[-1,4] *[-1,5] #0 saturation and value not in mask 40508# Hue shift: 40509 +*[3] $4 +*[4] $9 +*[5] $14 +[-1,-2,-3] 40510 +[-1,0] %[0] 360 40511# Saturation : 40512 if $5>=0 +*[3] -$5 else +*[3] {1/(1+$5)-1} fi +. 1 40513 if $10>=0 +*[4] -$10 else +*[4] {1/(1+$10)-1} fi +. 1 40514 if $15>=0 +*[5] -$15 else +*[5] {1/(1+$15)-1} fi +. 1 40515 *[-1,-2,-3] ^[1,-1] 40516# Value : 40517 if $6>=0 +*[3] -$6 else +*[3] {1/(1+$6)-1} fi +. 1 40518 if $11>=0 +*[4] -$11 else +*[4] {1/(1+$11)-1} fi +. 1 40519 if $16>=0 +*[5] -$16 else +*[5] {1/(1+$16)-1} fi +. 1 40520 *[-1,-2,-3] ^[2,-1] 40521#reconstruction 40522 rm[3,4,5] a[0,1,2] c hsv2rgb 40523 endl done 40524 40525fx_hsv_equalizer_preview : 40526 l. 40527 if $1==0 fx_hsv_equalizer $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16 40528 else 40529 to_rgb rgb2hsv s c 40530 (0,359) r. ..,{{0,h}/10},1,1,3 . f. 1 #create lower band 40531 j[0] [3],0,91% j[1] [4],0,91% j[2] [4],0,91% rm[-1,-2] #paste lower band 40532 +f[0] if(abs(i-$2)<$3/2|abs(i-$2-360)<$3/2|abs(i-$2+360)<$3/2,1,0) 40533 +f[0] if(abs(i-$7)<$8/2|abs(i-$7-360)<$8/2|abs(i-$7+360)<$8/2,1,0) 40534 +f[0] if(abs(i-$12)<$13/2|abs(i-$12-360)<$13/2|abs(i-$12+360)<$13/2,1,0) #masks 40535 -|[-3--1] +. 0.33 /. 1.33 #1 and 0.25 40536 *[2,-1] a c hsv2rgb 40537 fi endl 40538 40539#@gui Equalize HSI-HSL-HSV : fx_equalize_hsv, fx_equalize_hsv_preview(0)+ 40540#@gui : Colorspace = choice(1,"HSI","HSL","HSV") 40541#@gui : Opacity (%) = float(100,0,100) 40542#@gui : Value Blending = float(0,0,64) 40543#@gui : Color Blending = float(0,0,64) 40544#@gui : sep = separator() 40545#@gui : Preview Mapping = choice("None","Grey","Color") 40546#@gui : sep = separator() 40547#@gui : note = note("<small><b>Black:</b></small>") 40548#@gui : Hue Offset = float(0,-180,180) 40549#@gui : Saturation Offset = float(0,-1,1) 40550#@gui : Value Offset = float(0,-1,1) 40551#@gui : sep = separator() 40552#@gui : note = note("<small><b>Near black:</b></small>") 40553#@gui : Hue Offset = float(0,-180,180) 40554#@gui : Saturation Offset = float(0,-1,1) 40555#@gui : Value Offset = float(0,-1,1) 40556#@gui : sep = separator() 40557#@gui : note = note("<small><b>Dark grey:</b></small>") 40558#@gui : Hue Offset = float(0,-180,180) 40559#@gui : Saturation Offset = float(0,-1,1) 40560#@gui : Value Offset = float(0,-1,1) 40561#@gui : sep = separator() 40562#@gui : note = note("<small><b>Mi-dark grey:</b></small>") 40563#@gui : Hue Offset = float(0,-180,180) 40564#@gui : Saturation Offset = float(0,-1,1) 40565#@gui : Value Offset = float(0,-1,1) 40566#@gui : sep = separator() 40567#@gui : note = note("<small><b>Middle grey:</b></small>") 40568#@gui : Hue Offset = float(0,-180,180) 40569#@gui : Saturation Offset = float(0,-1,1) 40570#@gui : Value Offset = float(0,-1,1) 40571#@gui : sep = separator() 40572#@gui : note = note("<small><b>Mid-light grey:</b></small>") 40573#@gui : Hue Offset = float(0,-180,180) 40574#@gui : Saturation Offset = float(0,-1,1) 40575#@gui : Value Offset = float(0,-1,1) 40576#@gui : sep = separator() 40577#@gui : note = note("<small><b>Light grey:</b></small>") 40578#@gui : Hue Offset = float(0,-180,180) 40579#@gui : Saturation Offset = float(0,-1,1) 40580#@gui : Value Offset = float(0,-1,1) 40581#@gui : sep = separator() 40582#@gui : note = note("<small><b>Highlights:</b></small>") 40583#@gui : Hue Offset = float(0,-180,180) 40584#@gui : Saturation Offset = float(0,-1,1) 40585#@gui : Value Offset = float(0,-1,1) 40586#@gui : sep = separator() 40587#@gui : note = note("<small><b>White:</b></small>") 40588#@gui : Hue Offset = float(0,-180,180) 40589#@gui : Saturation Offset = float(0,-1,1) 40590#@gui : Value Offset = float(0,-1,1) 40591#@gui : sep = separator() 40592#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40593#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40594#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40595#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40596#@gui : sep = separator() 40597#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>David Revoy</i>. 40598#@gui : Latest Update: <i>2018/01/19</i>.</small>") 40599fx_equalize_hsv : 40600 cs=${"arg 1+$1,hsi,hsl,hsv"} 40601 repeat $! l[$>] split_opacity l[0] 40602 to_rgb 40603 9,1,1,4,\ 40604 {"V = [${6-30:3}]*pi/180; [cos(V),sin(V)]"},${7-31:3},\ 40605 {"V = [${8-32:3}]; 40606 const sV = size(V); 40607 repeat (sV,k, 40608 v0 = k/sV; 40609 v1 = (k+1)/sV; 40610 V[k]*=(V[k]>0?(1 - v0):v1); 40611 ); V"} 40612 r. 256,1,1,4,1 40613 sh. 3 b. $3 rm. # Value smoothness 40614 f. "[ atan2(G,R)*180/pi,B,A,0 ]" channels. 0,2 40615 +rgb2$cs.. +channels. 100% *. 256 round. map. ... 40616 +[-2,-1] rm.. +channels. 100% ${cs}2rgb.. 40617 if $4 # Spatial smoothness 40618 *. 255 bilateral.. .,$4,{2+$4} 40619 rgb2$cs.. /. 255 j.. .,0,0,0,2 ${cs}2rgb.. 40620 fi 40621 rm. 40622 blend alpha,{$2%} 40623 endl a c endl done 40624 40625fx_equalize_hsv_preview : 40626 if $5 40627 cs=${"arg 1+$1,hsi,hsl,hsv"} 40628 rm {0.8*[${-gui_preview_wh}]},1,3,\ 40629 "$5==1? 40630 (H = S = 0; V = y/(h-1)): 40631 (H = x*360/(w-1); S = y/(h-1); V = y/(h-1)); 40632 [H,S,V]" 40633 ${cs}2rgb. 40634 fi 40635 gui_split_preview "fx_equalize_hsv $*",${-3--1} 40636 if $5 r. ${-gui_preview_wh},1,3,0,0,0.5,0.5 fi 40637 40638#@gui Mixer [CMYK] : fx_mix_cmyk, fx_mix_cmyk_preview(1)+ 40639#@gui : Cyan Factor = float(1,0,4) 40640#@gui : Cyan Shift = float(0,-255,255) 40641#@gui : Cyan Smoothness = float(0,0,10) 40642#@gui : sep = separator() 40643#@gui : Magenta Factor = float(1,0,4) 40644#@gui : Magenta Shift = float(0,-255,255) 40645#@gui : Magenta Smoothness = float(0,0,10) 40646#@gui : sep = separator() 40647#@gui : Yellow Factor = float(1,0,4) 40648#@gui : Yellow Shift = float(0,-255,255) 40649#@gui : Yellow Smoothness = float(0,0,10) 40650#@gui : sep = separator() 40651#@gui : Key Factor = float(1,0,4) 40652#@gui : Key Shift = float(0,-255,255) 40653#@gui : Key Smoothness = float(0,0,10) 40654#@gui : sep = separator() 40655#@gui : Tones Range = choice("All tones","Shadows","Mid-Tones","Highlights") 40656#@gui : Tones Smoothness = float(2,0,10) 40657#@gui : sep = separator() 40658#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40659#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40660#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40661#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40662#@gui : sep = separator() 40663#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 40664fx_mix_cmyk : 40665 repeat $! l. split_opacity rv to_rgb. 40666 fx_start_mix $13,$14 40667 rgb2cmyk. s. c 40668 *[-4] $1 +[-4] $2 b[-4] $3% 40669 *... $4 +... $5 b... $6% 40670 *.. $7 +.. $8 b.. $9% 40671 *. $10 +. $11 b. $12% 40672 a[-4--1] c cmyk2rgb. 40673 fx_end_mix $13 40674 if $!!=3 rv a c fi endl mv. 0 done 40675 40676fx_mix_cmyk_preview : 40677 gui_split_preview "fx_mix_cmyk $*",${-3--1} 40678 40679#@gui Mixer [HSV] : fx_mix_hsv, fx_mix_hsv_preview(1)+ 40680#@gui : Hue Factor = float(1,0,4) 40681#@gui : Hue Shift = float(0,-180,180) 40682#@gui : Hue Smoothness = float(0,0,10) 40683#@gui : sep = separator() 40684#@gui : Saturation Factor = float(1,0,4) 40685#@gui : Saturation Shift = float(0,-1,1) 40686#@gui : Saturation Smoothness = float(0,0,10) 40687#@gui : sep = separator() 40688#@gui : Value Factor = float(1,0,4) 40689#@gui : Value Shift = float(0,-1,1) 40690#@gui : Value Smoothness = float(0,0,10) 40691#@gui : sep = separator() 40692#@gui : Tones Range = choice("All Tones","Shadows","Mid-Tones","Highlights") 40693#@gui : Tones Smoothness = float(2,0,10) 40694#@gui : sep = separator() 40695#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40696#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40697#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40698#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40699#@gui : sep = separator() 40700#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 40701fx_mix_hsv : 40702 repeat $! l. split_opacity rv to_rgb. 40703 fx_start_mix $10,$11 40704 rgb2hsv. s. c -[-2,-1] 0.5 40705 *... $1 +... $2 b... $3% 40706 *.. $4 +.. $5 b.. $6% 40707 *. $7 +. $8 b. $9% 40708 %... 360 +[-2,-1] 0.5 c[-2,-1] 0,1 a[-3--1] c hsv2rgb. 40709 fx_end_mix $10 40710 if $!!=3 rv a c fi endl mv. 0 done 40711 40712fx_mix_hsv_preview : 40713 gui_split_preview "fx_mix_hsv $*",${-3--1} 40714 40715#@gui Mixer [Lab] : fx_mix_lab, fx_mix_lab_preview(1)+ 40716#@gui : Lightness Factor = float(1,0.5,1.5) 40717#@gui : Lightness Shift = float(0,-50,50) 40718#@gui : Lightness Smoothness = float(0,0,10) 40719#@gui : sep = separator() 40720#@gui : A-Color Factor = float(1,0,4) 40721#@gui : A-Color Shift = float(0,-20,20) 40722#@gui : A-Color Smoothness = float(0,0,10) 40723#@gui : sep = separator() 40724#@gui : B-Color Factor = float(1,0,4) 40725#@gui : B-Color Shift = float(0,-20,20) 40726#@gui : B-Color Smoothness = float(0,0,10) 40727#@gui : sep = separator() 40728#@gui : Tones Range = choice("All Tones","Shadows","Mid-Tones","Highlights") 40729#@gui : Tones Smoothness = float(2,0,10) 40730#@gui : sep = separator() 40731#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40732#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40733#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40734#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40735#@gui : sep = separator() 40736#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 40737fx_mix_lab : 40738 repeat $! l[$>] split_opacity to_rgb[0] 40739 gui_parallel_overlap[0] "_fx_mix_lab $*",0,{3*max($3,$6,$9)} 40740 a c 40741 endl mv[$>] 0 done 40742 40743_fx_mix_lab : 40744 fx_start_mix $10,$11 40745 rgb2lab. s. c 40746 *... $1 +... $2 b... $3% 40747 *.. $4 +.. $5 b.. $6% 40748 *. $7 +. $8 b. $9% 40749 a[-3--1] c lab2rgb. 40750 fx_end_mix $10 40751 40752fx_mix_lab_preview : 40753 gui_split_preview "fx_mix_lab $*",${-3--1} 40754 40755#@gui Mixer [PCA] : fx_mix_pca, fx_mix_pca_preview(1)+ 40756#@gui : Primary Factor = float(0,-1.5,1.5) 40757#@gui : Primary Shift = float(0,-255,255) 40758#@gui : Primary Twist = float(0,-180,180) 40759#@gui : Primary Gamma = float(0,-100,100) 40760#@gui : sep = separator() 40761#@gui : Secondary Factor = float(0,-1.5,1.5) 40762#@gui : Secondary Shift = float(0,-255,255) 40763#@gui : Secondary Twist = float(0,-180,180) 40764#@gui : Secondary Gamma = float(0,-100,100) 40765#@gui : sep = separator() 40766#@gui : Tertiary Factor = float(0,-1.5,1.5) 40767#@gui : Tertiary Shift = float(0,-255,255) 40768#@gui : Tertiary Twist = float(0,-180,180) 40769#@gui : Tertiary Gamma = float(0,-100,100) 40770#@gui : sep = separator() 40771#@gui : Display Color Axes = bool(1) 40772#@gui : Stats = value(-1,-1,-1,-1) 40773#@gui : Avg Covariance = value(0,0,0,0,0,0,0,0,0,0,0,0) 40774#@gui : sep = separator() 40775#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40776#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40777#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40778#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40779#@gui : sep = separator() 40780#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/07/18</i>.</small>") 40781fx_mix_pca : 40782 repeat $! l[$>] split_opacity l[0] to_rgb 40783 40784 # Get image covariance (and remember it to speed up multiple calls of the filter). 40785 if [$14]==round(stats()[0,4],0.1) _avg={[$15][0,3]} C={[$15][3,9]} status= 40786 else 40787 +rr2d 256,256,0,2 C=${"covariance_colors. _avg"} rm. 40788 __status="{$1}{$2}{$3}{$4}"\ 40789 "{$5}{$6}{$7}{$8}"\ 40790 "{$9}{$10}{$11}{$12}"\ 40791 "${13}"\ 40792 "{"{round(stats()[0,4],0.1)}"}"\ 40793 "{"$_avg,$C"}"\ 40794 "{$16}{${17,18}}" 40795 fi 40796 40797 # Find value ranges for gamma correction. 40798 if "$4 || $8 || $12" +l 40799 f "begin(avg = ["$_avg"]; eig = eig(["$C"]); Pt = eig[3,9]); Pt*(I-avg)" 40800 s c repeat $! vmax$>={$>,1.1*max(abs(im),abs(iM))} done 40801 rm 40802 endl else vmax0,vmax1,vmax2=1 fi 40803 40804 # Modify image values. 40805 f "begin( 40806 do_gamma(val,vmax,gamma) = (vmax*sign(val)*(abs(val)/vmax)^gamma); 40807 40808 const gamma0 = 10^-($4%); 40809 const gamma1 = 10^-($8%); 40810 const gamma2 = 10^-($12%); 40811 const vmax0 = "$vmax0"; 40812 const vmax1 = "$vmax1"; 40813 const vmax2 = "$vmax2"; 40814 40815 avg = ["$_avg"]; 40816 eig = eig(["$C"]); 40817 for (k = 3, k<12, k+=3, eig[k]<0?copy(eig[k],eig[k,3]*=-1,3)); 40818 Pt = eig[3,9]; 40819 P = transpose(Pt,3); 40820 T = mul(P,diag(10^[$1,$5,$9]),3); 40821 40822 R1 = rot(eig[3,3],$3°); 40823 R2 = rot(eig[6,3],$7°); 40824 R3 = rot(eig[9,3],$11°); 40825 T = mul(R1,mul(R2,mul(R3,T,3),3),3); 40826 avg_shift = avg + $2*eig[3,3] + $6*eig[6,3] + $10*eig[9,3]; 40827 40828 if ("0$_is_preview", 40829 L = [ 2,5,10]*sqrt(1e-5 + eig[0,3]); 40830 run('__cols=',vtos(round([ 40831 avg - L[0]*eig[3,3], 40832 avg + L[0]*eig[3,3], 40833 avg - L[1]*eig[6,3], 40834 avg + L[1]*eig[6,3], 40835 avg - L[2]*eig[9,3], 40836 avg + L[2]*eig[9,3] ]))); 40837 ); 40838 ); 40839 nI = Pt*(I - avg); 40840 ($4 || $8 || $12)?( 40841 nI[0] = do_gamma(nI[0],vmax0,gamma0); 40842 nI[1] = do_gamma(nI[1],vmax1,gamma1); 40843 nI[2] = do_gamma(nI[2],vmax2,gamma2); 40844 ); 40845 avg_shift + T*nI" 40846 c 0,255 40847 endl a c endl done u $__status 40848 40849fx_mix_pca_preview : 40850 _is_preview=1 40851 __status= 40852 repeat $! l[$>] 40853 gui_split_preview "fx_mix_pca ${1-13},\"$14\",\"$15\",${16-18}",${-3--1} 40854 if $13 40855 rr2d ${-gui_preview_wh},0,1 40856 ($__cols) r. 3,6,1,1,-1 permute. yzcx s. x,3 40857 r[-3--1] {w#0/2},13,1,3,3 c[-3--1] 0,255 40858 frame[-3--1] 1,1,0 40859 to[0] Primary,4,2,13,1 j[0] ...,64,4 40860 to[0] Secondary,4,17,13,1 j[0] ..,64,19 40861 to[0] Tertiary,4,32,13,1 j[0] .,64,34 40862 k[0] 40863 fi 40864 endl done 40865 u $__status 40866 40867#@gui Mixer [RGB] : fx_mix_rgb, fx_mix_rgb_preview(1)+ 40868#@gui : Red Factor = float(1,0,4) 40869#@gui : Red Shift = float(0,-255,255) 40870#@gui : Red Smoothness = float(0,0,10) 40871#@gui : sep = separator() 40872#@gui : Green Factor = float(1,0,4) 40873#@gui : Green Shift = float(0,-255,255) 40874#@gui : Green Smoothness = float(0,0,10) 40875#@gui : sep = separator() 40876#@gui : Blue Factor = float(1,0,4) 40877#@gui : Blue Shift = float(0,-255,255) 40878#@gui : Blue Smoothness = float(0,0,10) 40879#@gui : sep = separator() 40880#@gui : Tones Range = choice("All Tones","Shadows","Mid-Tones","Highlights") 40881#@gui : Tones Smoothness = float(2,0,10) 40882#@gui : sep = separator() 40883#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40884#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40885#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40886#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40887#@gui : sep = separator() 40888#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 40889fx_start_mix : 40890 if $1==1 +tones. 3 +[-2,-1] b[-2,-1] $2% ri[-2,-1] ... *. ... mv... $! 40891 elif $1==2 +tones. 3 +[-3,-1] b[-2,-1] $2% ri[-2,-1] ... *.. ... mv... $! 40892 elif $1==3 +tones. 3 +[-3,-2] b[-2,-1] $2% ri[-2,-1] ... *.. ... mv... $! 40893 fi 40894 40895fx_end_mix : 40896 if $1==1 *[-3,-1] +[-2,-1] 40897 elif $1==2 *[-2,-1] +[-2,-1] 40898 elif $1==3 *[-2,-1] +[-2,-1] 40899 fi 40900 c 0,255 40901 40902fx_mix_rgb : 40903 repeat $! l. split_opacity rv to_rgb. 40904 fx_start_mix $10,$11 40905 -. 128 s. c 40906 *... $1 +... $2 b... $3% 40907 *.. $4 +.. $5 b.. $6% 40908 *. $7 +. $8 b. $9% 40909 a[-3--1] c +. 128 c. 0,255 40910 fx_end_mix $10 40911 if $!!=3 rv a c fi endl mv. 0 done 40912 40913fx_mix_rgb_preview : 40914 gui_split_preview "fx_mix_rgb $*",${-3--1} 40915 40916#@gui Mixer [YCbCr] : fx_mix_ycbcr, fx_mix_ycbcr_preview(1)+ 40917#@gui : Luminance Factor = float(1,0,4) 40918#@gui : Luminance Shift = float(0,-255,255) 40919#@gui : Luminance Smoothness = float(0,0,10) 40920#@gui : sep = separator() 40921#@gui : Blue Chroma Factor = float(1,0,4) 40922#@gui : Blue Chroma Shift = float(0,-255,255) 40923#@gui : Blue Chroma Smoothness = float(0,0,10) 40924#@gui : sep = separator() 40925#@gui : Red Chroma Factor = float(1,0,4) 40926#@gui : Red Chroma Shift = float(0,-255,255) 40927#@gui : Red Chroma Smoothness = float(0,0,10) 40928#@gui : sep = separator() 40929#@gui : Tones Range = choice("All Tones","Shadows","Mid-Tones","Highlights") 40930#@gui : Tones Smoothness = float(2,0,10) 40931#@gui : sep = separator() 40932#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40933#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40934#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40935#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40936#@gui : sep = separator() 40937#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 40938fx_mix_ycbcr : 40939 repeat $! l. split_opacity rv to_rgb. 40940 fx_start_mix $10,$11 40941 rgb2ycbcr. -. 128 s. c 40942 *... $1 +... $2 b... $3% 40943 *.. $4 +.. $5 b.. $6% 40944 *. $7 +. $8 b. $9% 40945 a[-3--1] c +. 128 c. 0,255 ycbcr2rgb. 40946 fx_end_mix $10 40947 if $!!=3 rv a c fi endl mv. 0 done 40948 40949fx_mix_ycbcr_preview : 40950 gui_split_preview "fx_mix_ycbcr $*",${-3--1} 40951 40952#@gui CLUT from After - Before Layers : fx_clut_from_ab, fx_clut_from_ab_preview 40953#@gui : Output Mode = choice("Replace Layer with CLUT","Insert New CLUT Layer","Save CLUT as .cube or .png File") 40954#@gui : Output CLUT Resolution = choice{4,16,25,36,49,64,81,100,121,144,169,225,256}_2 40955#@gui : sep = separator() 40956#@gui : Output Folder = _folder()_1- 40957#@gui : Output Filename = _text("output.cube")_1+ 40958#@gui : sep = separator() 40959#@gui : Influence of Color Samples (%) = float(50,0,100)_2 40960#@gui : sep = separator() 40961#@gui : note = note{"<b>What is this filter for?</b>\n\n 40962#@gui : This filter requires at least two input layers to work properly.\n 40963#@gui : It assumes you have an input top layer <b>A</b> and a base layer <b>B</b> such that <b>A</b> and 40964#@gui : <b>B</b> both represent the same image but with only color variations 40965#@gui : (typically <b>A</b> has been obtained from <b>B</b> using the color curves tool).\n\n 40966#@gui : This filter is then able to estimate and outputs a color HaldCLUT <b>H</b> so that applying <b>H</b> 40967#@gui : on the base layer <b>B</b> gives back <b>A</b>.\n\n 40968#@gui : This is useful when you have a color transformation between two images, that you want to recover and 40969#@gui : re-apply on a bunch of other images. 40970#@gui : "} 40971#@gui : sep = separator() 40972#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. 40973#@gui : Latest Update: <i>2019/08/27</i>.</small>") 40974fx_clut_from_ab : skip "${3=},${4=}" 40975 if $!<2 error "At least two input layers are needed to run this filter." fi 40976 repeat $!-1 l[$<,-1] nm=${gui_layer_name..} 40977 i[0] {a=0$_is_preview?32:64;[a,a,a]},4 f[1] ">I(#0,round(I(#2)*(w#0-1)/255))+=[R,G,B,1]; I" 40978 l[0] 40979 s c,-3 +max. 1 /[-3,-1] ==. 0 inpaint_pde.. .,75%,1 distance. 0 *. {-1/(1+$5)} exp. 40980 f.. "f = i(#-1); f*I + (1-f)*[x,y,z]*255/(w-1)" rm. 40981 S={arg(1+$2,16,25,36,49,64,81,100,121,144,169,225,256)} if $S!=w r. $S,$S,$S,3,3 fi 40982 c 0,255 40983 endl 40984 40985 if $1==2 # Output as a file 40986 is_png={str=lowercase(['"$4"']);find(str,'.png')==size(str)-4} 40987 is_cube={str=lowercase(['"$4"']);find(str,'.cube')==size(str)-5} 40988 if !$is_png" && "!$is_cube $!is_ciube error "Filename extension must be '.cube' or '.png'." fi 40989 if $is_png r[0] {0,r=round(whd^0.5);[r,r]},1,3,-1 o[0] "$3/$4" 40990 else 40991 if {0,w>32} r3dx[0] 32 fi 40992 output_cube[0] "$3/$4" 40993 fi 40994 rm[0] 40995 else 40996 r[0] {0,r=round(whd^0.5);[r,r]},1,3,-1 40997 if !$1 rm[1] fi # Replace Layer with CLUT 40998 nm[0] "name(CLUT to '"$nm"')" 40999 fi 41000 if 0$_output_mode k[0] fi 41001 endl done 41002 41003fx_clut_from_ab_preview : skip "${3=},${4=}" 41004 if $!<2 gui_warning_preview "At least two input layers are needed to run this filter." return fi 41005 _is_preview,_output_mode=1 fx_clut_from_ab 0,4,0,0,$5 41006 repeat $! l[$>] 41007 r {a=round(cbrt(wh));[a,a,a]},3,-1 41008 +r3dx. 24 _fx_clut_from_ab_preview. 41009 S={arg(1+$2,16,25,36,49,64,81,100,121,144,169,225,256)} if $S!=w#0 r[0] $S,$S,$S,3,3 fi 41010 r[0] {0,r=round(whd^0.5);[r,r]},1,3,-1 41011 rr2d[0] $_preview_width,$_preview_height,2,1 r2dx. 70% 41012 sh. 100% b. 1% n. 0,255 rm. 41013 blend alpha 41014 endl done 41015 41016 file_attr={$1==2?2:1} 41017 u "{$1}{$2}{$3}_"$file_attr"{$4}_"$file_attr"{$5}" 41018 41019# Render 3D visualization of a CLUT. 41020_fx_clut_from_ab_preview : 41021 repeat $! l[$>] 41022 fact={256/w} 41023 41024 # Color data, as a point cloud. 41025 pointcloud3d +3d 0.5,0.5,0.5 *3d $fact circles3d {1.25*$fact} o3d {0.004*$fact} 41026 41027 # Add cube edges. 41028 colorcube3d[] 41029 l. s3d l.. s y,6 repeat $! sh[$>] 4,100%,0,0 /. 1.25 rm. done endl a y endl # Darken colors of edges 41030 p3d. 1 41031 l. repeat 8 o={a=$>;0.5*[a&1,(a>>1)&1,(a>>2)&1]} ++3d[0] $o +-3d[0] $o done +3d endl # Increase thickness of edges 41032 41033 # Add 3D axes, without the 'O'. 41034 axes3d 64,64,64,24,R,G,B,0 41035 +3d 41036 41037 # Render 3D snapshot. 41038 pose3d 1.2451,0.120715,-0.893986,-58.3864,-0.572953,1.28275,-0.62477,-11.6557,\ 41039 0.696784,0.839071,1.08374,-333.008,0,0,217,1 41040 snapshot3d {max(512,0$_preview_width,0$_preview_height)},1.22,255,255,255 41041 autocrop frame 10,10,255 41042 to_rgba flood 0,0,0,20,1,1,255,255,255,0 41043 endl done 41044 41045#@gui Retinex : fx_retinex, fx_retinex_preview(0)+ 41046#@gui : Strength (%) = float(75,0,100) 41047#@gui : Value Offset = float(16,1,256) 41048#@gui : Colorspace = choice(1,"HSI","HSV","Lab","Linear RGB","RGB","YCbCr") 41049#@gui : Min Cut (%) = float(1,0,100) 41050#@gui : Max Cut (%) = float(1,0,100) 41051#@gui : Regularization = float(5,0,32) 41052#@gui : sep = separator() 41053#@gui : Low Scale = float(15,1,512) 41054#@gui : Middle Scale = float(80,1,512) 41055#@gui : High Scale = float(250,1,512) 41056#@gui : sep = separator() 41057#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41058#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41059#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41060#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41061#@gui : sep = separator() 41062#@gui : note = note("<small><b>Note:</b> This filter implements the <i>Multiscale Color Retinex</i> algorithm, 41063#@gui : as described in:</small>") 41064#@gui : url = link{"http://www.ipol.im/pub/art/2014/107/"} 41065#@gui : sep = separator() 41066#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/13/09</i>.</small>") 41067fx_retinex : 41068 repeat $! l[$>] 41069 +retinex $2,${"arg 1+$3,hsi,hsv,lab,lrgb,rgb,ycbcr"},$4,$5,${7--1} 41070 if $6 guided. ..,$6,$6 fi 41071 j[0] .,0,0,0,0,{$1%} rm. 41072 c 0,255 41073 endl done 41074 41075fx_retinex_preview : 41076 gui_split_preview "fx_retinex $*",${-3--1} 41077 41078#@gui Retro Fade : fx_retrofade, fx_retrofade_preview 41079#@gui : Iterations = int(20,1,64) 41080#@gui : Colors = int(6,2,32) 41081#@gui : Grain = float(40,1,100) 41082#@gui : sep = separator() 41083#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41084#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41085#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41086#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41087#@gui : sep = separator() 41088#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/25/10</i>.</small>") 41089fx_retrofade : 41090 repeat $! l[$>] split_opacity l[0] 41091 +f 0 41092 repeat $1 41093 +noise[0] $3 c. 0,255 autoindex. $2,0,0 41094 +[-2,-1] 41095 progress {$>*100/$1} 41096 done 41097 k. n 0,255 41098 progress 100 41099 endl a c endl done 41100 41101fx_retrofade_preview : 41102 gui_split_preview "fx_retrofade $*",${-3--1} 41103 41104#@gui Select-Replace Color : fx_select_color, fx_select_color_preview(0) 41105#@gui : Similarity Space = choice(0,"RGB[A]","RGB","YCbCr","Red","Green","Blue","Opacity","Luminance", 41106#@gui : "Blue & Red Chrominances","Hue","Saturation") 41107#@gui : Tolerance = float(20,0,100) 41108#@gui : Smoothness = float(0,0,10) 41109#@gui : Fill Holes = int(0,0,256) 41110#@gui : Selected Color = color(255,255,255,255) 41111#@gui : Output As = choice(0,"Selected Colors","Selected Mask","Rejected Colors","Rejected Mask","Replaced Color") 41112#@gui : Replacement Color = color(255,0,0,255) 41113#@gui : sep = separator() 41114#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41115#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41116#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41117#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41118#@gui : sep = separator() 41119#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41120_fx_select_color : 41121 if $1==1 to_rgb # RGB 41122 elif $1==2 to_rgb rgb2ycbcr # YCbCr 41123 elif $1==3 channels 0 # R 41124 elif $1==4 channels 1 # G 41125 elif $1==5 channels 2 # B 41126 elif $1==6 to_rgba channels 3 # Opacity 41127 elif $1==7 to_rgb rgb2ycbcr channels 0 # Luminance 41128 elif $1==8 to_rgb rgb2ycbcr channels 1,2 # B&R chrominances 41129 elif $1==9 to_rgb rgb2hsv channels 0 # Hue 41130 elif $1==10 to_rgb rgb2hsv channels 1 # Saturation 41131 fi 41132 41133fx_select_color : 41134 ($5^$6^$7^$8) _fx_select_color. $1 color={^} rm. 41135 repeat $! l[$>] to_rgba 41136 +_fx_select_color $1 41137 select_color[1] $2%,$color 41138 if $4 +area. 0,0 <=. {round($4^1.5)} inpaint.. .,0,3 rm. fi # Fill holes. 41139 b[1] $3 n[1] 0,255 41140 if $9==0 sh[0] 100% &. [1] # Selected colors. 41141 elif $9==1 rm[0] # Selected mask. 41142 elif $9==2 -[1] 255 *[1] -1 sh[0] 100% &. [1] # Rejected colors. 41143 elif $9==3 rm[0] - 255 * -1 # Rejected mask. 41144 else # Replaced color. 41145 /[1] 255 +*[0,1] +*[1] $11 +*[1] $12 +*[1] $13 *[1] $10 a[1,-3--1] c -[1,2] + 41146 fi 41147 k[0] 41148 endl done 41149 41150fx_select_color_preview : 41151 gui_split_preview "fx_select_color $*",${-3--1} 41152 41153#@gui Selective Desaturation : fx_selective_desaturation, fx_selective_desaturation_preview(1) 41154#@gui : Reference Color = color(255,255,255) 41155#@gui : Desaturate = choice("Reference Color","All but Reference Color") 41156#@gui : Strength = float(3,0,10) 41157#@gui : Regularization = int(0,0,20) 41158#@gui : Maximum Saturation = choice("From Input","From Reference Color","Maximum Value") 41159#@gui : sep = separator() 41160#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41161#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41162#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41163#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41164#@gui : sep = separator() 41165#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/15/07</i>.</small>") 41166fx_selective_desaturation : 41167 repeat $! l[$>] to_color split_opacity l[0] 41168 +fc $1,$2,$3 41169 -[1] [0] norm[1] /[1] {1e-6+iM} 41170 if $4 *[1] -{max(0.01,$5)} +[1] 1 41171 else >=[1] {5*$5}% 41172 fi 41173 c[1] 0,1 41174 rgb2hsl[0] s[0] c 41175 mM={[im,iM]} repeat $6 guided. [2],1,0.1 done n. $mM # Regularization step. 41176 if $7==0 *[1,-1] 41177 elif $7==1 ($1^$2^$3) rgb2hsl. *[1] {i[1]} rm[-2,-1] 41178 else rv[1,-1] rm. 41179 fi 41180 a c hsl2rgb 41181 endl a c endl done 41182 41183fx_selective_desaturation_preview : 41184 gui_split_preview "fx_selective_desaturation $*",${-3--1} 41185 41186#@gui Sepia : fx_sepia, fx_sepia_preview(1)+ 41187#@gui : Brightness (%) = float(0,-100,100) 41188#@gui : Contrast (%) = float(0,-100,100) 41189#@gui : Gamma (%) = float(0,-100,100) 41190#@gui : sep = separator() 41191#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41192#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41193#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41194#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41195#@gui : sep = separator() 41196#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41197fx_sepia : 41198 sepia adjust_colors ${1-3},0,0,0,255 41199 41200fx_sepia_preview : 41201 gui_split_preview "fx_sepia $*",${-3--1} 41202 41203#@gui Simulate Film : fx_simulate_film, fx_simulate_film_preview(1)+ 41204#@gui : Category = choice{"Black & White (25)","Instant [Consumer] (54)","Instant [Pro] (68)","Fuji XTrans III (15)", 41205#@gui : "Negative [Color] (13)","Negative [New] (39)","Negative [Old] (44)","Print Films (12)","Slide [Color] (26)"} 41206 41207##### Black & White 41208#@gui : Preset = choice{1,"All [Collage]","None", 41209#@gui : "Agfa APX 100","Agfa APX 25","Fuji Neopan 1600","Fuji Neopan Acros 100","Ilford Delta 100", 41210#@gui : "Ilford Delta 3200","Ilford Delta 400","Ilford FP4 Plus 125","Ilford HP5 Plus 400","Ilford HPS 800", 41211#@gui : "Ilford Pan F Plus 50","Ilford XP2","Kodak BW 400 CN","Kodak HIE (HS Infra)","Kodak T-Max 100", 41212#@gui : "Kodak T-Max 3200","Kodak T-Max 400","Kodak Tri-X 400","Polaroid 664","Polaroid 667","Polaroid 672", 41213#@gui : "Rollei IR 400","Rollei Ortho 25","Rollei Retro 100 Tonal","Rollei Retro 80s"}_2 41214 41215##### Instant [Consumer] 41216#@gui : Preset = choice{1,"All [Collage]","None", 41217#@gui : "Polaroid PX-100UV+ Cold --","Polaroid PX-100UV+ Cold -","Polaroid PX-100UV+ Cold", 41218#@gui : "Polaroid PX-100UV+ Cold +","Polaroid PX-100UV+ Cold ++","Polaroid PX-100UV+ Cold +++", 41219#@gui : "Polaroid PX-100UV+ Warm --","Polaroid PX-100UV+ Warm -","Polaroid PX-100UV+ Warm", 41220#@gui : "Polaroid PX-100UV+ Warm +","Polaroid PX-100UV+ Warm ++","Polaroid PX-100UV+ Warm +++", 41221#@gui : "Polaroid PX-680 --","Polaroid PX-680 -","Polaroid PX-680","Polaroid PX-680 +","Polaroid PX-680 ++", 41222#@gui : "Polaroid PX-680 Cold --","Polaroid PX-680 Cold -","Polaroid PX-680 Cold","Polaroid PX-680 Cold +", 41223#@gui : "Polaroid PX-680 Cold ++","Polaroid PX-680 Cold ++a","Polaroid PX-680 Warm --","Polaroid PX-680 Warm -", 41224#@gui : "Polaroid PX-680 Warm","Polaroid PX-680 Warm +","Polaroid PX-680 Warm ++","Polaroid PX-70 --", 41225#@gui : "Polaroid PX-70 -","Polaroid PX-70","Polaroid PX-70 +","Polaroid PX-70 ++","Polaroid PX-70 +++", 41226#@gui : "Polaroid PX-70 Cold --","Polaroid PX-70 Cold -","Polaroid PX-70 Cold","Polaroid PX-70 Cold +", 41227#@gui : "Polaroid PX-70 Cold ++","Polaroid PX-70 Warm --","Polaroid PX-70 Warm -","Polaroid PX-70 Warm", 41228#@gui : "Polaroid PX-70 Warm +","Polaroid PX-70 Warm ++","Polaroid Time Zero (Expired) ---", 41229#@gui : "Polaroid Time Zero (Expired) --","Polaroid Time Zero (Expired) -","Polaroid Time Zero (Expired)", 41230#@gui : "Polaroid Time Zero (Expired) +","Polaroid Time Zero (Expired) ++","Polaroid Time Zero (Expired) Cold ---", 41231#@gui : "Polaroid Time Zero (Expired) Cold --","Polaroid Time Zero (Expired) Cold -", 41232#@gui : "Polaroid Time Zero (Expired) Cold"}_0 41233 41234##### Instant [Pro] 41235#@gui : Preset = choice{1,"All [Collage]","None", 41236#@gui : "Fuji FP-100c --","Fuji FP-100c -","Fuji FP-100c","Fuji FP-100c (alt)","Fuji FP-100c +","Fuji FP-100c ++", 41237#@gui : "Fuji FP-100c ++a","Fuji FP-100c +++", 41238#@gui : "Fuji FP-100c Cool --","Fuji FP-100c Cool -","Fuji FP-100c Cool","Fuji FP-100c Cool +","Fuji FP-100c Cool ++", 41239#@gui : "Fuji FP-100c Negative --","Fuji FP-100c Negative -","Fuji FP-100c Negative","Fuji FP-100c Negative +", 41240#@gui : "Fuji FP-100c Negative ++","Fuji FP-100c Negative ++a","Fuji FP-100c Negative +++", 41241#@gui : "Fuji FP-3000b --","Fuji FP-3000b -","Fuji FP-3000b","Fuji FP-3000b +","Fuji FP-3000b ++","Fuji FP-3000b +++", 41242#@gui : "Fuji FP-3000b HC","Fuji FP-3000b Negative --","Fuji FP-3000b Negative -","Fuji FP-3000b Negative", 41243#@gui : "Fuji FP-3000b Negative +","Fuji FP-3000b Negative ++","Fuji FP-3000b Negative +++", 41244#@gui : "Fuji FP-3000b Negative Early","Polaroid 665 --","Polaroid 665 -","Polaroid 665","Polaroid 665 +", 41245#@gui : "Polaroid 665 ++","Polaroid 665 Negative -","Polaroid 665 Negative","Polaroid 665 Negative +", 41246#@gui : "Polaroid 665 Negative HC","Polaroid 669 --","Polaroid 669 -","Polaroid 669","Polaroid 669 +", 41247#@gui : "Polaroid 669 ++","Polaroid 669 +++","Polaroid 669 Cold --","Polaroid 669 Cold -","Polaroid 669 Cold", 41248#@gui : "Polaroid 669 Cold +","Polaroid 690 --","Polaroid 690 -","Polaroid 690","Polaroid 690 +","Polaroid 690 ++", 41249#@gui : "Polaroid 690 Cold --","Polaroid 690 Cold -","Polaroid 690 Cold","Polaroid 690 Cold +","Polaroid 690 Cold ++", 41250#@gui : "Polaroid 690 Warm --","Polaroid 690 Warm -","Polaroid 690 Warm","Polaroid 690 Warm +","Polaroid 690 Warm ++"}_0 41251 41252#### Fuji XTrans III 41253#@gui : Preset = choice{1,"All [Collage]","None", 41254#@gui : "Acros","Acros+G","Acros+R","Acros+Ye","Astia","Classic Chrome","Mono","Mono+G","Mono+R","Mono+Ye", 41255#@gui : "Pro Neg Hi","Pro Neg Std","Provia","Sepia","Velvia"}_0 41256 41257##### Negative [Color] 41258#@gui : Preset = choice{1,"All [Collage]","None", 41259#@gui : "Agfa Ultra Color 100","Agfa Vista 200","Fuji Superia 200","Fuji Superia HG 1600","Fuji Superia Reala 100", 41260#@gui : "Fuji Superia X-Tra 800","Kodak Ektar 100","Kodak Elite 100 XPRO","Kodak Elite Color 200", 41261#@gui : "Kodak Elite Color 400","Kodak Portra 160 NC","Kodak Portra 160 VC","Lomography Redscale 100"}_0 41262 41263##### Negative [New] 41264#@gui : Preset = choice{1,"All [Collage]","None", 41265#@gui : "Fuji 160C -","Fuji 160C","Fuji 160C +","Fuji 160C ++", 41266#@gui : "Fuji 400H -","Fuji 400H","Fuji 400H +","Fuji 400H ++", 41267#@gui : "Fuji 800Z -","Fuji 800Z","Fuji 800Z +","Fuji 800Z ++", 41268#@gui : "Fuji Ilford HP5 -","Fuji Ilford HP5","Fuji Ilford HP5 +","Fuji Ilford HP5 ++", 41269#@gui : "Kodak Portra 160 -","Kodak Portra 160","Kodak Portra 160 +","Kodak Portra 160 ++", 41270#@gui : "Kodak Portra 400 -","Kodak Portra 400","Kodak Portra 400 +","Kodak Portra 400 ++", 41271#@gui : "Kodak Portra 800 -","Kodak Portra 800","Kodak Portra 800 +","Kodak Portra 800 ++","Kodak Portra 800 HC", 41272#@gui : "Kodak T-MAX 3200 -","Kodak T-MAX 3200","Kodak T-MAX 3200 +","Kodak T-MAX 3200 ++","Kodak T-MAX 3200 (alt)", 41273#@gui : "Kodak TRI-X 400 -","Kodak TRI-X 400","Kodak TRI-X 400 +","Kodak TRI-X 400 ++","Kodak TRI-X 400 (alt)"}_0 41274 41275##### Negative [Old] 41276#@gui : Preset = choice{1,"All [Collage]","None", 41277#@gui : "Fuji Ilford Delta 3200 -","Fuji Ilford Delta 3200","Fuji Ilford Delta 3200 +","Fuji Ilford Delta 3200 ++", 41278#@gui : "Fuji Neopan 1600 -","Fuji Neopan 1600","Fuji Neopan 1600 +","Fuji Neopan 1600 ++", 41279#@gui : "Fuji Superia 100 -","Fuji Superia 100","Fuji Superia 100 +","Fuji Superia 100 ++", 41280#@gui : "Fuji Superia 400 -","Fuji Superia 400","Fuji Superia 400 +","Fuji Superia 400 ++", 41281#@gui : "Fuji Superia 800 -","Fuji Superia 800","Fuji Superia 800 +","Fuji Superia 800 ++", 41282#@gui : "Fuji Superia 1600 -","Fuji Superia 1600","Fuji Superia 1600 +","Fuji Superia 1600 ++", 41283#@gui : "Kodak Portra 160 NC -","Kodak Portra 160 NC","Kodak Portra 160 NC +","Kodak Portra 160 NC ++", 41284#@gui : "Kodak Portra 160 VC -","Kodak Portra 160 VC","Kodak Portra 160 VC +","Kodak Portra 160 VC ++", 41285#@gui : "Kodak Portra 400 NC -","Kodak Portra 400 NC","Kodak Portra 400 NC +","Kodak Portra 400 NC ++", 41286#@gui : "Kodak Portra 400 UC -","Kodak Portra 400 UC","Kodak Portra 400 UC +","Kodak Portra 400 UC ++", 41287#@gui : "Kodak Portra 400 VC -","Kodak Portra 400 VC","Kodak Portra 400 VC +","Kodak Portra 400 VC ++"}_0 41288 41289##### Print Films 41290#@gui : Preset = choice{1,"All [Collage]","None", 41291#@gui : "Fuji 3510 (Constlclip)","Fuji 3510 (Constlmap)","Fuji 3510 (Cuspclip)", 41292#@gui : "Fuji 3513 (Constlclip)","Fuji 3513 (Constlmap)","Fuji 3513 (Cuspclip)", 41293#@gui : "Kodak 2383 (Constlclip)","Kodak 2383 (Constlmap)","Kodak 2383 (Cuspclip)", 41294#@gui : "Kodak 2393 (Constlclip)","Kodak 2393 (Constlmap)","Kodak 2393 (Cuspclip)"}_0 41295 41296#### Slide [Color] 41297#@gui : Preset = choice{1,"All [Collage]","None", 41298#@gui : "Agfa Precisa 100","Fuji Astia 100F","Fuji FP 100C","Fuji Provia 100F","Fuji Provia 400F","Fuji Provia 400X", 41299#@gui : "Fuji Sensia 100","Fuji Superia 200 XPRO","Fuji Velvia 50","Generic Fuji Astia 100","Generic Fuji Provia 100", 41300#@gui : "Generic Fuji Velvia 100","Generic Kodachrome 64","Generic Kodak Ektachrome 100 VS", 41301#@gui : "Kodak E-100 GX Ektachrome 100","Kodak Ektachrome 100 VS","Kodak Elite Chrome 200","Kodak Elite Chrome 400", 41302#@gui : "Kodak Elite ExtraColor 100","Kodak Kodachrome 200","Kodak Kodachrome 25","Kodak Kodachrome 64", 41303#@gui : "Lomography X-Pro Slide 200", 41304#@gui : "Polaroid 669","Polaroid 690","Polaroid Polachrome"}_0 41305 41306#@gui : Thumbnail Size = int(512,0,1024)_1 41307#@gui : sep = separator() 41308#@gui : Strength (%) = float(100,0,100) 41309#@gui : Brightness (%) = float(0,-100,100) 41310#@gui : Contrast (%) = float(0,-100,100) 41311#@gui : Gamma (%) = float(0,-100,100) 41312#@gui : Hue (%) = float(0,-100,100) 41313#@gui : Saturation (%) = float(0,-100,100) 41314#@gui : Normalize Colors = choice("None","Pre-Normalize","Post-Normalize","Both") 41315#@gui : sep = separator() 41316#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41317#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41318#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41319#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41320#@gui : sep = separator() 41321#@gui : note = note("<small><b>Note:</b> The color LUTs proposed in this filter come from 41322#@gui : various free sources :</small>") 41323#@gui : note = note{"<small><b>*</b> 41324#@gui : <a href="https://rawpedia.rawtherapee.com/Film_Simulation">RawTherapee Film Simulation</a>.</small>"} 41325#@gui : note = note{"<small><b>*</b> 41326#@gui : <a href="https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html">Pat David Film Emulation</a>. 41327#@gui : </small>"} 41328#@gui : note = note{"<small><b>*</b> 41329#@gui : <a href="http://blog.sowerby.me/fuji-film-simulation-profiles">Fuji Film Simulation Profiles</a>.</small>"} 41330#@gui : note = note{"<small><b>*</b> 41331#@gui : <a href="http://juanmelara.com.au/print-film-emulation-luts-for-download/">Print Film LUTs For Download</a>. 41332#@gui : </small>"} 41333#@gui : sep = separator() 41334#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/02/27</i>.</small>") 41335fx_simulate_film : 41336 category=${arg\ 1+$1,bw,instant_consumer,instant_pro,fujixtransiii,negative_color,negative_new,negative_old,\ 41337 print,colorslide} 41338 presets=${-_fx_cluts_$category} 41339 index={arg(1+$1,${2-10})} 41340 thumbsize,strength,brightness,contrast,gamma,hue,saturation,normalize=${11-18} 41341 if $normalize==1" || "$normalize==3 # Pre-normalization 41342 repeat $! l[$>] split_opacity balance_gamma[0] , a c endl done 41343 fi 41344 if $index>=2 # Apply CLUT 41345 path_clut=${-path_cache} 41346 name=${arg\ 1+$index-2,$presets} 41347 clut $name,{0$_is_preview" && "!isfile(['{/${path_clut}clut_$name.cimgz}'])?17:48} 41348 repeat $!-1 if $strength<100 +map_clut[$>] . j[$>] .,0,0,0,0,{$strength%} rm. else map_clut[$>] . fi done 41349 rm. 41350 adjust_colors $brightness,$contrast,$gamma,$hue,$saturation,0,255 41351 if $normalize==2" || "$normalize==3 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done fi # Post-normalization 41352 41353 elif $index==1 # "None" 41354 adjust_colors $brightness,$contrast,$gamma,$hue,$saturation,0,255 41355 if $normalize==2" || "$normalize==3 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done fi # Post-normalization 41356 41357 else # Collage 41358 repeat $! l[$>] if max(w,h)>$thumbsize rr2d $thumbsize,$thumbsize,0,2 fi endl done 41359 N=$! +to "Original",1%,1%,7.5%,2,0.5 41360 Np={narg($presets)} repeat $Np 41361 clut_name=${arg\ 1+$>,$presets} 41362 clut $clut_name mv. $N 41363 repeat $N 41364 if $strength<100 [$>] +map_clut. [$N] j.. .,0,0,0,0,{$strength%} rm. else +map_clut[$>] [$N] fi 41365 adjust_colors. $brightness,$contrast,$gamma,$hue,$saturation,0,255 41366 if $normalize==2" || "$normalize==3 l. split_opacity n[0] 0,255 a c endl fi # Post-normalization 41367 strcapitalize $clut_name clut_name=${} 41368 to. $clut_name,1%,1%,7.5%,2,0.5 41369 done 41370 rm[$N] 41371 progress {$>*100/($Np-1)} 41372 done 41373 k[$N--1] frame 1,1,0,0,0,255 - 128 append_tiles {s=floor(sqrt($!));w>h?[s,0]:[0,s]} + 128 41374 fi 41375 41376fx_simulate_film_preview : 41377 _is_preview=1 41378 index={arg(1+$1,${2-10})} 41379 if !$index gui_warning_preview "Preview disabled in 'Collage' mode" 41380 else gui_split_preview "fx_simulate_film $*",${19-21} 41381 fi 41382 u "{$1}{$2}_"{2*($1==0)}\ 41383 "{$3}_"{2*($1==1)}\ 41384 "{$4}_"{2*($1==2)}\ 41385 "{$5}_"{2*($1==3)}\ 41386 "{$6}_"{2*($1==4)}\ 41387 "{$7}_"{2*($1==5)}\ 41388 "{$8}_"{2*($1==6)}\ 41389 "{$9}_"{2*($1==7)}\ 41390 "{$10}_"{2*($1==8)}\ 41391 "{$11}_"{1+!$index}\ 41392 "{$12}{$13}{$14}{$15}{$16}{$17}{$18}{$19}{$20,$21}" 41393 41394_fx_cluts_bw : 41395 u agfa_apx_100,agfa_apx_25,fuji_neopan_1600,fuji_neopan_acros_100,ilford_delta_100,ilford_delta_3200,\ 41396 ilford_delta_400,ilford_fp_4_plus_125,\ 41397 ilford_hp_5_plus_400,ilford_hps_800,ilford_pan_f_plus_50,ilford_xp_2,kodak_bw_400_cn,kodak_hie_hs_infra,\ 41398 kodak_t-max_100,kodak_t-max_3200,\ 41399 kodak_t-max_400,kodak_tri-x_400,polaroid_664,polaroid_667,polaroid_672,rollei_ir_400,rollei_ortho_25,\ 41400 rollei_retro_100_tonal,rollei_retro_80s 41401 41402_fx_cluts_instant_consumer : 41403 u polaroid_px-100uv+_cold_--,polaroid_px-100uv+_cold_-,polaroid_px-100uv+_cold,polaroid_px-100uv+_cold_+,\ 41404 polaroid_px-100uv+_cold_++,polaroid_px-100uv+_cold_+++,\ 41405 polaroid_px-100uv+_warm_--,polaroid_px-100uv+_warm_-,polaroid_px-100uv+_warm,polaroid_px-100uv+_warm_+,\ 41406 polaroid_px-100uv+_warm_++,polaroid_px-100uv+_warm_+++,\ 41407 polaroid_px-680_--,polaroid_px-680_-,polaroid_px-680,polaroid_px-680_+,polaroid_px-680_++,\ 41408 polaroid_px-680_cold_--,polaroid_px-680_cold_-,polaroid_px-680_cold,polaroid_px-680_cold_+,\ 41409 polaroid_px-680_cold_++,polaroid_px-680_cold_++_alt,\ 41410 polaroid_px-680_warm_--,polaroid_px-680_warm_-,polaroid_px-680_warm,polaroid_px-680_warm_+,polaroid_px-680_warm_++,\ 41411 polaroid_px-70_--,polaroid_px-70_-,polaroid_px-70,polaroid_px-70_+,polaroid_px-70_++,polaroid_px-70_+++,\ 41412 polaroid_px-70_cold_--,polaroid_px-70_cold_-,polaroid_px-70_cold,polaroid_px-70_cold_+,polaroid_px-70_cold_++,\ 41413 polaroid_px-70_warm_--,polaroid_px-70_warm_-,polaroid_px-70_warm,polaroid_px-70_warm_+,polaroid_px-70_warm_++,\ 41414 polaroid_time_zero_expired_---,polaroid_time_zero_expired_--,polaroid_time_zero_expired_-,\ 41415 polaroid_time_zero_expired,polaroid_time_zero_expired_+,polaroid_time_zero_expired_++,\ 41416 polaroid_time_zero_expired_cold_---,polaroid_time_zero_expired_cold_--,polaroid_time_zero_expired_cold_-,\ 41417 polaroid_time_zero_expired_cold 41418 41419_fx_cluts_instant_pro : 41420 u fuji_fp-100c_--,fuji_fp-100c_-,fuji_fp-100c,fuji_fp-100c_alt,fuji_fp-100c_+,fuji_fp-100c_++,fuji_fp-100c_++_alt,\ 41421 fuji_fp-100c_+++,\ 41422 fuji_fp-100c_cool_--,fuji_fp-100c_cool_-,fuji_fp-100c_cool,fuji_fp-100c_cool_+,fuji_fp-100c_cool_++,\ 41423 fuji_fp-100c_negative_--,fuji_fp-100c_negative_-,fuji_fp-100c_negative,fuji_fp-100c_negative_+,\ 41424 fuji_fp-100c_negative_++,fuji_fp-100c_negative_++_alt,fuji_fp-100c_negative_+++,\ 41425 fuji_fp-3000b_--,fuji_fp-3000b_-,fuji_fp-3000b,fuji_fp-3000b_+,fuji_fp-3000b_++,fuji_fp-3000b_+++,fuji_fp-3000b_hc,\ 41426 fuji_fp-3000b_negative_--,fuji_fp-3000b_negative_-,fuji_fp-3000b_negative,fuji_fp-3000b_negative_+,\ 41427 fuji_fp-3000b_negative_++,fuji_fp-3000b_negative_+++,fuji_fp-3000b_negative_early,\ 41428 polaroid_665_--,polaroid_665_-,polaroid_665,polaroid_665_+,polaroid_665_++,\ 41429 polaroid_665_negative_-,polaroid_665_negative,polaroid_665_negative_+,polaroid_665_negative_hc,\ 41430 polaroid_669_--,polaroid_669_-,polaroid_669,polaroid_669_+,polaroid_669_++,polaroid_669_+++,\ 41431 polaroid_669_cold_--,polaroid_669_cold_-,polaroid_669_cold,polaroid_669_cold_+,\ 41432 polaroid_690_--,polaroid_690_-,polaroid_690,polaroid_690_+,polaroid_690_++,\ 41433 polaroid_690_cold_--,polaroid_690_cold_-,polaroid_690_cold,polaroid_690_cold_+,polaroid_690_cold_++,\ 41434 polaroid_690_warm_--,polaroid_690_warm_-,polaroid_690_warm,polaroid_690_warm_+,polaroid_690_warm_++ 41435 41436_fx_cluts_fujixtransiii : 41437 u fuji_xtrans_iii_acros,fuji_xtrans_iii_acros+g,fuji_xtrans_iii_acros+r,fuji_xtrans_iii_acros+ye,\ 41438 fuji_xtrans_iii_astia,\ 41439 fuji_xtrans_iii_classic_chrome,fuji_xtrans_iii_mono,fuji_xtrans_iii_mono+g,fuji_xtrans_iii_mono+r,\ 41440 fuji_xtrans_iii_mono+ye,\ 41441 fuji_xtrans_iii_pro_neg_hi,fuji_xtrans_iii_pro_neg_std,fuji_xtrans_iii_provia,fuji_xtrans_iii_sepia,\ 41442 fuji_xtrans_iii_velvia 41443 41444_fx_cluts_negative_color : 41445 u agfa_ultra_color_100,agfa_vista_200,fuji_superia_200,fuji_superia_hg_1600,fuji_superia_reala_100,\ 41446 fuji_superia_x-tra_800,kodak_ektar_100,\ 41447 kodak_elite_100_xpro,kodak_elite_color_200,kodak_elite_color_400,kodak_portra_160_nc,kodak_portra_160_vc,\ 41448 lomography_redscale_100 41449 41450_fx_cluts_negative_new : 41451 u fuji_160c_-,fuji_160c,fuji_160c_+,fuji_160c_++,\ 41452 fuji_400h_-,fuji_400h,fuji_400h_+,fuji_400h_++,\ 41453 fuji_800z_-,fuji_800z,fuji_800z_+,fuji_800z_++,\ 41454 ilford_hp_5_-,ilford_hp_5,ilford_hp_5_+,ilford_hp_5_++,\ 41455 kodak_portra_160_-,kodak_portra_160,kodak_portra_160_+,kodak_portra_160_++,\ 41456 kodak_portra_400_-,kodak_portra_400,kodak_portra_400_+,kodak_portra_400_++,\ 41457 kodak_portra_800_-,kodak_portra_800,kodak_portra_800_+,kodak_portra_800_++,kodak_portra_800_hc,\ 41458 kodak_tmax_3200_-,kodak_tmax_3200,kodak_tmax_3200_+,kodak_tmax_3200_++,kodak_tmax_3200_alt,\ 41459 kodak_tri-x_400_-,kodak_tri-x_400,kodak_tri-x_400_+,kodak_tri-x_400_++,kodak_tri-x_400_alt 41460 41461_fx_cluts_negative_old : 41462 u ilford_delta_3200_-,ilford_delta_3200,ilford_delta_3200_+,ilford_delta_3200_++,\ 41463 fuji_neopan_1600_-,fuji_neopan_1600,fuji_neopan_1600_+,fuji_neopan_1600_++,\ 41464 fuji_superia_100_-,fuji_superia_100,fuji_superia_100_+,fuji_superia_100_++,\ 41465 fuji_superia_400_-,fuji_superia_400,fuji_superia_400_+,fuji_superia_400_++,\ 41466 fuji_superia_800_-,fuji_superia_800,fuji_superia_800_+,fuji_superia_800_++,\ 41467 fuji_superia_1600_-,fuji_superia_1600,fuji_superia_1600_+,fuji_superia_1600_++,\ 41468 kodak_portra_160_nc_-,kodak_portra_160_nc,kodak_portra_160_nc_+,kodak_portra_160_nc_++,\ 41469 kodak_portra_160_vc_-,kodak_portra_160_vc,kodak_portra_160_vc_+,kodak_portra_160_vc_++,\ 41470 kodak_portra_400_nc_-,kodak_portra_400_nc,kodak_portra_400_nc_+,kodak_portra_400_nc_++,\ 41471 kodak_portra_400_uc_-,kodak_portra_400_uc,kodak_portra_400_uc_+,kodak_portra_400_uc_++,\ 41472 kodak_portra_400_vc_-,kodak_portra_400_vc,kodak_portra_400_vc_+,kodak_portra_400_vc_++ 41473 41474_fx_cluts_print : 41475 u fuji_3510_constlclip,fuji_3510_constlmap,fuji_3510_cuspclip,\ 41476 fuji_3513_constlclip,fuji_3513_constlmap,fuji_3513_cuspclip,\ 41477 kodak_2383_constlclip,kodak_2383_constlmap,kodak_2383_cuspclip,\ 41478 kodak_2393_constlclip,kodak_2393_constlmap,kodak_2393_cuspclip 41479 41480_fx_cluts_colorslide : 41481 u agfa_precisa_100,fuji_astia_100f,fuji_fp_100c,fuji_provia_100f,fuji_provia_400f,fuji_provia_400x,fuji_sensia_100,\ 41482 fuji_superia_200_xpro,fuji_velvia_50,fuji_astia_100_generic,fuji_provia_100_generic,fuji_velvia_100_generic,\ 41483 kodak_kodachrome_64_generic,kodak_ektachrome_100_vs_generic,kodak_e-100_gx_ektachrome_100,kodak_ektachrome_100_vs,\ 41484 kodak_elite_chrome_200,\ 41485 kodak_elite_chrome_400,kodak_elite_extracolor_100,kodak_kodachrome_200,kodak_kodachrome_25,kodak_kodachrome_64,\ 41486 lomography_x-pro_slide_200,\ 41487 polaroid_669,polaroid_690,polaroid_polachrome 41488 41489#@gui Transfer Colors [Variational] : fx_transfer_rgb, fx_transfer_rgb_preview(1)+ : * 41490#@gui : Regularization = int(8,0,32) 41491#@gui : Preserve Luminance = float(0.2,0,1) 41492#@gui : Precision = _choice(1,"Low","Normal","High","Very High") 41493#@gui : Reference Colors = choice("Bottom Layer","Top Layer") 41494#@gui : Add User-Defined Constraints (Interactive) = _bool(0) 41495#@gui : sep = separator() 41496#@gui : Preview_ref_point = point(1,1,0,0,255,255,255,128,4)_0 41497#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41498#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41499#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41500#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41501#@gui : sep = separator() 41502#@gui : note = note{"<small><b>Instructions:</b>\n 41503#@gui : - This filter transfers the colors of one layer to all the others.\n 41504#@gui : - Don't forget to set the <i>Input layers...</i> option on the left to manage your input layers.\n 41505#@gui : </small>"} 41506#@gui : sep = separator() 41507#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/04/04</i>.</small>") 41508fx_transfer_rgb : 41509 to_rgb 41510 ref={$4?0:-1} 41511 transfer_rgb[^$ref] [$ref],0.25,$1,$2,{2^(4+$3)},$5,0 41512 c 0,255 41513 41514fx_transfer_rgb_preview : 41515 if $!<2 gui_print_preview "Warning:",,"This filter requires at least two input layers to work properly." return fi 41516 ref={$4?0:-1} 41517 +store[$ref] _fx_trgb_ref 41518 gui_split_preview[^$ref] "$_fx_trgb_ref fx_transfer_rgb $1,$2,0,0,0 rm.",${-3--1} 41519 _fx_trgb_ref= 41520 41521 mv[$ref] $! 41522 repeat $!-1 l[$>,-1] 41523 rr2d[0] $_preview_width,$_preview_height,0,3 rr2d. {0,[w,h]/3},0,3 41524 to. Reference,2,2,13,1,1,255 frame. 2,2,255 frame. 1,1,0 41525 j[0] .,$6%,$7% 41526 rm. 41527 endl done 41528 41529#@gui Transfer Colors [Histogram] : fx_transfer_histogram, fx_transfer_histogram_preview(1)+ : * 41530#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41531#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41532#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41533#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41534#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41535#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41536#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41537#@gui : Reference Colors = choice("Bottom Layer","Top Layer") 41538#@gui : sep = separator() 41539#@gui : Preview_ref_point = point(1,1,0,0,255,255,255,128,4)_0 41540#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41541#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41542#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41543#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41544#@gui : sep = separator() 41545#@gui : note = note{"<small><b>Note: </b> 41546#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 41547#@gui : multiple input layers. 41548#@gui : </small>"} 41549#@gui : sep = separator() 41550#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/01/13</i>.</small>") 41551fx_transfer_histogram : 41552 to_rgb 41553 ref={$2?0:-1} 41554 transfer_histogram[^$ref] [$ref],256,$1 41555 c 0,255 41556 41557fx_transfer_histogram_preview : 41558 if $!<2 gui_print_preview "Warning:",,"This filter requires at least two input layers to work properly." return fi 41559 ref={$2?0:-1} 41560 +store[$ref] _fx_trgb_ref 41561 gui_split_preview[^$ref] "$_fx_trgb_ref fx_transfer_histogram $1,0 rm.",${-3--1} 41562 _fx_trgb_ref= 41563 41564 mv[$ref] $! 41565 repeat $!-1 l[$>,-1] 41566 rr2d[0] $_preview_width,$_preview_height,0,3 rr2d. {0,[w,h]/3},0,3 41567 to. Reference,2,2,13,1,1,255 frame. 2,2,255 frame. 1,1,0 41568 j[0] .,$3%,$4% 41569 rm. 41570 endl done 41571 41572#@gui Transfer Colors [PCA] : fx_transfer_pca, fx_transfer_pca_preview(1)+ : * 41573#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41574#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41575#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41576#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41577#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41578#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41579#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41580#@gui : Reference Colors = choice("Bottom Layer","Top Layer") 41581#@gui : sep = separator() 41582#@gui : Preview_ref_point = point(1,1,0,0,255,255,255,128,4)_0 41583#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41584#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41585#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41586#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41587#@gui : sep = separator() 41588#@gui : note = note{"<small><b>Note: </b> 41589#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 41590#@gui : multiple input layers. 41591#@gui : </small>"} 41592#@gui : sep = separator() 41593#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/01/13</i>.</small>") 41594fx_transfer_pca : 41595 to_rgb 41596 ref={$2?0:-1} 41597 transfer_pca[^$ref] [$ref],$1 41598 c 0,255 41599 41600fx_transfer_pca_preview : 41601 if $!<2 gui_print_preview "Warning:",,"This filter requires at least two input layers to work properly." return fi 41602 ref={$2?0:-1} 41603 +store[$ref] _fx_trgb_ref 41604 gui_split_preview[^$ref] "$_fx_trgb_ref fx_transfer_pca $1,0 rm.",${-3--1} 41605 _fx_trgb_ref= 41606 41607 mv[$ref] $! 41608 repeat $!-1 l[$>,-1] 41609 rr2d[0] $_preview_width,$_preview_height,0,3 rr2d. {0,[w,h]/3},0,3 41610 to. Reference,2,2,13,1,1,255 frame. 2,2,255 frame. 1,1,0 41611 j[0] .,$3%,$4% 41612 rm. 41613 endl done 41614 41615#@gui Tune HSV Colors : fx_tune_hsv, fx_tune_hsv_preview(1) 41616#@gui : Dark = choice(2,"Ignore","Lock","Remap") 41617#@gui : Dark Color = color(0,0,0) 41618#@gui : Target Hue (%) = float(100,0,100) 41619#@gui : Target Saturation (%) = float(100,0,100) 41620#@gui : Target Value (%) = float(100,0,100) 41621#@gui : sep = separator() 41622#@gui : Light = choice(2,"Ignore","Lock","Remap") 41623#@gui : Light Color = color(255,255,255) 41624#@gui : Target Hue (%) = float(100,0,100) 41625#@gui : Target Saturation (%) = float(100,0,100) 41626#@gui : Target Value (%) = float(100,0,100) 41627#@gui : sep = separator() 41628#@gui : Average = choice(1,"Ignore","Lock","Remap") 41629#@gui : Average Color = color(128,128,128)_0 41630#@gui : Target Hue (%) = float(0,0,100)_0 41631#@gui : Target Saturation (%) = float(50,0,100)_0 41632#@gui : Target Value (%) = float(100,0,100)_0 41633#@gui : sep = separator() 41634#@gui : Red = choice("Ignore","Lock","Remap") 41635#@gui : Red Color = color(255,0,0)_0 41636#@gui : Target Hue (%) = float(100,0,100)_0 41637#@gui : Target Saturation (%) = float(12.5,0,100)_0 41638#@gui : Target Value (%) = float(0,0,100)_0 41639#@gui : sep = separator() 41640#@gui : Yellow = choice("Ignore","Lock","Remap") 41641#@gui : Yellow Color = color(255,255,0)_0 41642#@gui : Target Hue (%) = float(100,0,100)_0 41643#@gui : Target Saturation (%) = float(12.5,0,100)_0 41644#@gui : Target Value (%) = float(0,0,100)_0 41645#@gui : sep = separator() 41646#@gui : Green = choice("Ignore","Lock","Remap") 41647#@gui : Green Color = color(0,255,0)_0 41648#@gui : Target Hue (%) = float(100,0,100)_0 41649#@gui : Target Saturation (%) = float(12.5,0,100)_0 41650#@gui : Target Value (%) = float(0,0,100)_0 41651#@gui : sep = separator() 41652#@gui : Cyan = choice("Ignore","Lock","Remap") 41653#@gui : Cyan Color = color(0,255,255)_0 41654#@gui : Target Hue (%) = float(100,0,100)_0 41655#@gui : Target Saturation (%) = float(12.5,0,100)_0 41656#@gui : Target Value (%) = float(0,0,100)_0 41657#@gui : sep = separator() 41658#@gui : Blue = choice("Ignore","Lock","Remap") 41659#@gui : Blue Color = color(0,0,255)_0 41660#@gui : Target Hue (%) = float(100,0,100)_0 41661#@gui : Target Saturation (%) = float(12.5,0,100)_0 41662#@gui : Target Value (%) = float(0,0,100)_0 41663#@gui : sep = separator() 41664#@gui : Magenta = choice("Ignore","Lock","Remap") 41665#@gui : Magenta Color = color(255,0,255)_0 41666#@gui : Target Hue (%) = float(100,0,100)_0 41667#@gui : Target Saturation (%) = float(12.5,0,100)_0 41668#@gui : Target Value (%) = float(0,0,100)_0 41669#@gui : sep = separator() 41670#@gui : Preview color mapping = choice(2,"None","Center","Top Left","Top Right","Bottom Left","Bottom Right") 41671#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41672#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41673#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41674#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41675#@gui : sep = separator() 41676#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/12/17</i>.</small>") 41677_fx_tune_hsv : 41678 mode_dark,Rdark,Gdark,Bdark,Hdark,Sdark,Vdark,\ 41679 mode_light,Rlight,Glight,Blight,Hlight,Slight,Vlight,\ 41680 mode_avg,Ravg,Gavg,Bavg,Havg,Savg,Vavg,\ 41681 mode_red,Rred,Gred,Bred,Hred,Sred,Vred,\ 41682 mode_yellow,Ryellow,Gyellow,Byellow,Hyellow,Syellow,Vyellow,\ 41683 mode_green,Rgreen,Ggreen,Bgreen,Hgreen,Sgreen,Vgreen,\ 41684 mode_cyan,Rcyan,Gcyan,Bcyan,Hcyan,Scyan,Vcyan,\ 41685 mode_blue,Rblue,Gblue,Bblue,Hblue,Sblue,Vblue,\ 41686 mode_magenta,Rmagenta,Gmagenta,Bmagenta,Hmagenta,Smagenta,Vmagenta,\ 41687 preview_mapping=${1-64} 41688 all_colors=dark,light,avg,red,yellow,green,cyan,blue,magenta 41689 41690 repeat $! l[$>] split_opacity l[0] 41691 to_rgb 41692 41693 # Define list of considered colors. 41694 colors,sep= 41695 repeat narg($all_colors) color=${arg\ 1+$>,$all_colors} if ${mode_$color} colors.=$sep$color sep=, fi done 41696 41697 # Find darkest, lightest and average colors. 41698 +srgb2lab channels. 0 darklight={"[I(#-2,xm,ym),I(#-2,xM,yM)]"} rm. 41699 dark={[$darklight][0,3]} light={[$darklight][3,3]} 41700 +r. 1,1,1,3,2 avg={^} rm. 41701 41702 # Find the nearest existing colors to "pure" colors. 41703 eval. "> 41704 begin( 41705 red = yellow = green = cyan = blue = magenta = [0,0,0]; 41706 best_red = best_yellow = best_green = best_cyan = best_blue = best_magenta = inf; 41707 test_color(color,tR,tG,tB) = ( 41708 val = norm([tR,tG,tB]-[R,G,B]); 41709 val<best_#color?(best_#color = val; color# = I(#-2)); 41710 ); 41711 ); 41712 test_color(red,255,0,0); 41713 test_color(yellow,255,255,0); 41714 test_color(green,0,255,0); 41715 test_color(cyan,0,255,255); 41716 test_color(blue,0,0,255); 41717 test_color(magenta,255,0,255); 41718 end( 41719 run(' red=',vtos(red), 41720 ' yellow=',vtos(yellow), 41721 ' green=',vtos(green), 41722 ' cyan=',vtos(cyan), 41723 ' blue=',vtos(blue), 41724 ' magenta=',vtos(magenta)) 41725 ); I" 41726 41727 # Compute color mapping. 41728 if narg($colors) 41729 l[] 41730 41731 # Define color correspondences. 41732 repeat narg($colors) 41733 color=${arg\ 1+$>,$colors} 41734 if ${mode_$color}==2 (${$color},${R$color},${G$color},${B$color},${H$color},${S$color},${V$color}) 41735 else (${$color},${$color},0,0,0) 41736 fi 41737 done 41738 a y permute yzcx 41739 s c,-3 srgb2rgb[0,1] rgb2hsv[0,1] /. 100 41740 f.. " 41741 Hs = i(#0,x,0,0,0); Ss = i(#0,x,0,0,1); Vs = i(#0,x,0,0,2); 41742 Hd = i0; Sd = i1; Vd = i2; 41743 DeltaH = Hd - Hs; 41744 alphaH = i(#2,x,0,0,0); 41745 H = abs(DeltaH)<abs(DeltaH - 360)? 41746 lerp(Hs,Hd,alphaH): 41747 lerp(Hs,Hd - 360,alphaH)%360; 41748 S = lerp(Ss,Sd,i(#2,x,0,0,1)); 41749 V = lerp(Vs,Vd,i(#2,x,0,0,2)); 41750 [ H,S,V ]" 41751 rm. 41752 hsv2rgb rgb2srgb 41753 repeat w color=${arg\ 1+$>,$colors} t_$color={I[$>]} done 41754 -. .. a c 41755 41756 # Create CLUT. 41757 if 0$_is_preview 33,33,33,4 else 63,63,63,4 fi 41758 f.. "I(#-1,round([i0,i1,i2]*(w#-1-1)/255))+=[i3,i4,i5,1];" 41759 s. c,-3 +max. 1 /[-3,-1] eq. 0 41760 inpaint_pde.. . rm[-3,-1] 41761 2,2,2,3,"[x,y,z]*255" ri. ..,3 +[-2,-1] 41762 nm clut 41763 endl 41764 41765 # Apply CLUT. 41766 if $clut map_clut.. . rm. c 0,255 fi 41767 fi 41768 41769 if $preview_mapping # Generate view of color mapping 41770 __px,__py,__ps={s=min(w,h);p=$preview_mapping;p==1?[0.5,0.5,80]:\ 41771 p==2?[0,0,48]:\ 41772 p==3?[1,0,48]:\ 41773 p==4?[0,1,64]:[1,1,64]} 41774 l[] 41775 repeat narg($all_colors) color=${arg\ 1+$>,$all_colors} (${$color}) done a y permute. yzcx 41776 s x r {s=round(max($__ps,16));[s,s]} 41777 repeat narg($all_colors) l[$>] 41778 color=${arg\ 1+$>,$all_colors} 41779 mode=${mode_$color} 41780 if $mode==2 41781 polygon 3,0,100%,100%,100%,100%,0,1,${t_$color} 41782 line 0,100%,100%,0,0.5,0xAAAAAAAA,255 line 0,100%,100%,0,0.5,0x55555555,0 41783 fi 41784 to {`uppercase(['$color'][0])`},0.5~,0.5~,50%,2,0.5 41785 to_rgba 41786 if $mode frame 1,1,0,0,0,255 frame 2,2,255 else frame 3,3,0,0,0,64 fi 41787 endl done 41788 append_tiles 3,3 41789 store __preview_mapping 41790 endl 41791 fi 41792 41793 endl a c endl done 41794 41795fx_tune_hsv : 41796 _fx_tune_hsv ${1-63},0 41797 41798fx_tune_hsv_preview : 41799 preview_mapping=$64 41800 repeat $! l[$>] 41801 gui_split_preview "_is_preview=1 _fx_tune_hsv $*",${-3--1} 41802 if $preview_mapping 41803 $__preview_mapping 41804 if narg($_preview_width) rr2d[0] $_preview_width,$_preview_height,0,2 fi 41805 s. c,-3 to_colormode.. {-3,s} 41806 j... ..,$__px~,$__py~,0,0,1,.,255 rm[-2,-1] 41807 fi 41808 endl done 41809 41810 d,l,a,r,y,g,c,b,m={[$1==2?2:0,$8==2?2:0,$15==2?2:0,$22==2?2:0,$29==2?2:0,$36==2?2:0,$43==2?2:0,$50==2?2:0,$57==2?2:0]} 41811 u "{$1}{$2,$3,$4}_"$d"{$5}_"$d"{$6}_"$d"{$7}_"$d\ 41812 "{$8}{$9,$10,$11}_"$l"{$12}_"$l"{$13}_"$l"{$14}_"$l\ 41813 "{$15}{$16,$17,$18}_"$a"{$19}_"$a"{$20}_"$a"{$21}_"$a\ 41814 "{$22}{$23,$24,$25}_"$r"{$26}_"$r"{$27}_"$r"{$28}_"$r\ 41815 "{$29}{$30,$31,$32}_"$y"{$33}_"$y"{$34}_"$y"{$35}_"$y\ 41816 "{$36}{$37,$38,$39}_"$g"{$40}_"$g"{$41}_"$g"{$42}_"$g\ 41817 "{$43}{$44,$45,$46}_"$c"{$47}_"$c"{$48}_"$c"{$49}_"$c\ 41818 "{$50}{$51,$52,$53}_"$b"{$54}_"$b"{$55}_"$b"{$56}_"$b\ 41819 "{$57}{$58,$59,$60}_"$m"{$61}_"$m"{$62}_"$m"{$63}_"$m\ 41820 "{$64}{$65}{$66,$67}" 41821 41822#@gui User-Defined : fx_custom_transform, fx_custom_transform 41823#@gui : Red - Green - Blue - Alpha = text{"i"} 41824#@gui : Red - Green - Blue = text{"i + 90*(x/w)*cos(i/10)"} 41825#@gui : Red = text{"i"} 41826#@gui : Green = text{"i"} 41827#@gui : Blue = text{"i"} 41828#@gui : Alpha = text{"i"} 41829#@gui : Value Normalization = choice("None","RGB","RGBA") 41830#@gui : sep = separator() 41831#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41832fx_custom_transform : 41833 to_rgba repeat $! 41834 f. "$1" 41835 s. c a[-4--2] c f.. "$2" 41836 s.. c f[-4] "$3" f... "$4" f.. "$5" f. "$6" 41837 if $7==0 a[-4--1] c c. 0,255 41838 elif $7==1 a[-4--2] c n.. 0,255 c. 0,255 a[-2,-1] c 41839 else a[-4--1] c n. 0,255 41840 fi 41841 mv. 0 done 41842 41843#@gui ____<b>Contours</b> 41844#------------------------ 41845 41846#@gui Convolve : fx_convolve, fx_convolve_preview(0) 41847#@gui : Kernel = choice("Custom","Average 3x3","Average 5x5","Average 7x7","Average 9x9","Prewitt-X","Prewitt-Y", 41848#@gui : "Sobel-X","Sobel-Y","Rotinv-X","Rotinv-Y","Laplacian","Robert Cross 1","Robert Cross 2","Impulses 5x5", 41849#@gui : "Impulses 7x7","Impulses 9x9") 41850#@gui : Boundary = choice(1,"Dirichlet","Neumann") 41851#@gui : sep = separator() 41852#@gui : note = note("<small><b>Note:</b> If parameter <i>Kernel</i> is set to <i>Custom</i>, it uses the custom 41853#@gui : convolution kernel defined below. Use commas and semicolons as separators for res. matrix columns and rows. 41854#@gui : </small>") 41855#@gui : Custom Kernel = text("0,1,0;1,-4,1;0,1,0") 41856#@gui : sep = separator() 41857#@gui : note = note("<small><b>Note:</b> Kernel multiplier is useful only when parameter <i>Value range</i> is set 41858#@gui : to <i>Cut</i>.</small>") 41859#@gui : Value Range = choice(1,"Cut","Normalize") 41860#@gui : Kernel Multiplier = float(1,0,50) 41861#@gui : sep = separator() 41862#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41863#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41864#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41865#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41866#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41867#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41868#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41869#@gui : sep = separator() 41870#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41871#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41872#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41873#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41874#@gui : sep = separator() 41875#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/06/06</i>.</small>") 41876fx_convolve : skip "${3=1}" 41877 ac "_fx_convolve $1,$2,\"$3\",${4--5}",$-4 41878 41879_fx_convolve : 41880 if $1 _fx_convolve$1[] else ($3) fi 41881 if !$4 *. $5 fi 41882 convolve[0--2] .,$2 41883 if $4 n 0,255 else c 0,255 fi 41884 rm. 41885 41886_fx_convolve1 : 3,3 f 1 normalize_sum # Average 3x3 41887_fx_convolve2 : 5,5 f 1 normalize_sum # Average 5x5 41888_fx_convolve3 : 7,7 f 1 normalize_sum # Average 7x7 41889_fx_convolve4 : 9,9 f 1 normalize_sum # Average 9x9 41890_fx_convolve5 : (1,0,-1;1,0,-1;1,0,-1) # Prewitt-X 41891_fx_convolve6 : (1,1,1;0,0,0;-1,-1,-1) # Prewitt-Y 41892_fx_convolve7 : (1,0,-1;2,0,-2;1,0,-1) # Sobel-X 41893_fx_convolve8 : (1,2,1;0,0,0;-1,-2,-1) # Sobel-Y 41894_fx_convolve9 : a={0.25*(2-sqrt(2))} b={0.5*(sqrt(2)-1)} ($a,0,-$a;$b,0,-$b;$a,0,-$a) # Rotinv-X 41895_fx_convolve10 : a={0.25*(2-sqrt(2))} b={0.5*(sqrt(2)-1)} ($a,$b,$a;0,0,0;-$a,-$b,-$a) # Rotinv-Y 41896_fx_convolve11 : (0,1,0;1,-4,1;0,1,0) # Laplacian 41897_fx_convolve12 : (1,0;0,-1) # Robert Cross1 41898_fx_convolve13 : (0,1;-1,0) # Robert Cross2 41899_fx_convolve14 : 3,3 f 1 r 7,7,1,1,4,0,0.5,0.5 autocrop normalize_sum # Impulse 5x5 41900_fx_convolve15 : 3,3 f 1 r 9,9,1,1,4,0,0.5,0.5 autocrop normalize_sum # Impulse 7x7 41901_fx_convolve16 : 3,3 f 1 r 11,11,1,1,4,0,0.5,0.5 autocrop normalize_sum # Impulse 9x9 41902 41903fx_convolve_preview : skip "${3=1}" 41904 gui_split_preview "fx_convolve $1,$2,\"$3\",${4--1}",${-3--1} 41905 41906#@gui Curvature : fx_curvature, fx_curvature_preview(0) 41907#@gui : Smoothness = float(2,0,10) 41908#@gui : Min Threshold = float(0,0,100) 41909#@gui : Max Threshold = float(100,0,100) 41910#@gui : Absolute Value = bool(0) 41911#@gui : Negative Colors = bool(0) 41912#@gui : sep = separator() 41913#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41914#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41915#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41916#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41917#@gui : sep = separator() 41918#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41919fx_curvature : 41920 repeat $! l[$>] split_opacity l[0] 41921 b $1 iee 41922 if $4 abs fi 41923 c $2%,$3% 41924 if $5 negate fi 41925 n 0,255 41926 endl a c endl done 41927 41928fx_curvature_preview : 41929 gui_split_preview "fx_curvature ${^0}",${-3--1} 41930 41931#@gui Difference of Gaussians : fx_dog, fx_dog_preview(1) 41932#@gui : 1st Variance = float(1.4,0,5) 41933#@gui : 2nd Variance = float(1.5,0,5) 41934#@gui : Threshold = float(0,0,49) 41935#@gui : Negative Colors = bool(0) 41936#@gui : Monochrome = bool(1) 41937#@gui : sep = separator() 41938#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41939#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41940#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41941#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41942#@gui : sep = separator() 41943#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41944fx_dog : 41945 dog $1%,$2% 41946 if $5 norm fi 41947 c $3%,{100-$3}% 41948 if $4 negate fi 41949 n 0,255 41950 41951fx_dog_preview : 41952 gui_split_preview "fx_dog ${^0}",${-3--1} 41953 41954#@gui Distance Transform : fx_distance, fx_distance_preview(0) 41955#@gui : Value = int(128,0,255) 41956#@gui : Metric = choice(2,"Chebyshev","Manhattan","Euclidean","Squared-Euclidean") 41957#@gui : Normalization = choice(2,"Cut","Normalize","Modulo") 41958#@gui : Modulo Value = int(32,1,255) 41959#@gui : sep = separator() 41960#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41961#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41962#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41963#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41964#@gui : sep = separator() 41965#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/07/04</i>.</small>") 41966fx_distance : 41967 repeat $! l[$>] split_opacity l[0] 41968 distance $1,$2 41969 if $3==0 c 0,255 41970 elif $3==1 n 0,255 41971 else % $4 n 0,255 41972 fi 41973 endl a c endl done 41974 41975fx_distance_preview : 41976 gui_split_preview "fx_distance ${^0}",${-3--1} 41977 41978#@gui Edges : fx_edges, fx_edges_preview(0) 41979#@gui : Smoothness = float(0,0,10) 41980#@gui : Threshold = float(15,0,50) 41981#@gui : Negative Colors = bool(0) 41982#@gui : sep = separator() 41983#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41984#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41985#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41986#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41987#@gui : sep = separator() 41988#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41989fx_edges : 41990 to_rgb b $1% edges $2% 41991 if $3 negate fi 41992 n 0,255 41993 41994fx_edges_preview : 41995 gui_split_preview "fx_edges ${^0}",${-3--1} 41996 41997#@gui Edges Offsets : fx_edge_offsets, fx_edge_offsets_preview(0) 41998#@gui : Smoothness = float(0,0,10) 41999#@gui : Threshold = float(15,0,50) 42000#@gui : Scale = int(4,0,32) 42001#@gui : Thickness = int(1,0,16) 42002#@gui : Negative Colors = bool(0) 42003#@gui : sep = separator() 42004#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42005#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42006#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42007#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42008#@gui : sep = separator() 42009#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42010fx_edge_offsets : 42011 repeat $! 42012 os={s} 42013 b. $1% gradient_norm. >=. $2% skeleton. 0 distance. 1 round. 1 %. $3 >=. {max(1,$3-$4)} 42014 if !$5 negate. fi 42015 n. 0,255 to_colormode. $os 42016 mv. 0 done 42017 42018fx_edge_offsets_preview : 42019 gui_split_preview "fx_edge_offsets ${^0}",${-3--1} 42020 42021#@gui Extract Foreground [Interactive] : fx_extract_foreground, gui_no_preview 42022#@gui : Feathering = _float(0,0,4) 42023#@gui : Dilation = int(0,-32,32) 42024#@gui : Output Mode = choice{3,"RGBA Image (Full-Transparency / 1 Layer)","RGBA Image (Updatable / 1 Layer)", 42025#@gui : "RGB Image + Binary Mask (2 Layers)","RGBA Foreground + Background (2 Layers)"} 42026#@gui : View Resolution = _choice{1,"Small (Faster)","Medium","High (Slower)","Very High (Even Slower)"} 42027#@gui : sep = separator() 42028#@gui : note = note{"<small><b>Description:</b>\n 42029#@gui : This filter allows to quickly extract foreground objects from background in opaque RGB images. 42030#@gui : Click on the <i>Apply</i> or <i>OK</i> buttons below to open the interactive window and start adding 42031#@gui : foreground and background control points. When you're done, exit the interactive window: your extracted 42032#@gui : foreground will be transferred back to the host software.\n\n 42033#@gui : If you are not satisfied with the result, click on <i>Apply</i> once again to modify your control points 42034#@gui : defined previously. To remove all control points, click on the <i>Reset</i> button above. 42035#@gui : </small>"} 42036#@gui : Last Image Size = value(0,0) 42037#@gui : Control Points = value(-1) 42038#@gui : sep = separator() 42039#@gui : note = note{"<small><b>Interactions:</b>\n 42040#@gui : Use the following actions in the interactive window to build your extraction mask :\n\n 42041#@gui : - <b>Left mouse button</b> or key <b>F</b> create a new <b>foreground</b> control point 42042#@gui : (or move an existing one).\n 42043#@gui : - <b>Right mouse button</b> or key <b>B</b> create a new <b>background</b> control point 42044#@gui : (or move an existing one).\n 42045#@gui : - <b>Mouse wheel</b>, or keys <b>CTRL+arrows UP/DOWN</b> zoom view in/out.\n 42046#@gui : - Key <b>SPACE</b> updates the extraction mask.\n 42047#@gui : - Key <b>TAB</b> toggles background view modes.\n 42048#@gui : - Key <b>M</b> toggles marker view modes.\n 42049#@gui : - Key <b>BACKSPACE</b> deletes the last control point added.\n 42050#@gui : - Key <b>PAGE UP</b> increases background opacity.\n 42051#@gui : - Key <b>PAGE DOWN</b> decreases background opacity.\n 42052#@gui : - Keys <b>CTRL+D</b> increase window size.\n 42053#@gui : - Keys <b>CTRL+C</b> decrease window size.\n 42054#@gui : - Keys <b>CTRL+R</b> reset window size.\n 42055#@gui : - Keys <b>ESC</b>, <b>Q</b> or <b>ENTER</b> exit the interactive window. 42056#@gui : </small>"} 42057#@gui : sep = separator() 42058#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/29/09</i>.</small>") 42059fx_extract_foreground : 42060 if !$! return fi 42061 resolution={arg(1+$3,512,1024,2048,0)} 42062 repeat $! l[$<] 42063 nm=${-gui_layer_name} 42064 nm "[G"{`39`}"MIC] Interactive Foreground Extraction" 42065 if [$6][0]==-1" || "[$5]!=[w,h] _gui_control_points= else _gui_control_points=$6 fi 42066 status=${x_segment\ $resolution} 42067 sh 3 b. $1% if $2>0 dilate. {1+2*$2} elif $2<0 erode. {1-2*$2} fi 42068 rm. 42069 if $3==1 sh 3 max. 1 rm. 42070 elif $3==2 s c,-3 r. 100%,100%,1,4 rv nm[0] name(Mask) nm[1] name($nm) 42071 elif $3==3 42072 . 42073 sh.. 0,2 +channels... 3,3 >=. 3 *[-2,-1] rm. 42074 sh. 0,2 +channels.. 3,3 <=. {255-3} *[-2,-1] rm. 42075 sh. 3 *. -1 +. 255 rm. 42076 gui_autocrop_layers[0] 42077 pos0=${gui_layer_pos[0]} pos1=${gui_layer_pos[1]} 42078 nm[0] name($nm" [foreground]"),pos($pos0) 42079 nm[1] name($nm" [background]"),pos($pos1) 42080 fi 42081 endl done 42082 if narg($status)>=4 u \{$1\}\{$2\}\{$3\}\{$4\}\{{w},{h}\}\{$status\} else u "" fi 42083 42084#@gui Gradient Norm : fx_gradient_norm, fx_gradient_norm_preview(0) 42085#@gui : Smoothness = float(0,0,10) 42086#@gui : Linearity = float(0.5,0,1.5) 42087#@gui : Min Threshold = float(0,0,100) 42088#@gui : Max Threshold = float(100,0,100) 42089#@gui : Negative Colors = bool(0) 42090#@gui : sep = separator() 42091#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42092#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42093#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42094#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42095#@gui : sep = separator() 42096#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42097fx_gradient_norm : 42098 b $1 gradient_norm ^ $2 42099 c $3%,$4% 42100 if $5 negate fi 42101 n 0,255 42102 42103fx_gradient_norm_preview : 42104 gui_split_preview "fx_gradient_norm ${^0}",${-3--1} 42105 42106#@gui Gradient RGB : fx_gradient2rgb, fx_gradient2rgb_preview(0) 42107#@gui : Smoothness = float(0,0,10) 42108#@gui : Min Threshold = float(0,0,100) 42109#@gui : Max Threshold = float(100,0,100) 42110#@gui : Orientation Only = bool(0) 42111#@gui : Negative Colors = bool(0) 42112#@gui : sep = separator() 42113#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42114#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42115#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42116#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42117#@gui : sep = separator() 42118#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42119fx_gradient2rgb : 42120 b $1 gradient2rgb $4 42121 c $2%,$3% 42122 if $5 negate fi 42123 n 0,255 42124 42125fx_gradient2rgb_preview : 42126 gui_split_preview "fx_gradient2rgb ${^0}",${-3--1} 42127 42128#@gui Isophotes : fx_isophotes, fx_isophotes_preview(0) 42129#@gui : Levels = int(8,1,256) 42130#@gui : Smoothness = float(0,0,5) 42131#@gui : Filling = choice(1,"Transparent","Colors") 42132#@gui : sep = separator() 42133#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42134#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42135#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42136#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42137#@gui : sep = separator() 42138#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42139fx_isophotes : 42140 if $3 42141 topographic_map $1,$2 42142 else 42143 b $2 isophotes $1 42144 fi 42145 42146fx_isophotes_preview : 42147 gui_split_preview "fx_isophotes ${^0}",${-3--1} 42148 42149#@gui Laplacian : fx_laplacian, fx_laplacian_preview(0) 42150#@gui : Smoothness = float(0,0,10) 42151#@gui : Min Threshold = float(0,0,100) 42152#@gui : Max Threshold = float(100,0,100) 42153#@gui : Absolute Value = bool(0) 42154#@gui : Negative Colors = bool(0) 42155#@gui : sep = separator() 42156#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42157#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42158#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42159#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42160#@gui : sep = separator() 42161#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42162fx_laplacian : 42163 b $1 laplacian 42164 if $4 abs fi 42165 c $2%,$3% 42166 if $5 negate fi 42167 n 0,255 42168 42169fx_laplacian_preview : 42170 gui_split_preview "fx_laplacian ${^0}",${-3--1} 42171 42172#@gui Local Orientation : fx_local_orientation, fx_local_orientation_preview(1) 42173#@gui : Smoothness = float(0,0,5) 42174#@gui : Min Threshold = float(0,0,100) 42175#@gui : Max Threshold = float(100,0,100) 42176#@gui : Negative Colors = bool(0) 42177#@gui : sep = separator() 42178#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42179#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42180#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42181#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42182#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42183#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42184#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42185#@gui : sep = separator() 42186#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42187#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42188#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42189#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42190#@gui : sep = separator() 42191#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42192_fx_local_orientation : 42193 repeat $! l[$>] split_opacity l[0] 42194 b $1% gradient_orientation 2 complex2polar rm[0--1:2] 42195 c $2%,$3% 42196 if $4 negate fi 42197 n 0,255 42198 endl a c endl done 42199 42200fx_local_orientation : 42201 ac "_fx_local_orientation $1,$2,$3,$4",$5,2 42202 42203fx_local_orientation_preview : 42204 gui_split_preview "fx_local_orientation ${^0}",${-3--1} 42205 42206#@gui Morphological Filter : fx_morphological, fx_morphological_preview(0) 42207#@gui : Action = choice{"Erosion","Dilation","Opening","Closing","Original - Erosion","Dilation - Original", 42208#@gui : "Original - Opening","Closing - Original","Original - (Opening + Closing)/2","Closing - Opening"} 42209#@gui : Kernel = choice(0,"Square","Octagonal","Circular","Custom") 42210#@gui : Size = int(5,2,60) 42211#@gui : note = note("<small>Parameter <i>Size</i> is inactive for <i>Custom</i> kernel.</small>") 42212#@gui : Custom Kernel = text("1,0,1; 0,1,0; 1,0,1") 42213#@gui : Negative = bool() 42214#@gui : Process Transparency = bool(0) 42215#@gui : sep = separator() 42216#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42217#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42218#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42219#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42220#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42221#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42222#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42223#@gui : Value Action = choice("None","Cut","Stretch") 42224#@gui : sep = separator() 42225#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42226#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42227#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42228#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42229#@gui : sep = separator() 42230#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/22/06</i>.</small>") 42231fx_morphological : 42232 ac "_fx_morphological ${1-3},\"$4\",${5-6}",$7,$8 42233 42234fx_morphological_preview : 42235 gui_split_preview "fx_morphological ${1-3},\"$4\",${5--1}",${-3--1} 42236 if $2==3 42237 ('"$4"') f. "(i>=_'0' && i<=_'9') || i==_',' || i==_';'?i:-1" 42238 discard. -1 ({t}) rr2d. {0,max(24,w/6)},{0,max(24,h/6)},0,1 >. 0 *. 255 42239 to_rgba. frame. 1,1,0,0,0,0,255 frame. 1,1,255 frame. 1,1,0,0,0,0,255 42240 j[^-1] .,2,2,0,0,0.75 rm. 42241 else 42242 fi 42243 42244_fx_morphological : 42245 ('"$4"') f. "(i>=_'0' && i<=_'9') || i==_',' || i==_';'?i:-1" discard. -1 ckernel={t} rm. 42246 if $2==0 m "my_erode: erode $""1" m "my_dilate: dilate $""1" 42247 elif $2==1 m "my_erode: erode_oct $""1" m "my_dilate: dilate_oct $""1" 42248 elif $2==2 m "my_erode: erode_circ $""1" m "my_dilate: dilate_circ $""1" 42249 else 42250 m "my_erode : ("$ckernel") erode[^-1] . rm." 42251 m "my_dilate : ("$ckernel") dilate[^-1] . rm." 42252 fi 42253 # Erosion 42254 if $1==0 m "my_action : my_erode $3" 42255 # Dilation 42256 elif $1==1 m "my_action : my_dilate $3" 42257 # Opening 42258 elif $1==2 m "my_action : my_erode $3 my_dilate $3" 42259 # Closing 42260 elif $1==3 m "my_action : my_dilate $3 my_erode $3" 42261 # Original - Erosion 42262 elif $1==4 m "my_action : +my_erode $3 -" 42263 # Dilation - Original 42264 elif $1==5 m "my_action : +my_dilate $3 rv -" 42265 # Original - Opening 42266 elif $1==6 m "my_action : +my_erode $3 my_dilate. $3 -" 42267 # Closing - Original 42268 elif $1==7 m "my_action : +my_dilate $3 my_erode. $3 rv -" 42269 # Original - (Opening + Closing)/2 42270 elif $1==8 m "my_action : +my_erode $3 my_dilate. $3 +my_dilate.. $3 my_erode. $3 +[-2,-1] /. 2 -" 42271 # Closing - Opening 42272 else m "my_action : +my_erode $3 my_dilate. $3 my_dilate.. $3 my_erode.. $3 -" 42273 fi 42274 repeat $! l[$>] 42275 if !$6 split_opacity fi 42276 my_action[0] 42277 a c 42278 endl done 42279 if $5 repeat $! l[$>] split_opacity negate[0] a c endl done fi 42280 um my_erode,my_dilate,my_action 42281 42282#@gui Segmentation : fx_segment_watershed, fx_segment_watershed_preview(0) 42283#@gui : Edge Threshold = float(2,0,15) 42284#@gui : Smoothness = float(1,0,5) 42285#@gui : sep = separator() 42286#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42287#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42288#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42289#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42290#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42291#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42292#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42293#@gui : Value Action = choice("None","Cut","Normalize") 42294#@gui : sep = separator() 42295#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42296#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42297#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42298#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42299#@gui : sep = separator() 42300#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42301fx_segment_watershed : skip ${4=1} 42302 ac "b $2 segment_watershed $1",$3,$4 42303 42304fx_segment_watershed_preview : 42305 gui_split_preview "fx_segment_watershed ${^0}",${-3--1} 42306 42307#@gui Skeleton : fx_skeleton, fx_skeleton_preview(1) 42308#@gui : Method = choice{"Distance (Fast)","Thinning (Slow)"} 42309#@gui : Smoothness = float(0,0,10) 42310#@gui : sep = separator() 42311#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42312#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42313#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42314#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42315#@gui : sep = separator() 42316#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/07/04</i>.</small>") 42317fx_skeleton : 42318 remove_opacity 42319 b $2% >= 50% 42320 if $1 thinning 1 42321 else 42322 distance 0 sharpen 1e10 >= 100% 42323 repeat $! +erode[$>] 2 -[$>,-1] done 42324 fi 42325 * 255 42326 42327fx_skeleton_preview : 42328 gui_split_preview "fx_skeleton ${^0}",${-3--1} 42329 42330#@gui Super-Pixels : fx_superpixels, fx_superpixels_preview(0) 42331#@gui : Size = int(16,4,64) 42332#@gui : Regularity = float(10,0,128) 42333#@gui : Iterations = int(5,1,16) 42334#@gui : Colors = choice(1,"Random","Average") 42335#@gui : Border Opacity = float(1,0,1) 42336#@gui : Border Color = color(0,0,0,255) 42337#@gui : sep = separator() 42338#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42339#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42340#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42341#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42342#@gui : sep = separator() 42343#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/11/16</i>.</small>") 42344fx_superpixels : 42345 repeat $! l[$>] 42346 +srgb2lab slic. ${1-3} 42347 if $4 +blend shapeaverage else +map. 2,2 fi 42348 if $5 f[1] "i!=j(1,0) || i!=j(0,1)" [0],[0],1,4 fc. ${6-9} to_rgba.. j.. .,0,0,0,0,$5,... k.. 42349 else k. 42350 fi 42351 endl done 42352 42353fx_superpixels_preview : 42354 gui_split_preview "fx_superpixels ${^0}",${-3--1} 42355 42356#@gui Thin Edges : fx_thin_edges, fx_thin_edges_preview(0) 42357#@gui : Smoothness = float(0,0,10) 42358#@gui : Threshold = float(15,0,50) 42359#@gui : Negative Colors = bool(0) 42360#@gui : sep = separator() 42361#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42362#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42363#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42364#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42365#@gui : sep = separator() 42366#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42367fx_thin_edges : 42368 b $1% gradient_norm >= $2% thinning 1 42369 if !$3 negate fi 42370 n 0,255 42371 42372fx_thin_edges_preview : 42373 gui_split_preview "fx_thin_edges ${^0}",${-3--1} 42374 42375 42376#@gui ____<b>Deformations</b> 42377#---------------------------- 42378 42379#@gui Breaks : fx_breaks,fx_breaks(0) 42380#@gui : Type = choice("Flat","Relief") 42381#@gui : Amplitude = float(30,0,300) 42382#@gui : Frequency (%) = float(30,0,100) 42383#@gui : Smoothness = float(0.5,0,10) 42384#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42385#@gui : sep = separator() 42386#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/09/09</i>.</small>") 42387fx_breaks : 42388 repeat $! l[$>] 42389 if !$5 to_a fi 42390 100%,100%,1,1,"u<($3%)^6" 42391 if $1 # Wavy 42392 distance. 1 sharpen. 100000 neq. 0 distance. 1 b. $4 g. xy a[-2,-1] c 42393 else # Flat 42394 delaunay. 0 label_fg. 0,1 {1+iM},1,1,2 rand. -30,30 point. 0 map.. . rm. 42395 fi 42396 n. -$2,$2 warp[0] .,1,1,$5 rm. 42397 endl done 42398 42399#@gui Cartesian Transform : fx_custom_deformation, fx_custom_deformation(1) 42400#@gui : X-Warping = text{"(w+h)/20 * cos(y*20/h)"} 42401#@gui : Y-Warping = text{"(w+h)/20 * sin(x*20/w)"} 42402#@gui : Relative Warping = bool(1) 42403#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 42404#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42405#@gui : sep = separator() 42406#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42407fx_custom_deformation : 42408 if !$5 to_a fi 42409 repeat $! 42410 +norm. . f.. "$1" f. "$2" 42411 a[-2,-1] c warp.. .,$3,$4,$5,1 rm. 42412 mv. 0 done 42413 42414#@gui Circle Transform : fx_circle_transform, fx_circle_transform_preview(1) 42415#@gui : Center (%) = point(50,50,0,1) 42416#@gui : Radius = point(75,50,0,1) 42417#@gui : X-Scale = float(-2,-16,16) 42418#@gui : Y-Scale = float(-2,-16,16) 42419#@gui : Symmetry = choice("None","Inside","Outside") 42420#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 42421#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42422#@gui : Preview Reference Circle = bool(1) 42423#@gui : sep = separator() 42424#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/08/01</i>.</small>") 42425fx_circle_transform : 42426 repeat $! l[$>] to_rgba 42427 r={dx=($3-$1)*(w-1)%;dy=($4-$2)*(h-1)%;norm(dx,dy)} 42428 if $7==0 cond="i(X,Y,z,c,$8,$9)" 42429 elif $7==1 cond="if(N<"$r",i(X,Y,z,c,$8,$9),i)" 42430 else cond="if(N>"$r",i(X,Y,z,c,$8,$9),i)" 42431 fi 42432 f "U = x - w*$1%; 42433 V = y - h*$2%; 42434 N = sqrt(U*U + V*V); 42435 Nr = N - "$r"; 42436 X = x + $5*Nr*U/N; 42437 Y = y + $6*Nr*V/N; 42438 "$cond 42439 endl done 42440 42441fx_circle_transform_preview : 42442 fx_circle_transform $* 42443 if $10 42444 rr2d ${-gui_preview_wh},0,1 42445 repeat $! l[$>] 42446 x0,y0={[$1,$2]*([w,h]-1)%} 42447 r={dx=($3-$1)*(w-1)%;dy=($4-$2)*(h-1)%;norm(dx,dy)} 42448 circle $x0,$y0,{$r-1},1,0xFFFFFFFF,0,0,0,255 42449 circle $x0,$y0,{$r+1},1,0xFFFFFFFF,0,0,0,255 42450 circle $x0,$y0,$r,1,0xFFFFFFFF,0,255,0,255 42451 endl done 42452 fi 42453 42454#@gui Conformal Maps : fx_conformal_maps, fx_conformal_maps_preview(1) 42455#@gui : Mapping = choice{8,"Custom Formula","z","(z+1)/(z-1)","cos(z)","sin(z)","tan(z)","exp(z)","log(z)", 42456#@gui : "Dipole: 1/(4*z^2-1)","Star: -5*(z^3/3-z/4)/2"} 42457#@gui : Exponent (Real) = float(1,-16,16) 42458#@gui : Exponent (Imaginary) = float(0,-16,16) 42459#@gui : Custom Formula = text{1,"((1.1 + i*z/6)/(1.04 - i*z/6))^6.2"} 42460#@gui : sep = separator() 42461#@gui : Zoom = float(0,-4,4) 42462#@gui : Angle = float(0,-180,180) 42463#@gui : Aspect Ratio = float(0,-1,1) 42464#@gui : X-Shift = float(0,-5,5) 42465#@gui : Y-Shift = float(0,-5,5) 42466#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42467#@gui : Anti-Aliasing = int(0,0,3) 42468#@gui : sep = separator() 42469#@gui : Specify Different Output Size = _bool(0) 42470#@gui : Output Width = _text("1024") 42471#@gui : Output Height = _text("1024") 42472#@gui : sep = separator() 42473#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/15/02</i>.</small>") 42474fx_conformal_maps : 42475 to_a 42476 expr0="$4" 42477 expr1="z" 42478 expr2="(z+1)/(z-1)" 42479 expr3="cos(z)" 42480 expr4="sin(z)" 42481 expr5="tan(z)" 42482 expr6="exp(z)" 42483 expr7="log(z)" 42484 expr8="1/(4*z^2-1)" 42485 expr9="-5*(z^3/3-z/4)/2" 42486 42487 ('${expr$1}') 42488 replace_str. "*","**" 42489 replace_str. "/","//" 42490 replace_str. "^","^^" 42491 replace_str. "exp(","cexp(" 42492 replace_str. "log(","clog(" 42493 replace_str. "cos(","ccos(" 42494 replace_str. "sin(","csin(" 42495 replace_str. "tan(","ctan(" 42496 expr={t} 42497 rm. 42498 42499 repeat $! l[$>] 42500 wh={$12?[$13,$14]:[w,h]} 42501 {(1+$11)*[$wh]},1,100% 42502 f. "begin( 42503 ccos(z) = (iz = [ -z[1],z[0] ]; (cexp(iz) + cexp(-iz)/2)); 42504 csin(z) = (iz = [ -z[1],z[0] ]; (cexp(iz) - cexp(-iz)/2)); 42505 ctan(z) = csin(z)//ccos(z); 42506 boundary = $10; 42507 interpolation = 1; 42508 const f = max(w,h); 42509 const f0 = max(w#0,h#0); 42510 i = [0,1]; 42511 ); 42512 z = (2*[ x,y ] - [ w,h ])/f; 42513 z = rot(-$6°)*z; 42514 z-= [ $8, $9 ]; 42515 z/=[ 10^($5 + $7), 10^$5 ]; 42516 z = ("$expr"); 42517 if ($1, z = z^^[$2,$3]); 42518 z = rot($6°)*z; 42519 z = 0.5*(f0*z + [w#0,h#0]); 42520 I(#0,z)" 42521 r. $wh,1,100%,2 42522 rm.. 42523 endl done 42524 42525fx_conformal_maps_preview : 42526 fx_conformal_maps ${1-3},"$4",${5-11},0,0,0 42527 42528#@gui Crease : fx_crease,fx_crease(0) 42529#@gui : Amplitude = float(30,0,300) 42530#@gui : Frequency (%) = float(10,0,100) 42531#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42532#@gui : sep = separator() 42533#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/22</i>.</small>") 42534fx_crease : 42535 repeat $! l[$>] 42536 if !$3 to_a fi 42537 2,2,1,2,{"const w1 = w#-1-1; const h1 = h#-1 - 1; [ 0,w1,0,w1,0,0,h1,h1 ];"} 42538 r. {0,D=$2*[w,h]%;[max(D[0],1),max(D[1],1)]},1,2,3 noise. $1,1 42539 r. ..,..,1,2,3 warp.. .,0,1,$3 rm. 42540 endl done 42541 42542#@gui Distort Lens : fx_distort_lens, fx_distort_lens(1) 42543#@gui : Amplitude = float(0.1,-1,1) 42544#@gui : Aspect Ratio = float(0,-2,2) 42545#@gui : Zoom = float(0,-4,4) 42546#@gui : Center (%) = point(50,50,0,1) 42547#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 42548#@gui : sep = separator() 42549#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/18/02</i>.</small>") 42550fx_distort_lens : 42551 if !$6 to_a fi 42552 undistort ${1-3},$4%,$5%,$6 42553 42554#@gui Drop Water : fx_drop_water, fx_drop_water_preview(1) 42555#@gui : note = note("<small><b>Shape geometry:</b></small>") 42556#@gui : Shapes = choice("Procedural","Opaque Regions on Top Layer") 42557#@gui : Density = float(20,0,100) 42558#@gui : Radius = float(2,0,5) 42559#@gui : Variability = float(80,0,100) 42560#@gui : Random Seed = int(0,0,16384) 42561#@gui : note = note("<small>Parameters <i>Density</i>, <i>Radius</i>, <i>Variability</i> and <i>Random seed</i> 42562#@gui : are used only in <i>Procedural shapes</i> mode.</small>") 42563#@gui : sep = separator() 42564#@gui : note = note("<small><b>Light parameters:</b></small>") 42565#@gui : Refraction = float(3,0,20) 42566#@gui : Light Angle = float(35,0,360) 42567#@gui : Specular Size = float(10,0,100) 42568#@gui : Specular Intensity = float(1,0,1) 42569#@gui : Specular Centering = float(0.5,0,1) 42570#@gui : sep = separator() 42571#@gui : note = note("<small><b>Shadow parameters:</b></small>") 42572#@gui : Shadow Size = float(0.25,0,3) 42573#@gui : Shadow Intensity = float(0.5,0,1) 42574#@gui : Shadow Smoothness = float(0.75,0,3) 42575#@gui : Diffuse Shadow = float(0.05,0,3) 42576#@gui : sep = separator() 42577#@gui : Smoothness = float(0.15,0,3) 42578#@gui : Output as Separate Layers = _bool(1) 42579#@gui : sep = separator() 42580#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/21/07</i>.</small>") 42581fx_drop_water : 42582 N={$!-$1} 42583 if $N<=0 error "At least two layers are required in this mode." fi 42584 42585 repeat $N l[{$!-$>-1}] nm0={n} nm=${-gui_layer_name} 42586 nm img 42587 42588 # Create binary shapes (i.e. opacity map). 42589 srand $5 42590 if $1 # Shape from top layer. 42591 pass[0] 0 to_a. channels. 100% >=. 50% 42592 r. [0],[0],1,1,0,0,0.5,0.5 42593 else # Procedural shape. 42594 100%,100% 42595 rmin={max(0.1,$3*(1-$4%))} rmax={max(0.1,$3)} 42596 repeat 10 42597 100%,100% 42598 random3d {max(1,$2)} *3d. {-2,w},{-2,h},0 42599 j3d.. .,0,0,0,1,1,0,0 rm. 42600 b. {$rmin+($rmax-$rmin)*$>/9}%,0,1 42601 j.. .,0,0,0,0,0.5 rm. 42602 done 42603 >=. 10% 42604 fi 42605 nm. shape 42606 42607 # Create elevation map. 42608 +b[shape] 1% n. 0,30 42609 nm. elevation 42610 42611 # Warp image. 42612 g[elevation] xy a[-2,-1] c nm. grad 42613 +*[grad] {grad,$6*max(w,h)/100} *. [shape] b. $15% 42614 +warp[img] .,1,1,1 rm.. nm. refraction 42615 42616 # Compute specular spots. 42617 +*[grad] -1 100%,100%,1,1,1 a[-2,-1] c orientation. # 3D normal map. 42618 a={$7*pi/180} ca={-cos($a)} sa={-sin($a)} 42619 mix_channels. ({(1-$10)*$ca},{(1-$10)*$sa},1) c. {100-$8}%,100% n. 0,1 42620 *. [shape] nm. spots 42621 42622 # Compute ambiant light (gradient). 42623 mix_channels[grad] ($ca,$sa) 42624 n[grad] 0,1 *[grad] [shape] 42625 42626 # Drop shadow. 42627 +shift[shape] {-$11*$ca}%,{-$11*$sa}%,0,0,1 42628 -. [shape] >=. 1 b. $13% n. 0,1 42629 nm. shadow 42630 b[shape] $14% n. 0,1 # Add diffuse shadow around each drop. 42631 42632 # Prepare layers for output. 42633 nm[img] name($nm) 42634 42635 *[shadow] 255 channels[shadow] -1,0 mv[shadow] 1 42636 nm[shadow] name($nm" [shadow]"),mode(alpha),opacity({$12*100}) 42637 42638 to_a[refraction] sh[refraction] 100% +b[shape] $15% *[-2,-1] rm. 42639 mv[refraction] 2 42640 nm[refraction] name($nm" [refraction]"),mode(alpha) 42641 42642 channels[spots] -1,0 sh[spots] 0 f. 1 rm. *[spots] 255 42643 nm[spots] name($nm" [specular spots]"),mode(alpha),opacity({$9*100}) 42644 42645 rv[shape,grad] a[grad,shape] c *[grad] 255 b[grad] $15% 42646 nm[grad] name($nm" [gradient]"),mode(grainmerge) 42647 42648 rv 42649 if !$16 gui_merge_layers nm $nm0 fi 42650 endl done 42651 if $1 rm[0] fi 42652 42653fx_drop_water_preview : 42654 N={$!-$1} 42655 if $N<=0 gui_warning_preview "At least two layers are required in this mode." return fi 42656 if $1 42657 repeat $N l[{$!-$>-1}] 42658 pass[0] 0 mv. 0 42659 fx_drop_water $* gui_merge_layers 42660 endl done 42661 rm[0] 42662 else 42663 repeat $! l[$>] 42664 fx_drop_water $* gui_merge_layers 42665 endl done 42666 fi 42667 42668#@gui Equirectangular to Nadir-Zenith : fx_equirectangular2nadirzenith, fx_equirectangular2nadirzenith(1) 42669#@gui : Mode = choice{"to Nadir / Zenith","to Equirectangular"} 42670#@gui : sep = separator() 42671#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/29/12</i>.</small>") 42672fx_equirectangular2nadirzenith : 42673 if $1 nadirzenith2equirectangular else equirectangular2nadirzenith fi 42674 42675#@gui Euclidean - Polar : fx_euclidean2polar, fx_euclidean2polar(1) 42676#@gui : Center (%) = point(50,50,0,1) 42677#@gui : Stretch Factor = float(1,0.1,10) 42678#@gui : Boundary = choice(1,"Transparent","Nearest","Periodic","Mirror") 42679#@gui : Inverse Transform = bool(0) 42680#@gui : sep = separator() 42681#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42682fx_euclidean2polar : 42683 if !$4 to_a fi 42684 if $5 polar2euclidean $1%,$2%,$3,$4 else euclidean2polar $1%,$2%,$3,$4 fi 42685 42686#@gui Fish-Eye : fisheye, fisheye(1) 42687#@gui : Center (%) = point(50,50,0,1,255) 42688#@gui : Radius = float(70,0,100) 42689#@gui : Amplitude = float(1,0,2) 42690#@gui : sep = separator() 42691#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42692 42693#@gui Flower : fx_flower, fx_flower_preview(1) 42694#@gui : Center (%) = point(50,50,0,1) 42695#@gui : Amplitude / Angle = point(75,50,0,1) 42696#@gui : Petals = int(6,2,20) 42697#@gui : Offset (%) = float(0,0,100) 42698#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42699#@gui : sep = separator() 42700#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42701fx_flower : 42702 if !$7 to_a fi 42703 amplitude,angle={dx=$3-$1;dy=$4-$2;[norm(dx,dy),-atan2(dy,dx)*180/pi]} 42704 flower $amplitude,$5,$6%,$angle,$1%,$2%,$7 42705 42706fx_flower_preview : 42707 fx_flower $* 42708 line $1%,$2%,$3%,$4%,1,0xF0F0F0F0,0 42709 line $1%,$2%,$3%,$4%,1,0x0F0F0F0F,255 42710 42711#@gui Kaleidoscope [Blended] : fx_rotoidoscope, fx_rotoidoscope(1) 42712#@gui : Center (%) = point(50,50) 42713#@gui : Angular Tiles = int(10,1,72) 42714#@gui : Smoothness = float(0.5,0,5) 42715#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42716#@gui : sep = separator() 42717#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42718fx_rotoidoscope : 42719 if !$5 to_a fi 42720 rotoidoscope $1%,$2%,$3,$4%,$5 42721 42722#@gui Kaleidoscope [Polar] : fx_kaleidoscope, fx_kaleidoscope(1) 42723#@gui : Center (%) = point(50,50) 42724#@gui : X-Offset (%) = float(0,0,100) 42725#@gui : Y-Offset (%) = float(0,0,100) 42726#@gui : Radius Cut = float(100,0,100) 42727#@gui : Angle Cut = float(10,0,100) 42728#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42729#@gui : sep = separator() 42730#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42731fx_kaleidoscope : 42732 if !$7 to_a fi 42733 shift $3%,$4%,0,0,2 kaleidoscope $1%,$2%,$5,$6,$7 42734 42735#@gui Kaleidoscope [Symmetry] : fx_symmetrizoscope, fx_symmetrizoscope(1) 42736#@gui : Iterations = int(4,1,32) 42737#@gui : Angle = float(0,0,360) 42738#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42739#@gui : Symmetry Sides = choice("Backward","Forward","Swap") 42740#@gui : sep = separator() 42741#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/07/01</i>.</small>") 42742fx_symmetrizoscope : 42743 if !$3 to_a fi 42744 repeat $1 42745 ang={$2+180*$>/max(1,$1-1)} 42746 symmetrize 50%,50%,$ang,$3,0,{if($4!=2,$4,$>%2)} 42747 done 42748 42749#@gui Morph [Interactive] : fx_morph_interactive, fx_morph_interactive_preview 42750#@gui : Number of Frames = int(16,3,1024) 42751#@gui : Preview Precision = choice{2,"Coarsest (faster)","Coarse","Normal","Fine","Finest (slower)"} 42752#@gui : Keypoints = value(-1) 42753#@gui : sep = separator() 42754#@gui : note = note{"<b>Instructions:</b>"} 42755#@gui : note = note{" 42756#@gui : Use mouse buttons to add/move/remove correspondence keypoints over the interactive window that will appear, 42757#@gui : in order to create the morphing.\n\n 42758#@gui : <span color="#EE5500"><b>Source/target window:</b></span>\n\n 42759#@gui : - <b>Left mouse button</b>: Add new keypoint on current image and move it on the other one.\n 42760#@gui : - <b>Right mouse button</b>: Add/move keypoint on current image.\n 42761#@gui : - Key <b>DELETE</b> or <b>middle mouse button</b>: Delete keypoint.\n 42762#@gui : - Key <b>SPACE</b> or <b>mouse wheel</b>: Toggle source/target.\n\n 42763#@gui : <span color="#EE5500"><b>In-between window:</b></span>\n\n 42764#@gui : - <b>Mouse wheel</b>: Change morphing time, from 0 to 1.\n 42765#@gui : - <b>Left mouse button</b>: Reset morphing time to 0.5.\n\n 42766#@gui : <span color="#EE5500"><b>Both windows:</b></span>\n\n 42767#@gui : - Key <b>TAB</b>: Change keypoint radius.\n 42768#@gui : - Key <b>ENTER</b>: Play/stop in-between animation.\n 42769#@gui : - Key <b>R</b>: Reset keypoints.\n 42770#@gui : - Key <b>K</b>: Show/hide keypoints.\n 42771#@gui : - Keys <b>ESC</b> or <b>Q</b>: Process fullres and exit. 42772#@gui : "} 42773#@gui : sep = separator() 42774#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/04/16</i>.</small>") 42775fx_morph_interactive : 42776 if [$3][0]!=-1 __x_morph_keypoints=$3 fi 42777 rv 42778 x_morph $1,$2 42779 repeat $! gui_set_layer_name[$>] "Morphing ""#"$> gui_set_layer_pos[$>] 0,0 done 42780 rv 42781 u "{$1}{$2}{"$__x_morph_keypoints"}" 42782 42783fx_morph_interactive_preview : 42784 if $!<2 gui_warning_preview "This filter requires at least two input layers!" return fi 42785 rr2d ${-max_wh},0,3 + n 0,255 42786 if [$3][0]!=-1 gui_warning_preview "No preview available\n\nKeypoints from previous\nrun have been saved" 42787 else gui_warning_preview "No preview available" 42788 fi 42789 42790#@gui Perspective : fx_warp_perspective, fx_warp_perspective(1) 42791#@gui : X-Angle = float(1.73,-4,4) 42792#@gui : Y-Angle = float(0,-4,4) 42793#@gui : Zoom = float(1,0.1,4) 42794#@gui : Center (%) = point(50,50,0,1,255) 42795#@gui : X-Offset = float(0,0,100) 42796#@gui : Y-Offset = float(0,0,100) 42797#@gui : Boundary = choice(2,"Transparent","Nearest","Periodic","Mirror") 42798#@gui : sep = separator() 42799#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42800fx_warp_perspective : 42801 if !$8 to_a fi 42802 shift $6%,$7%,0,0,2 warp_perspective $1,$2,$3,$4,$5,$8 42803 42804#@gui Polar Transform : fx_transform_polar, fx_transform_polar(1) 42805#@gui : Preset = choice("Custom Transform","Inverse Radius","Swap Radius / Angle") 42806#@gui : Center (%) = point(50,50,0,1) 42807#@gui : Radius = text{"r + R/10*cos(a*5)"} 42808#@gui : Angle = text{"a"} 42809#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42810#@gui : sep = separator() 42811#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42812fx_transform_polar : 42813 if !$6 to_a fi 42814 if $1==0 42815 transform_polar "$4","$5",$2%,$3%,$6 42816 elif $1==1 42817 transform_polar R-r,a,$2%,$3%,$6 42818 else 42819 transform_polar a*R/(2*pi),r*2*pi/R,$2%,$3%,$6 42820 fi 42821 42822#@gui Quadrangle : fx_quadrangle, fx_quadrangle_preview(1) 42823#@gui : Top-Left Vertex (%) = point(5,5,0,1,255,0,0) 42824#@gui : Top-Right Vertex (%) = point(95,25,0,1,0,255,0) 42825#@gui : Bottom-Right Vertex (%) = point(60,95,0,1,64,128,255) 42826#@gui : Bottom-Left Vertex (%) = point(40,95,0,1,255,255,0) 42827#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 42828#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42829#@gui : Preview Type = choice(1,"Input","Output","Both") 42830#@gui : sep = separator() 42831#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/10/11</i>.</small>") 42832fx_quadrangle : 42833 at_quadrangle $1%,$2%,$3%,$4%,$5%,$6%,$7%,$8%,${9-10} 42834 42835fx_quadrangle_preview : 42836 repeat $! l[$>] 42837 if !$10 to_a fi 42838 if $11 +fx_quadrangle $* rr2d. {0,[w,h]},2,3 fi 42839 polygon[{$11==1?1:0}] 4,$1%,$2%,$3%,$4%,$5%,$6%,$7%,$8%,0.25,255 42840 if $11>=2 42841 circle[0] $1%,$2%,4,1,0 circle[0] $1%,$2%,3,1,255,0,0 42842 circle[0] $3%,$4%,4,1,0 circle[0] $3%,$4%,3,1,0,255,0 42843 circle[0] $5%,$6%,4,1,0 circle[0] $5%,$6%,3,1,64,128,255 42844 circle[0] $7%,$8%,4,1,0 circle[0] $7%,$8%,3,1,255,255,0 42845 elif $11>0 42846 rm[0] 42847 fi 42848 if $!==2 42849 drgba to[0] Quadrangle to[1] Result frame 1,1,0 42850 +a x a[0,1] y rr2d ${-gui_preview_wh},0,3 42851 k[{max(w#0,h#0)>max(w#1,h#1)?0:1}] 42852 fi 42853 endl done 42854 42855#@gui Raindrops : raindrops, raindrops(0) 42856#@gui : Amplitude = float(80,0,300) 42857#@gui : Density = float(0.1,0,1) 42858#@gui : Wavelength = float(1,0,2) 42859#@gui : Merging Steps = int(0,0,20) 42860#@gui : sep = separator() 42861#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/28/11</i>.</small>") 42862 42863#@gui Random : deform, deform(0) 42864#@gui : Amplitude = float(10,0,100) 42865#@gui : sep = separator() 42866#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42867 42868#@gui Ripple : ripple, ripple(0) 42869#@gui : Amplitude = float(10,0,100) 42870#@gui : Bandwidth = float(20,1,300) 42871#@gui : Shape = choice(2,"Bloc","Triangle","Sine","Sine+","Random") 42872#@gui : Angle = float(0,0,360) 42873#@gui : Offset = float(0,0,500) 42874#@gui : sep = separator() 42875#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/23/08</i>.</small>") 42876 42877#@gui Reflection : fx_reflect, fx_reflect(1) 42878#@gui : Height = float(50,0,100) 42879#@gui : Attenuation = float(1,0.1,4) 42880#@gui : Color = color(110,160,190,64) 42881#@gui : Waves Amplitude = float(0,0,100) 42882#@gui : Waves Smoothness = float(1.5,0,4) 42883#@gui : X-Angle = float(0,-10,10) 42884#@gui : Y-Angle = float(-3.30,-10,10) 42885#@gui : Focale = float(7,0,10) 42886#@gui : Zoom = float(1.5,1,5) 42887#@gui : sep = separator() 42888#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42889fx_reflect : 42890 repeat $! 42891 to_rgba. +rows. {100-$1}%,100% mirror. y water. $7,$8 42892 s. c 42893 f[-4] "(i*(255-$6) + $6*$3)/255" 42894 f... "(i*(255-$6) + $6*$4)/255" 42895 f.. "(i*(255-$6) + $6*$5)/255" a[-4--1] c 42896 *. '(h^$2-y^$2)/h^$2' a[-2,-1] y 42897 100%,100%,100%,1,$11*$12*(x/w-0.5) 42898 100%,100%,100%,1,$11*$12*(y/h-0.5) 42899 100%,100%,100%,1,"$10*(x/w-0.5) + $9*(y/h-0.5) + $11" 42900 /... . +... 0.5 *... {-3,w} 42901 /[-2,-1] +. 0.5 *. {h} 42902 a[-2,-1] c warp.. .,0,1,0 rm. 42903 mv. 0 done 42904 autocrop 0,0,0,0 42905 42906#@gui Seamcarve : fx_seamcarve, fx_seamcarve_preview(1) 42907#@gui : Width (%) = float(85,0,200) 42908#@gui : Height (%) = float(100,0,200) 42909#@gui : Maximal Seams per Iteration (%) = float(15,0,100) 42910#@gui : Use Top Layer as a Priority Mask = bool(0) 42911#@gui : Antialiasing = bool(1) 42912#@gui : sep = separator() 42913#@gui : note = note{"<small><b>Note:</b> 42914#@gui : You can define a transparent top layer that will help the seam-carving algorithm to preserve or force 42915#@gui : removing image structures:\n 42916#@gui : \n - Draw areas in <i>red</i> to force removing them. 42917#@gui : \n - Draw areas in <i>green</i> to preserve them. 42918#@gui : \n - Don't forget also to set the <i>Input layers...</i> parameter to input both layers to the filter. 42919#@gui : </small>"} 42920#@gui : sep = separator() 42921#@gui : note = note("<small>Authors: <i>Garagecoder</i> and <i>David Tschumperlé</i>. 42922#@gui : Latest Update: <i>2014/02/06</i>.</small>") 42923fx_seamcarve : 42924 if $4 42925 if $!<2 error "Priority mask (top layer) is missing!" fi 42926 _fx_seamcarve 42927 fi 42928 seamcarve $1%,$2%,$4,$5,$3% 42929 if $4 repeat $! channels[$>] 0,{$>,s-2} done fi 42930 c 0,255 42931 42932fx_seamcarve_preview : 42933 if $4 42934 if $!<2 to_rgb to "Priority mask (top layer) is missing!",5,5,18,2 return fi 42935 _fx_seamcarve 42936 fi 42937 repeat $! l[$>] 42938 w={w} h={h} 42939 seamcarve $1%,$2%,$4,$5,{max($3,10)}% 42940 if $4 channels 0,{s-2} fi 42941 to_rgba r $w,$h,1,100%,0,0,0.5,0.5 42942 endl done 42943 c 0,255 42944 42945_fx_seamcarve : 42946 mv[0] $! 42947 l. 42948 s c k[0,1] 42949 >[1] [0] !=[0] 0 -[0] [1] *[0] -1 + * 256 42950 endl 42951 repeat $!-1 a[$>] .,c done rm. 42952 42953#@gui Sphere : fx_map_sphere, fx_map_sphere_preview(1) 42954#@gui : Width = _int(512,1,4096) 42955#@gui : Height = _int(512,1,4096) 42956#@gui : Radius = float(90,0,400) 42957#@gui : Dilation = float(0.5,0,1) 42958#@gui : Angle = float(0,-50,50) 42959#@gui : Border Smoothness = float(0,0,200) 42960#@gui : Border Width = float(20,0,100) 42961#@gui : Orientation = choice("0 deg.","90 deg.","180 deg.","270 deg.") 42962#@gui : Background = choice("Transparent","Mean Color") 42963#@gui : Fading = float(0,0,100) 42964#@gui : Fading Shape = float(0.5,0,3) 42965#@gui : sep = separator() 42966#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/07/11</i>.</small>") 42967fx_map_sphere : 42968 rotate {$8*90} 42969 if $6 42970 repeat $! 42971 shift. {round(w/2)},0,0,0,2 +columns. {(1-$7/100)*w/2},{(1+$7/100)*w/2} 42972 100% gaussian. {0.1*w},{h},0 100% 100% a[-3--1] c r. ..,..,1,3 42973 smooth.. .,$6,5,0 rm. 42974 j.. .,{(1-$7/100)*{-2,w}/2} rm. shift. -{round(w/2)},0,0,0,2 42975 mv. 0 done 42976 fi 42977 shift $5%,0,0,0,2 to_rgba 42978 if $9 42979 repeat $! 42980 +rows[$>] 0 r. 1,1,1,4,2 RGBA$>={^} 42981 r. [$>],[$>],1,4 -[$>,-1] 42982 done 42983 fi 42984 map_sphere $1,$2,$3,$4,$10,$11 42985 if $9 42986 repeat $! 42987 (${RGBA$>}) y. c r. [$>],[$>],1,4 +[$>,-1] 42988 done 42989 fi 42990 42991fx_map_sphere_preview : 42992 fx_map_sphere {w},{h},${3--1} 42993 42994#@gui Spherize : fx_spherize, fx_spherize_preview(1) 42995#@gui : Radius (%) = float(50,0,300) 42996#@gui : Strength = float(1,-10,10) 42997#@gui : Smoothness (%) = float(0,0,4) 42998#@gui : Center (%) = point(50,50,0,1,255,255,255,170,10) 42999#@gui : Ratio = float(0,-2,2) 43000#@gui : Angle = float(0,-90,90) 43001#@gui : Interpolation = choice(2,"Nearest Neighbor","Linear","Cubic") 43002#@gui : Preview Grid = bool(0) 43003#@gui : sep = separator() 43004#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/10/03</i>.</small>") 43005fx_spherize : 43006 ratio={10^$6} 43007 spherize $1%,$2,$3%,$4%,$5%,$ratio,$7,$8 43008 cut 0,255 43009 43010fx_spherize_preview : 43011 cx,cy=${4,5} 43012 if $9 grid 5%,5%,50%,50%,0.6,255 fi 43013 fx_spherize ${1-3},$cx,$cy,${6--1} 43014 43015#@gui Square to Circle : fx_square_circle, fx_square_circle 43016#@gui : Mode = choice(0,"Square to Circle","Circle to Square") 43017#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 43018#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 43019#@gui : sep = separator() 43020#@gui : X-Factor (%) = float(0,-100,100) 43021#@gui : Y-Factor (%) = float(0,-100,100) 43022#@gui : X-Offset (%) = float(0,-300,300) 43023#@gui : Y-Offset (%) = float(0,-300,300) 43024#@gui : sep = separator() 43025#@gui : note = note("<small>This filter implements the mapping functions described in this page, 43026#@gui : by <i>C. Fong</i>:</small>") 43027#@gui : url = link("http://squircular.blogspot.com/2015/09/mapping-circle-to-square.html") 43028#@gui : sep = separator() 43029#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/10/30</i>.</small>") 43030fx_square_circle : 43031 mode,interp,boundary,factx,facty,offx,offy=${1-7} 43032 if !$boundary to_a fi 43033 base="const interpolation = "$interp"; 43034 const boundary = "$boundary"; 43035 const offx = "$offx"%; 43036 const offy = "$offy"%; 43037 const factx = 10^-("$factx"%); 43038 const facty = 10^-("$facty"%); 43039 const w2 = int(w/2); 43040 const h2 = int(h/2);" 43041 if !$mode # Square to circle 43042 f $base" 43043 const tst = 2*sqrt(2); 43044 U = (2*x/(w-1) - 1)*factx + offx; 43045 V = (2*y/(h-1) - 1)*facty + offy; 43046 U2 = U^2; 43047 V2 = V^2; 43048 U2mV2 = U2 - V2; 43049 X = 0.5*(sqrt(max(0,2 + tst*U + U2mV2)) - sqrt(max(0,2 - tst*U + U2mV2))); 43050 Y = 0.5*(sqrt(max(0,2 + tst*V - U2mV2)) - sqrt(max(0,2 - tst*V - U2mV2))); 43051 (X+=1)*=w2 - 0.5; 43052 (Y+=1)*=h2 - 0.5; 43053 I(X,Y)" 43054 else # Circle to square 43055 f $base" 43056 X = (2*x/(w-1) - 1)*factx + offx; 43057 Y = (2*y/(h-1) - 1)*facty + offy; 43058 U = X*sqrt(abs(1 - 0.5*Y^2)); 43059 V = Y*sqrt(abs(1 - 0.5*X^2)); 43060 (U+=1)*=w2 - 0.5; 43061 (V+=1)*=h2 - 0.5; 43062 I(U,V)" 43063 fi 43064 43065#@gui Stereographic Projection : fx_project_stereographic, fx_project_stereographic_preview(1) 43066#@gui : Transform = choice("Direct","Inverse") 43067#@gui : Center (%) = point(50,50,0,1,255,255,255,170) 43068#@gui : Radius / Angle = point(50,75,0,1,255,0,255,170) 43069#@gui : Horizon Leveling (deg) = float(0,-10,10) 43070#@gui : Left / Right Blur (%) = float(0,0,20) 43071#@gui : Dilation = float(0,-2,2) 43072#@gui : Mirror = choice("None","X-Axis","Y-Axis","XY-Axis") 43073#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 43074#@gui : Last Center = value(50,50) 43075#@gui : sep = separator() 43076#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/07/04</i>.</small>") 43077fx_project_stereographic : 43078 is_inverse,centerx,centery,radangx,radangy,rechor,lrblur,dilation,mirror,boundary,ocenterx,ocentery=${1-11} 43079 43080 if $centerx!=$ocenterx" || "$centery!=$ocentery 43081 deltax,deltay={[$radangx,$radangy]-[$ocenterx,$ocentery]} 43082 radangx,radangy={[$centerx,$centery]+[$deltax,$deltay]} 43083 fi 43084 status=\{$is_inverse\}\{$centerx,$centery\}\{$radangx,$radangy\}\{$rechor\}\{$lrblur\}\ 43085 \{$dilation\}\{$mirror\}\{$boundary\}\{$centerx,$centery\} 43086 43087 # So that preview line does not hide left/right frontier: 43088 nradangx,nradangy={[$centerx,$centery]+rot(-90°)*([$radangx,$radangy]-[$centerx,$centery])} 43089 init="const boundary = "$is_inverse?$boundary:2"; 43090 const interpolation = 1; 43091 const dilation = 2^"$dilation"; 43092 const centerx = "$centerx"%*(W-1); 43093 const centery = "$centery"%*(H-1); 43094 const radangx = "$nradangx"%*(W-1) - centerx; 43095 const radangy = "$nradangy"%*(H-1) - centery; 43096 const R = sqrt(radangx^2 + radangy^2); 43097 const theta0 = atan2(radangy,radangx); 43098 const pi2 = 2*pi;" 43099 m "_fx_project_stereographic_mirror : if !$""1 mirror y elif $""1==1 mirror xy elif $""1==3 mirror x fi" 43100 repeat $! l[$>] 43101 if !$boundary to_a fi 43102 if $rechor rotate $rechor,1,3 fi 43103 if $lrblur 43104 100%,1,1,1,!x||x==w-1 shift {round(w/2)},0,0,0,2 b. x,$lrblur% n. 0,1 +b.. x,$lrblur% 43105 r.. .,.,1,1 j... .,0,0,0,0,1,.. k[0] shift {-round(w/2)},0,0,0,2 43106 fi 43107 if $is_inverse 43108 100%,50%,1,100%,"* 43109 const W = w#0; 43110 const H = h#0; 43111 "$init" 43112 theta = theta0 + x*pi2/w; 43113 phi = (y/h - 0.5)*pi; 43114 z = R*sin(phi); 43115 rho = ((R + z)/(R - z))^(0.5/dilation)*R; 43116 X = centerx + rho*cos(theta); 43117 Y = centery + rho*sin(theta); 43118 I(#0,X,Y)" 43119 _fx_project_stereographic_mirror $mirror 43120 else 43121 _fx_project_stereographic_mirror $mirror 43122 {u=0$_is_preview?min(w,h):max(w,h);[u,u,1,s]},"* 43123 const W = w; 43124 const H = h; 43125 "$init" 43126 X = x - centerx; 43127 Y = y - centery; 43128 theta = atan2(Y,X); 43129 beta = ((X^2 + Y^2)/R^2)^dilation; 43130 z = R*(beta - 1)/(beta + 1); 43131 phi = asin(z/R); 43132 theta = ((theta - theta0)*w#0/pi2)%w#0; 43133 phi = (h#0*(phi/pi + 0.5))%h#0; 43134 I(#0,theta,phi)" 43135 fi 43136 k. endl done um _fx_project_stereographic 43137 43138 if 0$_is_preview 43139 line $centerx%,$centery%,$radangx%,$radangy%,0.75,0xF0F0F0F0,255,255,255,255 43140 line $centerx%,$centery%,$radangx%,$radangy%,0.75,0x0F0F0F0F,0,0,0,255 43141 fi 43142 u $status 43143 43144fx_project_stereographic_preview : 43145 _is_preview=1 43146 fx_project_stereographic $"*" 43147 43148#@gui Symmetrize : fx_symmetrize, fx_symmetrize_preview(1) 43149#@gui : Point 1 = point(50,50,0,1,0,255,0,170,10) 43150#@gui : Point 2 = point(50,75,-1,1,255,255,0,170,10) 43151#@gui : Angle = float(0,-180,180) 43152#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 43153#@gui : Type = choice("Symmetry","Antisymmetry") 43154#@gui : Swap Sides = bool(0) 43155#@gui : sep = separator() 43156#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/06/11</i>.</small>") 43157fx_symmetrize : 43158 if !$6 to_a fi 43159 angle={isnan($3)?$5:atan2($4-$2,$3-$1)*180/pi} 43160 symmetrize $1%,$2%,$angle,${6-8} 43161 43162fx_symmetrize_preview : 43163 fx_symmetrize $* 43164 rr2d ${-gui_preview_wh},0,1 43165 u,v={angle=isnan($3)?$5*pi/180:atan2($4-$2,$3-$1);[cos(angle),sin(angle)]} 43166 repeat $! l[$>] 43167 x0,y0,x1,y1={V=[$u,$v];([${1,2},${1,2}]+10000*[V,-V])*([w,h,w,h]-1)%} 43168 line $x0,$y0,$x1,$y1,1,0x0F0F0F0F,0,0,0,255 43169 line $x0,$y0,$x1,$y1,1,0xF0F0F0F0,255 43170 endl done 43171 43172#@gui Textured Glass : fx_textured_glass, fx_textured_glass_preview(0) 43173#@gui : X-Amplitude = float(40,0,400) 43174#@gui : Y-Amplitude = float(40,0,400) 43175#@gui : X-Smoothness = float(1,0,5) 43176#@gui : Y-Smoothness = float(1,0,5) 43177#@gui : Edge Attenuation = float(0,0,1) 43178#@gui : Edge Influence = float(2,0,10) 43179#@gui : Noise Scale = int(0,0,16) 43180#@gui : sep = separator() 43181#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43182#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43183#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43184#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43185#@gui : sep = separator() 43186#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/21/11</i>.</small>") 43187fx_textured_glass : 43188 repeat $! l[$>] 43189 100%,100%,1,1 43190 if $7 plasma. 1,1,$7 else rand. 0,1 fi 43191 g. xy 43192 if $5 43193 +gradient_norm... +. 1 b. $6 ^. -$5 43194 *... . *[-2,-1] 43195 fi 43196 blur_xy[-2,-1] $3,$4 43197 *.. {-2,$1/max(abs(im),abs(iM))} 43198 *. {$2/max(abs(im),abs(iM))} 43199 a[-2,-1] c 43200 warp.. .,1,1 rm. 43201 endl done 43202 43203fx_textured_glass_preview : 43204 gui_split_preview "fx_textured_glass $*",${-3--1} 43205 43206#@gui Twirl : fx_twirl, fx_twirl(1) 43207#@gui : Amplitude = float(1,-5,5) 43208#@gui : Center (%) = point(50,50,0,1) 43209#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 43210#@gui : sep = separator() 43211#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43212fx_twirl : 43213 if !$4 to_a fi 43214 twirl $1,$2%,$3%,$4 43215 43216#@gui Warp [Interactive] : fx_warp_interactive, fx_warp_interactive_preview(1) 43217#@gui : Preview Precision = choice{1,"Coarsest (faster)","Coarse","Normal","Fine","Finest (slower)"} 43218#@gui : sep = separator() 43219#@gui : note = note{"<small><b>Pre-defined keypoints</b></small>"} 43220#@gui : Regular Grid = int(2,2,10) 43221#@gui : Contours = int(0,0,32) 43222#@gui : Keypoints = value(-1) 43223#@gui : sep = separator() 43224#@gui : note = note{"<b>Instructions:</b>"} 43225#@gui : note = note{" 43226#@gui : Use mouse to add/move/delete keypoints over the interactive window that will appear, 43227#@gui : in order to create the deformation map.\n\n 43228#@gui : - <b>Left mouse button</b>: Add and move keypoint.\n 43229#@gui : - <b>Right mouse button</b>: Delete keypoint.\n 43230#@gui : - Key <b>SPACE</b> or <b>middle mouse button</b>: Show/hide keypoints.\n 43231#@gui : - Key <b>TAB</b>: Change keypoint radius.\n 43232#@gui : - Key <b>SHIFT</b>: Toggle to original image.\n 43233#@gui : - Key <b>R</b>: Reset keypoints.\n 43234#@gui : - Keys <b>ESC</b>, <b>ENTER</b> or <b>Q</b>: Process fullres and exit. 43235#@gui : "} 43236#@gui : sep = separator() 43237#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/04/08</i>.</small>") 43238fx_warp_interactive : 43239 if [$4][0]!=-1 __x_warp_keypoints=$4 fi 43240 x_warp $2,$2,$3,$1 43241 u "{$1}{$2}{$3}{"$__x_warp_keypoints"}" 43242 43243fx_warp_interactive_preview : 43244 if [$4][0]!=-1 __x_warp_keypoints=$4 fi 43245 repeat $! l[$>] 43246 rr2d $_preview_width,$_preview_height,0,3 to_color drgba 43247 if narg($__x_warp_keypoints) ($__x_warp_keypoints) r. 1,{w/4},1,4,-1 43248 else 43249 43250 # Keypoints located on regular grid. 43251 nbp,nbq=$2,$2 43252 1,{$nbp*$nbq},1,4,"const nbp = "$nbp"; const nbq = "$nbq"; 43253 p = y%nbp; 43254 q = int(y/nbp); 43255 x = p*100/(nbp - 1); 43256 y = q*100/(nbq - 1); 43257 [ x,y,x,y ]" 43258 43259 # Keypoints located on contours. 43260 nbc=$3 43261 if $nbc>0 43262 +b[0] 0.5 gradient_norm. sqrt. {round([w,h]/4)} gaussian. 20% 43263 1,$nbc,1,4,"> 43264 begin(ref(crop(#-1),gauss)); 43265 st = stats(#-2); 43266 iM = st[1]; 43267 xM = st[8]; 43268 yM = st[9]; 43269 img = vector(#w#-1*h#-1,-iM); 43270 draw(#-2,img,xM - w#-1/2,yM - h#-1/2,0,0,w#-1,h#-1,1,1,-1,gauss); 43271 nxyM = [ xM,yM ]*100/([w#-2,h#-2]-1); 43272 [ nxyM,nxyM ]" 43273 rm[-3,-2] 43274 a[-2,-1] y 43275 fi 43276 fi 43277 43278 +_x_warp_rbf. {0,round([w,h]/4)} *. 4 r. [0],[0],1,100%,3 +. '[x,y]' warp[0] .,0,1,3 rm. 43279 43280 eval. "* 43281 begin( 43282 col1 = [ 64,200,255 ]; 43283 const radius1 = 3; 43284 const radius2 = radius1 + 2; 43285 fact = ([ w#0,h#0 ] - 1)% 43286 ); 43287 X = (I)[0,2]*fact; 43288 ellipse(#0,X,radius2,radius2,0,1,0); 43289 ellipse(#0,X,radius1,radius1,0,1,col1); I" 43290 rm. 43291 43292 if narg($__x_warp_keypoints) 43293 0 t. "Keypoints from previous\nrun have been saved",0,0,24,1,255 43294 frame. 5,5,0 +dilate_circ. 5 a[-2,-1] c blend alpha 43295 fi 43296 endl done 43297 43298#@gui Water : water, water(0) 43299#@gui : Amplitude = float(30,0,300) 43300#@gui : Smoothness = float(1.5,0,4) 43301#@gui : Angle = float(45,0,180) 43302#@gui : sep = separator() 43303#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/07/10</i>.</small>") 43304 43305#@gui Wave : wave, wave(1) 43306#@gui : Amplitude = float(10,0,30) 43307#@gui : Frequency = float(0.4,0,2) 43308#@gui : Center (%) = point(50,50,0,1,255,255,255,170,10) 43309#@gui : sep = separator() 43310#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43311 43312#@gui Wind : fx_wind, fx_wind_preview(0) 43313#@gui : Amplitude = int(20,0,500) 43314#@gui : Angle = float(0,0,360) 43315#@gui : Attenuation = float(0.7,0,1) 43316#@gui : Threshold = float(20,0,100) 43317#@gui : Mode = choice(1,"Darker","Brighter") 43318#@gui : sep = separator() 43319#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43320#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43321#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43322#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43323#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43324#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43325#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43326#@gui : Value Action = choice("None","Cut","Normalize") 43327#@gui : sep = separator() 43328#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43329#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43330#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43331#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43332#@gui : sep = separator() 43333#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/13/07</i>.</small>") 43334fx_wind : 43335 if !$5 negate fi 43336 ac "wind ${1-4}",$6,$7 43337 if !$5 negate fi 43338 43339fx_wind_preview : 43340 gui_split_preview "fx_wind $*",${-3--1} 43341 43342#@gui Zoom : fx_zoom, fx_zoom(1) 43343#@gui : Factor = float(2,0.01,10) 43344#@gui : Center (%) = point(50,50,0,1,255) 43345#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 43346#@gui : sep = separator() 43347#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43348fx_zoom : 43349 if !$4" && "$1<1 to_a fi 43350 zoom $1,{$2%},{$3%},0,$4 43351 43352 43353#@gui ____<b>Degradations</b> 43354#----------------------------- 43355 43356#@gui Add Grain : fx_simulate_grain, fx_simulate_grain_preview(0) 43357#@gui : Preset = choice{"Orwo NP20-GDR","Kodak TMAX 400","Kodak TMAX 3200","Kodak TRI-X 1600","Unknown"} 43358#@gui : Blend Mode = choice(1,"Alpha","Grain Merge","Hard Light","Overlay","Soft Light","Grain Only") 43359#@gui : Opacity = float(0.2,0,1) 43360#@gui : Scale = float(100,30,800) 43361#@gui : Sharpness = float(0,0,512) 43362#@gui : Colored Grain = bool() 43363#@gui : sep = separator() 43364#@gui : Brightness (%) = float(0,-100,100) 43365#@gui : Contrast (%) = float(0,-100,100) 43366#@gui : Gamma (%) = float(0,-100,100) 43367#@gui : Hue (%) = float(0,-100,100) 43368#@gui : Saturation (%) = float(0,-100,100) 43369#@gui : sep = separator() 43370#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43371#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43372#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43373#@gui : Preview Grain Alone = bool() 43374#@gui : sep = separator() 43375#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/02/08</i>.</small>") 43376fx_simulate_grain : 43377 __fx_simulate_grain ${arg\ {1+$1},${-_fx_simulate_grain}},${2-11},0,0 43378 43379_fx_simulate_grain : 43380 u orwo_np20,kodak_tmax400,kodak_tmax3200,kodak_trix1600,unknown 43381 43382fx_simulate_grain_preview : 43383 gui_split_preview "_fx_simulate_grain_preview $*",$-2 43384 43385_fx_simulate_grain_preview : 43386 __fx_simulate_grain ${arg\ {1+$1},${-_fx_simulate_grain}},${2-13} 43387 43388__fx_simulate_grain : 43389 bm0=alpha bm1=grainmerge bm2=hardlight bm3=overlay bm4=softlight bm5=alpha 43390 input_cached data_film_presets/grain_$1.cimgz 43391 r. $4%,$4%,1,1,6 43392 if $4>100 b. 1 fi 43393 sharpen. $5 c. 0,255 43394 43395 repeat $!-1 l[$>,-1] split_opacity[0] 43396 +syntexturize. {0,[w,h]} 43397 if $6 +syntexturize.. {w},{h} +syntexturize... {w},{h} a[-3--1] c fi 43398 c. 0,255 43399 adjust_colors. ${7-11} 43400 if $13 k[0,-1] rv 43401 else blend[0,-1] ${bm$2},{if($2<=4,$3,1)} 43402 fi 43403 a[^-1] c endl done rm. 43404 43405#@gui Blur [Angular] : fx_blur_angular, fx_blur_angular_preview(1) 43406#@gui : Amplitude (%) = float(2,0,20) 43407#@gui : Center (%) = point(50,50,0,1) 43408#@gui : Sharpness = float(0,0,500) 43409#@gui : Preview Guides = bool(1) 43410#@gui : sep = separator() 43411#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43412#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43413#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43414#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43415#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43416#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43417#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43418#@gui : Value Action = choice("None","Cut","Normalize") 43419#@gui : sep = separator() 43420#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/16/01</i>.</small>") 43421fx_blur_angular : 43422 ac "blur_angular $1%,$2%,$3% sharpen $4",$6,$7 43423 43424fx_blur_angular_preview : 43425 fx_blur_angular $* 43426 if $5 43427 line 0,$3%,100%,$3%,0.5,0xF0F0F0F0,255 line 0,$3%,100%,$3%,0.5,0x0F0F0F0F,0 43428 line $2%,0,$2%,100%,0.5,0xF0F0F0F0,255 line $2%,0,$2%,100%,0.5,0x0F0F0F0F,0 43429 fi 43430 43431#@gui Blur [Bloom] : fx_blur_bloom, fx_blur_bloom_preview(0) 43432#@gui : Amplitude = float(1,0,10) 43433#@gui : Ratio = float(2,0,5) 43434#@gui : Iterations = int(5,0,100) 43435#@gui : Operator = choice("Add","Max","Min") 43436#@gui : Kernel = choice(1,"Deriche","Gaussian","Box","Triangle","Quadratic") 43437#@gui : Normalize Scales = bool(0) 43438#@gui : Anisotropy = float(0,0,1) 43439#@gui : Angle = float(0,-180,180) 43440#@gui : note = note("Parameter <i>Angle</i> is only active when <i>Anisotropy</i>>0") 43441#@gui : sep = separator() 43442#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43443#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43444#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43445#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43446#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43447#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43448#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43449#@gui : sep = separator() 43450#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43451#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43452#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43453#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43454#@gui : sep = separator() 43455#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/03/02</i>.</small>") 43456fx_blur_bloom : 43457 op=${"arg 1+$4,+,max,min"} 43458 if !$7 ac "blur_bloom ${1-3},"$op",${5-6},xy",$9 43459 else 43460 wh={[w,h]} 43461 rotate $8,2,1 43462 ac "blur_bloom ${1-3},"$op",${5-6},x blur_bloom {$1*(1-$7)},${2-3},"$op",${5-6},y",$9 43463 rotate {-$8},2,1 43464 r $wh,1,100%,0,0,0.5,0.5 c 0,255 43465 fi 43466 43467fx_blur_bloom_preview : 43468 gui_split_preview "fx_blur_bloom $*",${-3--1} 43469 43470#@gui Blur [Depth-of-Field] : fx_blur_dof, fx_blur_dof_preview(1) 43471#@gui : Blur Amplitude = float(3,0,20) 43472#@gui : Blur Precision = int(16,2,64) 43473#@gui : Depth-of-Field Type = choice{"Gaussian","User-Defined (Bottom Layer)"} 43474#@gui : Invert Blur = bool(0) 43475#@gui : sep = separator() 43476#@gui : note = note("<small><b>Gaussian depth-of-field:</b></small>") 43477#@gui : Center (%) = point(50,50,0,0,255) 43478#@gui : First Radius = float(30,0,200) 43479#@gui : Second Radius = float(30,0,200) 43480#@gui : Angle = float(0,0,180) 43481#@gui : Sharpness = float(1,0,8) 43482#@gui : Preview Guides = bool(1) 43483#@gui : sep = separator() 43484#@gui : note = note("<small><b>User-defined depth-of-field:</b></small>") 43485#@gui : Gamma = float(0,-2,2) 43486#@gui : note = note("<small>You can specify your own depth-of-field image, as a <b>bottom layer</b> image 43487#@gui : whose luminance encodes the depth for each pixel. 43488#@gui : Don't forget to modify the <b>Input layers</b> combo-box to make this layer active for the filter.</small>") 43489#@gui : sep = separator() 43490#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/25/02</i>.</small>") 43491fx_blur_dof : 43492 _$0 ${1-10},0,$12 43493 43494fx_blur_dof_preview : 43495 _fx_blur_dof $* 43496 43497_fx_blur_dof : 43498 if !$3 # Gaussian DOF. 43499 repeat $! l[$>] if $11 drgba fi split_opacity l[0] 43500 rmax={(w*w+h*h)^0.5} R={$7*$rmax/100} r={$8*$rmax/100} 43501 t={$9*pi/180} u={cos($t)} v={sin($t)} 43502 l1={($rmax/(1e-8+$R))^2} l2={($rmax/(1e-8+$r))^2} 43503 a={$l1*($u)^2+$l2*($v)^2} b={$u*$v*($l1-$l2)} c={$l1*($v)^2+$l2*($u)^2} 43504 100%,100%,1,1,'X=(x-$5*w/100)/max(w,h);Y=(y-$6*h/100)/max(w,h);f=$a*X*X+2*$b*X*Y+$c*Y*Y;exp(-f^$10/2.5)' 43505 -[1] 1 *[1] -$1 ms={im} Ms={iM} 43506 43507 if $11 # With preview of guides. 43508 +isoline3d[1] {0.1*$1} col3d. 255,255,0 43509 +isoline3d[1] {0.5*$1} col3d. 255,128,0 43510 +3d[-2--1] 43511 __fx_dof_blur[0,1] $2,$ms,$Ms,$4 43512 [0],[0],1,3 j3d. ..,0,0,0,1,1,0,0 rm.. 43513 circle. $5%,$6%,3,1,255,255,255 43514 +compose_channels. + !=. 0 dilate. 3 43515 j[0] ..,0,0,0,0,0.5,.,1 rm[-2,-1] 43516 else __fx_dof_blur[0,1] $2,$ms,$Ms,$4 # Without preview. 43517 fi 43518 endl if $11 k[0] fi a c endl done 43519 elif $!>1 # User-defined DOF (as bottom layer). 43520 luminance. n. 0,1 ^. {10^$12} 43521 repeat $!-1 +r. {$>,w},{$>,h},1,1,3 l[$>,-1] split_opacity[0] 43522 __fx_dof_blur[0,-1] $2,0,$1,$4 43523 a c endl done rm. 43524 else drgba to "Depth-of-field (bottom layer) is missing !",2,2,13,2,1,255 43525 fi 43526 43527# Render DOF blur (generic) 43528# [0] = Input image 43529# [1] = continuous DOF field (with same size as [0]). 43530# $1 = nb quantization levels. 43531# $2 = minimal blur level. 43532# $3 = maximal blur level. 43533# $4 = invert blur. 43534__fx_dof_blur : 43535 n[1] 0,{$1-1} round[1] 43536 [0],[0],1,{0,s+1} 43537 s=0 43538 repeat $1 43539 +==[1] {if($4,$<,$>)} b. 2% 43540 j.. [0],0,0,0,0,-1,.,1 43541 j.. .,0,0,0,100%,-1 43542 rm. 43543 ns={$2+($3-$2)*($>+1)/($1-1)} 43544 b[0] {sqrt($ns^2-$s^2)}% 43545 s=$ns 43546 done 43547 s. c,{-s+1} /[-2,-1] rm[0,1] 43548 43549#@gui Blur [Gaussian] : fx_gaussian_blur, fx_gaussian_blur_preview(0) 43550#@gui : XY-Amplitude = float(3,0,20) 43551#@gui : X-Amplitude = float(0,0,20) 43552#@gui : Y-Amplitude = float(0,0,20) 43553#@gui : Boundary = choice(1,"Black","Nearest") 43554#@gui : sep = separator() 43555#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43556#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43557#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43558#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43559#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43560#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43561#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43562#@gui : Value Action = choice("None","Cut","Normalize") 43563#@gui : sep = separator() 43564#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43565#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43566#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43567#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43568#@gui : sep = separator() 43569#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43570_fx_gaussian_blur : 43571 b $1,$4 43572 if $2>0 repeat $! l. s y b $2,$4 a y endl mv. 0 done fi 43573 if $3>0 repeat $! l. s x b $3,$4 a x endl mv. 0 done fi 43574 43575fx_gaussian_blur : 43576 ac "_fx_gaussian_blur $1,$2,$3,$4",$5,$6 43577 43578fx_gaussian_blur_preview : 43579 gui_split_preview "fx_gaussian_blur $*",${-3--1} 43580 43581#@gui Blur [Glow] : fx_glow, fx_glow_preview(0) 43582#@gui : Amplitude = float(6,0,20) 43583#@gui : sep = separator() 43584#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43585#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43586#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43587#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43588#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43589#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43590#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43591#@gui : Value Action = choice("None","Cut","Normalize") 43592#@gui : sep = separator() 43593#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43594#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43595#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43596#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43597#@gui : sep = separator() 43598#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43599fx_glow : 43600 ac "glow $1",$2,$3 43601 43602fx_glow_preview : 43603 gui_split_preview "fx_glow $*",${-3--1} 43604 43605#@gui Blur [Linear] : fx_blur_linear, fx_blur_linear_preview(1) 43606#@gui : Tangent Radius = float(10,0,100) 43607#@gui : Orthogonal Radius = float(0.5,0,100) 43608#@gui : Angle = float(0,0,180) 43609#@gui : Sharpness = float(0,0,500) 43610#@gui : Boundary = choice(1,"Black","Nearest") 43611#@gui : sep = separator() 43612#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43613#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43614#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43615#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43616#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43617#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43618#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43619#@gui : Value Action = choice("None","Cut","Normalize") 43620#@gui : sep = separator() 43621#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43622#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43623#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43624#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43625#@gui : sep = separator() 43626#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43627fx_blur_linear : 43628 ac "blur_linear $1,{$2*$1/100},$3,$5 sharpen $4",$6,$7 43629 43630fx_blur_linear_preview : 43631 gui_split_preview "fx_blur_linear $*",${-3--1} 43632 43633#@gui Blur [Multidirectional] : fx_blur_multidirectional, fx_blur_multidirectional_preview(0) 43634#@gui : Number of Orientations = int(5,1,16) 43635#@gui : Reference Angle (deg.) = float(0,0,360) 43636#@gui : Angle Range (deg.) = float(360,0,360) 43637#@gui : sep = separator() 43638#@gui : Smoothness = float(150,0,1024) 43639#@gui : Kernel type = choice(0,"Mono-Directional","Bi-Directional") 43640#@gui : Boundary conditions = choice(1,"Dirichlet","Neumann","Periodic","Mirror") 43641#@gui : Sharpness = float(0,0,1000) 43642#@gui : Blend Mode = choice{2,"Min","Max","Average","Edges-0.5 (beware: memory-consuming!)", 43643#@gui : "Edges-1 (beware: memory-consuming!)","Edges-2 (beware: memory-consuming!)", 43644#@gui : "Median (beware: memory-consuming!)"} 43645#@gui : Boost Contrast = float(2,0,32) 43646#@gui : sep = separator() 43647#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43648#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43649#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43650#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43651#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43652#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43653#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43654#@gui : sep = separator() 43655#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43656#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43657#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43658#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43659#@gui : sep = separator() 43660#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/09/11</i>.</small>") 43661_fx_blur_multidirectional : 43662 nb_orientations,\ 43663 angle_ref,\ 43664 angle_range,\ 43665 smoothness,\ 43666 kernel,\ 43667 boundary_conditions,\ 43668 sharpness,\ 43669 blend_mode,\ 43670 contrast=${1-9} 43671 repeat $! l[$>] 43672 # If no median blend, blend step by step in an accumulator to reduce memory usage. 43673 if $blend_mode<3 +f {$blend_mode?0:inf} fi 43674 43675 repeat $nb_orientations 43676 angle={$angle_ref+$angle_range*($>/$nb_orientations-0.5)} 43677 43678 # Kernel definition. 43679 $smoothness,1 gaussian. 20%,0.1 43680 if !$kernel f. "x>w/2?i:0" fi 43681 rotate. $angle,1 # /. {is} 43682 43683 # Blur and blend. 43684 +convolve_fft[0] .,$boundary_conditions rm.. n. 0,255 sharpen. $sharpness 43685 if $blend_mode<3 ${arg\ 1+$blend_mode,min,max,+}[1,-1] fi 43686 done 43687 rm[0] 43688 43689 if $blend_mode==6 blend_median 43690 elif $blend_mode>2 blend_edges {arg($blend_mode-2,0.5,1,2)} 43691 fi 43692 43693 n 0,255 ac "normalize_local "$contrast,hsl_l 43694 endl done 43695 43696fx_blur_multidirectional : 43697 ac "_fx_blur_multidirectional ${1-9}",$10 43698 43699fx_blur_multidirectional_preview : 43700 gui_split_preview "fx_blur_multidirectional $*",${-3--1} 43701 43702#@gui Blur [Radial] : fx_blur_radial, fx_blur_radial_preview(1) 43703#@gui : Amplitude = float(3,0,20) 43704#@gui : Center (%) = point(50,50,0,1) 43705#@gui : Sharpness = float(0,0,500) 43706#@gui : Preview Guides = bool(1) 43707#@gui : sep = separator() 43708#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43709#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43710#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43711#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43712#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43713#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43714#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43715#@gui : Value Action = choice("None","Cut","Normalize") 43716#@gui : sep = separator() 43717#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/16/01</i>.</small>") 43718fx_blur_radial : 43719 ac "blur_radial $1%,$2%,$3% sharpen $4",$6,$7 43720 43721fx_blur_radial_preview : 43722 fx_blur_radial $* 43723 if $5 43724 line 0,$3%,100%,$3%,0.5,0xF0F0F0F0,255 line 0,$3%,100%,$3%,0.5,0x0F0F0F0F,0 43725 line $2%,0,$2%,100%,0.5,0xF0F0F0F0,255 line $2%,0,$2%,100%,0.5,0x0F0F0F0F,0 43726 fi 43727 43728#@gui Chromatic Aberrations : fx_chromatic_aberrations, fx_chromatic_aberrations_preview(0) 43729#@gui : Primary Color = color(255,0,0) 43730#@gui : Deformation Type = choice("Shift","Radial","Angular","Random") 43731#@gui : X-Amplitude = float(2,-32,32) 43732#@gui : Y-Amplitude = float(2,-32,32) 43733#@gui : Smoothness = float(0,0,10) 43734#@gui : Attenuation Near Center (%) = float(50,-100,100) 43735#@gui : Attenuation Decay = float(1,0,8) 43736#@gui : sep = separator() 43737#@gui : Secondary Color = color(0,255,0) 43738#@gui : Deformation Type = choice("Shift","Radial","Angular","Random") 43739#@gui : X-Amplitude = float(0,-32,32) 43740#@gui : Y-Amplitude = float(0,-32,32) 43741#@gui : Smoothness = float(0,0,10) 43742#@gui : Attenuation Near Center (%) = float(0,-100,100) 43743#@gui : Attenuation Decay = float(1,0,8) 43744#@gui : sep = separator() 43745#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43746#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43747#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43748#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43749#@gui : sep = separator() 43750#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/08/10</i>.</small>") 43751fx_chromatic_aberrations : 43752 U1={u=[${1-3}];u/max(1e-8,norm(u))} 43753 U2={u=[${10-12}];u/max(1e-8,norm(u))} 43754 43755 repeat $! l[$>] to_color split_opacity l[0] 43756 43757 # Compute image decomposition : [0] = residual, [1] = weights for primary/secondary colors. 43758 100%,100%,1,2,"*begin(U1 = ["$U1"]; U2 = ["$U2"]); 43759 V = I(#0); 43760 d1 = dot(V,U1); V-=d1*U1; 43761 d2 = dot(V,U2); V-=d2*U2; 43762 I(#0) = V; 43763 [ d1,d2 ]" 43764 s. c 43765 43766 # Shift weights. 43767 _fx_chromatic_aberrations.. ${4-9} 43768 _fx_chromatic_aberrations. ${13-18} 43769 43770 # Reconstruct color image. 43771 a[-2,-1] c 43772 +[0] '"*begin(U1 = ["$U1"]; U2 = ["$U2"]); i(#1,x,y,0,0)*U1 + i(#1,x,y,0,1)*U2"' 43773 rm. 43774 endl a c endl done 43775 43776_fx_chromatic_aberrations : 43777 if $1==0 # Shift 43778 100%,100%,1,2,[$2,$3] 43779 elif $1==1 # Radial 43780 100%,100%,1,2," 43781 ang = atan2(y - h/2, x - w/2); 43782 U = [ $2*cos(ang), $3*sin(ang) ]" 43783 elif $1==2 # Angular 43784 100%,100%,1,2," 43785 ang = atan2(x - w/2, -y + h/2); 43786 U = [ $2*cos(ang), $3*sin(ang) ]" 43787 else # Random 43788 100%,100%,1,2,g s. c n.. 0,$1 n. 0,$2 a[-2,-1] c 43789 fi 43790 if $4 # Smoothness 43791 s. c 43792 m,M={-2,[im,iM]} b.. $4 n.. $m,$M 43793 m,M={[im,iM]} b. $4 n. $m,$M 43794 a[-2,-1] c 43795 fi 43796 if $5 # Center/Borders attenuation 43797 100%,100% =. 1,50%,50% distance. 1 n. 0,1.4142 c. 0,1 43798 if $5>0 pow. {0.1+$6} n. {1-$5%},1 43799 else negate. 1 pow. $6 n. {1+$5%},1 43800 fi 43801 *[-2,-1] 43802 fi 43803 43804 warp.. .,1,1,1 rm. 43805 43806fx_chromatic_aberrations_preview : 43807 gui_split_preview "fx_chromatic_aberrations $*",${-3--1} 43808 43809#@gui Dirty : fx_dirty, fx_dirty_preview(0) 43810#@gui : Amplitude = float(30,0,100) 43811#@gui : Monochrome = bool(1) 43812#@gui : sep = separator() 43813#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43814#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43815#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43816#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43817#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43818#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43819#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43820#@gui : Value Action = choice("None","Cut","Normalize") 43821#@gui : sep = separator() 43822#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43823#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43824#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43825#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43826#@gui : sep = separator() 43827#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/24/11</i>.</small>") 43828fx_dirty : 43829 ac "_fx_dirty ${1-2}",$3,$4 43830 43831fx_dirty_preview : 43832 gui_split_preview "fx_dirty ${1--2}",${-3--1} 43833 43834_fx_dirty : 43835 repeat $! l[$>] 43836 dct 100%,100%,1,{if($2,1,s)} noise. $1,2 43837 ==. 0 point. 0,0,0,1,1 43838 * idct c 0,255 43839 endl done 43840 43841#@gui Flip & Rotate Blocs : fx_flip_blocs,fx_flip_blocs_preview(0) 43842#@gui : X-Size (px) = int(4,1,128) 43843#@gui : Y-Size (px) = int(4,1,128) 43844#@gui : Flip = choice(3,"None","X-axis","Y-axis","XY-axes") 43845#@gui : Rotate = choice(1,"-90 deg.","0 deg.","90 deg.") 43846#@gui : sep = separator() 43847#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43848#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43849#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43850#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43851#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43852#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43853#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43854#@gui : sep = separator() 43855#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43856#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43857#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43858#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43859#@gui : sep = separator() 43860#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/01/09</i>.</small>") 43861fx_flip_blocs : 43862 repeat $! l[$>] 43863 if $5 ac "_fx_flip_blocs ${1-4}",$5 43864 else _fx_flip_blocs ${1-4} 43865 fi 43866 endl done 43867 43868_fx_flip_blocs : 43869 if ($3%2)" && "$1>1 s x,-$1 mirror x a x fi 43870 if ($3>1)" && "$2>1 s y,-$2 mirror y a y fi 43871 if $4!=1" && "$1>1" && "$2>1 43872 s y,-$2 N=$! 43873 s x,-$1 M={$!/$N} 43874 ap "rotate {($4-1)*90}" 43875 append_tiles $M,$N 43876 fi 43877 43878fx_flip_blocs_preview : 43879 gui_split_preview "fx_flip_blocs $*",${-3--1} 43880 43881#@gui JPEG Artefacts : fx_jpeg_artefacts, fx_jpeg_artefacts_preview(0) 43882#@gui : note = note("<small>This filter simulates the JPEG compression artifacts, 43883#@gui : using DCT quantization on 8x8 blocs.</small>") 43884#@gui : Quality (%) = int(50,1,100) 43885#@gui : sep = separator() 43886#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43887#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43888#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43889#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43890#@gui : sep = separator() 43891#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/05/07</i>.</small>") 43892fx_jpeg_artefacts : 43893 43894 # Input all 8x8 DCT and iDCT kernels. 43895 # (Generated with: l[] 8,8,64,1,"y*w+x==z" s z +ap idct a[-64--1] z ap[^-1] dct a[0--2] z nm idct,dct endl) 43896 base642img[] \ 43897"MSBmbG9hdCBsaXR0bGVfZW5kaWFuCjggOCA2NCAxICMyMjIyCnic5Vs9q51FEC60kKtWMYpaCirYKCoI767iR6UoSangtdM/EAM2Fgab2FhaWdgIUXO"\ 43898"qVO8sXEHBVDFia6kgCBaCQSyu+5w8c3nv5p55Bg+3uSmGs19nP2Z2Zt752P39/bJ/G8PHF5+qD1y4v77+yNWyeulegPWy9bbW+9pJ7z9XH6s/f3KxdL"\ 43899"BeRr2hjDb0nfR+4OZyxwlw8UbHS4f1nehtBTg66f3kAyOU261OfDTiA/ehEV91ga8T208+cDlg5JNKPiknvR8ykfKwLuRlo7y0k96PegS8MxsB80RAn"\ 43900"ROBRYC9R0AZtxF45o1w+cXz9fHvztTnP7y7nv7z5dLBern1NvTht37/75P17Qt/lOsPPQqwXrbeth6D/6Hv3F2fl2/++WXqMPfyegzmwZz439e9755f"\ 43901"HwbMvTxjHqwFQBlt6MMYjMV/8F/MgbkwJ+bGGlgLa2Jt7AF7wRjMg/+hD3vG3nmGxr0Y5/S+euPGe/XVJ/ZKB+vlBkAZbeh77ctX6re/f1E6WC83AMp"\ 43902"oQ9+Zd++oV6+8WTpYLzcAymhD30+fPlee/e2zqcPcywZAGW3oO6J+aPw437jeuJ9xv+N5xvMCD/d1vABPL3QcdVjjpbcV4rb+2PGK8jsdxx3QjrZCvJ"\ 43903"evOl2A3/c7jTqs8dvbJtKkgK7A/eU+rsMEGoDOpJehjDb0YQzG4j+kpWEuzIm5sQbWwpqkc8NesCfsDXvEXrFn3oGGs+BMOBvOiLPizPgP+fzgW3Gsu"\ 43904"87wb4mxTj53fixjfeDxo+qb2suC/2+Z1+ub9uX1TefyOundSG/HlxFfjfRupHclvo34dno30tvpNZNeRnob6V1I75n0nknvQnr7fZl4XybSu5Lexvs2"\ 43905"8b45vSvp7fe18L4W0ruS3n7fC+97JV808oWRLyr5ppCvGvnKyFeVfFfIl418aeTLSr4t5GsjX8/ka+f76Yj6ofHjfON6437G/Y7nGc/rMtZlJfVBoz5"\ 43906"weXrAS9QHjfrAKI+N8tj1gVEfuDyfKc+N+sCoD2bqg4n6oPia1AeuTwr1SaU+KNQHE/VRoT5yfVBd9lCfVeoz1wfVdZPbSJvAv6ECsAjc5vq/oOZX+1"\ 43907"Pncx3nusp1zkJ3lL1+p37gXcad7GXb490CoIw212MYi//4XcNcmNPvNdbCmn4vo341v9qfOt8HH71V/7rzSulgvYx6Qxlt3vfg36cBxnZDGW3+v6F+a"\ 43908"Pw4n1pv7Ffzq/2p9YCb6x0nwMXZjpcOa7z3trUcAW6f6TgFLv07BDjvbRNwDEAZbf5dgrH4zx5lEebCnJgba2AtrOlyK+pX86v9qfO5LeQ20lgfeHzk"\ 43909"+RK0L30ut8ybrav51f7UOsRHIz6cHkZ6NOLTiM9Cesykh5EehfQw0mMiPQrpWUnPRnoU0qOqfjW/2p86H/nA5YDzbCWfFPKR85mRz5zvyxH1Q+PH+dR"\ 43910"6Y7+aX+1PrUd52yhvG+Vlo7w0ylujvDXKW6O8nSlvC+VtobwulNcT5W2lvHV5Xynvi+pX86v9qfMp+x6+ogiUfU0fVAQlAuWfgF8rAuUfUPb9Kdrnl/"\ 43911"p32E7/VuswXaJ93vvKKrCvV7Qhdm/aCQf2H77bd29+m69tMpTR5vYfxuI/+O8q8E9g7VP0L2BP2Bv2eIn+hVP85o/8A9QxZW9h37ucQd+1fkee7veow"\ 43912"9TLBYAy2q5Rr0T29dmF/U55d2C/uz4a6ofGK//EuJ9xv+N5xvMu7XvgfHew74Ez4BV4Bo6BW+B1h/a529erhX29WtjXmBPf9+g732ncYU1XfN9jLQDK"\ 43913"aEMfxmAs/rNL2w5zrRb+idXCP4E9YC/YE/aGPWKvO/QvLP0DXO+Qf0DZ9+Rz5ycb68q+Hnh85HkL2m3B/xvt+E378rryD+wG9j1wRXqXnYV9zvuAvsl"\ 43914"5dLSvSa9KelfS20jvifQupHcjvQvvy7z87+oI/4TLFtLbdhb+Bd4H3Nd5N/APYL29hb3s37P+nYA+8lUhX03kKyPfzcq+9m+Qswv7fcH3dkT90Hjlnx"\ 43915"j3M+53PM94XmXfU55OlKeF+qBQH0xL+xo0WQ32NeV5oTx3fVDcN+Q+HuqDRn1g1Afz0j+BuVeDf4L6aKY+MuoDoz6YlX8gESO3LWHbGP2xrp+InzfGS"\ 43916"w58kxjLeEpN9G8bvz/W9RPx823j7dvG7491/UT8fB07Zbx0rZsYT/VvZ9W/bfz+WNdPxMu3jbNvG68/1vUT8XMjvmxBr0J8lkT/tvH7Y10/ET/fNt6+"\ 43917"bfz+WNdPxM+N8tS/Pz3uZQt5GvVvG78/1vUT9nccP9f2t8ohCO3zhP8h9A8o/0PC/g7t+4T9HfoXlH2e8D+E/gHlf0jY36F9n7C/Q/+Css8T/ofQP6D"\ 43918"8Dwn7O7TvE/Z36F9Q9nnC/xD6B5T/IWF/h/Z9wv4O/QvKPk/4H0L/gPI/JOzv0L5P2N+hf0HZ5wn/Q+gfUP6HhP0d2vcJ+zv0Lyj7POF/CP0Dyv+QsL"\ 43919"9D+z5hf4f+BWWfJ/wPoX9A+R8S8XMVo1f5Ayp+r/IHwvnV/tT5EvFzFb9X+QMqfq/yB8L5E/kD4fkS8XMVv1f5Ayp+r/IHVL6Ayh8I10vEz1X8XuUPq"\ 43920"Pi9yh8I50/kD4TnS8TPVbxe5Q+o+L3KH1B5Aip/IFwnET9X8XuVP6Di9yp/IJw/kT8Qni8RP1fxe5U/oOL3Kn9A5Quo/IFwvUT8XMXvVf6Ait+r/IFw"\ 43921"/kT+QHg+lZ+fyL8P7XvlP1D2u/IPJN4fhO8LVH5+Iv8+tO9V/n3i/UHoH0i8PwjfF6j8/ET+ffg+QPkPEu8Pwvz+xPuD8H2Bys9P5N+H7wNU/n3i/UG"\ 43922"Y3594fxC+L1D5+Yn8+9C+V/4DZb8r/0Di/UH4vkDl5yfy78P3ASr/PvH+IMzvT7w/CN8XqPz8RP59+D5A+Q8S7w/C/P7E+4PwfYHKz0/k34f2vcq/T7"\ 43923"w/CP0DifcH4fuC/wBiGjbi" 43924 43925 base642img[] \ 43926"MSBmbG9hdCBsaXR0bGVfZW5kaWFuCjggOCA2NCAxICMyOTE3CnicjVsxjybFEV0JB4iDyHdYhhAJIznBAiSS6ZbBkb3YS4glHOI/4ENyQuDTOsAJIRG"\ 43927"BEyP7di+6cKo5yZY4J95DmxKChIREYMln5ODo1/OqXd9KU1XZzX37Tc+rqqlX9aq+o6Ojevr+T+rvlh/VH9x6uh716189d79c/un9cue1pwo+O//pu/"\ 43928"Xhw9/WF/5+Mv62vnet/vzHn5Qb37xe8D189vs//Lr+4i8/G/d5853H6r+/d7d89sGrBffE9/DZP/734jjjN7e+Lp989efy4Jnny6NHj4o9H9e/NOfj3"\ 43929"zgP98T3cP3u4x+V+3ffKufffr7g7/AsOA/3xDU+++F/bpRXvvxwwT3wnHgWnIdrfA+fPfnFswvw4lx87/y1p6Rft/48rT9Pe+O5+4Jnw/PjjO9/8zqu"\ 43930"W7dH65hbee8a/m5gw/kPPnhV8D181u3RTt55rOHewI1n+9czz0u/bv1+rX+nvX3rawFePf+sn9+vxZ4PvMANTH/79vO1X0u3R+v2aDcf/0jwPdwbeF/"\ 43931"68sO1X0t/VunPI5/efUuAF7iB99oXz679Wro9pNtDbvf7Af8bm73HucDf7VDUH8BfNn8LcONvuh2KxgP+7mTztwA3nrvboWg84B5vb/4W4Ab+boei8Q"\ 43932"D89nzgPzPnA//Nzd8DN/B3OywaD8D/6ebvgRv36XZYNB6A//bm7xW4gb/bYdF4AP4723mtx72YeBjPA/w3NrwN55t4GPbAc3624R0+MfEw7IF7Pdjwt"\ 43933"v68YuJh2AP49XxgM/Ewzgf+8w1v63Fv42HYA/hf2fAK/s/Ew7AH7v3khlf6fVYTD8MexC/EX4i/8fxK/EL8lfgb8VfiF+KvxN+IvxK/EH8h/kb8lfiF"\ 43934"+Avxz/OJfyX+QvxC/JX4V+IvxC/EX4h/Jf6F+IX4C+Nf9DzGvzD+GuN/4mX8C+O/Mf4nXsa/MP4b418UL+NfGP+N8T/PZ/zP8xn/Ey/jf2X8C+N/4mX"\ 43935"8r4x/YfyvipfxvzL+xfgb+a8w/1Xmn2L8jfxXmP8q85/1N/JfYf6rzH/V+Bv5rzD/VeY/62/kv8L8N883/kb+W5j/KvOf9Tfy38L8V5j/ivE38t/C/F"\ 43936"eY/0b+Z74ddiD/CflHyH9N/U3+a+Q/If819Tf5r5H/hPzX1N/kPyH/Cflvnk/+m+eT/5r6m/wn5L+V/Cfqb/KfkP9W8p+ov8l/K/lvPQr4X/n7+Ap/3"\ 43937"yN/R/yLd+k6+eain4/rv/bzX+7PhvMt3xG/EP/I1X/sn93p9v9vtzHsiGvaX2j/ybe0f6P9x5m4F95fvKO0n8B+/+w2OiP/efyv+Rp4Lwx/H5O/I/7F"\ 43938"PfE94H2ixx/eseusRz7u8Qe8mu8Y/7MeQvwDr+ZbfK9f126P2u1R+f41zbd8/2Y9hvcPeIEbeG9v70/B9/AZ3p+I/5W/7xn+7niKxkPEv8D/8ebvBc+"\ 43939"Pez/BfHyxxb8w/xXmv8L8N84CfubfAtzAj3jSeMDfMf8W5t/K/DvsAvw3N38P3MCPfKjxEPG/8vfxFf5We0T8C/zkn9LjfjHxMOwB/OS/Sv7TeBj2AP"\ 43940"4bG95Rd5t4GPbAc5N/K/lX42HYA/jPNryV/KnxMOwR8b/y9/EV/ib+kH+JfyH+lfgL8QvxF+IX4q/E34i/EH8j/kr8jfgL8Tfir8TfiH8hfiH+Qvwt4"\ 43941"n/l73uGvy82eww7RPzL+F8UL+N/YfwXxn9RvIz/wvivjP+Jl/FfGP+V8T/xMv4L478y/idexv/C+C8R/xt/I/9N/mb+C/nX+Bv5b2X+E+a/1fhb2P9M"\ 43942"PoRfjL8HjzD/NeY/629h/zX5GBiNv0e/w/zXmP8k4n/l7+Mr/E3+k4h/yX9F/U3+W8h/i6132P8K+9/xXpD/qvqb/FfJfwf1Fvvvxv572Jj8V9Xf5L9"\ 43943"C/lsi/rd8YftvxNPZ1n9PviN+If5RY0f8HfG/5Uvar9B+o3/P6g979UvE/9pvAS/jZ9YT7L9F8x3jf9ZDiP+IvyP+B17Nl3x/Zj2F9yerP+zVLxH/a/"\ 43944"+NeGH+EOYP7b+F+a8w/xXmv2GXiL8j/sezMH+uzJ/C/DnsktUf9uqXiP+Bn/xx0H+rPfB35L9C/tN4GPaI+Dvi/3PTv5M/NR6GPbL6w179EvE/8a8nV"\ 43945"/pv4q/EvxC/vg+F+CXi74j/z03/zvqpaD19nfpjRn/Yq18i/tf+W/Ey/teT//ffwvq3sP4trH+HHSL+jvif8b8qXsb/yviXrP6wV79E/G/8Xdg/TD5h"\ 43946"/63+FvY/kw+RFyL+jvjf+Hth/zT5FHkhqz/s1S8R/9t6wfbf5D/t94r6m/xXyH9LxN8R/9t6if1zYf88+ves/rBXv0T8H+nnmf5b9WrbfyNXnG/1n6v"\ 43947"/R/ODqP6wej31m4P6I+L/SD/P9t94JupXc56B9yfS/6P5QVR/nJr6g/rdnOdo/+fxf6SfZ/tvvBPULwv1yxEPkf4fzQ+i+uPU1B/Ubyv122b4b5f/I/"\ 43948"08039Tvz7ov9Uekf4fzQ+i+uOU9cdD1h8mHoY9Iv6P9PNM/835xUH/Tfw6/9jV/6P5QVR/EH8h/nZq6g/khYj/I/08238rXsb/wvgvkf4fzQ+i+uPU1"\ 43949"B+c31XO75rWPx7/R/p5tv9m/lutno28EOn/0fwgqj+Mv4Xz26nnq/7j8X+kn2f6b51X2P6b/LdE+n80P4jqDzuv4fz+oP5I8P/kO+IX4l8Nfo//3fl9"\ 43950"gv8n3xF/I34x+D3+d/cXEvwvmu8Y/7MeMvHv8b87v0/wf9N8x/if9ZCJf4//3f2FBP8L89/C/FeY/8TkP4//3fl9gv8b819h/qvMf83kP4//3f2FBP9"\ 43951"P/Z78p/GwGP7z+N+d3yf4v5H/KvlP46EY/vP4391fSPD/1O9Z/4jWw6b+8fjfnd8n+L+x/qmsf5rWw6b+8fjf3V9I8L+w/l1Y/xbWv2LqX4//3fl9gv"\ 43952"8b69/C+rey/m2m/vX4391fSPC/+ntl/zP50PQ/Hv+78/sE/6u/hf3P5EPT/3j87+4vJPh/1jvsf4X972r6X4//3fl9gv9nvcP+t7H/FdP/evzv7i8k9"\ 43953"H93fp7Q/6feTf3jgH8T+r+7P5DQ/6febeuHe6wfEvq/Oz9P6P+Tf6l/zXmI0b88/d/dH0jo/031zgtTPxyzfkjo/+78PKH/T/6l/tmof1ajf3r6v7s/"\ 43954"kND/G/XPWT9Q/2yqfwb6vzs/T+j/lfp3o/49+dfo357+7+4PJPT/Rv37oH5QeyT0f3d+ntD/K+cfjfOPyb9m/uHp/+7+QEL/b5x/HNQPxB/2/9H8PKH"\ 43955"/T/7l/Ktx/lXN/MvT/939gYT+3zj/mvUD519N51+B/u/OzxP6/+Rfzj+nHm7mn57+7+4PJPR/9bdcmPqB+S+c/0fz84T+P+cdnH8f8G9C/3f3BxL6/5"\ 43956"x32PqB/Bf2/xF/Wr7b2f9z5/eJ/T+3fsjoD97+QmL/z+XPy3j/z53fJ/b/3Pohqz/s7S8k9v9c/ryM9//c+X1i/8+tH7L6w97+QmL/z+XPy3j/z53fJ"\ 43957"/b/3Pohoz94+wuJ/T+XPy/j/T93fp/Y/3Prh4z+4O0vJPb/XP68jPf/3Pl9Yv/PrR+y+sPe/kJi/8/lT+Pvvf0/d36f2P9z64es/rC3v5DY/3P509Y7"\ 43958"O/t/7vw+sf/n1g8Z/cHbX4j4P5qfZ/vvPf0+0v+j/YGo/ojmF4nf/7nz82z/vaffR/p/tD8Q1R/R/CLx+z93fp7tv/f0+0j/j/YHovojml8kfv/nzs+"\ 43959"z/feefh/p/9H+QFR/RPOLxO//3Pl5tv/e0+8j/T/aH4jqj2h+kfj9nzs/z/bfe/p9pP9H+wNR/RHNLxK//3Pn59n+e0+/j/T/aH8gqj+i+UXi93/u/D"\ 43960"zbf+/p95H+H+0PRPVHNL/4DgTd2gQ=" 43961 nm[-2,-1] dct,idct 43962 43963 # Input DCT quantization matrix. 43964 (16,11,10,16,24,40,51,61;12,12,14,19,26,58,60,55;14,13,16,24,40,57,69,56;14,17,22,29,51,87,80,62;\ 43965 18,22,37,56,68,109,103,77;24,35,55,64,81,104,113,92;49,64,78,87,103,121,120,101;72,92,95,98,112,100,103,99) 43966 f. "const S = $1<50?5000/$1:200-2*$1; max(1,round((S*i+50)/100,1,-1))" 43967 nm. Q 43968 43969 # Process images. 43970 repeat $!-3 l[$>,-3--1] 43971 43972 # Decompose image into luma/chroma 43973 l[0] w,h={[w,h]} r {w+(-w%16)},{h+(-h%16)},1,100%,0,3 rgb2ycbcr s c r[-2,-1] 50%,50%,1,1,2 round. endl 43974 43975 repeat 3 43976 # Compute DCT of image with 8x8 blocs. 43977 [$>] 43978 f[$>] "begin(boundary = 2; ref(vector64(),res)); 43979 if (!(x%8) && !(y%8), 43980 ref(crop(x,y,8,8),src); 43981 repeat (8,l, repeat (8,k, off = k + 8*l; res[off] = sum(src*crop(#"$dct",0,0,off,8,8,1)))); 43982 draw(#-1,res,x,y,0,0,8,8); 43983 ); i" 43984 round. 43985 43986 # Compute DCT quantization. 43987 +r[Q] {$>,w},100%,1,1,0,2 /.. . round.. *[-2,-1] 43988 43989 # Compute iDCT of 8x8 blocs. 43990 f. "begin(boundary = 2; ref(vector64(),res)); 43991 if (!(x%8) && !(y%8), 43992 ref(crop(x,y,8,8),src); 43993 repeat (8,l, repeat (8,k, off = k + 8*l; res[off] = sum(src*crop(#"$idct",0,0,off,8,8,1)))); 43994 draw(#"$>",res,x,y,0,0,8,8); 43995 ); i" 43996 rm. 43997 round[$>] 43998 done 43999 l[^3--1] r ${-max_wh},1,1,1 a c ycbcr2rgb round. r $w,$h,1,3,0 endl 44000 44001 endl done 44002 rm[dct,idct,Q] 44003 44004fx_jpeg_artefacts_preview : 44005 gui_split_preview "fx_jpeg_artefacts $*",${-3--1} 44006 44007#@gui Lomo : fx_lomo, fx_lomo_preview(1) 44008#@gui : Vignette Size = float(20,0,100) 44009#@gui : sep = separator() 44010#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44011#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44012#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44013#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44014#@gui : sep = separator() 44015#@gui : note = note("<small>Authors: <i>Jérome Boulanger</i> and <i>David Tschumperlé</i>. 44016#@gui : Latest Update: <i>2012/06/06</i>.</small>") 44017fx_lomo : 44018 remove_opacity repeat $! l[$>] to_rgb 44019 +gaussian {100-$1}%,{100-$1}% n. 0,1 * 44020 s c 44021 f[0] '255*atan((i-128)/128)' 44022 f[1] '255*tan((i-128)/128)' 44023 f[2] '255*atan((i-128)/255)' 44024 a c 44025 sharpen 1 44026 normalize 0,255 44027 endl done 44028 44029fx_lomo_preview : 44030 gui_split_preview "fx_lomo $*",${-3--1} 44031 44032#@gui Mess with Bits : fx_mess_with_bits, fx_mess_with_bits_preview 44033#@gui : note = note("<small><b>Input processing:</b></small>") 44034#@gui : Pre-Normalize = bool(1) 44035#@gui : Smoothness (%) = float(15,0,100) 44036#@gui : Multiplier = int(1,1,256) 44037#@gui : sep = separator() 44038#@gui : note = note("<small><b>Output processing:</b></small>") 44039#@gui : Reversing = choice{1,"None","Reverse bits","Reverse bytes"} 44040#@gui : Bit Masking (Start) = int(0,0,15) 44041#@gui : Bit Masking (End) = int(15,0,15) 44042#@gui : Opacity (%) = float(100,0,100) 44043#@gui : sep = separator() 44044#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44045#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44046#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44047#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44048#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44049#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44050#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44051#@gui : sep = separator() 44052#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44053#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44054#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44055#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44056#@gui : sep = separator() 44057#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/01/16</i>.</small>") 44058fx_mess_with_bits : 44059 ac "_fx_mess_with_bits ${1-7}",$8 44060 44061_fx_mess_with_bits : 44062 repeat $! +l[$>] 44063 b {($2/100)^2*100}% if $1 n 0,255 fi * $3 round 44064 # -> Here, images are 'ushort'-valued. 44065 if $4==1 f "for (k = res = 0, k<15, ++k, res|=((i>>k)&1)<<(15-k))" 44066 elif $4==2 f "res = ((i>>8)&255) | ((i&255)<<8)" 44067 fi 44068 f "begin( mask = (65535>>(15-max($5,$6))) & (65535<<min($5,$6))); i & mask" 44069 n 0,255 44070 endl j[$>] .,0,0,0,0,{$7%} rm. done 44071 44072fx_mess_with_bits_preview : 44073 gui_split_preview "fx_mess_with_bits $*",${-3--1} 44074 44075#@gui Noise [Additive] : fx_noise, fx_noise_preview(0) 44076#@gui : Amplitude = float(10,0,200) 44077#@gui : Noise Type = choice("Gaussian","Uniform","Salt and Pepper","Poisson") 44078#@gui : sep = separator() 44079#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44080#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44081#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44082#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44083#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44084#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44085#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44086#@gui : Value Action = choice(1,"None","Cut","Normalize") 44087#@gui : sep = separator() 44088#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44089#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44090#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44091#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44092#@gui : sep = separator() 44093#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44094fx_noise : 44095 ac "_fx_noise $1,$2",$3,$4 44096 44097_fx_noise : 44098 repeat $! l[$>] split_opacity l[0] noise $1,$2 endl a c endl done 44099 44100fx_noise_preview : 44101 gui_split_preview "fx_noise $*",${-3--1} 44102 44103#@gui Noise [Perlin] : fx_noise_perlin, fx_noise_perlin_preview(1) 44104#@gui : Random Seed = int(0,0,65536) 44105#@gui : sep = separator() 44106#@gui : note = note("<small><b>1st scale:</b></small>") 44107#@gui : Amplitude = float(100,0,512) 44108#@gui : Scale (%) = float(8,0,100) 44109#@gui : X/Y-Ratio = float(0,-4,4) 44110#@gui : sep = separator() 44111#@gui : note = note("<small><b>2nd scale:</b></small>") 44112#@gui : Amplitude = float(0,0,512) 44113#@gui : Scale (%) = float(4,0,100) 44114#@gui : X/Y-Ratio = float(0,-4,4) 44115#@gui : sep = separator() 44116#@gui : note = note("<small><b>3rd scale:</b></small>") 44117#@gui : Amplitude = float(0,0,512) 44118#@gui : Scale (%) = float(2,0,100) 44119#@gui : X/Y-Ratio = float(0,-4,4) 44120#@gui : sep = separator() 44121#@gui : note = note("<small><b>4th scale:</b></small>") 44122#@gui : Amplitude = float(0,0,512) 44123#@gui : Scale (%) = float(1,0,100) 44124#@gui : X/Y-Ratio = float(0,-4,4) 44125#@gui : sep = separator() 44126#@gui : Channel(s) = choice(2,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44127#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44128#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44129#@gui : "YCbCr [Green chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44130#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44131#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44132#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]") 44133#@gui : sep = separator() 44134#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44135#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44136#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44137#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44138#@gui : sep = separator() 44139#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/01/24</i>.</small>") 44140_fx_noise_perlin : 44141 seedx,seedy={[$1>>8,$1&255]} 44142 repeat $! l[$>] 44143 if $2 .,.,1,. noise_perlin. {r=2^$4;s=max(w,h)*$3%;[max(1,s/r),max(1,s*r)]},1,$seedx,$seedy *. $2 + fi 44144 if $5 .,.,1,. noise_perlin. {r=2^$7;s=max(w,h)*$6%;[max(1,s/r),max(1,s*r)]},1,$seedx,$seedy *. $5 + fi 44145 if $8 .,.,1,. noise_perlin. {r=2^$10;s=max(w,h)*$9%;[max(1,s/r),max(1,s*r)]},1,$seedx,$seedy *. $8 + fi 44146 if $11 .,.,1,. noise_perlin. {r=2^$13;s=max(w,h)*$12%;[max(1,s/r),max(1,s*r)]},1,$seedx,$seedy *. $11 + fi 44147 endl done 44148 44149fx_noise_perlin : 44150 ac "_fx_noise_perlin $*",$-4,1 44151 44152fx_noise_perlin_preview : 44153 gui_split_preview "fx_noise_perlin $*",${-3--1} 44154 44155#@gui Noise [Spread] : fx_spread, fx_spread_preview(0) 44156#@gui : X-Variations = float(4,0,20) 44157#@gui : Y-Variations = float(4,0,20) 44158#@gui : sep = separator() 44159#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44160#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44161#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44162#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44163#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44164#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44165#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44166#@gui : Value Action = choice("None","Cut","Normalize") 44167#@gui : sep = separator() 44168#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44169#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44170#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44171#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44172#@gui : sep = separator() 44173#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44174fx_spread : 44175 ac "spread $1,$2",$3,$4 44176 44177fx_spread_preview : 44178 gui_split_preview "fx_spread $*",${-3--1} 44179 44180#@gui Old-Movie Stripes : fx_stripes_y, fx_stripes_y_preview(1) 44181#@gui : Frequency = float(10,0,100) 44182#@gui : sep = separator() 44183#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44184#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44185#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44186#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44187#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44188#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44189#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44190#@gui : Value Action = choice("None","Cut","Normalize") 44191#@gui : sep = separator() 44192#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44193#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44194#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44195#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44196#@gui : sep = separator() 44197#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44198fx_stripes_y : 44199 ac "stripes_y $1",$2,$3 44200 44201fx_stripes_y_preview : 44202 gui_split_preview "fx_stripes_y $*",${-3--1} 44203 44204#@gui Oldschool 8bits : fx_8bits, fx_8bits_preview(0) 44205#@gui : Scale = float(25,1,100) 44206#@gui : Dithering = float(800,0,10000) 44207#@gui : Levels = int(16,2,256) 44208#@gui : sep = separator() 44209#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44210#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44211#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44212#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44213#@gui : sep = separator() 44214#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/02/11</i>.</small>") 44215fx_8bits : 44216 remove_opacity repeat $! l[$>] 44217 w={w} h={h} 44218 r $1%,$1%,1,100%,2 44219 +luminance sharpen. $2 otsu. 256 blend[-2,-1] shapeaverage0 44220 l. s c quantize $3,1,1 a c endl 44221 r. $w,$h,1,100%,1 44222 endl done 44223 44224fx_8bits_preview : 44225 gui_split_preview "fx_8bits $*",${-3--1} 44226 44227#@gui Pixel Sort : fx_pixelsort, fx_pixelsort_preview(1)+ 44228#@gui : note = note{"<small><b>Sorting parameters:</b></small>"} 44229#@gui : Order = choice(1,"Decreasing","Increasing") 44230#@gui : Axis = choice("X-axis","Y-axis","X-axis Then Y-axis","Y-axis Then X-axis") 44231#@gui : Sorting Criterion = choice("Red","Green","Blue","Intensity","Luminance","Lightness","Hue", 44232#@gui : "Saturation","Minimum","Maximum","Random") 44233#@gui : sep = separator() 44234#@gui : note = note{"<small><b>Masking parameters:</b></small>"} 44235#@gui : Mask By = choice(1,"Bottom Layer","Criterion","Contours","Random") 44236#@gui : Lower Mask Threshold (%) = float(0,0,100) 44237#@gui : Higher Mask Threshold (%) = float(100,0,100) 44238#@gui : Mask Smoothness (%) = float(0,0,5) 44239#@gui : Invert Mask = bool(0) 44240#@gui : Preview Mask = bool(0) 44241#@gui : sep = separator() 44242#@gui : note = note{"<small><b>Note:</b> 44243#@gui : This filter implements one version of the algorithm described here : 44244#@gui : </small>"} 44245#@gui : url = link("http://satyarth.me/articles/pixel-sorting/") 44246#@gui : sep = separator() 44247#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/10/29</i>.</small>") 44248fx_pixelsort : 44249 _fx_pixelsort ${1-8},0 44250 44251_fx_pixelsort : 44252 repeat $!-($4==0) l[$>] 44253 if $3==0 +to_rgb channels. 0 # Red 44254 elif $3==1 +to_rgb channels. 1 # Green 44255 elif $3==2 +to_rgb channels. 2 # Blue 44256 elif $3==3 +compose_channels + # Intensity 44257 elif $3==4 +luminance # Luminance 44258 elif $3==5 +to_rgb rgb2hsl. channels. 2 # Lightness 44259 elif $3==6 +to_rgb rgb2hsl. channels. 0 # Hue 44260 elif $3==7 +to_rgb rgb2hsl. channels. 1 # Saturation 44261 elif $3==8 +compose_channels min # Minimum 44262 elif $3==9 +compose_channels max # Maximum 44263 else 100%,100%,1,1 rand. 0,100 # Random 44264 fi 44265 if $4==0 pass. 0 norm. 44266 elif $4==1 . 44267 elif $4==2 +gradient_norm[0] 44268 else +rand. 0,100 44269 fi 44270 b. $7% ir. $5%,{$6+0.01}% 44271 if $8 ==. 0 fi 44272 if $9 k. * 255 44273 else pixelsort[0] {`$1?_'+':_'-'`},{`$2==0?'x':$2==1?'y':$2==2?'xy':'yx'`},[1],[2] k[0] 44274 fi 44275 endl done 44276 44277fx_pixelsort_preview : 44278 _fx_pixelsort $* 44279 44280#@gui Rain & Snow : fx_rain, fx_rain_preview(0) 44281#@gui : Angle = float(65,-180,180) 44282#@gui : Speed = float(10,0,50) 44283#@gui : Density (%) = float(50,0,100) 44284#@gui : Radius = float(0.1,0,3) 44285#@gui : Gamma = float(1,0,2) 44286#@gui : Opacity = float(1,0,1) 44287#@gui : sep = separator() 44288#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44289#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44290#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44291#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44292#@gui : sep = separator() 44293#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/29/06</i>.</small>") 44294fx_rain : 44295 repeat $! l[$<] nm=${-gui_layer_name} 44296 100%,100% l. 44297 noise 300 c 0,255 b 1,0 44298 c {100-$3}%,100% 44299 +>= 40% blend shapeaverage0 44300 blur_linear $2,$4,$1 44301 max n 0,255 apply_gamma $5 44302 nm name($nm),mode(screen),opacity({$6*100}) 44303 endl 44304 rv 44305 endl done 44306 44307fx_rain_preview : 44308 gui_split_preview "repeat $! l[$>] fx_rain $* rv blend screen,$6 endl done",${-3--1} 44309 44310#@gui Random Shade Stripes : fx_shade_stripes, fx_shade_stripes_preview(1) 44311#@gui : Frequency = float(30,1,100) 44312#@gui : Orientation = choice(1,"Horizontal","Vertical") 44313#@gui : Darkness = float(0.8,0,3) 44314#@gui : Lightness = float(1.3,0,3) 44315#@gui : sep = separator() 44316#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44317#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44318#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44319#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44320#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44321#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44322#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44323#@gui : Value Action = choice("None","Cut","Normalize") 44324#@gui : sep = separator() 44325#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44326#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44327#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44328#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44329#@gui : sep = separator() 44330#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44331fx_shade_stripes : 44332 ac "shade_stripes $1,$2,$3,$4",$5,$6 44333 44334fx_shade_stripes_preview : 44335 gui_split_preview "fx_shade_stripes $*",${-3--1} 44336 44337#@gui Rebuild From Similar Blocs : fx_rebuild_from_similar_blocs, fx_rebuild_from_similar_blocs(1) 44338#@gui : Bloc Size (%) = float(5,2,50) 44339#@gui : sep = separator() 44340#@gui : Regularization factor = float(10,0,20) 44341#@gui : Luminance factor = float(0.75,0,3) 44342#@gui : Norm type = choice(1,"L1","L2") 44343#@gui : sep = separator() 44344#@gui : note = note{"This filter subdivides the image into blocs, and replace each bloc by the most similar bloc 44345#@gui : found in the other blocs."} 44346#@gui : sep = separator() 44347#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/09/17</i>.</small>") 44348fx_rebuild_from_similar_blocs : 44349 repeat $! l[$>] split_opacity l[0] to_rgb 44350 w0,h0,S={[w,h,round(min(w,h)*$1%)]} # S: Bloc size 44351 44352 # Split image into regular blocs. 44353 r {ceil([w,h]/$S)*$S},1,100%,0,3,0.5,0.5 44354 M,N={[w,h]/$S} 44355 44356 s yx,-$S a z # Original RGB blocs 44357# +mirror x +mirror y a z # + all xy mirrors 44358# repeat 3 +rotate. 90 done a z # + all 90° rotations 44359 +l b xy,$2% rgb2ycbcr sh. 0 *. $3 rm. endl # Blocs to compare, in YCbCr space 44360 44361 # For each bloc, find most similar bloc. 44362 $M,$N,1,1,-1 44363 f. ": 44364 i<0?( 44365 ind = x + y*w; 44366 ref(crop(#1,0,0,ind,w#1,h#1,1),S); 44367 kmin = 0; 44368 dmin = inf; 44369 repeat (wh,k, k!=ind?( 44370 d = norm"{1+$4}"(S - crop(#1,0,0,k,w#1,h#1,1)); 44371 d<dmin?(dmin = d; kmin = k); 44372 )); 44373 xt = kmin%w; 44374 yt = int(kmin/w); 44375 i(xt,yt) = ind; 44376 kmin; 44377 ):i" 44378 44379 # Reconstruct image. 44380 {[$M,$N]*$S},1,{0,s} 44381 eval.. "draw(#-1,crop(#0,0,0,i,w#0,h#0,1),x*w#0,y*h#0,0,0,w#0,h#0)" 44382 k. r $w0,$h0,1,100%,0,0,0.5,0.5 44383 endl a c endl done 44384 44385#@gui Scanlines : fx_scanlines, fx_scanlines_preview(0) 44386#@gui : Amplitude = float(60,0,255) 44387#@gui : Bandwidth = float(2,1,300) 44388#@gui : Shape = choice(0,"Bloc","Triangle","Sine","Sine+","Random") 44389#@gui : Angle = float(0,0,360) 44390#@gui : Offset = float(0,0,500) 44391#@gui : sep = separator() 44392#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44393#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44394#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44395#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44396#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44397#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44398#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44399#@gui : Value Action = choice("None","Cut","Normalize") 44400#@gui : sep = separator() 44401#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44402#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44403#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44404#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44405#@gui : sep = separator() 44406#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/19/11</i>.</small>") 44407fx_scanlines : 44408 ac "scanlines ${1-5}",$6,$7 44409 44410fx_scanlines_preview : 44411 gui_split_preview "fx_scanlines $*",${-3--1} 44412 44413#@gui Self Glitching : fx_self_glitching, fx_self_glitching_preview(1) 44414#@gui : Multiplier = float(0,-5,5) 44415#@gui : Bias = float(0,-255,255) 44416#@gui : Negate = bool(0) 44417#@gui : Operator = choice("Add","Mul","And","Or","Xor","Pow","Reverse Pow","Mod","Reverse Mod") 44418#@gui : Shift Point = point(50,50,0,1) 44419#@gui : Boundary = choice(3,"Zero","Nearest","Periodic","Mirror") 44420#@gui : sep = separator() 44421#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44422#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44423#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44424#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44425#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44426#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44427#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44428#@gui : sep = separator() 44429#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44430#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44431#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44432#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44433#@gui : sep = separator() 44434#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/08/19</i>.</small>") 44435fx_self_glitching : 44436 ac "_fx_self_glitching ${1-7}",$8 44437 44438_fx_self_glitching : 44439 f "begin( 44440 shift = ([w,h]-1)*(50-[$5,$6])%; 44441 const sign = $3?-1:1; 44442 const boundary = $7; 44443 ); 44444 val = sign*((2^$1)*j(shift) + $2); 44445 ($4==0?(val + i): 44446 $4==1?(val * i): 44447 $4==2?(val & i): 44448 $4==3?(val | i): 44449 $4==4?xor(val,i): 44450 $4==5?(val^i): 44451 $4==6?(i^val): 44452 $4==7?(val%i): 44453 (i%val) 44454 )%256; 44455 " 44456 44457fx_self_glitching_preview : 44458 gui_split_preview "fx_self_glitching $*",${-3--1} 44459 44460#@gui Streak : fx_streak,fx_streak(1) 44461#@gui : Mask Color = color(255,0,0,255) 44462#@gui : Step (%) = float(0,0,30) 44463#@gui : Angle = float(0,0,360) 44464#@gui : Propagation = choice(3,"Backward","Forward","Bidirectional [Sharp]","Bidirectional [Smooth]") 44465#@gui : sep = separator() 44466#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/12/22</i>.</small>") 44467fx_streak : 44468 repeat $! l[$>] 44469 to_rgba 44470 if !$4 R,G,B,A=0 else R,G,B,A=${1-4} fi +select_color 0,$R,$G,$B,$A 44471 if $7==3 srgb2rgb.. fi 44472 f.. " 44473 const step = max(1,$5%*min(w,h)); 44474 const angle = $6*pi/180; 44475 const dx = step*cos(angle); 44476 const dy = step*sin(angle); 44477 if (!i(#-1),I, 44478 ixf = xf = x; iyf = yf = y; lf = 0; 44479 if ($7>=1, while (i(#-1,ixf=round(xf),iyf=round(yf)), ++lf; xf-=dx; yf-=dy)); # Forward 44480 ixb = xb = x; iyb = yb = y; lb = 0; 44481 if ($7!=1, while (i(#-1,ixb=round(xb),iyb=round(yb)), ++lb; xb+=dx; yb+=dy)); # Backward 44482 $7==0?I(ixb,iyb): 44483 $7==1?I(ixf,iyf): 44484 $7==2?(lf<lb?I(ixf,iyf):I(ixb,iyb)): 44485 (lb*lb*I(ixf,iyf) + lf*lf*I(ixb,iyb))/(lb^2+lf^2); 44486 )" 44487 if $7==3 rgb2srgb.. fi 44488 rm. 44489 endl done 44490 44491#@gui Visible Watermark : fx_watermark_visible, fx_watermark_visible(0) 44492#@gui : Text = text{"\\251 G'MIC"} 44493#@gui : Opacity = float(0.4,0.1,0.9) 44494#@gui : Size = int(50,13,128) 44495#@gui : Angle = float(25,0,360) 44496#@gui : Smoothness = float(0.5,0,5) 44497#@gui : Lightness = choice(1,"Darker","Brighter") 44498#@gui : sep = separator() 44499#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44500fx_watermark_visible : skip "${1= }" 44501 watermark_visible "$1",$2,$3,$4,$6,$5 44502 44503#@gui Warp by Intensity : fx_warp_by_intensity, fx_warp_by_intensity_preview(0) 44504#@gui : X-Factor = float(0.04,-6,6) 44505#@gui : Y-Factor = float(0.04,-6,6) 44506#@gui : sep = separator() 44507#@gui : X-Offset = float(128,0,255) 44508#@gui : Y-Offset = float(128,0,255) 44509#@gui : sep = separator() 44510#@gui : Correlated Channels = bool(0) 44511#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 44512#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 44513#@gui : sep = separator() 44514#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44515#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44516#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44517#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44518#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44519#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44520#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44521#@gui : sep = separator() 44522#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44523#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44524#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44525#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44526#@gui : sep = separator() 44527#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/02/09</i>.</small>") 44528fx_warp_by_intensity : 44529 if !$7 to_a fi 44530 ac "_fx_warp_by_intensity ${1-7}",$8 44531 44532_fx_warp_by_intensity : 44533 if $5 f "ni = norm2(R,G,B); J((ni-$3)*$1,(ni-$4)*$2,0,$6,$7)" 44534 else f "j((i-$3)*$1,(i-$4)*$2,0,0,$6,$7)" 44535 fi 44536 44537fx_warp_by_intensity_preview : 44538 gui_split_preview "fx_warp_by_intensity $*",${-3--1} 44539 44540#@gui ____<b>Details</b> 44541#------------------------ 44542 44543#@gui Details Equalizer : fx_equalize_details, fx_equalize_details_preview(0) 44544#@gui : Base Scale = float(5,0,15) 44545#@gui : Detail Scale = float(0.5,0,5) 44546#@gui : note = note("<small><b>Coarse scale:</b></small>") 44547#@gui : Threshold = float(0,0,10) 44548#@gui : Smoothness = float(0,0,10) 44549#@gui : Smoothness Type = choice(2,"Gaussian","Bilateral","Diffusion") 44550#@gui : Gain = float(0,-4,4) 44551#@gui : sep = separator() 44552#@gui : note = note("<small><b>Medium scale:</b></small>") 44553#@gui : Threshold = float(0,0,10) 44554#@gui : Smoothness = float(0,0,10) 44555#@gui : Smoothness Type = choice(2,"Gaussian","Bilateral","Diffusion") 44556#@gui : Gain = float(0,-4,4) 44557#@gui : sep = separator() 44558#@gui : note = note("<small><b>Small scale:</b></small>") 44559#@gui : Threshold = float(0,0,10) 44560#@gui : Smoothness = float(0,0,10) 44561#@gui : Smoothness Type = choice(2,"Gaussian","Bilateral","Diffusion") 44562#@gui : Gain = float(0,-4,4) 44563#@gui : sep = separator() 44564#@gui : note = note("<small><b>Fine scale:</b></small>") 44565#@gui : Threshold = float(0,0,10) 44566#@gui : Smoothness = float(0,0,10) 44567#@gui : Smoothness Type = choice(2,"Gaussian","Bilateral","Diffusion") 44568#@gui : Gain = float(0,-4,4) 44569#@gui : sep = separator() 44570#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44571#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44572#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44573#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44574#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44575#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44576#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44577#@gui : Value Action = choice("None","Cut","Normalize") 44578#@gui : sep = separator() 44579#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 44580#@gui : "Sixteen Threads"), Spatial Overlap = int(32,0,256) 44581#@gui : sep = separator() 44582#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44583#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44584#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44585#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44586#@gui : sep = separator() 44587#@gui : note = note("<small>Author: <i>Jérome Boulanger</i> and <i>David Tschumperlé</i>. 44588#@gui : Latest Update: <i>2015/11/11</i>.</small>") 44589_fx_equalize_details : 44590 repeat $! l[$>] 44591 split_details 5,{max(0.1,$1)},{max(0.1,$2)} 44592 __fx_equalize_details[1] ${3-6},8 44593 __fx_equalize_details[2] ${7-10},4 44594 __fx_equalize_details[3] ${11-14},2 44595 __fx_equalize_details[4] ${15-18},1 44596 + c 0,255 44597 endl done 44598 44599__fx_equalize_details : 44600 threshold $1,1 44601 if $3==0 b {$2*$5/2} 44602 elif $3==1 44603 if $2>0 44604 m={im} M={iM} n. 0,255 44605 repeat int($2/5) bilateral 15,{5*$5} done 44606 bilateral 15,{($2%5)*$5} 44607 *. {($M-$m)/255} +. $m 44608 fi 44609 else smooth {$2*50},0.2,0.8,$5,$5 fi 44610 * {10^$4} 44611 44612fx_equalize_details : 44613 ac "gui_parallel_overlap \"_fx_equalize_details ${1-18}\",$21,$22",$19,$20 44614 44615fx_equalize_details_preview : 44616 gui_split_preview "fx_equalize_details $*",${-3--1} 44617 44618#@gui Equalize Local Histograms : fx_equalize_local_histograms, fx_equalize_local_histograms_preview(0) 44619#@gui : Strength (%) = float(75,0,100) 44620#@gui : Mode = choice(2,"Raw","Hard","Soft") 44621#@gui : Radius = int(4,1,16) 44622#@gui : Sigma = float(100,0,256) 44623#@gui : Regularization = float(8,0,32) 44624#@gui : Reduce Halos = bool(1) 44625#@gui : sep = separator() 44626#@gui : Channel(s) = choice(16,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44627#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44628#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44629#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44630#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44631#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44632#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44633#@gui : sep = separator() 44634#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44635#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44636#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44637#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44638#@gui : sep = separator() 44639#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/31</i>.</small>") 44640fx_equalize_local_histograms : 44641 b0="normal" b1="overlay" b2="softlight" 44642 repeat $! l[$>] 44643 +ac "_fx_equalize_local_histograms ${1-6}",$7,1 44644 blend ${b$2},{$1%} 44645 endl done 44646 44647_fx_equalize_local_histograms : 44648 +n 0,511 round. 44649 f. " 44650 begin( 44651 const boundary = 1; 44652 const N = $3; 44653 const sigma = ($6?1:-1)*(0.1+$4); 44654 ref(vector512(),weights); 44655 repeat (size(weights),k, # Pre-compute exponentials 44656 weights[k] = sigma>=0?exp(-sqr(k/sigma)):1 - exp(-sqr(k/sigma)) 44657 ); 44658 ); 44659 44660 ref(vector512(0),bins); 44661 44662 repeat (s,c, 44663 ref(crop(x - N,y - N,0,c,2*N + 1,2*N + 1,1,1),V); 44664 repeat (size(V),k, # Compute local weighted histogram 44665 val = V[k]; 44666 diff = abs(val - V[size(V)/2]); 44667 bins[val]+=weights[diff]; 44668 ); 44669 ); 44670 44671 sum = 0; 44672 repeat (size(bins),k, 44673 sum+=bins[k]; 44674 bins[k] = sum; 44675 ); 44676 bins/=max(1e-5,sum); 44677 44678 P = I; 44679 size(P)==1?(P = bins[P[0]]; 0): 44680 size(P)==2?(P = [ bins[P[0]], bins[P[1]] ]; 0): 44681 size(P)==3?(P = [ bins[P[0]], bins[P[1]], bins[P[2]] ]; 0): 44682 size(P)==4?(P = [ bins[P[0]], bins[P[1]], bins[P[2]], bins[P[3]] ]; 0); 44683 P" 44684 n. 0,255 44685 if $5 norm.. bilateral. ..,$5,{2+$5} fi 44686 k. 44687 44688fx_equalize_local_histograms_preview : 44689 gui_split_preview "fx_equalize_local_histograms $*",${-3--1} 44690 44691#@gui Freaky Details : fx_freaky_details, fx_freaky_details_preview(0) 44692#@gui : Amplitude = int(2,1,5) 44693#@gui : Scale = float(10,0,100) 44694#@gui : Iterations = int(1,1,4) 44695#@gui : sep = separator() 44696#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44697#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44698#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44699#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44700#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44701#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44702#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44703#@gui : sep = separator() 44704#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44705#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44706#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44707#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44708#@gui : sep = separator() 44709#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Patrick David</i>. 44710#@gui : Latest Update: <i>2013/27/02</i>.</small>") 44711#@gui : sep = separator() 44712#@gui : note = note("This effect has been done following:") 44713#@gui : url = link("This tutorial from Patrick David", 44714#@gui : "https://patdavid.net/2013/02/calvin-hollywood-freaky-details-in-gimp.html") 44715fx_freaky_details : 44716 repeat $! l[$>] split_opacity l[0] 44717 repeat $3 44718 . +-. 255 *. -1 44719 repeat $1 bilateral. $2,{1.5*$2} done 44720 blend[-2,-1] vividlight blend overlay 44721 done 44722 endl a c endl done n 0,255 44723 44724fx_freaky_details_preview : 44725 gui_split_preview "fx_freaky_details $*",${-3--1} 44726 44727#@gui Local Normalization : fx_normalize_local, fx_normalize_local_preview(0) 44728#@gui : Amplitude = float(2,0,60) 44729#@gui : Radius = int(6,1,64) 44730#@gui : Neighborhood Smoothness = float(5,0,40) 44731#@gui : Average Smoothness = float(20,0,40) 44732#@gui : Constrain Values = bool(1) 44733#@gui : sep = separator() 44734#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44735#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44736#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44737#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44738#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44739#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44740#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44741#@gui : sep = separator() 44742#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44743#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44744#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44745#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44746#@gui : sep = separator() 44747#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44748fx_normalize_local : 44749 repeat $! l[$>] 44750 ac "normalize_local $1,$2,$3,$4,$5,0,255",$6 44751 endl done 44752 44753fx_normalize_local_preview : 44754 gui_split_preview "fx_normalize_local $*",${-3--1} 44755 44756#@gui Local Processing : fx_local_processing, fx_local_processing_preview(1) 44757#@gui : Action = choice("Normalize","Equalize") 44758#@gui : Strength (%) = float(75,0,100) 44759#@gui : Neighborhood Size (%) = float(10,1,100) 44760#@gui : Overlap (%) = float(50,0,75) 44761#@gui : Regularization (%) = float(20,0,100) 44762#@gui : Process Channels Individually = bool(0) 44763#@gui : sep = separator() 44764#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44765#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44766#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44767#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44768#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44769#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44770#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44771#@gui : sep = separator() 44772#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44773#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44774#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44775#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44776#@gui : sep = separator() 44777#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/02/28</i>.</small>") 44778fx_local_processing : 44779 com0="n 0,255" 44780 com1="equalize 256,0,255 n 0,255" 44781 com=${com$1} 44782 if $6 com="s c "$com" a c" fi 44783 repeat $! l[$>] 44784 size={round(max(8,max(w,h)*$3%))} 44785 +ac "at \""$com"\","$size","$size",1,$4%,$4%",$7 44786 if $5 +norm[0] bilateral[1] .,{$5/20}%,{2+$5/4} rm. fi 44787 blend alpha,{$2%} 44788 endl done 44789 44790fx_local_processing_preview : 44791 gui_split_preview "fx_local_processing $*",${-3--1} 44792 44793#@gui Magic Details : fx_magic_details,fx_magic_details_preview(0) 44794#@gui : Amplitude = float(6,0,30) 44795#@gui : Spatial Scale = float(3,0,10) 44796#@gui : Value Scale = float(15,0,20) 44797#@gui : Edges = float(-0.5,-3,3) 44798#@gui : Smoothness = float(2,0,20) 44799#@gui : sep = separator() 44800#@gui : Channel(s) = choice(27,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44801#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44802#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44803#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44804#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44805#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44806#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]") 44807#@gui : sep = separator() 44808#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44809#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44810#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44811#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44812#@gui : sep = separator() 44813#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/10</i>.</small>") 44814fx_magic_details : 44815 ac "_fx_magic_details ${1-5}",$6,1 44816 44817_fx_magic_details : 44818 repeat $! l[$>] 44819 +bilateral $2,$3 44820 +gradient_norm.. +. 1 44821 pow. {$4>=0?3.1-$4:-3.1-$4} 44822 b. $5 n. 1,{1+$1} 44823 -... .. *[-3,-1] + c 0,255 44824 endl done 44825 44826fx_magic_details_preview : 44827 gui_split_preview "fx_magic_details $*",${-3--1} 44828 44829#@gui Mighty Details : fx_mighty_details, fx_mighty_details_preview(0) 44830#@gui : Amplitude = float(25,0,100) 44831#@gui : Details Amount = float(1,0,2) 44832#@gui : Details Scale = float(25,1,100) 44833#@gui : Details Smoothness = int(1,0,10) 44834#@gui : sep = separator() 44835#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44836#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44837#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44838#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44839#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44840#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44841#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44842#@gui : sep = separator() 44843#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44844#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44845#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44846#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44847#@gui : sep = separator() 44848#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/08/08</i>.</small>") 44849_fx_mighty_details : 44850 +smooth $3,0,1,0.5,0.5 -[1] [0] 44851 +abs. sign.. M={iM} ^. {2-$2} *. {$M/iM} *[-2,-1] 44852 +diffusiontensors[0] 0,1,0.5,0.5 44853 repeat $4 smooth[1] [2],20 done 44854 *[1] {-$1/5} + 44855 44856fx_mighty_details : 44857 ac "_fx_mighty_details ${1-4}",$5,1 44858 n 0,255 44859 44860fx_mighty_details_preview : 44861 gui_split_preview "fx_mighty_details $*",${-3--1} 44862 44863#@gui Sharpen [Deblur] : fx_deblur, fx_deblur_preview(0) 44864#@gui : Radius = float(2,0,20) 44865#@gui : Iterations = int(10,0,100) 44866#@gui : Time Step = float(20,0,50) 44867#@gui : Smoothness = float(0.1,0,10) 44868#@gui : Regularization = choice(1,"Tikhonov","Mean Curvature","Total Variation") 44869#@gui : sep = separator() 44870#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44871#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44872#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44873#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44874#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44875#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44876#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44877#@gui : sep = separator() 44878#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 44879#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 44880#@gui : sep = separator() 44881#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44882#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44883#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44884#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44885#@gui : sep = separator() 44886#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44887fx_deblur : 44888 ac "gui_parallel_overlap \"deblur ${1-5} c 0,255\",$7,$8",$6,1 44889 44890fx_deblur_preview : 44891 gui_split_preview "fx_deblur $*",${-3--1} 44892 44893#@gui Sharpen [Gold-Meinel] : fx_unsharp_goldmeinel, fx_unsharp_goldmeinel_preview(0) 44894#@gui : Sigma = float(1,0.5,10) 44895#@gui : Iterations = int(5,1,15) 44896#@gui : Acceleration = float(1,1,3) 44897#@gui : Blur = choice(1,"Exponential","Gaussian") 44898#@gui : Cut = bool(true) 44899#@gui : sep = separator() 44900#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44901#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44902#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44903#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44904#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44905#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44906#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44907#@gui : sep = separator() 44908#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 44909#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 44910#@gui : sep = separator() 44911#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44912#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44913#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44914#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44915#@gui : sep = separator() 44916#@gui : note = note("<small>Author: <i>Jérôme Boulanger</i>. Latest Update: <i>2013/29/03</i>.</small>") 44917fx_unsharp_goldmeinel: 44918 ac "gui_parallel_overlap \"_fx_unsharp_goldmeinel $*\",$7,$8",$6,1 44919 44920_fx_unsharp_goldmeinel : 44921 deblur_goldmeinel $* 44922 if $5 c 0,255 else n 0,255 fi 44923 44924fx_unsharp_goldmeinel_preview: 44925 gui_split_preview "fx_unsharp_goldmeinel $*",${-3--1} 44926 44927#@gui Sharpen [Inverse Diffusion] : fx_sharpen_inversediff, fx_sharpen_inversediff_preview(0) 44928#@gui : Amplitude = float(50,1,300) 44929#@gui : Iterations = int(2,1,10) 44930#@gui : sep = separator() 44931#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44932#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44933#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44934#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44935#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44936#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44937#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44938#@gui : sep = separator() 44939#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44940#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44941#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44942#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44943#@gui : sep = separator() 44944#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44945fx_sharpen_inversediff : 44946 ac "repeat $2 sharpen $1 c 0,255 done",$3,1 44947 44948fx_sharpen_inversediff_preview : 44949 gui_split_preview "fx_sharpen_inversediff $*",${-3--1} 44950 44951#@gui Sharpen [Multiscale] : fx_sharpen_multiscale, fx_sharpen_multiscale_preview(0) 44952#@gui : Strength (%) = float(15,0,100) 44953#@gui : Regularity (%) = float(20,0,100) 44954#@gui : sep = separator() 44955#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44956#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44957#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44958#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44959#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44960#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44961#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44962#@gui : sep = separator() 44963#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44964#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44965#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44966#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44967#@gui : sep = separator() 44968#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/01/14</i>.</small>") 44969fx_sharpen_multiscale : 44970 ac "_fx_sharpen_multiscale $1,$2",$3 44971 44972fx_sharpen_multiscale_preview : 44973 gui_split_preview "fx_sharpen_multiscale $*",${-3--1} 44974 44975_fx_sharpen_multiscale : 44976 repeat $! l[$>] 44977 N={max(1,int(log2(min(w,h))-2))} 44978 +l repeat $N +r. 50%,50%,1,100%,2 +r. ..,..,1,100%,5 -[-3,-1] done endl # Decompose 44979 guided[0] 4,100 # Smooth guide image 44980 44981 # Process each scale. 44982 repeat $!-1 l[0,{$>+1}] 44983 +ri[0] [1],2 44984 +equalize.. 1024 44985 bilateral. ..,{2*$2%},100 44986 j[1] .,0,0,0,0,{$1%} 44987 k[0,1] 44988 endl done 44989 rm[0] 44990 44991 repeat $!-1 r. ..,..,1,100%,5 +[-2,-1] done # Recompose 44992 c 0,255 44993 endl done 44994 44995#@gui Sharpen [Octave Sharpening] : fx_unsharp_octave, fx_unsharp_octave_preview(0) 44996#@gui : Scales = int(4,1,10) 44997#@gui : Maximal Radius = float(5,0,20) 44998#@gui : Amount = float(3,0,10) 44999#@gui : Threshold = float(0,0,255) 45000#@gui : sep = separator() 45001#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45002#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45003#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45004#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45005#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45006#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45007#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45008#@gui : sep = separator() 45009#@gui : Parallel Processing = choice(1,"Auto","One Thread","Two Threads","Four Threads","Eight Threads", 45010#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 45011#@gui : sep = separator() 45012#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45013#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45014#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45015#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45016#@gui : sep = separator() 45017#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45018fx_unsharp_octave : 45019 ac "gui_parallel_overlap \"unsharp_octave $1,$2,$3,$4\",$6,$7",$5,1 45020 45021fx_unsharp_octave_preview : 45022 gui_split_preview "fx_unsharp_octave $*",${-3--1} 45023 45024#@gui Sharpen [Richardson-Lucy] : fx_unsharp_richardsonlucy, fx_unsharp_richardsonlucy_preview 45025#@gui : Sigma = float(1,0.5,10) 45026#@gui : Iterations = int(10,1,100) 45027#@gui : Blur = choice(1,"Exponential","Gaussian") 45028#@gui : Cut = bool(true) 45029#@gui : sep = separator() 45030#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45031#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45032#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45033#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45034#@gui : sep = separator() 45035#@gui : note = note("<small>Author: <i>Jérôme Boulanger</i>. Latest Update: <i>2013/29/03</i>.</small>") 45036fx_unsharp_richardsonlucy : 45037 deblur_richardsonlucy $* 45038 if $4 c 0,255 else n 0,255 fi 45039 45040fx_unsharp_richardsonlucy_preview : 45041 gui_split_preview "fx_unsharp_richardsonlucy $*",${-3--1} 45042 45043#@gui Sharpen [Shock Filters] : fx_sharpen_shock, fx_sharpen_shock_preview(0) 45044#@gui : Amplitude = float(150,1,400) 45045#@gui : Edge Threshold = float(0.1,0,0.7) 45046#@gui : Gradient Smoothness = float(0.8,0,10) 45047#@gui : Tensor Smoothness = float(1.1,0,10) 45048#@gui : Iterations = int(1,1,10) 45049#@gui : sep = separator() 45050#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45051#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45052#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45053#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45054#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45055#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45056#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45057#@gui : sep = separator() 45058#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45059#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45060#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45061#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45062#@gui : sep = separator() 45063#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45064fx_sharpen_shock : 45065 ac "repeat $5 sharpen $1,$2,$3,$4 c 0,255 done",$6,1 45066 45067fx_sharpen_shock_preview : 45068 gui_split_preview "fx_sharpen_shock $*",${-3--1} 45069 45070#@gui Sharpen [Texture] : fx_sharpen_texture, fx_sharpen_texture_preview(0) 45071#@gui : Strength = float(1,0,4) 45072#@gui : Radius = float(4,0,32) 45073#@gui : sep = separator() 45074#@gui : Channel(s) = choice(16,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45075#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45076#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45077#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45078#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45079#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45080#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]") 45081#@gui : sep = separator() 45082#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45083#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45084#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45085#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45086#@gui : sep = separator() 45087#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/09</i>.</small>") 45088fx_sharpen_texture : 45089 ac "_fx_sharpen_texture ${1-2}",$3,1 45090 45091_fx_sharpen_texture : 45092 repeat $! l[$>] 45093 +rolling_guidance $2,5,0.5 -. [0] *. $1 - c 0,255 45094 endl done 45095 45096fx_sharpen_texture_preview : 45097 gui_split_preview "fx_sharpen_texture $*",${-3--1} 45098 45099#@gui Sharpen [Unsharp Mask] : fx_unsharp, fx_unsharp_preview(0) 45100#@gui : Sharpening Type = choice(1,"Gaussian","Bilateral") 45101#@gui : Spatial Radius = float(1.25,0,20) 45102#@gui : Bilateral Radius = float(10,0,60) 45103#@gui : Amount = float(2,0,10) 45104#@gui : Threshold = float(0,0,20) 45105#@gui : Darkness Level = float(1,0,4) 45106#@gui : Lightness Level = float(1,0,4) 45107#@gui : Iterations = int(1,1,10) 45108#@gui : Negative Effect = bool(0) 45109#@gui : sep = separator() 45110#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45111#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45112#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45113#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45114#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45115#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45116#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45117#@gui : sep = separator() 45118#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45119#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45120#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45121#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45122#@gui : note = note{"\n\n<small><b>Note: </b> 45123#@gui : This filter is inspired by the original GIMP <i>Unsharp Mask</i> filter, with additional parameters. 45124#@gui : </small>"} 45125#@gui : sep = separator() 45126#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45127_fx_unsharp : 45128 repeat $! repeat $8 45129 if $1==0 +b. $2 else +bilateral. $2,$3 fi 45130 -. .. *. -$4 45131 +norm. >=. $5% ri. .. *[-2,-1] 45132 if $9 *. -1 fi 45133 +c. 0,100% c.. -100%,0 *.. $6 *. $7 +[-2,-1] 45134 +[-2,-1] c. 0,255 45135 done mv. 0 done 45136 45137fx_unsharp : 45138 ac "_fx_unsharp $1,$2,$3,$4,$5,$6,$7,$8,$9",$10,1 45139 45140fx_unsharp_preview : 45141 gui_split_preview "fx_unsharp $*",${-3--1} 45142 45143#@gui Split Details [Alpha] : fx_split_details_alpha, fx_split_details_alpha_preview(0) 45144#@gui : Number of Levels = int(6,2,8) 45145#@gui : Base Scale = float(10,0,30) 45146#@gui : Details Scale = float(1,0,20) 45147#@gui : Opacity Gain = float(5,1,20) 45148#@gui : sep = separator() 45149#@gui : Preview Without Alpha = bool(0) 45150#@gui : sep = separator() 45151#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/22/04</i>.</small>") 45152fx_split_details_alpha : 45153 remove_opacity 45154 repeat $! l[$<] 45155 repeat $1-1 45156 s={$3+($2-$3)*$>/if($1-2>0,$1-2,1)} 45157 +_fx_split_details_alpha_blur. $s 45158 sub_alpha.. .,$4 45159 done 45160 endl done 45161 45162_fx_split_details_alpha_blur : 45163 if $1>=0.1 b. $1 45164 else 45165 if $1>=0.05 (1,4,7,4,1;4,16,26,16,4;7,26,41,26,7;4,16,26,16,4;1,4,7,4,1) 45166 else (1,2,1;2,4,2;1,2,1) fi 45167 normalize_sum. convolve.. . rm. 45168 fi 45169 45170fx_split_details_alpha_preview : 45171 repeat $! l[$>] 45172 fx_split_details_alpha ${1-4} 45173 if $5 remove_opacity[^-1] else to_rgba. fi 45174 N={int(sqrt($!))} N={round($!/$N,1,1)} r2dy {100/$N}% 45175 repeat $! l[$>] 0 text. "#"{1+$>}" ",1,1,24,1,255 +dilate. 5 to_rgba[1] j[0] [1],2,0,0,0,1,[2],255 k[0] endl done 45176 to_rgba frame 1,1,0 frame 3,3,255 append_tiles , 45177 endl done 45178 45179#@gui Split Details [Gaussian] : fx_split_details_gaussian, fx_split_details_gaussian_preview(0) 45180#@gui : Number of Scales = int(6,3,12) 45181#@gui : Base Scale = float(10,0,200) 45182#@gui : Details Scale = float(1,0,20) 45183#@gui : sep = separator() 45184#@gui : Sharpen Details in Preview = bool(0) 45185#@gui : sep = separator() 45186#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/22/01</i>.</small>") 45187fx_split_details_gaussian : 45188 remove_opacity repeat $! l[$>] 45189 nm=${-gui_layer_name} 45190 pos=${-gui_layer_pos} 45191 split_details $1,$2,$3 45192 +[^0] 128 c[^0] 0,255 round 45193 repeat $!-1 nm[{1+$>}] "mode(grainmerge), name"($nm" [scale ""#"{1+$>}"]), pos("$pos")" done 45194 nm[0] "name"($nm" [residual]), pos("$pos")" 45195 rv 45196 endl done 45197 45198fx_split_details_gaussian_preview : 45199 repeat $! l[$>] 45200 fx_split_details_gaussian $* 45201 if $4 equalize[^-1] 256 fi n[^-1] 0,255 45202 N={int(sqrt($!))} N={round($!/$N,1,1)} r2dy {100/$N}% 45203 repeat $! l[$>] 0 text. "#"{1+$>}" ",1,1,24,1,255 +dilate. 5 to_rgba[1] j[0] [1],2,0,0,0,1,[2],255 k[0] endl done 45204 to_rgba frame 1,1,0 frame 3,3,255 append_tiles , 45205 endl done 45206 45207#@gui Split Details [Wavelets] : fx_split_details_wavelets, fx_split_details_wavelets_preview(0) 45208#@gui : Number of Scales = int(6,2,12) 45209#@gui : Add Alpha Channels to Detail Scale Layers = _bool(0) 45210#@gui : sep = separator() 45211#@gui : Sharpen Details in Preview = bool(0) 45212#@gui : sep = separator() 45213#@gui : note = note{"<small><b>Note:</b> This filter decomposes an image into several detail scales, 45214#@gui : using wavelet atrous. 45215#@gui : It should provide similar results to the 45216#@gui : <a href="http://registry.gimp.org/node/11742">Wavelet Decompose Plug-in</a> 45217#@gui : (by Marco Rossini). 45218#@gui : </small>"} 45219#@gui : sep = separator() 45220#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/23/03</i>.</small>") 45221fx_split_details_wavelets : 45222 remove_opacity repeat $! l[$>] 45223 nm=${-gui_layer_name} 45224 pos=${-gui_layer_pos} 45225 split_details $1,0,0 rv +[^-1] 128 c[^-1] 0,255 round 45226 if $2 to_a[^-1] fi 45227 repeat $!-1 nm[$>] "mode(grainmerge), name"($nm" [scale ""#"{1+$>}"]), pos("$pos")" done 45228 nm. "name"($nm" [residual]), pos("$pos")" 45229 endl done 45230 45231fx_split_details_wavelets_preview : 45232 repeat $! l[$>] 45233 fx_split_details_wavelets $1,0 45234 if $3 equalize[^-1] 256 fi n[^-1] 0,255 45235 N={int(sqrt($!))} N={round($!/$N,1,1)} r2dy {100/$N}% 45236 repeat $! l[$>] 0 text. "#"{1+$>}" ",1,1,24,1,255 +dilate. 5 to_rgba[1] j[0] [1],2,0,0,0,1,[2],255 k[0] endl done 45237 to_rgba frame 1,1,0 frame 3,3,255 append_tiles , 45238 endl done 45239 45240#@gui Tone Mapping : fx_map_tones, fx_map_tones_preview(0) 45241#@gui : Threshold = float(0.5,0,1) 45242#@gui : Gamma = float(0.7,0,1) 45243#@gui : Smoothness = float(0.1,0,10) 45244#@gui : Iterations = int(30,0,500) 45245#@gui : sep = separator() 45246#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45247#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45248#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45249#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45250#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45251#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45252#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45253#@gui : sep = separator() 45254#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45255#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45256#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45257#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45258#@gui : sep = separator() 45259#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45260fx_map_tones : 45261 ac "map_tones ${1-4}",$5,1 45262 n 0,255 45263 45264fx_map_tones_preview : 45265 gui_split_preview "fx_map_tones $*",${-3--1} 45266 45267#@gui Tone Mapping [Fast] : fx_map_tones_fast, fx_map_tones_fast_preview(0) 45268#@gui : Radius = float(3,0,20) 45269#@gui : Power = float(0.5,0,1) 45270#@gui : sep = separator() 45271#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45272#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45273#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45274#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45275#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45276#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45277#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45278#@gui : sep = separator() 45279#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45280#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45281#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45282#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45283#@gui : sep = separator() 45284#@gui : note = note("<small>Authors: <i>Paul Nasca</i> and <i>David Tschumperlé</i>. 45285#@gui : Latest Update: <i>2011/10/06</i>.</small>") 45286fx_map_tones_fast : 45287 ac "map_tones_fast $1,$2",$3,2 45288 45289fx_map_tones_fast_preview : 45290 gui_split_preview "fx_map_tones_fast ${^0}",${-3--1} 45291 45292#@gui ____<b>Frames</b> 45293#---------------------- 45294 45295#@gui Droste : fx_droste, fx_droste_preview(1) 45296#@gui : note = note("<span color=\"red\">Upper-left coordinates :</span>") 45297#@gui : Point #0 = point(20,20,0,1,255,0,0) 45298#@gui : sep = separator() 45299#@gui : note = note("<span color=\"magenta\">Upper-right coordinates :</span>") 45300#@gui : Point #1 = point(80,20,0,1,255,0,255) 45301#@gui : sep = separator() 45302#@gui : note = note("<span color=\"blue\">Lower-right coordinates :</span>") 45303#@gui : Point #2 = point(80,80,0,1,0,128,255) 45304#@gui : sep = separator() 45305#@gui : note = note("<span color=\"cyan\">Lower-left coordinates :</span>") 45306#@gui : Point #3 = point(20,80,0,1,0,255,255) 45307#@gui : sep = separator() 45308#@gui : Iterations = int(1,1,10) 45309#@gui : X-Shift = float(0,-100,100) 45310#@gui : Y-Shift = float(0,-100,100) 45311#@gui : Angle = float(0,0,360) 45312#@gui : Zoom = float(1,0.1,5) 45313#@gui : Mirror = choice("None","X-Axis","Y-Axis","XY-Axes") 45314#@gui : Boundary = choice(1,"Transparent","Nearest","Periodic","Mirror") 45315#@gui : Drawing Mode = choice{"Replace","Replace (Sharpest)","Behind","Below"} 45316#@gui : View Outlines Only = bool(0) 45317#@gui : sep = separator() 45318#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/11/06</i>.</small>") 45319fx_droste : 45320 repeat $! 45321 if $16==1 100%,100%,1,1,'x' 100%,100%,1,1,'y' a[-2,-1] c fi 45322 repeat $9 45323 x0={round($1*w/100)} y0={round($2*h/100)} x1={round($3*w/100)} y1={round($4*h/100)} 45324 x2={round($5*w/100)} y2={round($6*h/100)} x3={round($7*w/100)} y3={round($8*h/100)} 45325 100%,100%,1,2,-32767 polygon. 4,$x0,$y0,$x1,$y1,$x2,$y2,$x3,$y3,1,-65535 45326 sh. 0 45327 f. "if(i==-65535, 45328 x03 = "$x0"+(y-"$y0")/("$y3"-"$y0")*("$x3"-"$x0"); 45329 x12 = "$x1"+(y-"$y1")/("$y2"-"$y1")*("$x2"-"$x1"); 45330 (x-x03)/(x12-x03)*(w-1),i)" 45331 rm. 45332 sh. 1 45333 f. "if(i==-65535, 45334 y01 = "$y0"+(x-"$x0")/("$x1"-"$x0")*("$y1"-"$y0"); 45335 y32 = "$y3"+(x-"$x3")/("$x2"-"$x3")*("$y2"-"$y3"); 45336 (y-y01)/(y32-y01)*(h-1),i)" 45337 rm. 45338 xshift={w*$10/100} yshift={h*$11/100} alpha={-$12*pi/180} 45339 ca={cos($alpha)/$13} sa={sin($alpha)/$13} w2={w/2} h2={h/2} 45340 f. 'if(i==-32767,i,X=i(x,y,0,0)-$w2;Y=i(x,y,0,1)-$h2;if(c==0,$w2-$xshift+X*$ca-Y*$sa,$h2-$yshift+X*$sa+Y*$ca))' 45341 if $14==0 sh. 0 f. 'if(i==-32767,x,i)' rm. sh. 1 f. 'if(i==-32767,y,i)' rm. 45342 elif $14==1 sh. 0 f. 'if(i==-32767,x,w-1-i)' rm. sh. 1 f. 'if(i==-32767,y,i)' rm. 45343 elif $14==2 sh. 0 f. 'if(i==-32767,x,i)' rm. sh. 1 f. 'if(i==-32767,y,h-1-i)' rm. 45344 else sh. 0 f. 'if(i==-32767,x,w-1-i)' rm. sh. 1 f. 'if(i==-32767,y,h-1-i)' rm. 45345 fi 45346 if $16<2 warp.. .,0,{$16==0},$15 rm. 45347 else 45348 +warp.. .,0,1,$15 rm.. 45349 if $16==3 rv[-2,-1] fi 45350 blend[-2,-1] alpha 45351 fi 45352 done 45353 if $16==1 warp.. .,0,1,1 rm. fi 45354 mv. 0 done 45355 45356fx_droste_preview : 45357 if !$17 fx_droste $* else polygon 4,$1%,$2%,$3%,$4%,$5%,$6%,$7%,$8%,0.3,0,0,0,255 fi 45358 polygon 4,$1%,$2%,$3%,$4%,$5%,$6%,$7%,$8%,1,0xFFFFFFFF,0,0,0,255 45359 45360#@gui Frame [Blur] : fx_frame_blur, fx_frame_blur(1) 45361#@gui : Horizontal Size (%) = float(30,0,100) 45362#@gui : Vertical Size (%) = float(30,0,100) 45363#@gui : sep = separator() 45364#@gui : Crop = float(0,0,100) 45365#@gui : Blur = float(5,0,10) 45366#@gui : Roundness = float(0,0,1) 45367#@gui : Apply Color Balance = bool(0) 45368#@gui : Balance Color = color(128,128,128) 45369#@gui : Normalization = choice("None","Stretch","Equalize") 45370#@gui : sep = separator() 45371#@gui : Outline Size = float(5,0,50) 45372#@gui : Outline Color = color(255,255,255) 45373#@gui : X-Shadow = float(2,-10,10) 45374#@gui : Y-Shadow = float(2,-10,10) 45375#@gui : Shadow Smoothness = float(1,0,5) 45376#@gui : Shadow Contrast = float(0,0,100) 45377#@gui : X-Centering = float(0.5,0,1) 45378#@gui : Y-Centering = float(0.5,0,1) 45379#@gui : Angle = float(0,-180,180) 45380#@gui : sep = separator() 45381#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/19/01</i>.</small>") 45382fx_frame_blur : 45383 repeat $! l[$>] to_rgb 45384 sx={$1%*max(w,h)} sy={$2%*max(w,h)} 45385 +r {w+$sx},{h+$sy},1,100%,3 b[1] $4% 45386 45387 if $6 balance_gamma[1] ${7-9} fi 45388 if $10==1 n[1] 0,255 elif $10==2 n[1] 0,255 equalize[1] 256 fi 45389 rv 45390 45391 z[1] {$3/2}%,{$3/2}%,{100-$3/2}%,{100-$3/2}% 45392 to_rgba[1] 45393 45394 if $5 r={1+1/$5} sh[1] 100% f. '1-(abs(x/w-0.5)^$r+abs(y/h-0.5)^$r)^(1/$r)' 45395 v={min(i(w/2,0),i(w-1,h/2),i(w/2,h-1),i(0,h/2))} 45396 c. $v,{$v+0.5/max(w,h)} n. 0,255 rm. fi 45397 45398 s={$11%*max(w,h)} 45399 r[1] {w+$s},{h+$s},1,4,0,0,0.5,0.5 45400 i[1] 100%,100%,1,3 fc[1] ${12-14} blend[1,2] alpha to_a. 45401 45402 if $5 sh[1] 100% f. '1-(abs(x/w-0.5)^$r+abs(y/h-0.5)^$r)^(1/$r)' 45403 v={min(i(w/2,0),i(w-1,h/2),i(w/2,h-1),i(0,h/2))} 45404 c. $v,{$v+0.5/max(w,h)} n. 0,255 rm. fi 45405 rotate[1] $21,1,0 45406 r[1] [0],[0],1,4,0,0,$19,$20 45407 +channels[1] 100% b. $17%,0 c. 0,{max(1,100-$18)}% n. 0,255 45408 shift. {round(w*$15%)},{round(h*$16%)},0,0,0 /. -255 +. 1 *[0,-1] 45409 45410 blend alpha 45411 endl done 45412 45413#@gui Frame [Cube] : frame_cube, frame_cube(1) 45414#@gui : Depth = float(3,0,30) 45415#@gui : X-Center = float(0,-2,2) 45416#@gui : Y-Center = float(0,-2,2) 45417#@gui : Left Side Orientation = choice("Normal","Mirror-X","Mirror-Y","Mirror-XY") 45418#@gui : Right Side Orientation = choice("Normal","Mirror-X","Mirror-Y","Mirror-XY") 45419#@gui : Upper Side Orientation = choice("Normal","Mirror-X","Mirror-Y","Mirror-XY") 45420#@gui : Lower Side Orientation = choice("Normal","Mirror-X","Mirror-Y","Mirror-XY") 45421#@gui : sep = separator() 45422#@gui : note = note("<small>Author: <i>David Tschumperlé, Angelo Lama</i>. 45423#@gui : Latest Update: <i>2012/29/01</i>.</small>") 45424 45425#@gui Frame [Fuzzy] : fx_frame_fuzzy, fx_frame_fuzzy(0) 45426#@gui : Horizontal Size (%) = float(5,0,100) 45427#@gui : Vertical Size (%) = float(5,0,100) 45428#@gui : Fuzzyness = float(10,0,40) 45429#@gui : Smoothness = float(1,0,5) 45430#@gui : Color = color(255,255,255,255) 45431#@gui : sep = separator() 45432#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45433fx_frame_fuzzy : 45434 repeat $! l[$>] 45435 sx={$1%*max(w,h)/2} sy={$2%*max(w,h)/2} 45436 frame_fuzzy $sx,$sy,${3-8} 45437 endl done 45438 45439#@gui Frame [Mirror] : fx_frame_mirror, fx_frame_mirror_preview(1) 45440#@gui : note = note("<b>Frame size:</b>") 45441#@gui : Horizontal (%) = float(10,0,100) 45442#@gui : Vertical (%) = float(10,0,100) 45443#@gui : sep = separator() 45444#@gui : note = note("<b>Image alignment:</b>") 45445#@gui : Horizontal (%) = float(50,0,100) 45446#@gui : Vertical (%) = float(50,0,100) 45447#@gui : sep = separator() 45448#@gui : note = note("<b>Frame dilation/shrinking:</b>") 45449#@gui : Left = float(0,-5,5) 45450#@gui : Right = float(0,-5,5) 45451#@gui : Up = float(0,-5,5) 45452#@gui : Bottom = float(0,-5,5) 45453#@gui : sep = separator() 45454#@gui : Preview Opacity (%) = float(0.75,0,1) 45455#@gui : sep = separator() 45456#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/08/20</i>.</small>") 45457fx_frame_mirror : 45458 repeat $! l[$>] 45459 {100+2*$1}%,{100+2*$2}%,1,100%," 45460 const boundary = 3; 45461 const offx = (w - w#-1)*$3%; 45462 const offy = (h - h#-1)*$4%; 45463 const f_left = 2^$5; 45464 const f_right = 2^$6; 45465 const f_up = 2^$7; 45466 const f_bottom = 2^$8; 45467 x = x - offx; 45468 y = y - offy; 45469 x<0?(x*=-f_left): 45470 x>=w#-1?(x = w#-1 - 1 - f_right*(x - w#-1)); 45471 y<0?(y*=-f_up): 45472 y>=h#-1?(y = h#-1 - 1 - f_bottom*(y - h#-1)); 45473 I(#-1,x,y)" 45474 k. endl done 45475 45476fx_frame_mirror_preview : 45477 repeat $! l[$>] 45478 ws,hs={[w,h]} fx_frame_mirror $* wd,hd={[w,h]} 45479 rr2d $_preview_width,$_preview_height wp,hp={[w,h]} 45480 ws,hs={[$ws,$hs]*[$wp,$hp]/[$wd,$hd]} 45481 45482 coords={off=([$wp,$hp]-[$ws,$hs])*[$3,$4]%;[off,off+[$ws,$hs]-1]} 45483 split_opacity 100%,100%,1,1,$9 rectangle. $coords,1,1 *[0,-1] a c 45484 rectangle $coords,0.75,0xF0F0F0F0,255 45485 rectangle $coords,0.75,0x0F0F0F0F,0,0,0,255 45486 endl done 45487 45488#@gui Frame [Painting] : fx_frame_painting, fx_frame_painting_preview(1) 45489#@gui : Size (%) = float(10,0,100) 45490#@gui : Contrast = float(0.4,0,1) 45491#@gui : Smoothness = float(6,0,30) 45492#@gui : Color = color(225,200,120) 45493#@gui : sep = separator() 45494#@gui : Vignette Size = float(2,0,50) 45495#@gui : Vignette Contrast = float(400,0,1000) 45496#@gui : sep = separator() 45497#@gui : Defects Contrast = float(50,0,512) 45498#@gui : Defects Density = float(10,0,100) 45499#@gui : Defects Size = float(1,0,10) 45500#@gui : Defects Smoothness = float(0.5,0,20) 45501#@gui : sep = separator() 45502#@gui : Serial Number = int(123456,0,1000000) 45503#@gui : Frame as a New Layer = _bool(false) 45504#@gui : sep = separator() 45505#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/07/06</i>.</small>") 45506fx_frame_painting : 45507 if $14 45508 repeat $! 100%,100%,1,4 frame_painting. $1%,$2,$3%,${4-6},$7%,${8-13} 45509 rv[-2,-1] to_a. r. ..,..,1,4,0,0,0.5,0.5 mv[-2,-1] 0 done 45510 else frame_painting $1%,$2,$3%,${4-6},$7%,${8-13} 45511 fi 45512 45513fx_frame_painting_preview : 45514 frame_painting $1%,$2,$3%,${4-6},$7%,${8-13} 45515 45516#@gui Frame [Pattern] : fx_frame_pattern, fx_frame_pattern_preview(1) 45517#@gui : Tiles = int(10,3,30) 45518#@gui : Pattern = choice(1,"Top Layer","Self Image") 45519#@gui : Iterations = int(1,1,10) 45520#@gui : Constrain Image Size = _bool(1) 45521#@gui : sep = separator() 45522#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/01/08</i>.</small>") 45523fx_frame_pattern : 45524 if $2" || "$!==1 repeat $3 frame_pattern $1,$4 done 45525 else repeat $3 frame_pattern[^0] $1,[0],$4 done fi 45526 45527fx_frame_pattern_preview : 45528 fx_frame_pattern ${1-3},1 45529 45530#@gui Frame [Regular] : fx_frame, fx_frame(1) 45531#@gui : note = note("<b>Crop parameters :</b>") 45532#@gui : X-Start (%) = int(0,0,100) 45533#@gui : X-End (%) = int(100,0,100) 45534#@gui : Y-Start (%) = int(0,0,100) 45535#@gui : Y-End (%) = int(100,0,100) 45536#@gui : sep = separator() 45537#@gui : note = note("<b>Frame parameters :</b>") 45538#@gui : Width (%) = int(10,0,100) 45539#@gui : Height (%) = int(10,0,100) 45540#@gui : Color = color(0,0,0,255) 45541#@gui : Outline Size = int(1,0,100) 45542#@gui : Outline Color = color(255,255,255,255) 45543#@gui : sep = separator() 45544#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45545fx_frame : 45546 to_rgba repeat $! 45547 z. $1%,$3%,$2%,$4% 45548 frame. $11,$11,${12-15} 45549 sx={$5%*max(w,h)} sy={$6%*max(w,h)} 45550 frame. $sx,$sy,${7-10} 45551 mv. 0 done 45552 45553#@gui Frame [Round] : fx_frame_round, fx_frame_round(1) 45554#@gui : Sharpness = float(6,0.1,40) 45555#@gui : Size (%) = float(20,0,100) 45556#@gui : Smoothness = float(0.1,0,15) 45557#@gui : Shade = float(0,0,1) 45558#@gui : Color = color(255,255,255,255) 45559#@gui : Blur Frame = float(0,0,100) 45560#@gui : Blur Shade = float(0.1,0,1) 45561#@gui : Blur Amplitude = float(3,0,10) 45562#@gui : sep = separator() 45563#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45564fx_frame_round : 45565 frame_round ${1-8} 45566 if $9 frame_blur $1,{min(99,$1+$9)},$3,$10,$11% fi 45567 45568#@gui Frame [Smooth] : fx_frame_smooth, fx_frame_smooth(1) 45569#@gui : Width (%) = int(10,0,100) 45570#@gui : Height (%) = int(10,0,100) 45571#@gui : Roundness = float(0.25,0,1) 45572#@gui : sep = separator() 45573#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/25/04</i>.</small>") 45574fx_frame_smooth : 45575 repeat $! l[$>] 45576 sx={$1%*max(w,h)} sy={$2%*max(w,h)} 45577 100%,100%,1,1,0 45578 if $3 r={1+1/$3} f. '1-(abs(x/w-0.5)^$r+abs(y/h-0.5)^$r)^(1/$r)' 45579 v={min(i(w/2,0),i(w-1,h/2),i(w/2,h-1),i(0,h/2))} <=. $v 45580 fi 45581 frame $sx,$sy,1 45582 inpaint_pde[0] [1],100%,1,15 45583 rm. 45584 endl done c 0,255 45585 45586#@gui Old Photograph : fx_old_photo, fx_old_photo(1) 45587#@gui : Vignette Strength = float(200,0,255) 45588#@gui : Vignette Min Radius = float(50,0,100) 45589#@gui : Vignette Max Radius = float(85,0,100) 45590#@gui : sep = separator() 45591#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45592fx_old_photo : 45593 vignette ${1-3} old_photo 45594 45595#@gui Polaroid : fx_polaroid, fx_polaroid(1) 45596#@gui : Frame Size = int(10,0,400) 45597#@gui : Bottom Size = int(20,0,400) 45598#@gui : X-Shadow = float(0,-20,20) 45599#@gui : Y-Shadow = float(0,-20,20) 45600#@gui : Smoothness = float(3,0,5) 45601#@gui : Curvature = float(0,0,1) 45602#@gui : Angle = float(20,-180,180) 45603#@gui : Vignette Strength = float(50,0,255) 45604#@gui : Vignette Min Radius = float(70,0,100) 45605#@gui : Vignette Max Radius = float(95,0,100) 45606#@gui : sep = separator() 45607#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 45608fx_polaroid : 45609 vignette ${8-10} polaroid $1,$2 drop_shadow $3%,$4%,$5%,$6 rotate $7,1,0 45610 45611#@gui Tunnel : fx_tunnel, fx_tunnel(1) 45612#@gui : Depth = int(4,1,100) 45613#@gui : Factor = float(80,1,99) 45614#@gui : Center (%) = point(50,50) 45615#@gui : Opacity = float(0.2,0,1) 45616#@gui : Angle = float(0,-90,90) 45617#@gui : sep = separator() 45618#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/22/11</i>.</small>") 45619fx_tunnel : 45620 tunnel $1,$2%,{[${3,4}]%},${5-6} 45621 45622#@gui Vignette : fx_vignette, fx_vignette 45623#@gui : Strength = float(70,0,255) 45624#@gui : Min Radius = float(70,0,100) 45625#@gui : Max Radius = float(95,0,100) 45626#@gui : Color = color(0,0,0,255) 45627#@gui : sep = separator() 45628#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/24/10</i>.</small>") 45629fx_vignette : 45630 repeat $! to_rgb l[$>] 45631 to_rgba split_opacity 45632 =. 0 vignette. ${1-3} a c +fc ${4-7} rv blend alpha 45633 endl done 45634 45635#@gui ____<b>Frequencies</b> 45636#---------------------------- 45637 45638#@gui Bandpass : fx_bandpass, fx_bandpass_preview(0) 45639#@gui : Low Frequency = float(0,0,100) 45640#@gui : High Frequency = float(100,0,100) 45641#@gui : sep = separator() 45642#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45643#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45644#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45645#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45646#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45647#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45648#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45649#@gui : Value Action = choice(2,"None","Cut","Normalize") 45650#@gui : sep = separator() 45651#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45652#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45653#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45654#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45655#@gui : sep = separator() 45656#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45657fx_bandpass : 45658 repeat $! l[$>] split_opacity l[0] 45659 ac "bandpass $1%,$2%",$3,$4 45660 endl a c endl done 45661 45662fx_bandpass_preview : 45663 gui_split_preview "fx_bandpass $*",${-3--1} 45664 45665#@gui Fourier Analysis : fx_display_fft, fx_display_fft(1) 45666#@gui : sep = separator() 45667#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45668fx_display_fft : 45669 to_rgb display_fft 45670 45671#@gui Fourier Transform : fx_fourier, fx_fourier_preview(1) : * 45672#@gui : Magnitude / Phase = choice{2,"One Layer (Horizontal)","One Layer (Vertical)","Two Layers"} 45673#@gui : Discard Transparency = bool(1) 45674#@gui : sep = separator() 45675#@gui : note = note{"<small><b>Note:</b> Apply this filter once to get the direct FFT, 45676#@gui : and once again to get the reverse transform.</small>"} 45677#@gui : url = link("Click here for a video tutorial","http://www.youtube.com/watch?v=3137dDa6P4s") 45678#@gui : sep = separator() 45679#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/06/16</i>.</small>") 45680fx_fourier : skip ${2=0} 45681 if $2 remove_opacity fi 45682 magic="GMICFFT" 45683 45684 i=0 for $i<$! ni={$i+1} nm={$i,n} 45685 45686 # Detect FFT/iFFT mode. 45687 is_ifft=0 45688 +columns[$i] 100% 45689 l. 45690 mag,m0,M0,m1,M1=${u\ {t}} 45691 if ['$mag']=='$magic' is_ifft=1 fi 45692 onfail endl rm. 45693 if !$is_ifft +rows[$i] 100% l. mag,m0,M0,m1,M1=${u\ {t}} if ['$mag']=='$magic' is_ifft=2 fi onfail endl rm. fi 45694 if !$is_ifft 45695 +rows[$i] 100% l. mag,m0,M0=${u\ {t}} if ['$mag']=='$magic' is_ifft=3 fi onfail endl rm. 45696 if $is_ifft==3 45697 is_ifft=0 +rows[$ni] 100% 45698 l. mag,m1,M1=${u\ {t}} if ['$mag']=='$magic' is_ifft=3 fi onfail endl 45699 rm. 45700 fi 45701 fi 45702 45703 # Compute the transform. 45704 if !$is_ifft # FFT 45705 l[$i] 45706 fftpolar +.. 1 log.. m0,M0,m1,M1={[im#0,iM#0,im#1,iM#1]} n[-2,-1] 0,255 45707 if $1==0 ({'$magic,$m0,$M0,$m1,$M1'},0) y. a x 45708 elif $1==1 ({'$magic,$m0,$M0,$m1,$M1'},0) a y 45709 else ({'$magic,$m0,$M0'},0) a[-3,-1] y ({'$magic,$m1,$M1'},0) a[-2,-1] y 45710 fi 45711 nm $nm 45712 endl 45713 45714 else # iFFT 45715 if $is_ifft==1 columns[$i] 0,{$i,w-2} s[$i] x,2 45716 elif $is_ifft==2 rows[$i] 0,{$i,h-2} s[$i] y,2 45717 else rows[$i,$ni] 0,{$i,h-2} 45718 fi 45719 l[$i,{$i+1}] n[0] $m0,$M0 n[1] $m1,$M1 exp[0] -[0] 1 ifftpolar c 0,255 endl 45720 fi 45721 i+={$1<2" || "$is_ifft>2?1:2} 45722 done 45723 45724fx_fourier_preview : 45725 if $2 remove_opacity fi 45726 dfft 45727 45728#@gui Fourier Watermark : fx_watermark_fourier, _none_ 45729#@gui : Text = text{"(c) G'MIC"} 45730#@gui : Size = int(53,13,128) 45731#@gui : sep = separator() 45732#@gui : note = note("<small><b>Note: </b> To make the watermark visible afterwards, use the 45733#@gui : 'Fourier Analysis' filter. </small>") 45734#@gui : sep = separator() 45735#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45736fx_watermark_fourier : 45737 watermark_fourier "$1",$2 c 0,255 45738 45739#@gui ____<b>Layers</b> 45740#----------------------- 45741 45742#@gui Align Layers : fx_align_layers, fx_align_layers_preview : * 45743#@gui : Alignment Type = choice(0,"Rigid","Non-Rigid") 45744#@gui : Smoothness = float(0.7,0,1) 45745#@gui : Scales = choice(0,"Auto","1","2","3","4","5","6","7","8") 45746#@gui : Revert Layers = bool(0) 45747#@gui : sep = separator() 45748#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/01/11</i>.</small>") 45749fx_align_layers : 45750 to_colormode 0 45751 r ${-max_wh},1,100%,0,0,0.5,0.5 45752 if ${4=0} _fx_revert_layers fi 45753 remove_opacity 45754 if $1 register_nonrigid[^-1] .,$2,0.1,$3 45755 else register_rigid[^-1] .,$2 45756 fi 45757 45758fx_align_layers_preview : 45759 fx_align_layers $1,$2,0 blend_edges 0.1 45760 45761_fx_revert_layers : 45762 repeat int($!/2) rv[{2*$>},{2*$>+1}] done 45763 45764#@gui Blend [Average All] : fx_blend_average_all, fx_blend_average_all : * 45765#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 45766#@gui : sep = separator() 45767#@gui : note = note{"<small><b>Note:</b> 45768#@gui : This filter takes multiple layers as input and average them. Set the <i>Input layers</i> option 45769#@gui : to handle multiple input layers. 45770#@gui : </small>"} 45771#@gui : sep = separator() 45772#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/11/08</i>.</small>") 45773fx_blend_average_all : 45774 if $! to_rgba 45775 N=$! r ${-max_wh},1,100%,0,0,0.5,0.5 45776 _gb_fwd $1 45777 + / $N 45778 _gb_bwd $1 45779 fi 45780 45781_gb_fwd : 45782 to_color 45783 if $1==1 repeat $! l[$>] sh 0,2 srgb2rgb. rm. endl done 45784 elif $1==2 repeat $! l[$>] sh 0,2 srgb2rgb. rgb2lab. rm. endl done 45785 fi 45786 45787_gb_bwd : 45788 to_color 45789 if $1==1 repeat $! l[$>] sh 0,2 rgb2srgb. rm. endl done 45790 elif $1==2 repeat $! l[$>] sh 0,2 lab2rgb. rgb2srgb. rm. endl done 45791 fi 45792 45793#@gui Blend [Edges] : fx_blend_edges, fx_blend_edges(0) : * 45794#@gui : Opacity = float(1,0,1) 45795#@gui : Smoothness = float(0.8,0,5) 45796#@gui : Revert Layers = bool(0) 45797#@gui : sep = separator() 45798#@gui : note = note{"<small><b>Note:</b> 45799#@gui : This filter needs two layers to work properly. Set the <i>Input layers</i> option to handle 45800#@gui : multiple input layers. 45801#@gui : </small>"} 45802#@gui : sep = separator() 45803#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/21/01</i>.</small>") 45804fx_blend_edges : 45805 repeat int($!/2) l[$>,{$>+1}] if $3 rv fi +blend_edges[-2,-1] $2 rm... blend[-2,-1] alpha,$1 endl done 45806 45807#@gui Blend [Fade] : fx_blend_fade, fx_blend_fade(1) : + 45808#@gui : Preset = choice{1,"Custom","Linear","Circular","Wave","Keftales"} 45809#@gui : Offset = float(0,-1,1) 45810#@gui : Thinness = float(0,0,10) 45811#@gui : Sharpness = float(5,1,20) 45812#@gui : Sharpest = bool(0) 45813#@gui : Revert Layers = bool(0) 45814#@gui : Colorspace = choice("sRGB","Linear RGB","Lab") 45815#@gui : note = note{\n<small> 45816#@gui : The parameters below are used in most presets. 45817#@gui : </small>} 45818#@gui : 1st Parameter = float(0,-1,1) 45819#@gui : 2nd Parameter = float(0,-1,1) 45820#@gui : 3rd Parameter = float(0,-1,1) 45821#@gui : note = note{\n<small> 45822#@gui : The formula below is used for the <i>Custom</i> preset. 45823#@gui : </small>} 45824#@gui : Formula = text{"cos(4*pi*x/w) * sin(4*pi*y/h)"} 45825#@gui : note = note{"<small><b>Note:</b> 45826#@gui : This filter needs two layers to work properly. Set the <i>Input layers</i> option to handle 45827#@gui : multiple input layers. 45828#@gui : </small>"} 45829#@gui : sep = separator() 45830#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/21/01</i>.</small>") 45831fx_blend_fade : 45832 if $!==1 return fi 45833 to_colormode 4 45834 _gb_fwd $7 45835 if $1==0 [0],[0],1,1,"$11" 45836 else _fx_blend_fade$1 $8,$9,$10 r. [0],[0],1,1,3 45837 fi 45838 n. {-($!-2)*$3},{($!-2)*(1+$3)} 45839 -. {$2*(1+$3)*($!-2)} 45840 c. 0,{$!-2} 45841 if $6 rv[^-1] fi 45842 if $5 round. 1 45843 else roundify. $4 45844 fi 45845 blend_fade[^-1] . rm. 45846 _gb_bwd $7 45847 c 0,255 45848 45849_fx_blend_fade1 : [0],[0],1,1,"a=$1*pi/2; x*cos(a) + y*sin(a)" 45850_fx_blend_fade2 : [0],[0],1,1,0 =. 1,{($1+1)*50}%,{($2+1)*50}% distance. 1 45851_fx_blend_fade3 : [0],[0],1,1,0 =. 1,{($1+1)*50}%,{($2+1)*50}% distance. 1 *. {0.01+$3/2} cos. 45852_fx_blend_fade4 : [0],[0],1,1,"((x-w*($1+0.5))*(y-h*($2+0.5)))%(0.2*w*h*(1.001+$3))" 45853 45854#@gui Blend [Median] : fx_blend_median, fx_blend_median(0) : * 45855#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 45856#@gui : sep = separator() 45857#@gui : note = note{"<small><b>Note:</b> 45858#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 45859#@gui : multiple input layers. 45860#@gui : </small>"} 45861#@gui : sep = separator() 45862#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Iain Fergusson</i>. 45863#@gui : Latest Update: <i>2014/16/12</i>.</small>") 45864fx_blend_median : 45865 _gb_fwd $1 45866 blend_median 45867 _gb_bwd $1 45868 45869#@gui Blend [Seamless] : fx_blend_seamless, fx_blend_seamless_preview(1) : * 45870#@gui : Mixed Mode = bool(0) 45871#@gui : Inner Fading = float(0,0,100) 45872#@gui : Outer Fading = float(25,0,100) 45873#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 45874#@gui : sep = separator() 45875#@gui : Output as Separate Layers = _bool(0) 45876#@gui : sep = separator() 45877#@gui : note = note{"<small><b>Note:</b> 45878#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 45879#@gui : multiple input layers. 45880#@gui : </small>"} 45881#@gui : sep = separator() 45882#@gui : url = link("Click here for a detailed description of this filter.",\ 45883# "http://gimpchat.com/viewtopic.php?f=28&t=10204") 45884#@gui : url = link("+ Video tutorial 1","http://www.youtube.com/watch?v=Nu-S1HmOCgE") 45885#@gui : url = link("+ Video tutorial 2","http://www.youtube.com/watch?v=zsHgQY6025I") 45886#@gui : url = link("+ Video tutorial 3","http://www.youtube.com/watch?v=2e6FikWMkaQ") 45887#@gui : sep = separator() 45888#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/04/05</i>.</small>") 45889fx_blend_seamless : 45890 rv 45891 _gb_fwd $4 45892 to_a[^0] r[^0] [0],[0],1,100%,0 45893 repeat $! pos=${gui_layer_pos[$>]} shift[$>] ${u\ $pos},0,0 done 45894 if $5 # Output as separate layers 45895 +blend_seamless $1,$2%,$3% 45896 remove_opacity[0,-1] k[0,-1] rv sub_alpha[0] [1],1 45897 else 45898 blend_seamless $1,$2%,$3% # Output as a single layer. 45899 fi 45900 _gb_bwd $4 45901 45902fx_blend_seamless_preview : 45903 fx_blend_seamless ${1-4},0 45904 45905#@gui Blend [Standard] : fx_blend, fx_blend_preview : * 45906#@gui : Mode = choice{6,"Add","Alpha","And","Average","Blue","Burn","Custom formula","Darken","Difference", 45907#@gui : "Divide","Dodge","Edges","Exclusion","Freeze","Grain Extract","Grain Merge","Green","Hard Light", 45908#@gui : "Hard Mix","Hue","Interpolation","Lighten","Lightness","Linear Burn","Linear Light","Luminance", 45909#@gui : "Multiply","Negation","Or","Overlay","Pin Light","Red","Reflect","Saturation", 45910#@gui : "Shape Area Max","Shape Area Max0","Shape Area Min","Shape Area Min0","Shape Average","Shape Average0", 45911#@gui : "Shape Median","Shape Median0","Shape Min","Shape Min0","Shape Max","Shape Max0", 45912#@gui : "Soft Burn","Soft Dodge","Soft Light","Screen","Stamp","Subtract","Value","Vivid Light","Xor"} 45913#@gui : Process As = choice("Two-by-Two","Upper Layer is the Top Layer for All Blends", 45914#@gui : "Lower Layer is the Bottom Layer for All Blends") 45915#@gui : Opacity (%) = float(100,0,100) 45916#@gui : Preview All Outputs = bool(1) 45917#@gui : sep = separator() 45918#@gui : Custom Formula = text{"1/2 - 1/4*cos(pi*a) - 1/4*cos(pi*b)"} 45919#@gui : note = note{"<small><b>Note:</b> In custom formulas, <samp>a</samp> and <samp>b</samp> respectively stand for 45920#@gui : the values of the <i>base layer<i> and the <i>blend layer</i>, 45921#@gui : and are defined in value range [0,1].</small>"} 45922#@gui : sep = separator() 45923#@gui : note = note{"<small><b>Note:</b> 45924#@gui : This filter needs at least two layers to work properly. Do not forget to set the <i>Input layers</i> option 45925#@gui : below to handle multiple input layers. 45926#@gui : </small>"} 45927#@gui : url = link("Reference page for G'MIC blending modes", 45928#@gui : "https://github.com/dtschump/gmic-community/wiki/Blending-modes") 45929#@gui : sep = separator() 45930#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/03/08</i>.</small>") 45931fx_blend : 45932 mode=${arg\ 1+$1,add,alpha,and,average,blue,burn,custom_formula,darken,difference,\ 45933 divide,dodge,edges,exclusion,freeze,grainextract,grainmerge,green,hardlight,\ 45934 hardmix,hue,interpolation,lighten,lightness,linearburn,linearlight,luminance,\ 45935 multiply,negation,or,overlay,pinlight,red,reflect,saturation,\ 45936 shapeareamax,shapeareamax0,shapeareamin,shapeareamin0,\ 45937 shapeaverage,shapeaverage0,shapemedian,shapemedian0,\ 45938 shapemin,shapemin0,shapemax,shapemax0,\ 45939 softburn,softdodge,softlight,screen,stamp,subtract,value,\ 45940 vividlight,xor} 45941 m "_blend_custom_formula : f. \"a = i#0/255; b = i#1/255; 255*cut(($5),0,1)\"" 45942 if $2==0 repeat int($!/2) l[$>,{$>+1}] rv blend $mode,{$3%} endl done # Two-by-two. 45943 elif $2==1" && "$!>1 blend[^0] [0],$mode,{$3%},0 rm[0] # Top layer is top for all blends. 45944 elif $2==2" && "$!>1 blend[^-1] .,$mode,{$3%},1 rm. # Bottom layer is bottom for all blends. 45945 fi 45946 um _blend_custom_formula 45947 45948fx_blend_preview : 45949 fx_blend $"*" 45950 if $4 append_tiles , fi 45951 45952#@gui Colors to Layers : fx_split_colors, fx_split_colors_preview(1) 45953#@gui : Color Tolerance = float(50,0,256) 45954#@gui : Maximum Number of Output Layers = int(16,2,256) 45955#@gui : Minimal Area (%) = float(1,0,100) 45956#@gui : Autocrop Output Layers = bool() 45957#@gui : sep = separator() 45958#@gui : note = note{"<small><b>Note:</b> This filter decomposes an image into several layers each with 45959#@gui : a single color + a residual layer (if any). 45960#@gui : </small>"} 45961#@gui : sep = separator() 45962#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/11/03</i>.</small>") 45963fx_split_colors : skip ${2=0} 45964 to_rgb repeat $! l[$>] 45965 nm=${-gui_layer_name} 45966 min_area={max(1,w*h*$3%)} 45967 split_colors $1,$2,$min_area 45968 nm name($nm) 45969 if $4 gui_autocrop_layers fi 45970 endl done 45971 45972fx_split_colors_preview : 45973 repeat $! l[$>] 45974 +fx_split_colors ${1-4} drgba 45975 repeat $! l[$>] to ${arg\ {1+!!$>},"Original","#"$>},1,1,43,7,1,255 endl done 45976 frame 1,1,0 frame 3,3,255 to_rgba append_tiles , 45977 endl done 45978 45979#@gui Fade Layers : fx_fade_layers, fx_fade_layers_preview : + 45980#@gui : Inter-Frames = _int(10,2,100) 45981#@gui : sep = separator() 45982#@gui : note = note{"<small><b>Note:</b> 45983#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 45984#@gui : multiple input layers. 45985#@gui : </small>"} 45986#@gui : sep = separator() 45987#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/04/08</i>.</small>") 45988fx_fade_layers : 45989 if $!<2 return fi 45990 to_colormode 0 45991 r ${-max_wh},1,100%,0,0,0.5,0.5 45992 a z r 100%,100%,{(d-1)*$1+1},100%,3 s z 45993 45994fx_fade_layers_preview : 45995 if $!<2 return fi 45996 to_colormode 0 45997 r ${-max_wh},1,100%,0,0,0.5,0.5 45998 k[0,1] + / 2 45999 46000#@gui Layers to Tiles : append_tiles, fx_append_tiles_preview(1) : * 46001#@gui : X-Tiles = int(0,0,256) 46002#@gui : Y-Tiles = int(0,0,256) 46003#@gui : note = note("<small>For both parameters, <i>0</i> means <i>automatic</i>.</small>") 46004#@gui : sep = separator() 46005#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46006fx_append_tiles_preview : 46007 frame 1,1,0,0,0,255 append_tiles $1,$2 46008 46009#@gui Morph Layers : fx_morph_layers, gui_no_preview : * 46010#@gui : Inter-Frames = _int(10,2,100) 46011#@gui : Smoothness = _float(0.2,0,2) 46012#@gui : Precision = _float(0.1,0,2) 46013#@gui : Revert Layers = bool(0) 46014#@gui : sep = separator() 46015#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46016fx_morph_layers : 46017 if ${4=0} _fx_revert_layers fi 46018 to_rgb morph $1,$2,$3 46019 46020#@gui Multiscale Operator : fx_apply_multiscale, fx_apply_multiscale_preview(1) 46021#@gui : Number of Scales = int(4,2,16) 46022#@gui : sep = separator() 46023#@gui : Starting Scale (%) = float(25,0,400) 46024#@gui : Ending Scale (%) = float(100,0,400) 46025#@gui : Non-Linearity = float(0,-1,1) 46026#@gui : Rescaling = choice(3,"Bloc","Linear","Cubic","Lanczsos") 46027#@gui : sep = separator() 46028#@gui : X-Centering = float(0.5,0,1) 46029#@gui : Y-Centering = float(0.5,0,1) 46030#@gui : Angle = float(0,-180,180) 46031#@gui : sep = separator() 46032#@gui : Enable Interpolated Motion = bool(0) 46033#@gui : Ending X-Centering = float(0.5,0,1) 46034#@gui : Ending Y-Centering = float(0.5,0,1) 46035#@gui : Ending Angle = float(0,-180,180) 46036#@gui : sep = separator() 46037#@gui : G'MIC Operator = text("") 46038#@gui : Return Scaling = choice("None","Bloc","Linear","Cubic","Lanczos") 46039#@gui : Lock Return Scaling to Source Layer = bool(0) 46040#@gui : sep = separator() 46041#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/30/03</i>.</small>") 46042fx_apply_multiscale : skip "${13=}" 46043 repeat $! l[$<] 46044 w0={w} h0={h} 46045 apply_scales "$13",$1,$2%,$3%,{10^$4},{arg(1+$5,1,3,5,6)} 46046 if $8" || "($9" && "$8!=$12) to_a N=$! repeat $! 46047 angle={$9?$8+($12-$8)*$>/max($N-1,1):$8} 46048 rotate[$>] $angle 46049 done fi 46050 if $14 46051 if $15 siz=$w0,$h0 else siz=${-max_wh} fi 46052 r $siz,1,100%,{arg($14,1,3,5,6)} 46053 c 0,255 46054 fi 46055 w=${-max_w} h=${-max_h} N=$! 46056 repeat $! 46057 cx={$9?$6+($10-$6)*$>/max($N-1,1):$6} 46058 cy={$9?$7+($11-$7)*$>/max($N-1,1):$7} 46059 gui_set_layer_pos[$>] {$>,($w-w)*$cx},{$>,($h-h)*$cy} 46060 done 46061 endl done 46062 46063fx_apply_multiscale_preview : 46064 repeat $! l[$>] 46065 fx_apply_multiscale $"*" 46066 N={int(sqrt($!))} N={round($!/$N,1,1)} r2dy {100/$N}% 46067 to_rgba 46068 max_wh=${-max_wh} 46069 N=$! repeat $! l[$>] 46070 cx={$9?$6+($10-$6)*$>/max($N-1,1):$6} 46071 cy={$9?$7+($11-$7)*$>/max($N-1,1):$7} 46072 r $max_wh,1,100%,0,0,$cx,$cy 46073 0 text. "#"{1+$>}" ",1,1,24,1,255 +dilate. 5 to_rgba[1] j[0] [1],2,0,0,0,1,[2],255 k[0] 46074 endl done 46075 frame 1,1,0 frame 3,3,255 append_tiles , 46076 endl done 46077 46078#@gui Pack : fx_pack, fx_pack_preview(1) : * 46079#@gui : Order By = choice(2,"Width","Height","Maximum Dimension","Area","Name") 46080#@gui : Tends to Be Square = bool(1) 46081#@gui : Force Transparency = bool(1) 46082#@gui : Add Image Label = bool(0) 46083#@gui : Font Height (px) = float(16,0,64)_0 46084#@gui : Font Colors = choice(1,"White on black","Black on white")_0 46085#@gui : sep = separator() 46086#@gui : Output Coordinates File = _bool(0) 46087#@gui : Output Folder = _folder() 46088#@gui : sep = separator() 46089#@gui : note = note{"<small>This filter tries to pack all input layers into a single image, while trying to 46090#@gui : minimize the empty areas. 46091#@gui : This problem being NP-hard, the algorithm finds (of course) a <b>non-optimal</b>, but often acceptable 46092#@gui : solution to this packing problem.</small>"} 46093#@gui : sep = separator() 46094#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/03/20</i>.</small>") 46095fx_pack : skip "${8=}" 46096 if $4 to_rgba repeat $! l[$>] nm0={n} gui_layer_name nm=${} 46097 0 t. {``$nm},3,0,$5,1,1 frame. 1,1,0 46098 if $6 *. -1 fi 46099 n. 0,255 to_rgba. r. {[w+2,h+1,1,4]},0,0,0,1 46100 rv a y,{w#0>w?0.5:0} nm $nm0 46101 endl done 46102 fi 46103 if $3 to_a fi 46104 repeat $! gui_layer_name[$>] nm$>=${} nm[$>] {`lowercase(['${nm$>}'])`} done 46105 c0="w" c1="h" c2="max(w,h)" c3="w*h" c4="n" 46106 pack $2,${c$1} coords=${} 46107 if $7 46108 repeat 256 filename "$8/gmic_pack.txt",$> filename=${} if isfile(['{/$filename}']) else break fi done 46109 if !narg($filename) filename="$8/gmic_pack.txt" fi 46110 l[] repeat narg($coords)/2 46111 x={arg(1+2*$>,$coords)} y={arg(2+2*$>,$coords)} 46112 ('"Image ""#"{1+$>}" ("${nm$>}"): "$x,$y\n') 46113 done a x ot $filename rm endl 46114 fi 46115 nm "name(G'MIC packing),pos(0,0),mode(normal)" 46116 if $4 autocrop fi 46117 46118fx_pack_preview : skip "${8=}" 46119 if !$! return fi 46120 w={w} h={h} 46121 filled=0 repeat $! filled={$>,$filled+w*h} done 46122 fx_pack $1,$2,$3,$4,$5,$6,0 46123 area={w*h} 46124 to_rgba rr2d $w,$h,0 46125 i[0] $w,16,1,4,255 t[0] "Filled: "{round(100*$filled/$area)}%,3,1,14,1,0,0,0,255 46126 a y,0.5 46127 u "{$1}{$2}{$3}{$4}"\ 46128 "{$5}_"{2*$4}\ 46129 "{$6}_"{2*$4}\ 46130 "{$7}{$8}" 46131 46132#@gui Stroke : fx_stroke, fx_stroke_preview(0) 46133#@gui : Thickness (px) = int(3,1,256) 46134#@gui : Threshold (%) = float(50,0,100) 46135#@gui : Smoothness (px) = float(0,0,10) 46136#@gui : Shape = choice(2,"Square","Diamond","Round") 46137#@gui : Direction = choice(1,"Inward","Outward") 46138#@gui : sep = separator() 46139#@gui : Zoom (%) = float(100,1,300) 46140#@gui : X-Shift (px) = int(0,-256,256) 46141#@gui : Y-Shift (px) = int(0,-256,256) 46142#@gui : sep = separator() 46143#@gui : Starting Color = color(255,255,255,255) 46144#@gui : Ending Color = color(255,255,255,255) 46145#@gui : Inside Color = color(0,0,0,0) 46146#@gui : Outside Color = color(0,0,0,0) 46147#@gui : sep = separator() 46148#@gui : Output Stroke Layer On = choice(1,"Bottom","Top") 46149#@gui : Keep Original Image Size = bool(0) 46150#@gui : sep = separator() 46151#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/24/06</i>.</small>") 46152fx_stroke : 46153 to_a repeat $! l[$<] nm={n} 46154 if !$26" && "$5 expand_xy $1,0 is_frame1=0 else expand_xy 1,0 is_frame1=1 fi 46155 split_opacity +l. 46156 b $3 46157 if $6>=100 46158 shift $7,$8 46159 if $6!=100 wh={w},{h} r $6%,$6%,1,1,3 r $wh,1,1,0,0,0.5,0.5 fi 46160 else 46161 if $6!=100 wh={w},{h} r $6%,$6%,1,1,3 r $wh,1,1,0,0,0.5,0.5 fi 46162 shift $7,$8 46163 fi 46164 > {99.99-min(99.99,$2)}% 46165 distance $5,$4 46166 ($9^$10^$11^$12) 46167 if $1>1 ($13^$14^$15^$16) a[-2,-1] x r. $1,1,1,4,3 c. 0,255 fi 46168 i.. ($21^$22^$23^$24) ($17^$18^$19^$20) if $5 rv[-3,-1] fi 46169 a[-3--1] x map.. .,1 rm. 46170 nm $nm 46171 endl 46172 a[0,1] c 46173 if $is_frame1 shrink_xy 1 fi 46174 if $25 rv fi 46175 endl done 46176 46177fx_stroke_preview : 46178 repeat $! l[$>] 46179 fx_stroke $* 46180 nm foo 46181 gui_merge_layers 46182 endl done 46183 46184#@gui Tiles to Layers : split_tiles, fx_tiles2layers_preview(1) 46185#@gui : X-Tiles = int(3,1,100) 46186#@gui : Y-Tiles = int(3,1,100) 46187#@gui : Force Tiles to Have Same Size = _bool(false) 46188#@gui : sep = separator() 46189#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46190fx_tiles2layers_preview : 46191 split_tiles $1,$2,$3 to_rgba frame 1,1,0,0,0,255 frame 3,3,0,0,0,0 append_tiles , 46192 46193#@gui Tones to Layers : fx_tones2layers, fx_tones2layers_preview(0) 46194#@gui : Number of Tones = int(3,2,10) 46195#@gui : Start of Mid-Tones = int(85,0,255) 46196#@gui : End of Mid-Tones = int(170,0,255) 46197#@gui : Smoothness = float(0.5,0,5) 46198#@gui : Alpha = choice("Binary","Scalar") 46199#@gui : sep = separator() 46200#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/05/04</i>.</small>") 46201fx_tones2layers : 46202 sval=$2 eval={max($2,$3)} 46203 remove_opacity repeat $! l[$<] 46204 +luminance rv 46205 repeat $1-1 46206 [1] 46207 val0={$sval+($eval-$sval)*$>/($1-2)} 46208 val1={$sval+($eval-$sval)*($>+1)/($1-2)-1} 46209 +ir[0] $val0,$val1 46210 if $5 *. [0] b. $4% n. 0,255 # Scalar alpha. 46211 else b. $4% n. 0,255 # Binary alpha. 46212 fi 46213 a[-2,-1] c 46214 done 46215 rm[0] rv 46216 endl done 46217 46218fx_tones2layers_preview : 46219 fx_tones2layers $* rv 46220 r {100/$!}%,{100/$!}%,1,100%,2 46221 to_rgba frame 1,1,0,0,0,255 frame 3,3,0,0,0,0 append_tiles , 46222 46223#@gui ____<b>Lights & Shadows</b> 46224#--------------------------------- 46225 46226#@gui Burn : fx_burn, fx_burn_preview(1) 46227#@gui : Amplitude = float(0.5,0,1) 46228#@gui : Scale = float(30,1,100) 46229#@gui : Smoothness = float(1,0,4) 46230#@gui : sep = separator() 46231#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46232#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46233#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46234#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46235#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46236#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46237#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46238#@gui : Value Action = choice("None","Cut","Normalize") 46239#@gui : sep = separator() 46240#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46241#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46242#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46243#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46244#@gui : sep = separator() 46245#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/24/11</i>.</small>") 46246_fx_burn : 46247 repeat $! l[$>] 46248 w,h={[w,h]} 46249 +norm 46250 fx_fourier. 2 46251 +rows. 0,{$h-1} r. $2%,$2%,1,100%,0,0,0.5,0.5 b. $3% 46252 j.. .,{($w-w)/2},{($h-h)/2} rm. 46253 fx_fourier[-2,-1] 2 46254 blend overlay,$1 46255 endl done 46256 46257fx_burn : 46258 ac "_fx_burn ${1-3}",$4,$5 46259 46260fx_burn_preview : 46261 gui_split_preview "fx_burn ${^0}",${-3--1} 46262 46263#@gui Contrast Swiss Mask : fx_contrast_swm , fx_contrast_swm(0) 46264#@gui : sep = separator() 46265#@gui : Blur the Mask = float(2,0.5,10) 46266#@gui : sep = separator() 46267#@gui : note = note ("Contrast Mask need the negative of the mask") 46268#@gui : Skip to Use the Mask to Boost = bool(false) 46269#@gui : note = note ("Uncheck for Contrast Mask,Check for Contrast Boost") 46270#@gui : sep = separator() 46271#@gui : note = note("Merge the Mask") 46272#@gui : Intensity = float(1,0,1) 46273#@gui : sep = separator() 46274#@gui : note = note("<small>Author: <i>PhotoComiX</i>. Latest Update: <i>2011/01/01</i>.</small>") 46275#@gui : url = link("Filter explained here","http://www.gimpchat.com/viewtopic.php?f=9&t=864") 46276fx_contrast_swm : 46277 repeat $! l[$>] split_opacity l[0] 46278 +luminance to_rgb 46279 blur_xy[1] $1,$1 46280 if $2==0 negate[1] fi 46281 rv blend hardlight,$3 46282 endl a c endl done 46283 46284#@gui Drop Shadow : fx_drop_shadow, fx_drop_shadow(1) 46285#@gui : X-Shadow = float(3,-20,20) 46286#@gui : Y-Shadow = float(3,-20,20) 46287#@gui : Smoothness = float(1.8,0,5) 46288#@gui : Curvature = float(0,0,1) 46289#@gui : Corner Brightness = float(0,0,1) 46290#@gui : Angle = float(0,0,360) 46291#@gui : sep = separator() 46292#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/14/11</i>.</small>") 46293fx_drop_shadow : 46294 * -1 + 255 vignette {255*$5},80,95 * -1 + 255 46295 drop_shadow $1%,$2%,$3%,$4 rotate $6,1,0 46296 46297#@gui Drop Shadow 3D : fx_drop_shadow3d, fx_drop_shadow3d_preview(1) 46298#@gui : X-Angle = float(0,-90,90) 46299#@gui : Y-Angle = float(0,-90,90) 46300#@gui : Z-Angle = float(0,-90,90) 46301#@gui : Zoom = float(0,-100,100) 46302#@gui : X-Offset = float(1,-50,50) 46303#@gui : Y-Offset = float(1,-50,50) 46304#@gui : Perspective = float(2,0,10) 46305#@gui : Smoothness = float(0.5,0,5) 46306#@gui : Color = color(0,0,0,200) 46307#@gui : Preview Only Shadow = bool(0) 46308#@gui : sep = separator() 46309#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/02/07</i>.</small>") 46310fx_drop_shadow3d : 46311 repeat $! l[$<] 46312 +_fx_drop_shadow3d $* 46313 endl done 46314 46315fx_drop_shadow3d_preview : 46316 repeat $! l[$<] 46317 if $13 _fx_drop_shadow3d $* 46318 else +_fx_drop_shadow3d $* rv blend alpha 46319 fi 46320 endl done 46321 46322_fx_drop_shadow3d : 46323 point3d 0,0,1 r3d. 1,0,0,$1 r3d. 0,1,0,$2 r3d. 0,0,1,$3 46324 u={i(0,8)} v={i(0,9)} w={i(0,10)} rm. 46325 to_a channels 100% if im==iM return fi 46326 +f 'X=x/w-0.5;Y=y/h-0.5;A=($7-$4*$7/100)*$w/(X*$u+Y*$v+$7*$w);if(A<0,1e8,A)' 46327 +*. 'y/h-0.5' *.. 'x/w-0.5' +.. {0.5-$5/100} +. {0.5-$6/100} *.. {w} *. {h} 46328 a[-2,-1] c warp[0] .,0,1,0 rm. 46329 b $8% n 0,$12 i.. ($9^$10^$11) r.. .,.,1,3 a[-2,-1] c 46330 46331#@gui Equalize Light : fx_equalize_light, fx_equalize_light_preview(1) 46332#@gui : Amount (%) = float(75,0,100) 46333#@gui : Mode = choice("Preserve range","Preserve covariance") 46334#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46335#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46336#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46337#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46338#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46339#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46340#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46341#@gui : sep = separator() 46342#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46343#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46344#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46345#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46346#@gui : sep = separator() 46347#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/03/23</i>.</small>") 46348fx_equalize_light : 46349 ac "_fx_equalize_light $1,$2",$3,1 46350 46351_fx_equalize_light : 46352 repeat $! l[$>] split_opacity l[0] 46353 . +b. {max(0.1,100-$1)}% -[-2,-1] 46354 if $2 transfer_pca. .. else n. ..,.. fi 46355 rm.. 46356 endl a c endl done 46357 46358fx_equalize_light_preview : 46359 gui_split_preview "fx_equalize_light $*",${-3--1} 46360 46361#@gui Equalize Shadow : fx_equalize_shadow, fx_equalize_shadow_preview(1) 46362#@gui : Amplitude = float(1,0,1) 46363#@gui : sep = separator() 46364#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46365#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46366#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46367#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46368#@gui : sep = separator() 46369#@gui : note = note("<small>Authors: <i>Francois Grassard</i> and <i>David Tschumperlé</i>. 46370#@gui : Latest Update: <i>2021/03/23</i>.</small>") 46371fx_equalize_shadow : 46372 repeat $! l[$>] +negate blend softlight,$1 endl done 46373 46374fx_equalize_shadow_preview : 46375 gui_split_preview "fx_equalize_shadow $1",${-3--1} 46376 46377#@gui Guided Light Rays : fx_guided_lightrays,fx_guided_lightrays_preview(1) : + 46378#@gui : Amplitude (%) = float(10,0,100) 46379#@gui : Ray Length = float(2,0,2) 46380#@gui : Mode = choice("Boundary","Dense") 46381#@gui : Density (%) = float(80,0,100) 46382#@gui : Smoothness (%) = float(0.1,0,5) 46383#@gui : Threshold (%) = float(50,0,100) 46384#@gui : Light Position = point(50,50,0,1,255,255,0,-128,1%) 46385#@gui : Light Color = color(255,255,255) 46386#@gui : Blend Mode = choice(7,"Add","Alpha","Grain Merge","Hard Light","Lighten","Lightness", 46387#@gui : "Luminance","Overlay","Soft Light","Value") 46388#@gui : Opacity (%) = float(100,0,100) 46389#@gui : sep = separator() 46390#@gui : Preview Light Shape = bool(1) 46391#@gui : sep = separator() 46392#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/04/06</i>.</small>") 46393fx_guided_lightrays : 46394 bmode=${"arg0 $12,add,alpha,grainmerge,hardlight,lighten,lchlightness,\ 46395 luminance,overlay,softlight,value"} 46396 if $3 cond="i" else cond="i && !(j(-1) && j(1) && j(0,-1) && j(0,1))" fi 46397 if 0$_is_preview" && "$14 i[1] [0] gui_set_layer_opacity[1] 50 fi 46398 46399 l[0] # Process top layer only (light shape). 46400 if s==2" || "s==4 channels 100% else compose_channels max fi 46401 ge $6% 46402 46403 # Draw lightrays. 46404 100%,100% 46405 eval.. "* 46406 const L = $2<1?$2:$2^5; 46407 const Xl = $7<0?3*$7:$7>100?100+3*($7-100):$7; 46408 const Yl = $8<0?3*$8:$8>100?100+3*($8-100):$8; 46409 const xl = Xl*(w - 1)/100; 46410 const yl = Yl*(h - 1)/100; 46411 "$cond" && u<=$4%?( 46412 u = x - xl; v = y - yl; 46413 polygon(#-1,2,xl,yl,xl + L*u,yl + L*v,-1,255); 46414 )" 46415 46416 equalize. 65536,1,{iM} n. 0,1 power={10^(-$1%)} pow. {max(1e-2,$power)} b. $5% n. 0,255 46417 i[-2] (${9-11}:cyzx) r.. .,.,1,3 a[-2,-1] c 46418 k. gui_set_layer_mode $bmode gui_set_layer_opacity $13 46419 endl 46420 if 0$_is_preview gui_merge_layers 46421 elif 0$_output_mode k[0] 46422 fi 46423 46424fx_guided_lightrays_preview : 46425 _is_preview=1 46426 fx_guided_lightrays $* 46427 46428#@gui Illuminate 2D Shape : fx_illuminate_shape2d,fx_illuminate_shape2d_preview(1)+ 46429#@gui : note = note("<small><b>Input / Output:</b></small>) 46430#@gui : Input Type = choice{"Single Opaque Shapes Over Transp. BG","Multiple Colored Shapes Over Transp. BG", 46431#@gui : "Bump Map","Normal Map"} 46432#@gui : Output Type = choice{"Illumination","Bump Map","Normal Map"} 46433#@gui : Input Guide Color = color(255,0,0,255) 46434#@gui : Keep Base Layer as Input Background = bool(1) 46435#@gui : Keep Transparency in Output = bool(1) 46436#@gui : sep = separator() 46437#@gui : note = note("<small><b>Shape:</b></small>) 46438#@gui : Minimal Shape Area = int(4,1,100) 46439#@gui : note = note{"<small>Parameter <i>Minimal shape area</i> is only active in <i>Multiple colored shapes</i> 46440#@gui : input mode.</small>"} 46441#@gui : Preview Detected Shapes = bool(0) 46442#@gui : Erosion / Dilation = float(0,-10,10) 46443#@gui : Smoothness = float(3,0,6) 46444#@gui : Bump Factor = float(1,-5,5) 46445#@gui : Avg / Max Weight = float(1,0,1) 46446#@gui : Resolution = choice{4,"Full (Slower)","2048","1024","512","256","128","64 (Faster)"} 46447#@gui : sep = separator() 46448#@gui : note = note("<small><b>Illumination:</b></small>) 46449#@gui : Blending Mode = choice(10,"Normal","Lighten","Screen","Dodge","Add","Darken","Multiply","Burn","Overlay", 46450#@gui : "Soft Light","Hard Light","Grain Merge") 46451#@gui : Opacity (%) = float(75,0,100) 46452#@gui : Ambient (%) = float(30,-100,100) 46453#@gui : Diffuse (%) = float(40,0,200) 46454#@gui : Specular (%) = float(40,0,300) 46455#@gui : Shininess = float(80,0,100) 46456#@gui : Smoothness = float(0.2,0,5) 46457#@gui : Flatness = float(1,0,3) 46458#@gui : Linearity = float(0,-100,100) 46459#@gui : Levels = int(0,0,16) 46460#@gui : Light-X = float(2,-20,20) 46461#@gui : Light-Y = float(-2,-20,20) 46462#@gui : Light-Z = float(2,0,20) 46463#@gui : Normalize Illumination = bool(0) 46464#@gui : sep = separator() 46465#@gui : Open Interactive Preview = button() 46466#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46467#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46468#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46469#@gui : sep = separator() 46470#@gui : note = note{"<small><b>Note:</b> This filter automatically adds illumination to an opaque shape defined 46471#@gui : over a transparent background.</small>"} 46472#@gui : sep = separator() 46473#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/05/18</i>.</small>") 46474fx_illuminate_shape2d : 46475 input_type,\ 46476 output_type,\ 46477 keep_input_bg,\ 46478 preview_shapes,\ 46479 blending_mode,\ 46480 opacity=$1,$2,$7,$10,$16,$17 46481 blending_mode=${arg\ 1+$blending_mode,normal,lighten,screen,dodge,add,darken,multiply,burn,overlay,\ 46482 softlight,hardlight,grainmerge} 46483 keep_input_bg&={$!>1} 46484 46485 if $output_type # Output : bumpmap or normalmap 46486 repeat $!-$keep_input_bg _fx_illuminate_shape2d[$>] $* done 46487 46488 else # Output : illumination 46489 repeat $!-$keep_input_bg if $keep_input_bg sel=$>,-1 else sel=$> fi l[$sel] 46490 if !$keep_input_bg" && "$input_type>=2 # From bumpmap/normalmap w/o background 46491 _fx_illuminate_shape2d $* 46492 elif $keep_input_bg" && "$input_type>=2 # From bumpmap/normalmap w/ background 46493 _fx_illuminate_shape2d[0] $* 46494 elif !$keep_input_bg" && "$input_type<=1 # From shape w/o background 46495 +_fx_illuminate_shape2d $* rv 46496 else # From shape w/ background 46497 _fx_illuminate_shape2d[0] $* 46498 fi 46499 if !$preview_shapes" || "0$_is_preview!=1 46500 gui_set_layer_mode[0] $blending_mode 46501 gui_set_layer_opacity[0] $opacity 46502 if $!>1" && "(0$_output_mode==0" || "0$_is_preview==1) 46503 if $keep_input_bg" && "!0$_is_preview . fi 46504 gui_merge_layers[0,1] 46505 else k[0] fi 46506 fi 46507 endl done 46508 fi 46509 46510fx_illuminate_shape2d_preview : 46511 _is_preview=1 46512 input_type,\ 46513 keep_input_bg,\ 46514 preview_interactive=$1,$7,$-2 46515 keep_input_bg&={$!>1} 46516 if $preview_interactive fx_illuminate_shape2d_preview_interactive $* fi 46517 if $keep_input_bg 46518 repeat $!-1 l[$>,-1] 46519 fx_illuminate_shape2d $* 46520 rv to_colormode 0 a z 46521 gui_split_preview "slices 50%,100%",$-1 46522 endl done 46523 else 46524 gui_split_preview "fx_illuminate_shape2d $*",$-1 46525 fi 46526 46527fx_illuminate_shape2d_preview_interactive : 46528 _output_mode=0 46529 input_type,\ 46530 keep_input_bg=$1,$7 46531 keep_input_bg&={$!>1} 46532 repeat $!-$keep_input_bg if $keep_input_bg sel=$>,-1 else sel=$> fi +l[$sel] 46533 to_rgba 46534 +_fx_illuminate_shape2d[0] $1,2,${3-6},0,1,""$9,0,${11-15},""${16-29},""0,0 46535 if $!>2 rm[0] elif $input_type>=2 sh[0] 0,2 f. 128 rm. fi 46536 siz=${fitscreen\ {[w,h,1]},256,640} 46537 wsiz0=${fitscreen\ $siz,1,30%,100%} 46538 wsiz=$wsiz0 46539 r $siz,1,100%,3 46540 s. c,-3 !=. 0 l.. - 128 / 127 s c,-2 / endl a[-2,-1] c # Gradient map 46541 rv s. c,-3 46542 (160,128;128,160) r. 16,16 r. ..,..,1,3,0,2 46543 30,30,1,1 circle. 50%,50%,15%,1,1 b. 4 n. 0,1 46544 100%,100%,1,3,[255,255,0] 46545 nm normal,rgb,alpha,background,light_alpha,light_rgb 46546 46547 w[] $wsiz,0,0,{rgb,([{*,u},{*,v}]-[$wsiz])/2},"[G'MIC] Illuminate 2D Shape" 46548 cursor 0 46549 x0,y0,ox,oy,ob,olightz=-1 46550 lightz=2 clicked=0 46551 46552 do 46553 x,y,b,mw={rgb,[{*,x},{*,y}]*[w,h]/[{*,w},{*,h}]},{*,b},{*,-o} 46554 lightz={cut($lightz-0.3*sign($mw)+($y0>=0?3*($y-$y0)/h),0.1,4)} 46555 if $x<0 x,y={rgb,ang=$|;(1+[cos(1.4*ang),sin(0.85*ang)])*[w,h]/2} fi 46556 if !$b" || "($b&1) 46557 if $b" && "!$clicked x0,y0=$x,$y 46558 elif !$b x0,y0=-1 46559 fi 46560 lightx,lighty={rgb,3.5*(2*[$x/w,$y/h]-1)} 46561 if [$ox,$oy,$ob,$olightz]!=[$x,$y,$b,$lightz] 46562 +fx_illuminate_shape2d[normal,rgb] 4,0,${3-6},1,1,""$9,0,${11-15},""${16-25},$lightx,$lighty,$lightz,$29,""0,0 46563 +j[background] .,0,0,0,0,1,[alpha],255 rm.. 46564 +r2dx[light_alpha,light_rgb] {light_rgb,8+$lightz*(w-8)} j... .,{[$x,$y]-[w,h]/2},0,0,1,.. rm[-2,-1] 46565 r. $wsiz,1,100% to. "Light: ("{``{_round([$lightx,$lighty,$lightz],0.1)}}")",2,2,16 46566 w. rm. wait 20 46567 else wait 46568 fi 46569 clicked=$b 46570 elif $b&2 46571 +j[background] [rgb],0,0,0,0,1,[alpha],255 46572 +r2dx[light_alpha,light_rgb] {light_rgb,8+$lightz*(w-8)} j... .,{[$x,$y]-[w,h]/2},0,0,1,.. rm[-2,-1] 46573 w. rm. wait 46574 fi 46575 if {*,CTRLLEFT}" && "{*,-D} w[] {1.5*[{*,w},{*,h}]} wsiz={*,w},{*,h} 46576 elif {*,CTRLLEFT}" && "{*,-C} w[] {0.75*[{*,w},{*,h}]} wsiz={*,w},{*,h} 46577 elif {*,CTRLLEFT}" && "{*,-R} w[] $wsiz0 46578 fi 46579 ox,oy,ob=$x,$y,$b 46580 46581 while {*}" && "!{*,ESC}" && "!{*,Q} 46582 w 0 46583 rm endl done 46584 46585_fx_illuminate_shape2d : # Input selection must contains a single image. Output is a single image. 46586 input_type,\ 46587 output_type,\ 46588 gR,gG,gB,gA,\ 46589 keep_input_bg,\ 46590 keep_output_transparency,\ 46591 min_shape_area,\ 46592 preview_shapes,\ 46593 dilation,\ 46594 shape_smoothness,\ 46595 bump_factor,\ 46596 weight_avg_max,\ 46597 resolution,\ 46598 blending_mode,\ 46599 opacity,\ 46600 ambient,\ 46601 diffuse,\ 46602 specular,\ 46603 shininess,\ 46604 light_smoothness,\ 46605 flatness,\ 46606 linearity,\ 46607 levels,\ 46608 lightx,\ 46609 lighty,\ 46610 lightz,\ 46611 normalize_illumination,\ 46612 preview_interactive,\ 46613 preview_mode=${1-31} 46614 46615 # Generate 2D binary shape and corresponding bumpmap 46616 nm={n} 46617 if $input_type==0 # Single opaque shape 46618 to_rgba 46619 +channels. 100% >. 0 . 46620 select_color... 0,$gR,$gG,$gB,$gA 46621 mv... $! -[-2,-1] 46622 46623 elif $input_type==1 # Multiple colored shapes 46624 to_rgba 46625 +channels. 100% >. 0 *[-2,-1] 46626 if $min_shape_area>1 +quantize_area. {$min_shape_area^2} fi 46627 s. c,-{s-1} >. 0 rv[-2,-1] 46628 if s>1 f. "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm. round. 0.01 fi 46629 label. 0,0 f. "j(1)!=i || j(0,1)!=i" thinning. 1 ==. 0 *. .. 46630 select_color... 0,$gR,$gG,$gB,$gA 46631 mv... $! -[-2,-1] 46632 46633 elif $input_type==2 # Bump map 46634 to_a 46635 s c,-{s-1} >. 0 *.. . rv s. c S={$!-1} +[^0] /. $S 46636 46637 elif $input_type==3 # Normal map 46638 +channels 100% >. 0 *.. . rv 46639 f. "I==vector4(0)?[128,128,255,255]:I" 46640 channels. 0,2 46641 46642 else # Gradient map (hidden mode used by interactive preview) 46643 +channels 100% rv 46644 fi 46645 46646 if 0$_is_preview" && "$preview_shapes 46647 if $input_type==3 k[0] else k. fi 46648 +dilate. 3 46649 label_fg.. 0 srand 0 {-2,iM+1},1,1,3,'x==0?[0,0,0]:x==1?[255,255,255]:u([255,255,255])' map... . rm. 46650 *. 255 a c 46651 return 46652 fi 46653 46654 if $input_type<=1 46655 shape2bump. {arg($resolution,2048,1024,512,256,128,64)},$weight_avg_max,{$dilation%*max(w,h)},\ 46656 {$shape_smoothness*50} 46657 fi 46658 if $input_type<=2 46659 if $input_type==2" && "$shape_smoothness mM={[im,iM]} guided. ..,$shape_smoothness%,100 n. $mM fi 46660 *. $bump_factor 46661 fi 46662 46663 # Generate output. 46664 if $output_type==1 # Output as a bump map 46665 if $input_type<=2 46666 if $keep_output_transparency k[-2,-1] n 0,255 rv a c # With transparency 46667 else k. n 0,255 # Without transparency 46668 fi 46669 else 46670 rm gui_error_preview "Cannot convert a normal map to a bump map." return 46671 fi 46672 46673 elif $output_type==2 # Output as a normal map 46674 if $input_type<=2 round 0.0001 bump2normal. f. "i(#-2)?I:[128,128,255]" fi 46675 if $keep_output_transparency k[-2,-1] rv *. 255 a c # With transparency 46676 else k. # Without transparency 46677 fi 46678 46679 else # Output as illumination layer (phong model) 46680 if $input_type<=2 g. xy a[-2,-1] c 46681 elif $input_type==3 -. 128 /. 127 s. c,-2 /[-2,-1] 46682 fi 46683 f. "* 46684 begin( 46685 const flatness = "$flatness"; # Surface flatness 46686 const ka = "$ambient"%; # Ambient 46687 const kd = "$diffuse"%; # Diffuse 46688 const ks = "$specular"%; # Specular 46689 const alpha = "$shininess"; # Specularity 46690 const m1 = max(1,"$lightz"); 46691 const mwh1 = max(w,h) - 1; 46692 light = [ "m1*$lightx,m1*$lighty,-$lightz" ]; # Light position 46693 camera = [ 0,0,-"$lightz" ]; # Camera position 46694 ); 46695 res = i#0?( 46696 P = [ 2*x/mwh1 - 1,2*y/mwh1 - 1,0 ]; 46697 L = light - P; 46698 L/=norm(L); 46699 V = camera - P; 46700 V/=norm(V); 46701 N = -[ i0,i1,flatness ]; 46702 N/=norm(N); 46703 R = 2*dot(N,L)*N - L; 46704 res = ka + kd*dot(L,N) + ks*max(dot(R,V),0)^alpha; 46705 ):0; 46706 [ res,0 ]" 46707 channels. 0 *. 255 c. 0,255 46708 if $light_smoothness" || "$linearity 46709 mM={[im,iM]} 46710 if $light_smoothness b. $light_smoothness% fi 46711 if $linearity n. 0,1 ^. {10^-($linearity%)} fi 46712 n. $mM 46713 fi 46714 if $levels quantize. $levels,1,1 fi 46715 if $normalize_illumination n. 0,255 fi 46716 rv[-2,-1] *. 255 a[-2,-1] c 46717 nm $nm 46718 if !$keep_output_transparency remove_opacity. fi 46719 fi 46720 nm $nm 46721 46722#@gui Light Glow : fx_lightglow, fx_lightglow_preview(0) 46723#@gui : Density = float(30,0,100) 46724#@gui : Amplitude = float(0.5,0,2) 46725#@gui : Mode = choice(8,"Burn","Dodge","Freeze","Grain Merge","Hard Light","Interpolation","Lighten","Multiply", 46726#@gui : "Overlay","Reflect","Soft Light","Stamp","Value") 46727#@gui : Opacity = float(0.8,0,1) 46728#@gui : sep = separator() 46729#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46730#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46731#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46732#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46733#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46734#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46735#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46736#@gui : sep = separator() 46737#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46738#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46739#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46740#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46741#@gui : sep = separator() 46742#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/21/02</i>.</small>") 46743_fx_lightglow : 46744 mode=${arg\ 1+$3,burn,dodge,freeze,grainmerge,hardlight,interpolation,lighten,multiply,overlay,reflect,\ 46745 softlight,stamp,value} 46746 repeat $! 46747 +gradient_norm. >=. {100-$1}% distance. 1 ^. $2 *. -1 n. 0,255 blend $mode,$4 46748 mv. 0 done 46749 46750fx_lightglow : 46751 ac "_fx_lightglow ${1-4}",$5 46752 46753fx_lightglow_preview : 46754 gui_split_preview "fx_lightglow $*",${-3--1} 46755 46756#@gui Light Leaks : fx_light_leaks, fx_light_leaks_preview(1) 46757#@gui : Leak Type = int(0,0,70) 46758#@gui : Angle = float(0,-180,180) 46759#@gui : X-Scale = float(1,1,10) 46760#@gui : Y-Scale = float(1,1,10) 46761#@gui : Hue = float(0,-180,180) 46762#@gui : Opacity = float(0.85,0,1) 46763#@gui : Blend Mode = choice(2,"Normal","Lighten","Screen","Dodge","Add","Darken","Multiply","Burn","Overlay", 46764#@gui : "Soft Light","Hard Light","Difference","Subtract","Grain Extract","Grain Merge","Divide","Hue","Saturation", 46765#@gui : "Value") 46766#@gui : Output as Separate Layers = _bool(1) 46767#@gui : sep = separator() 46768#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46769#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46770#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46771#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46772#@gui : sep = separator() 46773#@gui : note = note{"<small>This filter uses the free light leaks dataset available at :</small>"} 46774#@gui : url = link{"Lomo Light Leaks","http://www.photoshoptutorials.ws/downloads/mockups-graphics/lomo-light-leaks/"} 46775#@gui : sep = separator() 46776#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/01/07</i>.</small>") 46777fx_light_leaks : 46778 filename=lightleak_${"padint $1",6}.cimgz 46779 input_cached data_lightleaks/$filename 46780 mode=${arg\ 1+$7,normal,lighten,screen,dodge,add,darken,multiply,burn,overlay,softlight,hardlight,difference,\ 46781 subtract,grainextract,grainmerge,divide,hue,saturation,value} 46782 mv. 0 46783 repeat $!-1 l[0,{1+$<}] 46784 +r[0] {1,w},{1,h},1,3,5 46785 rotate. $2,1,1,50%,50% 46786 if $3>1" || "$4>1 f. 'w2=w/2;h2=h/2;X=x-w2;Y=y-h2;i(w2+X/$3,h2+Y/$4,0,c,1,0)' fi 46787 c. 0,255 46788 if $5 rgb2hsv. sh. 0 +. $5 rm. hsv2rgb. fi 46789 if $8 46790 nm=${gui_layer_name[1]} 46791 nm. name($nm),opacity({$6*100}),mode($mode) rv[-2,-1] 46792 else blend[1,-1] $mode,$6 fi 46793 endl done 46794 rm[0] 46795 46796fx_light_leaks_preview : 46797 gui_split_preview "fx_light_leaks ${1--5},0",${-3--1} 46798 46799_fx_light_leaks : 46800 u="" repeat 71 if narg($u) u=$u, fi u=${u}lightleak_${"padint "$>,6} done 46801 u $u 46802 46803#@gui Light Patch : fx_light_patch, fx_light_patch(0) 46804#@gui : Density = int(5,2,30) 46805#@gui : Darkness = float(0.7,0,1) 46806#@gui : Lightness = float(2.5,1,4) 46807#@gui : sep = separator() 46808#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46809#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46810#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46811#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46812#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46813#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46814#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46815#@gui : sep = separator() 46816#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46817fx_light_patch : 46818 repeat $! l[$>] split_opacity l[0] 46819 ac "light_patch $1,$2,$3",$4 46820 endl a c endl done 46821 46822#@gui Light Rays : fx_lightrays, fx_lightrays(1) 46823#@gui : Density = float(80,0,100) 46824#@gui : Center (%) = point(50,50,0,1) 46825#@gui : Length = float(1,0,1) 46826#@gui : Attenuation = float(0.5,0,1) 46827#@gui : Transparency = bool(0) 46828#@gui : sep = separator() 46829#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/03/01</i>.</small>") 46830fx_lightrays : 46831 lightrays $1,$2%,$3%,$4,$5 46832 if $6 repeat $! r[$>] 100%,100%,1,{{$>,s}+({$>,s}%2)} done fi 46833 46834#@gui Pop Shadows : fx_pop_shadows, fx_pop_shadows_preview(1) 46835#@gui : Strength = float(0.75,0,1) 46836#@gui : Scale = float(5,0,20) 46837#@gui : Post-Normalize = bool(1) 46838#@gui : sep = separator() 46839#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46840#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46841#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46842#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46843#@gui : sep = separator() 46844#@gui : note = note("<small>Authors: <i>Morgan Hardwood</i> and <i>David Tschumperlé</i>. 46845#@gui : Latest Update: <i>2017/03/05</i>.</small>") 46846fx_pop_shadows : 46847 repeat $! l[$>] split_opacity l[0] 46848 .x2 46849 luminance.. negate.. imM={-2,[im,iM]} b.. $2% n.. $imM 46850 blend[0,1] overlay,$1 46851 max 46852 if $3 n 0,255 fi 46853 endl a c endl done 46854 46855fx_pop_shadows_preview : 46856 gui_split_preview "fx_pop_shadows $*",${-3--1} 46857 46858#@gui Relief Light : fx_light_relief, fx_light_relief(1) 46859#@gui : Ambient Lightness = float(0.3,0,5) 46860#@gui : Specular Lightness = float(0.2,0,2) 46861#@gui : Specular Size = float(0.2,0,1) 46862#@gui : Darkness = float(0,0,1) 46863#@gui : Light Smoothness = float(1,0,5) 46864#@gui : XY-Light = point(50,50,0,1,255,255,128,200,10) 46865#@gui : Z-Light = float(5,0,20) 46866#@gui : Z-Scale = float(0.5,0,3) 46867#@gui : Opacity as Heightmap = bool(0) 46868#@gui : Image Smoothness = float(0,0,10) 46869#@gui : sep = separator() 46870#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46871fx_light_relief : 46872 b $11% light_relief ${1-5},{[$6,$7]%},${8-10} 46873 46874#@gui Shadow Patch : fx_shadow_patch, fx_shadow_patch(1) 46875#@gui : Opacity = float(0.7,0,1) 46876#@gui : sep = separator() 46877#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46878#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46879#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46880#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46881#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46882#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46883#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46884#@gui : sep = separator() 46885#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46886fx_shadow_patch : 46887 repeat $! l[$>] split_opacity l[0] 46888 ac "shadow_patch $1",$2 46889 endl a c endl done 46890 46891#@gui Slice Luminosity : fx_slice_luminosity, fx_slice_luminosity_preview 46892#@gui : Luminosity Type = choice(1,"Average RGB","Luminance","Lightness","Value") 46893#@gui : Output As = _choice(1,"Mask","Masked Image") 46894#@gui : Preview Type = choice(2,"Mask","Mask + Background","Image","Image + Background") 46895#@gui : sep = separator() 46896#@gui : note = note{"<small><b>Slice 1</b> (shadows):</small>"} 46897#@gui : Activate Slice 1 = bool(1) 46898#@gui : Starting Value = int(0,0,255) 46899#@gui : Ending Value = int(64,0,255) 46900#@gui : Starting Feathering = int(0,0,255) 46901#@gui : Ending Feathering = int(0,0,255) 46902#@gui : sep = separator() 46903#@gui : note = note{"<small><b>Slice 2</b> (low midtones):</small>"} 46904#@gui : Activate Slice 2 = bool(1) 46905#@gui : Starting Value = int(64,0,255) 46906#@gui : Ending Value = int(128,0,255) 46907#@gui : Starting Feathering = int(0,0,255) 46908#@gui : Ending Feathering = int(0,0,255) 46909#@gui : sep = separator() 46910#@gui : note = note{"<small><b>Slice 3</b> (high midtones):</small>"} 46911#@gui : Activate Slice 3 = bool() 46912#@gui : Starting Value = int(128,0,255) 46913#@gui : Ending Value = int(192,0,255) 46914#@gui : Starting Feathering = int(0,0,255) 46915#@gui : Ending Feathering = int(0,0,255) 46916#@gui : sep = separator() 46917#@gui : note = note{"<small><b>Slice 4</b> (highlights):</small>"} 46918#@gui : Activate Slice 4 = bool() 46919#@gui : Starting Value = int(192,0,255) 46920#@gui : Ending Value = int(255,0,255) 46921#@gui : Starting Feathering = float(0,0,255) 46922#@gui : Ending Feathering = float(0,0,255) 46923#@gui : sep = separator() 46924#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/22/09</i>.</small>") 46925fx_slice_luminosity : 46926 remove_opacity repeat $! l[$<] to_rgb 46927 _fx_slice_luminosity $* 46928 if $2 i[0] [0] a[-2,-1] c fi 46929 rv 46930 endl done 46931 46932fx_slice_luminosity_preview : 46933 remove_opacity repeat $! l[$>] to_rgb 46934 _fx_slice_luminosity $* 46935 if $3==0 rm[0] channels {s-1} 46936 elif $3==1 100%,100%,1,1,128 a[0,-1] c r. 100%,100%,1,4 blend alpha 46937 elif $3==2 a c 46938 else +. 96 c. 0,255 a c 46939 fi 46940 endl done 46941 46942_fx_slice_luminosity : 46943 if $1==0 +compose_channels + /. 3 46944 elif $1==1 +luminance 46945 elif $1==2 +srgb2lab8. channels. 0 46946 else +compose_channels max 46947 fi 46948 if $4 +apply_curve[1] 0,{$5-$7-0.1},0,$5,255,$6,255,{$6+$8+0.1},0,512,0 fi 46949 if $9 +apply_curve[1] 0,{$10-$12-0.1},0,$10,255,$9,255,{$11+$13+0.1},0,512,0 fi 46950 if $14 +apply_curve[1] 0,{$15-$17-0.1},0,$15,255,$16,255,{$16+$18+0.1},0,512,0 fi 46951 if $19 +apply_curve[1] 0,{$20-$22-0.1},0,$20,255,$21,255,{$21+$23+0.1},0,512,0 fi 46952 rm[1] max[^0] 46953 46954#@gui ____<b>Patterns</b> 46955#------------------------ 46956 46957#@gui Bayer Filter : rgb2bayer, rgb2bayer(0) 46958#@gui : Starting Pattern = choice(0,"Red-Green","Blue-Green","Green-Red","Green-Blue") 46959#@gui : Keep Colors = bool(1) 46960#@gui : sep = separator() 46961#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46962 46963#@gui Box Fitting : fx_boxfitting, fx_boxfitting_preview(0) 46964#@gui : Minimal Size = int(3,1,32) 46965#@gui : Maximal Size = int(0,0,32) 46966#@gui : note = note("<small><b>Note:</b> Set <i>Maximal size</i> to <i>0</i> to allow any size 46967#@gui : for the squares.</small>") 46968#@gui : Initial Density = float(0.1,0,1) 46969#@gui : Transparency = bool(0) 46970#@gui : sep = separator() 46971#@gui : note = note("<small><b>Note:</b> This filter has been highly inspired by the work of Jared Tarbell, 46972#@gui : described on the page:</small>") 46973#@gui : url = link("http://www.complexification.net/gallery/machines/boxFittingImg/") 46974#@gui : sep = separator() 46975#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/06/06</i>.</small>") 46976fx_boxfitting : 46977 boxfitting ${1-3},3 46978 if $4 to_rgba replace_color 0,0,0,0,0,255,0,0,0,0 fi 46979 46980fx_boxfitting_preview : 46981 boxfitting ${1-3},1 46982 if $4 to_rgba replace_color 0,0,0,0,0,255,0,0,0,0 fi 46983 46984#@gui Camouflage : fx_camouflage, fx_camouflage 46985#@gui : Scale = int(9,2,12) 46986#@gui : Levels = int(12,2,32) 46987#@gui : Coherence = float(100,0,1000) 46988#@gui : Color 1 = color(30,46,33) 46989#@gui : Color 2 = color(75,90,65) 46990#@gui : Color 3 = color(179,189,117) 46991#@gui : Color 4 = color(255,246,158) 46992#@gui : sep = separator() 46993#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/26/10</i>.</small>") 46994fx_camouflage : 46995 repeat $! l[$>] split_opacity l[0] 46996 channels 0 r {w+16},{h+16},1,1,0 rand 0,16 46997 amp=$3 do smooth {min(50,$amp)},0,1 amp-=50 while $amp>0 46998 shrink_xy. 8 n 1,$2 round 46999 repeat $1 +area 0,0 <. {1+2^$>} inpaint[0] [1],0,3 rm. done 47000 +colormap 0 n.. 0,{w-1} 47001 4,1,1,3,"col=[${4-15}];col[3*x,3]" 47002 r. ..,..,1,3,3 rm.. map.. . rm. 47003 endl a c endl done 47004 47005#@gui Canvas : fx_canvas, fx_canvas_preview(0) 47006#@gui : note = note{"<b>First direction :</b>"} 47007#@gui : Amplitude = float(70,0,300) 47008#@gui : Angle = float(45,0,180) 47009#@gui : Sharpness = float(400,0,2000) 47010#@gui : note = note{"\n<b>Second direction : </b>"} 47011#@gui : Activate Second Direction = bool(true) 47012#@gui : Amplitude = float(70,0,300) 47013#@gui : Angle = float(135,0,180) 47014#@gui : Sharpness = float(400,0,2000) 47015#@gui : sep = separator() 47016#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47017#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47018#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47019#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47020#@gui : sep = separator() 47021#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47022fx_canvas : 47023 repeat $! l. 47024 if $4 47025 ({cos($2*pi/180)}^{sin($2*pi/180)}) vector2tensor. r. ..,.. +smooth.. .,$1 rm.. sharpen. $3 c. 0,255 47026 ({cos($6*pi/180)}^{sin($6*pi/180)}) vector2tensor. r. ..,.. smooth... .,$5 rm. sharpen.. $7 c.. 0,255 47027 +[-2,-1] /. 2 47028 else 47029 ({cos($2*pi/180)}^{sin($2*pi/180)}) vector2tensor. r. ..,.. smooth.. .,$1 rm. sharpen. $3 c. 0,255 47030 fi 47031 endl mv. 0 done 47032 47033fx_canvas_preview : 47034 gui_split_preview "fx_canvas $*",${-3--1} 47035 47036#@gui Canvas Texture : texturize_canvas, texturize_canvas(0) 47037#@gui : Amplitude = float(20,0,256) 47038#@gui : Fibrousness = float(3,0,20) 47039#@gui : Emboss = float(0.6,0,1) 47040#@gui : sep = separator() 47041#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47042 47043#@gui Cracks : fx_cracks, fx_cracks_preview(0) 47044#@gui : Density (%) = float(30,0,100) 47045#@gui : Relief = bool(true) 47046#@gui : Color = color(255,255,255,128) 47047#@gui : sep = separator() 47048#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 47049#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 47050#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 47051#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 47052#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 47053#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 47054#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 47055#@gui : sep = separator() 47056#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47057#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47058#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47059#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47060#@gui : sep = separator() 47061#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/07</i>.</small>") 47062fx_cracks : 47063 ac "cracks $1,$2,{$6/255},${3-5},255",$7 47064 47065fx_cracks_preview : 47066 gui_split_preview "fx_cracks $*",${-3--1} 47067 47068#@gui Crystal : fx_crystal, fx_crystal_preview(0) 47069#@gui : Density = float(50,0,100) 47070#@gui : Smoothness = float(0.2,0,2) 47071#@gui : Edges = float(20,0,100) 47072#@gui : sep = separator() 47073#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47074#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47075#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47076#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47077#@gui : sep = separator() 47078#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/19/01</i>.</small>") 47079fx_crystal : 47080 repeat $! l[$>] split_opacity l[0] 47081 s={s} 47082 +gradient_norm >=. {(100-$3)/5} remove_pixels. {100-max(0.1,$1*$3%)}%,{is} * 47083 +norm !=. 0 a c 47084 sigma=0.5 47085 do 47086 +b. $sigma sigma*={(1+$2)} 47087 sh[0,-1] $s max. .. rm[-2,-1] 47088 f. 'W=i(x,y,z,$s);if(W<0.001||W>=1,0,if(c<$s,i/W,1))' 47089 if !iM rm[1] break fi 47090 sh. $s 47091 j[0] [1],0,0,0,0,1,[2] k[0] 47092 while 1 47093 channels 0,{$s-1} 47094 endl a c endl done 47095 47096fx_crystal_preview : 47097 gui_split_preview "fx_crystal $*",${-3--1} 47098 47099#@gui Crystal Background : fx_crystal_background, fx_crystal_background 47100#@gui : Iterations = int(10,1,32) 47101#@gui : Density (%) = float(25,0,100) 47102#@gui : Random Seed = int(0,0,65535) 47103#@gui : Opacity (%) = float(100,0,100) 47104#@gui : Color = bool(1) 47105#@gui : sep = separator() 47106#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/18/10</i>.</small>") 47107fx_crystal_background : 47108 repeat $! l[$>] split_opacity l[0] 47109 N={2*max(3,round((${"is_percent $2"}?4*wh*$2:$2)))} 47110 if $5 col="u([255,255,255])" else col="u(255)" fi 47111 srand $3 M={max(w,h)} 2,$N 47112 repeat $1 rand. {-$M/2},{3*$M/2} polygon.. $N,{^},{-$4%},{$col} done 47113 rm. n 0,255 47114 endl a c endl done 47115 47116#@gui Halftone : fx_halftone, fx_halftone_preview(0) 47117#@gui : note = note("<b><small>Image parameters :</small></b>") 47118#@gui : Brightness (%) = float(0,-100,100) 47119#@gui : Contrast (%) = float(0,-100,100) 47120#@gui : Gamma (%) = float(0,-100,100) 47121#@gui : Smoothness = float(0,0,10) 47122#@gui : sep = separator() 47123#@gui : note = note("<b><small>Halftone parameters :</small></b>") 47124#@gui : Number of Tones = int(5,2,32) 47125#@gui : Size for Dark Tones = int(8,2,256) 47126#@gui : Size for Bright Tones = int(8,2,256) 47127#@gui : Shape = choice{5,"Square","Diamond","Circle","Square (Inv.)","Diamond (Inv.)","Circle (Inv.)"} 47128#@gui : Smoothness = float(0.1,0,32) 47129#@gui : sep = separator() 47130#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47131#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47132#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47133#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47134#@gui : sep = separator() 47135#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/23/07</i>.</small>") 47136fx_halftone : 47137 adjust_colors ${1-3},0,0,0,255 b $4 47138 repeat $! l[$>] split_opacity 47139 halftone[0] ${5-9} 47140 a c endl done 47141 47142fx_halftone_preview : 47143 gui_split_preview "fx_halftone $*",${-3--1} 47144 47145#@gui Hearts : fx_hearts, fx_hearts_preview(0) 47146#@gui : Density = float(2,0,30) 47147#@gui : sep = separator() 47148#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 47149#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 47150#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 47151#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 47152#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 47153#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 47154#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 47155#@gui : sep = separator() 47156#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47157#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47158#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47159#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47160#@gui : sep = separator() 47161#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47162fx_hearts : 47163 ac "hearts $1",$2 47164 47165fx_hearts_preview : 47166 gui_split_preview "fx_hearts $*",${-3--1} 47167 47168#@gui Lava : fx_lava, fx_lava_preview(0) 47169#@gui : Perturbation = int(8,0,15) 47170#@gui : Smoothness = float(5,0,100) 47171#@gui : Scale = float(3,0,20) 47172#@gui : Sharpness = float(0,0,1000) 47173#@gui : sep = separator() 47174#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47175#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47176#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47177#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47178#@gui : sep = separator() 47179#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/26/11</i>.</small>") 47180fx_lava : 47181 repeat $! l[$>] split_opacity l[0] norm 47182 100%,100% plasma. 1,1,{16-$1} smooth. $2,0,1,$3,$3,0.8,90 * 47183 gradient_norm n 0,255 47184 equalize map 3 47185 sharpen $4 47186 endl a c endl done 47187 47188fx_lava_preview : 47189 gui_split_preview "fx_lava $*",${-3--1} 47190 47191#@gui Marble : fx_marble, fx_marble 47192#@gui : Image Weight = float(.5,0,30) 47193#@gui : Pattern Weight = float(1,0,30) 47194#@gui : Pattern Angle = float(0,0,360) 47195#@gui : Amplitude = float(0,0,1000) 47196#@gui : Sharpness = float(.4,0,5) 47197#@gui : Anisotropy = float(.6,0,1) 47198#@gui : Alpha = float(.6,0,20) 47199#@gui : Sigma = float(1.1,0,20) 47200#@gui : Cut Low = float(0,0,100) 47201#@gui : Cut High = float(100,0,100) 47202#@gui : sep = separator() 47203#@gui : note = note("<small>Author: <i>Preben Soeberg</i>. Latest Update: <i>2010/29/12</i>.</small>") 47204fx_marble : 47205 repeat $! l[$>] split_opacity l[0] 47206 marble $1/10,$2/10,$3,$4,$5,$6,$7,$8,$9%,$10% 47207 endl a c endl done 47208 47209#@gui Maze : fx_maze, fx_maze 47210#@gui : Cell Size = int(24,1,256) 47211#@gui : Thickness = int(1,1,10) 47212#@gui : Masking = choice("None","Render on Dark Areas","Render on White Areas") 47213#@gui : Preserve Image Dimension = bool(1) 47214#@gui : Maze Type = choice("Dark Walls","White Walls") 47215#@gui : sep = separator() 47216#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/02/09</i>.</small>") 47217fx_maze : 47218 repeat $! l[$>] 47219 w={w} h={h} 47220 r. {100/$1}%,{100/$1}%,1,100%,2 47221 if $3==0 f. 1 47222 elif $3==1 negate. 47223 fi 47224 maze_mask. $1 dilate. $2 *. 255 47225 if !$5 negate. fi 47226 if $4 r. $w,$h,100%,100% fi 47227 endl done 47228 47229#@gui Mineral Mosaic : fx_mineral_mosaic,fx_mineral_mosaic(0) 47230#@gui : Density = float(1,0,3) 47231#@gui : Area = float(2,0,32) 47232#@gui : Smoothness = float(1,0,10) 47233#@gui : Shade Strength = float(100,0,255) 47234#@gui : Shade Angle = float(0,0,360) 47235#@gui : sep = separator() 47236#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/01/02</i>.</small>") 47237fx_mineral_mosaic : 47238 repeat $! l[$>] to_rgb 47239 +b $3 segment_watershed. $1 +norm. 47240 area. 0 +<=. {$2^2} inpaint.. . rm. label. 47241 +f[0] 'if(c==0,x,y)' rv[-2,-1] +blend[-2,-1] shapeaverage,1,1 47242 -[-3,-1] rm[0,-2] channels. 0,1 47243 alpha={$5*pi/180} sh. 0 *. {cos($alpha)} rm. sh. 1 *. {sin($alpha)} rm. compose_channels. + 47244 normalize_local. 1000 n. -$4,$4 47245 + c 0,255 47246 endl done 47247 47248#@gui Mosaic : fx_mosaic, fx_mosaic_preview(0) 47249#@gui : Density (%) = float(50,0,100) 47250#@gui : sep = separator() 47251#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 47252#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 47253#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 47254#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 47255#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 47256#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 47257#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 47258#@gui : sep = separator() 47259#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47260#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47261#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47262#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47263#@gui : sep = separator() 47264#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/19/07</i>.</small>") 47265fx_mosaic : 47266 ac "repeat $! l[$>] split_opacity mosaic[0] $1 a c endl done",$2 47267 47268fx_mosaic_preview : 47269 gui_split_preview "fx_mosaic $*",${-3--1} 47270 47271#@gui Op Art : fx_shapes,fx_shapes_preview(0) 47272#@gui : Shape = choice{1,"Custom Layers","Circles","Squares","Diamonds","Triangles","Horizontal Stripes", 47273#@gui : "Vertical Stripes","Balls","Hearts","Stars","Arrows","Truchet","Circles (Outline)","Squares (Outline)", 47274#@gui : "Diamonds (Outline)","Triangles (Outline)","Hearts (Outline)","Stars (Outline)","Arrows (Outline)"} 47275#@gui : Number of Scales = int(16,2,24) 47276#@gui : Resolution = float(10,1,50) 47277#@gui : Zoom Factor = _int(2,1,8) 47278#@gui : Minimal Size = float(5,0,150) 47279#@gui : Maximal Size = float(90,0,150) 47280#@gui : Stencil Type = choice(0,"Black & White","RGB","Color") 47281#@gui : Allow Angle = choice("0 deg.","90 deg.","180 deg.") 47282#@gui : Negative = bool(1) 47283#@gui : Antialiasing = bool(1) 47284#@gui : sep = separator() 47285#@gui : note = note{"<small><b>Note:</b> 47286#@gui : If you set the parameter <i>Shape</i> to <i>Custom layers</i>, the different shapes used to map 47287#@gui : the pixel intensities will be defined as 47288#@gui : the <i>Number of scales</i> top layers of your image. Don't forget to set also <i>Input layers</i> to 47289#@gui : <i>All</i> to be sure 47290#@gui : these layers are passed to the filter. 47291#@gui : </small>"} 47292#@gui : sep = separator() 47293#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47294#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47295#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47296#@gui : sep = separator() 47297#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/16/12</i>.</small>") 47298fx_shapes : 47299 if $1 # Pre-defined shapes. 47300 remove_opacity repeat $! l[$>] 47301 if !$7 _fx_shapes $* * 255 47302 elif $7==1 split_opacity to_rgb[0] s[0] c repeat 3 _fx_shapes[$>] $* done *[0-2] 255 a[0-2] c a c 47303 else +_fx_shapes $* r[0] $3%,$3% r[0] [1],[1] * 47304 fi 47305 endl done 47306 else # Custom shapes. 47307 if $!<=$2 47308 error[] "Command '$0': Some layers are missing in 'Custom layers' mode ("{$2+1}" expected at least, "\ 47309 $!" provided)." fi 47310 to_colormode[0-{$2-1}] ${max_s[0-{$2-1}]} remove_opacity[$2--1] 47311 repeat $!-$2 l[0-{$2-1},{$2+$>}] 47312 norm. w={w} h={h} r. $3%,$3%,1,1,2 47313 s={$4*max(round($w/w),round($h/h))} 47314 r0={$s*$5%} r1={$s*$6%} 47315 repeat $2 r={round($r0+$>*($r1-$r0)/($2-1))} if $r +r[$>] $r,$r,1,100%,3 else 1,1 fi done 47316 r[-$2--1] $s,$s,1,100%,0,0,0.5,0.5 47317 map_sprites[$2--1] $2,$8 47318 endl done rm[0-{$2-1}] 47319 fi 47320 47321fx_shapes_preview : 47322 if $1 repeat $! l[$>] 47323 w={w} h={h} 47324 gui_split_preview "fx_shapes ${1-3},1,${5--2}",$-1 47325 r $w,$h,1,100%,0,0,0.5,0.5 47326 endl done 47327 else 47328 if $!>$2 repeat $!-$2 l[0-{$2-1},{$2+$>}] 47329 w={w} h={h} 47330 +fx_shapes ${1-3},1,${5--2} rm.. 47331 r. $w,$h,1,100%,0,0,0.5,0.5 47332 endl done rm[0-{$2-1}] 47333 else gui_warning_preview "Missing input layers!" 47334 fi 47335 fi 47336 47337_fx_shapes : 47338 norm w={w} h={h} r $3%,$3%,1,1,2 47339 s={(1+$10)*$4*max(round($w/w),round($h/h))} 47340 r0={$s*$5%} r1={$s*$6%} 47341 repeat $2 r={round($r0+$>*($r1-$r0)/($2-1))} if $r _fx_shapes{$1-1}[] $r,$s else 1,1 fi done 47342 r[-$2--1] $s,$s,1,1,0,0,0.5,0.5 47343 if $9 rv[-$2--1] *[-$2--1] -1 +[-$2--1] 1 fi 47344 map_sprites $2,$8 47345 if $10 r 50%,50%,1,1,2 fi 47346 47347_fx_shapes0 : 47348 shape_circle $1 47349 47350_fx_shapes1 : 47351 $1,$1,1,1,1 47352 47353_fx_shapes2 : 47354 $1,$1,1,1 = 1,50%,50% distance 1,1 < {$1/2} 47355 47356_fx_shapes3 : 47357 $2,$2,1,1,'x+y<=2*$1-1' 47358 47359_fx_shapes4 : 47360 $2,$1,1,1,1 47361 47362_fx_shapes5 : 47363 $1,$2,1,1,1 47364 47365_fx_shapes6 : 47366 ball $1,200 n 0,1 47367 47368_fx_shapes7 : 47369 shape_heart 65 r $1,$1,1,1,2 >= 50% 47370 47371_fx_shapes8 : 47372 shape_star $1 47373 47374_fx_shapes9 : 47375 arrow3d 0,0,0,1,0,0,15%,40%,30% col3d 1 *3d $1 c3d 47376 $2,$2 j3d. ..,50%,50%,0,1,2,0,0 47377 rm.. +mirror y max 47378 47379_fx_shapes10 : 47380 S={$2+1-($2%2)} 47381 $S,$S,1,1,"X=x/(w-1);Y=y/(h-1);r=abs(0.5-sqrt(X^2+Y^2));a=atan2(y,x);r<0.1-0.17*(0.5-$1/$2)*sin(2*a)" 47382 +mirror xy max 47383 47384_fx_shapes11 : 47385 _fx_shapes0 $* expand_xy 1,0 +erode 3 - 47386 47387_fx_shapes12 : 47388 _fx_shapes1 $* expand_xy 1,0 +erode 3 - 47389 47390_fx_shapes13 : 47391 _fx_shapes2 $* expand_xy 1,0 +erode 3 - 47392 47393_fx_shapes14 : 47394 _fx_shapes3 $* expand_xy 1,0 +erode 3 - 47395 47396_fx_shapes15 : 47397 _fx_shapes7 $* expand_xy 1,0 +erode 3 - 47398 47399_fx_shapes16 : 47400 _fx_shapes8 $* expand_xy 1,0 +erode 3 - 47401 47402_fx_shapes17 : 47403 _fx_shapes9 $* expand_xy 1,0 +erode 3 - 47404 47405#@gui Pack Sprites : fx_pack_sprites, gui_no_preview 47406#@gui : Number of Scales = int(5,1,16) 47407#@gui : Minimal Scale (%) = float(25,1,100) 47408#@gui : Allow Angle = choice(3,"0 deg.","180 deg.","90 deg.","Any") 47409#@gui : Spacing = int(1,-16,16) 47410#@gui : Precision = int(7,1,32) 47411#@gui : sep = separator() 47412#@gui : Masking = choice("No Masking","Mask as Bottom Layer") 47413#@gui : Width = int(512,32,2048) 47414#@gui : Height = int(512,32,2048) 47415#@gui : note = note("<small><b>Notes:</b>\n - Parameters <i>Width</i> and <i>Height</i> are considered only when 47416#@gui : <i>No masking</i> mode is selected.\n 47417#@gui : - Set different sprites on different layers to pack multiple sprites at the same time.</small>") 47418#@gui : url = link("Click here for a video tutorial","http://www.youtube.com/watch?v=bpg7CGH7vCM") 47419#@gui : sep = separator() 47420#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/24/06</i>.</small>") 47421fx_pack_sprites : 47422 if $6 # With mask. 47423 if $!<2 error[] "Command '$0': Masking requires at least two input layers ! 47424 (please check that 'Input Layers' is correctly set)." fi 47425 repeat $!-1 l[$>] to_rgba split_opacity +!=[1] 0 *[0] . a c autocrop 0 endl done 47426 remove_empty[0--2] +channels. 100% channels. -4,0 mv. 0 47427 pack_sprites[0--2] ${1-5} 47428 else # No masking 47429 repeat $! l[$>] to_rgba split_opacity +!=[1] 0 *[0] . a c autocrop 0 endl done 47430 remove_empty i[0] $7,$8,1,5 pack_sprites ${1-5} 47431 fi 47432 channels[0] 0,{0,s-2} 47433 47434#@gui Paper Texture : fx_paper, fx_paper_preview(0) 47435#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 47436#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 47437#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 47438#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 47439#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 47440#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 47441#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 47442#@gui : sep = separator() 47443#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47444#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47445#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47446#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47447#@gui : sep = separator() 47448#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47449fx_paper : 47450 ac "texturize_paper",$1 47451 47452fx_paper_preview : 47453 gui_split_preview "fx_paper $*",${-3--1} 47454 47455#@gui Plaid : fx_plaid_texture,fx_plaid_texture(1) 47456#@gui : Line = float(50,0,100) 47457#@gui : Number of Angles = int(2,1,8) 47458#@gui : Starting Angle = float(0,0,360) 47459#@gui : Angle Range = float(90,0,360) 47460#@gui : Smoothness = float(1,0,5) 47461#@gui : Sharpen = float(300,0,1000) 47462#@gui : sep = separator() 47463#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/16/05</i>.</small>") 47464fx_plaid_texture : 47465 repeat $! l[$>] 47466 w={w} h={h} s={s} 47467 rows $1% 47468 b $5% sharpen $6 47469 r $w,$h,1,$s,2 47470 +rotate[0] $3,1,2,50%,50% 47471 repeat $2-1 +rotate[0] {$3+$4*($>+1)/($2-1)},1,2,50%,50% +[-2,-1] done rm[0] 47472 / $2 47473 endl done 47474 47475#@gui Polka Dots : fx_polka_dots, fx_polka_dots(1) 47476#@gui : Size = float(80,0,100) 47477#@gui : Density = float(20,0.1,100) 47478#@gui : First Offset = float(50,0,100) 47479#@gui : Second Offset = float(50,0,100) 47480#@gui : Angle = float(0,0,180) 47481#@gui : Aliasing = float(0.5,0.1,1) 47482#@gui : Shading = float(0.1,0.1,1) 47483#@gui : Opacity = float(1,0,1) 47484#@gui : Color = color(255,0,0,255) 47485#@gui : sep = separator() 47486#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47487fx_polka_dots : 47488 to_rgba polka_dots {$1*$2/100},${2--1} 47489 47490#@gui Random Color Ellipses : fx_color_ellipses, fx_color_ellipses(1) 47491#@gui : Density = int(400,0,3000) 47492#@gui : Radius = float(8,0,30) 47493#@gui : Opacity = float(0.1,0.01,0.5) 47494#@gui : sep = separator() 47495#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47496fx_color_ellipses : 47497 color_ellipses $1,$2,$3 47498 47499#@gui Random Pattern : fx_random_pattern, fx_random_pattern_preview(1) 47500#@gui : Size = _int(1024,16,8192) 47501#@gui : Min Detail Level = float(2,0,20) 47502#@gui : Seed = float(4038,0,100000) 47503#@gui : Randomize Seed = button() 47504#@gui : sep = separator() 47505#@gui : Brightness (%) = float(0,-100,100) 47506#@gui : Contrast (%) = float(0,-100,100) 47507#@gui : Gamma (%) = float(0,-100,100) 47508#@gui : Hue (%) = float(0,-100,100) 47509#@gui : Saturation (%) = float(0,-100,100) 47510#@gui : sep = separator() 47511#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/10/08</i>.</small>") 47512_fx_random_pattern : 47513 if $4 srand _seed={_round(u(100000))} else _seed=$3 fi 47514 srand $_seed 47515 random_pattern $1,$1,$2 47516 adjust_colors. ${5-9} 47517 mv. 0 47518 47519fx_random_pattern : 47520 if 0$_output_mode rm fi 47521 _fx_random_pattern $* 47522 47523fx_random_pattern_preview : 47524 _fx_random_pattern {max($_preview_width,$_preview_height)},${2--1} 47525 k[0] rr2d $_preview_width,$_preview_height,2,2 47526 to "Seed: \#"$_seed,5,5,5%,2 47527 u "{$1}{$2}{"{$4?$_seed:$3}"}{0}{$5}{$6}{$7}{$8}{$9}" 47528 47529#@gui Resynthetize Texture [FFT] : syntexturize, fx_syntexturize_preview(1) 47530#@gui : Width = _int(1024,32,8192) 47531#@gui : Height = _int(1024,32,8192) 47532#@gui : Equalize Light = float(0,0,100) 47533#@gui : sep = separator() 47534#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47535#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47536#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47537#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47538#@gui : sep = separator() 47539#@gui : note = note{"<small><b>Note:</b> This filter tries to re-synthetize a <b>micro</b>-texture 47540#@gui : (given as the input image) onto an output (seamless) image with an arbitrary size. 47541#@gui : It uses a phase randomization technique, as described in:</small>"} 47542#@gui : url = link("Micro-Texture Synthesis by Phase Randomization","http://www.ipol.im/pub/art/2011/ggm_rpn/") 47543#@gui : note = note("<small>This filter is based on the work of <i>Bruno Galerne</i>, <i>Yann Gousseau</i> and 47544#@gui : <i>Jean-Michel Morel</i>.</small>") 47545#@gui : sep = separator() 47546#@gui : url = link("Click here for a detailed description of this filter.",\ 47547# "http://gimpchat.com/viewtopic.php?f=28&t=10141") 47548#@gui : sep = separator() 47549#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Jérome Boulanger</i>. 47550#@gui : Latest Update: <i>2014/09/04</i>.</small>") 47551fx_syntexturize : 47552 repeat $! l[$>] 47553 if $3 +b {20.5-$3/50}% -[0] [1] fc. ${average_colors.} + c 0,255 fi 47554 syntexturize $1,$2 47555 endl done 47556 47557fx_syntexturize_preview : 47558 gui_split_preview "fx_syntexturize 100%,100%,$3",${-3--1} 47559 47560#@gui Resynthetize Texture [Patch-Based] : syntexturize_matchpatch, fx_syntexturize_matchpatch_preview(1) 47561#@gui : Width = _int(512,32,8192) 47562#@gui : Height = _int(512,32,8192) 47563#@gui : Number of Scales = int(0,0,16) 47564#@gui : Patch Size = int(7,1,32) 47565#@gui : Blending Size = int(5,1,24) 47566#@gui : Precision = float(1,0,5) 47567#@gui : Equalize Light = float(0,0,100) 47568#@gui : sep = separator() 47569#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47570#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47571#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47572#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47573#@gui : sep = separator() 47574#@gui : note = note{"<small><b>Note:</b> This filter tries to re-synthetize an input texture image onto a 47575#@gui : bigger output image (with an arbitrary size). 47576#@gui : Beware, this filter is quite slow to compute!</small>"} 47577#@gui : sep = separator() 47578#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/22/10</i>.</small>") 47579_fx_syntexturize_matchpatch_preview : 47580 repeat $! l[$>] 47581 if $7 +b {20.5-$7/50}% -[0] [1] fc. ${average_colors.} + c 0,255 fi 47582 w={w} h={h} 47583 syntexturize_matchpatch 100%,100%,${3--1} 47584 to_rgba r $w,$h,1,4,0,0,0.5,0.5 47585 endl done 47586 47587fx_syntexturize_matchpatch_preview : 47588 gui_split_preview "_fx_syntexturize_matchpatch_preview ${1--2}",${-3--1} 47589 47590#@gui Rorschach : fx_rorschach, fx_rorschach 47591#@gui : Scale = float(3,0,10) 47592#@gui : Mirror = choice(1,"None","X-Axis","Y-Axis","XY-Axes") 47593#@gui : Stencil Type = choice(2,"Black & White","RGB","Color") 47594#@gui : sep = separator() 47595#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/12/03</i>.</small>") 47596fx_rorschach : 47597 repeat $! remove_opacity l[$>] 47598 if $3==0 norm rorschach $1%,$2 * 255 47599 elif $3==1 to_rgb rorschach $1%,$2 * 255 47600 else +norm rorschach. $1%,$2 blend shapeaverage0 47601 fi 47602 endl done 47603 47604#@gui Satin : fx_satin, fx_satin(1) 47605#@gui : Iterations = int(20,4,128) 47606#@gui : Smoothness (%) = float(1,0,5) 47607#@gui : Seed = int(0,0,65535) 47608#@gui : sep = separator() 47609#@gui : Dark Color = color(0,0,0,255) 47610#@gui : Light Color = color(255,255,255,255) 47611#@gui : Stretch Contrast = bool(0) 47612#@gui : sep = separator() 47613#@gui : Brightness (%) = float(0,-100,100) 47614#@gui : Contrast (%) = float(0,-100,100) 47615#@gui : Gamma (%) = float(-50,-100,100) 47616#@gui : Hue (%) = float(0,-100,100) 47617#@gui : Saturation (%) = float(0,-100,100) 47618#@gui : sep = separator() 47619#@gui : note = note{"This filter has been inspired by 47620#@gui : <a href="https://fence-post.deviantart.com/art/Satin-Texture-in-GIMP-46937633">this tutorial</a> 47621#@gui : from DeviantArt user <i>fence-post</i>."} 47622#@gui : sep = separator() 47623#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/11/27</i>.</small>") 47624fx_satin : 47625 ($4,$8^$5,$9^$6,$10^$7,$11) srgb2rgb. r. 256,1,1,4,3 rgb2srgb. 47626 repeat $!-1 l[$>] 47627 srand $3 channels 0 f 0 47628 repeat $1 47629 100%,100%,1,1,"begin( 47630 A = u([0,0],[w,h]-1); 47631 B = u([0,0],[w,h]-1); 47632 N = [0,-1,1,0]*(B - A); 47633 D = A + N; 47634 C = B + N; 47635 abc = solve([A,1,B,1,C,1,D,1],[0,255,255,0]); 47636 ); 47637 dot(abc,[x,y,1])" 47638 c. 0,255 -- abs 47639 done 47640 b $2% gradient_norm negate n 0,255 47641 if $12 normalize_local , fi 47642 pass. 1 map.. . rm. 47643 sh. 0,2 adjust_colors. ${13-17} rm. 47644 endl done 47645 rm. 47646 47647#@gui Seamless Turbulence : fx_seamless_turbulence, fx_seamless_turbulence(0) 47648#@gui : Amplitude = float(15,0,30) 47649#@gui : Smoothness = float(20,0,40) 47650#@gui : Orientation = float(0,0,180) 47651#@gui : Deviation = float(1,0,1) 47652#@gui : Contrast = float(3,0,4) 47653#@gui : Color Rendering = bool(0) 47654#@gui : sep = separator() 47655#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/02/04</i>.</small>") 47656fx_seamless_turbulence : 47657 repeat $! l[$>] 47658 wh={w},{h} rm 47659 $wh,1,{if($6,3,1)} rand. 0,255 47660 $wh rand. {$3*pi/180-$4*10*pi},{$3*pi/180+$4*10*pi} +sin. cos.. a[-2,-1] c 47661 r[-2,-1] 130%,130%,1,100%,0,2,0.5,0.5 b. $2 orientation. 47662 vector2tensor. 47663 smooth.. .,$1,0.5,20 rm. 47664 r. $wh,1,100%,0,0,0.5,0.5 47665 if $5!=1 ia={ia} - $ia * $5 + $ia fi 47666 endl done 47667 c 0,255 n 0,255 47668 47669#@gui Shock Waves : fx_shockwaves, fx_shockwaves_preview 47670#@gui : Amplitude = float(10,0,100) 47671#@gui : Low Frequency = float(10,0,100) 47672#@gui : Frequency Range = float(20,0,100) 47673#@gui : sep = separator() 47674#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 47675#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 47676#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 47677#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 47678#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 47679#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 47680#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 47681#@gui : sep = separator() 47682#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47683#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47684#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47685#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47686#@gui : sep = separator() 47687#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/01/12</i>.</small>") 47688_fx_shockwaves : 47689 dct 47690 100%,100%,1,1,1 circle. 0,0,{$2+$3}%,1,{$1+1} circle. 0,0,$2%,1,1 47691 * idct c 0,255 47692 47693fx_shockwaves : 47694 ac "_fx_shockwaves ${1-3}",$4 47695 47696fx_shockwaves_preview : 47697 gui_split_preview "fx_shockwaves $*",${-3--1} 47698 47699#@gui Sponge : fx_sponge, fx_sponge_preview(0) 47700#@gui : Size = int(13,3,21) 47701#@gui : sep = separator() 47702#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 47703#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 47704#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 47705#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 47706#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 47707#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 47708#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 47709#@gui : sep = separator() 47710#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47711#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47712#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47713#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47714#@gui : sep = separator() 47715#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47716fx_sponge : 47717 ac "sponge $1",$2 47718 47719fx_sponge_preview : 47720 gui_split_preview "fx_sponge $*",${-3--1} 47721 47722#@gui Stained Glass : fx_stained_glass, fx_stained_glass_preview(0) 47723#@gui : Edges = float(20,0,100) 47724#@gui : Shading = float(0.1,0,0.5) 47725#@gui : Thin Separators = bool(1) 47726#@gui : sep = separator() 47727#@gui : Equalize = bool(1) 47728#@gui : Colors = float(1,0,3) 47729#@gui : Brightness (%) = float(0,-100,100) 47730#@gui : Contrast (%) = float(0,-100,100) 47731#@gui : Gamma (%) = float(0,-100,100) 47732#@gui : sep = separator() 47733#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47734#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47735#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47736#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47737#@gui : sep = separator() 47738#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/03</i>.</small>") 47739fx_stained_glass : 47740 repeat $! l[$>] split_opacity l[0] to_rgb 47741 stained_glass $1,$2,$3 47742 n 0,255 47743 if $4 equalize. fi 47744 rgb2lab. sh. 1,2 *. $5 rm. lab2rgb. 47745 adjust_colors. ${6-8} 47746 endl a c endl done 47747 47748fx_stained_glass_preview : 47749 gui_split_preview "fx_stained_glass $*",${-3--1} 47750 47751#@gui Stars : fx_stars, fx_stars(0) 47752#@gui : Density = float(10,0,200) 47753#@gui : Depth = float(0,0,5) 47754#@gui : Size = int(32,8,128) 47755#@gui : Branches = int(5,3,16) 47756#@gui : Thickness = float(0.38,0.1,1) 47757#@gui : Smoothness = float(0,0,10) 47758#@gui : Color = color(255,255,100,200) 47759#@gui : sep = separator() 47760#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/01/10</i>.</small>") 47761fx_stars : 47762 repeat $! l[$>] split_opacity rv 47763 stars $1%,$2,$3,$4,$5,$6%,${7-9},{$10/255} 47764 rv a c endl done 47765 47766#@gui Stencil : fx_stencil, fx_stencil_preview(0) 47767#@gui : Radius = float(3,0,10) 47768#@gui : Smoothness = float(0,0,30) 47769#@gui : Iterations = int(8,1,100) 47770#@gui : Aliasing = float(0,0,5) 47771#@gui : Stencil Type = choice(2,"Black & White","RGB","Color") 47772#@gui : Transparency = bool(0) 47773#@gui : sep = separator() 47774#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47775#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47776#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47777#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47778#@gui : sep = separator() 47779#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47780fx_stencil : 47781 if $5==0 norm stencil $1,$2,$3 47782 elif $5==1 stencil $1,$2,$3 47783 else repeat $! 47784 +norm. stencil. $1,$2,$3 >=. 50% blend[-2,-1] shapeaverage0 47785 mv. 0 done fi 47786 if $6 to_rgba replace_color 0,0,0,0,0,255,0,0,0,0 fi 47787 if $4 smooth {30*$4},0,1,1 fi 47788 47789fx_stencil_preview : 47790 gui_split_preview "fx_stencil $*",${-3--1} 47791 47792#@gui Tetris : fx_tetris, fx_tetris(0) 47793#@gui : Scale = int(10,1,20) 47794#@gui : sep = separator() 47795#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47796fx_tetris : 47797 tetris $1 47798 47799#@gui Triangular Pattern : fx_triangular_pattern,fx_triangular_pattern(1)+ 47800#@gui : Random Seed = int(43,0,65535) 47801#@gui : sep = separator() 47802#@gui : Depth = int(7,0,16) 47803#@gui : Split Type-1 = int(4,0,20) 47804#@gui : Split Type-2 = int(4,0,20) 47805#@gui : Split Type-3 = int(4,0,20) 47806#@gui : Split Type-4 = int(0,0,20) 47807#@gui : Split Type-5 = int(0,0,20) 47808#@gui : Holes Probability (Type-5) (%) = float(0,0,100) 47809#@gui : sep = separator() 47810#@gui : Filling opacity (%) = float(100,0,100) 47811#@gui : Outline Color = color(0,0,0,160) 47812#@gui : Anti-aliasing = choice(1,"None","x1.5","x2","x3","x4") 47813#@gui : sep = separator() 47814#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/09/29</i>.</small>") 47815fx_triangular_pattern : 47816 if !$! 1024,1024,1,3 fi 47817 W,H={0,[w,h]} f={arg0($14,1,1.5,2,3,4)*100} r[0] $f%,$f%,1,100% 47818 1,1,1,6 47819 eval " 47820 47821 # Init parameters for random generator. 47822 srand($1); 47823 const pn1 = $3; 47824 const pn2 = $4 + pn1; 47825 const pn3 = $5 + pn2; 47826 const pn4 = $6 + pn3; 47827 const pn5 = $7 + pn4; 47828 47829 # Create set of subdivided triangles. 47830 C = [ w#0,h#0 ]/2; 47831 da_push([ C,0,h#0-1,0,0 ], 47832 [ C,w#0-1,0,0,0 ], 47833 [ C,w#0-1,0,w#0-1,h#0-1 ], 47834 [ C,0,h#0-1,w#0-1,h#0-1 ]); 47835 repeat($2, 47836 n = int(u(pn5))%pn5; 47837 n = n<pn1?0:n<pn2?1:n<pn3?2:n<pn4?3:4; 47838 is_hole = u<=$8%; 47839 repeat(da_size(),k, 47840 F = I[k]; P0 = F[0,2]; P1 = F[2,2]; P2 = F[4,2]; 47841 n==0?( 47842 P = lerp(P1,P2,0.5); 47843 da_push([ P0,P,P1 ]); 47844 I[k] = [ P0,P,P2 ]; 47845 ):n==1?( 47846 P = lerp(P0,P2,0.5); 47847 da_push([ P1,P,P0 ]); 47848 I[k] = [ P1,P,P2 ]; 47849 ):n==2?( 47850 P = lerp(P0,P1,0.5); 47851 da_push([ P2,P,P0 ]); 47852 I[k] = [ P2,P,P1 ]; 47853 ):n==3?( 47854 P = (P0 + P1 + P2)/3; 47855 da_push([ P,P0,P1 ]); 47856 da_push([ P,P1,P2 ]); 47857 I[k] = [ P,P2,P0 ]; 47858 ):( 47859 P01 = lerp(P0,P1,0.5); P02 = lerp(P0,P2,0.5); P12 = lerp(P1,P2,0.5); 47860 da_push([ P0,P01,P02 ]); 47861 da_push([ P1,P12,P01 ]); 47862 is_hole?( # Hole 47863 I[k] = [ P2,P02,P12 ]; 47864 ):( # No hole 47865 da_push([ P2,P02,P12 ]); 47866 I[k] = [ P01,P02,P12 ]; 47867 ); 47868 ); 47869 ); 47870 ); 47871 47872 # Draw triangles. 47873 repeat(da_size(),k, 47874 F = I[k]; 47875 polygon(#0,3,F,$9%,u([255,255,255])); 47876 polygon(#0,-3,F,$13%/3,0xFFFFFFFF,$10,$11,$12,255); 47877 )" 47878 rm. 47879 r[0] $W,$H,1,100%,2 47880 47881#@gui Truchet : fx_truchet, fx_truchet(0) 47882#@gui : Scale = int(32,1,256) 47883#@gui : Radius = int(5,1,64) 47884#@gui : Smoothness = float(1,0,10) 47885#@gui : Type = choice(1,"Straight","Curved") 47886#@gui : Color = choice("White on Black","Black on White","White on Transparent","Black on Transparent", 47887#@gui : "Transparent on White","Transparent on Black","Random") 47888#@gui : sep = separator() 47889#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/26/10</i>.</small>") 47890fx_truchet : 47891 repeat $! l[$>] 47892 100%,100% truchet $1,$2,$4 rm.. 47893 if $5==1 * -1 47894 elif $5==2 i[0] 100%,100%,1,1,1 47895 elif $5==3 i[0] 100%,100% 47896 elif $5==4 * -1 i[0] 100%,100% 47897 elif $5==5 * -1 i[0] 100%,100%,1,1,-1 47898 elif $5==6 label 0,1 {iM+1},1,1,3 rand. 0,255 map.. . rm. 47899 fi 47900 a c b $3 n 0,255 47901 endl done 47902 47903#@gui Voronoi : fx_voronoi, fx_voronoi_preview(0) 47904#@gui : Threshold = float(160,0,255) 47905#@gui : Threshold on = choice(1,"Pixel values","Gradient values") 47906#@gui : Smoothness = float(0.5,0,10) 47907#@gui : Subsampling (%) = float(50,0,100) 47908#@gui : sep = separator() 47909#@gui : Flat color = choice(3,"Black","White","Transparent","Image") 47910#@gui : Outline thickness = int(1,0,8) 47911#@gui : Outline color = color(0,0,0,100) 47912#@gui : Centers radius = int(2,0,10) 47913#@gui : Centers color = color(255,255,255,40) 47914#@gui : sep = separator() 47915#@gui : Anti-aliasing = choice{1,"x1 (none)","x1.5","x2","x2.5"} 47916#@gui : sep = separator() 47917#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/04/30</i>.</small>") 47918fx_voronoi : 47919 repeat $! l[$>] wh={[w,h]} 47920 f={arg(1+$16,1,1.5,2,2.5)*100} r $f%,$f%,1,100%,3 47921 47922 if $2 +gradient_norm t={(255-$1)/4} else +s c med[^0] t={255-$1} fi 47923 if $3 mM={[im,iM]} b. $3 n. $mM fi 47924 >. $t 47925 f. "u<($4%)^4?i:0" 47926 label_fg. 0,1 voronoi. 47927 47928 # Flat. 47929 if $5<3 47930 1,1,1,4,"$5==0?[0,0,0,255]:$5==1?[255,255,255,255]:$5==2?[128,128,128,0]" 47931 r. [0],[0],1,4 rv[0,-1] rm. 47932 else 47933 blend[0] .,shapeaverage 47934 fi 47935 47936 # Outline. 47937 if $6" && "$10 47938 +f. "const boundary=1; i!=j(1) || i!=j(0,1)" 47939 dilate. $6 47940 1,1,1,4,"[${7-9},255]" r. [0],[0],1,4 47941 j[0] .,0,0,0,0,{$10/255},.. rm[-2,-1] 47942 fi 47943 47944 # Centers. 47945 if $11" && "$15 47946 1,{iM+1},1,3 eval.. "I[#-1,i]+=[x,y,1]" s. c,-2 /[-2,-1] rm.. 47947 eval. "const r = ($11-1)*arg(1+$16,1,1.5,2,2.5); ellipse(#0,i0,i1,r,r,0,$15/255,[${12-14},255])" 47948 fi 47949 rm. 47950 r $wh,1,100%,2 47951 47952 endl done 47953 47954fx_voronoi_preview : 47955 fx_voronoi ${1-15},{min(1,$16)} 47956 47957#@gui Weave : weave, weave(1) 47958#@gui : Density = int(6,1,32) 47959#@gui : Thickness = float(65,0,100) 47960#@gui : Shadow = float(0,0,100) 47961#@gui : Shading = float(0.5,0,3) 47962#@gui : Fibers Amplitude = float(0,0,255) 47963#@gui : Fibers Smoothness = float(0,0,10) 47964#@gui : Angle = choice("0 deg.","22.5 deg.","45 deg.","67.5 deg.") 47965#@gui : X-Curvature = float(0,-1,1) 47966#@gui : Y-Curvature = float(0,-1,1) 47967#@gui : sep = separator() 47968#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/18/01</i>.</small>") 47969 47970#@gui Whirls : fx_whirls, fx_whirls_preview(0) 47971#@gui : Density = int(7,3,20) 47972#@gui : Smoothness = float(2,0,10) 47973#@gui : Darkness = float(0.2,0,1) 47974#@gui : Lightness = float(1.8,1,3) 47975#@gui : sep = separator() 47976#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 47977#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 47978#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 47979#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 47980#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 47981#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 47982#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 47983#@gui : sep = separator() 47984#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 47985#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 47986#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 47987#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 47988#@gui : sep = separator() 47989#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47990fx_whirls : 47991 ac "whirls $1,$2,$3,$4",$5 47992 47993fx_whirls_preview : 47994 gui_split_preview "fx_whirls ${1-5}",${-3--1} 47995 47996 47997#@gui ____<b>Repair</b> 47998#----------------------- 47999 48000#@gui Bayer Reconstruction : bayer2rgb, gui_no_preview 48001#@gui : G/M Smoothness = _float(6,0,20) 48002#@gui : R/B Smoothness (Principal) = _float(6,0,20) 48003#@gui : R/B Smoothness (Secondary) = _float(4,0,20) 48004#@gui : sep = separator() 48005#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48006 48007#@gui Deinterlace : deinterlace, fx_deinterlace_preview(0) 48008#@gui : Algorithm = choice("Standard","Motion-Compensated") 48009#@gui : sep = separator() 48010#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48011#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48012#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48013#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48014#@gui : sep = separator() 48015#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48016fx_deinterlace : 48017 deinterlace 0 skip ${^0} 48018 48019fx_deinterlace_preview : 48020 gui_split_preview "fx_deinterlace $*",${-3--1} 48021 48022#@gui Inpaint [Holes] : fx_inpaint_holes, fx_inpaint_holes(0) 48023#@gui : Maximal Area = float(4,1,512) 48024#@gui : Tolerance = float(20,0,255) 48025#@gui : Connectivity = choice(1,"Low","High") 48026#@gui : sep = separator() 48027#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/27/05</i>.</small>") 48028fx_inpaint_holes : 48029 inpaint_holes {$1^1.5},$2,$3 48030 48031#@gui Inpaint [Morphological] : fx_inpaint_morpho, fx_inpaint_morpho_preview(1) 48032#@gui : Mask Color = _color(255,0,0,255) 48033#@gui : Mask Dilation = _int(0,0,32) 48034#@gui : sep = separator() 48035#@gui : note = note{"<small><b>Note:</b> It is strongly suggested to apply this filter only on a selection 48036#@gui : around the region to inpaint, to save computation time!</small>"} 48037#@gui : sep = separator() 48038#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/25/11</i>.</small>") 48039fx_inpaint_morpho : 48040 repeat $! l[$>] 48041 R=$1 G=$2 B=$3 A=$4 48042 if !$A" && "(s==2" || "s==4) split_opacity +!=. 0 *[0,-1] a c R=0 G=0 B=0 fi # Purely transparent color. 48043 +round select_color. 0,{round([$R,$G,$B,$A])} 48044 if $5 dilate. {1+2*$5} fi 48045 inpaint_morpho.. [1] 48046 rm. 48047 endl done 48048 48049fx_inpaint_morpho_preview : 48050 fx_inpaint_morpho ${1-4},{1+$5} 48051 48052#@gui Inpaint [Multi-Scale] : fx_inpaint_matchpatch, fx_inpaint_matchpatch_preview(1) 48053#@gui : Number of Scales = int(0,0,16) 48054#@gui : note = note{"<small>(Set <i>Number of scales</i> to <i>0</i> for automatic scale detection)</small>"} 48055#@gui : Patch Size = int(9,1,64) 48056#@gui : Number of Iterations per Scale = int(10,1,100) 48057#@gui : Blend Size = int(5,0,32) 48058#@gui : Allow Outer Blending = bool(1) 48059#@gui : Mask Color = color(255,0,0,255) 48060#@gui : Mask Dilation = int(0,0,32) 48061#@gui : sep = separator() 48062#@gui : Preview Progression While Running = _bool(0) 48063#@gui : sep = separator() 48064#@gui : note = note{"<small><b>Note:</b> Preview and final result may strongly differ.</small>"} 48065#@gui : sep = separator() 48066#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/25/11</i>.</small>") 48067fx_inpaint_matchpatch : 48068 repeat $! l[$>] nm={n} 48069 R=$6 G=$7 B=$8 A=$9 48070 if !$A" && "(s==2" || "s==4) split_opacity +!=. 0 *[0,-1] a c R=0 G=0 B=0 fi # Purely transparent color. 48071 +round select_color. 0,{round([$R,$G,$B,$A])} 48072 if $10 dilate. {1+2*$10} fi 48073 if $11 48074 visu_size=${fitscreen[]" "{0,[w,h,1]},25%,50%} 48075 w1.. $visu_size,0,"[Preview] G'MIC: Inpaint [multi-scale]" 48076 fi 48077 srand 0 inpaint_matchpatch.. [1],${1-5} 48078 rm. nm $nm 48079 endl done 48080 48081fx_inpaint_matchpatch_preview : 48082 fx_inpaint_matchpatch ${1-9},{1+$10},0 48083 48084#@gui Inpaint [Patch-Based] : fx_inpaint_patch, fx_inpaint_patch_preview 48085#@gui : Patch Size = _int(7,1,64) 48086#@gui : Lookup Size = _float(16,1,32) 48087#@gui : Lookup Factor = _float(0.1,0,1) 48088#@gui : Blend Size = _float(1.2,0,5) 48089#@gui : Blend Threshold = _float(0,0,1) 48090#@gui : Blend Decay = _float(0.05,0,0.5) 48091#@gui : Blend Scales = _int(10,1,20) 48092#@gui : Allow Outer Blending = _bool(1) 48093#@gui : Mask Color = _color(255,0,0,255) 48094#@gui : Mask Dilation = _int(0,0,32) 48095#@gui : Process by Blocs of Size = _choice("100%","75%","50%","25%","10%","5%","2%","1%") 48096#@gui : sep = separator() 48097#@gui : note = note("<small>A quick tutorial on how to use this filter can be found here:</small>") 48098#@gui : url = link("G'MIC Inpainting tutorial on Patrick David's blog.", 48099#@gui : "https://patdavid.net/2014/02/getting-around-in-gimp-gmic-inpainting.html") 48100#@gui : sep = separator() 48101#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Maxime Daisy</i>. 48102#@gui : Latest Update: <i>2015/25/11</i>.</small>") 48103_fx_inpaint_patch : 48104 repeat $! l[$>] 48105 R=$9 G=$10 B=$11 A=$12 48106 if !$A" && "(s==2" || "s==4) split_opacity +!=. 0 *[0,-1] a c R=0 G=0 B=0 fi # Purely transparent color. 48107 +round select_color. 0,{round([$R,$G,$B,$A])} 48108 if $13 dilate. {1+2*$13} fi 48109 inpaint.. [1],$1,{$1*$2},$3,1,{$4*$1},${5-8} 48110 rm. 48111 endl done 48112 48113fx_inpaint_patch : 48114 repeat $! l[$>] 48115 if $14 48116 bs={max(16,min(w,h)*arg(1+$14,100,75,50,25,10,5,2,1)%)} 48117 at "_fx_inpaint_patch $*",$bs,$bs,1,25%,25%,0,2 48118 else _fx_inpaint_patch $* 48119 fi 48120 endl done 48121 48122fx_inpaint_patch_preview : 48123 fx_inpaint_patch ${1-12},{1+$13},100 48124 48125#@gui Inpaint [Transport-Diffusion] : fx_inpaint_pde, fx_inpaint_pde_preview(1) 48126#@gui : Smoothness (%) = float(75,0,100) 48127#@gui : Regularization = choice(1,"Isotropic","Delaunay-Guided","Edge-Oriented") 48128#@gui : Regularization Iterations = int(20,0,100) 48129#@gui : Mask Color = _color(255,0,0,255) 48130#@gui : Mask Dilation = _int(0,0,32) 48131#@gui : sep = separator() 48132#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/10/04</i>.</small>") 48133fx_inpaint_pde : 48134 repeat $! l[$>] 48135 R=$4 G=$5 B=$6 A=$7 48136 if !$A" && "(s==2" || "s==4) split_opacity +!=. 0 *[0,-1] a c R=0 G=0 B=0 fi # Purely transparent color. 48137 +select_color 0,$R,$G,$B,$A 48138 if $8 dilate. {1+2*$8} fi 48139 inpaint_pde.. [1],$1%,$2,$3 48140 rm. 48141 endl done c 0,255 48142 48143fx_inpaint_pde_preview : 48144 fx_inpaint_pde ${1-7},{1+$8} 48145 48146#@gui Red-Eye Attenuation : red_eye, red_eye 48147#@gui : Threshold = float(75,0,100) 48148#@gui : Smoothness = float(3.5,0,20) 48149#@gui : Factor = float(0.1,0,1) 48150#@gui : sep = separator() 48151#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48152 48153#@gui Remove Hot Pixels : fx_remove_hotpixels, fx_remove_hotpixels_preview(0) 48154#@gui : Mask Size = int(3,3,20) 48155#@gui : Threshold = float(10,0,200) 48156#@gui : sep = separator() 48157#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48158#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48159#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48160#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48161#@gui : sep = separator() 48162#@gui : note = note("<small>Author: <i>Jérome Boulanger</i>. Latest Update: <i>2010/29/12</i>.</small>") 48163fx_remove_hotpixels : 48164 remove_hotpixels $1,$2 48165 48166fx_remove_hotpixels_preview : 48167 gui_split_preview "fx_remove_hotpixels $*",${-3--1} 48168 48169#@gui Solidify : fx_solidify_td, fx_solidify_td_preview(1) 48170#@gui : Smoothness (%) = float(75,0,100) 48171#@gui : Regularization = choice(1,"Isotropic","Delaunay-Guided","Edge-Oriented") 48172#@gui : Regularization Iterations = int(20,0,100) 48173#@gui : Dilation / Erosion = int(0,-20,20) 48174#@gui : Colorspace = choice(1,"sRGB","Linear RGB") 48175#@gui : sep = separator() 48176#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48177#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48178#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48179#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48180#@gui : sep = separator() 48181#@gui : note = note{"<small><b>Note:</b> 48182#@gui : This filter reconstructs transparent regions of an image using a transport-diffusion algorithm. 48183#@gui : Useful only for images having an alpha-channel. 48184#@gui : </small>"} 48185#@gui : sep = separator() 48186#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/07/04</i>.</small>") 48187fx_solidify_td : 48188 repeat $! l[$>] 48189 to_rgba sh 0,{s-2} if $5 srgb2rgb. fi rm. 48190 if $4 48191 . sh. 100% if $4>0 erode. {1+2*$4} else dilate. {1-2*$4} fi rm. 48192 solidify. $1%,$2,$3 48193 rv blend alpha 48194 else 48195 solidify $1%,$2,$3 48196 fi 48197 if $5 rgb2srgb. fi 48198 endl done 48199 48200fx_solidify_td_preview : 48201 gui_split_preview "fx_solidify_td $*",${-3--1} 48202 48203#@gui Smooth [Anisotropic] : fx_smooth_anisotropic, fx_smooth_anisotropic_preview(0) 48204#@gui : Amplitude = float(60,0,1000) 48205#@gui : Sharpness = float(0.7,0,2) 48206#@gui : Anisotropy = float(0.3,0,1) 48207#@gui : Gradient Smoothness = float(0.6,0,10) 48208#@gui : Tensor Smoothness = float(1.1,0,10) 48209#@gui : Spatial Precision = float(0.8,0.1,2) 48210#@gui : Angular Precision = float(30,1,180) 48211#@gui : Value Precision = float(2,0.1,5) 48212#@gui : Interpolation = choice(0,"Nearest Neighbor","Linear","Runge-Kutta") 48213#@gui : Fast Approximation = bool(1) 48214#@gui : Iterations = int(1,1,10) 48215#@gui : sep = separator() 48216#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48217#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48218#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48219#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48220#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48221#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48222#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48223#@gui : sep = separator() 48224#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48225#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48226#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48227#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48228#@gui : sep = separator() 48229#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/08/27</i>.</small>") 48230fx_smooth_anisotropic : 48231 repeat $! l[$>] 48232 ac "repeat $11 smooth $1,$2,$3,$4,$5,$6,$7,$8,$9,$10 done",$12 48233 endl done c 0,255 48234 48235fx_smooth_anisotropic_preview : 48236 gui_split_preview "fx_smooth_anisotropic $*",${-3--1} 48237 48238#@gui Smooth [Antialias] : fx_smooth_antialias, fx_smooth_antialias_preview(0) 48239#@gui : Amplitude = float(5,0,100) 48240#@gui : Edge Threshold (%) = float(10,0,100) 48241#@gui : Smoothness = float(0.8,0,5) 48242#@gui : sep = separator() 48243#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48244#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48245#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48246#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48247#@gui : sep = separator() 48248#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/11/13</i>.</small>") 48249fx_smooth_antialias : 48250 repeat $! l[$>] 48251 +diffusiontensors 0,1,1,$3,$3 48252 +gradient_norm.. >=. $2% *[-2,-1] 48253 smooth.. .,{$1^1/3},0.5,120,2,1 rm. 48254 endl done 48255 48256fx_smooth_antialias_preview : 48257 gui_split_preview "fx_smooth_antialias $*",${-3--1} 48258 48259#@gui Smooth [Bilateral] : fx_smooth_bilateral, fx_smooth_bilateral_preview(0) 48260#@gui : Spatial Variance = float(10,0,100) 48261#@gui : Value Variance = float(7,0,100) 48262#@gui : Iterations = int(2,1,10) 48263#@gui : sep = separator() 48264#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48265#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48266#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48267#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48268#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48269#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48270#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48271#@gui : sep = separator() 48272#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48273#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48274#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48275#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48276#@gui : sep = separator() 48277#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 48278fx_smooth_bilateral : skip ${5=0},${6=0} 48279 ac "repeat $3 bilateral $1,$2 done",$4 48280 48281fx_smooth_bilateral_preview : 48282 gui_split_preview "fx_smooth_bilateral $*",${-3--1} 48283 48284#@gui Denoise : fx_denoise,fx_denoise_preview(0) 48285#@gui : Noise type = choice{"Soft","Heavy","Heavy (Faster)","Poisson + Gaussian"} 48286#@gui : Iterations = int(1,1,5) 48287#@gui : sep = separator() 48288#@gui : Update Neural Network = button() 48289#@gui : sep = separator() 48290#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48291#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48292#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48293#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48294#@gui : sep = separator() 48295#@gui : note = note{"<small> 48296#@gui : <b><span color="#EE5500">Note:</span></b> This filter uses a convolutional neural network (CNN) 48297#@gui : to denoise images. This filter does not take advantage of GPU computing, so expect it to be quite slow 48298#@gui : if you don't have many CPU cores available. 48299#@gui : </small>"} 48300#@gui : sep = separator() 48301#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/11/06</i>.</small>") 48302fx_denoise : 48303 if $3 delete ${-path_cache}gmic_denoise_cnn.gmz fi 48304 repeat $2 48305 denoise_cnn $1,64 48306 progress {round(($>+1)/$2*100)} 48307 done 48308 48309fx_denoise_preview : 48310 r2din 280,280,0,0,0.5,0.5 48311 gui_split_preview "fx_denoise $*",${-3--1} 48312 48313#@gui Smooth [Guided] : fx_smooth_guided, fx_smooth_guided_preview(0) 48314#@gui : Guide As = choice("Self","Top Layer","Bottom Layer") 48315#@gui : Radius = int(5,1,100) 48316#@gui : Smoothness = float(30,0,512) 48317#@gui : Iterations = int(1,1,10) 48318#@gui : sep = separator() 48319#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48320#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48321#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48322#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48323#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48324#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48325#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48326#@gui : sep = separator() 48327#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48328#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48329#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48330#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48331#@gui : sep = separator() 48332#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/10/02</i>.</small>") 48333fx_smooth_guided : skip ${6=0},${7=0} 48334 if $1" && "!narg($_guide) 48335 if $!<2 gui_warning_preview "Missing guide layer" return fi 48336 store[{$1==1?0:-1}] _guide 48337 fi 48338 if $1==0 # Self-guide 48339 ac "repeat $4 guided $2,$3 done",$5 48340 elif $1==1 # Guide as top layer 48341 ac "$_guide r. ..,..,1,100%,0,0,0.5,0.5 repeat $4 guided[0] [1],$2,$3 done rm.",$5 48342 if !narg($_is_preview) $_guide mv. 0 fi 48343 else # Guide as bottom layer 48344 ac "$_guide r. ..,..,1,100%,0,0,0.5,0.5 repeat $4 guided[0] [1],$2,$3 done rm.",$5 48345 if !narg($_is_preview) $_guide fi 48346 fi 48347 48348fx_smooth_guided_preview : 48349 if $1" && "!narg($_guide) 48350 if $!<2 gui_warning_preview "Missing guide layer" return fi 48351 store[{$1==1?0:-1}] _guide 48352 fi 48353 _is_preview=1 48354 gui_split_preview "fx_smooth_guided $*",${-3--1} 48355 48356#@gui Smooth [Diffusion] : fx_smooth_diffusion, fx_smooth_diffusion_preview(0) 48357#@gui : Sharpness = float(0.7,0,2) 48358#@gui : Anisotropy = float(0.3,0,1) 48359#@gui : Gradient Smoothness = float(0.6,0,10) 48360#@gui : Tensor Smoothness = float(1.1,0,10) 48361#@gui : Time Step = float(15,5,50) 48362#@gui : Iterations = int(8,1,100) 48363#@gui : sep = separator() 48364#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48365#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48366#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48367#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48368#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48369#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48370#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48371#@gui : sep = separator() 48372#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 48373#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 48374#@gui : sep = separator() 48375#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48376#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48377#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48378#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48379#@gui : sep = separator() 48380#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 48381fx_smooth_diffusion : 48382 ac "gui_parallel_overlap \"smooth $6,$1,$2,$3,$4,$5,0 c 0,255\",$8,$9",$7 48383 48384fx_smooth_diffusion_preview : 48385 gui_split_preview "fx_smooth_diffusion $*",${-3--1} 48386 48387#@gui Smooth [Mean-Curvature] : fx_smooth_meancurvature, fx_smooth_meancurvature_preview(0) 48388#@gui : Time Step = float(30,5,50) 48389#@gui : Iterations = int(4,1,30) 48390#@gui : Keep Iterations as Different Layers = bool(false) 48391#@gui : sep = separator() 48392#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48393#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48394#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48395#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48396#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48397#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48398#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48399#@gui : sep = separator() 48400#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 48401#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 48402#@gui : sep = separator() 48403#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48404#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48405#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48406#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48407#@gui : sep = separator() 48408#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 48409fx_smooth_meancurvature : 48410 ac "gui_parallel_overlap \"meancurvature_flow $2,$1,$3 c 0,255\",$5,$6",$4 48411 48412fx_smooth_meancurvature_preview : 48413 gui_split_preview "fx_smooth_meancurvature $*",${-3--1} 48414 48415#@gui Smooth [Median] : fx_smooth_median, fx_smooth_median_preview(0) 48416#@gui : Radius = int(3,1,20) 48417#@gui : Threshold = float(255,0,255) 48418#@gui : sep = separator() 48419#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48420#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48421#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48422#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48423#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48424#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48425#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48426#@gui : sep = separator() 48427#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48428#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48429#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48430#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48431#@gui : sep = separator() 48432#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48433fx_smooth_median : 48434 ac "median $1,$2",$3 48435 48436fx_smooth_median_preview : 48437 gui_split_preview "fx_smooth_median $*",${-3--1} 48438 48439#@gui Smooth [NL-Means] : fx_smooth_nlmeans, fx_smooth_nlmeans_preview(0) 48440#@gui : Patch Size = float(4,0.5,10) 48441#@gui : Spatial Bandwidth = int(4,3,13) 48442#@gui : Tonal Bandwidth = float(10,1,50) 48443#@gui : Patch Measure = choice(3,"Linf-Norm","L1-Norm","L2-Norm","Luminance","Lightness","RGB") 48444#@gui : sep = separator() 48445#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48446#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48447#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48448#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48449#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48450#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48451#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48452#@gui : sep = separator() 48453#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 48454#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 48455#@gui : sep = separator() 48456#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48457#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48458#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48459#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48460#@gui : sep = separator() 48461#@gui : note = note("<small>Author: <i>Jérôme Boulanger</i>. Latest Update: <i>2015/01/07</i>.</small>") 48462fx_smooth_nlmeans: 48463 repeat $! l[$>] 48464 if s==1 nlmeans $1,$2,$3,-_fx_smooth_nlmeans$4 # Handle separately gray scale images. 48465 else ac "gui_parallel_overlap \"nlmeans $1,$2,$3,-_fx_smooth_nlmeans$4\",$6,$7",$5 48466 fi 48467 endl done 48468 48469_fx_smooth_nlmeans0 : s c abs max 48470_fx_smooth_nlmeans1 : s c abs + 48471_fx_smooth_nlmeans2 : norm 48472_fx_smooth_nlmeans3 : if s>=3 channels 0,2 luminance else norm fi 48473_fx_smooth_nlmeans4 : if s>=3 channels 0,2 srgb2rgb rgb2lab channels 0 else norm fi 48474_fx_smooth_nlmeans5 : 48475 48476fx_smooth_nlmeans_preview: 48477 gui_split_preview "fx_smooth_nlmeans $*",${-3--1} 48478 48479#@gui Smooth [Patch-Based] : fx_smooth_patch, fx_smooth_patch_preview(0) 48480#@gui : Spatial Variance = float(10,0.1,200) 48481#@gui : Patch Variance = float(10,0.1,200) 48482#@gui : Patch Size = int(3,2,21) 48483#@gui : Lookup Size = int(5,2,21) 48484#@gui : Patch Smoothness = float(0,0,4) 48485#@gui : Fast Approximation = bool(1) 48486#@gui : Iterations = int(1,1,10) 48487#@gui : sep = separator() 48488#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48489#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48490#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48491#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48492#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48493#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48494#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48495#@gui : sep = separator() 48496#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 48497#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 48498#@gui : sep = separator() 48499#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48500#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48501#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48502#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48503#@gui : sep = separator() 48504#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 48505fx_smooth_patch : 48506 ac "gui_parallel_overlap \"repeat $7 denoise $1,$2,$3,$4,$5,$6 done c 0,255\",$9,$10",$8 48507 48508fx_smooth_patch_preview : 48509 gui_split_preview "fx_smooth_patch $*",${-3--1} 48510 48511#@gui Smooth [Patch-PCA] : fx_smooth_patchpca, fx_smooth_patchpca_preview(0) 48512#@gui : Strength = float(4,0,16) 48513#@gui : Patch Size = int(7,2,21) 48514#@gui : Lookup Size = int(11,2,21) 48515#@gui : Spatial Sampling = int(7,1,16) 48516#@gui : sep = separator() 48517#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48518#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48519#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48520#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48521#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48522#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48523#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48524#@gui : sep = separator() 48525#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48526#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48527#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48528#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48529#@gui : sep = separator() 48530#@gui : note = note{"<small><b>Note:</b> Beware, this filter uses a very computationally intensive algorithm to 48531#@gui : denoise images. So, do not complain too much if you have less than 8 cores available for the computation :) 48532#@gui : </small>"} 48533#@gui : sep = separator() 48534#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Jérome Boulanger</i>. 48535#@gui : Latest Update: <i>2016/24/03</i>.</small>") 48536fx_smooth_patchpca : 48537 ac "denoise_patchpca ${1-4} c 0,255",$5 48538 48539fx_smooth_patchpca_preview : 48540 gui_split_preview "fx_smooth_patchpca $*",${-3--1} 48541 48542#@gui Smooth [Perona-Malik] : fx_smooth_peronamalik, fx_smooth_peronamalik_preview(0) 48543#@gui : K-Factor = float(20,0,255) 48544#@gui : Time Step = float(5,5,50) 48545#@gui : Iterations = int(5,1,30) 48546#@gui : Keep Iterations as Different Layers = bool(false) 48547#@gui : sep = separator() 48548#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48549#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48550#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48551#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48552#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48553#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48554#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48555#@gui : sep = separator() 48556#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 48557#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 48558#@gui : sep = separator() 48559#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48560#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48561#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48562#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48563#@gui : sep = separator() 48564#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/26/11</i>.</small>") 48565fx_smooth_peronamalik : 48566 ac "gui_parallel_overlap \"peronamalik_flow $1,$3,$2,$4 c 0,255\",$6,$7",$5 48567 48568fx_smooth_peronamalik_preview : 48569 gui_split_preview "fx_smooth_peronamalik $*",${-3--1} 48570 48571#@gui Smooth [Selective Gaussian] : fx_smooth_selective, fx_smooth_selective_preview(0) 48572#@gui : Amplitude = float(5,0,20) 48573#@gui : Edges = float(0.5,0,2) 48574#@gui : Scales = int(5,1,10) 48575#@gui : Iterations = int(1,1,10) 48576#@gui : sep = separator() 48577#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48578#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48579#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48580#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48581#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48582#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48583#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48584#@gui : sep = separator() 48585#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 48586#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 48587#@gui : sep = separator() 48588#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48589#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48590#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48591#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48592#@gui : sep = separator() 48593#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 48594fx_smooth_selective : 48595 ac "gui_parallel_overlap \"repeat $4 blur_selective $1,$2,$3 done c 0,255\",$6,$7",$5 48596 48597fx_smooth_selective_preview : 48598 gui_split_preview "fx_smooth_selective $*",${-3--1} 48599 48600#@gui Smooth [Skin] : fx_smooth_skin, fx_smooth_skin_preview(1) 48601#@gui : note = note("<small><b>Step 1:</b> Skin detection</small>") 48602#@gui : Skin Estimation = choice(2,"None","Manual","Automatic") 48603#@gui : Tolerance = float(0.5,0,1) 48604#@gui : Smoothness = float(1,0,5) 48605#@gui : Threshold = float(1,0,10) 48606#@gui : Pre-Normalize Image = bool(1) 48607#@gui : X-Coordinate [Manual] = float(50,0,100) 48608#@gui : Y-Coordinate [Manual] = float(50,0,100) 48609#@gui : Radius [Manual] = float(5,0,25) 48610#@gui : sep = separator() 48611#@gui : note = note("<small><b>Step 2:</b> Medium scale smoothing</small>") 48612#@gui : Base Scale = float(2,0,10) 48613#@gui : Fine Scale = float(0.2,0,0.8) 48614#@gui : Smoothness = float(3,0,10) 48615#@gui : Smoothness Type = choice(1,"Gaussian","Bilateral") 48616#@gui : sep = separator() 48617#@gui : note = note("<small><b>Step 3:</b> Details enhancement</small>") 48618#@gui : Gain = float(0.05,0,0.5) 48619#@gui : sep = separator() 48620#@gui : Preview Data = choice{5,"Skin Mask","Base Scale","Medium Scale (Original)","Medium Scale (Smoothed)", 48621#@gui : "Fine Scale","Result Image"} 48622#@gui : sep = separator() 48623#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48624#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48625#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48626#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48627#@gui : sep = separator() 48628#@gui : url = link("Click here for a video tutorial","http://www.youtube.com/watch?v=H8pQfq-ybCc") 48629#@gui : sep = separator() 48630#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/20/12</i>.</small>") 48631fx_smooth_skin : 48632 repeat $! l[$>] split_opacity l[0] to_rgb 48633 48634 # Skin detection step. 48635 if $5 +balance_gamma 128,128,128 else [0] fi 48636 if $1==0 channels. 0 f. 1 elif $1==2 detect_skin. $2 else detect_skin. $2,$6%,$7%,$8% fi 48637 M={iM} b. $3% *. {$M/iM} *. $4 c. 0,1 48638 48639 # Details smoothing step. 48640 split_details[0] 4,$9%,$10% 48641 +_fx_smooth_skin[2] $12,$11 48642 j[2] .,0,0,0,0,1,.. rm[-2,-1] 48643 *. {10^$13} + c 0,255 48644 48645 endl a c endl done 48646 48647_fx_smooth_skin : 48648 if $1==0 b {$2/8}% 48649 else 48650 if $2>0 48651 m={im} M={iM} n 0,255 48652 repeat int($2/5) bilateral 3%,{5*3} done 48653 bilateral 3%,{($2%5)*3} 48654 * {($M-$m)/255} + $m 48655 fi 48656 fi 48657 48658fx_smooth_skin_preview : 48659 if $-2==0 48660 gui_split_preview "if $5 balance_gamma 128,128,128 fi if $1==0 f 1 elif $1==2 detect_skin $2 "\ 48661 "else detect_skin $2,$6%,$7%,$8% fi M={iM} b $3% * {255*$M/iM} * $4 c 0,255",${-3--1} 48662 elif $-2==1 48663 gui_split_preview "b $9%",${-3--1} 48664 elif $-2==2 48665 gui_split_preview "split_details 4,$9%,$10% k.. n 0,255",${-3--1} 48666 elif $-2==3 48667 gui_split_preview "split_details 4,$9%,$10% k.. _fx_smooth_skin $12,$11 n 0,255",${-3--1} 48668 elif $-2==4 48669 gui_split_preview "split_details 4,$9%,$10% k. n 0,255",${-3--1} 48670 else 48671 gui_split_preview "fx_smooth_skin $*",${-3--1} 48672 fi 48673 48674 if $1==1 48675 to_rgb 48676 circle $6%,$7%,$8%,0.2,0,255,0 48677 circle $6%,$7%,$8%,0.4,0xFFFFFFFF,0,255,0 48678 line {$6-0.25*$8}%,{$7-0.25*$8}%,{$6+0.25*$8}%,{$7+0.25*$8}%,0.8,255,255,0 48679 line {$6+0.25*$8}%,{$7-0.25*$8}%,{$6-0.25*$8}%,{$7+0.25*$8}%,0.8,255,255,0 48680 fi 48681 48682#@gui Smooth [Thin Brush] : fx_smooth_anisotropic, fx_smooth_anisotropic(0) 48683#@gui : Amplitude = float(60,0,1000) 48684#@gui : Sharpness = float(0.9,0,2) 48685#@gui : Anisotropy = float(0.64,0,1) 48686#@gui : Gradient Smoothness = float(3.1,0,10) 48687#@gui : Tensor Smoothness = float(1.10,0,10) 48688#@gui : Spatial Precision = float(0.8,0.1,2) 48689#@gui : Angular Precision = float(30,1,180) 48690#@gui : Value Precision = float(2,0.1,5) 48691#@gui : Interpolation = choice(0,"Nearest Neighbor","Linear","Runge-Kutta") 48692#@gui : Fast Approximation = bool(1) 48693#@gui : Iterations = int(1,1,10) 48694#@gui : Channel(s) = choice("RGB","Luminance","Blue & Red chrominances","Blue chrominance","Red chrominance") 48695#@gui : sep = separator() 48696#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 48697#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 48698#@gui : note = note{"\n<small><b>Note: </b>This set of anisotropic smoothing parameters has been suggested 48699#@gui : by PhotoComiX.</small>"} 48700#@gui : sep = separator() 48701#@gui : note = note("<small>Author: <i>PhotoComiX</i>. Latest Update: <i>2010/26/12</i>.</small>") 48702 48703#@gui Smooth [Total Variation] : fx_smooth_tv, fx_smooth_tv_preview(0) 48704#@gui : Time Step = float(30,5,100) 48705#@gui : Iterations = int(10,1,40) 48706#@gui : Keep Iterations as Different Layers = bool(false) 48707#@gui : sep = separator() 48708#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48709#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48710#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48711#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48712#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48713#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48714#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48715#@gui : sep = separator() 48716#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 48717#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 48718#@gui : sep = separator() 48719#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48720#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48721#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48722#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48723#@gui : sep = separator() 48724#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 48725fx_smooth_tv : 48726 ac "gui_parallel_overlap \"tv_flow $2,$1,$3 c 0,255\",$5,$6",$4 48727 48728fx_smooth_tv_preview : 48729 gui_split_preview "fx_smooth_tv $*",${-3--1} 48730 48731#@gui Smooth [Wavelets] : fx_smooth_haar, fx_smooth_haar_preview(0) 48732#@gui : Threshold = float(1,0,10) 48733#@gui : Iterations = int(10,1,32) 48734#@gui : Scales = int(10,2,10) 48735#@gui : sep = separator() 48736#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 48737#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 48738#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 48739#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 48740#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 48741#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 48742#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 48743#@gui : sep = separator() 48744#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 48745#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 48746#@gui : sep = separator() 48747#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 48748#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 48749#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 48750#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 48751#@gui : sep = separator() 48752#@gui : note = note("<small>Author: <i>Jérome Boulanger and David Tschumperlé</i>. 48753#@gui : Latest Update: <i>2013/27/08</i>.</small>") 48754fx_smooth_haar : 48755 remove_opacity 48756 ac "gui_parallel_overlap \"denoise_haar $1,$3,$2 c 0,255\",$5,$6",$4 48757 48758fx_smooth_haar_preview : 48759 gui_split_preview "fx_smooth_haar $*",${-3--1} 48760 48761#@gui Upscale [Diffusion] : fx_upscale_smart, fx_upscale_smart_preview(0) 48762#@gui : Width = text("200%") 48763#@gui : Height = text("200%") 48764#@gui : Smoothness = float(2,0,20) 48765#@gui : Anisotropy = float(0.4,0,1) 48766#@gui : Sharpness = float(50,0,100) 48767#@gui : sep = separator() 48768#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48769fx_upscale_smart : 48770 to_rgb upscale_smart $1,$2,1,$3,$4,$5 c 0,255 48771 48772fx_upscale_smart_preview : 48773 repeat $! 48774 +r. $1,$2,1,1,0 48775 if w<{-2,w}" || "h<{-2,h} # Test for downscaling 48776 rm. /. 4 48777 0 t. "Downscaling is\nnot allowed!",5,5,20,1,255 r. ..,..,1,1,0,0,0.5,0.5 48778 -|[-2,-1] 48779 else 48780 z.. {50-50*{-2,w}/w}%,{50-50*{-2,h}/h}%,{50+50*{-2,w}/w}%,{50+50*{-2,h}/h}% 48781 rm. fx_upscale_smart. $1,$2,$3,$4,$5 c. 0,255 48782 fi 48783 mv. 0 done 48784 48785#@gui Upscale [Scale2x] : fx_scalenx, fx_scalenx_preview(0) 48786#@gui : Scaling Factor = choice("x 2","x 3","x 4","x 6","x 8","x 9","x 12","x 16","x 18","x 27") 48787#@gui : Colorbase = choice(0,"RGB","YCbCr","Lab") 48788#@gui : note = note{"\n<small><b>Note: </b> 48789#@gui : This filter re-implements the scaling algorithm described at : 48790#@gui : </small>"} 48791#@gui : url = link("http://scale2x.sourceforge.net") 48792#@gui : note = note{"<small> 48793#@gui : This filter is useful for resizing images that have very few colors 48794#@gui : (e.g. indexed images). It is generally useless for true colors images. 48795#@gui : </small>"} 48796#@gui : sep = separator() 48797#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48798fx_scalenx : 48799 repeat $! l[$>] split_opacity 48800 if $2==1 rgb2ycbcr[0] round[0] 48801 elif $2==2 rgb2lab8[0] round[0] 48802 fi 48803 if $1==0 scale2x 48804 elif $1==1 scale3x 48805 elif $1==2 scale2x scale2x 48806 elif $1==3 scale3x scale2x 48807 elif $1==4 scale2x scale2x scale2x 48808 elif $1==5 scale3x scale3x 48809 elif $1==6 scale3x scale2x scale2x 48810 elif $1==7 scale2x scale2x scale2x scale2x 48811 elif $1==8 scale3x scale3x scale2x 48812 elif $1==9 scale3x scale3x scale3x 48813 fi 48814 if $2==1 ycbcr2rgb[0] 48815 elif $2==2 lab82rgb[0] 48816 fi 48817 a c endl done 48818 48819fx_scalenx_preview : 48820 z 40%,40%,60%,60% 48821 fx_scalenx $1,$2 48822 48823#@gui Upscale [DCCI2x]: fx_scale_dcci2x, fx_scale_dcci2x_preview(0) 48824#@gui : note = note("<i>Directional Cubic Convolution Interpolation</i>"), sep = separator() 48825#@gui : Threshold = float(1.15,1,2) 48826#@gui : Exponent = int(5,1,6) 48827#@gui : Extend 1px = _bool(0) 48828#@gui : sep = separator() 48829#@gui : note = note("<small>Author: <i>Garagecoder</i>. Latest Update : <i>2015/11/07</i>.</small>") 48830#@gui : note = note{"\n<small><b>Note: </b> 48831#@gui : This filter re-implements the scaling algorithm described at : 48832#@gui : </small>"} 48833#@gui : url = link("wikipedia.org","https://en.wikipedia.org/wiki/Directional_Cubic_Convolution_Interpolation") 48834#@gui : note = note("<small>The algorithm is intended for enlarging images while avoiding</small>") 48835#@gui : note = note("<small>artifacts, e.g. staircase artifacts.</small>") 48836#@gui : note = note("\n<small>Threshold controls edge[lower] to texture[higher] balance.</small>") 48837#@gui : note = note("<small>Exponent controls texture edge sharpness[higher].</small>") 48838#@gui : note = note("<small>Warning: highly experimental...</small>") 48839fx_scale_dcci2x : skip ${1=1.15},${2=5},${3=0} 48840 repeat $! l[$>] 48841 split_opacity scale_dcci2x ${1-3} a c c 0,255 48842 endl done 48843 48844fx_scale_dcci2x_preview : 48845 z 25%,25%,75%,75% fx_scale_dcci2x $* 48846 48847#@gui ____<b>Rendering</b> 48848#------------------------- 48849 48850# Generic function to render a 3D image, with usual rendering parameters : 48851# $1 = Width 48852# $2 = Height 48853# $3 = Object size 48854# $4 = X-angle 48855# $5 = Y-angle 48856# $6 = Z-angle 48857# $7 = FOV 48858# $8 = X-light 48859# $9 = Y-light 48860# $10 = Z-light 48861# $11 = Specular lightness 48862# $12 = Specular shininess 48863# $13 = Rendering mode. 48864# $14 = Antialiasing (0 | 1) 48865fx_render3d : skip ${14=1} 48866 width={(1+$14)*$1} height={(1+$14)*$2} 48867 n3d c3d m3d {round($13)} f3d={0.5*max($width,$height)/tan($7*pi/360)} 48868 f3d $f3d l3d {$8*$f3d},{$9*$f3d},{$10*$f3d} sl3d $11 ss3d $12 48869 repeat $! l[$>] 48870 *3d {$3*max($width,$height)} r3d 0,0,1,{-$6} r3d 0,1,0,{-$5} r3d 1,0,0,{-$4} 48871 $width,$height,1,3,-1 48872 j3d. ..,50%,50% rm.. 48873 to_rgba replace_color 0,0,-1,-1,-1,255,0,0,0,0 48874 if $14 48875 r $1,$2,1,100%,2 s c,-3 +. 1e-5 /[0] [1] *[0] 255 a c 48876 fi 48877 endl done 48878 48879#@gui 3D Blocks : fx_blocks3d, fx_blocks3d(1) 48880#@gui : Resolution = int(32,1,128) 48881#@gui : Smoothness = float(0,0,40) 48882#@gui : Elevation = float(4,-10,10) 48883#@gui : Size = float(1.5,0,3) 48884#@gui : Angle = float(30,0,360) 48885#@gui : Tilt = float(60,0,90) 48886#@gui : FOV = float(45,1,90) 48887#@gui : Centering (%) = point(50,50) 48888#@gui : sep = separator() 48889#@gui : X-Light = float(0,-100,100) 48890#@gui : Y-Light = float(-50,-100,100) 48891#@gui : Z-Light = float(-100,-100,0) 48892#@gui : Specular Lightness = float(0.5,0,1) 48893#@gui : Specular Shininess = float(0.7,0,3) 48894#@gui : Use Light = bool(1) 48895#@gui : Antialiasing = bool(1) 48896#@gui : Outline Color = color(0,0,0,128) 48897#@gui : sep = separator() 48898#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/10/02</i>.</small>") 48899fx_blocks3d : 48900 repeat $! l[$>] 48901 nm=${"-gui_layer_name"} 48902 W={w} H={h} M={max(w,h)} 48903 if w>h r2dx $1 else r2dy $1 fi 48904 w={w} h={h} m={max(w,h)} 48905 if $3>0 mirror y fi 48906 imageblocks3d $3,$2% 48907 -3d. {$w/2},{$h/2} f={$4*$M/($m*(2-$16))} *3d $f,$f,{$f*abs($3*$1/100)} 48908 if $3>0 r3d 1,0,0,180 fi 48909 r3d 0,0,1,$5 r3d 1,0,0,-$6 48910 48911 # Render object. 48912 if $16 {2*$M},{2*$M},1,4,-1 else $M,$M,1,4,-1 fi 48913 f3d={0.5*w/tan($7*pi/360)} f3d $f3d 48914 l3d {$10*$f3d},{$11*$f3d},{$12*$f3d} sl3d $13 ss3d $14 48915 j3d. [0],$8%,$9%,0,1,{if($15,3,2)},0,1 48916 sh. 100% +. 1 *. 255 rm. 48917 48918 # Render object outline 48919 if $20 48920 .,.,1,3,-1 48921 j3d. [0],$8%,$9%,0,1,3,0,1 rm[0] 48922 g. xy,1 +[-2,-1] norm. !=. 0 48923 +r. 100%,100%,1,3 48924 sh. 0 *. $17 rm. 48925 sh. 1 *. $18 rm. 48926 sh. 2 *. $19 rm. 48927 j[0] .,0,0,0,0,{$20/255},.. rm[-2,-1] 48928 else rm[0] 48929 fi 48930 48931 replace_color 0,0,-1,-1,-1,0,0,0,0,0 48932 if $16 r 50%,50%,1,4,2 fi 48933 c 0,255 nm name($nm) 48934 endl done 48935 48936#@gui 3D Colored Object : fx_coloredobject3d, fx_coloredobject3d_preview(1) 48937#@gui : Type = choice{1,"Plane","Box","Pyramid","Ellipsoid","Torus","Gyroid","Weird","Cup"} 48938#@gui : Color = color(128,128,128,255) 48939#@gui : sep = separator() 48940#@gui : Size-1 = float(0.5,0,3) 48941#@gui : Size-2 = float(0.5,0,3) 48942#@gui : Size-3 = float(0.5,0,3) 48943#@gui : X-Angle = float(57,0,360) 48944#@gui : Y-Angle = float(41,0,360) 48945#@gui : Z-Angle = float(21,0,360) 48946#@gui : FOV = float(45,1,90) 48947#@gui : X-Light = float(0,-100,100) 48948#@gui : Y-Light = float(0,-100,100) 48949#@gui : Z-Light = float(-100,-100,0) 48950#@gui : Specular Lightness = float(0.5,0,1) 48951#@gui : Specular Shininess = float(0.7,0,3) 48952#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 48953#@gui : Antialiasing = bool(1) 48954#@gui : sep = separator() 48955#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/16/05</i>.</small>") 48956_fx_coloredobject3d : 48957 to_rgb _fx_coloredobject3d$1$2 ${6-8} col3d. ${3-5} 48958 db3d 0 48959 48960fx_coloredobject3d : 48961 _fx_coloredobject3d "_",${1-4,6-8} 48962 repeat $!-1 48963 +fx_render3d. {$>,w},{$>,h},$6,${9--1} 48964 sh. 3 *. {$5/255} rm. 48965 blend[$>,-1] alpha 48966 done 48967 rm. 48968 48969fx_coloredobject3d_preview : 48970 _fx_coloredobject3d "_preview_",${1-4,6-8} 48971 repeat $!-1 48972 +fx_render3d. {$>,w},{$>,h},$6,${9--1} 48973 sh. 3 *. {$5/255} rm. 48974 blend[$>,-1] alpha 48975 done rm. 48976 48977_fx_coloredobject3d_0 : plane3d 1 *3d. $1,$2,1 48978_fx_coloredobject3d_1 : box3d 1 *3d. $1,$2,$3 48979_fx_coloredobject3d_2 : pyramid3d 1,1 *3d. $1,$2,$3 48980_fx_coloredobject3d_3 : sphere3d 1 *3d. 1,{2*$2},{2*$3} 48981_fx_coloredobject3d_4 : torus3d $1,{$2/2},100,50 *3d. $3,0.5,0.5 48982_fx_coloredobject3d_5 : gyroid3d 24 *3d. $1,$2,$3 48983_fx_coloredobject3d_6 : weird3d 32 *3d. $1,$2,$3 48984_fx_coloredobject3d_7 : cup3d 128 *3d. $1,$2,$3 48985_fx_coloredobject3d_preview_0 : plane3d 1 *3d. $1,$2,1 48986_fx_coloredobject3d_preview_1 : box3d 1 *3d. $1,$2,$3 48987_fx_coloredobject3d_preview_2 : pyramid3d 1,1 *3d. $1,$2,$3 48988_fx_coloredobject3d_preview_3 : sphere3d 1 *3d. 1,{2*$2},{2*$3} 48989_fx_coloredobject3d_preview_4 : torus3d $1,{$2/2},100,50 *3d. $3,0.5,0.5 48990_fx_coloredobject3d_preview_5 : gyroid3d 8 *3d. $1,$2,$3 48991_fx_coloredobject3d_preview_6 : weird3d 12 *3d. $1,$2,$3 48992_fx_coloredobject3d_preview_7 : cup3d 64 *3d. $1,$2,$3 48993 48994#@gui 3D Elevation : fx_elevation3d, fx_elevation3d_preview(1) 48995#@gui : Factor = float(100,-1000,1000) 48996#@gui : Smoothness = float(1,0,10) 48997#@gui : sep = separator() 48998#@gui : Width = _int(1024,8,4096) 48999#@gui : Height = _int(1024,8,4096) 49000#@gui : Size = float(0.8,0,3) 49001#@gui : X-Angle = float(25,0,360) 49002#@gui : Y-Angle = float(0,0,360) 49003#@gui : Z-Angle = float(21,0,360) 49004#@gui : FOV = float(45,1,90) 49005#@gui : X-Light = float(0,-100,100) 49006#@gui : Y-Light = float(0,-100,100) 49007#@gui : Z-Light = float(-100,-100,0) 49008#@gui : Specular Lightness = float(0.5,0,1) 49009#@gui : Specular Shininess = float(0.7,0,3) 49010#@gui : Rendering = choice(2,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 49011#@gui : Antialiasing = bool(1) 49012#@gui : sep = separator() 49013#@gui : Top Layer Defines Object Texture = bool(0) 49014#@gui : sep = separator() 49015#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/11/10</i>.</small>") 49016_fx_elevation3d : 49017 if $3" && "$!>1 # Textured object 49018 repeat $!-1 l[0,{1+$>}] 49019 +ri.. .,3 49020 n. 0,{abs($1)} *. {sign($1)} b. $2 49021 elevation3d.. . rm. 49022 endl done 49023 else # Non-textured object 49024 repeat $! l[$>] 49025 +norm n. 0,{abs($1)} *. {sign($1)} b. $2 49026 elevation3d.. . rm. 49027 endl done 49028 fi 49029 db3d 49030 49031fx_elevation3d : 49032 _fx_elevation3d ${1-2},$17 49033 s0,s1=^,^0 fx_render3d[${s$17}] ${3--1} 49034 49035fx_elevation3d_preview : 49036 fx_elevation3d ${1-2},{w},{h},${5--1} 49037 if $17 rm[0] fi 49038 49039#@gui 3D Extrusion : fx_extrude3d, fx_extrude3d_preview(1) 49040#@gui : Depth = float(10,1,1024) 49041#@gui : Resolution = int(512,1,1024) 49042#@gui : Smoothness = float(0.6,0,3) 49043#@gui : sep = separator() 49044#@gui : Width = _int(1024,1,4096) 49045#@gui : Height = _int(1024,1,4096) 49046#@gui : Size = float(0.5,0,3) 49047#@gui : X-Angle = float(57,0,360) 49048#@gui : Y-Angle = float(41,0,360) 49049#@gui : Z-Angle = float(21,0,360) 49050#@gui : FOV = float(45,1,90) 49051#@gui : X-Light = float(0,-100,100) 49052#@gui : Y-Light = float(0,-100,100) 49053#@gui : Z-Light = float(-100,-100,0) 49054#@gui : Specular Lightness = float(0.5,0,1) 49055#@gui : Specular Shininess = float(0.7,0,3) 49056#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 49057#@gui : Antialiasing = bool(1) 49058#@gui : sep = separator() 49059#@gui : Top Layer Defines Object Texture = bool(0) 49060#@gui : sep = separator() 49061#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/11/10</i>.</small>") 49062_fx_extrude3d : 49063 if $4" && "$!>1 # Textured object 49064 repeat $!-1 l[0,{$>+1}] extrude3d. $1,$2,$3% t3d. .. endl done 49065 else extrude3d $1,$2,$3% # Non-textured object 49066 fi 49067 db3d 0 49068 49069fx_extrude3d : 49070 _fx_extrude3d ${1-3},$18 49071 s0,s1=^,^0 fx_render3d[${s$18}] ${4--1} 49072 49073fx_extrude3d_preview : 49074 fx_extrude3d ${1-3},{w},{h},${6--1} 49075 if $18 rm[0] fi 49076 49077#@gui 3D Image Object : fx_imageobject3d, fx_imageobject3d_preview(1) 49078#@gui : Type = choice{1,"Plane","Cube","Pyramid","Sphere","Torus","Gyroid","Weird","Cup","Rubik"} 49079#@gui : sep = separator() 49080#@gui : Width = _int(1024,1,4096) 49081#@gui : Height = _int(1024,1,4096) 49082#@gui : Size = float(0.5,0,3) 49083#@gui : X-Angle = float(57,0,360) 49084#@gui : Y-Angle = float(41,0,360) 49085#@gui : Z-Angle = float(21,0,360) 49086#@gui : FOV = float(45,1,90) 49087#@gui : X-Light = float(0,-100,100) 49088#@gui : Y-Light = float(0,-100,100) 49089#@gui : Z-Light = float(-100,-100,0) 49090#@gui : Specular Lightness = float(0.5,0,1) 49091#@gui : Specular Shininess = float(0.7,0,3) 49092#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 49093#@gui : Antialiasing = bool(1) 49094#@gui : sep = separator() 49095#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49096_fx_imageobject3d : 49097 to_rgb repeat $! l[$>] _fx_imageobject3d$1$2 endl done 49098 db3d 0 49099 49100fx_imageobject3d : 49101 _fx_imageobject3d "_",$1 fx_render3d ${2--1} 49102 49103fx_imageobject3d_preview : 49104 w={w} h={h} _fx_imageobject3d "_preview_",$1 fx_render3d $w,$h,${4--1} 49105 49106_fx_imageobject3d_0 : imageplane3d 49107_fx_imageobject3d_1 : imagecube3d 49108_fx_imageobject3d_2 : imagepyramid3d 49109_fx_imageobject3d_3 : imagesphere3d 128,64 49110_fx_imageobject3d_4 : torus3d 100,30,100,50 t3d. .. rm.. 49111_fx_imageobject3d_5 : gyroid3d 24 t3d. .. rm.. 49112_fx_imageobject3d_6 : weird3d 32 t3d. .. rm.. 49113_fx_imageobject3d_7 : cup3d 128 t3d. .. rm.. 49114_fx_imageobject3d_8 : imagerubik3d 5,5 49115_fx_imageobject3d_preview_0 : imageplane3d 49116_fx_imageobject3d_preview_1 : imagecube3d 49117_fx_imageobject3d_preview_2 : imagepyramid3d 49118_fx_imageobject3d_preview_3 : imagesphere3d 64,32 49119_fx_imageobject3d_preview_4 : torus3d 100,30,100,50 t3d. .. rm.. 49120_fx_imageobject3d_preview_5 : gyroid3d 8 c3d. n3d. t3d. .. rm.. 49121_fx_imageobject3d_preview_6 : weird3d 12 t3d. .. rm.. 49122_fx_imageobject3d_preview_7 : cup3d 64 t3d. .. rm.. 49123_fx_imageobject3d_preview_8 : imagerubik3d 3,3,5,5 49124 49125#@gui 3D Lathing : fx_lathing3d, fx_lathing3d_preview(1) 49126#@gui : Resolution = int(76,1,1024) 49127#@gui : Smoothness = float(2,0,5) 49128#@gui : Max Angle = float(361,0,361) 49129#@gui : sep = separator() 49130#@gui : Width = _int(1024,1,4096) 49131#@gui : Height = _int(1024,1,4096) 49132#@gui : Size = float(0.5,0,3) 49133#@gui : X-Angle = float(0,0,360) 49134#@gui : Y-Angle = float(0,0,360) 49135#@gui : Z-Angle = float(0,0,360) 49136#@gui : FOV = float(45,1,90) 49137#@gui : X-Light = float(0,-100,100) 49138#@gui : Y-Light = float(0,-100,100) 49139#@gui : Z-Light = float(-100,-100,0) 49140#@gui : Specular Lightness = float(0.5,0,1) 49141#@gui : Specular Shininess = float(0.7,0,3) 49142#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 49143#@gui : Antialiasing = bool(1) 49144#@gui : sep = separator() 49145#@gui : Top Layer Defines Object Texture = bool(0) 49146#@gui : sep = separator() 49147#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49148_fx_lathing3d : 49149 if $4" && "$!>1 # Textured object 49150 repeat $!-1 l[0,{$>+1}] lathe3d. $1,$2%,$3 t3d. .. endl done 49151 else lathe3d $1,$2%,$3 # Non-textured object 49152 fi 49153 db3d 0 49154 49155fx_lathing3d : 49156 _fx_lathing3d ${1-3},$18 49157 s0,s1=^,^0 fx_render3d[${s$18}] ${4--1} 49158 nm pos(0,0),mode(alpha) 49159 49160fx_lathing3d_preview : 49161 fx_lathing3d ${1-3},{w},{h},${6--1} 49162 if $18 rm[0] fi 49163 49164#@gui 3D Random Objects : fx_random3d, fx_random3d(1) 49165#@gui : Type = choice("Cube","Cone","Cylinder","Sphere","Torus") 49166#@gui : Density = int(50,1,300) 49167#@gui : Size = float(3,1,20) 49168#@gui : Z-Range = float(100,0,300) 49169#@gui : FOV = float(45,1,90) 49170#@gui : X-Light = float(0,-100,100) 49171#@gui : Y-Light = float(0,-100,100) 49172#@gui : Z-Light = float(-100,-100,0) 49173#@gui : Specular Lightness = float(0.5,0,1) 49174#@gui : Specular Shininess = float(0.7,0,3) 49175#@gui : Rendering = choice(3,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 49176#@gui : Opacity = float(1,0,1) 49177#@gui : sep = separator() 49178#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49179fx_random3d : 49180 repeat $! l[$>] 49181 f3d={0.5*max(w,h)/tan($5*pi/360)} f3d $f3d l3d {$6*$f3d},{$7*$f3d},{$8*$f3d} sl3d $9 ss3d $10 49182 to_rgb ({w},{h},{d},{s}) /. 2 repeat $2 49183 ({1,@0}) +. {1,@1} *. $3 /. 100 _fx_random3d$1 {^} rm.. 49184 r3d. 1,1,0,{u(0,360)} 49185 ({u(-1,1)}) *. {1,@0} ({u(-1,1)}) *. {1,@1} 49186 +3d... {-2,^},{^},{u(-$4,$4)} rm[-2,-1] 49187 col3d. {u(255)},{u(255)},{u(255)} done +3d[2--1] j3d[0] .,50%,50%,0,$12,$11,0,1 49188 k[0] 49189 endl done 49190 49191_fx_random3d0 : box3d $1 49192_fx_random3d1 : ($1) /. 2 cone3d {^},$1 rm.. 49193_fx_random3d2 : ($1) /. 2 cylinder3d {^},$1 rm.. 49194_fx_random3d3 : sphere3d $1,2 49195_fx_random3d4 : ($1) /. 3 torus3d $1,{^} rm.. 49196 49197#@gui Ball : fx_ball, fx_ball_preview(0) 49198#@gui : Radius = int(128,1,1024) 49199#@gui : Specular Light = float(0.8,0,8) 49200#@gui : Specular Size = float(1,0,8) 49201#@gui : Shadow = float(1.5,0,4) 49202#@gui : Color = color(255,0,255) 49203#@gui : sep = separator() 49204#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/11</i>.</small>") 49205fx_ball : 49206 ball $1,${5-7},${2-4} 49207 if $!>1 mv. 0 nm[0] "name(Ball),pos("{0,0.5*([${-max_wh}]-[w,h])}")" else nm[0] "name(Ball)" fi 49208 49209fx_ball_preview : 49210 fx_ball $* 49211 if $!>1 rv[-2,-1] blend[-2,-1] alpha fi 49212 49213#@gui Circle Art : fx_circle_art, fx_circle_art 49214#@gui : Type = choice(1,"Random","Lissajous spiral") 49215#@gui : Density = float(15,0,100) 49216#@gui : Radius = float(0.5,0,1) 49217#@gui : Modulo = int(8,2,16) 49218#@gui : Anti-Aliasing = bool(1) 49219#@gui : Random Colors = bool(1) 49220#@gui : sep = separator() 49221#@gui : note = note("<small><b>Lissajous parameters:</b></small>") 49222#@gui : Curve Length = float(15,0,50) 49223#@gui : Curve Angle = float(0,0,360) 49224#@gui : Minimal Radius = float(0,-5,5) 49225#@gui : Maximal Radius = float(0.5,-5,5) 49226#@gui : X-Dispersion = float(1,0,4) 49227#@gui : Y-Dispersion = float(1,0,4) 49228#@gui : X-Factor = int(1,0,16) 49229#@gui : Y-Factor = int(1,0,16) 49230#@gui : sep = separator() 49231#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/22/08</i>.</small>") 49232fx_circle_art : 49233 if !$2 f 0 return fi 49234 # Generate object coordinates. 49235 if $1==0 # Random. 49236 {round(2*($2^1.5))} 49237 rand. -1,1 +rand. -1,1 +rand. -$3,$3 a[-3--1] y 49238 else # Spiral. 49239 {max(1,round($2*$7))} 49240 t0={$8*2*pi/180} 49241 rows. 0,2 49242 f. "r = x/(w-1); 49243 t = 2*pi*x/$2; 49244 if(y==0,(r^$11)*cos("$t0"+$13*t), 49245 if(y==1,(r^$12)*sin("$t0"+$14*t), 49246 max(0,$3*($9+($10-$9)*r))))" 49247 fi 49248 49249 # Convert to 3D object. 49250 l. 49251 transpose s x,-1 h={h} 49252 i[0] ({'CImg3d'},{2*$h},$h) # Header. 49253 ++... . -[-4,-2] i .. i[-3,-1] 1,100% a[-6--1] x # Vertices. 49254 1,$h,1,1,5 1,$h,1,1,2*y ++. 1 a[-3--1] x z. 0,5 # Primitives. 49255 3,$h,1,1,1 1,$h,1,1,-1 y a y # Colors + Opacities. 49256 endl 49257 49258 # Render object on selected images. 49259 repeat $!-1 l[$>,-1] 49260 s={0,max(w,h)} rm[0] 49261 if $5 {2*$s},{2*$s} +*3d[0] $s # Anti-aliasing. 49262 else $s,$s +*3d[0] {$s/2} # No anti-aliasing. 49263 fi 49264 j3d[1] [2],50%,50%,0,1,2,0,0 rm[2] 49265 %. $4 49266 if $6 i.. 100%,100%,1,3 rand.. 0,255 plasma.. 1,1 equalize.. 256 n.. 0,255 blend[-2,-1] shapeaverage fi 49267 rv 49268 endl done 49269 rm. 49270 n 0,255 49271 if $5 r 50%,50%,1,100%,2 fi 49272 49273#@gui Equation Plot [Parametric] : fx_equation_parametric, fx_equation_parametric 49274#@gui : X(t) = text{"sin(t)*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)"} 49275#@gui : Y(t) = text{"cos(t)*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)"} 49276#@gui : Min-t = float(0,-1000,1000) 49277#@gui : Max-t = float(100,-1000,1000) 49278#@gui : Resolution = int(4096,2,32768) 49279#@gui : Outline Opacity = float(1,0,1) 49280#@gui : Dot Size = int(0,0,16) 49281#@gui : Start Color = color(64,0,0) 49282#@gui : End Color = color(128,0,0) 49283#@gui : Colored Outline = bool(1) 49284#@gui : Antialiasing = bool(1) 49285#@gui : Decoration = bool(1) 49286#@gui : sep = separator() 49287#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/13/11</i>.</small>") 49288fx_equation_parametric : 49289 repeat $! l[$>] 49290 w={w} h={h} rm 49291 $5,1,1,2,"t=$3+x*($4-$3)/($5-1);if(c==0,$1,$2)" 49292 channels. 0,2 49293 ($8,$11^$9,$12^$10,$13) r. {-2,w},1,1,3,3 a c 49294 display_parametric $w,$h,{$6+$14*1.001},$7,$15,$16 49295 endl done 49296 49297#@gui Equation Plot [Y=f(X)] : fx_equation_plot, fx_equation_plot 49298#@gui : F(X) = text{"X*c+10*cos(X+c+u)"} 49299#@gui : X-Min = float(-10,-100,100) 49300#@gui : X-Max = float(10,-100,100) 49301#@gui : Resolution = int(100,2,1024) 49302#@gui : Channels = int(3,1,32) 49303#@gui : Plot Type = choice(2,"None","Lines","Splines","Bars") 49304#@gui : Vertex Type = choice(0,"None","Points","Crosses 1","Crosses 2","Circles 1","Circles 2","Square 1","Square 2") 49305#@gui : sep = separator() 49306#@gui : note = note("<small><b>Note</b> : 49307#@gui : Use variable <b>X</b> instead of <b>x</b> in the above equation to take care of the X-min/max settings. 49308#@gui : Variable <b>c</b> refers to the current channel number. 49309#@gui : Variable <b>u</b> refers to a uniformly distributed random value in [0,1]. 49310#@gui : Reduce resolution to be able to view 49311#@gui : separate graph vertices.</small>") 49312#@gui : sep = separator() 49313#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49314fx_equation_plot : 49315 repeat $! l[$>] 49316 w={w} h={h} rm 49317 $4,1,1,$5,"X=$2+($3-$2)*x/($4-1);$1" 49318 dg $w,$h,$6,$7,$2,$3 49319 endl done 49320 49321#@gui Gradient [Corners] : fx_corner_gradient, fx_corner_gradient 49322#@gui : Color 1 (Up/Left Corner) = color(255,255,255,128) 49323#@gui : Color 2 (Up/Right Corner) = color(255,0,0,255) 49324#@gui : Color 3 (Bottom/Left Corner) = color(0,255,0,255) 49325#@gui : Color 4 (Bottom/Right Corner) = color(0,0,255,255) 49326#@gui : sep = separator() 49327#@gui : Colorspace = choice(1,"sRGB","Linear RGB","Lab") 49328#@gui : sep = separator() 49329#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49330fx_corner_gradient : skip ${17=0} 49331 repeat $! l[$>] 49332 wh={w},{h} rm 49333 ($1,$5;$9,$13^$2,$6;$10,$14^$3,$7;$11,$15^$4,$8;$12,$16) 49334 _gb_fwd $17 49335 r. $wh,1,100%,3 49336 _gb_bwd $17 49337 endl done 49338 49339#@gui Gradient [Custom Shape] : fx_custom_gradient, fx_custom_gradient_preview(1) 49340#@gui : note = note("<small><b>Shape selection:</b></small>") 49341#@gui : Select By = choice("Auto","Dark Pixels","Bright Pixels","Opaque Pixels") 49342#@gui : Smoothness = float(0,0,10) 49343#@gui : Threshold = float(0,0,100) 49344#@gui : Preview Shape = bool(1) 49345#@gui : note = note("<small><b>Note:</b> Shapes with small strokes may lead to incorrect previews.</small>") 49346#@gui : sep = separator() 49347#@gui : note = note("<small><b>Gradient parameters:</b></small>") 49348#@gui : Number of Colors = int(4,2,10) 49349#@gui : Cycles = float(1,1,16) 49350#@gui : Offset = float(0,0,100) 49351#@gui : Shading = float(128,1,256) 49352#@gui : Inner Length = float(100,0,100) 49353#@gui : Outer Length = float(100,0,100) 49354#@gui : Spatial Metric = choice(2,"Chebyshev","Manhattan","Euclidean") 49355#@gui : Color Metric = choice("RGB","HSV","Lab") 49356#@gui : Shade Back to First Color = bool(1) 49357#@gui : Preview Gradient = bool(0) 49358#@gui : Save Gradient As = _text("") 49359#@gui : sep = separator() 49360#@gui : note = note("<small><b>Color definitions:</b></small>") 49361#@gui : Colormap Type = choice(1,"Pre-Defined","User-Defined") 49362#@gui : Pre-Defined Colormap = int(0,0,65535) 49363#@gui : 1st Color = color(0,0,0,255) 49364#@gui : 2nd Color = color(255,0,0,255) 49365#@gui : 3rd Color = color(255,255,0,255) 49366#@gui : 4th Color = color(255,255,255,255) 49367#@gui : 5th Color = color(0,255,255,255) 49368#@gui : 6th Color = color(0,255,0,255) 49369#@gui : 7th Color = color(0,0,255,255) 49370#@gui : 8th Color = color(128,128,128,255) 49371#@gui : 9th Color = color(255,0,255,255) 49372#@gui : 10th Color = color(0,0,0,0) 49373#@gui : sep = separator() 49374#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/03/10</i>.</small>") 49375fx_custom_gradient_preview : skip "${15=}" 49376 repeat $! l[$>] 49377 if $4 49378 +_fx_custom_gradient1 ${1-14},"$15",${16--1} +erode. 3 -[-2,-1] +dilate. 5 a[-2,-1] c n. 0,255 49379 fx_custom_gradient[0] ${1-14},"$15",${16--1},-1 blend alpha 49380 else fx_custom_gradient ${1-14},"$15",${16--1},-1 49381 fi 49382 if $14 49383 +_fx_custom_gradient0[] ${1-14},"$15",${16--1} r. {{0,w}-16},16,1,4 frame. 1,1,0 j[0] .,8,{0,h-25} rm. 49384 fi 49385 endl done 49386 49387fx_custom_gradient : skip "${15=}" 49388 _fx_custom_gradient0 ${1-14},"$15",${16--1} 49389 if $-1>=0" && "narg("$15") 49390 dir_ggr=${-path_gimp}gradients 49391 0 nm. ${"normalize_filename \"$15\""} name_ggr={b} rm. output_ggr. $dir_ggr/$name_ggr.ggr,"$15" 49392 fi 49393 i.. (0^0^0^0) a[-2,-1] x 49394 repeat $!-1 l[$>,-1] 49395 _fx_custom_gradient1[0] ${1-14},"$15",${16--1} 49396 +distance[0] 1,$11 +distance[0] 0,$11 *. -1 +[0] 1 +[0,-2,-1] # Signed distance function. 49397 m={$9%*{0,im}} M={$10%*{0,iM}} 49398 -[0] $m *[0] {1,(w-2)/($M-$m)} +[0] 1 49399 round[0] map[0] . 49400 endl done 49401 rm. 49402 49403# Create colormap. 49404_fx_custom_gradient0 : 49405 if $16 4,8,1,1,${18-56} permute. yzcx 49406 else 8,1,1,3 srand $17 rand. 0,255 to_rgba. 49407 fi 49408 z. 0,{$5-1} 49409 if $13 49410 r. {200*$6}%,1,1,4,0,2 49411 __fx_custom_gradient0. $12,$8 49412 shift. {-round(w*0.5*$7%)},0,0,0,2 z. 0,{w/2-1} 49413 else 49414 __fx_custom_gradient0. $12,$8 49415 r. {100*$6}%,1,1,4,0,2 shift. {-round(w*$7%)},0,0,0,2 49416 fi 49417 49418__fx_custom_gradient0 : 49419 if $1==1 sh. 0,2 rgb2hsv. rm. 49420 elif $1==2 sh. 0,2 srgb2rgb. rgb2lab. rm. 49421 fi 49422 r. {$2*w},1,1,4,3 49423 if $1==1 sh. 0,2 hsv2rgb. rm. 49424 elif $1==2 sh. 0,2 lab2rgb. rgb2srgb. rm. 49425 fi 49426 49427# Extract shape from image. 49428_fx_custom_gradient1 : 49429 b $2% 49430 if $1==0 # Auto-mode. 49431 to_a split_opacity 49432 if iM>im+32 49433 rm.. >=[0] {100-$3}% 49434 else 49435 rm. norm n 0,1 49436 if ia>0.5 <=[0] $3% else >=[0] {100-$3}% fi 49437 fi 49438 elif $1==1 # Dark pixels. 49439 remove_opacity norm <= $3% 49440 elif $1==2 # Bright pixels. 49441 remove_opacity norm >= {100-$3}% 49442 else # Opaque pixels. 49443 to_a channels 100% >= {100-$3}% 49444 fi 49445 49446#@gui Gradient [from Line] : fx_line_gradient, fx_line_gradient_preview(1) 49447#@gui : Starting Point (%) = point(0,0,0,1,255,0,0) 49448#@gui : Ending Point (%) = point(100,100,0,1,64,128,255) 49449#@gui : Sampling = float(100,0,100) 49450#@gui : Length = int(0,0,4096) 49451#@gui : note = note("<small><b>Note:</b> Set length to <i>0</i> to release gradient length constraints.</small>") 49452#@gui : Sort Colors = choice("Don't Sort","By Red Component","By Green Component","By Blue Component", 49453#@gui : "By Luminance","By Blue Chrominance","By Red Chrominance","By Lightness") 49454#@gui : Reverse Gradient = bool(0) 49455#@gui : sep = separator() 49456#@gui : Preview Gradient = bool(1) 49457#@gui : Save Gradient As = _text("") 49458#@gui : sep = separator() 49459#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/29/06</i>.</small>") 49460fx_line_gradient : skip "${10=}" 49461 _fx_line_gradient $* 49462 if narg("$10") 49463 dir_ggr=${-path_gimp}gradients 49464 0 nm. ${"normalize_filename \"$10\""} name_ggr={b} rm. output_ggr. $dir_ggr/$name_ggr.ggr,"$10" 49465 fi 49466 repeat $! r[$>] 100%,64,1,100% done 49467 49468fx_line_gradient_preview : 49469 repeat $! l[$>] 49470 to_rgba 49471 if $9 +_fx_line_gradient $* fi 49472 l[0] 49473 line $1%,$2%,$3%,$4%,1,0xF0F0F0F0,255,255,255,255 49474 line $1%,$2%,$3%,$4%,1,0x0F0F0F0F,0,0,0,255 49475 endl 49476 if $!>1 r. {{0,w}-32},32,1,4,1 frame. 1,1,0,0,0,255 j[0] [1],16,{{0,h}-48} rm. fi 49477 endl done 49478 49479_fx_line_gradient : 49480 at_line $1%,$2%,0,$3%,$4%,0 r {max(0.1,$5)}%,1,1,100%,1 49481 m "feature1 : channels 0" 49482 m "feature2 : channels 1" 49483 m "feature3 : channels 2" 49484 m "feature4 : to_rgb luminance" 49485 m "feature5 : to_rgb rgb2ycbcr channels 1" 49486 m "feature6 : to_rgb rgb2ycbcr channels 2" 49487 m "feature7 : to_rgb srgb2rgb rgb2lab channels 0" 49488 if $7 repeat $! l[$>] +feature$7 rv a y sort +,x rows 1 endl done fi 49489 if $6 r $6,1,1,100%,3 fi 49490 if $8 mirror x fi 49491 49492#@gui Gradient [Linear] : fx_linear_gradient, fx_linear_gradient 49493#@gui : Starting Color = color(0,0,0,255) 49494#@gui : Ending Color = color(255,255,255,255) 49495#@gui : Swap Colors = bool(0) 49496#@gui : Angle = float(45,0,360) 49497#@gui : Fade Start = float(0,0,100) 49498#@gui : Fade End = float(100,0,100) 49499#@gui : sep = separator() 49500#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 49501#@gui : sep = separator() 49502#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49503fx_linear_gradient : skip ${13=0} 49504 repeat $! l[$>] 49505 wh={w},{h} rm 49506 ($1^$2^$3^$4) ($5^$6^$7^$8) 49507 if $9 rv[-2,-1] fi 49508 r $wh 49509 _gb_fwd $13 49510 fade_linear $10,$11,$12 49511 _gb_bwd $13 49512 endl done 49513 49514#@gui Gradient [Radial] : fx_radial_gradient, fx_radial_gradient 49515#@gui : Starting Color = color(0,0,0,255) 49516#@gui : Ending Color = color(255,255,255,255) 49517#@gui : Swap Colors = bool(0) 49518#@gui : Fade Start = float(0,0,100) 49519#@gui : Fade End = float(100,0,100) 49520#@gui : Center (%) = point(50,50,0,1,255) 49521#@gui : sep = separator() 49522#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 49523#@gui : sep = separator() 49524#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/29/06</i>.</small>") 49525fx_radial_gradient : skip ${14=0} 49526 repeat $! l[$>] 49527 wh={w},{h} rm 49528 ($1^$2^$3^$4) ($5^$6^$7^$8) 49529 if $9 rv[-2,-1] fi 49530 r $wh 49531 _gb_fwd $14 49532 100%,100% =. 1,$12%,$13% distance. 1 _fade $10,$11 49533 _gb_bwd $14 49534 endl done 49535 49536#@gui Gradient [Random] : fx_random_gradient, fx_random_gradient 49537#@gui : Density = int(32,1,1024) 49538#@gui : Seed = int(0,0,65535) 49539#@gui : Smoothness = float(0,0,10) 49540#@gui : Color Balance = color(128,128,128) 49541#@gui : Opacity = float(1,0,1) 49542#@gui : sep = separator() 49543#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/08/04</i>.</small>") 49544fx_random_gradient : 49545 repeat $! l[$>] 49546 to_rgba 100%,100% srand $2 49547 eval "repeat ($1,n, 49548 x = round(u(w-1)); 49549 y = round(u(h-1)); 49550 i(x,y) = 1; 49551 i(#0,x,y,0,0) = round(u(255)); 49552 i(#0,x,y,0,1) = round(u(255)); 49553 i(#0,x,y,0,2) = round(u(255)); 49554 i(#0,x,y,0,3) = $7*255 + (1-$7)*round(u(255)); 49555 )" 49556 if $7!=1 sh.. 100% n. 0,255 rm. fi 49557 ==. 0 49558 sh.. 0,2 srgb2rgb. rm. 49559 inpaint_pde.. [1],100%,1 rm. 49560 b $3% n 0,255 49561 sh 0,2 rgb2srgb. balance_gamma. ${4-6} rm. 49562 endl done 49563 49564#@gui Hypotrochoid : fx_hypotrochoid, fx_hypotrochoid(1) 49565#@gui : Periods = int(37,1,100) 49566#@gui : Outer Radius (%) = float(100,0,300) 49567#@gui : Inner Radius (%) = float(74,0,300) 49568#@gui : Distance to center (%) = float(80,0,300) 49569#@gui : Thickness (%) = float(0.5,0,5) 49570#@gui : Color = color(255,255,255,255) 49571#@gui : Anti-aliasing = bool(1) 49572#@gui : sep = separator() 49573#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/01/25</i>.</small>") 49574fx_hypotrochoid : 49575 {0,[w,h]*($10?1.5:1)} 49576 eval " 49577 const M = min(w,h)/2; 49578 const A = M*$2%; 49579 const B = A*$3%; 49580 const H = B*$4%; 49581 const S = M*$5%; 49582 const F = (A - B)/max(1e-5,B); 49583 const AmB = A - B; 49584 hypotrochoid(t) = (_t = t; round([ w/2 + AmB*cos(_t) + H*cos(F*_t), h/2 + AmB*sin(_t) - H*sin(F*_t) ])); 49585 49586 oX = hypotrochoid(t); 49587 dt = 1; 49588 for (t = 0, t<$1*2*pi, 49589 do ( 49590 X = hypotrochoid(t + dt); 49591 dist = abs(X[0] - oX[0]) | abs(X[1] - oX[1]); 49592 !dist?(dt*=2): 49593 dist>1?(dt/=1.25): 49594 (t+=dt), 49595 dist!=1; 49596 ); 49597 S<1?(I(X) = $9):ellipse(X,S,S,0,1,$9); 49598 oX = X; 49599 )" 49600 r. [0],[0],1,1,2 49601 channels. -3,0 sh. 0,2 fc. ${6-8} rm. 49602 blend[0,-1] alpha 49603 49604#@gui Lightning : fx_lightning, fx_lightning_preview 49605#@gui : note = note{"<small><b>Global parameters:</b></small>"} 49606#@gui : Number of Streaks = int(20,1,1024) 49607#@gui : Size (%) = float(90,0,150) 49608#@gui : Resolution = int(256,2,4096) 49609#@gui : Randomness = float(3,0,16) 49610#@gui : Smoothness = float(1.5,0,10) 49611#@gui : Balance = float(0.75,0,1) 49612#@gui : Color = color(255,255,255,255) 49613#@gui : Seed = int(0,0,65535) 49614#@gui : sep = separator() 49615#@gui : note = note{"<small><b>Initial streak:</b></small>"} 49616#@gui : XY-Coordinates (%) = point(50,5,0,1) 49617#@gui : Angle (deg) = float(0,-180,180) 49618#@gui : Thickness (px) = int(6,1,64) 49619#@gui : Blur = float(0.2,0,3) 49620#@gui : sep = separator() 49621#@gui : note = note{"<small><b>Auxiliary streaks:</b></small>"} 49622#@gui : Min Offset (%) = float(25,0,100) 49623#@gui : Max Offset (%) = float(60,0,100) 49624#@gui : Min Length (%) = float(95,0,200) 49625#@gui : Max Length (%) = float(100,0,200) 49626#@gui : Min Angle Deviation (deg) = float(30,0,180) 49627#@gui : Max Angle Deviation (deg) = float(40,0,180) 49628#@gui : Thickness Factor = float(-0.25,-1,1) 49629#@gui : Blur Factor = float(-0.1,-1,1) 49630#@gui : Opacity Factor = float(-0.20,-1,1) 49631#@gui : sep = separator() 49632#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/27/11</i>.</small>") 49633fx_lightning : 49634 repeat $! l[$<] 49635 100%,100% l. fact={max(w,h)/$3*$2%} srand $11 49636 repeat $1 49637 if $!<=1 49638 i=0 49639 new_level=1 49640 new_length=$3 49641 new_x=0 49642 new_y=0 49643 new_angle=$14 49644 else 49645 i={round(u(1,max(1,($!-1)*$6)))} 49646 level={$i,@-2} 49647 angle={$i,@-1} 49648 nb_points={$i,i[6]} 49649 p={round(($nb_points-2)*u($17%,$18%))} 49650 new_level={$level+1} 49651 new_length={max(2,round(($nb_points-$p)*u($19%,$20%)))} 49652 new_x={$i,i[8+3*$p]} 49653 new_y={$i,i[9+3*$p]} 49654 new_angle={$angle+u($21,$22)*if(u>0.5,1,-1)} 49655 fi 49656 49657 _fx_lightning $new_length,$4,$5 49658 r3d. 0,0,1,$new_angle 49659 +3d. $new_x,$new_y 49660 +*3d. $fact [0],[0] j3d. ..,$12%,$13%,0,1,1,0,0 rm.. 49661 49662 dilation={$15*(if($23>0,1.5,10)^($23*($new_level-1)))} 49663 blur={max(0,-1+(1+$16)*(if($24>0,2,5)^($24*($new_level-1))))} 49664 opacity={min(1,$10/255*(2^($25*($new_level-1))))} 49665 49666 dilate. $dilation b. $blur% n. 0,1 *. $opacity max[0,-1] 49667 ($new_level;$new_angle) a[-2,-1] y 49668 progress {($>*100)/($1-1)} 49669 done 49670 k[0] * 255 i[0] 100%,100%,1,3 fc[0] ${7-9} a c 49671 endl 49672 rv 49673 endl done 49674 49675fx_lightning_preview : 49676 repeat $! l[$>] 49677 fx_lightning $* rv blend alpha 49678 endl done 49679 49680_fx_lightning : 49681 l[] 49682 ({'CImg3d'},$1,{$1-1}) 49683 1,$1 noise. $2,1 cumulate. b. $3 shift. 0,1 1,100%,1,1,y 1,100% a[-3--1] x 49684 1,{h-1},1,1,2 +f. y ++. 1 a[-3--1] x 49685 4,100%,1,1,1 49686 y a y 49687 endl 49688 49689#@gui Lissajous : fx_lissajous, fx_lissajous(1) 49690#@gui : Resolution = int(4096,2,8192) 49691#@gui : sep = separator() 49692#@gui : X-Size = float(0.9,0,2) 49693#@gui : Y-Size = float(0.9,0,2) 49694#@gui : Z-Size = float(3,1,10) 49695#@gui : sep = separator() 49696#@gui : X-Multiplier = float(8,0,32) 49697#@gui : Y-Multiplier = float(7,0,32) 49698#@gui : Z-Multiplier = float(0,0,32) 49699#@gui : sep = separator() 49700#@gui : X-Offset = float(0,0,1) 49701#@gui : Y-Offset = float(0,0,1) 49702#@gui : Z-Offset = float(0,0,1) 49703#@gui : sep = separator() 49704#@gui : X-Angle = float(0,0,360) 49705#@gui : Y-Angle = float(0,0,360) 49706#@gui : Z-Angle = float(0,0,360) 49707#@gui : sep = separator() 49708#@gui : Thickness = float(0,0,50) 49709#@gui : Color = color(255,255,255,255) 49710#@gui : sep = separator() 49711#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/04</i>.</small>") 49712fx_lissajous : 49713 repeat $! l[$>] to_rgba 49714 {w},{h} 49715 f3d {0.5*max(w,h)/tan($4*pi/360)} 49716 lissajous3d $1,$5,$8,$6,$9,$7,$10 49717 r3d. 0,0,1,$13 r3d. 0,1,0,$12 r3d. 1,0,0,$11 49718 *3d. {0.5*$2*{-2,w}},{0.5*$3*{-2,h}},{0.5*$4*max({-2,w},{-2,h})} 49719 col3d. 1 j3d.. .,50%,50%,0,1,1,0,0 rm. 49720 distance. 1 >. $14% *.. . ==. 0 49721 r. 100%,100%,1,4 49722 sh. 0 *. $15 rm. 49723 sh. 1 *. $16 rm. 49724 sh. 2 *. $17 rm. 49725 sh. 3 *. $18 rm. 49726 +[-2,-1] 49727 endl done 49728 49729#@gui Mandelbrot - Julia Sets : fx_mandelbrot, fx_mandelbrot_preview 49730#@gui : X0 = value(-2) 49731#@gui : Y0 = value(-2) 49732#@gui : X1 = value(2) 49733#@gui : Y1 = value(2) 49734#@gui : note = note{"<small><b>Fractal Type:</b></small>"} 49735#@gui : Fractal Set = choice("Mandelbrot","Julia") 49736#@gui : Iterations = int(1024,16,65535) 49737#@gui : X-Seed (Julia) = float(0.317,-2,2) 49738#@gui : Y-Seed (Julia) = float(0.03,-2,2) 49739#@gui : sep = separator() 49740#@gui : note = note{"<small><b>Colormap:</b></small>"} 49741#@gui : Number of Colors = int(16,2,2048) 49742#@gui : Smoothness = int(8,1,256) 49743#@gui : Seed = int(255,0,65536) 49744#@gui : sep = separator() 49745#@gui : note = note{"<small><b>Navigation:</b></small>"} 49746#@gui : Zoom Center = point(50,50,0,0,255,255,255,200) 49747#@gui : Zoom Factor = float(0.25,0,1) 49748#@gui : Zoom In = button() 49749#@gui : Center = button() 49750#@gui : Zoom Out = button() 49751#@gui : Display Coordinates = bool(0) 49752#@gui : sep = separator() 49753#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/06/27</i>.</small>") 49754fx_mandelbrot : 49755 if !narg($_size) _size={max(w,h)} fi 49756 rm $_size,$_size 49757 mandelbrot ${1-4},$6,{$5?[1,$7,$8]:[0,0,0]} 49758 srand $11 $9,1,1,3 rand. 0,255 r. {$9*$10},1,1,3,3 point. 0 map.. .,3 rm. 49759 49760fx_mandelbrot_preview : 49761 _size={min(${-gui_preview_wh})} 49762 if "$15 || $16 || $17" 49763 x0,y0,x1,y1={"P0 = [${1,2}]; 49764 dP = [${3,4}] - P0; 49765 C = P0 + [${12,13}]%*dP; 49766 zfact = $14*($15?1:$16?0:-2); 49767 dC = 0.5*dP*(1 - 0.98*zfact); 49768 [C - dC,C + dC]"} 49769 status=\{$x0\}\{$y0\}\{$x1\}\{$y1\}\{$5\}\{$6\}\{$7\}\{$8\}\{$9\}\{$10\}\{$11\}\ 49770 \{50,50\}\{$14\}\{0\}\{0\}\{0\}\{$18\} 49771 px,py=50 49772 else 49773 x0,y0,x1,y1=${1-4} 49774 status= 49775 px,py=${12,13} 49776 fi 49777 fx_mandelbrot $x0,$y0,$x1,$y1,${5--1} 49778 49779 x0r,y0r,x1r,y1r={"C = ["$px,$py"]%*w; dC = 0.5*w*(1 - 0.98*$14); round([C - dC, C + dC - 1])"} 49780 rectangle $x0r,$y0r,$x1r,$y1r,0.7,0xF0F0F0F0,255,255,255,255 49781 rectangle $x0r,$y0r,$x1r,$y1r,0.7,0x0F0F0F0F,0,0,0,255 49782 if $18 to "Z0 = ( "{_$x0}" , "{_$y0}" )\nZ1 = ( "{_$x1}" , "{_$y1}" )",2,2,16 fi 49783 u $status 49784 49785#@gui Neon Lightning : fx_neon_lightning, fx_neon_lightning(1) 49786#@gui : Source (%) = point(50,50) 49787#@gui : R0 = float(0,0,100) 49788#@gui : Destination (%) = point(50,50) 49789#@gui : R1 = float(100,0,100) 49790#@gui : sep = separator() 49791#@gui : Density = int(50,1,512) 49792#@gui : Glow = float(0.7,0,5) 49793#@gui : Thickness = float(3,0,20) 49794#@gui : sep = separator() 49795#@gui : Color = color(130,80,50) 49796#@gui : Color Dispersion = float(0.25,0,1) 49797#@gui : Transparency = float(0,0,1) 49798#@gui : sep = separator() 49799#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/30/06</i>.</small>") 49800fx_neon_lightning : 49801 d={$13*255} 49802 repeat $! l[$>] 49803 100%,100%,1,4 rm[0] 49804 repeat $7 49805 x0={max(0,min(w,$1+u(-$3,$3)))} y0={max(0,min(h,$2+u(-$3,$3)))} 49806 x1={max(0,min(w,$4+u(-$6,$6)))} y1={max(0,min(h,$5+u(-$6,$6)))} 49807 u0={u(0,100)} v0={u(0,100)} u1={u(0,100)} v1={u(0,100)} 49808 R={max(0,min(255,u($10-$d,$10+$d)))} 49809 G={max(0,min(255,u($11-$d,$11+$d)))} 49810 B={max(0,min(255,u($12-$d,$12+$d)))} 49811 spline $x0%,$y0%,$u0%,$v0%,$x1%,$y1%,$u1%,$v1%,1,$R,$G,$B,1 49812 done 49813 s c,-3 49814 b[0] 3% 49815 distance. 1 *. -1 c. -{$9+1e-5},0 n. 0,1 sqrt. 49816 +b. $8%,1 n. 0,1 sqrt. n[-2,-1] 0,255 max[-2,-1] 49817 . blend[0,1] value 49818 smooth 5,0,1,0.5,2,10,0 49819 /. 255 ^. $14 *. 255 49820 a c c 0,255 49821 endl done 49822 49823#@gui Newton Fractal : fx_newton_fractal, fx_newton_fractal_preview 49824#@gui : X0 = value(-2) 49825#@gui : Y0 = value(-2) 49826#@gui : X1 = value(2) 49827#@gui : Y1 = value(2) 49828#@gui : note = note{"<span color="#EE5500"><b>Fractal Type:</b></span>"} 49829#@gui : Expression = choice(2,"Custom","z^^2 - 1","z^^3 - 1","z^^5 - 1","z^^6 + z^^3 - 1","z^^8 + 15*z^^4 - 1") 49830#@gui : p(z) = text{"rot(35°)*z^^3 - z^^2 + 1"}_1 49831#@gui : p'(z) = text{"3*z^^2 - 2*z"}_1 49832#@gui : p''(z) = text{"6*z - 2"}_1 49833#@gui : Descent method = choice(1,"Secant","Newton","Householder") 49834#@gui : Max iterations = int(200,16,1024) 49835#@gui : Precision = float(2,0,12) 49836#@gui : sep = separator() 49837#@gui : note = note{"<span color="#EE5500"><b>Rendering:</b></span>"} 49838#@gui : Coloring = choice(1,"By Custom Expression","By Iteration","By Value") 49839# 49840# Color by iteration 49841# 49842#@gui : Number of Colors = int(16,2,2048) 49843#@gui : Smoothness = int(8,1,256) 49844#@gui : Seed = int(255,0,65536) 49845# 49846# Color by value 49847# 49848#@gui : Colorspace = choice(2,"HSI","HSL","HSV")_0 49849#@gui : Hue min (%) = float(100,0,500)_0 49850#@gui : Hue max (%) = float(150,0,500)_0 49851#@gui : Lightness min (%) = float(20,0,500)_0 49852#@gui : Lightness max (%) = float(400,0,500)_0 49853# 49854# Custom coloring 49855# 49856#@gui : Colorspace = choice(3,"RGB,"HSI","HSL","HSV","Lab")_0 49857#@gui : Pre-Process = choice(2,"None","Equalize","Normalize","Equalize and Normalize")_0+ 49858#@gui : note = note{"<small><span color="#EE5500"><b>Tips for Custom expressions:</b></span>\n 49859#@gui : - Variables <b>i0,i1</b> stand for the real and imaginary parts of the iterated complex number.\n 49860#@gui : - Variable <b>i2</b> is the number of iterations required for convergence.\n 49861#@gui : - Variable <b>z</b> is the complex number with value <b>[ i0,i1 ]</b>.\n 49862#@gui : - Functions <b>p(z), dp(z)</b> and <b>d2p(z)</b> are the expressions used for computing the fractal. 49863#@gui : </small>"} 49864#@gui : Channel #1 = text{"carg(-z)"}_0 49865#@gui : Channel #2 = text{"(i0 + i1)/2"}_0 49866#@gui : Channel #3 = text{"10*(i2^0.4)"}_0 49867#@gui : Post-Process = choice(0,"None","Equalize","Normalize","Equalize and Normalize")_0 49868# 49869# Basic color adujstment 49870# 49871#@gui : Brightness (%) = float(0,-100,100) 49872#@gui : Contrast (%) = float(0,-100,100) 49873#@gui : Gamma (%) = float(0,-100,100) 49874#@gui : Hue (%) = float(0,-100,100) 49875#@gui : Saturation (%) = float(0,-100,100) 49876#@gui : Equalization (%) = float(0,0,100) 49877#@gui : Anti-aliasing = choice(2,"x1","x1.5","x2","x2.5","x3","x3.5","4") 49878#@gui : note = note{"<small><b>Note:</b> Anti-aliasing is applied on final rendering only, not on preview.</small>"} 49879#@gui : antialias_note = value(0)_2- 49880#@gui : sep = separator() 49881# 49882# Navigation 49883# 49884#@gui : note = note{"<span color="#EE5500"><b>Navigation:</b></span>"} 49885#@gui : Zoom Center = point(50,50,0,0,255,255,255,200) 49886#@gui : Zoom Factor = float(0.5,0,1) 49887#@gui : Angle = float(0,-180,180) 49888#@gui : Zoom In = button() 49889#@gui : Center = button() 49890#@gui : Zoom Out = button() 49891#@gui : Reset View = button() 49892#@gui : Display Coordinates on Preview Window = bool(1) 49893#@gui : Preview subsampling = choice(2,"None","x1.5","x2","x2.5","x3","x3.5","x4") 49894#@gui : sep = separator() 49895#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/01/09</i>.</small>") 49896fx_newton_fractal : skip "${6=},${7=},${8=},${22=},${25=},${28=}" 49897 repeat $! l[$>] 49898 if !narg($_size) _size={max(w,h)} fi 49899 rm 49900 antialias={arg(1+$33,1,1.5,2,2.5,3,3.5,4)} 49901 {$antialias*[$_size,$_size]} 49902 if $5==1 49903 pz="z^^2 - 1" dpz="2*zn" d2pz="2" 49904 elif $5==2 49905 pz="z^^3 - 1" dpz="3*z^^2" d2pz="6*z" 49906 elif $5==3 49907 pz="z^^5 - 1" dpz="5*z^^4" d2pz="20*z^^3" 49908 elif $5==4 49909 pz="z^^6 + z^^3 - 1" dpz="6*z^^5 + 3*z^^2" d2pz="30*z^^4 + 6*z" 49910 elif $5==5 49911 pz="z^^8 + 15*z^^4 - 1" dpz="8*z^^7 + 60*z^^3" d2pz="56*z^^6 + 180*z^^2"; 49912 else 49913 pz="$6" dpz="$7" d2pz="$8" 49914 fi 49915 if !narg($pz) pz="[1,0]" fi 49916 if !narg($dpz) dpz="[1,0]" fi 49917 if !narg($d2pz) d2pz="[1,0]" fi 49918 49919 newton_fractal ${1-4},$38,$9,$10,{10^-$11},$pz,$dpz,$d2pz 49920 49921 if $12==1 # Color by iteration 49922 channels 100% 49923 srand $15 $13,1,1,3 rand. 0,255 r. {$13*$14},1,1,3,3 point. 0 map.. .,3 rm. 49924 49925 elif $12==2 # Color by value 49926 f "[ atan2(i1,i0),1,i2 ]" s c n... {[$17,$18]*360%} n. {[$19,$20]%} c. 0,1 a c 49927 ${"arg 1+$16,hsi,hsl,hsv"}2rgb 49928 49929 else # Custom coloring 49930 49931 if $22 # Pre-process values 49932 s c,-2 49933 if $22&1 equalize 1024 fi 49934 if $22&2 /[-2] {-2,max(1e-5,abs(im),abs(iM))} n. 0,1 fi 49935 a c 49936 fi 49937 49938 f "*begin( 49939 p(z) = ("$pz"); 49940 dp(z) = ("$dpz"); 49941 d2p(z) = ("$d2pz"); 49942 ); 49943 z = [ i0,i1 ]; 49944 [ (0;$23),(0;$24),(0;$25) ]" 49945 49946 if $26 # Post-process values 49947 s c 49948 if $26&1 equalize 1024 fi 49949 if $26&2 normalize 0,1 fi 49950 a c 49951 fi 49952 49953 * 255 mod 256 49954 if $21 ${"arg $21,hsi8,hsl8,hsv8,lab8"}2rgb fi # Convert to RGB colors 49955 fi 49956 49957 r2dx $_size 49958 49959 if $32 ac "+equalize 1024 j.. .,0,0,0,0,{$32%} rm.",ycbcr_y fi 49960 adjust_colors ${27-31},0,0,0,255 49961 endl done 49962 49963fx_newton_fractal_preview : skip "${6=},${7=},${8=},${22=},${25=},${28=}" 49964 is_custom_expression={$5==0?2:1} 49965 is_color_by_custom={$12==0?2:0} 49966 is_color_by_iter={$12==1?2:0} 49967 is_color_by_value={$12==2?2:0} 49968 _size0={min(${-gui_preview_wh})} 49969 _size={$_size0/arg(1+$44,1,1.5,2,2.5,3,3.5,4)} 49970 49971 angle=$38 49972 if "$39 || $40 || $41" 49973 x0,y0,x1,y1={"P0 = [${1,2}]; 49974 dP = [${3,4}] - P0; 49975 M = P0 + 0.5*dP; 49976 C = P0 + [${35,36}]%*dP; 49977 C = M + rot(-$38°)*(C - M); 49978 zfact = $37*($39?1:$40?0:-2); 49979 dC = 0.5*dP*(1 - 0.98*zfact); 49980 [ C - dC, C + dC ]"} 49981 px,py=50 49982 elif $42 49983 x0,y0,x1,y1=-2,-2,2,2 49984 px,py=50 49985 angle=0 49986 else 49987 x0,y0,x1,y1=${1-4} 49988 px,py=${35,36} 49989 fi 49990 fx_newton_fractal $x0,$y0,$x1,$y1,$5,"$6","$7","$8",${9-22},"$23","$24","$25",${26-32},0,${34-37},$angle,${39--1} 49991 49992 repeat $! l[$>] 49993 r2dx $_size0,1 49994 x0r,y0r,x1r,y1r={"C = [ "$px,$py" ]%*w; dC = 0.5*w*(1 - 0.98*$37); round([ C - dC, C + dC - 1 ])"} 49995 rectangle $x0r,$y0r,$x1r,$y1r,0.7,0xF0F0F0F0,255,255,255,255 49996 rectangle $x0r,$y0r,$x1r,$y1r,0.7,0x0F0F0F0F,0,0,0,255 49997 if $43 to "Z0 = ( "{_$x0}" , "{_$y0}" )\nZ1 = ( "{_$x1}" , "{_$y1}" )",2,2,16 fi 49998 endl done 49999 50000 u "{"$x0"}{"$y0"}{"$x1"}{"$y1"}{$5}"\ 50001 "{$6}_"$is_custom_expression\ 50002 "{$7}_"$is_custom_expression\ 50003 "{$8}_"$is_custom_expression\ 50004 "{$9}{$10}{$11}{$12}"\ 50005 "{$13}_"$is_color_by_iter\ 50006 "{$14}_"$is_color_by_iter\ 50007 "{$15}_"$is_color_by_iter\ 50008 "{$16}_"$is_color_by_value\ 50009 "{$17}_"$is_color_by_value\ 50010 "{$18}_"$is_color_by_value\ 50011 "{$19}_"$is_color_by_value\ 50012 "{$20}_"$is_color_by_value\ 50013 "{$21}_"$is_color_by_custom\ 50014 "{$22}_"$is_color_by_custom\ 50015 "{$23}_"$is_color_by_custom\ 50016 "{$24}_"$is_color_by_custom\ 50017 "{$25}_"$is_color_by_custom\ 50018 "{$26}_"$is_color_by_custom\ 50019 "{$27}{$28}{$29}{$30}{$31}{$32}{$33}"\ 50020 "{$34}"_{$33==0?0:2}\ 50021 "{"$px,$py"}{$37}{"$angle"}{0}{0}{0}{0}{$43}{$44}" 50022 50023#@gui Plasma : fx_plasma, fx_plasma(0) 50024#@gui : Alpha = float(0.5,0,5) 50025#@gui : Beta = float(0,0,100) 50026#@gui : Scale = int(8,2,10) 50027#@gui : Randomize = bool(0) 50028#@gui : Transparency = bool(0) 50029#@gui : Color Balance = color(128,128,128) 50030#@gui : sep = separator() 50031#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/20/03</i>.</small>") 50032fx_plasma : skip ${4=0},${5=0} 50033 if $5 to_rgba else to_rgb fi 50034 if $4 rand 0,255 fi 50035 plasma $1,$2,$3 n 0,255 50036 balance_gamma ${6-8} 50037 50038#@gui Quick Copyright : fx_quick_copyright, fx_quick_copyright(0) 50039#@gui : Text = text{"\\251 G'MIC"} 50040#@gui : Size = int(27,13,128) 50041#@gui : Color = color(255,255,255,128) 50042#@gui : Outline = int(1,0,4) 50043#@gui : Position = choice(3,"Up-Left","Up-Right","Bottom-Left","Bottom-Right") 50044#@gui : Offset = int(5,0,40) 50045#@gui : Orientation = choice(1,"-90 deg.","0 deg.","+90 deg.","+180 deg.") 50046#@gui : sep = separator() 50047#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 50048fx_quick_copyright : 50049 i[0] 0 t[0] "$1",0,0,$2,1,$3,$4,$5 autocrop[0] 0 r[0] {{0,w}+2*$7},{{0,h}+2*$7},1,3,0,0,0.5,0.5 50050 i[1] 0 t[1] "$1",0,0,$2,1,1 autocrop[1] 0 r[1] {{1,w}+2*$7},{{1,h}+2*$7},1,1,0,0,0.5,0.5 dilate[1] {1+2*$7} 50051 rotate[0,1] {90*($10-1)} 50052 repeat $!-2 50053 if $8==0 j. [0],$9,$9,0,0,{$6/255},[1] 50054 elif $8==1 j. [0],{w-1-{0,w}-$9},$9,0,0,{$6/255},[1] 50055 elif $8==2 j. [0],$9,{h-1-{0,h}-$9},0,0,{$6/255},[1] 50056 else j. [0],{w-1-{0,w}-$9},{h-1-{0,h}-$9},0,0,{$6/255},[1] 50057 fi 50058 mv. 2 done 50059 rm[0,1] 50060 50061#@gui Rainbow : fx_rainbow, fx_rainbow 50062#@gui : Left Position = float(80,0,100) 50063#@gui : Right Position = float(80,0,100) 50064#@gui : Left Slope = float(175,0,400) 50065#@gui : Right Slope = float(175,0,400) 50066#@gui : Thinness = float(3,0.1,8) 50067#@gui : Opacity = float(80,0,199) 50068#@gui : sep = separator() 50069#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 50070fx_rainbow : 50071 repeat $! l[$>] 50072 100%,100% spline. 0,$1%,100,{-$3}%,100%,$2%,100,$4%,1,1 50073 flood. 0,0,0,0,0,1,1 flood. {w-1},0,0,0,0,1,1 50074 distance. 0 c. 0,255 n. 0,{$5*255} 50075 palette rainbow +luminance. c. 0,{min(100,200-$6)}% n. 0,255 a[-2,-1] c 50076 map.. . rm. 50077 if $6<100 sh. 3 *. {$6/100} rm. fi 50078 blend alpha 50079 endl done 50080 50081#@gui Shade Bobs : fx_shadebobs, fx_shadebobs 50082#@gui : note = note("<small>Bobs parameters :</small>") 50083#@gui : Density = int(50,1,200) 50084#@gui : Radius = int(5,1,100) 50085#@gui : Duration = int(200,1,500) 50086#@gui : Velocity = float(1,0,10) 50087#@gui : sep = separator() 50088#@gui : note = note("<small>Curve parameters :</small>") 50089#@gui : Rx = float(-1,-3,3) 50090#@gui : Ry = float(2,-3,3) 50091#@gui : Rz = float(1,-3,3) 50092#@gui : Rt = float(0.8,-3,3) 50093#@gui : Rcx = float(0,-3,3) 50094#@gui : Colormap = choice(8,"Grayscale","Standard","HSV","Lines","Hot","Cool","Jet","Flag","Cube") 50095#@gui : sep = separator() 50096#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/18/04</i>.</small>") 50097fx_shadebobs : 50098 channels 0 f 0 50099 repeat $! l[$>] 50100 t=0 50101 repeat $3 50102 repeat $1 50103 r={$6+$5*cos(6*$7*$t)+(1-$5)*sin(6*$8*$t)} 50104 a={(360*sin($7*$t)+30*$6*$>)*pi/180} 50105 ax={2*$>*pi/$1+$t} 50106 cx={(1+$9*cos($ax)+$r*cos($a))*w/2} 50107 cy={(1+$9*sin($ax)+$r*sin($a))*h/2} 50108 ellipse. $cx,$cy,$2%,$2%,0,-1,1 50109 done 50110 t+={$4%} 50111 done 50112 endl done 50113 & 255 if $10 map {$10-1} fi 50114 50115#@gui Sine Curve : fx_sine_curve, fx_sine_curve_preview 50116#@gui : note = note("<span color="#EE5500"><b>Curve parameters:</b></span>") 50117#@gui : Preset = choice{1,"Default (Circle)","Alien Rasta","All Round","Carnivorous Plant","Cat Pad","Flower", 50118#@gui : "Flower Cushion","Fly Karateka","Hearts","Moving Leaf","Radioactive Flower","Rosace","Spaceship", 50119#@gui : "Transformer","Tubular Waves","Twisted Heart","Twisted Heart 2","Twisted Tunnel","Waterslide"} 50120#@gui : Previous Preset = value(-1) 50121#@gui : Resolution (%) = float(75,0,100) 50122#@gui : Periods = float(1,0,3) 50123#@gui : sep = separator() 50124#@gui : Parameter Settings = choice(1,"Ratios","Multipliers","Offsets","Exponents","Signs","3D Angles") 50125#@gui : note = note("<small><span color="#EE0055"><b>Ratios:</b></span></small>") 50126#@gui : Xa/Xb = float(0.5,0,1)_0- 50127#@gui : Ya/Yb = float(0.5,0,1)_0 50128#@gui : Za/Zb = float(0.5,0,1)_0 50129#@gui : note = note("<small><span color="#EE0055"><b>Multipliers:</b></span></small>") 50130#@gui : Xa-Multiplier = int(1,0,1024)_2- 50131#@gui : Ya-Multiplier = int(1,0,1024)_2 50132#@gui : Za-Multiplier = int(0,0,1024)_2 50133#@gui : Xb-Multiplier = int(800,0,1024)_2 50134#@gui : Yb-Multiplier = int(800,0,1024)_2 50135#@gui : Zb-Multiplier = int(1,0,1024)_2 50136#@gui : note = note("<small><span color="#EE0055"><b>Offsets:</b></span></small>") 50137#@gui : Xa-Offset (deg.) = float(90,0,360)_0- 50138#@gui : Ya-Offset (deg.) = float(0,0,360)_0 50139#@gui : Za-Offset (deg.) = float(0,0,360)_0 50140#@gui : Xb-Offset (deg.) = float(90,0,360)_0 50141#@gui : Yb-Offset (deg.) = float(0,0,360)_0 50142#@gui : Zb-Offset (deg.) = float(0,0,360)_0 50143#@gui : note = note("<small><span color="#EE0055"><b>Exponents:</b></span></small>") 50144#@gui : Xa-Exponent = float(1,0,32)_0- 50145#@gui : Ya-Exponent = float(1,0,32)_0 50146#@gui : Za-Exponent = float(1,0,32)_0 50147#@gui : Xb-Exponent = float(1,0,32)_0 50148#@gui : Yb-Exponent = float(1,0,32)_0 50149#@gui : Zb-Exponent = float(1,0,32)_0 50150#@gui : note = note("<small><span color="#EE0055"><b>Signs:</b></span></small>") 50151#@gui : Xa-Sign = choice("Preserve","Invert","Negative","Positive")_0- 50152#@gui : Ya-Sign = choice("Preserve","Invert","Negative","Positive")_0 50153#@gui : Za-Sign = choice("Preserve","Invert","Negative","Positive")_0 50154#@gui : Xb-Sign = choice("Preserve","Invert","Negative","Positive")_0 50155#@gui : Yb-Sign = choice("Preserve","Invert","Negative","Positive")_0 50156#@gui : Zb-Sign = choice("Preserve","Invert","Negative","Positive")_0 50157#@gui : note = note("<small><span color="#EE0055"><b>3D Angles:</b></span></small>") 50158#@gui : X-Angle (deg.) = float(0,-180,180)_0- 50159#@gui : Y-Angle (deg.) = float(0,-180,180)_0 50160#@gui : Z-Angle (deg.) = float(0,-180,180)_0 50161#@gui : Zoom = float(1,0,10)_0 50162#@gui : Focale = int(8,1,20)_0 50163#@gui : sep = separator() 50164#@gui : note = note("<span color="#EE5500"><b>Rendering parameters:</b></span>") 50165#@gui : Center = point(50,50,0,1,0,238,85,-170,10)_0 50166#@gui : Old X-Center = value(50) 50167#@gui : Old Y-Center = value(50) 50168#@gui : Radius = point(68,68,0,1,238,0,85,-170,10)_0 50169#@gui : Angle = point(75,50,0,1,238,85,0,-170,10)_0 50170#@gui : Old X-Angle = value(75) 50171#@gui : Old Y-Angle = value(50) 50172#@gui : Primary radius (%) = float(3,0,100) 50173#@gui : Secondary radius (%) = float(2,0,100) 50174#@gui : Opacity (%) = float(40,0,100) 50175#@gui : Color = color(255,255,255) 50176#@gui : Anti-aliasing = choice(2,"None","× 1.25","× 1.5","× 2","× 3") 50177#@gui : sep = separator() 50178#@gui : Preview background = choice(1,"Image","Black","White") 50179#@gui : sep = separator() 50180#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/03/04</i>.</small>") 50181fx_sine_curve : 50182 50183 # Get parameters as named variables. 50184 preset,previous_preset,\ 50185 resolution,periods,dp,\ 50186 ratx,raty,ratz,\ 50187 mxa,mya,mza,mxb,myb,mzb,\ 50188 oxa,oya,oza,oxb,oyb,ozb,\ 50189 pxa,pya,pza,pxb,pyb,pzb,\ 50190 sxa,sya,sza,sxb,syb,szb,\ 50191 rotx,roty,rotz,zoom,focale,\ 50192 xc,yc,prev_xc,prev_yc,xr,yr,xa,ya,prev_xa,prev_ya,\ 50193 radius1,radius2,opacity,\ 50194 colR,colG,colB,\ 50195 antialiasing,\ 50196 preview_background=$* 50197 50198 if !narg($_is_preview) _is_preview=0 fi 50199 if [$prev_xc,$prev_yc]!=[$xc,$yc] 50200 xr,yr,xa,ya,prev_xa,prev_ya+={d=[$xc,$yc]-[$prev_xc,$prev_yc];[d,d,d]} 50201 fi 50202 if [$prev_xa,$prev_ya]!=[$xa,$ya] 50203 delta_a={" 50204 a = [ "$xa" - "$xc", "$ya" - "$yc" ]; 50205 b = [ "$prev_xa" - "$xc", "$prev_ya" - "$yc" ]; 50206 (atan2(a[1],a[0]) - atan2(b[1],b[0]))*180/pi; 50207 "} 50208 xr,yr={[$xc,$yc]+rot($delta_a°)*[$xr-$xc,$yr-$yc]} 50209 else delta_a=0 fi 50210 if [$colR,$colG,$colB]==[0,0,0]" && "$preview_background==1 colR,colG,colB=255 50211 elif [$colR,$colG,$colB]==[255,255,255]" && "$preview_background==2 colR,colG,colB=0 50212 fi 50213 50214 # Manage presets. 50215 update_params=0 50216 if $preset!=$previous_preset 50217 50218 # Set default parameters for presets ('Default (Circle)'). 50219 periods=1 50220 ratx,raty,ratz=0.5,0.5,0 50221 mxa,mxb,mya,myb,mza,mzb=1,1,1,1,0,1 50222 oxa,oxb,oya,oyb,oza,ozb=90,90,0,0,0,0 50223 pxa,pxb,pya,pyb,pza,pzb=1 50224 sxa,sxb,sya,syb,sza,szb=0 50225 rotx,roty,rotz,zoom,focale=0,0,0,2,8 50226 50227 # Set specific values for each preset. 50228 50229 # Default (circle) 50230 if $preset==0 50231 ratx,raty,ratz=0 zoom=1 50232 # Alien Rasta 50233 elif $preset==1 50234 mxa,mxb,mya,myb=1,800,1,800 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 oxa,oxb,oya,oyb=90,90,0,60 50235 # All Round 50236 elif $preset==2 50237 mxa,mxb,mya,myb=1,200,1,150 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50238 # Carnivorous Plant 50239 elif $preset==3 50240 mxa,mxb,mya,myb=9,512,1024,9 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50241 # Cat Pad 50242 elif $preset==4 50243 mxa,mxb,mya,myb=80,1,80,1 pxa,pxb,pya,pyb=1,3,1,3 50244 # Flower 50245 elif $preset==5 50246 ratz=0.8 mza,mzb=7,1024 pza,pzb=1.6,2 rotz=45 zoom=1 focale=4 50247 # Flower Cushion 50248 elif $preset==6 50249 mxa,mxb,mya,myb=80,1,1,80 pxa,pxb,pya,pyb=1,3,1,3 50250 # Fly Karateka 50251 elif $preset==7 50252 mxa,mxb,mya,myb=150,1,1,100 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50253 # Hearts 50254 elif $preset==8 50255 mxa,mxb,mya,myb=1,80,80,80 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50256 # Moving Leaf 50257 elif $preset==9 50258 mxa,mxb,mya,myb=2,200,200,1 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50259 # Radioactive Flower 50260 elif $preset==10 50261 mxa,mxb,mya,myb=1,800,1,800 pxa,pxb,pya,pyb=1,3,1,3 50262 # Rosace 50263 elif $preset==11 50264 mxa,mxb,mya,myb=1,10,1,10 50265 # Spaceship 50266 elif $preset==12 50267 mxa,mxb,mya,myb=1,400,1,200 pxa,pxb,pya,pyb=1,3,1,3 sxa,sxb,sya,syb=1,1,0,0 50268 # Transformer 50269 elif $preset==13 50270 mxa,mxb,mya,myb=1,800,800,2 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50271 # Tubular Waves 50272 elif $preset==14 50273 mxa,mxb,mya,myb=1,30,1,60 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50274 # Twisted Heart 50275 elif $preset==15 50276 mxa,mxb,mya,myb=500,1,1,500 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50277 # Twisted Heart 2 50278 elif $preset==16 50279 mxa,mxb,mya,myb=1,80,80,1 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50280 # Twisted Tunnel 50281 elif $preset==17 50282 mxa,mxb,mya,myb=1,80,1,40 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50283 # Waterslide 50284 elif $preset==18 50285 ratx=0.6 mxa,mxb,mya,myb=9,400,200,9 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 50286 fi 50287 fi 50288 50289 # Change unit for some variables. 50290 W,H={w#0?[w#0,h#0]:0$_is_preview" && "0$_preview_width?[0$_preview_width,0$_preview_height]:[1024,1024]} 50291 nresolution={max(1,round($periods*1000000*($resolution%)^2))} 50292 nfocale={arg($focale,0.05,0.1,0.2,0.3,0.4,0.5,0.75,1,1.25,1.5,1.75,2,3,4,8,16,32,128,1024,16384)} 50293 noxa,noxb,noya,noyb,noza,nozb={[$oxa,$oxb,$oya,$oyb,$oza,$ozb]*pi/180} 50294 nantialiasing={arg0($antialiasing,1,1.25,1.5,2,3)} 50295 rW,rH={[$W,$H]*$nantialiasing} # Size of the non-antialiased rendering 50296 50297 # Generate and render curve. 50298 l[] 50299 50300 # Compute curve coordinates. 50301 $nresolution,1,1,2,"* 50302 begin( 50303 const is_rot = "$rotx" || "$roty" || "$rotz"; 50304 ref(rot(1,0,0,"$rotx"°),Rx); 50305 ref(rot(0,1,0,"$roty"°),Ry); 50306 ref(rot(0,0,1,"$rotz"°),Rz); 50307 R = mul(Rz,mul(Ry,Rx,3),3); # 3D rotation 50308 50309 # Variables to manage 2D rotation. 50310 const ang = atan2("$ya" - "$yc","$xa" - "$xc"); 50311 const cosa = cos(ang); 50312 const sina = sin(ang); 50313 50314 # Variables to manage aspect ratio. 50315 const c = 35; 50316 const dxr0 = "$xr" - "$xc"; 50317 const dyr0 = "$yr" - "$yc"; 50318 const dxr = cosa*dxr0 + sina*dyr0; 50319 const dyr = -sina*dxr0 + cosa*dyr0; 50320 const _dx = abs(dxr)/c; const dx = 2.5*c*(_dx<1?_dx:_dx^3); 50321 const _dy = abs(dyr)/c; const dy = 2.5*c*(_dy<1?_dy:_dy^3); 50322 ); 50323 50324 cpow(x,p,s) = ( 50325 ref(x,_x); 50326 (!s?sign(_x):s==1?-sign(_x):s==2?-1:1)*abs(_x)^p 50327 ); 50328 50329 t = x/w*2*pi*"$periods"; 50330 X = lerp(cpow(sin("$mxa"*t + "$noxa"),"$pxa","$sxa"), 50331 cpow(sin("$mxb"*t + "$noxb"),"$pxb","$sxb"), 50332 "$ratx"); 50333 Y = lerp(cpow(sin("$mya"*t + "$noya"),"$pya","$sya"), 50334 cpow(sin("$myb"*t + "$noyb"),"$pyb","$syb"), 50335 "$raty"); 50336 Z = lerp(cpow(sin("$mza"*t + "$noza"),"$pza","$sza"), 50337 cpow(sin("$mzb"*t + "$nozb"),"$pzb","$szb"), 50338 "$ratz"); 50339 50340 # Set aspect ratio and rotate. 50341 X*=dx%; 50342 Y*=dy%; 50343 is_rot?(P = R*[ X,Y,Z ]; X = P[0]; Y = P[1]; Z = P[2]); 50344 50345 # 2D projection. 50346 X*="$nfocale"; 50347 Y*="$nfocale"; 50348 Z = max(1e-5,Z + 1 + "$nfocale"); 50349 pX = X/Z; 50350 pY = -Y/Z; 50351 50352 # Normalize and get display coordinates. 50353 ang?(X = cosa*pX - sina*pY; pY = sina*pX + cosa*pY; pX = X); 50354 50355 const ax = "$zoom*$rW"; const bx = "$xc*$rW"%; 50356 const ay = "$zoom*$rH"; const by = "$yc*$rH"%; 50357 [ ax*pX + bx, ay*pY + by ]" 50358 50359 # Draw curve (as an alpha-channel). 50360 $rW,$rH 50361 eval.. "* 50362 const mwh = min(w#-1,h#-1)*5%; 50363 const r1 = max(0.01,mwh*"$radius1"%); 50364 const r2 = max(0.01,mwh*"$radius2"%); 50365 const Mr = max(r1,r2); 50366 const opacity = ("$opacity"%)^3; 50367 50368 X = R; Y = G; 50369 50370 Mr<0?( 50371 i(#-1,X,Y) = lerp(i(#-1,X,Y),1,opacity); 50372 ):( 50373 pX = i(x - 1,0,0,0); 50374 pY = i(x - 1,0,0,1); 50375 dX = X - pX; 50376 dY = Y - pY; 50377 ang = atan2(dY,dX)*180/pi; 50378 ellipse(#-1,X,Y,r1,r2,ang°,opacity,255); 50379 ); 50380 I" 50381 rm.. 50382 r. $W,$H,1,1,2 n 0,255 50383 i[0] 100%,100%,1,3 fc[0] $colR,$colG,$colB 50384 a[-2,-1] c 50385 endl 50386 50387 if 0$_is_preview 50388 if $!==1 i[0] $W,$H,1,3 fi 50389 if $preview_background [0],[0] f. {$preview_background==1?0:255} to_rgb. rv[0,-1] rm. fi 50390 blend[0,-1] alpha 50391 line. $xc%,$yc%,$xr%,$yr%,0.75,0xF0F0F0F0,238,0,85 50392 line. $xc%,$yc%,$xr%,$yr%,0.75,0x0F0F0F0F,255 50393 line. $xc%,$yc%,$xa%,$ya%,0.75,0xF0F0F0F0,238,85,0 50394 line. $xc%,$yc%,$xa%,$ya%,0.75,0x0F0F0F0F,0 50395 fi 50396 mv. 0 50397 if 0$_output_mode k[0] fi 50398 50399 # Update parameter values. 50400 r,m,o,p,s,a={d=$dp;[d==0?2:0,d==1?2:0,d==2?2:0,d==3?2:0,d==4?2:0,d==5?2:0]} 50401 u "{"$preset"}{"$preset"}{"$resolution"}{"$periods"}{"$dp"}"\ 50402 "{"$ratx"}_"$r"{"$raty"}_"$r"{"$ratz"}_"$r\ 50403 "{"$mxa"}_"$m"{"$mya"}_"$m"{"$mza"}_"$m"{"$mxb"}_"$m"{"$myb"}_"$m"{"$mzb"}_"$m\ 50404 "{"$oxa"}_"$o"{"$oya"}_"$o"{"$oza"}_"$o"{"$oxb"}_"$o"{"$oyb"}_"$o"{"$ozb"}_"$o\ 50405 "{"$pxa"}_"$p"{"$pya"}_"$p"{"$pza"}_"$p"{"$pxb"}_"$p"{"$pyb"}_"$p"{"$pzb"}_"$p\ 50406 "{"$sxa"}_"$s"{"$sya"}_"$s"{"$sza"}_"$s"{"$sxb"}_"$s"{"$syb"}_"$s"{"$szb"}_"$s\ 50407 "{"$rotx"}_"$a"{"$roty"}_"$a"{"$rotz"}_"$a"{"$zoom"}_"$a"{"$focale"}_"$a\ 50408 "{"$xc,$yc"}{"$xc"}{"$yc"}{"$xr,$yr"}{"$xa,$ya"}{"$xa"}{"$ya"}{"$radius1"}{"$radius2"}{"$opacity"}"\ 50409 "{"$colR,$colG,$colB"}{"$antialiasing"}"\ 50410 "{"$preview_background"}" 50411 50412fx_sine_curve_preview : 50413 _is_preview=1 50414 fx_sine_curve $* 50415 k[0] 50416 50417#@gui Superformula : fx_superformula, fx_superformula(1) 50418#@gui : Resolution = int(4096,2,8192) 50419#@gui : sep = separator() 50420#@gui : X-Size = float(0.9,0,2) 50421#@gui : Y-Size = float(0.9,0,2) 50422#@gui : sep = separator() 50423#@gui : M = int(8,1,32) 50424#@gui : N1 = float(1,-32,32) 50425#@gui : N2 = float(5,-32,32) 50426#@gui : N3 = float(8,-32,32) 50427#@gui : sep = separator() 50428#@gui : X-Angle = float(0,0,360) 50429#@gui : Y-Angle = float(0,0,360) 50430#@gui : Z-Angle = float(0,0,360) 50431#@gui : sep = separator() 50432#@gui : Thickness = float(3,0,50) 50433#@gui : Color = color(128,255,128,255) 50434#@gui : sep = separator() 50435#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/04</i>.</small>") 50436fx_superformula : 50437 repeat $! l[$>] to_rgba 50438 {w},{h} 50439 f3d {0.5*max(w,h)/tan($4*pi/360)} 50440 superformula3d $1,${4-7} 50441 r3d. 0,0,1,$10 r3d. 0,1,0,$9 r3d. 1,0,0,$8 50442 *3d. {0.5*$2*{-2,w}},{0.5*$3*{-2,h}} 50443 col3d. 1 j3d.. .,50%,50%,0,1,1,0,0 rm. 50444 distance. 1 >. $11% *.. . ==. 0 50445 r. 100%,100%,1,4 50446 sh. 0 *. $12 rm. 50447 sh. 1 *. $13 rm. 50448 sh. 2 *. $14 rm. 50449 sh. 3 *. $15 rm. 50450 +[-2,-1] 50451 endl done 50452 50453#@gui Symmetric 2D Shape : fx_symmetric_shape2d, fx_symmetric_shape2d_preview(1) 50454#@gui : Subdivisions = int(5,2,32) 50455#@gui : Center = point(50,50,0,1,255,255,255,128) 50456#@gui : Old Center = value(50,50) 50457#@gui : Angle / Size = point(50,30,0,1,255,255,255,128) 50458#@gui : Old Angle / Size = value(50,30) 50459#@gui : sep = separator() 50460#@gui : Control Point 1 = point(50,25,1,1,255,128,0,255,4) 50461#@gui : Control Point 2 = point(56,42,1,1,255,128,0,255,4) 50462#@gui : Control Point 3 = point(52,52,-1,1,255,128,0,255,4) 50463#@gui : Control Point 4 = point(52,52,-1,1,255,128,0,255,4) 50464#@gui : Control Point 5 = point(52,52,-1,1,255,128,0,255,4) 50465#@gui : Control Point 6 = point(52,52,-1,1,255,128,0,255,4) 50466#@gui : sep = separator() 50467#@gui : Drawing Mode = choice(1,"Outlined","Filled") 50468#@gui : Color = color(255,0,255) 50469#@gui : Opacity (%) = float(100,0,100) 50470#@gui : sep = separator() 50471#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/06/17</i>.</small>") 50472fx_symmetric_shape2d : 50473 if !narg($_is_preview) _is_preview=0 fi 50474 repeat $! l[$<] 50475 100%,100%,1,4 _fx_symmetric_shape2d. $* rv 50476 if !0$_is_preview" && "0$_output_mode rm. fi 50477 endl done 50478 50479_fx_symmetric_shape2d : 50480 (${10-21}) f. "isnan(i)?-1024:i" discard. -1024 r. 2,{h/2},1,1,-1 permute. cyzx 50481 f. "x = R - $2; y = G - $3; [ atan2(y,x), norm(x,y) ]" 50482 l. n={h} .x{$1-1} a y f "const pi2 = 2*pi; [ (R + int(y/"$n")*pi2/$1)%pi2, G ]" sort +,y endl 50483 f. "[ $2*w#-2,$3*h#-2 ]/100 + [ G*cos(R), G*sin(R) ]*(min(w#-2,h#-2)-1)%" permute. cyzx 50484 coords={^} rm. 50485 if $22 polygon {narg($coords)/2},$coords,1,${23-25},{$26*255%} 50486 else polygon {narg($coords)/2},$coords,1,0xFFFFFFFF,${23-25},{$26*255%} 50487 fi 50488 50489fx_symmetric_shape2d_preview : 50490 _fx_symmetric_shape2d_preview $* 50491 50492_fx_symmetric_shape2d_preview : 50493 _is_preview=1 50494 cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4,cx5,cy5,cx6,cy6=${10-21} 50495 angx,angy=$6,$7 50496 if [$2,$3]!=[$4,$5]" || "[$angx,$angy]!=[$8,$9] # Center or angle has been modified 50497 dx,dy={[$2-$4,$3-$5]} 50498 repeat 6 i={1+$>} 50499 cx$i,cy$i={" 50500 const cx = "${cx$i}"; 50501 const cy = "${cy$i}"; 50502 dang = atan2($7 - $3,$6 - $2) - atan2($9 - $3,$8 - $2); 50503 dsca = norm($6 - $2,$7 - $3)/norm($9 - $3,$8 - $2); 50504 [ $2,$3 ] + dsca*rot(dang)*[ cx - $4, cy - $5 ]"} 50505 done 50506 angx,angy={[$6+$2-$4,$7+$3-$5]} 50507 fi 50508 50509 repeat $! l[$>] 50510 r {s=min(w,h);[s,s]},1,100%,0,0,0.5,0.5 50511 fx_symmetric_shape2d ${1-9},$cx1,$cy1,$cx2,$cy2,$cx3,$cy3,$cx4,$cy4,$cx5,$cy5,$cx6,$cy6,${22-26} 50512 rv blend alpha 50513 eval " 50514 t0 = atan2($7 - $3,$6 - $2); 50515 repeat ($1,k, 50516 const pi2 = 2*pi; 50517 const xc = $2*(w-1)%; 50518 const yc = $3*(h-1)%; 50519 x = xc + (w+h)*cos(t0 + 2*pi*k/$1); 50520 y = yc + (w+h)*sin(t0 + 2*pi*k/$1); 50521 polygon(-2,xc,yc,x,y,0.35,0xF0F0F0F0,255); 50522 polygon(-2,xc,yc,x,y,0.35,0x0F0F0F0F,0); 50523 )" 50524 endl done 50525 50526 u "{$1}"\ # Subdivisions 50527 "{$2,$3}"\ # Center 50528 "{$2,$3}"\ # Old Center 50529 "{"$angx,$angy"}"\ # Angle 50530 "{"$angx,$angy"}"\ # Old Angle 50531 "{"$cx1,$cy1"}"\ # Control point 1 50532 "{"$cx2,$cy2"}"\ # Control point 2 50533 "{"$cx3,$cy3"}"\ # Control point 3 50534 "{"$cx4,$cy4"}"\ # Control point 4 50535 "{"$cx5,$cy5"}"\ # Control point 5 50536 "{"$cx6,$cy6"}"\ # Control point 6 50537 "{$22}"\ # Drawing mode 50538 "{$23,$24,$25}"\ # Color 50539 "{$26}" # Opacity 50540 50541#@gui Tree : fx_tree, fx_tree_preview(1) 50542#@gui : note = note("<small><b><span color="#EE5500">Global parameters:</span></b></small>") 50543#@gui : Recursion Depth = int(11,1,18) 50544#@gui : Random Seed = int(10000,0,65535) 50545#@gui : X-ratio = float(0,-1,1) 50546#@gui : Y-ratio = float(0,-1,1) 50547#@gui : note = note("<small><b><span color="#FF0055">Note:</span></b> Set <i>Random Seed</i> to <b>0</b> to make it \ 50548# random as well.</small>") 50549#@gui : sep = separator(), note = note("<small><b><span color="#EE5500">Trunk:</span></b></small>") 50550#@gui : Thickness (%) = float(15,0,100) 50551#@gui : Base Thickness (%) = float(150,0,300) 50552#@gui : Angle (deg.) = float(0,-90,90) 50553#@gui : sep = separator(), note = note("<small><b><span color="#EE5500">Recursion:</span></b></small>") 50554#@gui : Avg Branching = float(2.15,1,6) 50555#@gui : Std Branching = float(0.8,0,6) 50556#@gui : Avg Left Angle (deg.) = float(-40,-90,90) 50557#@gui : Avg Right Angle (deg.) = float(40,-90,90) 50558#@gui : Std Angle (deg.) = float(10,0,90) 50559#@gui : Avg Length Factor (%) = float(75,0,200) 50560#@gui : Std Length Factor (%) = float(0,0,200) 50561#@gui : Avg Thickness Factor (%) = float(70,0,200) 50562#@gui : Std Thickness Factor (%) = float(20,0,200) 50563#@gui : sep = separator(), note = note("<small><b><span color="#EE5500">Colors / Opacity:</span></b></small>") 50564#@gui : Trunk color = color(40,25,0,255) 50565#@gui : Trunk opacity (%) = float(100,0,100) 50566#@gui : Leaf color = color(70,140,60,255) 50567#@gui : Leaf opacity (%) = float(100,0,100) 50568#@gui : Color gamma = float(0.4,-2,2) 50569#@gui : Opacity gamma = float(0.4,-2,2) 50570#@gui : sep = separator() 50571#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/03/24</i>.</small>") 50572_fx_tree: 50573 recursion_depth,random_seed,xratio,yratio,\ 50574 trunk_thickness,base_thickness,trunk_angle,\ 50575 avg_branching,std_branching,avg_leftangle,avg_rightangle,std_angle,avg_length,std_length,avg_thickness,std_thickness,\ 50576 Rt,Gt,Bt,At,Ot,Rl,Gl,Bl,Al,Ol,gammaRGBA,gammaO=${1-28} 50577 50578 W,H,S={[w,h,min(w,h)]} l[] 50579 if $2 srand $2 fi 50580 50581 # Init trunk. 50582 1,1,1,9," 50583 const h_thickness = "$trunk_thickness"%/2; 50584 const hb_thickness = h_thickness*"$base_thickness"%; 50585 R = rot("$trunk_angle"°); 50586 C = [ 0.5,0 ]; 50587 P0 = C + R*[ -hb_thickness,0 ]; 50588 P1 = C + R*[ hb_thickness,0 ]; 50589 P2 = C + R*[ h_thickness,0.5 ]; 50590 P3 = C + R*[ -h_thickness,0.5 ]; 50591 [ P0,P1,P2,P3,0 ]" 50592 50593 # Compute tree geometry. 50594 repeat $recursion_depth 50595 1,8,1,9 50596 eval.. "> 50597 const dangle = "$avg_rightangle" - "$avg_leftangle"; 50598 ref(I,val); 50599 ref(val[0,2],P0); 50600 ref(val[2,2],P1); 50601 ref(val[4,2],P2); 50602 ref(val[6,2],P3); 50603 ndepth = val[8] + 1; 50604 50605 # Median axis. 50606 A = (P0 + P1)/2; 50607 B = (P2 + P3)/2; 50608 AB = B - A; 50609 thickness = norm(B - P2); 50610 50611 N = round(cut("$avg_branching" + u(-1,1)*"$std_branching",1,6)); 50612 Nm1 = N<=1?1:N - 1; 50613 50614 repeat (N,n, 50615 ang = cut("$avg_leftangle" + dangle*n/Nm1 + u(-1,1)*"$std_angle",-90,90); 50616 len = cut("$avg_length" + u(-1,-1)*"$std_length",0,200); 50617 rot = rot(ang°); 50618 nB = B + len%*rot*AB; 50619 orth = (nB - B); 50620 orth/=norm(orth); 50621 orth = [ -orth[1],orth[0] ]; 50622 nthickness = thickness*("$avg_thickness" + u(-1,1)*"$std_thickness")%; 50623 Q0 = nB + nthickness*orth; 50624 Q1 = nB - nthickness*orth; 50625 da_push([ P3,P2,Q1,Q0,ndepth ]); 50626 ); 50627 end(resize(#-1,1,da_size(),1,s#-1,0)); val" 50628 done 50629 a y 50630 50631 # Normalize coordinates to fit image size and aspect ratio. 50632 1,100%,1,4,"[ i0#-1,i2#-1,i4#-1,i6#-1 ]" 50633 1,100%,1,4,"[ i1#-2,i3#-2,i5#-2,i7#-2 ]" 50634 sx,sy={10^[$xratio,$yratio]} 50635 -.. 0.5 *.. {-2,$S*$sx/(2.1*max(abs(iM),abs(im)))} +.. {$W/2} *. {$S*$sy/(1.05*max(iM))} 50636 f... "round([ i0#-2,i0#-1,i1#-2,i1#-1,i2#-2,i2#-1,i3#-2,i3#-1,i8 ])" 50637 rm[-2,-1] 50638 50639 # Make sure trunk starts at bottom when rotated. 50640 eval "ref(I,T); P0 = T[0,2]; P1 = T[2,2]; P2 = T[4,2]; P3 = T[6,2]; 50641 I[0] = [ lerp(P0,P2,-2),lerp(P1,P2,-2),P2,P3,0 ]" 50642 50643 # Draw tree. 50644 $W,$H,1,4 50645 eval.. "> 50646 begin( 50647 RGBAt = [ "$Rt,$Gt,$Bt,$At" ]; 50648 RGBAl = [ "$Rl,$Gl,$Bl,$Al" ]; 50649 const gRGBA = 10^"$gammaRGBA"; 50650 const gO = 10^"$gammaO"; 50651 ); 50652 ref(I,val); 50653 t = val[8]/"$recursion_depth"; # Between [0,1] 50654 RGBA = lerp(RGBAt,RGBAl,t^gRGBA); 50655 O = lerp("$Ot,$Ol",t^gO)%; 50656 polygon(#-1,4,val[0,8],O,RGBA); 50657 (i0==i2 && i1==i3) || (i4==i6 && i5==i7)?polygon(#-1,2,i0,i1,i4,i5,O,RGBA); 50658 val" 50659 mirror xy 50660 rm.. 50661 endl 50662 50663fx_tree : 50664 _fx_tree. $* mv. 0 50665 if 0$_output_mode k[0] fi 50666 50667fx_tree_preview : 50668 repeat $! l[$>] _fx_tree $* blend alpha endl done 50669 50670#@gui Turbulence : fx_turbulence, fx_turbulence 50671#@gui : Radius = float(128,1,1024) 50672#@gui : Octaves = int(6,1,12) 50673#@gui : Damping per Octave = float(4,1,10) 50674#@gui : Difference Mixing = float(0,-10,10) 50675#@gui : Mode = choice("Turbulence","Turbulence 2","Fractal Noise","Fractured Clouds","Stardust","Pea Soup") 50676#@gui : sep = separator() 50677#@gui : note = note("<small>Author: <i>Preben Soeberg</i>. Latest Update: <i>2010/29/12</i>.</small>") 50678fx_turbulence : 50679 remove_opacity turbulence ${^0} 50680 50681 50682#@gui ____<b>Sequences</b> 50683#------------------------- 50684 50685# fx_animate_preview : _command,_parameters1,_parameters2,_compute_half={ 0 | 1 },_width>=0,_height>=0 50686# Generate a preview with start/end rendering of an animation. 50687fx_animate_preview : skip ${4=1},${5=0},${6=$5} 50688 repeat $! 50689 if $5 width=$5 else width={w} fi 50690 if $6 height=$6 else height={h} fi 50691 if $4 s. x,2 else . fi 50692 -$1.. $2 -$1. $3 # Assume this is a 1->1 filter. 50693 r[-2,-1] {max(w,{-2,w})},{max(h,{-2,h})},1,100%,3 50694 if !$4 columns.. 0,50% columns. 50%,100% fi 50695 a[-2,-1] x r. $width,$height,1,100%,2 drgba. 50696 line. 50%,0,50%,100%,1,0,0,0,255 50697 to. "Start",3,-1,13,2,1,255 to. "End",{w-24},{h-18},13,2,1,255 50698 mv. 0 done 50699 50700#@gui 3D Elevation [Animated] : fx_animate_elevation3d, fx_animate_elevation3d_preview(1) 50701#@gui : Frames = _int(10,2,100) 50702#@gui : Output as Frames = _bool(1) 50703#@gui : Output as Files = _bool(0) 50704#@gui : Output Folder = _folder() 50705#@gui : note = note{"\n<b>Global parameters :</b>"} 50706#@gui : Factor = float(100,-1000,1000) 50707#@gui : Smoothness = float(1,0,10) 50708#@gui : Width = _int(1024,8,4096) 50709#@gui : Height = _int(1024,8,4096) 50710#@gui : Rendering = choice(2,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 50711#@gui : note = note{"\n<b>Starting parameters :</b>"} 50712#@gui : Size = float(0.8,0,3) 50713#@gui : X-Angle = float(35,0,360) 50714#@gui : Y-Angle = float(0,0,360) 50715#@gui : Z-Angle = float(0,0,360) 50716#@gui : FOV = float(45,1,90) 50717#@gui : X-Light = float(0,-100,100) 50718#@gui : Y-Light = float(0,-100,100) 50719#@gui : Z-Light = float(-100,-100,0) 50720#@gui : Specular Lightness = float(0.5,0,1) 50721#@gui : Specular Shininess = float(0.7,0,3) 50722#@gui : note = note{"\n<b>Ending parameters :</b>"} 50723#@gui : Size = float(0.8,0,3) 50724#@gui : X-Angle = float(35,0,1440) 50725#@gui : Y-Angle = float(0,0,1440) 50726#@gui : Z-Angle = float(360,0,1440) 50727#@gui : FOV = float(45,1,90) 50728#@gui : X-Light = float(0,-100,100) 50729#@gui : Y-Light = float(0,-100,100) 50730#@gui : Z-Light = float(-100,-100,0) 50731#@gui : Specular Lightness = float(0.5,0,1) 50732#@gui : Specular Shininess = float(0.7,0,3) 50733#@gui : sep = separator() 50734#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 50735fx_animate_elevation3d : skip "${4=}" 50736 if $3 filename="$4/gmic_elevation3d.png" else filename="" fi 50737 _fx_elevation3d ${5-6},0 50738 animate fx_render3d,"${7-8},${10-19},$9",\ 50739 "${7-8},${20-29},$9",$1,$2,{``$filename} 50740 50741fx_animate_elevation3d_preview : skip "${4=}" 50742 w={w} h={h} 50743 _fx_elevation3d ${5-6},0 50744 fx_animate_preview fx_render3d,$w","$h",${10-19},$9",\ 50745 $w","$h",${20-29},$9",0,$w,$h 50746 50747#@gui 3D Extrusion [Animated] : fx_animate_extrude3d, fx_animate_extrude3d_preview(1) 50748#@gui : Frames = _int(10,2,100) 50749#@gui : Output as Frames = _bool(1) 50750#@gui : Output as Files = _bool(0) 50751#@gui : Output Folder = _folder() 50752#@gui : note = note{"\n<b>Global parameters :</b>"} 50753#@gui : Depth = float(10,1,256) 50754#@gui : Resolution = int(512,1,1024) 50755#@gui : Smoothness = float(0.6,0,3) 50756#@gui : Width = _int(1024,8,4096) 50757#@gui : Height = _int(1024,8,4096) 50758#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 50759#@gui : note = note{"\n<b>Starting parameters :</b>"} 50760#@gui : Size = float(0.8,0,3) 50761#@gui : X-Angle = float(35,0,360) 50762#@gui : Y-Angle = float(0,0,360) 50763#@gui : Z-Angle = float(0,0,360) 50764#@gui : FOV = float(45,1,90) 50765#@gui : X-Light = float(0,-100,100) 50766#@gui : Y-Light = float(0,-100,100) 50767#@gui : Z-Light = float(-100,-100,0) 50768#@gui : Specular Lightness = float(0.5,0,1) 50769#@gui : Specular Shininess = float(0.7,0,3) 50770#@gui : note = note{"\n<b>Ending parameters :</b>"} 50771#@gui : Size = float(0.8,0,3) 50772#@gui : X-Angle = float(35,0,1440) 50773#@gui : Y-Angle = float(360,0,1440) 50774#@gui : Z-Angle = float(0,0,1440) 50775#@gui : FOV = float(45,1,90) 50776#@gui : X-Light = float(0,-100,100) 50777#@gui : Y-Light = float(0,-100,100) 50778#@gui : Z-Light = float(-100,-100,0) 50779#@gui : Specular Lightness = float(0.5,0,1) 50780#@gui : Specular Shininess = float(0.7,0,3) 50781#@gui : sep = separator() 50782#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 50783fx_animate_extrude3d : skip "${4=}" 50784 if $3 filename="$4/gmic_extrude3d.png" else filename="" fi 50785 _fx_extrude3d ${5-7},0 50786 animate fx_render3d,"${8-9},${11-20},$10",\ 50787 "${8-9},${21-30},$10",$1,$2,{``$filename} 50788 50789fx_animate_extrude3d_preview : skip "${4=}" 50790 w={w} h={h} 50791 _fx_extrude3d ${5-7},0 50792 fx_animate_preview fx_render3d,$w","$h",${11-20},$10",\ 50793 $w","$h",${21-30},$10",0,$w,$h 50794 50795#@gui 3D Image Object [Animated] : fx_animate_imageobject3d, fx_animate_imageobject3d_preview(1) 50796#@gui : Frames = _int(10,2,100) 50797#@gui : Output as Frames = _bool(1) 50798#@gui : Output as Files = _bool(0) 50799#@gui : Output Folder = _folder() 50800#@gui : note = note{"\n<b>Global parameters :</b>"} 50801#@gui : Type = choice{1,"Plane","Cube","Pyramid","Sphere","Torus","Gyroid","Weird","Cup","Rubik"} 50802#@gui : Width = _int(1024,1,4096) 50803#@gui : Height = _int(1024,1,4096) 50804#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 50805#@gui : note = note{"\n<b>Starting parameters :</b>"} 50806#@gui : Size = float(0.5,0,3) 50807#@gui : X-Angle = float(57,0,360) 50808#@gui : Y-Angle = float(41,0,360) 50809#@gui : Z-Angle = float(21,0,360) 50810#@gui : FOV = float(45,1,90) 50811#@gui : X-Light = float(0,-100,100) 50812#@gui : Y-Light = float(0,-100,100) 50813#@gui : Z-Light = float(-100,-100,0) 50814#@gui : Specular Lightness = float(0.5,0,1) 50815#@gui : Specular Shininess = float(0.7,0,3) 50816#@gui : note = note{"\n<b>Ending parameters :</b>"} 50817#@gui : Size = float(0.5,0,3) 50818#@gui : X-Angle = float(57,0,1440) 50819#@gui : Y-Angle = float(401,0,1440) 50820#@gui : Z-Angle = float(21,0,1440) 50821#@gui : FOV = float(45,1,90) 50822#@gui : X-Light = float(0,-100,100) 50823#@gui : Y-Light = float(0,-100,100) 50824#@gui : Z-Light = float(-100,-100,0) 50825#@gui : Specular Lightness = float(0.5,0,1) 50826#@gui : Specular Shininess = float(0.7,0,3) 50827#@gui : sep = separator() 50828#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 50829fx_animate_imageobject3d : skip "${4=}" 50830 if $3 filename="$4/gmic_imageobject3d.png" else filename="" fi 50831 _fx_imageobject3d "_",$5 50832 animate fx_render3d,"${6-7},${9-18},$8",\ 50833 "${6-7},${19-28},$8",$1,$2,{``$filename} 50834 50835fx_animate_imageobject3d_preview : skip "${4=}" 50836 w={w} h={h} 50837 _fx_imageobject3d "_preview_",$5 50838 fx_animate_preview fx_render3d,$w","$h",${9-18},$8",\ 50839 $w","$h",${19-28},$8",0,$w,$h 50840 50841#@gui 3D Text Pointcloud : fx_text_pointcloud3d, fx_text_pointcloud3d_preview 50842#@gui : Frames = _int(64,1,256) 50843#@gui : 1st Text = text("G'MIC") 50844#@gui : 2nd Text = text("Rocks!") 50845#@gui : Smoothness = float(1,0,5) 50846#@gui : Color = color(200,220,255) 50847#@gui : Background = color(255,255,255,255) 50848#@gui : X-Shadow= float(2,0,10) 50849#@gui : Y-Shadow= float(2,0,10) 50850#@gui : Shadow Smoothness = float(1,0,5) 50851#@gui : Stationary Frames = _int(19,1,32) 50852#@gui : sep = separator() 50853#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/01/09</i>.</small>") 50854fx_text_pointcloud3d : 50855 W={w} H={h} M={round(1.5*max(w,h))} rm 50856 text_pointcloud3d "$2","$3",$4 50857 col3d. ${5-7} *3d. {0.7*$M} 50858 f3d 4000 db3d 0 m3d 50859 repeat $1 50860 rprogress {60*$>/$1} 50861 angle={$>*360/$1} 50862 +r3d[0] 1,0,1,$angle 50863 $M,$M,1,3,-1 j3d. ..,50%,50%,0,1 rm.. 50864 done 50865 rm[0] a z autocrop -1 to_rgba s z replace_color 0,0,-1,-1,-1,255,0,0,0,0 50866 if $11 N=$! repeat $! l[$>] rprogress {60+40*$>/$N} 50867 i[0] 100%,100%,1,4 fc[0] ${8-11} +channels. 3,3 +negate. b[-2,-1] $14% to_rgba. 50868 j[0] .,$12%,$13%,0,0,1,..,255 rm[-2,-1] blend alpha 50869 endl done fi 50870 if $W>$H r2dx $W else r2dy $H fi 50871 if $15>1 50872 i[{int($1/2)}] [{int($1/2)}]x{$15-1} 50873 i[0] [0]x{$15-1} 50874 fi 50875 50876fx_text_pointcloud3d_preview : 50877 fx_text_pointcloud3d 4,"$2","$3",$4,${5-7},${8-11},${12-14},1 drgba 50878 frame 1,1,0 append_tiles 2,2 50879 50880#@gui 3D Tiles : fx_transition3d, fx_transition3d_preview(0) 50881#@gui : Inter-Frames = _int(10,3,100) 50882#@gui : X-Tiles = int(8,1,64) 50883#@gui : Y-Tiles = int(8,1,64) 50884#@gui : X-Rotation = text("1") 50885#@gui : Y-Rotation = text("1") 50886#@gui : Z-Rotation = text("0") 50887#@gui : Focale = float(800,100,2000) 50888#@gui : Enable Antialiasing = bool(1) 50889#@gui : sep = separator() 50890#@gui : note = note{"<small><b>Note:</b> 50891#@gui : This filter needs two layers to work properly. Set the <i>Input layers</i> option to handle 50892#@gui : multiple input layers. 50893#@gui : </small>"} 50894#@gui : sep = separator() 50895#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/13/08</i>.</small>") 50896fx_transition3d : 50897 f3d $7 50898 transition3d $1,$2,$3,"$4","$5","$6",$8 50899 50900fx_transition3d_preview : 50901 if $!==1 gui_warning_preview "Missing input layer" return fi 50902 f3d $7 50903 k[0,1] transition3d 4,$2,$3,"$4","$5","$6",$8 50904 k[1,2] 50905 r[0] 50%,100%,1,100%,0 50906 r[1] 50%,100%,1,100%,0,0,1 50907 a x 50908 line 50%,0,50%,100%,1,0,0,0,255 50909 50910#@gui B&W Pencil [Animated] : fx_animate_pencilbw, fx_animate_pencilbw_preview(0) 50911#@gui : Frames = _int(10,2,100) 50912#@gui : Output Frames = _bool(1) 50913#@gui : Output Files = _bool(0) 50914#@gui : Output Folder = _folder() 50915#@gui : note = note{"\n<b>Starting Parameters :</b>"} 50916#@gui : Pencil Type = float(2.3,0,5) 50917#@gui : Amplitude = float(100,0,200) 50918#@gui : note = note{"\n<b>Ending Parameters :</b>"} 50919#@gui : Pencil Type = float(0.3,0,5) 50920#@gui : Amplitude = float(60,0,200) 50921#@gui : sep = separator() 50922#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 50923fx_animate_pencilbw : skip "${4=}" 50924 if $3 filename="$4/gmic_pencilbw.png" else filename="" fi 50925 animate pencilbw,"${5-6}",\ 50926 "${7-8}",$1,$2,{``$filename} 50927 50928fx_animate_pencilbw_preview : skip "${4=}" 50929 fx_animate_preview pencilbw,"${5-6}",\ 50930 "${7-8}" 50931 50932#@gui B&W Stencil [Animated] : fx_animate_stencilbw, fx_animate_stencilbw_preview(1) 50933#@gui : Frames = _int(10,2,100) 50934#@gui : Output Frames = _bool(1) 50935#@gui : Output Files = _bool(0) 50936#@gui : Output Folder = _folder() 50937#@gui : note = note{"\n<b>Starting Parameters :</b>"} 50938#@gui : Edge Threshold = float(10,0,30) 50939#@gui : Smoothness = float(10,0,30) 50940#@gui : note = note{"\n<b>Ending Parameters :</b>"} 50941#@gui : Edge Threshold = float(10,0,30) 50942#@gui : Smoothness = float(20,0,30) 50943#@gui : sep = separator() 50944#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 50945fx_animate_stencilbw : skip "${4=}" 50946 if $3 filename="$4/gmic_stencilbw.png" else filename="" fi 50947 animate stencilbw,"${5-6}",\ 50948 "${7-8}",$1,$2,{``$filename} 50949 50950fx_animate_stencilbw_preview : skip "${4=}" 50951 fx_animate_preview stencilbw,"${5-6}",\ 50952 "${7-8}" 50953 50954#@gui Cartoon [Animated] : fx_animate_cartoon, fx_animate_cartoon_preview(0) 50955#@gui : Frames = _int(10,2,100) 50956#@gui : Output Frames = _bool(1) 50957#@gui : Output Files = _bool(0) 50958#@gui : Output Folder = _folder() 50959#@gui : note = note{"\n<b>Global Parameters :</b>"} 50960#@gui : Color Quantization = int(4,2,256) 50961#@gui : note = note{"\n<b>Starting parameters :</b>"} 50962#@gui : Smoothness = float(0.5,0,2) 50963#@gui : Sharpening = float(200,0,400) 50964#@gui : Edge Threshold = float(10,1,30) 50965#@gui : Edge Thickness = float(0.1,0,1) 50966#@gui : Color Strength = float(1.5,0,3) 50967#@gui : note = note{"\n<b>Ending parameters :</b>"} 50968#@gui : Smoothness = float(3,0,2) 50969#@gui : Sharpening = float(200,0,400) 50970#@gui : Edge Threshold = float(10,1,30) 50971#@gui : Edge Thickness = float(0.1,0,1) 50972#@gui : Color Strength = float(1.5,0,3) 50973#@gui : sep = separator() 50974#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 50975fx_animate_cartoon : skip "${4=}" 50976 if $3 filename="$4/gmic_cartoon.png" else filename="" fi 50977 animate cartoon,"${6-10},$5",\ 50978 "${11-15},$5",$1,$2,{``$filename} 50979 50980fx_animate_cartoon_preview : skip "${4=}" 50981 fx_animate_preview cartoon,"${6-10},$5",\ 50982 "${11-15},$5" 50983 50984#@gui Edges [Animated] : fx_animate_edges, fx_animate_edges_preview(0) 50985#@gui : Frames = _int(10,2,100) 50986#@gui : Output Frames = _bool(1) 50987#@gui : Output Files = _bool(0) 50988#@gui : Output Folder = _folder() 50989#@gui : note = note{"\n<b>Global Parameters :</b>"} 50990#@gui : Negative Colors = bool(0) 50991#@gui : note = note{"\n<b>Starting Parameters :</b>"} 50992#@gui : Smoothness = float(0,0,10) 50993#@gui : Edge Threshold = float(10,0,30) 50994#@gui : note = note{"\n<b>Ending Parameters :</b>"} 50995#@gui : Smoothness = float(0,0,10) 50996#@gui : Edge Threshold = float(30,0,30) 50997#@gui : sep = separator() 50998#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 50999fx_animate_edges : skip "${4=}" 51000 if $3 filename="$4/gmic_edges.png" else filename="" fi 51001 animate fx_edges,"${6-7},$5",\ 51002 "${8-9},$5",$1,$2,{``$filename} 51003 51004fx_animate_edges_preview : skip "${4=}" 51005 fx_animate_preview fx_edges,"${6-7},$5",\ 51006 "${8-9},$5" 51007 51008#@gui Edges on Fire : fx_fire_edges, fx_fire_edges_preview(0) 51009#@gui : Edges = float(0.7,0,3) 51010#@gui : Attenuation = float(0.25,0,1) 51011#@gui : Smoothness = float(0.5,0,5) 51012#@gui : Threshold = float(25,0,100) 51013#@gui : sep = separator() 51014#@gui : Number of Frames = _int(20,1,999) 51015#@gui : Starting Frame = int(20,0,199) 51016#@gui : Frame Skip = _int(0,0,20) 51017#@gui : sep = separator() 51018#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 51019#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 51020#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 51021#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 51022#@gui : sep = separator() 51023#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/06/07</i>.</small>") 51024fx_fire_edges : 51025 fire_edges ${1-7} rv 51026 51027fx_fire_edges_preview : 51028 gui_split_preview "fire_edges $1,$2,$3,$4,1,$6,0",${-3--1} 51029 51030#@gui Lava Lamp : fx_lavalampbw, fx_lavalampbw_preview(0) 51031#@gui : Number of Key-Frames = _int(3,2,50) 51032#@gui : Number of Inter-Frames = _int(30,2,100) 51033#@gui : Smooth Looping = _bool(1) 51034#@gui : sep = separator() 51035#@gui : Resolution = float(20,1,100) 51036#@gui : Size = float(2,0,30) 51037#@gui : Smoothness = _float(0.01,0,1) 51038#@gui : Transparent Background = bool(0) 51039#@gui : sep = separator() 51040#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/06/07</i>.</small>") 51041fx_lavalampbw : 51042 if !$! (255;100^64;16^128;0) r. 512,512,1,3,3 fi 51043 repeat $! l[$<] remove_opacity 51044 w={w} h={h} 51045 +r $4%,$4%,1,1,0 [-1]x{$1-1} rand[^0] 0,1 stencil[^0] $5,0 51046 if $3 [1] fi 51047 morph[^0] $2,$6,0 51048 stencil[^0] $5,0 51049 r[^0] $w,$h,1,1,3 b[^0] 10 >=[^0] 50% *[^0] 255 51050 r[^0] 100%,100%,1,4 j[^0] [0] rm[0] 51051 if $3 rm. fi 51052 endl done 51053 if !$7 repeat $! l[$>] split_opacity n. 0,1 *[^-1] . rm. endl done fi 51054 51055fx_lavalampbw_preview : 51056 fx_lavalampbw 2,2,1,$4,$5,$6,$7 k[0] 51057 51058#@gui Lissajous [Animated] : fx_animate_lissajous, fx_animate_lissajous_preview(1) 51059#@gui : Frames = _int(10,2,100) 51060#@gui : Output as Frames = _bool(1) 51061#@gui : Output as Files = _bool(0) 51062#@gui : Output Folder = _folder() 51063#@gui : sep = separator() 51064#@gui : note = note{"<b>Starting parameters :</b>"} 51065#@gui : Resolution = int(4096,2,8192) 51066#@gui : X-Size = float(0.9,0,2) 51067#@gui : Y-Size = float(0.9,0,2) 51068#@gui : Z-Size = float(3,1,10) 51069#@gui : X-Multiplier = float(8,0,32) 51070#@gui : Y-Multiplier = float(7,0,32) 51071#@gui : Z-Multiplier = float(0,0,32) 51072#@gui : X-Offset = float(0,0,1) 51073#@gui : Y-Offset = float(0,0,1) 51074#@gui : Z-Offset = float(0,0,1) 51075#@gui : X-Angle = float(0,0,360) 51076#@gui : Y-Angle = float(0,0,360) 51077#@gui : Z-Angle = float(0,0,360) 51078#@gui : Thickness = float(0,0,50) 51079#@gui : Color = color(255,255,255,255) 51080#@gui : sep = separator() 51081#@gui : note = note{"<b>Ending parameters :</b>"} 51082#@gui : Resolution = int(4096,2,8192) 51083#@gui : X-Size = float(0.9,0,2) 51084#@gui : Y-Size = float(0.9,0,2) 51085#@gui : Z-Size = float(3,1,10) 51086#@gui : X-Multiplier = float(8,0,32) 51087#@gui : Y-Multiplier = float(7,0,32) 51088#@gui : Z-Multiplier = float(0,0,32) 51089#@gui : X-Offset = float(0,0,1) 51090#@gui : Y-Offset = float(0,0,1) 51091#@gui : Z-Offset = float(0,0,1) 51092#@gui : X-Angle = float(0,0,360) 51093#@gui : Y-Angle = float(0,0,360) 51094#@gui : Z-Angle = float(0,0,360) 51095#@gui : Thickness = float(0,0,50) 51096#@gui : Color = color(255,255,255,255) 51097#@gui : sep = separator() 51098#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/04</i>.</small>") 51099fx_animate_lissajous : skip "${4=}" 51100 if $3 filename="$4/gmic_lissajous.png" else filename="" fi 51101 animate fx_lissajous,"${5-22}",\ 51102 "${23-40}",$1,$2,{``$filename} 51103 51104fx_animate_lissajous_preview : skip "${4=}" 51105 fx_animate_preview fx_lissajous,"${5-22}",\ 51106 "${23-40}",0 51107 51108#@gui Moiré Animation : fx_moire, fx_moire_preview(1)+ : * 51109#@gui : Stripe orientation = choice(1,"Horizontal","Vertical") 51110#@gui : Input Transparency = choice("Replace With White","Reconstruct From Previous Frames") 51111#@gui : Output Format = choice{2,"Same as Input","A4 / 75 PPI","A4 / 100 PPI (Recommended)", 51112#@gui : "A4 / 150 PPI","A4 / 300 PPI"} 51113#@gui : Auto-Reduce Number of Frames = bool(1) 51114#@gui : Landscape = bool(1) 51115#@gui : Margin (%) = float(2,0,30) 51116#@gui : sep = separator() 51117#@gui : Print Frame Numbers = choice(1,"Disable","Top Left","Top Right","Bottom Left","Bottom Right") 51118#@gui : Size of Frame Numbers (%) = float(5,0,30) 51119#@gui : sep = separator() 51120#@gui : note = note{"<small><b><span color="#EE5500">Instructions:</span></b>\n\n 51121#@gui : This filter renders Moire Animations, as shown on 51122#@gui : <a href="https://www.youtube.com/watch?v=f5plDb_JRq4">this video</a>.\n 51123#@gui : To make the animation visible:\n\n 51124#@gui : • Before running the filter, ensure that all frames are aligned and have the same size 51125#@gui : (and preferably without alpha)!\n 51126#@gui : • Run the filter. It is recommended to keep the number of frames <=6.\n 51127#@gui : • Print the first layer (merged frames) on a A4 blank paper, at 300 PPI.\n 51128#@gui : • Print the second layer (mask) on a A4 transparent sheet, at 300 PPI.\n 51129#@gui : • Drag the transparent layer over the A4 paper to render the animation effect. 51130#@gui : "} 51131#@gui : sep = separator() 51132#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/03/02</i>.</small>") 51133fx_moire : 51134 if 0$_is_preview" && "!narg($_preview_width) _preview_width,_preview_height=512 fi 51135 51136 # Reconstruct frames from base image. 51137 if $2 repeat $! if $>" && "{$<,s==2||s==4} blend[$<] [{$<+1}],alpha,1,1 fi done fi 51138 51139 # Auto-reduce number of frames (4, 5 or 6). 51140 if $4 51141 skip={" 51142 l<=6?1:( 51143 const l5 = int(l/5); 51144 const l4 = int(l/4); 51145 const l6 = int(l/6); 51146 5*l5==l?l5: 51147 6*l6==l?l6: 51148 4*l4==l?l4:( 51149 const r6 = abs(6*l6 - l); 51150 const r5 = abs(5*l5 - l); 51151 const r4 = abs(4*l4 - l); 51152 r5<=r4 && r5<=r6?l5: 51153 r6<=r4 && r6<=r5?l6: 51154 l4 51155 ) 51156 )"} 51157 k[^:$skip] 51158 if $!>6 rm[6--1] fi 51159 fi 51160 N=$! 51161 51162 # Blend with white background. 51163 repeat $! l[$>] if s==2||s==4 drgba 255 fi endl done 51164 51165 # Constrain size of frames. 51166 if 0$_is_preview 51167 W,H=$_preview_width,$_preview_height 51168 if $3 51169 if $W>$H W={$H/sqrt(2)} else H={$W*sqrt(2)} fi 51170 fW,fH=$W,$H 51171 W,H/={arg($3,4,3,2,1)} 51172 fi 51173 elif $3 51174 W,H,fW,fH={"$3==1?[620,877]:$3==2?[827,1169]:$3==3?[1240,1754]:[2480,3508]"},2480,3508 51175 W,H,fW,fH={round([$W,$H,$fW,$fH]*0.95)} # Take printer margins into account 51176 else 51177 W,H=${-max_wh} 51178 fi 51179 51180 if $3" && "$5 # Landscape mode 51181 W,H=$H,$W fW,fH=$fH,$fW 51182 fi 51183 if !narg($fW) fW,fH=$W,$H fi 51184 repeat $! l[$>] if [w,h]!=[$W,$H] 51185 - 255 51186 rr2d {(100-$6)%*[$W,$H]},2,2 51187 r $W,$H,1,100%,0,0,0.5,0.5 51188 + 255 51189 fi endl done 51190 51191 # Generate merged image and mask. 51192 if $1 # Vertical stripes 51193 100%,100%,1,100%,"i(#x%"$N",x,y,z,c)" rm[^-1] 51194 100%,100%,1,1,"x%"$N"?0:255" 51195 else # Horizontal stripes 51196 100%,100%,1,100%,"i(#y%"$N",x,y,z,c)" rm[^-1] 51197 100%,100%,1,1,"y%"$N"?0:255" 51198 fi 51199 51200 # Upscale with nearest-neighbor for printing. 51201 if $3 51202 ir={round(max($fW/$W,$fH/$H))*100} 51203 r $ir%,$ir%,1,100%,1 51204 r $fW,$fH,1,100%,0,1,0.5,0.5 51205 fi 51206 51207 # Insert frame number label. 51208 if $7" && "$8 51209 ax,ay={a=$7-1;[a%2?0.95:0.05,int(a/2)?0.95:0.05]} 51210 0 t. "#"$N,0,0,{0,h*$8%},1,255 autocrop. frame. 5%,15%,0 negate. to_rgb. j[^-1] .,$ax~,$ay~ rm. 51211 fi 51212 nm "name(Merged Frames),pos(0,0),opacity(100),mode(alpha)","name(Mask),pos(0,0),opacity(100),mode(alpha)" 51213 u $N 51214 51215fx_moire_preview : 51216 _is_preview=1 51217 fx_moire $* 51218 51219#@gui Rodilius [Animated] : fx_animate_rodilius, fx_animate_rodilius_preview(1) 51220#@gui : Frames = _int(10,2,100) 51221#@gui : Output as Frames = _bool(1) 51222#@gui : Output as Files = _bool(0) 51223#@gui : Output Folder = _folder() 51224#@gui : Color Mode = choice(1,"Darker","Lighter") 51225#@gui : note = note{"\n<b>Starting Parameters :</b>"} 51226#@gui : Amplitude = float(10,0,30) 51227#@gui : Thickness = float(10,0,100) 51228#@gui : Sharpness = float(300,0,1000) 51229#@gui : Orientations = int(5,2,20) 51230#@gui : Offset = float(0,0,180) 51231#@gui : note = note{"\n<b>Ending Parameters :</b>"} 51232#@gui : Amplitude = float(10,0,30) 51233#@gui : Thickness = float(10,0,100) 51234#@gui : Sharpness = float(300,0,1000) 51235#@gui : Orientations = int(5,2,20) 51236#@gui : Offset = float(180,0,180) 51237#@gui : sep = separator() 51238#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 51239fx_animate_rodilius : skip "${4=}" 51240 if $3 filename="$4/gmic_rodilius.png" else filename="" fi 51241 animate rodilius,"${6-10},$5",\ 51242 "${11-15},$5",$1,$2,{``$filename} 51243 51244fx_animate_rodilius_preview : skip "${4=}" 51245 fx_animate_preview rodilius,"${6-10},$5",\ 51246 "${11-15},$5" 51247 51248#@gui Soft Glow [Animated] : fx_animate_glow, fx_animate_glow_preview(1) 51249#@gui : Frames = _int(10,2,100) 51250#@gui : Output as Frames = _bool(1) 51251#@gui : Output as Files = _bool(0) 51252#@gui : Output Folder = _folder() 51253#@gui : note = note{"\n<b>Starting Parameters :</b>"} 51254#@gui : Amplitude = float(0,0,8) 51255#@gui : note = note{"\n<b>Ending Parameters :</b>"} 51256#@gui : Amplitude = float(3,0,8) 51257#@gui : sep = separator() 51258#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 51259fx_animate_glow : skip "${4=}" 51260 if $3 filename="$4/gmic_glow.png" else filename="" fi 51261 animate glow,"$5",\ 51262 "$6",$1,$2,{``$filename} 51263 51264fx_animate_glow_preview : skip "${4=}" 51265 fx_animate_preview glow,"$5",\ 51266 "$6" 51267 51268#@gui Spatial Transition : fx_spatial_transition, fx_spatial_transition_preview(1) 51269#@gui : Number of Added Frames = _int(10,1,256) 51270#@gui : Shading (%) = float(0,0,100) 51271#@gui : Transition Shape = choice(7,"Bottom Layer","Top Layer","Custom Formula","Horizontal","Vertical", 51272#@gui : "Angular","Radial","Plasma") 51273#@gui : Custom Formula = text{"cos(x*y/(16+32*A))"}_1 51274#@gui : A-Value = float(0,0,1) 51275#@gui : sep = separator() 51276#@gui : Preview Type = choice(1,"Transition Map","Timed Image","Sequence x4","Sequence x6","Sequence x8") 51277#@gui : Preview Time = float(0.5,0,1) 51278#@gui : Preview = value(0) 51279#@gui : sep = separator() 51280#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/10/04</i>.</small>") 51281fx_spatial_transition : 51282 to_rgba r ${-max_wh},1,100%,0,0,0.5,0.5 51283 shape=-1 formula= 51284 if $3==0 # Do nothing. 51285 elif $3==1 shape=0 51286 elif $3==2 formula="$4" 51287 elif $3==3 formula="sin(x*0.5*pi/w*(1+100*A))" 51288 elif $3==4 formula="sin(y*0.5*pi/h*(1+100*A))" 51289 elif $3==5 formula="atan2(y-h/2,x-w/2)%((1-A)*2*pi+0.001)" 51290 elif $3==6 formula="R=0.5*sqrt(w*w+h*h);sqrt((y-h/2)^2+(x-w/2)^2)%(0.001+R*(1-A))" 51291 elif $3==7 100%,100% plasma. 1,1,{8/(1+$5)} equalize. 1024 51292 fi 51293 if narg($formula) 51294 {w},{h},1,1,"A=$5;"$formula fi 51295 if $-1 # Preview mode. 51296 if $6==0 k[$shape] norm n 0,255 51297 elif $6==1" && "$7==0 rm[$shape] rm. 51298 elif $6==1" && "$7==1 rm[$shape] rm[0] 51299 elif $6==1 51300 transition[^$shape] [$shape],$1,$2,$7*($1-1) rm[$shape] rm[0--1:2] 51301 else 51302 transition[^$shape] [$shape],{$6*2},$2 rm[$shape] to_rgba 51303 fi 51304 if $!>1 to_rgba frame 2%,2%,0,0,0,0 append_tiles , fi 51305 else # Apply mode. 51306 transition[^$shape] [$shape],$1,$2 51307 rm. 51308 fi 51309 nm name(transition),pos(0,0) 51310 if narg($formula) u "{$1}{$2}{$3}{"$formula"}_"{$3==2?2:1}"{$5}{$6}{$7}{0}" fi 51311 51312fx_spatial_transition_preview : 51313 if ($3<=1" && "$!<3)" || "($3>1" && "$!<2) 51314 gui_print_preview "Warning:",,"This filter requires more input layers to work properly." 51315 return 51316 fi 51317 fx_spatial_transition ${1-3},"$4",${5-7},1 51318 51319 51320#@gui ____<b>Silhouettes</b> 51321#--------------------------- 51322 51323#@gui <i>Misc</i> 51324 51325#@gui Cupid : fx_cupid, fx_cupid_preview 51326#@gui : Size (%) = float(75,0,100) 51327#@gui : Smoothness = float(0,0,10) 51328#@gui : Color = color(255,255,255,255) 51329#@gui : Antialiasing = bool(1) 51330#@gui : sep = separator() 51331#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/08</i>.</small>") 51332fx_cupid : 51333 max_wh={$!>0?[${-max_wh}]:[512,512]} 51334 w,h={S=[$max_wh]*$1%;[max(S[0],1),max(S[1],1)]} 51335 l[] 51336 shape_cupid {($7?2:1)*min($w,$h)} 51337 if $7 r2dx 50% fi 51338 frame {2.5*$2}%,{2.5*$2}%,0 b $2% * $6 round c 0,255 autocrop 51339 100%,100%,1,3 fc. ${3-5} rv[-2,-1] a c 51340 gui_set_layer_name "Heart" 51341 gui_set_layer_pos {0.5*([$max_wh]-[w,h])} 51342 endl 51343 mv. 0 51344 51345fx_cupid_preview : 51346 fx_cupid $* blend[^0] [0],alpha rm[0] 51347 51348#@gui Gear : fx_gear, fx_gear_preview 51349#@gui : Size (%) = float(75,0,100) 51350#@gui : Number of Teeth = int(12,1,96) 51351#@gui : Elevation (%) = float(15,0,100) 51352#@gui : Angle (%) = float(0,0,100) 51353#@gui : Inner Radius (%) = float(40,0,100) 51354#@gui : Smoothness = float(0,0,10) 51355#@gui : Color = color(255,255,255,255) 51356#@gui : Antialiasing = bool(1) 51357#@gui : sep = separator() 51358#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/08</i>.</small>") 51359fx_gear : 51360 max_wh={$!>0?[${-max_wh}]:[512,512]} 51361 w,h={S=[$max_wh]*$1%;[max(S[0],1),max(S[1],1)]} 51362 l[] 51363 shape_gear {($11?2:1)*min($w,$h)},${2-5} 51364 if $11 r2dx 50% fi 51365 frame {2.5*$6}%,{2.5*$6}%,0 b $6% * $10 round c 0,255 autocrop 51366 100%,100%,1,3 fc. ${7-9} rv[-2,-1] a c 51367 gui_set_layer_name "Gear" 51368 gui_set_layer_pos {0.5*([$max_wh]-[w,h])} 51369 endl 51370 mv. 0 51371 51372fx_gear_preview : 51373 fx_gear $* blend[^0] [0],alpha rm[0] 51374 51375#@gui Heart : fx_heart, fx_heart_preview 51376#@gui : Size (%) = float(75,0,100) 51377#@gui : Smoothness = float(0,0,10) 51378#@gui : Color = color(255,255,255,255) 51379#@gui : Antialiasing = bool(1) 51380#@gui : sep = separator() 51381#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/08</i>.</small>") 51382fx_heart : 51383 max_wh={$!>0?[${-max_wh}]:[512,512]} 51384 w,h={S=[$max_wh]*$1%;[max(S[0],1),max(S[1],1)]} 51385 l[] 51386 shape_heart {($7?2:1)*min($w,$h)} 51387 if $7 r2dx 50% fi 51388 frame {2.5*$2}%,{2.5*$2}%,0 b $2% * $6 round c 0,255 autocrop 51389 100%,100%,1,3 fc. ${3-5} rv[-2,-1] a c 51390 gui_set_layer_name "Heart" 51391 gui_set_layer_pos {0.5*([$max_wh]-[w,h])} 51392 endl 51393 mv. 0 51394 51395fx_heart_preview : 51396 fx_heart $* blend[^0] [0],alpha rm[0] 51397 51398#@gui Sierpinski Triangle : fx_sierpinski, fx_sierpinski(1) 51399#@gui : Recursions = int(6,0,10) 51400#@gui : 1st X-Coord = float(50,0,100) 51401#@gui : 1st Y-Coord = float(0,0,100) 51402#@gui : 2nd X-Coord = float(0,0,100) 51403#@gui : 2nd Y-Coord = float(100,0,100) 51404#@gui : 3rd X-Coord = float(100,0,100) 51405#@gui : 3rd Y-Coord = float(100,0,100) 51406#@gui : Color = color(255,255,255) 51407#@gui : Opacity = float(1,0,1) 51408#@gui : sep = separator() 51409#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 51410fx_sierpinski : 51411 repeat $! l[$>] split_opacity l[0] 51412 100%,100% sierpinski. ${1-7} 51413 +fc.. $8,$9,$10 j[0] .,0,0,0,0,$11,..,255 rm[-2,-1] 51414 endl a c endl done 51415 51416#@gui _<i>Nature</i> 51417 51418#@gui Barnsley Fern : fx_barnsley_fern, fx_barnsley_fern_preview(1) 51419#@gui : Type = choice("Asplenium Adiantum-Nigrum","Thelypteridaceae") 51420#@gui : Density (%) = float(100,0,300) 51421#@gui : Angle = float(30,-180,180) 51422#@gui : Opacity (%) = float(40,0,100) 51423#@gui : Color = color(10,178,0,255) 51424#@gui : Add as a New Layer = _bool(1) 51425#@gui : sep = separator() 51426#@gui : note = note("This filter renders the Barnsley fern fractal, described here:") 51427#@gui : url = link("https://en.wikipedia.org/wiki/Barnsley_fern") 51428#@gui : sep = separator() 51429#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/18/10</i>.</small>") 51430fx_barnsley_fern : 51431 repeat $! l[$<] 51432 shape_fern {min(w,h)},$2%,$3,{$4%},$1 *. 255 51433 100%,100%,1,3,[${5-7}] 51434 rv[-2,-1] a[-2,-1] c 51435 if !$9 blend alpha,{$8/255} 51436 else nm. "name(Barnsley Fern),opacity("{round($8*100/255)})")" rv[-2,-1] 51437 fi 51438 endl done 51439 51440fx_barnsley_fern_preview : 51441 fx_barnsley_fern ${1-8},0 51442 51443#@gui Snowflake : fx_snowflake, fx_snowflake(1) 51444#@gui : Recursions = int(5,0,6) 51445#@gui : Opacity = float(1,0,1) 51446#@gui : Color = color(255,255,255) 51447#@gui : sep = separator() 51448#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 51449fx_snowflake : 51450 repeat $! l[$>] to_color split_opacity l[0] 51451 shape_snowflake {min(w,h)},$1 100%,100%,1,3,[${3-5}] 51452 j[0] .,{([w#0,h#0]-[w#1,h#1])/2},0,0,$2,.. k[0] 51453 endl a c endl done 51454 51455#@gui _<i>Others</i> 51456 51457#@gui Dragon Curve : fx_dragoncurve, fx_dragoncurve(1) 51458#@gui : Recursions = int(20,0,30) 51459#@gui : Angle = float(0,-180,180) 51460#@gui : Opacity = float(1,0,1) 51461#@gui : Color = color(255,255,255) 51462#@gui : sep = separator() 51463#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/01/29</i>.</small>") 51464fx_dragoncurve : 51465 repeat $! l[$>] to_color split_opacity l[0] 51466 shape_dragon {min(w,h)},$1,$2 100%,100%,1,3,[${4-6}] 51467 j[0] .,{([w#0,h#0]-[w#1,h#1])/2},0,0,$3,.. k[0] 51468 endl a c endl done 51469 51470#@gui ____<b>Various</b> 51471#------------------------ 51472 51473#@gui Custom Code [Global] : fx_custom_code, fx_custom_code_preview(1) 51474#@gui : Code = text(1,"repeat $! l[$>]\n\n to_rgb\n +deform 20\n blend_edges 3\n\nendl done\n\n\n") 51475#@gui : sep = separator() 51476#@gui : Channel(s) = choice{"None (Allows Multi-layers)","All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]", 51477#@gui : "RGB [Blue]","RGBA [Alpha]","Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]", 51478#@gui : "YCbCr [Luminance]","YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 51479#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 51480#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 51481#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 51482#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]"} 51483#@gui : Value Action = choice("None","Cut","Normalize") 51484#@gui : Display Debug Info on Preview = bool(0) 51485#@gui : Debug Font Size = choice(2,"Tiny","Small","Normal","Large") 51486#@gui : sep = separator() 51487#@gui : Preview Type = choice{"Full (Allows Multi-Layers)","Forward Horizontal","Forward Vertical", 51488#@gui : "Backward Horizontal","Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom", 51489#@gui : "Duplicate Right","Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse"} 51490#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 51491#@gui : sep = separator() 51492#@gui : note = note{"<small><b>Note: </b> 51493#@gui : This filter can execute any set of instructions understood by the <b>G'MIC</b> language interpreter. 51494#@gui : Here, you can then test some commands before creating your own G'MIC custom commands and plug-in 51495#@gui : menu entries.\n\n 51496#@gui : Please look at the documentation reference web page :</small>"} 51497#@gui : url = link("https://gmic.eu/reference/") 51498#@gui : note = note{"<small> 51499#@gui : to learn more about available <b>G'MIC</b> commands. 51500#@gui : </small>"} 51501#@gui : sep = separator() 51502#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/03/10</i>.</small>") 51503 51504#@gui Custom Code [Local] : fx_custom_code, fx_custom_code_preview(0) 51505#@gui : Code = text(1,"repeat $! l[$>]\n\n to_rgb\n +deform 20\n blend_edges 3\n\nendl done\n\n\n") 51506#@gui : sep = separator() 51507#@gui : Channel(s) = choice{"None (Allows Multi-layers)","All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]", 51508#@gui : "RGB [Blue]","RGBA [Alpha]","Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]", 51509#@gui : "YCbCr [Luminance]","YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 51510#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 51511#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 51512#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 51513#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]"} 51514#@gui : Value Action = choice("None","Cut","Normalize") 51515#@gui : Display Debug Info on Preview = bool(0) 51516#@gui : Debug Font Size = choice(2,"Tiny","Small","Normal","Large") 51517#@gui : sep = separator() 51518#@gui : Preview Type = choice{"Full (Allows Multi-Layers)","Forward Horizontal","Forward Vertical", 51519#@gui : "Backward Horizontal","Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom", 51520#@gui : "Duplicate Right","Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse"} 51521#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 51522#@gui : sep = separator() 51523#@gui : note = note{"<small><b>Note: </b> 51524#@gui : This filter can execute any set of instructions understood by the <b>G'MIC</b> language interpreter. 51525#@gui : Here, you can then test some commands before creating your own G'MIC custom commands and 51526#@gui : plug-in menu entries.\n\n 51527#@gui : Please look at the documentation reference web page :</small>"} 51528#@gui : url = link("https://gmic.eu/reference/") 51529#@gui : note = note{"<small> 51530#@gui : to learn more about available <b>G'MIC</b> commands. 51531#@gui : </small>"} 51532#@gui : sep = separator() 51533#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/03/10</i>.</small>") 51534fx_custom_code : skip "${1=-skip ,}" 51535 ({'{/"$1"}'}) discard. 92,10 _gcp_arg={t} rm. 51536 m "_fx_custom_code_start : "$_gcp_arg 51537 if $4 51538 _nb_in=$! 51539 _dim_in="" sep="" 51540 repeat $! l[$>] 51541 _dim_in=$_dim_in$sep"["$>"] = "{w}x{h}x{d}x{s}", in ["{_round([im,iM],0.1)}"]" sep="\n" 51542 endl done 51543 fi 51544 if $2 51545 ac "_fx_custom_code_start _status_out=${}",{$2-1},$3 51546 else 51547 _fx_custom_code_start _status_out=${} 51548 if $3==1 c 0,255 elif $3==2 n 0,255 fi 51549 fi 51550 if $4 51551 _nb_out=$! 51552 _dim_out="" sep="" 51553 repeat $! l[$>] 51554 _dim_out=$_dim_out$sep"["$>"] = "{w}x{h}x{d}x{s}", in ["{_round([im,iM],0.1)}"]" sep="\n" 51555 endl done 51556 fi 51557 um _fx_custom_code_start 51558 51559fx_custom_code_preview : skip "${1=-skip ,}" 51560 w={w} h={h} 51561 l 51562 ({'{/"$1"}'}) discard. 92,10 _gcp_arg={t} rm. 51563 if $6 gui_split_preview "fx_custom_code $_gcp_arg,${2--2}",${-3--1} 51564 else fx_custom_code $_gcp_arg,${2--2} 51565 fi 51566 onfail 51567 error_msg=${} 51568 rr2d $w,$h,2,1 51569 gui_print_preview "Syntax error:",,{``$error_msg},20,40 51570 endl 51571 if $4 # Display debug infos on preview 51572 if !$3 % 256 fi 51573 if $!>1 gui_preview fi 51574 rr2d $_preview_width,$_preview_height,0,1 51575 siz0=13 siz1=17 siz2=19 siz3=22 51576 if ['$_status_out']==0 _status_out=(empty) fi 51577 info="Input images: "#$_nb_in"\n"\ 51578 $_dim_in"\n\n"\ 51579 "Output images: "#$_nb_out"\n"\ 51580 $_dim_out"\n\n"\ 51581 "Output status: "$_status_out 51582 0 t. {``$info},0,0,${siz$5},1,255 expand_xy. 5,0 +dilate. 3 a[-2,-1] c 51583 rr2d[^-1] ${-max_wh},2,2 51584 r. ..,..,1,100%,0 drgba[^-1] 51585 /[^-1] 2 blend[^-1] .,alpha rm. 51586 fi 51587 51588#@gui Export RGB-565 File : fx_output_565,_none_ 51589#@gui : Filename = _fileout("out565.rgb") 51590#@gui : Reverse endianness = _bool(0) 51591#@gui : sep = separator() 51592#@gui : note = note{"<b>Note:</b> This filter saves your selected layer as a raw RGB-565 file. Keep in mind that 51593#@gui : you have to remember the image dimension if you want to reload the image file afterwards!"} 51594#@gui : sep = separator() 51595#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/05/03</i>.</small>") 51596fx_output_565 : 51597 output_565 "$1",$2 51598 51599#@gui Games & Demos : fx_gmic_demos, fx_gmic_demos_preview 51600#@gui : Selection = choice("2048","Blobs Editor","Bouncing Balls","Connect-Four","Fire Effect","Fireworks", 51601#@gui : "Fish-Eye Effect","Fourier Filtering","Hanoi Tower", 51602#@gui : "Histogram","Hough Transform","Jawbreaker","Virtual Landscape","The Game of Life","Light Effect", 51603#@gui : "Mandelbrot Explorer","3D Metaballs","Minesweeper", 51604#@gui : "Minimal Path","Pacman","Paint","Plasma Effect","RGB Quantization","3D Reflection","3D Rubber Object", 51605#@gui : "Shadebobs","Spline Editor", 51606#@gui : "3D Starfield","Tetris","Tic-Tac-Toe","3D Waves","Fractal Whirl") 51607#@gui : sep = separator() 51608#@gui : note = note("<small><b>Note:</b> This filter proposes a showcase of some interactive demos, all written 51609#@gui : as G'MIC scripts.</small>") 51610#@gui : note = note{"<small>On most demos, you can use the keyboard shortcut <b>CTRL+D</b> to double the window 51611#@gui : size (and <b>CTRL+C</b> to go back to the original size). 51612#@gui : Also, feel free to use the mouse buttons, as they are often used to perform an action. 51613#@gui : </small>"} 51614#@gui : sep = separator() 51615#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/10/09</i>.</small>") 51616fx_gmic_demos : 51617 coms=2048,blobs,bouncing,connect4,fire,fireworks,fisheye,fourier,hanoi,histogram,hough,jawbreaker,landscape,life,\ 51618 light,mandelbrot,metaballs3d,minesweeper,minimal_path,pacman,paint,plasma,quantize_rgb,reflection3d,\ 51619 rubber3d,shadebobs,spline,starfield3d,tetris,tictactoe,waves,whirl 51620 com=${arg\ {1+$1},$coms} 51621 if $!>0 sel=0 else sel= fi 51622 +l[$sel] m "foo : x_"$com foo rm um foo endl 51623 51624fx_gmic_demos_preview : 51625 rm input_cached img/gmic_demos.cimgz k[$1,-1] rows. $1 map[0] [1] k[0] 51626 51627#@gui Histogram Analysis : _none_, fx_display_histogram(1) 51628#@gui : Number of Clusters = int(256,2,1024) 51629#@gui : sep = separator() 51630#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 51631#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 51632#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 51633#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 51634#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 51635#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 51636#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 51637#@gui : sep = separator() 51638#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 51639fx_display_histogram : 51640 mode=${arg\ 1+$2,all,rgba,rgb,rgb_r,rgb_g,rgb_b,rgba_a,\ 51641 lrgb,lrgb_r,lrgb_g,lrgb_b,\ 51642 ycbcr_y,ycbcr_cbcr,ycbcr_cb,ycbcr_cr,ycbcr_cg,\ 51643 lab_l,lab_ab,lab_a,lab_b,\ 51644 lch_ch,lch_c,lch_h,\ 51645 hsv_h,hsv_s,hsv_v,hsi_i,hsl_l,\ 51646 cmyk_c,cmyk_m,cmyk_y,cmyk_k,\ 51647 yiq_y,yiq_iq} 51648 _ac_$mode m "_ac_precond : "$_p m "_ac_forward : "$_f m "_ac_backward : "$_b 51649 repeat $! l[$>] 51650 _ac_precond _ac_forward[0] channels $_s 51651 display_histogram {w},{h},$1,0,255 51652 if s==2" || "s==4 channels 0,2 fi 51653 endl done 51654 51655#@gui Import Data : fx_import_image, gui_no_preview 51656#@gui : Filename = filein() 51657#@gui : Normalize = bool(1) 51658#@gui : note = note{"\n<small><b>Note: </b> 51659#@gui : This filter can import any image data read by the <b>G'MIC</b> language interpreter. 51660#@gui : It includes exotic formats as : <i>Pandore, CImg, Inrimage, AVI/MPEG (requires FFMPEG installed), ...</i> 51661#@gui : </small>"} 51662#@gui : sep = separator() 51663#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 51664fx_import_image : skip "${1=}" 51665 rm i "$1" s z if $2 n 0,255 else c 0,255 fi 51666 51667#@gui Import RGB-565 File : fx_input_565 51668#@gui : Filename = filein() 51669#@gui : Width = text("800") 51670#@gui : Height = text("600") 51671#@gui : Reverse endianness = bool(0) 51672#@gui : sep = separator() 51673#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/05/03</i>.</small>") 51674fx_input_565 : skip "${1=}" 51675 l[] check "isint($2) && $2>0 && isint($3) && $3>0" 51676 onfail error "Invalid Specified Dimensions" 51677 endl 51678 if ['"$1"']==0 gui_warning_preview "Choose a filename" 51679 elif !isfile(['"$1"']) gui_warning_preview "Filename not found!" 51680 else input_565 "$1",${2-4} mv. 0 51681 fi 51682 51683#@gui Intarsia : fx_intarsia, fx_intarsia_preview 51684#@gui : note = note{"<small><b>Note:</b> 51685#@gui : Intarsia is a method of Crochet/Knitting with a number of colours, in which a separate ball of yarn 51686#@gui : is used for each area of colour. 51687#@gui : This filter creates a HTML version of a graph chart which is solely used for this purpose 51688#@gui : </small>"} 51689#@gui : sep = separator() 51690#@gui : Output Directory = _folder("") 51691#@gui : Output HTML File = _text("intarsia.html") 51692#@gui : sep = separator() 51693#@gui : Maximum Image Size = int(512,2,1024) 51694#@gui : Maximum Number of Image Colors = _int(12,2,64) 51695#@gui : Starting Point = choice(1,"Top Left","Top Right","Bottom Left","Bottom Right") 51696#@gui : Loop Method = choice("Row by Row","Column by Column") 51697#@gui : sep = separator() 51698#@gui : Add Comment Area in HTML Page = _bool(1) 51699#@gui : Preview Progress (%) = float(100,0,100) 51700#@gui : sep = separator() 51701#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/09/07</i>.</small>") 51702fx_intarsia : 51703 to_rgb repeat $! nm=${gui_layer_name[$>]} +l[$>] 51704 51705 # Constrain image for size and number of colors, and index it with colormap. 51706 if max(w,h)>$3 rr2d $3,$3,0 fi 51707 +colormap 0 51708 if w>$4 rm. +colormap $4,1 fi 51709 round[1] index[0] [1] 51710 51711 # Output header and title. 51712 0 nm. $nm ('{b}') f. 'if(x,i,if(i>=97&&i<=122,i-32,i))' image_basename={t} rm[-2,-1] 51713 ('"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\ 51714 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n\ 51715 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n\ 51716 <head></head><body bgcolor=\"#FFFDFF\"><center><font size=\"-1\">\n\ 51717 <h2>"$image_basename" ("{0,w}x{0,h}")</h2>\n\ 51718 <table cellpadding=\"8\"><tr><td>\n\ 51719 <table cellpadding=\"4\">\n"') 51720 51721 # Render image of colors. 51722 0 nm. "$2" image_name={b} rm. 51723 nb_cols={1,w} 51724 repeat $nb_cols 51725 color={1,I($>)} 51726 R={arg(1,$color)} G={arg(2,$color)} B={arg(3,$color)} 51727 ('${dec2hex\ {$R*65536+$G*256+$B}}') -. {'0'} r. 6,1,1,1,0,0,1,0 +. {'0'} 51728 f. if(i>=_'a'" && "i<=_'z',i+_'A'-_'a',i) 51729 hcolor={t} rm. 51730 48,32,1,4 fc. $color,255 frame. 1,1,0,0,0,255 o. "$1/"${image_name}_$>.png rm. 51731 ('"<tr><td><b>Colour "$>"</b></td><td><img src=\""${image_name}_$>.png"\" /></td><td>#"$hcolor"</td></tr>\n"') 51732 done 51733 ('"</table>\n</td><td>"') 51734 51735 # Render result and overview images. 51736 starting=${"arg {1+$5},\"Top left\",\"Top right\",\"Bottom left\",\"Bottom right\""} 51737 label=${"arg {1+$6},Row,Column"} 51738 if $6 dir0="T → B" dir1="B → T" else dir0="L → R" dir1="R → L" fi 51739 dir={arg(1+2*$5+$6,0,0,1,0,0,1,1,1)} 51740 51741 +map[0] [1] 51742 +fx_intarsia_preview. ${1-7},63 drgba. 51743 rr2d.. 200,200,1,1 51744 to_rgba[-2,-1] frame[-2,-1] 1,1,0,0,0,255 frame[-2,-1] 0,20,0,0,0,0 51745 t.. "Result",0,0,16,1,0,0,0,255 51746 t. "Ordering overview",0,0,16,1,0,0,0,255 51747 frame[-2,-1] 20,20,0,0,0,0 51748 51749 o.. "$1/"${image_name}_A.png 51750 o. "$1/"${image_name}_B.png 51751 rm[-2,-1] 51752 51753 ('"<table><tr><td><img src=\""${image_name}_A.png"\" /></td></tr><tr><td>"\ 51754 "<img src=\""${image_name}_B.png"\" /></td></tr></table></td></tr></table>\n"') 51755 if $7 ('"<p><b>Additional comments:</b><br/><textarea cols=\"80\" rows=\"10\" 51756 placeholder=\"Enter comments here...\"></textarea></p>\n"') fi 51757 ('"<p><b>Starting point:</b> "$starting"\ 51758 <b>Orientation:</b> "$label" by "$label"</p>\n"') 51759 rm[1] 51760 51761 # Output geometry. 51762 ('"<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\">\n"') 51763 51764 _fx_intarsia[0] $5,$6,0 51765 +l[0] 51766 s y 51767 repeat $! l[$>] 51768 if $>%2 mirror. x fi 51769 im={im} compress_rle 0,0 rows 6,100% 51770 ('"<tr><td valign=\"top\"><b>"$label" "{1+$>}"</b></td><td valign=\"top\">"${dir$dir}"</td><td>\n"') 51771 i=0 n=0 do 51772 val={0,i[$i]} i+=1 51773 if $val>=0 occ=1 51774 else 51775 occ={-$val} 51776 val={0,i[$i]} 51777 if $val<0 val=0 else i+=1 fi 51778 fi 51779 val+=$im 51780 ('"colour:<b>"$val"</b> "$occ') 51781 if {0,$i<h} ('", "') fi 51782 n+=1 51783 if !($n%8) ('"<br/>\n"') fi 51784 while $i<h#0 51785 ('"</td></tr>\n"') 51786 rm[0] a x 51787 dir={!$dir} 51788 endl done 51789 a x 51790 endl 51791 rm[0] 51792 51793 ('"</table>\n</font></center>\n</body>"') 51794 a x ot "$1/$2" 51795 rm 51796 endl done 51797 51798fx_intarsia_preview : 51799 to_rgb repeat $! l[$>] 51800 if max(w,h)>$3 rr2d $3,$3,0 fi 51801 to_rgba 51802 _fx_intarsia $5,$6,0 51803 100%,100%,1,1,'if(y%2,y*w+w-1-x,y*w+x)<$8*wh/100' * 51804 if min(w,h)<140 rr2d 140,140,1,1 fi 51805 expand_xy 16,0 51806 51807 100%,100% circle. 16,16,1%,1,1 51808 arrow3d. 0,0,0,{w/4},0,0,2%,15%,10% col3d. 1 j3d.. .,16,16,0,1,2,0,0 rm. 51809 +dilate. 3 r.. 100%,100%,1,3,0,0,0,0,0,0.5 a[-2,-1] c *. 255 51810 blend alpha 51811 51812 _fx_intarsia $5,$6,1 51813 endl done 51814 51815_fx_intarsia : 51816 if $3" && "$2 transpose fi 51817 if $1==0 # Start from top left. 51818 elif $1==1 # Start from top right. 51819 mirror x 51820 elif $1==2 # Start from bottom left. 51821 mirror y 51822 elif $1==3 # Start from bottom right. 51823 mirror xy 51824 fi 51825 if !$3" && "$2 transpose fi 51826 51827#@gui Sample Image : fx_image_sample, fx_image_sample_preview 51828#@gui : Input = choice{"Random","Apples","Balloons","Barbara","Boats","Bottles","Butterfly","Cameraman","Car","Cat", 51829#@gui : "Chick","Cliff","Colorful","David","Dog","Duck","Eagle","Elephant","Earth","Flower","Fruits", 51830#@gui : "Gmicky (Deevad)","Gmicky (Mahvin)","Gmicky & Wilber","Greece","Gummy","House","Inside","Landscape","Leaf", 51831#@gui : "Lena","Leno","Lion","Mandrill","Mona Lisa","Monkey","Parrots","Pencils","Peppers","Portrait0","Portrait1", 51832#@gui : "Portrait2","Portrait3","Portrait4","Portrait5","Portrait6","Portrait7","Portrait8","Portrait9", 51833#@gui : "Roddy","Rooster","Rose","Square","Swan","Teddy","Tiger","Tulips","Wall","Waterfall","Zelda"} 51834#@gui : note = note("<small>Choosing <b>0</b> for parameters <i>Width</i> or <i>Height</i> means <i>Automatic</i>. 51835#@gui : </small>") 51836#@gui : Width = _int(0,0,1024) 51837#@gui : Height = _int(0,0,1024) 51838#@gui : sep = separator() 51839#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/16/01</i>.</small>") 51840fx_image_sample : 51841 if $1 sp {$1-1},$2,$3 else sp ?,$2,$3 fi 51842 mv. 0 51843 51844fx_image_sample_preview : 51845 w={w} h={h} rm 51846 fx_image_sample $1,{$w>$h?$w:0},{$h>$w?$h:0} 51847 51848#@gui Solve Maze : fx_solve_maze, fx_solve_maze_preview(1) 51849#@gui : Starting Point (%) = point(5,5) 51850#@gui : Ending Point (%) = point(95,95) 51851#@gui : Smoothness = float(0.1,0,1) 51852#@gui : Thickness = int(3,1,10) 51853#@gui : Color = color(255,0,0) 51854#@gui : Maze Type = choice("Dark Walls","White Walls") 51855#@gui : sep = separator() 51856#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/01/09</i>.</small>") 51857fx_solve_maze : 51858 repeat $! 51859 +norm. >=. 50% 51860 if !$10 negate. fi 51861 *. 255 +b. $5% *.. 1e10 +[-2,-1] 51862 minimal_path. $1%,$2%,0,$3%,$4%,0 transpose. 51863 pointcloud. 0 dilate. $6 r. ..,..,1,1,0 51864 to_rgba. 51865 replace_color. 0,0,1,1,1,255,${7-9},255 51866 replace_color. 0,0,0,0,0,255,0,0,0,0 51867 ellipse. $1%,$2%,5,5,0,1,${7-9},255 51868 ellipse. $3%,$4%,5,5,0,1,${7-9},255 51869 rv[-2,-1] 51870 mv[-2,-1] 0 done 51871 51872fx_solve_maze_preview : 51873 drgba 51874 line $1%,$2%,$3%,$4%,1,0xCCCCCCCC,${7-9} 51875 ellipse $1%,$2%,3,3,0,1,${7-9} 51876 ellipse $1%,$2%,3,3,0,1,0x1,0 51877 ellipse $3%,$4%,3,3,0,1,${7-9} 51878 ellipse $3%,$4%,3,3,0,1,0x1,0 51879 51880#@gui _ 51881 51882#--------------------------------- 51883# 51884#@cli :: Additional Gallery Images 51885# 51886#--------------------------------- 51887#@cli _gallery_arrays 51888#@cli : This entry defines some examples of array filters for the G'MIC gallery page. 51889#@cli : $ image.jpg fx_frame_blur 30,30,0,5,0,0,128,128,128,0,5,255,255,255,2,2,1,0,0.5,0.5,0 _label="Frame~[blur]" 51890#@cli : $ sample tiger,leno,monkey,duck,eagle frame 3,3,0 frame 3,3,255 montage A _label="Montage" 51891#@cli : $ image.jpg fx_puzzle 5,5,0.5,0,0,0.3,100,0.2,255,100,0,0,0,0,0,0 _label="Puzzle" 51892 51893#@cli _gallery_artistic 51894#@cli : This entry defines some examples of artistic filters for the G'MIC gallery page. 51895#@cli : $ image.jpg fx_engrave 0.5,4,0,7.68,15.2,0,0,1,10,1,0,0,0,1,0 gui_merge_layers _label="Engrave" 51896#@cli : $ image.jpg fx_bokeh 3,8,0,30,8,4,0.3,0.2,210,210,80,160,0.7,30,20,20,1,2,170,130,20,110,0.15,0 _label="Bokeh" 51897#@cli : $ image.jpg fx_8bits 25,800,16,0 _label="Oldschool~8bits" 51898#@cli : $ image.jpg fire_edges 0.7,0.25,0.5,25,20 _fps=6 _label="Edges~on~fire" 51899#@cli : $ image.jpg fx_diffusiontensors 10,5,3,1,0.15,1,0,3,0 _label="Diffusion~tensors" 51900#@cli : $ image.jpg fx_dreamsmooth 3,1,1,0.8,0,0.8,1,24,0 _label="Dream~smoothing" 51901#@cli : $ image.jpg fx_feltpen 300,50,1,0.1,20,5,0 _label="Felt~pen" 51902#@cli : $ image.jpg gtutor_fpaint 0.5,0.5,0,0,45,0.5,0.5,0.5,0 _label="Finger~paint" 51903#@cli : $ image.jpg fx_graphic_novelfxl 0,2,6,5,20,0,0.62,14,0,1,0.5,0.78,1.92,0,0,0,1,1,1,0.5,0.8,1.28 \ 51904# _label="Novel~FX" 51905#@cli : $ image.jpg fx_illustration_look 100,0,0,0,0 _label="Illustration~look" 51906#@cli : $ image.jpg fx_lylejk_painting 10,2,4,10,0 _label="Lylejk~painting" 51907#@cli : $ image.jpg fx_painting 5,2.5,1.5,50,1,0 _label="Painting" 51908#@cli : $ image.jpg fx_posterize 150,30,1,6,0,0,1,0 _label="Posterize" 51909#@cli : $ image.jpg fx_quadtree 2,1024,1.05,0,2.33,0.68,0.39,1,0 _label="Quadtree~variations" 51910#@cli : $ image.jpg fx_vector_painting 9.37,0 _label="Vector~painting" 51911 51912#@cli _gallery_blackandwhite 51913#@cli : This entry defines some examples of black-and-white filters for the G'MIC gallery page. 51914#@cli : $ image.jpg fx_freaky_bw 90,20,0,0,0,0 _label="Freaky~B&W" 51915#@cli : $ image.jpg fx_engrave 0.5,50,0,8,40,0,0,0,10,1,0,0,0,1,0 _label="Engrave" 51916#@cli : $ image.jpg fx_gcd_layeretch 11,4,12,0.12,100,8.5,5,0,0,3,1,1,0 _label="Multi-layer~etch" 51917#@cli : $ image.jpg fx_pencil_portraitbw 30,120,1,0.5,144,79,21,0 _label="Pencil~portrait" 51918#@cli : $ image.jpg fx_gcd_etch 125,153,171,185,0.1,50,80,50,10,15,12,20,0,1,0.3,1,0,0 _label="Threshold~etch" 51919 51920#@cli _gallery_colors 51921#@cli : This entry defines some examples of color filters for the G'MIC gallery page. 51922#@cli : $ image.jpg fx_color_abstraction 1,10,0.2,0 _label="Color~abstraction" 51923#@cli : $ image.jpg fx_boost_chroma 90,0,0 _label="Boost~chromaticity" 51924#@cli : $ image.jpg fx_retrofade 20,6,40,0 _label="Retro~fade" 51925#@cli : $ image.jpg fx_tk_vintage 2,0.85,0.7,80,200,5,147,26,161,0.3,235,220,176,0.4,190,181,108,0.2,\ 51926# 0,0,100,0,0.3,25,0,0 _label="Vintage~style" 51927 51928#@cli _gallery_deformations 51929#@cli : This entry defines some examples of deformation filters for the G'MIC gallery page. 51930#@cli : $ image.jpg animate "flower","30,10,0,0","30,10,0,360",10 rm. _fps=6 _label="flower" 51931#@cli : $ image.jpg fx_conformal_maps 8,1,0,"((1.1 + i*z/6)/(1.04 - i*z/6))^6.2",0,0,0,0,0,3,0,0,"1024","1024" \ 51932# _label="Conformal~maps" 51933#@cli : $ image.jpg souphead_droste10 40,100,1,1,1,0,0,0,0,0,1,10,1,0,90,0,0,0,0,1,0,1,1,0,0,0,0,0,1,0,0 \ 51934# _label="Continuous~droste" 51935#@cli : $ image.jpg fx_crease 30,10,3 _label="Crease" 51936#@cli : $ image.jpg fx_distort_lens 0.29,0,0.23,50,50,0,0 _label="Distort~lens" 51937#@cli : $ image.jpg fx_drop_water 0,20,2,80,0,3,35,10,1,0.5,0.25,0.5,0.75,0.05,0.15,1 gui_merge_layers \ 51938# _label="Drop~water" 51939#@cli : $ image.jpg fx_reflect 50,1,110,160,190,64,0,1.5,0,-3.3,7,1.5 _label="Reflection" 51940#@cli : $ image.jpg fx_square_circle 0,1,0,0,0,0,0,0 _label="Square~to~circle" 51941#@cli : $ image.jpg fx_textured_glass 40,40,1,1,0,2,0,0 _label="Textured~glass" 51942#@cli : $ sample lena,leno,320 morph 40 _fps=5 _label="morph" 51943 51944#@cli _gallery_filtering 51945#@cli : This entry defines some examples of filters for the G'MIC gallery page. 51946#@cli : $ image.jpg fx_gcd_crt 1.8,1.8,0,0 equalize 256 _label="CRT~sub-pixels" 51947#@cli : $ image.jpg fx_dirty 30,1,0,0,0 _label="Dirty" 51948#@cli : $ image.jpg fx_freaky_details 2,10,1,11,0,32,0 _label="Freaky~details" 51949#@cli : $ image.jpg jeje_normalize_local_variance 50,5,5,1,0,0 _label="Local~variance~normalization" 51950#@cli : $ image.jpg fx_mighty_details 25,1,25,1,11,0 _label="Mighty~details" 51951 51952#@cli _gallery_patterns 51953#@cli : This entry defines some examples of pattern filters for the G'MIC gallery page. 51954#@cli : $ image.jpg fx_rain 65,10,50,0.1,1,1,0 gui_merge_layers _label="Rain~&~snow" 51955#@cli : $ 400,400,1,3 fx_camouflage 9,12,100,30,46,33,75,90,65,179,189,117,255,246,158 _label="Camouflage" 51956#@cli : $ image.jpg jeje_clouds 50,0.5 _label="Clouds" 51957#@cli : $ image.jpg fx_crystal 50,0.2,20,0 _label="Crystal" 51958#@cli : $ 400,400,1,3 fx_crystal_background 10,25,0,100,1 _label="Crystal~background" 51959#@cli : $ image.jpg fx_marble 0.5,1,0,0,0.4,0.6,0.6,1.1,0,100 _label="Marble" 51960#@cli : $ image.jpg fx_mineral_mosaic 1,2,1,100,0 _label="Mineral~mosaic" 51961#@cli : $ image.jpg fx_shapes 1,16,10,2,5,106.8,2,0,0,1,0 _label="Op~art" 51962#@cli : $ 400,400,1,3 fx_satin 20,1,0,0,0,0,255,255,255,255,255,0,0,0,-50,0,0 _label="Satin" 51963#@cli : $ 400,400,1,3 fx_seamless_turbulence 15,20,0,1,3,1 _label="Seamless~turbulence" 51964#@cli : $ image.jpg fx_shockwaves 10,10,20,0,0 _label="Shock~waves" 51965#@cli : $ 400,400,1,3 fx_equation_parametric "sin(t)*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)",\ 51966# "cos(t)*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)",0,100,4096,1,0,64,0,0,128,0,0,1,1,1 _label="Equation~plot~[parametric]" 51967#@cli : $ 400,400,1,3 KittyRings 30,8,0,1,113,0,113,0,255,0 _label="Kitaoka~spin~illusion" 51968#@cli : $ 400,400,1,3 fx_neon_lightning 50,50,0,50,50,100,50,0.7,3,130,80,50,0.25,0 _label="Neon~lighting" 51969#@cli : $ image.jpg fx_lava 8,5,3,0,0 _label="Lava" 51970#@cli : $ sample monkey,lion,monkey 100%,100% plasma. equalize. 256 transition[0,1,2] [3],10 rm. _fps=10 \ 51971# _label="transition" 51972#@cli : $ image.jpg fx_shapeism 2,7,0.38,0,1,5,32,8,3,1,5,0.5,1,0,0,0,255 _label="Shapeism" 51973 51974#@cli _gallery_3dmeshes 51975#@cli : This entry defines some examples of 3D rendering filters for the G'MIC gallery page. 51976#@cli : $ sample leno,lion,leno resize 400,400 transition3d 20,5,5 rm. _fps=10 _label="transition3d" 51977#@cli : $ 256,192 fx_text_pointcloud3d 64,"G'MIC","Rocks!",1,200,220,255,255,255,255,255,2,2,1,19 _fps=10 \ 51978# _label="3D~text~pointcloud" 51979 51980#@cli _gallery_stylization 51981#@cli : This entry defines some examples of image stylization for the G'MIC gallery page. 51982#@cli : $ sample car _fx_stylize starrynight _output_mode=1 \ 51983# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,5,2,1.85,0 _label="from~Van~Gogh:~Starry~Night" 51984#@cli : $ sample car _fx_stylize graytree _output_mode=1 \ 51985# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,2,2,1.85,0 _label="from~Mondrian:~Gray~Tree" 51986#@cli : $ sample car _fx_stylize yellowredblue _output_mode=1 \ 51987# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,10,2,1.85,0 \ 51988# _label="from~Kandinsky:~Yellow-Red-Blue" 51989#@cli : $ sample car _fx_stylize littlebayatlaciotat _output_mode=1 \ 51990# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,2,2,1.85,0 \ 51991# _label="from~Braque:~Little~Bay~at~La~Ciotat" 51992#@cli : $ sample car _fx_stylize leviaducalestaque _output_mode=1 \ 51993# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 \ 51994# _label="from~Braque:~Le~Viaduc~a~l'Estaque" 51995#@cli : $ sample car _fx_stylize greatwave _output_mode=1 \ 51996# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 _label="from~Hokusai:~The~Great~Wave" 51997#@cli : $ sample elephant input ../img/hatching.png _output_mode=1 \ 51998# +fx_stylize 1,4,0,0,1,2,3,0.5,0.1,3,3,0,0.7,0,0,1,0,5,5,7,1,30,1,2,1.85,0 _label="from~Hatch~Drawing" 51999#@cli : $ sample cat input ../img/hatching.png _output_mode=1 \ 52000# +fx_stylize 1,4,0,0,1,2,3,0.5,0.1,3,3,0,0.7,0,0,1,0,5,5,7,1,30,1,2,1.85,0 _label="from~Hatch~Drawing" 52001#@cli : $ sample bottles _fx_stylize starrynight _output_mode=1 \ 52002# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 _label="from~Van~Gogh:~Starry~Night" 52003#@cli : $ sample cat _fx_stylize summertime9a _output_mode=1 \ 52004# +fx_stylize 1,6,0,0,2,0,1,0.5,0.1,3,3,0,0.7,0,2,1,0,5,5,7,1,130,10,2,1.85,0 _label="from~Pollock:~Summertime~No~9A" 52005#@cli : $ sample cat _fx_stylize greatwave _output_mode=1 \ 52006# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 _label="from~Hokusai:~The~Great~Wave" 52007#@cli : $ sample dog _fx_stylize convergence _output_mode=1 \ 52008# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,5,2,1.85,0 _label="from~Pollock:~Convergence" 52009#@cli : $ sample dog _fx_stylize irises _output_mode=1 \ 52010# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,1,5,0,0.7,1,0,1,0,5,5,7,1,30,20,2,1.85,0 _label="from~Van~Gogh:~Irises" 52011#@cli : $ sample mandrill _fx_stylize themandola _output_mode=1 \ 52012# +fx_stylize 1,5,0,0,0,3,1,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 _label="from~Braque:~The~Mandola" 52013#@cli : $ sample square _fx_stylize orientalpleasuregardenanagoria _output_mode=1 \ 52014# +fx_stylize 1,6,0,0,0.52,0.5,3,0.14,0.1,3,3,0,0.7,3.39,0,1,0,5,5,7,5,30,4,2,1.85,0 \ 52015# _label="from~Klee:~Oriental~Pleasure~Garden~Anagoria" 52016#@cli : $ sample monalisa _fx_stylize squareswithconcentriccircles _output_mode=1 \ 52017# +fx_stylize 1,4,0,0,0.15,3,2,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 \ 52018# _label="from~Kandisnky:~Squares~with~Concentric~Circles" 52019#@cli : $ sample monalisa _fx_stylize inthestyleofkairouan _output_mode=1 \ 52020# +fx_stylize 1,4,2,0,0.15,3,2,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,5,2,1.85,0 \ 52021# _label="from~Klee:~In~the~Style~of~Kairouan" 52022#@cli : $ sample square _fx_stylize polyphony2 _output_mode=1 \ 52023# +fx_stylize 1,6,0,0,0.15,3,2,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 _label="from~Klee:~Polyphony~2" 52024#@cli : $ sample square _fx_stylize wheatstacksendofsummer _output_mode=1 \ 52025# +fx_stylize 1,6,0,0,0.15,3,2,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 \ 52026# _label="from~Monet:~Wheatstacks~-~End~of~Summer" 52027#@cli : $ sample square _fx_stylize portraitdemetzinger _output_mode=1 \ 52028# +fx_stylize 1,5,0,0,0.1,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,10,2,1.85,0 \ 52029# _label="from~Delaunay:~Portrait~de~Metzinger" 52030#@cli : $ sample monalisa input ../img/mandelbrot.jpg _output_mode=1 \ 52031# +fx_stylize 1,3,3,0,0.15,4,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,5,2,1.85,0 _label="from~Mandelbrot~Fractal~Set" 52032#@cli : $ sample bottles _fx_stylize redtree _output_mode=1 \ 52033# +fx_stylize 1,5,0,0,2.12,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 \ 52034# _label="from~Mondrian:~Evening;~Red~Tree" 52035#@cli : $ sample bottles _fx_stylize redwaistcoat _output_mode=1 \ 52036# +fx_stylize 1,4,0,0,0.67,3.17,3,0.5,0.06,3,3,0,0.7,5,0,2,0,5,5,7,1,30,5,1.05,1.85,0 \ 52037# _label="from~Klee:~Red~Waistcoat" 52038#@cli : $ sample bottles _fx_stylize reservoirhortadeebro _output_mode=1 \ 52039# +fx_stylize 1,6,0,0,0.5,2,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 _label="from~Picasso:~The~Reservoir" 52040#@cli : $ sample bottles _fx_stylize almondblossom _output_mode=1 \ 52041# +fx_stylize 1,6,0,0,0,3,3,0.5,0.1,3,3,0,0.7,5,0,2,0,5,5,7,1,30,1,2,1.85,0 _label="from~Van~Gogh:~Almond~Blossom" 52042#@cli : $ sample bottles _fx_stylize landscapenearantwerp _output_mode=1 \ 52043# +fx_stylize 1,6,0,0,2.17,3.65,3,0.5,0.1,3,3,0,0.7,1,0,1,0,5,5,7,1,30,1,2,1.85,0 \ 52044# _label="from~Braque:~Landscape~near~Antwerp" 52045#@cli : $ sample bottles _fx_stylize wheatfieldwithcrows _output_mode=1 \ 52046# +fx_stylize 1,6,0,0,3.86,2,3,0.5,0.1,3,3,0,0.7,3.35,1,1,0,5,5,7,1,30,1,5,1.85,0 \ 52047# _label="from~Van~Gogh:~Wheat~Field~with~Crows" 52048 52049#@cli _gallery_codesamples 52050#@cli : This entry defines some examples of coding fun filters for the G'MIC gallery page. 52051#@cli : $ https://gmic.eu/samples/lissajous.gmic go _fps=10 _label="Lissajous" 52052#@cli : $ https://gmic.eu/samples/torus3d.gmic go _fps=10 _label="3D~torus" 52053#@cli : $ https://gmic.eu/samples/pacman.gmic go _fps=25 _label="Pacman" 52054#@cli : $ https://gmic.eu/samples/scrolling.gmic go _fps=25 _label="Scrolling" 52055#@cli : $ https://gmic.eu/samples/landscape.gmic go _fps=12 _label="Landscape" 52056#@cli : $ https://gmic.eu/samples/mandelbrot.gmic go _fps=8 _label="Mandelbrot" 52057#@cli : $ https://gmic.eu/samples/heart.gmic go _fps=15 _label="Heart" 52058#@cli : $ https://gmic.eu/samples/distortion.gmic go _fps=20 _label="Distortion" 52059#@cli : $ https://gmic.eu/samples/rotozoom.gmic go _fps=15 _label="Rotozoom" 52060#@cli : $ https://gmic.eu/samples/french_flag.gmic go _fps=20 _label="French~Flag" 52061 52062# Local Variables: 52063# mode: sh 52064# End: 52065# 52066# (End of G'MIC custom commands) 52067