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" - 'w': display width (i.e. width of the display area managed by the window)."\n\ 603" - 'h': display height (i.e. height of the display area managed by the window)."\n\ 604" - 'wh': display width x display 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" - 'u': screen width (actually independent on the window size)."\n\ 609" - 'v': screen height (actually independent on the window size)."\n\ 610" - 'uv': screen width x screen height."\n\ 611" - 'n': current normalization type of the instant display."\n\ 612" - 't': window title of the instant display."\n\ 613" - 'x': X-coordinate of the mouse position (or -1, if outside the display area)."\n\ 614" - 'y': Y-coordinate of the mouse position (or -1, if outside the display area)."\n\ 615" - 'b': state of the mouse buttons { 1=left-but. | 2=right-but. | 4=middle-but. }."\n\ 616" - 'o': state of the mouse wheel."\n\ 617" - 'k': decimal code of the pressed key if any, 0 otherwise."\n\ 618" - 'c': boolean (0 or 1) telling if the instant display has been closed recently."\n\ 619" - 'r': boolean telling if the instant display has been resized recently."\n\ 620" - 'm': boolean telling if the instant display has been moved recently."\n\ 621" - Any other 'feature' stands for a keycode name (in capital letters), and is substituted "\ 622"by a boolean describing the current key state { 0=pressed | 1=released }."\n\ 623" - You can also prepend a hyphen '-' to a 'feature' (that supports it) to flush the "\ 624"corresponding event immediately after reading its state (works for keys, mouse and window events)."\n\ 625\n\ 626"* Item substitution is __never__ performed in items between double quotes. One must break the quotes "\ 627"to enable substitution if needed, as in '\"3+8 kg = \"{3+8}\" kg\"'. Using double quotes is then "\ 628"a convenient way to disable the substitutions mechanism in items, when necessary."\n\ 629"* One can also disable the substitution mechanism on items outside double quotes, by escaping the "\ 630"`{`, `}` or `$` characters, as in `\\{3+4\\}\\ doesn\47t\\ evaluate`." 631 632 _section "Mathematical Expressions" 633 _text \ 634"* \\G'MIC has an embedded __mathematical parser__, used to evaluate (possibly complex) math expressions "\ 635"specified inside braces '{}', or formulas in commands that may take one as an argument (e.g. ''fill'' or ''eval'')."\n\ 636"* When the context allows it, a formula is evaluated __for each pixel__ of the selected images "\ 637"(e.g. ''fill'' or ''eval'')."\n\ 638"* A math expression may return a __scalar__ or a __vector-valued__ result (with a fixed number of components)."\n\ 639"The mathematical parser understands the following set of functions, operators and variables:"\n\ 640"## Usual operators:"\n\ 641"'||' (logical or), '&&' (logical and), '|' (bitwise or), '&' (bitwise and), "\ 642"'!=', '==', '<=', '>=', '<', '>', '<<' (left bitwise shift), '>>' (right bitwise shift), '-', '+', '*', '/', "\ 643"'%' (modulo), '^' (power), '!' (logical not), '~' (bitwise not), '++', '--', '+=', '-=', '*=', '/=', '%=', "\ 644"'&=', '|=', '^=', '>>', '<<=' (in-place operators)."\n\ 645"## Usual math functions:"\n\ 646"'abs()', 'acos()', 'acosh()', 'arg()', 'arg0()', 'argkth()', 'argmax()', 'argmaxabs()', "\ 647"'argmin()', 'argminabs()', 'asin()', 'asinh()', 'atan()', 'atan2()', 'atanh()', 'avg()', 'bool()', 'cbrt()', "\ 648"'ceil()', 'cos()', 'cosh()', 'cut()', 'deg2rad()', 'erf()', 'erfinv()', 'exp()', 'fact()', 'fibo()', 'floor()', "\ 649"'gauss()', 'gcd()', 'int()', 'isnan()', 'isnum()', 'isinf()', 'isint()', 'isbool()', 'isexpr()', 'isfile()', "\ 650"'isdir()', 'isin()', 'kth()', 'log()', 'log2()', 'log10()', 'max()', 'maxabs()', 'med()', 'min()', 'minabs()', "\ 651"'narg()', 'prod()', 'rad2deg()', 'rol()' (left bit rotation), 'ror()' (right bit rotation), 'round()', 'sign()', "\ 652"'sin()', 'sinc()', 'sinh()', 'sqrt()', 'std()', 'srand(_seed)', 'sum()', 'tan()', 'tanh()', 'var()', 'xor()'."\n\ 653\n\ 654"* 'atan2(y,x)' is the version of 'atan()' with two arguments 'y' and 'x' (as in C/C++)."\n\ 655"* 'permut(k,n,with_order)' computes the number of permutations of 'k' objects from a set of 'n' objects."\n\ 656"* 'gauss(x,_sigma,_is_normalized)' returns `exp(-x^2/(2*s^2))/(is_normalized?sqrt(2*pi*sigma^2):1)`."\n\ 657"* 'cut(value,min,max)' returns 'value' if it is in range '[min,max]', or 'min' or 'max' otherwise."\n\ 658"* 'narg(a_1,...,a_N)' returns the number of specified arguments (here, 'N')."\n\ 659"* 'arg(i,a_1,..,a_N)' returns the `i`-th argument 'a_i'."\n\ 660"* 'isnum()', 'isnan()', 'isinf()', 'isint()', 'isbool()' test the type of the given number or expression, "\ 661"and return '0' (false) or '1' (true)."\n\ 662"* 'isfile('path')' (resp. 'isdir('path')') returns '0' (false) or '1' (true) whether its string argument is a "\ 663"path to an existing file (resp. to a directory) or not."\n\ 664"* 'isin(v,a_1,...,a_n)' returns '0' (false) or '1' (true) whether the first value 'v' appears in the set of other "\ 665"values 'a_i'."\n\ 666"* 'inrange(value,m,M,include_m,include_M)' returns '0' (false) or '1' (true) whether the specified value lies in "\ 667"range '[m,M]' or not ('include_m' and 'includeM' tells how boundaries 'm' and 'M' are considered)."\n\ 668"* 'argkth()', 'argmin()', 'argmax()', 'argminabs()', 'argmaxabs()'', 'avg()', 'kth()', 'min()', 'max()', 'minabs()', "\ 669"'maxabs()', 'med()', 'prod()', 'std()', 'sum()' and 'var()' can be called with an arbitrary number of scalar/vector "\ 670"arguments."\n\ 671"* 'vargkth()', 'vargmin()', 'vargmax()', 'vargminabs()', 'vargmaxabs()', 'vavg()', 'vkth()', 'vmin()', "\ 672"'vmax()', 'vminabs()', 'vmaxabs()', 'vmed()', 'vprod()', 'vstd()', 'vsum()' and 'vvar()' are the versions of the "\ 673"previous function with vector-valued arguments."\n\ 674"* 'round(value,rounding_value,direction)' returns a rounded value. 'direction' can be "\ 675"{ -1=to-lowest | 0=to-nearest | 1=to-highest }."\n\ 676"* 'lerp(a,b,t)' returns 'a*(1-t)+b*t'."\n\ 677"* 'swap(a,b)' swaps the values of the given arguments."\n\ 678"## Variable names:"\n\ 679"Variable names below are pre-defined. They can be overridden."\n\ 680"* 'l': length of the associated list of images."\n\ 681"* 'k': index of the associated image, in '[0,l-1]'."\n\ 682"* 'w': width of the associated image, if any ('0' otherwise)."\n\ 683"* 'h': height of the associated image, if any ('0' otherwise)."\n\ 684"* 'd': depth of the associated image, if any ('0' otherwise)."\n\ 685"* 's': spectrum of the associated image, if any ('0' otherwise)."\n\ 686"* 'r': shared state of the associated image, if any ('0' otherwise)."\n\ 687"* 'wh': shortcut for width x height."\n\ 688"* 'whd': shortcut for width x height x depth."\n\ 689"* 'whds': shortcut for width x height x depth x spectrum (i.e. number of image values)."\n\ 690"* 'im', 'iM', 'ia', 'iv', 'is', 'ip', 'ic', 'in': Respectively the minimum, maximum, average, variance, sum, "\ 691"product, median value and L2-norm of the associated image, if any ('0' otherwise)."\n\ 692"* 'xm', 'ym', 'zm', 'cm': The pixel coordinates of the minimum value in the associated image, "\ 693"if any ('0' otherwise)."\n\ 694"* 'xM', 'yM', 'zM', 'cM': The pixel coordinates of the maximum value in the associated image, "\ 695"if any ('0' otherwise)."\n\ 696"* All these variables are considered as __constant values__ by the math parser (for optimization purposes) "\ 697"which is indeed the case most of the time. Anyway, this might not be the case, if function 'resize(#ind,..)' "\ 698"is used in the math expression. If so, it is safer to invoke functions 'l()', 'w(_#ind)', 'h(_#ind)', ... 's(_#ind)' "\ 699"and 'in(_#ind)' instead of the corresponding named variables."\n\ 700"* 'i': current processed pixel value (i.e. value located at `(x,y,z,c)`) in the associated image, "\ 701"if any ('0' otherwise)."\n\ 702"* 'iN': N-th channel value of current processed pixel (i.e. value located at `(x,y,z,N)` in the associated image, "\ 703"if any ('0' otherwise). 'N' must be an integer in range '[0,9]'."\n\ 704"* 'R', 'G', 'B' and 'A' are equivalent to 'i0', 'i1', 'i2' and 'i3' respectively."\n\ 705"* 'I': current vector-valued processed pixel in the associated image, if any ('0' otherwise). "\ 706"The number of vector components is equal to the number of image channels (e.g. 'I' = `[ R,G,B ]` for a "\ 707"`RGB` image)."\n\ 708"* You may add '#ind' to any of the variable name above to retrieve the information for any "\ 709"numbered image '[ind]' of the list (when this makes sense). For instance 'ia#0' denotes the average value of the "\ 710"first image of the list)."\n\ 711"* 'x': current processed column of the associated image, if any ('0' otherwise)."\n\ 712"* 'y': current processed row of the associated image, if any ('0' otherwise)."\n\ 713"* 'z': current processed slice of the associated image, if any ('0' otherwise)."\n\ 714"* 'c': current processed channel of the associated image, if any ('0' otherwise)."\n\ 715"* 't': thread id when an expression is evaluated with multiple threads ('0' means __master thread__)."\n\ 716"* 'n': maximum number of threads when expression is evaluated in parallel (so that 't' goes from '0' to 'n-1')."\n\ 717"* 'e': value of e, i.e. `2.71828...`."\n\ 718"* 'pi': value of pi, i.e. `3.1415926...`."\n\ 719"* 'u': a random value between '[0,1]', following a uniform distribution."\n\ 720"* 'g': a random value, following a gaussian distribution of variance 1 (roughly in '[-6,6]')."\n\ 721"* 'interpolation': value of the default interpolation mode used when reading pixel values with the pixel access "\ 722"operators (i.e. when the interpolation argument is not explicitly specified, see below for more details on pixel "\ 723"access operators). Its initial default value is '0'."\n\ 724"* 'boundary': value of the default boundary conditions used when reading pixel values with the pixel access "\ 725"operators (i.e. when the boundary condition argument is not explicitly specified, see below for more details "\ 726"on pixel access operators). Its initial default value is '0'."\n\ 727"* The last image of the list is always associated to the evaluations of 'expressions', e.g. G'MIC sequence "\ 728"\n~~~\n256,128 fill {w}\n~~~\n will create a 256x128 image filled with value 256."\n\ 729"## Vector calculus:"\n\ 730"Most operators are also able to work with vector-valued elements."\n\ 731"* '[a0,a1,...,aN-1]' defines a 'N'-dimensional vector with scalar coefficients 'ak'."\n\ 732"* 'vectorN(a0,a1,,...,aN-1)' does the same, with the 'ak' being repeated periodically if only a few are specified."\n\ 733"* 'vector(#N,a0,a1,,...,aN-1)' does the same, and can be used for any constant expression 'N'."\n\ 734"* In previous expressions, the 'ak' can be vectors themselves, to be concatenated into a single vector."\n\ 735"* The scalar element 'ak' of a vector 'X' is retrieved by 'X[k]'."\n\ 736"* 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\ 737"* 'expr(formula,_w,_h,_d,_s)' outputs a vector of size 'w*h*d*s' with values generated from "\ 738"the specified formula, as if one were filling an image with dimensions '(w,h,d,s)'."\n\ 739"* Equality/inequality comparisons between two vectors is done with operators '==' and '!='."\n\ 740"* Some vector-specific functions can be used on vector values: "\ 741"'cross(X,Y)' (cross product), 'dot(X,Y)' (dot product), 'size(X)' (vector dimension), "\ 742"'sort(X,_is_increasing,_nb_elts,_size_elt)' (sorted values), 'reverse(A)' (reverse order of components), "\ 743"'shift(A,_length,_boundary_conditions)' and 'same(A,B,_nb_vals,_is_case_sensitive)' (vector equality test)."\n\ 744"* Function 'normP(u1,...,un)' computes the LP-norm of the specified vector ('P' being an `unsigned integer` constant "\ 745"or 'inf'). If 'P' is omitted, the L2 norm is calculated."\n\ 746"* Function 'resize(A,size,_interpolation,_boundary_conditions)' returns a resized version of a vector 'A' with "\ 747"specified interpolation mode. 'interpolation' can be "\ 748"{ -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | 4=grid | 5=bicubic | 6=lanczos }, and "\ 749"'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }."\n\ 750"* Function 'find(A,B,_starting_index,_search_step)' returns the index where sub-vector 'B' appears in vector 'A', "\ 751"(or '-1' if 'B' is not contained in 'A'). Argument 'A' can be also replaced by an image index '#ind'."\n\ 752"* A `2`-dimensional vector may be seen as a complex number and used in those particular functions/operators: "\ 753"'**' (complex multiplication), '//' (complex division), '^^' (complex exponentiation), "\ 754"'**=' (complex self-multiplication), '//=' (complex self-division), '^^=' (complex self-exponentiation), "\ 755"'cabs()' (complex modulus), 'carg()' (complex argument), 'cconj()' (complex conjugate), "\ 756"'cexp()' (complex exponential), 'clog()' (complex logarithm), 'ccos()' (complex cosine), "\ 757"'csin()' (complex sine), 'ctan()' (complex tangent), 'ccosh()' (complex hyperpolic cosine), "\ 758"'csinh()' (complex hyperbolic sine) and 'ctanh()' (complex hyperbolic tangent)."\n\ 759"* A `MN`-dimensional vector may be seen as a `M` x `N` matrix and used in those particular functions/operators: "\ 760"'*' (matrix-vector multiplication), 'det(A)' (determinant), 'diag(V)' (diagonal matrix from a vector), "\ 761"'eig(A)' (eigenvalues/eigenvectors), 'eye(n)' (n x n identity matrix), 'invert(A,_solver)' (matrix inverse), "\ 762"'mul(A,B,_nb_colsB)' (matrix-matrix multiplication), 'pseudoinvert(A,_nb_colsA,_solver)', "\ 763"'rot(u,v,w,angle)' (3D rotation matrix), 'rot(angle)' (2D rotation matrix), "\ 764"'solve(A,B,_nb_colsB)' (solver of linear system A.X = B), 'svd(A,_nb_colsA)' (singular value decomposition), "\ 765"'trace(A)' (matrix trace) and 'transpose(A,nb_colsA)' (matrix transpose). Argument 'nb_colsB' may be omitted if "\ 766"it is equal to `1`".\n\ 767"* 'mproj(S,nb_colsS,D,nb_colsD,method,max_iter,max_residual)' projects a matrix 'S' onto a dictionary (matrix) "\ 768"'D'. Equivalent to command ''mproj'' but inside the math evaluator."\n\ 769"* Specifying a vector-valued math expression as an argument of a command that operates on image values "\ 770"(e.g. 'fill') modifies the whole spectrum range of the processed image(s), for each spatial coordinates `(x,y,z)`. "\ 771"The command does not loop over the `c`-axis in this case."\n\ 772"## String manipulation:"\n\ 773"Character strings are defined and managed as vectors objects. "\ 774"Dedicated functions and initializers to manage strings are:"\n\ 775"* `['string']` and `'string'` define a vector whose values are the character codes of the "\ 776"specified `character string` (e.g. `'foo'` is equal to `[ 102,111,111 ]`)."\n\ 777"* `_'character'` returns the (scalar) byte code of the specified character (e.g. `_'A'` is equal to '65')."\n\ 778"* A special case happens for __empty__ strings: Values of both expressions `['']` and `''` are '0'."\n\ 779"* Functions 'lowercase()' and 'uppercase()' return string with all string characters lowercased or uppercased."\n\ 780"* Function 'stov(str,_starting_index,_is_strict)' parses specified string 'str' and returns the value contained "\ 781"in it."\n\ 782"* Function 'vtos(expr,_nb_digits,_siz)' returns a vector of size 'siz' which contains the character representation "\ 783"of values described by expression 'expr'. "\ 784"'nb_digits' can be { -1=auto-reduced | 0=all | >0=max number of digits }."\n\ 785"* Function 'echo(str1,str2,...,strN)' prints the concatenation of given string arguments on the console."\n\ 786"* Function 'string(_#siz,str1,str2,...,strN)' generates a vector corresponding to the concatenation of given "\ 787"string/number arguments."\n\ 788"## Special operators:"\n\ 789"* ';': expression separator. The returned value is always the last encountered expression. "\ 790"For instance expression '1;2;pi' is evaluated as 'pi'."\n\ 791"* '=': variable assignment. Variables in mathematical parser can only refer to numerical "\ 792"values (vectors or scalars). Variable names are case-sensitive. Use this operator in conjunction with ';' to define "\ 793"more complex evaluable expressions, such as \n~~~\nt = cos(x); 3*t^2 + 2*t + 1\n~~~\n"\ 794"These variables remain __local__ to the mathematical parser and cannot be accessed outside the evaluated "\ 795"expression."\n\ 796"* Variables defined in math parser may have a __constant__ property, by specifying keyword 'const' before the "\ 797"variable name (e.g. 'const foo = pi/4;'). The value set to such a variable must be indeed a __constant scalar__. "\ 798"Constant variables allows certain types of optimizations in the math JIT compiler."\n\ 799\ 800"## Specific functions:"\n\ 801"* 'addr(expr)': return the pointer address to the specified expression 'expr'. "\n\ 802"* 'fill(target,expr)' or 'fill(target,index_name,expr)' fill the content of the specified target "\ 803"(often vector-valued) using a given expression, e.g. `V = vector16(); fill(V,k,k^2 + k + 1);`. "\ 804"For a vector-valued target, it is basically equivalent to: "\ 805"`for (index_name = 0, index_name<size(target), ++index_name, target[index_name] = expr);`."\n\ 806"* 'u(max)' or 'u(min,max)': return a random value between '[0,max]' or '[min,max]', following a uniform "\ 807"distribution."\n\ 808"* 'f2ui(value)' and 'ui2f(value)': Convert a large unsigned integer as a negative floating point value "\ 809"(and vice-versa), so that 32bits floats can be used to store large integers while keeping a unitary precision."\n\ 810"* 'i(_a,_b,_c,_d,_interpolation_type,_boundary_conditions)': return the value of the pixel located at position "\ 811"`(a,b,c,d)` in the associated image, if any ('0' otherwise). "\ 812"'interpolation_type' can be { 0=nearest neighbor | 1=linear | 2=cubic }. "\ 813"'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. "\ 814"Omitted coordinates are replaced by their default values which are respectively 'x', 'y', 'z', 'c', 'interpolation' "\ 815"and 'boundary'. For instance command \n~~~\nfill 0.5*(i(x+1)-i(x-1))\n~~~\n will estimate the X-derivative of an "\ 816"image with a classical finite difference scheme."\n\ 817"* 'j(_dx,_dy,_dz,_dc,_interpolation_type,_boundary_conditions)' does the same for the pixel located at position "\ 818"`(x+dx,y+dy,z+dz,c+dc)` (pixel access relative to the current coordinates)."\n\ 819"* 'i[offset,_boundary_conditions]' returns the value of the pixel located at specified 'offset' in the associated "\ 820"image buffer (or '0' if offset is out-of-bounds)."\n\ 821"* 'j[offset,_boundary_conditions]' does the same for an offset relative to the current pixel coordinates "\ 822"`(x,y,z,c)`."\n\ 823"* 'i(#ind,_x,_y,_z,_c,_interpolation,_boundary_conditions)', "\ 824"'j(#ind,_dx,_dy,_dz,_dc,_interpolation,_boundary_conditions)', 'i[#ind,offset,_boundary_conditions]' and "\ 825"'i[offset,_boundary_conditions]' are similar expressions used to access pixel values for any numbered image '[ind]' "\ 826"of the list."\n\ 827"* 'I/J[offset,_boundary_conditions]' and 'I/J(#ind,_x,_y,_z,_interpolation,_boundary_conditions)' do the same as "\ 828"'i/j[offset,_boundary_conditions]' and 'i/j(#ind,_x,_y,_z,_c,_interpolation,_boundary_conditions)' but return a "\ 829"vector instead of a scalar (e.g. a vector `[ R,G,B ]` for a pixel at `(a,b,c)` in a color image)."\n\ 830"* 'crop(_#ind,_x,_y,_z,_c,_dx,_dy,_dz,_dc,_boundary_conditions)' returns a vector whose values come from the "\ 831"cropped region of image '[ind]' (or from default image selected if 'ind' is not specified). Cropped region starts "\ 832"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 "\ 833"if they are not ambiguous (e.g. 'crop(#ind,x,y,dx,dy)' is a valid invocation of this function)."\n\ 834"* 'draw(_#ind,S,x,y,z,c,dx,_dy,_dz,_dc,_opacity,_M,_max_M)' draws a sprite 'S' in image '[ind]' "\ 835"(or in default image selected if 'ind' is not specified) at coordinates `(x,y,z,c)`. "\ 836"The size of the sprite `dx x dy x dz x dc` must be specified. You can also specify a corresponding opacity mask "\ 837"'M' if its size matches 'S'."\n\ 838"* 'polygon(_#ind,nb_vertices,coords,_opacity,_color)' draws a filled polygon in image '[ind]' (or in default image "\ 839"selected if 'ind' is not specified) at specified coordinates. It draws a single line if 'nb_vertices' is set to 2."\n\ 840"* 'polygon(_#ind,-nb_vertices,coords,_opacity,_pattern,_color)' draws a outlined polygon in image '[ind]' (or in "\ 841"default image selected if 'ind' is not specified) at specified coordinates and with specified line pattern. "\ 842"It draws a single line if 'nb_vertices' is set to 2."\n\ 843"* 'ellipse(_#ind,xc,yc,radius1,_radius2,_angle,_opacity,_color)' draws a filled ellipse in image '[ind]' "\ 844"(or in default image selected if 'ind' is not specified) with specified coordinates."\n\ 845"* 'ellipse(_#ind,xc,yc,-radius1,-_radius2,_angle,_opacity,_pattern,_color)' draws an outlined ellipse in image "\ 846"'[ind]' (or in default image selected if 'ind' is not specified)."\n\ 847"* 'resize(#ind,w,_h,_d,_s,_interp,_boundary_conditions,_cx,_cy,_cz,_cc)' resizes an image of the associated list "\ 848"with specified dimension and interpolation method. When using this function, you should consider retrieving the "\ 849"(non-constant) image dimensions using the dynamic functions 'w(_#ind)', 'h(_#ind)', 'd(_#ind)', 's(_#ind)', "\ 850"'wh(_#ind)', 'whd(_#ind)' and 'whds(_#ind)' instead of the corresponding constant variables."\n\ 851"* 'if(condition,expr_then,_expr_else)': return value of 'expr_then' or 'expr_else', depending on the value of "\ 852"'condition' { 0=false | other=true }. 'expr_else' can be omitted in which case '0' is returned if the condition "\ 853"does not hold. Using the ternary operator 'condition?expr_then[:expr_else]' gives an equivalent expression. "\ 854"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 "\ 855"vertical lines on every 10th column of an image."\n\ 856"* 'do(expression,_condition)' repeats the evaluation of 'expression' until 'condition' vanishes "\ 857"(or until 'expression' vanishes if no 'condition' is specified). For instance, the expression: "\ 858"\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 "\ 859"sequence, for 'N>=0' (e.g., '46368' for 'N=24'). 'do(expression,condition)' always evaluates the specified "\ 860"expression at least once, then check for the loop condition. When done, it returns the last value of 'expression'."\n\ 861"* 'for(init,condition,_procedure,body)' first evaluates the expression 'init', then iteratively evaluates 'body' "\ 862"(followed by 'procedure' if specified) while 'condition' holds (i.e. not zero). It may happen that no iterations are "\ 863"done, in which case the function returns 'nan'. Otherwise, it returns the last value of 'body'. "\ 864"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 "\ 865"returns the 'N'-th value of the Fibonacci sequence, for 'N>=0' (e.g., '46368' for 'N=24')."\n\ 866"* 'while(condition,expression)' is exactly the same as 'for(init,condition,expression)' without the specification of "\ 867"an initializing expression."\n\ 868"* 'repeat(nb_iters,expr)' or 'fill(nb_iters,iter_name,expr)' run 'nb_iters' iterations of the specified expression "\ 869"'expr', e.g. `V = vector16(); repeat(16,k,V[k] = k^2 + k + 1);`. "\ 870"It is basically equivalent to: "\ 871"`for (iter_name = 0, iter_name<nb_iters, ++iter_name, expr);`."\n\ 872"* 'break()' and 'continue()' respectively breaks and continues the current running bloc "\ 873"(loop, init or main environment)."\n\ 874"* 'fsize('filename')' returns the size of the specified 'filename' (or '-1' if file does not exist)."\n\ 875"* 'date(attr,'path')' returns the date attribute for the given 'path' (file or directory), "\ 876"with 'attr' being { 0=year | 1=month | 2=day | 3=day of week | 4=hour | 5=minute | 6=second }, or a vector "\ 877"of those values."\n\ 878"* 'date(_attr)' returns the specified attribute for the current (locale) date (attributes being "\ 879"{ 0...6=same meaning as above | 7=milliseconds })."\n\ 880"* 'print(expr1,expr2,...)' or 'print(#ind)' prints the value of the specified expressions (or image information) "\ 881"on the console, and returns the value of the last expression (or 'nan' in case of an image). "\ 882"Function 'prints(expr)' also prints the string composed of the character codes defined by the vector-valued "\ 883"expression (e.g. 'prints('Hello')')."\n\ 884"* 'debug(expression)' prints detailed debug info about the sequence of operations done by the math parser to "\ 885"evaluate the expression (and returns its value)."\n\ 886"* 'display(_X,_w,_h,_d,_s)' or 'display(#ind)' display the contents of the vector 'X' (or specified image) and "\ 887"wait for user events. if no arguments are provided, a memory snapshot of the math parser environment is displayed "\ 888"instead."\n\ 889"* 'begin(expression)' and 'end(expression)' evaluates the specified expressions only once, respectively at the "\ 890"beginning and end of the evaluation procedure, and this, even when multiple evaluations are required "\ 891"(e.g. in 'fill \">begin(foo = 0); ++foo\"')."\n\ 892"* 'copy(dest,src,_nb_elts,_inc_d,_inc_s,_opacity)' copies an entire memory block of 'nb_elts' elements starting "\ 893"from a source value 'src' to a specified destination 'dest', with increments defined by 'inc_d' and 'inc_s' "\ 894"respectively for the destination and source pointers."\n\ 895"* 'stats(_#ind)' returns the statistics vector of the running image '[ind]', i.e the vector "\ 896"`[ im,iM,ia,iv,xm,ym,zm,cm,xM,yM,zM,cM,is,ip ]` (14 values)."\n\ 897"* 'ref(expr,a)' references specified expression 'expr' as variable name 'a'."\n\ 898"* 'unref(a,b,...)' destroys references to the named variable given as arguments."\n\ 899"* 'breakpoint()' inserts a possible computation breakpoint (useless with the cli interface)."\n\ 900"* '_(comment) expr' just returns expression 'expr' (useful for inserting inline comments in math expressions)."\n\ 901"* 'run('pipeline')' executes the specified G'MIC pipeline as if it was called outside the currently evaluated "\ 902"expression."\n\ 903"* 'set(A,\\'variable_name\\')' set the G'MIC variable '$variable_name' with the value of expression 'A'. If 'A' is"\ 904" a vector-valued variable, it is assumed to encode a string."\n\ 905"* 'store(A,\\'variable_name\\',_w,_h,_d,_s,_is_compressed)' transfers the data of vector 'A' as a "\ 906"`w x h x d x s` image to the G'MIC variable '$variable_name'. Thus, the data becomes available outside the math "\ 907"expression (that is equivalent to using the regular command ''store'', but directly in the math expression)."\n\ 908"* 'get(\\'variable_name\\',_size,_return_as_string)' returns the value of the specified variable, as a vector of "\ 909"'size' values, or as a scalar (if 'size' is zero or not specified)."\n\ 910"* 'name(_#ind,size)' returns a vector of size 'size', whose values are the characters codes of the name of image "\ 911"'[ind]' (or default image selected if 'ind' is not specified)."\n\ 912"* 'correlate(I,wI,hI,dI,sI,K,wK,hK,dK,sK,_boundary_conditions,_is_normalized,_channel_mode,_xcenter,_ycenter,"\ 913"_zcenter,_xstart,_ystart,_zstart,_xend,_yend,_zend,_xstride,_ystride,_zstride,_xdilation,_ydilation,_zdilation,"\ 914"_interpolation_type)' returns the correlation, unrolled as a vector, of the `wI x hI x dI x sI`-sized image 'I' "\ 915"with the `wK x hK x dK x sK`-sized kernel 'K' (the meaning of the other arguments are the same as in command "\ 916"'correlate'). Similar function 'convolve(...)' is also defined for computing the convolution between 'I' and 'K'."\n\ 917\ 918"## User-defined macros:"\n\ 919"* Custom macro functions can be defined in a math expression, using the assignment operator "\ 920"'=', e.g. \n~~~\nfoo(x,y) = cos(x + y); result = foo(1,2) + foo(2,3)\n~~~\n"\n\ 921"* Trying to override a built-in function (e.g. 'abs()') has no effect."\n\ 922"* Overloading macros with different number of arguments is possible. Re-defining a previously defined macro with "\ 923"the same number of arguments discards its previous definition."\n\ 924"* Macro functions are indeed processed as __macros__ by the mathematical evaluator. You should avoid invoking them "\ 925"with arguments that are themselves results of assignments or self-operations. "\ 926"For instance, \n~~~\nfoo(x) = x + x; z = 0; foo(++z)\n~~~\n returns '4' rather than expected value '2'."\n\ 927"* When substituted, macro arguments are placed inside parentheses, except if a number sign "\ 928"'#' is located just before or after the argument name. For instance, expression \n"\ 929"~~~\nfoo(x,y) = x*y; foo(1+2,3)\n~~~\n "\ 930"returns '9' (being substituted as '(1+2)*(3)'), while expression \n~~~\nfoo(x,y) = x#*y#; foo(1+2,3)\n~~~\n "\ 931"returns '7' (being substituted as '1+2*3')."\n\ 932"* Number signs appearing between macro arguments function actually count for __empty__ separators. They may be used "\ 933"to force the substitution of macro arguments in unusual places, e.g. as in \n~~~\nstr(N) = ['I like N#'];\n~~~\n"\ 934\ 935"## Multi-threaded and in-place evaluation:"\n\ 936"* If your image data are large enough and you have several CPUs available, it is likely that the math expression "\ 937"passed to a 'fill', 'eval' or 'input' commands is evaluated in parallel, using multiple computation threads."\n\ 938"* Starting an expression with ':' or '*' forces the evaluations required for an image to be run in parallel, "\ 939"even if the amount of data to process is small (beware, it may be slower to evaluate in this case!). "\ 940"Specify ':' (rather than '*') to avoid possible image copy done before evaluating the expression "\ 941"(this saves memory, but do this only if you are sure this step is not required!)"\n\ 942"* If the specified expression starts with '>' or '<', the pixel access operators 'i()', 'i[]', 'j()' and 'j[]' "\ 943"return values of the image being currently modified, in forward ('>') or backward ('<') order. "\ 944"The multi-threading evaluation of the expression is disabled in this case."\n\ 945"* Function 'critical(expr)' forces the execution of the given expression in a single thread at a time."\n\ 946"* 'begin_t(expr)' and 'end_t(expr)' evaluates the specified expression once for each running thread "\ 947"(so possibly several times) at the beginning and the end of the evaluation procedure."\n\ 948"* 'merge(variable,operator)' tells to merge the local variable value computed by threads, with the specified "\ 949"operator, when all threads have finished computing."\n\ 950"* Expressions 'i(_#ind,x,_y,_z,_c)=value', 'j(_#ind,x,_y,_z,_c)=value', 'i[_#ind,offset]=value' and "\ 951"'j[_#ind,offset]=value' set a pixel value at a different location than the running one in the image '[ind]' "\ 952"(or in the associated image if argument '#ind' is omitted), either with global coordinates/offsets "\ 953"(with 'i(...)' and 'i[...]'), or relatively to the current position `(x,y,z,c)` (with 'j(...)' and 'j[...]'). "\ 954"These expressions always return 'value'." 955 956 _section "Image and Data Viewers" 957 _text \ 958"* \\G'MIC has some very handy embedded __visualization modules__, for 1D signals (command ''plot''), "\ 959"1D/2D/3D images (command ''display'') and 3D vector objects (command ''display3d''). It manages interactive views "\ 960"of the selected image data."\n\ 961"* The following actions are available in the interactive viewers:"\n\ 962" - `(mousewheel)`: Zoom in/out."\n\ 963" - `ESC`: Close window."\n\ 964" - `CTRL+D`: Increase window size."\n\ 965" - `CTRL+C`: Decrease window size."\n\ 966" - `CTRL+R`: Reset window size."\n\ 967" - `CTRL+F`: Toggle fullscreen mode."\n\ 968" - `CTRL+S`: Save current view as a numbered file 'gmic_xxxx.ext'."\n\ 969" - `CTRL+O`: Save copy of the viewed data, as a numbered file 'gmic_xxxx.ext'."\n\ 970\n\ 971"* Actions specific to the __1D/2D image viewer__ (command ''display'') are:"\n\ 972" - `Left mouse button`: Create an image selection and zoom into it."\n\ 973" - `Middle mouse button`, or `CTRL+left mouse button`: Move image."\n\ 974" - `Mouse wheel` or `PADD+/-`: Zoom in/out."\n\ 975" - `Arrow keys`: Move image left/right/up/down."\n\ 976" - `CTRL+A`: Enable/disable transparency (show alpha channel)."\n\ 977" - `CTRL+N`: Change normalization mode (can be { none | normal | channel-by-channel })."\n\ 978" - `CTRL+SPACE`: Reset view."\n\ 979" - `CTRL+X`: Show/hide axes."\n\ 980" - `CTRL+Z`: Hold/release aspect ratio."\n\ 981\n\ 982"* Actions specific to the __3D volumetric image viewer__ (command ''display'') are:"\n\ 983" - `CTRL+P`: Play z-stack of frames as a movie."\n\ 984" - `CTRL+V`: Show/hide 3D view on bottom right zone."\n\ 985" - `CTRL+X`: Show/hide axes."\n\ 986" - `CTRL+(mousewheel)`: Go up/down."\n\ 987" - `SHIFT+(mousewheel)`: Go left/right."\n\ 988" - `Numeric PAD`: Zoom in/out (`+`/`-`) and move through zoomed image (digits)."\n\ 989" - `BACKSPACE`: Reset zoom scale."\n\ 990\n\ 991"* Actions specific to the __3D object viewer__ (command ''display3d'') are:"\n\ 992" - `(mouse)+(left mouse button)`: Rotate 3D object."\n\ 993" - `(mouse)+(right mouse button)`: Zoom 3D object."\n\ 994" - `(mouse)+(middle mouse button)`: Shift 3D object."\n\ 995" - `F1 ... F6`: Toggle between different 3D rendering modes."\n\ 996" - `F7/F8`: Decrease/increase focale."\n\ 997" - `F9`: Select animation mode."\n\ 998" - `F10`: Select animation speed."\n\ 999" - `SPACE`: Start/stop animation."\n\ 1000" - `CTRL+A`: Show/hide 3D axes."\n\ 1001" - `CTRL+B`: Switch between available background."\n\ 1002" - `CTRL+G`: Save 3D object, as numbered file 'gmic_xxxx.obj'."\n\ 1003" - `CTRL+L`: Show/hide outline."\n\ 1004" - `CTRL+P`: Print current 3D pose on stderr."\n\ 1005" - `CTRL+T`: Switch between single/double-sided 3D modes."\n\ 1006" - `CTRL+V`: Start animation with video output."\n\ 1007" - `CTRL+X`: Show/hide 3D bounding box."\n\ 1008" - `CTRL+Z`: Enable/disable z-buffered rendering." 1009 1010 _section "Adding Custom Commands" 1011 _text \ 1012"* New custom commands can be added by the user, through the use of \\G'MIC __custom commands files__."\n\ 1013"* A command file is a simple text file, where each line starts either by "\ 1014"\n~~~\ncommand_name: command_definition\n~~~\n or \n~~~\ncommand_definition (continuation)\n~~~\n"\n\ 1015"* At startup, G'MIC automatically includes user's command file '$HOME/.gmic' (on __Unix__) or "\ 1016"'%APPDATA%/user.gmic' (on __Windows__). The CLI tool 'gmic' automatically runs the command "\ 1017"'cli_start' if defined."\n\ 1018"* Custom command names must use character set `[a-zA-Z0-9_]` and cannot start with a number."\n\ 1019"* Any `# comment` expression found in a custom commands file is discarded by the G'MIC parser, "\ 1020"wherever it is located in a line."\n\ 1021"* In a custom command, the following '$-expressions' are recognized and substituted:"\n\ 1022" - '$""\*' is substituted by a copy of the specified string of arguments."\n\ 1023" - '$\"*\"' is substituted by a copy of the specified string of arguments, each being double-quoted."\n\ 1024" - '$""#' is substituted by the maximum index of known arguments (either specified by the user or set to a default "\ 1025"value in the custom command)."\n\ 1026" - '$""[]' is substituted by the list of selected image indices that have been specified in the command "\ 1027"invocation."\n\ 1028" - '$""?' is substituted by a printable version of '$""[]' to be used in command descriptions."\n\ 1029" - '$i' and '${i}' are both substituted by the `i`-th specified argument. Negative indices such as '${-j}' are "\ 1030"allowed and refer to the `j`-th latest argument. '$""0' is substituted by the custom command name."\n\ 1031" - '${i=default}' is substituted by the value of '$i' (if defined) or by its new value set to 'default' otherwise "\ 1032"('default' may be a `$-expression` as well)."\n\ 1033" - '${subset}' is substituted by the argument values (separated by commas ',') of a specified argument subset. "\ 1034"For instance expression '$""{2--2}' is substituted by all specified command arguments except the first and the last "\ 1035"one. Expression '$""{^0}' is then substituted by all arguments of the invoked command (eq. to '$""*' if all "\ 1036"arguments have been indeed specified)."\n\ 1037" - '$""=var' is substituted by the set of instructions that will assign each argument '$i' to the named variable "\ 1038"'var$i' (for i in '[0...$""#]'. This is particularly useful when a custom command want to manage variable numbers "\ 1039"of arguments. Variables names must use character set `[a-zA-Z0-9_]` and cannot start with a number."\n\ 1040\n\ 1041"* These particular `$-expressions` for custom commands are __always substituted__, even in "\ 1042"double-quoted items or when the dollar sign '$' is escaped with a backslash '\\$'. To avoid substitution, place an "\ 1043"empty double quoted string just after the '$' (as in '$\"\"1')."\n\ 1044"* Specifying arguments may be skipped when invoking a custom command, by replacing them by commas ',' as in "\ 1045"expression \n~~~\nflower ,,3\n~~~\n Omitted arguments are set to their default values, which must be thus explicitly "\ 1046"defined in the code of the corresponding custom command (using default argument expressions as '$""{1=default}')."\n\ 1047"* If one numbered argument required by a custom command misses a value, an error is thrown by the G'MIC interpreter." 1048 1049 _section "List of Commands" 1050 _text \ 1051"All available \\G'MIC commands are listed below, by categories. An argument specified between '[]' "\ 1052"or starting by '_' is optional except when standing for an existing image '[image]', where 'image' "\ 1053"can be either an index number or an image name. In this case, the '[]' characters are mandatory when writing the "\ 1054"item. Note that all images that serve as illustrations in this reference documentation are normalized in "\ 1055"range `[0,255]` before being displayed. You may need to do this explicitly (command 'normalize 0,255') if you want "\ 1056"to save and view images with the same aspect than those illustrated in the example codes." 1057 1058 # Insert list of commands. 1059 l reference_list_of_commands_$1 onfail endl 1060 1061 # Insert additional sections if specified. 1062 xfolder="$2" 1063 if "['$1']=='html' && ['$2']==0" xfolder=$HOME/work/src/gmic-community/reference fi 1064 1065 if ['$xfolder']!=0 1066 files $xfolder/*.gmd files=${} 1067 repeat narg({/$files}) 1068 arg 1+$>,$files file=${} 1069 l[] it $file s={b} t={t} rm endl 1070 _section {/$s} 1071 _text {/$t} 1072 done 1073 fi 1074 1075 _section "Examples of Use" 1076 _text \ 1077"`gmic` is a generic image processing tool which can be used in a wide variety of situations. "\ 1078"The few examples below illustrate possible uses of this tool:"\n\ 1079"### View a list of images: "\n\ 1080"\n~~~\n$ gmic file1.bmp file2.jpeg\n~~~"\n\n\ 1081"### Convert an image file: "\n\ 1082"\n~~~\n$ gmic input.bmp output output.jpg\n~~~"\n\n\ 1083"### Create a volumetric image from a movie sequence: "\n\ 1084"\n~~~\n$ gmic input.mpg append z output output.hdr\n~~~"\n\n\ 1085"### Compute image gradient norm: "\n\ 1086"\n~~~\n$ gmic input.bmp gradient_norm\n~~~"\n\n\ 1087"### Denoise a color image: "\n\ 1088"\n~~~\n$ gmic image.jpg denoise 30,10 output denoised.jpg\n~~~"\n\n\ 1089"### Compose two images using overlay layer blending: "\n\ 1090"\n~~~\n$ gmic image1.jpg image2.jpg blend overlay output blended.jpg\n~~~"\n\n\ 1091"### Evaluate a mathematical expression: "\n\ 1092"\n~~~\n$ gmic echo \"cos(pi/4)^2+sin(pi/4)^2={cos(pi/4)^2+sin(pi/4)^2}\"\n~~~"\n\n\ 1093"### Plot a 2D function: "\n\ 1094"\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\ 1095"===\n![](../img/example_plot.png)\n==="\n\n\ 1096"### Plot a 3D elevated function in random colors: "\n\ 1097"\n~~~\n$ gmic 128,128,1,3,\"u(0,255)\" plasma 10,3 blur 4 sharpen 10000 n 0,255 "\ 1098"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\ 1099"===\n![](../img/example_elevation3d.png)\n==="\n\n\ 1100"### Plot the isosurface of a 3D volume: "\n\ 1101"\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\ 1102"===\n![](../img/example_isosurface3d.png)\n==="\n\n\ 1103"### Render a G'MIC 3D logo: "\n\ 1104"\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 "\ 1105"elevation3d -0.1 moded3d 4\n~~~"\n\ 1106"===\n![](../img/example_logo.png)\n==="\n\n\ 1107"### Generate a 3D ring of torii: "\n\ 1108"\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}\" "\ 1109"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\ 1110"===\n![](../img/example_torii.png)\n==="\n\n\ 1111"### Create a vase from a 3D isosurface: "\n\ 1112"\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 "\ 1113"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 "\ 1114"color3d[-3] 255,128,0 add3d\n~~~"\n\ 1115"===\n![](../img/example_vase.png)\n==="\n\n\ 1116"### Launch a set of interactive demos: "\n\ 1117"\n~~~\n$ gmic demos\n~~~\n" 1118 1119 l reference_footer_$1 reference_end_$1 onfail endl 1120 um _section,_text 1121 rm 1122 1123# 1124# Implement output mode 'ascii' for command 'reference'. 1125# 1126reference_begin_ascii : 1127 use_vt100 1128 if !narg($_shell_cols) _shell_cols={${-shell_cols}-5} fi 1129 _section=0 1130 +e[] "" 1131 1132reference_header_ascii : 1133 if $_prerelease strprerelease=" (pre-release ""#"$_prerelease")" else strprerelease="" fi 1134 str=\n\ 1135 " "${_vt100_b}"gmic: GREYC\'s Magic for Image Computing:"$_vt100_n" command-line interface"\n\ 1136 " "${_vt100_c}${_vt100_b}"Version "${-strver}$strprerelease$_vt100_n\n\ 1137 " "$_vt100_g$_vt100_u"(https://gmic.eu)"$_vt100_n\n\ 1138 \n\ 1139 " Copyright (c) Since 2008, David Tschumperlé / GREYC / CNRS."\n\ 1140 " "$_vt100_g$_vt100_u"(https://www.greyc.fr)"$_vt100_n 1141 +e[] $str 1142 1143reference_section_ascii : 1144 _section+=1 1145 +e[] "" 1146 ('$_section." "') ('"$*"') +f.. {'" "'} +f.. {'-'} a[-4,-3] x a[-2,-1] x 1147 +e[] " "$_vt100_r$_vt100_b{-2,t}$_vt100_n 1148 +e[] " "$_vt100_r{t}$_vt100_n\n 1149 rm[-2,-1] 1150 1151reference_text_ascii : 1152 l[] 1153 ('"$*"') 1154 gmd2ascii $_shell_cols,1 1155 1156 # Ensure output text contains no more than two consecutive newlines. 1157 # Also add a 2-chars left margin on each line. 1158 s +,{'\n'} 1159 eval "repeat (l,p, 1160 i(#p)==_'\n' && h(#p)>2?resize(#p,1,2,1,1,0): 1161 (resize(#p,1,h#p + 2,1,1,0,0,0,1); copy(i[#p,0],_' ',2,1,0)))" 1162 a y 1163 +e[] {/{t}} 1164 rm 1165 endl 1166 1167reference_list_of_commands_ascii : 1168 l 1169 if !$! it $_path_rc/update$_version.gmic fi 1170 parse_cli ascii 1171 onfail 1172 rm 1173 +e[] \n" "$_vt100_r${_vt100_b}"No command descriptions available!"$_vt100_n 1174 +e[] " "${_vt100_r}"Try updating your command files, with command "$_vt100_b"'update'."$_vt100_n 1175 endl 1176 1177reference_footer_ascii : 1178 +e[] \n" "$_vt100_r$_vt100_b"** G\47MIC comes with ABSOLUTELY NO WARRANTY; "\ 1179 "for details visit: https://gmic.eu **"$_vt100_n 1180 1181# 1182# Implement output mode 'html' for command 'reference'. 1183# 1184reference_section_html : 1185 name="$*" 1186 reference_end_section_html 1187 ('"<!DOCTYPE html>"\n\ 1188"<html lang=\"en\">"\n\ 1189" <head>"\n\ 1190" <meta charset=\"utf-8\">"\n\ 1191" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 1192" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 1193"- "$name"</title>"\n\ 1194" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 1195" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 1196" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 1197" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\ 1198" </head>"\n\n\ 1199" <body>"\n\ 1200" <div id=\"include_header\"></div>"\n\n\ 1201" <div class=\"section_title\"><a href=\"index.html\"><p>Reference</p></a></div><div class=\"section_content\">"\n\ 1202" <a name=\"top\"></a>"\n\ 1203"<!-- ref_navigation_top -->"\n\n\ 1204"<!-- begin_content -->"\n\n\ 1205" <h1 class=\"ref_h1\">"$name"</h1>"\n':y) 1206 nm. $name 1207 1208reference_end_section_html : 1209 if $! # End previous section 1210 ('" <br/>"\n\n\ 1211 "<!-- end_content -->"\n\n\ 1212 "<!-- ref_navigation_bottom -->"\n\ 1213 " </div><div class=\"section_end\"></div>"\n\ 1214 " <div id=\"include_footer\"></div>"\n\ 1215 " </body>"':y) 1216 a[-2,-1] y 1217 fi 1218 1219reference_text_html : 1220 ('"$*"':y) gmd2html. 0 1221 if $!>1 a[-2,-1] y fi 1222 1223reference_footer_html : 1224 reference_end_section_html 1225 1226reference_finalize_html : 1227 1228 # Generate table of contents. 1229 if $_prerelease strprerelease=" (pre-release ""#"$_prerelease")" else strprerelease="" fi 1230 html="<!DOCTYPE html>"\n\ 1231"<html lang=\"en\">"\n\ 1232" <head>"\n\ 1233" <meta charset=\"utf-8\">"\n\ 1234" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 1235" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 1236"- Table of Contents</title>"\n\ 1237" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 1238" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 1239" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 1240" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 1241" </head>"\n\n\ 1242" <body>"\n\ 1243" <div id=\"include_header\"></div>"\n\n\ 1244" <div class=\"section_title\"><a href=\"index.html\"><p>Reference</p></a></div><div class=\"section_content\">"\n\n\ 1245" <a name=\"top\"></a>"\n\ 1246"<!-- ref_navigation_top -->"\n\n\ 1247"<!-- begin_content -->"\n\n\ 1248" <h1 class=\"ref_h1\">Preamble</h1>"\n\ 1249" <ul><li>This document is distributed under the "\ 1250"<a target=\"_blank\" href=\"http://www.gnu.org/licenses/fdl-1.3.txt\">GNU Free Documentation License</a>, "\ 1251"version 1.3.</li>"\n\ 1252" <li>A <a href=\"gmic_reference.pdf\">.pdf version</a> of this document is available.</li>"\n 1253 1254 if !0$_pdf_output 1255 html.=" <li>Quick access to the <a class=\"ref_loc\" "\ 1256 "href=\"https://gmic.eu/reference/list_of_commands.html\">"\ 1257 "List of Commands</a>.</li>"\n 1258 fi 1259 1260 html.="</ul>"\n\ 1261" <h1 class=\"ref_h1\">Version</h1>"\n\ 1262" <div class=\"ref_header\">"\n\ 1263" <span class=\"gmd_gmic\">G'MIC</span>: "\ 1264"<span class=\"gmd_monospace\">GREYC's Magic for Image Computing</span><br/>"\n\ 1265" <a href=\"https://gmic.eu\">https://gmic.eu</a><br/>"\n\ 1266" Version <b>"${-strver}"</b>"$strprerelease"<br/><br/>"\n\ 1267" Copyright © Since 2008, "\ 1268"<a target=\"_blank\" href=\"https://tschumperle.users.greyc.fr/\">David Tschumperlé</a> / "\ 1269"<a target=\"_blank\" href=\"https://www.greyc.fr\">GREYC</a> / "\ 1270"<a target=\"_blank\" href=\"http://www.cnrs.fr/en\">CNRS</a><br/>"\n\ 1271" <a target=\"_blank\" href=\"https://www.greyc.fr\">https://www.greyc.fr</a><br/>"\n\ 1272" </div>"\n\ 1273" <h1 class=\"ref_h1\">Table of Contents</h1>"\n\ 1274" <ul>"\n 1275 1276 ind_loc=${"-nmd 1,\"List of Commands\""} 1277 if narg($ind_loc) 1278 repeat $! l[$>] 1279 name={n} strvar $name url=${}.html 1280 if $>==$ind_loc 1281 html.="<li><a class=\"ref_loc\" href=\""$url"#top\">"$name"</a></li>" 1282 else 1283 html.="<li><a href=\""$url"#top\">"$name"</a></li>" 1284 fi 1285 endl done 1286 html.="\n </ul>"\n\n\ 1287 "<!-- end_content -->"\n\n\ 1288 "<!-- ref_navigation_bottom -->"\n\ 1289 " </div><div class=\"section_end\"></div>"\n\ 1290 " <div id=\"include_footer\"></div>"\n\ 1291 " </body>" 1292 1293 i[0] ({'$html'}:y) nm[0] "Table of Contents" 1294 ind_loc+=1 1295 if narg($ind_loc)" && "isfile('list_of_commands.html') # Merge with existing 'List of commands' page if it exists 1296 it list_of_commands.html 1297 if find(crop(),'"<!-- merged_content -->"')<0 l[$ind_loc,-1] 1298 s[0] -,{'"<!-- end_content -->"'} 1299 s. -,{'"<!-- begin_content -->"'} 1300 i[1] ('"<!-- merged_content -->"':y) 1301 k[0,1,-1] a y 1302 endl else nm. "List of Commands" rv[$ind_loc,-1] rm. fi 1303 fi 1304 fi 1305 1306 # Insert top and bottom navigation bar into pages. 1307 if !0$_pdf_output 1308 repeat $! 1309 current={$>,n} strvar[] $current url_current=${}.html 1310 if $>>1 previous={{$>-1},n} strvar[] $previous url_previous=${}.html else previous= fi 1311 if $< next={{$>+1},n} strvar[] $next url_next=${}.html else next= fi 1312 html_top=" <table class=\"ref_navigation_top\"><tr><td>"\ 1313 "<a href=\"index.html\">Table of Contents</a>" 1314 if $> html_top.=" ▸ <a href=\""$url_current"#top\">"$current"</a>" fi 1315 html_top.="</td><td>" 1316 if ['$previous']!=0 html_top.="<a href=\""$url_previous"#top\">◀ "$previous"</a>" fi 1317 if ['$previous']!=0" && "['$next']!=0 html_top.=" | " fi 1318 if ['$next']!=0 html_top.="<a href=\""$url_next"#top\">"$next" ▶</a>" fi 1319 html_top.="</td></tr></table>" 1320 1321 html_bottom="<div class=\"ref_navigation_bottom\">" 1322 if ['$previous']!=0 html_bottom.="<a href=\""$url_previous"#top\">◀ "$previous"</a>" fi 1323 if ['$previous']!=0" && "['$next']!=0 html_bottom.=" | " fi 1324 if ['$next']!=0 html_bottom.="<a href=\""$url_next"#top\">"$next" ▶</a>" fi 1325 html_bottom.="</div>" 1326 1327 replace_str[$>] "<!-- ref_navigation_top -->",$html_top 1328 replace_str[$>] "<!-- ref_navigation_bottom -->",$html_bottom 1329 done 1330 fi 1331 1332reference_end_html : 1333 reference_finalize_html 1334 1335 # Save html pages. 1336 repeat $! l[$>] strvar {n} ot ${}.html endl done 1337 if isfile('table_of_contents.html') x "ln -fs table_of_contents.html index.html" fi 1338 rm 1339 1340# 1341# Implement output mode 'man' for command 'reference'. 1342# (It is based on the 'ascii' output with some tricks to generate a roff file). 1343# 1344reference_begin_man : 1345 _section=0 1346 +e[] ".TH G\47MIC 1\n\ 1347 .SH NAME\n\ 1348 gmic \\- Perform image processing operations using the G\47MIC framework.\n\ 1349 \n\ 1350 .SH HELP\n" 1351 1352reference_header_man : 1353 _vt100_b="\\fB" 1354 _vt100_c="\\fB" 1355 _vt100_g="\\fB" 1356 _vt100_m= 1357 _vt100_n="\\fR" 1358 _vt100_r="\\fB" 1359 _vt100_u="\\fI" 1360 _prerelease= 1361 reference_header_ascii 1362 1363reference_section_man : 1364 reference_section_ascii "$*" 1365 1366reference_text_man : 1367 reference_text_ascii "$*" 1368 1369reference_list_of_commands_man : 1370 _vt100_c= 1371 reference_list_of_commands_ascii 1372 _vt100_m="\\fB" 1373 _vt100_b= 1374 1375reference_footer_man : 1376 reference_footer_ascii "$*" 1377 1378# 1379# Implement output mode 'pdf' for command 'reference'. 1380# (It is based on the 'html' output with some tricks to generate a pdf file with 'wkhtmltopdf'). 1381# 1382reference_begin_pdf : 1383 _pdf_output=1 1384 1385reference_section_pdf : 1386 reference_section_html "$*" 1387 1388reference_text_pdf : 1389 reference_text_html "$*" 1390 1391reference_footer_pdf : 1392 reference_end_section_html 1393 1394reference_end_pdf : 1395 1024,4,1,3 o. reference_pdf.png rm. 1396 reference_finalize_html 1397 1398 # Load existing html page for each command. 1399 l[] 1400 it ../../src/gmic_stdlib.gmic +parse_cli. list loc=${} 1401 parse_cli html 1402 repeat narg($loc) 1403 command=${"arg "1+$>","$loc} 1404 l[] if ['$command'][0]!=_'_' it $command.html fi onfail endl 1405 done 1406 sort_list +,n 1407 endl 1408 s +,{'"<!-- begin_content -->"'} 1409 s +,{'"<!-- end_content -->"'} 1410 k[2--1:5] 1411 1412 # Add specific header and footer. 1413 if $_prerelease strprerelease=" (pre-release ""#"$_prerelease")" else strprerelease="" fi 1414 i[0] ('"<!DOCTYPE html>"\n\ 1415"<html lang=\"en\">"\n\ 1416" <head>"\n\ 1417" <meta charset=\"utf-8\">"\n\ 1418" <link rel=\"stylesheet\" href=\"style.css\">"\n\ 1419" <title>reference_pdf</title>"\n\ 1420" <style>"\n\ 1421" body { background-color: white; font-size: 22px; }"\n\ 1422" .gmd_code_block { font-size: 1em; }"\n\ 1423" </style>"\n\ 1424" </head>"\n\n\ 1425" <body>"\n\ 1426" <div style=\"border: 3px solid black; text-align: center; width: 100%; margin-left: auto; "\ 1427"margin-right: auto; margin-top: 9cm; break-after: page\">"\n\ 1428" <img style=\"width: 98%\" src=\"../img/gmic_banner.jpg\" />"\n\ 1429" <h1 class=\"ref_h1\">The Handbook</h1>"\n\ 1430" <h3>Version "${strver[]}$strprerelease"</h3>"\n\ 1431" <p>© David Tschumperlé / GREYC / CNRS</p>"\n\ 1432" <p>"{date(0)}"/"{date(1)}"/"{date(2)}"</p>"\n\ 1433" </div>"':y) 1434 ('"<img style=\"margin-top: 2em; width: 100%;\" src=\"reference_pdf.png\"/>"\n\ 1435 "<p style=\"text-align: center;\">□ End of document</p>"\n\ 1436 "</body>"':y) a y 1437 ot reference_pdf.html 1438 rm 1439 1440 # Copy css to current folder. 1441 it ../style.css ot. style.css rm 1442 1443 # Use 'wkhtmltopdf' to convert html to a pdf file. 1444 # (There is a bug in wkhtmltopdf that prevents all images to appear in the generated document! 1445 # I have to print the .pdf manually 'in a file' first). 1446 delete reference_pdf.pdf 1447 v 0 e[] " > Waiting for file 'reference_pdf.pdf'." 1448 for !isfile('reference_pdf.pdf') wait 5000 done 1449 e[] " > Removing links in file 'reference_pdf.pdf'." 1450 x "pdfjam reference_pdf.pdf" 1451 e[] " > Compressing file 'reference_pdf.pdf' to 'gmic_reference.pdf'." 1452 x "gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=gmic_reference.pdf reference_pdf-pdfjam.pdf" 1453 e[] " > Clean temporary files." 1454 delete style.css,reference_pdf.html,reference_pdf.png,reference_pdf.pdf,reference_pdf-pdfjam.pdf 1455 e[] " > Upload file 'gmic_reference.pdf' to G'MIC server." 1456 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"put -O /www/gmic/reference gmic_reference.pdf; "\ 1457 "quit\" >/dev/null" 1458 1459# use_vt100 1460# This command defines some global variables used to output colored text on VT100 terminals. 1461use_vt100 : 1462 if !0$_vt100" || "['$_vt100_n']!=0 return fi 1463 _vt100_b="\33[1m" # Bold 1464 _vt100_c="\33[0;36;59m" # Cyan 1465 _vt100_g="\33[0;32;59m" # Green 1466 _vt100_i="\33[3m" # Italic 1467 _vt100_m="\33[0;35;59m" # Magenta 1468 _vt100_n="\33[0;0;0m" # Normal 1469 _vt100_r="\33[0;31;59m" # Red 1470 _vt100_s="\33[9m" # Strikethrough 1471 _vt100_u="\33[4m" # Underline 1472 1473#@cli version 1474#@cli : Display current version number on stdout. 1475version : 1476 use_vt100 1477 reference_header_ascii[] 1478 if !0$_cli_noarg +e[] "\n" fi 1479 1480v : # Allow 'gmic +v' to get the version number. 1481 version 1482 1483#------------------------------- 1484# 1485#@cli :: Input / Output 1486# 1487#------------------------------- 1488 1489#@cli camera : _camera_index>=0,_nb_frames>0,_skip_frames>=0,_capture_width>=0,_capture_height>=0 : (+) 1490#@cli : Insert one or several frames from specified camera. 1491#@cli : When 'nb_frames==0', the camera stream is released instead of capturing new images. 1492#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 1493#@cli : Default values: 'camera_index=0' (default camera), 'nb_frames=1', 'skip_frames=0' and \ 1494# 'capture_width=capture_height=0' (default size). 1495 1496#@cli clut : "clut_name",_resolution>0,_cut_and_round={ 0=no | 1=yes } 1497#@cli : Insert one of the 958 pre-defined CLUTs at the end of the image list.\n 1498#@cli : 'clut_name' can be { 2-strip-process | 60s | 60s_faded | 60s_faded_alt | 7drk_21 | action_magenta_01 | \ 1499# action_red_01 | adventure_1453 | agfa_apx_100 | agfa_apx_25 | agfa_precisa_100 | agfa_ultra_color_100 | \ 1500# agfa_vista_200 | agressive_highligjtes_recovery_5 | alberto_street | alien_green | amstragram | amstragram+ | \ 1501# analog_film_1 | analogfx_anno_1870_color | analogfx_old_style_i | analogfx_old_style_ii | analogfx_old_style_iii | \ 1502# analogfx_sepia_color | analogfx_soft_sepia_i | analogfx_soft_sepia_ii | anime | apocalypse_this_very_moment | \ 1503# aqua | aqua_and_orange_dark | arabica_12 | atomic_pink | autumn | ava_614 | avalanche | azrael_93 | bboyz_2 | \ 1504# bc_darkum | beach_aqua_orange | beach_faded_analog | berlin_sky | black_and_white | black_star | black_white_01 | \ 1505# black_white_02 | black_white_03 | black_white_04 | black_white_05 | black_white_06 | blade_runner | bleach_bypass | \ 1506# bleachbypass_1 | bleachbypass_2 | bleachbypass_3 | bleachbypass_4 | bleech_bypass_green | bleech_bypass_yellow_01 | \ 1507# blue_cold_fade | blue_dark | blue_house | blue_ice | blue_mono | blue_shadows_01 | blues | bob_ford | bourbon_64 | \ 1508# bright_green_01 | bright_teal_orange | bright_warm | brightgreen | brown_mobster | brownbm | brownish | bw_1 | \ 1509# 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 | \ 1510# chemical_168 | chrome_01 | cineblue | cinebm_4k | cinema | cinema_2 | cinema_3 | cinema_4 | cinema_5 | \ 1511# cinema_noir | cinematic-1 | cinematic-10 | cinematic-2 | cinematic-3 | cinematic-4 | cinematic-5 | cinematic-6 | \ 1512# cinematic-7 | cinematic-8 | cinematic-9 | cinematic_01 | cinematic_02 | cinematic_03 | cinematic_for_flog | \ 1513# cinematic_forest | cinematic_lady_bird | cinematic_mexico | city | city_7 | city_dust | classic_films_01 | \ 1514# classic_films_02 | classic_films_03 | classic_films_04 | classic_films_05 | classic_teal_and_orange | clayton_33 | \ 1515# clear_teal_fade | clouseau_54 | cobi_3 | coffee_44 | cold_clear_blue | cold_clear_blue_1 | cold_ice | \ 1516# cold_simplicity_2 | color_rich | colorful_0209 | colornegative | conflict_01 | contrail_35 | \ 1517# contrast_with_highlights_protection | contrasty_afternoon | contrasty_green | crispromance | crispwarm | \ 1518# crispwinter | cross_process_cp_130 | cross_process_cp_14 | cross_process_cp_15 | cross_process_cp_16 | \ 1519# cross_process_cp_18 | cross_process_cp_3 | cross_process_cp_4 | cross_process_cp_6 | crushin | cubicle_99 | d_o_1 | \ 1520# dark_blues_in_sunlight | dark_green_02 | dark_green_1 | dark_man_x | dark_orange_teal | dark_place_01 | darkness | \ 1521# date_39 | day_4nite | day_for_night | day_to_night_kings_blue | deep | deep_blue | deep_dark_warm | \ 1522# deep_high_contrast | deep_teal_fade | deep_warm_fade | deepskintones_2 | deepskintones_3 | delicatessen | \ 1523# denoiser_simple_40 | desert_gold_37 | dimension | directions_23 | django_25 | domingo_145 | dream_1 | dream_85 | \ 1524# drop_green_tint_14 | dropblues | duotone_blue_red | earth_tone_boost | edgyember | elegance_38 | enchanted | \ 1525# eterna_for_flog | expired_69 | expired_fade | expired_polaroid | extreme | fade | fade_to_green | faded | \ 1526# faded_47 | faded_alt | faded_analog | faded_extreme | faded_green | faded_pink-ish | faded_print | faded_retro_01 | \ 1527# faded_retro_02 | faded_vivid | fadedlook | fallcolors | faux_infrared | faux_infrared_bw_1 | \ 1528# faux_infrared_color_p_2 | faux_infrared_color_p_3 | faux_infrared_color_r_0a | faux_infrared_color_r_0b | \ 1529# faux_infrared_color_yp_1 | fgcinebasic | fgcinebright | fgcinecold | fgcinedrama | fgcinetealorange_1 | \ 1530# fgcinetealorange_2 | fgcinevibrant | fgcinewarm | film_0987 | film_9879 | film_gb-19 | film_high_contrast | \ 1531# film_print_01 | film_print_02 | filmic | flat_30 | flat_blue_moon | flavin | foggynight | folger_50 | formula_b | \ 1532# french_comedy | frosted | frostedbeachpicnic | fuji_160c | fuji_160c_+ | fuji_160c_++ | fuji_160c_- | \ 1533# fuji_3510_constlclip | fuji_3510_constlmap | fuji_3510_cuspclip | fuji_3513_constlclip | fuji_3513_constlmap | \ 1534# fuji_3513_cuspclip | fuji_400h | fuji_400h_+ | fuji_400h_++ | fuji_400h_- | fuji_800z | fuji_800z_+ | \ 1535# fuji_800z_++ | fuji_800z_- | fuji_astia_100_generic | fuji_astia_100f | fuji_fp-100c | fuji_fp-100c_+ | \ 1536# fuji_fp-100c_++ | fuji_fp-100c_+++ | fuji_fp-100c_++_alt | fuji_fp-100c_- | fuji_fp-100c_-- | fuji_fp-100c_alt | \ 1537# fuji_fp-100c_cool | fuji_fp-100c_cool_+ | fuji_fp-100c_cool_++ | fuji_fp-100c_cool_- | fuji_fp-100c_cool_-- | \ 1538# fuji_fp-100c_negative | fuji_fp-100c_negative_+ | fuji_fp-100c_negative_++ | fuji_fp-100c_negative_+++ | \ 1539# fuji_fp-100c_negative_++_alt | fuji_fp-100c_negative_- | fuji_fp-100c_negative_-- | fuji_fp-3000b | \ 1540# fuji_fp-3000b_+ | fuji_fp-3000b_++ | fuji_fp-3000b_+++ | fuji_fp-3000b_- | fuji_fp-3000b_-- | fuji_fp-3000b_hc | \ 1541# fuji_fp-3000b_negative | fuji_fp-3000b_negative_+ | fuji_fp-3000b_negative_++ | fuji_fp-3000b_negative_+++ | \ 1542# fuji_fp-3000b_negative_- | fuji_fp-3000b_negative_-- | fuji_fp-3000b_negative_early | fuji_fp_100c | fuji_hdr | \ 1543# fuji_neopan_1600 | fuji_neopan_1600_+ | fuji_neopan_1600_++ | fuji_neopan_1600_- | fuji_neopan_acros_100 | \ 1544# fuji_provia_100_generic | fuji_provia_100f | fuji_provia_400f | fuji_provia_400x | fuji_sensia_100 | \ 1545# fuji_superia_100 | fuji_superia_100_+ | fuji_superia_100_++ | fuji_superia_100_- | fuji_superia_1600 | \ 1546# fuji_superia_1600_+ | fuji_superia_1600_++ | fuji_superia_1600_- | fuji_superia_200 | fuji_superia_200_xpro | \ 1547# fuji_superia_400 | fuji_superia_400_+ | fuji_superia_400_++ | fuji_superia_400_- | fuji_superia_800 | \ 1548# fuji_superia_800_+ | fuji_superia_800_++ | fuji_superia_800_- | fuji_superia_hg_1600 | fuji_superia_reala_100 | \ 1549# fuji_superia_x-tra_800 | fuji_velvia_100_generic | fuji_velvia_50 | fuji_xtrans_iii_acros | \ 1550# fuji_xtrans_iii_acros+g | fuji_xtrans_iii_acros+r | fuji_xtrans_iii_acros+ye | fuji_xtrans_iii_astia | \ 1551# fuji_xtrans_iii_classic_chrome | fuji_xtrans_iii_mono | fuji_xtrans_iii_mono+g | fuji_xtrans_iii_mono+r | \ 1552# fuji_xtrans_iii_mono+ye | fuji_xtrans_iii_pro_neg_hi | fuji_xtrans_iii_pro_neg_std | fuji_xtrans_iii_provia | \ 1553# fuji_xtrans_iii_sepia | fuji_xtrans_iii_velvia | fusion_88 | futuristicbleak_1 | futuristicbleak_2 | \ 1554# futuristicbleak_3 | futuristicbleak_4 | going_for_a_walk | golden | golden_bright | golden_fade | golden_mono | \ 1555# golden_night_softner_43 | golden_sony_37 | golden_vibrant | goldengate | goldentime | goldfx_bright_spring_breeze | \ 1556# goldfx_bright_summer_heat | goldfx_hot_summer_heat | goldfx_perfect_sunset_01min | goldfx_perfect_sunset_05min | \ 1557# goldfx_perfect_sunset_10min | goldfx_spring_breeze | goldfx_summer_heat | good_morning | green_15 | green_2025 | \ 1558# green_action | green_afternoon | green_and_orange | green_blues | green_conflict | green_day_01 | green_day_02 | \ 1559# green_g_09 | green_indoor | green_light | green_mono | green_yellow | greenish_contrasty | greenish_fade | \ 1560# greenish_fade_1 | gremerta | hackmanite | hallowen_dark | happyness_133 | hard_teal_orange | harsh_day | \ 1561# harsh_sunset | helios | herderite | heulandite | hiddenite | highlights_protection | hilutite | hitman | hlg_1_1 | \ 1562# honey_light | hong_kong | horrorblue | howlite | hydracore | hyla_68 | hypersthene | hypnosis | hypressen | \ 1563# ilford_delta_100 | ilford_delta_3200 | ilford_delta_3200_+ | ilford_delta_3200_++ | ilford_delta_3200_- | \ 1564# ilford_delta_400 | ilford_fp_4_plus_125 | ilford_hp_5 | ilford_hp_5_+ | ilford_hp_5_++ | ilford_hp_5_- | \ 1565# ilford_hp_5_plus_400 | ilford_hps_800 | ilford_pan_f_plus_50 | ilford_xp_2 | indoor_blue | industrial_33 | \ 1566# infrared_-_dust_pink | instantc | justpeachy | jwick_21 | k_tone_vintage_kodachrome | kh_1 | kh_10 | kh_2 | kh_3 | \ 1567# kh_4 | kh_5 | kh_6 | kh_7 | kh_8 | kh_9 | killstreak | kodak_2383_constlclip | kodak_2383_constlmap | \ 1568# kodak_2383_cuspclip | kodak_2393_constlclip | kodak_2393_constlmap | kodak_2393_cuspclip | kodak_bw_400_cn | \ 1569# kodak_e-100_gx_ektachrome_100 | kodak_ektachrome_100_vs | kodak_ektachrome_100_vs_generic | kodak_ektar_100 | \ 1570# kodak_elite_100_xpro | kodak_elite_chrome_200 | kodak_elite_chrome_400 | kodak_elite_color_200 | \ 1571# kodak_elite_color_400 | kodak_elite_extracolor_100 | kodak_hie_hs_infra | kodak_kodachrome_200 | \ 1572# kodak_kodachrome_25 | kodak_kodachrome_64 | kodak_kodachrome_64_generic | kodak_portra_160 | kodak_portra_160_+ | \ 1573# kodak_portra_160_++ | kodak_portra_160_- | kodak_portra_160_nc | kodak_portra_160_nc_+ | kodak_portra_160_nc_++ | \ 1574# kodak_portra_160_nc_- | kodak_portra_160_vc | kodak_portra_160_vc_+ | kodak_portra_160_vc_++ | \ 1575# kodak_portra_160_vc_- | kodak_portra_400 | kodak_portra_400_+ | kodak_portra_400_++ | kodak_portra_400_- | \ 1576# kodak_portra_400_nc | kodak_portra_400_nc_+ | kodak_portra_400_nc_++ | kodak_portra_400_nc_- | \ 1577# kodak_portra_400_uc | kodak_portra_400_uc_+ | kodak_portra_400_uc_++ | kodak_portra_400_uc_- | \ 1578# kodak_portra_400_vc | kodak_portra_400_vc_+ | kodak_portra_400_vc_++ | kodak_portra_400_vc_- | kodak_portra_800 | \ 1579# kodak_portra_800_+ | kodak_portra_800_++ | kodak_portra_800_- | kodak_portra_800_hc | kodak_t-max_100 | \ 1580# kodak_t-max_3200 | kodak_t-max_400 | kodak_tmax_3200 | kodak_tmax_3200_+ | kodak_tmax_3200_++ | kodak_tmax_3200_- | \ 1581# kodak_tmax_3200_alt | kodak_tri-x_400 | kodak_tri-x_400_+ | kodak_tri-x_400_++ | kodak_tri-x_400_- | \ 1582# kodak_tri-x_400_alt | korben_214 | landscape_01 | landscape_02 | landscape_03 | landscape_04 | landscape_05 | \ 1583# landscape_1 | landscape_10 | landscape_2 | landscape_3 | landscape_4 | landscape_5 | landscape_6 | landscape_7 | \ 1584# landscape_8 | landscape_9 | lateafternoonwanderlust | latesunset | lc_1 | lc_10 | lc_2 | lc_3 | lc_4 | lc_5 | \ 1585# lc_6 | lc_7 | lc_8 | lc_9 | lenox_340 | life_giving_tree | light_blown | lomo | lomography_redscale_100 | \ 1586# lomography_x-pro_slide_200 | london_nights | louetta | low_contrast_blue | low_key_01 | lucky_64 | \ 1587# lushgreensummer | magenta_day | magenta_day_01 | magenta_dream | magenta_yellow | magentacoffee | matrix | \ 1588# mckinnon_75 | memories | metropolis | milo_5 | minimalistcaffeination | modern_film | modern_films_01 | \ 1589# modern_films_02 | modern_films_03 | modern_films_04 | modern_films_05 | modern_films_06 | modern_films_07 | \ 1590# mono_tinted | monochrome | monochrome_1 | monochrome_2 | moody_1 | moody_10 | moody_2 | moody_3 | moody_4 | \ 1591# moody_5 | moody_6 | moody_7 | moody_8 | moody_9 | moonlight | moonlight_01 | moonrise | morning_6 | morroco_16 | \ 1592# mostly_blue | moviz_1 | moviz_10 | moviz_11 | moviz_12 | moviz_13 | moviz_14 | moviz_15 | moviz_16 | moviz_17 | \ 1593# moviz_18 | moviz_19 | moviz_2 | moviz_20 | moviz_21 | moviz_22 | moviz_23 | moviz_24 | moviz_25 | moviz_26 | \ 1594# moviz_27 | moviz_28 | moviz_29 | moviz_3 | moviz_30 | moviz_31 | moviz_32 | moviz_33 | moviz_34 | moviz_35 | \ 1595# moviz_36 | moviz_37 | moviz_38 | moviz_39 | moviz_4 | moviz_40 | moviz_41 | moviz_42 | moviz_43 | moviz_44 | \ 1596# moviz_45 | moviz_46 | moviz_47 | moviz_48 | moviz_5 | moviz_6 | moviz_7 | moviz_8 | moviz_9 | mute_shift | \ 1597# muted_01 | muted_fade | mysticpurplesunset | nah | natural_vivid | nemesis | neon_770 | neutral_pump | \ 1598# neutral_teal_orange | neutral_warm_fade | newspaper | night_01 | night_blade_4 | night_king_141 | night_spy | \ 1599# nightfromday | nightlife | nostalgiahoney | nostalgic | nw-1 | nw-10 | nw-2 | nw-3 | nw-4 | nw-5 | nw-6 | nw-7 | \ 1600# nw-8 | nw-9 | old_west | once_upon_a_time | only_red | only_red_and_blue | operation_yellow | orange_dark_4 | \ 1601# orange_dark_7 | orange_dark_look | orange_tone | orange_underexposed | oranges | paladin | paladin_1875 | \ 1602# pasadena_21 | passing_by | pink_fade | pitaya_15 | pmcinematic_01 | pmcinematic_02 | pmcinematic_03 | \ 1603# pmcinematic_04 | pmcinematic_05 | pmcinematic_06 | pmcinematic_07 | pmnight_01 | pmnight_02 | pmnight_03 | \ 1604# pmnight_04 | pmnight_05 | polaroid_664 | polaroid_665 | polaroid_665_+ | polaroid_665_++ | polaroid_665_- | \ 1605# polaroid_665_-- | polaroid_665_negative | polaroid_665_negative_+ | polaroid_665_negative_- | \ 1606# polaroid_665_negative_hc | polaroid_667 | polaroid_669 | polaroid_669_+ | polaroid_669_++ | polaroid_669_+++ | \ 1607# polaroid_669_- | polaroid_669_-- | polaroid_669_cold | polaroid_669_cold_+ | polaroid_669_cold_- | \ 1608# polaroid_669_cold_-- | polaroid_672 | polaroid_690 | polaroid_690_+ | polaroid_690_++ | polaroid_690_- | \ 1609# polaroid_690_-- | polaroid_690_cold | polaroid_690_cold_+ | polaroid_690_cold_++ | polaroid_690_cold_- | \ 1610# polaroid_690_cold_-- | polaroid_690_warm | polaroid_690_warm_+ | polaroid_690_warm_++ | polaroid_690_warm_- | \ 1611# polaroid_690_warm_-- | polaroid_polachrome | polaroid_px-100uv+_cold | polaroid_px-100uv+_cold_+ | \ 1612# polaroid_px-100uv+_cold_++ | polaroid_px-100uv+_cold_+++ | polaroid_px-100uv+_cold_- | polaroid_px-100uv+_cold_-- | \ 1613# polaroid_px-100uv+_warm | polaroid_px-100uv+_warm_+ | polaroid_px-100uv+_warm_++ | polaroid_px-100uv+_warm_+++ | \ 1614# polaroid_px-100uv+_warm_- | polaroid_px-100uv+_warm_-- | polaroid_px-680 | polaroid_px-680_+ | polaroid_px-680_++ | \ 1615# polaroid_px-680_- | polaroid_px-680_-- | polaroid_px-680_cold | polaroid_px-680_cold_+ | polaroid_px-680_cold_++ | \ 1616# polaroid_px-680_cold_++_alt | polaroid_px-680_cold_- | polaroid_px-680_cold_-- | polaroid_px-680_warm | \ 1617# polaroid_px-680_warm_+ | polaroid_px-680_warm_++ | polaroid_px-680_warm_- | polaroid_px-680_warm_-- | \ 1618# polaroid_px-70 | polaroid_px-70_+ | polaroid_px-70_++ | polaroid_px-70_+++ | polaroid_px-70_- | polaroid_px-70_-- | \ 1619# polaroid_px-70_cold | polaroid_px-70_cold_+ | polaroid_px-70_cold_++ | polaroid_px-70_cold_- | \ 1620# polaroid_px-70_cold_-- | polaroid_px-70_warm | polaroid_px-70_warm_+ | polaroid_px-70_warm_++ | \ 1621# polaroid_px-70_warm_- | polaroid_px-70_warm_-- | polaroid_time_zero_expired | polaroid_time_zero_expired_+ | \ 1622# polaroid_time_zero_expired_++ | polaroid_time_zero_expired_- | polaroid_time_zero_expired_-- | \ 1623# polaroid_time_zero_expired_--- | polaroid_time_zero_expired_cold | polaroid_time_zero_expired_cold_- | \ 1624# polaroid_time_zero_expired_cold_-- | polaroid_time_zero_expired_cold_--- | portrait_1 | portrait_10 | portrait_2 | \ 1625# portrait_3 | portrait_4 | portrait_5 | portrait_6 | portrait_7 | portrait_8 | portrait_9 | progressen | \ 1626# protect_highlights_01 | prussian_blue | pseudogrey | purple | purple_2 | red_afternoon_01 | red_day_01 | \ 1627# red_dream_01 | redblueyellow | reds | reds_oranges_yellows | reeve_38 | remy_24 | rest_33 | retro | \ 1628# retro_brown_01 | retro_magenta_01 | retro_summer_3 | retro_yellow_01 | rollei_ir_400 | rollei_ortho_25 | \ 1629# rollei_retro_100_tonal | rollei_retro_80s | rotate_muted | rotate_vibrant | rotated | rotated_crush | \ 1630# saturated_blue | saving_private_damon | science_fiction | sea | serenity | seringe_4 | serpent | \ 1631# seventies_magazine | sevsuz | shade_kings_ink | shadow_king_39 | shine | skin_tones | smart_contrast | smokey | \ 1632# smooth_clear | smooth_cromeish | smooth_fade | smooth_green_orange | smooth_sailing | smooth_teal_orange | \ 1633# soft_fade | softwarming | solarized_color | solarized_color_2 | springmorning | sprocket_231 | spy_29 | street | \ 1634# studio_skin_tone_shaper | subtle_blue | subtle_green | subtle_yellow | summer | summer_alt | sunlightlove | sunny | \ 1635# sunny_alt | sunny_rich | sunny_warm | sunset_aqua_orange | sunset_intense_violet_blue | sunset_violet_mood | \ 1636# super_warm | super_warm_rich | sutro_fx | sweet_bubblegum | sweet_gelatto | taiga | tarraco | teal_fade | \ 1637# teal_moonlight | tealmagentagold | tealorange | tealorange_1 | tealorange_2 | tealorange_3 | \ 1638# technicalfx_backlight_filter | teigen_28 | tensiongreen_1 | tensiongreen_2 | tensiongreen_3 | tensiongreen_4 | \ 1639# terra_4 | the_matrices | thriller_2 | toastedgarden | trent_18 | true_colors_8 | turkiest_42 | tweed_71 | \ 1640# ultra_water | undeniable | undeniable_2 | unknown | urban_01 | urban_02 | urban_03 | urban_04 | urban_05 | \ 1641# urban_cowboy | uzbek_bukhara | uzbek_marriage | uzbek_samarcande | velvetia | very_warm_greenish | vfb_21 | \ 1642# vibrant | vibrant_alien | vibrant_contrast | vibrant_cromeish | victory | vintage | vintage_01 | vintage_02 | \ 1643# vintage_03 | vintage_04 | vintage_05 | vintage_163 | vintage_alt | vintage_brighter | vintage_chrome | \ 1644# vintage_mob | vintage_warmth_1 | violet_taste | vireo_37 | warm | warm_dark_contrasty | warm_fade | warm_fade_1 | \ 1645# warm_highlight | warm_neutral | warm_sunset_red | warm_teal | warm_vintage | warm_yellow | well_see | western | \ 1646# westernlut_2 | whiter_whites | winterlighthouse | wipe | wooden_gold_20 | yellow_55b | yellow_film_01 | \ 1647# yellowstone | you_can_do_it | zed_32 | zeke_39 | zilverfx_bw_solarization | zilverfx_infrared | \ 1648# zilverfx_vintage_bw }#@cli : Default values: 'resolution=33' and 'cut_and_round=1'. 1649#@cli : $ clut summer clut alien_green,17 clut orange_dark4,48 1650clut : check "isnum(${2=33}) && $2>0 && isbool(${3=1})" 1651 to_clutname "$1" name=${} l[] 1652 e[^-1] "Input CLUT '"$name"' with resolution $2." 1653 path_clut=${-path_cache} 1654 if isfile(['{/${path_clut}clut_$name.cimgz}']) i ${path_clut}clut_$name.cimgz fi 1655 if $!"!=1 || w<$2 || h<$2 || d<$2" # Decompression needed 1656 rm 1657 if narg($GMIC_SYSTEM_PATH) g_path_unix=$GMIC_SYSTEM_PATH 1658 else g_path_unix=/usr/lib/gimp/2.0/plug-ins/ 1659 fi 1660 path_test0=$path_clut 1661 path_test1=$_path_rc 1662 path_test2=${-path_gimp}plug-ins/ 1663 path_test3=${-path_gimp}plug-ins/gmic_gimp_qt/ 1664 path_test4=$g_path_unix 1665 repeat 5 file_clut=${path_test$>}/gmic_cluts.gmz 1666 l[] $file_clut onfail endl if $! break fi 1667 done 1668 if !$! # Download from G'MIC server 1669 i https://gmic.eu/gmic_cluts.gmz o ${path_clut}gmic_cluts.gmz 1670 fi 1671 1672 k[${"nmd 1,"$name}] 1673 if $!!=1 1674 rm i https://gmic.eu/gmic_cluts.gmz o ${path_clut}gmic_cluts.gmz # Try getting newest version of the CLUTs file 1675 repeat $! if ['{$>,n}']==['$name'] k[$>] break fi done 1676 if $!!=1 1677 error[0--5] "Command '$0': Unknown CLUT name '"$name"'." 1678 fi 1679 fi 1680 decompress_clut $2,$2,$2 1681 if $3 round c 0,255 to_rgb fi 1682 o. ${path_clut}clut_$name.cimgz 1683 elif "w>$2 || h>$2 || d>$2" r $2,$2,$2,3,2 # Downsize from higher resolution 1684 fi 1685 nm $name k. 1686 endl 1687 1688# [Internal] Use this command to 'clean' a .gmz file that represents CLUT keypoints. 1689# What it does is: 1690# 1691# - Standardize CLUT name. 1692# - Convert RGB CLUTs to Grayscale when possible. 1693# - Remove duplicates and sort by lexicographic order. 1694# - Display list of CLUTs to ease documentation update of command 'clut'. 1695# 1696clean_cluts : 1697 e[^-1] "Clean CLUT dataset.\n" 1698 round c 0,255 1699 1700 # Standardize names. 1701 repeat $! l[$>] 1702 nm={n} 1703 1704 # Standardize names for 'Moviz'. 1705 if "str = lowercase(['"$nm"*']); 1706 find(str,'tpf_-_cinematica_')==0" l[] 1707 if !narg($tpf) tpf=1 fi 1708 ('moviz_$tpf') 1709 tpf+=1 1710 nm={t} rm 1711 endl fi 1712 if "str = lowercase(['"$nm"*']); 1713 find(str,'_-_standard-vk')>=0" l[] 1714 if !narg($tpf) tpf=1 fi 1715 ('moviz_$tpf') 1716 tpf+=1 1717 nm={t} rm 1718 endl fi 1719 1720 # Standardize names for 'SmallHD MovieLook'. 1721 if "str = lowercase(['"$nm"*']); 1722 find(str,'_-_rec_709*')>=0" l[] 1723 ('$nm') z. 0,{w-11} 1724 nm={t} rm 1725 endl fi 1726 1727 # Standardize names for 'SmallHD MovieLook'. 1728 if "str = lowercase(['"$nm"']); 1729 find(str,'smallhd_movielook_')==0" l[] 1730 ('$nm') z. 18,100% 1731 replace_str "apocalypsethisverymoment","apocalypse_this_very_moment" 1732 replace_str "bobford","bob_ford" 1733 replace_str "lifegivingtree","life_giving_tree" 1734 replace_str "savingprivatedamon","saving_private_damon" 1735 replace_str "thematrices","the_matrices" 1736 nm={t} rm 1737 endl fi 1738 1739 # Standardize names for 'Fuji XTrans III'. 1740 if "str = lowercase(['"$nm"']); 1741 find(str,'fuji_xtrans_iii')==0" l[] 1742 ('$nm') 1743 replace_str "_-_","_" nm={t} rm 1744 endl fi 1745 1746 # Standardize names for 'RawTherapee'. 1747 if "str = lowercase(['"$nm"']); 1748 find(str,'kodak')==0 || 1749 find(str,'polaroid')==0 || 1750 find(str,'fuji')==0 || 1751 find(str,'ilford')==0" l[] 1752 ({'$nm'},{'*'}) 1753 replace_str " ","_" 1754 replace_str "xp_2","xp2" 1755 replace_str "hp_5","hp5" 1756 repeat 8 n={1+$>} 1757 replace_str "_"${n}"_+","_+" 1758 replace_str "_"${n}"_-","_-" 1759 replace_str "_"${n}"_alt","_alt" 1760 replace_str "_"${n}"_Alt","_alt" 1761 replace_str "_"${n}"*","*" 1762 done 1763 = 0,0,100% nm={t} rm 1764 endl fi 1765 1766 to_clutname $nm nm=${} 1767 1768 # Standardize names for 'PictureFX'. 1769 if "str = lowercase(['"$nm"']); 1770 find(str,'technicalfx')==0 || 1771 find(str,'picturefx')==0 || 1772 find(str,'analogfx')==0 || 1773 find(str,'goldfx')==0 || 1774 find(str,'zilverfx')==0" l[] 1775 ('$nm') 1776 replace_str "-","_" nm={t} rm 1777 endl fi 1778 1779 # Other name changes. 1780 l[] 1781 ({'$nm'},{'*'}) 1782 replace_str "_v_2*","*" 1783 replace_str "_v_1*","*" 1784 replace_str "_*","*" 1785 replace_str "_b_w","_bw" 1786 replace_str "&","" 1787 replace_str "rec_709_-_","rec709_" 1788 replace_str "s-log","slog" 1789 replace_str "__","_" 1790 replace_str "action_-_","action_" 1791 replace_str "-version-","" 1792 replace_str "picturefx_","" 1793 = 0,0,100% nm={t} rm 1794 endl 1795 nm $nm 1796 endl done 1797 1798 # Convert RGB CLUTs to Grayscale when possible. 1799 repeat $! l[$>] 1800 if "ref(crop(#0,0,0,0,3,1,h,1,1),R); 1801 ref(crop(#0,0,0,0,4,1,h,1,1),G); 1802 ref(crop(#0,0,0,0,5,1,h,1,1),B); 1803 R==G && G==B?1:0" 1804 channels 0,3 1805 fi 1806 endl done 1807 1808 # Search for duplicates and sort. 1809 p=0 for $p<$! 1810 nm0={$p,n} 1811 e[] "\r- Search duplicates for ["$p"] = '"$nm0"' " 1812 q={$p+1} for $q<$! 1813 nm={$q,n} 1814 if ['$nm0']==['$nm'] 1815 e[] " > Found duplicate ["$q"] -> Original 1x"{$p,h}", new 1x"{$q,h}"\n" 1816 rv[$p,$q] rm[$q] 1817 else q+=1 1818 fi 1819 done 1820 p+=1 1821 done 1822 sort_list +,n 1823 1824 # Display all clut names. 1825 doc="#@cli clut : \"clut_name\",_resolution>0,_cut_and_round={ 0=no | 1=yes }\n"\ 1826 "#@cli : Insert one of the "$!" pre-defined CLUTs at the end of the image list.\\n\n"\ 1827 "#@cli : 'clut_name' can be {" sep="|" 1828 nbc=28 1829 repeat $! l[$>] 1830 if !$< sep="}" fi 1831 str=" "{n}" "$sep 1832 s_str={size(['$str'])} 1833 nbc+=$s_str 1834 if $nbc<118 1835 doc=${doc}${str} 1836 else 1837 doc=${doc}" \\\n#"${str} 1838 nbc={1+$s_str} 1839 fi 1840 endl done 1841 1842 doc=${doc}"\n"\ 1843 "#@cli : Default values: 'resolution=33' and 'cut_and_round=1'.\n"\ 1844 "#@cli : $ clut summer clut alien_green,17 clut orange_dark4,48\n" 1845 e[] "\n"$doc 1846 1847#@cli m : eq. to 'command'. : (+) 1848 1849#@cli command : _add_debug_info={ 0 | 1 },{ filename | http[s]://URL | "string" } : (+) 1850#@cli : Import G'MIC custom commands from specified file, URL or string. 1851#@cli : (eq. to 'm').\n 1852#@cli : Imported commands are available directly after the 'command' invocation. 1853#@cli : Default value: 'add_debug_info=1'. 1854#@cli : $ image.jpg command "foo : mirror y deform $""1" +foo[0] 5 +foo[0] 15 1855 1856# compress_gmic 1857# Compress .gmic custom command files for compressing update files a little bit, 1858# by removing empty lines, and useless comments. 1859compress_gmic : 1860 merge_multiline_comments 1861 merge_multiline 1862 eval " # Remove useless comments 1863 p = 0; 1864 while (p<h, 1865 q = find(#-1,_'\n',p)%h; 1866 p==q?++p:( 1867 i[p]==_'#'?( # Line starts with a '#' 1868 ref(crop(0,p,1,5),cr); 1869 cr!='#@gui' && cr!='#@cli' && cr!='#@web'?copy(i[p],-1,q-p+1,1,0); # Remove comment line 1870 ):( # Line doesn't start with a '#' -> look for comment at line end 1871 l = find(#-1,_'#',p); 1872 l>=0 && l<q && i[l-1]<=_' '?( 1873 while (i[--l]<=_' ',0); 1874 copy(i[l+1],-1,q-l-1,1,0); 1875 ); 1876 0; 1877 ); 1878 p = q + 1; 1879 ); 1880 )" 1881 discard -1 1882 autocrop. {_'\n'} 1883 eval. "* # Merge consecutive line feeds 1884 i==_'\n' && j[1]==_'\n'?(i()=-1)" 1885 discard. -1 1886 eval. "* # Remove leading spaces on each line 1887 i<=_' ' && i!=_'\n' && j[-1]==_'\n'?( 1888 for (p = 1, j[p] && j[p]<=_' ' && j[p]!=_'\n', ++p); copy(i(),-1,p,1,0))" 1889 discard. -1 1890 1891#@cli cursor : _mode = { 0=hide | 1=show } : (+) 1892#@cli : Show or hide mouse cursor for selected instant display windows. 1893#@cli : Command selection (if any) stands for instant display window indices instead of image indices. 1894#@cli : Default value: 'mode=1'. 1895 1896#@cli delete : filename1[,filename2,...] : (+) 1897#@cli : Delete specified filenames on disk. Multiple filenames must be separated by commas. 1898 1899#@cli d : eq. to 'display'. : (+) 1900 1901#@cli display : _X[%]>=0,_Y[%]>=0,_Z[%]>=0,_exit_on_anykey={ 0 | 1 } : (+) 1902#@cli : Display selected images in an interactive viewer (use the instant display window [0] if opened). 1903#@cli : (eq. to 'd').\n 1904#@cli : Arguments 'X','Y','Z' determine the initial selection view, for 3D volumetric images. 1905#@cli : Default value: 'X=Y=Z=0' and 'exit_on_anykey=0'. 1906#@cli : $$ https://gmic.eu/oldtutorial/_display 1907 1908#@cli d0 : eq. to 'display0'. 1909d0 : 1910 _gmic_s="$?" v + _display2d 0,0 1911 1912#@cli display0 1913#@cli : Display selected images without value normalization. 1914#@cli : (eq. to 'd0'). 1915display0 : 1916 _gmic_s="$?" v + _display2d 0,0 1917 1918#@cli d2d : eq. to 'display2d'. 1919d2d : 1920 _gmic_s="$?" v + _display2d 0,1 1921 1922_d2d_core : 1923 _gmic_s="$?" _d2d_core=1 v + _display2d $1,1 1924 1925#@cli display2d 1926#@cli : Display selected 2d images in an interactive window. 1927#@cli : (eq. to 'd2d'). 1928#@cli : This command is used by default by command 'display' when displaying 2d images. 1929#@cli : If selected image is a volumetric image, each slice is displayed on a separate display 1930#@cli : window (up to 10 images can be displayed simultaneously this way), with synchronized moves. 1931#@cli : When interactive window is opened, the following actions are possible: 1932#@cli : * Left mouse button: Create an image selection and zoom into it. 1933#@cli : * Middle mouse button, or CTRL+left mouse button: Move image. 1934#@cli : * Mouse wheel or PADD+/-: Zoom in/out. 1935#@cli : * Arrow keys: Move image left/right/up/down. 1936#@cli : * `CTRL + A`: Enable/disable transparency (show/hide alpha channel). 1937#@cli : * `CTRL + C`: Decrease window size. 1938#@cli : * `CTRL + D`: Increase window size. 1939#@cli : * `CTRL + F`: Toggle fullscreen mode. 1940#@cli : * `CTRL + N`: Change normalization mode (can be { none | normal | channel-by-channel }). 1941#@cli : * `CTRL + O`: Save a copy of the input image, as a numbered file 'gmic_xxxxxx.gmz'. 1942#@cli : * `CTRL + R`: Reset both window size and view. 1943#@cli : * `CTRL + S`: Save a screenshot of the current view, as a numbered file 'gmic_xxxxxx.png'. 1944#@cli : * `CTRL + SPACE`: Reset view. 1945#@cli : * `CTRL + X`: Show/hide axes. 1946#@cli : * `CTRL + Z`: Hold/release aspect ratio. 1947display2d : 1948 _gmic_s="$?" v + _$0 0,1 1949 1950# $1 = exit_on_single_click?, can be { 0=no | 1=yes }. 1951# $2 = default window normalization for display window #0. 1952_display2d : check "isbool(${1=0}) && isint(${2=1}) && $2>=0" 1953 e[0--3] "Start interactive display of 2d image"$_gmic_s"." 1954 m "_d2d_format : 1955 if $""#>=8 u {_([$""*])[0,4]:\\ }\\ ...\\ {_([$""*])[$""#-4,4]:\\ } 1956 else ('\"$""*\"') replace. {','},32 u {t} rm. 1957 fi" 1958 p 1959 repeat $! l[$>] 1960 ('{n}') if s=crop();find(s,_'.',size(s)-1,-1)>0 nm={-2,b}.{-2,x} else nm={-2,b} fi rm. 1961 nm img 1962 1963 if !w v - d v + break fi 1964 if d>10 1965 error[0--6] "Command 'display2d': Input image has "{d}" slices, cannot manage more than 10 simultaneous views." 1966 fi 1967 is_multiview={d>1} 1968 is_moderate_ratio={0,D=[w,h];max(D)/min(D)<6} 1969 may_have_alpha={s==2||s>=4} 1970 alpha_mode,axes_mode,fullscreen_mode,ratio_mode={s==1||s==3},1,0,$is_moderate_ratio 1971 normalization_mode={{*}?!!{*,n}:$2} 1972 posx,posy,sizx,sizy={0,[0,0,w,h]} 1973 is_bottom_text,wait_event,mx,my,omb=0,1,-1,-1,0 1974 xsel0,ysel0,xsel1,ysel1,notification= 1975 wnormalization0={*,n} 1976 fontsize,fontsize_notif= 1977 1978 if $is_multiview" && "!${-is_macos} 1979 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 1980 elif d<=4 wsiz0=${fitscreen\ .,,45%} 1981 else wsiz0=${fitscreen\ .,,30%} 1982 fi 1983 wsiz0=${fitscreen\ $wsiz0,1,,90%} 1984 else wsiz0=${fitscreen\ .} 1985 fi 1986 1987 if $is_multiview 1988 if narg($_d2d_names) l[] $_d2d_names repeat $! wname$>={$>,t} done rm endl fi 1989 com_iskey,com_flushkey,com_isvisible,com_isresizeed,com_idisp,sep= 1990 repeat {img,d} 1991 if narg($_d2d_names) w$>[] {{*$>,w}?[-1,-1]:[$wsiz0]},0,${wname$>}" ("{w}x{h}x{d}x{s}")" 1992 else w$>[] {{*$>,w}?[-1,-1]:[$wsiz0]},0,$nm" ("{w}x{h}x{d}x{s}")-#"$> 1993 fi 1994 com_iskey.=$sep"{*"$>",$""1}" 1995 com_flushkey.=$sep"{*"$>",-$""1}" 1996 com_isvisible.=$sep"{*"$>"}" 1997 com_isresized.=$sep"{*"$>",r}" 1998 com_idisp.=$sep"{*"$>",x}" 1999 sep=, 2000 done 2001 m "iskey : u {max("$com_iskey")}"\n\ 2002 "flushkey : skip "$com_flushkey\n\ 2003 "isvisible : u {min("$com_isvisible")}"\n\ 2004 "isresized : u {max("$com_isresized")}"\n\ 2005 "idisp : u {argmax("$com_idisp")}" 2006 2007 # Auto-arrange display window layout in multi-view mode. 2008 if !${-is_macos} 2009 ww,wh={[$wsiz0]+[8,40]} 2010 if d==2 2011 if {*,u}/$ww>{*,v}/$wh # Horizontal alignment 2012 ox,oy={round([max(0,{*,u}-2*$ww),max(0,{*,v}-$wh)]/2)} 2013 w0[] -1,-1,-1,-1,$ox,$oy 2014 w1[] -1,-1,-1,-1,{$ox+$ww},$oy 2015 else # Vertical alignment 2016 ox,oy={round([{*,u}-$ww,{*,v}-2*$wh]/2)} 2017 w0[] -1,-1,-1,-1,$ox,$oy 2018 w1[] -1,-1,-1,-1,$ox,{$oy+$wh} 2019 fi 2020 elif d<=4 2021 ox,oy={round([max(0,{*,u}-2*$ww),max(0,{*,v}-2*$wh)]/2)} 2022 ww,wh+=$ox,$oy 2023 w0[] -1,-1,-1,-1,$ox,$oy 2024 w1[] -1,-1,-1,-1,$ww,$oy 2025 w2[] -1,-1,-1,-1,$ox,$wh 2026 if d==4 w3[] -1,-1,-1,-1,$ww,$wh fi 2027 else 2028 ox,oy={round([max(0,{*,u}-3*$ww),max(0,{*,v}-(d>6?3:2)*$wh)]/2)} 2029 ww2,wh2={2*[$ww,$wh]+[$ox,$oy]} 2030 ww,wh+=$ox,$oy 2031 w0[] -1,-1,-1,-1,$ox,$oy 2032 w1[] -1,-1,-1,-1,$ww,$oy 2033 w2[] -1,-1,-1,-1,$ww2,$oy 2034 w3[] -1,-1,-1,-1,$ox,$wh 2035 w4[] -1,-1,-1,-1,$ww,$wh 2036 if d>5 w5[] -1,-1,-1,-1,$ww2,$wh fi 2037 if d>6 w6[] -1,-1,-1,-1,$ox,$wh2 fi 2038 if d>7 w7[] -1,-1,-1,-1,$ww,$wh2 fi 2039 if d>8 w8[] -1,-1,-1,-1,$ww2,$wh2 fi 2040 fi 2041 fi 2042 2043 else 2044 w[] {{*,w}?[-1,-1]:[$wsiz0]},0,$nm" ("{w}x{h}x{d}x{s}")" 2045 m "iskey : u {*,$""1}"\n\ 2046 "flushkey : skip {*,-$""1}"\n\ 2047 "isvisible : u {*}"\n\ 2048 "isresized : u {*,r}"\n\ 2049 "idisp : u 0" 2050 fi 2051 2052 repeat {img,d} cursor[$>] 0 done 2053 2054 # Start event loop. 2055 for ${-isvisible}" && "!${"iskey ESC"}" && "!((${"iskey CTRLLEFT"}" || "${"iskey CTRLRIGHT"})" && "${"iskey W"}) 2056 2057 # Correct aspect ratio while centering image. 2058 if $ratio_mode" && "$sizx>16" && "$sizy>16 2059 nposx,nposy,nsizx,nsizy=$posx,$posy,$sizx,$sizy 2060 repeat 2 2061 if {*,w}/$sizx<{*,h}/$sizy 2062 nposy,nsizy={nsizy=$nsizx*{*,h}/{*,w};round([$nposy-(nsizy-$nsizy)/2,nsizy])} 2063 else 2064 nposx,nsizx={nsizx=$nsizy*{*,w}/{*,h};round([$nposx-(nsizx-$nsizx)/2,round(nsizx)])} 2065 fi 2066 if $<" && "$nsizx>w#0" && "$nsizy>h#0 nposx,nposy,nsizx,nsizy={[0,0,w#0,h#0]} fi 2067 done 2068 if [$nposx,$nposy,$nsizx,$nsizy]!=[$posx,$posy,$sizx,$sizy] 2069 posx,posy,sizx,sizy=$nposx,$nposy,$nsizx,$nsizy 2070 rmn baseview 2071 fi 2072 fi 2073 2074 # Generate baseview. 2075 if !narg($baseview) 2076 2077 # Get view corresponding to position and zoom factor. 2078 ($posx,{$posx+$sizx}) ($posy;{$posy+$sizy}) r[-2,-1] 2,2 a[-2,-1] c 2079 r. {[{*,w,h}]+1},1,2,3 z. 0,0,{[w,h]-2} round. 1,-1 ind_warp={$!-1} 2080 +channels[0] {0,[0,min(3,s-1)]} warp. ..,0,0,1 2081 if $is_multiview repeat {img,d-1} +slices[img] {1+$>} warp. [$ind_warp],0,0,1 done a[-{img,d}--1] z fi 2082 rm.. 2083 2084 if s>($alpha_mode?4:3) channels. 0,{$alpha_mode?3:2} fi # Discard useless channels 2085 if $normalization_mode 2086 # Find min and max values that are not nan of inf. 2087 eval[0] ">begin(m = inf; M = -inf); 2088 !isinf(i) && !isnan(i)?(m = min(i,m); M = max(i,M)); 2089 end(run('im,iM=',m,',',M))" 2090 vim,viM={[$im-abs($im),$iM+abs($iM)]} 2091 f. "isnan(i)?"$vim":isinf(i)?(i<0?"$vim":"$viM"):i" 2092 else 2093 im,iM=0,255 2094 f. "isnan(i)?"$im":isinf(i)?(i<0?"$im":"$iM"):i" 2095 fi 2096 2097 # Normalize view. 2098 if $normalization_mode==1 2099 sh. 0,{s-($alpha_mode" && "$may_have_alpha?2:1)} 2100 if $is_multiview repeat {img,d} +slices. $> n. 0,255 j.. .,0,0,$> rm. done else n. 0,255 fi 2101 rm. 2102 elif $normalization_mode==2 2103 sh. 0,{s-($alpha_mode" && "$may_have_alpha?2:1)} 2104 if $is_multiview repeat d*s z,c={[$>%d,int($>/d)]} sh. $z,$z,$c n. 0,255 rm. done 2105 else repeat s sh. $> n. 0,255 rm. done 2106 fi 2107 fi 2108 if $posx<0" || "$posy<0" || "$posx+$sizx>=w#0" || "$posy+$sizy>=h#0 2109 100%,100% 2110 rectangle. {A=-[$posx,$posy]*[w,h]/[$sizx,$sizy];\ 2111 B=A+[w#0,h#0]*[w,h]/[$sizx,$sizy]-1;\ 2112 [ceil(A),floor(B)]},1,1 2113 *[-2,-1] 2114 fi 2115 2116 # Add alpha channel if necessary. 2117 if $alpha_mode 2118 coords={A=-[$posx,$posy]*[w,h]/[$sizx,$sizy];\ 2119 B=A+[w#0,h#0]*[w,h]/[$sizx,$sizy]-1;\ 2120 [ceil(A),floor(B)]} 2121 if !$may_have_alpha # Alpha mode without alpha channel -> Add alpha channel 2122 100%,100%,1,1,64 rectangle. $coords,1,255 r. 100%,100%,.. a[-2,-1] c 2123 else # Alpha mode with alpha channel 2124 sh. 100% 100%,100%,1,1,64 rectangle. $coords,1,0 r. 100%,100%,.. +[-2,-1] rm. 2125 fi 2126 fi 2127 2128 # Render image with transparency pattern. 2129 if $alpha_mode 2130 (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] 2131 elif s==1 r. 100%,100%,100%,3 2132 elif s==2 r. 100%,100%,100%,3,0 2133 fi 2134 nm. baseview 2135 rmn view 2136 fi 2137 2138 # Manage notifications. 2139 if narg($notification) 2140 wait_event=0 2141 if !isnum($notification) # Create notification gfx 2142 rmn notification_gfx 2143 ofs,fs={narg($fontsize_notif)?0$fontsize_notif:32} 2144 do 2145 0 t. {``$notification},0,0,$fs,1,255 2146 if narg($fontsize_notif) break 2147 elif {baseview,"(w#-1>0.7*w || h#-1>0.25*h) && "$fs>13" && "$ofs>=$fs} 2148 ofs,fs=$fs,{max(13,round($fs/1.25))} rm. 2149 elif {baseview,"w#-1<0.3*w && h#-1<0.25*h && "$fs<64" && "$ofs<=$fs} 2150 ofs,fs=$fs,{min(64,round($fs*1.25))} rm. 2151 else 2152 fontsize_notif=$fs break 2153 fi 2154 while 1 2155 2156 r. {[w+12,h+8]},1,1,0,0,0.5,0.5 rectangle. 0,0,100%,100%,1,0xFFFFFFFF,255 to_rgb. 2157 nm. notification_gfx 2158 notification=$| 2159 else 2160 if $|>$notification+1 rm[notification_gfx] wait_event=1 notification= fi 2161 rmn view 2162 fi 2163 fi 2164 2165 # Generate view. 2166 if !narg($view) 2167 [baseview] 2168 if $mx>=0 2169 posmx,posmy={floor([$posx,$posy]+[$mx,$my]*[$sizx,$sizy]/[{*,w,h}])} 2170 is_selection_a_point={[0$xsel0,0$ysel0]==[0$xsel1,0$ysel1]} 2171 2172 if narg($xsel0)" && "!$is_selection_a_point 2173 dselx,dsely={[$xsel1-$xsel0,$ysel1-$ysel0]} 2174 ofs,fs={narg($fontsize)?0$fontsize:32} 2175 do 2176 0 t. " Box ( "{``{[min($xsel0,$xsel1),min($ysel0,$ysel1)]}}" ) - "\ 2177 "( "{``{[max($xsel0,$xsel1),max($ysel0,$ysel1)]}}" ) \n"\ 2178 " Size = ( "{``{abs([$dselx,$dsely]+1)}}" ), "\ 2179 "Length = "{_norm($dselx,$dsely)}" \n"\ 2180 " Angle = "{_atan2($dsely,$dselx)*180/pi}"\260 ",1,0,$fs,1,1 2181 if narg($fontsize) break 2182 elif {baseview,"(w#-1>0.7*w || h#-1>0.45*h) && "$fs>13" && "$ofs>=$fs} 2183 ofs,fs=$fs,{max(13,round($fs/1.25))} rm. 2184 elif {baseview,"w#-1<0.3*w && h#-1<0.45*h && "$fs<64" && "$ofs<=$fs} 2185 ofs,fs=$fs,{min(64,round($fs*1.25))} rm. 2186 else 2187 fontsize=$fs break 2188 fi 2189 while 1 2190 n. 0,255 +dilate. 3 *. -1 n. 0,80 +[-2,-1] r. 100%,100%,..,.. 2191 j.. .,0,$is_bottom_text~,0,0,0.85 rm. 2192 fi 2193 2194 if $mx>=0 2195 if $posmx>=0" && "$posmx<w#0" && "$posmy>=0" && "$posmy<h#0 2196 if !narg($xsel0)" || "$is_selection_a_point 2197 repeat {img,d} 2198 if {img,P=I($posmx,$posmy,$>);(s>=1" || "s<=4)" && "min(isint(P))" && "min(P)>=0" && "max(P)<=255} 2199 hexstr="= \#"\ 2200 {img,`"digit(x) = (x<10?_'0' + x:_'A' + x - 10);\ 2201 P = I("$posmx,$posmy,$>");\ 2202 [ digit(P[0]>>4),digit(P[0]&15),\ 2203 s<2?0:digit(P[1]>>4),s<2?0:digit(P[1]&15),\ 2204 s<3?0:digit(P[2]>>4),s<3?0:digit(P[2]&15),\ 2205 s<4?0:digit(P[3]>>4),s<4?0:digit(P[3]&15) ]"`}" " 2206 else hexstr= fi 2207 ofs,fs={narg($fontsize)?0$fontsize:32} 2208 do 2209 0 t. " Point ( "$posmx","$posmy" ) = [ "${_d2d_format\ {img,_I($posmx,$posmy,$>)}}" ] "$hexstr,\ 2210 1,0,$fs,1,1 2211 if narg($fontsize) break 2212 elif {baseview,"(w#-1>0.7*w || h#-1>0.15*h) && "$fs>13" && "$ofs>=$fs} 2213 _ofs,fs=$fs,{max(13,round($fs/1.25))} rm. 2214 elif {baseview,"w#-1<0.3*w && h#-1<0.15*h && "$fs<64" && "$ofs<=$fs} 2215 ofs,fs=$fs,{min(64,round($fs*1.25))} rm. 2216 else 2217 fontsize=$fs break 2218 fi 2219 while 1 2220 2221 n. 0,255 +dilate. 3 *. -1 n. 0,80 +[-2,-1] r. 100%,100%,1,.. 2222 j.. .,0,$is_bottom_text~,$>,0,0.85 rm. 2223 done 2224 fi 2225 x0,y0,x1,y1={[round([$posmx-$posx,$posmy-$posy]*[{*,w,h}]/[$sizx,$sizy]),\ 2226 round([$posmx-$posx+1,$posmy-$posy+1]*[{*,w,h}]/[$sizx,$sizy])-1]} 2227 if $x1-$x0>=8" && "$y1-$y0>=8 # Draw pixel contour when zoomed-in 2228 repeat d==1?1:d*s if d==1 sh. else sh. {z=$>%d;[z,z,int($>/d)]} fi 2229 rectangle. $x0,$y0,$x1,$y1,1,0x55555555,0 2230 rectangle. $x0,$y0,$x1,$y1,1,0xAAAAAAAA,255 2231 rm. 2232 done 2233 fi 2234 fi 2235 if $axes_mode # Draw horizontal/vertical axes 2236 repeat d==1?1:d*s if d==1 sh. else sh. {z=$>%d;[z,z,int($>/d)]} fi 2237 line. $mx,0,$mx,100%,0.5,0xFF00FF00,255 2238 line. $mx,0,$mx,100%,0.5,0x00FF00FF,0 2239 line. 0,$my,100%,$my,0.5,0xFF00FF00,255 2240 line. 0,$my,100%,$my,0.5,0x00FF00FF,0 2241 rm. 2242 done 2243 fi 2244 fi 2245 2246 if narg($xsel0) # Draw rectangular selection 2247 x0,y0,x1,y1={xm=min($xsel0,$xsel1);xM=max($xsel0,$xsel1);\ 2248 ym=min($ysel0,$ysel1);yM=max($ysel0,$ysel1);\ 2249 [[xm-$posx,ym-$posy]*[{*,w,h}]/[$sizx,$sizy],\ 2250 [xM+1-$posx,yM+1-$posy]*[{*,w,h}]/[$sizx,$sizy]-1]} 2251 repeat d==1?1:d*s if d==1 sh. else sh. {z=$>%d;[z,z,int($>/d)]} fi 2252 rectangle. $x0,$y0,$x1,$y1,0.2,0 2253 rectangle. $x0,$y0,$x1,$y1,0.9,0x55555555,0 2254 rectangle. $x0,$y0,$x1,$y1,0.9,0xAAAAAAAA,255 2255 rm. 2256 done 2257 if $xsel0>$xsel1 x0,x1=$x1,$x0 fi 2258 if $ysel0>$ysel1 y0,y1=$y1,$y0 fi 2259 if $xsel0!=$xsel1" && "$ysel0!=$ysel1 2260 x0,y0,x1,y1={[(0.5+[$xsel0-$posx,$ysel0-$posy])*[{*,w,h}]/[$sizx,$sizy],\ 2261 (0.5+[$xsel1-$posx,$ysel1-$posy])*[{*,w,h}]/[$sizx,$sizy]]} 2262 repeat d==1?1:d*s if d==1 sh. else sh. {z=$>%d;[z,z,int($>/d)]} fi 2263 line. $x0,$y0,$x1,$y1,0.9,0x33333333,0 2264 line. $x0,$y0,$x1,$y1,0.9,0xCCCCCCCC,255 2265 rm. 2266 done 2267 fi 2268 fi 2269 fi 2270 2271 if $notification_gfx 2272 +r[notification_gfx] 100%,100%,. j.. .,{[w#-2-w-4,4]},0,0,{sqrt(max(0,1-($|-$notification)))} rm. 2273 fi 2274 2275 nm. view 2276 if $is_multiview repeat d +slices[view] $> w$>. rm. done else w. fi 2277 fi 2278 2279 # Manage user events. 2280 if $wait_event wait else wait 40 fi 2281 idisp=${-idisp} # Index of 'active' display window 2282 wait_event=1 2283 2284 old_mx,old_my=$mx,$my 2285 nposx,nposy,nsizx,nsizy=$posx,$posy,$sizx,$sizy 2286 is_CTRL,mb,mx,my,mo={${"iskey CTRLLEFT"}" || "${"iskey CTRLRIGHT"}},{*$idisp,b,x,y,-o} 2287 2288 # Test end of pan shift. 2289 if !($mb&4)" && "!($is_CTRL" && "($mb&1)) pan_mx,pan_my,pan_posx,pan_posy= fi 2290 2291 # Test if text must be displayed at the bottom. 2292 if {view,$my<0" || "$my>=h-16} is_bottom_text=0 2293 elif $my<16 is_bottom_text=1 2294 fi 2295 2296 # Events related to window resizing. 2297 if ${-isresized} # One of the display windows has been resized 2298 repeat {img,d},w if {*$w,r} 2299 w$w[] {*$w,d,e} 2300 if $is_multiview repeat {img,d} w$>[] {*$w,w,h} done fi 2301 if $nsizx>w#0" && "$nsizy>h#0 nposx,nposy,nsizx,nsizy={[0,0,w#0,h#0]} fi 2302 break 2303 fi done 2304 fontsize,fontsize_notif= 2305 rmn baseview 2306 elif $is_CTRL" && "${"iskey D"}" && "{*$idisp,d}<{*$idisp,u}" && "{*$idisp,e}<{*$idisp,v} # Increase window size 2307 w$idisp[] {round([{*$idisp,w,h}]*1.25)} 2308 if $is_multiview repeat {img,d} w$>[] {*$idisp,w,h} done fi 2309 notification="Increase Window Size" 2310 fontsize,fontsize_notif= 2311 flushkey D rmn baseview 2312 elif $is_CTRL" && "${"iskey C"}" && "{*$idisp,d}>64" && "{*$idisp,e}>64 # Decrease window size 2313 w$idisp[] {round([{*$idisp,w,h}]/1.25)} 2314 if $is_multiview repeat {img,d} w$>[] {*$idisp,w,h} done fi 2315 notification="Decrease Window Size" 2316 fontsize,fontsize_notif= 2317 flushkey C rmn baseview 2318 elif $is_CTRL" && "${"iskey R"} # Reset window size (and view) 2319 nposx,nposy,nsizx,nsizy={0,[0,0,w,h]} 2320 repeat {img,d} w$>[] $wsiz0 done 2321 notification="Reset Window Size" 2322 fontsize,fontsize_notif= 2323 flushkey R rmn baseview 2324 fi 2325 2326 # Events related to image selection. 2327 if !$is_CTRL" && "$mb&1" && "$mx>0 2328 xsel,ysel={X=[$nposx,$nposy]+[$mx,$my]*[$nsizx,$nsizy]/[{*,w,h}];\ 2329 floor([max(0,min(X[0],w#0-1)),max(0,min(X[1],h#0-1))])} 2330 if !narg($xsel0)" && "!($omb&1) xsel0,ysel0,xsel1,ysel1=$xsel,$ysel,$xsel,$ysel 2331 elif narg($xsel0) xsel1,ysel1=$xsel,$ysel 2332 fi 2333 if $mx<=16 nposx-={$nsizx/64} wait_event=0 xzoom,yzoom= 2334 elif $mx>={*,w}-17 nposx+={$nsizx/64} wait_event=0 xzoom,yzoom= 2335 fi 2336 if $my<=16 nposy-={$nsizy/64} wait_event=0 xzoom,yzoom= 2337 elif $my>{*,h}-17 nposy+={$nsizx/64} wait_event=0 xzoom,yzoom= 2338 fi 2339 wait_event=0 2340 rmn view 2341 elif !($mb&1) 2342 if narg($xsel0) 2343 2344 if "p0 = ["$xsel0,$ysel0]"; p1 = ["$xsel1,$ysel1"]; # One px selection -> reset view or exit. 2345 siz = max("$sizx,$sizy"); 2346 p0==p1 || (siz>128 && norm1(p1-p0)<=siz/100)" 2347 if $1" && "$nsizx>=w#0" && "$nsizy>=h#0 break fi 2348 nposx,nposy,nsizx,nsizy={0,[0,0,w,h]} 2349 else # Otherwise, zoom in 2350 nposx,nposy,nsizx,nsizy={[min($xsel0,$xsel1),min($ysel0,$ysel1),abs([$xsel1-$xsel0,$ysel1-$ysel0])+1]} 2351 fi 2352 xzoom,yzoom= mb={$mb&6} 2353 rmn view 2354 fi 2355 xsel0,ysel0,xsel1,ysel1= 2356 fi 2357 2358 # Events related to image displacement and mode changes. 2359 if ${"iskey ARROWLEFT"} nposx-={$nsizx/($is_CTRL?4:16)} xzoom,yzoom= # Go left 2360 elif ${"iskey ARROWRIGHT"} nposx+={$nsizx/($is_CTRL?4:16)} xzoom,yzoom= # Go right 2361 elif ${"iskey ARROWUP"} nposy-={$nsizy/($is_CTRL?4:16)} xzoom,yzoom= # Go up 2362 elif ${"iskey ARROWDOWN"} nposy+={$nsizy/($is_CTRL?4:16)} xzoom,yzoom= # Go down 2363 elif $is_CTRL" && "${"iskey O"} # Save copy 2364 n=0 do filename gmic.gmz,$n n+=1 while isfile(['{/${}}']) 2365 if $is_multiview +slices[img] $idisp o. ${} rm. else o[img] ${} fi 2366 notification="Save Copy:\n"${} 2367 flushkey O 2368 elif $is_CTRL" && "${"iskey S"} # Save screenshot 2369 n=0 do filename gmic.png,$n n+=1 while isfile(['{/${}}']) 2370 if $is_multiview +slices[baseview] $idisp o. ${} rm. else o[baseview] ${} fi 2371 notification="Save Screenshot:\n"${} 2372 flushkey S 2373 elif $is_CTRL" && "${"iskey SPACE"} # Center view 2374 nposx,nposy,nsizx,nsizy={0,[0,0,w,h]} 2375 notification="Center View" 2376 flushkey SPACE 2377 elif $is_CTRL" && "${"iskey N"} # Change normalization mode 2378 normalization_mode={($normalization_mode+1)%3} 2379 notification=${"s0=Disable s1=Enable s2=\"Enable C.by.C\" u ${s"$normalization_mode"}"}" Normalization" 2380 flushkey N rmn baseview 2381 elif $is_CTRL" && "${"iskey A"} # Toggle alpha mode 2382 alpha_mode={!$alpha_mode} 2383 notification=${"s0=Disable s1=Enable u ${s"$alpha_mode"}"}" Alpha" 2384 flushkey A rmn baseview 2385 elif $is_CTRL" && "${"iskey F"} # Toggle fullscreen mode 2386 fullscreen_mode={!$fullscreen_mode} 2387 if $fullscreen_mode 2388 fullscreen_wsize={*,w,h} fullscreen_params=$nposx,$nposy,$nsizx,$nsizy 2389 w[] {*,u,v},0,1 2390 else 2391 nposx,nposy,nsizx,nsizy=$fullscreen_params 2392 w[] $fullscreen_wsize,0,0 2393 fi 2394 repeat {img,d} cursor[$>] {!$axes_mode} done 2395 notification=${"s0=Disable s1=Enable u ${s"$fullscreen_mode"}"}" Fullscreen" 2396 flushkey F rmn baseview 2397 elif $is_CTRL" && "${"iskey X"} # Toggle axes mode 2398 repeat {img,d} cursor[$>] $axes_mode done axes_mode={!$axes_mode} 2399 notification=${"s0=Hide s1=Show u ${s"$axes_mode"}"}" Axes" 2400 flushkey X rmn view 2401 elif $is_CTRL" && "${"iskey Z"}" && "$is_moderate_ratio # Toggle aspect-ratio mode 2402 ratio_mode={!$ratio_mode} 2403 notification=${"s0=Release s1=Hold u ${s"$ratio_mode"}"}" Aspect Ratio" 2404 if !$ratio_mode nposx,nposy,nsizx,nsizy={0,[0,0,w,h]} fi 2405 flushkey Z rmn baseview 2406 elif $mx>=0" && "($mb&4" || "($is_CTRL" && "$mb&1)) # Pan (middle mouse button) 2407 if !narg($pan_mx) pan_mx,pan_my,pan_posx,pan_posy=$mx,$my,$posx,$posy fi 2408 nposx,nposy={shiftx=($mx-$pan_mx)*$nsizx/{*,w};\ 2409 shifty=($my-$pan_my)*$nsizy/{*,h};\ 2410 [$pan_posx-shiftx,$pan_posy-shifty]} 2411 xzoom,yzoom= 2412 elif ${"iskey PADSUB"}" || "($mx>=0" && "$mo<0) # Zoom out 2413 if $nsizx>=w#0" && "$nsizy>=h#0 2414 nposx,nposy,nsizx,nsizy={[$nposx/2,$nposy/2,w#0,h#0]} 2415 else 2416 if !narg($xzoom) 2417 xzoom,yzoom={X=$mx<0?[$nposx,$nposy]+[$nsizx,$nsizy]/2:\ 2418 [$nposx,$nposy]+[$mx,$my]*[$nsizx,$nsizy]/[{*,w,h}];\ 2419 [max(0,min(X[0],w#0-1)),max(0,min(X[1],h#0-1))]} 2420 fi 2421 nposx,nposy,nsizx,nsizy={[[$xzoom,$yzoom]+[$nposx-$xzoom,$nposy-$yzoom]/0.75,\ 2422 min(w#0,round($nsizx/0.75)),\ 2423 min(h#0,round($nsizy/0.75))]} 2424 if $nsizx>w#0" && "$nsizy>h#0 nsizx,nsizy={[w#0,h#0]} fi 2425 fi 2426 elif ($nsizx>2" || "$nsizy>2)" && "(${"iskey PADADD"}" || "($mx>=0" && "$mo>0)) # Zoom in 2427 xzoom,yzoom={X=$mx<0?[$nposx,$nposy]+[$nsizx,$nsizy]/2:\ 2428 [$nposx,$nposy]+[$mx,$my]*[$nsizx,$nsizy]/[{*,w,h}];\ 2429 [max(0,min(X[0],w#0-1)),max(0,min(X[1],h#0-1))]} 2430 nposx,nposy,nsizx,nsizy={[[$xzoom,$yzoom]+0.75*[$nposx-$xzoom,$nposy-$yzoom],round(0.75*[$nsizx,$nsizy])]} 2431 fi 2432 2433 # Constrain image displacement. 2434 if $nposx>=w#0-0.5*$nsizx nposx={w#0-1-0.5*$nsizx} 2435 elif $nposx<=-0.5*$nsizx nposx={1-0.5*$nsizx} 2436 fi 2437 if $nposy>=h#0-0.5*$nsizy nposy={h#0-1-0.5*$nsizy} 2438 elif $nposy<=-0.5*$nsizy nposy={1-0.5*$nsizy} 2439 fi 2440 2441 if [$nposx,$nposy,$nsizx,$nsizy]!=[$posx,$posy,$sizx,$sizy] 2442 posx,posy,sizx,sizy=$nposx,$nposy,$nsizx,$nsizy 2443 rmn baseview 2444 fi 2445 if [$mx,$my]!=[$old_mx,$old_my] rmn view fi 2446 omb=$mb 2447 2448 done 2449 k[0] 2450 if narg($_d2d_core) w[] -1,-1,$wnormalization0 2451 else 2452 if $is_multiview repeat d w$>[] 0 done else w[] 0 fi 2453 fi 2454 nm $nm um iskey,flushkey,isvisible,isresized,idisp endl done 2455 um _d2d_format v -1 d[] 2456 2457#@cli d3d : eq. to 'display3d'. 2458d3d : skip "${1=},${2=0}" 2459 l[] is_image_arg=${"is_image_arg $1"} is_arg={$is_image_arg" || isnum($1)"} onfail is_arg=0 endl 2460 if $is_arg arg=$is_image_arg,$2 if $is_image_arg pass$1 1 _d3d_wh={[w,h]} store. _d3d_background fi 2461 else arg=0,0 noarg fi 2462 v + _display3d $arg 2463 2464#@cli display3d : _[background_image],_exit_on_anykey={ 0 | 1 } : _exit_on_anykey={ 0 | 1 } 2465#@cli : Display selected 3D objects in an interactive viewer (use the instant display window [0] if opened). 2466#@cli : (eq. to 'd3d'). 2467#@cli : Default values: '[background_image]=(default)' and 'exit_on_anykey=0'. 2468display3d : skip "${1=},${2=0}" 2469 l[] is_image_arg=${"is_image_arg $1"} is_arg={$is_image_arg" || isnum($1)"} onfail is_arg=0 endl 2470 if $is_arg arg=$is_image_arg,$2 if $is_image_arg pass$1 1 _d3d_wh={[w,h]} store. _d3d_background fi 2471 else arg=0,0 noarg fi 2472 v + _$0 $arg 2473 2474# $1 = is_user_background? 2475# $2 = exit_on_any_key? 2476_display3d : 2477 is_user_background,exit_on_anykey=$1,$2 2478 if !$! e[0--3] "Display 3D object []." return fi 2479 2480 repeat $! l[$>] 2481 l. check3d 0 2482 onfail l[] ({'${}'}) s +,{'"'check3d': "'} k. msg={t} rm endl error[] "Command 'display3d': "$msg 2483 endl 2484 nm={n} nbv,nbp={f2ui([i[6],i[7]])} 2485 e[0--5] "Display 3D object ["{arg(1+$>,$[])}"] = '"$nm"' ("$nbv" vertices, "$nbp" primitives)." 2486 2487 # Init display window and variables. 2488 disp_title=$nm" ("$nbv" vertices, "$nbp" primitives)" 2489 if !{*} 2490 if narg($_d3d_wh) w[] ${fitscreen\ $_d3d_wh,1},0,$disp_title 2491 else w[] {0.7*[{*,u,v}]},0,$disp_title 2492 fi 2493 else disp_normalization={*,n} w[] -1,-1,0,$disp_title fi 2494 disp_size0={*,w,h} 2495 2496 (1,0,0,0;0,1,0,0;0,0,1,0) store. pose3d 2497 posx,posy,zoomfactor=50,50,1 2498 is_fullscreen,is_zbuffer,is_axes3d,is_outline,is_boundingbox,is_animate,is_outvideo={*,f},1,1,0,0,0,0 2499 mode_render=4 2500 mode_drender={$nbp<2048?$mode_render:-1} 2501 mode_background={$is_user_background?7:3} 2502 mode_orientation=2 2503 mode_animate=1 2504 speed_animate=1 2505 focale=800 2506 mx0,my0,mx1,my1= 2507 notification= fontsize_notif= 2508 wait_event=1 2509 2510 # Create 3D axes. 2511 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 2512 2513 # Start interactive loop. 2514 do 2515 is_motion={narg($mx0)} 2516 if $is_animate" || "$is_outvideo rmn render fi 2517 2518 # Init background image. 2519 if !narg($background) 2520 if $mode_background<3 {*,w,h},1,3,{arg(1+$mode_background,0,255,128)} 2521 elif $mode_background==3 3,2,1,1,"32,32,64,64,116,96" permute. cyzx r. {*,w,h},1,3,3 round. 2522 elif $mode_background==4 3,2,1,1,"0,0,0,0,64,96" permute. cyzx r. {*,w,h},1,3,3 round. 2523 elif $mode_background==5 3,2,1,1,"8,0,0,160,90,0" permute. cyzx r. {*,w,h},1,3,3 round. 2524 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 2525 else $_d3d_background r. {*,w,h},1,3,1 2526 fi 2527 w. nm. background 2528 rmn object3d 2529 fi 2530 2531 # Init normalized 3D object. 2532 if !narg($object3d) 2533 +c3d[0] n3d. *3d. {background,$zoomfactor*0.65*min(w,h)} 2534 if $mode_orientation==1 rv3d. fi 2535 rmn boundingbox3d 2536 if $is_boundingbox +boundingbox3d. o3d. 0.35 nm. boundingbox3d +3d.. . rv[-2,-1] fi 2537 nm. object3d 2538 rmn render 2539 fi 2540 2541 # Render 3D object. 2542 if !narg($render) 2543 $pose3d 2544 if $is_animate" || "$is_outvideo l. 2545 da={$speed_animate*($is_animate?20*($|-$time_animate):1)} 2546 if $mode_animate==0 rotation3d 1,0,0,$da rv 2547 elif $mode_animate==1 rotation3d 0,1,0,$da rv 2548 elif $mode_animate==2 rotation3d 0,0,1,$da rv 2549 else 2550 dax,day,daz={[0.75,0.82,0.97]*$da} 2551 rotation3d 0,1,0,$dax rotation3d 1,0,0,$day rotation3d 0,0,1,$daz rv 2552 fi 2553 m* 1,3,1,1 j.. .,3 rm. +store. pose3d 2554 time_animate=$| 2555 endl fi 2556 p={^} rm. 2557 m={$is_motion?$mode_drender:$mode_render} 2558 [background] nm. render 2559 if $m<0 2560 if !narg($boundingbox3d) +boundingbox3d[object3d] o3d. 0.35 nm. boundingbox3d fi 2561 +pose3d[boundingbox3d] $p 2562 j3d[render] .,$posx%,$posy%,0,1,1,0,0,$focale rm. 2563 else 2564 +pose3d[object3d] $p 2565 if $is_outline 2566 {render,[w,h]},1,3,-1 2567 j3d. ..,$posx%,$posy%,0,1,$m,{$mode_orientation==2},$is_zbuffer,$focale 2568 +channels. 0 !=. -1 2569 +dilate. 5 r. 100%,100%,1,3 j[render] .,0,0,0,0,0.8,. rm. 2570 j[render] ..,0,0,0,0,1,. rm[-2,-1] 2571 else j3d[render] .,$posx%,$posy%,0,1,$m,{$mode_orientation==2},$is_zbuffer,$focale 2572 fi 2573 rm. 2574 fi 2575 if $is_axes3d 2576 +pose3d[axes3d] $p 2577 eval " # Colorize axes depending on their Z-sign 2578 const off = "$off_axes"; 2579 ref([ 255,0,0 ],col); 2580 i[13]>0?copy(i[off],col,3); 2581 i[19]>0?copy(i[off + 3],col,3); 2582 i[25]>0?copy(i[off + 6],col,3); 2583 " 2584 j3d[render] .,50,{-2,h-50},0,0.75,1,0,0,$focale rm. 2585 fi 2586 rmn view 2587 2588 if $is_outvideo 2589 o[render] $filename_outvideo,20,0,1 2590 nb_frames={int(360/$speed_animate)} 2591 if $is_outvideo>=$nb_frames 2592 o[] $filename_outvideo,20,0,0 # Close video stream 2593 is_outvideo=0 2594 notification="Output Video:\nDone!" 2595 else 2596 is_outvideo+=1 2597 notification="Output Video:\nFrame "{$is_outvideo+1}/$nb_frames 2598 fi 2599 fi 2600 fi 2601 2602 # Manage notifications. 2603 if narg($notification) 2604 wait_event=0 2605 if !isnum($notification) # Create notification gfx 2606 rmn notification_gfx 2607 ofs,fs={narg($fontsize_notif)?0$fontsize_notif:32} 2608 do 2609 0 t. {``$notification},0,0,$fs,1,255 2610 if narg($fontsize_notif) break 2611 elif {background,"(w#-1>0.7*w || h#-1>0.25*h) && "$fs>13" && "$ofs>=$fs} 2612 ofs,fs=$fs,{max(13,round($fs/1.25))} rm. 2613 elif {background,"w#-1<0.3*w && h#-1<0.25*h && "$fs<64" && "$ofs<=$fs} 2614 ofs,fs=$fs,{min(64,round($fs*1.25))} rm. 2615 else 2616 fontsize_notif=$fs break 2617 fi 2618 while 1 2619 r. {[w+12,h+8]},1,1,0,0,0.5,0.5 rectangle. 0,0,100%,100%,1,0xFFFFFFFF,255 to_rgb. 2620 nm. notification_gfx 2621 notification=$| 2622 else 2623 if $|>$notification+1 rm[notification_gfx] wait_event=1 notification= fi 2624 rmn view 2625 fi 2626 fi 2627 2628 # Refresh window view. 2629 if !narg($view) 2630 if $notification_gfx 2631 +j[render] [notification_gfx],0.99~,5,0,0,{sqrt(max(0,1-($|-$notification)))} 2632 else [render] 2633 fi 2634 nm. view w. -1,-1,0,$is_fullscreen,$disp_title 2635 fi 2636 2637 if $is_motion" || "$is_animate wait_event=0 fi 2638 if $wait_event wait elif !$is_outvideo wait 20 fi 2639 2640 # Manage user-events 2641 if $exit_on_anykey" && "{*,k} break fi 2642 if $is_outvideo continue fi # Skip user event management 2643 mx,my,mb={*,x,y,b} 2644 is_CTRL={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 2645 if {*,-F1} # Render: Dots 2646 mode_render,mode_drender={M=0;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2647 notification="Render: Dots" if $mode_drender<0 notification.=" + Box" fi 2648 rmn render 2649 elif {*,-F2} # Render: Wireframe 2650 mode_render,mode_drender={M=1;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2651 notification="Render: Wireframe" if $mode_drender<0 notification.=" + Box" fi 2652 rmn render 2653 elif {*,-F3} # Render: Flat 2654 mode_render,mode_drender={M=2;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2655 notification="Render: Flat" if $mode_drender<0 notification.=" + Box" fi 2656 rmn render 2657 elif {*,-F4} # Render: Flat-shaded 2658 mode_render,mode_drender={M=3;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2659 notification="Render: Flat-Shaded" if $mode_drender<0 notification.=" + Box" fi 2660 rmn render 2661 elif {*,-F5} # Render: Gouraud-shaded 2662 mode_render,mode_drender={M=4;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2663 notification="Render: Gouraud-Shaded" if $mode_drender<0 notification.=" + Box" fi 2664 rmn render 2665 elif {*,-F6} # Render: Phong-shaded 2666 mode_render,mode_drender={M=5;m=$mode_render;wasbbox=$mode_drender<0;[M,m!=M?(wasbbox?-1:M):(wasbbox?M:-1)]} 2667 notification="Render: Phong-Shaded" if $mode_drender<0 notification.=" + Box" fi 2668 rmn render 2669 elif {*,-F7}" && "($focale>100" || "!$focale) # Decrease focale 2670 if !$focale focale=2000 else focale-=100 fi 2671 notification="Focale: "$focale 2672 rmn render 2673 elif {*,-F8}" && "$focale # Increase focale 2674 if $focale>=2000 focale=0 notification="Focale: Inf" else focale+=100 notification="Focale: "$focale fi 2675 rmn render 2676 elif {*,-F9} # Choose animation mode 2677 mode_animate={($mode_animate+1)%4} 2678 n0,n1,n2,n3="X-Axis","Y-Axis","Z-Axis","XYZ-Axes" notification="Animation Mode: "${n$mode_animate} 2679 rmn render 2680 elif {*,-F10} # Choose animation speed 2681 speed_animate={max(1,($speed_animate+1)%9)} 2682 notification="Animation Speed: X"$speed_animate 2683 elif {*,-SPACE} # Start/stop animation 2684 is_animate,time_animate={!$is_animate},$| 2685 n0,n1="Off","On" notification="Animation: "${n$is_animate} 2686 rmn render 2687 fi 2688 if $is_CTRL 2689 if {*,-A} # Show/hide 3D axes 2690 is_axes3d={!$is_axes3d} 2691 n0,n1="Off","On" notification="3D Axes: "${n$is_axes3d} 2692 rmn render 2693 elif {*,-B} # Change background 2694 mode_background={($mode_background+1)%($is_user_background?8:7)} 2695 n0,n1,n2,n3,n4,n5,n6,n7=\ 2696 "Black","White","Gray","Gradient \#1","Gradient \#2","Gradient \#3","Checkerboard","User-Defined" 2697 notification="Background: "${n$mode_background} 2698 rmn background 2699 elif {*,-C}" && "{*,w}>128" && "{*,h}>128 w[] {0.8*[{*,w,h}]} # Decrease window size 2700 notification="Decrease Window Size" fontsize_notif= 2701 rmn background 2702 elif {*,-D}" && "{*,w}<0.8*{*,u}" && "{*,h}<0.8*{*,v} w[] {1.25*[{*,w,h}]} # Increase window size 2703 notification="Increase Window Size" fontsize_notif= 2704 rmn background 2705 elif {*,-F} # Toggle fullscreen 2706 is_fullscreen={!$is_fullscreen} 2707 if $is_fullscreen w[] {*,u,v} else w[] {0.75*[{*,u,v}]} fi 2708 n0,n1="Off","On" notification="Fullscreen: "${n$is_fullscreen} fontsize_notif= 2709 rmn background 2710 elif {*,-G} # Save object as a .obj file 2711 n=0 do filename gmic.obj,$n n+=1 while isfile(['{/${}}']) 2712 notification="Save Copy:\n"${} 2713 o[0] ${} 2714 elif {*,-L} # Show/hide outline 2715 is_outline={!$is_outline} 2716 n0,n1="Off","On" notification="Outline: "${n$is_outline} 2717 rmn render 2718 elif {*,-O} # Save object as a .gmz file 2719 n=0 do filename gmic.gmz,$n n+=1 while isfile(['{/${}}']) 2720 o[0] ${} 2721 notification="Save Copy:\n"${} 2722 elif {*,-P} # Print 3D pose on console 2723 $pose3d v 0 e[] " > 3D Pose = [ "{^}" ]." rm. 2724 elif {*,-R} # Reset window 2725 w[] $disp_size0 2726 notification="Reset Window Size" fontsize_notif= 2727 rmn background 2728 elif {*,-S} # Save screenshot 2729 n=0 do filename gmic.png,$n n+=1 while isfile(['{/${}}']) 2730 o[render] ${} 2731 notification="Save Screenshot:\n"${} 2732 elif {*,-T} # Change orientation mode 2733 mode_orientation={($mode_orientation+1)%3} 2734 n0,n1,n2="Forward","Backward","Double-Sided" notification="Orientation: "${n$mode_orientation} 2735 if $mode_orientation rv3d[object3d] fi 2736 rmn render 2737 elif {*,-V} # Start/stop output video 2738 is_outvideo={!$is_outvideo} 2739 is_animate=0 2740 n=0 do filename gmic.mp4,$n n+=1 while isfile(['{/${}}']) 2741 filename_outvideo=${} 2742 elif {*,-X} # Show/hide bounding box 2743 is_boundingbox={!$is_boundingbox} 2744 n0,n1="Off","On" notification="Bounding Box: "${n$is_boundingbox} 2745 rmn object3d 2746 elif {*,-Z} # Enable/disable Z-buffer 2747 is_zbuffer={!$is_zbuffer} 2748 n0,n1="Off","On" notification="Z-Buffer: "${n$is_zbuffer} 2749 rmn render 2750 fi 2751 fi 2752 if {*,-r} rmn background fontsize_notif= fi 2753 2754 if $mx>=0 # Manage mouse-drag 2755 if $mb 2756 if !narg($mx0) mx0,my0,mx1,my1=$mx,$my,$mx,$my else mx1,my1=$mx,$my fi 2757 else 2758 if narg($mx0) rmn render fi 2759 mx0,my0,mx1,my1= 2760 fi 2761 fi 2762 2763 # Estimate new 3D pose from motion. 2764 if narg($mx1)" && "($mx0!=$mx1" || "$my0!=$my1) 2765 rmn render 2766 if $mb&1" && "!$is_CTRL # Rotation 2767 rotation3d[] {" 2768 const w2 = "{*,w}"/2; 2769 const h2 = "{*,h}"/2; 2770 const R = 0.375*min("{*,w,h}"); 2771 const u0 = "$mx0" - w2; 2772 const v0 = "$my0" - h2; 2773 const u1 = "$mx1" - w2; 2774 const v1 = "$my1" - h2; 2775 n0 = norm(u0,v0); 2776 nu0 = n0>R?u0*R/n0:u0; 2777 nv0 = n0>R?v0*R/n0:v0; 2778 nw0 = sqrt(max(0,R^2 - nu0^2 - nv0^2)); 2779 n1 = norm(u1,v1); 2780 nu1 = n1>R?u1*R/n1:u1; 2781 nv1 = n1>R?v1*R/n1:v1; 2782 nw1 = sqrt(max(0,R^2 - nu1^2 - nv1^2)); 2783 u = nv0*nw1 - nw0*nv1; 2784 v = nw0*nu1 - nu0*nw1; 2785 w = nv0*nu1 - nu0*nv1; 2786 n = norm(u,v,w); 2787 [ u,v,w,-asin(n/R^2)*180/pi ]"} 2788 $pose3d m*[-2,-1] store. pose3d 2789 mx0,my0=$mx1,$my1 2790 elif $mb&4" || "($mb&1" && "$is_CTRL) # Pan 2791 posx,posy={" 2792 const px = "$mx1-$mx0+$posx*{*,w}%"; 2793 const py = "$my1-$my0+$posy*{*,h}%"; 2794 cut([ px*100/"{*,w}", py*100/"{*,h}" ],0,100)"} 2795 mx0,my0=$mx1,$my1 2796 elif $mb&2 # Zoom with mouse button 2797 fact={1+($my0-$my1)/100} 2798 zoomfactor*=$fact 2799 *3d[object3d] $fact if narg($boundingbox3d) *3d[boundingbox3d] $fact fi 2800 mx0,my0=$mx1,$my1 2801 fi 2802 fi 2803 if {*,o} # Zoom with mousewheel 2804 fact={1+{*,-o}/10} 2805 zoomfactor*=$fact 2806 *3d[object3d] $fact if narg($boundingbox3d) *3d[boundingbox3d] $fact fi 2807 rmn render 2808 fi 2809 2810 while {*}" && "!{*,ESC}" && "!($is_CTRL" && "{*,W}) 2811 k[0] 2812 endl done 2813 if narg($disp_normalization) w[] -1,-1,$disp_normalization else w[] 0 fi 2814 v -1 d[] 2815 2816#@cli da : eq. to 'display_array'. 2817da : 2818 _gmic_s="$?" v + _display_array $* 2819 2820#@cli display_array : _width>0,_height>0 2821#@cli : Display images in interactive windows where pixel neighborhoods can be explored. 2822#@cli : Default values: 'width=13' and 'height=width'. 2823display_array : 2824 _gmic_s="$?" v + _$0 $* 2825 2826_display_array : check ${1=13}>0" && "${2=$1}>0 2827 e[0--3] "Display $1x$2 array of pixel values for image"$_gmic_s"." 2828 2829 dxb={round($1/2,1,1)} dxf={$1-1-$dxb} 2830 dyb={round($2/2,1,1)} dyf={$2-1-$dyb} 2831 2832 repeat $! l[$>] 2833 if w<128" && "h<128 r 128,128,100%,100%,0,0,0.5,0.5 fi # Manage cases of small and large images. 2834 x0=0 y0=0 w={w} h={h} 2835 wmax={0.9*{*,u}} hmax={0.9*{*,v}} 2836 do 2837 if w>=$wmax" || "h>=$hmax 2838 n={n} nm. "Image "'{b}.{x}'" is too large, please select a sub-image." 2839 +select. 2 x0={i[0]} y0={i[1]} w={1+i[3]-i[0]} h={1+i[4]-i[1]} 2840 rm. nm. $n 2841 fi 2842 +z. $x0,$y0,0,{$x0+$w-1},{$y0+$h-1},0 round. 1 n. 0,255 2843 while w>=$wmax" || "h>=$hmax 2844 2845 x1=-1 y1=-1 c1=0 ox1=-1 oy1=-1 oc1=-1 2846 x2=-1 y2=-1 c2=0 ox2=-1 oy2=-1 oc2=-1 2847 x3=-1 y3=-1 c3=0 ox3=-1 oy3=-1 oc3=-1 2848 c0=0 oxm=-1 oym=-1 2849 w. -1,-1,0,0,{-2,b}.{-2,x} 2850 do # Enter event loop. 2851 2852 # Manage user interactions. 2853 wait[0-3] 2854 oc0=$c0 2855 repeat 4 2856 if $>" && "!{*$>}" && "${x$>}>=0 w$> 0 x$>=-1 y$>=-1 c$>=0 fi 2857 if {*$>,o} c$>={(${c$>}+sign({*$>,o}))%s} wait[$>] -1 fi 2858 if {*$>,SPACE}" || "{*$>,ENTER}" || "{*$>,ARROWRIGHT}" || "{*$>,ARROWDOWN} c$>={(${c$>}+1)%s} wait[$>] -1 fi 2859 if {*$>,BACKSPACE}" || "{*$>,ARROWLEFT}" || "{*$>,ARROWUP} c$>={(${c$>}-1)%s} wait[$>] -1 fi 2860 done 2861 if $oc0!=$c0 c1=$c0 c2=$c0 c3=$c0 fi 2862 xm={*,x} ym={*,y} 2863 if $xm>=0" && "{*,b}&1 x1=$xm y1=$ym fi 2864 if $xm>=0" && "{*,b}&2 x2=$xm y2=$ym fi 2865 if $xm>=0" && "{*,b}&4 x3=$xm y3=$ym fi 2866 2867 # Generate main image view. 2868 if $xm>=0" && "($oxm!=$xm" || "$oym!=$ym) w[] -1,-1,{-2,b}.{-2,x}" - ("$xm,$ym")" fi 2869 if $x1!=$ox1" || "$y1!=$oy1" || "$x2!=$ox2" || "$y2!=$oy2" || "$x3!=$ox3" || "$y3!=$oy3 2870 . 2871 if $x1>=0 2872 xb={$x1-$dxb} yb={$y1-$dyb} xe={$x1+$dxf} ye={$y1+$dyf} 2873 rectangle. $xb,$yb,$xe,$ye,0.2,0,255,255 2874 rectangle. $xb,$yb,$xe,$ye,1,0xFFFFFFFF,0,255,255 2875 fi 2876 if $x2>=0 2877 xb={$x2-$dxb} yb={$y2-$dyb} xe={$x2+$dxf} ye={$y2+$dyf} 2878 rectangle. $xb,$yb,$xe,$ye,0.2,255,32,255 2879 rectangle. $xb,$yb,$xe,$ye,1,0xFFFFFFFF,255,32,255 2880 fi 2881 if $x3>=0 2882 xb={$x3-$dxb} yb={$y3-$dyb} xe={$x3+$dxf} ye={$y3+$dyf} 2883 rectangle. $xb,$yb,$xe,$ye,0.2,255,255,0 2884 rectangle. $xb,$yb,$xe,$ye,1,0xFFFFFFFF,255,255,0 2885 fi 2886 w. {-2,w},{-2,h} rm. oxm=$xm oym=$ym 2887 fi 2888 2889 # Generate zoomed views. 2890 if $x1>=0" && "($ox1!=$x1" || "$oy1!=$y1" || "$oc1!=$c1) 2891 +z.. {$x1-$dxb},{$y1-$dyb},0,$c1,{$x1+$dxf},{$y1+$dyf},0,$c1 2892 +z.. {$x1-$dxb},{$y1-$dyb},0,{$x1+$dxf},{$y1+$dyf},0 2893 __display_array[-2,-1] $1,$2,0,255,255 2894 w1. {w},{h},0,0,{-3,b}" - ("$x1,$y1,c=$c1")" 2895 rm. ox1=$x1 oy1=$y1 oc1=$c1 2896 fi 2897 if $x2>=0" && "($ox2!=$x2" || "$oy2!=$y2" || "$oc2!=$c2) 2898 +z.. {$x2-$dxb},{$y2-$dyb},0,$c2,{$x2+$dxf},{$y2+$dyf},0,$c2 2899 +z.. {$x2-$dxb},{$y2-$dyb},0,{$x2+$dxf},{$y2+$dyf},0 2900 __display_array[-2,-1] $1,$2,255,32,255 2901 w2. {w},{h},0,0,{-3,b}" - ("$x2,$y2,c=$c2")" 2902 rm. ox2=$x2 oy2=$y2 oc2=$c2 2903 fi 2904 if $x3>=0" && "($ox3!=$x3" || "$oy3!=$y3" || "$oc3!=$c3) 2905 +z.. {$x3-$dxb},{$y3-$dyb},0,$c3,{$x3+$dxf},{$y3+$dyf},0,$c3 2906 +z.. {$x3-$dxb},{$y3-$dyb},0,{$x3+$dxf},{$y3+$dyf},0 2907 __display_array[-2,-1] $1,$2,255,255,0 2908 w3. {w},{h},0,0,{-3,b}" - ("$x3,$y3,c=$c3")" 2909 rm. ox3=$x3 oy3=$y3 oc3=$c3 2910 fi 2911 while {*}" && "\ 2912 !{*,ESC}" && "!{*,Q}" && "\ 2913 !{*1,ESC}" && "!{*1,Q}" && "\ 2914 !{*2,ESC}" && "!{*2,Q}" && "\ 2915 !{*3,ESC}" && "!{*3,Q} 2916 k[0] w 0 w1 0 w2 0 w3 0 2917 endl done 2918 2919__display_array : 2920 round.. 1 c.. 0,999 r. 100%,100%,1,3,{s==1} 2921 +luminance. r.. {$1*24},{$2*24} grid.. {100/$1}%,{100/$2}%,0,0,1,0 2922 xb={24*int($1/2)} yb={24*int($2/2)} xe={$xb+24} ye={$yb+24} 2923 rectangle.. $xb,$yb,$xe,$ye,1,0xFFFFFFFF,$3,$4,$5 2924 repeat $2,yg 2925 repeat $1,xg 2926 t.. {-3,i($xg,$yg)},{5+$xg*24},{5+$yg*24},13,0.8,{i($xg,$yg)>128?0:255} 2927 done 2928 done 2929 rm[-3,-1] 2930 2931#@cli dc : eq. to 'display_camera'. 2932dc : check_opencv $0 2933 v + _display_camera 2934 2935#@cli display_camera 2936#@cli : Open camera viewer. 2937#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 2938display_camera : check_opencv $0 2939 v + _$0 2940 2941_display_camera : 2942 e[0--3] "Open camera stream viewer." 2943 2944 # Initialize camera and get resolution. 2945 l[] camera 2946 onfail 2947 use_vt100 2948 e[0--4] ${_vt100_r}${_vt100_b}"Command 'display_camera': Unable to read camera stream. Exiting."$_vt100_n 2949 return 2950 endl 2951 2952 wc,hc={[w,h]} 2953 2954 # Open interactive window. 2955 w ${"fitscreen "$wc,$hc},0,"G'MIC Camera Stream Viewer" 2956 wnfs,hnfs={*,w,h} 2957 angle,fullscreen,brightness,contrast=0 2958 do 2959 2960 # Display frame from camera. 2961 ww,wh={*,w,h} 2962 camera 2963 if $angle rotate. {90*$angle} fi 2964 if $brightness +. {10*$brightness} c. 0,255 fi 2965 if $contrast /. 255 *. {1.2^$contrast} *. 255 c. 0,255 fi 2966 rr2d. $ww,$wh,2,1 w. 2967 rm 2968 wait 30 2969 2970 # Manage user events. 2971 if {*,r} w[] {*,d,e} 2972 elif {*,-R}" || "{*,-SPACE} angle={($angle+1)%4} 2973 elif {*,-ARROWUP} brightness={min(5,$brightness+1)} 2974 elif {*,-ARROWDOWN} brightness={max(-5,$brightness-1)} 2975 elif {*,-ARROWRIGHT} contrast={min(5,$contrast+1)} 2976 elif {*,-ARROWLEFT} contrast={max(-5,$contrast-1)} 2977 elif {*,-F}" || "{*,-ENTER}" || "{*,-F5} 2978 fullscreen={1-$fullscreen} 2979 if $fullscreen 2980 wwnfs,whnfs={*,w,h} 2981 w[] {*,u,v},0,1 2982 else 2983 w[] $wwnfs,$whnfs,0,0 2984 fi 2985 fi 2986 2987 while {*}" && "!{*,ESC} 2988 camera 0,0 w[] 0 2989 2990#@cli dfft : eq. to 'display_fft'. 2991dfft : 2992 v + _display_fft 2993 2994#@cli display_fft 2995#@cli : Display fourier transform of selected images, with centered log-module and argument. 2996#@cli : (eq. to 'dfft'). 2997#@cli : $ image.jpg +display_fft 2998display_fft : 2999 v + _$0 3000 3001_display_fft : 3002 e[0--3] "Render fourier transform of image$? with centered log-module and argument." 3003 repeat $! l[$>] fftpolar +.. 1 log.. n 0,255 a x endl done s x,2 3004 3005#@cli dg : eq. to 'display_graph'. 3006dg : 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}" 3007 _display_graph ${1-8},"$9","$10" 3008 3009#@cli display_graph : _width>=0,_height>=0,_plot_type,_vertex_type,_xmin,_xmax,_ymin,_ymax,_xlabel,_ylabel 3010#@cli : Render graph plot from selected image data. 3011#@cli : 'plot_type' can be { 0=none | 1=lines | 2=splines | 3=bar }. 3012#@cli : 'vertex_type' can be { 0=none | 1=points | 2,3=crosses | 4,5=circles | 6,7=squares }. 3013#@cli : 'xmin','xmax','ymin','ymax' set the coordinates of the displayed xy-axes. 3014#@cli : if specified 'width' or 'height' is '0', then image size is set to half the screen size. 3015#@cli : Default values: 'width=0', 'height=0', 'plot_type=1', 'vertex_type=1', 'xmin=xmax=ymin=ymax=0 (auto)', \ 3016# 'xlabel="x-axis"' and 'ylabel="y-axis"'. 3017#@cli : $ 128,1,1,1,'cos(x/10+u)' +display_graph 400,300,3 3018display_graph : check "${1=0}>=0 && ${2=0}>=0" 3019 skip ${3=1},${4=0},${5=0},${6=0},${7=0},${8=0},"${9=x-axis}","${10=y-axis}" 3020 _display_graph ${1-8},"$9","$10" 3021 3022_display_graph : check "${1=0}>=0 && ${2=0}>=0" 3023 skip ${3=1},${4=0},${5=0},${6=0},${7=0},${8=0},"${9=x-axis}","${10=y-axis}" 3024 e[0--3] "Render $1x$2 graph plot from data of image$?." 3025 3026 repeat $! l[$>] nm={0,n} 3027 3028 # Determine output size. 3029 if $1>0" && "$2>0 w,h=$1,$2 else w,h={{*,u}/2},{{*,v}/2} fi 3030 w,h={[max($w,33),max($h,33)]} 3031 3032 # Determine xmin,xmax/ymin,ymax. 3033 one={$3!=3} siz={w*h*d} 3034 if $5==$6 xmin=0 xmax={$siz-$one} else xmin={min($5,$6)} xmax={max($5,$6)} fi 3035 if $7==$8 ymin={im-(iM-im)/20} ymax={iM+(iM-im)/20} else ymin={min($7,$8)} ymax={max($7,$8)} fi 3036 dx={$xmax-$xmin} dy={$ymax-$ymin} 3037 3038 # Determine number of axes tick marks. 3039 u=${"_axes[] "$xmin,$xmax",{0.3*"$w"/14}"} offx={arg(1,$u)} deltax={arg(2,$u)} 3040 u=${"_axes[] "$ymin,$ymax",{0.3*"$h"/14}"} offy={arg(1,$u)} deltay={arg(2,$u)} 3041 3042 # Create plot canvas. 3043 gw={$w-32} gh={$h-32} gg={($gw-$one)/($siz-$one)} 3044 $gw,$gh,1,3,255 3045 3046 grid. {$deltax*$gw/$dx},{$deltay*$gh/$dy},{($offx-$xmin)*$gw/$dx},{$gh-($offy-$ymin)*$gh/$dy},0.25,0xCCCCCCCC,0 3047 3048 # Define color palette for curves. 3049 if s#-2==1 (120,120,200) 3050 elif s#-2<=3 (220,10,10;10,220,10;10,10,220) 3051 else 3052 (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 3053 sh. 0,2,0,0 f. 255,0,0,0,255,0,0,0,255 rm. 3054 fi 3055 3056 # Draw plot for each channel. 3057 repeat s#-3 sh... $> graph... .,$3,$4,$ymax,$ymin,1,{-2,@0-2} rm. shift. 0,-1 done 3058 rm[-3,-1] 3059 line. 0,0,100%,0,1,110 line. 100%,0,100%,100%,1,110 3060 line. 100%,100%,0,100%,1,255 line. 0,100%,0,0,1,255 3061 3062 100%,100%,1,1,255 3063 axes. $xmin,$xmax,$ymax,$ymin,14,1,0 3064 if $xmin>0 axes. 0,0,$ymax,$ymin,14,1,160 fi 3065 if $xmax<0 axes. {w-1},{w-1},$ymax,$ymin,14,1,160 fi 3066 if $ymin>0 axes. $xmin,$xmax,{h-1},{h-1},14,1,160 fi 3067 if $ymax<0 axes. $xmin,$xmax,0,0,14,1,160 fi 3068 +erode. 3 !=. 255 r.. 100%,100%,1,3 j... ..,0,0,0,0,1,.,1 rm[-2,-1] 3069 frame. 16,16,220 3070 0 t. "$9",0,0,14,1,-220,-220,-220 j.. .,{({-2,w}-w)/2},{{-2,h}-16},0,0,-1 rm. 3071 0 t. "$10",0,0,14,1,-220,-220,-220 rotate. -90 j.. .,2,{({-2,h}-h)/2},0,0,-1 rm. 3072 3073 nm $nm endl done c 0,255 3074 3075#@cli dh : eq. to 'display_histogram'. 3076dh : 3077 _gmic_s="$?" v + _display_histogram $"*" 3078 3079#@cli display_histogram : _width>=0,_height>=0,_clusters>0,_min_value[%],_max_value[%],_show_axes={ 0 | 1 },_expression. 3080#@cli : Render a channel-by-channel histogram. 3081#@cli : If selected images have several slices, the rendering is performed for all input slices. 3082#@cli : 'expression' is a mathematical expression used to transform the histogram data for visualization purpose. 3083#@cli : (eq. to 'dh'). 3084#@cli : if specified 'width' or 'height' is '0', then image size is set to half the screen size. 3085#@cli : Default values: 'width=0', 'height=0', 'clusters=256', 'min_value=0%', 'max_value=100%', 'show_axes=1' \ 3086# and 'expression=i'. 3087#@cli : $ image.jpg +display_histogram 512,300 3088display_histogram : 3089 _gmic_s="$?" v + _$0 $"*" 3090 3091_display_histogram : check "${1=0}>=0 && ${2=0}>=0 && ${3=256}>0" skip ${4=0%},${5=100%},${6=1},"${7=i}" 3092 e[0--3] "Render $1x$2 channel-by-channel histogram of image"$_gmic_s", with $3 clusters, minimum value $4 3093 and maximum value $5." 3094 repeat $! l[$>] nm={0,n} 3095 if ${is_percent\ $4} m={im+(iM-im)*$4} else m=$4 fi 3096 if ${is_percent\ $5} M={im+(iM-im)*$5} else M=$5 fi 3097 s={s} s c 3098 repeat $s l[{-1-$>}] s z histogram $3,$m,$M a z endl done 3099 a c f '"${7--1}"' vM={iM} s z 3100 repeat $! l[$>] 3101 if $1>0" && "$2>0 wh=$1,$2 else wh={{*,u}/2},{{*,v}/2} fi 3102 $wh,1,{s},-255 3103 repeat s sh[-2,-1] $> graph. ..,3,0,$vM,0,1,0 rm[-2,-1] done 3104 rm.. + 255 3105 if $6 3106 100%,100% 3107 axes. $m,$M,$vM,0,14,1,255 3108 if $m>0 axes. 0,0,$vM,0,14,1,200 fi 3109 if $M<0 axes. {w-1},{w-1},$vM,0,14,1,200 fi 3110 +dilate. 3 ri.. ... j... ..,0,0,0,0,1,.,255 rm[-2,-1] 3111 fi 3112 endl done 3113 a z nm $nm 3114 endl done 3115 3116#@cli display_parametric : _width>0,_height>0,_outline_opacity,_vertex_radius>=0,_is_antialiased={ 0 | 1 },\ 3117# _is_decorated={ 0 | 1 },_xlabel,_ylabel 3118#@cli : Render 2D or 3D parametric curve or point clouds from selected image data. 3119#@cli : Curve points are defined as pixels of a 2 or 3-channel image. 3120#@cli : If the point image contains more than 3 channels, additional channels define the (R,G,B) color for each vertex. 3121#@cli : If 'outline_opacity>1', the outline is colored according to the specified vertex colors and 3122#@cli : 'outline_opacity-1' is used as the actual drawing opacity. 3123#@cli : Default values: 'width=512', 'height=width', 'outline_opacity=3', 'vertex_radius=0', 'is_antialiased=1',\ 3124# 'is_decorated=1', 'xlabel="x-axis"' and 'ylabel="y-axis"'. 3125#@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 3126#@cli : $ 1000,1,1,2,u(-100,100) quantize 4,1 noise 12 channels 0,2 +normalize 0,255 append c \ 3127# display_parametric 512,512,0.1,8 3128display_parametric : check "${1=512}>0 && ${2=$1}>0 && ${4=0}>=0" skip ${3=3},${5=1},${6=1},"${7=x-axis}","${8=y-axis}" 3129 s0="no " s1="" o0="" o1="colored " 3130 e[^-1] "Render $1x$2 parametric graph plot from data of image$?, with "${o{$3>1}}"outline opacity "\ 3131 {$3>1?$3-1:$3}", vertex radius $4, "${s{$5!=0}}"antialiasing and "${s{$6!=0}}"decoration." 3132 repeat $! l[$>] 3133 nm={0,n} N={w*h*d} 3134 i[0] ('CImg3d') +[0] 0.5 i[1] ($N;$N) # Header + nb of vertices/primitives. 3135 3136 # Calibrate colors of vertices. 3137 if s==4 +channels. 3,3 r. 100%,100%,1,2 a[-2,-1] c is_grayscale=1 3138 else is_grayscale={s<4} channels. 0,5 3139 fi 3140 3141 # Manage coordinates of vertices. 3142 sh. 0 xm={im} xM={iM} rm. 3143 sh. 1 ym={im} yM={iM} rm. 3144 sh. 2 zm={im} zM={iM} rm. 3145 permute. cxyz s. x,2 3146 i.. (1,0;1,{$N-1}) r.. 2,$N,1,1,3 round.. 1,$N,1,1,1 # Primitives, colors and opacities. 3147 y a y c3d n3d *3d 1,-1,1 3148 3149 {if($6,max(1,$1-32),$1)},{if($6,max(1,$2-32),$2)},1,{if($is_grayscale,1,3)},255 3150 *3d[0] {0.96*min(w,h)} 3151 if $6 L={0.1*max($1,$2)} grid[1] $L,$L,0,0,0.25,0xCCCCCCCC,0 fi 3152 3153 if $5 # Anti-aliased. 3154 r[1] 200%,200%,1,100%,1 *3d[0] 2 3155 if $4 +circles3d[0] {2*$4} j3d[1] [2],50%,50%,0,1,3,0,0 rm[2] fi 3156 elif $4 # Aliased. 3157 +circles3d[0] $4 j3d[1] [2],50%,50%,0,1,3,0,0 rm[2] 3158 fi 3159 3160 # Convert point cloud to connected segments. 3161 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] 3162 r[5] 1,{h-1},1,1,0 3163 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 3164 y a y endl j3d[1] [0],50%,50%,0,{if($3>1,$3-1,$3)},2,0,0 3165 fi 3166 3167 rm[0] 3168 if $5 r. 50%,50%,1,100%,2 fi 3169 3170 if $6 # Add decoration. 3171 xc={0.5*($xm+$xM)} yc={0.5*($ym+$yM)} dx={0.5*($xM-$xm)/0.96} dy={0.5*($yM-$ym)/0.96} 3172 xm={$xc-$dx} xM={$xc+$dx} ym={$yc-$dy} yM={$yc+$dy} 3173 100%,100%,1,1,255 axes. $xm,$xM,$yM,$ym,14,1,0 3174 if $xm>0 axes. 0,0,$yM,$ym,14,1,160 fi 3175 if $xM<0 axes. {w-1},{w-1},$yM,$ym,14,1,160 fi 3176 if $ym>0 axes. $xm,$xM,{h-1},{h-1},14,1,160 fi 3177 if $yM<0 axes. $xm,$xM,0,0,14,1,160 fi 3178 +erode. 3 !=. 255 r.. 100%,100%,1,3 j... ..,0,0,0,0,1,.,1 rm[-2,-1] 3179 frame 1,1,128 frame 15,15,220 3180 0 t. "$7",0,0,14,1,-220,-220,-220 j.. .,{({-2,w}-w)/2},{{-2,h}-16},0,0,-1 rm. 3181 0 t. "$8",0,0,14,1,-220,-220,-220 rotate. -90 j.. .,2,{({-2,h}-h)/2},0,0,-1 rm. 3182 fi 3183 nm. $nm 3184 endl done 3185 3186#@cli dp : eq. to 'display_parallel'. 3187dp : 3188 _gmic_s="$?" v + _display_parallel 1 3189 3190#@cli display_parallel 3191#@cli : Display each selected image in a separate interactive display window. 3192#@cli : (eq. to 'dp'). 3193display_parallel : 3194 _gmic_s="$?" v + _$0 1 3195 3196# $1 = Normalization used for display window. 3197_display_parallel : check ${1=0}>=0 3198 e[0--3] "Display image$? in parallel." 3199 print 3200 is_d2d_compatible={"res = l<=10; repeat (l,k, res&=(w#k==w && h#k==h && d#k==1 && s#k==s))"} 3201 if $is_d2d_compatible 3202 N=$! 3203 repeat $! 3204 if s=['{$>,n}'];find(s,_'.',size(s)-1,-1)>0 nm={$>,b}.{$>,x} else nm={$>,b} fi 3205 ('$nm':;) 3206 done 3207 store[-$N--1] _d2d_names 3208 a z _display2d 0,$1 s z 3209 _d2d_names= 3210 else 3211 if $!<=1 v - d v + return fi 3212 14,$! eval. "!x?copy(i(),[[',d['],vtos(y,10,10),_']'])" =. 0 discard. 0 str={t} rm. 3213 m "__dp : parallel "$str __dp um __dp 3214 fi 3215 v -1 d[] 3216 3217#@cli dp0 : eq. to 'display_parallel0'. 3218dp0 : 3219 _gmic_s="$?" v + _display_parallel 0 3220 3221#@cli display_parallel0 3222#@cli : Display each selected image in a separate interactive display window, without value normalization. 3223#@cli : (eq. to 'dp0'). 3224display_parallel0 : 3225 _gmic_s="$?" v + _display_parallel 0 3226 3227#@cli display_polar : _width>32,_height>32,_outline_type,_fill_R,_fill_G,_fill_B,_theta_start,_theta_end,_xlabel,_ylabel 3228#@cli : Render polar curve from selected image data. 3229#@cli : 'outline_type' can be { r<0=dots with radius -r | 0=no outline | r>0=lines+dots with radius r }. 3230#@cli : 'fill_color' can be { -1=no fill | R,G,B=fill with specified color }. 3231#@cli : Default values: 'width=500', 'height=width', 'outline_type=1', 'fill_R=fill_G=fill_B=200', 'theta_start=0', \ 3232# 'theta_end=360', 'xlabel="x-axis"' and 'ylabel="y-axis"'. 3233#@cli : $ 300,1,1,1,'0.3+abs(cos(10*pi*x/w))+u(0.4)' display_polar 512,512,4,200,255,200 3234#@cli : $ 3000,1,1,1,'x^3/1e10' display_polar 400,400,1,-1,,,0,{15*360} 3235display_polar : check "${1=500}>32 && ${2=$1}>32" 3236 skip ${3=1},${4=200},${5=$4},${6=$5},${7=0},${8=360},"${9=x-axis}","${10=y-axis}" 3237 e[^-1] "Render $1x$2 polar graph plot from data of image"$_gmic_s", with outline $4 and fill color ($4,$5,$6)." 3238 repeat $! l[$>] nm={0,n} 3239 3240 # Compute (x,y) coordinates of the polar curve points. 3241 M={max(abs(iM),abs(im))} 3242 * {0.48*min($1,$2)/$M} 3243 y ({$7*pi/180};{-$8*pi/180}) r. 1,..,1,1,3 3244 +sin. cos.. *. ... *[-3,-2] 3245 a[-2,-1] x N={h} 3246 nm. coords 3247 3248 # Generate 3D object for curve outline. 3249 if $3 3250 ('CImg3d') +. 0.5 ($N,$N) 3251 +z[coords] 0,2 3252 1,$N,1,1,2 1,$N,1,1,'y' ++. 1 a[-3--1] x =. 0,2,100% 3253 3,$N,1,1,0 1,$N,1,1,1 y[-6--1] a[-6--1] y 3254 nm. _plot_polar_outline 3255 fi 3256 3257 # Generate 3D object for filling. 3258 if "$4>=0 && $5>=0 && $6>=0" 3259 ('CImg3d') +. 0.5 ({$N+1},$N) 3260 +z[coords] 0,-1,2,100% z. 0,2 3261 1,$N,1,1,3 1,$N 1,$N,1,1,'1+y' ++. 1 a[-4--1] x =. 1,3,100% 3262 3,$N,1,1,$4,$5,$6 1,$N,1,1,1 3263 y[-6--1] a[-6--1] y 3264 nm. _plot_polar_fill 3265 fi 3266 rm[coords] # Remove original curve coordinates. 3267 3268 # Render graph image. 3269 {$1-32},{$2-32},1,3,255 3270 L={0.1*max($1,$2)} grid. $L,$L,0,0,0.25,0xCCCCCCCC,0 # Draw background grid 3271 if "$4>=0 && $5>=0 && $6>=0" # Draw curve filling 3272 j3d. [_plot_polar_fill],50%,50%,0,1,2,1,0 3273 rm[_plot_polar_fill] 3274 fi 3275 if $3 3276 if $3>=0 # Draw curve outline 3277 j3d. [_plot_polar_outline],50%,50%,0,1,1,0,0 3278 fi 3279 if $3!=0 # Draw curve vertices 3280 if abs($3)>1 circles3d[_plot_polar_outline] {abs($3)} fi 3281 j3d. [_plot_polar_outline],50%,50%,0,0.2,2,0,0 3282 fi 3283 rm[_plot_polar_outline] 3284 fi 3285 3286 # Draw axes and frame. 3287 nM={$M/0.96} 3288 100%,100%,1,1,255 axes. {-$nM},$nM,$nM,{-$nM},14,1,0 3289 +erode. 3 !=. 255 r.. 100%,100%,1,3 j... ..,0,0,0,0,1,.,1 rm[-2,-1] 3290 frame. 1,1,128 frame. 15,15,220 3291 0 t. "$9",0,0,13,1,-220,-220,-220 j.. .,{({-2,w}-w)/2},{{-2,h}-16},0,0,-1 rm. 3292 0 t. "$10",0,0,13,1,-220,-220,-220 rotate. -90 j.. .,2,{({-2,h}-h)/2},0,0,-1 rm. 3293 3294 nm $nm endl done 3295 3296#@cli dq : eq. to 'display_quiver'. 3297dq : 3298 _gmic_s="$?" v + _display_quiver $* 3299 3300#@cli display_quiver : _size_factor>0,_arrow_size>=0,_color_mode={ 0=monochrome | 1=grayscale | 2=color } 3301#@cli : Render selected images of 2D vectors as a field of 2D arrows. 3302#@cli : (eq. to 'dq'). 3303#@cli : Default values: 'size_factor=16', 'arrow_size=1.5' and 'color_mode=1'. 3304#@cli : $ image.jpg +luminance gradient[-1] xy rv[-2,-1] *[-2] -1 a[-2,-1] c crop 60,10,90,30 +display_quiver[1] , 3305display_quiver : 3306 _gmic_s="$?" v + _$0 $* 3307 3308_display_quiver : check "${1=16}>0 && ${2=1.5}>=0 && isint(${3=2}) && $3>=0 && $3<=2" 3309 e[0--3] "Render field of 2D arrows from image"$_gmic_s", with size factor $1, arrow size $2 in "\ 3310 ${arg\ 1+$3,monochrome,grayscale,color}" mode." 3311 repeat $! l[$>] 3312 +norm. /.. {max(1e-6,iM)} rm. # Normalize vector values. 3313 {$1*w},{$1*h},1,{"1<<cut($3,0,2)"} 3314 eval.. " 3315 begin(ref(resize([255],s#1,1),C)); 3316 "${-math_lib}" 3317 len = norm2(I(x,y)); 3318 ang = atan2(i(x,y,0,1),i(x,y,0,0))*180/pi; 3319 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 ]; 3320 P*=$1*$2*len; 3321 X = resize([(x+0.5)*w#1/w,(y+0.5)*h#1/h],size(P),0,2); 3322 X+=mul(P,rot(-ang°),2); 3323 if ($3, 3324 v = min(1,max(0.5,3*len)); 3325 if ($3==1, 3326 C = [ 255*v,255 ], 3327 C = [ hsv2rgb([ ang,1,v ]), 255 ]; 3328 ); 3329 ); 3330 repeat (3,k, 3331 i0 = arg(k + 1,0,2,4); 3332 i1 = arg(k + 1,2,10,6); 3333 i2 = arg(k + 1,12,12,8); 3334 polygon(#1,3,X[i0,2],X[i1,2],X[i2,2],1,C); 3335 ); I" 3336 rm.. 3337 endl done 3338 3339#@cli drgba : eq. to 'display_rgba'. 3340drgba : skip "${1=none},${2=$1},${3=$1}" 3341 _gmic_s="$?" v + _display_rgba ${^0} v - 3342 if !${} noarg fi 3343 3344#@cli display_rgba : _background_RGB_color 3345#@cli : Render selected RGBA images over a checkerboard or colored background. 3346#@cli : (eq. to 'drgba'). 3347#@cli : Default values: 'background_RGB_color=undefined' (checkerboard). 3348#@cli : $ image.jpg +norm threshold[-1] 40% blur[-1] 3 normalize[-1] 0,255 append c display_rgba 3349display_rgba : skip "${1=none},${2=$1},${3=$1}" 3350 _gmic_s="$?" v + _$0 ${^0} v - 3351 if !${} noarg fi 3352 3353_display_rgba : skip "${1=},${2=$1},${3=$1}" 3354 l[] is_rgb={"isnum($1)"} onfail is_rgb=0 endl 3355 if $is_rgb e[0--4] "Render RGBA image"$_gmic_s" over RGB background ($*)." 3356 else e[0--4] "Render RGBA image"$_gmic_s" over a checkerboard background." 3357 fi 3358 repeat $! l[$>] if s==2" || "s==4 3359 if $is_rgb i[0] 100%,100%,1,3 fc[0] {[$*]} 3360 else i[0] (160,128;128,160) r[0] 16,16 r[0] [1],[1],1,{s-1},0,2 3361 fi 3362 nm[0] {1,n} 3363 sh. {s-1} j[0] [1],0,0,0,0,1,[2],255 k[0] 3364 fi endl done to_rgb u $is_rgb 3365 3366#@cli dt : eq. to 'display_tensors'. 3367dt : 3368 _gmic_s="$?" v + _display_tensors $* 3369 3370#@cli display_tensors : _size_factor>0,_ellipse_size>=0,_color_mode={ 0=monochrome | 1=grayscale | 2=color },_outline>=0 3371#@cli : Render selected images of tensors as a field of 2D ellipses. 3372#@cli : (eq. to 'dt'). 3373#@cli : Default values: 'size_factor=16', 'ellipse_size=1.5', 'color_mode=2' and 'outline=2'. 3374#@cli : $ image.jpg +diffusiontensors 0.1,0.9 resize2dx. 32 +display_tensors. 64,2 3375#@cli : $$ https://gmic.eu/oldtutorial/_display_tensors 3376display_tensors : 3377 _gmic_s="$?" v + _$0 $* 3378 3379_display_tensors : check "${1=16}>0 && ${2=1.5}>=0 && isint(${3=2}) && $3>=0 && $3<=2 && ${4=2}>=0" 3380 e[0--3] "Render field of 2x2 tensors from image"$_gmic_s", with size factor $1, ellipse size $2 in "\ 3381 ${arg\ 1+$3,monochrome,grayscale,color}" mode and outline $4." 3382 repeat $! l[$>] 3383 * {($2*$1/2)/max(abs(im),abs(iM))} # Normalize tensor values. 3384 {$1*w},{$1*h},1,{"1<<cut($3,0,2)"} 3385 f.. " 3386 begin(C = resize([255],s#1,1); Co = resize([0],s#1,1); Co[s#1 - 1] = $3?255:0); 3387 "${-math_lib}" 3388 X = ([ x,y ]+=0.5)*$1; 3389 T = [ R, G, G, B ]; 3390 E = eig(T); 3391 r1 = E[0]; 3392 r2 = E[1]; 3393 ang = atan2(E[3],E[2])*180/pi; 3394 if ($3, 3395 v = min(1,max(0.5,3*r1/($1*$2))); 3396 if ($3==1, 3397 C = [ 255*v,255 ], 3398 C = [ hsv2rgb([ 2*ang,1-r2/r1,v ]), 255 ]; 3399 ); 3400 ); 3401 for (k = 1, k>=0, --k, ellipse(#1,X,r1 + k*$4,r2 + k*$4,ang°,1,arg(k + 1,C,Co))); 3402 I" 3403 rm.. 3404 endl done 3405 3406#@cli dw : eq. to 'display_warp'. 3407dw : 3408 _gmic_s="$?" v + _display_warp $* 3409 3410#@cli display_warp : _cell_size>0 3411#@cli : Render selected 2D warping fields. 3412#@cli : (eq. to 'dw'). 3413#@cli : Default value: 'cell_size=15'. 3414#@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 3415display_warp : 3416 _gmic_s="$?" v + _$0 $* 3417 3418_display_warp : check "${1=15}>0" 3419 e[0--3] "Render 2D warping field"$_gmic_s", with cell size $1." 3420 repeat $! l[$>] 3421 if d!=1" || "s!=2 3422 error[0--3] "Command 'display_warp': Invalid image ["{$!-$>-1}"]: Dimensions "{w}","{h}","{d}","{s}" 3423 does not represent a 2D field of 2D vectors." 3424 fi 3425 i[0] 100%,100%,1,1,1 grid[0] $1,$1 nm[0] {1,n} 3426 warp[0] [1],1,1,0 rm[1] 3427 endl done * 255 3428 3429#@cli e : eq. to 'echo'. : (+) 3430 3431#@cli echo : message : (+) 3432#@cli : Output specified message on the error output. 3433#@cli : (eq. to 'e').\n 3434#@cli : Command selection (if any) stands for displayed call stack subset instead of image indices. 3435 3436#@cli echo_file : filename,message 3437#@cli : Output specified message, appending it to specified output file. 3438#@cli : (similar to 'echo' for specified output file stream). 3439echo_file : skip "${2='\n'}" 3440 ('"${2--1}\n"') ot. $1 rm. 3441 3442#@cli echo_stdout : message 3443#@cli : Output specified message, on the standard output (stdout). 3444#@cli : (similar to 'echo' for output on standard output instead of standard error). 3445echo_stdout : 3446 ('"$*"\n') o. -.raw,uchar rm. 3447 3448#@cli function1d : 0<=smoothness<=1,x0>=0,y0,x1>=0,y1,...,xn>=0,yn 3449#@cli : Insert continuous 1D function from specified list of keypoints (xk,yk) 3450#@cli : in range [0,max(xk)] (xk are positive integers). 3451#@cli : Default values: 'smoothness=1' and 'x0=y0=0'. 3452#@cli : $ function1d 1,0,0,10,30,40,20,70,30,80,0 +display_graph 400,300 3453function1d : check "${1=1}>=0 && $1<=1" skip ${2=0},${3=0} 3454 e[^-1] "Input continuous 1D function, with smoothness $1 and keypoints (${2--1})." 3455 l[] 3456 3457 # Sort and normalize input keypoints. 3458 smoothness={max(0,min(1,$1))} 3459 (${2--1}) r 2,{int(w/2)},1,1,-1 3460 sort +,y s x size={0,if(iM>=0,1+int(iM),0)} 3461 if !$size rm 0 break fi 3462 a x 3463 3464 # Compute slopes for splines. 3465 +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 3466 3467 # Determine spline coefficients for each part of the curve. 3468 $size,1,1,1,-1 3469 repeat h#0-1 3470 x0={0,i(0,$>)} y0={0,i(1,$>)} x1={0,i(0,$>+1)} y1={0,i(1,$>+1)} 3471 slope={($y1-$y0)/max(0.01,$x1-$x0)} 3472 yp0={0,i(2,$>)*$smoothness+(1-$smoothness)*$slope} 3473 yp1={0,i(2,$>+1)*$smoothness+(1-$smoothness)*$slope} 3474 i={round($x0,1,1)} j={round($x1,1,0)} 3475 line[1] $i,0,$j,0,1,$> 3476 if $j-$i<=1 # Linear interpolation for very close points. 3477 ({$y0-$x0*$slope}^{$slope}^0^0) 3478 else # Cubic interpolation otherwise. 3479 (1,$x0,{($x0)^2},{($x0)^3};\ 3480 1,$x1,{($x1)^2},{($x1)^3};\ 3481 0,1,{2*$x0},{3*($x0)^2};\ 3482 0,1,{2*$x1},{3*($x1)^2}) 3483 ($y0;$y1;$yp0;$yp1) 3484 invert.. mmul[-2,-1] y. c 3485 fi 3486 done 3487 a[2--1] x map.. . rm. 3488 3489 # Render final curve. 3490 100%,1,1,1,1 3491 (0,{w-1}) r. {-2,w},1,1,1,3 round. 3492 +sqr. +*[-2,-1] a[-4--1] c *[-2,-1] s. c +[-4--1] rm.. 3493 endl 3494 3495#@cli i : eq. to 'input'. : (+) 3496 3497#@cli input : \ 3498# [type:]filename : \ 3499# [type:]http://URL : \ 3500# [selection]x_nb_copies>0 : \ 3501# { width>0[%] | [image_w] },{ _height>0[%] | [image_h] },{ _depth>0[%] | [image_d] },{ _spectrum>0[%] \ 3502# | [image_s] },_{ value1,_value2,... | 'formula' } : \ 3503# (value1{,|;|/|^}value2{,|;|/|^}...[:{x|y|z|c|,|;|/|^}]) : \ 3504# 0 : (+) 3505#@cli : Insert a new image taken from a filename or from a copy of an existing image [index], 3506#@cli : or insert new image with specified dimensions and values. Single quotes may be omitted in 3507#@cli : 'formula'. Specifying argument '0' inserts an 'empty' image. 3508#@cli : (eq. to 'i' | (no arg)). 3509#@cli : Default values: 'nb_copies=1', 'height=depth=spectrum=1' and 'value1=0'. 3510#@cli : $ input image.jpg 3511#@cli : $ input (1,2,3;4,5,6;7,8,9^9,8,7;6,5,4;3,2,1) 3512#@cli : $ image.jpg (1,2,3;4,5,6;7,8,9) (255^128^64) 400,400,1,3,'if(x>w/2,x,y)*c' 3513#@cli : $$ 3514 3515#@cli input_565 : filename,width>0,height>0,reverse_endianness={ 0 | 1 } 3516#@cli : Insert image data from a raw RGB-565 file, at the end of the list. 3517#@cli : Default value: 'reverse_endianness=0'. 3518input_565 : check "isint($2) && $2>0 && isint($3) && $3>0 && isbool(${4=0})" 3519 e[^-1] "Input raw RGB-565 file '$1', with size $2x$3." 3520 l[] raw:"$1",ushort if $4 endian ushort fi 3521 r $2,$3,1,1,-1 +>> 5 &. 63 +&.. 31 >>... 11 *[-3,-1] 8 *.. 4 a c endl 3522 3523#@cli input_cube : "filename",_convert_1d_cluts_to_3d={ 0 | 1 }. 3524#@cli : Insert CLUT data from a .cube filename (Adobe CLUT file format). 3525#@cli : Default value: 'convert_1d_cluts_to_3d=1'. 3526input_cube : skip ${2=1} 3527 e[^-1] "Input CLUT from file '$1'" 3528 l[] 3529 it[] "$1" f "i<_' ' && i!=10?_' ':i" s -,10 3530 i[0] 0 3531 range={" 3532 ref(vector128(),line); 3533 dmin = [ 0,0,0 ]; 3534 dmax = [ 1,1,1 ]; 3535 dim = size = 0; 3536 target = 0; 3537 for (k = 1, k<l, ++k, 3538 linesiz = min(size(line)-1,h#k); 3539 copy(line[0],i[#k,0],linesiz); 3540 copy(line[linesiz],0,size(line) - linesiz,1,0); 3541 same(line,'LUT_1D_SIZE ',12)?( 3542 copy(line[0],line[12],size(line) - 12); 3543 size = stov(line); 3544 dim = 1; 3545 resize(#0,3,size,1,1,0); 3546 ):same(line,'LUT_3D_SIZE ',12)?( 3547 copy(line[0],line[12],size(line) - 12); 3548 size = stov(line); 3549 dim = 3; 3550 resize(#0,3,size,size,size,0); 3551 ):same(line,'DOMAIN_MIN ',11)?( 3552 copy(line[0],line[11],size(line) - 11); 3553 dmin[0] = stov(line); 3554 ind = find(line,_' '); 3555 copy(line[0],line[ind + 1],size(line) - ind); 3556 dmin[1] = stov(line); 3557 ind = find(line,_' '); 3558 copy(line[0],line[ind + 1],size(line) - ind); 3559 dmin[2] = stov(line); 3560 ):same(line,'DOMAIN_MAX ',11)?( 3561 copy(line[0],line[11],size(line) - 11); 3562 dmax[0] = stov(line); 3563 ind = find(line,_' '); 3564 copy(line[0],line[ind + 1],size(line) - ind); 3565 dmax[1] = stov(line); 3566 ind = find(line,_' '); 3567 copy(line[0],line[ind + 1],size(line) - ind); 3568 dmax[2] = stov(line); 3569 ):( 3570 val = stov(line); 3571 !isnan(val)?do ( 3572 i[#0,target++] = val; 3573 ind = find(line,_' '); 3574 ind<0?break(); 3575 copy(line[0],line[ind + 1],size(line) - ind); 3576 val = stov(line); 3577 ,_(while); !isnan(val)); 3578 ); 3579 ); 3580 [dmin,dmax];"} 3581 3582 k[0] 3583 permute yzcx 3584 if [$range]!=[0,0,0,1,1,1] 3585 f "begin( 3586 range = ["$range"]; 3587 dmin = range[0,3]; 3588 dmax = range[3,3]; 3589 delta = dmax - dmin; 3590 ); 3591 (I - dmin)*255/delta" 3592 else * 255 3593 fi 3594 if "w>1 && h==1 && d==1 && $2" size={w} s c y.. y. z r $size,$size,$size a c fi 3595 nm "$1" 3596 endl 3597 3598#@cli input_flo : "filename" 3599#@cli : Insert optical flow data from a .flo filename (vision.middlebury.edu file format). 3600input_flo : 3601 e[^-1] "Input optical flow from file '$1'" 3602 l[] 3603 i raw:"$1",float 3604 if i!=202021.25 endian. fi 3605 if i!=202021.25 error[0--3] "Command 'input_flo': Filename '$1' is not a valid .flo file." return fi 3606 +rows 1,2 cast. float,uint w,h={^} rm. 3607 rows 3,100% r 2,$w,$h,1,-1 permute yzcx 3608 endl 3609 3610#@cli ig : eq. to 'input_glob'. 3611ig : 3612 v + _input_glob "$*" 3613 3614#@cli input_glob : pattern 3615#@cli : Insert new images from several filenames that match the specified glob pattern. 3616#@cli : (eq. to 'ig'). 3617input_glob : 3618 _input_glob "$*" 3619 3620_input_glob : 3621 e[0--3] "Input all files that match glob pattern '$*'." 3622 files 3,"$*" 3623 N=$! 3624 m "_ig : $""=arg repeat $""# i ${arg{1+$>}} done" 3625 _ig ${} um _ig 3626 if $N==$! error[0--3] "Command 'input_glob': No matching filenames for pattern '$*'." fi 3627 3628#@cli input_gpl : filename 3629#@cli : Input specified filename as a .gpl palette data file. 3630input_gpl : 3631 e[^-1] "Input .gpl palette file '$*'." 3632 l[] 3633 it[] "$*" discard 13 replace 9,32 s -,10 3634 colors=0 3635 repeat $! l[$>] 3636 s -,32 3637 if $!>=3" && "isint({0,t})" && "isint({1,t})" && "isint({2,t}) colors=$colors;{0,t},{1,t},{2,t} fi 3638 rm 0 3639 onfail rm 0 endl done 3640 rm ($colors) rows 1,100% nm "$1" permute yzcx 3641 endl 3642 3643#@cli it : eq. to 'input_text'. 3644it : 3645 v + _input_text "$*" 3646 3647#@cli input_text : filename 3648#@cli : Input specified text-data filename as a new image. 3649#@cli : (eq. to 'it'). 3650input_text : 3651 v + _$0 "$*" 3652 3653_input_text : 3654 e[0--3] "Input text-data file '$*'." 3655 i raw:"$*",uchar 3656 if i[0]==239" && "i[1]==187" && "i[2]==191 rows. 3,100% fi # Remove BOM 3657 discard. {'\r'} # Remove CR 3658 3659# Merge multi-lines (lines continued by backslash before NL) in a string image. 3660merge_multiline : 3661 eval[^] "*i==_'\\' && j[-1]!=_'\\' && j[+1]==_'\n'?( 3662 for (p = 2, j[p] && j[p]<=_' ' && j[p]!=_'\n', ++p); copy(i(),-1,p,1,0))" 3663 discard -1 3664 3665# Merge multi-line comments in a string image. 3666merge_multiline_comments : 3667 eval[^] "*i==_'\\' && j[-1]!=_'\\' && j[+1]==_'\n' && j[+2]==_'#'?( 3668 for (p = 3, j[p] && j[p]<=_' ' && j[p]!=_'\n', ++p); copy(i(),-1,p,1,0))" 3669 discard -1 3670 3671#@cli network : mode={ -1=disabled | 0=enabled w/o timeout | >0=enabled w/ specified timeout in seconds } : (+) 3672#@cli : Enable/disable load-from-network and set corresponding timeout. 3673#@cli : (Default mode is 'enabled w/o timeout'). 3674 3675#@cli o : eq. to 'output'. : (+) 3676 3677#@cli output : [type:]filename,_format_options : (+) 3678#@cli : Output selected images as one or several numbered file(s). 3679#@cli : (eq. to 'o'). 3680#@cli : Default value: 'format_options'=(undefined). 3681 3682#@cli output_565 : "filename",reverse_endianness={ 0=false | 1=true } 3683#@cli : Output selected images as raw RGB-565 files. 3684#@cli : Default value: 'reverse_endianness=0'. 3685output_565 : check "isbool(${2=0})" 3686 e[^-1] "Output image$? as raw RGB-565 file '$1'." 3687 N=$! repeat $N +l[$>] 3688 s c c 0,255 /[-3,-1] 8 /.. 4 round 3689 bsl... 11 bsl.. 5 + 3690 if $N>1 fn=${"filename \"$1\",$>"} else fn="$1" fi 3691 if $2 endian ushort fi 3692 o raw:$fn,ushort rm 3693 endl done is_change 0 3694 3695#@cli output_cube : "filename" 3696#@cli : Output selected CLUTs as a .cube file (Adobe CLUT format). 3697output_cube : 3698 e[^-1] "Output CLUT$? as file '$1'." 3699 N=$! repeat $N +l[$>] to_rgb 3700 l={round((w*h*d)^(1/3))} 3701 if w*h*d!=$l^3 error "Command '$0': CLUT '"{n}"' has invalid dimensions "({w},{h},{d},{s}). fi 3702 r $l,$l,$l,3,-1 permute cxyz / 255 3703 if $N>1 fn=${"filename \"$1\",$>"} else fn="$1" fi 3704 o dlm:$fn rm it[] $fn replace {','},32 3705 0 nm. $fn basename={b} rm. 3706 header="\# Created by: G'MIC (https://gmic.eu)\n"\ 3707 "TITLE \""$basename"\"\n\n"\ 3708 "# LUT size\n"\ 3709 "LUT_3D_SIZE "$l"\n\n"\ 3710 "# Data domain\n"\ 3711 "DOMAIN_MIN 0.0 0.0 0.0\n"\ 3712 "DOMAIN_MAX 1.0 1.0 1.0\n\n"\ 3713 "# LUT data points\n" 3714 i[0] ('$header') 3715 y a y ot $fn rm 3716 endl done is_change 0 3717 3718#@cli output_flo : "filename" 3719#@cli : Output selected optical flow as a .flo file (vision.middlebury.edu file format). 3720output_flo : 3721 e[^-1] "Output optical flow$? as file '$1'." 3722 N=$! repeat $N +l[$>] 3723 w,h={[w,h]} 3724 channels 0,1 permute cxyz i[0] (202021.25) i[1] ($w,$h) cast[1] uint,float y a y 3725 if $N>1 fn=${"filename \"$1\",$>"} else fn="$1" fi 3726 o raw:$fn,float rm 3727 endl done is_change 0 3728 3729#@cli output_ggr : filename,_gradient_name 3730#@cli : Output selected images as .ggr gradient files (GIMP). 3731#@cli : If no gradient name is specified, it is deduced from the filename. 3732output_ggr : skip "${2=}" 3733 e[^-1] "Output image$? as .ggr gradient file '$1'." 3734 N=$! 3735 repeat $N +l[$>] r 1,{w*h*d},1,100%,-1 to_rgba / 255 3736 if narg("$2") name="$2" 3737 else l[] 1 nm. "$1" ('{b}') f "if(x==0 && i>=_'a' && i<=_'z',i-_'a'+_'A',i)" name={t} rm endl 3738 fi 3739 ('"GIMP Gradient\nName: "$name\n{0,h}\n') 3740 repeat h#0 3741 start={_$>/{0,h}} 3742 end={_($>+1)/{0,h}} 3743 mid={_0.5*($start+$end)} 3744 rgba={0,I(0,$>)} 3745 r={arg(1,$rgba)} g={arg(2,$rgba)} b={arg(3,$rgba)} a={arg(4,$rgba)} 3746 ('$start" "$mid" "$end" "$r" "$g" "$b" "$a" "$r" "$g" "$b" "$a" 0 0\n"') 3747 done 3748 rm[0] a x 3749 if $N>1 ot ${"filename \"$1\",$>"} else ot "$1" fi 3750 rm 3751 endl done is_change 0 3752 3753#@cli output_gmz : filename,_datatype 3754#@cli : Output selected images as .gmz files (G'MIC native file format). 3755#@cli : 'datatype' can be { bool | uchar | char | ushort | short | uint | int | uint64 | int64 | float | double }. 3756output_gmz : skip ${2=auto} 3757 e[^-1] "Output image$? as gmz file '$1', with pixel type '$2'." 3758 1,64 3759 eval " 3760 draw([_'G',_'M',_'Z'],0,0,0,0,1,3); 3761 pos = 4; 3762 repeat (l - 1,k, 3763 ref(name(#k,1026),nam); 3764 len = find(nam,0); 3765 len>=0?( 3766 pos + len>=h?resize(#-1,1,2*h + len,1,1,0); 3767 len>0?draw(nam,0,pos,0,0,1,len); 3768 pos+=1 + len; 3769 ); 3770 ); 3771 resize(#-1,1,pos,1,1,0)" 3772 o cimgz:$1,$2 3773 rm. 3774 3775#@cli output_obj : filename,_save_materials={ 0=no | 1=yes } 3776#@cli : Output selected 3D objects as Wavefront 3D object files. 3777#@cli : Set 'save_materials' to '1' to produce a corresponding material file (`.mtl`) and eventually texture files. 3778#@cli : Beware, the export to `.obj` files may be quite slow for large 3D objects. 3779#@cli : Default value: 'save_materials=1'. 3780output_obj : check "isbool(${2=1})" check3d 0 3781 s0,s1=out, 3782 e[^-1] "Output 3D object$? as Wavefront 3D object file '$1' (with"${s$2}" materials)." 3783 N=$! repeat $N nm={$>,n} +l[$>] 3784 nb_materials,nb_primitives,nb_textures,nb_tcoords=0 3785 3786 # Generate basename, file header and eval macros. 3787 if $N>1 filename=${"filename \"$1\",$>"} else filename="$1" fi 3788 0 nm. $filename basename={b} folder={f} ext={x} if narg($ext) ext=.$ext fi rm. 3789 fnobj="begin(out = 0); 3790 tos(x) = vtos(x,6); 3791 write(ind,s) = ( 3792 l_s = find(s,0); 3793 l_s<=0?(l_s = size(s)); 3794 out + l_s>h(#ind)?resize(#ind,1,2*h(#ind) + l_s,1,1,0); 3795 copy(i[#ind,out],s,l_s); 3796 out+=l_s)" 3797 3798 # Decompose into vertices, primitives and colors. 3799 s3d 0 nb_vertices,nbp={1,f2ui([i[0],i[1]])} rm[0,1,5] 3800 e[] " > File '"$folder$basename$ext"' ("$nb_vertices" vertices, "$nbp" primitives)." 3801 3802 # Generate vertex output. 3803 l[0] 3804 e[] " - Export vertices." 3805 r 3,{h/3},1,1,-1 permute zycx 3806 0 nm. out_obj 3807 eval.. ">"$fnobj"; 3808 !(y%10000)?run('e[] \"\r - Export vertices: ',round(100*y/h),' % \"'); 3809 ref(string('v ',tos(i0),' ',tos(i1),' ',tos(i2),'\n'),str); 3810 write(#"$out_obj",str); I; 3811 end(resize(#"$out_obj",1,out,1,1,0))" 3812 rm[0] i[0] ('"\n# Vertices.\n"':y) a y nm out_obj 3813 e[] "\r - Export vertices: Done." 3814 endl 3815 3816 # Generate material output. 3817 if $2 l. 3818 e[] " - Export materials." 3819 256,256,256 nm. materials_rgb 3820 1,$nbp,1,3 nm. materials 3821 0 nm. out_mtl 3822 mv[0] $! 3823 eval $fnobj"; 3824 const nbp = "$nbp"; 3825 off = nb_materials = nb_textures = 0; 3826 repeat (nbp,p, 3827 !(p%10000)?run('e[] \"\r - Export materials: ',round(100*p/nbp),' % \"'); 3828 3829 i[off]!=-128?( # RGB color 3830 ref(cut(round(crop(0,off,1,3)),0,255),rgb); 3831 m = i(#"$materials_rgb",rgb); 3832 !m?( 3833 ++nb_materials; 3834 ref(string('newmtl m',nb_materials,'\n', 3835 'Kd ',tos(rgb[0]/255),' ',tos(rgb[1]/255),' ',tos(rgb[2]/255),'\n'),str); 3836 write(#"$out_mtl",str); 3837 m = i(#"$materials_rgb",rgb) = nb_materials; 3838 ); 3839 i[#"$materials",p] = m; 3840 off+=3; 3841 3842 ):i[off + 2]?( # Non-shared texture 3843 ++nb_materials; ++nb_textures; 3844 wt = i[off + 1]; ht = i[off + 2]; st = i[off + 3]; 3845 run('+rows. ',off + 4,',',off + 3 + wt*ht*st,' r. ',wt,',',ht,',1,',st,',-1 tfn=$folder${basename}_t', 3846 nb_textures,'.png o. $tfn rm.'); 3847 tfile = get('tfn',1024,1); 3848 ref(string('newmtl m',nb_materials,'\n', 3849 'map_Kd ',get('tfn',1024,1),'\n'),str); 3850 write(#"$out_mtl",str); 3851 I[#"$materials",p] = [ nb_materials,wt,ht ]; 3852 off+=4 + wt*ht*st; 3853 3854 ):( # Shared texture 3855 tind = i[off + 1]; 3856 I[#"$materials",p] = I[#"$materials",tind]; 3857 off+=4; 3858 3859 ); 3860 ); 3861 resize(#"$out_mtl",1,out,1,1,0); 3862 run('nb_materials,nb_textures=',nb_materials,',',nb_textures)" 3863 e[] "\r - Export materials: Done." 3864 k[materials,out_mtl] 3865 endl fi 3866 3867 # Generate primitive output. 3868 e[] " - Export primitives." 3869 0 nm. out_prim 3870 mv[1] $! 3871 eval $fnobj"; 3872 const materials = 0"$materials"; 3873 const nbp = "$nbp"; 3874 off = p_material = material = nb_primitives = nb_tcoords = 0; 3875 repeat (nbp,p, 3876 !(p%10000)?run('e[] \"\r - Export primitives: ',round(100*p/nbp),' % \"'); 3877 3878 type = i[off]; 3879 $2?material = i[#materials,p]; 3880 material!=p_material?ref(string('usemtl m',material,'\n'),str_mtl); 3881 3882 type==1?( # Colored point 3883 ref(string('p ',f2ui(i[off + 1] + 1),'\n'),str); 3884 write(#"$out_prim",str); 3885 ++nb_primitives; 3886 3887 ):type==2?( # Colored or textured segment 3888 ref(string('l ',f2ui(i[off + 1]) + 1,' ',f2ui(i[off + 2]) + 1,'\n'),str); 3889 write(#"$out_prim",str); 3890 ++nb_primitives; 3891 3892 ):type==3 || (type==9 && !$2)?( # Colored triangle 3893 $2 && material!=p_material?write(#"$out_prim",str_mtl); 3894 ref(string('f ',f2ui(i[off + 1]) + 1,' ',f2ui(i[off + 2]) + 1,' ',f2ui(i[off + 3]) + 1,'\n'),str); 3895 write(#"$out_prim",str); 3896 ++nb_primitives; 3897 3898 ):type==4 || (type==12 && !$2)?( # Colored quadrangle 3899 $2 && material!=p_material?write(#"$out_prim",str_mtl); 3900 ref(string('f ',f2ui(i[off + 1]) + 1,' ',f2ui(i[off + 2]) + 1,' ', 3901 f2ui(i[off + 3]) + 1,' ',f2ui(i[off + 4]) + 1,'\n'),str); 3902 write(#"$out_prim",str); 3903 ++nb_primitives; 3904 3905 ):type==9?( # Textured triangle 3906 material!=p_material?write(#"$out_prim",str_mtl); 3907 wt = i(#materials,0,p,0,1); ht = i(#materials,0,p,0,2); 3908 ref(string('vt ',tos(i[off + 4]/wt),' ',tos(1 - i[off + 5]/ht),'\n', 3909 'vt ',tos(i[off + 6]/wt),' ',tos(1 - i[off + 7]/ht),'\n', 3910 'vt ',tos(i[off + 8]/wt),' ',tos(1 - i[off + 9]/ht),'\n', 3911 'f ',f2ui(i[off + 1]) + 1,'/',nb_tcoords + 1,' ',f2ui(i[off + 2]) + 1,'/',nb_tcoords + 2, 3912 ' ',f2ui(i[off + 3]) + 1,'/',nb_tcoords + 3,'\n'),str); 3913 write(#"$out_prim",str); 3914 nb_tcoords+=3; 3915 ++nb_primitives; 3916 3917 ):type==12?( # Textured quadrangle 3918 material!=p_material?write(#"$out_prim",str_mtl); 3919 wt = i(#materials,0,p,0,1); ht = i(#materials,0,p,0,2); 3920 ref(string('vt ',tos(i[off + 5]/wt),' ',tos(1 - i[off + 6]/ht),'\n', 3921 'vt ',tos(i[off + 7]/wt),' ',tos(1 - i[off + 8]/ht),'\n', 3922 'vt ',tos(i[off + 9]/wt),' ',tos(1 - i[off + 10]/ht),'\n', 3923 'vt ',tos(i[off + 11]/wt),' ',tos(1 - i[off + 12]/ht),'\n', 3924 'f ',f2ui(i[off + 1]) + 1,'/',nb_tcoords + 1,' ',f2ui(i[off + 2]) + 1,'/',nb_tcoords + 2, 3925 ' ',f2ui(i[off + 3]) + 1,'/',nb_tcoords + 3,' ',f2ui(i[off + 4]) + 1,'/',nb_tcoords + 4,'\n'),str); 3926 write(#"$out_prim",str); 3927 nb_tcoords+=4; 3928 ++nb_primitives; 3929 3930 ):( # Unsupported primitive 3931 run(['warn[] \"Command 'output_obj': Cannot convert primitive \#'],p,'/',nbp - 1, 3932 ' (size ',type,'). Ignoring it.\"'); 3933 ); 3934 3935 off+=type + 1; 3936 p_material = material; 3937 ); 3938 resize(#"$out_prim",1,out,1,1,0); 3939 run('nb_primitives=',nb_primitives)" 3940 e[] "\r - Export primitives: Done." 3941 l[out_obj,out_prim] i[1] ('"\n# Primitives.\n"':y) a y endl 3942 if $2 k[out_mtl,out_obj] else k[out_obj] fi 3943 3944 # Generate file header. 3945 header="# Object name: "$nm\n\ 3946 "# Vertices: "$nb_vertices\n\ 3947 "# Primitives: "$nb_primitives\n\ 3948 "# Materials: "$nb_materials\n\ 3949 "# Textures: "$nb_textures\n\ 3950 {`"d2(x) = (s = date(x); s>9?vtos(s,-1,2):[0,s]+_'0'); 3951 string('# Generated on ',d2(0),'/',d2(1),'/',d2(2),' at ',d2(4),':',d2(5),':',d2(6), 3952 ' by G\47MIC (https://gmic.eu).\n')"`} 3953 3954 # Save object geometry (.obj file). 3955 l[out_obj] 3956 i[0] ('"# File: "$folder$basename$ext\n$header':y) 3957 if $2 i[1] ('"\n# Materials.\n\ 3958 mtllib "$folder$basename$ext".mtl\n"':y) fi 3959 a y 3960 o raw:$folder$basename$ext,uchar 3961 endl 3962 3963 # Save object materials (.mtl file). 3964 if $2 l[out_mtl] 3965 i[0] ('"# File: "$folder$basename$ext.mtl\n$header\n':y) 3966 a y 3967 o raw:$folder$basename$ext.mtl,uchar 3968 endl fi 3969 3970 rm 3971 endl done is_change 0 3972 3973#@cli ot : eq. to 'output_text'. 3974ot : 3975 _gmic_s="$?" v + _output_text "$*" 3976 3977#@cli output_text : filename 3978#@cli : Output selected images as text-data filenames. 3979#@cli : (eq. to 'ot'). 3980output_text : 3981 _gmic_s="$?" v + _$0 "$1" 3982 3983_output_text : 3984 e[0--3] "Output image"$_gmic_s" as text-data file '$1'." 3985 o raw:"$1",uchar 3986 3987#@cli on : eq. to 'outputn'. 3988on : 3989 _gmic_s="$?" v + _outputn $* 3990 3991#@cli outputn : filename,_index 3992#@cli : Output selected images as automatically numbered filenames in repeat...done loops. 3993#@cli : (eq. to 'on'). 3994outputn : 3995 _gmic_s="$?" v + _$0 $* 3996 3997_outputn : skip "${2=}" 3998 if $#==1 filename=${filename\ "$1",$>} 3999 else filename=${filename\ "$1",$2} 4000 fi 4001 e[0--3] "Output image"$_gmic_s" as file '"$filename"'." 4002 o $filename 4003 4004#@cli op : eq. to 'outputp'. 4005op : 4006 _gmic_s="$?" v + _outputp $* 4007 4008#@cli outputp : prefix 4009#@cli : Output selected images as prefixed versions of their original filenames. 4010#@cli : (eq. to 'op'). 4011#@cli : Default value: 'prefix=_'. 4012outputp : 4013 _gmic_s="$?" v + _$0 $* 4014 4015_outputp : skip ${1="_"} 4016 if $!>1 e[0--4] "Output image"$_gmic_s" as their initial locations, prefixed by '$1'." 4017 else e[0--4] "Output image"$_gmic_s" as its initial location, prefixed by '$1'." 4018 fi 4019 repeat $! o[$>] {$>,f}$1{$>,b}.{$>,x} done 4020 4021#@cli ow : eq. to 'outputw'. 4022ow : 4023 _gmic_s="$?" v + _outputw 4024 4025#@cli outputw 4026#@cli : Output selected images by overwriting their original location. 4027#@cli : (eq. to 'ow'). 4028outputw : 4029 _gmic_s="$?" v + _$0 $* 4030 4031_outputw : 4032 if $!>1 e[0--4] "Output image"$_gmic_s" as their initial location." 4033 else e[0--4] "Output image"$_gmic_s" as its initial location." 4034 fi 4035 repeat $! o[$>] {$>,n} done 4036 4037#@cli ox : eq. to 'outputx'. 4038ox : 4039 _gmic_s="$?" v + _outputx $* 4040 4041#@cli outputx : extension1,_extension2,_...,_extensionN,_output_at_same_location={ 0 | 1 } 4042#@cli : Output selected images with same base filenames but for N different extensions. 4043#@cli : (eq. to 'ox'). 4044#@cli : Default value: 'output_at_same_location=0'. 4045outputx : 4046 _gmic_s="$?" v + _$0 $* 4047 4048_outputx : 4049 $=arg 4050 is_last_arg=0 is_same_location=0 4051 if isnum($-1) is_last_arg={isint($-1)" && "$-1>=0" && "$-1<=1} is_same_location=$-1 fi 4052 N={$#-$is_last_arg} s0= s1=s 4053 if !$N e[0--3] "Output image"$_gmic_s" at same location, with same base filename but extension '' 4054 (skipped, no extension provided)." return 4055 fi 4056 if $is_same_location 4057 if $is_last_arg 4058 e[0--4] "Output image"$_gmic_s" at same location, with same base filename but extension"${s{$N>1}}"' ${^-1}'." 4059 else 4060 e[0--4] "Output image"$_gmic_s" at same location, with same base filename but extension"${s{$N>1}}" '$*'." 4061 fi 4062 repeat $! l[$>] 4063 repeat $N ext=${arg{1+$>}} if ext=lowercase(['$ext']);ext=='jpg'||ext=='jpeg' ext.=,85 fi o {0,f}{0,b}.$ext done 4064 endl done 4065 else 4066 if $is_last_arg e[0--4] "Output image"$_gmic_s" with same base filename but extension"${s{$N>1}}"' ${^-1}'." 4067 else e[0--4] "Output image"$_gmic_s" with same base filename but extension"${s{$N>1}}" '$*'." 4068 fi 4069 repeat $! l[$>] 4070 repeat $N ext=${arg{1+$>}} if ext=lowercase(['$ext']);ext=='jpg'||ext=='jpeg' ext.=,85 fi o {0,b}.$ext done 4071 endl done 4072 fi 4073 4074#@cli parse_cli : _output_mode,_{ * | command_name } 4075#@cli : Parse definition of '#@cli'-documented commands and output info about them in specified output mode. 4076#@cli : 'output_mode' can be { ascii | bashcompletion | html | images | print }. 4077#@cli : Default values: 'output_mode=print' and 'command_name=*'. 4078parse_cli : skip "${1=print},${2=*}" 4079 e[^-1] "Parse '#@cli' command(s) '$2' and output in '$1' mode." 4080 4081 # Check that specified output mode is actually implemented. 4082 l[] ({'$$parse_cli_$1'}) rm 4083 onfail error[0--2] "Command 'parse_cli': Invalid output mode '$1'." 4084 endl 4085 4086 if !$! l[] it ${_path_rc}update$_version.gmic onfail endl fi 4087 if !$! return fi 4088 i[0] ('\n') y a y 4089 merge_multiline_comments 4090 4091 # Split commands/section into different blocs. 4092 eval " 4093 for (p = 0, p<h, 4094 4095 # Find next occurrence of line starting with '#@cli'. 4096 q = find(#0,'\n#@cli',p); 4097 q<0?(copy(i[p],0,h - p,1,0); break()); 4098 for (r = q + 6, r<h && (c=i[r])<=_' ' && c!=_'\n', ++r); 4099 r>=h || i[r]=='\n'?(copy(i[p],0,r - p,1,0); p = r; continue()); 4100 4101 (i[r]==_':' && i[r + 1]==_':')?( # Category 4102 r = find(#0,_'\n',r)%h; 4103 4104 ):i[r]!=_':'?do( # Command 4105 r = find(#0,_'\n',r)%h; 4106 crop(0,r,1,6)=='\n#@cli'?( 4107 for (s = r + 6, s<h && (c=i[s])<=_' ' && c!='_\n', ++s); 4108 s<h && i[s]==':' && i[s + 1]!=':'?(r = s):break(); 4109 ):break(),1 4110 4111 ):( # Unexpected '#@cli' line -> Display warning 4112 r = find(#0,_'\n',r)%h; 4113 ref(vector1024(),line); 4114 copy(line,i[q + 1],min(size(line),r - q - 1)); 4115 run('warn[0--3] \"Unexpected line: \'',line,'\'.\"'); 4116 copy(i[p],0,r - p,1,0); p = r; continue() 4117 ); 4118 copy(i[p],0,q - p + 1,1,0); # Set values to discard 4119 p = r)" 4120 s -,0 4121 4122 # Keep only command blocs and name them. 4123 if $! 4124 $!,1,1,1,"> 4125 begin( 4126 ref(vector1024(),command); 4127 ref(vector1024(),category); 4128 ); 4129 for (p = 5, p<h#x && (c=i[#x,p])<=_' ' && c!=_'\n', ++p); 4130 p>=h#x || i[#x,p]==_'\n'?(run('nm[',x,'] __to_discard__'); break()); 4131 4132 i[#x,p]==_':' && i[#x,p + 1]==_':'?( # Category 4133 for (p+=2, i[#x,p]<=_' ', ++p); 4134 for (q = h#x - 1, i[#x,q]<=_' ', --q); 4135 copy(category,i[#x,p],l = min(q - p + 1,size(category) - 1)); 4136 category[l] = 0; 4137 run('nm[',x,'] __to_discard__'); 4138 ):( # Command 4139 for (q = p, q<h#x && (c=i[#x,q])!=_':' && c>_' ', ++q); 4140 copy(command,i[#x,p],l = min(q - p,size(command) - 1)); 4141 command[l] = 0; 4142 run('nm[',x,'] \"',string(command,'@',category),'\"'); 4143 )" 4144 rm. rmn __to_discard__ 4145 l parse_cli_trigger_$1 $2 onfail endl 4146 fi 4147 parse_cli_$1 4148 4149# Return 1 if last of the selected bloc describes a shortcut command, 0 otherwise. 4150parse_cli_is_eqto : 4151 nbl={"n = 1; for (p = 0, (q = find(#-1,_'\n',p))>=0, ++n, p = ++q); n"} 4152 u {$nbl"==1 && find(#-1,'eq. to \'')>=0"} 4153 4154# 4155# Implements 'bashcompletion' mode for command 'parse_cli'. 4156# 4157parse_cli_bashcompletion : 4158 v 0 use_vt100 4159 sort_list +,n 4160 +e[] "#"\n\ 4161"# Bash completion rules for 'gmic'."\n\ 4162"#"\n\ 4163"# This file has been generated automatically."\n\ 4164"# Do not edit!"\n\ 4165"#"\n\ 4166"# This file should be copied/renamed in '/usr/share/bash-completion/completions/gmic'."\n\ 4167"#"\n\n\ 4168"_gmic()"\n\ 4169"{"\n\ 4170" local cur prev opts coms"\n\ 4171" if type -t _init_completion >/dev/null; then"\n\ 4172" _init_completion -n = || return"\n\ 4173" else"\n\ 4174" COMPREPLY=()"\n\ 4175" cur=\"${COMP_WORDS[COMP_CWORD]}\""\n\ 4176" prev=\"${COMP_WORDS[COMP_CWORD-1]}\""\n\ 4177" fi" 4178 coms=" coms=\"" c= 4179 4180 # Extract list of available commands. 4181 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4182 ('{n}') l. s -,{'@'} name={0,t} rm endl nm $name 4183 coms.=$c$name c=" " 4184 endl done 4185 +e[] $coms"\""\n\ 4186" opts=$(echo \"$coms\" | sed \"s: \\([^ ]\\+\\): \\1 -\\1 \\+\\1:g\")"\n 4187 4188 # Duplicate list of arguments for command shortcuts. 4189 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi 4190 name={$>,n} 4191 if ${parse_cli_is_eqto[$>]} 4192 +l[$>] s -,{'"eq. to "'} k. s -,39 eqto={0,t} rm endl 4193 l[$>] pass[$eqto] 0 k. nm $name 4194 onfail 4195 warn[] "Warning: Ignoring shortcut '"$_vt100_c$name$_vt100_m$_vt100_b"', "\ 4196 "links to unknown command '"$_vt100_c$eqto$_vt100_m$_vt100_b"'." 4197 nm __to_discard__ 4198 endl 4199 fi 4200 done 4201 rmn __to_discard__ 4202 4203 # Extract list of arguments. 4204 +e[] " case \"${prev}\" in" 4205 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4206 name={n} 4207 if n=['$name'];"n[0]!=_'_' && find(n,'input') && find(n,'output') && "\ 4208 "n!='i' && n!='o' && n!='m' && n!='it' && n!='ot'" 4209 if s=['$name'];s=='help'||s=='h' 4210 +e[] " \""$name"\" | \"-"$name"\" | \"+"$name"\")" 4211 +e[] " COMPREPLY=( $(compgen -W \"$coms\" -- \"$cur\") ); return 0;;" 4212 else 4213 s -,{'\n'} k[0] discard {'#@cli'} max {'" "'} autocrop {'" "'} 4214 s -,{':'} autocrop {'" "'} rm[0] replace {'" "'},{'_'} 4215 n_args=0 args,c= repeat $! if ['{/{$>,t}}']!='(+)' args.=$c{$>,t} c=" " n_args+=1 fi done 4216 if $n_args==1 args="> "$args fi 4217 if ['$args']!=0 4218 +e[] " \""$name"\" | \"-"$name"\" | \"+"$name"\")" 4219 +e[] " COMPREPLY=( $(compgen -W \""{/{/$args}}"\") ); return 0;;" 4220 fi 4221 fi 4222 rm 0 4223 fi 4224 endl done 4225 4226 +e[] " esac"\n\n\ 4227" COMPREPLY=( $(compgen -W \"$opts\" -- \"$cur\") )"\n\ 4228" if type -t _filedir >/dev/null; then"\n\ 4229" _filedir"\n\ 4230" else"\n\ 4231" comptopt -o filenames 2>/dev/null"\n\ 4232" COMPREPLY=( $(compgen -f -- ${cur}) )"\n\ 4233" fi"\n\ 4234"}"\n\ 4235"complete -F _gmic -o filenames gmic" 4236 rm 4237 4238parse_cli_trigger_bashcompletion : 4239 parse_cli_trigger_print $* 4240 4241# 4242# Implements 'ascii' mode for command 'parse_cli'. 4243# 4244parse_cli_ascii : 4245 use_vt100 4246 if !narg($_shell_cols) _shell_cols={${-shell_cols}-5} fi 4247 category= n_category=0 4248 if !narg($_section) _section=1 fi 4249 4250 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4251 4252 # Detect and display new category. 4253 if !0$_no_categories 4254 ('{n}') l. s -,{'@'} if $!>1 cat={t} fi rm endl 4255 if ['$cat']!=['$category'] 4256 n_category+=1 4257 category=$cat 4258 ('$_section.$n_category." "') ('$category') +f.. {'" "'} +f.. {'-'} a[-4,-3] x a[-2,-1] x 4259 +e[] \n" "$_vt100_r$_vt100_b{-2,t}$_vt100_n 4260 +e[] " "$_vt100_r{t}$_vt100_n 4261 rm[-2,-1] 4262 fi 4263 fi 4264 4265 # Parse command declaration. 4266 s -,{'\n'} discard {'#@cli'} max {'" "'} autocrop {'" "'} 4267 +l[0] 4268 s -,{'": "'} autocrop {'" "'} 4269 name={0,t} rm[0] 4270 is_builtin=0 4271 if $! 4272 is_builtin={"find(#-1,'(+)')>=0"} 4273 if $is_builtin rm. fi 4274 fi 4275 +e[] "\n "$_vt100_m$_vt100_b$name${"s1,s0=\" (+)\", u $s"$is_builtin}:$_vt100_n 4276 repeat $! l[$>] 4277 if ${parse_cli_is_eqto.} 4278 s -,39 eqto={1,t} k[0] 4279 +e[] " "${_vt100_i}"Shortcut for command '"$_vt100_m$_vt100_b$eqto$_vt100_n"'." 4280 else 4281 eqto= 4282 l. _gmd2ascii_cut $_shell_cols,8 if $!>1 i[1--2] ('"\\\\\n "':y) a y fi endl 4283 str=" "{t}${"if "$<" u \" |\" else u \"\" fi"} 4284 +e[] ${_vt100_c}$str$_vt100_n 4285 fi 4286 endl done 4287 rm 4288 endl 4289 rm[0] 4290 4291 # Parse command description. 4292 n_example=0 nl="\n" 4293 repeat $! if {$>,i==_':'} l[$>] 4294 if "h==1 || (h==2 && i[-1,2]==_' ')" rm ('": "':y) fi # Empty description lines 4295 rows {1+(i[1]==_'" "')},100% 4296 if "find(#0,'(eq. to ')>=0" # Found 'Eq. to' description. 4297 +l s -,{'\47'} shortcut={1,t} rm onfail shortcut="(unknown)" rm endl 4298 +e[] $nl" ("${_vt100_i}"equivalent to shortcut command '"$_vt100_m$_vt100_b$shortcut$_vt100_n"')." nl="\n" 4299 elif "find(#0,'Default value:')>=0 || find(#0,'Default values:')>=0" # Found 'Default value(s):' description 4300 if !0$_no_default_values 4301 s +,{':'} 4302 if $!>2" && "h#1==1" && "i("#1")==_':' 4303 i[0] ('$_vt100_b':y) i[2] ('$_vt100_n':y) 4304 fi 4305 a y gmd2ascii $_shell_cols,5 4306 if $!>1 i[1--2] ('"\n "':y) a y fi autocrop {'\n'} 4307 +e[] "\n "{/{t}} nl= 4308 fi 4309 elif i==_'$'" && "i[1]!=_'$' # Found example description 4310 if !0$_no_examples 4311 rows 1,100% autocrop {'" "'} 4312 _gmd2ascii_cut {$_shell_cols-8},7 4313 if $!>1 i[1--2] ('"\\\\\n "':y) a y fi autocrop {'\n'} 4314 example={/{t}} 4315 n_example+=1 4316 if $n_example==1 example_str=${_vt100_b}"Example:"$_vt100_n"\n "[#$n_example] nl="\n" 4317 else example_str=" "[#$n_example] 4318 fi 4319 +e[] $nl" "$example_str" "$_vt100_c$example$_vt100_n nl= 4320 fi 4321 elif i==_'$'" && "i[1]==_'$' # Found link to tutorial page 4322 if !0$_no_tutorial_link 4323 if h==2 4324 url=https://gmic.eu/tutorial/$name 4325 else 4326 rows 2,100 autocrop {'" "'} url={t} 4327 fi 4328 +e[] "\n "${_vt100_b}"Tutorial: "$_vt100_n$_vt100_u$url$_vt100_n nl= 4329 fi 4330 else # Other kind of description line 4331 parse_cli_text_ascii. 4332 if w +e[] $nl{/{t}} nl= fi 4333 fi 4334 4335 endl fi done 4336 rm 0 4337 endl done rm u $eqto 4338 4339parse_cli_text_ascii : 4340 if !narg($_shell_cols) _shell_cols={${-shell_cols}-5} fi 4341 replace_str "\\n","\n" gmd2ascii $_shell_cols,0 4342 4343 # Ensure output text contains no more than two consecutive newlines. 4344 # Also add a 4-chars left margin on each line. 4345 if w 4346 s +,{'\n'} 4347 if {i==_'\n'} rm. fi # Remove last newline. 4348 eval "repeat (l,p, 4349 i(#p)==_'\n'?( 4350 h(#p)>2?resize(#p,1,1,1,1,0) 4351 ):( 4352 resize(#p,1,h#p + 4,1,1,0,0,0,1); 4353 copy(i[#p,0],_' ',4,1,0)) 4354 )" 4355 a y 4356 fi 4357 4358parse_cli_trigger_ascii : 4359 if "['$1']!='*'" 4360 1,$!,1,1," 4361 begin(ref([lowercase(['$1']),_'@'],str)); 4362 ref(lowercase(name(#y)),nm); 4363 !find(nm,str)?y:-1" 4364 discard. -1 if h k[{i}] else rm fi 4365 fi 4366 4367# 4368# Implements 'html' mode for command 'parse_cli'. 4369# 4370parse_cli_html : 4371 v 0 use_vt100 e[] "" 4372 4373 # Sort by categories. 4374# repeat $! ('{$>,n}') l. s +,{'@'} rv a y nm={t} endl rm. nm[$>] $nm done # Rename as 'category@name' 4375# sort_list +,n # Sort by categories 4376# repeat $! ('{$>,n}') l. s +,{'@'} rv a y nm={t} endl rm. nm[$>] $nm done # Rename as 'name@category' 4377 4378 # Generate html page 'List of Commands'. 4379 html="<!DOCTYPE html>"\n\ 4380"<html lang=\"en\">"\n\ 4381" <head>"\n\ 4382" <meta charset=\"utf-8\">"\n\ 4383" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 4384" <link rel=\"stylesheet\" href=\"../highslide/highslide.css\"/>"\n\ 4385" <link rel=\"stylesheet\" href=\"https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css\">"\n\n\ 4386" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 4387"- Reference Documentation</title>"\n\ 4388" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 4389" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 4390" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 4391" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 4392" </head>"\n\n\ 4393" <body>"\n\ 4394" <div id=\"include_header\"></div>"\n\n\ 4395" <div class=\"section_title\"><a href=\"index.html\"><p>Reference</p></a></div><div class=\"section_content\">"\n\n\ 4396" <a name=\"top\"></a>"\n\n\ 4397"<!-- begin_content -->"\n\n\ 4398"<!-- list_of_categories -->"\n 4399 4400 list_categories,c= 4401 category,p_category= n,is_tr,is_table,row=0 4402 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4403 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4404 if ['$category']!=['$p_category'] 4405 strvar $category category_id=${} 4406 if $is_tr 4407 if $n%5" && "$row>1 html.=" <td colspan=\""{5-$n%5}"\"></td>"\n fi 4408 html.=" </tr>"\n is_tr=0 4409 fi 4410 if $is_table html.=" </table><br/>"\n is_table=0 fi 4411 html.="\n <h1 class=\"ref_h1\"><a name=\""$category_id"\"></a>"$category":</h1>"\n\ 4412 " <table class=\"ref_table_category\">"\n 4413 4414 ('$category') replace_str. ",","," lcategory={t} rm. 4415 list_categories.=$c$lcategory c=, 4416 is_table=1 4417 n,row=0 4418 fi 4419 if !${parse_cli_is_eqto.} 4420 is_builtin={"find(#-1,'(+)')>=0"} 4421 if !($n%5) 4422 if $is_tr html.=" </tr>"\n fi 4423 html.=" <tr>"\n 4424 is_tr=1 row+=1 4425 fi 4426 if ['$name']=='index' url_name=_index.html else url_name=$name.html fi 4427 if $is_builtin 4428 html.=" <td><a href=\""$url_name"#top\"><span class=\"gmd_monospace\" >"$name"</span></a></td>"\n 4429 else 4430 html.=" <td><a href=\""$url_name"#top\">"$name"</a></td>"\n 4431 fi 4432 n+=1 4433 fi 4434 p_category=$category 4435 endl done 4436 if $is_tr 4437 if $n%5" && "$row>1 html.=" <td colspan=\""{5-$n%5}"\"></td>"\n fi 4438 html.=" </tr>"\n 4439 fi 4440 if $is_table html.=" </table>"\n fi 4441 4442 # Add 'Shortcuts' category. 4443 html.="\n <h1 class=\"ref_h1\"><a name=\"shortcuts\"></a>Command Shortcuts:</h1>"\n\ 4444 " <table class=\"ref_table_shortcuts\">"\n\ 4445 " <tr style=\"background-color: \#d8dcea;\"><td><b>Shortcut name</b></td><td>"\ 4446 "<b>Equivalent command name</b></td></tr>"\n 4447 4448 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4449 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4450 if ${parse_cli_is_eqto.} 4451 is_builtin={"find(#-1,'(+)')>=0"} 4452 +l s -,{'"eq. to \47"'} k. s -,{'\47'} k[0] autocrop {'" "'} eqto={t} rm endl 4453 ('$name') replace_str. ">",">" replace_str. "<","<" html_name={t} rm. 4454 html.=" <tr><td><a href=\""$eqto.html"#top\"><b>"$html_name"</b></a></td>" 4455 if $is_builtin 4456 html.="<td><a href=\""$eqto.html"#top\"><span class=\"gmd_monospace\">"$eqto"</span></a></td>" 4457 else 4458 html.="<td><a href=\""$eqto.html"#top\">"$eqto"</a></td>" 4459 fi 4460 html.="</tr>"\n 4461 n+=1 4462 fi 4463 endl done 4464 if $is_table html.=" </table>"\n fi 4465 4466 html.=\n\ 4467"<!-- end_content -->"\n\n\ 4468"<!-- ref_navigation_bottom -->"\n\ 4469" </div><div class=\"section_end\"></div>"\n\ 4470" <div id=\"include_footer\"></div>"\n\ 4471" </body>" 4472 ({'$html'}:y) 4473 4474 # Insert TOC for categories. 4475 toc_html=" <h1 class=\"ref_h1\">Categories:</h1><ul>"\n 4476 repeat narg({/$list_categories}) 4477 arg 1+$>,{/$list_categories} category=${} 4478 ('$category') replace_str. ",","," category={t} rm. 4479 strvar $category category_id=${} 4480 toc_html.=" <li><a href=\"#"$category_id"\">"$category"</a></li>"\n 4481 done 4482 toc_html.=" <li><a href=\"#shortcuts\">Command Shortcuts</a></li>"\n 4483 toc_html.=" </ul>" 4484 4485 replace_str. "<!-- list_of_categories -->",$toc_html 4486 ot. list_of_commands.html 4487 if !isfile('index.html') x "ln -fs list_of_commands.html index.html" fi 4488 rm. 4489 4490 # Retrieve full list of commands and discard those starting with '_'. 4491 repeat $! if s=['{$<,n}'];s[0]==_'_' rm[$<] else l[$<] 4492 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4493 is_eqto=${parse_cli_is_eqto.} 4494 if !$is_eqto _is_$name=1 else rm fi 4495 endl fi done 4496 4497 # Generate html page for each command. 4498 repeat $! l[$>] 4499 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4500 e[] "\r > "$_vt100_c[#{1+$>}]$_vt100_n" "{`copy(vector48(_'" "'),['$category" / "$name'])`} 4501 4502 # Find previous and next commands. 4503 if !$> previous= else pass[{$>-1}] 1 ('{n}') discard. {'_c1'} previous={t} rm[-2,-1] fi 4504 if !$< next= else pass[{$>+1}] 1 ('{n}') l. s -,{'@'} next={0,t} rm endl rm. fi 4505 if ['$name']=='index' url_name=_index.html else url_name=$name.html fi 4506 if ['$previous']=='index' url_previous=_index.html else url_previous=$previous.html fi 4507 if ['$next']=='index' url_next=_index.html else url_next=$next.html fi 4508 4509 strvar[] $category category_id=${} 4510 4511 html="<!DOCTYPE html>"\n\ 4512"<html lang=\"en\">"\n\ 4513" <head>"\n\ 4514" <meta charset=\"utf-8\">"\n\ 4515" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 4516" <link rel=\"stylesheet\" href=\"../highslide/highslide.css\"/>"\n\ 4517" <link rel=\"stylesheet\" href=\"https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css\">"\n\n\ 4518" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 4519"- Reference Documentation - "$name"</title>"\n\ 4520" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 4521" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 4522" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 4523" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 4524" <script src=\"../highslide/highslide-full.js\"></script>"\n\ 4525" <script>"\n\ 4526" hs.graphicsDir = '../highslide/graphics/';"\n\ 4527" hs.wrapperClassName = 'wide-border';"\n\ 4528" hs.showCredits = 'false';"\n\ 4529" </script>"\n\ 4530" </head>"\n\n\ 4531" <body>"\n\ 4532" <div id=\"include_header\"></div>"\n\n\ 4533" <div class=\"section_title\"><a href=\"index.html\"><p>Reference</p></a></div>"\ 4534"<div class=\"section_content\" style=\"padding-top: 0;\">"\n\n\ 4535" <a name=\"top\"></a>"\n\n\ 4536"<!-- begin_content -->"\n\n 4537 4538 if !0$_pdf_output 4539 html.=" <table class=\"ref_navigation_top\"><tr><td>"\ 4540"<a href=\"index.html\">Table of Contents</a> ▸ "\ 4541"<a href=\"list_of_commands.html#top\">List of Commands</a> ▸ "\ 4542"<a href=\"list_of_commands.html#"$category_id"\">"$category"</a> ▸ "\ 4543"<a href=\""$url_name"#top\"><samp>"$name"</samp></a></td>" 4544 if narg($previous)" || "narg($next) 4545 html.="<td>" 4546 if narg($previous) html.="<a href=\""$url_previous"#top\">◀ <samp>"$previous"</samp></a>" fi 4547 if narg($previous)" && "narg($next) html.=" | " fi 4548 if narg($next) html.="<a href=\""$url_next"#top\"><samp>"$next"</samp> ▶</a>" fi 4549 html.="</td>"\n 4550 fi 4551 html.=" </tr></table>\n" 4552 4553 else 4554 html.="<img style=\"margin-top: 2em; width: 100%;\" src=\"reference_pdf.png\"/>"\n 4555 fi 4556 4557 # Parse command declaration. 4558 s -,{'\n'} discard {'#@cli'} max {'" "'} autocrop {'" "'} 4559 +l[0] 4560 s -,{'": "'} autocrop {'" "'} rm[0] 4561 is_builtin=0 4562 if $!" && find(#-1,'(+)')>=0" is_builtin=1 rm. fi 4563 if $is_builtin 4564 html.=" <table class=\"ref_h1_builtin\"><tr><td><h1 class=\"ref_h1\" style=\"margin-bottom: 0;\">"\ 4565 $name"</h1></td><td><span class=\"ref_builtin_command\">Built-in command</span></td></tr></table>"\n 4566 else 4567 html.=" <h1 class=\"ref_h1\">"$name"</h1>"\n 4568 fi 4569 if $! 4570 html.="\n <h2>Arguments:</h2>\n <ul>"\n 4571 if $!>1 or=" or" else or= fi 4572 repeat $! l[$>] 4573 if !$< or= fi 4574 html.=" <li><span class=\"gmd_monospace\">"{t}"</span>"$or"</li>"\n 4575 endl done 4576 html.=" </ul>"\n 4577 else 4578 html.="\n <h3>No arguments</h2>"\n 4579 fi 4580 rm 4581 endl 4582 rm[0] 4583 4584 # Parse command description. 4585 html.="\n <h2>Description:</h2>"\n 4586 line=0 4587 n_example=0 4588 nb_examples=0 4589 is_tutorial_tag=0 4590 tutorial_html= 4591 4592 repeat $! if {$>,i==_':'} l[$>] 4593 if "h==1 || (h==2 && i[-1,2]==_' ')" rm ('": "':y) fi # Empty description lines 4594 rows {1+(i[1]==_'" "')},100% 4595 if i==_'$'" && "i[1]!=_'$' nb_examples+=1 fi 4596 endl fi done 4597 4598 repeat $! l[$>] 4599 if "find(#0,'(eq. to ')>=0" 4600 4601 # Found 'Eq. to' description. 4602 +l s -,{'\47'} 4603 replace_str[1] "&","&" 4604 replace_str[1] "<","<" 4605 replace_str[1] ">",">" 4606 shortcut={1,t} 4607 rm 4608 onfail 4609 shortcut="(unknown)" 4610 rm 4611 endl 4612 html.=" <p>(<em>equivalent to shortcut command</em> <span class=\"gmd_monospace\">"$shortcut\ 4613 "</span>).</p>"\n 4614 4615 elif "find(#0,'See also:')>=0" 4616 4617 # Found 'See also:' description. 4618 s +,{':'} autocrop {'" "'} 4619 if $!>2" && "h#1==1" && "i("#1")==_':' 4620 html.="\n <h2>See also:</h2>"\n 4621 rm[0,1] 4622 fi 4623 a y 4624 gmd2html 0 4625 html.=" "{t}\n 4626 4627 elif "find(#0,'Default value:')>=0 || find(#0,'Default values:')>=0" 4628 4629 # Found 'Default value(s):' description 4630 s +,{':'} autocrop {'" "'} 4631 if $!>2" && "h#1==1" && "i("#1")==_':' 4632 html.="\n<h2>Default values:</h2>"\n 4633 rm[0,1] 4634 fi 4635 a y 4636 gmd2html 0 4637 html.="<p style=\"word-wrap:break-word\">"{t}"</p>"\n 4638 4639 elif i==_'$'" && "i[1]!=_'$' 4640 4641 # Found 'Example of use' description. 4642 rows 1,100% autocrop {'" "'} 4643 if !0$_pdf_output 4644 replace_str "image.jpg","<a href=\"image.jpg\" class=\"highslide\" onclick=\"return hs.expand(this)\">"\ 4645 "image.jpg</a>" 4646 fi 4647 example={/{t}} 4648 n_example+=1 4649 if $n_example>1 basename=${name}_$n_example.jpg else basename=${name}.jpg fi 4650 if $n_example==1 4651 if !$is_tutorial_tag html.="<tutorial_tag>" is_tutorial_tag=1 fi 4652 html.="\n <h2>Example"${"if "$nb_examples">1 u s else u \"\" fi"}" of use:</h2>"\n fi 4653 if $nb_examples!=1 html.=" <h3>• Example \#"$n_example"</h3>"\n fi 4654 html.=" <div class=\"gmd_code_block\">$ gmic "$example"</div><br/>"\n 4655 4656 if 0$_pdf_output html.="<div style=\"text-align: center;\">"\n fi 4657 if isfile('img/f_$basename') # Single output image 4658 if !0$_pdf_output 4659 html.=" <span><a href=\"img/"f_$basename"\" class=\"highslide\" onclick=\"return hs.expand(this)\">"\ 4660 "<img class=\"center_image\" src=\"img/"t_$basename"\"/></a>"\ 4661 "<div class=\"highslide-caption\">Command: <b>"$example"</b></div></span>"\n 4662 else 4663 html.="<img style=\"max-width:45%\" src=\"img/"t_$basename"\"/>"\n 4664 fi 4665 elif isfile('img/f0_$basename') # Multiple output images 4666 i=0 4667 html.=" <div class=\"center\">" 4668 for isfile('img/f${i}_$basename') 4669 if !0$_pdf_output 4670 html.=" <span><a href=\"img/"f${i}_$basename"\" class=\"highslide\" "\ 4671 "onclick=\"return hs.expand(this)\">"\ 4672 "<img src=\"img/"t${i}_$basename"\"/></a>"\ 4673 "<div class=\"highslide-caption\">Command: <b>"$example"</b></div></span>"\n 4674 else 4675 html.="<img style=\"max-width:45%\" src=\"img/"t${i}_$basename"\"/>"\n 4676 fi 4677 i+=1 4678 done 4679 html.=" </div>" 4680 fi 4681 if 0$_pdf_output html.="</div>"\n fi 4682 4683 elif i==_'$'" && "i[1]==_'$' 4684 4685 # Found link to tutorial page. 4686 if !$is_tutorial_tag html.="<tutorial_tag>" is_tutorial_tag=1 fi 4687 if h==2 4688 url=https://gmic.eu/tutorial/$name 4689 l[] it $url if "find(#-1,'404 Not Found')>=0" url=https://gmic.eu/oldtutorial/_$name fi rm endl 4690 else 4691 rows 2,100 autocrop {'" "'} url={t} 4692 fi 4693 4694 tutorial_html.=" <p>This command has a <span class=\"ref_tutorial_button\"><a href=\""$url"\">"\ 4695 "tutorial page</a></span>.</p>" 4696 else 4697 4698 # Other kind of description line 4699 +autocrop {"' '"} is_list={isin(i,_'*',_'-',_'.')} rm. 4700 ('\n') a y 4701 replace_str "\\n","\n" gmd2html 0 4702 if $line==1" && "!$is_list html.=" <br/>"\n fi 4703 html.={t} 4704 if i[-1,2]!=_'\n' html.="\n" fi 4705 line+=1 4706 fi 4707 endl done 4708 4709 # Generate page. 4710 html.=\n\ 4711"<!-- end_content -->"\n\n\ 4712"<!-- ref_navigation_bottom -->"\n\ 4713" </div><div class=\"section_end\"></div>"\n\ 4714" <div id=\"include_footer\"></div>"\n\ 4715" </body>" 4716 rm ({'$html'}:y) 4717 replace_str. "<tutorial_tag>",$tutorial_html # Insert tutorial button 4718 nm $name ot $url_name 4719 endl done 4720 rm 4721 e[] "\r > "${_vt100_g}{`copy(vector64(_'" "'),'"Parsing done!"')`}$_vt100_n 4722 4723parse_cli_trigger_html : 4724 parse_cli_trigger_print $* 4725 4726# 4727# Implements 'image' mode for command 'parse_cli'. 4728# 4729parse_cli_images : 4730 v 0 use_vt100 e[] "" 4731 old_category,category= n_category,n_example=0 4732 if !isfile('image.jpg') l[] sp bottles,640 onfail testimage2d 500 endl o. image.jpg rm. fi 4733 n_global=0 4734 repeat $! if s=['{$>,n}'];s[0]==_'_' continue fi l[$>] 4735 ('{n}') l. s -,{'@'} name={0,t} if $!>1 category={1,t} else category= fi rm endl 4736 4737 if ['$category']!=['$old_category'] 4738 n_category+=1 4739 e[] $_vt100_r"\n ** Section \#"$n_category": "$category"."$_vt100_n"\n" 4740 fi 4741 s -,{'\n'} discard {'#@cli'} max {'" "'} autocrop {'" "'} 4742 n_example=0 4743 4744 repeat $! l[$>] 4745 if "i==_':' && ( 4746 for (p = 1, p<h && i[p]<=_' ', ++p); 4747 i[p]==_'$' && i[p+1]!=_'$')" 4748 4749 s +,{'$'} rm[0,1] a y autocrop {'" "'} example={/{t}} 4750 n_example+=1 4751 n_global+=1 4752 if $n_example>1 4753 basename=${name}_$n_example.jpg 4754 else 4755 basename=${name}.jpg 4756 fi 4757 e[] $_vt100_c[$n_global]$_vt100_n" Command '"$_vt100_g$name$_vt100_n"': $ "$example 4758 skip_rendering={"['"$name"'][0]==_'_' || "\ 4759 "(isfile(['"{/${_parse_cli_images_path}f_$basename}"']) &&"\ 4760 " isfile(['"{/${_parse_cli_images_path}t_$basename}"'])) || "\ 4761 "(isfile(['"{/${_parse_cli_images_path}f0_$basename}"']) && "\ 4762 "isfile(['"{/${_parse_cli_images_path}t0_$basename}"']))"} 4763 4764 if !$skip_rendering # Generate picture only if the file doesn't yet exist 4765 m "run_example : "$example 4766 l[] 4767 reset etime=$| 4768 run_example 4769 etime="done in "$_vt100_n{_round($|-$etime,0.01)}"s"$_vt100_m 4770 _parse_cli_images 4771 if $! 4772 if $!>1 repeat $! o[$>] ${_parse_cli_images_path}f$>_$basename,85 done 4773 else o ${_parse_cli_images_path}f_$basename,85 fi 4774 rr2d 480,320,0,2 4775 if $!>1 repeat $! o[$>] ${_parse_cli_images_path}t$>_$basename,75 done 4776 else o ${_parse_cli_images_path}t_$basename,75 fi 4777 rm 4778 fi 4779 onfail 4780 rm gui_error_preview "Unable to generate preview image" 4781 o ${_parse_cli_images_path}f_$basename,85 4782 rr2d 480,320,0,2 4783 o ${_parse_cli_images_path}t_$basename,75 4784 rm 4785 etime="failed" 4786 endl 4787 um run_example 4788 else etime="skipped" 4789 fi 4790 e[] "\r"$_vt100_c[$n_global]$_vt100_n" Command '"$_vt100_g$name$_vt100_n"': $ "\ 4791 $example" "${_vt100_m}"("$etime")."$_vt100_n 4792 fi 4793 endl done 4794 old_category=$category 4795 rm 0 4796 endl done rm 4797 4798# Generate a single image from a list of images, for the reference documentation. 4799_parse_cli_images : 4800 if !$! rm return fi 4801 W,H={[640,480]} 4802 4803 repeat $! l[$>] nm={n} 4804 label=[$>]:" "'$nm' 4805 if ${-is_3d} # 3D vector object 4806 label2="("{i[6]}" vert., "{i[7]}" prim.)" 4807 r3d 1,1,0,-80 r3d 0,1,0,80 snapshot3d {max($W,$H)} 4808 else # Regular 1D,2D or 3D image 4809 label2="("{w}x{h}x{d}x{s}")" 4810 r 100%,100%,100%,3,{s==1?1:0} 4811 if d>1 # Volumetric image -> Render as a 2D image 4812 +slices 50% 4813 +z[0] 50%,0,0,50%,100%,100% permute. zyxc 4814 +z[0] 0,50%,0,100%,50%,100% permute. xzyc 4815 rr2d... $W,$H,0,2 4816 r2dy.. {-3,h},1 4817 r2dx. {-3,w},1 4818 s={min(w#-2,h)} 4819 if $s>64 projections3d[0] 50%,50%,50%,1 mv[0] $! r3d. 1,1,0,-80 r3d. 0,1,0,80 snapshot3d. $s 4820 else rm[0] 0 4821 fi 4822 4823 eW,eH={[w#0+w#1,h#0+h#2]} 4824 if $eW>$W" || "$eH>$H fact={min($W/$eW,$H/$eH)*100} r $fact%,$fact%,1,100%,2 fi 4825 n 0,255 4826 4827 fs={0,max(w,h)*7%} 4828 if {0,h>1.5*$fs} to[0] XY,4,2,$fs fi 4829 if {1,h>1.5*$fs} to[1] XZ,4,2,$fs fi 4830 if {2,h>1.5*$fs} to[2] YZ,4,2,$fs fi 4831 if w to[3] 3D,4,2,$fs frame[3] 1,1,200 fi 4832 frame[0-2] 1,1,200 4833 a[0,1] x a[1,2] x a y 4834 fi 4835 fi 4836 4837 if w>5*h r $W,{$H/3},1,100%,1 4838 elif h>5*w r {$W/3},$H,1,100%,1 4839 else rr2d $W,$H,0,{w<$W&&h<$H?1:2} 4840 fi 4841 n 0,255 4842 4843 r {[w,h]+2},1,100%,0,0,0.5,0.5 4844 - 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 4845 4846 0 t. $label" "$label2,5,0,32,1,1 4847 if w>w#0" || "h>h#0 4848 rm. 0 t. $label\n$label2,5,0,32,1,1 4849 if w>w#0" || "h>h#0 rr2d. {0,[w,h]},0,2 fi 4850 fi 4851 *. -1 n. 0,255 to_rgb. 4852 - 245 a y,0.5 + 245 4853 4854 endl done 4855 c 0,255 4856 4857parse_cli_trigger_images : 4858 parse_cli_trigger_print $* 4859 4860# 4861# Implements 'list' mode for command 'parse_cli'. 4862# (return a list of all commands, separated by commas). 4863# 4864parse_cli_list : 4865 res= 4866 repeat $! ('{$>,n}') l. s -,{'@'} res.=$c{0,t} c=, rm endl done 4867 rm u $res 4868 4869# 4870# Implements 'print' mode for command 'parse_cli'. 4871# 4872parse_cli_print : 4873 v 0 e[] "" 4874 sort_list +,n 4875 repeat $! l[$>] 4876 ('{n}') l. s -,{'@'} name={0,t} rm endl 4877 +e[] $name 4878 endl done rm 4879 4880parse_cli_trigger_print : 4881 if "['$1']!='*'" 4882 1,$!,1,1," 4883 begin(ref(lowercase(['$1']),str)); 4884 ref(lowercase(name(#y)),nm); 4885 arobace = find(nm,_'@'); 4886 inrange(find(nm,str),0,arobace - 1)?y:-1" 4887 discard. -1 k[{^}] 4888 fi 4889 4890#@cli parse_gmd 4891#@cli : Parse and tokenize selected images, viewed as text strings formatted with the G'MIC markdown syntax. 4892parse_gmd : 4893 e[^-1] "Parse and tokenize images$? viewed as text strings formatted with the G\47MIC markdown syntax." 4894 y 1 a[^-1] .,y rm. 4895 eval[^] ">"${-_gmd_tokens}" 4896 begin( 4897 section = subsection = subsubsection = subsubsubsection = anchor = 4898 bullet = subbullet = subsubbullet = center = right = table = blockquote = detail_block = code_block = 4899 shell = bold_italic_a = bold_italic_u = bold_a = bold_u = italic_a = italic_u = strikethrough = underline = 4900 monospace = value_set = word_highlight = url = page_link = text_link1 = text_link2 = img1 = img2 = pipeline = 4901 formula = opening_offset = -1; 4902 4903 blank(c) = isin(c,_' ',_'\n',s_whitespace,s_tab,0); 4904 semiblank(c) = isin(c,_' ',_'\n',_'.',_',',_';',_':',_'!',_'?', 4905 _')',_'(',_'[',_']',_'|',_'-',s_whitespace,s_tab,0); 4906 newline(c) = isin(c,_'\n',0); 4907 reset(c) = (#c = -1); 4908 res = crop(); 4909 ); 4910 4911 pc = j[-1]; c = i; nc = j[1]; ac = j[2]; 4912 ym1 = y - 1; y1 = y + 1; y2 = y + 2; 4913 linestart = newline(pc); 4914 4915 is_raw = max(blockquote,code_block,shell,monospace,url,page_link,text_link2,img2,pipeline,formula)>=0; 4916 non_escaped = is_raw || (pc!=_'\\'); 4917 4918 # Manage document layout. 4919 #------------------------ 4920 4921 # Escaped character. 4922 !non_escaped && 4923 isin(c,_'%',_'$',_'\\',_'\'',_'`',_'*',_'_',_'{',_'}',_'[',_']',_'<',_'>',_'(',_')',_'#',_'+',_'-',_'.',_'!')?( 4924 res[ym1] = i[ym1] = 0; 4925 ): 4926 4927 # Section: '# Section name'. 4928 linestart && c==_'#' && nc==_' '?( # Opening 4929 section = y; 4930 ): 4931 section>=0 && newline(c)?( # Closing 4932 opening_offset = section; 4933 res[section++] = s_section; 4934 while (blank(res[section]), res[section++] = 0); # Remove leading whitespaces 4935 res[y] = e_section; 4936 for (p = opening_offset - 1, p>=0 && res[p]==_'\n', res[p--] = 0); # Remove newlines preceding 4937 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 4938 for (p = y1, p<size(res) && blank(res[p]), res[p++] = 0); # Remove newlines following 4939 ): 4940 4941 # Subsection: '## Subsection name'. 4942 linestart && c==_'#' && nc==c && ac==_' '?( # Opening 4943 subsection = y; 4944 ): 4945 subsection>=0 && newline(c)?( # Closing 4946 opening_offset = subsection; 4947 res[subsection++] = s_subsection; res[subsection++] = 0; 4948 while (blank(res[subsection]), res[subsection++] = 0); # Remove leading whitespaces 4949 res[y] = e_subsection; 4950 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 4951 for (p = y1, p<size(res) && res[p] && blank(res[p]), res[p] = 0); # Remove newlines following 4952 ): 4953 4954 # Subsubsection: '### Subsubsection name'. 4955 linestart && c==_'#' && nc==c && ac==c && j[3]==_' '?( # Opening 4956 subsubsection = y; 4957 ): 4958 subsubsection>=0 && newline(c)?( # Closing 4959 opening_offset = subsubsection; 4960 res[subsubsection++] = s_subsubsection; copy(res[subsubsection],0,2,1,0); subsubsection+=2; 4961 while (blank(res[subsubsection]), res[subsubsection++] = 0); # Remove leading whitespaces 4962 res[y] = e_subsubsection; 4963 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 4964 for (p = y1, p<size(res) && res[p] && blank(res[p]), res[p] = 0); # Remove newlines following 4965 ): 4966 4967 # Subsubsubsection: '#### Subsubsubsection name'. 4968 linestart && c==_'#' && nc==c && ac==c && j[3]==c && j[4]==_' '?( # Opening 4969 subsubsubsection = y; 4970 ): 4971 subsubsubsection>=0 && newline(c)?( # Closing 4972 opening_offset = subsubsubsection; 4973 res[subsubsubsection++] = s_subsubsubsection; copy(res[subsubsubsection],0,3,1,0); subsubsubsection+=3; 4974 while (blank(res[subsubsubsection]), res[subsubsubsection++] = 0); # Remove leading whitespaces 4975 res[y] = e_subsubsubsection; 4976 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 4977 for (p = y1, p<size(res) && res[p] && blank(res[p]), res[p] = 0); # Remove blanks following 4978 ): 4979 4980 # Anchor: '= Anchor name'. 4981 linestart && c==_'=' && nc==_' '?( # Opening 4982 anchor = y; 4983 ): 4984 anchor>=0 && newline(c)?( # Closing 4985 opening_offset = anchor; 4986 res[anchor++] = s_anchor; 4987 while (blank(res[anchor]), res[anchor++] = 0); # Remove leading whitespaces 4988 res[y] = e_anchor; 4989 res[y1]==_'\n'?(res[y1] = 0); 4990 for (p = ym1, p>opening_offset && blank(res[p]), res[p--] = 0); # Remove trailing blanks 4991 ): 4992 4993 # List bullet: '* List item'. 4994 linestart && isin(c,_'-',_'*',_'+') && nc==_' ' && bullet<0?( # Opening 4995 bullet = y; 4996 ): 4997 bullet>=0 && newline(c)?( # Closing 4998 opening_offset = bullet; 4999 res[bullet++] = s_bullet; res[bullet] = 0; 5000 res[y] = e_bullet; 5001 ): 5002 5003 # Sublist bullet: ' * Sub-list item'. 5004 linestart && c==_' ' && nc==_' ' && isin(ac,_'-',_'*',_'+') && j[3]==_' ' && subbullet<0?( # Opening 5005 subbullet = y; 5006 ): 5007 subbullet>=0 && newline(c)?( # Closing 5008 opening_offset = subbullet; 5009 res[subbullet++] = s_subbullet; copy(res[subbullet],0,2,1,0); 5010 res[y] = e_subbullet; 5011 ): 5012 5013 # Subsublist bullet: ' * Subsub-list item'. 5014 linestart && c==_' ' && nc==_' ' && ac==_' ' && j[3]==_' ' && isin(j[4],_'-',_'*',_'+') && j[5]==_' ' && 5015 subsubbullet<0?( # Opening 5016 subsubbullet = y; 5017 ): 5018 subsubbullet>=0 && newline(c)?( # Closing 5019 opening_offset = subsubbullet; 5020 res[subsubbullet++] = s_subsubbullet; copy(res[subsubbullet],0,4,1,0); 5021 res[y] = e_subsubbullet; 5022 ): 5023 5024 # Centered block: '\n===\n Centered text\n===\n'. 5025 linestart && c==_'=' && nc==c && ac==c && newline(j[3])?( 5026 center<0?( # Opening 5027 center = y; 5028 ): 5029 center>=0 && y>center + 3?( # Closing 5030 opening_offset = center; 5031 res[center++] = s_center; copy(res[center],0,3,1,0); center+=3; 5032 newline(res[ym1])?(res[ym1] = 0); 5033 res[y] = e_center; copy(res[y + 1],0,3,1,0); 5034 ); 5035 ): 5036 5037 # Right block: '\n>>>\n Right-aligned text\n>>>\n'. 5038 linestart && c==_'>' && nc==c && ac==c && newline(j[3])?( 5039 right<0?( # Opening 5040 right = y; 5041 ): 5042 right>=0 && y>right + 3?( # Closing 5043 opening_offset = right; 5044 res[right++] = s_right; copy(res[right],0,3,1,0); right+=3; 5045 newline(res[ym1])?(res[ym1] = 0); 5046 res[y] = e_right; copy(res[y + 1],0,3,1,0); 5047 ); 5048 ): 5049 5050 # Table : '\n| foo | bar\n' (with first delimiter '||', '|+' or '|-'). 5051 table<0 && linestart && c==_'|'?( # Opening 5052 table = y; 5053 ): 5054 table>=0 && newline(c) && nc!=_'|'?( # Closing 5055 opening_offset = table; 5056 d = i[table + 1]; 5057 d==_'|'?(res[table++] = s_htable; res[table++] = 0): 5058 d==_'-'?(res[table++] = s_vtable; res[table++] = 0): 5059 d==_'+'?(res[table++] = s_hvtable; res[table++] = 0):(res[table++] = s_table); 5060 5061 i[table]==_' '?(res[table++] = 0); 5062 newline(i[table]) && i[table + 1]==_'|'?(copy(res[table],0,2,1,0); table+=2); 5063 for (p = table, p<y, ++p, # Find column / line separators inside table 5064 i[p]==_'|'?( 5065 res[p] = newline(i[p - 1]) || newline(i[p + 1])?0:m_table; 5066 i[p - 1]==_' '?(res[p - 1] = 0); 5067 i[p + 1]==_' '?(res[p + 1] = 0); 5068 ):newline(i[p])?( 5069 res[p] = n_table; 5070 ); 5071 ); 5072 res[y] = e_table; 5073 ): 5074 5075 # Blockquote : '\n> line1\n> line2'. 5076 code_block<0 && blockquote<0 && linestart && c==_'>' && blank(nc)?( # Opening 5077 blockquote = y; 5078 ): 5079 blockquote>=0 && newline(c) && (nc!=_'>' || !blank(ac))?( # Closing 5080 opening_offset = blockquote; 5081 res[blockquote++] = s_blockquote; res[blockquote] = 0; 5082 # Remove leading '>' when multi-lines: 5083 for (p = blockquote, p<y, ++p, newline(res[p - 1]) && res[p]==_'>'?copy(res[p],0,res[p + 1]==_' '?2:1,1,0)); 5084 res[y] = e_blockquote; 5085 ): 5086 5087 # Detail block: '\n??? Details:\nDetail block\n???\n'. 5088 linestart && c==_'?' && nc==c && ac==c && blank(j[3])?( 5089 detail_block<0?( # Opening 5090 detail_block = y; 5091 ): 5092 detail_block>=0 && y>detail_block + 3 && newline(j[3])?( # Closing 5093 opening_offset = detail_block; 5094 res[detail_block++] = s_detail_block; copy(res[detail_block],0,2,1,0); 5095 res[ym1] = e_detail_block; copy(res[y],0,4,1,0); 5096 ); 5097 ): 5098 5099 # Code block: '\n~~~\n Code block\n~~~\n'. 5100 linestart && isin(c,_'~','`') && nc==c && ac==c && newline(j[3])?( 5101 code_block<0?( # Opening 5102 code_block = y; 5103 ): 5104 code_block>=0 && y>code_block + 3?( # Closing 5105 opening_offset = code_block; 5106 res[code_block++] = s_code_block; copy(res[code_block],0,3,1,0); code_block+=3; 5107 copy(res[code_block],i[code_block],y - code_block); # Cancel tokens found inside 5108 for (p = code_block, p<y, ++p, res[p]==_' '?(res[p] = s_whitespace)); # Keep leading whitespaces. 5109 res[ym1] = e_code_block; copy(res[y],0,4,1,0); 5110 ); 5111 ): 5112 5113 # Shell command: '\n"""\n Shell command\n"""\n'. 5114 linestart && c==_'\"' && nc==c && ac==c && newline(j[3])?( 5115 shell<0?( # Opening 5116 shell = y; 5117 ): 5118 shell>=0 && y>shell + 3?( # Closing 5119 opening_offset = shell; 5120 res[shell++] = s_shell; copy(res[shell],0,3,1,0); shell+=3; 5121 copy(res[shell],i[shell],y - shell); # Cancel tokens found inside 5122 res[ym1] = e_shell; copy(res[y],0,4,1,0); 5123 ); 5124 ): 5125 5126 # Horizontal rule: '---', '___' or '***'. 5127 linestart && isin(c,_'-','_','*') && nc==c && ac==c && newline(j[3])?( 5128 res[y] = s_hrule; 5129 copy(res[y1],0,3,1,0); 5130 ): 5131 5132 # Manage text style. 5133 #------------------- 5134 5135 # Bold italic (asterisk): '***bold italic text***'. 5136 non_escaped && c==_'*' && nc==c && ac==c?( # Opening 5137 bold_italic_a<0?( 5138 bold_italic_a = y; 5139 ): 5140 bold_italic_a>=0 && y>bold_italic_a + 3 && j[3]!=_'*'?( # Closing 5141 opening_offset = bold_italic_a; 5142 res[bold_italic_a++] = s_bold_italic_a; res[bold_italic_a++] = 0; res[bold_italic_a] = 0; 5143 res[y] = e_bold_italic_a; res[y1] = res[y2] = 0; 5144 ); 5145 ): 5146 5147 # Bold italic (underscore): '___bold italic text___'. 5148 non_escaped && c==_'_' && nc==c && ac==c?( 5149 bold_italic_u<0 && semiblank(pc)?( # Opening 5150 bold_italic_u = y; 5151 ): 5152 bold_italic_u>=0 && y>bold_italic_u + 3 && semiblank(j[3])?( # Closing 5153 opening_offset = bold_italic_u; 5154 res[bold_italic_u++] = s_bold_italic_u; res[bold_italic_u++] = 0; res[bold_italic_u] = 0; 5155 res[y] = e_bold_italic_u; res[y1] = res[y2] = 0; 5156 ); 5157 ): 5158 5159 # Bold (asterisk): '**bold text**'. 5160 non_escaped && c==_'*' && nc==c?( # Opening 5161 bold_a<0?( 5162 bold_a = y; 5163 ): 5164 bold_a>=0 && y>bold_a + 2 && ac!=_'*'?( # Closing 5165 opening_offset = bold_a; 5166 res[bold_a++] = s_bold_a; res[bold_a] = 0; 5167 res[y] = e_bold_a; res[y1] = 0; 5168 ); 5169 ): 5170 5171 # Bold (underscore): '__bold text__'. 5172 non_escaped && c==_'_' && nc==c?( 5173 bold_u<0 && semiblank(pc)?( # Opening 5174 bold_u = y; 5175 ): 5176 bold_u>=0 && y>bold_u + 2 && semiblank(ac)?( # Closing 5177 opening_offset = bold_u; 5178 res[bold_u++] = s_bold_u; res[bold_u] = 0; 5179 res[y] = e_bold_u; res[y1] = 0; 5180 ); 5181 ): 5182 5183 # Italic (asterisk): '*italic text*'. 5184 non_escaped && c==_'*' && pc!=c?( # Opening 5185 italic_a<0?( 5186 italic_a = y; 5187 ): 5188 italic_a>=0 && y>italic_a + 1 && ac!=_'*'?( # Closing 5189 opening_offset = italic_a; 5190 res[italic_a] = s_italic_a; 5191 res[y] = e_italic_a; 5192 ); 5193 ): 5194 5195 # Italic (underscore): '_italic text_'. 5196 non_escaped && c==_'_' && pc!=c?( 5197 italic_u<0 && semiblank(pc)?( # Opening 5198 italic_u = y 5199 ): 5200 italic_u>=0 && y>italic_u + 1 && semiblank(nc)?( # Closing 5201 opening_offset = italic_u; 5202 res[italic_u] = s_italic_u; 5203 res[y] = e_italic_u; 5204 ); 5205 ): 5206 5207 # Strikethrough: '~~strikethrough text~~'. 5208 non_escaped && c==_'~' && nc==c && pc!=c?( # Opening 5209 strikethrough<0?( 5210 strikethrough = y; 5211 ): 5212 strikethrough>=0 && y>strikethrough + 2?( # Closing 5213 opening_offset = strikethrough; 5214 res[strikethrough++] = s_strikethrough; res[strikethrough] = 0; 5215 res[y] = e_strikethrough; res[y1] = 0; 5216 ); 5217 ): 5218 5219 # Underline: '==strikethrough text=='. 5220 non_escaped && c==_'=' && nc==c && pc!=c?( # Opening 5221 underline<0?( 5222 underline = y; 5223 ): 5224 underline>=0 && y>underline + 2?( # Closing 5225 opening_offset = underline; 5226 res[underline++] = s_underline; res[underline] = 0; 5227 res[y] = e_underline; res[y1] = 0; 5228 ); 5229 ): 5230 5231 # Monospace: '`monospace text`'. 5232 non_escaped && c==_'`'?( 5233 monospace<0?( # Opening 5234 monospace = y; 5235 ): 5236 monospace>=0 && y>monospace + 1?( # Closing 5237 opening_offset = monospace; 5238 res[monospace++] = s_monospace; 5239 copy(res[monospace],i[monospace],y - monospace); # Cancel tokens found inside 5240 for (p = monospace, p<y, ++p, res[p]==_' '?(res[p] = s_whitespace)); # Keep leading whitespaces. 5241 res[y] = e_monospace; 5242 ); 5243 ): 5244 5245 # Value Set: '{ value1 | value2 | value3 }'. 5246 non_escaped && c==_'{' && value_set<0 && semiblank(pc)?( # Opening 5247 value_set = y; 5248 ): 5249 non_escaped && c==_'}' && value_set>=0 && y>value_set + 1 && semiblank(nc)?( # Closing 5250 opening_offset = value_set; 5251 res[value_set++] = s_value_set; 5252 copy(res[value_set],i[value_set],y - value_set); # Cancel tokens found inside 5253 res[y] = e_value_set; 5254 ): 5255 5256 # Word highlight: ' 'word_highlight' '. 5257 non_escaped && c=='\'' && nc!=c?( 5258 word_highlight<0 && semiblank(pc)?( # Opening 5259 word_highlight = y; 5260 ): 5261 word_highlight>=0 && y>word_highlight + 1 && semiblank(nc)?( # Closing 5262 opening_offset = word_highlight; 5263 res[word_highlight++] = s_word_highlight; 5264 copy(res[word_highlight],i[word_highlight],y - word_highlight); # Cancel tokens found inside 5265 res[y] = e_word_highlight; 5266 ); 5267 ): 5268 5269 # URL: '<https://url.com>'. 5270 non_escaped && c==_'<' && url<0 && 5271 (crop(0,y1,1,8)=='https://' || crop(0,y1,1,7)=='http://' || crop(0,y1,1,6)=='ftp://')?( # Opening 5272 url = y; 5273 ): 5274 non_escaped && c==_'>' && url>=0 && y>url + 1?( # Closing 5275 opening_offset = url; 5276 res[url++] = s_url; 5277 copy(res[url],i[url],y - url); # Cancel tokens found inside 5278 res[y] = e_url; 5279 ): 5280 5281 # Page link (command or reference): ' ''command or page name'' ' (not a URL!). 5282 non_escaped && c==_'\'' && nc==c?( 5283 page_link<0 && semiblank(pc)?( # Opening 5284 page_link = y; 5285 ): 5286 page_link>=0 && y>page_link + 2 && semiblank(ac)?( # Closing 5287 opening_offset = page_link; 5288 res[page_link++] = s_page_link; res[page_link++] = 0; 5289 copy(res[page_link],i[page_link],y - page_link); # Cancel tokens found inside 5290 res[y] = e_page_link; res[y1] = 0; 5291 ); 5292 ): 5293 5294 # Text link: '[link text](https://url.com)'. 5295 non_escaped && c==_'[' && text_link1<0 && text_link2<0 && img1<0?( # Opening 5296 text_link1 = y; 5297 ): 5298 non_escaped && c==_']' && nc==_'(' && text_link1>=0 && text_link2<0 && img1<0?( # Middle 5299 text_link2 = y; 5300 ): 5301 non_escaped && c==_')' && text_link2>=0 && img1<0?( # Closing 5302 opening_offset = text_link1; 5303 res[text_link1] = s_text_link; 5304 res[text_link2++] = m_text_link; res[text_link2++] = 0; 5305 copy(res[text_link2],i[text_link2],y - text_link2); # Cancel tokens found inside 5306 res[y] = e_text_link; 5307 ): 5308 5309 # Image: '![alt caption](https://url.com/image.png)'. 5310 non_escaped && c==_'!' && nc==_'[' && img1<0 && img2<0?( # Opening 5311 img1 = y; 5312 ): 5313 non_escaped && c==_']' && nc==_'(' && img1>=0 && img2<0?( # Middle 5314 img2 = y; 5315 ): 5316 non_escaped && c==_')' && img2>=0?( # Closing 5317 opening_offset = img1; 5318 res[img1++] = s_img; res[img1++] = 0; 5319 res[img2++] = m_img; res[img2++] = 0; 5320 copy(res[img1],i[img1],img2 - img1 - 2); copy(res[img2],i[img2],y - img2); # Cancel tokens found inside 5321 res[y] = e_img; 5322 ): 5323 5324 # G'MIC pipeline (image): '%% G'MIC pipeline %%'. 5325 non_escaped && c==_'%' && nc==c?( 5326 pipeline<0 && semiblank(pc)?( # Opening 5327 pipeline = y; 5328 ): 5329 pipeline>=0 && y>pipeline + 2 && semiblank(ac)?( # Closing 5330 opening_offset = pipeline; 5331 res[pipeline++] = s_pipeline; res[pipeline++] = 0; 5332 copy(res[pipeline],i[pipeline],y - pipeline); # Cancel tokens found inside 5333 while (blank(i[pipeline]), res[pipeline++] = 0); # Remove leading blanks 5334 for (p = ym1, blank(res[p]), res[p--] = 0); # Remove trailing blanks 5335 res[y] = e_pipeline; res[y1] = 0; 5336 ); 5337 ): 5338 5339 # Formula in LaTeX: '$$ x = cos(x + 2) $$`'. 5340 non_escaped && c==_'$' && nc==c?( 5341 formula<0 && semiblank(pc)?( # Opening 5342 formula = y; 5343 ): 5344 formula>=0 && y>formula + 2 && semiblank(ac)?( # Closing 5345 opening_offset = formula; 5346 res[formula++] = s_formula; res[formula++] = 0; 5347 copy(res[formula],i[formula],y - formula); # Cancel tokens found inside 5348 while (blank(i[formula]), res[formula++] = 0); # Remove leading blanks 5349 for (p = ym1, blank(res[p]), res[p--] = 0); # Remove trailing blanks 5350 res[y] = e_formula; res[y1] = 0; 5351 ); 5352 ): 5353 5354 # G'MIC word: '\G'MIC'. 5355 semiblank(pc) && c==_'\\' && nc==_'G' && ac==_'\'' && j[3]==_'M' && j[4]==_'I' && j[5]==_'C' && semiblank(j[6])?( 5356 res[y] = s_gmic; 5357 copy(res[y1],0,4,1,0); 5358 res[y + 5] = e_gmic; 5359 ): 5360 5361 # Whitespaces. 5362 c==_' '?( 5363 5364 # Keep consecutive whitespaces. 5365 c==_' ' && (linestart || pc==c)?( 5366 res[y] = s_whitespace; 5367 ); 5368 5369 # Reset tokens that cannot contain whitespace. 5370 reset(word_highlight); 5371 reset(url); 5372 text_link2>=0?(reset(text_link1); reset(text_link2)); 5373 img2>=0?(reset(img1); reset(img2)); 5374 ): 5375 5376 # Escaped newline. 5377 c==_'\\' && nc==_'n'?( 5378 res[y] = _'\n'; res[y + 1] = 0; 5379 ): 5380 5381 # Tab. 5382 c==_'\t'?( 5383 res[y] = s_tab; 5384 ): 5385 5386 # Newline. 5387 c==_'\n'?( 5388 5389 # Reset tokens that cannot contain newlines. 5390 reset(bold_italic_a); 5391 reset(bold_italic_u); 5392 reset(bold_u); 5393 reset(bold_a); 5394 reset(italic_a); 5395 reset(italic_u); 5396 reset(strikethrough); 5397 reset(underline); 5398 reset(monospace); 5399 reset(word_highlight); 5400 reset(url); 5401 reset(page_link); 5402 text_link2>=0?(reset(text_link1); reset(text_link2)); 5403 img2>=0?(reset(img1); reset(img2)); 5404 ); 5405 5406 # Cancel opened tokens starting after the opening offset of the latest closed token. 5407 #------------------------------------------------------------------------------------ 5408 opening_offset>=0?( 5409 section>=opening_offset ? reset(section); 5410 subsection>=opening_offset ? reset(subsection); 5411 subsubsection>=opening_offset ? reset(subsubsection); 5412 subsubsubsection>=opening_offset ? reset(subsubsubsection); 5413 anchor>=opening_offset ? reset(anchor); 5414 bullet>=opening_offset ? reset(bullet); 5415 subbullet>=opening_offset ? reset(subbullet); 5416 subsubbullet>=opening_offset ? reset(subsubbullet); 5417 center>=opening_offset ? reset(center); 5418 right>=opening_offset ? reset(right); 5419 table>=opening_offset ? reset(table); 5420 blockquote>=opening_offset ? reset(blockquote); 5421 detail_block>=opening_offset ? reset(detail_block); 5422 code_block>=opening_offset? reset(code_block); 5423 shell>=opening_offset? reset(shell); 5424 bold_italic_a>=opening_offset ? reset(bold_italic_a); 5425 bold_italic_u>=opening_offset ? reset(bold_italic_u); 5426 bold_a>=opening_offset ? reset(bold_a); 5427 bold_u>=opening_offset ? reset(bold_u); 5428 italic_a>=opening_offset ? reset(italic_a); 5429 italic_u>=opening_offset ? reset(italic_u); 5430 strikethrough>=opening_offset ? reset(strikethrough); 5431 underline>=opening_offset ? reset(underline); 5432 monospace>=opening_offset ? reset(monospace); 5433 value_set>=opening_offset ? reset(value_set); 5434 word_highlight>=opening_offset ? reset(word_highlight); 5435 url>=opening_offset ? reset(url); 5436 page_link>=opening_offset ? reset(page_link); 5437 text_link1>=opening_offset || text_link2>=opening_offset ? (reset(text_link1); reset(text_link2)); 5438 img1>=opening_offset || img2>=opening_offset ? (reset(img1); reset(img2)); 5439 pipeline>=opening_offset ? reset(pipeline); 5440 formula>=opening_offset ? reset(formula); 5441 opening_offset = -1; 5442 ); 5443 5444 end(copy(i[0],res))" 5445 discard 0 5446 5447#@cli gmd2html : _include_default_header_footer={ 0=none | 1=Reference | 2=Tutorial | 3=News } : (no arg) 5448#@cli : Convert selected gmd-formatted text images to html format. 5449#@cli : Default values: 'include_default_header_footer=1'. 5450gmd2html : skip "${1=}" 5451 l[] is_arg={isint("$1")} onfail is_arg=0 endl 5452 if $is_arg embed_html=$1 else embed_html=1 noarg fi 5453 5454 parse_gmd 5455 s_section,e_section={${-_gmd_tokens}"[s_section,e_section]"} 5456 repeat $! l[$>] nm$>={b} strvar ${nm$>} fnm=${} 5457 if "i=="$s_section" && find(#-1,"$e_section")>0" 5458 +rows 1,{"find(#-1,"$e_section")-1"} title$>={t} rm. 5459 else title$>= 5460 fi 5461 . # [0] = Output, [1] = Input 5462 eval. "> 5463 begin("${-_gmd_tokens}${-_gmd_write}"); 5464 c = i; 5465 c>0?( 5466 c==_'\n' ? write('<br/>\n'): 5467 c==_'&' ? write('&'): 5468 c==_'\47' ? write('''): 5469 c==_'>' ? write('>'): 5470 c==_'\"' ? write('"'): 5471 c==_'<' ? write('<'): 5472 write(c); 5473 ):( 5474 isin(c,e_bold_a,e_bold_u,e_bold_italic_a,e_bold_italic_u,e_italic_a,e_italic_u, 5475 e_monospace,e_strikethrough,e_underline,e_word_highlight) ? write('</span>'): 5476 isin(c,e_bullet,e_subbullet,e_subsubbullet) ? write('</div>\n'): 5477 isin(c,e_section,e_subsection,e_subsubsection,e_subsubsubsection) ? write('</div>\n'): 5478 5479 c==s_section ? ( 5480 ind_e = find(#1,e_section,y); 5481 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5482 ref(get('_gmd_name',1024,1),str_nam); 5483 write_nl(); 5484 write('<a name=\"'); 5485 len = find(str_nam,0); 5486 write(str_nam,len); 5487 write('\"></a><div class=\"gmd_section\">'); 5488 ): 5489 c==s_subsection ? ( 5490 ind_e = find(#1,e_subsection,y); 5491 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5492 ref(get('_gmd_name',1024,1),str_nam); 5493 write_nl(); 5494 write('<a name=\"'); 5495 len = find(str_nam,0); 5496 write(str_nam,len); 5497 write('\"></a><div class=\"gmd_subsection\">'); 5498 ): 5499 c==s_subsubsection ? ( 5500 ind_e = find(#1,e_subsubsection,y); 5501 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5502 ref(get('_gmd_name',1024,1),str_nam); 5503 write_nl(); 5504 write('<a name=\"'); 5505 len = find(str_nam,0); 5506 write(str_nam,len); 5507 write('\"></a><div class=\"gmd_subsubsection\">'); 5508 ): 5509 c==s_subsubsubsection ? ( 5510 ind_e = find(#1,e_subsubsubsection,y); 5511 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5512 ref(get('_gmd_name',1024,1),str_nam); 5513 write_nl(); 5514 write('<a name=\"'); 5515 len = find(str_nam,0); 5516 write(str_nam,len); 5517 write('\"></a><div class=\"gmd_subsubsubsection\">'); 5518 ): 5519 c==s_anchor ? ( 5520 ind_e = find(#1,e_anchor,y); 5521 run('_gmd2html_section. ',y + 1,',',ind_e - 1); 5522 ref(get('_gmd_name',1024,1),str_nam); 5523 write('<a name=\"'); 5524 len = find(str_nam,0); 5525 write(str_nam,len); 5526 write('\"></a>\n'); 5527 copy(i[y],0,ind_e - y + 1,1,0); 5528 ): 5529 c==s_bullet ? write('<div class=\"gmd_bullet\">'): 5530 c==s_subbullet ? write('<div class=\"gmd_subbullet\">'): 5531 c==s_subsubbullet ? write('<div class=\"gmd_subsubbullet\">'): 5532 c==s_center ? write('<div class=\"gmd_center\">\n'): 5533 c==e_center ? (write_nl(); write('</div>')): 5534 c==s_right ? write('<div class=\"gmd_right\">\n'): 5535 c==e_right ? (write_nl(); write('</div>')): 5536 c==s_table ? (write_nl(); write('<table class=\"gmd_table\">\n<tr><td>')): 5537 c==s_htable ? (write_nl(); write('<table class=\"gmd_htable\">\n<tr><td>')): 5538 c==s_vtable ? (write_nl(); write('<table class=\"gmd_vtable\">\n<tr><td>')): 5539 c==s_hvtable ? (write_nl(); write('<table class=\"gmd_hvtable\">\n<tr><td>')): 5540 c==m_table ? write('</td><td>'): 5541 c==n_table ? write('</td></tr>\n<tr><td>'): 5542 c==e_table ? write('</td></tr>\n</table>\n'): 5543 c==s_blockquote ? (write_nl(); write('<blockquote class=\"gmd_blockquote\">\n')): 5544 c==e_blockquote ? (write('\n</blockquote>\n')): 5545 c==s_detail_block ? ( 5546 write_nl(); 5547 write('<details class=\"gmd_details\">\n<summary>'); 5548 ny = y + 1; 5549 nc = j[1]; 5550 nc!=e_detail_block?( 5551 j[1] = 0; 5552 ind_e = find(#1,e_detail_block,ny); 5553 nc==_' '?( # Has a title 5554 ind_nl = find(#1,_'\n',ny); 5555 ind_nl<0 || ind_nl>ind_e?(ind_nl = ind_e); 5556 write(#1,y + 2,ind_nl - y - 2); 5557 copy(i[ny],0,ind_nl - y - 1,1,0); 5558 i[ind_nl]!=e_detail_block?(i[ind_nl] = 0); 5559 ):write('Details:'); 5560 write('</summary>\n'); 5561 ) 5562 ): 5563 c==e_detail_block ? (write_nl(); write('</details>\n')): 5564 c==s_code_block ? write('<div class=\"gmd_code_block\">'): 5565 c==e_code_block ? write('</div>\n'); 5566 5567 c==s_shell ? ( 5568 ind_e = find(#1,e_shell,y); 5569 run('_gmd2html_shell. ',y + 1,',',ind_e - 1); 5570 ref(get('_gmd_command',1024,1),str_com); 5571 write('<div class=\"gmd_code_block\">$ '); 5572 len = find(str_com,0); 5573 write(str_com,len); 5574 write('<br/><br/>\n'); 5575 write(#-1,0,h(#-1)); 5576 run('rm.'); 5577 write('</div>\n'); 5578 copy(i[y],0,ind_e - y + 1,1,0); 5579 ): 5580 c==s_hrule ? (write_nl(); write('<hr/>\n')): 5581 5582 c==s_bold_italic_a ? write('<span class=\"gmd_bold_italic_a\">'): 5583 c==s_bold_italic_u ? write('<span class=\"gmd_bold_italic_u\">'): 5584 c==s_bold_a ? write('<span class=\"gmd_bold_a\">'): 5585 c==s_bold_u ? write('<span class=\"gmd_bold_u\">'): 5586 c==s_italic_a ? write('<span class=\"gmd_italic_a\">'): 5587 c==s_italic_u ? write('<span class=\"gmd_italic_u\">'): 5588 c==s_strikethrough? write('<span class=\"gmd_strikethrough\">'): 5589 c==s_underline? write('<span class=\"gmd_underline\">'): 5590 c==s_monospace ? write('<span class=\"gmd_monospace\">'): 5591 c==s_value_set ? write('<span class=\"gmd_value_set\">{'): 5592 c==e_value_set ? write('}</span>'): 5593 c==s_word_highlight ? write('<span class=\"gmd_word_highlight\">'): 5594 5595 c==s_url ? ( 5596 ind_e = find(#1,e_url,y); 5597 write('<a href=\"'); 5598 write(#1,y + 1,ind_e - y - 1); 5599 write('\" target=\"_blank\">'); 5600 ): 5601 c==e_url ? write('</a>'): 5602 5603 c==s_page_link ? ( 5604 ind_e = find(#1,e_page_link,y); 5605 run('_gmd2html_page_link. ',y + 1,',',ind_e - 1); 5606 ref(get('_gmd_link',1024,1),str_link); 5607 ref(get('_gmd_text',1024,1),str_text); 5608 write('<span class=\"gmd_page_link\"><a href=\"'); 5609 len = find(str_link,0); 5610 write(str_link,len); 5611 write('\">'); 5612 len = find(str_text,0); 5613 write(str_text,len); 5614 write('</a></span>'); 5615 copy(i[y],0,ind_e - y + 1,1,0); 5616 ): 5617 5618 c==s_text_link ? ( 5619 ind_m = find(#1,m_text_link,y); 5620 ind_e = find(#1,e_text_link,ind_m); 5621 write('<a href=\"'); 5622 write(#1,ind_m + 1,ind_e - ind_m - 1); 5623 i[ind_m + 1]==_'#' || crop(#1,0,ind_m + 1,1,15)=='https://gmic.eu'? 5624 write('\">'): # Local link 5625 write('\" target=\"_blank\">'); 5626 ): 5627 c==m_text_link ? ( 5628 ind_e = find(#1,e_text_link,y); 5629 copy(i[y],0,ind_e - y + 1,1,0); 5630 write('</a>'); 5631 ): 5632 5633 c==s_img ? ( 5634 ind_m = find(#1,m_img,y); 5635 ind_e = find(#1,e_img,ind_m); 5636 ind_d = find(#1,_'.',ind_e - 1,-1); 5637 is_video = 0; 5638 ind_d>ind_m?( # Check for a video 5639 ref(crop(#1,0,ind_d + 1,1,3),ext3); 5640 ref(crop(#1,0,ind_d + 1,1,4),ext4); 5641 is_video = ext3=='mp4' || ext3=='ogg' || ext4=='webm' 5642 ); 5643 is_video?( 5644 write('<video controls loop autoplay muted src=\"'); 5645 write(#1,ind_m + 1,ind_e - ind_m - 1); 5646 write('\">'); 5647 ):( 5648 write('<img class=\"gmd_image\" src=\"'); 5649 write(#1,ind_m + 1,ind_e - ind_m - 1); 5650 write('\" alt=\"'); 5651 write(#1,y + 1,ind_m - y - 1); 5652 write('\" title=\"'); 5653 ); 5654 ): 5655 c==m_img ? ( 5656 ind_e = find(#1,e_img,y); 5657 copy(i[y],0,ind_e - y + 1,1,0); 5658 is_video?write('</video>'):write('\"/>'); 5659 ): 5660 5661 c==s_pipeline ? ( 5662 ind_e = find(#1,e_pipeline,y); 5663 run('_gmd2html_pipeline. ',y + 1,',',ind_e - 1)?( # If output images 5664 ref(get('_gmd_command',1024,1),str_com); 5665 ref(get('_gmd_filename',1024,1),str_fil); 5666 write('<img class=\"gmd_image\" src=\"'); 5667 len = find(str_fil,0); 5668 write(str_fil,len); 5669 write('\" alt=\"'); 5670 len = find(str_com,0); 5671 write(str_com,len); 5672 write('\"/>'); 5673 ); 5674 copy(i[y],0,ind_e - y + 1,1,0); 5675 ): 5676 5677 c==s_formula ? ( 5678 ind_e = find(#1,e_formula,y); 5679 run('_gmd2html_formula. ',y + 1,',',ind_e - 1); 5680 ref(get('_gmd_filename',1024,1),str_fil); 5681 write('<img class=\"gmd_formula\" src=\"'); 5682 len = find(str_fil,0); 5683 write(str_fil,len); 5684 write('\" alt=\"'); 5685 ): 5686 c==e_formula ? write('\"/>'): 5687 5688 c==s_gmic ? write('<span class=\"gmd_gmic\">G'MIC</span>'): 5689 c==s_whitespace ? write(' '): 5690 c==s_tab ? write(' '); 5691 ); 5692 end(resize(#0,1,_write_off,1,1,0))" 5693 k[0] autocrop 0 nm $fnm.html 5694 endl done 5695 5696 # Embed with header and footer if needed. 5697 if $embed_html 5698 section_title=${"arg "$embed_html",Reference,Tutorial,News"} 5699 repeat $! l[$>] nm={b} nm0=${nm$>} 5700 if ['${title$>}']!=0 title=${title$>} else title=$nm0 fi 5701 if isfile('../style.css') style="../style.css" else style="https://gmic.eu/style.css" fi 5702 i[0] ('"<!DOCTYPE html>"\n\ 5703"<html lang=\"en\">"\n\ 5704" <head>"\n\ 5705" <meta charset=\"utf-8\">"\n\ 5706" <link rel=\"stylesheet\" href=\""$style"\">"\n\ 5707" <title>"$title"</title>"\n\ 5708" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 5709" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 5710" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 5711" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\ 5712" </head>"\n\n\ 5713" <body>"\n\ 5714" <div id=\"include_header\"></div>"\n\n\ 5715" <div class=\"section_title\"><p>"$section_title"</p></div><div class=\"section_content\">"\n\n\ 5716"<!-- begin_content -->"\n\n':y) 5717 ('\n\n\ 5718"<!-- end_content -->"\n\n\ 5719" </div><div class=\"section_end\"></div>"\n\n\ 5720" <div id=\"include_footer\"></div>"\n\ 5721" </body>"':y) 5722 a y nm $nm.html 5723 endl done 5724 fi 5725 5726# Manage sections / subsections / subsubsections / subsubsubsections. 5727_gmd2html_section : 5728 +rows. $1,$2 strvar {t} _gmd_name=${} rm. 5729 5730# Manage page links. 5731_gmd2html_page_link : 5732 +rows. $1,$2 5733 if i==_'-' # Force link to a G'MIC reference page 5734 rows. 1,100% _gmd_text={t} strvar {t} varname=${} 5735 if ['$varname']=='index' varname=_index fi 5736 _gmd_link=https://gmic.eu/reference/$varname.html 5737 else 5738 basename {t} _gmd_text=${} strvar $_gmd_text varname=${} 5739 if ['$varname']=='index' varname=_index fi 5740 _gmd_link=$varname.html 5741 fi 5742 rm. 5743 5744# Manage pipeline execution and result saving. 5745_gmd2html_pipeline : 5746 +rows. $1,$2 5747 _gmd_command={t} rm. 5748 strcasevar $_gmd_command 5749 _gmd_filename=img/${}.png 5750 is_output={fsize(['$_gmd_filename'])} 5751 if !isfile(['$_gmd_filename']) l[] 5752 l[] 5753 run $_gmd_command a x 5754 if !$!" || "($!==1" && "!h) is_output=0 fi 5755 onfail 5756 rm error[] "Command '"$_gmd_command"': "${} 5757 endl 5758 if $! 5759 if !isdir('img') x "mkdir -p img" fi 5760 o. $_gmd_filename rm. 5761 fi 5762 endl fi 5763 ({'$_gmd_command'}) 5764 _gmd_ascii2html. 5765 _gmd_command={t} rm. 5766 u $is_output 5767 5768# Convert formula to image (using LaTeX). 5769_gmd2html_formula : 5770 +rows. $1,$2 replace. {'\n'},{'" "'} j.. .,0,$1 5771 formula={/{t}} rm. 5772 strcasevar $formula varname=${} 5773 _gmd_filename=img/$varname.png 5774 if !isfile(['$_gmd_filename']) l[] 5775 ({'"\\documentclass[preview]{standalone}"\n\ 5776 "\\usepackage{amsmath,amssymb,amsfonts}"\n\ 5777 "\\pagestyle{empty}"\n\ 5778 "\\begin{document}"\n\ 5779 "\\begin{align*}"\n\ 5780 $formula\n\ 5781 "\\end{align*}"\n\ 5782 "\\end{document}"'}) 5783 path_tmp=${-path_tmp} 5784 ot. ${path_tmp}$varname.tex rm. 5785 x "cd "$path_tmp"; rm -f "$varname".pdf; pdflatex -interaction=nonstopmode "$varname".tex >/dev/null" 5786 if isfile(['${path_tmp}$varname.pdf']) 5787 i ${path_tmp}$varname.pdf,800 5788 autocrop. lt. 128 r2dy. 20% n. 0,255 channels. -3,0 5789 if !isdir('img') x "mkdir -p img" fi 5790 o. $_gmd_filename 5791 fi 5792 rm 5793 endl fi 5794 5795# Manage shell execution. 5796_gmd2html_shell : 5797 _gmd_shell. $* 5798 _gmd_ascii2html. 5799 5800_gmd2ascii_shell : 5801 _gmd_shell. $* 5802 5803_gmd_shell : 5804 +rows. $1,$2 _gmd_command={t} rm. 5805 path_tmp=${-path_tmp} 5806 strcasevar $_gmd_command 5807 filename=$path_tmp${}.log 5808 x $_gmd_command" > "$filename" 2>&1" 5809 if isfile(['$filename']) it $filename else 0 fi 5810 autocrop. {'\n'} 5811 5812# Convert an ascii buffer into html. 5813_gmd_ascii2html : 5814 repeat $! l[$>] 5815 . # [0] = Output, [1] = Input 5816 eval. "> 5817 begin("${-_gmd_write}${-_gmd_vt100}" spans = 0); 5818 c = i; 5819 c==_'&'?write('&'): 5820 c==_'\"'?write('"'): 5821 c==_'\''?write('''): 5822 c==_'<'?write('<'): 5823 c==_'>'?write('>'): 5824 c==_'\n'?write('<br/>\n'): 5825 c==_'\33' && j[1]==_'['?( # VT100 sequence 5826 ref(crop(0,y,1,8),C); 5827 same(C,vt100_b,size(vt100_b))?( 5828 write('<span class=\"gmd_bold_a\">'); 5829 copy(i[y],0,size(vt100_b),1,0); 5830 ++spans 5831 ):same(C,vt100_c,size(vt100_c))?( 5832 write('<span style=\"color: darkcyan\">'); 5833 copy(i[y],0,size(vt100_c),1,0); 5834 ++spans 5835 ): 5836 same(C,vt100_g,size(vt100_g))?( 5837 write('<span style=\"color: darkgreen\">'); 5838 copy(i[y],0,size(vt100_g),1,0); 5839 ++spans 5840 ): 5841 same(C,vt100_i,size(vt100_i))?( 5842 write('<span class=\"gmd_italic_a\">'); 5843 copy(i[y],0,size(vt100_i),1,0); 5844 ++spans 5845 ): 5846 same(C,vt100_m,size(vt100_m))?( 5847 write('<span style=\"color: darkmagenta\">'); 5848 copy(i[y],0,size(vt100_m),1,0); 5849 ++spans 5850 ): 5851 same(C,vt100_n,size(vt100_n))?( 5852 repeat (spans,write('</span>')); 5853 copy(i[y],0,size(vt100_n),1,0); 5854 spans = 0 5855 ): 5856 same(C,vt100_r,size(vt100_r))?( 5857 write('<span style=\"color: darkred\">'); 5858 copy(i[y],0,size(vt100_r),1,0); 5859 ++spans 5860 ): 5861 same(C,vt100_s,size(vt100_s))?( 5862 write('<span class=\"gmd_strikethrough\">'); 5863 copy(i[y],0,size(vt100_s),1,0); 5864 ++spans 5865 ): 5866 same(C,vt100_u,size(vt100_u))?( 5867 write('<span class=\"gmd_underline\">'); 5868 copy(i[y],0,size(vt100_u),1,0); 5869 ++spans 5870 ): 5871 write(c) 5872 ):write(c); 5873 " 5874 k[0] discard 0 5875 endl done 5876 5877#@cli gmd2ascii : _max_line_length>0,_indent_forced_newlines>=0 : (no arg) 5878#@cli : Convert selected gmd-formatted text images to ascii format. 5879#@cli : Default values: 'max_line_length=80' and 'indent_forced_newline=0'. 5880gmd2ascii : 5881 is_arg=1 l[] check "isint(${1=80}) && $1>0 && isint(${2=0}) && $2>=0" onfail is_arg=0 endl 5882 max_line_length,indent_forced_newline=${1-2} 5883 if !$is_arg 5884 if !narg($_shell_cols) _shell_cols={${-shell_cols}-5} fi 5885 max_line_length,indent_newline=$_shell_cols,0 noarg 5886 fi 5887 5888 use_vt100 parse_gmd 5889 repeat $! l[$>] nm={b} strvar $nm fnm=${} 5890 . # [0] = Output, [1] = Input 5891 eval. "> 5892 begin("${-_gmd_tokens}${-_gmd_write}${-_gmd_vt100}" 5893 is_blockquote = is_code_block = is_center = is_right = 0; 5894 ref(vector1024(),tmp); 5895 const nbcols = "${-shell_cols}"; 5896 ref(vector(#nbcols,_' '),whiteline); 5897 ); 5898 c = i; 5899 5900 c==_'\n'?( 5901 is_blockquote ? write([vt100_n,'\n > ',vt100_m]): 5902 is_code_block ? write('\n '): 5903 write(c); 5904 is_center ? write(whiteline,nbcols/4): 5905 is_right ? write(whiteline,nbcols/2); 5906 ): 5907 c>0?write(c): 5908 ( 5909 isin(c,e_bold_a,e_bold_u,e_bold_italic_a,e_bold_italic_u,e_italic_a,e_italic_u, 5910 e_strikethrough,e_underline,e_url,e_page_link,e_formula) ? write(vt100_n): 5911 isin(c,e_bullet,e_subbullet,e_subsubbullet) ? write(_'\n'): 5912 isin(c,e_section,e_subsection,e_subsubsection,e_subsubsubsection) ? write([vt100_n,'\n\n']): 5913 5914 c==s_section ? (write_nl(); write([_'\n',vt100_r,vt100_b,'# '])): 5915 c==s_subsection ? (write_nl(); write([_'\n',vt100_r,vt100_b,'## '])): 5916 c==s_subsubsection ? (write_nl(); write([_'\n',vt100_r,vt100_b,'### '])): 5917 c==s_subsubsubsection ? (write_nl(); write([_'\n',vt100_r,vt100_b,'#### '])): 5918 c==s_anchor ? ( 5919 ind_e = find(#1,e_anchor,y); 5920 copy(i[y],0,ind_e - y + 1,1,0); 5921 ): 5922 c==s_bullet ? write(' * '): 5923 c==s_subbullet ? write(' - '): 5924 c==s_subsubbullet ? write(' + '): 5925 c==s_center ? (write(whiteline,nbcols/4); is_center = 1): 5926 c==e_center ? (write(_'\n'); is_center = 0): 5927 c==s_right ? (write(whiteline,nbcols/2); is_right = 1): 5928 c==e_right ? (write(_'\n'); is_right = 0): 5929 c==s_tab ? write(whiteline,4): 5930 isin(c,s_table,s_htable,s_vtable,s_hvtable,n_table) ? (write_nl(); write([vt100_r,' | ',vt100_n])): 5931 c==m_table ? write([vt100_r,' | ',vt100_n]): 5932 c==s_blockquote ? (write([[' > '],vt100_m]); is_blockquote = 1): 5933 c==e_blockquote ? (write([vt100_n,'\n']); is_blockquote = 0): 5934 c==s_detail_block ? ( 5935 ny = y + 1; 5936 nc = j[1]; 5937 nc!=e_detail_block?( 5938 j[1] = 0; 5939 ind_e = find(#1,e_detail_block,ny); 5940 nc==_' '?( # Has a title 5941 ind_nl = find(#1,_'\n',ny); 5942 ind_nl<0 || ind_nl>ind_e?(ind_nl = ind_e); 5943 write([vt100_c,vt100_b,'+ ']); 5944 write(#1,y + 2,ind_nl - y - 2); 5945 write([vt100_n,vt100_c,'\n\n']); 5946 copy(i[ny],0,ind_nl - y - 1,1,0); 5947 i[ind_nl]!=e_detail_block?(i[ind_nl] = 0); 5948 ):write([vt100_c,vt100_b,'Details:',vt100_n,vt100_c,'\n\n']); 5949 ) 5950 ): 5951 c==e_detail_block ? write([vt100_n,'\n']): 5952 c==s_code_block ? (_write_off?write(_'\n'); write([[' '],vt100_c]); is_code_block = 1): 5953 c==e_code_block ? (write([vt100_n,'\n\n']); is_code_block = 0): 5954 c==s_shell ? ( 5955 ind_e = find(#1,e_shell,y); 5956 run('_gmd2ascii_shell. ',y + 1,',',ind_e - 1); 5957 ref(get('_gmd_command',1024,1),str_com); 5958 write('$ '); 5959 len = find(str_com,0); 5960 write(str_com,len); 5961 write('\n\n'); 5962 write(#-1,0,h(#-1)); 5963 run('rm.'); 5964 write(_'\n'); 5965 copy(i[y],0,ind_e - y + 1,1,0); 5966 ): 5967 c==s_hrule ? (write_nl(); write('+------------------------------+\n')): 5968 5969 c==s_bold_italic_a ? write([vt100_m,vt100_b,vt100_i]): 5970 c==s_bold_italic_u ? write([vt100_b,vt100_i]): 5971 c==s_bold_a ? write([vt100_m,vt100_b]): 5972 c==s_bold_u ? write(vt100_b): 5973 c==s_italic_a ? write([vt100_m,vt100_i]): 5974 c==s_italic_u ? write(vt100_i): 5975 c==s_strikethrough? write(vt100_s): 5976 c==s_underline? write(vt100_u): 5977 c==s_monospace ? write([_'\47',vt100_c]): 5978 c==e_monospace ? write([vt100_n,_'\47']): 5979 c==s_value_set ? write([vt100_g,vt100_i,_'{']): 5980 c==e_value_set ? write([_'}',vt100_n]): 5981 c==s_word_highlight ? write([_'\47',vt100_g]): 5982 c==e_word_highlight ? write([vt100_n,_'\47']): 5983 5984 isin(c,s_url,s_page_link,s_text_link) ? write(vt100_u): 5985 c==m_text_link ? ( 5986 ind = find(#1,e_text_link,y); 5987 copy(i[y],0,ind - y + 1,1,0); 5988 write(vt100_n); 5989 ): 5990 c==s_img ? ( 5991 ind_m = find(#1,m_img,y); 5992 ind_e = find(#1,e_img,ind_m); 5993 write(vt100_u); 5994 write(#1,ind_m + 1,ind_e - ind_m -1); 5995 write([vt100_n,_' ',vt100_g,vt100_i,'[image: \'']); 5996 ): 5997 c==m_img ? ( 5998 ind = find(#1,e_img,y); 5999 copy(i[y],0,ind - y + 1,1,0); 6000 write([['\']'],vt100_n]); 6001 ): 6002 c==s_pipeline ? ( 6003 ind = find(#1,e_pipeline); 6004 write([vt100_g,vt100_i,'[image]',vt100_n]); 6005 copy(i[y],0,ind - y + 1,1,0); 6006 ): 6007 c==s_formula ? write(vt100_g); 6008 6009 c==s_gmic ? ( 6010 write([vt100_b,'G\47MIC',vt100_n]); 6011 ): 6012 c==s_whitespace ? write(_' '); 6013 ); 6014 end(resize(#0,1,_write_off,1,1,0))" 6015 k[0] discard 0 6016 _gmd2ascii_cut $max_line_length,$indent_forced_newline 6017 nm $fnm.txt 6018 6019 endl done 6020 6021# Cut long ascii lines in selected text images (ignoring the VT100 codes for the length). 6022# $1: Max length of each line >0. 6023# $2: Indentation put after each forced newline. 6024_gmd2ascii_cut : 6025 repeat $! l[$>] 6026 . # [0] = Output, [1] = Input 6027 eval ${-_gmd_write}" 6028 const N = max(8,$1); 6029 ref(vector(#$2+1,_' '),nl); nl[0] = _'\n'; 6030 6031 # p = pos of block start, q = pos of latest endable (>=p), l = text length in block (w/o VT100 codes). 6032 p = q = r = 0; l = 1; 6033 while (r<h, 6034 i[r]=='\33' && i[r + 1]==_'['?( # VT100-code -> ignore 6035 while (i[r++]!=_'m', 0); 6036 ):i[r]==_'\n'?( 6037 len = r - p + 1; 6038 write(#1,p,len); 6039 p = q = r + 1; 6040 l = 0; 6041 ):l>N?( 6042 q - p<0.6*N?(q = r - 1); 6043 len = q - p + 1; 6044 write(#1,p,len); 6045 write(nl); 6046 p = r = ++q; 6047 l = size(nl) - 1; 6048 ):( 6049 isin(i[r],_',',_' ')?(q = r); 6050 ); 6051 ++r; ++l; 6052 ); 6053 p<h?(len = h - p; write(#1,p,len))" 6054 6055 k[0] autocrop 0 6056 endl done 6057 6058# Define variables associated to markdown tokens, for the math parser. 6059_gmd_tokens : 6060 u "const s_section = -1; 6061 const e_section = -2; 6062 const s_subsection = -3; 6063 const e_subsection = -4; 6064 const s_subsubsection = -5; 6065 const e_subsubsection = -6; 6066 const s_subsubsubsection = -7; 6067 const e_subsubsubsection = -8; 6068 const s_anchor = -9; 6069 const e_anchor = -10; 6070 const s_bullet = -11; 6071 const e_bullet = -12; 6072 const s_subbullet = -13; 6073 const e_subbullet = -14; 6074 const s_subsubbullet = -15; 6075 const e_subsubbullet = -16; 6076 const s_center = -17; 6077 const e_center = -18; 6078 const s_right = -19; 6079 const e_right = -20; 6080 const s_table = -21; 6081 const s_htable = -22; 6082 const s_vtable = -23; 6083 const s_hvtable = -24; 6084 const m_table = -25; 6085 const n_table = -26; 6086 const e_table = -27; 6087 const s_blockquote = -28; 6088 const e_blockquote = -29; 6089 const s_detail_block = -30; 6090 const e_detail_block = -31; 6091 const s_code_block = -32; 6092 const e_code_block = -33; 6093 const s_shell = -34; 6094 const e_shell = -35; 6095 const s_hrule = -36; 6096 6097 const s_bold_italic_a = -37; 6098 const e_bold_italic_a = -38; 6099 const s_bold_italic_u = -39; 6100 const e_bold_italic_u = -40; 6101 const s_bold_a = -41; 6102 const e_bold_a = -42; 6103 const s_bold_u = -43; 6104 const e_bold_u = -44; 6105 const s_italic_a = -45; 6106 const e_italic_a = -46; 6107 const s_italic_u = -47; 6108 const e_italic_u = -48; 6109 const s_strikethrough = -49; 6110 const e_strikethrough = -50; 6111 const s_underline = -51; 6112 const e_underline = -52; 6113 const s_monospace = -53; 6114 const e_monospace = -54; 6115 const s_value_set = -55; 6116 const e_value_set = -56; 6117 const s_word_highlight = -57; 6118 const e_word_highlight = -58; 6119 6120 const s_url = -59; 6121 const e_url = -60; 6122 const s_page_link = -61; 6123 const e_page_link = -62; 6124 const s_text_link = -63; 6125 const m_text_link = -64; 6126 const e_text_link = -65; 6127 const s_img = -66; 6128 const m_img = -67; 6129 const e_img = -68; 6130 const s_pipeline = -69; 6131 const e_pipeline = -70; 6132 const s_formula = -71; 6133 const e_formula = -72; 6134 6135 const s_gmic = -73; 6136 const e_gmic = -74; 6137 const s_whitespace = -75; 6138 const s_tab = -76;" 6139 6140# Define variables corresponding to VT100 sequences, for the math parser. 6141_gmd_vt100 : 6142 use_vt100 6143 u "ref('"$_vt100_b"',vt100_b); 6144 ref('"$_vt100_c"',vt100_c); 6145 ref('"$_vt100_g"',vt100_g); 6146 ref('"$_vt100_i"',vt100_i); 6147 ref('"$_vt100_m"',vt100_m); 6148 ref('"$_vt100_n"',vt100_n); 6149 ref('"$_vt100_r"',vt100_r); 6150 ref('"$_vt100_s"',vt100_s); 6151 ref('"$_vt100_u"',vt100_u);" 6152 6153# Define variables and functions to write strings and characters in a streamed way for the math parser. 6154_gmd_write : 6155 u "write(str) = write(str,0); 6156 write(str,len) = ( 6157 ref(str,_str); unref(_siz); const _siz = size(_str); ref(len,_len); 6158 _siz?( # String 6159 l = _len?_len:_siz; 6160 _write_off + l>h(#0)?resize(#0,1,8 + l + 5*h(#0)/3,1,1,0); 6161 copy(i[#0,_write_off],_str,l); 6162 _write_off+=l; 6163 ):( # Character 6164 _write_off>=h(#0)?resize(#0,1,8 + 5*h(#0)/3,1,1,0); 6165 i[#0,_write_off++] = _str; 6166 ) 6167 ); 6168 write(ind,start,len) = ( 6169 ref(len,_len); 6170 _write_off + _len>h(#0)?resize(#0,1,8 + _len + 5*h(#0)/3,1,1,0); 6171 copy(i[#0,_write_off],i[#ind,start],_len); 6172 _write_off+=_len; 6173 ); 6174 write_nl() = ( # Force newline 6175 i[#0,_write_off -1 ]!=_'\n'?write(_'\n'); 6176 ); 6177 _write_off = 0;" 6178 6179#@cli parse_gui : _outputmode,_{ * | filter_name} 6180#@cli : Parse selected filter definitions and generate info about filters in selected output mode. 6181#@cli : 'outputmode' can be { json | list | print | strings | update | zart }.\n 6182#@cli : It is possible to define a custom output mode, by implementing the following commands 6183#@cli : ('outputmode' must be replaced by the name of the custom user output mode): 6184#@cli : . 'parse_gui_outputmode' : A command that outputs the parsing information with a custom format. 6185#@cli : . 'parse_gui_parseparams_outputmode' (optional): A simple command that returns 0 or 1. It tells the parser \ 6186# whether parameters of matching filter must be analyzed (slower) or not. 6187#@cli : . 'parse_gui_trigger_outputmode' (optional): A command that is called by the parser just before parsing \ 6188# the set of each matching filters.\n 6189#@cli : Here is the list of global variables set by the parser, accessible in command 'parse_gui_outputmode':\n 6190#@cli : '$_nbfilters': Number of matching filters. 6191#@cli : '$_nongui' (stored as an image): All merged lines in the file that do not correspond to '#@gui' lines.\n 6192#@cli : For each filter `\#F` ('F' in range `[0,$_nbfilters-1]`): 6193#@cli : * '$_fF_name' : Filter name. 6194#@cli : * '$_fF_path' : Full path. 6195#@cli : * '$_fF_locale' : Filter locale (empty, if not specified). 6196#@cli : * '$_fF_command' : Filter command. 6197#@cli : * '$_fF_commandpreview' : Filter preview command (empty, if not specified). 6198#@cli : * '$_fF_zoomfactor' : Default zoom factor (empty, if not specified). 6199#@cli : * '$_fF_zoomaccurate' : Is preview accurate when zoom changes ? (can be { 0=false | 1=true }). 6200#@cli : * '$_fF_inputmode' : Default preferred input mode (empty, if not specified). 6201#@cli : * '$_fF_hide' : Path of filter hid by current filter (for localized filters, empty if not specified). 6202#@cli : * '$_fF_nbparams' : Number of parameters.\n 6203#@cli : For each parameter `\#P` of the filter \#F ('P' in range `[0,$_fF_nbparams-1]`): 6204#@cli : * '$_fF_pP_name' : Parameter name. 6205#@cli : * '$_fF_pP_type' : Parameter type. 6206#@cli : * '$_fF_pP_responsivity' : Parameter responsivity (can be { 0 | 1 }). 6207#@cli : * '$_fF_pP_visibility' : Parameter visibility. 6208#@cli : * '$_fF_pP_propagation' : Propagation of the parameter visibility. 6209#@cli : * '$_fF_pP_nbargs' : Number of parameter arguments.\n 6210#@cli : For each argument `\#A` of the parameter \#P ('A' in range `[0,$_fF_pP_nbargs-1]`): 6211#@cli : * '$_fF_pP_aA' : Argument value\n 6212#@cli : Default parameters: 'filter_name=*' and 'output_format=print'. 6213parse_gui : skip "${1=print},${2=*}" 6214 e[^-1] "Parse '#@gui' filters '$2' and output in '$1' mode." 6215 6216 # Check that specified output mode is actually implemented. 6217 l[] ({'$$parse_gui_$1'}) rm 6218 onfail error[0--2] "Command 'parse_gui': Invalid output mode '$1'." 6219 endl 6220 6221 # Input .gmic data. 6222 use_vt100 6223 if !$! l[] it ${_path_rc}update$_version.gmic onfail endl fi 6224 if !$! return fi 6225 y a y merge_multiline_comments 6226 6227 # Extract all filter chunks with full path. 6228 e[] "" 6229 e[] "\r > Extract filter chunks." 6230 macros=" 6231 is_blank(p) = ((_c=source[p])<=_' ' && _c!=_'\n'); 6232 skip_blank(p) = (while (is_blank(p), ++p)); 6233 clean(name) = ( 6234 _l = find(name,0); 6235 _l>0?( 6236 _p = 0; while (1, 6237 _p = find(name,_'<',_p); 6238 _p<0 || _p>=_l?break(); 6239 isin(name[_p+1],_'b',_'i') && name[_p+2]==_'>'?( # Opening tag 6240 copy(name[_p],name[_p+3],_l-_p-2); 6241 _l-=3; 6242 ):name[_p+1]==_'/' && isin(name[_p+2],_'b',_'i') && name[_p+3]==_'>'?( # Closing tag 6243 copy(name[_p],name[_p+4],_l-_p-3); 6244 _l-=4; 6245 ):++_p; 6246 ); 6247 _p = 0; while (1, _p = find(name,_'/',_p); _p<0 || _p>=_l?break(); name[_p++] = _'-'); # Replace '/' by '-' 6248 ); 6249 );" 6250 6251 eval $macros" 6252 store_block(p,q,path,name,hide) = ( 6253 run('+rows[0] ',p,',',q,' discard. -1 autocrop. 10 autocrop. 32 nm. \"',path,'/',name,'\"'); 6254 6255 # Insert hide() info at the end of the chunk, with magic number '-2'. 6256 hide[0]?run([40,45,50,44,123,39,34],hide,[34,39,125,41],' y. a[-2,-1] y'); 6257 ); 6258 6259 # Init variables. 6260 #---------------- 6261 ref(crop(),source); 6262 path = prev_path = name = prev_name = hide = prev_hide = vector1024(); 6263 6264 # Start parsing. 6265 #--------------- 6266 prev_p0 = p0 = p = 0; 6267 while (p<size(source), 6268 p = find(source,'#@gui',p)%size(source); 6269 6270 !p || (p>0 && source[p - 1]==_'\n')?( # Found line starting with '#@gui' 6271 p0 = p; # Remember starting position of line 6272 p+=5; 6273 source[p]==_'_' && (l = find(source,_' ',++p))>=0?(p = l + 1); # Skip locale 6274 6275 # Detect new filter, folder or hide() directive. 6276 #----------------------------------------------- 6277 skip_blank(p); 6278 source[p]!=_':'?( 6279 hide[0] = 0; 6280 q = find(source,_':',p)%size(source); 6281 r = find(source,_'\n',p)%size(source); 6282 is_hide = q>r && (l=find(source,'hide(',p)%size(source))<r; 6283 r<q && !is_hide?( 6284 6285 # Definition of a new folder. 6286 #---------------------------- 6287 r0 = r; while (is_blank(--r),0); 6288 copy(name,source[p],r-p+1); name[r-p+1] = 0; 6289 for (levelup = 0, name[levelup]==_'_', ++levelup); 6290 levelup?( 6291 copy(name,name[levelup],r-p+2-levelup); # Clean folder name 6292 while (levelup--, # Update path 6293 lp = find(path,0); l = max(0,find(path,_'/',lp-1,0)); path[l] = 0; 6294 ); 6295 ); 6296 clean(name); 6297 name[0]?( 6298 ln = find(name,0); # Update path 6299 lp = find(path,0); 6300 lp?(path[lp] = _'/'; copy(path[lp+1],name,ln); path[lp+ln+1] = 0):(copy(path,name,ln); path[ln] = 0); 6301 ); 6302 copy(i[#0,p0],-1,r0-p0+1,1,0); # Discard folder definition line (will be removed later) 6303 p = r0 + 1; 6304 ):!is_hide?( 6305 6306 # Definition of a new filter. 6307 #---------------------------- 6308 while (is_blank(--q),0); 6309 copy(name,source[p],q-p+1); name[q-p+1] = 0; 6310 clean(name); 6311 store_block(prev_p0,p0-1,prev_path,prev_name,prev_hide); 6312 6313 prev_p0 = p0; 6314 prev_path = path; 6315 prev_name = name; 6316 prev_hide = hide; 6317 p = q + 1; 6318 ):( 6319 6320 # Manage hide() directive. 6321 #-------------------------- 6322 l0 = l + 5; l = find(source,_')',l0); 6323 l<r?( 6324 copy(hide,source[l0],l-l0); hide[l-l0] = 0; 6325 copy(i[#0,p0],-1,r-p0+1,1,0); 6326 ); 6327 p = r + 1; 6328 ) 6329 ) 6330 ):++p 6331 ); 6332 prev_p0!=p0?store_block(prev_p0,size(source)-1,prev_path,prev_name,prev_hide) # Insert last block 6333 " 6334 rm[0] 6335 6336 # Isolate only requested filters. 6337 if "['$2']!='*'" 6338 1,$!,1,1," 6339 begin(ref(lowercase(['$2']),str)); 6340 ref(lowercase(name(#y)),nm); 6341 find(nm,str)>=0?y:-1" 6342 discard. -1 k[{^}] 6343 fi 6344 l parse_gui_trigger_$1 onfail endl # Allow global pre-processing before parsing each filter. 6345 6346 # Parse each filter. 6347 nbchunks=$! 6348 f=0 repeat $nbchunks,c _f${f}_path={$>,f} if {$>,h} l[$>] 6349 if crop(0,0,1,5)!='#@gui' # Non-gui : merge code and skip chunk 6350 autocrop {'\n'} store nongui$c 0 continue 6351 fi 6352 6353 # Init variables. 6354 _f${f}_locale= 6355 _f${f}_commandpreview= 6356 _f${f}_zoomfactor= 6357 _f${f}_zoomaccurate= 6358 _f${f}_inputmode= 6359 _f${f}_nbparams=0 6360 _f${f}_hide= 6361 6362 # Detect locale. 6363 if crop(0,0,1,6)=='#@gui_' _f${f}_locale={`crop(0,6,1,2)`} fi 6364 6365 # Detect hid filter. 6366 p={"find(#0,-2,h-1,0)"} 6367 if $p>=0 +rows. {$p+1},100% _f${f}_hide={t} rm. fi 6368 6369 # Separate '#@gui' lines from other lines, and merge them. 6370 eval $macros" 6371 ref(crop(),source); 6372 is_first = 1; 6373 p = 0; 6374 while (p<size(source), 6375 p = find(source,'#@gui',p)%size(source); 6376 !p || (p>0 && source[p - 1]==_'\n')?( # Found line starting with '#@gui' 6377 p0 = p; # Remember starting position of line 6378 p+=5; 6379 source[p]==_'_' && (l = find(source,_' ',++p))>=0?(p = l + 1); # Skip locale 6380 skip_blank(p); 6381 source[p]==_':'?(++p; skip_blank(p)); 6382 r = find(source,_'\n',p)%size(source); # Find end of line 6383 run('+rows[0] ',p,',',r); 6384 source[r]==_'\n'?(i[#-1,h(#-1)-1] = is_first?0:_' '); 6385 copy(i[#0,p0],-1,min(r,size(source)-1)-p0+1,1,0); # Part to be discarded 6386 p = r + 1; 6387 is_first = 0; 6388 ):++p 6389 )" 6390 a[^0] y discard.. -1 6391 autocrop[0] {'\n'} store[0] nongui$c 6392 s -,0 # Split in two images : definition and parameters 6393 f "max(_' ',i)" # Replace all blank characters by space 6394 6395 # Parse filter definition. 6396 l[0] 6397 _f${f}_zoomaccurate=0 6398 s -,{':'} autocrop {'" "'} 6399 _f${f}_name={`$macros" name=[['"{0,t}"'],0]; clean(name); name"`} rm[0] # Filter name 6400 if $! l[0] 6401 s -,{','} autocrop {'" "'} 6402 _f${f}_command={0,t} # Filter command 6403 if $!>1 l[1] 6404 s -,{'('} 6405 _f${f}_commandpreview={0,t} # Filter preview command 6406 if $!>1 l[1] 6407 s +,{'+'} 6408 discard[0] {')'} 6409 _f${f}_zoomfactor={0,t} # Default zoom factor 6410 if $!>1" && "i[0]==_'+' _f${f}_zoomaccurate=1 fi # Is zoom accurate ? 6411 endl fi 6412 endl fi 6413 rm 6414 endl fi 6415 if $! _f${f}_inputmode={0,t} fi # Default input mode 6416 rm 6417 endl 6418 e[] "\r > "$_vt100_c[#$f]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 6419 6420 # Parse filter parameters. 6421 parseparams=1 6422 l[] parseparams=${-parse_gui_parseparams_$1} onfail endl 6423 6424 if !$!" || "!$parseparams _f${f}_nbparams=0 6425 else 6426 eval $macros" 6427 ref(crop(),source); 6428 ref(vector256(),name); 6429 ref(vector256(),type); 6430 ref(vector65536(),argument); 6431 6432 p = nbparams = 0; 6433 while (p<size(source), 6434 q = find(source,_'=',p)%size(source); 6435 source[q]==_'='?( # Found new parameter 6436 skip_blank(p); 6437 r = q + 1; skip_blank(r); 6438 while (is_blank(--q),0); 6439 copy(name,source[p],q-p+1); name[q-p+1] = 0; # Parameter name 6440 store(name,'tmparg',q-p+1); 6441 p = r; 6442 q = min(find(source,_'(',p)%size(source), 6443 find(source,_'{',p)%size(source), 6444 find(source,_'[',p)%size(source)); 6445 c = source[q]==_'('?_')':source[q]==_'{'?_'}':_']'; 6446 r = q + 1; skip_blank(r); 6447 while (is_blank(--q),0); 6448 6449 responsivity = 1; 6450 source[p]==_'_'?(responsivity = 0; ++p); 6451 copy(type,source[p],q-p+1); type[q-p+1] = 0; # Parameter type 6452 for (i = 0, type[i], ++i, type[i] = lowercase(type[i])); # Force lowercase 6453 run('$tmparg _f"${f}"_p',nbparams,'_name={t} rm. _f"${f}"_p',nbparams,'_type=', 6454 type,' _f"${f}"_p',nbparams,'_responsivity=',responsivity); 6455 6456 # Parse list of arguments. 6457 p = r; 6458 r = find(source,c,p)%size(source); 6459 nbargs = 0; 6460 6461 type[0,5]==[['bool'],0] || 6462 type[0,7]==[['button'],0] || 6463 type[0,6]==[['value'],0] || 6464 type[0,7]==[['filein'],0] || 6465 type[0,8]==[['fileout'],0] || 6466 type[0,7]==[['folder'],0] || 6467 type[0,5]==[['note'],0] || 6468 type[0,10]==[['separator'],0]?( # Single-argument parameter 6469 p!=r?( 6470 skip_blank(p); 6471 pe = r; 6472 while (is_blank(--pe),0); 6473 copy(argument,source[p],pe-p+1); argument[pe-p+1] = 0; # Parameter argument 6474 store(argument,'tmparg',1,pe-p+1); run('$tmparg _f"${f}"_p',nbparams,'_a0={t} rm.'); 6475 nbargs = 1; 6476 ):(argument[0] = 0); 6477 p = r + 1; 6478 ):( # Multiple-arguments parameter -> parse list of arguments 6479 while (p<r, 6480 skip_blank(p); 6481 pe = q = min(r,find(source,_',',p)%size(source)); 6482 while (is_blank(--pe),0); 6483 copy(argument,source[p],pe-p+1); argument[pe-p+1] = 0; # Parameter argument 6484 store(argument,'tmparg',1,pe-p+1); run('$tmparg _f"${f}"_p',nbparams,'_a',nbargs,'={t} rm.'); 6485 ++nbargs; 6486 p = q + 1; 6487 ); 6488 ); 6489 run('_f"${f}"_p',nbparams,'_nbargs=',nbargs); 6490 6491 # Extract visibility state. 6492 p = r + 1; 6493 p<size(source) && source[p]==_'_' && isin(source[p+1],_'0',_'1',_'2')?( 6494 r = p + 1; 6495 run('_f"${f}"_p',nbparams,'_visibility=',source[r]-_'0'); 6496 isin(source[r+1],_'+',_'-',_'*')?run('_f"${f}"_p',nbparams,'_propagation=',[source[++r]]); 6497 ); 6498 6499 p = r + 1; 6500 skip_blank(p); 6501 source[p]==_','?++p; 6502 ++nbparams; 6503 ):++p; 6504 ); 6505 run('_f"${f}"_nbparams=',nbparams)" 6506 fi 6507 if !$! 0 fi 6508 f+=1 6509 endl fi done 6510 _nbfilters=$f rm 6511 6512 # Merge all non-gui code. 6513 repeat $nbchunks if narg(${nongui$>}) ${nongui$>} if !w rm. fi fi done 6514 if $! ('\n') a[^-1] .,y rm. a y else 0 fi 6515 store. _nongui 6516 6517 # Done! 6518 e[] "\r > "${_vt100_g}{`copy(vector64(_'" "'),'"Parsing done!"')`}$_vt100_n 6519 v + parse_gui_$1 # Output result of the parsing. 6520 6521# 6522# Implements 'print' mode for command 'parse_gui' (default output mode). 6523# 6524parse_gui_parseparams_print : u 0 # Tell parser to not parse filter parameters 6525parse_gui_trigger_print : sort_list +,n 6526parse_gui_print : 6527 e[] "\r"${_vt100_g}{`vector68(_'" "')`}$_vt100_n 6528 e[] " > "${_vt100_g}"List of matching filters:"$_vt100_n"\n\n" 6529 repeat $_nbfilters 6530 +e[] " [#"{1+$>}"] "${_f$>_path}${_f$>_name} 6531 done 6532 6533# 6534# Implements 'whatsnew' mode for command 'parse_gui'. 6535# 6536parse_gui_parseparams_whatsnew : u 0 # Tell parser to not parse filter parameters 6537parse_gui_whatsnew : 6538 e[] " >> Generate output, in 'whatsnew' mode.\n" 6539 l[] 6540 1,1,1,1x$_nbfilters 6541 repeat $! nm[$>] -${_f$>_path}${_f$>_name} f[$>] $> done 6542 sort_list +,n a x 6543 repeat w n={0,i[$>]} ('${_f${n}_path}" "${_f${n}_name}\n') done 6544 rm[0] 6545 endl 6546 y a y 6547 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 6548 6549# 6550# Implements 'list' mode for command 'parse_gui'. 6551# 6552parse_gui_parseparams_list : u 0 # Tell parser to not parse filter parameters 6553parse_gui_list : 6554 e[] " >> Generate output, in 'list' mode.\n" 6555 ('"*** List of filters in the G\47MIC plug-in ("$_nbfilters" filters, on "\ 6556 {`v=date(1);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}"/"\ 6557 {`v=date(2);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}", "\ 6558 {`v=date(4);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}":"\ 6559 {`v=date(5);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}") ***\n\n"') 6560 6561 ('"* List of filters, sorted by path:\n\n"') 6562 l[] 6563 1,1,1,1x$_nbfilters 6564 repeat $! nm[$>] -${_f$>_path}${_f$>_name} f[$>] $> done 6565 sort_list +,n a x 6566 repeat w n={0,i[$>]} 6567 ('${_f${n}_path}${_f${n}_name}" (command: '"${_f${n}_command}"')\n"') 6568 done 6569 rm[0] 6570 endl 6571 6572 ('"\n* List of filters, sorted alphabetically:\n\n"') 6573 l[] 6574 1,1,1,1x$_nbfilters 6575 repeat $! nm[$>] -${_f$>_name} f[$>] $> done 6576 sort_list +,n a x 6577 repeat w n={0,i[$>]} 6578 ('${_f${n}_name}" (in '"${_f${n}_path}"')\n"') 6579 done 6580 rm[0] 6581 endl 6582 6583 ('"\n*** End of list ***\n"') 6584 y a y 6585 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 6586 6587# 6588# Implements 'update' mode for command 'parse_gui'. 6589# 6590parse_gui_parseparams_update : u 1 # Tell parser to parse filter parameters 6591parse_gui_update : 6592 e[] " >> Generate output, in 'update' mode.\n" 6593 path=/ 6594 N={$_nbfilters-1} 6595 is_af={date([1,2])==[4,1]" && "(date(4)%2)} # April fool mode ? 6596 repeat $_nbfilters,f 6597 e[] "\r >> "$_vt100_c[#$f/$N]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 6598 6599 # Insert directives to change folder if necessary. 6600 if ;['$path']!=['${_f${f}_path}'] 6601 command_path={`" 6602 src = ['"$path"']; 6603 dest = ['"${_f${f}_path}'"]; 6604 ref(vector1024(),command); 6605 for (p = 0, p<min(size(src),size(dest)) && src[p]==dest[p], ++p); # Find common base 6606 while (p>0 && src[p]!=_'/' && dest[p]!=_'/', --p); 6607 6608 nb_levelup = 0; 6609 for (q = p + 1, q<size(src), ++nb_levelup, q = find(src,_'/',q) + 1); 6610 nb_levelup?(copy(command,'#@gui '); copy(command[6],_'_',nb_levelup,1,0)); 6611 6612 is_testing = !find(dest,'Testing/'); 6613 is_about = !find(dest,'About/'); 6614 6615 dest[p]==_'/'?++p; 6616 while (p<size(dest), 6617 q = find(dest,_'/',p)%size(dest); 6618 eoc = find(command,0); 6619 !eoc || command[eoc-1]!=_'_'?(copy(command[eoc],'#@gui '); eoc+=6); 6620 is_italic = (is_testing && find(dest,'Testing/',p)<0) || is_about; 6621 copy(command[eoc],is_italic?'<i>':'<b>'); 6622 copy(command[eoc + 3],dest[p],q-p); 6623 copy(command[eoc + 3 + q - p],is_italic?'</i>\n':'</b>\n'); 6624 p = q + 1; 6625 ); command"`} 6626 ('$command_path\n') 6627 fi 6628 6629 path=${_f${f}_path} 6630 6631 if narg(${_f${f}_commandpreview}) commandpreview=,${_f${f}_commandpreview} else commandpreview= fi 6632 if narg(${_f${f}_locale}) locale=_${_f${f}_locale} else locale= fi 6633 if narg(${_f${f}_zoomfactor}) zoomfactor=(${_f${f}_zoomfactor}) else zoomfactor= fi 6634 if ${_f${f}_zoomaccurate} zoomaccurate=+ else zoomaccurate= fi 6635 if narg(${_f${f}_inputmode}) inputmode=" : "${_f${f}_inputmode} else inputmode= fi 6636 strcapitalize ${_f${f}_name} name=${} 6637 6638 if ['${_f${f}_hide}']!=0 ('"#@gui"$locale" hide("${_f${f}_hide}")\n"') fi 6639 ('"#@gui"$locale" "$name:${_f${f}_command}$commandpreview$zoomfactor$zoomaccurate$inputmode\n') 6640 6641 repeat ${_f${f}_nbparams},p 6642 responsivity,visibility= 6643 if !${_f${f}_p${p}_responsivity} responsivity=_ fi 6644 if narg(${_f${f}_p${p}_visibility}) visibility=_${_f${f}_p${p}_visibility}${_f${f}_p${p}_propagation} fi 6645 is_choice={['${_f${f}_p${p}_type}']=='choice'} 6646 is_color={['${_f${f}_p${p}_type}']=='color'} 6647 6648 # Build list of arguments. 6649 args= c= 6650 if $is_choice # Capitalize arguments of choice() 6651 repeat ${_f${f}_p${p}_nbargs},a 6652 if $is_af straprilfool ${_f${f}_p${p}_a${a}} 6653 else strcapitalize ${_f${f}_p${p}_a${a}} 6654 fi 6655 args.=$c${} c=, done 6656 elif $is_color # Force html color code for color() 6657 if inrange(${_f${f}_p${p}_nbargs},3,4)" && "\ 6658 inrange(${_f${f}_p${p}_a0},0,255)" && "\ 6659 inrange(${_f${f}_p${p}_a1},0,255)" && "\ 6660 inrange(${_f${f}_p${p}_a2},0,255)" && "\ 6661 (${_f${f}_p${p}_nbargs}==3" || "inrange(${_f${f}_p${p}_a3},0,255)) 6662 args=# 6663 repeat ${_f${f}_p${p}_nbargs},a 6664 args.={`"tab = [ _'0',_'1',_'2',_'3',_'4',_'5',_'6',_'7',_'8',_'9',_'a',_'b',_'c',_'d',_'e',_'f' ]; 6665 const v = "${_f${f}_p${p}_a${a}}"; [ tab[(v>>4)&15],tab[v&15] ]"`} 6666 done 6667 else repeat ${_f${f}_p${p}_nbargs},a args.=$c${_f${f}_p${p}_a${a}} c=, done 6668 fi 6669 else 6670 repeat ${_f${f}_p${p}_nbargs},a args.=$c${_f${f}_p${p}_a${a}} c=, done 6671 fi 6672 sep1,sep2={`" 6673 s = ['"$args"']; 6674 size(s)?( 6675 find(s,_'(')<0 && find(s,_')')<0?[_'(',_',',_')']: 6676 find(s,_'{')<0 && find(s,_'}')<0?[_'{',_',',_'}']: 6677 [_'[',_',',_']'] 6678 ):[_'(',_',',_')']; 6679 "`} 6680 if s=['${_f${f}_p${p}_type}'];"s=='link' || s=='note' || s=='separator' || s=='value'" name=_ 6681 else strcapitalize ${_f${f}_p${p}_name} name=${} 6682 fi 6683 ('"#@gui"$locale" :"{/$name}=$responsivity${_f${f}_p${p}_type}{``$sep1}{``{/$args}}{``$sep2}$visibility\n') 6684 6685 done 6686 done 6687# repeat $! l[$>] utf82html endl done 6688 $_nongui y a y 6689 6690 # Clean generated output, add footer and header. 6691 compress_gmic. 6692 i[0] ('"#@gmic"\n\ 6693 "#"\n\ 6694 "# File : update"$_version".gmic"\n\ 6695 "# ( G\47MIC command file )"\n\ 6696 "#"\n\ 6697 "# Description : Update file for G\47MIC commands and filters (for version "${-strver}")."\n\ 6698 "# ( https://gmic.eu )"\n\ 6699 "#"\n\ 6700 "# License : CeCILL v2.1"\n\ 6701 "# ( https://cecill.info/licences/Licence_CeCILL_V2.1-en.html )"\n\ 6702 "#"\n\ 6703 "# Generated on : "\ 6704 {date(0)}"/"\ 6705 {`v=date(1);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}"/"\ 6706 {`v=date(2);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}", "\ 6707 {`v=date(4);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}":"\ 6708 {`v=date(5);sv=vtos(v);v<10?[_'0',sv]:[sv,0]`}\n\ 6709 "#"\n') 6710 ('"\n# Local Variables:"\n\ 6711 "# mode: sh"\n\ 6712 "# End:"\n\ 6713 "#"\n\ 6714 "# (End of G\47MIC update file)"') 6715 y a y 6716 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 6717 6718# April Fool version! 6719straprilfool : skip "${1=}" 6720 if ['"$1"']==0 u "" return fi 6721 l[] ('{/"$1"}') 6722 f "(i<=_' ' || i==_'_') && i!=_'\n'?_' ':i" # Replace blank characters and underscores 6723 f "x%2?lowercase(i):uppercase(i)" 6724 f "c = lowercase(i); 6725 c==_'o'?_'0': 6726 c==_'i'?_'1': 6727 c==_'e'?_'3': 6728 c==_'a'?_'4': 6729 c==_'s'?_'5': 6730 c==_'t'?_'7': 6731 c==_'b'?_'8': 6732 i" 6733 u {t} rm endl 6734 6735# 6736# Implements 'json' mode for command 'parse_gui'. 6737# 6738parse_gui_parseparams_json : u 1 # Tell parser to not parse filter parameters 6739parse_gui_trigger_json : 6740 repeat $! l[$>] # Keep only 1-level folders 6741 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`} 6742 endl done 6743 sort_list +,n 6744 6745parse_gui_json : 6746 e[] " >> Generate output, in 'json' mode.\n" 6747 ('"{\n \"format_version\": \"gmic_json_1.0\",\n \"gmic_version\": \""${-strver}"\",\n \"categories\": [\n"') 6748 6749 current_category= 6750 N={$_nbfilters-1} 6751 repeat $_nbfilters,f 6752 e[] "\r >> "$_vt100_c[#$f/$N]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 6753 6754 # Manage categories. 6755 0 nm. {`s=['${_f${f}_path}'];s[0,size(s)-1]`} _parse_gui_json[] {b} path=${} rm. 6756 if ['$current_category']!=['$path'] 6757 if ['$current_category']!=0 ('" ]\n },\n"') fi 6758 ('" {\n"') 6759 ('" \"name\": \""$path"\", \"filters\": [\n"') 6760 current_category=$path 6761 else 6762 if i[-1,2]==_'\n' z. 0,{w-2} fi 6763 ('",\n"') 6764 fi 6765 6766 # Filter definition. 6767 _parse_gui_json[] ${_f${f}_name} fname=${} 6768 6769 locale=en 6770 if narg(${_f${f}_locale}) locale=${_f${f}_locale} fi 6771 6772 ('" {\n \"name\": \""$fname"\", \"lang\": \""$locale"\", \"command\": \""${_f${f}_command}"\", "\ 6773 "\"command_preview\": \""${_f${f}_commandpreview}"\", \"parameters\": [\n"') 6774 6775 sepf={`$<?_',':0`} 6776 ppos=1 6777 repeat ${_f${f}_nbparams},p 6778 _parse_gui_json ${_f${f}_p{$p}_name} name={/${}} 6779 type=${_f${f}_p{$p}_type} 6780 nbargs=${_f${f}_p{$p}_nbargs} 6781 arg0= repeat $nbargs ('${_f${f}_p${p}_a$>}') autocrop. {'\"'} _parse_gui_json {t} arg$>=${} rm. done 6782 sepp={`$<?_',':0`} 6783 if narg(${_f${f}_p{$p}_visibility}) 6784 visibility=", \"visibility\": \""${_f${f}_p{$p}_visibility}"\"" 6785 else 6786 visibility= 6787 fi 6788 6789 if ['$type']=='bool' 6790 if lowercase(['$arg0'])=='false' arg0=0 elif lowercase(['$arg0'])=='true' arg0=1 elif !isnum($arg0) arg0=0 fi 6791 ('" { \"type\": \"bool\", \"name\": \""$name"\", \"default\": \""$arg0"\", \"pos\": "\ 6792 "\""$ppos"\""$visibility" }"$sepp\n') 6793 ppos+=1 6794 6795 elif ['$type']=='button' 6796 if narg($arg0) alignment=", \"alignment\": \""$arg0"\"" else alignment= fi 6797 ('" { \"type\": \"button\", \"name\": \""$name"\""$alignment", \"pos\": \""$ppos"\""$visibility" }"\ 6798 $sepp\n') 6799 ppos+=1 6800 6801 elif ['$type']=='choice' 6802 default=0 n=0 choices= 6803 l[] if isint($arg0) default=$arg0 n+=1 fi onfail endl 6804 c= repeat $nbargs-$n,a choices.=${c}"\""$>"\": \""${arg{$n+$a}}"\"" c=", " done 6805 ('" { \"type\": \"choice\", \"name\": \""$name"\", \"default\": \""$default"\", \"pos\": \""$ppos"\", "\ 6806 "\"choices\": { "$choices" }"$visibility" }"$sepp\n') 6807 ppos+=1 6808 6809 elif ['$type']=='color' 6810 args= c= repeat $nbargs,a args.=$c${arg$a} c="," done 6811 ('" { \"type\": \"color\", \"name\": \""$name"\", \"default\": \""$args"\", \"pos\": "\ 6812 "\""$ppos"\""$visibility" }"$sepp\n') 6813 ppos+=$nbargs 6814 6815 elif s=['$type'];s=='int' 6816 ('" { \"type\": \"int\", \"name\": \""$name"\", \"default\": \""$arg0"\", \"min\": \""$arg1"\", "\ 6817 "\"max\": \""$arg2"\", \"pos\": \""$ppos"\""$visibility" }"$sepp\n') 6818 ppos+=1 6819 6820 elif s=['$type'];s=='float' 6821 ('" { \"type\": \"float\", \"name\": \""$name"\", \"default\": \""$arg0"\", \"min\": \""$arg1"\", "\ 6822 "\"max\": \""$arg2"\", \"pos\": \""$ppos"\""$visibility" }"$sepp\n') 6823 ppos+=1 6824 6825 elif ['$type']=='file'" || "['$type']=='filein'" || "['$type']=='fileout' 6826 ('" { \"type\": \"file\", \"name\": \""$name"\", \"default\": \""{/$arg0}"\", \"pos\": "\ 6827 "\""$ppos"\""$visibility" }"$sepp\n') 6828 ppos+=1 6829 6830 elif ['$type']=='folder' 6831 ('" { \"type\": \"folder\", \"name\": \""$name"\", \"default\": \""{/$arg0}"\", \"pos\": "\ 6832 "\""$ppos"\""$visibility" }"$sepp\n') 6833 ppos+=1 6834 6835 elif ['$type']=='link' 6836 align=-1 name= url= n=0 6837 l[] if isnum($arg0) align=$arg0 n+=1 fi onfail endl 6838 if $nbargs-$n>1 name=${arg$n} url=${arg{$n+1}} 6839 else url,name=${arg$n} 6840 fi 6841 if $align==0 align=left elif $align==1 align=right else align=center fi 6842 ('" { \"type\": \"link\", \"name\": \""$name"\", \"url\": \""{/$url}"\", \"align\": "\ 6843 "\""$align"\""$visibility" }"$sepp\n') 6844 6845 elif ['$type']=='note' 6846 ('" { \"type\": \"note\", \"text\": \""{/$arg0}"\""$visibility" }"$sepp\n') 6847 6848 elif ['$type']=='point' 6849 ('" { \"type\": \"point\", \"name\": \""$name"\", \"position\": \""$arg0,$arg1"\", \"pos\": "\ 6850 "\""$ppos"\""$visibility" }"$sepp\n') 6851 ppos+=2 6852 6853 elif ['$type']=='separator' 6854 ('" { \"type\": \"separator\""$visibility" }"$sepp\n') 6855 6856 elif ['$type']=='text' 6857 ('" { \"type\": \"text\", \"name\": \""$name"\", \"default\": \""{/$arg0}"\", \"pos\": "\ 6858 "\""$ppos"\""$visibility" }"\ 6859 $sepp\n') 6860 ppos+=1 6861 6862 elif ['$type']=='value' 6863 ('" { \"type\": \"value\", \"value\": \""{/$arg0}"\", \"pos\": \""$ppos"\""$visibility" }"$sepp\n') 6864 ppos+=1 6865 6866 else # Unknown parameter 6867 ('" { \"type\": \"unknown\", \"name\": \""$name"\""$visibility" }"$sepp\n') 6868 fi 6869 6870 done 6871 ('" ]\n }\n"') 6872 done 6873 if ['$current_category']!=0 ('" ]\n }\n"') fi 6874 ('" ]\n}\n"') 6875 y a y html2utf8 6876 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 6877 6878_parse_gui_json : 6879 l[] 6880 ('{/"$*"}') 6881 replace_str "\\","\\\\" 6882 replace_str "\n","\\n" 6883 replace_str "\r","\\r" 6884 replace_str "\"","\\\"" 6885 replace_str "&","&" 6886 replace_str " "," " 6887 replace_str. "<i>","" 6888 replace_str. "</i>","" 6889 replace_str. "<b>","" 6890 replace_str. "</b>","" 6891 replace_str. "<small>","" 6892 replace_str. "</small>","" 6893 u {t} rm. 6894 onfail u "" endl 6895 6896# 6897# Implements 'strings' mode for command 'parse_gui'. 6898# (Extract all strings from filters, for translation purpose). 6899# 6900parse_gui_strings : 6901 e[] " >> Generate output, in 'strings' mode.\n" 6902 m "is_str : u {\"s = ['$""1']; isl = 0; "\ 6903 "repeat (size(s),k, inrange(lowercase(s[k]),_'a',_'z')?(isl = 1; break())); isl && size(s)>2 \"}" 6904 N={$_nbfilters-1} 6905 repeat $_nbfilters,f 6906 if !narg(${_f${f}_locale})" && "find(['${_f${f}_path}'],'Testing/')<0 # Consider only English, non-Testing filters 6907 e[] "\r >> "$_vt100_c[#$f/$N]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 6908 name=${_f${f}_name} 6909 is_str $name if ${} ({'$name'}:y) nm. $name fi 6910 repeat ${_f${f}_nbparams},p 6911 pname=${_f${f}_p${p}_name} 6912 ptype=${_f${f}_p${p}_type} 6913 is_str $pname if ${} ({'$pname'}:y) nm. $pname fi 6914 if ['$ptype']==['choice'] 6915 repeat ${_f${f}_p${p}_nbargs},a 6916 ({'${_f${f}_p${p}_a${a}}'}) discard. {'\"'} 6917 aname={t} rm. 6918 is_str $aname if ${} ({'$aname'}:y) nm. $aname fi 6919 done 6920 fi 6921 done 6922 fi 6923 done 6924 repeat $! nm[$>] {`lowercase(['{$>,n}'])`} done 6925 sort_list +,n 6926 repeat $!-1 if ['{$<,n}']==['{{$<+1},n}'] rm[$<] fi done 6927 um is_str 6928 if $! y i[1--1] (10) a y else 0 fi 6929 6930#@cli pass : _shared_state={ -1=status only | 0=non-shared (copy) | 1=shared | 2=adaptive } : (+) 6931#@cli : Insert images from parent context of a custom command or a local environment. 6932#@cli : Command selection (if any) stands for a selection of images in the parent context. 6933#@cli : By default (adaptive shared state), selected images are inserted in a shared state if they do not belong 6934#@cli : to the context (selection) of the current custom command or local environment as well. 6935#@cli : Typical use of command 'pass' concerns the design of custom commands that take images as arguments. 6936#@cli : This commands return the list of corresponding indices in the status. 6937#@cli : Default value: 'shared_state=2'. 6938#@cli : $ command "average : pass$""1 add[^-1] [-1] remove[-1] div 2" sample ? +mirror y +average[0] [1] 6939 6940#@cli plot : _plot_type,_vertex_type,_xmin,_xmax,_ymin,_ymax,_exit_on_anykey={ 0 | 1 } : \ 6941# 'formula',_resolution>=0,_plot_type,_vertex_type,_xmin,xmax,_ymin,_ymax,_exit_on_anykey={ 0 | 1 } : (+) 6942#@cli : Display selected images or formula in an interactive viewer (use the instant display window [0] if opened). 6943#@cli : 'plot_type' can be { 0=none | 1=lines | 2=splines | 3=bar }. 6944#@cli : 'vertex_type' can be { 0=none | 1=points | 2,3=crosses | 4,5=circles | 6,7=squares }. 6945#@cli : 'xmin', 'xmax', 'ymin', 'ymax' set the coordinates of the displayed xy-axes. 6946#@cli : Default values: 'plot_type=1', 'vertex_type=1', 'xmin=xmax=ymin=ymax=0 (auto)' and 'exit_on_anykey=0'. 6947 6948#@cli p : eq. to 'print'. : (+) 6949 6950#@cli print : (+) 6951#@cli : Output information on selected images, on the standard error (stderr). 6952#@cli : (eq. to 'p'). 6953 6954#@cli random_pattern : _width>0,_height>0,_min_detail_level>=0 6955#@cli : Insert a new RGB image of specified size at the end of the image list, rendered with a random pattern. 6956#@cli : Default values: 'width=height=512' and 'min_detail_level=2'. 6957#@cli : $ repeat 6 random_pattern 256 done 6958random_pattern : check "isint(${1=512}) && $1>0 && isint(${2=$1}) && $2>0 && ${3=2}>=0" 6959 e[^-1] "Generate a RGB image $1x$2, with a random pattern." 6960 m "rgb2rgb:" 6961 6962 # Generate the 3 channels independently. 6963 repeat 3 6964 do 6965 expr="z = [ "{u(20)}"*((x+0.5)/w-0.5), "{u(20)}"*((y+0.5)/h-0.5) + 0.5/h ]; "${-_random_pattern_expr} 6966 {round([$1,$2]*128/min($1,$2))},1,2,*$expr 6967 replace_naninf. 0 norm. n. 0,255 equalize. 256 c. 0,255 6968 cond=${-_random_pattern_check_image.\ $3} 6969 if !$cond rm. fi 6970 while !$cond 6971 rm. $1,$2,1,2,*$expr 6972 replace_naninf. 0 norm. n. 0,255 equalize. 256 c. 0,255 6973 done 6974 a[-3--1] c 6975 6976 # Convert result from random colorspace to RGB. 6977 ${"arg "{1+int(u(6))%6}",ycbcr2rgb,hsi82rgb,hsl82rgb,hsv82rgb,lab82rgb,rgb2rgb"}. 6978 6979 # Local normalization in random colorspace. 6980 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"} 6981 6982 # Random color balance. 6983 ac. "*. '[{u([0.25,0.25,0.25],[2,2,2])}]'",${"arg "{1+int(u(6))%6}",lab,ycbcr,hsi,hsl,hsv,rgb"} 6984 6985 # Equalize 6986 +equalize. 256 j.. .,0,0,0,0,{u(0.25,1)} rm. n. 0,255 6987 um rgb2rgb nm random_pattern 6988 6989# $1 : probability of a termination node in [0,1] 6990# $2 : level of recursion (avoid stack overflow due to recursivity) 6991_random_pattern_expr : skip "${1=0},${2=0}" 6992 nl={$2+1} 6993 if (u<$1" && "$2>1)" || "$2>6 # Termination node 6994 r={u} 6995 if $r<0.75 u z 6996 else u [{_round(u([-1,-1],[1,1]),0.1)}] 6997 fi 6998 else # Function or operator 6999 p1,p2={[$1,$1]+u([0.2,0.2])} 7000 r={u(27)} 7001 if $r<1 u ccos(${$0\ $p1,$nl}) 7002 elif $r<2 u csin(${$0\ $p1,$nl}) 7003 elif $r<3 u ctan(${$0\ $p1,$nl}) 7004 elif $r<4 u ccosh(${$0\ $p1,$nl}) 7005 elif $r<5 u csinh(${$0\ $p1,$nl}) 7006 elif $r<6 u ctanh(${$0\ $p1,$nl}) 7007 elif $r<7 u cexp(${$0\ $p1,$nl}) 7008 elif $r<8 u clog(${$0\ $p1,$nl}) 7009 elif $r<9 u [cabs(${$0\ $p1,$nl}),0] 7010 elif $r<10 u [0,cabs(${$0\ $p1,$nl})] 7011 elif $r<11 u [carg(${$0\ $p1,$nl}),0] 7012 elif $r<12 u [0,carg(${$0\ $p1,$nl})] 7013 elif $r<13 u cconj(${$0\ $p1,$nl}) 7014 elif $r<14 u (${$0\ $p1,$nl})+(${$0\ $p2,$nl}) 7015 elif $r<15 u (${$0\ $p1,$nl})-(${$0\ $p2,$nl}) 7016 elif $r<16 u ${$0\ $p1,$nl}**${$0\ $p2,$nl} 7017 elif $r<17 u ${$0\ $p1,$nl}//${$0\ $p2,$nl} 7018 elif $r<18 u (${$0\ $p1,$nl})^^0.5 7019 elif $r<19 u (${$0\ $p1,$nl})^^2 7020 elif $r<20 u (${$0\ $p1,$nl})^^3 7021 elif $r<21 u ${$0\ $p1,$nl}*${$0\ $p2,$nl} 7022 elif $r<22 u ${$0\ $p1,$nl}/(0.01+cabs(${$0\ $p2,$nl})) 7023 elif $r<23 u abs(${$0\ $p1,$nl})^0.5 7024 elif $r<24 u (${$0\ $p1,$nl})^2 7025 elif $r<25 u [(${$0\ $p1,$nl})[0],0] 7026 elif $r<26 u [0,(${$0\ $p1,$nl})[1]] 7027 else u (${$0\ $p1,$nl})^3 7028 fi 7029 fi 7030 7031# Check that rendered image has enough details in it. 7032# $1 = Minimum detail level. 7033_random_pattern_check_image : 7034 cond=1 7035 +s. xy,4 7036 l[^0] 7037 repeat $! if $cond l[$>] 7038 gradient_norm. 7039 if ic<$1 cond=0 fi 7040 endl fi done 7041 rm 7042 endl 7043 u $cond 7044 7045#@cli screen : _x0[%],_y0[%],_x1[%],_y1[%] : (+) 7046#@cli : Take screenshot, optionally grabbed with specified coordinates, and insert it 7047#@cli : at the end of the image list. 7048 7049#@cli select : feature_type,_X[%]>=0,_Y[%]>=0,_Z[%]>=0,_exit_on_anykey={ 0 | 1 },_is_deep_selection={ 0 | 1 } : (+) 7050#@cli : Interactively select a feature from selected images (use the instant display window [0] if opened). 7051#@cli : 'feature_type' can be { 0=point | 1=segment | 2=rectangle | 3=ellipse }. 7052#@cli : Arguments 'X','Y','Z' determine the initial selection view, for 3D volumetric images. 7053#@cli : The retrieved feature is returned as a 3D vector (if 'feature_type==0') or as a 6d vector 7054#@cli : (if 'feature_type!=0') containing the feature coordinates. 7055#@cli : Default values: 'X=Y=Z=(undefined)', 'exit_on_anykey=0' and 'is_deep_selection=0'. 7056 7057#@cli serialize : _datatype,_is_compressed={ 0 | 1 },_store_names={ 0 | 1 } : (+) 7058#@cli : Serialize selected list of images into a single image, optionnally in a compressed form. 7059#@cli : 'datatype' can be { auto | uchar | char | ushort | short | uint | int | uint64 | int64 | float | double }. 7060#@cli : Specify 'datatype' if all selected images have a range of values constrained to a particular datatype, 7061#@cli : in order to minimize the memory footprint. 7062#@cli : The resulting image has only integers values in [0,255] and can then be saved as a raw image of 7063#@cli : unsigned chars (doing so will output a valid .cimg[z] or .gmz file). 7064#@cli : If 'store_names' is set to '1', serialization uses the .gmz format to store data in memory 7065#@cli : (otherwise the .cimg[z] format). 7066#@cli : Default values: 'datatype=auto', 'is_compressed=1' and 'store_names=1'. 7067#@cli : $ image.jpg +serialize uchar +unserialize[-1] 7068 7069#@cli shape_circle : _size>=0 7070#@cli : Input a 2D circle binary shape with specified size. 7071#@cli : Default value: 'size=512'. 7072#@cli : $ shape_circle , 7073shape_circle : check "${1=512}>=0" 7074 e[^-1] "Input a $1x$1 circle binary shape." 7075 ir={round($1)} 7076 if !$ir 0 7077 elif $ir<2 $ir,$ir,1,1,1 7078 else 7079 {int($ir/2)+($ir%2)},{int($ir/2)+($ir%2)} =. 1,100%,100% 7080 distance. 1 <=. {(i+0.4)/sqrt(2)} 7081 +mirror. x 7082 if $ir>1" && "($ir%2) r. {w-1},100%,1,1,0,0,1 fi 7083 a[-2,-1] x +mirror. y 7084 if $ir>1" && "($ir%2) r. 100%,{h-1},1,1,0,0,0,1 fi 7085 a[-2,-1] y 7086 fi 7087 nm. "[2D circle shape]" 7088 7089#@cli shape_cupid : _size>=0 7090#@cli : Input a 2D cupid binary shape with specified size. 7091#@cli : Default value: 'size=512'. 7092#@cli : $ shape_cupid , 7093shape_cupid : check "${1=512}>=0" 7094 e[^-1] "Input a $1x$1 cupid binary shape." 7095 ir={round($1)} 7096 if !$ir 0 7097 else 7098 base642img[] \ 7099"MiBzaG9ydCBsaXR0bGVfZW5kaWFuCjEgMjMwMSAxIDEgIzI2NDQKeJx1mOl3lEUWxm+n6aS7IUSQRQQEFA37FtkFVFAEBxHZEoKACwRQEUHU0fGM58y"\ 7100"Zxa9z5i9AFBAhAZKwg8qACMM6CDgZIIQ9Kx0CmAHqzq/u2yR80A91nue5daveWm5tb2moNBSSkAiptCoq9RqToa6p3NVmMtyli2pzecp1IHWUke6R30"\ 7101"wjyB9hfh0o97AMIw11D8kQ0mDXRga6VpLlWsoA10L6uQzpQ909XVy6u6hkulTp6lJkyamw1GhTGc33b2iGHHYR+RT8RVvIUReThKbI3+H/0wflGD512"\ 7102"kT+oa3EaRt0M7mlEanFZ4X2QqdTLiLX8flK+5i+rWn36eb0MYqOyErT7eBp8rX2gz8Ej9H3iGww3Y5vZRg/QztvaqMuox13tAvpAdMX3JO0J+CX3AuG"\ 7103"l904wytuvOFV9yLYF5wgG8Fy9xK6j1S4iWBvcBL23lLpXkH3kio3Bd1Tqt10sIdcczOkULtLws0Eu4GzwEypdbPJfxx8S3aC190i2aWPge+iu0idW4r"\ 7104"uJDfcMvARuek+Ajsa7tT24O9lB33zuE3b4rdY1mtrw3zGPFtTZbm+K9/Qv+mM1Re6iPFKl2mM1Qp9R1Yxd1NJX8FXYptCDK2Ef0m5yfitgtcy7qsNMy"\ 7105"i7iLY9IGsMW1Cvx5aylm94XGfYSgp0seF6w9aMyWLKt6HP76HbShFYCxaDCXCTYTvZqksYq4fp01KwA31dKjXE6ff6PthZ9uoyxrSL7AOr3KNyQD9gz"\ 7106"B+Tg2CFe1yOGHaTf4Plrrv8BNYRq7eZi1OUqSN+7zJPJfCDGpJu6tdNXzmDPqRh6aHPShn8MDHXQ5+Ti8bD0l3HyiXa4u3ddZxcpT2ed9PxUtHAX5RK"\ 7107"fA4Z/51UJXkmvJp+HYQ/Aa+BH2J8M3WCXKPfB+GPUzbgacYTxmNWNsGYHqSdmWb3vBn1jIcvop4IcZzKfKbKSdp1Td+2b9ajsyl/ClsC22H8/NrKoew"\ 7108"p+pLQt8x2kzSDeT6lz1N2ofWjDlsue8hJ+p/QBeZXR30ziaEy2ndXx7BmA3st9le1JWPzstmOoBPYX2WNXzHbfPOrwT6LuKzQSazT+dbGauqaTcxW6S"\ 7109"vUH/hVYZtDPNckbUewVZjtYeoNbEepqxzba8R/gvoCW4Q5iWLrQP3etoAYiMhlK8v60Yn2XW+7ZGUfZe+ZSPvyiJGIXKDOOdqVcXuJdr0hJ7CVYZvNG"\ 7110"r3DHFToa4xRRErN70O+P0d+hp81/QHfno2OEEdpDboE/V+rY5lpz0tMv8/YzEJHrIzXl3Wm6VM2TkvJD/RJ00tMn0afsDFbgn8uuokct/F/j/wZfDsV"\ 7111"nYZenNQROYYtlzi5ojmWf9Ri4B3ak2Nt9/P1BvFdT4xc1Wwr42NzHrFzhxgpT/p5W55+zDjk2Bj8i7RAPyHefX6EdRjoqqT/ftJC/QPzOMP8f2zQgf8"\ 7112"+2vkW+lpS7yXf60SyfKA/RU+3Nv2zIT+Vto4z2+5knSU60vq2O9mGEh1h+rsGPczG8lvrwyeM21Cbi2+tn38iHoaY3kWb5uqf6fNg0ztIb+pf6GOjfl"\ 7113"3/RhsCvd3m/nNibbDVv83m5nPiKsj3eib+9ejT6C2kHP0r6yf4ntfT9VvL22zzcMD4JvvuAfPZRB3zdCfnZ5rpYjAPfRheZHyH7QGFxrfbPN3j3mej8"\ 7114"W3GN1hdW22drbe+brH59/xN3ZTkUfpY1GCfpRtsvRVYXwosnvLh2bqWtRTwV3QVa8jzKGdJAeOdZvbp1FkKrjP/rbae1uGTQ9sumD3K3rPL1uhaUo5+"\ 7115"RwymwqP4f0+sRThfPP/B5t3bp+t+1nLApzJGt5I+U+D1ST4Jfsd4TCbC1fxj8rz+aPgcuA4co/usnjGmozIazDfcT39jhuvBZ8ENGpdnwI3oUfgVgk9"\ 7116"RvhgcqLuZv7hk0eYt6CzdQ2x4/IEz2tv3c341Bc/JfwyvyDn24QFazvmSDlYRcxnST6tZHy05XyroV2swHuqhTUMlrPOpmh46Q53Z2jp0mTpytHPoOn"\ 7117"t0rj4Rus39aoYOD03WJqGb+gTndkqoWjszJimh89QzWUOhMvZjj+eo/2VV5iVDxuovrLV0xuMW6yVOf2/anvU02IbUWuukhV6TGO2N6iVJ1YvSRM9Lm"\ 7118"BTSUql3P8stt4+7Uzr3j48Z8xhzlsk5wz3PfWjzcZF23EDXOn9OtSD2s8kPs889wNqPc89qTmxPw5ZCrMe5fzWFT6P/IcY2Lhe5a966Tx/nPnXP99e4"\ 7119"n4+fXHbSPyYnuHcFPjE56XIb/Eu4f93zP+3mWJu8zxn3GmUD/7PudePe55x7Ax74lLk3OTe9PSrn3dwkj9HWeQ38ksuDh83H8xtJ+xU3v4FfdQuMF+F"\ 7120"T7hbCw2avuI9Xci+sS/r/Fq9yb8ODtnl+Pdn+Knxqf4VX41OL/+Yk93f0+/kWxqcGfs14jLhPI969DnM/8+unOfW8TaymmB5LTG1J6m2UHUfMbeXsqM"\ 7121"bfr4Px+hD2Rj2BM3o7ugr/Hfjncj9u1DH2md7gQvbdMOsnxnnWp0Hvwn8W97VGHUP3x28BayiFPT3OHjwgqcOcAT7f6/nsLWHWoc/PQuex76SgfX6j3"\ 7122"m35T1JvHudCmHPH5z9JvXnEclj2WHsGYl8g5/G/p/fR/zL0Xmv/IM7DRaZ/QOey3x/izC2l/I/W3zGss0Wm96NzuHuVcmafxX+/rfEXqHsxazKFemKs"\ 7123"/Qj311Gc4Uuwhbn/xeUFzrxK7g1eH0I/j67mnnGaMofRY/BPcE/xdRxBP82ZeF0/Mv9j6BE6nJj5mG+G2cfjMpgz6iZno/c/jh5An3/hbPX+J9D90PW"\ 7124"cx2dt7TaVPujb+kfrw8/oXui7+pn1we9xPbTYfE+zz3WDe78zdm8tMn4Wn65w7+/3wke10Ph59pLOcO9zEXtH3Wj8Mrw93Ptcxacd55Ln5fC2ut54Jb"\ 7125"wV3PvXEKMtOYu8PQHP0Hzj19n30nWd8Trs8SS/RdlUzjTP6+Fh/cbafwcuugb+oDj3NdhCbrvVYHP2vlVgnHfLV2CU9fOl3V0qDbmPui/AJuxxcxmrI"\ 7126"cYv2v4yyOo+z9vvBrHj+Tn2plp4Kd8/w15Ww3hudZPpU5Zs5s15mRgu5k16gVjf4J6hTD/Jd8MY676y1vVlzvvIN64r8dhb1vCe2swbdDXvsULePavY"\ 7127"YwvAlbx91rLWVrgmvON6yATXm/MsLMvdAOI5zf4jrOQtvIc+3WF+VruBxHMz+5+wxg0iljvyrcGG+W4IeR2lwA1Fd6JNw5I4FHsnKXTDkziM+h4x3I1"\ 7128"/Efj9fVgMfsd+UES5Xdzni8Gd3PWLqH8774BivreV/aOI72/WNobFnGVFtG0j+04h7d0AFoEFnCke19HeIpfFG7UZ5bN4z0bx6897N9X0cuZhEzgN36"\ 7129"mkALNkiqX+Msn1I/WViYzPBNdTXuQdOc5lyljel8/x1hzN+/MZ0tOuk4wijWzA4J9K8D+lvf1PCf6ltLU0iPdvkO7Xngf/XIbw/r2H98r4fzD9eWf3Z"\ 7130"u5GVv4foPOEnDEgMjAgMSAxICMzOQp4nHNn8GWIYmBgSGfIZchkSGaIZzCAQj0gLxMoms5QBZQHAHyqBfY=" 7131 decompress_rle. r. $ir,$ir,1,1,5 if $ir>480 b. 0.2% fi >=. 40% 7132 fi 7133 nm. "[2D cupid shape]" 7134 7135#@cli shape_diamond : _size>=0 7136#@cli : Input a 2D diamond binary shape with specified size. 7137#@cli : Default value: 'size=512'. 7138#@cli : $ shape_diamond , 7139shape_diamond : check "${1=512}>=0" 7140 e[^-1] "Input a $1x$1 diamond binary shape." 7141 ir={round($1)} 7142 if !$ir 0 7143 elif $ir<2 $ir,$ir,1,1,1 7144 else 7145 {int($ir/2)+($ir%2)},{int($ir/2)+($ir%2)} =. 1,100%,100% 7146 distance. 1,1 <=. {i/2} 7147 +mirror. x 7148 if $ir>1" && "($ir%2) r. {w-1},100%,1,1,0,0,1 fi 7149 a[-2,-1] x +mirror. y 7150 if $ir>1" && "($ir%2) r. 100%,{h-1},1,1,0,0,0,1 fi 7151 a[-2,-1] y 7152 fi 7153 nm. "[2D diamond shape]" 7154 7155#@cli shape_dragon : _size>=0,_recursion_level>=0,_angle 7156#@cli : Input a 2D Dragon curve with specified size. 7157#@cli : Default value: 'size=512', 'recursion_level=18' and 'angle=0'. 7158#@cli : $ shape_dragon , 7159shape_dragon : check "${1=512}>=0 && ${2=18}>=0" skip "${3=0}" 7160 e[^-1] "Input a $1x$1 Dragon curve, with recursion level $2 and angle $3." 7161 ir={round($1)} 7162 if !$ir 0 7163 else l[] 7164 (0,1^0,0) ind=1 7165 repeat $2 +f "begin(C = I["$ind"]; R = rot(90°)); R*(I - C) + C" ind={2*h} a y done 7166 s c -.. {-2,ia} -. {ia} a c / {max(abs(im),abs(iM))} 7167 angle={$3-atan2(i1,i0)*180/pi} f. "begin(R = rot("$angle"°)); R*I" 7168 n 0,{$1-1} round $1,$1,1,1 eval.. "!x?polygon(#1,2,I(0,y),I(1,y),1,1); I" k. 7169 endl fi 7170 nm. "[2D dragon shape]" 7171 7172#@cli shape_fern : _size>=0,_density[%]>=0,_angle,0<=_opacity<=1,\ 7173# _type={ 0=Asplenium adiantum-nigrum | 1=Thelypteridaceae } 7174#@cli : Input a 2D Barnsley fern with specified size. 7175#@cli : Default value: 'size=512', 'density=50%', 'angle=30', 'opacity=0.3' and 'type=0'. 7176#@cli : $ shape_fern , 7177shape_fern : check "${1=512}>=0 && ${2=50%}>=0 && isnum(${3=30}) && ${4=0.3}>=0 && $4<=1 && isnum(${5=0})" 7178 e[^-1] "Input a $1x$1 Barnsley fern, with density $2, angle $3 and opacity $4." 7179 ir={round($1)} 7180 if !$ir 0 7181 else l[] 7182 N={${"is_percent $2"}?$ir^2*$2:$2} 7183 $N,1,1,2 7184 eval " 7185 if ($5==0, 7186 # Type 0: Asplenium adiantum-nigrum. 7187 f1 = [ 0,0,0,0.16 ]; g1 = [ 0,0 ]; 7188 f2 = [ 0.2,-0.26,0.23,0.22 ]; g2 = [ 0,1.6 ]; 7189 f3 = [ -0.15,0.28,0.26,0.24 ]; g3 = [ 0,0.44 ]; 7190 f4 = [ 0.85,0.04,-0.04,0.85 ]; g4 = [ 0,1.6 ], 7191 7192 # Type 1: Thelypteridaceae. 7193 f1 = [ 0,0,0,0.25 ]; g1 = [ 0,-0.4 ]; 7194 f2 = [ 0.035,-0.2,0.16,0.04 ]; g2 = [ -0.09,0.02 ]; 7195 f3 = [ -0.04,0.2,0.16,0.04 ]; g3 = [ 0.12,0.07 ]; 7196 f4 = [ 0.95,0.005,-0.005,0.93 ]; g4 = [ -0.002,0.5 ]; 7197 ); 7198 xy = [ 0,0 ]; 7199 repeat ("$N",n, 7200 r = u(100); 7201 xy = r<=1?((f1*xy)+=g1): 7202 r<=8?((f2*xy)+=g2): 7203 r<=15?((f3*xy)+=g3):((f4*xy)+=g4); 7204 I[n] = xy 7205 )" 7206 permute xczy 7207 i.. 2,2,1,1,{"R=rot(-$3°); R[2] = -R[2]; R[3] = -R[3]; R"} m* 7208 repeat 2 sh. $>,$>,0,0 -. {im} rm. done n 0,{$ir-1} 7209 pointcloud -$4 r $ir,$ir,1,1,0,0,0.5,0.5 7210 endl fi 7211 nm. "[2D Barnsley fern]" 7212 7213#@cli shape_gear : _size>=0,_nb_teeth>0,0<=_height_teeth<=100,0<=_offset_teeth<=100,0<=_inner_radius<=100 7214#@cli : Input a 2D gear binary shape with specified size. 7215#@cli : Default value: 'size=512', 'nb_teeth=12', 'height_teeth=20', 'offset_teeth=0' and 'inner_radius=40'. 7216#@cli : $ shape_gear , 7217shape_gear : check "${1=512}>=0 && isint(${2=12}) && $2>0 && ${3=20}>=0 && $3<=100 && ${4=0}>=0 && $4<=100 && 7218 ${5=40}>=0 && $5<=100" 7219 e[^-1] "Input a $1x$1 gear binary shape with $2 teeth, teeth height $3, teeth offset $4 and inner radius $5." 7220 ir={round($1)} 7221 if !$ir 0 7222 else l[] 7223 $ir,$ir 7224 polygon {" 7225 const nb_teeth = $2; 7226 const height_teeth = $3%; 7227 const offset_teeth = 2*$4%; 7228 ref(vector2048(),pts); 7229 for (i = 0, i<size(pts), 7230 a = i*2*pi/size(pts); 7231 r = 1 - height_teeth + height_teeth*(int(a*nb_teeth/pi + 2*nb_teeth - offset_teeth)%2); 7232 pts[i++] = round(w/2*(1 + r*cos(a))); 7233 pts[i++] = round(h/2*(1 + r*sin(a))); 7234 ); 7235 [size(pts)/2,pts]; 7236 "},1,1 7237 if $5 circle. 50%,50%,{0.5*w*$5%},1,0 fi 7238 endl fi 7239 nm. "[2D gear shape]" 7240 7241#@cli shape_heart : _size>=0 7242#@cli : Input a 2D heart binary shape with specified size. 7243#@cli : Default value: 'size=512'. 7244#@cli : $ shape_heart , 7245shape_heart : check "${1=512}>=0" 7246 e[^-1] "Input a $1x$1 heart binary shape." 7247 ir={round($1)} 7248 if !$ir 0 7249 else l[] 7250 2048,1,1,1,"t = x*2*pi/w; 16*sin(t)^3" 7251 2048,1,1,1,"t = x*2*pi/w; 13*cos(t) - 5*cos(2*t) - 2*cos(3*t) - cos(4*t)" 7252 a c display_parametric $ir,$ir,1,0,0,0 7253 flood 50%,50%,0,0,0,1,0 ==. 0 7254 endl 7255 fi 7256 nm. "[2D heart shape]" 7257 7258#@cli shape_polygon : _size>=0,_nb_vertices>=3,_angle 7259#@cli : Input a 2D polygonal binary shape with specified geometry. 7260#@cli : Default value: 'size=512', 'nb_vertices=5' and 'angle=0'. 7261#@cli : $ repeat 6 shape_polygon 256,{3+$>} done 7262shape_polygon : check "${1=512}>=0 && isint(${2=5}) && $2>=3" skip ${3=0} 7263 e[^-1] "Input a $1x$1 polygon binary shape, with $2 vertices and angle $3 deg." 7264 ir={round($1)} 7265 if !$ir 0 7266 else l[] 7267 (0;{2*pi}) + {($3-90)*pi/180} r. 1,{$2+1},1,1,3 rows. 0,{h-2} 7268 ir2={round($ir/2)} 7269 +sin. cos.. 7270 a x n 0,{$ir-1} s x +.. {-2,0.5*($ir-im-iM)} +. {-1,0.5*($ir-im-iM)} a x 7271 $ir,$ir polygon. $2,{-2,^},1,1 rm.. 7272 endl 7273 fi 7274 nm. "[2D $2-polygon shape]" 7275 7276#@cli shape_snowflake : size>=0,0<=_nb_recursions<=6 7277#@cli : Input a 2D snowflake binary shape with specified size. 7278#@cli : Default values: 'size=512' and 'nb_recursions=5'. 7279#@cli : $ repeat 6 shape_snowflake 256,$> done 7280shape_snowflake : check "${1=512}>=0 && isint(${2=5}) && $2>=0 && $2<=6" 7281 e[^-1] "Input a $1x$1 snowflake binary shape, with $2 recursions." 7282 ir={round($1)} 7283 if !$ir 0 7284 else l[] 7285 $ir,$ir (0;120;240) *. {pi/180} +sin. cos.. a[-2,-1] c 7286 repeat $2 7287 1,{4*h},1,2 7288 f.. " 7289 p0 = I; 7290 p1 = I[(y+1)%h]; 7291 t = (p1 - p0)/3; 7292 pm = (p0 + p1)/2 - 0.866*[ -t[1], t[0] ]; 7293 k = 4*y; 7294 I[#-1,k++] = p0; 7295 I[#-1,k++] = p0 + t; 7296 I[#-1,k++] = pm; 7297 I[#-1,k] = p1 - t; 7298 " 7299 rm.. 7300 done 7301 *. {0.5*$1} +. {$1/2} permute. cyzx polygon.. {h},{^},1,1 rm. 7302 endl fi 7303 nm. "[2D snowflake shape]" 7304 7305#@cli shape_star : _size>=0,_nb_branches>0,0<=_thickness<=1 7306#@cli : Input a 2D star binary shape with specified size. 7307#@cli : Default values: 'size=512', 'nb_branches=5' and 'thickness=0.38'. 7308#@cli : $ repeat 9 shape_star 256,{$>+2} done 7309shape_star : check "${1=512}>=0 && ${2=5}>0 && ${3=0.5}>=0 && $3<=1" 7310 e[^-1] "Input a $1x$1 star binary shape, with $2 branches and thickness $3." 7311 ir={round($1)} 7312 if !$ir 0 7313 else l[] 7314 star3d $2,$3 col3d 1 c3d n3d *3d $1,$1 7315 $1,$1 j3d. ..,50%,50%,0,1,2 rm.. 7316 endl 7317 fi 7318 nm. "[2D star shape]" 7319 7320#@cli sh : eq. to 'shared'. : (+) 7321 7322#@cli shared : x0[%],x1[%],y[%],z[%],c[%] : y0[%],y1[%],z[%],c[%] : z0[%],z1[%],c[%] : c0[%],c1[%] : c0[%] : \ 7323# (no arg) : (+) 7324#@cli : Insert shared buffers from (opt. points/rows/planes/channels of) selected images. 7325#@cli : Shared buffers cannot be returned by a command, nor a local environment. 7326#@cli : (eq. to 'sh'). 7327#@cli : $ image.jpg shared 1 blur[-1] 3 remove[-1] 7328#@cli : $ image.jpg repeat s shared 25%,75%,0,$> mirror[-1] x remove[-1] done 7329#@cli : $$ https://gmic.eu/oldtutorial/_shared 7330 7331#@cli sp : eq. to 'sample'. 7332sp : skip "${1=?}",${2=0} 7333 v + _sample[] "$1",${2--1} v - 7334 if !${} noarg fi 7335 7336#@cli sample : _name1={ ? | apples | balloons | barbara | boats | bottles | butterfly | cameraman | car | cat | \ 7337# cliff | chick | colorful | david | dog | duck | eagle | elephant | earth | flower | fruits | gmicky | \ 7338# gmicky_mahvin | gmicky_wilber | greece | gummy | house | inside | landscape | leaf | lena | leno | lion | \ 7339# mandrill | monalisa | monkey | parrots | pencils | peppers | portrait0 | portrait1 | portrait2 | portrait3 | \ 7340# portrait4 | portrait5 | portrait6 | portrait7 | portrait8 | portrait9 | roddy | rooster | rose | square | swan | \ 7341# teddy | tiger | tulips | wall | waterfall | zelda },_name2,...,_nameN,_width={ >=0 | 0 (auto) },\ 7342# _height = { >=0 | 0 (auto) } : (no arg) 7343#@cli : Input a new sample RGB image (opt. with specified size). 7344#@cli : (eq. to 'sp').\n 7345#@cli : Argument 'name' can be replaced by an integer which serves as a sample index. 7346#@cli : $ repeat 6 sample done 7347sample : skip "${1=?}",${2=0} 7348 v + _sample[] "$1",${2--1} v - 7349 if !${} noarg fi 7350 7351__sample : 7352 u apples,balloons,barbara,boats,bottles,butterfly,cameraman,car,cat,chick,cliff,colorful,\ 7353 david,dog,duck,eagle,elephant,earth,flower,fruits,gmicky,gmicky_mahvin,gmicky_wilber,greece,gummy,house,\ 7354 inside,landscape,leaf,lena,leno,lion,mandrill,monalisa,monkey,parrots,pencils,peppers,\ 7355 portrait0,portrait1,portrait2,portrait3,portrait4,portrait5,portrait6,portrait7,portrait8,portrait9,\ 7356 roddy,rooster,rose,square,swan,teddy,tiger,tulips,wall,waterfall,zelda 7357 7358_sample : 7359 l[] 7360 if "$#>=3 && isnum($-2) && isint($-2) && $-2>=0 && isnum($-1) && isint($-1) && $-1>=0" # W and H specified. 7361 N={$#-2} W=$-2 H=$-1 7362 elif "$#>=2 && isnum($-1) && isint($-1) && $-1>=0" # Only W specified. 7363 N={$#-1} W=$-1 H=0 7364 else # No dimensions specified 7365 N={$#} W,H=0 7366 fi 7367 onfail N={$#} W,H=0 7368 endl 7369 7370 # Check validity of given arguments. 7371 $=arg 7372 samples=${-__sample} 7373 M=${"arg2var _sp_name",$samples} 7374 is_arg=1 7375 repeat $N 7376 arg=${arg{1+$>}} is_rand{1+$>}=0 7377 if ['$arg']=='?' arg={round(u(1,$M))} is_rand{1+$>}=1 7378 elif !isnum($arg)" || "!isint($arg) 7379 repeat $M name=${_sp_name{1+$>}} 7380 if '$name'!=0" && "'$name'==['$arg'] arg={1+$>} break fi 7381 done 7382 else arg={($arg%$M)+1} fi 7383 if !isnum($arg)" || "!isint($arg) is_arg=0 break fi 7384 arg{1+$>}=$arg 7385 done 7386 if !$is_arg N=1 W=0 H=0 arg1={round(u(1,$M))} fi 7387 7388 # Input sample images. 7389 repeat $N 7390 name=${_sp_name${arg{1+$>}}} 7391 7392 # Retrieve image data. 7393 filename=${-path_cache}sample_$name.png 7394 url=https://gmic.eu/img/sample_$name.png 7395 if isfile(['{/$filename}']) $filename 7396 else 7397 if ${is_rand{1+$>}} l[] $url o. $filename onfail testimage2d {m=max($W,$H);m>0?m:400} endl 7398 else $url o. $filename 7399 fi 7400 fi 7401 7402 # Resize to desired dimensions. 7403 if $W>0" && "$H==0 r2dx. $W round. 7404 elif $W==0" && "$H>0 r2dy. $H round. 7405 elif $W>0" && "$H>0 7406 if w/$W>h/$H r2dy. $H else r2dx. $W fi 7407 r. $W,$H,1,100%,0,0,0.5,0.5 round. 7408 fi 7409 nm. $name 7410 e[0--4] "Input sample image '"{n}"' (1 image "{w}x{h}x{d}x{s}")." 7411 done 7412 +. 0 u $is_arg 7413 7414#@cli srand : value : (no arg) : (+) 7415#@cli : Set random generator seed. 7416#@cli : If no argument is specified, a random value is used as the random generator seed. 7417 7418#@cli store : _is_compressed={ 0 | 1 },variable_name1,_variable_name2,... : (+) 7419#@cli : Store selected images into one or several named variables. 7420#@cli : Selected images are transferred to the variables, and are so removed from the image list. 7421#@cli : (except if the prepended variant of the command '+store[selection]' is used). 7422#@cli : If a single variable name is specified, all images of the selection are assigned 7423#@cli : to the named variable. Otherwise, there must be as many variable names as images 7424#@cli : in the selection, and each selected image is assigned to each specified named variable. 7425#@cli : Use command `input $variable_name` to bring the stored images back in the list. 7426#@cli : Default value: 'is_compressed=0'. 7427#@cli : $ sample eagle,earth store img1,img2 input $img2 $img1 7428#@cli : $$ 7429 7430#@cli testimage2d : _width>0,_height>0,_spectrum>0 7431#@cli : Input a 2D synthetic image. 7432#@cli : Default values: 'width=512', 'height=width' and 'spectrum=3'. 7433#@cli : $ testimage2d 512 7434testimage2d : check "${1=512}>0 && ${2=$1}>0 && ${3=3}>0" 7435 e[^-1] "Input 2D synthetic image of size $1x$2x$3." 7436 Dmax2={0.15*min($1,$2)^2} 7437 $1,$2,1,$3," 7438 X = x - w/2; 7439 Y = y - h/2; 7440 a = atan2(Y,X); 7441 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))))" 7442 polygon. 4,20%,20%,60%,20%,70%,70%,35%,45%,0.9,0,255,0 7443 torus3d {$1/7},{$1/20} r3d. 0,1,1,-80 col3d. 128,200,255 7444 j3d.. .,30%,70%,0,1,5,0,0 rm. round. 1 7445 nm. "[2D test image]" 7446 7447#@cli um : eq. to 'uncommand'. 7448um : 7449 v + uncommand $* v - 7450 7451#@cli uncommand : command_name[,_command_name2,...] : * : (+) 7452#@cli : Discard definition of specified custom commands. 7453#@cli : Set argument to '*' for discarding all existing custom commands. 7454#@cli : (eq. to 'um'). 7455 7456#@cli uniform_distribution : nb_levels>=1,spectrum>=1 7457#@cli : Input set of uniformly distributed spectrum-d points in [0,1]^spectrum. 7458#@cli : $ uniform_distribution 64,3 * 255 +distribution3d circles3d[-1] 10 7459uniform_distribution : check "isint($1) && $1>0 && isint($2) && $2>0" 7460 e[^1] "Input set of $1 uniformly distributed $2-d points in [0,1]^$2." 7461 n={round($1^(1/$2),1,1)} 7462 (0,1) r. $n,1,1,1,3 7463 repeat $2-1 +channels. 100% r. {$n*w},1,1,1,1 r.. .,1,1,100%,0,2 a[-2,-1] c done 7464 r. $1,1,1,$2,1 nm. "[uniform $2D distribution]" 7465 7466#@cli unserialize : : (+) 7467#@cli : Recreate lists of images from serialized image buffers, obtained with command 'serialize'. 7468 7469#@cli up : eq. to 'update'. 7470up : 7471 v + _update 7472 7473#@cli update 7474#@cli : Update commands from the latest definition file on the G'MIC server. 7475#@cli : (eq. to 'up'). 7476update : 7477 v + _$0 7478 7479_update : 7480 out=${_path_rc}update$_version.gmic 7481 e[0--3] "Update command definition file '"{/$out}"' from the G\47MIC server." 7482 l[] cimgz:https://gmic.eu/update$_version.gmic 7483 if h>7" && "same([{^}],'#@gmic',6) ot $out fi 7484 rm 7485 onfail error[0--3] "Command 'update' : Unreachable update file." 7486 endl 7487 m $out 7488 7489# Function that inserts a new 'Update information' filter for a previous version number, 7490# passed as an argument. 7491update_deprecate : check "isint($1) && $1>0 && $1<999" 7492 e[^-1] "Deprecate filter updates for G'MIC version $1." 7493 l[] 7494 file=${_path_rc}update$1.gmic 7495 i cimgz:"https://gmic.eu/update$1.gmic",uchar 7496 +l. s +,{'"UPDATE"" INFORMATION"'} is_deprecated={$!>1} rm endl # Check if deprecation has not been already done. 7497 if $is_deprecated 7498 e[0--4] " > Version $1 already deprecated -> Removing deprecation." 7499 off1={"ref(crop(),data); find(data,'\n#@gui !<b><i>>> UPDATE"" INFORMATION</i></b>')"} 7500 if $off1>0 7501 +rows $off1,100% rows[0] 0,{$off1-1} 7502 off2={"ref(crop(),data); find(data,'\n\n')"} 7503 if $off2>0 7504 rows. {$off2+2},100% a y 7505 o cimgz:$file,uchar 7506 _upload[] $file 7507 e[0--6] " > Done! Version $1 is not deprecated anymore." 7508 fi 7509 fi 7510 else 7511 s +,{'"#@cli :: "'} 7512 i[1] ('"\n\ 7513 \#@gui !<b><i>>> UPDATE"" INFORMATION</i></b> : _none_, _none_\n\ 7514 \#@gui : note = note{\"A <b>new version</b> of the <i>G\47MIC</i> plug-in is available!\\n\\n\n\ 7515 \#@gui : You are strongly encouraged to upgrade your version, 7516 by visiting our <i>Download page</i>:\\n\\n\"}\n\ 7517 \#@gui : url = link{\"Visit G\47MIC Download Page\",\"https://gmic.eu/download.html\"}\n\ 7518 \#@gui : note = note{\"\\nOf course, your plug-in will continue to work, but please note that we 7519 won\47t be able\n\ 7520 \#@gui : to provide filter updates anymore for your current plug-in version.\\n\\n\n\ 7521 \#@gui : Best regards,\\n\\n <i>The G\47MIC team.</i>\"}\n\n"') 7522 y[1] a y 7523 o cimgz:$file,uchar 7524 _upload[] $file 7525 e[0--4] " > Done! Version $1 is now deprecated." 7526 fi 7527 rm endl 7528 7529# update_download_version. 7530# Update file versions on G'MIC download page, with specified version number. 7531# $1 = version number (e.g. '2.9.8'). 7532update_download_version : check " 7533 is_digit(c)=(c>=_'0' && c<=_'9'); 7534 ver = ['${1=undefined}']; 7535 size(ver)==5 && is_digit(ver[0]) && ver[1]==_'.' && is_digit(ver[2]) && ver[3]==_'.' && is_digit(ver[4])" 7536 e[^-1] "Replace version number on G'MIC download page to '$1'." 7537 rm filename=$HOME/work/src/gmic/html/download.html it[] $filename 7538 eval " 7539 is_digit(c) = (c>=_'0' && c<=_'9'); 7540 ver = ['$1']; 7541 ref(crop(),data); 7542 p = stop = N = 0; 7543 while (!stop, 7544 p = find(data,'?dwl=gmic_',p); 7545 p<0?(stop=1):( 7546 str = data[p + 10,5]; 7547 is_digit(str[0]) && str[1]==_'.' && is_digit(str[2]) && str[3]=='.' && is_digit(str[4])?( 7548 copy(data[p + 10],ver,size(ver)); 7549 ++N; 7550 ); 7551 ++p; 7552 ); 7553 ); 7554 p = find(data,'/source/gmic_',0); 7555 p>0?( 7556 str = data[p + 13,5]; 7557 is_digit(str[0]) && str[1]==_'.' && is_digit(str[2]) && str[3]=='.' && is_digit(str[4])?( 7558 copy(data[p + 13],ver,size(ver)); 7559 ++N; 7560 ); 7561 ); 7562 copy(i[0],data,size(data)); 7563 echo(' -> ',N,' occurrences found.'); 7564 " 7565 ot $filename 7566 7567# Generate images used in the G'MIC installer for Windows (InnoSetup). 7568update_instimg : 7569 sp gmicky,600 7570 7571 # Large image. 7572 +l 7573 r2dx 164 7574 0 t. "G'MIC-Qt for GIMP",0,0,96,1,1 7575 0 t. "(version "${-strver}")",0,0,64,1,1 7576 a[-2,-1] y,0.5 rows. -5,100% 7577 *. -1 n. 0,255 to_rgb. r2dx. {0,0.95*w} 7578 - 255 a y,0.5 + 255 7579 - 255 r 164,314,1,3,0,0,0.5,0.25 + 255 7580 o $HOME/work/src/gmic/resources/gmic_instimg.bmp 7581 rm 7582 endl 7583 7584 # Small image. 7585 r2dx 55 - 255 r 55,55,1,3,0,0,0.5,0.5 + 255 7586 o $HOME/work/src/gmic/resources/gmic_instimg_small.bmp 7587 rm 7588 7589# Generate Color Presets page for the G'MIC website. 7590# Input images : samples you want to generate 7591# $1 = upload to G'MIC server, can be { 0 | 1 }. 7592update_color_presets_html : check "isbool(${1=0})" 7593 use_vt100 7594 path_current=${-path_current} path_ok=$HOME/work/src/gmic/html/color_presets/ 7595 if ['$path_current']!=['$path_ok'] 7596 error[0--3] "Command 'update_color_presets_html: Command run from wrong path: '"$path_current"', "\ 7597 "should be '"$path_ok"'." 7598 fi 7599 7600 # Load default set of images if none selected. 7601 if !$! 7602 files ../img/color_presets_sample* files=${} 7603 repeat narg($files) arg 1+$>,$files ${} done 7604 fi 7605 7606 # Init variables. 7607 jpeg_quality=70 # Set JPEG quality of output images. 7608 thumb_width=180 # Set thumbnail width. 7609 thumb_height=90 # Set mini thumbnail height. 7610 categories=creative,picturefx,pixlsus,abigailgonzalez,alexjordan,berat,ericellerbrock,inavision,jtsemple,\ 7611 kylerholland,ohadperetz,shamoonabbasi,youssefhossam,others,\ 7612 bw,instant_consumer,instant_pro,fujixtransiii,negative_color,negative_new,negative_old,print,colorslide 7613 category_names="Creative Pack",\ 7614 "PictureFX",\ 7615 "PIXLS.US",\ 7616 "Abigail Gonzalez's CLUTs",\ 7617 "Alex Jordan's CLUTs",\ 7618 "Berat's CLUTs",\ 7619 "Eric Ellerbrock's CLUTs",\ 7620 "InAvision's CLUTs",\ 7621 "J.T. Semple's CLUTs",\ 7622 "Kyler Holland's CLUTs",\ 7623 "Ohad Peretz's CLUTs",\ 7624 "Shamoon Abbasi's CLUTs",\ 7625 "Youssef Hossam's CLUTs",\ 7626 "Others",\ 7627 "Films: Black and White",\ 7628 "Films: Instant [Consumer]",\ 7629 "Films: Instant [Pro]",\ 7630 "Films: Fuji XTrans III",\ 7631 "Films: Negative [Color]",\ 7632 "Films: Negative [New]",\ 7633 "Films: Negative [Old]",\ 7634 "Films: Print Films",\ 7635 "Films: Slide [Color]" 7636 category_authors="RawTherapee",\ 7637 "Marc Roovers",\ 7638 "PIXLS.US contributors",\ 7639 "Abigail Gonzalez",\ 7640 "Alex Jordan",\ 7641 "Berat",\ 7642 "Eric Ellerbrock",\ 7643 "InAvision",\ 7644 "J.T. Semple",\ 7645 "Kyler Holland",\ 7646 "Ohad Peretz",\ 7647 "Shamoon Abbasi",\ 7648 "Youssef Hossam",\ 7649 0,\ 7650 "Pat David",\ 7651 "Pat David",\ 7652 "Pat David",\ 7653 "Stuart Sowerby",\ 7654 "Pat David",\ 7655 "Pat David",\ 7656 "Pat David",\ 7657 "Juan Melara",\ 7658 "Pat David" 7659 category_authors_url="https://rawpedia.rawtherapee.com/Film_Simulation",\ 7660 "https://marcrphoto.wordpress.com/specials/698-2/",\ 7661 "https://discuss.pixls.us/t/help-to-create-a-set-of-pixls-us-color-luts",\ 7662 "https://www.abigailgonzalez.com/",\ 7663 "https://freshluts.com/users/1",\ 7664 "https://freshluts.com/users/10185",\ 7665 "https://www.facebook.com/eric.ellerbrockom",\ 7666 "https://freshluts.com/users/64078",\ 7667 "https://freshluts.com/users/120",\ 7668 "https://sellfy.com/p/SGnG/",\ 7669 "https://freshluts.com/users/992",\ 7670 "https://www.facebook.com/shamoon",\ 7671 "https://freshluts.com/users/52679",\ 7672 0,\ 7673 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 7674 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 7675 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 7676 "http://blog.sowerby.me/fuji-film-simulation-profiles",\ 7677 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 7678 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 7679 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html",\ 7680 "http://juanmelara.com.au/print-film-emulation-luts-for-download",\ 7681 "https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html" 7682 7683 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" 7684 m "_title : ('\"$""*\"') replace_str. \"_\",\" \" replace_str. \"iii\",\"III\" f. \"(!y || j(0,-1)==32) && 7685 i>=_'a' && i<=_'z'?uppercase(i):i\" u {t} rm." 7686 7687 nb_presets=0 7688 repeat narg($categories) 7689 category=${arg\ {1+$>},$categories} 7690 presets=${-_fx_cluts_$category} 7691 nb_presets+={narg({/$presets})} 7692 done 7693 7694 e[] "\n > Update 'Color Presets' pages, for "$!" image samples and "$nb_presets" presets." 7695 7696 # Prepare folder structure. 7697 e[] $_vt100_g"\n * Prepare folder structure."$_vt100_n 7698 x "mkdir -p img" 7699 7700 # Generate thumbnails. 7701 e[] $_vt100_g"\n * Generate thumbnails from samples.\n"$_vt100_n 7702 x "mkdir -p original" 7703 nb_samples=$! 7704 to_rgb repeat $nb_samples l[$<] 7705 nm[0] sample_{1+$<} 7706 basename={0,b} basename$<=$basename 7707 e[] " - "$basename 7708 +r2dx $thumb_width 7709 +to[0] "Reference",4,{0,h-28},20,2 frame. 1,1,0 7710 o. original/$basename.jpg,$jpeg_quality rm. 7711 +_thumb[1] o. original/thumb_$basename.jpg,$jpeg_quality rm. 7712 +r2dy[0] $thumb_height r. {h},{h},1,100%,0,0,0.5,0.5 _thumb. 7713 o. original/minithumb_$basename.jpg,$jpeg_quality rm. 7714 endl done 7715 7716 # Generate color grading data and rendering on each input sample. 7717 ind_preset=0 7718 repeat narg($categories) 7719 category=${arg\ {1+$>},$categories} 7720 presets=${-_fx_cluts_$category} 7721 7722 e[] $_vt100_g"\n * Category ""#"{1+$>}": "$_vt100_b$category"\n"$_vt100_n 7723 x "mkdir -p "$category 7724 x "mkdir -p "$category/clut 7725 7726 repeat narg({/$presets}) 7727 preset=${arg\ {1+$>},$presets} 7728 e[] " - "$preset 7729 clut $preset,64 to_rgb. 7730 s={sqrt(w*h*d)} +r. $s,$s,1,3,-1 7731 if iM<=255 *. 257 fi # Force PNG to be saved in 16bits. 7732 o. $category/clut/$preset.png # Save as HaldCLUT 7733 rm. 7734 7735 +r3dx. 13 7736 o. $category/clut/$preset.cube # Save as .cube 7737 x 0,"rm -f "$category/clut/$preset.zip 7738 x 0,"zip -j -9 "$category/clut/$preset.zip" "$category/clut/$preset.cube 7739 rm. 7740 7741 repeat $nb_samples l[{2*$>},{2*$>+1},-1] 7742 basename={0,b} 7743 if !isfile(['{/$category/$basename/$preset.jpg}']) 7744 x "mkdir -p \""$category/$basename"\"" 7745 +map_clut[^-1] . 7746 _title $preset 7747 to.. ${},4,{-2,h-28},20,2 frame.. 1,1,0 7748 o.. $category/$basename/$preset.jpg,$jpeg_quality 7749 _thumb. o. $category/$basename/thumb_$preset.jpg,$jpeg_quality 7750 rm[-2,-1] 7751 fi 7752 endl done 7753 7754 rm. 7755 7756 ind_preset+=1 7757 done 7758 x 0,"zip -rj9 "$category/${category}_cube.zip" "$category/clut/*.cube 7759 x 0,"zip -rj9 "$category/${category}_haldclut.zip" "$category/clut/*.png 7760 done 7761 7762 rm[1--1:2] # Remove thumbnails. 7763 7764 # Generate html gallery code. 7765 e[] "\n * Generate html code.\n" 7766 7767 repeat narg($categories) 7768 category=${arg\ {1+$>},$categories} 7769 arg {1+$>},$category_names 7770 category_name=${} 7771 presets=${-_fx_cluts_$category} 7772 x 0,"rm -f "$category/clut/"*.cube" 7773 7774 repeat $nb_samples 7775 width={$>,64+w} height={$>,64+h} 7776 basename={$>,b} 7777 e[] " - "$category_name" / "$basename 7778 7779 ('"<!DOCTYPE html>"\n\ 7780"<html lang=\"en\">"\n\ 7781" <head>"\n\ 7782" <meta charset=\"utf-8\">"\n\ 7783" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 7784" <link rel=\"stylesheet\" href=\"../highslide/highslide.css\"/>"\n\ 7785" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 7786"- Color Presets</title>"\n\ 7787" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 7788" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 7789" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 7790" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 7791" <script src=\"../highslide/highslide-full.js\"></script>"\n\ 7792" <script>"\n\ 7793" hs.graphicsDir = '../highslide/graphics/';"\n\ 7794" hs.wrapperClassName = 'wide-border';"\n\ 7795" hs.showCredits = 'false';"\n\ 7796" </script>"\n\ 7797" </head>"\n\n\ 7798" <body>"\n\ 7799" <div id=\"include_header\"></div>"\n\n\ 7800" <div class=\"section_title\"><p>Color Presets</p></div><div class=\"section_content\">"\n\n\ 7801" <p>Among all features available in <span class=\"gmd_gmic\">G'MIC</span>, our <b>Color Presets</b> and "\ 7802"<b>Simulate Film</b> filters are able to apply various pre-defined <b>color CLUTs</b> on your images "\ 7803"(<b>600+</b> color CLUTs available).</p>"\n\ 7804" <p>Below, you can navigate through the different proposed presets and see how they modify the colors "\ 7805"of some sample images."\n\ 7806" You can also download each color preset separately as its corresponding "\ 7807"<a href=\"http://www.quelsolaar.com/technology/clut.html\">HaldCLUT</a> file (in <b>.png</b> format), to use it in "\ 7808" other software that support this feature.</p>"\n\n\ 7809" <p><b>Image credits:</b> Sample images below have been borrowed from "\ 7810"<a href=\"https://www.flickr.com/photos/patdavid/\">Patrick David</a>, "\ 7811"<a href=\"https://www.flickr.com/photos/davelau/\">Chi King</a>, "\ 7812"<a href=\"https://pixabay.com/en/tulips-tulip-field-tulpenbluete-3359902/\">Capri23auto</a> "\ 7813"and <a href=\"https://pixabay.com/en/girl-face-colorful-colors-artistic-2696947/\">ivanovgood</a>,"\n\ 7814" distributed a minima under "\ 7815"<a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-by-SA 2.0</a>.</p>"\n\n\ 7816" <p class=\"colorpresets_disclaimer\"><b>Disclaimer:</b><br/>"\n\ 7817" The trademarked names which may appear in the filenames of the HaldCLUT images are there for "\ 7818"informational purposes only. They serve only to inform the user which film stock the given HaldCLUT image"\n\ 7819" is designed to approximate. As there is no way to convey this information other than by using the "\ 7820"trademarked name, we believe this constitutes fair use. Neither the publisher nor the authors are affiliated"\n\ 7821" with or endorsed by the companies that own the trademarks.</p>"\n\n\ 7822"<!-- end_content -->"\n\n\ 7823" </div><div class=\"section_end\"></div>"\n\n\ 7824" <a name="browse"></a><div class=\"section_title\"><p>Browse</p></div><div class=\"section_content\">"\n\n\ 7825" <table><tr>"\n\ 7826" <td style=\"width: 400px\">Select category:"\n\ 7827" <ul>\n"') 7828 repeat narg($categories) 7829 _category=${arg\ {1+$>},$categories} 7830 arg {1+$>},$category_names 7831 _category_name=${} 7832 7833 arg {1+$>},$category_authors_url 7834 if isnum(${}) _category_author_url_start= _category_author_url_end= 7835 else _category_author_url_start="<a href=\""${}"\">" _category_author_url_end="</a>" 7836 fi 7837 7838 arg {1+$>},$category_authors 7839 if isnum(${}) _category_author="" 7840 else _category_author=$_category_author_url_start${}$_category_author_url_end 7841 fi 7842 7843 if narg($_category_author) 7844 _category_author="<span class=\"smaller\">(by "$_category_author")</span>" 7845 fi 7846 7847 if ['$_category']==['$category'] 7848 ('" <li><span class=\"gmd_bold_a\"><b>"$_category_name"</b> "\ 7849 $_category_author"</span></li>"\n') 7850 else 7851 ('" <li><a href=\""${_category}_$basename.html"#browse\">"$_category_name"</a> "\ 7852 $_category_author"</li>\n"') 7853 fi 7854 done 7855 7856 ('" </ul>\n"\ 7857 " </td>"\n\ 7858 " <td>Select sample image:<br/><br/>\n"') 7859 repeat $nb_samples 7860 _basename=${basename$>} 7861 if ['$_basename']==['$basename'] 7862 ('" <a href=\""${category}_$_basename.html"#browse\">"\ 7863 "<img alt=\"\" style=\"border: 3px solid \#cc7700\" "\ 7864 "src=\""original/minithumb_$_basename.jpg"\"/></a>\n"') 7865 else 7866 ('" <a href=\""${category}_$_basename.html"#browse\"><img alt=\"\" "\ 7867 "src=\""original/minithumb_$_basename.jpg"\"/></a>\n"') 7868 fi 7869 done 7870 ('" </td>"\n\ 7871 " </tr></table>"\n\ 7872 " </div><div class=\"section_end\"></div>"\n\n') 7873 ('" <div class=\"section_title\"><p>Presets</p></div><div class=\"section_content\">"\n\n\ 7874 " <table class=\"colorpresets_table\">"\n\ 7875 " <tr><td>"\n\ 7876 " <div><a href=\"original/"$basename".jpg\" class=\"highslide\" "\ 7877 "onclick=\"return hs.expand(this)\"><img alt=\"\" "\ 7878 "src=\"original/thumb_"$basename".jpg\" /></a>"\n\ 7879 " <div class=\"highslide-caption\"><b>Reference Image</b></div></div>"\n\ 7880 " </td><td colspan=\"3\"></td></tr>"\n\ 7881 " <tr><td><b>Reference Image</b></td><td colspan=\"3\"></td></tr>"\n\n') 7882 7883 repeat narg({/$presets}) 7884 preset=${arg\ {1+$>},$presets} 7885 7886 ('$preset') replace_seq. 39,"92,92,39" preset_esc={t} rm. 7887 _title $preset title=${} 7888 if $>%4==0 if $> ('" </tr>\n"') fi ('" <tr>\n"') fi 7889 7890 ('" <td><table>"\n\ 7891 " <tr><td>"\n\ 7892 " <div><a href=\"#\" onclick=\"return hs.htmlExpand(this, "\ 7893 "{ width: "$width", height: "$height" })\">"\n\ 7894 " <img alt=\"\" src=\""$category/$basename/thumb_$preset".jpg\" /></a>"\n\ 7895 " <div class=\"highslide-maincontent\" style=\"text-align: center\">"\n\ 7896 " <img alt=\"\" src=\""$category/$basename/$preset.jpg"\" "\ 7897 "onclick=\"hs.close()\" "\ 7898 "onmouseover=\"javascript:this.src='"$category/$basename/$preset_esc.jpg"';\" "\ 7899 "onmouseout=\"javascript:this.src='original/"$basename".jpg';\" /></div>"\n\ 7900 " <div class=\"highslide-caption\"><b>Preset:</b> <i>"$title"</i> "\ 7901 "[<a href=\""$category/clut/$preset.png"\">Download .png HaldCLUT</a>] "\ 7902 "or [<a href=\""$category/clut/$preset.zip"\">Download .cube</a>]"\ 7903 "</div></div>"\n\ 7904 " </td></tr>"\n\ 7905 " <tr><td><span class=\"smaller\">"$title"</span></td></tr>"\n\ 7906 " </table></td>\n\n"') 7907 done 7908 r={narg({/$presets})%4} 7909 if $r%4 ('" <td colspan=\""{4-$r}"\"></td>\n"') fi 7910 ('" </tr></table>"\n\n\ 7911 " <hr/><p style=\"text-align: center\">"\n\ 7912 " <a href=\""$category/${category}_cube.zip"\"><img src=\"../img/menu_download.png\" /></a> "\ 7913 "<span class=\"gmd_bold_a\">Get the Full Pack "<i>"${category_name}"</i>":</span> "\ 7914 "[<b><a href=\""$category/${category}_haldclut.zip"\">Download .png HaldCLUT</a></b>] "\ 7915 "or [<b><a href=\""$category/${category}_cube.zip"\">Download .cube</a></b>]"\ 7916 " <a href=\""$category/${category}_cube.zip"\"><img src=\"../img/menu_download.png\" /></a>"\n\ 7917 " </p><hr/>"\n\ 7918 "<!-- end_content -->"\n\n\ 7919 " </div><div class=\"section_end\"></div>"\n\ 7920 " <div id=\"include_footer\"></div>"\n\ 7921 " </body>"') 7922 a[$nb_samples--1] x ot. ${category}_$basename.html rm. 7923 done 7924 7925 done 7926 7927 # All done, exiting. 7928 rm 7929 category=${arg\ 1,$categories} 7930 x "ln -fs "${category}_$basename0.html" index.html" 7931 if $1 7932 e[] "\n * Transfer color presets on G'MIC server.\n" 7933 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"mirror -eRL . /www/gmic/color_presets ; quit\"" 7934 fi 7935 e[] "\n > All done, for "$nb_presets" presets.\n" 7936 7937# Generate gallery page for the G'MIC website. 7938# $1 = upload to G'MIC server, can be { 0 | 1 }. 7939update_gallery_html : check "isbool(${1=0})" 7940 e[^-1] "Generate gallery pages for the G'MIC website." 7941 use_vt100 7942 path_current=${-path_current} path_ok=$HOME/work/src/gmic/html/gallery/ 7943 if ['$path_current']!=['$path_ok'] 7944 error[0--3] "Command 'update_gallery_html: Command run from wrong path: '"$path_current"', "\ 7945 "should be '"$path_ok"'." 7946 fi 7947 x "rm -rf img && mkdir -p img" 7948 7949 # Define categories and sample pictures. 7950 categories=arrays,artistic,blackandwhite,colors,deformations,filtering,patterns,3dmeshes,stylization,codesamples 7951 nb_categories={narg($categories)} 7952 commands_arrays=_gallery_arrays,array,array_fade,array_mirror,frame_blur,frame_cube,frame_painting,img2ascii,\ 7953 imagegrid,rotate_tiles,vignette,tunnel 7954 commands_artistic=_gallery_artistic,boxfitting,cartoon,cubism,draw_whirl,fractalize,halftone,sketchbw,light_relief,\ 7955 mosaic,linify,polaroid,polygonize,poster_hope,rodilius,stencil,stained_glass 7956 commands_blackandwhite=_gallery_blackandwhite,pencilbw,old_photo,sepia 7957 commands_colors=_gallery_colors,solarize,hsv2rgb,transfer_rgb 7958 commands_deformations=_gallery_deformations,deform,map_sphere,seamcarve,spherize,twirl,warp_perspective,water,wave 7959 commands_filtering=_gallery_filtering,blur_angular,blur_linear,blur_radial,glow,smooth,bilateral,dog,deriche,\ 7960 distance,gradient_norm,normalize_local,sharpen,solidify 7961 commands_patterns=_gallery_patterns,tsp,chessboard,mandelbrot,maze_mask,plasma,shape_fern,shape_snowflake,\ 7962 sierpinski,syntexturize_matchpatch,truchet,turbulence,watermark_visible,weave 7963 commands_3dmeshes=_gallery_3dmeshes,add3d,distribution3d,elevation3d,gmic3d,imageblocks3d,imagerubik3d,\ 7964 skeleton3d,spherical3d,tensors3d,text3d,torus3d,weird3d 7965 commands_stylization=_gallery_stylization 7966 commands_codesamples=_gallery_codesamples 7967 7968 pics=apples,bottles,butterfly,car,cat,cliff,david,dog,duck,eagle,elephant,earth,flower,fruits,greece,gummy,inside,\ 7969 landscape,leaf,leno,lion,mandrill,monalisa,parrots,pencils,rooster,rose,square,teddy,tiger,wall,waterfall,zelda 7970 7971 # Generate html pages. 7972 it[] $HOME/work/src/gmic/src/gmic_stdlib.gmic 7973 merge_multiline_comments. s -,10 7974 ('\n') a[0--3] .,y rm. a y 7975 nb_cols=3 7976 7977 repeat $nb_categories,ncat 7978 category=${arg\ 1+$>,$categories} 7979 if isfile('{/$category.html}') continue fi 7980 e[] "\n * Process category '"$_vt100_b$category$_vt100_n"'." 7981 7982 commands=${commands_$category} 7983 nb_commands={narg($commands)} 7984 col,nex=0 7985 7986 repeat $nb_categories 7987 cat=${arg\ 1+$>,$categories} 7988 if '$cat'=='$category' td_$cat="<td style=\"background-color: \#dddddd\">" 7989 else td_$cat="<td>" 7990 fi 7991 done 7992 7993 html="<!DOCTYPE html>"\n\ 7994"<html lang=\"en\">"\n\ 7995" <head>"\n\ 7996" <meta charset=\"utf-8\">"\n\ 7997" <link rel=\"stylesheet\" href=\"../style.css\">"\n\ 7998" <link rel=\"stylesheet\" href=\"../highslide/highslide.css\"/>"\n\ 7999" <link rel=\"stylesheet\" href=\"https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css\">"\n\n\ 8000" <title>G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing "\ 8001"- Gallery</title>"\n\ 8002" <script src=\"../jquery-3.5.1.min.js\"></script>"\n\ 8003" <script>var jQuery_3_5_1 = $.noConflict(true);</script>"\n\ 8004" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_header\").load(\"../header1.html\"); });</script>"\n\ 8005" <script>jQuery_3_5_1(function(){ jQuery_3_5_1(\"#include_footer\").load(\"../footer.html\"); });</script>"\n\n\ 8006" <script src=\"https://code.jquery.com/jquery-1.12.4.js\"></script>"\n\ 8007" <script src=\"https://code.jquery.com/ui/1.12.1/jquery-ui.js\"></script>"\n\n\ 8008" <script src=\"../highslide/highslide-full.js\"></script>"\n\ 8009" <script>"\n\ 8010" hs.graphicsDir = '../highslide/graphics/';"\n\ 8011" hs.wrapperClassName = 'wide-border';"\n\ 8012" hs.showCredits = 'false';"\n\ 8013" </script>"\n\ 8014" </head>"\n\n\ 8015" <body>"\n\ 8016" <div id=\"include_header\"></div>"\n\n\ 8017" <div class=\"section_title\"><p>Image Gallery</p></div><div class=\"section_content\">"\n\n\ 8018" <p>This gallery gives a quick overview of the kind of features and generic filters available in the "\ 8019"<span class=\"gmd_gmic\">G'MIC</span> open-source image processing framework.</p>"\n\ 8020" <p>All the images below have been processed by the CLI interface "\ 8021"<samp><a href=\"reference/\">gmic</a></samp>"\ 8022" of G'MIC, from a set of initial 2D color images."\n\ 8023" Click on an image to enlarge it and display the G'MIC command-line "\ 8024"used for the processing (<i>note: to reproduce this, you may have to escape some characters, "\ 8025"according to the type of shell you use!</i>).</p>"\n\ 8026" <p>Remember, G'MIC lets you define your own image pipelines through"\ 8027"custom <a href=\"https://gmic.eu/gmic_stdlib.gmic\">command files</a>."\n\ 8028" Your custom filters can be easily added afterwards in the plug-in for "\ 8029"<a href=\"http://www.gimp.org\">GIMP</a> or <a href=\"http://www.krita.org\">Krita</a>.</p>"\n\ 8030" <p>For more details, visit the <a href=\"https://gmic.eu/tutorial\">tutorial pages</a> as well as the "\ 8031"<a href=\"https://gmic.eu/reference/\">technical reference</a> to get a full documentation on this "\ 8032"software.</p>"\n 8033 8034 html_menu=" <table class=\"gallery_navigation\"><tr>\n "\ 8035 $td_arrays"<a href=\"arrays.html#menu\">Arrays & Frames</a></td>"\ 8036 $td_artistic"<a href=\"artistic.html#menu\">Artistic</a></td>"\ 8037 $td_blackandwhite"<a href=\"blackandwhite.html#menu\">B&W</a></td>"\ 8038 $td_colors"<a href=\"colors.html#menu\">Colors</a></td>"\ 8039 $td_deformations"<a href=\"deformations.html#menu\">Deformations</a></td>"\ 8040 $td_filtering"<a href=\"filtering.html#menu\">Filtering</a></td>"\ 8041 $td_patterns"<a href=\"patterns.html#menu\">Patterns</a></td>"\ 8042 $td_3dmeshes"<a href=\"3dmeshes.html#menu\">3D Meshes</a></td>"\ 8043 $td_stylization"<a href=\"stylization.html#menu\">Stylization</a></td>"\ 8044 $td_codesamples"<a href=\"codesamples.html#menu\">Code samples</a></td>"\n\ 8045 " </tr></table><br/>\n\n" 8046 8047 html=${html}${html_menu}" <table class=\"gallery_table\">\n" 8048 8049 repeat $nb_commands 8050 command=${"arg "1+$>,$commands} 8051 is_stylization={['$command']=='_gallery_stylization'} 8052 8053 e[] $_vt100_m" - Command '"$_vt100_b$command$_vt100_n"' ["{1+$>}/$nb_commands"]." 8054 +l # Parse command definition and examples 8055 s -,{'"#@cli "$command" :"'} 8056 if $!<2 s -,{'"#@cli "$command"\n"'} i[1] ('\n') a[-2,-1] y fi 8057 if $!<2 warn[] " ** Command '"$command"' not found! **" 8058 else 8059 k. 8060 eval " 8061 ref(crop(#-1),str); 8062 ind = 0; 8063 while ((ind = find(str,'\n#@cli ',ind))>=0, 8064 ++ind; 8065 str[ind+6]!=_':' ? break() : 8066 str[ind+7]==_' ' && str[ind+8]==_'$' && str[ind+9]==_' '?( 8067 beg = ind + 10; 8068 end = find(str,_'\n',beg) - 1; 8069 ref(vector1024(0),com); 8070 run('+rows[0] ',beg,',',end); 8071 ); 8072 ); 8073 "; 8074 rm[0] 8075 8076 nb_examples=$! 8077 repeat $nb_examples # For each example found 8078 example$nex={$>,t} 8079 8080 e[] $_vt100_g" $ "${example$nex}$_vt100_n 8081 sample=${"arg 1+"{($nex+8*$ncat)%narg($pics)},$pics} 8082 is_codesample=0 8083 8084 l[] # Create a html representation of the command 8085 ('${example$nex}') y 8086 is_input={"find(#-1,'image.jpg')>=0"} 8087 8088 if !$is_input" && find(#-1,'sample ')>=0" 8089 s +,{'"sample "'} 8090 if {0,crop()=='"sample "'" && "$!>1} l[1] 8091 s +,{'" "'} 8092 if "find(#0,_',')==-1" sample={0,t} is_input=1 fi 8093 a y 8094 endl fi 8095 a y 8096 fi 8097 replace_str. "image.jpg",\ 8098 "<a href=\"../img/sample_"$sample".png\" target=\"_blank\">"$sample".png</a>" 8099 replace_str. "_output_mode=1","" 8100 # Discard '_fps=?' and '_label=?' 8101 l. s +,{'" "'} repeat $! if {$<,crop(0,0,1,5)=='_fps='||crop(0,0,1,7)=='_label='} 8102 rm[$<] 8103 fi done a y endl 8104 l. s +,{'" "'} repeat $! if {$<,crop(0,0,1,8)=='https://'} l[$<] # Add hyperlink 8105 if crop(0,0,1,24)=='https://gmic.eu/samples/' 8106 is_codesample=1 8107 basename_codesample={`crop(0,24,1,h-24)`} 8108 filename_codesample="../../resources/samples"/$basename_codesample 8109 url_codesample="https://gmic.eu/samples/"$basename_codesample 8110 if $1 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"put -O /www/gmic/samples \\\""\ 8111 $filename_codesample"\\\"; quit\" >/dev/null" fi 8112 i[0] ('"<a onclick=\"javascript:$( '\#dialog"$nex"' ).dialog( 'open' );\" 8113 style=\"cursor: pointer;\">"') 8114 else i[0] ('"<a href=\""{$<,t}"\" target=\"_blank\">"') 8115 fi 8116 ('</a>') y a y 8117 endl fi done a y endl 8118 replaced_example$nex={t} rm 8119 endl 8120 ('${example$nex}') replace_str. "https://gmic.eu/samples/","../../resources/samples/" example$nex={t} rm. 8121 m "_run : _preview_width,_preview_height=450,300 "${example$nex} 8122 8123 if $is_input sample_=${sample}_ else sample_= fi 8124 filename_original=img/${category}_${sample_}original_$nex.jpg 8125 filename_thumb_original=img/${category}_${sample_}thumb_original_$nex.jpg 8126 if "find(['"${example$nex}"'],' _fps=')>=0" 8127 filename_full=img/${category}_${sample_}full_$nex.gif 8128 filename_thumb=img/${category}_${sample_}thumb_$nex.gif 8129 _is_animated=1 8130 else 8131 filename_full=img/${category}_${sample_}full_$nex.jpg 8132 filename_thumb=img/${category}_${sample_}thumb_$nex.jpg 8133 _is_animated=0 8134 fi 8135 8136 etime= 8137 _label= 8138 if !isfile('{/$filename_thumb}') l[] 8139 if $is_input sp $sample,600 o image.jpg rm fi 8140 8141 db3d m3d md3d f3d l3d sl3d ss3d 0.8 srand 512 8142 etime=$| _run etime={_round($|-$etime,0.01)} 8143 8144 if $is_stylization 8145 +l _gallery o $filename_full,70 rm endl k. 8146 _gallery 8147 width,height={[w,h]} 8148 else 8149 _gallery 8150 width,height={[w,h]} 8151 if $_is_animated o $filename_full,$_fps else o $filename_full,70 fi 8152 fi 8153 e[] "\r"$_vt100_g" $ "${example$nex}" (done in "$_vt100_n${etime}"s"$_vt100_g")."$_vt100_n 8154 8155 crop 5,5,{w-6},{h-6} # Remove frame added by '_gallery' 8156 frame 3%,3%,255 rr2d 440,440,0,3 drop_shadow 2,2,2 8157 if $_is_animated rr2d 230,230,0,3 else rr2d 300,300,0,3 fi 8158 100%,100%,1,3,245 blend[^-1] .,alpha,1,1 rm. 8159 if $_is_animated o $filename_thumb,$_fps else o $filename_thumb,60 fi 8160 rm 8161 8162 if $is_input 8163 image.jpg _gallery 8164 rr2d $width,$height,0,5 c 0,255 8165 to "Input",2%,2%,6% 8166 - 255 r $width,$height,1,3,0,0,0.5,0.5 + 255 8167 o $filename_original,60 8168 8169 crop 5,5,{w-6},{h-6} # Remove frame added by '_gallery' 8170 frame 3%,3%,255 rr2d 440,440,0,3 drop_shadow 2,2,2 8171 if $_is_animated rr2d 230,230,0,3 else rr2d 300,300,0,3 fi 8172 100%,100%,1,3,245 blend[^-1] .,alpha,1,1 rm. 8173 o $filename_thumb_original,60 8174 rm 8175 fi 8176 endl fi 8177 8178 is_samesize=0 8179 l[] 8180 $filename_full 8181 width,height={round([w,h]*(max(w,h)<300?1.75:1))} 8182 if isfile(['{/${filename}_original}']) $filename_original is_samesize={w==w#0" && "h==h#0} fi 8183 rm 8184 endl 8185 if !$is_samesize filename_original=$filename_full fi 8186 if !($col%$nb_cols) html=${html}" <tr>\n" fi 8187 if $nb_examples==1 counter= 8188 else counter=" <span class=\"gallery_caption\">"[{$>+1}/$nb_examples]"</span>" 8189 fi 8190 html_etime= 8191 if narg($etime) html_etime="<br/><span class=\"gallery_caption\">(generated in "${etime}"s)</span>" fi 8192 8193 html_codesample= 8194 if $is_codesample 8195 html_codesample="\n <div id=\"dialog"$nex"\" title=\""samples/$basename_codesample"\">"\ 8196 "\n <pre class>\n" 8197 it[] $url_codesample html_codesample=${html_codesample}{t} rm. 8198 html_codesample=${html_codesample}"\n</pre></div>\n"\ 8199 "<br/><script>$( function() { $( \"#dialog"$nex"\" )."\ 8200 "dialog({ autoOpen: false, width:600 }); } );</script>\n 8201 <a onclick=\"javascript:$( '#dialog"$nex"' ).dialog( 'open' );\" 8202 style=\"cursor: pointer;\"><span class=\"gallery_caption\">[ Source code ]</p></a>\n" 8203 fi 8204 if ['$_label']==0 _label=$command$counter else ('$_label') replace_str. "~"," " _label={t} rm. fi 8205 if $is_input 8206 html=${html}\ 8207 " <td><div><a href=\"#\" onclick=\"return hs.htmlExpand(this, { width: "{$width+64}","\ 8208 "height: "{$height+64}" })\">\n"\ 8209 " <img alt=\""gallery_$command$nex"\" src=\""$filename_thumb"\" "\ 8210 "onmouseover=\"javascript:this.src='"$filename_thumb_original"';\" 8211 onmouseout=\"javascript:this.src='"$filename_thumb"';\"/><br/><b>"\ 8212 ${_label}${html_codesample}"</b></a>\n"\ 8213 " <div class=\"highslide-maincontent\">\n"\ 8214 " <img alt=\""gallery_$command$nex"\" width=\""$width"\" "\ 8215 "src=\""$filename_full"\" 8216 onclick=\"hs.close()\" onmouseover=\"javascript:this.src='"$filename_full"';\" 8217 onmouseout=\"javascript:this.src='"$filename_original"';\"/>\n"\ 8218 " </div>\n"\ 8219 " <div class=\"highslide-caption\">Command: "\ 8220 "<samp>$ gmic "${replaced_example$nex}"</samp>"\ 8221 ${html_etime}"</div></div></td>\n" 8222 else 8223 html=${html}\ 8224 " <td><div><a href=\"#\" onclick=\"return hs.htmlExpand(this, { width: "{$width+64}","\ 8225 "height: "{$height+64}" })\">\n"\ 8226 " <img alt=\""gallery_$command$nex"\" src=\""$filename_thumb"\" />"\ 8227 "<br/><b>"\ 8228 ${_label}${html_codesample}"</b></a>\n"\ 8229 " <div class=\"highslide-maincontent\">\n"\ 8230 " <img alt=\""gallery_$command$nex"\" width=\""$width"\" "\ 8231 "src=\""$filename_full"\" onclick=\"hs.close()\" />\n"\ 8232 " </div>\n"\ 8233 " <div class=\"highslide-caption\">Command: "\ 8234 "<samp>$ gmic "${replaced_example$nex}"</samp>"\ 8235 ${html_etime}"</div></div></td>\n" 8236 fi 8237 nex+=1 8238 col={($col+1)%$nb_cols} 8239 if !$col html=${html}" </tr>\n" fi 8240 done 8241 fi 8242 rm 8243 endl 8244 done 8245 if $col html=${html}" <td colspan=\""{$nb_cols-$col}"\"></td></tr>\n" fi 8246 html=${html}" </table><br/>\n"\ 8247 ${html_menu}\ 8248 " </div><div class=\"section_end\"></div>"\n" <div id=\"include_footer\"></div>"\n" </body>" 8249 ('$html') ot. $category.html rm. 8250 done 8251 rm 8252 8253 # Transfer on G'MIC server 8254 x "ln -fs artistic.html index.html" 8255 if $1 8256 e[] "\n * Transfer gallery on G'MIC server.\n" 8257 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"mirror -eRL . /www/gmic/gallery ; quit\"" 8258 fi 8259 e[] " * All done!\n" 8260 8261# Generate a single image from a list of images, for the gallery. 8262_gallery : 8263 repeat $! l[$>] W$>={w} H$>={h} D$>={d} S$>={s} IS_3D$>=${-_is_3d} endl done 8264 repeat $! l[$>] 8265 if ${IS_3D$>} r3d 1,1,0,-80 r3d 0,1,0,80 snapshot3d 400 8266 else if w>8192 z 0,8191 elif h>8192 rows 0,8191 fi n 0,255 8267 fi 8268 endl done 8269 8270 if !$_is_animated 8271 +__gallery 8272 if w>1024 r={round(1024*100/w,0.1)} r[^-1] $r%,$r%,1,100%,2 fi rm. 8273 fi 8274 8275 repeat $! l[$>] 8276 if s==1 r {w},{h},1,3 8277 elif s==4 drgba 8278 else r {w},{h},1,3,0 fi 8279 if w<=h" && "h<256 r2dy 256,2 elif h<=w" && "w<256 r2dx 256,2 fi 8280 if w<=h" && "h>620 r2dy 620,2 elif h<=w" && "w>620 r2dx 620,2 fi 8281 if h<48 r 100%,48 fi 8282 if w<48 r 48,100% fi 8283 if $_is_animated" && "(w>480" || "h>480) rr2d 480,480,0,2 fi 8284 frame 1,1,0 frame 4,4,255 8285 endl done 8286 8287 if $_is_animated 8288 - 255 r ${-max_wh},1,3,0,0,0.5,0.5 + 255 8289 else 8290 - 255 __gallery + 255 8291 if w<256 - 255 r 256,100%,1,100%,0,0,0.5,0.5 + 255 fi 8292 if h<256 - 255 r 100%,256,1,100%,0,0,0.5,0.5 + 255 fi 8293 fi 8294 8295__gallery : 8296 if $!==2 if w>h a y else a x fi 8297 else montage A # append_tiles 2 8298 fi 8299 8300# Generate reference documentation pages for the G'MIC website. 8301# $1 = upload to G'MIC server, can be { 0 | 1 }. 8302update_reference_html : check "isbool(${1=0})" 8303 path_current=${-path_current} path_ok=$HOME/work/src/gmic/html/reference/ 8304 if ['$path_current']!=['$path_ok'] 8305 error[0--3] "Command 'update_reference_html: Command run from wrong path: '"$path_current"', "\ 8306 "should be '"$path_ok"'." 8307 fi 8308 x "rm -f *.pdf" 8309 8310 rm 8311 e[^-1] "Generate reference documentation pages for the G'MIC website." 8312 it $HOME/work/src/gmic/src/gmic_stdlib.gmic 8313 a y 8314 8315 # Generate image of examples. 8316 x "mkdir -p img" 8317 _parse_cli_images_path="img/" 8318 +parse_cli images 8319 parse_cli html 8320 8321 # Generate reference pages in html. 8322 rm 8323 x "cp -rf "$HOME/work/src/gmic-community/reference/images" ." 8324 reference html,$HOME/work/src/gmic-community/reference 8325 8326 # Upload to G'MIC server. 8327 if $1 8328 e[] "\n > Transfer reference documentation on G'MIC server.\n" 8329 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"mirror -RL . /www/gmic/reference ; quit\"" 8330 fi 8331 e[] "\n > All done.\n" 8332 8333# Generate tutorial pages for the G'MIC website. 8334# $1 = upload to G'MIC server, can be { 0 | 1 }. 8335update_tutorial_html : check "isbool(${1=0})" 8336 path_current=${-path_current} path_ok=$HOME/work/src/gmic/html/tutorial/ 8337 if ['$path_current']!=['$path_ok'] 8338 error[0--3] "Command 'update_tutorial_html: Command run from wrong path: '"$path_current"', "\ 8339 "should be '"$path_ok"'." 8340 fi 8341 8342 rm 8343 e[^-1] "Generate tutorial pages for the G'MIC website." 8344 path_tutorial=$HOME/work/src/gmic-community/tutorial 8345 use_vt100 8346 8347 # Build directory structure. 8348 e[] " > Build directory structure." 8349 x "mkdir -p images scripts" 8350 files 5,$path_tutorial/* 8351 l[] 8352 ({'${}'}:y) s -,{','} 8353 for $! 8354 file={0,t} rm[0] 8355 basename $file basename=${} 0 nm. $basename ext={`lowercase(['{x}'])`} rm. 8356 if ['$basename']!='img' 8357 if isdir(['$file']) files 5,$file/* ({'${}'}:y) s. -,{','} # Folder -> Recursively add files 8358 elif s=['$ext'];s=='png'||s=='jpg'||s=='jpeg'||s=='gif'||s=='mp4'||s=='svg' 8359 x "cp -f \""$file"\" images/" # Image/videos: Copy to sub-folder 'images/' 8360 elif s=['$ext'];s=='gmic' 8361 x "cp -f \""$file"\" scripts/" # Scripts: Copy to sub-folder 'scripts/' 8362 elif s=['$ext'];s=='gmd' # G'MIC Markdown -> Copy to current folder './' 8363 it[] $file 8364 ot. $basename rm. 8365 fi 8366 fi 8367 done 8368 endl 8369 8370 # Generate html pages. 8371 files 0,*.gmd files=${} 8372 repeat narg({/$files}) 8373 arg0 $>,$files file=${} 8374 e[] " > Generate '"$_vt100_c$file$_vt100_n"'." 8375 t0=$| 8376 it $file 8377 replace_str. "../listmanip/","" 8378 gmd2html 2 8379 ot {n} rm. 8380 t1=$| 8381 e[] "\r > Generate '"$_vt100_c$file$_vt100_n"' (done in "$_vt100_g{_round($t1-$t0,0.1)}"s"$_vt100_n")." 8382 done 8383 x "rm -f *.gmd" 8384 8385 # Upload to G'MIC server. 8386 if $1 8387 e[] "\n > Transfer tutorial pages on G'MIC server.\n" 8388 x "lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"mirror -RL . /www/gmic/tutorial ; quit\"" 8389 fi 8390 e[] "\n > All done.\n" 8391 8392# string2ts : ts_file.ts,strings_en.txt,strings_fr.txt 8393# Regenerate .ts file from new translated strings (separated by newline in files strings_*). 8394# Specified .ts file can be an empty argument (""). 8395strings2ts : skip "${1=}" 8396 e[^-1] "Regenerate translation file by merging file '$1' and source/translated strings '$2/$3'." 8397 8398 # Import data and extract original/translated strings. 8399 if narg($1) 8400 l[] it "$1" 8401 lang={`" 8402 lang = vector256(); 8403 p = find(#-1,'language=\"'); 8404 p>=0?( 8405 p+=10; 8406 q = find(#-1,'\">',p); 8407 q>=0?copy(lang,i[p],q - p); 8408 ); lang"`} 8409 e[] " > File '$1', detected language : "$lang. 8410 s -,10 8411 N0=0 8412 repeat $! l[$>] 8413 autocrop {'" "'} 8414 if s=crop();find(s,'<source>')>=0" && "find(s,'</source>')>=0 8415 discard {'<source>'} discard {'</source>'} src$N0={t} 8416 elif s=crop();find(s,'<translation>')>=0" && "find(s,'</translation>')>=0 8417 discard {'<translation>'} discard {'</translation>'} dest$N0={t} 8418 N0+=1 8419 fi 8420 endl done 8421 rm 8422 endl 8423 else N0=0 lang= 8424 fi 8425 if $N0 e[] " > File '$1' contains "$N0" strings." fi 8426 l[] it "$2" s -,10 N1=$! repeat $! nsrc$>={$>,t} done rm endl 8427 l[] it "$3" replace_str " ;",";" s -,10 N2=$! repeat $! ndest$>={$>,t} done rm endl 8428 if $N1!=$N2 error[0--3] "Command 'strings2ts': Number of lines do not match in files '$2' and '$3'." fi 8429 e[] " > Files '$2' and '$3' contain "$N1" strings." 8430 8431 # Merge all strings together (set higher priority to strings that were already in the .ts file). 8432 l[] repeat $N1 ({'${ndest$>}'}) nm. ${nsrc$>} done y endl 8433 repeat $N0 rmn ${src$>} done # Discard already-translated strings in the .ts file 8434 if $N0 i[0] 0 l[0] rm repeat $N0 i ({'${dest$>}'}) nm. ${src$>} done y endl fi 8435 repeat $! l[$<] src={n} dest={t} 8436 if lowercase(['$src'])==lowercase(['$dest']) rm fi 8437 endl done 8438 sort_list +,n 8439 e[] " > "$!" strings remain after cleaning/merging ("{$!-$N0}" new)." 8440 8441 # Generate .ts file. 8442 repeat $! l[$>] 8443 _strings2ts_src {n} src=${} 8444 _strings2ts_dest {t} dest=${} 8445 rm 8446 ({'" <message>"\n\ 8447 " <source>"$src"</source>"\n\ 8448 " <translation>"$dest"</translation>"\n\ 8449 " </message>"\n\n'}) 8450 endl done 8451 i[0] ({'"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\n\ 8452 "<!DOCTYPE TS>"\n\ 8453 "<TS version=\"2.1\" language=\""$lang"\">"\n\ 8454 " <context>"\n\ 8455 " <name>FilterTextTranslator</name>"\n\n'}) 8456 ({'" </context>"\n\ 8457 "</TS>"\n'}) 8458 y a y 8459 8460_strings2ts_src : 8461 ({'"$*"'}) 8462 replace_str. "°","°" 8463 replace_str. "à","à" 8464 replace_str. "&","&" 8465 replace_str. "<","<" 8466 replace_str. ">",">" 8467 replace_str. "\"",""" 8468 replace_str. "'","'" 8469 u {t} 8470 rm. 8471 8472_strings2ts_dest : 8473 ({'"$*"'}) html2utf8. 8474 replace_str. "°","°" 8475 replace_str. "à","à" 8476 replace_str. "&","&" 8477 replace_str. "<","<" 8478 replace_str. ">",">" 8479 replace_str. "\"",""" 8480 replace_str. "'","'" 8481 u {t} 8482 rm. 8483 8484# 8485# Output mode 'zart' (output in stdout). 8486# 8487parse_gui_parseparams_zart : u 1 # Tell parser to not parse filter parameters 8488parse_gui_trigger_zart : 8489 repeat $! l[$>] # Keep only 1-level folders 8490 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`} 8491 endl done 8492 sort_list +,n 8493 8494parse_gui_zart : 8495 e[] " >> Generate output, in 'zart' mode.\n" 8496 +e[] "<?xml version=\"1.0\" ?>" 8497 +e[] "<document name=\"Presets\">\n" 8498 8499 current_group= 8500 N={$_nbfilters-1} 8501 repeat $_nbfilters,f 8502 e[] "\r >> "$_vt100_c[#$f/$N]$_vt100_n" "{`copy(vector48(_'" "'),['${_f${f}_path}${_f${f}_name}'])`} 8503 8504 # Manage groups. 8505 0 nm. {`s=['${_f${f}_path}'];s[0,size(s)-1]`} path={b} rm. 8506 if ['$current_group']!=['$path'] 8507 if ['$current_group']!=0 +e[] "</preset_group>\n" fi 8508 +e[] "<!-- ******** \n\n "$path"\n\n ******** -->" 8509 +e[] "<preset_group name=\""$path"\">\n" 8510 current_group=$path 8511 fi 8512 8513 # Filter definition. 8514 _parse_gui_zart[] ${_f${f}_name} fname=${} 8515 8516 +e[] "<!-- "$path/$fname" -->" 8517 +e[] "<preset name=\""$fname"\">" 8518 +e[] " <command>"${_f${f}_commandpreview}" $""*</command>" 8519 repeat ${_f${f}_nbparams},p 8520 _parse_gui_zart ${_f${f}_p{$p}_name} name=${} 8521 type=${_f${f}_p{$p}_type} 8522 nbargs=${_f${f}_p{$p}_nbargs} 8523 arg0= repeat $nbargs ('${_f${f}_p${p}_a$>}') autocrop. {'\"'} _parse_gui_zart {t} arg$>=${} rm. done 8524 8525 if ['$type']=='bool' 8526 if lowercase(['$arg0'])=='false' arg0=0 elif lowercase(['$arg0'])=='true' arg0=1 elif !isnum($arg0) arg0=0 fi 8527 +e[] " <bool name=\""$name"\" default=\""$arg0"\" />" 8528 8529 elif ['$type']=='choice' 8530 default=0 n=0 args= 8531 l[] if isint($arg0) default=$arg0 n+=1 fi onfail endl 8532 c= repeat $nbargs-$n,a args.=${c}"choice"$>"=\""${arg{$n+$a}}"\"" c=" " done 8533 +e[] " <choice name=\""$name"\" default=\""$default"\" "$args" />" 8534 8535 elif ['$type']=='color' 8536 args= c= repeat $nbargs,a args.=$c${arg$a} c="," done 8537 +e[] " <color name=\""$name"\" default=\""$args"\" />" 8538 8539 elif s=['$type'];s=='int'" || "s=='float' 8540 +e[] " <"$type" name=\""$name"\" default=\""$arg0"\" min=\""$arg1"\" max=\""$arg2"\" />" 8541 8542 elif ['$type']=='file'" || "['$type']=='filein'" || "['$type']=='fileout' 8543 +e[] " <file name=\""$name"\" default=\""$arg0"\" />" 8544 8545 elif ['$type']=='folder' 8546 +e[] " <folder name=\""$name"\" default=\""$arg0"\" />" 8547 8548 elif ['$type']=='link' 8549 align=-1 name= url= n=0 8550 l[] if isnum($arg0) align=$arg0 n+=1 fi onfail endl 8551 if $nbargs-$n>1 name=${arg$n} url=${arg{$n+1}} 8552 else url,name=${arg$n} 8553 fi 8554 if $align==0 align=left elif $align==1 align=right else align=center fi 8555 +e[] " <link name=\""$name"\" url=\""$url"\" align=\""$align"\" />" 8556 8557 elif ['$type']=='note' 8558 text={/$arg0} 8559 +e[] " <note text=\""$text"\" />" 8560 8561 elif ['$type']=='point' 8562 +e[] " <point name=\""$name"\" position=\""$arg0,$arg1"\" />" 8563 8564 elif ['$type']=='separator' 8565 +e[] " <separator />" 8566 8567 elif ['$type']=='text' 8568 +e[] " <text name=\""$name"\" default=\""$arg0"\" />" 8569 8570 elif ['$type']=='value' 8571 +e[] " <value value=\""$arg0"\" />" 8572 8573 else # Unsupported parameter 8574 +e[] " <value value=\""$arg0"\" />" 8575 fi 8576 8577 done 8578 +e[] "</preset>\n" 8579 done 8580 if narg($current_group) +e[] "</preset_group>" fi 8581 +e[] "</document>" 8582 e[] "\r >> "${_vt100_g}{`copy(vector64(_'" "'),'"Output done!"')`}$_vt100_n 8583 8584_parse_gui_zart : 8585 l[] 8586 ('"$*"') 8587 replace_str "&","#amp;" 8588 replace_str. "&","&" 8589 replace_str. "<","<" 8590 replace_str. ">",">" 8591 replace_str. "\"",""" 8592 replace_str "#amp;","&" 8593 u {t} rm. 8594 onfail u "" endl 8595 8596# Convert last ascii buffer with html codes (e.g. 配), as an UTF-8 encoded buffer. 8597html2utf8 : 8598 if h 8599 eval " 8600 ref(crop(),source); 8601 ref(vector8(),svalue); 8602 p = 0; 8603 while (1, 8604 p = p0 = find(source,'&#',p); 8605 p<0?break(); 8606 p+=2; 8607 p>=size(source)?break(); 8608 q = find(source,';',p); 8609 q>p && q<=p+8 && !isnan(val=stov(source,p))?( 8610 copy(svalue,source[p],q-p); svalue[q-p] = 0; 8611 val = stov(svalue,0,1); 8612 !isnan(val) && isint(val) && val>0?( 8613 8614 # Encode in UTF-8. 8615 val<=0x007f?( # 7 bits or less -> 1 byte 8616 i[p0++] = val; 8617 ):val<=0x07ff?( # 11 bits or less -> 2 bytes 8618 i[p0++] = (val>>6)|0xc0; 8619 i[p0++] = (val&0x3f)|0x80; 8620 ):val<=0xffff?( # 16 bits or less -> 3 bytes 8621 i[p0++] = (val>>12)|0xe0; 8622 i[p0++] = ((val>>6)&0x3f)|0x80; 8623 i[p0++] = (val&0x3f)|0x80; 8624 ):( # 21 bits or less -> 4 bytes 8625 i[p0++] = (val>>18)|0xf0; 8626 i[p0++] = ((val>>12)&0x3f)|0x80; 8627 i[p0++] = ((val>>6)&0x3f)|0x80; 8628 i[p0++] = (val&0x3f)|0x80; 8629 ); 8630 copy(i[p0],-1,q-p0+1,1,0); 8631 p = q + 1; 8632 ); 8633 ); 8634 )" 8635 discard. -1 8636 fi 8637 8638# Convert last UTF-8 encoded buffer to ascii buffer with html codes. 8639utf82html : 8640 if h 8641 eval " 8642 write_seq() = ( copy(res[q],'&#'); q+=2; s = vtos(val); l = find(s,0); copy(res[q],s,l); q+=l; res[q++]=_';' ); 8643 ref(vector(#4*wh),res); 8644 q = 0; 8645 repeat (wh,p, 8646 i = i[p]; 8647 !(i&0x80)?( # 1-byte 8648 res[q++] = i; 8649 ):(i&0xe0)==0xc0?( # 2-bytes 8650 val = (i&0x1f)<<6; i = i[p + 1]; val|= (i&0x3f); 8651 write_seq(); 8652 ):(i&0xf0)==0xe0?( # 3-bytes 8653 val = (i&0xf)<<12; i = i[p + 1]; val|= (i&0x3f)<<6; i = i[p + 2]; val|= (i&0x3f); 8654 write_seq(); 8655 ):(i&0xf8)==0xf0?( # 4-bytes 8656 val = (i&0x7)<<18; i = i[p + 1]; val|= (i&0x3f)<<12; i = i[p + 2]; val|= (i&0x3f)<<6; 8657 i = i[p + 3]; val|= (i&0x3f); 8658 write_seq(); 8659 ); 8660 ); 8661 store(res,'res',1,q)" 8662 rm. $res 8663 fi 8664 8665# Force certain filters to move from one path to another. 8666_upload_filters_move : 8667 m "move_filter : skip \"${""2=}\" nmd 3,\"$""1\" ind=${} 8668 if $ind basename \"$""1\" nm[$ind] \"$""2\"/${} 8669 else v 0 e[0--4] \"Cannot move unknown filter '\"${_vt100_r}\"$""1\"${_vt100_n}\"' 8670 to '\"${_vt100_g}\"$""2\"${_vt100_n}\"'\" fi" 8671 8672 sort_list +,n 8673 move_filter "Testing/Garagecoder/Anti Alias","Repair" 8674 move_filter "Testing/Garagecoder/Auto Balance","Colors" 8675 move_filter "Testing/Garagecoder/Compression Blur","Repair" 8676 move_filter "Testing/Garagecoder/Emboss","Black & White" 8677 move_filter "Testing/Garagecoder/JPEG Smooth","Repair" 8678 move_filter "Testing/Garagecoder/Quick Tonemap","Details" 8679 move_filter "Testing/Garagecoder/Normalize Brightness","Colors" 8680 move_filter "Testing/Garagecoder/Sharpen [Gradient]","Details" 8681 move_filter "Testing/Garagecoder/Sharpen [Tones]","Details" 8682 move_filter "Testing/Garagecoder/Temperature Balance","Colors" 8683 move_filter "Testing/Garagecoder/Unquantize [JPEG Smooth]","Repair" 8684 move_filter "Testing/Garagecoder/Upscale [Edge]","Repair" 8685 move_filter "Testing/Garagecoder/Wiremap","Rendering" 8686 move_filter "Testing/Garagecoder/Smooth [Geometric-Median]","Repair" 8687 move_filter "Testing/Gmic Tutorials/Hedcut (Experimental)","Patterns" 8688 move_filter "Testing/Iain Fergusson/Easy Skin Retouch","Details" 8689 move_filter "Testing/Iain Fergusson/Moire Removal","Repair" 8690 move_filter "Testing/Iain Fergusson/Halftone Shapes","Patterns" 8691 move_filter "Testing/Iain Fergusson/Simple Local Contrast","Details" 8692 move_filter "Testing/Iain Fergusson/Turbulent Halftone","Patterns" 8693 move_filter "Testing/Joan Rake/Deformations/Ultrawarp++++","Degradations" 8694 move_filter "Testing/Naggobot/Blockism","Artistic" 8695 move_filter "Testing/Reptorian/Blur [Splinter]","Degradations" 8696 move_filter "Testing/Reptorian/Construction Material Texture","Rendering" 8697 move_filter "Testing/Reptorian/Emboss-Relief","Details" 8698 move_filter "Testing/Reptorian/Fragment Blur","Degradations" 8699 move_filter "Testing/Reptorian/Kaleidoscope [Reptorian-Polar]","Deformations" 8700 move_filter "Testing/Reptorian/Logarithmic Distortion","Deformations" 8701 move_filter "Testing/Reptorian/Nebulous","Rendering" 8702 move_filter "Testing/Reptorian/Pixel Push","Deformations" 8703 move_filter "Testing/Reptorian/Point Warp","Deformations" 8704 move_filter "Testing/Reptorian/Popcorn Fractal","Rendering" 8705 move_filter "Testing/Reptorian/Pseudorandom Noise","Rendering" 8706 move_filter "Testing/Reptorian/Sinusoidal Water Distortion","Deformations" 8707 move_filter "Testing/Samj/Arrays & Tiles/Annular Steiner Chain Round Tile","Arrays & Tiles" 8708 move_filter "Testing/Samj/Arrays & Tiles/Reptile","Patterns" 8709 move_filter "Testing/Samj/Artistic/Angoisse Anguish","Artistic" 8710 move_filter "Testing/Samj/Artistic/Chalk It Up [Fr]","Artistic" 8711 move_filter "Testing/Samj/Artistic/Barbouillage Paint Daub","Artistic" 8712 move_filter "Testing/Samj/Artistic/Skeletik","Artistic" 8713 move_filter "Testing/Samj/Patterns/Denim Texture","Patterns" 8714 move_filter "Testing/Samj/Patterns/Soft Random Shades","Patterns" 8715 move_filter "Testing/Samj/Rendering/Pythagoras Tree","Rendering" 8716 move_filter "Testing/Samj/Rendering/Snowflake 2","Rendering" 8717 move_filter "Testing/Samj/Rendering/Twisted Rays","Rendering" 8718 move_filter "Testing/Souphead/Disco","Rendering" 8719 move_filter "Testing/Souphead/Moon2panorama","Deformations" 8720 move_filter "Testing/Souphead/Spiral RGB","Rendering" 8721 move_filter "Testing/Souphead/Kitaoka Spin Illusion","Rendering" 8722 move_filter "Testing/Zonderr/Spiral","Rendering" 8723 um move_filter 8724 8725upload_filters : 8726 e[^-1] "Upload filter definition file on G'MIC server.\n" 8727 rm 8728 8729 # Be sure to get the latest version of filters. 8730 x "cd "$HOME"/work/src/gmic && git pull" 8731 x "cd "$HOME"/work/src/gmic-community && git pull" 8732 8733 # Define the list of compatible versions. 8734 (298,$_version) store. compat 8735 8736 # Import filters from stdlib and community. 8737 files $HOME/work/src/gmic-community/include/*.gmic 8738 files=${},$HOME/work/src/gmic/src/gmic_stdlib.gmic 8739 repeat narg($files) l[] 8740 file=${"arg 1+$>,"$files} 8741 it[] $file 8742 basename $file basename=${} 8743 if ['$basename']=='sylvie_alexandre.gmic' 8744 s +,{'"#@gui <b>"'} i[1--2:2] ('"#@gui ________<b>Testing<b>\n#@gui <i>Samj</i>\n"') y a y 8745 elif s=['$basename'];s=='template.gmic' 8746 rm 0 8747 fi 8748 endl done 8749 i[1--2] ('"#@gui _________________\n"') y a y 8750 8751 # Create update file. 8752 +l. 8753 e[] "** Generate filter update file." 8754 m "parse_gui_trigger_update : _upload_filters_move" 8755 v + parse_gui. update v - 8756 um parse_gui_trigger_update 8757 8758 # Upload filter files on G'MIC server. 8759 e[] "** Upload filter update." 8760 ot ${_path_rc}update$_version.gmic 8761 if "d = date(3); h = date(4); h>=7 && d>=1 && d<=5" url=http://bit.ly/2CmhX65 # url=http://bit.ly/2uaBRMB 8762 else url=https://bit.ly/33lRzX4 # https://bit.ly/2WeKVPv url=http://bit.ly/2uaBRMB # 8763 fi 8764 replace_str "<i>David Tschumperlé</i>","<i><a href=\""$url"\">David Tschumperlé</a></i>" 8765 o cimgz:/tmp/update$_version.gmic,uchar 8766 8767 $compat 8768 repeat w 8769 v={i[$>]} 8770 _upload[] ${_path_rc}update$_version.gmic,plain_update$v.gmic,1 8771 _upload[] /tmp/update$_version.gmic,update$v.gmic,1 8772 done 8773 rm 8774 endl 8775 8776 # Create JSON file. 8777 +l. 8778 e[] "** Generate JSON filters file." 8779 v + parse_gui. json v - 8780 8781 # Upload filter files on G'MIC server. 8782 e[] "** Upload JSON filters." 8783 ot ${_path_rc}/update$_version.json 8784 8785 $compat 8786 repeat w 8787 v={i[$>]} 8788 _upload[] ${_path_rc}/update$_version.json,update$v.json,1 8789 done 8790 rm 8791 endl 8792 8793 # Create filter listing. 8794 +l. 8795 e[] "** Generate filter listing." 8796 v + parse_gui. list v - 8797 ot /tmp/gui_filters.txt 8798 rm 8799 endl 8800 rm 8801 8802_upload : skip "${2=""}","${3=0}" 8803 if narg("$2") out="$2" else basename "$1" out=${} fi 8804 if !narg($GMIC_LOGIN) 8805 GMIC_LOGIN=${"gmic_ftp 0"} 8806 GMIC_PASSWD=${"gmic_ftp 1"} 8807 GMIC_FTP=${"gmic_ftp 2"} 8808 fi 8809 if narg($GMIC_LOGIN) 8810 x $3,"lftp ftp://"$GMIC_LOGIN":"$GMIC_PASSWD"@"$GMIC_FTP" -e \"put -O /www/gmic/ \\\"$1\\\" -o \\\""$out"\\\"; 8811 quit\" >/dev/null" 8812 fi 8813 8814# Upload or list released binaries on the G'MIC web server. 8815# $1=version number (e.g "1.6.7_pre") 8816# $2={ 0=print list of URLs | 1=upload files } 8817upload_binaries : check "isbool(${2=1})" 8818 is_pre=${"strcontains $1,_pre"} 8819 N=0 8820 file$N=gmic_$1_debian9-2_stretch_amd64.deb N+=1 8821 file$N=gmic_$1_debian10_buster_amd64.deb N+=1 8822 file$N=gmic_$1_ubuntu18-04_bionic_amd64.deb N+=1 8823 file$N=gmic_$1_ubuntu18-10_cosmic_amd64.deb N+=1 8824 file$N=gmic_$1_ubuntu19-04_disco_amd64.deb N+=1 8825 file$N=gmic_$1_ubuntu19-10_eoan_amd64.deb N+=1 8826 file$N=gmic_$1_ubuntu20-04_focal_amd64.deb N+=1 8827 file$N=gmic_$1_ubuntu20-10_groovy_amd64.deb N+=1 8828 file$N=gmic_$1_ubuntu21-04_hirsute_amd64.deb N+=1 8829 8830 file$N=gmic_$1_gimp2.8_debian9-2_stretch_amd64.zip N+=1 8831 file$N=gmic_$1_gimp2.10_debian10_buster_amd64.zip N+=1 8832 file$N=gmic_$1_gimp2.8_ubuntu18-04_bionic_amd64.zip N+=1 8833 file$N=gmic_$1_gimp2.10_ubuntu18-10_cosmic_amd64.zip N+=1 8834 file$N=gmic_$1_gimp2.10_ubuntu19-04_disco_amd64.zip N+=1 8835 file$N=gmic_$1_gimp2.10_ubuntu19-10_eoan_amd64.zip N+=1 8836 file$N=gmic_$1_gimp2.10_ubuntu20-04_focal_amd64.zip N+=1 8837 file$N=gmic_$1_gimp2.10_ubuntu20-10_groovy_amd64.zip N+=1 8838 file$N=gmic_$1_gimp2.10_ubuntu21-04_hirsute_amd64.zip N+=1 8839 8840 file$N=gmic_$1_krita_debian9-2_stretch_amd64.zip N+=1 8841 file$N=gmic_$1_krita_debian10_buster_amd64.zip N+=1 8842 file$N=gmic_$1_krita_ubuntu18-04_bionic_amd64.zip N+=1 8843 file$N=gmic_$1_krita_ubuntu18-10_cosmic_amd64.zip N+=1 8844 file$N=gmic_$1_krita_ubuntu19-04_disco_amd64.zip N+=1 8845 file$N=gmic_$1_krita_ubuntu19-10_eoan_amd64.zip N+=1 8846 file$N=gmic_$1_krita_ubuntu20-04_focal_amd64.zip N+=1 8847 file$N=gmic_$1_krita_ubuntu20-10_groovy_amd64.zip N+=1 8848 file$N=gmic_$1_krita_ubuntu21-04_hirsute_amd64.zip N+=1 8849 8850 file$N=gmic_$1_cli_win64.zip N+=1 8851 file$N=gmic_$1_lib_win64.zip N+=1 8852 file$N=gmic_$1_qt_win64.zip N+=1 8853 file$N=gmic_$1_gimp2.10_win64.zip N+=1 8854 file$N=gmic_$1_gimp2.10_win64.exe N+=1 8855 file$N=gmic_$1_krita_win64.zip N+=1 8856 8857 if !$2 # Only get list of URLs 8858 e[0--3] "List URLs of released binaries ($1) from the G'MIC web server.\n" 8859 repeat $N 8860 file=${file$>} 8861 is_win=${strcontains[]" "$file,win} 8862 if $is_win folder="windows" else folder="linux" fi 8863 e[] "http://gmic.eu/files/"$folder/$file 8864 done 8865 e[] "" 8866 8867 else # Upload files 8868 e[0--3] "Upload released binaries ($1) on the G'MIC web server." 8869 8870 t0=$| n=0 t=0 8871 e[] "- Waiting for binary files to be build." 8872 do 8873 repeat $N 8874 file=${file$>} 8875 if isfile(['{/$file}']) 8876 strreplace $file,_$1_,_ 8877 file_short=${} 8878 is_win=${strcontains[]" "$file,win} 8879 if $is_win folder="windows" else folder="linux" fi 8880 e[] "- Upload file '"$file"' to 'https://gmic.eu/files/prerelease/"$file_short"'." 8881 _upload[] $file,"files/prerelease/"$file_short 8882 if !$is_pre 8883 e[] "- Upload file '"$file"' to 'https://gmic.eu/files/"$folder/$file"'." 8884 _upload[] $file,"files/"$folder/$file 8885 fi 8886 8887 file$>= n+=1 8888 fi 8889 done 8890 if $n<$N 8891 if !($t%4) 8892 remaining= sep= 8893 repeat $N if narg(${file$>}) remaining.=${sep}${file$>} sep=", " fi done 8894 e[] "- Waiting for files: "$remaining"." 8895 fi 8896 wait 30000 t+=1 8897 fi 8898 while $n<$N" && "$|<$t0+60*60*6 8899 if $n<$N e[] "- Partial uploads done (timeout reached)." 8900 else e[] "- All uploads done !" 8901 fi 8902 fi 8903 8904# Update version number in html header file. 8905# (works both for CImg and G'MIC !) 8906# $1 = filename 8907# $2 = version number 8908# $3 = is_prerelease = { 0 | 1 } 8909_update_header_html : check "narg(${1=}) && ${2=0}>0 && isbool(${3=0})" 8910 filename="$1" 8911 l[] 8912 it[] $filename 8913 s +,{'\n'} 8914 repeat $! if {$>,h>=64} l[$>] 8915 +autocrop {'" "'} autocrop. {'\t'} 8916 if "find(#0,['Latest stable version: '])>=0" 8917 is_gmic={"find(#-1,'gmic.eu')>=0"} 8918 is_cimg={"find(#-1,'cimg.eu')>=0"} 8919 if !$is_gmic" && "!$is_cimg error "Cannot determine CImg or G'MIC header file." fi 8920 8921 # Retrieve latest stable version specified in the header file. 8922 +l. s -,{'>'} 8923 if {2,"i[0]>=_'0' && i[0]<=_'9' && i[1]==_'.' && i[2]>=_'0' && i[2]<=_'9' && 8924 i[3]==_'.' && i[4]>=_'0' && i[4]<=_'9'"} 8925 sta={2,`crop(0,0,1,5)`} 8926 fi 8927 if $3 pre=${strver\ $2} else sta=${strver\ $2} fi 8928 rm endl 8929 rm[0] 8930 if $is_gmic 8931 i[0] ('" Latest stable version: <b>"\ 8932 "<a href=\"https://gmic.eu/download.html\">"$sta"</a></b>"') 8933 if $3 8934 i[1] ('" "\ 8935 "Current pre-release: <b><a href=\"https://gmic.eu/files/prerelease\">"$pre"</a></b>"') 8936 fi 8937 else 8938 i[0] ('" Latest stable version: "\ 8939 "<b><a href=\"http://cimg.eu/files/CImg_"$sta".zip\">"$sta"</a></b>"') 8940 if $3 8941 i[1] ('" "\ 8942 "Current pre-release: <b><a href=\"http://cimg.eu/files/CImg_latest.zip\">"$pre"</a></b>"') 8943 fi 8944 fi 8945 y 8946 fi 8947 rm. 8948 endl fi done 8949 a y 8950 ot $filename 8951 rm 8952 endl 8953 8954#@cli v : eq. to 'verbose'. : (+) 8955 8956#@cli verbose : level : { + | - } : (+) 8957#@cli : Set or increment/decrement the verbosity level. Default level is 0. 8958#@cli : (eq. to 'v').\n 8959#@cli : When 'level'>0, G'MIC log messages are displayed on the standard error (stderr). 8960#@cli : Default value: 'level=1'. 8961 8962#@cli wait : delay : (no arg) : (+) 8963#@cli : Wait for a given delay (in ms), optionally since the last call to 'wait'. 8964#@cli : or wait for a user event occurring on the selected instant display windows. 8965#@cli : 'delay' can be { <0=delay+flush events | 0=event | >0=delay }. 8966#@cli : Command selection (if any) stands for instant display window indices instead of image indices. 8967#@cli : If no window indices are specified and if 'delay' is positive, the command results 8968#@cli : in a 'hard' sleep during specified delay. 8969#@cli : Default value: 'delay=0'. 8970 8971#@cli warn : _force_visible={ 0 | 1 },_message : (+) 8972#@cli : Print specified warning message, on the standard error (stderr). 8973#@cli : Command selection (if any) stands for displayed call stack subset instead of image indices. 8974 8975#@cli w : eq. to 'window'. : (+) 8976 8977#@cli window : _width[%]>=-1,_height[%]>=-1,_normalization,_fullscreen,_pos_x[%],_pos_y[%],_title : (+) 8978#@cli : Display selected images into an instant display window with specified size, normalization type, 8979#@cli : fullscreen mode and title. 8980#@cli : (eq. to 'w').\n 8981#@cli : If 'width' or 'height' is set to -1, the corresponding dimension is adjusted to the window 8982#@cli : or image size. 8983#@cli : Specify 'pos_x' and 'pos_y' arguments only if the window has to be moved to the specified 8984#@cli : coordinates. Otherwise, they can be avoided. 8985#@cli : 'width'=0 or 'height'=0 closes the instant display window. 8986#@cli : 'normalization' can be { -1=keep same | 0=none | 1=always | 2=1st-time | 3=auto }. 8987#@cli : 'fullscreen' can be { -1=keep same | 0=no | 1=yes }. 8988#@cli : You can manage up to 10 different instant display windows by using the numbered variants 8989#@cli : 'w0' (default, eq. to 'w'),'w1',...,'w9' of the command 'w'. 8990#@cli : Invoke 'window' with no selection to make the window visible, if it has been closed by the user. 8991#@cli : Default values: 'width=height=normalization=fullscreen=-1' and 'title=(undefined)'. 8992 8993#--------------------------------- 8994# 8995#@cli :: List Manipulation 8996# 8997#--------------------------------- 8998 8999#@cli k : eq. to 'keep'. : (+) 9000 9001#@cli keep : (+) 9002#@cli : Keep only selected images. 9003#@cli : (eq. to 'k'). 9004#@cli : $ image.jpg split x keep[0-50%:2] append x 9005#@cli : $ image.jpg split x keep[^30%-70%] append x 9006 9007#@cli mv : eq. to 'move'. : (+) 9008 9009#@cli move : position[%] : (+) 9010#@cli : Move selected images at specified position. 9011#@cli : (eq. to 'mv'). 9012#@cli : $ image.jpg split x,3 move[1] 0 9013#@cli : $ image.jpg split x move[50%--1:2] 0 append x 9014 9015#@cli nm : eq. to 'name'. : (+) 9016 9017#@cli name : "name1","name2",... : (+) 9018#@cli : Set names of selected images. 9019#@cli : - If the selection contains a single image, then it is assumed the command has a single name 9020#@cli : argument (possibly containing multiple comas). 9021#@cli : - If the selection contains more than one image, each command argument defines a single image 9022#@cli : name for each image of the selection. 9023#@cli : (eq. to 'nm'). 9024#@cli : $ image.jpg name image blur[image] 2 9025#@cli : $$ 9026 9027#@cli rm : eq. to 'remove'. : (+) 9028 9029#@cli remove : (+) 9030#@cli : Remove selected images. 9031#@cli : (eq. to 'rm'). 9032#@cli : $ image.jpg split x remove[30%-70%] append x 9033#@cli : $ image.jpg split x remove[0-50%:2] append x 9034 9035#@cli remove_duplicates 9036#@cli : Remove duplicates images in the selected images list. 9037#@cli : $ (1,2,3,4,2,4,3,1,3,4,2,1) split x remove_duplicates append x 9038remove_duplicates : 9039 e[^-1] "Remove duplicates images in selected list of image$?." 9040 repeat $!,base 9041 off=0 9042 repeat $!-$>-1 9043 comp={$base+1+$>-$off} 9044 if $comp>=$! break fi 9045 +-[$base,$comp] abs. is_duplicate={!is} rm. 9046 if $is_duplicate rm[$comp] off+=1 fi 9047 done 9048 done 9049 9050#@cli remove_empty 9051#@cli : Remove empty images in the selected image list. 9052remove_empty : 9053 e[^-1] "Remove empty images in selected list of image$?." 9054 $!,1,1,1,"!w#x?x:-1" discard. -1 rm[{^},-1] 9055 9056#@cli rmn : eq. to 'remove_named'. 9057rmn : 9058 e[^-1] "Remove images named '$*'." 9059 nmd $"*" rm[${}] 9060 9061#@cli remove_named : "name1","name2",... 9062#@cli : Remove all images with specified names from the list of images. 9063#@cli : Does nothing if no images with those names exist. 9064#@cli : (eq. to 'rmn'). 9065remove_named : 9066 e[^-1] "Remove images named '$*'." 9067 nmd $"*" rm[${}] 9068 9069#@cli rv : eq. to 'reverse'. : (+) 9070 9071#@cli reverse : (+) 9072#@cli : Reverse positions of selected images. 9073#@cli : (eq. to 'rv'). 9074#@cli : $ image.jpg split x,3 reverse[-2,-1] 9075#@cli : $ image.jpg split x,-16 reverse[50%-100%] append x 9076 9077#@cli sort_list : _ordering={ + | - },_criterion 9078#@cli : Sort list of selected images according to the specified image criterion. 9079#@cli : Default values: 'ordering=+', 'criterion=i'. 9080#@cli : $ (1;4;7;3;9;2;4;7;6;3;9;1;0;3;3;2) split y sort_list +,i append y 9081sort_list : skip ${1=+},${2=i} 9082 s0="descending" s1="ascending" 9083 e[^-1] "Sort list of image$? in "${s{_'+'=='$1'}}" order, according to the image criterion '$2'." 9084 if $! 9085 if '$2'=='n' # Special case : lexicographic order from image names 9086 op={`;'$1'=='-'?_'>':_'<'`} 9087 $!,1,1,1,"n = name(#x,1024); find(n,0)%1025" slen={iM} rm. # Largest name length. 9088 eval " 9089 const lm1 = l - 1; 9090 const slen = "$slen"; 9091 strcmp(n0,n1) = (for (k = 0, k<slen && !(diff = lowercase(n0[k]) - lowercase(n1[k])), ++k); diff); 9092 quicksort(lo0,hi0) = ( 9093 stack = vector(#2*l); 9094 stacksize = 0; 9095 push(elt0,elt1) = (stack[stacksize++] = elt0; stack[stacksize++] = elt1); 9096 pop() = (_s1 = stack[--stacksize]; _s0 = stack[--stacksize]; [_s0,_s1]); 9097 push(lo0,hi0); 9098 while (stacksize>0, 9099 range = pop(); 9100 lo = range[0]; 9101 hi = range[1]; 9102 pivot = int((lo + hi)/2); 9103 ref(name(#pivot,slen),npivot); 9104 while (lo<hi, 9105 while ((ref(name(#lo,slen),nlo);strcmp(nlo,npivot)<0), ++lo); 9106 while ((ref(name(#hi,slen),nhi);strcmp(npivot,nhi)<0), --hi); 9107 lo<=hi?(lo!=hi?run('rv[',lo,',',hi,']'); ++lo; --hi); 9108 ); 9109 if (range[0]<hi,push(range[0],hi)); 9110 if (lo<range[1],push(lo,range[1])); 9111 ) 9112 ); 9113 quicksort(0,lm1)" 9114 9115 else # Generic case 9116 i=$! repeat $! ({$>,$2}) done a[$i--1] y +f. 'y' a[-2,-1] x sort. $1,y z. 1,1 9117 repeat h nm$>={$>,n} nm[$>] sortlist$> done 9118 repeat h mv[sortlist{i(0,$>)}] -1 done 9119 repeat h nm[$>] ${nm{i(0,$>)}} done 9120 rm. 9121 fi 9122 fi 9123 9124_sort_list_lexi : 9125 u {" 9126 str1 = ['$1']; 9127 str2 = ['$2']; 9128 siz = min(size(str1),size(str2)); 9129 lex = -1; 9130 for (i = 0, i<siz && lex<0, ++i, 9131 s1 = lowercase(str1[i]); 9132 s2 = lowercase(str2[i]); 9133 lex = s1"$3"s2?1:s2"$3"s1?0:-1; 9134 ); 9135 lex<0?size(str1)"$3"size(str2):lex; 9136 "} 9137 9138#--------------------------------- 9139# 9140#@cli :: Mathematical Operators 9141# 9142#--------------------------------- 9143 9144#@cli abs : (+) 9145#@cli : Compute the pointwise absolute values of selected images. 9146#@cli : $ image.jpg +sub {ia} abs[-1] 9147#@cli : $ 300,1,1,1,'cos(20*x/w)' +abs display_graph 400,300 9148 9149#@cli acos : (+) 9150#@cli : Compute the pointwise arccosine of selected images. 9151#@cli : $ image.jpg +normalize -1,1 acos[-1] 9152#@cli : $ 300,1,1,1,'cut(x/w+0.1*u,0,1)' +acos display_graph 400,300 9153#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 9154 9155#@cli acosh : (+) 9156#@cli : Compute the pointwise hyperbolic arccosine of selected images. 9157 9158#@cli + : eq. to 'add'. : (+) 9159 9160#@cli add : value[%] : [image] : 'formula' : (no arg) : (+) 9161#@cli : Add specified value, image or mathematical expression to selected images, \ 9162# or compute the pointwise sum of selected images. 9163#@cli : (eq. to '+'). 9164#@cli : $ image.jpg +add 30% cut 0,255 9165#@cli : $ image.jpg +blur 5 normalize 0,255 add[1] [0] 9166#@cli : $ image.jpg add '80*cos(80*(x/w-0.5)*(y/w-0.5)+c)' cut 0,255 9167#@cli : $ image.jpg repeat 9 +rotate[0] {$>*36},1,0,50%,50% done add div 10 9168 9169#@cli & : eq. to 'and'. : (+) 9170 9171#@cli and : value[%] : [image] : 'formula' : (no arg) : (+) 9172#@cli : Compute the bitwise AND of selected images with specified value, image or mathematical \ 9173# expression, or compute the pointwise sequential bitwise AND of selected images. 9174#@cli : (eq. to '&'). 9175#@cli : $ image.jpg and {128+64} 9176#@cli : $ image.jpg +mirror x and 9177 9178#@cli argmax 9179#@cli : Compute the argmax of selected images. Returns a single image 9180#@cli : with each pixel value being the index of the input image with maximal value. 9181#@cli : $ image.jpg sample lena,lion,square +argmax 9182argmax : 9183 e[^-1] "Compute argmax of image$?." 9184 if !$! return fi 9185 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 9186 ${-max_whds},"argmax("$str")" k. nm [argmax] 9187 9188#@cli argmaxabs 9189#@cli : Compute the argmaxabs of selected images. Returns a single image 9190#@cli : with each pixel value being the index of the input image with maxabs value. 9191argmaxabs : 9192 e[^-1] "Compute argmaxabs of image$?." 9193 if !$! return fi 9194 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 9195 ${-max_whds},"argmaxabs("$str")" k. nm [argmaxabs] 9196 9197#@cli argmin 9198#@cli : Compute the argmin of selected images. Returns a single image 9199#@cli : with each pixel value being the index of the input image with minimal value. 9200#@cli : $ image.jpg sample lena,lion,square +argmin 9201argmin : 9202 e[^-1] "Compute argmin of image$?." 9203 if !$! return fi 9204 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 9205 ${-max_whds},"argmin("$str")" k. nm [argmin] 9206 9207#@cli argminabs 9208#@cli : Compute the argminabs of selected images. Returns a single image 9209#@cli : with each pixel value being the index of the input image with minabs value. 9210argminabs : 9211 e[^-1] "Compute argminabs of image$?." 9212 if !$! return fi 9213 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 9214 ${-max_whds},"argminabs("$str")" k. nm [argminabs] 9215 9216#@cli asin : (+) 9217#@cli : Compute the pointwise arcsine of selected images. 9218#@cli : $ image.jpg +normalize -1,1 asin[-1] 9219#@cli : $ 300,1,1,1,'cut(x/w+0.1*u,0,1)' +asin display_graph 400,300 9220#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 9221 9222#@cli asinh : (+) 9223#@cli : Compute the pointwise hyperbolic arcsine of selected images. 9224 9225#@cli atan : (+) 9226#@cli : Compute the pointwise arctangent of selected images. 9227#@cli : $ image.jpg +normalize 0,8 atan[-1] 9228#@cli : $ 300,1,1,1,'4*x/w+u' +atan display_graph 400,300 9229#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 9230 9231#@cli atan2 : [x_argument] : (+) 9232#@cli : Compute the pointwise oriented arctangent of selected images. 9233#@cli : Each selected image is regarded as the y-argument of the arctangent function, while the 9234#@cli : specified image gives the corresponding x-argument. 9235#@cli : $ (-1,1) (-1;1) resize 400,400,1,1,3 atan2[1] [0] keep[1] mod {pi/8} 9236#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 9237 9238#@cli atanh : (+) 9239#@cli : Compute the pointwise hyperbolic arctangent of selected images. 9240 9241#@cli << : eq. to 'bsl'. : (+) 9242 9243#@cli bsl : value[%] : [image] : 'formula' : (no arg) : (+) 9244#@cli : Compute the bitwise left shift of selected images with specified value, image or \ 9245# mathematical expression, or compute the pointwise sequential bitwise left shift of \ 9246# selected images. 9247#@cli : (eq. to '<<'). 9248#@cli : $ image.jpg bsl 'round(3*x/w,0)' cut 0,255 9249 9250#@cli >> : eq. to 'bsr'. : (+) 9251 9252#@cli bsr : value[%] : [image] : 'formula' : (no arg) : (+) 9253#@cli : Compute the bitwise right shift of selected images with specified value, image or \ 9254# mathematical expression, or compute the pointwise sequential bitwise right shift of \ 9255# selected images. 9256#@cli : (eq. to '>>'). 9257#@cli : $ image.jpg bsr 'round(3*x/w,0)' cut 0,255 9258 9259#@cli cos : (+) 9260#@cli : Compute the pointwise cosine of selected images. 9261#@cli : $ image.jpg +normalize 0,{2*pi} cos[-1] 9262#@cli : $ 300,1,1,1,'20*x/w+u' +cos display_graph 400,300 9263#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 9264 9265#@cli cosh : (+) 9266#@cli : Compute the pointwise hyperbolic cosine of selected images. 9267#@cli : $ image.jpg +normalize -3,3 cosh[-1] 9268#@cli : $ 300,1,1,1,'4*x/w+u' +cosh display_graph 400,300 9269 9270#@cli deg2rad 9271#@cli : Convert pointwise angle values of selected images, from degrees to radians (apply 'i*pi/180'). 9272deg2rad : 9273 e[^-1] "Convert pointwise angle values of image$?, from degrees to radians." 9274 * 0.017453292519943295 9275 9276#@cli / : eq. to 'div'. : (+) 9277 9278#@cli div : value[%] : [image] : 'formula' : (no arg) : (+) 9279#@cli : Divide selected images by specified value, image or mathematical expression, \ 9280# or compute the pointwise quotient of selected images. 9281#@cli : (eq. to '/'). 9282#@cli : $ image.jpg div '1+abs(cos(x/10)*sin(y/10))' 9283#@cli : $ image.jpg +norm add[-1] 1 +div 9284 9285#@cli div_complex : [divider_real,divider_imag],_epsilon>=0 9286#@cli : Perform division of the selected complex pairs (real1,imag1,...,realN,imagN) of images by 9287#@cli : specified complex pair of images (divider_real,divider_imag). 9288#@cli : In complex pairs, the real image must be always located before the imaginary image in the image list. 9289#@cli : Default value: 'epsilon=1e-8'. 9290div_complex : check ${3=1e-8}>=0 9291 e[^-1] "Divide complex pair$? by complex pair "${"pass$1,$2 -1"}" (with epsilon $3)." 9292 repeat int($!/2) pass${1,2} 0 l[$>,{$>+1},-2,-1] 9293 +*[1,2] +*[0,3] -[-2,-1] # bc-ad 9294 *[0] [2] *[1] [3] +[0,1] # ac+bd 9295 sqr[1,2] +[1,2] +[1] $3 # c^2+d^2 9296 /[2] [1] /[0,1] 9297 endl done 9298 9299#@cli == : eq. to 'eq'. : (+) 9300 9301#@cli eq : value[%] : [image] : 'formula' : (no arg) : (+) 9302#@cli : Compute the boolean equality of selected images with specified value, image or \ 9303# mathematical expression, or compute the boolean equality of selected images. 9304#@cli : (eq. to '=='). 9305#@cli : $ image.jpg round 40 eq {round(ia,40)} 9306#@cli : $ image.jpg +mirror x eq 9307 9308#@cli erf : (+) 9309#@cli : Compute the pointwise error function of selected images. 9310#@cli : $ image.jpg +normalize 0,2 erf[-1] 9311#@cli : $ 300,1,1,1,'7*x/w-3.5+u' +erf display_graph 400,300 9312 9313#@cli exp : (+) 9314#@cli : Compute the pointwise exponential of selected images. 9315#@cli : $ image.jpg +normalize 0,2 exp[-1] 9316#@cli : $ 300,1,1,1,'7*x/w+u' +exp display_graph 400,300 9317 9318#@cli >= : eq. to 'ge'. : (+) 9319 9320#@cli ge : value[%] : [image] : 'formula' : (no arg) : (+) 9321#@cli : Compute the boolean 'greater or equal than' of selected images with specified value, image 9322#@cli : or mathematical expression, or compute the boolean 'greater or equal than' of selected images. 9323#@cli : (eq. to '>='). 9324#@cli : $ image.jpg ge {ia} 9325#@cli : $ image.jpg +mirror x ge 9326 9327#@cli > : eq. to 'gt'. : (+) 9328 9329#@cli gt : value[%] : [image] : 'formula' : (no arg) : (+) 9330#@cli : Compute the boolean 'greater than' of selected images with specified value, image or \ 9331# mathematical expression, or compute the boolean 'greater than' of selected images. 9332#@cli : (eq. to '>'). 9333#@cli : $ image.jpg gt {ia} 9334#@cli : $ image.jpg +mirror x gt 9335 9336#@cli <= : eq. to 'le'. : (+) 9337 9338#@cli le : value[%] : [image] : 'formula' : (no arg) : (+) 9339#@cli : Compute the boolean 'less or equal than' of selected images with specified value, image or \ 9340# mathematical expression, or compute the boolean 'less or equal than' of selected images. 9341#@cli : (eq. to '<='). 9342#@cli : $ image.jpg le {ia} 9343#@cli : $ image.jpg +mirror x le 9344 9345#@cli < : eq. to 'lt'. : (+) 9346 9347#@cli lt : value[%] : [image] : 'formula' : (no arg) : (+) 9348#@cli : Compute the boolean 'less than' of selected images with specified value, image or \ 9349# mathematical expression, or compute the boolean 'less than' of selected images. 9350#@cli : (eq. to '<'). 9351#@cli : $ image.jpg lt {ia} 9352#@cli : $ image.jpg +mirror x lt 9353 9354#@cli log : (+) 9355#@cli : Compute the pointwise base-e logarithm of selected images. 9356#@cli : $ image.jpg +add 1 log[-1] 9357#@cli : $ 300,1,1,1,'7*x/w+u' +log display_graph 400,300 9358 9359#@cli log10 : (+) 9360#@cli : Compute the pointwise base-10 logarithm of selected images. 9361#@cli : $ image.jpg +add 1 log10[-1] 9362#@cli : $ 300,1,1,1,'7*x/w+u' +log10 display_graph 400,300 9363 9364#@cli log2 : (+) 9365#@cli : Compute the pointwise base-2 logarithm of selected images 9366#@cli : $ image.jpg +add 1 log2[-1] 9367#@cli : $ 300,1,1,1,'7*x/w+u' +log2 display_graph 400,300 9368 9369#@cli max : value[%] : [image] : 'formula' : (no arg) : (+) 9370#@cli : Compute the maximum between selected images and specified value, image or \ 9371# mathematical expression, or compute the pointwise maxima between selected images. 9372#@cli : $ image.jpg +mirror x max 9373#@cli : $ image.jpg max 'R=((x/w-0.5)^2+(y/h-0.5)^2)^0.5;255*R' 9374 9375#@cli maxabs : value[%] : [image] : 'formula' : (no arg) : (+) 9376#@cli : Compute the maxabs between selected images and specified value, image or \ 9377# mathematical expression, or compute the pointwise maxabs between selected images. 9378 9379#@cli m/ : eq. to 'mdiv'. : (+) 9380 9381#@cli mdiv : value[%] : [image] : 'formula' : (no arg) : (+) 9382#@cli : Compute the matrix division of selected matrices/vectors by specified value, image or \ 9383# mathematical expression, or compute the matrix division of selected images. 9384#@cli : (eq. to 'm/'). 9385 9386#@cli med 9387#@cli : Compute the median of selected images. 9388#@cli : $ image.jpg sample lena,lion,square +med 9389med : 9390 e[^-1] "Compute median of image$?." 9391 if !$! return fi 9392 13,$! eval. "!x?copy(i(),[[',i#'],vtos(y,10,10)])" =. 0 discard. 0 str={t} rm. 9393 ${-max_whds},"med("$str")" k. nm [med] 9394 9395#@cli min : value[%] : [image] : 'formula' : (no arg) : (+) 9396#@cli : Compute the minimum between selected images and specified value, image or \ 9397# mathematical expression, or compute the pointwise minima between selected images. 9398#@cli : $ image.jpg +mirror x min 9399#@cli : $ image.jpg min 'R=((x/w-0.5)^2+(y/h-0.5)^2)^0.5;255*R' 9400 9401#@cli minabs : value[%] : [image] : 'formula' : (no arg) : (+) 9402#@cli : Compute the minabs between selected images and specified value, image or \ 9403# mathematical expression, or compute the pointwise minabs between selected images. 9404 9405#@cli % : eq. to 'mod'. : (+) 9406 9407#@cli mod : value[%] : [image] : 'formula' : (no arg) : (+) 9408#@cli : Compute the modulo of selected images with specified value, image or mathematical \ 9409# expression, or compute the pointwise sequential modulo of selected images. 9410#@cli : (eq. to '%'). 9411#@cli : $ image.jpg +mirror x mod 9412#@cli : $ image.jpg mod 'R=((x/w-0.5)^2+(y/h-0.5)^2)^0.5;255*R' 9413 9414#@cli m* : eq. to 'mmul'. : (+) 9415 9416#@cli mmul : value[%] : [image] : 'formula' : (no arg) : (+) 9417#@cli : Compute the matrix right multiplication of selected matrices/vectors by specified value, image or \ 9418# mathematical expression, or compute the matrix right multiplication of selected images. 9419#@cli : (eq. to 'm*'). 9420#@cli : $ (0,1,0;0,0,1;1,0,0) (1;2;3) +mmul 9421 9422#@cli * : eq. to 'mul'. : (+) 9423 9424#@cli mul : value[%] : [image] : 'formula' : (no arg) : (+) 9425#@cli : Multiply selected images by specified value, image or mathematical expression, \ 9426# or compute the pointwise product of selected images. 9427#@cli : (eq. to '*'). 9428#@cli : See also: ''add'', ''sub'', ''div''. 9429#@cli : $ image.jpg +mul 2 cut 0,255 9430#@cli : $ image.jpg (1,2,3,4,5,6,7,8) ri[-1] [0] mul[0] [-1] 9431#@cli : $ image.jpg mul '1-3*abs(x/w-0.5)' cut 0,255 9432#@cli : $ image.jpg +luminance negate[-1] +mul 9433 9434#@cli mul_channels : value1,_value2,...,_valueN 9435#@cli : Multiply channels of selected images by specified sequence of values. 9436#@cli : $ image.jpg +mul_channels 1,0.5,0.8 9437mul_channels : 9438 e[^-1] "Multiply channels of image$? by value sequence ($*)." 9439 $=arg repeat $#,i 9440 fact=${arg{1+($>%$#)}} 9441 repeat $! if {$>,$i<s} sh[$>] $i *. $fact rm. fi done 9442 done 9443 9444#@cli mul_complex : [multiplier_real,multiplier_imag] 9445#@cli : Perform multiplication of the selected complex pairs (real1,imag1,...,realN,imagN) of images by 9446#@cli : specified complex pair of images (multiplier_real,multiplier_imag). 9447#@cli : In complex pairs, the real image must be always located before the imaginary image in the image list. 9448mul_complex : 9449 e[^-1] "Multiply complex pair$? by complex pair "${"pass$1,$2 -1"}"." 9450 repeat int($!/2) pass${1,2} 0 l[$>,{$>+1},-2,-1] 9451 +*[0,3] +*[1,2] +[-2,-1] # ad+bc 9452 *[0,2] *[1,2] -[0,1] # ac-bd 9453 endl done 9454 9455#@cli != : eq. to 'neq'. : (+) 9456 9457#@cli neq : value[%] : [image] : 'formula' : (no arg) : (+) 9458#@cli : Compute the boolean inequality of selected images with specified value, image or \ 9459# mathematical expression, or compute the boolean inequality of selected images. 9460#@cli : (eq. to '!='). 9461#@cli : $ image.jpg round 40 neq {round(ia,40)} 9462 9463#@cli | : eq. to 'or'. : (+) 9464 9465#@cli or : value[%] : [image] : 'formula' : (no arg) : (+) 9466#@cli : Compute the bitwise OR of selected images with specified value, image or mathematical \ 9467# expression, or compute the pointwise sequential bitwise OR of selected images. 9468#@cli : (eq. to '|'). 9469#@cli : $ image.jpg or 128 9470#@cli : $ image.jpg +mirror x or 9471 9472#@cli ^ : eq. to 'pow'. : (+) 9473 9474#@cli pow : value[%] : [image] : 'formula' : (no arg) : (+) 9475#@cli : Raise selected images to the power of specified value, image or mathematical \ 9476# expression, or compute the pointwise sequential powers of selected images. 9477#@cli : (eq. to '^'). 9478#@cli : $ image.jpg div 255 +pow 0.5 mul 255 9479#@cli : $ image.jpg gradient pow 2 add pow 0.2 9480 9481#@cli rad2deg 9482#@cli : Convert pointwise angle values of selected images, from radians to degrees (apply 'i*180/pi'). 9483rad2deg : 9484 e[^-1] "Convert pointwise angle values of image$?, from radians to degrees." 9485 * 57.295779513082323 9486 9487#@cli rol : value[%] : [image] : 'formula' : (no arg) : (+) 9488#@cli : Compute the bitwise left rotation of selected images with specified value, image or \ 9489# mathematical expression, or compute the pointwise sequential bitwise left rotation of \ 9490# selected images. 9491#@cli : $ image.jpg rol 'round(3*x/w,0)' cut 0,255 9492 9493#@cli ror : value[%] : [image] : 'formula' : (no arg) : (+) 9494#@cli : Compute the bitwise right rotation of selected images with specified value, image or \ 9495# mathematical expression, or compute the pointwise sequential bitwise right rotation of \ 9496# selected images. 9497#@cli : $ image.jpg ror 'round(3*x/w,0)' cut 0,255 9498 9499#@cli sign : (+) 9500#@cli : Compute the pointwise sign of selected images. 9501#@cli : $ image.jpg +sub {ia} sign[-1] 9502#@cli : $ 300,1,1,1,'cos(20*x/w+u)' +sign display_graph 400,300 9503 9504#@cli sin : (+) 9505#@cli : Compute the pointwise sine of selected images. 9506#@cli : $ image.jpg +normalize 0,{2*pi} sin[-1] 9507#@cli : $ 300,1,1,1,'20*x/w+u' +sin display_graph 400,300 9508#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 9509 9510#@cli sinc : (+) 9511#@cli : Compute the pointwise sinc function of selected images. 9512#@cli : $ image.jpg +normalize {-2*pi},{2*pi} sinc[-1] 9513#@cli : $ 300,1,1,1,'20*x/w+u' +sinc display_graph 400,300 9514 9515#@cli sinh : (+) 9516#@cli : Compute the pointwise hyperbolic sine of selected images. 9517#@cli : $ image.jpg +normalize -3,3 sinh[-1] 9518#@cli : $ 300,1,1,1,'4*x/w+u' +sinh display_graph 400,300 9519 9520#@cli sqr : (+) 9521#@cli : Compute the pointwise square function of selected images. 9522#@cli : $ image.jpg +sqr 9523#@cli : $ 300,1,1,1,'40*x/w+u' +sqr display_graph 400,300 9524 9525#@cli sqrt : (+) 9526#@cli : Compute the pointwise square root of selected images. 9527#@cli : $ image.jpg +sqrt 9528#@cli : $ 300,1,1,1,'40*x/w+u' +sqrt display_graph 400,300 9529 9530#@cli - : eq. to 'sub'. : (+) 9531 9532#@cli sub : value[%] : [image] : 'formula' : (no arg) : (+) 9533#@cli : Subtract specified value, image or mathematical expression to selected images, \ 9534# or compute the pointwise difference of selected images. 9535#@cli : (eq. to '-'). 9536#@cli : $ image.jpg +sub 30% cut 0,255 9537#@cli : $ image.jpg +mirror x sub[-1] [0] 9538#@cli : $ image.jpg sub 'i(w/2+0.9*(x-w/2),y)' 9539#@cli : $ image.jpg +mirror x sub 9540 9541#@cli tan : (+) 9542#@cli : Compute the pointwise tangent of selected images. 9543#@cli : $ image.jpg +normalize {-0.47*pi},{0.47*pi} tan[-1] 9544#@cli : $ 300,1,1,1,'20*x/w+u' +tan display_graph 400,300 9545#@cli : $$ https://gmic.eu/oldtutorial/trigometric-and-inverse-trigometric-commands 9546 9547#@cli tanh : (+) 9548#@cli : Compute the pointwise hyperbolic tangent of selected images. 9549#@cli : $ image.jpg +normalize -3,3 tanh[-1] 9550#@cli : $ 300,1,1,1,'4*x/w+u' +tanh display_graph 400,300 9551 9552#@cli xor : value[%] : [image] : 'formula' : (no arg) : (+) 9553#@cli : Compute the bitwise XOR of selected images with specified value, image or mathematical \ 9554# expression, or compute the pointwise sequential bitwise XOR of selected images. 9555#@cli : $ image.jpg xor 128 9556#@cli : $ image.jpg +mirror x xor 9557 9558#--------------------------------- 9559# 9560#@cli :: Values Manipulation 9561# 9562#--------------------------------- 9563 9564#@cli apply_curve : 0<=smoothness<=1,x0,y0,x1,y1,x2,y2,...,xN,yN 9565#@cli : Apply curve transformation to image values. 9566#@cli : Default values: 'smoothness=1', 'x0=0', 'y0=100'. 9567#@cli : $ image.jpg +apply_curve 1,0,0,128,255,255,0 9568apply_curve : check "${1=1}>=0 && $1<=1" skip ${2=0},${3=100} 9569 e[^-1] "Apply intensity curve with smoothness $1 and keypoints (${2--1}) on image$?." 9570 9571 # Determine value mapping. 9572 (${^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] 9573 9574 # Apply value mapping. 9575 -[^-1] $vm *[^-1] {8191/($vM-$vm)} map[^-1] .,1 rm. 9576 9577#@cli apply_gamma : gamma>=0 9578#@cli : Apply gamma correction to selected images. 9579#@cli : $ image.jpg +apply_gamma 2 9580apply_gamma : check $1>=0 9581 e[^-1] "Apply Gamma-correction to image$?, with gamma $1." 9582 if $1==1 return fi 9583 repeat $! l[$>] mM={[im,iM]} n 0,1 ^ {1/$1} n $mM endl done 9584 9585#@cli balance_gamma : _ref_color1,... 9586#@cli : Compute gamma-corrected color balance of selected image, with respect to specified reference color. 9587#@cli : Default value: 'ref_color1=128'. 9588#@cli : $ image.jpg +balance_gamma 128,64,64 9589balance_gamma : check "isnum(${1=128})" 9590 e[^-1] "Apply gamma-corrected color balance of image$?, with reference color ("${^0}")." 9591 repeat $! l[$>] 9592 (${^0}) r. {-2,s},1,1,1,0,1 s.. c /. 255 9593 repeat $!-1 /[$>] 255 ^[$>] {log({@$>})/log({$>,ia})} *[$>] 255 done 9594 rm. a c c 0,255 9595 endl done 9596 9597#@cli cast : datatype_source,datatype_target 9598#@cli : Cast datatype of image buffer from specified source type to specified target type. 9599#@cli : 'datatype_source' and 'datatype_target' can be \ 9600# { uchar | char | ushort | short | uint | int | uint64 | int64 | float | double }. 9601cast : 9602 e[^-1] "Cast datatype of image buffer$? from '$1' to '$2'." 9603 stype="$1" 9604 if s='$stype';s[0]==_'u'" && "s[1]!=_'n' stype="unsigned_"{`s='$stype';s[1,size(s)-1]`} 9605 elif s='$stype';s[0]==_'u'" && "s[0,9]=='"unsigned "' stype="unsigned_"{`s='$stype';s[9,size(s)-9]`} 9606 fi 9607 dtype="$2" 9608 if s='$dtype';s[0]==_'u'" && "s[1]!=_'n' dtype="unsigned_"{`s='$dtype';s[1,size(s)-1]`} 9609 elif s='$dtype';s[0]==_'u'" && "s[0,9]=='"unsigned "' dtype="unsigned_"{`s='$dtype';s[9,size(s)-9]`} 9610 fi 9611 ssize={s='$stype';s=='"unsigned_char"'||s=='char'?1:s=='"unsigned_short"'||s=='short'?2:s=='"unsigned_int"'||\ 9612 s=='int'||s=='float'?4:8} 9613 dsize={s='$dtype';s=='"unsigned_char"'||s=='char'?1:s=='"unsigned_short"'||s=='short'?2:s=='"unsigned_int"'||\ 9614 s=='int'||s=='float'?4:8} 9615 repeat $! l[$>] 9616 w,h,d,s={[w,h,d,s]} 9617 serialize $1,0,0 9618 s -,{'\n$w\ $h\ $d\ $s\n'} 9619 i[1] ('\n1\ {int($w*$h*$d*$s*$ssize/$dsize)}\ 1\ 1\n') y[1] 9620 replace_str[0] $stype,$dtype 9621 a y unserialize 9622 endl done 9623 9624#@cli complex2polar 9625#@cli : Compute complex to polar transforms of selected images. 9626#@cli : $ image.jpg +fft complex2polar[-2,-1] log[-2] shift[-2] 50%,50%,0,0,2 remove[-1] 9627complex2polar : 9628 e[^-1] "Compute complex to polar transforms of image$?." 9629 repeat int($!/2) l[{2*$>},{2*$>+1}] 9630 ri[1] [0],3 +atan2[1] [0] nm. {1,n} sqr[-3,-2] +[-3,-2] sqrt.. 9631 endl done 9632 9633#@cli compress_clut : _max_error>0,_avg_error>0,_max_nbpoints>=8 | 0 (unlimited),\ 9634# _error_metric={ 0=L2-norm | 1=deltaE_1976 | 2=deltaE_2000 },_reconstruction_colorspace={ 0=srgb | 1=rgb | 2=lab },\ 9635# _try_rbf_first={ 0 | 1 } 9636#@cli : Compress selected color LUTs as sequences of colored keypoints. 9637#@cli : Default values: 'max_error=1.5', 'avg_error=0.75', 'max_nb_points=2048', 'error_metric=2', \ 9638# 'reconstruction_colorspace=0' and 'try_rbf_first=1'. 9639compress_clut : check "${1=1.5}>0 && ${2=0.75}>0 && isint(${3=2048}) && (!$3 || $3>=8) && isin(${4=2},0,1,2) && "\ 9640 "isin(${5=0},0,1,2) && isbool(${6=1})" 9641 e[^-1] "Compress color LUT$? as a set of colored keypoints, with maximum error $1, average error $2, "\ 9642 "$3 maximum keypoints, "${"s0,s1,s2=L2-RGB,DeltaE_1976,DeltaE_2000 u $s$4"}" metric and "\ 9643 ${"s0,s1,s2=srgb,rgb,lab u $s$5"}" colorspace for reconstruction." 9644 v 0 9645 max_error,avg_error,max_keypoints,metric,colorspace,try_rbf=${1-6} 9646 if $try_rbf method=rbf else method=pde fi 9647 repeat $! l[$>] nm={b} 9648 if iM>1024 / 257 fi # When input is 16bits 9649 if d==1 S={round(cbrt(wh))} r $S,$S,$S,100%,-1 fi # When input is a 2D haldclut image 9650 e[] "\n* Process CLUT '"$nm"' ("{w}"x"{h}"x"{d}")." 9651 9652 # Detect B&W cluts. 9653 if "s==3 && 9654 crop(0,0,0,0,w,h,d,1)==crop(0,0,0,1,w,h,d,1) && 9655 crop(0,0,0,0,w,h,d,1)==crop(0,0,0,2,w,h,d,1)" 9656 channels 0 9657 fi 9658 9659 _metric={s==3?$metric:0} 9660 if $_metric +srgb2lab fi 9661 9662 # Initialize keypoints (corners of the RGB cube). 9663 1,8,1,{s+3} 9664 eval " 9665 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 ]; 9666 repeat (size(coords)/3,k, 9667 P = coords[3*k,3]; 9668 I[k] = [ P, I(#0,round(P*([w#0,h#0,d#0]-1)/255)) ] 9669 )" 9670 9671 # Iteratively add keypoints. 9672 sep="\n" 9673 do 9674 +decompress_clut_$method. {0,[w,h,d]},$colorspace 9675 if !$_metric -. [0] norm. else srgb2lab. deltaE. [1],{$_metric-1}," " fi 9676 emax,eavg={[iM,ia]} 9677 e[] "\r"$sep" > Add [#"{-2,h}"] Max_Err = "{_$emax}", Avg_Err = "{_$eavg}" " sep="" 9678 if $emax<=$max_error" && "$eavg<=$avg_error rm. break fi 9679 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.. 9680 a[-2,-1] y 9681 if $max_keypoints" && "h>=320" && "'$method'=='rbf' method=pde rows. 0,7 fi # RBF failed, switch to PDE method. 9682 while h<($max_keypoints?$max_keypoints:inf) 9683 9684 # Iteratively remove keypoints. 9685 if h>8 9686 if $_metric max_rounding,avg_rounding=0.1,0.025 9687 else max_rounding,avg_rounding=1,0.25 9688 fi 9689 if $emax>$max_error" || "$eavg>$avg_error 9690 max_error=round($max_error,$max_rounding,1) 9691 avg_error=round($avg_error,$avg_rounding,1) 9692 fi 9693 index=8 sep="\n" 9694 do 9695 +l. s y rm[$index] a y endl # Remove kth keypoint 9696 +decompress_clut_$method. {0,[w,h,d]},$colorspace 9697 if $_metric==0 -. [0] norm. else srgb2lab. deltaE. [1],{$_metric-1}," " fi 9698 emax,eavg={[iM,ia]} rm. 9699 9700 if $emax<=$max_error" && "$eavg<=$avg_error rv[-2,-1] else index+=1 fi 9701 e[] "\r"$sep" > Rem [#"{min($index,h-1)}"/"{h}"] Max_Err = "{_$emax}", Avg_Err = "{_$eavg}" " 9702 sep="" 9703 rm. 9704 while $index<h 9705 fi 9706 k. 9707 9708 # Sort keypoints in lexicographic order (increasing order for RBF, decreasing for PDE). 9709 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% 9710 9711 to_clutname $nm nm ${} 9712 endl done 9713 9714# compress_cluts : {"file_pattern" | "file_list.txt"},_max_error>0,_avg_error>0,_max_nb_points>=8 9715# Batch compress CLUT files. 9716compress_cluts : check "${2=1.5}>0 && ${3=0.75}>0 && isint(${4=2048}) && $4>8" 9717 rm 9718 if isfile(['{/"$1"}']) it[] "$1" s -,{'\n'} 9719 else files "$1" ('${}') s -,{','} 9720 fi 9721 rv 9722 repeat $! l[$<] 9723 filename={t} 0 nm. $filename ext={x} rm 9724 basename $filename 9725 l[] ('${}') replace_str .$ext,"" basename={t} rm endl 9726 need_compression=1 9727 cclut=cclut_$basename.gmz 9728 9729 if isfile(['{/$cclut}']) 9730 i $cclut 9731 if "dat = (date(5) + 60*(date(4) + date(2)*24)); 9732 fdat = (date(5,'"{/$cclut}"') + 60*(date(4,'"{/$cclut}"') + date(2,'"{/$cclut}"')*24)); 9733 !h && dat-fdat<30" 9734 e[] "* Skip file '"$filename"' (CLUT already being compressed)." 9735 need_compression=0 9736 elif h>0" && "h!=2048 9737 e[] "* Skip file '"$filename"' (CLUT already compressed)." 9738 need_compression=0 9739 fi 9740 rm. 9741 fi 9742 9743 if $need_compression 9744 0 o. $cclut rm. # Lock current file 9745 if lowercase(['$ext'])=='cube' input_cube $filename c. 0,255 9746 elif lowercase(['$ext'])=='png' i $filename S={round(cbrt(wh))} r $S,$S,$S,100%,-1 9747 else e[] "* Skip file '"$filename"' (unknown CLUT format)." continue 9748 fi 9749 9750 e[] "* Compress file '"$filename"'." 9751 if w>33 r3dx 33 fi 9752 to_rgb 9753 tic compress_clut $2,$3,$4 toc 9754 o $cclut 9755 fi 9756 rm 9757 endl done 9758 9759# cluts2libclut : "compressed_CLUT_collection.gmz" 9760# Convert specified compressed CLUT collection for C++ 'libclut' 9761# (https://framagit.org/dtschump/libclut) 9762cluts2libclut : skip ${1=$HOME/work/src/gmic/resources/gmic_cluts.gmz} 9763 e[] "Convert compressed CLUT collection '$1' to .png/.ppm/.txt for C++ libclut." 9764 l[] 9765 i $1 9766 0 nm. "$1" basename={b} rm. 9767 list= 9768 repeat $! l[$>] if s<6 r 100%,100%,1,6,0,1 fi transpose list.={n}"\n" endl done s c,2 a y 9769 o. $basename.png 9770 o. $basename.ppm 9771 ('$list') ot. $basename.txt 9772 rm 9773 endl 9774 9775#@cli compress_rle : _is_binary_data={ 0 | 1 },_maximum_sequence_length>=0 9776#@cli : Compress selected images as 2xN data matrices, using RLE algorithm. 9777#@cli : Set 'maximum_sequence_length=0' to disable maximum length constraint. 9778#@cli : Default values: 'is_binary_data=0' and 'maximum_sequence_length=0'. 9779#@cli : $ image.jpg resize2dy 100 quantize 4 round +compress_rle , +decompress_rle[-1] 9780compress_rle : check "isbool(${1=0}) && isint(${2=0}) && $2>=0" 9781 s0=" for binary data" s1="" 9782 if $2 s=", with maximal sequence length "$2 else s="" fi 9783 e[^-1] "Compress image$? using RLE algorithm"${s{!$1}}$s"." 9784 repeat $! l[$>] nm={0,n} im={im} header={w};{h};{d};{s};$im;{$1!=0} 9785 - $im y x ({{0,@-1}+1}) a x r 100%,3 9786 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)' 9787 if $2 # Constrain maximum sequence length. 9788 transpose mirror x 9789 f. '>x==2?i:!x?(j(0,-1)==$2?1:i!=1?j(0,-1)+1:1):(i==-1&&j(-1)==$2?y:i)' 9790 mirror x transpose 9791 fi 9792 z 0,{w-2} s y,3 y[1] discard[1] -1 warp[0,2] [1],0,0 rm[1] 9793 if $1 # Encode for binary data. 9794 !=[0] 0 *[0] 2 -[0] 1 * 9795 else # Encode for arbitrary data. 9796 *. -1 rv a x y discard -1 f '>i(0,y-1)<0&&i==0&&i(0,y+1)<0?-1:i' discard -1 9797 fi 9798 i[0] ($header) a y nm $nm 9799 endl done 9800 9801#@cli cumulate : { x | y | z | c }...{ x | y | z | c } : (no arg) : (+) 9802#@cli : Compute the cumulative function of specified image data, optionally along the specified axes. 9803#@cli : $ image.jpg +histogram +cumulate[-1] display_graph[-2,-1] 400,300,3 9804 9805#@cli c : eq. to 'cut'. : (+) 9806 9807#@cli cut : { value0[%] | [image0] },{ value1[%] | [image1] } : [image] : (+) 9808#@cli : Cut values of selected images in specified range. 9809#@cli : (eq. to 'c').\n 9810#@cli : $ image.jpg +add 30% cut[-1] 0,255 9811#@cli : $ image.jpg +cut 25%,75% 9812 9813#@cli decompress_clut : _width>0,_height>0,_depth>0,_reconstruction_colorspace={ 0=srgb | 1=rgb | 2=lab } 9814#@cli : Decompress selected colored keypoints into 3D CLUTs, using a mixed RBF/PDE approach. 9815#@cli : Default values: 'width=height=depth=33' and 'reconstruction_colorspace=0'. 9816decompress_clut : check "isint(${1=33}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=$1}) && $3>0 && "\ 9817 "isin(${4=0},0,1,2)" 9818 e[^-1] "Decompress colored keypoint$? into $1x$2x$3 CLUTs, using "\ 9819 ${"s0,s1=srgb,rgb u $s$4"}" colorspace for reconstruction." 9820 repeat $! l[$>] 9821 if "h>=320 || (P0 = I[0]; P1 = I[h - 1]; val(P) = (P[0]*65536 + P[1]*256 + P[2]); val(P0)>val(P1))" 9822 decompress_clut_pde. ${1-4} 9823 else 9824 decompress_clut_rbf. ${1-4} 9825 fi 9826 endl done 9827 9828#@cli decompress_clut_rbf : _width>0,_height>0,_depth>0,_reconstruction_colorspace={ 0=srgb | 1=rgb | 2=lab } 9829#@cli : Decompress selected colored keypoints into 3D CLUTs, using RBF thin plate spline interpolation. 9830#@cli : Default value: 'width=height=depth=33' and 'reconstruction_colorspace=0'. 9831decompress_clut_rbf : check "isint(${1=33}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=$1}) && $3>0 && "\ 9832 "isin(${4=0},0,1,2)" 9833 e[^-1] "Decompress colored keypoint$? into $1x$2x$3 CLUTs (RBF approach), using "\ 9834 ${"s0,s1,s2=srgb,rgb,lab u $s$4"}" colorspace for reconstruction." 9835 repeat $! l[$>] 9836 if $4 s c,-3 srgb2${"arg $4,rgb,lab"}. a c fi 9837 rbf $1,$2,$3,0,0,0,255,255,255 9838 if $4 ${"arg $4,rgb,lab"}2srgb fi 9839 endl done 9840 9841#@cli decompress_clut_pde : _width>0,_height>0,_depth>0,_reconstruction_colorspace={ 0=srgb | 1=rgb | 2=lab } 9842#@cli : Decompress selected colored keypoints into 3D CLUTs, using multiscale diffusion PDE's. 9843#@cli : Default values: 'width=height=depth=33' and 'reconstruction_colorspace=0'. 9844decompress_clut_pde : check "isint(${1=33}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=$1}) && $3>0 && "\ 9845 "isin(${4=0},0,1,2)" 9846 e[^-1] "Decompress colored keypoint$? into $1x$2x$3 CLUTs (PDE approach), using "\ 9847 ${"s0,s1,s2=srgb,rgb,lab u $s$4"}" colorspace for reconstruction." 9848 repeat $! l[$>] nm={n} 9849 if $4 s c,-3 srgb2${"arg $4,rgb,lab"}. a c fi 9850 2,2,2,{s-3} 9851 do 9852 +f. 0 .,.,.,1 9853 eval[0] "begin(fact = ([w#1,h#1,d#1] - 1)/255); PC = I; P = PC[0,3]; X = round(P*fact); 9854 I(#2,X)+=PC[3,s-3]; ++i(#3,X); I" 9855 f. "*i?(I(#2)/=i;1):0" 9856 if im rm[-3,-1] # No missing data so far 9857 else # Reconstruct missing data by anisotropic diffusion scheme 9858 +distance. 1 .,.,.,3 9859 eval.. "* # Specific gradient discretization for distance function 9860 const boundary = 1; 9861 maxabs(a,b) = (abs(a)>abs(b)?a:b); 9862 I(#-1) = [ maxabs(j(1) - i,i - j(-1)), 9863 maxabs(j(0,1) - i,i - j(0,-1)), 9864 maxabs(j(0,0,1) - i,i - j(0,0,-1)) ]" 9865 orientation. rm.. 9866 repeat 20 9867 j[-4] ...,0,0,0,0,1,.. 9868 +warp[-4] .,1,2,1 *.. -1 warp[-5] ..,1,2,1 +[-5,-1] /[-4] 2 9869 done 9870 j[-4] ...,0,0,0,0,1,.. k[0,1] 9871 fi 9872 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 9873 while 1 9874 k. 9875 if $4 ${"arg $4,rgb,lab"}2srgb fi 9876 nm $nm 9877 endl done 9878 um srgb2srgb 9879 9880#@cli decompress_rle 9881#@cli : Decompress selected data vectors, using RLE algorithm. 9882decompress_rle : 9883 e[^-1] "Decompress data vector$?, using RLE algorithm." 9884 repeat $! l[$>] 9885 9886 # Retrieve original data dimension and min value. 9887 y whds={0,@0-3} im={0,@4} is_binary_data={0,@5} rows 6,100% 9888 9889 # Transform RLE data to list of pairs {nb_occurrences,value}. 9890 if $is_binary_data # Decode for binary data. 9891 +>= 0 abs[0] a x 9892 else # Decode for arbitrary data 9893 +<. 0 9894 (0;1;1) 9895 erode.. .,0 rm. -. 1 a x discard -1 # Get back compressed '0' (minimum) values. 9896 +< 0 (0;1;1) dilate.. . rm. *. -2 +. 1 # Get back singletons. 9897 rv abs. a x discard -1 9898 r 2,{h/2},1,1,-1 9899 fi 9900 9901 # Decompress, using 3D objects. 9902 s y,-256 9903 repeat $! l[$>] 9904 i[0] ('CImg3d') +[0] 0.5 9905 i[1] ({2*h};{h}) 9906 s. x,2 cumulate.. siz={-2,@-1} 9907 +shift.. 0,1 -... 1 rv[-3,-1] z[-3,-1] 0,2 a[-3,-1] x 9908 i[3] (2,0,1;2,{2*h-2},{2*h-1}) r[3] 3,{h},1,1,3 round[3] 9909 r[4] 3 1,100%,1,1,1 y a y 9910 $siz j3d. ..,0,0,0,1,2,0,0 rm.. 9911 endl done 9912 a x r $whds,-1 + $im 9913 endl done 9914 9915#@cli discard : _value1,_value2,... : { x | y | z | c}...{ x | y | z | c},_value1,_value2,... : (no arg) : (+) 9916#@cli : Discard specified values in selected images or discard neighboring duplicate values, 9917#@cli : optionally only for the values along the first of a specified axis. 9918#@cli : If no arguments are specified, neighboring duplicate values are discarded. 9919#@cli : If all pixels of a selected image are discarded, an empty image is returned. 9920#@cli : $ (1;2;3;4;3;2;1) +discard 2 9921#@cli : $ (1,2,2,3,3,3,4,4,4,4) +discard x 9922 9923#@cli eigen2tensor 9924#@cli : Recompose selected pairs of eigenvalues/eigenvectors as 2x2 or 3x3 tensor fields. 9925#@cli : $$ 9926eigen2tensor : 9927 e[^-1] "Recompose pairs in eigen field$? as 2x2 or 3x3 tensor fields." 9928 repeat $!/2 l[$>,{$>+1}] nm={0,n} 9929 if s==2 # 2D tensors. 9930 s. c 9931 +sqr. *.. ... sqr... # u^2 uv v^2 9932 sh. +*... -1 9933 sh[-5] # v^2 -uv u^2 9934 a[-3--1] c a[-4--2] c 9935 sh... 0 *[-3,-1] # l1*(u^2;uv;v^2) 9936 sh... 1 *[-2,-1] # l2*(v^2;-uv;u^2) 9937 rm... +[-2,-1] 9938 elif s==6 # 3D tensors. 9939 s. c 9940 l[-6--4] +sqr.. +*[-2,-3] +sqr... *[-5] [-6] *[-4] [-6] sqr[-6] a c endl 9941 l[-3--1] +sqr.. +*[-2,-3] +sqr... *[-5] [-6] *[-4] [-6] sqr[-6] a c endl 9942 s... c 9943 -[-5] ... -[-4] ... *.. [-5] *. [-4] 9944 (1^0^0^1^0^1) ri. ... *. [-4] rm[-6--4] +[-3--1] 9945 else error[0--3] "Command '$0': Invalid image ["{$!-$>-1}"] : Dimensions "{w}","{h}","{d}","{s}" does 9946 not represent a field of 2D or 3D eigenvectors." 9947 fi 9948 nm $nm endl done 9949 9950#@cli endian : _datatype : (+) 9951#@cli : Reverse data endianness of selected images, eventually considering the pixel being of the specified datatype. 9952#@cli : 'datatype' can be { bool | uchar | char | ushort | short | uint | int | uint64 | int64 | float | double }. 9953#@cli : This command does nothing for 'bool', 'uchar' and 'char' datatypes. 9954 9955#@cli equalize : _nb_levels>0[%],_value_min[%],_value_max[%] : (+) 9956#@cli : Equalize histograms of selected images. 9957#@cli : If value range is specified, the equalization is done only for pixels in the specified 9958#@cli : value range. 9959#@cli : Default values: 'nb_levels=256', 'value_min=0%' and 'value_max=100%'. 9960#@cli : $ image.jpg +equalize 9961#@cli : $ image.jpg +equalize 4,0,128 9962 9963#@cli f : eq. to 'fill'. : (+) 9964 9965#@cli fill : value1,_value2,... : [image] : 'formula' : (+) 9966#@cli : Fill selected images with values read from the specified value list, existing image 9967#@cli : or mathematical expression. Single quotes may be omitted in 'formula'. 9968#@cli : (eq. to 'f'). 9969#@cli : $ 4,4 fill 1,2,3,4,5,6,7 9970#@cli : $ 4,4 (1,2,3,4,5,6,7) fill[-2] [-1] 9971#@cli : $ 400,400,1,3 fill "X=x-w/2; Y=y-h/2; R=sqrt(X^2+Y^2); a=atan2(Y,X); \ 9972# if(R<=180,255*abs(cos(c+200*(x/w-0.5)*(y/h-0.5))),850*(a%(0.1*(c+1))))" 9973#@cli : $$ 9974 9975#@cli index : { [palette] | palette_name },0<=_dithering<=1,_map_palette={ 0 | 1 } : (+) 9976#@cli : Index selected vector-valued images by specified vector-valued palette. 9977#@cli : 'palette_name' can be { default | hsv | lines | hot | cool | jet | flag | cube | rainbow | algae | amp |\ 9978# balance | curl | deep | delta | dense | diff | haline | ice | matter | oxy | phase | rain | solar | speed | tarn |\ 9979# tempo | thermal | topo | turbid | aurora | hocuspocus | srb2 | uzebox } 9980#@cli : Default values: 'dithering=0' and 'map_palette=0'. 9981#@cli : $ image.jpg +index 1,1,1 9982#@cli : $ image.jpg (0;255;255^0;128;255^0;0;255) +index[-2] [-1],1,1 9983#@cli : $$ https://gmic.eu/tutorial/gindex 9984index : check "${2=0}>=0 && $2<=1 && isbool(${3=0})" 9985 names=${-_palette_names} N={narg($names)} 9986 l[] if isint("$1") name=${"arg 1+($1%"$N"),"$names} else name="$1" fi onfail name="$1" endl 9987 e[^-1] "Index values in image$? by color LUT '"$name"', with dithering level $2." 9988 palette $1 index[^-1] .,$2,$3 rm. 9989 9990#@cli ir : eq. to 'inrange'. 9991ir : check "isbool(${3=1}) && isbool(${4=$3})" 9992 _gmic_s="$?" v + _inrange $* 9993 9994#@cli inrange : min[%],max[%],_include_min_boundary={ 0=no | 1=yes },_include_max_boundary={ 0=no | 1=yes } 9995#@cli : Detect pixels whose values are in specified range `[min,max]`, in selected images. 9996#@cli : (eq. to 'ir'). 9997#@cli : Default value: 'include_min_boundary=include_max_boundary=1'. 9998#@cli : $ image.jpg +inrange 25%,75% 9999inrange : check "isbool(${3=1}) && isbool(${4=$3})" 10000 _gmic_s="$?" v + _$0 $* 10001 10002_inrange : skip "${3=1},${4=$3}" 10003 v={$3+2*$4} 10004 s=${"arg 1+"$v",out,\" min\",\" max\",\" min and max\""} 10005 if $v%3 b="y" else b="ies" fi 10006 e[0--3] "Extract pixel values in range [$1,$2] in image"$_gmic_s", with"$s" boundar"$b" included." 10007 repeat $! l[$>] 10008 m=$1 M=$2 10009 if ${is_percent\ $1} m={im+(iM-im)*$1} fi 10010 if ${is_percent\ $2} M={im+(iM-im)*$2} fi 10011 f. inrange(i,$m,$M,$3) 10012 endl done 10013 10014#@cli map : [palette],_boundary_conditions : palette_name,_boundary_conditions : (+) 10015#@cli : Map specified vector-valued palette to selected indexed scalar images. 10016#@cli : 'palette_name' can be { default | hsv | lines | hot | cool | jet | flag | cube | rainbow | algae | amp | \ 10017# balance | curl | deep | delta | dense | diff | gray | haline | ice | matter | oxy | phase | rain | solar | speed | \ 10018# tarn | tempo | thermal | topo | turbid | aurora | hocuspocus | srb2 | uzebox } 10019#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 10020#@cli : Default value: 'boundary_conditions=0'. 10021#@cli : $ image.jpg +luminance map[-1] 3 10022#@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 \ 10023# ycbcr2rgb[-1] 10024#@cli : $$ 10025map : check "isint(${2=0}) && $2>=0 && $2<=3" 10026 s0,s1,s2,s3=dirichlet,neumann,periodic,mirror boundary=${s$2} 10027 names=${-_palette_names} N={narg($names)} 10028 l[] if isint("$1") name=${"arg 1+($1%"$N"),"$names} else name="$1" fi onfail name="$1" endl 10029 e[^-1] "Map color LUT '"$name"' on image$?, with "$boundary" boundary conditions." 10030 palette $1 map[^-1] .,$2 rm. 10031 10032#@cli mix_channels : (a00,...,aMN) : [matrix] 10033#@cli : Apply specified matrix to channels of selected images. 10034#@cli : $ image.jpg +mix_channels (0,1,0;1,0,0;0,0,1) 10035mix_channels : 10036 e[^-1] "Apply matrix $1 to channels of image$?." 10037 if ${"is_image_arg $1"} pass$1 1 else i ${^0} fi 10038 repeat $!-1 l[$>] nm={n} 10039 whd={[w,h,d]} r. {[whd,s]},1,1,-1 10040 pass. 0 mv. 0 m* r $whd,{h},-1 10041 nm $nm endl done rm. 10042 10043#@cli negate : base_value : (no arg) 10044#@cli : Negate image values. 10045#@cli : Default value: 'base_value=(undefined)'. 10046#@cli : $ image.jpg +negate 10047negate : skip "${1=,}" 10048 if isnum("$*") 10049 e[0--3] "Negate values of image$?, according to base value $*." 10050 - {"$*"} * -1 10051 else 10052 e[0--3] "Negate values of image$?." 10053 repeat $! -[$>] {$>,iM} done * -1 10054 if ['"$1"']!=',' noarg fi 10055 fi 10056 10057#@cli noise : std_deviation>=0[%],_noise_type : (+) 10058#@cli : Add random noise to selected images. 10059#@cli : 'noise_type' can be { 0=gaussian | 1=uniform | 2=salt&pepper | 3=poisson | 4=rice }. 10060#@cli : Default value: 'noise_type=0'. 10061#@cli : $ image.jpg +noise[0] 50,0 +noise[0] 50,1 +noise[0] 10,2 cut 0,255 10062#@cli : $ 300,300,1,3 [0] noise[0] 20,0 noise[1] 20,1 +histogram 100 display_graph[-2,-1] 400,300,3 10063 10064#@cli noise_perlin : _scale_x[%]>0,_scale_y[%]>0,_scale_z[%]>0,_seed_x,_seed_y,_seed_z 10065#@cli : Render 2D or 3D Perlin noise on selected images, from specified coordinates. 10066#@cli : The Perlin noise is a specific type of smooth noise, 10067#@cli : described here : <https://en.wikipedia.org/wiki/Perlin_noise>. 10068#@cli : Default values: 'scale_x=scale_y=scale_z=16' and 'seed_x=seed_y=seed_z=0'. 10069#@cli : $ 500,500,1,3 noise_perlin , 10070noise_perlin : check "${1=16}>0 && ${2=$1}>0 && ${3=$1}>0 && isnum(${4=0}) && isnum(${5=0}) && isnum(${6=0})" 10071 e[^-1] "Render Perlin noise on image$?, with scales (${1-3}) and seeds (${4-6})." 10072 10073 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, 10074 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, 10075 237,149,56,87,174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231, 10076 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, 10077 216,80,73,209,76,132,187,208,89,18,169,200,196,135,130,116,188,159,86,164,100,109,198, 10078 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, 10079 16,58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70,221,153,101,155,167, 10080 43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,178,185,112,104,218,246,97,228,251, 10081 34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31, 10082 181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,93,222,114,67,29, 10083 24,72,243,141,128,195,78,66,215,61,156,180 ]; 10084 p = [ permutation,permutation ]; 10085 fade(t) = (t*t*t*(t*(t*6 - 15) + 10)); 10086 _lerp(t,a,b) = lerp(a,b,t); 10087 pcmod255 = vectors(); repeat (s,k,pcmod255[k] = p[k%255]); 10088 sx = ['$1']; is_px = sx[size(sx) - 1]==_'%'; 10089 sy = ['$2']; is_py = sy[size(sy) - 1]==_'%'; 10090 sz = ['$3']; is_pz = sz[size(sz) - 1]==_'%'; 10091 x0 = $4; 10092 y0 = $5; 10093 z0 = $6; 10094 x1 = x0 + (is_px?1/$1:w/$1); 10095 y1 = y0 + (is_py?1/$2:h/$2); 10096 z1 = z0 + (is_pz?1/$3:d/$3); 10097 fw = (x1 - x0)/max(w - 1,1); 10098 fh = (y1 - y0)/max(h - 1,1); 10099 fd = (z1 - z0)/max(d - 1,1);" 10100 10101 repeat $! if {$>,d>1} # 3D version 10102 f[$>] "*begin("$init" 10103 grad(hash,x,y,z) = ( gh = hash&15; gu = gh<8?x:y; gv = gh<4?y:gh==12 || gh==14?x:z; 10104 (!(gh&1)?gu:-gu) + (!(gh&2)?gv:-gv)) 10105 ); 10106 x = x0 + x*fw + pcmod255[c]; y = y0 + y*fh + pcmod255[c]; z = z0 + z*fd + pcmod255[c]; 10107 ix = floor(x); iy = floor(y); iz = floor(z); 10108 X = ix&255; Y = iy&255; Z = iz&255; 10109 fx = x - ix; fy = y - iy; fz = z - iz; 10110 u = fade(fx); v = fade(fy); w = fade(fz); 10111 A = p[X] + Y; AA = p[A] + Z; AB = p[A + 1] + Z; 10112 B = p[X + 1] + Y; BA = p[B] + Z; BB = p[B + 1] + Z; 10113 fx1 = fx - 1; fy1 = fy - 1; fz1 = fz - 1; 10114 lerp(lerp(lerp(grad(p[AA],fx,fy,fz), 10115 grad(p[BA],fx1,fy,fz),u), 10116 lerp(grad(p[AB],fx,fy1,fz), 10117 grad(p[BB],fx1,fy1,fz),u),v), 10118 lerp(lerp(grad(p[AA + 1],fx,fy,fz1), 10119 grad(p[BA + 1],fx1,fy,fz1,u), 10120 lerp(grad(p[AB + 1],fx,fy1,fz1), 10121 grad(p[BB+1],fx1,fy1,fz1),u),v),w)" 10122 else # 2D version 10123 f[$>] "*begin("$init" 10124 grad(hash,x,y) = ( gh = hash&15; gu = gh<8?x:y; gv = gh<4?y:gh==12 || gh==14?x:0; 10125 (!(gh&1)?gu:-gu) + (!(gh&2)?gv:-gv)) 10126 ); 10127 x = x0 + x*fw + pcmod255[c]; y = y0 + y*fh + pcmod255[c]; 10128 ix = floor(x); iy = floor(y); 10129 X = ix&255; Y = iy&255; 10130 fx = x - ix; fy = y - iy; 10131 u = fade(fx); v = fade(fy); 10132 A = p[X] + Y; B = p[X + 1] + Y; 10133 fx1 = fx - 1; fy1 = fy - 1; 10134 lerp(lerp(grad(p[A],fx,fy), 10135 grad(p[B],fx1,fy),u), 10136 lerp(grad(p[A + 1],fx,fy1), 10137 grad(p[B + 1],fx1,fy1),u),v)" 10138 fi done 10139 10140#@cli noise_poissondisk : _radius[%]>0,_max_sample_attempts>0 10141#@cli : Add poisson disk sampling noise to selected images. 10142#@cli : Implements the algorithm from the article "Fast Poisson Disk Sampling in Arbitrary Dimensions", 10143#@cli : by Robert Bridson (SIGGRAPH'2007). 10144#@cli : Default values: 'radius=8' and 'max_sample_attempts=30'. 10145#@cli : $ 300,300 noise_poissondisk 8 10146##### : Original G'MIC code by Garagecoder (Andy Kelday) 10147noise_poissondisk : check "${1=8}>0 && ${2=30}>0" 10148 e[^-1] "Add poisson disk sampling points to image$?, with radius $1 and max sample attempts $2." 10149 repeat $! l[$>] 10150 R={${"is_percent $1"}?max(w,h,d)*$1:$1} # [0] input image to draw samples on 10151 dim={d>1?3:h>1?2:1} cw={0.999*$R/sqrt($dim)} # dimensions, grid cell width 10152 ({[w,h,d,1]}) y. c # [1] image dimensions vector 10153 {[ceil(I/$cw)]} # [2] "accelerator" grid/cells 10154 r[1] 1,1,1,$dim,-1 # keep only used dimensions in [1] 10155 1,1,1,$dim 1,1,1,1 # [3] samples list, [4] active list 10156 {vector$dim(2*ceil(sqrt($dim))+1)} r. 100%,100%,100%,2 # [5] cell proximity kernel 10157 f. "P=[x,y,z]-int([w/2,h/2,d/2]);[sum(sqr(P)),dot(P,[1,w#2,w#2*h#2])]" 10158 r. {[whd,s,1,1,-1]} sort. +,x z. 0,1,100%,100% y. c # sort kernel by distance 10159 nm[1] dims nm[2] grid nm[3] samples nm[4] active nm[5] prox 10160 eval ${-math_lib}" 10161 begin( 10162 dotoff = resize([ 1,w#2,w#2*h#2 ],d#2>1?3:h#2>1?2:1,0); 10163 ); 10164 const N = "$dim"; 10165 const radius = "$R"; 10166 const grid_cw = "$cw"; 10167 const max_sample_attempts = $2; 10168 const value = iM#0 + (im#0==iM#0); 10169 mag2(vec) = sum(sqr(vec)); 10170 prox = I#5; 10171 lim = I#1; 10172 10173 dar_insert(#3,I#1,0); # dummy sample to simplify bounds checks 10174 dar_insert(#3,u(I#1),1); # add initial sample to list 10175 dar_insert(#4,1,0); # add its index to active list 10176 I(#2,int(I[#3,1]/grid_cw)) = 1; # add its index to grid cell 10177 I(#0,I[#3,1]) = value; # draw the point 10178 10179 while (dar_size(#4)>0, 10180 R = int(u(dar_size(#4)-1e-4)); # choose a random active list index 10181 P = i[#4,R]; # get the index of that sample 10182 T = I[#3,P]; # position vector of that sample 10183 10184 repeat (max_sample_attempts,attempts, 10185 do (S = 4*(u(vectorN(1)) - 0.5); M = mag2(S), M <= 1 || M > 4); 10186 10187 X = T + radius * S; # potential sample from annulus around T 10188 if (min(X)<0 || min(lim-X)<0, continue()); # check within bounds 10189 10190 # check proximity of surrounding points 10191 G = int(X/grid_cw); # grid cell position vector 10192 GI = dot(G,dotoff); # grid cell direct buffer index 10193 10194 for (K = 0; rejected = 0, K<size(prox), ++K, 10195 V = i[#2,GI+prox[K]]; # sample index from grid to check 10196 if (V>0 && mag2(I[#3,V]-X)<sqr(radius), rejected = 1; break()) 10197 ); 10198 10199 if (!rejected, 10200 Q = dar_size(#3); # sample found, get new index 10201 dar_insert(#3,X); # insert into samples list 10202 dar_insert(#4,Q); # insert its index into active 10203 I(#2,G) = Q; # insert its index into grid 10204 I(#0,X) = value; # draw the point 10205 break(); 10206 ); 10207 ); 10208 if (attempts==max_sample_attempts, dar_remove(#4,R)); 10209 )" 10210 k[0] 10211 endl done 10212 10213#@cli normp : p>=0 10214#@cli : Compute the pointwise Lp-norm norm of vector-valued pixels in selected images. 10215#@cli : Default value: 'p=2'. 10216#@cli : $ image.jpg +normp[0] 0 +normp[0] 1 +normp[0] 2 +normp[0] inf 10217normp : check "isnum(${1==2}) && $1>=0" 10218 e[^-1] "Compute pointwise L"$1"-norm of vectors, in image$?." 10219 if $1==0 != 0 compose_channels + 10220 elif $1==1 abs compose_channels + 10221 elif $1==2 norm 10222 elif $1==inf abs compose_channels max 10223 else ^ $1 compose_channels + ^ {1/$1} 10224 fi 10225 10226#@cli norm 10227#@cli : Compute the pointwise euclidean norm of vector-valued pixels in selected images. 10228#@cli : $ image.jpg +norm 10229#@cli : $$ 10230norm : 10231 e[^-1] "Compute pointwise euclidean norm of vectors, in image$?." 10232 sqr compose_channels + sqrt 10233 10234#@cli n : eq. to 'normalize'. : (+) 10235 10236#@cli normalize : { value0[%] | [image0] },{ value1[%] | [image1] },_constant_case_ratio : [image] : (+) 10237#@cli : Linearly normalize values of selected images in specified range. 10238#@cli : (eq. to 'n'). 10239#@cli : $ image.jpg split x,2 normalize[-1] 64,196 append x 10240#@cli : $$ 10241 10242#@cli normalize_l2 10243#@cli : Normalize selected images such that they have a unit L2 norm. 10244normalize_l2 : 10245 e[^-1] "Normalize image$?, s.t they have a unit L2 norm." 10246 repeat $! /[$>] {norm={$>,in};if(norm!=0,norm,1)} done 10247 10248#@cli normalize_sum 10249#@cli : Normalize selected images such that they have a unit sum. 10250#@cli : $ image.jpg +histogram normalize_sum[-1] display_graph[-1] 400,300 10251normalize_sum : 10252 e[^-1] "Normalize image$?, s.t they have a unit sum." 10253 repeat $! /[$>] {sum={$>,is};if(sum!=0,sum,1)} done 10254 10255#@cli not 10256#@cli : Apply boolean not operation on selected images. 10257#@cli : $ image.jpg +ge 50% +not[-1] 10258not : 10259 e[^-1] "Apply boolean not operation on image$?." 10260 == 0 10261 10262#@cli orientation 10263#@cli : Compute the pointwise orientation of vector-valued pixels in selected images. 10264#@cli : $ image.jpg +orientation +norm[-2] negate[-1] mul[-2] [-1] reverse[-2,-1] 10265#@cli : $$ 10266orientation : 10267 e[^-1] "Compute pointwise orientation vectors, in image$?." 10268 repeat $! +norm[$>] replace. 0,1 /[$>,-1] done 10269 10270#@cli oneminus 10271#@cli : For each selected image, compute one minus image. 10272#@cli : $ image.jpg normalize 0,1 +oneminus 10273oneminus : 10274 e[^-1] "Compute one minus selected images$?." 10275 * -1 + 1 10276 10277#@cli otsu : _nb_levels>0 10278#@cli : Hard-threshold selected images using Otsu's method. 10279#@cli : The computed thresholds are returned as a list of values in the status. 10280#@cli : Default value: 'nb_levels=256'. 10281#@cli : $ image.jpg luminance +otsu , 10282otsu : check "isint(${1=256}) && $1>0" 10283 e[^-1] "Hard-threshold image$? using Otsu\47s method, with $1 histogram levels." 10284 repeat $! l[$>] 10285 imM={[im,iM]} +histogram $1,$imM 10286 otsu={" 10287 sum = sumB = wB = best_variance = best_t = 0; 10288 repeat (w,t,sum+=t*i[t]); 10289 repeat (w,t, 10290 wB+=i[t]; 10291 if (!wB, continue()); 10292 wF = whds#-2 - wB; 10293 if (!wF, break()); 10294 sumB+=t*i[t]; 10295 mB = sumB/wB; 10296 mF = (sum - sumB)/wF; 10297 variance = wB*wF*(mB - mF)^2; 10298 if (variance>best_variance, best_variance = variance; best_t = t); 10299 ); 10300 imM = ["$imM"]; 10301 imM[0] + best_t*(imM[1] - imM[0])/(w - 1)"} 10302 rm. >=. $otsu 10303 if $> u ${},$otsu else u $otsu fi 10304 endl done 10305 10306#@cli polar2complex 10307#@cli : Compute polar to complex transforms of selected images. 10308polar2complex : 10309 e[^-1] "Compute polar to complex transforms of image$?." 10310 repeat int($!/2) l[{2*$>},{2*$>+1}] 10311 ri[1] [0],3 +sin. cos.. *. ... *[-3,-2] 10312 endl done 10313 10314#@cli quantize : nb_levels>=1,_keep_values={ 0 | 1 },_quantization_type={ -1=median-cut | 0=k-means | 1=uniform } 10315#@cli : Quantize selected images. 10316#@cli : Default value: 'keep_values=1' and 'quantization_type=0'. 10317#@cli : $ image.jpg luminance +quantize 3 10318#@cli : $ 200,200,1,1,'cos(x/10)*sin(y/10)' +quantize[0] 6 +quantize[0] 4 +quantize[0] 3 +quantize[0] 2 10319quantize : check "isint($1) && $1>=1 && isbool(${2=1}) && isint(${3=0}) && $3>=-1 && $3<=1" 10320 e[^-1] "Quantize image$? using $1 levels, "${arg\ 1+!$2,with,without}" keeping value range." 10321 repeat $! l[$>] 10322 if $3==1 # Uniform quantization. 10323 if s==1 # Greyscale image. 10324 if $2 mM={[im,iM]} n 0,$1 round 1,-1 min {$1-1} n $mM 10325 else n 0,$1 round 1,-1 min {$1-1} fi 10326 else mM={[im,iM]} uniform_distribution $1,{s} n. $mM index.. .,0,$2 rm. 10327 fi 10328 else +colormap $1,{!$3},1 index.. .,0,$2 rm. # Non-uniform quantization. 10329 fi 10330 endl done 10331 10332#@cli quantize_area : _min_area>0 10333#@cli : Quantize selected images such that each flat region has an area greater or equal to 'min_area'. 10334#@cli : Default value: 'min_area=10'. 10335#@cli : $ image.jpg quantize 3 +blur 1 round[-1] +quantize_area[-1] 2 10336quantize_area : check "${1=10}>0" 10337 e[^-1] "Quantize image$? by regions of areas greater than $1." 10338 if $1==1 return fi 10339 repeat $! l[$>] 10340 if s>1 +f. "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm. round. 0.01 else [0] fi 10341 area. 0,0 <. $1 10342 do 10343 [0] 10344 f.. "* 10345 begin( 10346 const boundary = 1; 10347 offx = [ -1,1,0,0,0,0 ]; 10348 offy = [ 0,0,-1,1,0,0 ]; 10349 offz = [ 0,0,0,0,-1,1 ]; 10350 nb_offs = d>1?6:h>1?4:2; 10351 ); 10352 is_neighbor = j(-1) && j(-1); 10353 if (h>1, is_neighbor&=j(1,0) && j(0,1)); 10354 if (d>1, is_neighbor&=j(0,0,-1) && j(0,0,1)); 10355 is_neighbor = !is_neighbor; 10356 i && is_neighbor?( 10357 col0 = I(#0); 10358 kmin = -1; 10359 distmin = inf; 10360 repeat (nb_offs,k, 10361 p = offx[k]; 10362 q = offy[k]; 10363 r = offz[k]; 10364 if (!j(p,q,r), 10365 col = J(#0,p,q,r); 10366 dist = norm(col-=col0); 10367 if (dist<distmin, distmin = dist; kmin = k); 10368 ); 10369 ); 10370 if (kmin>=0, 10371 I(#-1) = J(#0,offx[kmin],offy[kmin],offz[kmin]); 10372 0, 10373 1 10374 ); 10375 ):i" 10376 rv[0,-1] rm. 10377 while iM 10378 rm. 10379 endl done 10380 10381#@cli rand : { value0[%] | [image0] },_{ value1[%] | [image1] } : [image] : (+) 10382#@cli : Fill selected images with random values uniformly distributed in the specified range. 10383#@cli : $ 400,400,1,3 rand -10,10 +blur 10 sign[-1] 10384 10385#@cli replace : source,target 10386#@cli : Replace pixel values in selected images. 10387#@cli : $ (1;2;3;4) +replace 2,3 10388replace : 10389 e[^-1] "Replace pixel values $1 with $2 in image$?." 10390 f "i==$1?$2:i" 10391 10392#@cli replace_inf : _expression 10393#@cli : Replace all infinite values in selected images by specified expression. 10394#@cli : $ (0;1;2) log +replace_inf 2 10395replace_inf : 10396 e[^-1] "Replace all infinite values in image$? by expression '$1'." 10397 f "isinf(i)?$1:i" 10398 10399#@cli replace_nan : _expression 10400#@cli : Replace all NaN values in selected images by specified expression. 10401#@cli : $ (-1;0;2) sqrt +replace_nan 2 10402replace_nan : 10403 e[^-1] "Replace all NaN values in images$? by expression '$1'." 10404 f "isnan(i)?$1:i" 10405 10406#@cli replace_naninf : _expression 10407#@cli : Replace all NaN and infinite values in selected images by specified expression. 10408replace_naninf : 10409 e[^-1] "Replace all NaN and infinite values in images$? by expression '$1'." 10410 f "isnan(i) || isinf(i)?$1:i" 10411 10412#@cli replace_seq : "search_seq","replace_seq" 10413#@cli : Search and replace a sequence of values in selected images. 10414#@cli : $ (1;2;3;4;5) +replace_seq "2,3,4","7,8" 10415replace_seq : skip "${2=''}" 10416 e[^-1] "Replace value sequence '$1' by value sequence '${2--1}' in image$?." 10417 y repeat $! l[$>] nm={n} 10418 1,100% 10419 eval "ref([ $1 ],str1); 10420 ref([ ${2--1} ],str2); 10421 copy_bloc(pd,src,len) = ( 10422 l = len; 10423 pd + l>=h#1?resize(#1,1,h(#1) + 3*l,1,1,0); 10424 copy(i[pd],src,l); 10425 pd+=l; 10426 ); 10427 for (ps = pd = 0, ps<h#0 && (qs = find(#0,str1,ps))>=0, 10428 qs>ps?copy_bloc(pd,i[#0,ps],qs - ps); 10429 copy_bloc(pd,str2,size(str2)); 10430 ps = qs + size(str1); 10431 ); 10432 ps<h#0?copy_bloc(pd,i[#0,ps],h#0 - ps); 10433 resize(#1,1,pd,1,1,0)" 10434 k. nm $nm 10435 endl done 10436 10437#@cli replace_str : "search_str","replace_str" 10438#@cli : Search and replace a string in selected images (viewed as strings, i.e. sequences of character codes). 10439#@cli : $ ('"Hello there, how are you ?"') +replace_str "Hello there","Hi David" 10440replace_str : skip "${2=}" 10441 e[^-1] "Replace string '$1' by string '${2--1}' in image$?." 10442 replace_seq {``{'"$1"'}},{'"${2--1}"'} 10443 10444#@cli round : rounding_value>=0,_rounding_type : (no arg) : (+) 10445#@cli : Round values of selected images. 10446#@cli : 'rounding_type' can be { -1=backward | 0=nearest | 1=forward }. 10447#@cli : Default value: 'rounding_type=0'. 10448#@cli : $ image.jpg +round 100 10449#@cli : $ image.jpg mul {pi/180} sin +round 10450 10451#@cli roundify : gamma>=0 10452#@cli : Apply roundify transformation on float-valued data, with specified gamma. 10453#@cli : Default value: 'gamma=0'. 10454#@cli : $ 1000 fill '4*x/w' repeat 5 +roundify[0] {$>*0.2} done append c display_graph 400,300 10455roundify : check $1>=0 10456 e[^-1] "Roundify image$?, with gamma $1." 10457 if $1==1 return fi 10458 repeat $! l[$>] 10459 +round 1 -.. . +*.. 2 abs. ^. $1 sign... *[-3,-1] *.. 0.5 + 10460 endl done 10461 10462#@cli = : eq. to 'set'. : (+) 10463 10464#@cli set : value,_x[%],_y[%],_z[%],_c[%] : (+) 10465#@cli : Set pixel value in selected images, at specified coordinates. 10466#@cli : (eq. to '=').\n 10467#@cli : If specified coordinates are outside the image bounds, no action is performed. 10468#@cli : Default values: 'x=y=z=c=0'. 10469#@cli : $ 2,2 set 1,0,0 set 2,1,0 set 3,0,1 set 4,1,1 10470#@cli : $ image.jpg repeat 10000 set 255,{u(100)}%,{u(100)}%,0,{u(100)}% done 10471 10472#@cli threshold : value[%],_is_soft={ 0 | 1 } : 10473#@cli : Threshold values of selected images. 10474#@cli : 'soft' can be { 0=hard-thresholding | 1=soft-thresholding }. 10475#@cli : Default value: 'is_soft=0'. 10476#@cli : $ image.jpg +threshold[0] 50% +threshold[0] 50%,1 10477#@cli : $$ 10478threshold : check "isexpr($1) && isbool(${2=0})" 10479 e[^-1] ${"arg 1+!$2,Soft,Hard"}"-threshold image$? by $1." 10480 if $2 # Soft thresholding 10481 f "begin( 10482 str = ['$1']; 10483 value = str[size(str)-1]==_'%'?im + (iM-im)*$1:$1 10484 ); 10485 i>=value?i - value: 10486 i<=-value?i + value:0" 10487 else ge $1 10488 fi 10489 10490#@cli vector2tensor 10491#@cli : Convert selected vector fields to corresponding tensor fields. 10492vector2tensor : 10493 e[^-1] "Convert vector field$? to tensor field$?." 10494 repeat $! l[$>] 10495 s c 10496 if $!==2 +sqr. *.. ... sqr... 10497 elif $!==3 +sqr.. +*... .. +sqr... *[-5,-4] [-6] sqr[-6] 10498 else error[0--4] "Command '$0': Invalid image ["{$!-$>-1}"] : Dimensions "{w}","{h}","{d}","{s}" does not 10499 represent a field of 2D or 3D vectors." 10500 fi 10501 a c 10502 endl done 10503 10504#--------------------------------- 10505# 10506#@cli :: Colors 10507# 10508#--------------------------------- 10509 10510#@cli adjust_colors : -100<=_brightness<=100,-100<=_contrast<=100,-100<=_gamma<=100,-100<=_hue_shift<=100,\ 10511# -100<=_saturation<=100,_value_min,_value_max 10512#@cli : Perform a global adjustment of colors on selected images. 10513#@cli : Range of correct image values are considered to be in [value_min,value_max] (e.g. [0,255]). 10514#@cli : If 'value_min==value_max==0', value range is estimated from min/max values of selected images. 10515#@cli : Processed images have pixel values constrained in [value_min,value_max]. 10516#@cli : Default values: 'brightness=0', 'contrast=0', 'gamma=0', 'hue_shift=0', 'saturation=0', 'value_min=value_max=0'. 10517#@cli : $ image.jpg +adjust_colors 0,30,0,0,30 10518adjust_colors : check "${1=0}>=-100 && $1<=100 && ${2=0}>=-100 && $2<=100 && ${3=0}>=-100 && $3<=100 && 10519 ${4=0}>=-100 && $4<=100 && ${5=0}>=-100 && $5<=100" skip ${6=0},${7=0} 10520 e[^-1] "Adjust colors of image$?, with brightness $1, contrast $2, gamma $3, hue shift $4, saturation $5 and 10521 value range [$6,$7]." 10522 repeat $! l[$>] split_opacity l[0] 10523 range={"$6==$7 && $6==0?[im,iM]:[min($6,$7),max($6,$7)]"} 10524 m={arg(1,$range)} M={arg(2,$range)} fact={255/max(1e-5,$M-$m)} 10525 - $m * $fact 10526 if $4" || "$5 # Adjust Hue/Saturation 10527 to_rgb[0] rgb2hsv[0] 10528 sh[0] 0 +. {$4*1.8} rm. 10529 sh[0] 1 +. {($5%)^(1+($5>0))} c. 0,1 rm. 10530 hsv2rgb[0] 10531 fi 10532 if $3 # Adjust Gamma 10533 /[0] 255 ^[0] {10^-($3%)} *[0] 255 10534 fi 10535 if $2 # Adjust Contrast 10536 -[0] 128 *[0] {exp($2/64)} +[0] 128 10537 fi 10538 +[0] {$1*2} # Adjust Brightness 10539 /[0] $fact +[0] $m c[0] $range # Renormalize values. 10540 a c 10541 endl a c endl done 10542 10543#@cli ac : eq. to 'apply_channels'. 10544ac : 10545 _gmic_s="$?" v + _apply_channels $"*" 10546 10547#@cli apply_channels : "command",color_channels,_value_action={ 0=none | 1=cut | 2=normalize } 10548#@cli : Apply specified command on the chosen color channel(s) of each selected images. 10549#@cli : (eq. to 'ac').\n 10550#@cli : Argument 'color_channels' refers to a colorspace, and can be basically one of 10551#@cli : { all | rgba | [s]rgb | ryb | lrgb | ycbcr | lab | lch | hsv | hsi | hsl | cmy | cmyk | yiq }. 10552#@cli : You can also make the processing focus on a few particular channels of this colorspace, 10553#@cli : by setting 'color_channels' as 'colorspace_channel' (e.g. 'hsv_h' for the hue). 10554#@cli : All channel values are considered to be provided in the [0,255] range. 10555#@cli : Default value: 'value_action=0'. 10556#@cli : $ image.jpg +apply_channels "equalize blur 2",ycbcr_cbcr 10557apply_channels : 10558 _gmic_s="$?" v + _$0 $"*" 10559 10560_apply_channels : check "isint(${3=0}) && $3>=0 && $3<=2" 10561 channels=${"_ac_list \"$2\""} 10562 e[^-1] "Apply command '$1' on channels '"$channels"' of image"$_gmic_s"." 10563 ('$/') id={h=0;for(k=0,k<w,((h*=31)+=i[k++])%=1048576)} rm. 10564 _ac_$channels m _ac_precond$id:$_p m _ac_forward$id:$_f m _ac_backward$id:$_b 10565 repeat $! l[$>] 10566 _ac_precond$id is_alpha={s==2" || "s==4} 10567 if $is_alpha s c,{1-s} fi 10568 _ac_forward$id[0] a c 10569 sh $_s _ac. "$1" 10570 if $3==1 c. 0,255 elif $3==2 n. 0,255 fi 10571 rm. 10572 if $is_alpha s c,{1-s} fi 10573 _ac_backward$id[0] a c 10574 endl done 10575 um _ac_precond$id,_ac_forward$id,_ac_backward$id 10576 10577_ac_list : 10578 if isnum("$1") 10579 arg 1+round($1),all,rgba,rgb,rgb_r,rgb_g,rgb_b,rgba_a,\ 10580 lrgb,lrgb_r,lrgb_g,lrgb_b,\ 10581 ycbcr_y,ycbcr_cbcr,ycbcr_cb,ycbcr_cr,ycbcr_cg,\ 10582 lab_l,lab_ab,lab_a,lab_b,\ 10583 lch_ch,lch_c,lch_h,\ 10584 hsv_h,hsv_s,hsv_v,hsi_i,hsl_l,\ 10585 cmyk_c,cmyk_m,cmyk_y,cmyk_k,\ 10586 yiq_y,yiq_iq,ryb,ryb_r,ryb_y,ryb_b 10587 else u "$1" fi 10588 10589_ac : 10590 whds={w},{h},{d},{s} ${1--1} k[0] r $whds,0 10591 10592_ac_all : _p="" _f="" _b="" _s=0,100% 10593 10594_ac_rgba : _p="to_rgba" _f="" _b="" _s=0,3 10595_ac_rgba_r : _p="to_color" _f="" _b="" _s=0 10596_ac_rgba_g : _p="to_color" _f="" _b="" _s=1 10597_ac_rgba_b : _p="to_color" _f="" _b="" _s=2 10598_ac_rgba_a : _p="to_rgba" _f="" _b="" _s=3 10599 10600_ac_rgb : _p="to_color" _f="" _b="" _s=0,2 10601_ac_rgb_r : _ac_rgba_r 10602_ac_rgb_g : _ac_rgba_g 10603_ac_rgb_b : _ac_rgba_b 10604 10605_ac_srgb : _ac_rgb 10606_ac_srgb_r : _ac_rgb_r 10607_ac_srgb_g : _ac_rgb_g 10608_ac_srgb_b : _ac_rgb_b 10609 10610_ac_lrgb : _p="to_color" _f="srgb2rgb" _b="rgb2srgb" _s=0,2 10611_ac_lrgb_r : _p="to_color" _f="srgb2rgb" _b="rgb2srgb" _s=0 10612_ac_lrgb_g : _p="to_color" _f="srgb2rgb" _b="rgb2srgb" _s=1 10613_ac_lrgb_b : _p="to_color" _f="srgb2rgb" _b="rgb2srgb" _s=2 10614 10615_ac_ryb : _p="to_color" _f="rgb2ryb" _b="ryb2rgb" _s=0,2 10616_ac_ryb_r : _p="to_color" _f="rgb2ryb" _b="ryb2rgb" _s=0 10617_ac_ryb_y : _p="to_color" _f="rgb2ryb" _b="ryb2rgb" _s=1 10618_ac_ryb_b : _p="to_color" _f="rgb2ryb" _b="ryb2rgb" _s=2 10619 10620_ac_ycbcr : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=0,2 10621_ac_ycbcr_y : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=0 10622_ac_ycbcr_cbcr : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=1,2 10623_ac_ycbcr_cb : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=1 10624_ac_ycbcr_cr : _p="to_color" _f="rgb2ycbcr" _b="ycbcr2rgb" _s=2 10625_ac_ycbcr_cg : _p="to_color" _f="sh 0,1 mirror. c rm. rgb2ycbcr" _b="ycbcr2rgb sh 0,1 mirror. c rm." _s=2 10626 10627_ac_lab : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=0,2 10628_ac_lab_l : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=0 10629_ac_lab_ab : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=1,2 10630_ac_lab_a : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=1 10631_ac_lab_b : _p="to_color" _f="srgb2lab8" _b="lab82srgb" _s=2 10632 10633_ac_lch : _p="to_color" _f="srgb2rgb rgb2lch8" _b="lch82rgb rgb2srgb" _s=0,2 10634_ac_lch_l : _ac_lab_l 10635_ac_lch_ch : _p="to_color" _f="srgb2rgb rgb2lch8" _b="lch82rgb rgb2srgb" _s=1,2 10636_ac_lch_c : _p="to_color" _f="srgb2rgb rgb2lch8" _b="lch82rgb rgb2srgb" _s=1 10637_ac_lch_h : _p="to_color" _f="srgb2rgb rgb2lch8" _b="lch82rgb rgb2srgb" _s=2 10638 10639_ac_hsv : _p="to_color" _f="rgb2hsv8" _b="hsv82rgb" _s=0,2 10640_ac_hsv_h : _p="to_color" _f="rgb2hsv8" _b="hsv82rgb" _s=0 10641_ac_hsv_s : _p="to_color" _f="rgb2hsv8" _b="hsv82rgb" _s=1 10642_ac_hsv_v : _p="to_color" _f="rgb2hsv8" _b="hsv82rgb" _s=2 10643 10644_ac_hsi : _p="to_color" _f="rgb2hsi8" _b="hsi82rgb" _s=0,2 10645_ac_hsi_h : _p="to_color" _f="rgb2hsi8" _b="hsi82rgb" _s=0 10646_ac_hsi_s : _p="to_color" _f="rgb2hsi8" _b="hsi82rgb" _s=1 10647_ac_hsi_i : _p="to_color" _f="rgb2hsi8" _b="hsi82rgb" _s=2 10648 10649_ac_hsl : _p="to_color" _f="rgb2hsl8" _b="hsl82rgb" _s=0,2 10650_ac_hsl_h : _p="to_color" _f="rgb2hsl8" _b="hsl82rgb" _s=0 10651_ac_hsl_s : _p="to_color" _f="rgb2hsl8" _b="hsl82rgb" _s=1 10652_ac_hsl_l : _p="to_color" _f="rgb2hsl8" _b="hsl82rgb" _s=2 10653 10654_ac_cmy : _p="to_color" _f="rgb2cmy" _b="cmy2rgb" _s=0,2 10655_ac_cmy_c : _p="to_color" _f="rgb2cmy" _b="cmy2rgb" _s=0 10656_ac_cmy_m : _p="to_color" _f="rgb2cmy" _b="cmy2rgb" _s=1 10657_ac_cmy_y : _p="to_color" _f="rgb2cmy" _b="cmy2rgb" _s=2 10658 10659_ac_cmyk : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=0,3 10660_ac_cmyk_c : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=0 10661_ac_cmyk_m : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=1 10662_ac_cmyk_y : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=2 10663_ac_cmyk_k : _p="to_color" _f="rgb2cmyk" _b="cmyk2rgb" _s=3 10664 10665_ac_yiq : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=0,2 10666_ac_yiq_y : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=0 10667_ac_yiq_iq : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=1,2 10668_ac_yiq_i : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=1 10669_ac_yiq_q : _p="to_color" _f="rgb2yiq8" _b="yiq82rgb" _s=2 10670 10671#@cli autoindex : nb_colors>0,0<=_dithering<=1,_method={ 0=median-cut | 1=k-means } 10672#@cli : Index selected vector-valued images by adapted colormaps. 10673#@cli : Default values: 'dithering=0' and 'method=1'. 10674#@cli : $ image.jpg +autoindex[0] 4 +autoindex[0] 8 +autoindex[0] 16 10675autoindex : check "isint($1) && $1>0 && ${2=0}>=0" skip ${3=1} 10676 e[^-1] "Index colors in images$? by adapted colormap with $1 entries, dithering level $2 and "\ 10677 ${arg\ 1+!$3,k-means,median-cut}" method." 10678 repeat $! l[$>] 10679 if w>h if w>256 +r2dx 256 else [0] fi 10680 else if h>256 +r2dy 256 else [0] fi 10681 fi 10682 colormap[1] $1,$3,0 10683 index[0] [1],$2,1 rm[1] 10684 endl done 10685 10686#@cli bayer2rgb : _GM_smoothness,_RB_smoothness1,_RB_smoothness2 10687#@cli : Transform selected RGB-Bayer sampled images to color images. 10688#@cli : Default values: 'GM_smoothness=RB_smoothness=1' and 'RB_smoothness2=0.5'. 10689#@cli : $ image.jpg rgb2bayer 0 +bayer2rgb 1,1,0.5 10690bayer2rgb : skip ${1=1},${2=1},${3=0.5} 10691 e[^-1] "Transform RGB-Bayer image$? to color images, with smoothness ($1,$2,$3)." 10692 channels 0 repeat $! l[$>] 10693 10694 # Expand image size to avoid problems with borders. 10695 expand_x {"2 + 4*$1"},0 expand_y {"2 + 4*$1"},0 10696 10697 # Compute green-magenta chromaticity. 10698 (-1,1;1,-1) r. ..,..,1,1,0,2 10699 +*.. . 10700 10701 (0.25,0.5,0.25) convolve.. . transpose. convolve.. . rm. 10702 b. $1 10703 10704 *.. . 10705 -[-3,-2] 10706 10707 # Compute red-blue chromaticity. 10708 (1,-1) r. ..,..,1,1,0,2 # Horizontal estimate 10709 *. ... 10710 (0.25,0.5,0.25) convolve.. . transpose. convolve.. . rm. 10711 blur_y. $2 blur_x. $3 10712 10713 (1;-1) r. ..,..,1,1,0,2 # Vertical estimate 10714 *. [-4] 10715 (0.25,0.5,0.25) convolve.. . transpose. convolve.. . rm. 10716 blur_x. $2 blur_y. $3 10717 10718 +[-2,-1] /. 2 10719 10720 # Luminance reconstruction. 10721 (2,0;0,-2) r. ..,..,1,1,0,2 10722 *. .. 10723 -[-4,-1] 10724 10725 # RGB reconstruction. 10726 a[-3--1] c 10727 mix_rgb. 1,-1,2,1,1,0,1,-1,-2 10728 10729 # Shrink to original image size. 10730 shrink_x {"2 + 4*$1"},0 shrink_y {"2 + 4*$1"},0 10731 c 0,255 10732 10733 endl done 10734 10735#@cli deltaE : [image],_metric={ 0=deltaE_1976 | 1=deltaE_2000 },"_to_Lab_command" 10736#@cli : Compute the CIE DeltaE color difference between selected images and specified [image]. 10737#@cli : Argument 'to_Lab_command' is a command able to convert colors of [image] into a Lab representation. 10738#@cli : Default values: 'metric=1' and 'to_Lab_command="srgb2lab"'. 10739#@cli : $ image.jpg +blur 2 +deltaE[0] [1],1,srgb2lab 10740deltaE : check ${"is_image_arg $1"}" && isbool(${2=1})" skip "${3=srgb2lab}" 10741 e[^-1] "Compute the CIE DeltaE_"${"s0,s1=1976,2000 u $s$2"}" color difference between image$? and image$1, "\ 10742 "with to_Lab command '$3'." 10743 pass$1 1 10744 needs_to_lab={"s = ['$3']; s!=0 && s!=' '"} 10745 if $needs_to_lab m "_deltaE_to_lab : $3" +_deltaE_to_lab. rm.. fi 10746 repeat $!-1 l[$>,-1] nm={0,n} 10747 if $needs_to_lab _deltaE_to_lab[0] fi 10748 if !$2 -.. . norm.. # DeltaE_1976 10749 else 100%,100%,100%,1,${-math_lib}"deltaE00(I#0,I#1)" rv[0,-1] rm. # DeltaE_2000 10750 fi 10751 nm[0] $nm endl done 10752 rm. um _deltaE_to_lab 10753 10754#@cli cmy2rgb 10755#@cli : Convert color representation of selected images from CMY to RGB. 10756cmy2rgb : 10757 e[^-1] "Convert color representation of image$? from CMY to RGB." 10758 rgb2cmy 10759 10760#@cli cmyk2rgb 10761#@cli : Convert color representation of selected images from CMYK to RGB. 10762cmyk2rgb : 10763 e[^-1] "Convert color representation of image$? from CMYK to RGB." 10764 repeat $! l[$>] 10765 s c +/. -255 +. 1 *[0-2] . rm. +[0-2] . rm. 10766 a c cmy2rgb 10767 endl done 10768 10769#@cli colorblind : type={ 0=protanopia | 1=protanomaly | 2=deuteranopia | 3=deuteranomaly | \ 10770# 4=tritanopia | 5=tritanomaly | 6=achromatopsia | 7=achromatomaly } 10771#@cli : Simulate color blindness vision. 10772#@cli : $ image.jpg +colorblind 0 10773colorblind : check "isint($1) && $1>=0 && $1<=7" 10774 s0="protanopia" s1="protanomaly" s2="deuteranopia" s3="deuteranomaly" s4="tritanopia" 10775 s5="tritanomaly" s6="achromatopsia" s7="achromatomaly" 10776 e[^-1] "Simulate color blindness of type '"${s$1}"' on image$?." 10777 type0=(0.567,0.433,0;0.558,0.442,0;0,0.242,0.758) 10778 type1=(0.817,0.183,0;0.333,0.667,0;0,0.125,0.875) 10779 type2=(0.625,0.375,0;0.7,0.3,0;0,0.3,0.7) 10780 type3=(0.8,0.2,0;0.258,0.742,0;0,0.142,0.858) 10781 type4=(0.95,0.05,0;0,0.433,0.567;0,0.475,0.525) 10782 type5=(0.967,0.033,0;0,0.733,0.267;0,0.183,0.817) 10783 type6=(0.299,0.587,0.114;0.299,0.587,0.114;0.299,0.587,0.114) 10784 type7=(0.618,0.320,0.062;0.163,0.775,0.062;0.163,0.320,0.516) 10785 repeat $! l[$>] split_opacity l[0] to_rgb mix_channels ${type$1} endl a c endl done 10786 10787#@cli colormap : nb_levels>=0,_method={ 0=median-cut | 1=k-means },_sort_vectors 10788#@cli : Estimate best-fitting colormap with 'nb_colors' entries, to index selected images. 10789#@cli : Set 'nb_levels==0' to extract all existing colors of an image. 10790#@cli : 'sort_vectors' can be { 0=unsorted | 1=by increasing norm | 2=by decreasing occurrence }. 10791#@cli : Default value: 'method=1' and 'sort_vectors=1'. 10792#@cli : $ image.jpg +colormap[0] 4 +colormap[0] 8 +colormap[0] 16 10793#@cli : $$ https://gmic.eu/oldtutorial/_colormap 10794colormap : check "isint($1) && $1>=0" skip ${2=1},${3=1} 10795 if $1 e[0--3] "Estimate colormap with $1 entries for image$?, by "${arg\ 1+!$2,k-means,median-cut}" method." 10796 else e[0--3] "Estimate full colormap for image$?." 10797 fi 10798 repeat $! l[$>] nm={b} is_half=${-is_half} 10799 10800 if $1 # Estimate quantized colormap. 10801 r {whd},1,1,100%,-1 10802 if !$2 +_colormap $1 # Just run the median-cut algorithm 10803 else 10804 +_colormap $1 10805 max_diff={(iM-im+1)/8192} 10806 do 10807 +index.. . # Find nearest cluster for each color 10808 if $is_half 10809 ..,1,1,{1,s} 10810 eval " 10811 ref(vector(#w*s#0),csum); 10812 ref(vector(#w,0),cocc); 10813 repeat (w#2,k, 10814 val = i[#2,k]; 10815 repeat (s#0,c,csum[val + c*w]+=i(#0,k,0,0,c)); 10816 ++cocc[val]; 10817 ); 10818 off = 0; 10819 repeat (s#0,c, 10820 repeat (w,k,occ = cocc[k]; occ?(csum[off++]/=occ)); 10821 ); 10822 draw(#3,csum,0,0,0,0)" 10823 rm.. 10824 else 10825 ..,1,1,{1,s+1} 10826 f.. ">I[#3,i]+=[ I[#0,x],1 ]" rm.. 10827 f. "s = i(x,0,0,s-1); s?I/s:[ I[#1,x], 0 ]" 10828 fi 10829 +-.. . abs. diff={iM/w} rm. # Compute colormap difference 10830 j.. . rm. 10831 while $diff>$max_diff 10832 fi 10833 if $3 index.. .,0,0 histogram.. {[w,0,w-1]} a y sort -,x rows 1 # Sort by decreasing occurrence 10834 else rm.. 10835 fi 10836 10837 else # Extract full colormap. 10838 10839 # Compute map of hashcodes. 10840 +n. 0,255 f. "ret = vectors(); H = 0; repeat (s,p,(H*=31)+=j(0,0,0,p)); ret[0] = H%2048; ret" 10841 channels. 0 equalize. 2048 n. 0,2047 round. 10842 10843 # Find single occurrence of each color/vector. 10844 1,1,1,.. .x2047 10845 eval[0] ">"${-math_lib}" 10846 begin( ret = vectors(); col_r = vectors() ); 10847 col_s = I; 10848 H = 2 + i#1; 10849 sH = dar_size(#H); 10850 is_found = 0; 10851 repeat (sH,p, 10852 copy(col_r,i[#H,p],s#0,1,h(#H)); 10853 col_r==col_s?(is_found = 1; break()); 10854 ); 10855 !is_found?dar_insert(#H,col_s); 10856 ret; 10857 end(repeat (l - 2,p, resize(#2 + p,1,dar_size(#2 + p),1,s#0,0)))" 10858 a[2--1] y transpose. k. 10859 fi 10860 10861 if $3==1 +norm rv a c sort +,x channels 1,100% fi # Sort colors by increasing norm. 10862 nm "[colormap of "$nm"]" 10863 endl done 10864 10865_colormap : # Implementation of the median-cut algorithm. 10866 m "__colormap : repeat s sh[$""1] $> =.. {iv},$""1,0,0,$> rm. done" 10867 1,1,1,{s} __colormap 0 # Initialize image of box variances 10868 repeat $1-1 10869 b,a={[xM,cM]} # b = box with highest variance, a = axis with highest variance 10870 shift[$b] 0,0,0,{-$a},2 sort[$b] +,x shift[$b] 0,0,0,$a,2 10871 if {$b,w>1} s[$b] x,2 else 1 fi # Split selected box along its median axis 10872 mv[$b] -1 r. {w+1},1,1,100%,0 10873 __colormap $b __colormap {$!-2} # Update box variances 10874 done 10875 rm. r 1,1,1,100%,2 a x # Average value in each box and append as final colormap 10876 um __colormap 10877 10878#@cli compose_channels 10879#@cli : Compose all channels of each selected image, using specified arithmetic operator (+,-,or,min,...). 10880#@cli : Default value: '1=+'. 10881#@cli : $ image.jpg +compose_channels and 10882#@cli : $$ 10883compose_channels : skip ${1="+"} 10884 e[^-1] "Compose all channels of image$?, with operator '$1'." 10885 repeat $! l[$>] 10886 sh 0 10887 repeat s#-2-1 sh.. {$>+1} l[-2,-1] $1 endl done 10888 rm. r 100%,100%,100%,1,-1 10889 endl done 10890 10891#@cli direction2rgb 10892#@cli : Compute RGB representation of selected 2D direction fields. 10893#@cli : $ image.jpg luminance gradient append c blur 2 orientation +direction2rgb 10894direction2rgb : 10895 e[^-1] "Compute RGB representation of 2D direction field$?." 10896 channels 0,1 repeat $! l[$>] nm={0,n} 10897 s c complex2polar round.. 0.001 10898 *. {180/pi} %. 360 100%,100%,1,1,1 mv... $! 10899 if im!=iM n. 0,1 else f. 1 fi 10900 a c hsv2rgb 10901 nm $nm endl done 10902 10903#@cli ditheredbw 10904#@cli : Create dithered B&W version of selected images. 10905#@cli : $ image.jpg +equalize ditheredbw[-1] 10906ditheredbw : 10907 e[^-1] "Create dithered B&W version of image$?." 10908 repeat $! l[$>] split_opacity 10909 luminance[0] n[0] 0,255 (0,255) index[0] .,1,1 rm. 10910 a c endl done 10911 10912#@cli fc : eq. to 'fill_color'. 10913fc : 10914 _gmic_s="$?" v + _fill_color $* 10915 10916#@cli fill_color : col1,...,colN 10917#@cli : Fill selected images with specified color. 10918#@cli : (eq. to 'fc'). 10919#@cli : $ image.jpg +fill_color 255,0,255 10920#@cli : $$ https://gmic.eu/oldtutorial/_fill_color 10921fill_color : 10922 _gmic_s="$?" v + _$0 $* 10923 10924_fill_color : 10925 e[0--3] "Fill image"$_gmic_s" with color (${^0})." 10926 repeat $! l[$>] 10927 repeat s sh[0] $> f. {arg(1+$>,${^0})} done k[0] 10928 nm {n} endl done 10929 10930#@cli gradient2rgb : _is_orientation={ 0 | 1 } 10931#@cli : Compute RGB representation of 2D gradient of selected images. 10932#@cli : Default value: 'is_orientation=0'. 10933#@cli : $ image.jpg +gradient2rgb 0 equalize[-1] 10934gradient2rgb : check "isbool(${1=0})" 10935 arg 1+!$1,"orientation ","" 10936 e[^-1] "Compute RGB representation of 2D gradient "${}"of image$?." 10937 norm repeat $! l[$>] 10938 if $1 gradient_orientation 2 else g xy fi 10939 a c direction2rgb 10940 endl done 10941 10942#@cli hcy2rgb 10943#@cli : Convert color representation of selected images from HCY to RGB. 10944hcy2rgb : 10945 e[^-1] "Convert color representation of image$? from HCY to RGB." 10946 to_color f " 10947 H = (R/60)%6; 10948 X = G*(1 - abs(H%2 - 1)); 10949 RGB = arg(1 + int(H),[G,X,0],[X,G,0],[0,G,X],[0,X,G],[X,0,G],[G,0,X]); 10950 m = B - 0.3*RGB[0] - 0.59*RGB[1] - 0.11*RGB[2]; 10951 cut((RGB+=m)*=255,0,255)" 10952 10953#@cli hsi2rgb 10954#@cli : Convert color representation of selected images from HSI to RGB. 10955hsi2rgb : 10956 e[^-1] "Convert color representation of image$? from HSI to RGB." 10957 to_color 10958 f " 10959 H = (R/60)%6; 10960 S = G; 10961 I = B; 10962 Z = 1 - abs((H%2) - 1); 10963 C = I*S/(1 + Z); 10964 X = C*Z; 10965 m = I*(1 - S)/3; 10966 RGB = arg(1 + int(H),[C,X,0],[X,C,0],[0,C,X],[0,X,C],[X,0,C],[C,0,X]); 10967 (RGB+=m)*=3*255" 10968 10969#@cli hsi82rgb 10970#@cli : Convert color representation of selected images from HSI8 to RGB. 10971hsi82rgb : 10972 e[^-1] "Convert color representation of image$? from HSI8 to RGB." 10973 _hsx82rgb hsi2rgb 10974 10975#@cli hsl2rgb 10976#@cli : Convert color representation of selected images from HSL to RGB. 10977hsl2rgb : 10978 e[^-1] "Convert color representation of image$? from HSL to RGB." 10979 to_color 10980 f " 10981 H = (R/60)%6; 10982 S = G; 10983 L = B; 10984 C = (1 - abs(2*L - 1))*S; 10985 X = C*(1 - abs(H%2 - 1)); 10986 m = L - C/2; 10987 RGB = arg(1 + int(H),[C,X,0],[X,C,0],[0,C,X],[0,X,C],[X,0,C],[C,0,X]); 10988 (RGB+=m)*=255" 10989 10990#@cli hsl82rgb 10991#@cli : Convert color representation of selected images from HSL8 to RGB. 10992hsl82rgb : 10993 e[^-1] "Convert color representation of image$? from HSL8 to RGB." 10994 _hsx82rgb hsl2rgb 10995 10996#@cli hsv2rgb 10997#@cli : Convert color representation of selected images from HSV to RGB. 10998#@cli : $ (0,360;0,360^0,0;1,1^1,1;1,1) resize 400,400,1,3,3 hsv2rgb 10999hsv2rgb : 11000 e[^-1] "Convert color representation of image$? from HSV to RGB." 11001 to_color 11002 f " 11003 H = (R/60)%6; 11004 S = G; 11005 V = B; 11006 C = V*S; 11007 X = C*(1 - abs(H%2 - 1)); 11008 m = V - C; 11009 RGB = arg(1 + int(H),[C,X,0],[X,C,0],[0,C,X],[0,X,C],[X,0,C],[C,0,X]); 11010 (RGB+=m)*=255" 11011 11012#@cli hsv82rgb 11013#@cli : Convert color representation of selected images from HSV8 to RGB. 11014hsv82rgb : 11015 e[^-1] "Convert color representation of image$? from HSV8 to RGB." 11016 _hsx82rgb hsv2rgb 11017 11018_hsx82rgb : 11019 repeat $! 11020 sh[$>] 0 /. 0.708333 rm. 11021 sh[$>] 1,2 /. 255 rm. 11022 done 11023 11024#@cli int2rgb 11025#@cli : Convert color representation of selected images from INT24 to RGB. 11026int2rgb : 11027 e[^-1] "Convert color representation of image$? from INT24 scalars to RGB." 11028 round repeat $! l[$>] 11029 +>> 8 &[1] 255 +&[0] 255 >>[0] 16 a c 11030 endl done 11031 11032#@cli jzazbz2rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11033#@cli : Convert color representation of selected images from RGB to Jzazbz. 11034#@cli : Default value: 'illuminant=2'. 11035jzazbz2rgb : skip "${1=,}" 11036 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 11037 e[^-1] "Convert color representation of image$? from Jzazbz to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11038 jzazbz2xyz xyz2rgb $illu 11039 11040#@cli jzazbz2xyz 11041#@cli : Convert color representation of selected images from RGB to XYZ. 11042jzazbz2xyz : 11043 e[^-1] "Convert color representation of image$? from Jzazbz to XYZ." 11044 repeat $! l[$>] split_opacity 11045 f[0] ${-_jzazbz_const}" 11046 tmp = i0 + Jzazbz_d0; 11047 Iz = tmp/(1 + Jzazbz_d - Jzazbz_d*tmp); 11048 azz = i1; 11049 bzz = i2; 11050 Lp = Iz + 0.138605043271539*azz + 0.0580473161561189*bzz; 11051 Mp = Iz - 0.138605043271539*azz - 0.0580473161561189*bzz; 11052 Sp = Iz - 0.0960192420263189*azz - 0.811891896056039*bzz; 11053 tmp = Lp^(1/Jzazbz_p); 11054 L = peakLum*((Jzazbz_c1 - tmp)/(Jzazbz_c3*tmp-Jzazbz_c2))^(1/Jzazbz_n); 11055 tmp = Mp^(1/Jzazbz_p); 11056 M = peakLum*((Jzazbz_c1 - tmp)/(Jzazbz_c3*tmp-Jzazbz_c2))^(1/Jzazbz_n); 11057 tmp = Sp^(1/Jzazbz_p); 11058 S = peakLum*((Jzazbz_c1 - tmp)/(Jzazbz_c3*tmp-Jzazbz_c2))^(1/Jzazbz_n); 11059 Xp = 1.92422643578761*L - 1.00479231259537*M + 0.037651404030618*S; 11060 Yp = 0.350316762094999*L + 0.726481193931655*M - 0.065384422948085*S; 11061 Zp = -0.0909828109828476*L - 0.312728290523074*M + 1.52276656130526*S; 11062 X = (Xp + (Jzazbz_b - 1)*Zp)/Jzazbz_b; 11063 Y = (Yp + (Jzazbz_g - 1)*X)/Jzazbz_g; 11064 Z = Zp; 11065 [ X,Y,Z ]/255" 11066 a c endl done 11067 11068# The XYZ<->Jzazbz conversion code has been written by Alan Gibson, 11069# and published on this page: <http://im.snibgo.com/jzazbz.htm> 11070_jzazbz_const : 11071 u "const Jzazbz_b = 1.15; 11072 const Jzazbz_g = 0.66; 11073 const Jzazbz_c1 = 3424/4096; 11074 const Jzazbz_c2 = 2413/128; 11075 const Jzazbz_c3 = 2392/128; 11076 const Jzazbz_n = 2610/16384; 11077 const Jzazbz_p = 1.7*2523/32; 11078 const Jzazbz_d = -0.56; 11079 const Jzazbz_d0 = 1.6295499532821566e-11; 11080 const peakLum = 10000;" 11081 11082#@cli lab2lch 11083#@cli : Convert color representation of selected images from Lab to Lch. 11084lab2lch : 11085 e[^-1] "Convert color representation of image$? from Lab to Lch." 11086 repeat $! l[$>] 11087 to_color s c complex2polar[1,2] a c 11088 endl done 11089 11090#@cli lab2rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11091#@cli : Convert color representation of selected images from Lab to RGB. 11092#@cli : Default value: 'illuminant=2'. 11093#@cli : $ (50,50;50,50^-3,3;-3,3^-3,-3;3,3) resize 400,400,1,3,3 lab2rgb 11094lab2rgb : skip "${1=,}" 11095 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 11096 e[^-1] "Convert color representation of image$? from Lab to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11097 lab2xyz $illu xyz2rgb $illu 11098 11099#@cli lab2srgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11100#@cli : Convert color representation of selected images from Lab to sRGB. 11101#@cli : Default value: 'illuminant=2'. 11102#@cli : $ (50,50;50,50^-3,3;-3,3^-3,-3;3,3) resize 400,400,1,3,3 lab2rgb 11103lab2srgb : skip "${1=,}" 11104 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 11105 e[^-1] "Convert color representation of image$? from Lab to sRGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11106 lab2rgb $illu rgb2srgb 11107 11108#@cli lab82srgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11109#@cli : Convert color representation of selected images from Lab8 to sRGB. 11110#@cli : Default value: 'illuminant=2'. 11111#@cli : $ (50,50;50,50^-3,3;-3,3^-3,-3;3,3) resize 400,400,1,3,3 lab2rgb 11112lab82srgb : skip "${1=,}" 11113 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 11114 e[^-1] "Convert color representation of image$? from Lab8 to sRGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11115 lab82rgb $illu rgb2srgb 11116 11117#@cli lab2xyz : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11118#@cli : Convert color representation of selected images from Lab to XYZ. 11119#@cli : Default value: 'illuminant=2'. 11120lab2xyz : skip "${1=,}" 11121 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 11122 e[^-1] "Convert color representation of image$? from Lab to XYZ, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11123 to_color 11124 f " 11125 begin( 11126 const epsilon = 216/24389; 11127 const kappa = 24389/27; 11128 D65 = [ 0.4124564, 0.3575761, 0.1804375, 11129 0.2126729, 0.7151522, 0.0721750, 11130 0.0193339, 0.1191920, 0.9503041 ]; 11131 D50 = [ 0.43603516, 0.38511658, 0.14305115, 11132 0.22248840, 0.71690369, 0.06060791, 11133 0.01391602, 0.09706116, 0.71392822 ]; 11134 E = [ 0.488718,0.3106803,0.2006017, 11135 0.1762044,0.8129847,0.0108109, 11136 0,0.0102048,0.9897952 ]; 11137 white = ("$illu"==2?E:"$illu"==1?D65:D50)*[ 1,1,1 ]; 11138 ); 11139 11140 fy = (i0 + 16)/116; 11141 fz = fy - i2/200; 11142 fx = i1/500 + fy; 11143 fx3 = fx^3; 11144 fz3 = fz^3; 11145 XYZ = [ fx3>epsilon?fx3:(116*fx - 16)/kappa, 11146 i0>kappa*epsilon?((i0+16)/116)^3:i0/kappa, 11147 fz3>epsilon?fz3:(116*fz - 16)/kappa ]; 11148 XYZ*=white" 11149 11150#@cli lab82rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11151#@cli : Convert color representation of selected images from Lab8 to RGB. 11152#@cli : Default value: 'illuminant=2'. 11153lab82rgb : skip "${1=,}" 11154 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 11155 e[^-1] "Convert color representation of image$? from Lab8 to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11156 repeat $! 11157 sh[$>] 0 /. 2.55 rm. 11158 sh[$>] 1 /. 0.85 -. 127 rm. 11159 sh[$>] 2 /. 0.836 -. 149 rm. 11160 done lab2rgb $illu c 0,255 11161 11162#@cli lch2lab 11163#@cli : Convert color representation of selected images from Lch to Lab. 11164lch2lab : 11165 e[^-1] "Convert color representation of image$? from Lch to Lab." 11166 repeat $! l[$>] 11167 to_color s c polar2complex[1,2] a c 11168 endl done 11169 11170#@cli lch2rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11171#@cli : Convert color representation of selected images from Lch to RGB. 11172#@cli : Default value: 'illuminant=2'. 11173lch2rgb : skip "${1=,}" 11174 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 11175 e[^-1] "Convert color representation of image$? from Lch to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11176 lch2lab lab2rgb $illu 11177 11178#@cli lch82rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11179#@cli : Convert color representation of selected images from Lch8 to RGB. 11180#@cli : Default value: 'illuminant=2'. 11181lch82rgb : skip "${1=,}" 11182 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 11183 e[^-1] "Convert color representation of image$? from Lch8 to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11184 pi,facth={[pi,255/(2*pi)]} 11185 repeat $! 11186 sh[$>] 0 /. 2.55 rm. 11187 sh[$>] 1 /. 1.1086 rm. 11188 sh[$>] 2 /. $facth -. $pi rm. 11189 done lch2rgb $illu c 0,255 11190 11191#@cli luminance 11192#@cli : Compute luminance of selected sRGB images. 11193#@cli : $ image.jpg +luminance 11194#@cli : $$ 11195luminance : 11196 e[^-1] "Compute luminance of image$?." 11197 remove_opacity srgb2rgb 11198 repeat $! l[$>] 11199 if s==3 sh 0 sh[0] 1 sh[0] 2 *[1] 0.22248840 *[2] 0.71690369 *[3] 0.06060791 +[1-3] rm[1] 11200 elif s!=1 norm n 0,255 11201 fi endl done 11202 channels 0 rgb2srgb 11203 11204#@cli lightness 11205#@cli : Compute lightness of selected sRGB images. 11206#@cli : $ image.jpg +lightness 11207lightness : 11208 e[^-1] "Compute lightness of image$?." 11209 remove_opacity srgb2rgb 11210 if s==3 srgb2lab channels 0 * {255/100} elif s!=1 norm n 0,255 rgb2srgb fi 11211 11212#@cli lut_contrast : _nb_colors>1,_min_rgb_value 11213#@cli : Generate a RGB colormap where consecutive colors have high contrast. 11214#@cli : This function performs a specific score maximization to generate the result, so 11215#@cli : it may take some time when 'nb_colors' is high. 11216#@cli : Default values: 'nb_colors=256' and 'min_rgb_value=64'. 11217lut_contrast : check "isint(${1=256}) && $1>=1 && isnum(${2=48})" 11218 e[^-1] "Generate high-contrast RGB colormap with $1 colors and min RGB value $2." 11219 l[] 11220 11221 # Initialization by farthest point sampling of the RGB cube. 11222 64,64,64,1 eval "repeat (8,k, x = !!(k&1); y = !!(k&2); z = !!(k&4); i([x,y,z]*(w-1)) = 1)" 11223 N={is} 11224 e[] "" 11225 do 11226 +neq. 0 distance. 1 xyzM={[xM,yM,zM]} rm. 11227 col={round([$xyzM]*255/(w-1))} 11228 if max($col)>=$2 =. 1,$xyzM N+=1 else =. -1,$xyzM fi 11229 e[] "\r [ Init ] > Colors \#"$N 11230 while $N<$1 11231 >. 0 {is},1,1,3 11232 eval.. ">begin(k = 0); i>0?(I[#-1,k++] = round([ x,y,z ]*255/63))" 11233 k. 11234 11235 N0=5 # 5 first colors to be preserved. 11236 s x repeat $! 11237 if {$>,I==[0,0,0]} rv[$>,0] fi 11238 if {$>,I==[255,255,255]} rv[$>,1] fi 11239 if {$>,I==[255,0,0]} rv[$>,2] fi 11240 if {$>,I==[0,255,0]} rv[$>,3] fi 11241 if {$>,I==[0,0,255]} rv[$>,4] fi 11242 done a x 11243 11244 # Functional optimization. 11245 e[] "" 11246 +srgb2lab a c 11247 energy_max=${-_lut_contrast.} 11248 nb_attempts=1000 11249 do 11250 e[] "\r [ Optim ] > Score = "{_$energy_max}", Attempts = "$nb_attempts" " 11251 . eval " 11252 do( 11253 k0 = round(u("$N0",w-1)); 11254 k1 = round(u("$N0",w-1)), 11255 k0==k1); 11256 tmp = I[k0]; I[k0] = I[k1]; I[k1] = tmp" 11257 energy=${-_lut_contrast.} 11258 if $energy>$energy_max energy_max=$energy k. nb_attempts=1000 else rm. nb_attempts-=1 fi 11259 while $nb_attempts>0 11260 11261 channels 0,2 11262 endl 11263 11264_lut_contrast : 11265 100%,1,1,1,"> 11266 const N = 10; 11267 dist = 0; sumw = 0; 11268 RGB0 = (I[#0,x])[3,3]; 11269 kmin = max(x-N,0); 11270 kmax = min(x+N,w-1); 11271 for (k = kmin, k<=kmax, ++k, 11272 RGB = (I[#0,k])[3,3]; 11273 w = (1 + N - abs(k-x))^1.5; 11274 dist+= w*norm(RGB - RGB0); 11275 sumw+=w; 11276 ); 11277 dist/=sumw" 11278 u {is} rm. 11279 11280#@cli map_clut : [clut] | "clut_name" 11281#@cli : Map specified RGB color LUT to selected images. 11282#@cli : $ image.jpg uniform_distribution {2^6},3 mirror[-1] x +map_clut[0] [1] 11283map_clut : 11284 e[^-1] "Map color LUT $1 on image$?." 11285 if !$! return fi 11286 to_color 11287 if ${"is_image_arg $1"} pass$1 0 to_rgb. else clut "$1" fi 11288 l={round((w*h*d)^(1/3))} 11289 if w*h*d!=$l^3 error "Command '$0': Specified CLUT $1 has invalid dimensions "({w},{h},{d},{s}). fi 11290 r. $l,$l,$l,3,-1 11291 repeat $!-1 l[$>,-1] nm={0,n} split_opacity[0] /[0] {256/$l} 11292 +warp. [0],0,1,1 11293 rm[0] mv. 0 a[^-1] c nm[0] $nm 11294 endl done rm. 11295 11296#@cli mix_rgb : a11,a12,a13,a21,a22,a23,a31,a32,a33 11297#@cli : Apply 3x3 specified matrix to RGB colors of selected images. 11298#@cli : Default values: 'a11=1', 'a12=a13=a21=0', 'a22=1', 'a23=a31=a32=0' and 'a33=1'. 11299#@cli : $ image.jpg +mix_rgb 0,1,0,1,0,0,0,0,1 11300#@cli : $$ 11301mix_rgb : skip ${1=1},${2=0},${3=0},${4=0},${5=1},${6=0},${7=0},${8=0},${9=1} 11302 e[^-1] "Apply matrix [ $1 $2 $3 ; $4 $5 $6 ; $7 $8 $9 ] to RGB colors of image$?." 11303 to_color repeat $! sh[$>] 0,2 mix_channels. (${1-3};${4-6};${7-9}) rm. done 11304 11305#@cli oklab2rgb 11306#@cli : Convert color representation of selected images from OKlab to RGB. 11307#@cli : (see colorspace definition at: <https://bottosson.github.io/posts/oklab/> ). 11308#@cli : See also: ''rgb2oklab''. 11309oklab2rgb : 11310 e[^-1] "Convert color representation of image$? from Oklab to RGB." 11311 repeat $! l[$>] split_opacity to_rgb[0] 11312 f[0] " 11313 l = (i0 + 0.3963377774*i1 + 0.2158037573*i2)^3; 11314 m = (i0 - 0.1055613458*i1 - 0.0638541728*i2)^3; 11315 s = (i0 - 0.0894841775*i1 - 1.2914855480*i2)^3; 11316 [ 4.0767245293*l - 3.3072168827*m + 0.2307590544*s, 11317 -1.2681437731*l + 2.6093323231*m - 0.3411344290*s, 11318 -0.0041119885*l - 0.7034763098*m + 1.7068625689*s ]" 11319 * 255 11320 a c endl done 11321 11322#@cli palette : palette_name | palette_number 11323#@cli : Input specified color palette at the end of the image list. 11324#@cli : 'palette_name' can be { default | hsv | lines | hot | cool | jet | flag | cube | rainbow | \ 11325# parula | spring | summer | autumn | winter | bone | copper | pink | vga | \ 11326# algae | amp | balance | curl | deep | delta | dense | diff | gray | haline | ice | \ 11327# matter | oxy | phase | rain | solar | speed | tarn | tempo | thermal | topo | turbid | aurora | hocuspocus | srb2 | \ 11328# uzebox | amiga7800 | amiga7800mess | fornaxvoid1 } 11329#@cli : $ palette hsv 11330palette : 11331 names=${-_palette_names} N={narg($names)} 11332 l[] if isint("$1") name=${"arg 1+($1%"$N"),"$names} else name="$1" fi onfail name="$1" endl 11333 e[^-1] "Input color palette '"$name"'." 11334 _palette_$name 11335 nm. $name 11336 11337_palette_names : 11338 u default,hsv,lines,hot,cool,jet,flag,cube,rainbow,\ 11339 parula,spring,summer,autumn,winter,bone,copper,pink,vga,\ 11340 algae,amp,balance,curl,deep,delta,dense,diff,gray,haline,ice,\ 11341 matter,oxy,phase,rain,solar,speed,tarn,tempo,thermal,topo,turbid,aurora,hocuspocus,srb2,uzebox,\ 11342 amiga7800,amiga7800mess,fornaxvoid1 11343 11344_palette2code : # Convert a set of input palettes 11345 sort_list +,n 11346 repeat $! l[$>] 11347 r {whd},1,1,100%,-1 11348 img2base64 0,0 11349 e[] "_palette_"{n}" : " 11350 b64=\"${}\" 11351 l[] ('$b64') s x,-119 ('\\\\\n') a[0--3] .,x rm. a x b64={t} rm endl # No more than 120 char / lines 11352 e[] " base642img \\\n"$b64"\n" 11353 endl done 11354 11355# The color palettes below comes from the CImg library 'http://cimg.eu/'. 11356_palette_default : 11357 256,1,1,3,[16+32*int(x>>5),16+32*int((x>>2)&7),32+64*int(x&3)] 11358 11359_palette_hsv : 11360 256,1,1,3,[x*359/(w-1),1,1] hsv2rgb. round. 11361 11362_palette_lines : 11363 base642img \ 11364"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2MTcKeJwNkhGgu1AYxT8YDP4QDB4Eg+BKEATBYBAEQXDhQhAMHgweBBeuXB\ 11365gMgmAwCIIgCIJBEAQPguBKEASDwWDwYDD4/tGx75zf+Q4gAuhCPFVzM0CgvUXFmr0plIpkB2KwW4bppr16aMgRzge16wbwTbxW0L6Y0IxsjiFyZyQvAISoD\ 11366PFMYgWlnTUI/M4bsllO+I5M0GuoWm+LP6kImrtktjhu8sxjaJ9V6zwNDy0FijoRcloRzGvghbDTAiO+Z8/Hv9JoKRbRr79JjwXqpOfBGxRasEejCH2kHyhr\ 11367uCHk2jXJ5xkgGFdjPgp/4IZ4HDTk4LTjXrAED56dzkIskRGG8Gwh9FdqTh8bkMgp0+JG9tb+xXpLf58ugHG/GoPG6ZmnSGh+Bn1OyCkX23dUAjon753DhyT\ 11368JuhiCaxcy8acf79DuuwbQNo/NItIqXXWF491E8R0ECNOppKlesjlaK8wsIqpKwL3QJwnhCygGtbCWbgbvJ0W4GFMOSrgnpIQ9rZHDYMyVS261dE1U1B/hkU\ 11369InqiU/44MDQ/m4BMtHV9Wq5bgqjtJ6laFWKUDtOwsRFvaMLvSAZbHj+u9o/u0itAN5xHX85KSu4GblHN0BJgEHfPGtksZjK4JkzFY1AvkIMTEJBX7tO4HCF\ 113706Hov85VvUXaEWosOIqirYUDkWW/OH7FGP18B9h0jjs49tyukEYSKYiZTjCmPnkxI7neAWkOOTxrs4A3blzFEhvJsgMXqmsicxgRGMFil7o5wS3HuIZmAGcc\ 11371g8wvlM8UfPWXpfJN5JTPj+YlnxB6QD6tvGmdD9oUxoBrWc3mf8h5fjM=" 11372 11373_palette_flag : 11374 base642img \ 11375"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICMyNAp4nPv/n4Hh/wjGDCMeD4JIGEAMAH3RPtA=" 11376 11377_palette_cube : 11378 base642img \ 11379"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjMxIDEgMSAzICMzMzgKeJxj5BCQkFfXN7Nz8wuLS80trWnpmTJn8erNuw6dunTr0cuPP39/e/f83v\ 11380Xzxw/s2LBy4cyJnY1VRVnJ0cHezjYmOqqyoryszFxCUoqahhaOHgER8en55XVtfdPmLV27dc+RM1fuPH79+ffvL2+e3Ll69ui+beuWz5ve395QUZCRGBHo6\ 11381WhlpKUsLczNwsIjIqOsbWzt7BUUlZhZWNnYMWHGguXrt+87fu7avadvv/759enVo1uXTx/es2XNkjlTe1vryvLS4sL83e0tDDQUJQQ5Wdj4xGRVdU1tXX1C\ 11382YpKzi6ubuybNWrhy486DJy/cePD8/fd/DIQAE6eghKKGgYW9u39YXFpeWV1r79Q5S9Zs2XP49OVbj159+vWf9oCQN5kI+oIOgIVbWFpZy8jK0TMwIjGjoKK\ 11383hvX/6vOXrtu07evbqnSdvvvymQ0ABAC/raR8=" r. 256,1,1,3,3 round. 11384 11385_palette_rainbow : 11386 base642img \ 11387"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjI1IDEgMSAzICM1NjcKeJxj5ublE+DnF5KQUVBWU9fS0tHV0dXVAVL6RiZm5haWFpaWVpZWVtbW1i\ 11388BsbWMDJq3BwMrK0sLMWF9LRYqLkYGRAQygFAYbG2DkVrH2iUjNq2zpnTp3+eadB09fvvXo+dvPP/7+//v375/fv37++PH9+7dvX799/fr1GwQAWV+/ACEUA\ 11389Bmf3796+uDW1XMnD+3dum75wpkTOhvK81Ii/Z3NDbSUxNhZuPkEhISFhMWl5RRV1LV09AyMjE1MLWwcnJxd3T29vH18/fz9AwIDg4JDQCA0DAjCI0BkRGRk\ 11390dExsQnJaZm5ReW1T54Tp85au3rBp8+ZNmzZt3Lhxw4YN69euXbd2zWpMABTfsHHTpq3bd+7ae+Dg4eMnTp+9cPnC2RNHDuzatnH10gWzJvW01JUXZCbHhvt\ 113915OttbW5gYGepDgJ6enq6OjpaWpoa6mqqKorysnJy8goKCopKSopKigrycrLSkuIggHy+/kJCQAB8PFzOHiIyKnqm9R0BYbHJmXmlVY2tn38SpM2bPmTd/wc\ 11392JFi5csWbZ82dJly5avWLFiJRCsAoPVYGL1GqBDN27eugPoyqMnz1+/++gxMCRPH9mzdd3KhbOn9rU3VBZmxEcEByGD4BAwPzgoMDAgwM/P19vT093d1dnJ3\ 11393trK3NhIX0dDTVUJ5GCgi5VVVIFpSkdXT9/A0AAGQH7U1dXW1gJ5UA2E1NTUNdQ1NDTU1dXUVJQU5WQkxYT4efkFhIQE+Xm5mAHNkQH/" 11394 r. 256,1,1,3,3 round. 11395 11396# The color palettes below have been converted from 11397# 'https://stackoverflow.com/questions/33273340/matlab-set-color-map-color-range'. 11398_palette_parula : 11399 base642img \ 11400"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNjQgMSAxIDMgIzIwMwp4nAHAAD//NTY2NDAoHAwDAwUJDhETFBQSEAwJBwYGBggLEBYdJS44Qk1ZZX\ 11401F7hpGbpK22v8fP2N/n7/b8//79+/j29fX2+C0zOT9FTVZeZGlucnZ6foKGio+UmZ2hpKeprK6xs7W3ubu8vb6/v7+/v76+vby8u7q5ubm7vsLHzNLX3OLp8\ 11402PiMmKWyvsvX3uHh4N7c2tjW1NPS0tHPzcrGwr65tK+ppJ6Yko2HgXx4dHBsaGVhXlpXU09LRj85NDAsKCMfGhUQJK9mpg==" r. 256,1,1,3,3 round. 11403 11404_palette_jet : 11405 base642img \ 11406"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNzYgMSAxIDMgIzEzMQp4nGNgwA24JFSN7H2i0ksa+2av3Hb4wr3XP/9jgt/vH145tnPN/ImtMH1MvN\ 11407Iapk7+sVnlLRPnrdl57PLDd7+xaPz55t7Fw9tWzulrKkmP8rU3UpXgYoTbPWXh+j0nrz35+BeLxm8vb587sHnZzO76wpRwLxt9JVF2PL5gYAAAc+1twA==" 11408 r. 256,1,1,3,3 round. 11409 11410_palette_hot : 11411 base642img \ 11412"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTI0IDEgMSAzICMxNDEKeJzjFRKXVdLQNTK3dXb3DY6IS87IK66oa+nsmzJz3pKV67fu2n/k1IWrt+\ 114134/ff3+66//1AUMpABGdl5BcRlFdZBTndx9g0BOzS2urGvuADl18cr1W3buP3LyPMipr4BO/UdNu0kEjFxC0kpaRtbO3kHRydnFNS3dk2cvXr1lz5EzV+88e\ 11414fP1LwA796yq" r. 256,1,1,3,3 round. 11415 11416_palette_cool : 11417 base642img \ 11418"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMzIgMSAxIDMgIzc4CnicY+ERkVHRMbFx8QmJSckpqWnpmTJnyZote46cuXLnyZsvf/58efPkzpUzR/\ 11419ZsWbNkzpSelpqSnJSYEB8XGxMdFRkRHpb/BAAAHuY/4Q==" r. 256,1,1,3,3 round. 11420 11421_palette_spring : 11422 base642img \ 11423"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjggMSAxIDMgIzcxCnic+/8fN2DhFVPQNLJ28Q1LyCyqbumdtmDlpt1Hzl578PLT79+fXj64dvbI7k\ 114240rF0zrbakuykwI83WxNtJUEONlAQDKiDfN" r. 256,1,1,3,3 round. 11425 11426_palette_summer : 11427 base642img \ 11428"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjggMSAxIDMgIzcxCnicY+EVU9A0snbxDUvILKpu6Z22YOWm3UfOXnvw8tPvprbuCVNmzl20bPX6LT\ 11429v2Hjx26vyVm3cfPXv94cvPv2l4AACR+i4M" r. 256,1,1,3,3 round. 11430 11431_palette_autumn : 11432 base642img \ 11433"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjYgMSAxIDMgIzQyCnic+/8fF2Dhk1DSMXPwDI5NL6xu6ZuxaM22Aycv333+8TcDTgAAaHcm2w==" 11434 r. 256,1,1,3,3 round. 11435 11436_palette_winter : 11437 base642img \ 11438"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMzEgMSAxIDMgIzc5CnicY2DAC1h4RGRUdU1t3fzC4tLzyxs6JsxYuHLjzkOnLt16/Prz778/v358+/\ 11439Lpwzs3rlw4ffzw/t3bN69bvXzxvFnTJvV1tTUBACEGJp4=" r. 256,1,1,3,3 round. 11440 11441_palette_bone : 11442 base642img \ 11443"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KOTkgMSAxIDMgIzI1Mgp4nGNkZuXg4uETFBaVkJKRU1BWVdfU0TMwNjG3tLZzcHJx9/T28w8KCY+Mjk\ 11444tISk3PzM4rKCwpq6iqbWhqaevs7p0wccq0GbPnzl+4ZNnKtRu3bN+9/9Cxk2cuXLl+696jpy/ffPj8/dc/RmKsCI2IiU9KzcjJLyqtqK5rbGnv6ps4Zfqsu\ 11445QsWAw3esHnbzr37Dx09cfrM+YtXrt24fef+w8fPnr968+7j56/ff/35x8TKwcMvJCopLa+koq6lZ2hibmXnCDTZNyA4PDI2ITktE2hwSVlldV1DU2t7Z3cf\ 114462N2zwO5esXrtho1btu3YvXf/wSPHcFoBAJTokrQ=" r. 256,1,1,3,3 round. 11447 11448_palette_copper : 11449 base642img \ 11450"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTE1IDEgMSAzICMzMzkKeJxj4+TmExQWk5SWU1RW09TRNzKxsLK1d3b18PINCA6NiI5LSE7LyM4rKC\ 114516rqK5rbGnv7O2fNGX6rLnzFy1dvmrthk1bd+zee+DQ0ROnz164fO3mnXsPnzx7+eb9xy/ff/359x87YGFl5+Dm5RMQFBYVk5CSlpVXVFZRU9fU1tEzMDIxN\ 11452be0trG1d3R2dfP08vH1DwwKCY2Iio6NT0hKTk3PyMrJKygsLi2rqKyurW9sam1r7+zu7eufOGXa9Jmz5sybv3DxkmUrVq1Zu37Dpi1bt+/avXffgUOHjx5j\ 11453YgZZysnFzcPLxy8oJCwiIiYuISklLSMrp6CopKyiqqauoakFdIG+gaGRsYmpmbmFpZWNrZ29g6OTs4ubu4ent4+vn39AYFBwaFh4RGRUdExsXHxCYnJKalp\ 114546RmZWdm5uXn5BUXFJaVl5RWVVTW1dPQCk5ZAs" r. 256,1,1,3,3 round. 11455 11456_palette_pink : 11457 base642img \ 11458"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTIxIDEgMSAzICMzMDUKeJxT1DG1cfbwC46ISUzNzC0sraiub2rr7O6bOGX6zDnzFy5ZtnL1ug2bt2\ 114597fuXvvgUOHDx85euz4iZOnTp85e+7c+QsXL12+cuXqtes3bt66ffvO3Xv37j94+PDR4ydPnj57/uLFy1evX799++79hw8fP33+8uXr12/ff/z49ev37z9//\ 11460/37zyoso6SurW9sZmVr7+Tq7uXjHxQSFh4ZHRuflJyanpGVnZtfWFRSWl5RWV1b39Ta0d0PddLiZSvXIJx05NiJU2fOXbh89fqNW3fu3X/0BGgzFS1uaGxq\ 11461aW1r7+zu6e2bMHHS5CnTps+YOWv2nHnzFy5avGTpsuUrVq5avWbtuvUbNm4COmn3vgOHj504fRbonhu3795/+OTZi1dv33/68u3Hrz//AH2168E=" 11462 r. 256,1,1,3,3 round. 11463 11464_palette_vga : 11465 base642img \ 11466"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICMxNzgKeJz7/+fn10/vXz9/8uDOjasXzpw4sv/IiTMXrt648+DJ89fvP339+ec/Bv\ 11467jx8dXj25dOHdi2ZsGU1tIEVwbCwDWhtHXKgjXbDpy6dPvxq48/MM2Q0zF3cPcLiYpPycgtLK2saSAMaipLC3MzUuKjQvzcHcx15IhwB4Yt/zH8v2vr+pWL5\ 1146807r72goz00KdTPEdDthQEYIYbgMw3c0CSEi/E9G7JIRQoT9T0YYEgYAJsphWQ==" 11469 11470# The color palettes below have been converted from 'https://matplotlib.org/cmocean/'. 11471_palette_algae : 11472 base642img \ 11473"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNTAgMSAxIDMgIzE2MQp4nAGWAGn/1M3Hwbq0raegmZKLhH11bWVcU0k+MygeFg8JBwYICg0PEhQVFx\ 11474gZGRkZGRkYFxYVExL38u7p5ODc19PPy8fEwLy4tbGtqqainpqWko2JhH96dnFtaGRfW1ZRTUlEQDw3My4qJczFvbavqKGak42GgHp0bmhjX1pXVFJRUFBPT\ 11475k1MS0lIRkRCPz07ODUyLywpJiMgHBkV1p88Lw==" r. 256,1,1,3,3 round. 11476 11477_palette_amp : 11478 base642img \ 11479"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNjEgMSAxIDMgIzE5NAp4nAG3AEj/8O3r6ejm5OLh397c29nY1tXU0tHPzszLycjGxMPBv728uri1s7\ 11480CtqqainpqVkIuFgHp0b2lkXlhTTkhDPurm4dzX0s3Iw765tLCrpqGcmJOOiYSAe3ZxbGdiXVhTTklDPTgyLSgjHhkWEhAODg0ODg4ODg4NDQwLCgnq5N7Y0\ 11481szGwLq0rqihnJWPiYN9eHJsZmBbVU9KRUA7NjIuKygmJCQkJCUmJicoKSkpKCcmJSMhHxwaGBUS64BWpQ==" r. 256,1,1,3,3 round. 11482 11483_palette_balance : 11484 base642img \ 11485"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTIxIDEgMSAzICMzNzQKeJwBawGU/hgaHB4gIiMlJigoKSkoJyQgGhMNCgoMERYcIictMzg+Q0lOVV\ 11486thaG51fIKJkJado6mwtrzDyc7V2+Dm7PDu7Oro5+Xj4t/e3dva2NfW1NLR0M7Ny8rIxsXDwcC+vLq4tbOwraqno56alZCLhYB6dG9pY15YU01IQj0dICImK\ 11487CsuMDM2OTs/QUVJTFFVW19kaGxxdHh8gISHi46SlZmcoKOmqqyvs7a5vL/CxcnMz9PW2t3h5ens6OPe2dTPysXAu7axraijnpmVkIuGgXx3cm1pY15ZVE9K\ 11488RD45My4oIx8aFhMQDw4NDg4ODg4ODQ0MCwoJREpRWF5lbHN7goqSmqGpsLa7vb69vby8u7u6urm5ubm5ubq6uru8vL2+v8HDxcbIys3P0dXX2t3f4ubp6+f\ 11489h2tXPyMK9trCqpJ6YkYuGf3l0bWhiXFZQS0ZBPDczLisoJiQkJCQlJSYnKCkpKSgnJiQiIR4cGhcVEqaTs4c=" r. 256,1,1,3,3 round. 11490 11491_palette_curl : 11492 base642img \ 11493"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTI0IDEgMSAzICMzODEKeJwTFROXkJCUkpKWlpaRARJSkuJiosJCggKCwmLSCup6Znbu/uHx6fnldW\ 1149429U2YtXLF+6+6DJ85duXn/6euP3/78+fn96+eP79++efXy+bOnjx89uH/3zu2b169duXT+7KkTRw/u271984Y1K5YsmDN9Ul9nS31VaUF2anxUqL+Xi72Vq\ 11495ZySmpaekZmVraOrp29gSERMQnJGTkFxeXV9U3tX38SpM2bPW7h0xaq1GzZv27F738Ejx0+dvXDl+q27D5+8ePPhy+d3r57cv3X1wumjB/ds37hm+UKgHb0d\ 11496TbUVxXmZKQnR4UF+Xq6OtlZmxvraGqpKCrJgn4kIg/wmwMfr4ubh7esfFBIWGR2bkJSSnpWTV1BUXFpeUVVdU1tXV9/Q2NTc2tbR1Tth8rRZcxcuXbVu846\ 114979h0+cvQz2+cfXT+5eO3/i4O4ta5cvnD21v6u1obq8uCA3KyMtJTkpMSEhIT4+PgEG4uPjYqMjw0OD/L09nO2tzACwu7nF" r. 256,1,1,3,3 round. 11498 11499_palette_deep : 11500 base642img \ 11501"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNDkgMSAxIDMgIzE1OAp4nAGTAGz/+e7j2M7Dt6yhlYqAdm5mYVxYVVJPTUtKSEZEQ0FAPz49PT0+P0\ 11502BBQT8+Ozk2MzAsKfv38/Ds6OXh3dnV0czIw764s66po56Yk46Ig396dG9qZF5ZU05IQz46NjIvKycjHxvJw724s6+rqKWko6Kjo6Ojo6OjoqKhoJ+dnJuam\ 11503ZeWlZSTkY+Mh4B4b2ZeVU1FPTYvM2JJnA==" r. 256,1,1,3,3 round. 11504 11505_palette_delta : 11506 base642img \ 11507"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM3NzAKeJwTEBIWEROXkJSWkZWTV1BUUlZRVVUDAlVlJUV5OVlZGWlpKRCQlp\ 11508aWASmBqFFT19DU0tHVNzA0NjWzsLKxc3Bycff08Q8Ki4xNSMnIKSipqGlo6ejpnzx91rxFS1euWb952869Bw4fP3X2wuVrN+8+ePzs5Zv3n7/9/Pvv7+9fP\ 1150979/+/r508f37968fvXi2dPHjx7cu3PrxrUrl86fPX3i6OEDe3dt37Jx3arlSxbMnTVtcn9PR2tjXVV5cUFORmpibFRYkL+3u4uDraWZkb62hqqSvIykuIiQ\ 11510AB8vDzcXFzc3Dw8vH7+AINCbIqJiYuLiEhISkmAAZIiLi8srKCmrqqlramnr6ukbGBmbmJpbWFqDPeTm4e3rHxgcFhEVE5eQlJKWkZWTV1BUUlZRWV1b39j\ 11511c2t7Z3ds3YdKUaTNmzZk7f+HipctXrFqzdv3GTVu2bt+xc/eeffsPHjpy9NiJk6fPnLtw8fKVa9dv3r5z78Gjx0+fv3z99t2HT1++/fj15+f3L58+vH398t\ 11512mTR/fv3r55/eqlC+fOnDp5/Ojhgwf27dm9c8e2rZs3bVy/bu2aVStXLF+2ZPGihQvmzZ0ze+aM6dOmTp40sb+vt7urs72tpbmxoa62uqqirLS4sCAvJyszP\ 11513TU5MT4uJioiLCQowM/H29Pd1dnR3tba0tzUxMhAT0dLQ01F2d7JFRJvMQnJ6dl5RWVVtY2tnb0TgL6aOWv27Dlz5gLBvHnz5s+fv2DBgoULFy5atHjxkiVL\ 11514ly5dtmz58hUrVq5ctWr16jVr1q5dt27d+vUbNmzYuHHT5s1btm4DhsEuUCAcOHj4yNHjJ04BQ+H8xUtXrl6/cQsYDPcfPHz0+MnTp6ePH96/e9umdSuXLpw\ 11515zY0p/d3tTXVVpYW5GSkJ0eDAwYp3trS1MDHS11JUVZKUlRIUF+Hi4ONjZWIGAjZ2Dk5uHj18QlIIlpYCpE5J+gYkTmDq1tLV14EBbW1tLS1NDQ11NVQWYsB\ 11516Xk5WSkpSTERUWEAGwPYP8=" 11517 11518_palette_dense : 11519 base642img \ 11520"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNzQgMSAxIDMgIzIyNAp4nHt878alM8cO7N66YfXSBbOnT+rram9uqKmqKCstKQaBktLSsvLyioqKys\ 11521pKIFleDpIoLMjLyc5MS0mKj4kMC/L38XBxsDF//+bV8ycP792+ce3ShTMnjx3ev3fXts3r16xYsmDOjCkTejpaGmoqivOz05Pjo8NDAnw8XB3trMyNDfW0N\ 11522FSVFGSlJcXFRISFhQQF+Pnev3398sWzp0+ePH4EA48fP34CBo8fP3p4/+7tm9euXDh78tihfbu2bly7YvG8mVP6u1rqK0vyMpJjwwN93BxtzI30NFUBgy55\ 11523hg==" r. 256,1,1,3,3 round. 11524 11525_palette_diff : 11526 base642img \ 11527"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTQzIDEgMSAzICM0NDAKeJwBrQFS/gcJCw0ODxESFBYWGBseIiYqLjI2Oj5CRUlNUVRYXF9jZmtvcn\ 11528Z5fYCEiYyQk5ebn6Onq66yt7q/wsfLz9PX3N/k5+vu8fP19fX08e/s6ebi39zZ1dLOy8jEwr67uLWyr6yppqOgnZqYlZKPjIqHhIF+fHl2c3Bua2hkYF1ZV\ 11529lJPS0hFQT47NzQwLSomIyAdIyYpLC8zNTk7P0JFSEtNUFNVWFteYGNmaGtucHN2eXx+gYSHioyPkpWYm56hpKeqrbC0trq+wMTHy8/R1djc3+Pm6ezu8PHx\ 115308O/s6ufj4NzZ1dLOy8fDwLy5trKvq6mlop+bmJWSj4yJhoOAfXp3dHFubGhmY2BeW1hWU1FOTEpHRUI/PTs4NTIwLSooJSJAQ0dKTlFUWFteYWRmaGpsbnB\ 11531yc3V4enx9gIKEhoiKjY+Rk5aYmpyfoaSnqauusLO2uLu+wcTGyszP0tXY29/i5efq7O7v8PDv7Onm4t3Z1dDLxsK9ubSvq6einZqVkY2IhIB8d3Nva2djX1\ 11532tXU09LR0RAOzg0MS0qJyQiISAeHRsbGRgWFRQSEA4ODAoIBjEs26k=" r. 256,1,1,3,3 round. 11533 11534_palette_gray : 11535 256,1,1,1,x r. 100%,1,1,3 11536 11537_palette_haline : 11538 base642img \ 11539"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNDYgMSAxIDMgIzE0OQp4nAGKAHX/KiwuLSgiGxQPDAwPEhcbICUpLTA0Nzo8QEJGSU5TWF9mb3mEkJ\ 115406sucXR2+bw+RgaHB8mMDlBSE9VW19laW5zeHyBhouQlZqfpKmus7i9wsbLztLV2Nrd4OPm6e1xfoyZoaKfnJiVkpCOjIuKiYmIiIiHh4aFhIOBfnt4dHBrZ\ 115412JeW1xgZW12gIqU7TdADQ==" r. 256,1,1,3,3 round. 11542 11543_palette_ice : 11544 base642img \ 11545"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTA5IDEgMSAzICMzMzgKeJwBRwG4/gQGBwoMDhETFRgaHB4gIiQmKCorLS8wMjQ1Nzg5Ojs8PD0+Pj\ 115464+Pj4+Pj4+Pj4+Pj4+Pz9AQUJDREVGSEpLTE9QUlRWWFpcXmFjZWhqbXBzdnl8f4OGio6Slpqfo6essLS5vsLGy8/T2Nzg5OkGCAkMDhASFBYYGRwdHyEjJ\ 11547CYoKSwtLzEzNDc4Ojw+QEJER0lLTlBSVVhaXWBiZWdqbW9ydXd6fX+ChIaJjI6Rk5WYmp2goqSnqayvsbS2uLu9v8LEx8rLzdDS1NfZ293f4eTm6evt8PL0\ 115489/n7ExYaHSAkJyouMTU5PEBDR0pOUlZZXWFlaW1xdHh8gISIjI+Tlpmcn6KkpqiqrK6vsLKztLW2t7i5urq7vL2+v8DAwcLDxMXGx8jJysvMzc3P0NDS09P\ 11549V1tfY2dvc3t/h4+Xn6evt7/L09fj6/ETzn2w=" r. 256,1,1,3,3 round. 11550 11551_palette_matter : 11552 base642img \ 11553"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNjQgMSAxIDMgIzIwMwp4nAHAAD///fz8+/v6+vn4+Pf29fTz8vHw7+3s6ujn5eLg3drX1NDNycXAvL\ 11554ezrqmkn5qVkIqFgHt1cGplYFpVUEpFQDs2Mevl4NrUz8nEvrmzrqijnZiSjYiCfXdybGdiXVhTTkpGQj46NzMwLSsoJiQiIB8dHBsaGhkYGBcXFhYVFBMSE\ 11555Q+uqKOemJOPioWBfHh0cGxpZWJfXFpYVlRTUlJSU1NUVVdYWVtcXV5fYGFiYmNjY2NiYWBfXVxaV1VST0xJRkM/PV5d6A==" r. 256,1,1,3,3 round. 11556 11557_palette_oxy : 11558 base642img \ 11559"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2NTYKeJyzd3RydnP39PL18w8MDg2LiIqJjUtMSknNyMzOyS8oKi4rr6iqqa\ 11560tvaG5pbevo7Oru6e0LDAgMDA4JCQ0Pj4iMigaqj09ISEpOTklLS8/IzMrOyc3LLygsKi4uLSsvr6yqrq6tq2tobGoCGgAzoX/CxEmTp0ydNn3mzFmz586bP\ 115613/hosVLli5bvmLV6jVr163fsHHzlq3btu/YuXvP3n0HDh46dOToseMnT50+c+78hYuXr1y9duPmrdt3791/8Ojxk6fPX7x89ebt+w+fPn/5/u3L54/v3719\ 11562/frVq1cvIeAFEDx//vzZs2dPnz558uTx40ePHj18+ODB/fv37t29e+cOKxCwQQE7DED5rGDAwgJSws7Bxc3HLygkKibh6x8QGBQcEhoWHhERFR0dEwcMgMS\ 11563k5JTUtPT0zKys7Ny8vPxCYACUAgOgAhgANbV1DcAAaAGFIDAAenp7+4D+nwTy/wyg/+cAAwDo/8Vg/wMDAOT/TZu3QP2/dz8wAAj7/937T5+//vv75/fPH6\ 11564BQ+PTh3ZvXL58/ffLowb27d25ev3b10sXz586cOnni6JFDB/fv3bN7x/ZtWzdt3LAO4n92dg4OTk4uLi5ubh4eHl4g4AMCfhAAMYB8Hm5uLk5OTg4OdnZvs\ 11565P+DQ8LC4AkgPjEpKTk1FSUBFJWUlpVVVFZW1dTW1jc0NgJTUGt7R2cnSgIABsCcuXPnLYAmgJXAAAAlgE2bNoMSwK7de/bsAwbAYWAAnAAGwNlz585fvHT5\ 11566yrXrN27evnP3HigAngED4DUwAD58fJSRlpIYExUe4uft4epgZ2NlYWZqYmRooK+ro6OtqamhrqaqqqKspKSoIC8vJysrIyMlJSkJADQjlG8=" 11567 11568_palette_phase : 11569 base642img \ 11570"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTA2IDEgMSAzICMzMjkKeJwBPgHB/qissLO2uby/wsTHyczO0dPU1tjZ29zd3d7e3t7d3NvZ19XSz8\ 11571zJxcG9ubWxrKeinpiTjYeBe3VuaGFbVE1HQTs1MCsnIyEeHBkXFRMRDw0MCwsOEhgeJS01PkdQWWJqcXh/hIqPlJidoqZ2dHJwbmtoZWNhXVtYVVJPTElFQ\ 11572j47NzQwLSsoJiUlJicpLC8zNjo/Q0dLT1NXW19iZmltcHN2eXx+gYOGiIqLjY6PkJGSk5OUlZWWlpeXmJiZmZmampmZmZiXlpSSkI6MioiGhIF/fXp4DhIX\ 11573Gx4iJiouMjY6PkNHTFFXXGJobnV8g4qSmaGor7e+xMvQ1tvf4+fq7O/w8vPz9PPz8vHv7ero5eHd2dTPysbBu7axrKejnpqVkIyHgnx3cWtlXlhRSUI5Mio\ 11574jHRcTEA8ODQ0NDQ0NDPDwmdk=" r. 256,1,1,3,3 round. 11575 11576_palette_rain : 11577 base642img \ 11578"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTE1IDEgMSAzICMzNDIKeJx7++bVy2dPHz96eP/e3Tu3b928cf3q5Yvnz5w8dmjf7u2b169evmTBnB\ 11579lTJvZ2tjbWVpYU5makxEeHBfq4O9taGOtpqirIiIsI8nJxsLGyMDMzs7CwcXBy8woIiYhJSEnLyikoKCopq6ioqIIAkFZRVlZSUnzz6vnTRw/u3bl57cqlC\ 115802dPnzh25NCBfXt37dyxfduWzZs2rl+3ds2qlSuWL12yeOGC+fPmzJ41Y/q0qZMnTZzQ19Pd1dHW0txYX1tdWVFaXJifm52ZnpqcGB8bFREWEhTg5+Pl7urs\ 11581aG9rbWluYmSgr6OloaaiKC8r/fHdq+ePH9y9efXimZNHDgA9tm7V0oVzZ06bPLG/p6sTZGZTQ31dbU1VZUV5aWlJcVFhQX5+Xl4uDORBAYidk5OTnZWVmZm\ 11582enpaanJSYEBcTHRkRGgy23RNovZMD0H4rSwDxo6Ac" r. 256,1,1,3,3 round. 11583 11584_palette_solar : 11585 base642img \ 11586"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMzUgMSAxIDMgIzExNgp4nAFpAJb/N0BJUltkbXZ/h46VnKGnrLG1ur7BxcjMztHU1tja3N3f3+AVGB\ 11587odHyIlJysvNDpARk5VXGRrc3uDi5OcpK22v8jR2+Xu+RkcHyEjJCQkIiAeHBoYFhQTExITFBUXGh0gJCgsMDU6PkNIm9UqlA==" 11588 r. 256,1,1,3,3 round. 11589 11590_palette_speed : 11591 base642img \ 11592"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNDkgMSAxIDMgIzE1OAp4nAGTAGz//fn28+/r5+Pf2tXOyMG5samgl46FfHJpYFZNQzoxKCAZEg4LCg\ 11593wOEBMVFxgZGRkYF/rz7efh29bQy8bCvbm1sq6rqKWinpuYlZKOi4eDf3t3c25pZWBbVlFMSEI9ODMvKSTIvbKnnJCFeW5jWE1COS8nHxgRDAcFBQgLDxQYG\ 11594x8iJScpKywsLCwrKiknJCIfGxgUF7w7kA==" r. 256,1,1,3,3 round. 11595 11596_palette_tarn : 11597 base642img \ 11598"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTA1IDEgMSAzICMzMjYKeJwBOwHE/hcaHiEjJyktMDU8Q0lQV11kanF4f4aNk5uiqbG4v8XKzc/S1N\ 11599bY2t3f4uPm6evu8PT2+vv8+/j08Ovn4tzWzsa+t6+ooJmSioR9dm5nX1dPRz84MSolIh8eHRwaGRcUExAOCwoICQsODyQoLTE1OT5CRklMT1JVWFpdYGNlZ\ 116002psb3F0dnl7fYCEiY6Ump+lq7C2vMHHzdLY3uTq7/T39vPu6eTf2tXRzcrGwr66trOvq6ekoJyZlpKOi4eDf3t3cm5qZGFcV1NOSkVBPTgzLikkIA0ODw8Q\ 11601Dw8ODQwNEBETFhgbHR8hIyUnKisuMTQ3O0FIUlpia3N8hI2Vnqavt8DJ0dri6/H18uzj29HJwLewq6ikop+dm5mXlJKPjYuJh4WEgoF/fnx7enh2c3JvbWt\ 11602paGZkYmFfXVpVUfhNmgM=" r. 256,1,1,3,3 round. 11603 11604_palette_tempo : 11605 base642img \ 11606"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTEyIDEgMSAzICMzNDcKeJwBUAGv/v369/Tx7uvn5OHe29fU0c3Kx8PAvLm1sq+rp6OgnJiVkI2JhY\ 11607B9eHRwa2hjX1pVUUxIQz86NTEtKSUhHhsYFhMSEREQEBEREhMUFBUWFxcYGRkaGhsbGxscHBwcHBsbGxsbGhoaGRkZGBgXFxYWFRX08vDu7Oro5eTi4N7c2\ 11608tjW1dPRz87MysnHxcPCwL+9u7q4t7W0srGvrqyqqaempKKhn52cmpiWlZKQj42KiYeEgoB+fHp4dXNxb21raWZkYmBeXFpXVVNRT01LSEZFQ0A+PDo4NjQx\ 11609Ly4rKSclIiAe8+/s6eXi3tvY1dLOy8jFwr+9ure0sa+sqqelo6CenJqYlpSSkY+OjIuKiIeGhYSDg4KBgYGAgH9/fn5+fXx8e3t6eXh4d3Z1dHNycXBvbm1\ 11610samloZmVkY2FgX11cW1pYV1ZUU1JQT05MS0pIR0ZFRA7PoM4=" r. 256,1,1,3,3 round. 11611 11612_palette_thermal : 11613 base642img \ 11614"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTA3IDEgMSAzICMzMjUKeJxjYWFhZWVj5+Ti4RcUkZBRUNUyMLWyd/HwCQiJiI5PSsvMyS8qq6ypb2\ 11615rr7J0wefqseQuXrlizYfP2XfsOHj155vzla7fuPnj07MXrt+8/fv7y7fuPn79+/YaAX79+/vzx/dvXL58/fXz/7s2rF8qq6hpa2jp6+gaGRkbGYACkTMzML\ 11616aysbe0dnJxd3T28vH39/AODgkNCwyMio6JjY+MTEpOSU1LTMjKzcnLzC4pKyiqraxua2zp7JkyeNmveoqUr127cumPPgSMnzly4cuPOgycv3nz8+tPE0tbJ\ 116173ScwPCYpI6+0urGjb8qM2fPmz58/b+6c2bNmzpg2dcrkSRMn9Pf39fb2dHd1drS3tbY0NzXU11RXlpcWFeRlZ6QmJcREhgUH+nl7uLk6Odrb2dqAgK2tHdS\ 11618lQIcGBoeGRwIArFub1Q==" r. 256,1,1,3,3 round. 11619 11620_palette_topo : 11621 base642img \ 11622"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2OTEKeJxT19TS1tXTNzQyNjE1s7C0sraxtbWzt3dwcAQBBwcHe3s7OztbCA\ 11623Cy7MFyTk7Ozi6urm7u7h6enl7e3j6+fn7+AYFBwSGhYRGR0TFxCUkp6Zk5+UVllbWNrZ29E6fOmrd4+eoNW3bsPXj05LlL127de/Ts9fvP33/z8vELCAoJC\ 116244uIiolLSEpKScvIysopKCqpqGvpGhibWVrbOTq7eXr7BQaHRUbHJSSnZWTnFRSXVVTXNTS3dXT3TZg8bebseQuXLF+5Zv2mrTt27zt46PDRY8dPnDx1+szZ\ 11625c+cvXLp85eq16zdu3rp95979Bw8fPX767PmLV6/fvHv/8dPnr99/SEmDrFNWUVMHB4SBobGJmbmllY2tvaOzq5uHt69/YHBoRBTYR2mZ2bn5hcWl5ZXVtfW\ 11626NTS1tHV09fRMmTZk2Y9ac+QsXL12+cvXa9Rs3b92+c/fe/QcPHz1+8tSZcxcuXr567cZNkPVg21+8fP3m7fsPQMu//fj5+4+qmoaWDjD8jYGhD7HVxc3DC2\ 11627htQCAwMMMjIqNiYuPiE5OSU1LTMzKzcnLz8guLikvKyisqq2tq6xoam5pb29o7urp7+vonTJw0ZSrIMfMWLFoCdcy2Hbv27AO5BeSUy1ev37pz78Hjp89fv\ 11628Xn/8fO3H7/+6ugZmphb2tg7uXp4+wWFRkTHJ6UCI664rLKmvqm1vbO7F2zupMmTp0yZOnXatGnTp8+YMXPmzFmzZs+eM2fu3Lnz5s2fv2DBgoULFwHBYgwA\ 11629FVyyZOmy5StWrlq9dt0GRAgdO3EKGPHAmAdHvZS0tLQMMPqBCQAM5MHxoqEJS59m5uagBGptYwNLiSjADgIcXDx8/IPDomITUzKywQmwoaW9u2/S1JlzFix\ 11630evmrdxq079xw4fPzUuUtXb9558AQAVgJv5Q==" 11631 11632_palette_turbid : 11633 base642img \ 11634"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMTI2IDEgMSAzICMzNzAKeJx78fzpk8ePHj64f+/undu3bt64fu3qlcuXLl28cP7c2TOnT506cfzY0S\ 11635OHDx08sH/f3j27d+7Yvm3L5k0b1q9ds2rl8mVLFi2YN2fWzOlTJ0/s7+3p6mhraWqoq6mqKC0uzM/NzkxPTU6Ii4kMDw0O9Pf19nR3dXa0t7W2NDc1NtTX1\ 11636dZUV1X+8unD29cvnz15dP/u7RvXrlw6f/b0yWNHDh3Yu3vn9q2bNqxbvXI5xI4Z06ZMmtAHsaKxvra6sqKsBGRJTlZmelpKcmJCXGxMVGREWGhIcGCAv5+P\ 11637t5enh7uri5Ojg72djbWVpYW5qYmxkaG+nq6OlqaGuqqKsqKC/KrlSxbOmz1j6qT+3s72lsa6msryksL8nCyguxPjY6IiQkOCAvx8vb083N1cXZyBZgENs7O\ 116381tbWxsbEGASsYsIQACyAwNzc3MzMzNTUxMQbaZ2hgoK8HtFNHW0sTaK2aqoqKshLQZjlZGWkAeF+paA==" 11639 r. 256,1,1,3,3 round. 11640 11641# The color palettes below comes from the LoSpec palette list 'https://lospec.com/palette-list'. 11642_palette_aurora : 11643 base642img \ 11644"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2ODYKeJxt0kFo01AYB/B3qYwwaDbCaEG6aS4T3ME4qJrgVpCiLUqolEgYbI\ 11645QirIce9kQLknXbZSplWaGMSaeUYWU0g21QD0XbFLaasimMQqmUOiyBHiyOemgZZfpMql7Ew/v43vtOv+//QN/5yze89x89eZ58++HzMQJjQJnXizmktH4gh\ 11646JSQN6SgbqO/bgHgfnfwejYwG88d1hqtdivEwSVZ1U60PQnSDiitv1Er31R5Cd5zWkmapTnok9ZrKXmRNdtI2ifJalbekDiONg/Stzj4UJIPNVmCHOOckWS5\ 11647gbRaWS3suqnhcSFRKaEWaqNyJRWfvCuEN3fqCBViK9DPDA/1EhghuoHpbH//GTDC+CNesQc3DZgBBSzktGuZzwZdAoMDspedWlzLpMvlkzqqZDJh3uegvPE\ 11648CQp3TemY1Av7xG9iuXz/zOaMjxkLGo/KnilvJeHQhMB18FkumCzVAO7xQkovqS8iN/PVralYSWRvL+fRRTv10cqylxGl9rG/qe1FNG2Cr4Q/o/opmrIOkxj\ 11649kOblbVdFwS+eEBzGIhhjwML2QSsQDvplhhLrpTKn1FzWphIzDqnFgp11EznwpfWd07avxEjXr5aI2/aHf5PP7gi1fb+XSAdzBncfwcjlMOIZLYfQ89Qxdww\ 11650kIAzGoFrD9+zYaPEv/zG0xWzx8ddP3GJhS9GPnrAeSeLkcXpyZnHojh2FYR0Yzhr8iQowdJmvPqMaqy5OWuU2Y7zeoRL0jrnf380qSTdHb9Ta2qqhIc0b+G\ 11651lNzXvw4yrr/zr7W0YjYdj9hJWx/AcBdGCZcYMwZMBAZ4gPG4y+G0mkyEqafXhGGQJ9g71FzEv5H4iFCzdDThEddW2pnqrk7oNFG7VclEb24fFg1S5xShLyi\ 11652ffewTnPaFoJJPh4NXb9t/Aejmgpc=" 11653 11654_palette_hocuspocus : 11655 base642img \ 11656"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM2MzQKeJxjk3x5buu8lopLu5f0lsV5mHk7WxlpKkrINhWlhnla6iotmtpakR\ 11657Ht7b5oUlNRUpCT+anN87qK4jzteqtz4/wdjVRfXNy1pK880UdUiJ+Xi52VyUJTXpSPg1ns57Vt08sjLGTeHp5bFW2vovrr3qFVfWVRLk9Ob53TmhMW8OT0p\ 11658tlNOUF2DASAqIiwkKAAPx8vDzcXFycH+9PrZw5uW71g+uJpnQ1lWQkRMGW/Hp3aNKspK1wUAjR/3Tu2blpdWsDzFy9fv3n3/uOHG4fXz2orjGfklTN0DEwq\ 11659bZ26bOfJm6/+MIg83t2fZq1amRUb6GiqIQu0go2NlUVgamtpWpibuUZ+Upifq6WBfn1xerSfk5n29LaytDB3c8OOyowoL0sdhRktxUlBrqYWx3fPbczwMZD\ 11660ePK0ywdtcWevjkRnFweYy3Dc29GT7mcrIf9ndGW+rxM0Mda/AgcWdBVHuRqpk+n9qX3NFYWZ8eKCosCAfDxcHO5Dm5+XmZP9258jKSeUJEcBwnt9ZHOt5cP\ 11661Oymf1NpSncvHwCgkIiouj+F5adluOmIchflwfyhqbslb3LJlQm+bismNJSkOBjo1eQHO4P9L/pjiVTmvPj/ewXT2goiPGxNN+zfEp9TpiLcU9lZoyPvZGqi\ 11662CAo+pkZfz29sHvZxJriO1vA/uZ+cnhZZ7afoQjMP0yioiIiIsLCwkJCQoKCggLK3z69evbo3q1rl86dOnZo365tm9YuWzRv1rRJfV1tTXVVZc115cX52enJ\ 116638dHhwf7e7s6/P715/vDOtQtH9+3avnn9mhVPz+9cPLE61R/mf3h6gMY/AyMzCxs7hxyu+AcA2aYUlw==" 11664 11665_palette_srb2 : 11666 base642img \ 11667"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM0OTcKeJz7//398/vXzx/fv3398vnT+9vry/PT48P93e3N9dXlxfnZGcAS0/\ 11668ra6kpzU2NDfJz3b169eDZIXXZ8sLe9sfZ/GIAYdBrG/fz0xul9G5dMh8ufX9+f76/P///19cPrZ7cXw4Tf3z+/f/38/vr8eH97fXn+/5+f3z69f/NyqIWh5\ 11669QWZiVFB3s42prpqckD33Du+dmpNipcRAxT8/39///z6ePuXR+aWhzjqSV/dv2pqQ1Yo2Pkg+efH1vYUBxlKMKCB89vnt+eH26v/J+T/5QtmTOhsrCzKSooK\ 11670BjrDuLo4Pzs5PjzY390ZqEZb+fXj25eB2neDgmVyd3P9uzund66Y3gZ2vK+rrRmG/2/vnl0d7awNcbY8uru2L+6vzo72t9dTV5AU4mZl+P/hwYUDGxZMaCh\ 11671ICHAwUOD//+TE2knlUfZQb8vnQ/XB/P/x9eO7186f2D+3vzx+P1ABDv//h4c3If/3dzRUFILiwMvJ2lhbRdob6G9rc2N9bXVleWlxYf77l4/v3rx89uTm6u\ 11672Ls5Ohg/zs7p5eGmknCbXoP9TeMXxzurC8vzM5AwP8wvr+3m6ONuZGuhrKcpAg/F8uKKQ3ZES4Gsujx//nhud3Lm2NMYKENEgX5Hx78z89tndOSHeRvb64uz\ 116738/+Hxb/ADJVV38=" 11674 11675_palette_uzebox : 11676 base642img \ 11677"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM1Mwp4nGNQ8ciduO3Wf4aRSkOBChR4QEEuFEyEgm1QcAsK/kPBcNFPLgilEK\ 11678yiEPynEAAA16V90A==" 11679 11680_palette_amiga7800 : 11681 base642img \ 11682"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM1MzMKeJxjEFQydglNK++YuWr3mbvv/v////3Z1SObF01syI/ztdGWMnQKTiltm7\ 116835i56nbb/7+h4CfL64f27pkclNhgr+dfUBiUfOUpduO33j5Cyr9/93dM7tXzewoTwt1MZbVcwhMKm6Zumz7iZsvfwMlP9w/t3fN7K7KjHA3UxVhJgYGDkkta\ 116845/YvPoJCzcdvvIUTRIM2MQ1LL2ic2r75m84eGD9vN6a7ChPC3UxVqg0g4CikXNIaln7jJW7Tj+8sH/d3J7qrEgPczVRFqAkn7yBY1BySeu05TtO3nr95///\ 11685b0+vHN60cEJ9XqyPtZYkA5r/v399cvnQxgX9dbkx3laaEuwoll96/AVFMwfYen4FpEC6cXzb0inNRYkB9nqyPJjOu4MUdLoy3EBZLmkdW7/4gsZJi7ccvfb\ 116868x/8fz68d3bJ4UmNBvJ+tjjSXlLaNb1x+w8RFm49cffYdHLwoIahu4RmVXdM7b/2Bi48+Q4L//b2ze1bP6qxID3M1UUZ1PVAW3X9o/p/eDIl3TgZkAHVk65\ 11687xNt46sm9FcnBTooC/HC5Jh5peGu/DEvfdfPr97+QRug4+jaUxGCSTyX71+/eb1+y8/voPBJ0g81RZm1EDi/dt/ZAB1ZGWyr5pNUAay9/5+fApPnhZKAtw8g\ 11688mLS8BDcvP/04undVZkR7maqIsJAIMDFzgEGvHL6oHTY1DetCdV/ADmMewY=" 11689 11690_palette_amiga7800mess : 11691 base642img \ 11692"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM3MTQKeJxj1LONLG9ZsP3sjbsPXn349v//PyAEgxu7Z5aHOLoXLdh84smf/2jg7+\ 11693fnV/ZvmFsV712/+cT9t7//QDVBNP9+/+T6qd2rpjame3nGpFZNmrts454j567euvfw2dkDG+bPmNBQmBrl76LKycbKo2DmFp6YW905ce7yTbsPX75weP3sy\ 11694b0FYb6exrKycrKyTEyMTEDMKG2XWtY1e+PxCye2LWqrLQ7yM9eQ5GdhYBCTUdbQs3IPjC1s7Z2+dMfOTy9unzu0Y/W87sqcBA9XSx03n9DcCWsOXbz//N33\ 11695vyD3AcGfn28fXti/dXVvYYQjI7r////88uzGhaOrJzZk+JtrKEjKqVoGZjX1zFx35Oixa0+e37p4aNOSGV2VeUl+ZvraKvLiUrKKqjZBCQX1E+at2nni1I7\ 116961S+f21hWlR/na6kowMzIys/ApW7v6R6XmljVPmLNq2+XT+zatWjCpuTQjysfWQE2OQ8bQKTg2s7y1d8aS9TsOXnz78sn9OzeObVs5q60wxtNC0ye2oGXm6j\ 116973n7zx8/urth88gB/5/8/jm2V1LJteXZod4OASnVfTMWLp+9/nHr7+CJP+8f3jtzP5N83vrC8OCXEyt7N0iynoWbth37OytZ59+/rxy+tjB7WsXTG4tTwm0U\ 11698pWXQvf/mpkVYYG+NsCwF5cQYGNkYBGUU1RSkFfVtQiJzO1YtPrikc3zumszQ73ttVX4BXj5WHjFJWUsQxOT6/rnr9137t6bVy+ePbp17jDQA50lCd7muR0T\ 11699l+07eenuiw8/QYGPlITe3rt6amlzZe/izUfO33rx/R807YAiCMh6c/P88TWTy2Oi8lvmbDt19ws0Xf6Dxb+vuTo4/hkYGBkZeCSV9Z3D4zOnTZ++ujInJNj\ 11700TRl+GixEkycDJxcnJwa2gb+vqm1q75OiVGc2FCTGRfi5WBurywhyszABUd6ys" 11701 11702_palette_fornaxvoid1 : 11703 base642img \ 11704"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMjU2IDEgMSAzICM1MjkKeJyrKi3ISU+OiwwN8HF3srM01Te3d/MLi03NLalp6Z48exEDO6+IlIK6ro\ 11705mVg7tvSFTChwcXDmxYMKGhICHAwUBBgOH/p2e3zh3aunLuxNaKnIQQj8/Pb184snPtwmld9cXpMQGu/6HgwYEFDQlAHTeObJjbWZrkZ6UuzAAC/9/dPbN71\ 11706cyO8rRQF2MlQQYGVk5eITEpOWV1bX0TCxsHRkYGFIChXkBez9YnOquqc8bybUevPP7/6enNM0AXNoDcp6EgsGzT3hOX77388v/Wtom5HioMjy8f2bpsekdl\ 11707ZpS3ja4cP4Oqlr6xhY2jm5d/cERsYlrWvWvnju3btm7ZvGl9bXVleWlnDu/auGLB9L7WmpLspMgAjw8vH925eu7EwV1b1i5bMHNSD7r/+zqaasoKslLiIoJ\ 1170883BysTG8cWjMN6HG4+9H9r62hpqKkICcjKS4qLMjPy43u//8fHl46vGXptI7KrGgfWz2FBXNnz5w+dfLEvp6ujraWpgYGTiFpFV0ze4/AqOSc0rq2A2tmth\ 11709UnGDDgAuj+/48GXn/6icI/c+Hy9Vt3Hz558frdp68///zH8D+RABb//79/ePHw5qVTh3dvWTuxLNrh/7d3T+9eOXN496ZVC2dO6GhgEFQydglNK++YuWr3m\ 11710bvv/qP7n6B6KHhx4QA4Cfy/v39+fby9PAOXsIyqnjlGeAIAmOWLbw==" 11711 11712# Command that tries to compress a smooth-enough palette. 11713compress_palette : 11714 N={w} 11715 do 11716 N-=1 11717 +r. $N,1,1,3,2 round. 11718 ri. ..,3 round. 11719 deltaE. .. 11720 dEavg,dEmax={[ia,iM]} rm. 11721 e[] "N = "$N", dEavg = "$dEavg", dEmax = "$dEmax 11722 while $dEavg<0.75" && "$dEmax<1.25 11723 N+=1 11724 r $N,1,1,3,2 round. 11725 e[] "" 11726 img2base64 0,0 rm 11727 str=\"${}\" 11728 ('$str') s. x,-119 ('\\\n') if $!>2 a[0--3] .,x fi rm. 11729 i[0] ('" base642img \\\n"') 11730 ('"\n r. 256,1,1,3,3 round.\n"') 11731 a x 11732 ot pal.txt 11733 11734#@cli pseudogray : _max_increment>=0,_JND_threshold>=0,_bits_depth>0 11735#@cli : Generate pseudogray colormap with specified increment and perceptual threshold. 11736#@cli : If 'JND_threshold' is 0, no perceptual constraints are applied. 11737#@cli : Default values: 'max_increment=5', 'JND_threshold=2.3' and 'bits_depth=8'. 11738#@cli : $ pseudogray 5 11739pseudogray : check "isint(${1=5}) && $1>=0 && ${2=2.3}>=0 && isint(${3=8}) && $3>0" 11740 e[^-1] "Generate pseudogray colormap with increment $1, JND threshold $2 and $3 bits depth." 11741 11742 # Generate all possible sRGB colors with given increments. 11743 {round(2^$3)},1,1,3,'x' 11744 if !$1 n. 0,255 return fi 11745 {$1+1},{$1+1},{$1+1},1,'x' +f. 'y' +f. 'z' a[-3--1] c r. {w*h*d},1,1,3,-1 11746 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)' 11747 permute. cxyz discard. -1 r. 3,{h/3},1,1,-1 permute. yzcx 11748 r.. {w*100}% ri. ..,0,2 +[-2,-1] 11749 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)' 11750 permute. cxyz discard. -1 r. 3,{h/3},1,1,-1 permute. yzcx 11751 n. 0,255 11752 +srgb2lab. rv[-2,-1] a[-2,-1] y sort. +,x # Sort by increasing lightness. 11753 if !$2 rows. 1 11754 else # Add perceptual constraint if requested. 11755 11756 # Constraint 1 : keep colors close enough to equivalent 'pure' grays. 11757 s. y rv[-2,-1] . sh. 1,2 f. 0 rm. -[-2,-1] norm. 11758 <=. $2 *. 'x+1' discard. 0 -. 1 map. .. rm.. 11759 11760 # Constraint 2 : remove neighboring colors that are above the JND. 11761 repeat 10000 11762 +srgb2lab. +shift. 0,{1-2*($>%2)},0,0,1 -[-2,-1] norm. 11763 <=. $2 11764 if im rm. break fi 11765 *. 'y+1' discard. 0 -. 1 map. .. rm.. 11766 done 11767 transpose. 11768 fi 11769 nm. pseudogray$1 11770 11771#@cli replace_color : tolerance[%]>=0,smoothness[%]>=0,src1,src2,...,dest1,dest2,... 11772#@cli : Replace pixels from/to specified colors in selected images. 11773#@cli : $ image.jpg +replace_color 40,3,204,153,110,255,0,0 11774replace_color : check "$1>=0 && $2>=0" 11775 l[] (${3--1}) y c s c,2 col1={0,^} col2={1,^} rm endl 11776 e[^-1] "Replace color ("$col1") by color ("$col2") in image$?, with tolerance $1 and smoothness $2." 11777 repeat $! l[$>] 11778 1,1,1,100%,$col1 ri[1] [0] 11779 if $1 -[1] [0] norm[1] <=[1] $1 else ==[1] [0] l[1] s c & endl fi 11780 b[1] $2 11781 1,1,1,{0,s},$col2 ri[2] [0] j[0] [2],0,0,0,0,1,[1] k[0] 11782 endl done 11783 11784#@cli retinex : _value_offset>0,_colorspace={ hsi | hsv | lab | lrgb | rgb | ycbcr },\ 11785# 0<=_min_cut<=100,0<=_max_cut<=100,_sigma_low>0,_sigma_mid>0,_sigma_high>0 11786#@cli : Apply multi-scale retinex algorithm on selected images to improve color consistency. 11787#@cli : (as described in the page <http://www.ipol.im/pub/art/2014/107/>). 11788#@cli : Default values: 'offset=1', 'colorspace=hsv', 'min_cut=1', 'max_cut=1', 'sigma_low=15','sigma_mid=80' \ 11789# and 'sigma_high=250'. 11790retinex : check "${1=5}>0 && ${3=1}>=0 && $3<=100 && ${4=1}>=0 && $4<=100 && ${5=15}>0 && ${6=80}>0 && ${7=250}>0" 11791 skip "${2=hsv}" 11792 e[^-1] "Apply Retinex color consistency algorithm on image$?, with value offset $1, colorspace '$2', cuts ($3,$4) 11793 and sigmas (${5-7})." 11794 if '$2'=='hsi' mode=hsi_i 11795 elif '$2'=='hsv' mode=hsv_v 11796 elif '$2'=='lab' mode=lab_l 11797 elif '$2'=='rgb' mode=rgb 11798 elif '$2'=='lrgb' mode=lrgb 11799 elif '$2'=='ycbcr' mode=ycbcr_y 11800 else error[0--2] "Command '$0': Invalid colorspace argument '$2'." 11801 fi 11802 ac "_retinex $1,${3--1}",$mode 11803 11804_retinex : 11805 - {im-$1} {[w,h,d,s]},1 11806 repeat 3 +b[0] {arg(1+$>,${4-6})} +/[0,-1] rm.. *[1,-1] done 11807 rm[0] log c $2%,{100-$3}% n 0,255 11808 11809#@cli rgb2bayer : _start_pattern=0,_color_grid=0 11810#@cli : Transform selected color images to RGB-Bayer sampled images. 11811#@cli : Default values: 'start_pattern=0' and 'color_grid=0'. 11812#@cli : $ image.jpg +rgb2bayer 0 11813rgb2bayer : skip ${1=0},${2=0} 11814 e[^-1] "Transform image$? to a RGB-Bayer "${arg\ 1+!$2,color,monochrome}" grid, starting from pattern '$1'." 11815 to_rgb repeat $! l[$>] 11816 _rgb2bayer$1 ri[1] [0],0,2 * if !$2 s c + fi 11817 endl done 11818 11819_rgb2bayer0 : (1,0;0,0^0,1;1,0^0,0;0,1) 11820_rgb2bayer1 : (0,0;0,1^0,1;1,0^1,0;0,0) 11821_rgb2bayer2 : (0,1;0,0^1,0;0,1^0,0;1,0) 11822_rgb2bayer3 : (0,0;1,0^1,0;0,1^0,1;0,0) 11823 11824#@cli rgb2cmy 11825#@cli : Convert color representation of selected images from RGB to CMY. 11826#@cli : $ image.jpg rgb2cmy split c 11827rgb2cmy : 11828 e[^-1] "Convert color representation of image$? from RGB to CMY." 11829 to_rgb * -1 + 255 c 0,255 11830 11831#@cli rgb2cmyk 11832#@cli : Convert color representation of selected images from RGB to CMYK. 11833#@cli : $ image.jpg rgb2cmyk split c 11834#@cli : $ image.jpg rgb2cmyk split c fill[3] 0 append c cmyk2rgb 11835rgb2cmyk : 11836 e[^-1] "Convert color representation of image$? from RGB to CMYK." 11837 rgb2cmy repeat $! l[$>] 11838 s c +min -[0-2] . +/. 255 -. 1 *. -1 +==. 0 +[-2,-1] 11839 /[0-2] . rm. a c 11840 endl done 11841 11842#@cli rgb2hcy 11843#@cli : Convert color representation of selected images from RGB to HCY. 11844#@cli : $ image.jpg rgb2hcy split c 11845rgb2hcy : 11846 e[^-1] "Convert color representation of image$? from RGB to HCY." 11847 to_color f " 11848 M = max(R,G,B); 11849 C = M - min(R,G,B); 11850 H = 60*(C==0?0:M==R?((G-B)/C)%6:M==G?(B-R)/C+2:(R-G)/C+4); 11851 Y = 0.299*R + 0.587*G + 0.114*B; 11852 [ H,C/255,Y/255 ]" 11853 11854#@cli rgb2hsi 11855#@cli : Convert color representation of selected images from RGB to HSI. 11856#@cli : $ image.jpg rgb2hsi split c 11857rgb2hsi : 11858 e[^-1] "Convert color representation of image$? from RGB to HSI." 11859 to_color 11860 f " 11861 m = min(R,G,B); 11862 M = max(R,G,B); 11863 C = M - m; 11864 sum = R + G + B; 11865 H = 60*(C==0?0:M==R?((G - B)/C)%6:M==G?(B - R)/C + 2:(R - G)/C + 4); 11866 S = sum<=0?0:1 - 3*m/sum; 11867 I = sum/(3*255); 11868 [ H, S, I ]" 11869 11870#@cli rgb2hsi8 11871#@cli : Convert color representation of selected images from RGB to HSI8. 11872#@cli : $ image.jpg rgb2hsi8 split c 11873rgb2hsi8 : 11874 e[^-1] "Convert color representation of image$? from RGB to HSI8." 11875 rgb2hsi _rgb2hsx8 11876 11877#@cli rgb2hsl 11878#@cli : Convert color representation of selected images from RGB to HSL. 11879#@cli : $ image.jpg rgb2hsl split c 11880#@cli : $ image.jpg rgb2hsl +split c add[-3] 100 mod[-3] 360 append[-3--1] c hsl2rgb 11881rgb2hsl : 11882 e[^-1] "Convert color representation of image$? from RGB to HSL." 11883 to_color 11884 f " 11885 m = min(R,G,B); 11886 M = max(R,G,B); 11887 C = M - m; 11888 H = 60*(C==0?0:M==R?((G - B)/C)%6:M==G?(B - R)/C + 2:(R - G)/C + 4); 11889 L = 0.5*(m + M)/255; 11890 S = L==1 || L==0?0:C/(1 - abs(2*L - 1))/255; 11891 [ H, S, L ]" 11892 11893#@cli rgb2hsl8 11894#@cli : Convert color representation of selected images from RGB to HSL8. 11895#@cli : $ image.jpg rgb2hsl8 split c 11896rgb2hsl8 : 11897 e[^-1] "Convert color representation of image$? from RGB to HSL8." 11898 rgb2hsl _rgb2hsx8 11899 11900#@cli rgb2hsv 11901#@cli : Convert color representation of selected images from RGB to HSV. 11902#@cli : $ image.jpg rgb2hsv split c 11903#@cli : $ image.jpg rgb2hsv +split c add[-2] 0.3 cut[-2] 0,1 append[-3--1] c hsv2rgb 11904rgb2hsv : 11905 e[^-1] "Convert color representation of image$? from RGB to HSV." 11906 to_color 11907 f " 11908 M = max(R,G,B); 11909 C = M - min(R,G,B); 11910 H = 60*(C==0?0:M==R?((G - B)/C)%6:M==G?(B - R)/C + 2:(R - G)/C + 4); 11911 S = M<=0?0:C/M; 11912 [ H, S, M/255 ]" 11913 11914#@cli rgb2hsv8 11915#@cli : Convert color representation of selected images from RGB to HSV8. 11916#@cli : $ image.jpg rgb2hsv8 split c 11917rgb2hsv8 : 11918 e[^-1] "Convert color representation of image$? from RGB to HSV8." 11919 rgb2hsv _rgb2hsx8 11920 11921_rgb2hsx8 : 11922 repeat $! 11923 sh[$>] 0 *. 0.708333 rm. 11924 sh[$>] 1,2 *. 255 rm. 11925 done 11926 11927#@cli rgb2int 11928#@cli : Convert color representation of selected images from RGB to INT24 scalars. 11929#@cli : $ image.jpg rgb2int 11930rgb2int : 11931 e[^-1] "Convert color representation of image$? from RGB to INT24 scalars." 11932 to_rgb round repeat $! l[$>] 11933 s c <<[0] 16 <<[1] 8 + 11934 endl done 11935 11936#@cli rgb2jzazbz : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11937#@cli : Convert color representation of selected images from RGB to Jzazbz. 11938#@cli : Default value: 'illuminant=2'. 11939rgb2jzazbz : skip "${1=,}" 11940 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 11941 e[^-1] "Convert color representation of image$? from RGB to Jzazbz, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11942 rgb2xyz $illu xyz2jzazbz 11943 11944#@cli rgb2lab : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11945#@cli : Convert color representation of selected images from RGB to Lab. 11946#@cli : Default value: 'illuminant=2'. 11947rgb2lab : skip "${1=,}" 11948 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 11949 e[^-1] "Convert color representation of image$? from RGB to Lab, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11950 rgb2xyz $illu xyz2lab $illu 11951 11952#@cli rgb2lab8 : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11953#@cli : Convert color representation of selected images from RGB to Lab8. 11954#@cli : Default value: 'illuminant=2'. 11955#@cli : $ image.jpg rgb2lab8 split c 11956rgb2lab8 : skip "${1=,}" 11957 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 11958 e[^-1] "Convert color representation of image$? from RGB to Lab8, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11959 rgb2lab $illu repeat $! 11960 sh[$>] 0 *. 2.55 rm. 11961 sh[$>] 1 +. 127 *. 0.85 rm. 11962 sh[$>] 2 +. 149 *. 0.836 rm. 11963 done c 0,255 11964 11965#@cli rgb2lch : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11966#@cli : Convert color representation of selected images from RGB to Lch. 11967#@cli : Default value: 'illuminant=2'. 11968#@cli : $ image.jpg rgb2lch split c 11969rgb2lch : skip "${1=,}" 11970 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 11971 e[^-1] "Convert color representation of image$? from RGB to Lch, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11972 rgb2lab $illu lab2lch 11973 11974#@cli rgb2lch8 : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 11975#@cli : Convert color representation of selected images from RGB to Lch8. 11976#@cli : Default value: 'illuminant=2'. 11977#@cli : $ image.jpg rgb2lch8 split c 11978rgb2lch8 : skip "${1=,}" 11979 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 11980 e[^-1] "Convert color representation of image$? from RGB to Lch8, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 11981 pi,facth={[pi,255/(2*pi)]} 11982 rgb2lch $illu repeat $! 11983 sh[$>] 0 *. 2.55 rm. 11984 sh[$>] 1 *. 1.1086 rm. 11985 sh[$>] 2 +. $pi *. $facth rm. 11986 done c 0,255 11987 11988#@cli rgb2luv 11989#@cli : Convert color representation of selected images from RGB to LUV. 11990#@cli : $ image.jpg rgb2luv split c 11991rgb2luv : 11992 e[^-1] "Convert color representation of image$? from RGB to LUV." 11993 repeat $! l[$>] 11994 +rgb2xyz rgb2lab.. channels.. 0 s. c 11995 *. 3 +*.. 15 +[-2,-1] +. ... +. 1e-8 # Z <- X+15Y+3Z 11996 *... 4 *.. 9 /[-3,-2] . rm. 11997 -.. 0.2009 -. 0.4610 11998 +*... 13 *... . *[-2,-1] a c 11999 endl done 12000 12001#@cli rgb2oklab 12002#@cli : Convert color representation of selected images from RGB to Oklab. 12003#@cli : (see colorspace definition at: <https://bottosson.github.io/posts/oklab/> ). 12004#@cli : See also: ''oklab2rgb''. 12005rgb2oklab : 12006 e[^-1] "Convert color representation of image$? from RGB to Oklab." 12007 repeat $! l[$>] split_opacity to_rgb[0] /[0] 255 12008 f[0] " 12009 l = cbrt(0.4121656120*R + 0.5362752080*G + 0.0514575653*B); 12010 m = cbrt(0.2118591070*R + 0.6807189584*G + 0.1074065790*B); 12011 s = cbrt(0.0883097947*R + 0.2818474174*G + 0.6302613616*B); 12012 [ 0.2104542553*l + 0.7936177850*m - 0.0040720468*s, 12013 1.9779984951*l - 2.4285922050*m + 0.4505937099*s, 12014 0.0259040371*l + 0.7827717662*m - 0.8086757660*s ]" 12015 a c endl done 12016 12017#@cli rgb2ryb 12018#@cli : Convert color representation of selected images from RGB to RYB. 12019#@cli : $ image.jpg rgb2ryb split c 12020rgb2ryb : 12021 e[^-1] "Convert color representation of image$? from RGB to RYB." 12022 to_color 12023 f "red = R; 12024 green = G; 12025 blue = B; 12026 white = min(red,green,blue); 12027 red-=white; 12028 green-=white; 12029 blue-=white; 12030 maxgreen = max(red,green,blue); 12031 yellow = min(red,green); 12032 red-=yellow; 12033 green-=yellow; 12034 blue>0 && green>0?(blue/=2; green/=2); 12035 yellow+=green; 12036 blue+=green; 12037 maxyellow = max(red,yellow,blue); 12038 maxyellow>0?( 12039 N = maxgreen/maxyellow; 12040 red*=N; 12041 yellow*=N; 12042 blue*=N; 12043 ); 12044 red+=white; 12045 yellow+=white; 12046 blue+=white; 12047 [ red,yellow,blue ]" 12048 12049#@cli rgb2srgb 12050#@cli : Convert color representation of selected images from linear RGB to sRGB. 12051rgb2srgb : 12052 e[^-1] "Convert color representation of image$? from linear RGB to sRGB." 12053 f "val = i/255; sval = val<=0.0031308?val*12.92:1.055*val^0.416667 - 0.055; cut(255*sval,0,255)" 12054 12055#@cli rgb2xyz : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12056#@cli : Convert color representation of selected images from RGB to XYZ. 12057#@cli : Default value: 'illuminant=2'. 12058#@cli : $ image.jpg rgb2xyz split c 12059rgb2xyz : skip "${1=,}" 12060 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 12061 e[^-1] "Convert color representation of image$? from RGB to XYZ, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12062 if $illu==2 # E 12063 mix_rgb {[0.488718,0.3106803,0.2006017,\ 12064 0.1762044,0.8129847,0.0108109,\ 12065 0,0.0102048,0.9897952]/255} 12066 elif $illu==1 # D65 12067 mix_rgb {[0.4124564,0.3575761,0.1804375,\ 12068 0.2126729,0.7151522,0.0721750,\ 12069 0.0193339,0.1191920,0.9503041]/255} 12070 else # D50 12071 mix_rgb {[0.43603516,0.38511658,0.14305115,\ 12072 0.22248840,0.71690369,0.06060791,\ 12073 0.01391602,0.09706116,0.71392822]/255} 12074 fi 12075 12076#@cli rgb2xyz8 : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12077#@cli : Convert color representation of selected images from RGB to XYZ8. 12078#@cli : Default value: 'illuminant=2'. 12079#@cli : $ image.jpg rgb2xyz8 split c 12080rgb2xyz8 : skip "${1=,}" 12081 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 12082 e[^-1] "Convert color representation of image$? from RGB to XYZ8, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12083 rgb2xyz $illu repeat $! 12084 sh[$>] 0 *. 255 rm. 12085 sh[$>] 1 *. 255 rm. 12086 sh[$>] 2 *. 231.8182 rm. 12087 done 12088 12089#@cli rgb2yiq 12090#@cli : Convert color representation of selected images from RGB to YIQ. 12091#@cli : $ image.jpg rgb2yiq split c 12092rgb2yiq : 12093 e[^-1] "Convert color representation of image$? from RGB to YIQ." 12094 mix_rgb 0.299,0.587,0.114,\ 12095 0.595716,-0.274453,-0.321263,\ 12096 0.211456,-0.522591,0.311135 12097 12098#@cli rgb2yiq8 12099#@cli : Convert color representation of selected images from RGB to YIQ8. 12100#@cli : $ image.jpg rgb2yiq8 split c 12101rgb2yiq8 : 12102 e[^-1] "Convert color representation of image$? from RGB to YIQ." 12103 rgb2yiq 12104 repeat $! 12105 sh[$>] 1 +. 151.908 *. 0.8393238012481239 rm. 12106 sh[$>] 2 +. 133.261 *. 0.9567690472081104 rm. 12107 done 12108 12109#@cli rgb2ycbcr 12110#@cli : Convert color representation of selected images from RGB to YCbCr. 12111#@cli : $ image.jpg rgb2ycbcr split c 12112rgb2ycbcr : 12113 e[^-1] "Convert color representation of image$? from RGB to YCbCr." 12114 mix_rgb 66,129,25,-38,-74,112,112,-94,-18 12115 repeat $! 12116 sh[$>] 0,2 +. 128 /. 256 rm. 12117 sh[$>] 0 +. 16 rm. 12118 sh[$>] 1,2 +. 128 rm. 12119 done 12120 12121#@cli rgb2yuv 12122#@cli : Convert color representation of selected images from RGB to YUV. 12123#@cli : $ image.jpg rgb2yuv split c 12124rgb2yuv : 12125 e[^-1] "Convert color representation of image$? from RGB to YUV." 12126 mix_rgb {[0.299,0.587,0.114,\ 12127 -0.14713,-0.28886,0.436,\ 12128 0.615,-0.51498,-0.10001]/255} 12129 12130#@cli rgb2yuv8 12131#@cli : Convert color representation of selected images from RGB to YUV8. 12132#@cli : $ image.jpg rgb2yuv8 split c 12133rgb2yuv8 : 12134 e[^-1] "Convert color representation of image$? from RGB to YUV8." 12135 rgb2yuv repeat $! 12136 sh[$>] 0 *. 255 rm. 12137 sh[$>] 1 +. 0.44 *. 289.773 rm. 12138 sh[$>] 2 +. 0.62 *. 205.645 rm. 12139 done 12140 12141#@cli remove_opacity 12142#@cli : Remove opacity channel of selected images. 12143remove_opacity : 12144 e[^-1] "Remove opacity channel of image$?." 12145 repeat $! l[$>] 12146 if s==2 channels 0 12147 elif s==4 channels 0,2 12148 fi 12149 nm {n} endl done 12150 12151#@cli ryb2rgb 12152#@cli : Convert color representation of selected images from RYB to RGB. 12153ryb2rgb : 12154 e[^-1] "Convert color representation of image$? from RYB to RGB." 12155 to_color 12156 f "red = R; 12157 yellow = G; 12158 blue = B; 12159 white = min(red,yellow,blue); 12160 red-=white; 12161 yellow-=white; 12162 blue-=white; 12163 maxyellow = max(red,yellow,blue); 12164 green = min(yellow,blue); 12165 yellow-=green; 12166 blue-=green; 12167 blue>0 && green>0?(blue*=2; green*=2); 12168 red+=yellow; 12169 green+=yellow; 12170 maxgreen = max(red,green,blue); 12171 maxgreen>0?( 12172 N = maxyellow/maxgreen; 12173 red*=N; 12174 green*=N; 12175 blue*=N; 12176 ); 12177 red+=white; 12178 green+=white; 12179 blue+=white; 12180 [ red,green,blue ]" 12181 12182#@cli select_color : tolerance[%]>=0,col1,...,colN 12183#@cli : Select pixels with specified color in selected images. 12184#@cli : $ image.jpg +select_color 40,204,153,110 12185#@cli : $$ https://gmic.eu/oldtutorial/_select_color 12186select_color : skip ${1=0} 12187 e[^-1] "Select color (${2--1}) in image$?, with tolerance $1." 12188 repeat $! l[$>] 12189 +fc ${2--1} - norm <= $1 12190 endl done 12191 12192#@cli sepia 12193#@cli : Apply sepia tones effect on selected images. 12194#@cli : $ image.jpg sepia 12195sepia : 12196 e[^-1] "Apply sepia tones effect on image$?." 12197 (0,44,115,143,196,244^0,20,84,119,184,235^0,5,44,73,144,200) r. 256,1,1,3,3 12198 repeat $!-1 l[$>,-1] split_opacity luminance[0] map[0] . a[^-1] c endl done 12199 rm. 12200 12201#@cli solarize 12202#@cli : Solarize selected images. 12203#@cli : $ image.jpg solarize 12204solarize : 12205 e[^-1] "Solarize image$?." 12206 luminance n 0,128 map 1 12207 12208#@cli split_colors : _tolerance>=0,_max_nb_outputs>0,_min_area>0 12209#@cli : Split selected images as several image containing a single color. 12210#@cli : One selected image can be split as at most 'max_nb_outputs' images. 12211#@cli : Output images are sorted by decreasing area of extracted color regions and have an additional alpha-channel. 12212#@cli : Default values: 'tolerance=0', 'max_nb_outputs=256' and 'min_area=8'. 12213#@cli : $ image.jpg quantize 5 +split_colors , display_rgba 12214split_colors : check "${1=0}>=0 && isint(${2=256}) && $2>0 && ${3=8}>=1" 12215 e[^-1] "Split image$? as single color outputs, with tolerance $1, $2 maximal outputs and minimal color area $3." 12216 repeat $! l[$>] 12217 +label 0,1 norm. area. 0,1 12218 12219 # Loop over biggest color regions. 12220 repeat $2-1 12221 coordsM={1,[xM,yM,zM,cM]} 12222 if {1,i($coordsM)<$3} break fi 12223 color={0,I($coordsM)} 12224 +select_color[0] $1,$color 12225 ==. 0 *[1] . ==. 0 12226 done 12227 if iM#1 !=[1] 0 mv[1] $! # Residual mask, if any. 12228 else rm[1] fi 12229 r[^0] [0],[0],[0],{0,s+1} 12230 N={$!-1} 12231 sh[^0] 0,{s-2} *[-$N--1] [0] rm[-$N--1] 12232 sh[^0] 100% *[-$N--1] 255 rm[0,-$N--1] 12233 12234 endl done 12235 12236#@cli split_opacity 12237#@cli : Split color and opacity parts of selected images. 12238split_opacity : 12239 e[^-1] "Split color and opacity parts of image$?." 12240 repeat $! l[$<] s c,{if(s==4,-3,if(s==2,-1,-s))} endl done 12241 12242#@cli srgb2lab : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12243#@cli : Convert color representation of selected images from sRGB to Lab. 12244#@cli : Default value: 'illuminant=2'. 12245#@cli : $ image.jpg srgb2lab split c 12246#@cli : $ image.jpg srgb2lab +split c mul[-2,-1] 2.5 append[-3--1] c lab2srgb 12247srgb2lab : skip "${1=,}" 12248 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 12249 e[^-1] "Convert color representation of image$? from sRGB to Lab, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12250 srgb2rgb rgb2lab $illu 12251 12252#@cli srgb2lab8 : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12253#@cli : Convert color representation of selected images from sRGB to Lab8. 12254#@cli : Default value: 'illuminant=2'. 12255srgb2lab8 : skip "${1=,}" 12256 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 12257 e[^-1] "Convert color representation of image$? from sRGB to Lab8, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12258 srgb2rgb rgb2lab8 $illu 12259 12260#@cli srgb2rgb 12261#@cli : Convert color representation of selected images from sRGB to linear RGB. 12262srgb2rgb : 12263 e[^-1] "Convert color representation of image$? from sRGB to linear RGB." 12264 f "sval = i/255; val = sval<=0.04045?sval/12.92:((sval + 0.055)/(1.055))^2.4; cut(255*val,0,255)" 12265 12266#@cli to_a 12267#@cli : Force selected images to have an alpha channel. 12268to_a : 12269 e[^-1] "Force image$? to have an alpha channel." 12270 repeat $! l[$>] 12271 if s==1||s==3 channels 0,{s} sh. {s-1} f. 255 rm. fi 12272 endl done 12273 12274#@cli to_color 12275#@cli : Force selected images to be in color mode (RGB or RGBA). 12276to_color : 12277 e[^-1] "Force image$? to be in color mode." 12278 repeat $! l[$>] 12279 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 12280 elif s==2 r 100%,100%,1,4,0,1,0,0,0,1 12281 elif s==1 r 100%,100%,1,3,1 12282 fi 12283 endl done 12284 12285#@cli to_colormode : mode={ 0=adaptive | 1=G | 2=GA | 3=RGB | 4=RGBA } 12286#@cli : Force selected images to be in a given color mode. 12287#@cli : Default value: 'mode=0'. 12288to_colormode : skip ${1=0} 12289 if $1==1 to_gray 12290 elif $1==2 to_graya 12291 elif $1==3 to_rgb 12292 elif $1==4 to_rgba 12293 else 12294 is_rgb=0 is_alpha=0 12295 repeat $! 12296 if {$>,!s||s>4} error "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 12297 elif {$>,s==2} is_alpha=1 12298 elif {$>,s==3} is_rgb=1 12299 elif {$>,s==4} is_rgb=1 is_alpha=1 12300 fi 12301 done 12302 to_colormode {if($is_rgb,3,1)+$is_alpha} 12303 fi 12304 12305#@cli to_gray 12306#@cli : Force selected images to be in GRAY mode. 12307#@cli : $ image.jpg +to_gray 12308to_gray : 12309 e[^-1] "Force image$? to be in GRAY mode." 12310 repeat $! l[$>] 12311 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 12312 elif s>=3 channels 0,2 luminance 12313 elif s==2 r 100%,100%,100%,1,0 12314 fi 12315 endl done 12316 12317#@cli to_graya 12318#@cli : Force selected images to be in GRAYA mode. 12319to_graya : 12320 e[^-1] "Force image$? to be in GRAYA mode." 12321 repeat $! l[$>] 12322 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 12323 elif s==4 +channels 3 channels.. 0,2 luminance.. a c 12324 elif s==3 luminance channels 0,1 sh. 1 f. 255 rm. 12325 elif s==1 channels 0,1 sh. 1 f. 255 rm. 12326 fi 12327 endl done 12328 12329#@cli to_pseudogray : _max_step>=0,_is_perceptual_constraint={ 0 | 1 },_bits_depth>0 12330#@cli : Convert selected scalar images ([0-255]-valued) to pseudo-gray color images. 12331#@cli : Default values: 'max_step=5', 'is_perceptual_constraint=1' and 'bits_depth=8'. 12332#@cli : The original pseudo-gray technique has been introduced by Rich Franzen <http://r0k.us/graphics/pseudoGrey.html>. 12333#@cli : Extension of this technique to arbitrary increments for more tones, has been done by David Tschumperlé. 12334to_pseudogray : check "isint(${1=5}) && $1>=0 && isint(${3=8}) && $3>0" skip ${2=1} 12335 e[^-1] "Convert scalar image$? to pseudo-gray color images, with steps $1." 12336 channels 0 srgb2rgb pseudogray $1,{2.3*$2},$3 12337 12338 # Compute colormap with 65336 entries, to have match corresponding lightness. 12339 +srgb2lab. channels. 0 *. {65535/100} round. rows. 0,2 12340 rv[-2,-1] permute. xcyz +. 1 a[-2,-1] y pointcloud. 0 12341 +norm. !=. 0 distance. 1 *. -1 watershed.. . rm. -. 1 12342 12343 # Map colormap to images, with lightness preservation. 12344 repeat $!-1 12345 to_rgb[$>] rgb2lab[$>] channels[$>] 0 *[$>] {65535/100} round[$>] c[$>] 0,65535 12346 map[$>] . 12347 done rm. 12348 12349#@cli to_rgb 12350#@cli : Force selected images to be in RGB mode. 12351to_rgb : 12352 e[^-1] "Force image$? to be in RGB mode." 12353 repeat $! l[$>] 12354 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 12355 elif s==4 channels 0,2 12356 elif s==2 channels 0,0 r 100%,100%,100%,3 12357 elif s==1 r 100%,100%,100%,3 12358 fi 12359 endl done 12360 12361#@cli to_rgba 12362#@cli : Force selected images to be in RGBA mode. 12363to_rgba : 12364 e[^-1] "Force image$? to be in RGBA mode." 12365 repeat $! l[$>] 12366 if s>4 error[0--5] "Command '$0': Image ["$>"] is not a G,GA,RGB or RGBA image ("{s}" channels)." 12367 elif s==3 channels 0,3 sh. 3 f. 255 rm. 12368 elif s==2 r 100%,100%,100%,4 sh. 2 f. .. rm. 12369 elif s==1 r 100%,100%,100%,4 sh. 3 f. 255 rm. 12370 fi 12371 endl done 12372 12373#@cli transfer_histogram : [reference_image],_nb_levels>0,_color_channels 12374#@cli : Transfer histogram of the specified reference image to selected images. 12375#@cli : Argument 'color channels' is the same as with command 'apply_channels'. 12376#@cli : Default value: 'nb_levels=256' and 'color_channels=all'. 12377#@cli : $ image.jpg 100,100,1,3,"u([256,200,100])" +transfer_histogram[0] [1] 12378transfer_histogram : check ${"is_image_arg $1"}" && ${2=1024}>0" skip "${3=0}" 12379 channels=${"_ac_list \"$3\""} 12380 e[^-1] "Transfer histogram from image ["${"pass$1 -1"}"] to image$?, "\ 12381 "with $2 levels, for channels '"$channels"'." 12382 pass$1 1 sref={s} rm. 12383 to_colormode $sref 12384 if ['$channels']!='all' 12385 pass$1 {$sref==3?2:0} 12386 to_color 12387 ac. "+store _transfer_histogram_reference",$channels rm. 12388 ac "_transfer_histogram $2",$channels,1 12389 else 12390 pass$1 12391 store. _transfer_histogram_reference 12392 repeat $! _transfer_histogram[$>] $2 done 12393 fi 12394 _transfer_histogram_reference= 12395 12396_transfer_histogram : 12397 $_transfer_histogram_reference 12398 repeat min(s#0,s#1) 12399 sh $> 12400 +histogram[-2,-1] $1 cumulate[-2,-1] /.. {-2,i[-1,2]} /. {i[-1,2]} 12401 f.. "* 12402 const w1 = w -1; 12403 val = i; X = x; 12404 val<i[#-1,X]?( 12405 step = int(X/2); 12406 while (X && step>=1, nX = max(0,X - step); val<i[#-1,nX]?(X = nX):(step = int(step/2))); 12407 X?(vc = i[#-1,X]; vp = i[#-1,X - 1]; (vc - val)>(val - vp)?--X); # Rounding 12408 ):( 12409 step = int((w1 - X)/2); 12410 while (X<w1 && step>=1, nX = min(w1,X + step); val>i[#-1,nX]?(X = nX):(step = int(step/2))); 12411 X<w1?(vc = i[#-1,X]; vn = i[#-1,X + 1]; (val - vc)>(vn - val)?++X); # Rounding 12412 ); 12413 im#-3 + (iM#-3 - im#-3)*X/w1" 12414 n[-4] 0,{w-1} round[-4] map[-4] .. 12415 k[0,1] 12416 done 12417 rm. 12418 12419#@cli transfer_pca : [reference_image],_color_channels 12420#@cli : Transfer mean and covariance matrix of specified vector-valued reference image to selected images. 12421#@cli : Argument 'color channels' is the same as with command 'apply_channels'. 12422#@cli : Default value: 'color_channels=all'. 12423#@cli : $ sample lena,earth +transfer_pca[0] [1] 12424transfer_pca : check ${"is_image_arg $1"} skip "${2=all}" 12425 channels=${"_ac_list \"$2\""} 12426 e[^-1] "Transfer mean vector and covariance matrix from image ["${"pass$1 -1"}"] to image$?, "\ 12427 "for channels '"$channels"'." 12428 pass$1 1 sref={s} rm. 12429 to_colormode[^-1] $sref 12430 if $sref==1 # Scalar case can to be solved more easily 12431 pass$1 12432 var_ref,avg_ref={[iv,ia]} rm. 12433 repeat $! l[$>] - {ia} * {sqrt($var_ref/iv)} + $avg_ref endl done 12434 elif ['$channels']!='all' 12435 pass$1 {$sref==3?2:0} 12436 to_color 12437 ac. "+store _transfer_pca_reference",$channels rm. 12438 ac "_transfer_pca",$channels,1 12439 else 12440 pass$1 12441 store. _transfer_pca_reference 12442 repeat $! _transfer_pca[$>] done 12443 fi 12444 _transfer_pca_reference= 12445 12446_transfer_pca : 12447 $_transfer_pca_reference 12448 f.. "*begin( 12449 cov = [ "${"covariance_colors[0] _avg"}" ]; 12450 avg = [ "$_avg" ]; 12451 eig = eig(cov); 12452 lambda = 1/sqrt(1e-6 + eig[0,s]); 12453 rot = mul(diag(lambda),eig[s,s*s],s); 12454 12455 cov_ref = [ "${"covariance_colors[1] _avg_ref"}" ]; 12456 avg_ref = [ "$_avg_ref" ]; 12457 eig_ref = eig(cov_ref); 12458 lambda_ref = sqrt(eig_ref[0,s]); 12459 rot_ref = mul(transpose(eig_ref[s,s*s],s),diag(lambda_ref),s); 12460 12461 M = mul(rot_ref,rot,s); 12462 ); 12463 avg_ref + M*(I - avg)" 12464 rm. 12465 12466#@cli transfer_rgb : [target],_gamma>=0,_regularization>=0,_luminosity_constraints>=0,_rgb_resolution>=0,\ 12467# _is_constraints={ 0 | 1 } 12468#@cli : Transfer colors from selected source images to selected reference image (given as argument). 12469#@cli : 'gamma' determines the importance of color occurrences in the matching process (0=none to 1=huge). 12470#@cli : 'regularization' determines the number of guided filter iterations to remove quantization effects. 12471#@cli : 'luminosity_constraints' tells if luminosity constraints must be applied on non-confident matched colors. 12472#@cli : 'is_constraints' tells if additional hard color constraints must be set (opens an interactive window). 12473#@cli : Default values: 'gamma=0.3','regularization=8', 'luminosity_constraints=0.1', 'rgb_resolution=64' and \ 12474# 'is_constraints=0'. 12475#@cli : $ sample pencils,wall +transfer_rgb[0] [1],0,0.01 12476transfer_rgb : check "${2=0.3}>=0 && ${3=8}>=0 && ${4=0.15}>=0 && ${5=64}>=0 && isint(${6=0})" 12477 e[^-1] "Transfer colors of image $1 to image$?." 12478 sigma=1.5 12479 repeat $! pass$1 0 l[$>,-1] 12480 nm_source={0,b} nm_target={1,b} 12481 nm[0] source nm[1] target 12482 12483 # Generate matching functions from 3D RGB features. 12484 +_transfer_rgb[source,target] $2,$sigma,$5 12485 nm.. fsource nm. ftarget 12486 n[fsource,ftarget] 0,255 12487 12488 # Manage color constraints. 12489 if $6 12490 h0={2*{*,v}/3} ws0={source,max(1,w*$h0/h)} wt0={target,max(1,w*$h0/h)} 12491 w1={2*{*,u}/3} hs1={source,max(1,h*$w1/w)} ht1={target,max(1,h*$w1/w)} 12492 if abs($ws0+$wt0-$w1)<abs($hs1+$ht1-$h0) # Append along X. 12493 +r2dy[source,target] $h0 +b[-2,-1] 0.5% a[-4,-3] x a[-2,-1] x 12494 else # Append along Y. 12495 +r2dx[source,target] $w1 +b[-2,-1] 0.5% a[-4,-3] y a[-2,-1] y 12496 fi 12497 if w>$w1 r2dx[-2,-1] $w1 fi 12498 if h>$h0 r2dy[-2,-1] $h0 fi 12499 nm.. visu nm. both 12500 12501 w[visu] -1,-1 12502 N=0 do 12503 w[] -1,-1,"[G'MIC] Add Color Guide (Constraint ""#"{1+$N}")" 12504 +select[$visu] 1 if i==-1 rm. break fi 12505 line[$visu] {i[0]},{i[1]},{i[3]},{i[4]},1,0xF0F0F0F0,0 12506 line[$visu] {i[0]},{i[1]},{i[3]},{i[4]},1,0x0F0F0F0F,255 12507 circle[$visu] {i[0]},{i[1]},5,1,0,0,0 circle[$visu] {i[0]},{i[1]},3,1,255,0,0 12508 circle[$visu] {i[3]},{i[4]},5,1,0,0,0 circle[$visu] {i[3]},{i[4]},3,1,0,255,0 12509 s. y,2 rows[-2,-1] 0,1 a[-2,-1] x permute. xczy 12510 +warp[$both] .,0,0 rm.. 12511 *. {($5-1)/255} s. x,2 12512 -. .. *. -1 a[-2,-1] c 12513 N+=1 12514 while {*} 12515 if $N a[-$N--1] x permute. xczy nm. constraints fi 12516 rm[$visu,$both] w 0 12517 fi 12518 12519 # Estimate warping field. 12520 if $constraints 12521 +pointcloud. 0 r. ...,...,...,3,0 +compose_channels. + a[-2,-1] c 12522 displacement[fsource] [ftarget],0.001,5,0,10000,1,. rm[ftarget,constraints,-1] 12523 else 12524 displacement[fsource] [ftarget],0.005 rm[ftarget] 12525 fi 12526 nm[fsource] displacement 12527 12528 # Generate video of matching. 12529 # if videos 12530 # N=$! 12531 # [displacement],[displacement],[displacement],1,x +f. y +f. z a[-3--1] c *. {255/(w-1)} +. 1 12532 # +_transfer_rgb[source] 0,$sigma,{w} *.. . distance. 1 *. -1 watershed.. . rm. 12533 # +_transfer_rgb[source] 0,$sigma,{w} a[-2,-1] c 12534 12535 # [displacement],[displacement],[displacement],1,x +f. y +f. z a[-3--1] c *. {255/(w-1)} +. 1 12536 # +_transfer_rgb[target] 0,$sigma,{w} *.. . distance. 1 *. -1 watershed.. . rm. 12537 # +_transfer_rgb[target] 0,$sigma,{w} a[-2,-1] c 12538 # warp. [displacement],1,1,1,48 12539 12540 # l[$N--1] 12541 # f3d 1200 12542 # ap "s. c,-3 view_func. 6,.. rm.." 12543 # ap "makefig" 12544 # append[^0] [0],x rm[0] 12545 # r2dx 1024 12546 # [-1]x20 12547 # o videos/video_${nm_source}_to_${nm_target}.mp4,10 12548 # rm 12549 # endl 12550 # fi 12551 12552 # Estimate confidence of the color mapping. 12553 +_transfer_rgb[target] 0,$sigma,{displacement,w} 12554 warp. [displacement],1,1,1 c. 0,100% nm. fconfidence 12555 +map_clut[source] . nm. confidence 12556 12557 # Generate transfer CLUT. 12558 [displacement],[displacement],[displacement],1,x +f. y +f. z a[-3--1] c *. {255/(w-1)} +. 1 12559 +_transfer_rgb[target] 0,0,{w} *.. . 12560 warp[-2,-1] [displacement],1,0,1 12561 distance. 1 *. -1 watershed.. . rm. -. 1 12562 nm. clut 12563 b[clut] $sigma% 12564 12565 # Enforce luminosity constraint for non-confident colors. 12566 if $4>0 12567 ^[fconfidence] {$4/10} *[fconfidence] -1 +[fconfidence] 1 12568 +f[fconfidence] x +f. y +f. z a[-3--1] c *. {255/(w-1)} 12569 rgb2hsv[clut,-1] channels. 100% 12570 j[clut] .,0,0,0,2,1,[fconfidence] rm. 12571 hsv2rgb[clut] 12572 fi 12573 12574 # Map CLUT to get result. 12575 +map_clut[source] [clut] nm. res_noregul 12576 12577 # Apply guided smoothing to remove quantization artifacts. 12578 if !$3 12579 nm[res_noregul] res 12580 else 12581 l[source,res_noregul] 12582 rgb2ycbcr # Perform regularization in YCbCr to avoid creation of false colors. 12583 +-[1] [0] repeat $3 guided. [0],5,5 done +. [0] c. 0,255 12584 ycbcr2rgb 12585 endl 12586 nm. res 12587 j[res] [res_noregul],0,0,0,0,1,[confidence] 12588 rm[res_noregul] 12589 fi 12590 12591 k[res] 12592 endl done 12593 12594# _transfer_rgb : _gamma>=0,_smoothness>=0,_resolution>0 12595# Convert selected images into 3D volumetric scalar function for color matching. 12596_transfer_rgb : l[] check "${1=0}>=0 && ${2=1.5}>=0 && ${3=128}>0" gamma=$1 smoothness=$2 res=$3 12597 onfail noarg gamma=0 smoothness=1.5 res=128 endl 12598 e[^-1] "Convert image$? as 3D volumetric scalar functions for color matching, with gamma "$gamma", 12599 smoothness "$smoothness" and resolution "$res"." 12600 to_rgb repeat $! l[$>] 12601 b 0.3% 12602 r {w*h},3,1,1,-1 * {($res-1)/255} 12603 pointcloud 1,$res,$res,$res f 'if(i,i^$gamma,0)' b $smoothness% n 0,1 12604 endl done 12605 12606#@cli xyz2jzazbz 12607#@cli : Convert color representation of selected images from XYZ to RGB. 12608xyz2jzazbz : 12609 e[^-1] "Convert color representation of image$? from XYZ to Jzazbz." 12610 repeat $! l[$>] split_opacity 12611 f[0] ${-_jzazbz_const}" 12612 X = i0*255; 12613 Y = i1*255; 12614 Z = i2*255; 12615 Xp = Jzazbz_b*X - (Jzazbz_b - 1)*Z; 12616 Yp = Jzazbz_g*Y - (Jzazbz_g - 1)*X; 12617 Zp = Z; 12618 L = 0.41478972*Xp + 0.579999*Yp + 0.0146480*Zp; 12619 M = -0.2015100*Xp + 1.120649*Yp + 0.0531008*Zp; 12620 S = -0.0166008*Xp + 0.264800*Yp + 0.6684799*Zp; 12621 tmp = (L/peakLum)^Jzazbz_n; 12622 Lp = ((Jzazbz_c1 + Jzazbz_c2*tmp)/(1 + Jzazbz_c3*tmp))^Jzazbz_p; 12623 tmp = (M/peakLum)^Jzazbz_n; 12624 Mp = ((Jzazbz_c1 + Jzazbz_c2*tmp)/(1 + Jzazbz_c3*tmp))^Jzazbz_p; 12625 tmp = (S/peakLum)^Jzazbz_n; 12626 Sp = ((Jzazbz_c1 + Jzazbz_c2*tmp)/(1 + Jzazbz_c3*tmp))^Jzazbz_p; 12627 Iz = 0.5*Lp + 0.5*Mp; 12628 az = 3.52400*Lp - 4.066708*Mp + 0.542708*Sp; 12629 bz = 0.199076*Lp + 1.096799*Mp - 1.295875*Sp; 12630 Jz = (1 + Jzazbz_d)*Iz/(1 + Jzazbz_d*Iz) - Jzazbz_d0; 12631 [ Jz,az,bz ]" 12632 a c endl done 12633 12634#@cli xyz2lab : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12635#@cli : Convert color representation of selected images from XYZ to Lab. 12636#@cli : Default value: 'illuminant=2'. 12637xyz2lab : skip "${1=,}" 12638 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 12639 e[^-1] "Convert color representation of image$? from XYZ to Lab, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12640 to_color 12641 f " 12642 begin( 12643 const epsilon = 216/24389; 12644 const kappa = 24389/27; 12645 lab(x) = (x>epsilon?cbrt(x):(x*kappa + 16)/116); 12646 D65 = [ 0.4124564, 0.3575761, 0.1804375, 12647 0.2126729, 0.7151522, 0.0721750, 12648 0.0193339, 0.1191920, 0.9503041 ]; 12649 D50 = [ 0.43603516, 0.38511658, 0.14305115, 12650 0.22248840, 0.71690369, 0.06060791, 12651 0.01391602, 0.09706116, 0.71392822 ]; 12652 E = [ 0.488718,0.3106803,0.2006017, 12653 0.1762044,0.8129847,0.0108109, 12654 0,0.0102048,0.9897952 ]; 12655 white = ("$illu"==2?E:"$illu"==1?D65:D50)*[ 1,1,1 ]; 12656 ); 12657 xr = i0/white[0]; 12658 yr = i1/white[1]; 12659 zr = i2/white[2]; 12660 fx = lab(xr); 12661 fy = lab(yr); 12662 fz = lab(zr); 12663 [ cut(116*fy - 16,0,100), 500*(fx - fy), 200*(fy - fz) ]" 12664 12665#@cli xyz2rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12666#@cli : Convert color representation of selected images from XYZ to RGB. 12667#@cli : Default value: 'illuminant=2'. 12668xyz2rgb : skip "${1=,}" 12669 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 12670 e[^-1] "Convert color representation of image$? from XYZ to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12671 if $illu==2 # E 12672 mix_rgb {[2.3706743,-0.9000405,-0.4706338,\ 12673 -0.513885,1.4253036,0.0885814,\ 12674 0.0052982,-0.0146949,1.0093968]*255} 12675 elif $illu # D65 12676 mix_rgb {[3.2404542,-1.5371385,-0.4985314,\ 12677 -0.9692660,1.8760108,0.0415560,\ 12678 0.0556434,-0.2040259,1.0572252]*255} 12679 else # D50 12680 mix_rgb {[3.134274799724,-1.617275708956,-0.490724283042,\ 12681 -0.978795575994,1.916161689117,0.033453331711,\ 12682 0.071976988401,-0.228984974402,1.405718224383]*255} 12683 fi 12684 c 0,255 12685 12686#@cli xyz82rgb : illuminant={ 0=D50 | 1=D65 | 2=E } : (no arg) 12687#@cli : Convert color representation of selected images from XYZ8 to RGB. 12688#@cli : Default value: 'illuminant=2'. 12689xyz82rgb : skip "${1=,}" 12690 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 12691 e[^-1] "Convert color representation of image$? from XYZ8 to RGB, using the "${arg\ 1+$illu,D50,D65,E}" illuminant." 12692 repeat $! 12693 sh[$>] 0 /. 255 rm. 12694 sh[$>] 1 /. 255 rm. 12695 sh[$>] 2 /. 231.8182 rm. 12696 done xyz2rgb $illu 12697 12698#@cli ycbcr2rgb 12699#@cli : Convert color representation of selected images from YCbCr to RGB. 12700ycbcr2rgb : 12701 e[^-1] "Convert color representation of image$? from YCbCr to RGB." 12702 repeat $! 12703 sh[$>] 0 -. 16 rm. 12704 sh[$>] 1,2 -. 128 rm. 12705 sh[$>] 0,2 mix_rgb. 298,0,409,\ 12706 298,-100,-208,\ 12707 298,516,0 12708 +. 128 /. 256 c. 0,255 rm. 12709 done 12710 12711#@cli yiq2rgb 12712#@cli : Convert color representation of selected images from YIQ to RGB. 12713yiq2rgb : 12714 e[^-1] "Convert color representation of image$? from YIQ to RGB." 12715 mix_rgb 1,0.9563,0.6210,\ 12716 1,-0.2721,-0.6474,\ 12717 1,-1.1070,1.7046 12718 c 0,255 12719 12720#@cli yiq82rgb 12721#@cli : Convert color representation of selected images from YIQ8 to RGB. 12722yiq82rgb : 12723 e[^-1] "Convert color representation of image$? from YIQ8 to RGB." 12724 repeat $! 12725 sh[$>] 1 /. 0.8393238012481239 -. 151.908 rm. 12726 sh[$>] 2 /. 0.9567690472081104 -. 133.261 rm. 12727 done 12728 mix_rgb 1,0.9563,0.6210,\ 12729 1,-0.2721,-0.6474,\ 12730 1,-1.1070,1.7046 12731 c 0,255 12732 12733#@cli yuv2rgb 12734#@cli : Convert color representation of selected images from YUV to RGB. 12735yuv2rgb : 12736 e[^-1] "Convert color representation of image$? from YUV to RGB." 12737 mix_rgb {[1,0,1.13983,\ 12738 1,-0.39465,-0.5806,\ 12739 1,2.03211,0]*255} 12740 c 0,255 12741 12742#@cli yuv82rgb 12743#@cli : Convert selected images from YUV8 to RGB color bases. 12744yuv82rgb : 12745 e[^-1] "Convert color representation of image$? from YUV8 to RGB." 12746 repeat $! 12747 sh[$>] 0 /. 255 rm. 12748 sh[$>] 1 /. 289.773 -. 0.44 rm. 12749 sh[$>] 2 /. 205.645 -. 0.62 rm. 12750 done yuv2rgb 12751 12752#--------------------------------- 12753# 12754#@cli :: Geometry Manipulation 12755# 12756#--------------------------------- 12757 12758#@cli a : eq. to 'append' : (+) 12759 12760#@cli append : [image],axis,_centering : axis,_centering : (+) 12761#@cli : Append specified image to selected images, or all selected images together, along specified axis. 12762#@cli : (eq. to 'a').\n 12763#@cli : 'axis' can be { x | y | z | c }. 12764#@cli : Usual 'centering' values are { 0=left-justified | 0.5=centered | 1=right-justified }. 12765#@cli : Default value: 'centering=0'. 12766#@cli : $ image.jpg split y,10 reverse append y 12767#@cli : $ image.jpg repeat 5 +rows[0] 0,{10+18*$>}% done remove[0] append x,0.5 12768#@cli : $ image.jpg append[0] [0],y 12769 12770#@cli append_tiles : _M>=0,_N>=0,0<=_centering_x<=1,0<=_centering_y<=1 12771#@cli : Append MxN selected tiles as new images. 12772#@cli : If 'N' is set to 0, number of rows is estimated automatically. 12773#@cli : If 'M' is set to 0, number of columns is estimated automatically. 12774#@cli : If 'M' and 'N' are both set to '0', auto-mode is used. 12775#@cli : If 'M' or 'N' is set to 0, only a single image is produced. 12776#@cli : 'centering_x' and 'centering_y' tells about the centering of tiles when they have different sizes. 12777#@cli : Default values: 'M=0', 'N=0', 'centering_x=centering_y=0.5'. 12778#@cli : $ image.jpg split xy,4 append_tiles , 12779append_tiles : check "isint(${1=0}) && isint(${2=0}) && ${3=0}>=0 && $3<=1 && ${4=$3}>=0 && $4<=1" 12780 if !$! 12781 e[0--3] "Append image$? as a 0x0-tiled image." 12782 return 12783 elif !$1" && "!$2 # Auto-mode 12784 N={int(sqrt($!))} M={ceil($!/$N)} 12785 e[0--3] "Append image$? as a "${M}x${N}"-tiled image (auto-mode)." 12786 elif !$2 # Auto-rows 12787 M=$1 N={round($!/$1,1,1)} 12788 e[0--3] "Append image$? as a "${M}x${N}"-tiled image." 12789 elif !$1 # Auto-columns 12790 M={round($!/$2,1,1)} N=$2 12791 e[0--3] "Append image$? as a "${M}x${N}"-tiled image." 12792 else 12793 e[0--3] "Append image$?, as $1x$2-tiled images." 12794 M=$1 N=$2 12795 fi 12796 W,H=${-max_wh} rr2d $W,$H,2,1 12797 MN={$M*$N} if $!%$MN 0x{$MN-($!%$MN)} fi 12798 repeat $!/$MN l[$>-{$>+$MN-1}] 12799 repeat $!/$M a[$>-{$>+$M-1}] x,$3 done a y,$4 12800 endl done 12801 12802#@cli apply_scales : "command",number_of_scales>0,_min_scale[%]>=0,_max_scale[%]>=0,_scale_gamma>0,_interpolation 12803#@cli : Apply specified command on different scales of selected images. 12804#@cli : 'interpolation' can be { 0=none | 1=nearest | 2=average | 3=linear | 4=grid | 5=bicubic | 6=lanczos }. 12805#@cli : Default value: 'min_scale=25%', 'max_scale=100%' and 'interpolation=3'. 12806#@cli : $ image.jpg apply_scales "blur 5 sharpen 1000",4 12807apply_scales : check "isint($2) && $2>0 && ${3=25%}>=0 && ${4=100%}>=0 && ${5=1}>0 && isint(${6=3}) && $6>=0" 12808 skip "${1=}" 12809 s0="no" s1="nearest-neighbor" s2="average" s3="linear" s4="grid" s5="bicubic" s6="lanczos" 12810 e[^-1] "Apply command '$1' on image$? for $2 scales ($3 -> $4) and "${s{min(6,$6)}}" interpolation." 12811 repeat $! l[$<] nm={0,n} 12812 scale0={if(${"is_percent $3"},$3*max(w,h,d),$3)} 12813 scale1={if(${"is_percent $4"},$4*max(w,h,d),$4)} 12814 repeat $2 12815 scale={$scale0+($scale1-$scale0)*($>/max(1,$2-1))^$5} 12816 w={0,w==1?1:max(1,round($scale*w/max(w,h,d)))} 12817 h={0,h==1?1:max(1,round($scale*h/max(w,h,d)))} 12818 d={0,d==1?1:max(1,round($scale*d/max(w,h,d)))} 12819 +r[0] $w,$h,$d,100%,$6 12820 if narg("$1") l. $1 endl fi 12821 done 12822 rm[0] nm $nm 12823 endl done 12824 12825#@cli autocrop : value1,value2,... : (no arg) : (+) 12826#@cli : Autocrop selected images by specified vector-valued intensity. 12827#@cli : If no arguments are provided, cropping value is guessed. 12828#@cli : $ 400,400,1,3 fill_color 64,128,255 ellipse 50%,50%,120,120,0,1,255 +autocrop 12829 12830#@cli autocrop_components : _threshold[%],_min_area[%]>=0,_is_high_connectivity={ 0 | 1 },\ 12831# _output_type={ 0=crop | 1=segmentation | 2=coordinates } 12832#@cli : Autocrop and extract connected components in selected images, according to a mask given as the last channel of 12833#@cli : each of the selected image (e.g. alpha-channel). 12834#@cli : Default values: 'threshold=0%', 'min_area=0.1%', 'is_high_connectivity=0' and 'output_type=1'. 12835#@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 \ 12836# +autocrop_components , 12837autocrop_components : skip ${1=0%} check "${2=0.1%}>=0 && isbool(${3=0}) && isint(${4=1}) && $4>=0 && $4<=2" 12838 e[^-1] "Autocrop connected components from image$?, with threshold $1, minimal area $2, "\ 12839 ${arg\ 1+$3,low,high}" connectivity "\ 12840 "and output type set to '"${arg\ 1+$4,crop,segmentation,coordinates}"'.\n" 12841 repeat $! l[$>] 12842 min_area={max(1,round(if(${is_percent\ $2},$2*w*h,$2)))} 12843 +channels 100% >. $1 area_fg. 0,$3 >=. $min_area # Discard background and small objects. 12844 +area. 0,1 <. $min_area -|[-2,-1] label_fg. 0,1 # Fill small holes in objects. 12845 12846 # Extract detected objects. 12847 N={iM} repeat iM 12848 n={1+$>} 12849 e[] "\r > "$n/$N 12850 rprogress {100*$n/$N} 12851 +==[1] $n +*[0,-1] rm.. 12852 if $4==0 coords=${autocrop_coords.\ auto} rm. +z[0] $coords 12853 elif $4==1 autocrop. 12854 else coords=${autocrop_coords.\ auto} rm. ($coords) y. 12855 fi 12856 done 12857 rm[0,1] 12858 if !$! 0 fi 12859 if $4==2 a x fi 12860 endl done 12861 12862#@cli autocrop_seq : value1,value2,... | auto 12863#@cli : Autocrop selected images using the crop geometry of the last one by specified vector-valued intensity, 12864#@cli : or by automatic guessing the cropping value. 12865#@cli : Default value: auto mode. 12866#@cli : $ image.jpg +fill[-1] 0 ellipse[-1] 50%,50%,30%,20%,0,1,1 autocrop_seq 0 12867autocrop_seq : skip ${1=auto} 12868 e[^-1] "Auto-crop image$? using crop geometry of last image by vector '$*'." 12869 if !$! return fi 12870 is_auto={['"$1"']=='auto'} 12871 if $!==1 _autocrop$is_auto ${1--1} return fi 12872 coords=${autocrop_coords.\ ${1--1}} 12873 x0={arg(1,$coords)} y0={arg(2,$coords)} z0={arg(3,$coords)} 12874 x1={arg(4,$coords)} y1={arg(5,$coords)} z1={arg(6,$coords)} 12875 if $x0>$x1" || "$y0>$y1" || "$z0>$z1 i[0--2] 0 rm[1--1:2] 12876 else z $x0,$y0,$z0,$x1,$y1,$z1 12877 fi 12878 12879#@cli channels : { [image0] | c0[%] },_{ [image1] | c1[%] } : (+) 12880#@cli : Keep only specified channels of selected images. 12881#@cli : Dirichlet boundary is used when specified channels are out of range. 12882#@cli : $ image.jpg channels 0,1 12883#@cli : $ image.jpg luminance channels 0,2 12884 12885#@cli columns : { [image0] | x0[%] },_{ [image1] | x1[%] } : (+) 12886#@cli : Keep only specified columns of selected images. 12887#@cli : Dirichlet boundary is used when specified columns are out of range. 12888#@cli : $ image.jpg columns -25%,50% 12889 12890#@cli z : eq. to 'crop'. : (+) 12891 12892#@cli crop : x0[%],x1[%],_boundary_conditions : x0[%],y0[%],x1[%],y1[%],_boundary_conditions : \ 12893# x0[%],y0[%],z0[%],x1[%],y1[%],z1[%],_boundary_conditions : \ 12894# x0[%],y0[%],z0[%],c0[%],x1[%],y1[%],z1[%],c1[%],_boundary_conditions : (+) 12895#@cli : Crop selected images with specified region coordinates. 12896#@cli : (eq. to 'z').\n 12897#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 12898#@cli : Default value: 'boundary_conditions=0'. 12899#@cli : $ image.jpg +crop -230,-230,280,280,1 crop[0] -230,-230,280,280,0 12900#@cli : $ image.jpg crop 25%,25%,75%,75% 12901 12902#@cli diagonal 12903#@cli : Transform selected vectors as diagonal matrices. 12904#@cli : $ 1,10,1,1,'y' +diagonal 12905diagonal : 12906 e[^-1] "Transform vector$? as diagonal matrix." 12907 y repeat $! r[$>] {$>,h+1},100%,1,1,0 r[$>] {$>,h},100%,1,1,-1 done 12908 12909# downsize_aliased : 100<=factor<=0 12910# Downsize selected images with a specific algorithm to better render anti-aliased rendering 12911# over transparent background (from aliased transparent images, manage transparent border pixels with more care). 12912downsize_aliased : check "${1=50}>=0 && $1<=100" 12913 if $1==100 return elif !$1 r 1,1,1,100%,2 return fi 12914 N={ceil(1+100/$1)} 12915 repeat $! l[$>] 12916 split_opacity 12917 if $!==1 continue fi 12918 +dilate.. $N +==.. 0 12919 j[0] ..,0,0,0,0,1,. rm[-2,-1] 12920 a c 12921 r $1%,$1%,$1%,100%,2 12922 endl done 12923 12924#@cli elevate : _depth,_is_plain={ 0 | 1 },_is_colored={ 0 | 1 } 12925#@cli : Elevate selected 2D images into 3D volumes. 12926#@cli : Default values: 'depth=64', 'is_plain=1' and 'is_colored=1'. 12927elevate : check "${1=64}>0" skip ${2=1},${3=1} 12928 e[^-1] "Elevate 2D image$? into $1-slices volume(s)." 12929 r 100%,100%,1,100% 12930 repeat $! l[$>] nm={0,n} 12931 +norm 100%,100%,$1,{if($3,{0,s},1)} 12932 m={-2,im} d={-2,iM-$m} 12933 repeat $1 12934 if $2 +>=[1] {$m+$d*($>+1)/$1} 12935 else +ir[1] {$m+$d*$>/$1},{$m+$d*($>+1)/$1} 12936 fi 12937 r. 100%,100%,1,.. if $3 *. [0] fi 12938 j.. .,0,0,$> rm. 12939 done 12940 rm[0,1] nm $nm endl done 12941 12942#@cli expand_x : size_x>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 12943#@cli : Expand selected images along the x-axis. 12944#@cli : Default value: 'boundary_conditions=1'. 12945#@cli : $ image.jpg expand_x 30,0 12946expand_x : check "$1>=0 && ${2=1}>=0 && $2<=3" 12947 e[^-1] "Expand image$? along the x-axis with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 12948 boundary conditions." 12949 repeat $! r[$>] {$>,w+2*$1},100%,100%,100%,0,$2,0.5,0.5,0.5 done 12950 12951#@cli expand_xy : size>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 12952#@cli : Expand selected images along the xy-axes. 12953#@cli : Default value: 'boundary_conditions=1'. 12954#@cli : $ image.jpg expand_xy 30,0 12955expand_xy : check "$1>=0 && ${2=1}>=0 && $2<=3" 12956 e[^-1] "Expand image$? along the xy-axes with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 12957 boundary conditions." 12958 repeat $! r[$>] {$>,w+2*$1},{$>,h+2*$1},100%,100%,0,$2,0.5,0.5,0.5 done 12959 12960#@cli expand_xyz : size>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 12961#@cli : Expand selected images along the xyz-axes. 12962#@cli : Default value: 'boundary_conditions=1'. 12963expand_xyz : check "$1>=0 && ${2=1}>=0 && $2<=3" 12964 e[^-1] "Expand image$? along the xyz-axes with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 12965 boundary conditions." 12966 repeat $! r[$>] {$>,w+2*$1},{$>,h+2*$1},{$>,d+2*$1},100%,0,$2,0.5,0.5,0.5 done 12967 12968#@cli expand_y : size_y>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 12969#@cli : Expand selected images along the y-axis. 12970#@cli : Default value: 'boundary_conditions=1'. 12971#@cli : $ image.jpg expand_y 30,0 12972expand_y : check "$1>=0 && ${2=1}>=0 && $2<=3" 12973 e[^-1] "Expand image$? along the y-axis with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 12974 boundary conditions." 12975 repeat $! r[$>] 100%,{$>,h+2*$1},100%,100%,0,$2,0.5,0.5,0.5 done 12976 12977#@cli expand_z : size_z>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 12978#@cli : Expand selected images along the z-axis. 12979#@cli : Default value: 'boundary_conditions=1'. 12980expand_z : check "$1>=0 && ${2=1}>=0 && $2<=3" 12981 e[^-1] "Expand image$? along the z-axis with size $1 and "${"arg 1+$2,dirichlet,neumann,periodic,mirror"}" 12982 boundary conditions." 12983 repeat $! r[$>] 100%,100%,{$>,d+2*$1},100%,0,$2,0.5,0.5,0.5 done 12984 12985#@cli extract : "condition",_output_type={ 0=xyzc-coordinates | 1=xyz-coordinates | 2=scalar-values | 3=vector-values } 12986#@cli : Extract a list of coordinates or values from selected image, where 12987#@cli : specified mathematical condition holds. 12988#@cli : For N coordinates matching, result is a 1xNx1x4 image. 12989#@cli : Default values: 'output_type=0'. 12990#@cli : $ sp lena +extract "norm(I)>128",3 12991extract : check "isin(${2=0},0,1,2,3)" 12992 s0,s1,s2,s3=xyzc-coordinates,xyz-coordinates,scalar-values,vector-values 12993 e[^-1] "Extract "$s$2" from image$? verifying condition '$1'." 12994 str=">"${-math_lib}"begin(run('1,32,1,',arg(1+$2,4,3,1,s)));($1)?(" 12995 if $2==0 str.="dar_insert(#-1,[x,y,z,c]));i" 12996 elif $2==1 str.="dar_insert(#-1,[x,y,z]));I" 12997 elif $2==2 str.="dar_insert(#-1,i));i" 12998 else str.="dar_insert(#-1,I));I" 12999 fi 13000 str.=";end(resize(#-1,1,dar_size(#-1),1,s(#-1),0))" 13001 repeat $! nm={$>,n} eval[$>] $str nm. $nm rv[$>,-1] rm. done 13002 13003#@cli extract_region : [label_image],_extract_xyz_coordinates={ 0 | 1 },_label_1,...,_label_M 13004#@cli : Extract all pixels of selected images whose corresponding label in '[label_image]' is equal to 'label_m', 13005#@cli : and output them as M column images. 13006#@cli : Default value: 'extract_xyz_coordinates=0'. 13007#@cli : $ image.jpg +blur 3 quantize. 4,0 +extract_region[0] [1],0,1,3 13008extract_region : check ${"is_image_arg $1"}" && isnum(${2=0})" 13009 if $#<3 e[0--3] "Extract pixels of image$? for labels [] in image $1, with"${"arg 1+!!$2,out"}" coordinates 13010 -> no labels provided, ignoring." return fi 13011 e[^-1] "Extract pixels of image$? for labels {${3--1}} in image $1, with"${"arg 1+!!$2,out"}" coordinates." 13012 pass$1 mv. 0 repeat $!-1 l[0,{1+$<}] nm={n} 13013 1,16,1,{s+($2?3:0)} if $#>3 .x{$#-3} fi 13014 f[0] ">"${-math_lib}" 13015 begin( 13016 const N = iM + 1; # Number of labels 13017 R = [ ${3--1} ]; # Requested labels 13018 hash = vectorN(0); # Correspondence table 13019 repeat (size(R),k, hash[R[k]] = k + 2); 13020 ); 13021 (ind = hash[i])>0?( 13022 $2?dar_insert(#ind,[ I(#1),x,y,z ]):dar_insert(#ind,I(#1)); 13023 ); i; 13024 end( 13025 repeat (l - 2,k, resize(#k + 2,1,dar_size(#k + 2),1,-100,0)) 13026 )" 13027 rm[1] nm $nm 13028 endl done rm[0] 13029 13030#@cli montage : "_layout_code",_montage_mode={ 0<=centering<=1 | 2<=scale+2<=3 },\ 13031# _output_mode={ 0=single layer | 1=multiple layers },"_processing_command" 13032#@cli : Create a single image montage from selected images, according to specified layout code : 13033#@cli : - 'X' to assemble all images using an automatically estimated layout. 13034#@cli : - 'H' to assemble all images horizontally. 13035#@cli : - 'V' to assemble all images vertically. 13036#@cli : - 'A' to assemble all images as an horizontal array. 13037#@cli : - 'B' to assemble all images as a vertical array. 13038#@cli : - 'Ha:b' to assemble two blocks 'a' and 'b' horizontally. 13039#@cli : - 'Va:b' to assemble two blocks 'a' and 'b' vertically. 13040#@cli : - 'Ra' to rotate a block 'a' by 90 deg. ('RRa' for 180 deg. and 'RRRa' for 270 deg.). 13041#@cli : - 'Ma' to mirror a block 'a' along the X-axis ('MRRa' for the Y-axis). 13042#@cli : A block 'a' can be an image index (treated periodically) or a nested layout expression 'Hb:c','Vb:c','Rb' or 13043#@cli : 'Mb' itself. 13044#@cli : For example, layout code 'H0:V1:2' creates an image where image [0] is on the left, and images [1] and [2] 13045#@cli : vertically packed on the right. 13046#@cli : Default values: 'layout_code=X', 'montage_mode=2', output_mode='0' and 'processing_command=""'. 13047#@cli : $ image.jpg sample ? +plasma[0] shape_cupid 256 normalize 0,255 frame 3,3,0 frame 10,10,255 to_rgb \ 13048# +montage A +montage[^-1] H1:V0:VH2:1H0:3 13049montage : check "isnum(${2=2}) && $2>=0 && $2<=3" skip "${1=X}",${3=0},"${4=}" 13050 if $2<=1 e[0--3] "Create aligned montage from image$?, with layout code '$1' and centering $2." 13051 else e[0--3] "Create scaled montage from image$?, with layout code '$1' and scale "{$2-2}"." 13052 fi 13053 to_colormode 0 13054 13055 # Manage automatic layout. 13056 if lowercase('"$1"')=='x' +l 13057 repeat $! nm[$>] $> done 13058 repeat $!-1 13059 if {-2,w>h}" && "w>h mode=V # Both landscape. 13060 elif {-2,h>w}" && "h>w mode=H # Both portrait. 13061 elif {-2,w>h}" && "h>w # Landscape - portrait. 13062 if {-2,h/w}<(w/h) mode=V else mode=H fi 13063 else # Portrait - landscape. 13064 if {-2,w/h}<(h/w) mode=H else mode=V fi 13065 fi 13066 name=$mode{-2,n}:{n} 13067 montage[-2,-1] $mode,$2 13068 mv. 0 nm[0] $name 13069 done 13070 layout={0,n} 13071 rm endl montage $layout,$2,$3,"$4" 13072 13073 else # Non-automatic layout. 13074 13075 # Format and check validity of layout code. 13076 N=$! 13077 l[] _scode="$1" _mode=$2 13078 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. 13079 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. 13080 elif s=lowercase('"$1"');s=='a'||s=='b' # Montage as an array. 13081 if $N<2 return fi 13082 nr={round(sqrt($N))} nc={round($N/$nr,1,1)} # Horizontal array. 13083 if lowercase('"$1"')=='b' n=$nr nr=$nc nc=$n fi # Vertical array. 13084 $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 13085 if $nr>1 i[0] {$nr-1},1,1,1,-2 a x fi y 13086 else # Other complex montage. 13087 ('"$1"') f "if(i==72 || i==104,-1, 13088 if(i==86 || i==118,-2, 13089 if(i==82 || i==114,-3, 13090 if(i==77 || i==109,-4, 13091 if(i>=48 && i<=57,i-48,-5)))))" 13092 s +,-1 s +,-2 s +,-3 s +,-4 s +,-5 13093 repeat $! l[$>] if im>=0 ++. 48 =.. {t} rm. rows 0 fi endl done a y discard -5 13094 fi 13095 f 'if(i<0,i,i%$N)' 13096 endl 13097 if $!==$N rm return fi # Empty layout code. 13098 nm[^-1] 0 repeat h c={i[$>]} # Duplicate multiple references. 13099 if $c>=0 if {$c,n} i.. [$c] i={$!-2} =. $i,0,$> ref$i=$c else nm[$c] 1 ref$c=$c fi fi 13100 done 13101 _code={^} _lcode={narg($_code)} rm. 13102 13103 # Determine image positions and sizes. 13104 N=$! repeat $N ($>,0,0,{$>,w},{$>,h},0,0,0) done 13105 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 13106 onfail error[0--3] "Too many input images." 13107 endl 13108 13109 # Render montage. 13110 if narg("$4") m "__montage : $4 k[0]" 13111 else m "__montage : if $""7%2 mirror x fi if $""8%2 mirror y fi rotate {90*$""6} 13112 r {max(1,round($""4,1,1))},{max(1,round($""5,1,1))},1,100%,3" 13113 fi 13114 13115 s=${max_s[^-1]} 13116 repeat h 13117 i={i(0,$>)} xi={i(1,$>)} yi={i(2,$>)} wi={i(3,$>)} hi={i(4,$>)} ai={i(5,$>)} mxi={i(6,$>)} myi={i(7,$>)} 13118 if $3||!$> i.. $w,$h,1,$s fi 13119 __montage[$i] ${ref$i},$xi,$yi,{max(1,$wi)},{max(1,$hi)},$ai,$mxi,$myi 13120 j.. [$i],$xi,$yi 13121 done 13122 um __montage 13123 rm[0-{$N-1},-1] 13124 13125 fi 13126 nm "[Montage '$1']" 13127 13128_montage : 13129 if $_p>$_lcode error "Command 'montage': Incomplete layout code '"$_scode"'." fi 13130 c={arg($_p,$_code)} 13131 if $c>=0 _p+=1 u $c # Single index. 13132 elif $c==-4 # Mirror. 13133 _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 13134 elif $c==-3 # Rotation. 13135 _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 13136 else # Merge. 13137 _p+=1 13138 l=${-_montage} lw={$l,@3} lh={$l,@4} 13139 r=${-_montage} rw={$r,@3} rh={$r,@4} 13140 13141 if $c==-1 # Horizontal merge. 13142 if $_mode<2 13143 h={max($lh,$rh)} 13144 +[$l] '0,0,{($h-$lh)*min(1,$_mode)},0,0,0,0,0' 13145 +[$r] '0,$lw,{($h-$rh)*min(1,$_mode)},0,0,0,0,0' 13146 else 13147 h={($_mode-2)*max($lh,$rh)+(3-$_mode)*min($lh,$rh)} 13148 lf={$h/$lh} rf={$h/$rh} lw={$lw*$lf} rw={$rw*$rf} 13149 *[$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' 13150 fi 13151 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 13152 13153 else # Vertical merge. 13154 if $_mode<2 13155 w={max($lw,$rw)} 13156 +[$l] '0,{($w-$lw)*min(1,$_mode)},0,0,0,0,0,0' 13157 +[$r] '0,{($w-$rw)*min(1,$_mode)},$lh,0,0,0,0,0' 13158 else 13159 w={($_mode-2)*max($lw,$rw)+(3-$_mode)*min($lw,$rw)} 13160 lf={$w/$lw} rf={$w/$rw} lh={$lh*$lf} rh={$rh*$rf} 13161 *[$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' 13162 fi 13163 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 13164 fi 13165 u $l 13166 fi 13167 13168#@cli mirror : { x | y | z }...{ x | y | z } : (+) 13169#@cli : Mirror selected images along specified axes. 13170#@cli : $ image.jpg +mirror y +mirror[0] c 13171#@cli : $ image.jpg +mirror x +mirror y append_tiles 2,2 13172 13173#@cli permute : permutation_string : (+) 13174#@cli : Permute selected image axes by specified permutation. 13175#@cli : 'permutation' is a combination of the character set {x|y|z|c}, 13176#@cli : e.g. 'xycz', 'cxyz', ... 13177#@cli : $ image.jpg permute yxzc 13178 13179#@cli r : eq. to 'resize'. : (+) 13180 13181#@cli resize : {[image_w] | width>0[%]},_{[image_h] | height>0[%]},_{[image_d] | depth>0[%]},\ 13182# _{[image_s] | spectrum>0[%]},_interpolation,_boundary_conditions,_ax,_ay,_az,_ac : (+) 13183#@cli : Resize selected images with specified geometry. 13184#@cli : (eq. to 'r').\n 13185#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 13186# 4=grid | 5=bicubic | 6=lanczos }. 13187#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 13188#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 13189#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13190#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 13191#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0 or 4' 13192#@cli : (set to '0' by default, must be defined in range [0,1]). 13193#@cli : Default values: 'interpolation=1', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 13194#@cli : $ image.jpg +resize[-1] 256,128,1,3,2 +resize[-1] 120%,120%,1,3,0,1,0.5,0.5 \ 13195# +resize[-1] 120%,120%,1,3,0,0,0.2,0.2 +resize[-1] [0],[0],1,3,4 13196 13197#@cli ri : eq. to 'resize_as_image'. 13198ri : skip "${2=1},${3=0},${4=0},${5=0},${6=0},${7=0}" # Faster than the non-shortcut version of the command 13199 pass$1 r[^-1] .,.,.,.,${2--1} rm. 13200 13201#@cli resize_as_image : [reference],_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 13202#@cli : Resize selected images to the geometry of specified [reference] image. 13203#@cli : (eq. to 'ri'). 13204#@cli : Default values: 'interpolation=1', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 13205#@cli : $ image.jpg sample duck +resize_as_image[-1] [-2] 13206resize_as_image : check ${"is_image_arg $1"}" && isint(${2=1}) && $2>=-1 && $2<=6 && "\ 13207 "isint(${3=0}) && $3>=0 && $3<=3 && isnum(${4=0}) && isnum(${5=0}) && isnum(${6=0}) && isnum(${7=0})" 13208 pass$1 r[^-1] .,.,.,.,${2--1} rm. 13209 13210#@cli resize_mn : width[%]>=0,_height[%]>=0,_depth[%]>=0,_B_value,_C_value 13211#@cli : Resize selected images with Mitchell-Netravali filter (cubic). 13212#@cli : For details about the method, see: <https://de.wikipedia.org/wiki/Mitchell-Netravali-Filter>. 13213#@cli : Default values: 'height=100%', 'depth=100%', 'B=0.3333' and 'C=0.3333'. 13214#@cli : $ image.jpg resize2dx 32 resize_mn 800%,800% 13215resize_mn : check "${2=100%}>=0 && ${3=100%}>=0" skip "${4=0.333},${5=0.333}" 13216 e[^-1] "Resize image$? to $1x$2x$3 using Mitchell-Netravali filter (B=$4, C=$5)." 13217 lib="const B = $4; const C = $5; const boundary = 1; const interp = 0; 13218 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 13219 + ( (B/2+2*C)*P0 + (2*B+C-3)*P1 + (-5*B/2-2*C+3)*P2 -C*P3)*d^2 13220 + ( (-B/2-C)*P0 + (B/2+C)*P2)*d 13221 + B/6*P0 + (-B/3+1)*P1 + B/6*P2);" 13222 repeat $! l[$>] nm={n} 13223 nw={${"is_percent $1"}?max(1,round($1*w)):round($1)} 13224 nh={${"is_percent $2"}?max(1,round($2*h)):round($2)} 13225 nd={${"is_percent $3"}?max(1,round($3*d)):round($3)} 13226 if !$nw" || "!$nh" || "!$nd rm 0 13227 elif !w rm $nw,$nh,$nd,1 13228 else 13229 if w==1||$nw<w r $nw,100%,100%,100%,{w==1?1:2} 13230 elif $nw>w 13231 $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); 13232 P2 = I(#-1,X+1); P3 = I(#-1,X+2); mn(P0,P1,P2,P3,d);" k. 13233 fi 13234 if h==1||$nh<h 13235 r 100%,$nh,100%,100%,{h==1?1:2} 13236 elif $nh!=h 13237 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); 13238 P2 = I(#-1,x,Y+1); P3 = I(#-1,x,Y+2); mn(P0,P1,P2,P3,d);" k. 13239 fi 13240 if d==1" || "$nd<d 13241 r 100%,100%,$nd,100%,{d==1?1:2} 13242 elif $nd!=d 13243 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); 13244 P2 = I(#-1,x,y,Z+1); P3 = I(#-1,x,y,Z+2); mn(P0,P1,P2,P3,d);" k. 13245 fi 13246 fi 13247 nm $nm 13248 endl done 13249 13250#@cli resize_pow2 : _interpolation,_boundary_conditions,_ax,_ay,_az,_ac 13251#@cli : Resize selected images so that each dimension is a power of 2. 13252#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 13253# 4=grid | 5=bicubic | 6=lanczos }. 13254#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 13255#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 13256#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13257#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 13258#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 13259#@cli : (set to '0' by default, must be defined in range [0,1]). 13260#@cli : Default values: 'interpolation=0', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 13261#@cli : $ image.jpg +resize_pow2[-1] 0 13262resize_pow2 : check "isint(${1=0}) && $1>=-1 && $1<=6" skip ${2=0},${3=0},${4=0},${5=0},${6=0} 13263 e[^-1] "Resize image$? so that each dimension is a power of 2." 13264 repeat $! 13265 r[$>] {$>,2^(round(log2(w),1,1))},{$>,2^(round(log2(h),1,1))},{$>,2^(round(log2(d),1,1))},100%,${1-6} 13266 done 13267 13268#@cli rr2d : eq. to 'resize_ratio2d'. 13269rr2d : 13270 _gmic_s="$?" v + _resize_ratio2d $* 13271 13272#@cli resize_ratio2d : width>0,height>0,_mode={ 0=inside | 1=outside | 2=padded },0=<_interpolation<=6 13273#@cli : Resize selected images while preserving their aspect ratio. 13274#@cli : (eq. to 'rr2d'). 13275#@cli : Default values: 'mode=0' and 'interpolation=6'. 13276resize_ratio2d : 13277 _gmic_s="$?" v + _$0 $* 13278 13279_resize_ratio2d : check "$1>0 && $2>0 && ${3=0}>=0 && $3<=2 && ${4=6}>=0 && $4<=6" 13280 e[0--3] "Resize 2D image"$_gmic_s" to $1x$2 with ratio-"${arg\ 1+$3,inside,outside,padded}\ 13281 " mode and interpolation type $4." 13282 repeat $! 13283 ratio={$>,if($3==1,max($1/w,$2/h),min($1/w,$2/h))} 13284 r[$>] {$>,max(1,w*$ratio)},{$>,max(1,h*$ratio)},100%,100%,$4 13285 done 13286 if $3==2 r $1,$2,100%,100%,0,0,0.5,0.5 fi 13287 13288 13289#@cli r2dx : eq. to 'resize2dx'. 13290r2dx : 13291 _gmic_s="$?" v + _resize2dx $* 13292 13293#@cli resize2dx : width[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 13294#@cli : Resize selected images along the x-axis, preserving 2D ratio. 13295#@cli : (eq. to 'r2dx').\n 13296#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 13297# 4=grid | 5=bicubic | 6=lanczos }. 13298#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 13299#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 13300#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13301#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 13302#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 13303#@cli : (set to '0' by default, must be defined in range [0,1]). 13304#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 13305#@cli : $ image.jpg +resize2dx 100,2 append x 13306resize2dx : 13307 _gmic_s="$?" v + _$0 $* 13308 13309_resize2dx : check "$1>0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 13310 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 13311 e[0--3] "Resize 2D image"$_gmic_s" to $1 pixels along the x-axis, preserving 2D ratio." 13312 repeat $! l[$>] 13313 size={if(${is_percent\ $1},$1*w,$1)} 13314 r {max(1,$size)},{max(1,h*$size/w)},100%,100%,${2-7} 13315 endl done 13316 13317#@cli r2dy : eq. to 'resize2dy'. 13318r2dy : 13319 _gmic_s="$?" v + _resize2dy $* 13320 13321#@cli resize2dy : height[%]>=0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 13322#@cli : Resize selected images along the y-axis, preserving 2D ratio. 13323#@cli : (eq. to 'r2dy').\n 13324#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 13325# 4=grid | 5=bicubic | 6=lanczos }. 13326#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 13327#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 13328#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13329#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 13330#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 13331#@cli : (set to '0' by default, must be defined in range [0,1]). 13332#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 13333#@cli : $ image.jpg +resize2dy 100,2 append x 13334resize2dy : 13335 _gmic_s="$?" v + _$0 $* 13336 13337_resize2dy : check "$1>=0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 13338 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 13339 e[0--3] "Resize 2D image"$_gmic_s" to $1 pixels along the y-axis, preserving 2D ratio." 13340 repeat $! l[$>] 13341 size={if(${is_percent\ $1},$1*h,$1)} 13342 r {max(1,w*$size/h)},{max(1,$size)},100%,100%,${2-7} 13343 endl done 13344 13345#@cli r3dx : eq. to 'resize3dx'. 13346r3dx : 13347 _gmic_s="$?" v + _resize3dx $* 13348 13349#@cli resize3dx : width[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 13350#@cli : Resize selected images along the x-axis, preserving 3D ratio. 13351#@cli : (eq. to 'r3dx').\n 13352#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 13353# 4=grid | 5=bicubic | 6=lanczos }. 13354#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 13355#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 13356#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13357#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 13358#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 13359#@cli : (set to '0' by default, must be defined in range [0,1]). 13360#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 13361resize3dx : 13362 _gmic_s="$?" v + _$0 $* 13363 13364_resize3dx : check "$1>0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 13365 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 13366 e[0--3] "Resize 3D image"$_gmic_s" to $1 pixels along the x-axis, preserving 3D ratio." 13367 repeat $! l[$>] 13368 size={if(${is_percent\ $1},$1*w,$1)} 13369 r {max(1,$size)},{max(1,h*$size/w)},{max(1,d*$size/w)},100%,${2-7} 13370 endl done 13371 13372#@cli r3dy : eq. to 'resize3dy'. 13373r3dy : 13374 _gmic_s="$?" v + _resize3dy $* 13375 13376#@cli resize3dy : height[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 13377#@cli : Resize selected images along the y-axis, preserving 3D ratio. 13378#@cli : (eq. to 'r3dy').\n 13379#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 13380# 4=grid | 5=bicubic | 6=lanczos }. 13381#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 13382#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 13383#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13384#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 13385#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 13386#@cli : (set to '0' by default, must be defined in range [0,1]). 13387#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 13388resize3dy : 13389 _gmic_s="$?" v + _$0 $* 13390 13391_resize3dy : check "$1>0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 13392 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 13393 e[0--3] "Resize 3D image"$_gmic_s" to $1 pixels along the y-axis, preserving 3D ratio." 13394 repeat $! l[$>] 13395 size={if(${is_percent\ $1},$1*h,$1)} 13396 r {max(1,w*$size/h)},{max(1,$size)},{max(1,d*$size/h)},100%,${2-7} 13397 endl done 13398 13399#@cli r3dz : eq. to 'resize3dz'. 13400r3dz : 13401 _gmic_s="$?" v + _resize3dz $* 13402 13403#@cli resize3dz : depth[%]>0,_interpolation,_boundary_conditions,_ax,_ay,_az,_ac 13404#@cli : Resize selected images along the z-axis, preserving 3D ratio. 13405#@cli : (eq. to 'r3dz').\n 13406#@cli : 'interpolation' can be { -1=none (memory content) | 0=none | 1=nearest | 2=average | 3=linear | \ 13407# 4=grid | 5=bicubic | 6=lanczos }. 13408#@cli : 'boundary_conditions' has different meanings, according to the chosen 'interpolation' mode : 13409#@cli : . When 'interpolation=={ -1 | 1 | 2 | 4 }', 'boundary_conditions' is meaningless. 13410#@cli : . When 'interpolation==0', 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13411#@cli : . When 'interpolation=={ 3 | 5 | 6 }', 'boundary_conditions' can be { 0=none | 1=neumann }. 13412#@cli : 'ax,ay,az,ac' set the centering along each axis when 'interpolation=0' 13413#@cli : (set to '0' by default, must be defined in range [0,1]). 13414#@cli : Default values: 'interpolation=3', 'boundary_conditions=0' and 'ax=ay=az=ac=0'. 13415resize3dz : 13416 _gmic_s="$?" v + _$0 $* 13417 13418_resize3dz : check "$1>0 && ${2=3}>=0 && $2<=6 && ${3=0}>=0 && $3<=3 && ${4=0}>=0 && $4<=1 && ${5=0}>=0 && $5<=1 && 13419 ${6=0}>=0 && $6<=1 && ${7=0}>=0 && $7<=1" 13420 e[0--3] "Resize 3D image"$_gmic_s" to $1 pixels along the z-axis, preserving 3D ratio." 13421 repeat $! l[$>] 13422 size={if(${is_percent\ $1},$1*d,$1)} 13423 r[$>] {max(1,w*$size/d)},{max(1,h*$size/d)},{max(1,$size)},100%,${2-7} 13424 endl done 13425 13426#@cli rotate : angle,_interpolation,_boundary_conditions,_center_x[%],_center_y[%] : \ 13427# u,v,w,angle,interpolation,boundary_conditions,_center_x[%],_center_y[%],_center_z[%] : (+) 13428#@cli : Rotate selected images with specified angle (in deg.), and optionally 3D axis (u,v,w). 13429#@cli : 'interpolation' can be { 0=none | 1=linear | 2=bicubic }. 13430#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13431#@cli : When a rotation center (cx,cy,_cz) is specified, the size of the image is preserved. 13432#@cli : Default values: 'interpolation=1', 'boundary_conditions=0' and 'center_x=center_y=(undefined)'. 13433#@cli : $ image.jpg +rotate -25,1,2,50%,50% rotate[0] 25 13434 13435#@cli rotate_tileable : angle,_max_size_factor>=0 13436#@cli : Rotate selected images by specified angle and make them tileable. 13437#@cli : If resulting size of an image is too big, the image is replaced by a 1x1 image. 13438#@cli : Default values: 'max_size_factor=8'. 13439rotate_tileable : check ${2=8}>=0 13440 e[^-1] "Rotate image$? with angle $1 deg. and make them tileable." 13441 13442 # Reduce angle to known fraction. 13443 angle={$1%360} 13444 if $angle>=270 rotate 270 angle-=270 13445 elif $angle>=180 rotate 180 angle-=180 13446 elif $angle>=90 rotate 90 angle-=90 13447 fi 13448 # List of known fractions. 13449 (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) 13450 s. x,2 +/[-2,-1] atan. *. {180/pi} # Compute corresponding angles. 13451 ($angle) index. .. rm.. 13452 p={-3,@{^}} q={-2,@{^}} rm[-3--1] # Find nearest fraction p/q to atan(angle). 13453 if !$p||!$q return fi 13454 13455 repeat $! l[$>] 13456 # Compute width and height of tile. 13457 theta={atan2($p,$q)} 13458 gcd=${gcd" "{h*$q},{w*$p}} 13459 pw={h*$q/$gcd} 13460 nw={round($pw*w/cos($theta))} 13461 gcd=${gcd" "{h*$p},{w*$q}} 13462 qh={w*$q/$gcd} 13463 nh={round($qh*h/cos($theta))} 13464 13465 # Rotate and make tileable (may result in very large images!). 13466 if !$2" || "($nw<$2*w" && "$nh<$2*h) 13467 r {1.5*$nw},{1.5*$nh},1,100%,0,2 13468 rotate {$theta*180/pi},1,2,50%,50% 13469 r $nw,$nh,1,100%,0,2,0.5,0.5 13470 else error[0--4] "Command '$0': Invalid image dimension "({w},{h},{d},{s}). 13471 fi 13472 endl done 13473 13474#@cli rows : { [image0] | y0[%] },_{ [image1] | y1[%] } : (+) 13475#@cli : Keep only specified rows of selected images. 13476#@cli : Dirichlet boundary conditions are used when specified rows are out of range. 13477#@cli : $ image.jpg rows -25%,50% 13478 13479#@cli scale2x 13480#@cli : Resize selected images using the Scale2x algorithm. 13481#@cli : $ image.jpg threshold 50% resize 50%,50% +scale2x 13482scale2x : 13483 e[^-1] "Double xy-dimensions of image$?, using Scale2x algorithm." 13484 repeat $! l[$>] 13485 r 200%,200% 13486 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); 13487 !dy*(!dx*if(C==A&&C!=D&&A!=B,A,i) + dx*if(A==B&&A!=C&&B!=D,B,i)) + 13488 dy*(dx*if(B==D&&B!=A&&D!=C,D,i) + !dx*if(D==C&&D!=B&&C!=A,C,i))" 13489 endl done 13490 13491#@cli scale3x 13492#@cli : Resize selected images using the Scale3x algorithm. 13493#@cli : $ image.jpg threshold 50% resize 33%,33% +scale3x 13494scale3x : 13495 e[^-1] "Triple xy-dimensions of image$?, using Scale3x algorithm." 13496 repeat $! l[$>] 13497 r 300%,300% 13498 f "dx=x%3;dy=y%3;c0=!dx;c1=(dx==1);c2=(dx==2); 13499 A=j(-3,-3,0,0,0,1);B=j(0,-3,0,0,0,1);C=j(3,-3,0,0,0,1); 13500 D=j(-3,0,0,0,0,1);F=j(3,0,0,0,0,1); 13501 G=j(-3,3,0,0,0,1);H=j(0,3,0,0,0,1);I=j(3,3,0,0,0,1); 13502 !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) + 13503 c2*if(B==F&&B!=D&&F!=H,F,i)) + 13504 (dy==1)*(c0*if((H==D&&H!=F&&D!=B&&i!=A)||(D==B&&D!=H&&B!=F&&i!=G),D,i) + c1*i + 13505 c2*if((B==F&&B!=D&&F!=H&&i!=I)||(F==H&&F!=B&&H!=D&&i!=C),F,i)) + 13506 (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) + 13507 c2*if(F==H&&F!=B&&H!=D,F,i))" 13508 endl done 13509 13510#@cli scale_dcci2x : _edge_threshold>=0,_exponent>0,_extend_1px={ 0=false | 1=true } 13511#@cli : Double image size using directional cubic convolution interpolation, 13512#@cli : as described in <https://en.wikipedia.org/wiki/Directional_Cubic_Convolution_Interpolation>. 13513#@cli : Default values: 'edge_threshold=1.15', 'exponent=5' and 'extend_1px=0'. 13514#@cli : $ image.jpg +scale_dcci2x , 13515scale_dcci2x : check "${1=1.15}>=0 && ${2=5}>=0" skip ${3=0} 13516 e[^-1] "Double xy-dimensions of image$?, using DCCI2x algorithm." 13517 repeat $! l[$>] 13518 r {2*w-(!$3)},{2*h-(!$3)},1,100%,4 13519 13520 # Estimate diagonal values. 13521 f "begin( 13522 const threshold = $1; 13523 const exponent = $2; 13524 interpolation = 0; 13525 boundary = 1; 13526 j1(x,y) = P[7*y + x + 24]; # eq. to 'j(x,y)', but faster 13527 j2(x,y) = P[7*x - y + 24]; # eq. to 'j(-y,x)', but faster 13528 interp(k) = -k#(-3,-3) + 9*k#(-1,-1) + 9*k#(1,1) - k#(3,3); 13529 d(k) = sum(abs([ 13530 k#(-1,-3) - k#(-3,-1), k#(1,-3) - k#(-1,-1), k#(3,-3) - k#(1,-1), 13531 k#(-1,-1) - k#(-3,1), k#(1,-1) - k#(-1,1), k#(3,-1) - k#(1,1), 13532 k#(-1,1) - k#(-3,3), k#(1,1) - k#(-1,3), k#(3,1) - k#(1,3) 13533 ])); 13534 ); 13535 if (!((x*y)%2),i, 13536 ref(crop(x - 3,y - 3,0,c,7,7,1,1),P); 13537 d1 = d(j1); 13538 d2 = d(j2); 13539 ratio = (1 + d1)/(1 + d2); 13540 value = ratio>threshold ? interp(j1): # Up-right edge 13541 ratio<(1/threshold) ? interp(j2): # Down-right edge 13542 (w1 = 1/(1 + d1^exponent); w2 = 1/(1 + d2^exponent); 13543 (interp(j1)*w1 + interp(j2)*w2)/(w1 + w2)); # Smooth area 13544 value/=16)" 13545 13546 # Estimate remaining values. 13547 f "begin( 13548 const threshold = $1; 13549 const exponent = $2; 13550 interpolation = 0; 13551 boundary = 1; 13552 j1(x,y) = P[7*y + x + 24]; # eq. to 'j(x,y)', but faster 13553 j2(x,y) = P[7*x - y + 24]; # eq. to 'j(-y,x)', but faster 13554 interp(k) = -k#(0,-3) + 9*k#(0,-1) + 9*k#(0,1) - k#(0,3); 13555 d(k) = sum(abs([ 13556 k#(-1,-2) - k#(1,-2), 13557 k#(-2,-1) - k#(0,-1), k#(0,-1) - k#(2,-1), 13558 k#(-3,0) - k#(-1,0), k#(-1,0) - k#(1,0), k#(1,0) - k#(3,0), 13559 k#(-2,1) - k#(0,1), k#(0,1) - k#(2,1), 13560 k#(-1,2) - k#(1,2) 13561 ])); 13562 ); 13563 if ((x%2) + (y%2)!=1,i, 13564 ref(crop(x - 3,y - 3,0,c,7,7,1,1),P); 13565 d1 = d(j1); 13566 d2 = d(j2); 13567 ratio = (1 + d1)/(1 + d2); 13568 value = ratio>threshold ? interp(j1) : # Horizontal edge 13569 ratio<(1/threshold) ? interp(j2) : # Vertical edge 13570 (w1 = 1/(1 + d1^exponent); w2 = 1/(1 + d2^exponent); 13571 (interp(j1)*w1 + interp(j2)*w2)/(w1 + w2)); # Smooth area 13572 value/=16)" 13573 endl done 13574 13575#@cli seamcarve : _width[%]>=0,_height[%]>=0,_is_priority_channel={ 0 | 1 },_is_antialiasing={ 0 | 1 },\ 13576# _maximum_seams[%]>=0 13577#@cli : Resize selected images with specified 2D geometry, using the seam-carving algorithm. 13578#@cli : Default values: 'height=100%', 'is_priority_channel=0', 'is_antialiasing=1' and 'maximum_seams=25%'. 13579#@cli : $ image.jpg seamcarve 60% 13580# The main code of this algorithm has been done by Andy (Garagecoder). 13581seamcarve : check "${2=100%}>=0 && ${5=25%}>=0" skip ${3=0},${4=1} 13582 e[^-1] "Resize image$? to $1x$2 using seam-carving algorithm, "${arg\ 1+!$3,with,without}" priority channel, "\ 13583 ${arg\ 1+!$4,with,without}" anti-aliasing and maximum seams $5." 13584 repeat $! l[$>] 13585 nw={max(1,round(if(${is_percent\ $1},$1*w,$1)))} 13586 nh={max(1,round(if(${is_percent\ $2},$2*h,$2)))} 13587 if $nw!=w _seamcarve $nw,$3,$4,$5 fi 13588 if $nh!=h transpose _seamcarve $nh,$3,$4,$5 transpose fi 13589 endl done 13590 13591# Subroutine to remove/add vertical seams/ 13592# $1 = desired width. 13593# $2 = is_priority_channel={ 0 | 1 } 13594# $3 = is_antialiasing={ 0 | 1 } 13595# $4 = max number of seams added/removed at once. 13596_seamcarve : 13597 do 13598 max_seams={max(1,round(if(${is_percent\ $4},$4*w,$4)))} 13599 ssms={max(min(round($1-w),w),1-w)} 13600 sms={min($max_seams,abs($ssms))} 13601 13602 # Compute potential map. 13603 if $2 s[0] c,{1-s} /. 256 fi 13604 +gradient[0] a[-2,-1] c abs. compose_channels. + n. 0,1 13605 if $2 +. .. a[0,1] c fi 13606 13607 # Add x-coordinates channel for anti-aliasing. 13608 if $3 100%,1,1,1,x r. [0],[0] a[0,-1] c fi 13609 13610 # Calculate low matrix (backwards propagation). 13611 . 13612 repeat h 13613 +rows. {$<+1} erode. 3 13614 j.. .,0,$<,0,0,-1 rm. 13615 done 13616 13617 # Initialise seams, top matrix. 13618 100%,100% +rows[1] 0 13619 nm[1] grad nm[2] low nm[3] seam nm[4] top 13620 13621 repeat h#0-1 nr={$>+1} 13622 +rows[low] $nr 13623 13624 # Find optimum matches between two 1D matrices. 13625 +*[4,5] +shift[4] 1 *. [5] +shift[5] 1 *. [4] 13626 +[-2,-1] j[5] [4] a[-3--1] c 13627 f. ">if(c,i,max(j(-1)+j(0,0,0,1),j(-2)+j(0,0,0,2)))" 13628 s. c shift... 1 +.. ... shift... 1 +[-3,-1] 13629 >[-2,-1] f. "<if(j(1)<0,1,-i)" 13630 13631 # Add matched row to seams. 13632 j[seam] .,0,$> 13633 13634 # Distribute matched pixels in top matrix. 13635 a[-2,-1] c f. "j(i,0,0,-1)" channels. 1 13636 13637 # Add next energy row to top matrix. 13638 +rows[grad] $nr +[top,-1] 13639 done 13640 13641 # Add / remove seams. 13642 max={iM*2} repeat $sms =. $max,{xm} done 13643 j[grad] .,0,100% rm[low,top] a[-2,-1] c 13644 f. "<if(c,i,j(j(0,0,0,1),1,0,0,0,1))" channels. 0 13645 +[0] 0.1 !=. $max 13646 w={w} h={h} s={0,s} 13647 if $ssms<0 * discard 0 r {$w-$sms},$h,1,$s,-1 # Remove seams. 13648 elif $ssms>0 # Add seams. 13649 -. 2 s[0] c 13650 repeat $s if $><($s-1) . fi a[$>,-1] c done 13651 permute cxyz a c discard -1 f "if(i<0,j(0,-1),i)" 13652 r {$w+$sms},$h,1,$s,-1 13653 fi 13654 13655 # Perform anti-aliasing step. 13656 if $3 13657 s c,{1-s} g. x,1 round !=. 1 13658 (0.5,0.5) +convolve[0] . rm.. 13659 j[0] .,0,0,0,0,1,[1] rm[-2,-1] 13660 fi 13661 13662 rprogress {a=w/$1;if(a<1,a*100,100/a)} 13663 while w!=$1 13664 13665#@cli shift : vx[%],_vy[%],_vz[%],_vc[%],_boundary_conditions,_interpolation={ 0=nearest_neighbor | 1=linear } : (+) 13666#@cli : Shift selected images by specified displacement vector. 13667#@cli : Displacement vector can be non-integer in which case linear interpolation should be chosen. 13668#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13669#@cli : Default value: 'boundary_conditions=0' and 'interpolation=0'. 13670#@cli : $ image.jpg +shift[0] 50%,50%,0,0,0 +shift[0] 50%,50%,0,0,1 +shift[0] 50%,50%,0,0,2 13671 13672#@cli shrink_x : size_x>=0 13673#@cli : Shrink selected images along the x-axis. 13674#@cli : $ image.jpg shrink_x 30 13675shrink_x : check "$1>=0" 13676 e[^-1] "Shrink image$? along the x-axis with size $1." 13677 repeat $! z[$>] $1,{$>,w-$1-1} done 13678 13679#@cli shrink_xy : size>=0 13680#@cli : Shrink selected images along the xy-axes. 13681#@cli : $ image.jpg shrink_xy 30 13682shrink_xy : check "$1>=0" 13683 e[^-1] "Shrink image$? along the xy-axes with size $1." 13684 repeat $! z[$>] $1,$1,{$>,w-$1-1},{$>,h-$1-1} done 13685 13686#@cli shrink_xyz : size>=0 13687#@cli : Shrink selected images along the xyz-axes. 13688shrink_xyz : check "$1>=0" 13689 e[^-1] "Shrink image$? along the xyz-axes with size $1." 13690 repeat $! z[$>] $1,$1,$1,{$>,w-$1-1},{$>,h-$1-1},{$>,d-$1-1} done 13691 13692#@cli shrink_y : size_y>=0 13693#@cli : Shrink selected images along the y-axis. 13694#@cli : $ image.jpg shrink_y 30 13695shrink_y : check "$1>=0" 13696 e[^-1] "Shrink image$? along the y-axis with size $1." 13697 repeat $! z[$>] 0,$1,100%,{$>,h-$1-1} done 13698 13699#@cli shrink_z : size_z>=0 13700#@cli : Shrink selected images along the z-axis. 13701shrink_z : check "$1>=0" 13702 e[^-1] "Shrink image$? along the z-axis with size $1." 13703 repeat $! z[$>] 0,0,$1,100%,100%,{$>,d-$1-1} done 13704 13705#@cli slices : { [image0] | z0[%] },_{ [image1] | z1[%] } : (+) 13706#@cli : Keep only specified slices of selected images. 13707#@cli : Dirichlet boundary conditions are used when specified slices are out of range. 13708 13709#@cli sort : _ordering={ + | - },_axis={ x | y | z | c } : (+) 13710#@cli : Sort pixel values of selected images. 13711#@cli : If 'axis' is specified, the sorting is done according to the data of the first column/row/slice/channel 13712#@cli : of selected images. 13713#@cli : Default values: 'ordering=+' and 'axis=(undefined)'. 13714#@cli : $ 64 rand 0,100 +sort display_graph 400,300,3 13715 13716#@cli s : eq. to 'split'. : (+) 13717 13718#@cli split : { x | y | z | c }...{ x | y | z | c },_split_mode : \ 13719# keep_splitting_values={ + | - },_{ x | y | z | c }...{ x | y | z | c },value1,_value2,... : (no arg) : (+) 13720#@cli : Split selected images along specified axes, or regarding to a sequence of scalar values 13721#@cli : (optionally along specified axes too). 13722#@cli : (eq. to 's').\n 13723#@cli : 'split_mode' can be { 0=split according to constant values | >0=split in N parts | \ 13724# <0=split in parts of size -N }. 13725#@cli : Default value: 'split_mode=-1'. 13726#@cli : $ image.jpg split c 13727#@cli : $ image.jpg split y,3 13728#@cli : $ image.jpg split x,-128 13729#@cli : $ 1,20,1,1,"1,2,3,4" +split -,2,3 append[1--1] y 13730#@cli : $ (1,2,2,3,3,3,4,4,4,4) +split x,0 append[1--1] y 13731 13732#@cli split_tiles : M!=0,_N!=0,_is_homogeneous={ 0 | 1 } 13733#@cli : Split selected images as a MxN array of tiles. 13734#@cli : If M or N is negative, it stands for the tile size instead. 13735#@cli : Default values: 'N=M' and 'is_homogeneous=0'. 13736#@cli : $ image.jpg +local split_tiles 5,4 blur 3,0 sharpen 700 append_tiles 4,5 endlocal 13737split_tiles : skip ${2=$1},${3=0} 13738 if $3 e[^-1] "Split image$? as a $1x$2 array of homogeneous tiles." 13739 else e[^-1] "Split image$? as a $1x$2 array of tiles." 13740 fi 13741 repeat $! l[$<] s y,$2 s x,$1 if $3 r [0],[0],100%,100%,0 fi endl done 13742 13743#@cli undistort : -1<=_amplitude<=1,_aspect_ratio,_zoom,_center_x[%],_center_y[%],_boundary_conditions 13744#@cli : Correct barrel/pincushion distortions occurring with wide-angle lens. 13745#@cli : References: 13746#@cli : [1] Zhang Z. (1999). Flexible camera calibration by viewing a plane from unknown orientation. 13747#@cli : [2] Andrew W. Fitzgibbon (2001). Simultaneous linear estimation of multiple view geometry and lens distortion. 13748#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13749#@cli : Default values: 'amplitude=0.25', 'aspect_ratio=0', 'zoom=0', 'center_x=center_y=50%' \ 13750# and 'boundary_conditions=0'. 13751undistort : check "${1=0.1}>=-1 && $1<=1 && ${6=0}>=0 && $6<=3" skip ${2=0},${3=0},${4=50%},${5=50%} 13752 e[^-1] "Undistort barrel/pincushion effect in image$?, with amplitude $1, aspect ratio $2, zoom factor $3, 13753 center ($4,$5) and "${"arg 1+$6,dirichlet,neumann,periodic,mirror"}" boundary conditions." 13754 repeat $! l[$>] 13755 center_x={${"is_percent $4"}?w*$4:$4} 13756 center_y={${"is_percent $5"}?h*$5:$5} 13757 f " 13758 const interpolation = 1; 13759 const boundary = $6; 13760 const center_x = "$center_x"; 13761 const center_y = "$center_y"; 13762 const alpha = cut($1,-0.999,0.999); 13763 const ratio = $2>=0?1+$2:1/(1-$2); 13764 const zoom = $3>=0?1+$3:1/(1-$3); 13765 const M = max(w,h); 13766 x = 2*(x - center_x)/(zoom*ratio*M); 13767 y = 2*(y - center_y)/(zoom*M); 13768 r = norm(x,y); 13769 nr = r/(1 - alpha*r^2); 13770 if (r>0, 13771 nx = nr/r*x; ny = nr/r*y, 13772 nx = x; ny = y 13773 ); 13774 x = 0.5*nx*ratio*M + center_x; 13775 y = 0.5*ny*M + center_y; 13776 I(x,y)" 13777 endl done 13778 13779#@cli y : eq. to 'unroll'. : (+) 13780 13781#@cli unroll : _axis={ x | y | z | c } : (+) 13782#@cli : Unroll selected images along specified axis. 13783#@cli : (eq. to 'y'). 13784#@cli : Default value: 'axis=y'. 13785#@cli : $ (1,2,3;4,5,6;7,8,9) +unroll y 13786 13787#@cli upscale_smart : width[%],_height[%],_depth,_smoothness>=0,_anisotropy=[0,1],sharpening>=0 13788#@cli : Upscale selected images with an edge-preserving algorithm. 13789#@cli : Default values: 'height=100%', 'depth=100%', 'smoothness=2', 'anisotropy=0.4' and 'sharpening=10'. 13790#@cli : $ image.jpg resize2dy 100 +upscale_smart 500%,500% append x 13791upscale_smart : skip ${2=100%},${3=100%} check "${4=2}>=0 && ${5=0.4}>=0 && $5<=1 && ${6=10}>=0" 13792 e[^-1] "Upscale image$? to $1x$2x$3, with smoothness $4, anisotropy $5 and sharpening $6." 13793 repeat $! l[$>] 13794 w={w} h={h} 13795 +r. $1,$2,$3,1,0 # Compute desired dimensions. 13796 if w<$w" && "h<$h # Test for downscaling 13797 rm. r. $1,$2,$3,100%,2 13798 else 13799 rm. +diffusiontensors 0,$5,1.2,1.2 13800 r[-2,-1] $1,$2,$3,100%,5 13801 smooth.. .,$4 rm. 13802 ac "sharpen. $6,10",ycbcr_y 13803 fi 13804 endl done 13805 13806#@cli warp : [warping_field],_mode,_interpolation,_boundary_conditions,_nb_frames>0 : (+) 13807#@cli : Warp selected images with specified displacement field. 13808#@cli : 'mode' can be { 0=backward-absolute | 1=backward-relative | 2=forward-absolute | 3=forward-relative }. 13809#@cli : 'interpolation' can be { 0=nearest-neighbor | 1=linear | 2=cubic }. 13810#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13811#@cli : Default values: 'mode=0', 'interpolation=1', 'boundary_conditions=1' and 'nb_frames=1'. 13812#@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))' \ 13813# warp[-2] [-1],1,1,0 quiver[-1] [-1],10,1,1,1,100 13814#@cli : $$ https://gmic.eu/oldtutorial/_warp 13815 13816#@cli warp_patch : [warping_field],patch_width>=1,_patch_height>=1,_patch_depth>=1,_std_factor>0,_boundary_conditions. 13817#@cli : Patch-warp selected images, with specified 2D or 3D displacement field (in backward-absolute mode). 13818#@cli : Argument 'std_factor' sets the std of the gaussian weights for the patch overlap, 13819#@cli : equal to 'std = std_factor*patch_size'. 13820#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 13821#@cli : Default values: 'std_factor=0.3' and 'boundary_conditions=3'. 13822warp_patch : check ${is_image_arg\ $1}" && isint(${2=3}) && $2>=1 && isint(${3=$2}) && $3>=1 && 13823 isint(${4=1}) && $4>=1 && isnum(${5=0.3}) && $5>0 && isint(${6=3}) && $6>=0 && $6<=3" 13824 e[^-1] "Patch-warp image$? with backward-absolute displacement field $1, using $2x$3x$4 patches, std factor $5 13825 and "${"arg 1+$6,dirichlet,neumann,periodic,mirror"}" boundary conditions." 13826 if $2<=1 pass$1 warp[^-1] .,0 rm. return fi 13827 repeat $! pass$1 l[$>,-1] nm={0,n} 13828 [0],[0],[0],1,1 a[0,-1] c # Add weighting channel 13829 100%,100%,100%,{0,s} 13830 13831 if s#1>=3 # 3D version 13832 eval[1] "> 13833 begin( 13834 const pw = $2; 13835 const ph = $3; 13836 const pd = $4; 13837 const stdf = $5; 13838 const boundary = $6; 13839 const pw1 = int(pw/2); 13840 const pw2 = pw - pw1 - 1; 13841 const ph1 = int(ph/2); 13842 const ph2 = ph - ph1 - 1; 13843 const pd1 = int(pd/2); 13844 const pd2 = pd - pd1 - 1; 13845 const pwhd = pw*ph*pd; 13846 return = vector(s); 13847 13848 # Pre-compute gaussian weights. 13849 if (stdf<5, 13850 ref(vectorpwhd(),weights); 13851 offw = 0; 13852 for (zw = -pd1, zw<=pd2, ++zw, 13853 for (yw = -ph1, yw<=ph2, ++yw, 13854 for (xw = -pw1, xw<=pw2, ++xw, 13855 weights[offw++] = exp(-xw^2/(2*(stdf*pw)^2) - yw^2/(2*(stdf*ph)^2) - zw^2/(2*(stdf*pd)^2)); 13856 ); 13857 ); 13858 ); 13859 ); 13860 ); 13861 u = i(x,y,z,0); 13862 v = i(x,y,z,1); 13863 w = i(x,y,z,2); 13864 ref(crop(#0,u - pw1, v - ph1,w - pd1,pw,ph,pd,boundary),patch); 13865 stdf<5? 13866 draw(#2,patch,x - pw1,y - ph1,z - pd1,0,pw,ph,pd,s#0,-1,weights): 13867 draw(#2,patch,x - pw1,y - ph1,z - pd1,0,pw,ph,pd,s#0,-1); 13868 return" 13869 else # 2D version 13870 eval[1] "> 13871 begin( 13872 const pw = $2; 13873 const ph = $3; 13874 const stdf = $5; 13875 const boundary = $6; 13876 13877 const pw1 = int(pw/2); 13878 const pw2 = pw - pw1 - 1; 13879 const ph1 = int(ph/2); 13880 const ph2 = ph - ph1 - 1; 13881 const pwh = pw*ph; 13882 return = vector(s); 13883 13884 # Pre-compute gaussian weights. 13885 if (stdf<5, 13886 ref(vectorpwh(),weights); 13887 offw = 0; 13888 for (yw = -ph1, yw<=ph2, ++yw, 13889 for (xw = -pw1, xw<=pw2, ++xw, 13890 weights[offw++] = exp(-xw^2/(2*(stdf*pw)^2) - yw^2/(2*(stdf*ph)^2)); 13891 ); 13892 ); 13893 ); 13894 ); 13895 u = i(x,y,z,0); 13896 v = i(x,y,z,1); 13897 ref(crop(#0,u - pw1, v - ph1,pw,ph,boundary),patch); 13898 stdf<5? 13899 draw(#2,patch,x - pw1,y - ph1,0,0,pw,ph,1,s#0,-1,weights): 13900 draw(#2,patch,x - pw1,y - ph1,0,0,pw,ph,1,s#0,-1); 13901 return" 13902 fi 13903 s. c,-{0,s-1} /[-2,-1] k. nm $nm 13904 endl done 13905 13906#@cli warp_rbf : xs0[%],ys0[%],xt0[%],yt0[%],...,xsN[%],ysN[%],xtN[%],ytN[%] 13907#@cli : Warp selected images using RBF-based interpolation. 13908#@cli : Each argument (xsk,ysk)-(xtk,ytk) corresponds to the coordinates of a keypoint 13909#@cli : respectively on the source and target images. The set of all keypoints define the overall image deformation. 13910#@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% 13911warp_rbf : 13912 e[^-1] "Warp image$? using RBF interpolation, with keypoints ($*)." 13913 $=arg N={$#/4} 13914 if int($N)!=$N error[0--2] "Command 'warp_rbf': Wrong number of arguments ($#)." fi 13915 repeat $! l[$>] 13916 # Retrieve absolute keypoints coordinates. 13917 4,$N 13918 repeat wh a=${arg{1+$>}} isp=${"is_percent "$a} eval i[$>]=$isp?($>%2?w#0:h#0)*$a:$a done 13919 s. x,2 -. .. a[-2,-1] x permute. yzcx 13920 13921 # Generate warping field by RBF interpolation. 13922 rbf. {0,[w,h]} warp[0] .,1,1,3 rm. 13923 endl done 13924 13925#--------------------------------- 13926# 13927#@cli :: Filtering 13928# 13929#--------------------------------- 13930 13931#@cli bandpass : _min_freq[%],_max_freq[%] 13932#@cli : Apply bandpass filter to selected images. 13933#@cli : Default values: 'min_freq=0' and 'max_freq=20%'. 13934#@cli : $ image.jpg bandpass 1%,3% 13935#@cli : $$ https://gmic.eu/oldtutorial/_bandpass 13936bandpass : skip ${1=0},${2=20%} 13937 e[^-1] "Apply bandpass filter [$1,$2] to image$?." 13938 repeat $! l[$>] 13939 100%,100%,100% f. "sqrt((x/w-0.5)^2 + (y/h-0.5)^2 + (z/d-0.5)^2)" 13940 n. 0,1 ir. $1,$2 shift. {int(w/2)},{int(h/2)},{int(d/2)},0,2 13941 fft.. *... . *[-2,-1] ifft rm. 13942 endl done 13943 13944#@cli bilateral : [guide],std_deviation_s[%]>=0,std_deviation_r[%]>=0,_sampling_s>=0,_sampling_r>=0 : \ 13945# std_deviation_s[%]>=0,std_deviation_r[%]>=0,_sampling_s>=0,_sampling_r>=0 : (+) 13946#@cli : Blur selected images by anisotropic (eventually joint/cross) bilateral filtering. 13947#@cli : If a guide image is provided, it is used for drive the smoothing filter. 13948#@cli : A guide image must be of the same xyz-size as the selected images. 13949#@cli : Set 'sampling' arguments to '0' for automatic adjustment. 13950#@cli : $ image.jpg repeat 5 bilateral 10,10 done 13951 13952#@cli b : eq. to 'blur'. : (+) 13953 13954#@cli blur : std_deviation>=0[%],_boundary_conditions,_kernel : \ 13955# axes,std_deviation>=0[%],_boundary_conditions,_kernel : (+) 13956#@cli : Blur selected images by a deriche or gaussian filter (recursive implementation). 13957#@cli : (eq. to 'b').\n 13958#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann }. 13959#@cli : 'kernel' can be { 0=deriche | 1=gaussian }. 13960#@cli : When specified, argument 'axes' is a sequence of { x | y | z | c }. 13961#@cli : Specifying one axis multiple times apply also the blur multiple times. 13962#@cli : Default values: 'boundary_conditions=1' and 'kernel=1'. 13963#@cli : $ image.jpg +blur 5,0 +blur[0] 5,1 13964#@cli : $ image.jpg +blur y,10% 13965#@cli : $$ https://gmic.eu/oldtutorial/_blur 13966 13967#@cli blur_angular : amplitude[%],_center_x[%],_center_y[%] 13968#@cli : Apply angular blur on selected images. 13969#@cli : Default values: 'center_x=center_y=50%'. 13970#@cli : $ image.jpg blur_angular 2% 13971#@cli : $$ https://gmic.eu/oldtutorial/_blur_angular 13972blur_angular : skip ${2=50%},${3=50%} 13973 e[^-1] "Apply angular blur on image$?, with amplitude $1 and center point ($2,$3)." 13974 euclidean2polar $2,$3,1.3,1 13975 repeat $! l[$>] 1,100% =. 1,50%,50% b. y,$1 convolve_fft.. . rm. endl done 13976 polar2euclidean $2,$3,1.3,1 13977 13978#@cli blur_bloom : _amplitude>=0,_ratio>=0,_nb_iter>=0,_blend_operator={ + | max | min },\ 13979# _kernel={ 0=deriche | 1=gaussian | 2=box | 3=triangle | 4=quadratic },\ 13980# _normalize_scales={ 0 | 1 },_axes 13981#@cli : Apply a bloom filter that blend multiple blur filters of different radii, 13982#@cli : resulting in a larger but sharper glare than a simple blur. 13983#@cli : When specified, argument 'axes' is a sequence of { x | y | z | c }. 13984#@cli : Specifying one axis multiple times apply also the blur multiple times. 13985#@cli : Reference: Masaki Kawase, "Practical Implementation of High Dynamic Range Rendering", GDC 2004. 13986#@cli : Default values: 'amplitude=1', 'ratio=2', 'nb_iter=5', 'blend_operator=+', 'kernel=1', 'normalize_scales=0' \ 13987# and 'axes=(all)' 13988#@cli : $ image.jpg blur_bloom , 13989blur_bloom : check "${1=1}>=0 && ${2=2}>=0 && isint(${3=5}) && $3>=0 && isint(${5=1}) && $5>=0 && $5<=4 && 13990 isnum(${6=0})" skip "${4=+},${7=}" 13991 e[^-1] "Apply bloom effect on image$?, with amplitude $1, ratio $2, $3 iterations, blend operator '$4' and "\ 13992 ${"arg 1+!$6,\"\",\"no \""}"scale normalization." 13993 if narg("$7") axes=$7, fi 13994 m "_bloom0 : b "$axes"$""1" 13995 m "_bloom1 : b "$axes"$""1,1,1" 13996 m "_bloom2 : boxfilter "$axes"{1+2*$""1},0,1" 13997 m "_bloom3 : boxfilter "$axes"{1+2*$""1},0,1,2" 13998 m "_bloom4 : boxfilter "$axes"{1+2*$""1},0,1,3" 13999 repeat $! l[$>] nm={n} mM={[im,iM]} 14000 [0] repeat $3 sigma={$1*($2^$>)} +_bloom$5[0] $sigma 14001 if $6 n. $mM fi 14002 -$4[1,-1] 14003 done 14004 n. $mM k. nm $nm 14005 endl done 14006 um _bloom0,_bloom1,_bloom2,_bloom3,_bloom4 14007 14008#@cli blur_linear : amplitude1[%],_amplitude2[%],_angle,_boundary_conditions={ 0=dirichlet | 1=neumann } 14009#@cli : Apply linear blur on selected images, with specified angle and amplitudes. 14010#@cli : Default values: 'amplitude2=0', 'angle=0' and 'boundary_conditions=1'. 14011#@cli : $ image.jpg blur_linear 10,0,45 14012#@cli : $$ https://gmic.eu/oldtutorial/_blur_linear 14013blur_linear : skip ${2=0},${3=0},${4=1} 14014 e[^-1] "Apply linear blur on image$?, with angle $3 deg. and amplitudes ($1,$2)." 14015 std1={if(${is_percent\ $1},$1*max(w,h),$1)} 14016 std2={if(${is_percent\ $2},$2*max(w,h),$2)} 14017 stdM={round(1.25*max($std1,$std2))} 14018 if $stdM<=0 return fi 14019 repeat $! l[$>] 14020 expand_xy $stdM,{$4!=0} 14021 {2*$stdM},{2*$stdM} gaussian. $1,$2,$3 normalize_sum. 14022 convolve_fft[0] [1] rm. shrink_xy $stdM 14023 endl done 14024 14025#@cli blur_radial : amplitude[%],_center_x[%],_center_y[%] 14026#@cli : Apply radial blur on selected images. 14027#@cli : Default values: 'center_x=center_y=50%'. 14028#@cli : $ image.jpg blur_radial 2% 14029#@cli : $$ https://gmic.eu/oldtutorial/_blur_radial 14030blur_radial : skip ${2=50%},${3=50%} 14031 e[^-1] "Apply radial blur on image$?, with amplitude $1 and center point ($2,$3)." 14032 euclidean2polar $2,$3,5,1 blur_x $1 polar2euclidean $2,$3,5,1 14033 14034#@cli blur_selective : sigma>=0,_edges>0,_nb_scales>0 14035#@cli : Blur selected images using selective gaussian scales. 14036#@cli : Default values: 'sigma=5', 'edges=0.5' and 'nb_scales=5'. 14037#@cli : $ image.jpg noise 20 cut 0,255 +local[-1] repeat 4 blur_selective , done endlocal 14038#@cli : $$ https://gmic.eu/oldtutorial/_blur_selective 14039blur_selective : check "${1=5}>=0 && ${2=0.5}>=0 && isint(${3=5}) && $3>0" 14040 e[^-1] "Blur image$? using $3 selective gaussian scales, with sigma $1 and edges $2." 14041 repeat $! l[$>] nm={0,n} 14042 +gradient_norm +. 1 ^. {-max(0.01,$2)} quantize. {$3+1},0,1 min. {$3-1} ri. .. 14043 repeat $3 +==. $> *. ... +[-2,-1] b.. {$1/($3+1)} done 14044 rm.. nm $nm endl done 14045 14046#@cli blur_x : amplitude[%]>=0,_boundary_conditions={ 0=dirichlet | 1=neumann } 14047#@cli : Blur selected images along the x-axis. 14048#@cli : Default value: 'boundary_conditions=1'. 14049#@cli : $ image.jpg +blur_x 6 14050#@cli : $$ https://gmic.eu/oldtutorial/_blur_x 14051blur_x : skip ${2=1} 14052 e[^-1] "Blur image$? along the x-axis, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 14053 deriche $1,0,x,$2 14054 14055#@cli blur_xy : amplitude_x[%],amplitude_y[%],_boundary_conditions={ 0=dirichlet | 1=neumann } 14056#@cli : Blur selected images along the X and Y axes. 14057#@cli : Default value: 'boundary_conditions=1'. 14058#@cli : $ image.jpg +blur_xy 6 14059#@cli : $$ https://gmic.eu/oldtutorial/_blur_y 14060blur_xy : skip ${2=$1},${3=1} 14061 e[^-1] "Blur image$? along the xy-axes, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 14062 deriche $1,0,x,$3 deriche $2,0,y,$3 14063 14064#@cli blur_xyz : amplitude_x[%],amplitude_y[%],amplitude_z,_boundary_conditions={ 0=dirichlet | 1=neumann } 14065#@cli : Blur selected images along the X, Y and Z axes. 14066#@cli : Default value: 'boundary_conditions=1'. 14067#@cli : $$ https://gmic.eu/oldtutorial/_blur_xyz 14068blur_xyz : skip ${4=1} 14069 e[^-1] "Blur image$? along the xyz-axes, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 14070 deriche $1,0,x,$4 deriche $2,0,y,$4 deriche $3,0,z,$4 14071 14072#@cli blur_y : amplitude[%]>=0,_boundary_conditions={ 0=dirichlet | 1=neumann } 14073#@cli : Blur selected images along the y-axis. 14074#@cli : Default value: 'boundary_conditions=1'. 14075#@cli : $ image.jpg +blur_y 6 14076#@cli : $$ https://gmic.eu/oldtutorial/_blur_y 14077blur_y : skip ${2=1} 14078 e[^-1] "Blur image$? along the y-axis, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 14079 deriche $1,0,y,$2 14080 14081#@cli blur_z : amplitude[%]>=0,_boundary_conditions={ 0=dirichlet | 1=neumann } 14082#@cli : Blur selected images along the z-axis. 14083#@cli : Default value: 'boundary_conditions=1'. 14084#@cli : $$ https://gmic.eu/oldtutorial/_blur_z 14085blur_z : skip ${2=1} 14086 e[^-1] "Blur image$? along the z-axis, with sigma $1 and "${arg\ 1+!$2,neumann,dirichlet}" boundary conditions." 14087 deriche $1,0,z,$2 14088 14089#@cli boxfilter : size>=0[%],_order,_boundary_conditions,_nb_iter>=0 : \ 14090# axes,size>=0[%],_order,_boundary_conditions,_nb_iter>=0 : (+) 14091#@cli : Blur selected images by a box filter of specified size (fast recursive implementation). 14092#@cli : 'order' can be { 0=smooth | 1=1st-derivative | 2=2nd-derivative }. 14093#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann }. 14094#@cli : When specified, argument 'axes' is a sequence of { x | y | z | c }. 14095#@cli : Specifying one axis multiple times apply also the blur multiple times. 14096#@cli : Default values: 'order=0', 'boundary_conditions=1' and 'nb_iter=1'. 14097#@cli : $ image.jpg +boxfilter 5% 14098#@cli : $ image.jpg +boxfilter y,3,1 14099 14100#@cli bump2normal 14101#@cli : Convert selected bumpmaps to normalmaps. 14102#@cli : $ 300,300 circle 50%,50%,128,1,1 blur 5% bump2normal 14103bump2normal : 14104 e[^-1] "Convert bumpmap$? to normalmap." 14105 repeat $! l[$>] 14106 channels 0 g xy,1 +f. 1 a c orientation 14107 * 127 + 128 round c 0,255 14108 endl done 14109 14110#@cli compose_freq 14111#@cli : Compose selected low and high frequency parts into new images. 14112#@cli : $ image.jpg split_freq 2% mirror[-1] x compose_freq 14113compose_freq : 14114 e[^-1] "Compose low and high frequency part$? into new images." 14115 repeat int($!/2) +[$>,{$>+1}] done 14116 14117#@cli convolve : [mask],_boundary_conditions,_is_normalized={ 0 | 1 },_channel_mode,\ 14118# _xcenter,_ycenter,_zcenter,_xstart,_ystart,_zstart,_xend,_yend,_zend,_xstride,_ystride,_zstride,\ 14119# _xdilation,_ydilation,_zdilation,interpolation_type : (+) 14120#@cli : Convolve selected images by specified mask. 14121#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14122#@cli : 'channel_mode' can be { 0=sum input channels | 1=one-for-one | 2=expand }. 14123#@cli : 'interpolation_type' can be { 0=nearest-neighbor | 1=linear }. 14124#@cli : Default values: 'boundary_conditions=1', 'is_normalized=0', 'channel_mode=1', \ 14125# 'xcenter=ycenter=zcenter=-1' (-1=centered), 'xstart=ystart=zstart=0', 'xend=yend=zend=-1' (-1=max coordinates), \ 14126# 'xstride=ystride=zstride=1', 'xdilation=ydilation=zdilation=1' and 'interpolation_type=0'. 14127#@cli : $ image.jpg (0,1,0;1,-4,1;0,1,0) convolve[-2] [-1] keep[-2] 14128#@cli : $ image.jpg (0,1,0) resize[-1] 130,1,1,1,3 +convolve[0] [1] 14129#@cli : $$ https://gmic.eu/oldtutorial/_convolve 14130 14131#@cli convolve_fft : [mask],_boundary_conditions 14132#@cli : Convolve selected images with specified mask, in the fourier domain. 14133#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14134#@cli : $ image.jpg 100%,100% gaussian[-1] 20,1,45 +convolve_fft[0] [1] 14135convolve_fft : check ${is_image_arg\ $1}" && isin(${2=2},0,1,2,3)" 14136 e[^-1] "Convolve image$? with mask $1, in the fourier domain." 14137 pass$1 store. kernel 14138 repeat $! l[$>] if w 14139 w0,h0,d0={[w,h,d]} 14140 $kernel 14141 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 14142 r ${-max_whd},100%,0,0,0.5,0.5 r 100%,100%,100%,${-max_s} 14143 fft[1] fft[0] 14144 +*[1,2] +*[0,3] +[-2,-1] *[1,3] *[0,2] -[0,1] 14145 ifft rm. 14146 shift {-int(([w,h,d]-1)/2)},0,2 14147 r $w0,$h0,$d0,100%,0,0,0.5,0.5 14148 fi endl done 14149 14150#@cli correlate : [mask],_boundary_conditions,_is_normalized={ 0 | 1 },_channel_mode,\ 14151# _xcenter,_ycenter,_zcenter,_xstart,_ystart,_zstart,_xend,_yend,_zend,_xstride,_ystride,_zstride,\ 14152# _xdilation,_ydilation,_zdilation,interpolation_type : (+) 14153#@cli : Correlate selected images by specified mask. 14154#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 14155#@cli : 'channel_mode' can be { 0=sum input channels | 1=one-for-one | 2=expand }. 14156#@cli : 'interpolation_type' can be { 0=nearest-neighbor | 1=linear }. 14157#@cli : Default values: 'boundary_conditions=1', 'is_normalized=0', 'channel_mode=1', \ 14158# 'xcenter=ycenter=zcenter=-1' (-1=centered), 'xstart=ystart=zstart=0', 'xend=yend=zend=-1' (-1=max coordinates), \ 14159# 'xstride=ystride=zstride=1', 'xdilation=ydilation=zdilation=1' and 'interpolation_type=0'. 14160#@cli : $ image.jpg (0,1,0;1,-4,1;0,1,0) correlate[-2] [-1] keep[-2] 14161#@cli : $ image.jpg +crop 40%,40%,60%,60% +correlate[0] [-1],0,1 14162 14163#@cli cross_correlation : [mask] 14164#@cli : Compute cross-correlation of selected images with specified mask. 14165#@cli : $ image.jpg +shift -30,-20 +cross_correlation[0] [1] 14166cross_correlation : check ${is_image_arg\ $1} 14167 e[^-1] "Compute cross-correlation of image$? with mask $1." 14168 repeat $! pass$1 0 l[$>,-1] 14169 norm fft.. fft. [-2,-1] *.. [-5] *. [-6] 14170 -[-2,-1] *[-5,-3] *[-3,-2] +[-3,-2] ifft rm. 14171 endl done 14172 14173#@cli curvature 14174#@cli : Compute isophote curvatures on selected images. 14175#@cli : $ image.jpg blur 10 curvature 14176curvature : 14177 e[^-1] "Compute isophote curvatures on image$?." 14178 repeat $! l[$>] 14179 if d==1 14180 +g xy,0 hessian... xxxyyy # ixx ixy iyy ix iy 14181 *... .. *[-4] . *[-4] -2 # ixx -2iyixy ixiyy ix iy 14182 +[-4,-3] *... .. # ixx -2ixiyixy+ix^2iyy ix iy 14183 sqr[-2,-1] *[-4] . +[-4,-3] # iy^2ixx-2ixiyixy+ix^2iyy ix^2 iy^2 14184 +[-2,-1] +. 0.1 ^. 1.5 / # (iy^2ixx+2ixiyixy+ix^2iyy)/(ix^2+iy^2) 14185 else 14186 +inn +gradient_norm.. laplacian... # inn+iee inn in 14187 -[-3,-2] +. 0.1 /[-2,-1] # iee in 14188 +inn. laplacian.. - # iee/in 14189 fi 14190 endl done 14191 14192#@cli dct : _{ x | y | z }...{ x | y | z } : (no arg) 14193#@cli : Compute the discrete cosine transform of selected images, optionally along the specified axes only. 14194#@cli : Output images are always evenly sized, so this command may change the size of the selected images. 14195#@cli : Default values: (no arg) 14196#@cli : See also: ''idct''. 14197#@cli : $ image.jpg +dct +idct[-1] abs[-2] +[-2] 1 log[-2] 14198#@cli : $$ https://gmic.eu/oldtutorial/_dct-and-idct 14199dct : skip ${1=0} 14200 ('"$1"') 14201 is_axes={im>=_'x'" && "iM<=_'z'} 14202 if $is_axes 14203 e[0--3] "Compute discrete cosine transform of image$? along axes '$1'." 14204 repeat w 14205 axis={i[$>]} 14206 if $axis==_'x' repeat $!-1 l[$>] if w>1 _dct fi endl done 14207 elif $axis==_'y' repeat $!-1 l[$>] if h>1 permute yxzc _dct permute yxzc fi endl done 14208 elif $axis==_'z' repeat $!-1 l[$>] if d>1 permute zxyc _dct permute yzxc fi endl done 14209 fi 14210 done 14211 rm. 14212 else 14213 rm. 14214 e[0--3] "Compute discrete cosine transform of image$?." 14215 noarg 14216 repeat $! l[$>] 14217 if w>1 _dct fi 14218 if h>1 permute yxzc _dct permute yxzc fi 14219 if d>1 permute zxyc _dct permute yzxc fi 14220 endl done 14221 fi 14222 14223# 1D direct transform (DCT-II) along the x-axis, for a single image. 14224_dct : 14225 if w%2 r {w+1},100%,100%,100%,0,1 fi 14226 s x l[1--1:2] a x mirror x endl mv[1] $! a x 14227 fft x 14228 100%,1,1,1,2*cos(-x*pi/(2*w)) *[0,2] 14229 100%,1,1,1,2*sin(-x*pi/(2*w)) *[1,2] 14230 - 14231 +z[0] 0,0 /. {sqrt(2)} j.. .,0,0,0 rm. * {sqrt(2/w)} # Make the transform orthogonal. 14232 14233#@cli deblur : amplitude[%]>=0,_nb_iter>=0,_dt>=0,_regul>=0,_regul_type={ 0=Tikhonov | 1=meancurv. | 2=TV } 14234#@cli : Deblur image using a regularized Jansson-Van Cittert algorithm. 14235#@cli : Default values: 'nb_iter=10', 'dt=20', 'regul=0.7' and 'regul_type=1'. 14236#@cli : $ image.jpg blur 3 +deblur 3,40,20,0.01 14237deblur : check "${2=10}>=0 && ${3=20}>=0 && ${4=0.7}>=0" skip ${5=1} 14238 e[^-1] "Deblur image$? with a regularized Jansson-Van Cittert algorithm, with sigma $1, $2 iterations, 14239 time step $3 and regularization $4." 14240 repeat $! l[$>] nm={0,n} 14241 [0] 14242 repeat $2 14243 if $5>=2 +curvature. # TV regularization. 14244 elif $5>=1 +iee. # Meancurv. regularization. 14245 else +laplacian. # Tikhonov regularization. 14246 fi 14247 *. $4 14248 +b.. $1 -. [-4] # Data fidelity term. 14249 -[-2,-1] 14250 *. {$3/(0.0001+max(abs(im),abs(iM)))} # Adaptive time step. 14251 +[-2,-1] # Update image. 14252 done 14253 rm.. 14254 nm $nm endl done 14255 14256#@cli deblur_goldmeinel : sigma>=0,_nb_iter>=0,_acceleration>=0,_kernel_type={ 0=deriche | 1=gaussian }. 14257#@cli : Deblur selected images using Gold-Meinel algorithm 14258#@cli : Default values: 'nb_iter=8', 'acceleration=1' and 'kernel_type=1'. 14259#@cli : $ image.jpg +blur 1 +deblur_goldmeinel[-1] 1 14260###### : (contribution from Jérôme Boulanger). 14261deblur_goldmeinel : check "$1>=0 && ${2=8}>=0 && ${3=1}>=0" skip ${4=1} 14262 e[^-1] "Deblur image$? using Gold-Meinel algorithm, with sigma $1, $2 iterations, acceleration $3 and "\ 14263 ${arg\ 1+!$4,"",quasi-}"gaussian kernel." 14264 repeat $! l[$>] 14265 [0] repeat $2 14266 +b. $1,1,$4 +/[0,-1] rm.. ^. $3 *[-1,-2] # u *= f / Hu 14267 done rm[0] 14268 endl done 14269 14270#@cli deblur_richardsonlucy : sigma>=0, nb_iter>=0, _kernel_type={ 0=deriche | 1=gaussian }. 14271#@cli : Deblur selected images using Richardson-Lucy algorithm. 14272#@cli : Default values: 'nb_iter=50' and 'kernel_type=1'. 14273#@cli : $ image.jpg +blur 1 +deblur_richardsonlucy[-1] 1 14274###### : (contribution from Jérôme Boulanger). 14275deblur_richardsonlucy : check "$1>=0 && ${2=50}>=0" skip ${3=1} 14276 e[^-1] "Deblur image$? using Richardson-Lucy algorithm, with sigma $1, $2 iterations and "\ 14277 ${arg\ 1+!$3,"",quasi-}"gaussian kernel." 14278 repeat $! l[$>] 14279 [0] repeat $2 14280 +b. $1,1,{$3!=0} max. 1e-6 +/[0,-1] rm.. b. $1,1,{$3!=0} *[-1,-2] # u *= H ( f / Hu ) 14281 done rm[0] 14282 endl done 14283 14284#@cli deconvolve_fft : [kernel],_regularization>=0 14285#@cli : Deconvolve selected images by specified mask in the fourier space. 14286#@cli : Default value: 'regularization>=0'. 14287#@cli : $ image.jpg +gaussian 5 +convolve_fft[0] [1] +deconvolve_fft[-1] [1] 14288deconvolve_fft : check ${is_image_arg\ $1}" && ${2=.001}>=0" 14289 e[^-1] "Deconvolve image$? with mask $1 and regularization $2, in the fourier domain." 14290 repeat $! pass$1 0 l[$>,-1] 14291 w2={0,int(w/2)} h2={0,int(h/2)} d2={0,int(d/2)} 14292 r[1] [0],[0],[0],1,0,0,0.5,0.5,0.5,0.5 shift[1] -$w2,-$h2,-$d2,0,2 14293 fft[0] fft[2] # a b a' b' 14294 +l[-1,-2] sqr + + $2 endl # a b a' b' (a'^2+b'^2+eps) 14295 +*[-4] ... # a b a' b' (a'^2+b'^2) ba' 14296 +*[-6] ... # a b a' b' (a'^2+b'^2) ba' ab' 14297 -[-2,-1] # a b a' b' (a'^2+b'^2) ba'-ab' 14298 *[-6,-4] # aa' b b' (a'^2+b'^2) ba'-ab' 14299 *[-4,-3] # aa' bb' (a'^2+b'^2) ba'-ab' 14300 +[-4,-3] # aa'+bb' (a'^2+b'^2) ba'-ab' 14301 /. .. /[-3,-2] # divide (aa'+bb') and (ba'-ab') by (a'^2+b'^2) 14302 ifft rm. 14303 endl done 14304 14305#@cli deinterlace : _method={ 0 | 1 } 14306#@cli : Deinterlace selected images ('method' can be { 0=standard or 1=motion-compensated }). 14307#@cli : Default value: 'method=0'. 14308#@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 14309deinterlace : skip ${1=0} 14310 e[^-1] "Deinterlace image$? with "${arg\ 1+!$1,motion-compensated,standard}" method." 14311 repeat $! l[$>] 14312 wh={w},{h} 14313 s y a[0--1:2] y a[^0] y ri.. .,0 r 100%,200%,1,100%,5 14314 if $1!=0 +displacement. ..,0.05 warp... .,1,1,1 rm. fi 14315 + / 2 c 0,255 r $wh 14316 endl done 14317 14318#@cli denoise : [guide],std_deviation_s[%]>=0,_std_deviation_r[%]>=0,_patch_size>0,_lookup_size>0,_smoothness,\ 14319# _fast_approx={ 0 | 1 } : \ 14320# std_deviation_s[%]>=0,_std_deviation_r[%]>=0,_patch_size>0,_lookup_size>0,_smoothness,\ 14321# _fast_approx={ 0 | 1 } : (+) 14322#@cli : Denoise selected images by non-local patch averaging. 14323#@cli : Default values: 'std_deviation_p=10', 'patch_size=5', 'lookup_size=6' and 'smoothness=1'. 14324#@cli : $ image.jpg +denoise 5,5,8 14325 14326#@cli denoise_haar : _threshold>=0,_nb_scales>=0,_cycle_spinning>0 14327#@cli : Denoise selected images using haar-wavelet thresholding with cycle spinning. 14328#@cli : Set 'nb_scales==0' to automatically determine the optimal number of scales. 14329#@cli : Default values: 'threshold=1.4', 'nb_scale=0' and 'cycle_spinning=10'. 14330#@cli : $ image.jpg noise 20 cut 0,255 +denoise_haar[-1] 0.8 14331denoise_haar : check "${1=1.4}>=0 && isint(${2=0}) && $2>=0 && isint(${3=10}) && $3>0" 14332 e[^-1] "Denoise image$? using haar-wavelet thresholding, with threshold $1, "\ 14333 ${arg\ 1+($2>0),auto,$2}" scales and $3 spinning cycles." 14334 repeat $! l[$>] nm={0,n} 14335 nb_scales={min(if($2,$2,32),int(log2(min(w,h))-1))} 14336 w={w} h={h} d={d} sigma=${-std_noise} 14337 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 14338 +f 0 14339 repeat $3 14340 dx={round(u(0,{4*$nb_scales}))} 14341 dy={round(u(0,{4*$nb_scales}))} 14342 dz={if($d==1,0,round(u(0,{4*$nb_scales})))} 14343 +shift[0] $dx,$dy,$dz,0,2 14344 haar. $nb_scales 14345 threshold. {$1*$sigma},1 14346 ihaar. $nb_scales 14347 shift. {-$dx},{-$dy},{-$dz},0,2 14348 +[-2,-1] 14349 done 14350 rm[0] / $3 r $w,$h,$d,100%,0 14351 nm $nm endl done 14352 14353#@cli denoise_patchpca : _strength>=0,_patch_size>0,_lookup_size>0,_spatial_sampling>0 14354#@cli : Denoise selected images using the patch-pca algorithm. 14355#@cli : Default values: 'patch_size=7', 'lookup_size=11', 'details=1.8' and 'spatial_sampling=5'. 14356#@cli : $ image.jpg +noise 20 cut[-1] 0,255 +denoise_patchpca[-1] , 14357denoise_patchpca : check "${1=1.8} && $1>=0 && isint(${2=7}) && $2>0 && isint(${3=11}) && $3>0 && isint(${4=5}) && $4>0" 14358 e[^-1] "Denoise image$? using patch-pca, with strength $1, patch size $2, lookup size $3 and spatial sampling $4." 14359 repeat $! l[$>] nm={n} 14360 N2={$2*$2} M2={$3*$3} stdnoise=${-std_noise} 14361 100%,100%,1,100% nm. aggreg 14362 100%,100% nm. weights 14363 f[0] "* 14364 begin( 14365 n1 = int($2/2); n2 = $2 - n1 - 1; 14366 m1 = int($3/2); m2 = $3 - m1 - 1; 14367 patch(x,y) = crop(x - n1,y - n1,0,c,$2,$2,1,1,1); 14368 ngauss(x) = exp(-x*x/(2*n1*n1)); 14369 ref(vector"$N2"(0),zero); 14370 ref(vector"$N2"(0),mask); 14371 for (l = 0; q = -n1, q<=n2, ++q, 14372 for (p = -n1, p<=n2, ++p, mask[l++] = ngauss(p)*ngauss(q) 14373 ) 14374 ) 14375 ); 14376 14377 if (!(x%$4) && !(y%$4), # Sub-sampling 14378 ref(patch(x,y),X); 14379 14380 # Build correlation matrix for PCA. 14381 ref(vector"{$N2*$N2}"(0),M); 14382 for (q = -m1, q<=m2, ++q, 14383 for (p = -m1, p<=m2, ++p, 14384 ref(patch(x + p,y + q) - X,Xk); 14385 M += mul(Xk,Xk,"$N2"); 14386 ) 14387 ); 14388 M/="$M2"; 14389 eig = eig(M); 14390 lambda = sqrt(abs(eig[0,"$N2"])); 14391 14392 # Determine number of lambdas to keep and project neighboring patches. 14393 for (k = 0, k<size(lambda) && lambda[k]>=$1*"$stdnoise", ++k); 14394 Qt = eig["$N2","{$N2*$N2}"]; 14395 Q = transpose(Qt,"$N2"); 14396 for (q = -m1, q<=m2, ++q, 14397 for (p = -m1, p<=m2, ++p, 14398 pY = Qt*(patch(x + p,y + q) - X); 14399 copy(pY[k],zero[0],size(pY) - k); 14400 (Y = Q*pY)+=X; 14401 draw(#"$aggreg",Y,x + p - n1,y + q - n1,0,c,$2,$2,1,1,-1,mask); 14402 draw(#"$weights",mask,x + p - n1,y + q - n1,0,c,$2,$2,1,1,-1); 14403 ) 14404 ); 14405 0);0" 14406 max[weights] 0.01 /[aggreg,weights] k[aggreg] nm $nm 14407 endl done 14408 14409#@cli deriche : std_deviation>=0[%],order={ 0 | 1 | 2 },axis={ x | y | z | c },_boundary_conditions : (+) 14410#@cli : Apply Deriche recursive filter on selected images, along specified axis and with 14411#@cli : specified standard deviation, order and boundary conditions. 14412#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann }. 14413#@cli : Default value: 'boundary_conditions=1'. 14414#@cli : $ image.jpg deriche 3,1,x 14415#@cli : $ image.jpg +deriche 30,0,x deriche[-2] 30,0,y add 14416#@cli : $$ https://gmic.eu/oldtutorial/_deriche 14417 14418#@cli dilate : size>=0 : size_x>=0,size_y>=0,size_z>=0 : \ 14419# [kernel],_boundary_conditions,_is_real={ 0=binary-mode | 1=real-mode } : (+) 14420#@cli : Dilate selected images by a rectangular or the specified structuring element. 14421#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann }. 14422#@cli : Default values: 'size_z=1', 'boundary_conditions=1' and 'is_real=0'. 14423#@cli : $ image.jpg +dilate 10 14424 14425#@cli dilate_circ : _size>=0,_boundary_conditions,_is_normalized={ 0 | 1 } 14426#@cli : Apply circular dilation of selected images by specified size. 14427#@cli : Default values: 'boundary_conditions=1' and 'is_normalized=0'. 14428#@cli : $ image.jpg +dilate_circ 7 14429dilate_circ : check $1>=0 skip ${2=1},${3=0} 14430 e[^-1] "Apply circular dilation of image$? by size $1, boundary conditions $2 and is_normalized $3." 14431 if $1<2 return fi 14432 shape_circle $1 dilate[^-1] .,$2,$3 rm. 14433 14434#@cli dilate_oct : _size>=0,_boundary_conditions,_is_normalized={ 0 | 1 } 14435#@cli : Apply octagonal dilation of selected images by specified size. 14436#@cli : Default values: 'boundary_conditions=1' and 'is_normalized=0'. 14437#@cli : $ image.jpg +dilate_oct 7 14438dilate_oct : check $1>=0 skip ${2=1},${3=0} 14439 e[^-1] "Apply octagonal dilation of image$? by size $1, boundary conditions $2 and is_normalized $3." 14440 if $1<2 return fi 14441 if $1&1 ss={$1} else ss={$1+1} fi 14442 i[0] (0,1,0;1,1,1;0,1,0) i[1] (1,1,1;1,1,1;1,1,1) 14443 repeat $!-2 14444 r={round(($ss-1)*sqrt(2)/(1+sqrt(2))/2)} 14445 q={round(($ss-1)/(1+sqrt(2))/2)} 14446 if $r>0 repeat $r dilate. [0],$2,$3 done fi 14447 if $q>0 repeat $q dilate. [1],$2,$3 done fi 14448 mv. 2 done rm[0,1] 14449 14450_kr_circle : 14451 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 14452 distance. 1 round. 0.5 ir. 0,{$1/2} 14453 14454_jf_circle : 14455 {round($1)},{round($1)} 14456 center={0.5*(w-1)} 14457 f. 'sqrt((x-$center)^2+(y-$center)^2)' 14458 if !(w%2) 14459 round. 0.0001,-1 14460 t1={sqrt(((round($1)-1)/2)^2+0.25)} 14461 t2={sqrt(((round($1)+1)/2)^2+0.25)} 14462 k={$1-round($1)+0.5} 14463 t={$t1+($t2-$t1)*$k} 14464 ir. 0,$t 14465 else ir. 0,{$1/2-0.25} 14466 fi 14467 14468#@cli dilate_threshold : size_x>=1,size_y>=1,size_z>=1,_threshold>=0,_boundary_conditions 14469#@cli : Dilate selected images in the (X,Y,Z,I) space. 14470#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann }. 14471#@cli : Default values: 'size_y=size_x', 'size_z=1', 'threshold=255' and 'boundary_conditions=1'. 14472dilate_threshold : check "isint($1) && $1>=1 && isint(${2=$1}) && $2>=1 && isint(${3=1}) && $3>=1 && ${4=255}>=0 && 14473 isint(${5=1}) && $5>=0" 14474 e[^-1] "Dilate image$? with mask $1x$2x$3, threshold $4 and "${arg\ $5,dirichlet,neumann}" boundary conditions." 14475 l[] 14476 dx1={int($1/2)} dx2={$1-$dx1-1} 14477 dy1={int($2/2)} dy2={$2-$dy1-1} 14478 dz1={int($3/2)} dz2={$3-$dz1-1} 14479 (-$dx1,$dx1) (-$dy1;$dy1) (-$dz1/$dz1) r $1,$2,$3,1,3 a c round r {w*h*d},3,1,1,-1 transpose. 14480 i.. 1,100%,1,1,254 1,100%,1,1,255 a x 14481 ('{^}') rm.. replace_str "254,","(v=j(" replace_str ",255",",0,0,$5);if(abs(v-i)<=$4,v,-1e20))" list={t} 14482 rm 14483 endl 14484 f 'max($list)' 14485 14486#@cli divergence 14487#@cli : Compute divergence of selected vector fields. 14488#@cli : $ image.jpg luminance +gradient append[-2,-1] c divergence[-1] 14489divergence : 14490 e[^-1] "Compute divergence of vector field$?." 14491 repeat $! l[$>] 14492 if s==1 g x,0 14493 elif s==2 s c g.. x,0 g. y,0 + 14494 elif s==3 s c g... x,0 g.. y,0 g. z,0 + 14495 else error[] "Command '$0': Cannot compute divergence of image ["$>"] (has "{s}">3 channels)." 14496 fi 14497 endl done 14498 14499#@cli dog : _sigma1>=0[%],_sigma2>=0[%] 14500#@cli : Compute difference of gaussian on selected images. 14501#@cli : Default values: 'sigma1=2%' and 'sigma2=3%'. 14502#@cli : $ image.jpg dog 2,3 14503dog : check "${1=2%}>=0 && ${2=3%}>=0" 14504 e[^-1] "Compute difference of gaussian on image$?, with standard deviations $1 and $2." 14505 repeat $! l[$>] 14506 [0] parallel "b[0] $1","b[1] $2" - abs 14507 endl done 14508 14509#@cli diffusiontensors : _sharpness>=0,0<=_anisotropy<=1,_alpha[%],_sigma[%],is_sqrt={ 0 | 1 } 14510#@cli : Compute the diffusion tensors of selected images for edge-preserving smoothing algorithms. 14511#@cli : Default values: 'sharpness=0.7', 'anisotropy=0.3', 'alpha=0.6', 'sigma=1.1' and 'is_sqrt=0'. 14512#@cli : $ image.jpg diffusiontensors 0.8 abs pow 0.2 14513#@cli : $$ https://gmic.eu/oldtutorial/_diffusiontensors 14514diffusiontensors : check "${1=0.7}>=0 && ${2=0.3}>=0 && $2<=1" skip ${3=0.6},${4=1.1},${5=0} 14515 e[^-1] "Compute diffusion tensors for image$?, with sharpness $1, anisotropy $2, alpha $3 and sigma $4." 14516 p1={if($5,0.5,1)*max($1,1e-2)} 14517 p2={$p1/(1e-7+1-$2)} 14518 b $3 n 0,255 structuretensors 0 b $4 14519 repeat $! l[$>] 14520 eigen max.. 0 14521 if s==2 s.. c +[-3,-2] +.. 1 +^.. -$p1 ^... -$p2 a[-3,-1] c # 2D 14522 else s.. c +[-4--2] +.. 1 +^.. -$p1 r. 100%,100%,100%,2 ^... -$p2 a[-3,-1] c # 3D 14523 fi 14524 eigen2tensor 14525 endl done 14526 14527#@cli edges : _threshold[%]>=0 14528#@cli : Estimate contours of selected images. 14529#@cli : Default value: 'edges=15%' 14530#@cli : $ image.jpg +edges 15% 14531edges : skip ${1=15%} 14532 e[^-1] "Estimate image contours of image$?, with threshold $1." 14533 gradient_norm b 0.5 >= $1 distance 0 equalize negate c 30%,70% n 0,1 14534 14535#@cli erode : size>=0 : size_x>=0,size_y>=0,_size_z>=0 : \ 14536# [kernel],_boundary_conditions,_is_real={ 0=binary-mode | 1=real-mode } : (+) 14537#@cli : Erode selected images by a rectangular or the specified structuring element. 14538#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann }. 14539#@cli : Default values: 'size_z=1', 'boundary_conditions=1' and 'is_real=0'. 14540#@cli : $ image.jpg +erode 10 14541 14542#@cli erode_circ : _size>=0,_boundary_conditions,_is_normalized={ 0 | 1 } 14543#@cli : Apply circular erosion of selected images by specified size. 14544#@cli : Default values: 'boundary_conditions=1' and 'is_normalized=0'. 14545#@cli : $ image.jpg +erode_circ 7 14546erode_circ : check $1>=0 skip ${2=1},${3=0} 14547 e[^-1] "Apply circular erosion of image$? by size $1, boundary conditions $2 and is_normalized $3." 14548 if $1<2 return fi 14549 shape_circle $1 erode[^-1] .,$2,$3 rm. 14550 14551#@cli erode_oct : _size>=0,_boundary_conditions,_is_normalized={ 0 | 1 } 14552#@cli : Apply octagonal erosion of selected images by specified size. 14553#@cli : Default values: 'boundary_conditions=1' and 'is_normalized=0'. 14554#@cli : $ image.jpg +erode_oct 7 14555erode_oct : check $1>=0 skip ${2=1},${3=0} 14556 e[^-1] "Apply octagonal erosion of image$? by size $1, boundary conditions $2 and is_normalized $3." 14557 if $1<2 return fi 14558 if $1&1 ss={$1} else ss={$1+1} fi 14559 i[0] (0,1,0;1,1,1;0,1,0) i[1] (1,1,1;1,1,1;1,1,1) 14560 repeat $!-2 14561 r={round(($ss-1)*sqrt(2)/(1+sqrt(2))/2)} 14562 q={round(($ss-1)/(1+sqrt(2))/2)} 14563 if $r>0 repeat $r erode. [0],$2,$3 done fi 14564 if $q>0 repeat $q erode. [1],$2,$3 done fi 14565 mv. 2 done rm[0,1] 14566 14567#@cli erode_threshold : size_x>=1,size_y>=1,size_z>=1,_threshold>=0,_boundary_conditions 14568#@cli : Erode selected images in the (X,Y,Z,I) space. 14569#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann }. 14570#@cli : Default values: 'size_y=size_x', 'size_z=1', 'threshold=255' and 'boundary_conditions=1'. 14571erode_threshold : check "isint($1) && $1>=1 && isint(${2=$1}) && $2>=1 && isint(${3=1}) && $3>=1 && ${4=255}>=0 && 14572 isint(${5=1}) && $5>=0" 14573 e[^-1] "Erode image$? with mask $1x$2x$3, threshold $4 and "${arg\ $5,dirichlet,neumann}" boundary conditions." 14574 l[] 14575 dx1={int($1/2)} dx2={$1-$dx1-1} 14576 dy1={int($2/2)} dy2={$2-$dy1-1} 14577 dz1={int($3/2)} dz2={$3-$dz1-1} 14578 (-$dx1,$dx1) (-$dy1;$dy1) (-$dz1/$dz1) r $1,$2,$3,1,3 a c round r {w*h*d},3,1,1,-1 transpose. 14579 i.. 1,100%,1,1,254 1,100%,1,1,255 a x 14580 ('{^}') rm.. replace_str "254,","(v=j(" replace_str ",255",",0,0,$5);if(abs(v-i)<=$4,v,1e20))" list={t} 14581 rm 14582 endl 14583 f 'min($list)' 14584 14585#@cli fft : _{ x | y | z }...{ x | y | z } : (+) 14586#@cli : Compute the direct fourier transform (real and imaginary parts) of selected images, 14587#@cli : optionally along the specified axes only. 14588#@cli : See also: ''ifft''. 14589#@cli : $ image.jpg luminance +fft append[-2,-1] c norm[-1] log[-1] shift[-1] 50%,50%,0,0,2 14590#@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 \ 14591# shift -$w2,-$h2,0,0,2 ifft remove[-1] 14592#@cli : $$ https://gmic.eu/oldtutorial/_fft 14593 14594#@cli g : eq. to 'gradient'. : (+) 14595 14596#@cli gradient : { x | y | z }...{ x | y | z },_scheme : (no arg) : (+) 14597#@cli : Compute the gradient components (first derivatives) of selected images. 14598#@cli : (eq. to 'g').\n 14599#@cli : 'scheme' can be { -1=backward | 0=centered | 1=forward | 2=sobel | 3=rotation-invariant (default) | \ 14600# 4=deriche | 5=vanvliet }. 14601#@cli : (no arg) compute all significant components. 14602#@cli : Default value: 'scheme=0'. 14603#@cli : $ image.jpg gradient 14604#@cli : $$ https://gmic.eu/oldtutorial/_gradient 14605 14606#@cli gradient_norm 14607#@cli : Compute gradient norm of selected images. 14608#@cli : $ image.jpg gradient_norm equalize 14609#@cli : $$ https://gmic.eu/oldtutorial/_gradient_norm 14610gradient_norm : 14611 e[^-1] "Compute gradient norm of image$?." 14612 repeat $! l[$>] g sqr s c + sqrt endl done 14613 14614#@cli gradient_orientation : _dimension={1,2,3} 14615#@cli : Compute N-d gradient orientation of selected images. 14616#@cli : Default value: 'dimension=3'. 14617#@cli : $ image.jpg +gradient_orientation 2 14618gradient_orientation : check "${1=3}==1 || $1==2 || $1==3" 14619 e[^-1] "Compute $1-d gradient orientation of image$?." 14620 repeat $! l[$<] 14621 if $1==1 g x +abs. +. 1e-8 -/ 14622 elif $1==2 g xy +sqr +[-2,-1] +. 1e-8 sqrt. /... . /[-2,-1] 14623 else g xyz +sqr +[-3--1] +. 1e-8 sqrt. /[-4,-3] . /[-2,-1] 14624 fi 14625 endl done 14626 14627#@cli guided : [guide],radius[%]>=0,regularization[%]>=0 : radius[%]>=0,regularization[%]>=0 : (+) 14628#@cli : Blur selected images by guided image filtering. 14629#@cli : If a guide image is provided, it is used to drive the smoothing process. 14630#@cli : A guide image must be of the same xyz-size as the selected images. 14631#@cli : This command implements the filtering algorithm described in: 14632#@cli : He, Kaiming; Sun, Jian; Tang, Xiaoou, "Guided Image Filtering", 14633#@cli : IEEE Transactions on Pattern Analysis and Machine Intelligence, vol.35, no.6, pp.1397,1409, June 2013 14634#@cli : $ image.jpg +guided 5,400 14635 14636#@cli haar : scale>0 14637#@cli : Compute the direct haar multiscale wavelet transform of selected images. 14638#@cli : See also: ''ihaar''. 14639#@cli : $$ https://gmic.eu/oldtutorial/_haar 14640haar : check "isint(${1=1}) && $1>=0" 14641 e[^-1] "Compute haar transform of image$? with $1 scales." 14642 repeat $! l[$>] 14643 _haar 14644 repeat $1-1 14645 w={max(0,round(w/2^(1+$>))-1)} 14646 h={max(0,round(h/2^(1+$>))-1)} 14647 d={max(0,round(d/2^(1+$>))-1)} 14648 +z 0,0,0,$w,$h,$d _haar. j.. . rm. 14649 done 14650 endl done 14651 14652_haar : # Mono-scale direct haar transform. 14653 _haar_x _haar_y _haar_z 14654 14655_haar_x : # Direct haar transform along the x-axis. 14656 if w<=1 return fi 14657 if w%2 error[0--6] "Command 'haar': Invalid image width="{w}" (is not even)." fi 14658 +shift -1 r 50% +-[1] [0] +[0,1] / {sqrt(2)} a x 14659 14660_haar_y : # Direct haar transform along the y-axis. 14661 if h<=1 return fi 14662 if h%2 error[0--6] "Command 'haar': Invalid image height="{h}" (is not even)." fi 14663 +shift 0,-1 r 100%,50% +-[1] [0] +[0,1] / {sqrt(2)} a y 14664 14665_haar_z : # Direct haar transform along the z-axis. 14666 if d<=1 return fi 14667 if d%2 error[0--6] "Command 'haar': Invalid image depth="{h}" (is not even)." fi 14668 +shift 0,0,-1 r 100%,100%,50% +-[1] [0] +[0,1] / {sqrt(2)} a z 14669 14670#@cli heat_flow : _nb_iter>=0,_dt,_keep_sequence={ 0 | 1 } 14671#@cli : Apply iterations of the heat flow on selected images. 14672#@cli : Default values: 'nb_iter=10', 'dt=30' and 'keep_sequence=0'. 14673#@cli : $ image.jpg +heat_flow 20 14674heat_flow : skip ${1=10},${2=30},${3=0} 14675 e[^-1] "Apply $1 iterations of the heat flow on image$?, with time step $2." 14676 pde_flow $1,$2,laplacian,$3 14677 14678#@cli hessian : { xx | xy | xz | yy | yz | zz }...{ xx | xy | xz | yy | yz | zz } : (no arg) : (+) 14679#@cli : Compute the hessian components (second derivatives) of selected images. 14680#@cli : (no arg) compute all significant components. 14681#@cli : $ image.jpg hessian 14682 14683#@cli idct : _{ x | y | z }...{ x | y | z } : (no arg) 14684#@cli : Compute the inverse discrete cosine transform of selected images, optionally along the specified axes only. 14685#@cli : Output images are always evenly sized, so this command may change the size of the selected images. 14686#@cli : (dct images obtained with the 'dct' command are evenly sized anyway). 14687#@cli : Default values: (no arg) 14688#@cli : See also: ''dct''. 14689#@cli : $$ https://gmic.eu/oldtutorial/_dct-and-idct 14690idct : skip ${1=0} 14691 ('"$1"') 14692 is_axes={im>=_'x'" && "iM<=_'z'} 14693 if $is_axes 14694 e[0--3] "Compute inverse discrete cosine transform of image$? along axes '$1'." 14695 repeat w 14696 axis={i[$>]} 14697 if $axis==_'x' repeat $!-1 l[$>] if w>1 _idct fi endl done 14698 elif $axis==_'y' repeat $!-1 l[$>] if h>1 permute yxzc _idct permute yxzc fi endl done 14699 elif $axis==_'z' repeat $!-1 l[$>] if d>1 permute zxyc _idct permute yzxc fi endl done 14700 fi 14701 done 14702 rm. 14703 else 14704 rm. 14705 e[0--3] "Compute inverse discrete cosine transform of image$?." 14706 noarg 14707 repeat $! l[$>] 14708 if w>1 _idct fi 14709 if h>1 permute yxzc _idct permute yxzc fi 14710 if d>1 permute zxyc _idct permute yzxc fi 14711 endl done 14712 fi 14713 14714# 1D inverse transform (DCT-III) along the x-axis, for a single image. 14715_idct : 14716 if w%2 r {w+1},100%,100%,100%,0,0 fi 14717 / {sqrt(2/w)} +z[0] 0,0 *. {sqrt(2)} j.. .,0,0,0 rm. # Make the transform orthogonal. 14718 +mirror x shift. 1 *. -1 14719 100%,1,1,1,cos(x*pi/(2*w)) 14720 100%,1,1,1,sin(x*pi/(2*w)) 14721 +*[0,3] +*[1,2] +[-2,-1] 14722 *[0,2] *[1,2] -[0,1] 14723 ifft x k[0] / 2 14724 s x,2 mirror. x 14725 r[0] 200%,100%,100%,100%,4,0,0 14726 r[1] 200%,100%,100%,100%,4,0,1 14727 + 14728 14729#@cli iee 14730#@cli : Compute gradient-orthogonal-directed 2nd derivative of image(s). 14731#@cli : $ image.jpg iee 14732iee : 14733 e[^-1] "Compute gradient-orthogonal-directed 2nd derivative of image$?." 14734 repeat $! l[$>] 14735 if d==1 14736 +g xy,0 hessian... xxxyyy # ixx ixy iyy ix iy 14737 *... .. *[-4] . *[-4] -2 # ixx -2iyixy ixiyy ix iy 14738 +[-4,-3] *... .. # ixx -2ixiyixy+ix^2iyy ix iy 14739 sqr[-2,-1] *[-4] . +[-4,-3] # iy^2ixx-2ixiyixy+ix^2iyy ix^2 iy^2 14740 +[-2,-1] +. 1e-8 / # (iy^2ixx+2ixiyixy+ix^2iyy)/(ix^2+iy^2) 14741 else 14742 +inn laplacian.. - 14743 fi 14744 endl done 14745 14746#@cli ifft : _{ x | y | z }...{ x | y | z } : (+) 14747#@cli : Compute the inverse fourier transform (real and imaginary parts) of selected images. 14748#@cli : optionally along the specified axes only. 14749#@cli : See also: ''fft''. 14750#@cli : $$ https://gmic.eu/oldtutorial/_fft 14751 14752#@cli ihaar : scale>0 14753#@cli : Compute the inverse haar multiscale wavelet transform of selected images. 14754#@cli : See also: ''haar''. 14755#@cli : $$ https://gmic.eu/oldtutorial/_haar 14756ihaar : check "isint(${1=1}) && $1>=0" 14757 e[^-1] "Compute inverse haar transform of image$? with $1 scales." 14758 repeat $! l[$>] 14759 repeat $1-1 14760 w={max(0,round(w/2^(1+$<))-1)} 14761 h={max(0,round(h/2^(1+$<))-1)} 14762 d={max(0,round(d/2^(1+$<))-1)} 14763 +z 0,0,0,$w,$h,$d _ihaar. j.. . rm. 14764 done 14765 _ihaar 14766 endl done 14767 14768_ihaar : # Mono-scale inverse haar transform. 14769 _ihaar_x _ihaar_y _ihaar_z 14770 14771_ihaar_x : # Inverse haar transform along the x-axis. 14772 if w<=1 return fi 14773 if w%2 error[0--6] "Command 'ihaar': Invalid image width="{w}" (is not even)." fi 14774 s x,2 r 200% (-1,1) *[-2,-1] + / {sqrt(2)} 14775 14776_ihaar_y : # Inverse haar transform along the y-axis. 14777 if h<=1 return fi 14778 if h%2 error "Command 'ihaar': Invalid image height="{h}" (is not even)." fi 14779 s y,2 r 100%,200% (-1;1) r. {-2,w} *[-2,-1] + / {sqrt(2)} 14780 14781_ihaar_z : # Inverse haar transform along the z-axis. 14782 if d<=1 return fi 14783 if d%2 error "Command 'ihaar': Invalid image depth="{h}" (is not even)." fi 14784 s z,2 r 100%,100%,200% (-1/1) r. {-2,w},{-2,h} *[-2,-1] + / {sqrt(2)} 14785 14786#@cli ilaplacian : { nb_iterations>0 | 0 },_[initial_estimate] 14787#@cli : Invert selected Laplacian images. 14788#@cli : If given 'nb_iterations' is '0', inversion is done in Fourier space (single iteration), 14789#@cli : otherwise, by applying 'nb_iterations' of a Laplacian-inversion PDE flow. 14790#@cli : Note that the resulting inversions are just estimation of possible/approximated solutions. 14791#@cli : Default values: 'nb_iterations=0' and '[initial_estimated]=(undefined)'. 14792#@cli : $ image.jpg +laplacian +ilaplacian[-1] 0 14793ilaplacian : check "${1=0}>=0" skip "${2=}" 14794 is_estimate=${"is_image_arg $2"} nb_iter={round($1)} 14795 if !$nb_iter # Inversion in Fourier space 14796 if $is_estimate 14797 e[0--4] "Invert Laplacian image$? in Fourier space, with initial estimate $2." 14798 pass$2 1 ia=${-average_colors} rm. 14799 else 14800 e[0--4] "Invert Laplacian image$? in Fourier space." 14801 ia=0 14802 fi 14803 repeat $! l[$>] 14804 fft 100%,100%,1,1,"2*(cos(x*2*pi/w) + cos(y*2*pi/h)) - 4" =. 1 14805 /[-3,-2] . rm. 14806 = 0 ifft rm. 14807 endl done + '"begin(S = resize(["$ia"],s,0)); S"' 14808 14809 else # Inversion with PDE-flow 14810 if $is_estimate 14811 e[0--4] "Invert Laplacian image$? using $1 iterations of PDE flow and 14812 initial estimate $2." 14813 repeat $! pass$2 0 l[$>,-1] 14814 *[0] 5 i[1] (0,5,0;5,0,5;0,5,0) 14815 repeat $1 +convolve. [1] -. [0] +[-2,-1] /. 21 done k. # Optimized semi-implicit scheme, with dt=5 14816 endl done 14817 else 14818 e[0--4] "Invert Laplacian image$? using $1 iterations of PDE flow." 14819 repeat $! l[$>] 14820 * 5 (0,5,0;5,0,5;0,5,0) +f.. 0 14821 repeat $1 +convolve. [1] -. [0] +[-2,-1] /. 21 done k. # Optimized semi-implicit scheme, with dt=5 14822 endl done 14823 fi 14824 fi 14825 14826#@cli inn 14827#@cli : Compute gradient-directed 2nd derivative of image(s). 14828#@cli : $ image.jpg inn 14829inn : 14830 e[^-1] "Compute gradient-directed 2nd derivative of image$?." 14831 repeat $! l[$>] 14832 if d==1 14833 +g xy,0 hessian... xxxyyy # ixx ixy iyy ix iy 14834 *[-5] .. *[-4] . *[-4] 2 # ixixx 2iyixy iyy ix iy 14835 +[-5,-4] *[-4] .. # ix^2ixx+2ixiyixy iyy ix iy 14836 sqr[-2,-1] *... . +[-4,-3] # ix^2ixx+2ixiyixy+iy^2iyy ix^2 iy^2 14837 +[-2,-1] +. 1e-8 / # (ix^2ixx+2ixiyixy+iy^2iyy)/(ix^2+iy^2) 14838 else 14839 +g xyz,0 hessian[-4] xxxyxzyyyzzz # ixx ixy ixz iyy iyz izz ix iy iz 14840 *[-9] ... *[-8] .. *[-8] 2 *[-7] . *[-7] 2 # ixixx 2iyixy 2izixz iyy iyz izz ix iy iz 14841 +[-9--7] *[-7] ... # ix^2ixx+2ixiyixy+2ixizixy iyy iyz izz ix iy iz 14842 *[-6] .. *[-5] . *[-5] 2 # ix^2ixx+2ixiyixy+2ixizixy iyiyy 2iziyz izz ix iy iz 14843 +[-6,-5] *[-5] .. +[-6,-5] # ix^2ixx+2ixiyixy+2ixizixy+iy^2iyy+2iyiziyz izz ix iy iz 14844 sqr[-3--1] *[-4] . +[-5,-4] # ix^2ixx+2ixiyixy+2ixizixy+iy^2iyy+2iyiziyz+iz^2izz ix^2 iy^2 iz^2 14845 +[-3--1] +. 1e-8 / # (ix^2ixx+2ixiyixy+2ixizixy+iy^2iyy+2iyiziyz+iz^2izz)/(ix^2+iy^2+iz^2) 14846 fi 14847 endl done 14848 14849#@cli inpaint : [mask] : [mask],0,_fast_method : \ 14850# [mask],_patch_size>=1,_lookup_size>=1,_lookup_factor>=0,_lookup_increment!=0,_blend_size>=0,\ 14851# 0<=_blend_threshold<=1,_blend_decay>=0,_blend_scales>=1,_is_blend_outer={ 0 | 1 } : (+) 14852#@cli : Inpaint selected images by specified mask. 14853#@cli : If no patch size (or 0) is specified, inpainting is done using a fast average or median algorithm. 14854#@cli : Otherwise, it used a patch-based reconstruction method, that can be very time consuming. 14855#@cli : 'fast_method' can be { 0=low-connectivity average | 1=high-connectivity average | 2=low-connectivity median | \ 14856# 3=high-connectivity median }. 14857#@cli : Default values: 'patch_size=0', 'fast_method=1', 'lookup_size=22', 'lookup_factor=0.5', 'lookup_increment=1', \ 14858# 'blend_size=0', 'blend_threshold=0', 'blend_decay=0.05', 'blend_scales=10' and 'is_blend_outer=1'. 14859#@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] 14860#@cli : $ image.jpg 100%,100% circle 30%,30%,30,1,255,0,255 circle 70%,70%,50,1,255,0,255 \ 14861# +inpaint[0] [1],5,15,0.5,1,9,0 remove[1] 14862 14863#@cli inpaint_pde : [mask],_nb_scales[%]>=0,_diffusion_type={ 0=isotropic | 1=delaunay-guided | \ 14864# 2=edge-guided | 3=mask-guided },_diffusion_iter>=0 14865#@cli : Inpaint selected images by specified mask using a multiscale transport-diffusion algorithm. 14866#@cli : If 'diffusion type==3', non-zero values of the mask (e.g. a distance function) are used 14867#@cli : to guide the diffusion process. 14868#@cli : Default values: 'nb_scales=75%', 'diffusion_type=1' and 'diffusion_iter=20'. 14869#@cli : $ image.jpg 100%,100% ellipse[-1] 30%,30%,40,30,0,1,255 +inpaint_pde[0] [1] 14870inpaint_pde : check ${is_image_arg\ $1}" && ${2=75%}>=0 && isint(${3=1}) && $3>=0 && $3<=3 && ${4=20}>=0" 14871 s0="isotropic" s1="delaunay-guided" s2="edge-guided" s3="mask-guided" 14872 e[^-1] "Inpaint image$? by mask $1, using a multiscale diffusion algorithm with $2 scales 14873 and $4 iterations of "${s$3}" diffusion." 14874 repeat $! nm={n} pass$1 l[$>,-1] 14875 nb_scalesM={ceil(log2(max(w,h,d)))} 14876 nb_scales={round(${"is_percent $2"}?$nb_scalesM*$2:$2)} 14877 nb_scales={max(1,min($nb_scales,$nb_scalesM))} 14878 nb_iter={max(5,$4)} 14879 14880 repeat $nb_scales 14881 {0,"S = 2^"$<"; round([ max(1,w/S), max(1,h/S), max(1,d/S), s ])"} 14882 100%,100%,100% 14883 eval[1] "const wl1 = w#-1 - 1; const hl1 = h#-1 - 1; const dl1 = d#-1 - 1; 14884 const w1 = max(1,w - 1); const h1 = max(1,h - 1); const d1 = max(1,d - 1); 14885 !i?( 14886 X = round(x*wl1/w1); Y = round(y*hl1/h1); Z = round(z*dl1/d1); 14887 I(#-2,X,Y,Z) += I(#0,x,y,z); 14888 ++i(#-1,X,Y,Z) 14889 );I" 14890 +max. 1 /[-3,-1] !=. 0 14891 14892 if !$> # First scale: Initialize by value propagation 14893 im={-2,im} +-.. {$im-1} *. .. 14894 +distance.. 1 *. -1 watershed.. . rm. 14895 +. {$im-1} mv. -3 14896 fi 14897 14898 if $>>0" || "$nb_scales==1 14899 14900 # Apply diffusion iterations. 14901 ri... ..,3 14902 if $3==0 # Isotropic diffusion 14903 repeat $nb_iter j... ..,0,0,0,0,1,. b... 0.5 done 14904 14905 elif $3==1 # Delaunay-guided 14906 +distance. 1 100%,100%,100%,{d==1?2:3} 14907 eval.. "* # Apply specific gradient scheme for distance function 14908 const boundary = 1; 14909 maxabs(a,b) = (abs(a)>abs(b)?a:b); 14910 ix = maxabs(j(1) - i,i - j(-1)); 14911 iy = maxabs(j(0,1) - i,i - j(0,-1)); 14912 d>1?( 14913 iz = maxabs(j(0,0,1) - i,i - j(0,0,-1)); 14914 copy(I(#-1),[ ix,iy,iz ],3,whd); 14915 ):copy(I(#-1),[ ix,iy ],2,whd)" 14916 rm.. orientation. 14917 repeat $nb_iter 14918 j[-4] ...,0,0,0,0,1,.. 14919 +warp[-4] .,1,2,1 *.. -1 warp[-5] ..,1,2,1 +[-5,-1] /[-4] 2 14920 done 14921 rm. 14922 14923 elif $3==2 # Edge-guided 14924 repeat $nb_iter 14925 +diffusiontensors... 0,1,1.5,0.5 14926 j[-4] ...,0,0,0,0,1,.. 14927 smooth[-4] .,1,10,0 rm. 14928 done 14929 14930 else # Mask-guided 14931 +r[1] .,2 g. a[-{d==1?2:3}--1] c orientation. 14932 repeat $nb_iter 14933 j[-4] ...,0,0,0,0,1,.. 14934 +warp[-4] .,1,2,1 *.. -1 warp[-5] ..,1,2,1 +[-5,-1] /[-4] 2 14935 done rm. 14936 fi 14937 j... ..,0,0,0,0,1,. 14938 fi 14939 rm[-2,-1] 14940 done 14941 nm. $nm rv[0,-1] rm. 14942 endl rm. done 14943 14944#@cli inpaint_flow : [mask],_nb_global_iter>=0,_nb_local_iter>=0,_dt>0,_alpha>=0,_sigma>=0 14945#@cli : Apply iteration of the inpainting flow on selected images. 14946#@cli : Default values: 'nb_global_iter=10', 'nb_local_iter=100', 'dt=5', 'alpha=1' and 'sigma=3'. 14947#@cli : $ image.jpg 100%,100% ellipse[-1] 30%,30%,40,30,0,1,255 inpaint_flow[0] [1] 14948inpaint_flow : check ${is_image_arg\ $1}" && ${2=10}>=0 && ${3=100}>=0 && ${4=5}>0 && ${5=1}>=0 && ${6=3}>=0" 14949 e[^-1] "Apply $2x$3 iterations of the inpainting flow on image$?, with mask $1, time step $4, alpha $5 and sigma $6." 14950 repeat $! pass$1 0 l[$>,-1] 14951 r. [0],[0],[0],1,0 inpaint.. [1] 14952 repeat $2 14953 progress {100*$>/($2-1)} 14954 +diffusiontensors.. 0,1,$5,$6,0 *. .. smooth... .,$3,$4,0 rm. 14955 done 14956 progress 100 14957 endl rm. done 14958 14959#@cli inpaint_holes : maximal_area[%]>=0,_tolerance>=0,_is_high_connectivity={ 0 | 1 } 14960#@cli : Inpaint all connected regions having an area less than specified value. 14961#@cli : Default values: 'maximal_area=4', 'tolerance=0' and 'is_high_connectivity=0'. 14962#@cli : $ image.jpg noise 5%,2 +inpaint_holes 8,40 14963inpaint_holes : check "${1=4}>=0 && ${2=0}>=0" skip ${3=0} 14964 e[^-1] "Inpaint holes with area less than $1 pixels in image$?, with tolerance $2 and "\ 14965 ${arg\ 1+!$3,high,low}" connectivity." 14966 repeat $! l[$>] 14967 100%,100%,100% 14968 area={if(${is_percent\ $1},$1*w*h*d,$1)} 14969 repeat s#0 sh[0] $> +area. $2,$3 <=. $1 -|[1,-1] rm. done 14970 if im k[0] whd={w},{h},{d} r 1,1,1,100%,2 r $whd,100% 14971 else inpaint[0] [1],0,{2*!$2+!!$3} k[0] fi 14972 endl done 14973 14974#@cli inpaint_morpho : [mask] 14975#@cli : Inpaint selected images by specified mask using morphological operators. 14976#@cli : $ image.jpg 100%,100% ellipse[-1] 30%,30%,40,30,0,1,255 +inpaint_morpho[0] [1] 14977inpaint_morpho : check ${is_image_arg\ $1} 14978 e[^-1] "Inpaint image$? by mask $1, using morphological operators." 14979 repeat $! pass$1 0 l[$>,-1] 14980 nm={0,n} im={0,im} iM={0,iM} im1={$im-1} iM1={$iM+1} 14981 channels. 0 ==. 0 14982 +f[0] $im1 j. [0],0,0,0,0,1,.. 14983 do 14984 +dilate. 3 14985 replace.. $im1,$iM1 14986 erode.. 3 14987 replace.. $iM1,$im1 14988 +[-2,-1] /. 2 14989 j. ...,0,0,0,0,1,.. 14990 while im==$im1 14991 k. nm $nm 14992 endl done 14993 14994#@cli inpaint_matchpatch : [mask],_nb_scales={ 0=auto | >0 },_patch_size>0,_nb_iterations_per_scale>0,\ 14995# _blend_size>=0,_allow_outer_blending={ 0 | 1 },_is_already_initialized={ 0 | 1 } 14996#@cli : Inpaint selected images by specified binary mask, using a multi-scale matchpatch algorithm. 14997#@cli : Default values: 'nb_scales=0', 'patch_size=9', 'nb_iterations_per_scale=10', 'blend_size=5',\ 14998# 'allow_outer_blending=1' and 'is_already_initialized=0'. 14999#@cli : $ image.jpg 100%,100% ellipse[-1] 30%,30%,40,30,0,1,255 +inpaint_matchpatch[0] [1] 15000inpaint_matchpatch : check ${is_image_arg\ $1}"&& ${2=0}>=0 && isint(${3=9}) && $3>0 && isint(${4=10}) && $4>0 && 15001 isint(${5=5}) && $5>=0" skip ${6=1},${7=0} 15002 e[^-1] "Inpaint image$? with mask $1, using a multiscale patch-matching algorithm with "\ 15003 ${"if $2 u \"$2 \" else u auto- fi"}\ 15004 "scales, $3x$3 patches, $4 iterations per scale and blending size $5." 15005 repeat $! pass$1 0 l[$>,-1] nm={0,n} 15006 15007 # Init variables and images. 15008 nm={0,n} nm img,mask 15009 nb_scales={max(1,round(if($2,$2,log2(min(w,h)/16)),1,1))} 15010 visu_size=${fitscreen[]" "{0,[w,h,1]},25%,50%} 15011 slices[img] 0 r[mask] [img],[img],1,1,0 !=[mask] 0 15012 if !$7 inpaint_pde[img] [mask],75% fi # Quick first estimate. 15013 im={img,im} -[img] $im 15014 15015 first_iter=1 iter=0 15016 repeat $nb_scales 15017 scale={100*(0.5^$<)} 15018 e[] "> Process scale "{1+$>}"/"$nb_scales" -> "$scale% 15019 progress {100*$>/max(1,$nb_scales-1)} 15020 15021 # Compute image and mask at current scales. 15022 +r[img,mask] $scale%,$scale%,1,100%,2 nm[-2,-1] scaled_img,scaled_mask 15023 >=[scaled_mask] 0.95 15024 if {scaled_mask,!iM} rm[scaled_img,scaled_mask] continue fi # Skip scale (if too low). 15025 +f[scaled_img] -4096 +j[scaled_img] .,0,0,0,0,1,[scaled_mask] rm.. nm. scaled_reference 15026 15027 coef={0.5^($nb_scales-$iter)} 15028 patch_size={v=round(max(min($3,5),$3*$coef));v+(1-(v%2))} 15029 patch_size={min(w,h,$patch_size)} 15030 blend_size={v=if($5,round(max(3,$5*$coef)));v+(1-(v%2))} 15031 iter+=1 15032 ==[scaled_mask] 0 15033 15034 if $first_iter # First iteration. 15035 15036 # Estimate initial correspondence map. 15037 100%,100%,1,1,x +f. y mv[scaled_mask] $! a[-3--1] c 15038 matchpatch[scaled_img] [scaled_reference],$patch_size,$patch_size,1,4,4,0,0,. 15039 rm[scaled_reference,-1] 15040 nm. correspondence 15041 first_iter=0 15042 15043 else # Standard iteration. 15044 15045 # Upscale correspondence map from previous scale. 15046 *[correspondence] 2 r[correspondence] 200%,200%,1,2 r[correspondence] [scaled_img],[scaled_img],1,2,0,1 15047 100%,100%,1,1,x +f. y a[-2,-1] c 15048 f[scaled_mask] "*if(i,1, 15049 upc = i(#"$correspondence",x-1,y,0,0); vpc = i(#"$correspondence",x-1,y,0,1); 15050 ucp = i(#"$correspondence",x,y-1,0,0); vcp = i(#"$correspondence",x,y-1,0,1); 15051 ucc = i(#"$correspondence",x,y,0,0); vcc = i(#"$correspondence",x,y,0,1); 15052 i(#-1,x,y,0,0) = (ucc==upc && vcc==vpc)?upc + 1:ucc; 15053 i(#-1,x,y,0,1) = (ucc==ucp && vcc==vcp)?vcp + 1:vcc; 15054 0)" 15055 rm[correspondence] nm. correspondence 15056 a[correspondence] [scaled_mask],c 15057 15058 # Refine correspondence map iteratively with matchpatch. 15059 nbs1={max(1,$nb_scales-1)} 15060 nb_iter={round(max(1,$4*(($<+1)/$nbs1)^2))} 15061 15062 repeat $nb_iter 15063 _inpaint_matchpatch[scaled_img] [correspondence],[scaled_mask],$blend_size,$6 15064 +matchpatch[scaled_img] [scaled_reference],$patch_size,$patch_size,1,4,4,0,0,[correspondence] 15065 j[correspondence] . rm. 15066 if {*1} w1[scaled_img] $visu_size,0 fi 15067 if {*2} w2[correspondence] $visu_size,1 fi 15068 done 15069 rm[scaled_img,scaled_mask,scaled_reference] channels[correspondence] 0,1 15070 fi 15071 15072 done 15073 progress 100 15074 15075 # Generate final result. 15076 if $correspondence 15077 ==[mask] 0 15078 _inpaint_matchpatch[img] [correspondence],[mask],$5,$6 15079 rm[correspondence] 15080 fi 15081 +[img] $im 15082 nm[0] $nm 15083 endl rm[mask] done 15084 15085# _inpaint_matchpatch : [correspondence_map],[mask],blend_size>0,_allow_outer_blending={ 0 | 1 } 15086_inpaint_matchpatch : 15087 pass$1 1 pass$2 {!$3" || "!$4} 15088 if !$3 15089 warp[0] [1],0,0,1 15090 else 15091 if $4 erode. $3 fi 15092 f[0] "*begin( 15093 boundary = 1; 15094 const patch_size = $3; 15095 const p2 = int(patch_size/2); 15096 const p1 = patch_size - p2 - 1; 15097 avg = resize([0],s#0); 15098 15099 # Pre-compute gaussian kernel for patch blending. 15100 wpq = resize([0],patch_size^2); 15101 g = 0; 15102 for (q = -p1, q<=p2, ++q, 15103 for (p = -p1, p<=p2, ++p, 15104 wpq[g++] = exp(-(p^2 + q^2)/(2*(0.3*patch_size)^2)); 15105 ); 15106 ); 15107 ); 15108 if (i#2,I, 15109 g = 0; 15110 avg = 0; 15111 norm = 0; 15112 for (q = -p1, q<=p2, ++q, 15113 for (p = -p1, p<=p2, ++p, 15114 U = I(#1,x + p,y + q); 15115 w = wpq[g++]; 15116 norm+=w; 15117 avg+=w*I(#0,U[0,2] - [p,q]); 15118 ); 15119 ); 15120 avg/norm)" 15121 fi 15122 k[0] 15123 15124# _inpaint_warping2d : fill-in zero-valued vectors in absolute 2d warping field (works even when 'spectrum>2'). 15125_inpaint_warping2d : 15126 repeat $! l[$>] 15127 100%,100%,100%,2,"> begin(const S = s#0; zero0 = vectorS(); zero1 = [0,0]; N = 0); I(#-1)==zero0?zero1:[++N,1]" 15128 s. c distance. 1 *. -1 15129 watershed.. . rm. 15130 15131 # Propagate offsets in each distinct voronoi cell. 15132 repeat 2 15133 f.. ">i?I:( # Forward propagation 15134 nP = vectors(); 15135 const sP = size(nP); 15136 r = i(#-1); 15137 (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)): 15138 (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)): 15139 (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)): 15140 (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)); 15141 nP)" 15142 f.. "<i?I:( # Backward propagation 15143 nP = vectors(); 15144 const sP = size(nP); 15145 r = i(#-1); 15146 (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)): 15147 (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)): 15148 (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)): 15149 (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)); 15150 nP)" 15151 done 15152 rm. 15153 endl done 15154 15155#@cli kuwahara : size>0 15156#@cli : Apply Kuwahara filter of specified size on selected images. 15157#@cli : $ image.jpg kuwahara 9 15158kuwahara : check $1>0 15159 e[^-1] "Apply Kuwahara filter of size $1 on image$?." 15160 repeat $! l[$>] 15161 s={s} 15162 +dilate $1 compose_channels. min 15163 +erode[0] $1 compose_channels. max 15164 -[-2,-1] 15165 $1,1,1,1,{1/$1} convolve[0] . transpose. convolve[0] . rm. 15166 p={int($1/2)} 15167 a[-2,-1] c 15168 f "v1=i(x-"$p",y-"$p",0,"$s",0,1); \ 15169 v2=i(x+"$p",y-"$p",0,"$s",0,1); \ 15170 v3=i(x-"$p",y+"$p",0,"$s",0,1); \ 15171 v4=i(x+"$p",y+"$p",0,"$s",0,1); \ 15172 vm=min(v1,v2,v3,v4); \ 15173 if(c>="$s",i, \ 15174 if(vm==v1,i(x-"$p",y-"$p",0,c,0,1), 15175 if(vm==v2,i(x+"$p",y-"$p",0,c,0,1), 15176 if(vm==v3,i(x-"$p",y+"$p",0,c,0,1), 15177 i(x+"$p",y+"$p",0,c,0,1)))))" 15178 channels 0,{s-2} 15179 endl done 15180 15181#@cli laplacian 15182#@cli : Compute Laplacian of selected images. 15183#@cli : $ image.jpg laplacian 15184laplacian : 15185 e[^-1] "Compute Laplacian of image$?." 15186 repeat $! l[$>] 15187 hessian ${arg\ 1+(d==1),xxyyzz,xxyy} + 15188 endl done 15189 15190#@cli lic : _amplitude>0,_channels>0 15191#@cli : Render LIC representation of selected vector fields. 15192#@cli : Default values: 'amplitude=30' and 'channels=1'. 15193#@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 15194lic : skip ${1=30},${2=1} 15195 e[^-1] "Render LIC representation of 2D vector field$?, with amplitude $1 and $2 channel(s)." 15196 repeat $! l[$>] nm={0,n} 15197 channels 0,1 / {max(abs(im),abs(iM))} vector2tensor 15198 100%,100%,100%,$2 rand. 0,255 smooth. ..,$1 rm.. 15199 equalize 15200 nm $nm endl done 15201 15202#@cli map_tones : _threshold>=0,_gamma>=0,_smoothness>=0,nb_iter>=0 15203#@cli : Apply tone mapping operator on selected images, based on Poisson equation. 15204#@cli : Default values: 'threshold=0.1', 'gamma=0.8', 'smoothness=0.5' and 'nb_iter=30'. 15205#@cli : $ image.jpg +map_tones , 15206map_tones : skip ${1=0.1},${2=0.8},${3=0.5},${4=30} 15207 e[^-1] "Apply tone mapping operator on image$?, with threshold $1, gamma $2, smoothness $3 and $4 iterations." 15208 repeat $! l[$>] 15209 15210 # Estimate target divergence for each channel. 15211 +l s c repeat $! l[$>] 15212 g xy,1 a c +norm orientation.. 15213 m={im} M={iM} b. $3 n. $m,$M 15214 *. 'alpha=$1*iM;(alpha/(1e-10+i))*(i/(1e-10+alpha))^$2' 15215 * s c g.. x,-1 g. y,-1 + 15216 endl done a c * 0.25 endl 15217 15218 # Start Poisson-PDE iterations 15219 repeat $4 +laplacian.. *. 0.25 +. ... -. .. *. 800 +[-3,-1] /.. 801 c.. 0,255 done rm. 15220 15221 endl done 15222 15223#@cli map_tones_fast : _radius[%]>=0,_power>=0 15224#@cli : Apply fast tone mapping operator on selected images. 15225#@cli : Default values: 'radius=3%' and 'power=0.3'. 15226#@cli : $ image.jpg +map_tones_fast , 15227map_tones_fast : check "${1=3%}>=0 && ${2=0.3}>=0" 15228 e[^-1] "Apply fast tone mapping operator on image$?, with radius $1 and power $2." 15229 repeat $! l[$>] 15230 +luminance b. $1 n 0,1 15231 +*. 2 -. 1 abs. *. {$2*log(10)} exp. 15232 <=.. 0.5 ri. ... 15233 +*... -1 +. 1 ^. .. *. -1 +. 1 *. ... 15234 ^[-4,-2] ==.. 0 *[-3,-2] + 15235 endl done n 0,255 15236 15237#@cli meancurvature_flow : _nb_iter>=0,_dt,_keep_sequence={ 0 | 1 } 15238#@cli : Apply iterations of the mean curvature flow on selected images. 15239#@cli : Default values: 'nb_iter=10', 'dt=30' and 'keep_sequence=0'. 15240#@cli : $ image.jpg +meancurvature_flow 20 15241meancurvature_flow : skip ${1=10},${2=30},${3=0} 15242 e[^-1] "Apply $1 iterations of the mean curvature flow on image$?, with time step $2." 15243 pde_flow $1,$2,iee,$3 15244 15245#@cli median : size>=0,_threshold>0 : (+) 15246#@cli : Apply (opt. thresholded) median filter on selected images with structuring element size x size. 15247#@cli : $ image.jpg +median 5 15248 15249#@cli nlmeans : [guide],_patch_radius>0,_spatial_bandwidth>0,_tonal_bandwidth>0,_patch_measure_command : \ 15250# _patch_radius>0,_spatial_bandwidth>0,_tonal_bandwidth>0,_patch_measure_command 15251#@cli : Apply non local means denoising of Buades et al, 2005. on selected images. 15252#@cli : The patch is a gaussian function of 'std_patch_radius'. 15253#@cli : The spatial kernel is a rectangle of radius 'spatial_bandwidth'. 15254#@cli : The tonal kernel is exponential (`exp(-d^2/_tonal_bandwidth^2)`) 15255#@cli : with `d` the euclidean distance between image patches. 15256#@cli : Default values: 'patch_radius=4', 'spatial_bandwidth=4', 'tonal_bandwidth=10' and 'patch_measure_command=-norm'. 15257#@cli : $ image.jpg +noise 10 nlmeans[-1] 4,4,{0.6*${-std_noise}} 15258nlmeans: 15259 if ${"is_image_arg $1"} 15260 15261 # Guided-filtering 15262 check "${2=4}>0 && ${3=4}>0 && ${4=10}>0" skip "${5=-norm}" 15263 e[^-1] "Apply non-local means denoising on image$?, with guide $1, patch size $2, spatial bandwidth $3, 15264 tonal bandwidth $4 and patch measure command '$5'." 15265 pass$1 0 l. $5 k[0] endl # [1] preprocessed image used to compute weights. 15266 repeat $!-1 l[$>,-1] 15267 100%,100%,100%,100%,{-1.0/($4*$4)} # [2] compute a scaling. 15268 nlmeans_core[0] [1],[2],$2,$3 rm. # Apply the NLM denoising with image 1 and 2 as parameter. 15269 endl done 15270 rm. 15271 15272 else 15273 15274 # Non-guided filtering 15275 check "${1=4}>0 && ${2=4}>0 && ${3=10}>0" skip "${4=-norm}" 15276 e[^-1] "Apply non-local means denoising on image$?, with patch size $1, spatial bandwidth $2, 15277 tonal bandwidth $3 and patch measure command '$4'." 15278 repeat $! l[$>] 15279 +l $4 k[0] endl # [1] preprocessed image used to compute weights. 15280 100%,100%,100%,100%,{-1.0/($3*$3)} # [2] compute a scaling. 15281 nlmeans_core[0] [1],[2],$1,$2 k[0] # Apply the NLM denoising with image 1 and 2 as parameter. 15282 endl done 15283 fi 15284 15285#@cli nlmeans_core: _reference_image,_scaling_map,_patch_radius>0,_spatial_bandwidth>0 15286#@cli : Apply non local means denoising using a image for weight and a map for scaling 15287nlmeans_core : check ${is_image_arg\ $1}" && "${is_image_arg\ $2}" && $3>0 && $4>0" 15288 e[^-1] "Apply non-local means denoising using weight images $1, scaling map $2, patch size $3 and 15289 spatial bandwidth $4." 15290 pass$1 0 pass$2 0 15291 repeat $!-2 l[$>,-1,-2] 15292 # [0] original, [1] weights, [2] scaling [3] sum(weights * patch), [4] sum(weights), [5] max(weights) 15293 100%,100%,100%,{0,s},0 100%,100%,100%,{1,s},0 100%,100%,100%,{1,s},1e-6 15294 if d#0==1 15295 repeat 2*$4+1 j={$>-$4} repeat 2*$4+1 i={$>-$4} 15296 if $i!=0||$j!=0 15297 # Compute shifted images [6] and weight [7] 15298 +shift[0,1] $i,$j,0,0,2 -[7] [1] 15299 sqr[7] b[7] $3 *[7] [2] exp[7] 15300 # Accumulate weights 15301 *[6] [7] max[5] [7] +[4,7] +[3,6] 15302 fi 15303 done done 15304 else 15305 repeat 2*$4+1 k={$>-$4} repeat 2*$4+1 j={$>-$4} repeat 2*$4+1 i={$>-$4} 15306 if $i!=0||$j!=0||$k!=0 15307 # Compute shifted images [6] and weight [7] 15308 +shift[0,1] $i,$j,0,0,2 -[7] [1] 15309 sqr[7] b[7] $3 *[7] [2] exp[7] 15310 # Accumulate weights 15311 *[6] [7] max[5] [7] +[4,7] +[3,6] 15312 fi 15313 done done done 15314 fi 15315 rm[1,2] 15316 *[0] [3] +[1,0] +[1,2] # Add central patch 15317 / # Normalize 15318 endl done 15319 15320#@cli normalize_local : _amplitude>=0,_radius>0,_n_smooth>=0[%],_a_smooth>=0[%],_is_cut={ 0 | 1 },_min=0,_max=255 15321#@cli : Normalize selected images locally. 15322#@cli : Default values: 'amplitude=3', 'radius=16', 'n_smooth=4%', 'a_smooth=2%', 'is_cut=1', 'min=0' and 'max=255'. 15323#@cli : $ image.jpg normalize_local 8,10 15324normalize_local : 15325 check "${1=3}>=0 && ${2=16}>0 && isbool(${5=1})" skip ${3=4%},${4=2%},${6=0},${7=255} 15326 e[^-1] "Normalize image$? locally, with amplitude $1, radius $2, neighborhood smoothness $3 and 15327 average smoothness $4." 15328 repeat $! l[$>] 15329 +l erode {2*$2+1} s c min endl 15330 +l.. dilate {2*$2+1} s c max endl 15331 +b... $4 b[-3,-2] $3 15332 +-.. ... +. 0.01 -[-5] [-4] /[-5,-1] 15333 *[-3,-2] {$1+1} *. -$1 +... . +[-2,-1] 15334 if $5 max.. $6 min. $7 fi 15335 -. .. *[-3,-1] + 15336 if $5 c $6,$7 fi 15337 endl done 15338 15339#@cli normalized_cross_correlation : [mask] 15340#@cli : Compute normalized cross-correlation of selected images with specified mask. 15341#@cli : $ image.jpg +shift -30,-20 +normalized_cross_correlation[0] [1] 15342normalized_cross_correlation : check ${is_image_arg\ $1} 15343 e[^-1] "Compute normalized cross-correlation of image$? with mask $1." 15344 pass$1 0 norm repeat $!-1 . l[$>,-1] 15345 fft.. fft. [-2,-1] *.. [-5] *. [-6] 15346 -[-2,-1] *[-5,-3] *[-3,-2] +[-3,-2] [-2,-1] a[-2,-1] c norm. 15347 /... . /[-2,-1] ifft rm. 15348 endl done rm. 15349 15350#@cli percentile : [mask],0<=_min_percentile[%]<=100,0<=_max_percentile[%]<=100. 15351#@cli : Apply percentile averaging filter to selected images. 15352#@cli : Default values: 'min_percentile=0' and 'max_percentile=100'. 15353#@cli : $ image.jpg shape_circle 11,11 +percentile[0] [1],25,75 15354percentile : check ${"is_image_arg $1"}" && inrange(${2=0},0,100) && inrange(${3=100},0,100) && $2<=$3" 15355 vmin,vmax={_[${"is_percent $2"}?100*$2:$2,${"is_percent $3"}?100*$3:$3]} 15356 e[^-1] "Apply percentile averaging filter to image$?, with mask $1, "\ 15357 "min percentile "$vmin"% and max percentile "$vmax"%." 15358 15359 # Generate code for masking. 15360 pass$1 0 !=. 0 N={is} if !$N rm. return fi 128,$N 15361 eval.. "> 15362 begin( 15363 p = 0; 15364 const w2 = int(w/2); 15365 const h2 = int(h/2); 15366 ); 15367 i?( 15368 out = string('N[',p,']=j(',x - w2,',',y - h2,');'); 15369 copy(i(#-1,0,p++),out,size(out)); 15370 )" 15371 discard. 0 code={t} rm[-2,-1] 15372 15373 # Apply filter. 15374 f " 15375 begin( N = vector"$N"() ); 15376 const boundary = 1; 15377 const sS = size(N) - 1; 15378 const s0 = round(sS*"$vmin"%); 15379 const s1 = round(sS*"$vmax"%); 15380 const ds = 1 + s1 - s0; 15381 "$code" 15382 S = sort(N); 15383 res = 0; for (s = s0, s<=s1, ++s, res+=S[s]); res/=ds" 15384 15385#@cli peronamalik_flow : K_factor>0,_nb_iter>=0,_dt,_keep_sequence={ 0 | 1 } 15386#@cli : Apply iterations of the Perona-Malik flow on selected images. 15387#@cli : Default values: 'K_factor=20', 'nb_iter=5', 'dt=5' and 'keep_sequence=0'. 15388#@cli : $ image.jpg +heat_flow 20 15389peronamalik_flow : check "${1=20}>0 && ${2=5}>=0" skip ${3=5},${4=0} 15390 e[^-1] "Apply $2 iterations of the Perona-Malik flow on image$?, with K factor $1 and time step $3." 15391 m "_peronamalik_flow : 15392 +gradient xy,0 a[-2,-1] c norm. b. 0.8 /. $1 sqr. *. -1 exp. a[-2,-1] c 15393 f. '\"s1=s-1; 15394 C=i(x,y,z,s-1); 15395 if(c>=s1,0, 15396 (C+i(x+1,y,z,s-1,0,1))*(j(1,0,0,0,0,1)-i) - 15397 (C+i(x-1,y,z,s-1,0,1))*(i-j(-1,0,0,0,0,1)) + 15398 (C+i(x,y+1,z,s-1,0,1))*(j(0,1,0,0,0,1)-i) - 15399 (C+i(x,y-1,z,s-1,0,1))*(i-j(0,-1,0,0,0,1)))\"'" 15400 pde_flow $2,$3,_peronamalik_flow,$4 15401 um _peronamalik_flow 15402 15403#@cli phase_correlation : [destination] 15404#@cli : Estimate translation vector between selected source images and specified destination. 15405#@cli : $ image.jpg +shift -30,-20 +phase_correlation[0] [1] unroll[-1] y 15406phase_correlation : check ${"is_image_arg $1"} 15407 e[^-1] "Estimate shift between source image$? and destination $1." 15408 pass$1 15409 repeat $!-1 15410 normalized_cross_correlation[$>] . 15411 l[$>] eval " 15412 store([xM>=w/2?xM - w:xM, 15413 yM>=h/2?yM - h:yM, 15414 zM>=d/2?zM - d:zM]*=-1,'res',1,1,1,3)" 15415 endl 15416 $res nm. "[phase correlation]" rv[$>,-1] rm. 15417 done rm. 15418 15419#@cli pde_flow : _nb_iter>=0,_dt,_velocity_command,_keep_sequence={ 0 | 1 } 15420#@cli : Apply iterations of a generic PDE flow on selected images. 15421#@cli : Default values: 'nb_iter=10', 'dt=30', 'velocity_command=laplacian' and 'keep_sequence=0'. 15422#@cli : $ image.jpg +pde_flow 20 15423pde_flow : skip ${1=10},${2=30},${3=laplacian},${4=0} 15424 e[^-1] "Apply $1 iterations of the velocity flow '$3' on image$?, with time step $2." 15425 repeat $! l[$<] 15426 repeat $1 15427 +$3. *. {$2/(0.01+max(abs(im),abs(iM)))} 15428 if $4 +. .. else +[-2,-1] fi 15429 done 15430 if $4 rm[0] fi 15431 a x 15432 endl done 15433 if $4 s x,$1 fi 15434 15435#@cli periodize_poisson 15436#@cli : Periodize selected images using a Poisson solver in Fourier space. 15437#@cli : $ image.jpg +periodize_poisson array 2,2,2 15438periodize_poisson : 15439 e[^-1] "Periodize image$? using Poisson solver in Fourier space." 15440 repeat $! l[$>] 15441 s c repeat $! l[$>] 15442 mM={[im,iM]} sum={0,ia} 15443 laplacian ilaplacian 0 + $sum c $mM 15444 endl done a c 15445 endl done 15446 15447#@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) 15448#@cli : Reconstruct 1D/2D or 3D image from selected sets of keypoints, by RBF-interpolation. 15449#@cli : A set of keypoints is represented by a vector-valued image, where each pixel represents a single keypoint. 15450#@cli : Vector components of a keypoint have the following meaning: 15451#@cli : - For 1D reconstruction: [ x_k, f1(k),...fN(k) ]. 15452#@cli : - For 2D reconstruction: [ x_k,y_k, f1(k),...,fN(k) ]. 15453#@cli : - For 3D reconstruction: [ x_k,y_k,z_k, f1(k),...,fN(k) ]. 15454#@cli : Values 'x_k','y_k' and 'z_k' are the spatial coordinates of keypoint 'k'. 15455#@cli : Values 'f1(k),..,fN(k)' are the 'N' components of the vector value of keypoint 'k'. 15456#@cli : The command reconstructs an image with specified size 'dx'x'dy'x'dz', with 'N' channels. 15457#@cli : Default values: 'x0=y0=z0=0', 'x1=dx-1', 'y1=dy-1', 'z1=dz-1', 'phi(r)=r^2*log(1e-5+r)'. 15458#@cli : $ sp colorful r2dx 400 100%,100% noise_poissondisk. 10 1,{is},1,5 \ 15459# 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 15460#@cli : $ 32,1,1,5,u([400,400,255,255,255]) rbf 400,400 c 0,255 15461rbf : 15462 $=a d_phi_r=r^2*log(1e-5+r) 15463 if isin($#,1,3,4) # 1D reconstruction 15464 dx,x0,x1=$a1,{$#>1?[$a2,$a3]:[0,$a1-1]} 15465 phi_r={`$#>3?['$a4']:'$d_phi_r'`} 15466 check $dx>0 15467 e[^-1] "Reconstruct 1D image from keypoint set$?, with size "$dx", "\ 15468 "from ("$x0") to ("$x1") and phi(r) = "$phi_r. 15469 repeat $! l[$>] nm={n} if !w $dx elif whd==1 channels. 1,100% r. $dx,1,1,100% else 15470 r 1,{whd},1,100%,-1 permute. cyzx 15471 $dx,1,1,{w-1},"* 15472 begin( 15473 phi(r) = ("$phi_r"); 15474 ref(crop(#0,0,0,0,0,1,h#0,1,1),X); 15475 ref(crop(#0,1,0,0,0,s,h#0,1,1,1),F); 15476 ref(vector(#h#0^2),M); 15477 repeat (h#0,k, 15478 for (l = 0, l<=k, ++l, 15479 r = abs(X[k] - X[l]); 15480 M[k*h#0 + l] = M[l*h#0 + k] = phi(r); 15481 ) 15482 ); 15483 ref(solve(M,F,s),W); 15484 const fx = ("$x1-$x0")/(w-1); 15485 ); 15486 ref(vectors(),res); x = (x - "$x0")*fx; 15487 repeat (h#0,k, r = abs(x - X[k]); res+=W[s*k,s]*phi(r))" 15488 k. nm $nm 15489 fi endl done 15490 15491 elif isin($#,2,6,7) # 2D reconstruction 15492 dx,dy,x0,y0,x1,y1=$a1,$a2,{$#>2?[$a3,$a4,$a5,$a6]:[0,0,[$a1,$a2]-1]} 15493 phi_r={`$#>6?['$a7']:'$d_phi_r'`} 15494 check $dx>0" && "$dy>0 15495 e[^-1] "Reconstruct 2D image from keypoint set$?, with size "$dx,$dy", "\ 15496 "from ("$x0,$y0") to ("$x1,$y1") and phi(r) = "$phi_r. 15497 repeat $! l[$>] nm={n} if !w $dx,$dy elif whd==1 channels 2,100% r. $dx,$dy,1,100% else 15498 r 1,{whd},1,100%,-1 permute. cyzx 15499 $dx,$dy,1,{w-2},"* 15500 begin( 15501 phi(r) = ("$phi_r"); 15502 ref(crop(#0,0,0,0,0,1,h#0,1,1),X); 15503 ref(crop(#0,1,0,0,0,1,h#0,1,1),Y); 15504 ref(crop(#0,2,0,0,0,s,h#0,1,1,1),F); 15505 ref(vector(#h#0^2),M); 15506 repeat (h#0,k, 15507 for (l = 0, l<=k, ++l, 15508 r = norm(X[k] - X[l],Y[k] - Y[l]); 15509 M[k*h#0 + l] = M[l*h#0 + k] = phi(r); 15510 ) 15511 ); 15512 ref(solve(M,F,s),W); 15513 const fx = ("$x1-$x0")/(w-1); 15514 const fy = ("$y1-$y0")/(h-1); 15515 ); 15516 ref(vectors(),res); x = (x - "$x0")*fx; y = (y - "$y0")*fy; 15517 repeat (h#0,k, r = norm(x - X[k], y - Y[k]); res+=W[s*k,s]*phi(r))" 15518 k. nm $nm 15519 fi endl done 15520 15521 elif isin($#,3,9,10) # 3D reconstruction 15522 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]} 15523 phi_r={`$#>9?['$arg10']:'$d_phi_r'`} 15524 check $dx>0" && "$dy>0" && "$dz>0 15525 e[^-1] "Reconstruct 3D image from keypoint set$?, with size "$dx,$dy,$dz", "\ 15526 "from ("$x0,$y0,$z0") to ("$x1,$y1,$z1") and phi(r) = "$phi_r. 15527 repeat $! l[$>] nm={n} if !w $dx,$dy,$dz elif whd==1 channels 3,100% r. $dx,$dy,$dz,100% else 15528 r 1,{whd},1,100%,-1 permute. cyzx 15529 $dx,$dy,$dz,{w-3},"* 15530 begin( 15531 phi(r) = ("$phi_r"); 15532 ref(crop(#0,0,0,0,0,1,h#0,1,1),X); 15533 ref(crop(#0,1,0,0,0,1,h#0,1,1),Y); 15534 ref(crop(#0,2,0,0,0,1,h#0,1,1),Z); 15535 ref(crop(#0,3,0,0,0,s,h#0,1,1,1),F); 15536 ref(vector(#h#0^2),M); 15537 repeat (h#0,k, 15538 for (l = 0, l<=k, ++l, 15539 r = norm(X[k] - X[l],Y[k] - Y[l],Z[k] - Z[l]); 15540 M[k*h#0 + l] = M[l*h#0 + k] = phi(r); 15541 ) 15542 ); 15543 ref(solve(M,F,s),W); 15544 const fx = ("$x1-$x0")/(w - 1); 15545 const fy = ("$y1-$y0")/(h - 1); 15546 const fz = ("$z1-$z0")/(d - 1); 15547 ); 15548 ref(vectors(),res); x = (x - "$x0")*fx; y = (y - "$y0")*fy; z = (z - "$z0")*fz; 15549 repeat (h#0,k, r = norm(x - X[k], y - Y[k], z - Z[k]); res+=W[s*k,s]*phi(r))" 15550 k. nm $nm 15551 fi endl done 15552 15553 else error[0--2] "Command 'rbf': invalid arguments '$*'." 15554 fi 15555 15556#@cli red_eye : 0<=_threshold<=100,_smoothness>=0,0<=attenuation<=1 15557#@cli : Attenuate red-eye effect in selected images. 15558#@cli : Default values: 'threshold=75', 'smoothness=3.5' and 'attenuation=0.1'. 15559#@cli : $ image.jpg +red_eye , 15560red_eye : skip ${1=75},${2=3.5},${3=0.1} 15561 e[^-1] "Attenuate red-eye effect in image$?, with threshold $1, smoothness $2 and attenuation $3." 15562 to_rgb rgb2ycbcr repeat $! l[$>] 15563 s c -. 128 +>=. $1% b. $2 sqrt. *. -1 +. 1 15564 n. $3,1 *[-2,-1] +. 128 a c ycbcr2rgb 15565 endl done 15566 15567#@cli remove_hotpixels : _mask_size>0, _threshold[%]>0 15568#@cli : Remove hot pixels in selected images. 15569#@cli : Default values: 'mask_size=3' and 'threshold=10%'. 15570#@cli : $ image.jpg noise 10,2 +remove_hotpixels , 15571remove_hotpixels : check ${1=3}>0 skip ${2=10%} 15572 e[^-1] "Remove hot pixels in image$?, with mask size $1 and threshold $2." 15573 repeat $! l[$>] 15574 +median $1 +- abs. >=. $2 15575 *.. . ==. 0 *[-3,-1] + 15576 endl done 15577 15578#@cli remove_pixels : number_of_pixels[%]>=0 15579#@cli : Remove specified number of pixels (i.e. set them to 0) from the set of non-zero pixels in selected images. 15580#@cli : $ image.jpg +remove_pixels 50% 15581remove_pixels : check "$1>=0" 15582 e[^-1] "Remove $1 of the non-zero pixels in image$?." 15583 repeat $! l[$>] 15584 +norm !=. 0 15585 N={is} # Number of non-zero pixels. 15586 n={round(if(${"is_percent $1"},$N*$1,$1))} # Number of pixels to remove. 15587 if $n<=0 rm. # No pixels to remove. 15588 elif $n>=$N rm. f 0 # All pixels to remove. 15589 elif $n>int($N/2) # More pixels to remove than to keep. 15590 remove_pixels. {$N-$n} ==. 0 * 15591 else # Less pixels to remove than to keep. 15592 d={d} r 100%,{d*h},1,100%,-1 # Force image to be in 2D. 15593 15594 # Retrieve coordinates of all non-zero pixels. 15595 100%,1,1,1,x 1,{-2,h},1,1,y +[-2,-1] 1 r[-2,-1] ..,. 15596 *[-2,-1] ... rm... 15597 y[-2,-1] a[-2,-1] x discard. y,0 15598 15599 # Generate a 1xN vector with at least n non-zero pixels. 15600 do 15601 1,100%,1,1 rand. 0,{h} <=. {$n*1.25} 15602 if is>=$n break else rm. fi 15603 while 1 15604 15605 # Generate a 1xn vector of coordinates to 'remove'. 15606 r. 2 *[-2,-1] discard. y,0 15607 i.. 1,100% rand.. 0,1 a[-2,-1] x sort. +,y 15608 rows. 0,{$n-1} -. 1 z. 1,3 15609 15610 # Set those pixels to 0 using a 3D object. 15611 i.. ({'CImg3d'},{h},{h}) 15612 1,100%,1,1,1 1,100%,1,1,y a[-2,-1] x 15613 3,100% 1,100%,1,1,1 y[-5--1] a[-5--1] y 15614 if s#0<=3 j3d.. .,0,0,0,1,0,0,0,0 15615 else [0],[0],1,1,1 j3d. ..,0,0,0,1,0,0,0,0 *[0,-1] 15616 fi 15617 rm. 15618 15619 r 100%,{h/$d},$d,100%,-1 # Resize to original dimension (eventually 3D). 15620 fi 15621 endl done 15622 15623#@cli rolling_guidance : std_deviation_s[%]>=0,std_deviation_r[%]>=0,_precision>=0 15624#@cli : Apply the rolling guidance filter on selected image. 15625#@cli : Rolling guidance filter is a fast image abstraction filter, described in: 15626#@cli : "Rolling Guidance Filter", Qi Zhang Xiaoyong, Shen Li, Xu Jiaya Jia, ECCV'2014. 15627#@cli : Default values: 'std_deviation_s=4', 'std_deviation_r=10' and 'precision=0.5'. 15628#@cli : $ image.jpg +rolling_guidance , +- 15629rolling_guidance : check "${1=4}>=0 && ${2=10}>=0 && ${3=0.5}>=0" 15630 e[^-1] "Apply rolling guidance filter on image$?, with standard deviations ($1,$2) and precision $3." 15631 precision={2^-$3} 15632 repeat $! l[$>] 15633 +b $1 15634 repeat 100 15635 if c>1 +norm. +bilateral... .,$1,$2 rm.. 15636 else +bilateral.. .,$1,$2 15637 fi 15638 -.. . std={-2,sqrt(iv)} rm.. 15639 if $std<$precision break fi 15640 done 15641 k. 15642 endl done 15643 15644#@cli sharpen : amplitude>=0 : amplitude>=0,edge>=0,_alpha,_sigma : (+) 15645#@cli : Sharpen selected images by inverse diffusion or shock filters methods. 15646#@cli : 'edge' must be specified to enable shock-filter method. 15647#@cli : Default values: 'alpha=0' and 'sigma=0'. 15648#@cli : $ image.jpg sharpen 300 15649#@cli : $ image.jpg blur 5 sharpen 300,1 15650 15651#@cli smooth : amplitude[%]>=0,_sharpness>=0,0<=_anisotropy<=1,_alpha[%],_sigma[%],_dl>0,_da>0,\ 15652# _precision>0,_interpolation,_fast_approx={ 0 | 1 } : \ 15653# nb_iterations>=0,_sharpness>=0,_anisotropy,_alpha,_sigma,_dt>0,0 : [tensor_field],_amplitude>=0,_dl>0,_da>0,\ 15654# _precision>0,_interpolation,_fast_approx={ 0 | 1 } : \ 15655# [tensor_field],_nb_iters>=0,_dt>0,0 : (+) 15656#@cli : Smooth selected images anisotropically using diffusion PDE's, with specified field of 15657#@cli : diffusion tensors. 15658#@cli : 'interpolation' can be { 0=nearest | 1=linear | 2=runge-kutta }. 15659#@cli : Default values: 'sharpness=0.7', 'anisotropy=0.3', 'alpha=0.6', 'sigma=1.1', 'dl=0.8', 'da=30', \ 15660# 'precision=2', 'interpolation=0' and 'fast_approx=1'. 15661#@cli : $ image.jpg repeat 3 smooth 40,0,1,1,2 done 15662#@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 15663#@cli : $$ https://gmic.eu/oldtutorial/_smooth 15664 15665#@cli split_freq : smoothness>0[%] 15666#@cli : Split selected images into low and high frequency parts. 15667#@cli : $ image.jpg split_freq 2% 15668split_freq : 15669 e[^-1] "Split image$? into low and high frequency parts, with smoothness $1." 15670 repeat $! l[$>] +b $1 -[0] [1] rv endl done 15671 15672#@cli solve_poisson : "laplacian_command",_nb_iterations>=0,_time_step>0,_nb_scales>=0 15673#@cli : Solve Poisson equation so that applying 'laplacian[n]' is close to the result of 'laplacian_command[n]'. 15674#@cli : Solving is performed using a multi-scale gradient descent algorithm. 15675#@cli : If 'nb_scales=0', the number of scales is automatically determined. 15676#@cli : Default values: 'nb_iterations=60', 'dt=5' and 'nb_scales=0'. 15677#@cli : $ image.jpg command "foo : gradient x" +solve_poisson foo +foo[0] +laplacian[1] 15678solve_poisson : check "${2=60}>=0 && ${3=5}>0 && ${4=0}>=0" 15679 e[^-1] "Solve Poisson equation for image$?, for laplacian command '$1', with $2 iterations, time step $3 and "\ 15680 ${arg\ 1+($4==0),$4,auto}" scales." 15681 repeat $! l[$>] 15682 [0] 15683 repeat if($4,$4,int(max(log2(max(w,h))-1,1))) 15684 f={2^$<} 15685 r[1] {0,max(1,w/$f)},{0,max(1,h/$f)},1,100%,3 15686 +ri[0] [1],2 l. -$1 k[0] endl 15687 repeat $2 +laplacian.. -. .. *. {$3/max(1e-8,abs(im),abs(iM))} +[-3,-1] done 15688 rm. 15689 done 15690 rm[0] 15691 endl done 15692 15693#@cli split_details : _nb_scales>0,_base_scale[%]>=0,_detail_scale[%]>=0 15694#@cli : Split selected images into 'nb_scales' detail scales. 15695#@cli : If 'base_scale'=='detail_scale'==0, the image decomposition is done with 'a trous' wavelets. 15696#@cli : Otherwise, it uses laplacian pyramids with linear standard deviations. 15697#@cli : Default values: 'nb_scales=4', 'base_scale=0' and 'detail_scale=0'. 15698#@cli : $ image.jpg split_details , 15699split_details : check "isint(${1=4}) && $1>0 && ${2=0}>=0 && ${3=0}>=0" 15700 if ($2)==0" && "($3)==0 15701 e[^-1] "Split image$? using $1 spatial scales and 'a trous' wavelets." 15702 repeat $! l[$<] 15703 repeat $1-1 15704 +f. "begin(interpolation = 0; boundary = 1; d = 2^"$>"; d2 = d*2); 15705 i(x - d2) + i(x + d2) + 4*i(x - d) + 4*i(x + d) + 6*i;" 15706 /. 16 15707 if h>1 15708 f. "begin(interpolation = 0; boundary = 1; d = 2^"$>"; d2 = d*2); 15709 i(x,y - d2) + i(x,y + d2) + 4*i(x,y - d) + 4*i(x,y + d) + 6*i;" 15710 /. 16 15711 fi 15712 if d>1 15713 f. "begin(interpolation = 0; boundary = 1; d = 2^"$>"; d2 = d*2); 15714 i(x,y,z - d2) + i(x,y,z + d2) + 4*i(x,y,z - d) + 4*i(x,y,z + d) + 6*i;" 15715 /. 16 15716 fi 15717 -.. . 15718 done rv 15719 endl done 15720 else 15721 e[^-1] "Split image$? using $1 spatial scales with base scale $2 and detail scale $3." 15722 repeat $! l[$<] 15723 ss={max(0.3,if(${is_percent\ $2},$2*max(w,h),$2))} 15724 se={max(0.3,if(${is_percent\ $3},$3*max(w,h),$3))} 15725 ds={$se-$ss} 15726 repeat $1-1 +b. {$ss+$>*$ds/max(1,$1-2)} -.. . rv[-2,-1] done 15727 endl done 15728 fi 15729 15730#@cli structuretensors : _scheme={ 0=centered | 1=forward/backward } : (+) 15731#@cli : Compute the structure tensor field of selected images. 15732#@cli : Default value: 'scheme=1'. 15733#@cli : $ image.jpg structuretensors abs pow 0.2 15734#@cli : $$ https://gmic.eu/oldtutorial/_structuretensors 15735 15736#@cli solidify : _smoothness[%]>=0,_diffusion_type={ 0=isotropic | 1=delaunay-oriented | 2=edge-oriented },\ 15737# _diffusion_iter>=0 15738#@cli : Solidify selected transparent images. 15739#@cli : Default values: 'smoothness=75%', 'diffusion_type=1' and 'diffusion_iter=20'. 15740#@cli : $ image.jpg 100%,100% circle[-1] 50%,50%,25%,1,255 append c +solidify , display_rgba 15741solidify : check "${1=75%}>=0 && isint(${2=1}) && $2>=0 && $2<=2 && ${3=20}>=0" 15742 s0="isotropic" s1="delaunay-oriented" s2="edge-oriented" 15743 e[^-1] "Solidify transparent image$? with smoothness $1 and $3 iterations of "${s$2}" diffusion." 15744 repeat $! l[$>] split_opacity 15745 if $!>1 <=. 128 inpaint_pde.. [1],${1-3} rm. c 0,255 fi 15746 endl done 15747 15748#@cli syntexturize : _width[%]>0,_height[%]>0 15749#@cli : Resynthetize 'width'x'height' versions of selected micro-textures by phase randomization. 15750#@cli : The texture synthesis algorithm is a straightforward implementation of the method described in : 15751#@cli : <http://www.ipol.im/pub/art/2011/ggm_rpn/>. 15752#@cli : Default values: 'width=height=100%'. 15753#@cli : $ image.jpg crop 2,282,50,328 +syntexturize 320,320 15754syntexturize : check "${1=100%}>0 && ${2=$1}>0" 15755 e[^-1] "Resynthetize $1x$2 versions of texture$? by phase randomization." 15756 repeat $! l[$>] 15757 15758 # Prepare input image data. 15759 mM={[im,iM]} repeat s sh. $> sum$>={is} var$>={iv} rm. done # Retrieve some stats for post-normalization. 15760 nw={if(${is_percent\ $1},$1*w,$1)} 15761 nh={if(${is_percent\ $2},$2*h,$2)} 15762 repeat s sum$>*={$nw*$nh/(w*h)} done # Re-estimate output (0,0) frequency. 15763 15764 if $nw>w||$nh>h # Spot extension required when rendering on bigger image. 15765 periodize_poisson 15766 100%,100% rectangle. 5,5,{w-6},{h-6},1,1 b. 2 n. 0,1 15767 $nw,$nh,1,{-2,s} fc. ${average_colors...} 15768 j. ...,{(w-{-2,w})/2},{(h-{-2,h})/2},0,0,1,.. 15769 rm[-3,-2] 15770 else 15771 r $nw,$nh,1,100%,0,0,0.5,0.5 15772 periodize_poisson 15773 fi 15774 fft 15775 15776 # Compute coherent random phase. 15777 100%,100% rand. {-pi},{pi} 15778 =. 0 15779 if !(w%2) =. {(u<0.5)*pi},{int(w/2)} fi 15780 if !(h%2) =. {(u<0.5)*pi},0,{int(h/2)} fi 15781 if !(h%2)&&!(h%2) =. {(u<0.5)*pi},{int(w/2)},{int(h/2)} fi 15782 15783 # Add random phase to fft of input image. 15784 +sin. cos.. 15785 +*[-4,-1] +*[-4,-3] +[-2,-1] 15786 *[-5,-3] *[-3,-2] -[-3,-2] 15787 15788 # Get synthetized result and normalize it. 15789 repeat s =.. ${sum$>},0,0,0,$> =. 0,0,0,0,$> done 15790 ifft rm. 15791 repeat s sh. $> avg={ia} -. $avg *. {sqrt(${var$>}/if(iv,iv,1))} +. $avg rm. done 15792 c $mM 15793 15794 endl done 15795 15796#@cli syntexturize_matchpatch : _width[%]>0,_height[%]>0,_nb_scales>=0,_patch_size>0,_blending_size>=0,_precision>=0 15797#@cli : Resynthetize 'width'x'height' versions of selected micro-textures using a patch-matching algorithm. 15798#@cli : If 'nbscales==0', the number of scales used is estimated from the image size. 15799#@cli : Default values: 'width=height=100%', 'nb_scales=0', 'patch_size=7', 'blending_size=5' and 'precision=1'. 15800#@cli : $ image.jpg crop 25%,25%,75%,75% syntexturize_matchpatch 512,512 15801syntexturize_matchpatch : check "${1=100%}>0 && ${2=$1}>0 && isint(${3=0}) && $3>=0 && isint(${4=7}) && $4>0 && 15802 ${5=5}>=0 && ${6=1}>=0" 15803 e[^-1] "Resynthetize $1x$2 version(s) of texture$? using a patch-matching algorithm with "\ 15804 ${"if $3 u \"$3 \" else u auto- fi"}"scales, $4x$4 patches, blending size $5 and precision $6." 15805 repeat $! l[$>] 15806 nb_scales={round(if($3,$3,log2(min(w,h)/16)),1,1)} 15807 width={if(${"is_percent $1"},round(w*$1,1,1),$1)} 15808 height={if(${"is_percent $2"},round(h*$2,1,1),$2)} 15809 15810 repeat $nb_scales 15811 scale={100*(0.5^$<)} 15812 +r[0] $scale%,$scale%,1,3,2 15813 15814 if !$> 15815 15816 # Initialization. 15817 {1+round(w*$width/{0,w},1,1)},{1+round(h*$height/{0,h},1,1)},1,1 15818 15819 noise. 0.2,2 ==. 1 +distance. 1 *. -1 15820 label_fg.. 0 watershed.. . rm. 15821 15822 100%,100%,1,1,x +f. y a[-2,-1] c channels. 0,2 15823 +blend. ..,shapeaverage -.. . rm. 15824 channels. 0,1 15825 15826 {-2,iM+1} rand. 0,{-4,w} +rand. 0,{-4,h} a[-2,-1] c 15827 map... . rm. +[-2,-1] round. 15828 s. c %.. {-3,w} %. {-3,h} a[-2,-1] c 15829 15830 else 15831 15832 # Upscale. 15833 rv[-2,-1] channels. 0,1 15834 *. 2 r. 200%,200%,1,2,1 15835 f. "*upc = i(x - 1,y,0,0); 15836 vpc = i(x - 1,y,0,1); 15837 ucp = i(x,y - 1,0,0); 15838 vcp = i(x,y - 1,0,1); 15839 ucc = i(x,y,0,0); 15840 vcc = i(x,y,0,1); 15841 if (ucc==upc && vcc==vpc && c==0, upc + 1, 15842 if (ucc==ucp && vcc==vcp && c==1, vcp + 1,i))" 15843 fi 15844 15845 # Synthesis. 15846 psize={-2,min(w,h,$4)} 15847 repeat 1+$6*$< 15848 psynth={int(max(3,$5*$scale%))} 15849 +warp_patch.. .,$psynth 15850 matchpatch. ...,$psize,$psize,1,4,4,0,0,.. rm.. 15851 done 15852 rm.. 15853 15854 done 15855 warp_patch.. .,$5 15856 rm. r $width,$height,1,100%,0,0,0.5,0.5 15857 endl done 15858 15859# _syntexturize_matchpatch : [correspondence_map],blend_size>0 15860_syntexturize_matchpatch : check ${is_image_arg\ $1}" && isint(${2=3}) && $2>=0" 15861 if $2<=1 pass$1 warp[^-1] .,0 rm. 15862 else repeat $! pass$1 l[$>,-1] 15863 [1],[1],1,[0] 15864 f. "*begin( 15865 boundary = 1; 15866 const patch_size = $2; 15867 const p2 = int(patch_size/2); 15868 const p1 = patch_size - p2 - 1; 15869 avg = resize([0],s#0); 15870 15871 # Pre-compute gaussian kernel. 15872 wpq = resize([0],patch_size^2); 15873 g = 0; 15874 for (q = -p1, q<=p2, ++q, 15875 for (p = -p1, p<=p2, ++p, 15876 wpq[g++] = exp(-(p^2 + q^2)/(2*(0.3*patch_size)^2)); 15877 ); 15878 ); 15879 ); 15880 g = 0; 15881 avg = 0; 15882 norm = 0; 15883 for (q = -p1, q<=p2, ++q, 15884 for (p = -p1, p<=p2, ++p, 15885 U = I(#1,x + p,y + q); 15886 w = wpq[g++]; 15887 avg+=w*I(#0,U - [p,q]); 15888 norm+=w; 15889 ); 15890 ); 15891 avg/norm" 15892 k. 15893 endl done fi 15894 15895#@cli tv_flow : _nb_iter>=0,_dt,_keep_sequence={ 0 | 1 } 15896#@cli : Apply iterations of the total variation flow on selected images. 15897#@cli : Default values: 'nb_iter=10', 'dt=30' and 'keep_sequence=0'. 15898#@cli : $ image.jpg +tv_flow 40 15899tv_flow : skip ${1=10},${2=30},${3=0} 15900 e[^-1] "Apply $1 iterations of the total variation flow on image$?, with time step $2." 15901 pde_flow $1,$2,curvature,$3 15902 15903#@cli unsharp : radius[%]>=0,_amount>=0,_threshold[%]>=0 15904#@cli : Apply unsharp mask on selected images. 15905#@cli : Default values: 'amount=2' and 'threshold=0'. 15906#@cli : $ image.jpg blur 3 +unsharp 1.5,15 cut 0,255 15907unsharp : check "${2=2}>=0" skip ${3=0} 15908 e[^-1] "Apply unsharp mask on image$?, with radius $1, amount $2 and threshold $3." 15909 repeat $! 15910 +b[$>] $1 -. [$>] 15911 if $3 +norm. >=. $3 *[-2,-1] fi 15912 *. $2 -[$>,-1] 15913 done 15914 15915#@cli unsharp_octave : _nb_scales>0,_radius[%]>=0,_amount>=0,threshold[%]>=0 15916#@cli : Apply octave sharpening on selected images. 15917#@cli : Default values: 'nb_scales=4', 'radius=1', 'amount=2' and 'threshold=0'. 15918#@cli : $ image.jpg blur 3 +unsharp_octave 4,5,15 cut 0,255 15919unsharp_octave : check "${1=4}>0 && ${3=2}>=0" skip ${2=1},${4=0} 15920 e[^-1] "Apply octave sharpening on image$?, with $1 scales, radius $2, amount $3 and threshold $4." 15921 repeat $! l[$>] nm={0,n} 15922 +f 0 weight=0 15923 repeat $1 15924 +unsharp[0] {$2*2^-$<},$3,$4 *. {2^-$>} 15925 weight+={2^-$>} 15926 +[1,-1] 15927 done 15928 rm[0] / $weight 15929 nm $nm endl done 15930 15931#@cli vanvliet : std_deviation>=0[%],order={ 0 | 1 | 2 | 3 },axis={ x | y | z | c },_boundary_conditions : (+) 15932#@cli : Apply Vanvliet recursive filter on selected images, along specified axis and with 15933#@cli : specified standard deviation, order and boundary conditions. 15934#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann }. 15935#@cli : Default value: 'boundary_conditions=1'. 15936#@cli : $ image.jpg +vanvliet 3,1,x 15937#@cli : $ image.jpg +vanvliet 30,0,x vanvliet[-2] 30,0,y add 15938 15939#@cli voronoi 15940#@cli : Compute the discrete Voronoi diagram of non-zero pixels in selected images. 15941#@cli : $ 400,400 noise 0.2,2 eq 1 +label_fg 0 voronoi[-1] +gradient[-1] xy,1 append[-2,-1] c \ 15942# norm[-1] ==[-1] 0 map[-2] 2,2 mul[-2,-1] normalize[-2] 0,255 dilate_circ[-2] 4 reverse max 15943voronoi : 15944 e[^-1] "Compute the discrete Voronoi diagram of non-zero pixels in image$?." 15945 repeat $! l[$>] s c repeat $! l[$>] 15946 +!=. 0 distance. 1 *. -1 15947 watershed.. . rm. 15948 endl done a c endl done 15949 15950#@cli watermark_fourier : text,_size>0 15951#@cli : Add a textual watermark in the frequency domain of selected images. 15952#@cli : Default value: 'size=33'. 15953#@cli : $ image.jpg +watermark_fourier "Watermarked!" +display_fft remove[-3,-1] normalize 0,255 \ 15954# append[-4,-2] y append[-2,-1] y 15955watermark_fourier : check ${2=33}>0 15956 e[^-1] "Add textual watermark '$1' with size $2 in the frequency domain of image$?." 15957 i[0] 0 t[0] "$1",0,0,$2,1,1 >=[0] 0.5 autocrop[0] 0 15958 repeat $!-1 w2={int(w/2)} h2={int(h/2)} 15959 fft. 15960 shift[-2,-1] $w2,$h2,0,0,2 15961 [0],[0],1,{s} 15962 j[-3,-2] .,3,3,0,0,1,[0] 15963 mirror[0] x 15964 j[-3,-2] .,{{-2,w}-2-{0,w}},3,0,0,1,[0] 15965 mirror[0] y 15966 j[-3,-2] .,{{-2,w}-2-{0,w}},{{-2,h}-2-{0,h}},0,0,1,[0] 15967 mirror[0] x 15968 j[-3,-2] .,3,{{-2,h}-2-{0,h}},0,0,1,[0] 15969 mirror[0] y 15970 rm. 15971 shift[-2,-1] -$w2,-$h2,0,0,2 15972 ifft[-2,-1] rm. 15973 mv. 1 done 15974 rm[0] 15975 15976#@cli watershed : [priority_image],_is_high_connectivity={ 0 | 1 } : (+) 15977#@cli : Compute the watershed transform of selected images. 15978#@cli : Default value: 'is_high_connectivity=1'. 15979#@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 15980 15981#--------------------------------- 15982# 15983#@cli :: Features Extraction 15984# 15985#--------------------------------- 15986 15987#@cli area : tolerance>=0,is_high_connectivity={ 0 | 1 } 15988#@cli : Compute area of connected components in selected images. 15989#@cli : Default values: 'is_high_connectivity=0'. 15990#@cli : $ image.jpg luminance stencil[-1] 1 +area 0 15991#@cli : $$ https://gmic.eu/oldtutorial/_area 15992area : check "$1>=0" skip ${2=0} 15993 e[^-1] "Compute area of connected components in image$?, with tolerance $1 and "\ 15994 ${arg\ 1+!$2,high,low}" connectivity." 15995 repeat $! l[$>] s c 15996 repeat $! label[$>] $1,$2 nb={$>,1+iM} +histogram[$>] $nb,0,{$nb-1} map[$>] . rm. done 15997 a c endl done 15998 15999#@cli area_fg : tolerance>=0,is_high_connectivity={ 0 | 1 } 16000#@cli : Compute area of connected components for non-zero values in selected images. 16001#@cli : Similar to 'area' except that 0-valued pixels are not considered. 16002#@cli : Default values: 'is_high_connectivity=0'. 16003#@cli : $ image.jpg luminance stencil[-1] 1 +area_fg 0 16004area_fg : check "$1>=0" skip ${2=0} 16005 e[^-1] "Compute area of foreground connected components in image$?, with tolerance $1 and "\ 16006 ${arg\ 1+!$2,high,low}" connectivity." 16007 repeat $! l[$>] s c 16008 repeat $! label_fg[$>] $1,$2 nb={$>,1+iM} +histogram[$>] $nb,0,{$nb-1} =. 0 map[$>] . rm. done 16009 a c endl done 16010 16011#@cli at_line : x0[%],y0[%],z0[%],x1[%],y1[%],z1[%] 16012#@cli : Retrieve pixels of the selected images belonging to the specified line (x0,y0,z0)-(x1,y1,z1). 16013#@cli : $ image.jpg +at_line 0,0,0,100%,100%,0 line[0] 0,0,100%,100%,1,0xFF00FF00,255,0,0 16014at_line : check ${7=100%}>=0 16015 e[^-1] "Retrieve pixels of image$?, belonging to line ($1,$2,$3)-($4,$5,$6)." 16016 repeat $! l[$>] 16017 x0={if(${is_percent\ $1},(w-1)*$1,$1)} 16018 y0={if(${is_percent\ $2},(h-1)*$2,$2)} 16019 z0={if(${is_percent\ $3},(d-1)*$3,$3)} 16020 x1={if(${is_percent\ $4},(w-1)*$4,$4)} 16021 y1={if(${is_percent\ $5},(h-1)*$5,$5)} 16022 z1={if(${is_percent\ $6},(d-1)*$6,$6)} 16023 ($x0,$x1^$y0,$y1^$z0,$z1) 16024 r. {1+max(abs($x1-$x0),abs($y1-$y0),abs($z1-$z0))},1,1,3,3 16025 round. 1 warp[0] .,0,0,0 rm. 16026 endl done 16027 16028#@cli at_quadrangle : x0[%],y0[%],x1[%],y1[%],x2[%],y2[%],x3[%],y3[%],_interpolation,_boundary_conditions : \ 16029# x0[%],y0[%],z0[%],x1[%],y1[%],z1[%],x2[%],y2[%],z2[%],x3[%],y3[%],z3[%],_interpolation,_boundary_conditions 16030#@cli : Retrieve pixels of the selected images belonging to the specified 2D or 3D quadrangle. 16031#@cli : 'interpolation' can be { 0=nearest-neighbor | 1=linear | 2=cubic }. 16032#@cli : 'boundary_conditions' can be { 0=dirichlet | 1=neumann | 2=periodic | 3=mirror }. 16033#@cli : $ image.jpg params=5%,5%,95%,5%,60%,95%,40%,95% +at_quadrangle $params polygon.. 4,$params,0.5,255 16034at_quadrangle : check "$#>=8 && $#<=14 && $#!=11" 16035 _at_quadrangle{$#<12?2:3} $* 16036 16037_at_quadrangle2 : check "${9=1}>=0 && $9<=2 && ${10=0}>=0 && $10<=3" 16038 repeat $! l[$>] 16039 x0={round(${"is_percent $1"}?(w-1)*$1:$1)} 16040 y0={round(${"is_percent $2"}?(h-1)*$2:$2)} 16041 x1={round(${"is_percent $3"}?(w-1)*$3:$3)} 16042 y1={round(${"is_percent $4"}?(h-1)*$4:$4)} 16043 x2={round(${"is_percent $5"}?(w-1)*$5:$5)} 16044 y2={round(${"is_percent $6"}?(h-1)*$6:$6)} 16045 x3={round(${"is_percent $7"}?(w-1)*$7:$7)} 16046 y3={round(${"is_percent $8"}?(h-1)*$8:$8)} 16047 ($x0,$x1;$x3,$x2^$y0,$y1;$y3,$y2) 16048 r. {P0=[$x0,$y0];P1=[$x1,$y1];P2=[$x2,$y2];P3=[$x3,$y3];\ 16049 1+round([max(norm(P1-P0),norm(P3-P2)),max(norm(P3-P0),norm(P2-P1))])},1,2,3 16050 warp.. .,0,$9,$10 rm. 16051 endl done 16052 16053_at_quadrangle3 : check "${13=1}>=0 && $13<=2 && ${14=0}>=0 && $14<=3" 16054 repeat $! l[$>] 16055 x0={round(${"is_percent $1"}?(w-1)*$1:$1)} 16056 y0={round(${"is_percent $2"}?(h-1)*$2:$2)} 16057 z0={round(${"is_percent $3"}?(h-1)*$3:$3)} 16058 x1={round(${"is_percent $4"}?(w-1)*$4:$4)} 16059 y1={round(${"is_percent $5"}?(h-1)*$5:$5)} 16060 z1={round(${"is_percent $6"}?(h-1)*$6:$6)} 16061 x2={round(${"is_percent $7"}?(w-1)*$7:$7)} 16062 y2={round(${"is_percent $8"}?(h-1)*$8:$8)} 16063 z2={round(${"is_percent $9"}?(h-1)*$9:$9)} 16064 x3={round(${"is_percent $10"}?(w-1)*$10:$10)} 16065 y3={round(${"is_percent $11"}?(h-1)*$11:$11)} 16066 z3={round(${"is_percent $12"}?(h-1)*$12:$12)} 16067 ($x0,$x1;$x3,$x2^$y0,$y1;$y3,$y2^$z0,$z1;$z3,$z2) 16068 r. {P0=[$x0,$y0,$z0];P1=[$x1,$y1,$z1];P2=[$x2,$y2,$z2];P3=[$x3,$y3,$z2];\ 16069 1+round([max(norm(P1-P0),norm(P3-P2)),max(norm(P3-P0),norm(P2-P1))])},1,3,3 16070 warp.. .,0,$13,$14 rm. 16071 endl done 16072 16073#@cli barycenter 16074#@cli : Compute the barycenter vector of pixel values. 16075#@cli : $ 256,256 ellipse 50%,50%,20%,20%,0,1,1 deform 20 +barycenter +ellipse[-2] {@0,1},5,5,0,10 16076barycenter : 16077 e[^-1] "Compute the barycenter vector of pixel values of image$?." 16078 norm repeat $! l[$>] nm={0,b} 16079 sum={is} 16080 if $sum>0 16081 if d>1 +* 'z' z={is} rm. else z=0 fi 16082 if h>1 +* 'y' y={is} rm. else y=0 fi 16083 * 'x' x={is} rm. 16084 ({$x/$sum};{$y/$sum};{$z/$sum}) 16085 else ({w/2},{h/2},{d/2}) rm.. 16086 fi 16087 nm "[barycenter of '"$nm"']" endl done 16088 16089#@cli delaunay 16090#@cli : Generate discrete 2D Delaunay triangulation of non-zero pixels in selected images. 16091#@cli : Input images must be scalar. 16092#@cli : Each pixel of the output image is a triplet (a,b,c) meaning the pixel belongs to 16093#@cli : the Delaunay triangle 'ABC' where 'a','b','c' are the labels of the pixels 'A','B','C'. 16094#@cli : $ 400,400 rand 32,255 100%,100% noise. 0.4,2 eq. 1 mul +delaunay 16095#@cli : $ image.jpg b 1% 100%,100% noise. 0.8,2 eq. 1 mul +delaunay channels 0,2 16096delaunay : 16097 e[^-1] "Generate discrete 2D Delaunay triangulation of non-zero pixels in image$?." 16098 repeat $! l[$>] 16099 16100 # Retrieve point coordinates. 16101 +slices 0 norm. !=. 0 {is+1},1,1,2 +f.. ">begin(p = 0); i?(I[#-1,++p] = [x,y]; p):0" 16102 16103 # Compute voronoi diagram of point cloud. 16104 distance... 1 *... -1 watershed. ... rm... 16105 16106 # Detect delaunay triangles. 16107 100%,100%,1,3 16108 _delaunay 1,0,0,1 _delaunay -1,0,0,-1 _delaunay -1,0,0,1 _delaunay 0,-1,1,0 rm.. 16109 16110 # Map initial labels. 16111 s. c +warp[0] [1],0,0 point. 0,0 map[-4--2] . rm. a[-3--1] c 16112 k. 16113 endl done 16114 16115_delaunay : 16116 f.. "* 16117 const boundary = 1; 16118 p0 = i; 16119 p1 = j($1,$2); 16120 p2 = j($3,$4); 16121 if (p0!=p1 && p0!=p2 && p1!=p2, 16122 P0 = I[#-3,p0]; 16123 P1 = I[#-3,p1]; 16124 P2 = I[#-3,p2]; 16125 polygon(#-1,3,P0,P1,P2,1,[p0,p1,p2]); 16126 ); i" 16127 16128#@cli detect_skin : 0<=tolerance<=1,_skin_x,_skin_y,_skin_radius>=0 16129#@cli : Detect skin in selected color images and output an appartenance probability map. 16130#@cli : Detection is performed using CbCr chromaticity data of skin pixels. 16131#@cli : If arguments 'skin_x', 'skin_y' and 'skin_radius' are provided, skin pixels are learnt 16132#@cli : from the sample pixels inside the circle located at ('skin_x','skin_y') with radius 'skin_radius'. 16133#@cli : Default value: 'tolerance=0.5' and 'skin_x=skiny=radius=-1'. 16134detect_skin : check "${1=0.5}>=0 && $1<=1" skip ${2=-1},${3=-1},${4=-1} 16135 if $2<0||$3<=0||$4<=0 16136 e[0--3] "Detect skin in image$?, using tolerance $1." 16137 m0=120.9292108800069 16138 m1=142.5745272918084 16139 A=0.09749985486268997 16140 B=0.06388871371746063 16141 C=0.05250053107738495 16142 to_rgb srgb2rgb rgb2ycbcr channels 1,2 16143 repeat $! l[$>] 16144 whd={w},{h},{d} r {w*h*d},2,1,1,-1 16145 s y -[0] $m0 -[1] $m1 a y 16146 i[0] ($A,$B;$B,$C) +m* rm[0] 16147 * s y + *. {$1-1} exp. 16148 r $whd,1,-1 16149 endl done 16150 else 16151 e[0--3] "Detect skin in image$?, using tolerance $1 and target circle at ($2,$3) with radius $4." 16152 to_rgb srgb2rgb rgb2ycbcr channels 1,2 16153 repeat $! l[$>] 16154 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 16155 +warp[0] [1],0,0 rm[1] 16156 s[1] c 16157 m0={1,ia} -[1] $m0 16158 m1={2,ia} -[2] $m1 16159 M={h} a[1,2] x +transpose[1] rv[1,2] m*[1,2] /[1] $M invert[1] 16160 rv whd={w},{h},{d} r[1] {w*h*d},2,1,1,-1 16161 s[1] y -[1] $m0 -[2] $m1 a[1,2] y +m* rm[0] 16162 * s y + *. {$1-1} exp. 16163 r $whd,1,-1 16164 endl done 16165 fi 16166 16167#@cli displacement : [source_image],_smoothness,_precision>=0,_nb_scales>=0,_iteration_max>=0,is_backward={ 0 | 1 },\ 16168# _[guide] : (+) 16169#@cli : Estimate displacement field between specified source and selected target images. 16170#@cli : If 'smoothness>=0', regularization type is set to isotropic, else to anisotropic. 16171#@cli : If 'nbscales==0', the number of scales used is estimated from the image size. 16172#@cli : Default values: 'smoothness=0.1', 'precision=5', 'nb_scales=0', 'iteration_max=10000', 'is_backward=1' \ 16173# and '[guide]=(unused)'. 16174#@cli : $ image.jpg +rotate 3,1,0,50%,50% +displacement[-1] [-2] quiver[-1] [-1],15,1,1,1,{1.5*iM} 16175 16176#@cli distance : isovalue[%],_metric : isovalue[%],[metric],_method : (+) 16177#@cli : Compute the unsigned distance function to specified isovalue, opt. according to a custom metric. 16178#@cli : 'metric' can be { 0=chebyshev | 1=manhattan | 2=euclidean | 3=squared-euclidean }. 16179#@cli : 'method' can be { 0=fast-marching | 1=low-connectivity dijkstra | 2=high-connectivity dijkstra | \ 16180# 3=1+return path | 4=2+return path }. 16181#@cli : Default value: 'metric=2' and 'method=0'. 16182#@cli : $ image.jpg threshold 20% distance 0 pow 0.3 16183#@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 16184#@cli : $$ https://gmic.eu/oldtutorial/_distance 16185 16186#@cli fftpolar 16187#@cli : Compute fourier transform of selected images, as centered magnitude/phase images. 16188#@cli : $ image.jpg fftpolar ellipse 50%,50%,10,10,0,1,0 ifftpolar 16189fftpolar : 16190 e[^-1] "Compute fourier transform of image$?, as centered magnitude/phase images." 16191 repeat $! l[$<] 16192 fft complex2polar shift {-round(w/2)},{-round(h/2)},{-round(d/2)},0,2 16193 endl done 16194 16195#@cli histogram : _nb_levels>0[%],_value0[%],_value1[%] : (+) 16196#@cli : Compute the histogram of selected images. 16197#@cli : If value range is set, the histogram is estimated only for pixels in the specified 16198#@cli : value range. Argument 'value1' must be specified if 'value0' is set. 16199#@cli : Default values: 'nb_levels=256', 'value0=0%' and 'value1=100%'. 16200#@cli : $ image.jpg +histogram 64 display_graph[-1] 400,300,3 16201 16202#@cli histogram_nd : nb_levels>0[%],_value0[%],_value1[%] 16203#@cli : Compute the 1D,2D or 3D histogram of selected multi-channels images (having 1,2 or 3 channels). 16204#@cli : If value range is set, the histogram is estimated only for pixels in the specified 16205#@cli : value range. 16206#@cli : Default values: 'value0=0%' and 'value1=100%'. 16207#@cli : $ image.jpg channels 0,1 +histogram_nd 256 16208histogram_nd : check $1>0 skip ${2=0%},${3=100%} 16209 e[^-1] "Compute histogram of multi-channels image$?, using $1 levels in range [$1,$2]." 16210 percent_nblevels=${"is_percent $1"} 16211 percent_min=${"is_percent $2"} 16212 percent_max=${"is_percent $3"} 16213 repeat $! l[$>] s={s} 16214 r {w*h*d},{min(3,s)},1,1,-1 16215 vmin=$2 vmax=$3 16216 if $percent_min||$percent_max 16217 im={im} iM={iM} 16218 vmin={if($percent_min,$im+($iM-$im)*$2,$2)} 16219 vmax={if($percent_max,$im+($iM-$im)*$3,$3)} 16220 fi 16221 dv={$vmax-$vmin} 16222 nb_levels={max(1,round(if($percent_nblevels,$1*(1+$vmax-$vmin),$1)))} 16223 f 'if(i>=$vmin&&i<=$vmax,if(i==$vmax,$nb_levels-1,int((i-$vmin)*$nb_levels/($vmax-$vmin))),-1)' 16224 pointcloud 1,$nb_levels,{if($s>1,$nb_levels,1)},{if($s>2,$nb_levels,1)} 16225 endl done 16226 16227#@cli histogram_cumul : _nb_levels>0,_is_normalized={ 0 | 1 },_val0[%],_val1[%] 16228#@cli : Compute cumulative histogram of selected images. 16229#@cli : Default values: 'nb_levels=256', 'is_normalized=0', 'val0=0%' and 'val1=100%'. 16230#@cli : $ image.jpg +histogram_cumul 256 histogram[0] 256 display_graph 400,300,3 16231histogram_cumul : check ${1=256}>0 skip ${2=0},${3=0%},${4=100%} 16232 arg 1+!$2,"normalized ","" 16233 e[^-1] "Compute "${}"cumulative histogram of image$?, using $1 levels." 16234 histogram $1,$3,$4 cumulate if $2 repeat $! /[$>] {$>,iM} done fi 16235 16236#@cli histogram_pointwise : nb_levels>0[%],_value0[%],_value1[%] 16237#@cli : Compute the histogram of each vector-valued point of selected images. 16238#@cli : If value range is set, the histogram is estimated only for values in the specified 16239#@cli : value range. 16240#@cli : Default values: 'value0=0%' and 'value1=100%'. 16241histogram_pointwise : skip ${2=0%},${3=100%} 16242 e[^-1] "Compute the pointwise histogram of vector-valued points in image$?, with $1 levels." 16243 repeat $! l[$>] nm={0,n} 16244 nb_levels={round(if(${is_percent\ $1},(iM-im)*$1,$1))} 16245 value0={if(${is_percent\ $2},im+(iM-im)*$2,$2)} 16246 value1={if(${is_percent\ $3},im+(iM-im)*$3,$3)} 16247 - $value0 * {$nb_levels/max(1,abs($value1-$value0))} c 0,{$nb_levels-1} round 16248 w={w} h={h} d={d} r {w*h*d},{s},1,1,-1 16249 i.. (0,{w-1}) r.. .,.,1,1,3 round.. 16250 r[-2,-1] 300%,100%,1,1,4 shift. 1 +[-2,-1] y. 16251 i.. ({'CImg3d'},{h/3},{h/3}) 16252 (1,0;1,{h/3-1}) r. 2,{-2,h/3},1,1,3 round. 16253 3,100%,1,1,1 1,100%,1,1,-1 y[-5,-3,-2] a[-5--1] y 16254 {$w*$h*$d},$nb_levels j3d. ..,0,0,0,1,0,0,0 rm.. 16255 r $w,$h,$d,$nb_levels,-1 16256 nm $nm endl done 16257 16258#@cli hough : _width>0,_height>0,gradient_norm_voting={ 0 | 1 } 16259#@cli : Compute hough transform (theta,rho) of selected images. 16260#@cli : Default values: 'width=512', 'height=width' and 'gradient_norm_voting=1'. 16261#@cli : $ image.jpg +blur 1.5 hough[-1] 400,400 blur[-1] 0.5 add[-1] 1 log[-1] 16262hough : check "${1=512}>0 && ${2=$1}>0" skip ${3=1} 16263 e[^-1] "Compute $1x$2 hough transform of image$?, "${arg\ 1+!$3,with,without}" gradient norm voting." 16264 slices 50% luminance repeat $! l[$>] nm={0,n} 16265 rhomax={sqrt(w^2+h^2)/2} 16266 g (0,{w-1}) (0;{{-2,h}-1}) r[-2,-1] {-3,w},{-3,h},1,1,3 -.. {w/2} -. {h/2} 16267 complex2polar[-4--1] -. ... polar2complex[-2,-1] rm. 16268 +<. 0 *. {pi} +[-3,-1] abs. %.. {2*pi} 16269 *. {$2/$rhomax} *.. {0.5*$1/pi} 16270 y[-3--1] x {w} mv[-4] $! if !$3 f. 1 fi 16271 a y pointcloud 1 r $1,$2,1,1,0 16272 nm $nm endl done 16273 16274#@cli ifftpolar 16275#@cli : Compute inverse fourier transform of selected images, from centered magnitude/phase images. 16276ifftpolar : 16277 e[^-1] "Compute inverse fourier transform of image$?, from centered magnitude/phase images." 16278 repeat int($!/2) l[$>,{$>+1}] 16279 shift {round(w/2)},{round(h/2)},{round(d/2)},0,2 polar2complex ifft rm. 16280 endl done 16281 16282#@cli isophotes : _nb_levels>0 16283#@cli : Render isophotes of selected images on a transparent background. 16284#@cli : Default value: 'nb_levels=64' 16285#@cli : $ image.jpg blur 2 isophotes 6 dilate_circ 5 display_rgba 16286isophotes : skip ${1=64} 16287 e[^-1] "Render isophote maps from images$?, with $1 levels." 16288 to_rgba repeat $! l[$>] 16289 +luminance repeat $1 +isoline3d[1] {$>*255/($1-1)} done rm[1] +3d[^0] col3d. 1 16290 [0],[0] j3d. ..,0,0,0,1,0,0,0 rm.. * 16291 endl done 16292 16293#@cli label : _tolerance>=0,is_high_connectivity={ 0 | 1 },_is_L2_norm={ 0 | 1 } : (+) 16294#@cli : Label connected components in selected images. 16295#@cli : Default values: 'tolerance=0', 'is_high_connectivity=0' and 'is_L2_norm=1'. 16296#@cli : $ image.jpg luminance threshold 60% label normalize 0,255 map 0 16297#@cli : $ 400,400 set 1,50%,50% distance 1 mod 16 threshold 8 label mod 255 map 2 16298#@cli : $$ https://gmic.eu/oldtutorial/_label 16299 16300#@cli label_fg : tolerance>=0,is_high_connectivity={ 0 | 1 } 16301#@cli : Label connected components for non-zero values (foreground) in selected images. 16302#@cli : Similar to 'label' except that 0-valued pixels are not labeled. 16303#@cli : Default value: 'is_high_connectivity=0'. 16304label_fg : check "$1>=0" skip ${2=0} 16305 e[^-1] "Label foreground connected components on image [1], with tolerance $1 and "\ 16306 ${arg\ 1+!$2,high,low}" connectivity." 16307 repeat $! l[$>] 16308 if d>1 +z -1,-1,-1,{w-1},{h-1},{d-1} label. $1,$2 z. 1,1,1,{w-1},{h-1},{d-1} 16309 else +z -1,-1,{w-1},{h-1} label. $1,$2 z. 1,1,{w-1},{h-1} 16310 fi 16311 !=.. 0 * +histogram {1+iM} =. 0 16312 >. 0 cumulate. map.. . rm. 16313 endl done 16314 16315#@cli laar 16316#@cli : Extract the largest axis-aligned rectangle in non-zero areas of selected images. 16317#@cli : Rectangle coordinates are returned in status, as a sequence of numbers x0,y0,x1,y1. 16318#@cli : $ shape_cupid 256 coords=${-laar} normalize 0,255 to_rgb rectangle $coords,0.5,0,128,0 16319laar : 16320 e[^-1] "Extract the largest axis-aligned rectangle in non-zero areas of image$?." 16321 res= sep= 16322 repeat $! l[$>] 16323 +channels 0 gt. 0 nm. shape 16324 +cumulate[shape] xy nm. cumul 16325 val={i[-1,2]} 16326 if !$val res.=-1,-1,-1,-1 # All black 16327 elif $val==wh res.=0,0,{[w,h]-1} # All white 16328 else 16329 16330 # Step 1: Compute largest square. 16331 Rin,Rout=0,{min(w,h)+1} 16332 P0,P= 16333 do 16334 Rmid={int(($Rin+$Rout)/2)} 16335 Q=${_laar\ $Rmid,$Rmid,$P} 16336 if narg($Q) Rin=$Rmid P0=$Q P=$Q else Rout=$Rmid P= fi 16337 while $Rin!=$Rout-1 16338 if $Rin==1 P=${_laar\ 1,1} fi 16339 16340 # Step 2: Compute largest rectangle, for W>H. 16341 maxA,maxW,maxH=0 maxcoords= 16342 P=$P0 W,H=$Rin 16343 for $H>0 16344 A={$W*$H} if $A>$maxA maxA,maxW,maxH=$A,$W,$H maxP={[$P][0,2]} fi 16345 nW={$W+1} 16346 Q=${_laar\ $nW,$H,$P} 16347 if narg($Q) W=$nW P=$Q 16348 elif $H>1 16349 pH={$H-1} 16350 Q=${_laar\ $nW,$pH} 16351 if narg($Q) W,H=$nW,$pH P=$Q 16352 else H-=2 P= 16353 fi 16354 else break 16355 fi 16356 done 16357 16358 # Step 3: Compute largest rectangle, for H>W. 16359 P=$P0 W,H=$Rin 16360 for $W>0 16361 A={$W*$H} if $A>$maxA maxA,maxW,maxH=$A,$W,$H maxP={[$P][0,2]} fi 16362 nH={$H+1} 16363 Q=${_laar\ $W,$nH,$P} 16364 if narg($Q) H=$nH P=$Q 16365 elif $W>1 16366 pW={$W-1} 16367 Q=${_laar\ $pW,$nH} 16368 if narg($Q) W,H=$pW,$nH P=$Q 16369 else W-=2 P= 16370 fi 16371 else break 16372 fi 16373 done 16374 16375 res.=$sep$maxP,{[$maxP]+[$maxW,$maxH]-1} sep=, 16376 fi 16377 rm[shape,cumul] 16378 endl done u $res 16379 16380# $1,$2: Rectangle width and height. 16381# ${3--1}: Coordinates of candidate locations. If empty, full-search is done. 16382# Return the list of upper-left rectangle coordinates that fit. 16383# Images [shape] and [cumul] must be defined. 16384_laar : skip "${3=}" 16385 fn="cumul(x0,y0,x1,y1) = ( 16386 _px0 = x0 - 1; 16387 _py0 = y0 - 1; 16388 i(#"$cumul,"x1,y1) + i(#"$cumul",_px0,_py0) - i(#"$cumul",x1,_py0) - i(#"$cumul",_px0,y1); 16389 );" 16390 res= 16391 if narg($3) # Test suggested locations 16392 (${3--1}) r. 2,{w/2},1,1,-1 s. x a[-2,-1] c 16393 f. ${fn}"x1 = i0 + $1 - 1; y1 = i1 + $2 - 1; 16394 i(#"$shape",i0,i1) && x1<w#"$shape" && y1<h#"$shape" && cumul(i0,i1,x1,y1)==$1*$2?I:[-1,-1]" 16395 l. discard y,-1 if w s c a x res={^} fi rm endl 16396 else # Test all shape points 16397 +f[cumul] *${fn}"x1 = x + $1 - 1; y1 = y + $2 - 1; 16398 i(#"$shape",x,y) && x1<w#"$shape" && y1<h#"$shape" && cumul(x,y,x1,y1)==$1*$2" 16399 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 16400 rm. 16401 fi 16402 u $res 16403 16404#@cli max_patch : _patch_size>=1 16405#@cli : Return locations of maximal values in local patch-based neighborhood of given size for selected images. 16406#@cli : Default value: 'patch_size=16'. 16407#@cli : $ image.jpg norm +max_patch 16 16408max_patch : check "isint(${1=16}) && $1>=1" 16409 e[^-1] "Return locations of maximal values in local patch neighborhood of size $1, in image$?." 16410 repeat $! +dilate[$>] $1 ==[$>,-1] done 16411 16412#@cli min_patch : _patch_size>=1 16413#@cli : Return locations of minimal values in local patch-based neighborhood of given size for selected images. 16414#@cli : Default value: 'patch_size=16'. 16415#@cli : $ image.jpg norm +min_patch 16 16416min_patch : check "isint(${1=16}) && $1>=1" 16417 e[^-1] "Return locations of minimal values in local patch neighborhood of size $1, in image$?." 16418 repeat $! +erode[$>] $1 ==[$>,-1] done 16419 16420#@cli minimal_path : x0[%]>=0,y0[%]>=0,z0[%]>=0,x1[%]>=0,y1[%]>=0,z1[%]>=0,_is_high_connectivity={ 0 | 1 } 16421#@cli : Compute minimal path between two points on selected potential maps. 16422#@cli : Default value: 'is_high_connectivity=0'. 16423#@cli : $ image.jpg +gradient_norm fill[-1] 1/(1+i) minimal_path[-1] 0,0,0,100%,100%,0 pointcloud[-1] 0 *[-1] 280 \ 16424# to_rgb[-1] ri[-1] [-2],0 or 16425minimal_path : check "$1>=0 && $2>=0 && $3>=0" skip ${7=0} 16426 e[^-1] "Compute minimal path between points ($1,$2,$3) and ($4,$5,$6) for potential map$?, with "\ 16427 ${arg\ 1+$7,low,high}" connectivity." 16428 repeat $! l[$>] nm={0,n} 16429 - {im} + {iM/100} 16430 100%,100% = 1,${4-6} distance. 1,[0],{if($7,4,3)} k. 16431 x={round(if(${is_percent\ $1},$1*(w-1),$1))} 16432 y={round(if(${is_percent\ $2},$2*(h-1),$2))} 16433 z={round(if(${is_percent\ $3},$3*(d-1),$3))} 16434 ($x;$y;$z) 16435 do 16436 p={0,i($x,$y,$z)} 16437 if $p&1 x-=1 16438 elif $p&2 x+=1 16439 fi 16440 if $p&4 y-=1 16441 elif $p&8 y+=1 16442 fi 16443 if $p&16 z-=1 16444 elif $p&32 z+=1 16445 fi 16446 ($x;$y;$z) 16447 while $p 16448 rm[0,-1] a x 16449 nm $nm endl done 16450 16451#@cli mse : : (+) 16452#@cli : Compute MSE (Mean-Squared Error) matrix between selected images. 16453#@cli : $ image.jpg +noise 30 +noise[0] 35 +noise[0] 38 cut. 0,255 mse 16454 16455#@cli patches : patch_width>0,patch_height>0,patch_depth>0,x0,y0,z0,_x1,_y1,_z1,...,_xN,_yN,_zN 16456#@cli : Extract N+1 patches from selected images, centered at specified locations. 16457#@cli : $ image.jpg +patches 64,64,1,153,124,0,184,240,0,217,126,0,275,38,0 16458patches : check "isint($1) && $1>0 && isint($2) && $2>0 && isint($3) && $3>0" 16459 e[^-1] "Extract $1x$2x$3 patches from image$?, at locations (${4--1})." 16460 (${4--1}) r. 3,{w/3},1,1,-1 permute. yzcx N={w} 16461 H={int(sqrt(w))} W={round(w/$H,1,1)} r. {$W*$H},1,1,3,0 r. $W,$H,1,3,-1 16462 r. {w*$1},{h*$2},{d*$3} 16463 $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] 16464 repeat $!-1 warp[$>] .,0,0,0 done rm. 16465 repeat $! l[$<] s y,$H s x,$W k[0-{$N-1}] endl done 16466 16467#@cli matchpatch : [patch_image],patch_width>=1,_patch_height>=1,_patch_depth>=1,_nb_iterations>=0,\ 16468# _nb_randoms>=0,_patch_penalization,_output_score={ 0 | 1 },_[guide] : (+) 16469#@cli : Estimate correspondence map between selected images and specified patch image, using 16470#@cli : a patch-matching algorithm. 16471#@cli : Each pixel of the returned correspondence map gives the location (p,q) of the closest patch in 16472#@cli : the specified patch image. If 'output_score=1', the third channel also gives the corresponding 16473#@cli : matching score for each patch as well. 16474#@cli : If 'patch_penalization' is >=0, SSD is penalized with patch occurrences. 16475#@cli : If 'patch_penalization' is <0, SSD is inf-penalized when distance between patches are less \ 16476# than '-patch_penalization'. 16477#@cli : Default values: 'patch_height=patch_width', 'patch_depth=1', 'nb_iterations=5', 'nb_randoms=5', \ 16478# 'patch_penalization=0', 'output_score=0' and 'guide=(undefined)'. 16479#@cli : $ image.jpg sample colorful +matchpatch[0] [1],3 +warp[-2] [-1],0 16480 16481#@cli plot2value 16482#@cli : Retrieve values from selected 2D graph plots. 16483#@cli : $ 400,300,1,1,'if(y>300*abs(cos(x/10+2*u)),1,0)' +plot2value +display_graph[-1] 400,300 16484plot2value : 16485 e[^-1] "Retrieve values from 2D graph plot$?." 16486 repeat $! l[$>] 16487 s c >= 50% 16488 repeat $! l[$>] (1,{w}) ri[1] [0],3 * histogram {w},1,{w} endl done 16489 a c 16490 endl done 16491 16492#@cli pointcloud : _type = { -X=-X-opacity | 0=binary | 1=cumulative | 2=label | 3=retrieve coordinates },\ 16493# _width,_height>0,_depth>0 16494#@cli : Render a set of point coordinates, as a point cloud in a 1D/2D or 3D binary image 16495#@cli : (or do the reverse, i.e. retrieve coordinates of non-zero points from a rendered point cloud). 16496#@cli : Input point coordinates can be a NxMx1x1, Nx1x1xM or 1xNx1xM image, where 'N' is the number of points, 16497#@cli : and M the point coordinates. 16498#@cli : If 'M'>3, the 3-to-M components sets the (M-3)-dimensional color at each point. 16499#@cli : Parameters 'width','height' and 'depth' are related to the size of the final image : 16500#@cli : - If set to 0, the size is automatically set along the specified axis. 16501#@cli : - If set to N>0, the size along the specified axis is N. 16502#@cli : - If set to N<0, the size along the specified axis is at most N. 16503#@cli : Points with coordinates that are negative or higher than specified ('width','height','depth') 16504#@cli : are not plotted. 16505#@cli : Default values: 'type=0' and 'max_width=max_height=max_depth=0'. 16506#@cli : $ 3000,2 rand 0,400 +pointcloud 0 dilate[-1] 3 16507#@cli : $ 3000,2 rand 0,400 {w} {w},3 rand[-1] 0,255 append y +pointcloud 0 dilate[-1] 3 16508pointcloud : check "${1=0}<=3 && ${2=0}>=0 && ${3=0}>=0 && ${4=0}>=0" 16509 e[^-1] "Convert image$? to point clouds, in "${arg\ 2+($1>=0)*$1-($1<0),{-$1}-opacity,binary,cumulative,labeling}\ 16510 " mode, with dimensions $2x$3x$4." 16511 repeat $! l[$>] nm={0,n} 16512 if $1!=3 # Render point cloud image from set of point coordinates 16513 16514 # Force input data to be of size Nx1x1xM. 16515 if "d>1 || (w>1 && h>1 && s>1)" 16516 error "Command '$0': Invalid input image "{w}x{h}x{d}x{s}". Should be NxMx1x1, Nx1x1xM or 1xNx1xM." 16517 fi 16518 if "w>1 && h>1 && s==1" r 100%,1,1,{h},-1 # NxMx1x1 -> Nx1x1xM 16519 elif "w==1 && h>1 && s>1" r {h},1,1,{s},-1 # 1xNx1xM -> Nx1x1xM 16520 fi 16521 16522 # Retrieve coordinates and color info. 16523 if s<3 channels 0,2 fi 16524 if s<4 100%,1,1,1,1 a[-2,-1] c fi 16525 sh. 0 round. siz_x={!$2?iM+1:$2} 16526 sh.. 1 round. siz_y={!$3?iM+1:$3} 16527 sh... 2 round. siz_z={!$4?iM+1:$4} 16528 rm[-3--1] 16529 16530 # Draw point cloud. 16531 $siz_x,$siz_y,$siz_z,{$1!=2?s-3:1} 16532 if $1<0 # -X-opacity 16533 f.. ">V = I; P = V[0,3]; C = V[3,size(V) - 3]; I(#-1,P) = (1+$1)*I(#-1,P) - $1*C; V" 16534 elif $1==0 # Binary 16535 f.. ">V = I; P = V[0,3]; C = V[3,size(V) - 3]; I(#-1,P) = C; V" 16536 elif $1==1 # Cumulative 16537 f.. ">V = I; P = V[0,3]; C = V[3,size(V) - 3]; I(#-1,P) += C; V" 16538 else # Label 16539 f.. ">begin(l = 0); V = I; P = V[0,3]; C = V[3,size(V) - 3]; I(#-1,P) = ++l; V" 16540 fi 16541 16542 else # Retrieve set of point coordinates from rendered point cloud image 16543 16,1,1,{s+3} 16544 f.. "> 16545 begin(N = 0; zero = vectors(0)); 16546 I!=zero?I[#-1,N++] = [ x,y,z,I ]; 16547 N>=w(#-1)?resize(#-1,1.5*w(#-1),1,1,s#-1,0); 16548 end(resize(#-1,N,1,1,s#-1,0)); 16549 I" 16550 fi 16551 k. nm $nm endl done 16552 16553#@cli psnr : _max_value 16554#@cli : Compute PSNR (Peak Signal-to-Noise Ratio) matrix between selected images. 16555#@cli : Default value: 'max_value=255'. 16556#@cli : $ image.jpg +noise 30 +noise[0] 35 +noise[0] 38 cut[-1] 0,255 psnr 255 replace_inf 0 16557psnr : skip "${1=}" 16558 if isnum("$1") 16559 e[0--3] "Compute the "$!x$!" matrix of PSNR values, from image$? with maximum value $1." 16560 mse log10 - {log10(($1)^2)} 16561 else 16562 e[0--3] "Compute the "$!x$!" matrix of PSNR values, from image$?." 16563 noarg 16564 if $! 16565 $! repeat $!-1 =. {$>,iM},$> done 16566 mse[^-1] sqr. log10 -.. 'max(i[#-1,x],i[#-1,y])' rm. 16567 fi 16568 fi 16569 * -10 nm [PSNR] 16570 16571#@cli segment_watershed : _threshold>=0 16572#@cli : Apply watershed segmentation on selected images. 16573#@cli : Default values: 'threshold=2'. 16574#@cli : $ image.jpg segment_watershed 2 16575segment_watershed : check "${1=2}>=0" 16576 e[^-1] "Apply watershed segmentation on image$?, with edge threshold $1." 16577 repeat $! l[$>] 16578 min={im} 16579 + {1+$min} +gradient_norm 16580 +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))" 16581 *[-3,-1] *. -1 watershed.. . rm. 16582 - {1+$min} 16583 endl done 16584 16585#@cli shape2bump : _resolution>=0,0<=_weight_avg_max_avg<=1,_dilation,_smoothness>=0 16586#@cli : Estimate bumpmap from binary shape in selected images. 16587#@cli : Default value: 'resolution=256', 'weight_avg_max=0.75', 'dilation=0' and 'smoothness=100'. 16588shape2bump : check "isint(${1=256}) && $1>=0 && ${2=0.75}>=0 && $2<=1 && isnum(${3=0}) && ${4=100}>=0" 16589 e[^-1] "Estimate bumpmap from binary shape in image$?, using "\ 16590 ${"if $1 u \"resolution $1\" else u \"full resolution\" fi"}", avg/max weight $2, dilation $3 16591 and smoothness $4." 16592 repeat $! 16593 +l[$>] 16594 norm > 0 16595 siz={[w,h]} 16596 16597 # Generate skeleton. 16598 distance 0 + $3 16599 +f. "const boundary = 1; 16600 (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))" 16601 16602 # Downsize for faster computation. 16603 is_resized=0 16604 if $1" && "max(w,h)>$1 rr2d $1,$1,0,2 gt. 0 thinning. 1 *.. {$1/max($siz)} is_resized=1 fi 16605 16606 # Generate z-map. 16607 +f. 0 .x2 16608 f[1] "*if (i, 16609 r = i(#0,x,y); 16610 ir = floor(r); 16611 r2 = r^2; 16612 for (q = -ir, q<=ir, ++q, 16613 Y = y + q; 16614 for (p = -ir, p<=ir, ++p, 16615 X = x + p; 16616 dist = norm(p,q); 16617 if (dist<r, 16618 elev = sqrt(r2 - dist^2); 16619 i(#2,X,Y) = max(i(#2,X,Y),elev); 16620 if ($2<1, i(#3,X,Y) += elev; ++i(#4,X,Y)); 16621 ); 16622 ) 16623 ); 16624 ); i" 16625 16626 if $2<1 M={-3,iM} max. 1 /[-2,-1] n. 0,$M j. ..,0,0,0,0,$2 16627 else rm[-2,-1] 16628 fi 16629 k. 16630 if $is_resized *. {max([$siz]/[w,h])} r $siz,1,1,5 c 0,100% fi 16631 endl 16632 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 16633 k. 16634 done 16635 16636#@cli skeleton : _boundary_conditions={ 0=dirichlet | 1=neumann } 16637#@cli : Compute skeleton of binary shapes using distance transform and constrained thinning. 16638#@cli : Default value: 'boundary_conditions=1'. 16639#@cli : $ shape_cupid 320 +skeleton 0 16640skeleton : check "!isnum(${1=1}) || ($1>=0 && $1<=1)" 16641 if isnum($1) bc=$1 else bc=1 noarg fi 16642 e[^-1] "Compute skeleton of binary image$? with "${"arg 1+"$bc",dirichlet,neumann"}" boundary conditions." 16643 repeat $! l[$>] s c repeat $! l[$>] 16644 # [0] = 2D binary shape 16645 1,16,1,2 # [1] = List of boundary pixels 16646 1,16,1,2 # [2] = List of boundary pixels (next iteration) 16647 16648 # [3] = Pixels on median axis. 16649 +distance[0] 0 16650 f. "const boundary = 1; 16651 (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))" 16652 16653 # Extract boundary pixels. 16654 f[0] ">"${-math_lib}"const boundary = "$bc"; 16655 i && (!j(-1) || !j(1) || !j(0,-1) || !j(0,1))?dar_insert(#1,[x,y]); i;" 16656 16657 # Run thinning algorithm. 16658 eval ${-math_lib}" 16659 const boundary = "$bc"; 16660 16661 # Lookup tables for detecting the simple points. 16662 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, 16663 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, 16664 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, 16665 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, 16666 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, 16667 1,1,1,0,1,1,1,0,0,1,1,1,1,1,1,0,1,1,1,1,0 ]; 16668 dotm = [ 128,64,32,16,0,8,4,2,1 ]; 16669 is_removed = 1; 16670 16671 # Start thinning iterations. 16672 while (is_removed, 16673 is_removed = 0; 16674 N = dar_size(#1); 16675 repeat (N,n, 16676 xc = i(#1,0,n,0,0); 16677 yc = i(#1,0,n,0,1); 16678 icc = i(#0,xc,yc); 16679 (icc && !i(#3,xc,yc))?( 16680 xp = xc - 1; yp = yc - 1; 16681 xn = xc + 1; yn = yc + 1; 16682 ref(crop(#0,xp,yp,3,3),V); 16683 val = dot(dotm,V>0); 16684 is_removable[val]?( 16685 i(#0,xc,yc) = 0; 16686 is_removed = 1; 16687 V[3]==1?(dar_insert(#2,[xp,yc]); i(#0,xp,yc) = 2); 16688 V[5]==1?(dar_insert(#2,[xn,yc]); i(#0,xn,yc) = 2); 16689 V[1]==1?(dar_insert(#2,[xc,yp]); i(#0,xc,yp) = 2); 16690 V[7]==1?(dar_insert(#2,[xc,yn]); i(#0,xc,yn) = 2); 16691 ):(dar_insert(#2,[xc,yc]); i(#0,xc,yc) = 2); 16692 ) 16693 ); 16694 resize(#1,1,h(#2),1,2,0); 16695 copy(i(#1),i(#2),2*h(#2)); 16696 i[#2,h(#2)-1] = 0; 16697 );" 16698 k[0] > 0 thinning 16699 endl done a c endl done 16700 16701skeleton_v236 : check ${1=0}>=0 16702 e[^-1] "Compute skeleton of binary image$?." 16703 distance 0 b $1 sharpen 1e10 >= 100% 16704 repeat $! +erode[$>] 2 -[$>,-1] done 16705 16706#@cli slic : size>0,_regularity>=0,_nb_iterations>0 16707#@cli : Segment selected 2D images with superpixels, using the SLIC algorithm (Simple Linear Iterative Clustering). 16708#@cli : Scalar images of increasingly labeled pixels are returned. 16709#@cli : Reference paper: Achanta, R., Shaji, A., Smith, K., Lucchi, A., Fua, P., & Susstrunk, S. (2010). \ 16710# SLIC Superpixels (No. EPFL-REPORT-149300). 16711#@cli : Default values: 'size=16', 'regularity=10' and 'nb_iterations=10'. 16712#@cli : $ image.jpg +srgb2lab slic[-1] 16 +blend shapeaverage f[-2] "j(1,0)==i && j(0,1)==i" *[-1] [-2] 16713slic : check "${1=16}>0 && ${2=10}>=0 && ${3=10}>0" 16714 e[^-1] "Segment image$? using SLIC superpixels, with size $1, regularity $2 and $3 iterations." 16715 S,m,nb_iter=${1-3} 16716 repeat $! l[$>] slices 50% 16717 16718 # Initialize superpixel centers Ck. 16719 {[max(1,round(w/$S)),max(1,round(h/$S))]},1,2,"round(([x,y]+=0.5)*="$S")" 16720 16721 # Perturb the Ck towards low gradient positions. 16722 if $S>=3 16723 +b[0] 0.7 g. xy,1 a[-2,-1] c norm. # Gradient norm with forward differences 16724 f.. " 16725 const n = round("$S"/3); 16726 const n1 = int(n/2); 16727 pos = argmin(crop(#-1,i0 - n1,i1 - n1,n,n,1)); 16728 dxy = [pos%n,int(pos/n)] - n1; 16729 [ cut(i0 + dxy[0],0,w#0-1), cut(i1 + dxy[1],0,h#0-1) ]" 16730 rm. 16731 fi 16732 r. {wh},1,1,2,-1 16733 100%,1,1,{0,s},"I(#0,I#1)" a[-2,-1] c # Add superpixels colors 16734 [0],[0],1,2 eval.. "I(#-1,i0,i1) = [ x + 1,1 ]; I" s. c distance. 1 *. -1 watershed.. . rm. channels. 0,1 16735 16736 # Start iteration loop. 16737 repeat $nb_iter 16738 16739 # Assign best superpixel to each pixel. 16740 sh[2] 1 f. inf rm. 16741 eval[1] " 16742 const m = "$m"; 16743 const S = "$S"; 16744 k = x; 16745 xk = i0; 16746 yk = i1; 16747 Ik = (I)[2,s#0]; 16748 x0 = max(xk - S,0); 16749 x1 = min(xk + S,w#0 - 1); 16750 y0 = max(yk - S,0); 16751 y1 = min(yk + S,h#0 - 1); 16752 for (y = y0, y<=y1, ++y, 16753 for (x = x0, x<=x1, ++x, 16754 delta_c = norm(I(#0,x,y) - Ik); 16755 delta_s = norm(x - xk, y - yk); 16756 delta = delta_c + m/S*delta_s; 16757 if (delta<i(#-1,x,y,0,1), 16758 I(#-1,x,y) = [ k,delta ]; 16759 ); 16760 ) 16761 ); 16762 I" 16763 16764 # Update superpixels. 16765 f[1] 0 channels[1] 0,{-2,s} 16766 eval[2] "I[#1,i0]+=[ x,y,I#0,1 ];I" 16767 s[1] c,-{1,s-1} max[2] 1 /[1,2] 16768 16769 done 16770 16771 # Remove small and isolated regions (surrounded by pixels all having the same label). 16772 k[2] channels 0 label. 0,0 16773 +area 0,0 <. {$S^2/8} 16774 {0,iM+1},1,1,1,x 16775 eval[0] "> 16776 const boundary = 1; 16777 if (i[#-1,i]>=0, 16778 N = [ j(-1,0),j(0,-1),j(1,0),j(0,1) ]; 16779 repeat (size(N),k, 16780 if (N[k]!=i, 16781 i[#-1,i] = i[#-1,i]==i || i[#-1,i]==N[k]?N[k]:-1 16782 ); 16783 ); 16784 ); 16785 i" 16786 f. "i<0?0:1" +map[0] . rm.. or[-2,-1] 16787 16788 +[0] 1 100%,100% j[0] .,0,0,0,0,1,.. rm. 16789 distance. 0 *. -1 watershed.. . rm. 16790 label. 0,0 16791 endl done 16792 16793#@cli ssd_patch : [patch],_use_fourier={ 0 | 1 },_boundary_conditions={ 0=dirichlet | 1=neumann } 16794#@cli : Compute fields of SSD between selected images and specified patch. 16795#@cli : Argument 'boundary_conditions' is valid only when 'use_fourier=0'. 16796#@cli : Default value: 'use_fourier=0' and 'boundary_conditions=0'. 16797#@cli : $ image.jpg +crop 20%,20%,35%,35% +ssd_patch[0] [1],0,0 16798ssd_patch : check ${is_image_arg\ $1} skip ${2=0},${3=0} 16799 e[^-1] "Compute field of SSD between image$? and patch $1 using "${arg\ 1+!$2,fourier,spatial}" mode." 16800 repeat $! pass$1 0 l[$>,-1] 16801 r 100%,100%,100%,${-max_s} s c 16802 repeat $!/2 l[$>,{-1-$<}] 16803 +sqr[1] val={is} rm. # Sum J(p,q)^2 16804 +sqr[0] +f[1] 1 16805 if $2 16806 convolve_fft.. . rm. # Sum I(x+p,y+q)^2 16807 mirror[1] xyz convolve_fft[0] [1] rm[1] # Sum I(x+p,y+q).J(p,q) 16808 else 16809 correlate.. .,$3 rm. # Sum I(x+p,y+q)^2 16810 correlate[0] [1],$3 rm[1] # Sum I(x+p,y+q).J(p,q) 16811 fi 16812 *[0] -2 +[0,1] + $val 16813 endl done + 16814 endl done 16815 16816#@cli thinning : _boundary_conditions={ 0=dirichlet | 1=neumann } 16817#@cli : Compute skeleton of binary shapes using morphological thinning 16818#@cli : (beware, this is a quite slow iterative process) 16819#@cli : Default value: 'boundary_conditions=1'. 16820#@cli : $ shape_cupid 320 +thinning 16821thinning : check "!isnum(${1=1}) || ($1>=0 && $1<=1)" 16822 if isnum($1) bc=$1 else bc=1 noarg fi 16823 e[^-1] "Apply morphological thinning to binary image$? with "\ 16824 ${"arg 1+"$bc",dirichlet,neumann"}" boundary conditions." 16825 repeat $! l[$>] s c repeat $! l[$>] 16826 # [0] = 2D binary shape (current iteration) 16827 1,16,1,2 # [1] = List of boundary pixels (current iteration) 16828 1,16,1,2 # [2] = List of pixels to remove (current iteration) 16829 1,16,1,2 # [3] = List of boundary pixels (for next iteration) 16830 16831 # Extract boundary pixels. 16832 f[0] ">"${-math_lib}"const boundary = "$bc"; 16833 i && (!j(-1) || !j(1) || !j(0,-1) || !j(0,1))?dar_insert(#1,[x,y]); i;" 16834 16835 # Run thinning algorithm. 16836 eval ${-math_lib}" 16837 const boundary = "$bc"; 16838 16839 # Lookup tables for detecting the 8 3x3 hit&miss. 16840 hm_and = [ 231,189,231,189,122,91,94,218 ]; 16841 hm_eq = [ 7,148,224,41,18,80,72,10 ]; 16842 16843 # Start thinning iterations. 16844 dotm = [ 128,64,32,16,0,8,4,2,1 ]; 16845 is_removed = vector8(0); 16846 ind = 1; 16847 nind = 3; 16848 it = 0; 16849 do ( 16850 N = dar_size(#ind); 16851 it8 = it%8; 16852 is_removed[it8] = 0; 16853 16854 # Find removable contour points. 16855 repeat (N,n, 16856 xc = i(#ind,0,n,0,0); 16857 yc = i(#ind,0,n,0,1); 16858 icc = i(#0,xc,yc); 16859 icc?( 16860 xp = xc - 1; yp = yc - 1; 16861 xn = xc + 1; yn = yc + 1; 16862 ref(crop(#0,xp,yp,3,3),V); 16863 val = dot(dotm,V>0); 16864 (val & hm_and[it8])==hm_eq[it8]?( 16865 dar_insert(#2,[xc,yc]); 16866 is_removed[it8] = 1; 16867 V[3]==1?(dar_insert(#nind,[xp,yc]); i(#0,xp,yc) = 2); 16868 V[5]==1?(dar_insert(#nind,[xn,yc]); i(#0,xn,yc) = 2); 16869 V[1]==1?(dar_insert(#nind,[xc,yp]); i(#0,xc,yp) = 2); 16870 V[7]==1?(dar_insert(#nind,[xc,yn]); i(#0,xc,yn) = 2); 16871 ):(dar_insert(#nind,[xc,yc]); i(#0,xc,yc) = 2); 16872 ); 16873 ); 16874 16875 # Re-assign value '1' to contour points. 16876 N = dar_size(#nind); 16877 repeat (N,n, i(#0,i[#nind,n],i[#nind,n + h(#nind)]) = 1); 16878 _tmp = ind; ind = nind; nind = _tmp; 16879 i[#nind,h(#nind)-1] = 0; 16880 16881 # Remove matching contour points. 16882 N = dar_size(#2); 16883 repeat (N,n, i(#0,I[#2,n]) = 0); 16884 i[#2,h(#2)-1] = 0; 16885 ++it; 16886 _(while), max(is_removed) 16887 );" 16888 k[0] 16889 endl done a c endl done 16890 16891#@cli tones : N>0 16892#@cli : Get N tones masks from selected images. 16893#@cli : $ image.jpg +tones 3 16894tones : check $1>0 16895 e[^-1] "Get $1 tones masks from image$?." 16896 norm n 0,{$1-1} round 1 repeat $! l[$<] 16897 repeat $1-1 +==[0] {1+$>} done ==[0] 0 16898 endl done 16899 16900#@cli topographic_map : _nb_levels>0,_smoothness 16901#@cli : Render selected images as topographic maps. 16902#@cli : Default values: 'nb_levels=16' and 'smoothness=2'. 16903#@cli : $ image.jpg topographic_map 10 16904topographic_map : check "isint(${1=16}) && $1>0" skip ${2=2} 16905 e[^-1] "Render topographic maps from image$?, with $1 levels and smoothness $2." 16906 repeat $! l[$>] 16907 +b $2 isophotes. $1 compose_channels. + ==. 0 blend shapeaverage0 16908 endl done 16909 16910#@cli tsp : _precision>=0 16911#@cli : Try to solve the 'travelling salesman' problem, using a combination of greedy search and 2-opt algorithms. 16912#@cli : Selected images must have dimensions Nx1x1xC to represent N cities each with C-dimensional coordinates. 16913#@cli : This command re-order the selected data along the x-axis so that the point sequence becomes a shortest path. 16914#@cli : Default values: 'precision=256'. 16915#@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 \ 16916# line[-1] {0,boundary=2;[I[$>],I[$>+1]]},1,255,128,0 done keep[-1] 16917tsp : check "${1=256}>=0" 16918 e[^-1] "Try to solve the 'travelling salesman' problem for pointcloud$?, with precision $1." 16919 repeat $! l[$>] n={n} 16920 if h>1" || "d>1 error[0--4] "Selected image '"{n}"' has invalid dimensions ("{[w,h,d,s]}")." fi 16921 16922 # Find initial estimate, using greedy nearest neighbor algorithm. 16923 eval " 16924 is_used = vectorw(0); 16925 next = vectorw(-1); 16926 n_initial = n_current = round(u(0,w-1)); 16927 do ( 16928 is_used[n_current] = 1; 16929 P_current = I[n_current]; 16930 n_next = -1; dmin = inf; 16931 repeat (w,n, 16932 if (!is_used[n], 16933 d = norm(I[n] - P_current); 16934 if (d<dmin, dmin = d; n_next = n); 16935 ); 16936 ); 16937 if (n_next<0, next[n_current] = n_initial; break()); 16938 next[n_current] = n_next; 16939 n_current = n_next; 16940 _(while), 1 16941 ); 16942 resize(#-1,w,1,1,s+1,0); 16943 copy(i(0,0,0,s),next,w)" 16944 100%,1,1,{s-1},">begin(ind = 0); val = I[#0,ind]; ind = val[s]; val" rm.. 16945 16946 # Improving initial estimate iteratively by 2-opt algorithm. 16947 eval " 16948 is_improved = 1; 16949 while (is_improved, 16950 is_improved = 0; 16951 nb_try = $1*w; 16952 repeat (nb_try,try, 16953 r = round(max(8,0.5*w*(try/nb_try)^0.25)); 16954 i = round(u(0,w-1)); 16955 ni = (i+1)%w; 16956 pi = (i-1)%w; 16957 do (j = (i + round(u(-r,r)))%w; _(while), j==i || j==ni || j==pi); 16958 nj = (j+1)%w; 16959 P_i = I[i]; 16960 P_ni = I[ni]; 16961 P_j = I[j]; 16962 P_nj = I[nj]; 16963 dist_ini = norm(P_ni - P_i); 16964 dist_jnj = norm(P_nj - P_j); 16965 dist_ij = norm(P_j - P_i); 16966 dist_ninj = norm(P_nj - P_ni); 16967 if (dist_ij + dist_ninj<dist_ini + dist_jnj, 16968 mi = (min(i,j) + 1)%w; 16969 mj = max(i,j); 16970 oi = min(mi,mj); 16971 oj = max(mi,mj); 16972 delta = oj - oi + 1; 16973 repeat (s,c, copy(i(oi,0,0,c),i(oj,0,0,c),delta,1,-1)); # Reverse path between nodes. 16974 is_improved = 1; 16975 ); 16976 ); 16977 )" 16978 nm $n 16979 endl done 16980 16981#@cli variance_patch : _patch_size>=1 16982#@cli : Compute variance of each images patch centered at (x,y), in selected images. 16983#@cli : Default value: 'patch_size=16' 16984#@cli : $ image.jpg +variance_patch 16985variance_patch : check "isint(${1=16}) && $1>=1" 16986 e[^-1] "Compute variance of image patches in image$?, with patch size $1." 16987 $1,$1,1,1,1 normalize_sum. 16988 repeat $!-1 l[$>,-1] 16989 +sqr[0] convolve[0,2] [1] 16990 sqr[0] rv[0,2] -[0,2] max[0] 0 16991 endl done rm. 16992 16993#--------------------------------- 16994# 16995#@cli :: Image Drawing 16996# 16997#--------------------------------- 16998 16999#@cli arrow : x0[%],y0[%],x1[%],y1[%],_thickness[%]>=0,_head_length[%]>=0,_head_thickness[%]>=0,_opacity,\ 17000# _pattern,_color1,... 17001#@cli : Draw specified arrow on selected images. 17002#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 17003#@cli : even if a color is specified. If a pattern is specified, the arrow is 17004#@cli : drawn outlined instead of filled. 17005#@cli : Default values: 'thickness=1%', 'head_length=10%', 'head_thickness=3%', 'opacity=1', 'pattern=(undefined)' \ 17006# and 'color1=0'. 17007#@cli : $ 400,400,1,3 repeat 100 arrow 50%,50%,{u(100)}%,{u(100)}%,3,20,10,0.3,${-rgb} done 17008arrow : check "${5=1%}>=0 && ${6=10%}>=0 && ${7=3%}" skip ${8=1} 17009 e[^-1] "Draw arrow in image$?, from ($1,$2) to ($3,$4), with thickness $5, head length $6, 17010 head_thickness $7 and opacity $8." 17011 repeat $! l[$>] 17012 polygon. 7,{" 17013 x0 = "${"is_percent $1"}"?(w-1)*$1:$1; 17014 y0 = "${"is_percent $2"}"?(h-1)*$2:$2; 17015 x1 = "${"is_percent $3"}"?(w-1)*$3:$3; 17016 y1 = "${"is_percent $4"}"?(h-1)*$4:$4; 17017 p0 = [x0,y0]; 17018 dp = [x1,y1]-=p0; 17019 l = norm2(dp); # arrow length 17020 t = "${"is_percent $5"}"?l*$5:$5; # thickness 17021 hl = "${"is_percent $6"}"?l*$6:$6; # head length 17022 ht = "${"is_percent $7"}"?l*$7:$7; # head thickness 17023 lmhl = l - hl; 17024 X = mul([0,-t,lmhl,-t,lmhl,-ht,l,0,lmhl,ht,lmhl,t,0,t],rot(-atan2(dp[1],dp[0])),2); 17025 X+=[p0,p0,p0,p0,p0,p0,p0]"},${8--1} 17026 endl done 17027 17028#@cli axes : x0,x1,y0,y1,_font_height>=0,_opacity,_pattern,_color1,... 17029#@cli : Draw xy-axes on selected images. 17030#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 17031#@cli : even if a color is specified. 17032#@cli : To draw only one x-axis at row Y, set both 'y0' and 'y1' to Y. 17033#@cli : To draw only one y-axis at column X, set both 'x0' and 'x1' to X. 17034#@cli : Default values: 'font_height=14', 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 17035#@cli : $ 400,400,1,3,255 axes -1,1,1,-1 17036axes : check "isint(${5=14}) && $5>=0 && ${6=1}>=0" skip ${7=0},${8=0} 17037 if ${"is_pattern \"$7\""} 17038 e[0--3] "Draw xy-axes on image$?, with x-range ($1,$2), y-range ($3,$4), font height $5, opacity $6, 17039 pattern $7 and color (${8--1})." 17040 pattern=$7 color=${8--1} 17041 else 17042 e[0--3] "Draw xy-axes on image$?, with x-range ($1,$2), y-range ($3,$4), font height $5, opacity $6 17043 and color (${7--1})." 17044 pattern=0xFFFFFFFF color=${7--1} 17045 fi 17046 if !$5" || "!$6 return fi 17047 mx={min($1,$2)} Mx={max($1,$2)} 17048 my={min($3,$4)} My={max($3,$4)} 17049 17050 # Start drawing axes on selected images. 17051 repeat $! l[$>] 17052 w1={0,w-1} h1={0,h-1} 17053 17054 # Determine number of axes tick marks. 17055 if $1!=$2 u=${"_axes[] $1,$2,{0.3*w/$5}"} offx={arg(1,$u)} deltax={arg(2,$u)} fi 17056 if $3!=$4 u=${"_axes[] $3,$4,{0.3*h/$5}"} offy={arg(1,$u)} deltay={arg(2,$u)} fi 17057 17058 # Draw x-axis. 17059 is_0x=0 17060 if $3==$4 y0=$3 else y0={v=-($my)*$h1/($My-$my);if($4>=$3,v,$h1-v)} fi 17061 sty={if($y0>$h1-$5,-1,1)} 17062 17063 if $1!=$2" && "$y0>=0" && "$y0<=$h1 17064 line 0,$y0,$w1,$y0,$6,$pattern,$color 17065 4,4,1,1,x<=y +mirror. y rows. 1,3 a[-2,-1] y .,.,1,[0] fc. $color 17066 if $2>=$1 j[0] .,{$w1-3},{$y0-3},0,0,$6,.. 17067 else mirror.. x j[0] .,0,{$y0-3},0,0,$6,.. 17068 fi 17069 rm[-2,-1] 17070 17071 i=0 do 17072 val={_$offx+$i*$deltax} i+=1 17073 if $val>=$mx" && "$val<=$Mx 17074 x={v=($val-$mx)*$w1/($Mx-$mx);if($2>=$1,v,$w1-v)} 17075 line $x,{$y0-1},$x,{$y0+1},$6,$pattern,$color 17076 if $val 17077 0 t. $val,0,0,$5,1,1 100%,100%,1,[0] fc. $color 17078 j[0] .,{max(0,min($w1-w,$x-w/2))},{if($sty>0,$y0+3,$y0-h-3)},0,0,$6,.. rm[-2,-1] 17079 else is_0x=1 17080 fi 17081 fi 17082 while $val<$Mx 17083 fi 17084 17085 # Draw y-axis. 17086 is_0y=0 17087 if $1==$2 x0=$1 else x0={v=-($mx)*$w1/($Mx-$mx);if($2>=$1,v,$w1-v)} fi 17088 stx={if($x0>$w1-$5,-1,1)} 17089 17090 if $3!=$4" && "$x0>=0" && "$x0<=$w1 17091 line $x0,0,$x0,$h1,$6,$pattern,$color 17092 4,4,1,1,x>=y +mirror. x z. 1,3 a[-2,-1] x .,.,1,[0] fc. $color 17093 if $4>=$3 j[0] .,{$x0-3},{$h1-3},0,0,$6,.. 17094 else mirror.. y j[0] .,{$x0-3},0,0,0,$6,.. 17095 fi 17096 rm[-2,-1] 17097 17098 i=0 do 17099 val={_$offy+$i*$deltay} i+=1 17100 if $val>=$my" && "$val<=$My 17101 y={v=($val-$my)*$h1/($My-$my);if($4>=$3,v,$h1-v)} 17102 line {$x0-1},$y,{$x0+1},$y,$6,$pattern,$color 17103 if $val 17104 0 t. $val,0,0,$5,1,1 100%,100%,1,[0] fc. $color 17105 j[0] .,{if($stx>0,$x0+6,$x0-w-6)},{max(0,min($h1-h,$y-h/2))},0,0,$6,.. rm[-2,-1] 17106 else is_0y=1 17107 fi 17108 fi 17109 while $val<$My 17110 fi 17111 17112 # Draw origin, if necessary. 17113 if $is_0x" || "$is_0y 17114 0 t. 0,0,0,$5,1,1 100%,100%,1,[0] fc. $color 17115 j[0] .,{if($stx>0,$x0+6,$x0-w-6)},{if($sty>0,$y0+3,$y0-h-3)},0,0,$6,.. rm[-2,-1] 17116 fi 17117 17118 endl done 17119 17120# Return optimal (offset0,scale) to display input (min,max) values. 17121# $1 = min value, $2 = max value, $3 = max number of tags(>=1). 17122_axes : 17123 n={max(1,round($3))} 17124 d={abs($2-$1)/($n-1)} 17125 s={10^round(log10($d))} 17126 m={round(min($1,$2),$s,-1)} 17127 M={round(max($1,$2),$s,1)} 17128 do N={1+round(($M-$m)/$s,1,1)} s={2*$s} while $N>$n 17129 u $m,{$s/2} 17130 17131#@cli ball : _size>0, _R,_G,_B,0<=_specular_light<=8,0<=_specular_size<=8,_shadow>=0 17132#@cli : Input a 2D RGBA colored ball sprite. 17133#@cli : Default values: 'size=64', 'R=255', 'G=R', 'B=R', 'specular_light=0.8', 'specular_size=1' and 'shading=1.5'. 17134#@cli : $ repeat 9 ball {1.5^($>+2)},${-rgb} done append x 17135ball : 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} 17136 e[^-1] "Input $1x$1 ball with color (${2-4}), specular light $5, specular size $6 and shadow factor $7." 17137 l[] 17138 {2*$1},{2*$1} = 1,65%,30% distance 1 * -1 17139 +n 0,1 ^[1] $7 *[1] 1.4 +*[1] $3 +*[1] $4 *[1] $2 a[^0] c 17140 >=[0] {100-10*$6}% b[0] {3*$6}% n[0] 0,{$5*255} rv + c 0,255 17141 100%,100% circle[1] 50%,50%,34%,1,1 *[0] [1] *. 255 a c 17142 r $1,$1,1,4,2 17143 endl 17144 17145# chromeball64x64 : Output a 64x64 GreyA chrome ball sprite. 17146# ${1-3} = R,G,B 17147chromeball64x64 : 17148 base642img[] \ 17149"MiB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KNjQgNjQgMSAyICMzMzY0CnicxZl5VJNnvsfT0mM7ntPp9N7paefe6ZzOmWlnemfGmTpzer0dO1W"\ 17150"RnQCBQPZ9TwhhDQkYwyKQAAlbEjZBthgRRBahFamAggp1KS7QIgKyk7DIpoCQd54XtComyPLH/f7xvn/k/Xyf3/N7n+X35EUgLOqN9z/DHcqtaW69cq"\ 17151"EmK8z7s3csP2ZZO/7ILGzpHhwaHBzoHxgA9/vt55M8fvPaxuh37NOu9AyNjBpNY+PjE+OmkYGuOzfb73XURu1589X0zx2PXu8ZMo0Dbnh41DQxMT5mH"\ 17152"O7vam/v7O5sUH35Cgebvyiaf+g3jRuHB/oGjeMPpqamHkyMDvb3g3iG+7tvnjm8a71e/Af+5PXOYdPo4MCwaWr24cO5ubnZ2ekHY6PDgwNDRtNQT9u3"\ 17153"mRirqXztt5Laa10jo0N9fcaZ+UWghflHwGBudnpywjTUNzjcd/faN3kBH1vGX98VWdd6b2B4oKt3fH7JbF5+vDC/ADQPm0xPTRr779/vuNZUdUzyT0t"\ 17154"9eON/5Webb3f8eOdqW9/Eo2XI/Gh6auYxbAMMHsIO48OD/TcvnCvNltjbvIz/I/RMXVPTlaa6xrauwbG55eU5wAObpZmJialpoJnpSZCZ63WV+rRgxz"\ 17155"fW9n0Xr/RsZVX1mdOV9a237o3OLT+amJw3Q9DS3IRxdNQ4NmYcn4YN7l8+U5ybIDq4pgsf4fPrjhcWFhScqL54vWt0Zn5++sHcotkMLc1OjptGR4yjw"\ 17156"6MPZqbBu+yoLyvURfjueQF/z1V98YRGo8vWV128PTTzeGlpeWkZtA5B5sVHczNTD4CmZ+Zmp8b6Oy7XFB9NDOV+8hz+1j7Jt9+kKVIyC0433DItmiHz"\ 17157"CvtEZvPSit/j+bnpsYGbF6tL8tIiRfRn4+C1PzGKWwuVCRm5xWevDS5CVmRemp0Y6m1rqCrOT1eKBS4/peA/XZKu1mkVKVn5ZQ0/TJmt8dDSeO8PNy6"\ 17158"fK9fnZqllIu4fnuA2u4VnO0rU8WmZheUN9x5ZxaHFwatN9bVnSgtzstKOBAkIO1b595007W25CQkpmUUwb7V981T3pXM1VWXFBUcztcpQIWfX6rj9G6"\ 17159"nqXotGmZCUDvjO2cWFhWXL/OTdK9/WlJ8yFORkalXhIt5qAL/4l/hSz8UUhVKlKyiv7xibmRibsxzDo77vL56tKDXk52TqUuQiAetTmP/USXm1pzFZo"\ 17160"VADvuHOkGlocGzJIr881tlaV1kC+KwMXZS/gI0Er+DNL7zUV+9d1CgUqvTC8gsdIyO9vabHljMwP3S7sbr0eN7R7KN5sf4CLu2XIHv7MXFX7rZmg/jT"\ 17161"CysutBuNvT2j81Yy+OBea22ZIe9YblFpPOAZuxGIXQd9ws/fbTMoFIm6/NPfXu8Z6e8bsZIAEMCtxqoSvf54WbUK5pEIm332nsJTP7RXqRSJaTkl3zS"\ 17162"13e3pG5mxnABoebKrpe5MWXllXXUc4JnEn73tZo+kpH9/u+FofGJSpr6ytvlGR49VHloytrfW19bVXy6RifgcJuXXv8E6OKIP1d9oOa1JUGtyT5yuvX"\ 17163"yza8gqDz0e6/zuUvOVCxkhfjwOk/znv1Id7d0Z+ZcvNeiTEsEELK6qb7kzMG2Vh5ZMP95ovXIqOsCXx2aQ93zFdbZz8ZKX19bX5CSqtbmG01+f/+6u0"\ 17164"eokBKNo4PZ3X6cG+/G5LDrZ1t3fzdbBjZqgLz97KkOdmlVUUl7deKN7fNHqNFgauX0+O9zfl8dh0chIfCjazs4ZxY07WlxWlKXRZBcYSmsab9wzPlxc"\ 17165"smzxeKhFHx0oFHDZTBoJxZARHA46ItG86IxCg/5Yhi47/3hpdX1L293eQdP0/Mse5ocdlUlhAQKQPTqV6MmNYSDt7J3d0dzIjAKDoSA3J6/wRGlV9df"\ 17166"nGi5dvdU1MDa9ZjbO99bnxAGey2bQyHiUUCVEO9k5unp4sw9r8/XHiwoLi/T6E8XFJWUV1bUXWm/c6TbNLS4/DWN5prvpZDrMc1gMKgmHZGskZHdHey"\ 17167"ekhxctVJVTdBzIcBy20RtOlFR8Xdf43Z2eQePk9KPHy0vzk73f158u0MaGBwhA78lErAMxK5qHQdo7OiM90ARfeVoewE+A5oEMer3hZFnVuebrt37s6"\ 17168"ukb6Ou80VRbebIgKzkmPIDPolNJeMy/XHJVEgba2cEJGHhhqP6RqcdAwydLTpVXlJWcMBiKSyrONjRdam48X1dzSl+QBy8d8VHSAB6LRiHhvP/+xVHN"\ 17169"kQCKm5PjioEPjuYXrtTmFukNJWWnSk8CA8PJU2WlhsLcrAxtilqVmJAQHxd9ONSfx6BRyVj0xx+mZKkihBgXJydnFzcPT28snswSSaMTkjOOFR4HPSg"\ 17170"qKsjNTE2Ii4mOlB+WyQ7LwfWQNNiPS6fRKViv99+JyNaqZCwvV8C7url7on2weBKFwRUGS+VH4hRKpTI2SiYVBwXCCgoODgkJDg4KFAk4DCabhkHtQH"\ 17171"DS0zPigyhebq6urkg3d5SXNwZHIJKpNPAAl8fj8/krFz5fIPAV+MISCAQ8LpvN51N99iMQX4J9QxslJPt4uiNh3tMLhIDDE0kUKpVGpzOYLBaLvSIOE"\ 17172"HxnsZhMFs8vwI/s80cE4r9CFGk6VbiAjPP2RHl4oFBeXmhvDHAgEElkMmxCg22eiQ7E5PmFSPwIaHgPJUmOJCVGifl08Dp90F5eIABvHwwWi3tqQQEm"\ 17173"K6I9EZ3FFYllMi7uILz+/40TEBkXJfXns8GIIOJxGB9v72cGRBKRBExgARtgRaMzuQJ/SUS0mIb9aGXzxzOE4TIJWE/4YErCrxW4AAEcTyAQSLBWcAq"\ 17174"VQgX54Pj6B4VHxcoFBORqFfQ5nswPDPL35cLpFfBXXOg0Gtzac4JRFofL9w2UhMuiFTEhVPyTQvAtNAbDEAj5bI6vn5/IPyAwQOQH+/B4XM5q5tnwKw"\ 17175"Ao+DU4TB4dHaOIk7II7k+LsD97uLmTWWwGnSMQ+geGhIaKxWCYgMESFBTgD8tPKBSKwA8SqVQep1QqYqOlXCLuw6f1h42DowMSR6WQaWy+UBQUKpWAB"\ 17176"8ElFHYSiyVhEnCXyCIjo6JiVMlqRbRczCUTv3pWP/3C1fagiw/INoXJEwiD4KclUglMAwupTA4GvTwyVhGfqErVpSnB7GGTSd4/e64A+/jg/v0O7j44"\ 17177"YMDhCQNDACgGAx0oRCyVRUYdiYlVqlN1uvRMTZxUxKURiPj/fqEA3PPVflsndx8Chc7h8EXB0jAgqXjFAPBH4hLUKdrMLF1aYmQwj0HCk6l/ebH+tLH"\ 17178"be8DBHUOiMUCeRSHhh+UR0dERMqBDkXHxquRUjS5dl5oYLRawqAQsjbMXsUav79t7wBlNoIM3xfUNORyjUCYmJ6mTU5ISkmBUk5qckhgVyqdRiBgMU2"\ 17179"T7cgX/+sEvv3JGE+nwdBNKY1O06ZnpWm16SoIqJS01Me5IpCyYSyHgfbywfMna6nlV/2e31xlLptEoZDpfHJWoyy3ILyjIzdKoosOCgvxYVCyYFyhPi"\ 17180"lj+hSUa6BOXvUgKk4rxROMYAWFH1FpNSnJ8ZFiwL5OC9/ZCodAoT4JYEfuJFRyBeNfDwZnEpHq7ubhj6Twhn8nkMYk+aA83Dx8Sm0OlsMK12ohPreJA"\ 17181"n5FcPMg0vJu9vbMXDuPh5unuam9r6+BJF/n5R6Tk5aei3loPRyB22vliUHgqztV23wEHuwOObo62SAyJzpfEZxflpBI/WJ+G9ZZdmIxL9EG5OhzYb4c"\ 17182"kEJnCUHmMUp2uVXj/6tX0iv6Hmp6nUYaHHkrUKmLjlOq0rOwU6u4dG6RX9ME+ukydW1FZXl6kCafs+91mWKCdu7Hqijvj8JY9dadajf3w1cgzvUutWV"\ 17183"hbdnQl/XOD9J9y5iwXTp2itzdAF1s+PKxoTPoKh7eTXwr8RZlo6+H7e9anYTX82hptE7FO6M80ibKM7yzfCA1kllvC32veIA5U+PL5/722jeMWDHY2b"\ 17184"gaHoGNr+JLN4RAU/gIeulkcMiOfwz9/xaixJNOzcfDmzc3jEHTmJ/7QVnAI8n6CfzC7Nb7vyZ9pmVvDIUi4OnK2kLwnAaysiJFbxSEInsw2A1vnLwF+"\ 17185"39ZxCALLcvp2eAkCsY3wIagJ8fvt4NDCTuy2eGifent8YMX2eN2mlq2XdXZwe/w2m4d6/r/5DW1Z6/DbDKClZXt8RfH2eHXE9nim2/b43e9tC596HbG"\ 17186"lveepKhGIbSWACgq2beAL74IF+PrW+TJ4/2BtnbeH+R19W8VbVvfPgK3yzk/Kh+6t4c1P6wfUlvCF3T8VIKVb4ROe1U+/7N88fu3549CXm64hJv+AeF"\ 17187"6CTeILTmsK0NhN4WYmYq02Y2DmvIQjEHLrH37WBk+1gCMQRCtfHdZq0s4ijkD8tXMj+P2PrODg+JXx6u3kzLpH8C+urU93e69HA9ng2q3TfbwNfIFGO"\ 17188"Fda7sUF0kZP8L8S1K05Ay80hP52g/CqdnzOTa1o6QFqqdb57dlp7bl/A5UFagkxIDQ1IDEgMSAjNTIKeJxz941i0M/Iz03VTykpTs4ozS3Qd0ktzi7J"\ 17189"L9BPzigCiscXF2SkFqXqFeSlMwAAcSYQbQ==" 17190 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] 17191 c.. 0,255 a[-2,-1] c 17192 17193#@cli chessboard : size1>0,_size2>0,_offset1,_offset2,_angle,_opacity,_color1,...,_color2,... 17194#@cli : Draw chessboard on selected images. 17195#@cli : Default values: 'size2=size1', 'offset1=offset2=0', 'angle=0', 'opacity=1', 'color1=0' and 'color2=255'. 17196#@cli : $ image.jpg chessboard 32,32,0,0,25,0.3,255,128,0,0,128,255 17197chessboard : check "$1>0 && ${2=$1}>0" skip ${3=0},${4=0},${5=0},${6=1},${7=0},${8=255} 17198 e[^-1] "Draw chessboard on image$?, with sizes ($1,$2), offsets ($3,$4), angle $5 deg., opacity $6 and 17199 colors (${7--1})." 17200 i[0] (${7--1}) r[0] {{0,w}/2},1,1,2,-1 permute[0] cyzx 17201 repeat $!-1 17202 w={w} h={h} theta={$5*pi/180} 17203 ($3,{$3+$w-1};$3,{$3+$w-1}^$4,$4;{$4+$h-1},{$4+$h-1}) r. $w,$h,1,2,3 17204 r. {$w*$h},2,1,1,-1 17205 i.. ({cos($theta)},{-sin($theta)};{sin($theta)},{cos($theta)}) m*[-2,-1] 17206 r. $w,$h,1,2,-1 17207 %. {$1+$2} >=. $1 s. c xor[-2,-1] map. [0] r. 100%,100%,1,.. 17208 j.. .,0,0,0,0,$6 rm. 17209 mv. 1 done rm[0] 17210 17211#@cli cie1931 17212#@cli : Draw CIE-1931 chromaticity diagram on selected images. 17213#@cli : $ 500,400,1,3 cie1931 17214cie1931 : 17215 e[^-1] "Draw CIE-1931 chromaticity diagram on image$?." 17216 17217 # Generate convex hull of visible colors, as a 3D object. 17218 (67.5;73.5;109.5;103.5;51.5;100.5;37;36) # Header 17219 (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. 17220 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;\ 17221 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;\ 17222 441,279,0;475,313,0;509,347,0;731,568,0) 17223 xM=731 yM=829 17224 2,{h-1},1,1,3,0 1,{h},1,1,'y' ++. 1 %. {h} +[-2,-1] 1 a[-3--1] x # Primitives. 17225 3,{h},1,1,160 1,{h},1,1,1 # Colors + opacities. 17226 y[-4--2] a[-5--1] y mv. 0 17227 17228 # Generate RGB triangle of displayable colors. 17229 xR=636 yR=504 xG=297 yG=234 xB=147 yB=774 17230 512,512,1,3 triangle_shade. 0,0,{w-1},0,0,{h-1},""255,0,0,""0,255,0,""0,0,255 rgb2srgb. 17231 +compose_channels. max +. 1e-8 /[-2,-1] *. 255 17232 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;\ 17233 9;0;1;2;0;0;511;0;0;511;-128;512;512;3) 17234 y. (1) a[-3--1] y mv. 1 17235 17236 # Draw chroma diagram. 17237 repeat $!-2 17238 to_rgb. fc. 255,255,255 grid. 10%,10%,0,0,0.3,0xCCCCCCCC,1,0 17239 100%,100%,1,3 17240 +*3d[0,1] {(w-8)/$xM},{(h-32)/$yM} 17241 j3d... .,2,30,0,1,2 17242 +!=... 0 distance. 1 *. -1 watershed[-4] . rm. /... 1.5 17243 j3d... .,2,30,0,1,2 17244 p3d. 1 p3d. 2 col3d. 128 j3d... .,2,30,0,1,1 rm. 17245 {-2,w},{-2,h} j3d. ..,2,30,0,1,2 rm.. 17246 +erode. 4 -. .. ==. 0 *[-3,-1] 17247 a[-2,-1] c blend[-2,-1] alpha 17248 100%,100%,1,1,255 axes. 0,0.75,0.85,0,14,1 +erode. 3 negate. to_rgb.. 17249 j... ..,0,0,0,0,1,.,400 rm[-2,-1] 17250 mv. 2 done rm[0,1] 17251 17252#@cli circle : x[%],y[%],R[%],_opacity,_pattern,_color1,... 17253#@cli : Draw specified colored circle on selected images. 17254#@cli : A radius of '100%' stands for 'sqrt(width^2+height^2)'. 17255#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 17256#@cli : even if a color is specified. If a pattern is specified, the circle is 17257#@cli : drawn outlined instead of filled. 17258#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 17259#@cli : $ image.jpg repeat 300 circle {u(100)}%,{u(100)}%,{u(30)},0.3,${-rgb} done circle 50%,50%,100,0.7,255 17260circle : skip ${4=1},${5=0},${6=0} 17261 if ${"is_pattern \"$5\""} 17262 e[0--3] "Draw outlined circle at ($1,$2) with radius $3 on image$?, with opacity $4, pattern $5 and 17263 color (${6--1})." 17264 else 17265 e[0--3] "Draw filled circle at ($1,$2) with radius $3 on image$?, with opacity $4 and color (${5--1})." 17266 fi 17267 ellipse $1,$2,$3,$3,0,${4--1} 17268 17269#@cli close_binary : 0<=_endpoint_rate<=100,_endpoint_connectivity>=0,_spline_distmax>=0,_segment_distmax>=0,\ 17270# 0<=_spline_anglemax<=180,_spline_roundness>=0,_area_min>=0,_allow_self_intersection={ 0 | 1 } 17271#@cli : Automatically close open shapes in binary images (defining white strokes on black background). 17272#@cli : Default values: 'endpoint_rate=75', 'endpoint_connectivity=2', 'spline_distmax=80', 'segment_distmax=20', \ 17273# 'spline_anglemax=90', 'spline_roundness=1','area_min=100', 'allow_self_intersection=1'. 17274close_binary : 17275 check "${1=75}>=0 && $1<=100 && ${2=2}>=0 && ${3=80}>=0 && ${4=20}>=0 && ${5=90}>=0 && $5<=180 && ${6=1}>=0 && 17276 ${7=100}>=0 && isnum(${8=1})" 17277 e[^-1] "Close open shapes in binary image$?, with endpoint rate $1, endpoint connectivity $2, spline max distance $3, 17278 segment max distance $4, spline max angle $5, spline roundness $6, area min $7 and self intersections "\ 17279 ${"arg 1+!$8,allowed,\"not allowed\""}"." 17280 17281 # Set algorithm parameters. 17282 endpoint_threshold={100-$1} # in [0,100] 17283 endpoint_connectivity={round($2)} 17284 spline_distmax=$3 # in px 17285 segment_distmax=$4 # in px 17286 spline_anglemax=$5 # in deg 17287 spline_roundness=$6 17288 area_min=$7 # in px 17289 allow_self_intersections={!!$8} # 0 or 1 17290 17291 # Define useful functions to navigate through edgels. 17292 _edgel_lib=" 17293 begin( 17294 pn = [ 0,1,1,1,-1,0,-1,1,0,-1,-1,-1,1,0,1,-1 ]; 17295 pp = [ 0,-1,1,-1,1,0,1,1,0,1,-1,1,-1,0,-1,-1 ]; 17296 ); 17297 17298 next(img,p) = ( # Used when shape is made of '!=0' (in 8-connexity) 17299 p0 = p#[0,2] + pn[4*p#[2],2]; 17300 p1 = p#[0,2] + pn[4*p#[2] + 2,2]; 17301 case = !!i(#img,p0[0],p0[1],0,0) + 2*!!i(#img,p1[0],p1[1],0,0); 17302 !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 ]; 17303 ); 17304 17305 previous(img,p) = ( # Used when shape is made of '!=0' (in 8-connexity) 17306 p0 = p#[0,2] + pp[4*p#[2],2]; 17307 p1 = p#[0,2] + pp[4*p#[2] + 2,2]; 17308 case = !!i(#img,p0[0],p0[1],0,0) + 2*!!i(#img,p1[0],p1[1],0,0); 17309 !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 ]; 17310 ); 17311 17312 next2(img,p) = ( # Used when shape is made of '{ 0 | 4 }' (in 4-connexity) 17313 p0 = p#[0,2] + pn[4*p#[2],2]; 17314 p1 = p#[0,2] + pn[4*p#[2] + 2,2]; 17315 case = !(i(#img,p0[0],p0[1],0,0)&3) + 2*!(i(#img,p1[0],p1[1],0,0)&3); 17316 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 ]; 17317 ); 17318 17319 next3(img,p) = ( # Used when shape is made of '{ 1 | 2 }' (in 4-connexity) 17320 p0 = p#[0,2] + pn[4*p#[2],2]; 17321 p1 = p#[0,2] + pn[4*p#[2] + 2,2]; 17322 val1 = i(#img,p0[0],p0[1],0,0); 17323 val2 = i(#img,p1[0],p1[1],0,0); 17324 case = (val1==1 || val1==2) + 2*(val2==1 || val2==2); 17325 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 ]; 17326 ); 17327 17328 vec(p) = ( 17329 ang = i(p[0],p[1],0,p[2])*pi/180; 17330 [ cos(ang), sin(ang) ]; 17331 );" 17332 17333 repeat $! l[$>] nm={n} 17334 17335 # Ensure input is a 2D binary image. 17336 slices 50% channels 0 > 0 17337 nm. strokes 17338 17339 # Extract primary edgel normals. 17340 100%,100%,1,4," 17341 ref(crop(#"$strokes",x - 1,y - 1,0,0,3,3,1,1,1),N); 17342 N[4]?[ N[5]?-2:0, N[7]?-2:90, N[3]?-2:180, N[1]?-2:270 ]:[-2,-2,-2,-2]; 17343 " nm. e_normals 17344 17345 # Smooth edgel normals. 17346 f[e_normals] $_edgel_lib" 17347 const boundary = 1; 17348 i<-1?-2:( 17349 ppos = npos = pos = [ x,y,c ]; 17350 u = vec(pos); 17351 for (t = 1, t<=5, ++t, 17352 ppos = previous(#"$strokes",ppos); 17353 npos = next(#"$strokes",npos); 17354 if (ppos==npos, break()); 17355 w = exp(-t^2/30); 17356 u+=w*vec(ppos); 17357 u+=w*vec(npos); 17358 ); 17359 ang = (atan2(u[1],u[0])*180/pi)%360; 17360 )" 17361 17362 # Estimate edgel curvatures. 17363 +f[e_normals] $_edgel_lib" 17364 const boundary = 1; 17365 i<-1?-2:( 17366 pos = [ x,y,c ]; 17367 ppos = previous(#"$strokes",pos); 17368 npos = next(#"$strokes",pos); 17369 pu = vec(ppos); 17370 nu = vec(npos); 17371 du = (nu - pu)/2; 17372 cr = cross([vec(pos),0],[du,0]); 17373 norm(du)*sign(cr[2]); 17374 )" 17375 nm. e_curvatures 17376 17377 # Smooth edgel curvatures. 17378 +f[e_curvatures] $_edgel_lib" 17379 const boundary = 1; 17380 i<-1?-2:( 17381 ppos = npos = pos = [ x,y,c ]; 17382 val = i; sumw = 1; 17383 for (t = 1, t<=5, ++t, 17384 ppos = previous(#"$strokes",ppos); 17385 npos = next(#"$strokes",npos); 17386 if (ppos==npos, break()); 17387 w = exp(-t^2/30); 17388 val+=w*i(ppos[0],ppos[1],0,ppos[2]); 17389 val+=w*i(npos[0],npos[1],0,npos[2]); 17390 sumw+=2*w; 17391 ); 17392 val/sumw; 17393 )" 17394 nm. e_smooth_curvatures 17395 17396 # Estimate stroke radius. 17397 +distance[strokes] 0 17398 f. " 17399 i<1-0.01||i>1+0.01?0:( 17400 p = x; q = y; d = 1; 17401 for (is_better = 1, is_better && d<32, 17402 next_p = p; 17403 next_q = q; 17404 is_better = 0; 17405 pp = p - 1; 17406 np = p + 1; 17407 pq = q - 1; 17408 nq = q + 1; 17409 (nd = i(pp,pq))>d?(d = nd; next_p = pp; next_q = pq; is_better = 1); 17410 (nd = i(p, pq))>d?(d = nd; next_p = p; next_q = pq; is_better = 1); 17411 (nd = i(np,pq))>d?(d = nd; next_p = np; next_q = pq; is_better = 1); 17412 (nd = i(pp,q))>d?(d = nd; next_p = pp; next_q = q; is_better = 1); 17413 (nd = i(np,q))>d?(d = nd; next_p = np; next_q = q; is_better = 1); 17414 (nd = i(pp,nq))>d?(d = nd; next_p = pp; next_q = nq; is_better = 1); 17415 (nd = i(p, nq))>d?(d = nd; next_p = p; next_q = nq; is_better = 1); 17416 (nd = i(np,nq))>d?(d = nd; next_p = np; next_q = nq; is_better = 1); 17417 p = next_p; 17418 q = next_q; 17419 ); 17420 d)" 17421 nm. stroke_radii 17422 17423 # Detect end points. 17424 compose_channels[e_smooth_curvatures] max nm[e_smooth_curvatures] smooth_curvatures 17425 +compose_channels[e_curvatures] max nm. curvatures 17426 17427 f. "i(#"$smooth_curvatures")>=("$endpoint_threshold"%)/(max(1,i(#"$stroke_radii"))) || 17428 i>=max(0.25,"$endpoint_threshold"%)" 17429 label_fg. 0,1 nm. keypoints 17430 if iM>0 17431 {iM},1,1,3,-1 nm. keycoords 17432 f[keypoints] "> # Keep only a single point on connected regions of high curvatures. 17433 ret = 0; 17434 if (i, 17435 j = i - 1; 17436 old_max = I[#"$keycoords",j]; 17437 kappa = i(#"$smooth_curvatures"); 17438 if (kappa>old_max[2], 17439 I[#"$keycoords",j] = [ x,y,kappa ]; 17440 i(#"$keypoints",old_max[0],old_max[1]) = 0; 17441 ret = 1; 17442 ); 17443 ); ret" 17444 channels[keycoords] 0,3 # Channels 2,3 = number of connexions and normal angle for each keypoint. 17445 fi 17446 rm[smooth_curvatures,stroke_radii,keypoints] 17447 17448 # Estimate point normals. 17449 if !narg($keycoords) 17450 rm[e_normals,e_curvatures] [strokes] nm. new_strokes 17451 else 17452 f[keycoords] " 17453 P = (I)[0,2]; 17454 angles = I(#"$e_normals",P); 17455 U = [ 0,0 ]; 17456 repeat (size(angles),k, 17457 if (angles[k]>=0, 17458 w = max(1e-8,i(#"$e_curvatures",P[0],P[1],0,k))^2; 17459 ang = angles[k]*pi/180; 17460 U += w*[ cos(ang),sin(ang) ]; 17461 ); 17462 ); 17463 [ P,0,(atan2(U[1],U[0])*180/pi)%360 ]" 17464 rm[e_normals,e_curvatures] 17465 17466 # Detect pairs of keypoints preserving the spline constraints. 17467 256,1,1,3 nm. keypairs 17468 f[keycoords] "> 17469 begin(ind = 0); 17470 for (nx = x + 1, nx<w, ++nx, 17471 const cosmin = cos("$spline_anglemax"*pi/180); 17472 Ic = I[x]; 17473 In = I[nx]; 17474 S = Ic[0,2]; 17475 T = In[0,2]; 17476 angS = Ic[3]*pi/180; 17477 angT = In[3]*pi/180; 17478 NS = [ cos(angS),sin(angS) ]; 17479 NT = [ cos(angT),sin(angT) ]; 17480 ST = T - S; 17481 dist = norm(ST); 17482 cosN = dot(NS,-NT); 17483 angN = acos(cosN)*180/pi; 17484 quality = max(0,1 - dist/"$spline_distmax") * max(0,dot(NS,ST) - dot(NT,ST))/dist * max(0,cosN - cosmin); 17485 if (quality>0, 17486 if (ind>=w(#"$keypairs"), resize(#"$keypairs",2*ind,1,1,3,0)); 17487 I[#"$keypairs",ind++] = [ quality,x,nx ]; 17488 ); 17489 ); 17490 end(resize(#"$keypairs",ind,1,1,3,0)); 17491 I" 17492 if {keypairs,w} sort[keypairs] -,x 17493 else rm[keypairs] 17494 fi 17495 17496 # Find and connect splines. 17497 [strokes] nm. new_strokes 17498 ind_strokes={$allow_self_intersections?$strokes:$new_strokes} 17499 17500 if narg($keypairs) 17501 f[keypairs] ">"$_edgel_lib" 17502 for_spline(code) = for (t = 0, t<=1, t+=dt, 17503 t3 = t*(t2 = t*t); 17504 P = round(mul([t3,t2,t,1],C,2)); 17505 code#; 17506 dP = abs(mul([3*t2,2*t,1,0],C,2)) + 1e-8; 17507 dt = min(dtmin,0.75/max(dP)); 17508 ); 17509 17510 Ic = I; 17511 indS = Ic[1]; 17512 indT = Ic[2]; 17513 if (i(#"$keycoords",indS,0,0,2)<"$endpoint_connectivity" && 17514 i(#"$keycoords",indT,0,0,2)<"$endpoint_connectivity", 17515 S = I(#"$keycoords",indS)[0,2]; 17516 T = I(#"$keycoords",indT)[0,2]; 17517 angS = i(#"$keycoords",indS,0,0,3)*pi/180; 17518 angT = i(#"$keycoords",indT,0,0,3)*pi/180; 17519 ST = T - S; 17520 dist = "$spline_roundness"*norm(ST); 17521 NS = [ cos(angS),sin(angS) ]; 17522 NT = [ cos(angT),sin(angT) ]; 17523 tmax = max(abs(ST)); 17524 is_cond = 1; 17525 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); 17526 dt = dtmin = 1/max(abs(T - S)); 17527 current_val = 1; 17528 nb_switches = 0; 17529 for_spline( 17530 if (i(#"$ind_strokes",P,0,0)!=current_val, ++nb_switches; current_val=!current_val); 17531 if (nb_switches>2, is_cond = 0; break()) 17532 ); 17533 if (is_cond, 17534 17535 # Check that the new spline did not create small closed regions. 17536 const area_max_threshold = "$area_min"; 17537 const area_min_threshold = 5; 17538 const max_edgels = 2*(area_max_threshold + 1); 17539 17540 if (area_max_threshold<=0, 17541 for_spline(i(#"$new_strokes",P)=1); 17542 , #else 17543 for_spline(i(#"$new_strokes",P)|=2); 17544 for_spline( 17545 if (i(#"$new_strokes",P[0] + 1,P[1])==0, 17546 edgels = area = 0; Q0 = Q = [ P[0] + 1,P[1],2 ]; 17547 do ( 17548 i(#"$new_strokes",Q[0],Q[1]) = 4; 17549 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 17550 Q = next2(#"$new_strokes",Q), 17551 Q!=Q0 && ++edgels<=max_edgels); 17552 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 17553 is_cond = 0; break() 17554 ); 17555 ); 17556 if (i(#"$new_strokes",P[0],P[1] + 1)==0, 17557 edgels = area = 0; Q0 = Q = [ P[0],P[1] + 1,3 ]; 17558 do ( 17559 i(#"$new_strokes",Q[0],Q[1]) = 4; 17560 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 17561 Q = next2(#"$new_strokes",Q), 17562 Q!=Q0 && ++edgels<=max_edgels); 17563 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 17564 is_cond = 0; break() 17565 ); 17566 ); 17567 if (i(#"$new_strokes",P[0] - 1,P[1])==0, 17568 edgels = area = 0; Q0 = Q = [ P[0] - 1,P[1],0 ]; 17569 do ( 17570 i(#"$new_strokes",Q[0],Q[1]) = 4; 17571 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 17572 Q = next2(#"$new_strokes",Q), 17573 Q!=Q0 && ++edgels<=max_edgels); 17574 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 17575 is_cond = 0; break() 17576 ); 17577 ); 17578 if (i(#"$new_strokes",P[0],P[1] - 1)==0, 17579 edgels = area = 0; Q0 = Q = [ P[0],P[1] - 1,1 ]; 17580 do ( 17581 i(#"$new_strokes",Q[0],Q[1]) = 4; 17582 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 17583 Q = next2(#"$new_strokes",Q), 17584 Q!=Q0 && ++edgels<=max_edgels); 17585 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 17586 is_cond = 0; break() 17587 ); 17588 ); 17589 0); 17590 17591 # Set or unset spline, and clean temp points used for local area estimations. 17592 for_spline( 17593 if (i(#"$new_strokes",P[0] + 1,P[1])==4, 17594 edgels = 0; Q0 = Q = [ P[0] + 1,P[1],2 ]; 17595 do (i(#"$new_strokes",Q[0],Q[1]) = 0; Q = next2(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 17596 ); 17597 if (i(#"$new_strokes",P[0],P[1] + 1)==4, 17598 edgels = 0; Q0 = Q = [ P[0],P[1] + 1,3 ]; 17599 do (i(#"$new_strokes",Q[0],Q[1]) = 0; Q = next2(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 17600 ); 17601 if (i(#"$new_strokes",P[0] - 1,P[1])==4, 17602 edgels = 0; Q0 = Q = [ P[0] - 1,P[1],0 ]; 17603 do (i(#"$new_strokes",Q[0],Q[1]) = 0; Q = next2(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 17604 ); 17605 if (i(#"$new_strokes",P[0],P[1] - 1)==4, 17606 edgels = 0; Q0 = Q = [ P[0],P[1] - 1,1 ]; 17607 do (i(#"$new_strokes",Q[0],Q[1]) = 0; Q = next2(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 17608 ); 17609 0); 17610 for_spline(i(#"$new_strokes",P) = is_cond?1:(i(#"$new_strokes",P)&1)); 17611 if (is_cond, 17612 ++i(#"$keycoords",indS,0,0,2); 17613 ++i(#"$keycoords",indT,0,0,2); 17614 ); 17615 ); 17616 ); 17617 ); I" 17618 rm[keypairs] 17619 fi 17620 17621 # Find and connect segments. 17622 ==[new_strokes] 0 # Negate values to consider boundary pixels (0) as strokes. 17623 17624 f[keycoords] ">"$_edgel_lib" 17625 for_segment(code) = for (t = 0, t<=tmax, ++t, 17626 P = round(S + t*ST); 17627 code#; 17628 ); 17629 17630 if (i(#"$keycoords",x,0,0,2)<"$endpoint_connectivity", 17631 S = I(#"$keycoords",x)[0,2]; 17632 angS = i(#"$keycoords",x,0,0,3)*pi/180; 17633 NS = [ cos(angS),sin(angS) ]; 17634 ST = round(NS*"$segment_distmax"); 17635 tmax = max(abs(ST)); 17636 ST/=tmax; 17637 is_cond = 0; 17638 current_val = 0; 17639 nb_switches = 0; 17640 for_segment( 17641 if (i(#"$new_strokes",P,0,0)!=current_val, ++nb_switches; current_val=1 - current_val); 17642 if (nb_switches==2,is_cond = 1; break();); 17643 ); 17644 tmax = t; 17645 if (is_cond, 17646 17647 # Check that the new segment did not create small closed regions. 17648 const area_max_threshold = "$area_min"; 17649 const area_min_threshold = 5; 17650 const max_edgels = 2*(area_max_threshold + 1); 17651 if (area_max_threshold<=0, 17652 for_segment(i(#"$new_strokes",P)=0); 17653 , #else 17654 for_segment(i(#"$new_strokes",P)|=4); 17655 for_segment( 17656 if (i(#"$new_strokes",P[0] + 1,P[1])==1, 17657 edgels = area = 0; Q0 = Q = [ P[0] + 1,P[1],2 ]; 17658 do ( 17659 i(#"$new_strokes",Q[0],Q[1]) = 2; 17660 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 17661 Q = next3(#"$new_strokes",Q), 17662 Q!=Q0 && ++edgels<=max_edgels); 17663 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 17664 is_cond = 0; break() 17665 ); 17666 ); 17667 if (i(#"$new_strokes",P[0],P[1] + 1)==1, 17668 edgels = area = 0; Q0 = Q = [ P[0],P[1] + 1,3 ]; 17669 do ( 17670 i(#"$new_strokes",Q[0],Q[1]) = 2; 17671 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 17672 Q = next3(#"$new_strokes",Q), 17673 Q!=Q0 && ++edgels<=max_edgels); 17674 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 17675 is_cond = 0; break() 17676 ); 17677 ); 17678 if (i(#"$new_strokes",P[0] - 1,P[1])==1, 17679 edgels = area = 0; Q0 = Q = [ P[0] - 1,P[1],0 ]; 17680 do ( 17681 i(#"$new_strokes",Q[0],Q[1]) = 2; 17682 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 17683 Q = next3(#"$new_strokes",Q), 17684 Q!=Q0 && ++edgels<=max_edgels); 17685 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 17686 is_cond = 0; break() 17687 ); 17688 ); 17689 if (i(#"$new_strokes",P[0],P[1] - 1)==1, 17690 edgels = area = 0; Q0 = Q = [ P[0],P[1] - 1,1 ]; 17691 do ( 17692 i(#"$new_strokes",Q[0],Q[1]) = 2; 17693 area+=(Q[2]&1?0:1-Q[2])*(Q[0]+!Q[2]); 17694 Q = next3(#"$new_strokes",Q), 17695 Q!=Q0 && ++edgels<=max_edgels); 17696 if (edgels<=max_edgels && area>=area_min_threshold && area<area_max_threshold, 17697 is_cond = 0; break() 17698 ); 17699 ); 17700 0); 17701 17702 # Set or unset segment, and clean temp points used for local area estimations. 17703 for_segment( 17704 if (i(#"$new_strokes",P[0] + 1,P[1])==2, 17705 edgels = 0; Q0 = Q = [ P[0] + 1,P[1],2 ]; 17706 do (i(#"$new_strokes",Q[0],Q[1]) = 1; Q = next3(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 17707 ); 17708 if (i(#"$new_strokes",P[0],P[1] + 1)==2, 17709 edgels = 0; Q0 = Q = [ P[0],P[1] + 1,3 ]; 17710 do (i(#"$new_strokes",Q[0],Q[1]) = 1; Q = next3(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 17711 ); 17712 if (i(#"$new_strokes",P[0] - 1,P[1])==2, 17713 edgels = 0; Q0 = Q = [ P[0] - 1,P[1],0 ]; 17714 do (i(#"$new_strokes",Q[0],Q[1]) = 1; Q = next3(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 17715 ); 17716 if (i(#"$new_strokes",P[0],P[1] - 1)==2, 17717 edgels = 0; Q0 = Q = [ P[0],P[1] - 1,1 ]; 17718 do (i(#"$new_strokes",Q[0],Q[1]) = 1; Q = next3(#"$new_strokes",Q), Q!=Q0 && ++edgels<=max_edgels) 17719 ); 17720 0); 17721 for_segment(i(#"$new_strokes",P) = is_cond?0:i(#"$new_strokes",P)&3); 17722 if (is_cond, ++i(#"$keycoords",x,0,0,2)); 17723 ); 17724 ); 17725 ); I" 17726 ==[new_strokes] 0 17727 if !0$_keep_keycoords rm[keycoords] fi # Small hack used by the plug-in preview. 17728 fi 17729 rm[strokes] 17730 nm[new_strokes] $nm 17731 endl done 17732 17733#@cli ellipse : x[%],y[%],R[%],r[%],_angle,_opacity,_pattern,_color1,... : (+) 17734#@cli : Draw specified colored ellipse on selected images. 17735#@cli : A radius of '100%' stands for 'sqrt(width^2+height^2)'. 17736#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 17737#@cli : even if a color is specified. If a pattern is specified, the ellipse is 17738#@cli : drawn outlined instead of filled. 17739#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 17740#@cli : $ image.jpg repeat 300 ellipse {u(100)}%,{u(100)}%,{u(30)},{u(30)},{u(180)},0.3,${-rgb} done \ 17741# ellipse 50%,50%,100,100,0,0.7,255 17742 17743#@cli flood : x[%],_y[%],_z[%],_tolerance>=0,_is_high_connectivity={ 0 | 1 },_opacity,_color1,... : (+) 17744#@cli : Flood-fill selected images using specified value and tolerance. 17745#@cli : Default values: 'y=z=0', 'tolerance=0', 'is_high_connectivity=0', 'opacity=1' and 'color1=0'. 17746#@cli : $ image.jpg repeat 1000 flood {u(100)}%,{u(100)}%,0,20,0,1,${-rgb} done 17747 17748#@cli gaussian : _sigma1[%],_sigma2[%],_angle 17749#@cli : Draw a centered gaussian on selected images, with specified standard deviations and orientation. 17750#@cli : Default values: 'sigma1=3', 'sigma2=sigma1' and 'angle=0'. 17751#@cli : $ 400,400 gaussian 100,30,45 17752#@cli : $$ https://gmic.eu/oldtutorial/_gaussian 17753gaussian : skip ${1=3},${2=$1},${3=0} 17754 e[^-1] "Draw centered gaussian on image$? with standard deviations ($1,$2) and angle $3 deg." 17755 u={cos($3*pi/180)} 17756 v={sin($3*pi/180)} 17757 dmax={max(w,h)} 17758 if isnum($1) l1=$1 else l1={${1}10000*$dmax/100} fi 17759 if isnum($2) l2=$2 else l2={${2}10000*$dmax/100} fi 17760 l1={1/(2*max(1/3,$l1)^2)} 17761 l2={1/(2*max(1/3,$l2)^2)} 17762 A={$l1*$u*$u+$l2*$v*$v} 17763 B={($l1-$l2)*$u*$v} 17764 C={$l1*$v*$v+$l2*$u*$u} 17765 repeat $! l[$>] nm={0,n} 17766 w={w} h={h} ds={d},{s} rm 17767 $w,$h,1,1,'X=x-{($w-1)/2};Y=y-{($h-1)/2};$A*X*X+2*$B*X*Y+$C*Y*Y' 17768 * -1 exp r $w,$h,$ds 17769 nm $nm endl done 17770 17771#@cli graph : [function_image],_plot_type,_vertex_type,_ymin,_ymax,_opacity,_pattern,_color1,... : \ 17772# 'formula',_resolution>=0,_plot_type,_vertex_type,_xmin,xmax,_ymin,_ymax,_opacity,_pattern,_color1,... : (+) 17773#@cli : Draw specified function graph on selected images. 17774#@cli : 'plot_type' can be { 0=none | 1=lines | 2=splines | 3=bar }. 17775#@cli : 'vertex_type' can be { 0=none | 1=points | 2,3=crosses | 4,5=circles | 6,7=squares }. 17776#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 17777#@cli : even if a color is specified. 17778#@cli : Default values: 'plot_type=1', 'vertex_type=1', 'ymin=ymax=0 (auto)', 'opacity=1', 'pattern=(undefined)' 17779#@cli : and 'color1=0'. 17780#@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 \ 17781# graph[0] [2],2,0,0,0,1,0,255,0 graph[0] [3],2,0,0,0,1,0,0,255 keep[0] 17782 17783#@cli grid : size_x[%]>=0,size_y[%]>=0,_offset_x[%],_offset_y[%],_opacity,_pattern,_color1,... 17784#@cli : Draw xy-grid on selected images. 17785#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 17786#@cli : even if a color is specified. 17787#@cli : Default values: 'offset_x=offset_y=0', 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 17788#@cli : $ image.jpg grid 10%,10%,0,0,0.5,255 17789#@cli : $ 400,400,1,3,255 grid 10%,10%,0,0,0.3,0xCCCCCCCC,128,32,16 17790grid : check "$1>=0 && $2>=0" skip ${3=0},${4=0},${5=1},${6=0},${7=$6} 17791 if ${"is_pattern \"$6\""} 17792 e[0--3] "Draw xy-grid on image$?, with sizes ($1,$2), offsets ($3,$4), opacity $5, pattern $6 and color (${7--1})." 17793 pattern=$6 color=${7--1} 17794 else 17795 e[0--3] "Draw xy-grid on image$?, with sizes ($1,$2), offsets ($3,$4), opacity $5, and color (${6--1})." 17796 pattern=0xFFFFFFFF color=${6--1} 17797 fi 17798 eval " 17799 is_percent(str) = (unref(_is_pct); _is_pct=['#str']; _is_pct[size(_is_pct) - 1]==_'%'); 17800 repeat (l,k, 17801 17802 # Horizontal lines. 17803 size = is_percent($1)?max(1,w#k*$1):$1; 17804 size>=1?( 17805 off = (is_percent($3)?size*$3:$3)%size; 17806 for (x = off, x<w#k, x+=size, polygon(#k,-2,x,0,x,h - 1,$5,"$pattern","$color")); 17807 ); 17808 17809 # Vertical lines. 17810 size = is_percent($2)?max(1,h#k*$2):$2; 17811 size>=1?( 17812 off = (is_percent($4)?size*$4:$4)%size; 17813 for (y = off, y<h#k, y+=size, polygon(#k,-2,0,y,w - 1,y,$5,"$pattern","$color")); 17814 ) 17815 )" 17816 17817#@cli j : eq. to 'image'. : (+) 17818 17819#@cli image : [sprite],_x[%|~],_y[%|~],_z[%|~],_c[%|~],_opacity,_[opacity_mask],_max_opacity_mask : (+) 17820#@cli : Draw specified sprite image on selected images. 17821#@cli : (eq. to 'j').\n 17822#@cli : If one of the x,y,z or c argument ends with a '~', its value is expected to be 17823#@cli : a centering ratio (in [0,1]) rather than a position. 17824#@cli : Usual centering ratio are { 0=left-justified | 0.5=centered | 1=right-justified }. 17825#@cli : Default values: 'x=y=z=c=0', 'opacity=1', 'opacity_mask=(undefined)' and 'max_opacity_mask=1'. 17826#@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] 17827 17828#@cli line : x0[%],y0[%],x1[%],y1[%],_opacity,_pattern,_color1,... : (+) 17829#@cli : Draw specified colored line on selected images. 17830#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 17831#@cli : even if a color is specified. 17832#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 17833#@cli : $ image.jpg repeat 500 line 50%,50%,{u(w)},{u(h)},0.5,${-rgb} done line 0,0,100%,100%,1,0xCCCCCCCC,255 \ 17834# line 100%,0,0,100%,1,0xCCCCCCCC,255 17835 17836#@cli linethick : x0[%],y0[%],x1[%],y1[%],_thickness,_opacity,_color1 17837#@cli : Draw specified colored thick line on selected images. 17838#@cli : Default values: 'thickness=2', 'opacity=1' and 'color1=0'. 17839#@cli : $ 400,400,1,3 repeat 100 linethick {u([w,h,w,h,5])},0.5,${-rgb} done 17840linethick : check "${5=2}>=0 && isnum(${6=1}) && isnum(${7=0})" 17841 e[^-1] "Draw thick line ($1,$2) - ($3,$4) on image$?, with thickness $5, opacity $6 and color (${7--1})." 17842 if !$5 line ${1-4},${6--1} 17843 else repeat $! l[$>] 17844 x0={${"is_percent $1"}?(w-1)*$1:$1} 17845 y0={${"is_percent $2"}?(h-1)*$2:$2} 17846 x1={${"is_percent $3"}?(w-1)*$3:$3} 17847 y1={${"is_percent $4"}?(h-1)*$4:$4} 17848 coords={" 17849 const th = "$5"; 17850 P0 = [ "$x0","$y0" ]; 17851 P1 = [ "$x1","$y1" ]; 17852 dP = P1 - P0; 17853 n = [ -dP[1],dP[0] ]/max(1e-8,norm(dP))*th/2; 17854 round([ P0 - n, P0 + n, P1 + n, P1 - n ]); 17855 "} 17856 polygon 4,$coords,${6--1} 17857 endl done fi 17858 17859#@cli mandelbrot : z0r,z0i,z1r,z1i,_iteration_max>=0,_is_julia={ 0 | 1 },_c0r,_c0i,_opacity : (+) 17860#@cli : Draw mandelbrot/julia fractal on selected images. 17861#@cli : Default values: 'iteration_max=100', 'is_julia=0', 'c0r=c0i=0' and 'opacity=1'. 17862#@cli : $ 400,400 mandelbrot -2.5,-2,2,2,1024 map 0 +blur 2 elevation3d[-1] -0.2 17863 17864#@cli marble : _image_weight,_pattern_weight,_angle,_amplitude,_sharpness>=0,_anisotropy>=0,_alpha,_sigma,\ 17865# _cut_low>=0,_cut_high>=0 17866#@cli : Render marble like pattern on selected images. 17867#@cli : Default values: 'image_weight=0.2', 'pattern_weight=0.1', 'angle=45', 'amplitude=0', 'sharpness=0.4' \ 17868# and 'anisotropy=0.8', 17869#@cli : 'alpha=0.6', 'sigma=1.1' and 'cut_low=cut_high=0'. 17870#@cli : $ image.jpg +marble , 17871marble : 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%} 17872 e[^-1] "Render marble like pattern on image$?, with image weight $1, pattern weight $2, angle $3 deg., 17873 amplitude $4, sharpness $5, anisotropy $6, alpha $7, sigma $8, and cut ($9,$10)." 17874 sx={$2*sin($3*pi/180)} sy={$2*cos($3*pi/180)} f sin(x*$sx+y*$sy+i*$1) 17875 if $4 smooth $4,$5,$6,$7,$8 fi 17876 c $9,$10 n 0,255 17877 17878#@cli maze : _width>0,_height>0,_cell_size>0 17879#@cli : Input maze with specified size. 17880#@cli : $ maze 30,20 negate normalize 0,255 17881maze : check "isint(${1=15}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=24}) && $3>0" 17882 e[^-1] "Input $1x$2 maze." 17883 ({round(u($1-1))},{round(u($2-1))}) # Starting cell. 17884 $1,$2,1,1,15 +f. 0 a[-2,-1] c # Starting maze data. 17885 _generate_maze $1,$2 17886 _render_maze. $3 nm. [maze] 17887 17888_generate_maze : 17889 17890 # Start opening walls. 17891 do 17892 x={-2,@-2} y={-2,@-1} # Coords of the current cell. 17893 =. 1,$x,$y,0,1 # Mark current cell as visited. 17894 17895 # Check for neighboring cells that are candidate for opening wall, and select one random. 17896 is_candidate=0 17897 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. 17898 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. 17899 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. 17900 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. 17901 if $is_candidate 17902 ($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 17903 fi 17904 17905 # Remove wall between the current and chosen neighboring cells. 17906 if $is_candidate 17907 if {-2,@-1}==8 =. {i($x,$y)&7},$x,$y =. {i($x,$y-1)&11},$x,{$y-1} # Remove up wall. 17908 elif {-2,@-1}==4 =. {i($x,$y)&11},$x,$y =. {i($x,$y+1)&7},$x,{$y+1} # Remove down wall. 17909 elif {-2,@-1}==2 =. {i($x,$y)&13},$x,$y =. {i($x-1,$y)&14},{$x-1},$y # Remove left wall. 17910 else =. {i($x,$y)&14},$x,$y =. {i($x+1,$y)&13},{$x+1},$y # Remove right wall. 17911 fi 17912 z.. 0,1 a[-3,-2] y # Add neighboring cell to stack of cells to explore. 17913 else # No candidate : remove current cell from cells to explore. 17914 if h#-2==1 break fi 17915 rows.. 0,{{-2,h}-2} 17916 fi 17917 while 1 17918 rm.. channels. 0 17919 17920_render_maze : 17921 # Create the 16 configurations of walls. 17922 i[0] $1,$1 i[1] [0]x15 17923 line[8-15] 0,0,100%,0,1,1 17924 line[4-7,12-15] 0,100%,100%,100%,1,1 17925 line[2-3,6-7,10-11,14-15] 0,0,0,100%,1,1 17926 line[1-15:2] 100%,0,100%,100%,1,1 17927 # Map the wall data with them. 17928 a[0-15] x r. {w*$1},{h*$1} *. $1 channels. 0,1 17929 $1,$1,1,1,x $1,$1,1,1,y a[-2,-1] c r. ..,..,1,2,0,2 +[-2,-1] 17930 warp.. .,0,0,0 rm. 17931 17932#@cli maze_mask : _cellsize>0 17933#@cli : Input maze according to size and shape of selected mask images. 17934#@cli : Mask may contain disconnected shapes. 17935#@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 17936maze_mask : check "isint(${1=24}) && $1>0" 17937 e[^-1] "Input masked maze from image$? with cell size $1." 17938 compose_channels + >= 50% repeat $! l[$>] 17939 do 17940 +rand[0] 0,1 *. [0] ({[xM,yM]}) rm.. # Select one starting point in the mask. 17941 +flood[0] {^},0,0,0,1,2 >=. 2 +negate. *.. 15 a[-2,-1] c 17942 flood[0] {-2,^},0,0,0,1,0 17943 _generate_maze {w},{h} 17944 while iM#0 17945 rm[0] + _render_maze. $1 nm. [maze] 17946 endl done 17947 17948#@cli newton_fractal : z0r,z0i,z1r,z1i,_angle,0<=_descent_method<=2,_iteration_max>=0,_convergence_precision>0,\ 17949# _expr_p(z),_expr_dp(z),_expr_d2p(z) 17950#@cli : Draw newton fractal on selected images, for complex numbers in range (z0r,z0i) - (z1r,z1i). 17951#@cli : Resulting images have 3 channels whose meaning is [ last_zr, last_zi, nb_iter_used_for_convergence ]. 17952#@cli : 'descent_method' can be { 0=secant | 1=newton | 2=householder }. 17953#@cli : Default values: 'angle=0', 'descent_method=1', 'iteration_max=200', 'convergence_precision=0.01', \ 17954# 'expr_p(z)=z^^3-1', 'expr_dp(z)=3*z^^2' and 'expr_d2z(z)=6*z'. 17955#@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" \ 17956# f "[ atan2(i1,i0)*90+20,1,cut(i2/30,0.2,0.7) ]" hsl2rgb 17957newton_fractal : check "isin(${6=1},0,1,2) && ${7=200}>=0 && ${8=0.01}>0" 17958 skip "${4=0},${9=z^^3-1},${10=3*z^^2},${11=6*z}" 17959 m0,m1,m2=secant,newton,householder 17960 e[^-1] "Draw newton fractal on image$?, for complex range ($1,$2)-($3,$4), with angle $5, $7 max "${m$6}" "\ 17961 "iterations, precision $8, and expressions 'p(z)=$9', 'dp(z)=$10' and 'd2p(z)=$11'." 17962 channels 0,2 17963 f "* 17964 begin( 17965 const dx = abs($3 - $1); 17966 const dy = abs($4 - $2); 17967 const angle = $5; 17968 const method = $6; 17969 const itermax = $7; 17970 const precision = $8; 17971 17972 zc = [ $1 + $3, $2 + $4 ]/2; 17973 R = rot(-angle°); 17974 ); 17975 17976 p(z) = ($9); 17977 dp(z) = ($10); 17978 d2p(z) = ($11); 17979 17980 zn = [ $1 + x*dx/(w-1), $2 + y*dy/(h-1) ]; 17981 angle?(zn = (R*(zn-=zc)+=zc)); 17982 17983 !method?(znm1 = zn + [ precision,0 ]); 17984 repeat (itermax,iter, 17985 pzn = p(zn); 17986 method==0?( 17987 znp1 = zn - pzn**(zn - znm1)//(pzn - p(znm1)); # secant 17988 znm1 = zn; 17989 ):method==1?( 17990 dpzn = dp(zn); 17991 znp1 = zn - pzn//dpzn; # newton 17992 ):( # householder 17993 dpzn = dp(zn); 17994 d2pzn = d2p(zn); 17995 hn = (pzn**d2pzn)//(2*dpzn^^2); 17996 znp1 = zn - pzn//dpzn**([1,0] + hn); 17997 ); 17998 norm(znp1 - zn)<precision?break(); 17999 zn = znp1; 18000 ); 18001 cabs(zn)<2?[ zn,iter ]:[ 0,0,iter ]" 18002 18003#@cli j3d : eq. to 'object3d'. : (+) 18004 18005#@cli object3d : [object3d],_x[%],_y[%],_z,_opacity,_rendering_mode,_is_double_sided={ 0 | 1 },\ 18006# _is_zbuffer={ 0 | 1 },_focale,_light_x,_light_y,_light_z,_specular_lightness,_specular_shininess : (+) 18007#@cli : Draw specified 3D object on selected images. 18008#@cli : (eq. to 'j3d').\n 18009#@cli : 'rendering_mode' can be { 0=dots | 1=wireframe | 2=flat | 3=flat-shaded | 4=gouraud-shaded | 5=phong-shaded }. 18010#@cli : Default values: 'x=y=z=0', 'opacity=1' and 'is_zbuffer=1'. All other arguments take their default values 18011#@cli : from the 3D environment variables. 18012#@cli : $ image.jpg torus3d 100,10 cone3d 30,-120 add3d[-2,-1] rotate3d. 1,1,0,60 object3d[0] [-1],50%,50% keep[0] 18013 18014#@cli pack_sprites : _nb_scales>=0,0<=_min_scale<=100,_allow_rotation={ 0=0 deg. | 1=180 deg. | 2=90 deg. | 3=any },\ 18015# _spacing,_precision>=0,max_iterations>=0 18016#@cli : Try to randomly pack as many sprites as possible onto the 'empty' areas of an image. 18017#@cli : Sprites can be eventually rotated and scaled during the packing process. 18018#@cli : First selected image is the canvas that will be filled with the sprites. 18019#@cli : Its last channel must be a binary mask whose zero values represent potential locations for drawing the sprites. 18020#@cli : All other selected images represent the sprites considered for packing. 18021#@cli : Their last channel must be a binary mask that represents the sprite shape (i.e. a 8-connected component). 18022#@cli : The order of sprite packing follows the order of specified sprites in the image list. 18023#@cli : Sprite packing is done on random locations and iteratively with decreasing scales. 18024#@cli : 'nb_scales' sets the number of decreasing scales considered for all specified sprites to be packed. 18025#@cli : 'min_scale' (in %) sets the minimal size considered for packing (specified as a percentage of the 18026#@cli : original sprite size). 18027#@cli : 'spacing' can be positive or negative. 18028#@cli : 'precision' tells about the desired number of failed trials before ending the filling process. 18029#@cli : Default values: 'nb_scales=5', 'min_scale=25', 'allow_rotation=3', 'spacing=1', 'precision=7' \ 18030# and 'max_iterations=256'. 18031#@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 \ 18032# to_rgba pack_sprites 3,25 18033pack_sprites : check "isint(${1=5}) && $1>=0 && ${2=25}>=0 && $2<=100 && isint(${3=3}) && $3>=0 && $3<=3 && 18034 isint(${4=1}) && isint(${5=7}) && $5>=0 && isint(${6=256}) && $6>=0" 18035 e[^-1] "Randomly pack image$? with $1 scales, minimum scale $2%, "${arg\ 1+$3,no,180\"\ \"deg.,90\"\ \"deg.,any}\ 18036 " rotation, spacing $4, precision $5 and $6 maximum iterations." 18037 N={$!-1} is_first_time=1 18038 repeat $! r[$>] 100%,100%,1,{$>,max(2,s)} done # Ensure all images have a binary shape mask. 18039 18040 # Start iterations over scales. 18041 repeat $1 18042 rprogress {$>*100/$1} 18043 nb_attempts=0 18044 18045 # Generate all sprites for current scale. 18046 ratio={if($1>1,$2+(100-$2)*$</($1-1),100)}% 18047 repeat $N +l[{1+$>}] 18048 w={w*$ratio} h={h*$ratio} 18049 if $w<1||$h<1 rm 18050 else r $w,$h,1,100%,2 sh. 100% !=. 0 area{1+$>}={is} rm. 18051 fi 18052 endl done 18053 18054 # Pack rescaled sprites together. 18055 l[0,{$N+1}--1] repeat $6 18056 18057 # Compute reference sprite. 18058 ind={1+($>%$N)} area=${area$ind} 18059 if $3==0 [$ind] 18060 elif $3==1 +rotate[$ind] {round(u)*180} 18061 elif $3==2 +rotate[$ind] {round(u(3))*90} 18062 else +rotate[$ind] {u*360} sh. 100% !=. 0 area={is} rm. 18063 fi 18064 18065 # Get binary map of possible locations. 18066 +channels[0] 100% ==. 0 18067 if $4>1 erode. {2*$4-1} 18068 elif $4<1 dilate. {-2*$4+3} 18069 fi 18070 18071 # Generate random skeleton-oriented point cloud. 18072 +rectangle. 0,0,100%,100%,1,0xFFFFFFFF,0 18073 if $is_first_time noise. 0.1,2 ==. 1 fi 18074 distance. 0 noise. 1,1 18075 max_patch. {$ind,round(1.5*max(w,h))} 18076 *. .. pointcloud3d. 18077 18078 # Subdivide point cloud if multiple sprites. 18079 if $N>1 l. 18080 s3d /[1] $N round[1] max[1] 1 n={1,@0} 18081 r[2] 3,{{2,h}/3},1,1,-1 18082 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] 18083 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 18084 endl fi 18085 18086 # Create 3D cloud of sprites. 18087 n={@7} 18088 if $n 18089 s3d. rm[-2,-1] 18090 if $3==0 # No rotation allowed. 18091 [-6] i.. (-128;{w};{h};{s}) 18092 if $n>1 4,{$n-1},1,1,-128,0,0,0 fi 18093 +channels.. 100% i.. (-128;{w};{h};{s}) 18094 if $n>1 ... fi 18095 elif $3==1 # 180 deg. rotation allowed. 18096 +rotate[-6] {round(u(1))*180} i.. (-128;{w};{h};{s}) 18097 if $n>1 +rotate. 180 i.. (-128;{w};{h};{s}) fi 18098 if $n>2 4,{$n-2},1,1,-128,0,0,0 1,100% rand. 0,1 round. 1 j.. .,1 rm. fi 18099 +channels[-4] 100% i.. (-128;{w};{h};{s}) 18100 if $n>1 +channels[-4] 100% i.. (-128;{w};{h};{s}) fi 18101 if $n>2 [-5] fi 18102 else # 90 deg. rotation (or more) allowed. 18103 +rotate[-6] {round(u(3))*90} i.. (-128;{w};{h};{s}) 18104 if $n>1 +rotate. 90 i.. (-128;{w};{h};{s}) fi 18105 if $n>2 +rotate. 90 i.. (-128;{w};{h};{s}) fi 18106 if $n>3 +rotate. 90 i.. (-128;{w};{h};{s}) fi 18107 if $n>4 4,{$n-4},1,1,-128,0,0,0 1,100% rand. 0,3 round. 1 j.. .,1 rm. fi 18108 +channels[-8] 100% i.. (-128;{w};{h};{s}) 18109 if $n>1 +channels[-8] 100% i.. (-128;{w};{h};{s}) fi 18110 if $n>2 +channels[-8] 100% i.. (-128;{w};{h};{s}) fi 18111 if $n>3 +channels[-8] 100% i.. (-128;{w};{h};{s}) fi 18112 if $n>4 [-9] fi 18113 fi 18114 y[{$N+3}--1] a[{$N+3}--1] y 18115 fi 18116 rm... # Delete reference sprite. 18117 18118 # Draw cloud and detect non-intersecting sprites. 18119 [0] sh. 100% f. 1 -. [-4] 18120 j3d.. ...,0,0,0,1,2,0,0 rm[-3,-1] 18121 sh. 100% area_fg. 0,1 ==. $area 18122 *. ... rm... sh.. 0,{-2,s-2} *. .. rm. 18123 18124 # Draw selected sprites on rendering image. 18125 if iM j[0] ..,0,0,0,0,1,. rm[-2,-1] 18126 else 18127 rm[-2,-1] 18128 nb_attempts+=1 18129 if $nb_attempts>$5 break else continue fi 18130 fi 18131 18132 done k[0] endl 18133 18134 done k[0] 18135 18136#@cli piechart : label_height>=0,label_R,label_G,label_B,"label1",value1,R1,G1,B1,...,"labelN",valueN,RN,GN,BN 18137#@cli : Draw pie chart on selected (RGB) images. 18138#@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 18139piechart : check $1>=0 18140 e[^-1] "Draw pie chart on image$?, with label height $1 and color ($2,$3,$4)." 18141 $=arg repeat $! l[$>] 18142 ellipse 50%,50%,{w/2-1},{h/2-1},0,1,1 18143 ellipse 50%,50%,{w/2-1},{h/2-1},0,1,0xFFFFFFFF 18144 (${6--1:5}) normalize_sum. 18145 theta=0 18146 if w>1 repeat w 18147 xe={0.5*{-2,w}*(1+cos($theta))} 18148 ye={0.5*{-2,h}*(1+sin($theta))} 18149 line.. 50%,50%,$xe,$ye 18150 theta-={2*pi*i($>)} 18151 done fi 18152 theta=0 18153 repeat w if i($>) 18154 ntheta={$theta-2*pi*i($>)} 18155 xc={0.5*{-2,w}*(1+0.5*cos(0.5*($ntheta+$theta)))} 18156 yc={0.5*{-2,h}*(1+0.5*sin(0.5*($ntheta+$theta)))} 18157 xf={0.5*{-2,w}*(1+0.8*cos(0.5*($ntheta+$theta)))} 18158 yf={0.5*{-2,h}*(1+0.8*sin(0.5*($ntheta+$theta)))} 18159 flood.. $xf,$yf,0,0,0,1,${arg{7+5*$>}},${arg{8+5*$>}},${arg{9+5*$>}} 18160 if abs($ntheta-$theta)>0.1 18161 0 t. ${arg{5+5*$>}},0,0,$1,1,1 18162 ($2^$3^$4) r. ..,..,1,3 *. .. 18163 j[-4] .,{$xc-w/2},{$yc-h/2},0,0,1,.. 18164 rm[-2,-1] 18165 fi 18166 theta=$ntheta 18167 fi done 18168 rm. 18169 endl done 18170 18171#@cli plasma : _alpha,_beta,_scale>=0 : (+) 18172#@cli : Draw a random colored plasma fractal on selected images. 18173#@cli : This command implements the so-called 'Diamond-Square' algorithm. 18174#@cli : Default values: 'alpha=1', 'beta=1' and 'scale=8'. 18175#@cli : $ 400,400,1,3 plasma 18176#@cli : $$ https://gmic.eu/oldtutorial/_plasma 18177 18178#@cli point : x[%],y[%],_z[%],_opacity,_color1,... : (+) 18179#@cli : Set specified colored pixel on selected images. 18180#@cli : Default values: 'z=0', 'opacity=1' and 'color1=0'. 18181#@cli : $ image.jpg repeat 10000 point {u(100)}%,{u(100)}%,0,1,${-rgb} done 18182 18183#@cli polka_dots : diameter>=0,_density,_offset1,_offset2,_angle,_aliasing,_shading,_opacity,_color,... 18184#@cli : Draw dots pattern on selected images. 18185#@cli : Default values: 'density=20', 'offset1=offset2=50', 'angle=0', 'aliasing=10', 'shading=1', 'opacity=1' \ 18186# and 'color=255'. 18187#@cli : $ image.jpg polka_dots 10,15,0,0,20,10,1,0.5,0,128,255 18188polka_dots : check $1>=0 skip ${2=20},${3=50},${4=50},${5=0},${6=10},${7=1},${8=1},${9=255} 18189 e[^-1] "Draw polka dots on image$?, with diameter $1, density $2, angle $3 deg., shift ($4,$5), aliasing $6 and 18190 shading $7." 18191 theta={$5*pi/180} ct={cos($theta)} st={sin($theta)} mid1={$1/2} mid2={$2/2} 18192 i[0] (${9--1}) y[0] c 18193 repeat $!-1 18194 WH={max(w,h)} 18195 100%,100%,100%,1,"xn = 100*x/"$WH"-$3; yn = 100*y/"$WH"-$4; \ 18196 xr = xn*"$ct"-yn*"$st"; yr = xn*"$st"+yn*"$ct"; \ 18197 xc = xr%$2-"$mid2"; yc = yr%$2-"$mid2"; \ 18198 "$mid1"-sqrt(xc*xc+yc*yc)" 18199 *. $6 c. 0,$7 n. 0,$8 (${9--1}) y. c r. ..,..,.. 18200 j... .,0,0,0,0,1,.. rm[-2,-1] 18201 mv. 1 done rm[0] 18202 18203#@cli polygon : N>=1,x1[%],y1[%],...,xN[%],yN[%],_opacity,_pattern,_color1,... : (+) 18204#@cli : Draw specified colored N-vertices polygon on selected images. 18205#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 18206#@cli : even if a color is specified. If a pattern is specified, the polygon is 18207#@cli : drawn outlined instead of filled. 18208#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 18209#@cli : $ image.jpg polygon 4,20%,20%,80%,30%,80%,70%,20%,80%,0.3,0,255,0 \ 18210# polygon 4,20%,20%,80%,30%,80%,70%,20%,80%,1,0xCCCCCCCC,255 18211#@cli : $ image.jpg 2,16,1,1,'u(if(x,{h},{w}))' polygon[-2] {h},{^},0.6,255,0,255 remove[-1] 18212 18213#@cli quiver : [function_image],_sampling[%]>0,_factor>=0,_is_arrow={ 0 | 1 },_opacity,_color1,... 18214#@cli : Draw specified 2D vector/orientation field on selected images. 18215#@cli : Default values: 'sampling=5%', 'factor=1', 'is_arrow=1', 'opacity=1', 'pattern=(undefined)' 18216#@cli : and 'color1=0'. 18217#@cli : $ 100,100,1,2,'if(c==0,x-w/2,y-h/2)' 500,500,1,3,255 quiver[-1] [-2],10 18218#@cli : $ image.jpg +resize2dy 600 luminance[0] gradient[0] mul[1] -1 reverse[0,1] append[0,1] c \ 18219# blur[0] 8 orientation[0] quiver[1] [0],20,1,1,0.8,255 18220quiver : check ${"is_image_arg $1"}" && ${2=5%}>0 && ${3=1}>=0 && isbool(${4=1})" skip "${5=1},${6=0}" 18221 e[^-1] "Draw 2D vector field $1 on image$?, with sampling $2, factor $3, arrows "${"arg 1+$4,disabled,enabled"}", 18222 opacity $5 and color (${6--1})." 18223 pass$1 repeat $!-1 l[$>,-1] 18224 eval ${-math_lib}" 18225 s_sampling = ['$2']; 18226 sampling = s_sampling[size(s_sampling) - 1 ]==_'%'?min(w#0,h#0)*$2:$2; 18227 vmax = max(abs(im),abs(iM)); 18228 vmax = vmax?vmax:1; 18229 fact = $3*sampling/vmax; 18230 for (y = sampling/2, y<h#0, y+=sampling, 18231 for (x = sampling/2, x<w#0, x+=sampling, 18232 X = round(x*w/w#0); Y = round(y*h/h#0); 18233 u = i(X,Y,0,0)*fact; v = i(X,Y,0,1)*fact; 18234 if ($4, 18235 arrow(#0,[x,y],[x + u,y + v],45,sampling/4,$5,[${6--1}]), 18236 polygon(#0,2,[x - 0.5*u,y - 0.5*v],[x + 0.5*u,y + 0.5*v],$5,[${6--1}]); 18237 ); 18238 ); 18239 ); 18240 " 18241 endl done rm. 18242 18243#@cli rectangle : x0[%],y0[%],x1[%],y1[%],_opacity,_pattern,_color1,... 18244#@cli : Draw specified colored rectangle on selected images. 18245#@cli : 'pattern' is an hexadecimal number starting with '0x' which can be omitted 18246#@cli : even if a color is specified. If a pattern is specified, the rectangle is 18247#@cli : drawn outlined instead of filled. 18248#@cli : Default values: 'opacity=1', 'pattern=(undefined)' and 'color1=0'. 18249#@cli : $ image.jpg repeat 30 rectangle {u(100)}%,{u(100)}%,{u(100)}%,{u(100)}%,0.3,${-rgb} done 18250rectangle : skip ${5=1},${6=0},${7=$6} 18251 if ${"is_pattern \"$5\""} 18252 e[0--3] "Draw outlined rectangle from ($1,$2) to ($3,$4) on image$?, with opacity $5 and color (${7--1})." 18253 else 18254 e[0--3] "Draw filled rectangle from ($1,$2) to ($3,$4) on image$?, with opacity $5 and color (${6--1})." 18255 fi 18256 polygon 4,$1,$2,$3,$2,$3,$4,$1,$4,${5--1} 18257 18258#@cli rorschach : 'smoothness[%]>=0','mirroring={ 0=none | 1=x | 2=y | 3=xy } 18259#@cli : Render rorschach-like inkblots on selected images. 18260#@cli : Default values: 'smoothness=5%' and 'mirroring=1'. 18261#@cli : $ 400,400 rorschach 3% 18262rorschach : check "${1=5%}>=0 && isint(${2=1}) && $2>=0 && $2<=3" 18263 e[^-1] "Render rorschach-like inkblots on image$?, with smoothness $1 and "${arg\ 1+$2,no,x,y,xy}"-mirroring." 18264 if $2==0 # No mirroring. 18265 rand -1,1 b $1 >= 0 18266 elif $2==1 # X-mirroring. 18267 repeat $! l[$>] 18268 w={w} 18269 columns 0,{w/2-1} rand -1,1 b $1 >= 0 18270 +mirror x if $w%2 columns. 1,100% fi a x 18271 endl done 18272 elif $2==2 # Y-mirroring. 18273 repeat $! l[$>] 18274 h={h} 18275 rows 0,{h/2-1} rand -1,1 b $1 >= 0 18276 +mirror y if $h%2 rows. 1,100% fi a y 18277 endl done 18278 elif $2==3 # XY-mirroring. 18279 repeat $! l[$>] 18280 w={w} h={h} 18281 z 0,0,{w/2-1},{h/2-1} rand -1,1 b $1 >= 0 18282 +mirror x if $w%2 columns. 1,100% fi a x 18283 +mirror y if $h%2 rows. 1,100% fi a y 18284 endl done 18285 fi 18286 18287#@cli sierpinski : recursion_level>=0 18288#@cli : Draw Sierpinski triangle on selected images. 18289#@cli : Default value: 'recursion_level=7'. 18290#@cli : $ image.jpg sierpinski 7 18291sierpinski : check ${1=7}>=0 skip ${2=50},${3=0},${4=0},${5=100},${6=100},${7=100} 18292 e[^-1] "Draw Sierpinski triangle of degree $1 on image$?." 18293 _sierpinski ${2-7},$1 18294 18295_sierpinski : 18296 if $7<=0 polygon 3,$1%,$2%,$3%,$4%,$5%,$6%,1,255 return fi 18297 _sierpinski $1,$2,{($1+$3)/2},{($2+$4)/2},{($1+$5)/2},{($2+$6)/2},{$7-1} 18298 _sierpinski {($1+$3)/2},{($2+$4)/2},$3,$4,{($3+$5)/2},{($4+$6)/2},{$7-1} 18299 _sierpinski {($1+$5)/2},{($2+$6)/2},$5,$6,{($3+$5)/2},{($4+$6)/2},{$7-1} 18300 18301#@cli spiralbw : width>0,_height>0,_is_2dcoords={ 0 | 1 } 18302#@cli : Input a 2D rectangular spiral image with specified size. 18303#@cli : Default values: 'height=width' and 'is_2dcoords=0'. 18304#@cli : $ spiralbw 16 18305#@cli : $ image.jpg spiralbw {[w,h]},1 +warp[0] [1],0 +warp[2] [1],2 18306spiralbw : check "$1>=1 && ${2=$1}>=1 && isbool(${3=0})" 18307 e[^-1] "Input 2D rectangular spiral image of size $1x$2." 18308 main="alpha = min(x,y,w - 1 - x,h - 1 - y); 18309 t0 = alpha*2*(w + h) - 4*alpha^2; 18310 X = x - alpha; 18311 Y = y - alpha; 18312 W = w - 2*alpha; 18313 H = h - 2*alpha; 18314 t = t0 + (Y==0?X: 18315 X==W - 1?W - 1 + Y: 18316 Y==H - 1?2*W + H - 3 - X: 18317 2*(W + H - 2) - Y);" 18318 if $3 $1,$2,1,2,$main"[ t%w, int(t/w) ]" else $1,$2,1,1,$main fi 18319 18320#@cli spline : x0[%],y0[%],u0[%],v0[%],x1[%],y1[%],u1[%],v1[%],_opacity,_color1,... 18321#@cli : Draw specified colored spline curve on selected images (cubic hermite spline). 18322#@cli : Default values: 'opacity=1' and 'color1=0'. 18323#@cli : $ image.jpg repeat 30 spline {u(100)}%,{u(100)}%,{u(-600,600)},{u(-600,600)},{u(100)}%,{u(100)}%,\ 18324# {u(-600,600)},{u(-600,600)},0.6,255 done 18325spline : skip ${9=1},${10=0} 18326 e[^-1] "Draw spline from ($1,$2) [$3,$4] to ($5,$6) [$7,$8] on image$?, with opacity $9 and color (${10--1})." 18327 repeat $! l[$>] 18328 x0={if(${"is_percent $1"},$1*(w-1),$1)} 18329 y0={if(${"is_percent $2"},$2*(h-1),$2)} 18330 u0={if(${"is_percent $3"},$3*(w-1),$3)} 18331 v0={if(${"is_percent $4"},$4*(h-1),$4)} 18332 x1={if(${"is_percent $5"},$5*(w-1),$5)} 18333 y1={if(${"is_percent $6"},$6*(h-1),$6)} 18334 u1={if(${"is_percent $7"},$7*(w-1),$7)} 18335 v1={if(${"is_percent $8"},$8*(h-1),$8)} 18336 eval ${-math_lib}"spline(#0,["$x0","$y0"],["$u0","$v0"],["$x1","$y1"],["$u1","$v1"],$9,[${10--1}])" 18337 endl done 18338 18339#@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,... 18340#@cli : Draw tetraedron with interpolated colors on selected (volumetric) images. 18341tetraedron_shade : 18342 e[^-1] "Draw tetraderon ($1,$2,$3)-($4,$5,$6)-($7,$8,$9)-($10,$11,$12) with interpolated colors in image$?." 18343 18344 # Find bounding box. 18345 xm={round(min($1,$4,$7,$10),1,-1)} xM={round(max($1,$4,$7,$10),1,1)} 18346 ym={round(min($2,$5,$8,$11),1,-1)} yM={round(max($2,$5,$8,$11),1,1)} 18347 zm={round(min($3,$6,$9,$12),1,-1)} zM={round(max($3,$6,$9,$12),1,1)} 18348 18349 # Find color mapping coefficients for each vertex. 18350 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 18351 18352 # Draw tetraedron on selected images. 18353 f[^-1] "* 18354 begin( 18355 x0 = $1; y0 = $2; z0 = $3; 18356 x1 = $4; y1 = $5; z1 = $6; 18357 x2 = $7; y2 = $8; z2 = $9; 18358 x3 = $10; y3 = $11; z3 = $12; 18359 u01 = x1 - x0; v01 = y1 - y0; w01 = z1 - z0; 18360 u02 = x2 - x0; v02 = y2 - y0; w02 = z2 - z0; 18361 u03 = x3 - x0; v03 = y3 - y0; w03 = z3 - z0; 18362 u12 = x2 - x1; v12 = y2 - y1; w12 = z2 - z1; 18363 u13 = x3 - x1; v13 = y3 - y1; w13 = z3 - z1; 18364 u23 = x3 - x2; v23 = y3 - y2; w23 = z3 - z2; 18365 nx012 = v01*w02 - w01*v02; ny012 = w01*u02 - u01*w02; nz012 = u01*v02 - v01*u02; 18366 if (nx012*u03 + ny012*v03 + nz012*w03<0, nx012*=-1; ny012*=-1; nz012*=-1); 18367 nx013 = v01*w03 - w01*v03; ny013 = w01*u03 - u01*w03; nz013 = u01*v03 - v01*u03; 18368 if (nx013*u02 + ny013*v02 + nz013*w02<0, nx013*=-1; ny013*=-1; nz013*=-1); 18369 nx023 = v02*w03 - w02*v03; ny023 = w02*u03 - u02*w03; nz023 = u02*v03 - v02*u03; 18370 if (nx023*u01 + ny023*v01 + nz023*w01<0, nx023*=-1; ny023*=-1; nz023*=-1); 18371 nx123 = v12*w13 - w12*v13; ny123 = w12*u13 - u12*w13; nz123 = u12*v13 - v12*u13; 18372 if (-nx123*u01 - ny123*v01 - nz123*w01<0, nx123*=-1; ny123*=-1; nz123*=-1); 18373 ); 18374 if (x<"$xm" || x>"$xM" || y<"$ym" || y>"$yM" || z<"$zm" || z>"$zM",i, 18375 dx0 = x - x0; dy0 = y - y0; dz0 = z - z0; 18376 dx1 = x - x1; dy1 = y - y1; dz1 = z - z1; 18377 is_in = dx0*nx012 + dy0*ny012 + dz0*nz012>=0 && 18378 dx0*nx013 + dy0*ny013 + dz0*nz013>=0 && 18379 dx0*nx023 + dy0*ny023 + dz0*nz023>=0 && 18380 dx1*nx123 + dy1*ny123 + dz1*nz123>=0; 18381 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 18382 ) 18383" 18384 rm. 18385 18386#@cli t : eq. to 'text'. : (+) 18387 18388#@cli text : text,_x[%|~],_y[%|~],_font_height[%]>=0,_opacity,_color1,... : (+) 18389#@cli : Draw specified colored text string on selected images. 18390#@cli : (eq. to 't').\n 18391#@cli : If one of the x or y argument ends with a '~', its value is expected to be 18392#@cli : a centering ratio (in [0,1]) rather than a position. 18393#@cli : Usual centering ratio are { 0=left-justified | 0.5=centered | 1=right-justified }. 18394#@cli : Sizes '13' and '128' are special and correspond to binary fonts (no-antialiasing). 18395#@cli : Any other font size is rendered with anti-aliasing. 18396#@cli : Specifying an empty target image resizes it to new dimensions such that the image contains 18397#@cli : the entire text string. 18398#@cli : Default values: 'x=y=0.01~', 'font_height=16', 'opacity=1' and 'color1=0'. 18399#@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 \ 18400# y+={2*$>} done 18401#@cli : $ 0 text "G'MIC",0,0,23,1,255 18402 18403#@cli to : eq. to 'text_outline'. 18404to : skip "${1=}",${2=0.01~},${3=0.01~} check "${4=7.5%}>0 && ${5=2}>=0 && isnum(${6=1}) && isnum(${7=255}) && "\ 18405 "isnum(${8=$7}) && isnum(${9=$7}) && isnum(${10=255})" 18406 _text_outline $"*" 18407 18408#@cli text_outline : text,_x[%|~],_y[%|~],_font_height[%]>0,_outline>=0,_opacity,_color1,... 18409#@cli : Draw specified colored and outlined text string on selected images. 18410#@cli : If one of the x or y argument ends with a '~', its value is expected to be 18411#@cli : a centering ratio (in [0,1]) rather than a position. 18412#@cli : Usual centering ratio are { 0=left-justified | 0.5=centered | 1=right-justified }. 18413#@cli : Default values: 'x=y=0.01~', 'font_height=7.5%', 'outline=2', 'opacity=1', 'color1=color2=color3=255' \ 18414# and 'color4=255'. 18415#@cli : $ image.jpg text_outline "Hi there!",10,10,63,3 18416text_outline : skip "${1=}",${2=0.01~},${3=0.01~} 18417 check "${4=7.5%}>0 && ${5=2}>=0 && isnum(${6=1}) && isnum(${7=255}) && "\ 18418 "isnum(${8=$7}) && isnum(${9=$7}) && isnum(${10=255})" 18419 _text_outline $"*" 18420 18421_text_outline : skip "${1=}" 18422 e[0--3] "Draw outlined text '$1' at position ($2,$3) on image$?, with font height $4, outline $5, opacity $6 and 18423 color ${7--1}." 18424 if ['"$1"']==0 return fi 18425 sepx,sepy={"sx=['$2']; sy=['$3']; [sx[size(sx)-1], sy[size(sy)-1]]"} 18426 is_fontpercent=${"is_percent $4"} 18427 xpos={`s=['"$2"'];$sepx==_'~'||$sepx==_'%'?s[0,size(s)-1]:s`} 18428 ypos={`s=['"$3"'];$sepy==_'~'||$sepy==_'%'?s[0,size(s)-1]:s`} 18429 repeat $! l[$>] 18430 0 t. "$1",0,0,{-2,$is_fontpercent?h*$4:$4},1,1 expand_xy. {1+$5},0 18431 +dilate. {2*$5+1} 18432 i[-3] (${7--1}) r... {s#0},1,1,1,0,2 y... c r... .,.,1,100% 18433 if $5 *[-3,-2] else rm.. fi 18434 if w#0 18435 j... ..,{[($sepx==_'~'?(w#0-1-w):$sepx==_'%'?(w#0-1)%:1)*$xpos,\ 18436 ($sepy==_'~'?(h#0-1-h):$sepy==_'%'?(h#0-1)%:1)*$ypos]},0,0,$6,. 18437 k[0] 18438 else k[1] 18439 fi 18440 endl done 18441 18442#@cli triangle_shade : x0,y0,x1,y1,x2,y2,R0,G0,B0,...,R1,G1,B1,...,R2,G2,B2,... 18443#@cli : Draw triangle with interpolated colors on selected images. 18444#@cli : $ image.jpg triangle_shade 20,20,400,100,120,200,255,0,0,0,255,0,0,0,255 18445triangle_shade : 18446 e[^-1] "Draw triangle ($1,$2)-($3,$4)-($5,$6) with interpolated colors on image$?." 18447 # Find color mapping coefficients for each vertex. 18448 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 18449 18450 # Pre-compute coefs to test point inside triangle. 18451 invarea={(-$4*$5+$2*(-$3+$5)+$1*($2-$6)+$3*$6)^-1} 18452 s1={$2*$5-$1*$6} s2={$6-$2} s3={$1-$5} 18453 t1={$1*$4-$2*$3} t2={$2-$4} t3={$3-$1} 18454 18455 # Begin drawing on each selected image. 18456 repeat $!-1 l[$>,-1] repeat s#0 18457 a={i(0,0,0,$>)} b={i(0,1,0,$>)} c={i(0,2,0,$>)} 18458 sh[0] $> 18459 f. "s = "$invarea"*("$s1" + "$s2"*x + "$s3"*y); 18460 t = "$invarea"*("$t1" + "$t2"*x + "$t3"*y); 18461 s>=0 && t>=0 && t+s<=1 ? "$a"*x+"$b"*y+"$c":i" 18462 rm. 18463 done endl done 18464 rm. 18465 18466#@cli truchet : _scale>0,_radius>=0,_pattern_type={ 0=straight | 1=curved } 18467#@cli : Fill selected images with random truchet patterns. 18468#@cli : Default values: 'scale=32', 'radius=5' and 'pattern_type=1'. 18469#@cli : $ 400,300 truchet , 18470truchet : check "isint(${1=32}) && $1>0 && ${2=3}>=0" skip ${3=1} 18471 e[^-1] "Render "${arg\ 1+!$3,curved,straight}" truchet patterns in image$?, with scale $1 and radius $2." 18472 repeat $! l[$>] nm={0,n} 18473 w={w} h={h} s={s} rm 18474 $1,$1 = 1,0,0 = 1,100%,100% distance 1,{1+$3} M={int(iM/2)} # Generate truchet pattern and its mirrored version. 18475 ir {$M-$2/2-($1%2)},{$M+$2/2} +mirror y a x 18476 {round($w/$1,1,1)},{round($h/$1,1,1)} rand. 0,1 >=. 50% r. {w*$1},{h*$1} *. $1 18477 channels. 0,1 (0,{$1-1}) r. $1,$1,1,1,3 +transpose. a[-2,-1] c ri. ..,0,2 +[-2,-1] 18478 warp.. . rm. >= 50% r $w,$h,1,1,0 r 100%,100%,1,$s 18479 nm $nm endl done 18480 18481#@cli turbulence : _radius>0,_octaves={1,2,3...,12},_alpha>0,_difference={-10,10},_mode={0,1,2,3} 18482#@cli : Render fractal noise or turbulence on selected images. 18483#@cli : Default values: 'radius=32', 'octaves=6', 'alpha=3', 'difference=0' and 'mode=0'. 18484#@cli : $ 400,400,1,3 turbulence 16 18485#@cli : $$ https://gmic.eu/oldtutorial/_turbulence 18486turbulence : check "${1=32}>0 && ${2=6}>0" skip ${3=3},${4=0},${5=0} 18487 e[^-1] "Render fractal noise or turbulence on image$?, with radius $1, octaves $2, damping per octave $3, 18488 difference $4 and mode $5." 18489 repeat $! l[$>] nm={0,n} 18490 if $4 . fi 18491 f. 0 +noise. 10,0 b. $1,0 18492 if $5==0||$5==1 -. {ia} abs. 18493 elif $5==3||$5==4 ^. 2 18494 elif $5==5 ^. 3 18495 fi 18496 repeat $2-1 18497 +noise.. 10,0 b. {$1/2^$>},0 18498 if $5==0 -. {ia} abs. 18499 elif $5==4 ^. 2 18500 elif $5==5 ^. 3 18501 fi 18502 *.. $3 +[-2--1] 18503 done 18504 n. 0,255 18505 rm.. 18506 if $4 *. $4 mv.. 2 - n. 0,255 fi 18507 nm $nm endl done 18508 18509#@cli yinyang 18510#@cli : Draw a yin-yang symbol on selected images. 18511#@cli : $ 400,400 yinyang 18512yinyang : 18513 e[^-1] "Draw yin-yang symbol on image$?." 18514 f 0 repeat $! l[$>] 18515 s={s} channels 0 18516 r={round(0.95*min(w,h)/4)} 18517 +line 50%,0,50%,50%,1,2 ellipse. 50%,{h/2-$r},$r,$r,0,1,2 18518 line. 50%,50%,50%,100%,1,1 ellipse. 50%,{h/2+$r},$r,$r,0,1,1 18519 flood. {w/2-$r},50%,0,0,0,1,2 18520 flood. {w/2+$r},50%,0,0,0,1,1 18521 ellipse.. 50%,50%,{2*$r},{2*$r},0,1,1 18522 * 18523 ellipse. 50%,{h/2-$r},{$r/3},{$r/3},0,1,1 18524 ellipse. 50%,{h/2+$r},{$r/3},{$r/3},0,1,2 18525 r 100%,100%,1,$s 18526 endl done 18527 18528#--------------------------------- 18529# 18530#@cli :: Matrix Computation 18531# 18532#--------------------------------- 18533 18534#@cli dijkstra : starting_node>=0,ending_node>=0 : (+) 18535#@cli : Compute minimal distances and paths from specified adjacency matrices by the Dijkstra algorithm. 18536 18537#@cli eigen : (+) 18538#@cli : Compute the eigenvalues and eigenvectors of selected symmetric matrices or matrix fields. 18539#@cli : If one selected image has 3 or 6 channels, it is regarded as a field of 2x2 or 3x3 symmetric matrices, 18540#@cli : whose eigen elements are computed at each point of the field. 18541#@cli : $ (1,0,0;0,2,0;0,0,3) +eigen 18542#@cli : $ image.jpg structuretensors blur 2 eigen split[0] c 18543#@cli : $$ https://gmic.eu/oldtutorial/_eigen 18544 18545#@cli invert : solver={ 0=SVD | 1=LU } : (+) 18546#@cli : Compute the inverse of the selected matrices. 18547#@cli : SVD solver is slower but less numerically instable than LU. 18548#@cli : Default value: 'solver=1'. 18549#@cli : $ (0,1,0;0,0,1;1,0,0) +invert 18550 18551#@cli orthogonalize : _mode = { 0=orthogonalize | 1=orthonormalize } 18552#@cli : Orthogonalize or orthonormalize selected matrices, using Modified Gram-Schmidt process. 18553#@cli : Default value: 'mode=0'. 18554orthogonalize : 18555 if isbool($1) mode=$1 else mode=0 noarg fi 18556 u0,u1,v0,v1=Orthogonalize,Orthonormalize,x,ce 18557 e[^-1] ${u$mode}" matri"${v{$!!=1}}"$?, using Modified Gram-Schmidt process." 18558 repeat $! l[$>] 18559 eval "> 18560 proj(u,v) = (dot(u,v)/dot(u,u)*u); 18561 for (p = 1, p<w, ++p, 18562 ref(crop(p,0,1,h),v); 18563 repeat (p,q, 18564 ref(crop(q,0,1,h),u); 18565 v-=proj(u,v); 18566 ); 18567 draw(v,p,0,0,0,1,h); 18568 )" 18569 if $mode 18570 eval. "*!y?( 18571 ref(crop(x,0,1,h),v); 18572 n = norm(v); 18573 v/=n?norm(v):1; 18574 draw(v,x,0,0,0,1,h); 18575 )" 18576 fi 18577 endl done 18578 18579#@cli meigen : m>=1 18580#@cli : Compute an approximation of the 'm' largest eigenvalues and eigenvectors of selected symmetric matrices, 18581#@cli : using the Arnoldi iteration method (https://en.wikipedia.org/wiki/Arnoldi_iteration). 18582#@cli : A larger 'm' goes with better numerical precision. 18583#@cli : $ (1,0,0;0,2,0;0,0,3) +meigen 3 18584meigen : check "isint($1) && $1>0" 18585 if $!!=1 s="ce" else s="x" fi 18586 e[^-1] "Compute $1 largest eigen-values of matri"$s"$?." 18587 repeat $! l[$>] nm={n} 18588 if w!=h" || "d!=1" || "s!=1 v 1 error[0--5] "Command 'meigen': Image '"$nm"' is not a square matrix." fi 18589 eval ${-math_lib}" store(meig(crop(),$1,h),'val',1,min($1,h))" $val k. nm $nm 18590 endl done 18591 18592#@cli mproj : [dictionary],_method,_max_iter={ 0=auto | >0 },_max_residual>=0 : (+) 18593#@cli : Find best matching projection of selected matrices onto the span of an over-complete 18594#@cli : dictionary D, using the orthogonal projection or Matching Pursuit algorithm. 18595#@cli : Selected images are 2D-matrices in which each column represent a signal to project. 18596#@cli : '[dictionary]' is a matrix in which each column is an element of the dictionary D. 18597#@cli : 'method' tells what projection algorithm must be applied. It can be: 18598#@cli : \ - 0 = orthogonal projection (least-squares solution using LU-based solver). 18599#@cli : \ - 1 = matching pursuit. 18600#@cli : \ - 2 = matching pursuit, with a single orthogonal projection step at the end. 18601#@cli : \ - >=3 = orthogonal matching pursuit where an orthogonal projection step is performed 18602#@cli : \ every 'method-2' iterations. 18603#@cli : 'max_iter' sets the max number of iterations processed for each signal. 18604#@cli : If set to '0' (default), 'max_iter' is equal to the number of columns in D. 18605#@cli : (only meaningful for matching pursuit and its variants). 18606#@cli : 'max_residual' gives a stopping criterion on signal reconstruction accuracy. 18607#@cli : (only meaningful for matching pursuit and its variants). 18608#@cli : For each selected image, the result is returned as a matrix W 18609#@cli : whose columns correspond to the weights associated to each column of D, 18610#@cli : such that the matrix product D*W is an approximation of the input matrix. 18611#@cli : Default values: 'method=0', 'max_iter=0' and 'max_residual=1e-6'. 18612 18613#@cli solve : [image] : (+) 18614#@cli : Solve linear system AX = B for selected B-matrices and specified A-matrix. 18615#@cli : If the system is under- or over-determined, the least squares solution is returned 18616#@cli : (using SVD-based solver). 18617#@cli : $ (0,1,0;1,0,0;0,0,1) (1;2;3) +solve[-1] [-2] 18618 18619#@cli svd : (+) 18620#@cli : Compute SVD decomposition of selected matrices. 18621#@cli : $ 10,10,1,1,'if(x==y,x+u(-0.2,0.2),0)' +svd 18622 18623#@cli transpose 18624#@cli : Transpose selected matrices. 18625#@cli : $ image.jpg +transpose 18626transpose : 18627 e[^-1] "Transpose image$?." 18628 permute yxzc 18629 18630#@cli trisolve : [image] : (+) 18631#@cli : Solve tridiagonal system AX = B for selected B-vectors and specified tridiagonal A-matrix. 18632#@cli : Tridiagonal matrix must be stored as a 3 column vector, where 2nd column contains the 18633#@cli : diagonal coefficients, while 1st and 3rd columns contain the left and right coefficients. 18634#@cli : $ (0,0,1;1,0,0;0,1,0) (1;2;3) +trisolve[-1] [-2] 18635 18636#--------------------------------- 18637# 18638#@cli :: 3D Meshes 18639# 18640#--------------------------------- 18641 18642#@cli +3d : eq. to 'add3d'. : (+) 18643 18644#@cli add3d : tx,_ty,_tz : [object3d] : (no arg) : (+) 18645#@cli : Shift selected 3D objects with specified displacement vector, or merge them with specified 18646#@cli : 3D object, or merge all selected 3D objects together. 18647#@cli : (eq. to '+3d'). 18648#@cli : Default values: 'ty=tz=0'. 18649#@cli : $ sphere3d 10 repeat 5 +add3d[-1] 10,{u(-10,10)},0 color3d[-1] ${-rgb} done add3d 18650#@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 \ 18651# add3d rotate3d[-1] 0,0,1,18 done double3d 0 18652 18653#@cli animate3d : _width>0,_height>0,_angle_dx,_angle_dy,_angle_dz,_zoom_factor>=0,_filename 18654#@cli : Animate selected 3D objects in a window. 18655#@cli : If argument 'filename' is provided, each frame of the animation is saved as a numbered filename. 18656#@cli : Default values: 'width=640', 'height=480', 'angle_dx=0', 'angle_dy=1', 'angle_dz=0', 'zoom_factor=1' \ 18657# and 'filename=(undefined)'. 18658animate3d : skip ${1=640},${2=480},${3=0},${4=1},${5=0},"${7=""}" check ${6=1}>=0 18659 e[^-1] "Animate 3D object$?, in a $1x$2 window with angle velocities ($3,$4,$5)." 18660 is_multi={$!>1} repeat $! +l[$>] 18661 n3d *3d {$6*min($1,$2)/1.5} c3d 18662 ax=0 ay=0 az=0 frame=0 vfact=1 18663 do 18664 +r3d 1,0,0,$ax r3d. 0,1,0,$ay r3d. 0,0,1,$az 18665 ax+=$3 ay+=$4 az+=$5 18666 $1,$2,1,3,-1 j3d. ..,50%,50%,0,1 18667 if narg("$7") 18668 to_rgba. replace_color. 0,0,-1,-1,-1,255,64,64,64,0 18669 if $is_multi filename=${filename\ "$7",$>,$frame} else filename=${filename\ "$7",$frame} fi 18670 o. $filename frame+=1 18671 else 18672 replace. -1,64 18673 fi 18674 w. {$vfact*w},{$vfact*h},0,0,-1,-1,{0,n} wait 20 k[0] 18675 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,-D} vfact=1.5 fi # Increase window size. 18676 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,-C} vfact={1/1.5} fi # Decrease window size. 18677 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,-R} vfact=1 fi # Decrease window size. 18678 while {*}" && "!{*,ESC}" && "!{*,Q} rm w 0 18679 endl done 18680 18681#@cli apply_camera3d : pos_x,pos_y,pos_z,target_x,target_y,target_z,up_x,up_y,up_z 18682#@cli : Apply 3D camera matrix to selected 3D objects. 18683#@cli : Default values: 'target_x=0', 'target_y=0', 'target_z=0', 'up_x=0', 'up_y=-1' and 'up_z=0'. 18684apply_camera3d : skip ${4=0},${5=0},${6=0},${7=0},${8=-1},${9=0} 18685 e[^-1] "Apply 3D camera matrix to 3D object$?, with camera position ($1,$2,$3), target position ($4,$5,$6) and 18686 up-vector ($7,$8,$9)." 18687 ({$4-$1}^{$5-$2}^{$6-$3}) # f. 18688 ($7^$8^$9) # up. 18689 orientation[-2,-1] # f/|f| and up/|up|. 18690 _cross3d {-2,^},{^} # s = f x up 18691 _cross3d {^},{-3,^} # u = s x f 18692 rm... y[-3--1] x mv[-2,-1] -3 18693 a[-3--1] y z. 0,3 # Rotation matrix R. 18694 -3d[^-1] $1,$2,$3 pose3d[^-1] {^} rm. -3d 0,0,800 18695 18696_cross3d : 18697 ({$2*$6-$3*$5}^{$3*$4-$1*$6}^{$1*$5-$2*$4}) orientation. y. 18698 18699#@cli apply_matrix3d : a11,a12,a13,...,a31,a32,a33 18700#@cli : Apply specified 3D rotation matrix to selected 3D objects. 18701#@cli : $ torus3d 10,1 +apply_matrix3d {mul(rot(1,0,1,-15°),[1,0,0,0,2,0,0,0,8],3)} double3d 0 18702apply_matrix3d : 18703 e[^-1] "Apply 3x3 matrix (${1-3};${4-6};${7-9}) to 3D object$?." 18704 repeat $! l[$>] 18705 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. 18706 endl done 18707 18708#@cli array3d : size_x>=1,_size_y>=1,_size_z>=1,_offset_x[%],_offset_y[%],_offset_y[%] 18709#@cli : Duplicate a 3D object along the X,Y and Z axes. 18710#@cli : Default values: 'size_y=1', 'size_z=1' and 'offset_x=offset_y=offset_z=100%'. 18711#@cli : $ torus3d 10,1 +array3d 5,5,5,110%,110%,300% 18712array3d : check "isint($1) && $1>0 && isint(${2=1}) && $2>0 && isint(${3=1}) && $3>0" 18713 skip ${4=100%},${5=100%},${6=100%} 18714 e[^-1] "Duplicate 3D object$? along X,Y,Z axes with factors ($1,$2,$3) and offsets ($4,$5,$6)." 18715 repeat $! l[$>] 18716 18717 # Retrieve object dimensions. 18718 +rows 8,{8+3*i[6]} r. 3,{h/3},1,1,-1 s. x,3 18719 dx={-3,if(${is_percent\ $4},$4*(iM-im),$4)} 18720 dy={-2,if(${is_percent\ $5},$5*(iM-im),$5)} 18721 dz={if(${is_percent\ $6},$6*(iM-im),$6)} 18722 rm[-3--1] 18723 18724 # Duplicate along X. 18725 off=0 repeat int(log2($1)) 18726 ++3d. {2^$>*$dx} +3d. .. 18727 if !($1&(2^$>)) rm.. else +3d.. $off off+={2^$>*$dx} fi 18728 done +3d. $off +3d 18729 18730 # Duplicate along Y. 18731 off=0 repeat int(log2($2)) 18732 ++3d. 0,{2^$>*$dy} +3d. .. 18733 if !($2&(2^$>)) rm.. else +3d.. 0,$off off+={2^$>*$dy} fi 18734 done +3d. 0,$off +3d 18735 18736 # Duplicate along Z. 18737 off=0 repeat int(log2($3)) 18738 ++3d. 0,0,{2^$>*$dz} +3d. .. 18739 if !($3&(2^$>)) rm.. else +3d.. 0,0,$off off+={2^$>*$dz} fi 18740 done +3d. 0,0,$off +3d 18741 endl done 18742 18743#@cli arrow3d : x0,y0,z0,x1,y1,z1,_radius[%]>=0,_head_length[%]>=0,_head_radius[%]>=0 18744#@cli : Input 3D arrow with specified starting and ending 3D points. 18745#@cli : Default values: 'radius=5%', 'head_length=25%' and 'head_radius=15%'. 18746#@cli : $ repeat 10 a={$>*2*pi/10} arrow3d 0,0,0,{cos($a)},{sin($a)},-0.5 done +3d 18747arrow3d : check "${7=5%}>=0 && ${8=25%}>=0 && ${9=15%}>=0" 18748 e[^-1] "Input 3D arrow, from (${1-3}) to (${4-6}), with radius $7, head length $8 and head radius $9." 18749 18750 # Create 3D object. 18751 L={sqrt(($4-$1)^2+($5-$2)^2+($6-$3)^2)} 18752 R={if(${is_percent\ $7},$7*$L,$7)} 18753 l={if(${is_percent\ $8},$8*$L,$8)} 18754 r={if(${is_percent\ $9},$9*$L,$9)} 18755 L-=$l cylinder3d $R,$L cone3d $r,$l +3d. 0,0,$L +3d[-2,-1] 18756 18757 # Compute rotation matrix for arrow orientation. 18758 ({$4-$1}^{$5-$2}^{$6-$3}) (0.01^-0.02^0.03) orientation[-2,-1] 18759 _cross3d {-2,^},{^} _cross3d {^},{-3,^} rm... y[-3--1] x mv[-2,-1] -3 18760 a[-3--1] y 18761 18762 # Rotate and translate the arrow at specified coordinates. 18763 s3d.. r[-5] 3,{-5,h/3},1,1,-1 m*[-5,-1] 18764 y[-4] a[-6--1] y +3d. ${1-3} rv3d. 18765 18766#@cli axes3d : _size_x,_size_y,_size_z,_font_size>0,_label_x,_label_y,_label_z,_is_origin={ 0=no | 1=yes } 18767#@cli : Input 3D axes with specified sizes along the x,y and z orientations. 18768#@cli : Default values: 'size_x=size_y=size_z=1', 'font_size=23', 'label_x=X', 'label_y=Y', 'label_z=Z' and \ 18769# 'is_origin=1' 18770#@cli : $ axes3d , 18771axes3d : check "${4=23}>0 && isbool(${8=1})" skip ${1=1},${2=$1},${3=$2},"${5=X},${6=Y},${7=Z}" 18772 e[^-1] "Input 3D axes with sizes ($1,$2,$3)." 18773 l[] 18774 m={max(abs($1),abs($2),abs($3))/40} m2={2*$m} m3={1.2*$m2} 18775 if $1 line3d 0,0,0,$1,0,0 fi 18776 if $2 line3d 0,0,0,0,$2,0 fi 18777 if $3 line3d 0,0,0,0,0,$3 fi 18778 if $1 18779 cone3d $m,{2*$m},16 r3d. 0,1,0,90 +3d. {$1-$m2},0,0 18780 _axes3d "$5",$4 +3d. {$1+$m3},0,0 18781 fi 18782 if $2 18783 cone3d $m,{2*$m},16 r3d. 1,0,0,-90 +3d. 0,{$2-$m2},0 18784 _axes3d "$6",$4 +3d. 0,{$2+$m3},0 18785 fi 18786 if $3 18787 cone3d $m,{2*$m},16 +3d. 0,0,{$3-$m2} 18788 _axes3d "$7",$4 +3d. 0,0,{$3+$m3} 18789 fi 18790 if $8 _axes3d "O",$4 -3d. $m3,$m3,$m3 fi 18791 +3d nm [3d\ axes] 18792 endl 18793 18794_axes3d : 18795 0 t. "$1",2,0,$2,1,1 +dilate. 3 *.. 255 r.. 100%,100%,1,3 18796 i... (67.5;73.5;109.5;103.5;51.5;100.5;1;1;0;0;0;1;0;-128;{w};{h};3) 18797 i.. (-128;{w};{h};1) y[-3,-1] a[-4--1] y 18798 18799#@cli boundingbox3d 18800#@cli : Replace selected 3D objects by their 3D bounding boxes. 18801#@cli : $ torus3d 100,30 +boundingbox3d +3d[-1] [-2] 18802boundingbox3d : 18803 e[^-1] "Replace 3D object$? by their 3D bounding boxes." 18804 repeat $! l[$>] 18805 nbv={f2ui(i[6])} rows 8,{8+3*$nbv} r. 3,$nbv,1,1,-1 s. x 18806 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 ]"} 18807 rm box3d $sx,$sy,$sz c3d +3d $xc,$yc,$zc p3d. 1 18808 endl done 18809 18810#@cli box3d : _size_x,_size_y,_size_z 18811#@cli : Input 3D box at (0,0,0), with specified geometry. 18812#@cli : Default values: 'size_x=1' and 'size_z=size_y=size_x'. 18813#@cli : $ box3d 100,40,30 +primitives3d 1 color3d[-2] ${-rgb} 18814box3d : skip ${1=1},${2=$1},${3=$2} 18815 e[^-1] "Input 3D box, with size ($1,$2,$3)." 18816 1,86,1,1,\ 18817 67.5,73.5,109.5,103.5,51.5,100.5,8,6,\ 18818 0,0,0,$1,0,0,$1,$2,0,0,$2,0,\ 18819 0,0,$3,$1,0,$3,$1,$2,$3,0,$2,$3,\ 18820 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,\ 18821 200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,\ 18822 1,1,1,1,1,1 18823 nm. [3D\ box] 18824 18825#@cli c3d : eq. to 'center3d'. 18826c3d : 18827 _center3d 18828 18829#@cli center3d 18830#@cli : Center selected 3D objects at (0,0,0). 18831#@cli : (eq. to 'c3d'). 18832#@cli : $ repeat 100 circle3d {u(100)},{u(100)},{u(100)},2 done add3d color3d[-1] 255,0,0 +center3d \ 18833# color3d[-1] 0,255,0 add3d 18834center3d : 18835 _$0 18836 18837_center3d : 18838 e[0--3] "Center 3D object$?." 18839 check3d 0 repeat $! l[$>] 18840 if i[6] 18841 s3d r[2] 3,{2,h/3},1,1,-1 s[2] x 18842 -[2] {2,(iM+im)/2} -[3] {3,(iM+im)/2} -[4] {4,(iM+im)/2} 18843 a[2-4] x y[2] a y 18844 fi 18845 endl done 18846 18847#@cli circle3d : _x0,_y0,_z0,_radius>=0 18848#@cli : Input 3D circle at specified coordinates. 18849#@cli : Default values: 'x0=y0=z0=0' and 'radius=1'. 18850#@cli : $ repeat 500 a={$>*pi/250} circle3d {cos(3*$a)},{sin(2*$a)},0,{$a/50} color3d[-1] ${-rgb},0.4 done add3d 18851circle3d : skip ${1=0},${2=0},${3=0},${4=1} 18852 e[^-1] "Input 3D circle at position ($1,$2,$3) with radius $4." 18853 r={$4/sqrt(3)} 18854 1,24,1,1,\ 18855 67.5,73.5,109.5,103.5,51.5,100.5,2,1,\ 18856 {$1-$r},{$2-$r},{$3-$r},\ 18857 {$1+$r},{$2+$r},{$3+$r},\ 18858 5,0,1,0,0,0,200,200,200,1 18859 nm. [3D\ circle] 18860 18861#@cli circles3d : _radius>=0,_is_wireframe={ 0 | 1 } 18862#@cli : Convert specified 3D objects to sets of 3D circles with specified radius. 18863#@cli : Default values: 'radius=1' and 'is_wireframe=1'. 18864#@cli : $ image.jpg luminance resize2dy 40 threshold 50% * 255 pointcloud3d color3d[-1] 255,255,255 circles3d 0.7 18865circles3d : check "${1=1}>=0 && isbool(${2=0})" 18866 e[^-1] "Convert 3D object$? to sets of 3D "${arg\ 1+$2,filled,wireframe}" circles with radius $1." 18867 p3d 0 repeat $! l[$>] 18868 -3d {$1/2},0,0 ++3d $1,0,0 +3d[1] [0] 18869 s3d # Two 3d objects decomposed here! 18870 rows[7] 0 j[1] [7] # Number of points 18871 rv[2,8] # Points 18872 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 18873 k[0-5] a y 18874 endl done 18875 18876#@cli col3d : eq. to 'color3d'. : (+) 18877 18878#@cli color3d : R,_G,_B,_opacity : (no arg) : (+) 18879#@cli : Set color and opacity of selected 3D objects. 18880#@cli : (eq. to 'col3d'). 18881#@cli : Default value: 'B=G=R' and 'opacity=(undefined)'. 18882#@cli : $ torus3d 100,10 double3d 0 repeat 7 +rotate3d[-1] 1,0,0,20 color3d[-1] ${-rgb} done add3d 18883 18884#@cli colorcube3d 18885#@cli : Input 3D color cube. 18886#@cli : $ colorcube3d mode3d 2 +primitives3d 1 18887colorcube3d : 18888 e[^-1] "Input 3D RGB-color cube." 18889 (67.5;73.5;109.5;103.5;51.5;100.5;8;6) 18890 (0;0;0;\ 18891 255;0;0;\ 18892 255;255;0;\ 18893 0;255;0;\ 18894 0;0;255;\ 18895 255;0;255;\ 18896 255;255;255;\ 18897 0;255;255) 18898 (12;0;3;2;1;0;0;0;63;63;63;63;0;\ 18899 12;1;2;6;5;0;0;0;63;63;63;63;0;\ 18900 12;0;4;7;3;0;0;63;0;63;63;0;63;\ 18901 12;4;5;6;7;0;0;63;0;63;63;0;63;\ 18902 12;0;1;5;4;0;0;63;0;63;63;0;63;\ 18903 12;3;7;6;2;0;0;0;63;63;63;63;0) 18904 (0,255;0,255^0,0;255,255^0,0;0,0) 18905 (255,255;255,255^0,0;255,255^0,255;0,255) 18906 (0,0;0,0^0,0;255,255^0,255;0,255) 18907 (0,255;0,255^0,0;255,255^255,255;255,255) 18908 (0,255;0,255^0,0;0,0^0,0;255,255) 18909 (0,255;0,255^255,255;255,255^0,0;255,255) 18910 r[-6--1] 64,64,1,3,3 round[-6--1] y[-6--1] i[-7--2] (-128;64;64;3) 18911 (1;1;1;1;1;1) 18912 a[-16--1] y nm. [3D\ colorcube] 18913 18914#@cli cone3d : _radius,_height,_nb_subdivisions>0 18915#@cli : Input 3D cone at (0,0,0), with specified geometry. 18916#@cli : Default value: 'radius=1','height=1' and 'nb_subdivisions=24'. 18917#@cli : $ cone3d 10,40 +primitives3d 1 color3d[-2] ${-rgb} 18918cone3d : check ${3=24}>0 skip ${1=1},${2=1} 18919 e[^-1] "Input 3D cone, with radius $1, height $2 and $3 subdivisions." 18920 # Header. 18921 (67.5;73.5;109.5;103.5;51.5;100.5) 18922 ({$3+2};{2*$3}) 18923 18924 # Vertices. 18925 (0,0,0;0,0,$2) 18926 (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 18927 18928 # Primitives. 18929 1,$3,1,1,'y' +shift. 0,-1 +[-2,-1] 2 18930 2,$3,1,1,3,0 .. [-4] a[-3--1] x 18931 i[-4] 2,$3,1,1,3,1 a[-4--2] x 18932 a[-2,-1] y 18933 18934 # Colors / opacities. 18935 3,{h},1,1,200 18936 1,{h},1,1,1 18937 y[-4--2] a[-6--1] y nm. [3D\ cone] 18938 18939#@cli cubes3d : _size>=0 18940#@cli : Convert specified 3D objects to sets of 3D cubes with specified size. 18941#@cli : Default value: 'size=1'. 18942#@cli : $ image.jpg luminance resize2dy 40 threshold 50% * 255 pointcloud3d color3d[-1] 255,255,255 cubes3d 1 18943cubes3d : check ${1=1}>=0 18944 e[^-1] "Convert 3D object$? to sets of 3D cubes with size $1." 18945 p3d 0 repeat $! l[$>] 18946 nbv={@6} nbp={@7} 18947 if $nbv&&$nbp 18948 s3d 18949 l[1] = {8*i[0]} = {6*i[1]},0,1 endl # Header. 18950 l[2] r 3,{h/3},1,1,-1 # Vertices. 18951 half={$1/2} 18952 - '$half,0,0' ++ '$1,0,0' a x 18953 - '0,$half,0' ++ '0,$1,0' a x 18954 - '0,0,$half' ++ '0,0,$1' a x 18955 endl 18956 l[3] r 2,{h/2},1,1,-1 # Primitives. 18957 z 1,1 * 8 r 4,100% i[0] 1,100%,1,1,4 a x [-1]x5 a x 18958 + '"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"' 18959 endl 18960 l[4] r 3,{h/3},1,1,-1 r 18,100%,1,1,0,2 endl r[5] 6,100% # Colors & opacities. 18961 y a y 18962 fi 18963 endl done 18964 18965#@cli cup3d : _resolution>0 18966#@cli : Input 3D cup object. 18967#@cli : Default value: 'resolution=128'. 18968#@cli : $ cup3d , 18969cup3d : check ${1=128}>0 18970 e[^-1] "Input 3D cup, with resolution $1." 18971 100,200 18972 ellipse. 0%,0%,40%,40%,0,1,1 18973 ellipse. 0,0,35%,35%,0,1,0 18974 polygon. 4,0,45%,8%,45%,20%,90%,0,90%,1,1 18975 ellipse. 0%,100%,30%,10%,0,1,1 b. 0.1% 18976 lathe3d. $1,2 nm. [3D\ cup] 18977 18978#@cli cylinder3d : _radius,_height,_nb_subdivisions>0 18979#@cli : Input 3D cylinder at (0,0,0), with specified geometry. 18980#@cli : Default value: 'radius=1','height=1' and 'nb_subdivisions=24'. 18981#@cli : $ cylinder3d 10,40 +primitives3d 1 color3d[-2] ${-rgb} 18982cylinder3d : check ${3=24}>0 skip ${1=1},${2=1} 18983 e[^-1] "Input 3D cylinder, with radius $1, height $2 and $3 subdivisions." 18984 l[] 18985 N={round($3)} 18986 nbv,nbp={[2*$N+2,3*$N]} 18987 ({0.5+[{'CImg3d'}]}) 18988 ($nbv,$nbp) 18989 1,$nbv,1,3,"Z = (y<="$N"?0:$2); ang = ((y%("$N"+1))-1)*2*pi/"$N"; 18990 !(y%("$N"+1))?[0,0,Z]:[$1*cos(ang),$1*sin(ang),Z]" 18991 1,$N,1,13,"i1 = 1 + y; i2 = 1 + (i1%"$N"); const j0 = "$N" + 1; j1 = j0 + i1; j2 = j0 + i2; 18992 [ 3,0,i2,i1, 3,j0,j1,j2, 4,i1,i2,j2,j1 ]" 18993 permute[^0,1] "cyzx" 1,$nbp,1,3,200 1,$nbp,1,1,1 y a y 18994 nm. [3D\ cylinder] endl 18995 18996#@cli delaunay3d 18997#@cli : Generate 3D delaunay triangulations from selected images. 18998#@cli : One assumes that the selected input images are binary images containing the set of points to mesh. 18999#@cli : The output 3D object is a mesh composed of non-oriented triangles. 19000#@cli : $ 500,500 noise 0.05,2 eq 1 * 255 +delaunay3d color3d[1] 255,128,0 dilate_circ[0] 5 to_rgb[0] \ 19001# +object3d[0] [1],0,0,0,1,1 max[-1] [0] 19002delaunay3d : 19003 e[^-1] "Generate 3D delaunay triangulation from image$?." 19004 repeat $! l[$>] 19005 channels 0 != 0 19006 19007 # Label each point separately 19008 whd={w},{h},{d} +r 1,{w*h*d},1,1,-1 cumulate. *. .. r. $whd,1,-1 19009 19010 # Compute voronoi diagram of point cloud. 19011 +distance[0] 1 *[2] -1 watershed[1] [2] rm[2] 19012 19013 # Get redondant set of delaunay triangles from the voronoi diagram. 19014 r[1] 100%,100%,100%,3 19015 if d>1 # Add detection cases for 3D images. 19016 +_delaunay3d[1] 1,0,0,0,0,1 +_delaunay3d[1] -1,0,0,0,0,-1 19017 +_delaunay3d[1] 0,1,0,0,0,1 +_delaunay3d[1] 0,-1,0,0,0,-1 19018 fi 19019 +_delaunay3d[1] 1,0,0,0,1,0 _delaunay3d[1] -1,0,0,0,-1,0 # 2D detection. 19020 a[^0] x transpose. -. 1 19021 19022 # Build 3D mesh. 19023 pointcloud3d[0] 19024 s3d[0] rm[3-5] i.. 1,100%,1,1,3 a[-2,-1] x 19025 3,100%,1,1,200 1,100%,1,1,1 =[1] {h},0,1 y a y 19026 endl done 19027 19028_delaunay3d : 19029 f. "A=j($1,$2,$3,0,0,1); B=j($4,$5,$6,0,0,1); 19030 if(i!=A && i!=B && A!=B, kth(1+c,i,A,B),0)" 19031 discard. 0 r. {h/3},3,1,1,-1 19032 19033#@cli distribution3d 19034#@cli : Get 3D color distribution of selected images. 19035#@cli : $ image.jpg distribution3d colorcube3d primitives3d[-1] 1 add3d 19036distribution3d : 19037 e[^-1] "Get 3D color distribution of image$?." 19038 to_rgb permute "cxyz" y 19039 repeat $! l[$>] 19040 nbp={round(h/3)} 19041 i.. (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 19042 $nbp;$nbp) # Number of vertices and primitives. 19043 1,$nbp,1,1,1 +f. y a[-2,-1] x y. # Primitives. 19044 .. # Colors. 19045 1,$nbp,1,1,1 # Opacities. 19046 a y nm. [3D\ distribution] # Build 3D object. 19047 endl done 19048 19049#@cli /3d : eq. to 'div3d'. : (+) 19050 19051#@cli div3d : factor : factor_x,factor_y,_factor_z : (+) 19052#@cli : Scale selected 3D objects isotropically or anisotropically, with the inverse of specified 19053#@cli : factors. 19054#@cli : (eq. to '/3d'). 19055#@cli : Default value: 'factor_z=0'. 19056#@cli : $ torus3d 5,2 repeat 5 +add3d[-1] 12,0,0 div3d[-1] 1.2 color3d[-1] ${-rgb} done add3d 19057 19058#@cli db3d : eq. to 'double3d'. : (+) 19059 19060#@cli double3d : _is_double_sided={ 0 | 1 } : (+) 19061#@cli : Enable/disable double-sided mode for 3D rendering. 19062#@cli : (eq. to 'db3d'). 19063#@cli : Default value: 'is_double_sided=1'. 19064#@cli : $ mode3d 1 repeat 2 torus3d 100,30 rotate3d[-1] 1,1,0,60 double3d $> snapshot3d[-1] 400 done 19065 19066#@cli elevation3d : { z-factor | [elevation_map] | 'formula' },base_height={ -1 | >=0 } : (no arg) 19067#@cli : Generate 3D elevation of selected images, opt. with a specified elevation map. 19068#@cli : When invoked with (no arg) or 'z-factor', the elevation map is computed as the pointwise L2 norm of the 19069#@cli : pixel values. Otherwise, the elevation map is taken from the specified image or formula. 19070#@cli : $ image.jpg +blur 5 elevation3d. 0.75 19071#@cli : $ 128,128,1,3,u(255) plasma 10,3 blur 4 sharpen 10000 n 0,255 \ 19072# elevation3d[-1] 'X=(x-64)/6;Y=(y-64)/6;-100*exp(-(X^2+Y^2)/30)*abs(cos(X)*sin(Y))' 19073elevation3d : skip "${1=_noarg}" check "${2=-1}==-1 || $2>=0" 19074 if $2>=0 base_str=" and base height $2" else base_str= fi 19075 if isnum($1) 19076 e[^-1] "Generate 3D elevation of image$?, with z-factor $1"$base_str. argtype,zfactor=0,$1 19077 elif ${"is_image_arg $1"} 19078 e[^-1] "Generate 3D elevation of image$?, from elevation $1"$base_str. argtype=2 19079 pass$1 0 if s>1 norm. fi store. elevation_img 19080 elif isexpr($1) 19081 e[^-1] "Generate 3D elevation of image$?, with formula '$1'"$base_str. argtype=1 19082 else 19083 e[^-1] "Generate 3D elevation of image$?." argtype,zfactor=0,1 19084 fi 19085 is_base={$2>=0} 19086 19087 repeat $! l[$>] nm={n} 19088 to_rgb M,N={[w,h]} 19089 19090 # Generate vertices. 19091 100%,100%,1,2,[x,y] 19092 if !$argtype +norm[0] *. $zfactor # with z-factor 19093 elif $argtype==1 [0],[0],1,1,"$1" # with formula 19094 else $elevation_img # from [image] 19095 fi 19096 a[-2,-1] c 19097 19098 if $is_base . sh. 100% f. {-sign($1)*$2} rm. a[-2,-1] y fi 19099 r. {wh},1,1,3,-1 permute. cxyz nbv={h} 19100 19101 # Generate primitives. 19102 header="const M = "$M"; const N = "$N"; const MN = M*N" 19103 {[$M,$N]-1},1,5,$header"; # Rear 19104 i0 = M*y + x; i1 = i0 + MN; 19105 [ 4,ui2f(i0),ui2f(i0 + M),ui2f(i0 + 1 + M),ui2f(i0 + 1) ]" 19106 r. 1,{wh},1,100%,-1 nbp={h} 19107 19108 if $is_base # Add base primitives if necessary 19109 {[$M,$N]-1},1,5,$header"; # Front 19110 i0 = M*y + x; i1 = i0 + MN; 19111 [ 4,ui2f(i1),ui2f(i1 + 1),ui2f(i1 + 1 + M),ui2f(i1 + M) ]" 19112 r. 1,{wh},1,100%,-1 nbp+={h} 19113 {$M-1},1,1,10,$header" ; # Top and bottom 19114 i0 = x; i1 = i0 + MN; i2 = i0 + M*(N - 1); i3 = i2 + MN; 19115 [ 4,ui2f(i0),ui2f(i0 + 1),ui2f(i1 + 1),ui2f(i1), 19116 4,ui2f(i2),ui2f(i3),ui2f(i3 + 1),ui2f(i2 + 1) ]" 19117 r. 1,{wh},1,100%,-1 s. c,2 nbp+={2*h} 19118 {$N-1},1,1,10,$header"; # Left and right 19119 i0 = M*x; i1 = i0 + MN; i2 = i0 + M - 1; i3 = i2 + MN; 19120 [ 4,ui2f(i0),ui2f(i1),ui2f(i1 + M),ui2f(i0 + M), 19121 4,ui2f(i2),ui2f(i2 + M),ui2f(i3 + M),ui2f(i3) ]" 19122 r. 1,{wh},1,100%,-1 s. c,2 nbp+={2*h} 19123 permute[-6--1] cyxz -a[-6--1] y 19124 else permute. cyxz 19125 fi 19126 19127 # Generate colors / opacities. 19128 mv[0] $! r. {[w,h]-1},1,3,0 r. {wh},1,1,3,-1 permute. cxyz 19129 if $is_base 3,{$nbp-h},1,1,200 fi 19130 1,$nbp,1,1,1 19131 19132 # Add header and merge object. 19133 i[0] ('CImg3d':y) +[0] 0.5 i[1] ({ui2f([$nbv,$nbp]):;}) y a y 19134 nm $nm 19135 endl done 19136 19137#@cli empty3d 19138#@cli : Input empty 3D object. 19139#@cli : $ empty3d 19140empty3d : 19141 e[^-1] "Input empty 3D object." 19142 (67.5;73.5;109.5;103.5;51.5;100.5;0;0) nm. [3D\ empty] 19143 19144#@cli extrude3d : _depth>0,_resolution>0,_smoothness[%]>=0 19145#@cli : Generate extruded 3D object from selected binary XY-profiles. 19146#@cli : Default values: 'depth=16', 'resolution=1024' and 'smoothness=0.5%'. 19147#@cli : $ image.jpg threshold 50% extrude3d 16 19148extrude3d : check "${1=16}>0 && ${2=1024}>0 && ${3=0.5%}>=0" 19149 e[^-1] "Generate extruded 3D object from XY-profile$?, with depth $1, resolution $2 and smoothness $3." 19150 norm n 0,1 autocrop 0 repeat $! l[$>] nm={0,n} 19151 wr={round(max(1,if(w>h,min($2,w),min($2,h)*w/h)))} 19152 hr={round(max(1,if(w>h,min($2,w)*h/w,min($2,h))))} 19153 fact={$1/max(w/$wr,h/$hr)} 19154 b $3,0 r $wr,$hr,1,1,2 expand_xyz 1,0 19155 isosurface3d 50% *3d 1,1,$fact rv3d 19156 nm $nm endl done 19157 19158#@cli f3d : eq. to 'focale3d'. : (+) 19159 19160#@cli focale3d : focale : (+) 19161#@cli : Set 3D focale. 19162#@cli : (eq. to 'f3d').\n 19163#@cli : Set 'focale' to 0 to enable parallel projection (instead of perspective). 19164#@cli : Set negative 'focale' will disable 3D sprite zooming. 19165#@cli : Default value: 'focale=700'. 19166#@cli : $ repeat 5 torus3d 100,30 rotate3d[-1] 1,1,0,60 focale3d {$<*90} snapshot3d[-1] 400 done remove[0] 19167 19168#@cli gaussians3d : _size>0,_opacity 19169#@cli : Convert selected 3D objects into set of 3D gaussian-shaped sprites. 19170#@cli : $ image.jpg r2dy 32 distribution3d gaussians3d 20 colorcube3d primitives3d[-1] 1 +3d 19171gaussians3d : check "${1=32}>0" skip ${2=0.3} 19172 e[^-1] "Convert 3D object$? into sets of gaussian-shaped 3D sprites, with size $1 and opacity $2." 19173 p3d 2 p3d 0 repeat $! l[$>] nm={0,n} s3d 19174 nbv={h} rm. (-128;$1;$1;1) 19175 $1,$1 gaussian. 35%,35%,0 c. 30%,100% n. 0,$2 y. a[-2,-1] y # First opacity is generated. 19176 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. 19177 a y 19178 nm $nm endl done 19179 19180#@cli gmic3d 19181#@cli : Input a 3D G'MIC logo. 19182#@cli : $ gmic3d +primitives3d 1 19183gmic3d : 19184 e[^-1] "Input 3D G\47MIC logo." 19185 text3d G,60,20,2 col3d. 16,64,255 19186 text3d \',60,20,2 +3d. 40 col3d. 64,128,255 19187 text3d M,60,20,2 +3d. 50 col3d. 96,196,255 19188 text3d I,60,20,2 +3d. 90 col3d. 64,128,255 19189 text3d C,60,20,2 +3d. 100 col3d. 16,64,255 19190 sphere3d 8 +3d. 102,-3,20 col3d. 192,128,255 19191 +3d[-6--1] c3d. 19192 repeat 30 19193 box3d {min(3+$</2,10)} col3d. {30*$>},{20+80*$>},{10*$>},0.5 19194 r3d. 1,1,1,{$>*12} 19195 +3d. {80*cos(0.5+1.02*$>*12*pi/180)},{30*sin(0.8+$>*12*pi/180)},{2*$>-60} 19196 done 19197 +3d[-30--1] +3d. 0,5,30 +3d[-2--1] nm. [3d\ gmic] 19198 19199#@cli gyroid3d : _resolution>0,_zoom 19200#@cli : Input 3D gyroid at (0,0,0), with specified resolution. 19201#@cli : Default values: 'resolution=32' and 'zoom=5'. 19202#@cli : $ gyroid3d 48 +primitives3d 1 19203gyroid3d : check ${1=32}>0 skip ${2=5} 19204 e[^-1] "Input 3D gyroid, with resolution $1 and range $2." 19205 isosurface3d "'0.49*(\ 19206 cos( 2*x + y + z - pi) + cos( 2*x - y + z - pi)\ 19207 + cos(- 2*x + y - z - pi) + cos(- 2*x - y - z - pi)\ 19208 + cos( x + 2*y + z - pi) + cos( x + 2*y - z - pi)\ 19209 + cos(- x - 2*y + z - pi) + cos(- x - 2*y - z - pi)\ 19210 + cos( x + y + 2*z - pi) + cos(- x + y + 2*z - pi)\ 19211 + cos( x - y - 2*z - pi) + cos(- x - y - 2*z - pi)\ 19212 + cos(- 2*x + y + z) + cos( 2*x + y - z)\ 19213 + cos(- 2*x - y + z) + cos( 2*x - y - z)\ 19214 + cos(- x + 2*y + z) + cos( x - 2*y + z)\ 19215 + cos(- x + 2*y - z) + cos( x - 2*y - z)\ 19216 + cos( x - y + 2*z) + cos( x + y - 2*z)\ 19217 + cos(- x - y + 2*z) + cos(- x + y - 2*z)\ 19218 ) + 0.27*( \ 19219 cos(- 2*x + 2*y - pi) + cos( 2*x - 2*y - pi)\ 19220 + cos( 2*x + 2*y - pi) + cos(- 2*x - 2*y - pi)\ 19221 + cos(- 2*y + 2*z - pi) + cos( 2*y - 2*z - pi)\ 19222 + cos( 2*y + 2*z - pi) + cos(- 2*y - 2*z - pi)\ 19223 + cos(- 2*z + 2*x - pi) + cos( 2*z - 2*x - pi)\ 19224 + cos( 2*z + 2*x - pi) + cos(- 2*z - 2*x - pi)\ 19225 ) - 0.69'",0,{-$2},{-$2},{-$2},$2,$2,$2,$1,$1,$1 19226 c3d. n3d. nm. [3D\ gyroid] 19227 19228#@cli histogram3d 19229#@cli : Get 3D color histogram of selected images. 19230#@cli : $ image.jpg resize2dx 64 histogram3d circles3d 3 opacity3d. 0.75 colorcube3d primitives3d[-1] 1 add3d 19231histogram3d : 19232 e[^-1] "Get 3D color histogram of image$?." 19233 to_rgb repeat $! l[$>] 19234 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]" 19235 endl done 19236 19237#@cli image6cube3d 19238#@cli : Generate 3D mapped cubes from 6-sets of selected images. 19239#@cli : $ image.jpg animate flower,"30,0","30,5",6 image6cube3d 19240image6cube3d : 19241 e[^-1] "Generate 3D mapped cubes from image$?." 19242 M={max(${-max_wh})} r $M,$M,1,3 imageplane3d n3d c3d 19243 repeat int($!/6) l[$>-{$>+5}] 19244 +3d[0] 0,0,-0.5 19245 r3d[1] 0,1,0,90 +3d[1] -0.5,0,0 19246 r3d[2] 0,1,0,180 +3d[2] 0,0,0.5 19247 r3d[3] 0,1,0,270 +3d[3] 0.5,0,0 19248 r3d[4] 1,0,0,90 +3d[4] 0,0.5,0 19249 r3d[5] 1,0,0,270 +3d[5] 0,-0.5,0 19250 +3d nm "[3D image cube]" 19251 endl done 19252 19253#@cli imageblocks3d : _maximum_elevation,_smoothness[%]>=0 19254#@cli : Generate 3D blocks from selected images. 19255#@cli : Transparency of selected images is taken into account. 19256#@cli : Default values: 'maximum_elevation=10' and 'smoothness=0'. 19257#@cli : $ image.jpg resize2dy 32 imageblocks3d -20 mode3d 3 19258imageblocks3d : check ${2=0}>=0 skip ${1=10},${3=0} 19259 e[^-1] "Generate 3D blocks from image$?, with maximum elevation $1 and smoothness $2." 19260 repeat $! l[$>] 19261 w={w} h={h} 19262 split_opacity to_rgb[0] is_opacity={$!==2} 19263 19264 # Create 3D object template. 19265 l[] box3d 1,1,0 19266 repeat $w-1 ++3d. 1,0,0 done +3d 19267 repeat $h-1 ++3d. 0,1,0 done +3d 19268 endl 19269 s3d. 19270 19271 # Set vertex altitudes. 19272 +norm[0] b. $2 19273 y. n. 0,$1 19274 r[-5] 24,{-5,round(w*h/24)},1,1,-1 19275 if $1<0 j[-5] .,2 j[-5] .,5 j[-5] .,8 j[-5] .,11 19276 else j[-5] .,14 j[-5] .,17 j[-5] .,20 j[-5] .,23 19277 fi 19278 rm. y[-4] 19279 19280 # Set primitive colors. 19281 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 19282 19283 # Set primitive opacities. 19284 if $is_opacity rm. mv[0] $! /. 255 y. r. 6,100%,1,1 y. fi 19285 19286 a y 19287 endl done 19288 19289#@cli imagecube3d 19290#@cli : Generate 3D mapped cubes from selected images. 19291#@cli : $ image.jpg imagecube3d 19292imagecube3d : 19293 e[^-1] "Generate 3D mapped cubes from image$?." 19294 slices 50% to_rgb repeat $! l[$>] nm={0,n} 19295 i.. (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 19296 8;6;\ # Number of vertices and primitives. 19297 -0.5;-0.5;-0.5;\ # Vertex coordinates. 19298 0.5;-0.5;-0.5;\ 19299 0.5;0.5;-0.5;\ 19300 -0.5;0.5;-0.5;\ 19301 -0.5;-0.5;0.5;\ 19302 0.5;-0.5;0.5;\ 19303 0.5;0.5;0.5;\ 19304 -0.5;0.5;0.5;\ 19305 12;0;3;2;1;0;0;0;{h};{w};{h};{w};0;\ # Primitives description. 19306 12;1;2;6;5;0;0;0;{h};{w};{h};{w};0;\ 19307 12;5;6;7;4;0;0;0;{h};{w};{h};{w};0;\ 19308 12;4;7;3;0;0;0;0;{h};{w};{h};{w};0;\ 19309 12;4;0;1;5;0;0;0;{h};{w};{h};{w};0;\ 19310 12;3;7;6;2;0;0;0;{h};{w};{h};{w};0;\ 19311 -128;{w};{h};{s}) # Texture map for the first face. 19312 y. 19313 (-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. 19314 a y 19315 nm $nm endl done 19316 19317#@cli imageplane3d 19318#@cli : Generate 3D mapped planes from selected images. 19319#@cli : $ image.jpg imageplane3d 19320imageplane3d : 19321 e[^-1] "Generate 3D mapped planes from image$?." 19322 slices 50% to_color repeat $! l[$>] nm={0,n} 19323 i.. (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 19324 4;1;\ # Number of vertices and primitives. 19325 0;0;0;\ # Vertex coordinates. 19326 {w};0;0;\ 19327 {w};{h};0;\ 19328 {0};{h};0;\ 19329 12;0;3;2;1;0;0;0;{h};{w};{h};{w};0;\ # Primitives description. 19330 -128;{w};{h};{s}) # Texture map. 19331 y. 19332 (1) # Opacity. 19333 a y 19334 nm $nm endl done 19335 19336#@cli imagepyramid3d 19337#@cli : Generate 3D mapped pyramids from selected images. 19338#@cli : $ image.jpg imagepyramid3d 19339imagepyramid3d : 19340 e[^-1] "Generate 3D mapped pyramids from image$?." 19341 to_rgb repeat $! l[$>] nm={0,n} 19342 w2={w/2} 19343 i.. (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 19344 5;5;\ # Number of vertices and primitives. 19345 -0.5;-0.5;-0.5;\ # Vertex coordinates. 19346 0.5;-0.5;-0.5;\ 19347 0.5;0.5;-0.5;\ 19348 -0.5;0.5;-0.5;\ 19349 0;0;0.5;\ 19350 12;0;3;2;1;0;0;0;{h};{w};{h};{w};0;\ # Primitives description. 19351 9;0;4;3;0;{h};$w2;0;{w};{h};\ 19352 9;1;4;0;0;{h};$w2;0;{w};{h};\ 19353 9;2;4;1;0;{h};$w2;0;{w};{h};\ 19354 9;3;4;2;0;{h};$w2;0;{w};{h};\ 19355 -128;{w};{h};{s}) # Texture map for the first face. 19356 y. 19357 (-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. 19358 a y 19359 nm $nm endl done 19360 19361#@cli imagerubik3d : _xy_tiles>=1,0<=xy_shift<=100,0<=z_shift<=100 19362#@cli : Generate 3D mapped rubik's cubes from selected images. 19363#@cli : Default values: 'xy_tiles=3', 'xy_shift=5' and 'z_shift=5'. 19364#@cli : $ image.jpg imagerubik3d , 19365imagerubik3d : check "${1=3}>=1 && ${2=5}>=0 && $2<=100 && ${3=5}>=0 && $3<=100" 19366 e[^-1] "Generate 3D mapped rubik\47s cubes from image$? with $1 xy-tiles, xy-shift $2 and z-shift $3." 19367 repeat $! l[$>] nm={0,n} 19368 # Generate primary 3D side. 19369 ('CImg3d') +. 0.5 19370 (8,5) 19371 (0,0,0;\ 19372 100,0,0;\ 19373 100,100,0;\ 19374 0,100,0;\ 19375 $2,$2,{-$3};\ 19376 {100-$2},$2,{-$3};\ 19377 {100-$2},{100-$2},{-$3};\ 19378 $2,{100-$2},{-$3}) 19379 (4,4,7,6,5;\ 19380 4,0,4,5,1;\ 19381 4,3,2,6,7;\ 19382 4,0,3,7,4;\ 19383 4,1,5,6,2) 19384 3,5,1,1,200 19385 1,5,1,1,1 19386 y[-6--1] a[-6--1] y 19387 repeat $1-1 ++3d. 100 done +3d[-$1--1] # Duplicate along X 19388 repeat $1-1 ++3d. 0,100 done +3d[-$1--1] # Duplicate along Y 19389 t3d. .. rm.. 19390 /3d. $1 -3d. 50,50,50 19391 +r3d. 0,1,0,-90 +r3d. 0,1,0,-90 +r3d. 0,1,0,-90 # Generate the 5 other sides. 19392 +r3d. 0,0,1,-90 +r3d. 0,0,1,180 19393 +3d 19394 nm $nm endl done 19395 19396#@cli imagesphere3d : _resolution1>=3,_resolution2>=3 19397#@cli : Generate 3D mapped sphere from selected images. 19398#@cli : Default values: 'resolution1=32' and 'resolutions2=16'. 19399#@cli : $ image.jpg imagesphere3d 32,16 19400imagesphere3d : check "${1=32}>=3 && ${2=16}>=3" 19401 e[^-1] "Generate 3D mapped sphere from image$?, with resolutions ($1,$2)." 19402 to_rgb repeat $! l[$>] nm={0,n} 19403 19404 # Generate object header. 19405 tw={w-1} th={h-1} # Maximum texture xy-coordinates. 19406 nbv={2+$1*($2-2)} # Number of vertices. 19407 nbp={$1*($2-1)} # Number of primitives. 19408 (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 19409 $nbv;$nbp) # Number of vertices and primitives. 19410 19411 # Define sphere vertices. 19412 (0;0;1) (0;0;-1) (0,{2*pi};0,{2*pi}^0,0;{pi},{pi}) 19413 r. {$1+1},$2,1,2,3 z. 0,1,{w-2},{h-2} s. c 19414 +sin. +sin... *[-2,-1] +cos.. sin... cos[-4] *[-4,-3] 19415 a[-3--1] c permute. cxyz y. a[-3--1] y 19416 19417 # Define sphere primitives (triangles and quadrangles). 19418 repeat $1,v 19419 tx0={$v*$tw/$1} tx1={($v+1)*$tw/$1} ty1={$th/($2-1)} 19420 (9;0;{2+$v};{2+($v+1)%$1};{$tw/2};0;$tx0;$ty1;$tx1;$ty1) # Textured triangle from 1st pole. 19421 repeat $2-3,u 19422 ty0=$ty1 ty1={($u+2)*$th/($2-1)} i0={2+$u*$1+$v} i1={2+$u*$1+($v+1)%$1} 19423 (12;$i0;{$i0+$1};{$i1+$1};$i1;$tx0;$ty0;$tx0;$ty1;$tx1;$ty1;$tx1;$ty0) # Textured quadrangle. 19424 done 19425 (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. 19426 done 19427 a[-$nbp--1] y 19428 19429 # Define sphere textures, opacities and generate object. 19430 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 19431 nm $nm endl done 19432 19433#@cli isoline3d : isovalue[%] : 'formula',value,_x0,_y0,_x1,_y1,_size_x>0[%],_size_y>0[%] : (+) 19434#@cli : Extract 3D isolines with specified value from selected images or from specified formula. 19435#@cli : Default values: 'x0=y0=-3', 'x1=y1=3' and 'size_x=size_y=256'. 19436#@cli : $ image.jpg blur 1 isoline3d 50% 19437#@cli : $ isoline3d 'X=x-w/2;Y=y-h/2;(X^2+Y^2)%20',10,-10,-10,10,10 19438 19439#@cli isosurface3d : isovalue[%] : 'formula',value,_x0,_y0,_z0,_x1,_y1,_z1,_size_x>0[%],_size_y>0[%],_size_z>0[%] : (+) 19440#@cli : Extract 3D isosurfaces with specified value from selected images or from specified formula. 19441#@cli : Default values: 'x0=y0=z0=-3', 'x1=y1=z1=3' and 'size_x=size_y=size_z=32'. 19442#@cli : $ image.jpg resize2dy 128 luminance threshold 50% expand_z 2,0 blur 1 isosurface3d 50% mul3d 1,1,30 19443#@cli : $ isosurface3d 'x^2+y^2+abs(z)^abs(4*cos(x*y*z*3))',3 19444 19445#@cli label3d : "text",font_height>=0,_opacity,_color1,... 19446#@cli : Generate 3D text label. 19447#@cli : Default values: 'font_height=13', 'opacity=1' and 'color=255,255,255'. 19448label3d : check ${2=13}>=0 skip ${3=1},${4=255},${5=$4},${6=$5} 19449 e[^-1] "Generate 3D label '$1' with font height $2, opacity $3 and color (${4--1})." 19450 l[] 0 t "$1",0,0,$2,1,${4--1},255 sprite3d endl 19451 19452#@cli label_points3d : _label_size>0,_opacity 19453#@cli : Add a numbered label to all vertices of selected 3D objects. 19454#@cli : Default values: 'label_size=13' and 'opacity=0.8'. 19455#@cli : $ torus3d 100,40,6,6 label_points3d 23,1 mode3d 1 19456label_points3d : check ${1=13}>0 skip ${2=0.8} 19457 e[^-1] "Label vertices of 3D object$?." 19458 repeat $! 19459 +p3d[$>] 0 l. s3d rm[-3--1] 19460 nbp={-2,@0} =.. $nbp,0,1 # Set correct number of primitives 19461 (1,0;1,{$nbp-1}) r. 2,$nbp,1,1,3 r. 1,{2*h},1,1,-1 # Create new primitive data 19462 repeat $nbp # Create texture labels as primitive colors. 19463 0 t. $>,0,0,$1,1,255,255,255 autocrop. 0 19464 i.. (-128;{w};{h};3) y. 19465 done 19466 repeat $nbp # Create texture masks as primitive opacities. 19467 0 t. $>,0,0,$1,1,$2 autocrop. 0 19468 i.. (-128;{w};{h};1) y. 19469 done 19470 a y # Merge final object data. 19471 endl 19472 +3d[$>,-1] 19473 done 19474 19475#@cli lathe3d : _resolution>0,_smoothness[%]>=0,_max_angle>=0 19476#@cli : Generate 3D object from selected binary XY-profiles. 19477#@cli : Default values: 'resolution=128', 'smoothness=0.5%' and 'max_angle=361'. 19478#@cli : $ 300,300 rand -1,1 blur 40 sign normalize 0,255 lathe3d , 19479lathe3d : check "${1=128}>0 && ${2=0.5%}>=0 && ${3=361}>=0" 19480 e[^-1] "Generate lathed 3D object from XY-profile$?, with resolution $1, smoothness $2 and maximum angle $3 deg." 19481 tmax={($3-180)*pi/180} norm n 0,1 autocrop 0 19482 repeat $! l[$>] 19483 wr={max(1,w2=2*w;if(w2>h,min($1,w2),min($1,h)*w2/h))} 19484 hr={max(1,w2=2*w;if(w2>h,min($1,w2)*h/w2,min($1,h)))} 19485 rmax={sqrt(($wr)^2+($hr)^2)/2} 19486 $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))" 19487 *. {2*({-2,w}-1)/(w-1)} r. $wr,$hr,$wr 19488 (0;{{-2,h}-1}) r. $wr,$hr,$wr,1,3 a[-2--1] c 19489 warp.. .,0,1,0 rm. 19490 expand_xyz 10,0 b $2 isosurface3d 50% rv3d 19491 endl done 19492 19493#@cli l3d : eq. to 'light3d'. : (+) 19494 19495#@cli light3d : position_x,position_y,position_z : [texture] : (no arg) : (+) 19496#@cli : Set the light coordinates or the light texture for 3D rendering. 19497#@cli : (eq. to 'l3d').\n 19498#@cli : (no arg) resets the 3D light to default. 19499#@cli : $ torus3d 100,30 double3d 0 specs3d 1.2 repeat 5 light3d {$>*100},0,-300 +snapshot3d[0] 400 done remove[0] 19500 19501#@cli line3d : x0,y0,z0,x1,y1,z1 19502#@cli : Input 3D line at specified coordinates. 19503#@cli : $ repeat 100 a={$>*pi/50} line3d 0,0,0,{cos(3*$a)},{sin(2*$a)},0 color3d. ${-rgb} done add3d 19504line3d : 19505 e[^-1] "Input 3D line (${1-3})-(${4-6})." 19506 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] 19507 19508#@cli lissajous3d : resolution>1,a,A,b,B,c,C 19509#@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))__. 19510#@cli : Default values: 'resolution=1024', 'a=2', 'A=0', 'b=1', 'B=0', 'c=0' and 'C=0'. 19511#@cli : $ lissajous3d , 19512lissajous3d : check ${1=1024}>1 skip ${2=2},${3=0},${4=1},${5=0},${6=0},${7=0} 19513 e[^-1] "Input 3D lissajous curve, with resolution $1, (a,A)=($2,$3), (b,B)=($4,$5) and (c,C)=($6,$7)." 19514 res={round($1)} 19515 19516 # Define object header and vertices. 19517 (67.5;73.5;109.5;103.5;51.5;100.5;$res;{$res-1}) 19518 (0,{2*pi}) r. $res,1,1,1,3 [-1]x2 19519 *... $2 +... {$3*2*pi} *.. $4 +.. {$5*2*pi} *. $6 +. {$7*2*pi} 19520 a[-3--1] y sin. transpose. r. 1,{w*h},1,1,-1 19521 19522 # Define object primitives, colors and opacities. 19523 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 19524 1,{3*($res-1)},1,1,200 1,{$res-1},1,1,1 a[-5--1] y nm. [3D\ lissajou] 19525 19526#@cli m3d : eq. to 'mode3d'. : (+) 19527 19528#@cli mode3d : _mode : (+) 19529#@cli : Set static 3D rendering mode. 19530#@cli : (eq. to 'm3d').\n 19531#@cli : 'mode' can be { -1=bounding-box | 0=dots | 1=wireframe | 2=flat | 3=flat-shaded | 4=gouraud-shaded | \ 19532# 5=phong-shaded }."); 19533#@cli : Bounding-box mode ('mode==-1') is active only for the interactive 3D viewer. 19534#@cli : Default value: 'mode=4'. 19535#@cli : $ (0,1,2,3,4,5) double3d 0 repeat w torus3d 100,30 rotate3d[-1] 1,1,0,60 mode3d {0,@$>} \ 19536# snapshot3d[-1] 300 done remove[0] 19537 19538#@cli md3d : eq. to 'moded3d'. : (+) 19539 19540#@cli moded3d : _mode : (+) 19541#@cli : Set dynamic 3D rendering mode for interactive 3D viewer. 19542#@cli : (eq. to 'md3d').\n 19543#@cli : 'mode' can be { -1=bounding-box | 0=dots | 1=wireframe | 2=flat | 3=flat-shaded | 4=gouraud-shaded | \ 19544# 5=phong-shaded }. 19545#@cli : Default value: 'mode=-1'. 19546 19547#@cli *3d : eq. to 'mul3d'. : (+) 19548 19549#@cli mul3d : factor : factor_x,factor_y,_factor_z : (+) 19550#@cli : Scale selected 3D objects isotropically or anisotropically, with specified factors. 19551#@cli : (eq. to '*3d'). 19552#@cli : Default value: 'factor_z=0'. 19553#@cli : $ torus3d 5,2 repeat 5 +add3d[-1] 10,0,0 mul3d[-1] 1.2 color3d[-1] ${-rgb} done add3d 19554 19555#@cli n3d : eq. to 'normalize3d'. 19556n3d : 19557 _normalize3d 19558 19559#@cli normalize3d 19560#@cli : Normalize selected 3D objects to unit size. 19561#@cli : (eq. to 'n3d'). 19562#@cli : $ repeat 100 circle3d {u(3)},{u(3)},{u(3)},0.1 done add3d color3d[-1] 255,0,0 +normalize3d[-1] \ 19563# color3d[-1] 0,255,0 add3d 19564normalize3d : 19565 _$0 19566 19567_normalize3d : 19568 e[0--3] "Normalize size of 3D object$?." 19569 check3d 0 repeat $! l[$>] 19570 if i[6] 19571 s3d r[2] 3,{2,h/3},1,1,-1 s[2] x 19572 factor={v=max({2,iM-im},{3,iM-im},{4,iM-im});if(v,v,1)} 19573 a[2-4] x /[2] $factor y[2] a y 19574 fi 19575 endl done 19576 19577#@cli o3d : eq. to 'opacity3d'. : (+) 19578 19579#@cli opacity3d : _opacity : (+) 19580#@cli : Set opacity of selected 3D objects. 19581#@cli : (eq. to 'o3d'). 19582#@cli : Default value: 'opacity=1'. 19583#@cli : $ torus3d 100,10 double3d 0 repeat 7 +rotate3d[-1] 1,0,0,20 opacity3d[-1] {u} done add3d 19584 19585#@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,\ 19586# _smoothness>=0,_isovalue>=0 19587#@cli : Input 3D object from specified parametric surface `(a,b) ⟶ (x(a,b),y(a,b),z(a,b))`. 19588#@cli : Default values: 'x=(2+cos(b))*sin(a)', 'y=(2+cos(b))*cos(a)', 'c=sin(b)', 'amin=-pi', 'amax=pi', \ 19589# 'bmin=-pi', 'bmax=pi', \ 19590# 'res_a=512', 'res_b=res_a', 'res_x=64', 'res_y=res_x', 'res_z=res_y', 'smoothness=2%' and 'isovalue=10%'. 19591#@cli : $ parametric3d , 19592parametric3d : skip "${1=(2+cos(b))*sin(a)}","${2=(2+cos(b))*cos(a)}","${3=sin(b)}" 19593 skip ${4={-pi}},${5={pi}},${6={-pi}},${7={pi}} 19594 check "${8=512}>0 && ${9=$8}>0 && ${10=64}>0 && ${11=$10}>0 && ${12=$11}>0 && \ 19595 ${13=2%}>=0 && ${14=10%}>=0" 19596 e[^-1] "Input 3D object from parametric surface ($1,$2,$3)." 19597 # Compute (x(a,b),y(a,b),z(a,b)) and normalize it. 19598 ($4,$5;$4,$5^$6,$6;$7,$7) r. $8,$9,1,2,3 channels. 0,2 19599 f. "a=i(x,y,0,0);b=i(x,y,0,1);if(c==0,$1,if(c==1,$2,$3))" 19600 sh. 0 xmin={im} xmax={iM} n. 16,{$10-17} rm. 19601 sh. 1 ymin={im} ymax={iM} n. 16,{$11-17} rm. 19602 sh. 2 zmin={im} zmax={iM} n. 16,{$12-17} rm. 19603 r. {w*h},3,1,1,-1 19604 19605 # Extract 3D surface. 19606 pointcloud. 1 r. $10,$11,$12,1,0 b. $13,0 19607 isosurface3d. $14 19608 c3d. n3d. *3d. {$xmax-$xmin},{$ymax-$ymin},{$zmax-$zmin} nm. [3D\ parametric] 19609 19610#@cli pca_patch3d : _patch_size>0,_M>0,_N>0,_normalize_input={ 0 | 1 },_normalize_output={ 0 | 1 },_lambda_xy 19611#@cli : Get 3D patch-pca representation of selected images. 19612#@cli : The 3D patch-pca is estimated from M patches on the input image, and displayed as a cloud of N 3D points. 19613#@cli : Default values: 'patch_size=7', 'M=1000', 'N=3000', 'normalize_input=1', 'normalize_output=0', \ 19614# and 'lambda_xy=0'. 19615#@cli : $ image.jpg pca_patch3d 7 19616pca_patch3d : check "isint(${1=7}) && $1>0 && isint(${2=1000}) && $2>0 && isint(${3=3000}) && $3>0" 19617 skip ${4=1},${5=0},${6=0} 19618 e[^-1] "Get 3D patch-pca representation"${arg\ 1+($!>1),s,""}" of image$?, from $2 $1x$1 input patches, 19619 with $3 output patches, input normalization "${arg\ 1+!$4,enabled,disabled}", output normalization "\ 19620 ${arg\ 1+!$5,enabled,disabled}" and lambda_xy $6." 19621 P1={int($1/2)} # Backward half-patch size. 19622 P2={$1-$P1-1} # Forward half-patch size. 19623 19624 n 0,255 round 1 19625 repeat $! l[$>] nm={0,n} 19626 s={s} 19627 19628 # Pick set of M random located patches. 19629 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 19630 z[1] 0,1 transpose[1] *[1] $6 a[1,2] y s[^0] x 19631 19632 # Normalize patch coordinates by using average and standard deviation. 19633 ++[^0] /. $2 -[1--2] . rm. 19634 a[^0] x 19635 if $4 l. s y / 'sqrt(1e-8+iv)' a y endl fi 19636 19637 # Do PCA for dimension reduction. 19638 +transpose. m*[-2,-1] 19639 eigen. rows.. 0,2 columns. 0,2 transpose. 19640 if $5 sqrt.. /.. {-2,iM} ri.. . /. .. fi 19641 rm.. 19642 19643 # Pick set of N random located patches. 19644 repeat $3 19645 x={round(u({0,w}))} 19646 y={round(u({0,h}))} 19647 ({$6*$x};{$6*$y}) 19648 +z[0] {$x-$P1},{$y-$P1},{$x+$P2},{$y+$P2},1 19649 y. a[-2,-1] y 19650 done 19651 19652 # Generate 3D representation of the projected patch set. 19653 +a[2--1] x m*[1,-1] transpose[1] # Vertex coordinates. 19654 rows[2--1] 2,100% # Colors 19655 if $s!=3 19656 r[2--1] $1,$1,1,{min(3,$s)},-1 19657 r[2--1] $1,$1,1,3,{if($s!=1,0,1)} 19658 y[2--1] 19659 fi 19660 i[2--2] (-128;$1;$1;3) a[2--1] y 19661 rm[0] # Remove input image (now useless). 19662 i[0] ('CImg3d') # Header. 19663 i[1] ($3;$3) # Geometry. 19664 i[3] 2,$3,1,1,if(x==0,1,y) # Primitives. 19665 1,$3,1,1,1 # Opacities. 19666 y a[-6--1] y # Merge as a 3D object. 19667 19668 nm $nm endl done 19669 19670#@cli plane3d : _size_x,_size_y,_nb_subdivisions_x>0,_nb_subdisivions_y>0 19671#@cli : Input 3D plane at (0,0,0), with specified geometry. 19672#@cli : Default values: 'size_x=1', 'size_y=size_x' and 'nb_subdivisions_x=nb_subdivisions_y=24'. 19673#@cli : $ plane3d 50,30 +primitives3d 1 color3d[-2] ${-rgb} 19674plane3d : check "${3=24}>0 && ${4=24}>0" skip ${1=1},${2=$1} 19675 e[^-1] "Input 3D plane, with size (${1,2}) and subdivisions (${3,4})." 19676 {$3+1},{$4+1} elevation3d. 0 *3d. {$1/$3},{$2/$4} col3d. 200 nm. [3D\ plane] 19677 19678#@cli point3d : x0,y0,z0 19679#@cli : Input 3D point at specified coordinates. 19680#@cli : $ repeat 1000 a={$>*pi/500} point3d {cos(3*$a)},{sin(2*$a)},0 color3d[-1] ${-rgb} done add3d 19681point3d : 19682 e[^-1] "Input 3D point ($1,$2,$3)." 19683 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] 19684 19685#@cli pointcloud3d 19686#@cli : Convert selected planar or volumetric images to 3D point clouds. 19687#@cli : $ image.jpg luminance resize2dy 100 threshold 50% mul 255 pointcloud3d color3d[-1] 255,255,255 19688pointcloud3d : 19689 e[^-1] "Convert image$? to 3D point cloud." 19690 repeat $! l[$>] nm={0,n} 19691 s z repeat $! l[$>] 19692 +norm !=. 0 19693 i.. (1,{w};1,{w}^1,1;{h},{h}) r.. .,.,1,2,3 *[-2,-1] round. permute. cxyz 19694 l. s -,0 a y is_points=$! endl 19695 if $is_points 19696 -. 1 r. 2,{h/2},1,1,-1 permute. cyzx +warp.. .,0,0 rm... 19697 permute.. cyzx i.. 1,{h},1,1,$> a[-3,-2] x # Coordinates. 19698 i... ('CImg3d') i... ({h},{h}) # Header and size. 19699 i.. 1,{h},1,1,1 i.. 1,{h},1,1,y a[-3,-2] x # Primitives. 19700 permute. cyzx # Colors. 19701 if w==1 r. 3,{h},1,1 19702 elif w>3 i.. 4,{h},1,1,-128,1,1,{w} a[-2,-1] x 19703 else r. 3,{h},1,1,0 19704 fi 19705 1,{h},1,1,1 # Opacities. 19706 y[-6--1] a[-6--1] y 19707 else rm empty3d 19708 fi 19709 endl done 19710 +3d 19711 nm $nm endl done 19712 19713#@cli pose3d : p1,...,p12 19714#@cli : Apply 3D pose matrix to selected 3D objects. 19715#@cli : $ torus3d 100,20 pose3d 0.152437,1.20666,-0.546366,0,-0.535962,0.559129,1.08531,0,1.21132,0.0955431,\ 19716# 0.548966,0,0,0,-206,1 snapshot3d 400 19717pose3d : 19718 e[^-1] "Apply 3D pose matrix [ $1,$2,$3,$4; $5,$6,$7,$8; $9,$10,$11,$12 ] to 3D object$?." 19719 repeat $! l[$>] if ${-_is_3d} 19720 s3d r[2] 3,{2,h/3},1,1,-1 i[3] 1,{2,h},1,1,1 a[2,3] x 19721 i[3] ($1,$5,$9;$2,$6,$10;$3,$7,$11;$4,$8,$12) m*[2,3] 19722 r[2] 1,{2,3*h},1,1,-1 a y 19723 else error "Command '$0': Image ["{$!-$>-1}"] does not represent a 3D object." 19724 fi endl done 19725 19726#@cli p3d : eq. to 'primitives3d'. 19727p3d : check "isint($1) && $1>=0 && $1<=2" 19728 _primitives3d $* 19729 19730#@cli primitives3d : mode 19731#@cli : Convert primitives of selected 3D objects. 19732#@cli : (eq. to 'p3d').\n 19733#@cli : 'mode' can be { 0=points | 1=outlines | 2=non-textured }. 19734#@cli : $ sphere3d 30 primitives3d 1 torus3d 50,10 color3d[-1] ${-rgb} add3d 19735primitives3d : check "isint($1) && $1>=0 && $1<=2" 19736 _$0 $* 19737 19738_primitives3d : 19739 e[0--3] "Convert primitives of 3D object$? to "${"arg 1+$1,points,outlines,non-textured"}"." 19740 repeat $! l[$>] 19741 s3d 1,64 .x2 19742 eval " 19743 const mode = $1; 19744 19745 # Read a RGBA color from the current primitive material. 19746 get_RGBA(tx,ty,goto_next) = ( 19747 R = i[#4,pc]; 19748 R!=-128?( # RGB color 19749 G = i[#4,pc+1]; 19750 B = i[#4,pc+2]; 19751 goto_next?(pc+=3); 19752 ):( # Texture 19753 W = i[#4,pc+1]; H = i[#4,pc+2]; S = i[#4,pc+3]; WH = W*H; 19754 WH?( # Non-shared texture 19755 off = pc + (ty%H)*W + (tx%W) + 4; 19756 goto_next?(pc+=WH*S + 4); 19757 ):( # Shared texture 19758 off = pcol[W]; 19759 i[#4,off]==-128?( 19760 ++off; 19761 W = i[#4,off++]; H = i[#4,off++]; S = i[#4,off++]; WH = W*H; 19762 off += (ty%H)*W + (tx%W); 19763 ):(WH=1); 19764 goto_next?(pc+=4); 19765 ); 19766 R = i[#4,off]; 19767 S==1?(G = B = R):( 19768 G = i[#4,off + WH]; 19769 S==2?(B = 0):( 19770 B = i[#4,off + 2*WH]; 19771 ); 19772 ); 19773 ); 19774 19775 A = i[#5,po]; 19776 A!=-128?( # Scalar 19777 goto_next?(po+=1); 19778 ):( # Texture 19779 W = i[#5,po+1]; H = i[#5,po+2]; S = i[#5,po+3]; WH = W*H; 19780 WH?( # Non-shared texture 19781 off = po + (ty%H)*W + (tx%W) + 4; 19782 goto_next?(po+=WH*S + 4); 19783 ):( # Shared texture 19784 off = popa[W]; 19785 i[#5,off]==-128?( 19786 ++off; 19787 W = i[#5,off++]; H = i[#5,off++]; S = i[#5,off++]; WH = W*H; 19788 off += (ty%H)*W + (tx%W); 19789 ); 19790 goto_next?(po+=4); 19791 ); 19792 A = i[#5,off]; 19793 ); 19794 ); 19795 19796 # Copy material of current primitives 'nb' times. 19797 copy_material(nb) = ( 19798 R = i[#4,pc++]; G = i[#4,pc++]; B = i[#4,pc++]; 19799 R!=-128?( # RGB color 19800 unref(data); data = [ R,G,B ]; 19801 repeat (nb, copy(i[#-2,qc],data,3); qc+=3); 19802 ):( 19803 W = G; H = B; S = i[#4,pc++]; WHS = W*H*S; 19804 WHS?( # Non-shared texture 19805 qc + WHS + 4*nb>=h(#-2)?resize(#-2,1,int(1.5*qc + WHS + 4*nb),1,1,0,0); 19806 copy(i[#-2,qc],i[#4,pc-4],WHS+4); 19807 pc+=WHS; qc+=WHS+4; 19808 unref(data); data = [-128,nq,0,0]; 19809 for (k = 1, k<nb, ++k, copy(i[#-2,qc],data,4); qc+=4); 19810 ):( # Shared texture 19811 unref(data); data = [-128,pref[W],0,0]; 19812 repeat (nb, copy(i[#-2,qc],data,4); qc+=4); 19813 ); 19814 ); 19815 19816 A = i[#5,po++]; 19817 A!=-128?( # Opacity value 19818 repeat (nb, i[#-1,qo++] = A); 19819 ):( # Texture 19820 W = i[#5,po++]; H = i[#5,po++]; S = i[#5,po++]; WHS = W*H*S; 19821 WHS?( # Non-shared texture 19822 qo + WHS + 4*nb>=h(#-1)?resize(#-1,1,int(1.5*qo + WHS + 4*nb),1,1,0,0); 19823 copy(i[#-1,qo],i[#5,po-4],WHS+4); 19824 po+=WHS; qo+=WHS+4; 19825 unref(data); data = [-128,nq,0,0]; 19826 for (k = 1, k<nb, ++k, copy(i[#-1,qo],data,4); qo+=4); 19827 ):( # Shared texture 19828 unref(data); data = [ -128,pref[W],0,0 ]; 19829 repeat (nb, copy(i[#-1,qo],data,4); qo+=4); 19830 ); 19831 ); 19832 ); 19833 19834 # Add a new colored point primitive. 19835 add_point(ind,R,G,B,A) = ( 19836 copy(i[#-3,qp],[1,ind],2); qp+=2; 19837 copy(i[#-2,qc],[R,G,B],3); qc+=3; 19838 i[#-1,qo++] = A; 19839 ++nq; 19840 ); 19841 19842 # Add a new colored segment primitive. 19843 add_segment(ind0,ind1,R,G,B,A) = ( 19844 copy(i[#-3,qp],[2,ind0,ind1],3); qp+=3; 19845 copy(i[#-2,qc],[R,G,B],3); qc+=3; 19846 i[#-1,qo++] = A; 19847 ++nq; 19848 ); 19849 19850 pcol = popa = pref = vector"{i[#1,1]}"(); 19851 for (pp = pc = po = qp = qc = qo = np = nq = 0, pp<h#3, ++np, 19852 qp + 28>=h(#-3)?resize(#-3,1,int(1.5*qp + 28),1,1,0,0); 19853 qc + 16>=h(#-2)?resize(#-2,1,int(1.5*qc + 16),1,1,0,0); 19854 qo + 4>=h(#-1)?resize(#-1,1,int(1.5*qo + 4),1,1,0,0); 19855 N = i[#3,pp++]; 19856 pcol[np] = pc; 19857 popa[np] = po; 19858 pref[np] = nq; 19859 19860 N==1?( # Colored point 19861 v0 = i[#3,pp++]; 19862 get_RGBA(0,0,1); 19863 add_point(v0,R,G,B,A); 19864 19865 ):N==2?( # Colored segment 19866 v0 = i[#3,pp++]; v1 = i[#3,pp++]; 19867 get_RGBA(0,0,1); 19868 mode==0?( 19869 add_point(v0,R,G,B,A); 19870 add_point(v1,R,G,B,A); 19871 ):( 19872 add_segment(v0,v1,R,G,B,A); 19873 ); 19874 19875 ):N==3?( # Colored triangle 19876 v0 = i[#3,pp++]; v1 = i[#3,pp++]; v2 = i[#3,pp++]; 19877 get_RGBA(0,0,1); 19878 mode==0?( 19879 add_point(v0,R,G,B,A); 19880 add_point(v1,R,G,B,A); 19881 add_point(v2,R,G,B,A); 19882 ):mode==1?( 19883 add_segment(v0,v1,R,G,B,A); 19884 add_segment(v1,v2,R,G,B,A); 19885 add_segment(v2,v0,R,G,B,A); 19886 ):( 19887 copy(i[#-3,qp],i[#3,pp-4],4); qp+=4; 19888 copy(i[#-2,qc],i[#4,pc-3],3); qc+=3; 19889 i[#-1,qo++] = A; 19890 ++nq; 19891 ); 19892 19893 ):N==4?( # Colored quadrangle 19894 v0 = i[#3,pp++]; v1 = i[#3,pp++]; v2 = i[#3,pp++]; v3 = i[#3,pp++]; 19895 get_RGBA(0,0,1); 19896 mode==0?( 19897 add_point(v0,R,G,B,A); 19898 add_point(v1,R,G,B,A); 19899 add_point(v2,R,G,B,A); 19900 add_point(v3,R,G,B,A); 19901 ):mode==1?( 19902 add_segment(v0,v1,R,G,B,A); 19903 add_segment(v1,v2,R,G,B,A); 19904 add_segment(v2,v3,R,G,B,A); 19905 add_segment(v3,v0,R,G,B,A); 19906 ):( 19907 copy(i[#-3,qp],i[#3,pp-5],5); qp+=5; 19908 copy(i[#-2,qc],i[#4,pc-3],3); qc+=3; 19909 i[#-1,qo++] = A; 19910 ++nq; 19911 ); 19912 19913 ):N==5?( # Colored sphere 19914 v0 = i[#3,pp++]; v1 = i[#3,pp++]; i[#3,pp++] = (mode==1); v2 = i[#3,pp++]; v3 = i[#3,pp++]; 19915 get_RGBA(0,0,1); 19916 mode==0?( 19917 x0 = i[#2,3*v0]; y0 = i[#2,3*v0+1]; z0 = i[#2,3*v0+2]; 19918 x1 = i[#2,3*v1]; y1 = i[#2,3*v1+1]; z1 = i[#2,3*v1+2]; 19919 copy(i[#2,3*v0],([ x0,y0,z0 ] + [ x1,y1,z1 ])/2,3); 19920 add_point(v0,R,G,B,A); 19921 ):( 19922 copy(i[#-3,qp],i[#3,pp-6],6); qp+=6; 19923 copy(i[#-2,qc],i[#4,pc-3],3); qc+=3; 19924 i[#-1,qo++] = A; 19925 ++nq; 19926 ); 19927 19928 ):N==6?( # Textured segment 19929 v0 = i[#3,pp++]; v1 = i[#3,pp++]; 19930 tx0 = i[#3,pp++]; ty0 = i[#3,pp++]; tx1 = i[#3,pp++]; ty1 = i[#3,pp++]; 19931 mode==0?( 19932 get_RGBA(tx0,ty0,0); add_point(v0,R,G,B,A); 19933 get_RGBA(tx1,ty1,1); add_point(v1,R,G,B,A); 19934 ):mode==1?( 19935 copy(i[#-3,qp],i[#3,pp-7],7); qp+=7; 19936 copy_material(1); 19937 ++nq; 19938 ):( 19939 get_RGBA(tx0,ty0,0); R0 = R; G0 = G; B0 = B; A0 = A; 19940 get_RGBA(tx1,ty1,1); (R0+=R)/=2; (G0+=G)/=2; (B0+=B)/=2; (A0+=A)/=2; 19941 add_segment(v0,v1,R0,G0,B0,A0); 19942 ); 19943 19944 ):N==9?( # Textured triangle 19945 v0 = i[#3,pp++]; v1 = i[#3,pp++]; v2 = i[#3,pp++]; 19946 tx0 = i[#3,pp++]; ty0 = i[#3,pp++]; 19947 tx1 = i[#3,pp++]; ty1 = i[#3,pp++]; 19948 tx2 = i[#3,pp++]; ty2 = i[#3,pp++]; 19949 mode==0?( 19950 get_RGBA(tx0,ty0,0); add_point(v0,R,G,B,A); 19951 get_RGBA(tx1,ty1,0); add_point(v1,R,G,B,A); 19952 get_RGBA(tx2,ty2,1); add_point(v2,R,G,B,A); 19953 ):mode==1?( 19954 copy(i[#-3,qp],[ 6,v0,v1,tx0,ty0,tx1,ty1, 19955 6,v1,v2,tx1,ty1,tx2,ty2, 19956 6,v2,v0,tx2,ty2,tx0,ty0 ],21); qp+=21; 19957 copy_material(3); 19958 nq+=3; 19959 ):( 19960 get_RGBA(tx0,ty0,0); R0 = R; G0 = G; B0 = B; A0 = A; 19961 get_RGBA(tx1,ty1,0); R0+=R; G0+=G; B0+=B; A0+=A; 19962 get_RGBA(tx2,ty2,2); (R0+=R)/=3; (G0+=G)/=3; (B0+=B)/=3; (A0+=A)/=3; 19963 copy(i[#-3,qp],[ 3,v0,v1,v2 ],4); qp+=4; 19964 copy(i[#-2,qc],[ R,G,B ],3); qc+=3; 19965 i[#-1,qo++] = A; 19966 ++nq; 19967 ); 19968 19969 ):N==12?( # Textured quadrangle 19970 v0 = i[#3,pp++]; v1 = i[#3,pp++]; v2 = i[#3,pp++]; v3 = i[#3,pp++]; 19971 tx0 = i[#3,pp++]; ty0 = i[#3,pp++]; 19972 tx1 = i[#3,pp++]; ty1 = i[#3,pp++]; 19973 tx2 = i[#3,pp++]; ty2 = i[#3,pp++]; 19974 tx3 = i[#3,pp++]; ty3 = i[#3,pp++]; 19975 mode==0?( 19976 get_RGBA(tx0,ty0,0); add_point(v0,R,G,B,A); 19977 get_RGBA(tx1,ty1,0); add_point(v1,R,G,B,A); 19978 get_RGBA(tx2,ty2,0); add_point(v2,R,G,B,A); 19979 get_RGBA(tx3,ty3,1); add_point(v3,R,G,B,A); 19980 ):mode==1?( 19981 copy(i[#-3,qp],[ 6,v0,v1,tx0,ty0,tx1,ty1, 19982 6,v1,v2,tx1,ty1,tx2,ty2, 19983 6,v2,v3,tx2,ty2,tx3,ty3, 19984 6,v3,v0,tx3,ty3,tx0,ty0 ],28); qp+=28; 19985 copy_material(4); 19986 nq+=4; 19987 ):( 19988 get_RGBA(tx0,ty0,0); R0 = R; G0 = G; B0 = B; A0 = A; 19989 get_RGBA(tx1,ty1,0); R0+=R; G0+=G; B0+=B; A0+=A; 19990 get_RGBA(tx2,ty2,0); R0+=R; G0+=G; B0+=B; A0+=A; 19991 get_RGBA(tx3,ty3,2); (R0+=R)/=4; (G0+=G)/=4; (B0+=B)/=4; (A0+=A)/=4; 19992 copy(i[#-3,qp],[ 4,v0,v1,v2,v3 ],5); qp+=5; 19993 copy(i[#-2,qc],[ R,G,B ],3); qc+=3; 19994 i[#-1,qo++] = A; 19995 ++nq; 19996 ); 19997 ); 19998 ); 19999 resize(#-3,1,qp,1,1,0,0); 20000 resize(#-2,1,qc,1,1,0,0); 20001 resize(#-1,1,qo,1,1,0,0); 20002 i[#1,1] = nq" 20003 20004 rm[3-5] a y 20005 endl done 20006 20007#@cli projections3d : _x[%],_y[%],_z[%],_is_bounding_box={ 0 | 1 } 20008#@cli : Generate 3D xy,xz,yz projection planes from specified volumetric images. 20009projections3d : skip ${1=50%},${2=50%},${3=50%},${4=1} 20010 e[^-1] "Generate 3D xy,xz,yz projection planes from image$?." 20011 n 0,255 repeat $! l[$>] 20012 w={w} h={h} d={d} 20013 x={if(${is_percent\ $1},$1*w,$1)} 20014 y={if(${is_percent\ $2},$2*h,$2)} 20015 z={if(${is_percent\ $3},$3*d,$3)} 20016 +rows $2,$2 r. {w},{d},1,100%,-1 20017 +columns.. $1,$1 permute. zyxc 20018 slices... $3,$3 r[-3--1] 100%,100%,1,3 20019 imageplane3d[-3--1] 20020 r3d. 0,1,0,-90 r3d.. 1,0,0,90 20021 +3d... 0,0,$z +3d.. 0,$y,0 +3d. $x,0,0 20022 +3d[-3--1] o3d. 0.8 20023 if $4 box3d $w,$h,$d p3d. 1 o3d. 0.4 +3d[-2,-1] fi 20024 endl done 20025 20026#@cli pyramid3d : width,height 20027#@cli : Input 3D pyramid at (0,0,0), with specified geometry. 20028#@cli : $ pyramid3d 100,-100 +primitives3d 1 color3d[-2] ${-rgb} 20029pyramid3d : 20030 e[^-1] "Input new 3D pyramid, with width $1 and height $2." 20031 (67.5;73.5;109.5;103.5;51.5;100.5;\ # Magick number for CImg3d. 20032 5;5;\ # Number of vertices and primitives. 20033 {-$1/2};{-$1/2};{-$2/2};\ # Vertex coordinates. 20034 {$1/2};{-$1/2};{-$2/2};\ 20035 {$1/2};{$1/2};{-$2/2};\ 20036 {-$1/2};{$1/2};{-$2/2};\ 20037 0;0;{$2/2};\ 20038 4;0;3;2;1;\ # Primitives description. 20039 3;0;4;3;\ 20040 3;1;4;0;\ 20041 3;2;4;1;\ 20042 3;3;4;2) 20043 1,15,1,1,200 1,5,1,1,1 a[-3--1] y nm. [3D\ pyramid] 20044 20045#@cli quadrangle3d : x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3 20046#@cli : Input 3D quadrangle at specified coordinates. 20047#@cli : $ quadrangle3d -10,-10,10,10,-10,10,10,10,10,-10,10,10 repeat 10 +rotate3d[-1] 0,1,0,30 \ 20048# color3d[-1] ${-rgb},0.6 done add3d mode3d 2 20049quadrangle3d : 20050 e[^-1] "Input 3D quadrangle ($1,$2,$3)-($4,$5,$6)-($7,$8,$9)-($10,$11,$12)." 20051 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] 20052 20053#@cli random3d : nb_points>=0 20054#@cli : Input random 3D point cloud in [0,1]^3. 20055#@cli : $ random3d 100 circles3d 0.1 opacity3d 0.5 20056random3d : check "$1>=0" 20057 e[^-1] "Input random 3D point cloud, with $1 points." 20058 if $1<0.5 empty3d 20059 else l[] 20060 N={round($1)} 20061 ({'CImg3d'},$N,$N) 20062 3,$N rand. 0,1 20063 1,$N,1,1,1 1,$N,1,1,y a[-2,-1] x 20064 3,$N,1,1,200 1,$N,1,1,1 20065 y a y 20066 endl fi 20067 nm. [3D\ random\ pointcloud] 20068 20069#@cli rv3d : eq. to 'reverse3d'. : (+) 20070 20071#@cli reverse3d : (+) 20072#@cli : Reverse primitive orientations of selected 3D objects. 20073#@cli : (eq. to 'rv3d'). 20074#@cli : $ torus3d 100,40 double3d 0 +reverse3d 20075 20076#@cli r3d : eq. to 'rotate3d'. : (+) 20077 20078#@cli rotate3d : u,v,w,angle : (+) 20079#@cli : Rotate selected 3D objects around specified axis with specified angle (in deg.). 20080#@cli : (eq. to 'r3d'). 20081#@cli : $ torus3d 100,10 double3d 0 repeat 7 +rotate3d[-1] 1,0,0,20 done add3d 20082 20083#@cli rotation3d : u,v,w,angle 20084#@cli : Input 3x3 rotation matrix with specified axis and angle (in deg). 20085#@cli : $ rotation3d 1,0,0,0 rotation3d 1,0,0,90 rotation3d 1,0,0,180 20086rotation3d : 20087 e[^-1] "Input 3D rotation matrix around axis ($1,$2,$3) with angle $4 deg." 20088 3,3,1,1,{"rot(${1-4}°)"} nm. [3D\ rotation] 20089 20090#@cli sierpinski3d : _recursion_level>=0,_width,_height 20091#@cli : Input 3d Sierpinski pyramid. 20092#@cli : $ sierpinski3d 3,100,-100 +primitives3d 1 color3d[-2] ${-rgb} 20093sierpinski3d : check ${1=4}>=0 skip ${2=1},${3=1} 20094-e[^-1] "Input 3D Sierpinski pyramid of degree $1, with width $2 and height $3." 20095 l[] 20096 _sierpinski3d {-$2/2},{-$2/2},{-$3/2},{$2/2},{-$2/2},{-$3/2},\ 20097 {$2/2},{$2/2},{-$3/2},{-$2/2},{$2/2},{-$3/2},\ 20098 0,0,{$3/2},$1 20099 +3d endl 20100 nm. [3D\ sierpinski] 20101 20102_sierpinski3d : 20103 if $16<=0 20104 (67.5;73.5;109.5;103.5;51.5;100.5;\ 20105 5;5;\ 20106 $1;$2;$3;\ 20107 $4;$5;$6;\ 20108 $7;$8;$9;\ 20109 $10;$11;$12;\ 20110 $13;$14;$15;\ 20111 4;0;3;2;1;\ 20112 3;0;4;3;\ 20113 3;1;4;0;\ 20114 3;2;4;1;\ 20115 3;3;4;2) 20116 1,15,1,1,200 1,5,1,1,1 a[-3--1] y 20117 return fi 20118 _sierpinski3d $1,$2,$3,\ 20119 {($1+$4)/2},{($2+$5)/2},{($3+$6)/2},\ 20120 {($1+$4+$7+$10)/4},{($2+$5+$8+$11)/4},{($3+$6+$9+$12)/4},\ 20121 {($1+$10)/2},{($2+$11)/2},{($3+$12)/2},\ 20122 {($1+$13)/2},{($2+$14)/2},{($3+$15)/2},\ 20123 {$16-1} 20124 _sierpinski3d {($1+$4)/2},{($2+$5)/2},{($3+$6)/2},\ 20125 $4,$5,$6,\ 20126 {($4+$7)/2},{($5+$8)/2},{($6+$9)/2},\ 20127 {($1+$4+$7+$10)/4},{($2+$5+$8+$11)/4},{($3+$6+$9+$12)/4},\ 20128 {($4+$13)/2},{($5+$14)/2},{($6+$15)/2},\ 20129 {$16-1} 20130 _sierpinski3d {($1+$4+$7+$10)/4},{($2+$5+$8+$11)/4},{($3+$6+$9+$12)/4},\ 20131 {($4+$7)/2},{($5+$8)/2},{($6+$9)/2},\ 20132 $7,$8,$9,\ 20133 {($7+$10)/2},{($8+$11)/2},{($9+$12)/2},\ 20134 {($7+$13)/2},{($8+$14)/2},{($9+$15)/2},\ 20135 {$16-1} 20136 _sierpinski3d {($1+$10)/2},{($2+$11)/2},{($3+$12)/2},\ 20137 {($1+$4+$7+$10)/4},{($2+$5+$8+$11)/4},{($3+$6+$9+$12)/4},\ 20138 {($7+$10)/2},{($8+$11)/2},{($9+$12)/2},\ 20139 $10,$11,$12,\ 20140 {($10+$13)/2},{($11+$14)/2},{($12+$15)/2},\ 20141 {$16-1} 20142 _sierpinski3d {($1+$13)/2},{($2+$14)/2},{($3+$15)/2},\ 20143 {($4+$13)/2},{($5+$14)/2},{($6+$15)/2},\ 20144 {($7+$13)/2},{($8+$14)/2},{($9+$15)/2},\ 20145 {($10+$13)/2},{($11+$14)/2},{($12+$15)/2},\ 20146 $13,$14,$15,\ 20147 {$16-1} 20148 20149#@cli size3d 20150#@cli : Return bounding box size of the last selected 3D object. 20151size3d : 20152 +rows. 8,{8+3*i[6]} r. 3,{h/3},1,1,-1 s. x,3 20153 u {-3,iM-im},{-2,iM-im},{iM-im} 20154 rm[-3--1] 20155 20156#@cli skeleton3d : _metric,_frame_type={ 0=squares | 1=diamonds | 2=circles | 3=auto },_skeleton_opacity,\ 20157# _frame_opacity,_is_frame_wireframe={ 0 | 1 } 20158#@cli : Build 3D skeletal structure object from 2d binary shapes located in selected images. 20159#@cli : 'metric' can be { 0=chebyshev | 1=manhattan | 2=euclidean }. 20160#@cli : Default values: 'metric=2', 'bones_type=3', 'skeleton_opacity=1' and 'frame_opacity=0.1'. 20161#@cli : $ shape_cupid 480 +skeleton3d , 20162skeleton3d : check "isint(${1=2}) && $1>=0 && $1<=2 && isint(${2=3}) && $2>=0 && $2<=3" skip ${3=1},${4=0.1},${5=1} 20163 e[^-1] "Build 3D skeletal structure object from image$?, with "${arg\ 1+$1,chebyshev,manhattan,euclidean}" metric, "\ 20164 ${arg\ 1+$2,squares,diamonds,circles,auto}" bones, skeleton opacity $3 and frame opacity $4 ." 20165 repeat $! l[$>] channels 0 20166 20167 # Construct skeleton representation. 20168 +distance 0,$1 20169 +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))" 20170 if $3 +slices. -1,0 isosurface3d. 0.5 o3d. $3 col3d. 255,0,0 fi 20171 *[0-2] pointcloud3d[0] 20172 20173 # Construct bones from skeleton. 20174 if $4 l[0] s3d 0 20175 n={1,@0} 20176 if $n 20177 r[2] 3,$n,1,1,-1 r[3] 2,$n,1,1,-1 r[4] 3,$n,1,1,-1 20178 20179 if $2==0" || "($2==3" && "$1==0) # Frame with squares. 20180 =[1] {4*$n} 20181 i[3] [2]x3 +z.. 0,1 z. 0,2 -[2] . +[4] . 20182 s. x *.. -1 a[-3--1] x +[3] . -[5,-1] a[2-5] x 20183 rm[3] 1,$n,1,1,4 +f. 4*y ++. 1 ++. 1 ++. 1 rv[-3,-1] a[-5--1] x mv. 3 20184 20185 elif $2==1" || "($2==3" && "$1==1) # Frame with diamonds. 20186 =[1] {4*$n} 20187 i[3] [2]x3 +z.. 0,0 z. 0,2 -[2] . +[4] . 20188 shift. 1,0 -[3] . +[5,-1] a[2-5] x 20189 rm[3] 1,$n,1,1,4 +f. 4*y ++. 1 ++. 1 ++. 1 rv[-3,-1] a[-5--1] x mv. 3 20190 20191 elif $2==2" || "($2==3" && "$1==2) # Frame with circles. 20192 =[1] {2*$n} 20193 +z[4] 0,0 z. 0,2 ++[2,-1] -[2,-2] a[2,-1] x 20194 rm[3] 1,$n,1,1,5 +f. 2*y ++. 1 3,100% a[-4--1] x mv. 3 20195 fi 20196 y a y o3d $4 if $5 p3d 1 fi col3d 200 20197 else rm empty3d fi 20198 endl else rm[0] fi 20199 +3d 20200 endl done 20201 20202#@cli snapshot3d : _size>0,_zoom>=0,_backgroundR,_backgroundG,_backgroundB,_backgroundA : [background_image],zoom>=0 20203#@cli : Take 2d snapshots of selected 3D objects. 20204#@cli : Set 'zoom' to 0 to disable object auto-scaling. 20205#@cli : Default values: 'size=512', 'zoom=1' and '[background_image]=(default)'. 20206#@cli : $ torus3d 100,20 rotate3d 1,1,0,60 snapshot3d 400,1.2,128,64,32 20207#@cli : $ torus3d 100,20 rotate3d 1,1,0,60 sample ? +snapshot3d[0] [1],1.2 20208snapshot3d : check "${2=1}>=0" skip ${1=512},${3=""} 20209 if ${"is_image_arg $1"} # Background image specified. 20210 e[0--3] "Take $1x$1 snapshot$? of 3D object$?, with zoom factor $2 and background image $3." 20211 pass$1 0 to_color. 20212 elif isnum($3) # Background color specified. 20213 e[0--3] "Take $1x$1 snapshot$? of 3D object$?, with zoom factor $2 and background color ${3--1}." 20214 (${3--1}) y. c r. $1,$1 to_color. 20215 else # Default background color. 20216 e[0--3] "Take $1x$1 snapshot$? of 3D object$?, with zoom factor $2 and default background." 20217 1,2,1,3,32,64,32,116,64,96 r. $1,$1,1,3,3 20218 fi 20219 repeat $!-1 . l[$>,-1] 20220 if $2!=0 c3d[0] n3d[0] *3d[0] {3*min(w,h)*$2/4} fi 20221 if s>3 # RGBA rendering. 20222 100%,100%,1,3,-1 j3d. [0],50%,50%,0,1 20223 to_rgba. replace_color. 0,0,-1,-1,-1,255,0,0,0,0 blend[-2,-1] alpha 20224 else # RGB rendering. 20225 j3d[1] [0],50%,50%,0,1 20226 fi 20227 nm[1] {-2,n} rm[0] 20228 endl done rm. 20229 20230#@cli sl3d : eq. to 'specl3d'. : (+) 20231 20232#@cli specl3d : value>=0 : (+) 20233#@cli : Set lightness of 3D specular light. 20234#@cli : (eq. to 'sl3d'). 20235#@cli : Default value: 'value=0.15'. 20236#@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,@$>} \ 20237# snapshot3d[-1] 400 done remove[0] 20238 20239#@cli ss3d : eq. to 'specs3d'. : (+) 20240 20241#@cli specs3d : value>=0 : (+) 20242#@cli : Set shininess of 3D specular light. 20243#@cli : (eq. to 'ss3d'). 20244#@cli : Default value: 'value=0.8'. 20245#@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,@$>} \ 20246# snapshot3d[-1] 400 done remove[0] 20247 20248#@cli sphere3d : radius,_nb_recursions>=0 : (+) 20249#@cli : Input 3D sphere at (0,0,0), with specified geometry. 20250#@cli : Default value: 'nb_recursions=3'. 20251#@cli : $ sphere3d 100 +primitives3d 1 color3d[-2] ${-rgb} 20252 20253#@cli spherical3d : _nb_azimuth>=3,_nb_zenith>=3,_radius_function(phi,theta) 20254#@cli : Input 3D spherical object at (0,0,0), with specified geometry. 20255#@cli : Default values: 'nb_zenith=nb_azimut=64' and 'radius_function="abs(1+0.5*cos(3*phi)*sin(4*theta))"'. 20256#@cli : $ spherical3d 64 +primitives3d 1 20257spherical3d : check "${1=64}>=3 && ${2=$1}>=3" skip "${3=abs(1+0.5*cos(3*phi)*sin(4*theta))}" 20258 e[^-1] "Input 3D spherical object, with subdivisions ($1,$2) and height function '$3'." 20259 ('CImg3d':y) # Magic number. 20260 n1={round($1)} n2={round($2)} 20261 20262 # Define 3D vertices. 20263 $n1,{$n2-1},1,3,"phi = 2*pi*(x+0.5)/w;\ 20264 theta = -pi/2+pi*(y+0.5)/h;\ 20265 cp = cos(phi);\ 20266 sp = sin(phi);\ 20267 ct = cos(theta);\ 20268 ($3)*if(c==0,ct*cp,if(c==1,ct*sp,sin(theta)))" 20269 r. {w*h},3,1,1,-1 permute. yxzc 20270 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. 20271 nbv={h} y. 20272 20273 # Define 3D primitives. 20274 $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")))" 20275 r. {w*h},4,1,1,-1 permute. yxzc i.. 1,{h},1,1,4 a[-2,-1] x 20276 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. 20277 +[-5,-4] 2 rv[-5,-4] +[-2,-1] {$nbv-$n1} a[-3--1] x a[-4--2] x 20278 nbp={h+{-2,h}+{-3,h}} 20279 y[-3--1] a[-3--1] y 20280 20281 # Define other object information (properties, colors and opacities). 20282 i... ($nbv;$nbp) 20283 1,{3*$nbp},1,1,200 1,$nbp,1,1,1 a[-2,-1] y 20284 20285 # Append as a 3D object. 20286 a[-5--1] y nm. "[3D spherical surface '$3']" 20287 20288#@cli spline3d : x0[%],y0[%],z0[%],u0[%],v0[%],w0[%],x1[%],y1[%],z1[%],u1[%],v1[%],w1[%],_nb_vertices>=2 20289#@cli : Input 3D spline with specified geometry. 20290#@cli : Default values: 'nb_vertices=128'. 20291#@cli : $ repeat 100 spline3d {u},{u},{u},{u},{u},{u},{u},{u},{u},{u},{u},{u},128 color3d[-1] ${-rgb} done \ 20292# box3d 1 primitives3d[-1] 1 add3d 20293spline3d : check ${13=128}>=2 20294 e[^-1] "Input new 3D spline from (${1-3}) [${4-6}] to (${7-9}) [${10-12}] with $13 vertices." 20295 ('CImg3d') +. 0.5 # Header. 20296 ($13;{$13-1}) # Nb vertices / primitives. 20297 # Define vertices. 20298 1,$13,1,1,1 (0;1) r. 1,$13,1,1,3 +sqr. +*[-2,-1] a[-4--1] x 20299 +*. '$2,$5,{3*(($8)-($2))-2*($5)-($11)},{($5)+($11)+2*(($2)-($8))}' l. s x + endl 20300 +*.. '$3,$6,{3*(($9)-($3))-2*($6)-($12)},{($6)+($12)+2*(($3)-($9))}' l. s x + endl 20301 *... '$1,$4,{3*(($7)-($1))-2*($4)-($10)},{($4)+($10)+2*(($1)-($7))}' l... s x + endl 20302 a[-3--1] x 20303 1,{$13-1},1,1,2 (0,1;{$13-2},{$13-1}) r. 2,..,1,1,3 round. a[-2,-1] x # Primitives. 20304 1,{3*($13-1)},1,1,200 1,{$13-1},1,1,1 # Colors / opacities. 20305 y[-3,-4,-6] a[-6--1] y 20306 20307#@cli s3d : eq. to 'split3d'. : (+) 20308 20309#@cli split3d : _full_split={ 0 | 1 } : (+) 20310#@cli : Split selected 3D objects into feature vectors : 20311#@cli : * If 'full_split==0', { header, sizes, vertices, primitives, colors, opacities }. 20312#@cli : * If 'full_split==1', { header, sizes, vertices, p0,...,pP, c0,...,cP, o0,...,oP }. 20313#@cli : (eq. to 's3d').\n 20314#@cli : To recreate the 3D object, append all produced images along the y-axis. 20315#@cli : Default value: 'full_split=0'. 20316#@cli : $ box3d 100 +split3d 20317 20318#@cli sprite3d 20319#@cli : Convert selected images as 3D sprites. 20320#@cli : Selected images with alpha channels are managed. 20321#@cli : $ image.jpg sprite3d 20322sprite3d : 20323 e[^-1] "Convert image$? as 3D sprites." 20324 repeat $! l[$>] nm={0,n} 20325 split_opacity 20326 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] 20327 if $!==2 (1) a y 20328 else /. 255 i.. (-128;{w};{h};{s}) y. 20329 fi 20330 a y 20331 nm $nm endl done 20332 20333#@cli sprites3d : [sprite],_sprite_has_alpha_channel={ 0 | 1 } 20334#@cli : Convert selected 3D objects as a sprite cloud. 20335#@cli : Set 'sprite_has_alpha_channel' to 1 to make the last channel of the selected sprite be a transparency mask. 20336#@cli : Default value: 'mask_has_alpha_channel=0'. 20337#@cli : $ torus3d 100,20 image.jpg resize2dy[-1] 64 100%,100% gaussian[-1] 30%,30% *[-1] 255 append[-2,-1] c \ 20338# +sprites3d[0] [1],1 display_rgba[-2] 20339sprites3d : check ${is_image_arg\ $1} skip ${2=0} 20340 e[^-1] "Convert image$? as 3D sprites clouds, using sprite $1 ("${"arg {1+!$2},with,without"}" alpha-channel)." 20341 repeat $! 20342 if !{$>,i(0,7)} continue fi # Do nothing if 3D object is empty. 20343 pass$1 0 20344 if !w empty3d rv[$>,-1] nm[$>] {n} rm. continue fi 20345 l[$>,-1] 20346 s3d[0] N={1,@0} =[1] $N,0,1 20347 rm[3-5] i[3] (1,0;1,{$N-1}) r[3] 2,$N,1,1,3 round[3] 20348 if $2 # With alpha-channel. 20349 if s==1 # Only alpha-channel. 20350 i.. 3,$N,1,1,200 /. 255 20351 i.. (-128;{w};{h};1) 20352 if $N>1 1,{4*($N-1)},1,1,-128,0,0,0 fi 20353 else # Image + alpha. 20354 s. c,-{s-1} /. 255 20355 i... (-128;{w};{h};{-2,s}) 20356 if $N>1 i.. 1,{4*($N-1)},1,1,-128,0,0,0 fi 20357 i.. (-128;{w};{h};1) 20358 if $N>1 1,{4*($N-1)},1,1,-128,0,0,0 fi 20359 fi 20360 else # Without alpha-channel. 20361 i.. (-128;{w};{h};{s}) y[-3,-1] 20362 if $N>1 1,{4*($N-1)},1,1,-128,0,0,0 fi 20363 1,$N,1,1,1 20364 fi 20365 y a y 20366 endl done 20367 20368#@cli star3d : _nb_branches>0,0<=_thickness<=1 20369#@cli : Input 3D star at position `(0,0,0)`, with specified geometry. 20370#@cli : Default values: 'nb_branches=5' and 'thickness=0.38'. 20371#@cli : $ star3d , +primitives3d 1 color3d[-2] ${-rgb} 20372star3d : check "${1=5}>0 && ${2=0.38}>=0 && $2<=1" 20373 e[^-1] "Input 3D star, with $1 branches and thickness $2." 20374 N={2*$1} ('CImg3d') +. 0.5 ({$N+1};$N) 20375 ({-pi/2};{3*pi/2}) r. 1,{$N+1},1,1,3 rows. 0,{h-2} +sin. cos.. a[-2,-1] x 20376 (1,1;$2,$2) *[-2,-1] z. 0,2 r. 3,{h+1},1,1,0 20377 (3,$N,1,0;3,$N,$N,{$N-1}) r. 4,$N,1,1,3 round. =. 0,2,100% 20378 3,$N,1,1,200 1,$N,1,1,1 y[-6,-4--2] a[-6--1] y nm. [3D\ star] 20379 20380#@cli streamline3d : x[%],y[%],z[%],_L>=0,_dl>0,_interpolation,_is_backward={ 0 | 1 },_is_oriented={ 0 | 1 } : \ 20381# 'formula',x,y,z,_L>=0,_dl>0,_interpolation,_is_backward={ 0 | 1 },_is_oriented={ 0 | 1 } : (+) 20382#@cli : Extract 3D streamlines from selected vector fields or from specified formula. 20383#@cli : 'interpolation' can be { 0=nearest integer | 1=1st-order | 2=2nd-order | 3=4th-order }. 20384#@cli : Default values: 'dl=0.1', 'interpolation=2', 'is_backward=0' and 'is_oriented=0'. 20385#@cli : $ 100,100,100,3 rand -10,10 blur 3 repeat 300 +streamline3d[0] {u(100)},{u(100)},{u(100)},1000,1,1 \ 20386# color3d[-1] ${-rgb} done remove[0] box3d 100 primitives3d[-1] 1 add3d 20387 20388#@cli -3d : eq. to 'sub3d'. : (+) 20389 20390#@cli sub3d : tx,_ty,_tz : (+) 20391#@cli : Shift selected 3D objects with the opposite of specified displacement vector. 20392#@cli : (eq. to '3d'). 20393#@cli : Default values: 'ty=tz=0'. 20394#@cli : $ sphere3d 10 repeat 5 +sub3d[-1] 10,{u(-10,10)},0 color3d[-1] ${-rgb} done add3d 20395 20396#@cli superformula3d : resolution>1,m>=1,n1,n2,n3 20397#@cli : Input 2D superformula curve as a 3D object. 20398#@cli : Default values: 'resolution=1024', 'm=8', 'n1=1', 'n2=5' and 'n3=8'. 20399#@cli : $ superformula3d , 20400superformula3d : check "${1=1024}>1 && ${2=8}>=1" skip ${3=1},${4=5},${5=8} 20401 e[^-1] "Input 2D superformula curve, with resolution $1, m=$2 and (n1,n2,n3)=($3,$4,$5)." 20402 res={round($1)} 20403 20404 # Define object header and vertices. 20405 (67.5;73.5;109.5;103.5;51.5;100.5;$res;{$res-1}) 20406 (0,{2*pi}) r. $res,1,1,1,3 . 20407 20408 *. {$2/4} +sin. cos.. abs[-2,-1] 20409 ^.. $4 ^. $5 +[-2,-1] ^. {-1/$3} 20410 +sin.. cos... *. .. *[-3,-2] n[-2,-1] -1,1 20411 a[-2,-1] y rows. 0,2 transpose. r. 1,{w*h},1,1,-1 20412 20413 # Define object primitives, colors and opacities. 20414 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 20415 1,{3*($res-1)},1,1,200 1,{$res-1},1,1,1 a[-5--1] y nm. [3D\ superformula] 20416 20417#@cli tensors3d : _radius_factor>=0,_shape={ 0=box | >=N=ellipsoid },_radius_min>=0 20418#@cli : Generate 3D tensor fields from selected images. 20419#@cli : when 'shape'>0, it gives the ellipsoid shape precision. 20420#@cli : Default values: 'radius_factor=1', 'shape=2' and 'radius_min=0.05'. 20421#@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 20422tensors3d : check "${1=1}>=0 && isint(${2=2}) && $2>=0 && ${3=0.05}>=0" 20423 e[^-1] "Generate 3D tensor field(s) from image$?, with radius factor $1, "\ 20424 ${"if $2 u ellipsoid else u box fi"}" shape and radius min $3." 20425 repeat $! l[$>] 20426 20427 # Check input image format. 20428 if s==1 100%,100%,100%,6,"[i#0,0,0,i#0,0,i#0]" k. 20429 elif s==3 100%,100%,100%,6,"[R#0,G#0,0,B#0,0,0]" k. 20430 elif s==4 100%,100%,100%,6,"[R#0,G#0,0,A#0,0,0]" k. 20431 elif s==9 100%,100%,100%,6,"I=I#0;[I[0],I[1],I[2],I[4],I[5],I[8]]" k. 20432 fi 20433 if s!=6 error[0--4] "Command '$0': Image '"{n}"' has an invalid size (spectrum="{s}")." fi 20434 20435 # Estimate eigenvalues/eigenvectors. 20436 100%,100%,100%,12," 20437 T = I(#0); 20438 M = [ T[0], T[1], T[2], T[1], T[3], T[4], T[2], T[4], T[5] ]; 20439 eig = eig(M); 20440 if (det(eig[3,9])<0, eig[3]*=-1; eig[4]*=-1; eig[5]*=-1); 20441 eig[0] = max(0,eig[0]); 20442 eig[1] = max(0,eig[1]); 20443 eig[2] = max(0,eig[2]); 20444 eig" 20445 k. 20446 20447 # Create 3D object. 20448 if $2 sphere3d 1,{$2-1} else box3d 1 fi 20449 N,P={[i[6],i[7]]} siz={h} n3d. c3d. .x{0,whd-1} 20450 f[0] " 20451 const N = "$N"; 20452 const P = "$P"; 20453 const siz = "$siz"; 20454 eig = I; 20455 const d = size(eig); 20456 ind = 1 + x + w*y + wh*z; 20457 L = eig[0,3]; 20458 if (max(L)==0, # Empty tensor -> do not display 20459 i[#ind,6] = i[#ind,7] = 0; 20460 resize(#ind,1,8,1,1,0); 20461 _(else), 20462 L*=$1; 20463 L[0] = max($3,L[0]); 20464 L[1] = max($3,L[1]); 20465 L[2] = max($3,L[2]); 20466 R = eig[3,9]; 20467 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))); 20468 20469 ref(crop(#ind,0,8,0,0,1,3*N,1,1),pts); 20470 pts *= resize(L,size(pts),0,2); 20471 pts = mul(pts,R,3); 20472 pts += resize([x,y,z],size(pts),0,2); 20473 draw(#ind,pts,0,8,0,0,1,size(pts),1,1); 20474 20475 col0 = cut(255*anisotropy*abs([ R[0],R[1],R[2] ]) + (1 - anisotropy)*200,0,255); 20476 col = resize(col0,3*P,0,2); 20477 const off = siz - 4*P; 20478 draw(#ind,col,0,off,0,0,1,size(col),1,1); 20479 0); I" 20480 rm[0] +3d 20481 endl done 20482 20483#@cli text_pointcloud3d : _"text1",_"text2",_smoothness 20484#@cli : Input 3D text pointcloud from the two specified strings. 20485#@cli : Default values: 'text1="text1"', 'text2="text2"' and 'smoothness=1'. 20486#@cli : $ text_pointcloud3d "G'MIC","Rocks!" 20487text_pointcloud3d : skip "${1=text1}","${2=text2}",${3=1} 20488 e[^-1] "Input 3D pointcloud text object from strings '$1' and '$2', with smoothness $3." 20489 0 t. "$1",0,0,53,1,1 20490 0 t. "$2",0,0,53,1,1 mirror. y 20491 autocrop[-2,-1] 0 20492 expand_xy[-2,-1] 2,0 dilate[-2,-1] 2 20493 permute. zyxc r[-2,-1] ${-max_whd} &[-2,-1] 20494 20495 100%,100% rand. 0,{{-2,d}-1} round. ri. .. f. 'if(z==i,1,0)' 20496 distance. 1 +. 1 +f. 1 rv[-2,-1] /[-2,-1] *. .. 20497 +dilate. 0,0,{d} ==[-2,-1] *. .. 20498 20499 1,100%,100% rand. 0,{{-2,w}-1} round. ri. .. f. 'if(x==i,1,0)' 20500 distance. 1 +. 1 +f. 1 rv[-2,-1] /[-2,-1] *. ... 20501 +dilate. 0,0,{d} ==[-2,-1] *[-3,-1] 20502 20503 -|[-2,-1] 20504 20505 b. $3 isosurface3d. 25% 20506 c3d. n3d. nm. "[3D text pointcloud]" 20507 20508#@cli text3d : text,_font_height>0,_depth>0,_smoothness 20509#@cli : Input a 3D text object from specified text. 20510#@cli : Default values: 'font_height=53', 'depth=10' and 'smoothness=1.5'. 20511#@cli : $ text3d "G'MIC as a\n3D logo!" 20512text3d : skip ${2=53},${3=10},${4=1.5} 20513 e[^-1] "Input 3D text object '$1' with size $2, depth $3 and smoothness $4." 20514 0 t. "$1",0,0,$2,1,1 autocrop. 0 r. 100%,100%,$3 expand_xyz. 10,0 20515 b. $4 isosurface3d. 40% rv3d. nm. "[3D text '$1']" 20516 20517#@cli t3d : eq. to 'texturize3d'. 20518t3d : check ${"is_image_arg $1"}" && (!narg(${2=}) || "${"is_image_arg $2"}")" 20519 e[^-1] "Texturize 3D object$? with texture $1"\ 20520 ${"if narg($2) u \" and texture coordinates $2\" else u \"\" fi"}"." 20521 pass$1 0 slices. 0 if s==1 to_rgb. else channels. 0,2 fi 20522 if narg($2) pass$2 else 0 fi 20523 v + _texturize3d 20524 20525#@cli texturize3d : [ind_texture],_[ind_coords] 20526#@cli : Texturize selected 3D objects with specified texture and coordinates. 20527#@cli : (eq. to 't3d').\n 20528#@cli : When '[ind_coords]' is omitted, default XY texture projection is performed. 20529#@cli : Default value: 'ind_coords=(undefined)'. 20530#@cli : $ image.jpg torus3d 100,30 texturize3d[-1] [-2] keep[-1] 20531texturize3d : check ${"is_image_arg $1"}" && (!narg(${2=}) || "${"is_image_arg $2"}")" 20532 e[^-1] "Texturize 3D object$? with texture $1"\ 20533 ${"if narg($2) u \" and texture coordinates $2\" else u \"\" fi"}"." 20534 pass$1 0 slices. 0 if s==1 to_rgb. else channels. 0,2 fi 20535 if narg($2) pass$2 else 0 fi 20536 v + _$0 20537 20538_texturize3d : 20539 repeat $!-2 l[$>,-2,-1] 20540 np={f2ui(i[7])} 20541 s3d[0] 20542 20543 # Retrieve texture coordinates for each vertex. 20544 if !w 20545 +r[2] 3,{2,round(h/3)},1,1,-1 s. x,3 rm. 20546 n.. 0,{6,w-1} n. 0,{6,h-1} a[-2,-1] x 20547 mv. -2 20548 fi 20549 20550 # Texturize 3D object 20551 1,{5,2*h} 20552 1,{5,3*h} 20553 1,{5,h},1,1,1 20554 eval " 20555 add_material() = ( 20556 ind_tex>=0?( # Shared texture 20557 copy(i[#-2,qc],[ -128,ind_tex,0,0 ],4); qc+=4 20558 ):( # Non-shared texture 20559 qc + whds#6 + 4>=h(#-2)?resize(#-2,1,int(1.5*qc + whds#6 + 4),1,1,0,0); 20560 copy(i[#-2,qc],[ -128,w#6,h#6,s#6 ],4); qc+=4; 20561 copy(i[#-2,qc],i(#6),whds#6); qc+=whds#6; 20562 ind_tex = np; 20563 ); 20564 ); 20565 20566 ind_tex = -1; 20567 for (pp = pc = qp = qc = np = 0, pp<h#3, ++np, 20568 qp + 13>=h(#-3)?resize(#-3,1,int(1.5*qp + 13),1,1,0,0); 20569 qc + 3>=h(#-2)?resize(#-2,1,int(1.5*qc + 3),1,1,0,0); 20570 N = i[#3,pp++]; 20571 20572 N==1?( # Colored point 20573 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 20574 R = i(#6,tx0,ty0,0,0); G = i(#6,tx0,ty0,0,1); B = i(#6,tx0,ty0,0,2); 20575 copy(i[#-3,qp],[ 1,v0 ],2); qp+=2; 20576 copy(i[#-2,qc],[ R,G,B ],3); qc+=3; 20577 20578 ):(N==2 || N==6)?( # Colored segment 20579 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 20580 v1 = i[#3,pp++]; tx1 = i(#7,0,v1); ty1 = i(#7,1,v1); 20581 N==6?(pp+=4); 20582 copy(i[#-3,qp],[ 6,v0,v1,tx0,ty0,tx1,ty1 ],7); qp+=7; 20583 add_material(); 20584 20585 ):(N==3 || N==9)?( # Colored triangle 20586 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 20587 v1 = i[#3,pp++]; tx1 = i(#7,0,v1); ty1 = i(#7,1,v1); 20588 v2 = i[#3,pp++]; tx2 = i(#7,0,v2); ty2 = i(#7,1,v2); 20589 N==9?(pp+=6); 20590 copy(i[#-3,qp],[ 9,v0,v1,v2,tx0,ty0,tx1,ty1,tx2,ty2 ],10); qp+=10; 20591 add_material(); 20592 20593 ):(N==4 || N==12)?( # Colored quadrangle 20594 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 20595 v1 = i[#3,pp++]; tx1 = i(#7,0,v1); ty1 = i(#7,1,v1); 20596 v2 = i[#3,pp++]; tx2 = i(#7,0,v2); ty2 = i(#7,1,v2); 20597 v3 = i[#3,pp++]; tx3 = i(#7,0,v3); ty3 = i(#7,1,v3); 20598 N==12?(pp+=8); 20599 copy(i[#-3,qp],[ 12,v0,v1,v2,v3,tx0,ty0,tx1,ty1,tx2,ty2,tx3,ty3 ],13); qp+=13; 20600 add_material(); 20601 20602 ):N==5?( # Colored sphere 20603 v0 = i[#3,pp++]; tx0 = i(#7,0,v0); ty0 = i(#7,1,v0); 20604 v1 = i[#3,pp++]; tx1 = i(#7,0,v1); ty1 = i(#7,1,v1); 20605 v2 = i[#3,pp++]; pp+=2; 20606 (tx0+=tx1)/=2; (ty0+=ty1)/=2; 20607 R = i(#6,tx0,ty0,0,0); G = i(#6,tx0,ty0,0,1); B = i(#6,tx0,ty0,0,2); 20608 copy(i[#-3,qp],[ 5,v0,v1,v2,0,0 ],6); qp+=6; 20609 copy(i[#-2,qc],[ R,G,B ],3); qc+=3; 20610 20611 ); 20612 ); 20613 resize(#-3,1,qp,1,1,0,0); 20614 resize(#-2,1,qc,1,1,0,0)" 20615 20616 rm[3-5] mv[-3--1] 3 20617 if !w rm.. fi 20618 a[0-5] y 20619 endl done rm[-2,-1] 20620 20621#@cli torus3d : _radius1,_radius2,_nb_subdivisions1>2,_nb_subdivisions2>2 20622#@cli : Input 3D torus at (0,0,0), with specified geometry. 20623#@cli : Default values: 'radius1=1', 'radius2=0.3', 'nb_subdivisions1=24' and 'nb_subdivisions2=12'. 20624#@cli : $ torus3d 10,3 +primitives3d 1 color3d[-2] ${-rgb} 20625torus3d : check "${3=24}>2 && ${4=12}>2" skip ${1=1},${2=0.3} 20626 e[^-1] "Input 3D torus, with radii ($1,$2) and subdivisions ($3,$4)." 20627 # Header. 20628 nbp={$3*$4} 20629 1,8,1,1,67.5,73.5,109.5,103.5,51.5,100.5,$nbp,{$4*$3} 20630 20631 # Vertices. 20632 (0;{2*pi}) +y. x 20633 r.. 1,{$3+1},1,1,3 z.. 0,0,0,{$3-1} 20634 r. {$4+1},1,1,1,3 z. 0,{$4-1} 20635 +sin[-2,-1] cos[-4,-3] r[-4--1] $4,$3 20636 *... $2 +... $1 *. $2 *[-4] ... *[-3,-2] 20637 y[-3--1] a[-3--1] x 20638 20639 # Primitives. 20640 1,$3,1,1,'y' *. $4 +shift. 0,-1 $4,1,1,1,'x' +shift. -1 r[-4--1] $4,$3 20641 ++[-4,-1] +.. [-4] +[-5] ... +[-4,-3] y[-4--1] i[-5] 1,{h},1,1,4 a[-5--1] x 20642 20643 # Colors / opacities. 20644 3,{h},1,1,200 1,{h},1,1,1 y[-4--2] a[-5--1] y 20645 nm. [3D\ torus] 20646 20647#@cli triangle3d : x0,y0,z0,x1,y1,z1,x2,y2,z2 20648#@cli : Input 3D triangle at specified coordinates. 20649#@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 20650triangle3d : 20651 e[^-1] "Input 3D triangle ($1,$2,$3)-($4,$5,$6)-($7,$8,$9)." 20652 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] 20653 20654#@cli volume3d 20655#@cli : Transform selected 3D volumetric images as 3D parallelepipedic objects. 20656#@cli : $ image.jpg animate blur,0,5,30 append z volume3d 20657volume3d : 20658 e[^-1] "Transform image$? as 3D parallelepipedic objects." 20659 repeat $! l[$>] 20660 w={w} h={h} d={d} 20661 +slices[0] 0 20662 +columns[0] 0 permute. zyxc mirror. x 20663 +slices[0] 100% mirror. x 20664 +columns[0] 100% permute. zyxc 20665 +rows[0] 100% permute. xzyc 20666 +rows[0] 0 permute. xzyc mirror. y 20667 rm[0] image6cube3d *3d $w,$h,$d 20668 endl done 20669 20670#@cli weird3d : _resolution>0 20671#@cli : Input 3D weird object at (0,0,0), with specified resolution. 20672#@cli : Default value: 'resolution=32'. 20673#@cli : $ weird3d 48 +primitives3d 1 color3d[-2] ${-rgb} 20674weird3d : skip ${1=32} 20675 e[^-1] "Input 3D weird object, with resolution $1." 20676 isosurface3d '" 20677 T = 1.61803399; 20678 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))"',\ 20679 0,-4.7,-4.7,-4.7,4.7,4.7,4.7,$1,$1,$1 20680 c3d. n3d. nm. [3D\ weird] 20681 20682#------------------------------- 20683# 20684#@cli :: Control Flow 20685# 20686#------------------------------- 20687 20688#@cli ap : eq. to 'apply_parallel'. 20689ap : 20690 _gmic_s="$?" v + _apply_parallel "$*" 20691 20692#@cli apply_parallel : "command" 20693#@cli : Apply specified command on each of the selected images, by parallelizing it for all image of the list. 20694#@cli : (eq. to 'ap'). 20695#@cli : $ image.jpg +mirror x +mirror y apply_parallel "blur 3" 20696apply_parallel : 20697 _gmic_s="$?" v + _$0 "$*" 20698 20699_apply_parallel : 20700 e[0--3] "Apply command '$*' on all image"$_gmic_s" in parallel, using "$_cpus" threads." 20701 if $!" && "narg("$*") 20702 m "_ap : repeat $! l[$>] $* if $! k[0] else 0 fi endl done" 20703 N={min($!,$_cpus)} 20704 commands= sep= repeat $N commands=$commands${sep}_ap[$>--1:$N] sep=, done 20705 parallel $commands 20706 um _ap 20707 fi 20708 20709#@cli apc : eq. to 'apply_parallel_channels'. 20710apc : 20711 _gmic_s="$?" v + _apply_parallel_channels "$*" 20712 20713#@cli apply_parallel_channels : "command" 20714#@cli : Apply specified command on each of the selected images, by parallelizing it for all channel 20715#@cli : of the images independently. 20716#@cli : (eq. to 'apc'). 20717#@cli : $ image.jpg apply_parallel_channels "blur 3" 20718apply_parallel_channels : 20719 _gmic_s="$?" v + _$0 "$*" 20720 20721_apply_parallel_channels : 20722 e[0--3] "Apply command '$*' on all channels of image"$_gmic_s" in parallel, using "$_cpus" threads." 20723 N=$! repeat $N s$>={$>,s} done s c 20724 ap "$1" 20725 repeat $N a[$>-{$>+${s$>}-1}] c done 20726 20727#@cli apo : eq. to 'apply_parallel_overlap'. 20728apo : check "${2=0}>=0 && isint(${3=0}) && $3>=0" 20729 _gmic_s="$?" v + _apply_parallel_overlap "$1",${2--1} 20730 20731#@cli apply_parallel_overlap : "command",overlap[%],nb_threads={ 0=auto | 1 | 2 | 4 | 8 | 16 } 20732#@cli : Apply specified command on each of the selected images, by parallelizing it on 'nb_threads' 20733#@cli : overlapped sub-images. 20734#@cli : (eq. to 'apo').\n 20735#@cli : 'nb_threads' must be a power of 2. 20736#@cli : Default values: 'overlap=0','nb_threads=0'. 20737#@cli : $ image.jpg +apply_parallel_overlap "smooth 500,0,1",1 20738apply_parallel_overlap : check "${2=0}>=0 && isint(${3=0}) && $3>=0" 20739 _gmic_s="$?" v + _$0 "$1",${2--1} 20740 20741_apply_parallel_overlap : check "${2=0}>=0 && isint(${3=0}) && $3>=0" 20742 N={if($3,max(1,round($3)),$_cpus)} N={2^int(log2(min(16,$N)))} 20743 e[0--3] "Apply parallelized command '$1' on image"$_gmic_s", with overlap $2 and "$N" threads." 20744 __apo_exception="" 20745 m "_check1 : if $!!=1 rm 0 __apo_exception=\"Command 'apply_parallel_overlap': Specified command '$1' changes the 20746 size of the image stack.\" fi" 20747 repeat $! l[$>] 20748 _apply_parallel_overlap$N "$1",$2 20749 endl done 20750 um _check1 20751 20752_apply_parallel_overlap1 : 20753 $1 20754 if narg($__apo_exception) error[0--12] $__apo_exception fi 20755 20756_apply_parallel_overlap2 : 20757 if w>=h 20758 ovx={round(if(${"is_percent $2"},w*$2,$2))} w2={int(w/2)} 20759 +z[0] {$w2-$ovx},100% z[0] 0,{$w2+$ovx-1} 20760 parallel "l[0] $1 _check1 endl","l[1] $1 _check1 endl" 20761 if narg($__apo_exception) error[0--12] $__apo_exception fi 20762 z[0] 0,{0,w-1-$ovx} z[1] $ovx,100% a x 20763 else 20764 ovy={round(if(${"is_percent $2"},h*$2,$2))} h2={int(h/2)} 20765 +rows[0] {$h2-$ovy},100% rows[0] 0,{$h2+$ovy-1} 20766 parallel "l[0] $1 _check1 endl","l[1] $1 _check1 endl" 20767 if narg($__apo_exception) error[0--12] $__apo_exception fi 20768 rows[0] 0,{0,h-1-$ovy} rows[1] $ovy,100% a y 20769 fi 20770 20771_apply_parallel_overlap4 : 20772 if max(w,h)/min(w,h)>=3 20773 _apply_parallel_overlap2 "_apply_parallel_overlap2 \"$1\",$2",$2 20774 else 20775 ovx={round(if(${"is_percent $2"},w*$2,$2))} w2={int(w/2)} 20776 ovy={round(if(${"is_percent $2"},h*$2,$2))} h2={int(h/2)} 20777 +z[0] {$w2-$ovx},0,100%,{$h2+$ovy-1} +z[0] 0,{$h2-$ovy},{$w2+$ovx-1},100% 20778 +z[0] {$w2-$ovx},{$h2-$ovy},100%,100% z[0] 0,0,{$w2+$ovx-1},{$h2+$ovy-1} 20779 parallel "l[0] $1 _check1 endl","l[1] $1 _check1 endl","l[2] $1 _check1 endl","l[3] $1 _check1 endl" 20780 if narg($__apo_exception) error[0--12] $__apo_exception fi 20781 z[0] 0,0,{0,w-1-$ovx},{0,h-1-$ovy} z[1] $ovx,0,100%,{1,h-1-$ovy} 20782 z[2] 0,$ovy,{2,w-1-$ovx},100% z[3] $ovx,$ovy,100%,100% 20783 a[0,1] x a[1,2] x a y 20784 fi 20785 20786_apply_parallel_overlap8 : 20787 _apply_parallel_overlap2 "_apply_parallel_overlap4 \"$1\",$2",$2 20788 20789_apply_parallel_overlap16 : 20790 _apply_parallel_overlap2 "_apply_parallel_overlap8 \"$1\",$2",$2 20791 20792#@cli at : eq. to 'apply_tiles'. 20793at : check "${2=10%}>0 && ${3=10%}>0 && ${4=10%}>0 && ${5=0}>=0 && ${6=0}>=0 && ${7=0}>=0 && 20794 isint(${8=1}) && $8>=0 && $8<=3" 20795 _gmic_s="$?" v + _apply_tiles "$1",${2--1} 20796 20797#@cli apply_tiles : "command",_tile_width[%]>0,_tile_height[%]>0,_tile_depth[%]>0,_overlap_width[%]>=0,\ 20798# _overlap_height[%]>=0,_overlap_depth[%]>=0,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 20799#@cli : Apply specified command on each tile (neighborhood) of the selected images, eventually with overlapping tiles. 20800#@cli : (eq. to 'at'). 20801#@cli : Default values: 'tile_width=tile_height=tile_depth=10%','overlap_width=overlap_height=overlap_depth=0' \ 20802# and 'boundary_conditions=1'. 20803#@cli : $ image.jpg +equalize[0] 256 +apply_tiles[0] "equalize 256",16,16,1,50%,50% 20804apply_tiles : check "${2=10%}>0 && ${3=10%}>0 && ${4=10%}>0 && ${5=0}>=0 && ${6=0}>=0 && ${7=0}>=0 && 20805 isint(${8=1}) && $8>=0 && $8<=3" 20806 _gmic_s="$?" v + _$0 "$1",${2--1} 20807 20808_apply_tiles : 20809 e[0--3] "Apply command '$1' on $2x$3x$4 tiles of image$?, with overlaps ($5,$6,$7) and "\ 20810 ${"arg 1+$8,dirichlet,neumann,periodic,mirror"}" boundary conditions." 20811 repeat $! l[$>] 20812 bw={cut(round(${"is_percent $2"}?w*$2:$2),1,w)} 20813 bh={cut(round(${"is_percent $3"}?h*$3:$3),1,h)} 20814 bd={cut(round(${"is_percent $4"}?d*$4:$4),1,d)} 20815 ow={round(${"is_percent $5"}?$bw*$5:$5)} 20816 oh={round(${"is_percent $6"}?$bh*$6:$6)} 20817 od={round(${"is_percent $7"}?$bd*$7:$7)} 20818 sw={cut($bw-$ow,1,$bw)} 20819 sh={cut($bh-$oh,1,$bh)} 20820 sd={cut($bd-$od,1,$bd)} 20821 100%,100%,100%,{s+1} # Reconstructed image + weights 20822 if $ow>0" || "$oh>0" || "$od>0 l[] # Generate gaussian weight in case of overlap 20823 $bw,1,1 1,$bh,1 1,1,$bd 20824 = 1,50%,50%,50% distance 1 20825 /[0] {0.3*$bw} /[1] {0.3*$bh} /[2] {0.3*$bd} 20826 sqr * -1 exp r $bw,$bh,$bd,1 * 20827 endl else $bw,$bh,$bd,1,1 20828 fi 20829 $bw,$bh,$bd,[0] 20830 m "__at : $1 k. r "$bw,$bh,$bd,{0,s},0 20831 eval " 20832 ref(crop(#2),mask); 20833 for (z = 0, z<d#0, z+="$sd", 20834 for (y = 0, y<h#0, y+="$sh", 20835 for (x = 0, x<w#0, x+="$sw", 20836 draw(crop(#0,x,y,z,w,h,d,$8),0,0,0,0,w,h,d); 20837 run('__at.'); 20838 breakpoint(); 20839 draw(#1,crop(#-1),x,y,z,0,w,h,d,s#0,-1,mask); 20840 draw(#1,mask,x,y,z,s#0,w,h,d,1,-1); 20841 ) 20842 ) 20843 )" 20844 rm[-2,-1] 20845 s. c,-{0,s} /[-2,-1] k. 20846 um __at 20847 endl done 20848 20849#@cli apply_timeout : "command",_timeout={ 0=no timeout | >0=with specified timeout (in seconds) } 20850#@cli : Apply a command with a timeout. 20851#@cli : Set variable '$_is_timeout' to '1' if timeout occurred, '0' otherwise. 20852#@cli : Default value: 'timeout=20'. 20853apply_timeout : check "${2=20}>=0" 20854 if $2<=0 20855 e[0--3] "Apply command '$1' on image$?, with no timeout." 20856 $1 20857 _is_timeout=0 20858 else 20859 e[0--3] "Apply command '$1' on image$?, with a timeout of $2 seconds." 20860 l[] ('$/') id={is} rm endl 20861 l 20862 +store initial 20863 __done$id=0 __is_timeout$id=0 20864 parallel "$1 __done"$id"=1",\ 20865 "l[] do if $|-"$|">$2 __is_timeout"$id"=1 error \"\" elif $__done"$id" break fi wait 100 while 1 endl" 20866 onfail 20867 rm $initial 20868 _is_timeout=0 20869 if ${__is_timeout$id} _is_timeout=1 error[0--5] "Command '$0': Time out ($2 seconds) for command '$1'." 20870 else error[0--5] "Command '$0': "${} 20871 fi 20872 endl 20873 fi 20874 20875#@cli check : condition : (+) 20876#@cli : Evaluate specified condition and display an error message if evaluated to false. 20877#@cli : If 'expression' is not a math expression, it is regarded as a filename and checked if it exists. 20878 20879#@cli check3d : _is_full_check={ 0 | 1 } : (+) 20880#@cli : Check validity of selected 3D vector objects, and display an error message 20881#@cli : if one of the selected images is not a valid 3D vector object. 20882#@cli : Full 3D object check is slower but more precise. 20883#@cli : Default value: 'is_full_check=1'. 20884 20885# check_display : calling_command_name 20886# Check if a display is available, and throw an error otherwise. 20887check_display : skip "${1=check_display}" 20888 if !{*,u} error[0--3] "Command '$1': No display available." fi 20889 20890# check_opencv : calling_command_name 20891# Check is OpenCV features are available, and throw an error otherwise. 20892check_opencv : skip "${1=check_opencv}" 20893 l[] check_opencv.mp4,0,0,1 rm 20894 onfail if find(['${}'],'-Dcimg_use_opencv')>0 20895 error[0--4] "Command '$1': No OpenCV features available. "\ 20896 "Your G'MIC interpreter has not been compiled with OpenCV support." 20897 fi rm endl 20898 20899#@cli continue : (+) 20900#@cli : Go to end of current 'repeat...done', 'do...while' or 'local...endlocal' block. 20901#@cli : $ image.jpg repeat 10 blur 1 if 1==1 continue fi deform 10 done 20902 20903#@cli break : (+) 20904#@cli : Break current 'repeat...done', 'do...while' or 'local...endlocal' block. 20905#@cli : $ image.jpg repeat 10 blur 1 if 1==1 break fi deform 10 done 20906 20907#@cli do : (+) 20908#@cli : Start a 'do...while' block. 20909#@cli : $ image.jpg luminance i={ia+2} do set 255,{u(100)}%,{u(100)}% while ia<$i 20910 20911#@cli done : (+) 20912#@cli : End a 'repeat/for...done' block, and go to associated 'repeat/for' position, if iterations remain. 20913 20914#@cli elif : condition : (+) 20915#@cli : Start a 'elif...[else]...fi' block if previous 'if' was not verified 20916#@cli : and test if specified condition holds 20917#@cli : 'condition' is a mathematical expression, whose evaluation is interpreted as { 0=false | other=true }.. 20918#@cli : $$ https://gmic.eu/tutorial/iffi 20919 20920#@cli else : (+) 20921#@cli : Execute following commands if previous 'if' or 'elif' conditions failed. 20922#@cli : $$ https://gmic.eu/tutorial/iffi 20923 20924#@cli fi : (+) 20925#@cli : End a 'if...[elif]...[else]...fi' block. 20926#@cli : (eq. to 'fi').\n 20927#@cli : $$ https://gmic.eu/tutorial/iffi 20928 20929#@cli endl : eq. to 'endlocal'. : (+) 20930 20931#@cli endlocal : (+) 20932#@cli : End a 'local...endlocal' block. 20933#@cli : (eq. to 'endl'). 20934 20935#@cli error : message : (+) 20936#@cli : Print specified error message on the standard error (stderr) and exit interpreter, except 20937#@cli : if error is caught by a 'onfail' command. 20938#@cli : Command selection (if any) stands for displayed call stack subset instead of image indices. 20939 20940#@cli eval : expression : (+) 20941#@cli : Evaluate specified math expression. 20942#@cli : - If no command selection is specified, the expression is evaluated once and its result is set to status. 20943#@cli : - If command selection is specified, the evaluation is looped over selected images. Status is not modified. 20944#@cli : (in this latter case, 'eval' is similar to 'fill' without assigning the image values). 20945 20946#@cli x : eq. to 'exec'. : (+) 20947 20948#@cli exec : _is_verbose={ 0 | 1 },"command" : (+) 20949#@cli : Execute external command using a system call. 20950#@cli : The status value is then set to the error code returned by the system call. 20951#@cli : If 'is_verbose=1', the executed command is allowed to output on stdout/stderr. 20952#@cli : (eq. to 'x'). 20953#@cli : Default value: 'is_verbose=1'. 20954 20955#@cli xo : eq. to 'exec_out'. 20956xo : 20957 v + _exec_out $"*" 20958 20959#@cli exec_out : _mode,"command" 20960#@cli : Execute external command using a system call, and return resulting `stdout` and/or `stderr`. 20961#@cli : 'mode' can be { 0=stdout | 1=stderr | 2=stdout+stderr }. 20962exec_out : 20963 v + _exec_out $"*" 20964 20965_exec_out : 20966 l[] 20967 if "isint($1) && isin($1,0,1,2)" mode=$1 command="${2--1}" 20968 else mode=0 command="$*" 20969 fi 20970 onfail mode=0 command="$*" endl 20971 s0,s1,s2=stdout,stderr,stdout+stderr 20972 e[0--3] "Execute external command '"$command"', and return "${s$mode}" output." 20973 file_rand filename=${} 20974 if $mode==0 x $command" > "$filename 20975 elif $mode==1 x $command" 2> "$filename 20976 else x $command" >"$filename" 2>&1" 20977 fi 20978 it $filename u {t} rm. delete $filename 20979 20980#@cli for : condition : (+) 20981#@cli : Start a 'for...done' block. 20982#@cli : $ image.jpg resize2dy 32 400,400,1,3 x=0 for $x<400 image[1] [0],$x,$x x+=40 done 20983 20984#@cli if : condition : (+) 20985#@cli : Start a 'if...[elif]...[else]...fi' block and test if specified condition holds. 20986#@cli : 'condition' is a mathematical expression, whose evaluation is interpreted as { 0=false | other=true }. 20987#@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 20988#@cli : $$ https://gmic.eu/tutorial/iffi 20989 20990#@cli l : eq. to 'local'. : (+) 20991 20992#@cli local : (+) 20993#@cli : Start a 'local...[onfail]...endlocal' block, with selected images. 20994#@cli : (eq. to 'l'). 20995#@cli : $ image.jpg local[] 300,300,1,3 rand[0] 0,255 blur 4 sharpen 1000 endlocal 20996#@cli : $ image.jpg +local repeat 3 deform 20 done endlocal 20997#@cli : $$ https://gmic.eu/oldtutorial/_local 20998 20999#@cli mutex : index,_action={ 0=unlock | 1=lock } : (+) 21000#@cli : Lock or unlock specified mutex for multi-threaded programming. 21001#@cli : A locked mutex can be unlocked only by the same thread. All mutexes are unlocked by default. 21002#@cli : 'index' designates the mutex index, in [0,255]. 21003#@cli : Default value: 'action=1'. 21004 21005#@cli noarg : (+) 21006#@cli : Used in a custom command, 'noarg' tells the command that its argument list have not been used 21007#@cli : finally, and so they must be evaluated next in the G'MIC pipeline, just as if the custom 21008#@cli : command takes no arguments at all. 21009#@cli : Use this command to write a custom command which can decide if it takes arguments or not. 21010 21011#@cli onfail : (+) 21012#@cli : Execute following commands when an error is encountered in the body of the 'local...endlocal' block. 21013#@cli : The status value is set with the corresponding error message. 21014#@cli : $ image.jpg +local blur -3 onfail mirror x endlocal 21015 21016#@cli parallel : _wait_threads,"command1","command2",... : (+) 21017#@cli : Execute specified commands in parallel, each in a different thread. 21018#@cli : Parallel threads share the list of images. 21019#@cli : 'wait_threads' can be { 0=when current environment ends | 1=immediately }. 21020#@cli : Default value: 'wait_threads=1'. 21021#@cli : $ image.jpg [0] parallel "blur[0] 3","mirror[1] c" 21022 21023# The implementation below allows to use parallel as a regular command with selections. 21024parallel : skip "${1=},${2=},${3=},${4=},${5=},${6=},${7=},${8=},${9=},${10=},${11=},${12=},${13=},${14=},${15=}" 21025 if $1==0||$1==1||$1==2 e[0--3] "Execute "{$#-1}" commands '${2--1}' in parallel on image$?." 21026 else e[0--3] "Execute "$#" commands '$*' in parallel on image$?." 21027 fi 21028 parallel $"*" 21029 21030#@cli progress : 0<=value<=100 : -1 : (+) 21031#@cli : Set the progress index of the current processing pipeline. 21032#@cli : This command is useful only when G'MIC is used by an embedding application. 21033 21034#@cli q : eq. to 'quit'. : (+) 21035 21036#@cli quit : (+) 21037#@cli : Quit G'MIC interpreter. 21038#@cli : (eq. to 'q'). 21039 21040#@cli repeat : nb_iterations,_variable_name : (+) 21041#@cli : Start 'nb_iterations' iterations of a 'repeat...done' block. 21042#@cli : 'nb_iterations' is a mathematical expression that will be evaluated. 21043#@cli : $ image.jpg split y repeat $!,n shift[$n] $<,0,0,0,2 done append y 21044#@cli : $ image.jpg mode3d 2 repeat 4 imagecube3d rotate3d 1,1,0,40 snapshot3d 400,1.4 done 21045#@cli : $$ https://gmic.eu/oldtutorial/_repeat 21046 21047#@cli return : (+) 21048#@cli : Return from current custom command. 21049 21050#@cli rprogress : 0<=value<=100 | -1 | "command",0<=value_min<=100,0<=value_max<=100 21051#@cli : Set the progress index of the current processing pipeline (relatively to 21052#@cli : previously defined progress bounds), or call the specified command with 21053#@cli : specified progress bounds. 21054rprogress : skip ${2=""} 21055 if !narg($_progress_bounds) _progress_bounds=0,100 fi 21056 m={arg(-2,$_progress_bounds)} M={arg(-1,$_progress_bounds)} 21057 if $#==2&&!narg($2) # 1 argument -> Set progress bar. 21058 e[0--3] "Set relative progress index to $1%." 21059 progress {if($1<0,-1,min(100,max(0,$m+($M-$m)*$1%)))} 21060 elif $#==3 # 3 arguments -> Call command with specified bounds. 21061 nm={min($2,$-1)} nM={max($2,$-1)} 21062 e[0--3] "Call command '$1' with progress bounds ["$nm,$nM"]." 21063 progress $m _progress_bounds=$_progress_bounds,{$m+$nm*($M-$m)/100},{$m+$nM*($M-$m)/100} # Push new bounds. 21064 run "$1" 21065 progress $M ($_progress_bounds) _progress_bounds={@0--3} rm. # Pop bounds. 21066 else error[0--3] "Command '$0': Invalid argument '$*'." 21067 fi 21068 21069#@cli run : "G'MIC pipeline" 21070#@cli : Run specified G'MIC pipeline. 21071#@cli : This is only useful when used from a shell, e.g. to avoid shell substitutions to happen in argument. 21072run : 21073 $* 21074 21075#@cli skip : item : (+) 21076#@cli : Do nothing but skip specified item. 21077 21078#@cli u : eq. to 'status'. : (+) 21079 21080#@cli status : status_string : (+) 21081#@cli : Set the current status. Used to define a returning value from a function. 21082#@cli : (eq. to 'u'). 21083#@cli : $ image.jpg command "foo : u0=Dark u1=Bright status ${u{ia>=128}}" text_outline ${-foo},2,2,23,2,1,255 21084 21085#@cli while : condition : (+) 21086#@cli : End a 'do...while' block and go back to associated 'do' if specified condition holds. 21087#@cli : 'condition' is a mathematical expression, whose evaluation is interpreted as { 0=false | other=true }. 21088 21089#------------------------- 21090# 21091#@cli :: Neural Networks 21092# 21093#------------------------- 21094 21095#@cli nn_lib : 21096#@cli : Return the list of library functions that has to be included in a math expression,\ 21097# in order to use the neural network library. 21098nn_lib : 21099 u " 21100 #--------------------------------------------------------------------------- 21101 # Definition of the library environment variables and convenience functions. 21102 #--------------------------------------------------------------------------- 21103 begin( 21104 const nn_is_training = isnan($_nn_is_training)?0:$_nn_is_training; 21105 const nn_optimizer = isnan($_nn_optimizer)?2:$_nn_optimizer; # Adam optimizer by default 21106 const nn_iteration = isnan($_nn_iteration)?0:$_nn_iteration; 21107 const nn_batch_iteration = isnan($_nn_batch_iteration)?0:$_nn_batch_iteration; 21108 const nn_nb_threads_max = n; 21109 ); 21110 21111 begin_t( 21112 nn_thread = t; 21113 nn_nb_threads_used = nn_thread + 1; 21114 nn_nb_samples = 0; 21115 ); 21116 21117 ++nn_nb_samples; 21118 21119 end( 21120 merge(nn_nb_threads_used,max); 21121 merge(nn_nb_samples,+); 21122 ); 21123 21124 nn_update() = ( # This has to be the last 'end()' bloc encountered in $_nn_update 21125 set(nn_iteration + 1,'_nn_iteration'); 21126 set(nn_batch_iteration + 1,'_nn_batch_iteration'); 21127 ); 21128 21129 nn_display(L) = display(L#_out,L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum); 21130 nn_display_deriv(L) = display(L#_deriv_out,L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum); 21131 21132 #-------------------------------------------- 21133 # Activation functions and their derivatives. 21134 #-------------------------------------------- 21135 _nn_activate_pointwise(Z,activation) = (fill(#Z,k,nn_activation_#activation(#Z[k]))); 21136 nn_activate(Z,activation) = nn_activate_#activation(#Z); 21137 21138 # ELU: Exponential Linear Unit. 21139 #------------------------------- 21140 nn_activation_elu(z) = (z<0?exp(z) - 1:z); 21141 nn_activation_deriv_elu(z) = (z<0?exp(z):1); 21142 nn_activate_elu(Z) = _nn_activate_pointwise(Z,elu); 21143 nn_activate_deriv_elu(Z) = _nn_activate_pointwise(Z,deriv_elu); 21144 21145 # GELU: Gaussian Error Linear Unit. 21146 #----------------------------------- 21147 nn_activation_gelu(z) = (0.5*z*(1 + erf(z/sqrt(2)))); 21148 nn_activation_deriv_gelu(z) = (0.5 + 0.5*erf(z/sqrt(2)) + z*exp(-z^2/2)/sqrt(2*pi)); 21149 nn_activate_gelu(Z) = _nn_activate_pointwise(Z,gelu); 21150 nn_activate_deriv_gelu(Z) = _nn_activate_pointwise(Z,deriv_gelu); 21151 21152 # LeakyRELU: Leaky Rectified Linear Unit. 21153 #----------------------------------------- 21154 nn_activation_leakyrelu(z) = (z<0?0.05*z:z); 21155 nn_activation_deriv_leakyrelu(z) = (z<0?0.05:1); 21156 nn_activate_leakyrelu(Z) = _nn_activate_pointwise(Z,leakyrelu); 21157 nn_activate_deriv_leakyrelu(Z) = _nn_activate_pointwise(Z,deriv_leakyrelu); 21158 21159 # Linear. 21160 #-------- 21161 nn_activate_linear(Z) = (0); 21162 nn_activate_deriv_linear(Z) = (#Z = 1); 21163 21164 # RELU: Rectified Linear Unit. 21165 #------------------------------ 21166 nn_activation_relu(z) = (z<0?0:z); 21167 nn_activation_deriv_relu(z) = (z<0?0:1); 21168 nn_activate_relu(Z) = _nn_activate_pointwise(Z,relu); 21169 nn_activate_deriv_relu(Z) = _nn_activate_pointwise(Z,deriv_relu); 21170 21171 # Sigmoid. 21172 #--------- 21173 nn_activation_sigmoid(z) = (0.5 + 0.5*tanh(z/2)); 21174 nn_activation_deriv_sigmoid(z) = (_nn_sig = nn_activation_sigmoid(z); _nn_sig*(1-_nn_sig)); 21175 nn_activate_sigmoid(Z) = _nn_activate_pointwise(Z,sigmoid); 21176 nn_activate_deriv_sigmoid(Z) = _nn_activate_pointwise(Z,deriv_sigmoid); 21177 21178 # Sqr: Square. 21179 #------------- 21180 nn_activate_sqr(Z) = (Z*=Z); 21181 nn_activate_deriv_sqr(Z) = (Z*=2); 21182 21183 # Sqrt: sqrt(|z|). 21184 #----------------- 21185 nn_activation_sqrt(z) = (sqrt(abs(z))); 21186 nn_activation_deriv_sqrt(z) = (0.5*sign(x)/sqrt(max(1e-8,abs(z)))); 21187 nn_activate_sqrt(Z) = _nn_activate_pointwise(Z,sqrt); 21188 nn_activate_deriv_sqrt(Z) = _nn_activate_pointwise(Z,deriv_sqrt); 21189 21190 # Tanh. 21191 #------ 21192 nn_activation_tanh(z) = (tanh(z)); 21193 nn_activation_deriv_tanh(z) = (1 - tanh(z)^2); 21194 nn_activate_tanh(Z) = _nn_activate_pointwise(Z,tanh); 21195 nn_activate_deriv_tanh(Z) = _nn_activate_pointwise(Z,deriv_tanh); 21196 21197 #------------ 21198 # Optimizers. 21199 #------------ 21200 21201 # Stochastic gradient descent. 21202 #----------------------------- 21203 nn_optimizer_sgd_update_layer(L_params,dL_params) = ( 21204 L_params#-=nn_learning_rate*#dL_params; 21205 ); 21206 21207 # David optimizer. 21208 #----------------- 21209 nn_optimizer_david_update_layer(L_params,dL_params) = ( 21210 _dt = nn_learning_rate/abs(maxabs(1e-9,#dL_params)); 21211 L_params#-=_dt*#dL_params; 21212 ); 21213 21214 # Adam optimizer. 21215 #---------------- 21216 nn_optimizer_adam_init_update_layer() = ( 21217 begin( 21218 const nn_optimizer_adam_beta1 = 0.9; 21219 const nn_optimizer_adam_beta2 = 0.999; 21220 const nn_optimizer_adam_beta1_t = nn_iteration>200?0:nn_optimizer_adam_beta1^(nn_iteration + 1); 21221 const nn_optimizer_adam_beta2_t = nn_iteration>200?0:nn_optimizer_adam_beta2^(nn_iteration + 1); 21222 const nn_optimizer_adam_alpha_t = sqrt(1 - nn_optimizer_adam_beta2_t)/(1 - nn_optimizer_adam_beta1_t); 21223 ); 21224 ); 21225 21226 nn_optimizer_adam_update_layer(L_params,dL_params) = ( 21227 dL_params#_name_m = '_nn_#dL_params#_m'; 21228 dL_params#_name_v = '_nn_#dL_params#_v'; 21229 !nn_iteration || isnan($_nn_#dL_params#_m)?( 21230 dL_params#_m = dL_params#_v = vector(#size(dL_params)); 21231 ):( 21232 dL_params#_m = get(dL_params#_name_m,size(dL_params)); 21233 dL_params#_v = get(dL_params#_name_v,size(dL_params)); 21234 ); 21235 dL_params#_m = lerp(dL_params,dL_params#_m,nn_optimizer_adam_beta1); 21236 dL_params#_v = lerp(dL_params^2,dL_params#_v,nn_optimizer_adam_beta2); 21237 store(dL_params#_m,dL_params#_name_m,size(dL_params)); 21238 store(dL_params#_v,dL_params#_name_v,size(dL_params)); 21239 21240 L_params#-=nn_learning_rate*nn_optimizer_adam_alpha_t*dL_params#_m/sqrt(1e-8 + dL_params#_v); 21241 ); 21242 21243 # Adamax optimizer. 21244 #------------------ 21245 nn_optimizer_adamax_init_update_layer() = ( 21246 begin( 21247 const nn_optimizer_adamax_beta1 = 0.9; 21248 const nn_optimizer_adamax_beta2 = 0.999; 21249 const nn_optimizer_adamax_ombeta1_t = nn_iteration>200?1:(1 - nn_optimizer_adamax_beta1^(nn_iteration + 1)); 21250 ); 21251 ); 21252 21253 nn_optimizer_adamax_update_layer(L_params,dL_params) = ( 21254 dL_params#_name_m = '_nn_#dL_params#_m'; 21255 dL_params#_name_v = '_nn_#dL_params#_v'; 21256 !nn_iteration || isnan($_nn_#dL_params#_m)?( 21257 dL_params#_m = dL_params#_v = vector(#size(dL_params)); 21258 ):( 21259 dL_params#_m = get(dL_params#_name_m,size(dL_params)); 21260 dL_params#_v = get(dL_params#_name_v,size(dL_params)); 21261 ); 21262 dL_params#_m = lerp(dL_params,dL_params#_m,nn_optimizer_adamax_beta1); 21263 dL_params#_v = vmax(abs(dL_params),nn_optimizer_adamax_beta2*dL_params#_v); 21264 store(dL_params#_m,dL_params#_name_m,size(dL_params)); 21265 store(dL_params#_v,dL_params#_name_v,size(dL_params)); 21266 21267 L_params#-=(nn_learning_rate/nn_optimizer_adamax_ombeta1_t)*dL_params#_m/sqrt(1e-8 + dL_params#_v); 21268 ); 21269 21270 # Generic function that dispatches to selected optimizer. 21271 #-------------------------------------------------------- 21272 begin( 21273 nn_optimizer==2?nn_optimizer_adam_init_update_layer(): # Adam 21274 nn_optimizer==3?nn_optimizer_adamax_init_update_layer(); # Adamax 21275 ); 21276 nn_optimizer_update_layer(L,dL) = ( 21277 !nn_optimizer?nn_optimizer_sgd_update_layer(#L,#dL): # Stochastic gradient descent 21278 nn_optimizer==1?nn_optimizer_david_update_layer(#L,#dL): # David 21279 nn_optimizer==2?nn_optimizer_adam_update_layer(#L,#dL): # Adam 21280 nn_optimizer==3?nn_optimizer_adamax_update_layer(#L,#dL); # Adamax 21281 ); 21282 21283 # Strategy to adapt learning rate regarding loss decrease/increase. 21284 #------------------------------------------------------------------- 21285 nn_optimizer_update_learning_rate(L) = ( 21286 nn_batch_iteration?( 21287 # Compute trend: percentage of loss decrease(<0) or increase(>0). 21288 L#_trend = (L#_out - L#_previous_out)/max(1e-8,L#_previous_out); 21289 L#_trend_moment = lerp(sign(L#_trend),L#_trend_moment,0.75); 21290 21291 # Adapt strategy regarding to trend. 21292 L#_trend>=0.3?( # Large local loss increase -> drastically reduce learning rate 21293 L#_learning_rate = max(0.25*L#_learning_rate,1e-11); 21294 L#_nb_increases = L#_nb_decreases = 0; 21295 ):L#_trend_moment>=0?( # Global loss increase 21296 ++L#_nb_increases; 21297 L#_nb_decreases = 0; 21298 L#_nb_increases>=2?( # Global loss increase -> slightly reduce learning rate 21299 L#_learning_rate = max(0.75*L#_learning_rate,1e-11); 21300 L#_nb_increases = 0; 21301 ); 21302 ):L#_trend_moment<0?( # Global loss decrease 21303 ++L#_nb_decreases; 21304 L#_nb_decreases>=4?( # Global loss decrease -> slightly increase learning rate 21305 L#_learning_rate = min(L#_learning_rate*1.15,1); 21306 L#_nb_decreases = 0; 21307 ); 21308 ); 21309 ):(L#_trend = 0); 21310 ); 21311 21312 #---------------- 21313 # Network layers. 21314 #---------------- 21315 21316 # add: Add two inputs. 21317 #--------------------- 21318 nn_layer_add_init_forward(L,IN) = ( 21319 const L#_out_width = IN#_out_width; 21320 const L#_out_height = IN#_out_height; 21321 const L#_out_depth = IN#_out_depth; 21322 const L#_out_spectrum = IN#_out_spectrum; 21323 ); 21324 21325 nn_layer_add_forward(L,IN0,IN1) = ( 21326 L#_out = IN0#_out + IN1#_out; 21327 ); 21328 21329 nn_layer_add_backward(L,IN0,IN1) = ( 21330 IN0#_deriv_out = IN1#_deriv_out = L#_deriv_out/2; 21331 ); 21332 21333 # append: Append two inputs as a new output. 21334 #-------------------------------------------- 21335 nn_layer_append_init_forward(L,IN0,IN1) = ( 21336 const L#_out_width = IN0#_out_width; 21337 const L#_out_height = IN0#_out_height; 21338 const L#_out_depth = IN0#_out_depth; 21339 const L#_out_spectrum = IN0#_out_spectrum + IN1#_out_spectrum; 21340 ); 21341 21342 nn_layer_append_forward(L,IN0,IN1) = ( 21343 L#_out = vector(#size(IN0#_out) + size(IN1#_out)); 21344 copy(L#_out,IN0#_out,size(IN0#_out)); 21345 copy(L#_out[size(IN0#_out)],IN1#_out,size(IN1#_out)); 21346 ); 21347 21348 nn_layer_append_backward(L,IN0,IN1) = ( 21349 IN0#_deriv_out = L#_deriv_out[0,size(IN0#_out)]; 21350 IN1#_deriv_out = L#_deriv_out[size(IN0#_out),size(IN1#_out)]; 21351 ); 21352 21353 # avgpool2d : 2D average pooling. 21354 #-------------------------------- 21355 nn_layer_avgpool2d_init_forward(L,IN) = ( 21356 const L#_out_width = int(IN#_out_width/2); 21357 const L#_out_height = int(IN#_out_height/2); 21358 const L#_out_depth = IN#_out_depth; 21359 const L#_out_spectrum = IN#_out_spectrum; 21360 nn_avgpool2d_kernel_forward = vector4(0.25); 21361 nn_avgpool2d_kernel_backward = [ 1,0,0,0 ]; 21362 ); 21363 21364 nn_layer_avgpool2d_forward(L,IN) = ( 21365 L#_out = correlate(IN#_out, 21366 IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum, 21367 nn_avgpool2d_kernel_forward,2,2,1,1, 21368 1,0,1, 21369 0,0,0, 21370 0,0,0, 21371 L#_out_width - 1,L#_out_height - 1,L#_out_depth - 1, 21372 2,2,1); 21373 ); 21374 21375 nn_layer_avgpool2d_backward(L,IN) = ( 21376 IN#_deriv_out = correlate(L#_deriv_out, 21377 L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 21378 nn_avgpool2d_kernel_backward,2,2,1,1, 21379 0,0,1, 21380 0,0,0, 21381 0,0,0, 21382 IN#_out_width - 1,IN#_out_height - 1,IN#_out_depth - 1, 21383 0.5,0.5,1, 21384 1,1,1, 21385 0); 21386 ); 21387 21388 # batchnorm: Batch-normalization layer. 21389 #--------------------------------------- 21390 nn_layer_batchnorm_init_forward(L,IN) = ( 21391 const L#_ind = $L#; 21392 const L#_out_width = IN#_out_width; 21393 const L#_out_height = IN#_out_height; 21394 const L#_out_depth = IN#_out_depth; 21395 const L#_out_spectrum = IN#_out_spectrum; 21396 const L#_base_col = nn_is_training==1?0:2; 21397 L#_mu = crop(##L#_ind,L#_base_col,0,1,h##L#_ind); 21398 L#_sigma = sqrt(crop(##L#_ind,L#_base_col + 1,0,1,h##L#_ind)); 21399 isnan(L#_mu[0])?(L#_mu = 0; L#_sigma = 1); 21400 L#_gamma = crop(##L#_ind,4,0,1,h##L#_ind); 21401 L#_beta = crop(##L#_ind,5,0,1,h##L#_ind); 21402 L#_out = vector(#size(IN#_out)); 21403 ); 21404 21405 nn_layer_batchnorm_forward(L,IN) = ( 21406 L#_z = IN#_out; 21407 L#_z-=L#_mu; 21408 L#_z/=1e-9 + L#_sigma; 21409 L#_out = L#_gamma*L#_z; 21410 L#_out+=L#_beta; 21411 ); 21412 21413 nn_layer_batchnorm_init_backward(L,IN) = ( 21414 L#_threads_nb_samples = vector(#nn_nb_threads_max); 21415 L#_threads_in_mean = L#_threads_in_variance = vector(#nn_nb_threads_max*size(IN#_out)); 21416 L#_nb_samples = 0; 21417 L#_in_mean = L#_in_variance = vector(#size(IN#_out)); 21418 L#_batch_deriv_gamma = vector(#size(L#_gamma)); 21419 L#_batch_deriv_beta = vector(#size(L#_beta)); 21420 ); 21421 21422 nn_layer_batchnorm_backward(L,IN,learning_mode) = ( 21423 ++L#_nb_samples; 21424 L#_pim = IN#_out - L#_in_mean; 21425 L#_in_mean+=L#_pim/L#_nb_samples; 21426 L#_in_variance+=(IN#_out - L#_in_mean)*L#_pim; 21427 learning_mode&1?( 21428 L#_batch_deriv_gamma+=L#_deriv_out*L#_z; 21429 ); 21430 learning_mode&2?( 21431 L#_batch_deriv_beta+=L#_deriv_out; 21432 ); 21433 IN#_deriv_out = L#_deriv_out*L#_gamma/(1e-9 + L#_sigma); 21434 ); 21435 21436 nn_layer_batchnorm_end_t_backward(L) = ( 21437 L#_in_variance/=L#_nb_samples; 21438 copy(L#_threads_nb_samples[nn_thread],L#_nb_samples); 21439 copy(L#_threads_in_mean[nn_thread*size(L#_in_mean)],L#_in_mean); 21440 copy(L#_threads_in_variance[nn_thread*size(L#_in_variance)],L#_in_variance); 21441 L#_in_mean*=L#_nb_samples; 21442 ); 21443 21444 nn_layer_batchnorm_end_backward(L) = ( 21445 merge(L#_nb_samples,+); 21446 merge(L#_in_mean,+); 21447 merge(L#_threads_nb_samples,+); 21448 merge(L#_threads_in_mean,+); 21449 merge(L#_threads_in_variance,+); 21450 merge(L#_batch_deriv_gamma,+); 21451 merge(L#_batch_deriv_beta,+); 21452 L#_in_mean/=L#_nb_samples; 21453 L#_in_variance = 0; 21454 repeat (nn_nb_threads_used,_k, 21455 L#_in_variance+=L#_threads_nb_samples[_k]* 21456 (L#_threads_in_variance[_k*size(L#_in_variance),size(L#_in_variance)] + 21457 (L#_threads_in_mean[_k*size(L#_in_mean),size(L#_in_variance)] - L#_in_mean)^2); 21458 ); 21459 L#_in_variance/=L#_nb_samples; 21460 ); 21461 21462 nn_layer_batchnorm_update(L,learning_mode) = ( 21463 draw(##L#_ind,L#_in_mean,0,0,0,0,1,h##L#_ind,1,1); # Update batch mean and batch variance 21464 draw(##L#_ind,L#_in_variance,1,0,0,0,1,h##L#_ind,1,1); 21465 !$nn_batch_iteration?( 21466 momentum = isnan(i[##L#_ind,2])?1:0.01; 21467 draw(##L#_ind,L#_in_mean,2,0,0,0,1,h##L#_ind,1,1,momentum); # Global mean and variance 21468 draw(##L#_ind,L#_in_variance,3,0,0,0,1,h##L#_ind,1,1,momentum); 21469 ); 21470 learning_mode&1?( 21471 nn_optimizer_update_layer(L#_gamma,L#_batch_deriv_gamma); 21472 draw(##L#_ind,L#_gamma,4,0,0,0,1,h##L#_ind); 21473 ); 21474 learning_mode&2?( 21475 nn_optimizer_update_layer(L#_beta,L#_batch_deriv_beta); 21476 draw(##L#_ind,L#_beta,5,0,0,0,1,h##L#_ind); 21477 ); 21478 ); 21479 21480 # clone: Duplicate input as two new outputs. 21481 #------------------------------------------- 21482 nn_layer_clone_init_forward(L0,L1,IN) = ( 21483 const L0#_out_width = IN#_out_width; 21484 const L0#_out_height = IN#_out_height; 21485 const L0#_out_depth = IN#_out_depth; 21486 const L0#_out_spectrum = IN#_out_spectrum; 21487 const L1#_out_width = IN#_out_width; 21488 const L1#_out_height = IN#_out_height; 21489 const L1#_out_depth = IN#_out_depth; 21490 const L1#_out_spectrum = IN#_out_spectrum; 21491 ); 21492 21493 nn_layer_clone_forward(L0,L1,IN) = ( 21494 L0#_out = L1#_out = IN#_out; 21495 ); 21496 21497 nn_layer_clone_backward(L0,L1,IN) = ( 21498 IN#_deriv_out = L0#_deriv_out + L1#_deriv_out; 21499 ); 21500 21501 # conv2d: 2D convolutional layer. 21502 #-------------------------------- 21503 nn_layer_conv2d_init_forward(L,IN,size,stride,dilation) = ( 21504 const L#_ind = $L#; 21505 const L#_out_width = max(1,int(IN#_out_width/stride)); 21506 const L#_out_height = max(1,int(IN#_out_height/stride)); 21507 const L#_out_depth = IN#_out_depth; 21508 const L#_out_spectrum = h##L#_ind; 21509 const L#_kernel_size = size; 21510 const L#_kernel_center = L#_kernel_size - 1 - int(L#_kernel_size/2); 21511 const L#_stride = stride; 21512 const L#_dilation = dilation; 21513 21514 L#_weights = crop(##L#_ind,0,0,w##L#_ind - 1,h##L#_ind); 21515 L#_biases = crop(##L#_ind,w##L#_ind - 1,0,1,h##L#_ind); 21516 L#_out = vector(##L#_out_width*L#_out_height*L#_out_depth*h##L#_ind); 21517 ); 21518 21519 nn_layer_conv2d_forward(L,IN) = ( 21520 unref(_sizl); 21521 const _sizl = size(L#_out)/L#_out_spectrum; # Size of output plane 21522 L#_out = convolve(IN#_out, 21523 IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum, 21524 L#_weights, 21525 L#_kernel_size,L#_kernel_size,1,IN#_out_spectrum*L#_out_spectrum, 21526 1,0,2, 21527 L#_kernel_center,L#_kernel_center,0, 21528 0,0,0, 21529 L#_out_width - 1,L#_out_height - 1,L#_out_depth - 1, 21530 L#_stride,L#_stride,1, 21531 L#_dilation,L#_dilation,1); 21532 repeat (L#_out_spectrum,_l, 21533 copy(L#_out[_l*_sizl],L#_biases[_l],_sizl,1,0,-1); # Add biases 21534 ); 21535 ); 21536 21537 nn_layer_conv2d_init_backward(L,IN) = ( 21538 L#_batch_deriv_weights = vector(#size(L#_weights)); 21539 L#_batch_deriv_biases = vector(#size(L#_biases)); 21540 ); 21541 21542 nn_layer_conv2d_backward(L,IN) = ( 21543 unref(_sizk,_sizl,_sizw); 21544 const _sizk = size(IN#_out)/IN#_out_spectrum; # Size of input plane 21545 const _sizl = size(L#_out)/L#_out_spectrum; # Size of output plane 21546 const _sizw = L#_kernel_size^2; # Size of kernel^2 21547 21548 # Compute dL/dxk(x,y). 21549 L#_weights_mirrored = vector(#size(L#_weights)); 21550 repeat (IN#_out_spectrum,_k, 21551 repeat (L#_out_spectrum,_l, 21552 copy(L#_weights_mirrored[_k*L#_out_spectrum*_sizw + _l*_sizw + _sizw - 1], 21553 L#_weights[_l*(w##L#_ind - 1) + _k*_sizw],_sizw,-1,1); 21554 ); 21555 ); 21556 IN#_deriv_out = convolve(L#_deriv_out, 21557 L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 21558 L#_weights_mirrored, 21559 L#_kernel_size,L#_kernel_size,1,L#_out_spectrum*IN#_out_spectrum, 21560 0,0,2, 21561 L#_kernel_size - 1 - L#_kernel_center, 21562 L#_kernel_size - 1 - L#_kernel_center,0, 21563 0,0,0,IN#_out_width - 1,IN#_out_height - 1,IN#_out_depth - 1, 21564 1/L#_stride,1/L#_stride,1, 21565 L#_dilation/L#_stride,L#_dilation/L#_stride,1); 21566 21567 # Compute dL/dbl. 21568 L#_deriv_biases = vector(#size(L#_biases)); 21569 fill(L#_deriv_biases,_l,sum(L#_deriv_out[_l*_sizl,_sizl])); 21570 L#_batch_deriv_biases+=L#_deriv_biases; 21571 21572 # Compute dL/dwlk. 21573 L#_xk_mirrored = vector(#_sizk); 21574 L#_deriv_weights = vector(#size(L#_weights)); 21575 repeat (L#_out_spectrum,_l, 21576 repeat (IN#_out_spectrum,_k, 21577 copy(L#_xk_mirrored[_sizk - 1],IN#_out[_k*_sizk],_sizk,-1,1); 21578 L#_dwlk = convolve(L#_xk_mirrored, 21579 IN#_out_width,IN#_out_height,IN#_out_depth,1, 21580 L#_deriv_out[_l*_sizl,_sizl], 21581 L#_out_width,L#_out_height,L#_out_depth,1, 21582 0,0,1, 21583 1/L#_stride*(IN#_out_width - 1 - L#_dilation*L#_kernel_center), 21584 1/L#_stride*(IN#_out_height - 1 - L#_dilation*L#_kernel_center),0, 21585 0,0,0,L#_kernel_size - 1,L#_kernel_size - 1,0, 21586 L#_dilation,L#_dilation,1, 21587 L#_stride,L#_stride,1); 21588 copy(L#_deriv_weights[_l*(w##L#_ind - 1) + _k*_sizw],L#_dwlk,_sizw); 21589 ); 21590 ); 21591 L#_batch_deriv_weights+=L#_deriv_weights; 21592 ); 21593 21594 nn_layer_conv2d_end_backward(L) = ( 21595 merge(L#_batch_deriv_weights,+); 21596 merge(L#_batch_deriv_biases,+); 21597 L#_batch_deriv_weights/=nn_nb_samples; 21598 L#_batch_deriv_biases/=nn_nb_samples; 21599 ); 21600 21601 nn_layer_conv2d_update(L) = ( 21602 nn_optimizer_update_layer(L#_weights,L#_batch_deriv_weights); 21603 nn_optimizer_update_layer(L#_biases,L#_batch_deriv_biases); 21604 draw(##L#_ind,L#_weights,0,0,0,0,w##L#_ind - 1,h##L#_ind); 21605 draw(##L#_ind,L#_biases,w##L#_ind - 1,0,0,0,1,h##L#_ind); 21606 ); 21607 21608 # fc: Fully-connected layer. 21609 #--------------------------- 21610 nn_layer_fc_init_forward(L) = ( 21611 const L#_ind = $L#; 21612 const L#_out_width = 1; 21613 const L#_out_height = 1; 21614 const L#_out_depth = 1; 21615 const L#_out_spectrum = h##L#_ind; 21616 21617 L#_weights = crop(##L#_ind,0,0,w##L#_ind - 1,h##L#_ind); 21618 L#_biases = crop(##L#_ind,w##L#_ind - 1,0,1,h##L#_ind); 21619 L#_out = vector(#h##L#_ind); 21620 ); 21621 21622 nn_layer_fc_forward(L,IN) = ( 21623 L#_out = mul(L#_weights,IN#_out); 21624 L#_out+=L#_biases; 21625 ); 21626 21627 nn_layer_fc_init_backward(L) = ( 21628 L#_batch_deriv_weights = vector(#size(L#_weights)); 21629 L#_batch_deriv_biases = vector(#size(L#_biases)); 21630 ); 21631 21632 nn_layer_fc_backward(L,IN) = ( 21633 IN#_deriv_out = mul(transpose(L#_weights,size(IN#_out)),L#_deriv_out); 21634 L#_deriv_weights = mul(L#_deriv_out,IN#_out,size(IN#_out)); 21635 L#_batch_deriv_weights+=L#_deriv_weights; 21636 L#_batch_deriv_biases+=L#_deriv_out; 21637 ); 21638 21639 nn_layer_fc_end_backward(L) = ( 21640 merge(L#_batch_deriv_weights,+); 21641 merge(L#_batch_deriv_biases,+); 21642 L#_batch_deriv_weights/=nn_nb_samples; 21643 L#_batch_deriv_biases/=nn_nb_samples; 21644 ); 21645 21646 nn_layer_fc_update(L) = ( 21647 nn_optimizer_update_layer(L#_weights,L#_batch_deriv_weights); 21648 nn_optimizer_update_layer(L#_biases,L#_batch_deriv_biases); 21649 draw(##L#_ind,L#_weights,0,0,0,0,w##L#_ind - 1,h##L#_ind); 21650 draw(##L#_ind,L#_biases,w##L#_ind - 1,0,0,0,1,h##L#_ind); 21651 ); 21652 21653 # input: Input image or vector data. 21654 #----------------------------------- 21655 nn_layer_input_init_forward(L,w,h,d,s) = ( 21656 const L#_out_width = w; 21657 const L#_out_height = h; 21658 const L#_out_depth = d; 21659 const L#_out_spectrum = s; 21660 ref(#L,L#_out); 21661 ); 21662 21663 # maxpool2d : 2D max pooling. 21664 #---------------------------- 21665 nn_layer_maxpool2d_init_forward(L,IN) = ( 21666 const L#_out_width = int(IN#_out_width/2); 21667 const L#_out_height = int(IN#_out_height/2); 21668 const L#_out_depth = IN#_out_depth; 21669 const L#_out_spectrum = IN#_out_spectrum; 21670 nn_avgpool2d_kernel_forward = [ 0.25,0.25,0.25,0.25 ]; 21671 nn_avgpool2d_kernel_backward = [ 1,0,0,0 ]; 21672 ); 21673 21674 nn_layer_maxpool2d_forward(L,IN) = ( 21675 L#_out = vector(##L#_out_width*L#_out_height*L#_out_depth*L#_out_spectrum); 21676 L#_from = vector(#size(L#_out)); 21677 repeat (size(L#_out),_l, 21678 _x = _l%L#_out_width; 21679 _y = int(_l/L#_out_width)%L#_out_height; 21680 _z = int(_l/(L#_out_width*L#_out_height))%L#_out_depth; 21681 _c = int(_l/(L#_out_width*L#_out_height*L#_out_depth)); 21682 _k = 2*_x + IN#_out_width*(2*_y + IN#_out_height*(_z + IN#_out_depth*_c)); 21683 _k+=arg0(argmax([ IN#_out[_k,2],IN#_out[_k + IN#_out_width,2] ]),0,1,IN#_out_width,IN#_out_width + 1); 21684 L#_from[_l] = _k; 21685 L#_out[_l] = IN#_out[_k]; 21686 ); 21687 ); 21688 21689 nn_layer_maxpool2d_backward(L,IN) = ( 21690 IN#_deriv_out = vector(#size(IN#_out),0); 21691 repeat (size(L#_out),_l, 21692 IN#_deriv_out[L#_from[_l]] = L#_deriv_out[_l]; 21693 ); 21694 ); 21695 21696 # nl: Non-linearity. 21697 #------------------- 21698 nn_layer_nl_init_forward(L,IN) = ( 21699 const L#_out_width = IN#_out_width; 21700 const L#_out_height = IN#_out_height; 21701 const L#_out_depth = IN#_out_depth; 21702 const L#_out_spectrum = IN#_out_spectrum; 21703 21704 L#_out = vector(#size(IN#_out)); 21705 ); 21706 21707 nn_layer_nl_forward(L,IN,activation) = ( 21708 L#_out = IN#_out; 21709 nn_activate(L#_out,#activation); 21710 ); 21711 21712 nn_layer_nl_backward(L,IN,activation) = ( 21713 IN#_deriv_out = IN#_out; 21714 nn_activate(IN#_deriv_out,deriv_#activation); 21715 IN#_deriv_out*=L#_deriv_out; 21716 ); 21717 21718 # rename: Rename input. 21719 #---------------------- 21720 nn_layer_rename_init_forward(L,IN) = ( 21721 const L#_out_width = IN#_out_width; 21722 const L#_out_height = IN#_out_height; 21723 const L#_out_depth = IN#_out_depth; 21724 const L#_out_spectrum = IN#_out_spectrum; 21725 ref(IN#_out,L#_out); 21726 ); 21727 21728 nn_layer_rename_backward(L,IN) = ( 21729 ref(L#_deriv_out,IN#_deriv_out); 21730 ); 21731 21732 # reshape: Reshape input to output with compatible size. 21733 #------------------------------------------------------- 21734 nn_layer_reshape_init_forward(L,IN,w,h,d,s) = ( 21735 const L#_out_width = w; 21736 const L#_out_height = h; 21737 const L#_out_depth = d; 21738 const L#_out_spectrum = s; 21739 ref(IN#_out,L#_out); 21740 ); 21741 21742 nn_layer_reshape_init_backward(L,IN) = ( 21743 ref(L#_deriv_out,IN#_deriv_out); 21744 ); 21745 21746 # # softmax : Compute the softmax function. 21747 # #---------------------------------------- 21748 # nn_layer_softmax_init_forward(L,IN) = ( 21749 # const L#_out_width = IN#_out_width; 21750 # const L#_out_height = IN#_out_height; 21751 # const L#_out_depth = IN#_out_depth; 21752 # const L#_out_spectrum = IN#_out_spectrum; 21753 # ); 21754 21755 # nn_layer_softmax_forward(L,IN) = ( 21756 # L#_out = exp(IN#_out - max(IN#_out)); 21757 # L#_sum = resize(correlate(L#_out,L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 21758 # [ 1 ],1,1,1,1, 21759 # 0,0,3),size(L#_out),0,2); 21760 # L#_out/=L#_sum; 21761 # ); 21762 21763 # nn_layer_softmax_backward(L,IN) = ( 21764 # IN#_deriv_out = L#_deriv_out; # TODO ! 21765 # ); 21766 21767 # split: Split input as two outputs. 21768 #----------------------------------- 21769 nn_layer_split_init_forward(L0,L1,IN,nb_channels0) = ( 21770 const L0#_out_width = IN#_out_width; 21771 const L0#_out_height = IN#_out_height; 21772 const L0#_out_depth = IN#_out_depth; 21773 const L0#_out_spectrum = nb_channels0; 21774 const L1#_out_width = IN#_out_width; 21775 const L1#_out_height = IN#_out_height; 21776 const L1#_out_depth = IN#_out_depth; 21777 const L1#_out_spectrum = IN#_out_spectrum - nb_channels0; 21778 ); 21779 21780 nn_layer_split_forward(L0,L1,IN) = ( 21781 unref(_siz0); 21782 const siz0 = L0#_out_width*L0#_out_height*L0#_out_depth*L0#_out_spectrum; 21783 L0#_out = IN#_out[0,siz0]; 21784 L1#_out = IN#_out[siz0,L1#_out_width*L1#_out_height*L1#_out_depth*L1#_out_spectrum]; 21785 ); 21786 21787 nn_layer_split_backward(L0,L1,IN) = ( 21788 IN#_deriv_out = vector(#size(IN#_out)); 21789 copy(IN#_deriv_out,L0#_deriv_out,size(L0#_out)); 21790 copy(IN#_deriv_out[size(L0#_out)],L1#_deriv_out,size(L1#_out)); 21791 ); 21792 21793 # upsample2d : 2D upsampling. 21794 #---------------------------- 21795 nn_layer_upsample2d_init_forward(L,IN) = ( 21796 const L#_out_width = 2*IN#_out_width; 21797 const L#_out_height = 2*IN#_out_height; 21798 const L#_out_depth = IN#_out_depth; 21799 const L#_out_spectrum = IN#_out_spectrum; 21800 nn_upsample2d_kernel_forward = [ 1,0,0,0 ]; 21801 nn_upsample2d_kernel_backward = [ 0.25,0.25,0.25,0.25 ]; 21802 ); 21803 21804 nn_layer_upsample2d_forward(L,IN,interpolation) = ( 21805 L#_out = correlate(IN#_out, 21806 IN#_out_width,IN#_out_height,IN#_out_depth,IN#_out_spectrum, 21807 nn_upsample2d_kernel_forward,2,2,1,1, 21808 1,0,1, 21809 0,0,0, 21810 0,0,0, 21811 L#_out_width - 1,L#_out_height - 1,L#_out_depth - 1, 21812 0.5,0.5,1, 21813 1,1,1, 21814 interpolation); 21815 ); 21816 21817 nn_layer_upsample2d_backward(L,IN) = ( 21818 IN#_deriv_out = correlate(L#_deriv_out, 21819 L#_out_width,L#_out_height,L#_out_depth,L#_out_spectrum, 21820 nn_upsample2d_kernel_backward,2,2,1,1, 21821 0,0,1, 21822 0,0,0, 21823 0,0,0, 21824 IN#_out_width - 1,IN#_out_height - 1,IN#_out_depth - 1, 21825 2,2,1, 21826 1,1,1, 21827 0); 21828 ); 21829 21830 #---------------- 21831 # Loss functions. 21832 #---------------- 21833 21834 # mse : Mean-squared error. 21835 #-------------------------- 21836 nn_loss_mse_init_backward(L) = ( 21837 L#_batch_out = 0; 21838 ); 21839 21840 nn_loss_mse_backward(L,IN,TRUTH) = ( 21841 IN#_deriv_out = 2*(IN#_out - TRUTH); 21842 L#_out = norm(IN#_deriv_out/2)^2/size(IN#_deriv_out); 21843 L#_batch_out+=L#_out; 21844 ); 21845 21846 nn_loss_mse_end_backward(L) = ( 21847 merge(L#_batch_out,+); 21848 L#_batch_out/=nn_nb_samples; 21849 L#_out = L#_batch_out; 21850 ); 21851 21852 nn_loss_mse_update(L,is_adaptive_learning_rate) = ( 21853 const L#_ind = $L#; 21854 L#_iteration = i[##L#_ind,0]; 21855 L#_learning_rate = i[##L#_ind,1]; 21856 L#_previous_out = i[##L#_ind,2]; 21857 L#_trend_moment = i[##L#_ind,3]; 21858 L#_nb_decreases = i[##L#_ind,4]; 21859 L#_nb_increases = i[##L#_ind,5]; 21860 is_adaptive_learning_rate?nn_optimizer_update_learning_rate(#L); 21861 copy(i[##L#_ind,0],[ L#_iteration + 1,L#_learning_rate,L#_out,L#_trend_moment,L#_nb_decreases,L#_nb_increases ]); 21862 nn_learning_rate = L#_learning_rate; 21863 ); 21864 " 21865 21866#@cli nn_init 21867#@cli : Initialize a new network. 21868nn_init : 21869 e[^-1] "[nn_lib] Initialize new network." 21870 _nn_forward,_nn_backward,_nn_parameters,_nn_iteration,_nn_batch_iteration,_nn_is_training,_nn_optimizer= 21871 _nn_init="$0 " 21872 _nn_update="end(nn_update());" 21873 21874#@cli nn_check_layer : name 21875#@cli : Check that the layer with specified name exists in the network. 21876nn_check_layer : 21877 if !${"is_variable_name $1"} 21878 error[0--3] "nn_check_layer: Invalid layer name '$1'." 21879 elif narg($_nn_$1_out_size)!=4 21880 error[0--3] "nn_check_layer: Layer with name '$1' does not exist." 21881 fi 21882 21883#@cli nn_save : 'filename.gmz' 21884#@cli : Save current network as a .gmz file. 21885#@cli : Neural network files can be only saved in .gmz format. 21886nn_save : check "s=['$1']; find(s,'.gmz')==size(s) - 4" 21887 e[^-1] "[nn_lib] Save current network as file '$1'." 21888 ('$_nn_parameters') autocrop. {','} sel={t} rm. 21889 ('$_nn_init') autocrop. {'" "'} 21890 nm. _nn_init 21891 o[$sel,-1] "$1" 21892 rm. 21893 21894#@cli nn_load : 'filename.gmz' 21895#@cli : Load and initialize network saved as a .gmz file. 21896#@cli : Neural network files can be only loaded in .gmz format. 21897nn_load : check "s=['$1']; find(s,'.gmz')==size(s) - 4" 21898 e[^-1] "[nn_lib] Load network from file '$1'." 21899 i "$1" run {t} rm. 21900 21901#@cli nn_layer_input : name,width,_height,_depth,_spectrum 21902#@cli : Add an 'input' layer to the network. 21903#@cli : Default values: 'height=1', 'depth=1' and 'spectrum=1'. 21904nn_layer_input : check ${"is_variable_name $1"}" && isint($2) && $2>0 && isint(${3=1}) && $3>0 && "\ 21905 "isint(${4=1}) && $4>0 && isint(${5=1}) && $5>0" 21906 e[^-1] "[nn_lib] Add input layer '$1', with size ($2,$3,$4,$5)." 21907 _nn_$1_out_size=$2,$3,$4,$5 21908 _nn_forward.="begin(nn_layer_input_init_forward($1,$2,$3,$4,$5));" 21909 _nn_init.="$0 $* " 21910 21911#@cli nn_layer_add : name,in0,in1 21912#@cli : Add an 'add' layer to the network. 21913nn_layer_add : nn_check_layer "$2" nn_check_layer "$3" 21914 check ${"is_variable_name $1"}" && [$_nn_$2_out_size]==[$_nn_$3_out_size]" 21915 e[^-1] "[nn_lib] Add 'add' layer '$1', with inputs '$2' and '$3'." 21916 _nn_$1_out_size=$_nn_$2_out_size 21917 _nn_forward.="begin(nn_layer_add_init_forward($1,$2));"\ 21918 "nn_layer_add_forward($1,$2,$3);" 21919 _nn_backward..="nn_layer_add_backward($1,$2,$3);" 21920 _nn_init.="$0 $* " 21921 21922#@cli nn_layer_append : name,in0,in1 21923#@cli : Add an 'append' layer to the network. 21924nn_layer_append : nn_check_layer "$2" nn_check_layer "$3" check ${"is_variable_name $1"} 21925 e[^-1] "[nn_lib] Add 'append' layer '$1', with inputs '$2' and '$3'." 21926 if s1=[$_nn_$2_out_size];s2=[$_nn_$3_out_size];s1[0,3]!=s2[0,3] 21927 error "nn_layer_append: Cannot append inputs $2("$_nn_$2_out_size") and $3("$_nn_$3_out_size") together." 21928 fi 21929 _nn_$1_out_size={[$_nn_$2_out_size]+[0,0,0,[$_nn_$3_out_size][3]]} 21930 _nn_forward.="begin(nn_layer_append_init_forward($1,$2,$3));"\ 21931 "nn_layer_append_forward($1,$2,$3);" 21932 _nn_backward..="nn_layer_append_backward($1,$2,$3);" 21933 _nn_init.="$0 $* " 21934 21935#@cli nn_layer_avgpool2d : name,in 21936#@cli : Add a 'avgpool2d' layer (2d average pooling) to the network. 21937nn_layer_avgpool2d : nn_check_layer "$2" check ${"is_variable_name $1"} 21938 e[^-1] "[nn_lib] Add 'avgpool2d' layer '$1', with input '$2'." 21939 _nn_$1_out_size={s=[$_nn_$2_out_size];[int(s[0,2]/2),s[2,2]]} 21940 _nn_forward.="begin(nn_layer_avgpool2d_init_forward($1,$2));"\ 21941 "nn_layer_avgpool2d_forward($1,$2);" 21942 _nn_backward..="nn_layer_avgpool2d_backward($1,$2);" 21943 _nn_init.="$0 $* " 21944 21945#@cli nn_layer_batchnorm : name,in,learning_mode. 21946#@cli : Add a 'batchnorm' layer to the network. 21947#@cli : 'learning_mode' can be { 0=no parameters learnt | 1=gamma-only | 2=beta-only | 3=gamma & beta}. 21948nn_layer_batchnorm : nn_check_layer "$2" check ${"is_variable_name $1"}" && isint(${3=0}) && inrange($3,0,3)" 21949 s0,s1,s2,s3="no parameters","gamma-only","beta-only","gamma & beta" 21950 e[^-1] "[nn_lib] Add 'batchnorm' layer '$1' to the network, with input '$2' and learning mode '"${s$3}"'." 21951 _nn_$1_out_size=$_nn_$2_out_size 21952 if !isint($$1) 6,{prod($_nn_$2_out_size)} f. nan,nan,nan,nan,1,0 nm. $1 fi 21953 _nn_forward.="begin(nn_layer_batchnorm_init_forward($1,$2));"\ 21954 "nn_layer_batchnorm_forward($1,$2);" 21955 _nn_backward..="begin(nn_layer_batchnorm_init_backward($1,$2));"\ 21956 "nn_layer_batchnorm_backward($1,$2,$3);"\ 21957 "end_t(nn_layer_batchnorm_end_t_backward($1));"\ 21958 "end(nn_layer_batchnorm_end_backward($1));" 21959 _nn_update..="end(nn_layer_batchnorm_update($1,$3));" 21960 _nn_init.="$0 $* " 21961 _nn_parameters.="$1," 21962 21963#@cli nn_layer_clone : name0,name1,in 21964#@cli : Add a 'clone' layer to the network. 21965nn_layer_clone : nn_check_layer "$3" check ${"is_variable_name $1"}" && "${"is_variable_name $2"} 21966 e[^-1] "[nn_lib] Add 'clone' layer with input '$3' and outputs '$1' and '$2'." 21967 _nn_$1_out_size=$_nn_$3_out_size 21968 _nn_$2_out_size=$_nn_$3_out_size 21969 _nn_forward.="begin(nn_layer_clone_init_forward($1,$2,$3));"\ 21970 "nn_layer_clone_forward($1,$2,$3);" 21971 _nn_backward..="nn_layer_clone_backward($1,$2,$3);" 21972 _nn_init.="$0 $* " 21973 21974#@cli nn_layer_conv2d : name,in,nb_channels>0,_kernel_size>0,_stride>0,_dilation>0 21975#@cli : Add a 'conv2d' layer (2D convolutional layer) to the network. 21976#@cli : Default values: 'kernel_size=3', 'stride=1' and 'dilation=1'. 21977nn_layer_conv2d : nn_check_layer "$2" 21978 check ${"is_variable_name $1"}" && isint($3) && $3>0 && isint(${4=3}) && $4>0 && ${5=1}>0" 21979 skip "${6=1}" 21980 e[^-1] "[nn_lib] Add 'conv2d' layer '$1', with input '$2', $3 channels, $4x$4 kernels, stride $5 and dilation $6." 21981 _nn_$1_out_size={s=[$_nn_$2_out_size];[max(1,int(s[0]/$5)),max(1,int(s[1]/$5)),s[2],$3]} 21982 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 21983 _nn_forward.="begin(nn_layer_conv2d_init_forward($1,$2,$4,$5,$6));"\ 21984 "nn_layer_conv2d_forward($1,$2);" 21985 _nn_backward..="begin(nn_layer_conv2d_init_backward($1,$2));"\ 21986 "nn_layer_conv2d_backward($1,$2);"\ 21987 "end(nn_layer_conv2d_end_backward($1));" 21988 _nn_update..="end(nn_layer_conv2d_update($1));" 21989 _nn_init.="$0 $* " 21990 _nn_parameters.="$1," 21991 21992#@cli nn_layer_conv2dnl : name,in,nb_channels>0,_kernel_size>0,_stride>0,_dilation>0,_activation 21993#@cli : Add a 'con2dnl' (2D convolutional layer followed by a non-linearity), to the network. 21994#@cli : Default values: 'kernel_size=3', 'stride=1', 'dilation=1' and 'activation=leakyrelu'. 21995nn_layer_conv2dnl : nn_check_layer "$2" 21996 check ${"is_variable_name $1"}" && isint($3) && $3>0 && isint(${4=3}) && $4>0 && ${5=1}>0" 21997 skip "${6=1}","${7=leakyrelu}" 21998 e[^-1] "[nn_lib] Add 'conv2d+nl' layer '$1', with input '$2', $3 channels, $4x$4 kernels, "\ 21999 "stride $5, dilation $6 and '$7' activation." 22000 nn_layer_conv2d $1_0,$2,$3,$4,$5,$6 22001 nn_layer_nl $1,$1_0,$7 22002 22003#@cli nn_layer_fc : name,in,nb_channels>0 22004#@cli : Add a 'fc' layer (fully connected layer) to the network. 22005nn_layer_fc : nn_check_layer "$2" check ${"is_variable_name $1"}" && isint($3) && $3>0" 22006 e[^-1] "[nn_lib] Add 'fc' layer '$1', with input '$2' and $3 channels." 22007 _nn_$1_out_size=1,1,1,$3 22008 if !isint($$1) {prod($_nn_$2_out_size)+1},$3 f. 4*g/(w-1) nm. $1 fi 22009 _nn_forward.="begin(nn_layer_fc_init_forward($1));"\ 22010 "nn_layer_fc_forward($1,$2);" 22011 _nn_backward..="begin(nn_layer_fc_init_backward($1));"\ 22012 "nn_layer_fc_backward($1,$2);"\ 22013 "end(nn_layer_fc_end_backward($1));" 22014 _nn_update..="end(nn_layer_fc_update($1));" 22015 _nn_init.="$0 $* " 22016 _nn_parameters.="$1," 22017 22018#@cli nn_layer_fcnl : name,in,nb_neurons>0,_activation 22019#@cli : Add a 'fcnl' layer (fully connected layer followed by a non-linearity), to the network. 22020#@cli : Default value: 'activation=leakyrelu'. 22021nn_layer_fcnl : nn_check_layer "$2" check ${"is_variable_name $1"}" && isint($3) && $3>0" skip ${4=leakyrelu} 22022 e[^-1] "[nn_lib] Add 'fc+nl' layer '$1' to the network, with input '$2', $3 channels and '$4' activation." 22023 nn_layer_fc $1_0,$2,$3 22024 nn_layer_nl $1,$1_0,$4 22025 22026#@cli nn_layer_maxpool2d : name,in 22027#@cli : Add a 'maxpool2d' layer (2d max pooling) to the network. 22028nn_layer_maxpool2d : nn_check_layer "$2" check ${"is_variable_name $1"} 22029 e[^-1] "[nn_lib] Add 'maxpool2d' layer '$1', with input '$2'." 22030 _nn_$1_out_size={s=[$_nn_$2_out_size];[int(s[0,2]/2),s[2,2]]} 22031 _nn_forward.="begin(nn_layer_maxpool2d_init_forward($1,$2));"\ 22032 "nn_layer_maxpool2d_forward($1,$2);" 22033 _nn_backward..="nn_layer_maxpool2d_backward($1,$2);" 22034 _nn_init.="$0 $* " 22035 22036#@cli nn_layer_nl : name,in,activation 22037#@cli : Add a 'nl' layer (non-linearity) to the network. 22038#@cli : Default value: 'activation=leakyrelu'. 22039nn_layer_nl : nn_check_layer "$2" check ${"is_variable_name $1"} skip ${3=leakyrelu} 22040 e[^-1] "[nn_lib] Add 'nl' layer '$1', with input '$2' and '$3' activation." 22041 _nn_$1_out_size=$_nn_$2_out_size 22042 _nn_forward.="begin(nn_layer_nl_init_forward($1,$2));"\ 22043 "nn_layer_nl_forward($1,$2,$3);" 22044 _nn_backward..="nn_layer_nl_backward($1,$2,$3);" 22045 _nn_init.="$0 $* " 22046 22047#@cli nn_layer_rename : name,in 22048#@cli : Add a 'rename' layer to the network. 22049nn_layer_rename : nn_check_layer "$2" check ${"is_variable_name $1"} 22050 e[^-1] "[nn_lib] Add 'rename' layer '$1', with input '$2'." 22051 _nn_$1_out_size=$_nn_$2_out_size 22052 _nn_forward.="begin(nn_layer_rename_init_forward($1,$2));" 22053 _nn_backward..="nn_layer_rename_backward($1,$2);" 22054 _nn_init.="$0 $* " 22055 22056#@cli nn_layer_reshape : name,in,width>0,height>0,depth>0,spectrum>0 22057#@cli : Add a 'reshape' layer to the network. 22058nn_layer_reshape : nn_check_layer "$2" check ${"is_variable_name $1"} 22059 e[^-1] "[nn_lib] Add 'reshape' layer '$1', with input '$2' and size ($3,$4,$5,$6)." 22060 _nn_$1_out_size=$3,$4,$5,$6 22061 if prod($_nn_$1_out_size)!=prod($_nn_$2_out_size) 22062 error "nn_layer_reshape: Cannot reshape input ("$_nn_$2_out_size") to output ("$_nn_$1_out_size")." 22063 fi 22064 _nn_forward.="begin(nn_layer_reshape_init_forward($1,$2,$3,$4,$5,$6));" 22065 _nn_backward..="begin(nn_layer_reshape_init_backward($1,$2));" 22066 _nn_init.="$0 $* " 22067 22068# #@cli nn_layer_softmax : name,in 22069# #@cli : Add a 'softmax' layer to the network. 22070# nn_layer_softmax : nn_check_layer "$2" check ${"is_variable_name $1"} 22071# e[^-1] "[nn_lib] Add 'softmax' layer '$1', with input '$2'." 22072# _nn_$1_out_size=$_nn_$2_out_size 22073# _nn_forward.="begin(nn_layer_softmax_init_forward($1,$2));"\ 22074# "nn_layer_softmax_forward($1,$2);" 22075# _nn_backward..="nn_layer_softmax_backward($1,$2);" 22076# _nn_init.="$0 $* " 22077 22078#@cli nn_layer_split : name0,name1,in,nb_channels0 22079#@cli : Add a 'split' layer to the network. 22080nn_layer_split : nn_check_layer "$3" check ${"is_variable_name $1"}" && "${"is_variable_name $2"} 22081 e[^-1] "[nn_lib] Add 'split' layer, with input '$3' and outputs '$1' and '$2'." 22082 _nn_$1_out_size={[[$_nn_$3_out_size][0,3],$4]} 22083 _nn_$2_out_size={[$_nn_$3_out_size]-[0,0,0,$4]} 22084 _nn_forward.="begin(nn_layer_split_init_forward($1,$2,$3,$4));"\ 22085 "nn_layer_split_forward($1,$2,$3);" 22086 _nn_backward..="nn_layer_split_backward($1,$2,$3);" 22087 _nn_init.="$0 $* " 22088 22089#@cli nn_layer_upsample2d : name,in,_interpolation_type = { 0=nearest-neighbor | 1=linear } 22090#@cli : Add a 'upsample2d' layer to the network. 22091nn_layer_upsample2d : nn_check_layer "$2" check ${"is_variable_name $1"}" && isbool(${3=0})" 22092 e[^-1] "[nn_lib] Add 'upsample2d' layer '$1', with input '$2'." 22093 _nn_$1_out_size={s=[$_nn_$2_out_size];[2*s[0,2],s[2,2]]} 22094 _nn_forward.="begin(nn_layer_upsample2d_init_forward($1,$2));"\ 22095 "nn_layer_upsample2d_forward($1,$2,$3);" 22096 _nn_backward..="nn_layer_upsample2d_backward($1,$2);" 22097 _nn_init.="$0 $* " 22098 22099#@cli nn_loss_mse : name,in,ground_truth,_learning_rate,_is_adaptive_learning_rate={ 0=false | 1=true } 22100#@cli : Add a 'mse' loss to the network. 22101#@cli : Default value: 'learning_rate=1e-6' and 'is_adaptive_learning_rate=1'. 22102nn_loss_mse : nn_check_layer "$2" check ${"is_variable_name $1"}" && "${"is_variable_name $3"}" && "\ 22103 "${4=1e-6}>0 && isbool(${5=1})" 22104 s0,s1=fixed,adaptive 22105 e[^-1] "[nn_lib] Add 'mse' loss '$1', with input '$2', ground truth '$3' and "${s$5}" learning rate $4." 22106 _nn_$1_out_size=1,1,1,1 22107 if !isint($$1) 22108 # (iteration,learning_rate,previous_out,trend_moment,nb_decreases,nb_increases) 22109 (0,$4,inf,0,0,0) nm. $1 22110 fi 22111 _nn_backward..="begin(nn_loss_mse_init_backward($1));"\ 22112 "nn_loss_mse_backward($1,$2,$3);"\ 22113 "end(nn_loss_mse_end_backward($1));" 22114 _nn_update..="end(nn_loss_mse_update($1,$5));" 22115 _nn_init.="$0 $* " 22116 _nn_parameters.="$1," 22117 22118#---------------------------------- 22119# 22120#@cli :: Arrays, Tiles and Frames 22121# 22122#---------------------------------- 22123 22124#@cli array : M>0,_N>0,_expand_type={ 0=min | 1=max | 2=all } 22125#@cli : Create MxN array from selected images. 22126#@cli : Default values: 'N=M' and 'expand_type=0'. 22127#@cli : $ image.jpg array 3,2,2 22128array : check "isint($1) && $1>0 && isint(${2=$1}) && $2>0" skip ${3=0} 22129 e[^-1] "Create $1x$2 array from image$?, with expand type $3." 22130 r0={100/max($1,$2)} r1={100/min($1,$2)} r2=100 22131 r ${r$3}%,${r$3}%,1,100%,2 r {$1*100}%,{$2*100}%,1,100%,0,2 22132 22133#@cli array_fade : M>0,_N>0,0<=_fade_start<=100,0<=_fade_end<=100,_expand_type={0=min | 1=max | 2=all} 22134#@cli : Create MxN array from selected images. 22135#@cli : Default values: 'N=M', 'fade_start=60', 'fade_end=90' and 'expand_type=1'. 22136#@cli : $ image.jpg array_fade 3,2 22137array_fade : skip ${2=$1},${3=60},${4=90},${5=1} 22138 e[^-1] "Create $1x$2 array of ($3%,$4%) faded tiles from image$?, with expand type $5." 22139 repeat $! l[$>] . shift.. {round(w/2)},{round(h/2)},1,1,2 fade_diamond $3,$4 endl done 22140 array $1,$2,$5 22141 22142#@cli array_mirror : N>=0,_dir={ 0=x | 1=y | 2=xy | 3=tri-xy },_expand_type={ 0 | 1 } 22143#@cli : Create 2^Nx2^N array from selected images. 22144#@cli : Default values: 'dir=2' and 'expand_type=0'. 22145#@cli : $ image.jpg array_mirror 2 22146array_mirror : skip ${2=2},${3=0} 22147 e[^-1] "Create a 2^$1x2^$1 mirrored-array from image$?, with expand type $2." 22148 repeat $1 22149 if $3==0 22150 if $2>=3 r 33%,33%,100%,100%,2 22151 else r 50%,50%,100%,100%,2 22152 fi 22153 fi 22154 repeat $! l[$>] 22155 if $2==0 +mirror x a x 22156 elif $2==1 +mirror y a y 22157 else +mirror x a x +mirror y a y if $2==3 r 150%,150%,1,100%,0,2,1,1 fi 22158 fi 22159 endl done 22160 done 22161 22162#@cli array_random : Ms>0,_Ns>0,_Md>0,_Nd>0 22163#@cli : Create MdxNd array of tiles from selected MsxNs source arrays. 22164#@cli : Default values: 'Ns=Ms', 'Md=Ms' and 'Nd=Ns'. 22165#@cli : $ image.jpg +array_random 8,8,15,10 22166array_random : skip ${2=$1},${3=$1},${4=$2} 22167 e[^-1] "Create $3x$4 array of tiles from $1x$2 array$?." 22168 repeat $! l[$>] nm={0,n} 22169 split_tiles $1,$2 22170 repeat $3 repeat $4 [{u($1*$2-1)}] done done 22171 rm[0-{$1*$2-1}] append_tiles $3,$4 22172 nm $nm endl done 22173 22174#@cli frame : eq. to 'frame_xy'. 22175frame : skip ${2=$1}>=0,${3=255},${4=$3},${5=$4},${6=255} 22176 _gmic_s="$?" v + _frame_xy ${1--1} 22177 22178#@cli frame_blur : _sharpness>0,_size>=0,_smoothness,_shading,_blur 22179#@cli : Draw RGBA-colored round frame in selected images. 22180#@cli : Default values: 'sharpness=10', 'size=30', 'smoothness=0', 'shading=1' and 'blur=3%'. 22181#@cli : $ image.jpg frame_blur 3,30,8,10% 22182frame_blur : skip ${1=10},${2=30},${3=0},${4=1},${5=3%} 22183 e[^-1] "Draw round frame on image$?, with sharpness $1, size $2, smoothness $3, shading $4 and blur $5." 22184 to_rgba repeat $! l[$>] nm={0,n} 22185 100%,100%,1,1,"-(abs(x/w-0.5)^$1 + abs(y/h-0.5)^$1)^(1/$1)" >=. $2% 22186 if $4 distance. 1 n. 0,1 *. -1 +. 1 ^. {1/$4} fi 22187 b. $3 +b.. $5 mv. -3 blend_fade[0,1] . rm. 22188 nm $nm endl done 22189 22190#@cli frame_cube : _depth>=0,_centering_x,_centering_y,_left_side={0=normal | 1=mirror-x | 2=mirror-y | 3=mirror-xy},\ 22191# _right_side,_lower_side,_upper_side 22192#@cli : Insert 3D frames in selected images. 22193#@cli : Default values: 'depth=1', 'centering_x=centering_y=0' and 'left_side=right_side,lower_side=upper_side=0'. 22194#@cli : $ image.jpg frame_cube , 22195frame_cube : check "${1=1}>=0" skip ${2=0},${3=0},${4=0},${5=0},${6=0},${7=0} 22196 e[^-1] "Insert 3D frame in image$?, with depth $1, centering point ($2,$3) and orientations (${4--1})." 22197 repeat $! l[$>] nm={0,n} split_opacity 22198 if $!==2 frame_cube ${1--1} a c # Manage image with alpha-channel. 22199 else 22200 m={max(w,h)} w={w} h={h} s={s} 22201 imageplane3d c3d /3d. $w,$h,1 22202 +_frame_cube[0] $4 r3d. 0,1,0,-90 +3d. -0.5,0,-0.5 # Left side. 22203 +_frame_cube[0] $5 r3d. 0,1,0,90 +3d. 0.5,0,-0.5 # Right side. 22204 +_frame_cube[0] $6 r3d. 1,0,0,-90 +3d. 0,0.5,-0.5 # Lower side. 22205 +_frame_cube[0] $7 r3d. 1,0,0,90 +3d. 0,-0.5,-0.5 # Upper side. 22206 +3d 0,0,1 +3d *3d $w,$h,$m # Append sides together. 22207 f=1000 22208 cx=$2*$w/2*($f+$m*$1)/$f 22209 cy=$3*$h/2*($f+$m*$1)/$f 22210 s3d r[2] 3,{{2,h}/3},1,1,-1 22211 f[2] "if(i(2,y)<0.5,i,i+if(x==0,"$cx",if(x==1,"$cy",($1-1)*"$m")))" 22212 y[2] a y 22213 *3d 2 {2*$w},{2*$h},1,$s f3d {2*$f} 22214 j3d. ..,50%,50%,0,1,2,0,0 rm.. 22215 r $w,$h,1,100%,2 22216 fi 22217 nm $nm endl done 22218 22219_frame_cube : 22220 if $1==1 r3d. 0,1,0,180 rv3d. 22221 elif $1==2 r3d. 1,0,0,180 rv3d. 22222 elif $1==3 r3d. 0,0,1,180 22223 fi 22224 22225#@cli frame_fuzzy : size_x[%]>=0,_size_y[%]>=0,_fuzzyness>=0,_smoothness[%]>=0,_R,_G,_B,_A 22226#@cli : Draw RGBA-colored fuzzy frame in selected images. 22227#@cli : Default values: 'size_y=size_x', 'fuzzyness=5', 'smoothness=1' and 'R=G=B=A=255'. 22228#@cli : $ image.jpg frame_fuzzy 20 22229frame_fuzzy : skip ${2=$1},${3=5},${4=1},${5=255},${6=$5},${7=$6},${8=255} 22230 e[^-1] "Draw $1x$2 fuzzy frame on image$?, with fuzzyness $3, smoothness $4 and RGBA color ($5,$6,$7,$8)." 22231 to_rgba repeat $! l[$>] 22232 100%,100%,1,1,1 22233 padx={if(${"is_percent $1"},$1*(w-1)/2,$1)} 22234 pady={if(${"is_percent $2"},$2*(h-1)/2,$2)} 22235 rectangle. $padx,$pady,{w-1-$padx},{h-1-$pady} 22236 spread. $3 b. $4 100%,100%,1,4 fc. ${5-8} 22237 j[0] [2],0,0,0,0,1,[1] k[0] 22238 endl done 22239 22240#@cli frame_painting : _size[%]>=0,0<=_contrast<=1,_profile_smoothness[%]>=0,_R,_G,_B,_vignette_size[%]>=0,\ 22241# _vignette_contrast>=0,_defects_contrast>=0,0<=_defects_density<=100,_defects_size>=0,_defects_smoothness[%]>=0,\ 22242# _serial_number 22243#@cli : Add a painting frame to selected images. 22244#@cli : Default values: 'size=10%', 'contrast=0.4', 'profile_smoothness=6%', 'R=225', 'G=200', 'B=120', \ 22245# 'vignette_size=2%', 'vignette_contrast=400', 'defects_contrast=50', 'defects_density=10', 'defects_size=1', \ 22246# 'defects_smoothness=0.5%' and 'serial_number=123456789'. 22247#@cli : $ image.jpg frame_painting , 22248frame_painting : 22249 check "${1=10%}>=0 && ${2=0.4}>=0 && $2<=1 && ${3=6%}>=0 && ${7=2%}>=0 && ${8=400}>=0 && ${9=50}>=0 && 22250 ${10=10}>=0 && $10<=100 && ${11=1}>=0 && ${12=0.5%}>=0" 22251 skip ${4=225},${5=200},${6=120},${13=123456789} 22252 e[^-1] "Add painting frame to image$?, with size $1, contrast $2, profile smoothness $3, color (${4-6}), 22253 vignette size $7, vignette strength $8, defects contrast $9, defects density $10, defects size $11, 22254 defects smoothness $12 and serial number $13." 22255 if !$1 return fi 22256 repeat $! l[$>] 22257 $1,$1 s={max(w,h)} rm. # Determine size of the frame 22258 ('${dec2bin\ $13}') -. {'0'} r. $s # Generate frame profile from serial number 22259 transpose. b. $3 n. {1-$2},{1+$2} 22260 +r. {{-2,w}+2*$s},100%,1,1 # Upper frame 22261 +mirror. y # Lower frame 22262 mv... $! transpose. r. 100%,{-4,h+2*$s},1,1 # Left frame 22263 +mirror. x # Right frame 22264 ...,...,1,1,1 22265 polygon. 3,0,0,{$s-1},{$s-1},0,{$s-1},1,0 22266 polygon. 3,100%,0,{w-$s},100%,100%,100%,1,0 # Upper/lower mask 22267 ..,..,1,1,1 22268 polygon. 3,1,0,100%,{$s-2},100%,0 22269 polygon. 3,1,100%,100%,{h-$s+1},100%,100%,1,0 # Left/right mask 22270 _frame_painting[-6--3] ${4-6},${9-12} # Add colors + defects 22271 22272 # Build full frame picture. 22273 {-7,w+2*$s},{-7,h+2*$s},1,3 22274 j. [-7],0,0,0,0,1,...,1 rm[-7] mirror... y 22275 j. [-6],0,{h-$s},0,0,1,...,1 rm[-6,-3] 22276 j. [-4],0,0,0,0,1,..,1 rm[-4] mirror.. x 22277 j. ...,{w-$s},0,0,0,1,..,1 rm[-3,-2] 22278 ..,..,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. 22279 a[-2--1] c 22280 r.. .,.,1,100%,0,0,0.5,0.5 blend alpha # Insert initial image into frame picture. 22281 endl done 22282 22283_frame_painting : # Add color + texture to each frame part. 22284 repeat $! l[$>] 22285 +*. $2 +*.. $3 *... $1 a[-3--1] c 22286 100%,100% 22287 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" 22288 b. $7 g. +[-2,-1] n. -$4,$4 22289 +[-2,-1] c. 0,255 22290 endl done 22291 22292#@cli frame_pattern : M>=3,_constrain_size={ 0 | 1 } : M>=3,_[frame_image],_constrain_size={ 0 | 1 } 22293#@cli : Insert selected pattern frame in selected images. 22294#@cli : Default values: 'pattern=0' and 'constrain_size=0'. 22295#@cli : $ image.jpg frame_pattern 8 22296frame_pattern : check $1>=3 skip "${2=0},${3=}" 22297 to_colormode 0 22298 if ${"is_image_arg $2"} # Frame from specified image. 22299 e[^-1] "Insert $1x$1 pattern frame on image$?, using frame image$2." 22300 pass$2 0 repeat $!-1 l[$>,-1] 22301 wh={0,w},{0,h} 22302 +r[1] {0,max(1,w/($1-2))},{0,max(1,h/($1-2))},1,100%,2 22303 r[0] {{0,w}+2*w},{{0,h}+2*h},1,100%,0,0,0.5,0.5 22304 [-1]x{$1+2} a[{-$1-2}--1] x j[0] .,0,0 j[0] .,0,{{0,h}-1-h} rm. 22305 [-1]x{$1+1} a[{-$1-2}--1] y j[0] .,0,0 j[0] .,{{0,w}-1-w} rm. 22306 if $3 r[0] $wh,1,100%,2 fi 22307 endl done rm. 22308 else # Self-frame. 22309 e[^-1] "Insert $1x$1 self-pattern frame on image$?." 22310 repeat $! l[$>] 22311 wh={w},{h} 22312 +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 22313 [-1]x{$1+2} a[{-$1-2}--1] x j... .,0,0 j... .,0,{{-3,h}-1-h} rm. 22314 [-1]x{$1+1} a[{-$1-2}--1] y j.. .,0,0 j.. .,{{-2,w}-1-w} rm. 22315 if $3 r $wh,1,100%,2 fi 22316 endl done 22317 fi 22318 22319#@cli frame_round : _sharpness>0,_size>=0,_smoothness,_shading,_R,_G,_B,_A 22320#@cli : Draw RGBA-colored round frame in selected images. 22321#@cli : Default values: 'sharpness=10', 'size=10', 'smoothness=0', 'shading=0' and 'R=G=B=A=255'. 22322#@cli : $ image.jpg frame_round 10 22323frame_round : skip ${1=10},${2=10},${3=0},${4=0},${5=255},${6=$5},${7=$6},${8=255} 22324 e[^-1] "Draw round frame on image$?, with sharpness $1, size $2, smoothness $3, shading $4 and 22325 RGBA color ($5,$6,$7,$8)." 22326 to_rgba repeat $! l[$>] nm={0,n} 22327 100%,100%,1,1,"-(abs(x/w-0.5)^$1 + abs(y/h-0.5)^$1)^(1/$1)" >=. $2% 22328 if $4 distance. 1 n. 0,1 *. -1 +. 1 ^. {1/$4} fi 22329 b. $3 i... 100%,100%,1,4 fc... $5,$6,$7,$8 blend_fade[0,1] . rm. 22330 nm $nm endl done 22331 22332#@cli frame_seamless : frame_size>=0,_patch_size>0,_blend_size>=0,\ 22333# _frame_direction={ 0=inner (preserve image size) | 1=outer } 22334#@cli : Insert frame in selected images, so that tiling the resulting image makes less visible seams. 22335#@cli : Default values: 'patch_size=7', 'blend_size=5' and 'frame_direction=1'. 22336#@cli : $ image.jpg +frame_seamless 30 array 2,2 22337frame_seamless : check "$1>=0 && isint(${2=7}) && $2>0 && isint(${3=5}) && $3>=0" skip ${4=1} 22338 s0="inner" s1="outer" 22339 e[^-1] "Insert "${s{!!$4}}" seamless frame in image$?, with size $1, patch size $2 and blend size $3." 22340 repeat $! l[$>] 22341 w2={round(w/2)} h2={round(h/2)} 22342 w4={round(w/4)} h4={round(h/4)} 22343 if !$4 r {max(1,w-$1)},{max(1,h-$1)},1,100%,0,0,0.5,0.5 fi 22344 100%,100%,1,1,-1 r[-2,-1] {w+$1},{h+$1},1,100%,0,0,0.5,0.5 n. 0,1 22345 shift -$w2,-$h2,0,0,2 22346 inpaint_matchpatch.. [1],0,$2,10,$3 22347 rectangle. $1,$1,{w-1-$1},{h-1-$1} 22348 shift -$w4,-$h4,0,0,2 22349 inpaint_matchpatch.. [1],0,$2,10,$3 22350 rm. 22351 shift {$w4+$w2},{$h4+$h2},0,0,2 22352 endl done 22353 22354#@cli frame_x : size_x[%],_col1,...,_colN 22355#@cli : Insert colored frame along the x-axis in selected images. 22356#@cli : Default values: 'col1=col2=col3=255' and 'col4=255'. 22357#@cli : $ image.jpg frame_x 20,255,0,255 22358frame_x : skip ${2=255},${3=$2},${4=$3},${5=255} 22359 e[^-1] "Insert $1 outer frame in image$? along the x-axis, with color (${2--1})." 22360 _frame $1,0,0,${2--1} 22361 22362#@cli frame_xy : size_x[%],_size_y[%],_col1,...,_colN 22363#@cli : Insert colored frame along the x-axis in selected images. 22364#@cli : Default values: 'size_y=size_x', 'col1=col2=col3=255' and 'col4=255'. 22365#@cli : (eq. to 'frame'). 22366#@cli : $ image.jpg frame_xy 1,1,0 frame_xy 20,10,255,0,255 22367frame_xy : skip ${2=$1},${3=255},${4=$3},${5=$4},${6=255} 22368 _gmic_s="$?" v + _$0 ${1--1} 22369 22370_frame_xy : 22371 e[0--3] "Insert $1x$2 outer frame in image"$_gmic_s" along the xy-axes, with color (${3--1})." 22372 _frame $1,$2,0,${3--1} 22373 22374#@cli frame_xyz : size_x[%],_size_y[%],_size_z[%]_col1,...,_colN 22375#@cli : Insert colored frame along the x-axis in selected images. 22376#@cli : Default values: 'size_y=size_x=size_z', 'col1=col2=col3=255' and 'col4=255'. 22377frame_xyz : skip ${2=$1},${3=$2},${4=255},${5=$4},${6=$5},${7=255} 22378 e[^-1] "Insert $1x$2x$3 outer frame in image$? along the xyz-axes, with color (${4--1})." 22379 _frame $1,$2,$3,${4--1} 22380 22381#@cli frame_y : size_y[%],_col1,...,_colN 22382#@cli : Insert colored frame along the y-axis in selected images. 22383#@cli : Default values: 'col1=col2=col3=255' and 'col4=255'. 22384#@cli : $ image.jpg frame_y 20,255,0,255 22385frame_y : skip ${2=255},${3=$2},${4=$3},${5=255} 22386 e[^-1] "Insert $1 outer frame in image$? along the y-axis, with color (${2--1})." 22387 _frame 0,$1,0,${2--1} 22388 22389_frame : 22390 repeat $! l[$>] 22391 nm={0,n} 22392 w={round($1*if(${is_percent\ $1},w,1))} 22393 h={round($2*if(${is_percent\ $2},h,1))} 22394 d={round($3*if(${is_percent\ $3},d,1))} 22395 {w+2*$w},{h+2*$h},{d+2*$d},100% fc[1] ${4--1} 22396 j[1] [0],$w,$h,$d rm[0] nm $nm 22397 endl done 22398 22399#@cli img2ascii : _charset,_analysis_scale>0,_analysis_smoothness[%]>=0,_synthesis_scale>0,_output_ascii_filename 22400#@cli : Render selected images as binary ascii art. 22401#@cli : This command returns the corresponding the list of widths and heights (expressed as a number of characters) 22402#@cli : for each selected image. 22403#@cli : Default values: 'charset=[ascii charset]', 'analysis_scale=16', 'analysis_smoothness=20%', \ 22404# 'synthesis_scale=16' and '_output_ascii_filename=[undefined]'. 22405#@cli : $ image.jpg img2ascii , 22406img2ascii : check "${2=16}>0 && ${3=20%}>=0 && ${4=16}>0" 22407 skip "${1= !\042#$%&\047()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\133\\\135^_\140abcdefghijk"\ 22408 "lmnopqrstuvwxyz\173|\174~}","${5=}" 22409 e[^-1] "Render image$? as binary ascii art, with charset '$1', analysis scale $2, analysis smoothness $3, 22410 synthesis scale $4 and output ascii filename '$5'." 22411 is_multi={$!>1} 22412 22413 # Generate dictionaries for image analysis and synthesis. 22414 l[] 22415 ('"$1"') repeat w 22416 C={`92`}${dec2oct\ {0,@$>}} 22417 0 t. $C,0,0,$2,1,1 22418 0 t. $C,0,0,$4,1,1 22419 done rm[0] 22420 = -1 = -1,0,100% autocrop = 0 = 0,0,100% 22421 l[0--2:2] r {${-max_w}+1},100%,1,1,0,0,0.5 b $3 n 0,255 a z endl 22422 l[1--1] r {${-max_w}+1},100%,1,1,0,0,0.5 a z endl 22423 endl 22424 w={-2,w} h={-2,h} 22425 22426 # Transform selected images to ascii art. 22427 repeat $!-2 l[$>,-2,-1] 22428 luminance[0] n[0] 0,255 22429 nw={0,round(w/$w,1,1)} 22430 nh={0,round(h/$h,1,1)} 22431 if $> list_wh=$list_wh,$nw,$nh else list_wh=$nw,$nh fi 22432 22433 s[0] y,-$h s[0--3] x,-$w r[0--3] $w,$h,1,1,0,0 22434 repeat $!-2 l[$>,-2,-1] 22435 rprogress {$>*100/($!-2)} 22436 ri[0] [1] -[0] [1] sqr[0] r[0] 1,1,100%,1,2 y[0] 22437 C={0,ym} rm[0] 22438 +slices[1] $C mv. 0 22439 if narg("$5") +f[0] $C a[0,-1] c fi 22440 endl done 22441 append_tiles[0--2] $nw,$nh 22442 22443 if narg("$5") s[0] c l[1] # Export as text file. 22444 r $nw,$nh,1,1,1 22445 ('"$1"') map[0] . k[0] 22446 s y i[1-$!] ('\n') 22447 a x 22448 if $is_multi filename=${filename\ "$5",$>} else filename="$5" fi 22449 ot $filename rm 22450 endl fi 22451 22452 endl done 22453 rm[-2,-1] u $list_wh 22454 22455#@cli imagegrid : M>0,_N>0 22456#@cli : Create MxN image grid from selected images. 22457#@cli : Default value: 'N=M'. 22458#@cli : $ image.jpg imagegrid 16 22459imagegrid : skip ${2=$1} 22460 e[^-1] "Create $1x$2 image grid from image$?." 22461 repeat $! l[$>] 22462 ({w},{h}) ($1,$2) /[-2,-1] round. 1 r.. {^},..,..,2 rm. 22463 ({w},{h}) ($1,$2) *[-2,-1] r.. {^},..,..,2 rm. 22464 $1,$2,1,.,1 shift. 1,1 ri. ..,0,2 * 22465 endl done 22466 22467#@cli imagegrid_hexagonal : _resolution>0,0<=_outline<=1 22468#@cli : Create hexagonal grids from selected images. 22469#@cli : Default values: 'resolution=32', 'outline=0.1' and 'is_antialiased=1'. 22470#@cli : $ image.jpg imagegrid_hexagonal 24 22471imagegrid_hexagonal : check "isint(${1=32}) && $1>0 && ${2=0.1}>=0 && $2<=1" 22472 e[^-1] "Create hexagonal grid(s) from image$?, with resolution $1 and outline $2." 22473 repeat $! l[$>] 22474 22475 # Generate hexagonal grid. 22476 l[] 22477 # Generate hexagon. 22478 ({'CImg3d'},6,6) 22479 (0;{2*pi}) -. {pi/2} r. 1,7,1,1,3 +sin. cos.. a[-2,-1] x rows. 0,5 z. 0,2 22480 2,6,1,1,3,0 1,100%,1,1,y ++. 1 %. 6 rv[-2,-1] a[-3--1] x 22481 3,100%,1,1,1 1,100%,1,1,1 y a y 22482 *3d. {1-$2} 22483 22484 # Generate minimal pattern (2x2 hexagons). 22485 ++3d {sqrt(3)} ++3d {sqrt(3)/2},1.5 22486 col3d... 2 col3d.. 3 col3d. 4 +3d 22487 /3d 1.5 22488 endl 22489 22490 # Duplicate it to get a grid with correct size. 22491 ny={1+round(0.5*$1,1,1)} 22492 nx={0,1+round($1*w/h*3/(sqrt(3)*4),1,1)} 22493 array3d. $nx,$ny,1,{4*sqrt(3)/3},2 22494 c3d. *3d. {0,h/$1} 22495 22496 # Fill grid with image colors. 22497 [0],[0] j3d. ..,50%,50%,0,1,2,0,0 rm.. 22498 blend shapeaverage0 22499 22500 endl done 22501 22502#@cli imagegrid_triangular : pattern_width>=1,_pattern_height>=1,_pattern_type,0<=_outline_opacity<=1,\ 22503# _outline_color1,... 22504#@cli : Create triangular grids from selected images. 22505#@cli : 'pattern type' can be { 0=horizontal | 1=vertical | 2=crossed | 3=cube | 4=decreasing | 5=increasing }. 22506#@cli : Default values: 'pattern_width=24', 'pattern_height=pattern_width', 'pattern_type=0', 'outline_opacity=0.1' \ 22507# and 'outline_color1=0'. 22508#@cli : $ image.jpg imagegrid_triangular 6,10,3,0.5 22509imagegrid_triangular : check "$1>=1 && ${2=$1}>=1 && isint(${3=0}) && $3>=0 && $3<=5" skip ${4=0},${5=0} 22510 s0="horizontal" s1="vertical" s2="crossed" s3="cube" 22511 e[^-1] "Create triangular grid(s) from image$?, with pattern width $1, height $2, pattern type '"${s$3}"', "\ 22512 "outline opacity $4 and outline color (${5--1})." 22513 22514 # Create triangular patterns and outlines (always square!). 22515 M={max($1,$2)} 22516 if $3==4" || "$3==5 # Decreasing/Increasing. 22517 $M,$M,1,1,x>y ++. 2 a[-2,-1] x ++. 4 a[-2,-1] y 22518 $M,$M,1,1,"!x || !y || x==y" r. 200%,200%,1,1,0,2 22519 a[-2,-1] c 22520 if $3==5 mirror. y fi 22521 elif $3==3 # Cube. 22522 $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 22523 ++. 4 =. 4,50%,50% =.. 2 a[-2,-1] x label. 0,0 22524 (2,2,2,0,1,2,1,1,3,3,3,1,1,0) map.. . rm. 22525 100%,100%,1,1 22526 line. 0,0,{$M-1},{$M-1},1,1 line. {$M-1},$M,0,100%,1,1 22527 line. {$M-1},{$M-1},{3*$M-1},{$M-1},1,1 line. {2*$M},0,0,0,1,1 22528 line. {2*$M},0,100%,100%,1,1 line. {2*$M},100%,100%,0,1,1 22529 a[-2,-1] c 22530 elif $3==2 # Horizontal + vertical. 22531 $M,$M,1,1,x>y ++. 2 mirror. x a[-2,-1] x ++. 4 mirror. y a[-2,-1] y 22532 100%,100%,1,1,"!x || !y || x==int(w/2) || y==int(h/2) || x==y || w-1-x==y" 22533 a[-2,-1] c 22534 elif $3==1 # Vertical. 22535 $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 22536 100%,100%,1,1,"!x || x==int(w/2) || x==y || w-1-x==y" 22537 a[-2,-1] c 22538 else # Horizontal. 22539 $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 22540 100%,100%,1,1,"!y || y==int(h/2) || x==y || w-1-x==y" 22541 a[-2,-1] c 22542 fi 22543 22544 # Apply grid on images. 22545 repeat $!-1 22546 wh={$>,w},{$>,h} 22547 if $1>$2 r[$>] 100%,{$>,$1*h/$2} elif $1<$2 r[$>] {$>,$2*w/$1} fi 22548 +r. [$>],[$>],1,2,0,2,0.5,0.5 22549 s. c 22550 blend[$>,-2] shapeaverage 22551 +fc[$>] ${5--1} j[$>] .,0,0,0,0,$4,.. rm[-2,-1] 22552 r[$>] $wh,1,100%,2 22553 done 22554 rm. 22555 22556#@cli linearize_tiles : M>0,_N>0 22557#@cli : Linearize MxN tiles on selected images. 22558#@cli : Default value: 'N=M'. 22559#@cli : $ image.jpg +linearize_tiles 16 22560linearize_tiles : check "$1>0 && ${2=$1}>0" 22561 e[^-1] "Linearize $1x$2 tiles on image$?." 22562 repeat $! l[$>] nm={0,n} 22563 s={s} split_tiles $1,$2 s c # Split as tiles for all channels. 22564 repeat $! l[$>] 22565 wh={w},{h} 22566 +f x +f. y +f. 1 y a[^0] x solve.. . rm. 22567 $wh,1,1,{@0}"*x + "{@1}"*y + "{@2} rm.. 22568 endl done 22569 repeat int($!/$s) a[-$s--1] c mv. 0 done append_tiles $1,$2 22570 nm $nm endl done 22571 22572#@cli map_sprites : _nb_sprites>=1,_allow_rotation={ 0=none | 1=90 deg. | 2=180 deg. } 22573#@cli : Map set of sprites (defined as the 'nb_sprites' latest images of the selection) to other selected images, 22574#@cli : according to the luminosity of their pixel values. 22575#@cli : $ image.jpg resize2dy 48 repeat 16 ball {8+2*$>},${-rgb} mul[-1] {(1+$>)/16} done map_sprites 16 22576map_sprites : check "isint($1) && $1>0 && isint(${2=0}) && $2>=0 && $2<=2" 22577 e[^-1] "Map set of $1 sprites to image selection$?." 22578 norm[0--{$1+1}] quantize[0--{$1+1}] $1,0,1 22579 slices[-$1--1] 0 r[-$1--1] ${max_wh[-$1--1]},1,100%,0,0,0.5,0.5 22580 if $2==1 22581 N={4*$1} 22582 repeat $!-$1 *[$>] 4 +rand[$>] 0,3 round. +[$>,-1] done 22583 repeat $1 l[{1+$<}] +mirror xy +rotate 90 endl done 22584 elif $2==2 22585 N={2*$1} 22586 repeat $!-$1 *[$>] 2 +rand[$>] 0,1 round. +[$>,-1] done 22587 repeat $1 l[{1+$<}] +mirror xy endl done 22588 else N=$1 fi 22589 r[-$N--1] 100%,100%,1,${max_s[-$N--1]} w={w} h={h} a[-$N--1] x 22590 r[^-1] ${w}00%,${h}00%,1,1 *[^-1] $w 22591 (0,{$w-1};0,{$w-1}^0,0;{$h-1},{$h-1}) r. $w,$h,1,2,3 round. 22592 repeat $!-2 +r. [$>],[$>],1,2,0,2 r[$>] 100%,100%,1,2,0 +[$>,-1] +warp.. [$>],0,0 rv[$>,-1] rm. done rm[-2,-1] 22593 22594#@cli pack : is_ratio_constraint={ 0 | 1 },_sort_criterion 22595#@cli : Pack selected images into a single image. 22596#@cli : The returned status contains the list of new (x,y) offsets for each input image. 22597#@cli : Parameter 'is_ratio_constraint' tells if the resulting image must tend to a square image. 22598#@cli : Default values: 'is_ratio_constraint=0' and 'sort_criterion=max(w,h)'. 22599#@cli : $ image.jpg repeat 10 +resize2dx[-1] 75% balance_gamma[-1] ${-rgb} done pack 0 22600pack : skip ${1=0},${2=max(w,h)} 22601 e[^-1] "Pack image$? into a single image." 22602 if $!<2 return fi 22603 if ${-max_d}>1 error[0--3] "Command '$0': Selected images contain at least one volumetric image (depth>1). 22604 Should all be 2D." fi 22605 nm={0,n} to_colormode 0 22606 22607 # Sort images by decreasing size. 22608 repeat $! nm$>={$>,n} nm[$>] ${nm$>}:$> done 22609 m "_pack : ('{n}') l. s +,{':'} u {t} rm endl" 22610 if ['$2']=='n' sort_list +,n else sort_list -,"$2" fi 22611 22612 # Start packing 22613 offsets${-_pack[0]}=0,0 22614 N=$! 22615 i[0] 0 # List of empty slots. 22616 22617 do l[0,1,2] 22618 w1,h1,w2,h2={[w#1,h#1,w#2,h#2]} 22619 22620 # Search an empty slot that fits. 22621 slot,min_slot_area=-1,inf 22622 repeat h#0 22623 x,y,w,h={0,crop(0,$>,4,1)} 22624 slot_area={$w*$h} 22625 if $w>=$w2" && "$h>=$h2" && "$slot_area<=$min_slot_area # Found a fit. 22626 slot,min_slot_area=$>,$slot_area 22627 fi 22628 done 22629 22630 if $slot>=0 # Empty slot found -> Use it. 22631 x,y,w,h={0,crop(0,$slot,4,1)} 22632 j[1] [2],$x,$y offsets${-_pack[2]}=$x,$y 22633 l[0] 22634 s y rm[$slot] 22635 area1={max(($w-$w2)*$h,$w2*($h-$h2))} 22636 area2={max(($w-$w2)*$h2,$w*($h-$h2))} 22637 if $area1>=$area2 # Split - type1 22638 if $w2<$w i[$slot] ({$x+$w2},$y,{$w-$w2},$h) fi 22639 if $h2<$h i[$slot] ($x,{$y+$h2},$w2,{$h-$h2}) fi 22640 else # Split - type 2 22641 if $w2<$w i[$slot] ({$x+$w2},$y,{$w-$w2},$h2) fi 22642 if $h2<$h i[$slot] ($x,{$y+$h2},$w,{$h-$h2}) fi 22643 fi 22644 a y if !$! 0 fi 22645 endl 22646 rm[2] 22647 22648 else # Empty slot not found -> Append horizontally or vertically. 22649 if $1 22650 metric_h={abs($w1+$w2-max($h1,$h2))} 22651 metric_v={abs($h1+$h2-max($w1,$w2))} 22652 else 22653 metric_h={if($h2<$h1,$w2*($h1-$h2),$w1*($h2-$h1))} 22654 metric_v={if($w2<$w1,($w1-$w2)*$h2,($w2-$w1)*$h1)} 22655 fi 22656 22657 if $metric_h<=$metric_v # Append horizontally. 22658 offsets${-_pack[2]}=$w1,0 22659 a[1,2] x,0 22660 if $h2<$h1 ($w1,$h2,$w2,{$h1-$h2}) a[0,-1] y 22661 elif $h2>$h1 (0,$h1,$w1,{$h2-$h1}) a[0,-1] y 22662 fi 22663 else # Append vertically. 22664 offsets${-_pack[2]}=0,$h1 22665 a[1,2] y,0 22666 if $w2<$w1 ($w2,$h1,{$w1-$w2},$h2) a[0,-1] y 22667 elif $w2>$w1 ($w1,0,{$w2-$w1},$h1) a[0,-1] y 22668 fi 22669 fi 22670 fi 22671 22672 endl while $!>2 22673 rm[0] 22674 22675 # Return offsets. 22676 status= 22677 repeat $N if narg($status) status=$status,${offsets$>} else status=${offsets$>} fi done 22678 nm $nm u $status 22679 um _pack 22680 22681#@cli puzzle : _width>0,_height>0,_M>=1,_N>=1,_curvature,_centering,_connectors_variability,_resolution>=1 22682#@cli : Input puzzle binary mask with specified size and geometry. 22683#@cli : Default values: 'width=height=512', 'M=N=5', 'curvature=0.5', 'centering=0.5', 'connectors_variability=0.5' \ 22684# and 'resolution=64'. 22685#@cli : $ puzzle , 22686puzzle : check "isint(${1=512}) && $1>0 && isint(${2=$1}) && $2>0 && isint(${3=5}) && $3>0 && 22687 isint(${4=$3}) && $4>0 && isint(${8=64}) && $8>0" 22688 skip ${5=0.5},${6=0.5},${7=0.5} 22689 e[^-1] "Draw $3x$4 puzzle pattern on image$?, with curvature $5, centering $6, connectors variability $7 22690 and resolution $8." 22691 l[] 22692 if $4>=2 _puzzle[] $3,{$4-1},${5-8} +3d. 0,1 fi 22693 if $3>=2 _puzzle[] $4,{$3-1},${5-8} r3d. 0,0,1,-90 +3d. 1,$4 fi 22694 *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 22695 $1,$2 j3d. ..,0,0,0,1,1,0,0 rm.. 22696 endl 22697 22698_puzzle : 22699 R={$6*$1} 22700 repeat $2 22701 ({'CImg3d'},$R,{$R-1}) 22702 repeat $1 22703 sign={if(u<=0.5,-1,1)} 22704 center={$4*u(-0.25,0.25)} 22705 knob={$5*u(-0.05,0.12)} 22706 ($>,0;\ 22707 {0.2+$center+$>},{-$sign*$3*0.1};\ 22708 {0.4+$center+$>},0;\ 22709 {0.35+$center+$>},{0.1*$sign};\ 22710 {0.45+$center+$>},{(0.15+$knob)*$sign};\ 22711 {0.55+$center+$>},{(0.15+$knob)*$sign};\ 22712 {0.65+$center+$>},{0.1*$sign};\ 22713 {0.6+$center+$>},0;\ 22714 {0.8+$center+$>},{-$sign*$3*0.1}) 22715 done 22716 ($1,0) a[-{$1+1}--1] y r. 2,$R,1,1,5 z. 0,2 22717 (2,0,1;2,{$R-2},{$R-1}) r. 3,{$R-1},1,1,3 round. 22718 3,{h},1,1,255 1,{h},1,1,255 y[-5--1] y a[-5--1] y +3d. 0,$> 22719 done +3d 22720 22721#@cli quadratize_tiles : M>0,_N>0 22722#@cli : Quadratize MxN tiles on selected images. 22723#@cli : Default value: 'N=M'. 22724#@cli : $ image.jpg +quadratize_tiles 16 22725quadratize_tiles : check "$1>0 && ${2=$1}>0" 22726 e[^-1] "Quadratize $1x$2 tiles on image$?." 22727 repeat $! l[$>] nm={0,n} 22728 s={s} split_tiles $1,$2 s c # Split as tiles for all channels. 22729 repeat $! l[$>] 22730 wh={w},{h} 22731 +f x^2 +f. y^2 +f. x*y +f. x +f. y +f. 1 y a[^0] x 22732 solve.. . rm. 22733 $wh,1,1,{@0}"*x^2 + "{@1}"*y^2 + "{@2}"*x*y +"{@3}"*x + "{@4}"*y + "{@5} rm.. 22734 endl done 22735 repeat int($!/$s) a[-$s--1] c mv. 0 done append_tiles $1,$2 22736 nm $nm endl done 22737 22738#@cli rotate_tiles : angle,_M>0,N>0 22739#@cli : Apply MxN tiled-rotation effect on selected images. 22740#@cli : Default values: 'M=8' and 'N=M'. 22741#@cli : $ image.jpg to_rgba rotate_tiles 10,8 drop_shadow 10,10 display_rgba 22742rotate_tiles : skip ${2=8},${3=$2} 22743 e[^-1] "Apply $2x$3 tiled-rotation effect on image$?, with angle $1 deg." 22744 split_tiles $2,$3,1 rotate $1 append_tiles $2,$3 22745 22746#@cli shift_tiles : M>0,_N>0,_amplitude 22747#@cli : Apply MxN tiled-shift effect on selected images. 22748#@cli : Default values: 'N=M' and 'amplitude=20'. 22749#@cli : $ image.jpg +shift_tiles 8,8,10 22750shift_tiles : check "${2=$1}>=0" skip ${3=20} 22751 e[^-1] "Apply $1x$2 tiled-shift effect on image$?, with amplitude $3." 22752 repeat $! l[$>] 22753 $1,$2,1,2 noise. $3 r. ..,..,1,2 warp.. .,1,1,0 rm. 22754 endl done 22755 22756#@cli taquin : M>0,_N>0,_remove_tile={ 0=none | 1=first | 2=last | 3=random },_relief,_border_thickness[%],\ 22757# _border_outline[%],_outline_color 22758#@cli : Create MxN taquin puzzle from selected images. 22759#@cli : Default value: 'N=M', 'relief=50', 'border_thickness=5', 'border_outline=0' and 'remove_tile=0'. 22760#@cli : $ image.jpg +taquin 8 22761taquin : check "isint($1) && $1>0 & isint(${2=$1}) && $2>0" 22762 skip ${3=0},${4=50},${5=5%},${6=0},${7=0},${8=$7},${9=$8},${10=255} 22763 e[^-1] "Create $1x$2 taquin puzzle from image$?, with relief $4, border thickness $5, border outline $6 and 22764 outline color (${7--1})." 22765 repeat $! l[$>] nm={0,n} 22766 split_tiles $1,$2 r ${-min_wh},100%,100%,0 22767 100%,100%,1,1,1 22768 if ${"is_percent $5"} rectangle. {100*$5/2}%,{100*$5/2}%,{100-50*$5}%,{100-50*$5}%,1,0 22769 else rectangle. $5,$5,{w-1-$5},{h-1-$5},1,0 fi 22770 *. '1-2*(x/w<y/h)' *. $4 22771 repeat $!-1 l[$>,-1] split_opacity[0] +[0] . a[^-1] c endl done rm. c 0,255 22772 frame $6,$6,${7-10} 22773 if $3==3 f. 0 fi 22774 repeat $! mv[$>] {u($!)} done 22775 if $3==1 f[0] 0 elif $3==2 f. 0 fi 22776 append_tiles $1,$2 22777 nm $nm endl done 22778 22779#@cli tunnel : _level>=0,_factor>0,_centering_x,_centering_y,_opacity,_angle 22780#@cli : Apply tunnel effect on selected images. 22781#@cli : Default values: 'level=9', 'factor=80%', 'centering_x=centering_y=0.5', 'opacity=1' and 'angle=0' 22782#@cli : $ image.jpg tunnel 20 22783tunnel : check "${1=9}>=0 && ${2=80%}>0" skip ${3=0.5},${4=0.5},${5=0.1},${6=0} 22784 e[^-1] "Apply tunnel effect on image$?, with depth $1, factor $2, centering ($3,$4), opacity $5 and angle $6." 22785 repeat $! l[$>] 22786 repeat $1 +r. $2,$2,1,100%,5 22787 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] 22788 else j.. .,{({-2,w}-w)*$3},{({-2,h}-h)*$4},0,0,$5 rm. fi 22789 done 22790 endl done c 0,255 22791 22792#----------------------------- 22793# 22794#@cli :: Artistic 22795# 22796#----------------------------- 22797 22798#@cli boxfitting : _min_box_size>=1,_max_box_size>=0,_initial_density>=0,_nb_attempts>=1 22799#@cli : Apply box fitting effect on selected images, as displayed the web page: 22800#@cli : <http://www.complexification.net/gallery/machines/boxFittingImg/>. 22801#@cli : Default values: 'min_box_size=1', 'max_box_size=0', 'initial_density=0.1' and 'nb_attempts=3'. 22802#@cli : $ image.jpg boxfitting , 22803boxfitting : check "isint(${1=3}) && $1>=1 && isint(${2=0}) && $2>=0 && ${3=0.1}>=0 && isint(${4=3}) && $4>=1" 22804 e[^-1] "Apply box fitting effect on image$?, with box sizes ($1,$2), density $3 and $4 attempts." 22805 min_size=$1 22806 max_size={if($2,$2,max(w,h))} 22807 repeat $! l[$>] 22808 nb_attempts=0 prec=5 22809 100%,100% 22810 repeat 1e8 22811 22812 # Add random non-intersecting squares with min size. 22813 if $><1 # Takes random points for the first iteration. 22814 100%,100% noise. {max(1e-3,$3)},2 ==. 1 22815 else # Then, try to take points near the median axis of the distance function otherwise. 22816 +distance. 1 +rand. 0,1 *[-2,-1] max_patch. {round($prec*$min_size)} 22817 prec={max(1,$prec*0.9)} 22818 fi 22819 22820 # Discard new squares that intersect something. 22821 dilate. $min_size area_fg. 0,1 ==. {($min_size)^2} 22822 +dilate.. 3 ==. 0 *[-2,-1] area_fg. 0,1 ==. {($min_size)^2} 22823 if !iM nb_attempts+=1 if $nb_attempts>$4 rm. break fi # If no new squares have been placed. 22824 else nb_attempts=0 fi 22825 +[-2,-1] 22826 22827 # Make current squares grown until max square size is reached. 22828 repeat int(($max_size-$min_size)/2) 22829 +dilate. 3 area_fg. 0,1 ==. {($min_size+2*$>+2)^2} 22830 if !iM rm. break fi # No more squares to grow. 22831 -|[-2,-1] 22832 done 22833 22834 done 22835 blend shapeaverage0 22836 endl done 22837 22838#@cli brushify : [brush],_brush_nb_sizes>=1,0<=_brush_min_size_factor<=1,_brush_nb_orientations>=1,\ 22839# _brush_light_type,0<=_brush_light_strength<=1,_brush_opacity,_painting_density[%]>=0,\ 22840# 0<=_painting_contours_coherence<=1,0<=_painting_orientation_coherence<=1,_painting_coherence_alpha[%]>=0,\ 22841# _painting_coherence_sigma[%]>=0,_painting_primary_angle,0<=_painting_angle_dispersion<=1 22842#@cli : Apply specified brush to create painterly versions of specified images. 22843#@cli : 'brush_light_type' can be { 0=none | 1=flat | 2=darken | 3=lighten | 4=full }. 22844#@cli : Default values: 'brush_nb_sizes=3', 'brush_min_size_factor=0.66', 'brush_nb_orientations=12', \ 22845# 'brush_light_type=0', 'brush_light_strength=0.25', 'brush_opacity=0.8', 'painting_density=20%', \ 22846# 'painting_contours_coherence=0.9', 'painting_orientation_coherence=0.9', 'painting_coherence_alpha=1', \ 22847# 'painting_coherence_sigma=1', 'painting_primary_angle=0', 'painting_angle_dispersion=0.2' 22848#@cli : $ image.jpg 40,40 gaussian[-1] 10,4 spread[-1] 10,0 brushify[0] [1],1 22849brushify : check ${"is_image_arg $1"}" &&"\ # $1: [brush] 22850 "isint(${2=4}) && $2>=1 &&"\ # $2: brush_nb_sizes 22851 "${3=0.25}>=0 && $3<=1 &&"\ # $3: brush_min_size_factor 22852 "isint(${4=12}) && $4>=1 &&"\ # $4: brush_nb_orientations 22853 "isint(${5=4}) && $5>=0 &&"\ # $5: brush_light_type 22854 "${6=0.07}>=0 && $6<=1 &&"\ # $6: brush_light_strength 22855 "isnum(${7=0.75}) &&"\ # $7: brush_opacity 22856 "${8=40%}>=0 && $8>=0 &&"\ # $8: painting_density[%] 22857 "${9=0.7}>=0 && $9<=1 &&"\ # $9: painting_contours_coherence 22858 "${10=1}>=0 && $10<=1 &&"\ # $10: painting_orientation_coherence 22859 "${11=1}>=0 && ${12=0.5%}>=0 &&"\ # $11 and $12: painting_coherence_alpha and sigma 22860 "isnum(${13=45}) &&"\ # $13: painting_primary_angle 22861 "${14=0.2}>=0 && $14<=1" # $14: painting_angle_dispersion 22862 e[^-1] "Brushify image$?, with brush $1." 22863 22864 # Precompute the set of oriented/resized brushes. 22865 pass$1 0 l. 22866 slices 0 max 1e-8 norm n 0,1 threshold 0.1,1 autocrop. 22867 repeat $4 +rotate[0] {360*$>/$4} done 22868 rm[0] n 0,1 threshold 0.1,1 22869 autocrop r ${-max_wh},1,1,0,0,0.5,0.5 22870 a z nm brush 22871 wb={w} hb={h} whb={wh} ls={255*$6} 22872 if $5==0 +f. 0 22873 elif $5==1 +n. -$ls,0 22874 elif $5==2 +g xy +[-2,-1] min. 0 n. -$ls,0 22875 elif $5==3 +g xy +[-2,-1] max. 0 n. 0,$ls 22876 else +g xy +[-2,-1] n. -$ls,$ls 22877 fi 22878 nm. brushlight 22879 22880 repeat $2-1 22881 ratio={v=(1+$>)/max(1,$2-1);100*((1-v)+$3*v)}% 22882 +r[brush,brushlight] $ratio,$ratio,100%,1,2 22883 ri[-2,-1] [brush],0,0,0.5,0.5 22884 done 22885 a[^:2] z a[^0] z 22886 endl 22887 22888 # Generate images with brushes. 22889 repeat $!-2 l[$>,brush,brushlight] 22890 s={0,s} nm={0,n} to_rgb[0] nm[0] img 22891 22892 # Generate set of random points with orientations. 22893 +diffusiontensors[img] $9,$10,$11,$12 nm. geometry 22894 +channels[geometry] 0 sh[geometry] 2 +[-2,-1] ^. 0.3 quantize. $2,0 *. -1 +. $2 -. 1 nm. contours 22895 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 22896 +to_rgba[img] nm. res 22897 22898 # Render filter. 22899 f[pts] "* 22900 begin( 22901 S2 = round(0.5*["$wb","$hb"]); 22902 brush_r = brush_g = brush_b = brush_a = vector"$whb"(255); 22903 ang = $13*pi/180; 22904 cu = [ cos(ang),sin(ang) ]; 22905 cv = [ -cu[1],cu[0] ]; 22906 T = mul(cu,cu,2) + $14*mul(cv,cv,2); 22907 ); 22908 P = I; 22909 G = I(#"$geometry",P); 22910 ang = u(pi); 22911 V = [ G[0],G[1],G[1],G[2] ]*(T*[ cos(ang),sin(ang) ]); 22912 amp = i(#"$contours",P); #cut($2-round(5*$2*sqrt(G[0] + G[2])),0,$2-1); 22913 ang = round(((atan2(V[1],V[0])%(2*pi))*$4/(2*pi)))%$4; 22914 col = I(#"$img",P); 22915 ind = amp*$4 + ang; 22916 ref(crop(#"$brush",0,0,ind,0,"$wb","$hb",1,1),brush); 22917 ref(crop(#"$brushlight",0,0,ind,0,"$wb","$hb",1,1),brushlight); 22918 brush_r = cut(col[0] + brushlight,0,255); 22919 brush_g = cut(col[1] + brushlight,0,255); 22920 brush_b = cut(col[2] + brushlight,0,255); 22921 draw(#"$res",[brush_r,brush_g,brush_b,brush_a],P - S2,"$wb","$hb",1,4,$7,brush,1); 22922 P" 22923 k[res,brush,brushlight] mv[res] 0 nm[0] $nm to_colormode[0] {$s+($s%2)} 22924 endl done rm[brush,brushlight] 22925 22926#@cli cartoon : _smoothness,_sharpening,_threshold>=0,_thickness>=0,_color>=0,quantization>0 22927#@cli : Apply cartoon effect on selected images. 22928#@cli : Default values: 'smoothness=3', 'sharpening=150', 'threshold=20', 'thickness=0.25', 'color=1.5' \ 22929# and 'quantization=8'. 22930#@cli : $ image.jpg cartoon 3,50,10,0.25,3,16 22931cartoon : skip ${1=3},${2=150},${3=20},${4=0.25},${5=1.5},${6=8} 22932 e[^-1] "Apply cartoon effect on image$?, with smoothness $1, sharpening $2, threshold $3, thickness $4, color $5 22933 and quantization $6." 22934 repeat $! l[$>] split_opacity l[0] to_rgb 22935 b $1 sharpen $2,1 c 0,255 n 0,255 22936 if $4 +edges $3 b. $4 >=. 0.9 else 100%,100%,1,1,1 fi 22937 rgb2lab.. s.. c *[-3,-2] $5 a[-4--2] c lab2rgb.. 22938 quantize.. $6,1,-1 22939 n.. 0,255 * 22940 endl a c endl done 22941 22942#@cli color_ellipses : _count>0,_radius>=0,_opacity>=0 22943#@cli : Add random color ellipses to selected images. 22944#@cli : Default values: 'count=400', 'radius=5' and 'opacity=0.1'. 22945#@cli : $ image.jpg +color_ellipses ,,0.15 22946color_ellipses : skip ${1=1400},${2=5},${3=0.1} 22947 e[^-1] "Add $1 random color ellipses to image$?, with maximum radius $2 and opacity $1." 22948 repeat $1 22949 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 22950 done 22951 22952#@cli cubism : _density>=0,0<=_thickness<=50,_max_angle,_opacity,_smoothness>=0 22953#@cli : Apply cubism effect on selected images. 22954#@cli : Default values: 'density=50', 'thickness=10', 'max_angle=75', 'opacity=0.7' and 'smoothness=0'. 22955#@cli : $ image.jpg cubism , 22956cubism : check "${1=50}>=0 && ${2=10}>=0 && $2<=50 && ${5=0}>=0" skip ${3=75},${4=0.7} 22957 e[^-1] "Apply cubism effect on image$?, with density $1, thickness $2, maximum angle $3 deg., opacity $4 and 22958 smoothness $5." 22959 if "!$1 || !$2 || !$3 || !$4" return fi 22960 repeat $! l[$>] 22961 w={w} h={h} s={s} 22962 P={round($2*max(w,h)/200)} 22963 N={round(1.5*$1*w*h/(4*$P)/100)} 22964 22965 # Define Header + nb vertices / primitives. 22966 ('CImg3d') +. 0.5 ({4*$N};$N) 22967 22968 # Generate list of random points. 22969 1,$N rand. $P,{$w-1-$P} +rand. $P,{$h-1-$P} a[-2,-1] x round. 22970 22971 # Generate list of primitives. 22972 ++. '-$P,-$P' ++.. '$P,-$P' ++... '$P,$P' ++[-4] '-$P,$P' 22973 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}) 22974 r.. 5,$N,1,1,3 round.. 1 a[-2,-1] x 22975 22976 # Generate list of vertices. 22977 1,$N rand. {225-$3},{225+$3} *. {pi/180} 22978 +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} 22979 r... 400%,100%,1,1,0,2 +[-3,-1] 22980 22981 # Generate materials. 22982 (-128;$w;$h;$s) +b[0] $5 22983 if $N>1 4,{$N-1},1,1,-128,0,0,0 fi 22984 1,$N,1,1,1 22985 22986 # Apply effect on current image. 22987 y[1--1] a[1--1] y rv3d. 22988 if $4>=1 j3d[0] [1],0,0,0,1,2,0,0 rm[1] 22989 else +j3d[0] [1],0,0,0,1,2,0,0 rm[1] blend alpha,$4 22990 fi 22991 22992 endl done 22993 22994#@cli draw_whirl : _amplitude>=0 22995#@cli : Apply whirl drawing effect on selected images. 22996#@cli : Default value: 'amplitude=100'. 22997#@cli : $ image.jpg draw_whirl , 22998draw_whirl : skip ${1=100} 22999 e[^-1] "Apply whirl drawing effect on image$? with amplitude $1." 23000 repeat $! l[$>] 23001 100%,100% noise. 70,2 ==. 1 *. 255 ri. .. &[-1,-2] smooth. $1,0,1,2,2 23002 sqrt. n. 0,255 equalize. 23003 endl done 23004 23005#@cli drawing : _amplitude>=0 23006#@cli : Apply drawing effect on selected images. 23007#@cli : Default value: 'amplitude=200'. 23008#@cli : $ image.jpg +drawing , 23009drawing : skip ${1=200} 23010 e[^-1] "Apply drawing effect on image$? with amplitude $1." 23011 repeat $! l[$>] split_opacity l[0] to_rgb 23012 smooth $1,0.2,1,3,3 b 2 sharpen 1000 [0] 23013 r[0] 20,20,1,3,2 equalize[0] index[1] [0],1,1 23014 nm[1] {0,n},1 rm[0] 23015 endl a c endl done 23016 23017#@cli drop_shadow : _offset_x[%],_offset_y[%],_smoothness[%]>=0,0<=_curvature<=1,_expand_size={ 0 | 1 } 23018#@cli : Drop shadow behind selected images. 23019#@cli : Default values: 'offset_x=20', 'offset_y=offset_x', 'smoothness=5', 'curvature=0' and 'expand_size=1'. 23020#@cli : $ image.jpg drop_shadow 10,20,5,0.5 expand_xy 20,0 display_rgba 23021drop_shadow : check "${3=5}>=0 && ${4=0}>=0 && $4<=1" skip ${1=20},${2=$1},${5=1} 23022 e[^-1] "Drop shadow behind image$?, with offsets ($1,$2), smoothness $3 and curvature $4." 23023 to_a repeat $! l[$>] 23024 nm={0,n} 23025 dx={if(${is_percent\ $1},w*$1,$1)} 23026 dy={if(${is_percent\ $2},h*$2,$2)} 23027 sigma={if(${is_percent\ $3},max(w,h)*$3,$3)} 23028 w={w} h={h} s={s} +channels 100% coords=${autocrop_coords.\ 0} rm. z $coords # Crop part with opaque pixels. 23029 r {w+abs($dx)},{h+abs($dy)},1,100%,0,0,{if($dx>0,0,1)},{if($dy>0,0,1)} 23030 r. {w+4*$sigma},{h+4*$sigma},1,100%,0,0,0.5,0.5 23031 +channels. 100% 23032 if !$4 shift. $dx,$dy # Flat shadow. 23033 else # Curved shadow. 23034 (0;{pi}) ri. ..,3 sin. *. -$4 +. 1 *. $dx 23035 (0,{pi}) ri. ..,3 sin. *. -$4 +. 1 *. $dy 23036 a[-2,-1] c warp.. .,1,0,0 rm. 23037 fi 23038 b. $sigma,0 23039 r. 100%,100%,1,2,0,0,0,0,0,1 mv. 0 blend alpha 23040 +channels. 100% >=. 1 * autocrop 0 23041 if !$5 $w,$h,1,$s j. ..,{arg(1,$coords)},{arg(2,$coords)} rm.. fi 23042 nm $nm 23043 endl done 23044 23045#@cli ellipsionism : _R>0[%],_r>0[%],_smoothness>=0[%],_opacity,_outline>0,_density>0 23046#@cli : Apply ellipsionism filter to selected images. 23047#@cli : Default values: 'R=10', 'r=3', 'smoothness=1%', 'opacity=0.7', 'outline=8' and 'density=0.6'. 23048#@cli : $ image.jpg ellipsionism , 23049ellipsionism : check "${1=10}>0 && ${2=3}>0 && ${5=8}>0 && ${6=0.6}>0" skip ${3=1%},${4=0.7} 23050 e[^-1] "Apply ellipsionism filter to image$?, with radii ($1,$2), smoothness $3, opacity $4 and outline $5." 23051 repeat $! l[$>] to_color 23052 23053 # Compute contour angle. 23054 +luminance g. xy a[-2,-1] c b. $3 orientation. 23055 sh. 0 sh.. 1 atan2. .. *. {180/pi} +. 90 rm[-2,-1] channels. 1,1 23056 23057 # Render ellipses. 23058 100%,100%,1,4 23059 eval " 23060 const interpolation = 1; 23061 const N = $6*wh/max($1,$2); 23062 repeat (N,n, 23063 x = round(u(w-1)); y = round(u(h-1)); 23064 ellipse(x,y,$1,$2,i(#-2,x,y)°,$4,I(#0,x,y),255); 23065 ellipse(x,y,-$1,-$2,i(#-2,x,y)°,$4,0xFFFFFFFF,I(#0,x,y)/$5,255); 23066 )" 23067 rm.. blend alpha 23068 endl done 23069 23070#@cli fire_edges : _edges>=0,0<=_attenuation<=1,_smoothness>=0,_threshold>=0,_nb_frames>0,_starting_frame>=0,\ 23071# frame_skip>=0 23072#@cli : Generate fire effect from edges of selected images. 23073#@cli : Default values: 'edges=0.7', 'attenuation=0.25', 'smoothness=0.5', 'threshold=25', 'nb_frames=1', \ 23074# 'starting_frame=20' and 'frame_skip=0'. 23075#@cli : $ image.jpg fire_edges , 23076fire_edges : check "${1=0.7}>=0 && ${2=0.25}>=0 && $2<=1 && ${3=0.5}>=0 && ${4=25}>=0 && ${5=1}>0 && 23077 ${6=20}>=0 && ${7=0}>=0" 23078 e[^-1] "Generate fire effect from edges of image$?, with edges $1, attenuation $2, smoothness $3, threshold $4, 23079 $5 frames, starting frame $6 and frame skip $7." 23080 repeat $! l[$>] nm={0,n} 23081 norm +gradient_norm n. 0,1 roundify. $1 f[0] 0 23082 (0,0,0;0,0,0;1,1,1;0,1,0) *. {(1-$2^4)/4} 23083 repeat $5*(1+$7)+$6 23084 {0,w},{0,h} rand. 0,255 *. [1] 23085 b. $3 23086 if $4 >=. $4% else equalize. fi 23087 n. 0,255 23088 j[0] .,0,0,0,0,1,[1],1 rm. 23089 correlate[0] [2] 23090 if $>>=$6" && "($>-$6)%($7+1)==0 [0] fi 23091 done rm[0-2] 23092 nm $nm endl done 23093 (0,255,255,255,255^0,0,255,255,255^0,0,0,128,255) r. 256,1,1,3,3 23094 map[^-1] . rm. 23095 23096#@cli fractalize : 0<=detail_level<=1 23097#@cli : Randomly fractalize selected images. 23098#@cli : Default value: 'detail_level=0.8' 23099#@cli : $ image.jpg fractalize , 23100fractalize : check "${1=0.8}>=0 && $1<=1" 23101 e[^-1] "Randomly fractalize image$?, with detail level $1." 23102 xc=0.4433 23103 yc=0.2645 23104 delta=0.1 23105 c0r=0.317 23106 c0i=0.03 23107 repeat $! l[$>] nm={0,n} 23108 luminance equalize 256 b 0.25% n 0,255 23109 100%,100% 23110 dx={$delta*w/max(w,h)} 23111 dy={$delta*h/max(w,h)} 23112 x0={$xc-$dx/2} 23113 y0={$yc-$dy/2} 23114 x1={$xc+$dx/2} 23115 y1={$yc+$dy/2} 23116 mandelbrot. $x0,$y0,$x1,$y1,256,1,$c0r,$c0i 23117 +==. 0 inpaint.. . rm. 23118 n. 0,256 23119 16,1,1,3 rand. 0,255 r. 256,1,1,3,3 map.. . rm. 23120 s. c 23121 i[2,3] [0] 23122 s={0.1*(1-$1)} 23123 parallel "register_nonrigid[1] [0],"$s",5","register_nonrigid[3] [2],"$s",5","register_nonrigid[5] [4],"$s",5" 23124 rm[0,2,4] a c nm $nm 23125 endl done 23126 23127#@cli glow : _amplitude>=0 23128#@cli : Add soft glow on selected images. 23129#@cli : Default value: 'amplitude=1%'. 23130#@cli : $ image.jpg glow , 23131glow : skip ${1=1%} 23132 e[^-1] "Add soft glow on image$?, with amplitude $1." 23133 repeat $! l[$>] split_opacity +b[0] $1 n. [0] blend_edges[0,-1] 1 a c endl done 23134 23135#@cli halftone : nb_levels>=2,_size_dark>=2,_size_bright>=2,_shape={ 0=square | 1=diamond | 2=circle | \ 23136# 3=inv-square | 4=inv-diamond | 5=inv-circle },_smoothness[%]>=0 23137#@cli : Apply halftone dithering to selected images. 23138#@cli : Default values: 'nb_levels=5', 'size_dark=8', 'size_bright=8', 'shape=5' and 'smoothnesss=0'. 23139#@cli : $ image.jpg halftone , 23140halftone : check "${1=5}>=2 && ${2=8}>=2 && ${3=8}>=2 && ${5=0}>=0" skip ${4=5} 23141 s0="square" s1="diamond" s2="circle" s3="inv-square" s4="inv-diamond" s5="inv-circle" 23142 e[^-1] "Apply halftone dithering to image$?, with $1 levels, dark size $3, bright size $4, "\ 23143 ${s$4}" shape and smoothness $5." 23144 repeat $! l[$>] s c repeat $! l[$>] 23145 (0,255) a y quantize $1,0 rows 0,{h-2} 23146 repeat $1 23147 s={round(($2*$<+$3*$>)/($1-1))} 23148 $s,$s =. 1,50%,50% distance. 1,{$4%3} +shift. {round(w/2)},{round(h/2)},0,0,2 min[-2,-1] 23149 if $4>=3 <. {100*$</($1-1.1)}% *. {-255} +. {255-$>} 23150 else <. {100*$>/($1-1.1)}% *. 255 -. $> 23151 fi 23152 ri. ..,0,2 b. $5 +==.. $> *[-2,-1] +[-2,-1] 23153 done endl done a c 23154 endl done 23155 23156#@cli hardsketchbw : _amplitude>=0,_density>=0,_opacity,0<=_edge_threshold<=100,_is_fast={ 0 | 1 } 23157#@cli : Apply hard B&W sketch effect on selected images. 23158#@cli : Default values: 'amplitude=1000', 'sampling=3', 'opacity=0.1', 'edge_threshold=20' and 'is_fast=0'. 23159#@cli : $ image.jpg +hardsketchbw 200,70,0.1,10 median[-1] 2 +local reverse blur[-1] 3 blend[-2,-1] overlay endlocal 23160hardsketchbw : skip ${1=300},${2=50},${3=0.1},${4=20},${5=0} 23161 e[^-1] "Apply hard B&W sketch effect on image$?, with amplitude $1, density $2, opacity $3 and edge threshold $4." 23162 if !$2 channels 0 f 255 return fi 23163 luminance n 0,1 23164 23165 if $5 # Fast version. 23166 repeat $! l[$>] nm={0,n} 23167 g xy rv *.. -1 a c 23168 if $4 +norm >=. $4% * fi 23169 100%,100%,1,1,255 quiver. ..,{max(1,10-$2/6)},$1,0,$3 rm.. 23170 nm $nm endl done 23171 23172 else # Slower version. 23173 repeat $! l[$>] nm={0,n} 23174 23175 # Isolate starting points and tangents. 23176 w={w} h={h} g xy rv *.. -1 a c * $1 23177 +norm >=. $4% 100%,100% noise. $2,2 ==. 1 *[-2,-1] 23178 23179 # Retrieve points coordinates and corresponding tangents. 23180 pointcloud3d. s3d. rm[-6--5,-3--1] r. 3,{h/3},1,1,-1 s. x rm. a[-2,-1] c 23181 warp.. .,0,0 +-. .. +[-3,-2] s[-2,-1] c 23182 23183 # Convert as a 3d object and render on white background. 23184 i... 1,{h} 1,{h} a[-6--1] x 23185 i.. ('CImg3d') i.. ({2*h},{h}) 23186 1,{h},1,1,2 1,{h},1,1,2*y ++. 1 a[-3--1] x 23187 3,{h} 1,{h},1,1,$3 y[-6--1] a[-6--1] y 23188 $w,$h,1,1,255 j3d. ..,0,0,0,1,1,0,0 rm.. 23189 nm $nm endl done 23190 fi 23191 23192#@cli hearts : _density>=0 23193#@cli : Apply heart effect on selected images. 23194#@cli : Default value: 'density=10'. 23195#@cli : $ image.jpg hearts , 23196hearts : skip ${1=10} 23197 e[^-1] "Apply heart filter on image$?, with density $1." 23198 repeat $! l[$>] 23199 100%,100%,1 noise. $1,2 ==. 1 ri. .. n. 0,1 *[-1,-2] _heart9x7 23200 dilate.. . rm. 23201 endl done 23202 23203_heart9x7 : 23204 (9,7,1,1,0,1,-1,2,-3,2,-1,4,-1,13,-1,7,-3,5,-5,3,-7,1,-4) 23205 decompress_rle. 23206 23207#@cli houghsketchbw : _density>=0,_radius>0,0<=_threshold<=100,0<=_opacity<=1,_votesize[%]>0 23208#@cli : Apply hough B&W sketch effect on selected images. 23209#@cli : Default values: 'density=100', 'radius=3', 'threshold=100', 'opacity=0.1' and 'votesize=100%'. 23210#@cli : $ image.jpg +houghsketchbw , 23211houghsketchbw : check "${1=100}>=0 && ${2=3}>=0 && ${3=100}>=0 && $3<=100 && ${4=0.1}>=0 && $4<=1 && ${5=100%}>0" 23212 e[^-1] "Apply hough B&W sketch effect on image$?, with density $1, radius $2, threshold $3, opacity $4 23213 and votesize $5." 23214 luminance repeat $! l[$>] nm={0,n} 23215 23216 # Compute normalized Hough transform. 23217 res={round(if(${is_percent\ $5},$5*max(w,h),$5))} w={w} h={h} rhomax={sqrt(w^2+h^2)/2} 23218 hough $res,$res n 0,255 23219 23220 # Retrieve coordinates of maximas in hough space. 23221 normalize_local. $1,$2 >=. $3% pointcloud3d. 23222 s3d. rm[-6--5,-3--1] r. 3,{h/3},1,1,-1 columns. 0,1 23223 23224 # Convert to (x0,y0)-(x1,y1) line coordinates. 23225 s. x,2 23226 *.. {2*pi/$res} # theta 23227 *. {$rhomax/$res} # rho 23228 +cos.. *. .. +. {$w/2} # x 23229 +sin... *. ... +. {$h/2} # y 23230 rm... # Remove rho 23231 i... ... 23232 cos[-4] sin... *[-4,-3] 10000 # cos(t) sin(t) 23233 ++.. ... # x + sin(t) 23234 +-.. [-5] # y - cos(t) 23235 -[-4] [-5] # x - sin(t) 23236 +... [-6] # y + cos(t) 23237 rm[-6,-5] 23238 23239 # Transform as a 3D object. 23240 i... 1,{h} 1,{h} a[-6--1] x # Vertices 23241 i.. ('CImg3d') i.. ({2*h},{h}) # Header and size. 23242 1,{h},1,1,2 1,{h},1,1,2*y ++. 1 a[-3--1] x # Primitives. 23243 3,{h},1,1,0 1,{h},1,1,$4 # Colors and opacities 23244 y[-6--1] a[-6--1] y 23245 23246 # Render on a white image. 23247 $w,$h,1,1,255 j3d. ..,0,0,0,1,1,0,0 rm.. 23248 nm $nm endl done 23249 23250#@cli lightrays : 100<=_density<=0,_center_x[%],_center_y[%],_ray_length>=0,_ray_attenuation>=0 23251#@cli : Generate ray lights from the edges of selected images. 23252#@cli : Default values: 'density=50%', 'center_x=50%', 'center_y=50%', 'ray_length=0.9' and 'ray_attenuation=0.5'. 23253#@cli : $ image.jpg +lightrays , + cut 0,255 23254lightrays : check "${1=50}>=0 && $1<=100 && ${4=1}>=0 && ${5=1}>=0" skip ${2=50%},${3=50%} 23255 e[^-1] "Generate ray lights from image$?, with density $1, center point ($2,$3), ray length $4 and attenuation $5." 23256 repeat $! l[$>] 23257 gradient_norm >= $1% euclidean2polar $2,$3 23258 repeat log2(w) +shift. {2^$>} +[-2,-1] done 23259 function1d 0.5,0,1,{$4*w},1,{1+($4+1-$5)*w},0 r. {-2,w},1,1,1,0 23260 (1,{w}) r. {-2,w},1,1,1,3 /[-2,-1] 23261 ri. .. *[-2,-1] polar2euclidean $2,$3 n 0,255 23262 endl done 23263 23264#@cli light_relief : _ambient_light,_specular_lightness,_specular_size,_darkness,_light_smoothness,_xl,_yl,_zl,\ 23265# _zscale,_opacity_is_heightmap={ 0 | 1 } 23266#@cli : Apply relief light to selected images. 23267#@cli : Default values(s) : 'ambient_light=0.3', 'specular_lightness=0.5', 'specular_size=0.2', 'darkness=0', \ 23268# 'xl=0.2', 'yl=zl=0.5', 23269#@cli : 'zscale=1', 'opacity=1' and 'opacity_is_heightmap=0'. 23270#@cli : $ image.jpg blur 2 light_relief 0.3,4,0.1,0 23271light_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} 23272 e[^-1] "Apply relief light to image$?." 23273 repeat $! l[$>] 23274 ({-$6},{1-$6};{-$6},{1-$6}^{-$7},{-$7};{1-$7},{1-$7}^$8,$8;$8,$8) r. ..,..,1,3,3 # Create light vector field. 23275 if $10 +channels.. 3 to_rgb... else +to_rgb.. norm. fi 23276 b. $5% g. xy 100%,100%,1,1,$9 a[-3--1] c # Create normal vector field. 23277 orientation[-2,-1] *[-2,-1] s. c +[-3--1] # Normalized scalar product. 23278 100%,100% =. 1,{$6*100}%,{$7*100}% distance. 1 sqr. *. -1 # Compute specular attenuation. 23279 /. {($3*max(w,h))^2} exp. *. $2 +. $1 23280 *[-2,-1] -. $4 *. {-2,iM} 23281 split_opacity[0] +[0,-1] a c c 0,255 23282 endl done 23283 23284#@cli linify : 0<=_density<=100,_spreading>=0,_resolution[%]>0,_line_opacity>=0,_line_precision>0,\ 23285# _mode={ 0=subtractive | 1=additive } 23286#@cli : Apply linify effect on selected images. 23287#@cli : The algorithm is inspired from the one described on the webpage <http://linify.me/about>. 23288#@cli : Default values: 'density=50', 'spreading=2', 'resolution=40%', 'line_opacity=10', 'line_precision=24' \ 23289# and 'mode=0'. 23290#@cli : $ image.jpg linify 60 23291linify : check "${1=40}>=0 && $1<=100 && ${2=2}>=0 && ${3=40%}>0 && ${4=10}>=0 && isint(${5=24}) && $5>0 && 23292 isbool(${6=0})" 23293 e[^-1] "Apply linify effect on image$?, with density $1, spreading $2, resolution $3, line opacity $4, 23294 line precision $5 and "${"-arg 1+$6,subtractive,additive"}" mode." 23295 repeat $! l[$>] remove_opacity nm={n} 23296 100%,100%,1,{s},$6?0:255 23297 if {0,w>h} r2dx[0] {${"-is_percent $3"}?max(1,$3*w):min(w,$3)} 23298 else r2dy[0] {${"-is_percent $3"}?max(1,$3*h):min(h,$3)} 23299 fi 23300 n[0] 0,100 23301 if narg($_debug)" && "!{*,w} w[] ${-fitscreen[]\ {1,[w,h]}} fi 23302 eval " 23303 is_in(ind,P) = (P[0]>=0 && P[0]<w#ind && P[1]>=0 && P[1]<h#ind); 23304 const add = $6; 23305 const density = add?100 - $1:$1; 23306 const spreading = max(0.1,$2); 23307 const opacity = $4; 23308 const precision = $5; 23309 const om2add = 1 - 2*add; 23310 23311 fact = [ w/w#0, h/h#0,1,1 ]; 23312 nb_lines = 0; 23313 ref0 = add?iM#0:im#0; 23314 do ( 23315 S = stats(#0); 23316 P0 = add?[ S[8],S[9],0,S[11] ]:[ S[4],S[5],0,S[7] ]; # coords of min or max intensity 23317 ref = S[add]; 23318 best_ang = best_avg = add?0:inf; 23319 repeat (precision,k, 23320 ang = u(360)*pi/180; 23321 dP = [ cos(ang), sin(ang),0,0 ]; 23322 dP/=max(abs(dP)); 23323 N = avg = 0; 23324 P = P0; while (is_in(#0,P), avg+=i(#0,P); ++N; P+=dP); 23325 P = P0; while (is_in(#0,P), avg+=i(#0,P); ++N; P-=dP); 23326 avg/=N; 23327 if (add?(avg>best_avg):(avg<best_avg), best_avg = avg; best_ang = ang); 23328 ); 23329 dP = [ cos(best_ang), sin(best_ang),0,0 ]; 23330 dP/=max(abs(dP)); 23331 P = P0; while (is_in(#0,P), i(#0,P)+=om2add*spreading; P+=dP); 23332 P = P0; while (is_in(#0,P), i(#0,P)+=om2add*spreading; P-=dP); 23333 P = P0*fact; while (is_in(#1,P), i(#1,P)-=om2add*opacity*spreading; P+=dP); 23334 P = P0*fact; while (is_in(#1,P), i(#1,P)-=om2add*opacity*spreading; P-=dP); 23335 if (!(nb_lines%250), 23336 progress = density==ref0?100:round(100*(ref - ref0)/(density - ref0)); 23337 run('progress ',vtos(progress)); 23338 if (narg("$_debug"), 23339 run('+c[1] 0,255 r. {*,w},{*,h},1,3,2 to. ',vtos(progress),'%,1%,1%,5%,1 w. -1,-1,0 rm.') 23340 ); 23341 ); 23342 ++nb_lines; 23343 breakpoint(); 23344 _(while), add?(ref>density):(ref<density))" 23345 k. c 0,255 nm $nm 23346 endl done 23347 23348#@cli mosaic : 0<=_density<=100 23349#@cli : Create random mosaic from selected images. 23350#@cli : Default values: 'density=30'. 23351#@cli : $ image.jpg mosaic , +fill "I!=J(1) || I!=J(0,1)?[0,0,0]:I" 23352mosaic : check "${1=30}>=0" 23353 e[^-1] "Apply mosaic effect on image$?, with density $1." 23354 repeat $! l[$>] 23355 100%,100%,1,2,'u<0.25*($1%)^4?[u,1]' s. c 23356 distance. 1 *. -1 watershed.. . rm. 23357 blend shapeaverage 23358 endl done 23359 23360#@cli old_photo 23361#@cli : Apply old photo effect on selected images. 23362#@cli : $ image.jpg old_photo 23363old_photo : 23364 e[^-1] "Apply old photo effect on image$?." 23365 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 23366 23367#@cli pencilbw : _size>=0,_amplitude>=0 23368#@cli : Apply B&W pencil effect on selected images. 23369#@cli : Default values: 'size=0.3' and 'amplitude=60'. 23370#@cli : $ image.jpg pencilbw , 23371pencilbw : skip ${1=0.3},${2=60} 23372 e[^-1] "Apply B&W pencil effect on image$?, with size $1 and amplitude $2." 23373 repeat $! l[$>] split_opacity l[0] 23374 norm b $1 sharpen 4000 smooth $2,0,1 equalize sqrt n 0,255 23375 endl a c endl done 23376 23377#@cli pixelsort : _ordering={ + | - },_axis={ x | y | z | xy | yx },_[sorting_criterion],_[mask] 23378#@cli : Apply a 'pixel sorting' algorithm on selected images, as described in the page : 23379#@cli : <http://satyarth.me/articles/pixel-sorting/>. 23380#@cli : Default values: 'ordering=+', 'axis=x' and 'sorting_criterion=mask=(undefined)'. 23381#@cli : $ image.jpg +norm +ge[-1] 30% +pixelsort[0] +,y,[1],[2] 23382pixelsort : check "(str1='${1=+}'; str1=='+' || str1=='-') && "\ 23383 "(str2='${2=x}'; str2=='x' || str2=='y' || str2=='z' || str2=='xy' || str2=='yx') && "\ 23384 "('${3=}'==0 || "${"is_image_arg $3"}") && "\ 23385 "('${4=}'==0 || "${"is_image_arg $4"}")" 23386 s0="descending" s1="ascending" 23387 if '$3'!=0" && "'$4'!=0 23388 e[^-1] "Apply 'pixelsort' effect to image$? in "${s{['$1']=='+'}}" order, along axis $2, 23389 with sorting criterion $3 and mask $4." 23390 elif '$3'!=0" && "'$4'==0 23391 e[^-1] "Apply 'pixelsort' effect to image$? in "${s{['$1']=='+'}}" order, along axis $2, 23392 with sorting criterion $3." 23393 elif '$3'==0" && "'$4'!=0 23394 e[^-1] "Apply 'pixelsort' effect to image$? in "${s{['$1']=='+'}}" order, along axis $2, 23395 with mask $4." 23396 else 23397 e[^-1] "Apply 'pixelsort' effect to image$? in "${s{['$1']=='+'}}" order, along axis $2." 23398 fi 23399 repeat $! 23400 if '$3'!=0 pass$3 0 else +compose_channels[$>] + fi 23401 if '$4'!=0 pass$4 0 else [$>],[$>],[$>],1,1 fi 23402 l[$>,-2,-1] 23403 nm={0,n} >=. 50% mv.. 0 a c 23404 order={`";'$1'=='+'?'<':'>'"`} 23405 if '$2'=='x'; 23406 _pixelsort $order channels 1,{s-2} 23407 elif '$2'=='y'; 23408 permute yxzc _pixelsort $order channels 1,{s-2} permute yxzc 23409 elif '$2'=='z'; 23410 permute zxyc _pixelsort $order channels 1,{s-2} permute yzxc 23411 elif '$2'=='xy'; 23412 _pixelsort $order permute yxzc _pixelsort $order channels 1,{s-2} permute yxzc 23413 elif '$2'=='yx'; 23414 permute yxzc _pixelsort $order permute yxzc _pixelsort $order channels 1,{s-2} 23415 fi 23416 nm $nm 23417 endl 23418 done 23419 23420_pixelsort : 23421 1,{h},{d} 23422 f. ": 23423 quicksort(x0,x1,y,z) = ( 23424 stack = vector"{0,2*w}"(); 23425 stacksize = 0; 23426 push(elt0,elt1) = (stack[stacksize++] = elt0; stack[stacksize++] = elt1); 23427 pop() = (_s1 = stack[--stacksize]; _s0 = stack[--stacksize]; [_s0,_s1]); 23428 swap(a,b) = (_tmp = a; a = b; b = _tmp); 23429 push(x0,x1); 23430 while (stacksize>0, 23431 range = pop(); 23432 lo = range[0]; 23433 hi = range[1]; 23434 pivot = i(#0,int((lo + hi)/2),y,z,0); 23435 while (lo<=hi, 23436 while (i(#0,lo,y,z,0)$1pivot, ++lo); 23437 while (pivot$1i(#0,hi,y,z,0), --hi); 23438 lo<=hi?(lo!=hi?(swap(I(#0,lo,y,z),I(#0,hi,y,z))); ++lo; --hi); 23439 ); 23440 range[0]<hi?push(range[0],hi); 23441 lo<range[1]?push(lo,range[1]); 23442 ) 23443 ); 23444 s1 = s#0 - 1; 23445 repeat (w#0,x0, 23446 if (i(#0,x0,y,z,s1), 23447 for (x1 = x0, x1<w#0 && i(#0,x1,y,z,s1)==1, ++x1); 23448 quicksort(x0,min(x1,w#0-1),y,z); 23449 x0 = ++x1; 23450 ) 23451 )" 23452 rm. 23453 23454#@cli polaroid : _size1>=0,_size2>=0 23455#@cli : Create polaroid effect in selected images. 23456#@cli : Default values: 'size1=10' and 'size2=20'. 23457#@cli : $ image.jpg to_rgba polaroid 5,30 rotate 20 drop_shadow , drgba 23458polaroid : check "${1=10}>=0 && ${2=20}>=0" 23459 e[^-1] "Create polaroid effect in image$?, with borders sizes $1 and $2." 23460 - 255 r {100+$1}%,{100+$1}%,1,100%,0,0,0.5,0.5 r 100%,{100+$2}%,1,100%,0,0,0 + 255 23461 23462#@cli polygonize : _warp_amplitude>=0,_smoothness[%]>=0,_min_area[%]>=0,_resolution_x[%]>0,_resolution_y[%]>0 23463#@cli : Apply polygon effect on selected images. 23464#@cli : Default values: 'warp_amplitude=300', 'smoothness=2%', 'min_area=0.1%', 'resolution_x=resolution_y=10%'. 23465#@cli : $ image.jpg image.jpg polygonize 100,10 +fill "I!=J(1) || I!=J(0,1)?[0,0,0]:I" 23466polygonize : check "${1=300}>=0 && ${2=2%}>=0 && ${3=0.1%}>=0 && ${4=10%}>0 && ${5=$4}>0" 23467 e[^-1] "Polygonize image$? with warp amplitude $1, smoothness $2, minimal area $3 and resolutions ($4,$5)." 23468 repeat $! l[$>] 23469 +b $2 gradient_norm. g. a[-2,-1] c channels. 0,2 *. {1/0.1+max(abs(im),abs(iM))} 23470 resx={max(1,round(if(${is_percent\ $4},w*$4,w/$4)-1))} 23471 resy={max(1,round(if(${is_percent\ $5},h*$5,h/$5)-1))} 23472 plane3d 1,1,$resx,$resy *3d. {0,w-1},{0,h-1},1 23473 s3d. rm.. i.. (0;{h-1}) r.. 3,{h},1,1,3 round.. y.. 23474 [-4] a[-7--2] y r. 3,{h/3},1,1,-1 z. 0,1 permute. yzcx 23475 repeat $1 +warp[1] .,0,0 +[-2,-1] done 23476 permute. cxyz z. 0,2 y. j[2] .,0,8 rm[-3,-1] 23477 [0],[0] j3d. [1],0,0,0,1,2 rm[1] 23478 if $3>0 23479 min_area={0,if(${is_percent\ $3},$3*w*h,$3)} 23480 +area. 0,1 >=. $min_area +.. 1 *.. . distance. 1 *. -1 watershed.. . rm. 23481 fi 23482 blend shapeaverage 23483 endl done 23484 23485#@cli poster_edges : 0<=_edge_threshold<=100,0<=_edge_shade<=100,_edge_thickness>=0,_edge_antialiasing>=0,\ 23486# 0<=_posterization_level<=15,_posterization_antialiasing>=0 23487#@cli : Apply poster edges effect on selected images. 23488#@cli : Default values: 'edge_threshold=40', 'edge_shade=5', 'edge_thickness=0.5', 'edge_antialiasing=10', \ 23489# 'posterization_level=12' and 'posterization_antialiasing=0'. 23490#@cli : $ image.jpg poster_edges , 23491poster_edges : check "${1=40}>=0 && $1<=100 && ${2=5}>=0 && $2<=100 && ${3=0.5}>=0 && ${4=10}>=0 && 23492 ${5=12}>=0 && $5<=15 && ${6=0}>=0" 23493 e[^-1] "Apply poster edge on image$?, with edge threshold $1, edge shade $2, edge thickness $3, 23494 edge antialiasing $4, $5 level of posterization and posterization antialiasing $6." 23495 repeat $! l[$>] split_opacity l[0] 23496 +g xy,1 a[-2,-1] c norm. b. $3 n. 0,255 23497 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 23498 if $4 smooth. {min(50,$4)},0,1,{$4/40},{$4/40},0.8,90 fi 23499 if $5 autoindex[0] {round((4-sqrt($5+1))*32+2)} fi 23500 if $6 smooth[0] {min(50,$6)},0,1,{$6/40},{$6/40},0.8,90 fi 23501 * 23502 endl a c endl done 23503 23504#@cli poster_hope : _smoothness>=0 23505#@cli : Apply Hope stencil poster effect on selected images. 23506#@cli : Default value: 'smoothness=3'. 23507#@cli : $ image.jpg poster_hope , 23508poster_hope : check "${1=3}>=0" 23509 e[^-1] "Apply Hope stencil poster effect on image$?, with smoothness $1." 23510 repeat $! l[$>] to_rgb 23511 apc "smooth 200,0,1,$1,1" 23512 quantize 7,0 f 'if(i!=5,i,i+1-2*(y%2))' 23513 (0,32,47;0,32,47;209,1,23;209,1,23;90,141,145;-1,-1,-1;253,221,138) permute. yzcx 23514 map[0] [1] rm[1] 23515 endl done 23516 23517#@cli rodilius : 0<=_amplitude<=100,_0<=thickness<=100,_sharpness>=0,_nb_orientations>0,_offset,\ 23518# _color_mode={ 0=darker | 1=brighter } 23519#@cli : Apply rodilius (fractalius-like) filter on selected images. 23520#@cli : Default values: 'amplitude=10', 'thickness=10', 'sharpness=400', 'nb_orientations=7', 'offset=0' \ 23521# and 'color_mode=1'. 23522#@cli : $ image.jpg rodilius 12,10,300,10 normalize_local 10,6 23523#@cli : $ image.jpg normalize_local 10,16 rodilius 10,4,400,16 smooth 60,0,1,1,4 normalize_local 10,16 23524rodilius : check "${1=10}>=0 && $1<=200 && ${2=10}>=0 && $2<=100 && ${3=400}>=0 && ${4=7}>0" skip ${5=0},${6=1} 23525 e[^-1] "Apply rodilius filter on image$? with amplitude $1, thickness $2, sharpness $3, $4 orientations, 23526 offset $5 and "${arg\ 1+!$6,brighter,darker}" color mode." 23527 repeat $! l[$>] split_opacity rv 23528 if !$6 negate. fi 23529 +f. 0 nm. {-2,n} 23530 repeat round($4) 23531 angle={$5+$>*180/round($4)} 23532 +blur_linear.. $1%,{$1*$2/100}%,$angle,1 b. 0.7 sharpen. $3 max[-2,-1] 23533 done rm.. 23534 if !$6 negate. fi 23535 rv a c endl done 23536 23537#@cli sketchbw : _nb_angles>0,_start_angle,_angle_range>=0,_length>=0,_threshold>=0,_opacity,_bgfactor>=0,\ 23538# _density>0,_sharpness>=0,_anisotropy>=0,_smoothness>=0,_coherence>=0,_is_boost={ 0 | 1 },_is_curved={ 0 | 1 } 23539#@cli : Apply sketch effect to selected images. 23540#@cli : Default values: 'nb_angles=2', 'start_angle=45', 'angle_range=180', 'length=30', 'threshold=3', \ 23541# 'opacity=0.03', 'bgfactor=0', 'density=0.6', 'sharpness=0.1', 'anisotropy=0.6', 'smoothness=0.25', 'coherence=1', \ 23542# 'is_boost=0' and 'is_curved=1'. 23543#@cli : $ image.jpg +sketchbw 1 reverse blur[-1] 3 blend[-2,-1] overlay 23544sketchbw : 23545 check "${1=2}>0 && ${3=180}>=0 && ${4=30}>=0 && ${5=3}>=0 && ${7=0}>=0 && ${8=0.6}>0 && ${9=0.1}>=0 && 23546 ${10=0.6}>=0 && ${11=0.25}>=0 && ${12=1}>=0" 23547 skip ${2=45},${6=0.03},${13=0},${14=0} 23548 e[^-1] "Apply B&W sketch effect on image$?." 23549 nb_angles,start_angle,angle_range,length,threshold,opacity,bgfactor,density,sharpness,\ 23550 anisotropy,smoothness,coherence,is_boost,is_curved=${1-14} 23551 length={max($length,1)} 23552 repeat $! l[$>] 23553 {0,[w,h,1,1,0]} # [1] = canvas to draw onto 23554 +gradient_norm[0] sqrt. 23555 diffusiontensors[0] $sharpness,$anisotropy,$smoothness,$coherence 23556 a[0,-1] c # [0] = field of stroke tensors + gradient norm 23557 1,{$density*wh/sqrt($length)},1,2,round(u([w#0,h#0]-1)) # [2] = set of random points 23558 23559 repeat $nb_angles 23560 23561 # Compute vector field for considered orientation. 23562 [0],[0],1,2," 23563 const angle = ("$start_angle" + "$>"*"$angle_range"/"$nb_angles")*pi/180; 23564 const ca = cos(angle); 23565 const sa = sin(angle); 23566 T = I(#0); 23567 U = [ T[0]*ca + T[1]*sa, T[1]*ca + T[2]*sa ]; 23568 if ("$is_boost",U/=(1e-8 + norm(U))); 23569 U" 23570 23571 # Draw curved or straight strokes. 23572 if $is_curved 23573 f[2] "* 23574 oub = ovb = ouf = ovf = 0; 23575 oixb = xb = xf = i0; 23576 oiyb = yb = yf = i1; 23577 oixf = oiyf = -1; 23578 op = "$opacity" * (i(#0,xf,yf,0,3)<"$threshold"?"$bgfactor":1); 23579 omop = 1 - op; 23580 23581 if (op>0, repeat ("$length",dl, 23582 23583 # Forward 23584 ixf = round(xf); 23585 iyf = round(yf); 23586 if (ixf!=oixf || iyf!=oiyf, (i(#1,ixf,iyf)*=omop)+=op; oixf = ixf; oiyf = iyf); 23587 uf = i(#-1,xf,yf,0,0,1,1); 23588 vf = i(#-1,xf,yf,0,1,1,1); 23589 if (ouf*uf + ovf*vf<0, uf*=-1; vf*=-1); 23590 xf+=uf; 23591 yf+=vf; 23592 ouf = uf; 23593 ovf = vf; 23594 23595 # Backward 23596 ub = i(#-1,xb,yb,0,0,1,1); 23597 vb = i(#-1,xb,yb,0,1,1,1); 23598 if (oub*ub + ovb*vb<0, ub*=-1; vb*=-1); 23599 xb-=ub; 23600 yb-=vb; 23601 oub = ub; 23602 ovb = vb; 23603 ixb = round(xb); 23604 iyb = round(yb); 23605 if (ixb!=oixb || iyb!=oiyb, (i(#1,ixb,iyb)*=omop)+=op; oixb = ixb; oiyb = iyb); 23606 )); 23607 I" 23608 else 23609 f[2] "* 23610 const l = "$length"; 23611 x = i0; 23612 y = i1; 23613 u = i(#-1,x,y,0,0); 23614 v = i(#-1,x,y,0,1); 23615 op = "$opacity" * (i(#0,x,y,0,3)<"$threshold"?"$bgfactor":1); 23616 omop = 1 - op; 23617 polygon(#1,2,x - l*u,y - l*v,x + l*u,y + l*v,op,1); 23618 I" 23619 fi 23620 rm. 23621 done 23622 k.. * -1 n 0,255 23623 endl done 23624 23625#@cli sponge : _size>0 23626#@cli : Apply sponge effect on selected images. 23627#@cli : Default value: 'size=13'. 23628#@cli : $ image.jpg sponge , 23629sponge : skip ${1=13} 23630 e[^-1] "Apply sponge filter on image$?, with brush size $1." 23631 repeat $! l[$>] 23632 100%,100%,1,1 noise. 20,2 ==. 1 ri. .. n. 0,1 *[-1,-2] 23633 _circle $1 dilate.. . rm. 23634 endl done 23635 23636_circle : 23637 if $1%2==0 2,2 else 1 fi 23638 +. 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 23639 23640#@cli stained_glass : _edges[%]>=0, shading>=0, is_thin_separators={ 0 | 1 } 23641#@cli : Generate stained glass from selected images. 23642#@cli : Default values: 'edges=40%', 'shading=0.2' and 'is_precise=0'. 23643#@cli : $ image.jpg stained_glass 20%,1 cut 0,20 23644stained_glass : check "${1=40%}>=0 && ${2=0.2}>=0" skip ${3=0} 23645 e[^-1] "Apply stained glass effect on image$?, with edges $1, shading $2 and thin-separators "\ 23646 ${arg\ 1+!$3,enabled,disabled}"." 23647 repeat $! l[$>] 23648 im={im-1} - $im # Ensure strict positiveness of image labels. 23649 +gradient_norm >=. $1 *.. . 23650 distance. 1 sharpen. 1e10 !=. 0 23651 if $3 skeleton. 0 fi 23652 distance. 1 watershed.. . +.. $im 23653 n. 0,1 ^. $2 * 23654 endl done 23655 23656#@cli stars : _density[%]>=0,_depth>=0,_size>0,_nb_branches>=1,0<=_thickness<=1,_smoothness[%]>=0,_R,_G,_B,_opacity 23657#@cli : Add random stars to selected images. 23658#@cli : Default values: 'density=10%', 'depth=1', 'size=32', 'nb_branches=5', 'thickness=0.38', 'smoothness=0.5', \ 23659# 'R=G=B=200' and 'opacity=1'. 23660#@cli : $ image.jpg stars , 23661stars : check "${1=10%}>=0 && ${2=1}>=0 && ${3=32}>0 && ${4=5}>=1 && ${5=0.38}>=0 && $5<=1 && ${6=0.5}>=0" 23662 skip ${7=200},${8=$7},${9=$8},${10=1} 23663 e[^-1] "Add $1 random stars to image$?, with depth $2, size $3, $4 branches, thickness $5, smoothness $6, 23664 color ($7,$8,$9) and opacity $10." 23665 if !$1 return fi 23666 23667 # Generate star sprites. 23668 star3d $4,$5 col3d. 255 *3d. $3 23669 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 23670 autocrop[-4--1] 0 r2dy[-4--1] $3 b[-4--1] $6,0 r[-4--1] 100%,100%,1,4 23671 repeat 4 sh[{-1-$>}] 0,2 fc. $7,$8,$9 rm. done 23672 23673 # Draw stars on selected images. 23674 repeat $!-1 [-4--1] l[$>,-4--1] 23675 N={round(if(${is_percent\ $1},w*h*$1,$1)/4,1,1)} 23676 repeat 4 23677 2,$N rand. -1,1 1,$N rand. 0,1 a[-2,-1] x 23678 i.. ('CImg3d') +.. 0.5 i.. ($N;$N) 23679 (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 23680 rv[-2,-1] sprites3d.. .,1 rm. *3d. {0.75*{0,w}},{0.75*{0,h}},{1000*$2} 23681 j3d[0] .,50%,50%,0,$10,0,0,0 rm. 23682 done 23683 endl done 23684 rm[-4--1] 23685 23686#@cli stencil : _radius[%]>=0,_smoothness>=0,_iterations>=0 23687#@cli : Apply stencil filter on selected images. 23688#@cli : Default values: 'radius=3', 'smoothness=1' and 'iterations=8'. 23689#@cli : $ image.jpg +norm stencil. 2,1,4 +mul rm[0] 23690stencil : check "${1=3}>=0 && ${2=1}>=0 && ${3=8}>=0" 23691 e[^-1] "Apply stencil filter on image$?, with radius $1, smoothness $2 and $3 iterations." 23692 n 0,1 repeat $3 b $1 unsharp {$1+$2},1000 c 0,255 done 23693 23694#@cli stencilbw : _edges>=0,_smoothness>=0 23695#@cli : Apply B&W stencil effect on selected images. 23696#@cli : Default values: 'edges=15' and 'smoothness=10'. 23697#@cli : $ image.jpg +stencilbw 40,4 23698stencilbw : skip ${1=15},${2=10} 23699 e[^-1] "Apply B&W stencil effect on image$?, with edges $1 and smoothness $2." 23700 repeat $! l[$>] split_opacity luminance[0] n[0] 0,255 23701 +edges[0] $1 quantize[0] 3,0,1 b[0] $2 23702 sharpen[0] 1000000 n[0] 0,1 *[0,-1] n[0] 0,255 23703 a c endl done 23704 23705#@cli stylize : [style_image],_fidelity_finest,_fidelity_coarsest,_fidelity_smoothness_finest>=0,\ 23706# _fidelity_smoothnes_coarsest>=0,0<=_fidelity_chroma<=1,_init_type,_init_resolution>=0,init_max_gradient>=0,\ 23707# _patchsize_analysis>0,_patchsize_synthesis>0,_patchsize_synthesis_final>0,_nb_matches_finest>=0,\ 23708# _nb_matches_coarsest>=0,_penalize_repetitions>=0,_matching_precision>=0,_scale_factor>1,_skip_finest_scales>=0,\ 23709# _"image_matching_command" 23710#@cli : Transfer colors and textures from specified style image to selected images, using a multi-scale \ 23711# patch-mathing algorithm. 23712#@cli : If instant display window[0] is opened, the steps of the image synthesis are displayed on it. 23713#@cli : 'init_type' can be { 0=best-match | 1=identity | 2=randomized }. 23714#@cli : Default values: 'fidelity_finest=0.5', 'fidelity_coarsest=2', 'fidelity_smoothness_finest=3', \ 23715# 'fidelity_smoothness_coarsest=0.5', 'fidelity_chroma=0.1', 'init_type=0', 'init_resolution=16', \ 23716# 'init_max_gradient=0', 'patchsize_analysis=5', 'patchsize_synthesis=5', 'patchsize_synthesis_final=5', \ 23717# 'nb_matches_finest=2', 'nb_matchesc_coarsest=30', 'penalize_repetitions=10', 'matching_precision=2', \ 23718# 'scale_factor=1.85', 'skip_finest_scales=0' and \ 23719# '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 a[0,1] c a[1,2] c"'. 23720stylize : 23721 check ${"is_image_arg $1"}" && isnum(${2=0.5}) && isnum(${3=2}) && ${4=3}>=0 && ${5=0.5}>=0 && ${6=0.1}>=0 && "\ 23722 "$6<=1 && isint(${7=0}) && $7>=0 && $7<=3 && isint(${8=16}) && $8>=0 && ${9=0}>=0 && isint(${10=5}) && "\ 23723 "$10>0 && isint(${11=5}) && $11>0 && isint(${12=$11}) && $12>0 && isint(${13=2}) && isint(${14=30}) && "\ 23724 "${15=10}>=0 && ${16=2}>=0 && ${17=1.85}>1 && isint(${18=0})>=0" 23725 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}" 23726 e[^-1] "Stylize image$? with style image $1." 23727 fidelity_finest,\ # $2 23728 fidelity_coarsest,\ # $3 23729 fidelity_smoothness_finest,\ # $4 23730 fidelity_smoothness_coarsest,\ # $5 23731 fidelity_chroma,\ # $6 23732 init_type,\ # $7 23733 init_resolution,\ # $8 23734 init_max_gradient,\ # $9 23735 patchsize_analysis,\ # $10 23736 patchsize_synthesis,\ # $11 23737 patchsize_synthesis_final,\ # $12 23738 nb_matches_finest,\ # $13 23739 nb_matches_coarsest,\ # $14 23740 penalize_repetitions,\ # $15 23741 matching_precision,\ # $16 23742 scale_factor,\ # $17 23743 skip_finest_scales=${2-18} \ # $18 23744 m "stylize_match : $19" 23745 23746 init_resolution={max(2*$patchsize_analysis,$init_resolution)} 23747 mprec0={round(2+1.5*$matching_precision)} 23748 mprec1={1+round(4*$matching_precision)} 23749 is_window={*} 23750 23751 pass$1 repeat $!-1 l[$>,-1] 23752 to_colormode.. {s} 23753 nb_scales={1+round(log(min(w#0,h#0,w#1,h#1)/$init_resolution)/log($scale_factor),1,-1)} 23754 if {*} wsiz=${"fitscreen "{0,[w,h]}} w[0] $wsiz,0,"[G'MIC Stylize]" fi 23755 23756 repeat $nb_scales,scale 23757 size_factor={100/($scale_factor^$<)} 23758 if !$scale 23759 23760 # Initialization. 23761 +r[0,1] $size_factor%,$size_factor%,100%,100%,2 ws,hs={-2,[w,h]} 23762 +to_color[0,1] channels[-2,-1] 0,2 gradient_norm[-2,-1] 23763 r. [-3],[-3],[-3],1,2 r.. [-4],[-4],[-4],1,2 23764 a[-3,-1] c a[-3,-1] c # Append gradient information as last channel 23765 stylize_match[-2,-1] 23766 if $init_type==0 23767 +matchpatch.. .,3,3,1,{2*$mprec0},{2*$mprec1},$penalize_repetitions # Initial image match with 3x3 patches 23768 else 23769 ..,..,1,2,"round([x,y]*([w#-1,h#-1]-1)/([w,h]-1))" # Identity 23770 if d#-2>1 channels. 0,2 fi 23771 if $init_type==2 eval. ">P = u([w,h]-1); tmp = I(P); I(P) = I; I() = tmp" fi # Randomize 23772 fi 23773 rm[-3,-2] 23774 if $init_max_gradient>0 # Keep only high gradients of target image 23775 +gradient_norm[0] r. ..,..,1,1,2 gt. $init_max_gradient 23776 +.. 1 *[-2,-1] _inpaint_warping2d. --. 1 23777 fi 23778 if $is_window" && "!{*} break fi 23779 23780 else 23781 23782 # Upscale. 23783 factor={1-($scale-1)/max(1,$nb_scales-2)} # Linear scale factor from 1 to 0 23784 +r[0,1] $size_factor%,$size_factor%,100%,100%,2 23785 +to_color[-2,-1] channels[-2,-1] 0,2 gradient_norm[-2,-1] 23786 23787 a[-3,-1] c a[-3,-1] c # Append gradient information as last channel 23788 stylize_match[-2,-1] mv[-2,-1] -3 23789 sh. 0 *. {-3,w/$ws} rm. sh. 1 *. {-3,h/$hs} rm. round. 23790 23791 # Smart upscale of displacement field. 23792 +. 1 r. ...,...,1,100%,4 -. 1 23793 do 23794 f. "begin(const boundary = 1; nx = ny = vectors(); nx[0] = ny[1] = 1); 23795 i>=0?I:( 23796 j(-1)>=0?J(-1) + nx: 23797 j(0,-1)>=0?J(0,-1) + ny: 23798 j(1)>0?J(1) - nx: 23799 j(0,1)>0?J(0,1) - ny:I)" 23800 while im<0 23801 ws,hs={-2,[w,h]} 23802 23803 if $<<$skip_finest_scales rm[-3,-2] continue fi # Skip finest scales 23804 +warp_patch.. .,$patchsize_synthesis,$patchsize_synthesis,1 23805 if {*} w. fi 23806 23807 # Inject gradients from target (in Lab colorspace). 23808 fidelity={max(0,$fidelity_finest+($fidelity_coarsest-$fidelity_finest)*$factor)} 23809 fidelity_smoothness={$fidelity_smoothness_finest+\ 23810 ($fidelity_smoothness_coarsest-$fidelity_smoothness_finest)*$factor} 23811 23812 if $fidelity>0.1 23813 sh. 0,2 sh[-5] 0,2 +gradient_norm[-2,-1] rm[-4,-3] # Gradient norm on colors only 23814 *. $fidelity argmax[-2,-1] b. xy,$fidelity_smoothness n. 0,{min(1,$fidelity)} 23815 sh[-5,-2] 0,2 srgb2lab[-2,-1] rm[-2,-1] 23816 +*. $fidelity_chroma r. 100%,100%,1,2,1 a[-2,-1] c j.. [-5],0,0,0,0,1,. rm. 23817 sh. 0,2 lab2srgb. rm. 23818 fi 23819 rm[-4] 23820 23821 # Iterate patch-matching steps. 23822 nb_matches={max(0,round($nb_matches_finest+($nb_matches_coarsest-$nb_matches_finest)*$factor^2))} 23823 nb_scales1={$nb_scales-1} 23824 nb_matches1={$nb_matches-1} 23825 if {*} +r. $wsiz,1,100% to. "Scale "$scale/$nb_scales1": 0%",5,2,24 w. -1,-1,0 rm. fi 23826 23827 repeat $nb_matches 23828 matchpatch. ...,$patchsize_analysis,$patchsize_analysis,1,$mprec0,$mprec1,$penalize_repetitions,0,.. 23829 -.. . abs.. diff={-2,ia} rm.. 23830 +warp_patch.. .,$patchsize_synthesis,$patchsize_synthesis,1 23831 if {*}" && "(!($>%5)" || "$nb_matches<=10) 23832 +r. $wsiz,1,100% 23833 to. "Scale "$scale/$nb_scales1": "{round(100*($>+1)/$nb_matches)}%,5,2,24 w. -1,-1,0 rm. 23834 fi 23835 if $is_window" && "!{*} break fi 23836 if $diff<1 break fi 23837 done 23838 rm[-3,-1] 23839 fi 23840 if $is_window" && "!{*} break fi 23841 done 23842 if $is_window" && "!{*} k[0,1] break fi 23843 23844 # Do final rendering. 23845 +warp_patch[1] .,$patchsize_synthesis_final,$patchsize_synthesis_final,1 c. 0,255 23846 rv[0,-1] rm[-2,-1] 23847 endl done rm. 23848 um stylize_match 23849 23850#@cli tetris : _scale>0 23851#@cli : Apply tetris effect on selected images. 23852#@cli : Default value: 'scale=10'. 23853#@cli : $ image.jpg +tetris 10 23854tetris : skip ${1=10} 23855 e[^-1] "Apply tetris effect on image$?, with scale $1." 23856 repeat $! l[$>] 23857 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 23858 endl done 23859 23860#@cli warhol : _M>0,_N>0,_smoothness>=0,_color>=0 23861#@cli : Create MxN Andy Warhol-like artwork from selected images. 23862#@cli : Default values: 'M=3', 'N=M', 'smoothness=2' and 'color=20'. 23863#@cli : $ image.jpg warhol 3,3,3,40 23864warhol : skip ${1=3},${2=$1},${3=2},${4=20} 23865 e[^-1] "Create $1x$2 Andy Warhol-like artwork from image$?." 23866 r0={100/max($1,$2)} 23867 repeat $! l[$>] 23868 norm b $3 r $r0%,$r0%,1,100%,2 quantize 6 n 0,5 round 1 23869 repeat $1 repeat $2 23870 (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.. 23871 done done append_tiles[^0] $1,$2 nm[1] {0,n} rm[0] 23872 endl done 23873 23874#@cli weave : _density>=0,0<=_thickness<=100,0<=_shadow<=100,_shading>=0,_fibers_amplitude>=0,_fibers_smoothness>=0,\ 23875# _angle,-1<=_x_curvature<=1,-1<=_y_curvature<=1 23876#@cli : Apply weave effect to the selected images. 23877#@cli : 'angle' can be { 0=0 deg. | 1=22.5 deg. | 2=45 deg. | 3=67.5 deg. }. 23878#@cli : Default values: 'density=6', 'thickness=65', 'shadow=40', 'shading=0.5', 'fibers_amplitude=0', _\ 23879# 'fibers_smoothness=0', 'angle=0' and 'curvature_x=curvature_y=0' 23880#@cli : $ image.jpg weave , 23881weave : check "${1=6}>=0 && ${2=65}>=0 && $2<=100 && ${3=40}>=0 && $3<=100 && ${4=0.5}>=0" 23882 check "${5=0}>=0 && ${6=0}>=0 && ${7=0}>=0 && $7<=3 && ${8=0}>=-1 && $8<=1 && ${9=0}>=-1 && $9<=1" 23883 e[^-1] "Apply weave effect to image$?, with $1 strips, thickness $2, shadow $3, shading $4, "\ 23884 "fibers amplitude $5 and fibers smoothness $6, angle "{$7*22.5}" deg. and curvatures ($8,$9)." 23885 repeat $! l[$>] split_opacity l[0] 23886 w={round(max(w,h)/$1,1,1)} h=$w s={(100-$3)*255%} p={max(0.01,$4)} 23887 23888 # Create patterns. 23889 1,$h =. 1,0,50% distance. 1 ^. $p c. 50%,100% r. {max(1,round($2*$w%))},100% 23890 $w,1 =. 1,50% distance. 1 ^. $p c. 50%,100% *. -1 r. 100%,{max(1,round($2*$h%))} 23891 +*. -1 +*... -1 n[-4,-2] 0,$s n[-3,-1] $s,255 23892 {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] 23893 +f... 255 a[-4,-1] c +f. 255 a[-2,-1] c 23894 23895 amp_x={$8*($w-w)/2} amp_y={$9*($w-w)/2} 23896 r[-4--1] $w,$h,1,100%,0,0,0.5,0.5 23897 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)' 23898 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)' 23899 blend[-4,-3] alpha blend[-2,-1] alpha c[-2,-1] 0,255 23900 23901 # Render full pattern and merge. 23902 /[-2,-1] 255 . ... a[-4,-2] x a[-2,-1] x a[-2,-1] y rotate_tileable. {$7*22.5} 23903 r. ..,..,1,1,0,2 *[-2,-1] 23904 endl a c endl done 23905 23906#@cli whirls : _texture>=0,_smoothness>=0,_darkness>=0,_lightness>=0 23907#@cli : Add random whirl texture to selected images. 23908#@cli : Default values: 'texture=3', 'smoothness=6', 'darkness=0.5' and 'lightness=1.8'. 23909#@cli : $ image.jpg whirls , 23910whirls : skip ${1=3},${2=6},${3=0.5},${4=1.8} 23911 e[^-1] "Add random whirl texture to image$?, with texture $1, smoothness $2, darkness $3 and lightness $4." 23912 repeat $! l[$>] 23913 100%,100% noise. 0.3,2 ==. 1 repeat $1 b. $2 +. 0.1 gradient_norm. ^. 0.2 done 23914 n. $3,$4 ri. .. * c 0,255 23915 endl done 23916 23917#------------------------------------ 23918# 23919#@cli :: Warpings 23920# 23921#------------------------------------ 23922 23923#@cli deform : _amplitude>=0,_interpolation 23924#@cli : Apply random smooth deformation on selected images. 23925#@cli : 'interpolation' can be { 0=none | 1=linear | 2=bicubic }. 23926#@cli : Default value: 'amplitude=10'. 23927#@cli : $ image.jpg +deform[0] 10 +deform[0] 20 23928deform : skip ${1=10},${2=1} 23929 e[^-1] "Apply random smooth deformation on image$?, with amplitude $1." 23930 repeat $! l[$>] 23931 2%,2%,1,2 noise. $1 r. ..,..,1,2,5 warp.. .,1,$2,1 rm. 23932 endl done 23933 23934#@cli euclidean2polar : _center_x[%],_center_y[%],_stretch_factor>0,\ 23935# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 23936#@cli : Apply euclidean to polar transform on selected images. 23937#@cli : Default values: 'center_x=center_y=50%', 'stretch_factor=1' and 'boundary_conditions=1'. 23938#@cli : $ image.jpg +euclidean2polar , 23939euclidean2polar : skip ${1=50%},${2=50%} check "${3=1}>0 && isint(${4=1}) && $4>=0 && $4<=3" 23940 e[^-1] "Apply euclidean to polar transform on image$?, with center point ($1,$2), stretch factor $3 and "\ 23941 ${"arg 1+$4,dirichlet,neumann,periodic,mirror"}" boundary conditions." 23942 repeat $! l[$>] 23943 cx={if(${is_percent\ $1},$1*(w-1),$1)} 23944 cy={if(${is_percent\ $2},$2*(h-1),$2)} 23945 R={sqrt(max($cx^2,(w-1-$cx)^2)+max($cy^2,(h-1-$cy)^2))} 23946 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)' 23947 endl done 23948 23949#@cli equirectangular2nadirzenith 23950#@cli : Transform selected equirectangular images to nadir/zenith rectilinear projections. 23951equirectangular2nadirzenith : 23952 e[^-1] "Transform equirectangular image$? to nadir/zenith rectilinear projections." 23953 repeat $! l[$>] 23954 100%,100%,1,2 23955 sh. 100% 23956 f. " 23957 X = 2*x/(w-1) - 1; 23958 Y = y/(h-1) - 0.5; 23959 if (X<0, 23960 sinphi1 = 1; X+=0.5, 23961 sinphi1 = -1; X-=0.5 23962 ); 23963 rr = sqrt(X*X + Y*Y); 23964 cc = atan(2*rr); 23965 phi = rr==0?0:asin(cos(cc)*sinphi1); 23966 X = atan2(X,-Y*sinphi1)/pi; 23967 Y = phi/pi; 23968 (++X)*=0.5*w; 23969 (Y+=0.5)*=h; 23970 i(#-2) = X; Y;" 23971 warp[0] [1],0,0,1 k... 23972 endl done 23973 23974#@cli fisheye : _center_x,_center_y,0<=_radius<=100,_amplitude>=0 23975#@cli : Apply fish-eye deformation on selected images. 23976#@cli : Default values: 'x=y=50', 'radius=50' and 'amplitude=1.2'. 23977#@cli : $ image.jpg +fisheye , 23978fisheye : skip ${1=50},${2=50},${3=50},${4=1.2} 23979 e[^-1] "Apply Fish-eye effect on image$?, centered at ($1%,$2%) with radius $3% and amplitude $4." 23980 if $4==0 return fi 23981 repeat $! l[$>] 23982 100%,100%,1,1 =. 1,$1%,$2% distance. 1 c. 0,$3% *. -1 n. 0,1 ^. {1/$4} 23983 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 23984 n. 0,{max(w,h)} *[-2,-1] 23985 warp.. .,1,1,1 rm. 23986 endl done 23987 23988#@cli flower : _amplitude,_frequency,_offset_r[%],_angle,_center_x[%],_center_y[%],\ 23989# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror} 23990#@cli : ~~~\ntoto\n~~~ 23991#@cli : Apply flower deformation on selected images. 23992#@cli : Default values: 'amplitude=30', 'frequency=6', 'offset_r=0', 'angle=0', 'center_x=center_y=50%' \ 23993# and 'boundary_conditions=3'. 23994#@cli : $ image.jpg +flower , 23995flower : skip ${1=30},${2=6},${3=0},${4=0},${5=50%},${6=50%},${7=3} 23996 e[^-1] "Apply flower deformation on image$?, with amplitude $1, frequency $2, offset $3, angle $4 deg. and 23997 center point ($1,$2)." 23998 if ${"is_percent $3"} 23999 transform_polar "r + (R*$3) + R*$1/100*cos(a*$2+$4*pi/180)","a",$5,$6,$7 24000 else 24001 transform_polar "r + $3 + R*$1/100*cos(a*$2+$4*pi/180)","a",$5,$6,$7 24002 fi 24003 24004#@cli kaleidoscope : _center_x[%],_center_y[%],_radius,_angle,\ 24005# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 24006#@cli : Create kaleidoscope effect from selected images. 24007#@cli : Default values: 'center_x=center_y=50%', 'radius=100', 'angle=30' and 'boundary_conditions=3'. 24008#@cli : $ image.jpg kaleidoscope , 24009kaleidoscope : skip ${1=50%},${2=50%},${3=100},${4=30},${5=3} 24010 e[^-1] "Create kaleidoscope effect from image$?, with center point ($1,$2), radius $3, angle $4 deg." 24011 euclidean2polar $1,$2,1,$5 repeat $! l[$>] 24012 +columns 0,$3% rows. 0,$4% ri. ..,0,2 nm[1] {0,n} rm[0] 24013 endl done polar2euclidean $1,$2,1,$5 24014 24015#@cli map_sphere : _width>0,_height>0,_radius,_dilation>0,_fading>=0,_fading_power>=0 24016#@cli : Map selected images on a sphere. 24017#@cli : Default values: 'width=height=512', 'radius=100', 'dilation=0.5', 'fading=0' and 'fading_power=0.5'. 24018#@cli : $ image.jpg map_sphere , 24019map_sphere : check "${1=512}>0 && ${2=512}>0 && ${5=0}>=0 && ${6=0.5}>=0" skip ${3=100},${4=0.5} 24020 e[^-1] "Map image$? on spheres in $1x$2 images, with radius $3, dilation $4 and fading $5." 24021 r2={($3*min($1,$2)/200)^2} # Compute squared radius. 24022 repeat $! l[$>] 24023 i.. 100%,1,1,100%,0 nm[0] {1,n} a y # Add one border line to have a sphere exterior. 24024 ({-$1/2},{$1/2}) ({-$2/2};{$2/2}) r[-2,-1] $1,$2,1,1,3 atan2. .. rm.. # Compute theta angle. 24025 $1,$2 =. 1,50%,50% distance. 1,3 /. $r2 sqrt. c. 0,1 24026 asin. # Compute phi angle. 24027 +.. {pi} *.. {({-3,w}-1)/(2*pi)} # Normalize theta to X-coordinates 24028 *. {2/pi} ^. $4 *. {{-3,h}-1} *. -1 +. {{-3,h}-1} # Normalize phi to Y-coordinates 24029 if $5 +>=. 1 distance. 1 c. 0,$5% n. 0,1 ^. $6 c.. 1,100% -[-2,-1] fi 24030 r[-1,-2] 100%,100%,{-3,d} 24031 +f. z a[-3--1] c 24032 warp.. .,0,1,1 rm. # Apply image warping 24033 endl done 24034 24035#@cli nadirzenith2equirectangular 24036#@cli : Transform selected nadir/zenith rectilinear projections to equirectangular images. 24037nadirzenith2equirectangular : 24038 e[^-1] "Transform nadir/zenith rectilinear projection$? to equirectangular images." 24039 repeat $! l[$>] 24040 100%,100%,1,2 24041 sh. 100% 24042 f. " 24043 X = 2*x/(w-1) - 1; 24044 Y = y/(h-1) - 0.5; 24045 output = 1; 24046 if (Y>0.125, 24047 sinphi1 = 1; xc = -0.5, 24048 if (Y<-0.125, 24049 sinphi1 = -1; xc = 0.5, 24050 output = 0 24051 )); 24052 cosc = sinphi1*sin(Y*pi); 24053 xx = cos(Y*pi)*sin(X*pi)/cosc; 24054 yy = -sinphi1*cos(Y*pi)*cos(X*pi)/cosc; 24055 if (abs(xx)>1, output=0); 24056 (xx*=0.5)+=xc; 24057 yy*=0.5; 24058 if (!output, xx = yy = -1); 24059 (++xx)*=0.5*w; 24060 (yy+=0.5)*=h; 24061 i(#-2) = xx; yy;" 24062 to_a[0] warp[0] [1],0,0,0 k... 24063 endl done 24064 24065#@cli polar2euclidean : _center_x[%],_center_y[%],_stretch_factor>0,\ 24066# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 24067#@cli : Apply euclidean to polar transform on selected images. 24068#@cli : Default values: 'center_x=center_y=50%', 'stretch_factor=1' and 'boundary_conditions=1'. 24069#@cli : $ image.jpg +euclidean2polar , 24070polar2euclidean : skip ${1=50%},${2=50%} check "${3=1}>0 && isint(${4=1}) && $4>=0 && $4<=3" 24071 e[^-1] "Apply polar to euclidean transform on image$?, with center point ($1,$2), stretch factor $3 and "\ 24072 ${"arg 1+$4,dirichlet,neumann,periodic,mirror"}" boundary conditions." 24073 repeat $! l[$>] 24074 cx={if(${is_percent\ $1},$1*(w-1),$1)} 24075 cy={if(${is_percent\ $2},$2*(h-1),$2)} 24076 R={sqrt(max($cx^2,(w-1-$cx)^2)+max($cy^2,(h-1-$cy)^2))} 24077 f "X = sqrt((x-"$cx")^2+(y-"$cy")^2); 24078 tmp = atan2((y-"$cy"),(x-"$cx")); 24079 Y = if(tmp<0,tmp+2*pi,tmp); 24080 i((X/"$R")^(1/$3)*(w-1),Y*(h-1)/(2*pi),z,c,1,$4)" 24081 endl done 24082 24083#@cli raindrops : _amplitude,_density>=0,_wavelength>=0,_merging_steps>=0 24084#@cli : Apply raindrops deformation on selected images. 24085#@cli : Default values: 'amplitude=80','density=0.1', 'wavelength=1' and 'merging_steps=0'. 24086#@cli : $ image.jpg +raindrops , 24087raindrops : check "${2=0.1}>=0 && ${3=1}>=0 && isint(${4=0}) && $4>=0" skip ${1=80} 24088 e[^-1] "Apply raindrops deformation on image$?, with amplitude $1, density $2, wavelength $3 and $4 merging steps." 24089 repeat $! l[$>] 24090 100%,100% noise. $2,2 ==. 1 distance. 1 f. 'cos(i)/(1+i/(1e-8+$3))' 24091 if $4 24092 i.. (0,1,0;1,0,1;0,1,0) /.. 2 . 24093 repeat $4 +convolve. ...,1 -. ... rm... done rm[-3,-2] 24094 fi 24095 g. a[-2,-1] c *. {$1/(1e-5+max(abs(im),abs(iM)))} 24096 warp.. .,1 rm. 24097 endl done 24098 24099#@cli ripple : _amplitude,_bandwidth,_shape={ 0=bloc | 1=triangle | 2=sine | 3=sine+ | 4=random },_angle,_offset 24100#@cli : Apply ripple deformation on selected images. 24101#@cli : Default values: 'amplitude=10', 'bandwidth=10', 'shape=2', 'angle=0' and 'offset=0'. 24102#@cli : $ image.jpg +ripple , 24103ripple : skip ${1=10},${2=20},${3=2},${4=0},${5=0} 24104 e[^-1] "Apply ripple deformation on image$?, with amplitude $1, bandwidth $2, shape $3, angle $4 deg. and offset $5." 24105 theta={$4*pi/180} C={cos($theta)} S={-sin($theta)} 24106 repeat $! l[$>] 24107 100%,100%,1,1,"x" -. {w/2} 100%,100%,1,1,'y' 24108 -. {h/2-$5} *.. $S *. $C +[-2,-1] # Generate rotated Y. 24109 _ripple$3. $1,$2 # Generate warp field. 24110 +*. {-$S} *.. $C a[-2,-1] c # Rotate warp field. 24111 warp.. .,1 rm. 24112 endl done 24113 24114_ripple0 : f {$1/2}*"(1-2*(i%"{2*$2}"<$2))" 24115_ripple1 : f "I=(i%$2)/$2;$1*(2*if(I<0.5,I,1-I)-0.5)" 24116_ripple2 : f {-$1/2}*"cos(i*"{2*pi/$2}")" 24117_ripple3 : f {-$1/2}*"abs(cos(i*"{2*pi/$2}"))" 24118_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. 24119 24120#@cli rotoidoscope : _center_x[%],_center_y[%],_tiles>0,_smoothness[%]>=0,\ 24121# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 24122#@cli : Create rotational kaleidoscope effect from selected images. 24123#@cli : Default values: 'center_x=center_y=50%', 'tiles=10', 'smoothness=1' and 'boundary_conditions=3'. 24124#@cli : $ image.jpg +rotoidoscope , 24125rotoidoscope : skip ${1=50%},${2=50%},${5=1} check "${3=10}>0 && ${4=3}>=0" 24126 e[^-1] "Create rotational kaleidoscope effect from image$?, with center point ($1,$2), $3 tiles and smoothness $4." 24127 repeat $! l[$>] 24128 repeat $3 +rotate[0] {360/$3},1,$5,$1,$2 blend_edges $4 done 24129 endl done 24130 24131#@cli spherize : _radius[%]>=0,_strength,_smoothness[%]>=0,_center_x[%],_center_y[%],_ratio_x/y>0,_angle,\ 24132# _interpolation 24133#@cli : Apply spherize effect on selected images. 24134#@cli : Default values: 'radius=50%', 'strength=1', 'smoothness=0', 'center_x=center_y=50%', 'ratio_x/y=1', \ 24135# 'angle=0' and 'interpolation=1'. 24136#@cli : $ image.jpg grid 5%,5%,0,0,0.6,255 spherize , 24137spherize : check "${1=50%}>=0 && ${3=0}>=0 && ${6=1}>0 && isint(${8=1}) && $8>=0 && $8<=2" 24138 skip "${2=1},${4=50%},${5=50%},${7=0}" 24139 e[^-1] "Apply spherize effect on image$?, with radius $1, strength $2, smoothness $3, center ($4,$5), 24140 x/y-ratio $6, angle $7 and "${"arg 1+$8,nearest-neighbor,linear,cubic"}" interpolation." 24141 if !$1||!$2 return fi 24142 repeat $! l[$>] 24143 rmax={${"is_percent $1"}?0.5*sqrt((w-1)^2+(h-1)^2)*$1:$1} 24144 centerx={${"is_percent $4"}?(w-1)*$4:$4} 24145 centery={${"is_percent $5"}?(h-1)*$5:$5} 24146 strength={$2>0?$2:1-exp($2/5)} 24147 100%,100%,1,2," 24148 begin( 24149 center = [ "$centerx","$centery" ]; 24150 wh1 = [ w,h ] - 1; 24151 m2wh1 = 0.5*max(wh1); 24152 rmax = "$rmax"/m2wh1; 24153 const f = 1/"$strength"; 24154 const ratio = $6; 24155 rotf = rot($7°); 24156 rotb = rot(-$7°); 24157 ); 24158 xy = ([x,y] - center)/m2wh1; 24159 xy = rotf*xy; 24160 ratio>=1?(xy[1]*=ratio):(xy[0]/=ratio); 24161 r = norm2(xy); 24162 z = r<rmax?sign($2)*sqrt(rmax^2 - r^2):0; 24163 ratio>=1?(xy[1]/=ratio):(xy[0]*=ratio); 24164 xy = rotb*xy; 24165 xy = center + f*xy/(f + z)*m2wh1" 24166 b. $3 24167 warp.. .,0,$8,1 rm. 24168 endl done 24169 24170#@cli symmetrize : _x[%],_y[%],_angle,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror },\ 24171# _is_antisymmetry={ 0 | 1 },_swap_sides={ 0 | 1 } 24172#@cli : Symmetrize selected images regarding specified axis. 24173#@cli : Default values: 'x=y=50%', 'angle=90', 'boundary_conditions=3', 'is_antisymmetry=0' and 'swap_sides=0'. 24174#@cli : $ image.jpg +symmetrize 50%,50%,45 +symmetrize[-1] 50%,50%,-45 24175symmetrize : skip ${1=50%},${2=50%},${3=90},${4=3},${5=0},${6=0} 24176 e[^-1] "Symmetrize image$?, regarding axis ($1,$2,$3 deg.)." 24177 theta={$3*pi/180} u={cos($theta)} v={sin($theta)} 24178 if $6 symmetry_cond=A<0 else symmetry_cond=A>0 fi 24179 repeat $! l[$>] 24180 x0={if(${is_percent\ $1},w*$1,$1)} 24181 y0={if(${is_percent\ $2},h*$2,$2)} 24182 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)' 24183 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)' 24184 fi 24185 endl done 24186 24187#@cli transform_polar : "expr_radius",_"expr_angle",_center_x[%],_center_y[%],\ 24188# _boundary_conditions={ 0=dirichlet | 1=neumann } 24189#@cli : Apply user-defined transform on polar representation of selected images. 24190#@cli : Default values: 'expr_radius=R-r', 'expr_rangle=a', 'center_x=center_y=50%' and 'boundary_conditions=1'. 24191#@cli : $ image.jpg +transform_polar[0] R*(r/R)^2,a +transform_polar[0] r,2*a 24192transform_polar : skip "${1=R-r}","${2=a}",${3=50%},${4=50%},${5=1} 24193 e[^-1] "Apply custom polar transform with 'new_r = $1', 'new_a = $2', center point ($3%,$4%)." 24194 repeat $! l[$>] 24195 cx={if(${is_percent\ $3},$3*(w-1),$3)} 24196 cy={if(${is_percent\ $4},$4*(h-1),$4)} 24197 R={sqrt(max($cx^2,(w-1-$cx)^2)+max($cy^2,(h-1-$cy)^2))} 24198 f "R ="$R"; 24199 r = sqrt((x-"$cx")^2 + (y-"$cy")^2); 24200 a = atan2(y-"$cy",x-"$cx"); 24201 nr = ($1); 24202 na = ($2); 24203 i("$cx" + nr*cos(na), "$cy" + nr*sin(na), z, c,1,$5)" 24204 endl done 24205 24206#@cli twirl : _amplitude,_center_x[%],_center_y[%],\ 24207# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 24208#@cli : Apply twirl deformation on selected images. 24209#@cli : Default values: 'amplitude=1', 'center_x=center_y=50%' and 'boundary_conditions=3'. 24210#@cli : $ image.jpg twirl 0.6 24211twirl : skip ${1=1},${2=50%},${3=50%},${4=3} 24212 e[^-1] "Apply twirl deformation on image$?, with amplitude $1 and center point at ($2%,$3%)." 24213 euclidean2polar $2,$3,1,$4 repeat $! 24214 [$>],[$>],1,1,$1*x channels. -1,0 warp[$>] .,1,1,2 rm. 24215 done polar2euclidean $2,$3,1,1 24216 24217#@cli warp_perspective : _x-angle,_y-angle,_zoom>0,_x-center,_y-center,\ 24218# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 24219#@cli : Warp selected images with perspective deformation. 24220#@cli : Default values: 'x-angle=1.5', 'y-angle=0', 'zoom=1', 'x-center=y-center=50' and 'boundary_conditions=2'. 24221#@cli : $ image.jpg warp_perspective , 24222warp_perspective : skip ${1=1.5},${2=0},${3=1},${4=50},${5=50},${6=2} 24223 e[^-1] "Apply perspective warp on image$?, with angles ($1 deg.,$2 deg.), zoom $3 and offsets ($4,$5)." 24224 repeat $! l[$>] 24225 (0,100) -. $4 /. 100 (0;100) -. $5 /. 100 r[-2,-1] ...,...,...,1,3 24226 +*.. $2 +*.. $1 +[-2,-1] +. $3 /... . /[-2,-1] 24227 *.. 100 +.. $4 /.. 100 *.. {-3,w} 24228 *. 100 +. $5 /. 100 *. {-3,h} 24229 a[-2,-1] c warp.. .,0,1,$6 rm. 24230 endl done 24231 24232#@cli water : _amplitude,_smoothness>=0,_angle 24233#@cli : Apply water deformation on selected images. 24234#@cli : Default values: 'amplitude=30', 'smoothness=1.5' and 'angle=45'. 24235#@cli : $ image.jpg water , 24236water : check ${2=1.5}>=0 skip ${1=30},${3=1},${4=45} 24237 e[^-1] "Apply water deformation on image$?, with amplitude $1, smoothness $2 and angle $3." 24238 repeat $! l[$>] 24239 25%,25%,25%,1 noise. $1 g. xy *.. {-sin($3*pi/180)} *. {cos($3*pi/180)} +[-2,-1] b. $2 *. 2 24240 r. ..,..,1,2,3 warp.. .,1 rm. 24241 endl done 24242 24243#@cli wave : _amplitude>=0,_frequency>=0,_center_x,_center_y 24244#@cli : Apply wave deformation on selected images. 24245#@cli : Default values: 'amplitude=4', 'frequency=0.4' and 'center_x=center_y=50'. 24246#@cli : $ image.jpg wave , 24247wave : skip ${1=4},${2=0.4},${3=50},${4=50} 24248 e[^-1] "Apply wave deformation on image$?, with amplitude $1, frequency $2 and center point at ($3%,$4%)." 24249 repeat $! l[$>] 24250 100%,100% =. 1,$3%,$4% distance. 1 24251 *. $2 +sin. cos.. a[-2,-1] c *. $1 24252 warp.. .,1 rm. 24253 endl done 24254 24255#@cli wind : _amplitude>=0,_angle,0<=_attenuation<=1,_threshold 24256#@cli : Apply wind effect on selected images. 24257#@cli : Default values: 'amplitude=20', 'angle=0', 'attenuation=0.7' and 'threshold=20'. 24258#@cli : $ image.jpg +wind , 24259wind : check "isint(${1=20}) && $1>=0 && ${3=0.7}>=0 && $3<=1" skip "${2=0},${4=20}" 24260 e[^-1] "Apply wind effect on image$?, with amplitude $1, angle "{round($2/45)*45}" deg., attenuation $3 24261 and threshold $4." 24262 if !$1 return fi 24263 dxdy=${-_wind{round($2/45)%8}} 24264 fact={(1-$3)^(1/$1)} 24265 repeat $! l[$>] 24266 +gradient_norm >=. $4% 24267 r. 100%,100%,1,.. *. .. 24268 repeat $1 24269 shift. $dxdy,0,0,0 max.. . *. $fact 24270 remove_pixels. {100/$1}% 24271 done rm. 24272 endl done 24273 24274_wind0 : u 1,0 24275_wind1 : u 1,1 24276_wind2 : u 0,1 24277_wind3 : u -1,1 24278_wind4 : u -1,0 24279_wind5 : u -1,-1 24280_wind6 : u 0,-1 24281_wind7 : u 1,-1 24282 24283#@cli zoom : _factor,_cx,_cy,_cz,_boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 24284#@cli : Apply zoom factor to selected images. 24285#@cli : Default values: 'factor=1', 'cx=cy=cz=0.5' and 'boundary_conditions=0'. 24286#@cli : $ image.jpg +zoom[0] 0.6 +zoom[0] 1.5 24287zoom : skip ${1=2},${2=0.5},${3=0.5},${4=0.5},${5=0} 24288 e[^-1] "Apply zoom effect on image$?, with factor $1 and center ($2,$3)." 24289 repeat $! l[$>] 24290 if d==1 # 2D image. 24291 ({(w-1)*$2*(1-1/$1)},{(w-1)*($2+(1-$2)/$1)}) 24292 ({({-2,h}-1)*$3*(1-1/$1)};{({-2,h}-1)*($3+(1-$3)/$1)}) 24293 r[-2--1] ...,...,1,1,3 a[-2--1] c warp.. .,0,1,$5 24294 else # 3D image. 24295 ({(w-1)*$2*(1-1/$1)},{(w-1)*($2+(1-$2)/$1)}) 24296 ({({-2,h}-1)*$3*(1-1/$1)};{({-2,h}-1)*($3+(1-$3)/$1)}) 24297 ({({-3,d}-1)*$4*(1-1/$1)}/{({-3,d}-1)*($4+(1-$4)/$1)}) 24298 r[-3--1] [-4],[-4],[-4],1,3 a[-3--1] c warp.. .,0,1,$5 24299 fi 24300 rm. 24301 endl done 24302 24303#----------------------------- 24304# 24305#@cli :: Degradations 24306# 24307#----------------------------- 24308 24309#@cli cracks : 0<=_density<=100,_is_relief={ 0 | 1 },_opacity,_color1,... 24310#@cli : Draw random cracks on selected images with specified color. 24311#@cli : Default values: 'density=25', 'is_relief=0', 'opacity=1' and 'color1=0'. 24312#@cli : $ image.jpg +cracks , 24313cracks : check "${1=25}>=0" skip ${2=0},${3=1},${4=0} 24314 e[^-1] "Add random cracks to image$?, with density $1, opacity $3 and color (${4--1})." 24315 repeat $! l[$>] cut={[im,iM]} 24316 100%,100%,1,2,'u<0.25*($1%)^4?[u,1]:[0,0]' 24317 s. c distance. 1 *. -1 watershed.. . rm. 24318 +dilate. 3 -[-2,-1] !=. 0 # thinning. 1 24319 if $2 24320 f. "i?i:j(1)?2:j(-1)?0.5:i" n. 0,1 24321 +fc.. ${4--1} *. .. !=.. 0 j... .,0,0,0,0,$3,.. 24322 else 24323 +fc.. ${4--1} j... .,0,0,0,0,$3,.. 24324 fi 24325 k[0] 24326 endl done 24327 24328#@cli light_patch : _density>0,_darkness>=0,_lightness>=0 24329#@cli : Add light patches to selected images. 24330#@cli : Default values: 'density=10', 'darkness=0.9' and 'lightness=1.7'. 24331#@cli : $ image.jpg +light_patch 20,0.9,4 24332light_patch : skip ${1=10},${2=0.9},${3=1.7} 24333 e[^-1] "Apply light patches to image$?, with density $1, darkness $2 and lightness $3." 24334 repeat $! l[$>] 24335 n 0,255 $1,$1 noise. 40 ri. ..,5 c. 0,255 24336 n. $2,$3 * c 0,255 24337 endl done 24338 24339#@cli noise_hurl : _amplitude>=0 24340#@cli : Add hurl noise to selected images. 24341#@cli : Default value: 'amplitude=10'. 24342#@cli : $ image.jpg +noise_hurl , 24343noise_hurl : skip ${1=10} 24344 e[^-1] "Add hurl noise to image$?, with amplitude $1%." 24345 repeat $! l[$>] 24346 +f 0 noise. 10 n. {-2,[im,iM]} 100%,100% 24347 noise. $1,2 >. 0 ri. .. 24348 *.. . *. -1 +. 1 *[-3,-1] + 24349 endl done 24350 24351#@cli pixelize : _scale_x>0,_scale_y>0,_scale_z>0 24352#@cli : Pixelize selected images with specified scales. 24353#@cli : Default values: 'scale_x=20' and 'scale_y=scale_z=scale_x'. 24354#@cli : $ image.jpg +pixelize , 24355pixelize : skip ${1=20},${2=$1},${3=$1} 24356 e[^-1] "Pixelize image$? with scales ($1%,$2%,$3%)." 24357 repeat $! l[$>] whd={w},{h},{d} r $1%,$2%,$3%,100%,2 r $whd endl done 24358 24359#@cli scanlines : _amplitude,_bandwidth,_shape={ 0=bloc | 1=triangle | 2=sine | 3=sine+ | 4=random },_angle,_offset 24360#@cli : Apply ripple deformation on selected images. 24361#@cli : Default values: 'amplitude=60', 'bandwidth=2', 'shape=0', 'angle=0' and 'offset=0'. 24362#@cli : $ image.jpg +scanlines , 24363scanlines : skip ${1=60},${2=2},${3=0},${4=0},${5=0} 24364 e[^-1] "Apply scanlines effect on image$?, with amplitude $1, bandwidth $2, shape $3, angle $4 deg. and offset $5." 24365 theta={$4*pi/180} C={cos($theta)} S={-sin($theta)} 24366 repeat $! l[$>] 24367 100%,100%,1,1,"x" -. {w/2} 100%,100%,1,1,'y' 24368 -. {h/2-$5} *.. $S *. $C +[-2,-1] # Generate rotated Y. 24369 _ripple$3. $1,$2 # Generate warp field. 24370 n. {-$1},$1 24371 + cut 0,255 24372 endl done 24373 24374#@cli shade_stripes : _frequency>=0,_direction={ 0=horizontal | 1=vertical },_darkness>=0,_lightness>=0 24375#@cli : Add shade stripes to selected images. 24376#@cli : Default values: 'frequency=5', 'direction=1', 'darkness=0.8' and 'lightness=2'. 24377#@cli : $ image.jpg +shade_stripes 30 24378shade_stripes : skip ${1=5},${2=1},${3=0.8},${4=2} 24379 e[^-1] "Add "${arg\ 1+!$2,vertical,horizontal}" shaded stripes to image$?, with frequency $1, darkness $3 and 24380 lightness $4." 24381 n 0,255 repeat $! l[$>] 24382 {max(1,w*($2!=0))},{max(1,h*($2==0))} noise. $1,2 ==. 1 distance. 1 ri. .. n. $3,$4 * c 0,255 24383 endl done 24384 24385#@cli shadow_patch : _opacity>=0 24386#@cli : Add shadow patches to selected images. 24387#@cli : Default value: 'opacity=0.7'. 24388#@cli : $ image.jpg +shadow_patch 0.4 24389shadow_patch : skip ${1=0.7} 24390 e[^-1] "Apply shadow patches to image$?, with opacity $1." 24391 repeat $! l[$>] 24392 100%,100%,1,1 shift. -2,-2 shift. 1,1 24393 plasma. 3,0.3,8 abs. b. 1 c. 3%,15% ri. .. 24394 n. $1,1 * 24395 endl done 24396 24397#@cli spread : _dx>=0,_dy>=0,_dz>=0 24398#@cli : Spread pixel values of selected images randomly along x,y and z. 24399#@cli : Default values: 'dx=3', 'dy=dx' and 'dz=0'. 24400#@cli : $ image.jpg +spread 3 24401spread : skip ${1=3},${2=$1},${3=0} 24402 e[^-1] "Spread pixel of image$? randomly, with amplitudes ($1,$2,$3)." 24403 repeat $! l[$>] 24404 100%,100%,100%,3 24405 sh. 0 rand. {-$1},$1 rm. 24406 sh. 1 rand. {-$2},$2 rm. 24407 sh. 2 rand. {-$3},$3 rm. 24408 warp.. .,1 rm. 24409 endl done 24410 24411#@cli stripes_y : _frequency>=0 24412#@cli : Add vertical stripes to selected images. 24413#@cli : Default value: 'frequency=10'. 24414#@cli : $ image.jpg +stripes_y , 24415stripes_y : skip ${1=10} 24416 e[^-1] "Add vertical stripes to image$?, with frequency $1." 24417 repeat $! l[$>] 24418 100% noise. $1,2 ==. 1 *. 255 ri. .. 24419 *. 0.15 + c 0,255 24420 endl done 24421 24422#@cli texturize_canvas : _amplitude>=0,_fibrousness>=0,_emboss_level>=0 24423#@cli : Add paint canvas texture to selected images. 24424#@cli : Default values: 'amplitude=20', 'fibrousness=3' and 'emboss_level=0.6'. 24425#@cli : $ image.jpg +texturize_canvas , 24426texturize_canvas : check "${1=20}>=0 && ${2=3}>=0 && ${3=0.6}>=0 && ${4=80}" 24427 e[^-1] "Add canvas texture to image$?, with amplitude $1, fibrousness $2 and emboss level $3." 24428 repeat $! l[$>] 24429 {w},{h} rand. 0,255 +blur_x. $2 blur_y.. $2 +[-2,-1] g. a[-2,-1] c 24430 +compose_channels. + orientation.. compose_channels.. + n.. $3,1 n. 0,255 24431 sharpen. 80 *[-2,-1] n. -$1,$1 + c 0,255 24432 endl done 24433 24434#@cli texturize_paper 24435#@cli : Add paper texture to selected images. 24436#@cli : $ image.jpg +texturize_paper 24437texturize_paper : 24438 e[^-1] "Add paper texture to image$?." 24439 repeat $! l[$>] 24440 . 30%,30% noise. 1,2 ==. 1 r. ..,..,..,1,0 ifft. 24441 rm. shift. {round(w/2)},{round(h/2)},{round(d/2)},0,2 sharpen. 1 n. 1,1.2 ri. .. 24442 *[-2,-1] c. ..,.. rm.. 24443 endl done 24444 24445#@cli vignette : _strength>=0,0<=_radius_min<=100,0<=_radius_max<=100 24446#@cli : Add vignette effect to selected images. 24447#@cli : Default values: 'strength=100', 'radius_min=70' and 'radius_max=90'. 24448#@cli : $ image.jpg vignette , 24449vignette : check "${1=100}>=0 && ${2=70}>=0 && $2<=100 && ${3=90}>=0 && $3<=100" 24450 e[^-1] "Add vignette effect to image$?, with strength $1 and size $2." 24451 repeat $! l[$>] 24452 mM={[im,iM]} d={max(w,h)} 24453 $d,$d =. 1,50%,50% distance. 1 ri. ..,2 24454 c. $2%,$3% n. 0,$1 - c $mM 24455 endl done 24456 24457#@cli watermark_visible : _text,0<_opacity<1,_size>0,_angle,_mode={ 0=remove | 1=add },_smoothness>=0 24458#@cli : Add or remove a visible watermark on selected images (value range must be [0,255]). 24459#@cli : Default values: 'text=(c) G'MIC', 'opacity=0.3', 'size=53', 'angle=25', 'mode=1' and 'smoothness=0'. 24460#@cli : $ image.jpg watermark_visible ,0.7 24461watermark_visible : check "${2=0.3}>0 && $2<1 && ${3=53}>0 && ${6=0.5}>=0" 24462 skip "${1=\251\ G\47MIC}",${4=25},${5=1} 24463 e[^-1] ${arg\ 1+!$5,Add,Remove}" visible watermark '$1' on image$?, with opacity $2, size $3, angle $4 deg." 24464 repeat $! l[$>] 24465 0 t. "$1",0,0,$3,1,255 rotate. $4,0,0 b. $6 n. 0,255 24466 ri. ..,0,2 +. .. c. 0,255 # Generate opaque watermark image 24467 if $5 *. $2 *.. {1-$2} + # Add watermark 24468 else *. $2 - / {1-$2} # Remove watermark 24469 fi 24470 c 0,255 24471 endl done 24472 24473#-------------------------------------- 24474# 24475#@cli :: Blending and Fading 24476# 24477#-------------------------------------- 24478 24479#@cli blend : [layer],blending_mode,_opacity[%],_selection_is={ 0=base-layers | 1=top-layers } : \ 24480# blending_mode,_opacity[%] 24481#@cli : Blend selected G,GA,RGB or RGBA images by specified layer or blend all selected images together, 24482#@cli : using specified blending mode. 24483#@cli : 'blending_mode' can be { add | alpha | and | average | blue | burn | darken | difference | 24484#@cli : divide | dodge | edges | exclusion | freeze | grainextract | grainmerge | green | hardlight | 24485#@cli : hardmix | hue | interpolation | lchlightness | lighten | lightness | linearburn | linearlight | luminance | 24486#@cli : multiply | negation | or | overlay | pinlight | red | reflect | saturation | seamless | seamless_mixed | 24487#@cli : screen | shapeareamax | shapeareamax0 | shapeareamin | shapeareamin0 | shapeaverage | shapeaverage0 | 24488#@cli : shapemedian | shapemedian0 | shapemin | shapemin0 | shapemax | shapemax0 | softburn | softdodge | 24489#@cli : softlight | stamp | subtract | value | vividlight | xor }. 24490#@cli : 'opacity' should be in '[0,1]', or '[0,100]' if expressed with a '%'. 24491#@cli : Default values: 'blending_mode=alpha', 'opacity=1' and 'selection_is=0'. 24492#@cli : $ image.jpg +drop_shadow , resize2dy[-1] 200 rotate[-1] 20 +blend alpha display_rgba[-2] 24493#@cli : $ image.jpg testimage2d {w},{h} blend overlay 24494#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 24495# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 24496# ex add,alpha,and,average,blue,burn,darken 24497#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 24498# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 24499# ex difference,divide,dodge,exclusion,freeze,grainextract,grainmerge 24500#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 24501# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 24502# ex green,hardlight,hardmix,hue,interpolation,lighten,lightness 24503#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 24504# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 24505# ex linearburn,linearlight,luminance,multiply,negation,or,overlay 24506#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 24507# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 24508# ex pinlight,red,reflect,saturation,screen,shapeaverage,softburn 24509#@cli : $ command "ex : $""=arg repeat $""# +blend[0,1] ${arg{$>+1}} \ 24510# text_outline[-1] Mode:\" \"${arg{$>+1}},2,2,23,2,1,255 done" image.jpg testimage2d {w},{h} \ 24511# ex softdodge,softlight,stamp,subtract,value,vividlight,xor 24512blend : skip ${1=alpha},${2=1},${3=1},${4=0} 24513 if ${"is_image_arg $1"} 24514 n={narg($*)} mode=${arg\ 1+($n>=2),alpha,$2} 24515 e[^-1] "Blend image$? with "${arg\ 1+$4,base,top}" layer $1, using '"$mode"' mode and opacity $3." 24516 repeat $! pass$1 l[$>,-1] if $4 rv fi blend $mode,$3 endl done return 24517 fi 24518 e[^-1] "Blend all image$? together, using '$1' mode and opacity $2." 24519 repeat $!-1 l[0,1] 24520 r[1] [0],[0],[0],100%,0,0,0.5,0.5 24521 s={"s0 = s#0<3?1:3; s1 = s<3?1:3; max(s0,s1)"} # Target color format (G or RGB). 24522 to_colormode[0] {$s+1-(s#0%2)} # Target format (G,GA,RGB or RGBA). 24523 to_colormode[1] {$s+1-(s%2)} # Mask format (G,GA,RGB or RGBA). 24524 if {0,"s==2 || s==4"} # Target has alpha. 24525 if "s==2 || s==4" # Mask has alpha. 24526 sh[0,1] 0,{s-2} _blend_$1[2,3] rm[2,3] 24527 if ['"$1"']=='alpha' # Special blending code for alpha-mode. 24528 sh[0,1] 0,{{0,s}-2} sh[0,1] 100% *[2,4] *[3,4] rm[2,3] 24529 +channels[1] 100% sh[1] 100% f[3] 255 rm[3] 24530 j[0] [1],0,0,0,0,{max(0,min(1,$2))},[2],255 rm[1,2] 24531 sh[0] 0,{s-2} sh[0] 100% +[2] 1e-10 /[1,2] rm[1] c 0,255 24532 else 24533 sh[1] 0,{s-2} sh[1] 100% j[0] [2],0,0,0,0,{max(0,min(1,$2))},[3],255 rm[^0] 24534 fi 24535 else # Mask has no alpha. 24536 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] 24537 fi 24538 else # Target has no alpha. 24539 if "s==2 || s==4" # Mask has alpha. 24540 sh[1] 0,{s-2} _blend_$1[0,2] rm[2] 24541 sh[1] 100% j[0] [1],0,0,0,0,{max(0,min(1,$2))},[2],255 rm[^0] 24542 else # Mask has no alpha. 24543 _blend_$1 j[0] [1],0,0,0,0,{max(0,min(1,$2))} rm[1] 24544 fi 24545 fi 24546 endl done 24547 24548_blend_alpha : 24549_blend_normal : 24550_blend_and : 24551 &[1] [0] 24552_blend_add : 24553 +[1] [0] c[1] 0,255 24554_blend_average : 24555 +[1] [0] /[1] 2 24556_blend_blue : 24557 sh[0] 0,1 j[1] [2] rm[2] 24558_blend_burn : 24559 +-[0] 255 +[1] 0.1 /[2] [1] rm[1] +[1] 1 *[1] 255 c[1] 0,255 24560_blend_darken : 24561 min[1] [0] 24562_blend_difference : 24563 -[1] [0] abs[1] 24564_blend_divide : 24565 +[1] 0.1 ^[1] -1 *[1] [0] *[1] 255 c[1] 0,255 24566_blend_dodge : 24567 -[1] 255.1 ^[1] -1 *[1] [0] *[1] -255 c[1] 0,255 24568_blend_edges : 24569 +blend_edges 0.5 rm[1] 24570_blend_exclusion : 24571 +*[0,1] /[2] -127.5 +[1,2] +[1] [0] 24572_blend_freeze : 24573 *[1] -255 -[1] 0.1 +-[0] 255 sqr[2] /[2] [1] rm[1] +[1] 1 *[1] 255 c[1] 0,255 24574_blend_grainextract : 24575 -[1] [0] *[1] -1 +[1] 128 c[1] 0,255 24576_blend_grainmerge : 24577 +[1] [0] -[1] 128 c[1] 0,255 24578_blend_green : 24579 sh[0] 0 sh[0] 2 j[1] [2] j[1] [3],0,0,0,2 rm[2,3] 24580_blend_hardlight : 24581 +*[0,1] /[2] 127.5 ++[0,1] *[3] 2 -[3] 255 -[3] [2] >[1] 128 24582 j[2] [3],0,0,0,0,1,[1] rm[1,3] c[1] 0,255 24583_blend_hardmix : 24584 +[1] [0] >=[1] 255 *[1] 255 24585_blend_hue : 24586 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] 24587_blend_interpolation : 24588 +*[0] {pi/255} *[1] {pi/255} cos[1,2] +[1,2] -[1] 2 *[1] -63.75 c[1] 0,255 24589_blend_lighten : 24590 max[1] [0] 24591_blend_lightness : 24592 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] 24593_blend_lchlightness : 24594 _blend_lightness 24595_blend_luminance : 24596 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] 24597_blend_linearburn : 24598 +[1] [0] -[1] 255 c. 0,255 24599_blend_linearlight : 24600 *[1] 2 +[1] [0] -[1] 255 c[1] 0,255 24601_blend_multiply : 24602 *[1] [0] /[1] 255 24603_blend_negation : 24604 +[1] [0] -[1] 255 abs[1] *[1] -1 +[1] 255 24605_blend_or : 24606 -|[1] [0] 24607_blend_overlay : 24608 +*[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 24609_blend_pinlight : 24610 *[1] 2 +blend darken -[1] 256 +blend[0,1] lighten >=[1] 0 24611 j[2] [3],0,0,0,0,1,[1] rm[1,3] 24612_blend_reflect : 24613 -[1] 255.1 *[1] -1 +sqr[0] /[2] [1] rm[1] c[1] 0,255 24614_blend_red : 24615 sh[0] 1,100% j[1] [2],0,0,0,1 rm[2] 24616_blend_seamless : 24617 +blend_seamless 0 rm[1] 24618_blend_seamless_mixed : 24619 +blend_seamless 1 rm[1] 24620_blend_saturation : 24621 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 24622 hsv2rgb[2,3] rm[2,3] 24623_blend_screen : 24624 +-[0] 255 -[1] 255 *[1,2] /[1] 255 *[1] -1 +[1] 255 24625_blend_shapeareamax : 24626 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[1] round[1] 0.01 label[1] 0 24627 +f[0] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[2] round[2] 0.01 area[2] 0,0 24628 {1,iM+1},1,1,{0,s+1} 24629 f[1] ">area = i(#2); best = I[#3,i]; if (area>best[size(best) - 1], I[#3,i] = [ I(#0),area ]);i" 24630 rm[2] channels[2] 0,{s-2} map[1] [2] rm[2] 24631_blend_shapeareamax0 : 24632 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 24633 +f[0] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[2] round[2] 0.01 area[2] 0,0 24634 {1,iM+1},1,1,{0,s+1} 24635 f[1] ">area = i(#2); best = I[#3,i]; if (area>best[size(best) - 1], I[#3,i] = [ I(#0),area ]);i" 24636 rm[2] channels[2] 0,{s-2} point[2] 0,0,0,1,0 map[1] [2] rm[2] 24637_blend_shapeareamin : 24638 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[1] round[1] 0.01 label[1] 0 24639 +f[0] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[2] round[2] 0.01 area[2] 0,0 24640 {1,iM+1},1,1,{0,s+1},inf 24641 f[1] ">area = i(#2); best = I[#3,i]; if (area<best[size(best) - 1], I[#3,i] = [ I(#0),area ]);i" 24642 rm[2] channels[2] 0,{s-2} map[1] [2] rm[2] 24643_blend_shapeareamin0 : 24644 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 24645 +f[0] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[2] round[2] 0.01 area[2] 0,0 24646 {1,iM+1},1,1,{0,s+1},inf 24647 f[1] ">area = i(#2); best = I[#3,i]; if (area<best[size(best) - 1], I[#3,i] = [ I(#0),area ]);i" 24648 rm[2] channels[2] 0,{s-2} point[2] 0,0,0,1,0 map[1] [2] rm[2] 24649_blend_shapeaverage : 24650 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} 24651 f[0] ">i(#2,i(#1,x,y,z,0),0,0,c)+=i;i" 24652 +histogram[1] {w},0,{w-1} /[-2,-1] map[1] . rm. 24653_blend_shapeaverage0 : 24654 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} 24655 f[0] ">i(#2,i(#1,x,y,z,0),0,0,c)+=i;i" 24656 +histogram[1] {w},0,{w-1} /[-2,-1] point. 0,0,0,1,0 map[1] . rm. 24657_blend_shapemedian : 24658 f[1] "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm[1] round[1] 0.01 label[1] 0 24659 N={iM+1} $N,1,1,{s#0} $N,8,1,{s#0} s. x 24660 f[1] "> 24661 begin(siz = vector"$N"()); 24662 k = i; 24663 k3 = k + 3; 24664 hk3 = h(#k3); 24665 copy(i[#k3,siz[k]++],I(#0),s#0,hk3,whd#0); 24666 if (siz[k]>=hk3,resize(#k3,1,round(1.5*hk3+1),1,s#0,0,0)); 24667 end(repeat (size(siz),k, resize(#k+3,1,siz[k],1,s#0,0,0))); 24668 i" 24669 repeat s#0 sh[3--1] $> $N,1,1,1,"ic(#"$N"+3+x)" j[2] .,0,0,0,$> rm[-{$N+1}--1] done 24670 map[1] [2] k[0,1] 24671_blend_shapemedian0 : 24672 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 24673 N={iM} {$N+1},1,1,{s#0} $N,8,1,{s#0} s. x 24674 f[1] "> 24675 begin(siz = vector"$N"()); 24676 k = i; 24677 if (k, 24678 k1 = k - 1; 24679 k2 = k + 2; 24680 hk2 = h(#k2); 24681 copy(i[#k2,siz[k1]++],I(#0),s#0,hk2,whd#0); 24682 if (siz[k1]>=hk2,resize(#k2,1,round(1.5*hk2+1),1,s#0,0,0)); 24683 ); 24684 end(repeat (size(siz),k, resize(#k+3,1,siz[k],1,s#0,0,0))); 24685 i" 24686 repeat s#0 sh[3--1] $> $N,1,1,1,"ic(#"$N"+3+x)" j[2] .,1,0,0,$> rm[-{$N+1}--1] done 24687 map[1] [2] k[0,1] 24688_blend_shapemin : 24689 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 24690 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" 24691 map[1] [2] rm. 24692_blend_shapemin0 : 24693 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 24694 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" 24695 point. 0,0,0,1,0 map[1] [2] rm. 24696_blend_shapemax : 24697 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 24698 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" 24699 map[1] [2] rm. 24700_blend_shapemax0 : 24701 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 24702 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" 24703 point. 0,0,0,1,0 map[1] [2] rm. 24704_blend_softburn : 24705 +-[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 24706 j[2] [3],0,0,0,0,1,[1] rm[1,3] c[1] 0,255 24707_blend_softdodge : 24708 +-[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 24709 j[2] [3],0,0,0,0,1,[1] rm[1,3] c[1] 0,255 24710_blend_softlight : 24711 +/[0] 255 /[1] 255 +sqr. *[2] [1] *[1] [3] *[1] -2 *[2] 2 +[1-3] *[1] 255 c[1] 0,255 24712_blend_stamp : 24713 *[1] 2 +[1] [0] -[1] 255 c[1] 0,255 24714_blend_subtract : 24715 -[1] [0] *[1] -1 c[1] 0,255 24716_blend_value : 24717 to_color sh 0,2 rgb2hsv[2,3] sh[2] 0,1 j[1] [4] rm[4] hsv2rgb[2,3] rm[2,3] 24718_blend_vividlight : 24719 *[1] 2 +blend burn -[1] 256 +blend[0,1] dodge >=[1] 0 24720 j[2] [3],0,0,0,0,1,[1] rm[1,3] 24721_blend_xor : 24722 xor[1] [0] 24723 24724#@cli blend_edges : smoothness[%]>=0 24725#@cli : Blend selected images togethers using 'edges' mode. 24726#@cli : $ image.jpg testimage2d {w},{h} +blend_edges 0.8 24727blend_edges : check {$1>=0} 24728 e[^-1] "Blend image$? using 'edges' mode, with smoothness $1." 24729 if $!>1 to_rgb ri[^0] [0],0,0,0.5,0.5 repeat $! l[$>] 24730 +gradient_norm +. 1 b. $1 n. 1,10 sqr. s.. c *[-4--2] . a[-4--1] c 24731 endl done ri[^0] [0],0,0,0.5,0.5 + s. c /[-4--2] . rm. a[-3--1] c fi 24732 24733#@cli blend_fade : [fading_shape] 24734#@cli : Blend selected images together using specified fading shape. 24735#@cli : $ image.jpg testimage2d {w},{h} 100%,100%,1,1,'cos(y/10)' normalize[-1] 0,1 +blend_fade[0,1] [2] 24736blend_fade : 24737 e[^-1] "Blend image$? together using fading pattern $1." 24738 r ${-max_whds},0 24739 pass$1 0 r. [0],[0],[0],100%,1 max. 0 min. {$!-2} 24740 repeat $!-1 +-. $> abs. -. 1 *. -1 max. 0 *[$>,-1] done rm. 24741 + 24742 24743_fade : 24744 ri.. ...,5 ri. ..,3 c. $1%,$2% n. 0,1 j... ..,0,0,0,0,1,. rm[-2,-1] 24745 24746#@cli blend_median 24747#@cli : Blend selected images together using 'median' mode. 24748#@cli : $ image.jpg testimage2d {w},{h} +mirror[0] y +blend_median 24749blend_median : 24750 e[^-1] "Blend image$? using 'median' mode." 24751 if $!<2 return fi 24752 to_colormode 0 r ${-max_whd},100%,0,0,0.5,0.5,0.5 24753 if $!==2 + / 2 24754 else 24755 whds={w},{h},{d},{s} r 100%,100%,{d*s},1,-1 a c 24756 100%,100%,100%,1,"med(I(#0))" k. r $whds,-1 24757 fi 24758 24759#@cli blend_seamless : _is_mixed_mode={ 0 | 1 },_inner_fading[%]>=0,_outer_fading[%]>=0 24760#@cli : Blend selected images using a seamless blending mode (Poisson-based). 24761#@cli : Default values: 'is_mixed=0', 'inner_fading=0' and 'outer_fading=100%'. 24762blend_seamless : check "${2=0}>=0 && ${3=100%}>=0" skip ${1=0} 24763 s0="non-mixed" s1="mixed" 24764 e[^-1] "Blend image$? using seamless mode (Poisson-based), in "${s{$1!=0}}" mode with inner fading $2 and 24765 outer fading $3." 24766 to_a[^0] r {0,w+32},{0,h+32},1,100%,0,0,0.5,0.5 # Avoid periodic boundaries problems. 24767 24768 if ['$3']!='100%' # With outer fading. 24769 repeat $!-1 l[0,1] 24770 +blend_seamless $1,$2,100% channels.. 100% !=.. 0 distance.. 1 24771 iM={-2,iM} ic={if(${is_percent\ $3},2*$3*$iM,1+$3)} 24772 if $ic<=$iM c.. 0,{max(1,$ic)} n.. 0,1 24773 else n.. 0,{max(0,2-$ic/$iM)} 24774 fi 24775 *.. -1 +.. 1 24776 j[0] [2],0,0,0,0,1,[1] rm[1,2] 24777 endl done 24778 else # Without outer fading. 24779 24780 repeat $!-1 l[0,1] 24781 24782 # Get background average color. 24783 +r[0] 1,1,1,100%,2 avg={^} rm. 24784 24785 # Compute mixed gradients of background and top layer. 24786 split_opacity. !=. 0 *.. . erode. 3 24787 g[0,1] xy,1 24788 *[-3,-2] . 24789 24790 # Modify mask if 'mixed' mode selected. 24791 if $1 24792 +a[0,1] c +a[2,3] c norm[-2,-1] 24793 <[-2,-1] *[-2,-1] 24794 fi 24795 24796 # Compute the desired gradient map. 24797 if $2 24798 distance. 0 24799 iM={iM} ic={if(${is_percent\ $2},2*$2*$iM,1+$2)} 24800 if $ic<=$iM c. 0,{max(1,$ic)} n. 0,1 24801 else n. 0,{max(0,2-$ic/$iM)} 24802 fi 24803 fi 24804 24805 j[-5] ...,0,0,0,0,1,. 24806 j[-4] ..,0,0,0,0,1,. 24807 rm[-3--1] 24808 24809 # Compute divergence (right-hand term of Poisson eq.) 24810 g[0] x,-1 g[1] y,-1 + 24811 24812 # Inverse Laplacian and renormalize 24813 ilaplacian 0 24814 +fc. $avg 24815 +[-2,-1] 24816 c 0,255 24817 24818 endl done 24819 fi 24820 z 16,16,{w-17},{h-17} 24821 24822#@cli fade_diamond : 0<=_start<=100,0<=_end<=100 24823#@cli : Create diamond fading from selected images. 24824#@cli : Default values: 'start=80' and 'end=90'. 24825#@cli : $ image.jpg testimage2d {w},{h} +fade_diamond 80,85 24826fade_diamond : skip ${1=70},${2=90} 24827 e[^-1] "Create ($1%,$2%) diamond-shaped fading from image$?." 24828 repeat int($!/2) l[$>,{$>+1}] 24829 (0,1,0;1,1,1;0,1,0) _fade $1,$2 24830 endl done 24831 24832#@cli fade_linear : _angle,0<=_start<=100,0<=_end<=100 24833#@cli : Create linear fading from selected images. 24834#@cli : Default values: 'angle=45', 'start=30' and 'end=70'. 24835#@cli : $ image.jpg testimage2d {w},{h} +fade_linear 45,48,52 24836fade_linear : skip ${1=45},${2=30},${3=70} 24837 e[^-1] "Create ($2%,$3%) linear fading from image$?, with angle $1 deg." 24838 repeat int($!/2) l[$>,{$>+1}] 24839 64,64,1,1,"x*cos($1*pi/180) + y*sin($1*pi/180)" _fade $2,$3 24840 endl done 24841 24842#@cli fade_radial : 0<=_start<=100,0<=_end<=100 24843#@cli : Create radial fading from selected images. 24844#@cli : Default values: 'start=30' and 'end=70'. 24845#@cli : $ image.jpg testimage2d {w},{h} +fade_radial 30,70 24846fade_radial : skip ${1=30},${2=70} 24847 e[^-1] "Create ($1%,$2%) radial fading from image$?." 24848 repeat int($!/2) l[$>,{$>+1}] 24849 100%,100% =. 1,50%,50% distance. 1 _fade $1,$2 24850 endl done 24851 24852#@cli fade_x : 0<=_start<=100,0<=_end<=100 24853#@cli : Create horizontal fading from selected images. 24854#@cli : Default values: 'start=30' and 'end=70'. 24855#@cli : $ image.jpg testimage2d {w},{h} +fade_x 30,70 24856fade_x : skip ${1=30},${2=70} 24857 e[^-1] "Create ($1%,$2%) horizontal fading from image$?." 24858 repeat int($!/2) l[$>,{$>+1}] (0,1) _fade $1,$2 endl done 24859 24860#@cli fade_y : 0<=_start<=100,0<=_end<=100 24861#@cli : Create vertical fading from selected images. 24862#@cli : Default values: 'start=30' and 'end=70'. 24863#@cli : $ image.jpg testimage2d {w},{h} +fade_y 30,70 24864fade_y : skip ${1=30},${2=70} 24865 e[^-1] "Create ($1%,$2%) vertical fading from image$?." 24866 repeat int($!/2) l[$>,{$>+1}] (0;1) _fade $1,$2 endl done 24867 24868#@cli fade_z : 0<=_start<=100,0<=_end<=100 24869#@cli : Create transversal fading from selected images. 24870#@cli : Default values: 'start=30' and 'end=70'. 24871fade_z : skip ${1=30},${2=70} 24872 e[^-1] "Create ($1%,$2%) transversal fading from image$?." 24873 repeat int($!/2) l[$>,{$>+1}] (0/1) _fade $1,$2 endl done 24874 24875#@cli sub_alpha : [base_image],_opacity_gain>=1 24876#@cli : Compute the minimal alpha-channel difference (opposite of alpha blending) between the selected images 24877#@cli : and the specified base image. 24878#@cli : The alpha difference A-B is defined as the image having minimal opacity, such that alpha_blend(B,A-B) = A. 24879#@cli : Default value: 'opacity_gain=1'. 24880#@cli : $ image.jpg testimage2d {w},{h} +sub_alpha[0] [1] display_rgba 24881sub_alpha : check "${2=1}>=1 && "${"is_image_arg $1"} 24882 e[^-1] "Compute minimal alpha-channel difference between image$? and base image $1, with opacity gain $2." 24883 remove_opacity repeat $! pass$1 0 l[$>,-1] 24884 to_colormode 0 r ${-max_whd},100%,0,0,0.5,0.5 # Normalize image dimensions. 24885 24886 # Estimate minimal alpha-channel. 24887 +>[0,1] *[2] 255 24888 -[0,2] [1] replace[2] 0,1 24889 i[2] [0] /[2,3] 24890 compose_channels[2] max 24891 *[2] $2 c[2] 0,1 24892 24893 # Synthetize alpha-difference image. 24894 +replace[2] 0,1 /[0,3] +[0,1] *[1] 255 a c 24895 24896 endl done 24897 24898#--------------------------------------------- 24899# 24900#@cli :: Image Sequences and Videos 24901# 24902#--------------------------------------------- 24903 24904#@cli animate : filter_name,"param1_start,...,paramN_start","param1_end,...,paramN_end",nb_frames>=0,\ 24905# _output_frames={ 0 | 1 },_output_filename : delay>0,_back and forth={ 0 | 1 } 24906#@cli : Animate filter from starting parameters to ending parameters or animate selected images 24907#@cli : in a display window. 24908#@cli : Default value: 'delay=30'. 24909#@cli : $ image.jpg animate flower,"0,3","20,8",9 24910animate : skip ${1=30},${2=0},${3=""},${4=10},${5=1},"${6=}" 24911 if "isnum($1)" 24912 e[0--3] "Animate image$?, with a delay of $1 ms"${"if $2 u \", in back-and-forth mode\" else u \"\" fi"}. 24913 if !$! return fi 24914 speed,pause,direction,scale,frame=$1,-1,1,1,0 24915 is_same_size={"res = 1; s = [ w#0,h#0 ]; for (k = 1, k<l && res, ++k, res = (s==[ w#k,h#k ]))"} 24916 24917 w[0] ${fitscreen[]\ {0,[w,h]}},1,0,{0,b}.{0,x} 24918 do 24919 title={$frame,b}{`narg({$frame,x})?_'.':0`}{$frame,x} 24920 if $is_same_size 24921 w[$frame] -1,-1,1,0,$title 24922 else 24923 w[$frame] {$scale*[${fitscreen[]\ {$frame,[w,h]}}]},1,0,$title 24924 fi 24925 frame+=$direction 24926 if $2 24927 if $frame==-1 frame=0 direction=1 24928 elif $frame==$! frame={$!-1} direction=-1 24929 fi 24930 else frame%=$! 24931 fi 24932 wait $speed 24933 24934 # Increase window size. 24935 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} scale*=1.5 wait -1 fi 24936 24937 # Decrease window size. 24938 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} scale/=1.5 wait -1 fi 24939 24940 # Reset window size. 24941 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} scale=1 wait -1 fi 24942 if {*,o} speed={min(500,max(10,$speed-10*{*,o}))} wait -1 fi 24943 if {*,SPACE} 24944 if $pause>=0 direction=$pause pause=-1 24945 else pause=$direction direction=0 fi 24946 wait -1 24947 fi 24948 24949 while {*}" && "!{*,Q}" && "!{*,ESC} w 0 24950 else 24951 e[0--3] "Compute animated version of filter '$1', from parameters $2 to $3 with $4 frames." 24952 if !($5||narg("$6")) return fi 24953 ($2) ($3) y[-2,-1] x a[-2,-1] y r. 100%,$4,1,1,3 mv. 0 rprogress 0 24954 repeat $!-1,u 24955 e[] " > Animate image ["$>"]" 24956 repeat $4 +l[0,1] 24957 -$1. {0,@{$>*{0,w}}-{($>+1)*{0,w}-1}} rm[0] 24958 if narg("$6") o ${filename\ "$6",$u,$>} fi 24959 if !$5 rm fi 24960 rprogress {100*($>+1)/$4} 24961 e[] "\r > Animate image ["$u"] : Frame "{$>+1}"/$4 " 24962 endl done 24963 rm[1] done rm[0] 24964 fi 24965 24966#@cli apply_camera : _"command",_camera_index>=0,_skip_frames>=0,_output_filename 24967#@cli : Apply specified command on live camera stream, and display it on display window [0]. 24968#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 24969#@cli : Default values: 'command=""', 'camera_index=0' (default camera), 'skip_frames=0' and 'output_filename=""'. 24970apply_camera : check_opencv $0 skip "${1=},${4=}" check "${2=0}>=0 && ${3=0}>=0" 24971 e[^-1] "Apply command '$1' on camera stream ""#$2, with $3 frames skip and output filename '$4'." 24972 is_ext "$4",avi is_outavi=${} 24973 is_ext "$4",mp4 is_outmp4=${} 24974 l[] i=0 do 24975 camera $2,1,$3 $1 w. -1,-1,"[G'MIC] Camera ""#$2 ("{w}x{h}")" 24976 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 24977 if {*,S} o. gmic_camera.png fi 24978 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 24979 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 24980 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 24981 rm. 24982 while {*}" && "!{*,ESC}" && "!{*,Q} camera $2,0 endl 24983 24984#@cli apply_files : "filename_pattern",_"command",_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,\ 24985# _output_filename 24986#@cli : Apply a G'MIC command on specified input image files, in a streamed way. 24987#@cli : If a display window is opened, rendered frames are displayed in it during processing. 24988#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image file 24989#@cli : extension (saved as a sequence of images). 24990#@cli : Default values: 'command=(undefined)', 'first_frame=0', 'last_frame=-1', 'frame_step=1' \ 24991# and 'output_filename=(undefined)'. 24992apply_files : check "isint(${3=0}) && $3>=0 && isint(${4=-1}) && ($4>=0 || $4==-1) && ${5=1}>=1" skip "${2=},${6=}" 24993 e[^-1] "Apply command '$2' on input image files '$1', with first frame $3, last frame $4, frame step $5 and 24994 output filename '$6'.\n" 24995 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} v + _apply_stream[] "${_file{$frame+1}}","$2",${3-5},"$6" 24996 24997#@cli apply_video : video_filename,_"command",_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,\ 24998# _output_filename 24999#@cli : Apply a G'MIC command on all frames of the specified input video file, in a streamed way. 25000#@cli : If a display window is opened, rendered frames are displayed in it during processing. 25001#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 25002#@cli : file extension (saved as a sequence of images). 25003#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 25004#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1' and 'output_filename=(undefined)'. 25005apply_video : check_opencv $0 check "isint(${3=0}) && $3>=0 && isint(${4=-1}) && ($4>=0 || $4==-1) && ${5=1}>=1" 25006 skip "${2=},${6=}" 25007 e[^-1] "Apply command '$2' on input video file '$1', with first frame $3, last frame $4, frame step $5 and 25008 output filename '$6'.\n" 25009 _N= v + _apply_stream[] "\"$1\",$frame","$2",${3-5},"$6" 25010 25011_apply_stream : skip "${2=},${6=}" 25012 is_ext "$6",avi is_outavi=${} 25013 is_ext "$6",mp4 is_outmp4=${} 25014 frame=$3 i=0 go_on=1 25015 do 25016 l[] $1 onfail go_on=0 endl 25017 if $go_on 25018 e[] "\r > Frame ""#"$frame$_N" " 25019 frame+=$5 25020 l $2 onfail error[0--5] "Command 'apply_stream': Specified command errored: "${} endl 25021 if !$! continue fi 25022 if narg("$6") 25023 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o. "$6",25,mp4v,1 else o. ${filename\ "$6",$i} i+=1 fi 25024 fi 25025 if {*} 25026 title="[G'MIC] Frame ""#"$frame 25027 if !narg($wh) wh=${fitscreen[]\ {[w,h]}} w. $wh,0,$title 25028 else w. -1,-1,0,$title 25029 fi 25030 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 25031 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 25032 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 25033 fi 25034 rm. 25035 fi 25036 while $go_on" && "($4==-1" || "$frame<=$4) 25037 if $is_outavi||$is_outmp4 o[] "$6",25,mp4v,0 fi 25038 25039#@cli average_files : "filename_pattern",_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,_output_filename 25040#@cli : Average specified input image files, in a streamed way. 25041#@cli : If a display window is opened, rendered frames are displayed in it during processing. 25042#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 25043#@cli : file extension (saved as a sequence of images). 25044#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1' and 'output_filename=(undefined)'. 25045average_files : check "isint(${2=0}) && $2>=0 && isint(${3=-1}) && ($3>=0 || $3==-1) && ${4=1}>=1" skip "${5=}" 25046 e[^-1] "Average input image files '$1', with first frame $2, last frame $3, frame step $4 and 25047 output filename '$5'.\n" 25048 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} v + _average_stream[] "${_file{$frame+1}}",${2-4},"$5" 25049 25050#@cli average_video : video_filename,_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,_output_filename 25051#@cli : Average frames of specified input video file, in a streamed way. 25052#@cli : If a display window is opened, rendered frames are displayed in it during processing. 25053#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 25054#@cli : file extension (saved as a sequence of images). 25055#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 25056#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1' and 'output_filename=(undefined)'. 25057average_video : check_opencv $0 check "isint(${2=0}) && $2>=0 && isint(${3=-1}) && ($3>=0 || $3==-1) && ${4=1}>=1" 25058 skip "${5=}" 25059 e[^-1] "Average frames of input video file '$1', with first frame $2, last frame $3, frame step $4 and 25060 output filename '$5'.\n" 25061 _N= v + _average_stream[] "\"$1\",$frame",${2-4},"$5" 25062 25063_average_stream : skip "${5=}" 25064 is_ext "$5",avi is_outavi=${} 25065 is_ext "$5",mp4 is_outmp4=${} 25066 frame=$2 i=0 go_on=1 N=0 25067 imM=inf,-inf 25068 do 25069 l[] $1 onfail go_on=0 endl 25070 if $go_on 25071 e[] "\r > Frame ""#"$frame$_N" " 25072 imM={v=[$imM];[min(im,v[0]),max(iM,v[1])]} 25073 N+=1 25074 if $!>1 r ${-max_whds} + fi 25075 if narg("$5") 25076 +/. $N c. $imM 25077 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o. "$5",25,mp4v,1 else o. ${filename\ "$5",$i} i+=1 fi 25078 rm. 25079 fi 25080 if {*} 25081 title="[G'MIC] Frame ""#"$frame 25082 +n 0,255 25083 if !narg($wh) wh=${fitscreen[]\ {[w,h]}} w. $wh,0,$title 25084 else w. -1,-1,0,$title 25085 fi 25086 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 25087 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 25088 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 25089 rm. 25090 fi 25091 frame+=$4 25092 fi 25093 while $go_on" && "($3==-1" || "$frame<=$3) 25094 / $N c $imM 25095 if $is_outavi||$is_outmp4 o[] "$5",25,mp4v,0 fi 25096 25097#@cli fade_files : "filename_pattern",_nb_inner_frames>0,_first_frame>=0,_last_frame={ >=0 | -1=last },\ 25098# _frame_step>=1,_output_filename 25099#@cli : Generate a temporal fading from specified input image files, in a streamed way. 25100#@cli : If a display window is opened, rendered frames are displayed in it during processing. 25101#@cli : The output filename may have extension 'avi' or 'mp4' (saved as a video), or any other usual image 25102#@cli : file extension (saved as a sequence of images). 25103#@cli : Default values: 'nb_inner_frames=10', 'first_frame=0', 'last_frame=-1', 'frame_step=1' \ 25104# and 'output_filename=(undefined)'. 25105fade_files : check "isint(${2=10}) && $2>0 && isint(${3=0}) && $3>=0 && 25106 isint(${4=-1}) && ($4>=0 || $4==-1) && ${5=1}>=1" skip "${6=}" 25107 e[^-1] "Fade input image files '$1', with $2 inner frames, first frame $3, last frame $4, frame step $5 and 25108 output filename '$6'.\n" 25109 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} v + _fade_stream[] "${_file{$frame+1}}",${2-5},"$6" 25110 25111#@cli fade_video : video_filename,_nb_inner_frames>0,_first_frame>=0,_last_frame={ >=0 | -1=last },\ 25112# _frame_step>=1,_output_filename 25113#@cli : Create a temporal fading sequence from specified input video file, in a streamed way. 25114#@cli : If a display window is opened, rendered frames are displayed in it during processing. 25115#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 25116#@cli : Default values: 'nb_inner_frames=10', 'first_frame=0', 'last_frame=-1', 'frame_step=1' \ 25117# and 'output_filename=(undefined)'. 25118fade_video : check_opencv $0 check "isint(${2=10}) && $2>0 && isint(${3=0}) && $3>=0 && 25119 isint(${4=-1}) && ($4>=0 || $4==-1) && ${5=1}>=1" skip "${6=}" 25120 e[^-1] "Fade frames of input video file '$1', with $2 inner frames, first frame $3, last frame $4, frame step $5 and 25121 output filename '$6'.\n" 25122 _N= v + _fade_stream[] "\"$1\",$frame",${2-5},"$6" 25123 25124_fade_stream : skip "${6=}" 25125 is_ext "$6",avi is_outavi=${} 25126 is_ext "$6",mp4 is_outmp4=${} 25127 frame=$3 i=0 go_on=1 25128 25129 l $1 onfail go_on=0 endl # Load first image. 25130 if !$go_on return fi 25131 w={w} h={h} s={s} 25132 if {*} w. ${fitscreen\ $w,$h},0,"[G'MIC]" fi 25133 pframe=$frame frame+=$5 25134 do 25135 l[] $1 onfail go_on=0 endl 25136 if !$go_on break fi 25137 to_colormode. $s r. $w,$h 25138 repeat $2+2 if $< 25139 title="[G'MIC] Frame ""#"$pframe" -> ""#"$frame$_N" ("{1+$>}/$2")" 25140 e[] "\r - "$title 25141 +j[0] [1],0,0,0,0,{$>/($2+1)} 25142 if narg("$6") 25143 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o. "$6",25,mp4v,1 else filename "$6",$i i+=1 o. ${} fi 25144 fi 25145 if {*} 25146 w. -1,-1,0,$title 25147 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 25148 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 25149 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 25150 fi 25151 rm. 25152 fi done 25153 rm[0] pframe=$frame frame+=$5 25154 while $go_on" && "($4==-1" || "$frame<=$4) 25155 25156 # Output last frame. 25157 if narg("$6") 25158 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o[] "$6",25,mp4v,0 else filename "$6",$i o. ${} fi 25159 fi 25160 rm 25161 25162#@cli files2video : "filename_pattern",_output_filename,_fps>0,_codec 25163#@cli : Convert several files into a single video file. 25164#@cli : Default values: 'output_filename=output.mp4', 'fps=25' and 'codec=mp4v'. 25165files2video : check "isint(${3=25}) && $3>0" skip "${2=output.mp4}",${4=mp4v} 25166 files=${"files \"$1\""} arg2var _file,$files nb_files=${} 25167 ('$files') if w>128 z. 0,127 s_files={t}... else s_files=$files fi rm. 25168 e[^-1] "Convert image files '"$s_files"' into frames of output video '$2', with $3 fps and $4 codec.\n" 25169 repeat $nb_files l[] 25170 file=${_file{$>+1}} 25171 _file=${basename\ $file} 25172 e[] "\r - Image "{1+$>}/$nb_files" ["$_file"] -> [$2] " 25173 i $file o "$2",$3,$4,1 25174 rm 25175 onfail e[] "\n - Error occurred on input file '"$file"'.\n" 25176 endl done 25177 o $"$2",0,0,0 25178 25179#@cli median_files : "filename_pattern",_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,\ 25180# _frame_rows[%]>=1,_is_fast_approximation={ 0 | 1 } 25181#@cli : Compute the median frame of specified input image files, in a streamed way. 25182#@cli : If a display window is opened, rendered frame is displayed in it during processing. 25183#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1', 'frame_rows=20%' \ 25184# and 'is_fast_approximation=0'. 25185median_files : check "isint(${2=0}) && $2>=0 && isint(${3=-1}) && ($3>=0 || $3==-1) && 25186 ${4=1}>=1 && ${5=20%}>0 && isnum(${6=0})" 25187 s0="fast" s1="precise" 25188 e[^-1] "Compute median of input image files '$1', with first frame $2, last frame $3, frame step $4, 25189 frame rows $5, using "${s{!$6}}" algorithm." 25190 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} 25191 l[] 25192 ${_file{$frame+1}} nm. res f. 0 25193 v + _median_stream "${_file{$frame+1}}",${2-6} v - 25194 endl 25195 25196#@cli median_video : video_filename,_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,\ 25197# _frame_rows[%]>=1,_is_fast_approximation={ 0 | 1 } 25198#@cli : Compute the median of all frames of an input video file, in a streamed way. 25199#@cli : If a display window is opened, rendered frame is displayed in it during processing. 25200#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 25201#@cli : Default values: 'first_frame=0', 'last_frame=-1', 'frame_step=1', 'frame_rows=100%' \ 25202# and 'is_fast_approximation=1'. 25203median_video : check_opencv $0 check "isint(${2=0}) && $2>=0 && isint(${3=-1}) && ($3>=0 || $3==-1) && 25204 ${4=1}>=1 && ${5=100%}>0 && isnum(${6=1})" 25205 s0="fast" s1="precise" 25206 e[^-1] "Compute median frame of input video file '$1', with first frame $2, last frame $3, frame step $4, 25207 frame rows $5, using "${s{!$6}}" algorithm." 25208 _N= 25209 l[] 25210 "$1",0 nm. res f. 0 25211 v + _median_stream "\"$1\",$frame",${2-6} v - 25212 endl 25213 25214_median_stream : 25215 25216 # Retrieve min/max values of all frames when fast method is used. 25217 if $6 25218 e[] "- Retrieve min/max values of all frames.\n" 25219 frame=$2 go_on=1 25220 imM=inf,-inf 25221 do 25222 l[] $1 onfail go_on=0 endl 25223 if $go_on 25224 e[] "\r > Frame ""#"$frame$_N" " 25225 imM={v=[$imM];[min(im,v[0]),max(iM,v[1])]} 25226 if {*} 25227 title="[G'MIC] Frame ""#"$frame 25228 if !narg($wh) wh=${fitscreen[]\ {[w,h]}} w. $wh,1,$title 25229 else w. -1,-1,1,$title 25230 fi 25231 fi 25232 rm. 25233 frame+=$4 25234 fi 25235 while $go_on" && "($3==-1" || "$frame<=$3) 25236 _N=/{$frame-$4} 25237 fact={v=[$imM];dv=v[1]-v[0];dv<=0?0:255/dv} 25238 fi 25239 25240 # Start median computation. 25241 h1={h-1} drows={round(${is_percent\ $5}?$5*h:$5)} 25242 nb_iter={round(h/$drows,1,1)} 25243 repeat $nb_iter 25244 row0={$drows*$>} row1={0,min(h,$row0+$drows-1)} 25245 e[] "- Iteration \#"{$>+1}/$nb_iter": Load rows "$row0-$row1/$h1".\n" 25246 frame=$2 go_on=1 25247 25248 if $6 25249 # Fast method : compute median frame using streamed histogram computation. 25250 N=0 25251 {w},$drows,256,{s} nm. hist 25252 do 25253 l[] $1 nm. img onfail go_on=0 endl 25254 if $img 25255 e[] "\r > Frame ""#"$frame$_N" " 25256 if {*}" && "!$> 25257 title="[G'MIC] Frame ""#"$frame 25258 if !narg($wh) wh=${fitscreen[]\ {img,[w,h]}} w[img] $wh,1,$title 25259 else w[img] -1,-1,1,$title 25260 fi 25261 fi 25262 rows[img] $row0,$row1 f[img] ":++i(#-2,x,y,round(i*"$fact"),c)" 25263 rm[img] 25264 frame+=$4 N+=1 25265 fi 25266 while $go_on" && "($3==-1" || "$frame<=$3) 25267 cumulate[hist] z 25268 N2={int($N/2)} 25269 [hist],[hist],1,[hist] 25270 if $N%2 # Odd number of frames. 25271 f. ":go_on = 1; for (z = 0, i(#"$hist",x,y,z,c)<"$N2" && z<256, ++z); z" 25272 else # Even number of frames. 25273 f. ":begin(N2p = "$N2"; N2n = N2p + 1); 25274 go_on = 1; 25275 for (zp = 0, i(#"$hist",x,y,zp,c)<N2p && zp<256, ++zp); 25276 for (zn = zp, i(#"$hist",x,y,zn,c)<N2n && zn<256, ++zn); 25277 0.5*(zn + zp);" 25278 fi 25279 rm.. 25280 /. $fact c. $imM 25281 25282 else 25283 # Slow method : compute median frame using temporal quicksort. 25284 l[] 25285 do 25286 l[] $1 nm. img onfail go_on=0 endl 25287 if $go_on 25288 e[] "\r > Frame ""#"$frame$_N" " 25289 if {*}" && "!$> 25290 title="[G'MIC] Frame ""#"$frame 25291 if !narg($wh) wh=${fitscreen[]\ {[w,h]}} w. $wh,1,$title 25292 else w. -1,-1,1,$title 25293 fi 25294 fi 25295 rows. $row0,$row1 25296 frame+=$4 25297 fi 25298 while $go_on" && "($3==-1" || "$frame<=$3) 25299 e[] "\r > Compute median blending of "$!" frames." 25300 __median_stream 25301 endl 25302 fi 25303 25304 _N=/{$frame-$4} 25305 j[res] .,0,$row0 25306 if {*} w[res] -1,-1,1,"[G'MIC] Iteration ""#"$> fi 25307 rm. 25308 25309 done 25310 e[] "- Done!" 25311 25312# Median blending optimized to deal with a lot of input frames. 25313__median_stream : 25314 if $!<2 return 25315 elif $!==2 + / 2 25316 else 25317 f. ": 25318 stack = vector"{0,2*$!}"(); 25319 stacksize = 0; 25320 push(elt0,elt1) = (stack[stacksize++] = elt0; stack[stacksize++] = elt1); 25321 pop() = (_s1 = stack[--stacksize]; _s0 = stack[--stacksize]; [_s0,_s1]); 25322 push(0,"$!" - 1); 25323 while (stacksize>0, 25324 range = pop(); 25325 lo = range[0]; 25326 hi = range[1]; 25327 pivot = i(#int((lo + hi)/2)); 25328 while (lo<=hi, 25329 while (i(#lo)<pivot, ++lo); 25330 while (pivot<i(#hi), --hi); 25331 if (lo<=hi, _tmp = i(#lo); i(#lo++) = i(#hi); i(#hi--) = _tmp); 25332 ); 25333 if (range[0]<hi,push(range[0],hi)); 25334 if (lo<range[1],push(lo,range[1])); 25335 )" 25336 if $!%2 k[{int($!/2)}] 25337 else k[{int($!/2-1)},{$!/2}] + / 2 25338 fi 25339 fi 25340 25341#@cli morph : nb_inner_frames>=1,_smoothness>=0,_precision>=0 25342#@cli : Create morphing sequence between selected images. 25343#@cli : Default values: 'smoothness=0.1' and 'precision=4'. 25344#@cli : $ image.jpg +rotate 20,1,1,50%,50% morph 9 25345morph : check "$1>=0.5 && ${2=0.1}>=0 && ${3=4}>=0" 25346 nbf={round($1)} 25347 e[^-1] "Create morphing sequence between image$?, with "$nbf" inner frames, smoothness $2 and precision $3.\n" 25348 nchan=${-max_s} if $nchan<=4 to_colormode $nchan else channels 0,{$nchan-1} fi 25349 ri[^0] [0],3 25350 repeat $!-1 nm={$>,n} l[$<,{$<+1}] 25351 e[] "\r > Morph image "$>" to image "{$>+1}". " 25352 +equalize[0,1] n[-2,-1] 0,255 25353 +displacement[3] [2],$2,$3 +displacement[2] [3],$2,$3 rm[-4,-3] 25354 repeat $nbf+2 if $>&&$< 25355 t={$>/($nbf+1)} omt={1-$t} 25356 +*[2] $t +warp[0] .,1,1,1 rm.. *. $omt 25357 +*[3] {1-$t} +warp[1] .,1,1,1 rm.. *. $t 25358 +[-2,-1] 25359 fi done 25360 rm[2,3] mv[2--1] 1 nm $nm 25361 endl done 25362 25363#@cli morph_files : "filename_pattern",_nb_inner_frames>0,_smoothness>=0,_precision>=0,\ 25364# _first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,_output_filename 25365#@cli : Generate a temporal morphing from specified input image files, in a streamed way. 25366#@cli : If a display window is opened, rendered frames are displayed in it during processing. 25367#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 25368#@cli : file extension (saved as a sequence of images). 25369#@cli : Default values: 'nb_inner_frames=10', 'smoothness=0.1', 'precision=4', 'first_frame=0', 'last_frame=-1', \ 25370# 'frame_step=1' and 'output_filename=(undefined)'. 25371morph_files : check "isint(${2=10}) && $2>0 && ${3=0.1}>=0 && ${4=4}>=0 && 25372 isint(${5=0}) && $5>=0 && isint(${6=-1}) && ($6>=0 || $6==-1) && ${7=1}>=1" skip "${8=}" 25373 e[^-1] "Morph input image files '$1', with $2 inner frames, smoothness $3, precision $4, first frame $5, 25374 last frame $6, frame step $7 and output filename '$8'.\n" 25375 files 3,"$1" _N=/{narg(${})-1} arg2var _file,${} _morph_stream[] "${_file{$frame+1}}",${2-7},"$8" 25376 25377#@cli morph_rbf : nb_inner_frames>=1,xs0[%],ys0[%],xt0[%],yt0[%],...,xsN[%],ysN[%],xtN[%],ytN[%] 25378#@cli : Create morphing sequence between selected images, using RBF-based interpolation. 25379#@cli : Each argument (xsk,ysk)-(xtk,ytk) corresponds to the coordinates of a keypoint 25380#@cli : respectively on the source and target images. The set of all keypoints define the overall image deformation. 25381morph_rbf : check "$1>=0.5" 25382 nbf={round($1)} 25383 e[^-1] "Create morphing sequence between image$? using RBF interpolation, "\ 25384 "with "$nbf" inner frames and keypoints ($*)." 25385 $=arg N={($#-1)/4} 25386 if int($N)!=$N error[0--2] "Command 'morph_rbf': Wrong number of arguments ($#)." fi 25387 ri[^0] [0],3 25388 repeat $!-1 nm={$>,n} l[$<,{$<+1}] 25389 e[] "\r > Morph image "$>" to image "{$>+1}". " 25390 25391 # Retrieve absolute keypoints coordinates. 25392 4,$N 25393 repeat wh a=${arg{2+$>}} isp=${"is_percent "$a} eval i[$>]=$isp?($>%2?w#0:h#0)*$a:$a done 25394 permute. yzcx 25395 25396 # Generate forward and backward warping fields. 25397 +f. "[i0,i1,i2-i0,i3-i1]" 25398 f.. "[i2,i3,i0-i2,i1-i3]" 25399 rbf[-2,-1] {0,[w,h]} 25400 25401 # Compute morphing sequence. 25402 repeat $nbf+2 if $>&&$< 25403 [0],[0],1,[0]," 25404 const interpolation = 1; 25405 const boundary = 3; 25406 const t = "$>"/("$nbf"+1); 25407 const omt = 1 - t; 25408 begin(print([t,omt])); 25409 ub = i(#2,x,y,0,0); 25410 vb = i(#2,x,y,0,1); 25411 uf = i(#3,x,y,0,0); 25412 vf = i(#3,x,y,0,1); 25413 omt*I(#0,x - t*uf,y - t*vf) + t*I(#1,x - omt*ub,y - omt*vb)" 25414 fi done 25415 rm[2,3] mv[2--1] 1 nm $nm 25416 endl done 25417 25418#@cli morph_video : video_filename,_nb_inner_frames>0,_smoothness>=0,_precision>=0,\ 25419# _first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1,_output_filename 25420#@cli : Generate a temporal morphing from specified input video file, in a streamed way. 25421#@cli : If a display window is opened, rendered frames are displayed in it during processing. 25422#@cli : The output filename may have extension '.avi' or '.mp4' (saved as a video), or any other usual image 25423#@cli : file extension (saved as a sequence of images). 25424#@cli : This command requires features from the OpenCV library (not enabled in G'MIC by default). 25425#@cli : Default values: 'nb_inner_frames=10', 'smoothness=0.1', 'precision=4', 'first_frame=0', 'last_frame=-1', \ 25426# 'frame_step=1' and 'output_filename=(undefined)'. 25427morph_video : check_opencv $0 check "isint(${2=10}) && $2>0 && ${3=0.1}>=0 && ${4=4}>=0 && 25428 isint(${5=0}) && $5>=0 && isint(${6=-1}) && ($6>=0 || $6==-1) && ${7=1}>=1" skip "${8=}" 25429 e[^-1] "Morph frames of input video file '$1', with $2 fading frames, smoothness $3, precision $4, first frame $5, 25430 last frame $6, frame step $7 and output filename '$8'.\n" 25431 _N= v + _morph_stream[] "\"$1\",$frame",${2-7},"$8" 25432 25433_morph_stream : skip "${8=}" 25434 is_ext "$8",avi is_outavi=${} 25435 is_ext "$8",mp4 is_outmp4=${} 25436 frame=$5 i=0 go_on=1 25437 25438 l $1 onfail go_on=0 endl # Load first image. 25439 if !$go_on return fi 25440 w={w} h={h} s={s} 25441 if {*} w. ${fitscreen\ $w,$h},0,"[G'MIC]" fi 25442 pframe=$frame frame+=$7 25443 do 25444 l[] $1 onfail go_on=0 endl 25445 if !$go_on break fi 25446 to_colormode. $s r. $w,$h 25447 cutvals={[min(im#0,im#1),max(iM#0,iM#1)]} 25448 e[] "\r - Frame ""#"$pframe" -> ""#"$frame" " 25449 +equalize[0,1] n[-2,-1] 0,255 25450 +displacement[3] [2],$3,$4 +displacement[2] [3],$3,$4 rm[-4,-3] 25451 repeat $2+2 if $< 25452 title="Frame ""#"$pframe" -> ""#"$frame" ("$>/$2") " 25453 e[] "\r - "$title 25454 t={$>/($2+1)} omt={1-$t} 25455 +*[2] $t +warp[0] .,1,1,1 rm.. *. $omt 25456 +*[3] {1-$t} +warp[1] .,1,1,1 rm.. *. $t 25457 +[-2,-1] c. $cutvals 25458 if narg("$8") 25459 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o. "$8",25,mp4v,1 else filename "$8",$i i+=1 o. ${} fi 25460 fi 25461 if {*} 25462 w. -1,-1,0,$title 25463 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 fi # Increase window size. 25464 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 fi # Decrease window size. 25465 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} wait -1 fi # Reset window size. 25466 fi 25467 rm. 25468 fi done 25469 rm[0,-2,-1] pframe=$frame frame+=$7 25470 while $go_on" && "($6==-1" || "$frame<=$6) 25471 25472 # Output last frame. 25473 if narg("$8") 25474 if $is_outavi||$is_outmp4 z. 0,{w-(w%8)-1} o[] "$8",25,mp4v,0 else filename "$8",$i o. ${} fi 25475 fi 25476 rm 25477 25478#@cli register_nonrigid : [destination],_smoothness>=0,_precision>0,_nb_scale>=0 25479#@cli : Register selected source images with specified destination image, using non-rigid warp. 25480#@cli : Default values: 'smoothness=0.2', 'precision=6' and 'nb_scale=0(auto)'. 25481#@cli : $ image.jpg +rotate 20,1,1,50%,50% +register_nonrigid[0] [1] 25482register_nonrigid : check ${is_image_arg\ $1}" && ${2=0.2}>=0 && ${3=5}>0 && ${4=0}>=0" 25483 e[^-1] "Register source image$? with destination image $1, using non-rigid warp with smoothness $2, 25484 precision $3 and $4 scale(s)." 25485 pass$1 0 equalize. n. 0,255 25486 repeat $!-1 25487 +equalize[$>] n. 0,255 +displacement.. .,$2,$3,$4 rm.. 25488 warp[$>] .,1,1,1 rm. 25489 done rm. 25490 25491#@cli register_rigid : [destination],_smoothness>=0,\ 25492# _boundary_conditions={ 0=dirichlet | 1=neumann | 2=periodic | 3=mirror } 25493#@cli : Register selected source images with specified destination image, using rigid warp (shift). 25494#@cli : Default values: 'smoothness=0.1%' and 'boundary_conditions=0'. 25495#@cli : $ image.jpg +shift 30,20 +register_rigid[0] [1] 25496register_rigid : check ${is_image_arg\ $1}" && ${2=0.1%}>=0 && isint(${3=0}) && $3>=0 && $3<=3" 25497 e[^-1] "Register source image$? with destination image $1, using rigid warp with smoothness $2." 25498 m "_register_rigid : b $2 equalize 256 n 0,1" 25499 pass$1 0 W,H,D,S={[w,h,d,s]} 25500 f={max(w,h)/1024} 25501 if $f<=1 # Small image: one-step registration 25502 _register_rigid. 25503 repeat $!-1 25504 if {$>,w!=$W||h!=$H||d!=$D} 25505 error[0--4] "Images have incompatible sizes ("{$>,[w,h,d,s]}") and ("{[$W,$H,$D,$S]}")." 25506 fi 25507 +_register_rigid[$>] phase_correlation. .. shift[$>] {^},0,$3 rm. 25508 done 25509 rm. 25510 else # Large image: two-steps registration 25511 +r. {[min(w,1024),min(h,1024),min(d,1024)]},100%,0,0,0.5,0.5 25512 rr2d.. 1024,1024,0,2 25513 _register_rigid[-2,-1] 25514 repeat $!-2 25515 if {$>,w!=$W||h!=$H||d!=$D} 25516 error[0--4] "Images have incompatible sizes ("{$>,[w,h,d,s]}") and ("{[$W,$H,$D,$S]}")." 25517 fi 25518 25519 # Low scale. 25520 +rr2d[$>] 1024,1024,0,2 _register_rigid. 25521 phase_correlation. ... 25522 s={$f*crop()} rm. 25523 25524 # High scale. 25525 +shift[$>] $s,0,$3 25526 r. {[min(w,1024),min(h,1024),min(d,1024)]},100%,0,0,0.5,0.5 _register_rigid. 25527 phase_correlation. .. 25528 s={[$s]+crop()} rm. 25529 25530 shift[$>] $s,0,$3 25531 done 25532 rm[-2,-1] 25533 fi 25534 um _register_rigid 25535 25536#@cli transition : [transition_shape],nb_added_frames>=0,100>=shading>=0,_single_frame_only={ -1=disabled | >=0 } 25537#@cli : Generate a transition sequence between selected images. 25538#@cli : Default values: 'shading=0' and 'single_frame_only=-1'. 25539#@cli : $ image.jpg +mirror c 100%,100% plasma[-1] 1,1,6 transition[0,1] [2],5 25540transition : check ${is_image_arg\ $1}" && $2>=0 && ${3=0}>=0 && $3<=100" skip ${4=-1} 25541 frame={round($4)} s0=" and shading $3" s1=", shading $3 and single-frame-only "$frame 25542 e[^-1] "Create transition sequence between image$? with $2 added frames, transition shape $1"${s{$4>0}}"." 25543 if $!<2" || "!$2 return fi 25544 to_colormode 0 r ${-max_whd},100%,0,0,0.5,0.5 25545 pass$1 0 norm. r. [0],[0],[0],1,3 n. 0,1 mv. 0 25546 repeat $!-2 l[0,{$<+1},{$<+2}] 25547 nm0={1,n} 25548 if $3 repeat $2 if $4<0" || "$>==$frame 25549 val0={($>+0.5)/$2-$3%} 25550 val1={($>+0.5)/$2+$3%} 25551 +f[0] '(i-$val0)/($val1-$val0)' c. 0,1 25552 +j[2] [1],0,0,0,0,1,. rm.. 25553 nm. $nm0\ ""#{1+$>} 25554 fi done else repeat $2 if $4<0" || "$>==$frame 25555 +>=[0] {($>+0.5)/$2} 25556 +j[2] [1],0,0,0,0,1,. rm.. 25557 nm. $nm0\ ""#{1+$>} 25558 fi done fi 25559 mv[2] $! 25560 endl done rm[0] 25561 25562#@cli transition3d : _nb_frames>=2,_nb_xtiles>0,_nb_ytiles>0,_axis_x,_axis_y,_axis_z,_is_antialias={ 0 | 1 } 25563#@cli : Create 3D transition sequence between selected consecutive images. 25564#@cli : 'axis_x', 'axis_y' and 'axis_z' can be set as mathematical expressions, depending on 'x' and 'y'. 25565#@cli : Default values: 'nb_frames=10', 'nb_xtiles=nb_ytiles=3', 'axis_x=1', 'axis_y=1', 'axis_z=0' \ 25566# and 'is_antialias=1'. 25567#@cli : $ image.jpg +blur 5 transition3d 9 display_rgba 25568transition3d : check "isint(${1=10}) && $1>=2 && isint(${2=3}) && $2>0 && isint(${3=$2}) && $3>0" 25569 skip ${4=1},${5=1},${6=0},${7=1} 25570 e[^-1] "Create 3D transition sequence between image$?, with $1 frames, $2x$3 tiles and rotation axis ($4,$5,$6).\n" 25571 if $!<2 return fi 25572 slices 0 to_rgb r ${-max_whds},3 25573 off=0 repeat $!-1 l[{$>+$off},{$>+$off+1}] 25574 e[] "\r > Generate transition from image "$>" to image "{$>+1}". " 25575 25576 # Create 3D rotation vectors. 25577 $2,$3,1,1,'$4' 25578 $2,$3,1,1,'$5' 25579 $2,$3,1,1,'$6' 25580 a[-3--1] z 25581 permute. zxyc r. 3,{$2*$3},1,1,-1 25582 repeat h rot$>={@0-2} shift. 0,-1,0,0 done 25583 rm. 25584 25585 # Create 3D tiles. 25586 +split_tiles[-2,-1] $2,$3 mv[0,1] $! 25587 N={$2*$3} i=0 y=0 25588 repeat $3 25589 x=0 25590 repeat $2 25591 lw={$i,w} lh={$i,h} 25592 imageplane3d[$i] imageplane3d[$N] r3d[$N] ${rot$i},180 c3d[$i,$N] +3d[$i,$N] 25593 x$i=$x y$i=$y x+=$lw i+=1 25594 done 25595 y+=$lh 25596 done 25597 25598 # Generate intermediate animation frames. 25599 repeat $1-2 25600 repeat $N r3d[$>] ${rot$>},{180/(1-$1)} ++3d[$>] ${x$>},${y$>},0 done 25601 +3d[-$N--1] c3d. 25602 25603 if $7 # Antialiased rendering. 25604 i... {-2,2*[w,h]},1,3,-1 25605 *3d. 2 j3d... .,50%,50%,0,1,2,0,0 rm. 25606 to_rgba.. replace_color.. 0,0,-1,-1,-1,255,0,0,0,0 25607 downsize_aliased.. 50 25608 else # Standard rendering. 25609 i... {-2,w},{-2,h},1,3,-1 j3d... .,50%,50%,0,1,2,0,0 rm. 25610 to_rgba.. replace_color.. 0,0,-1,-1,-1,255,0,0,0,0 25611 fi 25612 25613 done 25614 rm[0-{$N-1}] 25615 nm[1--2] {0,n} 25616 off+={$1-2} 25617 endl done 25618 25619#@cli video2files : input_filename,_output_filename,_first_frame>=0,_last_frame={ >=0 | -1=last },_frame_step>=1 25620#@cli : Split specified input video file into image files, one for each frame. 25621#@cli : First and last frames as well as step between frames can be specified. 25622#@cli : Default values: 'output_filename=frame.png', 'first_frame=0', 'last_frame=-1' and 'frame_step=1'. 25623video2files : check "isint(${3=0}) && $3>=0 && isint(${4=-1}) && ($4>=0 || $4==-1) && isint(${5=1}) && $5>=1" 25624 skip ${2="frame.png"} 25625 e[^-1] "Split input video file '$1' into image frames '$2', with first frame $3, last frame $4, and frame step $5.\n" 25626 frame=$3 stopflag=0 25627 do l[] 25628 i "$1",$frame 25629 if $! 25630 o ${"filename \"$2\","$frame} rm 25631 e[] "\r > Frame ""#"$frame 25632 frame+=$5 25633 else stopflag=1 25634 fi 25635 onfail stopflag=1 25636 endl while !$stopflag" && "($frame<=$4" || "$4==-1) 25637 25638#------------------------------ 25639# 25640#@cli :: Convenience Functions 25641# 25642#------------------------------ 25643 25644#@cli alert : _title,_message,_label_button1,_label_button2,... 25645#@cli : Display an alert box and wait for user's choice. 25646#@cli : If a single image is in the selection, it is used as an icon for the alert box. 25647#@cli : Default values: 'title=[G'MIC Alert]' and 'message=This is an alert box.'. 25648alert : skip "${1=[G"{`39`}"MIC Alert]},${2=This is an alert box.},${3=OK}" 25649 if $!==1 25650 e[0--3] "Display alert box, with image$?, title '$1', message '$2' and buttons '${3--1}'." 25651 else 25652 e[0--3] "Display alert box, with title '$1', message '$2' and buttons '${3--1}'." 25653 fi 25654 25655 if $!==1 logo= else logo=[] fi 25656 +l$logo 25657 25658 # Manage alert icon. 25659 if $!==1 to_rgb 25660 else # No logo provided, generate default logo (alert). 25661 64,64 polygon 3,50%,10%,10%,90%,90%,90%,1,1 b 3 >= 50% 25662 +erode. 5 -. .. ==. 0 25663 polygon. 4,47%,43%,53%,43%,53%,66%,47%,66%,1,0 circle. 50%,76%,2,1,0 25664 +*[0] 255 . 100%,100% a[-3--1] c -. '3*(y-h/2)' 25665 *. .. rm.. *[0] 255 rv a c 25666 drop_shadow 3,3,1 i[0] 100%,100%,1,3,200 blend alpha 25667 fi 25668 channels -1,2 25669 25670 # Create buttons graphics. 25671 $=arg 25672 repeat $#-2 label=${arg{$>+3}} 0 t. $label,0,0,16,1,-200 done 25673 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 25674 +[^0] 200 to_rgb[^0] 25675 mv[0] $! 25676 [0],[0],1,1,'(y-h/2)' *. -2 c. -30,30 +[0--3] . rm. c[^-1] 0,255 # Add shading to buttons. 25677 25678 repeat $!-1 l[$<] 25679 25680 # Create selected buttons. 25681 +rectangle 0,0,100%,100%,1,0xFFFFFFFF,0 25682 rectangle. 1,1,{w-2},{h-2},1,0xFFFFFFFF,0 25683 line. 2,{h-3},{w-3},{h-3},1,150 line. {w-3},{h-3},{w-3},2,1,150 25684 line. 1,1,{w-3},1,1,255 line. 1,1,1,{h-3},1,255 25685 rectangle. 4,4,{w-5},{h-5},1,0xAAAAAAAA,0 25686 25687 # Create clicked buttons. 25688 +shift.. 1,1,0,0,2 25689 rectangle. 0,0,100%,100%,1,0xFFFFFFFF,0 25690 rectangle. 1,1,{w-2},{h-2},1,0xFFFFFFFF,150 25691 rectangle. 4,4,{w-5},{h-5},1,0xAAAAAAAA,0 25692 25693 # Create default aspect. 25694 rectangle... 0,0,100%,100%,1,0xFFFFFFFF,0 25695 line... 1,{h-2},{w-2},{h-2},1,150 line... {w-2},{h-2},{w-2},1,1,150 25696 line... 0,0,{w-2},0,1,255 line... 0,0,0,{h-2},1,255 25697 25698 # Create coordinates image. 25699 i[0] 100%,100% =[0] 1,0,0 25700 25701 a c endl done 25702 25703 25704 # Render alert box graphics. 25705 +l 25706 channels 0,3 sh 1,100% -[50%--1] 200 rm[50%--1] frame 8,8,0 25707 if $!<6 a[^-1] x else append_tiles[^-1] , fi 25708 0 t. "$2",0,0,16,1,0,-200,-200,-200 r. {w+16},{h+8},1,4,0 25709 a[-2,-1] x,0.5 rv a y,0.5 25710 sh 1,100% +. 200 rm. 25711 rectangle 0,0,100%,100%,1,0xFFFFFFFF,0 25712 line 0,0,{w-2},0,1,0,255,255,255 line 0,0,0,{h-2},1,0,255,255,255 25713 endl 25714 rm.. 25715 +channels. 0 25716 25717 # Retrieve (x,y) coordinates of the buttons and fill active area. 25718 (0,{w-1}) (0;{-2,h-1}) ri[-2,-1] ...,3 a[-2,-1] c round. rv[-2,-1] *[-2,-1] 25719 discard. 0 y. r. {h/2},2,1,1,-1 25720 channels.. 1,3 rv[-2,-1] 25721 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 25722 a[-2,-1] c 25723 25724 # Enter event loop. 25725 repeat 9 if !{*$>} disp=$> break fi done # Find available display window. 25726 if !narg($disp) error[0--4] "Command '$0': Cannot open display window for alert box." fi 25727 25728 selected={if($#==3,0,-1)} clicked=-1 25729 do 25730 25731 # Render current view. 25732 +channels. 0,2 25733 if $clicked>=0 25734 x0={-3,i($clicked,0)} y0={-3,i($clicked,1)} 25735 sh[$clicked] 7,9 25736 j.. .,$x0,$y0 rm. 25737 elif $selected>=0 25738 x0={-3,i($selected,0)} y0={-3,i($selected,1)} 25739 sh[$selected] 4,6 25740 j.. .,$x0,$y0 rm. 25741 fi 25742 w$disp. 100%,100%,0,"$1" rm. wait 25743 25744 # Handle user interactions. 25745 xm={*$disp,x} ym={*$disp,y} bm={{*$disp,b}&1} val={i($xm,$ym,0,3)} 25746 if $bm" && "$val clicked={$val-1} 25747 elif $bm" && "!$val" && "$clicked>=0 selected=$clicked clicked=-1 25748 elif !$bm" && "$clicked>=0" && "$clicked==$val-1 break 25749 fi 25750 if {*$disp,ARROWRIGHT} selected={($selected+1)%{-2,w}} wait -1 25751 elif {*$disp,ARROWLEFT} selected={($selected-1)%{-2,w}+($selected==-1)} wait -1 25752 elif $selected>=0" && "{*$disp,ENTER} clicked=$selected break 25753 fi 25754 25755 while {*$disp}" && "!{*$disp,ESC} 25756 25757 # Return result (index of clicked button or '-1'). 25758 w$disp 0 rm u $clicked 25759 endl 25760 25761#@cli arg : n>=1,_arg1,...,_argN 25762#@cli : Return the n-th argument of the specified argument list. 25763arg : check "isint($1) && ($1)>0" 25764 $=arg u ${arg{1+($1)}} 25765 25766#@cli arg0 : n>=0,_arg0,...,_argN 25767#@cli : Return the n-th argument of the specified argument list (where 'n' starts from '0'). 25768arg0 : check "isint($1) && ($1)>=0" 25769 $=arg u ${arg{2+($1)}} 25770 25771#@cli arg2img : argument_1,...,argument_N 25772#@cli : Split specified list of arguments and return each as a new image (as a null-terminated string). 25773arg2img : 25774 $=arg repeat $# ({'${arg{1+$>}}'},0) done 25775 25776#@cli arg2var : variable_name,argument_1,...,argument_N 25777#@cli : For each i in [1...N], set 'variable_name$i=argument_i'. 25778#@cli : The variable name should be global to make this command useful (i.e. starts by an underscore). 25779arg2var : 25780 $=arg u {$#-1} repeat ${} $1{1+$>}=${arg{2+$>}} done 25781 25782#@cli autocrop_coords : value1,value2,... | auto 25783#@cli : Return coordinates (x0,y0,z0,x1,y1,z1) of the autocrop that could be performed on the latest 25784#@cli : of the selected images. 25785#@cli : Default value: 'auto' 25786autocrop_coords : skip ${1=auto} 25787 is_auto={['"$1"']=='auto'} 25788 w={w} h={h} d={d} 25789 value={i(w-1,h-1,d-1)} +=. {1+$value},100%,100%,100% _autocrop$is_auto. ${1--1} =. $value,100%,100%,100% 25790 x0={$w-w} y0={$h-h} z0={$d-d} rm. 25791 +_autocrop$is_auto. ${1--1} 25792 x1={$x0+w-1} y1={$y0+h-1} z1={$z0+d-1} rm. 25793 u $x0,$y0,$z0,$x1,$y1,$z1 25794 25795_autocrop0 : autocrop $* 25796_autocrop1 : skip $* autocrop 25797 25798#@cli average_colors 25799#@cli : Return the average vector-value of the latest of the selected images. 25800average_colors : 25801 res="" 25802 repeat s-1 sh. {1+$>} res=$res,{ia} rm. done 25803 sh. 0 u {ia}$res rm. 25804 25805#@cli base642img : "base64_string" 25806#@cli : Decode given base64-encoded string as a newly inserted image at the end of the list. 25807#@cli : The argument string must have been generated using command 'img2base64'. 25808base642img : 25809 base642uchar "$1" unserialize. 25810 25811#@cli base642uchar : "base64_string" 25812#@cli : Decode given base64-encoded string as a newly inserted 1-column image at the end of the list. 25813#@cli : The argument string must have been generated using command 'uchar2base64'. 25814base642uchar : 25815 0 25816 eval " 25817 ref(vector256(),hash); 25818 for (k = _'A', k<=_'Z', ++k, hash[k] = k - _'A'); 25819 for (k = _'a', k<=_'z', ++k, hash[k] = k - _'a' + 26); 25820 for (k = _'0', k<=_'9', ++k, hash[k] = k - _'0' + 52); 25821 hash[_'+'] = hash[_'-'] = 62; 25822 hash[_'/'] = hash[_'_'] = 63; 25823 s = ['$1']; 25824 const ss = size(s); 25825 ss>=2?( 25826 resize(#-1,1,ss*3/4 - (s[ss-1]==_'=') - (s[ss-2]==_'='),1,1); 25827 od = 0; 25828 for (os = 0, os<size(s), 25829 c1 = hash[s[os++]]; 25830 c2 = hash[s[os++]]; 25831 c3 = hash[s[os++]]; 25832 c4 = hash[s[os++]]; 25833 i[#-1,od++] = (c1<<2) | (c2>>4); 25834 i[#-1,od++] = ((c2&15)<<4) | (c3>>2); 25835 i[#-1,od++] = ((c3&3)<<6) | c4; 25836 ) 25837 )" 25838 nm. "[unnamed]" 25839 25840#@cli basename : file_path,_variable_name_for_folder 25841#@cli : Return the basename of a file path, and opt. its folder location. 25842#@cli : When specified 'variable_name_for_folder' must starts by an underscore 25843#@cli : (global variable accessible from calling function). 25844basename : skip ${2=unused} 25845 l[] ({"'$1'"}) replace 92,47 s +,47 25846 if i==47 a y $2={t} u "" 25847 elif $!==1 u {t} $2="" 25848 else a[^-1] y u {t} $2={-2,t} 25849 fi 25850 rm endl 25851 25852#@cli bin : binary_int1,... 25853#@cli : Print specified binary integers into their octal, decimal, hexadecimal and string representations. 25854bin : 25855 dec=${bin2dec\ ${^0}} 25856 e[^-1] "Convert binary integer"${arg\ 1+($#>1),"",s}" '${^0}' to octal '"${dec2oct\ $dec}"', 25857 decimal '"$dec"', hexadecimal '"${dec2hex\ $dec}"' and string '"${dec2str\ $dec}"'." 25858 25859#@cli bin2dec : binary_int1,... 25860#@cli : Convert specified binary integers into their decimal representations. 25861bin2dec : 25862 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 25863 25864_bin2dec : 25865 u {"str = vtos(abs($1)); 25866 for (k = val = 0, str[k], ++k, 25867 c = str[k]; 25868 (val<<=1)+=(c==_'0'?0:c==_'1'?1:nan); 25869 isnan(val)?break() 25870 ); sign($1)*val"} 25871 25872# Command to check what lines of G'MIC sources are larger than 120 columns. 25873_check120 : 25874 use_vt100 25875 it[] "$1" s +,10 25876 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]" 25877 lines={{@-1}-1} f. "I = I; if(I[0]<0,I[1]=-1); I" 25878 discard. -1 25879 if w 25880 r. 1,{h/2},1,2,-1 25881 repeat h 25882 l,L={I[$>]} 25883 e[] $_vt100_c" - [Line "$_vt100_b$L$_vt100_n$_vt100_c", "\ 25884 $_vt100_b{$l,h}$_vt100_n$_vt100_c" chars]: "$_vt100_n{$l,t} 25885 done 25886 fi 25887 rm 25888 _total_lines+=$lines 25889 e[] " - Scanned : "${lines}" lines" 25890 25891check120 : 25892 _total_lines=0 25893 files 0,*.h c={`narg($files)?',':0`} if narg(${}) files=$files$c${} fi 25894 files 0,*.cpp c={`narg($files)?',':0`} if narg(${}) files=$files$c${} fi 25895 files 0,*.c c={`narg($files)?',':0`} if narg(${}) files=$files$c${} fi 25896 files 0,*.gmic c={`narg($files)?',':0`} if narg(${}) files=$files$c${} fi 25897 repeat narg($files) 25898 arg 1+$>,$files file=${} 25899 e[] " * File '"$file"'." 25900 v + _check120 $file v - 25901 done 25902 e[] " - Total scanned : "${_total_lines}" lines" 25903 25904#@cli covariance_colors : _avg_outvarname 25905#@cli : Return the covariance matrix of the vector-valued colors in the latest of the selected images 25906#@cli : (for arbitrary number of channels). 25907#@cli : Parameter 'avg_outvarname' is used as a variable name that takes the value of the average vector-value. 25908covariance_colors : skip "${1=avg}" 25909 $1=${-average_colors} 25910 f ">begin( avg = [ "$""$1" ]; const S2 = s^2; C = vectorS2(0); ); 25911 mI = I - avg; C+=mul(mI,mI,s); 25912 end( C/=whd - 1; run('u ',vtos(C)) ); 25913 I" 25914 25915#@cli dec : decimal_int1,... 25916#@cli : Print specified decimal integers into their binary, octal, hexadecimal and string representations. 25917dec : 25918 e[^-1] "Convert decimal integer"${arg\ 1+($#>1),"",s}" '${^0}' to binary '"${dec2bin\ ${^0}}"',"\ 25919 " octal '"${dec2oct\ ${^0}}"', hexadecimal '"${dec2hex\ ${^0}}"' and string '"${dec2str\ ${^0}}"'." 25920 25921#@cli dec2str : decimal_int1,... 25922#@cli : Convert specifial decimal integers into its string representation. 25923dec2str : 25924 u {`[${^0}]`} 25925 25926#@cli dec2bin : decimal_int1,... 25927#@cli : Convert specified decimal integers into their binary representations. 25928dec2bin : 25929 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 25930 25931_dec2bin : 25932 u {`"const sgn = sign($1); 25933 const N = (isinf($1) || isnan($1)?1:1 + floor(log2(max(1,abs($1))))) + (sgn>=0?0:1); 25934 res = vectorN(); 25935 sgn>=0?0:(res[0] = _'-'); 25936 for (val = abs($1); k = size(res) - 1, k>=(sgn<0?1:0), --k, res[k] = _'0' + (val&1); val>>=1); res"`} 25937 25938#@cli dec2hex : decimal_int1,... 25939#@cli : Convert specified decimal integers into their hexadecimal representations. 25940dec2hex : 25941 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 25942 25943_dec2hex : 25944 u {`"begin(tab = [ _'0',_'1',_'2',_'3',_'4',_'5',_'6',_'7',_'8',_'9',_'a',_'b',_'c',_'d',_'e',_'f' ]); 25945 const sgn = sign($1); 25946 const N = (isinf($1) || isnan($1)?1:1 + floor(log2(max(1,abs($1)))/4)) + (sgn>=0?0:1); 25947 res = vectorN(); 25948 sgn>=0?0:(res[0] = _'-'); 25949 for (val = abs($1); k = size(res) - 1, k>=(sgn<0?1:0), --k, res[k] = tab[val&15]; val>>=4); res"`} 25950 25951#@cli dec2oct : decimal_int1,... 25952#@cli : Convert specified decimal integers into their octal representations. 25953dec2oct : 25954 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 25955 25956_dec2oct : 25957 u {`"const sgn = sign($1); 25958 const N = (isinf($1) || isnan($1)?1:1 + floor(log2(max(1,abs($1)))/3)) + (sgn>=0?0:1); 25959 res = vectorN(); 25960 sgn>=0?0:(res[0] = _'-'); 25961 for (val = abs($1); k = size(res) - 1, k>=(sgn<0?1:0), --k, res[k] = _'0' + (val&7); val>>=3); res"`} 25962 25963#@cli fact : value 25964#@cli : Return the factorial of the specified value. 25965fact : check isint($1) 25966 res=1 repeat $1 res*={($>+1)} done u $res 25967 25968#@cli fibonacci : N>=0 25969#@cli : Return the Nth number of the Fibonacci sequence. 25970#@cli : $ echo ${"fibonacci 10"} 25971#@cli : \n~~~\n[gmic]-0./ Start G'MIC interpreter.\n[gmic]-0./ 55\n[gmic]-0./ End G'MIC interpreter.\n~~~\n 25972fibonacci : check "$1>=0" 25973 u {N=$1;if(N<2,N,for(n=N;F0=0;F1=1,n=n-1,F2=F0+F1;F0=F1;F1=F2))} 25974 25975#@cli file_mv : filename_src,filename_dest 25976#@cli : Rename or move a file from a location $1 to another location $2. 25977file_mv : 25978 e[^-1] "Move file '$1' to location '$2'." 25979 if ${-is_windows} x "move "$1" "$2 else x "mv "$1" "$2 fi 25980 25981#@cli file_rand 25982#@cli : Return a random filename for storing temporary data. 25983file_rand : 25984 do filename=${-path_tmp}gmic$_pid{`round(u(vector6(_'0'),vector6(_'9')))`} 25985 while isfile(['{/$filename}']) 25986 u $filename 25987 25988#@cli filename : filename,_number1,_number2,...,_numberN 25989#@cli : Return a filename numbered with specified indices. 25990filename : skip "${1=default}" 25991 if $#==1 u "$1" 25992 else 25993 (${2--1}) nm. "$1" u {f}{b} 25994 repeat w 25995 u ${}_{int(i/100000)%10}{int(i/10000)%10}{int(i/1000)%10}{int(i/100)%10}{int(i/10)%10}{i%10} 25996 shift. -1 25997 done 25998 if narg({'{x}'}) u ${}.{x} fi 25999 rm. 26000 fi 26001 26002#@cli files : _mode,path : (+) 26003#@cli : Return the list of files and/or subfolders from specified path. 26004#@cli : 'path' can be eventually a matching pattern. 26005#@cli : 'mode' can be { 0=files only | 1=folders only | 2=files + folders }. 26006#@cli : Add '3' to 'mode' to return full paths instead of filenames only. 26007#@cli : Default value: 'mode=5'. 26008 26009#@cli fitratio_wh : min_width,min_height,ratio_wh 26010#@cli : Return a 2D size 'width,height' which is bigger than 'min_width,min_height' and has the specified w/h ratio. 26011fitratio_wh : 26012 if $3*$2>$1 u {int($3*$2)},$2 else u $1,{int($1/$3)} fi 26013 26014#@cli fitscreen : width,height,_depth,_minimal_size[%],_maximal_size[%] : [image],_minimal_size[%],_maximal_size[%] 26015#@cli : Return the 'ideal' size WxH for a window intended to display an image of specified size on screen. 26016#@cli : Default values: 'depth=1', 'minimal_size=128' and 'maximal_size=85%'. 26017fitscreen : skip "${2=},${3=},${4=},${5=}" 26018 if ${"is_image_arg $1"} 26019 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 26020 else 26021 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 26022 fi 26023 eval " 26024 is_percent(str) = (unref(_is_pct); _is_pct=['#str']; _is_pct[size(_is_pct) - 1]==_'%'); 26025 const u = "{*,u}"; 26026 const v = "{*,v}"; 26027 ms = round(is_percent("$m")?[ u,v ]*"$m":[ "$m,$m" ]); 26028 Ms = round(is_percent("$M")?[ u,v ]*"$M":[ "$M,$M" ]); 26029 s = [ "$W,$H" ]; 26030 "$D">1?(s+="$D"); 26031 s[0]<ms[0]?(s = [ ms[0],s[1]*ms[0]/s[0] ]); 26032 s[1]<ms[1]?(s = [ s[0]*ms[1]/s[1],ms[1] ]); 26033 s[0]>Ms[0]?(s = [ Ms[0],s[1]*Ms[0]/s[0] ]); 26034 s[1]>Ms[1]?(s = [ s[0]*Ms[1]/s[1],Ms[1] ]); 26035 s[0] = max(1,s[0],ms[0]); 26036 s[1] = max(1,s[1],ms[1]); 26037 round(s)" 26038 26039#@cli fontchart 26040#@cli : Insert G'MIC font chart at the end of the image list. 26041#@cli : $ fontchart 26042fontchart : 26043 e[^-1] "Generate G'MIC font chart." 26044 l[] 26045 repeat 256 26046 if $>==92 char=\\ else char={`max(1,(c=$>;c>=23&&c<=28?32:c))`} fi 26047 0 t. {``$char},0,0,50,1,255 26048 done 26049 a z,0.5 26050 s z 26051 repeat $! 26052 t[$>] $>,1,-1,13,1,200 26053 0 t. \\${dec2oct\ $>},1,-1,13,1,1 26054 100%,100%,1,1,200 j[$>] .,{$>,[w,h]-[w#-1,h#-1]},0,0,1,.. rm[-2,-1] 26055 done 26056 frame 1,1,128 append_tiles , 26057 endl 26058 26059# font2cimgh 26060# Encode a font image as a C-style string for CImg.h. 26061font2cimgh : 26062 e[^-1] "Encode font image$? as a C-style string for CImg.h." 26063 repeat $! l[$>] bnm={0,b} 26064 e[] " > Encode font '"$bnm"'." 26065 W,H={[w/256,h]} 26066 if !isint($W) error[0--4] "Font image '"$bnm"' has wrong dimensions ("{[w,h,d,s]}")." fi 26067 +f "i==im || i==iM" is_binary={im==1} rm. 26068 26069 # Find best parameters for RLE compression. 26070 Mm=0 MM=100 26071 do 26072 M={floor(($Mm+$MM)/2)} 26073 +compress_rle $is_binary,$M rows. 6,100% +. {32-im} iM={iM} 26074 if iM<126 Mm=$M rm. elif iM>126 MM=$M rm. fi 26075 while $iM!=126 26076 k. nb_chunks={1+int(h/65536)} 26077 26078 e[] "\r > Encode font '"$bnm"' -> W = "$W", H = "$H", M = "$M", is_binary = "$is_binary", 26079 nb_chunks = "$nb_chunks"." 26080 26081 # Generate C-style string for storing font data. 26082 replace_str "\\","\\\\" 26083 replace_str "\"","\\\"" 26084 s y,-111 26085 repeat $! 26086 if {$>,i[h-1]==_'\\'&&i[h-2]!=_'\\'} rows[$>] 0,{$>,h-2} rows[{$>+1}] -1,100% =[{$>+1}] {'\\'} fi 26087 l[$>] 26088 i[0] ('" \""') ('\"') 26089 if !$< ('" };"') fi 26090 ('\n') 26091 y a y 26092 endl 26093 done 26094 repeat $nb_chunks-1 ind={int($!*($>+1)/$nb_chunks)} l[$ind] = {','},0,100% ('\n') y a y endl done 26095 i[0] ('" static const char *const data_font"${W}x${H}"[] = {"\n') 26096 y a y ot $bnm.h 26097 26098 endl done 26099 26100#@cli fps 26101#@cli : Return the number of time this function is called per second, or -1 if this info is not yet available. 26102#@cli : Useful to display the framerate when displaying animations. 26103fps : 26104 if narg($_fps_fps) 26105 dt={$|-$_fps_time} 26106 if $dt>1 _fps_fps={round($_fps_nbframes/$dt)} _fps_time=$| _fps_nbframes=0 fi 26107 u $_fps_fps 26108 _fps_nbframes+=1 26109 else _fps_nbframes=0 _fps_time=$| _fps_fps=-1 u -1 26110 fi 26111 26112#@cli gcd : a,b 26113#@cli : Return the GCD (greatest common divisor) between a and b. 26114gcd : check "isint($1) && isint($2) && $1*$2!=0" 26115 _gcd {max(abs($1),abs($2))},{min(abs($1),abs($2))} 26116 26117_gcd : 26118 r={$1%$2} if $r u ${_gcd\ $2,$r} else u $2 fi 26119 26120#@cli hex : hexadecimal_int1,... 26121#@cli : Print specified hexadecimal integers into their binary, octal, decimal and string representations. 26122hex : 26123 dec=${hex2dec\ ${^0}} 26124 e[^-1] "Convert hexadecimal integer"${arg\ 1+($#>1),s,""}" '${^0}' to binary '"${dec2bin\ $dec}"', 26125 octal '"${dec2oct\ $dec}"', decimal '"$dec"' and string '"${dec2str\ $dec}"'." 26126 26127#@cli hex2dec : hexadecimal_int1,... 26128#@cli : Convert specified hexadecimal integers into their decimal representations. 26129hex2dec : 26130 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 26131 26132_hex2dec : 26133 u {"str = ['$1']; str[0]==_'-'?-stov([['0x'],str[1,max(1,size(str)-1)]]):stov([['0x'],str])"} 26134 26135#@cli hex2img : "hexadecimal_string" 26136#@cli : Insert new image 1xN at the end of the list with values specified by the given hexadecimal-encoded string. 26137hex2img : 26138 ('"$1"') 1,{w/2} 26139 f. "* 26140 from_char(x) = x>=48 && x<=57?x - 48:x-87; 26141 off = 2*y; 26142 from_char(i[#-2,off])*16 + from_char(i[#-2,off + 1])" 26143 rm.. 26144 26145#@cli hex2str : hexadecimal_string 26146#@cli : Convert specified hexadecimal string into a string. 26147#@cli : See also: ''str2hex''. 26148hex2str : skip ${1=""} 26149 if !narg("$1") u "" return fi 26150 ('$*') if w<2 rm. u "" return fi 26151 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 26152 u {t} rm. 26153 26154#@cli img2base64 : _encoding={ 0=base64 | 1=base64url },_store_names={ 0 | 1 } 26155#@cli : Encode selected images as a base64-encoded string. 26156#@cli : The images can be then decoded using command 'base642img'. 26157#@cli : Default values: 'encoding=0'. 26158img2base64 : check "isbool(${1=0}) && isbool(${2=1})" 26159 if isnum("$1") encoding=$1 else encoding=0 noarg fi 26160 +serialize auto,1,$2 u ${uchar2base64\ $encoding} rm. 26161 26162#@cli img2hex 26163#@cli : Return representation of last image as an hexadecimal-encoded string. 26164#@cli : Input image must have values that are integers in [0,255]. 26165img2hex : 26166 whds={w},{h},{d},{s} y. 2,{h} 26167 f.. "* 26168 to_char(x) = x>=0 && x<=9?48 + x:87 + x; 26169 i(#-1,0,y) = to_char(int(i/16)); 26170 i(#-1,1,y) = to_char(i%16); 26171 i" 26172 u {t} rm. r. $whds,-1 26173 26174#@cli img2str 26175#@cli : Return the content of the latest of the selected images as a special G'MIC input string. 26176img2str : 26177 i[-2] 256 26178 eval. ">begin(off = 0); 26179 sep = x==w - 1?(y==h - 1?(z==d - 1?(c==s - 1?0:_'^'):_'/'):_';'):_','; 26180 it = vtos(i); 26181 off + size(it) + 1>=w(#-2)?resize(#-2,round(1.5*w(#-2)),1,1,1,0); 26182 for (k = 0, k<size(it) && it[k], ++k, i[#-2,off++] = it[k]); 26183 i[#-2,off++] = sep" 26184 u {-2,t} rm.. 26185 26186#@cli img2text : _line_separator 26187#@cli : Return text contained in a multi-line image. 26188#@cli : Default value: 'line_separator= '. 26189img2text : skip "${1= }" 26190 +l s y s -,0 y x if $!>1 i[1--2] ('"$1"') fi a x u {0,t} rm endl 26191 26192#@cli img82hex 26193#@cli : Convert selected 8bits-valued vectors into their hexadecimal representations (ascii-encoded). 26194img82hex : 26195 e[^-1] "Convert 8bits-valued vector$? into hexadecimal representations (ascii-encoded)." 26196 % 256 y 26197 repeat $! 26198 +f[$>] 'v=int(i)&15;v+if(v<10,48,87)' # Lower digit 26199 f[$>] 'v=int(i)>>4;v+if(v<10,48,87)' # Higher digit 26200 a[$>,-1] x 26201 done 26202 26203#@cli hex2img8 26204#@cli : Convert selected hexadecimal representations (ascii-encoded) into 8bits-valued vectors. 26205hex2img8 : 26206 e[^-1] "Convert hexadecimal representation$? (ascii-encoded) into 8bits-valued vectors." 26207 repeat $! 26208 s. x,2 f[-2,-1] 'if(i>=97,i-87,i-48)' *.. 16 +[-2,-1] 26209 mv. 0 done 26210 26211#@cli is_3d 26212#@cli : Return 1 if all of the selected images are 3D objects, 0 otherwise. 26213is_3d : 26214 u 1 l check3d 1 onfail u 0 endl 26215 26216# Faster version. 26217_is_3d : 26218 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"} 26219 26220#@cli is_change : _value={ 0=false | 1=true } 26221#@cli : Set or unset the 'is_change' flag associated to the image list. 26222#@cli : This flag tells the interpreter whether or not the image list should be displayed when the pipeline ends. 26223#@cli : Default value: 'value=1'. 26224is_change : 26225 l[] check "isbool(${1=1})" arg=$1 onfail noarg arg=1 endl 26226 if $arg 0 rm. else w9[] 0 fi 26227 26228#@cli is_half 26229#@cli : Return 1 if the type of image pixels is limited to half-float. 26230is_half : 26231 (2049) u {i==2048} rm. 26232 26233#@cli is_ext : filename,_extension 26234#@cli : Return 1 if specified filename has a given extensioin. 26235is_ext : skip "${1=}" 26236 0 nm. "_$1" u {"lowercase(['"{x}"'])==lowercase(['$2'])"} rm. 26237 26238#@cli is_image_arg : string 26239#@cli : Return 1 if specified string looks like '[ind]'. 26240is_image_arg : skip "${1=;}" 26241 u {"str = ['$1']; 26242 s1 = size(str) - 1; 26243 (str[0]==_'[' && str[s1]==_']') || (str[0]=='.' && str[s1]=='.') && min(str)>=45 && max(str)<=122"} 26244 26245#@cli is_pattern : string 26246#@cli : Return 1 if specified string looks like a drawing pattern '0x......'. 26247is_pattern : skip "${1=;}" 26248 u {"str = ['$1']; size(str)>2 && same(str,'0x',2)"} 26249 26250#@cli is_percent : string 26251#@cli : Return 1 if specified string ends with a '%', 0 otherwise. 26252is_percent : 26253 u {"s=['$1'];s[size(s)-1]==_'%'"} 26254 26255#@cli is_variable_name : "str" 26256#@cli : Returns 1 if specified argument can be considered as a variable name, 0 otherwise. 26257is_variable_name : 26258 l[] 26259 u {"str = ['$1']; 26260 res = 1; 26261 for (k = 0, res && k<size(str), ++k, 26262 c = str[k]; 26263 res&= (c>=_'a' && c<=_'z') || (c>=_'A' && c<=_'Z') || (c>=_'0' && c<=_'9') || c=='_'; 26264 ); 26265 c = str[0]; 26266 res && (c<_'0' || c>_'9')"} 26267 onfail u 0 endl 26268 26269#@cli is_videofilename 26270#@cli : Return 1 if extension of specified filename is typical from video files. 26271is_videofilename : skip "${1=}" 26272 0 nm. "_$1" u {" 26273 ext = lowercase(['"{x}"']); 26274 ext=='avi' || ext=='mov' || ext=='asf' || ext=='divx' || ext=='flv' || ext=='mpg' || 26275 ext=='m1v' || ext=='m2v' || ext=='m4v' || ext=='mjp' || ext=='mp4' || ext=='mkv' || 26276 ext=='mpe' || ext=='movie' || ext=='ogm' || ext=='ogg' || ext=='ogv' || ext=='qt' || ext=='rm' || 26277 ext=='vob' || ext=='wmv' || ext=='xvid' || ext=='mpeg'"} 26278 rm. 26279 26280#@cli is_macos 26281#@cli : Return 1 if current computer OS is Darwin (MacOS), 0 otherwise. 26282is_macos : 26283 if !narg($_is_macos) l[] 26284 if ${-is_windows} _is_macos=0 26285 else 26286 file=${-path_tmp}gmic_uname 26287 x "uname >"{/$file} 26288 it[] $file 26289 _is_macos={same(crop(),'Darwin',6,0)} 26290 rm 26291 fi 26292 onfail _is_macos=0 rm 26293 endl fi 26294 u $_is_macos 26295 26296#@cli is_windows 26297#@cli : Return 1 if current computer OS is Windows, 0 otherwise. 26298is_windows : 26299 if !narg($_is_windows) _is_windows={['$OS']!=0" && "['$WINDIR']!=0} fi 26300 u $_is_windows 26301 26302#@cli math_lib 26303#@cli : Return string that defines a set of several useful macros for the embedded math evaluator. 26304math_lib : 26305 u " 26306 26307 # Return number of elements in min-heap #ind. 26308 heap_size(ind) = i[#ind,whd(#ind)-1]; 26309 26310 # Insert new element 'elt' into min-heap #ind. 26311 heap_insert(ind,elt) = ( 26312 _heap_siz = heap_size(#ind); 26313 _heap_siz>=h(#ind) - 1?resize(#ind,1,_heap_siz*2 + 2,1,s#ind,0); 26314 hind = h(#ind); 26315 unref(_heap_elt); 26316 _heap_elt = [ elt ]; 26317 _heap_eltsiz = max(1,size(_heap_elt)); 26318 26319 copy(i[#ind,_heap_siz],_heap_elt[0],_heap_eltsiz,hind,1); 26320 for (_heap_pos = _heap_siz, 26321 _heap_pos && (_heap_par = int((_heap_pos + 1)/2) - 1; _heap_elt[0]<i[#ind,_heap_par]), 26322 _heap_pos = _heap_par, 26323 copy(i[#ind,_heap_pos],i[#ind,_heap_par],_heap_eltsiz,hind,hind); 26324 copy(i[#ind,_heap_par],_heap_elt,_heap_eltsiz,hind,1); 26325 ); 26326 (heap_size(#ind)) = ++_heap_siz; 26327 ); 26328 26329 # Remove root element from min-heap #ind. 26330 heap_remove(ind) = ( 26331 _heap_siz = heap_size(#ind) - 1; 26332 hind = h(#ind); 26333 _heap_eltsiz = max(1,s#ind); 26334 26335 copy(i[#ind,0],i[#ind,_heap_siz],_heap_eltsiz,hind,hind); 26336 _heap_pos = 0; 26337 do ( 26338 _heap_left = 2*_heap_pos + 1; 26339 _heap_right = _heap_left + 1; 26340 value = i[#ind,_heap_pos]; 26341 _heap_right<_heap_siz && value>i[#ind,_heap_right]?( 26342 _heap_swap = i[#ind,_heap_left]<i[#ind,_heap_right]?_heap_left:_heap_right; 26343 ):_heap_left<_heap_siz && value>i[#ind,_heap_left]?( 26344 _heap_swap = _heap_left; 26345 ):break(); 26346 copy(i[#ind,_heap_siz],i[#ind,_heap_swap],_heap_eltsiz,hind,hind); # Use previous last elt as temporary for swap. 26347 copy(i[#ind,_heap_swap],i[#ind,_heap_pos],_heap_eltsiz,hind,hind); 26348 copy(i[#ind,_heap_pos],i[#ind,_heap_siz],_heap_eltsiz,hind,hind); 26349 _heap_pos = _heap_swap; 26350 ); 26351 (heap_size(#ind)) = _heap_siz; 26352 ); 26353 26354 # Return number of elements in dynamic array #ind. 26355 dar_size(ind) = i[#ind,whd(#ind)-1]; 26356 26357 # Return last element of a dynamic array 26358 dar_Back(ind) = I[#ind,dar_size(#ind)-1]; 26359 dar_back(ind) = i[#ind,dar_size(#ind)-1]; 26360 26361 # Inserts new element 'elt' into dynamic array #ind, at index [pos] ('pos' must be in [0,dar_size(#ind)]). 26362 dar_insert(ind,elt,pos) = ( 26363 _dar_pos = pos; 26364 _dar_siz = dar_size(#ind); 26365 if (_dar_pos<=_dar_siz, 26366 _dar_siz>=h(#ind) - 1?resize(#ind,1,_dar_siz*2 + 2,1,s(#ind),0); 26367 for (_dar_c = 0, _dar_c<s(#ind), ++_dar_c, 26368 copy(i(#ind,_dar_pos + 1,0,0,_dar_c),i(#ind,_dar_pos,0,0,_dar_c),_dar_siz - _dar_pos) 26369 ); 26370 unref(_dar_elt); _dar_elt = elt; 26371 copy(i[#ind,_dar_pos],_dar_elt,max(1,size(_dar_elt)),h(#ind),1); 26372 (dar_size(ind#)) = ++_dar_siz; 26373 ); 26374 ); 26375 26376 # Inserts new element 'elt' at the end of dynamic array #ind. 26377 dar_insert(ind,elt) = ( 26378 _dar_siz = dar_size(#ind); 26379 _dar_siz>=h(#ind) - 1?resize(#ind,1,_dar_siz*2 + 2,1,s(#ind),0); 26380 unref(_dar_elt); _dar_elt = elt; 26381 copy(i[#ind,_dar_siz],_dar_elt,max(1,size(_dar_elt)),h(#ind),1); 26382 (dar_size(ind#)) = ++_dar_siz; 26383 ); 26384 26385 # Remove element from dynamic array #ind, at index [pos] ('pos' must be in [0,dar_size(#ind) - 1]). 26386 dar_remove(ind,pos) = ( 26387 _dar_pos = pos; 26388 _dar_siz = dar_size(#ind); 26389 if (_dar_pos<_dar_siz, 26390 _dar_siz = --dar_size(#ind); 26391 for (_dar_c = 0, _dar_c<s(#ind), ++_dar_c, 26392 copy(i(#ind,_dar_pos,0,0,_dar_c),i(#ind,_dar_pos + 1,0,0,_dar_c),_dar_siz - _dar_pos) 26393 ); 26394 ) 26395 ); 26396 26397 # Remove last element from dynamic array #ind. 26398 dar_remove(ind) = ( 26399 _dar_siz = dar_size(#ind); 26400 _dar_siz>0?--dar_size(#ind); 26401 ); 26402 26403 # Distance from point A to point B 26404 dist(A,B) = ( 26405 norm(B - A); 26406 ); 26407 26408 # Distance from point X to segment [A,B] 26409 dist(X,A,B) = ( 26410 AB = B - A; 26411 P = A + dot(X - A,B - A)/max(1e-8,dot(AB,AB))*AB; 26412 dot(P - A,P - B)<=0?norm(P - X):min(norm(A - X),norm(B - X)); 26413 ); 26414 26415 # Distance from segment [A,B] to segment [C,D] 26416 dist(A,B,C,D) = ( 26417 min(dist(A,C,D),dist(B,C,D),dist(C,A,B),dist(D,A,B)); 26418 ); 26419 26420 # Return the 'm' largest eigenvalues of a (large) square matrix A, 26421 # using the Arnoldi iteration method (https://en.wikipedia.org/wiki/Arnoldi_iteration). 26422 # A larger 'm' goes with better numerical precision. 26423 meig(A,m,n) = ( 26424 unref(meig_m,meig_n); 26425 const meig_n = n; 26426 const meig_m = min(m,meig_n); 26427 26428 # Initialize data. 26429 ref(vector(#meig_m*meig_n),meig_V); 26430 ref(vector(#meig_m^2),meig_H); 26431 ref(expr('u(-1,1)',1,meig_n),meig_vj); meig_vj/=norm(meig_vj); 26432 26433 # Iteration loop. 26434 repeat (meig_m,meig_j, 26435 copy(meig_V[meig_j*meig_n],meig_vj,meig_n); 26436 meig_vj = A*meig_vj; 26437 for (meig_i = 0, meig_i<=meig_j, ++meig_i, 26438 ref(meig_V[meig_i*meig_n,meig_n],meig_vi); 26439 meig_d = dot(meig_vj,meig_vi); 26440 meig_H[meig_j*meig_m + meig_i] = meig_d; 26441 meig_vj-=meig_d*meig_vi; 26442 ); 26443 meig_nvj = norm(meig_vj); 26444 meig_H[meig_j*meig_m + meig_j + 1] = meig_nvj; 26445 meig_nvj<1e-12?break(); 26446 meig_vj/=meig_nvj; 26447 ); 26448 eig(meig_H)[0,m]; 26449 ); 26450 26451 # Dichotomic search : Find x in [xmin,xmax] s.a f(x) = target, with a epsilon-precision 26452 search_dichotomic(fn_x,target,epsilon,xmin,xmax) = ( 26453 # fn_x must be a strictly monotonic function ! 26454 # if 'xmin = xmax = nan', range of 'x' is auto-detected. 26455 _dicho_fn(x) = _dicho_sgn*(fn_x); 26456 _dicho_epsilon = epsilon; 26457 _dicho_m = xmin; 26458 _dicho_M = xmax; 26459 _dicho_sgn = 1; 26460 _dicho_autom = isnan(_dicho_m); 26461 _dicho_autoM = isnan(_dicho_M); 26462 if (_dicho_autom, _dicho_m = -1); 26463 if (_dicho_autoM, _dicho_M = 1); 26464 _dicho_sgn = _dicho_fn(_dicho_m)>_dicho_fn(_dicho_M)?-1:1; 26465 _dicho_res = nan; 26466 _dicho_target = _dicho_sgn*target; 26467 _dicho_nb_attempts = 30; 26468 _dicho_autom?do ( 26469 _dicho_fm = _dicho_fn(_dicho_m); 26470 _dicho_fm<_dicho_target?break(); 26471 _dicho_m*=2; 26472 _(while), --_dicho_nb_attempts); 26473 _dicho_nb_attempts?( 26474 _dicho_autoM?do ( 26475 _dicho_fM = _dicho_fn(_dicho_M); 26476 _dicho_fM>_dicho_target?break(); 26477 _dicho_M*=2; 26478 _(while), --_dicho_nb_attempts); 26479 _dicho_nb_attempts?( 26480 _dicho_nb_attempts = 100; 26481 do ( 26482 _dicho_c = (_dicho_m + _dicho_M)/2; 26483 _dicho_fc = _dicho_fn(_dicho_c); 26484 abs(_dicho_fc - _dicho_target)<_dicho_epsilon?(_dicho_res = _dicho_c; break()): 26485 _dicho_fc<_dicho_target?(_dicho_m = _dicho_c): 26486 (_dicho_M = _dicho_c); 26487 _(while), --_dicho_nb_attempts 26488 ); 26489 ); 26490 ); 26491 _dicho_res; 26492 ); 26493 search_dichotomic(fn_x,target,epsilon) = search_dichotomic(fn_x,target,1e-3,nan,nan); 26494 search_dichotomic(fn_x,target) = search_dichotomic(fn_x,target,1e-3); 26495 search_dichotomic(fn_x) = search_dichotomic(fn_x,0); 26496 26497 arrow(ind,P0,P1,angle,length,opacity,color) = ( # Draw an arrow from P0 to P1 on image #ind 26498 unref(_da_color); 26499 _opacity = opacity; 26500 _da_color = color; 26501 _P0 = P0; 26502 _P1 = P1; 26503 _P0P1 = _P1; 26504 _P0P1-=_P0; 26505 if (length<0, _P0P1*=-length/100, _P0P1*=length/norm2(_P0P1)); 26506 coords = [ _P0,_P1,_P1,_P1 - rot(angle°)*_P0P1,_P1,_P1 - rot(-angle°)*_P0P1 ]; 26507 repeat (3,_k, polygon(#ind,2,coords[4*_k,2],coords[4*_k+2,2],_opacity,_da_color)); 26508 ); 26509 26510 spline(ind,P0,T0,P1,T1,opacity,color) = ( # Draw spline P0-P1 with tangents T0,T1 on image #ind 26511 unref(_ds_color); 26512 _P0 = P0; 26513 _P1 = P1; 26514 _opacity = opacity; 26515 _ds_color = resize(color,s#ind)*=abs(_opacity); 26516 _omopacity = 1 - max(_opacity,0); 26517 _C = mul([ 2,-2,1,1,-3,3,-2,-1,0,0,1,0,1,0,0,0 ],[ _P0,P1,T0,T1 ],2); 26518 _dt = _dtmin = 1/max(abs(_P1 - _P0)); 26519 _P0 = inf; 26520 for (_t = 0, _t<=1, _t+=_dt, 26521 _P = round(mul([_t^3,_t^2,_t,1],_C,2)); 26522 _dP = abs(mul([3*_t^2,2*_t,1,0],_C,2)); 26523 _dt = min(_dtmin,0.75/max(_dP)); 26524 if (_P0!=_P, I(#ind,_P) = _ds_color + _omopacity*I(#ind,_P)); 26525 _P0 = _P; 26526 ); 26527 nan; 26528 ); 26529 26530 triangle(ind,P0,P1,P2,opacity,color0,color1,color2) = ( # Draw a shaded triangle P0-P1-P2 on image #ind 26531 unref(_dt_color); 26532 unref(_dt_color0); 26533 unref(_dt_color1); 26534 unref(_dt_color2); 26535 _opacity = opacity; 26536 _dt_color0 = resize(color0,s#ind); 26537 _dt_color1 = resize(color1,s#ind); 26538 _dt_color2 = resize(color2,s#ind); 26539 _A = round(P0); 26540 _B = round(P1); 26541 _C = round(P2); 26542 _xmin = max(0,min(_A[0],_B[0],_C[0])); 26543 _xmax = min(w#ind-1,max(_A[0],_B[0],_C[0])); 26544 _ymin = max(0,min(_A[1],_B[1],_C[1])); 26545 _ymax = min(h#ind-1,max(_A[1],_B[1],_C[1])); 26546 _M = transpose([_A,1,_B,1,_C,1],3); 26547 for (_y = _ymin, _y<_ymax, ++_y, 26548 for (_x = _xmin, _x<_xmax, ++_x, 26549 _L = round(solve(_M,[_x,_y,1]),1e-5); 26550 if (min(_L)>=0, 26551 _dt_color = _L[0]*_dt_color0 + _L[1]*_dt_color1 + _L[2]*_dt_color2; 26552 copy(i(#ind,_x,_y,0,0),_dt_color,size(_dt_color),whd#ind,1,_opacity); 26553 ); 26554 ); 26555 ); 26556 nan; 26557 ); 26558 26559 hsv2rgb(I) = ( # Convert HSV vector to RGB 26560 _I = I; 26561 _I[0]%=360; 26562 _I[1] = cut(_I[1],0,1); 26563 _I[2] = cut(_I[2],0,1); 26564 _c = _I[2]*_I[1]; 26565 _x = _c*(1-abs((_I[0]/60)%2-1)); 26566 (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; 26567 ); 26568 26569 is_intriangle(P,A,B,C) = ( # Test if a point is inside a triangle 26570 _v0 = C - A; 26571 _v1 = B - A; 26572 _v2 = P - A; 26573 _dot00 = dot(_v0,_v0); 26574 _dot01 = dot(_v0,_v1); 26575 _dot02 = dot(_v0,_v2); 26576 _dot11 = dot(_v1,_v1); 26577 _dot12 = dot(_v1,_v2); 26578 _invDenom = 1/(_dot00*_dot11 - _dot01*_dot01); 26579 _u = (_dot11*_dot02 - _dot01*_dot12)*_invDenom; 26580 _v = (_dot00*_dot12 - _dot01*_dot02)*_invDenom; 26581 _u>=0 && _v>=0 && _u + _v<1); 26582 26583 is_inquadrilateral(P,A,B,C,D) = ( # Test if a point is inside a quadrilateral 26584 is_intriangle(P,A,B,D) || is_intriangle(P,B,C,D); 26585 ); 26586 26587 is_percent(str) = (unref(_is_pct); _is_pct=['#str']; _is_pct[size(_is_pct) - 1]==_'%'); 26588 26589 length_spline(P0,T0,P1,T1) = ( # Compute the length of a spline P0-P1 with tangents T0,T1 26590 _P0 = P0; 26591 _P1 = P1; 26592 _C = mul([ 2,-2,1,1,-3,3,-2,-1,0,0,1,0,1,0,0,0 ],[ _P0,_P1,T0,T1 ],2); 26593 _l = norm(_P1 - _P0); 26594 if (_l, 26595 _nl = _l + 1; 26596 _dt = 1/_l; 26597 while (_nl - _l>=0.01, 26598 _l = _nl; 26599 _nl = 0; 26600 __P0 = _P0; 26601 for (_t = 0, _t<=1, _t+=_dt, 26602 __P = mul([_t^3,_t^2,_t,1],_C,2); 26603 _nl+=norm(__P - __P0); 26604 __P0 = __P; 26605 ); 26606 _dt = 1/max(1,_nl); 26607 ); 26608 ); 26609 _l 26610 ); 26611 26612 pexp(x) = ( # Good polynomial approximation of 'exp(-x^2)' for |x|<2 26613 _pexp_x = abs(x); 26614 _pexp_x<2?-0.110353*_pexp_x^4 + 0.683221*_pexp_x^3 -1.17282*_pexp_x^2 + 1:0 26615 ); 26616 26617 proj(X,A,B) = ( # Projection of point X onto line (A,B) 26618 _AB = B - A; 26619 P = A + dot(X - A,_AB)/max(1e-8,dot(_AB,_AB))*_AB; 26620 ); 26621 26622 # CIE DeltaE_2000 color difference function. 26623 # (code adapted from https://github.com/gfiumara/CIEDE2000). 26624 deltaE00(lab1,lab2) = ( 26625 _deltaE00_deg2rad(deg) = (deg*pi/180); 26626 unref(_deltaE00_lab1); _deltaE00_lab1 = lab1; 26627 unref(_deltaE00_lab2); _deltaE00_lab2 = lab2; 26628 unref(_deltaE00_k_L); const _deltaE00_k_L = 1; 26629 unref(_deltaE00_k_C); const _deltaE00_k_C = 1; 26630 unref(_deltaE00_k_H); const _deltaE00_k_H = 1; 26631 unref(_deltaE00_deg360inrad); const _deltaE00_deg360inrad = _deltaE00_deg2rad(360); 26632 unref(_deltaE00_deg180inrad); const _deltaE00_deg180inrad = _deltaE00_deg2rad(180); 26633 unref(_deltaE00_pow25to7); const _deltaE00_pow25to7 = 25^7; 26634 26635 # Step 1 26636 _deltaE00_C1 = norm(_deltaE00_lab1[1,2]); 26637 _deltaE00_C2 = norm(_deltaE00_lab2[1,2]); 26638 _deltaE00_barC = (_deltaE00_C1 + _deltaE00_C2)/2; 26639 _deltaE00_G = 0.5*(1 - sqrt(_deltaE00_barC^7/(_deltaE00_barC^7 + _deltaE00_pow25to7))); 26640 _deltaE00_a1prime = (1 + _deltaE00_G)*_deltaE00_lab1[1]; 26641 _deltaE00_a2prime = (1 + _deltaE00_G)*_deltaE00_lab2[1]; 26642 _deltaE00_Cprime1 = norm(_deltaE00_a1prime,_deltaE00_lab1[2]); 26643 _deltaE00_Cprime2 = norm(_deltaE00_a2prime,_deltaE00_lab2[2]); 26644 26645 _deltaE00_lab1[2]==0 && _deltaE00_a1prime==0?( 26646 _deltaE00_hprime1 = 0; 26647 ):( 26648 _deltaE00_hprime1 = atan2(_deltaE00_lab1[2],_deltaE00_a1prime); 26649 _deltaE00_hprime1<0?(_deltaE00_hprime1+=_deltaE00_deg360inrad); 26650 _deltaE00_lab2[2]==0 && _deltaE00_a2prime==0?( 26651 _deltaE00_hprime2 = 0; 26652 ):( 26653 _deltaE00_hprime2 = atan2(_deltaE00_lab2[2],_deltaE00_a2prime); 26654 _deltaE00_hprime2<0?(_deltaE00_hprime2+=_deltaE00_deg360inrad); 26655 ); 26656 ); 26657 26658 # Step 2 26659 _deltaE00_deltaLprime = _deltaE00_lab2[0] - _deltaE00_lab1[0]; 26660 _deltaE00_deltaCprime = _deltaE00_Cprime2 - _deltaE00_Cprime1; 26661 _deltaE00_CprimeProduct = _deltaE00_Cprime1*_deltaE00_Cprime2; 26662 _deltaE00_CprimeProduct==0?( 26663 _deltaE00_deltahprime = 0; 26664 ):( 26665 _deltaE00_deltahprime = _deltaE00_hprime2 - _deltaE00_hprime1; 26666 _deltaE00_deltahprime<-_deltaE00_deg180inrad?( 26667 _deltaE00_deltahprime += _deltaE00_deg360inrad; 26668 ):_deltaE00_deltahprime>_deltaE00_deg180inrad?( 26669 _deltaE00_deltahprime -= _deltaE00_deg360inrad; 26670 ); 26671 ); 26672 _deltaE00_deltaHprime = 2*sqrt(_deltaE00_CprimeProduct)*sin(_deltaE00_deltahprime/2); 26673 26674 # Step 3 26675 _deltaE00_barLprime = (_deltaE00_lab1[0] + _deltaE00_lab2[0])/2; 26676 _deltaE00_barCprime = (_deltaE00_Cprime1 + _deltaE00_Cprime2)/2; 26677 _deltaE00_hprimeSum = _deltaE00_hprime1 + _deltaE00_hprime2; 26678 _deltaE00_Cprime1*_deltaE00_Cprime2==0?( 26679 _deltaE00_barhprime = _deltaE00_hprimeSum; 26680 ):( 26681 abs(_deltaE00_hprime1 - _deltaE00_hprime2)<=_deltaE00_deg180inrad?( 26682 _deltaE00_barhprime = _deltaE00_hprimeSum/2; 26683 ):( 26684 _deltaE00_hprimeSum<_deltaE00_deg360inrad?( 26685 _deltaE00_barhprime = (_deltaE00_hprimeSum + _deltaE00_deg360inrad)/2; 26686 ):( 26687 _deltaE00_barhprime = (_deltaE00_hprimeSum - _deltaE00_deg360inrad)/2; 26688 ); 26689 ); 26690 ); 26691 26692 _deltaE00_T = 1.0 - (0.17*cos(_deltaE00_barhprime - _deltaE00_deg2rad(30))) + 26693 (0.24*cos(2*_deltaE00_barhprime)) + 26694 (0.32*cos(3*_deltaE00_barhprime + _deltaE00_deg2rad(6))) - 26695 (0.2*cos(4*_deltaE00_barhprime - _deltaE00_deg2rad(63))); 26696 _deltaE00_deltaTheta = _deltaE00_deg2rad(30)* 26697 exp(-((_deltaE00_barhprime - _deltaE00_deg2rad(275)) / _deltaE00_deg2rad(25))^2); 26698 26699 _deltaE00_R_C = 2*sqrt(_deltaE00_barCprime^7/(_deltaE00_barCprime^7 + _deltaE00_pow25to7)); 26700 _deltaE00_S_L = 1 + 0.015*(_deltaE00_barLprime - 50)^2/sqrt(20 + (_deltaE00_barLprime - 50)^2); 26701 _deltaE00_S_C = 1 + 0.045*_deltaE00_barCprime; 26702 _deltaE00_S_H = 1 + 0.015*_deltaE00_barCprime*_deltaE00_T; 26703 _deltaE00_R_T = -sin(2*_deltaE00_deltaTheta)* _deltaE00_R_C; 26704 26705 sqrt((_deltaE00_deltaLprime/(_deltaE00_k_L*_deltaE00_S_L))^2 + 26706 (_deltaE00_deltaCprime/(_deltaE00_k_C*_deltaE00_S_C))^2 + 26707 (_deltaE00_deltaHprime/(_deltaE00_k_H*_deltaE00_S_H))^2 + 26708 _deltaE00_R_T*_deltaE00_deltaCprime/(_deltaE00_k_C*_deltaE00_S_C)* 26709 _deltaE00_deltaHprime/(_deltaE00_k_H*_deltaE00_S_H)); 26710 );" 26711 26712#@cli mad 26713#@cli : Return the MAD (Maximum Absolute Deviation) of the last selected image. 26714#@cli : The MAD is defined as MAD = med_i|x_i-med_j(x_j)| 26715mad : 26716 if $! +-. {ic} abs. u {1.4826*ic} rm. else u 0 fi 26717 26718#@cli max_w 26719#@cli : Return the maximal width between selected images. 26720max_w : 26721 _minmax_whds max,0,1 26722 26723#@cli max_h 26724#@cli : Return the maximal height between selected images. 26725max_h : 26726 _minmax_whds max,1,1 26727 26728#@cli max_d 26729#@cli : Return the maximal depth between selected images. 26730max_d : 26731 _minmax_whds max,2,1 26732 26733#@cli max_s 26734#@cli : Return the maximal spectrum between selected images. 26735max_s : 26736 _minmax_whds max,3,1 26737 26738#@cli max_wh 26739#@cli : Return the maximal wxh size of selected images. 26740max_wh : 26741 _minmax_whds max,0,2 26742 26743#@cli max_whd 26744#@cli : Return the maximal wxhxd size of selected images. 26745max_whd : 26746 _minmax_whds max,0,3 26747 26748#@cli max_whds 26749#@cli : Return the maximal wxhxdxs size of selected images. 26750max_whds : 26751 _minmax_whds max,0,4 26752 26753#@cli median_color 26754#@cli : Return the median color value of the last selected image. 26755median_color : 26756 u {"expr('med(crop(#-1,0,0,0,y,w#-1,h#-1,d#-1,1))',1,3)"} 26757 26758#@cli min_w 26759#@cli : Return the minimal width between selected images. 26760min_w : 26761 _minmax_whds min,0,1 26762 26763#@cli min_h 26764#@cli : Return the minimal height between selected images. 26765min_h : 26766 _minmax_whds min,1,1 26767 26768#@cli min_d 26769#@cli : Return the minimal depth between selected images. 26770min_d : 26771 _minmax_whds min,2,1 26772 26773#@cli min_s 26774#@cli : Return the minimal s size of selected images. 26775min_s : 26776 _minmax_whds min,3,1 26777 26778#@cli min_wh 26779#@cli : Return the minimal wxh size of selected images. 26780min_wh : 26781 _minmax_whds min,0,2 26782 26783#@cli min_whd 26784#@cli : Return the minimal wxhxd size of selected images. 26785min_whd : 26786 _minmax_whds min,0,3 26787 26788#@cli min_whds 26789#@cli : Return the minimal wxhxdxs size of selected images. 26790min_whds : 26791 _minmax_whds min,0,4 26792 26793_minmax_whds : 26794 u {" 26795 mw = w; mh = h; md = d; ms = s; 26796 repeat (l,k, 26797 mw = $1(mw,w#k); 26798 mh = $1(mh,h#k); 26799 md = $1(md,d#k); 26800 ms = $1(ms,s#k); 26801 ); 26802 ([mw,mh,md,ms])[$2,$3]"} 26803 26804 26805#@cli nmd : eq. to 'named' : (+) 26806 26807#@cli named : _mode,"name1","name2",... : (+) 26808#@cli : Return the set of indices corresponding to images of the selection with specified names. 26809#@cli : After this command returns, the status contains a list of indices (unsigned integers), 26810#@cli : separated by commas (or an empty string if no images with those names have been found). 26811#@cli : (eq. to 'nmd'). 26812#@cli : 'mode' can be { 0=all indices (default) | 1=lowest index | 2=highest index | \ 26813# 3 = all indices (case insensitive) | 4 = lowest index (case insensitive) | 5 = highest index (case insensitive)} 26814 26815#@cli normalize_filename : filename 26816#@cli : Return a "normalized" version of the specified filename, without spaces and capital letters. 26817normalize_filename : 26818 ('"$1"') f. 'if(i>=65&&i<=90,i+32,if(i==32,95,i))' u {t} rm. 26819 26820#@cli oct : octal_int1,... 26821#@cli : Print specified octal integers into their binary, decimal, hexadecimal and string representations. 26822oct : 26823 dec=${oct2dec\ ${^0}} 26824 e[^-1] "Convert octal integer"${arg\ 1+($#>1),"",s}" '${^0}' to binary '"${dec2bin\ $dec}"', decimal '"$dec"', 26825 hexadecimal '"${dec2hex\ $dec}"' and string '"${dec2str\ $dec}"'." 26826 26827#@cli oct2dec : octal_int1,... 26828#@cli : Convert specified octal integers into their decimal representations. 26829oct2dec : 26830 $=arg res,sep= repeat $# res=$res$sep${_$0\ ${arg{$>+1}}} sep=, done u $res 26831 26832_oct2dec : 26833 u {"str = vtos(abs($1)); 26834 for (k = val = 0, str[k], ++k, 26835 c = str[k]; 26836 (val<<=3)+=(c>=_'0' && c<=_'7'?c - _'0':nan); 26837 isnan(val)?break() 26838 ); sign($1)*val"} 26839 26840#gmic ovh2stats : logfile_globname 26841#gmic : Generate statistics on the usage of G'MIC-Qt from OVH server logfiles. 26842#gmic : logfiles must be located in current directory. 26843#gmic : Default value: 'logfile_globname=gmic.eu-*-*-*.log.gz" 26844ovh2stats : skip "${1=gmic.eu-*-*-*.log.gz}" 26845 e[^-1] "Generate statistics on the usage of G'MIC-Qt from OVH server logfiles '$1'." 26846 use_vt100 26847 26848 # Load log files. 26849 files "$1" files=${} 26850 e[] "* Load log files." 26851 if !narg(${}) error[0--2] "No OVH logfiles matching name '$1' have been found." fi 26852 26853 repeat narg(${}) 26854 arg0 $>,$files file=${} 26855 day,month,year={"str = ['"$file"']; 26856 t1 = find(str,_'-') + 1; 26857 t2 = find(str,_'-',t1) + 1; 26858 t3 = find(str,_'-',t2) + 1; 26859 t1>0 && t2>t1 && t3>t2?( 26860 day = stov(str,t1); 26861 month = stov(str,t2); 26862 year = stov(str,t3); 26863 [ day,month,year ]; 26864 ):[0,0,0]"} 26865 if !$day&&!$month&&!$year day,month,year=n.a fi 26866 e[] " > "$year/$month/$day:" "$_vt100_g$file$_vt100_n 26867 it $file 26868 nm. ${year}_${month}_${day} 26869 done 26870 26871 # Keep only lines containing 'G'MIC-Qt'. 26872 repeat $! nm={$>,n} l[$>] s -,{'\n'} 26873 eval " 26874 str = ['G'MIC-Qt']; 26875 to_keep = vectorl(); 26876 p = 0; 26877 repeat (l,k, find(#k,str)>=0?(to_keep[p++] = k)); 26878 store(to_keep,'to_keep',p); 26879 run('$to_keep k[{^}]')" 26880 if $!>1 i[1--2] ('\n') fi 26881 a y nm $nm endl done 26882 26883 # Analyze log files. 26884 e[] "\n* Analyze log files (day by day)." 26885 +_ovh2stats # Display stats, day by day. 26886 26887 e[] "\n* Analyze log files (all days)." 26888 a y _ovh2stats # Display stats, all days. 26889 26890 26891_ovh2stats : 26892 v + N=$! repeat $! l[$>] ('{n}') replace. {'_'},{'/'} date={t} rm. 26893 s -,{'\n'} 26894 26895 # Name each image by the IP address. 26896 eval " 26897 name = vector256(); 26898 repeat (l,k, 26899 p = find(#k,_' '); 26900 copy(name,i[#k,0],p); 26901 name[p] = 0; 26902 run('name[',k,'] ',name); 26903 )" 26904 26905 # Discard IP duplicates. 26906 eval " 26907 const N = "$!"; 26908 ref(vector(#2*N),tab); 26909 repeat (N,k, 26910 ref(name(#k,256),nam); 26911 for (i = j = 0, i<size(nam) && nam[i], ++i, nam[i]!=_'.'?(nam[j++] = nam[i])); nam[j] = 0; 26912 tab[2*k] = stov(nam); 26913 tab[2*k + 1] = k; 26914 ); 26915 tab = sort(tab,1,N,2); 26916 for (i = 0, i<size(tab) - 1, ++i, tab[2*i]==tab[2*i + 2]?tab[2*i] = tab[2*i + 1] = -1); 26917 store(tab,'tab')" 26918 $tab discard. -1 r. 2,{h/2},1,1,-1 z. 1,1 k[{^}] 26919 26920 # Analyze G'MIC version, host software and OS. 26921 eval " 26922 gimp = krita = _8bf = paintdotnet = digikam = standalone = 0; 26923 linux = windows = macos = bsd = unknown = 0; 26924 ips = 0; 26925 repeat (l,k, 26926 ref(lowercase(crop(#k,0,0,0,0,1,256,1,1)),str); 26927 find(str,'gimp')>=0?++gimp: 26928 find(str,'krita')>=0?++krita: 26929 find(str,'8bf')>=0?++_8bf: 26930 find(str,'paint.net')>=0?++paintdotnet: 26931 find(str,'digikam')>=0?++digikam: 26932 ++standalone; 26933 26934 find(str,'windows')>=0?++windows: 26935 find(str,'linux')>=0?++linux: 26936 find(str,'mac os')>=0?++macos: 26937 find(str,'bsd')>=0?++bsd: 26938 ++unknown; 26939 26940 ++ips; 26941 ); 26942 store([ips,gimp,krita,_8bf,paintdotnet,digikam,standalone,windows,linux,macos,bsd,unknown],'features')" 26943 rm $features 26944 ips,gimp,krita,_8bf,paintdotnet,digikam,standalone,windows,linux,macos,bsd,unknown={^} 26945 26946 if $N>1 26947 e[] " > "$date": "\ 26948 ${_vt100_b}"Unique IPs"${_vt100_n}" = "$ips" (100%), "\ 26949 ${_vt100_m}${_vt100_b}"GIMP"${_vt100_n}" = "$gimp" ("{_round($gimp/$ips*100,0.1)}"%), "\ 26950 ${_vt100_c}${_vt100_b}"Krita"${_vt100_n}" = "$krita" ("{_round($krita/$ips*100,0.1)}"%), "\ 26951 ${_vt100_g}${_vt100_b}"8bf"${_vt100_n}" = "$_8bf" ("{_round($_8bf/$ips*100,0.1)}"%), "\ 26952 ${_vt100_r}${_vt100_b}"Paint.NET"${_vt100_n}" = "$paintdotnet" ("{_round($paintdotnet/$ips*100,0.1)}"%), "\ 26953 ${_vt100_m}${_vt100_b}"Digikam"${_vt100_n}" = "$digikam" ("{_round($digikam/$ips*100,0.1)}"%), "\ 26954 ${_vt100_c}${_vt100_b}"Standalone"${_vt100_n}" = "$standalone" ("{_round($standalone/$ips*100,0.1)}"%)." 26955 26956 e[] " "\ 26957 ${_vt100_r}${_vt100_b}"Windows"${_vt100_n}" = "$windows" ("{_round($windows/$ips*100,0.1)}"%), "\ 26958 ${_vt100_g}${_vt100_b}"Linux"${_vt100_n}" = "$linux" ("{_round($linux/$ips*100,0.1)}"%), "\ 26959 ${_vt100_m}${_vt100_b}"Mac OS"${_vt100_n}" = "$macos" ("{_round($macos/$ips*100,0.1)}"%), "\ 26960 ${_vt100_c}${_vt100_b}"BSD"${_vt100_n}" = "$bsd" ("{_round($bsd/$ips*100,0.1)}"%), "\ 26961 ${_vt100_c}${_vt100_b}"Unknown"${_vt100_n}" = "$unknown" ("{_round($unknown/$ips*100,0.1)}"%).\n" 26962 fi 26963 26964 endl done 26965 + / $N round. 26966 ips,gimp,krita,_8bf,paintdotnet,digikam,standalone,windows,linux,macos,bsd,unknown={^} 26967 summary0,summary1=Total,Average 26968 e[] " > "${summary{$N>1}}" : "\ 26969 ${_vt100_b}"Unique IPs"${_vt100_n}" = "$ips" (100%), "\ 26970 ${_vt100_m}${_vt100_b}"GIMP"${_vt100_n}" = "$gimp" ("{_round($gimp/$ips*100,0.1)}"%), "\ 26971 ${_vt100_c}${_vt100_b}"Krita"${_vt100_n}" = "$krita" ("{_round($krita/$ips*100,0.1)}"%), "\ 26972 ${_vt100_g}${_vt100_b}"8bf"${_vt100_n}" = "$_8bf" ("{_round($_8bf/$ips*100,0.1)}"%), "\ 26973 ${_vt100_r}${_vt100_b}"Paint.NET"${_vt100_n}" = "$paintdotnet" ("{_round($paintdotnet/$ips*100,0.1)}"%), "\ 26974 ${_vt100_m}${_vt100_b}"Digikam"${_vt100_n}" = "$digikam" ("{_round($digikam/$ips*100,0.1)}"%), "\ 26975 ${_vt100_c}${_vt100_b}"Standalone"${_vt100_n}" = "$standalone" ("{_round($standalone/$ips*100,0.1)}"%)." 26976 26977 e[] " "\ 26978 ${_vt100_r}${_vt100_b}"Windows"${_vt100_n}" = "$windows" ("{_round($windows/$ips*100,0.1)}"%), "\ 26979 ${_vt100_g}${_vt100_b}"Linux"${_vt100_n}" = "$linux" ("{_round($linux/$ips*100,0.1)}"%), "\ 26980 ${_vt100_m}${_vt100_b}"Mac OS"${_vt100_n}" = "$macos" ("{_round($macos/$ips*100,0.1)}"%), "\ 26981 ${_vt100_c}${_vt100_b}"BSD"${_vt100_n}" = "$bsd" ("{_round($bsd/$ips*100,0.1)}"%), "\ 26982 ${_vt100_c}${_vt100_b}"Unknown"${_vt100_n}" = "$unknown" ("{_round($unknown/$ips*100,0.1)}"%).\n" 26983 rm 26984 26985#@cli padint : number,_size>0 26986#@cli : Return a integer with 'size' digits (eventually left-padded with '0'). 26987padint : check "isint($1)" skip ${2=4} 26988 u "" repeat $2 u ${}{int($1/10^$<)%10} done 26989 26990#@cli path_cache 26991#@cli : Return a path to store G'MIC data files for one user (whose value is OS-dependent). 26992path_cache : 26993 if !narg({'$_path_cache'}) 26994 _path_cache=$_path_rc 26995 if ['$GMIC_CACHE_PATH']!=0 _patch_cache=$GMIC_CACHE_PATH 26996 elif !${-is_windows} 26997 if isdir(['{/$HOME/.cache}']) _path_cache=$HOME/.cache/gmic/ 26998 elif ['$XDG_CACHE_HOME']!=0 _path_cache=$XDG_CACHE_HOME/gmic/ 26999 fi 27000 if !isdir('{/$_path_cache}') x "mkdir -p "$_path_cache fi 27001 fi 27002 fi 27003 u $_path_cache 27004 27005#@cli path_current 27006#@cli : Return current folder from where G'MIC has been run. 27007path_current : 27008 if !${-is_windows} 27009 filename=${-path_tmp}gmic_pwd 27010 l[] x "pwd > "$filename it $filename autocrop {'\n'} autocrop {'" "'} u {t}/ rm onfail u "./" endl 27011 else u "./" 27012 fi 27013 27014#@cli path_gimp 27015#@cli : Return a path to store GIMP configuration files for one user (whose value is OS-dependent). 27016path_gimp : 27017 if !narg({'$_path_gimp'}) 27018 if narg({'${GIMP2_DIRECTORY}'}) _path_gimp=${GIMP2_DIRECTORY} 27019 elif narg({'${USERPROFILE}'}) _path_gimp=${USERPROFILE} 27020 elif narg({'${HOME}'}) _path_gimp=${HOME} 27021 fi 27022 if ${-is_windows} sep={`92`} else sep=/ fi 27023 if isdir(['{/$_path_gimp${sep}AppData${sep}Roaming${sep}GIMP${sep}2.10}']) 27024 _path_gimp=$_path_gimp${sep}AppData${sep}Roaming${sep}GIMP${sep}2.10${sep} 27025 elif isdir(['{/$_path_gimp${sep}AppData${sep}Roaming${sep}GIMP${sep}2.8}']) 27026 _path_gimp=$_path_gimp${sep}AppData${sep}Roaming${sep}GIMP${sep}2.8${sep} 27027 elif isdir(['{/$_path_gimp${sep}.config${sep}GIMP${sep}2.10}']) 27028 _path_gimp=$_path_gimp${sep}.config${sep}GIMP${sep}2.10${sep} 27029 elif isdir(['{/$_path_gimp${sep}.gimp-2.8}']) 27030 _path_gimp=$_path_gimp${sep}.gimp-2.8${sep} 27031 elif isdir(['{/$_path_gimp${sep}.gimp-2.6}']) 27032 _path_gimp=$_path_gimp${sep}.gimp-2.6${sep} 27033 else 27034 _path_gimp=${-path_tmp} 27035 fi 27036 fi 27037 u $_path_gimp 27038 27039#@cli path_tmp 27040#@cli : Return a path to store temporary files (whose value is OS-dependent). 27041path_tmp : 27042 if !narg({'$_path_tmp'}) 27043 if narg({'${TMP}'}) _path_tmp=${TMP} 27044 elif narg({'${TEMP}'}) _path_tmp=${TEMP} 27045 elif narg({'${TMPDIR}'}) _path_tmp=${TMPDIR} 27046 elif narg({'${HOME}'}) _path_tmp="/tmp" 27047 fi 27048 if ${-is_windows} _path_tmp=$_path_tmp{`92`} else _path_tmp=$_path_tmp/ fi 27049 fi 27050 u $_path_tmp 27051 27052#@cli remove_copymark : "image_name" 27053#@cli : Remove copy mark from names of selected images. 27054remove_copymark : 27055 u {`"name = ['$1']; 27056 i = find(name,'_c'); 27057 i>=0 && i<size(name) - 2 && (c=name[i+2])>=_'1' && c<=_'9'?( 27058 ext = ['"{$>,x}"']; 27059 size(ext)?copy(name[i],[_'.',ext,0]):(name[i]=0); 27060 ); name"`} 27061 27062# render_donations: Parse the PayPal .CSV file and generate 'latest-months' donation gfx. 27063# $1 = filename.csv 27064# $2 = number of latest months. 27065render_donations : skip "${1="$HOME"/work/src/gmic_donations/donations.csv}",${2=0} 27066 use_vt100 27067 nb_months={$2?$2:4} 27068 l[] 27069 it[] "$1" s -,{'\n'} 27070 rm[0] # Discard labels 27071 27072 # Parse CSV data. 27073 eur2usd={1/0.7988} # Change rate from EUR to USD (Paypal conversion rate). 27074 nb_entries=$! 27075 repeat $!,e l[0] 27076 27077 # Split CSV items. 27078 repeat 10 l$>= done 27079 f ">begin(iss=0);i==_'\"'?(iss=!iss;i):i==_',' && !iss?-1:i" s -,-1 autocrop {'\"'} 27080 if $!>3 f[3] "lowercase(i)" fi # currency 27081 if $!>4 replace[4-{min($!,6)}] {','},{'.'} fi # amounts 27082 repeat $! l$>={$>,t} done 27083 rm 27084 27085 # Available values. 27086 date_$e=$l0 27087 name_$e=$l1 27088 type_$e=$l2 27089 currency_$e=$l3 27090 donation_$e={$l4} 27091 charge_paypal_$e={$l5} 27092 charge_lila_$e={$l6} 27093 mail_$e=$l7 27094 message_$e=$l8 27095 27096 # Deduced values. 27097 l[] 27098 ('${date_$e}') s -,{'/'} day_$e,month_$e,year_$e={0,t},{1,t},{2,t} rm 27099 edate_$e={${day_$e}+100*(${month_$e}+100*${year_$e})} 27100 endl 27101 donation_charged_$e={${donation_$e}+${charge_paypal_$e}+${charge_lila_$e}} 27102 27103 if '${currency_$e}'=='eur' 27104 donation_eur_$e=${donation_$e} 27105 donation_charged_eur_$e=${donation_charged_$e} 27106 donation_usd_$e={${donation_$e}*$eur2usd} 27107 donation_charged_usd_$e={${donation_charged_$e}*$eur2usd} 27108 else 27109 donation_usd_$e=${donation_$e} 27110 donation_charged_usd_$e=${donation_charged_$e} 27111 donation_eur_$e={${donation_$e}/$eur2usd} 27112 donation_charged_eur_$e={${donation_charged_$e}/$eur2usd} 27113 fi 27114 27115 # Print infos. 27116 if ${donation_$e}>=15 col=$_vt100_r else col= fi 27117 e[] "- ["$_vt100_c$_vt100_b"#"$e$_vt100_n" - "$_vt100_c${date_$e}$_vt100_n"] "\ 27118 $col$_vt100_b{_${donation_$e}}" "${currency_$e}$_vt100_n\ 27119 " (paypal: "{_${charge_paypal_$e}}" "${currency_$e},\ 27120 " lila: "{_${charge_lila_$e}}" "${currency_$e}" ->"\ 27121 " "{_${donation_charged_$e}}" "${currency_$e}" ="\ 27122 " "{_${donation_charged_eur_$e}}" eur),"\ 27123 " from "${name_$e}" ("${mail_$e}") : '"$_vt100_b${message_$e}$_vt100_n"'" 27124 endl done 27125 27126 # Compute image for donations of the last months. 27127 e[] "" 27128 all_eur,all_usd,all_charged_eur,all_charged_usd,asep_eur,asep_usd= 27129 repeat $nb_months 27130 edate={y=date(0);m=date(1)-1-$>;while(m<=0,--y;m+=12);100*y+m} 27131 s_month=${"arg "$edate%100",January,February,March,April,May,June,July,August,\ 27132 September,October,November,December"} 27133 s_year={int($edate/100)} 27134 27135 month_eur,month_charged_eur,month_usd,month_charged_usd,msep_eur,msep_usd= 27136 nb_sponsors=0 27137 repeat $nb_entries,e if $edate==int(${edate_$e}/100) 27138 currency=${currency_$e} 27139 val_eur=${donation_eur_$e} 27140 val_charged_eur=${donation_charged_eur_$e} 27141 val_usd=${donation_usd_$e} 27142 val_charged_usd=${donation_charged_usd_$e} 27143 nb_sponsors+=1 27144 27145 if '${currency_$e}'=='eur' 27146 all_eur.=$asep_eur$val_eur 27147 all_charged_eur.=$asep_eur$val_charged_eur 27148 month_eur.=$msep_eur$val_eur 27149 month_charged_eur.=$msep_eur$val_charged_eur 27150 asep_eur=, msep_eur=, 27151 else 27152 all_usd.=$asep_usd$val_usd 27153 all_charged_usd.=$asep_usd$val_charged_usd 27154 month_usd.=$msep_usd$val_usd 27155 month_charged_usd.=$msep_usd$val_charged_usd 27156 asep_usd=, msep_usd=, 27157 fi 27158 fi done 27159 27160 month_sum_eur={sum(0$month_eur)+sum(0$month_usd)/$eur2usd} 27161 month_sum_charged_eur={sum(0$month_charged_eur)+sum(0$month_charged_usd)/$eur2usd} 27162 27163 e[] "* "$_vt100_c$_vt100_b$s_month" "$s_year": "$_vt100_n\ 27164 $_vt100_b{_$month_sum_eur}" eur"$_vt100_n" (charged: "{_$month_sum_charged_eur}" eur)"\ 27165 " = "{_sum(0$month_eur)}" eur"$_vt100_n" (charged: "{_sum(0$month_charged_eur)}" eur)"\ 27166 " + "{_sum(0$month_usd)}" usd (charged: "{_sum(0$month_charged_usd)}" usd)" 27167 27168 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 27169 shape_circle 24 s. x,2 s[-2,-1] y,2 27170 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] 27171 channels. 0 *.. . *. 255 a[-2,-1] c 27172 r. {[w,h]+4},1,100%,0,0,0.5,0.5 27173 sh. 100% dilate_circ. 3 b. 1 rm. 27174 27175 t. $s_month" "$s_year,0.02~,0.5~,24,0.5,0,0,0,255 27176 t. {_round($month_sum_eur)}" \37 = "{_round($month_sum_eur*$eur2usd)}" $",0.5~,0.5~,24,1,0,0,0,255 27177 t. $nb_sponsors" sponsor"${"if "$nb_sponsors"!=1 u s else u \"\" fi"},0.97~,0.5~,24,0.5,0,0,0,255 27178 done 27179 rv 27180 27181 all_max={max($all_eur,[$all_usd]/$eur2usd)} 27182 all_min={min($all_eur,[$all_usd]/$eur2usd)} 27183 all_sum_eur={sum($all_eur)} 27184 all_sum_usd={sum($all_usd)} 27185 all_sum_charged_eur={sum($all_charged_eur)} 27186 all_sum_charged_usd={sum($all_charged_usd)} 27187 all_avg={avg($all_eur,[$all_usd]/$eur2usd)} 27188 all_med={med($all_eur,[$all_usd]/$eur2usd)} 27189 27190 0 t. "Avg: "{_round($all_avg,0.1)}"\37 / "\ 27191 "Med: "{_round($all_med,0.1)}"\37 / "\ 27192 "Min: "{_round($all_min,0.1)}"\37 / "\ 27193 "Max: "{_round($all_max,0.1)}"\37",0,0,24,1,1 27194 *. 200 i[-2] 100%,100%,1,3 a[-2,-1] c 27195 27196 rows -5,100% a y,0.5 r2dx 480 27197 if $2==0 o $HOME/work/src/gmic/html/img/donations_latest_months.png fi 27198 endl 27199 27200 total_eur={$all_sum_eur+$all_sum_usd/$eur2usd} 27201 total_charged_eur={$all_sum_charged_eur+$all_sum_charged_usd/$eur2usd} 27202 e[] "\n==> "$_vt100_c${_vt100_b}"TOTAL : "$_vt100_n\ 27203 $_vt100_b{_floor($total_eur)}" eur"$_vt100_n" (charged : "{_floor($total_charged_eur)}" eur)"\ 27204 " = "{_floor($all_sum_eur)}" eur (charged: "{_floor($all_sum_charged_eur)}" eur)"\ 27205 " + "{_floor($all_sum_usd)}" usd (charged: "{_floor($all_sum_charged_usd)}" usd)\n" 27206 27207 # Generate report image for Twitter. 27208 sp gmicky,{h} 27209 l[-2,-1] 27210 rgb={I(w-1)} to_rgba rv 27211 frame 10,10,0,0,0,0 27212 drgba $rgb a x 27213 shape_heart 82 +r. 100%,100%,1,3 hsv2rgb. rv[-2,-1] *. 255 a[-2,-1] c 27214 r. ..,..,1,100%,0,0,0.23,0.15 drop_shadow. 3,3,2,0,0 27215 blend alpha,0.7 r2dx 500 27216 if $2==0 o $HOME/Desktop/donations_latest_months.jpg,85 rm return fi 27217 endl 27218 27219 # Generate coin graphics. 27220 l[] 27221 $HOME/work/src/gmic/html/img/icon_coin.png 27222 N=0 27223 text$N,r$N,g$N,b$N,file$N="2 \37",32,48,32,"don_2eur.png" N+=1 27224 text$N,r$N,g$N,b$N,file$N="5 \37",200,200,200,"don_5eur.png" N+=1 27225 text$N,r$N,g$N,b$N,file$N="10 \37",190,100,100,"don_10eur.png" N+=1 27226 text$N,r$N,g$N,b$N,file$N="+ \37",255,128,0,"don_moreeur.png" N+=1 27227 text$N,r$N,g$N,b$N,file$N="2 $",32,48,32,"don_2usd.png" N+=1 27228 text$N,r$N,g$N,b$N,file$N="5 $",200,200,200,"don_5usd.png" N+=1 27229 text$N,r$N,g$N,b$N,file$N="10 $",190,100,100,"don_10usd.png" N+=1 27230 text$N,r$N,g$N,b$N,file$N="+ $",255,128,0,"don_moreusd.png" N+=1 27231 repeat $N +l[0] 27232 frame. 10,10,0,0,0,0 27233 sh. 0,2 27234 (${r$>}^${g$>}^${b$>}) rgb2hsl[-2,-1] H,S={[R,G]} rm. 27235 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 27236 hsl2rgb. rm. 27237 sh. 100% dilate_circ. 10 rm. 27238 27239 100%,100% t. ${text$>},0.5~,0.5~,45%,1,255 dilate_circ. 10 +dilate_circ. 15 to_rgb.. a[-2,-1] c 27240 blend[-2,-1] alpha drop_shadow. 1,1 r2dx. 48 frame 10,5,0,0,0,0 27241 outfile=$HOME/work/src/gmic/html/img/${file$>} 27242 if !isfile('$outfile') o. $outfile fi 27243 rm. 27244 endl done 27245 rm[0] 27246 endl 27247 27248#@cli reset 27249#@cli : Reset global parameters of the interpreter environment. 27250reset : 27251 e[^-1] "Reset global parameters of the interpreter environment." 27252 db3d m3d md3d f3d l3d sl3d ss3d 27253 27254#@cli rgb 27255#@cli : Return a random int-valued RGB color. 27256rgb : 27257 u {round(u(255))},{round(u(255))},{round(u(255))} 27258 27259RGB : rgb 27260 27261#@cli rgba 27262#@cli : Return a random int-valued RGBA color. 27263rgba : 27264 u {round(u(255))},{round(u(255))},{round(u(255))},{round(u(255))} 27265 27266RGBA : rgba 27267 27268#@cli shell_cols 27269#@cli : Return the estimated number of columns of the current shell. 27270shell_cols : 27271 if ${-is_windows} u 80 27272 else 27273 file_rand filename=${} 27274 l[] cols=80 x "tput cols > "$filename it $filename if isint({t}) cols={{t}} fi rm onfail cols=80 rm endl 27275 delete $filename 27276 u $cols 27277 fi 27278 27279#@cli size_value 27280#@cli : Return the size (in bytes) of an image value. 27281size_value : 27282 u {str=['$_pixeltype'];echo(str);str=='float'?4:str=='double'?8:0} 27283 27284 27285#@cli std_noise 27286#@cli : Return the estimated noise standard deviation of the last selected image. 27287std_noise : 27288 if $! +laplacian. -. {ic} abs. u {1.4826*ic/sqrt(d==1?20:42)} rm. else u 0 fi 27289 27290#@cli str : string 27291#@cli : Print specified string into its binary, octal, decimal and hexadecimal representations. 27292str : skip $1 27293 dec={'$*'} 27294 e[^-1] "Convert string '$*' to binary '"${dec2bin\ $dec}"', octal '"${dec2oct\ $dec}"', decimal '"$dec"' and 27295 hexadecimal '"${dec2hex\ $dec}"'." 27296 27297#@cli str2hex : "string" 27298#@cli : Convert specified string argument into a sequence of hexadecimal values (returned as a string). 27299#@cli : See also: ''hex2str''. 27300#@cli : $ hex=${"str2hex \"Hello my friends\""} echo $hex 27301#@cli : \n~~~\n[gmic]-0./ Start G'MIC interpreter.\n[gmic]-0./ 48656c6c6f206d7920667269656e6473\n\ 27302# [gmic]-0./ End G'MIC interpreter.\n~~~\n 27303str2hex : 27304 ('"$*"') y. r. 2,100% f. 'v=if(x,i%16,int(i/16));if(v<=9,48+v,87+v)' u {t} rm. 27305 27306#@cli strcapitalize : string 27307#@cli : Capitalize specified string. 27308strcapitalize : 27309 l[] ('{/"$1"}') 27310 f "(i<=_' ' || i==_'_') && i!=_'\n'?_' ':i" # Replace blank characters and underscores 27311 f "> 27312 t(s) = ( unref(ss); const ss = size(s); lowercase(crop(x,ss))!=s || j[ss]!=_' '); 27313 !x || (p=j[-1])==_'.' || p==_':' || p==_';' || p==_'\"' || (find(#0,_' ',x)<0 && p==_' ') || 27314 (p==_' ' || p==_'-') && 27315 t('a') && t('an') && t('and') && t('as') && t('at') && t('but') && t('by') && t('for') && t('from') && 27316 t('in') && t('into') && t('like') && t('near') && t('nor') && t('of') && t('off') && t('on') && 27317 t('onto') && t('or') && t('over') && t('past') && t('per') && t('than') && t('the') && t('to') && 27318 t('up') && t('upon') && t('via') && t('with')?uppercase(i):i" 27319 u {t} rm endl 27320 27321#@cli strcontains : string1,string2 27322#@cli : Return 1 if the first string contains the second one. 27323strcontains : 27324 u {"find(['$1'],['$2'])>=0"} 27325 27326#@cli strlen : string1 27327#@cli : Return the length of specified string argument. 27328strlen : skip "${1=}" 27329 u {narg({'"$1"'})} 27330 27331#@cli strreplace : string,search,replace 27332#@cli : Search and replace substrings in an input string. 27333strreplace : skip "${3=}" 27334 if narg("$3") 27335 ls=${strlen\ "$2"} 27336 lr={${strlen\ "$3"}-1} 27337 l[] ('"$1"':y) s +,{'"$2"'} s y,-$ls 27338 repeat $! if [{$>,^}]==['"$2"'] rows[$>] 0,$lr f[$>] {'"$3"'} fi done 27339 a y u {t} rm endl 27340 else 27341 l[] ('"$1"') s -,{'"$2"'} a y u {t} rm endl 27342 fi 27343 27344#@cli strlowercase : string 27345#@cli : Return a lower-case version of the specified string. 27346strlowercase : 27347 ('"$*"') u {`lowercase([{^}])`} rm. 27348 27349#@cli struppercase : string 27350#@cli : Return an upper-case version of the specified string. 27351struppercase : 27352 ('"$*"') u {`uppercase([{^}])`} rm. 27353 27354#@cli strvar : "string" 27355#@cli : Return a simplified version of the specified string, that can be used as a variable name. 27356#@cli : (version that creates a lowercase result, no longer than 128 chars). 27357strvar : 27358 _strvar_fn="lowercase(c)" _strvar "$*" 27359 27360#@cli strcasevar : "string" 27361#@cli : Return a simplified version of the specified string, that can be used as a variable name. 27362#@cli : (version that keeps original case of specified string, no longer than 128 chars). 27363strcasevar : 27364 _strvar_fn="c" _strvar "$*" 27365 27366_strvar : 27367 l[] 27368 ('"$*"':y) f. "c = i; inrange(c,_'0',_'9') || inrange(c,_'a',_'z') || 27369 inrange(c,_'A',_'Z') || c==_'_'?"$_strvar_fn":_'_'" 27370 rows. 0,{min(h,128)-1} autocrop. {'_'} 27371 if inrange(i,_'0',_'9') i.. ('_') a[-2,-1] y fi 27372 do h={h} replace_str. "__","_" while h!=$h 27373 u {t} rm 27374 endl 27375 27376#@cli strver : _version 27377#@cli : Return the specified version number of the G'MIC interpreter, as a string. 27378#@cli : Default value: 'version=$_version'. 27379strver : skip "${1=}" 27380 if isnum("$1")" && $1>0" ver="$1" else ver=$_version noarg fi 27381 ('$ver') r. {2*w-1} f. 'if(x%2,_'.',i)' u {t} rm. 27382 27383#@cli tic 27384#@cli : Initialize tic-toc timer. 27385#@cli : Use it in conjunction with 'toc'. 27386tic : 27387 e[^-1] "Initialize timer." 27388 if !narg($_ticpos) _ticpos=0 fi _tic$_ticpos=$| _ticpos+=1 27389 27390#@cli toc 27391#@cli : Display elapsed time of the tic-toc timer since the last call to 'tic'. 27392#@cli : This command returns the elapsed time in the status value. 27393#@cli : Use it in conjunction with 'tic'. 27394toc : 27395 v=$^ _ticpos-=1 u {_$|-${_tic$_ticpos}} 27396 v 0 e[^-1] "Elapsed time: "${}" s". v $v 27397 27398#@cli to_clutname : "string" 27399#@cli : Return simplified name that can be used as a CLUT name, from specified input string. 27400to_clutname : 27401 0 nm. "$1" nm={b} rm. 27402 u {`"ss = lowercase([['"{/$nm}"'],0]); 27403 const N = 2*size(ss); 27404 sd = vectorN(); 27405 for (ps = pd = 0, ss[ps], ++ps, 27406 ss[ps]<=_' '?(sd[pd++] = _'_'): 27407 (ss[ps]==_'(' || ss[ps]==_')' || 27408 ss[ps]==_'{' || ss[ps]==_'}' || 27409 ss[ps]==_'[' || ss[ps]==_']' || 27410 ss[ps]==_'\'' || ss[ps]==_'\"')?0: 27411 (ps && ss[ps]>=_'0' && ss[ps]<=_'9' && ss[ps-1]>=_'a' && ss[ps-1]<=_'z')?(sd[pd++] = _'_'; sd[pd++] = ss[ps]): 27412 (sd[pd++] = ss[ps]); 27413 ); sd[pd] = 0; sd"`} 27414 27415#@cli uchar2base64 : _encoding={ 0=base64 | 1=base64url } 27416#@cli : Encode the values of the latest of the selected images as a base64-encoded string. 27417#@cli : The string can be decoded using command 'base642uchar'. 27418#@cli : Selected images must have values that are integers in [0,255]. 27419#@cli : Default values: 'encoding=0'. 27420uchar2base64 : skip "${1=0}" 27421 if isnum("$1") encoding=$1 else encoding=0 noarg fi 27422 {ceil(whds*4/3)+([0,2,1])[whds%3]} 27423 eval " 27424 hash = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 27425 "$encoding"?(hash[62] = _'-'; hash[63] = _'_'); 27426 od = ov = n = 0; 27427 for (os = 0, os<whds#-2, 27428 v = i[#-2,os++]&255; 27429 n==0?(i[#-1,od++] = hash[v>>2]; ov = v; n = 1): 27430 n==1?(i[#-1,od++] = hash[((ov&3)<<4) | (v>>4)]; ov = v; n = 2): 27431 (i[#-1,od++] = hash[((ov&15)<<2) | (v>>6)]; i[#-1,od++] = hash[v&63]; n = 0); 27432 ); 27433 n==1?(i[#-1,od++] = hash[((ov&3)<<4)]; copy(i[#-1,od],_'=',2,1,0); od+=2): 27434 n==2?(i[#-1,od++] = hash[((ov&15)<<2)]; i[#-1,od++] = _'='); 27435 " 27436 u {t} rm. 27437 27438#------------------------------------- 27439# 27440#@cli :: Other Interactive Commands 27441# 27442#------------------------------------- 27443 27444#@cli demos : _run_in_parallel={ 0=no | 1=yes | 2=auto } 27445#@cli : Show a menu to select and view all G'MIC interactive demos. 27446demos : check "isint(${1=2}) && $1>=0 && $1<=2" check_display $0 27447 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 27448 strver=${-strver} 27449 if $_prerelease strver=${strver}_pre#$_prerelease fi 27450 e[] "\n 27451------ "${g}"G\47MIC demos"$n" ------------------\n 27452----\n 27453---- "${c}"Mouse button"$n" to select a demo.\n 27454---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 27455---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 27456---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 27457----\n 27458-------------------------------------" 27459 l[] 27460 entries="2048 game","Blobs Editor","Bouncing Balls","Connect Four","Fire Effect","Fireworks","Fish-Eye Effect",\ 27461 "Fourier Filtering","Tower of Hano\357","Histogram Demo","Hough Transform","Jawbreaker","Virtual Landscape",\ 27462 "The Game of Life","Light Effect","Mandelbrot Explorer","3D Metaballs","Minesweeper","Minimal Path",\ 27463 "Pacman","Paint","Plasma Effect","RGB Quantization","3D Reflection","3D Rubber Object","Shade Bobs",\ 27464 "Spline Editor","3D Starfield","Tetris","Tic-Tac-Toe","Image Waves","Fractal Whirls","Color Curves" 27465 commands=x_2048,x_blobs,x_bouncing,x_connect4,x_fire,x_fireworks,x_fisheye,\ 27466 x_fourier,x_hanoi,x_histogram,x_hough,x_jawbreaker,x_landscape,x_life,\ 27467 x_light,x_mandelbrot,x_metaballs3d,x_minesweeper,x_minimal_path,x_pacman,x_paint,\ 27468 x_plasma,x_quantize_rgb,x_reflection3d,x_rubber3d,x_shadebobs,x_spline,x_starfield3d,\ 27469 x_tetris,x_tictactoe,x_waves,x_whirl,_demo_color_curves 27470 nb_entries={narg($entries)} 27471 parallel_mode={1-if($1!=2,$1,$_cpus>=2)} 27472 strver=${-strver} 27473 if $_prerelease strver.=_pre#$_prerelease fi 27474 27475 # Generate menu graphics. 27476 l[] 27477 repeat $nb_entries 27478 arg 1+$>,$entries entry=${} 27479 0 t. $entry,0,0,24,1,1 27480 done 27481 r ${-max_wh},1,1,0,0,0.5,0.5 27482 frame 12,6,0 a z 27483 +n[0] 0,255 27484 +shift[0] 1,3,0,0 max[0,-1] 27485 +f[0] z+1 27486 1,1,100%,3,u(128,255) r. 1,[0],[0],3 *. 'y/(h-1)' r. [0],[0],[0],3,3 27487 27488 100%,100%,1,1,"x = min(x,w-1-x); y = min(y,h-1-y); (x*y/wh)^0.7>0.01" 27489 +dilate. 3 xor.. . 27490 +[0] .. 27491 *.. 100 +[1,-2] 27492 *[2,3] . 27493 rm. 27494 frame 4,4,0 27495 a c s z 27496 append_tiles 3 s c 27497 to_rgb[1] a[3-5] c 27498 27499 0 t. "G\'MIC demos",2,2,32,1,1,1,1 27500 if $_prerelease 0 t. "Version:\n"$strver,40,1,18,1,1,1,1 rows. 2,100% 27501 else 0 t. "Version: "$strver,40,1,18,1,1,1,1 rows. -2,100% 27502 fi 27503 a[-2,-1] x,0.5 27504 b. 0.5 n. 0,1 27505 (32;255^255;255^0;0) r. ..,..,1,3,3 *[-2,-1] round. 1,-1 +!=. 0 channels. 1 27506 27507 s=8 27508 r[^-2,-1] 100%,{h+h#0+2*$s+6},1,100%,0,0,0,1 27509 rectangle[0] 0,$s,100%,{$s+6+h-1},1,0.6 27510 rectangle[1] 0,$s,100%,{$s+6+h-1},1,120,120,32 27511 j[0] .,{(w#0-w)/2},{$s+3},0,0,-1 27512 j[1] ..,{(w#0-w)/2},{$s+3},0,0,1,. rm[-2,-1] 27513 c[0] 0,1 27514 nm menu_opac,menu_fgcol,menu_ind,menu_bgcol 27515 endl 27516 27517 # Generate 3D cursors. 27518 arrow3d 20,20,0,0,0,0,20%,40%,40% col3d. 255,128,0 nm. cursor3d 27519 27520 # Generate 3D background object. 27521 l[] 27522 n=16 27523 chromeball64x64[] 200,100,64 n. 0,230 s. c,-3 27524 rgb2hsv.. r.. 100%,100%,$n,3 f.. "[z*360/d,G,B]" hsv2rgb.. 27525 N={6*$n} P={2*$N-1} 27526 i[0] ('CImg3d') i[1] ($N,$P) i[2] 3,$N # Header, points 27527 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 27528 l[4] # Colors 27529 s z i[0--2] (-128,{w},{h},3) 4,{$N-$n},1,1,'x==0?-128:x==1?y%$n:0' # Colors 27530 3,{$P-$N},1,1,200 y a y 27531 endl 27532 l[5] # Opacities 27533 n 0,0.5 i[0] (-128,{w},{h},1) 4,{$N-1},1,1,-128,0,0,0 27534 1,{$P-$N},1,1,0.25 y a y 27535 endl 27536 y a y 27537 nm background3d 27538 endl 27539 27540 # Generate background. 27541 {menu_fgcol,[w,h]},1,3 +plasma. 1,1,5 n. 0,230 water. 100 27542 (0.1;0.03^0;0.1^0.2;0.1) ri. ..,3 *[-2,-1] 27543 (0;1) r. ..,..,1,1,3 pow. 1.5 n. 0.2,1.15 *[-2,-1] n. 0,128 27544 nm. background 27545 w. -1,-1,0,"[G'MIC - "$strver"]" cursor 0 w[] -1,-1,0,0,{([{*,u,v}]-[{*,w,h}])/2} 27546 27547 # Enter event loop. 27548 omb,ind_clicked,cfx,cfy,cfz,alpha=0 27549 nfx,nfy,nfz={[g,g,g]} time0={$|-4} 27550 do 27551 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}]} 27552 ind={menu_ind,i($mx,$my)} 27553 if $mb" && "!$ind_clicked ind_clicked=$ind fi 27554 27555 # Render current view. 27556 [background] 27557 27558 3,$N,1,1,"const t = 0.8*"$|"; const a = "$alpha"; const oma = 1 - a; 27559 x==0?oma*cos("$cfx"*y + t) + a*cos("$nfx"*y + t): 27560 x==1?oma*sin("$cfy"*y + t) + a*sin("$nfy"*y + t): 27561 oma*sin("$cfz"*y + t) + a*sin("$nfz"*y + t)" 27562 y. 27563 j[background3d] .,0,8 rm. 27564 +r3d[background3d] 1,2,3,{20*$|} *3d. {menu_fgcol,[w,h]/2-30},300 +3d. 0,0,300 27565 j3d.. .,50%,50%,0,1,1,0,0,200 rm. 27566 if $|-$time0>5 alpha+=0.02 fi 27567 if $alpha>1 alpha-=1 cfx,cfy,cfz=$nfx,$nfy,$nfz nfx,nfy,nfz={[g,g,g]} time0={$|-u*3} fi 27568 27569 if $ind>0 +==[menu_ind] # Draw selection background 27570 $ind j.. [menu_bgcol],0,0,0,0,{$mb" && "$ind_clicked==$ind?0.6:1},. rm. 27571 fi 27572 j. [menu_fgcol],0,0,0,0,1,[menu_opac] 27573 27574 if $mx>0 27575 +r3d[cursor3d] 1,1.3,0.6,{50*cos($|)} 27576 j3d.. .,$mx,$my,0,1,4,0,0,800,{-2,[w,h]/2},-1000,0.7 rm. 27577 fi 27578 27579 w. -1,-1,0 27580 if {*,CTRLLEFT}" && "{*,D} w. 150%,150% elif {*,CTRLLEFT}" && "{*,C} w. 100%,100% fi 27581 rm. 27582 27583 # Manage user selection. 27584 if !$mb" && "$omb" && "$ind_clicked" && "$ind_clicked==$ind 27585 m "com : v 1 "${arg\ $ind,$commands} parallel $parallel_mode,"l[] com rm endl" um com 27586 elif !$mb ind_clicked=0 27587 fi 27588 omb=$mb 27589 27590 wait 20 27591 while {*}" && "!{*,ESC}" && "!{*,Q} 27592 rm w 0 endl v 0 e[] "" 27593 27594_demo_color_curves : 27595 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 27596 if !narg($__demo_color_curve) 27597 e[] "\n 27598------ "${g}"Color curves"$n" ----------------------------------------------------------------------------\n 27599----\n 27600---- "${c}"Left mouse button"$n" on a curve creates a new control point (or moves an existing one).\n 27601---- "${c}"Right mouse button"$n" on a control point deletes it.\n 27602---- "${c}"Left mouse button"$n" on the main image window shows the initial image until button is released.\n 27603---- "${c}"Right mouse button"$n" on the main image window adds a keypoint to all curves from picked color.\n 27604---- Key '"${c}"R"$n"' on a curve resets it.\n 27605---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 27606---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 27607---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 27608---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' close the current window.\n 27609----\n 27610------------------------------------------------------------------------------------------------" 27611 __demo_color_curve=1 l[] do rm sp ? while s!=3 endl x_color_curves rgb __demo_color_curve= 27612 else 27613 e[] "\n 27614------ "${g}"Color curves"$n" ----------------------------------------------------------------------------\n 27615----\n 27616---- Only "${c}"one session"$n" allowed at the same time !\n 27617----\n 27618------------------------------------------------------------------------------------------------" 27619 fi 27620 27621#@cli tixy : "expression" 27622#@cli : Animate specified mathematical expression with a 16x16 grid of circles, \ 27623# using the rules described at <https://tixy.land>. 27624tixy : skip "${1=sin(t-sqrt((x-8)^2+(y-8)^2))}" check_display $0 27625 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r b=$_vt100_b 27626 if narg("$*") expr="$*" else expr="$1" fi 27627 l[] ('$expr') 27628 replace_str "%","%25" 27629 replace_str "&","%26" 27630 replace_str "(","%28" 27631 replace_str ")","%29" 27632 replace_str "+","%2B" 27633 replace_str ",","%2C" 27634 replace_str ";","%2C" 27635 replace_str "/","%2F" 27636 replace_str "[","%5B" 27637 replace_str "]","%5D" 27638 replace_str "|","%7C" 27639 replace_str "^","**" 27640 replace_str " ","+" 27641 url=https://tixy.land?code={t} 27642 rm endl 27643 27644 e[] "\n 27645------ "${g}"tixy"$n" ------------------------------------------------------------------------------------\n 27646----\n 27647---- tixy - creative code golfing: "${g}"https://tixy.land"$n"\n 27648----\n 27649---- "$r${b}"Expression:"$n" "$expr"\n 27650----\n 27651---- "$r${b}"Corresponding URL:"$n" "$url"\n 27652----\n 27653---- "$r${b}"Rules:"$n"\n 27654---- . Specified expression depends on 4 variables "${g}"(t,i,x,y)"$n" and is rendered as an animation.\n 27655---- . Variables "${g}"x"$n" and "${g}"y"$n", in range "${c}"[0,15]"$n", are the spatial position of each dot.\n 27656---- . Variable "${g}"i"$n", in range "${c}"[0,255]"$n", is the dot index, i.e. "${c}"i = x + 16*y"$n".\n 27657---- . Variable "${g}"t>=0"$n" is the (decimal) number of elapsed seconds.\n 27658---- . Specified expression "${g}"func(t,i,x,y)"$n" must return a complex value "${c}"c"$n".\n 27659---- . Variable "${g}"z"$n" can be used as a shortcut for "${g}"[ x,y ]"$n".\n 27660---- . Variable "${g}"j"$n" is the complex imaginary number "${g}"[ 0,1 ]"$n".\n 27661---- . "${c}"cabs(c)"$n" in "${g}"[0,1]"$n" determines the radius of each dot at "${c}"(x,y)"$n".\n 27662---- . "${c}"carg(c)"$n" in "${g}"[-pi,pi]"$n" determine the color of each dot at "${c}"(x,y)"$n".\n 27663----\n 27664---- Key '"${c}"SPACE"$n"' starts/stops recording animation as video file '"${c}"out.mp4"$n"'.\n 27665---- Key '"${c}"ENTER"$n"' takes a screenshot of current image.\n 27666---- Key '"${c}"A"$n"' enables/disables anti-aliasing.\n 27667---- Key '"${c}"F"$n"' displays formula on the image.\n 27668---- Key '"${c}"R"$n"' resets time.\n 27669---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 27670---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 27671---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 27672---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' close the current window.\n 27673------------------------------------------------------------------------------------------------" 27674 w[] 400,400,0,"[G'MIC] tixy: "$expr 27675 t0=$| is_recording=0 is_antialias=1 is_screenshot=0 is_formula=0 nb_frames=0 27676 360,1,1,3,[x,abs(cos(x/w*pi))^0.5,1] hsv2rgb. shift. -180,0,0,0,2 nm. cmap 27677 strvar $expr basename=${} 27678 27679 do 27680 27681 # Manage user-events. 27682 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 27683 if $is_ctrl" && "{*,-D} w[] {1.25*[{*,w,h}]} rmn formula,mformula 27684 elif $is_ctrl" && "{*,-C} w[] {0.8*[{*,w,h}]} rmn formula,mformula 27685 elif $is_ctrl" && "{*,R} w[] 400,400 rmn formula,mformula 27686 elif {*,-A} is_antialias={!$is_antialias} 27687 elif {*,-F} is_formula={!$is_formula} 27688 elif {*,R} t0=$| 27689 elif {*,-SPACE} 27690 if $is_recording o[] $basename.mp4,15,0,0 nb_frames=0 27691 else t0=$| fi 27692 is_recording={!$is_recording} 27693 elif {*,-ENTER} is_screenshot=1 27694 fi 27695 27696 # Render animation frame. 27697 m={min({*,w,h})} _is_antialias={$is_antialias" && "$m<512} 27698 {m=$m*($_is_antialias?2:1);[m,m]},1,3 27699 27700 16,16,1,1,">begin( 27701 const b = w#-1/16; 27702 const t = "$|-$t0"; 27703 j = [ 0,1 ]; 27704 ); 27705 i = x + 16*y; 27706 ref([ x,y ],z); 27707 val = ("$expr"); 27708 n = cabs(val); 27709 r = floor(0.48*b*cut(n,0,1)); 27710 a = (360+carg(val)*180/pi)%360; 27711 c = I[#"$cmap",a]; 27712 r>1?ellipse(#-1,b*(x + 0.5),b*(y + 0.5),r,r,0,1,c): 27713 r>0?ellipse(#-1,b*(x + 0.5),b*(y + 0.5),1,1,0,0.5,c)" 27714 rm. 27715 27716 if $_is_antialias r. 50%,50%,1,3,2 fi 27717 if {*,w}!={*,h} -. 128 r. {*,w,h},1,3,0,0,0.5,0.5 +. 128 fi 27718 if $is_formula 27719 if !narg($formula) 27720 0 t. {``$expr},0,0,48,1,255 frame. 5,5,0 +dilate. 11 max. 128 to_rgb.. 27721 if w>0.75*{*,w} r2dx[-2,-1] {0.75*{*,w}} fi 27722 mv[-2,-1] 0 nm[0,1] formula,mformula 27723 fi 27724 j. [formula],0.5~,1~,0,0,1,[mformula],255 27725 fi 27726 if $is_screenshot o. $basename.png is_screenshot=0 fi 27727 if $is_recording o. $basename.mp4,15,0,1 nb_frames+=1 to. "Recording video\n[Frame \#"$nb_frames"]",0,0,5% fi 27728 w. rm. wait 40 27729 while {*}" && "!{*,ESC}" && "!{*,Q} 27730 rmn cmap,formula,mformula 27731 w[] 0 27732 27733#@cli x_2048 27734#@cli : Launch the 2048 game. 27735x_2048 : check_display $0 27736 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 27737 e[] "\n 27738------ "${g}"2048"$n" -----------------------------------------------\n 27739----\n 27740---- Join the numbers and get to the "${g}"2048"$n" tile!\n 27741----\n 27742---- Use your "${c}"arrow keys"$n" to move the tiles. When two tiles\n 27743---- with the same number touch, they merge into one!\n 27744---- This command is a port of the '"${c}"2048"$n"' game originally\n 27745---- designed by "${c}"Gabriele Cirulli"$n", and available at:\n 27746---- "${g}"http://gabrielecirulli.github.io/2048/"$n"\n 27747----\n 27748---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 27749----\n 27750--------------------------------------------------------------" 27751 l[] 27752 score=0 f3d 50 m3d 0 27753 m "_x_2048_setrandom : +==[0] 0 f. 'if(i,4*y+x,-1)' discard. -1 27754 off={i[round(u(h-1))]} rm. x={$off&3} y={$off>>2} n={if(u<0.75,1,2)} 27755 =[0] $n,$x,$y [{2+$n}] c3d. 27756 repeat 6 j3d[1] .,{78+$x*121},{190+$y*121},{10*$<},{(1+$>)/6} w[1] wait 20 done 27757 rm." 27758 m "_x_2048_object3d : +f[0] 'if(i,i*16+4*y+x,-1)' discard. -1 27759 N={h} repeat h v={-{1+$>},@$>} ++3d[{2+($v>>4)}] {$v&3},{($v>>2)&3} done 27760 +3d[-$N--1] rm.." 27761 i[0] 4,4 27762 27763 # Pre-render game canvas and numbered titles. 27764 b0=204,192,179 b1=238,228,218 b2=237,224,200 b3=242,177,121 27765 b4=245,149,99 b5=246,124,95 b6=246,94,59 b7=237,207,114 27766 c0=119,110,101 c1=249,246,242 s0=" " 27767 520,630,1,3 fc. 250,248,239 27768 t. "2048",20,10,86,1,$c0 27769 t. "Join the numbers and get to the 2048 tile!",20,90,20,1,$c0 27770 rectangle. 422,20,501,75,1,187,173,160 t. "SCORE",439,25,15,1,238,228,218 27771 repeat 12 27772 107,107,1,3 fc. ${b{min($>,7)}} +fc. ${c{$>>2}} 27773 s1={2^$>} 0 t. ${s{$>>0}},0,0,52,1,1 27774 r. ..,..,1,1,0,0,0.5,0.5 dilate_circ. 3 b. 0.5 27775 j... ..,0,0,0,0,1,.,1 rm[-2,-1] 27776 done 27777 frame_round[2--1] 10,5,1,0.5,187,173,160 frame[2--1] 7,7,187,173,160 to_rgb[2--1] 27778 r[2] 400%,400%,1,3,0,2 j[1] [2],18,130 27779 sprite3d[3--1] 27780 27781 # Run game. 27782 w[1] 100%,100%,0,"[G"{`39`}"MIC] 2048" insert_new=1 27783 repeat 2 _x_2048_setrandom done 27784 do 27785 27786 # Render game graphics at current iteration. 27787 if $insert_new 27788 _x_2048_object3d *3d. 121 j[1] [2],18,130 j3d[1] .,78,190 rm. 27789 80,25,1,3 fc. $c1 0 t. $score,0,0,25,1,1,1,1 ri. ..,0,0,0.5,0.8 27790 rectangle[1] 422,45,501,69,1,187,173,160 j[1] ..,422,45,0,0,1,. rm[-2,-1] 27791 w[1] insert_new=0 27792 fi 27793 27794 # Check for the end of the game. 27795 ++[0] 1 f. 'j(-1)==i||j(1)==i||j(0,-1)==i||j(1,0)==i||i==1' 27796 if {0,iM==11} # Game won. 27797 alert "Game Over","\nCongratulations! You got the 2048 title!\n\n Your score: "$score,"OK" 27798 break 27799 elif !iM # Game lost. 27800 alert "Game Over","\nBad luck! You lost the game!\n\n Your score: "$score,"OK" 27801 break 27802 fi 27803 rm. 27804 27805 # Manage user events. 27806 wait 27807 is_shift=0 um shift2048,ishift2048,vshift2048 27808 if {*,ARROWLEFT} 27809 m "shift2048:" m "ishift2048:" m "vshift2048:" 27810 is_shift=1 27811 elif {*,ARROWRIGHT} 27812 m "shift2048: rotate 180" m "ishift2048: rotate 180" 27813 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" 27814 is_shift=1 27815 elif {*,ARROWUP} 27816 m "shift2048: rotate -90" m "ishift2048: rotate 90" 27817 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" 27818 is_shift=1 27819 elif {*,ARROWDOWN} 27820 m "shift2048: rotate 90" m "ishift2048: rotate -90" 27821 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" 27822 is_shift=1 27823 fi 27824 if {*,r} w[1] 100%,100% fi 27825 27826 # Manage tile shifts and fusions. 27827 if $is_shift 27828 wait -1 27829 shift2048[0] 27830 repeat 2 27831 27832 # Tile shifts. 27833 _x_2048_object3d 27834 +s[0] y discard[-4--1] 0 y[-4--1] x r[-4--1] 4,1,1,1,0,0 a[-4--1] y 27835 +==[0,-1] insert_new={$insert_new||!im} rm. 27836 +f[0,-1] 'if(i,x,-1)' discard[-2,-1] -1 rv[-2,-1] -[-2,-1] rv[0,-2] rm.. 27837 27838 if (im||iM)&&!{*,k} # Render animation for shift. 27839 /. 5 z. 0,2 y. 27840 repeat 5 27841 j.. .,0,8,0,0,-1 27842 j[1] [2],18,130 +vshift2048.. *3d. 121 j3d[1] .,78,190 rm. 27843 w[1] wait 20 27844 done 27845 fi 27846 rm[-2,-1] 27847 27848 # Tile fusions. 27849 if !$> dscore=0 27850 [0] +f[0] 'if(i,i*16+4*y+x,-1)' discard. -1 27851 repeat h 27852 x={i[$>]&3} y={(i[$>]>>2)&3} n={i[$>]>>4} 27853 if $x>0" && "{0,i($x-1,$y)}==$n 27854 =[0] 0,$x,$y =[0] {$n+1},{$x-1},$y =.. 0,$x,$y insert_new=1 dscore+={2^($n+1)} 27855 else =. -1,0,$> 27856 fi 27857 done 27858 score+=$dscore 27859 27860 if iM<0 rm[-2,-1] 27861 else # At least one tile fusions. 27862 discard. -1 27863 rv[0,-2] _x_2048_object3d rv[0,-3] vshift2048. *3d. 121 # Only tiles that do not move in this step. 27864 j[1] [2],18,130 j3d[1] .,78,190 rm[-3,-1] 27865 N={h} repeat h v={-{1+$>},@$>} ++3d[{2+($v>>4)}] {$v&3},{($v>>2)&3} done # Only tiles that move. 27866 +3d[-$N--1] rm.. 27867 0 t. +$dscore,0,0,33,1,1 100%,100%,1,3 fc. $c0 27868 repeat 6 # Render animation for fusion. 27869 +vshift2048... *3d. 121 +j3d[1] .,78,190 27870 j. ...,440,{40-3*$>},0,0,{min(1,$</3)},[-4] 27871 w. rm[-2,-1] -3d... {1/6},0,0 wait 20 27872 done 27873 rm[-3--1] 27874 fi 27875 27876 fi 27877 done 27878 ishift2048[0] 27879 27880 # Insert new tile. 27881 if $insert_new _x_2048_setrandom fi 27882 fi 27883 27884 while {*}" && "!{*,ESC}" && "!{*,Q} 27885 rm w 0 endl um _x_2048_setrandom,_x_2048_object3d 27886 27887#@cli x_blobs 27888#@cli : Launch the blobs editor. 27889#@cli : ![x_blobs](../img/x_blobs.jpg) 27890x_blobs : check_display $0 27891 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 27892 e[] "\n 27893------ "${g}"Blobs editor"$n" --------------------------\n 27894----\n 27895---- "${c}"Mouse"$n" to insert/move/delete blobs.\n 27896---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 27897---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 27898---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 27899----\n 27900-----------------------------------------------------" 27901 27902 # Create background image [0]. 27903 l[] (0;0^0;128^0;255) r. 450,450,1,3,3 flower. 30,8,0,0,50%,50%,1 water. 20 27904 w {f=h<0.5*{*,v}?1.5:1;[w,h]*=f},0,0,"[G"{`39`}"MIC] Blobs Editor" 27905 27906 # Start event loop. 27907 moving=-1 27908 do 27909 x={{*,x}*{0,w}/{*,w}} 27910 y={{*,y}*{0,h}/{*,h}} 27911 b={*,b} nearest=-1 27912 fps=${-fps} 27913 27914 # Render image of blobs and find nearest blob to mouse pointer. 27915 if $!>1 27916 {0,[w,h]},1,2 27917 repeat h#1 27918 r={1,i[2]*(1+i[3]*cos(i[4]+i[5]*$|*1000))} 27919 ellipse. {1,@0,1},$r,$r,0,1,{1,@6-7} 27920 d={sqrt(($x-{1,@0})^2+($y-{1,@1})^2)} 27921 if $d<$r nearest=$> fi 27922 shift[1] 0,-1,0,0,2 done 27923 b. 15 27924 +norm. +>=. 50 <=.. 40 *[-3,-1] 27925 +*[0,-1] rm.. rv[-2,-1] *. 1.6 c. 0,255 +[-2,-1] 27926 if $fps>0 to. $fps" fps",5,{h-29},24,2,0.2 fi 27927 w. 27928 if {*,CTRLLEFT}" && "{*,D} w[] {2*[w,h]} elif {*,CTRLLEFT}" && "{*,C} w[] {[w,h]} fi 27929 rm. 27930 else 27931 +to[0] "G\47MIC Blobs Editor",75,100,35,3,1,200,128,255 27932 to. "* Left mouse button : Create and move blobs.\n\n\ 27933 * Right mouse button : Remove blob.\n\n\ 27934 * Middle mouse button : Remove all blobs.\n\n\ 27935 * Key 'ESC' or 'Q' : Quit.\n\n\ 27936 * Colors and sizes of appearing blobs are\n chosen randomly",\ 27937 50,180,18,1,1,255 27938 w. 27939 if {*,CTRLLEFT}" && "{*,D} w[] {1.5*[w,h]} elif {*,CTRLLEFT}" && "{*,C} w[] {[w,h]} fi 27940 rm. 27941 fi 27942 wait 20 27943 27944 # Manage blob insertion, removal or move. 27945 if $x<0||$y<0 continue fi 27946 if $b&1 27947 if $nearest>=0" || "$moving>=0 # Move existing blob. 27948 if $moving<0 moving=$nearest fi 27949 =[1] $x,0,$moving =[1] $y,1,$moving 27950 else # Insert new blob. 27951 ($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 27952 moving={h-1} 27953 fi 27954 elif $b&2 # Remove existing blob. 27955 if $nearest>=0 l[1] s y rm[$nearest] a y endl nearest=-1 fi 27956 elif $b&4 # Remove all blobs. 27957 k[0] 27958 else 27959 moving=-1 27960 fi 27961 27962 while {*}" && "!{*,ESC}" && "!{*,Q} 27963 rm w 0 endl 27964 27965#@cli x_bouncing 27966#@cli : Launch the bouncing balls demo. 27967x_bouncing : check_display $0 27968 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 27969 e[] "\n 27970------ "${g}"Bouncing balls"$n" ------------------------------\n 27971----\n 27972---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 27973---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 27974---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 27975----\n 27976-----------------------------------------------------" 27977 l[] 27978 520,320,1,3 plasma 1,1,9 n 0,220 27979 N=12 27980 repeat $N 27981 ball[] {round(u(32,80))},${-rgb} 27982 t$>={u(200)} x$>={0,u(10,w-10)} h$>={u(150,300)} vx$>={if(u<0.5,1,-1)*u(1,8)} 27983 done 27984 mv[0] $! 27985 w. {f=w<0.5*{*,u}?1.5:1;[w,h]*=f},0,"[G"{`39`}"MIC] Bouncing Balls" 27986 (0;0.7;1) r. {-2,w},70,1,1,3 27987 27988 do 27989 [$N] 27990 repeat $N 27991 bw={$>,w} bh={$>,h} 27992 y={${h$>}*abs(cos(${t$>}*pi/60))-$bh/2} 27993 dt=1 27994 if $y<0 d={-$y} y=0 bh-=$d bw+=$d dt={max(0.2,1-($d/$bh)^2)} else dt=1 fi 27995 if ${x$>}+$bw/2>w 27996 d={${x$>}+$bw/2-w} bw-=$d bh+={0.5*$d} 27997 if ${x$>}+$bw/4>w vx$>={-${vx$>}} fi 27998 fi 27999 if ${x$>}-$bw/2<0 28000 d={$bw/2-${x$>}} bw-=$d bh+={0.5*$d} 28001 if ${x$>}-$bw/4<0 vx$>={-${vx$>}} fi 28002 fi 28003 +r[$>] $bw,$bh,1,4,3 s. c,-3 28004 j... ..,{max(0,min({$N,w-$bw},${x$>}-$bw/2))},{{$N,h}-{h}-$y-70},0,0,1,.,255 rm[-2,-1] 28005 t$>+=$dt 28006 x$>+={$dt*${vx$>}} 28007 done 28008 28009 +rows. {h-2*70},{h-1-70} mirror. y *. [{$N+1}] 28010 j.. .,0,{-2,h-71},0,0,0.5 rm. 28011 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-29},24,2,0.2 fi 28012 if {*,CTRLLEFT}" && "{*,D} w[] {1.5*w},{1.5*h} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 28013 w. rm. wait 20 28014 while {*}" && "!{*,ESC}" && "!{*,Q} 28015 w 0 rm endl 28016 28017#@cli x_color_curves : _colorspace={ rgb | cmy | cmyk | hsi | hsl | hsv | lab | lch | ycbcr | last } 28018#@cli : Apply color curves on selected RGB[A] images, using an interactive window. 28019#@cli : Set 'colorspace' to 'last' to apply last defined color curves without opening interactive windows. 28020#@cli : Default value: 'colorspace=rgb'. 28021x_color_curves : skip ${1=rgb} 28022 if ['"$1"']!='last'&&!{*,u} error[0--3] "Command '$0': No display available." return fi 28023 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 28024 e[^-1] "Apply color curves of image$?, in the '$1' colorspace." 28025 if ['"$1"']=='last' 28026 if !narg($_xcc_colorbase) return fi 28027 __x_color_curves[] $_xcc_colorbase 28028 else 28029 e[] "\n 28030------------------------------------------------------------------------------------------------\n 28031----\n 28032---- "${c}"Left mouse button"$n" on a curve creates a new control point (or moves an existing one).\n 28033---- "${c}"Right mouse button"$n" on a control point deletes it.\n 28034---- "${c}"Left mouse button"$n" on the main image window shows the initial image until button is released.\n 28035---- "${c}"Right mouse button"$n" on the main image window adds a keypoint to all curves from picked color.\n 28036---- Key '"${c}"R"$n"' on a curve resets it.\n 28037---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 28038---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 28039---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 28040---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' close the current window.\n 28041----\n 28042------------------------------------------------------------------------------------------------" 28043 __x_color_curves[] $1 _xcc_colorbase=$1 28044 fi 28045 28046 to_color repeat $! l[$>] 28047 28048 if ['"$1"']!='last' # Open interactive windows to set color curves. 28049 +r[0] ${fitscreen[]\ {0,[w,h,1]},128,70%},1,100%,3 28050 +l. # Compute additional info for each image channel (histogram and color axis). 28051 xcc_goto s c histogram 256,0,255 xcc_info 28052 endl 28053 __C0= __C1= __C2= __C3= __C4= 28054 if narg($__xcc_C0) __C0=$__xcc_C0 fi 28055 if narg($__xcc_C1) __C1=$__xcc_C1 fi 28056 if narg($__xcc_C2) __C2=$__xcc_C2 fi 28057 if narg($__xcc_C3) __C3=$__xcc_C3 fi 28058 if narg($__xcc_C4) __C4=$__xcc_C4 fi 28059 28060 x={1,({*,u}-560-w)/2} y={1,({*,v}-h)/2} 28061 if $!==5 # 3 channels. 28062 parallel "w[] 256,256,0,0,"$x","$y",\"Curve: "$_title0"\" x_select_function1d... __C0,"$_color0"",\ 28063 "w[] 256,256,0,0,"{$x+280}","$y",\"Curve: "$_title1"\" x_select_function1d.. __C1,"$_color1"",\ 28064 "w[] 256,256,0,0,"$x","{$y+300}",\"Curve: "$_title2"\" x_select_function1d. __C2,"$_color2"",\ 28065 "w. 100%,100%,0,0,"{$x+560}","$y" _x_color_curves[-4]" 28066 elif $!==6 # 4 channels. 28067 parallel "w[] 256,256,0,0,"$x","$y",\"Curve: "$_title0"\" x_select_function1d[-4] __C0,"$_color0"",\ 28068 "w[] 256,256,0,0,"{$x+280}","$y",\"Curve: "$_title1"\" x_select_function1d... __C1,"$_color1"",\ 28069 "w[] 256,256,0,0,"$x","{$y+300}",\"Curve: "$_title2"\" x_select_function1d.. __C2,"$_color2"",\ 28070 "w[] 256,256,0,0,"{$x+280}","{$y+300}",\"Curve: "$_title3"\" x_select_function1d. __C3,"$_color3"",\ 28071 "w. 100%,100%,0,0,"{$x+560}","$y" _x_color_curves[-5]" 28072 elif $!==7 # 5 channels. 28073 parallel "w[] 256,256,0,0,"$x","$y",\"Curve: "$_title0"\" x_select_function1d[-5] __C0,"$_color0"",\ 28074 "w[] 256,256,0,0,"{$x+280}","$y",\"Curve: "$_title1"\" x_select_function1d[-4] __C1,"$_color1"",\ 28075 "w[] 256,256,0,0,"$x","{$y+300}",\"Curve: "$_title2"\" x_select_function1d... __C2,"$_color2"",\ 28076 "w[] 256,256,0,0,"{$x+280}","{$y+300}",\"Curve: "$_title3"\" x_select_function1d.. __C3,"$_color3"",\ 28077 "w[] 256,256,0,0,"{$x+280}","{$y+600}",\"Curve: "$_title4"\" x_select_function1d. __C4,"$_color4"",\ 28078 "w. 100%,100%,0,0,"{$x+560}","$y" _x_color_curves[-6]" 28079 fi 28080 k[0] 28081 fi 28082 28083 # Apply color curves on fullres image. 28084 xcc_goto 28085 repeat s function1d[] 1,${__xcc_C$>} *. {255%} r. 256,1,1,1,5 c. 0,255 sh[0] $> map. .. rm[-2,-1] done 28086 xcc_backto 28087 28088 endl done 28089 um xcc_goto,xcc_backto,xcc_info 28090 28091_x_color_curves : 28092 title={0,b} if narg({'{0,x}'}) title=$title.{0,x} fi ('$title') discard. {'~'} title={t} rm. 28093 +drgba. w. 100%,100%,0,"[G"{`39`}"MIC] Image: "$title rm. 28094 xcc_goto. . 28095 28096 oC0= oC1= oC2= oC3= oC4= viewmode=0 28097 do 28098 wait 100 need_refresh=0 28099 28100 # Manage user events. 28101 oviewmode=$viewmode is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} x={*,x} y={*,y} 28102 if {*,r} need_refresh=1 # Window resize. 28103 elif $is_ctrl" && "{*,-D} w[] {{*,w}*125%},{{*,h}*125%} need_refresh=1 # Increase window size. 28104 elif $is_ctrl" && "{*,-C} w[] {{*,w}*80%},{{*,h}*80%} need_refresh=1 # Decrease window size. 28105 elif $is_ctrl" && "{*,-R} w[] {w},{h} need_refresh=1 # Reset window size. 28106 elif {*,b}&1 viewmode={x={*,x};if(x<w/3,1,if(x<2*w/3,2,3))} # Change viewmode. 28107 elif {*,b}&2" && "$x>=0" && "$y>=0 # Add control point from picked color. 28108 xc={$x*w/{*,w}} yc={$y*h/{*,h}} +z[0] $xc,$yc,$xc,$yc 28109 repeat s (${__C$>},{i[$>]/255%},{i[$>]/255%}) r. 2,{w/2},1,1,-1 sort. +,y __C$>={^} rm. done 28110 rm. wait -1 28111 else viewmode=0 28112 fi 28113 need_refresh={$need_refresh||$oviewmode!=$viewmode} 28114 28115 # Update result. 28116 repeat s if ['_${oC$>}']!=['_${__C$>}'] # Channel must be updated. 28117 function1d[] 1,${__C$>} *. {255%} r. 256,1,1,1,5 c. 0,255 28118 +channels[0] $> map. .. j[1] .,0,0,0,$> rm[-2,-1] 28119 need_refresh=1 oC$>=${__C$>} 28120 fi done 28121 28122 # Display view. 28123 if $need_refresh 28124 if $viewmode==0 # Modified view. 28125 +xcc_backto[1] 28126 elif $viewmode%2 # Split view. 28127 w2={0,int(w/2)} b={$viewmode==1} +z[{!$b}] 0,{$w2-1} +z[$b] $w2,100% 28128 xcc_backto.. xcc_backto. a[-2,-1] x line. 50%,0,50%,100%,1,0 28129 else # Original view. 28130 +xcc_backto[0] 28131 fi 28132 if s>3 drgba. fi w. rm. refresh=0 28133 fi 28134 28135 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,SPACE}" && "!{*,ENTER} 28136 w 0 28137 28138 # Transfer curves to output variable and request curve widgets to close. 28139 repeat 5 if narg(${__C$>}) __xcc_C$>=${__C$>} __C$>=-1 fi done 28140 28141# Define colorspace conversion functions. 28142__x_color_curves : 28143 if ['"$1"']=='rgb' 28144 _color0="255,180,180" _color1="180,255,180" _color2="180,180,255" _color3="220,220,220" 28145 _title0=Red _title1=Green _title2=Blue _title3=Alpha 28146 m "xcc_goto:" m "xcc_backto:" 28147 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 28148 a[0,-3] y a[1,-2] y a[2,-1] y" 28149 elif ['"$1"']=='cmy' 28150 _color0="180,255,255" _color1="255,180,255" _color2="255,255,100" _color3="220,220,220" 28151 _title0=Cyan _title1=Magenta _title2=Yellow _title3=Alpha 28152 m "xcc_goto: s c,-3 rgb2cmy[0] a c" m "xcc_backto: s c,-3 cmy2rgb[0] a c" 28153 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 28154 a[0,-3] y a[1,-2] y a[2,-1] y" 28155 elif ['"$1"']=='cmyk' 28156 _color0="180,255,255" _color1="255,180,255" _color2="255,255,100" _color3="180,180,180" _color4="220,220,220" 28157 _title0=Cyan _title1=Magenta _title2=Yellow _title3=Key _title4=Alpha 28158 m "xcc_goto: s c,-3 rgb2cmyk[0] a c" m "xcc_backto: s c,-4 cmyk2rgb[0] a c" 28159 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 28160 a[0,-4] y a[1,-3] y a[2,-2] y a[3,-1] y" 28161 elif ['"$1"']=='hsi' 28162 _color0="255,220,220" _color1="220,220,220" _color2="180,180,180" _color3="220,220,220" 28163 _title0=Hue _title1=Saturation _title2=Intensity _title3=Alpha 28164 m "xcc_goto: s c,-3 rgb2hsi8[0] a c" m "xcc_backto: s c,-3 hsi82rgb[0] a c" 28165 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)) 28166 hsi82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 28167 elif ['"$1"']=='hsl' 28168 _color0="255,220,220" _color1="220,220,220" _color2="180,180,180" _color3="220,220,220" 28169 _title0=Hue _title1=Saturation _title2=Lightness _title3=Alpha 28170 m "xcc_goto: s c,-3 rgb2hsl8[0] a c" m "xcc_backto: s c,-3 hsl82rgb[0] a c" 28171 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)) 28172 hsl82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 28173 elif ['"$1"']=='hsv' 28174 _color0="255,220,220" _color1="220,220,220" _color2="180,180,180" _color3="220,220,220" 28175 _title0=Hue _title1=Saturation _title2=Value _title3=Alpha 28176 m "xcc_goto: s c,-3 rgb2hsv8[0] a c" m "xcc_backto: s c,-3 hsv82rgb[0] a c" 28177 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)) 28178 hsv82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 28179 elif ['"$1"']=='lab' 28180 _color0="180,180,180" _color1="220,180,220" _color2="220,220,180" _color3="220,220,220" 28181 _title0=Lightness _title1=Chroma-A _title2=Chroma-B _title3=Alpha 28182 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" 28183 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)) 28184 lab82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 28185 elif ['"$1"']=='lch' 28186 _color0="180,180,180" _color1="220,180,220" _color2="255,220,220" _color3="220,220,220" 28187 _title0=Lightness _title1=Chroma _title2=Hue _title3=Alpha 28188 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 28189 rgb2srgb[0] a c" 28190 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)) 28191 lch82rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 28192 elif ['"$1"']=='ycbcr' 28193 _color0="180,180,180" _color1="220,220,255" _color2="255,220,220" _color3="220,220,220" 28194 _title0=Luma _title1=Blue\ chroma _title2=Red\ chroma _title3=Alpha 28195 m "xcc_goto: s c,-3 rgb2ycbcr[0] a c" m "xcc_backto: s c,-3 ycbcr2rgb[0] a c" 28196 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)) 28197 ycbcr2rgb[-3--1] permute[-3--1] xcyz a[0,-3] y a[1,-2] y a[2,-1] y" 28198 else error[0--3] "Command 'x_color_curves': Unknown specified color space '$1'." 28199 fi 28200 28201#@cli x_colorize : _is_lineart={ 0 | 1 },_max_resolution={ 0 | >=128 },_multichannels_output={ 0 | 1 },\ 28202# _[palette1],_[palette2],_[grabber1] 28203#@cli : Colorized selected B&W images, using an interactive window. 28204#@cli : When >0, argument 'max_resolution' defines the maximal image resolution used in the interactive window. 28205#@cli : Default values: 'is_lineart=1', 'max_resolution=1024' and 'multichannels_output=0'. 28206x_colorize : skip ${1=0},${3=0},${4=0},${5=0},${6=0} check "${2=1024}==0 || $2>=128" check_display $0 28207 s0="image" s1="lineart" s2="multichannel" s3="merged" use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 28208 e[^-1] "Colorize selected B&W "${s{!$1}}"$? interactively, with maximum resolution $2 and "${s{2+!$3}}" output." 28209 e[] "\n 28210--------------------------------------------------------------------------------------\n 28211----\n 28212---- "${c}"Left mouse button"$n" creates a new colored control point (or moves an existing one).\n 28213---- "${c}"Right mouse button"$n" or key '"${c}"X"$n"' over a control point deletes it.\n 28214---- "${c}"Right mouse button"$n" or key '"${c}"P"$n"' anywhere else picks a color from the image.\n 28215---- "${c}"Mouse wheel"$n", or keys '"${c}"CTRL+arrows UP/DOWN"$n"' zoom view in/out.\n 28216---- '"${c}"CTRL+mouse wheel"$n"', '"${c}"SHIFT+mouse wheel"$n"' or "${c}"arrow keys"$n" move image in zoomed view.\n 28217---- Key '"${c}"SPACE"$n"' updates the extrapolated color field.\n 28218---- Key '"${c}"TAB"$n"' toggles between markers view modes.\n 28219---- Key '"${c}"BACKSPACE"$n"' deletes the last control point added.\n 28220---- Key '"${c}"PAGE UP"$n"' increases image contrast.\n 28221---- Key '"${c}"PAGE DOWN"$n"' decreases image contrast.\n 28222---- Key '"${c}"R"$n"' toggles color replace mode.\n 28223---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 28224---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 28225---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 28226---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' exit the interactive window.\n 28227----\n 28228--------------------------------------------------------------------------------------" 28229 N=$! 28230 thread_main="_x_colorize[0] ${1--1}" 28231 thread_color="w[] 400,320,0,\"Palette: main\" x_select_color[] __color,255,255,255" 28232 28233 is_palette1=${"is_image_arg[] $4"} 28234 if $is_palette1 28235 pass$4 1 ('{b}') discard. {'~'} palette_title1={t} rm. 28236 thread_palette1="w[] 400,400,0,\"Palette: "$palette_title1"\" x_select_palette["{$!-1}"] __color" 28237 fi 28238 28239 is_palette2=${"is_image_arg[] $5"} 28240 if $is_palette2 28241 pass$5 1 ('{b}') discard. {'~'} palette_title2={t} rm. 28242 thread_palette2="w[] 400,400,0,\"Palette: "$palette_title2"\" x_select_palette["{$!-1}"] __color" 28243 fi 28244 28245 is_grabber=${"is_image_arg[] $6"} 28246 if $is_grabber 28247 pass$6 1 ('{b}') discard. {'~'} palette_grabber={t} rm. 28248 thread_grabber="w[] ${\"fitscreen[] {[w,h,1]},128,50%\"},0,\"Grabber: "$palette_grabber"\" 28249 x_grab_color["{$!-1}"] __color" 28250 fi 28251 28252 __color=255,255,255 28253 28254 if !$is_palette1" && "!$is_palette2" && "!$is_grabber 28255 repeat $N l[$>] 28256 parallel $thread_main,$thread_color 28257 endl done 28258 else 28259 repeat $N l[$>,$N--1] 28260 parallel $thread_main,$thread_color,$thread_palette1,$thread_palette2,$thread_grabber 28261 endl done 28262 fi 28263 k[0-{$N-1}] 28264 28265_x_colorize : 28266 28267 # Init variables and images. 28268 name={n} title={b} if narg({x}) title=$title.{x} fi 28269 w={w} h={h} 28270 28271 if $1 # Line-art. 28272 if s==4 sh. 3 if abs(im-iM)>64 +*. -1 rm.. +. 255 else rm. sh. 0 fi 28273 else sh. 0 28274 fi 28275 n 0,255 28276 else # Regular image. 28277 if s==1 sh. 0 28278 else +luminance. 28279 fi 28280 fi 28281 28282 nm. img 28283 28284 fdim=${fitscreen[]\ $w,$h} ww={arg(1,$fdim)} wh={arg(2,$fdim)} x0=0 y0=0 x1={w-1} y1={h-1} 28285 selection=-1 view_markers=2 contrast=9 xpan=-1 ypan=-1 replace_color= current_replace_color= 28286 28287 if narg($_gui_control_points)>=6 # Import list of control points from plug-in GUI. 28288 ($_gui_control_points) r. {w/6},6,1,1,-1 28289 else 0 # Empty list of control points. 28290 fi 28291 nm. points 28292 28293 # Compute potential map. 28294 if $2>0 if $w>$h +r2dx[img] {min($2,$w)},2 else +r2dy[img] {min($2,$h)},2 fi else [img] fi 28295 __x_colorize. $1 28296 pw={potential,w} ph={potential,h} 28297 28298 # Start event loop. 28299 do 28300 28301 # Handle user events for zoom/navigation/resizing. 28302 if narg($replace_color)" && "{*,x}<0" && "{*,y}<0 wait 200 else wait fi 28303 x={*,x} y={*,y} b={*,b} o={*,-o} 28304 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 28305 is_shift={{*,SHIFTLEFT}" || "{*,SHIFTRIGHT}} 28306 is_mouseout={$x<0" || "$y<0} 28307 x={$x0+$x*($x1-$x0+1)/$ww} y={$y0+$y*($y1-$y0+1)/$wh} 28308 oww=$ww owh=$wh ox0=$x0 oy0=$y0 ox1=$x1 oy1=$y1 28309 28310 if {*,r} # When window resized. 28311 nww={*,d} nwh={*,e} m={min($nww,$nwh)} 28312 cx={($x0+$x1)/2} cy={($y0+$y1)/2} dx={$nww*($x1-$x0+1)/$ww} dy={$nwh*($y1-$y0+1)/$wh} 28313 x0={$cx-$dx/2} x1={$cx+$dx/2} 28314 y0={$cy-$dy/2} y1={$cy+$dy/2} 28315 ww=$nww wh=$nwh 28316 elif $is_ctrl" && "{*,-D} # Increase window size. 28317 nww={min({*,u},$ww*1.25)} nwh={min({*,v},$wh*1.25)} m={min($nww,$nwh)} 28318 if $m==$nww ww=$m wh={$h*$m/$w} else ww={$w*$m/$h} wh=$m fi 28319 elif $is_ctrl" && "{*,-C} # Decrease window size. 28320 nww={$ww/1.25} nwh={$wh/1.25} 28321 if min($nww,$nwh)>=64 ww=$nww wh=$nwh fi 28322 elif $is_ctrl" && "{*,R} # Reset window size. 28323 fdim=${fitscreen[]\ $w,$h} ww={arg(1,$fdim)} wh={arg(2,$fdim)} 28324 x0=0 y0=0 x1={$w-1} y1={$h-1} 28325 elif ($is_shift" && "$o<0)" || "{*,ARROWLEFT} # Go left. 28326 dx={($x1-$x0)/6} x0-=$dx x1-=$dx 28327 elif ($is_shift" && "$o>0)" || "{*,ARROWRIGHT} # Go right. 28328 dx={($x1-$x0)/6} x0+=$dx x1+=$dx 28329 elif ($is_ctrl" && "$o>0)" || "({*,ARROWUP}" && "!$is_ctrl) # Go up. 28330 dy={($y1-$y0)/6} y0-=$dy y1-=$dy 28331 elif ($is_ctrl" && "$o<0)" || "({*,ARROWDOWN}" && "!$is_ctrl) # Go down. 28332 dy={($y1-$y0)/6} y0+=$dy y1+=$dy 28333 elif $o>0" || "($is_ctrl" && "{*,ARROWUP}) # Zoom in. 28334 if $x1-$x0>16" && "$y1-$y0>16 28335 cx={if($x>=0" && "!{*,ARROWUP},$x,($x0+$x1)/2)} 28336 cy={if($y>=0" && "!{*,ARROWUP},$y,($y0+$y1)/2)} 28337 x0={$cx+($x0-$cx)*0.75} y0={$cy+($y0-$cy)*0.75} 28338 x1={$cx+($x1-$cx)*0.75} y1={$cy+($y1-$cy)*0.75} 28339 fi 28340 elif $o<0" || "($is_ctrl" && "{*,ARROWDOWN}) # Zoom out. 28341 zfactor={max(($x1-$x0+1)/$w,($y1-$y0+1)/$h)} 28342 if $zfactor<1.3 28343 cx={if($x>=0" && "!{*,ARROWDOWN},$x,($x0+$x1)/2)} 28344 cy={if($y>=0" && "!{*,ARROWDOWN},$y,($y0+$y1)/2)} 28345 x0={$cx+($x0-$cx)/0.75} y0={$cy+($y0-$cy)/0.75} 28346 x1={$cx+($x1-$cx)/0.75} y1={$cy+($y1-$cy)/0.75} 28347 dx={$zfactor^2*($w-$x0-$x1)/2} dy={$zfactor^2*($h-$y0-$y1)/2} 28348 x0+=$dx x1+=$dx y0+=$dy y1+=$dy 28349 else 28350 dx={($w-$x0-$x1)/2} dy={($h-$y0-$y1)/2} 28351 x0+=$dx x1+=$dx y0+=$dy y1+=$dy 28352 fi 28353 elif $b&4" && "!$is_mouseout # Pan. 28354 if $panx<0" && "$pany<0 panx=$x pany=$y 28355 else dx={round($panx-$x)} dy={round($pany-$y)} x0+=$dx y0+=$dy x1+=$dx y1+=$dy 28356 fi 28357 else panx=-1 pany=-1 28358 fi 28359 if $ww!=$oww" || "$wh!=$owh" || "$ox0!=$x0" || "$oy0!=$y0" || "$ox1!=$x1" || "$oy1!=$y1 rm[baseview] fi 28360 28361 # Handle events related to control points management. 28362 N={points,w} 28363 if narg($baseview)" && "($b&3" || "{*,X}" || "{*,P})" && "$x>=0" && "$y>=0" && "$x<$w" && "$y<$h 28364 if $selection==-1" && "$N # Check for selection of an existing point. 28365 ($x;$y) r. $N,2 -. [points] *. {max($ww,$wh)/max($x1-$x0,$y1-$y0)} sqr. s. y +[-2,-1] 28366 dmin={im} selection={if($dmin>25,-1,xm)} rm. 28367 fi 28368 if narg($replace_color) # Go back from 'Replace color' mode. 28369 replace_color= wait -1 28370 elif $selection>=0 28371 if $b&1" && "$view_markers # Move existing point. 28372 +columns[points] $selection ox={i[0]} oy={i[1]} =. $x =. $y,0,1 j[points] .,$selection rm. 28373 rm[view] 28374 elif ($b&2" || "{*,X})" && "$view_markers # Remove existing point. 28375 if $N>1 +z[points] {$selection+1},100% j[points] .,$selection rm. r[points] {$N-1},100%,1,1,0 28376 else rm[points] 0 nm. points fi 28377 wait -1 rm[view] 28378 fi 28379 elif $b&1 # Add new point 28380 ($x;$y;0) ($__color) y. y +. 1 a[-2,-1] y a[points,-1] x selection=$N 28381 if !$view_markers view_markers=2 fi 28382 rm[view] 28383 elif $b&2" || "{*,P} # Pick color from image. 28384 __color={colors,I($x*$pw/$w,$y*$ph/$h)} 28385 fi 28386 else selection=-1 28387 if {*,-SPACE}" && "narg($colors) replace_color= rm[colors] # Update color map. 28388 elif {*,-TAB} view_markers={($view_markers-1)%3} rm[view] wait -1 # Toggle markers. 28389 elif !$is_ctrl" && "{*,-R} # Switch color replace mode. 28390 if narg($replace_color) replace_color= else replace_color=$__color fi 28391 rm[baseview] wait -1 28392 elif {*,PAGEDOWN} contrast={max(0,$contrast-1)} rm[view] wait -1 # Decrease contrast. 28393 elif {*,PAGEUP} contrast={min(9,$contrast+1)} rm[view] wait -1 # Increase contrast. 28394 elif {*,BACKSPACE}" && "$N # Remove last point. 28395 if $N>1 z[points] 0,{$N-2} else i=$points rm[points] i[$i] 0 nm[$i] points fi 28396 rm[view] wait -1 28397 fi 28398 fi 28399 28400 # Manage zoomed view bounds. 28401 w2={round(($x1-$x0)/2)} h2={round(($y1-$y0)/2)} 28402 if $x0<-$w2 x1-={$x0+$w2} x0=-$w2 fi 28403 if $y0<-$h2 y1-={$y0+$h2} y0=-$h2 fi 28404 if $x1>=$w+$w2 x0+={$w-1+$w2-$x1} x1={$w-1+$w2} fi 28405 if $y1>=$h+$h2 y0+={$h-1+$h2-$y1} y1={$h-1+$h2} fi 28406 28407 # Render color map. 28408 if !narg($colors) 28409 N={points,w} 28410 if narg($view) to[view] "Processing...",5,5,20,2 w[view] fi 28411 if $N 28412 [points] 28413 sh. 0,0,0,0 *. {$pw/$w} rm. 28414 sh. 1,1,0,0 *. {$ph/$h} rm. 28415 pointcloud. -1,$pw,$ph 28416 28417 # Additional term that depends on marker's positions. 28418 +compose_channels. max !=. 0 distance. 1 *. 0.02 +. 1 ^. -1 +. [potential] 28419 if !$1 dilate.. 3 fi 28420 watershed.. . rm. -. 1 28421 else [potential],[potential],1,3,255 28422 fi 28423 nm. colors 28424 if narg($baseview) rm[baseview] fi 28425 fi 28426 28427 # Manage replace color mode. 28428 if !narg($replace_color)" && "narg($points_replaced) 28429 rm[points,colors,view] nm[colors_replaced] colors nm[points_replaced] points current_replace_color= 28430 elif narg($replace_color)" && "['$__color']!=['$current_replace_color'] 28431 if narg($colors_replaced) rm[colors_replaced,points_replaced] fi 28432 current_replace_color=$__color 28433 if {points,w} 28434 +replace_color[colors] 0,0,$replace_color,$current_replace_color 28435 +rows[points] 3,5 permute. xzcy -. 1 28436 replace_color. 0,0,$replace_color,$current_replace_color 28437 +. 1 permute. xcyz +j[points] .,0,3 rm.. 28438 else 0 0 28439 fi 28440 nm.. colors_replaced 28441 nm. points_replaced 28442 if narg($baseview) rm[baseview] fi 28443 fi 28444 28445 # Render base image. 28446 if !narg($baseview) 28447 nx0={$x0*$pw/$w} ny0={$y0*$ph/$h} 28448 nx1={$x1*$pw/$w} ny1={$y1*$ph/$h} 28449 +z[img] $x0,$y0,$x1,$y1 28450 r. $ww,$wh,1,100%,{if($ww<w" && "$wh<h,2,1)} 28451 if narg($replace_color)" && "{points,w} icolors=$colors_replaced else icolors=$colors fi 28452 +z[$icolors] $nx0,$ny0,$nx1,$ny1 28453 r. $ww,$wh,1,100%,{if($ww<w" && "$wh<h,2,3)} 28454 if $1 *.. -1 +.. 255 channels.. -3,0 blend. ..,alpha rm.. 28455 else rgb2ycbcr. j. ..,0,0,0,0 rm.. ycbcr2rgb. 28456 fi 28457 nm. baseview 28458 if narg($view) rm[view] fi 28459 fi 28460 28461 # Render view. 28462 if !narg($view) 28463 [baseview] r. 100%,100%,1,3 28464 if $contrast<9 /. {10-$contrast} +. {128*(1-1/(10-$contrast))} fi 28465 if $view_markers 28466 if $view_markers==2 rad1=5 rad2=3 else rad1=3 rad2=2 fi 28467 if narg($replace_color)" && "{points,w} ipoints=$points_replaced else ipoints=$points fi 28468 repeat w#$ipoints 28469 +columns[$ipoints] $> 28470 x={(i[0]-$x0)*$ww/(1+$x1-$x0)} 28471 y={(i[1]-$y0)*$wh/(1+$y1-$y0)} 28472 col={i[3]-1},{i[4]-1},{i[5]-1} 28473 rm. 28474 circle. $x,$y,$rad1,1,0 circle. $x,$y,$rad2,1,$col 28475 done 28476 fi 28477 28478 if narg($replace_color) 28479 to. "Replace by",5,5,20,2 28480 rectangle. 80,8,111,25,1,0 rectangle. 82,10,109,23,1,$replace_color 28481 rectangle. 150,8,181,25,1,0 rectangle. 152,10,179,23,1,$current_replace_color 28482 fi 28483 28484 nm. view 28485 w[view] $ww,$wh,0,$title 28486 fi 28487 28488 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,ENTER} 28489 28490 # Recompute colors at full resolution. 28491 if narg($view) to[view] "Processing fullres...",5,5,20,2 w[view] fi 28492 k[0,img,points] 28493 N={points,w} status= 28494 if $N 28495 status={points,^} 28496 [img] __x_colorize. $1 28497 pointcloud[points] -1,$w,$h 28498 +compose_channels[points] max !=. 0 distance. 1 *. 0.02 +. 1 ^. -1 +[potential,-1] 28499 if !$1 zfact={{img,max(w,h)}/{potential,max(w,h)}} dilate[points] {int(3*$zfact)} fi 28500 watershed[points] [potential] -[points] 1 nm[points] colors 28501 else [img],[img],1,3,255 nm. colors 28502 fi 28503 28504 if $3 # Multichannels output. 28505 k[0,colors] a c 28506 else # Merge for single layer output. 28507 k[0,img,colors] 28508 if $1 +*[img] -1 +. 255 channels. -3,0 blend[colors,-1] alpha rm[0,img] 28509 else rgb2ycbcr[colors] j[colors] [img],0,0,0,0 rm[0,img] ycbcr2rgb[colors] 28510 fi 28511 fi 28512 a c nm $name 28513 28514 __color=-1 # Force color selectors to close. 28515 u $status # Return control points. 28516 w 0 28517 28518# Compute potential function. 28519__x_colorize : 28520 if $1 # Potential for lineart. 28521 n. 0,1 ^. 5 repeat 4 +b. 0.5% min done 28522 else # Potential for generic grayscale image. 28523 gradient_norm. n. 0,255 normalize_local. 3,3 *. -1 n. 0,255 28524 b. 0.05% n. 0,1 sqr. +b. 0.5% n[-2,-1] 0,1 min[-2,-1] 28525 fi 28526 nm. potential 28527 28528#@cli x_connect4 28529#@cli : Launch the Connect Four game. 28530x_connect4 : check_display $0 28531 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 28532 e[] "\n 28533------ "${g}"Connect Four"$n" --------------------------------------------\n 28534----\n 28535---- Connect four tokens in a row, column or diagonally\n 28536---- to win the game.\n 28537----\n 28538---- "${c}"Left mouse button"$n" on a column inserts a new token.\n 28539---- Keys '"${c}"SPACE"$n"' or '"${c}"ENTER"$n"' lets the computer play the turn\n 28540---- (or restart game when it's over).\n 28541---- Key '"${c}"ENTER"$n"' also enables autoplay for the current player.\n 28542---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' close the window.\n 28543----\n 28544----------------------------------------------------------------" 28545 l[] 28546 28547 # Create sprite graphics. 28548 7,6 nm. board 28549 R={board,u={*,u};v={*,v};int(0.5*min(u/w,v/h))} 28550 28551 {2*$R},{2*$R} circle. 50%,50%,32%,1,1 b. 2% g. xy +[-2,-1] n. 0,1 28552 +n. -1,0.5 abs. negate. +f. 200 rv[-3--1] a[-3--1] c hsv2rgb. 28553 to_rgba. circle. 50%,50%,27%,1,0 28554 28555 {4*$R},{4*$R} circle. 50%,50%,20%,1,1 b. 1% g. xy +[-2,-1] n. 0,1 negate. 28556 pow. 0.5 +n. -1,0.8 abs. negate. +f. 10 rv[-3--1] a[-3--1] c 28557 . sh. 0 f. 60 rm. hsv2rgb[-2,-1] 28558 100%,100% circle. 50%,50%,30%,1,255 a[-3,-2] .,c rm. 28559 28560 r2dx[-3--1] $R s[-3--1] c,-3 rm... 28561 n[^0] 0,255 round[^0] nm[^0] cache,cachem,token0,token1,tokenm 28562 +b[cachem] 2% shift. 1%,1%,0,0,2 max[cachem,-1] 28563 r[cache,cachem] 100%,{board,h*100}%,1,100%,0,2 28564 28565 # Define board evaluation function. 28566 evalf="const op = 3 - p; 28567 case(dx,dy) = ( 28568 pgood = pbad = 0; 28569 for (k = -2, k<2, ++k, 28570 X = x + k*dx; 28571 Y = y + k*dy; 28572 if (X>=0 && X<w && Y>=0 && Y<h, 28573 val = i(X,Y); 28574 if (pgood>=0 && val==op, pgood = -1, pgood+=!!val); 28575 if (pbad>=0 && val==p, pbad = -1, pbad+=!!val); 28576 ); 28577 ); 28578 pgood = arg(2+pgood,0,1,2,4,100,1e8); 28579 pbad = arg(2+pbad,0,1,2,4,10000,1e8); 28580 pgood - pbad; 28581 ); 28582 case(1,0) + case(0,1) + case(1,1) + case(1,-1)" 28583 28584 # Start game. 28585 do 28586 28587 # Initialize game. 28588 if !narg($visu) 28589 {board,[w,h]*$R},1,3,64 28590 repeat h#$board,y repeat w#$board,x 28591 val={board,i($x,$y)} if $val j. [token{$val-1}],{$x*$R},{$y*$R},0,0,1,[tokenm],255 fi 28592 done done 28593 +r[cache,cachem] {board,[w,h]*$R},1,100%,0,2 a[-2,-1] c blend[-2,-1] alpha 28594 nm. visu w[visu] 100%,100%,0,"[G'MIC] Connect Four" 28595 turn=0 is_falling=0 x=-1 yv=0 dyv=0 winner= 28596 autoplayer0=0 autoplayer1=0 28597 fi 28598 28599 # Estimate ymax for each column. 28600 if !narg($ymax) 28601 {board,w},1,1,1,"y = -1; repeat (h#"$board",k, if(!i(#"$board",x,k),y = k)); y" nm. ymax 28602 if iM<0 winner=-1,-1,-1 fi # Draw game 28603 fi 28604 28605 if narg($winner) # End of game animation 28606 [visu] nm. tmpvisu 28607 x={arg(1,$winner)} y={arg(2,$winner)} c={arg(3,$winner)} 28608 if $x<0 # Draw game 28609 if !narg($text) 28610 0 t. "Draw game",0,0,57,1,1 r2dx. {tmpvisu,w/2} expand_xy. 3,0 +dilate. 5 n.. 0,255 to_rgb.. 28611 nm[-2,-1] text,textm 28612 fi 28613 j[tmpvisu] [text],{tmpvisu,([w,h]-[w#$text,h#$text])/2},0,0,{0.7+0.3*sin(5*$|)},[textm] 28614 else 28615 repeat 4 28616 [token$turn] 28617 rgb2hsv. sh. 1,2 +. {0.4*sin(5*$|)} c. 0,1 rm. hsv2rgb. 28618 j. [cache],0,0,0,0,1,[cachem],255 28619 j[tmpvisu] .,{$R*[$x,$y]},0,0,1 rm. 28620 x+={$c!=2?1:0} y+={$c==1?0:$c==4?-1:1} 28621 done 28622 fi 28623 w[tmpvisu] 100%,100% rm[tmpvisu] wait 20 28624 28625 if {*,-SPACE}" || "{*,-ENTER} # Restart new game 28626 rm[visu,ymax] f[board] 0 winner= 28627 fi 28628 28629 elif !$is_falling # Manage column selection 28630 28631 if !${autoplayer$turn} 28632 x={visu,X={*,x};X<0?X:int(X*w#$board/w)} 28633 yM={i("#"$ymax,$x)} 28634 if {board,$x<0" || "$x>=w} w[visu] 100%,100% 28635 else 28636 [visu] $R,100%,1,3,($yM>=0?1:0)*($turn?[255,255,0]:[255,0,0]) 28637 j.. .,{$x*$R},0,0,0,{$yM>=0?0.15:0.3} rm. 28638 w. 100%,100% rm. 28639 fi 28640 wait 28641 fi 28642 28643 if {*,-b}&1" && "$yM>=0" && "$x>=0 is_falling=1 yv=0 dyv=1 # Manual play 28644 elif ${autoplayer$turn}" || "{*,-SPACE}" || "{*,ENTER} # Computer play 28645 if {*,-ENTER} autoplayer$turn=1 fi 28646 max_score=-inf max_col= 28647 repeat w#$board,move1 28648 yM1={i("#"$ymax,$move1)} 28649 if $yM1>=0 28650 +=[board] {1+$turn},$move1,$yM1 nm. board1 28651 {board,w},1,1,1,"y = -1; repeat (h#"$board1",k, if(!i(#"$board1",x,k),y = k)); y" nm. ymax1 28652 opp_max_score=-inf opp_max_board={board,^} 28653 opp_turn={($turn+1)%2} 28654 repeat w#$board,move2 28655 yM2={i("#"$ymax1,$move2)} 28656 if $yM2>=0 28657 +=[board1] {1+$opp_turn},$move2,$yM2 28658 +f. "const p = 1 + "$opp_turn"; "$evalf score={is+u} rm. 28659 if $score>$opp_max_score opp_max_score=$score opp_max_board={^} fi 28660 rm. 28661 fi 28662 done 28663 rm[board1,ymax1] 28664 28665 {board,[w,h,1,1]},$opp_max_board 28666 f. "const p = 1 + "$turn"; "$evalf score={is+u} rm. 28667 if $score>$max_score max_score=$score max_col=$move1 fi 28668 fi 28669 done 28670 x=$max_col is_falling=1 yv=0 dyv=1 28671 fi 28672 28673 else # Manage token falling animation 28674 if !narg($column) 28675 $R,{board,h*$R},1,3,64 28676 repeat h#$board v={board,i($x,$>)} if $v j. [token{$v-1}],0,{$>*$R},0,0,1,[tokenm],255 fi done 28677 nm. column 28678 fi 28679 28680 yM={i("#"$ymax,$x)} 28681 [column] 28682 j. [token$turn],0,$yv,0,0,1,[tokenm],255 28683 j. [cache],0,0,0,0,1,[cachem],255 28684 [visu] nm. tmpvisu 28685 j[tmpvisu] ..,{$R*$x},0,0,0 rm.. w[tmpvisu] 100%,100% 28686 if $yv>=$yM*$R 28687 j[visu] [tmpvisu] is_falling=0 28688 =[board] {$turn+1},$x,$yM 28689 rm[ymax,column] 28690 28691 # Check end of game. 28692 +f[board] "if (!i,0, 28693 case_h = i==j(1) && i==j(2) && i==j(3); 28694 case_v = i==j(0,1) && i==j(0,2) && i==j(0,3); 28695 case_d1 = i==j(1,1) && i==j(2,2) && i==j(3,3); 28696 case_d2 = i==j(1,-1) && i==j(2,-2) && i==j(3,-3); 28697 case_h?1:case_v?2:case_d1?3:case_d2?4)" 28698 if iM winner={[xM,yM,i(xM,yM)]} # Player won ! 28699 else turn={($turn+1)%2} 28700 fi 28701 rm. 28702 fi 28703 rm[tmpvisu] 28704 yv={min($yM*$R,$yv+$dyv)} dyv+={visu,h/100} 28705 wait 20 28706 fi 28707 28708 while {*}" && "!{*,ESC}" && "!{*,Q} 28709 rm w 0 endl 28710 28711#@cli xz : eq. to 'x_crop' 28712xz : 28713 _gmic_s="$?" v + _x_crop 28714 28715#@cli x_crop 28716#@cli : Crop selected images interactively. 28717#@cli : (eq. to 'xz'). 28718x_crop : 28719 _gmic_s="$?" v + _$0 28720 28721_x_crop : 28722 e[0--3] "Crop image"$_gmic_s" interactively." 28723 repeat $! l[$>] 28724 w ${"fitscreen "{[w,h,d]}},1,"[G'MIC] "{n}" - Interactive crop" 28725 +select 2,{round([w,h,d]/2)},0,1 u={^} z.. $u rm. 28726 w[] 0 is_change 28727 endl done u $u 28728 28729#@cli x_cut 28730#@cli : Cut selected images interactively. 28731x_cut : 28732 e[^-1] "Cut image"$_gmic_s" interactively." 28733 repeat $! l[$>] 28734 wsiz0=${"fitscreen ."} 28735 value0,value1=-1,-1 28736 w[] $wsiz0,0,"[G'MIC] "{n}" - Interactive cut" 28737 0 28738 for {*}" && "!{*,ESC} 28739 28740 if [w#1,h#1]!=[{*,w,h}] # Generate image view 28741 rm[1] +slices[0] 50% r. {*,w,h},1,100%,1 w. 28742 fi 28743 28744 mx,my,mb={*,x,y,b} 28745 if $mb" && "$mx>=0" && "$my>=0 28746 value0,value1={"dw1 = "{*,w}" - 1; value0 = "$mx"*100/dw1; 28747 dh1 = "{*,h}" - 1; value1 = "$my"*100/dh1; 28748 [ value0,value1 ];"} 28749 update_view=1 28750 fi 28751 28752 if $update_view 28753 if $value0>=0" && "$value1>=0 28754 +c[1] $value0%,$value1% n. 0,255 28755 to. "Min: "{_round($value0,0.1)}%"\n"\ 28756 "Max: "{_round($value1,0.1)}%,1%,1%,{max(13,3.5*h%)} 28757 w. rm. 28758 else w. 28759 fi 28760 update_view=0 28761 fi 28762 28763 wait 28764 if {*,r} update_view=1 fi 28765 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} 28766 w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 update_view=1 28767 fi 28768 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} 28769 w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 update_view=1 28770 fi 28771 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} 28772 w[] $wsiz0 wait -1 update_view=1 28773 fi 28774 done 28775 w[] 0 rm. u $value0%,$value1% c ${} 28776 endl done 28777 28778#@cli x_fire 28779#@cli : Launch the fire effect demo. 28780x_fire : skip "${1=G\47MIC}" check_display $0 28781 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 28782 e[] "\n 28783------ "${g}"Fire effect"$n" ------------------------\n 28784----\n 28785---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 28786---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 28787---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 28788----\n 28789-------------------------------------------" 28790 28791 # Init image data. 28792 i[0] 100,32 w[0] {[4.5*w,6.75*h]},0,"[G"{`39`}"MIC] Fire Effect" 28793 if {*,w}<0.5*{*,u} w[] {[{*,w},{*,h}]*1.5} fi 28794 i[1] (0,255,255,255,255^0,0,255,255,255^0,0,0,128,255) r[1] 256,1,1,3,3 28795 i[2] (0,0,0;0,0,0;1,1,1;0,1,0) *[2] 0.21 28796 text3d "$1",33,3,1 28797 mv. 3 c3d[3] n3d[3] *3d[3] 320 col3d[3] 255,205,130 db3d 0 f3d 300 28798 100,100 rand. 0,255 ellipse. 50%,50%,5,5,0,1,300 b. 10 28799 sharpen. 1000 shrink_xy. 1 n. 0,255 to_rgb. light3d . rm. 28800 28801 # Start animation loop. 28802 angle=0 28803 do 28804 correlate[0] [2] # Apply fire effect. 28805 {0,w},1 rand. 128,256 j[0] .,0,{{0,h}-1} rm. # Add new random values at the bottom line. 28806 +r[0] 400,200,1,1,3 map. [1] # Map fire palette 28807 +r3d[3] 0,1,0,$angle j3d.. .,50%,50%,0,1,5,0,0 # Draw 3D object. 28808 *3d. 0.25,0.16,1 j3d[0] .,50%,50%,0,1,3,0,0 28809 rm. 28810 angle+=3 # Update 3D angle. 28811 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-22},16,1,0.2 fi 28812 w. 28813 if {*,CTRLLEFT}" && "{*,D} w[] {1.5*[w,h]} elif {*,CTRLLEFT}" && "{*,C} w[] {[w,h]} fi 28814 rm. wait 40 28815 while {*}" && "!{*,ESC}" && "!{*,Q} 28816 28817 # Exit properly. 28818 rm[0-3] w 0 28819 28820#@cli x_fireworks 28821#@cli : Launch the fireworks demo. 28822x_fireworks : check_display $0 28823 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 28824 e[] "\n 28825------ "${g}"Fireworks"$n" --------------------------\n 28826----\n 28827---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 28828---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 28829---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 28830----\n 28831--------------------------------------------" 28832 l[] 28833 (16;64^64;32^128;32) r 320,160,1,3,3 # [-2] = Background (color gradient). 28834 . # [-1] = Rendered image. 28835 w. {1.5*w},{1.5*h},0,"[G"{`39`}"MIC] Fireworks" # Display window. 28836 time=0 28837 do # Start animation loop. 28838 time-=1 28839 if $!==2\ ||\ $time<0 # Insert new rocket. 28840 i[0] ({u(w)},\ # X-position 28841 {h},\ # Y-position 28842 {u(-3,3)},\ # X-velocity 28843 {u(2)-5},\ # Y-velocity 28844 {30+u(20)},\ # Time of explosion 28845 1.5,\ # Radius 28846 255,255,255) # Color 28847 time={u(20)} # Elapsed time until next rocket. 28848 fi 28849 *. 0.99 # Create fading effect with previous frames. 28850 j. ..,0,0,0,0,0.2 # Add background. 28851 i=0 28852 repeat $!-2 28853 to_be_removed=0 28854 radius={if({$i,@4}>0,{$i,@5}/3,{$i,@5}*(1+2*({$i,@4}+2)/120))} 28855 ellipse. {$i,@0},{$i,@1},{$i,@5},{max(1,$radius)},{atan2({$i,@3},{$i,@2})*180/pi},0.6,{$i,@6-8} # Draw rocket. 28856 ({$i,@2},{$i,@3},0,0.09,-1,0,0,0,0) +[$i,-1] # Compute new position of the rocket. 28857 if {$i,@0}<0\ ||\ {$i,@0}>=w\ ||\ {$i,@1}>=h\ ||\ $radius<0 to_be_removed=1 fi # Discard if rocket disappear. 28858 if {$i,@4}<0\ &&\ {$i,@4}>=-1 # In case of explosion -> Split current rocket into several colorful rockets. 28859 color={min(255,80+u(200))},{min(255,80+u(200))},{min(255,80+u(200))} 28860 radius={u(10)} 28861 N={5+u(10)} 28862 repeat $N 28863 angle={$>*2*pi/$N} 28864 i... ({$i,@0,1},{2*cos($angle)+{$i,@2}/1.5},{2*sin($angle)+{$i,@3}/1.5},-2,$radius,$color) 28865 done 28866 to_be_removed=1 28867 fi 28868 if $to_be_removed rm[$i] else i+=1 fi # If processed rocket has to be removed. 28869 done 28870 fps=${-fps} if $fps>0 to. $fps" fps",3,{h-20},14,1,0.2 fi 28871 w. wait 20 # Display rendered frame. 28872 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 28873 while {*}" && "!{*,ESC}" && "!{*,Q} 28874 rm w 0 endl 28875 28876#@cli x_fisheye 28877#@cli : Launch the fish-eye effect demo. 28878x_fisheye : check_display $0 28879 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 28880 e[] "\n 28881------ "${g}"Fish-eye effect"$n" --------------------\n 28882----\n 28883---- "${c}"Mouse pointer"$n" moves fish-eye center.\n 28884---- "${c}"Mouse buttons"$n" set fish-eye size.\n 28885---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 28886---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 28887---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 28888----\n 28889-------------------------------------------" 28890 28891 if $!>0 a x n 0,255 r2dy 220 else 28892 120,90,1,3 rand. 0,255 plasma. 0.3,3 n 0,255 28893 t " G\47MIC\nFISH-EYE\n EFFECT",20,13,23,1,255 scale3x b 5 sharpen 1000 28894 f i+150-3*abs(y-h/2) c. 0,255 frame_fuzzy. 15,10,15,1.5,0 to_rgb. 28895 fi 28896 torus3d 20,6 col3d. {u(30,255)},{u(30,255)},{u(30,255)} +r3d. 1,0,0,90 28897 col3d. {u(30,255)},{u(30,255)},{u(30,255)} +3d. 15 +3d[-2,-1] *3d. 4 db3d 0 c3d. 28898 R=30 28899 w.. {1.25*{-2,w}},{1.25*{-2,h}},0,"[G"{`39`}"MIC] Fish-Eye Effect" 28900 do 28901 wait 40 28902 if {*,b}==1 R={min(80,$R+8)} fi 28903 if {*,b}==2 R={max(3,$R-8)} fi 28904 +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 28905 if {*,x}>=0 28906 fisheye. {{*,x}*100/{*,w}},{{*,y}*100/{*,h}},$R 28907 fi 28908 w. 28909 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 28910 rm. 28911 if {*}==0" || "{*,ESC}" || "{*,Q} rm[-2,-1] w 0 return fi 28912 while 1 28913 28914#@cli x_fourier 28915#@cli : Launch the fourier filtering demo. 28916x_fourier : check_display $0 28917 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 28918 e[] "\n 28919------ "${g}"Fourier-filtering"$n" ----------------------------------------\n 28920----\n 28921---- "${c}"Mouse buttons"$n" on the right image to set min/max frequencies.\n 28922---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 28923---- Keys '"${c}"CTRL+C"$n"' to decrease window size.\n 28924---- Keys '"${c}"CTRL+R"$n"' to reset window size.\n 28925---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 28926----\n 28927-----------------------------------------------------------------" 28928 28929 if !$! sp ? r2dx 400 fi 28930 28931 repeat $! l[$>] 28932 28933 # Init variables. 28934 need_update=1 # need_update (boolean) 28935 freqmin=0 # min freq. (in %) 28936 freqmax=100 # max freq. (in %) 28937 28938 if w>3*{*,u}/5 r2dx. {3*{*,u}/10} fi # Reduce image size if necessary. 28939 if h>3*{*,v}/5 r2dy. {3*{*,v}/5} fi 28940 28941 # Compute fourier transform. 28942 +fft. nm.. real nm. imag 28943 28944 # Generate log-magnitude image. 28945 +sqr[real,imag] +[-2,-1] sqrt. +. 1 log. 28946 n. 0,255 shift. {round(w/2)},{round(h/2)},0,0,2 to_colormode. {-2,s} 28947 nm. logmag 28948 28949 +r2dy. 128 frame. 1,1,0 nm. thumb 28950 w[0,-2] -1,-1,0,"[G"{`39`}"MIC] Fourier Filtering" 28951 28952 l 28953 if !narg($first_time) 28954 parallel 0,"alert[thumb] \"[G"{`39`}"MIC Fourier Filtering]\",\ 28955 \"The G\47MIC Fourier filtering demo illustrates the effect\n\ 28956 of bandpass frequency filtering on an image. Use your mouse\n\ 28957 buttons to select low and high bounds for the frequencies\n\ 28958 displayed on the Fourier representation of the image\n\ 28959 (right image).\",\ 28960 \"OK\"" 28961 first_time=0 28962 fi 28963 28964 # Enter user event-loop. 28965 do 28966 28967 if $need_update # If image must be updated. 28968 28969 # Generated filtering mask. 28970 [logmag],[logmag] nm. mask 28971 r={sqrt(w^2+h^2)*$freqmax/200} ellipse[mask] 50%,50%,$r,$r,0,1,1 28972 r={max(0,sqrt(w^2+h^2)*$freqmin/200-1)} if $r ellipse[mask] 50%,50%,$r,$r,0,1,0 fi 28973 28974 # Compute filtered log-magnitude. 28975 +*[logmag] [mask] +. [mask] /. 2 n. 0,255 28976 28977 # Compute filtered fourier representation. 28978 shift[mask] -{mask,round(w/2)},-{mask,round(h/2)},0,0,2 28979 +*[real,imag] [mask] 28980 rm[mask] 28981 28982 # Compute filtered image by inverse fourier. 28983 ifft[-2,-1] rm. n. 0,255 28984 28985 # Display filtered image. 28986 rv[-2,-1] 28987 if {*} r[-2,-1] {{*,w}/2},{*,h} fi 28988 t. "Freq. Min/Max = "{int($freqmin)}"% / "{int($freqmax)}"%",5,5,13,1,255 28989 w[-2,-1] rm[-2,-1] 28990 need_update=0 28991 28992 fi 28993 28994 wait 28995 28996 if {*,b}" && "{*,x}>={*,w}/2 # If mouse button pressed on the right pane. 28997 r={200*sqrt(({*,x}-3*{*,w}/4)^2+({*,y}-{*,h}/2)^2)/\ # Compute selected radius (in %). 28998 sqrt(({*,w}/2)^2+{*,h}^2)} 28999 if {*,b}&1 freqmax=$r # Update max freq. if left button. 29000 else freqmin={max(0,$r-3)} # Update min freq. if other button. 29001 fi 29002 if $freqmin>=$freqmax freqmin=$freqmax fi # Check that the min/max freq. are ordered. 29003 need_update=1 # Tell that the image must be updated. 29004 fi 29005 29006 if {*,r} need_update=1 fi 29007 29008 # Increase window size. 29009 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} need_update=1 fi 29010 29011 # Decrease window size. 29012 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} need_update=1 fi 29013 29014 # Reset window size. 29015 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {2*{0,w}},{0,h} need_update=1 fi 29016 29017 while {*}" && "!{*,ESC}" && "!{*,Q} 29018 w 0 29019 endl 29020 rm[^0] # Clean images and window. 29021 endl done rm 29022 29023#@cli x_grab_color : _variable_name 29024#@cli : Open a color grabber widget from the first selected image. 29025#@cli : Argument 'variable_name' specifies the variable that contains the selected color values at any time. 29026#@cli : Assigning '-1' to it forces the interactive window to close. 29027#@cli : Default values: 'variable_name=xgc_variable'. 29028x_grab_color : skip ${1=xgc_variable} check_display $0 29029 if !$! error[0--3] "Command '$0': Missing specified input image." fi 29030 l[0] nm={n} nm. img 29031 e[^-1] "Open "${arg\ {0,s},GRAY,GRAYA,RGB,RGBA}" color grabber widget for image$?, with variable name '$1'." 29032 29033 if !{*} w[] ${fitscreen[]\ {[w,h,1]},128,50%},0,0,-1,-1,"Grab a color" fi 29034 _x_grab_color +dilate. 3 nm. icon_mask *.. 255 to_rgb.. nm.. icon_sprite 29035 29036 xc=5 yc=5 o$1=$$1 29037 29038 cursor[0] 0 29039 do 29040 if !narg($visu0) 29041 +r[img] {*,w},{*,h},1,100%,2 drgba. w. nm. visu0 29042 fi 29043 29044 x={*,x} y={*,y} b={*,b} mouse_over={$x>=0" && "$y>=0} 29045 hc={narg($$1)?40:24} 29046 yc={visu0,nhc=h-$hc-8;!$mouse_over?$yc:$y<$hc||$yc+$hc>=h?nhc:$y>=nhc?5:$yc} 29047 29048 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] 29049 [visu0] nm. visu 29050 if narg($color) 29051 24,$hc,1,[img] fc. $color 29052 if narg($$1) rectangle. 0,24,100%,100%,1,$$1 line. 0,24,100%,24,1,0 fi 29053 drgba. frame. 1,1,0 frame. 1,1,255 j[visu] .,$xc,$yc rm. 29054 0 29055 if narg($$1) 29056 t. "Position ("$X","$Y")\nColor ("{``$color}")\nSelected ("{``$$1}")",1,0,15,1,255 29057 else 29058 t. "Position ("$X","$Y")\nColor ("{``$color}")",1,0,15,1,255 29059 fi 29060 +dilate. 5 r.. 100%,100%,1,3 29061 j[visu] ..,{30+$xc},$yc,0,0,0.85,.,255 rm[-2,-1] 29062 fi 29063 29064 if $mouse_over 29065 X={img,round($x*(w-1)/({*,w}-1))} 29066 Y={img,round($y*(h-1)/({*,h}-1))} 29067 color={img,round(I($X,$Y))} 29068 j[visu] [icon_sprite],$x,{icon_sprite,$y-h+1},0,0,1,[icon_mask] 29069 if $b&1 $1=$color fi 29070 fi 29071 w[visu] rm[visu] 29072 29073 ox=$x oy=$y ob=$b ohc=$hc oyc=$yc ocolor=$color o$1=$$1 29074 fi 29075 29076 if arg(1,{'$1'})==_'_'" && "arg(2,{'$1'})==_'_' wait 50 else wait fi 29077 if {*,r} w[] -1 rm[visu0] yc=5 fi 29078 if ['$$1']=='-1' break fi # Close request 29079 29080 while {*}" && "!{*,ESC}" && "!{*,Q} 29081 w 0 k[img] nm $nm endl 29082 u $color 29083 29084# Define color grabber icon. 29085_x_grab_color : 29086 base642img[] \ 29087"MSB1bnNpZ25lZF9jaGFyIGxpdHRsZV9lbmRpYW4KMSAzMzcgMSAxICMyNzcKeJyNiNlOwlAYBi9IDDcaY+LGpiJbj7tBKEbglTQE7dcbkZS1gfNXFCx"\ 29088"lK6WE83w+gDaaeG0mmWTm67NSea5s1Pz6Ot80tnrb/d3BnhkYBq3QKDyOTA5nmfqDnW2W5nK77Mj60yLXgZvrqm6Oq47MYWc4ZhnCJE2wrgjmBWFwRm"\ 29089"r/hNQ3ZqivKQIlCN0YQZdeQGgxzXOD1T3XWEMhVWMtz1Wmw4h1QHEOShogqQc67YPOBwpdmgpdWzDSY9DNFJS1wWUH/NZF926FTl4oel48tgui3C6KU"\ 29090"rMo7rWCYCvJg4k/fvp/5/dJq9QyuUy48UXMOZ5H7ah9ND2YRMbhUXgUsoLDgOnxsf++0/TX1zRf1fcNa0iPgw==" 29091 -. 127 decompress_rle. 29092 frame. 10,10,0 29093 r2dx. 24 29094 29095#@cli x_hanoi 29096#@cli : Launch the Tower of Hanoi game. 29097x_hanoi : check_display $0 29098 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29099 e[] "\n 29100------ "${g}"Tower of Hanoï"$n" ---------------------\n 29101----\n 29102---- "${c}"Left button"$n" and "${c}"mouse"$n" to move a disk.\n 29103---- "${c}"Right button"$n" to rotate 3D view.\n 29104---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 29105---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 29106---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29107----\n 29108-------------------------------------------" 29109 l[] 29110 l[] # Create 3D rods 29111 cylinder3d 1,10 r3d 1,0,0,90 29112 ++3d 10,0,0 +-3d.. 10,0,0 29113 box3d 30,1,10 -3d. 15,0,5 29114 +3d nm rods3d 29115 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 29116 (86,50,50;132,36,12;218,109,66;231,207,180;255,193,140) permute. yzcx r. 32,1,1,3,3 29117 map.. . rm. b. 2% b. x,1% sharpen. 100 c. 0,255 29118 r3d.. 1,0,0,-90 texturize3d.. . r3d.. 1,0,0,90 rm. 29119 endl 29120 29121 l[] # Create 3D disks 29122 6,1,1,3,'[360*x/w,0.9*(1-(x/w)^0.5),0.9]' hsi2rgb. 29123 ytop0=0 29124 repeat w#0 29125 R,r={3-0.3*$>},{1.6-0.22*$>} 29126 torus3d $R,$r,36,10 29127 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] 29128 luminance,0.75 # Marble texture 29129 texturize3d.. . rm. 29130 /3d. 1,1,{0.3+$r} r3d. 1,0,0,90 -3d. 0,0.8,0 29131 a$>,x$>,y$>,h$>=0,0,$ytop0,{1.8*$r/(0.3+$r)} 29132 ytop0+=${h$>} 29133 nm. disk3d$> 29134 done 29135 rm[0] 29136 endl 29137 29138 w[] 640,400,0,"[G"{`39`}"MIC] Tower of Hano\357" 29139 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 29140 nb_moves,buttons,motion3d_x,motion3d_y=0 29141 x,rod,rod_source,rod_target,selected=-1 29142 fading=$| error=0 29143 do 29144 29145 # Display 3D view for current game state. 29146 repeat 6 +r3d[disk3d$>] 1,1,1,${a$>} +3d. {10*(${x$>}-1)},-${y$>},0 done +3d[-6--1] +3d. [rods3d] 29147 r3d. 1,0,0,20 29148 if !($buttons&2) r3d. 0,1,0.3,{5*cos(1.5*$|)} r3d. 0.3,0,1,{3*sin(0.8*$|)} fi 29149 r3d. 1,0,0,$motion3d_y r3d. 0,-1,0,$motion3d_x *3d. 20 29150 [background] j3d. ..,50%,70%,10,1,5,0,1,800,200,0,-3000,0.15,0.2 29151 t. "#Moves: "$nb_moves,2%,92%,20,1,255 29152 29153 if $error (255^0^0) ri. .. j.. .,0,0,0,0,$error error={max(0,$error-0.2)} rm. fi 29154 if $|-$fading<1 *. {$|-$fading} fi 29155 w. wait 40 29156 if {*,CTRLLEFT}" && "{*,D} w[] {w*1.5},{h*1.5} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 29157 rm[-2,-1] 29158 29159 # Get index of top disk for each rod. 29160 top0,top1,top2,ytop0,ytop1,ytop2=-1 29161 repeat 6 29162 rod={round(${x$>})} 29163 if $selected!=$>" && "${y$>}+${h$>}>${ytop$rod} ytop$rod={${y$>}+${h$>}} top$rod=$> fi 29164 done 29165 29166 # Manage user events. 29167 prev_buttons=$buttons 29168 mouse_x,mouse_y,buttons={*,x},{*,y},{*,b} 29169 if $mouse_x>=0 x={2.6*($mouse_x/{*,w}-0.5)+1} rod={round($x)} fi 29170 29171 if $mouse_x>=0" && "$buttons&2 # Right mouse button 29172 motion3d_x,motion3d_y={([$mouse_x,$mouse_y]/[{*,w},{*,h}]-0.5)*90} 29173 29174 elif $mouse_x>=0" && "$buttons&1 # Left mouse button 29175 if $selected<0 # Select a disk 29176 selected=${top$rod} 29177 rod_source={$selected<0?-1:$rod} 29178 fi 29179 if $selected>=0" && "$rod>=0 # Move a selected disk 29180 if ${y$selected}<11 y$selected={min(11,${y$selected}+3)} 29181 else 29182 x$selected+={d=$rod-${x$selected};sign(d)*min(0.3,abs(d))} 29183 y$selected={x=${x$selected};11+1.5*sin(pi*abs(x-round(x)))} 29184 a$selected={x=${x$selected};45*sin(pi*abs(x-round(x)))} 29185 fi 29186 fi 29187 29188 elif !$buttons # No mouse button 29189 if $rod>=0" && "$selected>=0 29190 if $rod_target<0 29191 if ${top$rod}<$selected rod_target=$rod nb_moves+={$rod_target!=$rod_source} # Allowed move 29192 else rod_target=$rod_source error=0.8 # Forbidden move 29193 fi 29194 fi 29195 x$selected=$rod_target 29196 a$selected=0 29197 ytop={max(0,${ytop$rod_target})} 29198 if ${y$selected}>$ytop y$selected={max($ytop,${y$selected}-3)} 29199 else x,rod,rod_source,rod_target,selected=-1 29200 fi 29201 fi 29202 fi 29203 29204 if !($buttons&2) # Slowly go back to initial 3D view 29205 motion3d_x-={sign($motion3d_x)*min(1,abs($motion3d_x))} 29206 motion3d_y-={sign($motion3d_y)*min(1,abs($motion3d_y))} 29207 fi 29208 29209 while {*}" && "!{*,ESC}" && "!{*,Q} 29210 w[] 0 rm endl 29211 29212#@cli x_histogram 29213#@cli : Launch the histogram demo. 29214x_histogram : check_display $0 29215 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29216 e[] "\n 29217------ "${g}"Histogram demo"$n" -------------------------------\n 29218----\n 29219---- "${c}"Mouse"$n" to set parameters.\n 29220---- "${c}"Right button"$n" or key '"${c}"SPACE"$n"' to reset.\n 29221---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29222----\n 29223-----------------------------------------------------" 29224 29225 if !$! sp ? to_rgb 29226 else k[0] to_rgb r2dy 300,2 if w>800 r 800,100%,1,3,2 fi n 0,255 29227 fi 29228 29229 # Prepare image layout. 29230 +frame. 1,1,0 29231 300,{h},1,3,220 29232 29233 t. "Gamma :",5,0,16,1,0 29234 t. "Contrast :",5,50,16,1,0 29235 t. "Brightness :",5,100,16,1,0 29236 t. "Smoothness :",5,150,16,1,0 29237 t. "Sharpness :",5,200,16,1,0 29238 t. "Clusters :",5,250,16,1,0 29239 a[-2,-1] x 29240 {w},200,1,3,255 29241 grid. 10%,10%,0,0,0.3,0xCCCCCCCC,0 29242 rectangle. 0,0,100%,100%,1,0xFFFFFFFF,0 29243 axes. 0,255,1,0,13,1,0 29244 frame[-2,-1] 5,5,220 29245 a[-2,-1] y 29246 29247 # Initialize variables. 29248 clusters=64 sharpness=0 smoothness=0 contrast=1 brightness=0 gamma=1 29249 29250 # Start event loop. 29251 do 29252 29253 # Render corrected image and insert it in canvas. 29254 [0] 29255 ia={ia} 29256 if $gamma /. 255 ^. {1/$gamma} *. 255 fi 29257 -. $ia *. $contrast +. $brightness +. $ia 29258 b. $smoothness 29259 sharpen. $sharpness 29260 c. 0,255 29261 +j.. .,6,6 29262 29263 # Render parameter sliders. 29264 sx={{0,w}+12} 29265 _x_histogram. {$gamma*100/4} j.. .,$sx,25 rm. 29266 _x_histogram. {$contrast*100/4} j.. .,$sx,75 rm. 29267 _x_histogram. {($brightness+128)*100/256} j.. .,$sx,125 rm. 29268 _x_histogram. {$smoothness*100/10} j.. .,$sx,175 rm. 29269 _x_histogram. {$sharpness*100/2000} j.. .,$sx,225 rm. 29270 _x_histogram. {$clusters*100/256} j.. .,$sx,275 rm. 29271 29272 # Render corresponding histogram. 29273 +s.. c histogram[-3--1] $clusters,0,255 /[-3--1] {6*{0,wh}/$clusters} rm[-5] 29274 +z[-4] 5,{0,h+16},{{-4,w}-5},{{-4,h}-6} 29275 graph. [-4],3,0,1,0,0.2,255,0,0 29276 graph. ...,3,0,1,0,0.2,0,255,0 29277 graph. ..,3,0,1,0,0.2,0,0,255 29278 rm[-4--2] 29279 j.. .,5,{0,h+16} rm. 29280 29281 if {*,b}&1\ &&\ {*,x}<{0,w}\ &&\ {*,y}<{0,h} 29282 j. [0],6,6 to. Original,10,10,16 29283 fi 29284 29285 # Display rendering. 29286 w. {w},{h},0,"[G"{`39`}"MIC] Histogram Demo" rm. 29287 wait 29288 29289 # Manage user interactions. 29290 if {*,b}&1\ &&\ {*,x}>={0,w}-10 29291 if {*,y}>=25\ &&\ {*,y}<=42 29292 gamma={max(0,min(4,({*,x}-$sx)*4/280))} 29293 elif {*,y}>=75\ &&\ {*,y}<=92 29294 contrast={max(0,min(4,({*,x}-$sx)*4/280))} 29295 elif {*,y}>=125\ &&\ {*,y}<=142 29296 brightness={max(-128,min(128,({*,x}-$sx)*256/280-128))} 29297 elif {*,y}>=175\ &&\ {*,y}<=192 29298 smoothness={max(0,min(10,({*,x}-$sx)*10/280))} 29299 elif {*,y}>=225\ &&\ {*,y}<=242 29300 sharpness={max(0,min(2000,({*,x}-$sx)*2000/280))} 29301 elif {*,y}>=275\ &&\ {*,y}<=292 29302 clusters={max(2,min(256,({*,x}-$sx)*256/280))} 29303 fi 29304 fi 29305 if {*,b}&2\ ||\ {*,SPACE} clusters=64 sharpness=0 smoothness=0 contrast=1 brightness=0 gamma=1 fi 29306 while {*}" && "!{*,ESC}" && "!{*,Q} 29307 w 0 rm 29308 29309_x_histogram : 29310 val={max(0,min(100,$1))} 29311 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 29312 0 t. {round($val)}%,0,0,14,1,1 +*. -255 +. 255 r. 100%,100%,1,3 29313 j... .,{(280-w)/2},{(16-h)/2},0,0,1,.. rm[-2,-1] 29314 r. {w+2},{h+2},1,3,0,0,0.5,0.5 29315 29316#@cli x_hough 29317#@cli : Launch the hough transform demo. 29318x_hough : check_display $0 29319 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29320 e[] "\n 29321------ "${g}"Hough-transform"$n" -----------------------------------------\n 29322----\n 29323---- "${c}"Mouse buttons"$n" on the vote image to draw corresponding line.\n 29324---- "${c}"Mouse buttons"$n" on the image to vote for all lines crossing.\n 29325---- the clicked point.\n 29326---- Key '"${c}"SPACE"$n"' to reset the hough window.\n 29327---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29328----\n 29329-----------------------------------------------------------------" 29330 29331 if !$! l[] sp greece onfail testimage2d 400 endl fi 29332 n 0,255 29333 29334 repeat $! l[$>] 29335 r. ${fitscreen\ {[w,h]}},1,100%,3 # Resize to fit screen if necessary. 29336 if !narg($first_time) 29337 parallel 0,"+l[0] r2dy 128 frame 1,1,0 \ 29338 alert \"[G"{`39`}"MIC Hough Transform]\",\ 29339 \"The G\47MIC Hough transform demo illustrates the application\n\ 29340 of the Hough transform to detect lines in an image. Use your\n\ 29341 mouse buttons to explore the transform image and see how\n\ 29342 lines in images are represented by points in the transform.\",\ 29343 \"OK\" \ 29344 rm endl" 29345 first_time=0 29346 fi 29347 29348 rhomax={sqrt(w^2+h^2)/2} 29349 +b. 1.5 hough. 512,400 b. 0.5 +. 1 log. n. 0,255 29350 w.. -1,-1,0,"[G"{`39`}"MIC] Image" w1. -1,-1,0,"[G"{`39`}"MIC] Hough Transform" 29351 29352 do 29353 wait 29354 29355 if {*,b} # When clicking on the image. 29356 x0={{*,x}-{*,w}/2} 29357 y0={{*,y}-{*,h}/2} 29358 rho0={sqrt(($x0)^2+($y0)^2)} 29359 theta0={atan2($y0,$x0)} 29360 (0,{2*pi}) ($theta0,{$theta0-2*pi}) 29361 r[-2,-1] {-3,w},1,1,1,3 29362 cos. *. $rho0 +<. 0 abs.. 29363 *. {pi} +[-3,-1] %.. {2*pi} 29364 *.. {0.5*{-3,w}/pi} *. {{-3,h}/$rhomax} 29365 a[-2,-1] y 29366 repeat w point.. {i($>,0)},{i($>,1)},0,0.3,255 done 29367 rm. w1. 29368 29369 elif {*1,x}>=0" && "{*1,b} # When clicking on the vote window. 29370 theta={{*1,x}*2*pi/{*1,w}} 29371 rho={{*1,y}*$rhomax/{*1,h}} 29372 x={{-2,w}/2+$rho*cos($theta)} 29373 y={{-2,h}/2+$rho*sin($theta)} 29374 x0={$x+1000*sin($theta)} 29375 y0={$y-1000*cos($theta)} 29376 x1={$x-1000*sin($theta)} 29377 y1={$y+1000*cos($theta)} 29378 .. 29379 line. $x0,$y0,$x1,$y1,1,0x0F0F0F0F,255 29380 line. {$x0+1},$y0,$x1,$y1,1,0x0F0F0F0F,255 29381 line. $x0,{$y0+1},$x1,$y1,1,0x0F0F0F0F,255 29382 line. $x0,$y0,$x1,$y1,1,0xF0F0F0F0,0 29383 line. {$x0+1},$y0,$x1,$y1,1,0xF0F0F0F0,0 29384 line. $x0,{$y0+1},$x1,$y1,1,0xF0F0F0F0,0 29385 w. rm. 29386 29387 elif {*,SPACE}" || "{*1,SPACE} 29388 rm. +b. 1.5 hough. 512,400 b. 0.5 +. 1 log. n. 0,255 29389 w1. -1,-1,0,"Hough Transform" 29390 29391 elif {*,r} w.. 29392 elif {*1,r} w1. 29393 fi 29394 29395 while {*}" && "{*1}" && "!{*,ESC}" && "!{*,Q}" && "!{*1,ESC}" && "!{*1,Q} 29396 w 0 w1 0 29397 rm. endl 29398 if !{*}" || "!{*1} break fi 29399 done rm 29400 29401#@cli x_jawbreaker : 0<_width<20,0<_height<20,0<_balls<=8 29402#@cli : Launch the Jawbreaker game. 29403x_jawbreaker : check "${1=12}>0 && $1<20 && ${2=13}>0 && $2<20 && ${3=5}>0 && $3<=8" check_display $0 29404 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29405 e[] "\n 29406------ "${g}"Jawbreaker"$n" --------------------------------------------\n 29407----\n 29408---- The goal of the game is to "${c}"remove the maximum number of\n 29409---- balls on the board"$n", simply by clicking on them. But a\n 29410---- colored ball can disappear only if it is grouped with at\n 29411---- least one ball of the same color. The score is higher if\n 29412---- you destroy larger sets of connected colored balls.\n 29413----\n 29414---- "${c}"Left mouse button"$n" to select/destroy balls on board.\n 29415---- Key '"${c}"BACKSPACE"$n"' or '"${c}"SPACE"$n"' to undo the last move.\n 29416---- Key '"${c}"S"$n"' to save snapshot of the current view.\n 29417---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29418----\n 29419--------------------------------------------------------------" 29420 29421 # Init images and variables. 29422 $1,$2 nm. board rand[board] 1,$3 round[board] 1 29423 . nm. undo 29424 40,40,1,4 nm. balls _x_jawbreaker_ball. 29425 autocrop. 0 expand_xy. 1,0 *. 1.5 c. 0,255 r. {{board,w}*w},{{board,h}*h},1,1,0,2 /. 255 29426 {w},{h},1,3 nm. back l. 29427 rand 0,255 blur_xy 6,20 equalize 100,0,255 blur_xy 2,4 29428 sh 0 sh.. 1 sh... 2 /... 4 /.. 8 /. 2 rm[-3--1] 29429 endl 29430 [back] nm. visu 29431 score=0 29432 undoscore=0 29433 render_board=1 29434 shapescorey=0 29435 shapescore=0 29436 29437 # Enter user-event loop. 29438 do 29439 29440 # Render board graphics. 29441 if $render_board 29442 +abs[board] -. 1 *. {360/$3} +>=[board] 0 *. 0.9 +!=[board] 0 29443 ri[-3--1] [balls] [balls] *[-2,-1] a[-3--1] c hsv2rgb. 29444 +compose_channels. + >. 0 dilate. 3 29445 j[visu] [back] j[visu] ..,0,0,0,0,1,. rm[-2,-1] 29446 if !$shapescorey w[visu] {back,w},{back,h},0,"[G"{`39`}"MIC] Jawbreaker (Score : "$score")" fi 29447 render_board=0 29448 fi 29449 29450 # Add shape score sprite if necessary. 29451 if $shapescorey 29452 +t[visu] "+"$shapescore,{*,x},{{*,y}-64+$shapescorey},32,{($shapescorey-1)/31},255 29453 shapescorey={max(0,$shapescorey-1)} 29454 w. {back,w},{back,h},0,"[G"{`39`}"MIC] Jawbreaker (Score : "$score")" rm. wait 25 29455 else wait fi 29456 29457 # Check for the end of the game. 29458 +f[board] "if(i,j(-1)==i || j(1)==i || j(0,1)==i || j(0,-1)==i,0)" 29459 if !is rm. break fi rm. 29460 29461 # Manage user-events 29462 if {*,r} render_board=1 # Will resize window to initial size, if resized. 29463 elif {*,S} o[visu] gmic_jawbreaker.png # Save snapshot if requested. 29464 elif {*,BACKSPACE}" || "{*,SPACE} # Manage undo move. 29465 abs[undo] j[board] [undo] 29466 score=$undoscore 29467 render_board=1 29468 29469 elif {*,x}>=0" && "{*,b} # Manage button click. 29470 29471 # Retrieve board coordinates. 29472 wait -1 29473 x={"int("{*,x}"*"{board,w}"/"{*,w}")"} 29474 y={"int("{*,y}"*"{board,h}"/"{*,h}")"} 29475 29476 # When selecting a ball -> display selection and init new shape score sprite. 29477 if {{board,i($x,$y)}>0} 29478 abs[board] flood[board] $x,$y,0,0,0,1,-{board,i($x,$y)} 29479 +>=[board] 0 -. 1 29480 shapescore={(is+1)^2} shapescorey={if($shapescore,32,0)} rm. 29481 29482 # When confirming selection of a ball -> remove set of connected balls. 29483 elif {board,i($x,$y)} 29484 29485 +flood[board] $x,$y,0,0,0,1,-1 ==. -1 29486 if is>1 # If selected ball is connected to at least one ball. 29487 29488 # Save undo state. 29489 j[undo] [board] 29490 undoscore=$score 29491 29492 # Manage board shifts (vertical and horizontal). 29493 flood[board] $x,$y,0,0,0,1,0 29494 repeat w#$board 29495 +columns[board] $> mirror. y 29496 h={board,h} l. s -,0 a y if $! r 1,$h,1,1,0 mirror y else i 1,$h fi endl 29497 j[board] .,$> rm. 29498 done 29499 rows[board] -1,100% f[board] "if(y==0,if(i(x,h-1),x,w),i)" sort[board] +,x rows[board] 1,100% 29500 29501 # Update score. 29502 score+={int((is-1)^2)} 29503 29504 fi 29505 rm. # Remove selection mask. 29506 29507 else abs[board] # Remove previous selection if clicked outside balls. 29508 fi 29509 29510 render_board=1 29511 fi 29512 29513 while {*}" && "!{*,Q}" && "!{*,ESC} 29514 29515 # Game over. 29516 if {*}" && "!{*,ESC} 29517 w[] {visu,w},{visu,h},0,"[G"{`39`}"MIC] Jawbreaker (Final Score : "$score")" 29518 260,85 nm. gameover t. "Game Over!",3,0,53,1,1 t. "Score : "$score,23,53,32,1,1 29519 +dilate. 5 nm. "mgameover" *.. 255 r.. 100%,100%,1,3 29520 repeat 25 29521 +r[gameover,mgameover] {400-12*($>+1)}%,{400-12*($>+1)}% 29522 +j[visu] ..,{({visu,w}-w)/2},{({visu,h}-h)/2},0,0,{$>/25},. 29523 w. rm[-3--1] wait 25 29524 done 29525 do 29526 wait if {*,r} w[] {*,w},{*,h} wait -1 fi 29527 while {*}" && "!{*,Q}" && "!{*,ESC}" && "!{*,b} 29528 rm[gameover,mgameover] 29529 fi 29530 29531 # End properly. 29532 rm[board,undo,balls,back,visu] 29533 w 0 29534 29535_x_jawbreaker_ball : 29536 mwh={min(w,h)} 29537 sh 3 f. 0 rm. 29538 ellipse {0.5*$mwh},{0.5*$mwh},{0.5*$mwh-4},{0.5*$mwh-4},0,1,240,240,240,1 29539 sh 0,2 *. '($mwh+y-x)/(2*w)' rm. 29540 sh 3 *.. . dilate. 5 rm. 29541 sh 0,2 +. 'if(i&&(!j(-1)||!j(1)||!j(0,-1)||!j(0,1)),240/6,0)' rm. 29542 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 29543 29544#@cli x_landscape 29545#@cli : Launch the virtual landscape demo. 29546x_landscape : check_display $0 29547 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29548 e[] "\n 29549------ "${g}"Virtual landscape"$n" -------------------------------------\n 29550----\n 29551---- Enjoy the view!\n 29552----\n 29553---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 29554---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 29555---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29556----\n 29557--------------------------------------------------------------" 29558 l[] 29559 W=150 H=350 29560 29561 # Generate global map + colors. 29562 900,900 plasma. 1,1,6 b. 0.07% n. 0,255 nm. map 29563 +g. *. 0.5 +[-2,-1] n. 0,1 ^. 2 n. -150,330 29564 equalize[map] 256 n[map] -400,160 c[map] 0,100% # Add water. 29565 (0,102,51;149,175,124;102,42,0;255,255,255) permute. yzcx srgb2rgb. r. 256,1,1,3,3 rgb2srgb. 29566 +n[map] 0,255 map. .. rm.. 29567 +. .. rm.. c. 0,255 nm. colors # Colors. 29568 29569 # Pre-compute some images used on each frame. 29570 $W,$H,1,1,'x' y. x nm. x # Increasing x. 29571 $W,$H,1,1,'1+x+y*w' y. x nm. offsets # Offsets (+1). 29572 $W,$H,1,1,'0.5*y' nm. gmap Mgmap={iM} # Z-increment for altitude map. 29573 $W,$H,1,3 fc. 60,80,135 nm. ccolors # Color for the horizon. 29574 $W,$H,1,1,'(y/$H)^2' nm. mcolors # Mask for the horizon. 29575 $W,400,1,1,'b=h-1-$Mgmap;if(y>=b,256+(y-b)*255/(h-1-b),y*255/b)' round. # Background. 29576 29577 (96^16^128) (0^200^255) a[-2,-1] x r. 256,1,1,3,3 29578 (0^32^0) (0^64^128) a[-2,-1] x r. 256,1,1,3,3 29579 a[-2,-1] x map.. . rm. 29580 29581 nm. background 29582 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. 29583 (64^16^0) r. $W nm. groundcolor # Ground color. 29584 29585 # Start animation. 29586 w[] 600,400,0,"[G"{`39`}"MIC] Virtual Landscape" 29587 do 29588 29589 # Get part of the map to display. 29590 t={$|*0.03} 29591 xm={map,w/2+(w-$H/2)/2*cos(3.1*$t)} 29592 ym={map,h/2+(h-$H/2)/2*sin(2.8*$t)} 29593 u={map,(w-$H/2)*cos(2.5*$t)} 29594 v={map,(h-$H/2)*sin(9.7*$t)} 29595 a={atan2($v,$u)*180/pi} 29596 +r3d[viewrange3d] 0,0,1,$a y. x 29597 ({$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.. 29598 r. $W,$H,1,2,3 +warp[map,colors] .,0,1,0 rm... 29599 nm.. lmap nm. lcolors 29600 29601 # Add color shading and altitude to local maps. 29602 +!=[lmap] 0 nm. ground 29603 +[lmap] [gmap] 29604 j[lcolors] [ccolors],0,0,0,0,1,[mcolors] 29605 j[lcolors] [groundcolor] 29606 +round[lmap] f. '>m=abs(j(0,-1));i>m?i:-m' nm. y0 # Compute visible top points. 29607 +shift. 0,1 abs. +. 1 nm. y1 # Compute visible bottom points. 29608 *[y0,y1] [ground] rm[ground] 29609 r[lcolors,y0,y1] {$W*$H},1,1,100%,-1 29610 29611 # Keep only visible primitives. 29612 +>[y0] 0 *. [offsets] discard. 0 y. 29613 if h # There is something to display (ground). 29614 -. 1 +warp[x] .,0,0,0 nm. lx 29615 warp[lcolors,y0,y1] ..,0,0,0 rm.. 29616 29617 # Generate 3D object. 29618 N={h} ({'CImg3d'},{2*$N},$N) 29619 +a[lx] [y0],x rm[y0] +a[lx] [y1],x rm[lx,y1] a[-2,-1] y z. 0,2 29620 1,$N,1,1,2 +f. y ++. $N a[-3--1] x 29621 mv[lcolors] $! permute. cyzx 29622 1,$N,1,1,1 29623 y[-5--1] y a[-5--1] y *3d. -1,-1 29624 +j3d[background] .,{background,w-1},{background,h},0,1,1,0,0,0 rm[-3,-2] 29625 else # Case of nothing to display (only water). 29626 rm[-5--1] [background] 29627 fi 29628 29629 r. {*,w},{*,h},1,3 29630 fps=${-fps} if $fps>0 to. $fps" fps",5,5,24,2,0.2 fi 29631 w. -1,-1,0 rm. 29632 if {*,CTRLLEFT}" && "{*,D} w[] 900,600 elif {*,CTRLLEFT}" && "{*,C} w[] 600,400 fi 29633 wait 20 29634 while {*}" && "!{*,ESC}" && "!{*,Q} 29635 rm w 0 endl 29636 29637#@cli x_life 29638#@cli : Launch the game of life. 29639x_life : check_display $0 29640 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29641 e[] "\n 29642------ "${g}"The game of life"$n" --------------------------------------\n 29643----\n 29644---- The goal is to create the "${c}"biggest possible biological\n 29645---- system"$n". You start with a stock of cells which you can\n 29646---- spread over the board. For each new cells created\n 29647---- simultaneously and spontaneously by your system, you\n 29648---- gain more new cells to scatter.\n 29649----\n 29650---- "${c}"Left mouse button"$n" to scatter cells in stock.\n 29651---- "${c}"Right mouse button"$n" to reset game.\n 29652---- Key '"${c}"S"$n"' to save snapshot of the current view.\n 29653---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29654----\n 29655--------------------------------------------------------------" 29656 29657 i[0] 90,90,1,1,0 # Image[0] = game state. 29658 i[1] [0] f[1] 0 # Image[1] = generation counter. 29659 i[2] 400,400,1,3 # Image[2] = visualization. 29660 i[3] 1 # Image[3] = colormap (to be initialized). 29661 iteration=0 # Iteration counter. 29662 score=0 # Current score. 29663 bestscore=0 # Best score. 29664 stock=500 # Remaining cells. 29665 w[0] 400,400,0,"[G"{`39`}"MIC] The Game of Life" # Initialize display window. 29666 cursor[0] 0 29667 29668 # Start user-event loop. 29669 do 29670 (1,1,1;1,0,1;1,1,1) +correlate[0] .,0 rm.. # Count numbers of neighboring living cells. 29671 +ir. 2,2 &. [0] ir.. 3,3 -|[-2,-1] # Make the game evolve (kill or create cells). 29672 rv[0,-1] # Update game state. 29673 if {*,x}>0" && "{*,b}==1" && "$stock>0 # Add random cells to the game if mouse button pressed. 29674 nb={u*7} 29675 repeat $nb 29676 x={{*,x}/{*,w}*{0,w}+u(-4,4)} 29677 y={{*,y}/{*,h}*{0,h}+u(-3,3)} 29678 =[0] 1,$x,$y 29679 =[1] $iteration,$x,$y 29680 point[2] {$x*{2,w}/{0,w}},{$y*{2,h}/{0,h}},0,0.8,255 29681 done 29682 stock={round(max(0,$stock-$nb))} 29683 fi 29684 29685 -. [0] *. -1 # Compute difference between consecutive states. 29686 stock-={2*(min(0,int(is/16*$score/150)))} # Increment available cells if the evolution is fast. 29687 +[1] [0] # Increment generation counter for still existing cells. 29688 min. 0 +. 1 *[1,-1] # Reset generation counter for died cells. 29689 29690 if {*,b}==2 # Reset game if right mouse button has been pressed. 29691 f[0-2] 0 iteration=0 score=0 bestscore=0 stock=500 rm[3] i[3] 1 29692 fi 29693 29694 if {3,w}==1 # Create color palette if necessary. 29695 rm[3] i[3] {u(3,12)},1,1,3,u(100,255) 29696 r[3] {u(100,300)}%,1,1,3,4 29697 point[3] 0,0,0,1,0 29698 r[3] {u(100,600)}%,1,1,3,5 c[3] 0,255 29699 fi 29700 29701 +r[1] {2,w},{2,h} &. 7 b. {1+$score*0.05} # Render colored image of the game and display it. 29702 n. 0,{3,w} map. [3] *. 0.1 +[2,-1] /[2] 1.1 29703 [2] if {*,x}>0 # Add a small target icon at the mouse position. 29704 opac={0.7*min(1,$stock/500)} r={min(500,$stock)*cos($iteration)/100} 29705 ellipse. {*,x},{*,y},{15+$r},{15+$r},0,$opac,0,196,0 29706 ellipse. {*,x},{*,y},{10+$r},{10+$r},0,$opac,32,64,16 29707 ellipse. {*,x},{*,y},{5+$r},{5+$r},0,$opac,255,230,0 29708 fi 29709 t. "Living cells : "$score"\n"\ # Add score description. 29710 "Stock : "$stock"\n"\ 29711 "Score : "$bestscore,5,3,22,0.7,255 29712 w. {*,w},{*,h} 29713 if {*,S} o. gmic_life.png fi # Save snapshot if requested. 29714 rm. 29715 29716 if !($iteration%10) # Re-compute current and best scores, every 10th iterations 29717 score={0,is} bestscore={max($score,$bestscore)} 29718 fi 29719 wait 60 29720 iteration+=1 29721 while {*}" && "!{*,ESC}" && "!{*,Q} 29722 29723 # End game and quit properly. 29724 rm[0-3] w 0 29725 29726#@cli x_light 29727#@cli : Launch the light effect demo. 29728x_light : check_display $0 29729 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29730 e[] "\n 29731------ "${g}"Light effect"$n" ------------------------\n 29732----\n 29733---- Move light position with "${c}"mouse"$n".\n 29734---- "${c}"Mouse buttons"$n" fade light in/out.\n 29735---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 29736---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 29737---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29738----\n 29739-------------------------------------------" 29740 29741 # Create warping and color images. 29742 0 t. " G\47MIC\nLight effect",0,0,80,1,255 expand_xy. 15,0 b. 3 29743 . n.. 0,1 r.. 100%,100%,1,3 29744 sh.. 0 *. 120 rm. 29745 sh.. 1 *. 70 rm. 29746 sh.. 0,50%,0,2 *. 120 rm. 29747 25%,25%,1,1 rand. -20,20 smooth. 10,0,1,1,4 ri. ..,3 b. 3 n. -100,100 29748 +[-2,-1] g. xy a[-2,-1] c n. -150,150 29749 w[] {1.5*{-2,w}},{1.5*{-2,h}},0,"[G"{`39`}"MIC] Light Effect" # Init display window. 29750 cursor[0] 0 29751 29752 # Create a large light image. 29753 light=70 29754 640,640 gaussian. $light n. 0,255 29755 t=0 29756 29757 # Start animation. 29758 do 29759 29760 # Manage light position and intensity. 29761 if {*,x}>=0 29762 X={round((w-{*,x})/2)} 29763 Y={round((h-{*,y})/2)} 29764 else 29765 X={round((w-{-2,w}*(1+cos(2*$t)))/2)} 29766 Y={round((h-{-2,h}*(1+sin(2.5*$t)))/2)} 29767 t+=0.02 29768 fi 29769 if {*,b}&1 light={min(200,$light+10)} gaussian. $light n. 0,255 fi 29770 if {*,b}&2 light={max(10,$light-10)} gaussian. $light n. 0,255 fi 29771 29772 # Render lightened image. 29773 +z. $X,$Y,{$X+{-2,w}-1},{$Y+{-2,h}-1} 29774 warp. ...,1,0,1 29775 r. 100%,100%,1,3 +. [-4] c. 0,255 29776 fps=${-fps} if $fps>0 to. $fps" fps",5,5,16,1,0.2 fi 29777 w. 29778 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 29779 rm. if {*,x}>=0" && "!{*,b} wait else wait 20 fi 29780 while {*}" && "!{*,ESC}" && "!{*,Q} 29781 w[] 0 rm[-3--1] 29782 29783#@cli x_mandelbrot : _julia={ 0 | 1 },_c0r,_c0i 29784#@cli : Launch Mandelbrot/Julia explorer. 29785x_mandelbrot : skip ${1=0},${2=0.317},${3=0.03} check_display $0 29786 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29787 e[] "\n 29788------ "${g}"Mandelbrot/Julia explorer"$n" -----------------\n 29789----\n 29790---- Select zooming region with "${c}"mouse"$n".\n 29791---- "${c}"Click once"$n" to reset zoom factor.\n 29792---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29793---- Key '"${c}"C"$n"' to print current fractal coordinates.\n 29794----\n 29795--------------------------------------------------" 29796 29797 # Init variables and display. 29798 rm w 512,512,0 _x_mandelbrot_coords $1 _x_mandelbrot_palette 29799 29800 # Start event loop. 29801 do 29802 siz={min({*,w},{*,h})} # Desired window dimension. 29803 $siz,$siz mandelbrot. {0,^},256,$1,{if($1,$2,0)},{if($1,$3,0)} map. [1] # Render fractal. 29804 if $1 w. $siz,$siz,0,"[G"{`39`}"MIC] Julia Set c=("{0,@0-1}")-("{0,@2-3}"), c0=($2,$3)" # Display on window. 29805 else w. $siz,$siz,0,"[G"{`39`}"MIC] Mandelbrot Set c=("{0,@0-1}")-("{0,@2-3}")" fi 29806 w={w} h={h} round. select. 2,0,0,0,1 # Get the user selection. 29807 if i[0]>0 # If valid selection found. 29808 M={max(i[3]-i[0],i[4]-i[1])} # Compute max dimension of selected rectangle. 29809 if $M<5 _x_mandelbrot_coords $1 rm[1] _x_mandelbrot_palette mv. 1 # If selection too small, reset the view, 29810 else ({{0,@0}+{@0}*({0,@2}-{0,@0})/$w};\ # Else compute new fractal coordinates. 29811 {{0,@1}+{@1}*({0,@3}-{0,@1})/$h};\ 29812 {{0,@0}+({@0}+$M)*({0,@2}-{0,@0})/$w};\ 29813 {{0,@1}+({@1}+$M)*({0,@3}-{0,@1})/$h}) 29814 fi 29815 rm[0] mv. 0 # Validate new coordinates. 29816 fi 29817 rm. # Delete latest rendering. 29818 if {*,C} # If 'C' key has been pressed. 29819 if $1 e[] "Julia set, at c = ("{0,@0-1}")-("{0,@2-3}"), with c0 = ($2,$3)." 29820 else e[] "Mandelbrot set, at c = ("{0,@0-1}")-("{0,@2-3}")." 29821 fi 29822 fi 29823 if !{*}" || "{*,ESC}" || "{*,Q} break fi 29824 wait -1 29825 while 1 rm w 0 29826 29827_x_mandelbrot_coords : 29828 if $1 (-2;-2;2;2) else (-2.1;-1.5;1.2;1.5) fi 29829 29830_x_mandelbrot_palette : 29831 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 29832 29833#@cli x_mask_color : _colorspace={ all | rgb | lrgb | ycbcr | lab | lch | hsv | hsi | hsl | cmy | cmyk | yiq },\ 29834# _spatial_tolerance>=0,_color_tolerance>=0 29835#@cli : Interactively select a color, and add an alpha channel containing the corresponding color mask. 29836#@cli : Argument 'colorspace' refers to the color metric used to compute color similarities, and can be basically 29837#@cli : one of { rgb | lrgb | ycbcr | lab | lch | hsv | hsi | hsl | cmy | cmyk | yiq }. 29838#@cli : You can also select one one particular channel of this colorspace, by setting 'colorspace' as 29839#@cli : 'colorspace_channel' (e.g. 'hsv_h' for the hue). 29840#@cli : Default values: 'colorspace=all', 'spatial_tolerance=5' and 'color_tolerance=5'. 29841x_mask_color : check "${2=5}>=0 && ${3=5}>=0" skip ${1=all} check_display $0 29842 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29843 e[^-1] "Interactively create color mask for image$?, with color space $1, spatial tolerance $2 and 29844 color tolerance $3." 29845 e[] "\n 29846----------------------------------------------------------------------------------------------------\n 29847----\n 29848---- "${c}"Left mouse button"$n" adds a wanted color to the selection.\n 29849---- "${c}"Right mouse button"$n" adds an unwanted colors to the selection.\n 29850---- "${c}"Middle mouse button"$n" or key '"${c}"R"$n"' resets color mask.\n 29851---- Key '"${c}"SPACE"$n"' or '"${c}"TAB"$n"' toggles view modes (masked RGB or mask).\n 29852---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 29853---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 29854---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 29855---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' exit the interactive window.\n 29856----\n 29857----------------------------------------------------------------------------------------------------" 29858 l[] _ac_$1 onfail error[0--3] "Command '$0' : Invalid colorspace '$*'." endl 29859 m _ac_forward:$_f 29860 repeat $! l[$>] slices 0 basename {0,n} nm=${} 29861 wh=${fitscreen\ {[w,h,1]},128,1024} 29862 +r $wh,1,100%,2 29863 +_ac_forward. channels. $_s 29864 if {1,s>3} channels[1] 0,2 fi to_rgb[1] 29865 29866 w[1] 100%,100%,0,$nm 29867 colors_add=-1 colors_sub=-1 visumode=0 29868 is_clicked=0 time=0 delay=0.1 29869 do 29870 29871 # Manage user events. 29872 time={$is_clicked?$time:$|} 29873 wait 29874 x={2,round({*,x}*(w-1)/({*,w}-1))} 29875 y={2,round({*,y}*(h-1)/({*,h}-1))} 29876 b={*,b} 29877 c=$x,$y,{2,I($x,$y)} 29878 is_add={arg(1,$colors_add)>=0} 29879 is_sub={arg(1,$colors_sub)>=0} 29880 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 29881 is_resized=0 29882 refresh=0 29883 29884 if $x>=0" && "$b&1 # Add a color 29885 if $is_add colors_add=$colors_add,$c else colors_add=$c fi 29886 is_clicked=1 29887 refresh={$|-$time>$delay} 29888 elif $x>=0" && "$b&2 # Subtract a color 29889 if $is_sub colors_sub=$colors_sub,$c else colors_sub=$c fi 29890 is_clicked=1 29891 refresh={$|-$time>$delay} 29892 elif $b&4" || "{*,R} # Reset colors 29893 colors_add=-1 colors_sub=-1 refresh=1 is_clicked=1 29894 elif !$b 29895 refresh={$is_clicked==1} 29896 is_clicked=0 29897 fi 29898 if {*,-TAB}" || "{*,-SPACE} visumode={($visumode+1)%3} refresh=1 fi # Change visu mode 29899 if {*,r} is_resized=1 29900 elif $is_ctrl" && "{*,-D} w[] {1,1.25*[w,h]} is_resized=1 29901 elif $is_ctrl" && "{*,-C} w[] {1,0.8*[w,h]} is_resized=1 29902 elif $is_ctrl" && "{*,R} w[] ${fitscreen\ {0,[w,h,1]},128,1024} is_resized=1 29903 fi 29904 if $is_resized rm[1,2] +r {*,d},{*,e},1,3,2 +_ac_forward. channels. $_s refresh=1 fi 29905 29906 # Refresh view. 29907 if $refresh 29908 _x_mask_color[2] {$2*w#2/w#0},$3,{``$colors_add},{``$colors_sub} delay=${} 29909 if $visumode==0 +. 64 c. 0,255 +a[1,-1] c drgba. w. -1,-1,$nm" [half-masked]" rm. 29910 elif $visumode==1 +a[1,-1] c drgba. w. -1,-1,$nm" [masked]" rm. 29911 else w. -1,-1,$nm" [mask]" 29912 fi 29913 rm. 29914 time=$| 29915 fi 29916 29917 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,ENTER} 29918 29919 # Rescale to original image dimensions. 29920 if arg(1,$colors_add)>=0 ($colors_add) 29921 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)}' 29922 j.. . colors_add={-2,^} rm[-2,-1] 29923 fi 29924 if arg(1,$colors_sub)>=0 ($colors_sub) 29925 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)}' 29926 j.. . colors_sub={-2,^} rm[-2,-1] 29927 fi 29928 rm[-2,-1] +_ac_forward channels. $_s 29929 _x_mask_color. $2,$3,{``$colors_add},{``$colors_sub} 29930 rm.. a c 29931 29932 endl done 29933 um _ac_forward 29934 29935_x_mask_color : # Estimate color mask image. 29936 100%,100% 29937 is_add={arg(1,$3)>=0} 29938 is_sub={arg(1,$4)>=0} 29939 t0=$| 29940 if $is_add" || "$is_sub 29941 if $is_add 29942 ($3) r. {2+s#0},{w/(2+s#0)},1,1,-1 29943 N_add={h} M_add={"M = vectorw(); fill(M,k,med(crop(k,1)));M"} rm. 29944 fi 29945 if $is_sub 29946 ($4) r. {2+s#0},{w/(2+s#0)},1,1,-1 29947 N_sub={h} M_sub={"M = vectorw(); fill(M,k,med(crop(k,1)));M"} rm. 29948 fi 29949 f. "begin( 29950 invert(A,nA) = inv(A,nA); # For <v.2.9.2 29951 const is_add = "$is_add"; 29952 const is_sub = "$is_sub"; 29953 const ss = sqrt(2)*$1; 29954 const sc = sqrt(2)*$2; 29955 colors_add = [ $3 ]; 29956 colors_sub = [ $4 ]; 29957 M_add = [ 0"$M_add"]; 29958 M_sub = [ 0"$M_sub"]; 29959 const N_add = 0"$N_add"; 29960 const N_sub = 0"$N_sub"; 29961 const siz = 2 + s#0; 29962 const siz2 = sqr(siz); 29963 sigma = vectorsiz(sc); 29964 sigma[0] = sigma[1] = ss; 29965 29966 tensor(op) = ( 29967 T = vectorsiz2(); 29968 if (is_#op, 29969 for (k = 0, k<size(colors_#op), k+=siz, C = colors_#op[k,siz]-=M_#op; C*=sigma; T+=mul(C,C,siz)); 29970 T/=1e-8 + N_#op; 29971 T+=eye(siz); 29972 T = invert(T); 29973 ); T 29974 ); 29975 29976 T_add = tensor(add); 29977 T_sub = tensor(sub); 29978 ); 29979 P = [ x,y,I#0 ]; 29980 pot_add = is_add?(C = P - M_add; exp(-dot(C,T_add*C))):1; 29981 pot_sub = is_sub?(C = P - M_sub; exp(-dot(C,T_sub*C))):0; 29982 pot_add - pot_sub" 29983 c. 0,1 n. 0,512 c. 0,255 29984 else f. 255 29985 fi 29986 u {$|-$t0} 29987 29988#@cli x_metaballs3d 29989#@cli : Launch the 3D metaballs demo. 29990x_metaballs3d : check_display $0 29991 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 29992 e[] "\n 29993------ "${g}"3D metaballs"$n" ---------------------------------------\n 29994----\n 29995---- "${c}"Mouse button"$n" or '"${c}"SPACE"$n"' key to toggle rendering mode.\n 29996---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 29997---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 29998---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 29999----\n 30000-----------------------------------------------------------" 30001 l[] 30002 100,100 noise. 100,1 plasma. 1,0,10 r. 512,320,1,3 n. 0,1 b. 4,0 n. 0,255 30003 mix_channels. (0.7,0,0;0,0.9,0;0,0,1.2) c. 0,255 l3d 30004 0 30005 24,24,24,1,'X=x-w/2;Y=y-h/2;Z=z-d/2;exp(-(X*X+Y*Y+Z*Z)/100)' 30006 72,72,72 M=8 mode=3 30007 s0=Dots s1=Wireframe s2=Flat s3=Flat-shaded s4=Gouraud-shaded s5=Phong-shaded 30008 repeat $M fx$>={2*g} fy$>={2*g} fz$>={2*g} done 30009 w[0] -1,-1,0,"[G"{`39`}"MIC] 3D Metaballs" 30010 do 30011 repeat $M 30012 x$>={w/2+0.5*(w-{2,w}-4)*cos(${fx$>}*$|)} 30013 y$>={h/2+0.5*(h-{2,h}-4)*sin(${fy$>}*$|)} 30014 z$>={d/2+0.5*(d-{2,d}-4)*sin(${fz$>}*$|)} 30015 done 30016 f[3] 0 repeat $M j[3] [2],{${x$>}-{2,w/2}},{${y$>}-{2,h/2}},{${z$>}-{2,d/2}},0,-1 done 30017 +r[3] 28,28,28,1,2 isosurface3d. 0.4 -3d. 12,12,12 *3d. 13 rv3d. 30018 r3d. 1,2,1,{100*$|} 30019 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. 30020 if !$mode circles3d.. 4 fi 30021 if !{1,w} 30022 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 30023 +dilate. 3 +j[0] ..,5,3,0,0,1,.,255 mv. 1 rm[2,-2,-1] 30024 fi 30025 +j3d[1] ..,50%,50%,0,1,{if(!$mode,3,$mode)},0,0,300,0,0,-500,0.1,1.5 30026 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-22},16,2,0.2 fi 30027 w. 30028 if {*,CTRLLEFT}" && "{*,D} w[] {2*w},{2*h} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 30029 rm[-3--1] wait 20 30030 if {*,b}" || "{*,SPACE} mode={($mode+if({*,b}&2,-1,1))%6} wait -1 rm[1] i[1] 0 fi 30031 while {*}" && "!{*,ESC}" && "!{*,Q} 30032 rm w 0 endl 30033 30034#@cli x_minesweeper : 8<=_width=<20,8<=_height<=20 30035#@cli : Launch the Minesweeper game. 30036x_minesweeper : check "${1=20}>=8 && $1<=30 && ${2=$1}>=8 && $2<=30" check_display $0 30037 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30038 e[] "\n 30039------ "${g}"Minesweeper"$n" -------------------------------------------\n 30040----\n 30041---- The goal is to "${c}"clear the minefield"$n" without detonating a\n 30042---- mine.\n 30043----\n 30044---- "${c}"Left mouse button"$n" to try clearing one square.\n 30045---- "${c}"Right mouse button"$n" to flag or unflag a square.\n 30046---- "${c}"Middle mouse button"$n" to reset mine field.\n 30047---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30048----\n 30049--------------------------------------------------------------\n" 30050 30051 # Generate random mine field and player board. 30052 # Labels : 0=mine, 1=empty, 2='1-near', 3='2-near', ..., 9='8-near', 10=still unknown. 30053 $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 30054 do x={round(u(w-1))} y={round(u(h-1))} while i($x,$y)!=1 # Find a good starting point. 30055 +f[field] 11 =. 12,$x,$y nm. board 30056 30057 # Generate sprite graphics. 30058 24,24,1,3,200 fc. 255,180,130 30059 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 30060 z. 1,1,{w-2},{h-2} frame. 1,1,0 30061 +fc. 230,250,255 30062 +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 30063 +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 30064 +t[-7] "7",9,5,13,1,128,0,0 +t[-8] "8",9,5,13,1,64,0,0 30065 +f. 'if(x<=1||y<=1||x>=w-2||y>=h-2,if(x<y,128,255),160+2*(y+x))' 30066 +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 30067 rv[-2,-1] 30068 . 100%,100%,1,3 line. 6,14,10,18,1,0,200,0 line. 10,18,16,6,1,0,200,0 dilate. 2 30069 +channels. 1 n. 0,0.7 dilate. 3 j... ..,0,0,0,0,1,. rm[-2,-1] 30070 a[-13--1] x nm. sprites 30071 30072 # Pre-calculate offsets and canvas for faster board rendering. 30073 (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 30074 .,.,1,3,255 frame. 1,1,0 frame. 23,23,255 30075 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. 30076 nm. canvas 30077 30078 # Start user interaction loop. 30079 failed=0 succeeded=0 nb_flags=0 started=0 30080 do 30081 30082 # Render board. 30083 +*[board] 24 r. [offsets],[offsets] channels. 0,1 +. [offsets] +warp[sprites] .,0,0 rm.. 30084 j[canvas] .,24,24 rm. 30085 30086 # Wait for user's selection. 30087 wait -1 30088 if $failed 30089 0 t. "Game\nOver!",3,3,38,1,255 r. 100%,100%,1,4 sh. 3 dilate. 5 /. 2 rm. 30090 drop_shadow. 5,5,1 blend[canvas,-1] alpha 30091 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. 30092 do w[canvas] {w},{h} wait while {*}" && "!{*,ESC}" && "!{*,Q} 30093 elif $succeeded 30094 0 t. "Success!",3,3,38,1,255 r. 100%,100%,1,4 sh. 3 dilate. 5 /. 2 rm. 30095 drop_shadow. 5,5,1 blend[canvas,-1] alpha 30096 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 30097 negate. j[canvas] .,0,3 rm. 30098 do w[canvas] {w},{h} wait while {*}" && "!{*,ESC}" && "!{*,Q} 30099 else 30100 +==[board] 10 nb_flags={is} rm. 30101 do 30102 if !$started tic=$| fi 30103 0 t. "Elapsed time : "{round($|-$tic)}" s / Flags : "$nb_flags,0,0,18,1,255,200,0 30104 r. {canvas,w},100%,1,3,0,0,0.5,0.5 30105 negate. j[canvas] .,0,3 rm. 30106 wait 50 30107 x={int(({*,x}-24)/24)} y={int(({*,y}-24)/24)} b={*,b} 30108 w[canvas] {w},{h},0,"[G"{`39`}"MIC] Minesweeper" 30109 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!$b 30110 fi 30111 30112 # Manage selected square. 30113 if $x>=0\ &&\ $y>=0\ &&\ $x<{board,w}\ &&\ $y<{board,h} 30114 if $b&1 # Try to clean square. 30115 started=1 val={field,i($x,$y)} 30116 if $val==0 +==[field] 0 j[board] [field],0,0,0,0,1,. rm. failed=1 # Found a mine -> boom! 30117 elif $val==1 # Found an empty area 30118 +flood[field] $x,$y,0,0,1,1,-1 ==. -1 dilate. 3 j[board] [field],0,0,0,0,1,. rm. 30119 else =[board] $val,$x,$y # Close to one or several mines 30120 fi 30121 elif n={board,i($x,$y)};$b&2" && "n>=10" && "n<=11 30122 =[board] {if({board,i($x,$y)}==11,10,11)},$x,$y # Flag or unflag a square. 30123 elif $b&4 f[board] 10 # Reset minefield. 30124 fi 30125 fi 30126 30127 if $nb_mines==$nb_flags\ &&\ {board,iM}!=11 succeeded=1 fi # Check if board is cleared. 30128 while {*}" && "!{*,ESC}" && "!{*,Q} 30129 w 0 30130 30131#@cli x_minimal_path 30132#@cli : Launch the minimal path demo. 30133x_minimal_path : check_display $0 30134 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30135 e[] "\n 30136------ "${g}"Minimal path"$n" ------------------------------------------\n 30137----\n 30138---- "${c}"Click on two points"$n" to compute and display the minimal\n 30139---- path between those points. The ending point is then\n 30140---- chosen as the next starting point for another path.\n 30141---- Key '"${c}"S"$n"' to save snapshot of the current view.\n 30142---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30143----\n 30144--------------------------------------------------------------" 30145 30146 if !$! sp ? fi 30147 n 0,200 round 1 30148 repeat $! l[$>] 30149 w[0] -1,-1,0,"[G"{`39`}"MIC] Select Starting Point P0" 30150 30151 if !narg($first_time) 30152 parallel 0,"+l[0] r2dy 128 frame 1,1,0 \ 30153 alert \"[G"{`39`}"MIC Minimal Path]\",\ 30154 \"The G\47MIC minimal path demo illustrates how minimal paths\n\ 30155 can be computed in images to detect and track edge points.\n\ 30156 Use your mouse to select desired starting and ending points,\n\ 30157 and see what is the minimal path computed between these points.\",\ 30158 \"OK\" \ 30159 rm endl" 30160 first_time=0 30161 fi 30162 30163 +gradient_norm b. 1 f. exp(-i/10) 30164 to_rgb[0] +select[0] 0 P0={^} 30165 ellipse[0] {@0,1},3,3,0,1,255,0,255 30166 ellipse[0] {@0,1},3,3,0,1,0xFFFFFFFF,255,255,255 30167 rm. 30168 if min($P0)>=0 30169 p=1 30170 do 30171 w[0] -1,-1,0,"[G"{`39`}"MIC] Select Ending Point P"$p 30172 +select[0] 0 30173 if {*,S} 30174 rm. 30175 +to[0] "Saving snapshot...",5,5,13,1,1,255,255,255 w. rm. 30176 o[0] gmic_minimal_path.png 30177 wait -1 30178 else 30179 P1={^} 30180 ellipse[0] {@0,1},3,3,0,1,255,0,255 30181 ellipse[0] {@0,1},3,3,0,1,0xFFFFFFFF,255,255,255 30182 rm. 30183 if min($P1)>=0 30184 +to[0] "Processing...",5,5,13,1,1,255,255,255 w. rm. 30185 +minimal_path[1] $P0,$P1,1 30186 pointcloud. 0 *. 255 r. 100%,100%,1,[0],0,0,0,0,0,0.5 ri. [0],0 -|[0,-1] 30187 P0=$P1 p+=1 30188 fi 30189 fi 30190 while {*}" && "!{*,ESC}" && "!{*,Q} 30191 fi 30192 rm[1] w 0 30193 endl done 30194 30195#@cli x_morph : _nb_frames>=2,_preview_fidelity={ 0=coarsest | 1=coarse | 2=normal | 3=fine | 4=finest } 30196#@cli : Launch the interactive image morpher. 30197#@cli : Default values: 'nb_frames=16' and 'preview_fidelity=3'. 30198x_morph : check "isint(${1=16}) && isint(${2=3}) && $2>=0 && $2<=4" check_display $0 30199 if $!<2 error[0--3] "Command '$0': Requires at least two input images!" return fi 30200 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r b=$_vt100_b 30201 e[] "\n 30202------ "${g}"Interactive image morpher"$n" ---------------------------\n 30203----\n 30204---- "${b}"Source/target window:"$n"\n 30205---- "${c}"Left mouse button"$n": Add new keypoint on current image\n 30206---- and move it on the other one.\n 30207---- "${c}"Right mouse button"$n": Add/move keypoint on current image.\n 30208---- Key '"${c}"DELETE"$n"' or "${c}"middle mouse button"$n": Delete keypoint.\n 30209---- Key '"${c}"SPACE"$n"' or "${c}"mouse wheel"$n": Toggle source/target.\n\n 30210---- "${b}"In-between window:"$n"\n 30211---- "${c}"Mouse wheel"$n": Change morphing time, from 0 to 1.\n 30212---- "${c}"Left mouse button"$n": Reset morphing time to 0.5.\n\n 30213---- "${b}"Both windows:"$n"\n 30214---- Key '"${c}"TAB"$n"': Change keypoint radius.\n 30215---- Key '"${c}"ENTER"$n"': Play/stop in-between animation.\n 30216---- Key '"${c}"R"$n"': Reset keypoints.\n 30217---- Key '"${c}"K"$n"': Show/hide keypoints.\n 30218---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"': Process fullres and exit.\n 30219----\n 30220-----------------------------------------------------------" 30221 30222 offset=0 30223 radius_keypoints=3 30224 repeat $!-1 l[{[$>,$>+1]+$offset}] nm0={0,n} nm1={1,n} 30225 to_colormode 0 30226 rr2d ${-max_wh},2 30227 nm img0,img1 30228 256,1,1,1,"x>=4?x-2:1" map. 2 nm. colormap 30229 30230 # Start interactive window. 30231 selected_keypoint=-1 30232 view_keypoints=1 30233 time_inbetween=0.5 30234 animate_inbetween=0 30235 move_other=0 30236 frame=0 30237 30238 do 30239 # Generate set of keypoints (x0,y0,x1,y1,index_color) 30240 if !narg($keypoints) 30241 if narg($__x_morph_keypoints) ($__x_morph_keypoints) r. 1,{w/5},1,5,-1 30242 else 1,4,1,5,"p = y%2; q = int(y/2); [ [ p,q,p,q ]*100,y ]" 30243 fi 30244 N0={h} nm. keypoints 30245 rmn warp0,warp1 30246 fi 30247 30248 # Generate base images. 30249 if !narg($imgb0)" || "!narg($imgb1) 30250 if {*} wdims=${"fitscreen "{*,d},{img0,{*,d}*h/w}} 30251 else wdims=${"fitscreen "{img0,[w,h,1]},128,50%} 30252 fi 30253 w[] $wdims,0,"[G'MIC] Interactive Morph" 30254 repeat 2 +to_color[img$>] r. $wdims,1,100%,2 n. 0,255 nm. imgb$> done 30255 rmn imgr,warp0,warp1 30256 fi 30257 30258 # Generate warp fields. 30259 if (!narg($warp0)" || "!narg($warp1)) 30260 subsamp={arg(1+$2,8,6,4,2,1)} 30261 +_x_warp_rbf[keypoints] {imgb0,round([w,h]/$subsamp)} 30262 +l[keypoints] s c,-2 rv[0,1] a c endl +_x_warp_rbf. {imgb0,round([w,h]/$subsamp)} rm.. 30263 *[-2,-1] $subsamp 30264 r[-2,-1] {imgb0,[w,h]},1,100%,3 30265 nm[-2,-1] warp0,warp1 30266 rmn imgm 30267 fi 30268 30269 # Render visualization. 30270 if !narg($imgr) 30271 [imgb$frame] nm. imgr 30272 if s==4 drgba. fi 30273 if $view_keypoints 30274 eval[keypoints] "* 30275 begin( 30276 fact = ([ w#"$imgb0",h#"$imgb0" ] - 1)/100; 30277 const radius1 = "$radius_keypoints"; 30278 const radius2 = radius1 + 2; 30279 const opacity = min(1,3/"($radius_keypoints-1)"); 30280 ); 30281 X = round((I)[2*"$frame",2]*fact); 30282 y=="$selected_keypoint"?(ellipse(#-1,X,radius2+2,radius2+2,0,1,255)); 30283 ellipse(#-1,X,radius2,radius2,0,opacity,0); 30284 ellipse(#-1,X,radius1,radius1,0,opacity,I[#"$colormap",i4]); I" 30285 fi 30286 w. -1,-1,0,"[G'MIC] Interactive Morph ("${"s0=Source s1=Target u ${s"$frame"}"}")" 30287 fi 30288 30289 # Generate morph image 30290 if !narg($imgm) 30291 t,onemt={t=$animate_inbetween?0.5*(1+sin(2*($time_inbetween+$|-$animate_inbetween))):$time_inbetween;[t,1-t]} 30292 +*[warp1] $t *. -1 +warp[imgb0] .,1,2,3 rm.. *. $onemt 30293 +*[warp0] $onemt *. -1 +warp[imgb1] .,1,2,3 rm.. *. $t 30294 +[-2,-1] c. 0,255 nm. imgm 30295 w1. -1,-1,0,"[G'MIC] Interactive Morph (In-between)" 30296 fi 30297 30298 # Manage user interaction 30299 if $animate_inbetween wait 40 else wait fi 30300 mb={*,b} mxy={[{*,x,y}]*100/([{*,w,h}]-1)} mouse_over={{*,x}>=0} 30301 30302 if $mouse_over" && "($mb" || "{*,DELETE})" && "$selected_keypoint<0" && "h#$keypoints>0 30303 30304 # Determine selected keypoint. 30305 selected_keypoint={keypoints,"dmin = inf; kmin = -1; fact = ([w#"$imgr",h#"$imgr"]-1)%; 30306 repeat (h,k, 30307 dist = norm(((I[k])[2*"$frame",2] - ["$mxy"])*fact); 30308 dist<dmin?(dmin = dist; kmin = k) 30309 ); 30310 kmin>=0 && dmin<"max(8,1.5*$radius_keypoints)"?kmin:-1"} 30311 fi 30312 30313 if {*,-o}" || "{*,-SPACE}" || "{*1,-SPACE} frame={!$frame} rmn imgr fi # Swap frames 30314 if {*,-K}" || "{*1,-K} view_keypoints={!$view_keypoints} rmn imgr fi # Show/hide keypoints 30315 if {*,-R}" || "{*1,-R} rmn keypoints,imgr __x_morph_keypoints= fi # Reset keypoints 30316 if {*,-TAB}" || "{*1,-TAB} # Change keypoint radius 30317 radius_keypoints={max(2,($radius_keypoints+2)%8)} view_keypoints=1 rmn imgr 30318 fi 30319 if {*,-ENTER}" || "{*1,-ENTER} animate_inbetween={$animate_inbetween?0:$|} fi # Start in-between animation 30320 if {*,r} rmn imgb0,imgb1 fi # Window resize 30321 if {*1,r} rmn imgm fi 30322 if {*1,o} # Change time of in-between 30323 time_inbetween={max(0,min(1,$time_inbetween+0.05*{*1,-o}))} animate_inbetween=0 rmn imgm 30324 fi 30325 if {*1,-b} time_inbetween=0.5 animate_inbetween=0 rmn imgm fi # Reset in-between time 30326 30327 if $mouse_over" && "($mb==1" || "$mb==2)" && "$selected_keypoint<0 # Add keypoint 30328 if $mb==1" && "!$move_other frame={!$frame} move_other=1 fi # Move on other window 30329 ({keypoints,[$mxy,$mxy,h]}) 30330 permute. zycx a[keypoints,-1] y 30331 selected_keypoint={keypoints,h-1} 30332 rmn imgr 30333 30334 elif $mouse_over" && "($mb==1" || "$mb==2)" && "$selected_keypoint>=0 # Move keypoint 30335 if $mb==1" && "!$move_other frame={!$frame} move_other=1 fi # Move on other window 30336 ({[$mxy]}) permute. zycx j[keypoints] .,0,$selected_keypoint,0,{2*$frame} rm. 30337 rmn imgr 30338 30339 elif $mouse_over" && "$selected_keypoint>=0" && ("{*,-DELETE}" || "$mb==4") && "h#$keypoints>4 # Delete keypoint 30340 1,1,1,5,-1 j[keypoints] .,0,$selected_keypoint rm. discard[keypoints] -1 r[keypoints] 1,{keypoints,h/5},1,5,-1 30341 N0-={$selected_keypoint<$N0?1:0} selected_keypoint=-1 30342 rmn warp0,warp1,imgr 30343 30344 elif !{*,b}" && "$selected_keypoint>=0 30345 if $move_other frame={!$frame} move_other=0 fi 30346 selected_keypoint=-1 30347 rmn warp0,warp1,imgr 30348 fi 30349 30350 if $animate_inbetween rmn imgm fi 30351 while {*}" && "!{*,ESC}" && "!{*,Q}" && "{*1}" && "!{*1,ESC}" && "!{*1,Q} 30352 if !$< __x_morph_keypoints={keypoints,^} fi 30353 30354 # Render fullres morphing. 30355 rmn colormap,imgb0,imgb1,warp0,warp1,imgr,imgm 30356 +_x_warp_rbf[keypoints] {img0,[w,h]} 30357 +l[keypoints] s c,-2 rv[0,1] a c endl +_x_warp_rbf. {img0,[w,h]} rm.. 30358 nm[-2,-1] warp0,warp1 30359 30360 repeat $1 30361 t,onemt={t=$>/max(1,$1-1);[t,1-t]} 30362 +*[warp1] $t *. -1 +warp[img0] .,1,2,3 rm.. *. $onemt 30363 +*[warp0] $onemt *. -1 +warp[img1] .,1,2,3 rm.. *. $t 30364 +[-2,-1] c. 0,255 nm. ${nm0}_$> 30365 if {*}" && "{*1} w1 0 fi 30366 if {*}" || "{*1} 30367 text="Processing frame \#"$>"/"{$1-1}"..." 30368 if {*} +r. {*,d,e},1,100%,2 to. $text,5,5,20,2 w. rm. fi 30369 if {*1} +r. {*1,d,e},1,100%,2 to. $text,5,5,20,2 w1. rm. fi 30370 fi 30371 done 30372 nm. $nm1 k[-$1--1] 30373 offset+={$!-2} 30374 endl done w0 0 w1 0 30375 30376#@cli x_pacman 30377#@cli : Launch pacman game. 30378x_pacman : check_display $0 30379 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30380 e[] "\n 30381------ "${g}"Pacman"$n" -----------------------------------------------\n 30382----\n 30383---- This is a G\47MIC implementation of the "${g}"pacman"$n" game.\n 30384----\n 30385---- Move the pacman to eat all pacdots on the different levels.\n 30386---- Eating a pacgum makes pacman invincible for "${c}"10 seconds"$n",\n 30387---- which mean pacman can eat ghosts during this time.\n 30388---- Eating a ghost earns "${c}"100 pts"$n".\n 30389---- Eating a cherry earns "${c}"10 pts"$n".\n 30390---- Eating a strawberry earns "${c}"100 pts"$n".\n 30391---- Eating an orange earns "${c}"1000 pts"$n".\n 30392---- Eating a banana earns "${c}"5000 pts"$n".\n 30393----\n 30394---- "${c}"Arrow keys"$n" to control pacman.\n 30395---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 30396---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 30397---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30398----\n 30399--------------------------------------------------------------" 30400 l[] 30401 30402 # Initialize characters gfx. 30403 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" 30404 repeat 4 30405 _pacman_ghost_standard_gfx 255,0,0,$> nm. ghost0_$> 30406 _pacman_ghost_standard_gfx 0,255,222,$> nm. ghost1_$> 30407 _pacman_ghost_standard_gfx 255,184,222,$> nm. ghost2_$> 30408 _pacman_ghost_standard_gfx 255,184,71,$> nm. ghost3_$> 30409 _pacman_ghost_afraid_gfx $> nm. ghosta_$> 30410 _pacman_ghost_base_gfx $> r. 16,16,1,1,2 nm. ghostm_$> 30411 _pacman_ghost_standard_gfx 0,0,0,$> nm. ghostd_$> 30412 _pacman_pacman_gfx $> nm.. pacman_$> nm. pacmanm_$> 30413 done 30414 +channels[ghostd_0] 0 !=. 0 nm. ghostdm 30415 _pacman_cherry_gfx nm. fruit0 _pacman_strawberry_gfx nm. fruit1 30416 _pacman_orange_gfx nm. fruit2 _pacman_banana_gfx nm. fruit3 30417 20,2,1,3,200 nm. gate 30418 score0,score1,score2,score3,score4=10,100,1000,5000,"Argh!" 30419 repeat 5 30420 0 t. ${score$>},0,0,13,1,255,255,255 autocrop. 0 expand_xy. 1,0 +dilate. 3 30421 nm. scorem$> nm.. score$> 30422 done 30423 time4=255,255,255 time3=255,255,32 time2=255,128,32 time1=255,32,32 30424 repeat 11 0 t. $<" s",0,0,23,1,${time{min(4,round(($<+1)/2))}} nm. time$< done 30425 0 t. "Get Ready!",0,0,32,1,255 autocrop. 0 expand_xy. 4,0 +dilate. 8 r.. 100%,100%,1,3 30426 nm.. get_ready nm. get_readym 30427 0 t. "Game\nOver!",0,0,53,1,255 autocrop. 0 expand_xy. 4,0 +dilate. 8 r.. 100%,100%,1,3 30428 nm.. game_over nm. game_overm 30429 30430 # Start game. 30431 score=0 level=-1 lives=3 is_quit=0 30432 do 30433 30434 # Build new level if necessary. 30435 if $level<0 30436 _rlevel=33 _glevel=33 _blevel=255 30437 _pacman_map_level{((-$level-1)%6)+1} mw={w} mh={h} mw2={int(w/2)} mh2={int(h/2)} 30438 if $level<-6 replace. 3,2 fi 30439 . nm[-2,-1] map0,map 30440 30441 # Precompute valid directions on each map point, and shortest path to the ghost's home. 30442 +shift[map] -1,0 +shift[map] 0,-1 +shift[map] 1,0 +shift[map] 0,1 a[-4--1] z !=. 1 nm. can_go 30443 +==[map] 1 100%,100% =. 1,$mw2,$mh2 distance. 1,..,3 rm.. 30444 f. 'if(i==2,0,if(i==8,1,if(i==1,2,if(i==4,3,i))))' nm. path 30445 +==[map] 2 pacdots={is} rm. 30446 level={-$level} 30447 fi 30448 30449 # Render board gfx. 30450 f[map] 'if(i>=4,0,i)' +==[map] 1 expand_xy. 1,0 r. 1600%,1600% erode. 9 b. 2 30451 g. xy abs[-2,-1] +[-2,-1] >=. 80% b. 2 n. 0,1 shrink_xy. 16 30452 +*. $_glevel +*.. $_blevel *... $_rlevel a[-3--1] c 30453 16,16,1,1,'x' +-[map] 1 max. 0 *. 16 r. 1600%,1600% 30454 16,16,1,1,'y' ri[-3,-1] ..,0,2 +[-2,-1] a[-2,-1] c 30455 16,16,1,3 _pacman_pacdots_gfx _pacman_pacgum_gfx a[-3--1] y 30456 warp. ..,0,0 rm.. -|[-2,-1] r. 100%,{h+24},1,3,0,0,0,1 30457 t. "Lives :",10,0,24,1,255 t. "Score :",{w-140},0,24,1,255 30458 if $lives +r[pacman_2] 12,12,1,4,2 r. {100*$lives}%,100%,1,4,0,2 j.. .,90,7 rm. fi 30459 nm. visu 30460 w[visu] {visu,f=h<0.5*{*,v}?1.5:1;[w,h]*=f},0,"[G"{`39`}"MIC] Pacman" cursor[0] 0 30461 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 30462 nm. level_N nm.. levelm_N 30463 30464 repeat 4 xg$>={16*$mw2} yg$>={16*$mh2+4*$>} dg$>=3 mg$>=0 done 30465 xp={16*10} yp={16*21} dp=-1 pacgum_timer=-1 fruit_timer=$| dying_pacman=0 is_get_ready=1 30466 xscore=0 yscore=0 nscore=0 oscore=0 30467 30468 # Start game interaction. 30469 do 30470 30471 # Display board graphics. 30472 t={int(6*$|)%4} left={if($pacgum_timer>=0,10-$|+$pacgum_timer,-1)} 30473 [visu] 30474 repeat 4 30475 mg=${mg$>} xg=${xg$>} yg={${yg$>}+24} 30476 if $mg==0 j. [ghost$>_$t],$xg,$yg,0,0,1,[ghostm_$t] 30477 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] 30478 elif $mg==2 j. [ghostd_$t],$xg,$yg,0,0,0.8,[ghostdm] 30479 else j. [ghost$>_$t],$xg,$yg,0,0,{$mg-2},[ghostm_$t] j. [ghostd_$t],$xg,$yg,0,0,1,[ghostdm] 30480 fi 30481 done 30482 if $dying_pacman 30483 _pacman_pacman_gfx {$dying_pacman/2} rotate[-2,-1] {90*(abs($dp)-1)} j... ..,$xp,{24+$yp},0,0,1,.,255 rm[-2,-1] 30484 dying_pacman+=1 30485 if $dying_pacman>64 30486 if $lives!=1 rm. break fi 30487 j. [game_over],{(w-{game_over,w})/2},{12+(h-{game_over,h})/2},0,0,{min(1,($dying_pacman-64)/50)},\ 30488 [game_overm],255 30489 rectangle. 90,7,101,18,1,0 30490 fi 30491 else 30492 +rotate[pacman_$t,pacmanm_$t] {90*(abs($dp)-1)} j... ..,$xp,{24+$yp},0,0,1,.,255 rm[-2,-1] 30493 if $left>=0" && "($left>=5" || "$t<=2) j. [time{round($left)}],{(w-{time0,w})/2-10},1 fi 30494 fi 30495 t. $score,{w-60},3,20,1,255 30496 if $is_get_ready 30497 j. [level_N],{(w-{level_N,w})/2},{12+(h-1.5*{level_N,h})/2},0,0,1,[levelm_N] 30498 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 30499 fi 30500 if $oscore>0 j. [score$nscore],$xscore,$yscore,0,0,$oscore,[scorem$nscore],255 oscore-=0.04 yscore-=1 fi 30501 j. [gate],158,223,0,0,0.6 30502 w. 30503 if {*,CTRLLEFT}" && "{*,D} w[] {2*w},{2*h} 30504 elif {*,CTRLLEFT}" && "{*,C} w[] {f=h<0.5*{*,v}?1.5:1;[w,h]*=f} 30505 fi 30506 rm. 30507 30508 # Manage ghosts displacements and collisions. 30509 repeat 4 30510 xg=${xg$>} yg=${yg$>} dg=${dg$>} mg=${mg$>} 30511 30512 if max(abs($xg-$xp),abs($yg-$yp))<=8 # Test collision between ghost and pacman. 30513 if $mg==0" && "!$dying_pacman dying_pacman=1 # Was in normal mode -> dying pacman. 30514 xscore=$xp yscore={$yp+12} oscore=1 nscore=4 30515 elif $mg==1 mg=2 mg$>=$mg score+=100 # Was in invicibility mode -> dying ghost. 30516 xscore=$xp yscore={$yp+12} oscore=1 nscore=1 30517 fi 30518 fi 30519 if $mg>=2" && "($xg>>4)==$mw2" && "($yg>>4)==$mh2 # Check if dying ghost has returned to home. 30520 mg+=0.01 30521 if $mg>=3 mg=0 xg&=-2 yg&=-2 fi 30522 mg$>=$mg 30523 fi 30524 30525 if !($xg&15)" && "!($yg&15) # Check if ghost can take a new direction. 30526 ({u},{u},{u},{u};0,1,2,3) 30527 if $mg<2 # Try to chase or escape pacman 30528 =. {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)),\ 30529 dX1=$xp-$xg;dY1=$yp-$yg;if(abs(dX1)<abs(dY1),if(dX1>0,2,0),if(dY1>0,3,1)))} 30530 =. 0,{($dg+2)%4} 30531 if $is_get_ready =. 0.8,{path,i({$xg>>4},{$yg>>4})} fi 30532 else =. 1,{path,i({$xg>>4},{$yg>>4})} # If dying ghost, follow the best path to home. 30533 fi 30534 sort. -,x 30535 repeat 4 d={i($>,1)} # Try directions until it matches. 30536 if {can_go,i({$xg>>4},{$yg>>4},$d)} dg=$d break fi 30537 done rm. 30538 dg$>=$d 30539 fi 30540 u={D=${dg$>};(D==0)-(D==2)} 30541 v={D=${dg$>};(D==1)-(D==3)} 30542 xg$>={($xg+$u*(1+($mg==0)))%(16*$mw)} 30543 yg$>={($yg+$v*(1+($mg==0)))%(16*$mh)} 30544 done 30545 30546 wait 22 30547 30548 # Manage pacman displacement. 30549 if !$dying_pacman 30550 d={if({*,ARROWRIGHT},1,if({*,ARROWDOWN},2,if({*,ARROWLEFT},3,if({*,ARROWUP},4,$dp))))} 30551 if !($xp&15)" && "!($yp&15) 30552 i={map,i({$xp>>4},{$yp>>4})} 30553 if $i==2 score+=10 pacdots-=1 # Pacdot eaten. 30554 elif $i==3 pacgum_timer=$| repeat 4 if !${mg$>} mg$>=1 dg$>={(${dg$>}+2)%4} fi done # Pacgum eaten. 30555 elif $i>=4 score+={${score{$i-4}}} xscore=$xp yscore={$yp+12} oscore=1 nscore={$i-4} # Fruit eaten. 30556 fi 30557 =[map] 0,{$xp>>4},{$yp>>4} 30558 16,16,1,3 j[visu] .,$xp,{24+$yp} rm. 30559 d={if({can_go,i({$xp>>4},{$yp>>4},{abs($d)-1})},$d,$dp)} 30560 d={if({can_go,i({$xp>>4},{$yp>>4},{abs($d)-1})},$d,-abs($dp))} 30561 dp=$d 30562 else dp={if(abs($d-$dp)==2,$d,$dp)} # Allow to turn back on non-integer locations. 30563 fi 30564 is_get_ready={if($dp>0,0,$is_get_ready)} 30565 u={($dp==1)-($dp==3)} 30566 v={($dp==2)-($dp==4)} 30567 xp={($xp+2*$u)%(16*$mw)} 30568 yp={($yp+2*$v)%(16*$mh)} 30569 30570 if $pacgum_timer>=0" && "$|>$pacgum_timer+10 # Check if pacgum still has some effect. 30571 repeat 4 xg$>&=-2 yg$>&=-2 mg$>={if(${mg$>}==1,0,${mg$>})} done 30572 pacgum_timer=-1 30573 fi 30574 30575 if !$is_get_ready" && "($|-$fruit_timer)>=10 30576 x={round(u(0,{map0,w}))} 30577 y={round(u(0,{map0,h}))} 30578 if !{map,i($x,$y)}" && "{map0,i($x,$y)}==2 30579 n={min(3,int(abs(g*1.7)))} =[map] {4+$n},$x,$y j[visu] [fruit$n],{16*$x},{16*$y+24} fruit_timer=$| 30580 fi 30581 fi 30582 30583 fi 30584 if !{*}" || "{*,Q}" || "{*,ESC} is_quit=1 fi 30585 30586 while !$is_quit" && "$pacdots 30587 30588 if $is_quit break # Player asked to quit 30589 elif $pacdots # Player lost a life 30590 lives-=1 30591 else # Player achieved level 30592 level={-$level-1} wait[0] -1 30593 rm[map0,map,can_go,path] 30594 fi 30595 rm[visu,level_N,levelm_N] 30596 while $lives 30597 rm w 0 endl 30598 30599# The functions below create the various sprite gfx. 30600_pacman_ghost_standard_gfx : 30601 _pacman_ghost_base_gfx $4 (0,$1^0,$2^0,$3) map.. . rm. 30602 ellipse. 10,11,3,4,0,1,255 ellipse. 20,11,3,4,0,1,255 30603 r. 16,16,1,3,2 point. 5,{7-($4>=2)},0,1,1 point. 10,{7-($4>=2)},0,1,1 30604 30605_pacman_ghost_afraid_gfx : 30606 _pacman_ghost_base_gfx $1 30607 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 30608 map.. . rm. r. 16,16,1,3,2 30609 line. 4,4,6,6,1,$col,255 line. 4,6,6,4,1,$col,255 30610 line. 9,4,11,6,1,$col,255 line. 9,6,11,4,1,$col,255 30611 f. 'if(y>=9&&y<=10&&x>=2&&x<=13&&((int((x+1)/2)+y)%2),arg(c+1,$col),i)' 30612 30613_pacman_pacman_gfx : 30614 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' 30615 (0,255^0,255^0,0^0,255) map.. . rm. r. 16,16,1,4,2 s. c,-3 30616 30617_pacman_pacdots_gfx : 30618 (255^184^151) r. 4,4,1,3 r. 16,16,1,3,0,0,0.5,0.5 30619 30620_pacman_pacgum_gfx : 30621 64,64,1,3 circle. 31,31,31,1,255,128,64 r2dx. 16 30622 30623_pacman_cherry_gfx : 30624 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KNzYgMSAxIDEgIzU5CnicFYpBCgAxDALVXvv/p5ZtmsgmIMoM7k0Cx/ySYYIXrE5qOgTmE1KGl"\ 30625 "oUW1pp1qVUqmkt3Hj9Whx3SMSAyMCAxIDEgIzI2Cnicc/eNYkjPzUyONwACveTM3PQqBgA+VQX2" 30626 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 30627 30628_pacman_strawberry_gfx : 30629 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KNzIgMSAxIDEgIzYwCnicJYlJDoAwEMOyHOH/H+UANJ0RBaRIlp1tJ4HAd9HFaoUtTNWC1yIPW"\ 30630 "T5ew5em+lT994guKHgAoIoa8zEgMjAgMSAxICMyNgp4nHP3jWJIz81MjjcAAr3kzNz0KgYAPlUF9g==" 30631 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 30632 30633_pacman_orange_gfx : 30634 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KNDQgMSAxIDEgIzQ2CnicBcHBDQAgDAOxXPjC/gsxU4VKi7DnAukKPU6SYjTVptxhbSv8wpVuf"\ 30635 "UwDEZ4xIDIwIDEgMSAjMjYKeJxz941iSM/NTI43AAK95Mzc9CoGAD5VBfY=" 30636 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 30637 30638_pacman_banana_gfx : 30639 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KNzAgMSAxIDEgIzQ4CnicNcqxDQAgDMTANx0S++8aIC9ShObceC6QQoSJ5Ai5vWW2WTI6xr+bv"\ 30640 "LU/BnUW3jEgMjAgMSAxICMyNgp4nHP3jWJIz81MjjcAAr3kzNz0KgYAPlUF9g==" 30641 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 30642 30643_pacman_map_level1 : 30644 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjAxIDEgMSAxICM5Nwp4nGWOUQ6AMAhDKX56Be9/QnWJArEM9MdsGa9QYOsGiOy4FaZYHAo1a"\ 30645 "MezIJ+QJnszLsq2aRaf9Q9GiaBnGmEZhSe8wLOdVqO+My+cFdJj9OpVQ0vzRm8l/L954AHE9jnsMSAyMCAxIDEgIzI2Cnicc/eNYk"\ 30646 "jPzUyONwACveTM3PQqBgA+VQX2" 30647 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 30648 _rlevel=33 _glevel=33 _blevel=255 30649 30650_pacman_map_level2 : 30651 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjA4IDEgMSAxICMxMDAKeJxljkEOAzEIAxn32C/0/y+MdlUloAKJemgvjAOG+PkCs8ElHsjRQ"\ 30652 "k0iycwS+/2jcuJlnhhhf3SxPKWw9DaJmYsbmLOqmyaXn92UsVV9Y+sweOvb7YB1vQPPDnV4a/ABHS45BDEgMjAgMSAxICMyNgp4nH"\ 30653 "P3jWJIz81MjjcAAr3kzNz0KgYAPlUF9g==" 30654 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 30655 _rlevel=200 _glevel=33 _blevel=33 30656 30657_pacman_map_level3 : 30658 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjA5IDEgMSAxICMxMDEKeJxVTlsOwDAIAve5K+z+N+zStGomeyTdjwIKYT9IoHGAbpOgdQ3n1"\ 30659 "i1ZinHdnO+20FuKg3nf4WIO3YolP8QEQ75CEkoKaUIDT3K95w8OZbp4lDcMj1PNUjXyDg+u4LTGC5LiOwAxIDIwIDEgMSAjMjYKeJ"\ 30660 "xz941iSM/NTI43AAK95Mzc9CoGAD5VBfY=" 30661 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 30662 _rlevel=33 _glevel=200 _blevel=255 30663 30664_pacman_map_level4 : 30665 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjEwIDEgMSAxICM5MAp4nHVPQQ6AMAhr8egX/P8TN+cGGSy6TBMTQgqlUPaDBDINLBJZbMQHq"\ 30666 "mwq7e40eahgy8i/jDKB1QhlRWBzcPH09Rnr9ALTrHSOuN5N+IFF9LIY9uOPDitcQvExIDIwIDEgMSAjMjYKeJxz941iSM/NTI43AA"\ 30667 "K95Mzc9CoGAD5VBfY=" 30668 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 30669 _rlevel=200 _glevel=200 _blevel=33 30670 30671_pacman_map_level5 : 30672 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMjA3IDEgMSAxICMxMDAKeJxdjlEKxCAMRPOmn3uF3v+ELXRrDE2qwrIgzPB8Mn52MDv4ihBbQ"\ 30673 "yjQyuRBz96RF8NmSYAb98s65j95Wd0bFqxG1MNV/s1ealMujRHdI5wtf9X0WnWmFWO/7JmJXScPVxI1CjEgMjAgMSAxICMyNgp4nH"\ 30674 "P3jWJIz81MjjcAAr3kzNz0KgYAPlUF9g==" 30675 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 30676 _rlevel=200 _glevel=255 _blevel=33 30677 30678_pacman_map_level6 : 30679 base642img[] "MiBjaGFyIGxpdHRsZV9lbmRpYW4KMTgzIDEgMSAxICM5Mgp4nGVO0QqAQAhz67Ff6P+/sK66TNqJUBCozDHn5gUwW9EIBnhi2nmBP"\ 30680 "QmHCeMwDbuzBNCH1oZeDBEiPSWiAoXU8Yfhn4PyiNc1X3i99NwUJPMoVyVs3PAASqEr4jEgMjAgMSAxICMyNgp4nHP3jWJIz81Mjj"\ 30681 "cAAr3kzNz0KgYAPlUF9g==" 30682 decompress_rle. +mirror. x z. 1,100% a[-2,-1] x 30683 _rlevel=255 _glevel=130 _blevel=233 30684 30685#@cli x_paint 30686#@cli : Launch the interactive painter. 30687x_paint : check_display $0 30688 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30689 e[] "\n 30690------ "${g}"Interactive painter"$n" -----------------------\n 30691----\n 30692---- Use "${c}"mouse"$n" to select color and brush.\n 30693---- "${c}"Left button"$n" draws a colored stroke.\n 30694---- "${c}"Right button"$n" fills a colored region.\n 30695---- "${c}"Arrow keys"$n" or '"${c}"SPACE"$n"' and '"${c}"BACKSPACE"$n"' to swap\n 30696---- between available images.\n 30697---- Key '"${c}"S"$n"' to save snapshot of the current view.\n 30698---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30699----\n 30700--------------------------------------------------" 30701 to_rgb 30702 if !$! i[0] 512,512,1,3,255 nm[0] "[New image]" else k[0] fi 30703 1 # Brush image [-1] 30704 parallel "_x_paint[]","w[] 400,320,0,Palette x_select_color[] __color,0,0,0" k[0] 30705 30706_x_paint : 30707 30708 # Init variables. 30709 pass[-2,-1] 1 ('{-2,n}') discard. {'_c1'} nm... {t} rm. 30710 __color={0,if(ia<128,vector3(255),vector3(0))} 30711 brushsize=1 30712 brushopacity=0 30713 brushangle=90 30714 brushthickness=1 30715 image=0 30716 refresh_image=1 30717 refresh_brush=1 30718 ox1=-1 30719 oy1=-1 30720 30721 # Start user event loop. 30722 do 30723 30724 # Open/refresh brush window. 30725 if $refresh_brush 30726 rm. (32,64;64,32) r. 16,16,1,3,1 r. {8*48},{4*48},1,3,0,2 30727 repeat 4,y repeat 8 30728 ellipse. {48*$>+24},{48*$y+24},{2*$>+1},{(2*$>+1)*$brushthickness},$brushangle,{1-$y/4},255 30729 done done 30730 rectangle. {$brushsize*48},{$brushopacity*48},\ 30731 {$brushsize*48+47},{$brushopacity*48+47},\ 30732 1,0xFFFFFFFF,255,128,128 30733 {w},16,1,3 line. 0,50%,100%,50%,1,0x55555555,128,64,128 30734 bx={$brushangle*w/180} 30735 rectangle. {$bx-16},20%,{$bx+16},80%,1,128 30736 line. {$bx-16},20%,{$bx+16},20%,1,255 line. {$bx+16},20%,{$bx+16},80%,1,255 30737 line. {$bx-16},80%,{$bx+16},80%,1,64 line. {$bx-16},20%,{$bx-16},80%,1,64 30738 a[-2,-1] y 30739 16,{h-16},1,3 line. 50%,0,50%,100%,1,0x55555555,128,64,128 30740 by={$brushthickness*(h-16)} 30741 rectangle. 20%,{$by-16},80%,{$by+16},1,128 30742 line. 20%,{$by-16},80%,{$by-16},1,255 line. 80%,{$by-16},80%,{$by+16},1,255 30743 line. 20%,{$by-16},20%,{$by+16},1,64 line. 20%,{$by+16},80%,{$by+16},1,64 30744 a[-2,-1] x 30745 w3. {w},{h},0,"Brush" 30746 refresh_brush=0 30747 fi 30748 30749 # Open/refresh image window. 30750 if $refresh_image 30751 w1[$image] {$image,w},{$image,h},0,"Image "\#$image" : "{$image,b}.{$image,x} 30752 refresh_image=0 30753 fi 30754 30755 # Manage user events. 30756 x1={*1,x} y1={*1,y} 30757 x2={*2,x} y2={*2,y} 30758 x3={*3,x} y3={*3,y} 30759 30760 if $x1>=0 # Event in the image window. 30761 if {*1,b}&1 # Left button -> draw brush stroke. 30762 ox1={if($ox1<0,$x1,$ox1)} 30763 oy1={if($oy1<0,$y1,$oy1)} 30764 delta={max(abs($x1-$ox1),abs($y1-$oy1))} 30765 r1={2*$brushsize+1} 30766 r2={$r1*$brushthickness} 30767 dx={2*($x1-$ox1)/max(1,$delta)} 30768 dy={2*($y1-$oy1)/max(1,$delta)} 30769 o={1-($brushopacity/4)^0.04} 30770 repeat max(1,($delta+1)/2) 30771 ellipse[$image] {$ox1+$>*$dx},{$oy1+$>*$dy},$r1,$r2,$brushangle,$o,$__color 30772 done 30773 ox1=$x1 oy1=$y1 30774 refresh_image=1 30775 else 30776 ox1=-1 oy1=-1 30777 if {*1,b}&2 # Right button -> fill region. 30778 flood[$image] $x1,$y1,0,10,0,1,$__color 30779 refresh_image=1 30780 fi 30781 fi 30782 fi 30783 30784 if {*1,ARROWRIGHT}" || "{*2,ARROWRIGHT}" || "{*3,ARROWRIGHT}" || "\ # Manage image selection. 30785 {*1,ARROWUP}" || "{*2,ARROWUP}" || "{*3,ARROWUP}" || "\ 30786 {*1,SPACE}" || "{*2,SPACE}" || "{*3,SPACE} 30787 image={($image+1)%($!-2)} refresh_image=1 30788 elif {*1,ARROWLEFT}" || "{*2,ARROWLEFT}" || "{*3,ARROWLEFT}" || "\ 30789 {*1,ARROWDOWN}" || "{*2,ARROWDOWN}" || "{*3,ARROWDOWN}" || "\ 30790 {*1,BACKSPACE}" || "{*2,BACKSPACE}" || "{*3,BACKSPACE} 30791 image={($image-1)%($!-2)} refresh_image=1 30792 fi 30793 30794 if {*1,S} o[$image] gmic_paint.png fi # Save snapshot if requested. 30795 30796 if {*3,b}" && "$x3>=0 # Manage brush selection. 30797 if $x3<384" && "$y3>=192 brushangle={$x3*180/(w-16)} # Bottom slider -> select brush angle. 30798 elif $x3>=384" && "$y3<192 brushthickness={$y3/(h-16)} # Right slider -> select brush thickness. 30799 elif $x3<384" && "$y3<192 brushsize={int($x3*8/(w-16))} brushopacity={int($y3*4/(h-16))} 30800 fi 30801 refresh_brush=1 30802 fi 30803 wait 30804 while {*1}" && "!{*1,Q}" && "!{*1,ESC} 30805 30806 # Exit properly. 30807 __color=-1 w1[] 0 w2[] 0 w3[] 0 rm[-2,-1] 30808 30809#@cli x_plasma 30810#@cli : Launch the plasma effect demo. 30811x_plasma : check_display $0 30812 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30813 e[] "\n 30814------ "${g}"Plasma effect"$n" ----------------------\n 30815----\n 30816---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 30817---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 30818---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30819----\n 30820-------------------------------------------" 30821 l[] 30822 30823 # Init plasma backgrounds. 30824 N=8 30825 repeat $N 30826 320,200,1,3 rand. 0,255 plasma. 1,0,7 n. 0,255 30827 amp={u(-40,40)} freq={round(u(2,6))} dir$>={if(u<0.5,-1,1)*round(u(1,2))} 30828 100%,100%,1,1,'$amp*cos(y*2*pi*$freq/h)' 30829 done 30830 30831 {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 30832 0 t. "** Welcome to G\47MIC, a powerful image processing framework **",0,0,50,1,255 30833 b. 0.5 n. 0,255 30834 M={w} 30835 30836 # Start animation loop. 30837 w[] {0,f=1.5*h<0.5*{*,v}?3:1.5;[w,h]*=f},0,"[G"{`39`}"MIC] Plasma Effect" 30838 t=0 tt={-1.5*{0,w}} 30839 30840 do 30841 tic=$| 30842 30843 # Render interpolated background between two successive plasmas. 30844 a={int($t)} a2={2*$a} a21={$a2+1} 30845 b={($a+1)%$N} b2={2*$b} b21={$b2+1} 30846 +warp[$a2] [$a21],1,0,2 30847 +warp[$b2] [$b21],1,0,2 30848 j.. .,0,0,0,0,{$t-$a} rm. 30849 30850 shift[$a21] 0,${dir$a},0,0,2 # Animate plasma background. 30851 shift[$b21] 0,${dir$b},0,0,2 30852 if int($t+0.005)>int($t) dir$a={if(u<0.5,-1,1)*round(u(1,3))} fi 30853 t={($t+max(0.005,($|-$tic)))%$N} 30854 30855 # Render text scrolling. 30856 +z.. $tt,{$tt+w-1+2} 30857 warp. [-4],0,0,0 30858 r. 100%,100%,1,3 30859 +*. -1 +. 255 30860 j... .,0,0,0,0,1,..,255 rm. 30861 j.. .,-2,-2,0,0,1,.,255 rm. 30862 30863 tt+={max(2,($|-$tic)*250)} # Animate scrolling. 30864 if $tt>=$M tt={-1.5*{0,w}} fi 30865 30866 # Display rendered frame. 30867 fps=${-fps} if $fps>0 to. $fps" fps",5,5,16,1,0.2 fi 30868 w. 30869 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 30870 rm. wait 20 30871 while {*}" && "!{*,ESC}" && "!{*,Q} 30872 rm[{-2*$N-2}--1] w[] 0 endl 30873 30874#@cli x_quantize_rgb : _nbcolors>=2 30875#@cli : Launch the RGB color quantization demo. 30876x_quantize_rgb : check "isint(${1=16}) && $1>1" check_display $0 30877 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 30878 e[] "\n 30879------ "${g}"RGB Quantization"$n" --------------------------------------\n 30880----\n 30881---- This demo shows how RGB colors can be quantified using\n 30882---- the "${c}"k-means algorithm"$n".\n 30883----\n 30884---- "${c}"Left mouse button"$n" on 3D view rotates the color cube.\n 30885---- "${c}"Right mouse button"$n" on 3D view toggles colors/clusters mode.\n 30886---- "${c}"Left mouse button"$n" on image toggles dithering mode,\n 30887---- "${c}"Left mouse button"$n" on colormap adds a random color.\n 30888---- "${c}"Right mouse button"$n" on colormap removes a color.\n 30889---- Key '"${c}"R"$n"' init colormap with random values.\n 30890---- Key '"${c}"U"$n"' init colormap with uniform sampling.\n 30891---- Key '"${c}"M"$n"' init colormap with median-cut algorithm.\n 30892---- Key '"${c}"SPACE"$n"' does a single iteration of k-means and pauses.\n 30893---- Key '"${c}"ENTER"$n"' runs k-means algorithm.\n 30894---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 30895---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 30896---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 30897----\n 30898--------------------------------------------------------------" 30899 30900 if !$! sp ? fi 30901 k[0] to_rgb if h>300 r2dy 300 round 1 fi nm. img # Resize input image if necessary. 30902 +r {w*h},1,1,3,-1 r. {min(w,8192)},1,1,3 nm. colors # Get reduced set of image colors. 30903 $1,1,1,3 rand. 0,255 round. 1 nm. centroids # Initialize random centroids. 30904 _x_quantize_rgb_3d (1,0,0,0;0,1,0,0;0,0,1,0) nm. pose3d # Init 3D object. 30905 _x_quantize_rgb_text "Colors",clustering0 30906 _x_quantize_rgb_text "Clusters",clustering1 30907 _x_quantize_rgb_text "Dithering: off",dithering0 30908 _x_quantize_rgb_text "Dithering: on",dithering1 30909 if {img,h<300} +r2dy[img] 300,1 else [img] fi # Generate visualization canvas. 30910 {w+315},365,1,3,255 rm.. 30911 rectangle. 4,4,305,305,1,0xFFFFFFFF,0 30912 rectangle. 309,4,{w-5},305,1,0xFFFFFFFF,0 30913 rectangle. 4,309,{w-5},360,1,0xFFFFFFFF,0 30914 .,. 30915 rectangle. 310,5,{w-6},305,1,1 30916 rectangle. 5,310,{w-6},360,1,2 30917 300,300,1,1,'(y<<11)+(x<<2)+3' j.. .,5,5 rm. 30918 a[-2,-1] c nm. visu 30919 30920 # Start k-means iterations. 30921 dithering=0 clustering=0 pause=1 s0=off s1=on 30922 do 30923 30924 # Create and display visualization. 30925 if !narg($visu_3d) # Update 3D vizualization. 30926 +-[centroids] 2 ++[centroids] 2 a[-2,-1] x permute. cxyz y. -. 128 30927 j[obj3d] .,0,8 rm. # Update centroids position in 3D object. 30928 [obj3d] 30929 if $clustering 30930 if {colors,iM}<256 # Estimate nearest centroids for all colors. 30931 +index[colors] [centroids] *. 256 +[colors,-1] 30932 fi 30933 +channels[colors] 0 >>. 8 map. 2 permute. cxyz y. j.. .,0,{{-2,h}-$_N-h} rm. 30934 fi 30935 30936 pose3d. {pose3d,^} 300,300,1,3 j3d. ..,50%,50%,100,1,2,0,0,300 rm.. 30937 j. [clustering$clustering],2,0,0,0,1,[mclustering$clustering],255 30938 nm. visu_3d j[visu] [visu_3d],5,5 30939 fi 30940 30941 if !narg($visu_img) # Update indexed image. 30942 +index[img] [centroids],{0.7*$dithering},1 if h<300 r2dy. 300,1 fi 30943 j. [dithering$dithering],2,0,0,0,1,[mdithering$dithering],255 30944 nm. visu_img j[visu] [visu_img],310,5 30945 fi 30946 30947 if !narg($visu_centroids) # Update colormap. 30948 +luminance[centroids] a. [centroids],y sort. +,x rows. 1 r. {visu,w-10},50,1,3 30949 0 t. "Colors: "{centroids,w},2,0,16,1,255,255,255 +dilate. 3 j... ..,2,2,0,0,1,.,255 30950 rm[-2,-1] nm. visu_centroids j[visu] [visu_centroids],5,310 30951 fi 30952 l[visu] 30953 w -1,-1,0,"[G"{`39`}"MIC] RGB Quantization" 30954 if {*,CTRLLEFT}" && "{*,D} w[] {2*w},{2*h} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 30955 endl 30956 30957 # Check for user's interactions. 30958 x={int({*,x}*{visu,w}/{*,w})} 30959 y={int({*,y}*{visu,h}/{*,h})} 30960 b={*,b} 30961 i={visu,i($x,$y,0,3)} 30962 if $b&1" && "$i==1 # Toggle dithering. 30963 dithering={!$dithering} rm[visu_img] wait -1 30964 elif $b&1" && "$i==2 # Add new color. 30965 (${-rgb}) y. c a[centroids,-1] x _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 30966 pause=1 wait 100 30967 elif $b&2" && "$i==2" && "{centroids,w}>2 # Remove color. 30968 r[centroids] {centroids,w-1} _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 30969 pause=1 wait 100 30970 elif $b&2" && "$i>=3 # Toggle clusters/colors mode. 30971 clustering={!$clustering} rm[visu_3d] wait -1 30972 elif {*,M} # Init colormap with median-cut. 30973 +&[colors] 255 colormap. {centroids,w},0,0 rm[centroids] nm. centroids 30974 _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 30975 pause=1 wait -1 30976 elif {*,R} # Init colormap with random values. 30977 rand[centroids] 0,255 round[centroids] 1 30978 _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 30979 pause=1 wait -1 30980 elif {*,U} # Init colormap with uniform sampling. 30981 uniform_distribution {centroids,w},3 *. 255 rm[centroids] nm. centroids 30982 _x_quantize_rgb_3d rm[visu_3d,visu_img,visu_centroids] &[colors] 255 30983 pause=1 wait -1 30984 elif {*,ENTER} # Start k-means iterations. 30985 pause=0 30986 elif $b&1" && "$i>=3 # Manage 3D view rotation. 30987 coords={visu,i($x,$y,0,3)-3} u1={(($coords>>2)&511)-150} v1={($coords>>11)-150} 30988 if !narg($u0) u0=$u1 v0=$v1 fi 30989 if $u0!=$u1" || "$v0!=$v1 30990 n0={sqrt(($u0)^2+($v0)^2)} 30991 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))} 30992 n1={sqrt(($u1)^2+($v1)^2)} 30993 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))} 30994 u={$nv0*$nw1-$nw0*$nv1} v={$nw0*$nu1-$nu0*$nw1} w={$nv0*$nu1-$nu0*$nv1} n={sqrt(($u)^2+($v)^2+($w)^2)} 30995 rotation3d[] $u,$v,$w,{-asin($n/18225)*180/pi} mv[pose3d] $! m*[-2,-1] nm. pose3d 30996 u0=$u1 v0=$v1 rm[visu_3d] 30997 fi 30998 elif !($b&1) u0= 30999 fi 31000 31001 if !$pause" || "{*,SPACE} # Do one iteration of k-means. 31002 pause={*,-SPACE} 31003 31004 # Estimate new centroids positions. 31005 &[colors] 255 +index[colors] [centroids] *. 256 +[colors,-1] # Estimate nearest centroids for all colors. 31006 repeat s#$colors # Recompute centroid positions. 31007 sh[colors] $> +histogram. {centroids,w*256},0,{centroids,w*256-1} rm.. 31008 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] 31009 done a[-{colors,s}--1] c 31010 rm[centroids] nm. centroids 31011 31012 # Reassign unused centroids. 31013 +>>[colors] 8 channels. 0 histogram. {centroids,w},0,{centroids,w-1} 31014 cmax={xM} 31015 repeat w if !i($>) point[centroids] $>,0,0,1,{centroids,I($cmax)} point[centroids] $>,0,0,-0.001,${-rgb} fi done 31016 rm. c[centroids] 0,255 31017 31018 if $visu_3d rm[visu_3d] fi 31019 if $visu_img rm[visu_img] fi 31020 if $visu_centroids rm[visu_centroids] fi 31021 wait 20 31022 31023 else if $visu_img wait fi 31024 fi 31025 31026 while {*}" && "!{*,Q}" && "!{*,ESC} 31027 rm w 0 31028 31029 _x_quantize_rgb_3d : 31030 if $obj3d rm[obj3d] fi 31031 +distribution3d[centroids] circles3d. 5 col3d. 255 # Pre-compute 3D object. 31032 colorcube3d p3d. 1 31033 +&[colors] 255 distribution3d. circles3d. 3 o3d. 0.25 +3d[-3--1] 31034 -3d. 128,128,128 nm. obj3d _N={i[7]} 31035 31036_x_quantize_rgb_text : 31037 0 t. "$1",0,0,16,1,255 r. {w+2},15,1,1,0,0,0.5,0.5 +dilate. 3 to_rgb.. 31038 nm.. $2 nm. m$2 31039 31040#@cli x_reflection3d 31041#@cli : Launch the 3D reflection demo. 31042x_reflection3d : check_display $0 31043 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31044 e[] "\n 31045------ "${g}"3D reflection"$n" ----------------------\n 31046----\n 31047---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 31048---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 31049---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31050----\n 31051-------------------------------------------" 31052 31053 # Render background. 31054 128,256,1,3 rand. 0,255 plasma. 1,100 blur_xy. 30,2 31055 sh. 0 n. 0,90 rm. sh. 1 n. 0,60 rm. sh. 2 n. 0,180 rm. 31056 +mirror. x [-2,-1] a[-4--1] x 31057 +luminance. mirror. x b. 2 n. 0,255 31058 31059 # Create 3D objects. 31060 torus3d 30,10 col3d. 255,200,0 31061 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 31062 spherical3d 47,34,"100*abs(1+0.6*cos(3*phi)*sin(4*theta))" 31063 r3d[-2,-1] 0,1,0,90 db3d 0 31064 31065 # Start animation loop. 31066 xb,xl,anim=0 31067 w[] 400,400,0,"[G"{`39`}"MIC] 3D Reflection" 31068 do 31069 31070 tic=$| 31071 # Recreate 3D interpolated background object. 31072 +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.. 31073 31074 # Render 3D background object (with flat colors). 31075 +z[-6] $xb,0,{$xb+255},255 j3d. ..,75%,50%,0,1,3,0,0 31076 31077 # Render light reflection map. 31078 +z[-6] $xl,0,{$xl+255},255 31079 xf={min(30,$anim-70)+20*cos(1.8*$|)} 31080 yf={50+20*sin(2.7*$|)} 31081 j3d. [-6],{20+$xf}%,$yf%,0,1,4,0,0 31082 31083 # Add light reflection to 3D background object. 31084 l3d . rm. +j3d. ..,75%,50%,0,1,5,0,0 j.. .,0,0,0,0,0.6 rm[-3,-1] 31085 31086 # Add 3D foreground object. 31087 j3d. [-4],$xf%,$yf%,0,1,4,0,0 31088 31089 # Display frame and update animation variables. 31090 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-19},13,1,0.2 fi 31091 w. rm. 31092 31093 if {*,CTRLLEFT}" && "{*,D} w[] 800,800 elif {*,CTRLLEFT}" && "{*,C} w[] 400,400 fi 31094 xb={($xb+6)&255} 31095 xl={($xl-6)&255} 31096 anim+=1 31097 r3d[-2,-1] {sin(0.5*$|)},{cos($|)},1,{max(0.005,$|-$tic)*33} 31098 r3d... -1,0.3,0.8,{max(0.005,$|-$tic)*100} 31099 wait 20 31100 while {*}" && "!{*,ESC}" && "!{*,Q} 31101 rm[-5--1] w[] 0 31102 31103#@cli x_rubber3d 31104#@cli : Launch the 3D rubber object demo. 31105x_rubber3d : check_display $0 31106 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31107 e[] "\n 31108------ "${g}"3D rubber object"$n" -------------------\n 31109----\n 31110---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 31111---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 31112---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31113----\n 31114-------------------------------------------" 31115 rm 31116 sphere3d 150,0 torus3d 70,15 cylinder3d 20,40 31117 col3d... 200,200,200,0.3 col3d.. 128,200,76 col3d. 200,128,76 31118 c3d[-3--1] r3d. 1,0,0,70 +3d[-3--1] +3d. 10,-8,20 *3d. 1.5 31119 400,400,64,3 31120 {w},{h},1,3,'if(c==0,x,if(c==1,y,y*{1,d}/h))' 31121 {w},{h},1,3 31122 w[] {w},{h},0,"[G"{`39`}"MIC] 3D Rubber Object" 31123 frame=0 31124 do 31125 fps=${-fps} 31126 {w},{h},1,3 fc. 16,32,32 j3d. [0],50%,50%,0,1,3,0,0 j[1] .,0,0,$frame rm. 31127 r3d[0] 0.1,1,0.6,{3*cos($|*1.25)} r3d[0] 1,0.2,0.6,-1 31128 +warp[1] [2],0,0 *[3] 0.8 *. 0.2 +[3] . rm. 31129 if $fps>0 to. $fps" fps",5,{h-29},24,2,0.2 fi 31130 w. 31131 if {*,CTRLLEFT}" && "{*,D} w[] {2*w},{2*h} elif {*,CTRLLEFT}" && "{*,C} w[] {w},{h} fi 31132 wait[0] 20 31133 sh[2] 2 -. 1 &. {{1,d}-1} rm. 31134 frame={($frame-1)%{1,d}} 31135 while {*}" && "!{*,ESC}" && "!{*,Q} 31136 rm w 0 31137 31138#@cli x_segment : _max_resolution={ 0 | >=128 } 31139#@cli : Segment foreground from background in selected opaque RGB images, interactively. 31140#@cli : Return RGBA images with binary alpha-channels. 31141#@cli : Default value: 'max_resolution=1024'. 31142x_segment : check "${1=1024}==0 || $1>=128" check_display $0 31143 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31144 e[^-1] "Extract foreground from background in image$? interactively, with maximum resolution $1." 31145 e[] "\n 31146----------------------------------------------------------------------------------------------------\n 31147----\n 31148---- "${c}"Left mouse button"$n" or key '"${c}"F"$n"' create a new foreground control point 31149 (or move an existing one).\n 31150---- "${c}"Right mouse button"$n" or key '"${c}"B"$n"' create a new background control point 31151 (or move an existing one).\n 31152---- "${c}"Mouse wheel"$n", or keys '"${c}"CTRL+arrows UP/DOWN"$n"' zoom view in/out.\n 31153---- '"${c}"CTRL+mouse wheel"$n"', '"${c}"SHIFT+mouse wheel"$n"' or "${c}"arrow keys"$n" move image in zoomed view.\n 31154---- Key '"${c}"SPACE"$n"' updates the extraction mask.\n 31155---- Key '"${c}"TAB"$n"' toggles background view modes.\n 31156---- Key '"${c}"M"$n"' toggles marker view modes.\n 31157---- Key '"${c}"BACKSPACE"$n"' deletes the last control point added.\n 31158---- Key '"${c}"PAGE UP"$n"' increases background opacity.\n 31159---- Key '"${c}"PAGE DOWN"$n"' decreases background opacity.\n 31160---- Keys '"${c}"CTRL+D"$n"' increase window size.\n 31161---- Keys '"${c}"CTRL+C"$n"' decrease window size.\n 31162---- Keys '"${c}"CTRL+R"$n"' reset window size.\n 31163---- Keys '"${c}"ESC"$n"', '"${c}"Q"$n"' or '"${c}"ENTER"$n"' exit the interactive window.\n 31164----\n 31165----------------------------------------------------------------------------------------------------" 31166 repeat $! l[$>] 31167 31168 # Init variables and images. 31169 name={0,n} title={0,b} if narg({0,x}) title=$title.{0,x} fi 31170 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} 31171 selection=-1 marker_mode=2 xpan=-1 ypan=-1 bg_mode=0 opacity=64 31172 to_rgb nm img 31173 31174 if narg($_gui_control_points)>=4 # Import list of control points from plug-in GUI. 31175 ($_gui_control_points) r. {w/4},4,1,1,-1 31176 else 0 # Empty list of control points. 31177 fi 31178 nm. points 31179 31180 # Compute potential map. 31181 if $1>0 if $w>$h +r2dx[img] {min($1,$w)},2 else +r2dy[img] {min($1,$h)},2 fi else [img] fi 31182 _x_segment. 31183 pw={potential,w} ph={potential,h} 31184 31185 # Start event loop. 31186 do 31187 31188 # Handle user events for zoom/navigation/resizing. 31189 wait 31190 x={*,x} y={*,y} b={*,b} o={*,-o} 31191 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 31192 is_shift={{*,SHIFTLEFT}" || "{*,SHIFTRIGHT}} 31193 is_mouseout={$x<0" || "$y<0} 31194 x={$x0+$x*($x1-$x0+1)/$ww} y={$y0+$y*($y1-$y0+1)/$wh} 31195 oww=$ww owh=$wh ox0=$x0 oy0=$y0 ox1=$x1 oy1=$y1 31196 31197 if {*,r} # When window resized. 31198 nww={*,d} nwh={*,e} m={min($nww,$nwh)} 31199 cx={($x0+$x1)/2} cy={($y0+$y1)/2} dx={$nww*($x1-$x0+1)/$ww} dy={$nwh*($y1-$y0+1)/$wh} 31200 x0={$cx-$dx/2} x1={$cx+$dx/2} 31201 y0={$cy-$dy/2} y1={$cy+$dy/2} 31202 ww=$nww wh=$nwh 31203 elif $is_ctrl" && "{*,-D} # Increase window size. 31204 nww={min({*,u},$ww*1.25)} nwh={min({*,v},$wh*1.25)} m={min($nww,$nwh)} 31205 if $m==$nww ww=$m wh={$h*$m/$w} else ww={$w*$m/$h} wh=$m fi 31206 elif $is_ctrl" && "{*,-C} # Decrease window size. 31207 nww={$ww/1.25} nwh={$wh/1.25} 31208 if min($nww,$nwh)>=64 ww=$nww wh=$nwh fi 31209 elif $is_ctrl" && "{*,-R} # Reset window size. 31210 fdim=${fitscreen[]\ $w,$h} ww={arg(1,$fdim)} wh={arg(2,$fdim)} 31211 x0=0 y0=0 x1={$w-1} y1={$h-1} 31212 elif ($is_shift" && "$o<0)" || "{*,ARROWLEFT} # Go left. 31213 dx={($x1-$x0)/6} x0-=$dx x1-=$dx 31214 elif ($is_shift" && "$o>0)" || "{*,ARROWRIGHT} # Go right. 31215 dx={($x1-$x0)/6} x0+=$dx x1+=$dx 31216 elif ($is_ctrl" && "$o>0)" || "({*,ARROWUP}" && "!$is_ctrl) # Go up. 31217 dy={($y1-$y0)/6} y0-=$dy y1-=$dy 31218 elif ($is_ctrl" && "$o<0)" || "({*,ARROWDOWN}" && "!$is_ctrl) # Go down. 31219 dy={($y1-$y0)/6} y0+=$dy y1+=$dy 31220 elif $o>0" || "($is_ctrl" && "{*,ARROWUP}) # Zoom in. 31221 if $x1-$x0>16" && "$y1-$y0>16 31222 cx={if($x>=0" && "!{*,ARROWUP},$x,($x0+$x1)/2)} 31223 cy={if($y>=0" && "!{*,ARROWUP},$y,($y0+$y1)/2)} 31224 x0={$cx+($x0-$cx)*0.75} y0={$cy+($y0-$cy)*0.75} 31225 x1={$cx+($x1-$cx)*0.75} y1={$cy+($y1-$cy)*0.75} 31226 fi 31227 elif $o<0" || "($is_ctrl" && "{*,ARROWDOWN}) # Zoom out. 31228 zfactor={max(($x1-$x0+1)/$w,($y1-$y0+1)/$h)} 31229 if $zfactor<1.3 31230 cx={if($x>=0" && "!{*,ARROWDOWN},$x,($x0+$x1)/2)} 31231 cy={if($y>=0" && "!{*,ARROWDOWN},$y,($y0+$y1)/2)} 31232 x0={$cx+($x0-$cx)/0.75} y0={$cy+($y0-$cy)/0.75} 31233 x1={$cx+($x1-$cx)/0.75} y1={$cy+($y1-$cy)/0.75} 31234 dx={$zfactor^2*($w-$x0-$x1)/2} dy={$zfactor^2*($h-$y0-$y1)/2} 31235 x0+=$dx x1+=$dx y0+=$dy y1+=$dy 31236 else 31237 dx={($w-$x0-$x1)/2} dy={($h-$y0-$y1)/2} 31238 x0+=$dx x1+=$dx y0+=$dy y1+=$dy 31239 fi 31240 elif $b&4" && "!$is_mouseout # Pan. 31241 if $panx<0" && "$pany<0 panx=$x pany=$y 31242 else dx={round($panx-$x)} dy={round($pany-$y)} x0+=$dx y0+=$dy x1+=$dx y1+=$dy 31243 fi 31244 else panx=-1 pany=-1 31245 fi 31246 if $ww!=$oww" || "$wh!=$owh" || "$ox0!=$x0" || "$oy0!=$y0" || "$ox1!=$x1" || "$oy1!=$y1 rm[baseview] fi 31247 31248 # Handle events related to control points management. 31249 N={points,w} 31250 is_left_button={$b&1" || "{*,F}} is_right_button={$b&2" || "{*,B}} 31251 is_button={$is_left_button" || "$is_right_button} 31252 if narg($baseview)" && "$is_button" && "$x>=0" && "$y>=0" && "$x<$w" && "$y<$h 31253 if $selection==-1" && "$N # Check for selection of an existing point. 31254 ($x;$y) r. $N,2 -. [points] *. {max($ww,$wh)/max($x1-$x0,$y1-$y0)} sqr. s. y +[-2,-1] 31255 dmin={im} selection={if($dmin>25,-1,xm)} rm. 31256 fi 31257 if $selection>=0 31258 if $marker_mode # Move existing point. 31259 +columns[points] $selection ox={i[0]} oy={i[1]} 31260 =. $x =. $y,0,1 =. {1+$is_left_button},0,3 31261 j[points] .,$selection rm. rm[view] 31262 fi 31263 else # Add new foreground or background point. 31264 ($x;$y;0;{1+$is_left_button}) a[points,-1] x selection=$N if !$marker_mode marker_mode=2 fi rm[view] 31265 fi 31266 else selection=-1 31267 if {*,SPACE}" && "narg($labels) rm[labels] # Update labels. 31268 elif {*,TAB}" && "narg($baseview) # Toggle background view modes 31269 bg_mode={($bg_mode+1)%6} rm[baseview] wait -1 31270 elif {*,M}" && "narg($view) # Toggle markers view modes 31271 marker_mode={($marker_mode-1)%3} rm[view] wait -1 31272 elif {*,PAGEDOWN}" && "narg($baseview) # Decrease background opacity 31273 opacity={max(0,$opacity-32)} rm[baseview] wait -1 31274 elif {*,PAGEUP}" && "narg($baseview) # Increase background opacity 31275 opacity={min(255,$opacity+32)} rm[baseview] wait -1 31276 elif {*,BACKSPACE}" && "$N # Remove last point. 31277 if $N>1 z[points] 0,{$N-2} 31278 else i=$points rm[points] i[$i] 0 nm[$i] points 31279 fi rm[view] wait -1 31280 fi 31281 fi 31282 31283 # Manage zoomed view bounds. 31284 w2={round(($x1-$x0)/2)} h2={round(($y1-$y0)/2)} 31285 if $x0<-$w2 x1-={$x0+$w2} x0=-$w2 fi 31286 if $y0<-$h2 y1-={$y0+$h2} y0=-$h2 fi 31287 if $x1>=$w+$w2 x0+={$w-1+$w2-$x1} x1={$w-1+$w2} fi 31288 if $y1>=$h+$h2 y0+={$h-1+$h2-$y1} y1={$h-1+$h2} fi 31289 31290 # Render labels. 31291 if !narg($labels) 31292 N={points,w} 31293 if narg($view) to[view] "Processing...",5,5,20,2 w[view] fi 31294 if $N 31295 [points] 31296 sh. 0,0,0,0 *. {$pw/$w} rm. 31297 sh. 1,1,0,0 *. {$ph/$h} rm. 31298 pointcloud. -1,$pw,$ph dilate. 3 31299 watershed. [potential] -. 1 31300 else [potential],[potential],1,1,1 31301 fi 31302 nm. labels 31303 if narg($baseview) rm[baseview] fi 31304 fi 31305 31306 # Render base image. 31307 if !narg($baseview) 31308 nx0={$x0*$pw/$w} ny0={$y0*$ph/$h} 31309 nx1={$x1*$pw/$w} ny1={$y1*$ph/$h} 31310 +z[img] $x0,$y0,$x1,$y1 31311 r. $ww,$wh,1,100%,{if($ww<w" && "$wh<h,2,1)} 31312 +z[labels] $nx0,$ny0,$nx1,$ny1 31313 r. $ww,$wh,1,100%,{if($ww<w" && "$wh<h,2,3)} 31314 if $bg_mode>=3 *. -1 +. 1 fi 31315 *. {255-$opacity} +. $opacity a[-2,-1] c 31316 if $bg_mode%3>=1 i.. 100%,100%,1,3,{(($bg_mode-1)%3)*255} blend[-2,-1] alpha 31317 else drgba. 31318 fi 31319 nm. baseview 31320 if narg($view) rm[view] fi 31321 fi 31322 31323 # Render view. 31324 if !narg($view) 31325 [baseview] r. 100%,100%,1,3 31326 if $marker_mode 31327 if $marker_mode==2 rad1=5 rad2=3 opa=1 else rad1=3 rad2=2 opa=0.8 fi 31328 col0=255,0,0 col1=0,255,0 31329 repeat w#$points 31330 +columns[points] $> x={(i[0]-$x0)*$ww/(1+$x1-$x0)} y={(i[1]-$y0)*$wh/(1+$y1-$y0)} l={i[3]-1} rm. 31331 circle. $x,$y,$rad1,1,0 circle. $x,$y,$rad2,$opa,${col$l} 31332 done 31333 fi 31334 31335 nm. view 31336 w[view] $ww,$wh,0,$title 31337 fi 31338 31339 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,ENTER} 31340 31341 # Recompute labels at full resolution. 31342 if narg($view) to[view] "Processing fullres...",5,5,20,2 w[view] fi 31343 k[img,points] 31344 N={points,w} status= 31345 if $N 31346 status={points,^} 31347 [img] _x_segment. pointcloud[points] -1,$w,$h 31348 zfact={{img,max(w,h)}/{potential,max(w,h)}} dilate[points] {int(3*$zfact)} 31349 watershed[points] [potential] -[points] 1 k[img,points] 31350 *. 255 31351 else k[img] [img],[img],1,1,255 31352 fi 31353 a c nm $name 31354 31355 endl done 31356 u $status # Return control points of last image. 31357 w 0 31358 31359# Compute potential function. 31360_x_segment : 31361 b. 0.2% gradient_norm. f. '1/(1+i^2)' 31362 nm. potential 31363 31364#@cli x_select_color : _variable_name 31365#@cli : Display a RGB or RGBA color selector. 31366#@cli : Argument 'variable_name' specifies the variable that contains the selected color values (as R,G,B,[A]) 31367#@cli : at any time. 31368#@cli : Its value specifies the initial selected color. Assigning '-1' to it forces the interactive window to close. 31369#@cli : Default value: 'variable_name=xsc_variable'. 31370x_select_color : skip ${1=xsc_variable} check_display $0 31371 rm 31372 n={narg($$1)} if !$n $1=0,0,0 fi 31373 rgba_mode={$n>=4} R={arg(1,$$1)} G={arg(2,$$1)} B={arg(3,$$1)} A={if($rgba_mode,arg(4,$$1),255)} 31374 e[^-1] "Open "${arg\ 1+$rgba_mode,RGB,RGBA}" color selector widget, with variable '$1' and starting color "\ 31375 ($$1)"." 31376 if !{*} w[] {400+24*$rgba_mode},400,0,"Select a color" fi 31377 update_view=1 is_sv=0 is_h=0 is_a=0 colordb=0 is_thread_variable={arg(1,{'$1'})==_'_'" && "arg(2,{'$1'})==_'_'} 31378 31379 # Manage color presets. 31380 m "add_preset : if !narg($_xsc_preset$""1) _xsc_preset$""1=$""2,$""3,$""4 fi" 31381 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 31382 add_preset 4,0,0,255 add_preset 5,255,255,0 add_preset 6,255,0,255 add_preset 7,0,255,255 31383 add_preset 8,50,50,50 add_preset 9,100,100,100 add_preset 10,150,150,150 add_preset 11,200,200,200 31384 um add_preset 31385 if !narg($_xsc_preset) _xsc_preset=11 fi 31386 ($R^$G^$B) c. 0,255 rgb2hsv. H={i[0]} S={i[1]} V={i[2]} rm. 31387 31388 # Start event loop. 31389 do 31390 w={*,d} h={*,e} x={*,x} y={*,y} b={*,b} 31391 31392 # Update base image. 31393 if !$! 31394 $w,$h,1,3,200 31395 if $rgba_mode x1={w-89} y1={h-57} x2={w-80} else x1={w-49} y1={h-57} x2={w-40} fi 31396 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} 31397 rectangle {$x0-1},{$y0-1},{$x1+1},{$y1+1},1,0xFFFFFFFF,232 31398 line {$x0-1},{$y0-1},{$x1+1},{$y0-1},1,128 31399 line {$x0-1},{$y0-1},{$x0-1},{$y1+1},1,128 31400 (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. 31401 rectangle {$x2-1},{$y0-1},{$x3+1},{$y1+1},1,0xFFFFFFFF,232 31402 line {$x2-1},{$y0-1},{$x3+1},{$y0-1},1,128 31403 line {$x2-1},{$y0-1},{$x2-1},{$y1+1},1,128 31404 (359;0^1;1^1;1) r. {$x3-$x2+1},{$y1-$y0+1},1,3,3 hsv2rgb. j.. .,$x2,$y0 rm. 31405 if $rgba_mode 31406 rectangle {$x4-1},{$y0-1},{$x5+1},{$y1+1},1,0xFFFFFFFF,232 31407 line {$x4-1},{$y0-1},{$x5+1},{$y0-1},1,128 31408 line {$x4-1},{$y0-1},{$x4-1},{$y1+1},1,128 31409 (1;0) r. {$x5-$x4+1},{$y1-$y0+1},1,4,3 *. 255 drgba. j.. .,$x4,$y0 rm. 31410 fi 31411 t. "Current",$x0,{$y1+12},14,1,0 31412 if narg($_xsc_old) 31413 t. "Old",$x0,{$y1+34},14,1,0 31414 ($_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. 31415 fi 31416 repeat 12 31417 (${_xsc_preset$>}) -. 255 r. 4,1,1,1,0 +. 255 31418 y. c r. 18,18 drgba. frame. 1,1,{255*($>==$_xsc_preset)} 31419 j.. .,{$x6+($>%6)*25},{$y6+($>>=6)*25} rm. 31420 done 31421 update_view=1 31422 fi 31423 31424 # Update view. 31425 if $update_view 31426 . 31427 cx={$x0+$V*($x1-$x0)} cy={$y0+(1-$S)*($y1-$y0)} 31428 if $cx>$x0 line. {$cx-1},$y0,{$cx-1},$y1,1,200 fi 31429 if $cx<$x1 line. {$cx+1},$y0,{$cx+1},$y1,1,200 fi 31430 if $cy>$y0 line. $x0,{$cy-1},$x1,{$cy-1},1,200 fi 31431 if $cy<$y1 line. $x0,{$cy+1},$x1,{$cy+1},1,200 fi 31432 line. $x0,$cy,$x1,$cy,1,0 line. $cx,$y0,$cx,$y1,1,0 31433 cy={$y0+(359-$H)*($y1-$y0)/359} 31434 if $cy>$y0 line. $x2,{$cy-1},$x3,{$cy-1},1,200 fi 31435 if $cy<$y1 line. $x2,{$cy+1},$x3,{$cy+1},1,200 fi 31436 line. $x2,$cy,$x3,$cy,1,0 31437 if $rgba_mode 31438 cy={$y0+(255-$A)*($y1-$y0)/255} 31439 if $cy>$y0 line. $x4,{$cy-1},$x5,{$cy-1},1,200 fi 31440 if $cy<$y1 line. $x4,{$cy+1},$x5,{$cy+1},1,200 fi 31441 line. $x4,$cy,$x5,$cy,1,0 31442 fi 31443 ($H^$S^$V^$A) sh. 0,2 hsv2rgb. rm. round. R={i[0]} G={i[1]} B={i[2]} 31444 r. 48,16 drgba. r. {w+2},{h+2},1,3,0,0,0.5,0.5 j.. .,{$x0+55},{$y1+10} rm. 31445 t. "HSV ("{round($H)}","{round($S*255)}","{round($V*255)}")",{$x0+115},{$y1+24},14,1,0 31446 if $rgba_mode t. "RGBA ("$R","$G","$B","{round($A)}")",{$x0+115},{$y1+8},14,1,0 31447 else t. "RGB ("$R","$G","$B")",{$x0+115},{$y1+8},14,1,0 31448 fi 31449 ('${dec2hex\ {$R*65536+$G*256+$B}}') -. {'0'} r. 6,1,1,1,0,0,1,0 +. {'0'} 31450 f. if(i>=_'a'" && "i<=_'z',i+_'A'-_'a',i) 31451 t.. "html ""#"{t},{$x0+115},{$y1+40},14,1,0 rm. 31452 w. 100%,100%,0 rm. 31453 if $rgba_mode $1=$R,$G,$B,$A else $1=$R,$G,$B fi 31454 update_view=0 31455 fi 31456 if $is_thread_variable wait 50 else wait fi 31457 31458 # Manage window size. 31459 ww={*,w} wh={*,h} 31460 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 31461 if {*,r} ww={*,d} wh={*,e} 31462 elif $is_ctrl" && "{*,-D} ww={1.25*$ww} wh={1.25*$wh} 31463 elif $is_ctrl" && "{*,-C} ww={0.8*$ww} wh={0.8*$wh} 31464 elif $is_ctrl" && "{*,R} ww={400+24*$rgba_mode} wh=400 31465 fi 31466 ww={max(200,$ww)} wh={max(200,$wh)} 31467 if $ww!={*,w}" || "$wh!={*,h} w[] $ww,$wh rm fi 31468 31469 # Manage user events. 31470 if $b&1" && "$x>=0" && "$y>=0 31471 if !$is_h" && "!$is_a" && "($is_sv" || "($x>=$x0" && "$x<=$x1" && "$y>=$y0" && "$y<=$y1)) # SV selection 31472 S={max(0,min(1,1-($y-$y0)/($y1-$y0)))} V={max(0,min(1,($x-$x0)/($x1-$x0)))} 31473 update_view=1 colordb=0 is_sv=1 k[0] 31474 elif !$is_sv" && "!$is_a" && "($is_h" || "($x>=$x2" && "$x<=$x3" && "$y>=$y0" && "$y<=$y1)) # H selection 31475 H={max(0,min(359,359-($y-$y0)*359/($y1-$y0)))} 31476 colordb=0 is_h=1 rm 31477 elif !$is_sv" && "!$is_h" && "($is_a" || "($x>=$x4" && "$x<=$x5" && "$y>=$y0" && "$y<=$y1)) # A selection 31478 A={round(max(0,min(255,255-($y-$y0)*255/($y1-$y0))))} 31479 colordb=0 is_a=1 update_view=1 k[0] 31480 elif !$is_sv" && "!$is_h" && "!$is_a" && "{narg($_xsc_old)}" && "$x>=$x0+55" && "$x<=$x0+102" && "\ 31481 $y>=$y1+32" && "$y<=$y1+47 # Old color 31482 ($_xsc_old) y. c sh. 0,2 rgb2hsv. rm. H={i[0]} S={i[1]} V={i[2]} A={i[3]} 31483 colordb=0 rm 31484 elif !$is_sv" && "!$is_h" && "!$is_a" && "$x>=$x6" && "$x<=$x5" && "$y>=$y6" && "$y<=$y6+50" && "\ 31485 ($x-$x6)%25<=20" && "($y-$y6)%25<=20 # Preset. 31486 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. 31487 H={i[0]} S={i[1]} V={i[2]} A={i[3]} 31488 colordb=0 rm 31489 elif !$is_sv" && "!$is_h" && "!$is_a" && "$x>=$x0+55" && "$x<=$x0+102" && "$y>=$y1+10" && "$y<=$y1+27 31490 # Add current as old and/or preset. 31491 _xsc_old=$R,$G,$B,$A colordb={($colordb+1)%2} 31492 if !$colordb # Double-click to add to preset. 31493 _xsc_preset$_xsc_preset=$R,$G,$B,$A _xsc_preset={($_xsc_preset-1)%12} 31494 fi 31495 rm wait -1 31496 else colordb=0 31497 fi 31498 elif !$b is_sv=0 is_h=0 is_a=0 31499 fi 31500 if {*,ARROWUP} colordb=0 S={min(1,$S+1/256)} update_view=1 k[0] wait -1 31501 elif {*,ARROWDOWN} colordb=0 S={max(0,$S-1/256)} update_view=1 k[0] wait -1 31502 elif {*,ARROWRIGHT} colordb=0 V={min(1,$V+1/256)} update_view=1 k[0] wait -1 31503 elif {*,ARROWLEFT} colordb=0 V={max(0,$V-1/256)} update_view=1 k[0] wait -1 31504 elif {*,PAGEUP} colordb=0 H={min(359,$H+1)} rm wait -1 31505 elif {*,PAGEDOWN} colordb=0 H={max(0,$H-1)} rm wait -1 31506 fi 31507 31508 # Check RGB variable modification from another thread. 31509 if ['$$1']=='-1' break fi # Close request 31510 if (($rgba_mode" && "['$$1']!='$R,$G,$B,$A')" || "(!$rgba_mode" && "['$$1']!='$R,$G,$B'))" && "\ 31511 $x<0" && "$y<0" && "!$is_sv" && "!$is_h" && "!$is_a 31512 ($$1) y. c -. 255 r. 1,1,1,4,0 +. 255 sh. 0,2 rgb2hsv. rm. 31513 H={i[0]} S={i[1]} V={i[2]} A={i[3]} rm 31514 fi 31515 31516 while {*}" && "!{*,ESC}" && "!{*,Q} 31517 rm w 0 31518 if $rgba_mode u $R,$G,$B,$A else u $R,$G,$B fi 31519 _xsc_old=${} 31520 31521#@cli x_select_function1d : _variable_name,_background_curve_R,_background_curve_G,_background_curve_B 31522#@cli : Open an interactive window, where the user can defined its own 1D function. 31523#@cli : If an image is selected, it is used to display additional information : 31524#@cli : - The first row defines the values of a background curve displayed on the window (e.g. an histogram). 31525#@cli : - The 2nd, 3rd and 4th rows define the R,G,B color components displayed beside the X and Y axes. 31526#@cli : Argument 'variable_name' specifies the variable that contains the selected function keypoints at any time. 31527#@cli : Assigning '-1' to it forces the interactive window to close. 31528#@cli : Default values: 'variable_name=xsf_variable', 'background_curve_R=220', \ 31529# 'background_curve_G=background_curve_B=background_curve_T'. 31530x_select_function1d : skip ${1=xsf_variable},${2=220},${3=$2},${4=$2} check_display $0 31531 e[^-1] "Open 1D function widget, with variable name '$1'." 31532 if $! k[0] fi 31533 is_additional_data=$! 31534 if !{*} w[] 400,400,0,"Create a 1D function" fi 31535 reset_w={*,w} reset_h={*,h} 31536 if !narg($$1) $1=0,0,100,100 fi 31537 ($$1) nm. points y. x r. 2,{w/2},1,1,-1 31538 is_thread_variable={arg(1,{'$1'})==_'_'" && "arg(2,{'$1'})==_'_'} selected=-1 X=-1 Y=-1 31539 do 31540 31541 # Update base view. 31542 if !narg($baseview) 31543 {{*,d}-48},{{*,e}-48},1,3,255 31544 if $is_additional_data # Render background graph. 31545 100%,100% +rows[0] 0 graph.. .,3,0,0,0,1,1 rm. c. 0,1 31546 +fc.. ${2-4} j... .,0,0,0,0,1,.. rm[-2,-1] 31547 fi 31548 grid. {(w-1)/8},{(h-1)/8},0,0,0.2,0xCCCCCCCC,0 31549 line. 0,100%,100%,0,0.2,0 31550 frame. 24,24,200 31551 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 31552 if $is_additional_data" && "{0,h}>1 # Render colored X-axis guide. 31553 if {0,h}>2 +rows[0] 1,3 else +rows[0] 1 r. 100%,3 fi 31554 r. {-2,w-48},3,1,1,3 permute. xzcy r. 100%,8 frame. 1,1,0 31555 j.. .,23,{-2,h-19} rotate. -90 j.. .,{-2,w-19},23 rm. 31556 fi 31557 nm. baseview 31558 l rm[view] onfail endl 31559 fi 31560 31561 # Update view. 31562 if !narg($view) 31563 +z[baseview] 24,24,{baseview,w-25},{baseview,h-25} r. 200%,200% 31564 31565 # Draw curve. 31566 function1d[] 1,{points,^} 31567 l. c 0,100 transpose 31568 i[0] ({'CImg3d'},{h},{h-1}) 31569 i.. 1,100%,1,1,y 1,100% a[-3--1] x 31570 1,{h-1},1,1,2 +f. y ++. 1 a[-3--1] x 31571 4,100%,1,1,1 y a y col3d 0 31572 endl 31573 *3d. {-2,(w-1)/100},{-2,(1-h)/100} 31574 j3d.. .,0,100%,0,1,1,0,0 rm. 31575 31576 # Draw control points. 31577 repeat h#$points 31578 x={points,i(0,$>)} y={100-{points,i(1,$>)}} 31579 circle. $x%,$y%,6,1,0xFFFFFFFF,0 31580 done 31581 if $selected>=0 31582 x={points,i(0,$selected)} y={100-{points,i(1,$selected)}} 31583 circle. $x%,$y%,3,1,0 31584 fi 31585 31586 r. 50%,50%,1,3,2 31587 +j[baseview] .,24,24 rm.. 31588 31589 # Draw current coordinates. 31590 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 31591 nm. view 31592 w[view] 31593 fi 31594 31595 if $is_thread_variable wait 50 else wait fi 31596 31597 # Manage user events. 31598 x={*,x} y={*,y} b={*,b} is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 31599 X={($x-24)*100/({*,w}-49)} Y={100-($y-24)*100/({*,h}-49)} 31600 oww={*,w} owh={*,h} ww=$oww wh=$owh 31601 if {*,r} ww={*,d} wh={*,e} # Resize window. 31602 elif $is_ctrl" && "{*,-D} ww={view,w*125%} wh={view,h*125%} # Increase window size. 31603 elif $is_ctrl" && "{*,-C} ww={view,w*75%} wh={view,h*75%} # Decrease window size. 31604 elif $is_ctrl" && "{*,R} ww=$reset_w wh=$reset_h # Reset window size. 31605 elif !$is_ctrl" && "{*,R} rm[points] (0,0;100,100) nm. points $1={points,^} rm[view] # Reset keypoints. 31606 elif $b&3 # Add/move/delete point. 31607 is_inside={$X>=0" && "$Y>=0" && "$X<=100" && "$Y<=100} 31608 31609 # Check for a point selection. 31610 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 31611 31612 if $x>=0" && "$b&1" && "$selected>=0 # Move an existing point. 31613 if {*,SHIFTLEFT}" || "{*,SHIFTRIGHT} X={points,i(0,$selected)} fi 31614 if {*,CTRLLEFT}" || "{*,CTRLRIGHT} Y={points,i(1,$selected)} fi 31615 if {points,$selected>0" && "$selected<h-1} 31616 =[points] {points,max(min($X,i(0,$selected+1)-0.5),i(0,$selected-1)+0.5)},0,$selected 31617 fi 31618 =[points] {min(100,max(0,$Y))},1,$selected $1={points,^} rm[view] 31619 31620 elif $b&1" && "$is_inside # Create new point. 31621 ($X,$Y) a[points,-1] y sort[points] +,y 31622 +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] 31623 elif $b&2" && "$selected>0" && "$selected<{points,h-1}" && "$is_inside # Delete an existing point. 31624 l[points] s y rm[$selected] a y endl wait -1 selected=-1 $1={points,^} rm[view] 31625 fi 31626 elif !($b&1) selected=-1 31627 fi 31628 31629 # Manage window size. 31630 ww={min(90%*{*,u},max(200,$ww))} 31631 wh={min(90%*{*,v},max(200,$wh))} 31632 if $oww!=$ww" || "$owh!=$wh w[] $ww,$wh rm[baseview,view] fi 31633 31634 # Check points variable modification from another thread. 31635 if ['$$1']=='-1' break fi # Close request 31636 if ['$$1']!=['{points,^}'] # Keypoints changed 31637 rm[points] ($$1) nm. points y. x r. 2,{w/2},1,1,-1 l rm[view] onfail endl 31638 fi 31639 31640 while {*}" && "!{*,ESC}" && "!{*,Q} 31641 w[] 0 u {points,^} 31642 if $is_additional_data rm[^0] else rm fi 31643 31644#@cli x_select_palette : _variable_name,_number_of_columns={ 0=auto | >0 } 31645#@cli : Open a RGB or RGBA color selector widget from a palette. 31646#@cli : The palette is given as a selected image. 31647#@cli : Argument 'variable_name' specifies the variable that contains the selected color values (as R,G,B,[A]) 31648#@cli : at any time. 31649#@cli : Assigning '-1' to it forces the interactive window to close. 31650#@cli : Default values: 'variable_name=xsp_variable' and 'number_of_columns=2'. 31651x_select_palette : skip ${1=xsp_variable},${2=0} check_display $0 31652 if !$! error[0--3] "Command '$0': Missing specified palette image." fi 31653 k[0] +r {w*h*d},1,1,{s},-1 to_color. rgba_mode={s==4} to_rgba. nm. palette 31654 e[^-1] "Open "${arg\ 1+$rgba_mode,RGB,RGBA}" color selector widget for palette$?, with variable name '$1'." 31655 31656 if w>1024 error[0--3] "Command '$0': Too much colors ("{w}") in selected palette." fi 31657 if !{*} w[] 400,400,0,0,-1,-1,"Palette: "{0,b} fi 31658 31659 selected=-1 oselected=-1 31660 do 31661 ww={*,w} wh={*,h} 31662 R={palette,round(i($selected,0,0,0))} G={palette,round(i($selected,0,0,1))} 31663 B={palette,round(i($selected,0,0,2))} A={palette,round(i($selected,0,0,3))} 31664 31665 # Update color in specified variable. 31666 if $selected>=0" && "$oselected!=$selected 31667 if $rgba_mode $1=$R,$G,$B,$A else $1=$R,$G,$B fi 31668 fi 31669 31670 # Check close request from external thread. 31671 if ['$$1']=='-1' break fi 31672 31673 # Create base view. 31674 if !narg($baseview) l[palette] 31675 {w},1,1,1,x +. 1 31676 s. x append_tiles[^0] $2 31677 M={w} N={h} 100%,100%,1,1,1 31678 +r. {$ww-17},100%,1,1,4 31679 r.. 100%,{$wh-57},1,1,4 31680 r[-2,-1] .,.. -|[-2,-1] 31681 line. 100%,0,100%,100%,1,1 31682 line. 0,100%,100%,100%,1,1 31683 -. 1 *. -1 31684 r.. .,.,1,1,1 -.. 1 31685 +map.. [0],0 drgba. 31686 rv[-2,-1] *[-2,-1] 31687 +!=.. -1 dilate. 3 31688 mv... $! +. 1 a[-3--1] c 31689 nm. baseview 31690 endl 31691 if narg($view) rm[view] fi 31692 fi 31693 31694 # Create and display view. 31695 if !narg($view) 31696 $ww,$wh,1,3,200 31697 if $selected<0 sh[baseview] 0,2 31698 else 31699 +channels[baseview] 0,2 +channels[baseview] 4,4 31700 !=. {$selected+1} rectangle. 0,0,100%,100%,1,0xFFFFFFFF,1 31701 +dilate. 5 -[-2,-1] *. -1 +dilate. 5 *.. 255 31702 r.. 100%,100%,1,3 j... ..,0,0,0,0,1,. rm[-2,-1] 31703 if $rgba_mode t.. "RGBA ("$R","$G","$B","$A")",8,{$wh-45},14,1,0 31704 else t.. "RGB ("$R","$G","$B")",8,{$wh-45},14,1,0 31705 fi 31706 ($R^$G^$B) rgb2hsv. H={round(i[0])} S={round(i[1]*255)} V={round(i[2]*255)} rm. 31707 t.. "HSV ("$H","$S","$V")",8,{$wh-31},14,1,0 31708 ('${dec2hex\ {$R*65536+$G*256+$B}}') -. {'0'} r. 6,1,1,1,0,0,1,0 +. {'0'} 31709 f. if(i>=_'a'" && "i<=_'z',i+_'A'-_'a',i) 31710 t... "html ""#"{t},8,{$wh-17},14,1,0 rm. 31711 fi 31712 sh[baseview] 3 j... ..,8,8,0,0,1,. rm[-2,-1] 31713 nm. view w[view] 31714 fi 31715 31716 if arg(1,{'$1'})==_'_'" && "arg(2,{'$1'})==_'_' wait 50 else wait fi 31717 31718 # Manage window size. 31719 is_ctrl={{*,CTRLLEFT}" || "{*,CTRLRIGHT}} 31720 if {*,r} ww={*,d} wh={*,e} 31721 elif $is_ctrl" && "{*,-D} ww={1.25*$ww} wh={1.25*$wh} 31722 elif $is_ctrl" && "{*,-C} ww={0.8*$ww} wh={0.8*$wh} 31723 elif $is_ctrl" && "{*,R} ww=400 wh=400 31724 fi 31725 ww={max(200,$ww)} wh={max(200,$wh)} 31726 if ($ww!={*,w}" || "$wh!={*,h})" && "narg($baseview) w[] $ww,$wh rm[baseview] fi 31727 31728 # Handle user events. 31729 oselected=$selected 31730 if narg($baseview) 31731 x={*,x} y={*,y} b={*,b} 31732 if $b&1" && "$x>=0" && "$y>=0 # Select color. 31733 if {baseview,i($x-8,$y-8,0,4)} selected={baseview,i($x-8,$y-8,0,4)-1} else selected=-1 fi 31734 rm[view] wait -1 31735 elif {*,ARROWUP}" && "$selected>=$M selected-=$M rm[view] wait -1 31736 elif {*,ARROWDOWN}" && "$selected<{0,w-$M} selected+=$M rm[view] wait -1 31737 elif {*,ARROWRIGHT}" && "$selected<{0,w-1} selected+=1 rm[view] wait -1 31738 elif {*,ARROWLEFT}" && "$selected>0 selected-=1 rm[view] wait -1 31739 fi 31740 fi 31741 31742 while {*}" && "!{*,ESC}" && "!{*,Q} 31743 w 0 k[0] 31744 if $selected>=0 if $rgba_mode u $R,$G,$B,$A else u $R,$G,$B fi else u -1 fi 31745 31746#@cli x_shadebobs 31747#@cli : Launch the shade bobs demo. 31748x_shadebobs : check_display $0 31749 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31750 e[] "\n 31751------ "${g}"Shade bobs"$n" -------------------------------\n 31752----\n 31753---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 31754---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 31755---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31756----\n 31757-------------------------------------------------" 31758 rm t=100 w 512,512,0,"[G"{`39`}"MIC] Shade Bobs" 31759 31760 # Start animation loop. 31761 do 31762 t+=0.015 31763 if $t>4*pi" || "{*,b} # Reset motions variables if necessary. 31764 rx={u(-1,1)} ry={u(-1,1)} rz={u(-1,1)} rt={u(-1,1)} rcx={u(-0.6*0.6)} t=0 31765 N={20+round(u(80))} R={(2+round(u(40)))*min({*,w},{*,h})/300} 31766 if $obj3d rm[colormap,img,obj3d] fi 31767 {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 31768 (67.5;73.5;109.5;103.5;51.5;100.5;{2*$N};$N) 3,{2*$N},1,1,0 31769 1,$N,1,1,5 2,$N,1,1,'y+x*$N' a[-2--1] x z. 0,5 31770 4,$N,1,1,1 y[-3--1] a[-4--1] y nm. obj3d 31771 {*,w},{*,h} nm. img 31772 wait -1 31773 fi 31774 31775 # Compute bobs coordinates. 31776 r={$ry+$rx*cos(6*$rz*$t)+(1-$rx)*sin(6*$rt*$t)} 31777 (0;{30*$ry*($N-1)}) ($t;{2*pi*($N-1)/$N+$t}) r[-2,-1] 1,$N,1,1,3 31778 +.. {360*sin($rz*$t)} *.. {pi/180} 31779 +sin[-2,-1] cos[-4,-3] *[-4,-2] $r *[-3,-1] $rcx +[-4,-3] +[-2,-1] 31780 *.. {{*,w}/2} *. {{*,h}/2} a[-2,-1] x 31781 ++. $R -.. $R a[-2,-1] y z. 0,2 y. j[obj3d] .,0,8 rm. 31782 31783 # Draw bobs, map colors and display. 31784 j3d[img] [obj3d],50%,50%,0,-1,2,0,0 31785 &[img] 255 +map[img] [colormap] w. rm. wait 20 31786 if {*,CTRLLEFT}" && "{*,D} w[] 1024,1024 elif {*,CTRLLEFT}" && "{*,C} w[] 512,512 fi 31787 while {*}" && "!{*,ESC}" && "!{*,Q} 31788 rm w 0 31789 31790#@cli x_spline 31791#@cli : Launch spline curve editor. 31792x_spline : check_display $0 31793 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31794 e[] "\n 31795------ "${g}"Spline curve editor"$n" --------------------------\n 31796----\n 31797---- "${c}"Mouse"$n" to insert/move/delete points.\n 31798---- Key '"${c}"R"$n"' to reset the curve.\n 31799---- Key '"${c}"SPACE"$n"' to shows/hide spline curve.\n 31800---- Key '"${c}"P"$n"' to shows/hide control points.\n 31801---- Key '"${c}"ENTER"$n"' to shows/hide control polygon.\n 31802---- Key '"${c}"T"$n"' to shows/hide point tangents.\n 31803---- Key '"${c}"I"$n"' to shows/hide point indices.\n 31804---- Key '"${c}"C"$n"' to shows/hide point coordinates.\n 31805---- Keys '"${c}"+"$n"' and '"${c}"-"$n"' to increase/decrease roundness.\n 31806---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31807----\n 31808-----------------------------------------------------" 31809 31810 # Init display and variables. 31811 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 31812 w[0] {0,w},{0,h},0,0,{n} r[0] {*,w},{*,h},1,3,1 31813 i[1] 1 # Point coordinates 31814 roundness=0.5 # Curve roundness 31815 visuflags=23 # Visualisation flags 31816 nearest=-1 # Nearest point 31817 active=-1 # Active point 31818 31819 # Start event loop. 31820 do 31821 31822 # Init coordinates [1] if necessary. 31823 if {1,whds}==1 31824 rm[1] roundness=0.5 nearest=-1 active=-1 31825 i[1] ({0.2*w},{0.2*h};\ 31826 {0.2*w},{0.8*h};\ 31827 {0.8*w},{0.8*h};\ 31828 {0.8*w},{0.2*h}) 31829 fi 31830 31831 # Estimate screen-normalized coordinates [2], curve tangents [3] and tangent orientations [4]. 31832 [1] ({{*,w}/{0,w}},{{*,h}/{0,h}}) *[-2,-1] # Normalized coordinates. 31833 +shift[2] 0,-1,0,0,2 +shift[2] 0,1,0,0,2 -[-2,-1] *. $roundness # Curve tangents. 31834 +s. x sqr[-2,-1] +[-2,-1] sqrt. r. 2 +/[-2,-1] rm.. # Tangent orientations. 31835 31836 # Display curve, control points, polygon and tangents. 31837 +r[0] {*,w},{*,h},1,3 31838 if $visuflags&4 polygon. {2,h},{2,^},0.3,128,200,255 fi 31839 repeat h#1 31840 line. {2,@0-3},0.3,255,255,0 31841 if $visuflags&1 spline. {2,@0-1},{3,@0-1},{2,@2-3},{3,@2-3},1,255 fi 31842 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 31843 if $visuflags&16 t. $>,{{2,@0}-3},{{2,@1}-18},13,1,255,255,0 fi 31844 if $visuflags&32 t. "("{round({1,@0})}","{round({1,@1})}")",{{2,@0}-16},{{2,@1}+10},13,1,100,200,255 fi 31845 shift[1-4] 0,-1,0,0,2 31846 done 31847 if $visuflags&2 repeat h#1 31848 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 31849 done fi 31850 w. rm[3,4,-1] wait 31851 31852 # Handle key events. 31853 if {*,SPACE} visuflags+={if($visuflags&1,-1,1)} wait -1 fi # Show/hide spline 31854 if {*,P} visuflags+={if($visuflags&2,-2,2)} wait -1 fi # Show/hide points 31855 if {*,ENTER} visuflags+={if($visuflags&4,-4,4)} wait -1 fi # Show/hide polygon 31856 if {*,T} visuflags+={if($visuflags&8,-8,8)} wait -1 fi # Show/hide tangents 31857 if {*,I} visuflags+={if($visuflags&16,-16,16)} wait -1 fi # Show/hide indices 31858 if {*,C}" && "!{*,CTRLLEFT}" && "!{*,CTRLRIGHT} # Show/hide coordinates 31859 visuflags+={if($visuflags&32,-32,32)} wait -1 fi 31860 if {*,PADADD}" && "$roundness<1 roundness*=1.1 wait -1 fi # Increase roundness 31861 if {*,PADSUB}" && "$roundness>0.1 roundness*=0.9 wait -1 fi # Decrease roundness 31862 if {*,R}" && "!{*,CTRLLEFT}" && "!{*,CTRLRIGHT} rm. i[1] 1 wait -1 fi # Reset curve 31863 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} w[] {{*,w}*1.5},{{*,h}*1.5} fi # Increase window size 31864 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} w[] {{*,w}/1.5},{{*,h}/1.5} fi # Decrease window size 31865 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} w[] {0,w},{0,h} fi # Reset window size 31866 if {*,r} w[] fi # Resize window if necessary. 31867 31868 # Set/unset active point. 31869 if {*,b}==0 active=-1 # Unset active point if mouse button is released 31870 elif {*,x}>=0" && "{*,b}" && "$active==-1 # Find new active point 31871 [2] ({*,x},{*,y}) -[-2,-1] sqr. s. x +[-2,-1] # Compute distance vector to points 31872 nearest={ym} # Set nearest point 31873 if im<64 active=$nearest fi # Set it as active point, if near enough 31874 rm. 31875 fi 31876 rm[2] 31877 31878 # Move active point. 31879 if {*,b}&1" && "{*,x}>=0" && "$active!=-1 31880 =[1] {{*,x}*{0,w}/{*,w}},0,$active 31881 =[1] {{*,y}*{0,h}/{*,h}},1,$active 31882 31883 # Delete nearest point. 31884 elif {*,b}&2" && "{*,x}>=0" && "{1,h}>3 31885 l[1] s y rm[$nearest] a y endl wait -1 31886 31887 # Insert new active point. 31888 elif {*,b}&1" && "{*,x}>=0 31889 xy=({{*,x}*{0,w}/{*,w}},{{*,y}*{0,h}/{*,h}}) # Point coordinates in the image basis 31890 +shift[1] 0,-1,0,0,2 +. [1] /. 2 # Compute center of segments 31891 $xy -[-2,-1] sqr. s. x +[-2,-1] # Compute distance vector to segments 31892 ns={ym} rm. # Get nearest segment 31893 l[1] s y i[{$ns+1}] $xy a y endl # Insert new point at right position 31894 active={$ns+1} # Set new active point as newly inserted 31895 fi 31896 31897 while {*}" && "!{*,ESC}" && "!{*,Q} 31898 31899 # Render spline as a tertiary mask for output. 31900 +shift[1] 0,-1,0,0,2 +shift[1] 0,1,0,0,2 -[-2,-1] *. $roundness 31901 [0],[0],1,1,2 rm[0] 31902 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 31903 flood. 0,0,0,0,0,1,0 31904 31905 # Exit properly. 31906 rm[0,1] w 0 31907 31908#@cli x_starfield3d 31909#@cli : Launch the 3D starfield demo. 31910x_starfield3d : check_display $0 31911 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31912 e[] "\n 31913------ "${g}"3D starfield"$n" ---------------------------------------\n 31914----\n 31915---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31916----\n 31917-----------------------------------------------------------" 31918 l[] 31919 ('G\47MIC') s x 31920 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] 31921 expand_xy 6,0 dilate_circ 5 b 0.5 expand_z 1,0 isosurface3d 10% *3d 1,1,5 rv3d 31922 repeat $N col3d[$>] ${-rgb} done 31923 0 t. "Version "${-strver},0,0,48,1,1 r2dy. 18 +f. 255 to_rgb. 31924 random3d 2500 col3d. 255 *3d. 320,200,1000 -3d. 160,100 31925 l3d 0,0,-600 31926 w[] 640,400,0,"[G"{`39`}"MIC] 3D Starfield" 31927 t0=0 t=0 31928 31929 do 31930 320,200,1,3 31931 31932 # Starfield. 31933 l.. s3d 31934 r[2] 3,{2,h/3},1,1,-1 s[2] x %[4] 1000 31935 +/[4] 1000 *. -1 n. 0,2 c. 0,1 sqr. j.. . rm. 31936 a[2-4] x 31937 y a y 31938 endl 31939 j3d. ..,50%,50%,-600,1,0,0,0,240 -3d.. 0,0,{min(12,$t0/10-4)} 31940 31941 # Torus. 31942 torus3d 100,30 col3d. 255,64,255 31943 +col3d. 64,64,255 r3d. 1,0,0,-90 +3d. 65,0,0 31944 +3d[-2,-1] c3d. 31945 r3d. 1,1,0,{-6*$t} r3d. 0,0,1,{2*$t} 31946 j3d.. .,{($t-200)*2}%,50%,0,0.25,3,0,0 rm. 31947 31948 # Letters. 31949 repeat $N 31950 +r3d[$>] 1,{$>%4},1,{-${z$>}/2} 31951 j3d.. .,{90+${x$>}},{60+${y$>}},${z$>},1,4,0,0 rm. 31952 z$>={tl=280+6*$<;if($t<tl,min(0,${z$>}+20),-20*($t-tl))} 31953 done 31954 31955 # Presents. 31956 if $t<280 op={max(0,min(1,($t-200)/20))} 31957 else op={max(0,1-($t-280)/20)} 31958 fi 31959 j. ...,{(w-{-3,w})/2},120,0,0,$op,[-4] 31960 31961 w. wait 30 rm. 31962 t0+=1 t={$t0%350} 31963 if !$t x=0 repeat 5 z$>={-3200-150*$>} done fi 31964 31965 while {*}" && "!{*,ESC}" && "!{*,Q} 31966 w[] 0 rm endl 31967 31968#@cli x_tetris 31969#@cli : Launch tetris game. 31970x_tetris : check_display $0 31971 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 31972 e[] "\n 31973------ "${g}"Tetris"$n" --------------------------------------------\n 31974----\n 31975---- This is a G\47MIC implementation of the "${g}"Tetris"$n" game.\n 31976----\n 31977---- "${c}"Arrow keys"$n" to move/rotate the triominos.\n 31978---- Key '"${c}"SPACE"$n"' to make the current triomino falling.\n 31979---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 31980----\n 31981----------------------------------------------------------" 31982 rm 31983 31984 # Init board and triominos shapes. 31985 4,1,1,1,1,1,1,1 31986 3,2,1,1,1,0,0,1,1,1 31987 3,2,1,1,0,0,1,1,1,1 31988 2,2,1,1,1,1,1,1 31989 3,2,1,1,0,1,1,1,1,0 31990 3,2,1,1,0,1,0,1,1,1 31991 3,2,1,1,1,1,0,0,1,1 31992 nm[-7--1] m0,m4,m8,m12,m16,m20,m24 31993 31994 if u<0.25 # Enable extended set. 31995 i 2,1,1,1,1,1 31996 i 2,2,1,1,1,1,0,1 31997 i 3,1,1,1,1,1,1 31998 i 1,1,1,1,1 31999 i 3,2,1,1,1,1,1,1,0,1 32000 i 3,3,1,1,1,1,1,1,0,1,1,1,1 32001 nm[-6--1] m28,m32,m36,m40,m44,m48 32002 fi 32003 repeat $! i={4*$>} l[m$i] repeat 3 +rotate[0] {90*($>+1)} nm. m{$i+$>+1} done endl done 32004 N=$! 32005 32006 # Render triomino colored sprites. 32007 3,$N,1,1,'u(16,224)' r. 3,400% nm. colors 32008 (0,-1,0;1,0,-1;0,1,0) *. 120 nm. mask 32009 repeat $N 32010 +r[m$>] 500%,500%,1,3 +correlate. [mask],0 r. 200%,200%,1,1,3 ri.. . *[-2,-1] c. 30%,100% 32011 +r[m$>] .,.,1,3 +replace_color. 0,0,1,1,1,{colors,@{3*$>}-{3*$>+2}} rv[-3,-1] +[-3,-1] c.. 0,255 32012 channels. 0 *. 255 a[-2,-1] c nm. s$> 32013 done 32014 rm[colors,mask] 32015 fact={{s0,w}/{m0,w}} 32016 32017 # Generate board and background. 32018 W=12 H=20 32019 $W,$H . nm[-2,-1] board,curr_board 32020 {$fact*$W},{$fact*$H},1,3 . nm[-2,-1] render,curr_render +channels. 0 nm. curr_render_mask 32021 +rows[render] 0,50% plasma. 1,2 noise. 20 blur_y. 40%,1 +mirror. y a[-2,-1] y ri. [render] 32022 n. 0,64 blur_x. 1 100%,100% noise. 0.5,2 ==. 1 b. 1 *. 300 +[-2,-1] c. 0,255 nm. background 32023 32024 # Start game. 32025 time=$| score=0 fall_mode=0 gameover=0 n=-1 nn={round(u(0,$N-1))} 32026 do 32027 wait {if($fall_mode,-1,-20)} 32028 32029 # In case of game over. 32030 if $gameover 32031 +j[background] [curr_render],0,0,0,0,0.7,[curr_render_mask],255 32032 to. "Game\nOver!",22,30%,32,2,1,255 w. rm. 32033 continue 32034 fi 32035 32036 # Check for completed lines and select new random triomino. 32037 if $n<0 32038 l[board] s y i=-1 repeat $! if {$<,im} i=$<,$i fi done 32039 0 rm[$i] a y score+={2^(narg($i)-1)-1} r $W,$H,1,1,0,0,0,1 nm board endl 32040 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 32041 n=$nn nn={round(u(0,$N-1))} x={$W/2} y=0 do_render=1 fall_mode=0 32042 fi 32043 32044 # Render board at current time. 32045 if $do_render 32046 rm[curr_board,curr_render,curr_render_mask] 32047 [board] nm. curr_board j[curr_board] [m$n],{$x-int({m$n,w}/2)},$y,0,0,1,[m$n] 32048 [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. 32049 +*[curr_board] 255 r. [curr_render],[curr_render] nm. curr_render_mask 32050 0 t. "Score : "$score" Next :",4,0,25,1,200 r. 50%,50%,1,3,2 +!=. 0 *. 255 32051 j[curr_render] ..,0,0,0,0,1,.,255 j[curr_render_mask] .,0,0,0,0,1,.,255 rm[-2,-1] 32052 +*[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. 32053 do_render=0 32054 fi 32055 32056 +shift[background] 0,{round(-13*$|*1.04^$score)},0,0,2 32057 j. [curr_render],0,0,0,0,1,[curr_render_mask],255 32058 w. {2.25*w},{2.25*h},0,"[G"{`39`}"MIC] Tetris" rm. cursor[0] 0 32059 32060 # Manage user interactions. 32061 if {*,SPACE} fall_mode=1 fi 32062 if {*,ARROWUP}" || "{*,ARROWLEFT}" || "{*,ARROWRIGHT} 32063 an={if({*,ARROWUP},n=$n+1;if(n%4,n,n-4),$n)} 32064 nx={w2=int({m$an,w}/2);max(w2,min($x-{*,ARROWLEFT}+{*,ARROWRIGHT},$W-({m$an,w}%2)-w2))} 32065 +j[board] [m$an],{$nx-int({m$an,w}/2)},$y,0,0,-1,[m$an] 32066 if iM==1 x=$nx n=$an fi 32067 rm. 32068 do_render=1 32069 fi 32070 32071 if {*,ARROWDOWN}" || "$|-$time>0.9^int($score/2)" || "$fall_mode # Piece goes down. 32072 y+=1 32073 +j[board] [m$n],{$x-int({m$n,w}/2)},$y,0,0,-1,[m$n] 32074 if iM>1" || "$y+{m$n,h}>$H 32075 if $y<=1 gameover=1 fi # Game over! 32076 j[board] [curr_board] j[render] [curr_render] n=-1 32077 fi 32078 rm. 32079 time=$| do_render=1 32080 fi 32081 32082 while {*}" && "!{*,ESC}" && "!{*,Q} 32083 rm w 0 32084 32085#@cli x_threshold 32086#@cli : Threshold selected images interactively. 32087x_threshold : 32088 e[^-1] "Threshold image"$_gmic_s" interactively." 32089 repeat $! l[$>] 32090 wsiz0=${"fitscreen ."} 32091 value=-1 32092 w[] $wsiz0,0,"[G'MIC] "{n}" - Interactive threshold" 32093 0 32094 for {*}" && "!{*,ESC} 32095 32096 if [w#1,h#1]!=[{*,w,h}] # Generate image view 32097 rm[1] +slices[0] 50% r. {*,w,h},1,100%,1 w. 32098 fi 32099 32100 mx,my,mb={*,x,y,b} 32101 if $mb" && "$mx>=0" && "$my>=0 32102 value={"w>h?( dw1 = "{*,w}" - 1; val = (dw1 - "$mx")*100/dw1; ): 32103 ( dh1 = "{*,h}" - 1; val = (dh1 - "$my")*100/dh1; )"} 32104 update_view=1 32105 fi 32106 32107 if $update_view 32108 if $value>=0 32109 +ge[1] $value% *. 255 32110 to. "Threshold: "{_round($value,0.1)}%,1%,1%,{max(13,3.5*h%)} 32111 w. rm. 32112 else w. 32113 fi 32114 update_view=0 32115 fi 32116 32117 wait 32118 if {*,r} update_view=1 fi 32119 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,D} 32120 w[] {{*,w}*1.5},{{*,h}*1.5} wait -1 update_view=1 32121 fi 32122 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,C} 32123 w[] {{*,w}/1.5},{{*,h}/1.5} wait -1 update_view=1 32124 fi 32125 if ({*,CTRLLEFT}" || "{*,CTRLRIGHT})" && "{*,R} 32126 w[] $wsiz0 wait -1 update_view=1 32127 fi 32128 done 32129 w[] 0 rm. u $value% ge ${} 32130 endl done 32131 32132#@cli x_tictactoe 32133#@cli : Launch tic-tac-toe game. 32134x_tictactoe : check_display $0 32135 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32136 e[] "\n 32137------ "${g}"Tic-Tac-Toe game"$n" -----------------\n 32138----\n 32139---- Use "${c}"mouse"$n" to select positions of the\n 32140---- symbols. Close window to exit game.\n 32141----\n 32142-----------------------------------------" 32143 32144 # Allocate variables. 32145 message=0 # [-7] : State message. 32146 counter=0 # [-6] : Turn counter (0 to 8). 32147 player=0 # [-5] : Current player (0 or 1). 32148 state=0 # [-4] : Board state. 32149 tmp3=0 # [-3] : Temporary variable 3. 32150 tmp2=0 # [-2] : Temporary variable 2. 32151 tmp1=0 # [-1] : Temporary variable 1. 32152 _x_tictactoe2 # Generate board. 32153 w. -1,-1,0," " # Init display window. 32154 32155 # Start main loop. 32156 do 32157 32158 # Set state message depending on the current player. 32159 if $player message="Tic-Tac-Toe (O to play)" 32160 else message="Tic-Tac-Toe (X to play)" 32161 fi 32162 32163 # Select position by the user. 32164 do # Enter event loop. 32165 w[] {w},{h},0,"[G"{`39`}"MIC] "$message wait # Wait for events and force window size if necessary. 32166 if !{*}" || "{*,ESC}" || "{*,Q} w[] 0 rm return fi # Quit properly if window has been closed. 32167 if {*,b}&1" && "{*,x}>20" && "{*,y}>20" && "{*,x}<400" && "{*,y}<400 # If mouse button pressed on the board area. 32168 tmp3={int(({*,x}-15)/130)} # X of the selected position (0,1 or 2). 32169 tmp2={int(({*,y}-15)/130)} # Y of the selected position (0,1 or 2). 32170 tmp1={4^($tmp2*3+$tmp3)} # Get state code of the selected position. 32171 if int($state/$tmp1)%4 tmp1=-1 fi # Check availability of position. 32172 else tmp1=-1 fi # If no mouse button, do nothing but loop. 32173 while $tmp1<0 # Go on until a valid position selected. 32174 32175 # Draw symbol on selected position and update board state. 32176 _x_tictactoe{$player%2} # Generate the symbol sprite and his mask. 32177 j... ..,{"130*"$tmp3" + 15+u(-5,5)"},\ # Draw symbol (with some fuzzyness). 32178 {"130*"$tmp2" + 15+u(-5,5)"},0,0,1,. 32179 rm[-2--1] # Delete sprite and mask. 32180 w. # Update display window. 32181 state+={(1+$player)*$tmp1} # Update the board state. 32182 32183 # Check for a winning configuration. 32184 (21,1344,86016,4161,16644,66576,65793,4368;\ # The list of winning configurations. 32185 0,0,0,0,1,2,0,0;\ # Corresponding X coords for the stroke. 32186 0,1,2,0,0,0,0,0;\ # Corresponding Y coords for the stroke. 32187 3,3,3,4,4,4,5,6) # Corresponding index of the stroke sprite. 32188 repeat w # Start to check configurations. 32189 tmp1={@$>} # Save the current configuration code. 32190 if ($state&$tmp1)==$tmp1||($state&(2*$tmp1))==2*$tmp1 # If a winner has been found. 32191 _x_tictactoe{i($>,3)} # Generate the stroke symbol and his mask. 32192 j[-4] ..,{130*{-3,i($>,1)}+u(-5,5)},\ # And display it on the board. 32193 {130*{-3,i($>,2)}+u(-5,5)},0,0,1,. rm[-2--1] 32194 if ($state&$tmp1)==$tmp1 w.. -1,-1,0,"Tic-Tac-Toe (X won!)" 32195 else w.. -1,-1,0,"Tic-Tac-Toe (O won!)" # Update display window. 32196 fi 32197 do wait 32198 if {*} w[] {*,w},{*,h} fi 32199 while {*}" && "!{*,ESC}" && "!{*,Q} # Wait for the window to be closed. 32200 rm w[] 0 return # And return properly. 32201 fi 32202 done # Go on until all configurations checked. 32203 rm. # Delete winning configuration data. 32204 32205 player={($player+1)%2} # Select next player. 32206 counter+=1 # Increment turn counter. 32207 while $counter<9 # Loop to next move until all positions filled. 32208 32209 # Here, the game has been ended without winners. 32210 w[] -1,-1,0,0,"Tic-Tac-Toe (Tied game!)" # Change window title. 32211 do wait 32212 if {*} w[] {*,w},{*,h} fi 32213 while {*}" && "!{*,ESC}" && "!{*,Q} # Wait for the window to be closed. 32214 w[] 0 rm # Return properly. 32215 32216# Generate Tic-Tac-Toe graphics. 32217_x_tictactoe : # Apply a hand-drawing effect. 32218 spread. 4 b. 6,1,0 sharpen. 0.8 n. 0,1 32219 32220__x_tictactoe : # Apply color to last image and generate corresponding opacity mask. 32221 +f. 1-i +n.. $2,255 +n... $3,255 n[-4] $1,255 a[-4,-2,-1] c 32222 32223_x_tictactoe0 : # Generate a 'X' and his mask. 32224 128,128,1,1,1 line. 15%,15%,85%,85%,1,0 line. 15%,85%,85%,15%,1,0 erode. 12 32225 _x_tictactoe deform. 4 32226 __x_tictactoe 40,40,160 32227 32228_x_tictactoe1 : # Generate a 'O' and his mask. 32229 128,128,1,1,1 ellipse. 50%,50%,22%,22%,0,1,0 ellipse. 50%,50%,15%,15%,0,1,1 32230 _x_tictactoe deform. 4 32231 __x_tictactoe 160,40,160 32232 32233_x_tictactoe2 : # Generate the board. 32234 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 32235 100%,100% noise. 10 b. 8,0 sharpen. 1.5 n. 220,255 *[-2,-1] to_rgb. 32236 32237_x_tictactoe3 : # Generate an horizontal stroke and his mask. 32238 421,130,1,1,1 line. 10%,60%,90%,60%,1,0 erode. 6 32239 _x_tictactoe rotate. {u(-6,6)},1,1,50%,50% 32240 __x_tictactoe 180,10,10 32241 32242_x_tictactoe4 : # Generate a vertical stroke and his mask. 32243 _x_tictactoe3 transpose[-2--1] 32244 32245_x_tictactoe5 : # Generate a ++ diagonal stroke and his mask. 32246 421,421,1,1,1 line. 10%,10%,90%,90%,1,0 erode. 6 32247 _x_tictactoe 32248 __x_tictactoe 180,10,10 32249 32250_x_tictactoe6 : # Generate a +- diagonal stroke and his mask. 32251 421,421,1,1,1 line. 10%,90%,90%,10%,1,0 erode. 6 _x_tictactoe __x_tictactoe 180,10,10 32252 32253#@cli x_warp : _nb_keypoints_xgrid>=2,_nb_keypoints_ygrid>=2,_nb_keypoints_contours>=0,\ 32254# _preview_fidelity={ 0=coarsest | 1=coarse | 2=normal | 3=fine | 4=finest },\ 32255# _[background_image],0<=_background_opacity<=1 32256#@cli : Launch the interactive image warper. 32257#@cli : Default values: 'nb_keypoints_xgrid=nb_keypoints_ygrid=2', 'nb_keypoints_contours=0' and 'preview_fidelity=1'. 32258x_warp : check "isint(${1=2}) && $1>=2 && isint(${2=$1}) && $2>=2 && isint(${3=0}) && $3>=0 && 32259 isint(${4=1}) && $4>=0 && $4<=4 && ${6=0.5}>=0 && $6<=1" skip "${5=}" check_display $0 32260 if !$! error[0--3] "Command '$0': Requires at least one input image!" return fi 32261 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32262 e[] "\n 32263------ "${g}"Interactive image warper"$n" -----------------------------\n 32264----\n 32265---- "${c}"Left mouse button"$n": Add and move keypoint.\n 32266---- "${c}"Right mouse button"$n": Delete keypoint.\n 32267---- Key '"${c}"SPACE"$n"' or "${c}"middle mouse button"$n": Show/hide keypoints.\n 32268---- Key '"${c}"TAB"$n"': Change keypoint radius.\n 32269---- Key '"${c}"SHIFT"$n"': Toggle to original image.\n 32270---- Key '"${c}"R"$n"': Reset keypoints.\n 32271---- Keys '"${c}"ESC"$n"', '"${c}"ENTER"$n"' or '"${c}"Q"$n"': Process fullres and exit.\n 32272----\n 32273-------------------------------------------------------------" 32274 32275 if ${"is_image_arg $5"} pass$5 store. background fi 32276 radius_keypoints=4 32277 32278 repeat $! l[$>] nm={n} 32279 nm img 32280 if narg($background) $background rr2d. {-2,[w,h]},2,3 store. rbackground fi 32281 32282 # Start interactive window. 32283 selected_keypoint=-1 32284 view_keypoints=1 32285 do 32286 32287 # Generate base image. 32288 if !narg($imgb) 32289 if {*} wdims=${"fitscreen "{*,d},{img,{*,d}*h/w}} 32290 else wdims=${"fitscreen "{img,[w,h,1]},128,60%} 32291 fi 32292 w[] $wdims,0,"[G'MIC] Interactive Warp" 32293 +to_color[img] r. $wdims,1,100%,2 n. 0,255 nm. imgb 32294 rmn warp,imgw,imgr 32295 fi 32296 32297 # Generate set of keypoints. 32298 if !narg($keypoints) 32299 if narg($__x_warp_keypoints) ($__x_warp_keypoints) r. 1,{w/4},1,4,-1 32300 else 32301 32302 # Keypoints located on regular grid. 32303 nbp,nbq=$1,$2 32304 1,{$nbp*$nbq},1,4,"const nbp = "$nbp"; const nbq = "$nbq"; 32305 p = y%nbp; 32306 q = int(y/nbp); 32307 x = p*100/(nbp - 1); 32308 y = q*100/(nbq - 1); 32309 [ x,y,x,y ]" 32310 32311 # Keypoints located on contours. 32312 nbc=$3 32313 if $nbc>0 32314 +b[imgb] 0.5 gradient_norm. sqrt. {round([w,h]/4)} gaussian. 20% 32315 1,$nbc,1,4,"> 32316 begin(ref(crop(#-1),gauss)); 32317 st = stats(#-2); 32318 iM = st[1]; 32319 xM = st[8]; 32320 yM = st[9]; 32321 img = vector(#w#-1*h#-1,-iM); 32322 draw(#-2,img,xM - w#-1/2,yM - h#-1/2,0,0,w#-1,h#-1,1,1,-1,gauss); 32323 nxyM = [ xM,yM ]*100/([w#-2,h#-2]-1); 32324 [ nxyM,nxyM ]" 32325 rm[-3,-2] 32326 a[-2,-1] y 32327 fi 32328 fi 32329 N0={h} nm. keypoints 32330 rmn warp,imgw,imgr 32331 fi 32332 32333 # Generate warp field. 32334 if !narg($warp) 32335 subsamp={arg(1+$4,8,6,4,2,1)} 32336 +_x_warp_rbf[keypoints] {imgb,round([w,h]/$subsamp)} *. $subsamp 32337 r. {imgb,[w,h]},1,100%,3 +. '[x,y]' 32338 nm. warp 32339 rmn imgw,imgr 32340 fi 32341 32342 # Generate warped image. 32343 if !narg($imgw) 32344 +warp[imgb] [warp],0,1,3 nm. imgw 32345 rmn imgr 32346 fi 32347 32348 # Render visualization. 32349 if !narg($imgr) 32350 [imgw] 32351 if narg($rbackground) $rbackground ri. .. j.. .,0,0,0,0,$6 rm. fi 32352 nm. imgr 32353 32354 if s==4 drgba. fi 32355 if $view_keypoints 32356 eval[keypoints] "* 32357 begin( 32358 col1 = [ 64,200,255 ]; 32359 col2 = [ 255,255,255 ]; 32360 fact = ([ w#"$imgw",h#"$imgw" ] - 1)/100; 32361 const radius1 = "$radius_keypoints"; 32362 const radius2 = radius1 + 2; 32363 const opacity = min(1,3/"($radius_keypoints-1)"); 32364 ); 32365 X = round((I)[0,2]*fact); 32366 ellipse(#-1,X,radius2,radius2,0,opacity,0); 32367 ellipse(#-1,X,radius1,radius1,0,opacity,y<"$N0"?col1:col2); I" 32368 fi 32369 w. 32370 fi 32371 32372 # Manage user interaction 32373 wait 32374 mb={*,b} mxy={[{*,x,y}]*100/([{*,w,h}]-1)} mouse_over={{*,x}>=0} 32375 32376 if $mouse_over" && "$mb" && "$selected_keypoint<0" && "h#$keypoints>0 # Determine selected keypoint 32377 selected_keypoint={keypoints,"dmin = inf; kmin = -1; fact = ([w#"$imgr",h#"$imgr"]-1)%; 32378 repeat (h,k, 32379 dist = norm(((I[k])[0,2] - ["$mxy"])*fact); 32380 dist<dmin?(dmin = dist; kmin = k) 32381 ); 32382 kmin>=0 && dmin<"max(8,1.5*$radius_keypoints)"?kmin:-1"} 32383 fi 32384 32385 if {*,-SPACE}" || "$mb==4 view_keypoints={!$view_keypoints} rmn imgr fi # Show/hide keypoints 32386 32387 if {*,-R} rmn keypoints __x_warp_keypoints= fi # Reset keypoints 32388 32389 if {*,-TAB} # Change keypoint radius 32390 radius_keypoints={max(2,($radius_keypoints+2)%16)} view_keypoints=1 rmn imgr 32391 fi 32392 32393 if {*,SHIFTLEFT}" || "{*,SHIFTRIGHT} # View original 32394 if {imgb,s==4} +drgba[imgb] w. rm. else w[imgb] fi 32395 do wait while {*,SHIFTLEFT}" || "{*,SHIFTRIGHT} rmn imgr 32396 fi 32397 32398 if {*,r} rmn imgb fi # Window resize 32399 32400 if $mouse_over" && "$mb==1" && "$selected_keypoint<0 # Add keypoint 32401 wxy={warp,I([$mxy]*([w,h]-1)/100,1)*100/([w,h]-1)} 32402 ({"[ "$mxy,$wxy" ]"}) permute. zycx a[keypoints,-1] y 32403 selected_keypoint={keypoints,h-1} 32404 rmn warp 32405 32406 elif $mouse_over" && "$mb==1" && "$selected_keypoint>=0 # Move keypoint 32407 ({"[ "$mxy" ]"}) permute. zycx j[keypoints] .,0,$selected_keypoint rm. 32408 rmn warp 32409 32410 elif $mouse_over" && "$mb==2" && "$selected_keypoint>=0" && "h#$keypoints>4 # Remove keypoint 32411 1,1,1,4,-1 j[keypoints] .,0,$selected_keypoint rm. discard[keypoints] -1 r[keypoints] 1,{keypoints,h/4},1,4,-1 32412 N0-={$selected_keypoint<$N0?1:0} selected_keypoint=-1 32413 rmn warp 32414 32415 elif !$mb selected_keypoint=-1 32416 fi 32417 while {*}" && "!{*,ESC}" && "!{*,Q}" && "!{*,ENTER} 32418 if !$< __x_warp_keypoints={keypoints,^} fi 32419 32420 +drgba[imgw] to. "Processing fullres...",5,5,20,2 w. rm. 32421 k[img,keypoints] 32422 _x_warp_rbf[keypoints] {img,[w,h]} +. '[x,y]' 32423 warp[img] .,0,2,3 rm. nm $nm 32424 endl done c 0,255 w 0 32425 32426# Generate 2d warping field from set of keypoints, using RBF reconstruction. 32427# $1,$2 = width,height 32428_x_warp_rbf : 32429 if !h $1,$2,1,2,[x,y] return fi 32430 $1,$2,1,2,"* 32431 begin( 32432 fact = ([w,h] - 1)/100; 32433 xy(p) = (I[#0,p])[0,2]*fact; 32434 const N = h#0; 32435 ref(vector(#N*N),A); 32436 ref(vector(#N*2),B); 32437 repeat (N,p, 32438 repeat (N,q, A[q + N*p] = A[p + N*q] = norm(xy(p) - xy(q))); 32439 copy(B[2*p],(I[#0,p])[2,2]*fact - xy(p),2); 32440 ); 32441 W = solve(A,B,2); 32442 ); 32443 res = [ 0,0 ]; 32444 repeat (N,p,res += W[2*p,2]*(norm([x,y] - xy(p))));" 32445 k. 32446 32447#@cli x_waves 32448#@cli : Launch the image waves demo. 32449x_waves : check_display $0 32450 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32451 e[] "\n 32452------ "${g}"Image waves"$n" --------------------------\n 32453----\n 32454---- "${c}"Left mouse button"$n" to drop balls.\n 32455---- "${c}"Right mouse button"$n" to rotate view.\n 32456---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 32457---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 32458---- Keys '"${c}"CTRL+F"$n"' to switch fullscreen mode.\n 32459---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 32460----\n 32461---------------------------------------------" 32462 32463 if !$! l[] # Generate fractal image 32464 200,200 x={-1.06-u*0.1} y={-0.26-u*0.1} 32465 mandelbrot $x,$y,{$x+0.1},{$y+0.1},256 32466 16,1,1,3,u r. 256,1,1,3,3 shift. 1 32467 map[0] . rm. r2dx 100 32468 +mirror y +mirror x + n 0,128 32469 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 32470 endl else k[0] r[0] 100,100,1,3,2 fi 32471 i[0] (20;80;0^20;80;0^20;80;0) r[0] 400,300,1,3,3 water[0] 100,2 32472 w[0] {0,1.25*w},{0,1.25*h},0,"[G"{`39`}"MIC] Image Waves" 32473 w={w} elevation3d. 0 rv3d. 32474 sh. 8,{7+3*i[6]},0,0 r. 3,{h/3},1,1,-1 32475 (0,1,0;1,0,1;0,1,0) /. 2 32476 ball[] 20,200,255,128,1,0.7,3.5 32477 32478 0 $w,$w . 32479 l3d {$w/2},-200,-1000 sl3d 0.4 ss3d 0.8 f3d 500 time0=$| 32480 do 32481 +convolve. [3],1 -. ... rm... b. 0.8 -. {ia} # Update height map. 32482 r. 1,{$w*$w},1,1,-1 j[2] .,2,0 r. $w,$w,1,1,-1 # Set 3D object coordinates. 32483 [1] 32484 if {5,h} +l[5] rows 0,2 32485 nb={w} 32486 i[0] ('CImg3d') i[1] ($nb,$nb) transpose[2] 32487 (1,0;1,{$nb-1}) r. 2,$nb,1,1,3 round. 32488 1,{4*$nb},1,1,1 y a y 32489 endl [4] sprites3d.. .,1 rm. +3d[-2,-1] fi 32490 -3d. {$w/2},{$w/2} *3d. {0,0.9*max(w,h)/$w} # Center and scale 3D object. 32491 r3d. 0,0,1,{if({*,b}&2,{*,x}*360/{*,w},$|*30)} r3d. 1,0,0,120 # Get rotated 3D object. 32492 +j3d[0] .,50%,65%,30,1,3,0,0 32493 fps=${-fps} if $fps>0 to. $fps" fps",5,{h-22},16,2,0.2 fi 32494 w. 32495 if {*,CTRLLEFT}" && "{*,D} w[] {2.25*w},{2.25*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.25*w},{1.25*h} 32496 elif {*,CTRLLEFT}" && "{*,F} 32497 if !narg($is_fs) is_fs={*,w},{*,h} fw={min({*,u}*h/w,{*,v}*w/h)} w[] $fw,{$fw*h/w},0,1 32498 else w[] $is_fs,0,0 is_fs="" 32499 fi 32500 fi 32501 32502 rm[-2,-1] wait 20 32503 if {*,b}&1||($|-$time0)>1 ({u*$w};{u*$w};70;0) a[5,-1] x time0={$|-u} fi # Insert new ball. 32504 if {5,h} l[5,-1] # Manage ball motion and collision. 32505 sh[0] 2,2,0,0 sh[0] 3,3,0,0 -.. . +. 0.2 rm[-2,-1] 32506 s[0] x repeat $!-1 coords={$<,@0-1} if {$<,@2}<i($coords) =. {80+{i($coords)}},$coords rm[$<] fi done 32507 if $!==1 i[0] 0 else a[0--2] x fi 32508 endl 32509 fi 32510 while {*}" && "!{*,ESC}" && "!{*,Q} 32511 rm w 0 32512 32513#@cli x_whirl : _opacity>=0 32514#@cli : Launch the fractal whirls demo. 32515#@cli : Default values: 'opacity=0.2'. 32516x_whirl : check "${1=0.2}>=0" check_display $0 32517 use_vt100 g=$_vt100_g c=$_vt100_c n=$_vt100_n r=$_vt100_r 32518 e[] "\n 32519------ "${g}"Fractal whirls"$n" ----------------------------\n 32520----\n 32521---- Keys '"${c}"CTRL+D"$n"' to increase window size.\n 32522---- Keys '"${c}"CTRL+C"$n"' to reset window size.\n 32523---- Keys '"${c}"ESC"$n"' or '"${c}"Q"$n"' to exit.\n 32524----\n 32525--------------------------------------------------" 32526 32527 5,5,1,3 256,256,1,3 [-1] w. 384,384,0,"[G"{`39`}"MIC] Fractal Whirls" 32528 tangle=0 tzoom=0 xc={(w-{-3,w})/2} yc={(h-{-3,h})/2} 32529 do 32530 rand... 0,255 j.. [-3],$xc,$yc,0,0 32531 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)" 32532 tangle+=0.001 32533 tzoom+=0.02 32534 j. [-2],0,0,0,0,$1 w. 32535 if {*,CTRLLEFT}" && "{*,D} w[] {3*w},{3*h} elif {*,CTRLLEFT}" && "{*,C} w[] {1.5*w},{1.5*h} fi 32536 wait 20 32537 while {*}" && "!{*,ESC}" && "!{*,Q} 32538 rm[-3,-2] w[] 0 32539 32540#------------------------------------- 32541# 32542# Define menu entries for 32543# the G'MIC plug-in 32544# 32545#------------------------------------- 32546 32547# Function that returns the list of external sources to be included in the plug-in. 32548# This command can be superseded on the user '.gmic' file to add sources for the plug-in. 32549# $1 = try network update 32550# $2 = try 'gui_filter_sources' defined in local update file. 32551gui_filter_sources : skip ${1=0},${2=1} 32552 32553 # Try to update the command 'gui_filter_sources' itself. 32554 if $2 32555 local=${_path_rc}update$_version.gmic 32556 if isfile(['{/$local}']) m $local fi 32557 if isfile(['{/$_path_user}']) m $_path_user fi 32558 gui_filter_sources $1,0 32559 fi 32560 32561 # Try to clean older update files to save disk space. 32562 if u>0.95 l[] 32563 files=${"files "$_path_rc"/update*.gmic"} 32564 repeat narg($files) 32565 file=${arg\ 1+$>,$files} 32566 ('$file') z. {[w-8,w-6]} ver={t} rm. 32567 if isnum($ver)" && "$ver<$_version delete $file rm. fi 32568 done 32569 onfail 32570 endl fi 32571 32572 # Build list of filter sources. 32573 ({'https://gmic.eu/update$_version.gmic'},1) # Include stdlib update (last 1 -> Override default filters). 32574 l[] _gui_filter_sources $1 onfail rm endl # Invoke custom command to include other filter sources. 32575 l[] i cimgz:${_path_rc}gui_filter_sources onfail endl # Include other user-defined filters sources. 32576 ('{/$_path_user}') # Include local '.gmic' (or 'user.gmic') file. 32577 32578# Function that always returns a valid preview size. 32579gui_preview_wh : 32580 u {0$_preview_width?[0$_preview_width,0$_preview_height]:[400,400]} 32581 32582# Function used for filters based on parallelization with spatial splitting. 32583gui_parallel_overlap : 32584 apo "$1",$3,{if($2,2^($2-1),0)} 32585 32586# Function that renders a single preview image from multiple preview images. 32587# Pre-cond : Number of image is $!>1. 32588gui_preview : 32589 frame 1,1,0,0,0,255 montage B 32590 32591# Return name of a layer. 32592gui_layer_name : 32593 u ${"_gui_merge_layers[0] name,[unnamed]"} 32594 32595# Return blending mode of a layer. 32596gui_layer_mode : 32597 u ${"_gui_merge_layers[0] mode,alpha"} 32598 32599# Return opacity of a layer. 32600gui_layer_opacity : 32601 u ${"_gui_merge_layers[0] opacity,100"} 32602 32603# Return (x,y) position of a layer. 32604gui_layer_pos : 32605 u ${"_gui_merge_layers[0] pos,0,0"} 32606 32607# Set name of a layer. 32608gui_set_layer_name : 32609 repeat $! l[$>] 32610 opacity=${-gui_layer_opacity} mode=${-gui_layer_mode} pos=${-gui_layer_pos} 32611 nm "name($1),mode("$mode"),opacity("$opacity"),pos("$pos")" 32612 endl done 32613 32614# Set blending mode of a layer. 32615gui_set_layer_mode : 32616 repeat $! l[$>] 32617 name=${-gui_layer_name} opacity=${-gui_layer_opacity} pos=${-gui_layer_pos} 32618 nm "name("$name"),mode($1),opacity("$opacity"),pos("$pos")" 32619 endl done 32620 32621# Set opacity of a layer. 32622gui_set_layer_opacity : 32623 repeat $! l[$>] 32624 name=${-gui_layer_name} mode=${-gui_layer_mode} pos=${-gui_layer_pos} 32625 nm "name("$name"),mode("$mode"),opacity($1),pos("$pos")" 32626 endl done 32627 32628# Set position of a layer. 32629gui_set_layer_pos : 32630 repeat $! l[$>] 32631 name=${-gui_layer_name} mode=${-gui_layer_mode} opacity=${-gui_layer_opacity} 32632 nm "name("$name"),mode("$mode"),opacity("$opacity"),pos("{round("$1")},{round("$2")}")" 32633 endl done 32634 32635# Flatten list of input layers according to their blending modes, opacities and positions, 32636# set in each layer name by the G'MIC plug-in. 32637gui_merge_layers : 32638 if !$! return fi 32639 mode0=${"_gui_merge_layers. mode,alpha"} 32640 opacity0=${"_gui_merge_layers. opacity,100"} 32641 pos0=${"_gui_merge_layers. pos,0,0"} 32642 if $opacity0<100" || "['$pos0']!='0,0' 100%,100%,1,4 fi 32643 wh0={w},{h} 32644 wh=${-max_wh} r. $wh,1,100%,0 32645 repeat $!-1 l[-2,-1] rv 32646 mode=${"_gui_merge_layers[1] mode,alpha"} 32647 opacity=${"_gui_merge_layers[1] opacity,100"} 32648 pos=${"_gui_merge_layers[1] pos,0,0"} 32649 to_a[1] r[1] $wh,1,100%,0 32650 shift[1] ${u\ $pos},0,0 32651 to_colormode[0,1] 0 32652 blend $mode,{max(0,min(1,$opacity/100))} 32653 endl done 32654 r $wh0,1,100%,0 32655 32656_gui_merge_layers : 32657 u {`" 32658 str = ["{'{n}'}"]; const sstr = size(str); 32659 def = ['${2--1}']; 32660 ker = ['$1(']; const sker = size(ker); 32661 const N = max(size(str),size(def)); 32662 ref(vectorN(0),res); 32663 p = q = find(str,ker); 32664 p>=0?( 32665 q+=sker; 32666 r = find(str,'),',q); 32667 q = r>=0?r:(str[sstr-1]==_')'?sstr-1:-1); 32668 ); 32669 q>=0?copy(res,str[p + sker],q - p - sker):(def = ['${2--1}']; copy(res,def,size(def))); 32670 res"`} 32671 32672# gui_split_preview : "command",_split_type,_split_posx,_split_posy 32673# 'split_type' can be { 0=no split | 1=forw. horiz. | 2=forw. vert. | 3=back. horiz. | 4=back. vert. | 32674# 5=dupl. left | 6=dupl. top | 7=dupl. bottom | 8=dupl. right | 9=dupl. horiz.l | 10=dupl. vert. | 32675# 11=checkered | 12=checkered inv. } 32676# if 'posx' or 'posy' are equal to 'nan', splitting is done at the middle, and moving is not possible. 32677# 'compute_entire_image' can be { 0=no | 1=yes }. 32678gui_split_preview : check "isint(${2=0}) && $2>=0 && $2<=12 && ${5=0}>=0" skip "${3=nan},${4=nan}" 32679 __split_preview="$1" m "_split_preview : run $__split_preview k[0]" 32680 is_movable={!isnan($3)" && "!isnan($4)} 32681 posx,posy={$is_movable?cut([$3,$4],0,100):[50,50]} 32682 pw,ph=${-gui_preview_wh} 32683 repeat $! l[$>] 32684 is_failed=0 32685 +l 32686 apply_timeout _split_preview,0$_preview_timeout 32687 onfail 32688 if 0$_is_timeout gui_timeout_preview 32689 else gui_error_preview ${} 32690 fi 32691 is_failed=1 32692 endl 32693 32694 if $is_failed" || "!$2 k. 32695 else 32696 drgba rr2d $pw,$ph,0,2 32697 r {[max(w#0,w#1),max(h#0,h#1)]},1,100%,0,0,0.5,0.5 32698 posx,posy={round([$posx,$posy]*([w,h]-1)%)} 32699 32700 if $2==1" || "$2==3 # Forward/backward horizontal 32701 1,[0],1,1,'y>=$posy?($2==1):($2==3)' r. [0],[0],1,1 j[0] [1],0,0,0,0,1,. 32702 elif $2==2" || "$2==4 # Forward/backward vertical 32703 [0],1,1,1,'x>=$posx?($2==2):($2==4)' r. [0],[0],1,1 j[0] [1],0,0,0,0,1,. 32704 elif $2==5 # Duplicate top 32705 j[0] [1],0,$posy 32706 elif $2==6 # Duplicate left 32707 j[0] [1],$posx 32708 elif $2==7 # Duplicate bottom 32709 j[0] [1],0,{$posy-h} 32710 elif $2==8 # Duplicate right 32711 j[0] [1],{$posx-w} 32712 elif $2==9 # Duplicate horizontal 32713 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 32714 elif $2==10 # Duplicate vertical 32715 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 32716 elif $2==11 # Checkered 32717 1,[0],1,1,'y>=$posy' [0],1,1,1,'x>=$posx' r[-2,-1] [0],[0],1,1 xor[-2,-1] 32718 j[0] [1],0,0,0,0,1,. 32719 elif $2==12 # Checkered reverse 32720 1,[0],1,1,'y<=$posy' [0],1,1,1,'x>=$posx' r[-2,-1] [0],[0],1,1 xor[-2,-1] 32721 j[0] [1],0,0,0,0,1,. 32722 fi 32723 k[0] 32724 32725 dir=0 32726 if isin($2,1,3,5,7,9,11,12) 32727 dir+=1 32728 line 0,$posy,100%,$posy,0.75,0xF0F0F0F0,255 line 0,$posy,100%,$posy,0.75,0x0F0F0F0F,0 32729 if $is_movable 32730 coords={p=[$posx,$posy];[p+[-10,-1],p+[10,-1],p+[0,-11]]} 32731 polygon 3,$coords,0.7,255 32732 polygon 3,$coords,0.7,0xFFFFFFFF,0 32733 coords={p=[$posx,$posy];[p+[-10,1],p+[10,1],p+[0,11]]} 32734 polygon 3,$coords,0.7,255 32735 polygon 3,$coords,0.7,0xFFFFFFFF,0 32736 fi 32737 fi 32738 if isin($2,2,4,6,8,10,11,12) 32739 dir+=2 32740 line $posx,0,$posx,100%,0.75,0xF0F0F0F0,255 line $posx,0,$posx,100%,0.75,0x0F0F0F0F,0 32741 if $2!=9" && "$is_movable 32742 coords={p=[$posx,$posy];[p+[-1,-10],p+[-1,10],p+[-11,0]]} 32743 polygon 3,$coords,0.7,255 32744 polygon 3,$coords,0.7,0xFFFFFFFF,0 32745 coords={p=[$posx,$posy];[p+[1,-10],p+[1,10],p+[11,0]]} 32746 polygon 3,$coords,0.7,255 32747 polygon 3,$coords,0.7,0xFFFFFFFF,0 32748 fi 32749 fi 32750 l[] 32751 0 +t. "After",0,0,20,1,255 t.. "Before",0,0,20,1,255 32752 autocrop 0 z[0] {0,[-1,-1,w,h]} z[1] {1,[-1,-1,w,h]} 32753 if isin($2,3,4,7,8,12) rv fi 32754 +dilate[-2,-1] 3 /[-2,-1] 255 r[-4,-3] 100%,100%,1,3 32755 endl 32756 32757 if {-4,"const c1 = "$posx">w+2; const c2 = "$posy">h+2; arg("$dir",c2,c1,c1&&c2)"} 32758 j[0] [-4],2,2,0,0,1,.. 32759 fi 32760 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)"} 32761 j[0] [-3],{[w#0-3-w,isin($2,11,12)?2:h#0-3-h]},0,0,1,. 32762 fi 32763 k[0] 32764 fi 32765 endl done 32766 um _split_preview 32767 32768# Command to display text on a the G'MIC plug-in preview. 32769# $1 : header message 32770# $2 : header font size. 32771# $3 : main message 32772# $4 : main font size. 32773gui_print_preview : skip "${1=},${3=}" check "${2=32}>=0 && ${4=20}>=0" 32774 32775 # Resize image to output resolution. 32776 if $! k[0] fi 32777 drgba 32778 siz={0$_preview_width?[0$_preview_width,0$_preview_height]:[${fitscreen\ {[max(w,1),max(h,1),1]},400}]} 32779 sizw={arg(1,$siz)-8} 32780 if $! rr2d $siz,2,3 drgba else $siz,1,3,128 fi 32781 (1;0.5^1;0.5^0;1) 32782 (0,0.5,0;0.5,1,0.5;0,0.5,0) *. 0.65 32783 ri[-2,-1] ...,3 * c 0,255 32784 32785 # Render title. 32786 l[] 32787 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)} 32788 r. 100%,140%,1,100%,0,0 32789 onfail rm 32790 endl 32791 32792 # Render message. 32793 l[] 32794 0 t. "$3",0,0,$4,1,255 i.. 100%,100%,1,3,255 a c 32795 ('"$3"') is_err={"crop(0,4)=='*** '"} rm. 32796 32797 if $is_err 32798 x={"ref(crop(0,0,0,3,32,h,1,1),T); 32799 for (c = 32, c<w, ++c, crop(c,0,0,3,32,h,1,1)==T?break()); 32800 c<w?for (0, c<w, ++c, max(crop(#-1,c-2,0,0,3,5,h,1,1))<=0?break()); 32801 c<w?c:0"} 32802 if $x +z. {$x+1},100% z.. 0,$x sh.. 0,2 fc. 0,255,0 rm. i.. 1,10 fi 32803 fi 32804 32805 repeat $! l[$<] 32806 for w>$sizw 32807 x={"const c0 = "$sizw"-1; 32808 const c02 = c0/2; 32809 for (c = c0, c>=c02, --c, max(crop(#-1,c-2,0,0,3,5,h,1,1))<=0?break()); 32810 c<c02?for (c = c0, c>=c02, --c, max(crop(#-1,c,0,0,3,1,h,1,1))<=0?break()); 32811 c<c02?c0:c"} 32812 +z. {$x+1},100% z.. 0,$x 32813 done 32814 endl done 32815 a y,0 32816 onfail rm 32817 endl 32818 32819 a[^0] y,0.5 32820 r. [0],[0],1,100%,0,0,0.5,0.5 32821 blend alpha 32822 32823gui_no_preview : skip "$*" 32824 gui_print_preview "",0,"No preview available",32 32825 32826gui_timeout_preview : 32827 gui_print_preview "",0,"Preview timeout",32 32828 32829gui_warning_preview : 32830 gui_print_preview "Preview warning:",32,"$*",22 32831 32832gui_error_preview : 32833 gui_print_preview "Preview error:",32,"$*",20 32834 32835gui_check_version : 32836 if $_version<$1 32837 gui_error_preview "This filter requires at least version *"${"strver $1"}"* of the G'MIC framework.\n\n"\ 32838 "https://gmic.eu/download.html" 32839 u 0 32840 else u 1 32841 fi 32842 32843# Function to auto-crop layers and set their positions. 32844gui_autocrop_layers : 32845 repeat $! l[$>] 32846 nm=${-gui_layer_name} 32847 mode=${-gui_layer_mode} 32848 opacity=${-gui_layer_opacity} 32849 coords=${autocrop_coords\ auto} 32850 z $coords 32851 nm mode($mode),opacity($opacity),pos({arg(1,$coords)},{arg(2,$coords)}),name($nm) 32852 endl done 32853 32854 32855#@gui ____<i>About</i> 32856#--------------------- 32857 32858#@gui ♥ Support Us ! ♥ : _none_,fx_support_us 32859#@gui : note = note{"<center><a href="https://gmic.eu"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAA\ 32860# BXCAMAAACJMYjxAAAAXVBMVEX+/v4cO0s7OU4wPnEiJSju6+qiqrCMlZu3u8BufoHd3+FDY2JRLzljS2bLz9Lp9vrteR34lyZqHE3puI3S7/hbX6GUW4z\ 32861# wza97QiOaYUa6mqTdfz25i22+VxzqoGYqrht5AAAWRklEQVR42uyabZfiKBCFFYUCDDg7TqIh0f//M7duBSEx2p09Z18+7NzTPUYaE/J4qyjI7H7rt/5m\ 32862# nXe/9VtfS+vdb21U7Me/hNbblPzu/6czEs/Y39LmT/jU36C0+7/p/OvXeaf7S3+7bkQ19uN4uVzGG3/i31X0/3GyEFjXnu+991sCMN36dIGu479tLR9Cl\ 32863# +J/ll3PLMBKbJXbipbW+nq9Lgan2U/cl8V/4Tz3r8r+hEKMu/9CDCrDStdLz7RKXDGly+MxTBqZjM4hyJ3GR4Y1/suwOoHVuf8EFmgxK6YFWMyBI0yaGd\ 32864# Two+qPH8PwuDAvLX36fiyw/oFKRcdEHYuS9UtXB4GVSP/9HLw15JwjMtGfzx/jELwyLCjp3fUx/AEBUzlgYI8rh6oItBCGl+/TjH975Rj9p5QI+4gaVug\ 32865# YWPnQxOrvN5an0yFrv9+rE9m3oz7zD5xlxyviEBpHRiV+KqQgHAzoIeLAxAe+nw2tifq88pKn5P3bUTccZqzC69g0nc0f7f4ZY3l3OLQioQUdTsb/eu0W\ 32866# /RSKu8iwsrXuHHWvKsju2Vlgde3774cd2dxRe0s2xjI4psEhtl5ZpvAzdIVVNVgQXDo8jaWJQ9RGCdLtgeZjtAi26BftBqgyrCrg0suqxdvcoEdm1fdgx\ 32867# Uiqo1YOuxdjbasc6DmO1j5haeqgkLxe5e9uxQpid/EdpoYPA5FGxwYi+55WtCzDIlaMku6EgFL7gzJ2Hvbu0BKrsKq07KKfib/K150uOQoZzicVWr0E4a\ 32868# 3XG2AZMhgGw/LzcollzeLzuiu2Wotj0YcmG8sz6aYBMPM+fSl1UECzVyxjcEnFDS2i7HCYw9KnfQukS1Lod2ILzg1oTfTPW/DjBOtebPVKaUZrFFa3DYl\ 32869# WOzLmgKGbikaH0DIr8i+Z/QXVglqiCD6pMxwFAqthWDTjXRWVaqkFLdx1hnUgk3OStTNWh/YV1WmC5cwsN6K+MtZH87QW0wKrAmjOavq3RGJ/vT5uN7sp\ 32870# dz7tbWNtVbCWNFSljmml9POtGjaUt10TkN2TIBVrBeN3azlmxbBYFRY72+QmYxcxiAEKo6JWPjY3FiZBS9YXJ/N67zGxenwOQ2hAJG5k1eLKIuNrs7E2d\ 32871# fB0VQwpMau3MZgzlY+J/bVLPRJeppXsGzerYLquPYSDaILVSjZol7DoUPP66XQCMMkYMBbRnBVEZA35PLVzgr8Lq8vlBRfauLHQYlQbqgYGUFmpEP0MVp\ 32872# QEUBU7NhZ+wwoU+CWHzjryffq+76q1yOxWsgod2swqCCxdqVRYtrDKtFrhJZnNOL+Edf4VnTPGABZ07X9kLqBVA5KboFrV3/uL3jBZW6SJIoql3NJ4lbm\ 32873# wZrEEUBlV6JKoe2b3TpjggxptcBYnLT56F4cyfTzDsM2wGN0rLH+qrNDTiMidOK85fAsra52MLcGphwGskL3FRiVjXbIeBdYGVlKmE3+1eTjB+o/rHNsh\ 32874# BGEWqEsO8wIlFrCwscqH/E9+3zMxwFrFYc2IXeCJMKgShqDxhGLnQVjKKoOLEpEAY2OtYJ396eScezrrDmMB1eUKWktjQUOGdU+bHmboGC2PrQWq0JqPh\ 32875# HUnsEJmRS7q536ssYnZ2YoCjPpeWCEO3eqsRmAFwOLL5jD0cqzmzvJBWO0zK0dRT9eMfFGy690ZnPp0Utlyo0ShFPLjDNYPbuJlRz+D9dFaZ1zK4BuyXg\ 32876# LOU2gxYMvKCN4ZC4KHEHNUawrhZRPpJSx0E3EcpvgahSqwlKgmeD5+gUXzIKQCPQPT7zaUz+HIbtWzlDU2Y2qa8TJz1tiH4/EYZrDub/O7NxzvEM/IJlq\ 32877# pryPKQH4X/eddziCsWAp371531crIK6wGKvNhsfKEBcZ6AwuqsHQ7M5Yj0lv2SO2xCYrw9oLCgac6e22OxwbOyrQefeIW1fRDhTW+OR0dGBOEuGcjTTmK\ 32878# z26snnWrL1m2EVaN8MqFc+2Onh9gsRWbzujF+QhRWKz1ARab3s6NhRT1LSzQcrBWRBRKlXUftQ4Mq6+whhEtoPWjwOr96mwtk5LrE5lqBm0dWHnnQDDGC\ 32879# IMtAThJMpAKKDu/2vjygMRgWRlbiuhUunHiE1TfwNJUWSEOdltgcZzg4o4v2Aus4bo7O0ZzGzIrNHmGtVfuNoO1SvEGrKRWIDsnqWUNaLFIZFkogViRlr\ 32880# oo3yAS1lznNSyo0mpSwr3nE8rdFFisAmuvFrCe6X2/0ViSs1gEa1meC5+wrFNHNYel6XRUh1PqMyvWsIrDYixeKmj9mnK8td5r7JIYsqGbP3mwKvwEK9F\ 32881# 6t+r8AuvYzMVLnuRn/nPcxD6tsMISViuw5KLFWOC5VVodQwhaYLEuu2idc/0cliEub91lmMHq9RtYeTxEbrXXiCmZnCDpQkewUt7Vo9Bx5DQKCmS/WUFV\ 32882# TjXFV6Y6iLPU2lnsCGzRnDIsUihSJ4DOxbwP+oWtOGGJDJ8oULrdp9WOzNZpnIfh1aAeyLDu0GO13rHTOgHI2N5tG5zxHknKskzX5jsIiiFxW2JcTUD0c\ 32883# NleYJHzfxEWth7qTRrZilZvYYFVmQ15NO0hwzKoeeVHz3iti9KcFNlaamRYU6Glr8yKYZUEz0V9onTlakJYyXpnlbR0ttbkbqQDHLYQv1VZoTOWlZg+Xm\ 32884# yEGQIytmr4l0hvhFUVbAW8NlYNQ2EFeja/z3WDMjQRgfjlLatKKx4bsleeDbGl/ED9joUgU2IBliyBuHHIrADrNr6eMeLiUFs8VqWODArFFyhFryGplQF\ 32885# LyQ0GFk9Lm2Dd5rSsnf9VWK1z1mQslWHF4/4QcnpHg6ACj/fOmmDlN2TxPLUfhMZDuNwHNhQzY1x3pgUN8NRkrsdlvafsY766WGlBCqBkp9eua9MISp3t\ 32886# Al7IboA1Lo01W/KkEF5ZlZ1SNa/gLb/l99NwKWZWrC+sVdo1i601INCYDfYXJlbyoJXh8KF4amKFh/1xt6ZFe/7GXtUSMwIopK8YnERNlT2q4iyi+D2s/\ 32887# trfFrCaso8YXmDBS7MELw0Cy4BjzllTnnzCOn/I7/gLDsCq0GIhhXPsZY0XpgUNhdXt8X4DXsdIbYXUGgk6cPI+GpkKwyotGYEl6Yxh+e9h3fopDsfQZC\ 32888# Uz+SEWVqbQqrBYBRbhgOGV/H6usM7vH0aDE5gJLAnEsgU/cAAKKn6Qwz4rAkjeg+8/bJT6aCFjJ0X8IjWRUxDGR+YTLAG5ARaDAi2imuJ1jsJMy5njN7A\ 32889# wOeYwRH6vzvpsrHOOxgLrxt7KsC5PVgKrosLj6C+egmmfgcXImKKhVsbUYnABG7avOZxU0SZYRc7WFB/zTk92lnErWDUuAcsdi7P2Aqsm+PPnyVAOsrPw\ 32890# KJBpAcqAnA5cMjMWWBOqy4b/+BaJKK8mltPinsdaVBYQrLCCpckVAQfkb002FvupxCFZuWZZNNl3sMISFqZGHt9+goUYg/jwa1jnJ6x0Y2sJLZ4KJ00lA\ 32891# 5rQeAeqccsGvJ0/tMRx0SusKWKCc2tY6lj0/IuvK8OQahwaL1GYa1tHQX3tLJKL7iGEIaQ/FfGCaOI00cxR2PR4ajGwYCxgkRfOX9CIRu6QNmwqWzCCch\ 32892# lRZa3Wi55SW/OQD29gcdZvBJYrsIpCSuUYAHRN71tgIWWJDGUoAuxLWKwCK/AUAx4PcdTY31h9P/KxmExQjVHvNsiAi7B6kVnDkoG70wqW54bUHdewssi\ 32893# EfCSzhi2wyLyDFWqCFztzBIqmi+pC6nMYZmkA6dnfNyZ1haRBlN9PpvK7bTLqhdXzKBirX4pSZLa9fOmO/CwWvMIzH0ahlmFYCRFeGixtTdy55mksZ9ew\ 32894# JDPu1T4Xpcc/STe7JSdCIArLCDQ97OCFVZaxtnz/x7RPA2kGknEsj7pGFoT56NPLTyKdbgZLDXYLFhTEakiaHw/kJQix1d71h5ACKQTVTZFHMhhZ4Tdep\ 32895# Cln7QJJB67r/NLt8E1h0Q/W5x5hCRMABKyi3/NAkvYeO0ehfZth1fDdXIO1g1I7AscMic0uYInqOsti67tsI/LHQ7K46PMTyATWdymvhvz8l0+osHdu9S\ 32896# BglTQ1wATXBLJlzf5BWSkskeSsGRbiSURpP8DKq/MSFmp4ySUBlptguZbQNWcFvK6spKDU1eaF1rgLvz4O2tVvKknsYkqQgnCSfF8H4hyimdZkQ3BVXJv\ 32897# IUQxQxbVL+DQABsvj9A9FgBWifAtcDk4kVTU+iUqosNwJVjt1UFjfssFyKDAat5GVoid0WMdUXHCfkoIeTLHs98JLYBmfZ4Q5PXoOq2Mx45DBUht6ZBqV\ 32898# RZZHDuuVi7oQKnwIANCKHELF5s42bCldo5eciaTGLVZjkk+Uh5XNQ9VYiR/l3gfF2Evsd05fDZYh02hLU/OCvFu1HbFYaFnmGWBhCB0Wznd0TKKUcw2nL\ 32899# M/eYTlL8K6haqvi5A3WelF7eQIIUoy+vOkDYSVSVhBgVW3HJa8e9i/k5HcqpyEALLrGL03UQVUja8ubW2E1gQrJv7UG91Umc6mw6hT0yAIm9A4bosANSu\ 32900# WfYEVMS84SWabP7w0X1qi/DVaLr8sOkt9ew+ozawo7t8gCF05liCy4cIK1mWCfIiOWlmNC59BhbQYLL5VV6z+wM3EKtz5cUWkxYjgzyVeLLGwOdSPd3kE\ 32901# zwNqgdLlyyPkNrK+Uzldde3FQfd4eWl/GyHIjLH+CFTKG02BDWUs396RlsKAO61u8H1q2iAeruLHg4lTGpHUAkpyatn2jhNaHsVJdTEc+udCNtPJ5HkMI\ 32902# AsC5nmMyQgsVDJYbYdXeUZaVOnzYLdddqClT9Tz8m374KT5TnvNo2FcDthPAmGMUDxIx3OiruO5xoF1pPc6s/ArL0pDHuF7JidrIbEeW9HFt4KEvSl2H5\ 32903# aacpZ5VWMVXyL15REXg7wUtZ3VWHVZgb7A8lzAMKWFC12zVLjSqDTNYVeHdDsdD94Vd338aKQ/F91GbBlYrrjgHPZ7NlKPSUlgZjzzDciOskFuyao0p2n\ 32904# 84wvLKqsGCihvk8/OisxCcTeXFogGs4GC1/ihXE9cvoVRhsT/puLI5e4WVF1D6hdIC17tRWI+LSAKrP4zB6qGFWu08rBuzubDD+noJCyk+D7g2pogT3ea\ 32905# eF2nsuT8MkbPwaTnL9MGfDwGW6BhLN06X+RDDtgvqSS4ve8ydR1q+yWV7mBFWNx3FZ4ScXGg5C3QGWF8NFhpml+deTWbEFRYiTXhx9quwvxhB0d821LEm\ 32906# 3RlUv632UzpF1nInSXNBknONDQNjNrSyb1nBmAtf2vDJzvkOK0Rnsn67Ynp7hQ9YUGEkrEWW2incOXLoUQ9ABsrpnaL3a4jv5CcnGirIs8GC3UZYZC3hw\ 32907# hVWAKxngVHYyUpN/pnFymqZad21H6qtHxqdJN+If2cVEtbvdSJNHVx2jAx/acRVRH1vZFQpPvlV6bHXfVihcG26yox4+VnNwIdpm1jdg6WbELcIsNQoGL\ 32908# 7pYuAmP8Lq9Sh9OfvQbxR12idYAbC8wbrq1GDd2AX9NyyoxNwAQQZL1wX1jGalRRe0PNsKXoXHabBCREGtxQWwQoWlf3yNLG+KaezU+TewMnG6AevHD4N\ 32909# 1y4arSoq8GaSmzDFiO/PGvDE3XNgVTWmXDFZXjpbHqhxqIbJGpP2noTVLp07f+v7ChpY88NnJ/4SFOcNCibNrws4zTqjWJrSt0ZWdd0wU57tEijFNZZGG\ 32910# EmplKZ6bUUxTp1NwecwqMZalN2CB1ltY9OWmQr/KF9W/UtnDdd/gi6A4jZuJmPqZUIhkKj08qMpqpakWCqzS0mluy6xOCqjCHQMd17D4Hiq7yy9JoI1vg\ 32911# 7/GFYUGtvW5hgEpqWHkwbQWDj2b1mZnhd4pVDu8iP/l0xzM/BoWDpj+tHN2u23DMBSObfBXG32Tvf+r7hxaabu18RJsHXYxAi4tRTSlLyRttU3kc79oS4\ 32912# pTf5GTcPxDc9in0xePTzi09V51n/WxLp8tu2Rm4WAU/DWBM7p8yuTrAevuY/xqv/N2quf5AHakvG2p5W3gp0vKU058nbDu7njiBH5FWIqbOrZRUGrlxJO\ 32913# aqRF+jeEvEFw+xherypvWMuwnj6n56Jry0VLdUks8lTcBWBEBWPfkq5/Uu3WM8LFCe8YCHYal77HaWMYY9gorl6FCtf38mQoQz9cWjOrdmiwfXP2g6CO0\ 32914# XBNohz/BqsBqwno+tBJs1LWwPgWVAClFKyq3wQBxVw1Xc2lYvWRtWKWK3KOqynSX7iEr3wZa2a/vVX1f9CUyq0yvr3ZXKlP3lN21ZuQFSLk7wri7Kt386\ 32915# kajKp6zD5eH08B0kuaean5clM2L/Dqw7sP6cje0fA2HEswwdbFgTInY6rZg1kQj6YwwK8ICBgTOtkXagJQ4foKpDhWGRDhmGhimxYgtgaKHhhVbS/+Vyb\ 32916# axvZpnQIM0JDuq9sseS3fFyhHrgBEuDG2JyHVkhGr/cWBE1cLLaBbVaVr6OmGhvj8fWgbnByzfcR6LeSXiDSx0GX4Dam7eaXhAWSwdhKCip3s7VXV+FnY\ 32917# bhrw+1rGiN2+wQgHJdH1vDlOGYw+sozwMM3jjVYPnMIqFQ5U8d5gU2swJL0DTMcpWqsizW2GzOof1ZdV7YWkyYXF6sSwMBOFvh3va8832LCGsGIypI/yz\ 32918# 5zv8ipcdPWAr0hfjV40wFXXV2qImg6QvrhnwfzIPrHZgRA9stdNT4YihbXSg1UxYHbBMjPNoWFHUNqzH32UV6yOw8GCadyIL11b47z1zsWYxhoq5cYO1O\ 32919# xYyYcXwMQwTTR3s9aExRgHW621p375Vt9i7de+MLKxxM3GsPZXJTHOD2/nsf8BqtTOGZRCnXgBBJqx+5wb0hCVywMrWDMaTeq9kdVqyzp+1dDUhMRBYzY\ 32920# HektEhDJMxXjdyI6phKcaFYXIsUAByjU5N3ybbvWGNyg0Bou9gXRrWBnOk4zbNScEKIh3GhwEjBE4OWOsLLKnlPiwxFMqTu649BIvyMSxG+gFLbXh2gSc\ 32921# e1isbrEBEJ9kReKRAVxss3glLtzDPC2F9iwKrCWv/9g3H9jGstc3txVyUYZTSxjGKHnVRHDOylglr9jWXhqU/Rhbv5XW2h57lnVl4JncqvOgIG13PK47i\ 32922# EVYXWUcx4q3LRJjh9IBly1BlZEV0Gm6DFdyPkm/hcsAivgDxn9Nw1qxCBNzM6YGTCG/UhfMIB5F2SljxAot91CyurGMc9zYNIWfPc6LY7JwG1vlTaSo9K\ 32923# JdZYWywfO4WIFaBRpRoKxbIqMRRQTRcoBpUELTJVedUD2NlpqVYZLuhSejOgfnOPOkpfOY8vRqctNPDSIU+Y/QwtGkWyQ638MT5ruHK7hNakDTgWk8fHF\ 32924# ROzOfnmRJwvAWnO9vo4EvHECi0S3ik144+x/gRWjas5jBYQcrl1pI+B0BvswtN5Y35gPkaKdUeWrKUlrMrcToNBSDQJ+CJEe4ihYHlKY6ghA5OhHXlTMR\ 32925# jPdnrnG8d9sc3vHsfrWbjGsPiw80Jx/F4Z/1Wprkxd0926Tcd7ej+Fa3vhiw455Ia64dPDNyTfp4cGWE5574/bz5T9yFLDz+HYEe9eECk+h9aXzn1feqT\ 32926# halb8huwnzGXXwyVdH9qySJZkPz/XfH/5b/88/IdcfPxH+J0LVIAAAAASUVORK5CYII="/></a></center>"} 32927#@gui : note = note{"<center>is proposed to you by</center>"} 32928#@gui : note = note("<center><a href="https://tschumperle.users.greyc.fr/"><img src="data:image/png;base64,iVBORw0KGgo\ 32929# AAAANSUhEUgAAAEAAAABBCAMAAABW61JJAAADAFBMVEX27vz06viVWEaZZlbz5/Tv3urwxMeFXE2icmuBUT7w4u7QzeKaaFqRVUPs5vWKVEKBRyvr4vKR\ 32930# WEfSj4d/aGWuaVjkqqaca1+ATjnAfHCVWkh7UD/z6Pbv1d6DVUSGUT2TY1ONWUji1ubv0NiHeoaLd3zEgHW8d2qQYFCOX0+LUDri2uvcnpeQen+md3GKY\ 32931# laYYlGXXk3p3u3Z0uTFyN7nr62Aa2uoaFehYE93Tz/tvb7su7yYf4XIhHqgb2WRZVieY1KKXk/u1+Lvys/uwcPPi4KkZ1eiZladXk2ZW0nn2unXxNHpwM\ 32932# XqtrXntLPfr7DhpqKtk5yHdXuEcXSoc2uSbWeeZlaIWUjj3u/uzdPTvsrdu8LHrrmjipKQfYZ2ZWalbF9zYF+TaV6gaVurZ1aCYFakYlF9WEyJW0uDWUm\ 32933# PUz5yTDyETDTd1efSyNrRt8HOtsG8pK7go52IgpTMlJCbhY+rbF2QXEt7U0RiSTxXQjJ1PiLv5/bx4/Hw2+Xfztvmxs6WpMLlvMHNsbvCp7CalqqkjpuR\ 32934# h5iefX+iene3eW23c2VhXGWpbmKLZl2wa1unZFN0U0hrT0U/OzlRPC5aPCsrKyrKzOHCw9nnzdffx9K3u9KvudKnsszAtca+r76tqL2UnLfcqqp6iqiGj\ 32935# KWxmKK5mZ7VnZmbipbZmpLUlo68jY1rdY3JioC7f3eveXGfdG6wdmxpY2yIbGqxc2ZRTVNkUk9LQTt6STGFSjBHOS8qJR4gHhkWFxLd2ey5wNjGvM2Jmr\ 32936# mvobGCka+mnK6Pk6zZpKNpgaJ+g5mtjJB4eo6UgYu4hYHBh3+ZeHl2anBsV1RwSDM9MytmPig7IxPSz+ShsM3lubvetbl4k7TOq7LFoqnSpqd1hKLHnZ9\ 32937# paXmVcm6FaWRMU2F7XVZDRUpeRTZTMBxgMReaqsezrcC8n6mklaKfkaC/l5pbcY+nhoqvhYNMY4Cnfnx3b3xbY3eOc3W1cGFcWGBiVVZbTEliS0O4qbjS\ 32938# oKBQaYhBSFRDMiYCeYKqAAAKU0lEQVRYw42WBVhaaxjH4XDOoUREUhBEBQRFBLu7u2N2TqdzttO56czN3Kauu7u77rq7u7fb3X2/g9db3OeBv/Dg83D+P\ 32939# /7v+d7vPR8OhmE8Jhx4GSLsSuytFYyHceD9l/+fiPFrwD9/0/FjiHEM3tiYMXaZ9vt/+rVULNxfoHE39oH5MTcex8DhYB03EDCmL+z6+NTPVStWLj+xPA\ 32940# oGtH+GGxNAjPPB57/lOPNS/74D+18m7d7d359/3btTCAj/QowVB0LouLGvnbd+8/2Bw7cOHz584Kf9+3+4keSdMAXRvQxE0Amvzb/ss1f7h5tv3Rr5/ff\ 32941# Dzc0/zct/kZ2QMAHWJWgpugu17Mt9Tc0HRppHm0dGR9++bX7blP8y4aMOoc5CG4M/XRkv+/LNyEhzU/lUUVrARKKDQ/GNn35smnVxymKK7sX/V8Hdz74f\ 32942# fjdKLi1tJBBS85KTe32uSH840OSQKTTXTWv8P7yH3+w/cFBOAApzcxvY2ysLYSqz9428zqQY1qrOX/7wI9FI6w8NbRjYa2MWwuTEf/5jQSZiEIBx/rf9x\ 32943# SQMkOof6ubG7sMANS5xl1OqFxkEeO/X/te+JMyv9ncLZbP7zMyYTE6MV/vG9Y8M2m4Pn+c7+HIJav9UcAfC3NhsGzOmkhODCk90P55hgP/4+eusAl9QQV\ 32944# hqqFtDQ2gD20bG5Lh4oojd2exoAxIseOq6hwQAqeAWlLiFjiXgeAajCLKkPhM24BY83UMikQYVRAGZrvEPCy3SAoJRAKD2PKLoByzbmkIicec2jb7//m0\ 32945# yFD6nKLShoXfbhlg0EGntemwA4IPnJBWpeG75zZu3D5LpUAm7kJDWVB6wY3MQJfJUpwGAmbt3qmbtKSb67fDzOGgLsWXbjSx5Nz3SemMojmc+MgBwMufa\ 32946# i8+/HSwOMJo41YOn+S7u2UTBQQuaenvcDMrZ9QYA1vTv/Mo75fU8oHKBwK8vfhaoR6D29fklg7JqPWxACf2k2df2TJw7r7z8puBguE2NN2tu01uLbXVxb\ 32947# cKVj/QCjFf2sJJJvgUOxLKpHqIyD3ez2E7XufNul+/d4rIoavlivN4usJ+VsgPsJEVpY5qInkYrkcU8uvhyIj2sZvXqzJ+r2/QCloEm2EEqJKghuoUF3R\ 32948# SaI4uPjd+yk7tXpryfuXij/k78QOWbDABhBD5EmwRB4SV9yuDVzO1m25gcNIOS5WmtL8LSr/J2qUh5oe4REA2CNCVFQ/FI9BYwEWqCUSEyIUGmD7Bw1sC\ 32949# u2aS8VPdwQACvkqJN94VbGmxC4tEg6xkZCdtgfXvRPg8DhLlH8EEJ797R2HmjVwfY3/nUoNbW1tHrz+lLcFySl0wiFWIl2NraVlTQbOp2MZPDi8yUwRnW\ 32950# 1pkbMvQ++2eqVMmkwtQICAIEMrlizjaO57PC8O+YMWhG0ON4/Z1ot+KiimTkD4EloNF5PAtan9Kz/aI/2ycWRdEn7doK9N7HnVwN1gOgFeg0/lBI7P3Hu\ 32951# 9x8OGhQUHQgzgDdrVUZhdPJPBML3qFDkyLYPkrlFzsIZvEAYA0bkoCxlsRVQ4BQMc3E5BDE3hx/pUAcZlaDZgSO+/VM99OkQjUEKjA1nUQDvczxav80ZQ\ 32952# CUkAGPGVsWdnbM+BuhC5v5woig4YM+VJta0N3BAnrGbfFhuqBjBeDxH9SqZLGANX5i021newJB3Qjx1RpL8sEKdkgs+uDJBiUHHdsHeOcLKYShDfBfBz1\ 32953# dQPoF8FhpbOTz+TSybbgN08WrPY7DcUG1sc0ZJ7+Va4qYQlhrNsebm//PTQAPRjkxjUa3oEUMhShdUM/ouDgvdLr2YHX3aQqB7w4AY348rAvArykAE4Uo\ 32954# IpN5FlCJjdIlGkWjY70QGPPjl1wqEPPdNyEw5ofxxuYtuhuq1k8sJhInepDJZAtoKORce3Bb8APwk1rAUkmBBhriAABsDsPGeGNYdxXsxfIAAJgqwAjuv\ 32955# XWrH7Q/CMJjUUHiBbVG/PC+GCwB3MLAw/8F4BlLan3VmlIsgQfIwKMXXa17sjpa+OdpFLa7QIhwt8EA5uCkyzBnMIBpvL9aIiuXbH3lQNBAjUTR1LkeHg\ 32956# IyT6BW1f0SgyIUBA8DAmy3JiVijpknBYbh6S3TGY7gsA1WogWhWFm1RmV19fT8Np8M8fmNpSKBQHCTTBaQ1bvqXLxiAx0roygYIP00FyrZ5oVMh7VuR0d\ 32957# HnFNr1ASgqhWf5OS4SoeP3qZBfFNLOkYANYgK6+I80csJFKvjkaAKSvoabvicTVgiBoNh55iezsBNAerI6ly3MTExKTf36LE7h2iQKd80TUTmlfMEctBI\ 32958# KPrxDSF1uqMdSEC9IIaKNnkhiB0jMjLdzsrODldVVZXVvTGhW+LqmpSbf+TYHZMKGoSFEIl4ZNO9Sk8UDTrzZrWTFeVuZIvxaVeyRYQsVohgXiuryZOtc\ 32959# Fkd1R9vrM++LGW5uubemH/s2DSTCjCQTC1NIRotXAYGOprRtefqs+qsrI4JCy8Npvn3bj7XBqxO4AWE6zy1rt47J8dbwmK5sjDA+yYmk0ACrcAo8vIK/v\ 32960# QayTc5WUXaqbpy5eoGl/uZ0dZWVKoV1cmJSnXCJdRftgfyTsQA+fNvHQUAWzpkSoNABnaIC4cDxqQvF6iggEtKlm2KRgIXzYCXfeh4nIoJJ5FIpVJ7b3v\ 32961# pdUDInX/k6DsT8FyEsIliCRUx489tAac2LtihRlyuEbeQa8MxpyAIbunZVvMxQE99vSRJai+1T8rPZwHAkTsmh2xtaYBgSYfmMDfXzeYSjLTy8xODUeHu\ 32962# EwgjM6Y7nZxCXagFdHd3f5KTKJV6S3YXu+4ePnLrzjQTW1ADEI3G9pEpr2lP3sCuKA5QyBXQ3hgKskgYebJj5konZ2olrn7FihVnahMT7bt357KuDx89C\ 32963# gAmFSCCRgNBYQ1mLi8xO8FPEUAEe0xhaem/yTqwdfHi89UPOxnOzlSc9/qoyhMf1kq9O7bmsr59M3/fkWKyCbYQ7AECBJWEfDWSJldYitJ4PB65jEgUiS\ 32964# CzGCRwwpTn1acDcZOdnXE52YuWUyvPSj+PWvM1K2ff4a3De1hTsYluI/NtpLtvfk0QK0rp4LwzelsgArtcpOj1QiitWd+cWgkz0gFgbXbb2irqPUm29Um\ 32965# Jq/T7fScubEzCCJPMNs8qtXD3zzMCBWAjoqwMBAgQc7c/80QolMpLH0Y5Uo2PO+POZEedX9e6tKfe+t7axKTrw9Vbq2pZL/wqbIdqvnCg204jgFvvJ5dj\ 32966# Q6ZULh64uiGuLRBBKJEnVlktWMrAOePWfVL19LJwydps6/fWSpKS3kz49Yvll1gklT+bOTuAZzJNQxAPOsjFAQqxQk4gpPadC0LwAECx6oq8t9IRPxnn3\ 32967# fPRWUnWkq51Ue+tkiQmvqr+LP/TrueslO2y7XLgt9wpHhx0cCBiUmBrwAxGhEIEyGrBw+WRduk4+5yEVZL1lavOLHZeJZEmvlp3vn/2qa9zWbOvXCsDgC\ 32968# dfOwz6OWgJZZallnS+j+eitqBABHTjvTWVTlTGH/5VIUZ4CClbAAAAAElFTkSuQmCC" /> David Tschumperlé</a> and 32969#@gui : <a href="https://foureys.users.greyc.fr/"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAM\ 32970# AAACdt4HsAAAC/VBMVEW3xMQAAADUqJoDAwEICALFmozFqIwGBQG1jYA7O0EfICUdHiMPDAoODASth3svLzYFBQQoKS8LCQM1NTwaGx0SDg0bHSEHBgYJ\ 32971# DQTRpZfCmIpuVk4XFxh5XlU3N0C+lIemgnaif3OPcGZ2XFM/P0clJSoXHAoUFQfAloi4kINrVE0QFAgJCAece3BZRj9WQz03LCYODw8UFRjNo5WXdmuEa\ 32972# F6AY1plTkYpKysuJSEYGBwlHhsYFRELEAWotbWxin2ffXEyMzlPPjhMOzVHODMkJi4yJyILCQi0wcGTnp6CZlxPVVVDQ1VxWE9oUUopKzQsLTJDNC8iIy\ 32973# UrIh9nbm6LbWRZWGOGaWBJU15eS0IxMT0gJCkgGhYSEhUUEg8XFguyv7+Ejo7Ep4u7koWphHibeW6ZeG2VdGqJa2JzWlJERE00O0NSQjouMzkhGxkfJgo\ 32974# cFgkQEARBQUk3P0diU0ZBREQxNj4uLzoqMDZAMyoyKSY1PyEQERMcIQ8LCwwiGwgYEgYSDwSturqfqqrKoJOvlX2UfmpXW1tJSVFHR1BIT087O0hhTEVZ\ 32975# S0UiHxsoIA8nMA6wvLyMlpZ+iIh9YVhPT1hFT1h7aVc6QUlHR0c3OEVdRz86PDwxMzMpJyQnIR4qLxoeGBMcHAocIwjHnZDCpYpubXpvdnZvcnJkZG9XV\ 32976# myTc2leXWhWVWBOTk5LS0srKzA/Ni47LyovNRofIBQkKxEQGwq8oIVcYmJcXl5RUVtWV1dMS1VHPzgrKRSXoqJhY3iljHVbWnGbhG5naWVQW2WIc2BNTW\ 32977# BTUl0+P0xFSkk4OTZ6hIR4gYFze3ungHFQUGVjYmGDb1xoXlVdWVA+SFBAQFA9QEE4MjIuLy80Lyo5LRmFhJG6k4d1dIC0mX9vbm5UU2eNd2NJSVtGSi0\ 32978# 4RBYyPRQ6LQ+lsbGapaWAf4tsb4Z5eIVYY299aWlDSlN0Y1JvX09RSEBMQz5CPz4/SxinrKyVmZmNjIufeWF2Z12ObFYuJgeXgXY+PimhEuIiAAAMWklE\ 32979# QVRYw7yTX2hSURzHPZ57UeIqcvE2/IdOiZz5Z+OqUxRnc/iXDUrHGJhOlpuDMIN8mA+p0xJGU2a9jDlXIRgEjUYPG6PtZU+tFVHQ/hD0EKxeeqgoiIqu+\ 32980# 1Mrrce+cO49f+75nO/5/X6X9h808O/lMcvfVjKumjIZT3HsX4C3RRrN2eDYR7enNrjE1tbHucTG4rXJ0F995KouZ7XOxcraxw/laDlh8psD0Y1o28yZ23\ 32981# 8DHPGUxkJ/enT52ogNP4SEFygJwDFjDliyvMk0BAjX45bxT79fovgxYOZgsw6oNI4qIXaTg2EQlnIrDQEGD3fhczF0eOrN3GmHIOJ1MxX6qLHrqk5hw0x\ 32982# +AGYsjQHjuaXqo98cWB4qFWQky6PzeJJmhUqalbrJl60AxC2NAa9y48Xf9zsUZ3t5Ffq+Xko7SOrZa1YWnZb6hHnGF0vVMdehMPowQUXWjUoPALzs3ksV\ 32983# zQ08ri+J0NTdBd9YaPUnemWzhxSPnqWTJP0PWVcbVdTjtuq4J+OJHxTKpIGI8BQROr1Zsntuyy9Atmu1AeDFyczk5NuFjPMAIGwdtSp0tQjubrpDQX5aW\ 32984# GtQCty7S5MZn8+zvnIAGNX0yw8Zp8K3F4MKKdM8qg/i2sy19Zm7S4uPB/YBs9PRTt5hAG8vGJUIaRVw6zP5HBoMU9y5tYMYWPJGwka2qLL0OvE7JVt/An\ 32985# y055e4r0qbc679n9DlafLrjFKyIiLrAD32ygMK4Mw497+lkl+irT4vx59Oeaq1SeeAL795U0u6+3gkX7Vr//BltApFIrRwO3Qst1CdHHAVPZeowqCVVg2\ 32986# LL3IzPgpgcVXj5bI3q4tIVa1aZm1PM/uwhYr6jA84hADi5pnNo7OngXDFQ1szTJWE3IcLb9/QckueYlnozarYIjMw6/v6OujkvgPenb5aZkYuxQN5IlbY\ 32987# 3i4AvMAAwOygGcvxMnZm3VdcsVwz5F5wgDc7JOoSCLqvtzq8CrK3km05Zzun9tpPySlAk8GfD2zfYuDpGJ5kJHGHktYUJHAEaVMKuaeFTW2Y0pEYmieIU\ 32988# 10Jqa5HOMJDeb3XE8b3l7/NG9UUgPPgCwZYOzvpFJLGWTuxJItmBgDHY0kGUH6/ceOGn0jkmzp7ulVqAnb15LF+Se+dL1cmavpgktBHsGf3TIBRSMfArW\ 32989# QhCWMpQLOD4wAGWRAoX7++HyBknd3XO1qmNRrO1jNp74h/3mS6N/EuqmwavWgy2bTGAHSkYoVYGsdBOgVvAkCj2p5uvl7ehq3t04RdEtaEZecmnmkiNuZ\ 32990# gpJ1te/dudjpiPyuax6IExmDFGAA5j4DkDmRRAFATQvXMy4UglMkEmLq7Y1DhZrL1IzKvGB02Dl2fmNA163SivmbbVZGdEWQdh6kLt1iprxCnABACKh0Q\ 32991# AYXtWAz49e6AWn1V6pZq+eI+tUksVykEeiYTbRmShZvl7m6RLQU5QQAhA0my0pACpBCIBzngAtgV8eRJoF9uVQgEonBYpjGKmV2Doqtn+WK2VNRuZfcLh\ 32992# qNgXwiCfK1dgWrgxv0TjAPAtEOAarUoKrcyVWa7uOWcTDrUYu206SUSvs6mkAEIaoLwAkgjNQdBanSLFYMIYw9wyjSI8vkoynSjEuMwija3C6xsvlgsR9\ 32993# lhk1qur3llMBgsiOMQT1OAPLXt/vJyAUGOU732jlOz4kE+WhM/3MMcVqHtw2zm7jgik/Uz7YASC+5eASJpqpB+sFQ2IUqEYRyfl/eVmUCHYSt8UQcdrRl\ 32994# nRx0NP1piUFxxwVAwMxEqCb8SpMGFDrUNdSk6SAjZIaIvpSA2otbVW12KDtWlCIqIiKg9dIqgQ3TpHet3GIYXnv888/z/zwyacWCzVjtrQ9BKzwVkVZ4X\ 32995# MJl00O22MGrdMof1tDKCFdA2MAfSEk0UKKQhSYREdcFKhO2F4tFK/FrU7Y67k8XlYpzpX+P9Fj/pJzbstDZaVrKKCIDeAqDRuYWRDVCTrW+DgaTBmlSDg\ 32996# KzYzrzP39m3L1zOlxL5kvVEqcwKbJ6xMMEU0+onreTRBJpkyNbrIShRmqSL+tYWtiFAqEn2ht/h57vHPdalnSuZdNpZDW2UU4V4pxLzt6os6YDkEAEagg\ 32997# Uk2UCPAhCLhoIh+I+d9fvqFn89tJLrqDmejzqj+bjcXWowwXTscBb2SCmBXMjUEXFBGejKE2KANUCOFmjI5YjhQsoZVePxYW69HE9Z8jud6rrF4k62AxD\ 32998# UaKDR/6YooXM0oNBYMaSRSHMcGQ+EHLgZDVa8+X5TCPed/VKp0FrMqnJIIInwdlEPmOGh//tAxggoHSARYGIE0nVNH+NZoOBsMJmkW24W98VzsWFiI1Rg\ 32999# TIE6exhIpl+kXsEaNCXMV9BmmjLDioY1DWJzkmHWwWQc3mjQE1oOrKSvNRx1byxJglDeCfB870ww/ndHYaRhPJvNtKORCJ4ZSFRE35BJy6lKxuNgvd6kz\ 33000# DgYdZElM8gAhMF/FwDqQWhDCFEAcBo5VeDJy69cylQUp8al4w5vnlUTxfbGkA8XCkIydpptNBJ28A+MTZ3BVP9FIkTdIkwVZQIjr465ADD1Nh+32KjcZs\ 33001# LZ5cCyM7GeYCu8pameDq9IY4I+GG8NpoNfv6a6CEVqjfB1bbImGq4XR0j9Gdeex4+dAsmCp+KRfesCry42u4ybf37h/JufNzYREgfit2+SJo7GYm+MKQN\ 33002# CaEynhkE+ChC+2//g84Mdp085vUmhWiqwQaERdft9xTr/5cfShQ+rn+6u7lrdZud0BU0MGkqiQhlmCxOMUGTTRf57By+/DB3OJoqynBTasQRbDfssjlCx\ 33003# 8+VOeOnp+107rnzfdv/jvUNXIpGjoydPJkQAcByHJ2uTva+fXd2z48Dlt7//3M5mni+m2zmmwjc8cpPxpLtf7twJP6puX3149+HFQ9/v7vr+8eO967vRa\ 33004# C7wt6ayCW0aDsN4RCzm/xfTP4kpaA0eEhDxq0Fwxh2MGi8GEouWmFjBXoTUeGhr20npraVd1Yu0q1URD461tm47FWuFtqNrK6hzuokgzrGjil/gB17MBH\ 33005# /393ne530Or8uVvPHg0cQlsRi31HNXn/8Z3nS6PnN0+v7mzee3bVy36/zhx7MBR/3xi4M1b7nJ8SaLr0KW3+WzZ+3XduP9i0cTLx5xghGlw+jck9/7nWv\ 33006# uphztO8Ondq3fuP3QvgPDtn878msikc28/fguDzPVqm+8AbkpUP2IY7ceTg6h1wzo1xi6q8UvPdty89iZg18DgZnIhU0njl05Ox2Zvee4F7n9EOpUtWaa\ 33007# RSZcZHNsbnm5NRhkxrHjbpgh+zhrIXf8U7AIT04c2ToyMhZwBJaW0mPz6XTKYZN6+fMNIng2iVpdujColJTeoqCaZCOEsURTzTA0Ho2rYAHQweT1oZGRv\ 33008# XvvOQLz7bELewKOf/PTvyY5hrGPqHygmVxFknOyXFSrPuYjNi4KUBV8FKHQyHDdjtOj1717926YrQcCS/PtmVWBQGp68pIR7FUk2I9+HsC5FkBRXQZ4iD\ 33009# HLWI0RcC8xjnhe6vqHRqkSGL3+fWRDZEfd8Z/Uq8kbKEfKHbgTfYrmvKUWSBpSh1Y1/F0ZIxmzLzTIMmuAIE0kaDgHnpz7dvd0atV76XSkbuf/8cA1V4J\ 33010# zDFqrFTslmJPXUD2dgTWg9msYp2bjkunJQpcnGPYwxJSuJ0afnrw2vbpBfWa2PT8TGeL1SrArkoSzEPsAPSvyWkCQeeQjCZLF8q6MXQNu22tEMpGFMQU0\ 33011# p+DDB7vbY6tEvqYj1NTKSicXRAS91hYQhF6MJgS/iji7liZGSXiIoqNRCLUoT3hdJGMgnFtz8UL6y90NZ76mD1/DG6GerNe8Ccbr0oTlxVIlyQJfk8jbv\ 33012# fqqmCto1TjNWIiDoEYRIuFnOUjGPUn/cGQs/eXOxZ1ixvtZIX0myWQF65PSEphlvMHhoawPiawdwSTDMLxgRAsgXOAJXZY4WpQVxIeAy3V5WJEInGM/A1\ 33013# +ZdJMiwAuxFX+PMxEtIicNRESSGBJBtBi3V0gYQYHhdcMUqVJUkaBVXLCCMUlnGI4uNTiax1XCFlAkmcapAZ53rnGzXreFAcPSDAXGw0OEpWYggfwxmZc\ 33014# lq4AoIRyWlQrQKyLbcIfjRYvktDBoDZrqYg6nPHzflzU5DAF/AqeUboxPJCQ9V4LOWMW/KFmwKcbU7KKkzHWE/DjhmSpoCcLZ1fQO7uMId1VI+rM4zXr/\ 33015# AnoH9FcRhS6kAAAAAElFTkSuQmCC" /> Sébastien Fourey</a></center>") 33016#@gui : url = link{"( IMAGE Team / GREYC Laboratory - CNRS UMR 6072 )","https://www.greyc.fr/?page_id=443&lang=en"} 33017#@gui : note = note{"\nIf you appreciate what we do on <b>G'MIC</b> and want to help us maintaining and \ 33018# developing this piece of software, please consider <a href="https://libreart.info/en/projects/gmic"> \ 33019# making a donation</a>!\n\n"} 33020#@gui : note = note{<center><a href="https://libreart.info/en/projects/gmic"><img src="data:image/png;base64,iVBORw0K\ 33021# GgoAAAANSUhEUgAAALAAAAAwCAMAAACG2QC0AAAC+lBMVEV7e3uQkJAAAAAMDAyIiIhdXl68vr0rKytmZmZsbGy7vb0mJiZxcXF+fn6NjY17e3u1tbV0d\ 33022# HRzc3OEhISbm5u8vLy2t7Z4eHh6enp3d3eVlZWUlJSdnZ1vb2+4uLiamprOzs5XV1ezs7NpaWmHh4etra1eXl6Dg4NtbW2np6eDg4O9vb2YmJgrgnFwz7\ 33023# xqzbn6/fxlZWVsbGwvNjRtzrtuzrt00b5iy7Z0y7pky7b3/Ptxz7z2/Pr5/PtbyLI9ppFnzLd2zLtyy7lozLhz0L3z+/ny+vhmy7dvb2++6eBszbrB6uH\ 33024# a8+3W8ettzrr1+/nd8+/S8Orm9vN20b9SUlLo9/St49gqfGwuWVHj9fG5596G1sZcXFwyMjLw+fdopprk9fLP7+htxrRBkoLu+ffs+PbN7ufG7ORajIIs\ 33025# g3Lf9PC76N9+1MNpp5teo5VboZPU8Ouv5Nmr4te12tJ40r9ku6pmsaNZp5hNmInq9/W25tyZ3c+B1cR+tak4jn0thXRdXV1QUFDR7+mz5dup4tam4dWj4\ 33026# NSQ2suN2cp60sGZx79frJxlppljpZjY8ezK7OW649qb3dCU281808KFyrxqvq1NnY09k4Ivi3lOTk7E6+PI5+G43tag3tKk1cqK2MhPsp4+kIA4jHwzjH\ 33027# vE5d2t2tGp186MxbpWq5pWoZJAmIdFlYYyk383inpWV1fQ6eOx5dqo3dKd3tGw1s+oz8eYy8F20b5pzblvyLaDwbWDv7N5vLCIurBwr6Nrr6FFrplEqJR\ 33028# OopJSno81iXkrg3JaY2FDSEfV8eve7+ud2MyizcWSzcBtyLVfyrRww7NzvK50tahZtaJksaJol45EnItdj4VUioAziHdbdXArfW0qeGlTbmlkaGdiYmJg\ 33029# YGAmYVU3W1RQVFMoXFJIU1E+Pj7T6+aY1MiOz8KG0MGOzMCNy75owrB7s6hknZFBo5BEoY9DoY5UnI41mYVjgnxfgns9cWcnZ1o+X1k1TUg5QD4sPjsfP\ 33030# zgzMzMkKilq0aUXAAAALXRSTlMdvgAO0AmQAv33kAjy38w1MBPu1rJ4bibm5MS8uKqJdV9ZEv20nJORfGVUPh6rD+f7AAAHWUlEQVRo3mJgggJuhsEMBJ\ 33031# lgAOpgAQ1ZacZBDFTUtJSQHCwoKsyjbDiYAQenpIg2O9TB7PwinIZHvzg6EQcsqAYciQcXjhpyCIlxgx3MLi7C0XBbj6bA2gUFmJmZuegBSbwgGAJg3Lc\ 33032# 37vBocoMczCzHGXP7DB7baOR8M+JAMMzhwZfvCPODHMzP23BjqqkevYE1DBDrcrNtRznVuZkYuEU5Pk81oaODMZ2OHyC8FW/Ix8/EwCxz77KeqaneIAfW\ 33033# ZmbWO2IkFIEO5mu4agIFpkAwONxuHVxSYoae7s+E8IixMzCzwB2McPWAu7yjwC00OwdFyMVlR6MHFyvIwRleXiYowAsIQE4fOLcXuhkYuEVtQxVMavRgA\ 33034# zkYQE0Z7KYNBAH03o+BOdSsdu1dIRnbMiYlsQQSdoUaiYQq+BAQl9jcIAQujYBTK0X8QpRD8wk99dqf6E901osDjhWlx+QdGHZmdubZB3/+Wi7XFZkwJg\ 33035# 788+6fUrQir/V8zLKvs+wzAH4UHqTywkUy4SLF1v/sqReyL+7YHgPSudlnngm/NZIzJXzwxG9aeHLK0Jd/C9+J8PLWAMSK6+9D+FPQBIT7ia7rWlEYP2v\ 33036# VqimT1Wo1Depkqqj+qFDOyvtkvlmNUKFQxWC+NO7w1qoLEt5ygyC4Xy0xbSrh79kbptSRUIyV1TQYDIJ2UteuXW+kOc545LrXzs+Z67qe58YP2LYceh4e\ 33037# B9OEIk71po134vlGjlh7niwG92vN0YZ4R4JhrebX5LSy4yzbrnuHO6P5dOC68Wyx2++YSYeDMmaSq7iSpvPCKYSgiteyGGeG7df0E4AjndLJEcA5jU7Uj\ 33038# OZZQGl4rA6WP6LIrGMbDCunCxwxVcsMqzMv6x14YkhTxjjtpJyOYD8oXZz2mgynds/VfhrFHQaHcH9NkbwwQeQFonsWR12DcauSEyZSOC1Ad05wm+zinF\ 33039# +tCJ315B2GP40wFeZpH7+olC4M7Ep7jTYuQJQwUcIkvDTSIuPHqkxWNoc89pwgO+EPqfAfkrG8Qsmksr32LvWaFC4Rshc+N0OvB6wvhQ3vcdG3oRmQ7Rf\ 33040# O/XiR9A0s1QgKt8JS8gs3jQkyaYE1JIpM+JEQJXzXBeZtxzftfp8o7gx4Ru9hJ6zthUVGpYdai6gkkLoULguxwRW3YiyFhYgawG7FBIVdIUIfjIEY2WCP\ 33041# sP93A8DfiHsUjsjGBTjTBRKhcFs8oUthInAEqooHG1gcbh739dVzYd6YCDndNM2/O+F/1NNLaxNRFMDxT3TgrBQu9zKruSJNmRicagpOIpO0JDKpbakmC\ 33042# xOIrQXTxKBpUrTGJrHvqpRasK19F+wDrJZCv4BvxBe4905m2kqTxm39LwYuzJzzW8x9+lva720QkUYcZ+/eG5AG4gI8IEm9VxEfSB1xwV48/VBFmpZeO8\ 33043# Rz8UyXD+UhaZCyYK8k6mbIe6VWRF/rrSY/kssDkuiFC+W8dLjhqgAvSuYIkpYyfmSyq761+5RklzkKJlfEGNHS0tKPd9Y/fP4i7Bf9oKGIcef0qm6CdYC\ 33044# EWPEYrl9GdD9vdlHkW3BNbFsfuqMSps7Ac8Ke9YFohCINBRrQiqbm9kDU4UX5NhwUNsFPoDyiH5bTShnlq38DVjcqwI3fwO7CpQrwWm7YwZlJ9mcqwFbK\ 33045# lXFzmxUfzJXBE5Vg7+wq/BMcCw+6y2SW2jkGTIcmjgeL9vTsZDwiJtzXBdFpglOHYCK7G3Rzm3UIPowCbFKmzgFArI2h1mKC1fl+RD45VhUs7oJDgBecJ\ 33046# higqCcaUxoybesYsH94rQY4HJzRC6XSggvxTqGOYWQ0Gr0hDuky+AHYCTBtB7thH1OmCsXouIrMuWKCXS3gYOifj1UBj99nqIaj0VkVySC8PNdTiJaK0x\ 33047# ry6WPAkVmoBVZk59nuu00c6UZfRkZ0tHU6CSozNcAjzwjyeNdNNyLP52ywuE0YTFQBlz6KqfVtDUGC2hy8pNqr1ke3UgrzblcHM/d2TbCMVkrTd8jWKfu\ 33048# HQA0wzDuINZv3Z8EGP9mUkTT/qgTDaLNNUupAgNGKT05UB9P0bi1wrsvpkxnhwXwiBn3Xp7wyIdzbsAO1wLDQrHJCNedQFvbBsHKOoPypEiymtrvMqe7O\ 33049# BMBIo1ujjPocw8tQHcw/Qy1wbKwl2WN4ki25NRDpoR6Ppyc0FgMohgxDOKwKIcPzEw4KZMV74iMdQEgNI1kEWB31GMaoOOeShicMfzduTw0I/W4o6TH39\ 33050# YHdV/nIneutCj45LXfGIwwPe1864WCIxSY2Hq9zhRJCqBzMwEkHl8t+yU+1i/Idgf8D/GdIYIg7mGvUwbQE4X/ADuZb90B3aICbT4SAw63cqve+39IdEu\ 33051# BbCC9wQJtdgfPYfd0hAf5ySIsDJ2XEpRoeDIkgfvSQR54d6GBuBYl1P27qDnrw6BiHjA54JlRQjifm8W/dwQ3u/3p4V1gAOtcsKMrL0fD4p/EgBsfW3eW\ 33052# UEmCHz+YLyPIKcRoNYsAjyScPmc4HAHFPJOZJDzOgAAAAAElFTkSuQmCC"/></a>} 33053#@gui : url = link("Go to the donation page","https://libreart.info/en/projects/gmic") 33054#@gui : sep = separator() 33055#@gui : note = note{"\n<b>G'MIC</b> officially collaborates with <b>LILA</b> (<i>"Libre comme l'Art"</i>), 33056#@gui : a French non-profit organization, which promotes Arts and Artists as well as access to technics and 33057#@gui : knowledge for everyone.\n 33058#@gui : <span color="#EE5500"><b>LILA</b> collects donations to help developing <b>G'MIC</b>."} 33059#@gui : note = note{"<a href="https://libreart.info/en/projects/gmic"><img src="data:image/png;base64,iVBORw0KGgoAAAA\ 33060# NSUhEUgAAAJYAAAAyCAMAAACJUtIoAAABd1BMVEX///8iHCSKb5H+/f7KyMrz8vTw7fGfiaWag6DNwdA5NDu8rMDm4OiOdJWgiqb8/P2hi6fv7+93c3i7\ 33061# ubx/fIAwKzL49/j18/U4Mzr7+/v39ffJvc36+fq0oriUfJvs6O0oIyrb2tzVy9hBPEPy7/Po4+mCf4Pp5evZ0NvHusrDtcbBs8WvnLPu6u/c1d7Ft8iRe\ 33062# JiPdpbj4uOwnrWrmLCmkauempuCfX1hW1s6MzPOw9G5qb23pru1pLpybW1DPT3l3+fi2+Tf2OHe1uDAsMO2pbuyoLaXlJTt7O3TydbQxdO3tbeppqichq\ 33063# JVUFZKREQsJi7v7PDa0t3DwcKjjqmIhIc0LzYkHiby8fLT0dO/vb6olK6WfZxaVVhMR0vYz9vGxca7q7+yr7KtmrI+OD8nISnr5uywnbSsqqyal5uYlZe\ 33064# McpONiYx0b3LY19iqlq+koqWhnqF1cXZpZGhjX2JdWF5RTE4yKysuJycmHh7Pzc6QjZHw7PF1dNCuAAAF40lEQVRYw+2Z+VfaQBDHh26JWKupWpPmABRR\ 33065# LgFRaAuoBUSqKNb7vm21rdr7bv/4zmysUgM+fMY+fuj3h52Z3XnJJ7uzZKPwX1fUvuMq8sE/UsOtq+guGJL9jFspFYyQVYrBbZEcfSI6xx0QI8FGFa06y\ 33066# kM2OktGbkS5yckBSS1GcyJ3IgzUXBlW870atXGOFXCEuW3SMvyuWj4TEQkvrmWH8oww8ums34uOe9C4f8sYdUtzocIcdfc4ee96KnuoAaX1e8DtLMNqYV\ 33067# CbGs+w9HVPiDvOoshtKGrYOby3UqJJsjco2J5jFVMJmTv+IDcGVjFEwCqlxQ9918XyR/WESo7gXM+RldOJbUYpAQAWpwrMHLJyLGVfTmlmrNAENgsCTwv\ 33068# v370eFus73C35DddX0rkVWqh2ttM4Wy00LbMLYjnWXceuc0ExYTVGceoxn9KYp3ARS1d5IEmMKZIq0RVFSVUVHGK6hFLKsYR1rzdSYDQngrtBorsKwkKY\ 33069# LpDY9gacvLb2Na9PPsPKe7ze/bsmLGFhVGjKMyNN7LuI9X6TB8cjTF2IHbnWMwATrqPmUkCEWYcLFSjH6sEyVxp1wKSxoaxRU2NzjK9mdCylGI8YcDYJ1\ 33070# DNBkCmEz/L19hk70+vhRgiNTYhwmvbLcwHr6TMePHrMZJfW40+47KA5RiOh5iALxzS/339whvVvZMaK4BM1Z0HDrcR2HWI41kND9YCVa/YRFpK46gbLGU\ 33071# 270iJhiXLiLS7icCgU1MuxJnt7e3+qYNJAL+rNabCH/jFcqpeY8p7ViHUvnojFZdBi6wnXhg/CsUQ83ieVY9232WwPWsGk2zZU+2nQhn7HpVQrM5jSOVD\ 33072# 7ItodedBcwaZmP4BpES3DemUjLbKascAZp0Vk6ZJ0c1hqN8daWqkZS25I85L3bgTYjWFN2gy9uwTr68jISNs4xxoMph0uYycyrV8Nx+LDw8Mh0Wos5dMp\ 33073# 1hepKlb7CMd6+Zrpob63g4FZgAiRSGNZ+5ATlbcc602nzbZMV7LdroZVi6zG6sXxzfHn2I6w+sEav4Pje2yRsgbqB+slDt+xQ1cn2lfVsfQeqjzxQKZIF\ 33074# UUVDTY89Lp1q7HEaeMnS/mMdkuqhiVGM14AVswFZIyiuVyAnz2VuEJhRrUaa5Vmqet01pZ3qmEpGgVMY9kM2pSmFdG4A9GgzI+2ktVYdIlpuvFKB3on1b\ 33075# CYFhGw9cxpKmH1+FJofFkP/4wKjAoWY9mXcHSK3/iE8sar1ZYi6JTklSjAhqyigCKiVb1W19YeDs4YLGs2IqyLncio0D8avn6Hr2c9YA0s4+DkabBIRd9\ 33076# VD1ivyy+w+gKjY1YJa36RB0UPFdYj/hyewtu+qADuYa4gsxBL38KxD38ikaJuvRLWwyc8GNzFZuf7FuX0lXadGxvug0Jh4ahQyFuJtUp5a2Vzh9q5BGss\ 33077# BMBGPn3/QVhDAF5HEw56+q1dREZv6ecrZ3HXDE0eq44VbARwJ29vPjrFgkL8BrDsdCxtO4/FTYyXWqtjuQWAqSfiVHLFwNLvpW8Aa95GGN3n6qCOvepYh\ 33078# P54EQ6+tSNWIhVI9PvAeqwPtkr6JF6GNfC1vbV184RBX3/DRiwD1mONP6iI1TFwGdbU92Qy+S3ZSosYdmnWYxmfFp1/6QX/1LgM6/HH+fn5vW9riIUg/Y\ 33079# L1WB+psla7yrVDXNOiGSs5OTnZLgP0fKXfE/blxCj5ButL3kcF3sagXArtxZkuE9ZUEvUEV7d9i7/XH36RhvJotx2I6i9ZiTVFSfMXOh9S52sTltRKEtF\ 33080# ZMY7QraKk82Mz9imqhVj88LCkV3p3b4nXf1Uvrd3+SxWxZv7OWRURoJPWsOLR/sWb62KZNFMBy6TndoD3aJfXKv+Z5Gc5VmlWqE1RC7D4tDxQzScw2ovd\ 33081# rAzrVnONOrIAixdRG5jECNe2eq3/+RzfMamb+n+QNw+GFs1J0zJMkd0Bs97RwKuzMNB0FQlAkuxm8cIlRwGoliQzo1cEsxQaUKGO9Rt9fgZfvm2LPQAAA\ 33082# ABJRU5ErkJggg==/></a>"} 33083#@gui : sep = separator() 33084#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/03/13</i>.</small>") 33085fx_support_us : 33086 if $!>0 k[0] fi 33087 gui_print_preview "" 33088 l[] 33089 filename=${-path_tmp}gmic_donations.png 33090 need_update={"Y = date(0); M = date(1); D = date(2); date_current = Y*365 + M*31 + D; 33091 Y = date(0,'"{/$filename}"'); M = date(1,'"{/$filename}"'); 33092 D = date(2,'"{/$filename}"'); date_file = Y*365 + M*31 + D; 33093 date_current - date_file>=15"} 33094 if $need_update i https://gmic.eu/img/donations_latest_months.png o. $filename 33095 else i $filename 33096 fi 33097 0 t. "Latest donations to the G'MIC project:",0,0,24,1,1 rows. 0,120% *. 255 channels. -3,0 33098 rv a y,0.5 drgba 200 frame 4,4,200 frame 2,2,0 to_rgba 33099 onfail rm 33100 endl 33101 if w>w#0" || "h>h#0 rr2d. {-2,[w,h]},0 fi 33102 j.. .,{([w#0,h#0]-[w,h])/2},0,0,0.85 33103 33104#@gui About G'MIC : _none_, _none_ 33105#@gui : note = note{"<center><a href="https://gmic.eu"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAA\ 33106# BXCAMAAACJMYjxAAAAXVBMVEX+/v4cO0s7OU4wPnEiJSju6+qiqrCMlZu3u8BufoHd3+FDY2JRLzljS2bLz9Lp9vrteR34lyZqHE3puI3S7/hbX6GUW4z\ 33107# wza97QiOaYUa6mqTdfz25i22+VxzqoGYqrht5AAAWRklEQVR42uyabZfiKBCFFYUCDDg7TqIh0f//M7duBSEx2p09Z18+7NzTPUYaE/J4qyjI7H7rt/5m\ 33108# nXe/9VtfS+vdb21U7Me/hNbblPzu/6czEs/Y39LmT/jU36C0+7/p/OvXeaf7S3+7bkQ19uN4uVzGG3/i31X0/3GyEFjXnu+991sCMN36dIGu479tLR9Cl\ 33109# +J/ll3PLMBKbJXbipbW+nq9Lgan2U/cl8V/4Tz3r8r+hEKMu/9CDCrDStdLz7RKXDGly+MxTBqZjM4hyJ3GR4Y1/suwOoHVuf8EFmgxK6YFWMyBI0yaGd\ 33110# Two+qPH8PwuDAvLX36fiyw/oFKRcdEHYuS9UtXB4GVSP/9HLw15JwjMtGfzx/jELwyLCjp3fUx/AEBUzlgYI8rh6oItBCGl+/TjH975Rj9p5QI+4gaVug\ 33111# YWPnQxOrvN5an0yFrv9+rE9m3oz7zD5xlxyviEBpHRiV+KqQgHAzoIeLAxAe+nw2tifq88pKn5P3bUTccZqzC69g0nc0f7f4ZY3l3OLQioQUdTsb/eu0W\ 33112# /RSKu8iwsrXuHHWvKsju2Vlgde3774cd2dxRe0s2xjI4psEhtl5ZpvAzdIVVNVgQXDo8jaWJQ9RGCdLtgeZjtAi26BftBqgyrCrg0suqxdvcoEdm1fdgx\ 33113# Uiqo1YOuxdjbasc6DmO1j5haeqgkLxe5e9uxQpid/EdpoYPA5FGxwYi+55WtCzDIlaMku6EgFL7gzJ2Hvbu0BKrsKq07KKfib/K150uOQoZzicVWr0E4a\ 33114# 3XG2AZMhgGw/LzcollzeLzuiu2Wotj0YcmG8sz6aYBMPM+fSl1UECzVyxjcEnFDS2i7HCYw9KnfQukS1Lod2ILzg1oTfTPW/DjBOtebPVKaUZrFFa3DYl\ 33115# WOzLmgKGbikaH0DIr8i+Z/QXVglqiCD6pMxwFAqthWDTjXRWVaqkFLdx1hnUgk3OStTNWh/YV1WmC5cwsN6K+MtZH87QW0wKrAmjOavq3RGJ/vT5uN7sp\ 33116# dz7tbWNtVbCWNFSljmml9POtGjaUt10TkN2TIBVrBeN3azlmxbBYFRY72+QmYxcxiAEKo6JWPjY3FiZBS9YXJ/N67zGxenwOQ2hAJG5k1eLKIuNrs7E2d\ 33117# fB0VQwpMau3MZgzlY+J/bVLPRJeppXsGzerYLquPYSDaILVSjZol7DoUPP66XQCMMkYMBbRnBVEZA35PLVzgr8Lq8vlBRfauLHQYlQbqgYGUFmpEP0MVp\ 33118# QEUBU7NhZ+wwoU+CWHzjryffq+76q1yOxWsgod2swqCCxdqVRYtrDKtFrhJZnNOL+Edf4VnTPGABZ07X9kLqBVA5KboFrV3/uL3jBZW6SJIoql3NJ4lbm\ 33119# wZrEEUBlV6JKoe2b3TpjggxptcBYnLT56F4cyfTzDsM2wGN0rLH+qrNDTiMidOK85fAsra52MLcGphwGskL3FRiVjXbIeBdYGVlKmE3+1eTjB+o/rHNsh\ 33120# BGEWqEsO8wIlFrCwscqH/E9+3zMxwFrFYc2IXeCJMKgShqDxhGLnQVjKKoOLEpEAY2OtYJ396eScezrrDmMB1eUKWktjQUOGdU+bHmboGC2PrQWq0JqPh\ 33121# HUnsEJmRS7q536ssYnZ2YoCjPpeWCEO3eqsRmAFwOLL5jD0cqzmzvJBWO0zK0dRT9eMfFGy690ZnPp0Utlyo0ShFPLjDNYPbuJlRz+D9dFaZ1zK4BuyXg\ 33122# LOU2gxYMvKCN4ZC4KHEHNUawrhZRPpJSx0E3EcpvgahSqwlKgmeD5+gUXzIKQCPQPT7zaUz+HIbtWzlDU2Y2qa8TJz1tiH4/EYZrDub/O7NxzvEM/IJlq\ 33123# pryPKQH4X/eddziCsWAp371531crIK6wGKvNhsfKEBcZ6AwuqsHQ7M5Yj0lv2SO2xCYrw9oLCgac6e22OxwbOyrQefeIW1fRDhTW+OR0dGBOEuGcjTTmK\ 33124# z26snnWrL1m2EVaN8MqFc+2Onh9gsRWbzujF+QhRWKz1ARab3s6NhRT1LSzQcrBWRBRKlXUftQ4Mq6+whhEtoPWjwOr96mwtk5LrE5lqBm0dWHnnQDDGC\ 33125# IMtAThJMpAKKDu/2vjygMRgWRlbiuhUunHiE1TfwNJUWSEOdltgcZzg4o4v2Aus4bo7O0ZzGzIrNHmGtVfuNoO1SvEGrKRWIDsnqWUNaLFIZFkogViRlr\ 33126# oo3yAS1lznNSyo0mpSwr3nE8rdFFisAmuvFrCe6X2/0ViSs1gEa1meC5+wrFNHNYel6XRUh1PqMyvWsIrDYixeKmj9mnK8td5r7JIYsqGbP3mwKvwEK9F\ 33127# 6t+r8AuvYzMVLnuRn/nPcxD6tsMISViuw5KLFWOC5VVodQwhaYLEuu2idc/0cliEub91lmMHq9RtYeTxEbrXXiCmZnCDpQkewUt7Vo9Bx5DQKCmS/WUFV\ 33128# TjXFV6Y6iLPU2lnsCGzRnDIsUihSJ4DOxbwP+oWtOGGJDJ8oULrdp9WOzNZpnIfh1aAeyLDu0GO13rHTOgHI2N5tG5zxHknKskzX5jsIiiFxW2JcTUD0c\ 33129# NleYJHzfxEWth7qTRrZilZvYYFVmQ15NO0hwzKoeeVHz3iti9KcFNlaamRYU6Glr8yKYZUEz0V9onTlakJYyXpnlbR0ttbkbqQDHLYQv1VZoTOWlZg+Xm\ 33130# yEGQIytmr4l0hvhFUVbAW8NlYNQ2EFeja/z3WDMjQRgfjlLatKKx4bsleeDbGl/ED9joUgU2IBliyBuHHIrADrNr6eMeLiUFs8VqWODArFFyhFryGplQF\ 33131# LyQ0GFk9Lm2Dd5rSsnf9VWK1z1mQslWHF4/4QcnpHg6ACj/fOmmDlN2TxPLUfhMZDuNwHNhQzY1x3pgUN8NRkrsdlvafsY766WGlBCqBkp9eua9MISp3t\ 33132# Al7IboA1Lo01W/KkEF5ZlZ1SNa/gLb/l99NwKWZWrC+sVdo1i601INCYDfYXJlbyoJXh8KF4amKFh/1xt6ZFe/7GXtUSMwIopK8YnERNlT2q4iyi+D2s/\ 33133# trfFrCaso8YXmDBS7MELw0Cy4BjzllTnnzCOn/I7/gLDsCq0GIhhXPsZY0XpgUNhdXt8X4DXsdIbYXUGgk6cPI+GpkKwyotGYEl6Yxh+e9h3fopDsfQZC\ 33134# Uz+SEWVqbQqrBYBRbhgOGV/H6usM7vH0aDE5gJLAnEsgU/cAAKKn6Qwz4rAkjeg+8/bJT6aCFjJ0X8IjWRUxDGR+YTLAG5ARaDAi2imuJ1jsJMy5njN7A\ 33135# wOeYwRH6vzvpsrHOOxgLrxt7KsC5PVgKrosLj6C+egmmfgcXImKKhVsbUYnABG7avOZxU0SZYRc7WFB/zTk92lnErWDUuAcsdi7P2Aqsm+PPnyVAOsrPw\ 33136# KJBpAcqAnA5cMjMWWBOqy4b/+BaJKK8mltPinsdaVBYQrLCCpckVAQfkb002FvupxCFZuWZZNNl3sMISFqZGHt9+goUYg/jwa1jnJ6x0Y2sJLZ4KJ00lA\ 33137# 5rQeAeqccsGvJ0/tMRx0SusKWKCc2tY6lj0/IuvK8OQahwaL1GYa1tHQX3tLJKL7iGEIaQ/FfGCaOI00cxR2PR4ajGwYCxgkRfOX9CIRu6QNmwqWzCCch\ 33138# lRZa3Wi55SW/OQD29gcdZvBJYrsIpCSuUYAHRN71tgIWWJDGUoAuxLWKwCK/AUAx4PcdTY31h9P/KxmExQjVHvNsiAi7B6kVnDkoG70wqW54bUHdewssi\ 33139# EfCSzhi2wyLyDFWqCFztzBIqmi+pC6nMYZmkA6dnfNyZ1haRBlN9PpvK7bTLqhdXzKBirX4pSZLa9fOmO/CwWvMIzH0ahlmFYCRFeGixtTdy55mksZ9ew\ 33140# JDPu1T4Xpcc/STe7JSdCIArLCDQ97OCFVZaxtnz/x7RPA2kGknEsj7pGFoT56NPLTyKdbgZLDXYLFhTEakiaHw/kJQix1d71h5ACKQTVTZFHMhhZ4Tdep\ 33141# Cln7QJJB67r/NLt8E1h0Q/W5x5hCRMABKyi3/NAkvYeO0ehfZth1fDdXIO1g1I7AscMic0uYInqOsti67tsI/LHQ7K46PMTyATWdymvhvz8l0+osHdu9S\ 33142# BglTQ1wATXBLJlzf5BWSkskeSsGRbiSURpP8DKq/MSFmp4ySUBlptguZbQNWcFvK6spKDU1eaF1rgLvz4O2tVvKknsYkqQgnCSfF8H4hyimdZkQ3BVXJv\ 33143# IUQxQxbVL+DQABsvj9A9FgBWifAtcDk4kVTU+iUqosNwJVjt1UFjfssFyKDAat5GVoid0WMdUXHCfkoIeTLHs98JLYBmfZ4Q5PXoOq2Mx45DBUht6ZBqV\ 33144# RZZHDuuVi7oQKnwIANCKHELF5s42bCldo5eciaTGLVZjkk+Uh5XNQ9VYiR/l3gfF2Evsd05fDZYh02hLU/OCvFu1HbFYaFnmGWBhCB0Wznd0TKKUcw2nL\ 33145# M/eYTlL8K6haqvi5A3WelF7eQIIUoy+vOkDYSVSVhBgVW3HJa8e9i/k5HcqpyEALLrGL03UQVUja8ubW2E1gQrJv7UG91Umc6mw6hT0yAIm9A4bosANSu\ 33146# WfYEVMS84SWabP7w0X1qi/DVaLr8sOkt9ew+ozawo7t8gCF05liCy4cIK1mWCfIiOWlmNC59BhbQYLL5VV6z+wM3EKtz5cUWkxYjgzyVeLLGwOdSPd3kE\ 33147# zwNqgdLlyyPkNrK+Uzldde3FQfd4eWl/GyHIjLH+CFTKG02BDWUs396RlsKAO61u8H1q2iAeruLHg4lTGpHUAkpyatn2jhNaHsVJdTEc+udCNtPJ5HkMI\ 33148# AsC5nmMyQgsVDJYbYdXeUZaVOnzYLdddqClT9Tz8m374KT5TnvNo2FcDthPAmGMUDxIx3OiruO5xoF1pPc6s/ArL0pDHuF7JidrIbEeW9HFt4KEvSl2H5\ 33149# aacpZ5VWMVXyL15REXg7wUtZ3VWHVZgb7A8lzAMKWFC12zVLjSqDTNYVeHdDsdD94Vd338aKQ/F91GbBlYrrjgHPZ7NlKPSUlgZjzzDciOskFuyao0p2n\ 33150# 84wvLKqsGCihvk8/OisxCcTeXFogGs4GC1/ihXE9cvoVRhsT/puLI5e4WVF1D6hdIC17tRWI+LSAKrP4zB6qGFWu08rBuzubDD+noJCyk+D7g2pogT3ea\ 33151# eF2nsuT8MkbPwaTnL9MGfDwGW6BhLN06X+RDDtgvqSS4ve8ydR1q+yWV7mBFWNx3FZ4ScXGg5C3QGWF8NFhpml+deTWbEFRYiTXhx9quwvxhB0d821LEm\ 33152# 3RlUv632UzpF1nInSXNBknONDQNjNrSyb1nBmAtf2vDJzvkOK0Rnsn67Ynp7hQ9YUGEkrEWW2incOXLoUQ9ABsrpnaL3a4jv5CcnGirIs8GC3UZYZC3hw\ 33153# hVWAKxngVHYyUpN/pnFymqZad21H6qtHxqdJN+If2cVEtbvdSJNHVx2jAx/acRVRH1vZFQpPvlV6bHXfVihcG26yox4+VnNwIdpm1jdg6WbELcIsNQoGL\ 33154# 7pYuAmP8Lq9Sh9OfvQbxR12idYAbC8wbrq1GDd2AX9NyyoxNwAQQZL1wX1jGalRRe0PNsKXoXHabBCREGtxQWwQoWlf3yNLG+KaezU+TewMnG6AevHD4N\ 33155# 1y4arSoq8GaSmzDFiO/PGvDE3XNgVTWmXDFZXjpbHqhxqIbJGpP2noTVLp07f+v7ChpY88NnJ/4SFOcNCibNrws4zTqjWJrSt0ZWdd0wU57tEijFNZZGG\ 33156# EmplKZ6bUUxTp1NwecwqMZalN2CB1ltY9OWmQr/KF9W/UtnDdd/gi6A4jZuJmPqZUIhkKj08qMpqpakWCqzS0mluy6xOCqjCHQMd17D4Hiq7yy9JoI1vg\ 33157# 7/GFYUGtvW5hgEpqWHkwbQWDj2b1mZnhd4pVDu8iP/l0xzM/BoWDpj+tHN2u23DMBSObfBXG32Tvf+r7hxaabu18RJsHXYxAi4tRTSlLyRttU3kc79oS4\ 33158# pTf5GTcPxDc9in0xePTzi09V51n/WxLp8tu2Rm4WAU/DWBM7p8yuTrAevuY/xqv/N2quf5AHakvG2p5W3gp0vKU058nbDu7njiBH5FWIqbOrZRUGrlxJO\ 33159# aqRF+jeEvEFw+xherypvWMuwnj6n56Jry0VLdUks8lTcBWBEBWPfkq5/Uu3WM8LFCe8YCHYal77HaWMYY9gorl6FCtf38mQoQz9cWjOrdmiwfXP2g6CO0\ 33160# XBNohz/BqsBqwno+tBJs1LWwPgWVAClFKyq3wQBxVw1Xc2lYvWRtWKWK3KOqynSX7iEr3wZa2a/vVX1f9CUyq0yvr3ZXKlP3lN21ZuQFSLk7wri7Kt386\ 33161# kajKp6zD5eH08B0kuaean5clM2L/Dqw7sP6cje0fA2HEswwdbFgTInY6rZg1kQj6YwwK8ICBgTOtkXagJQ4foKpDhWGRDhmGhimxYgtgaKHhhVbS/+Vyb\ 33162# axvZpnQIM0JDuq9sseS3fFyhHrgBEuDG2JyHVkhGr/cWBE1cLLaBbVaVr6OmGhvj8fWgbnByzfcR6LeSXiDSx0GX4Dam7eaXhAWSwdhKCip3s7VXV+FnY\ 33163# bhrw+1rGiN2+wQgHJdH1vDlOGYw+sozwMM3jjVYPnMIqFQ5U8d5gU2swJL0DTMcpWqsizW2GzOof1ZdV7YWkyYXF6sSwMBOFvh3va8832LCGsGIypI/yz\ 33164# 5zv8ipcdPWAr0hfjV40wFXXV2qImg6QvrhnwfzIPrHZgRA9stdNT4YihbXSg1UxYHbBMjPNoWFHUNqzH32UV6yOw8GCadyIL11b47z1zsWYxhoq5cYO1O\ 33165# xYyYcXwMQwTTR3s9aExRgHW621p375Vt9i7de+MLKxxM3GsPZXJTHOD2/nsf8BqtTOGZRCnXgBBJqx+5wb0hCVywMrWDMaTeq9kdVqyzp+1dDUhMRBYzY\ 33166# HektEhDJMxXjdyI6phKcaFYXIsUAByjU5N3ybbvWGNyg0Bou9gXRrWBnOk4zbNScEKIh3GhwEjBE4OWOsLLKnlPiwxFMqTu649BIvyMSxG+gFLbXh2gSc\ 33167# e1isbrEBEJ9kReKRAVxss3glLtzDPC2F9iwKrCWv/9g3H9jGstc3txVyUYZTSxjGKHnVRHDOylglr9jWXhqU/Rhbv5XW2h57lnVl4JncqvOgIG13PK47i\ 33168# EVYXWUcx4q3LRJjh9IBly1BlZEV0Gm6DFdyPkm/hcsAivgDxn9Nw1qxCBNzM6YGTCG/UhfMIB5F2SljxAot91CyurGMc9zYNIWfPc6LY7JwG1vlTaSo9K\ 33169# JdZYWywfO4WIFaBRpRoKxbIqMRRQTRcoBpUELTJVedUD2NlpqVYZLuhSejOgfnOPOkpfOY8vRqctNPDSIU+Y/QwtGkWyQ638MT5ruHK7hNakDTgWk8fHF\ 33170# ROzOfnmRJwvAWnO9vo4EvHECi0S3ik144+x/gRWjas5jBYQcrl1pI+B0BvswtN5Y35gPkaKdUeWrKUlrMrcToNBSDQJ+CJEe4ihYHlKY6ghA5OhHXlTMR\ 33171# jPdnrnG8d9sc3vHsfrWbjGsPiw80Jx/F4Z/1Wprkxd0926Tcd7ej+Fa3vhiw455Ia64dPDNyTfp4cGWE5574/bz5T9yFLDz+HYEe9eECk+h9aXzn1feqT\ 33172# halb8huwnzGXXwyVdH9qySJZkPz/XfH/5b/88/IdcfPxH+J0LVIAAAAASUVORK5CYII="/></a></center>"} 33173#@gui : note = note{"<center>is proposed to you by</center>"} 33174#@gui : note = note("<center><a href="https://tschumperle.users.greyc.fr/"><img src="data:image/png;base64,iVBORw0KGgo\ 33175# AAAANSUhEUgAAAEAAAABBCAMAAABW61JJAAADAFBMVEX27vz06viVWEaZZlbz5/Tv3urwxMeFXE2icmuBUT7w4u7QzeKaaFqRVUPs5vWKVEKBRyvr4vKR\ 33176# WEfSj4d/aGWuaVjkqqaca1+ATjnAfHCVWkh7UD/z6Pbv1d6DVUSGUT2TY1ONWUji1ubv0NiHeoaLd3zEgHW8d2qQYFCOX0+LUDri2uvcnpeQen+md3GKY\ 33177# laYYlGXXk3p3u3Z0uTFyN7nr62Aa2uoaFehYE93Tz/tvb7su7yYf4XIhHqgb2WRZVieY1KKXk/u1+Lvys/uwcPPi4KkZ1eiZladXk2ZW0nn2unXxNHpwM\ 33178# XqtrXntLPfr7DhpqKtk5yHdXuEcXSoc2uSbWeeZlaIWUjj3u/uzdPTvsrdu8LHrrmjipKQfYZ2ZWalbF9zYF+TaV6gaVurZ1aCYFakYlF9WEyJW0uDWUm\ 33179# PUz5yTDyETDTd1efSyNrRt8HOtsG8pK7go52IgpTMlJCbhY+rbF2QXEt7U0RiSTxXQjJ1PiLv5/bx4/Hw2+Xfztvmxs6WpMLlvMHNsbvCp7CalqqkjpuR\ 33180# h5iefX+iene3eW23c2VhXGWpbmKLZl2wa1unZFN0U0hrT0U/OzlRPC5aPCsrKyrKzOHCw9nnzdffx9K3u9KvudKnsszAtca+r76tqL2UnLfcqqp6iqiGj\ 33181# KWxmKK5mZ7VnZmbipbZmpLUlo68jY1rdY3JioC7f3eveXGfdG6wdmxpY2yIbGqxc2ZRTVNkUk9LQTt6STGFSjBHOS8qJR4gHhkWFxLd2ey5wNjGvM2Jmr\ 33182# mvobGCka+mnK6Pk6zZpKNpgaJ+g5mtjJB4eo6UgYu4hYHBh3+ZeHl2anBsV1RwSDM9MytmPig7IxPSz+ShsM3lubvetbl4k7TOq7LFoqnSpqd1hKLHnZ9\ 33183# paXmVcm6FaWRMU2F7XVZDRUpeRTZTMBxgMReaqsezrcC8n6mklaKfkaC/l5pbcY+nhoqvhYNMY4Cnfnx3b3xbY3eOc3W1cGFcWGBiVVZbTEliS0O4qbjS\ 33184# oKBQaYhBSFRDMiYCeYKqAAAKU0lEQVRYw42WBVhaaxjH4XDOoUREUhBEBQRFBLu7u2N2TqdzttO56czN3Kauu7u77rq7u7fb3X2/g9db3OeBv/Dg83D+P\ 33185# /7v+d7vPR8OhmE8Jhx4GSLsSuytFYyHceD9l/+fiPFrwD9/0/FjiHEM3tiYMXaZ9vt/+rVULNxfoHE39oH5MTcex8DhYB03EDCmL+z6+NTPVStWLj+xPA\ 33186# oGtH+GGxNAjPPB57/lOPNS/74D+18m7d7d359/3btTCAj/QowVB0LouLGvnbd+8/2Bw7cOHz584Kf9+3+4keSdMAXRvQxE0Amvzb/ss1f7h5tv3Rr5/ff\ 33187# Dzc0/zct/kZ2QMAHWJWgpugu17Mt9Tc0HRppHm0dGR9++bX7blP8y4aMOoc5CG4M/XRkv+/LNyEhzU/lUUVrARKKDQ/GNn35smnVxymKK7sX/V8Hdz74f\ 33188# fjdKLi1tJBBS85KTe32uSH840OSQKTTXTWv8P7yH3+w/cFBOAApzcxvY2ysLYSqz9428zqQY1qrOX/7wI9FI6w8NbRjYa2MWwuTEf/5jQSZiEIBx/rf9x\ 33189# SQMkOof6ubG7sMANS5xl1OqFxkEeO/X/te+JMyv9ncLZbP7zMyYTE6MV/vG9Y8M2m4Pn+c7+HIJav9UcAfC3NhsGzOmkhODCk90P55hgP/4+eusAl9QQV\ 33190# hqqFtDQ2gD20bG5Lh4oojd2exoAxIseOq6hwQAqeAWlLiFjiXgeAajCLKkPhM24BY83UMikQYVRAGZrvEPCy3SAoJRAKD2PKLoByzbmkIicec2jb7//m0\ 33191# yFD6nKLShoXfbhlg0EGntemwA4IPnJBWpeG75zZu3D5LpUAm7kJDWVB6wY3MQJfJUpwGAmbt3qmbtKSb67fDzOGgLsWXbjSx5Nz3SemMojmc+MgBwMufa\ 33192# i8+/HSwOMJo41YOn+S7u2UTBQQuaenvcDMrZ9QYA1vTv/Mo75fU8oHKBwK8vfhaoR6D29fklg7JqPWxACf2k2df2TJw7r7z8puBguE2NN2tu01uLbXVxb\ 33193# cKVj/QCjFf2sJJJvgUOxLKpHqIyD3ez2E7XufNul+/d4rIoavlivN4usJ+VsgPsJEVpY5qInkYrkcU8uvhyIj2sZvXqzJ+r2/QCloEm2EEqJKghuoUF3R\ 33194# SaI4uPjd+yk7tXpryfuXij/k78QOWbDABhBD5EmwRB4SV9yuDVzO1m25gcNIOS5WmtL8LSr/J2qUh5oe4REA2CNCVFQ/FI9BYwEWqCUSEyIUGmD7Bw1sC\ 33195# u2aS8VPdwQACvkqJN94VbGmxC4tEg6xkZCdtgfXvRPg8DhLlH8EEJ797R2HmjVwfY3/nUoNbW1tHrz+lLcFySl0wiFWIl2NraVlTQbOp2MZPDi8yUwRnW\ 33196# 1pkbMvQ++2eqVMmkwtQICAIEMrlizjaO57PC8O+YMWhG0ON4/Z1ot+KiimTkD4EloNF5PAtan9Kz/aI/2ycWRdEn7doK9N7HnVwN1gOgFeg0/lBI7P3Hu\ 33197# 9x8OGhQUHQgzgDdrVUZhdPJPBML3qFDkyLYPkrlFzsIZvEAYA0bkoCxlsRVQ4BQMc3E5BDE3hx/pUAcZlaDZgSO+/VM99OkQjUEKjA1nUQDvczxav80ZQ\ 33198# CUkAGPGVsWdnbM+BuhC5v5woig4YM+VJta0N3BAnrGbfFhuqBjBeDxH9SqZLGANX5i021newJB3Qjx1RpL8sEKdkgs+uDJBiUHHdsHeOcLKYShDfBfBz1\ 33199# dQPoF8FhpbOTz+TSybbgN08WrPY7DcUG1sc0ZJ7+Va4qYQlhrNsebm//PTQAPRjkxjUa3oEUMhShdUM/ouDgvdLr2YHX3aQqB7w4AY348rAvArykAE4Uo\ 33200# IpN5FlCJjdIlGkWjY70QGPPjl1wqEPPdNyEw5ofxxuYtuhuq1k8sJhInepDJZAtoKORce3Bb8APwk1rAUkmBBhriAABsDsPGeGNYdxXsxfIAAJgqwAjuv\ 33201# XWrH7Q/CMJjUUHiBbVG/PC+GCwB3MLAw/8F4BlLan3VmlIsgQfIwKMXXa17sjpa+OdpFLa7QIhwt8EA5uCkyzBnMIBpvL9aIiuXbH3lQNBAjUTR1LkeHg\ 33202# IyT6BW1f0SgyIUBA8DAmy3JiVijpknBYbh6S3TGY7gsA1WogWhWFm1RmV19fT8Np8M8fmNpSKBQHCTTBaQ1bvqXLxiAx0roygYIP00FyrZ5oVMh7VuR0d\ 33203# HnFNr1ASgqhWf5OS4SoeP3qZBfFNLOkYANYgK6+I80csJFKvjkaAKSvoabvicTVgiBoNh55iezsBNAerI6ly3MTExKTf36LE7h2iQKd80TUTmlfMEctBI\ 33204# KPrxDSF1uqMdSEC9IIaKNnkhiB0jMjLdzsrODldVVZXVvTGhW+LqmpSbf+TYHZMKGoSFEIl4ZNO9Sk8UDTrzZrWTFeVuZIvxaVeyRYQsVohgXiuryZOtc\ 33205# Fkd1R9vrM++LGW5uubemH/s2DSTCjCQTC1NIRotXAYGOprRtefqs+qsrI4JCy8Npvn3bj7XBqxO4AWE6zy1rt47J8dbwmK5sjDA+yYmk0ACrcAo8vIK/v\ 33206# QayTc5WUXaqbpy5eoGl/uZ0dZWVKoV1cmJSnXCJdRftgfyTsQA+fNvHQUAWzpkSoNABnaIC4cDxqQvF6iggEtKlm2KRgIXzYCXfeh4nIoJJ5FIpVJ7b3v\ 33207# pdUDInX/k6DsT8FyEsIliCRUx489tAac2LtihRlyuEbeQa8MxpyAIbunZVvMxQE99vSRJai+1T8rPZwHAkTsmh2xtaYBgSYfmMDfXzeYSjLTy8xODUeHu\ 33208# EwgjM6Y7nZxCXagFdHd3f5KTKJV6S3YXu+4ePnLrzjQTW1ADEI3G9pEpr2lP3sCuKA5QyBXQ3hgKskgYebJj5konZ2olrn7FihVnahMT7bt357KuDx89C\ 33209# gAmFSCCRgNBYQ1mLi8xO8FPEUAEe0xhaem/yTqwdfHi89UPOxnOzlSc9/qoyhMf1kq9O7bmsr59M3/fkWKyCbYQ7AECBJWEfDWSJldYitJ4PB65jEgUiS\ 33210# CzGCRwwpTn1acDcZOdnXE52YuWUyvPSj+PWvM1K2ff4a3De1hTsYluI/NtpLtvfk0QK0rp4LwzelsgArtcpOj1QiitWd+cWgkz0gFgbXbb2irqPUm29Um\ 33211# Jq/T7fScubEzCCJPMNs8qtXD3zzMCBWAjoqwMBAgQc7c/80QolMpLH0Y5Uo2PO+POZEedX9e6tKfe+t7axKTrw9Vbq2pZL/wqbIdqvnCg204jgFvvJ5dj\ 33212# Q6ZULh64uiGuLRBBKJEnVlktWMrAOePWfVL19LJwydps6/fWSpKS3kz49Yvll1gklT+bOTuAZzJNQxAPOsjFAQqxQk4gpPadC0LwAECx6oq8t9IRPxnn3\ 33213# fPRWUnWkq51Ue+tkiQmvqr+LP/TrueslO2y7XLgt9wpHhx0cCBiUmBrwAxGhEIEyGrBw+WRduk4+5yEVZL1lavOLHZeJZEmvlp3vn/2qa9zWbOvXCsDgC\ 33214# dfOwz6OWgJZZallnS+j+eitqBABHTjvTWVTlTGH/5VIUZ4CClbAAAAAElFTkSuQmCC" /> David Tschumperlé</a> and 33215#@gui : <a href="https://foureys.users.greyc.fr/"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAM\ 33216# AAACdt4HsAAAC/VBMVEW3xMQAAADUqJoDAwEICALFmozFqIwGBQG1jYA7O0EfICUdHiMPDAoODASth3svLzYFBQQoKS8LCQM1NTwaGx0SDg0bHSEHBgYJ\ 33217# DQTRpZfCmIpuVk4XFxh5XlU3N0C+lIemgnaif3OPcGZ2XFM/P0clJSoXHAoUFQfAloi4kINrVE0QFAgJCAece3BZRj9WQz03LCYODw8UFRjNo5WXdmuEa\ 33218# F6AY1plTkYpKysuJSEYGBwlHhsYFRELEAWotbWxin2ffXEyMzlPPjhMOzVHODMkJi4yJyILCQi0wcGTnp6CZlxPVVVDQ1VxWE9oUUopKzQsLTJDNC8iIy\ 33219# UrIh9nbm6LbWRZWGOGaWBJU15eS0IxMT0gJCkgGhYSEhUUEg8XFguyv7+Ejo7Ep4u7koWphHibeW6ZeG2VdGqJa2JzWlJERE00O0NSQjouMzkhGxkfJgo\ 33220# cFgkQEARBQUk3P0diU0ZBREQxNj4uLzoqMDZAMyoyKSY1PyEQERMcIQ8LCwwiGwgYEgYSDwSturqfqqrKoJOvlX2UfmpXW1tJSVFHR1BIT087O0hhTEVZ\ 33221# S0UiHxsoIA8nMA6wvLyMlpZ+iIh9YVhPT1hFT1h7aVc6QUlHR0c3OEVdRz86PDwxMzMpJyQnIR4qLxoeGBMcHAocIwjHnZDCpYpubXpvdnZvcnJkZG9XV\ 33222# myTc2leXWhWVWBOTk5LS0srKzA/Ni47LyovNRofIBQkKxEQGwq8oIVcYmJcXl5RUVtWV1dMS1VHPzgrKRSXoqJhY3iljHVbWnGbhG5naWVQW2WIc2BNTW\ 33223# BTUl0+P0xFSkk4OTZ6hIR4gYFze3ungHFQUGVjYmGDb1xoXlVdWVA+SFBAQFA9QEE4MjIuLy80Lyo5LRmFhJG6k4d1dIC0mX9vbm5UU2eNd2NJSVtGSi0\ 33224# 4RBYyPRQ6LQ+lsbGapaWAf4tsb4Z5eIVYY299aWlDSlN0Y1JvX09RSEBMQz5CPz4/SxinrKyVmZmNjIufeWF2Z12ObFYuJgeXgXY+PimhEuIiAAAMWklE\ 33225# QVRYw7yTX2hSURzHPZ57UeIqcvE2/IdOiZz5Z+OqUxRnc/iXDUrHGJhOlpuDMIN8mA+p0xJGU2a9jDlXIRgEjUYPG6PtZU+tFVHQ/hD0EKxeeqgoiIqu+\ 33226# 1Mrrce+cO49f+75nO/5/X6X9h808O/lMcvfVjKumjIZT3HsX4C3RRrN2eDYR7enNrjE1tbHucTG4rXJ0F995KouZ7XOxcraxw/laDlh8psD0Y1o28yZ23\ 33227# 8DHPGUxkJ/enT52ogNP4SEFygJwDFjDliyvMk0BAjX45bxT79fovgxYOZgsw6oNI4qIXaTg2EQlnIrDQEGD3fhczF0eOrN3GmHIOJ1MxX6qLHrqk5hw0x\ 33228# +AGYsjQHjuaXqo98cWB4qFWQky6PzeJJmhUqalbrJl60AxC2NAa9y48Xf9zsUZ3t5Ffq+Xko7SOrZa1YWnZb6hHnGF0vVMdehMPowQUXWjUoPALzs3ksV\ 33229# zQ08ri+J0NTdBd9YaPUnemWzhxSPnqWTJP0PWVcbVdTjtuq4J+OJHxTKpIGI8BQROr1Zsntuyy9Atmu1AeDFyczk5NuFjPMAIGwdtSp0tQjubrpDQX5aW\ 33230# GtQCty7S5MZn8+zvnIAGNX0yw8Zp8K3F4MKKdM8qg/i2sy19Zm7S4uPB/YBs9PRTt5hAG8vGJUIaRVw6zP5HBoMU9y5tYMYWPJGwka2qLL0OvE7JVt/An\ 33231# y055e4r0qbc679n9DlafLrjFKyIiLrAD32ygMK4Mw497+lkl+irT4vx59Oeaq1SeeAL795U0u6+3gkX7Vr//BltApFIrRwO3Qst1CdHHAVPZeowqCVVg2\ 33232# LL3IzPgpgcVXj5bI3q4tIVa1aZm1PM/uwhYr6jA84hADi5pnNo7OngXDFQ1szTJWE3IcLb9/QckueYlnozarYIjMw6/v6OujkvgPenb5aZkYuxQN5IlbY\ 33233# 3i4AvMAAwOygGcvxMnZm3VdcsVwz5F5wgDc7JOoSCLqvtzq8CrK3km05Zzun9tpPySlAk8GfD2zfYuDpGJ5kJHGHktYUJHAEaVMKuaeFTW2Y0pEYmieIU\ 33234# 10Jqa5HOMJDeb3XE8b3l7/NG9UUgPPgCwZYOzvpFJLGWTuxJItmBgDHY0kGUH6/ceOGn0jkmzp7ulVqAnb15LF+Se+dL1cmavpgktBHsGf3TIBRSMfArW\ 33235# QhCWMpQLOD4wAGWRAoX7++HyBknd3XO1qmNRrO1jNp74h/3mS6N/EuqmwavWgy2bTGAHSkYoVYGsdBOgVvAkCj2p5uvl7ehq3t04RdEtaEZecmnmkiNuZ\ 33236# gpJ1te/dudjpiPyuax6IExmDFGAA5j4DkDmRRAFATQvXMy4UglMkEmLq7Y1DhZrL1IzKvGB02Dl2fmNA163SivmbbVZGdEWQdh6kLt1iprxCnABACKh0Q\ 33237# AYXtWAz49e6AWn1V6pZq+eI+tUksVykEeiYTbRmShZvl7m6RLQU5QQAhA0my0pACpBCIBzngAtgV8eRJoF9uVQgEonBYpjGKmV2Doqtn+WK2VNRuZfcLh\ 33238# qNgXwiCfK1dgWrgxv0TjAPAtEOAarUoKrcyVWa7uOWcTDrUYu206SUSvs6mkAEIaoLwAkgjNQdBanSLFYMIYw9wyjSI8vkoynSjEuMwija3C6xsvlgsR9\ 33239# lhk1qur3llMBgsiOMQT1OAPLXt/vJyAUGOU732jlOz4kE+WhM/3MMcVqHtw2zm7jgik/Uz7YASC+5eASJpqpB+sFQ2IUqEYRyfl/eVmUCHYSt8UQcdrRl\ 33240# nRx0NP1piUFxxwVAwMxEqCb8SpMGFDrUNdSk6SAjZIaIvpSA2otbVW12KDtWlCIqIiKg9dIqgQ3TpHet3GIYXnv888/z/zwyacWCzVjtrQ9BKzwVkVZ4X\ 33241# MJl00O22MGrdMof1tDKCFdA2MAfSEk0UKKQhSYREdcFKhO2F4tFK/FrU7Y67k8XlYpzpX+P9Fj/pJzbstDZaVrKKCIDeAqDRuYWRDVCTrW+DgaTBmlSDg\ 33242# KzYzrzP39m3L1zOlxL5kvVEqcwKbJ6xMMEU0+onreTRBJpkyNbrIShRmqSL+tYWtiFAqEn2ht/h57vHPdalnSuZdNpZDW2UU4V4pxLzt6os6YDkEAEagg\ 33243# Uk2UCPAhCLhoIh+I+d9fvqFn89tJLrqDmejzqj+bjcXWowwXTscBb2SCmBXMjUEXFBGejKE2KANUCOFmjI5YjhQsoZVePxYW69HE9Z8jud6rrF4k62AxD\ 33244# UaKDR/6YooXM0oNBYMaSRSHMcGQ+EHLgZDVa8+X5TCPed/VKp0FrMqnJIIInwdlEPmOGh//tAxggoHSARYGIE0nVNH+NZoOBsMJmkW24W98VzsWFiI1Rg\ 33245# TIE6exhIpl+kXsEaNCXMV9BmmjLDioY1DWJzkmHWwWQc3mjQE1oOrKSvNRx1byxJglDeCfB870ww/ndHYaRhPJvNtKORCJ4ZSFRE35BJy6lKxuNgvd6kz\ 33246# DgYdZElM8gAhMF/FwDqQWhDCFEAcBo5VeDJy69cylQUp8al4w5vnlUTxfbGkA8XCkIydpptNBJ28A+MTZ3BVP9FIkTdIkwVZQIjr465ADD1Nh+32KjcZs\ 33247# LZ5cCyM7GeYCu8pameDq9IY4I+GG8NpoNfv6a6CEVqjfB1bbImGq4XR0j9Gdeex4+dAsmCp+KRfesCry42u4ybf37h/JufNzYREgfit2+SJo7GYm+MKQN\ 33248# CaEynhkE+ChC+2//g84Mdp085vUmhWiqwQaERdft9xTr/5cfShQ+rn+6u7lrdZud0BU0MGkqiQhlmCxOMUGTTRf57By+/DB3OJoqynBTasQRbDfssjlCx\ 33249# 8+VOeOnp+107rnzfdv/jvUNXIpGjoydPJkQAcByHJ2uTva+fXd2z48Dlt7//3M5mni+m2zmmwjc8cpPxpLtf7twJP6puX3149+HFQ9/v7vr+8eO967vRa\ 33250# C7wt6ayCW0aDsN4RCzm/xfTP4kpaA0eEhDxq0Fwxh2MGi8GEouWmFjBXoTUeGhr20npraVd1Yu0q1URD461tm47FWuFtqNrK6hzuokgzrGjil/gB17MBH\ 33251# /393ne530Or8uVvPHg0cQlsRi31HNXn/8Z3nS6PnN0+v7mzee3bVy36/zhx7MBR/3xi4M1b7nJ8SaLr0KW3+WzZ+3XduP9i0cTLx5xghGlw+jck9/7nWv\ 33252# uphztO8Ondq3fuP3QvgPDtn878msikc28/fguDzPVqm+8AbkpUP2IY7ceTg6h1wzo1xi6q8UvPdty89iZg18DgZnIhU0njl05Ox2Zvee4F7n9EOpUtWaa\ 33253# RSZcZHNsbnm5NRhkxrHjbpgh+zhrIXf8U7AIT04c2ToyMhZwBJaW0mPz6XTKYZN6+fMNIng2iVpdujColJTeoqCaZCOEsURTzTA0Ho2rYAHQweT1oZGRv\ 33254# XvvOQLz7bELewKOf/PTvyY5hrGPqHygmVxFknOyXFSrPuYjNi4KUBV8FKHQyHDdjtOj1717926YrQcCS/PtmVWBQGp68pIR7FUk2I9+HsC5FkBRXQZ4iD\ 33255# HLWI0RcC8xjnhe6vqHRqkSGL3+fWRDZEfd8Z/Uq8kbKEfKHbgTfYrmvKUWSBpSh1Y1/F0ZIxmzLzTIMmuAIE0kaDgHnpz7dvd0atV76XSkbuf/8cA1V4J\ 33256# zDFqrFTslmJPXUD2dgTWg9msYp2bjkunJQpcnGPYwxJSuJ0afnrw2vbpBfWa2PT8TGeL1SrArkoSzEPsAPSvyWkCQeeQjCZLF8q6MXQNu22tEMpGFMQU0\ 33257# p+DDB7vbY6tEvqYj1NTKSicXRAS91hYQhF6MJgS/iji7liZGSXiIoqNRCLUoT3hdJGMgnFtz8UL6y90NZ76mD1/DG6GerNe8Ccbr0oTlxVIlyQJfk8jbv\ 33258# fqqmCto1TjNWIiDoEYRIuFnOUjGPUn/cGQs/eXOxZ1ixvtZIX0myWQF65PSEphlvMHhoawPiawdwSTDMLxgRAsgXOAJXZY4WpQVxIeAy3V5WJEInGM/A1\ 33259# +ZdJMiwAuxFX+PMxEtIicNRESSGBJBtBi3V0gYQYHhdcMUqVJUkaBVXLCCMUlnGI4uNTiax1XCFlAkmcapAZ53rnGzXreFAcPSDAXGw0OEpWYggfwxmZc\ 33260# lq4AoIRyWlQrQKyLbcIfjRYvktDBoDZrqYg6nPHzflzU5DAF/AqeUboxPJCQ9V4LOWMW/KFmwKcbU7KKkzHWE/DjhmSpoCcLZ1fQO7uMId1VI+rM4zXr/\ 33261# AnoH9FcRhS6kAAAAAElFTkSuQmCC" /> Sébastien Fourey</a></center>") 33262#@gui : url = link{"( IMAGE Team / GREYC Laboratory - CNRS UMR 6072 )","https://www.greyc.fr/?page_id=443&lang=en"} 33263#@gui : note = note{"\n 33264#@gui : This plug-in is based on our open-source libraries <b>G'MIC</b> and 33265#@gui : <b>CImg</b> (C++ Template Image Processing Library), 33266#@gui : available at:"} 33267#@gui : note = note(<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA/CAMAAABnwz74AAAC/VBMVEUCA\ 33268# wMBAQEDBgcPExQIDQ4KFBcGCwwQGRsPISjxhycoS1YZNT7rgCEkP0g2PTiOVzXidSJ4OxgXGBg3XGkTLDQbEw4eHRxCa3gyGw0aHB/uchSHPxlYVlNwNx\ 33269# kdHRtNKhNNeYgvMT8XEAnvn2vhjkjQfUi2hGWMZEo1SkzXbiQjISAmIiAcGRlnjZoTExM/IArWw7TnhWfti0igTjYmJzKlVizpcyeoqqOoRhfIZR8jIiB\ 33270# mMxQqJyqFpa9VLxhhhI8mIyno3cC8vJqJiHvkqGzujWbukle5e1CBRyyEn6I7XGN/RSJBPj0iICFnOR1aY2SgVBl5nKciIyFEJhRcLg7DvK7nqH3vr22l\ 33271# Z0qsY0TeZT1kOSerSyKTRiHg3NeESSd5VT6PsLuLr7tGRESFiIN0OBM+TlwyGgwODQ1XMhM6QVprSDzSdjloj5suMy6lfWE6VVxxSC2QPROUcFePbVSJj\ 33272# ojTx720zdXDazPGurA2U12bgnFybWhjW1YkISAnJCNFM1Tzdx32exgyNzMhHx75liH7nyH4jiFMM1UtMi/5kiDpfS/ZrowrKSf0ih/2za9JRkX8pB+aXj\ 33273# 9EQD8rLirteR3ncxz68Obz1sD1wZjUo4DBjWlRNVg6K0D6mSP3hRxsNxe/URb56t7muprtvZjhr4lqa2gyLy70jinwgx/1gBvpx6/uxKbzyKXztITcqYB\ 33274# KcH1mT3hmRGpgOVxOM0w+NzV5QiTuciCmUB/8qhzfZhbVWRP65NPgwp3btJn4yYrOoILBkXL7yW7QjmxaNlZOTEpBLknxjDkvKDLQZSDgbR59ao11XYT3\ 33275# xH14dXNycG/Wm25RP2fCiGCKblw7V1yhdlVtXVJEMVBTUE+daky5ckkyQkFVRz/5oC3CWiKwyL2Rsbn0xai+o47714byp31kYmGvfl1fXV36uVrmmFR2W\ 33276# kayYzSXSCJJMSG1ThfW5+PE1tL72pPmvopxWH9WS3adg3FYT1v7s00+OUX7rDJkj5mrlYVSaG9uaWbbdTHVCtkHAAAAfnRSTlMDAQkhFRoPLij+Vj7+Sf\ 33277# 7+/v53aTRHm3pkXf79/LSsqIh4PP7+/v38+/v5zb2ahk7+/v7+/v7+/Pz38uXBr56QU/7+/v7+/v7+/f368N3Yx7enkYtw/v7+/v7+/vzp5uPMu7u3sJu\ 33278# XcGZd/v7+9uzo5OLg39zb2NXUy62ggmXEYn5YAAAF/0lEQVRIx+2UVVAbURSGl92NJ00guBeKFau7u7u7u7tmG0KSxiGQYC0ORQu0RVociksp7nV39053\ 33279# aR+g02VgOn3r95DcmTvny7n/PTfAf/7zbyD9TTGBCOhM2Yy7DRqYzRo+H8CH6MgGR0k1df64qQHo782WZkiZ+rh+MpFKA9aEKIdbAL+ALJy3OkO/ts2Sf\ 33280# KVhobFSM9z+R5OpbGh/jF+gJvYj8II5Q9VqdXExy27OAggAZ2kqrf3CfGIzRgF4wATztbQD3tKkQM350Ea6XC6WC/n+4kh1pJw1Z5RRUlIgM85HkY13BM\ 33281# YGCCQxYBNvaUOgptFQuUql4kZFBbhwVfJIVqSqOEUzMFDpo1AwYZwEBr/YgH3rp1cqNTVb5WKBQBCACoQCd4HAn66KSkYNfgrFfTOcesLsly+x+Im77xs\ 33282# ZPQ8Q+IsDAtwvowjkqki5MEDlkpzCjFFkDyfgjA9bb+qLg1h3OtZ+KZGClk/u7kJ3d1QhEPP5LREBUVyu+mlNw3ASzgRQR46cPfXmJhAzrC7yb8m5k/OJ\ 33283# zxegCjn/Q1lmWYELl8ttnW4G480AzXw0dc/NnW1+Z7r/w1ev7uS0qNAc+OoPdzIzM8uiuC4uV1ai44QDpE0jGFR/1cXWJmL/nNc1NWUP6f4Cf35kTpxNV\ 33284# VhmASooHuLc2TsggQ4ebhaoK0gc8aj2tsfjh3Q+Cn2CTWKhR5gE6+C5CYAPw5FMktXbA8CCVD6fOXbwgEIrihiFMrnPgAEftw/CBEErYHwBRIUB3cR6LQ\ 33285# 2TVDG/l9cNXiETFQiFFN+FogHbqpJRQWrQE338p0rEhnlY3gzCviAhJhg/3iZCiEKRjguPj49D6w1TgxpxzwAxqNir23LOWNcoiCWMSB87bnAlJpBTKtD\ 33286# lwsVY/ZWg3NUA3hzMHcnAhsB+fJ+MoXZ01uL0dKkVvd+kXgWSXq9j00MfqQ1TDQ2HxE0n4hi09cy1sX+NE17BaZPpdIrdI0s7yd1bdy0nFrB2TJhgVaS+\ 33287# 4mIY9MR3Fu4l0kgwAGsTDwV7eXk/oURESFgsy74TJ/bNDe1lV1Sk5nLRS0yR2mzGSRAmUEkQzJ5LW+WFCu4PlFAoFMn5RX3Rep8KFhelKOXp0rgaM9xJZ\ 33288# juyCSBDj3w0ODgtuoo5cJBEIjnvc36RT6xPxaDk5ORBQxt9s5jzAdwERq5ypMIgDJwMDg7uk+jn12jVzzLU13p5Q25W2PlJkyzjQrJsRpHwh0DbfK0eBG\ 33289# AcV4TWNjdnh8TExipirPv375+lUNyKkVqv0cfyxxeQ9cjkn+utR6Y3Nw9sbfTLkoaEWC3zjQnLbphiAmn8BNcAQG2fbcD28yDnjSsHKpV+vrm+S5ICjYY\ 33290# MQQWdGjAIZAYBe++gjpPpzN4cjmz5EqVSyZyStGKZpPjZMHtTLQugUwXZfK42oGFh2qO6iSfyRDgc16rKyUv7P22V9OsnecZBPEW8XbokPAGBBjPWHWYT\ 33291# 502znTY1vkmEIKjhS0hFZcYt9DYLUAEHEfF4PXpo/dkAstcxyFQ9Glx9Mz7+xmdbHtYBp09oWIi3d1pa2t3vCCJrq+cNwxEwHGkgDAEaWtOabOOrm3qg8\ 33292# HjGtY9vR0dHe3tHP0Y8eSgiz2EGOGcACSCRTUNDgpxsRSJbT5FIhAXhmvjuXUb07VqOTOQpQzgznQidhAiPpgKogTzaoOexmTJXV1eOazuQwhEGELYP4E\ 33293# ME23qByNrmPS9cuHj10qX8s23k558+c/1tT6DLgNCYhISECxcvXj1z+hTGaRwBPmPelJaihvaChG4JDEpLSt78JtjUHYHW+5KS0vaC03Uf13dHYJr34MH\ 33294# 7Syh1dXX5aJSFCEdmDHa9Hp5hHH7P7RzCaQfiNqYbJ3C7dy0cE7Tn3PpuNJAXfi3c4zeBLK/LLeh6GF8rf+Dh2VGA8GaDXbxDD/QE5fWJMk5HZG5dHIUR\ 33295# HvXh5d/ceMhvAuTcvC7Va5BGuIWXG2MRdKS3E9g1gQagMyLPLVGGdCzXhYBuAGk59G5fba9FALoL0WKLk6mDg4OprpYOEfgPPj8AH7GtomieWx8AAAAAS\ 33296# UVORK5CYII=" /> <a href="https://gmic.eu/">https://gmic.eu</a> and 33297#@gui : <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA/CAMAAABnwz74AAADAFBMVEUAAAD8+/v77u/9+/v8/Pz47\ 33298# vT25Of04+aYbXL03eD+/fzx2tz89/v99/n98PHDn6ns4OnQtLqshov88PP/8/T51NT46evz4evguLmlYWn56PDgwMK7govXp6u0YG/CjZWUd5Dt1tqTXG\ 33299# WIWWLx0eLl0NrAcnnIeYDw4Onlxtf54e3z1+Xs0d/rzNvz5+704ev33ejt2ePdv87vt7ngqqyoconZpqSoUlpwPFndxdHgsbTGorHDm6zMg4XBbHPPaGq\ 33300# jOUW0NUTxzN/jv9PSl7PMj46zYWmfTFv+/P7YvcjuwMLOsLzmvrq1i5/WjZe3Z22oRk6UQk359vf77/TuutbkuM/brsPQqLrXuLXMpbXrrbCxbYi3cHaq\ 33301# WGOEQ2LDT1e8RU+YLDykLDqPHDD17/Lgs8nWqr70oKi+kqa0gpnKf43AdoWVXnvMc3qSU3DEYWTNXGKSQ1WbSVScP0uAJDj66fLrxt3sxNfw2dbqvtPdu\ 33302# svfxcPWoLnKkqq+i57hhZHTfYSpZoK8enqsbnauXGv66ez93N7qzNbrycjJkZ6xeJLTiZHDiIm/gYSxeICjYXudWHfCYG+OUGl6QmB/N1a5T1WvQVCsMj\ 33303# 9eHzz0x9/wwNr8zc/VtMPhnaPsmqHYlKHVnp27mZy9fJKYYoSld3yLWXmET3GEXGyZVFqGOU+PNki8g5zkkpvRlJiihI7Xh4yLaHqYb3nbbnFlMU2pP0l\ 33304# xLUn44t7rttDKhpXhkZCaeoavZXSjZ22AS2iXX2ezU2GPTlq7HjH61unt1M/irMuMcoGfWm+bT2mlUWa5WF3psc7/q7fXm6yrfIuzhInfe4Sjb4LafHb9\ 33305# 8vrm0MvgpMPBiafLn5+ieZW/kZGXcYueZoeQZG2OQ2OiXWKJRFR8Lz+cIjH5zuXhtNP9t7zSnqWUf46kaY17OkX91dj+xMGsjZTth5GFOT5RFjGGEybjx\ 33306# sz7wMjks8H5r7HMrarJgqHjoJhvDinu4NrWjn7NgXOhO12uTFzKaYJvHzpyRElCABtwx6DiAAAAJHRSTlMA/pTZ66c8G5RtyJC8rw7PnpSQfSTMUfTllM\ 33307# /Ev6+U7Ojg3lN8FIp+AAANFUlEQVRIx5SUaYhSURzFm4pWKlopiqB4+hz35ZW4jFuluTsjjUuZa2pOpqVONlZO5VYThZFKuLRQUUMRyCRtYBZUUmBT0AI\ 33308# tQn0oilbaC7pWEEHrvV/el/fjnPP/nztgfhsRQ8KSiCRiwKYePGjU+ElDB/zXaWqyETEYEgaLJRIDAaLNZmtrGzV8yL9TmuY3qUlkFANFDpBI0WhUrY6+\ 33309# DV4LnQtOHD5h6L8CsAQGSyyOM3BkHCkQjZbOyZDd8+btZiLPJw4fOvrvgKsBfBebynqWo1IZDBQeFUzI9CdOvHe7e32tBzfuZk4cPvqPGcy/GsB1saXSu\ 33310# JjKQDGaUahn2tmv373r7+da6vxMqsoRoo/MZk4c+RtDg9vagIK4VEqNSxlUMZCASsgA4H0/l5vJ8DN8L9dT4xYKwkUb5s2ePHLCLwA2GwlHwOGwZBQFJQ\ 33311# YaxN8BHq4lw+ebvEWvscjl1rj9bg6cP/Jg8tThE34GXFWTCRCOTMZRMJgoMUokBSXI6/fcfi/XwjfxTUVwU7Uat1blcAo1hwJ9Z7fk2Ywx44f8UIAld86\ 33312# R5iAsNkAkkjCkaCyrf30COChmgAdjQ8FjT/fjWjfncPhxOBx2oyWlEFusDs2cNm4IADTWoNPudOp0bDEZhcJSsDEJonjXX+QWLXxwvF6jN9XvDnMO5/NK\ 33313# pbs7XDs8O1R6FlNLOpLhg8MGDJ5vowjmtMvtTl2XLicVU6Xirk1bWtwej7cByFhMIIKiJ4k+qqfRnm84fCn5mE47F4xKEzHFY751CgA0BQhdGjkbAFgEq\ 33314# pQq7tKs27qIrkoZjfV6I0RwTSn3iRZEwpQ87KGXU+H7D2OhZ4novEzFAgBt8wNQczOLpdGwdAxxjioW6zZtRQtTRpPRWgcCjOAjk3KvhPOIJMt83uFL1+\ 33315# 4jDyQS3cNsvWKZDjJoImJw+LNnsTiIQkGh8GJqbh0AqFIpk9ViMaWNANHnKbsPL5qt1Say2TvJpGNDXu/qyDoqlToAgDpT8DgIwoJJYkkULBYbZx5xcar\ 33316# VlNds5qV5fV6eiefhhIV3dstC50pBJp3j0AsdPc8vWSoNC4NAnYnYs805AoQnYzBqUgPw4Djs8XC5X/9PeXjpZBKNRu+SyELBUCmWF74s+OFHDiu/UvGP\ 33317# HDCozRbFE3LyWXa2XNecyzFY1FUvNvXASo+nmE4DAM9hNnpVwpY8IpMltKVSKbbxudLfq79kqlTMtIEAACycXdW+dA1b49SwWFKpxr53I5qu6uNxLWZeX\ 33318# 5/qcR9QAPeAemuvnwuGrgUfKI7eo8Xo9UolnAWApiY1WbC6/coap12+wM6ya+z2y4tgukpVNVqt5ow53e3pU3E2tMxDZt+UyWSht+C12CjLxgpWS12vBQ\ 33319# AbhoKDBAvk7Ro5a06OlWPp2h9shQ1gEbwWqyVj4Z3wqHxHWza0HDmyezYTSVy7ppU8TJQeRqxWh+QcyICIAVNEQZ0QhIdwBDw+3ryaedylLFf7uDyruW5\ 33320# WHe2mG2B40aKefB7Zpadd1wIXz2JZvzXtkES/KYDwBAIoJJglmQxqHX9xWdHidnP7eT4QAd3RQleiOUL46CmXS7HrCMIMXgvGafetfEf+YfxriBSwiasW\ 33321# CATNAogAEORVLy73wG530cNT+T76Vr58Xz0BRzifPn24ePHQva3MxLVgjIl+DABbJHFgYf5VEkSw3zrgdN6yy+Xs9j063daNLoMqBSyYfb1ldMtr+lEDP\ 33322# enzv+ldETn9PBE6Jzvd4Xj6NFM4gkgHAsB8NRlaNXd5+5qlc+V2uY5tX7vpVKRVxUtVn75pvWeAnxTovarkB/+HD2/8EdorbQg5H770lP/0koJ2Mza2AQ\ 33323# hQCF26ZWvsm9cs1TjbWRrnplMdIrq5Wu31X1xpQCtfCn2f/G8+fOr1H9rFZO5JZA+G39SemmFaNqH9qiCKau7S7LfrbrCdJ9k5to51ZaNLtNLn8/haRfc\ 33324# MPSsLSrT/jf/zvQuHjh+fvU8meSQqm3lW/0s9DQkNHDCiqY2EwxM6d67u7OyEGq8jBEJUuNAwp1vUGllhUHYbOi7cu33o0IUzrl278gjt0f1I2ZyuXtIj\ 33325# 93ftGdkAEPGEuEAggCBCM+jk2bNzXjxQuODublgkuigyRJStC2/vWHzhwpmN+gJaqXikv6/ipY28S3n9S/SDsQCgjuLjccGSnau7Vgk6VwkIAqDgOAxGD\ 33326# 9NFEZGho+PgofXHlm87cxc53PqkzDnhKFvNaevTw4oejgH5CiDh57Q7t69bN2udRi7XyZ1rNp8/taK17BP6ey9+6bzcQ5OKozgewaKo6AUVPSgoXfaedu\ 33327# 1WGpHXrefKUltdE6KsTBO02rLUpkY15yuVUHv6dtlMEXM5Nam9sJRRura5LVa01Wj/1KA/osdPiCDoQX25f104n3M4v985v3OEL+wmsylsNptfsI6sP1l\ 33328# 2bjWZfHnDgQcHPt24cbe3vhDBrt2LllH2qAw+lQxCfFzpUdlRe0uj6MSnnQ9OioTCPrYpDL7P4bo72PXV1Xewd28cP/jg8qcbd4rJVOKlQhLBRbLSJeyc\ 33329# KteOSLmIzCepSbQIaZevXD5JE8pNsBEOGcPhOl4pDXvnRvWO44/PndhZLTqCvU5ddeEeAGwCr7uYI40jkIvLJG1fx+VyZO1Koaj003FaUmcwup8DAD+Uv\ 33330# EnbX333/v0d6x/f9dbVJ2sJ+251fPg4HgAOYXAUirjK+vBhVWWVpb/fwmRKGzQ8HqgeHjcYaO6Co56gJx3zsooBgFX8+Hoi1qElrFq7dtvp06NHTQC1AB\ 33331# 71h2cebsQt3Gixbux/WMUh1dgzGo1aq00Hml+/bg4EAtGhoFOrBlOHun5fR8Zms21ZW1FxoQJEMGF5oStTzjDFnL0cDukwh7SOeTQtcwJlnEE/sPe/9vv\ 33332# 9tuiQf8hm6yASCQTb0Afb1rMVFR8enf4IIlhUgqEwSXx+OwRBKgjazk3L0u3pYDDvzAQBoLkQQrM/Gh2K+jOdnWrqrY50dN2QreLsow/3nm0GgJI1eA5T\ 33333# KlDp5XYdxIW4XK5M1p4J5vNarTMf9bwONDd7SEFPwB90ao6do1LrO50AXbPtQoXt3rNHAHBo+eJKSc7gE0A+HZRu50KQ1KfTJhKxmFprb3c97wp0RbcHA\ 33334# kP+fIxXfY5892bCmcgr6+s7nJltbyqmjpqwa/eSqqac0QipDEfXbV8n3rOHIZE22Btqy8sbUb4j8BxonScYzeeTCWwx9g5rUBvLJM8r1J2dV7d4CoBTJR\ 33335# QGI5Wiiy1Vy0BPAx36MCJrsJcfq21EHS5Xt+P5c09B7eB2rS5dT1YMJnvPHyvX9N4i9MbGjpq4e8XCjRRGhG6JWMXi/v6N/RZ6BHlyE+WVFreajHA8Hne\ 33336# 5XSEY9kAtwv2rsaW1VEJisJdXo1YSropYU0dNLMHgGJamVDabQp48gVTS7m7IwG6pqytrEwnDRiMMO9wudwiADJ+FIixZoSYStwwm9l3tUL+NiWrHjipa\ 33337# tNTSn0XYbD1qQuWoQSVHdXp9S2udsIzWZmYbBaEQ7BowwiDFfWU77lA16lvEbQkl4RLx7Vsv9nwBsFCczY6YULbdgOpQvRyVy3UCua6v9XYbb3gAdoMQu\ 33338# nNcd7evRVSGPULWqNW31mqUhLWxV69oJwBg4tNTliwyYrL3SA2o3MFX8XU+Pl9q1zXwykf0Pr6D73IP5LrdcYNQVFZaW8sqDJzEmFJDxr5/t5oFAIdWVk\ 33339# YkqDksRxy5FJ0eSUXodElO+qQBdED9gANyGd3xeAg2ht+JRPt3lO8AI+stgtf7glb97t3+5FQAWNJPjzQ1NUWs1hTdQgfnEYk0IYj0ZtuxRrPAPGwOhcx\ 33340# G2BwO006sXs9i7fD2Ulft03jf9ZG9ClpjIQcYPIPBsVotVrqVHrHSU1kJJLC3DJbdvl33VcBmmz3Dbjg0zAY/VpM1peRiBXUfgapOeoV9XuUXAFgB2gGD\ 33341# wwH2OUQq0CNyA2pgG0yDdW2324b1PewQbObDIbiv7Hxp8X2qQqHRaIhE4pdEYs7YBYUBvgizhoITM6FheY/A1KrvsaMCVCDQ64BDYYs5zh9wG0EW2YY+0\ 33342# N/J5RqFQtn5YebsaWN+DNyTMSVLlzFk8LC+VWfqkfeMjAhUbDYqTzbuP2YXOLoH+G6Xgxvvaz3fyFJmOifNHTdm1E8qOlWy9CKnCTHLe/QmvUkgkaoQnw\ 33343# +paSg/dlMFzPl8h6OrK55Pz5s091cLHQAsXojjZEfCOj3bJ5VJrHQxg8OUPKkBSnc7XIFAV9f8SVOA299o8qIllS9TWUTVBOqxiiG2VlLObN2zh0SqsZH\ 33344# 8Uf/2SX9cmAoAXGXlS3ANXnIYFMY1PIWCB9Pyta1bt66ZUfTd7V8AJRsrXxZEweHOnMFv3roGU7Ji1rQf297fAZilOByFcwaPW4MHtjOKpgPbf9HoRUtx\ 33345# eDwes3TRLHC4wPZfVbTp6fIZRYVl+T81fdwY4Pb/9Q3i0ArjHjdFFQAAAABJRU5ErkJggg==" /> <a href="http://cimg.eu/">htt\ 33346# p://cimg.eu</a></center>) 33347#@gui : note = note{"\n 33348#@gui : If you appreciate <b>G'MIC</b>, you are welcome to send us a nice postcard from your place, at:\n\n 33349#@gui : <small><samp>David Tschumperlé,\n Laboratoire GREYC (CNRS UMR 6072), Equipe Image,\n 33350#@gui : 6 Bd du Maréchal Juin,\n 14050 Caen Cedex / France.</samp></small>"} 33351#@gui : note = note{"Postcards senders automatically enter the <i>Friends Hall of Fame</i> :) !\n\ 33352# You may also consider <a href="https://libreart.info/en/projects/gmic">making a donation</a>!"} 33353 33354#@gui Contributors : _none_, _none_ 33355#@gui : note = note{" 33356#@gui : We would like to thank all these people who contributed to <b>G'MIC</b> in one way or another. 33357#@gui : A big hug to : \n\n 33358#@gui : <b> -</b> <i>Sylvie Alexandre</i> <small>(packaging, testing & filters)</small> 33359#@gui : <b> -</b> <i>Partha Bagchi</i> <small>(packaging)</small> 33360#@gui : <b> -</b> <i>Daniel P. Berrangé</i> <small>(packaging)</small> 33361#@gui : <b> -</b> <i>Sébastien Bougleux</i> <small>(debugging)</small> 33362#@gui : <b> -</b> <i>Jérome Boulanger</i> <small>(testing & code)</small> 33363#@gui : <b> -</b> <i>Claude Bulin</i> <small>(packaging)</small> 33364#@gui : <b> -</b> <i>Aurélien Ceyden</i> <small>(packaging)</small> 33365#@gui : <b> -</b> <i>François Collard</i> <small>(testing)</small> 33366#@gui : <b> -</b> <i>Patrick David</i> <small>(testing & filters)</small> 33367#@gui : <b> -</b> <i>Maxime Daisy</i> <small>(code & testing)</small> 33368#@gui : <b> -</b> <i>Frédéric Devernay</i> <small>(code)</small> 33369#@gui : <b> -</b> <i>Iain Fergusson</i> <small>(filters)</small> 33370#@gui : <b> -</b> <i>Tobias Fleischer</i> <small>(testing & code)</small> 33371#@gui : <b> -</b> <i>Roberto Ferramosca</i> <small>(packaging)</small> 33372#@gui : <b> -</b> <i>Jérome Ferrari</i> <small>(testing, code & tutorials)</small> 33373#@gui : <b> -</b> <i>Andrea Ferrero</i> <small>(testing, code)</small> 33374#@gui : <b> -</b> <i>Chris Fiedler</i> <small>(gfx)</small> 33375#@gui : <b> -</b> <i>Sébastien Fourey</i> <small>(G'MIC-Qt, ZArt code & G'MIC online)</small> 33376#@gui : <b> -</b> <i>Gentlemanbeggar</i> <small>(filters)</small> 33377#@gui : <b> -</b> <i>David Gowers</i> <small>(testing)</small> 33378#@gui : <b> -</b> <i>Claes Holmerson</i> <small>(tutorials)</small> 33379#@gui : <b> -</b> <i>Arto Huotari</i> <small>(filters)</small> 33380#@gui : <b> -</b> <i>Dan Leinir Turthra Jensen</i> <small>(debugging)</small> 33381#@gui : <b> -</b> <i>Tom Keil</i> <small>(testing, filters & tutorials)</small> 33382#@gui : <b> -</b> <i>Andy Kelday</i> <small>(testing & filters)</small> 33383#@gui : <b> -</b> <i>Alan Kwan</i> (afre) <small>(testing & filters)</small> 33384#@gui : <b> -</b> <i>Angelo Lama</i> <small>(testing & EKD integration)</small> 33385#@gui : <b> -</b> <i>John Lakkas</i> <small>(filters)</small> 33386#@gui : <b> -</b> <i>Stéphane de la Linuxerie</i> <small>(design)</small> 33387#@gui : <b> -</b> <i>Mark</i> <small>(translation)</small> 33388#@gui : <b> -</b> <i>Mahvin</i> <small>(testing & design)</small> 33389#@gui : <b> -</b> <i>MareroQ</i> <small>(translation)</small> 33390#@gui : <b> -</b> <i>Ramon Miranda</i> <small>(translation)</small> 33391#@gui : <b> -</b> <i>Tou Omiya</i> <small>(translation)</small> 33392#@gui : <b> -</b> <i>Mauro Quercia</i> <small>(translation)</small> 33393#@gui : <b> -</b> <i>PhotoComiX</i> <small>(testing, translation & filters)</small> 33394#@gui : <b> -</b> <i>Garry Osgood</i> <small>(documentation & filters)</small> 33395#@gui : <b> -</b> <i>Jehan Pages</i> <small>(testing & code)</small> 33396#@gui : <b> -</b> <i>Andreas Påhlsson</i> <small>(filters)</small> 33397#@gui : <b> -</b> <i>James Prichard</i> <small>(testing & filters)</small> 33398#@gui : <b> -</b> <i>Guilherme Razgriz</i> <small>(translation)</small> 33399#@gui : <b> -</b> <i>Karsten Rodenacker</i> <small>(packaging & code)</small> 33400#@gui : <b> -</b> <i>Marc Roovers</i> <small>(clut data)</small> 33401#@gui : <b> -</b> <i>Dani Sardà</i> <small>(translation)</small> 33402#@gui : <b> -</b> <i>Yuri Shemanin</i> <small>(debugging)</small> 33403#@gui : <b> -</b> <i>Silvio Grosso</i> <small>(debugging)</small> 33404#@gui : <b> -</b> <i>Stepanekos</i> <small>(translation)</small> 33405#@gui : <b> -</b> <i>Thorsten "otto" Stettin</i> <small>(packaging)</small> 33406#@gui : <b> -</b> <i>Lukas Tvrdy</i> <small>(Krita integration)</small> 33407#@gui : <b> -</b> <i>Martin Wolff</i> <small>(testing & filters)</small> 33408#@gui : <b> -</b> <i>Bernd Zeimetz</i> <small>(packaging)</small> 33409#@gui : <b> -</b> <i>Matthias Zepper</i> <small>(testing)</small> 33410#@gui : <b> -</b>"} 33411 33412#@gui Download External Data : gui_download_all_data, gui_no_preview(1) 33413#@gui : note = note{"This filter will download all external data files used by some filters of the <i>G'MIC</i> 33414#@gui : plug-in (<i>Color Grading</i>, <i>Light Leaks</i>, <i>Grain</i>, etc...), 33415#@gui : and will install them as persistent files on your hard drive. After this operation, you won't need a permanent 33416#@gui : internet connection anymore in order to use some of the G'MIC filters."} 33417#@gui : note = note() 33418#@gui : note = note{"<b><span color="#EE5500">Warning:</span></b> A <b>lot of data</b> will be downloaded. 33419#@gui : This can take a long time !"} 33420#@gui : sep = separator() 33421#@gui : Force re-Download from Scratch = _bool(0) 33422#@gui : sep = separator() 33423#@gui : note = note{"<b><span color="#EE5500">Alternative (manual) method:</span></b>\nIf, for any reasons, 33424#@gui : your plug-in is unable to retrieve data from the Internet, you can download all 33425#@gui : those data files manually (as a single .zip file) at this address :"} 33426#@gui : url = link{"https://gmic.eu/gmic_all_data.zip"} 33427#@gui : note = note{"You must then decompress all files contained in this archive at the following location:\n 33428#@gui : - for <b>Unix</b>-like systems : <span color="blue"><samp>$HOME/.cache/gmic/</samp></span>\n 33429#@gui : - for <b>Windows</b> systems : <span color="blue"><samp>%APPDATA/gmic/</samp></span> 33430#@gui : "} 33431#@gui : sep = separator() 33432#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/16/04</i>.</small>") 33433gui_download_all_data : 33434 33435 # Color Presets. 33436 l[] clut foo rm onfail rm endl 33437 33438 # Grain. 33439 _filenames_grain=${-_fx_simulate_grain} 33440 _url_grain=https://gmic.eu/data_film_presets 33441 _prefix_grain=grain_ 33442 _ext_grain=cimgz 33443 33444 # Light leaks. 33445 _filenames_lightleak=${-_fx_light_leaks} 33446 _url_lightleak=https://gmic.eu/data_lightleaks 33447 _prefix_lightleak= 33448 _ext_lightleak=cimgz 33449 33450 # Sample images. 33451 _filenames_sample=${-__sample} 33452 _url_sample=https://gmic.eu/img 33453 _prefix_sample=sample_ 33454 _ext_sample=png 33455 33456 # Demo thumbnails. 33457 _filenames_demos=gmic_demos 33458 _url_demos=https://gmic.eu/img 33459 _prefix_demos= 33460 _ext_demos=cimgz 33461 33462 # Manage downloads. 33463 _n=0 33464 _N={narg($_filenames_grain,$_filenames_lightleak,$_filenames_logo,$_filenames_sample)} 33465 progress 0 33466 _gui_download_all_data[] grain,$1 33467 _gui_download_all_data[] lightleak,$1 33468 _gui_download_all_data[] logo,$1 33469 _gui_download_all_data[] sample,$1 33470 _gui_download_all_data[] demos,$1 33471 progress 100 33472 33473_gui_download_all_data : 33474 repeat narg(${_filenames_$1}) 33475 filename=${_prefix_$1}${arg\ 1+$>,${_filenames_$1}}.${_ext_$1} 33476 e[] "Download "$filename 33477 if $2" || "!isfile(['{/${-path_cache}$filename}']) l[] 33478 ${_url_$1}/$filename o ${-path_cache}$filename rm onfail 33479 endl fi 33480 progress {100*$_n/$_N} 33481 _n+=1 33482 done 33483 33484#@gui Filter Design : _none_, _none_ 33485#@gui : note = note{" 33486#@gui : <b>G'MIC</b> is an <b>open</b> image processing framework. Thus, including 33487#@gui : <b>user-defined filters</b> into this plug-in is possible.\n\n 33488#@gui : To do so, you need to create a <span foreground="purple" style="italic">.gmic</span> 33489#@gui : file in your <i>$HOME/</i> folder (or <i>%APPDATA%/user.gmic</i> on Windows). 33490#@gui : It will be read each time the plug-in is launched, or when the <i>Refresh</i> 33491#@gui : button (under the central pane) is pressed. It must be a regular text file, containing the declarations and 33492#@gui : implementations of the filters (written in the <b>G'MIC</b> language) that will be added 33493#@gui : to the list of available ones."} 33494#@gui : note = note{" 33495#@gui : Existing filters are already defined this way. 33496#@gui : Writing a filter from scratch in <b>G'MIC</b> requires some skills, but 33497#@gui : can be generally done in very few lines.\n\n 33498#@gui : <span foreground="purple" underline="single">Example of a valid <i>.gmic</i> entry :</span>"} 33499#@gui : note = note{"<samp>#@gui My effect : my_effect, my_effect</samp>"} 33500#@gui : note = note{"<samp>#@gui : Sigma = float(2,0,10)</samp>"} 33501#@gui : note = note{"<samp>my_effect :\n +blur $1 n 0,255 xor</samp>"} 33502#@gui : note = note{" 33503#@gui : Look at the reference documentation and the tutorial whose links are given below, to learn more. 33504#@gui : By the way, you are encouraged to share your nice custom filters with us on our forums, 33505#@gui : for inclusion into next releases of <b>G'MIC</b>. 33506#@gui : "} 33507#@gui : sep = separator() 33508#@gui : url = link(0,"[1] G'MIC reference documentation","https://gmic.eu/reference/") 33509#@gui : url = link(0,"[2] G'MIC scripting tutorial","https://gmic.eu/tutorial/index.shtml") 33510#@gui : url = link(0,"[3] G'MIC filter template","https://gmic.eu/template.gmic") 33511 33512#@gui Friends Hall of Fame : _none_, fx_friends 33513#@gui : note = note{"\n<span foreground="purple" underline="single">Supporters:</span>"} 33514#@gui : note = note{" <b>-</b> A big hug goes to these friends who supported the project:"} 33515#@gui : note = note{"<i> 33516#@gui : Christian Stenner, 33517#@gui : Daniel Balle, 33518#@gui : Matthias Fuchs, 33519#@gui : <a href="https://www.augustus5star.fr/">Alban Bourrat</a>, 33520#@gui : <a href="http://viewbug.com/photo/65310796">Elizabeth Hayman</a>, 33521#@gui : Nicolas Künzler, 33522#@gui : Mikael Wargh, 33523#@gui : Giovanni Bianchessi, 33524#@gui : Job van der Zwan, 33525#@gui : <a href="http://espitallier.net/">Laurent Espitallier</a>, 33526#@gui : Mark van der Grijp, 33527#@gui : Patrick Wauters, 33528#@gui : <a href="https://pocketvj.com">Marc-André Gasser</a>, 33529#@gui : <a href="http://www.flickr.com/photos/ssshupe/">Steven Shupe</a>, 33530#@gui : Mika Yrjölä, 33531#@gui : <a href="https://www.silviogrosso.com/">Silvio Grosso</a>, 33532#@gui : Marek Kubica, 33533#@gui : <a href="http://www.flickr.com/newmikey">Mike Bing</a>, 33534#@gui : <a href="http://pixby.com/">Dave Allen</a>, 33535#@gui : Margaret Wong, 33536#@gui : Adrian Bottomley, 33537#@gui : Pamela Young, 33538#@gui : <a href="http://chrisbowness.com/">Chris Bowness</a>, 33539#@gui : Peter Howarth, 33540#@gui : Marlon Montalvo, 33541#@gui : Christian Freiherr von Malchus, 33542#@gui : Nolan Tyrrell, 33543#@gui : Gilles Bouquerel, 33544#@gui : Mihail Balabanov, 33545#@gui : Rolf Niepraschk, 33546#@gui : Volkmar Geske, 33547#@gui : Menno Tjoelker, 33548#@gui : <a href="https://borkarabhijeet05.blogspot.com/p/about-me.html">Abhijeet Borkar</a>, 33549#@gui : <a href="https://www.behance.net/kontaktarl1e0a">Arleta Lesniewska</a>, 33550#@gui : Nicola Giaccobe, 33551#@gui : Helmut Mühleisen, 33552#@gui : Paul Buckley, 33553#@gui : Olivier Lecarme, 33554#@gui : Edward Ingram, 33555#@gui : <a href="http://www.gus-verlag.de/verlag/Artelier/">Stefan Städtler-Ley</a>, 33556#@gui : Michel Pastor, 33557#@gui : Sz.U, 33558#@gui : Sven Kraft, 33559#@gui : Frederik Elwert, 33560#@gui : Jessica Leonard, 33561#@gui : <a href="https://www.viewbug.com/member/KennZaney">Kenneth Simons</a>, 33562#@gui : <a href="https://www.flickr.com/photos/114936163@N05/">Milos Ciuk</a>, 33563#@gui : Manlio Barolo, 33564#@gui : John Lewandowski, 33565#@gui : <a href="http://mediaklan.com/">Didier Lima</a>, 33566#@gui : Žygimantas Tauras, 33567#@gui : Massimo Ferri, 33568#@gui : <a href="https://github.com/sina-ht">Hiroshi Takekawa</a>, 33569#@gui : Freelance writer, 33570#@gui : <a href="https://www.flickr.com/photos/49284009@N04/">Elaine Hutchings</a>, 33571#@gui : András Somogyi, 33572#@gui : <a href="https://www.flickr.com/photos/tonurics">Jason Dora</a>, 33573#@gui : Boris Hajdukovic, 33574#@gui : <a href="https://mappish.com/pages/about-us">Jeff Combs / Mappish</a>, 33575#@gui : <a href="http://flickr.com/photos/btraven">BTraven</a>, 33576#@gui : <a href="https://500px.com/spodeworld">Steven Brener</a>, 33577#@gui : Susanne Gabrielski, 33578#@gui : Andrea Correani, 33579#@gui : Mads Thomsen, 33580#@gui : Djek Eykhout, 33581#@gui : Michael Calabrese, 33582#@gui : Joachim Steiert 33583#@gui : Christian Dubettier, 33584#@gui : J. Casseur, 33585#@gui : <a href="http://www.gnomelibre.fr/">Okki</a>, 33586#@gui : Dariusz Duma, 33587#@gui : <a href="http://www.mahvin.com/">Mahvin</a>, 33588#@gui : Elleen Hennessy, 33589#@gui : BluffStuffPlus, 33590#@gui : <a href="http://www.bertrandchan.eu">Bertrand Chan</a>, 33591#@gui : Mirella Scotto, 33592#@gui : <a href="http://www.photopablo.com">Paul Sauve</a>, 33593#@gui : <a href="https://darktablemaster.de">Lars Mielke</a>, 33594#@gui : Devin Sorell, 33595#@gui : <a href="http://www.quesepuedehacerenlinux.net">Pepe Baeza</a>, 33596#@gui : <a href=" http://www.lesnoy-tanets.com">Andrey Pivovarova</a>, 33597#@gui : <a href="http://doliver.co.uk/">David Oliver</a>, 33598#@gui : <a href="https://ello.co/errore">errore</a>, 33599#@gui : <a href="http://www.anudai.de">Anudai</a>, 33600#@gui : James Stalnaker, 33601#@gui : <a href="https://plus.google.com/u/0/b/117441237982283011318/112547676857320288448/about">Paolo Finetti</a>, 33602#@gui : Luigi Scarselli, 33603#@gui : <a href="https://patdavid.net/">Pat David</a>, 33604#@gui : Juan Jose Rodriguez Vela, 33605#@gui : Thomas Jakob, 33606#@gui : Kim Bartholomew, 33607#@gui : <a href="http://www.captivemoment.com">Sudi</a>, 33608#@gui : Michael Prostka, 33609#@gui : Arkadi Gelfond, 33610#@gui : <a href="https://joeysl.wordpress.com/">Sabine Schäfers</a>, 33611#@gui : <a href="http://www.viewbug.com/member/KennZaney">Bull O'Woods</a>, 33612#@gui : Jost Jakob Schaper, 33613#@gui : Dominik Wefers, 33614#@gui : Frank McLaughlin, 33615#@gui : <a href="https://29a.ch/">Jonas Wagner</a>, 33616#@gui : <a href="www.ixaarii.com">Void lon iXaarii</a>, 33617#@gui : Mark Boadey, 33618#@gui : Laura Haglund, 33619#@gui : Lee Elliott, 33620#@gui : Bernard Desenclos, 33621#@gui : Randy Gordon-Gilmore, 33622#@gui : Eddie Dedrick, 33623#@gui : <a href="http://mindprints.org/">Greg FitzPatrick</a>, 33624#@gui : Zsolt Szabo, 33625#@gui : Daniel Hanna, 33626#@gui : Peter Bengtsson, 33627#@gui : Diego Nassetti, 33628#@gui : William Tweedy, 33629#@gui : Shawnee Horn, 33630#@gui : Stephan Munsch, 33631#@gui : <a href="http://www.mysticali3n-wear.com">MysticAli3n-Wear</a>, 33632#@gui : Mika Mantere, 33633#@gui : Christian Beuschel, 33634#@gui : Tore Busch, 33635#@gui : Douc McGregor. 33636#@gui : Marcel Dahm, 33637#@gui : Susan Voitel, 33638#@gui : <a href="https://www.flickr.com/photos/henkkoning">Henk Koning</a>, 33639#@gui : Arnie Jordan, 33640#@gui : Carol Jennings, 33641#@gui : Sébastien Huart, 33642#@gui : <a href="http://www.jessstryker.com/">Jess Stryker</a>, 33643#@gui : Rui Luis, 33644#@gui : <a href="https://www.flickr.com/photos/sallesrenato/">Renato Salles</a>, 33645#@gui : <a href="http://www.viewbug.com/member/alef0"> Petr Zagalak</a>, 33646#@gui : <a href="http://www.antonio.cat">Antonio Vicién Faure</a>, 33647#@gui : Vincent Bermel, 33648#@gui : Christian Stocco, 33649#@gui : <a href="https://www.flickr.com/photos/136307651@N04/">Richard Benedict</a>, 33650#@gui : Dr. Helmut Jarausch, 33651#@gui : <a href="http://www.michaeljamesbeck.com">Michael Beck</a>, 33652#@gui : <a href="http://rickleone.tumblr.com/">Riccardo Leone</a>, 33653#@gui : Gisela Looram, 33654#@gui : <a href="https://plus.google.com/u/0/+FrankTegtmeyer/posts">Frank Tegtmeyer</a>, 33655#@gui : David Kettrey, 33656#@gui : <a href="https://www.youtube.com/user/kncpt1">Peter Hoge</a>, 33657#@gui : Alexander Heitmann, 33658#@gui : <a href="http://harlequin.webcomics.fr/page/episode-1-page-1">Olivier Larski</a>, 33659#@gui : <a href="http://victorfandrey.blogspot.ca">Victor Fandrey</a>, 33660#@gui : Stefan Peter, 33661#@gui : <a href="https://plus.google.com/u/0/+DimitriosPsychogios">Dimitrios Psychogios</a>, 33662#@gui : <a href="https://plus.google.com/+AnttiLuoma">Antti Luoma</a>, 33663#@gui : <a href="https://twitter.com/jeyoung">Eddy Young Tie Yang</a>, 33664#@gui : Thomas Elfstrom, 33665#@gui : Valentine Boyce, 33666#@gui : George Harnett, 33667#@gui : Darius Manka, 33668#@gui : Chris Knox, 33669#@gui : <a href="http://tomtappingphotoblog.blogspot.fr/">Thomas Tapping</a>, 33670#@gui : Phillip R Ziesemer, 33671#@gui : Jean Francois. 33672#@gui : Franz Ziereis, 33673#@gui : Alessandro Renzi, 33674#@gui : Tsuda Koshi, 33675#@gui : <a href="http://www.boxrec.com">Boxrec Ltd</a>, 33676#@gui : <a href="http://www.wolfgangschweizer.com/">Wolfgang Schweizer</a>, 33677#@gui : <a href="http://www.ramonmiranda.com/">Ramon Miranda</a>, 33678#@gui : Volker Bradley, 33679#@gui : <a href="http://plus.google.com/+MarcoZara">Marco Zara</a>, 33680#@gui : <a href="http://plus.google.com/+MarcoTedaldi">Marco Tedaldi</a>, 33681#@gui : <a href="http://cybertographer.com">Rodney Lee</a>, 33682#@gui : Konstantinos Blatzonis, 33683#@gui : Simon Chanson, 33684#@gui : Herbert Malle, 33685#@gui : <a href="http://www.matthias-zepper.de/">Matthias Zepper</a>, 33686#@gui : Christian Mariucci, 33687#@gui : M. R., 33688#@gui : Mark Link, 33689#@gui : <a href="http://blog.meetthegimp.org/">Rolf Steinort</a>, 33690#@gui : <a href="https://plus.google.com/112357088505488756823/posts">Daniel Tauro</a>, 33691#@gui : <a href="http://geniisoft.com/">Ben Langhinrichs</a>, 33692#@gui : <a href="http://www.openlabs.it/">Paolo Pedaletti</a>, 33693#@gui : <a href="http://blog.photomontager.com">Ricardo Corin</a>, 33694#@gui : <a href="https://plus.google.com/115953666279509959258">James Prichard</a>, 33695#@gui : <a href="https://plus.google.com/116658221461047313647">Matt Jones</a>, 33696#@gui : <a href="http://www.flickr.com/people/twekkel/">Eddy Vervest</a>, 33697#@gui : <a href="http://www.flaviocdc.net/wiki/">Flavio Casadei Della Chiesa</a>, 33698#@gui : <a href="http://www.artwanted.com/artist.cfm?artid=10918">Lyle Kroll</a>. 33699#@gui : </i>"} 33700#@gui : sep = separator() 33701#@gui : note = note{"\n<span foreground="purple" underline="single">Postcard senders:</span>"} 33702#@gui : note = note{" <b>-</b> We've received <b>46</b> postcards from <b>G'MIC</b> enthusiasts so far. 33703#@gui : You could be the <b>47rd</b> sender :)"} 33704#@gui : note = note{" <b>-</b> A big hug goes to these postcard senders (recently received first) :"} 33705#@gui : note = note{"<i> 33706#@gui : <a href="https://cimg.eu/img/postcard73.jpg">Benjamin Russell</a> (Portsmouth/USA), 33707#@gui : <a href="https://cimg.eu/img/postcard72.jpg">Andreas Weissenburger</a> (Bochum/Germany), 33708#@gui : <a href="https://cimg.eu/img/postcard70.jpg">Patrick Wanters</a> (USA), 33709#@gui : <a href="https://cimg.eu/img/postcard69.jpg">Josep Febrer</a> (Pregonda/Menorca), 33710#@gui : <a href="https://cimg.eu/img/postcard68.jpg">Richard Gledson</a> (Newcastle upon tyne/England), 33711#@gui : <a href="https://cimg.eu/img/postcard67.jpg">James Jaworski</a> (Winnipeg/Canada), 33712#@gui : <a href="https://cimg.eu/img/postcard66.jpg">Powlux</a> (France), 33713#@gui : <a href="https://cimg.eu/img/postcard65.jpg">Volker Doebel</a> (Haldern/Germany), 33714#@gui : <a href="https://cimg.eu/img/postcard64.jpg">Patrick Wauters</a> (Bilbao/Spain), 33715#@gui : <a href="https://cimg.eu/img/postcard63.jpg">Sebastien Fourey</a> (Konstanz/Germany), 33716#@gui : <a href="https://cimg.eu/img/postcard62.jpg">David Revoy</a> (Toulouse/France), 33717#@gui : <a href="https://cimg.eu/img/postcard61.jpg">Giulio Canevari</a> (Pavia/Italy), 33718#@gui : <a href="https://cimg.eu/img/postcard60.jpg">Bruno Steinbach</a> (Pondicherry/India), 33719#@gui : <a href="https://cimg.eu/img/postcard59.jpg">Steve Gillow</a> (Fort Worth/Texas/USA), 33720#@gui : <a href="https://cimg.eu/img/postcard58.jpg">Peter Neave</a> (Sydney/Australia), 33721#@gui : <a href="https://cimg.eu/img/postcard57.jpg">Andrea [Photoflow]</a> (Italy), 33722#@gui : <a href="https://cimg.eu/img/postcard56.jpg">Garry R. Osgood</a> (New York/USA), 33723#@gui : <a href="https://cimg.eu/img/postcard55.jpg">Justin Pletzfeld</a> (Germany), 33724#@gui : <a href="https://cimg.eu/img/postcard54.jpg">Werner Meier</a> (Germany), 33725#@gui : <a href="https://cimg.eu/img/postcard53.jpg">Patrick Wauters</a> (Roma/Italy), 33726#@gui : <a href="https://cimg.eu/img/postcard52.jpg">Marc Lis</a> (Belgium), 33727#@gui : <a href="https://cimg.eu/img/postcard51.jpg">ZondeR</a> (France), 33728#@gui : <a href="https://cimg.eu/img/postcard50.jpg">Bill C.</a> (USA), 33729#@gui : <a href="https://cimg.eu/img/postcard49.jpg">Michael T.</a> (France), 33730#@gui : <a href="https://cimg.eu/img/postcard48.jpg">Patrick Wauters</a> (Lisboa), 33731#@gui : <a href="https://cimg.eu/img/postcard47.jpg">Akky [Gimpchat]</a> (Australia), 33732#@gui : <a href="https://cimg.eu/img/postcard45.jpg">Michel Thomas</a> (Germany), 33733#@gui : <a href="https://cimg.eu/img/postcard44.jpg">Pierre-Yves</a> (Ile de Batz/France), 33734#@gui : <a href="https://cimg.eu/img/postcard43.jpg">Family Hamacher</a> (Trier/Germany), 33735#@gui : <a href="https://cimg.eu/img/postcard41.jpg">Benoit Gauzere and Francois Lozes</a> (Hokusai/Japan), 33736#@gui : <a href="https://cimg.eu/img/postcard40.jpg">Dr. Rainer Teubner</a> (Seligenstadt/Germany), 33737#@gui : <a href="https://cimg.eu/img/postcard39.jpg">Mauro Mitrino</a> (Mantova/Italy), 33738#@gui : <a href="https://cimg.eu/img/postcard37.jpg">Werner Meier</a> (Mettlach/Germany), 33739#@gui : <a href="https://cimg.eu/img/postcard36.jpg">Arto Huotari</a> (Helsinki/Finland), 33740#@gui : <a href="https://cimg.eu/img/postcard33.jpg">Benoit Gauzere</a> (California/USA), 33741#@gui : <a href="https://cimg.eu/img/postcard30.jpg">Arkadi Gelfond</a> (Foster City - California/USA), 33742#@gui : <a href="https://cimg.eu/img/postcard29.jpg">Corinne Masimann</a> (Neuchatel/Switzerland), 33743#@gui : <a href="https://cimg.eu/img/postcard27.jpg">Mahvin</a> (Portland/USA), 33744#@gui : <a href="https://cimg.eu/img/postcard26.jpg">Vincent Roullier</a> (Caen/France), 33745#@gui : <a href="https://cimg.eu/img/postcard24.jpg">M????</a> (Munich/Germany), 33746#@gui : <a href="https://cimg.eu/img/postcard23.jpg">F. Albior</a> (Jaca/Spain), 33747#@gui : <a href="https://cimg.eu/img/postcard22.jpg">PhotoComIX</a> (Frascati/Italy), 33748#@gui : <a href="https://cimg.eu/img/postcard21.jpg">Guy Poizat</a> (Cabestany/France), 33749#@gui : <a href="https://cimg.eu/img/postcard20.jpg">Institut for Biomathematik und Biometrie</a> (Neuherberg/Germany), 33750#@gui : <a href="https://cimg.eu/img/postcard15.jpg">Jean-Michel Webbe</a> (Guadeloupe/France), 33751#@gui : <a href="https://cimg.eu/img/postcard14.jpg">Jaime</a> (Barcelona/Spain). 33752#@gui : </i>"} 33753#@gui : sep = separator() 33754#@gui : note = note{"\nMay the force be with you!"} 33755fx_friends : 33756 if $! ratio={w/h} else ratio=1 fi 33757 rm _heart80x73 scale3x r 150%,150%,1,1,0,0,0.5,0.5 33758 +*. 70 +*.. 110 +*... 255 *[-4] 255 a c 33759 blur_radial 4 sharpen 300 33760 i.. ${fitratio_wh\ {w},{h},$ratio},1,3 33761 rand.. 0,255 sh.. 1,2 /. 2 rm. 33762 blur_radial.. 20 sharpen.. 50 33763 r. ..,..,1,4,0,0,0.5,0.5 blend alpha 33764 143,80,1,1,0 t. "Greetings to\n all G\47MIC\n friends!",2,-2,27,1,1 33765 +dilate. 3 *.. 255 to_rgb.. j... ..,{[w#-3-w#-2,h#-3-h#-2]/2},0,0,1,. 33766 rm[-2,-1] 33767 33768_heart80x73 : 33769 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 33770 33771#@gui Gmicky - Roddy : fx_gmicky, fx_gmicky_preview 33772#@gui : Mascot Image = choice{"Gmicky (by Deevad)","Gmicky (by Mahvin)","Gmicky & Wilber (by Mahvin)", 33773#@gui : "Roddy (by Mahvin)"} 33774#@gui : sep = separator() 33775#@gui : note = note{"<b><i>Gmicky</i></b> is the name of the <b>G'MIC</b> mascot. 33776#@gui : He is a small and cute tiger who knows how to do magic. 33777#@gui : <b><i>Gmicky</i></b> is a tiger, i.e. fast, agile and elegant, just as the <b>G'MIC</b> code is :). 33778#@gui : As many magicians, <b><i>Gmicky</i></b> knows lot of <b>gimmicks</b>, 33779#@gui : and he is a direct and friendly companion of 33780#@gui : the ImageMagick's wizard, or the GraphicMagick's frog."} 33781#@gui : note = note{"<b><i>Roddy</i></b> is another mascot designed specifically for the 33782#@gui : <i>Artistic / Rodilius</i> filter of <b>G'MIC</b>.\n"} 33783#@gui : note = note{"<b><i>Gmicky</i></b> and <b><i>Roddy</i></b> have been both created and drawn by "} 33784#@gui : url = link("Mahvelous Mahvin","http://www.mahvin.com/") 33785#@gui : note = note{"and"} 33786#@gui : url = link{"David Revoy (Deevad)","http://www.davidrevoy.com/"} 33787fx_gmicky : 33788 rm 33789 if $1==0 sp gmicky nm "name(Gmicky)" 33790 elif $1==1 sp gmicky_mahvin nm "name(Gmicky)" 33791 elif $1==2 sp gmicky_wilber nm "name(Gmicky & Wilber)" 33792 else sp roddy nm "name(Roddy)" 33793 fi 33794 33795fx_gmicky_preview : 33796 fx_gmicky $* rr2d $_preview_width,$_preview_height,0,2 33797 33798#@gui Privacy Notice : _none_, _none_ 33799#@gui : note = note{"This plugin may download up-to-date filter definitions from the 33800#@gui : <a href="https://gmic.eu">gmic.eu</a> server.\n\n 33801#@gui : It is the case when first launched after a fresh installation, and periodically 33802#@gui : with a frequency which can be set in the settings dialog. 33803#@gui : The user should be aware that the following information may be retrieved 33804#@gui : from the server logs: <i>IP address of the client; date and time of the request;</i> 33805#@gui : as well as a short string, supplied through the HTTP protocol <i>"User Agent"</i> header 33806#@gui : field, which describes the full plugin version as shown in the window title 33807#@gui : (e.g. "<i>G'MIC-Qt for GIMP 2.8 - Linux 64 bits - 2.2.1_pre#180301</i>").\n\n 33808#@gui : Note that this information may solely be used for purely anonymous 33809#@gui : statistical purposes. 33810#@gui : "} 33811#@gui : sep = separator() 33812#@gui : note = note("<small>Author: <i>Sébastien Fourey</i>. Latest Update: <i>2018/03/01</i>.</small>") 33813 33814#@gui Release Notes : _none_, _none_ 33815#@gui : note = note{" 33816#@gui : - <b>2009/01/13</b> : version <i>1.3.0</i> (initial plug-in release).\n 33817#@gui : - <b>2010/09/03</b> : version <i>1.4.0</i>.\n 33818#@gui : - <b>2011/07/07</b> : version <i>1.5.0</i>.\n 33819#@gui : - <b>2014/08/20</b> : version <i>1.6.0</i>.\n 33820#@gui : - <b>2016/03/25</b> : version <i>1.7.0</i>.\n 33821#@gui : - <b>2017/05/29</b> : version <i>2.0.0</i>.\n 33822#@gui : - <b>2017/10/09</b> : version <i>2.1.0</i>.\n 33823#@gui : - <b>2018/02/15</b> : version <i>2.2.0</i>.\n 33824#@gui : - <b>2018/06/21</b> : version <i>2.3.0</i>.\n 33825#@gui : - <b>2018/10/04</b> : version <i>2.4.0</i>.\n 33826#@gui : - <b>2019/03/15</b> : version <i>2.5.0</i>.\n 33827#@gui : - <b>2019/04/29</b> : version <i>2.6.0</i>.\n 33828#@gui : - <b>2019/08/14</b> : version <i>2.7.0</i>.\n 33829#@gui : - <b>2019/12/04</b> : version <i>2.8.0</i>.\n 33830#@gui : - <b>2020/03/28</b> : version <i>2.9.0</i>.\n 33831#@gui : - <span foreground="purple"><b>2021/07/16</b> : version <i>2.9.8</i> (Current stable).</span>\n 33832##@gui : - <b>2021/07/16</b> : version <i>2.9.8</i> (Current pre-release).\n 33833#@gui : "} 33834#@gui : sep = separator() 33835#@gui : url = link{"View changelog to upcoming major version (3.0)","https://discuss.pixls.us/t/on-the-road-to-3-0"} 33836#@gui : url = link{"View latest minor changelog (2.9)","https://discuss.pixls.us/t/release-of-gmic-2-9"} 33837#@gui : url = link{"View latest major changelog (2.0)","https://discuss.pixls.us/t/release-of-gmic-2-0-0"} 33838 33839#@gui What's New? : _none_,fx_whatsnew_preview 33840#@gui : note = note("Here you'll find a list of filter additions and deletions in the plug-in, since your last visit. 33841#@gui : When you have seen what's new, press the <b>Got It!</b> button to reset the list of changes.") 33842#@gui : sep = separator() 33843#@gui : nochange = value(0)_0+ 33844#@gui : note = note("\nThere have been no changes since your last visit.\n\n") 33845#@gui : New Filters = text(1,"")_0 33846#@gui : Removed Filters = text(1,"")_0 33847#@gui : Got it! = button(0.5)_0+ 33848#@gui : sep = separator() 33849#@gui : note = note("<small>Authors: <i>David Tschumperlé</i>. 33850#@gui : Latest Update: <i>2021/01/18</i>.</small>") 33851fx_whatsnew_preview : skip "$*" 33852 file=${-path_cache}whatsnew.txt 33853 l[] 33854 parse_gui whatsnew 33855 if isfile(['{/$file}']) it $file date={date([0,1,2],['{/$file}']):/} else 0 date={date([0,1,2]):/} fi 33856 utf82html.. utf82html. 33857 if $4 ot.. $file newfilters,delfilters= is_changes=0 33858 else 33859 33860 # Check for changes. 33861 newfilters,delfilters= 33862 +- is_changes={max(abs(im),abs(iM))!=0} rm. 33863 33864 if !w # First call to the filter 33865 rm. s -,10 33866 repeat $! newfilters.=" - "{$>,t}{`10`} done 33867 33868 elif $is_changes # Estimate changes 33869 eval " 33870 ref(vector256(),str0); 33871 ref(vector256(),str1); 33872 for (s0 = s1 = 0, s0<h#0 && s1<h#1, 33873 e0 = find(#0,_'\n',s0)%h#0; 33874 e1 = find(#1,_'\n',s1)%h#1; 33875 str0 = 0; copy(str0,i[#0,s0],e0 - s0); 33876 str1 = 0; copy(str1,i[#1,s1],e1 - s1); 33877 ref(lowercase(str0) - lowercase(str1),diff); 33878 for (l = 0, l<size(diff) && !diff[l], ++l); 33879 cmp = diff[l]; 33880 !cmp?( # Same strings 33881 s0 = e0 + 1; 33882 s1 = e1 + 1; 33883 ):cmp<0?( # Added filter 33884 run('(\'\"',str0,'\"\') html2utf8. newfilters.=\" - \"{t}{`10`} rm.'); 33885 s0 = e0 + 1; 33886 ):( # Deleted filter 33887 run('(\'\"',str1,'\"\') html2utf8. delfilters.=\" - \"{t}{`10`} rm.'); 33888 s1 = e1 + 1; 33889 ); 33890 )" 33891 fi 33892 fi 33893 rm 33894 endl 33895 u "{0}"_{$is_changes?0:2}\ 33896 "{"{``$newfilters}"}"_{['$newfilters']!=0?2:0}\ 33897 "{"{``$delfilters}"}"_{['$delfilters']!=0?2:0}\ 33898 "{0}_2" 33899 33900#@gui ____<b>Arrays & Tiles</b> 33901#------------------------------- 33902 33903#@gui Array [Faded] : fx_array_fade, fx_array_fade_preview(1) 33904#@gui : X-Tiles = int(2,1,10) 33905#@gui : Y-Tiles = int(2,1,10) 33906#@gui : X-Offset (%) = float(0,0,100) 33907#@gui : Y-Offset (%) = float(0,0,100) 33908#@gui : Fade Start (%) = float(80,1,100) 33909#@gui : Fade End (%) = float(90,1,100) 33910#@gui : Mirror = choice("None","X-Axis","Y-Axis","XY-Axes") 33911#@gui : Size = _choice("Shrink", "Expand", "Repeat [Memory Consuming!]") 33912#@gui : sep = separator() 33913#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 33914fx_array_fade : 33915 if $7&1 mirror x fi if $7>1 mirror y fi 33916 array_fade $1,$2,$5,$6,$8 33917 shift -$3%,-$4%,0,0,2 33918 33919fx_array_fade_preview : 33920 fx_array_fade $1,$2,$3,$4,$5,$6,$7,0 33921 33922#@gui Array [Mirrored] : fx_array_mirror, fx_array_mirror_preview(1) 33923#@gui : Iterations = int(1,1,10) 33924#@gui : X-Offset (%) = float(0,0,100) 33925#@gui : Y-Offset (%) = float(0,0,100) 33926#@gui : Array Mode = choice(2,"X-Axis","Y-Axis","XY-Axes","2XY-Axes") 33927#@gui : Initialization = choice("Original","Mirror X","Mirror Y","Rotate 90 deg.","Rotate 180 deg.","Rotate 270 deg.") 33928#@gui : Expand Size = _bool(false) 33929#@gui : Crop (%) = int(0,0,100) 33930#@gui : sep = separator() 33931#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 33932fx_array_mirror : skip ${7=0} 33933 if $5==1 mirror x 33934 elif $5==2 mirror y 33935 elif $5==3 rotate 90 33936 elif $5==4 rotate 180 33937 elif $5==5 rotate 270 33938 fi 33939 if $7 33940 if $4==0 columns 0,{100-$7}% 33941 elif $4==1 rows 0,{100-$7}% 33942 elif $4==2 z 0,0,{100-$7}%,{100-$7}% 33943 elif $4==3 z {$7/2}%,{$7/2}%,{100-$7/2}%,{100-$7/2}% 33944 fi 33945 fi 33946 shift -$2%,-$3%,0,0,2 33947 array_mirror $1,$4,$6 33948 33949fx_array_mirror_preview : 33950 fx_array_mirror $1,$2,$3,$4,$5,0,$7 33951 33952#@gui Array [Random] : array_random, array_random(1) 33953#@gui : Source X-Tiles = int(5,1,20) 33954#@gui : Source Y-Tiles = int(5,1,20) 33955#@gui : Destination X-Tiles = int(7,1,20) 33956#@gui : Destination Y-Tiles = int(7,1,20) 33957#@gui : sep = separator() 33958#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 33959 33960#@gui Array [Random Colors] : fx_array_color, fx_array_color(1) 33961#@gui : X-Tiles = int(5,1,20) 33962#@gui : Y-Tiles = int(5,1,20) 33963#@gui : Opacity = float(0.5,0,1) 33964#@gui : sep = separator() 33965#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 33966fx_array_color : 33967 repeat $! l. 33968 $1,$2,1,3 rand. 0,255 to_colormode. {-2,s} ri. .. *. $3 *.. {1-$3} +[-2,-1] 33969 endl mv. 0 done 33970 33971#@gui Array [Regular] : fx_array, fx_array_preview(1) 33972#@gui : X-Tiles = int(2,1,10) 33973#@gui : Y-Tiles = int(2,1,10) 33974#@gui : X-Offset (%) = float(0,0,100) 33975#@gui : Y-Offset (%) = float(0,0,100) 33976#@gui : Mirror = choice("None","X-Axis","Y-Axis","XY-Axes") 33977#@gui : Size = _choice("Shrink", "Expand", "Repeat [Memory Consuming!]") 33978#@gui : sep = separator() 33979#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 33980fx_array : 33981 shift -$3%,-$4%,0,0,2 33982 if $5&1 mirror x fi if $5>1 mirror y fi 33983 array $1,$2,$6 33984 33985fx_array_preview : 33986 fx_array $1,$2,$3,$4,$5,0 33987 33988#@gui Ascii Art : fx_asciiart, fx_asciiart_preview(0)+ 33989#@gui : Charset = choice(5,"Custom","Binary Digits","Digits","Lowercase Letters","Uppercase Letters", 33990#@gui : "Ascii","Card Suits","Math Symbols") 33991#@gui : Custom Dictionary = text{" .oO0"} 33992#@gui : Analysis Scale = int(16,8,103) 33993#@gui : Analysis Smoothness = float(15,0,100) 33994#@gui : Synthesis Scale = int(16,8,103) 33995#@gui : Result Type = choice(2,"White on Black","Black on White","Colored on Black","Colored on Transparent") 33996#@gui : sep = separator() 33997#@gui : Gamma = float(0,-3,3) 33998#@gui : Smoothness = float(0.2,0,5) 33999#@gui : Colors = choice("Full Colors","2 Colors","3 Colors","4 Colors","8 Colors","12 Colors","16 Colors", 34000#@gui : "Grayscale","2 Grays","3 Grays","4 Grays","8 Grays","12 Grays","16 Grays") 34001#@gui : sep = separator() 34002#@gui : Output Ascii File = _bool(0) 34003#@gui : Output Folder = _folder() 34004#@gui : Output Filename = _text("gmic_asciiart.txt") 34005#@gui : sep = separator() 34006#@gui : url = link("Click here for a detailed description of this filter.",\ 34007# "http://www.gimpchat.com/viewtopic.php?f=28&t=10047") 34008#@gui : sep = separator() 34009#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/27/03</i>.</small>") 34010fx_asciiart : skip "${10=},${11=},${12=}" 34011 repeat $! l[$>] to_rgb 34012 apply_gamma {10^$7} b $8% n 0,255 34013 if $1==0 dict="$2" 34014 elif $1==1 34015 dict=" 01" 34016 elif $1==2 34017 dict=" 0123456789" 34018 elif $1==3 34019 dict=" abcdefghijklmnopqrstuvwxyz" 34020 elif $1==4 34021 dict=" ABCDEFGHIJKLMNOPQRSTUVWXYZ" 34022 elif $1==5 34023 dict=" !\042#$%&\047()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\133\\\135^_\140abcdefghijklmnopqrstu"\ 34024 "vwxyz\173|\174~" 34025 elif $1==6 34026 dict=" \16\17\20\21" 34027 elif $1==7 34028 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" 34029 fi 34030 if $6==1 negate fi 34031 if $-3 +img2ascii $dict,$3,$4%,$5,"$-2"/"$-1" 34032 else +img2ascii $dict,$3,$4%,$5 34033 fi 34034 wh=${} 34035 if $6==0 k. n 0,255 34036 elif $6==1 k. negate n 0,255 34037 elif $6==2" || "$6==3 34038 r[0] $wh,1,100%,1 34039 if $9>=7 luminance[0] fi 34040 if $9%7 quantize[0] {arg($9%7,2,3,4,8,12,16)-1},1,0 fi 34041 r[0] [1],[1],1,100% *[0] [1] 34042 if $6==2 rm[1] 34043 else *[1] 255 a c 34044 fi 34045 fi 34046 endl done 34047 34048fx_asciiart_preview : 34049 repeat $! l[$>] 34050 w={w} h={h} 34051 fx_asciiart $1,"$2",${3-9},0,foo,foo 34052 r $w,$h,1,100%,0,0,0.5,0.5 34053 endl done 34054 34055#@gui Chessboard : fx_chessboard, fx_chessboard_preview(0) 34056#@gui : First Size = int(64,1,512) 34057#@gui : Second Size = int(64,1,512) 34058#@gui : First Offset = int(0,0,512) 34059#@gui : Second Offset = int(0,0,512) 34060#@gui : Angle = float(0,0,180) 34061#@gui : Opacity = float(0.5,0,1) 34062#@gui : First Color = color(0,0,0,255) 34063#@gui : Second Color = color(255,255,255,255) 34064#@gui : sep = separator() 34065#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 34066#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 34067#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 34068#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 34069#@gui : sep = separator() 34070#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 34071fx_chessboard : 34072 to_rgba chessboard ${1-14} 34073 34074fx_chessboard_preview : 34075 gui_split_preview "fx_chessboard $*",${-3--1} 34076 34077#@gui Dices : fx_dices, fx_dices(0) 34078#@gui : Resolution = float(2,1,10) 34079#@gui : Size = int(24,8,64) 34080#@gui : Color Model = choice(1,"Black Dices","White Dices","Dices with Colored Numbers","Dices with Colored Sides") 34081#@gui : sep = separator() 34082#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/06</i>.</small>") 34083fx_dices : 34084 34085 # Create dice patterns. 34086 repeat 6 {2*$2},{2*$2} _dice$> done 34087 if $3%2 negate[-6--1] fi 34088 frame_round[-6--1] 10,10,0,0,128,128,128,0 34089 r2dy[-6--1] $2 a[-6--1] x 34090 34091 repeat $!-1 l[$>,-1] 34092 34093 # Prepare input images. 34094 +luminance[0] rv[1,2] r[0,1] {100*$1/$2}%,{100*$1/$2}%,1,100%,2 quantize[1] 6,0 34095 34096 # Convert input image to dices pattern. 34097 *.. $2 channels.. 0,1 r.. {$2*100}%,{$2*100}% 34098 $2,$2,1,2,'if(c,y,x)' r. ...,...,1,2,0,2 +[-3,-1] +warp. ..,0,0 rm... 34099 34100 if $3<2 rm[0] mv. 0 34101 else r[0] [2],[2],1,100% rv[0,-1] blend[0,-1] multiply 34102 fi 34103 34104 endl done rm. 34105 34106_dice0 : ellipse. 50%,50%,5.2%,5.2%,0,1,255 34107_dice1 : ellipse. 25%,25%,5.2%,5.2%,0,1,255 ellipse. 75%,75%,5.2%,5.2%,0,1,255 34108_dice2 : _dice1 _dice0 34109_dice3 : _dice1 ellipse. 25%,75%,5.2%,5.2%,0,1,255 ellipse. 75%,25%,5.2%,5.2%,0,1,255 34110_dice4 : _dice3 _dice0 34111_dice5 : _dice3 ellipse. 25%,50%,5.2%,5.2%,0,1,255 ellipse. 75%,50%,5.2%,5.2%,0,1,255 34112 34113#@gui Drawn Montage : fx_drawn_montage, fx_drawn_montage_preview(1) : * 34114#@gui : Layer = choice("1st","2nd","3rd","4th","5th","6th","7th","8th","9th","10th","11th","12th", 34115#@gui : "13th","14th","15th","16th") 34116#@gui : Associated Color = color(0,0,0) 34117#@gui : Zoom = float(-10,0,10) 34118#@gui : X-Centering (%) = float(50,0,100) 34119#@gui : Y-Centering (%) = float(50,0,100) 34120#@gui : Angle = choice("0 deg.","90 deg.","180 deg.","270 deg.") 34121#@gui : Pargs = value(-1) 34122#@gui : Args0 = value(0:0:0:0:50:50:0) 34123#@gui : Args1 = value(0:0:0:0:50:50:0) 34124#@gui : Args2 = value(0:0:0:0:50:50:0) 34125#@gui : Args3 = value(0:0:0:0:50:50:0) 34126#@gui : Args4 = value(0:0:0:0:50:50:0) 34127#@gui : Args5 = value(0:0:0:0:50:50:0) 34128#@gui : Args6 = value(0:0:0:0:50:50:0) 34129#@gui : Args7 = value(0:0:0:0:50:50:0) 34130#@gui : Args8 = value(0:0:0:0:50:50:0) 34131#@gui : Args9 = value(0:0:0:0:50:50:0) 34132#@gui : Args10 = value(0:0:0:0:50:50:0) 34133#@gui : Args11 = value(0:0:0:0:50:50:0) 34134#@gui : Args12 = value(0:0:0:0:50:50:0) 34135#@gui : Args13 = value(0:0:0:0:50:50:0) 34136#@gui : Args14 = value(0:0:0:0:50:50:0) 34137#@gui : Args15 = value(0:0:0:0:50:50:0) 34138#@gui : sep = separator() 34139#@gui : note = note{"<small><b>Note:</b> 34140#@gui : This filter requires a top layer containing the desired montage layout defined as free-form shapes 34141#@gui : of different colors. You can then assign each layer to a layout color to create the montage. 34142#@gui : </small>"} 34143#@gui : sep = separator() 34144#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/29</i>.</small>") 34145_fx_drawn_montage : 34146 nb_layers={min(16,$!-1)} 34147 34148 if !$nb_layers 34149 error="A top layout layer is missing for this filter to make it work properly!" 34150 if $-1 gui_warning_preview $error return 34151 else error $error 34152 fi 34153 fi 34154 34155 # Manage parameter changes. 34156 pargs,args0,args1,args2,args3,args4,args5,args6,args7,args8,args9,args10,args11,args12,args13,args14,args15=${9-25} 34157 if $1!=$pargs # Get back saved parameters for selected layer 34158 ('${args$1}') replace. {':'},{','} arg_R,arg_G,arg_B,arg_zoom,arg_xcenter,arg_ycenter,arg_angle=${u\ {t}} rm. 34159 else # Set new parameters for selected #L 34160 arg_R,arg_G,arg_B,arg_zoom,arg_xcenter,arg_ycenter,arg_angle=${2-8} 34161 fi 34162 args$1=$arg_R:$arg_G:$arg_B:$arg_zoom:$arg_xcenter:$arg_ycenter:$arg_angle 34163 status=\{$1\}\{$arg_R,$arg_G,$arg_B\}\{$arg_zoom\}\{$arg_xcenter\}\{$arg_ycenter\}\{$arg_angle\}\{$1\}\{$args0\}\ 34164 \{$args1\}\{$args2\}\{$args3\}\{$args4\}\{$args5\}\{$args6\}\{$args7\}\{$args8\}\{$args9\}\{$args10\}\ 34165 \{$args11\}\{$args12\}\{$args13\}\{$args14\}\{$args15\} 34166 34167 # Read parameters for all layers. 34168 c= repeat $nb_layers 34169 ('${args$>}') replace. {':'},{','} R$>,G$>,B$>,zoom$>,xcenter$>,ycenter$>,angle$>=${u\ {t}} 34170 cols=$cols$c${R$>},${G$>},${B$>} c=, rm. rotate[{1+$>}] {90*${angle$>}} 34171 done 34172 34173 # Get bounding boxes for each associated color in layout layer, as well as labeled layout layer. 34174 to_rgb[0] to_rgba[^0] $nb_layers,1,1,4,[inf,inf,-inf,-inf] [0],[0] 34175 f[0] " 34176 begin(colors = [ "$cols" ]); 34177 repeat ("$nb_layers",l, 34178 I==colors[3*l,3]?( 34179 if (x<i(#-2,l,0,0,0), i(#-2,l,0,0,0) = x); 34180 if (y<i(#-2,l,0,0,1), i(#-2,l,0,0,1) = y); 34181 if (x>i(#-2,l,0,0,2), i(#-2,l,0,0,2) = x); 34182 if (y>i(#-2,l,0,0,3), i(#-2,l,0,0,3) = y); 34183 i(#-1,x,y) = l + 1; 34184 ); 34185 ); I" 34186 34187 thumbnail=0 boundaries=0 34188 if $-1 34189 34190 # Render thumbnail of current layer, for preview. 34191 l={1+$1} 34192 if $l<=$nb_layers 34193 if {$l,w>h} +r2dx[$l] {(0$_preview_width?0$_preview_width:400)/6} 34194 else +r2dy[$l] {(0$_preview_height?0$_preview_height:400)/6} fi 34195 frame. 1,1,0,0,0,255 drgba. to. "#"$l,0,-2,13 to_rgba. 34196 mv. -3 34197 thumbnail=1 34198 fi 34199 34200 # Render region boundaries of layout layer, for preview. 34201 +f. "const boundaries = 1; ref(crop(x - 2,y - 2,5,5),V); if (min(V)==max(V),0,i)" 34202 (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. 34203 34204 repeat $nb_layers 34205 xmin,ymin,xmax,ymax={-3,I[$>]} 34206 if !isinf($xmin)" && "!isinf($ymin)" && "!isinf($xmax)" && "!isinf($ymax) 34207 xc$>,yc$>={0,0.5*([$xmin,$ymin]+[$xmax,$ymax]-6)*100/[w,h]} 34208 else xc$>,yc$>=-1024 34209 fi 34210 done 34211 34212 mv. -3 34213 boundaries=1 34214 fi 34215 34216 # Render montage. 34217 if iM>0 34218 34219 # Resize layers to fit proposed layout. 34220 repeat $nb_layers 34221 l={$>+1} xmin,ymin,xmax,ymax={-2,I[$>]} 34222 if !isinf($xmin)" && "!isinf($ymin)" && "!isinf($xmax)" && "!isinf($ymax) 34223 dx={$xmax-$xmin+1} 34224 dy={$ymax-$ymin+1} 34225 nw,nh={$l,round(min(w/$dx,h/$dy)*[$dx,$dy]/(1+3*(${zoom$>}/10)^2))} 34226 r[$l] $nw,$nh,1,100%,0,0,{(100-${xcenter$>})%},{(100-${ycenter$>})%} # Centered crop 34227 r[$l] $dx,$dy,1,100%,6 # Resize 34228 else r[$l] 1,1 # Save a bit of memory! 34229 fi 34230 done 34231 34232 # Draw image pixels over layout layer. 34233 to_rgba[0] 34234 f[0] " 34235 l = i#-1; 34236 l1 = l - 1; 34237 l<=0?I:( 34238 xmin = i(#-2,l1,0,0,0); 34239 ymin = i(#-2,l1,0,0,1); 34240 rx = x - xmin; 34241 ry = y - ymin; 34242 crop(#l,rx,ry,0,0,1,1,1,4); 34243 )" 34244 fi 34245 rm[-2,-1] 34246 34247 # Manage preview. 34248 if $boundaries blend[0,-1] alpha fi # Add shape boundaries. 34249 if $thumbnail # Add current layer thumbnail over preview 34250 drgba[0] rr2d[0] ${-gui_preview_wh} 34251 j[0] .,3,3,0,0,0.75 34252 rm. 34253 fi 34254 if $-1 repeat $nb_layers 34255 to "#"{1+$>},${xc$>}%,${yc$>}%,13,1,0.75 34256 done fi 34257 34258 34259 k[0] c 0,255 34260 u $status 34261 34262fx_drawn_montage : 34263 _fx_drawn_montage $*,0 34264 34265fx_drawn_montage_preview : 34266 _fx_drawn_montage $*,1 34267 34268#@gui Extract Objects : fx_extract_objects, fx_extract_objects_preview(1) 34269#@gui : Background Point (%) = point(0,0) 34270#@gui : sep = separator() 34271#@gui : Color Tolerance = int(20,0,256) 34272#@gui : Opacity Threshold (%) = int(50,0,100) 34273#@gui : Minimal Area = float(0.3,0,5) 34274#@gui : Connectivity = choice("Low","High") 34275#@gui : Output As = _choice(0,"Crop","Segmentation") 34276#@gui : sep = separator() 34277#@gui : Preview Guides = bool(1) 34278#@gui : sep = separator() 34279#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/23/02</i>.</small>") 34280#@gui : url = link("Filter explained here","http://gimpchat.com/viewtopic.php?f=28&t=7905") 34281fx_extract_objects : 34282 if $5 min_area=$5% else min_area=6 fi 34283 repeat $! l[$<] to_rgba 34284 nm=${-gui_layer_name} 34285 w={w} h={h} 34286 x={$1%*(w-1)} 34287 y={$2%*(h-1)} 34288 color={I($x,$y)} 34289 if $7==0 # Output: Crop. 34290 +replace_color $3,0,$color,0,0,0,0 autocrop_components. $4%,$min_area,$6,2 34291 repeat w 34292 +z[0] {1,i($>,0)},{1,i($>,1)},{1,i($>,3)},{1,i($>,4)} 34293 nm. pos({1,i($>,0)},{1,i($>,1)}),name($nm" "[$>]) 34294 done rm[0,1] 34295 elif $7==1 # Output: Segmentation. 34296 replace_color $3,0,$color,0,0,0,0 34297 +autocrop_components[0] $4%,$min_area,$6,2 34298 autocrop_components[0] $4%,$min_area,$6,1 34299 repeat w nm[$>] pos({i($>,0)},{i($>,1)}),name($nm" "[$>]) done rm. 34300 fi 34301 $w,$h,1,4 fc. $color nm. name($nm" [background]") 34302 endl done 34303 34304fx_extract_objects_preview : 34305 x0,y0=${1,2} 34306 if $5 min_area=$5% else min_area=5 fi 34307 repeat $! l[$>] to_rgba 34308 x={$x0%*(w-1)} 34309 y={$y0%*(h-1)} 34310 color={I($x,$y)} 34311 +replace_color $3,0,$color,0,0,0,0 34312 autocrop_components. $4%,$min_area,$6,2 34313 repeat w 34314 xycoords={1,i($>,0)},{1,i($>,1)},{1,i($>,3)},{1,i($>,4)} 34315 rectangle[0] $xycoords,0.3,0,0,255,255 34316 rectangle[0] $xycoords,1,0xFFFFFFFF,0,0,0,255 34317 done 34318 drgba[0] 34319 to[0] {w}" objects",2,2,13,2,0.3,255,255,255,255 34320 k[0] 34321 if $8 34322 line 0,$y0%,100%,$y0%,0.5,0xF0F0F0F0,255 line 0,$y0%,100%,$y0%,0.5,0x0F0F0F0F,0 34323 line $x0%,0,$x0%,100%,0.5,0xF0F0F0F0,255 line $x0%,0,$x0%,100%,0.5,0x0F0F0F0F,0 34324 fi 34325 circle $x,$y,3,1,0,255,0 circle $x,$y,3,1,0xFFFFFFFF,0 34326 endl done 34327 34328#@gui Grid [Cartesian] : fx_imagegrid, fx_imagegrid(0) 34329#@gui : X-Size = int(10,2,512) 34330#@gui : Y-Size = int(10,2,512) 34331#@gui : sep = separator() 34332#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 34333fx_imagegrid : 34334 imagegrid $1,$2 34335 34336#@gui Grid [Hexagonal] : fx_imagegrid_hexagonal, fx_imagegrid_hexagonal(1) 34337#@gui : Resolution = int(32,1,128) 34338#@gui : Outline = float(0.1,0,0.5) 34339#@gui : Anti-Aliasing = bool(1) 34340#@gui : sep = separator() 34341#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/12/01</i>.</small>") 34342fx_imagegrid_hexagonal : 34343 repeat $! l[$>] 34344 if $3 r 200%,200%,1,100% fi 34345 imagegrid_hexagonal $1,$2 34346 if $3 r 50%,50%,1,100%,2 fi 34347 endl done 34348 34349#@gui Grid [Triangular] : fx_imagegrid_triangular, fx_imagegrid_triangular(0) 34350#@gui : Pattern Width = int(10,8,128) 34351#@gui : Pattern Height = int(18,8,128) 34352#@gui : Pattern Type = choice(0,"Horizontal","Vertical","Crossed","Cube","Decreasing","Increasing") 34353#@gui : Outline Color = color(255,255,255,128) 34354#@gui : sep = separator() 34355#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/08/07</i>.</small>") 34356fx_imagegrid_triangular : 34357 repeat $! l[$>] split_opacity l[0] to_rgb 34358 imagegrid_triangular ${1-3},{$7/255},${4-6} 34359 endl a c endl done 34360 34361#@gui Make Seamless [Diffusion] : fx_make_seamless, fx_make_seamless_preview(1) 34362#@gui : Equalize Light = float(0,0,100) 34363#@gui : sep = separator() 34364#@gui : Preview Original = bool(0) 34365#@gui : Tiled Preview = choice(3,"None","2x1","1x2","2x2","3x3","4x4") 34366#@gui : sep = separator() 34367#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 34368#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 34369#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 34370#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 34371#@gui : sep = separator() 34372#@gui : note = note{"<small><b>Note:</b> This filter helps in converting your input pattern as a <b>seamless</b> 34373#@gui : (a.k.a periodic) texture.</small>"} 34374#@gui : sep = separator() 34375#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/24/02</i>.</small>") 34376fx_make_seamless : 34377 repeat $! l[$>] 34378 if $1 +b {20.5-$1/50}% -[0] [1] fc. ${average_colors.} + fi 34379 endl done 34380 periodize_poisson c 0,255 34381 34382fx_make_seamless_preview : 34383 u={arg($3,2,1,2,3,4)} v={arg($3,1,2,2,3,4)} 34384 gui_split_preview "if !$2 fx_make_seamless $* fi if $3 array "$u","$v" fi",${-3--1} 34385 34386#@gui Make Seamless [Patch-Based] : fx_frame_seamless, fx_frame_seamless_preview(0) 34387#@gui : Frame Size = int(32,0,256) 34388#@gui : Patch Size = int(9,3,64) 34389#@gui : Blend Size = int(0,0,64) 34390#@gui : Frame Type = choice(1,"Inner","Outer") 34391#@gui : Equalize Light = float(100,0,100) 34392#@gui : sep = separator() 34393#@gui : Preview Original = bool(0) 34394#@gui : Tiled Preview = choice(3,"None","2x1","1x2","2x2","3x3","4x4") 34395#@gui : sep = separator() 34396#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 34397#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 34398#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 34399#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 34400#@gui : sep = separator() 34401#@gui : note = note{"<small><b>Note:</b> This filter helps in converting your input pattern as a <b>seamless</b> 34402#@gui : (a.k.a periodic) texture.</small>"} 34403#@gui : sep = separator() 34404#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/15/12</i>.</small>") 34405fx_frame_seamless : 34406 repeat $! l[$>] 34407 if $5 +b {20.5-$5/50}% -[0] [1] fc. ${average_colors.} + fi 34408 endl done 34409 frame_seamless ${1-4} c 0,255 34410 34411fx_frame_seamless_preview : 34412 u={arg($7,2,1,2,3,4)} v={arg($7,1,2,2,3,4)} 34413 gui_split_preview "if !$6 fx_frame_seamless $* fi if $7 array "$u","$v" fi",${-3--1} 34414 34415#@gui Ministeck : fx_ministeck, fx_ministeck_preview(1) 34416#@gui : Number of Colors = int(8,2,24) 34417#@gui : Resolution (px) = int(64,16,256) 34418#@gui : Piece Size (px) = int(8,1,64) 34419#@gui : Piece Complexity = int(2,1,10) 34420#@gui : Relief Amplitude = float(100,0,256) 34421#@gui : Relief Size = float(0.3,0,1) 34422#@gui : Add 1px Outline = bool(0) 34423#@gui : sep = separator() 34424#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/14/01</i>.</small>") 34425fx_ministeck : 34426 repeat $! l[$>] 34427 if w>h r2dx {min($2,w)} else r2dy {min($2,h)} fi 34428 split_opacity l[0] 34429 +colormap. $1 index.. . 34430 [0],[0],1,1 rand[2] 0,1 dilate[2] $4 +[0,2] 34431 r[0] $3""00%,$3""00% 34432 +g[0] xy,1 !=[-2,-1] 0 +f[0] 'i(x+1,y+1)-i(x,y)' !=[-3--1] 0 -|[-3--1] 34433 z[0,-1] 0,0,{w-2},{h-2} 34434 if $7 . fi 34435 +shift. 1,1 *.. -1 +[-2,-1] b. {$6*$3/5} n. -$5,$5 34436 map[0] [1] rm[1] +[0,-1] 34437 if $7 ==[1] 0 * fi 34438 endl r. [0],[0],1,100% a c 34439 endl done 34440 c 0,255 34441 34442fx_ministeck_preview : 34443 repeat $! l[$>] 34444 w={w} h={h} 34445 fx_ministeck $* 34446 r $w,$h,1,100%,0,0,0.5,0.5 34447 endl done 34448 34449#@gui Montage : fx_montage, fx_montage_preview(1) : * 34450#@gui : Montage Type = choice("Auto","Custom Layout","Horizontal","Vertical","Horizontal Array","Vertical Array") 34451#@gui : Custom Layout = text{"V(H(0,1),H(2,V(3,4)))"} 34452#@gui : Merging Mode = choice(1,"Aligned","Scaled") 34453#@gui : Centering / Scale = float(0.5,0,1) 34454#@gui : Padding (px) = int(0,0,128) 34455#@gui : sep = separator() 34456#@gui : Frame (px) = int(0,0,128) 34457#@gui : Frame Color = color(0,0,0,255) 34458#@gui : sep = separator() 34459#@gui : Angle = float(0,0,360) 34460#@gui : Angle Variations = float(0,0,180) 34461#@gui : sep = separator() 34462#@gui : Cycle Layers = int(0,-255,255) 34463#@gui : Revert Layer Order = bool() 34464#@gui : Output As = _choice("Single Layer","Multiple Layers") 34465#@gui : sep = separator() 34466#@gui : note = note{"<small><b>Instructions:</b>\n 34467#@gui : - Don't forget to set the <i>Input layers...</i> option on the left if you have multiple input layers 34468#@gui : for your montage.\n 34469#@gui : - The <i>Custom layout</i> parameter is only active when <i>Montage type</i> is set to <i>Custom layout</i>. 34470#@gui : This is basically a string containing expressions such as:\n 34471#@gui : \n . <i>H(a,b)</i> or <i>V(a,b)</i> stand respectively for an horizontal and vertical merge of two 34472#@gui : blocks <i>a</i> and <i>b</i>. 34473#@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 34474#@gui : <i>RRR(a)</i> for resp. 180-deg and 270-deg. rotations. 34475#@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 34476#@gui : version of <i>a</i>.\n\n 34477#@gui : - A block <i>a</i> can be a layer index or a nested montage expression itself.\n 34478#@gui : - Layer indices start from <i>0 (top layer)</i> and are treated periodically. 34479#@gui : </small>"} 34480#@gui : url = link("Click here for a tutorial","https://patdavid.net/2014/05/gmic-montage.html") 34481#@gui : url = link("+ video tutorial","http://www.youtube.com/watch?v=iM42vx22gwg") 34482#@gui : sep = separator() 34483#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/22/12</i>.</small>") 34484fx_montage : skip "${2=A}" 34485 if !$! return fi 34486 code0=X code1="$2" code2=H code3=V code4=A code5=B 34487 if $3==1" && "$4<0.5 r {max(10,$4*200)}%,{max(10,$4*200)}%,1,100%,2 fi 34488 to_rgba if $14 rv fi if $13%$! mv[{$13%$!}--1] 0 fi 34489 if $11" || "$12 repeat $! rotate[$>] {$11+u(-$12,$12)},1,0 done fi 34490 montage ${code$1},{if($3==0,$4,2+max(0,$4-0.5))},$15,\ 34491 "if $""7%2 mirror x fi if $""8%2 mirror y fi "\ 34492 "rotate {90*$""6} "\ 34493 "if $5||$6 "\ 34494 "r {max(1,$""4-2*($5+$6))},{max(1,$""5-2*($5+$6))},1,100%,2 "\ 34495 "frame $6,$6,${7-10} "\ 34496 "r {w+2*$5},{h+2*$5},1,100%,0,0,0.5,0.5 "\ 34497 "else r $""4,$""5,1,100%,2 fi " 34498 if $15 gui_autocrop_layers fi 34499 gui_set_layer_name "[Montage]" 34500 34501fx_montage_preview : skip "${2=A}" 34502 if !$! return fi 34503 w={w} h={h} 34504 if $3==1" && "$4<0.5 r {max(10,$4*200)}%,{max(10,$4*200)}%,1,100%,2 fi 34505 drgba 34506 code0=X code1="$2" code2=H code3=V code4=A code5=B 34507 to_rgba if $14 rv fi if $13%$! mv[{$13%$!}--1] 0 fi 34508 if $11" || "$12 repeat $! rotate[$>] {$11+u(-$12,$12)},1,0 done fi 34509 montage ${code$1},{if($3==0,$4,2+max(0,$4-0.5))},0,\ 34510 "if $""7%2 mirror x fi if $""8%2 mirror y fi 34511 rotate {90*$""6} 34512 if $5||$6 34513 r {max(1,$""4-2*($5+$6))},{max(1,$""5-2*($5+$6))},1,100%,2 fs={min(53,max(w,h)/3)} 34514 frame $6,$6,${7-10} 34515 r {w+2*$5},{h+2*$5},1,100%,0,0,0.5,0.5 34516 0 t. \\\#$""1,0,0,$fs,1,255 expand_xy. 3,0 [-1]x3 a[-4--2] c 34517 dilate. {3+2*$fs/20} a.. .,c j[0] [1],{5+$5+$6},{$5+$6},0,0,1,[2],255 k[0] 34518 else 34519 r $""4,$""5,1,100%,2 fs={min(53,max(w,h)/3)} 34520 0 t. \\\#$""1,0,0,$fs,1,255 expand_xy. 3,0 [-1]x3 a[-4--2] c 34521 dilate. {3+2*$fs/20} a.. .,c j[0] [1],5,0,0,0,1,[2],255 k[0] 34522 fi " 34523 nw={w} nh={h} 34524 resize_ratio2d $w,{$h-16},2,2 34525 drgba 34526 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 34527 a y 34528 34529#@gui Puzzle : fx_puzzle, fx_puzzle_preview(1) 34530#@gui : note = note("<small><b>Pattern parameters:</b></small>") 34531#@gui : X-Tiles = int(5,2,32) 34532#@gui : Y-Tiles = int(5,2,32) 34533#@gui : Curvature = float(0.5,0,1.5) 34534#@gui : Connectors Centering = float(0,0,1) 34535#@gui : Connectors Variability = float(0,0,2) 34536#@gui : sep = separator() 34537#@gui : note = note("<small><b>Blending parameters:</b></small>") 34538#@gui : Relief Smoothness = float(0.3,0,3) 34539#@gui : Relief Contrast = float(100,0,255) 34540#@gui : Outline Smoothness = float(0.2,0,3) 34541#@gui : Outline Contrast = float(255,0,255) 34542#@gui : sep = separator() 34543#@gui : note = note("<small><b>Recomposition parameters:</b></small>") 34544#@gui : Scale = float(100,0,150) 34545#@gui : Scale Variations = float(0,0,100) 34546#@gui : Angle = float(0,-180,180) 34547#@gui : Angle Variations = float(0,0,180) 34548#@gui : Shuffle Pieces = bool(0) 34549#@gui : Additional Outline = bool(0) 34550#@gui : Output Each Piece on a Different Layer = _bool(0) 34551#@gui : sep = separator() 34552#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/06/01</i>.</small>") 34553fx_puzzle : 34554 repeat $! l[$<] 34555 w={w} h={h} to_rgb 34556 puzzle $w,$h,$1,$2,$3,$4,$5 34557 +b. $6%,0 g. xy +[-2,-1] n. -$7,$7 +[0,-1] # Relief. 34558 +b. $8%,0 n. 0,1 *. -1 +. 1 n. {(255-$9)/255},1 *[0,-1] c 0,255 # Outline. 34559 34560 if $10!=100||$11||$12||$13||$14||$15||$16 34561 34562 # Decompose puzzle into set of pieces. 34563 +-. 1 label_fg. 0 34564 +area_fg. 0,0 <. 50% -|... . ==. 0 *[-2,-1] 34565 distance.. 0 *.. -1 watershed. .. rm.. label. 0,0 34566 34567 repeat iM+1 34568 +==[1] $> 34569 coords=${autocrop_coords.\ 0} 34570 +z[0] $coords z.. $coords rv[-2,-1] *.. . *. 255 a[-2,-1] c 34571 x$>={arg(1,$coords)+round(w/2)} y$>={arg(2,$coords)+round(h/2)} 34572 done 34573 rm[0,1] 34574 34575 # Recompose puzzle. 34576 if $14 sort_list +,u fi 34577 34578 if $16 # One piece by layer. 34579 repeat $! l[$<] 34580 r2dy {max(0.1,$10+$11*u(-1,1))}% rotate {$12+$13*u(-1,1)} 34581 if $15 expand_xy 1,0 fi 34582 cx={round(w/2)} cy={round(h/2)} 34583 sh 100% if $15 dilate. 3 fi 34584 i[0] $w,$h,1,4 34585 j[0] ..,{${x$<}-$cx},{${y$<}-$cy},0,0,1,.,255 rm[-2,-1] 34586 endl done 34587 34588 else # All pieces on the same layer. 34589 i[0] $w,$h,1,{s} 34590 repeat $!-1 34591 r2dy. {max(0.1,$10+$11*u(-1,1))}% rotate. {$12+$13*u(-1,1)} 34592 if $15 expand_xy. 1,0 fi 34593 cx={round(w/2)} cy={round(h/2)} 34594 sh. 100% if $15 dilate. 3 fi 34595 j[0] ..,{${x$<}-$cx},{${y$<}-$cy},0,0,1,.,255 rm[-2,-1] 34596 done 34597 fi 34598 34599 else rm. 34600 fi 34601 endl done 34602 34603fx_puzzle_preview : 34604 fx_puzzle ${1-15},0 34605 34606#@gui Taquin : fx_taquin, fx_taquin(1) 34607#@gui : X-Tiles = int(7,1,20) 34608#@gui : Y-Tiles = int(7,1,20) 34609#@gui : Remove Tile = choice("None","First","Last","Random") 34610#@gui : sep = separator() 34611#@gui : Relief = float(50,0,255) 34612#@gui : Border Thickness (%) = float(5,0,100) 34613#@gui : Border Outline = int(0,0,16) 34614#@gui : Ouline Color = color(0,0,0,255) 34615#@gui : sep = separator() 34616#@gui : Random Seed = int(0,0,65535) 34617#@gui : sep = separator() 34618#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/13/01</i>.</small>") 34619fx_taquin : 34620 to_a repeat $! l[$>] srand $11 taquin $1,$2,$3,$4,$5%,$6,${7-10} endl done 34621 34622#@gui Tileable Rotation : fx_rotate_tileable, fx_rotate_tileable_preview(1) 34623#@gui : Angle = float(45,0,360) 34624#@gui : Maximum Size Factor = int(8,0,20) 34625#@gui : Array Mode = choice(0,"None","x-axis","y-axis","xy-axes","2xy-axes") 34626#@gui : sep = separator() 34627#@gui : note = note("<small><b>Note:</b> This filter implements the tileable rotation technique described by 34628#@gui : <b>Peter Yu</b>, at:</small>") 34629#@gui : url = link("[Peter Yu] Create rotated tileable patterns", 34630#@gui : "http://www.peteryu.ca/tutorials/gimp/rotate_tileable_patterns") 34631#@gui : sep = separator() 34632#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/26/05</i>.</small>") 34633fx_rotate_tileable : 34634 if $3 array_mirror 1,{$3-1},1 fi 34635 rotate_tileable $1,{if($3==0,$2,$2/2)} 34636 34637fx_rotate_tileable_preview : 34638 l fx_rotate_tileable $* 34639 onfail gui_warning_preview "Invalid image size" endl 34640 34641#@gui Tiled Rotation : fx_rotate_tiles, fx_rotate_tiles(1) 34642#@gui : X-Tiles = int(5,1,80) 34643#@gui : Y-Tiles = int(5,1,80) 34644#@gui : Angle = float(15,0,360) 34645#@gui : X-Shadow = float(3,-20,20) 34646#@gui : Y-Shadow = float(3,-20,20) 34647#@gui : Smoothness = float(1.8,0,5) 34648#@gui : sep = separator() 34649#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 34650fx_rotate_tiles : 34651 to_rgba rotate_tiles $3,$1,$2 drop_shadow $4%,$5%,$6% 34652 34653#@gui Tiled Normalization : fx_normalize_tiles, fx_normalize_tiles(1) 34654#@gui : X-Tiles = int(25,1,80) 34655#@gui : Y-Tiles = int(25,1,80) 34656#@gui : Minimal Value = float(0,0,255) 34657#@gui : Maximal Value = float(255,0,255) 34658#@gui : sep = separator() 34659#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 34660#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 34661#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 34662#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 34663#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 34664#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 34665#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 34666#@gui : sep = separator() 34667#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 34668_fx_normalize_tiles : 34669 repeat $! l. split_tiles $1,$2 n $3,$4 append_tiles $1,$2 endl mv. 0 done 34670 34671fx_normalize_tiles : 34672 ac "_fx_normalize_tiles ${1-4}",$-1 34673 34674#@gui Tiled Random Shifts : fx_shift_tiles, fx_shift_tiles(1) 34675#@gui : X-Tiles = int(10,1,30) 34676#@gui : Y-Tiles = int(10,1,30) 34677#@gui : Amplitude = float(10,0,100) 34678#@gui : Opacity = float(1,0,1) 34679#@gui : sep = separator() 34680#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 34681fx_shift_tiles : 34682 to_rgba shift_tiles $1,$2,$3 34683 if $4<1 repeat $! s. c *. $4 a[-4--1] c mv. 0 done fi 34684 34685#@gui Tiled Parameterization : fx_parameterize_tiles, fx_parameterize_tiles(1) 34686#@gui : X-Tiles = int(10,1,30) 34687#@gui : Y-Tiles = int(10,1,30) 34688#@gui : Fitting Function = choice("Linear","Quadratic") 34689#@gui : sep = separator() 34690#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 34691fx_parameterize_tiles : 34692 if $3 34693 quadratize_tiles $1,$2 34694 else 34695 linearize_tiles $1,$2 34696 fi 34697 c 0,255 34698 34699#@gui Tiled Isolation : fx_isolate_tiles, fx_isolate_tiles(0) 34700#@gui : X-Size = float(10,0,100) 34701#@gui : Y-Size = float(10,0,100) 34702#@gui : X-Border = float(5,0,100) 34703#@gui : Y-Border = float(5,0,100) 34704#@gui : Keep Tiles Square = bool(1) 34705#@gui : Keep Borders Square = bool(1) 34706#@gui : sep = separator() 34707#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/13/04</i>.</small>") 34708fx_isolate_tiles : 34709 repeat $! l[$>] to_rgba 34710 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 34711 if $6 bx={max($3,$4)} by=$bx else bx=$3 by=$4 fi 34712 s x,-$sx 34713 repeat $! l[$>] s y,-$sy r 100%,{100+$by}%,1,100%,0,0,0.5,0.5 a y endl done 34714 r {100+$bx}%,100%,1,100%,0,0,0.5,0.5 a x 34715 endl done 34716 34717 34718#@gui ____<b>Artistic</b> 34719#------------------------- 34720 34721#@gui Bokeh : fx_bokeh, fx_bokeh_preview(1) 34722#@gui : Number of Scales = int(3,1,10) 34723#@gui : Shape = choice(8,"Triangle","Square","Diamond","Pentagon","Hexagon","Octogon","Decagon","Star","Circular") 34724#@gui : Random Seed = int(0,0,65535) 34725#@gui : sep = separator() 34726#@gui : note = note{"<small><b>Starting parameters:</b></small>"} 34727#@gui : Density = int(30,1,256) 34728#@gui : Radius (%) = float(8,0,50) 34729#@gui : Outline (%) = float(4,0,100) 34730#@gui : Inner Shade = float(0.3,0,1) 34731#@gui : Smoothness = float(0.2,0,8) 34732#@gui : Color = color(210,210,80,160) 34733#@gui : Color Dispersion = float(0.7,0,1) 34734#@gui : sep = separator() 34735#@gui : note = note{"<small><b>Ending parameters:</b></small>"} 34736#@gui : Density = int(30,1,256) 34737#@gui : Radius (%) = float(20,0,50) 34738#@gui : Outline (%) = float(20,0,100) 34739#@gui : Inner Shade = float(1,0,1) 34740#@gui : Smoothness = float(2,0,8) 34741#@gui : Color = color(170,130,20,110) 34742#@gui : Color Dispersion = float(0.15,0,1) 34743#@gui : sep = separator() 34744#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 34745#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 34746#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 34747#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 34748#@gui : sep = separator() 34749#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/02/07</i>.</small>") 34750fx_bokeh : 34751 _shape=$2 34752 srand $3 34753 repeat $! l[$<] nm=${-gui_layer_name} pos=${-gui_layer_pos} 34754 100%,100%,1,3 34755 (${4-13};${14-23}) if $1>2 r. 100%,$1,1,1,3 fi 34756 repeat $1 34757 +rows. $> _fx_bokeh... {^} rm. 34758 done 34759 rm. nm. name($nm),opacity(100),mode(screen),pos($pos) 34760 rv 34761 if 0$_output_mode==0 gui_merge_layers 34762 elif 0$_output_mode<2 rm. 34763 fi 34764 endl done 34765 34766_fx_bokeh0 : shape_star $1,3 # Triangle. 34767_fx_bokeh1 : $1,$1,1,1,1 # Square. 34768_fx_bokeh2 : shape_diamond $1 # Diamond. 34769_fx_bokeh3 : shape_polygon $1,5,45 # Pentagon. 34770_fx_bokeh4 : shape_polygon $1,6,45 # Hexagon. 34771_fx_bokeh5 : shape_polygon $1,8,45 # Octogon. 34772_fx_bokeh6 : shape_polygon $1,10,45 # Decagon. 34773_fx_bokeh7 : shape_star $1,5 # Star. 34774_fx_bokeh8 : shape_circle $1 # Circle. 34775 34776fx_bokeh_preview : 34777 gui_split_preview "_output_mode=0 fx_bokeh $*",${-3--1} 34778 34779# [internal] Draw one step of bokeh with specified geometry on last image. 34780# $1=density, $2=size(in %), $3=outline(in %), $4=shade (in [0,1]), $5=smoothness (in %), 34781# $6,$7,$8,$9=RGBA (in [0,255]), $10 = color dispersion (in [0,1]) 34782_fx_bokeh : 34783 radius1={r=max(w,h)*$2%;r+1-(r%2)} 34784 radius2={r=$radius1-($radius1*$3%);r+1-(r%2)} 34785 34786 random3d $1 *3d. {-2,w},{-2,h},0 34787 _fx_bokeh$_shape $radius1 34788 if $radius2>=1 _fx_bokeh$_shape $radius2 ri. ..,0,0,0.5,0.5 *. {max(0,min(1,1-$4))} -[-2,-1] fi 34789 sigma={-3,$5%*w} 34790 r. {w+5*$sigma},{h+5*$sigma},1,1,0,0,0.5,0.5 34791 b. $sigma,0 n. 0,255 34792 sprites3d[1] [2],1 rm[2] 34793 l. 34794 s3d r.. 3,{-2,h/3},1,1,-1 s.. x 34795 d={$10*255} 34796 rand[-4] {$6-$d},{$6+$d} 34797 rand... {$7-$d},{$7+$d} 34798 rand.. {$8-$d},{$8+$d} 34799 a[-4--2] x c.. 0,255 y a y 34800 endl 34801 j3d[0] [1],0,0,0,{$9/255},1,0,0 rm[1] 34802 34803#@gui Brushify : fx_brushify, fx_brushify_preview(0) 34804#@gui : note = note("<small><b>Brush parameters:</b></small>") 34805#@gui : Shape = choice(7,"Bottom layer","Top layer","Rectangle","Diamond","Pentagon","Hexagon","Octogon", 34806#@gui : "Ellipse","Gaussian","Star","Heart") 34807#@gui : Ratio = float(0.25,0,1) 34808#@gui : Number of Sizes = int(4,1,16) 34809#@gui : Maximal Size = int(64,1,128) 34810#@gui : Minimal Size (%)= float(25,0,100) 34811#@gui : Number of Orientations = int(12,1,24) 34812#@gui : Fuzzyness = float(0,0,10) 34813#@gui : Smoothness = float(2,0,10) 34814#@gui : Light Type = choice(4,"None","Flat","Darken","Lighten","Full") 34815#@gui : Light Strength = float(0.2,0,1) 34816#@gui : Opacity = float(0.5,0,1) 34817#@gui : sep = separator() 34818#@gui : note = note("<small><b>Painting parameters:</b></small>") 34819#@gui : Density (%) = float(30,0,100) 34820#@gui : Contour Coherence = float(1,0,1) 34821#@gui : Orientation Coherence = float(1,0,1) 34822#@gui : Gradient Smoothness = float(1,0,10) 34823#@gui : Structure Smoothness = float(5,0,10) 34824#@gui : Primary Angle = float(0,-180,180) 34825#@gui : Angle Dispersion = float(0.2,0,1) 34826#@gui : sep = separator() 34827#@gui : Preview Brush = bool(1) 34828#@gui : sep = separator() 34829#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/22/04</i>.</small>") 34830fx_brushify : 34831 _fx_brushify $* 34832 s0=0--3 s1=1--2 s2=0--2 34833 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 34834 34835_fx_brushify : # Insert brush at the end of the list 34836 N={0.9*$4} 34837 if $1==0 +autocrop. i.. 100%,100%,1,3,1 blend[-2,-1] alpha rr2d. $N,$N,0,3 34838 elif $1==1 +autocrop[0] i.. 100%,100%,1,3,1 blend[-2,-1] alpha rr2d. $N,$N,0,3 34839 elif $1==2 $4,$4 rectangle. 10%,10%,90%,90%,1,1 34840 elif $1==3 shape_diamond. $N 34841 elif $1==4 shape_polygon $N,5 34842 elif $1==5 shape_polygon $N,6 34843 elif $1==6 shape_polygon $N,8 34844 elif $1==7 shape_circle. $N 34845 elif $1==8 $4,$4 gaussian. 30%,30%,0 34846 elif $1==9 shape_star $N 34847 elif $1==10 shape_heart $N 34848 fi 34849 norm. r. 100%,{max(0.01,100*$2)}%,1,1,2 r. $4,$4,1,1,0,0,0.5,0.5 34850 spread. $7 b. $8% n. 0,1 34851 34852fx_brushify_preview : 34853 if $1<2" && "$!<2 34854 gui_error_preview "When a custom brush (bottom or top layer) is specified, at least two layers are required 34855 for this filter to work.In this case, don't forget to set the 'Input layers' option!" 34856 return 34857 fi 34858 fx_brushify $* 34859 if $19 34860 _fx_brushify $* 34861 if $1==0 rm.. elif $1==1 rm[0] fi 34862 rr2d. {0,max(1,w/5)},{0,max(1,h/5)},0,2 n. 0,255 34863 frame. 3,3,0 frame. 1,1,255 frame. 1,1,0 34864 to_rgb. to. "Brush",4,2,13,2,1,255,255,0 to_a. 34865 j[^-1] .,2,2 rm. 34866 else 34867 if $1==0 rm. elif $1==1 rm[0] fi 34868 fi 34869 34870#@gui Cartoon : cartoon, fx_cartoon_preview(0) 34871#@gui : Smoothness = float(3,0,10) 34872#@gui : Sharpening = float(200,0,400) 34873#@gui : Edge Threshold = float(20,1,30) 34874#@gui : Edge Thickness = float(0.25,0,1) 34875#@gui : Color Strength = float(1.5,0,3) 34876#@gui : Color Quantization = int(8,2,256) 34877#@gui : sep = separator() 34878#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 34879#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 34880#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 34881#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 34882#@gui : sep = separator() 34883#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 34884fx_cartoon_preview : 34885 gui_split_preview "cartoon $*",${-3--1} 34886 34887#@gui Circle Abstraction : fx_circle_abstraction, fx_circle_abstraction_preview(1) 34888#@gui : Number of Colors = int(8,2,16) 34889#@gui : Density = int(5,1,100) 34890#@gui : Opacity = float(0.8,0,1) 34891#@gui : Smoothness = float(0,0,4) 34892#@gui : Filled Circles = bool(1) 34893#@gui : Fill Transparent Holes = bool(1) 34894#@gui : Normalize Colors = bool(1) 34895#@gui : sep = separator() 34896#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 34897#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 34898#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 34899#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 34900#@gui : sep = separator() 34901#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/16/06</i>.</small>") 34902fx_circle_abstraction : 34903 repeat $! l[$>] 34904 b $4% 34905 +colormap $1 index[0] [1],0,0 34906 [0],[0],1,4,0 34907 34908 repeat $1 34909 rprogress {$>*100/$1} 34910 +==[0] $> 34911 skeleton3d. 2,2,0,1,0 34912 if {@7} # Process only non empty objects. 34913 s3d. l[-6--1] 34914 r[2] 3,{2,h/3},1,1,-1 34915 1,{2,h/2*$2%},1,1,1 r. 1,{2,h/2},1,1,4 r. 3,200% *[2,-1] y 34916 endl 34917 a[-6--1] y col3d. {1,I($>)} 34918 34919 [0],[0],1,4,0 34920 j3d. ..,0,0,0,1,{1+$5},0,0 34921 sh. 3 col3d... 255 j3d. ...,0,0,0,$3,{1+$5},0,0 rm. 34922 rm.. 34923 blend[2,-1] alpha 34924 fi 34925 done 34926 k[2] 34927 if $6 +channels 3 <. 1 inpaint[0] [1],0,1 rm. channels. 0,2 fi 34928 if $7 n 0,255 fi 34929 rprogress 100 34930 endl done 34931 34932fx_circle_abstraction_preview : 34933 gui_split_preview "fx_circle_abstraction $*",${-3--1} 34934 34935#@gui Cubism : fx_cubism, fx_cubism_preview(1) 34936#@gui : Iterations = int(2,0,10) 34937#@gui : Density = float(50,0,200) 34938#@gui : Thickness = float(10,0,50) 34939#@gui : Angle = float(90,0,360) 34940#@gui : Opacity = float(0.7,0.01,1) 34941#@gui : Smoothness = float(0,0,5) 34942#@gui : sep = separator() 34943#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 34944#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 34945#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 34946#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 34947#@gui : sep = separator() 34948#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/05/06</i>.</small>") 34949fx_cubism : 34950 repeat $1 cubism ${2--1} done 34951 34952fx_cubism_preview : 34953 gui_split_preview "fx_cubism $*",${-3--1} 34954 34955#@gui Cutout : fx_cutout, fx_cutout_preview(1) 34956#@gui : Number of Levels = int(4,2,32) 34957#@gui : Edge Simplicity = float(0.5,0,3) 34958#@gui : Edge Fidelity = int(4,0,10) 34959#@gui : Normalize = bool(1) 34960#@gui : sep = separator() 34961#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 34962#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 34963#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 34964#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 34965#@gui : sep = separator() 34966#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Garagecoder</i> 34967#@gui : Latest Update: <i>2014/03/06</i>.</small>") 34968fx_cutout : 34969 repeat $! l[$>] split_opacity l[0] 34970 median {10-$3} 34971 quantize $1 34972 +luminance. round. area. 0,1 med={ic} rm. 34973 inpaint_holes {$med*$2%},0,1 34974 if $4 n 0,255 fi 34975 endl a c endl done 34976 34977fx_cutout_preview : 34978 gui_split_preview "fx_cutout $*",${-3--1} 34979 34980#@gui Doodle : fx_doodle, gui_no_preview(0) 34981#@gui : Precision (%) = float(30,0,100) 34982#@gui : Smoothness = float(2,0,10) 34983#@gui : Coherence = float(2,0,10) 34984#@gui : Contour Threshold = float(1.5,0,10) 34985#@gui : Spacing = int(2,0,20) 34986#@gui : Minimal Stroke Length = float(70,0,255) 34987#@gui : Preview Progression While Running = _bool(1) 34988#@gui : sep = separator() 34989#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/07/08</i>.</small>") 34990fx_doodle : skip "$*" 34991 repeat $! l[$>] 34992 b $2 n 0,255 structuretensors b $3 34993 100%,100%,1,1,100 34994 if $7 w. ${"fitscreen ."},"[G'MIC] Doodle" fi 34995 34996 _stopflag=0 34997 eval " 34998 const dt = 0.5; 34999 nb_strokes = nb_consecutive_fails = 0; 35000 35001 while (nb_consecutive_fails<500*$1%, 35002 run('+store. canvas'); 35003 35004 P0 = u([w,h] - 1); 35005 length = 0; 35006 35007 repeat (2,dir, 35008 P = P0; 35009 oiP = iP = round(P); 35010 C = I(#0,P); E = eig([ C[0], C[1], C[1], C[2] ]); oV = V = (dir?1:-1)*E[4,2]; 35011 35012 while (E[0]>$4^2 && (i(iP)>$5 || oiP==iP), 35013 i(iP) = 0; 35014 oiP = iP; 35015 P+=dt*V; 35016 iP = round(P); 35017 C = I(#0,P,1); E = eig([ C[0], C[1], C[1], C[2] ]); V = E[4,2]; 35018 dot(oV,V)<0?(V*=-1); 35019 oV = V; 35020 iP!=oiP?++length; 35021 ); 35022 ); 35023 length<$6?(run('rm. $canvas'); ++nb_consecutive_fails):( 35024 !(++nb_strokes%15)?run('distance. 0'); 35025 nb_consecutive_fails = 0; 35026 $7 && !(nb_strokes%30)?( 35027 nb_consecutive_fails = run('if !{*} u inf else +neq. 0 r. {*,w,h},1,1,2 w. rm. u 0 fi') 35028 ); 35029 ) 35030 )" 35031 k. != 0 * 255 35032 endl done 35033 35034#@gui Diffusion Tensors : fx_diffusiontensors, fx_diffusiontensors_preview(0) 35035#@gui : Resolution (%) = float(10,0,20) 35036#@gui : Size = float(5,0,16) 35037#@gui : Color Mode = choice(3,"Monochrome","Grayscale","Orientation","Color") 35038#@gui : Outline = int(1,0,16) 35039#@gui : sep = separator() 35040#@gui : Sharpness = float(0.15,0,1) 35041#@gui : Anisotropy = float(1,0,1) 35042#@gui : Gradient Smoothness = float(0,0,10) 35043#@gui : Tensor Smoothness = float(3,0,10) 35044#@gui : sep = separator() 35045#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35046#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35047#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35048#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35049#@gui : sep = separator() 35050#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/19/10</i>.</small>") 35051fx_diffusiontensors : 35052 repeat $! l[$>] 35053 wh={[w,h]} 35054 +diffusiontensors ${5-8} 35055 r2dx. {max(1,w*$1%)} 35056 dt. {round(125/max(1,$1))},$2,{$3<3?$3:0},$4 35057 if $3==3 35058 remove_opacity.. r.. .,.,1,100%,3 blend[0] [1],shapeaverage0 dilate. {1+2*$4} a c 35059 else k. fi 35060 r. $wh,1,100%,2 35061 endl done 35062 35063fx_diffusiontensors_preview : 35064 gui_split_preview "fx_diffusiontensors $*",${-3--1} 35065 35066#@gui Ellipsionism : fx_ellipsionism, fx_ellipsionism_preview(0) 35067#@gui : Primary Radius = float(20,1,100) 35068#@gui : Secondary Radius = float(10,1,100) 35069#@gui : Smoothness = float(0.5,0,10) 35070#@gui : Opacity = float(0.7,0,1) 35071#@gui : Outline = float(3,1,3) 35072#@gui : Density = float(0.5,0.1,2) 35073#@gui : sep = separator() 35074#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35075#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35076#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35077#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35078#@gui : sep = separator() 35079#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35080fx_ellipsionism : 35081 ellipsionism ${^0} 35082 35083fx_ellipsionism_preview : 35084 gui_split_preview "fx_ellipsionism $*",${-3--1} 35085 35086#@gui Felt Pen : fx_feltpen, fx_feltpen_preview(0) 35087#@gui : Amplitude = float(300,0,4000) 35088#@gui : Density = float(50,0,100) 35089#@gui : Smoothness = float(1,0,10) 35090#@gui : Opacity = float(0.1,0,1) 35091#@gui : Edge = float(20,0,100) 35092#@gui : Thickness = int(5,2,32) 35093#@gui : sep = separator() 35094#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35095#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35096#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35097#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35098#@gui : sep = separator() 35099#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/25/10</i>.</small>") 35100fx_feltpen : 35101 repeat $! l[$>] +fx_hardsketchbw ${1-5},0,0 blend hardlight erode_oct $6 endl done 35102 35103fx_feltpen_preview : 35104 gui_split_preview "fx_feltpen $*",${-3--1} 35105 35106#@gui Fractalize : fractalize, fractalize(1) 35107#@gui : Detail Level = float(0.8,0,1) 35108#@gui : sep = separator() 35109#@gui : note = note("<small><b>Note:</b> This filter uses lot of random values to generate its result, 35110#@gui : so running it twice will give you different results !</small>") 35111#@gui : sep = separator() 35112#@gui : url = link("Click here for a detailed description of this filter.",\ 35113# "http://www.gimpchat.com/viewtopic.php?f=28&t=10036") 35114#@gui : sep = separator() 35115#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/25/04</i>.</small>") 35116 35117#@gui Ghost : fx_ghost, fx_ghost_preview(0) 35118#@gui : note = note("<small><b>Ghost Effect:</b></small>") 35119#@gui : Amplitude = float(200,0,1000) 35120#@gui : Smoothness = float(2,0,10) 35121#@gui : Coherence = float(2,0,10) 35122#@gui : Gamma = float(1,-3,3) 35123#@gui : sep = separator() 35124#@gui : note = note("<small><b>Normalization:</b></small>") 35125#@gui : Amplitude = float(3,0,10) 35126#@gui : Radius = float(16,1,64) 35127#@gui : Invert = bool(0) 35128#@gui : sep = separator() 35129#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35130#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35131#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35132#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35133#@gui : sep = separator() 35134#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/01/30</i>.</small>") 35135fx_ghost : 35136 repeat $! l[$>] 35137 diffusiontensors. 1,1,$2,$3 eigen. compose_channels.. + sqrt.. n.. 1,100 pow.. $4 n.. 0,$1 35138 100%,100% 35139 eval.. "* 35140 ca = i(x,y,0,0); 35141 sa = i(x,y,0,1); 35142 N = i(#-3,x,y); 35143 x0 = x + N*ca; 35144 y0 = y + N*sa; 35145 x1 = x - N*ca; 35146 y1 = y - N*sa; 35147 polygon(#-1,2,x0,y0,x1,y1,-1,1); 35148 I" 35149 k. normalize_local $5,$6 35150 endl done n 0,255 if $7 negate fi 35151 35152fx_ghost_preview : 35153 gui_split_preview "fx_ghost $*",${-3--1} 35154 35155#@gui Hard Sketch : fx_hardsketchbw, fx_hardsketchbw_preview(0) 35156#@gui : Amplitude = float(300,0,4000) 35157#@gui : Density = float(50,0,100) 35158#@gui : Smoothness = float(1,0,10) 35159#@gui : Opacity = float(0.1,0,1) 35160#@gui : Edge = float(20,0,100) 35161#@gui : Fast Approximation = bool(0) 35162#@gui : Color Model = choice(4,"Black on white","White on black","Black on transparent white", 35163#@gui : "White on transparent black","Color on white") 35164#@gui : sep = separator() 35165#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35166#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35167#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35168#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35169#@gui : sep = separator() 35170#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35171fx_hardsketchbw : 35172 b $3 35173 if $7==4 repeat $! l[$>] +hardsketchbw $1,$2,$4,$5,$6 blend hardlight endl done return fi 35174 hardsketchbw $1,$2,$4,$5,$6 35175 if $7&1 negate fi 35176 if $7==2 r 100%,100%,1,4 repeat $! sh[$>] 3 *. -2 +. {2*255} c. 0,255 rm. done 35177 elif $7==3 r 100%,100%,1,4 repeat $! sh[$>] 3 *. 2 c. 0,255 rm. done 35178 fi 35179 35180fx_hardsketchbw_preview : 35181 gui_split_preview "fx_hardsketchbw $*",${-3--1} 35182 35183#@gui Highlight Bloom : fx_highlight_bloom, fx_highlight_bloom_preview(0) 35184#@gui : Details Strength (%) = float(90,0,400) 35185#@gui : Details Scale = float(60,0,255) 35186#@gui : Smoothness = float(60,0,255) 35187#@gui : Highlight (%) = int(30,0,100) 35188#@gui : Contrast (%) = float(20,0,100) 35189#@gui : sep = separator() 35190#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35191#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35192#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35193#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35194#@gui : sep = separator() 35195#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/24/10</i>.</small>") 35196#@gui : sep = separator() 35197#@gui : note = note("This effect has been inspired by:") 35198#@gui : url = link("This tutorial by Sebastien Guyader and Patrick David", 35199#@gui : "https://pixls.us/articles/highlight-bloom-and-photoillustration-look/") 35200fx_highlight_bloom : 35201 repeat $! l[$>] split_opacity l[0] 35202 +smooth $2,0.3,0.8,1,2 35203 -.. . 35204 amp=$3 do smooth. {min(50,$amp)},0.1,1,1,2 amp-=50 while $amp>0 35205 +retinex. 16,lab,0,15 j.. .,0,0,0,0,{$4%} rm. 35206 ac. "normalize_local {$5%},5",lab_l 35207 *.. {$1%} 35208 + c 0,255 35209 endl a c endl done 35210 35211fx_highlight_bloom_preview : 35212 gui_split_preview "fx_highlight_bloom $*",${-3--1} 35213 35214#@gui Hope Poster : fx_poster_hope, fx_poster_hope_preview(0)+ 35215#@gui : Gamma = float(0,-3,3) 35216#@gui : Smoothness = float(3,0,20) 35217#@gui : sep = separator() 35218#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35219#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35220#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35221#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35222#@gui : sep = separator() 35223#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/07/11</i>.</small>") 35224fx_poster_hope : 35225 repeat $! l[$>] split_opacity l[0] 35226 apply_gamma {10^$1} poster_hope $2 35227 endl a c endl done 35228 35229fx_poster_hope_preview : 35230 gui_split_preview "fx_poster_hope $*",${-3--1} 35231 35232#@gui Hough Sketch : fx_houghsketchbw, fx_houghsketchbw_preview(0) 35233#@gui : Smoothness = float(1.25,0,10) 35234#@gui : Density = float(10,0,70) 35235#@gui : Radius = int(5,0,30) 35236#@gui : Threshold = float(80,0,100) 35237#@gui : Opacity = float(0.1,0,1) 35238#@gui : Color Model = choice(4,"Black on white","White on black","Black on transparent white", 35239#@gui : "White on transparent black","Color on white") 35240#@gui : sep = separator() 35241#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35242#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35243#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35244#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35245#@gui : sep = separator() 35246#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/05</i>.</small>") 35247fx_houghsketchbw : 35248 b $1 n 0,255 35249 if $6==4 repeat $! l[$>] +houghsketchbw ${2-5} blend hardlight endl done return fi 35250 houghsketchbw ${2-5} 35251 if $6&1 negate fi 35252 if $6==2 r 100%,100%,1,4 repeat $! sh[$>] 3 *. -2 +. {2*255} c. 0,255 rm. done 35253 elif $6==3 r 100%,100%,1,4 repeat $! sh[$>] 3 *. 2 c. 0,255 rm. done 35254 fi 35255 35256fx_houghsketchbw_preview : 35257 gui_split_preview "fx_houghsketchbw $*",${-3--1} 35258 35259#@gui Kuwahara : fx_kuwahara, fx_kuwahara_preview(0) 35260#@gui : Iterations = int(2,1,20) 35261#@gui : Radius = int(5,1,30) 35262#@gui : sep = separator() 35263#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 35264#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 35265#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 35266#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 35267#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 35268#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 35269#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 35270#@gui : Value Action = choice("None","Cut","Normalize") 35271#@gui : sep = separator() 35272#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35273#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35274#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35275#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35276#@gui : sep = separator() 35277#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/31/05</i>.</small>") 35278fx_kuwahara : 35279 ac "repeat $1 kuwahara $2 done",$3,$4 35280 35281fx_kuwahara_preview : 35282 gui_split_preview "fx_kuwahara $*",${-3--1} 35283 35284#@gui Linify : fx_linify, fx_linify_preview(0) 35285#@gui : Density = float(40,0,100) 35286#@gui : Spreading = float(2,0,10) 35287#@gui : Resolution (%) = float(40,0,100) 35288#@gui : Line Opacity = float(10,0,30) 35289#@gui : Line Precision = int(24,1,128) 35290#@gui : Color Mode = choice(0,"Subtractive","Additive") 35291#@gui : sep = separator() 35292#@gui : Preview Progression While Running = _bool(1) 35293#@gui : sep = separator() 35294#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35295#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35296#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35297#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35298#@gui : sep = separator() 35299#@gui : note = note{"<b>Note:</b>\n\n 35300#@gui : - This filter is our own implementation of the nice algorithm proposed on the webpage 35301#@gui : <a href="http://linify.me">http://linify.me</a>.\n 35302#@gui : - This is a quite resource-demanding filter, so please be patient when running it.\n 35303#@gui : - It actually renders better when applied on small images (<1024). 35304#@gui : "} 35305#@gui : sep = separator() 35306#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/11/21</i>.</small>") 35307fx_linify : 35308 repeat $! l[$>] 35309 if $7 _debug=1 w ${-fitscreen\ {[w,h]}},0,"[Preview] G'MIC: Linify" fi 35310 linify $1,$2,$3%,$4,$5,$6 35311 endl done 35312 35313fx_linify_preview : 35314 gui_split_preview "fx_linify ${1-6},0",${-3--1} 35315 35316#@gui Lylejk's Painting : fx_lylejk_painting, fx_lylejk_painting_preview(0) 35317#@gui : Iterations = int(10,1,20) 35318#@gui : Abstraction = int(2,1,20) 35319#@gui : Radius = int(4,1,30) 35320#@gui : Canvas = float(10,0,100) 35321#@gui : sep = separator() 35322#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35323#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35324#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35325#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35326#@gui : sep = separator() 35327#@gui : note = note("<small>Authors: <i>Lyle Kroll</i> and <i>David Tschumperlé</i>. 35328#@gui : Latest Update: <i>2015/23/02</i>.</small>") 35329#@gui : url = link("Filter Explained here","http://www.gimpchat.com/viewtopic.php?f=10&t=2624") 35330fx_lylejk_painting : 35331 repeat $! l[$>] 35332 nm={0,n} 35333 +l repeat $1 b 0.75 unsharp 0.75,10.49 c 0,255 mv. 0 done endl 35334 smooth. 300,0.26,1,0,7 35335 . rv[-3--1] 35336 blend[-2,-1] lighten,0.5 35337 blend[-2,-1] grainmerge,1 35338 fx_kuwahara. $2,$3,0,0 35339 texturize_canvas. $4,4 35340 nm $nm 35341 endl done 35342 35343fx_lylejk_painting_preview : 35344 gui_split_preview "fx_lylejk_painting $*",${-3--1} 35345 35346#@gui Painting : fx_painting, fx_painting_preview(0)+ 35347#@gui : Abstraction = int(5,1,10) 35348#@gui : Details Scale = float(2.5,0,5) 35349#@gui : Color = float(1.5,0,4) 35350#@gui : Smoothness = float(50,0,1000) 35351#@gui : Sharpen Shades = bool(1) 35352#@gui : sep = separator() 35353#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35354#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35355#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35356#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35357#@gui : sep = separator() 35358#@gui : note = note("<small>Authors: <i>Lyle Kroll</i>, <i>Angelo Lama</i> and <i>David Tschumperlé</i>. 35359#@gui : \nLatest Update: <i>2011/28/02</i>.</small>") 35360fx_painting : skip ${4=0},${5=0} 35361 repeat $! l[$>] 35362 to_colormode {max(3,s)} split_opacity rv 35363 repeat $1 fx_normalize_local. 10,6,5,20,1,11 done 35364 fx_smooth_anisotropic. {100*$2},0.2,1,$2,{2*$2},0.8,90,2,0,1,1,2,1,16 35365 fx_mix_lab. 1,0,0,$3,0,0.5,$3,0,0.5,0,2,0 35366 if $5 fx_segment_watershed. 10,1,0 fi 35367 smooth. $4,0,1,1,1 35368 rv a c 35369 endl done 35370 35371fx_painting_preview : 35372 gui_split_preview "fx_painting $*",${-3--1} 35373 35374#@gui Pen Drawing : fx_pen_drawing, fx_pen_drawing_preview(0)+ 35375#@gui : Amplitude = float(10,0,30) 35376#@gui : sep = separator() 35377#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35378#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35379#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35380#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35381#@gui : sep = separator() 35382#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 35383fx_pen_drawing : 35384 drawing $1 35385 35386fx_pen_drawing_preview : 35387 gui_split_preview "fx_pen_drawing $*",${-3--1} 35388 35389#@gui Polygonize [Delaunay] : fx_polygonize_delaunay, fx_polygonize_delaunay_preview(0) 35390#@gui : Density (%) = float(40,0,100) 35391#@gui : Edges = float(5,0,100) 35392#@gui : Boundaries (%) = float(75,0,100) 35393#@gui : Smoothness = float(0.5,0,8) 35394#@gui : Filling = choice(3,"Black","White","Random","Average","Linear") 35395#@gui : Outline (%) = float(50,0,100) 35396#@gui : Outline Color = color(0,0,0,255) 35397#@gui : Anti-Aliasing = bool(1) 35398#@gui : sep = separator() 35399#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35400#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35401#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35402#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35403#@gui : sep = separator() 35404#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/06/05</i>.</small>") 35405fx_polygonize_delaunay : 35406 repeat $! l[$>] to_rgba 35407 wh={[w,h]} if $11 r 150%,150%,1,100%,3 fi 35408 35409 # Compute Delaunay triangulation. 35410 mM={[im,iM]} b $4 n $mM 35411 +to_rgb. gradient_norm. ge. $2 35412 f. "!x || !y || x==w-1 || y==h-1?(u^0.25<$3%):(u^0.25<$1%?i:0)" 35413 {is+1},1,1,2 f.. ">begin(p = 0); i?(I[#-1,++p] = [x,y];p):0" 35414 delaunay.. 35415 35416 # Render filling. 35417 if $5==4 # Linear 35418 +f[0] 0 f... "*i?( 35419 p = I(#1); P0 = I[#2,p[0]]; P1 = I[#2,p[1]]; P2 = I[#2,p[2]]; 35420 W = solve([P0[0],P1[0],P2[0],P0[1],P1[1],P2[1],1,1,1],[x,y,1]); 35421 I(#-1) = cut(W[0]*I(#0,P0) + W[1]*I(#0,P1) + W[2]*I(#0,P2),0,255); 35422 );I" 35423 elif $5==3 # Average 35424 +f[0] 0 f... "*i?( 35425 p = I(#1); P0 = I[#2,p[0]]; P1 = I[#2,p[1]]; P2 = I[#2,p[2]]; 35426 I(#-1) = (I(#0,P0) + I(#0,P1) + I(#0,P2))/3; 35427 );I" 35428 elif $5==2 # Random 35429 +norm[1] label_fg. 0 {iM+1},1,1,3 rand. 0,255 to_rgba. point. 0 map.. . rm. 35430 else # Black or white 35431 +norm[1] !=. 0 *. 255 channels. -3,0 35432 if $5 sh. 0,2 f. 255 rm. fi 35433 fi 35434 rm[0,2] 35435 35436 # Render outlines. 35437 if $6 35438 norm[0] f[0] "i!=j(1) || i!=j(0,1)" # thinning[0] 1 35439 +fc. ${7-10} j.. .,0,0,0,0,{$6%},... rm. 35440 fi 35441 35442 k. 35443 if $11 r $wh,1,100%,2 fi 35444 35445 endl done 35446 35447fx_polygonize_delaunay_preview : 35448 gui_split_preview "fx_polygonize_delaunay $*",${-3--1} 35449 35450#@gui Polygonize [Energy] : fx_polygonize, fx_polygonize_preview(0) 35451#@gui : Amplitude = int(300,0,2000) 35452#@gui : Smoothness = float(10,0,100) 35453#@gui : Minimal Area = float(10,0,100) 35454#@gui : X-Resolution = float(10,1,256) 35455#@gui : Y-Resolution = float(10,1,256) 35456#@gui : Outline Color = color(0,0,0,255) 35457#@gui : sep = separator() 35458#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35459#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35460#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35461#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35462#@gui : sep = separator() 35463#@gui : url = link("Click here for a detailed description of this filter.",\ 35464# "http://www.gimpchat.com/viewtopic.php?f=28&t=9174") 35465#@gui : sep = separator() 35466#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/02/12</i>.</small>") 35467fx_polygonize : 35468 polygonize $1,$2,{$3^2},$4,$5 35469 if $9 repeat $! l[$>] # has outline. 35470 +norm g. xy,1 !=[-2,-1] 0 -|[-2,-1] r. 100%,100%,1,4 35471 replace_color. 0,0,1,1,1,1,$6,$7,$8,$9 35472 blend alpha 35473 endl done fi 35474 35475fx_polygonize_preview : 35476 gui_split_preview "fx_polygonize $*",${-3--1} 35477 35478#@gui Poster Edges : fx_poster_edges, fx_poster_edges_preview(0) 35479#@gui : Image Smoothness = float(20,0,100) 35480#@gui : Edge Threshold = float(60,0,100) 35481#@gui : Edge Shade = float(5,0,30) 35482#@gui : Edge Thickness = float(0,0,5) 35483#@gui : Edge Antialiasing = float(10,0,100) 35484#@gui : Posterization Level = int(0,0,15) 35485#@gui : Posterization Antialiasing = float(0,0,100) 35486#@gui : sep = separator() 35487#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35488#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35489#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35490#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35491#@gui : sep = separator() 35492#@gui : url = link("Click here for a detailed description of this filter.",\ 35493# "http://www.davidrevoy.com/article147/gmic-new-filter-poster-edges") 35494#@gui : sep = separator() 35495#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>David Revoy</i>. 35496#@gui : Latest Update: <i>2012/30/11</i>.</small>") 35497fx_poster_edges : 35498 if $1 bilateral 10,$1 fi 35499 poster_edges ${2-7} 35500 35501fx_poster_edges_preview : 35502 gui_split_preview "fx_poster_edges $*",${-3--1} 35503 35504#@gui Posterize : fx_posterize, fx_posterize_preview(0) 35505#@gui : Smoothness = float(150,0,800) 35506#@gui : Edges (%) = float(30,0,100) 35507#@gui : Paint = float(1,0,10) 35508#@gui : Colors = int(12,2,32) 35509#@gui : Minimal Area = int(0,0,64) 35510#@gui : Outline (%) = float(0,0,100) 35511#@gui : Normalize Colors = bool(0) 35512#@gui : sep = separator() 35513#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35514#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35515#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35516#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35517#@gui : sep = separator() 35518#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/25/10</i>.</small>") 35519fx_posterize : 35520 repeat $! l[$>] split_opacity l[0] 35521 . amp=$1 do smooth. {min(50,$amp)},{$2%},1,$3,{2*$3} amp-=50 while $amp>0 35522 bilateral.. .,5,10 rm. 35523 srgb2rgb +colormap $4 rgb2srgb 35524 index.. .,0,0 35525 if $5 35526 +area.. 0,0 <. $5 inpaint... .,0,3 rm. 35527 fi 35528 map.. . rm. 35529 if $6 35530 +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] 35531 fi 35532 if $7 n 0,255 fi 35533 endl a c endl done 35534 35535fx_posterize_preview : 35536 gui_split_preview "fx_posterize $*",${-3--1} 35537 35538#@gui Quadtree Variations : fx_quadtree, fx_quadtree_preview(1) 35539#@gui : Mode = choice("Squares","Sierpinksi Design","Ellipse Painting") 35540#@gui : Precision = int(1024,2,4096) 35541#@gui : Homogeneity = float(0.5,0,2) 35542#@gui : Outline = int(0,0,4) 35543#@gui : sep = separator() 35544#@gui : note = note{"<small><b>For 'Ellipse painting' only:</b></small>"} 35545#@gui : Primary Radius = float(3,0,5) 35546#@gui : Secondary Radius = float(1.5,0,5) 35547#@gui : Anisotropy = float(1,0,4) 35548#@gui : Only Leafs = bool(1) 35549#@gui : sep = separator() 35550#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35551#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35552#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35553#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35554#@gui : sep = separator() 35555#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/15/06</i>.</small>") 35556fx_quadtree : 35557 mode,precision,homogeneity,outline,radius1,radius2,anisotropy,only_leafs=${1-8} 35558 m "_qt : sh 3 u {w>1&&h>1?iv*(w*h)^"$homogeneity":-0.1} k[0]" # Function used to split quads 35559 repeat $! l[$>] 35560 to_rgb 35561 35562 # Decompose image with quadtree. 35563 keep_only_leafs={$mode!=2" || "$only_leafs} 35564 +norm. a c 35565 _qt ({d=max(w,h);[0,0,d-1,d-1]},0,${}) 35566 repeat $precision 35567 +columns. 100% n={yM} rm. 35568 x0,y0,x1,y1,level={crop(0,$n,5,1)} 35569 xc={round(($x1+$x0)/2)} yc={round(($y1+$y0)/2)} 35570 xc1,yc1={[$xc,$yc]-1} 35571 level1={$level+1} 35572 B0=$x0,$y0,$xc1,$yc1 +crop[0] $B0,3 _qt. B0.=,$level1,${} rm. 35573 B1=$xc,$y0,$x1,$yc1 +crop[0] $B1,3 _qt. B1.=,$level1,${} rm. 35574 B2=$x0,$yc,$xc1,$y1 +crop[0] $B2,3 _qt. B2.=,$level1,${} rm. 35575 B3=$xc,$yc,$x1,$y1 +crop[0] $B3,3 _qt. B3.=,$level1,${} rm. 35576 if $keep_only_leafs 35577 sh. $n,$n,0,0 f. $B0 rm. 35578 ($B1;$B2;$B3) a[-2,-1] y # Insert new leafs 35579 else 35580 =. -1,5,$n # Mark as not terminal leaf anymore 35581 ($B0;$B1;$B2;$B3) a[-2,-1] y # Insert new leafs 35582 else 35583 fi 35584 done 35585 shift. 2,0,0,0,2 sort. +,y levelmax={i(0,h-1)} shift. -2,0,0,0,2 # Sort by quadtree level order 35586 35587 # Estimate data average in each quad. 35588 channels[0] 0,2 +structuretensors[0] a[0,-1] c 35589 r. {w+6},100%,1,1,0 35590 repeat h 35591 x0,y0,x1,y1={crop(0,$>,4,1)} 35592 +crop[0] $x0,$y0,$x1,$y1,3 r. 1,1,1,100%,2 y. x 35593 j.. .,{-2,w-6},$> rm. 35594 done 35595 35596 # Synthetize image. 35597 permute. cyzx 35598 channels[0] 0,3 f[0] 0 35599 35600 if $mode==0 # Squares 35601 f. "> 35602 rectangle(ind,P0,P1,opacity,color) = ( 35603 _P0 = P0; 35604 _P2 = P1; 35605 _P1 = [ _P2[0], _P0[1] ]; 35606 _P3 = [ _P0[0], _P2[1] ]; 35607 polygon(#ind,4,_P0,_P1,_P2,_P3,opacity,color); 35608 ); 35609 begin(colo = [ 0,0,0,255 ]); 35610 P = I; 35611 Xpp = P[0,2]; 35612 Xnn = P[2,2]; 35613 col = [ P[6,3],255 ]; 35614 if ("$outline"<=0, 35615 rectangle(#0,Xpp,Xnn,1,col); 35616 _(else), 35617 rectangle(#0,Xpp,Xnn,1,colo); 35618 rectangle(#0,Xpp + "$outline",Xnn - "$outline",1,col); 35619 ); 35620 I" 35621 35622 elif $mode==1 # Sierpinski design 35623 f. "> 35624 P = I; 35625 Xpp = P[0,2]; 35626 Xnn = P[2,2]; 35627 Xnp = [ Xnn[0],Xpp[1] ]; 35628 Xpn = [ Xpp[0],Xnn[1] ]; 35629 col1 = [ P[6,3],255 ]; 35630 col2 = [ P[6,3],64 ]; 35631 T = [ P[9],P[10],P[10],P[11] ]; 35632 eig = eig(T); 35633 angle = atan2(eig[5],eig[4])*180/pi; 35634 if ((angle>=0 && angle<90) || angle<-90, 35635 polygon(#0,3,Xpp,Xnp,Xnn,1,col1); 35636 polygon(#0,3,Xpp,Xnn,Xpn,1,col2); 35637 _(else), 35638 polygon(#0,3,Xnp,Xnn,Xpn,1,col1); 35639 polygon(#0,3,Xnp,Xpp,Xpn,1,col2) 35640 ); 35641 I" 35642 35643 else # Ellipse painting 35644 f. "> 35645 begin(colo = [ 0,0,0,255 ]); 35646 P = I; 35647 Xpp = P[0,2]; 35648 Xnn = P[2,2]; 35649 Xcc = (Xpp + Xnn)/2; 35650 R = (Xnn[0] - Xpp[0])/2; 35651 col = [ P[6,3],255 ]; 35652 r = "$radius2"*R; 35653 R*="$radius1"; 35654 T = [ P[9],P[10],P[10],P[11] ]; 35655 eig = eig(T); 35656 anisotropy = (1 + eig[1])/(1 + eig[0]); 35657 r*=anisotropy^"$anisotropy"; 35658 angle = atan2(eig[5],eig[4])*180/pi; 35659 if ("$outline">0, ellipse(#0,Xcc,R,r,angle°,1,colo)); 35660 ellipse(#0,Xcc,R - "$outline",r - "$outline",angle°,1,col); 35661 I" 35662 if !$outline sh[0] 100% if !im solidify[0] 10% fi fi 35663 fi 35664 k[0] 35665 endl done 35666 um _qt 35667 35668fx_quadtree_preview : 35669 gui_split_preview "fx_quadtree $*",${-3--1} 35670 35671#@gui Rodilius : fx_rodilius, fx_rodilius_preview(1) 35672#@gui : Amplitude = float(10,0,30) 35673#@gui : Thickness = float(10,0,100) 35674#@gui : Sharpness = float(300,0,1000) 35675#@gui : Orientations = int(5,2,36) 35676#@gui : Offset = float(30,0,180) 35677#@gui : Smoothness = int(0,0,5) 35678#@gui : Color Mode = choice(1,"Darker","Lighter") 35679#@gui : sep = separator() 35680#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 35681#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 35682#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 35683#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 35684#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 35685#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 35686#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 35687#@gui : Value Action = choice("None","Cut","Normalize") 35688#@gui : sep = separator() 35689#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35690#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35691#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35692#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35693#@gui : url = link("Click here for a video tutorial","http://www.youtube.com/watch?v=RC07VUpzwGc") 35694#@gui : sep = separator() 35695#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Rod/GimpChat</i>. 35696#@gui : Latest Update: <i>2013/05/03</i>.</small>") 35697fx_rodilius : 35698 ac "rodilius ${1-5,7} repeat $6 smooth 10,0,1,1,1,0.8,45 sharpen 30 done c 0,255",$8,$9 35699 35700fx_rodilius_preview : 35701 gui_split_preview "fx_rodilius $*",${-3--1} 35702 35703#@gui Shapeism : fx_shapeism, fx_shapeism_preview(0)+ 35704#@gui : Shape = choice(2,"Squares","Triangles","Circles","Diamond","Hexagon","Octagon","Stars","Custom") 35705#@gui : Branches = int(7,3,16) 35706#@gui : Thickness = float(0.38,0,1) 35707#@gui : Angle = float(0,0,360) 35708#@gui : note = note("<small><b>Note:</b> Parameters <i>Branches</i>, <i>Thickness</i> and <i>Angle</i> are 35709#@gui : used only for <i>Custom</i> shapes.</small>") 35710#@gui : Antialiasing = bool(1) 35711#@gui : sep = separator() 35712#@gui : Scales = int(5,1,16) 35713#@gui : Maximal Size = int(32,1,256) 35714#@gui : Minimal Size = int(8,1,256) 35715#@gui : Allow Angle = choice(3,"0 deg.","180 deg.","90 deg.","Any") 35716#@gui : Spacing = int(1,-5,5) 35717#@gui : Precision = int(5,1,10) 35718#@gui : Edges = float(0.5,0,2) 35719#@gui : Smoothness = float(1,0,10) 35720#@gui : Background = color(0,0,0,255) 35721#@gui : sep = separator() 35722#@gui : url = link("Click here for a detailed description of this filter.",\ 35723# "http://gimpchat.com/viewtopic.php?f=28&t=7500&sid=5b483979826903b8f8fc8fdaf1767dae") 35724#@gui : sep = separator() 35725#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/11/06</i>.</small>") 35726fx_shapeism : 35727 repeat $! l[$>] 35728 to_rgb 35729 +gradient_norm b. $13% ^. $12 quantize. $6,0,0 35730 100%,100%,1,2 35731 repeat $6 35732 35733 # Create map of possible locations. 35734 +channels[2] 100% +>[1] $> !=.. 0 -|[-2,-1] a[2,-1] c 35735 35736 # Create shape at given scale. 35737 size={if($6<=1,$7,$7+($8-$7)*$>/($6-1))} 35738 if $size<1 break fi 35739 if $5 {2*$size},{2*$size} _fx_shapeism$1. ${2-4} r2dy. $size 35740 else $size,$size _fx_shapeism$1. ${2-4} 35741 fi 35742 +!=. 0 expand_xy[-2,-1] 1,0 n[-2,-1] 0,1 35743 if $10<1 dilate. 3 fi 35744 . a[-3--1] c 35745 35746 # Pack sprites for given scale 35747 rprogress "pack_sprites[-2,-1] 1,100,$9,$10,$11",{$>*100/$6},{($>+1)*100/$6} 35748 channels. 0,1 35749 35750 done 35751 35752 rprogress 97 35753 rm[1] 35754 channels. 0 +!=. 0 blend[0,-1] shapeaverage0 *[1] 255 a c 35755 i[0] 100%,100%,1,4 fc[0] $14,$15,$16,$17 35756 blend alpha 35757 rprogress 100 35758 endl done 35759 35760fx_shapeism_preview : 35761 gui_print_preview "" 35762 50%,50% _fx_shapeism$1. ${2-4} frame. 1,1,0 >=. 50% n. 0,255 r. 100%,100%,1,4 35763 ri. [0],0,0,0.5,0.5 -| 35764 35765_fx_shapeism0 : # Square 35766 f 255 skip $* 35767 35768_fx_shapeism1 : # Triangle 35769 polygon 3,50%,0,0,100%,100%,100%,1,1 skip $* 35770 35771_fx_shapeism2 : # Circle 35772 shape_circle {w} rm.. skip $* 35773 35774_fx_shapeism3 : # Diamond 35775 shape_diamond {w} rm.. skip $* 35776 35777_fx_shapeism4 : # Hexagon 35778 star3d 3,1 *3d. {0,min(w,h)/2} j3d[0] .,50%,50%,0,1,2,0 k[0] skip $* 35779 35780_fx_shapeism5 : # Octogon 35781 star3d 4,1 *3d. {0,min(w,h)/2} j3d[0] .,50%,50%,0,1,2,0 k[0] skip $* 35782 35783_fx_shapeism6 : # Star 35784 star3d 5 *3d. {0,min(w,h)/2} j3d[0] .,50%,50%,0,1,2,0 k[0] skip $* 35785 35786_fx_shapeism7 : # Custom 35787 star3d $1,$2 *3d. {0,min(w,h)/2} r3d. 0,0,1,$3 j3d[0] .,50%,50%,0,1,2,0 k[0] 35788 35789#@gui Sharp Abstract : fx_sharp_abstract, fx_sharp_abstract_preview(0) 35790#@gui : Spatial Scale = float(4,0,32) 35791#@gui : Value Scale = float(10,0,16) 35792#@gui : Precision = float(0.5,0,2) 35793#@gui : sep = separator() 35794#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 35795#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 35796#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 35797#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 35798#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 35799#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 35800#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 35801#@gui : sep = separator() 35802#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35803#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35804#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35805#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35806#@gui : sep = separator() 35807#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/09</i>.</small>") 35808fx_sharp_abstract : 35809 ac "rolling_guidance ${1-3}",$4 35810 35811fx_sharp_abstract_preview : 35812 gui_split_preview "fx_sharp_abstract $*",${-3--1} 35813 35814#@gui Sketch : fx_sketchbw, fx_sketchbw_preview(0) 35815#@gui : Number of Orientations = int(3,1,16) 35816#@gui : Starting Angle = float(45,0,180) 35817#@gui : Angle Range = float(180,0,180) 35818#@gui : Stroke Length = float(30,0,1000) 35819#@gui : Contour Threshold = float(1.75,0,10) 35820#@gui : Opacity = float(0.02,0,0.3) 35821#@gui : Background Intensity = float(0.5,0,2) 35822#@gui : Density = float(0.75,0,5) 35823#@gui : Sharpness = float(0.1,0,1) 35824#@gui : Anisotropy = float(0.7,0,1) 35825#@gui : Smoothness = float(3,0,10) 35826#@gui : Coherence = float(6,0,10) 35827#@gui : Boost Stroke = bool(0) 35828#@gui : Curved Stroke = bool(1) 35829#@gui : Color Model = choice(4,"Black on white","White on black","Black on transparent white", 35830#@gui : "White on transparent black","Color on white") 35831#@gui : sep = separator() 35832#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35833#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35834#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35835#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35836#@gui : sep = separator() 35837#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/05/11</i>.</small>") 35838fx_sketchbw : 35839 if $15==4 repeat $! l[$>] +sketchbw ${1-14} blend hardlight endl done return fi 35840 sketchbw ${1-14} 35841 if $15&1 negate fi 35842 if $15==2 r 100%,100%,1,4 repeat $! sh[$>] 3 *. -2 +. {2*255} c. 0,255 rm. done 35843 elif $15==3 r 100%,100%,1,4 repeat $! sh[$>] 3 *. 2 c. 0,255 rm. done 35844 fi 35845 35846fx_sketchbw_preview : 35847 gui_split_preview "fx_sketchbw $*",${-3--1} 35848 35849#@gui Smooth Abstract : fx_smooth_abstract, fx_smooth_abstract_preview(0) 35850#@gui : Smoothness (%) = float(75,0,100) 35851#@gui : Regularization = choice(0,"Isotropic","Delaunay-oriented","Edge-oriented") 35852#@gui : Regularization Iterations = int(20,0,100) 35853#@gui : Geometry = float(1,0,5) 35854#@gui : Details = float(30,0,50) 35855#@gui : sep = separator() 35856#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 35857#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 35858#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 35859#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 35860#@gui : sep = separator() 35861#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/06/04</i>.</small>") 35862fx_smooth_abstract : 35863 repeat $! l[$>] split_opacity l[0] 35864 srgb2rgb 35865 mM={[im,iM]} +b $4 n. $mM gradient_norm. <=. {50-$5} 35866 inpaint_pde[0] [1],$1%,$2,$3 rm. 35867 rgb2srgb c 0,255 35868 endl a c endl done 35869 35870fx_smooth_abstract_preview : 35871 gui_split_preview "fx_smooth_abstract $*",${-3--1} 35872 35873#@gui Stylize : fx_stylize,fx_stylize_preview 35874#@gui : Style = choice{0,"Custom Style (Top Layer)","Custom Style (Bottom Layer)", 35875#@gui : "Braque: Landscape near Antwerp", 35876#@gui : "Braque: Le Viaduc à l'Estaque", 35877#@gui : "Braque: Little Bay at La Ciotat", 35878#@gui : "Braque: The Mandola", 35879#@gui : "Christine Garner: Black Colour Pencil", 35880#@gui : "Christine Garner: Colour Pencil Sepia", 35881#@gui : "Christine Garner: Dark Coloured Pencil", 35882#@gui : "Christine Garner: Pencil", 35883#@gui : "Christine Garner: Sketching Pastel", 35884#@gui : "Christine Garner: Willow Charcoal", 35885#@gui : "Delaunay: Windows Open Simultaneously", 35886#@gui : "Delaunay: Portrait de Metzinger", 35887#@gui : "Hokusai: The Great Wave", 35888#@gui : "Kandinsky: Squares with Concentric Circles", 35889#@gui : "Kandinsky: Yellow-Red-Blue", 35890#@gui : "Klee: Death and Fire", 35891#@gui : "Klee: In the Style of Kairouan", 35892#@gui : "Klee: Oriental Pleasure Garden Anagoria", 35893#@gui : "Klee: Polyphony 2", 35894#@gui : "Klee: Red waistcoat", 35895#@gui : "Klimt: The Kiss", 35896#@gui : "Mondrian: Composition in Red-Yellow-Blue", 35897#@gui : "Mondrian: Evening; Red Tree", 35898#@gui : "Mondrian: Gray Tree", 35899#@gui : "Monet: San Giorgio Maggiore at Dusk", 35900#@gui : "Monet: Water-Lily Pond", 35901#@gui : "Monet: Wheatstacks - End of Summer", 35902#@gui : "Munch: The Scream", 35903#@gui : "Picabia: Udnie", 35904#@gui : "Picasso: Les Demoiselles d'Avignon", 35905#@gui : "Picasso: Seated Woman", 35906#@gui : "Picasso: The Reservoir - Horta de Ebro", 35907#@gui : "Pollock: Convergence", 35908#@gui : "Pollock: Summertime Number 9A", 35909#@gui : "Van Gogh: Almond Blossom", 35910#@gui : "Van Gogh: Irises", 35911#@gui : "Van Gogh: The Starry Night", 35912#@gui : "Van Gogh: Wheat Field with Crows"} 35913#@gui : Scale Style to Fit Target Resolution = choice(5,"No rescaling","10%","20%","30%","50%","75%","100%","150%", 35914#@gui : "200%","250%","300%") 35915#@gui : Style Variations = choice("None","All XY-flips","All 90° rotations","All 45° rotations") 35916#@gui : Preview Progression While Running = bool(1) 35917#@gui : sep = separator(), note = note{"<small><b><span color="blue">Style/Target Parameters:</span></b></small>"} 35918#@gui : Fidelity to Target (Finest) = float(0.5,0,5) 35919#@gui : Fidelity to Target (Coarsest) = float(2,0,5) 35920#@gui : Fidelity Smoothness (Finest) = float(3,0,5) 35921#@gui : Fidelity Smoothness (Coarsest) = float(0.5,0,5) 35922#@gui : Fidelity Chromaticity = float(0.1,0,1) 35923#@gui : sep = separator(), note = note{"<small><b><span color="blue">Image Matching Parameters:</span></b></small>"} 35924#@gui : Match Colors With = choice(3,"Nothing","Gamma Balance","Histogram Transfer","PCA transfer") 35925#@gui : Colorspace = choice{3,"sRGB","Linear RGB","YCbCr","YCbCr (Luma/Chroma),"YCbCr (Luma Only)", 35926#@gui : "YCbCr (Chroma Only)","Lab","Lab (Luma/Chroma)","Lab (Luma Only)","Lab (Chroma Only)"} 35927#@gui : Keep Color Channels = choice{"All","Luminance Only (YCbCr)","Luminance Only (Lab)","Chrominances Only (CbCr)", 35928#@gui : "Chrominances Only (ab)"} 35929#@gui : Smoothness = float(0.7,0,5) 35930#@gui : Also Match Gradients = float(1,0,5) 35931#@gui : sep = separator(), note = note{"<small><b><span color="blue">Advanced Parameters:</span></b></small>"} 35932#@gui : Init. Type = choice("Best Match","Identity","Randomized") 35933#@gui : Init. Resolution = choice(1,"8px","16px","32px","64px","128px","256px") 35934#@gui : Init. With High Gradients Only = float(0,0,100) 35935#@gui : Patch Size for Analysis = int(5,2,16) 35936#@gui : Patch Size for Synthesis = int(5,2,16) 35937#@gui : Patch Size for Synthesis (Final) = int(7,2,16) 35938#@gui : Number of Matches (Finest) = int(1,0,10) 35939#@gui : Number of Matches (Coarsest) = int(30,0,200) 35940#@gui : Penalize Patch Repetitions = int(10,0,300) 35941#@gui : Matching Precision (Smaller is Faster) = float(2,0,10) 35942#@gui : Scale Factor = float(1.85,1.1,4) 35943#@gui : Skip Finest Scales = int(0,0,3) 35944#@gui : sep = separator() 35945#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/03/23</i>.</small>") 35946fx_stylize : 35947 init_resolution={arg(1+$16,8,16,32,64,128,256)} 35948 35949 # Define image matching function 35950 colorspace=${"arg 1+$11,all,lrgb,ycbcr,ycbcr,ycbcr_y,ycbcr_cbcr,lab,lab,lab_l,lab_ab"} 35951 match_colors="s c,-3 mv[1] 3 b[-2,-1] 1% negate[-2,-1] n[-2,-1] 0,1" 35952 luma,chroma= 35953 if $11==3" || "$11==7 # Chroma/Luma conversion for YCbCr or Lab 35954 luma=_${"arg 1+($11==7),y,l"} 35955 chroma=_${"arg 1+($11==7),cbcr,ab"} 35956 fi 35957 if $10==1 35958 match_colors=$match_colors" ac[0,1] \"balance_gamma ,\","$colorspace$luma 35959 if narg($chroma) match_colors=$match_colors" ac[0,1] \"balance_gamma ,\","$colorspace$chroma fi 35960 elif $10==2 35961 match_colors=$match_colors" transfer_histogram[0] [1],256,"$colorspace$luma 35962 if narg($chroma) match_colors=$match_colors" transfer_histogram[0] [1],256,"$colorspace$chroma fi 35963 elif $10==3 35964 match_colors=$match_colors" transfer_pca[0] [1],"$colorspace$luma" c[0] 0,255" 35965 if narg($chroma) match_colors=$match_colors" transfer_pca[0] [1],"$colorspace$chroma" c[0] 0,255" fi 35966 fi 35967 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]" 35968 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]" 35969 elif $12==3 match_colors=$match_colors" rgb2ycbcr[0,1] sh[0,1] 0 f[-2,-1] 128 rm[-2,-1] ycbcr2rgb[0,1]" 35970 elif $12==4 match_colors=$match_colors" srgb2lab[0,1] sh[0,1] 0 f[-2,-1] 50 rm[-2,-1] lab2srgb[0,1]" 35971 fi 35972 match_colors=$match_colors\ 35973 " 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" 35974 35975 patch_penalization=$23 35976 35977 # Insert style image at the end of the list. 35978 if $1<2 # Custom style (top or bottom layer) 35979 if $!<2 error "At least two layers are required in this mode." fi 35980 ind_first={$1==0?1:0} ind_style={$1==0?0:-1} N={$!-1} sh[$ind_style] 35981 else 35982 ind_first=0 N=$! ind_style= _fx_stylize {$1-2} 35983 fi 35984 35985 # Process layers. 35986 is_window=0 35987 repeat $N l[{$ind_first+$>},-1] nm={0,n} 35988 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 35989 if $3==1 . +mirror. x +mirror[-2,-1] y a[-4--1] z 35990 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 35991 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 35992 fi 35993 if $4 wsiz=${"fitscreen "{0,[w,h]}} w[0] $wsiz is_window={*} fi 35994 stylize[0] .,${5-9},$15,$init_resolution,${17-22},$patch_penalization,${24-26},$match_colors 35995 k[0,1] nm[0] $nm 35996 if $is_window" && "!{*} break fi 35997 endl done 35998 rm. # Remove style image 35999 if 0$_output_mode 36000 if narg($ind_style) rm[$ind_style] fi # Do not duplicate style layer if output mode -> new layers 36001 if $is_window" && "!{*} rm fi # In case user closed the window, does not output new layers. 36002 fi 36003 36004fx_stylize_preview : 36005 if $1<2 # Custom style (top or bottom layer) 36006 if $!<2 gui_warning_preview "At least two layers are required when specifying a custom style." return fi 36007 ind_first={$1==0?1:0} ind_style={$1==0?0:-1} N={$!-1} sh[$ind_style] 36008 else 36009 ind_first=0 N=$! ind_style= _fx_stylize {$1-2} 36010 fi 36011 repeat $N l[{$ind_first+$>},-1] 36012 gui_no_preview[0] , 36013 +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 36014 endl done rm. 36015 if narg($ind_style) rm[$ind_style] fi 36016 36017_fx_stylize : # Download pre-defined style image 36018 if isnum($1) 36019 name=${"arg 1+$1",\ 36020 "landscapenearantwerp,leviaducalestaque,littlebayatlaciotat,themandola",\ 36021 "blackcolourpencil,colourpencilsepia,darkcolouredpencil,pencil,sketchingpastel,willowcharcoal",\ 36022 "windowsopensimultaneously,portraitdemetzinger,greatwave,squareswithconcentriccircles,yellowredblue",\ 36023 "deathandfire,inthestyleofkairouan,orientalpleasuregardenanagoria,polyphony2,redwaistcoat,thekiss",\ 36024 "compositionredyellowblue,redtree,graytree,sangiorgiomaggioreatdusk,waterlilypond,wheatstacksendofsummer",\ 36025 "scream,udnie,lesdemoisellesdavignon,seatedwoman,reservoirhortadeebro,convergence,summertime9a",\ 36026 "almondblossom,irises,starrynight,wheatfieldwithcrows"} 36027 else name="$1" 36028 fi 36029 filename=${-path_cache}style_$name.png 36030 if isfile(['{/$filename}']) $filename 36031 else i https://gmic.eu/img/style_$name.png o. $filename 36032 fi 36033 36034#@gui Vector Painting : fx_vector_painting, fx_vector_painting_preview(1) 36035#@gui : Details = float(9,0,10) 36036#@gui : sep = separator() 36037#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36038#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36039#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36040#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36041#@gui : sep = separator() 36042#@gui : note = note("<small>Author: <i>David Tschumperlé</i>.\nLatest Update: <i>2015/25/08</i>.</small>") 36043fx_vector_painting : 36044 repeat $! l[$>] 36045 +luminance b. {10-$1}%,1,1 36046 f. "dmax = -1; nmax = 0; 36047 for (n = 0, ++n<=8, 36048 p = arg(n,-1,0,1,-1,1,-1,0,1); 36049 q = arg(n,-1,-1,-1,0,0,1,1,1); 36050 d = (j(p,q,0,0,0,1) - i)^2; 36051 if (d>dmax,dmax = d; nmax = n,nmax) 36052 )" 36053 blend shapeaverage 36054 endl done 36055 36056fx_vector_painting_preview : 36057 gui_split_preview "fx_vector_painting $*",${-3--1} 36058 36059#@gui Warhol : warhol, warhol(1) 36060#@gui : X-Tiles = int(3,1,10) 36061#@gui : Y-Tiles = int(3,1,10) 36062#@gui : Smoothness = float(2,0,10) 36063#@gui : Color = float(40,0,60) 36064#@gui : sep = separator() 36065#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36066 36067#@gui Whirl Drawing : fx_draw_whirl, fx_draw_whirl_preview(0) 36068#@gui : Amplitude = float(20,0,100) 36069#@gui : sep = separator() 36070#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36071#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36072#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36073#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36074#@gui : sep = separator() 36075#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36076fx_draw_whirl : 36077 repeat $! l[$>] split_opacity draw_whirl[0] $* a c endl done 36078 36079fx_draw_whirl_preview : 36080 gui_split_preview "fx_draw_whirl $*",${-3--1} 36081 36082#@gui ____<b>Black & White</b> 36083#------------------------------- 36084 36085#@gui Black & White : fx_blackandwhite, fx_blackandwhite_preview(1)+ 36086#@gui : Red Level = float(0.299,0,1) 36087#@gui : Red Smoothness = float(0,0,10) 36088#@gui : Green Level = float(0.587,0,1) 36089#@gui : Green Smoothness = float(0,0,10) 36090#@gui : Blue Level = float(0.114,0,1) 36091#@gui : Blue Smoothness = float(0,0,10) 36092#@gui : sep = separator() 36093#@gui : Brightness (%) = float(0,-100,100) 36094#@gui : Contrast (%) = float(0,-100,100) 36095#@gui : Gamma (%) = float(0,-100,100) 36096#@gui : Hue (%) = float(0,-100,100) 36097#@gui : Saturation (%) = float(0,-100,100) 36098#@gui : sep = separator() 36099#@gui : Grain (Shadows) = float(0,0,200) 36100#@gui : Grain (Midtones) = float(0,0,200) 36101#@gui : Grain (Highlights) = float(0,0,200) 36102#@gui : Grain Tone Fading = float(2,0,10) 36103#@gui : Grain Scale = float(0,0,3) 36104#@gui : Grain Type = choice("Gaussian","Uniform","Salt and Pepper","Poisson") 36105#@gui : sep = separator() 36106#@gui : Local Contrast = float(0,0,60) 36107#@gui : Radius = int(16,1,512) 36108#@gui : Contrast Smoothness = float(4,0,10) 36109#@gui : sep = separator() 36110#@gui : Pseudo-Gray Dithering = int(0,0,5) 36111#@gui : Use Maximum Tones = bool(false) 36112#@gui : sep = separator() 36113#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36114#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36115#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36116#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36117#@gui : sep = separator() 36118#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/20/02</i>.</small>") 36119fx_blackandwhite : 36120 repeat $! 36121 l. split_opacity rv to_rgb. s. c # Isolate opacity 36122 *... $1 b... $2% # Red level + smoothness 36123 *.. $3 b.. $4% # Green level + smoothness 36124 *. $5 b. $6% # Blue level + smoothness 36125 +[-3--1] /. {$1+$3+$5} c. 0,255 # (R,G,B) -> B&W 36126 adjust_colors ${7-11},0,255 36127 if $12||$13||$14 36128 100%,100% [-1]x2 # Create noise for shadows, midtones and highlights. 36129 noise... 100,$17 b... $16% n... -$12,$12 # Scaled grain on shadows. 36130 noise.. 100,$17 b.. $16% n.. -$13,$13 # Scaled grain on midtones. 36131 noise. 100,$17 b. $16% n. -$14,$14 # Scaled grain on highlights. 36132 +tones[-4] 3 b[-3--1] $15% # Get smoothed tones. 36133 *[-6,-3] *[-4,-2] *[-2,-1] # Get noisy tones. 36134 +[-4--1] c. 0,255 # Compose them with the B&W image. 36135 fi 36136 rv a c endl mv. 0 done # Re-compose opacity and loop to next image. 36137 if $18 normalize_local $18,$19,$20,2%,1,0,255 fi 36138 if $22 n 0,255 fi 36139 if $21 to_pseudogray $21,1 fi 36140 36141fx_blackandwhite_preview : 36142 gui_split_preview "fx_blackandwhite $*",${-3--1} 36143 36144#@gui B&W Stencil : fx_stencilbw, fx_stencilbw_preview(0) 36145#@gui : Threshold = float(10,0,30) 36146#@gui : Smoothness = float(10,0,30) 36147#@gui : Hue = float(0,0,360) 36148#@gui : Saturation = float(0,0,1) 36149#@gui : sep = separator() 36150#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36151#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36152#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36153#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36154#@gui : sep = separator() 36155#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36156fx_stencilbw : 36157 stencilbw $1,$2 36158 if $3||$4 repeat $! l[$>] split_opacity 36159 /[0] 255 i[0] 100%,100%,1,1,$4 i[0] 100%,100%,1,1,$3 a[0-2] c hsv2rgb[0] 36160 a c endl done fi 36161 36162fx_stencilbw_preview : 36163 gui_split_preview "fx_stencilbw $*",${-3--1} 36164 36165#@gui Charcoal : fx_charcoal, fx_charcoal_preview(0) 36166#@gui : Granularity = int(65,0,800) 36167#@gui : Lowlights Crossover Point = int(70,0,255) 36168#@gui : Highlights Crossover Point = int(170,0,255) 36169#@gui : Boost Contrast = bool(0) 36170#@gui : Resize Image for Optimum Effect = bool(1) 36171#@gui : Add Chalk Highlights = bool(0) 36172#@gui : Minimal Highlights = int(50,0,255) 36173#@gui : Maximal Highlights = int(70,0,255) 36174#@gui : Background Color = color(255,255,255) 36175#@gui : Foreground Color = color(0,0,0) 36176#@gui : Invert Background / Foreground = bool(0) 36177#@gui : sep = separator() 36178#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36179#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36180#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36181#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36182#@gui : sep = separator() 36183#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/17/03</i>.</small>") 36184#@gui : note = note("<small>Inspired from the Charcoal script by <i>micomicon</i> :</small>") 36185#@gui : url = link("http://registry.gimp.org/node/25078") 36186fx_charcoal : 36187 repeat $! l[$>] split_opacity l[0] 36188 compose_channels max 36189 w={w} h={h} 36190 if $5 r. 150%,150%,1,1,6 fi 36191 if $4 equalize. n. 0,255 fi 36192 sharpen {$1*3} cut 0,255 36193 if $6 +ir $7,$8 fi # Add highlights layer if required. 36194 ir[0] $2,$3 36195 if !$15 ==[0] 0 fi 36196 -| 36197 +*[0] $10 +*[0] $11 *[0] $9 36198 a[-3--1] c replace_color 0,0,0,0,0,$12,$13,$14 36199 r $w,$h,1,100%,2 36200 endl a c endl done 36201 36202fx_charcoal_preview : 36203 gui_split_preview "fx_charcoal $*",${-3--1} 36204 36205#@gui Colorize [Interactive] : fx_colorize_interactive, fx_colorize_interactive_preview 36206#@gui : Input Type = _choice("B&W Photograph","Lineart") 36207#@gui : Output Type = _choice{"Colorized Image (1 Layer)","Colors Only (1 Layer)","Image + Colors (2 Layers)", 36208#@gui : "Image + Colors (Multi-Layers)"} 36209#@gui : View Resolution = _choice{1,"Small (Faster)","Medium","High (Slower)","Very High (Even Slower)"} 36210#@gui : 1st Additional Palette (.gpl) = _filein() 36211#@gui : 2nd Additional Palette (.gpl) = _filein() 36212#@gui : Image to Grab Color from (.png) = _filein() 36213#@gui : sep = separator() 36214#@gui : note = note{"<small><b>Description:</b>\n 36215#@gui : This filter allows to quickly colorize a B&W image or lineart. 36216#@gui : Click on the <i>Apply</i> or <i>OK</i> buttons below to open the G'MIC interactive window and 36217#@gui : start adding color control points. When you're done, exit the interactive window: your colored 36218#@gui : result will be transferred back to the host software.\n\n 36219#@gui : If you are not satisfied with the result, <i>Undo it (CTRL+Z)</i>, and click on <i>Apply</i> once 36220#@gui : again to modify your control points defined previously. 36221#@gui : To clear all control points, click on the <i>Reset</i> button above. 36222#@gui : </small>"} 36223#@gui : Clear Control Points = button(0.5) 36224#@gui : Last Image Size = value(0,0) 36225#@gui : Control Points = value(-1) 36226#@gui : sep = separator() 36227#@gui : note = note{"<small><b>Interactions:</b>\n 36228#@gui : Use the following actions in the interactive window to manage your colorization :\n\n 36229#@gui : - <b>Left mouse button</b> creates a new color control point (or move an existing one).\n 36230#@gui : - <b>Right mouse button</b> or key <b>X</b> over a control point deletes it.\n 36231#@gui : - <b>Right mouse button</b> or key <b>P</b> anywhere else picks a color from the image.\n 36232#@gui : - <b>Mouse wheel</b>, or keys <b>CTRL+arrows up/down</b> zoom view in/out.\n 36233#@gui : - <b>CTRL+mouse wheel</b>, <b>SHIFT+wheel</b> or arrow keys move image in zoomed view.\n 36234#@gui : - Key <b>SPACE</b> updates the extrapolated color field.\n 36235#@gui : - Key <b>TAB</b> toggles markers view modes.\n 36236#@gui : - Key <b>BACKSPACE</b> deletes the last control point added.\n 36237#@gui : - Key <b>PAGE UP</b> increases image contrast.\n 36238#@gui : - Key <b>PAGE DOWN</b> decreases image contrast.\n 36239#@gui : - Key <b>R</b> enters/exits color replace mode.\n 36240#@gui : - Keys <b>CTRL+D</b> increase window size.\n 36241#@gui : - Keys <b>CTRL+C</b> decrease window size.\n 36242#@gui : - Keys <b>CTRL+R</b> resets window size.\n 36243#@gui : - Keys <b>ESC</b>, <b>Q</b> or <b>ENTER</b> exit the interactive window. 36244#@gui : </small>"} 36245#@gui : sep = separator() 36246#@gui : note = note("<small>You can find more information on how to use this filter here :</small>") 36247#@gui : url = link("David Revoy's G'MIC Colorization Page", 36248#@gui : "http://www.davidrevoy.com/article240/gmic-line-art-colorization") 36249#@gui : sep = separator() 36250#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/12/07</i>.</small>") 36251fx_colorize_interactive : skip "${4=},${5=},${6=}" 36252 N=$! nm={n} 36253 resolution={arg(1+$3,512,1024,2048,0)} 36254 nm "[G"{`39`}"MIC] Colorize" 36255 if [$9][0]==-1" || "[$8]!=[w,h] _gui_control_points= else _gui_control_points=$9 fi 36256 N=$! 36257 36258 arg_palette1=0 l[] 36259 0 nm. "$4" ext={x} rm 36260 if same(['$ext'],'gpl',-1,0) 36261 input_gpl "$4" arg_palette1=1 fi 36262 onfail rm endl 36263 if $arg_palette1 arg_palette1=[{$!-1}] fi 36264 36265 arg_palette2=0 l[] 36266 0 nm. "$5" ext={x} rm 36267 if same(['$ext'],'gpl',-1,0) 36268 input_gpl "$5" arg_palette2=1 fi 36269 onfail rm endl 36270 if $arg_palette2 arg_palette2=[{$!-1}] fi 36271 36272 arg_grabber=0 l[] 36273 0 nm. "$6" ext={x} rm 36274 i "$6" to_rgb arg_grabber=1 36275 onfail rm endl 36276 if $arg_grabber arg_grabber=[{$!-1}] fi 36277 36278 repeat $N 36279 status=${x_colorize[$>]\ $1,$resolution,$2,$arg_palette1,$arg_palette2,$arg_grabber} 36280 done 36281 k[0-{$N-1}] 36282 36283 if $2==1 repeat $! l[$<] # Output : colors only (1 layer). 36284 channels {s-3},{s-1} 36285 endl done 36286 elif $2>=2 repeat $! l[$<] # Output : Lineart + Colors (2 layers). 36287 +channels {s-3},{s-1} channels.. 0,{0,s-4} 36288 endl done 36289 if $2>=3 split_colors[1] 0,256,8 fi # Split colors into layers. 36290 fi 36291 nm $nm 36292 if !narg($status) status=-1 fi 36293 u \{$1\}\{$2\}\{$3\}\{"$4"\}\{"$5"\}\{"$6"\}\{0\}\{{w},{h}\}\{$status\} 36294 36295fx_colorize_interactive_preview : skip "${4=},${5=},${6=}" 36296 if $7 # Clear control points. 36297 gui_print_preview "No preview\n available",,"(Control points cleared)" 36298 u \{$1\}\{$2\}\{$3\}\{"$4"\}\{"$5"\}\{"$6"\}\{0\}\{{w},{h}\}\{-1\} 36299 else gui_no_preview , 36300 fi 36301 36302#@gui Colorize [Photographs] : fx_recolorize, fx_recolorize_preview(1) 36303#@gui : Smoothness = int(2,0,6) 36304#@gui : Anisotropy = float(0.2,0,1) 36305#@gui : Output Mode = choice("Merge Brightness / Colors","Split Brightness / Colors") 36306#@gui : sep = separator() 36307#@gui : note = note{"<small><b>Note:</b> This filter needs two layers to work properly. 36308#@gui : The bottom layer must be a B&W image, while the top layer contains color patches that will 36309#@gui : be extrapolated in a smart way (edge-directed) to fill the entire image. At the end, 36310#@gui : you get a completely recolored image.</small>"} 36311#@gui : sep = separator() 36312#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/16/01</i>.</small>") 36313fx_recolorize : 36314 repeat int($!/2) 36315 if $3 s=$>,{$>+1} else s={2*$>},{2*$>+1} fi 36316 l[$s] rv[0,1] 36317 channels[0] 0 to_rgb.. # Convert to pure gray. 36318 to_rgba. split_opacity. !=. 0 # Retrieve mask of color patches. 36319 srgb2rgb[-3,-2] rgb2lab8[-3,-2] channels... 0 channels.. 1,2 # Now, list is [0]=lightness / [1]=chroma / [2]=mask. 36320 +.. 1 *.. . +gradient_norm... *. -1 watershed... . rm. -.. 1 # Get first estimate for the color interpolation. 36321 +diffusiontensors... $2,1,0.5,0.5 ==.. 0 *. .. rm.. 36322 smooth.. .,{$1*80},0.8,60 rm. 36323 a[-2,-1] c lab82rgb. rgb2srgb. 36324 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 36325 endl 36326 done 36327 36328fx_recolorize_preview : 36329 fx_recolorize $* a x 36330 36331#@gui Colorize [with Colormap] : fx_bwrecolorize, fx_bwrecolorize_preview 36332#@gui : Brightness (%) = float(0,-100,100) 36333#@gui : Contrast (%) = float(0,-100,100) 36334#@gui : Gamma (%) = float(0,-100,100) 36335#@gui : Normalize Input = bool(0) 36336#@gui : sep = separator() 36337#@gui : Gradient Preset = choice("User-Defined","Black to White","White to Black","Sepia","Solarize") 36338#@gui : Interpolation Type = choice(1,"Nearest","Linear","Cubic","Lanczos") 36339#@gui : Preserve Initial Brightness = bool(0) 36340#@gui : sep = separator() 36341#@gui : note = note("<small><u>User-defined gradient :</u></small>") 36342#@gui : Number of Tones = int(5,2,8) 36343#@gui : 1st Tone = color(0,0,0,255) 36344#@gui : 2nd Tone = color(43,25,55,255) 36345#@gui : 3rd Tone = color(158,137,189,255) 36346#@gui : 4th Tone = color(224,191,228,255) 36347#@gui : 5th Tone = color(255,255,255,255) 36348#@gui : 6th Tone = color(255,255,255,255) 36349#@gui : 7th Tone = color(255,255,255,255) 36350#@gui : 8th Tone = color(255,255,255,255) 36351#@gui : sep = separator() 36352#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36353#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36354#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36355#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36356#@gui : sep = separator() 36357#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36358fx_bwrecolorize : 36359 remove_opacity 36360 if $4 n 0,255 fi 36361 if $5==0 # User-defined gradient 36362 (${9--2}) r. 4,$8,1,1,-1 permute. yzcx 36363 elif $5==1 # Black to white 36364 (0,255^0,255^0,255^255,255) 36365 elif $5==2 # White to black 36366 (255,0^255,0^255,0^255,255) 36367 elif $5==3 # Sepia 36368 (0,44,115,143,196,244^0,20,84,119,184,235^0,5,44,73,144,200^255,255,255,255,255,255) 36369 else # Solarize 36370 (0,359^1,1^1,1^255,255) r. 256,1,1,4,3 sh. 0,2 hsv2rgb. rm. 36371 fi 36372 if $6==0 r. 256,1,1,4,1 36373 elif $6==1 r. 256,1,1,4,3 36374 elif $6==2 r. 256,1,1,4,5 c. 0,255 36375 else r. 256,1,1,4,6 36376 fi 36377 if $7==1 sh. 0,2 rgb2hsv. sh. 2 f. x/w hsv2rgb.. rm[-2,-1] fi 36378 l[^-1] luminance adjust_colors ${1-3} endl map[^-1] . rm. 36379 36380fx_bwrecolorize_preview : 36381 gui_split_preview "fx_bwrecolorize ${^0}",${-3--1} 36382 36383#@gui Colorize Lineart [Auto-Fill] : fx_autofill_lineart, fx_autofill_lineart_preview(0) 36384#@gui : Contour Threshold (%) = float(90,0,100) 36385#@gui : Contour Normalization = bool(1) 36386#@gui : Minimal Region Area = int(8,0,256) 36387#@gui : Tolerance to Gaps = int(0,0,10) 36388#@gui : Preview Type = choice("Lineart + Colors","Colors Only") 36389#@gui : sep = separator() 36390#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/12/11</i>.</small>") 36391fx_autofill_lineart : 36392 repeat $! l[$>] nm=${-gui_layer_name} 36393 36394 # Format input lineart to expected format. 36395 is_alpha={s==2||s==4} 36396 if $is_alpha sh 100% is_alpha={im<128&&iM>128} rm. fi # Check is alpha-channel contains lineart 36397 if $is_alpha +channels 100% negate. 36398 else +norm fi 36399 n. 0,255 36400 l. 36401 36402 # Start multi-scale filling. 36403 repeat 1+$4 36404 fact={2^-$<} 36405 nw={0,max(1,round(w*$fact))} 36406 nh={0,max(1,round(h*$fact))} 36407 +r[0] $nw,$nh,1,1,2 if $2 normalize_local. , fi +>=. {min(99.5,$1)}% 36408 36409 if $colors 36410 scale2x[colors] r[colors] .,1 *[colors,-1] rv[-2,-1] 36411 fi 36412 36413 label_fg. 0,1 b.. 0.8 watershed. .. rm.. nm. colors 36414 done 36415 36416 # Inpaint regions that are too small. 36417 +area. 0,1 label_maxarea={"P=[xM,yM];i(#-2,P)-1"} 36418 if $3>1 36419 >. {$3*sqrt($3)} *[-2,-1] 36420 b.. 0.8 watershed. .. 36421 else 36422 rm. 36423 fi 36424 rm.. 36425 36426 # Colorize regions. 36427 N={iM} 36428 if $N 36429 -. 1 36430 srand 0 {iM+1},1,1,3,">[j(-1) + u(135,225),u(0,0.7),u(0.4,0.9)]" 36431 hsv2rgb. round. point. $label_maxarea,0,0,1,255 36432 map.. . rm. 36433 fi 36434 endl 36435 36436 # Format output layers. 36437 if !$is_alpha gui_set_layer_mode.. multiply fi 36438 gui_set_layer_name. $nm" [colors]" 36439 endl done 36440 36441fx_autofill_lineart_preview : 36442 repeat $! l[$>] 36443 fx_autofill_lineart ${1-4} 36444 if $5 k. else rv blend multiply fi 36445 endl done 36446 36447#@gui Colorize Lineart [Smart Coloring] : fx_colorize_lineart_smart, fx_colorize_lineart_smart_preview(0) 36448#@gui : Colorize Mode = choice("Generate Random-Colors Layer","Extrapolate Color Spots on Transparent Top Layer", 36449#@gui : "Auto-Clean Bottom Color Layer") 36450#@gui : sep = separator() 36451#@gui : note = note{"<small><b>Global geometry parameters:</b></small>"} 36452#@gui : Contour Detection (%) = float(95,0,100) 36453#@gui : Discard Contour Guides = bool(0) 36454#@gui : note = note{"<small>Add strokes with a saturated color having value 255 (e.g. pure red) on your lineart 36455#@gui : allows to guide the colorization algorithm with virtual contours.</small>"} 36456#@gui : Output Region Delimiters = _bool(0) 36457#@gui : sep = separator() 36458#@gui : note = note{"<small><b>For <i>Random colors</i> mode only:</b></small>"} 36459#@gui : Make Hue Depends on Region Size = float(1,0,1) 36460#@gui : Maximal Color Saturation = int(24,0,255) 36461#@gui : Minimal Color Intensity = int(200,0,255) 36462#@gui : sep = separator() 36463#@gui : note = note{"<small><b>For <i>color spots</i> mode only:</b></small>"} 36464#@gui : Color Shading (%) = int(0,0,100) 36465#@gui : sep = separator() 36466#@gui : note = note{"<small><b>Connection parameters:</b></small>"} 36467#@gui : End Point Rate (%) = float(75,0,100) 36468#@gui : End Point Connectivity = int(2,1,5) 36469#@gui : Spline Max Length (px) = float(60,0,256) 36470#@gui : Segment Max Length (px) = float(20,0,256) 36471#@gui : Spline Max Angle (deg) = float(90,0,180) 36472#@gui : Spline Roundness = float(1,0,2) 36473#@gui : Minimal Region Area = float(10,0,100) 36474#@gui : Allow Self Intersections = bool(1) 36475#@gui : sep = separator() 36476#@gui : Preview Type = choice(0,"Colored geometry","Colored regions","Colored lineart") 36477#@gui : sep = separator() 36478#@gui : note = note("<small>Authors: <i>David Tschumperlé</i>, <i>Sébastien Fourey</i> and 36479#@gui : <i>David Revoy</i>. Latest Update: <i>2018/11/09</i>.</small>") 36480fx_colorize_lineart_smart : 36481 _fx_colorize_lineart_smart $*,-1 round 36482 36483fx_colorize_lineart_smart_preview : 36484 if $1==1" && "$!<2 gui_warning_preview "A top layer with color spots is missing, for this colorization mode." return 36485 elif $1==2" && "$!<2 gui_warning_preview "A bottom color layer is missing, for this colorization mode." return 36486 fi 36487 _fx_colorize_lineart_smart ${1-3},0,${5--1} 36488 36489_fx_colorize_lineart_smart : 36490 if $1==1" && "$!<2 error "A top layer with color strokes is missing, for this colorization mode." 36491 elif $1==2" && "$!<2 error "A bottom color layer is missing, for this colorization mode." 36492 fi 36493 min_color_area={$15^2} 36494 36495 repeat $1?1:$! inds=${arg\ 1+!!$1,$<,0--1} l[$inds] 36496 36497 ind_lineart={$1==1?1:0} 36498 nm=${gui_layer_name[$ind_lineart]} nm[$ind_lineart] lineart 36499 36500 if $!>1 ind_colors={$1==1?0:1} nmc={$ind_colors,n} nm[$ind_colors] colors fi 36501 if $!>=3 rm[2--1] fi # Delete old color and added contour layers if any 36502 36503 # Constrain input lineart to be a binary, single channel image. 36504 [lineart] 36505 is_alpha={s==2||s==4} 36506 if $is_alpha sh. 100% is_alpha={iM-im>64} rm. fi 36507 if $is_alpha channels. 100% 36508 else luminance. negate. fi 36509 >. {255*(1-$2%)} 36510 nm. strokes 36511 36512 # Retrieve closed binary shape. 36513 _keep_keycoords={$-1==0} 36514 [strokes] close_binary. ${9-14},$min_color_area,$16 nm. new_strokes 36515 36516 if $-1==0 # Render estimated geometry 36517 +negate[strokes] *. 255 to_rgb. 36518 +-[new_strokes] [strokes] dilate. 2 36519 100%,100%,1,3,[0,128,255] j... .,0,0,0,0,1,.. rm[-2,-1] 36520 if narg($keycoords) f[keycoords] "ellipse(#-1,(I)[0,2],3,3,0,1,[255,0,0]);I" rm[keycoords] fi 36521 nm. geometry 36522 fi 36523 36524 # Label color regions and inpaint strokes. 36525 if $1==1 # Mode: Color spots-guided colorization 36526 to_rgba[$colors] [colors],[colors] 36527 f[colors] "i(#-1) = A<255?0:norm(R,G+0.3,B+0.6);I" 36528 label_fg. 0 {1+iM},1,1,{colors,s+1} 36529 f.. ">I[#-1,i]+=[ I(#"$colors"),1 ];I" 36530 s. c,{-s+1} /[-2,-1] 36531 +l[new_strokes] * -1 + 1 +b 1% b.. 1 min endl 36532 watershed... .,0 rm. map.. . rm. 36533 36534 if !$8 rm[strokes] # No color shading 36535 else # Shade colors 36536 j[strokes] [new_strokes] distance[strokes] 0 *[strokes] -1 36537 eq[new_strokes] 0 label_fg[new_strokes] 0,0 36538 if $min_color_area +area_fg[new_strokes] 0,0 >. $min_color_area *[new_strokes,-1] fi 36539 watershed[new_strokes] [strokes],0 rm[strokes] 36540 srgb2rgb. guided. [new_strokes],{1+$8/5},0 rgb2srgb. 36541 fi 36542 rm[new_strokes] 36543 nm. new_colors 36544 36545 elif $1==2 # Mode: Clean color layer 36546 j[strokes] [new_strokes] distance[strokes] 0 *[strokes] -1 36547 eq[new_strokes] 0 label_fg[new_strokes] 0,0 36548 if $min_color_area +area_fg[new_strokes] 0,0 xy_bg={[xM,yM]} >. $min_color_area *[new_strokes,-1] fi 36549 watershed[new_strokes] [strokes],0 rm[strokes] 36550 to_color[colors] sh[colors] 0,2 rgb2hsv8. rm. blend[colors,new_strokes] shapemedian sh[colors] 0,2 hsv82rgb. rm. 36551 nm[colors] new_colors 36552 36553 else # Mode: Random colorization 36554 j[strokes] [new_strokes] distance[strokes] 0 *[strokes] -1 36555 eq[new_strokes] 0 label_fg[new_strokes] 0,0 36556 if $min_color_area +area_fg[new_strokes] 0,0 xy_bg={[xM,yM]} >. $min_color_area *[new_strokes,-1] fi 36557 watershed[new_strokes] [strokes],0 rm[strokes] 36558 label[new_strokes] 0,0 36559 +histogram[new_strokes] {new_strokes,[iM+1,0,iM]} equalize. 1024 n. 0,240 36560 ind_bg={xM} 36561 channels. 0,2 srand 0 36562 f. "[i,u(1,max(3,$6))/255,u(min(252,$7),255)/255]" 36563 . sh. 0 rand. 0,360 rm. 36564 hsi2rgb[-2,-1] *.. $5 *. {1-$5} +[-2,-1] round. 36565 point. $ind_bg,0,0,1,255 point. 0,0,0,1,255 36566 36567 map[new_strokes] . rm. 36568 nm[new_strokes] new_colors 36569 fi 36570 36571 # Final rendering 36572 ind_lineart=$lineart 36573 ind_colors=$new_colors 36574 36575 if $4 # Output region delimiters 36576 100%,100%,1,1,"const boundary = 1; 36577 J(#"$new_colors",1)!=I(#"$new_colors") || J(#"$new_colors",0,1)!=I(#"$new_colors")" 36578 *. 255 channels. -3,0 sh. 0,2 fc. 255,0,0 rm. 36579 gui_set_layer_name. $nm" [region delimiters]" 36580 mv. {$lineart+1} 36581 fi 36582 if !narg($nmc) gui_set_layer_name[$ind_colors] $nm" [colors]" fi 36583 gui_set_layer_name[$ind_lineart] $nm 36584 36585 if $-1==-1 # Rendering : Lineart and color layers 36586 if !$is_alpha gui_set_layer_mode[$ind_lineart] multiply fi 36587 if $3 l[{$1==1?1:0}] # Discard contour guides 36588 if $is_alpha 36589 100%,100%,1,3,255 blend. [0],alpha,1 rgb2hsv. channels. 2 *. 255 negate. 36590 channels.. 0,{0,s-2} s={0,s} luminance[0] to_colormode[0] $s a c 36591 else 36592 s={s} to_rgb rgb2hsv channels 2 * 255 to_colormode $s 36593 fi 36594 endl fi 36595 36596 elif $-1==0 # Preview : Colored geometry 36597 if $is_alpha channels[$ind_lineart] 100% negate[$ind_lineart] fi to_rgb[$ind_lineart] 36598 n[$ind_lineart] 180,255 36599 blend[$ind_lineart,$ind_colors] multiply 36600 +select_color[geometry] 0,255,255,255 ==. 0 j[$ind_lineart] [geometry],0,0,0,0,1,. k[$ind_lineart] 36601 elif $-1==1 # Preview : Colored regions 36602 k[$ind_colors] 36603 else # Preview : Colored lineart 36604 if $is_alpha channels[$ind_lineart] 100% negate[$ind_lineart] fi to_rgb[$ind_lineart] 36605 if $3 l[$ind_lineart] s={s} to_rgb rgb2hsv channels 2 * 255 to_colormode $s endl fi 36606 blend[$ind_lineart,$ind_colors] multiply k[$ind_lineart] 36607 fi 36608 36609 endl done 36610 36611#@gui Colorize Lineart [Propagation] : fx_colorize_lineart, fx_colorize_lineart_preview(1) 36612#@gui : note = note("<b>Layers ordering:</b>") 36613#@gui : Input Layers = choice{0,"Color Spots + Lineart","Lineart + Color Spots", 36614#@gui : "Color Spots + Extrapolated Colors + Lineart","Lineart + Color Spots + Extrapolated Colors"} 36615#@gui : Output Layers = _choice{1,"Single (Merged)","Extrapolated Colors + Lineart", 36616#@gui : "Lineart + Extrapolated Colors","Color Spots + Extrapolated Colors + Lineart", 36617#@gui : "Lineart + Color Spots + Extrapolated Colors"} 36618#@gui : Extrapolate Colors As = choice("One Layer","Two Layers","Three Layers","Four Layers","Five Layers", 36619#@gui : "Six Layers","Seven Layers","Eight Layers","Nine Layers","Ten Layers","One Layer per Single Color", 36620#@gui : "One Layer per Single Region") 36621#@gui : sep = separator() 36622#@gui : Smoothness = float(0.05,0,1) 36623#@gui : sep = separator() 36624#@gui : note = note{"<small><b>Note:</b> You probably need to select <i>All</i> for the <i>Input layers</i> option 36625#@gui : on the left.\n 36626#@gui : <i>Color Spots</i> = your layer with color indications.\n 36627#@gui : <i>Lineart</i> = your layer with line-art (B&W or transparent).\n 36628#@gui : <i>Extrapolated Colors</i> = the G'MIC generated layer with flat colors.\n\n 36629#@gui : <b>Warnings:</b> 36630#@gui : \n - Do not rely too much on the preview, it is probably not accurate ! 36631#@gui : \n - Activate option <i>Extrapolate color as one layer per single color/region</i> only if you have 36632#@gui : <i>a lot</i> of available memory ! 36633#@gui : </small>"} 36634#@gui : sep = separator() 36635#@gui : url = link("Click here for a detailed description of this filter.",\ 36636# "http://www.gimpchat.com/viewtopic.php?f=28&t=7567") 36637#@gui : sep = separator() 36638#@gui : note = note("<small>Authors: <i>David Tschumperlé</i>, <i>Timothée Giet</i> and <i>David Revoy</i>. 36639#@gui : Latest Update: <i>2013/19/06</i>.</small>") 36640fx_colorize_lineart : 36641 if $!<2 return fi 36642 if $1<2 selection=0,1 else selection=0,1,2 fi 36643 l[$selection] 36644 36645 # Format input layers. 36646 if $1==0 # Color strokes + drawing 36647 elif $1==1 rv # Drawing + color strokes 36648 elif $1==2 rm[1] # Color strokes + extrapolated colors + drawing 36649 elif $1==3 rm[2] rv # Drawing + color strokes + extrapolated colors. 36650 fi 36651 36652 # Here we have only 'color strokes + drawing' -> process. 36653 +to_rgba[0] split_opacity. +.. 1 !=. 0 *[-2,-1] # Map of color labels to spread. 36654 +norm[1] n. 0,1 +histogram. 2,0,1 36655 if i(0)>i(1) *.. -1 +.. 1 fi rm. # Determine color model of the drawing. 36656 b. $4% watershed.. . rm. # Priority map. 36657 -. 1 36658 # Here we have 'color strokes + drawing + extrapolated colors'. 36659 36660 # Format output layers. 36661 if $2==0 rm[0] rv blend[0,1] multiply ind=-1 36662 elif $2==1 rm[0] rv ind=0 36663 elif $2==2 rm[0] ind=1 36664 elif $2==3 rv[1,2] ind=1 36665 elif $2==4 rv[0,1] ind=2 36666 fi 36667 36668 # Separate extrapolated colors as multiple layers. 36669 if $3" && "$ind>=0 l[$ind] 36670 +mix_channels (65536,256,1) 36671 if $3==10 do # Split by colors. 36672 iM={1,iM} 36673 if $iM>=0 36674 +==[1] $iM area={is} replace[1] $iM,-1 36675 +r. 100%,100%,1,3 *. [0] 36676 rv[-2,-1] *. 255 a[-2,-1] c nm. $area 36677 fi 36678 while $iM>=0 else # Split by disconnected regions. 36679 label. 36680 if $3<10 %. {$3+1} fi 36681 repeat iM+1 +==[1] $< area={is} +r. 100%,100%,1,[0] *. [0] rv[-2,-1] *. 255 a[-2,-1] c nm. $area done 36682 fi 36683 rm[0,1] 36684 sort_list +,n 36685 endl fi 36686 36687 endl 36688 36689fx_colorize_lineart_preview : 36690 fx_colorize_lineart $1,0,$3,$4 36691 36692#@gui Dithering : fx_ditheredbw, fx_ditheredbw_preview(0) 36693#@gui : Brightness (%) = float(0,-100,100) 36694#@gui : Contrast (%) = float(0,-100,100) 36695#@gui : Gamma (%) = float(0,-100,100) 36696#@gui : Hue = float(0,0,360) 36697#@gui : Saturation (%) = float(0,0,100) 36698#@gui : Smoothness = float(0,0,10) 36699#@gui : sep = separator() 36700#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36701#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36702#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36703#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36704#@gui : sep = separator() 36705#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 36706fx_ditheredbw : 36707 repeat $! l[$>] split_opacity l[0] 36708 luminance adjust_colors ${1-3} b $6 36709 ditheredbw 36710 if $4" || "$5 / 255 i[0] 100%,100%,1,2 fc[0] $4,{$5%} a c hsv2rgb fi 36711 endl a c endl done 36712 36713fx_ditheredbw_preview : 36714 gui_split_preview "fx_ditheredbw $*",${-3--1} 36715 36716#@gui Engrave : fx_engrave, fx_engrave_preview(0) 36717#@gui : note = note("<small><b>Black & White foreground:</b></small>") 36718#@gui : Radius = float(0.5,0,2) 36719#@gui : Density = float(50,0,200) 36720#@gui : Edges = float(0,0,10) 36721#@gui : Coherence = float(8,0,40) 36722#@gui : Threshold (%) = float(40,0,100) 36723#@gui : Minimal Area = int(0,-256,256) 36724#@gui : Flat Regions Removal = float(0,0,10) 36725#@gui : sep = separator() 36726#@gui : note = note("<small><b>Color background:</b></small>") 36727#@gui : Add Color Background = bool() 36728#@gui : Quantization = float(10,0,40) 36729#@gui : Shading = int(1,0,5) 36730#@gui : Hue = float(0,-180,180) 36731#@gui : Saturation (%) = float(0,-100,100) 36732#@gui : Lightness (%) = float(0,-100,100) 36733#@gui : sep = separator() 36734#@gui : Anti-Aliasing = choice(1,"Disabled","x1.5","x2","x3") 36735#@gui : sep = separator() 36736#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36737#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36738#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36739#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36740#@gui : sep = separator() 36741#@gui : note = note("<small>Authors: <i>Lyle Kroll</i> and <i>David Tschumperlé</i>. 36742#@gui : Latest Update: <i>03/13/2015</i>.</small>") 36743fx_engrave : 36744 f={arg(1+$14,1,1.5,2,3)} 36745 r={$f*(0.2+$1)} 36746 repeat $! l[$<] 36747 nm=${-gui_layer_name} pos=${-gui_layer_pos} 36748 if $8 [0] fi # Keep copy for color background. 36749 l[0] split_opacity l[0] 36750 wh={w},{h} 36751 norm 36752 if $14 r {100*$f}%,{100*$f}%,1,1,3 fi 36753 if $7>0 [0] fi # Keep copy for flat regions removal. 36754 l[0] 36755 amount={(0.5+$2)^2} 36756 repeat 5 b $r unsharp $r,{1+$2} c 0,255 done 36757 smooth 100,0.1,1,{$f*$3},{$f*$4} 36758 >= {100-$5}% 36759 endl 36760 if $7>0 # Flat region removal. 36761 gradient_norm[1] b[1] $3 <[1] $7 max[0,1] 36762 fi 36763 if $6<0 area_fg 0,0 > {$f*$6*$6} 36764 elif $6>0 == 0 area_fg 0,0 > {$f*$6*$6} == 0 36765 fi 36766 * 255 36767 if $14 r $wh,1,1,2 fi 36768 endl a c endl 36769 36770 # Process color background. 36771 if $!>1 36772 l[1] split_opacity l[0] 36773 f={arg(1+$14,1,1.5,2,3)} 36774 if $14 r {100*$f}%,{100*$f}%,1,100%,3 fi 36775 b {$f*$9} segment_watershed 5 36776 if $14 r $wh,1,100%,2 fi 36777 repeat $10 guided 10,{$10*80} done 36778 rgb2hsv s c +... $11 +.. {$12%} +. $13% a c hsv2rgb 36779 endl a c endl 36780 nm[0] mode(darken),name($nm),pos($pos) 36781 nm[1] name($nm" [colors]"),pos($pos) 36782 fi 36783 36784 endl done 36785 36786fx_engrave_preview : 36787 repeat $! l[$<] 36788 gui_split_preview "nm foo fx_engrave $* gui_merge_layers",${-3--1} 36789 endl done 36790 36791#@gui Freaky B&W : fx_freaky_bw, fx_freaky_bw_preview 36792#@gui : Strength (%) = float(90,0,100) 36793#@gui : Oddness (%) = float(20,0,100) 36794#@gui : Brightness (%) = float(0,-100,100) 36795#@gui : Contrast (%) = float(0,-100,100) 36796#@gui : Gamma (%) = float(0,-100,100) 36797#@gui : sep = separator() 36798#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36799#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36800#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36801#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36802#@gui : sep = separator() 36803#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/30/09</i>.</small>") 36804fx_freaky_bw : 36805 repeat $! l[$>] split_opacity l[0] 36806 to_rgb 36807 36808 # Estimate gradient field of B&W result. 36809 +expand_xy 1,0 channels. 0,4 36810 f. ">if (c!=4,i, 36811 Rx = i(x+1,y,0,0) - i(x,y,0,0); 36812 Ry = i(x,y+1,0,0) - i(x,y,0,0); 36813 Rn = Rx^2 + Ry^2; 36814 Gx = i(x+1,y,0,1) - i(x,y,0,1); 36815 Gy = i(x,y+1,0,1) - i(x,y,0,1); 36816 Gn = Gx^2 + Gy^2; 36817 Bx = i(x+1,y,0,2) - i(x,y,0,2); 36818 By = i(x,y+1,0,2) - i(x,y,0,2); 36819 Bn = Bx^2 + By^2; 36820 n = 1e-5 + max(Rn,Gn,Bn)^"{$2%}"; 36821 val = 0; 36822 if (Rn>=Gn && Rn>=Bn, 36823 i(x,y,0,3) = Rx/n; val=Ry/n, 36824 if (Gn>=Rn && Gn>=Bn, 36825 i(x,y,0,3) = Gx/n; val=Gy/n, 36826 i(x,y,0,3) = Bx/n; val=By/n)); 36827 val 36828 )" 36829 channels. 3,4 36830 luminance[0] ia={0,ia} 36831 36832 # Estimate laplacian of final image and invert it. 36833 s. c 36834 f.. "i - i(x-1,y,0,0)" 36835 f. "i - i(x,y-1,0,0)" 36836 +[-2,-1] 36837 ilaplacian. 0 36838 shrink_xy. 1 +. $ia n. 0,255 36839 36840 # Merge result with original color image. 36841 j[0] [1],0,0,0,0,{$1%} rm. 36842 adjust_colors ${3-5} 36843 endl a c endl done 36844 36845fx_freaky_bw_preview : 36846 gui_split_preview "fx_freaky_bw $*",${-3--1} 36847 36848#@gui Ink Wash : fx_ink_wash, fx_ink_wash(0) 36849#@gui : note = note("Ink wash controls") 36850#@gui : Size = float(0.14,0,4) 36851#@gui : Amplitude = float(23,0,200) 36852#@gui : sep = separator() 36853#@gui : note = note("Check if you wish visual control on this step") 36854#@gui : Skip All Other Steps = bool(false) 36855#@gui : note = note ("UNcheck to reactivate the other controls") 36856#@gui : sep = separator() 36857#@gui : Smoother Sharpness = float(0.5,0,2) 36858#@gui : Smoother Edge Protection = float(0.54,0,1) 36859#@gui : Smoother Softness = float(2.25,0,10) 36860#@gui : sep = separator() 36861#@gui : Stretch Contrast = choice("None","Automatic","Automatic & Contrast Mask","Manual Controls") 36862#@gui : note = note ("To activate the sliders below chose 'Manual Controls'") 36863#@gui : sep = separator() 36864#@gui : LN Amplitude = float(2,0,60) 36865#@gui : LN Size = float(6,0,64) 36866#@gui : LN Neightborhood-Smoothness = float(5,0,40) 36867#@gui : LN Average-Smoothness = float(20,0,40) 36868#@gui : sep = separator() 36869#@gui : note = note("<small>Author: <i>PhotoComiX</i>. 36870#@gui : Latest Update: <i>2011/05/04</i>.</small>") 36871#@gui : url = link(0,"Forum thread about the filter discussion","http://gimpchat.com/viewtopic.php?f=10&t=914") 36872fx_ink_wash : 36873 repeat $! l[$>] split_opacity l[0] 36874 fx_pencilbw. $1,$2,0,0,0 36875 if $3==1 continue 36876 elif $3==0 fx_smooth_anisotropic. 60,$4,$5,$6,1.1,0.8,30,2,0,1,1,0,1,16 36877 fi 36878 if $7==1 normalize_local. 2,6,5,24,1,0,255 36879 elif $7==2 normalize_local. 2,6,5,24,1,0,255 fx_contrast_swm 2,0,0.512 36880 elif $7==3 fx_normalize_local. $8,$9,$10,$11,1,3,0 36881 fi 36882 endl a c endl done 36883 36884#@gui Pencil : fx_pencilbw, fx_pencilbw_preview(0) 36885#@gui : Size = float(0.3,0,5) 36886#@gui : Amplitude = float(60,0,200) 36887#@gui : Hue = float(0,0,360) 36888#@gui : Saturation = float(0,0,1) 36889#@gui : sep = separator() 36890#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36891#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36892#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36893#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36894#@gui : sep = separator() 36895#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/05/03</i>.</small>") 36896fx_pencilbw : 36897 pencilbw $1,$2 36898 if $3" || "$4 repeat $! l[$>] split_opacity 36899 /[0] 255 i[0] 100%,100%,1,1,$4 i[0] 100%,100%,1,1,$3 a[0-2] c hsv2rgb[0] 36900 a c endl done fi 36901 36902fx_pencilbw_preview : 36903 gui_split_preview "fx_pencilbw $*",${-3--1} 36904 36905#@gui Pencil Portrait : fx_pencil_portraitbw, fx_pencil_portraitbw_preview(0) 36906#@gui : Stroke Length = float(30,0,500) 36907#@gui : Stroke Angle = float(120,0,180) 36908#@gui : Contour Threshold = float(1,0,10) 36909#@gui : Opacity = float(0.5,0,1) 36910#@gui : Color = color(144,79,21) 36911#@gui : sep = separator() 36912#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36913#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36914#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36915#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36916#@gui : sep = separator() 36917#@gui : note = note("<small>Authors: <i>Jamac4k</i> and <i>David Tschumperlé</i>. 36918#@gui : Latest Update: <i>2015/29/06</i>.</small>") 36919fx_pencil_portraitbw : 36920 repeat $! l[$>] split_opacity l[0] 36921 +b 2% 36922 +blend divide rm.. luminance. 36923 fx_ink_wash.. 0,167,0,0.5,0.54,2.25,0,2,6,5,20 36924 +fx_hardsketchbw. 80,32,1.89,0.21,31.46,0,0 36925 +fx_sketchbw.. 1,$2,180,$1,$3,0.03,0,0.6,0.1,0.6,0.25,1,0,1,0 36926 blend[0,1] darken 36927 blend[0,1] multiply,0.5 36928 blend[0,1] lighten,$4 36929 normalize_local , 36930 to_rgb +fc ${5-7} blend softlight 36931 endl a c endl done 36932 36933fx_pencil_portraitbw_preview : 36934 gui_split_preview "fx_pencil_portraitbw $*",${-3--1} 36935 36936#@gui Stamp : fx_stamp, fx_stamp_preview(0) 36937#@gui : Auto-Threshold = bool(1) 36938#@gui : Threshold = int(50,0,100) 36939#@gui : Smoothness = float(0,0,10) 36940#@gui : Sharpening = float(0,0,30) 36941#@gui : Grain = float(0,0,100) 36942#@gui : Negative = bool() 36943#@gui : Anti-Aliasing = bool(1) 36944#@gui : sep = separator() 36945#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36946#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36947#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36948#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36949#@gui : sep = separator() 36950#@gui : note = note("<small>Authors: <i>Antaron</i>, <i>Mahvin</i> and <i>David Tschumperlé</i>. 36951#@gui : Latest Update: <i>2015/16/03</i>.</small>") 36952fx_stamp : 36953 repeat $! l[$>] split_opacity l[0] 36954 wh={w},{h} 36955 norm 36956 if $7 r 150%,150%,1,1,3 fi 36957 noise $5 36958 if $1 otsu 256 else >= $2% fi 36959 b {if($7,1.5,1)*$3},0 sharpen $4 n 0,255 36960 apply_curve 1,0,0,101,33,170,229,255,255 36961 if $7 r $wh,1,1,2 fi 36962 if $6 negate fi 36963 endl a c endl done 36964 36965fx_stamp_preview : 36966 gui_split_preview "fx_stamp $*",${-3--1} 36967 36968 36969#@gui ____<b>Colors</b> 36970#---------------------- 36971 36972#@gui Abstraction : fx_color_abstraction, fx_color_abstraction_preview(0) 36973#@gui : Smoothness = float(1,0,10) 36974#@gui : Levels = int(10,2,100) 36975#@gui : Contrast = float(0.2,0.01,1) 36976#@gui : sep = separator() 36977#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 36978#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 36979#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 36980#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 36981#@gui : sep = separator() 36982#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/19/10</i>.</small>") 36983fx_color_abstraction : 36984 repeat $! l[$>] split_opacity l[0] to_rgb 36985 b $1 s c quantize $2,1,0 area 0 ^ $3 n 0,255 36986 endl a c endl done 36987 36988fx_color_abstraction_preview : 36989 gui_split_preview "fx_color_abstraction $*",${-3--1} 36990 36991#@gui Apply External CLUT : fx_apply_haldclut, fx_apply_haldclut_preview(1)+ 36992#@gui : Specify HaldCLUT As = choice(2,"Top Layer","Bottom Layer","Filename") 36993#@gui : HaldCLUT Filename = filein() 36994#@gui : note = note("<small><b>Note:</b> Do not forget to set the <i>Input layers</i> option if you select 36995#@gui : <i>Top layer</i> or <i>Bottom layer</i>.</small>") 36996#@gui : sep = separator() 36997#@gui : Strength (%) = float(100,0,100) 36998#@gui : Brightness (%) = float(0,-100,100) 36999#@gui : Contrast (%) = float(0,-100,100) 37000#@gui : Gamma (%) = float(0,-100,100) 37001#@gui : Hue (%) = float(0,-100,100) 37002#@gui : Saturation (%) = float(0,-100,100) 37003#@gui : Normalize Colors = choice("None","Pre-Normalize","Post-Normalize","Both") 37004#@gui : sep = separator() 37005#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37006#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37007#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37008#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37009#@gui : sep = separator() 37010#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/02/08</i>.</small>") 37011fx_apply_haldclut : skip "${2=}" 37012 mode=$1 37013 filename="$2" 37014 strength,brightness,contrast,gamma,hue,saturation,normalize=${3-9} 37015 37016 if $mode<2 # CLUT as a layer 37017 if $!<2 gui_warning_preview "Input layer with HaldCLUT is missing" return fi 37018 ind_clut={$mode?$!-1:0} 37019 else # CLUT as a file 37020 l 37021 0 nm. "$2" ext={x} rm. 37022 if lowercase(['$ext'])=='cube' input_cube "$2" 37023 else i "$2" 37024 fi 37025 ind_clut={$!-1} 37026 onfail gui_warning_preview "Specified HaldCLUT filename not found" return 37027 endl 37028 fi 37029 if {$ind_clut,iM>512} /[$ind_clut] 255 fi # Possibly a 16bits HaldCLUT. 37030 37031 if $normalize==1" || "$normalize==3 # Pre-normalization 37032 repeat $! if $>!=$ind_clut l[$>] split_opacity balance_gamma[0] , a c endl fi done 37033 fi 37034 repeat $! if $>!=$ind_clut +map_clut[$>] [$ind_clut] j[$>] .,0,0,0,0,{$strength%} rm. fi done rm[$ind_clut] 37035 adjust_colors $brightness,$contrast,$gamma,$hue,$saturation,0,255 37036 if $normalize==2" || "$normalize==3 # Post-normalization 37037 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done 37038 fi 37039 37040fx_apply_haldclut_preview : skip "${2=}" 37041 if $1<2 gui_warning_preview "No preview available in this mode" return fi 37042 gui_split_preview "fx_apply_haldclut $1,\"$2\",${3--2}",${-3--1} 37043 37044#@gui Basic Adjustments : fx_adjust_colors, fx_adjust_colors_preview 37045#@gui : Brightness (%) = float(0,-100,100) 37046#@gui : Contrast (%) = float(0,-100,100) 37047#@gui : Gamma (%) = float(0,-100,100) 37048#@gui : Hue (%) = float(0,-100,100) 37049#@gui : Saturation (%) = float(0,-100,100) 37050#@gui : sep = separator() 37051#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37052#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37053#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37054#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37055#@gui : sep = separator() 37056#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/16/06</i>.</small>") 37057fx_adjust_colors : 37058 adjust_colors ${1-5},0,255 37059 37060fx_adjust_colors_preview : 37061 gui_split_preview "fx_adjust_colors $*",${-3--1} 37062 37063#@gui Boost Chromaticity : fx_boost_chroma, fx_boost_chroma_preview(1) 37064#@gui : Amplitude (%) = float(50,0,100) 37065#@gui : Color Space = choice{"YCbCr (Distinct)","YCbCr (Mixed)","Lab (Distinct)","Lab (Mixed)"} 37066#@gui : sep = separator() 37067#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37068#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37069#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37070#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37071#@gui : sep = separator() 37072#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/19/07</i>.</small>") 37073fx_boost_chroma : 37074 repeat $! l[$>] split_opacity l[0] 37075 +to_rgb 37076 if $2>=2 37077 srgb2rgb rgb2lab. 37078 if $2==2 sh. 1 sh.. 2 equalize[-2,-1] rm[-2,-1] 37079 else sh. 1,2 equalize. rm. 37080 fi 37081 lab2rgb. rgb2srgb 37082 else 37083 rgb2ycbcr. 37084 if $2==0 sh. 1 sh.. 2 equalize[-2,-1] rm[-2,-1] 37085 else sh. 1,2 equalize. rm. 37086 fi 37087 ycbcr2rgb. 37088 fi 37089 j.. .,0,0,0,0,{$1%} rm. 37090 endl a c endl done 37091 37092fx_boost_chroma_preview : 37093 gui_split_preview "fx_boost_chroma $*",${-3--1} 37094 37095#@gui Boost-Fade : fx_boost_fade, fx_boost_fade_preview 37096#@gui : Amplitude = float(5,0,10) 37097#@gui : Chromaticity From = choice("YCbCr","Lab") 37098#@gui : sep = separator() 37099#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37100#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37101#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37102#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37103#@gui : sep = separator() 37104#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/11/26</i>.</small>") 37105fx_boost_fade : 37106 repeat $! l[$>] 37107 100%,100%,1,3 rand. 0,1 b. {10-10*($1/10)^0.5} n. 0,255 37108 to_colormode 0 a z 37109 ac "s z transfer_histogram.. . rm.",${"arg 1+$2,ycbcr_cbcr,lab_ab"} 37110 endl done 37111 37112fx_boost_fade_preview : 37113 gui_split_preview "fx_boost_fade $1,$2",${-3--1} 37114 37115#@gui Channel Processing : fx_channel_processing, fx_channel_processing_preview(1) 37116#@gui : Brightness (%) = float(0,-100,100) 37117#@gui : Contrast (%) = float(0,-100,100) 37118#@gui : Gamma (%) = float(0,-100,100) 37119#@gui : Smoothness = float(0,0,10) 37120#@gui : Value Action = choice("None","Cut","Cut & Normalize","Normalize","Threshold") 37121#@gui : Low Value = float(0,0,100) 37122#@gui : High Value = float(100,0,100) 37123#@gui : Quantization = int(256,1,256) 37124#@gui : Equalization = bool(0) 37125#@gui : Negation = bool(0) 37126#@gui : sep = separator() 37127#@gui : Tones Range = choice("All tones","Shadows","Mid-Tones","Highlights") 37128#@gui : Tones Smoothness = float(2,0,10) 37129#@gui : sep = separator() 37130#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 37131#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 37132#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 37133#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 37134#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 37135#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 37136#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 37137#@gui : sep = separator() 37138#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37139#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37140#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37141#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37142#@gui : sep = separator() 37143#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 37144_fx_channel_processing : 37145 adjust_colors ${1-3} b. $4% 37146 if $5==1 c. $6%,$7% 37147 elif $5==2 c. $6%,$7% n. 0,255 37148 elif $5==3 n. $6%,$7% 37149 elif $5==4 ir. $6%,$7% *. 255 37150 fi 37151 if $8!=256 quantize. $8,1,0 fi 37152 if $9 equalize. fi 37153 if $10 negate. fi 37154 37155fx_channel_processing : 37156 repeat $! l. split_opacity rv to_rgb. 37157 fx_start_mix $11,$12 37158 ac. "_fx_channel_processing $1,$2,$3,$4,$5,$6,$7,$8,$9,$10",$13,1 37159 fx_end_mix $11 37160 if $!!=3 rv a c fi endl mv. 0 done 37161 37162fx_channel_processing_preview : 37163 gui_split_preview "fx_channel_processing $*",${-3--1} 37164 37165#@gui Channels to Layers : fx_channels2layers, fx_channels2layers_preview 37166#@gui : Colorspace = choice("RGB","CMY","HSV") 37167#@gui : sep = separator() 37168#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/15/07</i>.</small>") 37169fx_channels2layers : 37170 repeat $! l[$<] nm=${-gui_layer_name} to_rgb 37171 if $1==0 # RGB 37172 s[0] c 37173 r[0] 100%,100%,1,3,0,0,0,0,0,0 nm[0] name($nm" "[red]),mode(add) 37174 r[1] 100%,100%,1,3,0,0,0,0,0,0.5 nm[1] name($nm" "[green]),mode(add) 37175 r[2] 100%,100%,1,3,0,0,0,0,0,1 nm[2] name($nm" "[blue]),mode(add) 37176 elif $1==1 # CMY 37177 rgb2cmy[0] -[0] 255 s[0] c 37178 r[0] 100%,100%,1,3,0,0,0,0,0,0 nm[0] name($nm" "[cyan]),mode(difference) 37179 r[1] 100%,100%,1,3,0,0,0,0,0,0.5 nm[1] name($nm" "[magenta]),mode(difference) 37180 r[2] 100%,100%,1,3,0,0,0,0,0,1 nm[2] name($nm" "[yellow]),mode(difference) 37181 +[0-2] 255 37182 i[0] 100%,100%,1,3,255 nm[0] name($nm" "[base]),mode(difference) 37183 else # HSV 37184 rgb2hsv[0] s[0] c,-2 37185 r[0] 100%,100%,1,3,0,0 sh[0] 2 f. 1 rm. nm[0] name($nm" "[color]),mode(normal) 37186 r[1] 100%,100%,1,3,0,0,0,0,0,1 nm[1] name($nm" "[value]),mode(value) 37187 hsv2rgb[0,1] rv[0,1] 37188 fi 37189 endl done 37190 37191fx_channels2layers_preview : 37192 repeat $! l[$>] 37193 fx_channels2layers $* 37194 repeat $! l[$>] to "#"{1+$>},1,1,43,7,1,255 endl done 37195 frame 1,1,0 frame 3,3,255 append_tiles , 37196 endl done 37197 37198#@gui Color Balance : fx_balance_gamma, fx_balance_gamma_preview 37199#@gui : Neutral Color = color(128,128,128) 37200#@gui : Stretch Colors = bool(1) 37201#@gui : sep = separator() 37202#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37203#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37204#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37205#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37206#@gui : sep = separator() 37207#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/01/07</i>.</small>") 37208fx_balance_gamma : 37209 repeat $! l[$>] split_opacity 37210 if $!>1 +!=. 0 *[0,-1] fi 37211 l[0] 37212 balance_gamma ${1-3} 37213 if $4 n 0,255 fi 37214 endl 37215 a c endl 37216 done 37217 37218fx_balance_gamma_preview : 37219 gui_split_preview "fx_balance_gamma $*",${-3--1} 37220 37221#@gui Color Blindness : colorblind, fx_colorblind_preview 37222#@gui : Blindness Type = choice("Protanopia","Protanomaly","Deuteranopia","Deuteranomaly","Tritanopia", 37223#@gui : "Tritanomaly","Achromatopsia","Achromatomaly") 37224#@gui : sep = separator() 37225#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37226#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37227#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37228#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37229#@gui : sep = separator() 37230#@gui : note = note{"<small><b>Note:</b> 37231#@gui : This filter simulates different types of colorblindness vision. 37232#@gui : </small>"} 37233#@gui : sep = separator() 37234#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/04</i>.</small>") 37235fx_colorblind_preview : 37236 gui_split_preview "colorblind $*",${-3--1} 37237 37238#@gui Color Presets : fx_color_presets, fx_color_presets_preview(1)+ 37239#@gui : LUTs Pack = choice{19,"Abigail Gonzalez (21)","Alex Jordan (81)","Berat (10)","Cinematic (8)", 37240#@gui : "Cinematic Travel (29)","Creative Pack (33)","Eric Ellerbrock (14)","FilterGrade Cinematic (8)", 37241#@gui : "InAvision (15)","J.T. Semple (14)","Kyler Holland (10)","Lutify.Me (7)","Michael Ezra (2)","Moviz (48)", 37242#@gui : "Ohad Peretz (7)","Olivio Sarikas (19)","ON1 Photography (90)","PictureFX (25)","Pixelmator (45)", 37243#@gui : "PIXLS.US (31)","Purple11 (12)","RocketStock (35)","Shamoon Abbasi (25)","SmallHD Movie Look (7)", 37244#@gui : "Youssef Hossam (5)","Others (69)"} 37245 37246##### Abigail Gonzales 37247#@gui : Preset = choice{1,"All [Collage]","None", 37248#@gui : "Blade Runner","Blue House","Blue Ice","Caribe","Cinema","Cinema 2","Cinema 3","Cinema 4","Cinema 5", 37249#@gui : "Cinema Noir","Cinematic for Flog","Day4Nite","Eterna for Flog","Filmic","Fuji HDR", 37250#@gui : "Golden Gate","Matrix","Monochrome 1","Monochrome 2","Old West","Science Fiction"}_0 37251 37252##### Alex Jordan 37253#@gui : Preset = choice{1,"All [Collage]","None", 37254#@gui : "Action Magenta 01","Action Red 01","Adventure 1453","Aggressive Highlights Recovery 5", 37255#@gui : "Bleech Bypass Green","Bleech Bypass Yellow 01","Blue Dark","Blue Shadows 01","Bright Green 01", 37256#@gui : "Brownish","Colorful 0209","Conflict 01","Contrast with Highlights Protection","Contrasty Afternoon", 37257#@gui : "Contrasty Green","Cross Process CP 130","Cross Process CP 14","Cross Process CP 15", 37258#@gui : "Cross Process CP 16","Cross Process CP 18","Cross Process CP 3","Cross Process CP 4", 37259#@gui : "Cross Process CP 6","Dark Green 02","Dark Green 1","Dark Place 01","Dream 1","Dream 85", 37260#@gui : "Faded Retro 01","Faded Retro 02","Film 0987","Film 9879","Film Highlight Contrast","Flat 30", 37261#@gui : "Green 2025","Green Action","Green Afternoon","Green Conflict","Green Day 01","Green Day 02", 37262#@gui : "Green G09","Green Indoor","Green Light","Harsh Day","Harsh Sunset","Highlights Protection", 37263#@gui : "Indoor Blue","Low Contrast Blue","Low Key 01","Magenta Day","Magenta Day 01","Magenta Dream", 37264#@gui : "Memories","Moonlight 01","Mostly Blue","Muted 01","Night 01","Only Red","Only Red and Blue", 37265#@gui : "Operation Yellow","Orange Dark 4","Orange Dark 7","Orange Dark Look","Orange Underexposed", 37266#@gui : "Protect Highlights 01","Red Afternoon 01","Red Day 01","Red Dream 01","Retro Brown 01", 37267#@gui : "Retro Magenta 01","Retro Yellow 01","Saturated Blue","Smart Contrast","Subtle Blue", 37268#@gui : "Subtle Green","Yellow 55B","Yellow Film 01"}_0 37269 37270##### Berat 37271#@gui : Preset = choice{1,"All [Collage]","None", 37272#@gui : "Brown BM","Cine Blue","Cine BM4k","Golden Time","Green and Orange","Monochrome","Sevsuz","Sunlight Love", 37273#@gui : "Western","Western Lut 2"}_0 37274 37275##### Cinematic 37276#@gui : Preset = choice{1,"All [Collage]","None", 37277#@gui : "Deep","Dimension","Enchanted","Flavin","Frosted","Shine","Ultra Water","Wipe"}_0 37278 37279##### Cinematic Travel 37280#@gui : Preset = choice{1,"All [Collage]","None", 37281#@gui : "Blue Cold Fade","Bright Teal Orange","Bright Warm","Clear Teal Fade","Cold Clear Blue","Cold Clear Blue 1", 37282#@gui : "Deep Blue","Deep Dark Warm","Deep High Contrast","Deep Teal Fade","Deep Warm Fade","Faded Green", 37283#@gui : "Greenish Contrasty","Greenish Fade","Greenish Fade 1","Hard Teal Orange","Neutral Teal Orange", 37284#@gui : "Neutral Warm Fade","Smooth Clear","Smooth Green Orange","Smooth Teal Orange","Teal Fade","Very Warm Greenish", 37285#@gui : "Warm Dark Contrasty","Warm Fade","Warm Fade 1","Warm Neutral","Warm Sunset Red","Warm Teal"}_0 37286 37287##### Creative Pack 37288#@gui : Preset = choice{1,"All [Collage]","None", 37289#@gui : "Anime","Bleach Bypass 1","Bleach Bypass 2","Bleach Bypass 3","Bleach Bypass 4","Candle Light", 37290#@gui : "Color Negative","Crisp Warm","Crip Winter","Drop Blues","Edgy Ember","Fall Colors","Foggy Night", 37291#@gui : "Futuristic Bleak 1","Futuristic Bleak 2","Futuristic Bleak 3","Futuristic Bleak 4","Horror Blue", 37292#@gui : "Late Sunset","Moonlight","Night From Day","Red Blue Yellow","Smokey","Soft Warming","Teal Magenta Gold", 37293#@gui : "Teal Orange","Teal Orange 1","Teal Orange 2","Teal Orange 3","Tension Green 1","Tension Green 2", 37294#@gui : "Tension Green 3","Tension Green 4"}_0 37295 37296##### Eric Ellerbrock 37297#@gui : Preset = choice{1,"All [Collage]","None", 37298#@gui : "Avalanche","Black Star","Helios","Hydracore","Hypnosis","Killstreak","Nemesis","Night Blade 4", 37299#@gui : "Paladin","Seringe 4","Serpent","Terra 4","Victory","Yellowstone"}_0 37300 37301##### FilterGrade Cinematic 37302#@gui : Preset = choice{1,"All [Collage]","None", 37303#@gui : "Cine Basic","Cine Bright","Cine Cold","Cine Drama","Cine Teal Orange 1","Cine Teal Orange 2", 37304#@gui : "Cine Vibrant","Cine Warm"}_0 37305 37306##### InAvision 37307#@gui : Preset = choice{1,"All [Collage]","None", 37308#@gui : "7Drk21","BC Darkum","Brown Mobster","Cold Ice","Dark Man X","Film GB-19","Formula B","Gremerta", 37309#@gui : "Hitman","J. Wick 21","London Nights","Louetta","Nightlife","VFB 21","Vintage Mob"}_0 37310 37311##### J.T. Semple 37312#@gui : Preset = choice{1,"All [Collage]","None", 37313#@gui : "Bright Green","Crisp Romance","Crushin","Frosted Beach Picnic","Just Peachy","Late Afternoon Wanderlust", 37314#@gui : "Lush Green Summer","Magenta Coffee","Minimalist Caffeination","Mystic Purple Sunset","Nostalgia Honey", 37315#@gui : "Spring Morning","Toasted Garden","Winter Lighthouse"}_0 37316 37317##### Kyler Holland 37318#@gui : Preset = choice{1,"All [Collage]","None", 37319#@gui : "KH 1","KH 2","KH 3","KH 4","KH 5","KH 6","KH 7","KH 8","KH 9","KH 10"}_0 37320 37321##### Lutify.Me 37322#@gui : Preset = choice{1,"All [Collage]","None", 37323#@gui : "Hackmanite","Herderite","Heulandite","Hiddenite","Hilutite","Howlite","Hypersthene"}_0 37324 37325##### Michael Ezra 37326#@gui : Preset = choice{1,"All [Collage]","None", 37327#@gui : "Deep Skin Tones 2","Deep Skin Tones 3"}_0 37328 37329##### Moviz 37330#@gui : Preset = choice{1,"All [Collage]","None", 37331#@gui : "Moviz 1","Moviz 2","Moviz 3","Moviz 4","Moviz 5","Moviz 6","Moviz 7","Moviz 8","Moviz 9","Moviz 10", 37332#@gui : "Moviz 11","Moviz 12","Moviz 13","Moviz 14","Moviz 15","Moviz 16","Moviz 17","Moviz 18","Moviz 19","Moviz 20", 37333#@gui : "Moviz 21","Moviz 22","Moviz 23","Moviz 24","Moviz 25","Moviz 26","Moviz 27","Moviz 28","Moviz 29","Moviz 30", 37334#@gui : "Moviz 31","Moviz 32","Moviz 33","Moviz 34","Moviz 35","Moviz 36","Moviz 37","Moviz 38","Moviz 39","Moviz 40", 37335#@gui : "Moviz 41","Moviz 42","Moviz 43","Moviz 44","Moviz 45","Moviz 46","Moviz 47","Moviz 48"}_0 37336 37337##### Ohad Peretz 37338#@gui : Preset = choice{1,"All [Collage]","None", 37339#@gui : "Cold Simplicity 2","D and O 1","Retro Summer 3","Subtle Yellow","Teal Moonlight","True Colors 8", 37340#@gui : "Vintage Warmth 1"}_0 37341 37342#### Olivio Sarikas 37343#@gui : Preset = choice{1,"All [Collage]","None", 37344#@gui : "Analog Film 1","Atomic Pink","Beach Aqua Orange","Beach Faded Analog","BW but Yellow","City Dust", 37345#@gui : "Dark Orange Teal","Day to Night King's Blue","DuoTone Blue Red","Faded Pink-ish","Flat Blue Moon", 37346#@gui : "Honey Light","Infrared - Dust Pink","Neutral Pump","Shade King's Ink","Sunset Aqua Orange", 37347#@gui : "Sunset Intense Violet Blue","Sunset Violet Mood","Violet Taste"}_0 37348 37349##### ON1 Photography 37350#@gui : Preset = choice{1,"All [Collage]","None", 37351#@gui : "2-Strip Process","Aqua","Aqua and Orange Dark","Berlin Sky","Blues", 37352#@gui : "Black & White-1","Black & White-2","Black & White-3","Black & White-4","Black & White-5", 37353#@gui : "Black & White-6","Black & White-7","Black & White-8","Black & White-9","Black & White-10","Chrome 01", 37354#@gui : "Cinematic-1","Cinematic-2","Cinematic-3","Cinematic-4","Cinematic-5","Cinematic-6","Cinematic-7", 37355#@gui : "Cinematic-8","Cinematic-9","Cinematic-10","Classic Teal and Orange","Earth Tone Boost","Fade to Green", 37356#@gui : "Film Print 01","Film Print 02","French Comedy","Green Blues","Green Yellow","Landscape-1","Landscape-2", 37357#@gui : "Landscape-3","Landscape-4","Landscape-5","Landscape-6","Landscape-7","Landscape-8","Landscape-9", 37358#@gui : "Landscape-10","Lifestyle & Commercial-1","Lifestyle & Commercial-2","Lifestyle & Commercial-3", 37359#@gui : "Lifestyle & Commercial-4","Lifestyle & Commercial-5","Lifestyle & Commercial-6","Lifestyle & Commercial-7", 37360#@gui : "Lifestyle & Commercial-8","Lifestyle & Commercial-9","Lifestyle & Commercial-10","Moody-1","Moody-2", 37361#@gui : "Moody-3","Moody-4","Moody-5","Moody-6","Moody-7","Moody-8","Moody-9","Moody-10","Nature & Wildlife-1", 37362#@gui : "Nature & Wildlife-2","Nature & Wildlife-3","Nature & Wildlife-4","Nature & Wildlife-5","Nature & Wildlife-6", 37363#@gui : "Nature & Wildlife-7","Nature & Wildlife-8","Nature & Wildlife-9","Nature & Wildlife-10","Oranges","Portrait-1", 37364#@gui : "Portrait-2","Portrait-3","Portrait-4","Portrait-5","Portrait-6","Portrait-7","Portrait-8","Portrait-9", 37365#@gui : "Portrait10","Purple","Reds","Reds Oranges Yellows","Studio Skin Tone Shaper","Vintage Chrome"}_0 37366 37367##### Picture FX 37368#@gui : Preset = choice{1,"All [Collage]","None", 37369#@gui : "AnalogFX - Anno 1870 Color","AnalogFX - Old Style I","AnalogFX - Old Style II","AnalogFX - Old Style III", 37370#@gui : "AnalogFX - Sepia Color","AnalogFX - Soft Sepia I","AnalogFX - Soft Sepia II", 37371#@gui : "PictureFX - Faux Infrared B&W1","PictureFX - Faux Infrared Color P2","PictureFX - Faux Infrared Color P3", 37372#@gui : "PictureFX - Faux Infrared R0a","PictureFX - Faux Infrared R0b","PictureFX - Faux Infrared YP1", 37373#@gui : "GoldFX - Bright Spring Breeze","GoldFX - Bright Summer Heat","GoldFX - Hot Summer Heat", 37374#@gui : "GoldFX - Perfect Sunset 01min","GoldFX - Perfect Sunset 05min","GoldFX - Perfect Sunset 10min", 37375#@gui : "GoldFX - Spring Breeze","GoldFX - Summer Heat", 37376#@gui : "TechnicalFX - Backlight Filter","ZilverFX - B&W Solarization","ZilverFX - InfraRed", 37377#@gui : "ZilverFX - Vintage B&W"}_0 37378 37379##### Pixelmator 37380#@gui : Preset = choice{1,"All [Collage]","None", 37381#@gui : "Black & White 01","Black & White 02","Black & White 03","Black & White 04","Black & White 05",\ 37382# "Black & White 06", 37383#@gui : "Cinematic 01","Cinematic 02","Cinematic 03","Cinematic 04","Cinematic 05","Cinematic 06","Cinematic 07", 37384#@gui : "Classic Films 01","Classic Films 02","Classic Films 03","Classic Films 04","Classic Films 05", 37385#@gui : "Landscape 01","Landscape 02","Landscape 03","Landscape 04","Landscape 05", 37386#@gui : "Modern Films 01","Modern Films 02","Modern Films 03","Modern Films 04","Modern Films 05","Modern Films 06",\ 37387# "Modern Films 07", 37388#@gui : "Night 01","Night 02","Night 03","Night 04","Night 05", 37389#@gui : "Urban 01","Urban 02","Urban 03","Urban 04","Urban 05", 37390#@gui : "Vintage 01","Vintage 02","Vintage 03","Vintage 04","Vintage 05"}_0 37391 37392##### PIXLS.US 37393#@gui : Preset = choice{1,"All [Collage]","None", 37394#@gui : "Amstragram","Amstragram+","Autumn","Cinematic Lady Bird","Cinematic Mexico","Dark Blues in Sunlight", 37395#@gui : "Delicatessen","Expired 69","Faded Look","Faded Print","Hypressen","Magenta Yellow","Metropolis", 37396#@gui : "Modern Film","Newspaper","Night Spy","Progressen","Prussian Blue","Seventies Magazine","Street", 37397#@gui : "Sweet Bubblegum","Sweet Gelatto","Taiga","Tarraco","Unknown","Uzbek Bukhara","Uzbek Marriage", 37398#@gui : "Uzbek Samarcande","Velvetia","Warm Vintage","Whiter Whites"}_2 37399 37400##### Purple11 37401#@gui : Preset = choice{1,"All [Collage]","None", 37402#@gui : "Going for a Walk","Good Morning","Nah","Once Upon a Time","Passing By","Serenity", 37403#@gui : "Smooth Sailing","Undeniable","Undeniable 2","Urban Cowboy","We'll See","You Can Do It"}_0 37404 37405##### RocketStock 37406#@gui : Preset = choice{1,"All [Collage]","None", 37407#@gui : "Arabica 12","Ava 614","Azrael 93","Bourbon 64","Byers 11","Chemical 168","Clayton 33","Clouseau 54", 37408#@gui : "Cobi 3","Contrail 35","Cubicle 99","Django 25","Domingo 145","Faded 47","Folger 50","Fusion 88", 37409#@gui : "Hyla 68","Korben 214","Lenox 340","Lucky 64","McKinnon 75","Milo 5","Neon 770","Paladin 1875","Pasadena 21", 37410#@gui : "Pitaya 15","Reeve 38","Remy 24","Sprocket 231","Teigen 28","Trent 18","Tweed 71","Vireo 37","Zed 32", 37411#@gui : "Zeke 39"}_0 37412 37413##### Shamoon Abbasi 37414#@gui : Preset = choice{1,"All [Collage]","None", 37415#@gui : "City 7","Coffee 44","Date 39","Day for Night","Denoise Simple 40","Desert Gold 37","Directions 23", 37416#@gui : "Drop Green Tint 14","Elegance 38","Golden Night Softner 43","Golden Sony 37","Green 15","Happyness 133", 37417#@gui : "HLG 1","Industrial 33","Morning 6","Morroco 16","Night King 141","Rest 33","Shadow King 39","Spy 29", 37418#@gui : "Thriller 2","Turkiest 42","Vintage 163","Wooden Gold 20"}_0 37419 37420##### SmallHD Movie Look 37421#@gui : Preset = choice{1,"All [Collage]","None", 37422#@gui : "Apocalypse This Very Moment","B-Boyz 2","Bob Ford","Life Giving Tree","Moonrise","Saving Private Damon", 37423#@gui : "The Matrices"}_0 37424 37425##### Youssef Hossam 37426#@gui : Preset = choice{1,"All [Collage]","None", 37427#@gui : "Cinematic Forest","City","Darkness","Hallowen Dark","Sea"}_0 37428 37429##### Others 37430#@gui : Preset = choice{1,"All [Collage]","None", 37431#@gui : "60's","60's (faded)","60's (faded alt)","Alien green","Black & White","Bleach bypass","Blue mono", 37432#@gui : "Cinematic-01","Cinematic-02","Cinematic-03", 37433#@gui : "Color (rich)","Faded","Faded (alt)","Faded (analog)","Faded (extreme)","Faded (vivid)","Expired (fade)", 37434#@gui : "Expired (polaroid)","Extreme","Fade","Faux infrared","Golden","Golden (bright)","Golden (fade)", 37435#@gui : "Golden (mono)","Golden (vibrant)","Green mono","Hong Kong","Instant-C","K-Tone Vintage Kodachrome", 37436#@gui : "Light (blown)","Lomo","Mono tinted","Muted fade", 37437#@gui : "Mute shift","Natural (vivid)","Nostalgic","Orange tone","Pink fade","Purple","Retro","Rotate (muted)", 37438#@gui : "Rotate (vibrant)","Rotated","Rotated (crush)","Smooth crome-ish","Smooth fade","Soft fade","Solarize color", 37439#@gui : "Solarized color2","Summer","Summer (alt)","Sunny","Sunny (alt)","Sunny (warm)","Sunny (rich)","Super warm", 37440#@gui : "Super warm (rich)","Sutro FX","Vibrant","Vibrant (alien)","Vibrant (contrast)","Vibrant (crome-ish)", 37441#@gui : "Vintage","Vintage (alt)","Vintage (brighter)","Warm","Warm (highlight)","Warm (yellow)"}_0 37442 37443#@gui : Thumbnail Size = int(512,0,1024)_1 37444#@gui : sep = separator() 37445#@gui : Strength (%) = float(100,0,100) 37446#@gui : Brightness (%) = float(0,-100,100) 37447#@gui : Contrast (%) = float(0,-100,100) 37448#@gui : Gamma (%) = float(0,-100,100) 37449#@gui : Hue (%) = float(0,-100,100) 37450#@gui : Saturation (%) = float(0,-100,100) 37451#@gui : Normalize Colors = choice("None","Pre-Normalize","Post-Normalize","Both") 37452#@gui : sep = separator() 37453#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 37454#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 37455#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 37456#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 37457#@gui : sep = value(0)_2+ 37458#@gui : sep = separator() 37459#@gui : note = note("<b>Note:</b> The color LUTs proposed in this category comes from:\n") 37460 37461#@gui : sep = value(0)_0+ 37462#@gui : note = note{"<center><img src="data:image/png;base64,\ 37463# iVBORw0KGgoAAAANSUhEUgAAABoAAAAgCAMAAAA7dZg3AAADAFBMVEUAAAAGBgYwHyUFBAQMDAwuHSMQDg8+LTMICAg2JStDMTfmu5gKBgfs6evgs5Di\ 37464# popINz06KS/tzrnnuarUmGxSQEVHOTE4JyNHIxggEBMVCg4NBwj29fXmx8Pu0rzoyrPlyLHoxKzgtKTdr5/pvpzjuY7ep4ritIjbooXgpYTgtYPcn4PA\ 37465# lYPZnIHYmn7NkHS6iXS7gGevc1mOVUhVRUiWW0GHSjM4Jy0+LyscGB4TCQkoBwk2Cgju7e7z1NDuzcjnx8bqzMXn0b/lxbvotaPit5PlsZLYrYvnqouY\ 37466# jInmrYXjq3/cnH/NkH/iqHzTl3zfpHnanHneona+kXCignDGimvHhWvVi2Z+Z2bMkWW3el6ldl3RflzAgli4bFadXlRrXVNvVlOoak+vY09hU0tYRkuh\ 37467# W0NOPUNZSUB+Tz5URDp2RzVcQDVqPi5yOy5WNihHLyAdFxcrChNCGA4aCQphCAjw6unry9HyzMrrxL/wxbfuyrLIr6/iqqWspqXnvaTtwqDnt5/mtpjl\ 37468# r5jbqpbfrY/ftYvFm4e5mYWWf4HYoYDEi3uPg3nGm3jYjXTEkXHOi3GFdXDDjm/ThW+6e2+vfWzSlGnakWmzdWiZc2fOi2PGe2HCh1uoaVt2Y1iZa1fB\ 37469# dlZ4VFOIXlFbSlCUWEyHWEhmS0aST0WBRDmPSzhvQjJaPCl3QChmNii6EiiiFyY0ISGQEB+bCxswHBlcDxh3CRIgDBEzEQ7g3Nzc3Nzu4tbevcPw1L7S\ 37470# yL3TrqzUq5mamJnCp5XCp5TZpJDroonQlYXon4S+hoOJgYPqnX3clHzAlHqBdHbboHTBgnTYnXG+f3FxZm+6j216YGnLhWfUg2WlcmSzcGSWa2N3ZmPE\ 37471# iV3IeliJXFW2e1HKdFGmVVGSYEyGU0toTUugaEqsYUpwVEqhYEh5V0Z7U0bIYUOQYUN/KUNIPkKGTD9vQzyJQjppPDhWOTWZMC7AGC0qJyhfLyRdLyA/\ 37472# IBgKBxgwJhcvIRcsEhdFKRSCDRRICw5SCAxjV0wNAAADGElEQVQoz23NBUxbYRAH8O9JX1+FlrrhMIa7O8PGcN1wBgx3xtzdBXd3GQ5zd3d3d3d/Lcmy\ 37473# LLvkkrv/L5cD9nIJqbF8MguGYZIgORkmwZbkjZ5TklpWgmlrvvJjrWC+FQmGE9YkUGGYRTYza0yaMgnMSxVZ8QdYG80oMCzg95JIMIVFpVLlCfKMPV4j\ 37474# gGFLEkyEFBJJamQyVd7ME2yx35FqRaFQWNKdSiZbUiyJQT6JNwnIKRy6/jL9TUtN8Iq9e1YYm9Q21NdPvsLj8SYDua1HJq7za7iopqKswlZ119TW2jd3\ 37475# 55yV5xoJGjfxyQVmxC62Enscez5jkdtCzkxFJ6dtepeB/azImwFaZ1W2KykvXLreJDxoCcdZcfp0R06B9CpybFCQipIqw+NYxO1m8zg/jouiotPcOiDn\ 37476# rH1Qe+1aZSVVLcMDh8+UW8SFaKrrFdemGIE5b33Ga2hoqLKV3Zeu8lle1J6oubg4SyjM0wPPvt3Zr0Fzmz97Ns1jlWFoUVzoIjXT7C+f7PSAnWhA352h\ 37477# 47ZgAc1D08/QUH/xLE5zRuf3vAIwbJPtPWECgzZmLJOppau7xMVxhpppZkZ38HIgpqcH+MtoPJPpfdTVwcFR3byrK2XzNCBBOku4XsukpO29odDV2WGm\ 37478# +kMLi2AFBYAiwmsV/jq0MTq+3POF61xdZqipJ7a/uLubIMg2MbLUl7FM5wQ3QFfXIISpv9rcIoslP4+gqd3RpYFeXr5cAwMDfZ+Tp8ti0l7nWL9/DlCc\ 37479# PtIWdSrQPzAsJHTDeqOy6hjTjF4Ms7YGGHGWZ14Rxi2JqqqLvx9/KcY0LTsHQzFMSnRb4b0bYVejqioro2+1ZnZ8HBajECQGOIqi4qnCpybG4eHR8a2v\ 37480# 2jI/iDAUgXARQHAcsxHTR9IiVhsZmzR1ZAls6CiOQLk9ACAQKpFAuERQbmRc3ZSSboNDOA5Bg+8AABAKAQhCEIz34NHj5BxIVrl9mwgiYqKBtFAMQmRC\ 37481# /9UvJYAgyKjIFpnYDfX3/In+NsQ2/0ff4L8w+sAufyhX9F+S/My3/Wz9Gwm+5rUIT8ACAAAAAElFTkSuQmCC"/> \ 37482# <a href="https://www.abigailgonzalez.com/">Abigail Gonzalez - FreshLUTs</a></center>"} 37483 37484#@gui : sep = value(0)_0+ 37485#@gui : note = note{"<center><img src="data:image/png;base64,\ 37486# iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAADAFBMVEXU1NTV0cfT0MXNyb6fmo7V0cvX08i2trza1tDX083UzsHQx7YSDxHW1NTb19PM\ 37487# ysjKxb68uKqdnJ1MRUjO0dnKzdna2NfBws3BwcnTz8fOycHIwLXEu6+hn6BkWVdBPD8uKCvU1+DX1NHT0dHIydDZ1c3PzMu9vsm9vcPQzcLJxsK1tcG4\ 37488# uMDTzL3Iw73OyLvLw7nNwK+sqau+tqmZl595dntoZWZsWlpVUVNVTUxIQ0M6NDclJCchICQgHh8dHB4FBAXW2+TRz8/Y1MnKyMXNxr3JwrjOxbe2tLOs\ 37489# rLLIwKyjpKzFuqq7tai5s6SNi4+emI2clIiLgH1zcHt8dHJxbXJ4Yl1ZS0hQR0gtIiUYFxoNCwzh4+bQzs24ucXV0MTRzMSws8TIwrrTyrmurrjMxLXF\ 37490# vrSxsLTLw7KoqbKlpKien6jHvKePjpmZmJaWkpCIhYySjYuOiIaZjYWIgYOCfHungHiTfXB3cXB2aGKDa1xnUlFUREh3T0MzLzM5LzA6JigoHR8ZFRfP\ 37491# 0t3f3dvCx9jT0tbEx9TT09G7vs/Fxs24vM2jqsbKxru7ubaxra60r6eop6ehoKa5qZqVk5qblZWlmpPGto6dloqjlIaAf4OcgHqWe3mBd3h3bWuMcmqD\ 37492# cGZqYWBaV1uDYVN4X1NfTk5tVUo6OT5ZQD1MPDpANDNILCvm6u3i5urR1N3W1tbKzNPU0M6wts7LyMvDwcPSy7+xsru+urWqqK/AtqyamqzOrqq8rqm7\ 37493# pqjayafDvKW3rqG7vJ+zqp+upp/Ir5ivpJetoZewlZSJipSymI24kYuvi4iTin6RhXqvg3iScnFtaG+YfG5hYWqXcWRuZWR9ZmGMb2BhXFuKYFlzXVho\ 37494# W1RaVVJhTEJOQ0JIPj9nQz3s7+7Dy925wdq+x9nBvb24srbYyq63s66rq63Qv6i9qKTZxqKqn6LFup3Lu5esr5aej5bjx4yDgoyqnoeig4a7qYCfjoCb\ 37495# i3qkiHh5amagcWN/XmNKS1mEXExqRkNuRDpq42GmAAAD9klEQVQ4y0XRZVRTYRzH8YfpHBtzzAUbsQIcsEA21w0ijXSjlHR3p510d5fd3d3d3d3ddxw9\ 37496# ft/+Pud/zz0PSElJwaWeOJGZ6eXV5Ok5/n+enp5NXl5ewMnJafm+g/v37dkzw93dfdLfpkK5u8+AAhtYLPutU7eaxBg7LFs27l9ToBwdo6Pj4oC9vr69\ 37497# iYmxzfRxVlYwWEy6b0aVoY4ODAZDobjcKD09wGIy9bW7kRVMB87Ku3xdcj0dOWGCDoTCUFwI2M+cyYpxgHZDOBJJ6aBKZTKp9WTktGmQCUONAbtI6IB2\ 37498# 1zWtz/wqkcnwj3V1J0+eBp0Jm6IH9O3sIh1sjLQ7Zm3l9mOdVwvxVZh/AmUFAbNIh+nhcKQpxsB0/fZjp84XyBowkNAC6DNA38zMOtIoHA7tc9fuPHw8\ 37499# 51LBtR2Y8Og4Fxc3N7cpcAgstF5mZGhqYDA31G5nW2th4dWL4RiHR7sO8FxckkyQWoDFjoH5hIeHPxz3P93lv1nX5vnbp4de73WBABNoAdxg/nqSBb/9\ 37500# 4umiInE/hb85apfe+727eW5wMBMALJYZSjAnW8ya7SH+XiSn+XngKpebJO1O4r2CgNlEgGWFhhJJi8nkWQJqEQ3vc0ZIiXV64hQdx0uaqgPAxInWTMZK\ 37501# 4mJzS/NZbB+xWPguTeCMQCQkxBgbG48zHANzCSuJa9ZYkjikbf5ZyYIt0D47gWINC4PeTAuwd+bYziOYW3LI5hHJiRwEYgsC4VpNWY6CggFIrF4xhzhv\ 37502# 1WIOmWy5yZVjsYDEdmW78nHVXC5340YIrF7BWDBvCXRhQ32qd3osAvqbxNnOfBxfz9HR0QaA+bYM0oJFi+YQLCy98096p1NiN8UnxnNicdW1tZ+aDwFg\ 37503# e/d+xKIlEbYEEqIjv6E+D+fs7Jp2hF2Do3xuPlhQAJg72OuWLl1HtCVa1Hg/qEwVCeLjhXSVpKYOFxXFG+gDz3Jaty29t4TBILJ9qb77M0QeAgFNHRxc\ 37504# l5z6srGxbwAcPdv2JuJICmMVOZsaIM/PvixMSxsMRquTPYS1Hxu/nAWtnW0vqlr4CXmBtJISekC3RCQS9SiUNJ8WYW7u0QM80OmdleEbKJUGyvuHRuSB\ 37505# eLG/f++AQlE6iu++MZTb2wHEed1U/K1bN/tzTn37WUyT3i4u/j2sVKvKy+hB5ddunAGBFy5QAwKaL13JOX+l+HZQRdnoaBm9RKGoGBkevtmVKwM+Pnh8\ 37506# aUB+V2lhX++voSANGh2iQSuVwWjqycymBj8V+JHooZS2l44Eo4PKystDNJqQkBB0j192VkZWtm+7Ag0GW+okSppcTqfTg1TqCnSFWqVSlwxKzp3z8xP1\ 37507# aDR/AFuiV5UIiV63AAAAAElFTkSuQmCC"/> \ 37508# <a href="https://freshluts.com/users/1">Alex Jordan - FreshLUTs</a></center>"} 37509 37510#@gui : sep = value(0)_0+ 37511#@gui : note = note{"<center><a href="https://freshluts.com/users/10185">Berat - FreshLUTs</a></center>"} 37512 37513#@gui : sep = value(0)_0+ 37514#@gui : note = note{"<center><a href="http://fixthephoto.com/free-cinematic-luts">Free Cinematic LUTs</a></center>"} 37515 37516#@gui : sep = value(0)_0+ 37517#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAAAgCAMAAACfHyDkAAAC9FBMVEUUI\ 37518# TIXITMfITUcITQfIzYhITYZIDNBMHbKPi/HKE3HLkPGKn9BL3PIMj/JODXJOjLHJ1TKRC3HJXxrOIfIJnZFLm/HKFzHK0fKPDDHJ23HJ2XINDzJNTnKQ\ 37519# S7FLoJpPXYmJUgiJEEeIjrJNzcrJDTKSS7KQy1xOot1QIdiNIRWMH1KMHlFL3UuJlAmIjbNXTWKR5GFRpB8QY52PYtmNYbFMoRdMoHHJ357QHpPL3pdO\ 37520# HZQMHUpJ08cIz7MXDzNYTdKJjbKQC7ENYbHLYBfNH1TMHpaNHlVNHZKMHJGLnJCLGrHKGrHKGHFT1YrIju+NzfNVDXKRDUzKTVaLDLLTDCRSZKBRJCCR\ 37521# InGVYZuPYR+QYJyP37IJXrIJ3NQMnE8LW2FR2nIT2bHKklCI0MqJkHOWDfIO4FnOYBYMH9qPHyXSXpjOnnBJ3Z2QXJbM3FML2WUTGMzKl7BKFktKlg0K\ 37522# Fg2KFJkJVJALU/KSU68KE7IM0szKkouJUeLJUXIQELMUDsZIzmuVDifUDiXLzh+QzeNSTZLMTaZSZJ8Q4vJToe+NIbKSIOyMX7BKX2kTHqsLnrLSXdvP\ 37523# nZUM3BvNm9gOGyNSWtWNGtLLWuFMGc4LGeUK2evKWdyNWS7UGBXM2A/Kl/JPV5IMVt3JFmqVVSjMUy9WEbLVkO3LkJsJEE1JEDJPz08Ijk1IzZjOTU+L\ 37524# TWGMTPMUTLJQDB/NjCgOS+/QC6kSI+HRYqZR4e4QIe1UoasT4G8MYB1PHqGOnfFUnWSOnWaMHTILnDJO2/KRm22KWynS2qlLWqeS2hnMmfIL2ClJ16EM\ 37525# VlOL1m4VlO3LFKvJlLJQE2zWExfN0vMVUq/LUZ6JkTEXUDLST2uND2VTjnDXji4VzhvQDZaNzVpODS1QC6sPYefP4KfP4FzNni2Jne6UnOkR3GqNHBqM\ 37526# XCuT2WIJGBlKlyxUlmMQFjHK1aIJVWdS1StTU+RM05VJE5zP0WCJEJYI0BTIzzFWTSmNzHHTC7FQC5jTTRlAAAEvUlEQVQ4y6XTdVRTcRTAcd7e3htjU\ 37527# 8E5kBkLN2ADBgiyMWCEdJdSSiMCEkqISimK3d1SAlIidnd3d3d3/uP9bXAQD/qHfv/hnnv4vPvgbBqUzqN2EtGh/5A4jncCCaEwKKjx1s2JN4PUyu/8t\ 37528# WsNQSpS+3HCpFIpSKiDCWosvXV74qQJ4687ODiYmY1vRHD0inMwTwInPRlz2czsa8MvkqAGlTYgceMGGLPEgPUhISEi0ffbCMoXOqwXie4AXCWvMBOJR\ 37529# BtAoqSlEyeMVyqViYmJASBEOn36GBgY6KjaQFBHb5ZXBahG6YLQGGWIjs7GYLXkn69SFhVdCQwMbG7uqYlycuoDIb8xmDouIiJTKYLRkTi5ObIiUcfAo\ 37530# EVIaJAkbur1du26fv26orqhekKaKPAtwoTI0LRzAU5OzU3C0aERMZdDnJx+BFMoIE3Z7HeFvaDevXv3gwcg73/Vv5UHU1dZRGYqAzU17zj6RYbOrQiAZ\ 37531# YsQSYGXJ/tVoVYXFPDqyvcnVsx/+mBPoOr6N+E4IyNuVRGMTUSZRWTMWtj7w0mQdibGnosq9bRUnWAyaTQTYxvr/lsK0Xn/YGLRlORM+GO6+tcnwDNOF\ 37532# cG2RKiWTGMbj6On4/Sgi0fVUsIa/KwQvX0JnAxPO3UF5iYiY0pyzIV1MDpS2qSra9SKMXQ6PS6ucrWpHY+/WmyY4tsF8nfE041SMy/AeLUuPzmc+zIPx\ 37533# hIKDmmQfJDDXaOWjNKmQ5+kJPzPxJaH8rSgEjzfMGmu71kYL1EyLFMX+o7V0qp2xNUSH2lsM9zaPX2ZrjY0pgYncS9xhO/YOHh5R8G8cMWRvLF6etX1C\ 37534# awk7so82BZIWyUpiAYpdks/7OOjq6s76jPOk1gd8qVDBdIcVmrayrMw1lAyWAo4SaePgZOtkuR5SqzFVm7zl3M4Pj4+Z+KXSnbGrkH3v1DmJSmOxL7W1\ 37535# j5Tn+/iwl2JtgVEq8Qgno21mMVym39Q39vbm3M83eVx7DE4X4DnWLmlxa6BF6khFlspUtD2dB3eJlHZErGVIUuxa8TQofr6+k9m7T7A4XBG1QlsXdxnH\ 37536# fDmcI778cRu3Ef74aUuEaQ6tRSstrZiGYan7hnRAxo6Z84+fX3vN5QcF3f57v0w5uKLrd1T0HZ5PNkmIUQXg7Q04u7tjhoyBPzBeL6tq2L7dHjScsJUY\ 37537# ssNGwZjOd4u1ZTvBrK/0dzZMplMrZ9TsofbysMGdh8yIlfgJYlKmcqA0Y/sKKF8F5CDp8hnMFTJHvrZ29q6b5vOkMmW+cHJnWHDGLKZ5STWllqiclggL\ 37538# UJ37RgIMRjlWLarhxx+nTHzA+lpEzVrKiwP12KdSCzDEKS5+f0BfaHZtXy2R9T26TAuo5raeCjChvXtOzOX7FQKFln2tzAfNHmr84ABO3LhQ8metw3GG\ 37539# fH2Xh5s7lQY9xJYJxLiJyE5aNNWZ+clhL2JJ9sjYprzjBdUUxM22/3etGmz47GOsr2E8MHmcHTT3SVUjZEmbPRVZWdjxUxPJg1GLx72R4mNS0avu2UVV\ 37540# cM+mkmDou0wDR5NNS7lY3+UkKBswYKyBNgWL6XRmNEj7WHHZ6LRrhj7q2zPPivLDhyKl5XFK4afv8l/7iccu3t+6IPmuwAAAABJRU5ErkJggg=="/>&n\ 37541# bsp; <a href="https://911templates.com/30travel_presets">30 Cinematic Travel Color</a></center>"} 37542 37543#@gui : sep = value(0)_0+ 37544#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAAAgCAMAAABAUVr7AAAC91BMVEUh\ 37545# ISH9DA39+QAhJCkpKSElJSElJDMxMCJFQCE4NyEIXKcmPyIqNSH80gUTJrp8HLEmJ04fOEgzJ0EiLDUhMi8hIib8ahT1phACygX5xwQFsdYbJKUjLj8gN\ 37546# TlfIiw2KyJfWB5oWx38gBhCSdiIG7tyGqsUH6TzEJnsEY49J00dRUr8Nzr31DA+JTAu5i8hKC78xyEzRh/3tBj3rBcArwYFvwRr0gEq1vEBgtEBo8wDcL\ 37547# 4TJKxsGqPnEoPlGn/kE3cZVF9HK0ovJjYsLS4xIitTJicqIiYhSiL5mCE+PiFgOSFIRSBWUB/6vB78jBuEcBkHtQj5ywOT3gAAxOAAu9sueMsCZ7UUIbA\ 37548# EU50yN5cdO1dWJUFKJTexKS4nMCr68icvKiNBLSJIMSEiWSBRSSBgSx/76R1lZRyUjhf8dBZg0wj37QMBuAKk4gF81wEBqcyLPskCecj4Q6buOZnWO5Ic\ 37549# SXghJXOdJmhoKVptIUgbVz5SJT79jTd59C1HJSv9/Cjg2ya9aSZTMyK/uCEffyAfah5PWh6UGx40Uh00YhuDfRl0dRj6Uhf83QZazgTt9QGD2wAAzOadS\ 37550# OKURNcCrdABw80ksMYtbbgTVLZVHa0bmKtwH6u0FqkLv6CkFpVnM5QZWZPPEocdK4YtNIMacYFjH3BPJ2ruLmkcNWFEJF01JVdTKlUfL1RaJ00HpkH1DT\ 37551# 47JzzyijrlfjUfPzL16S7gzSv8fivetijNpSRz7COARSKBJCKXeSGgKCGskyBFkiD3CyBtOB8+VB39+RfU0RbGwxZMbBYMkxFxjQz82gjx1Af43gRGyQE\ 37552# sseIXvN1dStM3aNCGNMYCkMQkbr4DhrhwHrh+PLfBPrNQKbAApq85IK4mZ6MJkp0OaYXxEHgpxHITZmoBtmgZTmD0TzyeFzQ62y1p3Cpm1ypixidXuiXS\ 37553# 4yObYSOSUCLLhx5LVx6R7B37nhx9XxyNWBs+dhpA0RlYfRn8MxEUnw3l8gaOywaizgW15gMlxgLHnPo6AAAA/XRSTlP9/f39/f39/f39/f39/f39/f39/\ 37554# 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\ 37555# 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\ 37556# 9/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39wCUWrAAAA0ZJREFUOMt103k803Ecx/GFbLNpmTW1\ 37557# piHLJmoSMxlmreauoQO5ReQoldwlUpR03/fpzH3kKDfRfd/3fd/nH31+3x8P80evv5+P9+f72EHoa+i0aVNNU1NlYyCZLCiQE6A2lKAUCAC+Pj71WfOgx\ 37558# vpmp/QgTsAgg0BC/JLj41FPyleeckoP5MCQkkhKiI9bHHd8CGpddXIZoKABM2JqadLyJYvjbO3szuCEyaxOLn+LmT6hTpeAACAWn0SEuYDJZCaXvQklEd\ 37559# Vw4cA/FnvD1s5WLOYh8t3AYAEguUlDqCMRO6XqQM+/vnn3Plsxj8e7j+64uQEy0DGpcg8hq6Ez/P2baDbcfTyekZER9hgDORg3cx0dk1p9Z5hRVacf23z\ 37560# Jhsul7QFx8GlWVuNKuVz+0XWSuc4kkwYXshrcgZHdNlwazXDPwfgE+HCdmj+/Mxe4umIzNfokIkGdXhAbi4Qh7ejy4iRfmSw99FOtQIDPwGsI6sOXXbi5\ 37561# kwvC8GhhYbGPb2pgICnUvQYnlU0ujkAOjx09bvTtndds8vkSicTUlMMhh+g3CQSjIP9VeiQgc4FMmT1s2KECPl9S6iANCCCS9LK7uzU1Z46aX6WvTJYNp\ 37562# 9PpDlKplEh21nM/ux6RFYNJEZutrS3186M6uvyHHDqhxdbVZvhRYSQsvAcnbYgcxsgOayvrpd5augwgZu/DctpVIiN7NGfiz2WfuLhDY5b1IiurA4+NgV\ 37563# AoZqtzwiNVsCL9w/XIBFV20XYvDdzcszeuANHS0dWmgmqtzA4Boq211EtjDmZYHncfJgYHr+3o+v1nAyJp7WHORILqRLb39itzwIg8Nm7cWtLZ+eNXVJQ\ 37564# iCjOt/uHY1ziif+ayp6eHx9aRUF6UQpGnAJO2Kgz7MaCZA14aV7ewWJ6eezHSq8iLtrSM/pm2IgcbgWDG+845ligG0CML6G80iNzcD6+zV+M/THTKfpvw\ 37565# vEgUE1OyEJphaRmRG5Hy/BuI/r/ARF1j+11CIUt0azKqNyKiLuXllxYzKhLoFGaObBMK91rMgCy+1qW8OL12DYUKV5SMFqBdDyagnr0CABMDAn8PoMTEz\ 37566# MyMjIzM4OA1ZpTBAh9iMBgVlOlYFApVCfwDpbUmiFdSYzcAAAAASUVORK5CYII="/> <a href="https://rawpedia.rawtherapee.c\ 37567# om/Film_Simulation">RawTherapee Film Simulation</a></center>"} 37568 37569#@gui : sep = value(0)_0+ 37570#@gui : note = note{"<center><img src="data:image/png;base64,\ 37571# iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAC91BMVEX+/v78/f4nKTn+/f4nKzspLTxJQkQlJzh3odlzndQyM0EsLzwlKDUlJzD6/f6X\ 37572# xvmUwfWItuuFsuh9p907OkExMjw2MzUrKS/v/f6PvPGMue6CreNuls5wXVpaT01SR0c1N0Y5OD0mKDcoKzUiJDX2/f2cwfWXu++KfXOHdW+UdWiDcWeQ\ 37573# cWSEa2JxZmF9ZlxpXVhtWVRUUVJGS1A9PkdDP0BAPEA/OjwrLTsmKTosLjgiJS/R9v3B6P2byv2lyPv6+/pvmtBskstNVGRnX116ZFx1X1hGSFdaVFFh\ 37574# U1BOR0xBR0xeTkovMEBFPDw+OTkxLzcpKzen1v6j0v6gzv6ozP6t0f2fy/3I7fvr7O2Ltet/q+J9p996o91rkcZpjcVlisJfhbxhdY5oeo2ejYBbX29o\ 37575# bW57YVlfXFdlWlR3XFNlU0xoUEtLTkotL0hTRkQ2NUIsM0ErLkFFRj8vLjO23f6s2v6x1f7c/f3h/P274P2w3/yQtuyEr+VwmtJwj7uJna1ogaWYnZtr\ 37576# gJt1hYthboN5gYBvdn2WhntaZXpda3lsd3NPXG12bGl7b2aKb2R9bGN5ZmOAaF9NUVpgV1dPV1ZUWVJTTkxXSklbSkZNRkQ1NTs7NTY0MDEoKzG32v7X\ 37577# +/2exficw/iUu/D28+7Y3N/t5NyNstrH1dh0n9fZ19XEzM7u28FiisFbgbhZfLSzrKSlpqDLtpi9qJW4oY2Ulo17hYhbbIaki39jaHlMXXeulHVDVmxP\ 37578# XGluZmRrYl87SV9YYF5bX1tiXlVnVU8tNkpGR0dFQUY1O0FZRz83OzhEOTfo/P7n/P3l/P3o/fzy+fr8+vKo0/Hx8e+cwezc5+ql0er17t2gx9210Nyc\ 37579# udyyzNPT0dKbtc56oM6Kq83z6MyEocqDpMOGnr3izryhrq7Vx62eoKuCj5x5hpvGsZpWdJqil5KomYazloKOeXKPhHGMc2tWWmsqV2qffWZxbWZdZmGE\ 37580# Z2A2QlpUXVmBaViAZlMyOlJoAiFnAAADzElEQVQ4yy2TZViaURTHL/i+sIG4OYkVIKAbDOkWN91AWsBtujZm94x1d9jdrru7u7u7u7vjw+6L/j/c++H3\ 37581# O/ec5zzPBRs3boiPi4vp171v+3YjhvtNnT596uShQydNWtrTk0lgQ3x8XGxM9yntV4/w83t7KJemNJt3Pu7Yo0ePxUvgsRTEr4+L7Qd5uxHDYn55e3vz\ 37582# 3I3Uk4aZ10JDo0JDBy1eAtbHxni437AHx/V6PYVB5ygJisqkO9Fjo6OjokJBLNZ9NeST91D0FArD7co/kaWQW15NGL1w4djoKNA2XbdO3XIplJaCZheb\ 37583# xaqVp1btGNy794TRo8cCyLHyTr5TeXpKAd3FljLFTOZBY/HzkBDMARjv1snXt+tIHoVRcKbByjSVlwmFQv6azuMXQQV4+NCuXbsYWuCAOcdM4RVCwad5\ 37584# iR9WhAV2HhcyGLQbjvEuHVfWn2U0c+RMcblIwE/c+mLdMhzO5+K4EAC5L+QdnmaeduXX19XKjWX8XVufXcZ5AeADuwCsP+QdkjKtBGm4Kc0iFfN3bbmJ\ 37585# AzC4wPPjQCvvs9ImY9WlSCRHU48eFMx78ygMM7zgEwCOB/nAh8aMBodEJLSkphlL+O+3rFvWKlwAEEM+4L6RoGJJSoMq0lIPFAvmJW7bdBUTAs8BWD5o\ 37586# 4ID+08Q2p0MS1KvX5zJxyUf+9hmbw+AMuMDOwIPHXJkrPqlmhUOhl0giKhVsnzEE1yYMgnjijfnFUpWmDgpBonKmNVxwD+PQ8AkEEE+8VUSqkqmobGZF\ 37587# qcnCYrOk7+AWsMBdgSfTdx46TiZT0wicBllKSobVwbZUrWnlwAve/7LRSC6PnCtnczSyn+np6cdkKcIVONihLdnZeWStFv26T6Th2GSm9Myc+sRNa1dd\ 37588# D/MoXjiQl52HomRtrrLWSWtUEwiEnMxtcwrnTFvlWSVYDlAUjSCTecGjqBp6k4vDURP+7k0+kjztro8XDO4lIOpQMh7VQoPmzFGpCBpC0N4f1b9n3b4U\ 37589# NmTI8rW7ARFBETyKx0fSSG4H25HhzPhWcthePWvujrkLEmbO3A3weAQPg2hH0YKDqeo/p63S6sN2e2FhQsKC2SNHzgZ4LjR0eIQ0KpgX6VZqmlroarld\ 37590# qagxmxULEqBA5OoQBNGS/EnwW0WSaU59AZ126kR+lmJ/TY1h33wQoCPqiBH+/v4kLhS8kbMMKuOU/fuZLMX8I/lmwx4QEEAkQoEEBYTLRfD0ZhW1slFN\ 37591# z1Imb042fCnChABiXgTJPyKAFozoUHcTg5pkq7QdmPN6RtL+WUX/AdPoMUu7nvi/AAAAAElFTkSuQmCC"/> \ 37592# <a href="https://www.facebook.com/eric.ellerbrockom">Eric Ellerbrock - FreshLUTs</a></center>"} 37593 37594#@gui : sep = value(0)_0+ 37595#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJsAAAAgCAMAA\ 37596# AAysvoIAAAAz1BMVEUAAAD///9AQEDQ0NCFhYU+Pj4EBAT+/v6ioqLk5OTi4uL29vYKCgrr6+t7e3v7+/sGBgYnJye8vLxcXFxVVVVra2v09PQ1NTXu7u\ 37597# 6srKyoqKghISHLy8u2traysrKdnZ1zc3Pd3d0cHBz4+PhgYGBFRUUrKyu/v7+YmJiIiIiBgYEVFRURERHx8fHp6emOjo5nZ2czMzMvLy/19fXGxsagoKC\ 37598# UlJR4eHhSUlLV1dWEhIRKSko5OTnm5ubY2NjOzs5qampNTU3BwcFtbW0lJSWTtii3AAADCklEQVRYw+2XaXPaMBCG9w2OxWHikDRgwBAIR7hvCFfu/v/f\ 37599# 1NUiDKFM6TD5QDs8H+JIWsnP7GoHIJwuZ7fj3QoXp0fBuF3S6XF5dju7HcG3uP0IrZkQhUL+NVEuFHog5ioU8EF0EwyqOkR4nAxoRbWRf/XTbw5pTNxNP\ 37600# UsrKjxK0wqzc1x2gqUV4d/c7rAmR6QQ4x1RIEHMBAEeUSQYLHWIIfZGTCtTgtD5QUwQ2X4nIcf/u30SYFDxguQmCPb3uRXDQmHX7ZYnR8AzP2rilg4LWQ\ 37601# nJh8OZIstxFh/4qYq5XBwoleX1boZXnwGvRUxCzMekMYt5Pk6NV27RsNDY53ZPhh038QNuiBG3BzLoEF0v5xWwiD44YVM97Lqhhbw+ds2PJkf1iOkC6ST\ 37602# aLeOW1Iv2VQmqLG55MnyrG9WBDC0USqZgKaKNG2XEnOw4StU8UNi4yV6F4kG31yvh4qBbV+KergM32wfqVNOCARs3x+StDIxoAbx8dWtx4rLa7eVKeP9D\ 37603# L3QPuRmGTQnJ1Gr3MwV3QI/Ana5cWlhdqXteLQJtjiUfKOv9qrLtJjMX2s2wt09jcWF+0M2TuKi4GZKfpN10t84gbPepp2/h0oXHNnMg/9XNg1pqt1Jcm\ 37604# OxzC9sCHXSrmkAJKc48wNeBpqbh0ch3jZt6mbXZRS7omI9IpVK3CsPstlvfhWppt5wtfGMvJOjSRTKrz1NwK6S5bhs3PoZdoi3drW0E1LfcbE734zF9Or\ 37605# A1u26J7bxlJSOPph+H9YTjDCaciqAXblZX6AkbOra4tWzbqfi8KUVH5K0T0Qx23HhW01+7NTtQPZ2uvAJcz9N/64FbdQh3QVTkF6Q0lSRwKwV/jkR0bKx\ 37606# M4haLCLm/czOkdtwMy7UbfSp4Uuhe0QXj+hUK3KgLRJ13BfcnCWlgFDSKiuWqhz6z+pY1DdzmVkNXwTI0iaqWVSZBZgW2KViWYyYrJPR7jUY5QYIlx5A9\ 37607# t6zU1LIKtGLA8w5ZQmFqLm8iOLb3T31HOjHObv+v2yn/dj5Vzm7H8Qt/zkuzg1TiwQAAAABJRU5ErkJggg=="/> <a href="https://f\ 37608# iltergrade.com/free-cinematic-luts-video-editing/">FilterGrade Free Cinematic LUTs Pack</a></center>"} 37609 37610#@gui : sep = value(0)_0+ 37611#@gui : note = note{"<center><img src="data:image/png;base64,\ 37612# iVBORw0KGgoAAAANSUhEUgAAACIAAAApCAIAAADf4mxWAAAKkklEQVRYhV1XTYxdR1b+zqmq+959P91td7fdjp3EsZOZJNaAEjEjmAi2CCFAGjQLZsVi\ 37613# diPEAokFYsNqtiCEGFhPpAFpAEUIxI8gIghBEqE4E0JiO7GdxG33z3vd/d677/5U1flYvG6PmaPSlUqnqr7zW/cruXh+jSQhpIiICmOM6nqwTGQAqmoZ\ 37614# oiRJEwpWQmYBeDYxCqAGKEBmwAAAutJ7MSTLFBicJTiaiApSNjrniWRmFIAEBGJnO01ESAIQkVOdnc3FAQLAzEQEgDeB88HMet6VI2dSqLHtFlE0G0GC\ 37615# TpSnZlMhICmiK3tXp5y6JCLQMwsAQIiV2huZjJLsucvbX3vlyxvPvlyqvvPOWzd/9MnJrA7e5aQZ5igAZOUWV7YqQNIewzgRAwU/Bn4smkGngaRaWh/o\ 37616# 9vZ2v6eSUuGVzEwGmMA9uUdEACVPvyRBPqHCWWJAAcUopk4ASaIUp73B0Lte7JqubYXmnRM4YSZJMSJzVScigJ2N0zwLAZiQjzEAiJzCqxDCRGEoB2ub\ 37617# F4eD9a5uLJqqmpkZnNPH2YYYxER/fJaIKOQM+9QPgcHI09pEBhWidIHJMS6HozVfhNQem2TAU+h9Z3DeOhV5HJOcsxr11FYznFaz8HTQnJytV4KkCiAE\ 37618# SfFhMBg5J03T5JxVIVBAieycO2uPswpWWU1NTn2i4GwYlCRXASOphBcz5xyZvSsG4/NJbFkvVF3wCgDiBBRR587idgYGqqpmJlGQRiPIU7zHFQEQEBG/\ 37619# QgPgQlGO1xcns6ZpiqLo91eNqaKSDHYa9Cd8AgAEURgBoRBnGcog1JkaqSBJ6mq9iPhQDIbnEOt62Ybgt86vJcIEOWcz2BNCgCuwbKvIqMA77TlXhlAE\ 37620# 3/M+eA3qgrrgvXfOq6qqA6DBF/1h7qqmSf1B2e+NLUMKJMtBC4o4QgmqOOcIWKIKDAYhIA50KipUwKAEM5lXuQU8xRmFFFXvQ1kvj9smPvXsJbFeSkYx\ 37621# gVKMJCAkxUAlAYWtGkNFvKBQUcFKQwglGySZJRCi3gwilixDJBT9ZTWLZufPbxxPmpSSGbzvp5RWoQdgZkwEoISHd6IK9FQLFUcIIeLESWeg2spbFXgn\ 37622# KRtgor4sZLactYxy8cL2wwe3Vb1naDWH4MycqQR1UUh0AwhQWO6cFN5b4VhCvXphciKWQ0/YJBqdeN9Y9CbiCBFCnNAmR7u9EltbG/PZTFUz1dq4rBdG\ 37623# Z5oVaAmV0FlUQc+HHpLz6Pl1r64Y2rpfK3WwkKqqsplBXRW7wqtPmYUKmZ0LTHW1aPuDwXh8rlrUIYiBX3v1xa+/+qU0ui6aNFbLRbVc5Gpx3DWT9mh6\ 37624# 0rmQm3UUIetgbbh1eaev5f7ew8n+0d7kcFZXA6+VZW+r+xw5hF5THU+my9HautMiNtkHzTk+f3XzV3/5Z6/+zG90kTTnNGWaifm4m/Zu3b93a/LFybIj\ 37625# jGuDzfXLLxVr5+689+6bf/XG8bH2QxG7xtG8emdMJIog86ODRTV78YWnhblqaqW1WdB13vUXi4g0hxslOLMmSZFwqXfh0uWNy888+8X0we5sEU2KcqM3\ 37626# 3Dp346uvHtz68PbdT51zJFW8V6GZgBIkV7Np23U7l7abpk6pA1TMeiFsX77uR6Ucvt1V2a+/EEZb4gqhNS1l+NMcP/fMU/vN4afLWZVyk/bvpKb66s/d\ 37627# +Pe33757/7Do9eu69jlHQRBxqV0cTQ/axi7vPH00mbrgVSGA9zLcerqpln/9gzfe/Z9bt+/ONst+Ebh15crvffd7IVg53Pnh9/7y337wF+vr66/90qs3\ 37628# vvLMYlaPzunLN57/6M6u82Vi8kKDqIhrFkdHh5PQKy5evPjfn30izq3+jCGE0eZTszvv3/70k7sPjm5+dM8lXTT1jRvTjdJ1Ohr0yzv37r35Xzevbl37\ 37629# +Nbd7/7Rbz17bbxc1Jvb52KM5j1WlIdi6tzJcbN7OOv39Pzm8OH+pO8D0Weue+UaZG1+MrHsRr2B9EIYluNhOR6Pp/f+AbwHMy/FYKypxO7e9ESu7Lzy\ 37630# 81deulquh3lCQk6EFxFVOEXXtccnJ1tbO2UxnB8dlz1HpAz0hwNBrGaTxWK5vbkBQ7IULSfjP/7TW1fPf/Dar/xa0xzGLMSxcD4eXkDxU8Xlq9h4r7LY\ 37631# Z5HR82ZGJrNUNfXJfH5p5+kU25PJxPtCNGeBK88Jw3TvQU649qWnCgmUlBPVhf29+Wd3duvuZPeTj2r0Z11hZeE3lAJwnLDWCqL6SPOqzkG1KGhaLXnt\ 37632# y9cXTZsRisGIKTqouJEAB3uPIO7K0xcLCcmiKAEs5vXB8cnN/x09mlUs0LRdQzIEoBMU0VynoYpdZ+aVSogZDg6PF9Vs/+hvf/g3/zo/qdt4NCiL2NSu\ 37633# cJB4cHBQjobjjXHbtiEYU3LKxbJqq3S0OKqPzayrgsfMtQ9v8ivPd3KhJUl6DZ0mLyJCEe/rmJuufTS5HxOchixxY9RnRq8XECcPH00uXNgO6qpqvrk9\ 37634# UtXgpE3N0aJmr0ySiCKbpJ57+63/7IfFy699s8+lGQwZSB5GY3JeRJV0DuiXvdgmXxRmJlBIaBfTw4Pj69dfqKsGUIorfBFCuP7SC58+fGd+dHgcq2nK\ 37635# A8tlP9z//ODNf36/OV4+uPMeIBEZTB4AkUU8YRmE0xQbBbMpnO9I7/3+g0/qqt3eOncyXxRlH+q6yF45/O3f/Z3ndr7/xt+9GRv21StjJOYp3nqwF3O6\ 37636# ffc2NFmC076KiPfeCMsk1cxM1RB8Uue8CDU2+3uPmjZubG/vHU2UKtHlvs5n8fDzz7/x7d/8/T/4zvnNdabsvF8rtK4Ws1ne3T+cL0JpqhQi62OysxIv\ 37637# KkZVBcCUlGjr+e7nDyjh/Lmdw4MT8c7gveuT6U//5M++/8d/eHFnsHVlPdGyCcIgEfP5o8N5dTSfaJE1uJyz/0nqbsxmlAzSNKn4anH0MKXhqPTeT6ez\ 37638# 0PMiatkVXg/2Zx9+cPdHH955eHffeUZGy7Hw5d78OGubDckgKUoWPSPVBCCWBc57f8q1AKo7OHy4t3dwfms95a6qKjjrUlS48XAQG8zgPv74sDpuxSwm\ 37639# QNpvffMXvv7KtVzXdd264MUVIk6fQMHqdAKGTEFMJqqH08n+3vTS5Uuz2axtojqSKcUaaNrYsF5Gyx068Y4SoDJaC9/59q9/6xu/uDEqSUU2E9OfCJqZ\ 37640# pZRMICIxw3mZz6rp0ezSzpXDvalFQzZ1yWknmlJeSpKubjKRjYzLcbn2+uv/8uev//2LLz5z+cqF1HWCrI5P5EYIQhyQ4VUsw7FnqOezhk53dnbufPwR\ 37641# SOdC19Q5x6IY9PvhcNH46JlU1TufBr3e/rR+6/3/uH3/7he7E69wznVd/H/eiAhWfI60lL0WzNY0yWkYrJXH08nG2jjHzEiFu/XR/b39+fG02z1Y1BZF\ 37642# LYs8ms2alHx0736wd/+zaRFKy6JSyPZoDA9VTTmvnkunTNwHiwlAEVxZ9EbjUuBi200mU6gIXJdTjFGUKt45pw5Q5JxzzE57BkJqVW/ZZetkc22oqhAx\ 37643# swyG1VPs9C2mZGY2VWWOJL33q3YmmWgASJNVuYpAGHNWSuqyCwXRkGLZmaX/A0GLBDxi5LN0AAAAAElFTkSuQmCC"/> \ 37644# <a href="https://freshluts.com/users/64078">InAvision - FreshLUTs</a></center>"} 37645 37646#@gui : sep = value(0)_0+ 37647#@gui : note = note{"<center><img src="data:image/png;base64,\ 37648# iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAC/VBMVEUEAwju6+4FBAnv7O8FBgoIDxju5+oPERcICQ8HCA0GBwwLEBkRFR/u6e05SFU6\ 37649# PkYzO0YSFx8MEx0HDRYOCQ1aXmcpOEcgLToJCxFHT1lFTFUtPUwsOUUhMD0YHCcTGCEKERvt5OdrcHZdYmpUX2dSWmNKVWBQVl9EVF4/T1o9S1c3RVEz\ 37650# RFEzPkomNUMlM0AqMTwdIysKDhUGCxPu6evDtLh0eH1ta25XXWVOXGVNVF1JUVtMUFo/R1ExQE0vPEkqNkIyOUEfKzgjKzYqKzIiKTIgJS0SFhwdFxsQ\ 37651# DhMLCg/ZxsjIu8DIuLq+sLO5rLGwpKZ7foSThIBjaHFpaG1lZWtZW2NLWmNTWV9QVFpNTFA6Qk1MRUk3PEksPEkuNkJBPUEoLjobJTMmKC4rICUgICUV\ 37652# GCI2ISAgGh4QFB3m2t3d0NLVwsPOv8O7sbnOtbLIsLG3oJ2mm5yYk5bPnZKGh4l8dnm6eXJwb3JmaG5ZYmlVWWOIY2FKWV9DT1pATFiKW1Y7RVG4YUqP\ 37653# UEE4NjscKTcdKDRwODAeJjBFKSoTGyQoGh4xGhkgExQUDRDTwMTLvcK4tMGvr7zKtLSvqK63qaver6rAq6q1pqepoKGXlqC5op+zmZOVkJKrlpHKl4yB\ 37654# gIXfj32JeXxtdHh0dHZwcnSmfnJobXJoa3DEeWxeY2xnYWhSXGWfa2G0dV+4bV6ybl2QZFqZX1m2Z1WBWFR5U1CRVk5GRk5lQEFWP0ExNjx3QzhbOTc2\ 37655# LTFOMTBfNC0XICwdHyo1JSc+Hx04GxsWFBns4OLp3N+/ucXAt77MurzQuLjRsanFqqmfnKbQrKW9qKWqoKLCpJzZp5qfl5nFopi4m5WHi5WgkpHfl4y7\ 37656# kYWch4WYhYF8fX+DfX6Jfn24gnt/fnunfHpeaneRenWqenKCcnKkeXBYZ27BhW2Xbm3Kf2yTZmZyYmRhYmN2ZGJuX2C/clxKTlqqalhYTE4+Rko9QEpv\ 37657# SUaBTkU2OUFNNzY8LzJaMSoaIyUoFRRPuIDSAAAD7UlEQVQ4y0WQY3RjURSF77y+l4ekQeM0TdJYbZPO1HabqW1zbBt1O7Zt27Zt2zbW3FmZtWb/uD/u\ 37658# +dY+ex8QUSoMDAxiMn0Xzu3RgUajtXN0dGxjl0MbBwcH0Li3KCfIzdmk8knv097VTvwfQyCCLcnOczeq+Bk+N0627+D6D3CEAIQgEBakyx7uru2fnt4v\ 37659# 9dL5rtAEInYLO1AUmufm7MzUZKgy0udf7tEj0avjYWhDo7nS7EBJkZu7i8DIzxzIV/VPndl9StduiV6dxhyL79y5oyv0AaVCFw93qWmokck06nxuzp7R\ 37660# dUq3pKTELl4JCfHtj3ToCGqlppBQaQhcE8zUqvqlzp5xduqkSRMTJyR4He80ZuxYYAmWuki1ZmdBodkwWD1gyb3ePadNm5qcnNRtwuQTCfHxoFYoFIa6\ 37661# ObsLgs2GLPXgLL+nix6+efs4tXuvUxfOeHWZDmpHh4fDGIKQQrPWb2WWXq/ZWBVbHtu07tnMXnOSrriAvaWjw11gzsJgU4BGbdDrc1t4vNhDtt0jF6++\ 37662# 3uVBISgNFwo9BAIBc6hRO4Q5RG9k2XitzVVVLSNXj1g8btx4YHELDWFmqf1DpAKDQZmi9sttInktv3/W7Rm5Krnz0fEgIlxq0gebhvqp56YYFviZzeyd\ 37663# X3c0HzxQt667d8rpidNBvcVjdKjH8AXKnhfP9Z6lFK+YP2jzmrU79jzq1DNsyEptCpBFscXeqt6zvG/3ueozCufNeb5+zbu1H570Sc4JioqSMUB9hHjA\ 37664# ALHmjs+i1ywSAWDQtvUbRsx7UUXimRYZ7ikCubmSwADvpUsXZn+KAVCxW5dtGFF3AKGI6PdicaAvSBNn5ATcUmoirFYUIAio3Hpt3rKDCEoSeGAmP00J\ 37665# lvfr7z04m8W2NsbABQixj7d/1bA4gJKUiDWQr/QF7C1hkrBoOYfD8fwLMHD4ogSgCJT4rOMv8Qf1siiWNQanxzBEMAHPhsRFHqJq4AqEYOmW83VAVsmo\ 37666# lFVyoEg4v3u/vLqsjEVQNhQCA9MkvoAhp3PkcjlHzkABqO77cr8nhX1DCZJCyDBNWh4fMBg1jBqc7kkXwQrf+w5rwHFPGYB9EHS7vy87E9TQ6QwnOr0t\ 37667# RsC/TX0bmnCRaNcPkiQpKjpAZ8kBXC7mBAG6ApZANm3+0ozvHjZ5G4qiFFUi8S+RAC6mwLgYxuU6VVTj5a0AKd85qFcriiJoDDvI31IAuG0xblsoLLL4\ 37668# 4/biONGujQ35r/KrAYJGF+QFsEsAxlVgmEKByUflR0b/Yo0qjgUVKyqK8wEqiiqQFFmBAlM4/VVjZJm1rMIWBw9JbImM4wGEwtnDC/b9AdM3HYNA1prq\ 37669# AAAAAElFTkSuQmCC"/> \ 37670# <a href="https://freshluts.com/users/120">J.T. Semple - FreshLUTs</a></center>"} 37671 37672#@gui : sep = value(0)_0+ 37673#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAmCAMAAACf4xmcAAACMVBMVEULF\ 37674# iILFyEOGSMJFSEOGyQOGCELGCITHykLGCELFh8JFh8NFyEQHSYSHicUISoNFyINGSULGCQWICoJFiMhKzQbJS8mMToKFSIdKDEZIy0RHSchLTgZJi8XI\ 37675# iwTGyQQGiMpMzsbKDQYJTAKFiQ4Qkg0PkYlLzgeKjQNFh8yPUQfLDcXIy0RHisQHCkWGyRUXmojLzkjLTYTIC0PGyceHyTr7/jK2eyhssZIVWFDTlo3Q\ 37676# 047RksvOkIuOEEtNz8pNj8nMz4eKTMaJzITGSEQFyHe6PTV4O7D1+vE1+a+0OTH1uPCzt6VsNGdrL2PlKNhfJxqd4ZocX4+SVQ6RlA3QUgtOkclMTwXJ\ 37677# C8aHybl6PLT4fLQ3uzM2erR1+O5zOOvxNysvtSEps2jtcqNqsiAocecp7hohaR+jaJyfolSaodLYn6DdX1kcHtnZ3RZZG9JWG1LWWVPWWM3TGMyP01GR\ 37678# EgqN0QxNEAjMT8aKTdFNzEdJSkzKicXHyHk7fbG3vbN3PTW4PHM3PDn5Oq2z+rC0Oa0yd2sxN2ivdy6yNrLy9avvs6otsmTrMmmrsCUpsB7lbd5krOMn\ 37679# q/VuJmFj5lsgJlYdJSDhZF7fo2ciIxvfIuMg4Z8cYCDbndeanZCWnNiYW85UW9OVWlhYmRrWWSJdmNiWmFQU15LT1xXT1oxRFo8SldQR0snN0oyPUdTT\ 37680# UQ4OkRoT0EeLD5IRD0uLTcyNTVWPzIfIzA7MC4sKCsgJCokISPHXUUCAAAD5klEQVQ4y0WSBXfbMBRGnxRbppniLJx0gSZpk6w0bFfumJmZmZmZmZmZG\ 37681# X7dnqLBPZKPYl19T1IM4PMB/YcBGd0gHhCZ2kTTDJtWJfv22/2LW/ylLDQZdM02dCA45ppKq/r2+3BpN6CFGiI80Bo/lgjouFBHTZZR+7qzH/g4clITo\ 37682# gzu+vVvMkBsaggNi+7s15dreqawR0Nsm9KQ83B1vUcAqA18b6h1f+/uAUDNy+g+7gNCb9/ZohKqyVgZV2Jc949kD86GdJ/nAeLjXX3x+JvnUkNiPkIMo\ 37683# jJmzNBs1CCkY9hfqp5+Lm1udChzfCoxDAMrJ2XUMA47j0LfrTt5Y/Xa0acm9LYzoPlIIdlTmFFlaKihI7ale+6Evf0PzZx7YM7ARjmEe9YL5pdPM6pk1\ 37684# IDHAYe4U8cO7d9/7sxhC5bvcDyZkUKg77snj3r+pglCGTZw3ohZJ4YOX3lllQNJanfv+vl6yx7ZIMAlnsbJeAMPzh95es6YB+fukRDB7WuFAj9GCAjhj\ 37685# sBlAxcdPTJq+PFVs1+Cx0+laTpCdNR0DiAE1KULRgwYNm/MyoubPJfoREMIERpHJSri0rGjhw2YdezC1UWbXFtV+aWhhirIMpUrMMYcZ/mooQNGLj4/f\ 37686# ulElzJbNiqgDZQjNOpIN2f3HzF/4Zjx97cx8VZggEp4OLUqRZ3ma6OHn1mycPzaXY6NcQSNCkAQzeyt65X/iz0/O2DxsiXLroeT+IufUcA1zNMqd+yBv\ 37687# e3WuP2H9417z+wMIEQgNB0712wA69m4USPHTpzM+Ecl5jjAs4iKI57mQeOGDVOb8oO220zHGd6EpqoMG2PYwXUdZcKgmLN1Ui3gxH8IUCoJKB9Rc/Kgd\ 37688# NO6urxDKWNiNQ+CaNQ0eeuFmKaU2Di1nB60rrHp71Jhg1+gKKap4ENpHRxT2qelTL6Mi8KFSCSSSCT4g8t+q94pK1asCQsoJvcEEO6NhMPhThxEEv743\ 37689# eaS1T74bVkRYGpFCwgaGgKBMHrxNZPjVmzFYMvycwktoQVzuYaGXC4XzDVwr7NuRcKyJq75k/UnjEIw2CdY6blAJy9/eVLAsgbXFYUnwvAIfThtbX2Cs\ 37690# Xw43jsS2DgpGPHXNVuWhZY4BJMY1LS1ttZks63B2q54vFicvjnvN3s1x5rEBVmYho1CS3ZKtjpb01bfmS4Wi+lXZWASje7Y7jBGJSVuYWGJMWhpaclWV\ 37691# 9e019em0tPT6S5L6RVV0ltLrhS1FKzMs7Bodkp19ZAhQ9qnxWK1qVRXKh+bXnKcUpcLUI5iZUlCD/c2pQa9jo5pHR31tSjmU/l4vAwcH7gsKjHqMvob3\ 37692# PCdJnRHhgoAAAAASUVORK5CYII="/> \ 37693# <a href="https://sellfy.com/p/SGnG/">Kyler Holland 10 Free CLUTs</a></center>"} 37694 37695#@gui : sep = value(0)_0+ 37696#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIMAAAAWCAMAAADU6N+kAAAANlBMVEUA\ 37697# AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAABH0wLDAAAAEHRSTlMAv0Dfn4CP78+vIDBgcFAQ4LAwBQAAA\ 37698# opJREFUSMeVlVmy4yAMRcFMNuA47H+z/TQgMSSp6vsRhAT4IAQxoBMUill1gdCd/Z+sTagI4iG5ettQztrbmOpAV1+h4oQX2uUF6pFy3BEUqHs00r0yoD\ 37699# dZe7ZduE5cImdlwzIh9RIwPQ5tMEuww5wMI2Nr7/ebJz4ehLg3+BvrLSJvzdGtARQaiRgsdml7nlcLl6xIMUy0oy4xVCIvnQ1iu1qLSQFE3cMML/mQA4T\ 37700# OOc9DhtJGhkDkHnfx/qrmZgBJ0cjgpO8uwcN2ZYgTg2Xcxzzt/xl6mzilOprsnYHOwvWoJXaO9CU4qke+M0h6+0rEcCrDNHhZr+ih8b3ovdLZ8FfyuDNQ\ 37701# cS+1Wem6qWcMTugJhnphyGNxlFsPUKzrOIRBvfZPMwNeq2v0zQxq00siS3mj8K1V+cYJvr522MlQJ3bGhOYFQUplcDNDkaUqMejCPM572Ttcm8+VNZ69f\ 37702# /CC7Qz7TGII+oGFQXaVWrd+MWg9AoKW+n59NwYrRxFAyiC5K2PBXP2AvjPU/Cc+1P3jc+HMDKplZpAS8UYZoFXhxRAL5KJ+c2p7w0qVGVTKoJmV1OSRQR\ 37703# PF0t5cTiLuqpeQV4b9CXEvKJE+Whnu8fk/ve764sCSF3sLw6RfDJ32MMLgJgbbD+iG9ET5o2BLGW6zFPtvhv0dC/pkEIMXhu5EyZejWJK9kaF9ZIirUw+\ 37704# Sn60yMlTsKEOcGVJWhkZQwtAWBmXMnbjLcou1gEqtCcNDNjA0bJmB3UGsi1vDyrymnas1HTydwzGAsk/UrX164Dh2Lurkg1rGrGDj81QaqdrWM8mYHpSL\ 37705# ayobMwVfAVSz+arDgwrt5wDlbgjnCaqAY0EvUwLo+bAaK/fYPzbBi89MLkUDAAAAAElFTkSuQmCC"/> <a href="https://lutify.me\ 37706# /free-luts/">Lutify.Me Free LUTs</a></center>"} 37707 37708#@gui : sep = value(0)_0+ 37709#@gui : note = note{"<center><a href="https://michaelezra.com">Michael Ezra</a>\ 37710# </center>"} 37711 37712#@gui : sep = value(0)_0+ 37713#@gui : note = note{"<center>Moviz LUTs</center>"} 37714 37715#@gui : sep = value(0)_0+ 37716#@gui : note = note{"<center><a href="https://freshluts.com/users/992">Ohad Peretz - FreshLUTs</a></center>"} 37717 37718#@gui : sep = value(0)_0+ 37719#@gui : #@gui : note = note{"<center><img src="data:image/png;base64,\ 37720# iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAC/VBMVEX9AEL7AUL9AUP8AED9AUH6AkL4AkP6A0L4A0H7AUT6AkD7AUD2BEP6AkT+AUX0B\ 37721# UL+AUD4+Pj0BkT9AUTxBkL3A0D9+fv2BUb5Az79+/r/AEL6+fr6/Pf81uPlD0b4BEXuCUT6/f32+/j8+Pjv8O/bGEnhE0frC0T2BUL++/38/fn98/f96v\ 37722# HML1XXH03oDUX+8/z99fr38fby8vH83+nk4uT50d/4us/uVn7tPWrrM2DqGVHSI1DoEUjzCEXxB0X5+f397vj88vTy7PP58vH65+z62ur84+jn6Of5x9j\ 37723# a19bTztD0sce0r7HncozkPGywVGvrNmTkLmDQNFnCN1fZKVbRJ1TsEkzyDEjpDUfyBz77Aj7sCz39/f3/8vn29/X79vT39vL19PL77u/96O7t6+vs3975\ 37724# ztzOz8/TyMj2sMPzqcLzpb31oLrDtbnNsrm7u7f1l7P1ka7xkqvvgqOtnZ+0m53ndJPtbY30ZIazeoWodYPmWHylb3inZ3euZnboSXTuRnG6Smm3RWDaM\ 37725# mDrLlvFNVrsJ1rlIlfLKlTqH1TvGk/bIk7pGUv5A0niDUP/AUPnC0HuCEH05ens5eXb3tz6y9vtz9fk1Nbt0dT3rsvQwsbIxcXqrcLGvL3Pt7r0m7byob\ 37726# XFra6xqqzOnqqtpKPtjKKolaDJj53udpvahZmkkpbvbpauj5PwaY/lZI2egoi+dIToVIS8boLFYHvjXHu6YXboRXS1WnHjRnC9T2+vXW7KUW7XRWzoQWy\ 37727# +QmCyTF/mK169PVvtIVPdIFLjHk/jE03tDErZHUn0BTz2+fr+5/Xz6uru6Oju2Nvv19vh2dn2xNPW09L4xdLY0ND3tczjv8jhxcfWwMbhtL71rL69t72+\ 37728# vLrSt7rfq7nqp7fMq7DVoK7jmq68oaXelKTgi52nm5rMkprNhpa/hJTngJTmYIvgboquhYmmf4jqY4KxdIG8aYGcdn3YZX3QaXvZX3vnTHfrT3WqWmvjN\ 37729# WjOOmPJOF/GM1XYIFXtDUL6xIL1AAAFQklEQVRIx6XWA3QcQRgA4J2ZNc527KRtnDRJbdu2bdu2bdu2bdu2XueS9vU2TfX6v3f7bubm239v5p+5IwAgCM\ 37730# JC/HWkB/8ewB2e7QzGyEawLA0YiPugQjsMut/8HgBGoJQRfln79y8T7p+ipH8eb7H8ACSJoOjoU6zz4pszpl5uOuv+qtIBGi3uJjIMEo/f/7nHssIFfNU\ 37731# +matUCTFXjRw3a3MSY0K/+r7KoTueXMpXc0zzJW+Kvi8aN79BVDWfkTd6aTIGAEp+71rXyVGoe9lkmoNaQIvD+y6yqw/U7SaiDAji9fs6N8s55u0IAIAg\ 37732# CAQSBEQYd88JNYd20ul/FiDQr0uzyEIDRB4CAiHkfpEWzhnwNG9Q3rUigjDdzKLhxQrnnDDARA2RBATAtyLgJE2l1bWCYvoByMkAx4ml7kTm7xfIA47j9\ 37733# w/33zcoPNzPX6dQQP2XIpkM01IAR3pOr4Lzf3Gi5hanRAHgLB+2rkObJk2mzLj72qiAApM02RoSzylkgHCWmlm9eQVuCACUf7GFBX19zEGV1d55XRxEgm\ 37734# bzqGzTjQB5AMA6uozO3ZungIWM6FLY1yfqdONGhexZco8QAL6F45ZPre16eUmWaV21kYsXAMmGtfY1Ty9Rjg7UJXZrrOPdQLnpULV2ckBvnZQ5jnIXq25\ 37735# jAYM9iSEtSE+LLr0bACbrGduFSjIQsWZ0VD8thFDheuYbNFkHaKgSAEWlDaIc87zzDJYtg//jGrEpTggJ6OqgrhxTlhPx2n+vYsDqntcI7S0D4W3U02ga\ 37736# A0Jck8uQ+UFSMsC91HfAbDicubvskbI2CWqrJyGEDDtovNWr2tVeAXqa/ZYC8HSpY+Y44FFPVNikoKWpgGCVq3N7mW11FvTaywhEGgBU2Clze8YTfKpnW\ 37737# GFSuQHD6jpFmYPVVY8u2CWyAKUSqXR9qxyULGhYwavSCo5M3t0yr9rLZhvbqZKe4oEbhNU3tAfpwMOK5LcHYHhlQota3gav3EWUPOXukfrUt8alA9a2pj\ 37738# RAQECamJTijUK8vA4WZxgIgUTvqGftTiDPWZpobilJGAAAIIRYcXuLhHgZmgdCAovAHgVCE2Tr4HfN1kBJYyBgkBpGTfkr3sHHyxEQA93GfHkGEp7hmGe\ 37739# zl00DNEwlTo1upW9w/nKp2tHRN9YlyzBiVWT2eMm9mY2lXSLExyRkhnasHdzASCuGQSZrG59WogxQH+rYWikx4CNW3i65J9kppfj1nK32aZcKlFunVFkr\ 37740# yQC967yt7mCEABvRocaR68vXbejacWY+dd1EmsY1PLRrdP6yWhlgNa+yqJfQIq0sv7x6cHD12qPyRVbOFtubggQUNaVmZ1lkFJHnnqaYQWO97QMlmtKUb\ 37741# pE/KkdISGieCUsTWdJCQMa/cwF7Isd5AkAxmke5srUsx0Atp4zYWTw+PmFnQAUTj/BnAdsK52pn5LSyUwMAsKdhtixtKwgizgJ4nmXdVwAgUann3JwNk6\ 37742# BWm/5spUvEeNcsUt6owIcXoVKpIL7i/RTQc2F0zHYJKhTpAGnSrR9pzTEncQjHQQInTy0QjV+xudF5EjSSFjfThYDoLTFq6/iX4Q4W4AxIUDrCty27mPN\ 37743# kAoM1Bj8FYvo2zuGd6+y9TR/DypTp36dH18XNokNbDFCSMGOA7xoQF5vZoK497tzUpk0n1ovOkr1hfIWKLPELQJJICHQVbxVrz54JR3Z7ofl9dYGy9crg\ 37744# d4hkxeTBJYp2W1+0xEAnRapY8If/ATxLEUJFk8lUUYUsBCmwiIC/JQhhRgAc35sY/FP8L/gKJ0Uj1jCuNAUAAAAASUVORK5CYII=\"/> \ 37745# <a href="https://gumroad.com/sarikasat">Olivio Sarikas - Free LUT Packs</a></center>"} 37746 37747#@gui : sep = value(0)_0+ 37748#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAClFBMVEUA\ 37749# AABzk3pTeVfj8PHk7u3Q39rp9PW1x726zcSUrJt4l3/Y7fLq5Ojt9PTv9fPn9Pbp8fHk7+/h7u66zMO5y8JtjnRxkXdkhmlnim7R6/Hc7/Ln9fbn8PDq8\ 37750# O/n9Pbt9PPR4Nvn7ezg6+zO3di3y8K2yL64zMOZs6KYsaF1lXyu3vDq2d/o5url5uru9PPo9vfm8/Xn8PC2yL+3y8G3ysCkuqtmim1oi2/0PVwAsO7m8f\ 37751# MBru33O1kGqe3r8/QKrO32PFrp8vT5PFjzO1r3N1YIp+zyOln0NFbnydHn8fLB4/ABrO4Npez2PVv1OFdNTU3j9PQRoesFq+0LpuwQouvpvMaCgoLzZX1\ 37752# SUlK95PG03vB4ze9Rve4ZsO4HpOwVnermx9C9wMHyc4jwbINra2vV6/Kl2PGs3e9aw+4gsu4Ire4vse0Mre1AsewRqewVn+samuoZl+nn3uPW2drstMDo\ 37753# tb+nq6ztjZ6HiIjucIbySmX0P11YWFj6OFT3MlLs9Pbm8/Xn8fTu8vPh8fPB5fG34/Gl2/GQ1fGb1PGf2vBox+5vxO5Uwu7k6+0TsO3n6exRsewDqezh5\ 37754# +kSmenc4+TqxM7rt8Lsp7XwkqOen6DshpmRkZKAgYHvXnbwWHFnZ2fzRmP0QmBVVVX3NlX5NVL5L07j8vPe8PPM6fJsyfGDyPCs3u+Dzu9gw+9Hvu49uu\ 37755# 5duu1Que1KrO1Ku+xJtewmrey/1+ssoOodnuoTkOjj4eXM1eTS1OLa39/k2N7Y29zbztnl0NfjzNPsusS3ubrrrbm1uLjnrLixsrLmpLGur6+urq/snqz\ 37756# olaTvip2WmJjxfZHsfZCLjY3raIB9fn7uYXjxUGryTWj1O1r4PVn6PFdLSkoQ11vXAAAAOHRSTlMAGwXd07u0iIRHJv796eTi4tjXiG8eGQ8M/vvp3dnU\ 37757# 1L+6urmBdGxCQRj+/vv76+rn2oWCgmwODToLEi0AAAKySURBVDjLZdNlW9tQFAfwFCiluDOc4XPf2hQyUqF0pe3oVvcWdxhuw204A4YPm7u7u7t+mSW5G\ 37758# S0Pv1d5zvkn5ya5F7JaExftGO7uGe4YHbcHWo3itC0oS5N9tbVbczYoxIkCrWQX69aa3SdkMns6WExhX4/KLdbOtr8uyiVbyMTkq3RMnFAbSLV5iLODOo\ 37759# eoszTdTJJuvYPz8v0OWfmgmtOWy/wvt8uBQs6PUpN9YdcFplVuFhWsY1dLDgu42C5k2dAF+uJ9/63lp0F9sC1v7wpaN3yI05OlRzop1peeR2EgYx+gyvD\ 37760# Bvp99db2iY1AqlRZmCMjAqcJEQBuyG4rf9PvP4tO8xETeORQmoRoeCBS60KGdsiU2u0adystrESAIIkBRBEFPXucR9JnbIcdj9Wz24jutvh01yafkpvGK\ 37761# yW/P0E79AZz+yFoozMzG1N69hgxJ0ifTlXXKV+l/7yMFqYTLoZCHAg/Uf26Ej0oqDr9Rzj9E5JJDsCrtIK7AHQsk4LiPBXjgrXJ+thkLCNBLaTgsEGZOI\ 37762# HxvHJLMfsFG1DVPYU+YvnfLUFRUNBCKLZJLBBrKUVNVVZVp/CP6Qt77ssF8ZthgMGCL3CFrSCL87MVfE8bfFOmvSeIabxYXD2fSoPiNIhBYeN8Ek5oquU\ 37763# kJM5klxSUudOxTm7mAuBQmPRCLRKKF51dKBjwDsJ/lakwB7uwnnICrf2EBRs2N22oa/ruDLckkDuGHjM/AiSs7N/tBGN/SOYYNfvkMeXW8PwZsOapMbBN\ 37764# QvBaTybIIcuv7e5dZE+KUWrI/5kVZ3vbesjkOKHMmJsBVbZm3s825o5Za+GCuMZm4XbEhgrLi6PluGalm8Dn8sa8MDp9hGQmOAfOt/HzsXUcrPxmnLR9G\ 37765# Xe19/KDVAui0SC9PD69IGj3AWv0HukgIS3/cZL8AAAAASUVORK5CYII="/> <a href="https://www.on1.com/free/lut-packs/">\ 37766# ON1 Free Photography LUTs</a></center>"} 37767 37768#@gui : sep = value(0)_0+ 37769#@gui : note = note{"<center><a href="https://marcrphoto.wordpress.com/specials/698-2/">PictureFX \ 37770# - A Free HaldCLUT Set</a></center>"} 37771 37772#@gui : sep = value(0)_0+ 37773#@gui : note = note{"<center><img src="data:image/png;base64,\ 37774# iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAC+lBMVEUAAAAAAAAAAADw8O8AAABiYmLv7+84ODgAAAAaGhoJCQjs7OwmDwjQ0NDu7u7k5\ 37775# OSPj4/s7Oy2trYAAAAAAACpqanv7+/Z2dnHx8fl5eWRkZFsbGzCwsLg4ODi4uLPz8/s7Ozn5+dfX1/v7++oqKgyGA0uIBseCwTb29vS0tIdDwzy8vLt7e\ 37776# zHxsb+rB26urrr6urz2sGTc63vUQPn5+fk5ORYkczWbo4kJCT9pBrY3N1YsJjVKAfkMQToRQCwsLCZe7CPaqZZMGX8pir3ggvd4d/y5tjT09Pz0q2am5v\ 37777# SZIJKHEakFBn7lBXkKA6xFQ7MHwL1awHzZQDyWwDbOgDy7eVZm9OTk5ZasYp/gYJZOXVsbnEZNmr3sGGzNVKzK0P6mzdNFjeEGjNeFC0dHiH9pQ/6jQje\ 37778# SAPgYADX19fOzs5hjcXYn7yoqKh2VJIeQ4v0xIlbs3/GTWq7Q2LyZlH5q05hIkovMkKtHzDt1gLt2+Feo9eBpsSqqqrRfZ7QdJmJiotnRYRDVX72uHJJJ\ 37779# FpdK1cVOVVKRk83Hk9yKE36qEBxFS6eGyz8nB32dw3XHwGek7eFhLSQeLFCa6/zzqN7XZvzx5ZKopXGVnVMLGkRXl5rMl6UNE1aGz66KC6UVSfY0wdmJA\ 37780# TCFwQ+EgStbADqWQDv19niyNdqncmvyb1Wf7jj3bOQkrKGda9YqqmZu6Xt5aBBbZlusYbzhoD0vX7w33pfRXlqOG9HRW5bYWSLNl6eJUByHjyQGC7rTir\ 37781# +sSX2nwHNwgDJYgDBUABvks3E28y0wcyNrsi1rMKyoreOdK7Kw6tyqaGXX5OGd3Pma3OXd2xTWWctRWIpb2AoIl73mVDFrzgmLTNbjRJ3OBHQpgC/hQDa\ 37782# hABgoNGlvtDgts7yzMzuwb6cg7qipqmkpKS4gJ+JtJs/gpuDdpdWcI44kIYnZ36rjn0eTnt9V3p3RHovjHEnhG9sdWoigmXweFRcglMtekwkF0qkc0Lh1\ 37783# z3VRDurkQCLhADNWgC0rmDQAAAAK3RSTlMABRL+FyPzRw0IIuj+Ou7HXtmKNi0Y5aqgl3lULNTPwKxuN82+rJCPjmZXgENtfQAABTVJREFUWMPtl2dUUm\ 37784# EYx4NLBmju9t7jBUFFAyQxxdSMUjRNwTRzlZlarkzLnC0tLRtmVrb33mV777333nvXOT0X7XTuvcTl5Nf+XzzH1//v/p5HDrzU+Z9/TP3mteybtmLUps+\ 37785# xkFqya9FnNBEOMf8boEGb1u0aGmFId4xMLVq3aV4fSQVcju56EwzRBxMNac9i6NxNQ2RIMCm/KVtn3wgZFNEQuU5AA8rzsX49bT1te1IFHjg017VbXfWE\ 37786# nIshtoTfgoBAjsw4VAHS/qAO/ZDksKgwAoEn5cd5IFSfItCF0vecNj0nOaxQCQSiQCAPoc4M8qurEdFf298YMiFMqYyKCvP8I+DOj5PDTzPyGtlmRAFbz\ 37787# +kJG0NwgcLIyD1uCWs3rcWgjgtkucMfGFMAFgRAT8/pG3NCJrgVSqCuUETtmTdy5KZ+mFbAC+FhkgBMYwLANiEnJHmCm0RiExlV5KvyvXENCGt5mMhDEO\ 37788# iB8NTVC8Cm4XU3iY1NpMJXpfJVxdzYO2/kJlwgMwtVAxgkgClhghyo20Cg7+fnp1LF7AOFFQgX4P8FYESYILm6L4ny9bO3t/cDwPW9XzFcIIhnCGDabht\ 37789# tX1nkZ+/s7LxoEQ5YgYQeAi8BogWk31mcsBsIEolSoYJ+dLTzopj9Cy8hngM/LkhIC0jfkLThokQiKVQqYQHOzv7+/tE4oFpAjmgBi08nJSUVKRSKoiJf\ 37790# GKA7DogGAQwEMoNE9IB+G5KSqqrstYG+TCbzj/658MdxrUAcogegux+q+vTpXhOZj4+Pf8z3K1d4GL4BBwMAwqGnv8n6aDMZ4uMji/7y8dMaJBwsCPRC9\ 37791# ID0oWO6Da+o9JFBoF1ZWVlRvjk7WwQCme9OGACAfq/hoX1r0rt370nls4O3rsRAwOv8aqdldID00d0AMKAiDapQ3hUeHj5+tutWKQjIt52f4dR/GQ3g9h\ 37792# gtILQiLS1t0qTwiYMm7hyf5/oE44FAftkbJ6f+7voB+AQzRwwIDYX+romDIDiAjwuczS97DwqPeIYBduyCxw+EzElJeYULBObnl70FwHqpXsCS0TABAHZ\ 37793# Afc4cb28t4SgmAgFNftkzJ6fExIN6AcKhWsCO8J0pKSl5ed548oS4gEajeQ4Cievd9QLwfwOMUD4edg/JzfUeN64ga7BAvlWjefl4df/ExDWYfgAM0WtE\ 37794# +fbZW7ZsCXZ1nZWbCwAP9WW1Jj5+3WpcwAHRAIAwc/v212PHbg4OnjUrd9zn1Cy+OCI1Pn5q7Ik1yw6KEBlAfVNd/PDkyWHDcAIgLlwo4G8TR0D/QEb19\ 37795# PQAJL3n0qN0GKS0dGx2dtB9ccS5qVNjD0iRoQA0pcSuR3VKl2dnFogjlsfGxmYgwwEOq0rsID3s7Ipj1UHiiHWOjo5LD+kHWCCCwqpjOMHFpfipV6r4si\ 37796# MOQISwyAAz4nkxEKDvslKtrhYIOEw4N2aSP1wbEQHC4pIS6B8NzEoVpzoGBATclBLOW1IAloiUI1NWTjniELQNNgj9URnE08ZsEoDTFkOU8JBcnSo+Nwq\ 37797# ylHRMuaoyWI0QNfyrC0zEhw5nZNwiHbSk3jTZbU0pfeHcufNNCoRUMGbOBABZwZwyxHEcoOZRAZYsjo5LPLcp+ar64ur8BSYC6vMtuTqvumxus1ZEiTPQ\ 37798# P0URaNGMy2boAjA4LOtmjc2MsT8A6BPLpi0am1uzCH0Cgs3iWltZ1fudDiYd6xFiZWXNZTEJ81Ms2EwmqybcTl25LEKYTDabwaD/TlMTDhdkCaEpUnUYd\ 37799# f7HgPwCbcV8KluLH2kAAAAASUVORK5CYII="/> \ 37800# <a href="https://www.pixelmator.com/pro/free-luts/">Pixelmator Free LUTs</a></center>"} 37801 37802#@gui : sep = value(0)_2+ 37803#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAA5FBMVEX///\ 37804# 8AAABJSUnMzMzKysr39/fW1tb9/f3u7u7w8PD6+vrn5+d9fX2VlZXy8vKSkpKHh4e3t7eMjIz8/Pz7+/t2dnZra2tQUFD5+fn09PTq6urj4+PU1NSpqam\ 37805# amprt7e3c3NzY2NjR0dHDw8O/v7+vr6+ioqKDg4NFRUXOzs7GxsY1NTUqKioGBga5ubmmpqaenp56enphYWFcXFxNTU09PT3g4ODe3t61tbWxsbGrq6uP\ 37806# j49vb29lZWVXV1dCQkIKCgrAwMC8vLx+fn5zc3M5OTloaGgyMjIjIyMZGRkTExMeHh4Ueor/AAADBElEQVRYw+2X53LaQBSF74IaoghVQIjei023Daa4x\ 37807# 3be/31yV7vYBKyMCPlhe3JmgHMumk+rvbArATlRQM4iJ+gMARE4QZHvCxDFowFlwZcHkLtN9wl5NGo5YJIEpqyfVJ6kPUCS+LLF+Svh6tUYIMFzzE8pnh\ 37808# IfAzJjsqNr6zgA19mylZhxghwaUNV1jY2hlsIoX7b8VEcv6ANqNTax2QIN97pw2IUoP4xLp/FHyvfnaMfsG9lA76APAJjwJv+8V8wv0Bpv3EgMAgHwruw\ 37809# U84R5WeOwCh1WHMIA+EWUmDdxTl4rUJrhJEsQEuDSQpUH8Z6QjbvEShfCAkxaON+m2IqQn1hoQGgATHcBoET8NsERgKffARmCujwGQHYBWYdQTZXwgBwt\ 37810# dHgwDQwP+FrlQgMkWnB5KKC3rSG+t6ywgCLmNvd19JsYWDZ+JuVwAPcGc4F5j6DKtJm0M/NQAHX0/kPM99DeMdtHWwsGdLZJNGhcsAau0Wp84F30L14gg\ 37811# BiSiD5V95u+ov528UT9kK8HixmGXqERBEBNRmtulOAl7SYAsKulAscDRmSrx7oFfwEA5VZzHGc0qKrAVYkysYLKUycIEFr/Af8eoBuGQwGGYdxBKAVvrs\ 37812# UvClDib1I+w13atwOIirxXieUOABpZtycSOESDq+eN67afhVq/TXcCudHPZPJoPJrj7Z5Xstu9orkHUIkIlZkMBL2QMOV0FyAdBZQ0ToGQiQPP0SZcN0B\ 37813# NFz8ApIjpA6Co1zV5CxBGMlgVcQdwj/BS/gDQrbWawABiZpqDLSC3fqgrADuAzkuyasEB4K5WBg7ITsb8jD5O0Ppzaq45AFx9lYl/cAmwBQwbV0MOUEuK\ 37814# ApD31/RGne5sBTWugjxI/gFQtS050WGAfGLQknF2YqYoe7YJcsuLRQQAXdsDNNhG3iRziD7aimJvKl7ETiYfElkn0RwXoIyDGDrJJR5W6RWTs8s9wIXkV\ 37815# 8rSBbiSJIqSpCgSCnO2KlwA5CQLx1P1J78kdGJf67/w6QEnP3yfqF/1kj/apHwTgAAAAABJRU5ErkJggg=="/> \ 37816# <a href="https://discuss.pixls.us/t/help-to-create-a-set-of-pixls-us-color-luts">PIXLS.US Contributors</a></center>"} 37817 37818#@gui : sep = value(0)_0+ 37819#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAZlBMVEX18v\ 37820# ny7PauecS0g8jt5PPr4fHz7vju5/Tm2e7IptjXv+Pw6fXo2++wfMXMrdrj1OusdsPq3/C3icu6jc2yf8fdyOfUueDEn9Xl1u3ezOjaxeXStt/BmdK8ks/\ 37821# h0OrPst2mbL6lar0clnGlAAABY0lEQVQ4y5WT2ZqDIAyFhbIp++JWt5n3f8kBtVorc1Eu+ID8JCcJFF8NwimlnPxn5oJZO9d1xzDImIGwXRmgmzyUbW9v\ 37822# bijT/tHQbb3AVvOrHQkl6zd3cUcv9zs/XuP2pnojgHbLZ0xmnucVMam7am30kZ/yubQHh/ZVZ9DKNUr1qVxPpZp04IZdQVmubkzZDLAgFRybZr2iH5tOH\ 37823# EScjOKRhUUYbTx74OQKil1vLFvd4sWDCBhe+W4DCjeTxM0hzvOvVBBF4Me0U7UDUw/WIoS1ltFvAigpyhfgNE3qLFwj7UAcByDxCmDJ8wCXOFmAHes88G\ 37824# wFSCJFPeaBqWdbJwBEOQBBirde46HNAeUgyN5MHvQdEBLj13NgDKJPAISekeNBiWdAV8B6xVIKJwH1BZDlZj8JLVt4An45/B86cGMiAABnrioYJrdvh1h\ 37825# HgJNSutIWJPszYyOZYMyi3ZyFCCm+HH88KhF9A33HkAAAAABJRU5ErkJggg=="/> \ 37826# <a href="https://purple11.com/free-luts/">Purple11 - Free LUTs</a></center>"} 37827 37828#@gui : sep = value(0)_0+ 37829#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAgCAMAAAAynjhNAAAA1VBMVEX+\ 37830# /v4ODg4DAwP7+/sQEBD5+flRUVFubm7z8/Pw8PCioqJSUlKAgIC3t7dqamo6Ojrk5OTn5+elpaU/Pz8iIiIYGBjh4eHa2trX19eysrKtra1eXl5YWFg9P\ 37831# T0tLS0kJCT29vb09PSJiYlwcHBgYGBVVVVMTExCQkIyMjInJycUFBTt7e3U1NTR0dHOzs6+vr66urqRkZFzc3NJSUkgICAICAjJycnFxcWvr6+cnJx3d3\ 37832# dlZWXp6em/v7+1tbWWlpZ7e3s3Nzfc3Nynp6eEhIR8fHxaWlqIUZ+rAAABlklEQVQoz4WT13KrMBRFZUsCgwFhegdjinFvcb1p997k/z8pJJa7ZrIeNGd\ 37833# maaTzsDdoXvFk6PFT8xrQbJxZBZ7lHVaNCxeNVrlmQ4BVzY/Rg0YkHWPwDXbmZHCrzXdp0gInWqOUmBeN+spsCMEFOHxe9AdUV4HXweAW+Gd7qFCtUbGz\ 37834# IGCg7nKzCcJx92ch4UyL3u5O2g3AHefNnueVXq9XH+mmS1fkEdVQI1wYZYoSxsWSc5N7LXLeG2cL68K37AU3ftBtWWqrdi+YQbjVXczSYync1v/OdI+ll\ 37835# 3PyfwihkJZr1uNGFCmS9JZxosDUhFSryiDiEDBXs5ws/vRLF7N1Bz8v9xPl4DD0S60B3hXiNNhbD3r5qnAdAKyPQlv0xdad9kr93a81dIIyjPIJvNFAnc\ 37836# ryOqkHPJrJ8lQ9ad1JjhHDGB4fwnRMRnkDoFxTAYvOP9+sw4SizGWE6YWPBqco8lMBXkthQ6NIg0xSJznb7t95aN7WYKDPR7QG9mtpPpYoDmiJsuquRBT\ 37837# Dd1VXMa4r+EuBvwA2hClvJ4GaGgAAAABJRU5ErkJggg=="/> <a href="https://www.rocketstock.com/free-after-effects-t\ 37838# emplates/35-free-luts-for-color-grading-videos/">RocketStock 35 Free LUTs for Color Grading</a></center>"} 37839 37840#@gui : sep = value(0)_0+ 37841#@gui : note = note{"<center><img src="data:image/png;base64,\ 37842# iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAC91BMVEVLNHxKKWxjXKBTO4Pr6nZoYqXWemJON4BNLnVtbqzRa19aUZeILkrJIyaQ69Nd\ 37843# V5vr6YyUaoPs63qIY3pKL3nag2QzHFnXc1jlnk9zQk1TFUdoMT1XxK9saKjv36BZS5Xi6JDq64TEb3bikW/hhmvSdWLe41pqOFjgaVI5GkmOEzHJQiu8\ 37844# Fh5u5NOD58dq18Viw8J357/l2bxt3LaqmK1dU5/o657p6pNZSJFWQY7X2oxUQ4lFNYatdX+khXybbni1b3Xm2HB4V25TKm6SXW24ZmmiYWeGVGadUGBe\ 37845# JGBIHFqGSlnJZVhVFVLQalFtIE/PXUlVKEi/QEbjxkWtMETi40GdOD+SJTx4JzuoHjjcMDdIFDK5GyufECS9IB2A69zHwsiT8L7s5rRy5a3Y7qPGsqKC\ 37846# mpuBeZVRdJLHzYnTm4nIh4aJcIJVXHvh5nrlmHrmv3Xl623gdGO/cmPFXE1MLE3TgErhgElGQEeEO0ciGEdJG0PlcUKHHEDJVz65JD3fPDhlFzDULSnC\ 37847# LSWDzOGm0dt81dBe1Lea8bCH7bDSvq6Nf6qF36fPyqXNjqJqhqE6QqB2d5muiJjJ5pWjmJFShJB90Y+xu4lmV4nW4oRSNnjJqHLNdXGqdmiHNWXd42Ti\ 37848# 1WNlOWLGX2GyVFy2ZlvJV1pSOlrXW1nmkFU2LlLoslCORk6tRE15NEvlp0rlXEo7Y0eWNUVdPEBkHTzgTznSNTnMJTfTRC2wHyPC79mUu8Sqs8Oqn790\ 37849# q7ZdqLWNl7WzrbOMnq+DtKtydaedw6WprZzij5dfzZPDvo6ZeI5qZ4XQwH7FnHt6WXk0N3dsPnTlzWy0mGxnLWztiWooF2pEZ2nkxWc4JWW4iWPewl/M\ 37850# R1/YnF1DQViYKlaOY1Xfr0ujgj8bMjGJJS53DieS2Liai6k4W6bc3Z9gwZmKgJDxrI7zqIyl1IttQYVajoCMhnyWYHpYU2rgrmeOkmWpLGDOk17YiVrF\ 37851# LVXm2lHdp0W4cjZMJjAgVhoxthLEAAAEA0lEQVQ4yy2RZVTaURjGr4LIGDAQAREFJEbZ3d3dCfbsmt3Oud7sdnZ317q7u7u7ex/2F/c7771fnt957jn3\ 37852# BZl2+HPbjtXRaJHa4Rs37t6zt3JjdeyRIyuWUFZWlgG9lnhrWry29sHT/UN3kw/FxFXur4zdrrycy8hIgxAzPF6fFt6kWFoUUBQUdO5AfVxybJO0zDLS\ 37853# 0qC37WON9p7+kCdisUikKhajD1Qn42FQsswq4GpnqxvOfSIOxWCgwSwKxrY/I7RI6+mtkrAStDJt9zpgFueD160LDg6eDxII7m3XldLTWymBbgimbU/p\ 37854# Wkz4e1H9vb29R734BR5FM45dRnp0QzqdbmhoBLL4+Wav4p5XXZWXancyJTm7uV0u8rZuoRuaGJmYGMFggMAdwl+LS25y43eVdOW7KSoqerT3EWyMTGAm\ 37855# MBhMVhZQKf1Jk5O5fHDVcXbqPD8EEtDdFk6ykhQ6gOJAqJn+O3m+aiVqIvRdlfOFyx4BrWZOSFlTU1MAZAEIzM09VffoUf4N+ze8OdGFfBKpXZCR6GQD\ 37856# lS9hCubzqC7hFS7oktTX6bO3S77e+1EykpDgZiMP/iPq8X9skeA50N1qNzBVMBMYNBdw/2yCkw1SHtkiEfz9A0tdEpm2tvYuFK8Qr4JS3wDzm5e4zlJI\ 37857# JFIeQEOhUKf/mFs4BFo6otHomZCxQPRohu7pIZKUPFRigwS5dz992LaG4MI8XsG87RuE9uAKVBdqNuyqdpaSAMrLjQ1o22KTLC3tRxwfB4wVcFUxC3Ua\ 37858# YbsdSDckghwcLodbs8bawt6uezQvj5slUF2/LkZTbVP6cWs+ieQMOlavhavspJknmVky7RwpWb4iSNinqaHmeuUKOxGfBVZLBKu0+4QkB4K1l2+wKma9\ 37859# t6bmZrWMwpycVPNDYHUHHK5y5uKtO70UKnVqbn1oaFmZvabGZjXzwpzBtvr3ACqQw5252GmVVihcmBAulgmFwhglSDhcODj47Vr9kgDHnUyz6ryV7c7j\ 37860# CYuLPXmZm5R0dLQ2ZSsoKNz5AjpSUlJwJ3dadV7/ziYXu5PJnrw2rJKWuk7YpeFhhXEfkMKIxxlrZ6Rd/5xd7IlIZZPJvGMSQf3o+PD4Lx/AaGQYG0f2\ 37861# sFgshKc7KxVBZBOfYpWwWupa6tATD3xAI8OgERfZgyIi3N3JLCKRxT6rs+sldmtEVNjNnOwHfqDWIN5YRd9sIB2BQBARHOg6vCO6IWLrlqiwmNnfPn6A\ 37862# wYhXgf7aN53DRnA4KA654ugO/bc7tmyN0NhX9hASDJqb5eBykSN9KFdXFArFSTwY3aBfe2JLFFZpQ+nDn34gulkFWpdBeV6fa2YmCsXUfVHbEK1/IiIK\ 37863# u3+DItXK7x94612QcMazZgAAAABJRU5ErkJggg=="/> \ 37864# <a href="https://www.facebook.com/shamoon">Shamoon Abbasi - FreshLUTs</a></center>"} 37865 37866#@gui : sep = value(0)_0+ 37867#@gui : note = note{"<center><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE4AAAAgCAQAAAAWXYa8AAAG3UlEQVRY\ 37868# he3WaYyV1RkH8N/cWa7AzCiCIiMuSBW3AtagYLQWitpQa7VVazRgMLbEiEuitqRRa6WgRUxFTRfjiMaoVGuNQm1IaajLB7WKbcS2Am5RtDDDNsyd5c7c+\ 37869# /TDe+879w5D0v2T//PhPec5zznvc/7Pck6NMr6f9rarxCqfGAqzHTak/N/HmLR3e/Kpq5ydbtI/ZVcZ/337dltZMaoybsapPy13O6BjDL4J2kvyd8ASd8\ 37870# IfNNDutHSD1Y4GJ6SSnej2WsVPRlbNDcK1VaMq44p27a1fjSNAxuegSxcjjEtnh5sw5KqTfZgeD5+3w5YhFfP7No7T3aRNrbqWlz2o4Bj3F8q7/sLbrvb\ 37871# D0qjenW7Q4nJ3GOVh39DHNLIWu9FUtyekNT9hbTNaLPSxY/Elvmo5rJar+nk1bVXGFWF/a92Helf5gVsNt97CVKWlRBxl8hocgTrjLPATUGMCmqyzFGMs\ 37872# cqrFcKHnNZVXdyefakdV07Y3c2X0uc/awcKWtHfx4HUvmaZliPTZar5VTrSBYyHrJK/oKYArbAKrdQ5tRaZqtDNtjipHRbdu3Z7z3NAbJKi3yCKaZGXRo\ 37873# 8c663xEeMCF0ACTNWnxXnnZmIryMQT2Yu5kl6g13pG+C45zCdjsdRxVGlE/sPRVI9nQtMOZXqjebLMW/uTSVDDb8ybb5hZLTTF+36RhMHPo1G6rjVv2bJ\ 37874# m3RafOPjk5Ob2gPMrJiYFFO3XyI99TDzUV270s351vyJfjabfXjNHuU42m2VPTWam7FwaYy2o0hneSWNvypDvNtMNmq+D4ROmjZMSwrMvLK8eWf/yYq+o\ 37875# fkFhYwnwOtQ3eTA7XpNlmpzjBbusM092gxlwTMHpfxk11tYOqZvpef2rC1B0HqwXnlaXqcWaF3jTZMv+Pe8avyyTNKit8xctwpAsadDvaWw7pru3ett8X\ 37876# nOYlWFxRKaEoXKdQNi7jEaPJ+pITZaz2Lr6ceXhsQto5RnrX06DWGWrQoCmpDMOgxQywzlIHOgCcrh4jzLfAVH9Ei6IjrJcd9mI37VrU6WUcTS4wwe7yd\ 37877# Vh1K45VVJwa2yJBPu6Px/I394mT4pPoL0k/iNnxUL458lFGV/wyfh5iTBSiEjNiZjwYuyokb4QQcyOiKw4PIS+3PZfLNeQUxfHxUUmvEPdHbcGzib/SmE\ 37878# vIa7XGIa41yvW21jHPWO3u8r5p5mjzM5B3s35jzXWxe7DLSpd6Ja2MH8hZ4yIstwd8mvIwzG2uGJSIrcZZaaWxbnJYZaKVmRsbxdgVmRCiMUaEvJgYfdE\ 37879# Vk0MIMTKEfHPkozOyIcQ5EfFiCLEwIu4u6ZVbW0S0VEnmRsTfIx/Hh4JCmbn9ohj50o63xP4hZS49QU6vRnNk0CnHNi5S5yl/hnZtO9u0oVhqJT6GGxId\ 37880# Q4t5XMaiKkmfPerNV4s+u+kloS81rkOrWiusd2Xyw0OZTJJP3WaZaKKJ6Y4Z9nM93kpFX7TMMsvMJr0nby3JRqRa7VY5P6bVqElSiYLlwnIbLNAIw5xl/\ 37881# IDxzbpFXTwTOyMi4uOYGUKsiYgLQngk1cs3F/KFQmFDvB27ImJbHJO6tYw7QmhL3FrGQalbfxwnRX9xbVGxvZjLNeTkRCZuKGl3xXlJCCwYYK5DK/1eNd\ 37882# 5NPnaoZxyMPRgFF5luuukDj8iMJvvb5GQb0xM+aooppri3wmVnl2Q7Kih/05NmmqmDLIiiu413jfcMszJ5ElbcHJclcbQwhGiOv0XEpSFui4gVyUn6y62\ 37883# 5kC90FrIxKnZEX5IsxSESom1fCXFXiKOLPfHbeDVy0RAKCgrJ/PB4PSIWhHBNVcwxr6apRON7JdN/peBbCV21aqfX1tQOaG+3TF3yWh/qftzrKqrEJq3O\ 37884# qniBzckcCLq8W7VdWucu06pLj81Ocbac32ODFa60zj0+cIZvW+JWkrdYQf29FjjHrLS6TXJVqfeCv5R6c+0Gea2V1hUX1841TheY7WFtHvBXk5yv15pBR\ 37885# 7lMcWTxifQu2BVfLzkiGw+l1X9zTA79zfl8vjOfzQuxICLeiMyghIj4Tlrnyuiocqt+sTii5NbGQmv0lfR6Y07y52sGXHKZR1GzxIcO8Knf2E5BT1IBjj\ 37886# NDk02e10Ohrvg1RasU80Y0OFeN3+kw0YkVZ13vfZxbinfo9ywON9VGb9GpsdlZ+j0nisgcaZbRtjrBjeSFSQOZNtIT+sXCyvDdZaGHyqGatnzaOgfN/Cv\ 37887# trop+Tt/AaGEIveYkZg1E3xLmJa/mfVb3/xQ595HziY2OSYUTspnrkrwcTaOb4cZkauCx2cGK/5VV1XjawMWSdV2vpUm/Z7DiQCnZ+n8w6zN8Bv4Bs+PS\ 37888# zRd3ZU8AAAAASUVORK5CYII="/> <a href="https://www.smallhd.com/community/movie-looks-download">SmallHD Free \ 37889# Movie Look Pack</a></center>"} 37890 37891#@gui : sep = value(0)_0+ 37892#@gui : note = note{"<center><a href="https://freshluts.com/users/52679">Youssef Hossam</a></center>"} 37893 37894#@gui : sep = value(0)_2+ 37895#@gui : sep = separator() 37896#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. 37897#@gui : Latest Update: <i>2019/10/11</i>.</small>") 37898fx_color_presets : 37899 category=${arg\ 1+$1,abigailgonzalez,alexjordan,berat,cinematic,cinematic_travel,creative,ericellerbrock,filtergrade,\ 37900 inavision,jtsemple,kylerholland,lutifyme,michaelezra,moviz,ohadperetz,oliviosarikas,on1,\ 37901 picturefx,pixelmator,pixlsus,purple11,rocketstock,shamoonabbasi,smallhd,youssefhossam,others} 37902 presets=${-_fx_cluts_$category} 37903 index={arg(1+$1,${2-27})} 37904 thumbsize,strength,brightness,contrast,gamma,hue,saturation,normalize=${28-35} 37905 37906 if $normalize==1" || "$normalize==3 # Pre-normalization 37907 repeat $! l[$>] split_opacity balance_gamma[0] , a c endl done 37908 fi 37909 if $index>=2 # Apply CLUT 37910 path_clut=${-path_cache} 37911 name=${arg\ 1+$index-2,$presets} 37912 clut $name,{0$_is_preview" && "!isfile(['{/${path_clut}clut_$name.cimgz}'])?17:48} 37913 repeat $!-1 if $strength<100 +map_clut[$>] . j[$>] .,0,0,0,0,{$strength%} rm. else map_clut[$>] . fi done 37914 rm. 37915 adjust_colors $brightness,$contrast,$gamma,$hue,$saturation,0,255 37916 if $normalize==2" || "$normalize==3 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done fi # Post-normalization 37917 37918 elif $index==1 # "None" 37919 adjust_colors $brightness,$contrast,$gamma,$hue,$saturation,0,255 37920 if $normalize==2" || "$normalize==3 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done fi # Post-normalization 37921 37922 else # Collage 37923 repeat $! l[$>] if max(w,h)>$thumbsize rr2d $thumbsize,$thumbsize,0,2 fi endl done 37924 N=$! +to "Original",1%,1%,7.5%,2,0.5 37925 Np={narg($presets)} repeat $Np 37926 clut_name=${arg\ 1+$>,$presets} 37927 clut $clut_name mv. $N 37928 repeat $N 37929 if $strength<100 [$>] +map_clut. [$N] j.. .,0,0,0,0,{$strength%} rm. else +map_clut[$>] [$N] fi 37930 adjust_colors. $brightness,$contrast,$gamma,$hue,$saturation,0,255 37931 if $normalize==2" || "$normalize==3 l. split_opacity n[0] 0,255 a c endl fi # Post-normalization 37932 strcapitalize $clut_name clut_name=${} 37933 to. $clut_name,0.01~,0.01~,7.5%,1 37934 done 37935 rm[$N] 37936 progress {$>*100/($Np-1)} 37937 done 37938 k[$N--1] frame 1,1,0,0,0,255 - 128 append_tiles {s=floor(sqrt($!));w>h?[s,0]:[0,s]} + 128 37939 fi 37940 37941fx_color_presets_preview : 37942 _is_preview=1 37943 index={arg(1+$1,${2-27})} 37944 if !$index gui_warning_preview "Preview disabled in 'Collage' mode" 37945 else gui_split_preview "fx_color_presets $*",${36-38} 37946 fi 37947 u "{$1}{$2}_"{2*($1==0)}\ 37948 "{$3}_"{2*($1==1)}\ 37949 "{$4}_"{2*($1==2)}\ 37950 "{$5}_"{2*($1==3)}\ 37951 "{$6}_"{2*($1==4)}\ 37952 "{$7}_"{2*($1==5)}\ 37953 "{$8}_"{2*($1==6)}\ 37954 "{$9}_"{2*($1==7)}\ 37955 "{$10}_"{2*($1==8)}\ 37956 "{$11}_"{2*($1==9)}\ 37957 "{$12}_"{2*($1==10)}\ 37958 "{$13}_"{2*($1==11)}\ 37959 "{$14}_"{2*($1==12)}\ 37960 "{$15}_"{2*($1==13)}\ 37961 "{$16}_"{2*($1==14)}\ 37962 "{$17}_"{2*($1==15)}\ 37963 "{$18}_"{2*($1==16)}\ 37964 "{$19}_"{2*($1==17)}\ 37965 "{$20}_"{2*($1==18)}\ 37966 "{$21}_"{2*($1==19)}\ 37967 "{$22}_"{2*($1==20)}\ 37968 "{$23}_"{2*($1==21)}\ 37969 "{$24}_"{2*($1==22)}\ 37970 "{$25}_"{2*($1==23)}\ 37971 "{$26}_"{2*($1==24)}\ 37972 "{$27}_"{2*($1==25)}\ 37973 "{$28}_"{1+!$index}\ 37974 "{$29}{$30}{$31}{$32}{$33}{$34}{$35}{$36}{$37,$38}"\ 37975 "{0}_"{2*($1!=24)}\ 37976 "{0}_"{2*($1==0)}\ 37977 "{0}_"{2*($1==1)}\ 37978 "{0}_"{2*($1==2)}\ 37979 "{0}_"{2*($1==3)}\ 37980 "{0}_"{2*($1==4)}\ 37981 "{0}_"{2*($1==5)}\ 37982 "{0}_"{2*($1==6)}\ 37983 "{0}_"{2*($1==7)}\ 37984 "{0}_"{2*($1==8)}\ 37985 "{0}_"{2*($1==9)}\ 37986 "{0}_"{2*($1==10)}\ 37987 "{0}_"{2*($1==11)}\ 37988 "{0}_"{2*($1==12)}\ 37989 "{0}_"{2*($1==13)}\ 37990 "{0}_"{2*($1==14)}\ 37991 "{0}_"{2*($1==15)}\ 37992 "{0}_"{2*($1==16)}\ 37993 "{0}_"{2*($1==17)}\ 37994 "{0}_"{2*($1==18)}\ 37995 "{0}_"{2*($1==19)}\ 37996 "{0}_"{2*($1==20)}\ 37997 "{0}_"{2*($1==21)}\ 37998 "{0}_"{2*($1==22)}\ 37999 "{0}_"{2*($1==23)}\ 38000 "{0}_"{2*($1==24)}\ 38001 "{0}" 38002 38003_fx_cluts_abigailgonzalez : 38004 u blade_runner,blue_house,blue_ice,caribe,cinema,cinema_2,cinema_3,\ 38005 cinema_4,cinema_5,cinema_noir,cinematic_for_flog,day_4nite,eterna_for_flog,filmic,\ 38006 fuji_hdr,goldengate,matrix,monochrome_1,monochrome_2,old_west,science_fiction 38007 38008_fx_cluts_alexjordan : 38009 u action_magenta_01,action_red_01,adventure_1453,agressive_highligjtes_recovery_5,bleech_bypass_green,\ 38010 bleech_bypass_yellow_01,blue_dark,blue_shadows_01,bright_green_01,brownish,colorful_0209,conflict_01,\ 38011 contrast_with_highlights_protection,contrasty_afternoon,contrasty_green,cross_process_cp_130,cross_process_cp_14,\ 38012 cross_process_cp_15,cross_process_cp_16,cross_process_cp_18,cross_process_cp_3,cross_process_cp_4,\ 38013 cross_process_cp_6,dark_green_02,dark_green_1,dark_place_01,dream_1,dream_85,faded_retro_01,faded_retro_02,\ 38014 film_0987,film_9879,film_high_contrast,flat_30,green_2025,green_action,green_afternoon,\ 38015 green_conflict,green_day_01,green_day_02,green_g_09,green_indoor,green_light,harsh_day,harsh_sunset,\ 38016 highlights_protection,indoor_blue,low_contrast_blue,low_key_01,magenta_day,magenta_day_01,magenta_dream,\ 38017 memories,moonlight_01,mostly_blue,muted_01,night_01,only_red,only_red_and_blue,operation_yellow,orange_dark_4,\ 38018 orange_dark_7,orange_dark_look,orange_underexposed,protect_highlights_01,red_afternoon_01,red_day_01,red_dream_01,\ 38019 retro_brown_01,retro_magenta_01,retro_yellow_01,saturated_blue,smart_contrast,subtle_blue,subtle_green,yellow_55b,\ 38020 yellow_film_01 38021 38022_fx_cluts_berat : 38023 u brownbm,cineblue,cinebm4k,goldentime,green_and_orange,monochrome,sevsuz,sunlightlove,western,westernlut2 38024 38025_fx_cluts_cinematic : 38026 u deep,dimension,enchanted,flavin,frosted,shine,ultra_water,wipe 38027 38028_fx_cluts_cinematic_travel : 38029 u blue_cold_fade,bright_teal_orange,bright_warm,clear_teal_fade,cold_clear_blue,cold_clear_blue_1,deep_blue,\ 38030 deep_dark_warm,deep_high_contrast,deep_teal_fade,deep_warm_fade,faded_green,greenish_contrasty,greenish_fade,\ 38031 greenish_fade_1,hard_teal_orange,neutral_teal_orange,neutral_warm_fade,smooth_clear,smooth_green_orange,\ 38032 smooth_teal_orange,teal_fade,very_warm_greenish,warm_dark_contrasty,warm_fade,warm_fade_1,warm_neutral,\ 38033 warm_sunset_red,warm_teal 38034 38035_fx_cluts_creative : 38036 u anime,bleachbypass_1,bleachbypass_2,bleachbypass_3,bleachbypass_4,candlelight,colornegative,crispwarm,crispwinter,\ 38037 dropblues,edgyember,fallcolors,foggynight,futuristicbleak_1,futuristicbleak_2,futuristicbleak_3,futuristicbleak_4,\ 38038 horrorblue,latesunset,moonlight,nightfromday,redblueyellow,smokey,softwarming,tealmagentagold,tealorange,\ 38039 tealorange_1,tealorange_2,tealorange_3,tensiongreen_1,tensiongreen_2,tensiongreen_3,tensiongreen_4 38040 38041_fx_cluts_ericellerbrock : 38042 u avalanche,black_star,helios,hydracore,hypnosis,killstreak,nemesis,night_blade_4,paladin,seringe_4,serpent,terra_4,\ 38043 victory,yellowstone 38044 38045_fx_cluts_filtergrade : 38046 u fgcinebasic,fgcinebright,fgcinecold,fgcinedrama,fgcinetealorange_1,fgcinetealorange_2,fgcinevibrant,fgcinewarm 38047 38048_fx_cluts_inavision : 38049 u 7drk_21,bc_darkum,brown_mobster,cold_ice,dark_man_x,film_gb-19,formula_b,gremerta,hitman,jwick_21,london_nights,\ 38050 louetta,nightlife,vfb_21,vintage_mob 38051 38052_fx_cluts_jtsemple : 38053 u brightgreen,crispromance,crushin,frostedbeachpicnic,justpeachy,lateafternoonwanderlust,lushgreensummer,\ 38054 magentacoffee,minimalistcaffeination,mysticpurplesunset,nostalgiahoney,springmorning,toastedgarden,\ 38055 winterlighthouse 38056 38057_fx_cluts_kylerholland : 38058 u kh1,kh2,kh3,kh4,kh5,kh6,kh7,kh8,kh9,kh10 38059 38060_fx_cluts_lutifyme : 38061 u hackmanite,herderite,heulandite,hiddenite,hilutite,howlite,hypersthene 38062 38063_fx_cluts_michaelezra : 38064 u deepskintones2,deepskintones3 38065 38066_fx_cluts_moviz : 38067 u moviz_1,moviz_2,moviz_3,moviz_4,moviz_5,moviz_6,moviz_7,moviz_8,moviz_9,moviz_10,\ 38068 moviz_11,moviz_12,moviz_13,moviz_14,moviz_15,moviz_16,moviz_17,moviz_18,moviz_19,moviz_20,\ 38069 moviz_21,moviz_22,moviz_23,moviz_24,moviz_25,moviz_26,moviz_27,moviz_28,moviz_29,moviz_30,\ 38070 moviz_31,moviz_32,moviz_33,moviz_34,moviz_35,moviz_36,moviz_37,moviz_38,moviz_39,moviz_40,\ 38071 moviz_41,moviz_42,moviz_43,moviz_44,moviz_45,moviz_46,moviz_47,moviz_48 38072 38073_fx_cluts_ohadperetz : 38074 u cold_simplicity_2,d_o_1,retro_summer_3,subtle_yellow,teal_moonlight,true_colors_8,vintage_warmth_1 38075 38076_fx_cluts_oliviosarikas : 38077 u analog_film_1,atomic_pink,beach_aqua_orange,beach_faded_analog,bw_but_yellow,city_dust,dark_orange_teal,\ 38078 day_to_night_kings_blue,duotone_blue_red,faded_pink-ish,flat_blue_moon,honey_light,infrared_-_dust_pink,neutral_pump,\ 38079 shade_kings_ink,sunset_aqua_orange,sunset_intense_violet_blue,sunset_violet_mood,violet_taste 38080 38081_fx_cluts_on1 : 38082 u 2-strip-process,aqua,aqua_and_orange_dark,berlin_sky,blues,\ 38083 bw_1,bw_2,bw_3,bw_4,bw_5,bw_6,bw_7,bw_8,bw_9,bw_10,chrome_01,\ 38084 cinematic-1,cinematic-2,cinematic-3,cinematic-4,cinematic-5,cinematic-6,cinematic-7,cinematic-8,\ 38085 cinematic-9,cinematic-10,\ 38086 classic_teal_and_orange,earth_tone_boost,fade_to_green,film_print_01,film_print_02,french_comedy,green_blues,\ 38087 green_yellow,\ 38088 landscape_1,landscape_2,landscape_3,landscape_4,landscape_5,landscape_6,landscape_7,landscape_8,landscape_9,\ 38089 landscape_10,\ 38090 lc_1,lc_2,lc_3,lc_4,lc_5,lc_6,lc_7,lc_8,lc_9,lc_10,\ 38091 moody_1,moody_2,moody_3,moody_4,moody_5,moody_6,moody_7,moody_8,moody_9,moody_10,\ 38092 nw-1,nw-2,nw-3,nw-4,nw-5,nw-6,nw-7,nw-8,nw-9,nw-10,oranges,\ 38093 portrait_1,portrait_2,portrait_3,portrait_4,portrait_5,portrait_6,portrait_7,portrait_8,portrait_9,portrait_10,\ 38094 purple_2,reds,reds_oranges_yellows,studio_skin_tone_shaper,vintage_chrome 38095 38096_fx_cluts_picturefx : 38097 u analogfx_anno_1870_color,analogfx_old_style_i,analogfx_old_style_ii,analogfx_old_style_iii,\ 38098 analogfx_sepia_color,analogfx_soft_sepia_i,analogfx_soft_sepia_ii,\ 38099 faux_infrared_bw_1,faux_infrared_color_p2,faux_infrared_color_p3,faux_infrared_color_r0a,\ 38100 faux_infrared_color_r0b,faux_infrared_color_yp1,\ 38101 goldfx_bright_spring_breeze,goldfx_bright_summer_heat,goldfx_hot_summer_heat,\ 38102 goldfx_perfect_sunset_01min,goldfx_perfect_sunset_05min,goldfx_perfect_sunset_10min,\ 38103 goldfx_spring_breeze,goldfx_summer_heat,technicalfx_backlight_filter,\ 38104 zilverfx_bw_solarization,zilverfx_infrared,zilverfx_vintage_bw 38105 38106_fx_cluts_pixelmator : 38107 u black_white_01,black_white_02,black_white_03,black_white_04,black_white_05,black_white_06,\ 38108 pmcinematic_01,pmcinematic_02,pmcinematic_03,pmcinematic_04,pmcinematic_05,pmcinematic_06,pmcinematic_07,\ 38109 classic_films_01,classic_films_02,classic_films_03,classic_films_04,classic_films_05,\ 38110 landscape_01,landscape_02,landscape_03,landscape_04,landscape_05,\ 38111 modern_films_01,modern_films_02,modern_films_03,modern_films_04,modern_films_05,modern_films_06,modern_films_07,\ 38112 pmnight_01,pmnight_02,pmnight_03,pmnight_04,pmnight_05,\ 38113 urban_01,urban_02,urban_03,urban_04,urban_05,\ 38114 vintage_01,vintage_02,vintage_03,vintage_04,vintage_05 38115 38116_fx_cluts_pixlsus : 38117 u amstragram,amstragram+,autumn,cinematic_lady_bird,cinematic_mexico,dark_blues_in_sunlight,delicatessen,expired_69,\ 38118 fadedlook,faded_print,hypressen,magenta_yellow,metropolis,modern_film,newspaper,night_spy,progressen,prussian_blue,\ 38119 seventies_magazine,street,sweet_bubblegum,sweet_gelatto,taiga,tarraco,unknown,uzbek_bukhara,\ 38120 uzbek_marriage,uzbek_samarcande,velvetia,warm_vintage,whiter_whites 38121 38122_fx_cluts_purple11 : 38123 u good_morning,going_for_a_walk,nah,once_upon_a_time,serenity,passing_by,smooth_sailing,undeniable,undeniable2,\ 38124 urban_cowboy,well_see,you_can_do_it 38125 38126_fx_cluts_rocketstock : 38127 u arabica_12,ava_614,azrael_93,bourbon_64,byers_11,chemical_168,clayton_33,clouseau_54,cobi_3,contrail_35,\ 38128 cubicle_99,django_25,domingo_145,\ 38129 faded_47,folger_50,fusion_88,hyla_68,korben_214,lenox_340,lucky_64,mckinnon_75,milo_5,neon_770,paladin_1875,\ 38130 pasadena_21,pitaya_15,reeve_38,remy_24,sprocket_231,teigen_28,trent_18,tweed_71,vireo_37,zed_32,zeke_39 38131 38132_fx_cluts_shamoonabbasi : 38133 u city_7,coffee_44,date_39,day_for_night,denoiser_simple_40,desert_gold_37,directions_23,drop_green_tint_14,\ 38134 elegance_38,golden_night_softner_43,golden_sony_37,green_15,happyness_133,hlg_1_1,industrial_33,morning_6,\ 38135 morroco_16,night_king_141,rest_33,shadow_king_39,spy_29,thriller_2,turkiest_42,vintage_163,wooden_gold_20 38136 38137_fx_cluts_smallhd : 38138 u apocalypse_this_very_moment,bboyz_2,bob_ford,life_giving_tree,moonrise,saving_private_damon,the_matrices 38139 38140_fx_cluts_others : 38141 u 60s,60s_faded,60s_faded_alt,alien_green,black_and_white,bleach_bypass,blue_mono,\ 38142 cinematic_01,cinematic_02,cinematic_03,\ 38143 color_rich,faded,faded_alt,faded_analog,faded_extreme,faded_vivid,expired_fade,expired_polaroid,extreme,fade,\ 38144 faux_infrared,golden,golden_bright,golden_fade,golden_mono,golden_vibrant,green_mono,hong_kong,instantc,\ 38145 k_tone_vintage_kodachrome,light_blown,lomo,mono_tinted,\ 38146 muted_fade,mute_shift,natural_vivid,nostalgic,orange_tone,pink_fade,purple,retro,rotate_muted,\ 38147 rotate_vibrant,rotated,rotated_crush,\ 38148 smooth_cromeish,smooth_fade,soft_fade,solarized_color,solarized_color_2,summer,summer_alt,sunny,sunny_alt,\ 38149 sunny_warm,\ 38150 sunny_rich,super_warm,super_warm_rich,sutro_fx,vibrant,vibrant_alien,vibrant_contrast,vibrant_cromeish,\ 38151 vintage,vintage_alt,vintage_brighter,warm,warm_highlight,warm_yellow 38152 38153_fx_cluts_youssefhossam : 38154 u cinematic_forest,city,darkness,hallowen_dark,sea 38155 38156#@gui Colorful Blobs : fx_colorful_blobs, fx_colorful_blobs_preview 38157#@gui : Colorspace = choice(1,"sRGB","Linear RGB","Lab") 38158#@gui : Background Color = color(200,200,200,0) 38159#@gui : Display Blob Controls = bool(1) 38160#@gui : sep = separator() 38161#@gui : Blob 1 = point(25,25,1,1,0,0,0,0,5) 38162#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38163#@gui : Blob 1 Color = color(255,0,0) 38164#@gui : Previous = value(-1,-1,-1,-1) 38165#@gui : sep = separator() 38166#@gui : Blob2 = point(75,25,1,1,0,0,0,0,5) 38167#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38168#@gui : Blob 2 Color = color(0,255,0) 38169#@gui : Previous = value(-1,-1,-1,-1) 38170#@gui : sep = separator() 38171#@gui : Blob 3 = point(50,75,1,1,0,0,0,0,5) 38172#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38173#@gui : Blob 3 Color = color(0,0,255) 38174#@gui : Previous = value(-1,-1,-1,-1) 38175#@gui : sep = separator() 38176#@gui : Blob 4 = point(5,90,-1,1,0,0,0,0,5) 38177#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38178#@gui : Blob 4 Color = color(255,255,0) 38179#@gui : Previous = value(-1,-1,-1,-1) 38180#@gui : sep = separator() 38181#@gui : Blob 5 = point(5,90,-1,1,0,0,0,0,5) 38182#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38183#@gui : Blob 5 Color = color(255,0,255) 38184#@gui : Previous = value(-1,-1,-1,-1) 38185#@gui : sep = separator() 38186#@gui : Blob 6 = point(5,90,-1,1,0,0,0,0,5) 38187#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38188#@gui : Blob 6 Color = color(0,255,255) 38189#@gui : Previous = value(-1,-1,-1,-1) 38190#@gui : sep = separator() 38191#@gui : Blob 7 = point(5,90,-1,1,0,0,0,0,5) 38192#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38193#@gui : Blob 7 Color = color(255,255,255) 38194#@gui : Previous = value(-1,-1,-1,-1) 38195#@gui : sep = separator() 38196#@gui : Blob 8 = point(5,90,-1,1,0,0,0,0,5) 38197#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38198#@gui : Blob 8 Color = color(0,0,0) 38199#@gui : Previous = value(-1,-1,-1,-1) 38200#@gui : sep = separator() 38201#@gui : Blob 9 = point(5,90,-1,1,0,0,0,0,5) 38202#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38203#@gui : Blob 9 Color = color(255,128,64) 38204#@gui : Previous = value(-1,-1,-1,-1) 38205#@gui : sep = separator() 38206#@gui : Blob 10 = point(5,90,-1,1,0,0,0,0,5) 38207#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38208#@gui : Blob 10 Color = color(255,64,128) 38209#@gui : Previous = value(-1,-1,-1,-1) 38210#@gui : sep = separator() 38211#@gui : Blob 11 = point(5,90,-1,1,0,0,0,0,5) 38212#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38213#@gui : Blob 11 Color = color(128,64,255) 38214#@gui : Previous = value(-1,-1,-1,-1) 38215#@gui : sep = separator() 38216#@gui : Blob 12 = point(5,90,-1,1,0,0,0,0,5) 38217#@gui : Radius = point(50,50,0,1,0,0,0,0,5)_0 38218#@gui : Blob 12 Color = color(64,128,255) 38219#@gui : Previous = value(-1,-1,-1,-1) 38220#@gui : sep = separator() 38221#@gui : note = note("This filter can be used to create custom palettes with given color shades. 38222#@gui : It has been inspired by 38223#@gui : <a href="https://research.adobe.com/project/playful-palette-an-interactive-parametric-color-mixer-for-artists/"> 38224#@gui : Adobe's Playful Palette</a>.") 38225#@gui : sep = separator() 38226#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/08/26</i>.</small>") 38227fx_colorful_blobs : 38228 N=12 38229 colorspace,bgR,bgG,bgB,bgA,display_controls,\ 38230 x0,y0,rx0,ry0,R0,G0,B0,p_x0,p_y0,p_rx0,p_ry0,\ 38231 x1,y1,rx1,ry1,R1,G1,B1,p_x1,p_y1,p_rx1,p_ry1,\ 38232 x2,y2,rx2,ry2,R2,G2,B2,p_x2,p_y2,p_rx2,p_ry2,\ 38233 x3,y3,rx3,ry3,R3,G3,B3,p_x3,p_y3,p_rx3,p_ry3,\ 38234 x4,y4,rx4,ry4,R4,G4,B4,p_x4,p_y4,p_rx4,p_ry4,\ 38235 x5,y5,rx5,ry5,R5,G5,B5,p_x5,p_y5,p_rx5,p_ry5,\ 38236 x6,y6,rx6,ry6,R6,G6,B6,p_x6,p_y6,p_rx6,p_ry6,\ 38237 x7,y7,rx7,ry7,R7,G7,B7,p_x7,p_y7,p_rx7,p_ry7,\ 38238 x8,y8,rx8,ry8,R8,G8,B8,p_x8,p_y8,p_rx8,p_ry8,\ 38239 x9,y9,rx9,ry9,R9,G9,B9,p_x9,p_y9,p_rx9,p_ry9,\ 38240 x10,y10,rx10,ry10,R10,G10,B10,p_x10,p_y10,p_rx10,p_ry10,\ 38241 x11,y11,rx11,ry11,R11,G11,B11,p_x11,p_y11,p_rx11,p_ry11,\ 38242 =$* 38243 if !0$_is_preview display_controls=0 fi 38244 if $1==1 srgb2cs=srgb2rgb cs2srgb=rgb2srgb 38245 elif $1==2 srgb2cs=srgb2lab cs2srgb=lab2srgb 38246 fi 38247 38248 {0,s=min(w,h);[s,s]},1,4 k. 100%,100%,1,1,1e-8 38249 38250 repeat $N 38251 # If center point has been moved -> Update radius point. 38252 rx$>,ry$>={"P = ["${x$>},${y$>}"]; 38253 R = ["${rx$>},${ry$>}"]; 38254 oP = ["${p_x$>},${p_y$>}"]; 38255 oP==[-1,-1]?P + [10,0]:P!=oP?R + P - oP:R"} 38256 38257 if !isnan(${x$>}) 38258 x,y,rx,ry,R,G,B={"const w1 = (w - 1)%; const h1 = (h -1)%; "\ 38259 round([${x$>}*w1,${y$>}*h1,${rx$>}*w1,${ry$>}*h1,${R$>},${G$>},${B$>}])} 38260 r={max(1,round(norm($x-$rx,$y-$ry)))} 38261 if $1 ($R^$G^$B) $srgb2cs. R,G,B={^} rm. fi 38262 f. "* 38263 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; 38264 const r = 1.2*"($r)"; 38265 dist = norm(x-"$x",y-"$y")/r; 38266 w = pexp(dist); 38267 j(#0,0,0,0) += w*"$R"; 38268 j(#0,0,0,0,1) += w*"$G"; 38269 j(#0,0,0,0,2) += w*"$B"; 38270 i + w; 38271 " 38272 fi 38273 done 38274 sh[0] 0,2 /. [1] if $1 $cs2srgb. fi 38275 f[0] "*begin(bg = [ "$bgR,$bgG,$bgB,$bgA" ]); i(#1)<0.5?bg:[R,G,B,255]" k[0] 38276 38277 repeat $N 38278 if !isnan(${x$>})" && "$display_controls 38279 x,y,rx,ry,R,G,B={"const w1 = (w - 1)%; const h1 = (h -1)%; "\ 38280 round([${x$>}*w1,${y$>}*h1,${rx$>}*w1,${ry$>}*h1,${R$>},${G$>},${B$>}])} 38281 circle $x,$y,3,0.85,0xFFFFFFFF,{v=avg(crop($x-3,$y-3,7,7))>128?0:255;[v,v,v,255]} 38282 rectangle {"const x = "$rx"; const y = "$ry"; [x-2,y-2,x+2,y+2]"},0.85,0xFFFFFFFF,\ 38283 {v=avg(crop($rx-3,$ry-3,7,7))>128?0:255;[v,v,v,255]} 38284 line $x,$y,$rx,$ry,0.5,0xF0F0F0F0,255 line $x,$y,$rx,$ry,0.5,0x0F0F0F0F,0,0,0,255 38285 fi 38286 done 38287 38288 if 0$_is_preview 38289 u \{$colorspace\}\{$bgR,$bgG,$bgB,$bgA\}\{$display_controls\}\ 38290 \{$x0,$y0\}\{$rx0,$ry0\}\{$R0,$G0,$B0\}\{$x0,$y0,$rx0,$ry0\}\ 38291 \{$x1,$y1\}\{$rx1,$ry1\}\{$R1,$G1,$B1\}\{$x1,$y1,$rx1,$ry1\}\ 38292 \{$x2,$y2\}\{$rx2,$ry2\}\{$R2,$G2,$B2\}\{$x2,$y2,$rx2,$ry2\}\ 38293 \{$x3,$y3\}\{$rx3,$ry3\}\{$R3,$G3,$B3\}\{$x3,$y3,$rx3,$ry3\}\ 38294 \{$x4,$y4\}\{$rx4,$ry4\}\{$R4,$G4,$B4\}\{$x4,$y4,$rx4,$ry4\}\ 38295 \{$x5,$y5\}\{$rx5,$ry5\}\{$R5,$G5,$B5\}\{$x5,$y5,$rx5,$ry5\}\ 38296 \{$x6,$y6\}\{$rx6,$ry6\}\{$R6,$G6,$B6\}\{$x6,$y6,$rx6,$ry6\}\ 38297 \{$x7,$y7\}\{$rx7,$ry7\}\{$R7,$G7,$B7\}\{$x7,$y7,$rx7,$ry7\}\ 38298 \{$x8,$y8\}\{$rx8,$ry8\}\{$R8,$G8,$B8\}\{$x8,$y8,$rx8,$ry8\}\ 38299 \{$x9,$y9\}\{$rx9,$ry9\}\{$R9,$G9,$B9\}\{$x9,$y9,$rx9,$ry9\}\ 38300 \{$x10,$y10\}\{$rx10,$ry10\}\{$R10,$G10,$B10\}\{$x10,$y10,$rx10,$ry10\}\ 38301 \{$x11,$y11\}\{$rx11,$ry11\}\{$R11,$G11,$B11\}\{$x11,$y11,$rx11,$ry11\} 38302 fi 38303 38304fx_colorful_blobs_preview : 38305 _is_preview=1 38306 rm {s=min($_preview_width,$_preview_height)/2;[s,s]},1,1 38307 fx_colorful_blobs $* 38308 38309#@gui Colormap : fx_colormap,fx_colormap_preview 38310#@gui : Colormap = choice{2,"Adaptive","Custom","Standard (256)","HSV (256)","Lines (256)","Hot (256)", 38311#@gui : "Cool (256)","Jet (256)","Flag (256)","Cube (256)"} 38312#@gui : Dithering = float(1,0,1) 38313#@gui : sep = separator() 38314#@gui : Number of Tones = int(32,2,256)_0 38315#@gui : Number of Colors = int(8,2,8)_0 38316#@gui : 1st Color = color(0,0,0)_0 38317#@gui : 2nd Color = color(255,255,255)_0 38318#@gui : 3rd Color = color(255,0,0)_0 38319#@gui : 4th Color = color(0,255,0)_0 38320#@gui : 5th Color = color(0,0,255)_0 38321#@gui : 6th Color = color(255,255,0)_0 38322#@gui : 7th Color = color(255,0,255)_0 38323#@gui : 8th Color = color(0,255,255)_0+ 38324#@gui : sep = separator() 38325#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38326#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38327#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38328#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38329#@gui : sep = separator() 38330#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/27/12</i>.</small>") 38331fx_colormap : 38332 repeat $! l[$>] split_opacity to_rgb[0] 38333 if $1>=2 # Pre-defined colormap. 38334 index[0] {$1-2},$2,1 38335 elif $1==1 # Custom colormap. 38336 (${5-28}) z. 0,{3*$4-1} 38337 r. 3,{w/3},1,1,-1 permute. yzcx r. $3,1,1,3,3 38338 index[0] .,$2,1 rm. 38339 else # Adaptive colormap. 38340 autoindex[0] $3,$2,{if($3<=32,1,0)} 38341 fi 38342 a c 38343 endl done 38344 38345fx_colormap_preview : 38346 gui_split_preview "fx_colormap $*",${-3--1} 38347 is_ad,is_cu={2*[$1==0||$1==1,$1==1]} 38348 u "{$1}{$2}"\ 38349 "{$3}_"$is_ad\ 38350 "{$4}_"$is_cu\ 38351 "{${5-7}}_"$is_cu\ 38352 "{${8-10}}_"$is_cu\ 38353 "{${11-13}}_"$is_cu\ 38354 "{${14-16}}_"$is_cu\ 38355 "{${17-19}}_"$is_cu\ 38356 "{${20-22}}_"$is_cu\ 38357 "{${23-25}}_"$is_cu\ 38358 "{${26-28}}_"$is_cu\ 38359 "{$29}{$30,$31}" 38360 38361#@gui Color Mask [Interactive] : fx_mask_color, gui_no_preview 38362#@gui : Color Metric = _choice(13,"RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","Linear RGB [All]", 38363#@gui : "Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 38364#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [red chrominance]", 38365#@gui : "YCbCr [green chrominance]","Lab [all]","Lab [lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 38366#@gui : "Lab [b-Chrominance]","Lch [all]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]", 38367#@gui : "HSV [all]","HSV [hue]","HSV [saturation]","HSV [value]","HSI [all]","HSI [intensity]","HSL [all]", 38368#@gui : "HSL [lightness]","CMYK [cyan]","CMYK [magenta]","CMYK [yellow]","CMYK [key]","YIQ [luma]","YIQ [chromas]") 38369#@gui : Spatial Tolerance = _float(10,0,100) 38370#@gui : Color Tolerance = _float(5,0,100) 38371#@gui : sep = separator() 38372#@gui : Output Mode = _choice(0,"Masked image","Color mask") 38373#@gui : sep = separator() 38374#@gui : note = note{"<small><b>Note:</b> This filter is CPU consuming, so use it at least with 4+ cores 38375#@gui : (or reduce the size of the interactive window to speed up computation).</small>"} 38376#@gui : note = note{"<small><b>Interactions:</b>\n 38377#@gui : Use the following actions in the interactive window to build your color mask :\n\n 38378#@gui : - <b>Left mouse button</b> make the color pointed by the mouse wanted for the mask.\n 38379#@gui : - <b>Right mouse button</b> make the color pointed by the mouse unwanted for the mask.\n 38380#@gui : - <b>Middle mouse button</b> or key <b>R</b> resets color mask.\n 38381#@gui : - Key <b>SPACE</b> or <b>TAB</b> toggles view modes (half/full-masked RGB or color mask).\n 38382#@gui : - Keys <b>CTRL+D</b> increase window size.\n 38383#@gui : - Keys <b>CTRL+C</b> decrease window size.\n 38384#@gui : - Keys <b>CTRL+R</b> resets window size.\n 38385#@gui : - Keys <b>ESC</b>, <b>Q</b> or <b>ENTER</b> exit the interactive window. 38386#@gui : </small>"} 38387#@gui : sep = separator() 38388#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>01/20/2017</i>.</small>") 38389fx_mask_color : 38390 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,\ 38391 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,\ 38392 cmyk_c,cmyk_m,cmyk_y,cmyk_k,yiq_y,yiq_iq 38393 repeat $! l[$<] to_rgb nm={n} nm ${-gui_layer_name} 38394 +x_mask_color ${arg\ 1+$1,$cs},$2,$3 38395 if $4==1 channels. 100% fi 38396 nm $nm rv 38397 endl done 38398 38399#@gui Curves : fx_curves_interactive, fx_curves_interactive_preview 38400#@gui : Colorspace = choice{"RGB","CMY","CMYK","HSI","HSL","HSV","Lab","Lch","YCbCr"} 38401#@gui : Output Preset as a HaldCLUT Layer = _choice("Disable","Lowres CLUT","Highres CLUT") 38402#@gui : Apply Transformation From = _choice("New Curves [Interactive]","Curves Previously Defined") 38403#@gui : Colorspace = value(0) 38404#@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) 38405#@gui : sep = separator() 38406#@gui : note = note{"<small><b>Description:</b>\n 38407#@gui : This filter allows to apply color curves on your images, in many different colorspaces. 38408#@gui : Click on the <i>Apply</i> or <i>OK</i> buttons below to open the G'MIC interactive windows and 38409#@gui : start building your color curves. 38410#@gui : When you're done, exit the main image window: your modified result will be transferred back to the 38411#@gui : host software.\n\n 38412#@gui : Once you've set curves, you can save them by pressing the <b>Add to faves</b> button below the filter tree. 38413#@gui : To clear control points for your curves, click on the <i>Reset</i> button above. 38414#@gui : </small>"} 38415#@gui : sep = separator() 38416#@gui : note = note{"<small><b>Interactions:</b>\n 38417#@gui : Use the following actions in the interactive windows to manage your colorization :\n\n 38418#@gui : - <b>Left mouse button</b> on a curve creates a new color control point (or move an existing one).\n 38419#@gui : - <b>Right mouse button</b> on a control point deletes it.\n 38420#@gui : - <b>Left mouse button</b> on the main image window shows the initial image until button is released.\n 38421#@gui : - <b>Right mouse button</b> on the main image window adds a keypoint to all curves from picked color.\n 38422#@gui : - Key <b>R</b> on a curve resets it.\n 38423#@gui : - Keys <b>CTRL+D</b> increase window size.\n 38424#@gui : - Keys <b>CTRL+C</b> decrease window size.\n 38425#@gui : - Keys <b>CTRL+R</b> resets window size.\n 38426#@gui : - Keys <b>ESC</b>, <b>Q</b> or <b>ENTER</b> close the current window. 38427#@gui : </small>"} 38428#@gui : sep = separator() 38429#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>09/28/2014</i>.</small>") 38430fx_curves_interactive : 38431 nm "Color curves" 38432 repeat 4 __xcc_C$>=0,0,100,100 done 38433 if $4==$1 l[] ($5) s -,-1 repeat $! __xcc_C$>={$>,^} done rm endl fi 38434 if $3 # Apply transformation from previously defined curves 38435 _xcc_colorbase=${arg\ {$4+1},rgb,cmy,cmyk,hsi,hsl,hsv,lab,lch,ycbcr} x_color_curves last 38436 else # Run interactive curve builder 38437 x_color_curves ${arg\ {$1+1},rgb,cmy,cmyk,hsi,hsl,hsv,lab,lch,ycbcr} 38438 u "{$1}{$2}{$3}{$1}{"$__xcc_C0,-1,$__xcc_C1,-1,$__xcc_C2,-1,$__xcc_C3,-1,$__xcc_C4"}" 38439 fi 38440 if $2 # Add HaldCLUT layer 38441 (0,255) (0;255) (0/255) r[-3--1] 2,2,2 a[-3--1] c 38442 if $2==2 r. 256,256,256,3,3 r. 4096,4096,1,3,-1 # High-res HaldCLUT 38443 else r. 64,64,64,3,3 r. 512,512,1,3,-1 # Low-res HaldCLUT 38444 fi 38445 x_color_curves. last 38446 fi 38447 38448fx_curves_interactive_preview : 38449 fx_curves_interactive $1,0,1,$4,"$5" 38450 38451#@gui Customize CLUT : fx_customize_clut,fx_customize_clut_preview(1)+ 38452#@gui : Keypoint Influence (%) = float(100,0,100) 38453#@gui : Lock Uniform Sampling = choice{0,"None","8 Keypoints (RGB Corners)","27 Keypoints","64 Keypoints", 38454#@gui : "125 Keypoints","216 Keypoints","343 Keypoints"}, 38455#@gui : Spatial Regularization = int(10,0,30) 38456#@gui : sep = separator() 38457#@gui : note = note("<small><b>Global correction:</b></small>") 38458#@gui : Brightness (%) = float(0,-100,100) 38459#@gui : Contrast (%) = float(0,-100,100) 38460#@gui : Gamma (%) = float(0,-100,100) 38461#@gui : Hue (%) = float(0,-100,100) 38462#@gui : Saturation (%) = float(0,-100,100) 38463#@gui : Post-Normalize = bool(0) 38464#@gui : sep = separator() 38465#@gui : Output Corresponding CLUT = _choice("Disable","512x512 Layer","4096x4096 Layer") 38466#@gui : Preview Type = choice{8,"Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38467#@gui : "Backward Vertical","Duplicate Horizontal","Duplicate Vertical","HaldCLUT","3D CLUT (Fast)","3D CLUT (Precise)"} 38468#@gui : CLUT Opacity = float(0.5,0,1) 38469#@gui : sep = separator() 38470#@gui : note = note("<small><b>Color correspondences:</b></small>") 38471#@gui : Action #1 = choice(1,"Ignore","Lock Source","Replace Source by Target") 38472#@gui : Source Color #1 = color(0,0,0), Target Color #1 = color(0,0,0) 38473#@gui : sep = separator() 38474#@gui : Action #2 = choice(1,"Ignore","Lock Source","Replace Source by Target") 38475#@gui : Source Color #2 = color(255,255,255), Target Color #2 = color(255,196,128) 38476#@gui : sep = separator() 38477#@gui : Action #3 = choice("Ignore","Lock Source","Replace Source by Target") 38478#@gui : Source Color #3 = color(0,0,0), Target Color #3 = color(0,0,0) 38479#@gui : sep = separator() 38480#@gui : Action #4 = choice("Ignore","Lock Source","Replace Source by Target") 38481#@gui : Source Color #4 = color(0,0,0), Target Color #4 = color(0,0,0) 38482#@gui : sep = separator() 38483#@gui : Action #5 = choice("Ignore","Lock Source","Replace Source by Target") 38484#@gui : Source Color #5 = color(0,0,0), Target Color #5 = color(0,0,0) 38485#@gui : sep = separator() 38486#@gui : Action #6 = choice("Ignore","Lock Source","Replace Source by Target") 38487#@gui : Source Color #6 = color(0,0,0), Target Color #6 = color(0,0,0) 38488#@gui : sep = separator() 38489#@gui : Action #7 = choice("Ignore","Lock Source","Replace Source by Target") 38490#@gui : Source Color #7 = color(0,0,0), Target Color #7 = color(0,0,0) 38491#@gui : sep = separator() 38492#@gui : Action #8 = choice("Ignore","Lock Source","Replace Source by Target") 38493#@gui : Source Color #8 = color(0,0,0), Target Color #8 = color(0,0,0) 38494#@gui : sep = separator() 38495#@gui : Action #9 = choice("Ignore","Lock Source","Replace Source by Target") 38496#@gui : Source Color #9 = color(0,0,0), Target Color #9 = color(0,0,0) 38497#@gui : sep = separator() 38498#@gui : Action #10 = choice("Ignore","Lock Source","Replace Source by Target") 38499#@gui : Source Color #10 = color(0,0,0), Target Color #10 = color(0,0,0) 38500#@gui : sep = separator() 38501#@gui : Action #11 = choice("Ignore","Lock Source","Replace Source by Target") 38502#@gui : Source Color #11 = color(0,0,0), Target Color #11 = color(0,0,0) 38503#@gui : sep = separator() 38504#@gui : Action #12 = choice("Ignore","Lock Source","Replace Source by Target") 38505#@gui : Source Color #12 = color(0,0,0), Target Color #12 = color(0,0,0) 38506#@gui : sep = separator() 38507#@gui : Action #13 = choice("Ignore","Lock Source","Replace Source by Target") 38508#@gui : Source Color #13 = color(0,0,0), Target Color #13 = color(0,0,0) 38509#@gui : sep = separator() 38510#@gui : Action #14 = choice("Ignore","Lock Source","Replace Source by Target") 38511#@gui : Source Color #14 = color(0,0,0), Target Color #14 = color(0,0,0) 38512#@gui : sep = separator() 38513#@gui : Action #15 = choice("Ignore","Lock Source","Replace Source by Target") 38514#@gui : Source Color #15 = color(0,0,0), Target Color #15 = color(0,0,0) 38515#@gui : sep = separator() 38516#@gui : Action #16 = choice("Ignore","Lock Source","Replace Source by Target") 38517#@gui : Source Color #16 = color(0,0,0), Target Color #16 = color(0,0,0) 38518#@gui : sep = separator() 38519#@gui : Action #17 = choice("Ignore","Lock Source","Replace Source by Target") 38520#@gui : Source Color #17 = color(0,0,0), Target Color #17 = color(0,0,0) 38521#@gui : sep = separator() 38522#@gui : Action #18 = choice("Ignore","Lock Source","Replace Source by Target") 38523#@gui : Source Color #18 = color(0,0,0), Target Color #18 = color(0,0,0) 38524#@gui : sep = separator() 38525#@gui : Action #19 = choice("Ignore","Lock Source","Replace Source by Target") 38526#@gui : Source Color #19 = color(0,0,0), Target Color #19 = color(0,0,0) 38527#@gui : sep = separator() 38528#@gui : Action #20 = choice("Ignore","Lock Source","Replace Source by Target") 38529#@gui : Source Color #20 = color(0,0,0), Target Color #20 = color(0,0,0) 38530#@gui : sep = separator() 38531#@gui : Action #21 = choice("Ignore","Lock Source","Replace Source by Target") 38532#@gui : Source Color #21 = color(0,0,0), Target Color #21 = color(0,0,0) 38533#@gui : sep = separator() 38534#@gui : Action #22 = choice("Ignore","Lock Source","Replace Source by Target") 38535#@gui : Source Color #22 = color(0,0,0), Target Color #22 = color(0,0,0) 38536#@gui : sep = separator() 38537#@gui : Action #23 = choice("Ignore","Lock Source","Replace Source by Target") 38538#@gui : Source Color #23 = color(0,0,0), Target Color #23 = color(0,0,0) 38539#@gui : sep = separator() 38540#@gui : Action #24 = choice("Ignore","Lock Source","Replace Source by Target") 38541#@gui : Source Color #24 = color(0,0,0), Target Color #24 = color(0,0,0) 38542#@gui : sep = separator() 38543#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/14/06</i>.</small>") 38544fx_customize_clut : 38545 38546 # Build CLUT. 38547 if !narg($_N) N=64 else N=$_N fi N1={$N-1} 38548 $N,$N,$N,4 38549 38550 if $2 # Lock uniform sampling 38551 uniform_distribution {(1+$2)^3},3 38552 repeat w point.. {round($N1*I[$>])},1,{255*I[$>]},1 done rm. 38553 fi 38554 38555 $=arg # Add user-defined color correspondences 38556 repeat 24 38557 mode=${arg{13+7*$<}} 38558 if $mode 38559 sr=${arg{14+7*$<}} sg=${arg{15+7*$<}} sb=${arg{16+7*$<}} 38560 tr=${arg{17+7*$<}} tg=${arg{18+7*$<}} tb=${arg{19+7*$<}} 38561 xyz={round(($N1/255)*[$sr,$sg,$sb])} 38562 point. $xyz,1,{$mode==2?[$tr,$tg,$tb]:[$sr,$sg,$sb]},1 38563 fi 38564 done 38565 38566 s c,-3 38567 if $1<100 # Need to compute a weighting map. 38568 +distance. 1 38569 if $1 ^. {1/(0.05+4*$1%)} else f. 0 fi 38570 n. 0,1 nm. influence mv. -3 38571 fi 38572 ==. 0 inpaint_pde.. .,100%,1,20 rm. c. 0,255 38573 38574 if $influence 38575 100%,100%,100%,3,[x,y,z] n. 0,255 38576 j. ..,0,0,0,0,1,... 38577 rm[-3,-2] 38578 fi 38579 38580 # Apply CLUT on input layers + global color corrections. 38581 if !$3 map_clut[^-1] . # w/o spatial regularization 38582 else repeat $!-1 # w/ spatial regularization 38583 +luminance[$>] +map_clut[$>] .. -. [$>] 38584 repeat $3 guided. ..,2,50 done +[$>,-1] rm. 38585 done fi 38586 adjust_colors ${4-8},0,255 38587 if $9 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done fi 38588 if $10 38589 if $10==2 r. 256,256,256,3,5 c. 0,255 fi 38590 siz={w^1.5} r. $siz,$siz,1,3,-1 38591 mv. 0 38592 else rm. 38593 fi 38594 38595fx_customize_clut_preview : 38596 if $11<7 gui_split_preview "fx_customize_clut ${1-9},0,0,${12--1}",$11 38597 elif $11==7 # HaldCLUT preview 38598 rm fx_customize_clut ${1-9},1,0,${12--1} 38599 elif $11>=8 # 3D CLUT preview 38600 _N={$11>=9?64:32} 38601 k[0] to_rgb w={w} h={h} 38602 +fx_customize_clut ${1-9},1,0,${12--1} mv. 1 38603 r. $_N,$_N,$_N,3,-1 pointcloud3d. o3d. $12 38604 l[] 38605 if $2 # Lock uniform sampling 38606 uniform_distribution {(1+$2)^3},3 38607 repeat w circle3d {0,round($_N*I[$>])},0.75 col3d. {0,255*I[$>]} done rm[0] 38608 fi 38609 $=arg # Add user-defined color correspondences 38610 repeat 24 38611 mode=${arg{13+7*$<}} 38612 if $mode 38613 sr=${arg{14+7*$<}} sg=${arg{15+7*$<}} sb=${arg{16+7*$<}} 38614 tr=${arg{17+7*$<}} tg=${arg{18+7*$<}} tb=${arg{19+7*$<}} 38615 xy={round(($_N/255)*[$sr,$sg])} 38616 z={round(($_N/255)*$sb)-0.1} 38617 circle3d $xy,$z,0.75 col3d. {$mode==2?[$tr,$tg,$tb]:[$sr,$sg,$sb]} 38618 fi 38619 done 38620 colorcube3d *3d. {$_N/255} o3d. 0.5 col3d. 0 p3d. 1 38621 endl 38622 +3d[2--1] 38623 pose3d. 5.10656,2.04904,2.723,-316.115,-0.0815767,4.97762,-3.59262,-41.7094,\ 38624 -3.40685,2.95212,4.16756,-118.811,0,0,203,1 38625 38626 # Try to find the best layout for displaying preview. 38627 if $w>$h # Landscape mode 38628 r2dx[0,1] {0,round(w/2)} 38629 to[0] "Before",2,0,13,1,0.75 38630 to[1] "After",2,0,13,1,0.75 38631 a[0,1] y r[0] 100%,$h,1,3,0 38632 else # Portrait mode. 38633 r2dy[0,1] {0,round(h/2)} 38634 to[0] "Before",2,0,13,1,0.75 38635 to[1] "After",2,0,13,1,0.75 38636 a[0,1] x r[0] $w,100%,1,3,0 38637 fi 38638 38639 snapshot3d. {0,1.1*min(w,h)},1.2,64,64,64 38640 autocrop. -. 64 r. {0,max(w,$w-w)},{0,max(h,$h-h)},1,3,0,0,0.5,0.5 +. 64 38641 to. "RGB CLUT",2,0,13,1,0.75 38642 a {`$w>$h?_'x':_'y'`} 38643 fi 38644 38645#@gui Decompose Channels : fx_decompose_channels, fx_decompose_channels_preview 38646#@gui : Color Basis = choice(7,"RGB","HSV","HSL","HSI","YUV","YCbCr","XYZ","Lab","Lch","CMY","CMYK","YIQ") 38647#@gui : Action = choice("Decompose","Recompose") 38648#@gui : Output Multiple Layers = _bool(0) 38649#@gui : Include Opacity Layer = bool(1) 38650#@gui : sep = separator() 38651#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/19/07</i>.</small>") 38652fx_decompose_channels : 38653 if !$2 # Decompose 38654 if $4 to_rgba else to_rgb fi 38655 repeat $! l[$<] nm={0,n} 38656 split_opacity 38657 _s3=A _s4=A 38658 _fx_decompose_channels$1[0] 38659 s[0] c 38660 if !$3 a x nm $nm 38661 else nm=${-gui_layer_name} repeat $! gui_set_layer_name[$>] {``$nm}" ["${_s$>}"]" done 38662 fi 38663 endl done 38664 else # Recompose 38665 channels 0 nbc={3+($1==10)} nb={$nbc+$4} 38666 if $3 repeat int($!/$nb) l[0-{$nb-1}] 38667 a[0-{$nbc-1}] c _fx_recompose_channels$1[0] a c 38668 endl mv. 0 done 38669 else repeat $! l[$>] 38670 s x,$nb a[0-{$nbc-1}] c _fx_recompose_channels$1[0] a c 38671 endl mv. 0 done fi 38672 fi 38673 38674fx_decompose_channels_preview : 38675 repeat $! l[$<] 38676 _s3=A _s4=A 38677 fx_decompose_channels $1,$2,1,$4 38678 if !$2 38679 fs={round(min(w,h)*15%)} 38680 repeat $! to[$>] ${_s$>},5,3,$fs,{max(2,round($fs/15))} done 38681 to_rgba 38682 fi 38683 endl done 38684 append_tiles , 38685 38686_fx_decompose_channels0 : _s0=R _s1=G _s2=B 38687_fx_decompose_channels1 : rgb2hsv8 _s0=H _s1=S _s2=V 38688_fx_decompose_channels2 : rgb2hsl8 _s0=H _s1=S _s2=L 38689_fx_decompose_channels3 : rgb2hsi8 _s0=H _s1=S _s2=I 38690_fx_decompose_channels4 : rgb2yuv8 _s0=Y _s1=U _s2=V 38691_fx_decompose_channels5 : rgb2ycbcr _s0=Y _s1=Cb _s2=Cr 38692_fx_decompose_channels6 : rgb2xyz8 _s0=X _s1=Y _s2=Z 38693_fx_decompose_channels7 : rgb2lab8 _s0=L _s1=a _s2=b 38694_fx_decompose_channels8 : rgb2lch8 _s0=L _s1=c _s2=h 38695_fx_decompose_channels9 : rgb2cmy _s0=C _s1=M _s2=Y 38696_fx_decompose_channels10 : rgb2cmyk _s0=C _s1=M _s2=Y _s3=K 38697_fx_decompose_channels11 : rgb2yiq8 _s0=Y _s1=I _s2=Q 38698 38699_fx_recompose_channels0 : 38700_fx_recompose_channels1 : hsv82rgb 38701_fx_recompose_channels2 : hsl82rgb 38702_fx_recompose_channels3 : hsi82rgb 38703_fx_recompose_channels4 : yuv82rgb 38704_fx_recompose_channels5 : ycbcr2rgb 38705_fx_recompose_channels6 : xyz82rgb 38706_fx_recompose_channels7 : lab82rgb 38707_fx_recompose_channels8 : lch82rgb 38708_fx_recompose_channels9 : cmy2rgb 38709_fx_recompose_channels10 : cmyk2rgb 38710_fx_recompose_channels11 : yiq82rgb 38711 38712#@gui Detect Skin : fx_detect_skin, fx_detect_skin_preview(1) 38713#@gui : Skin Estimation = choice(1,"Manual","Automatic") 38714#@gui : sep = separator() 38715#@gui : Tolerance = float(0.5,0,1) 38716#@gui : Smoothness = float(0.5,0,5) 38717#@gui : Threshold = float(1,0,10) 38718#@gui : Pre-Normalize Image = bool(1) 38719#@gui : sep = separator() 38720#@gui : note = note("<small><b>Manual estimation:</b>\n 38721#@gui : Use the sliders below to target as much skin pixels as you can.</small>") 38722#@gui : X-Coordinate = float(50,0,100) 38723#@gui : Y-Coordinate = float(50,0,100) 38724#@gui : Radius = float(5,0,25) 38725#@gui : sep = separator() 38726#@gui : Output Mode = choice(1,"Probability Map","Opaque Skin","Transparent Skin") 38727#@gui : sep = separator() 38728#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38729#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38730#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38731#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38732#@gui : sep = separator() 38733#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/03/01</i>.</small>") 38734fx_detect_skin : 38735 to_rgb 38736 m "_fx_detect_skin : 38737 if $5 balance_gamma 128,128,128 fi 38738 if $1 detect_skin $2 else detect_skin $2,$6%,$7%,$8% fi 38739 M={iM} b $3% * {255*$M/iM} * $4 c 0,255" 38740 repeat $! l[$>] 38741 if $9 # Opaque/transparent skin. 38742 +_fx_detect_skin a c 38743 if $9>1 sh 100% *. -1 +. 255 rm. fi 38744 else _fx_detect_skin # Probability mask. 38745 fi 38746 endl done 38747 um _fx_detect_skin 38748 38749fx_detect_skin_preview : 38750 gui_split_preview "fx_detect_skin $*",${-3--1} 38751 to_rgba 38752 if !$1 38753 circle $6%,$7%,$8%,0.3,0,255,0,255 38754 circle $6%,$7%,$8%,1,0xFFFFFFFF,0,255,0,255 38755 line {$6-0.25*$8}%,{$7-0.25*$8}%,{$6+0.25*$8}%,{$7+0.25*$8}%,1,255,255,0,255 38756 line {$6+0.25*$8}%,{$7-0.25*$8}%,{$6-0.25*$8}%,{$7+0.25*$8}%,1,255,255,0,255 38757 fi 38758 38759#@gui Equalize HSV : fx_hsv_equalizer, fx_hsv_equalizer_preview 38760#@gui : Preview Bands = bool(false) 38761#@gui : sep = separator() 38762#@gui : Hue Band = float(180,0,360) 38763#@gui : Band Width = float(40,1,360) 38764#@gui : Hue Shift = float(0,-180,180) 38765#@gui : Saturation Correction = float(0,-0.99,0.99) 38766#@gui : Value Correction = float(0,-0.99,0.99) 38767#@gui : sep = separator() 38768#@gui : Hue Band = float(180,0,360) 38769#@gui : Band Width = float(40,1,360) 38770#@gui : Hue Shift = float(0,-180,180) 38771#@gui : Saturation Correction = float(0,-0.99,0.99) 38772#@gui : Value Correction = float(0,-0.99,0.99) 38773#@gui : sep = separator() 38774#@gui : Hue Band = float(180,0,360) 38775#@gui : Band Width = float(40,1,360) 38776#@gui : Hue Shift = float(0,-180,180) 38777#@gui : Saturation Correction = float(0,-0.99,0.99) 38778#@gui : Value Correction = float(0,-0.99,0.99) 38779#@gui : sep = separator() 38780#@gui : note = note("<small>Author: <i>Jérome Ferrari</i>. 38781#@gui : Latest Update: <i>01/14/2011</i>.</small>") 38782#@gui : url = link("Filter explained here","http://www.flickr.com/groups/gmic/discuss/72157625798533482") 38783fx_hsv_equalizer : 38784 repeat $! l[$>] 38785 to_rgb rgb2hsv s c 38786# From now on 0,1,2 are H,S,V 38787#3 masks: 38788 +f[0] if(abs(i-$2)<$3/2|abs(i-$2-360)<$3/2|abs(i-$2+360)<$3/2,1,0) 38789 +f[0] if(abs(i-$7)<$8/2|abs(i-$7-360)<$8/2|abs(i-$7+360)<$8/2,1,0) 38790 +f[0] if(abs(i-$12)<$13/2|abs(i-$12-360)<$13/2|abs(i-$12+360)<$13/2,1,0) 38791# From now on 3,4,5 are Masks 38792 +threshold[1,2] 0.01 *[-1,-2] [-1]x2 *[-1,3] *[-1,4] *[-1,5] #0 saturation and value not in mask 38793# Hue shift: 38794 +*[3] $4 +*[4] $9 +*[5] $14 +[-1,-2,-3] 38795 +[-1,0] %[0] 360 38796# Saturation : 38797 if $5>=0 +*[3] -$5 else +*[3] {1/(1+$5)-1} fi +. 1 38798 if $10>=0 +*[4] -$10 else +*[4] {1/(1+$10)-1} fi +. 1 38799 if $15>=0 +*[5] -$15 else +*[5] {1/(1+$15)-1} fi +. 1 38800 *[-1,-2,-3] ^[1,-1] 38801# Value : 38802 if $6>=0 +*[3] -$6 else +*[3] {1/(1+$6)-1} fi +. 1 38803 if $11>=0 +*[4] -$11 else +*[4] {1/(1+$11)-1} fi +. 1 38804 if $16>=0 +*[5] -$16 else +*[5] {1/(1+$16)-1} fi +. 1 38805 *[-1,-2,-3] ^[2,-1] 38806#reconstruction 38807 rm[3,4,5] a[0,1,2] c hsv2rgb 38808 endl done 38809 38810fx_hsv_equalizer_preview : 38811 l. 38812 if $1==0 fx_hsv_equalizer $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16 38813 else 38814 to_rgb rgb2hsv s c 38815 (0,359) r. ..,{{0,h}/10},1,1,3 . f. 1 #create lower band 38816 j[0] [3],0,91% j[1] [4],0,91% j[2] [4],0,91% rm[-1,-2] #paste lower band 38817 +f[0] if(abs(i-$2)<$3/2|abs(i-$2-360)<$3/2|abs(i-$2+360)<$3/2,1,0) 38818 +f[0] if(abs(i-$7)<$8/2|abs(i-$7-360)<$8/2|abs(i-$7+360)<$8/2,1,0) 38819 +f[0] if(abs(i-$12)<$13/2|abs(i-$12-360)<$13/2|abs(i-$12+360)<$13/2,1,0) #masks 38820 -|[-3--1] +. 0.33 /. 1.33 #1 and 0.25 38821 *[2,-1] a c hsv2rgb 38822 fi endl 38823 38824#@gui Equalize HSI-HSL-HSV : fx_equalize_hsv, fx_equalize_hsv_preview(0)+ 38825#@gui : Colorspace = choice(1,"HSI","HSL","HSV") 38826#@gui : Opacity (%) = float(100,0,100) 38827#@gui : Value Blending = float(0,0,64) 38828#@gui : Color Blending = float(0,0,64) 38829#@gui : sep = separator() 38830#@gui : Preview Mapping = choice("None","Grey","Color") 38831#@gui : sep = separator() 38832#@gui : note = note("<small><b>Black:</b></small>") 38833#@gui : Hue Offset = float(0,-180,180) 38834#@gui : Saturation Offset = float(0,-1,1) 38835#@gui : Value Offset = float(0,-1,1) 38836#@gui : sep = separator() 38837#@gui : note = note("<small><b>Near black:</b></small>") 38838#@gui : Hue Offset = float(0,-180,180) 38839#@gui : Saturation Offset = float(0,-1,1) 38840#@gui : Value Offset = float(0,-1,1) 38841#@gui : sep = separator() 38842#@gui : note = note("<small><b>Dark grey:</b></small>") 38843#@gui : Hue Offset = float(0,-180,180) 38844#@gui : Saturation Offset = float(0,-1,1) 38845#@gui : Value Offset = float(0,-1,1) 38846#@gui : sep = separator() 38847#@gui : note = note("<small><b>Mi-dark grey:</b></small>") 38848#@gui : Hue Offset = float(0,-180,180) 38849#@gui : Saturation Offset = float(0,-1,1) 38850#@gui : Value Offset = float(0,-1,1) 38851#@gui : sep = separator() 38852#@gui : note = note("<small><b>Middle grey:</b></small>") 38853#@gui : Hue Offset = float(0,-180,180) 38854#@gui : Saturation Offset = float(0,-1,1) 38855#@gui : Value Offset = float(0,-1,1) 38856#@gui : sep = separator() 38857#@gui : note = note("<small><b>Mid-light grey:</b></small>") 38858#@gui : Hue Offset = float(0,-180,180) 38859#@gui : Saturation Offset = float(0,-1,1) 38860#@gui : Value Offset = float(0,-1,1) 38861#@gui : sep = separator() 38862#@gui : note = note("<small><b>Light grey:</b></small>") 38863#@gui : Hue Offset = float(0,-180,180) 38864#@gui : Saturation Offset = float(0,-1,1) 38865#@gui : Value Offset = float(0,-1,1) 38866#@gui : sep = separator() 38867#@gui : note = note("<small><b>Highlights:</b></small>") 38868#@gui : Hue Offset = float(0,-180,180) 38869#@gui : Saturation Offset = float(0,-1,1) 38870#@gui : Value Offset = float(0,-1,1) 38871#@gui : sep = separator() 38872#@gui : note = note("<small><b>White:</b></small>") 38873#@gui : Hue Offset = float(0,-180,180) 38874#@gui : Saturation Offset = float(0,-1,1) 38875#@gui : Value Offset = float(0,-1,1) 38876#@gui : sep = separator() 38877#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38878#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38879#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38880#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38881#@gui : sep = separator() 38882#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>David Revoy</i>. 38883#@gui : Latest Update: <i>2018/01/19</i>.</small>") 38884fx_equalize_hsv : 38885 cs=${"arg 1+$1,hsi,hsl,hsv"} 38886 repeat $! l[$>] split_opacity l[0] 38887 to_rgb 38888 9,1,1,4,\ 38889 {"V = [${6-30:3}]*pi/180; [cos(V),sin(V)]"},${7-31:3},\ 38890 {"V = [${8-32:3}]; 38891 const sV = size(V); 38892 repeat (sV,k, 38893 v0 = k/sV; 38894 v1 = (k+1)/sV; 38895 V[k]*=(V[k]>0?(1 - v0):v1); 38896 ); V"} 38897 r. 256,1,1,4,1 38898 sh. 3 b. $3 rm. # Value smoothness 38899 f. "[ atan2(G,R)*180/pi,B,A,0 ]" channels. 0,2 38900 +rgb2$cs.. +channels. 100% *. 256 round. map. ... 38901 +[-2,-1] rm.. +channels. 100% ${cs}2rgb.. 38902 if $4 # Spatial smoothness 38903 *. 255 bilateral.. .,$4,{2+$4} 38904 rgb2$cs.. /. 255 j.. .,0,0,0,2 ${cs}2rgb.. 38905 fi 38906 rm. 38907 blend alpha,{$2%} 38908 endl a c endl done 38909 38910fx_equalize_hsv_preview : 38911 if $5 38912 cs=${"arg 1+$1,hsi,hsl,hsv"} 38913 rm {0.8*[${-gui_preview_wh}]},1,3,\ 38914 "$5==1? 38915 (H = S = 0; V = y/(h-1)): 38916 (H = x*360/(w-1); S = y/(h-1); V = y/(h-1)); 38917 [H,S,V]" 38918 ${cs}2rgb. 38919 fi 38920 gui_split_preview "fx_equalize_hsv $*",${-3--1} 38921 if $5 r. ${-gui_preview_wh},1,3,0,0,0.5,0.5 fi 38922 38923#@gui Mixer [CMYK] : fx_mix_cmyk, fx_mix_cmyk_preview(1)+ 38924#@gui : Cyan Factor = float(1,0,4) 38925#@gui : Cyan Shift = float(0,-255,255) 38926#@gui : Cyan Smoothness = float(0,0,10) 38927#@gui : sep = separator() 38928#@gui : Magenta Factor = float(1,0,4) 38929#@gui : Magenta Shift = float(0,-255,255) 38930#@gui : Magenta Smoothness = float(0,0,10) 38931#@gui : sep = separator() 38932#@gui : Yellow Factor = float(1,0,4) 38933#@gui : Yellow Shift = float(0,-255,255) 38934#@gui : Yellow Smoothness = float(0,0,10) 38935#@gui : sep = separator() 38936#@gui : Key Factor = float(1,0,4) 38937#@gui : Key Shift = float(0,-255,255) 38938#@gui : Key Smoothness = float(0,0,10) 38939#@gui : sep = separator() 38940#@gui : Tones Range = choice("All tones","Shadows","Mid-Tones","Highlights") 38941#@gui : Tones Smoothness = float(2,0,10) 38942#@gui : sep = separator() 38943#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38944#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38945#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38946#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38947#@gui : sep = separator() 38948#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 38949fx_mix_cmyk : 38950 repeat $! l. split_opacity rv to_rgb. 38951 fx_start_mix $13,$14 38952 rgb2cmyk. s. c 38953 *[-4] $1 +[-4] $2 b[-4] $3% 38954 *... $4 +... $5 b... $6% 38955 *.. $7 +.. $8 b.. $9% 38956 *. $10 +. $11 b. $12% 38957 a[-4--1] c cmyk2rgb. 38958 fx_end_mix $13 38959 if $!!=3 rv a c fi endl mv. 0 done 38960 38961fx_mix_cmyk_preview : 38962 gui_split_preview "fx_mix_cmyk $*",${-3--1} 38963 38964#@gui Mixer [HSV] : fx_mix_hsv, fx_mix_hsv_preview(1)+ 38965#@gui : Hue Factor = float(1,0,4) 38966#@gui : Hue Shift = float(0,-180,180) 38967#@gui : Hue Smoothness = float(0,0,10) 38968#@gui : sep = separator() 38969#@gui : Saturation Factor = float(1,0,4) 38970#@gui : Saturation Shift = float(0,-1,1) 38971#@gui : Saturation Smoothness = float(0,0,10) 38972#@gui : sep = separator() 38973#@gui : Value Factor = float(1,0,4) 38974#@gui : Value Shift = float(0,-1,1) 38975#@gui : Value Smoothness = float(0,0,10) 38976#@gui : sep = separator() 38977#@gui : Tones Range = choice("All Tones","Shadows","Mid-Tones","Highlights") 38978#@gui : Tones Smoothness = float(2,0,10) 38979#@gui : sep = separator() 38980#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 38981#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 38982#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 38983#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 38984#@gui : sep = separator() 38985#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 38986fx_mix_hsv : 38987 repeat $! l. split_opacity rv to_rgb. 38988 fx_start_mix $10,$11 38989 rgb2hsv. s. c -[-2,-1] 0.5 38990 *... $1 +... $2 b... $3% 38991 *.. $4 +.. $5 b.. $6% 38992 *. $7 +. $8 b. $9% 38993 %... 360 +[-2,-1] 0.5 c[-2,-1] 0,1 a[-3--1] c hsv2rgb. 38994 fx_end_mix $10 38995 if $!!=3 rv a c fi endl mv. 0 done 38996 38997fx_mix_hsv_preview : 38998 gui_split_preview "fx_mix_hsv $*",${-3--1} 38999 39000#@gui Mixer [Lab] : fx_mix_lab, fx_mix_lab_preview(1)+ 39001#@gui : Lightness Factor = float(1,0.5,1.5) 39002#@gui : Lightness Shift = float(0,-50,50) 39003#@gui : Lightness Smoothness = float(0,0,10) 39004#@gui : sep = separator() 39005#@gui : A-Color Factor = float(1,0,4) 39006#@gui : A-Color Shift = float(0,-20,20) 39007#@gui : A-Color Smoothness = float(0,0,10) 39008#@gui : sep = separator() 39009#@gui : B-Color Factor = float(1,0,4) 39010#@gui : B-Color Shift = float(0,-20,20) 39011#@gui : B-Color Smoothness = float(0,0,10) 39012#@gui : sep = separator() 39013#@gui : Tones Range = choice("All Tones","Shadows","Mid-Tones","Highlights") 39014#@gui : Tones Smoothness = float(2,0,10) 39015#@gui : sep = separator() 39016#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39017#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39018#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39019#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39020#@gui : sep = separator() 39021#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 39022fx_mix_lab : 39023 repeat $! l[$>] split_opacity to_rgb[0] 39024 gui_parallel_overlap[0] "_fx_mix_lab $*",0,{3*max($3,$6,$9)} 39025 a c 39026 endl mv[$>] 0 done 39027 39028_fx_mix_lab : 39029 fx_start_mix $10,$11 39030 rgb2lab. s. c 39031 *... $1 +... $2 b... $3% 39032 *.. $4 +.. $5 b.. $6% 39033 *. $7 +. $8 b. $9% 39034 a[-3--1] c lab2rgb. 39035 fx_end_mix $10 39036 39037fx_mix_lab_preview : 39038 gui_split_preview "fx_mix_lab $*",${-3--1} 39039 39040#@gui Mixer [PCA] : fx_mix_pca, fx_mix_pca_preview(1)+ 39041#@gui : Primary Factor = float(0,-1.5,1.5) 39042#@gui : Primary Shift = float(0,-255,255) 39043#@gui : Primary Twist = float(0,-180,180) 39044#@gui : Primary Gamma = float(0,-100,100) 39045#@gui : sep = separator() 39046#@gui : Secondary Factor = float(0,-1.5,1.5) 39047#@gui : Secondary Shift = float(0,-255,255) 39048#@gui : Secondary Twist = float(0,-180,180) 39049#@gui : Secondary Gamma = float(0,-100,100) 39050#@gui : sep = separator() 39051#@gui : Tertiary Factor = float(0,-1.5,1.5) 39052#@gui : Tertiary Shift = float(0,-255,255) 39053#@gui : Tertiary Twist = float(0,-180,180) 39054#@gui : Tertiary Gamma = float(0,-100,100) 39055#@gui : sep = separator() 39056#@gui : Display Color Axes = bool(1) 39057#@gui : Stats = value(-1,-1,-1,-1) 39058#@gui : Avg Covariance = value(0,0,0,0,0,0,0,0,0,0,0,0) 39059#@gui : sep = separator() 39060#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39061#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39062#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39063#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39064#@gui : sep = separator() 39065#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/07/18</i>.</small>") 39066fx_mix_pca : 39067 repeat $! l[$>] split_opacity l[0] to_rgb 39068 39069 # Get image covariance (and remember it to speed up multiple calls of the filter). 39070 if [$14]==round(stats()[0,4],0.1) _avg={[$15][0,3]} C={[$15][3,9]} status= 39071 else 39072 +rr2d 256,256,0,2 C=${"covariance_colors. _avg"} rm. 39073 __status="{$1}{$2}{$3}{$4}"\ 39074 "{$5}{$6}{$7}{$8}"\ 39075 "{$9}{$10}{$11}{$12}"\ 39076 "${13}"\ 39077 "{"{round(stats()[0,4],0.1)}"}"\ 39078 "{"$_avg,$C"}"\ 39079 "{$16}{${17,18}}" 39080 fi 39081 39082 # Find value ranges for gamma correction. 39083 if "$4 || $8 || $12" +l 39084 f "begin(avg = ["$_avg"]; eig = eig(["$C"]); Pt = eig[3,9]); Pt*(I-avg)" 39085 s c repeat $! vmax$>={$>,1.1*max(abs(im),abs(iM))} done 39086 rm 39087 endl else vmax0,vmax1,vmax2=1 fi 39088 39089 # Modify image values. 39090 f "begin( 39091 do_gamma(val,vmax,gamma) = (vmax*sign(val)*(abs(val)/vmax)^gamma); 39092 39093 const gamma0 = 10^-($4%); 39094 const gamma1 = 10^-($8%); 39095 const gamma2 = 10^-($12%); 39096 const vmax0 = "$vmax0"; 39097 const vmax1 = "$vmax1"; 39098 const vmax2 = "$vmax2"; 39099 39100 avg = ["$_avg"]; 39101 eig = eig(["$C"]); 39102 for (k = 3, k<12, k+=3, eig[k]<0?copy(eig[k],eig[k,3]*=-1,3)); 39103 Pt = eig[3,9]; 39104 P = transpose(Pt,3); 39105 T = mul(P,diag(10^[$1,$5,$9]),3); 39106 39107 R1 = rot(eig[3,3],$3°); 39108 R2 = rot(eig[6,3],$7°); 39109 R3 = rot(eig[9,3],$11°); 39110 T = mul(R1,mul(R2,mul(R3,T,3),3),3); 39111 avg_shift = avg + $2*eig[3,3] + $6*eig[6,3] + $10*eig[9,3]; 39112 39113 if ("0$_is_preview", 39114 L = [ 2,5,10]*sqrt(1e-5 + eig[0,3]); 39115 run('__cols=',vtos(round([ 39116 avg - L[0]*eig[3,3], 39117 avg + L[0]*eig[3,3], 39118 avg - L[1]*eig[6,3], 39119 avg + L[1]*eig[6,3], 39120 avg - L[2]*eig[9,3], 39121 avg + L[2]*eig[9,3] ]))); 39122 ); 39123 ); 39124 nI = Pt*(I - avg); 39125 ($4 || $8 || $12)?( 39126 nI[0] = do_gamma(nI[0],vmax0,gamma0); 39127 nI[1] = do_gamma(nI[1],vmax1,gamma1); 39128 nI[2] = do_gamma(nI[2],vmax2,gamma2); 39129 ); 39130 avg_shift + T*nI" 39131 c 0,255 39132 endl a c endl done u $__status 39133 39134fx_mix_pca_preview : 39135 _is_preview=1 39136 __status= 39137 repeat $! l[$>] 39138 gui_split_preview "fx_mix_pca ${1-13},\"$14\",\"$15\",${16-18}",${-3--1} 39139 if $13 39140 rr2d ${-gui_preview_wh},0,1 39141 ($__cols) r. 3,6,1,1,-1 permute. yzcx s. x,3 39142 r[-3--1] {w#0/2},13,1,3,3 c[-3--1] 0,255 39143 frame[-3--1] 1,1,0 39144 to[0] Primary,4,2,13,1 j[0] ...,64,4 39145 to[0] Secondary,4,17,13,1 j[0] ..,64,19 39146 to[0] Tertiary,4,32,13,1 j[0] .,64,34 39147 k[0] 39148 fi 39149 endl done 39150 u $__status 39151 39152#@gui Mixer [RGB] : fx_mix_rgb, fx_mix_rgb_preview(1)+ 39153#@gui : Red Factor = float(1,0,4) 39154#@gui : Red Shift = float(0,-255,255) 39155#@gui : Red Smoothness = float(0,0,10) 39156#@gui : sep = separator() 39157#@gui : Green Factor = float(1,0,4) 39158#@gui : Green Shift = float(0,-255,255) 39159#@gui : Green Smoothness = float(0,0,10) 39160#@gui : sep = separator() 39161#@gui : Blue Factor = float(1,0,4) 39162#@gui : Blue Shift = float(0,-255,255) 39163#@gui : Blue Smoothness = float(0,0,10) 39164#@gui : sep = separator() 39165#@gui : Tones Range = choice("All Tones","Shadows","Mid-Tones","Highlights") 39166#@gui : Tones Smoothness = float(2,0,10) 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 = separator() 39173#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 39174fx_start_mix : 39175 if $1==1 +tones. 3 +[-2,-1] b[-2,-1] $2% r[-2,-1] ... *. ... mv... $! 39176 elif $1==2 +tones. 3 +[-3,-1] b[-2,-1] $2% r[-2,-1] ... *.. ... mv... $! 39177 elif $1==3 +tones. 3 +[-3,-2] b[-2,-1] $2% r[-2,-1] ... *.. ... mv... $! 39178 fi 39179fx_end_mix : 39180 if $1==1 *[-3,-1] +[-2,-1] 39181 elif $1==2 *[-2,-1] +[-2,-1] 39182 elif $1==3 *[-2,-1] +[-2,-1] 39183 fi 39184 c 0,255 39185 39186fx_mix_rgb : 39187 repeat $! l. split_opacity rv to_rgb. 39188 fx_start_mix $10,$11 39189 -. 128 s. c 39190 *... $1 +... $2 b... $3% 39191 *.. $4 +.. $5 b.. $6% 39192 *. $7 +. $8 b. $9% 39193 a[-3--1] c +. 128 c. 0,255 39194 fx_end_mix $10 39195 if $!!=3 rv a c fi endl mv. 0 done 39196 39197fx_mix_rgb_preview : 39198 gui_split_preview "fx_mix_rgb $*",${-3--1} 39199 39200#@gui Mixer [YCbCr] : fx_mix_ycbcr, fx_mix_ycbcr_preview(1)+ 39201#@gui : Luminance Factor = float(1,0,4) 39202#@gui : Luminance Shift = float(0,-255,255) 39203#@gui : Luminance Smoothness = float(0,0,10) 39204#@gui : sep = separator() 39205#@gui : Blue Chroma Factor = float(1,0,4) 39206#@gui : Blue Chroma Shift = float(0,-255,255) 39207#@gui : Blue Chroma Smoothness = float(0,0,10) 39208#@gui : sep = separator() 39209#@gui : Red Chroma Factor = float(1,0,4) 39210#@gui : Red Chroma Shift = float(0,-255,255) 39211#@gui : Red Chroma Smoothness = float(0,0,10) 39212#@gui : sep = separator() 39213#@gui : Tones Range = choice("All Tones","Shadows","Mid-Tones","Highlights") 39214#@gui : Tones Smoothness = float(2,0,10) 39215#@gui : sep = separator() 39216#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39217#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39218#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39219#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39220#@gui : sep = separator() 39221#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 39222fx_mix_ycbcr : 39223 repeat $! l. split_opacity rv to_rgb. 39224 fx_start_mix $10,$11 39225 rgb2ycbcr. -. 128 s. c 39226 *... $1 +... $2 b... $3% 39227 *.. $4 +.. $5 b.. $6% 39228 *. $7 +. $8 b. $9% 39229 a[-3--1] c +. 128 c. 0,255 ycbcr2rgb. 39230 fx_end_mix $10 39231 if $!!=3 rv a c fi endl mv. 0 done 39232 39233fx_mix_ycbcr_preview : 39234 gui_split_preview "fx_mix_ycbcr $*",${-3--1} 39235 39236#@gui CLUT from After - Before Layers : fx_clut_from_ab, fx_clut_from_ab_preview 39237#@gui : Output Mode = choice("Replace Layer with CLUT","Insert New CLUT Layer","Save CLUT as .cube or .png File") 39238#@gui : Output CLUT Resolution = choice{4,16,25,36,49,64,81,100,121,144,169,225,256}_2 39239#@gui : sep = separator() 39240#@gui : Output Folder = _folder()_1- 39241#@gui : Output Filename = _text("output.cube")_1+ 39242#@gui : sep = separator() 39243#@gui : Influence of Color Samples (%) = float(50,0,100)_2 39244#@gui : sep = separator() 39245#@gui : note = note{"<b>What is this filter for?</b>\n\n 39246#@gui : This filter requires at least two input layers to work properly.\n 39247#@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 39248#@gui : <b>B</b> both represent the same image but with only color variations 39249#@gui : (typically <b>A</b> has been obtained from <b>B</b> using the color curves tool).\n\n 39250#@gui : This filter is then able to estimate and outputs a color HaldCLUT <b>H</b> so that applying <b>H</b> 39251#@gui : on the base layer <b>B</b> gives back <b>A</b>.\n\n 39252#@gui : This is useful when you have a color transformation between two images, that you want to recover and 39253#@gui : re-apply on a bunch of other images. 39254#@gui : "} 39255#@gui : sep = separator() 39256#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. 39257#@gui : Latest Update: <i>2019/08/27</i>.</small>") 39258fx_clut_from_ab : 39259 if $!<2 error "At least two input layers are needed to run this filter." fi 39260 repeat $!-1 l[$<,-1] nm=${gui_layer_name..} 39261 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" 39262 l[0] 39263 s c,-3 +max. 1 /[-3,-1] ==. 0 inpaint_pde.. .,75%,1 distance. 0 *. {-1/(1+$5)} exp. 39264 f.. "f = i(#-1); f*I + (1-f)*[x,y,z]*255/(w-1)" rm. 39265 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 39266 c 0,255 39267 endl 39268 39269 if $1==2 # Output as a file 39270 is_png={str=lowercase(['"$4"']);find(str,'.png')==size(str)-4} 39271 is_cube={str=lowercase(['"$4"']);find(str,'.cube')==size(str)-5} 39272 if !$is_png" && "!$is_cube $!is_ciube error "Filename extension must be '.cube' or '.png'." fi 39273 if $is_png r[0] {0,r=round(whd^0.5);[r,r]},1,3,-1 o[0] "$3/$4" 39274 else 39275 if {0,w>32} r3dx[0] 32 fi 39276 output_cube[0] "$3/$4" 39277 fi 39278 rm[0] 39279 else 39280 r[0] {0,r=round(whd^0.5);[r,r]},1,3,-1 39281 if !$1 rm[1] fi # Replace Layer with CLUT 39282 nm[0] "name(CLUT to '"$nm"')" 39283 fi 39284 if $_output_mode k[0] fi 39285 endl done 39286 39287fx_clut_from_ab_preview : 39288 if $!<2 gui_warning_preview "At least two input layers are needed to run this filter." return fi 39289 _is_preview,_output_mode=1 fx_clut_from_ab 0,4,0,0,$5 39290 repeat $! l[$>] 39291 r {a=round(cbrt(wh));[a,a,a]},3,-1 39292 +r3dx. 24 _fx_clut_from_ab_preview. 39293 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 39294 r[0] {0,r=round(whd^0.5);[r,r]},1,3,-1 39295 rr2d[0] $_preview_width,$_preview_height,2,1 r2dx. 70% 39296 sh. 100% b. 1% n. 0,255 rm. 39297 blend alpha 39298 endl done 39299 39300 file_attr={$1==2?2:1} 39301 u "{$1}{$2}{$3}_"$file_attr"{$4}_"$file_attr"{$5}" 39302 39303# Render 3D visualization of a CLUT. 39304_fx_clut_from_ab_preview : 39305 repeat $! l[$>] 39306 fact={256/w} 39307 39308 # Color data, as a point cloud. 39309 pointcloud3d +3d 0.5,0.5,0.5 *3d $fact circles3d {1.25*$fact} o3d {0.004*$fact} 39310 39311 # Add cube edges. 39312 colorcube3d[] 39313 l. s3d l.. s y,6 repeat $! sh[$>] 4,100%,0,0 /. 1.25 rm. done endl a y endl # Darken colors of edges 39314 p3d. 1 39315 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 39316 39317 # Add 3D axes, without the 'O'. 39318 axes3d 64,64,64,24,R,G,B,0 39319 +3d 39320 39321 # Render 3D snapshot. 39322 pose3d 1.2451,0.120715,-0.893986,-58.3864,-0.572953,1.28275,-0.62477,-11.6557,\ 39323 0.696784,0.839071,1.08374,-333.008,0,0,217,1 39324 snapshot3d {max(512,0$_preview_width,0$_preview_height)},1.22,255,255,255 39325 autocrop frame 10,10,255 39326 to_rgba flood 0,0,0,20,1,1,255,255,255,0 39327 endl done 39328 39329#@gui Retinex : fx_retinex, fx_retinex_preview(0)+ 39330#@gui : Strength (%) = float(75,0,100) 39331#@gui : Value Offset = float(16,1,256) 39332#@gui : Colorspace = choice(1,"HSI","HSV","Lab","Linear RGB","RGB","YCbCr") 39333#@gui : Min Cut (%) = float(1,0,100) 39334#@gui : Max Cut (%) = float(1,0,100) 39335#@gui : Regularization = float(5,0,32) 39336#@gui : sep = separator() 39337#@gui : Low Scale = float(15,1,512) 39338#@gui : Middle Scale = float(80,1,512) 39339#@gui : High Scale = float(250,1,512) 39340#@gui : sep = separator() 39341#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39342#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39343#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39344#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39345#@gui : sep = separator() 39346#@gui : note = note("<small><b>Note:</b> This filter implements the <i>Multiscale Color Retinex</i> algorithm, 39347#@gui : as described in:</small>") 39348#@gui : url = link{"http://www.ipol.im/pub/art/2014/107/"} 39349#@gui : sep = separator() 39350#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/13/09</i>.</small>") 39351fx_retinex : 39352 repeat $! l[$>] 39353 +retinex $2,${"arg 1+$3,hsi,hsv,lab,lrgb,rgb,ycbcr"},$4,$5,${7--1} 39354 if $6 guided. ..,$6,$6 fi 39355 j[0] .,0,0,0,0,{$1%} rm. 39356 c 0,255 39357 endl done 39358 39359fx_retinex_preview : 39360 gui_split_preview "fx_retinex $*",${-3--1} 39361 39362#@gui Retro Fade : fx_retrofade, fx_retrofade_preview 39363#@gui : Iterations = int(20,1,64) 39364#@gui : Colors = int(6,2,32) 39365#@gui : Grain = float(40,1,100) 39366#@gui : sep = separator() 39367#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39368#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39369#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39370#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39371#@gui : sep = separator() 39372#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/25/10</i>.</small>") 39373fx_retrofade : 39374 repeat $! l[$>] split_opacity l[0] 39375 +f 0 39376 repeat $1 39377 +noise[0] $3 c. 0,255 autoindex. $2,0,0 39378 +[-2,-1] 39379 progress {$>*100/$1} 39380 done 39381 k. n 0,255 39382 progress 100 39383 endl a c endl done 39384 39385fx_retrofade_preview : 39386 gui_split_preview "fx_retrofade $*",${-3--1} 39387 39388#@gui Select-Replace Color : fx_select_color, fx_select_color_preview(0) 39389#@gui : Similarity Space = choice(0,"RGB[A]","RGB","YCbCr","Red","Green","Blue","Opacity","Luminance", 39390#@gui : "Blue & Red Chrominances","Hue","Saturation") 39391#@gui : Tolerance = float(20,0,100) 39392#@gui : Smoothness = float(0,0,10) 39393#@gui : Fill Holes = int(0,0,256) 39394#@gui : Selected Color = color(255,255,255,255) 39395#@gui : Output As = choice(0,"Selected Colors","Selected Mask","Rejected Colors","Rejected Mask","Replaced Color") 39396#@gui : Replacement Color = color(255,0,0,255) 39397#@gui : sep = separator() 39398#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39399#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39400#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39401#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39402#@gui : sep = separator() 39403#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 39404_fx_select_color : 39405 if $1==1 to_rgb # RGB 39406 elif $1==2 to_rgb rgb2ycbcr # YCbCr 39407 elif $1==3 channels 0 # R 39408 elif $1==4 channels 1 # G 39409 elif $1==5 channels 2 # B 39410 elif $1==6 to_rgba channels 3 # Opacity 39411 elif $1==7 to_rgb rgb2ycbcr channels 0 # Luminance 39412 elif $1==8 to_rgb rgb2ycbcr channels 1,2 # B&R chrominances 39413 elif $1==9 to_rgb rgb2hsv channels 0 # Hue 39414 elif $1==10 to_rgb rgb2hsv channels 1 # Saturation 39415 fi 39416 39417fx_select_color : 39418 ($5^$6^$7^$8) _fx_select_color. $1 color={^} rm. 39419 repeat $! l[$>] to_rgba 39420 +_fx_select_color $1 39421 select_color[1] $2%,$color 39422 if $4 +area. 0,0 <=. {round($4^1.5)} inpaint.. .,0,3 rm. fi # Fill holes. 39423 b[1] $3 n[1] 0,255 39424 if $9==0 sh[0] 100% &. [1] # Selected colors. 39425 elif $9==1 rm[0] # Selected mask. 39426 elif $9==2 -[1] 255 *[1] -1 sh[0] 100% &. [1] # Rejected colors. 39427 elif $9==3 rm[0] - 255 * -1 # Rejected mask. 39428 else # Replaced color. 39429 /[1] 255 +*[0,1] +*[1] $11 +*[1] $12 +*[1] $13 *[1] $10 a[1,-3--1] c -[1,2] + 39430 fi 39431 k[0] 39432 endl done 39433 39434fx_select_color_preview : 39435 gui_split_preview "fx_select_color $*",${-3--1} 39436 39437#@gui Selective Desaturation : fx_selective_desaturation, fx_selective_desaturation_preview(1) 39438#@gui : Reference Color = color(255,255,255) 39439#@gui : Desaturate = choice("Reference Color","All but Reference Color") 39440#@gui : Strength = float(3,0,10) 39441#@gui : Regularization = int(0,0,20) 39442#@gui : Maximum Saturation = choice("From Input","From Reference Color","Maximum Value") 39443#@gui : sep = separator() 39444#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39445#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39446#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39447#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39448#@gui : sep = separator() 39449#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/15/07</i>.</small>") 39450fx_selective_desaturation : 39451 repeat $! l[$>] to_color split_opacity l[0] 39452 +fc $1,$2,$3 39453 -[1] [0] norm[1] /[1] {1e-6+iM} 39454 if $4 *[1] -{max(0.01,$5)} +[1] 1 39455 else >=[1] {5*$5}% 39456 fi 39457 c[1] 0,1 39458 rgb2hsl[0] s[0] c 39459 mM={[im,iM]} repeat $6 guided. [2],1,0.1 done n. $mM # Regularization step. 39460 if $7==0 *[1,-1] 39461 elif $7==1 ($1^$2^$3) rgb2hsl. *[1] {i[1]} rm[-2,-1] 39462 else rv[1,-1] rm. 39463 fi 39464 a c hsl2rgb 39465 endl a c endl done 39466 39467fx_selective_desaturation_preview : 39468 gui_split_preview "fx_selective_desaturation $*",${-3--1} 39469 39470#@gui Sepia : fx_sepia, fx_sepia_preview(1)+ 39471#@gui : Brightness (%) = float(0,-100,100) 39472#@gui : Contrast (%) = float(0,-100,100) 39473#@gui : Gamma (%) = float(0,-100,100) 39474#@gui : sep = separator() 39475#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39476#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39477#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39478#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39479#@gui : sep = separator() 39480#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 39481fx_sepia : 39482 sepia adjust_colors ${1-3},0,0,0,255 39483 39484fx_sepia_preview : 39485 gui_split_preview "fx_sepia $*",${-3--1} 39486 39487#@gui Simulate Film : fx_simulate_film, fx_simulate_film_preview(1)+ 39488#@gui : Category = choice{"Black & White (25)","Instant [Consumer] (54)","Instant [Pro] (68)","Fuji XTrans III (15)", 39489#@gui : "Negative [Color] (13)","Negative [New] (39)","Negative [Old] (44)","Print Films (12)","Slide [Color] (26)"} 39490 39491##### Black & White 39492#@gui : Preset = choice{1,"All [Collage]","None", 39493#@gui : "Agfa APX 100","Agfa APX 25","Fuji Neopan 1600","Fuji Neopan Acros 100","Ilford Delta 100", 39494#@gui : "Ilford Delta 3200","Ilford Delta 400","Ilford FP4 Plus 125","Ilford HP5 Plus 400","Ilford HPS 800", 39495#@gui : "Ilford Pan F Plus 50","Ilford XP2","Kodak BW 400 CN","Kodak HIE (HS Infra)","Kodak T-Max 100", 39496#@gui : "Kodak T-Max 3200","Kodak T-Max 400","Kodak Tri-X 400","Polaroid 664","Polaroid 667","Polaroid 672", 39497#@gui : "Rollei IR 400","Rollei Ortho 25","Rollei Retro 100 Tonal","Rollei Retro 80s"}_2 39498 39499##### Instant [Consumer] 39500#@gui : Preset = choice{1,"All [Collage]","None", 39501#@gui : "Polaroid PX-100UV+ Cold --","Polaroid PX-100UV+ Cold -","Polaroid PX-100UV+ Cold", 39502#@gui : "Polaroid PX-100UV+ Cold +","Polaroid PX-100UV+ Cold ++","Polaroid PX-100UV+ Cold +++", 39503#@gui : "Polaroid PX-100UV+ Warm --","Polaroid PX-100UV+ Warm -","Polaroid PX-100UV+ Warm", 39504#@gui : "Polaroid PX-100UV+ Warm +","Polaroid PX-100UV+ Warm ++","Polaroid PX-100UV+ Warm +++", 39505#@gui : "Polaroid PX-680 --","Polaroid PX-680 -","Polaroid PX-680","Polaroid PX-680 +","Polaroid PX-680 ++", 39506#@gui : "Polaroid PX-680 Cold --","Polaroid PX-680 Cold -","Polaroid PX-680 Cold","Polaroid PX-680 Cold +", 39507#@gui : "Polaroid PX-680 Cold ++","Polaroid PX-680 Cold ++a","Polaroid PX-680 Warm --","Polaroid PX-680 Warm -", 39508#@gui : "Polaroid PX-680 Warm","Polaroid PX-680 Warm +","Polaroid PX-680 Warm ++","Polaroid PX-70 --", 39509#@gui : "Polaroid PX-70 -","Polaroid PX-70","Polaroid PX-70 +","Polaroid PX-70 ++","Polaroid PX-70 +++", 39510#@gui : "Polaroid PX-70 Cold --","Polaroid PX-70 Cold -","Polaroid PX-70 Cold","Polaroid PX-70 Cold +", 39511#@gui : "Polaroid PX-70 Cold ++","Polaroid PX-70 Warm --","Polaroid PX-70 Warm -","Polaroid PX-70 Warm", 39512#@gui : "Polaroid PX-70 Warm +","Polaroid PX-70 Warm ++","Polaroid Time Zero (Expired) ---", 39513#@gui : "Polaroid Time Zero (Expired) --","Polaroid Time Zero (Expired) -","Polaroid Time Zero (Expired)", 39514#@gui : "Polaroid Time Zero (Expired) +","Polaroid Time Zero (Expired) ++","Polaroid Time Zero (Expired) Cold ---", 39515#@gui : "Polaroid Time Zero (Expired) Cold --","Polaroid Time Zero (Expired) Cold -", 39516#@gui : "Polaroid Time Zero (Expired) Cold"}_0 39517 39518##### Instant [Pro] 39519#@gui : Preset = choice{1,"All [Collage]","None", 39520#@gui : "Fuji FP-100c --","Fuji FP-100c -","Fuji FP-100c","Fuji FP-100c (alt)","Fuji FP-100c +","Fuji FP-100c ++", 39521#@gui : "Fuji FP-100c ++a","Fuji FP-100c +++", 39522#@gui : "Fuji FP-100c Cool --","Fuji FP-100c Cool -","Fuji FP-100c Cool","Fuji FP-100c Cool +","Fuji FP-100c Cool ++", 39523#@gui : "Fuji FP-100c Negative --","Fuji FP-100c Negative -","Fuji FP-100c Negative","Fuji FP-100c Negative +", 39524#@gui : "Fuji FP-100c Negative ++","Fuji FP-100c Negative ++a","Fuji FP-100c Negative +++", 39525#@gui : "Fuji FP-3000b --","Fuji FP-3000b -","Fuji FP-3000b","Fuji FP-3000b +","Fuji FP-3000b ++","Fuji FP-3000b +++", 39526#@gui : "Fuji FP-3000b HC","Fuji FP-3000b Negative --","Fuji FP-3000b Negative -","Fuji FP-3000b Negative", 39527#@gui : "Fuji FP-3000b Negative +","Fuji FP-3000b Negative ++","Fuji FP-3000b Negative +++", 39528#@gui : "Fuji FP-3000b Negative Early","Polaroid 665 --","Polaroid 665 -","Polaroid 665","Polaroid 665 +", 39529#@gui : "Polaroid 665 ++","Polaroid 665 Negative -","Polaroid 665 Negative","Polaroid 665 Negative +", 39530#@gui : "Polaroid 665 Negative HC","Polaroid 669 --","Polaroid 669 -","Polaroid 669","Polaroid 669 +", 39531#@gui : "Polaroid 669 ++","Polaroid 669 +++","Polaroid 669 Cold --","Polaroid 669 Cold -","Polaroid 669 Cold", 39532#@gui : "Polaroid 669 Cold +","Polaroid 690 --","Polaroid 690 -","Polaroid 690","Polaroid 690 +","Polaroid 690 ++", 39533#@gui : "Polaroid 690 Cold --","Polaroid 690 Cold -","Polaroid 690 Cold","Polaroid 690 Cold +","Polaroid 690 Cold ++", 39534#@gui : "Polaroid 690 Warm --","Polaroid 690 Warm -","Polaroid 690 Warm","Polaroid 690 Warm +","Polaroid 690 Warm ++"}_0 39535 39536#### Fuji XTrans III 39537#@gui : Preset = choice{1,"All [Collage]","None", 39538#@gui : "Acros","Acros+G","Acros+R","Acros+Ye","Astia","Classic Chrome","Mono","Mono+G","Mono+R","Mono+Ye", 39539#@gui : "Pro Neg Hi","Pro Neg Std","Provia","Sepia","Velvia"}_0 39540 39541##### Negative [Color] 39542#@gui : Preset = choice{1,"All [Collage]","None", 39543#@gui : "Agfa Ultra Color 100","Agfa Vista 200","Fuji Superia 200","Fuji Superia HG 1600","Fuji Superia Reala 100", 39544#@gui : "Fuji Superia X-Tra 800","Kodak Ektar 100","Kodak Elite 100 XPRO","Kodak Elite Color 200", 39545#@gui : "Kodak Elite Color 400","Kodak Portra 160 NC","Kodak Portra 160 VC","Lomography Redscale 100"}_0 39546 39547##### Negative [New] 39548#@gui : Preset = choice{1,"All [Collage]","None", 39549#@gui : "Fuji 160C -","Fuji 160C","Fuji 160C +","Fuji 160C ++", 39550#@gui : "Fuji 400H -","Fuji 400H","Fuji 400H +","Fuji 400H ++", 39551#@gui : "Fuji 800Z -","Fuji 800Z","Fuji 800Z +","Fuji 800Z ++", 39552#@gui : "Fuji Ilford HP5 -","Fuji Ilford HP5","Fuji Ilford HP5 +","Fuji Ilford HP5 ++", 39553#@gui : "Kodak Portra 160 -","Kodak Portra 160","Kodak Portra 160 +","Kodak Portra 160 ++", 39554#@gui : "Kodak Portra 400 -","Kodak Portra 400","Kodak Portra 400 +","Kodak Portra 400 ++", 39555#@gui : "Kodak Portra 800 -","Kodak Portra 800","Kodak Portra 800 +","Kodak Portra 800 ++","Kodak Portra 800 HC", 39556#@gui : "Kodak T-MAX 3200 -","Kodak T-MAX 3200","Kodak T-MAX 3200 +","Kodak T-MAX 3200 ++","Kodak T-MAX 3200 (alt)", 39557#@gui : "Kodak TRI-X 400 -","Kodak TRI-X 400","Kodak TRI-X 400 +","Kodak TRI-X 400 ++","Kodak TRI-X 400 (alt)"}_0 39558 39559##### Negative [Old] 39560#@gui : Preset = choice{1,"All [Collage]","None", 39561#@gui : "Fuji Ilford Delta 3200 -","Fuji Ilford Delta 3200","Fuji Ilford Delta 3200 +","Fuji Ilford Delta 3200 ++", 39562#@gui : "Fuji Neopan 1600 -","Fuji Neopan 1600","Fuji Neopan 1600 +","Fuji Neopan 1600 ++", 39563#@gui : "Fuji Superia 100 -","Fuji Superia 100","Fuji Superia 100 +","Fuji Superia 100 ++", 39564#@gui : "Fuji Superia 400 -","Fuji Superia 400","Fuji Superia 400 +","Fuji Superia 400 ++", 39565#@gui : "Fuji Superia 800 -","Fuji Superia 800","Fuji Superia 800 +","Fuji Superia 800 ++", 39566#@gui : "Fuji Superia 1600 -","Fuji Superia 1600","Fuji Superia 1600 +","Fuji Superia 1600 ++", 39567#@gui : "Kodak Portra 160 NC -","Kodak Portra 160 NC","Kodak Portra 160 NC +","Kodak Portra 160 NC ++", 39568#@gui : "Kodak Portra 160 VC -","Kodak Portra 160 VC","Kodak Portra 160 VC +","Kodak Portra 160 VC ++", 39569#@gui : "Kodak Portra 400 NC -","Kodak Portra 400 NC","Kodak Portra 400 NC +","Kodak Portra 400 NC ++", 39570#@gui : "Kodak Portra 400 UC -","Kodak Portra 400 UC","Kodak Portra 400 UC +","Kodak Portra 400 UC ++", 39571#@gui : "Kodak Portra 400 VC -","Kodak Portra 400 VC","Kodak Portra 400 VC +","Kodak Portra 400 VC ++"}_0 39572 39573##### Print Films 39574#@gui : Preset = choice{1,"All [Collage]","None", 39575#@gui : "Fuji 3510 (Constlclip)","Fuji 3510 (Constlmap)","Fuji 3510 (Cuspclip)", 39576#@gui : "Fuji 3513 (Constlclip)","Fuji 3513 (Constlmap)","Fuji 3513 (Cuspclip)", 39577#@gui : "Kodak 2383 (Constlclip)","Kodak 2383 (Constlmap)","Kodak 2383 (Cuspclip)", 39578#@gui : "Kodak 2393 (Constlclip)","Kodak 2393 (Constlmap)","Kodak 2393 (Cuspclip)"}_0 39579 39580#### Slide [Color] 39581#@gui : Preset = choice{1,"All [Collage]","None", 39582#@gui : "Agfa Precisa 100","Fuji Astia 100F","Fuji FP 100C","Fuji Provia 100F","Fuji Provia 400F","Fuji Provia 400X", 39583#@gui : "Fuji Sensia 100","Fuji Superia 200 XPRO","Fuji Velvia 50","Generic Fuji Astia 100","Generic Fuji Provia 100", 39584#@gui : "Generic Fuji Velvia 100","Generic Kodachrome 64","Generic Kodak Ektachrome 100 VS", 39585#@gui : "Kodak E-100 GX Ektachrome 100","Kodak Ektachrome 100 VS","Kodak Elite Chrome 200","Kodak Elite Chrome 400", 39586#@gui : "Kodak Elite ExtraColor 100","Kodak Kodachrome 200","Kodak Kodachrome 25","Kodak Kodachrome 64", 39587#@gui : "Lomography X-Pro Slide 200", 39588#@gui : "Polaroid 669","Polaroid 690","Polaroid Polachrome"}_0 39589 39590#@gui : Thumbnail Size = int(512,0,1024)_1 39591#@gui : sep = separator() 39592#@gui : Strength (%) = float(100,0,100) 39593#@gui : Brightness (%) = float(0,-100,100) 39594#@gui : Contrast (%) = float(0,-100,100) 39595#@gui : Gamma (%) = float(0,-100,100) 39596#@gui : Hue (%) = float(0,-100,100) 39597#@gui : Saturation (%) = float(0,-100,100) 39598#@gui : Normalize Colors = choice("None","Pre-Normalize","Post-Normalize","Both") 39599#@gui : sep = separator() 39600#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39601#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39602#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39603#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39604#@gui : sep = separator() 39605#@gui : note = note("<small><b>Note:</b> The color LUTs proposed in this filter come from 39606#@gui : various free sources :</small>") 39607#@gui : note = note{"<small><b>*</b> 39608#@gui : <a href="https://rawpedia.rawtherapee.com/Film_Simulation">RawTherapee Film Simulation</a>.</small>"} 39609#@gui : note = note{"<small><b>*</b> 39610#@gui : <a href="https://patdavid.net/2013/08/film-emulation-presets-in-gmic-gimp.html">Pat David Film Emulation</a>. 39611#@gui : </small>"} 39612#@gui : note = note{"<small><b>*</b> 39613#@gui : <a href="http://blog.sowerby.me/fuji-film-simulation-profiles">Fuji Film Simulation Profiles</a>.</small>"} 39614#@gui : note = note{"<small><b>*</b> 39615#@gui : <a href="http://juanmelara.com.au/print-film-emulation-luts-for-download/">Print Film LUTs For Download</a>. 39616#@gui : </small>"} 39617#@gui : sep = separator() 39618#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/02/27</i>.</small>") 39619fx_simulate_film : 39620 category=${arg\ 1+$1,bw,instant_consumer,instant_pro,fujixtransiii,negative_color,negative_new,negative_old,\ 39621 print,colorslide} 39622 presets=${-_fx_cluts_$category} 39623 index={arg(1+$1,${2-10})} 39624 thumbsize,strength,brightness,contrast,gamma,hue,saturation,normalize=${11-18} 39625 if $normalize==1" || "$normalize==3 # Pre-normalization 39626 repeat $! l[$>] split_opacity balance_gamma[0] , a c endl done 39627 fi 39628 if $index>=2 # Apply CLUT 39629 path_clut=${-path_cache} 39630 name=${arg\ 1+$index-2,$presets} 39631 clut $name,{0$_is_preview" && "!isfile(['{/${path_clut}clut_$name.cimgz}'])?17:48} 39632 repeat $!-1 if $strength<100 +map_clut[$>] . j[$>] .,0,0,0,0,{$strength%} rm. else map_clut[$>] . fi done 39633 rm. 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 elif $index==1 # "None" 39638 adjust_colors $brightness,$contrast,$gamma,$hue,$saturation,0,255 39639 if $normalize==2" || "$normalize==3 repeat $! l[$>] split_opacity n[0] 0,255 a c endl done fi # Post-normalization 39640 39641 else # Collage 39642 repeat $! l[$>] if max(w,h)>$thumbsize rr2d $thumbsize,$thumbsize,0,2 fi endl done 39643 N=$! +to "Original",1%,1%,7.5%,2,0.5 39644 Np={narg($presets)} repeat $Np 39645 clut_name=${arg\ 1+$>,$presets} 39646 clut $clut_name mv. $N 39647 repeat $N 39648 if $strength<100 [$>] +map_clut. [$N] j.. .,0,0,0,0,{$strength%} rm. else +map_clut[$>] [$N] fi 39649 adjust_colors. $brightness,$contrast,$gamma,$hue,$saturation,0,255 39650 if $normalize==2" || "$normalize==3 l. split_opacity n[0] 0,255 a c endl fi # Post-normalization 39651 strcapitalize $clut_name clut_name=${} 39652 to. $clut_name,1%,1%,7.5%,2,0.5 39653 done 39654 rm[$N] 39655 progress {$>*100/($Np-1)} 39656 done 39657 k[$N--1] frame 1,1,0,0,0,255 - 128 append_tiles {s=floor(sqrt($!));w>h?[s,0]:[0,s]} + 128 39658 fi 39659 39660fx_simulate_film_preview : 39661 _is_preview=1 39662 index={arg(1+$1,${2-10})} 39663 if !$index gui_warning_preview "Preview disabled in 'Collage' mode" 39664 else gui_split_preview "fx_simulate_film $*",${19-21} 39665 fi 39666 u "{$1}{$2}_"{2*($1==0)}\ 39667 "{$3}_"{2*($1==1)}\ 39668 "{$4}_"{2*($1==2)}\ 39669 "{$5}_"{2*($1==3)}\ 39670 "{$6}_"{2*($1==4)}\ 39671 "{$7}_"{2*($1==5)}\ 39672 "{$8}_"{2*($1==6)}\ 39673 "{$9}_"{2*($1==7)}\ 39674 "{$10}_"{2*($1==8)}\ 39675 "{$11}_"{1+!$index}\ 39676 "{$12}{$13}{$14}{$15}{$16}{$17}{$18}{$19}{$20,$21}" 39677 39678_fx_cluts_bw : 39679 u agfa_apx_100,agfa_apx_25,fuji_neopan_1600,fuji_neopan_acros_100,ilford_delta_100,ilford_delta_3200,\ 39680 ilford_delta_400,ilford_fp_4_plus_125,\ 39681 ilford_hp_5_plus_400,ilford_hps_800,ilford_pan_f_plus_50,ilford_xp_2,kodak_bw_400_cn,kodak_hie_hs_infra,\ 39682 kodak_t-max_100,kodak_t-max_3200,\ 39683 kodak_t-max_400,kodak_tri-x_400,polaroid_664,polaroid_667,polaroid_672,rollei_ir_400,rollei_ortho_25,\ 39684 rollei_retro_100_tonal,rollei_retro_80s 39685 39686_fx_cluts_instant_consumer : 39687 u polaroid_px-100uv+_cold_--,polaroid_px-100uv+_cold_-,polaroid_px-100uv+_cold,polaroid_px-100uv+_cold_+,\ 39688 polaroid_px-100uv+_cold_++,polaroid_px-100uv+_cold_+++,\ 39689 polaroid_px-100uv+_warm_--,polaroid_px-100uv+_warm_-,polaroid_px-100uv+_warm,polaroid_px-100uv+_warm_+,\ 39690 polaroid_px-100uv+_warm_++,polaroid_px-100uv+_warm_+++,\ 39691 polaroid_px-680_--,polaroid_px-680_-,polaroid_px-680,polaroid_px-680_+,polaroid_px-680_++,\ 39692 polaroid_px-680_cold_--,polaroid_px-680_cold_-,polaroid_px-680_cold,polaroid_px-680_cold_+,\ 39693 polaroid_px-680_cold_++,polaroid_px-680_cold_++_alt,\ 39694 polaroid_px-680_warm_--,polaroid_px-680_warm_-,polaroid_px-680_warm,polaroid_px-680_warm_+,polaroid_px-680_warm_++,\ 39695 polaroid_px-70_--,polaroid_px-70_-,polaroid_px-70,polaroid_px-70_+,polaroid_px-70_++,polaroid_px-70_+++,\ 39696 polaroid_px-70_cold_--,polaroid_px-70_cold_-,polaroid_px-70_cold,polaroid_px-70_cold_+,polaroid_px-70_cold_++,\ 39697 polaroid_px-70_warm_--,polaroid_px-70_warm_-,polaroid_px-70_warm,polaroid_px-70_warm_+,polaroid_px-70_warm_++,\ 39698 polaroid_time_zero_expired_---,polaroid_time_zero_expired_--,polaroid_time_zero_expired_-,\ 39699 polaroid_time_zero_expired,polaroid_time_zero_expired_+,polaroid_time_zero_expired_++,\ 39700 polaroid_time_zero_expired_cold_---,polaroid_time_zero_expired_cold_--,polaroid_time_zero_expired_cold_-,\ 39701 polaroid_time_zero_expired_cold 39702 39703_fx_cluts_instant_pro : 39704 u fuji_fp-100c_--,fuji_fp-100c_-,fuji_fp-100c,fuji_fp-100c_alt,fuji_fp-100c_+,fuji_fp-100c_++,fuji_fp-100c_++_alt,\ 39705 fuji_fp-100c_+++,\ 39706 fuji_fp-100c_cool_--,fuji_fp-100c_cool_-,fuji_fp-100c_cool,fuji_fp-100c_cool_+,fuji_fp-100c_cool_++,\ 39707 fuji_fp-100c_negative_--,fuji_fp-100c_negative_-,fuji_fp-100c_negative,fuji_fp-100c_negative_+,\ 39708 fuji_fp-100c_negative_++,fuji_fp-100c_negative_++_alt,fuji_fp-100c_negative_+++,\ 39709 fuji_fp-3000b_--,fuji_fp-3000b_-,fuji_fp-3000b,fuji_fp-3000b_+,fuji_fp-3000b_++,fuji_fp-3000b_+++,fuji_fp-3000b_hc,\ 39710 fuji_fp-3000b_negative_--,fuji_fp-3000b_negative_-,fuji_fp-3000b_negative,fuji_fp-3000b_negative_+,\ 39711 fuji_fp-3000b_negative_++,fuji_fp-3000b_negative_+++,fuji_fp-3000b_negative_early,\ 39712 polaroid_665_--,polaroid_665_-,polaroid_665,polaroid_665_+,polaroid_665_++,\ 39713 polaroid_665_negative_-,polaroid_665_negative,polaroid_665_negative_+,polaroid_665_negative_hc,\ 39714 polaroid_669_--,polaroid_669_-,polaroid_669,polaroid_669_+,polaroid_669_++,polaroid_669_+++,\ 39715 polaroid_669_cold_--,polaroid_669_cold_-,polaroid_669_cold,polaroid_669_cold_+,\ 39716 polaroid_690_--,polaroid_690_-,polaroid_690,polaroid_690_+,polaroid_690_++,\ 39717 polaroid_690_cold_--,polaroid_690_cold_-,polaroid_690_cold,polaroid_690_cold_+,polaroid_690_cold_++,\ 39718 polaroid_690_warm_--,polaroid_690_warm_-,polaroid_690_warm,polaroid_690_warm_+,polaroid_690_warm_++ 39719 39720_fx_cluts_fujixtransiii : 39721 u fuji_xtrans_iii_acros,fuji_xtrans_iii_acros+g,fuji_xtrans_iii_acros+r,fuji_xtrans_iii_acros+ye,\ 39722 fuji_xtrans_iii_astia,\ 39723 fuji_xtrans_iii_classic_chrome,fuji_xtrans_iii_mono,fuji_xtrans_iii_mono+g,fuji_xtrans_iii_mono+r,\ 39724 fuji_xtrans_iii_mono+ye,\ 39725 fuji_xtrans_iii_pro_neg_hi,fuji_xtrans_iii_pro_neg_std,fuji_xtrans_iii_provia,fuji_xtrans_iii_sepia,\ 39726 fuji_xtrans_iii_velvia 39727 39728_fx_cluts_negative_color : 39729 u agfa_ultra_color_100,agfa_vista_200,fuji_superia_200,fuji_superia_hg_1600,fuji_superia_reala_100,\ 39730 fuji_superia_x-tra_800,kodak_ektar_100,\ 39731 kodak_elite_100_xpro,kodak_elite_color_200,kodak_elite_color_400,kodak_portra_160_nc,kodak_portra_160_vc,\ 39732 lomography_redscale_100 39733 39734_fx_cluts_negative_new : 39735 u fuji_160c_-,fuji_160c,fuji_160c_+,fuji_160c_++,\ 39736 fuji_400h_-,fuji_400h,fuji_400h_+,fuji_400h_++,\ 39737 fuji_800z_-,fuji_800z,fuji_800z_+,fuji_800z_++,\ 39738 ilford_hp_5_-,ilford_hp_5,ilford_hp_5_+,ilford_hp_5_++,\ 39739 kodak_portra_160_-,kodak_portra_160,kodak_portra_160_+,kodak_portra_160_++,\ 39740 kodak_portra_400_-,kodak_portra_400,kodak_portra_400_+,kodak_portra_400_++,\ 39741 kodak_portra_800_-,kodak_portra_800,kodak_portra_800_+,kodak_portra_800_++,kodak_portra_800_hc,\ 39742 kodak_tmax_3200_-,kodak_tmax_3200,kodak_tmax_3200_+,kodak_tmax_3200_++,kodak_tmax_3200_alt,\ 39743 kodak_tri-x_400_-,kodak_tri-x_400,kodak_tri-x_400_+,kodak_tri-x_400_++,kodak_tri-x_400_alt 39744 39745_fx_cluts_negative_old : 39746 u ilford_delta_3200_-,ilford_delta_3200,ilford_delta_3200_+,ilford_delta_3200_++,\ 39747 fuji_neopan_1600_-,fuji_neopan_1600,fuji_neopan_1600_+,fuji_neopan_1600_++,\ 39748 fuji_superia_100_-,fuji_superia_100,fuji_superia_100_+,fuji_superia_100_++,\ 39749 fuji_superia_400_-,fuji_superia_400,fuji_superia_400_+,fuji_superia_400_++,\ 39750 fuji_superia_800_-,fuji_superia_800,fuji_superia_800_+,fuji_superia_800_++,\ 39751 fuji_superia_1600_-,fuji_superia_1600,fuji_superia_1600_+,fuji_superia_1600_++,\ 39752 kodak_portra_160_nc_-,kodak_portra_160_nc,kodak_portra_160_nc_+,kodak_portra_160_nc_++,\ 39753 kodak_portra_160_vc_-,kodak_portra_160_vc,kodak_portra_160_vc_+,kodak_portra_160_vc_++,\ 39754 kodak_portra_400_nc_-,kodak_portra_400_nc,kodak_portra_400_nc_+,kodak_portra_400_nc_++,\ 39755 kodak_portra_400_uc_-,kodak_portra_400_uc,kodak_portra_400_uc_+,kodak_portra_400_uc_++,\ 39756 kodak_portra_400_vc_-,kodak_portra_400_vc,kodak_portra_400_vc_+,kodak_portra_400_vc_++ 39757 39758_fx_cluts_print : 39759 u fuji_3510_constlclip,fuji_3510_constlmap,fuji_3510_cuspclip,\ 39760 fuji_3513_constlclip,fuji_3513_constlmap,fuji_3513_cuspclip,\ 39761 kodak_2383_constlclip,kodak_2383_constlmap,kodak_2383_cuspclip,\ 39762 kodak_2393_constlclip,kodak_2393_constlmap,kodak_2393_cuspclip 39763 39764_fx_cluts_colorslide : 39765 u agfa_precisa_100,fuji_astia_100f,fuji_fp_100c,fuji_provia_100f,fuji_provia_400f,fuji_provia_400x,fuji_sensia_100,\ 39766 fuji_superia_200_xpro,fuji_velvia_50,fuji_astia_100_generic,fuji_provia_100_generic,fuji_velvia_100_generic,\ 39767 kodak_kodachrome_64_generic,kodak_ektachrome_100_vs_generic,kodak_e-100_gx_ektachrome_100,kodak_ektachrome_100_vs,\ 39768 kodak_elite_chrome_200,\ 39769 kodak_elite_chrome_400,kodak_elite_extracolor_100,kodak_kodachrome_200,kodak_kodachrome_25,kodak_kodachrome_64,\ 39770 lomography_x-pro_slide_200,\ 39771 polaroid_669,polaroid_690,polaroid_polachrome 39772 39773#@gui Transfer Colors [Variational] : fx_transfer_rgb, fx_transfer_rgb_preview(1)+ : * 39774#@gui : Regularization = int(8,0,32) 39775#@gui : Preserve Luminance = float(0.2,0,1) 39776#@gui : Precision = _choice(1,"Low","Normal","High","Very High") 39777#@gui : Reference Colors = choice("Bottom Layer","Top Layer") 39778#@gui : Add User-Defined Constraints (Interactive) = _bool(0) 39779#@gui : sep = separator() 39780#@gui : Preview_ref_point = point(1,1,0,0,255,255,255,128,4)_0 39781#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39782#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39783#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39784#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39785#@gui : sep = separator() 39786#@gui : note = note{"<small><b>Instructions:</b>\n 39787#@gui : - This filter transfers the colors of one layer to all the others.\n 39788#@gui : - Don't forget to set the <i>Input layers...</i> option on the left to manage your input layers.\n 39789#@gui : </small>"} 39790#@gui : sep = separator() 39791#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/04/04</i>.</small>") 39792fx_transfer_rgb : 39793 to_rgb 39794 ref={$4?0:-1} 39795 transfer_rgb[^$ref] [$ref],0.25,$1,$2,{2^(4+$3)},$5,0 39796 c 0,255 39797 39798fx_transfer_rgb_preview : 39799 if $!<2 gui_print_preview "Warning:",,"This filter requires at least two input layers to work properly." return fi 39800 ref={$4?0:-1} 39801 +store[$ref] _fx_trgb_ref 39802 gui_split_preview[^$ref] "$_fx_trgb_ref fx_transfer_rgb $1,$2,0,0,0 rm.",${-3--1} 39803 _fx_trgb_ref= 39804 39805 mv[$ref] $! 39806 repeat $!-1 l[$>,-1] 39807 rr2d[0] $_preview_width,$_preview_height,0,3 rr2d. {0,[w,h]/3},0,3 39808 to. Reference,2,2,13,1,1,255 frame. 2,2,255 frame. 1,1,0 39809 j[0] .,$6%,$7% 39810 rm. 39811 endl done 39812 39813#@gui Transfer Colors [Histogram] : fx_transfer_histogram, fx_transfer_histogram_preview(1)+ : * 39814#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 39815#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 39816#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 39817#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 39818#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 39819#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 39820#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 39821#@gui : Reference Colors = choice("Bottom Layer","Top Layer") 39822#@gui : sep = separator() 39823#@gui : Preview_ref_point = point(1,1,0,0,255,255,255,128,4)_0 39824#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39825#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39826#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39827#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39828#@gui : sep = separator() 39829#@gui : note = note{"<small><b>Note: </b> 39830#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 39831#@gui : multiple input layers. 39832#@gui : </small>"} 39833#@gui : sep = separator() 39834#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/01/13</i>.</small>") 39835fx_transfer_histogram : 39836 to_rgb 39837 ref={$2?0:-1} 39838 transfer_histogram[^$ref] [$ref],256,$1 39839 c 0,255 39840 39841fx_transfer_histogram_preview : 39842 if $!<2 gui_print_preview "Warning:",,"This filter requires at least two input layers to work properly." return fi 39843 ref={$2?0:-1} 39844 +store[$ref] _fx_trgb_ref 39845 gui_split_preview[^$ref] "$_fx_trgb_ref fx_transfer_histogram $1,0 rm.",${-3--1} 39846 _fx_trgb_ref= 39847 39848 mv[$ref] $! 39849 repeat $!-1 l[$>,-1] 39850 rr2d[0] $_preview_width,$_preview_height,0,3 rr2d. {0,[w,h]/3},0,3 39851 to. Reference,2,2,13,1,1,255 frame. 2,2,255 frame. 1,1,0 39852 j[0] .,$3%,$4% 39853 rm. 39854 endl done 39855 39856#@gui Transfer Colors [PCA] : fx_transfer_pca, fx_transfer_pca_preview(1)+ : * 39857#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 39858#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 39859#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 39860#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 39861#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 39862#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 39863#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 39864#@gui : Reference Colors = choice("Bottom Layer","Top Layer") 39865#@gui : sep = separator() 39866#@gui : Preview_ref_point = point(1,1,0,0,255,255,255,128,4)_0 39867#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39868#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39869#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39870#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39871#@gui : sep = separator() 39872#@gui : note = note{"<small><b>Note: </b> 39873#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 39874#@gui : multiple input layers. 39875#@gui : </small>"} 39876#@gui : sep = separator() 39877#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/01/13</i>.</small>") 39878fx_transfer_pca : 39879 to_rgb 39880 ref={$2?0:-1} 39881 transfer_pca[^$ref] [$ref],$1 39882 c 0,255 39883 39884fx_transfer_pca_preview : 39885 if $!<2 gui_print_preview "Warning:",,"This filter requires at least two input layers to work properly." return fi 39886 ref={$2?0:-1} 39887 +store[$ref] _fx_trgb_ref 39888 gui_split_preview[^$ref] "$_fx_trgb_ref fx_transfer_pca $1,0 rm.",${-3--1} 39889 _fx_trgb_ref= 39890 39891 mv[$ref] $! 39892 repeat $!-1 l[$>,-1] 39893 rr2d[0] $_preview_width,$_preview_height,0,3 rr2d. {0,[w,h]/3},0,3 39894 to. Reference,2,2,13,1,1,255 frame. 2,2,255 frame. 1,1,0 39895 j[0] .,$3%,$4% 39896 rm. 39897 endl done 39898 39899#@gui Tune HSV Colors : fx_tune_hsv, fx_tune_hsv_preview(1) 39900#@gui : Dark = choice(2,"Ignore","Lock","Remap") 39901#@gui : Dark Color = color(0,0,0) 39902#@gui : Target Hue (%) = float(100,0,100) 39903#@gui : Target Saturation (%) = float(100,0,100) 39904#@gui : Target Value (%) = float(100,0,100) 39905#@gui : sep = separator() 39906#@gui : Light = choice(2,"Ignore","Lock","Remap") 39907#@gui : Light Color = color(255,255,255) 39908#@gui : Target Hue (%) = float(100,0,100) 39909#@gui : Target Saturation (%) = float(100,0,100) 39910#@gui : Target Value (%) = float(100,0,100) 39911#@gui : sep = separator() 39912#@gui : Average = choice(1,"Ignore","Lock","Remap") 39913#@gui : Average Color = color(128,128,128)_0 39914#@gui : Target Hue (%) = float(0,0,100)_0 39915#@gui : Target Saturation (%) = float(50,0,100)_0 39916#@gui : Target Value (%) = float(100,0,100)_0 39917#@gui : sep = separator() 39918#@gui : Red = choice("Ignore","Lock","Remap") 39919#@gui : Red Color = color(255,0,0)_0 39920#@gui : Target Hue (%) = float(100,0,100)_0 39921#@gui : Target Saturation (%) = float(12.5,0,100)_0 39922#@gui : Target Value (%) = float(0,0,100)_0 39923#@gui : sep = separator() 39924#@gui : Yellow = choice("Ignore","Lock","Remap") 39925#@gui : Yellow Color = color(255,255,0)_0 39926#@gui : Target Hue (%) = float(100,0,100)_0 39927#@gui : Target Saturation (%) = float(12.5,0,100)_0 39928#@gui : Target Value (%) = float(0,0,100)_0 39929#@gui : sep = separator() 39930#@gui : Green = choice("Ignore","Lock","Remap") 39931#@gui : Green Color = color(0,255,0)_0 39932#@gui : Target Hue (%) = float(100,0,100)_0 39933#@gui : Target Saturation (%) = float(12.5,0,100)_0 39934#@gui : Target Value (%) = float(0,0,100)_0 39935#@gui : sep = separator() 39936#@gui : Cyan = choice("Ignore","Lock","Remap") 39937#@gui : Cyan Color = color(0,255,255)_0 39938#@gui : Target Hue (%) = float(100,0,100)_0 39939#@gui : Target Saturation (%) = float(12.5,0,100)_0 39940#@gui : Target Value (%) = float(0,0,100)_0 39941#@gui : sep = separator() 39942#@gui : Blue = choice("Ignore","Lock","Remap") 39943#@gui : Blue Color = color(0,0,255)_0 39944#@gui : Target Hue (%) = float(100,0,100)_0 39945#@gui : Target Saturation (%) = float(12.5,0,100)_0 39946#@gui : Target Value (%) = float(0,0,100)_0 39947#@gui : sep = separator() 39948#@gui : Magenta = choice("Ignore","Lock","Remap") 39949#@gui : Magenta Color = color(255,0,255)_0 39950#@gui : Target Hue (%) = float(100,0,100)_0 39951#@gui : Target Saturation (%) = float(12.5,0,100)_0 39952#@gui : Target Value (%) = float(0,0,100)_0 39953#@gui : sep = separator() 39954#@gui : Preview color mapping = choice(2,"None","Center","Top Left","Top Right","Bottom Left","Bottom Right") 39955#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 39956#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 39957#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 39958#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 39959#@gui : sep = separator() 39960#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/12/17</i>.</small>") 39961_fx_tune_hsv : 39962 mode_dark,Rdark,Gdark,Bdark,Hdark,Sdark,Vdark,\ 39963 mode_light,Rlight,Glight,Blight,Hlight,Slight,Vlight,\ 39964 mode_avg,Ravg,Gavg,Bavg,Havg,Savg,Vavg,\ 39965 mode_red,Rred,Gred,Bred,Hred,Sred,Vred,\ 39966 mode_yellow,Ryellow,Gyellow,Byellow,Hyellow,Syellow,Vyellow,\ 39967 mode_green,Rgreen,Ggreen,Bgreen,Hgreen,Sgreen,Vgreen,\ 39968 mode_cyan,Rcyan,Gcyan,Bcyan,Hcyan,Scyan,Vcyan,\ 39969 mode_blue,Rblue,Gblue,Bblue,Hblue,Sblue,Vblue,\ 39970 mode_magenta,Rmagenta,Gmagenta,Bmagenta,Hmagenta,Smagenta,Vmagenta,\ 39971 preview_mapping=${1-64} 39972 all_colors=dark,light,avg,red,yellow,green,cyan,blue,magenta 39973 39974 repeat $! l[$>] split_opacity l[0] 39975 to_rgb 39976 39977 # Define list of considered colors. 39978 colors,sep= 39979 repeat narg($all_colors) color=${arg\ 1+$>,$all_colors} if ${mode_$color} colors.=$sep$color sep=, fi done 39980 39981 # Find darkest, lightest and average colors. 39982 +srgb2lab channels. 0 darklight={"[I(#-2,xm,ym),I(#-2,xM,yM)]"} rm. 39983 dark={[$darklight][0,3]} light={[$darklight][3,3]} 39984 +r. 1,1,1,3,2 avg={^} rm. 39985 39986 # Find the nearest existing colors to "pure" colors. 39987 eval. "> 39988 begin( 39989 red = yellow = green = cyan = blue = magenta = [0,0,0]; 39990 best_red = best_yellow = best_green = best_cyan = best_blue = best_magenta = inf; 39991 test_color(color,tR,tG,tB) = ( 39992 val = norm([tR,tG,tB]-[R,G,B]); 39993 val<best_#color?(best_#color = val; color# = I(#-2)); 39994 ); 39995 ); 39996 test_color(red,255,0,0); 39997 test_color(yellow,255,255,0); 39998 test_color(green,0,255,0); 39999 test_color(cyan,0,255,255); 40000 test_color(blue,0,0,255); 40001 test_color(magenta,255,0,255); 40002 end( 40003 run(' red=',vtos(red), 40004 ' yellow=',vtos(yellow), 40005 ' green=',vtos(green), 40006 ' cyan=',vtos(cyan), 40007 ' blue=',vtos(blue), 40008 ' magenta=',vtos(magenta)) 40009 ); I" 40010 40011 # Compute color mapping. 40012 if narg($colors) 40013 l[] 40014 40015 # Define color correspondences. 40016 repeat narg($colors) 40017 color=${arg\ 1+$>,$colors} 40018 if ${mode_$color}==2 (${$color},${R$color},${G$color},${B$color},${H$color},${S$color},${V$color}) 40019 else (${$color},${$color},0,0,0) 40020 fi 40021 done 40022 a y permute yzcx 40023 s c,-3 srgb2rgb[0,1] rgb2hsv[0,1] /. 100 40024 f.. " 40025 Hs = i(#0,x,0,0,0); Ss = i(#0,x,0,0,1); Vs = i(#0,x,0,0,2); 40026 Hd = i0; Sd = i1; Vd = i2; 40027 DeltaH = Hd - Hs; 40028 alphaH = i(#2,x,0,0,0); 40029 H = abs(DeltaH)<abs(DeltaH - 360)? 40030 lerp(Hs,Hd,alphaH): 40031 lerp(Hs,Hd - 360,alphaH)%360; 40032 S = lerp(Ss,Sd,i(#2,x,0,0,1)); 40033 V = lerp(Vs,Vd,i(#2,x,0,0,2)); 40034 [ H,S,V ]" 40035 rm. 40036 hsv2rgb rgb2srgb 40037 repeat w color=${arg\ 1+$>,$colors} t_$color={I[$>]} done 40038 -. .. a c 40039 40040 # Create CLUT. 40041 if $_is_preview 33,33,33,4 else 63,63,63,4 fi 40042 f.. "I(#-1,round([i0,i1,i2]*(w#-1-1)/255))+=[i3,i4,i5,1];" 40043 s. c,-3 +max. 1 /[-3,-1] eq. 0 40044 inpaint_pde.. . rm[-3,-1] 40045 2,2,2,3,"[x,y,z]*255" ri. ..,3 +[-2,-1] 40046 nm clut 40047 endl 40048 40049 # Apply CLUT. 40050 if $clut map_clut.. . rm. c 0,255 fi 40051 fi 40052 40053 if $preview_mapping # Generate view of color mapping 40054 __px,__py,__ps={s=min(w,h);p=$preview_mapping;p==1?[0.5,0.5,80]:\ 40055 p==2?[0,0,48]:\ 40056 p==3?[1,0,48]:\ 40057 p==4?[0,1,64]:[1,1,64]} 40058 l[] 40059 repeat narg($all_colors) color=${arg\ 1+$>,$all_colors} (${$color}) done a y permute. yzcx 40060 s x r {s=round(max($__ps,16));[s,s]} 40061 repeat narg($all_colors) l[$>] 40062 color=${arg\ 1+$>,$all_colors} 40063 mode=${mode_$color} 40064 if $mode==2 40065 polygon 3,0,100%,100%,100%,100%,0,1,${t_$color} 40066 line 0,100%,100%,0,0.5,0xAAAAAAAA,255 line 0,100%,100%,0,0.5,0x55555555,0 40067 fi 40068 to {`uppercase(['$color'][0])`},0.5~,0.5~,50%,2,0.5 40069 to_rgba 40070 if $mode frame 1,1,0,0,0,255 frame 2,2,255 else frame 3,3,0,0,0,64 fi 40071 endl done 40072 append_tiles 3,3 40073 store __preview_mapping 40074 endl 40075 fi 40076 40077 endl a c endl done 40078 40079fx_tune_hsv : 40080 _fx_tune_hsv ${1-63},0 40081 40082fx_tune_hsv_preview : 40083 preview_mapping=$64 40084 repeat $! l[$>] 40085 gui_split_preview "_is_preview=1 _fx_tune_hsv $*",${-3--1} 40086 if $preview_mapping 40087 $__preview_mapping 40088 if narg($_preview_width) rr2d[0] $_preview_width,$_preview_height,0,2 fi 40089 s. c,-3 to_colormode.. {-3,s} 40090 j... ..,$__px~,$__py~,0,0,1,.,255 rm[-2,-1] 40091 fi 40092 endl done 40093 40094 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]} 40095 u "{$1}{$2,$3,$4}_"$d"{$5}_"$d"{$6}_"$d"{$7}_"$d\ 40096 "{$8}{$9,$10,$11}_"$l"{$12}_"$l"{$13}_"$l"{$14}_"$l\ 40097 "{$15}{$16,$17,$18}_"$a"{$19}_"$a"{$20}_"$a"{$21}_"$a\ 40098 "{$22}{$23,$24,$25}_"$r"{$26}_"$r"{$27}_"$r"{$28}_"$r\ 40099 "{$29}{$30,$31,$32}_"$y"{$33}_"$y"{$34}_"$y"{$35}_"$y\ 40100 "{$36}{$37,$38,$39}_"$g"{$40}_"$g"{$41}_"$g"{$42}_"$g\ 40101 "{$43}{$44,$45,$46}_"$c"{$47}_"$c"{$48}_"$c"{$49}_"$c\ 40102 "{$50}{$51,$52,$53}_"$b"{$54}_"$b"{$55}_"$b"{$56}_"$b\ 40103 "{$57}{$58,$59,$60}_"$m"{$61}_"$m"{$62}_"$m"{$63}_"$m\ 40104 "{$64}{$65}{$66,$67}" 40105 40106#@gui User-Defined : fx_custom_transform, fx_custom_transform 40107#@gui : Red - Green - Blue - Alpha = text{"i"} 40108#@gui : Red - Green - Blue = text{"i + 90*(x/w)*cos(i/10)"} 40109#@gui : Red = text{"i"} 40110#@gui : Green = text{"i"} 40111#@gui : Blue = text{"i"} 40112#@gui : Alpha = text{"i"} 40113#@gui : Value Normalization = choice("None","RGB","RGBA") 40114#@gui : sep = separator() 40115#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40116fx_custom_transform : 40117 to_rgba repeat $! 40118 f. "$1" 40119 s. c a[-4--2] c f.. "$2" 40120 s.. c f[-4] "$3" f... "$4" f.. "$5" f. "$6" 40121 if $7==0 a[-4--1] c c. 0,255 40122 elif $7==1 a[-4--2] c n.. 0,255 c. 0,255 a[-2,-1] c 40123 else a[-4--1] c n. 0,255 40124 fi 40125 mv. 0 done 40126 40127#@gui ____<b>Contours</b> 40128#------------------------ 40129 40130#@gui Convolve : fx_convolve, fx_convolve_preview(0) 40131#@gui : Kernel = choice("Custom","Average 3x3","Average 5x5","Average 7x7","Average 9x9","Prewitt-X","Prewitt-Y", 40132#@gui : "Sobel-X","Sobel-Y","Rotinv-X","Rotinv-Y","Laplacian","Robert Cross 1","Robert Cross 2","Impulses 5x5", 40133#@gui : "Impulses 7x7","Impulses 9x9") 40134#@gui : Boundary = choice(1,"Dirichlet","Neumann") 40135#@gui : sep = separator() 40136#@gui : note = note("<small><b>Note:</b> If parameter <i>Kernel</i> is set to <i>Custom</i>, it uses the custom 40137#@gui : convolution kernel defined below. Use commas and semicolons as separators for res. matrix columns and rows. 40138#@gui : </small>") 40139#@gui : Custom Kernel = text("0,1,0;1,-4,1;0,1,0") 40140#@gui : sep = separator() 40141#@gui : note = note("<small><b>Note:</b> Kernel multiplier is useful only when parameter <i>Value range</i> is set 40142#@gui : to <i>Cut</i>.</small>") 40143#@gui : Value Range = choice(1,"Cut","Normalize") 40144#@gui : Kernel Multiplier = float(1,0,50) 40145#@gui : sep = separator() 40146#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 40147#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 40148#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 40149#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 40150#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 40151#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 40152#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 40153#@gui : sep = separator() 40154#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40155#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40156#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40157#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40158#@gui : sep = separator() 40159#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/06/06</i>.</small>") 40160fx_convolve : skip "${3=1}" 40161 ac "_fx_convolve $1,$2,\"$3\",${4--5}",$-4 40162 40163_fx_convolve : 40164 if $1 _fx_convolve$1[] else ($3) fi 40165 if !$4 *. $5 fi 40166 convolve[0--2] .,$2 40167 if $4 n 0,255 else c 0,255 fi 40168 rm. 40169 40170_fx_convolve1 : 3,3 f 1 normalize_sum # Average 3x3 40171_fx_convolve2 : 5,5 f 1 normalize_sum # Average 5x5 40172_fx_convolve3 : 7,7 f 1 normalize_sum # Average 7x7 40173_fx_convolve4 : 9,9 f 1 normalize_sum # Average 9x9 40174_fx_convolve5 : (1,0,-1;1,0,-1;1,0,-1) # Prewitt-X 40175_fx_convolve6 : (1,1,1;0,0,0;-1,-1,-1) # Prewitt-Y 40176_fx_convolve7 : (1,0,-1;2,0,-2;1,0,-1) # Sobel-X 40177_fx_convolve8 : (1,2,1;0,0,0;-1,-2,-1) # Sobel-Y 40178_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 40179_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 40180_fx_convolve11 : (0,1,0;1,-4,1;0,1,0) # Laplacian 40181_fx_convolve12 : (1,0;0,-1) # Robert Cross1 40182_fx_convolve13 : (0,1;-1,0) # Robert Cross2 40183_fx_convolve14 : 3,3 f 1 r 7,7,1,1,4,0,0.5,0.5 autocrop normalize_sum # Impulse 5x5 40184_fx_convolve15 : 3,3 f 1 r 9,9,1,1,4,0,0.5,0.5 autocrop normalize_sum # Impulse 7x7 40185_fx_convolve16 : 3,3 f 1 r 11,11,1,1,4,0,0.5,0.5 autocrop normalize_sum # Impulse 9x9 40186 40187fx_convolve_preview : skip "${3=1}" 40188 gui_split_preview "fx_convolve $1,$2,\"$3\",${4--1}",${-3--1} 40189 40190#@gui Curvature : fx_curvature, fx_curvature_preview(0) 40191#@gui : Smoothness = float(2,0,10) 40192#@gui : Min Threshold = float(0,0,100) 40193#@gui : Max Threshold = float(100,0,100) 40194#@gui : Absolute Value = bool(0) 40195#@gui : Negative Colors = bool(0) 40196#@gui : sep = separator() 40197#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40198#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40199#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40200#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40201#@gui : sep = separator() 40202#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40203fx_curvature : 40204 repeat $! l[$>] split_opacity l[0] 40205 b $1 iee 40206 if $4 abs fi 40207 c $2%,$3% 40208 if $5 negate fi 40209 n 0,255 40210 endl a c endl done 40211 40212fx_curvature_preview : 40213 gui_split_preview "fx_curvature ${^0}",${-3--1} 40214 40215#@gui Difference of Gaussians : fx_dog, fx_dog_preview(1) 40216#@gui : 1st Variance = float(1.4,0,5) 40217#@gui : 2nd Variance = float(1.5,0,5) 40218#@gui : Threshold = float(0,0,49) 40219#@gui : Negative Colors = bool(0) 40220#@gui : Monochrome = bool(1) 40221#@gui : sep = separator() 40222#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40223#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40224#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40225#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40226#@gui : sep = separator() 40227#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40228fx_dog : 40229 dog $1%,$2% 40230 if $5 norm fi 40231 c $3%,{100-$3}% 40232 if $4 negate fi 40233 n 0,255 40234 40235fx_dog_preview : 40236 gui_split_preview "fx_dog ${^0}",${-3--1} 40237 40238#@gui Distance Transform : fx_distance, fx_distance_preview(0) 40239#@gui : Value = int(128,0,255) 40240#@gui : Metric = choice(2,"Chebyshev","Manhattan","Euclidean","Squared-Euclidean") 40241#@gui : Normalization = choice(2,"Cut","Normalize","Modulo") 40242#@gui : Modulo Value = int(32,1,255) 40243#@gui : sep = separator() 40244#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40245#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40246#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40247#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40248#@gui : sep = separator() 40249#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/07/04</i>.</small>") 40250fx_distance : 40251 repeat $! l[$>] split_opacity l[0] 40252 distance $1,$2 40253 if $3==0 c 0,255 40254 elif $3==1 n 0,255 40255 else % $4 n 0,255 40256 fi 40257 endl a c endl done 40258 40259fx_distance_preview : 40260 gui_split_preview "fx_distance ${^0}",${-3--1} 40261 40262#@gui Edges : fx_edges, fx_edges_preview(0) 40263#@gui : Smoothness = float(0,0,10) 40264#@gui : Threshold = float(15,0,50) 40265#@gui : Negative Colors = bool(0) 40266#@gui : sep = separator() 40267#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40268#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40269#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40270#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40271#@gui : sep = separator() 40272#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40273fx_edges : 40274 to_rgb b $1% edges $2% 40275 if $3 negate fi 40276 n 0,255 40277 40278fx_edges_preview : 40279 gui_split_preview "fx_edges ${^0}",${-3--1} 40280 40281#@gui Edges Offsets : fx_edge_offsets, fx_edge_offsets_preview(0) 40282#@gui : Smoothness = float(0,0,10) 40283#@gui : Threshold = float(15,0,50) 40284#@gui : Scale = int(4,0,32) 40285#@gui : Thickness = int(1,0,16) 40286#@gui : Negative Colors = bool(0) 40287#@gui : sep = separator() 40288#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40289#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40290#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40291#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40292#@gui : sep = separator() 40293#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40294fx_edge_offsets : 40295 repeat $! 40296 os={s} 40297 b. $1% gradient_norm. >=. $2% skeleton. 0 distance. 1 round. 1 %. $3 >=. {max(1,$3-$4)} 40298 if !$5 negate. fi 40299 n. 0,255 to_colormode. $os 40300 mv. 0 done 40301 40302fx_edge_offsets_preview : 40303 gui_split_preview "fx_edge_offsets ${^0}",${-3--1} 40304 40305#@gui Extract Foreground [Interactive] : fx_extract_foreground, gui_no_preview 40306#@gui : Feathering = _float(0,0,4) 40307#@gui : Dilation = int(0,-32,32) 40308#@gui : Output Mode = choice{3,"RGBA Image (Full-Transparency / 1 Layer)","RGBA Image (Updatable / 1 Layer)", 40309#@gui : "RGB Image + Binary Mask (2 Layers)","RGBA Foreground + Background (2 Layers)"} 40310#@gui : View Resolution = _choice{1,"Small (Faster)","Medium","High (Slower)","Very High (Even Slower)"} 40311#@gui : sep = separator() 40312#@gui : note = note{"<small><b>Description:</b>\n 40313#@gui : This filter allows to quickly extract foreground objects from background in opaque RGB images. 40314#@gui : Click on the <i>Apply</i> or <i>OK</i> buttons below to open the interactive window and start adding 40315#@gui : foreground and background control points. When you're done, exit the interactive window: your extracted 40316#@gui : foreground will be transferred back to the host software.\n\n 40317#@gui : If you are not satisfied with the result, click on <i>Apply</i> once again to modify your control points 40318#@gui : defined previously. To remove all control points, click on the <i>Reset</i> button above. 40319#@gui : </small>"} 40320#@gui : Last Image Size = value(0,0) 40321#@gui : Control Points = value(-1) 40322#@gui : sep = separator() 40323#@gui : note = note{"<small><b>Interactions:</b>\n 40324#@gui : Use the following actions in the interactive window to build your extraction mask :\n\n 40325#@gui : - <b>Left mouse button</b> or key <b>F</b> create a new <b>foreground</b> control point 40326#@gui : (or move an existing one).\n 40327#@gui : - <b>Right mouse button</b> or key <b>B</b> create a new <b>background</b> control point 40328#@gui : (or move an existing one).\n 40329#@gui : - <b>Mouse wheel</b>, or keys <b>CTRL+arrows UP/DOWN</b> zoom view in/out.\n 40330#@gui : - Key <b>SPACE</b> updates the extraction mask.\n 40331#@gui : - Key <b>TAB</b> toggles background view modes.\n 40332#@gui : - Key <b>M</b> toggles marker view modes.\n 40333#@gui : - Key <b>BACKSPACE</b> deletes the last control point added.\n 40334#@gui : - Key <b>PAGE UP</b> increases background opacity.\n 40335#@gui : - Key <b>PAGE DOWN</b> decreases background opacity.\n 40336#@gui : - Keys <b>CTRL+D</b> increase window size.\n 40337#@gui : - Keys <b>CTRL+C</b> decrease window size.\n 40338#@gui : - Keys <b>CTRL+R</b> reset window size.\n 40339#@gui : - Keys <b>ESC</b>, <b>Q</b> or <b>ENTER</b> exit the interactive window. 40340#@gui : </small>"} 40341#@gui : sep = separator() 40342#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/29/09</i>.</small>") 40343fx_extract_foreground : 40344 if !$! return fi 40345 resolution={arg(1+$3,512,1024,2048,0)} 40346 repeat $! l[$<] 40347 nm=${-gui_layer_name} 40348 nm "[G"{`39`}"MIC] Interactive Foreground Extraction" 40349 if [$6][0]==-1" || "[$5]!=[w,h] _gui_control_points= else _gui_control_points=$6 fi 40350 status=${x_segment\ $resolution} 40351 sh 3 b. $1% if $2>0 dilate. {1+2*$2} elif $2<0 erode. {1-2*$2} fi 40352 rm. 40353 if $3==1 sh 3 max. 1 rm. 40354 elif $3==2 s c,-3 r. 100%,100%,1,4 rv nm[0] name(Mask) nm[1] name($nm) 40355 elif $3==3 40356 . 40357 sh.. 0,2 +channels... 3,3 >=. 3 *[-2,-1] rm. 40358 sh. 0,2 +channels.. 3,3 <=. {255-3} *[-2,-1] rm. 40359 sh. 3 *. -1 +. 255 rm. 40360 gui_autocrop_layers[0] 40361 pos0=${gui_layer_pos[0]} pos1=${gui_layer_pos[1]} 40362 nm[0] name($nm" [foreground]"),pos($pos0) 40363 nm[1] name($nm" [background]"),pos($pos1) 40364 fi 40365 endl done 40366 if narg($status)>=4 u \{$1\}\{$2\}\{$3\}\{$4\}\{{w},{h}\}\{$status\} else u "" fi 40367 40368#@gui Gradient Norm : fx_gradient_norm, fx_gradient_norm_preview(0) 40369#@gui : Smoothness = float(0,0,10) 40370#@gui : Linearity = float(0.5,0,1.5) 40371#@gui : Min Threshold = float(0,0,100) 40372#@gui : Max Threshold = float(100,0,100) 40373#@gui : Negative Colors = bool(0) 40374#@gui : sep = separator() 40375#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40376#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40377#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40378#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40379#@gui : sep = separator() 40380#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40381fx_gradient_norm : 40382 b $1 gradient_norm ^ $2 40383 c $3%,$4% 40384 if $5 negate fi 40385 n 0,255 40386 40387fx_gradient_norm_preview : 40388 gui_split_preview "fx_gradient_norm ${^0}",${-3--1} 40389 40390#@gui Gradient RGB : fx_gradient2rgb, fx_gradient2rgb_preview(0) 40391#@gui : Smoothness = float(0,0,10) 40392#@gui : Min Threshold = float(0,0,100) 40393#@gui : Max Threshold = float(100,0,100) 40394#@gui : Orientation Only = bool(0) 40395#@gui : Negative Colors = bool(0) 40396#@gui : sep = separator() 40397#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40398#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40399#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40400#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40401#@gui : sep = separator() 40402#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40403fx_gradient2rgb : 40404 b $1 gradient2rgb $4 40405 c $2%,$3% 40406 if $5 negate fi 40407 n 0,255 40408 40409fx_gradient2rgb_preview : 40410 gui_split_preview "fx_gradient2rgb ${^0}",${-3--1} 40411 40412#@gui Isophotes : fx_isophotes, fx_isophotes_preview(0) 40413#@gui : Levels = int(8,1,256) 40414#@gui : Smoothness = float(0,0,5) 40415#@gui : Filling = choice(1,"Transparent","Colors") 40416#@gui : sep = separator() 40417#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40418#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40419#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40420#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40421#@gui : sep = separator() 40422#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40423fx_isophotes : 40424 if $3 40425 topographic_map $1,$2 40426 else 40427 b $2 isophotes $1 40428 fi 40429 40430fx_isophotes_preview : 40431 gui_split_preview "fx_isophotes ${^0}",${-3--1} 40432 40433#@gui Laplacian : fx_laplacian, fx_laplacian_preview(0) 40434#@gui : Smoothness = float(0,0,10) 40435#@gui : Min Threshold = float(0,0,100) 40436#@gui : Max Threshold = float(100,0,100) 40437#@gui : Absolute Value = bool(0) 40438#@gui : Negative Colors = bool(0) 40439#@gui : sep = separator() 40440#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40441#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40442#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40443#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40444#@gui : sep = separator() 40445#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40446fx_laplacian : 40447 b $1 laplacian 40448 if $4 abs fi 40449 c $2%,$3% 40450 if $5 negate fi 40451 n 0,255 40452 40453fx_laplacian_preview : 40454 gui_split_preview "fx_laplacian ${^0}",${-3--1} 40455 40456#@gui Local Orientation : fx_local_orientation, fx_local_orientation_preview(1) 40457#@gui : Smoothness = float(0,0,5) 40458#@gui : Min Threshold = float(0,0,100) 40459#@gui : Max Threshold = float(100,0,100) 40460#@gui : Negative Colors = bool(0) 40461#@gui : sep = separator() 40462#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 40463#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 40464#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 40465#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 40466#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 40467#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 40468#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 40469#@gui : sep = separator() 40470#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40471#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40472#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40473#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40474#@gui : sep = separator() 40475#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40476_fx_local_orientation : 40477 repeat $! l[$>] split_opacity l[0] 40478 b $1% gradient_orientation 2 complex2polar rm[0--1:2] 40479 c $2%,$3% 40480 if $4 negate fi 40481 n 0,255 40482 endl a c endl done 40483 40484fx_local_orientation : 40485 ac "_fx_local_orientation $1,$2,$3,$4",$5,2 40486 40487fx_local_orientation_preview : 40488 gui_split_preview "fx_local_orientation ${^0}",${-3--1} 40489 40490#@gui Morphological Filter : fx_morphological, fx_morphological_preview(0) 40491#@gui : Action = choice{"Erosion","Dilation","Opening","Closing","Original - Erosion","Dilation - Original", 40492#@gui : "Original - Opening","Closing - Original","Original - (Opening + Closing)/2","Closing - Opening"} 40493#@gui : Kernel = choice(0,"Square","Octagonal","Circular","Custom") 40494#@gui : Size = int(5,2,60) 40495#@gui : note = note("<small>Parameter <i>Size</i> is inactive for <i>Custom</i> kernel.</small>") 40496#@gui : Custom Kernel = text("1,0,1; 0,1,0; 1,0,1") 40497#@gui : Negative = bool() 40498#@gui : Process Transparency = bool(0) 40499#@gui : sep = separator() 40500#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 40501#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 40502#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 40503#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 40504#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 40505#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 40506#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 40507#@gui : Value Action = choice("None","Cut","Stretch") 40508#@gui : sep = separator() 40509#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40510#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40511#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40512#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40513#@gui : sep = separator() 40514#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/22/06</i>.</small>") 40515fx_morphological : 40516 ac "_fx_morphological ${1-3},\"$4\",${5-6}",$7,$8 40517 40518fx_morphological_preview : 40519 gui_split_preview "fx_morphological ${1-3},\"$4\",${5--1}",${-3--1} 40520 if $2==3 40521 ('"$4"') f. "(i>=_'0' && i<=_'9') || i==_',' || i==_';'?i:-1" 40522 discard. -1 ({t}) rr2d. {0,max(24,w/6)},{0,max(24,h/6)},0,1 >. 0 *. 255 40523 to_rgba. frame. 1,1,0,0,0,0,255 frame. 1,1,255 frame. 1,1,0,0,0,0,255 40524 j[^-1] .,2,2,0,0,0.75 rm. 40525 else 40526 fi 40527 40528_fx_morphological : 40529 ('"$4"') f. "(i>=_'0' && i<=_'9') || i==_',' || i==_';'?i:-1" discard. -1 ckernel={t} rm. 40530 if $2==0 m "my_erode: erode $""1" m "my_dilate: dilate $""1" 40531 elif $2==1 m "my_erode: erode_oct $""1" m "my_dilate: dilate_oct $""1" 40532 elif $2==2 m "my_erode: erode_circ $""1" m "my_dilate: dilate_circ $""1" 40533 else 40534 m "my_erode : ("$ckernel") erode[^-1] . rm." 40535 m "my_dilate : ("$ckernel") dilate[^-1] . rm." 40536 fi 40537 # Erosion 40538 if $1==0 m "my_action : my_erode $3" 40539 # Dilation 40540 elif $1==1 m "my_action : my_dilate $3" 40541 # Opening 40542 elif $1==2 m "my_action : my_erode $3 my_dilate $3" 40543 # Closing 40544 elif $1==3 m "my_action : my_dilate $3 my_erode $3" 40545 # Original - Erosion 40546 elif $1==4 m "my_action : +my_erode $3 -" 40547 # Dilation - Original 40548 elif $1==5 m "my_action : +my_dilate $3 rv -" 40549 # Original - Opening 40550 elif $1==6 m "my_action : +my_erode $3 my_dilate. $3 -" 40551 # Closing - Original 40552 elif $1==7 m "my_action : +my_dilate $3 my_erode. $3 rv -" 40553 # Original - (Opening + Closing)/2 40554 elif $1==8 m "my_action : +my_erode $3 my_dilate. $3 +my_dilate.. $3 my_erode. $3 +[-2,-1] /. 2 -" 40555 # Closing - Opening 40556 else m "my_action : +my_erode $3 my_dilate. $3 my_dilate.. $3 my_erode.. $3 -" 40557 fi 40558 repeat $! l[$>] 40559 if !$6 split_opacity fi 40560 my_action[0] 40561 a c 40562 endl done 40563 if $5 repeat $! l[$>] split_opacity negate[0] a c endl done fi 40564 um my_erode,my_dilate,my_action 40565 40566#@gui Segmentation : fx_segment_watershed, fx_segment_watershed_preview(0) 40567#@gui : Edge Threshold = float(2,0,15) 40568#@gui : Smoothness = float(1,0,5) 40569#@gui : sep = separator() 40570#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 40571#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 40572#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 40573#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 40574#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 40575#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 40576#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 40577#@gui : Value Action = choice("None","Cut","Normalize") 40578#@gui : sep = separator() 40579#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40580#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40581#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40582#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40583#@gui : sep = separator() 40584#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40585fx_segment_watershed : skip ${4=1} 40586 ac "b $2 segment_watershed $1",$3,$4 40587 40588fx_segment_watershed_preview : 40589 gui_split_preview "fx_segment_watershed ${^0}",${-3--1} 40590 40591#@gui Skeleton : fx_skeleton, fx_skeleton_preview(1) 40592#@gui : Method = choice{"Distance (Fast)","Thinning (Slow)"} 40593#@gui : Smoothness = float(0,0,10) 40594#@gui : sep = separator() 40595#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40596#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40597#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40598#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40599#@gui : sep = separator() 40600#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/07/04</i>.</small>") 40601fx_skeleton : 40602 remove_opacity 40603 b $2% >= 50% 40604 if $1 thinning 1 40605 else 40606 distance 0 sharpen 1e10 >= 100% 40607 repeat $! +erode[$>] 2 -[$>,-1] done 40608 fi 40609 * 255 40610 40611fx_skeleton_preview : 40612 gui_split_preview "fx_skeleton ${^0}",${-3--1} 40613 40614#@gui Super-Pixels : fx_superpixels, fx_superpixels_preview(0) 40615#@gui : Size = int(16,4,64) 40616#@gui : Regularity = float(10,0,128) 40617#@gui : Iterations = int(5,1,16) 40618#@gui : Colors = choice(1,"Random","Average") 40619#@gui : Border Opacity = float(1,0,1) 40620#@gui : Border Color = color(0,0,0,255) 40621#@gui : sep = separator() 40622#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40623#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40624#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40625#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40626#@gui : sep = separator() 40627#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/11/16</i>.</small>") 40628fx_superpixels : 40629 repeat $! l[$>] 40630 +srgb2lab slic. ${1-3} 40631 if $4 +blend shapeaverage else +map. 2,2 fi 40632 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.. 40633 else k. 40634 fi 40635 endl done 40636 40637fx_superpixels_preview : 40638 gui_split_preview "fx_superpixels ${^0}",${-3--1} 40639 40640#@gui Thin Edges : fx_thin_edges, fx_thin_edges_preview(0) 40641#@gui : Smoothness = float(0,0,10) 40642#@gui : Threshold = float(15,0,50) 40643#@gui : Negative Colors = bool(0) 40644#@gui : sep = separator() 40645#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 40646#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 40647#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 40648#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 40649#@gui : sep = separator() 40650#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40651fx_thin_edges : 40652 b $1% gradient_norm >= $2% thinning 1 40653 if !$3 negate fi 40654 n 0,255 40655 40656fx_thin_edges_preview : 40657 gui_split_preview "fx_thin_edges ${^0}",${-3--1} 40658 40659 40660#@gui ____<b>Deformations</b> 40661#---------------------------- 40662 40663#@gui Cartesian Transform : fx_custom_deformation, fx_custom_deformation(1) 40664#@gui : X-Warping = text{"(w+h)/20 * cos(y*20/h)"} 40665#@gui : Y-Warping = text{"(w+h)/20 * sin(x*20/w)"} 40666#@gui : Relative Warping = bool(1) 40667#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 40668#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 40669#@gui : sep = separator() 40670#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40671fx_custom_deformation : 40672 if !$5 to_a fi 40673 repeat $! 40674 +norm. . f.. "$1" f. "$2" 40675 a[-2,-1] c warp.. .,$3,$4,$5,1 rm. 40676 mv. 0 done 40677 40678#@gui Circle Transform : fx_circle_transform, fx_circle_transform_preview(1) 40679#@gui : Center (%) = point(50,50,0,1) 40680#@gui : Radius = point(75,50,0,1) 40681#@gui : X-Scale = float(-2,-16,16) 40682#@gui : Y-Scale = float(-2,-16,16) 40683#@gui : Symmetry = choice("None","Inside","Outside") 40684#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 40685#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 40686#@gui : Preview Reference Circle = bool(1) 40687#@gui : sep = separator() 40688#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/08/01</i>.</small>") 40689fx_circle_transform : 40690 repeat $! l[$>] to_rgba 40691 r={dx=($3-$1)*(w-1)%;dy=($4-$2)*(h-1)%;norm(dx,dy)} 40692 if $7==0 cond="i(X,Y,z,c,$8,$9)" 40693 elif $7==1 cond="if(N<"$r",i(X,Y,z,c,$8,$9),i)" 40694 else cond="if(N>"$r",i(X,Y,z,c,$8,$9),i)" 40695 fi 40696 f "U = x - w*$1%; 40697 V = y - h*$2%; 40698 N = sqrt(U*U + V*V); 40699 Nr = N - "$r"; 40700 X = x + $5*Nr*U/N; 40701 Y = y + $6*Nr*V/N; 40702 "$cond 40703 endl done 40704 40705fx_circle_transform_preview : 40706 fx_circle_transform $* 40707 if $10 40708 rr2d ${-gui_preview_wh},0,1 40709 repeat $! l[$>] 40710 x0,y0={[$1,$2]*([w,h]-1)%} 40711 r={dx=($3-$1)*(w-1)%;dy=($4-$2)*(h-1)%;norm(dx,dy)} 40712 circle $x0,$y0,{$r-1},1,0xFFFFFFFF,0,0,0,255 40713 circle $x0,$y0,{$r+1},1,0xFFFFFFFF,0,0,0,255 40714 circle $x0,$y0,$r,1,0xFFFFFFFF,0,255,0,255 40715 endl done 40716 fi 40717 40718#@gui Conformal Maps : fx_conformal_maps, fx_conformal_maps_preview(1) 40719#@gui : Mapping = choice{8,"Custom Formula","z","(z-1)/(z+1)","cos(z)","sin(z)","tan(z)","exp(z)","log(z)", 40720#@gui : "Dipole: 1/(4*z^2-1)","Star: -5*(z^3/3-z/4)/2"} 40721#@gui : Exponent (Real) = float(1,-16,16) 40722#@gui : Exponent (Imaginary) = float(0,-16,16) 40723#@gui : Custom Formula = text{1,"((1.1 + i*z/6)/(1.04 - i*z/6))^6.2"} 40724#@gui : sep = separator() 40725#@gui : Zoom = float(0,-4,4) 40726#@gui : Angle = float(0,-180,180) 40727#@gui : Aspect Ratio = float(0,-1,1) 40728#@gui : X-Shift = float(0,-5,5) 40729#@gui : Y-Shift = float(0,-5,5) 40730#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 40731#@gui : Anti-Aliasing = int(0,0,3) 40732#@gui : sep = separator() 40733#@gui : Specify Different Output Size = _bool(0) 40734#@gui : Output Width = _text("1024") 40735#@gui : Output Height = _text("1024") 40736#@gui : sep = separator() 40737#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/15/02</i>.</small>") 40738fx_conformal_maps : 40739 to_a 40740 expr0="$4" 40741 expr1="z" 40742 expr2="(z+1)/(z-1)" 40743 expr3="cos(z)" 40744 expr4="sin(z)" 40745 expr5="tan(z)" 40746 expr6="exp(z)" 40747 expr7="log(z)" 40748 expr8="1/(4*z^2-1)" 40749 expr9="-5*(z^3/3-z/4)/2" 40750 40751 ('${expr$1}') 40752 replace_str. "*","**" 40753 replace_str. "/","//" 40754 replace_str. "^","^^" 40755 replace_str. "exp(","cexp(" 40756 replace_str. "log(","clog(" 40757 replace_str. "cos(","ccos(" 40758 replace_str. "sin(","csin(" 40759 replace_str. "tan(","ctan(" 40760 expr={t} 40761 rm. 40762 40763 repeat $! l[$>] 40764 wh={$12?[$13,$14]:[w,h]} 40765 {(1+$11)*[$wh]},1,100% 40766 f. "begin( 40767 ccos(z) = (iz = [ -z[1],z[0] ]; (cexp(iz) + cexp(-iz)/2)); 40768 csin(z) = (iz = [ -z[1],z[0] ]; (cexp(iz) - cexp(-iz)/2)); 40769 ctan(z) = csin(z)//ccos(z); 40770 boundary = $10; 40771 interpolation = 1; 40772 const f = max(w,h); 40773 const f0 = max(w#0,h#0); 40774 i = [0,1]; 40775 ); 40776 z = (2*[ x,y ] - [ w,h ])/f; 40777 z = rot(-$6°)*z; 40778 z-= [ $8, $9 ]; 40779 z/=[ 10^($5 + $7), 10^$5 ]; 40780 z = ("$expr"); 40781 if ($1, z = z^^[$2,$3]); 40782 z = rot($6°)*z; 40783 z = 0.5*(f0*z + [w#0,h#0]); 40784 I(#0,z)" 40785 r. $wh,1,100%,2 40786 rm.. 40787 endl done 40788 40789fx_conformal_maps_preview : 40790 fx_conformal_maps ${1-3},"$4",${5-11},0,0,0 40791 40792#@gui Crease : fx_crease,fx_crease(0) 40793#@gui : Amplitude = float(30,0,300) 40794#@gui : Frequency (%) = float(10,0,100) 40795#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 40796#@gui : sep = separator() 40797#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/22</i>.</small>") 40798fx_crease : 40799 repeat $! l[$>] 40800 if !$3 to_a fi 40801 2,2,1,2,{"const w1 = w#-1-1; const h1 = h#-1 - 1; [ 0,w1,0,w1,0,0,h1,h1 ];"} 40802 r. {0,D=$2*[w,h]%;[max(D[0],1),max(D[1],1)]},1,2,3 noise. $1,1 40803 r. ..,..,1,2,3 warp.. .,0,1,$3 rm. 40804 endl done 40805 40806#@gui Distort Lens : fx_distort_lens, fx_distort_lens(1) 40807#@gui : Amplitude = float(0.1,-1,1) 40808#@gui : Aspect Ratio = float(0,-2,2) 40809#@gui : Zoom = float(0,-4,4) 40810#@gui : Center (%) = point(50,50,0,1) 40811#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 40812#@gui : sep = separator() 40813#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/18/02</i>.</small>") 40814fx_distort_lens : 40815 if !$6 to_a fi 40816 undistort ${1-3},$4%,$5%,$6 40817 40818#@gui Drop Water : fx_drop_water, fx_drop_water_preview(1) 40819#@gui : note = note("<small><b>Shape geometry:</b></small>") 40820#@gui : Shapes = choice("Procedural","Opaque Regions on Top Layer") 40821#@gui : Density = float(20,0,100) 40822#@gui : Radius = float(2,0,5) 40823#@gui : Variability = float(80,0,100) 40824#@gui : Random Seed = int(0,0,16384) 40825#@gui : note = note("<small>Parameters <i>Density</i>, <i>Radius</i>, <i>Variability</i> and <i>Random seed</i> 40826#@gui : are used only in <i>Procedural shapes</i> mode.</small>") 40827#@gui : sep = separator() 40828#@gui : note = note("<small><b>Light parameters:</b></small>") 40829#@gui : Refraction = float(3,0,20) 40830#@gui : Light Angle = float(35,0,360) 40831#@gui : Specular Size = float(10,0,100) 40832#@gui : Specular Intensity = float(1,0,1) 40833#@gui : Specular Centering = float(0.5,0,1) 40834#@gui : sep = separator() 40835#@gui : note = note("<small><b>Shadow parameters:</b></small>") 40836#@gui : Shadow Size = float(0.25,0,3) 40837#@gui : Shadow Intensity = float(0.5,0,1) 40838#@gui : Shadow Smoothness = float(0.75,0,3) 40839#@gui : Diffuse Shadow = float(0.05,0,3) 40840#@gui : sep = separator() 40841#@gui : Smoothness = float(0.15,0,3) 40842#@gui : Output as Separate Layers = _bool(1) 40843#@gui : sep = separator() 40844#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/21/07</i>.</small>") 40845fx_drop_water : 40846 N={$!-$1} 40847 if $N<=0 error "At least two layers are required in this mode." fi 40848 40849 repeat $N l[{$!-$>-1}] nm0={n} nm=${-gui_layer_name} 40850 nm img 40851 40852 # Create binary shapes (i.e. opacity map). 40853 srand $5 40854 if $1 # Shape from top layer. 40855 pass[0] 0 to_a. channels. 100% >=. 50% 40856 r. [0],[0],1,1,0,0,0.5,0.5 40857 else # Procedural shape. 40858 100%,100% 40859 rmin={max(0.1,$3*(1-$4%))} rmax={max(0.1,$3)} 40860 repeat 10 40861 100%,100% 40862 random3d {max(1,$2)} *3d. {-2,w},{-2,h},0 40863 j3d.. .,0,0,0,1,1,0,0 rm. 40864 b. {$rmin+($rmax-$rmin)*$>/9}%,0,1 40865 j.. .,0,0,0,0,0.5 rm. 40866 done 40867 >=. 10% 40868 fi 40869 nm. shape 40870 40871 # Create elevation map. 40872 +b[shape] 1% n. 0,30 40873 nm. elevation 40874 40875 # Warp image. 40876 g[elevation] xy a[-2,-1] c nm. grad 40877 +*[grad] {grad,$6*max(w,h)/100} *. [shape] b. $15% 40878 +warp[img] .,1,1,1 rm.. nm. refraction 40879 40880 # Compute specular spots. 40881 +*[grad] -1 100%,100%,1,1,1 a[-2,-1] c orientation. # 3D normal map. 40882 a={$7*pi/180} ca={-cos($a)} sa={-sin($a)} 40883 mix_channels. ({(1-$10)*$ca},{(1-$10)*$sa},1) c. {100-$8}%,100% n. 0,1 40884 *. [shape] nm. spots 40885 40886 # Compute ambiant light (gradient). 40887 mix_channels[grad] ($ca,$sa) 40888 n[grad] 0,1 *[grad] [shape] 40889 40890 # Drop shadow. 40891 +shift[shape] {-$11*$ca}%,{-$11*$sa}%,0,0,1 40892 -. [shape] >=. 1 b. $13% n. 0,1 40893 nm. shadow 40894 b[shape] $14% n. 0,1 # Add diffuse shadow around each drop. 40895 40896 # Prepare layers for output. 40897 nm[img] name($nm) 40898 40899 *[shadow] 255 channels[shadow] -1,0 mv[shadow] 1 40900 nm[shadow] name($nm" [shadow]"),mode(alpha),opacity({$12*100}) 40901 40902 to_a[refraction] sh[refraction] 100% +b[shape] $15% *[-2,-1] rm. 40903 mv[refraction] 2 40904 nm[refraction] name($nm" [refraction]"),mode(alpha) 40905 40906 channels[spots] -1,0 sh[spots] 0 f. 1 rm. *[spots] 255 40907 nm[spots] name($nm" [specular spots]"),mode(alpha),opacity({$9*100}) 40908 40909 rv[shape,grad] a[grad,shape] c *[grad] 255 b[grad] $15% 40910 nm[grad] name($nm" [gradient]"),mode(grainmerge) 40911 40912 rv 40913 if !$16 gui_merge_layers nm $nm0 fi 40914 endl done 40915 if $1 rm[0] fi 40916 40917fx_drop_water_preview : 40918 N={$!-$1} 40919 if $N<=0 gui_warning_preview "At least two layers are required in this mode." return fi 40920 if $1 40921 repeat $N l[{$!-$>-1}] 40922 pass[0] 0 mv. 0 40923 fx_drop_water $* gui_merge_layers 40924 endl done 40925 rm[0] 40926 else 40927 repeat $! l[$>] 40928 fx_drop_water $* gui_merge_layers 40929 endl done 40930 fi 40931 40932#@gui Equirectangular to Nadir-Zenith : fx_equirectangular2nadirzenith, fx_equirectangular2nadirzenith(1) 40933#@gui : Mode = choice{"to Nadir / Zenith","to Equirectangular"} 40934#@gui : sep = separator() 40935#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/29/12</i>.</small>") 40936fx_equirectangular2nadirzenith : 40937 if $1 nadirzenith2equirectangular else equirectangular2nadirzenith fi 40938 40939#@gui Euclidean - Polar : fx_euclidean2polar, fx_euclidean2polar(1) 40940#@gui : Center (%) = point(50,50,0,1) 40941#@gui : Stretch Factor = float(1,0.1,10) 40942#@gui : Boundary = choice(1,"Transparent","Nearest","Periodic","Mirror") 40943#@gui : Inverse Transform = bool(0) 40944#@gui : sep = separator() 40945#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40946fx_euclidean2polar : 40947 if !$4 to_a fi 40948 if $5 polar2euclidean $1%,$2%,$3,$4 else euclidean2polar $1%,$2%,$3,$4 fi 40949 40950#@gui Fish-Eye : fisheye, fisheye(1) 40951#@gui : Center (%) = point(50,50,0,1,255) 40952#@gui : Radius = float(70,0,100) 40953#@gui : Amplitude = float(1,0,2) 40954#@gui : sep = separator() 40955#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40956 40957#@gui Flower : fx_flower, fx_flower_preview(1) 40958#@gui : Center (%) = point(50,50,0,1) 40959#@gui : Amplitude / Angle = point(75,50,0,1) 40960#@gui : Petals = int(6,2,20) 40961#@gui : Offset (%) = float(0,0,100) 40962#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 40963#@gui : sep = separator() 40964#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40965fx_flower : 40966 if !$7 to_a fi 40967 amplitude,angle={dx=$3-$1;dy=$4-$2;[norm(dx,dy),-atan2(dy,dx)*180/pi]} 40968 flower $amplitude,$5,$6%,$angle,$1%,$2%,$7 40969 40970fx_flower_preview : 40971 fx_flower $* 40972 line $1%,$2%,$3%,$4%,1,0xF0F0F0F0,0 40973 line $1%,$2%,$3%,$4%,1,0x0F0F0F0F,255 40974 40975#@gui Kaleidoscope [Blended] : fx_rotoidoscope, fx_rotoidoscope(1) 40976#@gui : Center (%) = point(50,50) 40977#@gui : Angular Tiles = int(10,1,72) 40978#@gui : Smoothness = float(0.5,0,5) 40979#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 40980#@gui : sep = separator() 40981#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40982fx_rotoidoscope : 40983 if !$5 to_a fi 40984 rotoidoscope $1%,$2%,$3,$4%,$5 40985 40986#@gui Kaleidoscope [Polar] : fx_kaleidoscope, fx_kaleidoscope(1) 40987#@gui : Center (%) = point(50,50) 40988#@gui : X-Offset (%) = float(0,0,100) 40989#@gui : Y-Offset (%) = float(0,0,100) 40990#@gui : Radius Cut = float(100,0,100) 40991#@gui : Angle Cut = float(10,0,100) 40992#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 40993#@gui : sep = separator() 40994#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 40995fx_kaleidoscope : 40996 if !$7 to_a fi 40997 shift $3%,$4%,0,0,2 kaleidoscope $1%,$2%,$5,$6,$7 40998 40999#@gui Kaleidoscope [Symmetry] : fx_symmetrizoscope, fx_symmetrizoscope(1) 41000#@gui : Iterations = int(4,1,32) 41001#@gui : Angle = float(0,0,360) 41002#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 41003#@gui : Symmetry Sides = choice("Backward","Forward","Swap") 41004#@gui : sep = separator() 41005#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/07/01</i>.</small>") 41006fx_symmetrizoscope : 41007 if !$3 to_a fi 41008 repeat $1 41009 ang={$2+180*$>/max(1,$1-1)} 41010 symmetrize 50%,50%,$ang,$3,0,{if($4!=2,$4,$>%2)} 41011 done 41012 41013#@gui Morph [Interactive] : fx_morph_interactive, fx_morph_interactive_preview 41014#@gui : Number of Frames = int(16,3,1024) 41015#@gui : Preview Precision = choice{2,"Coarsest (faster)","Coarse","Normal","Fine","Finest (slower)"} 41016#@gui : Keypoints = value(-1) 41017#@gui : sep = separator() 41018#@gui : note = note{"<b>Instructions:</b>"} 41019#@gui : note = note{" 41020#@gui : Use mouse buttons to add/move/remove correspondence keypoints over the interactive window that will appear, 41021#@gui : in order to create the morphing.\n\n 41022#@gui : <span color="#EE5500"><b>Source/target window:</b></span>\n\n 41023#@gui : - <b>Left mouse button</b>: Add new keypoint on current image and move it on the other one.\n 41024#@gui : - <b>Right mouse button</b>: Add/move keypoint on current image.\n 41025#@gui : - Key <b>DELETE</b> or <b>middle mouse button</b>: Delete keypoint.\n 41026#@gui : - Key <b>SPACE</b> or <b>mouse wheel</b>: Toggle source/target.\n\n 41027#@gui : <span color="#EE5500"><b>In-between window:</b></span>\n\n 41028#@gui : - <b>Mouse wheel</b>: Change morphing time, from 0 to 1.\n 41029#@gui : - <b>Left mouse button</b>: Reset morphing time to 0.5.\n\n 41030#@gui : <span color="#EE5500"><b>Both windows:</b></span>\n\n 41031#@gui : - Key <b>TAB</b>: Change keypoint radius.\n 41032#@gui : - Key <b>ENTER</b>: Play/stop in-between animation.\n 41033#@gui : - Key <b>R</b>: Reset keypoints.\n 41034#@gui : - Key <b>K</b>: Show/hide keypoints.\n 41035#@gui : - Keys <b>ESC</b> or <b>Q</b>: Process fullres and exit. 41036#@gui : "} 41037#@gui : sep = separator() 41038#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/04/16</i>.</small>") 41039fx_morph_interactive : 41040 if [$3][0]!=-1 __x_morph_keypoints=$3 fi 41041 rv 41042 x_morph $1,$2 41043 repeat $! gui_set_layer_name[$>] "Morphing ""#"$> gui_set_layer_pos[$>] 0,0 done 41044 rv 41045 u "{$1}{$2}{"$__x_morph_keypoints"}" 41046 41047fx_morph_interactive_preview : 41048 if $!<2 gui_warning_preview "This filter requires at least two input layers!" return fi 41049 rr2d ${-max_wh},0,3 + n 0,255 41050 if [$3][0]!=-1 gui_warning_preview "No preview available\n\nKeypoints from previous\nrun have been saved" 41051 else gui_warning_preview "No preview available" 41052 fi 41053 41054#@gui Perspective : fx_warp_perspective, fx_warp_perspective(1) 41055#@gui : X-Angle = float(1.73,-4,4) 41056#@gui : Y-Angle = float(0,-4,4) 41057#@gui : Zoom = float(1,0.1,4) 41058#@gui : Center (%) = point(50,50,0,1,255) 41059#@gui : X-Offset = float(0,0,100) 41060#@gui : Y-Offset = float(0,0,100) 41061#@gui : Boundary = choice(2,"Transparent","Nearest","Periodic","Mirror") 41062#@gui : sep = separator() 41063#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41064fx_warp_perspective : 41065 if !$8 to_a fi 41066 shift $6%,$7%,0,0,2 warp_perspective $1,$2,$3,$4,$5,$8 41067 41068#@gui Polar Transform : fx_transform_polar, fx_transform_polar(1) 41069#@gui : Preset = choice("Custom Transform","Inverse Radius","Swap Radius / Angle") 41070#@gui : Center (%) = point(50,50,0,1) 41071#@gui : Radius = text{"r + R/10*cos(a*5)"} 41072#@gui : Angle = text{"a"} 41073#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 41074#@gui : sep = separator() 41075#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41076fx_transform_polar : 41077 if !$6 to_a fi 41078 if $1==0 41079 transform_polar "$4","$5",$2%,$3%,$6 41080 elif $1==1 41081 transform_polar R-r,a,$2%,$3%,$6 41082 else 41083 transform_polar a*R/(2*pi),r*2*pi/R,$2%,$3%,$6 41084 fi 41085 41086#@gui Quadrangle : fx_quadrangle, fx_quadrangle_preview(1) 41087#@gui : Top-Left Vertex (%) = point(5,5,0,1,255,0,0) 41088#@gui : Top-Right Vertex (%) = point(95,25,0,1,0,255,0) 41089#@gui : Bottom-Right Vertex (%) = point(60,95,0,1,64,128,255) 41090#@gui : Bottom-Left Vertex (%) = point(40,95,0,1,255,255,0) 41091#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 41092#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 41093#@gui : Preview Type = choice(1,"Input","Output","Both") 41094#@gui : sep = separator() 41095#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/10/11</i>.</small>") 41096fx_quadrangle : 41097 at_quadrangle $1%,$2%,$3%,$4%,$5%,$6%,$7%,$8%,${9-10} 41098 41099fx_quadrangle_preview : 41100 repeat $! l[$>] 41101 if !$10 to_a fi 41102 if $11 +fx_quadrangle $* rr2d. {0,[w,h]},2,3 fi 41103 polygon[{$11==1?1:0}] 4,$1%,$2%,$3%,$4%,$5%,$6%,$7%,$8%,0.25,255 41104 if $11>=2 41105 circle[0] $1%,$2%,4,1,0 circle[0] $1%,$2%,3,1,255,0,0 41106 circle[0] $3%,$4%,4,1,0 circle[0] $3%,$4%,3,1,0,255,0 41107 circle[0] $5%,$6%,4,1,0 circle[0] $5%,$6%,3,1,64,128,255 41108 circle[0] $7%,$8%,4,1,0 circle[0] $7%,$8%,3,1,255,255,0 41109 elif $11>0 41110 rm[0] 41111 fi 41112 if $!==2 41113 drgba to[0] Quadrangle to[1] Result frame 1,1,0 41114 +a x a[0,1] y rr2d ${-gui_preview_wh},0,3 41115 k[{max(w#0,h#0)>max(w#1,h#1)?0:1}] 41116 fi 41117 endl done 41118 41119#@gui Raindrops : raindrops, raindrops(0) 41120#@gui : Amplitude = float(80,0,300) 41121#@gui : Density = float(0.1,0,1) 41122#@gui : Wavelength = float(1,0,2) 41123#@gui : Merging Steps = int(0,0,20) 41124#@gui : sep = separator() 41125#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/28/11</i>.</small>") 41126 41127#@gui Random : deform, deform(0) 41128#@gui : Amplitude = float(10,0,100) 41129#@gui : sep = separator() 41130#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41131 41132#@gui Ripple : ripple, ripple(0) 41133#@gui : Amplitude = float(10,0,100) 41134#@gui : Bandwidth = float(20,1,300) 41135#@gui : Shape = choice(2,"Bloc","Triangle","Sine","Sine+","Random") 41136#@gui : Angle = float(0,0,360) 41137#@gui : Offset = float(0,0,500) 41138#@gui : sep = separator() 41139#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/23/08</i>.</small>") 41140 41141#@gui Reflection : fx_reflect, fx_reflect(1) 41142#@gui : Height = float(50,0,100) 41143#@gui : Attenuation = float(1,0.1,4) 41144#@gui : Color = color(110,160,190,64) 41145#@gui : Waves Amplitude = float(0,0,100) 41146#@gui : Waves Smoothness = float(1.5,0,4) 41147#@gui : X-Angle = float(0,-10,10) 41148#@gui : Y-Angle = float(-3.30,-10,10) 41149#@gui : Focale = float(7,0,10) 41150#@gui : Zoom = float(1.5,1,5) 41151#@gui : sep = separator() 41152#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41153fx_reflect : 41154 repeat $! 41155 to_rgba. +rows. {100-$1}%,100% mirror. y water. $7,$8 41156 s. c 41157 f[-4] "(i*(255-$6) + $6*$3)/255" 41158 f... "(i*(255-$6) + $6*$4)/255" 41159 f.. "(i*(255-$6) + $6*$5)/255" a[-4--1] c 41160 *. '(h^$2-y^$2)/h^$2' a[-2,-1] y 41161 100%,100%,100%,1,$11*$12*(x/w-0.5) 41162 100%,100%,100%,1,$11*$12*(y/h-0.5) 41163 100%,100%,100%,1,"$10*(x/w-0.5) + $9*(y/h-0.5) + $11" 41164 /... . +... 0.5 *... {-3,w} 41165 /[-2,-1] +. 0.5 *. {h} 41166 a[-2,-1] c warp.. .,0,1,0 rm. 41167 mv. 0 done 41168 autocrop 0,0,0,0 41169 41170#@gui Seamcarve : fx_seamcarve, fx_seamcarve_preview(1) 41171#@gui : Width (%) = float(85,0,200) 41172#@gui : Height (%) = float(100,0,200) 41173#@gui : Maximal Seams per Iteration (%) = float(15,0,100) 41174#@gui : Use Top Layer as a Priority Mask = bool(0) 41175#@gui : Antialiasing = bool(1) 41176#@gui : sep = separator() 41177#@gui : note = note{"<small><b>Note:</b> 41178#@gui : You can define a transparent top layer that will help the seam-carving algorithm to preserve or force 41179#@gui : removing image structures:\n 41180#@gui : \n - Draw areas in <i>red</i> to force removing them. 41181#@gui : \n - Draw areas in <i>green</i> to preserve them. 41182#@gui : \n - Don't forget also to set the <i>Input layers...</i> parameter to input both layers to the filter. 41183#@gui : </small>"} 41184#@gui : sep = separator() 41185#@gui : note = note("<small>Authors: <i>Garagecoder</i> and <i>David Tschumperlé</i>. 41186#@gui : Latest Update: <i>2014/02/06</i>.</small>") 41187fx_seamcarve : 41188 if $4 41189 if $!<2 error "Priority mask (top layer) is missing!" fi 41190 _fx_seamcarve 41191 fi 41192 seamcarve $1%,$2%,$4,$5,$3% 41193 if $4 repeat $! channels[$>] 0,{$>,s-2} done fi 41194 c 0,255 41195 41196fx_seamcarve_preview : 41197 if $4 41198 if $!<2 to_rgb to "Priority mask (top layer) is missing!",5,5,18,2 return fi 41199 _fx_seamcarve 41200 fi 41201 repeat $! l[$>] 41202 w={w} h={h} 41203 seamcarve $1%,$2%,$4,$5,{max($3,10)}% 41204 if $4 channels 0,{s-2} fi 41205 to_rgba r $w,$h,1,100%,0,0,0.5,0.5 41206 endl done 41207 c 0,255 41208 41209_fx_seamcarve : 41210 mv[0] $! 41211 l. 41212 s c k[0,1] 41213 >[1] [0] !=[0] 0 -[0] [1] *[0] -1 + * 256 41214 endl 41215 repeat $!-1 a[$>] .,c done rm. 41216 41217#@gui Sphere : fx_map_sphere, fx_map_sphere_preview(1) 41218#@gui : Width = _int(512,1,4096) 41219#@gui : Height = _int(512,1,4096) 41220#@gui : Radius = float(90,0,400) 41221#@gui : Dilation = float(0.5,0,1) 41222#@gui : Angle = float(0,-50,50) 41223#@gui : Border Smoothness = float(0,0,200) 41224#@gui : Border Width = float(20,0,100) 41225#@gui : Orientation = choice("0 deg.","90 deg.","180 deg.","270 deg.") 41226#@gui : Background = choice("Transparent","Mean Color") 41227#@gui : Fading = float(0,0,100) 41228#@gui : Fading Shape = float(0.5,0,3) 41229#@gui : sep = separator() 41230#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/07/11</i>.</small>") 41231fx_map_sphere : 41232 rotate {$8*90} 41233 if $6 41234 repeat $! 41235 shift. {round(w/2)},0,0,0,2 +columns. {(1-$7/100)*w/2},{(1+$7/100)*w/2} 41236 100% gaussian. {0.1*w},{h},0 100% 100% a[-3--1] c r. ..,..,1,3 41237 smooth.. .,$6,5,0 rm. 41238 j.. .,{(1-$7/100)*{-2,w}/2} rm. shift. -{round(w/2)},0,0,0,2 41239 mv. 0 done 41240 fi 41241 shift $5%,0,0,0,2 to_rgba 41242 if $9 41243 repeat $! 41244 +rows[$>] 0 r. 1,1,1,4,2 RGBA$>={^} 41245 r. [$>],[$>],1,4 -[$>,-1] 41246 done 41247 fi 41248 map_sphere $1,$2,$3,$4,$10,$11 41249 if $9 41250 repeat $! 41251 (${RGBA$>}) y. c r. [$>],[$>],1,4 +[$>,-1] 41252 done 41253 fi 41254 41255fx_map_sphere_preview : 41256 fx_map_sphere {w},{h},${3--1} 41257 41258#@gui Spherize : fx_spherize, fx_spherize_preview(1) 41259#@gui : Radius (%) = float(50,0,300) 41260#@gui : Strength = float(1,-10,10) 41261#@gui : Smoothness (%) = float(0,0,4) 41262#@gui : Center (%) = point(50,50,0,1,255,255,255,170,10) 41263#@gui : Ratio = float(0,-2,2) 41264#@gui : Angle = float(0,-90,90) 41265#@gui : Interpolation = choice(2,"Nearest Neighbor","Linear","Cubic") 41266#@gui : Preview Grid = bool(0) 41267#@gui : sep = separator() 41268#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/10/03</i>.</small>") 41269fx_spherize : 41270 ratio={10^$6} 41271 spherize $1%,$2,$3%,$4%,$5%,$ratio,$7,$8 41272 cut 0,255 41273 41274fx_spherize_preview : 41275 cx,cy=${4,5} 41276 if $9 grid 5%,5%,50%,50%,0.6,255 fi 41277 fx_spherize ${1-3},$cx,$cy,${6--1} 41278 41279#@gui Square to Circle : fx_square_circle, fx_square_circle 41280#@gui : Mode = choice(0,"Square to Circle","Circle to Square") 41281#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 41282#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 41283#@gui : sep = separator() 41284#@gui : X-Factor (%) = float(0,-100,100) 41285#@gui : Y-Factor (%) = float(0,-100,100) 41286#@gui : X-Offset (%) = float(0,-300,300) 41287#@gui : Y-Offset (%) = float(0,-300,300) 41288#@gui : sep = separator() 41289#@gui : note = note("<small>This filter implements the mapping functions described in this page, 41290#@gui : by <i>C. Fong</i>:</small>") 41291#@gui : url = link("http://squircular.blogspot.com/2015/09/mapping-circle-to-square.html") 41292#@gui : sep = separator() 41293#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/10/30</i>.</small>") 41294fx_square_circle : 41295 mode,interp,boundary,factx,facty,offx,offy=${1-7} 41296 if !$boundary to_a fi 41297 base="const interpolation = "$interp"; 41298 const boundary = "$boundary"; 41299 const offx = "$offx"%; 41300 const offy = "$offy"%; 41301 const factx = 10^-("$factx"%); 41302 const facty = 10^-("$facty"%); 41303 const w2 = int(w/2); 41304 const h2 = int(h/2);" 41305 if !$mode # Square to circle 41306 f $base" 41307 const tst = 2*sqrt(2); 41308 U = (2*x/(w-1) - 1)*factx + offx; 41309 V = (2*y/(h-1) - 1)*facty + offy; 41310 U2 = U^2; 41311 V2 = V^2; 41312 U2mV2 = U2 - V2; 41313 X = 0.5*(sqrt(max(0,2 + tst*U + U2mV2)) - sqrt(max(0,2 - tst*U + U2mV2))); 41314 Y = 0.5*(sqrt(max(0,2 + tst*V - U2mV2)) - sqrt(max(0,2 - tst*V - U2mV2))); 41315 (X+=1)*=w2 - 0.5; 41316 (Y+=1)*=h2 - 0.5; 41317 I(X,Y)" 41318 else # Circle to square 41319 f $base" 41320 X = (2*x/(w-1) - 1)*factx + offx; 41321 Y = (2*y/(h-1) - 1)*facty + offy; 41322 U = X*sqrt(abs(1 - 0.5*Y^2)); 41323 V = Y*sqrt(abs(1 - 0.5*X^2)); 41324 (U+=1)*=w2 - 0.5; 41325 (V+=1)*=h2 - 0.5; 41326 I(U,V)" 41327 fi 41328 41329#@gui Stereographic Projection : fx_project_stereographic, fx_project_stereographic_preview(1) 41330#@gui : Transform = choice("Direct","Inverse") 41331#@gui : Center (%) = point(50,50,0,1,255,255,255,170) 41332#@gui : Radius / Angle = point(50,75,0,1,255,0,255,170) 41333#@gui : Horizon Leveling (deg) = float(0,-10,10) 41334#@gui : Left / Right Blur (%) = float(0,0,20) 41335#@gui : Dilation = float(0,-2,2) 41336#@gui : Mirror = choice("None","X-Axis","Y-Axis","XY-Axis") 41337#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 41338#@gui : Last Center = value(50,50) 41339#@gui : sep = separator() 41340#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/07/04</i>.</small>") 41341fx_project_stereographic : 41342 is_inverse,centerx,centery,radangx,radangy,rechor,lrblur,dilation,mirror,boundary,ocenterx,ocentery=${1-11} 41343 41344 if $centerx!=$ocenterx" || "$centery!=$ocentery 41345 deltax,deltay={[$radangx,$radangy]-[$ocenterx,$ocentery]} 41346 radangx,radangy={[$centerx,$centery]+[$deltax,$deltay]} 41347 fi 41348 status=\{$is_inverse\}\{$centerx,$centery\}\{$radangx,$radangy\}\{$rechor\}\{$lrblur\}\ 41349 \{$dilation\}\{$mirror\}\{$boundary\}\{$centerx,$centery\} 41350 41351 # So that preview line does not hide left/right frontier: 41352 nradangx,nradangy={[$centerx,$centery]+rot(-90°)*([$radangx,$radangy]-[$centerx,$centery])} 41353 init="const boundary = "$is_inverse?$boundary:2"; 41354 const interpolation = 1; 41355 const dilation = 2^"$dilation"; 41356 const centerx = "$centerx"%*(W-1); 41357 const centery = "$centery"%*(H-1); 41358 const radangx = "$nradangx"%*(W-1) - centerx; 41359 const radangy = "$nradangy"%*(H-1) - centery; 41360 const R = sqrt(radangx^2 + radangy^2); 41361 const theta0 = atan2(radangy,radangx); 41362 const pi2 = 2*pi;" 41363 m "_fx_project_stereographic_mirror : if !$""1 mirror y elif $""1==1 mirror xy elif $""1==3 mirror x fi" 41364 repeat $! l[$>] 41365 if !$boundary to_a fi 41366 if $rechor rotate $rechor,1,3 fi 41367 if $lrblur 41368 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% 41369 r.. .,.,1,1 j... .,0,0,0,0,1,.. k[0] shift {-round(w/2)},0,0,0,2 41370 fi 41371 if $is_inverse 41372 100%,50%,1,100%,"* 41373 const W = w#0; 41374 const H = h#0; 41375 "$init" 41376 theta = theta0 + x*pi2/w; 41377 phi = (y/h - 0.5)*pi; 41378 z = R*sin(phi); 41379 rho = ((R + z)/(R - z))^(0.5/dilation)*R; 41380 X = centerx + rho*cos(theta); 41381 Y = centery + rho*sin(theta); 41382 I(#0,X,Y)" 41383 _fx_project_stereographic_mirror $mirror 41384 else 41385 _fx_project_stereographic_mirror $mirror 41386 {u=0$_is_preview?min(w,h):max(w,h);[u,u,1,s]},"* 41387 const W = w; 41388 const H = h; 41389 "$init" 41390 X = x - centerx; 41391 Y = y - centery; 41392 theta = atan2(Y,X); 41393 beta = ((X^2 + Y^2)/R^2)^dilation; 41394 z = R*(beta - 1)/(beta + 1); 41395 phi = asin(z/R); 41396 theta = ((theta - theta0)*w#0/pi2)%w#0; 41397 phi = (h#0*(phi/pi + 0.5))%h#0; 41398 I(#0,theta,phi)" 41399 fi 41400 k. endl done um _fx_project_stereographic 41401 41402 if $_is_preview 41403 line $centerx%,$centery%,$radangx%,$radangy%,0.75,0xF0F0F0F0,255,255,255,255 41404 line $centerx%,$centery%,$radangx%,$radangy%,0.75,0x0F0F0F0F,0,0,0,255 41405 fi 41406 u $status 41407 41408fx_project_stereographic_preview : 41409 _is_preview=1 41410 fx_project_stereographic $"*" 41411 41412#@gui Symmetrize : fx_symmetrize, fx_symmetrize_preview(1) 41413#@gui : Point 1 = point(50,50,0,1,0,255,0,170,10) 41414#@gui : Point 2 = point(50,75,-1,1,255,255,0,170,10) 41415#@gui : Angle = float(0,-180,180) 41416#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 41417#@gui : Type = choice("Symmetry","Antisymmetry") 41418#@gui : Swap Sides = bool(0) 41419#@gui : sep = separator() 41420#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/06/11</i>.</small>") 41421fx_symmetrize : 41422 if !$6 to_a fi 41423 angle={isnan($3)?$5:atan2($4-$2,$3-$1)*180/pi} 41424 symmetrize $1%,$2%,$angle,${6-8} 41425 41426fx_symmetrize_preview : 41427 fx_symmetrize $* 41428 rr2d ${-gui_preview_wh},0,1 41429 u,v={angle=isnan($3)?$5*pi/180:atan2($4-$2,$3-$1);[cos(angle),sin(angle)]} 41430 repeat $! l[$>] 41431 x0,y0,x1,y1={V=[$u,$v];([${1,2},${1,2}]+10000*[V,-V])*([w,h,w,h]-1)%} 41432 line $x0,$y0,$x1,$y1,1,0x0F0F0F0F,0,0,0,255 41433 line $x0,$y0,$x1,$y1,1,0xF0F0F0F0,255 41434 endl done 41435 41436#@gui Textured Glass : fx_textured_glass, fx_textured_glass_preview(0) 41437#@gui : X-Amplitude = float(40,0,400) 41438#@gui : Y-Amplitude = float(40,0,400) 41439#@gui : X-Smoothness = float(1,0,5) 41440#@gui : Y-Smoothness = float(1,0,5) 41441#@gui : Edge Attenuation = float(0,0,1) 41442#@gui : Edge Influence = float(2,0,10) 41443#@gui : Noise Scale = int(0,0,16) 41444#@gui : sep = separator() 41445#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41446#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41447#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41448#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41449#@gui : sep = separator() 41450#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/21/11</i>.</small>") 41451fx_textured_glass : 41452 repeat $! l[$>] 41453 100%,100%,1,1 41454 if $7 plasma. 1,1,$7 else rand. 0,1 fi 41455 g. xy 41456 if $5 41457 +gradient_norm... +. 1 b. $6 ^. -$5 41458 *... . *[-2,-1] 41459 fi 41460 blur_xy[-2,-1] $3,$4 41461 *.. {-2,$1/max(abs(im),abs(iM))} 41462 *. {$2/max(abs(im),abs(iM))} 41463 a[-2,-1] c 41464 warp.. .,1,1 rm. 41465 endl done 41466 41467fx_textured_glass_preview : 41468 gui_split_preview "fx_textured_glass $*",${-3--1} 41469 41470#@gui Twirl : fx_twirl, fx_twirl(1) 41471#@gui : Amplitude = float(1,-5,5) 41472#@gui : Center (%) = point(50,50,0,1) 41473#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 41474#@gui : sep = separator() 41475#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41476fx_twirl : 41477 if !$4 to_a fi 41478 twirl $1,$2%,$3%,$4 41479 41480#@gui Warp [Interactive] : fx_warp_interactive, fx_warp_interactive_preview(1) 41481#@gui : Preview Precision = choice{1,"Coarsest (faster)","Coarse","Normal","Fine","Finest (slower)"} 41482#@gui : sep = separator() 41483#@gui : note = note{"<small><b>Pre-defined keypoints</b></small>"} 41484#@gui : Regular Grid = int(2,2,10) 41485#@gui : Contours = int(0,0,32) 41486#@gui : Keypoints = value(-1) 41487#@gui : sep = separator() 41488#@gui : note = note{"<b>Instructions:</b>"} 41489#@gui : note = note{" 41490#@gui : Use mouse to add/move/delete keypoints over the interactive window that will appear, 41491#@gui : in order to create the deformation map.\n\n 41492#@gui : - <b>Left mouse button</b>: Add and move keypoint.\n 41493#@gui : - <b>Right mouse button</b>: Delete keypoint.\n 41494#@gui : - Key <b>SPACE</b> or <b>middle mouse button</b>: Show/hide keypoints.\n 41495#@gui : - Key <b>TAB</b>: Change keypoint radius.\n 41496#@gui : - Key <b>SHIFT</b>: Toggle to original image.\n 41497#@gui : - Key <b>R</b>: Reset keypoints.\n 41498#@gui : - Keys <b>ESC</b>, <b>ENTER</b> or <b>Q</b>: Process fullres and exit. 41499#@gui : "} 41500#@gui : sep = separator() 41501#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/04/08</i>.</small>") 41502fx_warp_interactive : 41503 if [$4][0]!=-1 __x_warp_keypoints=$4 fi 41504 x_warp $2,$2,$3,$1 41505 u "{$1}{$2}{$3}{"$__x_warp_keypoints"}" 41506 41507fx_warp_interactive_preview : 41508 if [$4][0]!=-1 __x_warp_keypoints=$4 fi 41509 repeat $! l[$>] 41510 rr2d $_preview_width,$_preview_height,0,3 to_color drgba 41511 if narg($__x_warp_keypoints) ($__x_warp_keypoints) r. 1,{w/4},1,4,-1 41512 else 41513 41514 # Keypoints located on regular grid. 41515 nbp,nbq=$2,$2 41516 1,{$nbp*$nbq},1,4,"const nbp = "$nbp"; const nbq = "$nbq"; 41517 p = y%nbp; 41518 q = int(y/nbp); 41519 x = p*100/(nbp - 1); 41520 y = q*100/(nbq - 1); 41521 [ x,y,x,y ]" 41522 41523 # Keypoints located on contours. 41524 nbc=$3 41525 if $nbc>0 41526 +b[0] 0.5 gradient_norm. sqrt. {round([w,h]/4)} gaussian. 20% 41527 1,$nbc,1,4,"> 41528 begin(ref(crop(#-1),gauss)); 41529 st = stats(#-2); 41530 iM = st[1]; 41531 xM = st[8]; 41532 yM = st[9]; 41533 img = vector(#w#-1*h#-1,-iM); 41534 draw(#-2,img,xM - w#-1/2,yM - h#-1/2,0,0,w#-1,h#-1,1,1,-1,gauss); 41535 nxyM = [ xM,yM ]*100/([w#-2,h#-2]-1); 41536 [ nxyM,nxyM ]" 41537 rm[-3,-2] 41538 a[-2,-1] y 41539 fi 41540 fi 41541 41542 +_x_warp_rbf. {0,round([w,h]/4)} *. 4 r. [0],[0],1,100%,3 +. '[x,y]' warp[0] .,0,1,3 rm. 41543 41544 eval. "* 41545 begin( 41546 col1 = [ 64,200,255 ]; 41547 const radius1 = 3; 41548 const radius2 = radius1 + 2; 41549 fact = ([ w#0,h#0 ] - 1)% 41550 ); 41551 X = (I)[0,2]*fact; 41552 ellipse(#0,X,radius2,radius2,0,1,0); 41553 ellipse(#0,X,radius1,radius1,0,1,col1); I" 41554 rm. 41555 41556 if narg($__x_warp_keypoints) 41557 0 t. "Keypoints from previous\nrun have been saved",0,0,24,1,255 41558 frame. 5,5,0 +dilate_circ. 5 a[-2,-1] c blend alpha 41559 fi 41560 endl done 41561 41562#@gui Water : water, water(0) 41563#@gui : Amplitude = float(30,0,300) 41564#@gui : Smoothness = float(1.5,0,4) 41565#@gui : Angle = float(45,0,180) 41566#@gui : sep = separator() 41567#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/07/10</i>.</small>") 41568 41569#@gui Wave : wave, wave(1) 41570#@gui : Amplitude = float(10,0,30) 41571#@gui : Frequency = float(0.4,0,2) 41572#@gui : Center (%) = point(50,50,0,1,255,255,255,170,10) 41573#@gui : sep = separator() 41574#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41575 41576#@gui Wind : fx_wind, fx_wind_preview(0) 41577#@gui : Amplitude = int(20,0,500) 41578#@gui : Angle = float(0,0,360) 41579#@gui : Attenuation = float(0.7,0,1) 41580#@gui : Threshold = float(20,0,100) 41581#@gui : Mode = choice(1,"Darker","Brighter") 41582#@gui : sep = separator() 41583#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41584#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41585#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41586#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41587#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41588#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41589#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41590#@gui : Value Action = choice("None","Cut","Normalize") 41591#@gui : sep = separator() 41592#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41593#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41594#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41595#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41596#@gui : sep = separator() 41597#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/13/07</i>.</small>") 41598fx_wind : 41599 if !$5 negate fi 41600 ac "wind ${1-4}",$6,$7 41601 if !$5 negate fi 41602 41603fx_wind_preview : 41604 gui_split_preview "fx_wind $*",${-3--1} 41605 41606#@gui Zoom : fx_zoom, fx_zoom(1) 41607#@gui : Factor = float(2,0.01,10) 41608#@gui : Center (%) = point(50,50,0,1,255) 41609#@gui : Boundary = choice(0,"Transparent","Nearest","Periodic","Mirror") 41610#@gui : sep = separator() 41611#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41612fx_zoom : 41613 if !$4" && "$1<1 to_a fi 41614 zoom $1,{$2%},{$3%},0,$4 41615 41616 41617#@gui ____<b>Degradations</b> 41618#----------------------------- 41619 41620#@gui Add Grain : fx_simulate_grain, fx_simulate_grain_preview(0) 41621#@gui : Preset = choice{"Orwo NP20-GDR","Kodak TMAX 400","Kodak TMAX 3200","Kodak TRI-X 1600","Unknown"} 41622#@gui : Blend Mode = choice(1,"Alpha","Grain Merge","Hard Light","Overlay","Soft Light","Grain Only") 41623#@gui : Opacity = float(0.2,0,1) 41624#@gui : Scale = float(100,30,200) 41625#@gui : Colored Grain = bool() 41626#@gui : sep = separator() 41627#@gui : Brightness (%) = float(0,-100,100) 41628#@gui : Contrast (%) = float(0,-100,100) 41629#@gui : Gamma (%) = float(0,-100,100) 41630#@gui : Hue (%) = float(0,-100,100) 41631#@gui : Saturation (%) = float(0,-100,100) 41632#@gui : sep = separator() 41633#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41634#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41635#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41636#@gui : Preview Grain Alone = bool() 41637#@gui : sep = separator() 41638#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/02/08</i>.</small>") 41639fx_simulate_grain : 41640 __fx_simulate_grain ${arg\ {1+$1},${-_fx_simulate_grain}},${2-10},0,0 41641 41642_fx_simulate_grain : 41643 u orwo_np20,kodak_tmax400,kodak_tmax3200,kodak_trix1600,unknown 41644 41645fx_simulate_grain_preview : 41646 gui_split_preview "_fx_simulate_grain_preview $*",$-2 41647 41648_fx_simulate_grain_preview : 41649 __fx_simulate_grain ${arg\ {1+$1},${-_fx_simulate_grain}},${2-12} 41650 41651__fx_simulate_grain : 41652 bm0=alpha bm1=grainmerge bm2=hardlight bm3=overlay bm4=softlight bm5=alpha 41653 if isfile(['{/${-path_cache}grain_$1.cimgz}']) i ${-path_cache}grain_$1.cimgz 41654 else i https://gmic.eu/data_film_presets/grain_$1.cimgz o. ${-path_cache}grain_$1.cimgz 41655 fi 41656 41657 repeat $!-1 l[$>,-1] split_opacity[0] 41658 +syntexturize. {0,max(10,100*w/$4)},{0,max(10,100*h/$4)} 41659 if $5 +syntexturize.. {w},{h} +syntexturize... {w},{h} a[-3--1] c fi 41660 r. {0,w},{0,h},1,100%,5 c. 0,255 41661 adjust_colors. ${6-10} 41662 if $12 k[0,-1] rv 41663 else blend[0,-1] ${bm$2},{if($2<=4,$3,1)} 41664 fi 41665 a[^-1] c endl done rm. 41666 41667#@gui Blur [Angular] : fx_blur_angular, fx_blur_angular_preview(1) 41668#@gui : Amplitude (%) = float(2,0,20) 41669#@gui : Center (%) = point(50,50,0,1) 41670#@gui : Sharpness = float(0,0,500) 41671#@gui : Preview Guides = bool(1) 41672#@gui : sep = separator() 41673#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41674#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41675#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41676#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41677#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41678#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41679#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41680#@gui : Value Action = choice("None","Cut","Normalize") 41681#@gui : sep = separator() 41682#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/16/01</i>.</small>") 41683fx_blur_angular : 41684 ac "blur_angular $1%,$2%,$3% sharpen $4",$6,$7 41685 41686fx_blur_angular_preview : 41687 fx_blur_angular $* 41688 if $5 41689 line 0,$3%,100%,$3%,0.5,0xF0F0F0F0,255 line 0,$3%,100%,$3%,0.5,0x0F0F0F0F,0 41690 line $2%,0,$2%,100%,0.5,0xF0F0F0F0,255 line $2%,0,$2%,100%,0.5,0x0F0F0F0F,0 41691 fi 41692 41693#@gui Blur [Bloom] : fx_blur_bloom, fx_blur_bloom_preview(0) 41694#@gui : Amplitude = float(1,0,10) 41695#@gui : Ratio = float(2,0,5) 41696#@gui : Iterations = int(5,0,100) 41697#@gui : Operator = choice("Add","Max","Min") 41698#@gui : Kernel = choice(1,"Deriche","Gaussian","Box","Triangle","Quadratic") 41699#@gui : Normalize Scales = bool(0) 41700#@gui : Anisotropy = float(0,0,1) 41701#@gui : Angle = float(0,-180,180) 41702#@gui : note = note("Parameter <i>Angle</i> is only active when <i>Anisotropy</i>>0") 41703#@gui : sep = separator() 41704#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41705#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41706#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41707#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41708#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41709#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41710#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41711#@gui : sep = separator() 41712#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41713#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41714#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41715#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41716#@gui : sep = separator() 41717#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/03/02</i>.</small>") 41718fx_blur_bloom : 41719 op=${"arg 1+$4,+,max,min"} 41720 if !$7 ac "blur_bloom ${1-3},"$op",${5-6},xy",$9 41721 else 41722 wh={[w,h]} 41723 rotate $8,2,1 41724 ac "blur_bloom ${1-3},"$op",${5-6},x blur_bloom {$1*(1-$7)},${2-3},"$op",${5-6},y",$9 41725 rotate {-$8},2,1 41726 r $wh,1,100%,0,0,0.5,0.5 c 0,255 41727 fi 41728 41729fx_blur_bloom_preview : 41730 gui_split_preview "fx_blur_bloom $*",${-3--1} 41731 41732#@gui Blur [Depth-of-Field] : fx_blur_dof, fx_blur_dof_preview(1) 41733#@gui : Blur Amplitude = float(3,0,20) 41734#@gui : Blur Precision = int(16,2,64) 41735#@gui : Depth-of-Field Type = choice{"Gaussian","User-Defined (Bottom Layer)"} 41736#@gui : Invert Blur = bool(0) 41737#@gui : sep = separator() 41738#@gui : note = note("<small><b>Gaussian depth-of-field:</b></small>") 41739#@gui : Center (%) = point(50,50,0,0,255) 41740#@gui : First Radius = float(30,0,200) 41741#@gui : Second Radius = float(30,0,200) 41742#@gui : Angle = float(0,0,180) 41743#@gui : Sharpness = float(1,0,8) 41744#@gui : Preview Guides = bool(1) 41745#@gui : sep = separator() 41746#@gui : note = note("<small><b>User-defined depth-of-field:</b></small>") 41747#@gui : Gamma = float(0,-2,2) 41748#@gui : note = note("<small>You can specify your own depth-of-field image, as a <b>bottom layer</b> image 41749#@gui : whose luminance encodes the depth for each pixel. 41750#@gui : Don't forget to modify the <b>Input layers</b> combo-box to make this layer active for the filter.</small>") 41751#@gui : sep = separator() 41752#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/25/02</i>.</small>") 41753fx_blur_dof : 41754 _$0 ${1-10},0,$12 41755 41756fx_blur_dof_preview : 41757 _fx_blur_dof $* 41758 41759_fx_blur_dof : 41760 if !$3 # Gaussian DOF. 41761 repeat $! l[$>] if $11 drgba fi split_opacity l[0] 41762 rmax={(w*w+h*h)^0.5} R={$7*$rmax/100} r={$8*$rmax/100} 41763 t={$9*pi/180} u={cos($t)} v={sin($t)} 41764 l1={($rmax/(1e-8+$R))^2} l2={($rmax/(1e-8+$r))^2} 41765 a={$l1*($u)^2+$l2*($v)^2} b={$u*$v*($l1-$l2)} c={$l1*($v)^2+$l2*($u)^2} 41766 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)' 41767 -[1] 1 *[1] -$1 ms={im} Ms={iM} 41768 41769 if $11 # With preview of guides. 41770 +isoline3d[1] {0.1*$1} col3d. 255,255,0 41771 +isoline3d[1] {0.5*$1} col3d. 255,128,0 41772 +3d[-2--1] 41773 __fx_dof_blur[0,1] $2,$ms,$Ms,$4 41774 [0],[0],1,3 j3d. ..,0,0,0,1,1,0,0 rm.. 41775 circle. $5%,$6%,3,1,255,255,255 41776 +compose_channels. + !=. 0 dilate. 3 41777 j[0] ..,0,0,0,0,0.5,.,1 rm[-2,-1] 41778 else __fx_dof_blur[0,1] $2,$ms,$Ms,$4 # Without preview. 41779 fi 41780 endl if $11 k[0] fi a c endl done 41781 elif $!>1 # User-defined DOF (as bottom layer). 41782 luminance. n. 0,1 ^. {10^$12} 41783 repeat $!-1 +r. {$>,w},{$>,h},1,1,3 l[$>,-1] split_opacity[0] 41784 __fx_dof_blur[0,-1] $2,0,$1,$4 41785 a c endl done rm. 41786 else drgba to "Depth-of-field (bottom layer) is missing !",2,2,13,2,1,255 41787 fi 41788 41789# Render DOF blur (generic) 41790# [0] = Input image 41791# [1] = continuous DOF field (with same size as [0]). 41792# $1 = nb quantization levels. 41793# $2 = minimal blur level. 41794# $3 = maximal blur level. 41795# $4 = invert blur. 41796__fx_dof_blur : 41797 n[1] 0,{$1-1} round[1] 41798 [0],[0],1,{0,s+1} 41799 s=0 41800 repeat $1 41801 +==[1] {if($4,$<,$>)} b. 2% 41802 j.. [0],0,0,0,0,-1,.,1 41803 j.. .,0,0,0,100%,-1 41804 rm. 41805 ns={$2+($3-$2)*($>+1)/($1-1)} 41806 b[0] {sqrt($ns^2-$s^2)}% 41807 s=$ns 41808 done 41809 s. c,{-s+1} /[-2,-1] rm[0,1] 41810 41811#@gui Blur [Gaussian] : fx_gaussian_blur, fx_gaussian_blur_preview(0) 41812#@gui : XY-Amplitude = float(3,0,20) 41813#@gui : X-Amplitude = float(0,0,20) 41814#@gui : Y-Amplitude = float(0,0,20) 41815#@gui : Boundary = choice(1,"Black","Nearest") 41816#@gui : sep = separator() 41817#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41818#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41819#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41820#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41821#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41822#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41823#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41824#@gui : Value Action = choice("None","Cut","Normalize") 41825#@gui : sep = separator() 41826#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41827#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41828#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41829#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41830#@gui : sep = separator() 41831#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41832_fx_gaussian_blur : 41833 b $1,$4 41834 if $2>0 repeat $! l. s y b $2,$4 a y endl mv. 0 done fi 41835 if $3>0 repeat $! l. s x b $3,$4 a x endl mv. 0 done fi 41836 41837fx_gaussian_blur : 41838 ac "_fx_gaussian_blur $1,$2,$3,$4",$5,$6 41839 41840fx_gaussian_blur_preview : 41841 gui_split_preview "fx_gaussian_blur $*",${-3--1} 41842 41843#@gui Blur [Glow] : fx_glow, fx_glow_preview(0) 41844#@gui : Amplitude = float(6,0,20) 41845#@gui : sep = separator() 41846#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41847#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41848#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41849#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41850#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41851#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41852#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41853#@gui : Value Action = choice("None","Cut","Normalize") 41854#@gui : sep = separator() 41855#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41856#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41857#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41858#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41859#@gui : sep = separator() 41860#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41861fx_glow : 41862 ac "glow $1",$2,$3 41863 41864fx_glow_preview : 41865 gui_split_preview "fx_glow $*",${-3--1} 41866 41867#@gui Blur [Linear] : fx_blur_linear, fx_blur_linear_preview(1) 41868#@gui : Tangent Radius = float(10,0,100) 41869#@gui : Orthogonal Radius = float(0.5,0,100) 41870#@gui : Angle = float(0,0,180) 41871#@gui : Sharpness = float(0,0,500) 41872#@gui : Boundary = choice(1,"Black","Nearest") 41873#@gui : sep = separator() 41874#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41875#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41876#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41877#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41878#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41879#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41880#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41881#@gui : Value Action = choice("None","Cut","Normalize") 41882#@gui : sep = separator() 41883#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41884#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41885#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41886#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41887#@gui : sep = separator() 41888#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 41889fx_blur_linear : 41890 ac "blur_linear $1,{$2*$1/100},$3,$5 sharpen $4",$6,$7 41891 41892fx_blur_linear_preview : 41893 gui_split_preview "fx_blur_linear $*",${-3--1} 41894 41895#@gui Blur [Multidirectional] : fx_blur_multidirectional, fx_blur_multidirectional_preview(0) 41896#@gui : Number of Orientations = int(5,1,16) 41897#@gui : Reference Angle (deg.) = float(0,0,360) 41898#@gui : Angle Range (deg.) = float(360,0,360) 41899#@gui : sep = separator() 41900#@gui : Smoothness = float(150,0,1024) 41901#@gui : Kernel type = choice(0,"Mono-Directional","Bi-Directional") 41902#@gui : Boundary conditions = choice(1,"Dirichlet","Neumann","Periodic","Mirror") 41903#@gui : Sharpness = float(0,0,1000) 41904#@gui : Blend Mode = choice{2,"Min","Max","Average","Edges-0.5 (beware: memory-consuming!)", 41905#@gui : "Edges-1 (beware: memory-consuming!)","Edges-2 (beware: memory-consuming!)", 41906#@gui : "Median (beware: memory-consuming!)"} 41907#@gui : Boost Contrast = float(2,0,32) 41908#@gui : sep = separator() 41909#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41910#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41911#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41912#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41913#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41914#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41915#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41916#@gui : sep = separator() 41917#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 41918#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 41919#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 41920#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 41921#@gui : sep = separator() 41922#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/09/11</i>.</small>") 41923_fx_blur_multidirectional : 41924 nb_orientations,\ 41925 angle_ref,\ 41926 angle_range,\ 41927 smoothness,\ 41928 kernel,\ 41929 boundary_conditions,\ 41930 sharpness,\ 41931 blend_mode,\ 41932 contrast=${1-9} 41933 repeat $! l[$>] 41934 # If no median blend, blend step by step in an accumulator to reduce memory usage. 41935 if $blend_mode<3 +f {$blend_mode?0:inf} fi 41936 41937 repeat $nb_orientations 41938 angle={$angle_ref+$angle_range*($>/$nb_orientations-0.5)} 41939 41940 # Kernel definition. 41941 $smoothness,1 gaussian. 20%,0.1 41942 if !$kernel f. "x>w/2?i:0" fi 41943 rotate. $angle,1 # /. {is} 41944 41945 # Blur and blend. 41946 +convolve_fft[0] .,$boundary_conditions rm.. n. 0,255 sharpen. $sharpness 41947 if $blend_mode<3 ${arg\ 1+$blend_mode,min,max,+}[1,-1] fi 41948 done 41949 rm[0] 41950 41951 if $blend_mode==6 blend_median 41952 elif $blend_mode>2 blend_edges {arg($blend_mode-2,0.5,1,2)} 41953 fi 41954 41955 n 0,255 ac "normalize_local "$contrast,hsl_l 41956 endl done 41957 41958fx_blur_multidirectional : 41959 ac "_fx_blur_multidirectional ${1-9}",$10 41960 41961fx_blur_multidirectional_preview : 41962 gui_split_preview "fx_blur_multidirectional $*",${-3--1} 41963 41964#@gui Blur [Radial] : fx_blur_radial, fx_blur_radial_preview(1) 41965#@gui : Amplitude = float(3,0,20) 41966#@gui : Center (%) = point(50,50,0,1) 41967#@gui : Sharpness = float(0,0,500) 41968#@gui : Preview Guides = bool(1) 41969#@gui : sep = separator() 41970#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 41971#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 41972#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 41973#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 41974#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 41975#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 41976#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 41977#@gui : Value Action = choice("None","Cut","Normalize") 41978#@gui : sep = separator() 41979#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/16/01</i>.</small>") 41980fx_blur_radial : 41981 ac "blur_radial $1%,$2%,$3% sharpen $4",$6,$7 41982 41983fx_blur_radial_preview : 41984 fx_blur_radial $* 41985 if $5 41986 line 0,$3%,100%,$3%,0.5,0xF0F0F0F0,255 line 0,$3%,100%,$3%,0.5,0x0F0F0F0F,0 41987 line $2%,0,$2%,100%,0.5,0xF0F0F0F0,255 line $2%,0,$2%,100%,0.5,0x0F0F0F0F,0 41988 fi 41989 41990#@gui Chromatic Aberrations : fx_chromatic_aberrations, fx_chromatic_aberrations_preview(0) 41991#@gui : Primary Color = color(255,0,0) 41992#@gui : X-Shift = float(2,-16,16) 41993#@gui : Y-Shift = float(2,-16,16) 41994#@gui : sep = separator() 41995#@gui : Secondary Color = color(0,255,0) 41996#@gui : X-Shift (px) = float(0,-16,16) 41997#@gui : Y-Shift (px) = float(0,-16,16) 41998#@gui : sep = separator() 41999#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42000#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42001#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42002#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42003#@gui : sep = separator() 42004#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/05/07</i>.</small>") 42005fx_chromatic_aberrations : 42006 42007 # Compute orthonormal color basis. 42008 l[] 42009 (${1-3}) (${6-8}) y c orientation[0] 42010 +*[0,1] +*[0] {is} -[1,3] rm[2] orientation[1] 42011 _cross3d {0,^},{^} y x a y 42012 M={^} transpose Minv={^} rm 42013 endl 42014 42015 # Shift images. 42016 repeat $! l[$>] to_color split_opacity l[0] 42017 mix_rgb $M 42018 s c 42019 100%,100%,1,2 fc. {($9-$4)/2},{($10-$5)/2} warp[0] .,1,2,1 rm. 42020 100%,100%,1,2 fc. {($4-$9)/2},{($5-$10)/2} warp[1] .,1,2,1 rm. 42021 100%,100%,1,2 fc. {(-$4-$9)/2},{(-$5-$10)/2} warp[2] .,1,2,1 rm. 42022 a c 42023 mix_rgb $Minv 42024 endl a c endl done 42025 c 0,255 42026 42027fx_chromatic_aberrations_preview : 42028 gui_split_preview "fx_chromatic_aberrations $*",${-3--1} 42029 42030#@gui Dirty : fx_dirty, fx_dirty_preview(0) 42031#@gui : Amplitude = float(30,0,100) 42032#@gui : Monochrome = bool(1) 42033#@gui : sep = separator() 42034#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42035#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42036#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42037#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42038#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42039#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42040#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42041#@gui : Value Action = choice("None","Cut","Normalize") 42042#@gui : sep = separator() 42043#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42044#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42045#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42046#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42047#@gui : sep = separator() 42048#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/24/11</i>.</small>") 42049fx_dirty : 42050 ac "_fx_dirty ${1-2}",$3,$4 42051 42052fx_dirty_preview : 42053 gui_split_preview "fx_dirty ${1--2}",${-3--1} 42054 42055_fx_dirty : 42056 repeat $! l[$>] 42057 dct 100%,100%,1,{if($2,1,s)} noise. $1,2 42058 ==. 0 point. 0,0,0,1,1 42059 * idct c 0,255 42060 endl done 42061 42062#@gui Flip & Rotate Blocs : fx_flip_blocs,fx_flip_blocs_preview(0) 42063#@gui : X-Size (px) = int(4,1,128) 42064#@gui : Y-Size (px) = int(4,1,128) 42065#@gui : Flip = choice(3,"None","X-axis","Y-axis","XY-axes") 42066#@gui : Rotate = choice(1,"-90 deg.","0 deg.","90 deg.") 42067#@gui : sep = separator() 42068#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42069#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42070#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42071#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42072#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42073#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42074#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42075#@gui : sep = separator() 42076#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42077#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42078#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42079#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42080#@gui : sep = separator() 42081#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/01/09</i>.</small>") 42082fx_flip_blocs : 42083 repeat $! l[$>] 42084 if $5 ac "_fx_flip_blocs ${1-4}",$5 42085 else _fx_flip_blocs ${1-4} 42086 fi 42087 endl done 42088 42089_fx_flip_blocs : 42090 if ($3%2)" && "$1>1 s x,-$1 mirror x a x fi 42091 if ($3>1)" && "$2>1 s y,-$2 mirror y a y fi 42092 if $4!=1" && "$1>1" && "$2>1 42093 s y,-$2 N=$! 42094 s x,-$1 M={$!/$N} 42095 ap "rotate {($4-1)*90}" 42096 append_tiles $M,$N 42097 fi 42098 42099fx_flip_blocs_preview : 42100 gui_split_preview "fx_flip_blocs $*",${-3--1} 42101 42102#@gui JPEG Artefacts : fx_jpeg_artefacts, fx_jpeg_artefacts_preview(0) 42103#@gui : note = note("<small>This filter simulates the JPEG compression artifacts, 42104#@gui : using DCT quantization on 8x8 blocs.</small>") 42105#@gui : Quality (%) = int(50,1,100) 42106#@gui : sep = separator() 42107#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42108#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42109#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42110#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42111#@gui : sep = separator() 42112#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/05/07</i>.</small>") 42113fx_jpeg_artefacts : 42114 42115 # Input all 8x8 DCT and iDCT kernels. 42116 # (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) 42117 base642img[] \ 42118"MSBmbG9hdCBsaXR0bGVfZW5kaWFuCjggOCA2NCAxICMyMjIyCnic5Vs9q51FEC60kKtWMYpaCirYKCoI767iR6UoSangtdM/EAM2Fgab2FhaWdgIUXO"\ 42119"qVO8sXEHBVDFia6kgCBaCQSyu+5w8c3nv5p55Bg+3uSmGs19nP2Z2Zt752P39/bJ/G8PHF5+qD1y4v77+yNWyeulegPWy9bbW+9pJ7z9XH6s/f3KxdL"\ 42120"BeRr2hjDb0nfR+4OZyxwlw8UbHS4f1nehtBTg66f3kAyOU261OfDTiA/ehEV91ga8T208+cDlg5JNKPiknvR8ykfKwLuRlo7y0k96PegS8MxsB80RAn"\ 42121"ROBRYC9R0AZtxF45o1w+cXz9fHvztTnP7y7nv7z5dLBern1NvTht37/75P17Qt/lOsPPQqwXrbeth6D/6Hv3F2fl2/++WXqMPfyegzmwZz439e9755f"\ 42122"HwbMvTxjHqwFQBlt6MMYjMV/8F/MgbkwJ+bGGlgLa2Jt7AF7wRjMg/+hD3vG3nmGxr0Y5/S+euPGe/XVJ/ZKB+vlBkAZbeh77ctX6re/f1E6WC83AMp"\ 42123"oQ9+Zd++oV6+8WTpYLzcAymhD30+fPlee/e2zqcPcywZAGW3oO6J+aPw437jeuJ9xv+N5xvMCD/d1vABPL3QcdVjjpbcV4rb+2PGK8jsdxx3QjrZCvJ"\ 42124"evOl2A3/c7jTqs8dvbJtKkgK7A/eU+rsMEGoDOpJehjDb0YQzG4j+kpWEuzIm5sQbWwpqkc8NesCfsDXvEXrFn3oGGs+BMOBvOiLPizPgP+fzgW3Gsu"\ 42125"87wb4mxTj53fixjfeDxo+qb2suC/2+Z1+ub9uX1TefyOundSG/HlxFfjfRupHclvo34dno30tvpNZNeRnob6V1I75n0nknvQnr7fZl4XybSu5Lexvs2"\ 42126"8b45vSvp7fe18L4W0ruS3n7fC+97JV808oWRLyr5ppCvGvnKyFeVfFfIl418aeTLSr4t5GsjX8/ka+f76Yj6ofHjfON6437G/Y7nGc/rMtZlJfVBoz5"\ 42127"weXrAS9QHjfrAKI+N8tj1gVEfuDyfKc+N+sCoD2bqg4n6oPia1AeuTwr1SaU+KNQHE/VRoT5yfVBd9lCfVeoz1wfVdZPbSJvAv6ECsAjc5vq/oOZX+1"\ 42128"Pncx3nusp1zkJ3lL1+p37gXcad7GXb490CoIw212MYi//4XcNcmNPvNdbCmn4vo341v9qfOt8HH71V/7rzSulgvYx6Qxlt3vfg36cBxnZDGW3+v6F+a"\ 42129"Pw4n1pv7Ffzq/2p9YCb6x0nwMXZjpcOa7z3trUcAW6f6TgFLv07BDjvbRNwDEAZbf5dgrH4zx5lEebCnJgba2AtrOlyK+pX86v9qfO5LeQ20lgfeHzk"\ 42130"+RK0L30ut8ybrav51f7UOsRHIz6cHkZ6NOLTiM9Cesykh5EehfQw0mMiPQrpWUnPRnoU0qOqfjW/2p86H/nA5YDzbCWfFPKR85mRz5zvyxH1Q+PH+dR"\ 42131"6Y7+aX+1PrUd52yhvG+Vlo7w0ylujvDXKW6O8nSlvC+VtobwulNcT5W2lvHV5Xynvi+pX86v9qfMp+x6+ogiUfU0fVAQlAuWfgF8rAuUfUPb9Kdrnl/"\ 42132"p32E7/VuswXaJ93vvKKrCvV7Qhdm/aCQf2H77bd29+m69tMpTR5vYfxuI/+O8q8E9g7VP0L2BP2Bv2eIn+hVP85o/8A9QxZW9h37ucQd+1fkee7veow"\ 42133"9TLBYAy2q5Rr0T29dmF/U55d2C/uz4a6ofGK//EuJ9xv+N5xvMu7XvgfHew74Ez4BV4Bo6BW+B1h/a529erhX29WtjXmBPf9+g732ncYU1XfN9jLQDK"\ 42134"aEMfxmAs/rNL2w5zrRb+idXCP4E9YC/YE/aGPWKvO/QvLP0DXO+Qf0DZ9+Rz5ycb68q+Hnh85HkL2m3B/xvt+E378rryD+wG9j1wRXqXnYV9zvuAvsl"\ 42135"5dLSvSa9KelfS20jvifQupHcjvQvvy7z87+oI/4TLFtLbdhb+Bd4H3Nd5N/APYL29hb3s37P+nYA+8lUhX03kKyPfzcq+9m+Qswv7fcH3dkT90Hjlnx"\ 42136"j3M+53PM94XmXfU55OlKeF+qBQH0xL+xo0WQ32NeV5oTx3fVDcN+Q+HuqDRn1g1Afz0j+BuVeDf4L6aKY+MuoDoz6YlX8gESO3LWHbGP2xrp+InzfGS"\ 42137"w58kxjLeEpN9G8bvz/W9RPx823j7dvG7491/UT8fB07Zbx0rZsYT/VvZ9W/bfz+WNdPxMu3jbNvG68/1vUT8XMjvmxBr0J8lkT/tvH7Y10/ET/fNt6+"\ 42138"bfz+WNdPxM+N8tS/Pz3uZQt5GvVvG78/1vUT9nccP9f2t8ohCO3zhP8h9A8o/0PC/g7t+4T9HfoXlH2e8D+E/gHlf0jY36F9n7C/Q/+Css8T/ofQP6D"\ 42139"8Dwn7O7TvE/Z36F9Q9nnC/xD6B5T/IWF/h/Z9wv4O/QvKPk/4H0L/gPI/JOzv0L5P2N+hf0HZ5wn/Q+gfUP6HhP0d2vcJ+zv0Lyj7POF/CP0Dyv+QsL"\ 42140"9D+z5hf4f+BWWfJ/wPoX9A+R8S8XMVo1f5Ayp+r/IHwvnV/tT5EvFzFb9X+QMqfq/yB8L5E/kD4fkS8XMVv1f5Ayp+r/IHVL6Ayh8I10vEz1X8XuUPq"\ 42141"Pi9yh8I50/kD4TnS8TPVbxe5Q+o+L3KH1B5Aip/IFwnET9X8XuVP6Di9yp/IJw/kT8Qni8RP1fxe5U/oOL3Kn9A5Quo/IFwvUT8XMXvVf6Ait+r/IFw"\ 42142"/kT+QHg+lZ+fyL8P7XvlP1D2u/IPJN4fhO8LVH5+Iv8+tO9V/n3i/UHoH0i8PwjfF6j8/ET+ffg+QPkPEu8Pwvz+xPuD8H2Bys9P5N+H7wNU/n3i/UG"\ 42143"Y3594fxC+L1D5+Yn8+9C+V/4DZb8r/0Di/UH4vkDl5yfy78P3ASr/PvH+IMzvT7w/CN8XqPz8RP59+D5A+Q8S7w/C/P7E+4PwfYHKz0/k34f2vcq/T7"\ 42144"w/CP0DifcH4fuC/wBiGjbi" 42145 42146 base642img[] \ 42147"MSBmbG9hdCBsaXR0bGVfZW5kaWFuCjggOCA2NCAxICMyOTE3CnicjVsxjybFEV0JB4iDyHdYhhAJIznBAiSS6ZbBkb3YS4glHOI/4ENyQuDTOsAJIRG"\ 42148"BEyP7di+6cKo5yZY4J95DmxKChIREYMln5ODo1/OqXd9KU1XZzX37Tc+rqqlX9aq+o6Ojevr+T+rvlh/VH9x6uh716189d79c/un9cue1pwo+O//pu/"\ 42149"Xhw9/WF/5+Mv62vnet/vzHn5Qb37xe8D189vs//Lr+4i8/G/d5853H6r+/d7d89sGrBffE9/DZP/734jjjN7e+Lp989efy4Jnny6NHj4o9H9e/NOfj3"\ 42150"zgP98T3cP3u4x+V+3ffKufffr7g7/AsOA/3xDU+++F/bpRXvvxwwT3wnHgWnIdrfA+fPfnFswvw4lx87/y1p6Rft/48rT9Pe+O5+4Jnw/PjjO9/8zqu"\ 42151"W7dH65hbee8a/m5gw/kPPnhV8D181u3RTt55rOHewI1n+9czz0u/bv1+rX+nvX3rawFePf+sn9+vxZ4PvMANTH/79vO1X0u3R+v2aDcf/0jwPdwbeF/"\ 42152"68sO1X0t/VunPI5/efUuAF7iB99oXz679Wro9pNtDbvf7Af8bm73HucDf7VDUH8BfNn8LcONvuh2KxgP+7mTztwA3nrvboWg84B5vb/4W4Ab+boei8Q"\ 42153"D89nzgPzPnA//Nzd8DN/B3OywaD8D/6ebvgRv36XZYNB6A//bm7xW4gb/bYdF4AP4723mtx72YeBjPA/w3NrwN55t4GPbAc3624R0+MfEw7IF7Pdjwt"\ 42154"v68YuJh2AP49XxgM/Ewzgf+8w1v63Fv42HYA/hf2fAK/s/Ew7AH7v3khlf6fVYTD8MexC/EX4i/8fxK/EL8lfgb8VfiF+KvxN+IvxK/EH8h/kb8lfiF"\ 42155"+Avxz/OJfyX+QvxC/JX4V+IvxC/EX4h/Jf6F+IX4C+Nf9DzGvzD+GuN/4mX8C+O/Mf4nXsa/MP4b418UL+NfGP+N8T/PZ/zP8xn/Ey/jf2X8C+N/4mX"\ 42156"8r4x/YfyvipfxvzL+xfgb+a8w/1Xmn2L8jfxXmP8q85/1N/JfYf6rzH/V+Bv5rzD/VeY/62/kv8L8N883/kb+W5j/KvOf9Tfy38L8V5j/ivE38t/C/F"\ 42157"eY/0b+Z74ddiD/CflHyH9N/U3+a+Q/If819Tf5r5H/hPzX1N/kPyH/Cflvnk/+m+eT/5r6m/wn5L+V/Cfqb/KfkP9W8p+ov8l/K/lvPQr4X/n7+Ap/3"\ 42158"yN/R/yLd+k6+eain4/rv/bzX+7PhvMt3xG/EP/I1X/sn93p9v9vtzHsiGvaX2j/ybe0f6P9x5m4F95fvKO0n8B+/+w2OiP/efyv+Rp4Lwx/H5O/I/7F"\ 42159"PfE94H2ixx/eseusRz7u8Qe8mu8Y/7MeQvwDr+ZbfK9f126P2u1R+f41zbd8/2Y9hvcPeIEbeG9v70/B9/AZ3p+I/5W/7xn+7niKxkPEv8D/8ebvBc+"\ 42160"Pez/BfHyxxb8w/xXmv8L8N84CfubfAtzAj3jSeMDfMf8W5t/K/DvsAvw3N38P3MCPfKjxEPG/8vfxFf5We0T8C/zkn9LjfjHxMOwB/OS/Sv7TeBj2AP"\ 42161"4bG95Rd5t4GPbAc5N/K/lX42HYA/jPNryV/KnxMOwR8b/y9/EV/ib+kH+JfyH+lfgL8QvxF+IX4q/E34i/EH8j/kr8jfgL8Tfir8TfiH8hfiH+Qvwt4"\ 42162"n/l73uGvy82eww7RPzL+F8UL+N/YfwXxn9RvIz/wvivjP+Jl/FfGP+V8T/xMv4L478y/idexv/C+C8R/xt/I/9N/mb+C/nX+Bv5b2X+E+a/1fhb2P9M"\ 42163"PoRfjL8HjzD/NeY/629h/zX5GBiNv0e/w/zXmP8k4n/l7+Mr/E3+k4h/yX9F/U3+W8h/i6132P8K+9/xXpD/qvqb/FfJfwf1Fvvvxv572Jj8V9Xf5L9"\ 42164"C/lsi/rd8YftvxNPZ1n9PviN+If5RY0f8HfG/5Uvar9B+o3/P6g979UvE/9pvAS/jZ9YT7L9F8x3jf9ZDiP+IvyP+B17Nl3x/Zj2F9yerP+zVLxH/a/"\ 42165"+NeGH+EOYP7b+F+a8w/xXmv2GXiL8j/sezMH+uzJ/C/DnsktUf9uqXiP+Bn/xx0H+rPfB35L9C/tN4GPaI+Dvi/3PTv5M/NR6GPbL6w179EvE/8a8nV"\ 42166"/pv4q/EvxC/vg+F+CXi74j/z03/zvqpaD19nfpjRn/Yq18i/tf+W/Ey/teT//ffwvq3sP4trH+HHSL+jvif8b8qXsb/yviXrP6wV79E/G/8Xdg/TD5h"\ 42167"/63+FvY/kw+RFyL+jvjf+Hth/zT5FHkhqz/s1S8R/9t6wfbf5D/t94r6m/xXyH9LxN8R/9t6if1zYf88+ves/rBXv0T8H+nnmf5b9WrbfyNXnG/1n6v"\ 42168"/R/ODqP6wej31m4P6I+L/SD/P9t94JupXc56B9yfS/6P5QVR/nJr6g/rdnOdo/+fxf6SfZ/tvvBPULwv1yxEPkf4fzQ+i+uPU1B/Ubyv122b4b5f/I/"\ 42169"08039Tvz7ov9Uekf4fzQ+i+uOU9cdD1h8mHoY9Iv6P9PNM/835xUH/Tfw6/9jV/6P5QVR/EH8h/nZq6g/khYj/I/08238rXsb/wvgvkf4fzQ+i+uPU1"\ 42170"B+c31XO75rWPx7/R/p5tv9m/lutno28EOn/0fwgqj+Mv4Xz26nnq/7j8X+kn2f6b51X2P6b/LdE+n80P4jqDzuv4fz+oP5I8P/kO+IX4l8Nfo//3fl9"\ 42171"gv8n3xF/I34x+D3+d/cXEvwvmu8Y/7MeMvHv8b87v0/wf9N8x/if9ZCJf4//3f2FBP8L89/C/FeY/8TkP4//3fl9gv8b819h/qvMf83kP4//3f2FBP9"\ 42172"P/Z78p/GwGP7z+N+d3yf4v5H/KvlP46EY/vP4391fSPD/1O9Z/4jWw6b+8fjfnd8n+L+x/qmsf5rWw6b+8fjf3V9I8L+w/l1Y/xbWv2LqX4//3fl9gv"\ 42173"8b69/C+rey/m2m/vX4391fSPC/+ntl/zP50PQ/Hv+78/sE/6u/hf3P5EPT/3j87+4vJPh/1jvsf4X972r6X4//3fl9gv9nvcP+t7H/FdP/evzv7i8k9"\ 42174"H93fp7Q/6feTf3jgH8T+r+7P5DQ/6febeuHe6wfEvq/Oz9P6P+Tf6l/zXmI0b88/d/dH0jo/031zgtTPxyzfkjo/+78PKH/T/6l/tmof1ajf3r6v7s/"\ 42175"kND/G/XPWT9Q/2yqfwb6vzs/T+j/lfp3o/49+dfo357+7+4PJPT/Rv37oH5QeyT0f3d+ntD/K+cfjfOPyb9m/uHp/+7+QEL/b5x/HNQPxB/2/9H8PKH"\ 42176"/T/7l/Ktx/lXN/MvT/939gYT+3zj/mvUD519N51+B/u/OzxP6/+Rfzj+nHm7mn57+7+4PJPR/9bdcmPqB+S+c/0fz84T+P+cdnH8f8G9C/3f3BxL6/5"\ 42177"x32PqB/Bf2/xF/Wr7b2f9z5/eJ/T+3fsjoD97+QmL/z+XPy3j/z53fJ/b/3Pohqz/s7S8k9v9c/ryM9//c+X1i/8+tH7L6w97+QmL/z+XPy3j/z53fJ"\ 42178"/b/3Pohoz94+wuJ/T+XPy/j/T93fp/Y/3Prh4z+4O0vJPb/XP68jPf/3Pl9Yv/PrR+y+sPe/kJi/8/lT+Pvvf0/d36f2P9z64es/rC3v5DY/3P509Y7"\ 42179"O/t/7vw+sf/n1g8Z/cHbX4j4P5qfZ/vvPf0+0v+j/YGo/ojmF4nf/7nz82z/vaffR/p/tD8Q1R/R/CLx+z93fp7tv/f0+0j/j/YHovojml8kfv/nzs+"\ 42180"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"\ 42181"zbf+/p95H+H+0PRPVHNL/4DgTd2gQ=" 42182 nm[-2,-1] dct,idct 42183 42184 # Input DCT quantization matrix. 42185 (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;\ 42186 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) 42187 f. "const S = $1<50?5000/$1:200-2*$1; max(1,round((S*i+50)/100,1,-1))" 42188 nm. Q 42189 42190 # Process images. 42191 repeat $!-3 l[$>,-3--1] 42192 42193 # Decompose image into luma/chroma 42194 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 42195 42196 repeat 3 42197 # Compute DCT of image with 8x8 blocs. 42198 [$>] 42199 f[$>] "begin(boundary = 2; ref(vector64(),res)); 42200 if (!(x%8) && !(y%8), 42201 ref(crop(x,y,8,8),src); 42202 repeat (8,l, repeat (8,k, off = k + 8*l; res[off] = sum(src*crop(#"$dct",0,0,off,8,8,1)))); 42203 draw(#-1,res,x,y,0,0,8,8); 42204 ); i" 42205 round. 42206 42207 # Compute DCT quantization. 42208 +r[Q] {$>,w},100%,1,1,0,2 /.. . round.. *[-2,-1] 42209 42210 # Compute iDCT of 8x8 blocs. 42211 f. "begin(boundary = 2; ref(vector64(),res)); 42212 if (!(x%8) && !(y%8), 42213 ref(crop(x,y,8,8),src); 42214 repeat (8,l, repeat (8,k, off = k + 8*l; res[off] = sum(src*crop(#"$idct",0,0,off,8,8,1)))); 42215 draw(#"$>",res,x,y,0,0,8,8); 42216 ); i" 42217 rm. 42218 round[$>] 42219 done 42220 l[^3--1] r ${-max_wh},1,1,1 a c ycbcr2rgb round. r $w,$h,1,3,0 endl 42221 42222 endl done 42223 rm[dct,idct,Q] 42224 42225fx_jpeg_artefacts_preview : 42226 gui_split_preview "fx_jpeg_artefacts $*",${-3--1} 42227 42228#@gui Lomo : fx_lomo, fx_lomo_preview(1) 42229#@gui : Vignette Size = float(20,0,100) 42230#@gui : sep = separator() 42231#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42232#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42233#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42234#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42235#@gui : sep = separator() 42236#@gui : note = note("<small>Authors: <i>Jérome Boulanger</i> and <i>David Tschumperlé</i>. 42237#@gui : Latest Update: <i>2012/06/06</i>.</small>") 42238fx_lomo : 42239 remove_opacity repeat $! l[$>] to_rgb 42240 +gaussian {100-$1}%,{100-$1}% n. 0,1 * 42241 s c 42242 f[0] '255*atan((i-128)/128)' 42243 f[1] '255*tan((i-128)/128)' 42244 f[2] '255*atan((i-128)/255)' 42245 a c 42246 sharpen 1 42247 normalize 0,255 42248 endl done 42249 42250fx_lomo_preview : 42251 gui_split_preview "fx_lomo $*",${-3--1} 42252 42253#@gui Mess with Bits : fx_mess_with_bits, fx_mess_with_bits_preview 42254#@gui : note = note("<small><b>Input processing:</b></small>") 42255#@gui : Pre-Normalize = bool(1) 42256#@gui : Smoothness (%) = float(15,0,100) 42257#@gui : Multiplier = int(1,1,256) 42258#@gui : sep = separator() 42259#@gui : note = note("<small><b>Output processing:</b></small>") 42260#@gui : Reversing = choice{1,"None","Reverse bits","Reverse bytes"} 42261#@gui : Bit Masking (Start) = int(0,0,15) 42262#@gui : Bit Masking (End) = int(15,0,15) 42263#@gui : Opacity (%) = float(100,0,100) 42264#@gui : sep = separator() 42265#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42266#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42267#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42268#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42269#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42270#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42271#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42272#@gui : sep = separator() 42273#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42274#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42275#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42276#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42277#@gui : sep = separator() 42278#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/01/16</i>.</small>") 42279fx_mess_with_bits : 42280 ac "_fx_mess_with_bits ${1-7}",$8 42281 42282_fx_mess_with_bits : 42283 repeat $! +l[$>] 42284 b {($2/100)^2*100}% if $1 n 0,255 fi * $3 round 42285 # -> Here, images are 'ushort'-valued. 42286 if $4==1 f "for (k = res = 0, k<15, ++k, res|=((i>>k)&1)<<(15-k))" 42287 elif $4==2 f "res = ((i>>8)&255) | ((i&255)<<8)" 42288 fi 42289 f "begin( mask = (65535>>(15-max($5,$6))) & (65535<<min($5,$6))); i & mask" 42290 n 0,255 42291 endl j[$>] .,0,0,0,0,{$7%} rm. done 42292 42293fx_mess_with_bits_preview : 42294 gui_split_preview "fx_mess_with_bits $*",${-3--1} 42295 42296#@gui Noise [Additive] : fx_noise, fx_noise_preview(0) 42297#@gui : Amplitude = float(10,0,200) 42298#@gui : Noise Type = choice("Gaussian","Uniform","Salt and Pepper","Poisson") 42299#@gui : sep = separator() 42300#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42301#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42302#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42303#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42304#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42305#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42306#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42307#@gui : Value Action = choice(1,"None","Cut","Normalize") 42308#@gui : sep = separator() 42309#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42310#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42311#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42312#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42313#@gui : sep = separator() 42314#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42315fx_noise : 42316 ac "_fx_noise $1,$2",$3,$4 42317 42318_fx_noise : 42319 repeat $! l[$>] split_opacity l[0] noise $1,$2 endl a c endl done 42320 42321fx_noise_preview : 42322 gui_split_preview "fx_noise $*",${-3--1} 42323 42324#@gui Noise [Perlin] : fx_noise_perlin, fx_noise_perlin_preview(1) 42325#@gui : Random Seed = int(0,0,65536) 42326#@gui : sep = separator() 42327#@gui : note = note("<small><b>1st scale:</b></small>") 42328#@gui : Amplitude = float(100,0,512) 42329#@gui : Scale (%) = float(8,0,100) 42330#@gui : X/Y-Ratio = float(0,-4,4) 42331#@gui : sep = separator() 42332#@gui : note = note("<small><b>2nd scale:</b></small>") 42333#@gui : Amplitude = float(0,0,512) 42334#@gui : Scale (%) = float(4,0,100) 42335#@gui : X/Y-Ratio = float(0,-4,4) 42336#@gui : sep = separator() 42337#@gui : note = note("<small><b>3rd scale:</b></small>") 42338#@gui : Amplitude = float(0,0,512) 42339#@gui : Scale (%) = float(2,0,100) 42340#@gui : X/Y-Ratio = float(0,-4,4) 42341#@gui : sep = separator() 42342#@gui : note = note("<small><b>4th scale:</b></small>") 42343#@gui : Amplitude = float(0,0,512) 42344#@gui : Scale (%) = float(1,0,100) 42345#@gui : X/Y-Ratio = float(0,-4,4) 42346#@gui : sep = separator() 42347#@gui : Channel(s) = choice(2,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42348#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42349#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42350#@gui : "YCbCr [Green chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42351#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42352#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42353#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]") 42354#@gui : sep = separator() 42355#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42356#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42357#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42358#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42359#@gui : sep = separator() 42360#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/01/24</i>.</small>") 42361_fx_noise_perlin : 42362 seedx,seedy={[$1>>8,$1&255]} 42363 repeat $! l[$>] 42364 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 42365 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 42366 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 42367 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 42368 endl done 42369 42370fx_noise_perlin : 42371 ac "_fx_noise_perlin $*",$-4,1 42372 42373fx_noise_perlin_preview : 42374 gui_split_preview "fx_noise_perlin $*",${-3--1} 42375 42376#@gui Noise [Spread] : fx_spread, fx_spread_preview(0) 42377#@gui : X-Variations = float(4,0,20) 42378#@gui : Y-Variations = float(4,0,20) 42379#@gui : sep = separator() 42380#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42381#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42382#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42383#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42384#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42385#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42386#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42387#@gui : Value Action = choice("None","Cut","Normalize") 42388#@gui : sep = separator() 42389#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42390#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42391#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42392#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42393#@gui : sep = separator() 42394#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42395fx_spread : 42396 ac "spread $1,$2",$3,$4 42397 42398fx_spread_preview : 42399 gui_split_preview "fx_spread $*",${-3--1} 42400 42401#@gui Old-Movie Stripes : fx_stripes_y, fx_stripes_y_preview(1) 42402#@gui : Frequency = float(10,0,100) 42403#@gui : sep = separator() 42404#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42405#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42406#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42407#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42408#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42409#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42410#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42411#@gui : Value Action = choice("None","Cut","Normalize") 42412#@gui : sep = separator() 42413#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42414#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42415#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42416#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42417#@gui : sep = separator() 42418#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42419fx_stripes_y : 42420 ac "stripes_y $1",$2,$3 42421 42422fx_stripes_y_preview : 42423 gui_split_preview "fx_stripes_y $*",${-3--1} 42424 42425#@gui Oldschool 8bits : fx_8bits, fx_8bits_preview(0) 42426#@gui : Scale = float(25,1,100) 42427#@gui : Dithering = float(800,0,10000) 42428#@gui : Levels = int(16,2,256) 42429#@gui : sep = separator() 42430#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42431#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42432#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42433#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42434#@gui : sep = separator() 42435#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/02/11</i>.</small>") 42436fx_8bits : 42437 remove_opacity repeat $! l[$>] 42438 w={w} h={h} 42439 r $1%,$1%,1,100%,2 42440 +luminance sharpen. $2 otsu. 256 blend[-2,-1] shapeaverage0 42441 l. s c quantize $3,1,1 a c endl 42442 r. $w,$h,1,100%,1 42443 endl done 42444 42445fx_8bits_preview : 42446 gui_split_preview "fx_8bits $*",${-3--1} 42447 42448#@gui Pixel Sort : fx_pixelsort, fx_pixelsort_preview(1)+ 42449#@gui : note = note{"<small><b>Sorting parameters:</b></small>"} 42450#@gui : Order = choice(1,"Decreasing","Increasing") 42451#@gui : Axis = choice("X-axis","Y-axis","X-axis Then Y-axis","Y-axis Then X-axis") 42452#@gui : Sorting Criterion = choice("Red","Green","Blue","Intensity","Luminance","Lightness","Hue", 42453#@gui : "Saturation","Minimum","Maximum","Random") 42454#@gui : sep = separator() 42455#@gui : note = note{"<small><b>Masking parameters:</b></small>"} 42456#@gui : Mask By = choice(1,"Bottom Layer","Criterion","Contours","Random") 42457#@gui : Lower Mask Threshold (%) = float(0,0,100) 42458#@gui : Higher Mask Threshold (%) = float(100,0,100) 42459#@gui : Mask Smoothness (%) = float(0,0,5) 42460#@gui : Invert Mask = bool(0) 42461#@gui : Preview Mask = bool(0) 42462#@gui : sep = separator() 42463#@gui : note = note{"<small><b>Note:</b> 42464#@gui : This filter implements one version of the algorithm described here : 42465#@gui : </small>"} 42466#@gui : url = link("http://satyarth.me/articles/pixel-sorting/") 42467#@gui : sep = separator() 42468#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/05/09</i>.</small>") 42469fx_pixelsort : 42470 _fx_pixelsort ${1-8},0 42471 42472_fx_pixelsort : 42473 repeat $!-($4==0) l[$>] 42474 if $3==0 +to_rgb channels. 0 # Red 42475 elif $3==1 +to_rgb channels. 1 # Green 42476 elif $3==2 +to_rgb channels. 2 # Blue 42477 elif $3==3 +compose_channels + # Intensity 42478 elif $3==4 +luminance # Luminance 42479 elif $3==5 +to_rgb rgb2hsl. channels. 2 # Lightness 42480 elif $3==6 +to_rgb rgb2hsl. channels. 0 # Hue 42481 elif $3==7 +to_rgb rgb2hsl. channels. 1 # Saturation 42482 elif $3==8 +compose_channels min # Minimum 42483 elif $3==9 +compose_channels max # Maximum 42484 else 100%,100%,1,1 rand. 0,100 # Random 42485 fi 42486 if $4==0 pass. 0 norm. 42487 elif $4==1 . 42488 elif $4==2 +gradient_norm[0] 42489 else +rand. 0,100 42490 fi 42491 b. $7% ir. $5%,{$6+0.01}% 42492 if $8 ==. 0 fi 42493 if $9 k. * 255 42494 else pixelsort[0] {`$1?_'+':_'-'`},{`$2==0?'x':$2==1?'y':$2==2?'xy':'yx'`},[1],[2] k[0] 42495 fi 42496 endl done 42497 42498fx_pixelsort_preview : 42499 _fx_pixelsort $* 42500 42501#@gui Rain & Snow : fx_rain, fx_rain_preview(0) 42502#@gui : Angle = float(65,-180,180) 42503#@gui : Speed = float(10,0,50) 42504#@gui : Density (%) = float(50,0,100) 42505#@gui : Radius = float(0.1,0,3) 42506#@gui : Gamma = float(1,0,2) 42507#@gui : Opacity = float(1,0,1) 42508#@gui : sep = separator() 42509#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42510#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42511#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42512#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42513#@gui : sep = separator() 42514#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/29/06</i>.</small>") 42515fx_rain : 42516 repeat $! l[$<] nm=${-gui_layer_name} 42517 100%,100% l. 42518 noise 300 c 0,255 b 1,0 42519 c {100-$3}%,100% 42520 +>= 40% blend shapeaverage0 42521 blur_linear $2,$4,$1 42522 max n 0,255 apply_gamma $5 42523 nm name($nm),mode(screen),opacity({$6*100}) 42524 endl 42525 rv 42526 endl done 42527 42528fx_rain_preview : 42529 gui_split_preview "repeat $! l[$>] fx_rain $* rv blend screen,$6 endl done",${-3--1} 42530 42531#@gui Random Shade Stripes : fx_shade_stripes, fx_shade_stripes_preview(1) 42532#@gui : Frequency = float(30,1,100) 42533#@gui : Orientation = choice(1,"Horizontal","Vertical") 42534#@gui : Darkness = float(0.8,0,3) 42535#@gui : Lightness = float(1.3,0,3) 42536#@gui : sep = separator() 42537#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42538#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42539#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42540#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42541#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42542#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42543#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42544#@gui : Value Action = choice("None","Cut","Normalize") 42545#@gui : sep = separator() 42546#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42547#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42548#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42549#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42550#@gui : sep = separator() 42551#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42552fx_shade_stripes : 42553 ac "shade_stripes $1,$2,$3,$4",$5,$6 42554 42555fx_shade_stripes_preview : 42556 gui_split_preview "fx_shade_stripes $*",${-3--1} 42557 42558#@gui Rebuild From Similar Blocs : fx_rebuild_from_similar_blocs, fx_rebuild_from_similar_blocs(1) 42559#@gui : Bloc Size (%) = float(5,2,50) 42560#@gui : sep = separator() 42561#@gui : Regularization factor = float(10,0,20) 42562#@gui : Luminance factor = float(0.75,0,3) 42563#@gui : Norm type = choice(1,"L1","L2") 42564#@gui : sep = separator() 42565#@gui : note = note{"This filter subdivides the image into blocs, and replace each bloc by the most similar bloc 42566#@gui : found in the other blocs."} 42567#@gui : sep = separator() 42568#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/09/17</i>.</small>") 42569fx_rebuild_from_similar_blocs : 42570 repeat $! l[$>] split_opacity l[0] to_rgb 42571 w0,h0,S={[w,h,round(min(w,h)*$1%)]} # S: Bloc size 42572 42573 # Split image into regular blocs. 42574 r {ceil([w,h]/$S)*$S},1,100%,0,3,0.5,0.5 42575 M,N={[w,h]/$S} 42576 42577 s yx,-$S a z # Original RGB blocs 42578# +mirror x +mirror y a z # + all xy mirrors 42579# repeat 3 +rotate. 90 done a z # + all 90° rotations 42580 +l b xy,$2% rgb2ycbcr sh. 0 *. $3 rm. endl # Blocs to compare, in YCbCr space 42581 42582 # For each bloc, find most similar bloc. 42583 $M,$N,1,1,-1 42584 f. ": 42585 i<0?( 42586 ind = x + y*w; 42587 ref(crop(#1,0,0,ind,w#1,h#1,1),S); 42588 kmin = 0; 42589 dmin = inf; 42590 repeat (wh,k, k!=ind?( 42591 d = norm"{1+$4}"(S - crop(#1,0,0,k,w#1,h#1,1)); 42592 d<dmin?(dmin = d; kmin = k); 42593 )); 42594 xt = kmin%w; 42595 yt = int(kmin/w); 42596 i(xt,yt) = ind; 42597 kmin; 42598 ):i" 42599 42600 # Reconstruct image. 42601 {[$M,$N]*$S},1,{0,s} 42602 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)" 42603 k. r $w0,$h0,1,100%,0,0,0.5,0.5 42604 endl a c endl done 42605 42606#@gui Scanlines : fx_scanlines, fx_scanlines_preview(0) 42607#@gui : Amplitude = float(60,0,255) 42608#@gui : Bandwidth = float(2,1,300) 42609#@gui : Shape = choice(0,"Bloc","Triangle","Sine","Sine+","Random") 42610#@gui : Angle = float(0,0,360) 42611#@gui : Offset = float(0,0,500) 42612#@gui : sep = separator() 42613#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42614#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42615#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42616#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42617#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42618#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42619#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42620#@gui : Value Action = choice("None","Cut","Normalize") 42621#@gui : sep = separator() 42622#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42623#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42624#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42625#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42626#@gui : sep = separator() 42627#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/19/11</i>.</small>") 42628fx_scanlines : 42629 ac "scanlines ${1-5}",$6,$7 42630 42631fx_scanlines_preview : 42632 gui_split_preview "fx_scanlines $*",${-3--1} 42633 42634#@gui Self Glitching : fx_self_glitching, fx_self_glitching_preview(1) 42635#@gui : Multiplier = float(0,-5,5) 42636#@gui : Bias = float(0,-255,255) 42637#@gui : Negate = bool(0) 42638#@gui : Operator = choice("Add","Mul","And","Or","Xor","Pow","Reverse Pow","Mod","Reverse Mod") 42639#@gui : Shift Point = point(50,50,0,1) 42640#@gui : Boundary = choice(3,"Zero","Nearest","Periodic","Mirror") 42641#@gui : sep = separator() 42642#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42643#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42644#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42645#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42646#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42647#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42648#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42649#@gui : sep = separator() 42650#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42651#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42652#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42653#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42654#@gui : sep = separator() 42655#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/08/19</i>.</small>") 42656fx_self_glitching : 42657 ac "_fx_self_glitching ${1-7}",$8 42658 42659_fx_self_glitching : 42660 f "begin( 42661 shift = ([w,h]-1)*(50-[$5,$6])%; 42662 const sign = $3?-1:1; 42663 const boundary = $7; 42664 ); 42665 val = sign*((2^$1)*j(shift) + $2); 42666 ($4==0?(val + i): 42667 $4==1?(val * i): 42668 $4==2?(val & i): 42669 $4==3?(val | i): 42670 $4==4?xor(val,i): 42671 $4==5?(val^i): 42672 $4==6?(i^val): 42673 $4==7?(val%i): 42674 (i%val) 42675 )%256; 42676 " 42677 42678fx_self_glitching_preview : 42679 gui_split_preview "fx_self_glitching $*",${-3--1} 42680 42681#@gui Streak : fx_streak,fx_streak(1) 42682#@gui : Mask Color = color(255,0,0,255) 42683#@gui : Step (%) = float(0,0,30) 42684#@gui : Angle = float(0,0,360) 42685#@gui : Propagation = choice(3,"Backward","Forward","Bidirectional [Sharp]","Bidirectional [Smooth]") 42686#@gui : sep = separator() 42687#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/12/22</i>.</small>") 42688fx_streak : 42689 repeat $! l[$>] 42690 to_rgba 42691 if !$4 R,G,B,A=0 else R,G,B,A=${1-4} fi +select_color 0,$R,$G,$B,$A 42692 if $7==3 srgb2rgb.. fi 42693 f.. " 42694 const step = max(1,$5%*min(w,h)); 42695 const angle = $6*pi/180; 42696 const dx = step*cos(angle); 42697 const dy = step*sin(angle); 42698 if (!i(#-1),I, 42699 ixf = xf = x; iyf = yf = y; lf = 0; 42700 if ($7>=1, while (i(#-1,ixf=round(xf),iyf=round(yf)), ++lf; xf-=dx; yf-=dy)); # Forward 42701 ixb = xb = x; iyb = yb = y; lb = 0; 42702 if ($7!=1, while (i(#-1,ixb=round(xb),iyb=round(yb)), ++lb; xb+=dx; yb+=dy)); # Backward 42703 $7==0?I(ixb,iyb): 42704 $7==1?I(ixf,iyf): 42705 $7==2?(lf<lb?I(ixf,iyf):I(ixb,iyb)): 42706 (lb*lb*I(ixf,iyf) + lf*lf*I(ixb,iyb))/(lb^2+lf^2); 42707 )" 42708 if $7==3 rgb2srgb.. fi 42709 rm. 42710 endl done 42711 42712#@gui Visible Watermark : fx_watermark_visible, fx_watermark_visible(0) 42713#@gui : Text = text{"\\251 G'MIC"} 42714#@gui : Opacity = float(0.4,0.1,0.9) 42715#@gui : Size = int(50,13,128) 42716#@gui : Angle = float(25,0,360) 42717#@gui : Smoothness = float(0.5,0,5) 42718#@gui : Lightness = choice(1,"Darker","Brighter") 42719#@gui : sep = separator() 42720#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42721fx_watermark_visible : skip "${1= }" 42722 watermark_visible "$1",$2,$3,$4,$6,$5 42723 42724#@gui Warp by Intensity : fx_warp_by_intensity, fx_warp_by_intensity_preview(0) 42725#@gui : X-Factor = float(0.04,-6,6) 42726#@gui : Y-Factor = float(0.04,-6,6) 42727#@gui : sep = separator() 42728#@gui : X-Offset = float(128,0,255) 42729#@gui : Y-Offset = float(128,0,255) 42730#@gui : sep = separator() 42731#@gui : Correlated Channels = bool(0) 42732#@gui : Interpolation = choice(1,"Nearest Neighbor","Linear") 42733#@gui : Boundary = choice(3,"Transparent","Nearest","Periodic","Mirror") 42734#@gui : sep = separator() 42735#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42736#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42737#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42738#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42739#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42740#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42741#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42742#@gui : sep = separator() 42743#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42744#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42745#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42746#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42747#@gui : sep = separator() 42748#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/02/09</i>.</small>") 42749fx_warp_by_intensity : 42750 if !$7 to_a fi 42751 ac "_fx_warp_by_intensity ${1-7}",$8 42752 42753_fx_warp_by_intensity : 42754 if $5 f "ni = norm2(R,G,B); J((ni-$3)*$1,(ni-$4)*$2,0,$6,$7)" 42755 else f "j((i-$3)*$1,(i-$4)*$2,0,0,$6,$7)" 42756 fi 42757 42758fx_warp_by_intensity_preview : 42759 gui_split_preview "fx_warp_by_intensity $*",${-3--1} 42760 42761#@gui ____<b>Details</b> 42762#------------------------ 42763 42764#@gui Details Equalizer : fx_equalize_details, fx_equalize_details_preview(0) 42765#@gui : Base Scale = float(5,0,15) 42766#@gui : Detail Scale = float(0.5,0,5) 42767#@gui : note = note("<small><b>Coarse scale:</b></small>") 42768#@gui : Threshold = float(0,0,10) 42769#@gui : Smoothness = float(0,0,10) 42770#@gui : Smoothness Type = choice(2,"Gaussian","Bilateral","Diffusion") 42771#@gui : Gain = float(0,-4,4) 42772#@gui : sep = separator() 42773#@gui : note = note("<small><b>Medium scale:</b></small>") 42774#@gui : Threshold = float(0,0,10) 42775#@gui : Smoothness = float(0,0,10) 42776#@gui : Smoothness Type = choice(2,"Gaussian","Bilateral","Diffusion") 42777#@gui : Gain = float(0,-4,4) 42778#@gui : sep = separator() 42779#@gui : note = note("<small><b>Small scale:</b></small>") 42780#@gui : Threshold = float(0,0,10) 42781#@gui : Smoothness = float(0,0,10) 42782#@gui : Smoothness Type = choice(2,"Gaussian","Bilateral","Diffusion") 42783#@gui : Gain = float(0,-4,4) 42784#@gui : sep = separator() 42785#@gui : note = note("<small><b>Fine scale:</b></small>") 42786#@gui : Threshold = float(0,0,10) 42787#@gui : Smoothness = float(0,0,10) 42788#@gui : Smoothness Type = choice(2,"Gaussian","Bilateral","Diffusion") 42789#@gui : Gain = float(0,-4,4) 42790#@gui : sep = separator() 42791#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42792#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42793#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42794#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42795#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42796#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42797#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42798#@gui : Value Action = choice("None","Cut","Normalize") 42799#@gui : sep = separator() 42800#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 42801#@gui : "Sixteen Threads"), Spatial Overlap = int(32,0,256) 42802#@gui : sep = separator() 42803#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42804#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42805#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42806#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42807#@gui : sep = separator() 42808#@gui : note = note("<small>Author: <i>Jérome Boulanger</i> and <i>David Tschumperlé</i>. 42809#@gui : Latest Update: <i>2015/11/11</i>.</small>") 42810_fx_equalize_details : 42811 repeat $! l[$>] 42812 split_details 5,{max(0.1,$1)},{max(0.1,$2)} 42813 __fx_equalize_details[1] ${3-6},8 42814 __fx_equalize_details[2] ${7-10},4 42815 __fx_equalize_details[3] ${11-14},2 42816 __fx_equalize_details[4] ${15-18},1 42817 + c 0,255 42818 endl done 42819 42820__fx_equalize_details : 42821 threshold $1,1 42822 if $3==0 b {$2*$5/2} 42823 elif $3==1 42824 if $2>0 42825 m={im} M={iM} n. 0,255 42826 repeat int($2/5) bilateral 15,{5*$5} done 42827 bilateral 15,{($2%5)*$5} 42828 *. {($M-$m)/255} +. $m 42829 fi 42830 else smooth {$2*50},0.2,0.8,$5,$5 fi 42831 * {10^$4} 42832 42833fx_equalize_details : 42834 ac "gui_parallel_overlap \"_fx_equalize_details ${1-18}\",$21,$22",$19,$20 42835 42836fx_equalize_details_preview : 42837 gui_split_preview "fx_equalize_details $*",${-3--1} 42838 42839#@gui Equalize Local Histograms : fx_equalize_local_histograms, fx_equalize_local_histograms_preview(0) 42840#@gui : Strength (%) = float(75,0,100) 42841#@gui : Mode = choice(2,"Raw","Hard","Soft") 42842#@gui : Radius = int(4,1,16) 42843#@gui : Sigma = float(100,0,256) 42844#@gui : Regularization = float(8,0,32) 42845#@gui : Reduce Halos = bool(1) 42846#@gui : sep = separator() 42847#@gui : Channel(s) = choice(16,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42848#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42849#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42850#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42851#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42852#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42853#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42854#@gui : sep = separator() 42855#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42856#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42857#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42858#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42859#@gui : sep = separator() 42860#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/31</i>.</small>") 42861fx_equalize_local_histograms : 42862 b0="normal" b1="overlay" b2="softlight" 42863 repeat $! l[$>] 42864 +ac "_fx_equalize_local_histograms ${1-6}",$7,1 42865 blend ${b$2},{$1%} 42866 endl done 42867 42868_fx_equalize_local_histograms : 42869 +n 0,511 round. 42870 f. " 42871 begin( 42872 const boundary = 1; 42873 const N = $3; 42874 const sigma = ($6?1:-1)*(0.1+$4); 42875 ref(vector512(),weights); 42876 repeat (size(weights),k, # Pre-compute exponentials 42877 weights[k] = sigma>=0?exp(-sqr(k/sigma)):1 - exp(-sqr(k/sigma)) 42878 ); 42879 ); 42880 42881 ref(vector512(0),bins); 42882 42883 repeat (s,c, 42884 ref(crop(x - N,y - N,0,c,2*N + 1,2*N + 1,1,1),V); 42885 repeat (size(V),k, # Compute local weighted histogram 42886 val = V[k]; 42887 diff = abs(val - V[size(V)/2]); 42888 bins[val]+=weights[diff]; 42889 ); 42890 ); 42891 42892 sum = 0; 42893 repeat (size(bins),k, 42894 sum+=bins[k]; 42895 bins[k] = sum; 42896 ); 42897 bins/=max(1e-5,sum); 42898 42899 P = I; 42900 size(P)==1?(P = bins[P[0]]; 0): 42901 size(P)==2?(P = [ bins[P[0]], bins[P[1]] ]; 0): 42902 size(P)==3?(P = [ bins[P[0]], bins[P[1]], bins[P[2]] ]; 0): 42903 size(P)==4?(P = [ bins[P[0]], bins[P[1]], bins[P[2]], bins[P[3]] ]; 0); 42904 P" 42905 n. 0,255 42906 if $5 norm.. bilateral. ..,$5,{2+$5} fi 42907 k. 42908 42909fx_equalize_local_histograms_preview : 42910 gui_split_preview "fx_equalize_local_histograms $*",${-3--1} 42911 42912#@gui Freaky Details : fx_freaky_details, fx_freaky_details_preview(0) 42913#@gui : Amplitude = int(2,1,5) 42914#@gui : Scale = float(10,0,100) 42915#@gui : Iterations = int(1,1,4) 42916#@gui : sep = separator() 42917#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42918#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42919#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42920#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42921#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42922#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42923#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42924#@gui : sep = separator() 42925#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42926#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42927#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42928#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42929#@gui : sep = separator() 42930#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Patrick David</i>. 42931#@gui : Latest Update: <i>2013/27/02</i>.</small>") 42932#@gui : sep = separator() 42933#@gui : note = note("This effect has been done following:") 42934#@gui : url = link("This tutorial from Patrick David", 42935#@gui : "https://patdavid.net/2013/02/calvin-hollywood-freaky-details-in-gimp.html") 42936fx_freaky_details : 42937 repeat $! l[$>] 42938 repeat $3 42939 . +-. 255 *. -1 42940 repeat $1 bilateral. $2,{1.5*$2} done 42941 blend[-2,-1] vividlight blend overlay 42942 done 42943 endl done n 0,255 42944 42945fx_freaky_details_preview : 42946 gui_split_preview "fx_freaky_details $*",${-3--1} 42947 42948#@gui Local Normalization : fx_normalize_local, fx_normalize_local_preview(0) 42949#@gui : Amplitude = float(2,0,60) 42950#@gui : Radius = int(6,1,64) 42951#@gui : Neighborhood Smoothness = float(5,0,40) 42952#@gui : Average Smoothness = float(20,0,40) 42953#@gui : Constrain Values = bool(1) 42954#@gui : sep = separator() 42955#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42956#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42957#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42958#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42959#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42960#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42961#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42962#@gui : sep = separator() 42963#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42964#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42965#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42966#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42967#@gui : sep = separator() 42968#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 42969fx_normalize_local : 42970 repeat $! l[$>] 42971 ac "normalize_local $1,$2,$3,$4,$5,0,255",$6 42972 endl done 42973 42974fx_normalize_local_preview : 42975 gui_split_preview "fx_normalize_local $*",${-3--1} 42976 42977#@gui Local Processing : fx_local_processing, fx_local_processing_preview(1) 42978#@gui : Action = choice("Normalize","Equalize") 42979#@gui : Strength (%) = float(75,0,100) 42980#@gui : Neighborhood Size (%) = float(10,1,100) 42981#@gui : Overlap (%) = float(50,0,75) 42982#@gui : Regularization (%) = float(20,0,100) 42983#@gui : Process Channels Individually = bool(0) 42984#@gui : sep = separator() 42985#@gui : Channel(s) = choice(7,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 42986#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 42987#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 42988#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 42989#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 42990#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 42991#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 42992#@gui : sep = separator() 42993#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 42994#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 42995#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 42996#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 42997#@gui : sep = separator() 42998#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/02/28</i>.</small>") 42999fx_local_processing : 43000 com0="n 0,255" 43001 com1="equalize 256,0,255 n 0,255" 43002 com=${com$1} 43003 if $6 com="s c "$com" a c" fi 43004 repeat $! l[$>] 43005 size={round(max(8,max(w,h)*$3%))} 43006 +ac "at \""$com"\","$size","$size",1,$4%,$4%",$7 43007 if $5 +norm[0] bilateral[1] .,{$5/20}%,{2+$5/4} rm. fi 43008 blend alpha,{$2%} 43009 endl done 43010 43011fx_local_processing_preview : 43012 gui_split_preview "fx_local_processing $*",${-3--1} 43013 43014#@gui Magic Details : fx_magic_details,fx_magic_details_preview(0) 43015#@gui : Amplitude = float(6,0,30) 43016#@gui : Spatial Scale = float(3,0,10) 43017#@gui : Value Scale = float(15,0,20) 43018#@gui : Edges = float(-0.5,-3,3) 43019#@gui : Smoothness = float(2,0,20) 43020#@gui : sep = separator() 43021#@gui : Channel(s) = choice(27,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43022#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43023#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43024#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43025#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43026#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43027#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]") 43028#@gui : sep = separator() 43029#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43030#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43031#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43032#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43033#@gui : sep = separator() 43034#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/10</i>.</small>") 43035fx_magic_details : 43036 ac "_fx_magic_details ${1-5}",$6,1 43037 43038_fx_magic_details : 43039 repeat $! l[$>] 43040 +bilateral $2,$3 43041 +gradient_norm.. +. 1 43042 pow. {$4>=0?3.1-$4:-3.1-$4} 43043 b. $5 n. 1,{1+$1} 43044 -... .. *[-3,-1] + c 0,255 43045 endl done 43046 43047fx_magic_details_preview : 43048 gui_split_preview "fx_magic_details $*",${-3--1} 43049 43050#@gui Mighty Details : fx_mighty_details, fx_mighty_details_preview(0) 43051#@gui : Amplitude = float(25,0,100) 43052#@gui : Details Amount = float(1,0,2) 43053#@gui : Details Scale = float(25,1,100) 43054#@gui : Details Smoothness = int(1,0,10) 43055#@gui : sep = separator() 43056#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43057#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43058#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43059#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43060#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43061#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43062#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43063#@gui : sep = separator() 43064#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43065#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43066#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43067#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43068#@gui : sep = separator() 43069#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/08/08</i>.</small>") 43070_fx_mighty_details : 43071 +smooth $3,0,1,0.5,0.5 -[1] [0] 43072 +abs. sign.. M={iM} ^. {2-$2} *. {$M/iM} *[-2,-1] 43073 +diffusiontensors[0] 0,1,0.5,0.5 43074 repeat $4 smooth[1] [2],20 done 43075 *[1] {-$1/5} + 43076 43077fx_mighty_details : 43078 ac "_fx_mighty_details ${1-4}",$5,1 43079 n 0,255 43080 43081fx_mighty_details_preview : 43082 gui_split_preview "fx_mighty_details $*",${-3--1} 43083 43084#@gui Sharpen [Deblur] : fx_deblur, fx_deblur_preview(0) 43085#@gui : Radius = float(2,0,20) 43086#@gui : Iterations = int(10,0,100) 43087#@gui : Time Step = float(20,0,50) 43088#@gui : Smoothness = float(0.1,0,10) 43089#@gui : Regularization = choice(1,"Tikhonov","Mean Curvature","Total Variation") 43090#@gui : sep = separator() 43091#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43092#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43093#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43094#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43095#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43096#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43097#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43098#@gui : sep = separator() 43099#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 43100#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 43101#@gui : sep = separator() 43102#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43103#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43104#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43105#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43106#@gui : sep = separator() 43107#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43108fx_deblur : 43109 ac "gui_parallel_overlap \"deblur ${1-5} c 0,255\",$7,$8",$6,1 43110 43111fx_deblur_preview : 43112 gui_split_preview "fx_deblur $*",${-3--1} 43113 43114#@gui Sharpen [Gold-Meinel] : fx_unsharp_goldmeinel, fx_unsharp_goldmeinel_preview(0) 43115#@gui : Sigma = float(1,0.5,10) 43116#@gui : Iterations = int(5,1,15) 43117#@gui : Acceleration = float(1,1,3) 43118#@gui : Blur = choice(1,"Exponential","Gaussian") 43119#@gui : Cut = bool(true) 43120#@gui : sep = separator() 43121#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43122#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43123#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43124#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43125#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43126#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43127#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43128#@gui : sep = separator() 43129#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 43130#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 43131#@gui : sep = separator() 43132#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43133#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43134#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43135#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43136#@gui : sep = separator() 43137#@gui : note = note("<small>Author: <i>Jérôme Boulanger</i>. Latest Update: <i>2013/29/03</i>.</small>") 43138fx_unsharp_goldmeinel: 43139 ac "gui_parallel_overlap \"_fx_unsharp_goldmeinel $*\",$7,$8",$6,1 43140 43141_fx_unsharp_goldmeinel : 43142 deblur_goldmeinel $* 43143 if $5 c 0,255 else n 0,255 fi 43144 43145fx_unsharp_goldmeinel_preview: 43146 gui_split_preview "fx_unsharp_goldmeinel $*",${-3--1} 43147 43148#@gui Sharpen [Inverse Diffusion] : fx_sharpen_inversediff, fx_sharpen_inversediff_preview(0) 43149#@gui : Amplitude = float(50,1,300) 43150#@gui : Iterations = int(2,1,10) 43151#@gui : sep = separator() 43152#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43153#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43154#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43155#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43156#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43157#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43158#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43159#@gui : sep = separator() 43160#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43161#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43162#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43163#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43164#@gui : sep = separator() 43165#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43166fx_sharpen_inversediff : 43167 ac "repeat $2 sharpen $1 c 0,255 done",$3,1 43168 43169fx_sharpen_inversediff_preview : 43170 gui_split_preview "fx_sharpen_inversediff $*",${-3--1} 43171 43172#@gui Sharpen [Multiscale] : fx_sharpen_multiscale, fx_sharpen_multiscale_preview(0) 43173#@gui : Strength (%) = float(15,0,100) 43174#@gui : Regularity (%) = float(20,0,100) 43175#@gui : sep = separator() 43176#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43177#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43178#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43179#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43180#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43181#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43182#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43183#@gui : sep = separator() 43184#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43185#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43186#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43187#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43188#@gui : sep = separator() 43189#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/01/14</i>.</small>") 43190fx_sharpen_multiscale : 43191 ac "_fx_sharpen_multiscale $1,$2",$3 43192 43193fx_sharpen_multiscale_preview : 43194 gui_split_preview "fx_sharpen_multiscale $*",${-3--1} 43195 43196_fx_sharpen_multiscale : 43197 repeat $! l[$>] 43198 N={max(1,int(log2(min(w,h))-2))} 43199 +l repeat $N +r. 50%,50%,1,100%,2 +r. ..,..,1,100%,5 -[-3,-1] done endl # Decompose 43200 guided[0] 4,100 # Smooth guide image 43201 43202 # Process each scale. 43203 repeat $!-1 l[0,{$>+1}] 43204 +ri[0] [1],2 43205 +equalize.. 1024 43206 bilateral. ..,{2*$2%},100 43207 j[1] .,0,0,0,0,{$1%} 43208 k[0,1] 43209 endl done 43210 rm[0] 43211 43212 repeat $!-1 r. ..,..,1,100%,5 +[-2,-1] done # Recompose 43213 c 0,255 43214 endl done 43215 43216#@gui Sharpen [Octave Sharpening] : fx_unsharp_octave, fx_unsharp_octave_preview(0) 43217#@gui : Scales = int(4,1,10) 43218#@gui : Maximal Radius = float(5,0,20) 43219#@gui : Amount = float(3,0,10) 43220#@gui : Threshold = float(0,0,255) 43221#@gui : sep = separator() 43222#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43223#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43224#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43225#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43226#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43227#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43228#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43229#@gui : sep = separator() 43230#@gui : Parallel Processing = choice(1,"Auto","One Thread","Two Threads","Four Threads","Eight Threads", 43231#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 43232#@gui : sep = separator() 43233#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43234#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43235#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43236#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43237#@gui : sep = separator() 43238#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43239fx_unsharp_octave : 43240 ac "gui_parallel_overlap \"unsharp_octave $1,$2,$3,$4\",$6,$7",$5,1 43241 43242fx_unsharp_octave_preview : 43243 gui_split_preview "fx_unsharp_octave $*",${-3--1} 43244 43245#@gui Sharpen [Richardson-Lucy] : fx_unsharp_richardsonlucy, fx_unsharp_richardsonlucy_preview 43246#@gui : Sigma = float(1,0.5,10) 43247#@gui : Iterations = int(10,1,100) 43248#@gui : Blur = choice(1,"Exponential","Gaussian") 43249#@gui : Cut = bool(true) 43250#@gui : sep = separator() 43251#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43252#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43253#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43254#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43255#@gui : sep = separator() 43256#@gui : note = note("<small>Author: <i>Jérôme Boulanger</i>. Latest Update: <i>2013/29/03</i>.</small>") 43257fx_unsharp_richardsonlucy : 43258 deblur_richardsonlucy $* 43259 if $4 c 0,255 else n 0,255 fi 43260 43261fx_unsharp_richardsonlucy_preview : 43262 gui_split_preview "fx_unsharp_richardsonlucy $*",${-3--1} 43263 43264#@gui Sharpen [Shock Filters] : fx_sharpen_shock, fx_sharpen_shock_preview(0) 43265#@gui : Amplitude = float(150,1,400) 43266#@gui : Edge Threshold = float(0.1,0,0.7) 43267#@gui : Gradient Smoothness = float(0.8,0,10) 43268#@gui : Tensor Smoothness = float(1.1,0,10) 43269#@gui : Iterations = int(1,1,10) 43270#@gui : sep = separator() 43271#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43272#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43273#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43274#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43275#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43276#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43277#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43278#@gui : sep = separator() 43279#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43280#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43281#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43282#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43283#@gui : sep = separator() 43284#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43285fx_sharpen_shock : 43286 ac "repeat $5 sharpen $1,$2,$3,$4 c 0,255 done",$6,1 43287 43288fx_sharpen_shock_preview : 43289 gui_split_preview "fx_sharpen_shock $*",${-3--1} 43290 43291#@gui Sharpen [Texture] : fx_sharpen_texture, fx_sharpen_texture_preview(0) 43292#@gui : Strength = float(1,0,4) 43293#@gui : Radius = float(4,0,32) 43294#@gui : sep = separator() 43295#@gui : Channel(s) = choice(16,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43296#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43297#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43298#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43299#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43300#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43301#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]") 43302#@gui : sep = separator() 43303#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43304#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43305#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43306#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43307#@gui : sep = separator() 43308#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/09</i>.</small>") 43309fx_sharpen_texture : 43310 ac "_fx_sharpen_texture ${1-2}",$3,1 43311 43312_fx_sharpen_texture : 43313 repeat $! l[$>] 43314 +rolling_guidance $2,5,0.5 -. [0] *. $1 - c 0,255 43315 endl done 43316 43317fx_sharpen_texture_preview : 43318 gui_split_preview "fx_sharpen_texture $*",${-3--1} 43319 43320#@gui Sharpen [Unsharp Mask] : fx_unsharp, fx_unsharp_preview(0) 43321#@gui : Sharpening Type = choice(1,"Gaussian","Bilateral") 43322#@gui : Spatial Radius = float(1.25,0,20) 43323#@gui : Bilateral Radius = float(10,0,60) 43324#@gui : Amount = float(2,0,10) 43325#@gui : Threshold = float(0,0,20) 43326#@gui : Darkness Level = float(1,0,4) 43327#@gui : Lightness Level = float(1,0,4) 43328#@gui : Iterations = int(1,1,10) 43329#@gui : Negative Effect = bool(0) 43330#@gui : sep = separator() 43331#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43332#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43333#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43334#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43335#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43336#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43337#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43338#@gui : sep = separator() 43339#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43340#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43341#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43342#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43343#@gui : note = note{"\n\n<small><b>Note: </b> 43344#@gui : This filter is inspired by the original GIMP <i>Unsharp Mask</i> filter, with additional parameters. 43345#@gui : </small>"} 43346#@gui : sep = separator() 43347#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43348_fx_unsharp : 43349 repeat $! repeat $8 43350 if $1==0 +b. $2 else +bilateral. $2,$3 fi 43351 -. .. *. -$4 43352 +norm. >=. $5% ri. .. *[-2,-1] 43353 if $9 *. -1 fi 43354 +c. 0,100% c.. -100%,0 *.. $6 *. $7 +[-2,-1] 43355 +[-2,-1] c. 0,255 43356 done mv. 0 done 43357 43358fx_unsharp : 43359 ac "_fx_unsharp $1,$2,$3,$4,$5,$6,$7,$8,$9",$10,1 43360 43361fx_unsharp_preview : 43362 gui_split_preview "fx_unsharp $*",${-3--1} 43363 43364#@gui Split Details [Alpha] : fx_split_details_alpha, fx_split_details_alpha_preview(0) 43365#@gui : Number of Levels = int(6,2,8) 43366#@gui : Base Scale = float(10,0,30) 43367#@gui : Details Scale = float(1,0,20) 43368#@gui : Opacity Gain = float(5,1,20) 43369#@gui : sep = separator() 43370#@gui : Preview Without Alpha = bool(0) 43371#@gui : sep = separator() 43372#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/22/04</i>.</small>") 43373fx_split_details_alpha : 43374 remove_opacity 43375 repeat $! l[$<] 43376 repeat $1-1 43377 s={$3+($2-$3)*$>/if($1-2>0,$1-2,1)} 43378 +_fx_split_details_alpha_blur. $s 43379 sub_alpha.. .,$4 43380 done 43381 endl done 43382 43383_fx_split_details_alpha_blur : 43384 if $1>=0.1 b. $1 43385 else 43386 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) 43387 else (1,2,1;2,4,2;1,2,1) fi 43388 normalize_sum. convolve.. . rm. 43389 fi 43390 43391fx_split_details_alpha_preview : 43392 repeat $! l[$>] 43393 fx_split_details_alpha ${1-4} 43394 if $5 remove_opacity[^-1] else to_rgba. fi 43395 N={int(sqrt($!))} N={round($!/$N,1,1)} r2dy {100/$N}% 43396 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 43397 to_rgba frame 1,1,0 frame 3,3,255 append_tiles , 43398 endl done 43399 43400#@gui Split Details [Gaussian] : fx_split_details_gaussian, fx_split_details_gaussian_preview(0) 43401#@gui : Number of Scales = int(6,3,12) 43402#@gui : Base Scale = float(10,0,200) 43403#@gui : Details Scale = float(1,0,20) 43404#@gui : sep = separator() 43405#@gui : Sharpen Details in Preview = bool(0) 43406#@gui : sep = separator() 43407#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/22/01</i>.</small>") 43408fx_split_details_gaussian : 43409 remove_opacity repeat $! l[$>] 43410 nm=${-gui_layer_name} 43411 pos=${-gui_layer_pos} 43412 split_details $1,$2,$3 43413 +[^0] 128 c[^0] 0,255 round 43414 repeat $!-1 nm[{1+$>}] "mode(grainmerge), name"($nm" [scale ""#"{1+$>}"]), pos("$pos")" done 43415 nm[0] "name"($nm" [residual]), pos("$pos")" 43416 rv 43417 endl done 43418 43419fx_split_details_gaussian_preview : 43420 repeat $! l[$>] 43421 fx_split_details_gaussian $* 43422 if $4 equalize[^-1] 256 fi n[^-1] 0,255 43423 N={int(sqrt($!))} N={round($!/$N,1,1)} r2dy {100/$N}% 43424 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 43425 to_rgba frame 1,1,0 frame 3,3,255 append_tiles , 43426 endl done 43427 43428#@gui Split Details [Wavelets] : fx_split_details_wavelets, fx_split_details_wavelets_preview(0) 43429#@gui : Number of Scales = int(6,2,12) 43430#@gui : Add Alpha Channels to Detail Scale Layers = _bool(0) 43431#@gui : sep = separator() 43432#@gui : Sharpen Details in Preview = bool(0) 43433#@gui : sep = separator() 43434#@gui : note = note{"<small><b>Note:</b> This filter decomposes an image into several detail scales, 43435#@gui : using wavelet atrous. 43436#@gui : It should provide similar results to the 43437#@gui : <a href="http://registry.gimp.org/node/11742">Wavelet Decompose Plug-in</a> 43438#@gui : (by Marco Rossini). 43439#@gui : </small>"} 43440#@gui : sep = separator() 43441#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/23/03</i>.</small>") 43442fx_split_details_wavelets : 43443 remove_opacity repeat $! l[$>] 43444 nm=${-gui_layer_name} 43445 pos=${-gui_layer_pos} 43446 split_details $1,0,0 rv +[^-1] 128 c[^-1] 0,255 round 43447 if $2 to_a[^-1] fi 43448 repeat $!-1 nm[$>] "mode(grainmerge), name"($nm" [scale ""#"{1+$>}"]), pos("$pos")" done 43449 nm. "name"($nm" [residual]), pos("$pos")" 43450 endl done 43451 43452fx_split_details_wavelets_preview : 43453 repeat $! l[$>] 43454 fx_split_details_wavelets $1,0 43455 if $3 equalize[^-1] 256 fi n[^-1] 0,255 43456 N={int(sqrt($!))} N={round($!/$N,1,1)} r2dy {100/$N}% 43457 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 43458 to_rgba frame 1,1,0 frame 3,3,255 append_tiles , 43459 endl done 43460 43461#@gui Tone Mapping : fx_map_tones, fx_map_tones_preview(0) 43462#@gui : Threshold = float(0.5,0,1) 43463#@gui : Gamma = float(0.7,0,1) 43464#@gui : Smoothness = float(0.1,0,10) 43465#@gui : Iterations = int(30,0,500) 43466#@gui : sep = separator() 43467#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43468#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43469#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43470#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43471#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43472#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43473#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43474#@gui : sep = separator() 43475#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43476#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43477#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43478#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43479#@gui : sep = separator() 43480#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43481fx_map_tones : 43482 ac "map_tones ${1-4}",$5,1 43483 n 0,255 43484 43485fx_map_tones_preview : 43486 gui_split_preview "fx_map_tones $*",${-3--1} 43487 43488#@gui Tone Mapping [Fast] : fx_map_tones_fast, fx_map_tones_fast_preview(0) 43489#@gui : Radius = float(3,0,20) 43490#@gui : Power = float(0.5,0,1) 43491#@gui : sep = separator() 43492#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43493#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43494#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43495#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43496#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43497#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43498#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43499#@gui : sep = separator() 43500#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43501#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43502#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43503#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43504#@gui : sep = separator() 43505#@gui : note = note("<small>Authors: <i>Paul Nasca</i> and <i>David Tschumperlé</i>. 43506#@gui : Latest Update: <i>2011/10/06</i>.</small>") 43507fx_map_tones_fast : 43508 ac "map_tones_fast $1,$2",$3,2 43509 43510fx_map_tones_fast_preview : 43511 gui_split_preview "fx_map_tones_fast ${^0}",${-3--1} 43512 43513#@gui ____<b>Frames</b> 43514#---------------------- 43515 43516#@gui Droste : fx_droste, fx_droste_preview(1) 43517#@gui : note = note("<span color=\"red\">Upper-left coordinates :</span>") 43518#@gui : Point #0 = point(20,20,0,1,255,0,0) 43519#@gui : sep = separator() 43520#@gui : note = note("<span color=\"magenta\">Upper-right coordinates :</span>") 43521#@gui : Point #1 = point(80,20,0,1,255,0,255) 43522#@gui : sep = separator() 43523#@gui : note = note("<span color=\"blue\">Lower-right coordinates :</span>") 43524#@gui : Point #2 = point(80,80,0,1,0,128,255) 43525#@gui : sep = separator() 43526#@gui : note = note("<span color=\"cyan\">Lower-left coordinates :</span>") 43527#@gui : Point #3 = point(20,80,0,1,0,255,255) 43528#@gui : sep = separator() 43529#@gui : Iterations = int(1,1,10) 43530#@gui : X-Shift = float(0,-100,100) 43531#@gui : Y-Shift = float(0,-100,100) 43532#@gui : Angle = float(0,0,360) 43533#@gui : Zoom = float(1,0.1,5) 43534#@gui : Mirror = choice("None","X-Axis","Y-Axis","XY-Axes") 43535#@gui : Boundary = choice(1,"Transparent","Nearest","Periodic","Mirror") 43536#@gui : Drawing Mode = choice{"Replace","Replace (Sharpest)","Behind","Below"} 43537#@gui : View Outlines Only = bool(0) 43538#@gui : sep = separator() 43539#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/11/06</i>.</small>") 43540fx_droste : 43541 repeat $! 43542 if $16==1 100%,100%,1,1,'x' 100%,100%,1,1,'y' a[-2,-1] c fi 43543 repeat $9 43544 x0={round($1*w/100)} y0={round($2*h/100)} x1={round($3*w/100)} y1={round($4*h/100)} 43545 x2={round($5*w/100)} y2={round($6*h/100)} x3={round($7*w/100)} y3={round($8*h/100)} 43546 100%,100%,1,2,-32767 polygon. 4,$x0,$y0,$x1,$y1,$x2,$y2,$x3,$y3,1,-65535 43547 sh. 0 43548 f. "if(i==-65535, 43549 x03 = "$x0"+(y-"$y0")/("$y3"-"$y0")*("$x3"-"$x0"); 43550 x12 = "$x1"+(y-"$y1")/("$y2"-"$y1")*("$x2"-"$x1"); 43551 (x-x03)/(x12-x03)*(w-1),i)" 43552 rm. 43553 sh. 1 43554 f. "if(i==-65535, 43555 y01 = "$y0"+(x-"$x0")/("$x1"-"$x0")*("$y1"-"$y0"); 43556 y32 = "$y3"+(x-"$x3")/("$x2"-"$x3")*("$y2"-"$y3"); 43557 (y-y01)/(y32-y01)*(h-1),i)" 43558 rm. 43559 xshift={w*$10/100} yshift={h*$11/100} alpha={-$12*pi/180} 43560 ca={cos($alpha)/$13} sa={sin($alpha)/$13} w2={w/2} h2={h/2} 43561 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))' 43562 if $14==0 sh. 0 f. 'if(i==-32767,x,i)' rm. sh. 1 f. 'if(i==-32767,y,i)' rm. 43563 elif $14==1 sh. 0 f. 'if(i==-32767,x,w-1-i)' rm. sh. 1 f. 'if(i==-32767,y,i)' rm. 43564 elif $14==2 sh. 0 f. 'if(i==-32767,x,i)' rm. sh. 1 f. 'if(i==-32767,y,h-1-i)' rm. 43565 else sh. 0 f. 'if(i==-32767,x,w-1-i)' rm. sh. 1 f. 'if(i==-32767,y,h-1-i)' rm. 43566 fi 43567 if $16<2 warp.. .,0,{$16==0},$15 rm. 43568 else 43569 +warp.. .,0,1,$15 rm.. 43570 if $16==3 rv[-2,-1] fi 43571 blend[-2,-1] alpha 43572 fi 43573 done 43574 if $16==1 warp.. .,0,1,1 rm. fi 43575 mv. 0 done 43576 43577fx_droste_preview : 43578 if !$17 fx_droste $* else polygon 4,$1%,$2%,$3%,$4%,$5%,$6%,$7%,$8%,0.3,0,0,0,255 fi 43579 polygon 4,$1%,$2%,$3%,$4%,$5%,$6%,$7%,$8%,1,0xFFFFFFFF,0,0,0,255 43580 43581#@gui Frame [Blur] : fx_frame_blur, fx_frame_blur(1) 43582#@gui : Horizontal Size (%) = float(30,0,100) 43583#@gui : Vertical Size (%) = float(30,0,100) 43584#@gui : sep = separator() 43585#@gui : Crop = float(0,0,100) 43586#@gui : Blur = float(5,0,10) 43587#@gui : Roundness = float(0,0,1) 43588#@gui : Apply Color Balance = bool(0) 43589#@gui : Balance Color = color(128,128,128) 43590#@gui : Normalization = choice("None","Stretch","Equalize") 43591#@gui : sep = separator() 43592#@gui : Outline Size = float(5,0,50) 43593#@gui : Outline Color = color(255,255,255) 43594#@gui : X-Shadow = float(2,-10,10) 43595#@gui : Y-Shadow = float(2,-10,10) 43596#@gui : Shadow Smoothness = float(1,0,5) 43597#@gui : Shadow Contrast = float(0,0,100) 43598#@gui : X-Centering = float(0.5,0,1) 43599#@gui : Y-Centering = float(0.5,0,1) 43600#@gui : Angle = float(0,-180,180) 43601#@gui : sep = separator() 43602#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/19/01</i>.</small>") 43603fx_frame_blur : 43604 repeat $! l[$>] to_rgb 43605 sx={$1%*max(w,h)} sy={$2%*max(w,h)} 43606 +r {w+$sx},{h+$sy},1,100%,3 b[1] $4% 43607 43608 if $6 balance_gamma[1] ${7-9} fi 43609 if $10==1 n[1] 0,255 elif $10==2 n[1] 0,255 equalize[1] 256 fi 43610 rv 43611 43612 z[1] {$3/2}%,{$3/2}%,{100-$3/2}%,{100-$3/2}% 43613 to_rgba[1] 43614 43615 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)' 43616 v={min(i(w/2,0),i(w-1,h/2),i(w/2,h-1),i(0,h/2))} 43617 c. $v,{$v+0.5/max(w,h)} n. 0,255 rm. fi 43618 43619 s={$11%*max(w,h)} 43620 r[1] {w+$s},{h+$s},1,4,0,0,0.5,0.5 43621 i[1] 100%,100%,1,3 fc[1] ${12-14} blend[1,2] alpha to_a. 43622 43623 if $5 sh[1] 100% f. '1-(abs(x/w-0.5)^$r+abs(y/h-0.5)^$r)^(1/$r)' 43624 v={min(i(w/2,0),i(w-1,h/2),i(w/2,h-1),i(0,h/2))} 43625 c. $v,{$v+0.5/max(w,h)} n. 0,255 rm. fi 43626 rotate[1] $21,1,0 43627 r[1] [0],[0],1,4,0,0,$19,$20 43628 +channels[1] 100% b. $17%,0 c. 0,{max(1,100-$18)}% n. 0,255 43629 shift. {round(w*$15%)},{round(h*$16%)},0,0,0 /. -255 +. 1 *[0,-1] 43630 43631 blend alpha 43632 endl done 43633 43634#@gui Frame [Cube] : frame_cube, frame_cube(1) 43635#@gui : Depth = float(3,0,30) 43636#@gui : X-Center = float(0,-2,2) 43637#@gui : Y-Center = float(0,-2,2) 43638#@gui : Left Side Orientation = choice("Normal","Mirror-X","Mirror-Y","Mirror-XY") 43639#@gui : Right Side Orientation = choice("Normal","Mirror-X","Mirror-Y","Mirror-XY") 43640#@gui : Upper Side Orientation = choice("Normal","Mirror-X","Mirror-Y","Mirror-XY") 43641#@gui : Lower Side Orientation = choice("Normal","Mirror-X","Mirror-Y","Mirror-XY") 43642#@gui : sep = separator() 43643#@gui : note = note("<small>Author: <i>David Tschumperlé, Angelo Lama</i>. 43644#@gui : Latest Update: <i>2012/29/01</i>.</small>") 43645 43646#@gui Frame [Fuzzy] : fx_frame_fuzzy, fx_frame_fuzzy(0) 43647#@gui : Horizontal Size (%) = float(5,0,100) 43648#@gui : Vertical Size (%) = float(5,0,100) 43649#@gui : Fuzzyness = float(10,0,40) 43650#@gui : Smoothness = float(1,0,5) 43651#@gui : Color = color(255,255,255,255) 43652#@gui : sep = separator() 43653#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43654fx_frame_fuzzy : 43655 repeat $! l[$>] 43656 sx={$1%*max(w,h)/2} sy={$2%*max(w,h)/2} 43657 frame_fuzzy $sx,$sy,${3-8} 43658 endl done 43659 43660#@gui Frame [Mirror] : fx_frame_mirror, fx_frame_mirror_preview(1) 43661#@gui : note = note("<b>Frame size:</b>") 43662#@gui : Horizontal (%) = float(10,0,100) 43663#@gui : Vertical (%) = float(10,0,100) 43664#@gui : sep = separator() 43665#@gui : note = note("<b>Image alignment:</b>") 43666#@gui : Horizontal (%) = float(50,0,100) 43667#@gui : Vertical (%) = float(50,0,100) 43668#@gui : sep = separator() 43669#@gui : note = note("<b>Frame dilation/shrinking:</b>") 43670#@gui : Left = float(0,-5,5) 43671#@gui : Right = float(0,-5,5) 43672#@gui : Up = float(0,-5,5) 43673#@gui : Bottom = float(0,-5,5) 43674#@gui : sep = separator() 43675#@gui : Preview Opacity (%) = float(0.75,0,1) 43676#@gui : sep = separator() 43677#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/08/20</i>.</small>") 43678fx_frame_mirror : 43679 repeat $! l[$>] 43680 {100+2*$1}%,{100+2*$2}%,1,100%," 43681 const boundary = 3; 43682 const offx = (w - w#-1)*$3%; 43683 const offy = (h - h#-1)*$4%; 43684 const f_left = 2^$5; 43685 const f_right = 2^$6; 43686 const f_up = 2^$7; 43687 const f_bottom = 2^$8; 43688 x = x - offx; 43689 y = y - offy; 43690 x<0?(x*=-f_left): 43691 x>=w#-1?(x = w#-1 - 1 - f_right*(x - w#-1)); 43692 y<0?(y*=-f_up): 43693 y>=h#-1?(y = h#-1 - 1 - f_bottom*(y - h#-1)); 43694 I(#-1,x,y)" 43695 k. endl done 43696 43697fx_frame_mirror_preview : 43698 repeat $! l[$>] 43699 ws,hs={[w,h]} fx_frame_mirror $* wd,hd={[w,h]} 43700 rr2d $_preview_width,$_preview_height wp,hp={[w,h]} 43701 ws,hs={[$ws,$hs]*[$wp,$hp]/[$wd,$hd]} 43702 43703 coords={off=([$wp,$hp]-[$ws,$hs])*[$3,$4]%;[off,off+[$ws,$hs]-1]} 43704 split_opacity 100%,100%,1,1,$9 rectangle. $coords,1,1 *[0,-1] a c 43705 rectangle $coords,0.75,0xF0F0F0F0,255 43706 rectangle $coords,0.75,0x0F0F0F0F,0,0,0,255 43707 endl done 43708 43709#@gui Frame [Painting] : fx_frame_painting, fx_frame_painting_preview(1) 43710#@gui : Size (%) = float(10,0,100) 43711#@gui : Contrast = float(0.4,0,1) 43712#@gui : Smoothness = float(6,0,30) 43713#@gui : Color = color(225,200,120) 43714#@gui : sep = separator() 43715#@gui : Vignette Size = float(2,0,50) 43716#@gui : Vignette Contrast = float(400,0,1000) 43717#@gui : sep = separator() 43718#@gui : Defects Contrast = float(50,0,512) 43719#@gui : Defects Density = float(10,0,100) 43720#@gui : Defects Size = float(1,0,10) 43721#@gui : Defects Smoothness = float(0.5,0,20) 43722#@gui : sep = separator() 43723#@gui : Serial Number = int(123456,0,1000000) 43724#@gui : Frame as a New Layer = _bool(false) 43725#@gui : sep = separator() 43726#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/07/06</i>.</small>") 43727fx_frame_painting : 43728 if $14 43729 repeat $! 100%,100%,1,4 frame_painting. $1%,$2,$3%,${4-6},$7%,${8-13} 43730 rv[-2,-1] to_a. r. ..,..,1,4,0,0,0.5,0.5 mv[-2,-1] 0 done 43731 else frame_painting $1%,$2,$3%,${4-6},$7%,${8-13} 43732 fi 43733 43734fx_frame_painting_preview : 43735 frame_painting $1%,$2,$3%,${4-6},$7%,${8-13} 43736 43737#@gui Frame [Pattern] : fx_frame_pattern, fx_frame_pattern_preview(1) 43738#@gui : Tiles = int(10,3,30) 43739#@gui : Pattern = choice(1,"Top Layer","Self Image") 43740#@gui : Iterations = int(1,1,10) 43741#@gui : Constrain Image Size = _bool(1) 43742#@gui : sep = separator() 43743#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/01/08</i>.</small>") 43744fx_frame_pattern : 43745 if $2" || "$!==1 repeat $3 frame_pattern $1,$4 done 43746 else repeat $3 frame_pattern[^0] $1,[0],$4 done fi 43747 43748fx_frame_pattern_preview : 43749 fx_frame_pattern ${1-3},1 43750 43751#@gui Frame [Regular] : fx_frame, fx_frame(1) 43752#@gui : note = note("<b>Crop parameters :</b>") 43753#@gui : X-Start (%) = int(0,0,100) 43754#@gui : X-End (%) = int(100,0,100) 43755#@gui : Y-Start (%) = int(0,0,100) 43756#@gui : Y-End (%) = int(100,0,100) 43757#@gui : sep = separator() 43758#@gui : note = note("<b>Frame parameters :</b>") 43759#@gui : Width (%) = int(10,0,100) 43760#@gui : Height (%) = int(10,0,100) 43761#@gui : Color = color(0,0,0,255) 43762#@gui : Outline Size = int(1,0,100) 43763#@gui : Outline Color = color(255,255,255,255) 43764#@gui : sep = separator() 43765#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43766fx_frame : 43767 to_rgba repeat $! 43768 z. $1%,$3%,$2%,$4% 43769 frame. $11,$11,${12-15} 43770 sx={$5%*max(w,h)} sy={$6%*max(w,h)} 43771 frame. $sx,$sy,${7-10} 43772 mv. 0 done 43773 43774#@gui Frame [Round] : fx_frame_round, fx_frame_round(1) 43775#@gui : Sharpness = float(6,0.1,40) 43776#@gui : Size (%) = float(20,0,100) 43777#@gui : Smoothness = float(0.1,0,15) 43778#@gui : Shade = float(0,0,1) 43779#@gui : Color = color(255,255,255,255) 43780#@gui : Blur Frame = float(0,0,100) 43781#@gui : Blur Shade = float(0.1,0,1) 43782#@gui : Blur Amplitude = float(3,0,10) 43783#@gui : sep = separator() 43784#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43785fx_frame_round : 43786 frame_round ${1-8} 43787 if $9 frame_blur $1,{min(99,$1+$9)},$3,$10,$11% fi 43788 43789#@gui Frame [Smooth] : fx_frame_smooth, fx_frame_smooth(1) 43790#@gui : Width (%) = int(10,0,100) 43791#@gui : Height (%) = int(10,0,100) 43792#@gui : Roundness = float(0.25,0,1) 43793#@gui : sep = separator() 43794#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/25/04</i>.</small>") 43795fx_frame_smooth : 43796 repeat $! l[$>] 43797 sx={$1%*max(w,h)} sy={$2%*max(w,h)} 43798 100%,100%,1,1,0 43799 if $3 r={1+1/$3} f. '1-(abs(x/w-0.5)^$r+abs(y/h-0.5)^$r)^(1/$r)' 43800 v={min(i(w/2,0),i(w-1,h/2),i(w/2,h-1),i(0,h/2))} <=. $v 43801 fi 43802 frame $sx,$sy,1 43803 inpaint_pde[0] [1],100%,1,15 43804 rm. 43805 endl done c 0,255 43806 43807#@gui Old Photograph : fx_old_photo, fx_old_photo(1) 43808#@gui : Vignette Strength = float(200,0,255) 43809#@gui : Vignette Min Radius = float(50,0,100) 43810#@gui : Vignette Max Radius = float(85,0,100) 43811#@gui : sep = separator() 43812#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43813fx_old_photo : 43814 vignette ${1-3} old_photo 43815 43816#@gui Polaroid : fx_polaroid, fx_polaroid(1) 43817#@gui : Frame Size = int(10,0,400) 43818#@gui : Bottom Size = int(20,0,400) 43819#@gui : X-Shadow = float(0,-20,20) 43820#@gui : Y-Shadow = float(0,-20,20) 43821#@gui : Smoothness = float(3,0,5) 43822#@gui : Curvature = float(0,0,1) 43823#@gui : Angle = float(20,-180,180) 43824#@gui : Vignette Strength = float(50,0,255) 43825#@gui : Vignette Min Radius = float(70,0,100) 43826#@gui : Vignette Max Radius = float(95,0,100) 43827#@gui : sep = separator() 43828#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 43829fx_polaroid : 43830 vignette ${8-10} polaroid $1,$2 drop_shadow $3%,$4%,$5%,$6 rotate $7,1,0 43831 43832#@gui Tunnel : fx_tunnel, fx_tunnel(1) 43833#@gui : Depth = int(4,1,100) 43834#@gui : Factor = float(80,1,99) 43835#@gui : Center (%) = point(50,50) 43836#@gui : Opacity = float(0.2,0,1) 43837#@gui : Angle = float(0,-90,90) 43838#@gui : sep = separator() 43839#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/22/11</i>.</small>") 43840fx_tunnel : 43841 tunnel $1,$2%,{[${3,4}]%},${5-6} 43842 43843#@gui Vignette : fx_vignette, fx_vignette 43844#@gui : Strength = float(70,0,255) 43845#@gui : Min Radius = float(70,0,100) 43846#@gui : Max Radius = float(95,0,100) 43847#@gui : Color = color(0,0,0,255) 43848#@gui : sep = separator() 43849#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/24/10</i>.</small>") 43850fx_vignette : 43851 repeat $! to_rgb l[$>] 43852 to_rgba split_opacity 43853 =. 0 vignette. ${1-3} a c +fc ${4-7} rv blend alpha 43854 endl done 43855 43856#@gui ____<b>Frequencies</b> 43857#---------------------------- 43858 43859#@gui Bandpass : fx_bandpass, fx_bandpass_preview(0) 43860#@gui : Low Frequency = float(0,0,100) 43861#@gui : High Frequency = float(100,0,100) 43862#@gui : sep = separator() 43863#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 43864#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 43865#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 43866#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 43867#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 43868#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 43869#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 43870#@gui : Value Action = choice(2,"None","Cut","Normalize") 43871#@gui : sep = separator() 43872#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 43873#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 43874#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 43875#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 43876#@gui : sep = separator() 43877#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43878fx_bandpass : 43879 repeat $! l[$>] split_opacity l[0] 43880 ac "bandpass $1%,$2%",$3,$4 43881 endl a c endl done 43882 43883fx_bandpass_preview : 43884 gui_split_preview "fx_bandpass $*",${-3--1} 43885 43886#@gui Fourier Analysis : fx_display_fft, fx_display_fft(1) 43887#@gui : sep = separator() 43888#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43889fx_display_fft : 43890 to_rgb display_fft 43891 43892#@gui Fourier Transform : fx_fourier, fx_fourier_preview(1) 43893#@gui : Magnitude / Phase = choice{1,"One Layer (Horizontal)","One Layer (Vertical)","Two Layers"} 43894#@gui : Discard Transparency = bool(1) 43895#@gui : sep = separator() 43896#@gui : note = note{"<small><b>Note:</b> Apply this filter once to get the direct FFT, 43897#@gui : and once again to get the reverse transform.</small>"} 43898#@gui : url = link("Click here for a video tutorial","http://www.youtube.com/watch?v=3137dDa6P4s") 43899#@gui : sep = separator() 43900#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/06/16</i>.</small>") 43901fx_fourier : skip ${2=0} 43902 if $2 remove_opacity fi 43903 magic="GMICFFT" 43904 43905 i=0 for $i<$! ni={$i+1} nm={$i,n} 43906 43907 # Detect FFT/iFFT mode. 43908 is_ifft=0 43909 +columns[$i] 100% 43910 l. 43911 mag,m0,M0,m1,M1=${u\ {t}} 43912 if ['$mag']=='$magic' is_ifft=1 fi 43913 onfail endl rm. 43914 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 43915 if !$is_ifft 43916 +rows[$i] 100% l. mag,m0,M0=${u\ {t}} if ['$mag']=='$magic' is_ifft=3 fi onfail endl rm. 43917 if $is_ifft==3 43918 is_ifft=0 +rows[$ni] 100% 43919 l. mag,m1,M1=${u\ {t}} if ['$mag']=='$magic' is_ifft=3 fi onfail endl 43920 rm. 43921 fi 43922 fi 43923 43924 # Compute the transform. 43925 if !$is_ifft # FFT 43926 l[$i] 43927 fftpolar +.. 1 log.. m0,M0,m1,M1={[im#0,iM#0,im#1,iM#1]} n[-2,-1] 0,255 43928 if $1==0 ({'$magic,$m0,$M0,$m1,$M1'},0) y. a x 43929 elif $1==1 ({'$magic,$m0,$M0,$m1,$M1'},0) a y 43930 else ({'$magic,$m0,$M0'},0) a[-3,-1] y ({'$magic,$m1,$M1'},0) a[-2,-1] y 43931 fi 43932 nm $nm 43933 endl 43934 43935 else # iFFT 43936 if $is_ifft==1 columns[$i] 0,{$i,w-2} s[$i] x,2 43937 elif $is_ifft==2 rows[$i] 0,{$i,h-2} s[$i] y,2 43938 else rows[$i,$ni] 0,{$i,h-2} 43939 fi 43940 l[$i,{$i+1}] n[0] $m0,$M0 n[1] $m1,$M1 exp[0] -[0] 1 ifftpolar c 0,255 endl 43941 fi 43942 i+={$1<2" || "$is_ifft>2?1:2} 43943 done 43944 43945fx_fourier_preview : 43946 if $2 remove_opacity fi 43947 dfft 43948 43949#@gui Fourier Watermark : fx_watermark_fourier, _none_ 43950#@gui : Text = text{"(c) G'MIC"} 43951#@gui : Size = int(53,13,128) 43952#@gui : sep = separator() 43953#@gui : note = note("<small><b>Note: </b> To make the watermark visible afterwards, use the 43954#@gui : 'Fourier Analysis' filter. </small>") 43955#@gui : sep = separator() 43956#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 43957fx_watermark_fourier : 43958 watermark_fourier "$1",$2 c 0,255 43959 43960#@gui ____<b>Layers</b> 43961#----------------------- 43962 43963#@gui Align Layers : fx_align_layers, fx_align_layers_preview : * 43964#@gui : Alignment Type = choice(0,"Rigid","Non-Rigid") 43965#@gui : Smoothness = float(0.7,0,1) 43966#@gui : Scales = choice(0,"Auto","1","2","3","4","5","6","7","8") 43967#@gui : Revert Layers = bool(0) 43968#@gui : sep = separator() 43969#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/01/11</i>.</small>") 43970fx_align_layers : 43971 to_colormode 0 43972 r ${-max_wh},1,100%,0,0,0.5,0.5 43973 if ${4=0} _fx_revert_layers fi 43974 remove_opacity 43975 if $1 register_nonrigid[^-1] .,$2,0.1,$3 43976 else register_rigid[^-1] .,$2 43977 fi 43978 43979fx_align_layers_preview : 43980 fx_align_layers $1,$2,0 blend_edges 0.1 43981 43982_fx_revert_layers : 43983 repeat int($!/2) rv[{2*$>},{2*$>+1}] done 43984 43985#@gui Blend [Average All] : fx_blend_average_all, fx_blend_average_all : * 43986#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 43987#@gui : sep = separator() 43988#@gui : note = note{"<small><b>Note:</b> 43989#@gui : This filter takes multiple layers as input and average them. Set the <i>Input layers</i> option 43990#@gui : to handle multiple input layers. 43991#@gui : </small>"} 43992#@gui : sep = separator() 43993#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/11/08</i>.</small>") 43994fx_blend_average_all : 43995 if $! to_rgba 43996 N=$! r ${-max_wh},1,100%,0,0,0.5,0.5 43997 _gb_fwd $1 43998 + / $N 43999 _gb_bwd $1 44000 fi 44001 44002_gb_fwd : 44003 to_color 44004 if $1==1 repeat $! l[$>] sh 0,2 srgb2rgb. rm. endl done 44005 elif $1==2 repeat $! l[$>] sh 0,2 srgb2rgb. rgb2lab. rm. endl done 44006 fi 44007 44008_gb_bwd : 44009 to_color 44010 if $1==1 repeat $! l[$>] sh 0,2 rgb2srgb. rm. endl done 44011 elif $1==2 repeat $! l[$>] sh 0,2 lab2rgb. rgb2srgb. rm. endl done 44012 fi 44013 44014#@gui Blend [Edges] : fx_blend_edges, fx_blend_edges(0) : * 44015#@gui : Opacity = float(1,0,1) 44016#@gui : Smoothness = float(0.8,0,5) 44017#@gui : Revert Layers = bool(0) 44018#@gui : sep = separator() 44019#@gui : note = note{"<small><b>Note:</b> 44020#@gui : This filter needs two layers to work properly. Set the <i>Input layers</i> option to handle 44021#@gui : multiple input layers. 44022#@gui : </small>"} 44023#@gui : sep = separator() 44024#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/21/01</i>.</small>") 44025fx_blend_edges : 44026 repeat int($!/2) l[$>,{$>+1}] if $3 rv fi +blend_edges[-2,-1] $2 rm... blend[-2,-1] alpha,$1 endl done 44027 44028#@gui Blend [Fade] : fx_blend_fade, fx_blend_fade(1) : + 44029#@gui : Preset = choice{1,"Custom","Linear","Circular","Wave","Keftales"} 44030#@gui : Offset = float(0,-1,1) 44031#@gui : Thinness = float(0,0,10) 44032#@gui : Sharpness = float(5,1,20) 44033#@gui : Sharpest = bool(0) 44034#@gui : Revert Layers = bool(0) 44035#@gui : Colorspace = choice("sRGB","Linear RGB","Lab") 44036#@gui : note = note{\n<small> 44037#@gui : The parameters below are used in most presets. 44038#@gui : </small>} 44039#@gui : 1st Parameter = float(0,-1,1) 44040#@gui : 2nd Parameter = float(0,-1,1) 44041#@gui : 3rd Parameter = float(0,-1,1) 44042#@gui : note = note{\n<small> 44043#@gui : The formula below is used for the <i>Custom</i> preset. 44044#@gui : </small>} 44045#@gui : Formula = text{"cos(4*pi*x/w) * sin(4*pi*y/h)"} 44046#@gui : note = note{"<small><b>Note:</b> 44047#@gui : This filter needs two layers to work properly. Set the <i>Input layers</i> option to handle 44048#@gui : multiple input layers. 44049#@gui : </small>"} 44050#@gui : sep = separator() 44051#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/21/01</i>.</small>") 44052fx_blend_fade : 44053 if $!==1 return fi 44054 to_colormode 4 44055 _gb_fwd $7 44056 if $1==0 [0],[0],1,1,"$11" 44057 else _fx_blend_fade$1 $8,$9,$10 r. [0],[0],1,1,3 44058 fi 44059 n. {-($!-2)*$3},{($!-2)*(1+$3)} 44060 -. {$2*(1+$3)*($!-2)} 44061 c. 0,{$!-2} 44062 if $6 rv[^-1] fi 44063 if $5 round. 1 44064 else roundify. $4 44065 fi 44066 blend_fade[^-1] . rm. 44067 _gb_bwd $7 44068 c 0,255 44069 44070_fx_blend_fade1 : [0],[0],1,1,"a=$1*pi/2; x*cos(a) + y*sin(a)" 44071_fx_blend_fade2 : [0],[0],1,1,0 =. 1,{($1+1)*50}%,{($2+1)*50}% distance. 1 44072_fx_blend_fade3 : [0],[0],1,1,0 =. 1,{($1+1)*50}%,{($2+1)*50}% distance. 1 *. {0.01+$3/2} cos. 44073_fx_blend_fade4 : [0],[0],1,1,"((x-w*($1+0.5))*(y-h*($2+0.5)))%(0.2*w*h*(1.001+$3))" 44074 44075#@gui Blend [Median] : fx_blend_median, fx_blend_median(0) : * 44076#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 44077#@gui : sep = separator() 44078#@gui : note = note{"<small><b>Note:</b> 44079#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 44080#@gui : multiple input layers. 44081#@gui : </small>"} 44082#@gui : sep = separator() 44083#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Iain Fergusson</i>. 44084#@gui : Latest Update: <i>2014/16/12</i>.</small>") 44085fx_blend_median : 44086 _gb_fwd $1 44087 blend_median 44088 _gb_bwd $1 44089 44090#@gui Blend [Seamless] : fx_blend_seamless, fx_blend_seamless_preview(1) : * 44091#@gui : Mixed Mode = bool(0) 44092#@gui : Inner Fading = float(0,0,100) 44093#@gui : Outer Fading = float(25,0,100) 44094#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 44095#@gui : sep = separator() 44096#@gui : Output as Separate Layers = _bool(0) 44097#@gui : sep = separator() 44098#@gui : note = note{"<small><b>Note:</b> 44099#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 44100#@gui : multiple input layers. 44101#@gui : </small>"} 44102#@gui : sep = separator() 44103#@gui : url = link("Click here for a detailed description of this filter.",\ 44104# "http://gimpchat.com/viewtopic.php?f=28&t=10204") 44105#@gui : url = link("+ Video tutorial 1","http://www.youtube.com/watch?v=Nu-S1HmOCgE") 44106#@gui : url = link("+ Video tutorial 2","http://www.youtube.com/watch?v=zsHgQY6025I") 44107#@gui : url = link("+ Video tutorial 3","http://www.youtube.com/watch?v=2e6FikWMkaQ") 44108#@gui : sep = separator() 44109#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/04/05</i>.</small>") 44110fx_blend_seamless : 44111 rv 44112 _gb_fwd $4 44113 to_a[^0] r[^0] [0],[0],1,100%,0 44114 repeat $! pos=${gui_layer_pos[$>]} shift[$>] ${u\ $pos},0,0 done 44115 if $5 # Output as separate layers 44116 +blend_seamless $1,$2%,$3% 44117 remove_opacity[0,-1] k[0,-1] rv sub_alpha[0] [1],1 44118 else 44119 blend_seamless $1,$2%,$3% # Output as a single layer. 44120 fi 44121 _gb_bwd $4 44122 44123fx_blend_seamless_preview : 44124 fx_blend_seamless ${1-4},0 44125 44126#@gui Blend [Standard] : fx_blend, fx_blend_preview : * 44127#@gui : Mode = choice{6,"Add","Alpha","And","Average","Blue","Burn","Custom formula","Darken","Difference", 44128#@gui : "Divide","Dodge","Edges","Exclusion","Freeze","Grain Extract","Grain Merge","Green","Hard Light", 44129#@gui : "Hard Mix","Hue","Interpolation","Lighten","Lightness","Linear Burn","Linear Light","Luminance", 44130#@gui : "Multiply","Negation","Or","Overlay","Pin Light","Red","Reflect","Saturation", 44131#@gui : "Shape Area Max","Shape Area Max0","Shape Area Min","Shape Area Min0","Shape Average","Shape Average0", 44132#@gui : "Shape Median","Shape Median0","Shape Min","Shape Min0","Shape Max","Shape Max0", 44133#@gui : "Soft Burn","Soft Dodge","Soft Light","Screen","Stamp","Subtract","Value","Vivid Light","Xor"} 44134#@gui : Process As = choice("Two-by-Two","Upper Layer is the Top Layer for All Blends", 44135#@gui : "Lower Layer is the Bottom Layer for All Blends") 44136#@gui : Opacity (%) = float(100,0,100) 44137#@gui : Preview All Outputs = bool(1) 44138#@gui : sep = separator() 44139#@gui : Custom Formula = text{"1/2 - 1/4*cos(pi*a) - 1/4*cos(pi*b)"} 44140#@gui : note = note{"<small><b>Note:</b> In custom formulas, <samp>a</samp> and <samp>b</samp> respectively stand for 44141#@gui : the values of the <i>base layer<i> and the <i>blend layer</i>, 44142#@gui : and are defined in value range [0,1].</small>"} 44143#@gui : sep = separator() 44144#@gui : note = note{"<small><b>Note:</b> 44145#@gui : This filter needs at least two layers to work properly. Do not forget to set the <i>Input layers</i> option 44146#@gui : below to handle multiple input layers. 44147#@gui : </small>"} 44148#@gui : url = link("Reference page for G'MIC blending modes", 44149#@gui : "https://github.com/dtschump/gmic-community/wiki/Blending-modes") 44150#@gui : sep = separator() 44151#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/03/08</i>.</small>") 44152fx_blend : 44153 mode=${arg\ 1+$1,add,alpha,and,average,blue,burn,custom_formula,darken,difference,\ 44154 divide,dodge,edges,exclusion,freeze,grainextract,grainmerge,green,hardlight,\ 44155 hardmix,hue,interpolation,lighten,lightness,linearburn,linearlight,luminance,\ 44156 multiply,negation,or,overlay,pinlight,red,reflect,saturation,\ 44157 shapeareamax,shapeareamax0,shapeareamin,shapeareamin0,\ 44158 shapeaverage,shapeaverage0,shapemedian,shapemedian0,\ 44159 shapemin,shapemin0,shapemax,shapemax0,\ 44160 softburn,softdodge,softlight,screen,stamp,subtract,value,\ 44161 vividlight,xor} 44162 m "_blend_custom_formula : f. \"a = i#0/255; b = i#1/255; 255*cut(($5),0,1)\"" 44163 if $2==0 repeat int($!/2) l[$>,{$>+1}] rv blend $mode,{$3%} endl done # Two-by-two. 44164 elif $2==1" && "$!>1 blend[^0] [0],$mode,{$3%},0 rm[0] # Top layer is top for all blends. 44165 elif $2==2" && "$!>1 blend[^-1] .,$mode,{$3%},1 rm. # Bottom layer is bottom for all blends. 44166 fi 44167 um _blend_custom_formula 44168 44169fx_blend_preview : 44170 fx_blend $"*" 44171 if $4 append_tiles , fi 44172 44173#@gui Colors to Layers : fx_split_colors, fx_split_colors_preview(1) 44174#@gui : Color Tolerance = float(50,0,256) 44175#@gui : Maximum Number of Output Layers = int(16,2,256) 44176#@gui : Minimal Area (%) = float(1,0,100) 44177#@gui : Autocrop Output Layers = bool() 44178#@gui : sep = separator() 44179#@gui : note = note{"<small><b>Note:</b> This filter decomposes an image into several layers each with 44180#@gui : a single color + a residual layer (if any). 44181#@gui : </small>"} 44182#@gui : sep = separator() 44183#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/11/03</i>.</small>") 44184fx_split_colors : skip ${2=0} 44185 to_rgb repeat $! l[$>] 44186 nm=${-gui_layer_name} 44187 min_area={max(1,w*h*$3%)} 44188 split_colors $1,$2,$min_area 44189 nm name($nm) 44190 if $4 gui_autocrop_layers fi 44191 endl done 44192 44193fx_split_colors_preview : 44194 repeat $! l[$>] 44195 +fx_split_colors ${1-4} drgba 44196 repeat $! l[$>] to ${arg\ {1+!!$>},"Original","#"$>},1,1,43,7,1,255 endl done 44197 frame 1,1,0 frame 3,3,255 to_rgba append_tiles , 44198 endl done 44199 44200#@gui Fade Layers : fx_fade_layers, fx_fade_layers_preview : + 44201#@gui : Inter-Frames = _int(10,2,100) 44202#@gui : sep = separator() 44203#@gui : note = note{"<small><b>Note:</b> 44204#@gui : This filter needs at least two layers to work properly. Set the <i>Input layers</i> option to handle 44205#@gui : multiple input layers. 44206#@gui : </small>"} 44207#@gui : sep = separator() 44208#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/04/08</i>.</small>") 44209fx_fade_layers : 44210 if $!<2 return fi 44211 to_colormode 0 44212 r ${-max_wh},1,100%,0,0,0.5,0.5 44213 a z r 100%,100%,{(d-1)*$1+1},100%,3 s z 44214 44215fx_fade_layers_preview : 44216 if $!<2 return fi 44217 to_colormode 0 44218 r ${-max_wh},1,100%,0,0,0.5,0.5 44219 k[0,1] + / 2 44220 44221#@gui Layers to Tiles : append_tiles, fx_append_tiles_preview(1) : * 44222#@gui : X-Tiles = int(0,0,256) 44223#@gui : Y-Tiles = int(0,0,256) 44224#@gui : note = note("<small>For both parameters, <i>0</i> means <i>automatic</i>.</small>") 44225#@gui : sep = separator() 44226#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44227fx_append_tiles_preview : 44228 frame 1,1,0,0,0,255 append_tiles $1,$2 44229 44230#@gui Morph Layers : fx_morph_layers, gui_no_preview : * 44231#@gui : Inter-Frames = _int(10,2,100) 44232#@gui : Smoothness = _float(0.2,0,2) 44233#@gui : Precision = _float(0.1,0,2) 44234#@gui : Revert Layers = bool(0) 44235#@gui : sep = separator() 44236#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44237fx_morph_layers : 44238 if ${4=0} _fx_revert_layers fi 44239 to_rgb morph $1,$2,$3 44240 44241#@gui Multiscale Operator : fx_apply_multiscale, fx_apply_multiscale_preview(1) 44242#@gui : Number of Scales = int(4,2,16) 44243#@gui : sep = separator() 44244#@gui : Starting Scale (%) = float(25,0,400) 44245#@gui : Ending Scale (%) = float(100,0,400) 44246#@gui : Non-Linearity = float(0,-1,1) 44247#@gui : Rescaling = choice(3,"Bloc","Linear","Cubic","Lanczsos") 44248#@gui : sep = separator() 44249#@gui : X-Centering = float(0.5,0,1) 44250#@gui : Y-Centering = float(0.5,0,1) 44251#@gui : Angle = float(0,-180,180) 44252#@gui : sep = separator() 44253#@gui : Enable Interpolated Motion = bool(0) 44254#@gui : Ending X-Centering = float(0.5,0,1) 44255#@gui : Ending Y-Centering = float(0.5,0,1) 44256#@gui : Ending Angle = float(0,-180,180) 44257#@gui : sep = separator() 44258#@gui : G'MIC Operator = text("") 44259#@gui : Return Scaling = choice("None","Bloc","Linear","Cubic","Lanczos") 44260#@gui : Lock Return Scaling to Source Layer = bool(0) 44261#@gui : sep = separator() 44262#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/30/03</i>.</small>") 44263fx_apply_multiscale : skip "${13=}" 44264 repeat $! l[$<] 44265 w0={w} h0={h} 44266 apply_scales "$13",$1,$2%,$3%,{10^$4},{arg(1+$5,1,3,5,6)} 44267 if $8" || "($9" && "$8!=$12) to_a N=$! repeat $! 44268 angle={$9?$8+($12-$8)*$>/max($N-1,1):$8} 44269 rotate[$>] $angle 44270 done fi 44271 if $14 44272 if $15 siz=$w0,$h0 else siz=${-max_wh} fi 44273 r $siz,1,100%,{arg($14,1,3,5,6)} 44274 c 0,255 44275 fi 44276 w=${-max_w} h=${-max_h} N=$! 44277 repeat $! 44278 cx={$9?$6+($10-$6)*$>/max($N-1,1):$6} 44279 cy={$9?$7+($11-$7)*$>/max($N-1,1):$7} 44280 gui_set_layer_pos[$>] {$>,($w-w)*$cx},{$>,($h-h)*$cy} 44281 done 44282 endl done 44283 44284fx_apply_multiscale_preview : 44285 repeat $! l[$>] 44286 fx_apply_multiscale $"*" 44287 N={int(sqrt($!))} N={round($!/$N,1,1)} r2dy {100/$N}% 44288 to_rgba 44289 max_wh=${-max_wh} 44290 N=$! repeat $! l[$>] 44291 cx={$9?$6+($10-$6)*$>/max($N-1,1):$6} 44292 cy={$9?$7+($11-$7)*$>/max($N-1,1):$7} 44293 r $max_wh,1,100%,0,0,$cx,$cy 44294 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] 44295 endl done 44296 frame 1,1,0 frame 3,3,255 append_tiles , 44297 endl done 44298 44299#@gui Pack : fx_pack, fx_pack_preview(1) : * 44300#@gui : Order By = choice(2,"Width","Height","Maximum Dimension","Area","Name") 44301#@gui : Tends to Be Square = bool(1) 44302#@gui : Force Transparency = bool(1) 44303#@gui : Add Image Label = bool(0) 44304#@gui : Font Height (px) = float(16,0,64)_0 44305#@gui : Font Colors = choice(1,"White on black","Black on white")_0 44306#@gui : sep = separator() 44307#@gui : Output Coordinates File = _bool(0) 44308#@gui : Output Folder = _folder() 44309#@gui : sep = separator() 44310#@gui : note = note{"<small>This filter tries to pack all input layers into a single image, while trying to 44311#@gui : minimize the empty areas. 44312#@gui : This problem being NP-hard, the algorithm finds (of course) a <b>non-optimal</b>, but often acceptable 44313#@gui : solution to this packing problem.</small>"} 44314#@gui : sep = separator() 44315#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/03/20</i>.</small>") 44316fx_pack : skip "${8=}" 44317 if $4 to_rgba repeat $! l[$>] nm0={n} gui_layer_name nm=${} 44318 0 t. {``$nm},3,0,$5,1,1 frame. 1,1,0 44319 if $6 *. -1 fi 44320 n. 0,255 to_rgba. r. {[w+2,h+1,1,4]},0,0,0,1 44321 rv a y,{w#0>w?0.5:0} nm $nm0 44322 endl done 44323 fi 44324 if $3 to_a fi 44325 repeat $! gui_layer_name[$>] nm$>=${} nm[$>] {`lowercase(['${nm$>}'])`} done 44326 c0="w" c1="h" c2="max(w,h)" c3="w*h" c4="n" 44327 pack $2,${c$1} coords=${} 44328 if $7 44329 repeat 256 filename "$8/gmic_pack.txt",$> filename=${} if isfile(['{/$filename}']) else break fi done 44330 if !narg($filename) filename="$8/gmic_pack.txt" fi 44331 l[] repeat narg($coords)/2 44332 x={arg(1+2*$>,$coords)} y={arg(2+2*$>,$coords)} 44333 ('"Image ""#"{1+$>}" ("${nm$>}"): "$x,$y\n') 44334 done a x ot $filename rm endl 44335 fi 44336 nm "name(G'MIC packing),pos(0,0),mode(normal)" 44337 if $4 autocrop fi 44338 44339fx_pack_preview : 44340 if !$! return fi 44341 w={w} h={h} 44342 filled=0 repeat $! filled={$>,$filled+w*h} done 44343 fx_pack $1,$2,$3,$4,$5,$6,0 44344 area={w*h} 44345 to_rgba rr2d $w,$h,0 44346 i[0] $w,16,1,4,255 t[0] "Filled: "{round(100*$filled/$area)}%,3,1,14,1,0,0,0,255 44347 a y,0.5 44348 u "{$1}{$2}{$3}{$4}"\ 44349 "{$5}_"{2*$4}\ 44350 "{$6}_"{2*$4}\ 44351 "{$7}{$8}" 44352 44353#@gui Stroke : fx_stroke, fx_stroke_preview(0) 44354#@gui : Thickness (px) = int(3,1,256) 44355#@gui : Threshold (%) = float(50,0,100) 44356#@gui : Smoothness (px) = float(0,0,10) 44357#@gui : Shape = choice(2,"Square","Diamond","Round") 44358#@gui : Direction = choice(1,"Inward","Outward") 44359#@gui : sep = separator() 44360#@gui : Zoom (%) = float(100,1,300) 44361#@gui : X-Shift (px) = int(0,-256,256) 44362#@gui : Y-Shift (px) = int(0,-256,256) 44363#@gui : sep = separator() 44364#@gui : Starting Color = color(255,255,255,255) 44365#@gui : Ending Color = color(255,255,255,255) 44366#@gui : Inside Color = color(0,0,0,0) 44367#@gui : Outside Color = color(0,0,0,0) 44368#@gui : sep = separator() 44369#@gui : Output Stroke Layer On = choice(1,"Bottom","Top") 44370#@gui : Keep Original Image Size = bool(0) 44371#@gui : sep = separator() 44372#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/24/06</i>.</small>") 44373fx_stroke : 44374 to_a repeat $! l[$<] nm={n} 44375 if !$26" && "$5 expand_xy $1,0 is_frame1=0 else expand_xy 1,0 is_frame1=1 fi 44376 split_opacity +l. 44377 b $3 44378 if $6>=100 44379 shift $7,$8 44380 if $6!=100 wh={w},{h} r $6%,$6%,1,1,3 r $wh,1,1,0,0,0.5,0.5 fi 44381 else 44382 if $6!=100 wh={w},{h} r $6%,$6%,1,1,3 r $wh,1,1,0,0,0.5,0.5 fi 44383 shift $7,$8 44384 fi 44385 > {99.99-min(99.99,$2)}% 44386 distance $5,$4 44387 ($9^$10^$11^$12) 44388 if $1>1 ($13^$14^$15^$16) a[-2,-1] x r. $1,1,1,4,3 c. 0,255 fi 44389 i.. ($21^$22^$23^$24) ($17^$18^$19^$20) if $5 rv[-3,-1] fi 44390 a[-3--1] x map.. .,1 rm. 44391 nm $nm 44392 endl 44393 a[0,1] c 44394 if $is_frame1 shrink_xy 1 fi 44395 if $25 rv fi 44396 endl done 44397 44398fx_stroke_preview : 44399 repeat $! l[$>] 44400 fx_stroke $* 44401 nm foo 44402 gui_merge_layers 44403 endl done 44404 44405#@gui Tiles to Layers : split_tiles, fx_tiles2layers_preview(1) 44406#@gui : X-Tiles = int(3,1,100) 44407#@gui : Y-Tiles = int(3,1,100) 44408#@gui : Force Tiles to Have Same Size = _bool(false) 44409#@gui : sep = separator() 44410#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 44411fx_tiles2layers_preview : 44412 split_tiles $1,$2,$3 to_rgba frame 1,1,0,0,0,255 frame 3,3,0,0,0,0 append_tiles , 44413 44414#@gui Tones to Layers : fx_tones2layers, fx_tones2layers_preview(0) 44415#@gui : Number of Tones = int(3,2,10) 44416#@gui : Start of Mid-Tones = int(85,0,255) 44417#@gui : End of Mid-Tones = int(170,0,255) 44418#@gui : Smoothness = float(0.5,0,5) 44419#@gui : Alpha = choice("Binary","Scalar") 44420#@gui : sep = separator() 44421#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/05/04</i>.</small>") 44422fx_tones2layers : 44423 sval=$2 eval={max($2,$3)} 44424 remove_opacity repeat $! l[$<] 44425 +luminance rv 44426 repeat $1-1 44427 [1] 44428 val0={$sval+($eval-$sval)*$>/($1-2)} 44429 val1={$sval+($eval-$sval)*($>+1)/($1-2)-1} 44430 +ir[0] $val0,$val1 44431 if $5 *. [0] b. $4% n. 0,255 # Scalar alpha. 44432 else b. $4% n. 0,255 # Binary alpha. 44433 fi 44434 a[-2,-1] c 44435 done 44436 rm[0] rv 44437 endl done 44438 44439fx_tones2layers_preview : 44440 fx_tones2layers $* rv 44441 r {100/$!}%,{100/$!}%,1,100%,2 44442 to_rgba frame 1,1,0,0,0,255 frame 3,3,0,0,0,0 append_tiles , 44443 44444#@gui ____<b>Lights & Shadows</b> 44445#--------------------------------- 44446 44447#@gui Burn : fx_burn, fx_burn_preview(1) 44448#@gui : Amplitude = float(0.5,0,1) 44449#@gui : Scale = float(30,1,100) 44450#@gui : Smoothness = float(1,0,4) 44451#@gui : sep = separator() 44452#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44453#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44454#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44455#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44456#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44457#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44458#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44459#@gui : Value Action = choice("None","Cut","Normalize") 44460#@gui : sep = separator() 44461#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44462#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44463#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44464#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44465#@gui : sep = separator() 44466#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/24/11</i>.</small>") 44467_fx_burn : 44468 repeat $! l[$>] 44469 w,h={[w,h]} 44470 +norm 44471 fx_fourier. 2 44472 +rows. 0,{$h-1} r. $2%,$2%,1,100%,0,0,0.5,0.5 b. $3% 44473 j.. .,{($w-w)/2},{($h-h)/2} rm. 44474 fx_fourier[-2,-1] 2 44475 blend overlay,$1 44476 endl done 44477 44478fx_burn : 44479 ac "_fx_burn ${1-3}",$4,$5 44480 44481fx_burn_preview : 44482 gui_split_preview "fx_burn ${^0}",${-3--1} 44483 44484#@gui Contrast Swiss Mask : fx_contrast_swm , fx_contrast_swm(0) 44485#@gui : sep = separator() 44486#@gui : Blur the Mask = float(2,0.5,10) 44487#@gui : sep = separator() 44488#@gui : note = note ("Contrast Mask need the negative of the mask") 44489#@gui : Skip to Use the Mask to Boost = bool(false) 44490#@gui : note = note ("Uncheck for Contrast Mask,Check for Contrast Boost") 44491#@gui : sep = separator() 44492#@gui : note = note("Merge the Mask") 44493#@gui : Intensity = float(1,0,1) 44494#@gui : sep = separator() 44495#@gui : note = note("<small>Author: <i>PhotoComiX</i>. Latest Update: <i>2011/01/01</i>.</small>") 44496#@gui : url = link("Filter explained here","http://www.gimpchat.com/viewtopic.php?f=9&t=864") 44497fx_contrast_swm : 44498 repeat $! l[$>] split_opacity l[0] 44499 +luminance to_rgb 44500 blur_xy[1] $1,$1 44501 if $2==0 negate[1] fi 44502 rv blend hardlight,$3 44503 endl a c endl done 44504 44505#@gui Drop Shadow : fx_drop_shadow, fx_drop_shadow(1) 44506#@gui : X-Shadow = float(3,-20,20) 44507#@gui : Y-Shadow = float(3,-20,20) 44508#@gui : Smoothness = float(1.8,0,5) 44509#@gui : Curvature = float(0,0,1) 44510#@gui : Corner Brightness = float(0,0,1) 44511#@gui : Angle = float(0,0,360) 44512#@gui : sep = separator() 44513#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/14/11</i>.</small>") 44514fx_drop_shadow : 44515 * -1 + 255 vignette {255*$5},80,95 * -1 + 255 44516 drop_shadow $1%,$2%,$3%,$4 rotate $6,1,0 44517 44518#@gui Drop Shadow 3D : fx_drop_shadow3d, fx_drop_shadow3d_preview(1) 44519#@gui : X-Angle = float(0,-90,90) 44520#@gui : Y-Angle = float(0,-90,90) 44521#@gui : Z-Angle = float(0,-90,90) 44522#@gui : Zoom = float(0,-100,100) 44523#@gui : X-Offset = float(1,-50,50) 44524#@gui : Y-Offset = float(1,-50,50) 44525#@gui : Perspective = float(2,0,10) 44526#@gui : Smoothness = float(0.5,0,5) 44527#@gui : Color = color(0,0,0,200) 44528#@gui : Preview Only Shadow = bool(0) 44529#@gui : sep = separator() 44530#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/02/07</i>.</small>") 44531fx_drop_shadow3d : 44532 repeat $! l[$<] 44533 +_fx_drop_shadow3d $* 44534 endl done 44535 44536fx_drop_shadow3d_preview : 44537 repeat $! l[$<] 44538 if $13 _fx_drop_shadow3d $* 44539 else +_fx_drop_shadow3d $* rv blend alpha 44540 fi 44541 endl done 44542 44543_fx_drop_shadow3d : 44544 point3d 0,0,1 r3d. 1,0,0,$1 r3d. 0,1,0,$2 r3d. 0,0,1,$3 44545 u={i(0,8)} v={i(0,9)} w={i(0,10)} rm. 44546 to_a channels 100% if im==iM return fi 44547 +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)' 44548 +*. 'y/h-0.5' *.. 'x/w-0.5' +.. {0.5-$5/100} +. {0.5-$6/100} *.. {w} *. {h} 44549 a[-2,-1] c warp[0] .,0,1,0 rm. 44550 b $8% n 0,$12 i.. ($9^$10^$11) r.. .,.,1,3 a[-2,-1] c 44551 44552#@gui Equalize Light : fx_equalize_light, fx_equalize_light_preview(1) 44553#@gui : Amount (%) = float(75,0,100) 44554#@gui : Mode = choice("Preserve range","Preserve covariance") 44555#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44556#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44557#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44558#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44559#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44560#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44561#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44562#@gui : sep = separator() 44563#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44564#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44565#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44566#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44567#@gui : sep = separator() 44568#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/03/23</i>.</small>") 44569fx_equalize_light : 44570 ac "_fx_equalize_light $1,$2",$3,1 44571 44572_fx_equalize_light : 44573 repeat $! l[$>] split_opacity l[0] 44574 . +b. {max(0.1,100-$1)}% -[-2,-1] 44575 if $2 transfer_pca. .. else n. ..,.. fi 44576 rm.. 44577 endl a c endl done 44578 44579fx_equalize_light_preview : 44580 gui_split_preview "fx_equalize_light $*",${-3--1} 44581 44582#@gui Equalize Shadow : fx_equalize_shadow, fx_equalize_shadow_preview(1) 44583#@gui : Amplitude = float(1,0,1) 44584#@gui : sep = separator() 44585#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44586#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44587#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44588#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44589#@gui : sep = separator() 44590#@gui : note = note("<small>Authors: <i>Francois Grassard</i> and <i>David Tschumperlé</i>. 44591#@gui : Latest Update: <i>2021/03/23</i>.</small>") 44592fx_equalize_shadow : 44593 repeat $! l[$>] +negate blend softlight,$1 endl done 44594 44595fx_equalize_shadow_preview : 44596 gui_split_preview "fx_equalize_shadow $1",${-3--1} 44597 44598#@gui Guided Light Rays : fx_guided_lightrays,fx_guided_lightrays_preview(1) : + 44599#@gui : Amplitude (%) = float(10,0,100) 44600#@gui : Ray Length = float(2,0,2) 44601#@gui : Mode = choice("Boundary","Dense") 44602#@gui : Density (%) = float(80,0,100) 44603#@gui : Smoothness (%) = float(0.1,0,5) 44604#@gui : Threshold (%) = float(50,0,100) 44605#@gui : Light Position = point(50,50,0,1,255,255,0,-128,1%) 44606#@gui : Light Color = color(255,255,255) 44607#@gui : Blend Mode = choice(7,"Add","Alpha","Grain Merge","Hard Light","Lighten","Lightness", 44608#@gui : "Luminance","Overlay","Soft Light","Value") 44609#@gui : Opacity (%) = float(100,0,100) 44610#@gui : sep = separator() 44611#@gui : Preview Light Shape = bool(1) 44612#@gui : sep = separator() 44613#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/04/06</i>.</small>") 44614fx_guided_lightrays : 44615 bmode=${"arg0 $12,add,alpha,grainmerge,hardlight,lighten,lchlightness,\ 44616 luminance,overlay,softlight,value"} 44617 if $3 cond="i" else cond="i && !(j(-1) && j(1) && j(0,-1) && j(0,1))" fi 44618 if 0$_is_preview" && "$14 i[1] [0] gui_set_layer_opacity[1] 50 fi 44619 44620 l[0] # Process top layer only (light shape). 44621 if s==2" || "s==4 channels 100% else compose_channels max fi 44622 ge $6% 44623 44624 # Draw lightrays. 44625 100%,100% 44626 eval.. "* 44627 const L = $2<1?$2:$2^5; 44628 const Xl = $7<0?3*$7:$7>100?100+3*($7-100):$7; 44629 const Yl = $8<0?3*$8:$8>100?100+3*($8-100):$8; 44630 const xl = Xl*(w - 1)/100; 44631 const yl = Yl*(h - 1)/100; 44632 "$cond" && u<=$4%?( 44633 u = x - xl; v = y - yl; 44634 polygon(#-1,2,xl,yl,xl + L*u,yl + L*v,-1,255); 44635 )" 44636 44637 equalize. 65536,1,{iM} n. 0,1 power={10^(-$1%)} pow. {max(1e-2,$power)} b. $5% n. 0,255 44638 i[-2] (${9-11}:cyzx) r.. .,.,1,3 a[-2,-1] c 44639 k. gui_set_layer_mode $bmode gui_set_layer_opacity $13 44640 endl 44641 if 0$_is_preview gui_merge_layers 44642 elif $_output_mode k[0] 44643 fi 44644 44645fx_guided_lightrays_preview : 44646 _is_preview=1 44647 fx_guided_lightrays $* 44648 44649#@gui Illuminate 2D Shape : fx_illuminate_shape2d,fx_illuminate_shape2d_preview(1)+ 44650#@gui : note = note("<small><b>Input / Output:</b></small>) 44651#@gui : Input Type = choice{"Single Opaque Shapes Over Transp. BG","Multiple Colored Shapes Over Transp. BG", 44652#@gui : "Bump Map","Normal Map"} 44653#@gui : Output Type = choice{"Illumination","Bump Map","Normal Map"} 44654#@gui : Input Guide Color = color(255,0,0,255) 44655#@gui : Keep Base Layer as Input Background = bool(1) 44656#@gui : Keep Transparency in Output = bool(1) 44657#@gui : sep = separator() 44658#@gui : note = note("<small><b>Shape:</b></small>) 44659#@gui : Minimal Shape Area = int(4,1,100) 44660#@gui : note = note{"<small>Parameter <i>Minimal shape area</i> is only active in <i>Multiple colored shapes</i> 44661#@gui : input mode.</small>"} 44662#@gui : Preview Detected Shapes = bool(0) 44663#@gui : Erosion / Dilation = float(0,-10,10) 44664#@gui : Smoothness = float(3,0,6) 44665#@gui : Bump Factor = float(1,-5,5) 44666#@gui : Avg / Max Weight = float(1,0,1) 44667#@gui : Resolution = choice{4,"Full (Slower)","2048","1024","512","256","128","64 (Faster)"} 44668#@gui : sep = separator() 44669#@gui : note = note("<small><b>Illumination:</b></small>) 44670#@gui : Blending Mode = choice(10,"Normal","Lighten","Screen","Dodge","Add","Darken","Multiply","Burn","Overlay", 44671#@gui : "Soft Light","Hard Light","Grain Merge") 44672#@gui : Opacity (%) = float(75,0,100) 44673#@gui : Ambient (%) = float(30,-100,100) 44674#@gui : Diffuse (%) = float(40,0,200) 44675#@gui : Specular (%) = float(40,0,300) 44676#@gui : Shininess = float(80,0,100) 44677#@gui : Smoothness = float(0.2,0,5) 44678#@gui : Flatness = float(1,0,3) 44679#@gui : Linearity = float(0,-100,100) 44680#@gui : Levels = int(0,0,16) 44681#@gui : Light-X = float(2,-20,20) 44682#@gui : Light-Y = float(-2,-20,20) 44683#@gui : Light-Z = float(2,0,20) 44684#@gui : Normalize Illumination = bool(0) 44685#@gui : sep = separator() 44686#@gui : Open Interactive Preview = button() 44687#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44688#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44689#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44690#@gui : sep = separator() 44691#@gui : note = note{"<small><b>Note:</b> This filter automatically adds illumination to an opaque shape defined 44692#@gui : over a transparent background.</small>"} 44693#@gui : sep = separator() 44694#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/05/18</i>.</small>") 44695fx_illuminate_shape2d : 44696 input_type,\ 44697 output_type,\ 44698 keep_input_bg,\ 44699 preview_shapes,\ 44700 blending_mode,\ 44701 opacity=$1,$2,$7,$10,$16,$17 44702 blending_mode=${arg\ 1+$blending_mode,normal,lighten,screen,dodge,add,darken,multiply,burn,overlay,\ 44703 softlight,hardlight,grainmerge} 44704 keep_input_bg&={$!>1} 44705 44706 if $output_type # Output : bumpmap or normalmap 44707 repeat $!-$keep_input_bg _fx_illuminate_shape2d[$>] $* done 44708 44709 else # Output : illumination 44710 repeat $!-$keep_input_bg if $keep_input_bg sel=$>,-1 else sel=$> fi l[$sel] 44711 if !$keep_input_bg" && "$input_type>=2 # From bumpmap/normalmap w/o background 44712 _fx_illuminate_shape2d $* 44713 elif $keep_input_bg" && "$input_type>=2 # From bumpmap/normalmap w/ background 44714 _fx_illuminate_shape2d[0] $* 44715 elif !$keep_input_bg" && "$input_type<=1 # From shape w/o background 44716 +_fx_illuminate_shape2d $* rv 44717 else # From shape w/ background 44718 _fx_illuminate_shape2d[0] $* 44719 fi 44720 if !$preview_shapes" || "0$_is_preview!=1 44721 gui_set_layer_mode[0] $blending_mode 44722 gui_set_layer_opacity[0] $opacity 44723 if $!>1" && "(0$_output_mode==0" || "0$_is_preview==1) 44724 if $keep_input_bg" && "!0$_is_preview . fi 44725 gui_merge_layers[0,1] 44726 else k[0] fi 44727 fi 44728 endl done 44729 fi 44730 44731fx_illuminate_shape2d_preview : 44732 _is_preview=1 44733 input_type,\ 44734 keep_input_bg,\ 44735 preview_interactive=$1,$7,$-2 44736 keep_input_bg&={$!>1} 44737 if $preview_interactive fx_illuminate_shape2d_preview_interactive $* fi 44738 if $keep_input_bg 44739 repeat $!-1 l[$>,-1] 44740 fx_illuminate_shape2d $* 44741 rv to_colormode 0 a z 44742 gui_split_preview "slices 50%,100%",$-1 44743 endl done 44744 else 44745 gui_split_preview "fx_illuminate_shape2d $*",$-1 44746 fi 44747 44748fx_illuminate_shape2d_preview_interactive : 44749 _output_mode=0 44750 input_type,\ 44751 keep_input_bg=$1,$7 44752 keep_input_bg&={$!>1} 44753 repeat $!-$keep_input_bg if $keep_input_bg sel=$>,-1 else sel=$> fi +l[$sel] 44754 to_rgba 44755 +_fx_illuminate_shape2d[0] $1,2,${3-6},0,1,""$9,0,${11-15},""${16-29},""0,0 44756 if $!>2 rm[0] elif $input_type>=2 sh[0] 0,2 f. 128 rm. fi 44757 siz=${fitscreen\ {[w,h,1]},256,640} 44758 wsiz0=${fitscreen\ $siz,1,30%,100%} 44759 wsiz=$wsiz0 44760 r $siz,1,100%,3 44761 s. c,-3 !=. 0 l.. - 128 / 127 s c,-2 / endl a[-2,-1] c # Gradient map 44762 rv s. c,-3 44763 (160,128;128,160) r. 16,16 r. ..,..,1,3,0,2 44764 30,30,1,1 circle. 50%,50%,15%,1,1 b. 4 n. 0,1 44765 100%,100%,1,3,[255,255,0] 44766 nm normal,rgb,alpha,background,light_alpha,light_rgb 44767 44768 w[] $wsiz,0,0,{rgb,([{*,u},{*,v}]-[$wsiz])/2},"[G'MIC] Illuminate 2D Shape" 44769 cursor 0 44770 x0,y0,ox,oy,ob,olightz=-1 44771 lightz=2 clicked=0 44772 44773 do 44774 x,y,b,mw={rgb,[{*,x},{*,y}]*[w,h]/[{*,w},{*,h}]},{*,b},{*,-o} 44775 lightz={cut($lightz-0.3*sign($mw)+($y0>=0?3*($y-$y0)/h),0.1,4)} 44776 if $x<0 x,y={rgb,ang=$|;(1+[cos(1.4*ang),sin(0.85*ang)])*[w,h]/2} fi 44777 if !$b" || "($b&1) 44778 if $b" && "!$clicked x0,y0=$x,$y 44779 elif !$b x0,y0=-1 44780 fi 44781 lightx,lighty={rgb,3.5*(2*[$x/w,$y/h]-1)} 44782 if [$ox,$oy,$ob,$olightz]!=[$x,$y,$b,$lightz] 44783 +fx_illuminate_shape2d[normal,rgb] 4,0,${3-6},1,1,""$9,0,${11-15},""${16-25},$lightx,$lighty,$lightz,$29,""0,0 44784 +j[background] .,0,0,0,0,1,[alpha],255 rm.. 44785 +r2dx[light_alpha,light_rgb] {light_rgb,8+$lightz*(w-8)} j... .,{[$x,$y]-[w,h]/2},0,0,1,.. rm[-2,-1] 44786 r. $wsiz,1,100% to. "Light: ("{``{_round([$lightx,$lighty,$lightz],0.1)}}")",2,2,16 44787 w. rm. wait 20 44788 else wait 44789 fi 44790 clicked=$b 44791 elif $b&2 44792 +j[background] [rgb],0,0,0,0,1,[alpha],255 44793 +r2dx[light_alpha,light_rgb] {light_rgb,8+$lightz*(w-8)} j... .,{[$x,$y]-[w,h]/2},0,0,1,.. rm[-2,-1] 44794 w. rm. wait 44795 fi 44796 if {*,CTRLLEFT}" && "{*,-D} w[] {1.5*[{*,w},{*,h}]} wsiz={*,w},{*,h} 44797 elif {*,CTRLLEFT}" && "{*,-C} w[] {0.75*[{*,w},{*,h}]} wsiz={*,w},{*,h} 44798 elif {*,CTRLLEFT}" && "{*,-R} w[] $wsiz0 44799 fi 44800 ox,oy,ob=$x,$y,$b 44801 44802 while {*}" && "!{*,ESC}" && "!{*,Q} 44803 w 0 44804 rm endl done 44805 44806_fx_illuminate_shape2d : # Input selection must contains a single image. Output is a single image. 44807 input_type,\ 44808 output_type,\ 44809 gR,gG,gB,gA,\ 44810 keep_input_bg,\ 44811 keep_output_transparency,\ 44812 min_shape_area,\ 44813 preview_shapes,\ 44814 dilation,\ 44815 shape_smoothness,\ 44816 bump_factor,\ 44817 weight_avg_max,\ 44818 resolution,\ 44819 blending_mode,\ 44820 opacity,\ 44821 ambient,\ 44822 diffuse,\ 44823 specular,\ 44824 shininess,\ 44825 light_smoothness,\ 44826 flatness,\ 44827 linearity,\ 44828 levels,\ 44829 lightx,\ 44830 lighty,\ 44831 lightz,\ 44832 normalize_illumination,\ 44833 preview_interactive,\ 44834 preview_mode=${1-31} 44835 44836 # Generate 2D binary shape and corresponding bumpmap 44837 nm={n} 44838 if $input_type==0 # Single opaque shape 44839 to_rgba 44840 +channels. 100% >. 0 . 44841 select_color... 0,$gR,$gG,$gB,$gA 44842 mv... $! -[-2,-1] 44843 44844 elif $input_type==1 # Multiple colored shapes 44845 to_rgba 44846 +channels. 100% >. 0 *[-2,-1] 44847 if $min_shape_area>1 +quantize_area. {$min_shape_area^2} fi 44848 s. c,-{s-1} >. 0 rv[-2,-1] 44849 if s>1 f. "begin(A = resize([ 0,(s-1)/s ],s,3));I+A" norm. round. 0.01 fi 44850 label. 0,0 f. "j(1)!=i || j(0,1)!=i" thinning. 1 ==. 0 *. .. 44851 select_color... 0,$gR,$gG,$gB,$gA 44852 mv... $! -[-2,-1] 44853 44854 elif $input_type==2 # Bump map 44855 to_a 44856 s c,-{s-1} >. 0 *.. . rv s. c S={$!-1} +[^0] /. $S 44857 44858 elif $input_type==3 # Normal map 44859 +channels 100% >. 0 *.. . rv 44860 f. "I==vector4(0)?[128,128,255,255]:I" 44861 channels. 0,2 44862 44863 else # Gradient map (hidden mode used by interactive preview) 44864 +channels 100% rv 44865 fi 44866 44867 if 0$_is_preview" && "$preview_shapes 44868 if $input_type==3 k[0] else k. fi 44869 +dilate. 3 44870 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. 44871 *. 255 a c 44872 return 44873 fi 44874 44875 if $input_type<=1 44876 shape2bump. {arg($resolution,2048,1024,512,256,128,64)},$weight_avg_max,{$dilation%*max(w,h)},\ 44877 {$shape_smoothness*50} 44878 fi 44879 if $input_type<=2 44880 if $input_type==2" && "$shape_smoothness mM={[im,iM]} guided. ..,$shape_smoothness%,100 n. $mM fi 44881 *. $bump_factor 44882 fi 44883 44884 # Generate output. 44885 if $output_type==1 # Output as a bump map 44886 if $input_type<=2 44887 if $keep_output_transparency k[-2,-1] n 0,255 rv a c # With transparency 44888 else k. n 0,255 # Without transparency 44889 fi 44890 else 44891 rm gui_error_preview "Cannot convert a normal map to a bump map." return 44892 fi 44893 44894 elif $output_type==2 # Output as a normal map 44895 if $input_type<=2 round 0.0001 bump2normal. f. "i(#-2)?I:[128,128,255]" fi 44896 if $keep_output_transparency k[-2,-1] rv *. 255 a c # With transparency 44897 else k. # Without transparency 44898 fi 44899 44900 else # Output as illumination layer (phong model) 44901 if $input_type<=2 g. xy a[-2,-1] c 44902 elif $input_type==3 -. 128 /. 127 s. c,-2 /[-2,-1] 44903 fi 44904 f. "* 44905 begin( 44906 const flatness = "$flatness"; # Surface flatness 44907 const ka = "$ambient"%; # Ambient 44908 const kd = "$diffuse"%; # Diffuse 44909 const ks = "$specular"%; # Specular 44910 const alpha = "$shininess"; # Specularity 44911 const m1 = max(1,"$lightz"); 44912 const mwh1 = max(w,h) - 1; 44913 light = [ "m1*$lightx,m1*$lighty,-$lightz" ]; # Light position 44914 camera = [ 0,0,-"$lightz" ]; # Camera position 44915 ); 44916 res = i#0?( 44917 P = [ 2*x/mwh1 - 1,2*y/mwh1 - 1,0 ]; 44918 L = light - P; 44919 L/=norm(L); 44920 V = camera - P; 44921 V/=norm(V); 44922 N = -[ i0,i1,flatness ]; 44923 N/=norm(N); 44924 R = 2*dot(N,L)*N - L; 44925 res = ka + kd*dot(L,N) + ks*max(dot(R,V),0)^alpha; 44926 ):0; 44927 [ res,0 ]" 44928 channels. 0 *. 255 c. 0,255 44929 if $light_smoothness" || "$linearity 44930 mM={[im,iM]} 44931 if $light_smoothness b. $light_smoothness% fi 44932 if $linearity n. 0,1 ^. {10^-($linearity%)} fi 44933 n. $mM 44934 fi 44935 if $levels quantize. $levels,1,1 fi 44936 if $normalize_illumination n. 0,255 fi 44937 rv[-2,-1] *. 255 a[-2,-1] c 44938 nm $nm 44939 if !$keep_output_transparency remove_opacity. fi 44940 fi 44941 nm $nm 44942 44943#@gui Light Glow : fx_lightglow, fx_lightglow_preview(0) 44944#@gui : Density = float(30,0,100) 44945#@gui : Amplitude = float(0.5,0,2) 44946#@gui : Mode = choice(8,"Burn","Dodge","Freeze","Grain Merge","Hard Light","Interpolation","Lighten","Multiply", 44947#@gui : "Overlay","Reflect","Soft Light","Stamp","Value") 44948#@gui : Opacity = float(0.8,0,1) 44949#@gui : sep = separator() 44950#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 44951#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 44952#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 44953#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 44954#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 44955#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 44956#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 44957#@gui : sep = separator() 44958#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44959#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44960#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44961#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44962#@gui : sep = separator() 44963#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/21/02</i>.</small>") 44964_fx_lightglow : 44965 mode=${arg\ 1+$3,burn,dodge,freeze,grainmerge,hardlight,interpolation,lighten,multiply,overlay,reflect,\ 44966 softlight,stamp,value} 44967 repeat $! 44968 +gradient_norm. >=. {100-$1}% distance. 1 ^. $2 *. -1 n. 0,255 blend $mode,$4 44969 mv. 0 done 44970 44971fx_lightglow : 44972 ac "_fx_lightglow ${1-4}",$5 44973 44974fx_lightglow_preview : 44975 gui_split_preview "fx_lightglow $*",${-3--1} 44976 44977#@gui Light Leaks : fx_light_leaks, fx_light_leaks_preview(1) 44978#@gui : Leak Type = int(0,0,70) 44979#@gui : Angle = float(0,-180,180) 44980#@gui : X-Scale = float(1,1,10) 44981#@gui : Y-Scale = float(1,1,10) 44982#@gui : Hue = float(0,-180,180) 44983#@gui : Opacity = float(0.85,0,1) 44984#@gui : Blend Mode = choice(2,"Normal","Lighten","Screen","Dodge","Add","Darken","Multiply","Burn","Overlay", 44985#@gui : "Soft Light","Hard Light","Difference","Subtract","Grain Extract","Grain Merge","Divide","Hue","Saturation", 44986#@gui : "Value") 44987#@gui : Output as Separate Layers = _bool(1) 44988#@gui : sep = separator() 44989#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 44990#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 44991#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 44992#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 44993#@gui : sep = separator() 44994#@gui : note = note{"<small>This filter uses the free light leaks dataset available at :</small>"} 44995#@gui : url = link{"Lomo Light Leaks","http://www.photoshoptutorials.ws/downloads/mockups-graphics/lomo-light-leaks/"} 44996#@gui : sep = separator() 44997#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/01/07</i>.</small>") 44998fx_light_leaks : 44999 filename=lightleak_${"padint $1",6}.cimgz 45000 if isfile(['{/${-path_cache}$filename}']) i ${-path_cache}$filename 45001 else i https://gmic.eu/data_lightleaks/$filename o. ${-path_cache}$filename 45002 fi 45003 mode=${arg\ 1+$7,normal,lighten,screen,dodge,add,darken,multiply,burn,overlay,softlight,hardlight,difference,\ 45004 subtract,grainextract,grainmerge,divide,hue,saturation,value} 45005 mv. 0 45006 repeat $!-1 l[0,{1+$<}] 45007 +r[0] {1,w},{1,h},1,3,5 45008 rotate. $2,1,1,50%,50% 45009 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 45010 c. 0,255 45011 if $5 rgb2hsv. sh. 0 +. $5 rm. hsv2rgb. fi 45012 if $8 45013 nm=${gui_layer_name[1]} 45014 nm. name($nm),opacity({$6*100}),mode($mode) rv[-2,-1] 45015 else blend[1,-1] $mode,$6 fi 45016 endl done 45017 rm[0] 45018 45019fx_light_leaks_preview : 45020 gui_split_preview "fx_light_leaks ${1--5},0",${-3--1} 45021 45022_fx_light_leaks : 45023 u="" repeat 71 if narg($u) u=$u, fi u=${u}lightleak_${"padint "$>,6} done 45024 u $u 45025 45026#@gui Light Patch : fx_light_patch, fx_light_patch(0) 45027#@gui : Density = int(5,2,30) 45028#@gui : Darkness = float(0.7,0,1) 45029#@gui : Lightness = float(2.5,1,4) 45030#@gui : sep = separator() 45031#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45032#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45033#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45034#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45035#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45036#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45037#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45038#@gui : sep = separator() 45039#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45040fx_light_patch : 45041 repeat $! l[$>] split_opacity l[0] 45042 ac "light_patch $1,$2,$3",$4 45043 endl a c endl done 45044 45045#@gui Light Rays : fx_lightrays, fx_lightrays(1) 45046#@gui : Density = float(80,0,100) 45047#@gui : Center (%) = point(50,50,0,1) 45048#@gui : Length = float(1,0,1) 45049#@gui : Attenuation = float(0.5,0,1) 45050#@gui : Transparency = bool(0) 45051#@gui : sep = separator() 45052#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/03/01</i>.</small>") 45053fx_lightrays : 45054 lightrays $1,$2%,$3%,$4,$5 45055 if $6 repeat $! r[$>] 100%,100%,1,{{$>,s}+({$>,s}%2)} done fi 45056 45057#@gui Pop Shadows : fx_pop_shadows, fx_pop_shadows_preview(1) 45058#@gui : Strength = float(0.75,0,1) 45059#@gui : Scale = float(5,0,20) 45060#@gui : Post-Normalize = bool(1) 45061#@gui : sep = separator() 45062#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45063#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45064#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45065#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45066#@gui : sep = separator() 45067#@gui : note = note("<small>Authors: <i>Morgan Hardwood</i> and <i>David Tschumperlé</i>. 45068#@gui : Latest Update: <i>2017/03/05</i>.</small>") 45069fx_pop_shadows : 45070 repeat $! l[$>] split_opacity l[0] 45071 .x2 45072 luminance.. negate.. imM={-2,[im,iM]} b.. $2% n.. $imM 45073 blend[0,1] overlay,$1 45074 max 45075 if $3 n 0,255 fi 45076 endl a c endl done 45077 45078fx_pop_shadows_preview : 45079 gui_split_preview "fx_pop_shadows $*",${-3--1} 45080 45081#@gui Relief Light : fx_light_relief, fx_light_relief(1) 45082#@gui : Ambient Lightness = float(0.3,0,5) 45083#@gui : Specular Lightness = float(0.2,0,2) 45084#@gui : Specular Size = float(0.2,0,1) 45085#@gui : Darkness = float(0,0,1) 45086#@gui : Light Smoothness = float(1,0,5) 45087#@gui : XY-Light = point(50,50,0,1,255,255,128,200,10) 45088#@gui : Z-Light = float(5,0,20) 45089#@gui : Z-Scale = float(0.5,0,3) 45090#@gui : Opacity as Heightmap = bool(0) 45091#@gui : Image Smoothness = float(0,0,10) 45092#@gui : sep = separator() 45093#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45094fx_light_relief : 45095 b $11% light_relief ${1-5},{[$6,$7]%},${8-10} 45096 45097#@gui Shadow Patch : fx_shadow_patch, fx_shadow_patch(1) 45098#@gui : Opacity = float(0.7,0,1) 45099#@gui : sep = separator() 45100#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45101#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45102#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45103#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45104#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45105#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45106#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45107#@gui : sep = separator() 45108#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45109fx_shadow_patch : 45110 repeat $! l[$>] split_opacity l[0] 45111 ac "shadow_patch $1",$2 45112 endl a c endl done 45113 45114#@gui Slice Luminosity : fx_slice_luminosity, fx_slice_luminosity_preview 45115#@gui : Luminosity Type = choice(1,"Average RGB","Luminance","Lightness","Value") 45116#@gui : Output As = _choice(1,"Mask","Masked Image") 45117#@gui : Preview Type = choice(2,"Mask","Mask + Background","Image","Image + Background") 45118#@gui : sep = separator() 45119#@gui : note = note{"<small><b>Slice 1</b> (shadows):</small>"} 45120#@gui : Activate Slice 1 = bool(1) 45121#@gui : Starting Value = int(0,0,255) 45122#@gui : Ending Value = int(64,0,255) 45123#@gui : Starting Feathering = int(0,0,255) 45124#@gui : Ending Feathering = int(0,0,255) 45125#@gui : sep = separator() 45126#@gui : note = note{"<small><b>Slice 2</b> (low midtones):</small>"} 45127#@gui : Activate Slice 2 = bool(1) 45128#@gui : Starting Value = int(64,0,255) 45129#@gui : Ending Value = int(128,0,255) 45130#@gui : Starting Feathering = int(0,0,255) 45131#@gui : Ending Feathering = int(0,0,255) 45132#@gui : sep = separator() 45133#@gui : note = note{"<small><b>Slice 3</b> (high midtones):</small>"} 45134#@gui : Activate Slice 3 = bool() 45135#@gui : Starting Value = int(128,0,255) 45136#@gui : Ending Value = int(192,0,255) 45137#@gui : Starting Feathering = int(0,0,255) 45138#@gui : Ending Feathering = int(0,0,255) 45139#@gui : sep = separator() 45140#@gui : note = note{"<small><b>Slice 4</b> (highlights):</small>"} 45141#@gui : Activate Slice 4 = bool() 45142#@gui : Starting Value = int(192,0,255) 45143#@gui : Ending Value = int(255,0,255) 45144#@gui : Starting Feathering = float(0,0,255) 45145#@gui : Ending Feathering = float(0,0,255) 45146#@gui : sep = separator() 45147#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/22/09</i>.</small>") 45148fx_slice_luminosity : 45149 remove_opacity repeat $! l[$<] to_rgb 45150 _fx_slice_luminosity $* 45151 if $2 i[0] [0] a[-2,-1] c fi 45152 rv 45153 endl done 45154 45155fx_slice_luminosity_preview : 45156 remove_opacity repeat $! l[$>] to_rgb 45157 _fx_slice_luminosity $* 45158 if $3==0 rm[0] channels {s-1} 45159 elif $3==1 100%,100%,1,1,128 a[0,-1] c r. 100%,100%,1,4 blend alpha 45160 elif $3==2 a c 45161 else +. 96 c. 0,255 a c 45162 fi 45163 endl done 45164 45165_fx_slice_luminosity : 45166 if $1==0 +compose_channels + /. 3 45167 elif $1==1 +luminance 45168 elif $1==2 +srgb2lab8. channels. 0 45169 else +compose_channels max 45170 fi 45171 if $4 +apply_curve[1] 0,{$5-$7-0.1},0,$5,255,$6,255,{$6+$8+0.1},0,512,0 fi 45172 if $9 +apply_curve[1] 0,{$10-$12-0.1},0,$10,255,$9,255,{$11+$13+0.1},0,512,0 fi 45173 if $14 +apply_curve[1] 0,{$15-$17-0.1},0,$15,255,$16,255,{$16+$18+0.1},0,512,0 fi 45174 if $19 +apply_curve[1] 0,{$20-$22-0.1},0,$20,255,$21,255,{$21+$23+0.1},0,512,0 fi 45175 rm[1] max[^0] 45176 45177#@gui ____<b>Patterns</b> 45178#------------------------ 45179 45180#@gui Bayer Filter : rgb2bayer, rgb2bayer(0) 45181#@gui : Starting Pattern = choice(0,"Red-Green","Blue-Green","Green-Red","Green-Blue") 45182#@gui : Keep Colors = bool(1) 45183#@gui : sep = separator() 45184#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45185 45186#@gui Box Fitting : fx_boxfitting, fx_boxfitting_preview(0) 45187#@gui : Minimal Size = int(3,1,32) 45188#@gui : Maximal Size = int(0,0,32) 45189#@gui : note = note("<small><b>Note:</b> Set <i>Maximal size</i> to <i>0</i> to allow any size 45190#@gui : for the squares.</small>") 45191#@gui : Initial Density = float(0.1,0,1) 45192#@gui : Transparency = bool(0) 45193#@gui : sep = separator() 45194#@gui : note = note("<small><b>Note:</b> This filter has been highly inspired by the work of Jared Tarbell, 45195#@gui : described on the page:</small>") 45196#@gui : url = link("http://www.complexification.net/gallery/machines/boxFittingImg/") 45197#@gui : sep = separator() 45198#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/06/06</i>.</small>") 45199fx_boxfitting : 45200 boxfitting ${1-3},3 45201 if $4 to_rgba replace_color 0,0,0,0,0,255,0,0,0,0 fi 45202 45203fx_boxfitting_preview : 45204 boxfitting ${1-3},1 45205 if $4 to_rgba replace_color 0,0,0,0,0,255,0,0,0,0 fi 45206 45207#@gui Camouflage : fx_camouflage, fx_camouflage 45208#@gui : Scale = int(9,2,12) 45209#@gui : Levels = int(12,2,32) 45210#@gui : Coherence = float(100,0,1000) 45211#@gui : Color 1 = color(30,46,33) 45212#@gui : Color 2 = color(75,90,65) 45213#@gui : Color 3 = color(179,189,117) 45214#@gui : Color 4 = color(255,246,158) 45215#@gui : sep = separator() 45216#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/26/10</i>.</small>") 45217fx_camouflage : 45218 repeat $! l[$>] split_opacity l[0] 45219 channels 0 r {w+16},{h+16},1,1,0 rand 0,16 45220 amp=$3 do smooth {min(50,$amp)},0,1 amp-=50 while $amp>0 45221 shrink_xy. 8 n 1,$2 round 45222 repeat $1 +area 0,0 <. {1+2^$>} inpaint[0] [1],0,3 rm. done 45223 +colormap 0 n.. 0,{w-1} 45224 4,1,1,3,"col=[${4-15}];col[3*x,3]" 45225 r. ..,..,1,3,3 rm.. map.. . rm. 45226 endl a c endl done 45227 45228#@gui Canvas : fx_canvas, fx_canvas_preview(0) 45229#@gui : note = note{"<b>First direction :</b>"} 45230#@gui : Amplitude = float(70,0,300) 45231#@gui : Angle = float(45,0,180) 45232#@gui : Sharpness = float(400,0,2000) 45233#@gui : note = note{"\n<b>Second direction : </b>"} 45234#@gui : Activate Second Direction = bool(true) 45235#@gui : Amplitude = float(70,0,300) 45236#@gui : Angle = float(135,0,180) 45237#@gui : Sharpness = float(400,0,2000) 45238#@gui : sep = separator() 45239#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45240#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45241#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45242#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45243#@gui : sep = separator() 45244#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45245fx_canvas : 45246 repeat $! l. 45247 if $4 45248 ({cos($2*pi/180)}^{sin($2*pi/180)}) vector2tensor. r. ..,.. +smooth.. .,$1 rm.. sharpen. $3 c. 0,255 45249 ({cos($6*pi/180)}^{sin($6*pi/180)}) vector2tensor. r. ..,.. smooth... .,$5 rm. sharpen.. $7 c.. 0,255 45250 +[-2,-1] /. 2 45251 else 45252 ({cos($2*pi/180)}^{sin($2*pi/180)}) vector2tensor. r. ..,.. smooth.. .,$1 rm. sharpen. $3 c. 0,255 45253 fi 45254 endl mv. 0 done 45255 45256fx_canvas_preview : 45257 gui_split_preview "fx_canvas $*",${-3--1} 45258 45259#@gui Canvas Texture : texturize_canvas, texturize_canvas(0) 45260#@gui : Amplitude = float(20,0,256) 45261#@gui : Fibrousness = float(3,0,20) 45262#@gui : Emboss = float(0.6,0,1) 45263#@gui : sep = separator() 45264#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45265 45266#@gui Cracks : fx_cracks, fx_cracks_preview(0) 45267#@gui : Density (%) = float(30,0,100) 45268#@gui : Relief = bool(true) 45269#@gui : Color = color(255,255,255,128) 45270#@gui : sep = separator() 45271#@gui : Channel(s) = choice("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>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/07</i>.</small>") 45285fx_cracks : 45286 ac "cracks $1,$2,{$6/255},${3-5},255",$7 45287 45288fx_cracks_preview : 45289 gui_split_preview "fx_cracks $*",${-3--1} 45290 45291#@gui Crystal : fx_crystal, fx_crystal_preview(0) 45292#@gui : Density = float(50,0,100) 45293#@gui : Smoothness = float(0.2,0,2) 45294#@gui : Edges = float(20,0,100) 45295#@gui : sep = separator() 45296#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45297#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45298#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45299#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45300#@gui : sep = separator() 45301#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/19/01</i>.</small>") 45302fx_crystal : 45303 repeat $! l[$>] split_opacity l[0] 45304 s={s} 45305 +gradient_norm >=. {(100-$3)/5} remove_pixels. {100-max(0.1,$1*$3%)}%,{is} * 45306 +norm !=. 0 a c 45307 sigma=0.2 45308 do 45309 +b. $sigma sigma*={(1+$2)} 45310 sh[0,-1] $s max. .. rm[-2,-1] 45311 f. 'W=i(x,y,z,$s);if(W<0.001||W>=1,0,if(c<$s,i/W,1))' 45312 if !iM rm[1] break fi 45313 sh. $s 45314 j[0] [1],0,0,0,0,1,[2] k[0] 45315 while 1 45316 channels 0,{$s-1} 45317 endl a c endl done 45318 45319fx_crystal_preview : 45320 gui_split_preview "fx_crystal $*",${-3--1} 45321 45322#@gui Crystal Background : fx_crystal_background, fx_crystal_background 45323#@gui : Iterations = int(10,1,32) 45324#@gui : Density (%) = float(25,0,100) 45325#@gui : Random Seed = int(0,0,65535) 45326#@gui : Opacity (%) = float(100,0,100) 45327#@gui : Color = bool(1) 45328#@gui : sep = separator() 45329#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/18/10</i>.</small>") 45330fx_crystal_background : 45331 repeat $! l[$>] split_opacity l[0] 45332 N={2*max(3,round((${"is_percent $2"}?4*wh*$2:$2)))} 45333 if $5 col="u([255,255,255])" else col="u(255)" fi 45334 srand $3 M={max(w,h)} 2,$N 45335 repeat $1 rand. {-$M/2},{3*$M/2} polygon.. $N,{^},{-$4%},{$col} done 45336 rm. n 0,255 45337 endl a c endl done 45338 45339#@gui Halftone : fx_halftone, fx_halftone_preview(0) 45340#@gui : note = note("<b><small>Image parameters :</small></b>") 45341#@gui : Brightness (%) = float(0,-100,100) 45342#@gui : Contrast (%) = float(0,-100,100) 45343#@gui : Gamma (%) = float(0,-100,100) 45344#@gui : Smoothness = float(0,0,10) 45345#@gui : sep = separator() 45346#@gui : note = note("<b><small>Halftone parameters :</small></b>") 45347#@gui : Number of Tones = int(5,2,32) 45348#@gui : Size for Dark Tones = int(8,2,256) 45349#@gui : Size for Bright Tones = int(8,2,256) 45350#@gui : Shape = choice{5,"Square","Diamond","Circle","Square (Inv.)","Diamond (Inv.)","Circle (Inv.)"} 45351#@gui : Smoothness = float(0.1,0,32) 45352#@gui : sep = separator() 45353#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45354#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45355#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45356#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45357#@gui : sep = separator() 45358#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/23/07</i>.</small>") 45359fx_halftone : 45360 adjust_colors ${1-3},0,0,0,255 b $4 45361 repeat $! l[$>] split_opacity 45362 halftone[0] ${5-9} 45363 a c endl done 45364 45365fx_halftone_preview : 45366 gui_split_preview "fx_halftone $*",${-3--1} 45367 45368#@gui Hearts : fx_hearts, fx_hearts_preview(0) 45369#@gui : Density = float(2,0,30) 45370#@gui : sep = separator() 45371#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45372#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45373#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45374#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45375#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45376#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45377#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45378#@gui : sep = separator() 45379#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45380#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45381#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45382#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45383#@gui : sep = separator() 45384#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45385fx_hearts : 45386 ac "hearts $1",$2 45387 45388fx_hearts_preview : 45389 gui_split_preview "fx_hearts $*",${-3--1} 45390 45391#@gui Lava : fx_lava, fx_lava_preview(0) 45392#@gui : Perturbation = int(8,0,15) 45393#@gui : Smoothness = float(5,0,100) 45394#@gui : Scale = float(3,0,20) 45395#@gui : Sharpness = float(0,0,1000) 45396#@gui : sep = separator() 45397#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45398#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45399#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45400#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45401#@gui : sep = separator() 45402#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/26/11</i>.</small>") 45403fx_lava : 45404 repeat $! l[$>] split_opacity l[0] norm 45405 100%,100% plasma. 1,1,{16-$1} smooth. $2,0,1,$3,$3,0.8,90 * 45406 gradient_norm n 0,255 45407 equalize map 3 45408 sharpen $4 45409 endl a c endl done 45410 45411fx_lava_preview : 45412 gui_split_preview "fx_lava $*",${-3--1} 45413 45414#@gui Marble : fx_marble, fx_marble 45415#@gui : Image Weight = float(.5,0,30) 45416#@gui : Pattern Weight = float(1,0,30) 45417#@gui : Pattern Angle = float(0,0,360) 45418#@gui : Amplitude = float(0,0,1000) 45419#@gui : Sharpness = float(.4,0,5) 45420#@gui : Anisotropy = float(.6,0,1) 45421#@gui : Alpha = float(.6,0,20) 45422#@gui : Sigma = float(1.1,0,20) 45423#@gui : Cut Low = float(0,0,100) 45424#@gui : Cut High = float(100,0,100) 45425#@gui : sep = separator() 45426#@gui : note = note("<small>Author: <i>Preben Soeberg</i>. Latest Update: <i>2010/29/12</i>.</small>") 45427fx_marble : 45428 repeat $! l[$>] split_opacity l[0] 45429 marble $1/10,$2/10,$3,$4,$5,$6,$7,$8,$9%,$10% 45430 endl a c endl done 45431 45432#@gui Maze : fx_maze, fx_maze 45433#@gui : Cell Size = int(24,1,256) 45434#@gui : Thickness = int(1,1,10) 45435#@gui : Masking = choice("None","Render on Dark Areas","Render on White Areas") 45436#@gui : Preserve Image Dimension = bool(1) 45437#@gui : Maze Type = choice("Dark Walls","White Walls") 45438#@gui : sep = separator() 45439#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/02/09</i>.</small>") 45440fx_maze : 45441 repeat $! l[$>] 45442 w={w} h={h} 45443 r. {100/$1}%,{100/$1}%,1,100%,2 45444 if $3==0 f. 1 45445 elif $3==1 negate. 45446 fi 45447 maze_mask. $1 dilate. $2 *. 255 45448 if !$5 negate. fi 45449 if $4 r. $w,$h,100%,100% fi 45450 endl done 45451 45452#@gui Mineral Mosaic : fx_mineral_mosaic,fx_mineral_mosaic(0) 45453#@gui : Density = float(1,0,3) 45454#@gui : Area = float(2,0,32) 45455#@gui : Smoothness = float(1,0,10) 45456#@gui : Shade Strength = float(100,0,255) 45457#@gui : Shade Angle = float(0,0,360) 45458#@gui : sep = separator() 45459#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/01/02</i>.</small>") 45460fx_mineral_mosaic : 45461 repeat $! l[$>] to_rgb 45462 +b $3 segment_watershed. $1 +norm. 45463 area. 0 +<=. {$2^2} inpaint.. . rm. label. 45464 +f[0] 'if(c==0,x,y)' rv[-2,-1] +blend[-2,-1] shapeaverage,1,1 45465 -[-3,-1] rm[0,-2] channels. 0,1 45466 alpha={$5*pi/180} sh. 0 *. {cos($alpha)} rm. sh. 1 *. {sin($alpha)} rm. compose_channels. + 45467 normalize_local. 1000 n. -$4,$4 45468 + c 0,255 45469 endl done 45470 45471#@gui Mosaic : fx_mosaic, fx_mosaic_preview(0) 45472#@gui : Density (%) = float(50,0,100) 45473#@gui : sep = separator() 45474#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45475#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45476#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45477#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45478#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45479#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45480#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45481#@gui : sep = separator() 45482#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45483#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45484#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45485#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45486#@gui : sep = separator() 45487#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/19/07</i>.</small>") 45488fx_mosaic : 45489 ac "repeat $! l[$>] split_opacity mosaic[0] $1 a c endl done",$2 45490 45491fx_mosaic_preview : 45492 gui_split_preview "fx_mosaic $*",${-3--1} 45493 45494#@gui Op Art : fx_shapes,fx_shapes_preview(0) 45495#@gui : Shape = choice{1,"Custom Layers","Circles","Squares","Diamonds","Triangles","Horizontal Stripes", 45496#@gui : "Vertical Stripes","Balls","Hearts","Stars","Arrows","Truchet","Circles (Outline)","Squares (Outline)", 45497#@gui : "Diamonds (Outline)","Triangles (Outline)","Hearts (Outline)","Stars (Outline)","Arrows (Outline)"} 45498#@gui : Number of Scales = int(16,2,24) 45499#@gui : Resolution = float(10,1,50) 45500#@gui : Zoom Factor = _int(2,1,8) 45501#@gui : Minimal Size = float(5,0,150) 45502#@gui : Maximal Size = float(90,0,150) 45503#@gui : Stencil Type = choice(0,"Black & White","RGB","Color") 45504#@gui : Allow Angle = choice("0 deg.","90 deg.","180 deg.") 45505#@gui : Negative = bool(1) 45506#@gui : Antialiasing = bool(1) 45507#@gui : sep = separator() 45508#@gui : note = note{"<small><b>Note:</b> 45509#@gui : If you set the parameter <i>Shape</i> to <i>Custom layers</i>, the different shapes used to map 45510#@gui : the pixel intensities will be defined as 45511#@gui : the <i>Number of scales</i> top layers of your image. Don't forget to set also <i>Input layers</i> to 45512#@gui : <i>All</i> to be sure 45513#@gui : these layers are passed to the filter. 45514#@gui : </small>"} 45515#@gui : sep = separator() 45516#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45517#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45518#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45519#@gui : sep = separator() 45520#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/16/12</i>.</small>") 45521fx_shapes : 45522 if $1 # Pre-defined shapes. 45523 remove_opacity repeat $! l[$>] 45524 if !$7 _fx_shapes $* * 255 45525 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 45526 else +_fx_shapes $* r[0] $3%,$3% r[0] [1],[1] * 45527 fi 45528 endl done 45529 else # Custom shapes. 45530 if $!<=$2 45531 error[] "Command '$0': Some layers are missing in 'Custom layers' mode ("{$2+1}" expected at least, "\ 45532 $!" provided)." fi 45533 to_colormode[0-{$2-1}] ${max_s[0-{$2-1}]} remove_opacity[$2--1] 45534 repeat $!-$2 l[0-{$2-1},{$2+$>}] 45535 norm. w={w} h={h} r. $3%,$3%,1,1,2 45536 s={$4*max(round($w/w),round($h/h))} 45537 r0={$s*$5%} r1={$s*$6%} 45538 repeat $2 r={round($r0+$>*($r1-$r0)/($2-1))} if $r +r[$>] $r,$r,1,100%,3 else 1,1 fi done 45539 r[-$2--1] $s,$s,1,100%,0,0,0.5,0.5 45540 map_sprites[$2--1] $2,$8 45541 endl done rm[0-{$2-1}] 45542 fi 45543 45544fx_shapes_preview : 45545 if $1 repeat $! l[$>] 45546 w={w} h={h} 45547 gui_split_preview "fx_shapes ${1-3},1,${5--2}",$-1 45548 r $w,$h,1,100%,0,0,0.5,0.5 45549 endl done 45550 else 45551 if $!>$2 repeat $!-$2 l[0-{$2-1},{$2+$>}] 45552 w={w} h={h} 45553 +fx_shapes ${1-3},1,${5--2} rm.. 45554 r. $w,$h,1,100%,0,0,0.5,0.5 45555 endl done rm[0-{$2-1}] 45556 else gui_warning_preview "Missing input layers!" 45557 fi 45558 fi 45559 45560_fx_shapes : 45561 norm w={w} h={h} r $3%,$3%,1,1,2 45562 s={(1+$10)*$4*max(round($w/w),round($h/h))} 45563 r0={$s*$5%} r1={$s*$6%} 45564 repeat $2 r={round($r0+$>*($r1-$r0)/($2-1))} if $r _fx_shapes{$1-1}[] $r,$s else 1,1 fi done 45565 r[-$2--1] $s,$s,1,1,0,0,0.5,0.5 45566 if $9 rv[-$2--1] *[-$2--1] -1 +[-$2--1] 1 fi 45567 map_sprites $2,$8 45568 if $10 r 50%,50%,1,1,2 fi 45569 45570_fx_shapes0 : 45571 shape_circle $1 45572 45573_fx_shapes1 : 45574 $1,$1,1,1,1 45575 45576_fx_shapes2 : 45577 $1,$1,1,1 = 1,50%,50% distance 1,1 < {$1/2} 45578 45579_fx_shapes3 : 45580 $2,$2,1,1,'x+y<=2*$1-1' 45581 45582_fx_shapes4 : 45583 $2,$1,1,1,1 45584 45585_fx_shapes5 : 45586 $1,$2,1,1,1 45587 45588_fx_shapes6 : 45589 ball $1,200 n 0,1 45590 45591_fx_shapes7 : 45592 shape_heart 65 r $1,$1,1,1,2 >= 50% 45593 45594_fx_shapes8 : 45595 shape_star $1 45596 45597_fx_shapes9 : 45598 arrow3d 0,0,0,1,0,0,15%,40%,30% col3d 1 *3d $1 c3d 45599 $2,$2 j3d. ..,50%,50%,0,1,2,0,0 45600 rm.. +mirror y max 45601 45602_fx_shapes10 : 45603 S={$2+1-($2%2)} 45604 $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)" 45605 +mirror xy max 45606 45607_fx_shapes11 : 45608 _fx_shapes0 $* expand_xy 1,0 +erode 3 - 45609 45610_fx_shapes12 : 45611 _fx_shapes1 $* expand_xy 1,0 +erode 3 - 45612 45613_fx_shapes13 : 45614 _fx_shapes2 $* expand_xy 1,0 +erode 3 - 45615 45616_fx_shapes14 : 45617 _fx_shapes3 $* expand_xy 1,0 +erode 3 - 45618 45619_fx_shapes15 : 45620 _fx_shapes7 $* expand_xy 1,0 +erode 3 - 45621 45622_fx_shapes16 : 45623 _fx_shapes8 $* expand_xy 1,0 +erode 3 - 45624 45625_fx_shapes17 : 45626 _fx_shapes9 $* expand_xy 1,0 +erode 3 - 45627 45628#@gui Pack Sprites : fx_pack_sprites, gui_no_preview 45629#@gui : Number of Scales = int(5,1,16) 45630#@gui : Minimal Scale (%) = float(25,1,100) 45631#@gui : Allow Angle = choice(3,"0 deg.","180 deg.","90 deg.","Any") 45632#@gui : Spacing = int(1,-16,16) 45633#@gui : Precision = int(7,1,32) 45634#@gui : sep = separator() 45635#@gui : Masking = choice("No Masking","Mask as Bottom Layer") 45636#@gui : Width = int(512,32,2048) 45637#@gui : Height = int(512,32,2048) 45638#@gui : note = note("<small><b>Notes:</b>\n - Parameters <i>Width</i> and <i>Height</i> are considered only when 45639#@gui : <i>No masking</i> mode is selected.\n 45640#@gui : - Set different sprites on different layers to pack multiple sprites at the same time.</small>") 45641#@gui : url = link("Click here for a video tutorial","http://www.youtube.com/watch?v=bpg7CGH7vCM") 45642#@gui : sep = separator() 45643#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/24/06</i>.</small>") 45644fx_pack_sprites : 45645 if $6 # With mask. 45646 if $!<2 error[] "Command '$0': Masking requires at least two input layers ! 45647 (please check that 'Input Layers' is correctly set)." fi 45648 repeat $!-1 l[$>] to_rgba split_opacity +!=[1] 0 *[0] . a c autocrop 0 endl done 45649 remove_empty[0--2] +channels. 100% channels. -4,0 mv. 0 45650 pack_sprites[0--2] ${1-5} 45651 else # No masking 45652 repeat $! l[$>] to_rgba split_opacity +!=[1] 0 *[0] . a c autocrop 0 endl done 45653 remove_empty i[0] $7,$8,1,5 pack_sprites ${1-5} 45654 fi 45655 channels[0] 0,{0,s-2} 45656 45657#@gui Paper Texture : fx_paper, fx_paper_preview(0) 45658#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45659#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45660#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45661#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45662#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45663#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45664#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45665#@gui : sep = separator() 45666#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45667#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45668#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45669#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45670#@gui : sep = separator() 45671#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45672fx_paper : 45673 ac "texturize_paper",$1 45674 45675fx_paper_preview : 45676 gui_split_preview "fx_paper $*",${-3--1} 45677 45678#@gui Plaid : fx_plaid_texture,fx_plaid_texture(1) 45679#@gui : Line = float(50,0,100) 45680#@gui : Number of Angles = int(2,1,8) 45681#@gui : Starting Angle = float(0,0,360) 45682#@gui : Angle Range = float(90,0,360) 45683#@gui : Smoothness = float(1,0,5) 45684#@gui : Sharpen = float(300,0,1000) 45685#@gui : sep = separator() 45686#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/16/05</i>.</small>") 45687fx_plaid_texture : 45688 repeat $! l[$>] 45689 w={w} h={h} s={s} 45690 rows $1% 45691 b $5% sharpen $6 45692 r $w,$h,1,$s,2 45693 +rotate[0] $3,1,2,50%,50% 45694 repeat $2-1 +rotate[0] {$3+$4*($>+1)/($2-1)},1,2,50%,50% +[-2,-1] done rm[0] 45695 / $2 45696 endl done 45697 45698#@gui Polka Dots : fx_polka_dots, fx_polka_dots(1) 45699#@gui : Size = float(80,0,100) 45700#@gui : Density = float(20,0.1,100) 45701#@gui : First Offset = float(50,0,100) 45702#@gui : Second Offset = float(50,0,100) 45703#@gui : Angle = float(0,0,180) 45704#@gui : Aliasing = float(0.5,0.1,1) 45705#@gui : Shading = float(0.1,0.1,1) 45706#@gui : Opacity = float(1,0,1) 45707#@gui : Color = color(255,0,0,255) 45708#@gui : sep = separator() 45709#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45710fx_polka_dots : 45711 to_rgba polka_dots {$1*$2/100},${2--1} 45712 45713#@gui Random Color Ellipses : fx_color_ellipses, fx_color_ellipses(1) 45714#@gui : Density = int(400,0,3000) 45715#@gui : Radius = float(8,0,30) 45716#@gui : Opacity = float(0.1,0.01,0.5) 45717#@gui : sep = separator() 45718#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45719fx_color_ellipses : 45720 color_ellipses $1,$2,$3 45721 45722#@gui Random Pattern : fx_random_pattern, fx_random_pattern_preview(1) 45723#@gui : Size = _int(1024,16,8192) 45724#@gui : Min Detail Level = float(2,0,20) 45725#@gui : Seed = float(4038,0,100000) 45726#@gui : Randomize Seed = button() 45727#@gui : sep = separator() 45728#@gui : Brightness (%) = float(0,-100,100) 45729#@gui : Contrast (%) = float(0,-100,100) 45730#@gui : Gamma (%) = float(0,-100,100) 45731#@gui : Hue (%) = float(0,-100,100) 45732#@gui : Saturation (%) = float(0,-100,100) 45733#@gui : sep = separator() 45734#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/10/08</i>.</small>") 45735_fx_random_pattern : 45736 if $4 srand _seed={_round(u(100000))} else _seed=$3 fi 45737 srand $_seed 45738 random_pattern $1,$1,$2 45739 adjust_colors. ${5-9} 45740 mv. 0 45741 45742fx_random_pattern : 45743 if $_output_mode rm fi 45744 _fx_random_pattern $* 45745 45746fx_random_pattern_preview : 45747 _fx_random_pattern {max($_preview_width,$_preview_height)},${2--1} 45748 k[0] rr2d $_preview_width,$_preview_height,2,2 45749 to "Seed: \#"$_seed,5,5,5%,2 45750 u "{$1}{$2}{"{$4?$_seed:$3}"}{0}{$5}{$6}{$7}{$8}{$9}" 45751 45752#@gui Resynthetize Texture [FFT] : syntexturize, fx_syntexturize_preview(1) 45753#@gui : Width = _int(1024,32,8192) 45754#@gui : Height = _int(1024,32,8192) 45755#@gui : Equalize Light = float(0,0,100) 45756#@gui : sep = separator() 45757#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45758#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45759#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45760#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45761#@gui : sep = separator() 45762#@gui : note = note{"<small><b>Note:</b> This filter tries to re-synthetize a <b>micro</b>-texture 45763#@gui : (given as the input image) onto an output (seamless) image with an arbitrary size. 45764#@gui : It uses a phase randomization technique, as described in:</small>"} 45765#@gui : url = link("Micro-Texture Synthesis by Phase Randomization","http://www.ipol.im/pub/art/2011/ggm_rpn/") 45766#@gui : note = note("<small>This filter is based on the work of <i>Bruno Galerne</i>, <i>Yann Gousseau</i> and 45767#@gui : <i>Jean-Michel Morel</i>.</small>") 45768#@gui : sep = separator() 45769#@gui : url = link("Click here for a detailed description of this filter.",\ 45770# "http://gimpchat.com/viewtopic.php?f=28&t=10141") 45771#@gui : sep = separator() 45772#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Jérome Boulanger</i>. 45773#@gui : Latest Update: <i>2014/09/04</i>.</small>") 45774fx_syntexturize : 45775 repeat $! l[$>] 45776 if $3 +b {20.5-$3/50}% -[0] [1] fc. ${average_colors.} + c 0,255 fi 45777 syntexturize $1,$2 45778 endl done 45779 45780fx_syntexturize_preview : 45781 gui_split_preview "fx_syntexturize 100%,100%,$3",${-3--1} 45782 45783#@gui Resynthetize Texture [Patch-Based] : syntexturize_matchpatch, fx_syntexturize_matchpatch_preview(1) 45784#@gui : Width = _int(512,32,8192) 45785#@gui : Height = _int(512,32,8192) 45786#@gui : Number of Scales = int(0,0,16) 45787#@gui : Patch Size = int(7,1,32) 45788#@gui : Blending Size = int(5,1,24) 45789#@gui : Precision = float(1,0,5) 45790#@gui : Equalize Light = float(0,0,100) 45791#@gui : sep = separator() 45792#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45793#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45794#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45795#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45796#@gui : sep = separator() 45797#@gui : note = note{"<small><b>Note:</b> This filter tries to re-synthetize an input texture image onto a 45798#@gui : bigger output image (with an arbitrary size). 45799#@gui : Beware, this filter is quite slow to compute!</small>"} 45800#@gui : sep = separator() 45801#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/22/10</i>.</small>") 45802_fx_syntexturize_matchpatch_preview : 45803 repeat $! l[$>] 45804 if $7 +b {20.5-$7/50}% -[0] [1] fc. ${average_colors.} + c 0,255 fi 45805 w={w} h={h} 45806 syntexturize_matchpatch 100%,100%,${3--1} 45807 to_rgba r $w,$h,1,4,0,0,0.5,0.5 45808 endl done 45809 45810fx_syntexturize_matchpatch_preview : 45811 gui_split_preview "_fx_syntexturize_matchpatch_preview ${1--2}",${-3--1} 45812 45813#@gui Rorschach : fx_rorschach, fx_rorschach 45814#@gui : Scale = float(3,0,10) 45815#@gui : Mirror = choice(1,"None","X-Axis","Y-Axis","XY-Axes") 45816#@gui : Stencil Type = choice(2,"Black & White","RGB","Color") 45817#@gui : sep = separator() 45818#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/12/03</i>.</small>") 45819fx_rorschach : 45820 repeat $! remove_opacity l[$>] 45821 if $3==0 norm rorschach $1%,$2 * 255 45822 elif $3==1 to_rgb rorschach $1%,$2 * 255 45823 else +norm rorschach. $1%,$2 blend shapeaverage0 45824 fi 45825 endl done 45826 45827#@gui Satin : fx_satin, fx_satin(1) 45828#@gui : Iterations = int(20,4,128) 45829#@gui : Smoothness (%) = float(1,0,5) 45830#@gui : Seed = int(0,0,65535) 45831#@gui : sep = separator() 45832#@gui : Dark Color = color(0,0,0,255) 45833#@gui : Light Color = color(255,255,255,255) 45834#@gui : Stretch Contrast = bool(0) 45835#@gui : sep = separator() 45836#@gui : Brightness (%) = float(0,-100,100) 45837#@gui : Contrast (%) = float(0,-100,100) 45838#@gui : Gamma (%) = float(-50,-100,100) 45839#@gui : Hue (%) = float(0,-100,100) 45840#@gui : Saturation (%) = float(0,-100,100) 45841#@gui : sep = separator() 45842#@gui : note = note{"This filter has been inspired by 45843#@gui : <a href="https://fence-post.deviantart.com/art/Satin-Texture-in-GIMP-46937633">this tutorial</a> 45844#@gui : from DeviantArt user <i>fence-post</i>."} 45845#@gui : sep = separator() 45846#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/11/27</i>.</small>") 45847fx_satin : 45848 ($4,$8^$5,$9^$6,$10^$7,$11) srgb2rgb. r. 256,1,1,4,3 rgb2srgb. 45849 repeat $!-1 l[$>] 45850 srand $3 channels 0 f 0 45851 repeat $1 45852 100%,100%,1,1,"begin( 45853 A = u([0,0],[w,h]-1); 45854 B = u([0,0],[w,h]-1); 45855 N = [0,-1,1,0]*(B - A); 45856 D = A + N; 45857 C = B + N; 45858 abc = solve([A,1,B,1,C,1,D,1],[0,255,255,0]); 45859 ); 45860 dot(abc,[x,y,1])" 45861 c. 0,255 -- abs 45862 done 45863 b $2% gradient_norm negate n 0,255 45864 if $12 normalize_local , fi 45865 pass. 1 map.. . rm. 45866 sh. 0,2 adjust_colors. ${13-17} rm. 45867 endl done 45868 rm. 45869 45870#@gui Seamless Turbulence : fx_seamless_turbulence, fx_seamless_turbulence(0) 45871#@gui : Amplitude = float(15,0,30) 45872#@gui : Smoothness = float(20,0,40) 45873#@gui : Orientation = float(0,0,180) 45874#@gui : Deviation = float(1,0,1) 45875#@gui : Contrast = float(3,0,4) 45876#@gui : Color Rendering = bool(0) 45877#@gui : sep = separator() 45878#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/02/04</i>.</small>") 45879fx_seamless_turbulence : 45880 repeat $! l[$>] 45881 wh={w},{h} rm 45882 $wh,1,{if($6,3,1)} rand. 0,255 45883 $wh rand. {$3*pi/180-$4*10*pi},{$3*pi/180+$4*10*pi} +sin. cos.. a[-2,-1] c 45884 r[-2,-1] 130%,130%,1,100%,0,2,0.5,0.5 b. $2 orientation. 45885 vector2tensor. 45886 smooth.. .,$1,0.5,20 rm. 45887 r. $wh,1,100%,0,0,0.5,0.5 45888 if $5!=1 ia={ia} - $ia * $5 + $ia fi 45889 endl done 45890 c 0,255 n 0,255 45891 45892#@gui Shock Waves : fx_shockwaves, fx_shockwaves_preview 45893#@gui : Amplitude = float(10,0,100) 45894#@gui : Low Frequency = float(10,0,100) 45895#@gui : Frequency Range = float(20,0,100) 45896#@gui : sep = separator() 45897#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45898#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45899#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45900#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45901#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45902#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45903#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45904#@gui : sep = separator() 45905#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45906#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45907#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45908#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45909#@gui : sep = separator() 45910#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/01/12</i>.</small>") 45911_fx_shockwaves : 45912 dct 45913 100%,100%,1,1,1 circle. 0,0,{$2+$3}%,1,{$1+1} circle. 0,0,$2%,1,1 45914 * idct c 0,255 45915 45916fx_shockwaves : 45917 ac "_fx_shockwaves ${1-3}",$4 45918 45919fx_shockwaves_preview : 45920 gui_split_preview "fx_shockwaves $*",${-3--1} 45921 45922#@gui Sponge : fx_sponge, fx_sponge_preview(0) 45923#@gui : Size = int(13,3,21) 45924#@gui : sep = separator() 45925#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 45926#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 45927#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 45928#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 45929#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 45930#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 45931#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 45932#@gui : sep = separator() 45933#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45934#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45935#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45936#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45937#@gui : sep = separator() 45938#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 45939fx_sponge : 45940 ac "sponge $1",$2 45941 45942fx_sponge_preview : 45943 gui_split_preview "fx_sponge $*",${-3--1} 45944 45945#@gui Stained Glass : fx_stained_glass, fx_stained_glass_preview(0) 45946#@gui : Edges = float(20,0,100) 45947#@gui : Shading = float(0.1,0,0.5) 45948#@gui : Thin Separators = bool(1) 45949#@gui : sep = separator() 45950#@gui : Equalize = bool(1) 45951#@gui : Colors = float(1,0,3) 45952#@gui : Brightness (%) = float(0,-100,100) 45953#@gui : Contrast (%) = float(0,-100,100) 45954#@gui : Gamma (%) = float(0,-100,100) 45955#@gui : sep = separator() 45956#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45957#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45958#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 45959#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 45960#@gui : sep = separator() 45961#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/03</i>.</small>") 45962fx_stained_glass : 45963 repeat $! l[$>] split_opacity l[0] to_rgb 45964 stained_glass $1,$2,$3 45965 n 0,255 45966 if $4 equalize. fi 45967 rgb2lab. sh. 1,2 *. $5 rm. lab2rgb. 45968 adjust_colors. ${6-8} 45969 endl a c endl done 45970 45971fx_stained_glass_preview : 45972 gui_split_preview "fx_stained_glass $*",${-3--1} 45973 45974#@gui Stars : fx_stars, fx_stars(0) 45975#@gui : Density = float(10,0,200) 45976#@gui : Depth = float(0,0,5) 45977#@gui : Size = int(32,8,128) 45978#@gui : Branches = int(5,3,16) 45979#@gui : Thickness = float(0.38,0.1,1) 45980#@gui : Smoothness = float(0,0,10) 45981#@gui : Color = color(255,255,100,200) 45982#@gui : sep = separator() 45983#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/01/10</i>.</small>") 45984fx_stars : 45985 repeat $! l[$>] split_opacity rv 45986 stars $1%,$2,$3,$4,$5,$6%,${7-9},{$10/255} 45987 rv a c endl done 45988 45989#@gui Stencil : fx_stencil, fx_stencil_preview(0) 45990#@gui : Radius = float(3,0,10) 45991#@gui : Smoothness = float(0,0,30) 45992#@gui : Iterations = int(8,1,100) 45993#@gui : Aliasing = float(0,0,5) 45994#@gui : Stencil Type = choice(2,"Black & White","RGB","Color") 45995#@gui : Transparency = bool(0) 45996#@gui : sep = separator() 45997#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 45998#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 45999#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46000#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46001#@gui : sep = separator() 46002#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46003fx_stencil : 46004 if $5==0 norm stencil $1,$2,$3 46005 elif $5==1 stencil $1,$2,$3 46006 else repeat $! 46007 +norm. stencil. $1,$2,$3 >=. 50% blend[-2,-1] shapeaverage0 46008 mv. 0 done fi 46009 if $6 to_rgba replace_color 0,0,0,0,0,255,0,0,0,0 fi 46010 if $4 smooth {30*$4},0,1,1 fi 46011 46012fx_stencil_preview : 46013 gui_split_preview "fx_stencil $*",${-3--1} 46014 46015#@gui Tetris : fx_tetris, fx_tetris(0) 46016#@gui : Scale = int(10,1,20) 46017#@gui : sep = separator() 46018#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46019fx_tetris : 46020 tetris $1 46021 46022#@gui Truchet : fx_truchet, fx_truchet(0) 46023#@gui : Scale = int(32,1,256) 46024#@gui : Radius = int(5,1,64) 46025#@gui : Smoothness = float(1,0,10) 46026#@gui : Type = choice(1,"Straight","Curved") 46027#@gui : Color = choice("White on Black","Black on White","White on Transparent","Black on Transparent", 46028#@gui : "Transparent on White","Transparent on Black","Random") 46029#@gui : sep = separator() 46030#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/26/10</i>.</small>") 46031fx_truchet : 46032 repeat $! l[$>] 46033 100%,100% truchet $1,$2,$4 rm.. 46034 if $5==1 * -1 46035 elif $5==2 i[0] 100%,100%,1,1,1 46036 elif $5==3 i[0] 100%,100% 46037 elif $5==4 * -1 i[0] 100%,100% 46038 elif $5==5 * -1 i[0] 100%,100%,1,1,-1 46039 elif $5==6 label 0,1 {iM+1},1,1,3 rand. 0,255 map.. . rm. 46040 fi 46041 a c b $3 n 0,255 46042 endl done 46043 46044#@gui Voronoi : fx_voronoi, fx_voronoi_preview(0) 46045#@gui : Threshold = float(160,0,255) 46046#@gui : Threshold on = choice(1,"Pixel values","Gradient values") 46047#@gui : Smoothness = float(0.5,0,10) 46048#@gui : Subsampling (%) = float(50,0,100) 46049#@gui : sep = separator() 46050#@gui : Flat color = choice(3,"Black","White","Transparent","Image") 46051#@gui : Outline thickness = int(1,0,8) 46052#@gui : Outline color = color(0,0,0,100) 46053#@gui : Centers radius = int(2,0,10) 46054#@gui : Centers color = color(255,255,255,40) 46055#@gui : sep = separator() 46056#@gui : Anti-aliasing = choice{1,"x1 (none)","x1.5","x2","x2.5"} 46057#@gui : sep = separator() 46058#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/04/30</i>.</small>") 46059fx_voronoi : 46060 repeat $! l[$>] wh={[w,h]} 46061 f={arg(1+$16,1,1.5,2,2.5)*100} r $f%,$f%,1,100%,3 46062 46063 if $2 +gradient_norm t={(255-$1)/4} else +s c med[^0] t={255-$1} fi 46064 if $3 mM={[im,iM]} b. $3 n. $mM fi 46065 >. $t 46066 f. "u<($4%)^4?i:0" 46067 label_fg. 0,1 voronoi. 46068 46069 # Flat. 46070 if $5<3 46071 1,1,1,4,"$5==0?[0,0,0,255]:$5==1?[255,255,255,255]:$5==2?[128,128,128,0]" 46072 r. [0],[0],1,4 rv[0,-1] rm. 46073 else 46074 blend[0] .,shapeaverage 46075 fi 46076 46077 # Outline. 46078 if $6" && "$10 46079 +f. "const boundary=1; i!=j(1) || i!=j(0,1)" 46080 dilate. $6 46081 1,1,1,4,"[${7-9},255]" r. [0],[0],1,4 46082 j[0] .,0,0,0,0,{$10/255},.. rm[-2,-1] 46083 fi 46084 46085 # Centers. 46086 if $11" && "$15 46087 1,{iM+1},1,3 eval.. "I[#-1,i]+=[x,y,1]" s. c,-2 /[-2,-1] rm.. 46088 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])" 46089 fi 46090 rm. 46091 r $wh,1,100%,2 46092 46093 endl done 46094 46095fx_voronoi_preview : 46096 fx_voronoi ${1-15},{min(1,$16)} 46097 46098#@gui Weave : weave, weave(1) 46099#@gui : Density = int(6,1,32) 46100#@gui : Thickness = float(65,0,100) 46101#@gui : Shadow = float(0,0,100) 46102#@gui : Shading = float(0.5,0,3) 46103#@gui : Fibers Amplitude = float(0,0,255) 46104#@gui : Fibers Smoothness = float(0,0,10) 46105#@gui : Angle = choice("0 deg.","22.5 deg.","45 deg.","67.5 deg.") 46106#@gui : X-Curvature = float(0,-1,1) 46107#@gui : Y-Curvature = float(0,-1,1) 46108#@gui : sep = separator() 46109#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/18/01</i>.</small>") 46110 46111#@gui Whirls : fx_whirls, fx_whirls_preview(0) 46112#@gui : Density = int(7,3,20) 46113#@gui : Smoothness = float(2,0,10) 46114#@gui : Darkness = float(0.2,0,1) 46115#@gui : Lightness = float(1.8,1,3) 46116#@gui : sep = separator() 46117#@gui : Channel(s) = choice(11,"All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46118#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46119#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46120#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46121#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46122#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46123#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46124#@gui : sep = separator() 46125#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46126#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46127#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46128#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46129#@gui : sep = separator() 46130#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46131fx_whirls : 46132 ac "whirls $1,$2,$3,$4",$5 46133 46134fx_whirls_preview : 46135 gui_split_preview "fx_whirls ${1-5}",${-3--1} 46136 46137 46138#@gui ____<b>Repair</b> 46139#----------------------- 46140 46141#@gui Bayer Reconstruction : bayer2rgb, gui_no_preview 46142#@gui : G/M Smoothness = _float(6,0,20) 46143#@gui : R/B Smoothness (Principal) = _float(6,0,20) 46144#@gui : R/B Smoothness (Secondary) = _float(4,0,20) 46145#@gui : sep = separator() 46146#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46147 46148#@gui Deinterlace : deinterlace, fx_deinterlace_preview(0) 46149#@gui : Algorithm = choice("Standard","Motion-Compensated") 46150#@gui : sep = separator() 46151#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46152#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46153#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46154#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46155#@gui : sep = separator() 46156#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46157fx_deinterlace : 46158 deinterlace 0 skip ${^0} 46159 46160fx_deinterlace_preview : 46161 gui_split_preview "fx_deinterlace $*",${-3--1} 46162 46163#@gui Inpaint [Holes] : fx_inpaint_holes, fx_inpaint_holes(0) 46164#@gui : Maximal Area = float(4,1,512) 46165#@gui : Tolerance = float(20,0,255) 46166#@gui : Connectivity = choice(1,"Low","High") 46167#@gui : sep = separator() 46168#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/27/05</i>.</small>") 46169fx_inpaint_holes : 46170 inpaint_holes {$1^1.5},$2,$3 46171 46172#@gui Inpaint [Morphological] : fx_inpaint_morpho, fx_inpaint_morpho_preview(1) 46173#@gui : Mask Color = _color(255,0,0,255) 46174#@gui : Mask Dilation = _int(0,0,32) 46175#@gui : sep = separator() 46176#@gui : note = note{"<small><b>Note:</b> It is strongly suggested to apply this filter only on a selection 46177#@gui : around the region to inpaint, to save computation time!</small>"} 46178#@gui : sep = separator() 46179#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/25/11</i>.</small>") 46180fx_inpaint_morpho : 46181 repeat $! l[$>] 46182 R=$1 G=$2 B=$3 A=$4 46183 if !$A" && "(s==2" || "s==4) split_opacity +!=. 0 *[0,-1] a c R=0 G=0 B=0 fi # Purely transparent color. 46184 +round select_color. 0,{round([$R,$G,$B,$A])} 46185 if $5 dilate. {1+2*$5} fi 46186 inpaint_morpho.. [1] 46187 rm. 46188 endl done 46189 46190fx_inpaint_morpho_preview : 46191 fx_inpaint_morpho ${1-4},{1+$5} 46192 46193#@gui Inpaint [Multi-Scale] : fx_inpaint_matchpatch, fx_inpaint_matchpatch_preview(1) 46194#@gui : Number of Scales = int(0,0,16) 46195#@gui : note = note{"<small>(Set <i>Number of scales</i> to <i>0</i> for automatic scale detection)</small>"} 46196#@gui : Patch Size = int(9,1,64) 46197#@gui : Number of Iterations per Scale = int(10,1,100) 46198#@gui : Blend Size = int(5,0,32) 46199#@gui : Allow Outer Blending = bool(1) 46200#@gui : Mask Color = color(255,0,0,255) 46201#@gui : Mask Dilation = int(0,0,32) 46202#@gui : sep = separator() 46203#@gui : Preview Progression While Running = _bool(0) 46204#@gui : sep = separator() 46205#@gui : note = note{"<small><b>Note:</b> Preview and final result may strongly differ.</small>"} 46206#@gui : sep = separator() 46207#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/25/11</i>.</small>") 46208fx_inpaint_matchpatch : 46209 repeat $! l[$>] nm={n} 46210 R=$6 G=$7 B=$8 A=$9 46211 if !$A" && "(s==2" || "s==4) split_opacity +!=. 0 *[0,-1] a c R=0 G=0 B=0 fi # Purely transparent color. 46212 +round select_color. 0,{round([$R,$G,$B,$A])} 46213 if $10 dilate. {1+2*$10} fi 46214 if $11 46215 visu_size=${fitscreen[]" "{0,[w,h,1]},25%,50%} 46216 w1.. $visu_size,0,"[Preview] G'MIC: Inpaint [multi-scale]" 46217 fi 46218 srand 0 inpaint_matchpatch.. [1],${1-5} 46219 rm. nm $nm 46220 endl done 46221 46222fx_inpaint_matchpatch_preview : 46223 fx_inpaint_matchpatch ${1-9},{1+$10},0 46224 46225#@gui Inpaint [Patch-Based] : fx_inpaint_patch, fx_inpaint_patch_preview 46226#@gui : Patch Size = _int(7,1,64) 46227#@gui : Lookup Size = _float(16,1,32) 46228#@gui : Lookup Factor = _float(0.1,0,1) 46229#@gui : Blend Size = _float(1.2,0,5) 46230#@gui : Blend Threshold = _float(0,0,1) 46231#@gui : Blend Decay = _float(0.05,0,0.5) 46232#@gui : Blend Scales = _int(10,1,20) 46233#@gui : Allow Outer Blending = _bool(1) 46234#@gui : Mask Color = _color(255,0,0,255) 46235#@gui : Mask Dilation = _int(0,0,32) 46236#@gui : Process by Blocs of Size = _choice("100%","75%","50%","25%","10%","5%","2%","1%") 46237#@gui : sep = separator() 46238#@gui : note = note("<small>A quick tutorial on how to use this filter can be found here:</small>") 46239#@gui : url = link("G'MIC Inpainting tutorial on Patrick David's blog.", 46240#@gui : "https://patdavid.net/2014/02/getting-around-in-gimp-gmic-inpainting.html") 46241#@gui : sep = separator() 46242#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Maxime Daisy</i>. 46243#@gui : Latest Update: <i>2015/25/11</i>.</small>") 46244_fx_inpaint_patch : 46245 repeat $! l[$>] 46246 R=$9 G=$10 B=$11 A=$12 46247 if !$A" && "(s==2" || "s==4) split_opacity +!=. 0 *[0,-1] a c R=0 G=0 B=0 fi # Purely transparent color. 46248 +round select_color. 0,{round([$R,$G,$B,$A])} 46249 if $13 dilate. {1+2*$13} fi 46250 inpaint.. [1],$1,{$1*$2},$3,1,{$4*$1},${5-8} 46251 rm. 46252 endl done 46253 46254fx_inpaint_patch : 46255 repeat $! l[$>] 46256 if $14 46257 bs={max(16,min(w,h)*arg(1+$14,100,75,50,25,10,5,2,1)%)} 46258 at "_fx_inpaint_patch $*",$bs,$bs,1,25%,25%,0,2 46259 else _fx_inpaint_patch $* 46260 fi 46261 endl done 46262 46263fx_inpaint_patch_preview : 46264 fx_inpaint_patch ${1-12},{1+$13},100 46265 46266#@gui Inpaint [Transport-Diffusion] : fx_inpaint_pde, fx_inpaint_pde_preview(1) 46267#@gui : Smoothness (%) = float(75,0,100) 46268#@gui : Regularization = choice(1,"Isotropic","Delaunay-Oriented","Edge-Oriented") 46269#@gui : Regularization Iterations = int(20,0,100) 46270#@gui : Mask Color = _color(255,0,0,255) 46271#@gui : Mask Dilation = _int(0,0,32) 46272#@gui : sep = separator() 46273#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/10/04</i>.</small>") 46274fx_inpaint_pde : 46275 repeat $! l[$>] 46276 R=$4 G=$5 B=$6 A=$7 46277 if !$A" && "(s==2" || "s==4) split_opacity +!=. 0 *[0,-1] a c R=0 G=0 B=0 fi # Purely transparent color. 46278 +select_color 0,$R,$G,$B,$A 46279 if $8 dilate. {1+2*$8} fi 46280 inpaint_pde.. [1],$1%,$2,$3 46281 rm. 46282 endl done c 0,255 46283 46284fx_inpaint_pde_preview : 46285 fx_inpaint_pde ${1-7},{1+$8} 46286 46287#@gui Red-Eye Attenuation : red_eye, red_eye 46288#@gui : Threshold = float(75,0,100) 46289#@gui : Smoothness = float(3.5,0,20) 46290#@gui : Factor = float(0.1,0,1) 46291#@gui : sep = separator() 46292#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46293 46294#@gui Remove Hot Pixels : fx_remove_hotpixels, fx_remove_hotpixels_preview(0) 46295#@gui : Mask Size = int(3,3,20) 46296#@gui : Threshold = float(10,0,200) 46297#@gui : sep = separator() 46298#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46299#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46300#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46301#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46302#@gui : sep = separator() 46303#@gui : note = note("<small>Author: <i>Jérome Boulanger</i>. Latest Update: <i>2010/29/12</i>.</small>") 46304fx_remove_hotpixels : 46305 remove_hotpixels $1,$2 46306 46307fx_remove_hotpixels_preview : 46308 gui_split_preview "fx_remove_hotpixels $*",${-3--1} 46309 46310#@gui Solidify : fx_solidify_td, fx_solidify_td_preview(1) 46311#@gui : Smoothness (%) = float(75,0,100) 46312#@gui : Regularization = choice(1,"Isotropic","Delaunay-Oriented","Edge-Oriented") 46313#@gui : Regularization Iterations = int(20,0,100) 46314#@gui : Dilation / Erosion = int(0,-20,20) 46315#@gui : Colorspace = choice(1,"sRGB","Linear RGB") 46316#@gui : sep = separator() 46317#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46318#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46319#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46320#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46321#@gui : sep = separator() 46322#@gui : note = note{"<small><b>Note:</b> 46323#@gui : This filter reconstructs transparent regions of an image using a transport-diffusion algorithm. 46324#@gui : Useful only for images having an alpha-channel. 46325#@gui : </small>"} 46326#@gui : sep = separator() 46327#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/07/04</i>.</small>") 46328fx_solidify_td : 46329 repeat $! l[$>] 46330 to_rgba sh 0,{s-2} if $5 srgb2rgb. fi rm. 46331 if $4 46332 . sh. 100% if $4>0 erode. {1+2*$4} else dilate. {1-2*$4} fi rm. 46333 solidify. $1%,$2,$3 46334 rv blend alpha 46335 else 46336 solidify $1%,$2,$3 46337 fi 46338 if $5 rgb2srgb. fi 46339 endl done 46340 46341fx_solidify_td_preview : 46342 gui_split_preview "fx_solidify_td $*",${-3--1} 46343 46344#@gui Smooth [Anisotropic] : fx_smooth_anisotropic, fx_smooth_anisotropic_preview(0) 46345#@gui : Amplitude = float(60,0,1000) 46346#@gui : Sharpness = float(0.7,0,2) 46347#@gui : Anisotropy = float(0.3,0,1) 46348#@gui : Gradient Smoothness = float(0.6,0,10) 46349#@gui : Tensor Smoothness = float(1.1,0,10) 46350#@gui : Spatial Precision = float(0.8,0.1,2) 46351#@gui : Angular Precision = float(30,1,180) 46352#@gui : Value Precision = float(2,0.1,5) 46353#@gui : Interpolation = choice(0,"Nearest Neighbor","Linear","Runge-Kutta") 46354#@gui : Fast Approximation = bool(1) 46355#@gui : Iterations = int(1,1,10) 46356#@gui : sep = separator() 46357#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46358#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46359#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46360#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46361#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46362#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46363#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46364#@gui : sep = separator() 46365#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46366#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46367#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46368#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46369#@gui : sep = separator() 46370#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/08/27</i>.</small>") 46371fx_smooth_anisotropic : 46372 repeat $! l[$>] 46373 ac "repeat $11 smooth $1,$2,$3,$4,$5,$6,$7,$8,$9,$10 done",$12 46374 endl done c 0,255 46375 46376fx_smooth_anisotropic_preview : 46377 gui_split_preview "fx_smooth_anisotropic $*",${-3--1} 46378 46379#@gui Smooth [Antialias] : fx_smooth_antialias, fx_smooth_antialias_preview(0) 46380#@gui : Amplitude = float(5,0,100) 46381#@gui : Edge Threshold (%) = float(10,0,100) 46382#@gui : Smoothness = float(0.8,0,5) 46383#@gui : sep = separator() 46384#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46385#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46386#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46387#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46388#@gui : sep = separator() 46389#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/11/13</i>.</small>") 46390fx_smooth_antialias : 46391 repeat $! l[$>] 46392 +diffusiontensors 0,1,1,$3,$3 46393 +gradient_norm.. >=. $2% *[-2,-1] 46394 smooth.. .,{$1^1/3},0.5,120,2,1 rm. 46395 endl done 46396 46397fx_smooth_antialias_preview : 46398 gui_split_preview "fx_smooth_antialias $*",${-3--1} 46399 46400#@gui Smooth [Bilateral] : fx_smooth_bilateral, fx_smooth_bilateral_preview(0) 46401#@gui : Spatial Variance = float(10,0,100) 46402#@gui : Value Variance = float(7,0,100) 46403#@gui : Iterations = int(2,1,10) 46404#@gui : sep = separator() 46405#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46406#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46407#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46408#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46409#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46410#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46411#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46412#@gui : sep = separator() 46413#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46414#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46415#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46416#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46417#@gui : sep = separator() 46418#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 46419fx_smooth_bilateral : skip ${5=0},${6=0} 46420 ac "repeat $3 bilateral $1,$2 done",$4 46421 46422fx_smooth_bilateral_preview : 46423 gui_split_preview "fx_smooth_bilateral $*",${-3--1} 46424 46425#@gui Smooth [Guided] : fx_smooth_guided, fx_smooth_guided_preview(0) 46426#@gui : Guide As = choice("Self","Top Layer","Bottom Layer") 46427#@gui : Radius = int(5,1,100) 46428#@gui : Smoothness = float(30,0,512) 46429#@gui : Iterations = int(1,1,10) 46430#@gui : sep = separator() 46431#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46432#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46433#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46434#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46435#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46436#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46437#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46438#@gui : sep = separator() 46439#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46440#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46441#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46442#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46443#@gui : sep = separator() 46444#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/10/02</i>.</small>") 46445fx_smooth_guided : skip ${6=0},${7=0} 46446 if $1" && "!narg($_guide) 46447 if $!<2 gui_warning_preview "Missing guide layer" return fi 46448 store[{$1==1?0:-1}] _guide 46449 fi 46450 if $1==0 # Self-guide 46451 ac "repeat $4 guided $2,$3 done",$5 46452 elif $1==1 # Guide as top layer 46453 ac "$_guide r. ..,..,1,100%,0,0,0.5,0.5 repeat $4 guided[0] [1],$2,$3 done rm.",$5 46454 if !narg($_is_preview) $_guide mv. 0 fi 46455 else # Guide as bottom layer 46456 ac "$_guide r. ..,..,1,100%,0,0,0.5,0.5 repeat $4 guided[0] [1],$2,$3 done rm.",$5 46457 if !narg($_is_preview) $_guide fi 46458 fi 46459 46460fx_smooth_guided_preview : 46461 if $1" && "!narg($_guide) 46462 if $!<2 gui_warning_preview "Missing guide layer" return fi 46463 store[{$1==1?0:-1}] _guide 46464 fi 46465 _is_preview=1 46466 gui_split_preview "fx_smooth_guided $*",${-3--1} 46467 46468#@gui Smooth [Diffusion] : fx_smooth_diffusion, fx_smooth_diffusion_preview(0) 46469#@gui : Sharpness = float(0.7,0,2) 46470#@gui : Anisotropy = float(0.3,0,1) 46471#@gui : Gradient Smoothness = float(0.6,0,10) 46472#@gui : Tensor Smoothness = float(1.1,0,10) 46473#@gui : Time Step = float(15,5,50) 46474#@gui : Iterations = int(8,1,100) 46475#@gui : sep = separator() 46476#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46477#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46478#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46479#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46480#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46481#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46482#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46483#@gui : sep = separator() 46484#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 46485#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 46486#@gui : sep = separator() 46487#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46488#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46489#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46490#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46491#@gui : sep = separator() 46492#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 46493fx_smooth_diffusion : 46494 ac "gui_parallel_overlap \"smooth $6,$1,$2,$3,$4,$5,0 c 0,255\",$8,$9",$7 46495 46496fx_smooth_diffusion_preview : 46497 gui_split_preview "fx_smooth_diffusion $*",${-3--1} 46498 46499#@gui Smooth [Mean-Curvature] : fx_smooth_meancurvature, fx_smooth_meancurvature_preview(0) 46500#@gui : Time Step = float(30,5,50) 46501#@gui : Iterations = int(4,1,30) 46502#@gui : Keep Iterations as Different Layers = bool(false) 46503#@gui : sep = separator() 46504#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46505#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46506#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46507#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46508#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46509#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46510#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46511#@gui : sep = separator() 46512#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 46513#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 46514#@gui : sep = separator() 46515#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46516#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46517#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46518#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46519#@gui : sep = separator() 46520#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 46521fx_smooth_meancurvature : 46522 ac "gui_parallel_overlap \"meancurvature_flow $2,$1,$3 c 0,255\",$5,$6",$4 46523 46524fx_smooth_meancurvature_preview : 46525 gui_split_preview "fx_smooth_meancurvature $*",${-3--1} 46526 46527#@gui Smooth [Median] : fx_smooth_median, fx_smooth_median_preview(0) 46528#@gui : Radius = int(3,1,20) 46529#@gui : Threshold = float(255,0,255) 46530#@gui : sep = separator() 46531#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46532#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46533#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46534#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46535#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46536#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46537#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46538#@gui : sep = separator() 46539#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46540#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46541#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46542#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46543#@gui : sep = separator() 46544#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46545fx_smooth_median : 46546 ac "median $1,$2",$3 46547 46548fx_smooth_median_preview : 46549 gui_split_preview "fx_smooth_median $*",${-3--1} 46550 46551#@gui Smooth [NL-Means] : fx_smooth_nlmeans, fx_smooth_nlmeans_preview(0) 46552#@gui : Patch Size = float(4,0.5,10) 46553#@gui : Spatial Bandwidth = int(4,3,13) 46554#@gui : Tonal Bandwidth = float(10,1,50) 46555#@gui : Patch Measure = choice(3,"Linf-Norm","L1-Norm","L2-Norm","Luminance","Lightness","RGB") 46556#@gui : sep = separator() 46557#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46558#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46559#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46560#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46561#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46562#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46563#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46564#@gui : sep = separator() 46565#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 46566#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 46567#@gui : sep = separator() 46568#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46569#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46570#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46571#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46572#@gui : sep = separator() 46573#@gui : note = note("<small>Author: <i>Jérôme Boulanger</i>. Latest Update: <i>2015/01/07</i>.</small>") 46574fx_smooth_nlmeans: 46575 repeat $! l[$>] 46576 if s==1 nlmeans $1,$2,$3,-_fx_smooth_nlmeans$4 # Handle separately gray scale images. 46577 else ac "gui_parallel_overlap \"nlmeans $1,$2,$3,-_fx_smooth_nlmeans$4\",$6,$7",$5 46578 fi 46579 endl done 46580 46581_fx_smooth_nlmeans0 : s c abs max 46582_fx_smooth_nlmeans1 : s c abs + 46583_fx_smooth_nlmeans2 : norm 46584_fx_smooth_nlmeans3 : if s>=3 channels 0,2 luminance else norm fi 46585_fx_smooth_nlmeans4 : if s>=3 channels 0,2 srgb2rgb rgb2lab channels 0 else norm fi 46586_fx_smooth_nlmeans5 : 46587 46588fx_smooth_nlmeans_preview: 46589 gui_split_preview "fx_smooth_nlmeans $*",${-3--1} 46590 46591#@gui Smooth [Patch-Based] : fx_smooth_patch, fx_smooth_patch_preview(0) 46592#@gui : Spatial Variance = float(10,0.1,200) 46593#@gui : Patch Variance = float(10,0.1,200) 46594#@gui : Patch Size = int(3,2,21) 46595#@gui : Lookup Size = int(5,2,21) 46596#@gui : Patch Smoothness = float(0,0,4) 46597#@gui : Fast Approximation = bool(1) 46598#@gui : Iterations = int(1,1,10) 46599#@gui : sep = separator() 46600#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46601#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46602#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46603#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46604#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46605#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46606#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46607#@gui : sep = separator() 46608#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 46609#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 46610#@gui : sep = separator() 46611#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46612#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46613#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46614#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46615#@gui : sep = separator() 46616#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 46617fx_smooth_patch : 46618 ac "gui_parallel_overlap \"repeat $7 denoise $1,$2,$3,$4,$5,$6 done c 0,255\",$9,$10",$8 46619 46620fx_smooth_patch_preview : 46621 gui_split_preview "fx_smooth_patch $*",${-3--1} 46622 46623#@gui Smooth [Patch-PCA] : fx_smooth_patchpca, fx_smooth_patchpca_preview(0) 46624#@gui : Strength = float(4,0,16) 46625#@gui : Patch Size = int(7,2,21) 46626#@gui : Lookup Size = int(11,2,21) 46627#@gui : Spatial Sampling = int(7,1,16) 46628#@gui : sep = separator() 46629#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46630#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46631#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46632#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46633#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46634#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46635#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46636#@gui : sep = separator() 46637#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46638#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46639#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46640#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46641#@gui : sep = separator() 46642#@gui : note = note{"<small><b>Note:</b> Beware, this filter uses a very computationally intensive algorithm to 46643#@gui : denoise images. So, do not complain too much if you have less than 8 cores available for the computation :) 46644#@gui : </small>"} 46645#@gui : sep = separator() 46646#@gui : note = note("<small>Authors: <i>David Tschumperlé</i> and <i>Jérome Boulanger</i>. 46647#@gui : Latest Update: <i>2016/24/03</i>.</small>") 46648fx_smooth_patchpca : 46649 ac "denoise_patchpca ${1-4} c 0,255",$5 46650 46651fx_smooth_patchpca_preview : 46652 gui_split_preview "fx_smooth_patchpca $*",${-3--1} 46653 46654#@gui Smooth [Perona-Malik] : fx_smooth_peronamalik, fx_smooth_peronamalik_preview(0) 46655#@gui : K-Factor = float(20,0,255) 46656#@gui : Time Step = float(5,5,50) 46657#@gui : Iterations = int(5,1,30) 46658#@gui : Keep Iterations as Different Layers = bool(false) 46659#@gui : sep = separator() 46660#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46661#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46662#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46663#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46664#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46665#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46666#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46667#@gui : sep = separator() 46668#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 46669#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 46670#@gui : sep = separator() 46671#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46672#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46673#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46674#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46675#@gui : sep = separator() 46676#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/26/11</i>.</small>") 46677fx_smooth_peronamalik : 46678 ac "gui_parallel_overlap \"peronamalik_flow $1,$3,$2,$4 c 0,255\",$6,$7",$5 46679 46680fx_smooth_peronamalik_preview : 46681 gui_split_preview "fx_smooth_peronamalik $*",${-3--1} 46682 46683#@gui Smooth [Selective Gaussian] : fx_smooth_selective, fx_smooth_selective_preview(0) 46684#@gui : Amplitude = float(5,0,20) 46685#@gui : Edges = float(0.5,0,2) 46686#@gui : Scales = int(5,1,10) 46687#@gui : Iterations = int(1,1,10) 46688#@gui : sep = separator() 46689#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46690#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46691#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46692#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46693#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46694#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46695#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46696#@gui : sep = separator() 46697#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 46698#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 46699#@gui : sep = separator() 46700#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46701#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46702#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46703#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46704#@gui : sep = separator() 46705#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 46706fx_smooth_selective : 46707 ac "gui_parallel_overlap \"repeat $4 blur_selective $1,$2,$3 done c 0,255\",$6,$7",$5 46708 46709fx_smooth_selective_preview : 46710 gui_split_preview "fx_smooth_selective $*",${-3--1} 46711 46712#@gui Smooth [Skin] : fx_smooth_skin, fx_smooth_skin_preview(1) 46713#@gui : note = note("<small><b>Step 1:</b> Skin detection</small>") 46714#@gui : Skin Estimation = choice(2,"None","Manual","Automatic") 46715#@gui : Tolerance = float(0.5,0,1) 46716#@gui : Smoothness = float(1,0,5) 46717#@gui : Threshold = float(1,0,10) 46718#@gui : Pre-Normalize Image = bool(1) 46719#@gui : X-Coordinate [Manual] = float(50,0,100) 46720#@gui : Y-Coordinate [Manual] = float(50,0,100) 46721#@gui : Radius [Manual] = float(5,0,25) 46722#@gui : sep = separator() 46723#@gui : note = note("<small><b>Step 2:</b> Medium scale smoothing</small>") 46724#@gui : Base Scale = float(2,0,10) 46725#@gui : Fine Scale = float(0.2,0,0.8) 46726#@gui : Smoothness = float(3,0,10) 46727#@gui : Smoothness Type = choice(1,"Gaussian","Bilateral") 46728#@gui : sep = separator() 46729#@gui : note = note("<small><b>Step 3:</b> Details enhancement</small>") 46730#@gui : Gain = float(0.05,0,0.5) 46731#@gui : sep = separator() 46732#@gui : Preview Data = choice{5,"Skin Mask","Base Scale","Medium Scale (Original)","Medium Scale (Smoothed)", 46733#@gui : "Fine Scale","Result Image"} 46734#@gui : sep = separator() 46735#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46736#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46737#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46738#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46739#@gui : sep = separator() 46740#@gui : url = link("Click here for a video tutorial","http://www.youtube.com/watch?v=H8pQfq-ybCc") 46741#@gui : sep = separator() 46742#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/20/12</i>.</small>") 46743fx_smooth_skin : 46744 repeat $! l[$>] split_opacity l[0] to_rgb 46745 46746 # Skin detection step. 46747 if $5 +balance_gamma 128,128,128 else [0] fi 46748 if $1==0 channels. 0 f. 1 elif $1==2 detect_skin. $2 else detect_skin. $2,$6%,$7%,$8% fi 46749 M={iM} b. $3% *. {$M/iM} *. $4 c. 0,1 46750 46751 # Details smoothing step. 46752 split_details[0] 4,$9%,$10% 46753 +_fx_smooth_skin[2] $12,$11 46754 j[2] .,0,0,0,0,1,.. rm[-2,-1] 46755 *. {10^$13} + c 0,255 46756 46757 endl a c endl done 46758 46759_fx_smooth_skin : 46760 if $1==0 b {$2/8}% 46761 else 46762 if $2>0 46763 m={im} M={iM} n 0,255 46764 repeat int($2/5) bilateral 3%,{5*3} done 46765 bilateral 3%,{($2%5)*3} 46766 * {($M-$m)/255} + $m 46767 fi 46768 fi 46769 46770fx_smooth_skin_preview : 46771 if $-2==0 46772 gui_split_preview "if $5 balance_gamma 128,128,128 fi if $1==0 f 1 elif $1==2 detect_skin $2 "\ 46773 "else detect_skin $2,$6%,$7%,$8% fi M={iM} b $3% * {255*$M/iM} * $4 c 0,255",${-3--1} 46774 elif $-2==1 46775 gui_split_preview "b $9%",${-3--1} 46776 elif $-2==2 46777 gui_split_preview "split_details 4,$9%,$10% k.. n 0,255",${-3--1} 46778 elif $-2==3 46779 gui_split_preview "split_details 4,$9%,$10% k.. _fx_smooth_skin $12,$11 n 0,255",${-3--1} 46780 elif $-2==4 46781 gui_split_preview "split_details 4,$9%,$10% k. n 0,255",${-3--1} 46782 else 46783 gui_split_preview "fx_smooth_skin $*",${-3--1} 46784 fi 46785 46786 if $1==1 46787 to_rgb 46788 circle $6%,$7%,$8%,0.2,0,255,0 46789 circle $6%,$7%,$8%,0.4,0xFFFFFFFF,0,255,0 46790 line {$6-0.25*$8}%,{$7-0.25*$8}%,{$6+0.25*$8}%,{$7+0.25*$8}%,0.8,255,255,0 46791 line {$6+0.25*$8}%,{$7-0.25*$8}%,{$6-0.25*$8}%,{$7+0.25*$8}%,0.8,255,255,0 46792 fi 46793 46794#@gui Smooth [Thin Brush] : fx_smooth_anisotropic, fx_smooth_anisotropic(0) 46795#@gui : Amplitude = float(60,0,1000) 46796#@gui : Sharpness = float(0.9,0,2) 46797#@gui : Anisotropy = float(0.64,0,1) 46798#@gui : Gradient Smoothness = float(3.1,0,10) 46799#@gui : Tensor Smoothness = float(1.10,0,10) 46800#@gui : Spatial Precision = float(0.8,0.1,2) 46801#@gui : Angular Precision = float(30,1,180) 46802#@gui : Value Precision = float(2,0.1,5) 46803#@gui : Interpolation = choice(0,"Nearest Neighbor","Linear","Runge-Kutta") 46804#@gui : Fast Approximation = bool(1) 46805#@gui : Iterations = int(1,1,10) 46806#@gui : Channel(s) = choice("RGB","Luminance","Blue & Red chrominances","Blue chrominance","Red chrominance") 46807#@gui : sep = separator() 46808#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 46809#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 46810#@gui : note = note{"\n<small><b>Note: </b>This set of anisotropic smoothing parameters has been suggested 46811#@gui : by PhotoComiX.</small>"} 46812#@gui : sep = separator() 46813#@gui : note = note("<small>Author: <i>PhotoComiX</i>. Latest Update: <i>2010/26/12</i>.</small>") 46814 46815#@gui Smooth [Total Variation] : fx_smooth_tv, fx_smooth_tv_preview(0) 46816#@gui : Time Step = float(30,5,100) 46817#@gui : Iterations = int(10,1,40) 46818#@gui : Keep Iterations as Different Layers = bool(false) 46819#@gui : sep = separator() 46820#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46821#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46822#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46823#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46824#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46825#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46826#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46827#@gui : sep = separator() 46828#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 46829#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 46830#@gui : sep = separator() 46831#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46832#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46833#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46834#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46835#@gui : sep = separator() 46836#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/08</i>.</small>") 46837fx_smooth_tv : 46838 ac "gui_parallel_overlap \"tv_flow $2,$1,$3 c 0,255\",$5,$6",$4 46839 46840fx_smooth_tv_preview : 46841 gui_split_preview "fx_smooth_tv $*",${-3--1} 46842 46843#@gui Smooth [Wavelets] : fx_smooth_haar, fx_smooth_haar_preview(0) 46844#@gui : Threshold = float(1,0,10) 46845#@gui : Iterations = int(10,1,32) 46846#@gui : Scales = int(10,2,10) 46847#@gui : sep = separator() 46848#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 46849#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 46850#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 46851#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 46852#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 46853#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 46854#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 46855#@gui : sep = separator() 46856#@gui : Parallel Processing = choice("Auto","One Thread","Two Threads","Four Threads","Eight Threads", 46857#@gui : "Sixteen Threads"), Spatial Overlap = int(24,0,256) 46858#@gui : sep = separator() 46859#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 46860#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 46861#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 46862#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 46863#@gui : sep = separator() 46864#@gui : note = note("<small>Author: <i>Jérome Boulanger and David Tschumperlé</i>. 46865#@gui : Latest Update: <i>2013/27/08</i>.</small>") 46866fx_smooth_haar : 46867 remove_opacity 46868 ac "gui_parallel_overlap \"denoise_haar $1,$3,$2 c 0,255\",$5,$6",$4 46869 46870fx_smooth_haar_preview : 46871 gui_split_preview "fx_smooth_haar $*",${-3--1} 46872 46873#@gui Upscale [Diffusion] : fx_upscale_smart, fx_upscale_smart_preview(0) 46874#@gui : Width = text("200%") 46875#@gui : Height = text("200%") 46876#@gui : Smoothness = float(2,0,20) 46877#@gui : Anisotropy = float(0.4,0,1) 46878#@gui : Sharpness = float(50,0,100) 46879#@gui : sep = separator() 46880#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46881fx_upscale_smart : 46882 to_rgb upscale_smart $1,$2,1,$3,$4,$5 c 0,255 46883 46884fx_upscale_smart_preview : 46885 repeat $! 46886 +r. $1,$2,1,1,0 46887 if w<{-2,w}" || "h<{-2,h} # Test for downscaling 46888 rm. /. 4 46889 0 t. "Downscaling is\nnot allowed!",5,5,20,1,255 r. ..,..,1,1,0,0,0.5,0.5 46890 -|[-2,-1] 46891 else 46892 z.. {50-50*{-2,w}/w}%,{50-50*{-2,h}/h}%,{50+50*{-2,w}/w}%,{50+50*{-2,h}/h}% 46893 rm. fx_upscale_smart. $1,$2,$3,$4,$5 c. 0,255 46894 fi 46895 mv. 0 done 46896 46897#@gui Upscale [Scale2x] : fx_scalenx, fx_scalenx_preview(0) 46898#@gui : Scaling Factor = choice("x 2","x 3","x 4","x 6","x 8","x 9","x 12","x 16","x 18","x 27") 46899#@gui : Colorbase = choice(0,"RGB","YCbCr","Lab") 46900#@gui : note = note{"\n<small><b>Note: </b> 46901#@gui : This filter re-implements the scaling algorithm described at : 46902#@gui : </small>"} 46903#@gui : url = link("http://scale2x.sourceforge.net") 46904#@gui : note = note{"<small> 46905#@gui : This filter is useful for resizing images that have very few colors 46906#@gui : (e.g. indexed images). It is generally useless for true colors images. 46907#@gui : </small>"} 46908#@gui : sep = separator() 46909#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 46910fx_scalenx : 46911 repeat $! l[$>] split_opacity 46912 if $2==1 rgb2ycbcr[0] round[0] 46913 elif $2==2 rgb2lab8[0] round[0] 46914 fi 46915 if $1==0 scale2x 46916 elif $1==1 scale3x 46917 elif $1==2 scale2x scale2x 46918 elif $1==3 scale3x scale2x 46919 elif $1==4 scale2x scale2x scale2x 46920 elif $1==5 scale3x scale3x 46921 elif $1==6 scale3x scale2x scale2x 46922 elif $1==7 scale2x scale2x scale2x scale2x 46923 elif $1==8 scale3x scale3x scale2x 46924 elif $1==9 scale3x scale3x scale3x 46925 fi 46926 if $2==1 ycbcr2rgb[0] 46927 elif $2==2 lab82rgb[0] 46928 fi 46929 a c endl done 46930 46931fx_scalenx_preview : 46932 z 40%,40%,60%,60% 46933 fx_scalenx $1,$2 46934 46935#@gui Upscale [DCCI2x]: fx_scale_dcci2x, fx_scale_dcci2x_preview(0) 46936#@gui : note = note("<i>Directional Cubic Convolution Interpolation</i>"), sep = separator() 46937#@gui : Threshold = float(1.15,1,2) 46938#@gui : Exponent = int(5,1,6) 46939#@gui : Extend 1px = _bool(0) 46940#@gui : sep = separator() 46941#@gui : note = note("<small>Author: <i>Garagecoder</i>. Latest Update : <i>2015/11/07</i>.</small>") 46942#@gui : note = note{"\n<small><b>Note: </b> 46943#@gui : This filter re-implements the scaling algorithm described at : 46944#@gui : </small>"} 46945#@gui : url = link("wikipedia.org","https://en.wikipedia.org/wiki/Directional_Cubic_Convolution_Interpolation") 46946#@gui : note = note("<small>The algorithm is intended for enlarging images while avoiding</small>") 46947#@gui : note = note("<small>artifacts, e.g. staircase artifacts.</small>") 46948#@gui : note = note("\n<small>Threshold controls edge[lower] to texture[higher] balance.</small>") 46949#@gui : note = note("<small>Exponent controls texture edge sharpness[higher].</small>") 46950#@gui : note = note("<small>Warning: highly experimental...</small>") 46951fx_scale_dcci2x : skip ${1=1.15},${2=5},${3=0} 46952 repeat $! l[$>] 46953 split_opacity scale_dcci2x ${1-3} a c c 0,255 46954 endl done 46955 46956fx_scale_dcci2x_preview : 46957 z 25%,25%,75%,75% fx_scale_dcci2x $* 46958 46959#@gui ____<b>Rendering</b> 46960#------------------------- 46961 46962# Generic function to render a 3D image, with usual rendering parameters : 46963# $1 = Width 46964# $2 = Height 46965# $3 = Object size 46966# $4 = X-angle 46967# $5 = Y-angle 46968# $6 = Z-angle 46969# $7 = FOV 46970# $8 = X-light 46971# $9 = Y-light 46972# $10 = Z-light 46973# $11 = Specular lightness 46974# $12 = Specular shininess 46975# $13 = Rendering mode. 46976# $14 = Antialiasing (0 | 1) 46977fx_render3d : skip ${14=1} 46978 width={(1+$14)*$1} height={(1+$14)*$2} 46979 n3d c3d m3d {round($13)} f3d={0.5*max($width,$height)/tan($7*pi/360)} 46980 f3d $f3d l3d {$8*$f3d},{$9*$f3d},{$10*$f3d} sl3d $11 ss3d $12 46981 repeat $! l[$>] 46982 *3d {$3*max($width,$height)} r3d 0,0,1,{-$6} r3d 0,1,0,{-$5} r3d 1,0,0,{-$4} 46983 $width,$height,1,3,-1 46984 j3d. ..,50%,50% rm.. 46985 to_rgba replace_color 0,0,-1,-1,-1,255,0,0,0,0 46986 if $14 46987 r $1,$2,1,100%,2 s c,-3 +. 1e-5 /[0] [1] *[0] 255 a c 46988 fi 46989 endl done 46990 46991#@gui 3D Blocks : fx_blocks3d, fx_blocks3d(1) 46992#@gui : Resolution = int(32,1,128) 46993#@gui : Smoothness = float(0,0,40) 46994#@gui : Elevation = float(4,-10,10) 46995#@gui : Size = float(1.5,0,3) 46996#@gui : Angle = float(30,0,360) 46997#@gui : Tilt = float(60,0,90) 46998#@gui : FOV = float(45,1,90) 46999#@gui : Centering (%) = point(50,50) 47000#@gui : sep = separator() 47001#@gui : X-Light = float(0,-100,100) 47002#@gui : Y-Light = float(-50,-100,100) 47003#@gui : Z-Light = float(-100,-100,0) 47004#@gui : Specular Lightness = float(0.5,0,1) 47005#@gui : Specular Shininess = float(0.7,0,3) 47006#@gui : Use Light = bool(1) 47007#@gui : Antialiasing = bool(1) 47008#@gui : Outline Color = color(0,0,0,128) 47009#@gui : sep = separator() 47010#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/10/02</i>.</small>") 47011fx_blocks3d : 47012 repeat $! l[$>] 47013 nm=${"gui_layer_name"} 47014 W={w} H={h} M={max(w,h)} 47015 if w>h r2dx $1 else r2dy $1 fi 47016 w={w} h={h} m={max(w,h)} 47017 if $3>0 mirror y fi 47018 imageblocks3d $3,$2% 47019 -3d. {$w/2},{$h/2} f={$4*$M/($m*(2-$16))} *3d $f,$f,{$f*abs($3*$1/100)} 47020 if $3>0 r3d 1,0,0,180 fi 47021 r3d 0,0,1,$5 r3d 1,0,0,-$6 47022 47023 # Render object. 47024 if $16 {2*$M},{2*$M},1,4,-1 else $M,$M,1,4,-1 fi 47025 f3d={0.5*w/tan($7*pi/360)} f3d $f3d 47026 l3d {$10*$f3d},{$11*$f3d},{$12*$f3d} sl3d $13 ss3d $14 47027 j3d. [0],$8%,$9%,0,1,{if($15,3,2)},0,1 47028 sh. 100% +. 1 *. 255 rm. 47029 47030 # Render object outline 47031 if $20 47032 .,.,1,3,-1 47033 j3d. [0],$8%,$9%,0,1,3,0,1 rm[0] 47034 g. xy,1 +[-2,-1] norm. !=. 0 47035 +r. 100%,100%,1,3 47036 sh. 0 *. $17 rm. 47037 sh. 1 *. $18 rm. 47038 sh. 2 *. $19 rm. 47039 j[0] .,0,0,0,0,{$20/255},.. rm[-2,-1] 47040 else rm[0] 47041 fi 47042 47043 replace_color 0,0,-1,-1,-1,0,0,0,0,0 47044 if $16 r 50%,50%,1,4,2 fi 47045 c 0,255 nm name($nm) 47046 endl done 47047 47048#@gui 3D Colored Object : fx_coloredobject3d, fx_coloredobject3d_preview(1) 47049#@gui : Type = choice{1,"Plane","Box","Pyramid","Ellipsoid","Torus","Gyroid","Weird","Cup"} 47050#@gui : Color = color(128,128,128,255) 47051#@gui : sep = separator() 47052#@gui : Size-1 = float(0.5,0,3) 47053#@gui : Size-2 = float(0.5,0,3) 47054#@gui : Size-3 = float(0.5,0,3) 47055#@gui : X-Angle = float(57,0,360) 47056#@gui : Y-Angle = float(41,0,360) 47057#@gui : Z-Angle = float(21,0,360) 47058#@gui : FOV = float(45,1,90) 47059#@gui : X-Light = float(0,-100,100) 47060#@gui : Y-Light = float(0,-100,100) 47061#@gui : Z-Light = float(-100,-100,0) 47062#@gui : Specular Lightness = float(0.5,0,1) 47063#@gui : Specular Shininess = float(0.7,0,3) 47064#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 47065#@gui : Antialiasing = bool(1) 47066#@gui : sep = separator() 47067#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/16/05</i>.</small>") 47068_fx_coloredobject3d : 47069 to_rgb _fx_coloredobject3d$1$2 ${6-8} col3d. ${3-5} 47070 db3d 0 47071 47072fx_coloredobject3d : 47073 _fx_coloredobject3d "_",${1-4,6-8} 47074 repeat $!-1 47075 +fx_render3d. {$>,w},{$>,h},$6,${9--1} 47076 sh. 3 *. {$5/255} rm. 47077 blend[$>,-1] alpha 47078 done 47079 rm. 47080 47081fx_coloredobject3d_preview : 47082 _fx_coloredobject3d "_preview_",${1-4,6-8} 47083 repeat $!-1 47084 +fx_render3d. {$>,w},{$>,h},$6,${9--1} 47085 sh. 3 *. {$5/255} rm. 47086 blend[$>,-1] alpha 47087 done rm. 47088 47089_fx_coloredobject3d_0 : plane3d 1 *3d. $1,$2,1 47090_fx_coloredobject3d_1 : box3d 1 *3d. $1,$2,$3 47091_fx_coloredobject3d_2 : pyramid3d 1,1 *3d. $1,$2,$3 47092_fx_coloredobject3d_3 : sphere3d 1 *3d. 1,{2*$2},{2*$3} 47093_fx_coloredobject3d_4 : torus3d $1,{$2/2},100,50 *3d. $3,0.5,0.5 47094_fx_coloredobject3d_5 : gyroid3d 24 *3d. $1,$2,$3 47095_fx_coloredobject3d_6 : weird3d 32 *3d. $1,$2,$3 47096_fx_coloredobject3d_7 : cup3d 128 *3d. $1,$2,$3 47097_fx_coloredobject3d_preview_0 : plane3d 1 *3d. $1,$2,1 47098_fx_coloredobject3d_preview_1 : box3d 1 *3d. $1,$2,$3 47099_fx_coloredobject3d_preview_2 : pyramid3d 1,1 *3d. $1,$2,$3 47100_fx_coloredobject3d_preview_3 : sphere3d 1 *3d. 1,{2*$2},{2*$3} 47101_fx_coloredobject3d_preview_4 : torus3d $1,{$2/2},100,50 *3d. $3,0.5,0.5 47102_fx_coloredobject3d_preview_5 : gyroid3d 8 *3d. $1,$2,$3 47103_fx_coloredobject3d_preview_6 : weird3d 12 *3d. $1,$2,$3 47104_fx_coloredobject3d_preview_7 : cup3d 64 *3d. $1,$2,$3 47105 47106#@gui 3D Elevation : fx_elevation3d, fx_elevation3d_preview(1) 47107#@gui : Factor = float(100,-1000,1000) 47108#@gui : Smoothness = float(1,0,10) 47109#@gui : sep = separator() 47110#@gui : Width = _int(1024,8,4096) 47111#@gui : Height = _int(1024,8,4096) 47112#@gui : Size = float(0.8,0,3) 47113#@gui : X-Angle = float(25,0,360) 47114#@gui : Y-Angle = float(0,0,360) 47115#@gui : Z-Angle = float(21,0,360) 47116#@gui : FOV = float(45,1,90) 47117#@gui : X-Light = float(0,-100,100) 47118#@gui : Y-Light = float(0,-100,100) 47119#@gui : Z-Light = float(-100,-100,0) 47120#@gui : Specular Lightness = float(0.5,0,1) 47121#@gui : Specular Shininess = float(0.7,0,3) 47122#@gui : Rendering = choice(2,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 47123#@gui : Antialiasing = bool(1) 47124#@gui : sep = separator() 47125#@gui : note = note{"<small><b>Note:</b> Add a top layer to define object texture.</small>"} 47126#@gui : sep = separator() 47127#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47128_fx_elevation3d : 47129 repeat $!/2 l[$>,{min($>+1,$!-1)}] 47130 if $!==1 +norm else r[1] [0],3 fi 47131 n[1] 0,{abs($1)} *[1] {sign($1)} b[1] $2 47132 elevation3d[0] [1] rm[1] 47133 endl done 47134 db3d 47135 47136fx_elevation3d : 47137 _fx_elevation3d ${1-2} fx_render3d ${3--1} 47138 47139fx_elevation3d_preview : 47140 fx_elevation3d ${1-2},{w},{h},${5--1} 47141 47142#@gui 3D Extrusion : fx_extrude3d, fx_extrude3d_preview(1) 47143#@gui : Depth = float(10,1,1024) 47144#@gui : Resolution = int(512,1,1024) 47145#@gui : Smoothness = float(0.6,0,3) 47146#@gui : sep = separator() 47147#@gui : Width = _int(1024,1,4096) 47148#@gui : Height = _int(1024,1,4096) 47149#@gui : Size = float(0.5,0,3) 47150#@gui : X-Angle = float(57,0,360) 47151#@gui : Y-Angle = float(41,0,360) 47152#@gui : Z-Angle = float(21,0,360) 47153#@gui : FOV = float(45,1,90) 47154#@gui : X-Light = float(0,-100,100) 47155#@gui : Y-Light = float(0,-100,100) 47156#@gui : Z-Light = float(-100,-100,0) 47157#@gui : Specular Lightness = float(0.5,0,1) 47158#@gui : Specular Shininess = float(0.7,0,3) 47159#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 47160#@gui : Antialiasing = bool(1) 47161#@gui : sep = separator() 47162#@gui : note = note{"<small><b>Note:</b> Add a top layer to define object texture.</small>"} 47163#@gui : sep = separator() 47164#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47165_fx_extrude3d : 47166 repeat $!/2 l[$>,{min($>+1,$!-1)}] 47167 extrude3d. $1,$2,$3% 47168 if $!==2 t3d. .. rm.. fi 47169 endl done 47170 db3d 0 47171 47172fx_extrude3d : 47173 _fx_extrude3d ${1-3} fx_render3d ${4--1} 47174 47175fx_extrude3d_preview : 47176 fx_extrude3d ${1-3},{w},{h},${6--1} 47177 47178#@gui 3D Image Object : fx_imageobject3d, fx_imageobject3d_preview(1) 47179#@gui : Type = choice{1,"Plane","Cube","Pyramid","Sphere","Torus","Gyroid","Weird","Cup","Rubik"} 47180#@gui : sep = separator() 47181#@gui : Width = _int(1024,1,4096) 47182#@gui : Height = _int(1024,1,4096) 47183#@gui : Size = float(0.5,0,3) 47184#@gui : X-Angle = float(57,0,360) 47185#@gui : Y-Angle = float(41,0,360) 47186#@gui : Z-Angle = float(21,0,360) 47187#@gui : FOV = float(45,1,90) 47188#@gui : X-Light = float(0,-100,100) 47189#@gui : Y-Light = float(0,-100,100) 47190#@gui : Z-Light = float(-100,-100,0) 47191#@gui : Specular Lightness = float(0.5,0,1) 47192#@gui : Specular Shininess = float(0.7,0,3) 47193#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 47194#@gui : Antialiasing = bool(1) 47195#@gui : sep = separator() 47196#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47197_fx_imageobject3d : 47198 to_rgb repeat $! l[$>] _fx_imageobject3d$1$2 endl done 47199 db3d 0 47200 47201fx_imageobject3d : 47202 _fx_imageobject3d "_",$1 fx_render3d ${2--1} 47203 47204fx_imageobject3d_preview : 47205 w={w} h={h} _fx_imageobject3d "_preview_",$1 fx_render3d $w,$h,${4--1} 47206 47207_fx_imageobject3d_0 : imageplane3d 47208_fx_imageobject3d_1 : imagecube3d 47209_fx_imageobject3d_2 : imagepyramid3d 47210_fx_imageobject3d_3 : imagesphere3d 128,64 47211_fx_imageobject3d_4 : torus3d 100,30,100,50 t3d. .. rm.. 47212_fx_imageobject3d_5 : gyroid3d 24 t3d. .. rm.. 47213_fx_imageobject3d_6 : weird3d 32 t3d. .. rm.. 47214_fx_imageobject3d_7 : cup3d 128 t3d. .. rm.. 47215_fx_imageobject3d_8 : imagerubik3d 5,5 47216_fx_imageobject3d_preview_0 : imageplane3d 47217_fx_imageobject3d_preview_1 : imagecube3d 47218_fx_imageobject3d_preview_2 : imagepyramid3d 47219_fx_imageobject3d_preview_3 : imagesphere3d 64,32 47220_fx_imageobject3d_preview_4 : torus3d 100,30,100,50 t3d. .. rm.. 47221_fx_imageobject3d_preview_5 : gyroid3d 8 c3d. n3d. t3d. .. rm.. 47222_fx_imageobject3d_preview_6 : weird3d 12 t3d. .. rm.. 47223_fx_imageobject3d_preview_7 : cup3d 64 t3d. .. rm.. 47224_fx_imageobject3d_preview_8 : imagerubik3d 3,3,5,5 47225 47226#@gui 3D Lathing : fx_lathing3d, fx_lathing3d_preview(1) 47227#@gui : Resolution = int(76,1,1024) 47228#@gui : Smoothness = float(2,0,5) 47229#@gui : Max Angle = float(361,0,361) 47230#@gui : sep = separator() 47231#@gui : Width = _int(1024,1,4096) 47232#@gui : Height = _int(1024,1,4096) 47233#@gui : Size = float(0.5,0,3) 47234#@gui : X-Angle = float(0,0,360) 47235#@gui : Y-Angle = float(0,0,360) 47236#@gui : Z-Angle = float(0,0,360) 47237#@gui : FOV = float(45,1,90) 47238#@gui : X-Light = float(0,-100,100) 47239#@gui : Y-Light = float(0,-100,100) 47240#@gui : Z-Light = float(-100,-100,0) 47241#@gui : Specular Lightness = float(0.5,0,1) 47242#@gui : Specular Shininess = float(0.7,0,3) 47243#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 47244#@gui : Antialiasing = bool(1) 47245#@gui : sep = separator() 47246#@gui : note = note{"<small><b>Note:</b> Add a top layer to define object texture.</small>"} 47247#@gui : sep = separator() 47248#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47249_fx_lathing3d : 47250 repeat $!/2 l[$>,{min($>+1,$!-1)}] 47251 lathe3d. $1,$2%,$3 47252 if $!==2 t3d. .. rm.. fi 47253 endl done 47254 db3d 0 47255 47256fx_lathing3d : 47257 _fx_lathing3d ${1-3} fx_render3d ${4--1} 47258 nm name("[3D lathing]"),pos(0,0),mode(alpha) 47259 47260fx_lathing3d_preview : 47261 fx_lathing3d ${1-3},{w},{h},${6--1} 47262 47263#@gui 3D Random Objects : fx_random3d, fx_random3d(1) 47264#@gui : Type = choice("Cube","Cone","Cylinder","Sphere","Torus") 47265#@gui : Density = int(50,1,300) 47266#@gui : Size = float(3,1,20) 47267#@gui : Z-Range = float(100,0,300) 47268#@gui : FOV = float(45,1,90) 47269#@gui : X-Light = float(0,-100,100) 47270#@gui : Y-Light = float(0,-100,100) 47271#@gui : Z-Light = float(-100,-100,0) 47272#@gui : Specular Lightness = float(0.5,0,1) 47273#@gui : Specular Shininess = float(0.7,0,3) 47274#@gui : Rendering = choice(3,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 47275#@gui : Opacity = float(1,0,1) 47276#@gui : sep = separator() 47277#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47278fx_random3d : 47279 repeat $! l[$>] 47280 f3d={0.5*max(w,h)/tan($5*pi/360)} f3d $f3d l3d {$6*$f3d},{$7*$f3d},{$8*$f3d} sl3d $9 ss3d $10 47281 to_rgb ({w},{h},{d},{s}) /. 2 repeat $2 47282 ({1,@0}) +. {1,@1} *. $3 /. 100 _fx_random3d$1 {^} rm.. 47283 r3d. 1,1,0,{u(0,360)} 47284 ({u(-1,1)}) *. {1,@0} ({u(-1,1)}) *. {1,@1} 47285 +3d... {-2,^},{^},{u(-$4,$4)} rm[-2,-1] 47286 col3d. {u(255)},{u(255)},{u(255)} done +3d[2--1] j3d[0] .,50%,50%,0,$12,$11,0,1 47287 k[0] 47288 endl done 47289 47290_fx_random3d0 : box3d $1 47291_fx_random3d1 : ($1) /. 2 cone3d {^},$1 rm.. 47292_fx_random3d2 : ($1) /. 2 cylinder3d {^},$1 rm.. 47293_fx_random3d3 : sphere3d $1,2 47294_fx_random3d4 : ($1) /. 3 torus3d $1,{^} rm.. 47295 47296#@gui Ball : fx_ball, fx_ball_preview(0) 47297#@gui : Radius = int(128,1,1024) 47298#@gui : Specular Light = float(0.8,0,8) 47299#@gui : Specular Size = float(1,0,8) 47300#@gui : Shadow = float(1.5,0,4) 47301#@gui : Color = color(255,0,255) 47302#@gui : sep = separator() 47303#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/27/11</i>.</small>") 47304fx_ball : 47305 ball $1,${5-7},${2-4} 47306 if $!>1 mv. 0 nm[0] "name(Ball),pos("{0,0.5*([${-max_wh}]-[w,h])}")" else nm[0] "name(Ball)" fi 47307 47308fx_ball_preview : 47309 fx_ball $* 47310 if $!>1 rv[-2,-1] blend[-2,-1] alpha fi 47311 47312#@gui Circle Art : fx_circle_art, fx_circle_art 47313#@gui : Type = choice(1,"Random","Lissajous spiral") 47314#@gui : Density = float(15,0,100) 47315#@gui : Radius = float(0.5,0,1) 47316#@gui : Modulo = int(8,2,16) 47317#@gui : Anti-Aliasing = bool(1) 47318#@gui : Random Colors = bool(1) 47319#@gui : sep = separator() 47320#@gui : note = note("<small><b>Lissajous parameters:</b></small>") 47321#@gui : Curve Length = float(15,0,50) 47322#@gui : Curve Angle = float(0,0,360) 47323#@gui : Minimal Radius = float(0,-5,5) 47324#@gui : Maximal Radius = float(0.5,-5,5) 47325#@gui : X-Dispersion = float(1,0,4) 47326#@gui : Y-Dispersion = float(1,0,4) 47327#@gui : X-Factor = int(1,0,16) 47328#@gui : Y-Factor = int(1,0,16) 47329#@gui : sep = separator() 47330#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/22/08</i>.</small>") 47331fx_circle_art : 47332 if !$2 f 0 return fi 47333 # Generate object coordinates. 47334 if $1==0 # Random. 47335 {round(2*($2^1.5))} 47336 rand. -1,1 +rand. -1,1 +rand. -$3,$3 a[-3--1] y 47337 else # Spiral. 47338 {max(1,round($2*$7))} 47339 t0={$8*2*pi/180} 47340 rows. 0,2 47341 f. "r = x/(w-1); 47342 t = 2*pi*x/$2; 47343 if(y==0,(r^$11)*cos("$t0"+$13*t), 47344 if(y==1,(r^$12)*sin("$t0"+$14*t), 47345 max(0,$3*($9+($10-$9)*r))))" 47346 fi 47347 47348 # Convert to 3D object. 47349 l. 47350 transpose s x,-1 h={h} 47351 i[0] ({'CImg3d'},{2*$h},$h) # Header. 47352 ++... . -[-4,-2] i .. i[-3,-1] 1,100% a[-6--1] x # Vertices. 47353 1,$h,1,1,5 1,$h,1,1,2*y ++. 1 a[-3--1] x z. 0,5 # Primitives. 47354 3,$h,1,1,1 1,$h,1,1,-1 y a y # Colors + Opacities. 47355 endl 47356 47357 # Render object on selected images. 47358 repeat $!-1 l[$>,-1] 47359 s={0,max(w,h)} rm[0] 47360 if $5 {2*$s},{2*$s} +*3d[0] $s # Anti-aliasing. 47361 else $s,$s +*3d[0] {$s/2} # No anti-aliasing. 47362 fi 47363 j3d[1] [2],50%,50%,0,1,2,0,0 rm[2] 47364 %. $4 47365 if $6 i.. 100%,100%,1,3 rand.. 0,255 plasma.. 1,1 equalize.. 256 n.. 0,255 blend[-2,-1] shapeaverage fi 47366 rv 47367 endl done 47368 rm. 47369 n 0,255 47370 if $5 r 50%,50%,1,100%,2 fi 47371 47372#@gui Equation Plot [Parametric] : fx_equation_parametric, fx_equation_parametric 47373#@gui : X(t) = text{"sin(t)*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)"} 47374#@gui : Y(t) = text{"cos(t)*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)"} 47375#@gui : Min-t = float(0,-1000,1000) 47376#@gui : Max-t = float(100,-1000,1000) 47377#@gui : Resolution = int(4096,2,32768) 47378#@gui : Outline Opacity = float(1,0,1) 47379#@gui : Dot Size = int(0,0,16) 47380#@gui : Start Color = color(64,0,0) 47381#@gui : End Color = color(128,0,0) 47382#@gui : Colored Outline = bool(1) 47383#@gui : Antialiasing = bool(1) 47384#@gui : Decoration = bool(1) 47385#@gui : sep = separator() 47386#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/13/11</i>.</small>") 47387fx_equation_parametric : 47388 repeat $! l[$>] 47389 w={w} h={h} rm 47390 $5,1,1,2,"t=$3+x*($4-$3)/($5-1);if(c==0,$1,$2)" 47391 channels. 0,2 47392 ($8,$11^$9,$12^$10,$13) r. {-2,w},1,1,3,3 a c 47393 display_parametric $w,$h,{$6+$14*1.001},$7,$15,$16 47394 endl done 47395 47396#@gui Equation Plot [Y=f(X)] : fx_equation_plot, fx_equation_plot 47397#@gui : F(X) = text{"X*c+10*cos(X+c+u)"} 47398#@gui : X-Min = float(-10,-100,100) 47399#@gui : X-Max = float(10,-100,100) 47400#@gui : Resolution = int(100,2,1024) 47401#@gui : Channels = int(3,1,32) 47402#@gui : Plot Type = choice(2,"None","Lines","Splines","Bars") 47403#@gui : Vertex Type = choice(0,"None","Points","Crosses 1","Crosses 2","Circles 1","Circles 2","Square 1","Square 2") 47404#@gui : sep = separator() 47405#@gui : note = note("<small><b>Note</b> : 47406#@gui : Use variable <b>X</b> instead of <b>x</b> in the above equation to take care of the X-min/max settings. 47407#@gui : Variable <b>c</b> refers to the current channel number. 47408#@gui : Variable <b>u</b> refers to a uniformly distributed random value in [0,1]. 47409#@gui : Reduce resolution to be able to view 47410#@gui : separate graph vertices.</small>") 47411#@gui : sep = separator() 47412#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47413fx_equation_plot : 47414 repeat $! l[$>] 47415 w={w} h={h} rm 47416 $4,1,1,$5,"X=$2+($3-$2)*x/($4-1);$1" 47417 dg $w,$h,$6,$7,$2,$3 47418 endl done 47419 47420#@gui Gradient [Corners] : fx_corner_gradient, fx_corner_gradient 47421#@gui : Color 1 (Up/Left Corner) = color(255,255,255,128) 47422#@gui : Color 2 (Up/Right Corner) = color(255,0,0,255) 47423#@gui : Color 3 (Bottom/Left Corner) = color(0,255,0,255) 47424#@gui : Color 4 (Bottom/Right Corner) = color(0,0,255,255) 47425#@gui : sep = separator() 47426#@gui : Colorspace = choice(1,"sRGB","Linear RGB","Lab") 47427#@gui : sep = separator() 47428#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47429fx_corner_gradient : skip ${17=0} 47430 repeat $! l[$>] 47431 wh={w},{h} rm 47432 ($1,$5;$9,$13^$2,$6;$10,$14^$3,$7;$11,$15^$4,$8;$12,$16) 47433 _gb_fwd $17 47434 r. $wh,1,100%,3 47435 _gb_bwd $17 47436 endl done 47437 47438#@gui Gradient [Custom Shape] : fx_custom_gradient, fx_custom_gradient_preview(1) 47439#@gui : note = note("<small><b>Shape selection:</b></small>") 47440#@gui : Select By = choice("Auto","Dark Pixels","Bright Pixels","Opaque Pixels") 47441#@gui : Smoothness = float(0,0,10) 47442#@gui : Threshold = float(0,0,100) 47443#@gui : Preview Shape = bool(1) 47444#@gui : note = note("<small><b>Note:</b> Shapes with small strokes may lead to incorrect previews.</small>") 47445#@gui : sep = separator() 47446#@gui : note = note("<small><b>Gradient parameters:</b></small>") 47447#@gui : Number of Colors = int(4,2,10) 47448#@gui : Cycles = float(1,1,16) 47449#@gui : Offset = float(0,0,100) 47450#@gui : Shading = float(128,1,256) 47451#@gui : Inner Length = float(100,0,100) 47452#@gui : Outer Length = float(100,0,100) 47453#@gui : Spatial Metric = choice(2,"Chebyshev","Manhattan","Euclidean") 47454#@gui : Color Metric = choice("RGB","HSV","Lab") 47455#@gui : Shade Back to First Color = bool(1) 47456#@gui : Preview Gradient = bool(0) 47457#@gui : Save Gradient As = _text("") 47458#@gui : sep = separator() 47459#@gui : note = note("<small><b>Color definitions:</b></small>") 47460#@gui : Colormap Type = choice(1,"Pre-Defined","User-Defined") 47461#@gui : Pre-Defined Colormap = int(0,0,65535) 47462#@gui : 1st Color = color(0,0,0,255) 47463#@gui : 2nd Color = color(255,0,0,255) 47464#@gui : 3rd Color = color(255,255,0,255) 47465#@gui : 4th Color = color(255,255,255,255) 47466#@gui : 5th Color = color(0,255,255,255) 47467#@gui : 6th Color = color(0,255,0,255) 47468#@gui : 7th Color = color(0,0,255,255) 47469#@gui : 8th Color = color(128,128,128,255) 47470#@gui : 9th Color = color(255,0,255,255) 47471#@gui : 10th Color = color(0,0,0,0) 47472#@gui : sep = separator() 47473#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2013/03/10</i>.</small>") 47474fx_custom_gradient_preview : skip "${15=}" 47475 repeat $! l[$>] 47476 if $4 47477 +_fx_custom_gradient1 ${1-14},"$15",${16--1} +erode. 3 -[-2,-1] +dilate. 5 a[-2,-1] c n. 0,255 47478 fx_custom_gradient[0] ${1-14},"$15",${16--1},-1 blend alpha 47479 else fx_custom_gradient ${1-14},"$15",${16--1},-1 47480 fi 47481 if $14 47482 +_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. 47483 fi 47484 endl done 47485 47486fx_custom_gradient : skip "${15=}" 47487 _fx_custom_gradient0 ${1-14},"$15",${16--1} 47488 if $-1>=0" && "narg("$15") 47489 dir_ggr=${-path_gimp}gradients 47490 0 nm. ${"normalize_filename \"$15\""} name_ggr={b} rm. output_ggr. $dir_ggr/$name_ggr.ggr,"$15" 47491 fi 47492 i.. (0^0^0^0) a[-2,-1] x 47493 repeat $!-1 l[$>,-1] 47494 _fx_custom_gradient1[0] ${1-14},"$15",${16--1} 47495 +distance[0] 1,$11 +distance[0] 0,$11 *. -1 +[0] 1 +[0,-2,-1] # Signed distance function. 47496 m={$9%*{0,im}} M={$10%*{0,iM}} 47497 -[0] $m *[0] {1,(w-2)/($M-$m)} +[0] 1 47498 round[0] map[0] . 47499 endl done 47500 rm. 47501 47502# Create colormap. 47503_fx_custom_gradient0 : 47504 if $16 4,8,1,1,${18-56} permute. yzcx 47505 else 8,1,1,3 srand $17 rand. 0,255 to_rgba. 47506 fi 47507 z. 0,{$5-1} 47508 if $13 47509 r. {200*$6}%,1,1,4,0,2 47510 __fx_custom_gradient0. $12,$8 47511 shift. {-round(w*0.5*$7%)},0,0,0,2 z. 0,{w/2-1} 47512 else 47513 __fx_custom_gradient0. $12,$8 47514 r. {100*$6}%,1,1,4,0,2 shift. {-round(w*$7%)},0,0,0,2 47515 fi 47516 47517__fx_custom_gradient0 : 47518 if $1==1 sh. 0,2 rgb2hsv. rm. 47519 elif $1==2 sh. 0,2 srgb2rgb. rgb2lab. rm. 47520 fi 47521 r. {$2*w},1,1,4,3 47522 if $1==1 sh. 0,2 hsv2rgb. rm. 47523 elif $1==2 sh. 0,2 lab2rgb. rgb2srgb. rm. 47524 fi 47525 47526# Extract shape from image. 47527_fx_custom_gradient1 : 47528 b $2% 47529 if $1==0 # Auto-mode. 47530 to_a split_opacity 47531 if iM>im+32 47532 rm.. >=[0] {100-$3}% 47533 else 47534 rm. norm n 0,1 47535 if ia>0.5 <=[0] $3% else >=[0] {100-$3}% fi 47536 fi 47537 elif $1==1 # Dark pixels. 47538 remove_opacity norm <= $3% 47539 elif $1==2 # Bright pixels. 47540 remove_opacity norm >= {100-$3}% 47541 else # Opaque pixels. 47542 to_a channels 100% >= {100-$3}% 47543 fi 47544 47545#@gui Gradient [from Line] : fx_line_gradient, fx_line_gradient_preview(1) 47546#@gui : Starting Point (%) = point(0,0,0,1,255,0,0) 47547#@gui : Ending Point (%) = point(100,100,0,1,64,128,255) 47548#@gui : Sampling = float(100,0,100) 47549#@gui : Length = int(0,0,4096) 47550#@gui : note = note("<small><b>Note:</b> Set length to <i>0</i> to release gradient length constraints.</small>") 47551#@gui : Sort Colors = choice("Don't Sort","By Red Component","By Green Component","By Blue Component", 47552#@gui : "By Luminance","By Blue Chrominance","By Red Chrominance","By Lightness") 47553#@gui : Reverse Gradient = bool(0) 47554#@gui : sep = separator() 47555#@gui : Preview Gradient = bool(1) 47556#@gui : Save Gradient As = _text("") 47557#@gui : sep = separator() 47558#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/29/06</i>.</small>") 47559fx_line_gradient : skip "${10=}" 47560 _fx_line_gradient $* 47561 if narg("$10") 47562 dir_ggr=${-path_gimp}gradients 47563 0 nm. ${"normalize_filename \"$10\""} name_ggr={b} rm. output_ggr. $dir_ggr/$name_ggr.ggr,"$10" 47564 fi 47565 repeat $! r[$>] 100%,64,1,100% done 47566 47567fx_line_gradient_preview : 47568 repeat $! l[$>] 47569 to_rgba 47570 if $9 +_fx_line_gradient $* fi 47571 l[0] 47572 line $1%,$2%,$3%,$4%,1,0xF0F0F0F0,255,255,255,255 47573 line $1%,$2%,$3%,$4%,1,0x0F0F0F0F,0,0,0,255 47574 endl 47575 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 47576 endl done 47577 47578_fx_line_gradient : 47579 at_line $1%,$2%,0,$3%,$4%,0 r {max(0.1,$5)}%,1,1,100%,1 47580 m "feature1 : channels 0" 47581 m "feature2 : channels 1" 47582 m "feature3 : channels 2" 47583 m "feature4 : to_rgb luminance" 47584 m "feature5 : to_rgb rgb2ycbcr channels 1" 47585 m "feature6 : to_rgb rgb2ycbcr channels 2" 47586 m "feature7 : to_rgb srgb2rgb rgb2lab channels 0" 47587 if $7 repeat $! l[$>] +feature$7 rv a y sort +,x rows 1 endl done fi 47588 if $6 r $6,1,1,100%,3 fi 47589 if $8 mirror x fi 47590 47591#@gui Gradient [Linear] : fx_linear_gradient, fx_linear_gradient 47592#@gui : Starting Color = color(0,0,0,255) 47593#@gui : Ending Color = color(255,255,255,255) 47594#@gui : Swap Colors = bool(0) 47595#@gui : Angle = float(45,0,360) 47596#@gui : Fade Start = float(0,0,100) 47597#@gui : Fade End = float(100,0,100) 47598#@gui : sep = separator() 47599#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 47600#@gui : sep = separator() 47601#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 47602fx_linear_gradient : skip ${13=0} 47603 repeat $! l[$>] 47604 wh={w},{h} rm 47605 ($1^$2^$3^$4) ($5^$6^$7^$8) 47606 if $9 rv[-2,-1] fi 47607 r $wh 47608 _gb_fwd $13 47609 fade_linear $10,$11,$12 47610 _gb_bwd $13 47611 endl done 47612 47613#@gui Gradient [Radial] : fx_radial_gradient, fx_radial_gradient 47614#@gui : Starting Color = color(0,0,0,255) 47615#@gui : Ending Color = color(255,255,255,255) 47616#@gui : Swap Colors = bool(0) 47617#@gui : Fade Start = float(0,0,100) 47618#@gui : Fade End = float(100,0,100) 47619#@gui : Center (%) = point(50,50,0,1,255) 47620#@gui : sep = separator() 47621#@gui : Colorspace = choice(0,"sRGB","Linear RGB","Lab") 47622#@gui : sep = separator() 47623#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/29/06</i>.</small>") 47624fx_radial_gradient : skip ${14=0} 47625 repeat $! l[$>] 47626 wh={w},{h} rm 47627 ($1^$2^$3^$4) ($5^$6^$7^$8) 47628 if $9 rv[-2,-1] fi 47629 r $wh 47630 _gb_fwd $14 47631 100%,100% =. 1,$12%,$13% distance. 1 _fade $10,$11 47632 _gb_bwd $14 47633 endl done 47634 47635#@gui Gradient [Random] : fx_random_gradient, fx_random_gradient 47636#@gui : Density = int(32,1,1024) 47637#@gui : Seed = int(0,0,65535) 47638#@gui : Smoothness = float(0,0,10) 47639#@gui : Color Balance = color(128,128,128) 47640#@gui : Opacity = float(1,0,1) 47641#@gui : sep = separator() 47642#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/08/04</i>.</small>") 47643fx_random_gradient : 47644 repeat $! l[$>] 47645 to_rgba 100%,100% srand $2 47646 eval "repeat ($1,n, 47647 x = round(u(w-1)); 47648 y = round(u(h-1)); 47649 i(x,y) = 1; 47650 i(#0,x,y,0,0) = round(u(255)); 47651 i(#0,x,y,0,1) = round(u(255)); 47652 i(#0,x,y,0,2) = round(u(255)); 47653 i(#0,x,y,0,3) = $7*255 + (1-$7)*round(u(255)); 47654 )" 47655 if $7!=1 sh.. 100% n. 0,255 rm. fi 47656 ==. 0 47657 sh.. 0,2 srgb2rgb. rm. 47658 inpaint_pde.. [1],100%,1 rm. 47659 b $3% n 0,255 47660 sh 0,2 rgb2srgb. balance_gamma. ${4-6} rm. 47661 endl done 47662 47663#@gui Hypotrochoid : fx_hypotrochoid, fx_hypotrochoid(1) 47664#@gui : Periods = int(37,1,100) 47665#@gui : Outer Radius (%) = float(100,0,300) 47666#@gui : Inner Radius (%) = float(74,0,300) 47667#@gui : Distance to center (%) = float(80,0,300) 47668#@gui : Thickness (%) = float(0.5,0,5) 47669#@gui : Color = color(255,255,255,255) 47670#@gui : Anti-aliasing = bool(1) 47671#@gui : sep = separator() 47672#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/01/25</i>.</small>") 47673fx_hypotrochoid : 47674 {0,[w,h]*($10?1.5:1)} 47675 eval " 47676 const M = min(w,h)/2; 47677 const A = M*$2%; 47678 const B = A*$3%; 47679 const H = B*$4%; 47680 const S = M*$5%; 47681 const F = (A - B)/max(1e-5,B); 47682 const AmB = A - B; 47683 hypotrochoid(t) = (_t = t; round([ w/2 + AmB*cos(_t) + H*cos(F*_t), h/2 + AmB*sin(_t) - H*sin(F*_t) ])); 47684 47685 oX = hypotrochoid(t); 47686 dt = 1; 47687 for (t = 0, t<$1*2*pi, 47688 do ( 47689 X = hypotrochoid(t + dt); 47690 dist = abs(X[0] - oX[0]) | abs(X[1] - oX[1]); 47691 !dist?(dt*=2): 47692 dist>1?(dt/=1.25): 47693 (t+=dt), 47694 dist!=1; 47695 ); 47696 S<1?(I(X) = $9):ellipse(X,S,S,0,1,$9); 47697 oX = X; 47698 )" 47699 r. [0],[0],1,1,2 47700 channels. -3,0 sh. 0,2 fc. ${6-8} rm. 47701 blend[0,-1] alpha 47702 47703#@gui Lightning : fx_lightning, fx_lightning_preview 47704#@gui : note = note{"<small><b>Global parameters:</b></small>"} 47705#@gui : Number of Streaks = int(20,1,1024) 47706#@gui : Size (%) = float(90,0,150) 47707#@gui : Resolution = int(256,2,4096) 47708#@gui : Randomness = float(3,0,16) 47709#@gui : Smoothness = float(1.5,0,10) 47710#@gui : Balance = float(0.75,0,1) 47711#@gui : Color = color(255,255,255,255) 47712#@gui : Seed = int(0,0,65535) 47713#@gui : sep = separator() 47714#@gui : note = note{"<small><b>Initial streak:</b></small>"} 47715#@gui : XY-Coordinates (%) = point(50,5,0,1) 47716#@gui : Angle (deg) = float(0,-180,180) 47717#@gui : Thickness (px) = int(6,1,64) 47718#@gui : Blur = float(0.2,0,3) 47719#@gui : sep = separator() 47720#@gui : note = note{"<small><b>Auxiliary streaks:</b></small>"} 47721#@gui : Min Offset (%) = float(25,0,100) 47722#@gui : Max Offset (%) = float(60,0,100) 47723#@gui : Min Length (%) = float(95,0,200) 47724#@gui : Max Length (%) = float(100,0,200) 47725#@gui : Min Angle Deviation (deg) = float(30,0,180) 47726#@gui : Max Angle Deviation (deg) = float(40,0,180) 47727#@gui : Thickness Factor = float(-0.25,-1,1) 47728#@gui : Blur Factor = float(-0.1,-1,1) 47729#@gui : Opacity Factor = float(-0.20,-1,1) 47730#@gui : sep = separator() 47731#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/27/11</i>.</small>") 47732fx_lightning : 47733 repeat $! l[$<] 47734 100%,100% l. fact={max(w,h)/$3*$2%} srand $11 47735 repeat $1 47736 if $!<=1 47737 i=0 47738 new_level=1 47739 new_length=$3 47740 new_x=0 47741 new_y=0 47742 new_angle=$14 47743 else 47744 i={round(u(1,max(1,($!-1)*$6)))} 47745 level={$i,@-2} 47746 angle={$i,@-1} 47747 nb_points={$i,i[6]} 47748 p={round(($nb_points-2)*u($17%,$18%))} 47749 new_level={$level+1} 47750 new_length={max(2,round(($nb_points-$p)*u($19%,$20%)))} 47751 new_x={$i,i[8+3*$p]} 47752 new_y={$i,i[9+3*$p]} 47753 new_angle={$angle+u($21,$22)*if(u>0.5,1,-1)} 47754 fi 47755 47756 _fx_lightning $new_length,$4,$5 47757 r3d. 0,0,1,$new_angle 47758 +3d. $new_x,$new_y 47759 +*3d. $fact [0],[0] j3d. ..,$12%,$13%,0,1,1,0,0 rm.. 47760 47761 dilation={$15*(if($23>0,1.5,10)^($23*($new_level-1)))} 47762 blur={max(0,-1+(1+$16)*(if($24>0,2,5)^($24*($new_level-1))))} 47763 opacity={min(1,$10/255*(2^($25*($new_level-1))))} 47764 47765 dilate. $dilation b. $blur% n. 0,1 *. $opacity max[0,-1] 47766 ($new_level;$new_angle) a[-2,-1] y 47767 progress {($>*100)/($1-1)} 47768 done 47769 k[0] * 255 i[0] 100%,100%,1,3 fc[0] ${7-9} a c 47770 endl 47771 rv 47772 endl done 47773 47774fx_lightning_preview : 47775 repeat $! l[$>] 47776 fx_lightning $* rv blend alpha 47777 endl done 47778 47779_fx_lightning : 47780 l[] 47781 ({'CImg3d'},$1,{$1-1}) 47782 1,$1 noise. $2,1 cumulate. b. $3 shift. 0,1 1,100%,1,1,y 1,100% a[-3--1] x 47783 1,{h-1},1,1,2 +f. y ++. 1 a[-3--1] x 47784 4,100%,1,1,1 47785 y a y 47786 endl 47787 47788#@gui Lissajous : fx_lissajous, fx_lissajous(1) 47789#@gui : Resolution = int(4096,2,8192) 47790#@gui : sep = separator() 47791#@gui : X-Size = float(0.9,0,2) 47792#@gui : Y-Size = float(0.9,0,2) 47793#@gui : Z-Size = float(3,1,10) 47794#@gui : sep = separator() 47795#@gui : X-Multiplier = float(8,0,32) 47796#@gui : Y-Multiplier = float(7,0,32) 47797#@gui : Z-Multiplier = float(0,0,32) 47798#@gui : sep = separator() 47799#@gui : X-Offset = float(0,0,1) 47800#@gui : Y-Offset = float(0,0,1) 47801#@gui : Z-Offset = float(0,0,1) 47802#@gui : sep = separator() 47803#@gui : X-Angle = float(0,0,360) 47804#@gui : Y-Angle = float(0,0,360) 47805#@gui : Z-Angle = float(0,0,360) 47806#@gui : sep = separator() 47807#@gui : Thickness = float(0,0,50) 47808#@gui : Color = color(255,255,255,255) 47809#@gui : sep = separator() 47810#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/04</i>.</small>") 47811fx_lissajous : 47812 repeat $! l[$>] to_rgba 47813 {w},{h} 47814 f3d {0.5*max(w,h)/tan($4*pi/360)} 47815 lissajous3d $1,$5,$8,$6,$9,$7,$10 47816 r3d. 0,0,1,$13 r3d. 0,1,0,$12 r3d. 1,0,0,$11 47817 *3d. {0.5*$2*{-2,w}},{0.5*$3*{-2,h}},{0.5*$4*max({-2,w},{-2,h})} 47818 col3d. 1 j3d.. .,50%,50%,0,1,1,0,0 rm. 47819 distance. 1 >. $14% *.. . ==. 0 47820 r. 100%,100%,1,4 47821 sh. 0 *. $15 rm. 47822 sh. 1 *. $16 rm. 47823 sh. 2 *. $17 rm. 47824 sh. 3 *. $18 rm. 47825 +[-2,-1] 47826 endl done 47827 47828#@gui Mandelbrot - Julia Sets : fx_mandelbrot, fx_mandelbrot_preview 47829#@gui : X0 = value(-2) 47830#@gui : Y0 = value(-2) 47831#@gui : X1 = value(2) 47832#@gui : Y1 = value(2) 47833#@gui : note = note{"<small><b>Fractal Type:</b></small>"} 47834#@gui : Fractal Set = choice("Mandelbrot","Julia") 47835#@gui : Iterations = int(1024,16,65535) 47836#@gui : X-Seed (Julia) = float(0.317,-2,2) 47837#@gui : Y-Seed (Julia) = float(0.03,-2,2) 47838#@gui : sep = separator() 47839#@gui : note = note{"<small><b>Colormap:</b></small>"} 47840#@gui : Number of Colors = int(16,2,2048) 47841#@gui : Smoothness = int(8,1,256) 47842#@gui : Seed = int(255,0,65536) 47843#@gui : sep = separator() 47844#@gui : note = note{"<small><b>Navigation:</b></small>"} 47845#@gui : Zoom Center = point(50,50,0,0,255,255,255,200) 47846#@gui : Zoom Factor = float(0.25,0,1) 47847#@gui : Zoom In = button() 47848#@gui : Center = button() 47849#@gui : Zoom Out = button() 47850#@gui : Display Coordinates = bool(0) 47851#@gui : sep = separator() 47852#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/06/27</i>.</small>") 47853fx_mandelbrot : 47854 if !narg($_size) _size={max(w,h)} fi 47855 rm $_size,$_size 47856 mandelbrot ${1-4},$6,{$5?[1,$7,$8]:[0,0,0]} 47857 srand $11 $9,1,1,3 rand. 0,255 r. {$9*$10},1,1,3,3 point. 0 map.. .,3 rm. 47858 47859fx_mandelbrot_preview : 47860 _size={min(${-gui_preview_wh})} 47861 if "$15 || $16 || $17" 47862 x0,y0,x1,y1={"P0 = [${1,2}]; 47863 dP = [${3,4}] - P0; 47864 C = P0 + [${12,13}]%*dP; 47865 zfact = $14*($15?1:$16?0:-2); 47866 dC = 0.5*dP*(1 - 0.98*zfact); 47867 [C - dC,C + dC]"} 47868 status=\{$x0\}\{$y0\}\{$x1\}\{$y1\}\{$5\}\{$6\}\{$7\}\{$8\}\{$9\}\{$10\}\{$11\}\ 47869 \{50,50\}\{$14\}\{0\}\{0\}\{0\}\{$18\} 47870 px,py=50 47871 else 47872 x0,y0,x1,y1=${1-4} 47873 status= 47874 px,py=${12,13} 47875 fi 47876 fx_mandelbrot $x0,$y0,$x1,$y1,${5--1} 47877 47878 x0r,y0r,x1r,y1r={"C = ["$px,$py"]%*w; dC = 0.5*w*(1 - 0.98*$14); round([C - dC, C + dC - 1])"} 47879 rectangle $x0r,$y0r,$x1r,$y1r,0.7,0xF0F0F0F0,255,255,255,255 47880 rectangle $x0r,$y0r,$x1r,$y1r,0.7,0x0F0F0F0F,0,0,0,255 47881 if $18 to "Z0 = ( "{_$x0}" , "{_$y0}" )\nZ1 = ( "{_$x1}" , "{_$y1}" )",2,2,16 fi 47882 u $status 47883 47884#@gui Neon Lightning : fx_neon_lightning, fx_neon_lightning(1) 47885#@gui : Source (%) = point(50,50) 47886#@gui : R0 = float(0,0,100) 47887#@gui : Destination (%) = point(50,50) 47888#@gui : R1 = float(100,0,100) 47889#@gui : sep = separator() 47890#@gui : Density = int(50,1,512) 47891#@gui : Glow = float(0.7,0,5) 47892#@gui : Thickness = float(3,0,20) 47893#@gui : sep = separator() 47894#@gui : Color = color(130,80,50) 47895#@gui : Color Dispersion = float(0.25,0,1) 47896#@gui : Transparency = float(0,0,1) 47897#@gui : sep = separator() 47898#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/30/06</i>.</small>") 47899fx_neon_lightning : 47900 d={$13*255} 47901 repeat $! l[$>] 47902 100%,100%,1,4 rm[0] 47903 repeat $7 47904 x0={max(0,min(w,$1+u(-$3,$3)))} y0={max(0,min(h,$2+u(-$3,$3)))} 47905 x1={max(0,min(w,$4+u(-$6,$6)))} y1={max(0,min(h,$5+u(-$6,$6)))} 47906 u0={u(0,100)} v0={u(0,100)} u1={u(0,100)} v1={u(0,100)} 47907 R={max(0,min(255,u($10-$d,$10+$d)))} 47908 G={max(0,min(255,u($11-$d,$11+$d)))} 47909 B={max(0,min(255,u($12-$d,$12+$d)))} 47910 spline $x0%,$y0%,$u0%,$v0%,$x1%,$y1%,$u1%,$v1%,1,$R,$G,$B,1 47911 done 47912 s c,-3 47913 b[0] 3% 47914 distance. 1 *. -1 c. -{$9+1e-5},0 n. 0,1 sqrt. 47915 +b. $8%,1 n. 0,1 sqrt. n[-2,-1] 0,255 max[-2,-1] 47916 . blend[0,1] value 47917 smooth 5,0,1,0.5,2,10,0 47918 /. 255 ^. $14 *. 255 47919 a c c 0,255 47920 endl done 47921 47922#@gui Newton Fractal : fx_newton_fractal, fx_newton_fractal_preview 47923#@gui : X0 = value(-2) 47924#@gui : Y0 = value(-2) 47925#@gui : X1 = value(2) 47926#@gui : Y1 = value(2) 47927#@gui : note = note{"<span color="#EE5500"><b>Fractal Type:</b></span>"} 47928#@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") 47929#@gui : p(z) = text{"rot(35°)*z^^3 - z^^2 + 1"}_1 47930#@gui : p'(z) = text{"3*z^^2 - 2*z"}_1 47931#@gui : p''(z) = text{"6*z - 2"}_1 47932#@gui : Descent method = choice(1,"Secant","Newton","Householder") 47933#@gui : Max iterations = int(200,16,1024) 47934#@gui : Precision = float(2,0,12) 47935#@gui : sep = separator() 47936#@gui : note = note{"<span color="#EE5500"><b>Rendering:</b></span>"} 47937#@gui : Coloring = choice(1,"By Custom Expression","By Iteration","By Value") 47938# 47939# Color by iteration 47940# 47941#@gui : Number of Colors = int(16,2,2048) 47942#@gui : Smoothness = int(8,1,256) 47943#@gui : Seed = int(255,0,65536) 47944# 47945# Color by value 47946# 47947#@gui : Colorspace = choice(2,"HSI","HSL","HSV")_0 47948#@gui : Hue min (%) = float(100,0,500)_0 47949#@gui : Hue max (%) = float(150,0,500)_0 47950#@gui : Lightness min (%) = float(20,0,500)_0 47951#@gui : Lightness max (%) = float(400,0,500)_0 47952# 47953# Custom coloring 47954# 47955#@gui : Colorspace = choice(3,"RGB,"HSI","HSL","HSV","Lab")_0 47956#@gui : Pre-Process = choice(2,"None","Equalize","Normalize","Equalize and Normalize")_0+ 47957#@gui : note = note{"<small><span color="#EE5500"><b>Tips for Custom expressions:</b></span>\n 47958#@gui : - Variables <b>i0,i1</b> stand for the real and imaginary parts of the iterated complex number.\n 47959#@gui : - Variable <b>i2</b> is the number of iterations required for convergence.\n 47960#@gui : - Variable <b>z</b> is the complex number with value <b>[ i0,i1 ]</b>.\n 47961#@gui : - Functions <b>p(z), dp(z)</b> and <b>d2p(z)</b> are the expressions used for computing the fractal. 47962#@gui : </small>"} 47963#@gui : Channel #1 = text{"carg(-z)"}_0 47964#@gui : Channel #2 = text{"(i0 + i1)/2"}_0 47965#@gui : Channel #3 = text{"10*(i2^0.4)"}_0 47966#@gui : Post-Process = choice(0,"None","Equalize","Normalize","Equalize and Normalize")_0 47967# 47968# Basic color adujstment 47969# 47970#@gui : Brightness (%) = float(0,-100,100) 47971#@gui : Contrast (%) = float(0,-100,100) 47972#@gui : Gamma (%) = float(0,-100,100) 47973#@gui : Hue (%) = float(0,-100,100) 47974#@gui : Saturation (%) = float(0,-100,100) 47975#@gui : Equalization (%) = float(0,0,100) 47976#@gui : Anti-aliasing = choice(2,"x1","x1.5","x2","x2.5","x3","x3.5","4") 47977#@gui : note = note{"<small><b>Note:</b> Anti-aliasing is applied on final rendering only, not on preview.</small>"} 47978#@gui : antialias_note = value(0)_2- 47979#@gui : sep = separator() 47980# 47981# Navigation 47982# 47983#@gui : note = note{"<span color="#EE5500"><b>Navigation:</b></span>"} 47984#@gui : Zoom Center = point(50,50,0,0,255,255,255,200) 47985#@gui : Zoom Factor = float(0.5,0,1) 47986#@gui : Angle = float(0,-180,180) 47987#@gui : Zoom In = button() 47988#@gui : Center = button() 47989#@gui : Zoom Out = button() 47990#@gui : Reset View = button() 47991#@gui : Display Coordinates on Preview Window = bool(1) 47992#@gui : Preview subsampling = choice(2,"None","x1.5","x2","x2.5","x3","x3.5","x4") 47993#@gui : sep = separator() 47994#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/01/09</i>.</small>") 47995fx_newton_fractal : skip "${6=},${7=},${8=},${22=},${25=},${28=}" 47996 repeat $! l[$>] 47997 if !narg($_size) _size={max(w,h)} fi 47998 rm 47999 antialias={arg(1+$33,1,1.5,2,2.5,3,3.5,4)} 48000 {$antialias*[$_size,$_size]} 48001 if $5==1 48002 pz="z^^2 - 1" dpz="2*zn" d2pz="2" 48003 elif $5==2 48004 pz="z^^3 - 1" dpz="3*z^^2" d2pz="6*z" 48005 elif $5==3 48006 pz="z^^5 - 1" dpz="5*z^^4" d2pz="20*z^^3" 48007 elif $5==4 48008 pz="z^^6 + z^^3 - 1" dpz="6*z^^5 + 3*z^^2" d2pz="30*z^^4 + 6*z" 48009 elif $5==5 48010 pz="z^^8 + 15*z^^4 - 1" dpz="8*z^^7 + 60*z^^3" d2pz="56*z^^6 + 180*z^^2"; 48011 else 48012 pz="$6" dpz="$7" d2pz="$8" 48013 fi 48014 if !narg($pz) pz="[1,0]" fi 48015 if !narg($dpz) dpz="[1,0]" fi 48016 if !narg($d2pz) d2pz="[1,0]" fi 48017 48018 newton_fractal ${1-4},$38,$9,$10,{10^-$11},$pz,$dpz,$d2pz 48019 48020 if $12==1 # Color by iteration 48021 channels 100% 48022 srand $15 $13,1,1,3 rand. 0,255 r. {$13*$14},1,1,3,3 point. 0 map.. .,3 rm. 48023 48024 elif $12==2 # Color by value 48025 f "[ atan2(i1,i0),1,i2 ]" s c n... {[$17,$18]*360%} n. {[$19,$20]%} c. 0,1 a c 48026 ${"arg 1+$16,hsi,hsl,hsv"}2rgb 48027 48028 else # Custom coloring 48029 48030 if $22 # Pre-process values 48031 s c,-2 48032 if $22&1 equalize 1024 fi 48033 if $22&2 /[-2] {-2,max(1e-5,abs(im),abs(iM))} n. 0,1 fi 48034 a c 48035 fi 48036 48037 f "*begin( 48038 p(z) = ("$pz"); 48039 dp(z) = ("$dpz"); 48040 d2p(z) = ("$d2pz"); 48041 ); 48042 z = [ i0,i1 ]; 48043 [ (0;$23),(0;$24),(0;$25) ]" 48044 48045 if $26 # Post-process values 48046 s c 48047 if $26&1 equalize 1024 fi 48048 if $26&2 normalize 0,1 fi 48049 a c 48050 fi 48051 48052 * 255 mod 256 48053 if $21 ${"arg $21,hsi8,hsl8,hsv8,lab8"}2rgb fi # Convert to RGB colors 48054 fi 48055 48056 r2dx $_size 48057 48058 if $32 ac "+equalize 1024 j.. .,0,0,0,0,{$32%} rm.",ycbcr_y fi 48059 adjust_colors ${27-31},0,0,0,255 48060 endl done 48061 48062fx_newton_fractal_preview : skip "${6=},${7=},${8=},${22=},${25=},${28=}" 48063 is_custom_expression={$5==0?2:1} 48064 is_color_by_custom={$12==0?2:0} 48065 is_color_by_iter={$12==1?2:0} 48066 is_color_by_value={$12==2?2:0} 48067 _size0={min(${-gui_preview_wh})} 48068 _size={$_size0/arg(1+$44,1,1.5,2,2.5,3,3.5,4)} 48069 48070 angle=$38 48071 if "$39 || $40 || $41" 48072 x0,y0,x1,y1={"P0 = [${1,2}]; 48073 dP = [${3,4}] - P0; 48074 M = P0 + 0.5*dP; 48075 C = P0 + [${35,36}]%*dP; 48076 C = M + rot(-$38°)*(C - M); 48077 zfact = $37*($39?1:$40?0:-2); 48078 dC = 0.5*dP*(1 - 0.98*zfact); 48079 [ C - dC, C + dC ]"} 48080 px,py=50 48081 elif $42 48082 x0,y0,x1,y1=-2,-2,2,2 48083 px,py=50 48084 angle=0 48085 else 48086 x0,y0,x1,y1=${1-4} 48087 px,py=${35,36} 48088 fi 48089 fx_newton_fractal $x0,$y0,$x1,$y1,$5,"$6","$7","$8",${9-22},"$23","$24","$25",${26-32},0,${34-37},$angle,${39--1} 48090 48091 repeat $! l[$>] 48092 r2dx $_size0,1 48093 x0r,y0r,x1r,y1r={"C = [ "$px,$py" ]%*w; dC = 0.5*w*(1 - 0.98*$37); round([ C - dC, C + dC - 1 ])"} 48094 rectangle $x0r,$y0r,$x1r,$y1r,0.7,0xF0F0F0F0,255,255,255,255 48095 rectangle $x0r,$y0r,$x1r,$y1r,0.7,0x0F0F0F0F,0,0,0,255 48096 if $43 to "Z0 = ( "{_$x0}" , "{_$y0}" )\nZ1 = ( "{_$x1}" , "{_$y1}" )",2,2,16 fi 48097 endl done 48098 48099 u "{"$x0"}{"$y0"}{"$x1"}{"$y1"}{$5}"\ 48100 "{$6}_"$is_custom_expression\ 48101 "{$7}_"$is_custom_expression\ 48102 "{$8}_"$is_custom_expression\ 48103 "{$9}{$10}{$11}{$12}"\ 48104 "{$13}_"$is_color_by_iter\ 48105 "{$14}_"$is_color_by_iter\ 48106 "{$15}_"$is_color_by_iter\ 48107 "{$16}_"$is_color_by_value\ 48108 "{$17}_"$is_color_by_value\ 48109 "{$18}_"$is_color_by_value\ 48110 "{$19}_"$is_color_by_value\ 48111 "{$20}_"$is_color_by_value\ 48112 "{$21}_"$is_color_by_custom\ 48113 "{$22}_"$is_color_by_custom\ 48114 "{$23}_"$is_color_by_custom\ 48115 "{$24}_"$is_color_by_custom\ 48116 "{$25}_"$is_color_by_custom\ 48117 "{$26}_"$is_color_by_custom\ 48118 "{$27}{$28}{$29}{$30}{$31}{$32}{$33}"\ 48119 "{$34}"_{$33==0?0:2}\ 48120 "{"$px,$py"}{$37}{"$angle"}{0}{0}{0}{0}{$43}{$44}" 48121 48122#@gui Plasma : fx_plasma, fx_plasma(0) 48123#@gui : Alpha = float(0.5,0,5) 48124#@gui : Beta = float(0,0,100) 48125#@gui : Scale = int(8,2,10) 48126#@gui : Randomize = bool(0) 48127#@gui : Transparency = bool(0) 48128#@gui : Color Balance = color(128,128,128) 48129#@gui : sep = separator() 48130#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/20/03</i>.</small>") 48131fx_plasma : skip ${4=0},${5=0} 48132 if $5 to_rgba else to_rgb fi 48133 if $4 rand 0,255 fi 48134 plasma $1,$2,$3 n 0,255 48135 balance_gamma ${6-8} 48136 48137#@gui Quick Copyright : fx_quick_copyright, fx_quick_copyright(0) 48138#@gui : Text = text{"\\251 G'MIC"} 48139#@gui : Size = int(27,13,128) 48140#@gui : Color = color(255,255,255,128) 48141#@gui : Outline = int(1,0,4) 48142#@gui : Position = choice(3,"Up-Left","Up-Right","Bottom-Left","Bottom-Right") 48143#@gui : Offset = int(5,0,40) 48144#@gui : Orientation = choice(1,"-90 deg.","0 deg.","+90 deg.","+180 deg.") 48145#@gui : sep = separator() 48146#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48147fx_quick_copyright : 48148 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 48149 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} 48150 rotate[0,1] {90*($10-1)} 48151 repeat $!-2 48152 if $8==0 j. [0],$9,$9,0,0,{$6/255},[1] 48153 elif $8==1 j. [0],{w-1-{0,w}-$9},$9,0,0,{$6/255},[1] 48154 elif $8==2 j. [0],$9,{h-1-{0,h}-$9},0,0,{$6/255},[1] 48155 else j. [0],{w-1-{0,w}-$9},{h-1-{0,h}-$9},0,0,{$6/255},[1] 48156 fi 48157 mv. 2 done 48158 rm[0,1] 48159 48160#@gui Rainbow : fx_rainbow, fx_rainbow 48161#@gui : Left Position = float(80,0,100) 48162#@gui : Right Position = float(80,0,100) 48163#@gui : Left Slope = float(175,0,400) 48164#@gui : Right Slope = float(175,0,400) 48165#@gui : Thinness = float(3,0.1,8) 48166#@gui : Opacity = float(80,0,199) 48167#@gui : sep = separator() 48168#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48169fx_rainbow : 48170 repeat $! l[$>] 48171 100%,100% spline. 0,$1%,100,{-$3}%,100%,$2%,100,$4%,1,1 48172 flood. 0,0,0,0,0,1,1 flood. {w-1},0,0,0,0,1,1 48173 distance. 0 c. 0,255 n. 0,{$5*255} 48174 palette rainbow +luminance. c. 0,{min(100,200-$6)}% n. 0,255 a[-2,-1] c 48175 map.. . rm. 48176 if $6<100 sh. 3 *. {$6/100} rm. fi 48177 blend alpha 48178 endl done 48179 48180#@gui Shade Bobs : fx_shadebobs, fx_shadebobs 48181#@gui : note = note("<small>Bobs parameters :</small>") 48182#@gui : Density = int(50,1,200) 48183#@gui : Radius = int(5,1,100) 48184#@gui : Duration = int(200,1,500) 48185#@gui : Velocity = float(1,0,10) 48186#@gui : sep = separator() 48187#@gui : note = note("<small>Curve parameters :</small>") 48188#@gui : Rx = float(-1,-3,3) 48189#@gui : Ry = float(2,-3,3) 48190#@gui : Rz = float(1,-3,3) 48191#@gui : Rt = float(0.8,-3,3) 48192#@gui : Rcx = float(0,-3,3) 48193#@gui : Colormap = choice(8,"Grayscale","Standard","HSV","Lines","Hot","Cool","Jet","Flag","Cube") 48194#@gui : sep = separator() 48195#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/18/04</i>.</small>") 48196fx_shadebobs : 48197 channels 0 f 0 48198 repeat $! l[$>] 48199 t=0 48200 repeat $3 48201 repeat $1 48202 r={$6+$5*cos(6*$7*$t)+(1-$5)*sin(6*$8*$t)} 48203 a={(360*sin($7*$t)+30*$6*$>)*pi/180} 48204 ax={2*$>*pi/$1+$t} 48205 cx={(1+$9*cos($ax)+$r*cos($a))*w/2} 48206 cy={(1+$9*sin($ax)+$r*sin($a))*h/2} 48207 ellipse. $cx,$cy,$2%,$2%,0,-1,1 48208 done 48209 t+={$4%} 48210 done 48211 endl done 48212 & 255 if $10 map {$10-1} fi 48213 48214#@gui Sine Curve : fx_sine_curve, fx_sine_curve_preview 48215#@gui : note = note("<span color="#EE5500"><b>Curve parameters:</b></span>") 48216#@gui : Preset = choice{1,"Default (Circle)","Alien Rasta","All Round","Carnivorous Plant","Cat Pad","Flower", 48217#@gui : "Flower Cushion","Fly Karateka","Hearts","Moving Leaf","Radioactive Flower","Rosace","Spaceship", 48218#@gui : "Transformer","Tubular Waves","Twisted Heart","Twisted Heart 2","Twisted Tunnel","Waterslide"} 48219#@gui : Previous Preset = value(-1) 48220#@gui : Resolution (%) = float(75,0,100) 48221#@gui : Periods = float(1,0,3) 48222#@gui : sep = separator() 48223#@gui : Parameter Settings = choice(1,"Ratios","Multipliers","Offsets","Exponents","Signs","3D Angles") 48224#@gui : note = note("<small><span color="#EE0055"><b>Ratios:</b></span></small>") 48225#@gui : Xa/Xb = float(0.5,0,1)_0- 48226#@gui : Ya/Yb = float(0.5,0,1)_0 48227#@gui : Za/Zb = float(0.5,0,1)_0 48228#@gui : note = note("<small><span color="#EE0055"><b>Multipliers:</b></span></small>") 48229#@gui : Xa-Multiplier = int(1,0,1024)_2- 48230#@gui : Ya-Multiplier = int(1,0,1024)_2 48231#@gui : Za-Multiplier = int(0,0,1024)_2 48232#@gui : Xb-Multiplier = int(800,0,1024)_2 48233#@gui : Yb-Multiplier = int(800,0,1024)_2 48234#@gui : Zb-Multiplier = int(1,0,1024)_2 48235#@gui : note = note("<small><span color="#EE0055"><b>Offsets:</b></span></small>") 48236#@gui : Xa-Offset (deg.) = float(90,0,360)_0- 48237#@gui : Ya-Offset (deg.) = float(0,0,360)_0 48238#@gui : Za-Offset (deg.) = float(0,0,360)_0 48239#@gui : Xb-Offset (deg.) = float(90,0,360)_0 48240#@gui : Yb-Offset (deg.) = float(0,0,360)_0 48241#@gui : Zb-Offset (deg.) = float(0,0,360)_0 48242#@gui : note = note("<small><span color="#EE0055"><b>Exponents:</b></span></small>") 48243#@gui : Xa-Exponent = float(1,0,32)_0- 48244#@gui : Ya-Exponent = float(1,0,32)_0 48245#@gui : Za-Exponent = float(1,0,32)_0 48246#@gui : Xb-Exponent = float(1,0,32)_0 48247#@gui : Yb-Exponent = float(1,0,32)_0 48248#@gui : Zb-Exponent = float(1,0,32)_0 48249#@gui : note = note("<small><span color="#EE0055"><b>Signs:</b></span></small>") 48250#@gui : Xa-Sign = choice("Preserve","Invert","Negative","Positive")_0- 48251#@gui : Ya-Sign = choice("Preserve","Invert","Negative","Positive")_0 48252#@gui : Za-Sign = choice("Preserve","Invert","Negative","Positive")_0 48253#@gui : Xb-Sign = choice("Preserve","Invert","Negative","Positive")_0 48254#@gui : Yb-Sign = choice("Preserve","Invert","Negative","Positive")_0 48255#@gui : Zb-Sign = choice("Preserve","Invert","Negative","Positive")_0 48256#@gui : note = note("<small><span color="#EE0055"><b>3D Angles:</b></span></small>") 48257#@gui : X-Angle (deg.) = float(0,-180,180)_0- 48258#@gui : Y-Angle (deg.) = float(0,-180,180)_0 48259#@gui : Z-Angle (deg.) = float(0,-180,180)_0 48260#@gui : Zoom = float(1,0,10)_0 48261#@gui : Focale = int(8,1,20)_0 48262#@gui : sep = separator() 48263#@gui : note = note("<span color="#EE5500"><b>Rendering parameters:</b></span>") 48264#@gui : Center = point(50,50,0,1,0,238,85,-170,10)_0 48265#@gui : Old X-Center = value(50) 48266#@gui : Old Y-Center = value(50) 48267#@gui : Radius = point(68,68,0,1,238,0,85,-170,10)_0 48268#@gui : Angle = point(75,50,0,1,238,85,0,-170,10)_0 48269#@gui : Old X-Angle = value(75) 48270#@gui : Old Y-Angle = value(50) 48271#@gui : Primary radius (%) = float(3,0,100) 48272#@gui : Secondary radius (%) = float(2,0,100) 48273#@gui : Opacity (%) = float(40,0,100) 48274#@gui : Color = color(255,255,255) 48275#@gui : Anti-aliasing = choice(2,"None","× 1.25","× 1.5","× 2","× 3") 48276#@gui : sep = separator() 48277#@gui : Preview background = choice(1,"Image","Black","White") 48278#@gui : sep = separator() 48279#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2021/03/04</i>.</small>") 48280fx_sine_curve : 48281 48282 # Get parameters as named variables. 48283 preset,previous_preset,\ 48284 resolution,periods,dp,\ 48285 ratx,raty,ratz,\ 48286 mxa,mya,mza,mxb,myb,mzb,\ 48287 oxa,oya,oza,oxb,oyb,ozb,\ 48288 pxa,pya,pza,pxb,pyb,pzb,\ 48289 sxa,sya,sza,sxb,syb,szb,\ 48290 rotx,roty,rotz,zoom,focale,\ 48291 xc,yc,prev_xc,prev_yc,xr,yr,xa,ya,prev_xa,prev_ya,\ 48292 radius1,radius2,opacity,\ 48293 colR,colG,colB,\ 48294 antialiasing,\ 48295 preview_background=$* 48296 48297 if !narg($_is_preview) _is_preview=0 fi 48298 if [$prev_xc,$prev_yc]!=[$xc,$yc] 48299 xr,yr,xa,ya,prev_xa,prev_ya+={d=[$xc,$yc]-[$prev_xc,$prev_yc];[d,d,d]} 48300 fi 48301 if [$prev_xa,$prev_ya]!=[$xa,$ya] 48302 delta_a={" 48303 a = [ "$xa" - "$xc", "$ya" - "$yc" ]; 48304 b = [ "$prev_xa" - "$xc", "$prev_ya" - "$yc" ]; 48305 (atan2(a[1],a[0]) - atan2(b[1],b[0]))*180/pi; 48306 "} 48307 xr,yr={[$xc,$yc]+rot($delta_a°)*[$xr-$xc,$yr-$yc]} 48308 else delta_a=0 fi 48309 if [$colR,$colG,$colB]==[0,0,0]" && "$preview_background==1 colR,colG,colB=255 48310 elif [$colR,$colG,$colB]==[255,255,255]" && "$preview_background==2 colR,colG,colB=0 48311 fi 48312 48313 # Manage presets. 48314 update_params=0 48315 if $preset!=$previous_preset 48316 48317 # Set default parameters for presets ('Default (Circle)'). 48318 periods=1 48319 ratx,raty,ratz=0.5,0.5,0 48320 mxa,mxb,mya,myb,mza,mzb=1,1,1,1,0,1 48321 oxa,oxb,oya,oyb,oza,ozb=90,90,0,0,0,0 48322 pxa,pxb,pya,pyb,pza,pzb=1 48323 sxa,sxb,sya,syb,sza,szb=0 48324 rotx,roty,rotz,zoom,focale=0,0,0,2,8 48325 48326 # Set specific values for each preset. 48327 48328 # Default (circle) 48329 if $preset==0 48330 ratx,raty,ratz=0 zoom=1 48331 # Alien Rasta 48332 elif $preset==1 48333 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 48334 # All Round 48335 elif $preset==2 48336 mxa,mxb,mya,myb=1,200,1,150 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48337 # Carnivorous Plant 48338 elif $preset==3 48339 mxa,mxb,mya,myb=9,512,1024,9 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48340 # Cat Pad 48341 elif $preset==4 48342 mxa,mxb,mya,myb=80,1,80,1 pxa,pxb,pya,pyb=1,3,1,3 48343 # Flower 48344 elif $preset==5 48345 ratz=0.8 mza,mzb=7,1024 pza,pzb=1.6,2 rotz=45 zoom=1 focale=4 48346 # Flower Cushion 48347 elif $preset==6 48348 mxa,mxb,mya,myb=80,1,1,80 pxa,pxb,pya,pyb=1,3,1,3 48349 # Fly Karateka 48350 elif $preset==7 48351 mxa,mxb,mya,myb=150,1,1,100 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48352 # Hearts 48353 elif $preset==8 48354 mxa,mxb,mya,myb=1,80,80,80 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48355 # Moving Leaf 48356 elif $preset==9 48357 mxa,mxb,mya,myb=2,200,200,1 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48358 # Radioactive Flower 48359 elif $preset==10 48360 mxa,mxb,mya,myb=1,800,1,800 pxa,pxb,pya,pyb=1,3,1,3 48361 # Rosace 48362 elif $preset==11 48363 mxa,mxb,mya,myb=1,10,1,10 48364 # Spaceship 48365 elif $preset==12 48366 mxa,mxb,mya,myb=1,400,1,200 pxa,pxb,pya,pyb=1,3,1,3 sxa,sxb,sya,syb=1,1,0,0 48367 # Transformer 48368 elif $preset==13 48369 mxa,mxb,mya,myb=1,800,800,2 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48370 # Tubular Waves 48371 elif $preset==14 48372 mxa,mxb,mya,myb=1,30,1,60 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48373 # Twisted Heart 48374 elif $preset==15 48375 mxa,mxb,mya,myb=500,1,1,500 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48376 # Twisted Heart 2 48377 elif $preset==16 48378 mxa,mxb,mya,myb=1,80,80,1 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48379 # Twisted Tunnel 48380 elif $preset==17 48381 mxa,mxb,mya,myb=1,80,1,40 pxa,pxb,pya,pyb=1,3,1,4 sxa,sxb,sya,syb=0,1,0,2 48382 # Waterslide 48383 elif $preset==18 48384 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 48385 fi 48386 fi 48387 48388 # Change unit for some variables. 48389 W,H={w#0?[w#0,h#0]:$_is_preview" && "0$_preview_width?[0$_preview_width,0$_preview_height]:[1024,1024]} 48390 nresolution={max(1,round($periods*1000000*($resolution%)^2))} 48391 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)} 48392 noxa,noxb,noya,noyb,noza,nozb={[$oxa,$oxb,$oya,$oyb,$oza,$ozb]*pi/180} 48393 nantialiasing={arg0($antialiasing,1,1.25,1.5,2,3)} 48394 rW,rH={[$W,$H]*$nantialiasing} # Size of the non-antialiased rendering 48395 48396 # Generate and render curve. 48397 l[] 48398 48399 # Compute curve coordinates. 48400 $nresolution,1,1,2,"* 48401 begin( 48402 const is_rot = "$rotx" || "$roty" || "$rotz"; 48403 ref(rot(1,0,0,"$rotx"°),Rx); 48404 ref(rot(0,1,0,"$roty"°),Ry); 48405 ref(rot(0,0,1,"$rotz"°),Rz); 48406 R = mul(Rz,mul(Ry,Rx,3),3); # 3D rotation 48407 48408 # Variables to manage 2D rotation. 48409 const ang = atan2("$ya" - "$yc","$xa" - "$xc"); 48410 const cosa = cos(ang); 48411 const sina = sin(ang); 48412 48413 # Variables to manage aspect ratio. 48414 const c = 35; 48415 const dxr0 = "$xr" - "$xc"; 48416 const dyr0 = "$yr" - "$yc"; 48417 const dxr = cosa*dxr0 + sina*dyr0; 48418 const dyr = -sina*dxr0 + cosa*dyr0; 48419 const _dx = abs(dxr)/c; const dx = 2.5*c*(_dx<1?_dx:_dx^3); 48420 const _dy = abs(dyr)/c; const dy = 2.5*c*(_dy<1?_dy:_dy^3); 48421 ); 48422 48423 cpow(x,p,s) = ( 48424 ref(x,_x); 48425 (!s?sign(_x):s==1?-sign(_x):s==2?-1:1)*abs(_x)^p 48426 ); 48427 48428 t = x/w*2*pi*"$periods"; 48429 X = lerp(cpow(sin("$mxa"*t + "$noxa"),"$pxa","$sxa"), 48430 cpow(sin("$mxb"*t + "$noxb"),"$pxb","$sxb"), 48431 "$ratx"); 48432 Y = lerp(cpow(sin("$mya"*t + "$noya"),"$pya","$sya"), 48433 cpow(sin("$myb"*t + "$noyb"),"$pyb","$syb"), 48434 "$raty"); 48435 Z = lerp(cpow(sin("$mza"*t + "$noza"),"$pza","$sza"), 48436 cpow(sin("$mzb"*t + "$nozb"),"$pzb","$szb"), 48437 "$ratz"); 48438 48439 # Set aspect ratio and rotate. 48440 X*=dx%; 48441 Y*=dy%; 48442 is_rot?(P = R*[ X,Y,Z ]; X = P[0]; Y = P[1]; Z = P[2]); 48443 48444 # 2D projection. 48445 X*="$nfocale"; 48446 Y*="$nfocale"; 48447 Z = max(1e-5,Z + 1 + "$nfocale"); 48448 pX = X/Z; 48449 pY = -Y/Z; 48450 48451 # Normalize and get display coordinates. 48452 ang?(X = cosa*pX - sina*pY; pY = sina*pX + cosa*pY; pX = X); 48453 48454 const ax = "$zoom*$rW"; const bx = "$xc*$rW"%; 48455 const ay = "$zoom*$rH"; const by = "$yc*$rH"%; 48456 [ ax*pX + bx, ay*pY + by ]" 48457 48458 # Draw curve (as an alpha-channel). 48459 $rW,$rH 48460 eval.. "* 48461 const mwh = min(w#-1,h#-1)*5%; 48462 const r1 = max(0.01,mwh*"$radius1"%); 48463 const r2 = max(0.01,mwh*"$radius2"%); 48464 const Mr = max(r1,r2); 48465 const opacity = ("$opacity"%)^3; 48466 48467 X = R; Y = G; 48468 48469 Mr<0?( 48470 i(#-1,X,Y) = lerp(i(#-1,X,Y),1,opacity); 48471 ):( 48472 pX = i(x - 1,0,0,0); 48473 pY = i(x - 1,0,0,1); 48474 dX = X - pX; 48475 dY = Y - pY; 48476 ang = atan2(dY,dX)*180/pi; 48477 ellipse(#-1,X,Y,r1,r2,ang°,opacity,255); 48478 ); 48479 I" 48480 rm.. 48481 r. $W,$H,1,1,2 n 0,255 48482 i[0] 100%,100%,1,3 fc[0] $colR,$colG,$colB 48483 a[-2,-1] c 48484 endl 48485 48486 if $_is_preview 48487 if $!==1 i[0] $W,$H,1,3 fi 48488 if $preview_background [0],[0] f. {$preview_background==1?0:255} to_rgb. rv[0,-1] rm. fi 48489 blend[0,-1] alpha 48490 line. $xc%,$yc%,$xr%,$yr%,0.75,0xF0F0F0F0,238,0,85 48491 line. $xc%,$yc%,$xr%,$yr%,0.75,0x0F0F0F0F,255 48492 line. $xc%,$yc%,$xa%,$ya%,0.75,0xF0F0F0F0,238,85,0 48493 line. $xc%,$yc%,$xa%,$ya%,0.75,0x0F0F0F0F,0 48494 fi 48495 mv. 0 48496 if $_output_mode k[0] fi 48497 48498 48499 # Update parameter values. 48500 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]} 48501 u "{"$preset"}{"$preset"}{"$resolution"}{"$periods"}{"$dp"}"\ 48502 "{"$ratx"}_"$r"{"$raty"}_"$r"{"$ratz"}_"$r\ 48503 "{"$mxa"}_"$m"{"$mya"}_"$m"{"$mza"}_"$m"{"$mxb"}_"$m"{"$myb"}_"$m"{"$mzb"}_"$m\ 48504 "{"$oxa"}_"$o"{"$oya"}_"$o"{"$oza"}_"$o"{"$oxb"}_"$o"{"$oyb"}_"$o"{"$ozb"}_"$o\ 48505 "{"$pxa"}_"$p"{"$pya"}_"$p"{"$pza"}_"$p"{"$pxb"}_"$p"{"$pyb"}_"$p"{"$pzb"}_"$p\ 48506 "{"$sxa"}_"$s"{"$sya"}_"$s"{"$sza"}_"$s"{"$sxb"}_"$s"{"$syb"}_"$s"{"$szb"}_"$s\ 48507 "{"$rotx"}_"$a"{"$roty"}_"$a"{"$rotz"}_"$a"{"$zoom"}_"$a"{"$focale"}_"$a\ 48508 "{"$xc,$yc"}{"$xc"}{"$yc"}{"$xr,$yr"}{"$xa,$ya"}{"$xa"}{"$ya"}{"$radius1"}{"$radius2"}{"$opacity"}"\ 48509 "{"$colR,$colG,$colB"}{"$antialiasing"}"\ 48510 "{"$preview_background"}" 48511 48512fx_sine_curve_preview : 48513 _is_preview=1 48514 fx_sine_curve $* 48515 k[0] 48516 48517#@gui Superformula : fx_superformula, fx_superformula(1) 48518#@gui : Resolution = int(4096,2,8192) 48519#@gui : sep = separator() 48520#@gui : X-Size = float(0.9,0,2) 48521#@gui : Y-Size = float(0.9,0,2) 48522#@gui : sep = separator() 48523#@gui : M = int(8,1,32) 48524#@gui : N1 = float(1,-32,32) 48525#@gui : N2 = float(5,-32,32) 48526#@gui : N3 = float(8,-32,32) 48527#@gui : sep = separator() 48528#@gui : X-Angle = float(0,0,360) 48529#@gui : Y-Angle = float(0,0,360) 48530#@gui : Z-Angle = float(0,0,360) 48531#@gui : sep = separator() 48532#@gui : Thickness = float(3,0,50) 48533#@gui : Color = color(128,255,128,255) 48534#@gui : sep = separator() 48535#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/04</i>.</small>") 48536fx_superformula : 48537 repeat $! l[$>] to_rgba 48538 {w},{h} 48539 f3d {0.5*max(w,h)/tan($4*pi/360)} 48540 superformula3d $1,${4-7} 48541 r3d. 0,0,1,$10 r3d. 0,1,0,$9 r3d. 1,0,0,$8 48542 *3d. {0.5*$2*{-2,w}},{0.5*$3*{-2,h}} 48543 col3d. 1 j3d.. .,50%,50%,0,1,1,0,0 rm. 48544 distance. 1 >. $11% *.. . ==. 0 48545 r. 100%,100%,1,4 48546 sh. 0 *. $12 rm. 48547 sh. 1 *. $13 rm. 48548 sh. 2 *. $14 rm. 48549 sh. 3 *. $15 rm. 48550 +[-2,-1] 48551 endl done 48552 48553#@gui Symmetric 2D Shape : fx_symmetric_shape2d, fx_symmetric_shape2d_preview(1) 48554#@gui : Subdivisions = int(5,2,32) 48555#@gui : Center = point(50,50,0,1,255,255,255,128) 48556#@gui : Old Center = value(50,50) 48557#@gui : Angle / Size = point(50,30,0,1,255,255,255,128) 48558#@gui : Old Angle / Size = value(50,30) 48559#@gui : sep = separator() 48560#@gui : Control Point 1 = point(50,25,1,1,255,128,0,255,4) 48561#@gui : Control Point 2 = point(56,42,1,1,255,128,0,255,4) 48562#@gui : Control Point 3 = point(52,52,-1,1,255,128,0,255,4) 48563#@gui : Control Point 4 = point(52,52,-1,1,255,128,0,255,4) 48564#@gui : Control Point 5 = point(52,52,-1,1,255,128,0,255,4) 48565#@gui : Control Point 6 = point(52,52,-1,1,255,128,0,255,4) 48566#@gui : sep = separator() 48567#@gui : Drawing Mode = choice(1,"Outlined","Filled") 48568#@gui : Color = color(255,0,255) 48569#@gui : Opacity (%) = float(100,0,100) 48570#@gui : sep = separator() 48571#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/06/17</i>.</small>") 48572fx_symmetric_shape2d : 48573 if !narg($_is_preview) _is_preview=0 fi 48574 repeat $! l[$<] 48575 100%,100%,1,4 _fx_symmetric_shape2d. $* rv 48576 if !$_is_preview" && "$_output_mode rm. fi 48577 endl done 48578 48579_fx_symmetric_shape2d : 48580 (${10-21}) f. "isnan(i)?-1024:i" discard. -1024 r. 2,{h/2},1,1,-1 permute. cyzx 48581 f. "x = R - $2; y = G - $3; [ atan2(y,x), norm(x,y) ]" 48582 l. n={h} .x{$1-1} a y f "const pi2 = 2*pi; [ (R + int(y/"$n")*pi2/$1)%pi2, G ]" sort +,y endl 48583 f. "[ $2*w#-2,$3*h#-2 ]/100 + [ G*cos(R), G*sin(R) ]*(min(w#-2,h#-2)-1)%" permute. cyzx 48584 coords={^} rm. 48585 if $22 polygon {narg($coords)/2},$coords,1,${23-25},{$26*255%} 48586 else polygon {narg($coords)/2},$coords,1,0xFFFFFFFF,${23-25},{$26*255%} 48587 fi 48588 48589fx_symmetric_shape2d_preview : 48590 _fx_symmetric_shape2d_preview $* 48591 48592_fx_symmetric_shape2d_preview : 48593 _is_preview=1 48594 cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4,cx5,cy5,cx6,cy6=${10-21} 48595 angx,angy=$6,$7 48596 if [$2,$3]!=[$4,$5]" || "[$angx,$angy]!=[$8,$9] # Center or angle has been modified 48597 dx,dy={[$2-$4,$3-$5]} 48598 repeat 6 i={1+$>} 48599 cx$i,cy$i={" 48600 const cx = "${cx$i}"; 48601 const cy = "${cy$i}"; 48602 dang = atan2($7 - $3,$6 - $2) - atan2($9 - $3,$8 - $2); 48603 dsca = norm($6 - $2,$7 - $3)/norm($9 - $3,$8 - $2); 48604 [ $2,$3 ] + dsca*rot(dang)*[ cx - $4, cy - $5 ]"} 48605 done 48606 angx,angy={[$6+$2-$4,$7+$3-$5]} 48607 fi 48608 48609 repeat $! l[$>] 48610 r {s=min(w,h);[s,s]},1,100%,0,0,0.5,0.5 48611 fx_symmetric_shape2d ${1-9},$cx1,$cy1,$cx2,$cy2,$cx3,$cy3,$cx4,$cy4,$cx5,$cy5,$cx6,$cy6,${22-26} 48612 rv blend alpha 48613 eval " 48614 t0 = atan2($7 - $3,$6 - $2); 48615 repeat ($1,k, 48616 const pi2 = 2*pi; 48617 const xc = $2*(w-1)%; 48618 const yc = $3*(h-1)%; 48619 x = xc + (w+h)*cos(t0 + 2*pi*k/$1); 48620 y = yc + (w+h)*sin(t0 + 2*pi*k/$1); 48621 polygon(-2,xc,yc,x,y,0.35,0xF0F0F0F0,255); 48622 polygon(-2,xc,yc,x,y,0.35,0x0F0F0F0F,0); 48623 )" 48624 endl done 48625 48626 u "{$1}"\ # Subdivisions 48627 "{$2,$3}"\ # Center 48628 "{$2,$3}"\ # Old Center 48629 "{"$angx,$angy"}"\ # Angle 48630 "{"$angx,$angy"}"\ # Old Angle 48631 "{"$cx1,$cy1"}"\ # Control point 1 48632 "{"$cx2,$cy2"}"\ # Control point 2 48633 "{"$cx3,$cy3"}"\ # Control point 3 48634 "{"$cx4,$cy4"}"\ # Control point 4 48635 "{"$cx5,$cy5"}"\ # Control point 5 48636 "{"$cx6,$cy6"}"\ # Control point 6 48637 "{$22}"\ # Drawing mode 48638 "{$23,$24,$25}"\ # Color 48639 "{$26}" # Opacity 48640 48641#@gui Tree : fx_tree, fx_tree_preview(1) 48642#@gui : note = note("<small><b><span color="#EE5500">Global parameters:</span></b></small>") 48643#@gui : Recursion Depth = int(11,1,18) 48644#@gui : Random Seed = int(10000,0,65535) 48645#@gui : X-ratio = float(0,-1,1) 48646#@gui : Y-ratio = float(0,-1,1) 48647#@gui : note = note("<small><b><span color="#FF0055">Note:</span></b> Set <i>Random Seed</i> to <b>0</b> to make it \ 48648# random as well.</small>") 48649#@gui : sep = separator(), note = note("<small><b><span color="#EE5500">Trunk:</span></b></small>") 48650#@gui : Thickness (%) = float(15,0,100) 48651#@gui : Base Thickness (%) = float(150,0,300) 48652#@gui : Angle (deg.) = float(0,-90,90) 48653#@gui : sep = separator(), note = note("<small><b><span color="#EE5500">Recursion:</span></b></small>") 48654#@gui : Avg Branching = float(2.15,1,6) 48655#@gui : Std Branching = float(0.8,0,6) 48656#@gui : Avg Left Angle (deg.) = float(-40,-90,90) 48657#@gui : Avg Right Angle (deg.) = float(40,-90,90) 48658#@gui : Std Angle (deg.) = float(10,0,90) 48659#@gui : Avg Length Factor (%) = float(75,0,200) 48660#@gui : Std Length Factor (%) = float(0,0,200) 48661#@gui : Avg Thickness Factor (%) = float(70,0,200) 48662#@gui : Std Thickness Factor (%) = float(20,0,200) 48663#@gui : sep = separator(), note = note("<small><b><span color="#EE5500">Colors / Opacity:</span></b></small>") 48664#@gui : Trunk color = color(40,25,0,255) 48665#@gui : Trunk opacity (%) = float(100,0,100) 48666#@gui : Leaf color = color(70,140,60,255) 48667#@gui : Leaf opacity (%) = float(100,0,100) 48668#@gui : Color gamma = float(0.4,-2,2) 48669#@gui : Opacity gamma = float(0.4,-2,2) 48670#@gui : sep = separator() 48671#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/03/24</i>.</small>") 48672_fx_tree: 48673 recursion_depth,random_seed,xratio,yratio,\ 48674 trunk_thickness,base_thickness,trunk_angle,\ 48675 avg_branching,std_branching,avg_leftangle,avg_rightangle,std_angle,avg_length,std_length,avg_thickness,std_thickness,\ 48676 Rt,Gt,Bt,At,Ot,Rl,Gl,Bl,Al,Ol,gammaRGBA,gammaO=${1-28} 48677 48678 W,H,S={[w,h,min(w,h)]} l[] 48679 if $2 srand $2 fi 48680 48681 # Init trunk. 48682 1,1,1,9," 48683 const h_thickness = "$trunk_thickness"%/2; 48684 const hb_thickness = h_thickness*"$base_thickness"%; 48685 R = rot("$trunk_angle"°); 48686 C = [ 0.5,0 ]; 48687 P0 = C + R*[ -hb_thickness,0 ]; 48688 P1 = C + R*[ hb_thickness,0 ]; 48689 P2 = C + R*[ h_thickness,0.5 ]; 48690 P3 = C + R*[ -h_thickness,0.5 ]; 48691 [ P0,P1,P2,P3,0 ]" 48692 48693 # Compute tree geometry. 48694 repeat $recursion_depth 48695 1,8,1,9 48696 eval.. >${-math_lib}" 48697 const dangle = "$avg_rightangle" - "$avg_leftangle"; 48698 ref(I,val); 48699 ref(val[0,2],P0); 48700 ref(val[2,2],P1); 48701 ref(val[4,2],P2); 48702 ref(val[6,2],P3); 48703 ndepth = val[8] + 1; 48704 48705 # Median axis. 48706 A = (P0 + P1)/2; 48707 B = (P2 + P3)/2; 48708 AB = B - A; 48709 thickness = norm(B - P2); 48710 48711 N = round(cut("$avg_branching" + u(-1,1)*"$std_branching",1,6)); 48712 Nm1 = N<=1?1:N - 1; 48713 48714 repeat (N,n, 48715 ang = cut("$avg_leftangle" + dangle*n/Nm1 + u(-1,1)*"$std_angle",-90,90); 48716 len = cut("$avg_length" + u(-1,-1)*"$std_length",0,200); 48717 rot = rot(ang°); 48718 nB = B + len%*rot*AB; 48719 orth = (nB - B); 48720 orth/=norm(orth); 48721 orth = [ -orth[1],orth[0] ]; 48722 nthickness = thickness*("$avg_thickness" + u(-1,1)*"$std_thickness")%; 48723 Q0 = nB + nthickness*orth; 48724 Q1 = nB - nthickness*orth; 48725 dar_insert(#-1,[ P3,P2,Q1,Q0,ndepth ]); 48726 ); 48727 end(resize(#-1,1,dar_size(#-1),1,s#-1,0)); val" 48728 done 48729 a y 48730 48731 # Normalize coordinates to fit image size and aspect ratio. 48732 1,100%,1,4,"[ i0#-1,i2#-1,i4#-1,i6#-1 ]" 48733 1,100%,1,4,"[ i1#-2,i3#-2,i5#-2,i7#-2 ]" 48734 sx,sy={10^[$xratio,$yratio]} 48735 -.. 0.5 *.. {-2,$S*$sx/(2.1*max(abs(iM),abs(im)))} +.. {$W/2} *. {$S*$sy/(1.05*max(iM))} 48736 f... "round([ i0#-2,i0#-1,i1#-2,i1#-1,i2#-2,i2#-1,i3#-2,i3#-1,i8 ])" 48737 rm[-2,-1] 48738 48739 # Make sure trunk starts at bottom when rotated. 48740 eval "ref(I,T); P0 = T[0,2]; P1 = T[2,2]; P2 = T[4,2]; P3 = T[6,2]; 48741 I[0] = [ lerp(P0,P2,-2),lerp(P1,P2,-2),P2,P3,0 ]" 48742 48743 # Draw tree. 48744 $W,$H,1,4 48745 eval.. "> 48746 begin( 48747 RGBAt = [ "$Rt,$Gt,$Bt,$At" ]; 48748 RGBAl = [ "$Rl,$Gl,$Bl,$Al" ]; 48749 const gRGBA = 10^"$gammaRGBA"; 48750 const gO = 10^"$gammaO"; 48751 ); 48752 ref(I,val); 48753 t = val[8]/"$recursion_depth"; # Between [0,1] 48754 RGBA = lerp(RGBAt,RGBAl,t^gRGBA); 48755 O = lerp("$Ot,$Ol",t^gO)%; 48756 polygon(#-1,4,val[0,8],O,RGBA); 48757 (i0==i2 && i1==i3) || (i4==i6 && i5==i7)?polygon(#-1,2,i0,i1,i4,i5,O,RGBA); 48758 val" 48759 mirror xy 48760 rm.. 48761 endl 48762 48763fx_tree : 48764 _fx_tree. $* mv. 0 48765 if $_output_mode k[0] fi 48766 48767fx_tree_preview : 48768 repeat $! l[$>] _fx_tree $* blend alpha endl done 48769 48770#@gui Turbulence : fx_turbulence, fx_turbulence 48771#@gui : Radius = float(128,1,1024) 48772#@gui : Octaves = int(6,1,12) 48773#@gui : Damping per Octave = float(4,1,10) 48774#@gui : Difference Mixing = float(0,-10,10) 48775#@gui : Mode = choice("Turbulence","Turbulence 2","Fractal Noise","Fractured Clouds","Stardust","Pea Soup") 48776#@gui : sep = separator() 48777#@gui : note = note("<small>Author: <i>Preben Soeberg</i>. Latest Update: <i>2010/29/12</i>.</small>") 48778fx_turbulence : 48779 remove_opacity turbulence ${^0} 48780 48781 48782#@gui ____<b>Sequences</b> 48783#------------------------- 48784 48785# fx_animate_preview : _command,_parameters1,_parameters2,_compute_half={ 0 | 1 },_width>=0,_height>=0 48786# Generate a preview with start/end rendering of an animation. 48787fx_animate_preview : skip ${4=1},${5=0},${6=$5} 48788 repeat $! 48789 if $5 width=$5 else width={w} fi 48790 if $6 height=$6 else height={h} fi 48791 if $4 s. x,2 else . fi 48792 -$1.. $2 -$1. $3 # Assume this is a 1->1 filter. 48793 r[-2,-1] {max(w,{-2,w})},{max(h,{-2,h})},1,100%,3 48794 if !$4 columns.. 0,50% columns. 50%,100% fi 48795 a[-2,-1] x r. $width,$height,1,100%,2 drgba. 48796 line. 50%,0,50%,100%,1,0,0,0,255 48797 to. "Start",3,-1,13,2,1,255 to. "End",{w-24},{h-18},13,2,1,255 48798 mv. 0 done 48799 48800#@gui 3D Elevation [Animated] : fx_animate_elevation3d, fx_animate_elevation3d_preview(1) 48801#@gui : Frames = _int(10,2,100) 48802#@gui : Output as Frames = _bool(1) 48803#@gui : Output as Files = _bool(0) 48804#@gui : Output Folder = _folder() 48805#@gui : note = note{"\n<b>Global parameters :</b>"} 48806#@gui : Factor = float(100,-1000,1000) 48807#@gui : Smoothness = float(1,0,10) 48808#@gui : Width = _int(1024,8,4096) 48809#@gui : Height = _int(1024,8,4096) 48810#@gui : Rendering = choice(2,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 48811#@gui : note = note{"\n<b>Starting parameters :</b>"} 48812#@gui : Size = float(0.8,0,3) 48813#@gui : X-Angle = float(35,0,360) 48814#@gui : Y-Angle = float(0,0,360) 48815#@gui : Z-Angle = float(0,0,360) 48816#@gui : FOV = float(45,1,90) 48817#@gui : X-Light = float(0,-100,100) 48818#@gui : Y-Light = float(0,-100,100) 48819#@gui : Z-Light = float(-100,-100,0) 48820#@gui : Specular Lightness = float(0.5,0,1) 48821#@gui : Specular Shininess = float(0.7,0,3) 48822#@gui : note = note{"\n<b>Ending parameters :</b>"} 48823#@gui : Size = float(0.8,0,3) 48824#@gui : X-Angle = float(35,0,1440) 48825#@gui : Y-Angle = float(0,0,1440) 48826#@gui : Z-Angle = float(360,0,1440) 48827#@gui : FOV = float(45,1,90) 48828#@gui : X-Light = float(0,-100,100) 48829#@gui : Y-Light = float(0,-100,100) 48830#@gui : Z-Light = float(-100,-100,0) 48831#@gui : Specular Lightness = float(0.5,0,1) 48832#@gui : Specular Shininess = float(0.7,0,3) 48833#@gui : sep = separator() 48834#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48835fx_animate_elevation3d : skip "${4=}" 48836 if $3 filename="$4/gmic_elevation3d.png" else filename="" fi 48837 _fx_elevation3d ${5-6} 48838 animate fx_render3d,"${7-8},${10-19},$9",\ 48839 "${7-8},${20-29},$9",$1,$2,{``$filename} 48840 48841fx_animate_elevation3d_preview : skip "${4=}" 48842 w={w} h={h} 48843 _fx_elevation3d ${5-6} 48844 fx_animate_preview fx_render3d,$w","$h",${10-19},$9",\ 48845 $w","$h",${20-29},$9",0,$w,$h 48846 48847#@gui 3D Extrusion [Animated] : fx_animate_extrude3d, fx_animate_extrude3d_preview(1) 48848#@gui : Frames = _int(10,2,100) 48849#@gui : Output as Frames = _bool(1) 48850#@gui : Output as Files = _bool(0) 48851#@gui : Output Folder = _folder() 48852#@gui : note = note{"\n<b>Global parameters :</b>"} 48853#@gui : Depth = float(10,1,256) 48854#@gui : Resolution = int(512,1,1024) 48855#@gui : Smoothness = float(0.6,0,3) 48856#@gui : Width = _int(1024,8,4096) 48857#@gui : Height = _int(1024,8,4096) 48858#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 48859#@gui : note = note{"\n<b>Starting parameters :</b>"} 48860#@gui : Size = float(0.8,0,3) 48861#@gui : X-Angle = float(35,0,360) 48862#@gui : Y-Angle = float(0,0,360) 48863#@gui : Z-Angle = float(0,0,360) 48864#@gui : FOV = float(45,1,90) 48865#@gui : X-Light = float(0,-100,100) 48866#@gui : Y-Light = float(0,-100,100) 48867#@gui : Z-Light = float(-100,-100,0) 48868#@gui : Specular Lightness = float(0.5,0,1) 48869#@gui : Specular Shininess = float(0.7,0,3) 48870#@gui : note = note{"\n<b>Ending parameters :</b>"} 48871#@gui : Size = float(0.8,0,3) 48872#@gui : X-Angle = float(35,0,1440) 48873#@gui : Y-Angle = float(360,0,1440) 48874#@gui : Z-Angle = float(0,0,1440) 48875#@gui : FOV = float(45,1,90) 48876#@gui : X-Light = float(0,-100,100) 48877#@gui : Y-Light = float(0,-100,100) 48878#@gui : Z-Light = float(-100,-100,0) 48879#@gui : Specular Lightness = float(0.5,0,1) 48880#@gui : Specular Shininess = float(0.7,0,3) 48881#@gui : sep = separator() 48882#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48883fx_animate_extrude3d : skip "${4=}" 48884 if $3 filename="$4/gmic_extrude3d.png" else filename="" fi 48885 _fx_extrude3d ${5-7} 48886 animate fx_render3d,"${8-9},${11-20},$10",\ 48887 "${8-9},${21-30},$10",$1,$2,{``$filename} 48888 48889fx_animate_extrude3d_preview : skip "${4=}" 48890 w={w} h={h} 48891 _fx_extrude3d ${5-7} 48892 fx_animate_preview fx_render3d,$w","$h",${11-20},$10",\ 48893 $w","$h",${21-30},$10",0,$w,$h 48894 48895#@gui 3D Image Object [Animated] : fx_animate_imageobject3d, fx_animate_imageobject3d_preview(1) 48896#@gui : Frames = _int(10,2,100) 48897#@gui : Output as Frames = _bool(1) 48898#@gui : Output as Files = _bool(0) 48899#@gui : Output Folder = _folder() 48900#@gui : note = note{"\n<b>Global parameters :</b>"} 48901#@gui : Type = choice{1,"Plane","Cube","Pyramid","Sphere","Torus","Gyroid","Weird","Cup","Rubik"} 48902#@gui : Width = _int(1024,1,4096) 48903#@gui : Height = _int(1024,1,4096) 48904#@gui : Rendering = choice(4,"Dots","Wireframe","Flat","Flat-Shaded","Gouraud","Phong") 48905#@gui : note = note{"\n<b>Starting parameters :</b>"} 48906#@gui : Size = float(0.5,0,3) 48907#@gui : X-Angle = float(57,0,360) 48908#@gui : Y-Angle = float(41,0,360) 48909#@gui : Z-Angle = float(21,0,360) 48910#@gui : FOV = float(45,1,90) 48911#@gui : X-Light = float(0,-100,100) 48912#@gui : Y-Light = float(0,-100,100) 48913#@gui : Z-Light = float(-100,-100,0) 48914#@gui : Specular Lightness = float(0.5,0,1) 48915#@gui : Specular Shininess = float(0.7,0,3) 48916#@gui : note = note{"\n<b>Ending parameters :</b>"} 48917#@gui : Size = float(0.5,0,3) 48918#@gui : X-Angle = float(57,0,1440) 48919#@gui : Y-Angle = float(401,0,1440) 48920#@gui : Z-Angle = float(21,0,1440) 48921#@gui : FOV = float(45,1,90) 48922#@gui : X-Light = float(0,-100,100) 48923#@gui : Y-Light = float(0,-100,100) 48924#@gui : Z-Light = float(-100,-100,0) 48925#@gui : Specular Lightness = float(0.5,0,1) 48926#@gui : Specular Shininess = float(0.7,0,3) 48927#@gui : sep = separator() 48928#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 48929fx_animate_imageobject3d : skip "${4=}" 48930 if $3 filename="$4/gmic_imageobject3d.png" else filename="" fi 48931 _fx_imageobject3d "_",$5 48932 animate fx_render3d,"${6-7},${9-18},$8",\ 48933 "${6-7},${19-28},$8",$1,$2,{``$filename} 48934 48935fx_animate_imageobject3d_preview : skip "${4=}" 48936 w={w} h={h} 48937 _fx_imageobject3d "_preview_",$5 48938 fx_animate_preview fx_render3d,$w","$h",${9-18},$8",\ 48939 $w","$h",${19-28},$8",0,$w,$h 48940 48941#@gui 3D Text Pointcloud : fx_text_pointcloud3d, fx_text_pointcloud3d_preview 48942#@gui : Frames = _int(64,1,256) 48943#@gui : 1st Text = text("G'MIC") 48944#@gui : 2nd Text = text("Rocks!") 48945#@gui : Smoothness = float(1,0,5) 48946#@gui : Color = color(200,220,255) 48947#@gui : Background = color(255,255,255,255) 48948#@gui : X-Shadow= float(2,0,10) 48949#@gui : Y-Shadow= float(2,0,10) 48950#@gui : Shadow Smoothness = float(1,0,5) 48951#@gui : Stationary Frames = _int(19,1,32) 48952#@gui : sep = separator() 48953#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/01/09</i>.</small>") 48954fx_text_pointcloud3d : 48955 W={w} H={h} M={round(1.5*max(w,h))} rm 48956 text_pointcloud3d "$2","$3",$4 48957 col3d. ${5-7} *3d. {0.7*$M} 48958 f3d 4000 db3d 0 m3d 48959 repeat $1 48960 rprogress {60*$>/$1} 48961 angle={$>*360/$1} 48962 +r3d[0] 1,0,1,$angle 48963 $M,$M,1,3,-1 j3d. ..,50%,50%,0,1 rm.. 48964 done 48965 rm[0] a z autocrop -1 to_rgba s z replace_color 0,0,-1,-1,-1,255,0,0,0,0 48966 if $11 N=$! repeat $! l[$>] rprogress {60+40*$>/$N} 48967 i[0] 100%,100%,1,4 fc[0] ${8-11} +channels. 3,3 +negate. b[-2,-1] $14% to_rgba. 48968 j[0] .,$12%,$13%,0,0,1,..,255 rm[-2,-1] blend alpha 48969 endl done fi 48970 if $W>$H r2dx $W else r2dy $H fi 48971 if $15>1 48972 i[{int($1/2)}] [{int($1/2)}]x{$15-1} 48973 i[0] [0]x{$15-1} 48974 fi 48975 48976fx_text_pointcloud3d_preview : 48977 fx_text_pointcloud3d 4,"$2","$3",$4,${5-7},${8-11},${12-14},1 drgba 48978 frame 1,1,0 append_tiles 2,2 48979 48980#@gui 3D Tiles : fx_transition3d, fx_transition3d_preview(0) 48981#@gui : Inter-Frames = _int(10,3,100) 48982#@gui : X-Tiles = int(8,1,64) 48983#@gui : Y-Tiles = int(8,1,64) 48984#@gui : X-Rotation = text("1") 48985#@gui : Y-Rotation = text("1") 48986#@gui : Z-Rotation = text("0") 48987#@gui : Focale = float(800,100,2000) 48988#@gui : Enable Antialiasing = bool(1) 48989#@gui : sep = separator() 48990#@gui : note = note{"<small><b>Note:</b> 48991#@gui : This filter needs two layers to work properly. Set the <i>Input layers</i> option to handle 48992#@gui : multiple input layers. 48993#@gui : </small>"} 48994#@gui : sep = separator() 48995#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2012/13/08</i>.</small>") 48996fx_transition3d : 48997 f3d $7 48998 transition3d $1,$2,$3,"$4","$5","$6",$8 48999 49000fx_transition3d_preview : 49001 if $!==1 gui_warning_preview "Missing input layer" return fi 49002 f3d $7 49003 k[0,1] transition3d 4,$2,$3,"$4","$5","$6",$8 49004 k[1,2] 49005 r[0] 50%,100%,1,100%,0 49006 r[1] 50%,100%,1,100%,0,0,1 49007 a x 49008 line 50%,0,50%,100%,1,0,0,0,255 49009 49010#@gui B&W Pencil [Animated] : fx_animate_pencilbw, fx_animate_pencilbw_preview(0) 49011#@gui : Frames = _int(10,2,100) 49012#@gui : Output Frames = _bool(1) 49013#@gui : Output Files = _bool(0) 49014#@gui : Output Folder = _folder() 49015#@gui : note = note{"\n<b>Starting Parameters :</b>"} 49016#@gui : Pencil Type = float(2.3,0,5) 49017#@gui : Amplitude = float(100,0,200) 49018#@gui : note = note{"\n<b>Ending Parameters :</b>"} 49019#@gui : Pencil Type = float(0.3,0,5) 49020#@gui : Amplitude = float(60,0,200) 49021#@gui : sep = separator() 49022#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49023fx_animate_pencilbw : skip "${4=}" 49024 if $3 filename="$4/gmic_pencilbw.png" else filename="" fi 49025 animate pencilbw,"${5-6}",\ 49026 "${7-8}",$1,$2,{``$filename} 49027 49028fx_animate_pencilbw_preview : skip "${4=}" 49029 fx_animate_preview pencilbw,"${5-6}",\ 49030 "${7-8}" 49031 49032#@gui B&W Stencil [Animated] : fx_animate_stencilbw, fx_animate_stencilbw_preview(1) 49033#@gui : Frames = _int(10,2,100) 49034#@gui : Output Frames = _bool(1) 49035#@gui : Output Files = _bool(0) 49036#@gui : Output Folder = _folder() 49037#@gui : note = note{"\n<b>Starting Parameters :</b>"} 49038#@gui : Edge Threshold = float(10,0,30) 49039#@gui : Smoothness = float(10,0,30) 49040#@gui : note = note{"\n<b>Ending Parameters :</b>"} 49041#@gui : Edge Threshold = float(10,0,30) 49042#@gui : Smoothness = float(20,0,30) 49043#@gui : sep = separator() 49044#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49045fx_animate_stencilbw : skip "${4=}" 49046 if $3 filename="$4/gmic_stencilbw.png" else filename="" fi 49047 animate stencilbw,"${5-6}",\ 49048 "${7-8}",$1,$2,{``$filename} 49049 49050fx_animate_stencilbw_preview : skip "${4=}" 49051 fx_animate_preview stencilbw,"${5-6}",\ 49052 "${7-8}" 49053 49054#@gui Cartoon [Animated] : fx_animate_cartoon, fx_animate_cartoon_preview(0) 49055#@gui : Frames = _int(10,2,100) 49056#@gui : Output Frames = _bool(1) 49057#@gui : Output Files = _bool(0) 49058#@gui : Output Folder = _folder() 49059#@gui : note = note{"\n<b>Global Parameters :</b>"} 49060#@gui : Color Quantization = int(4,2,256) 49061#@gui : note = note{"\n<b>Starting parameters :</b>"} 49062#@gui : Smoothness = float(0.5,0,2) 49063#@gui : Sharpening = float(200,0,400) 49064#@gui : Edge Threshold = float(10,1,30) 49065#@gui : Edge Thickness = float(0.1,0,1) 49066#@gui : Color Strength = float(1.5,0,3) 49067#@gui : note = note{"\n<b>Ending parameters :</b>"} 49068#@gui : Smoothness = float(3,0,2) 49069#@gui : Sharpening = float(200,0,400) 49070#@gui : Edge Threshold = float(10,1,30) 49071#@gui : Edge Thickness = float(0.1,0,1) 49072#@gui : Color Strength = float(1.5,0,3) 49073#@gui : sep = separator() 49074#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49075fx_animate_cartoon : skip "${4=}" 49076 if $3 filename="$4/gmic_cartoon.png" else filename="" fi 49077 animate cartoon,"${6-10},$5",\ 49078 "${11-15},$5",$1,$2,{``$filename} 49079 49080fx_animate_cartoon_preview : skip "${4=}" 49081 fx_animate_preview cartoon,"${6-10},$5",\ 49082 "${11-15},$5" 49083 49084#@gui Edges [Animated] : fx_animate_edges, fx_animate_edges_preview(0) 49085#@gui : Frames = _int(10,2,100) 49086#@gui : Output Frames = _bool(1) 49087#@gui : Output Files = _bool(0) 49088#@gui : Output Folder = _folder() 49089#@gui : note = note{"\n<b>Global Parameters :</b>"} 49090#@gui : Negative Colors = bool(0) 49091#@gui : note = note{"\n<b>Starting Parameters :</b>"} 49092#@gui : Smoothness = float(0,0,10) 49093#@gui : Edge Threshold = float(10,0,30) 49094#@gui : note = note{"\n<b>Ending Parameters :</b>"} 49095#@gui : Smoothness = float(0,0,10) 49096#@gui : Edge Threshold = float(30,0,30) 49097#@gui : sep = separator() 49098#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49099fx_animate_edges : skip "${4=}" 49100 if $3 filename="$4/gmic_edges.png" else filename="" fi 49101 animate fx_edges,"${6-7},$5",\ 49102 "${8-9},$5",$1,$2,{``$filename} 49103 49104fx_animate_edges_preview : skip "${4=}" 49105 fx_animate_preview fx_edges,"${6-7},$5",\ 49106 "${8-9},$5" 49107 49108#@gui Edges on Fire : fx_fire_edges, fx_fire_edges_preview(0) 49109#@gui : Edges = float(0.7,0,3) 49110#@gui : Attenuation = float(0.25,0,1) 49111#@gui : Smoothness = float(0.5,0,5) 49112#@gui : Threshold = float(25,0,100) 49113#@gui : sep = separator() 49114#@gui : Number of Frames = _int(20,1,999) 49115#@gui : Starting Frame = int(20,0,199) 49116#@gui : Frame Skip = _int(0,0,20) 49117#@gui : sep = separator() 49118#@gui : Preview Type = choice("Full","Forward Horizontal","Forward Vertical","Backward Horizontal", 49119#@gui : "Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom","Duplicate Right", 49120#@gui : "Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse") 49121#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 49122#@gui : sep = separator() 49123#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/06/07</i>.</small>") 49124fx_fire_edges : 49125 fire_edges ${1-7} rv 49126 49127fx_fire_edges_preview : 49128 gui_split_preview "fire_edges $1,$2,$3,$4,1,$6,0",${-3--1} 49129 49130#@gui Lava Lamp : fx_lavalampbw, fx_lavalampbw_preview(0) 49131#@gui : Number of Key-Frames = _int(3,2,50) 49132#@gui : Number of Inter-Frames = _int(30,2,100) 49133#@gui : Smooth Looping = _bool(1) 49134#@gui : sep = separator() 49135#@gui : Resolution = float(20,1,100) 49136#@gui : Size = float(2,0,30) 49137#@gui : Smoothness = _float(0.01,0,1) 49138#@gui : Transparent Background = bool(0) 49139#@gui : sep = separator() 49140#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/06/07</i>.</small>") 49141fx_lavalampbw : 49142 if !$! (255;100^64;16^128;0) r. 512,512,1,3,3 fi 49143 repeat $! l[$<] remove_opacity 49144 w={w} h={h} 49145 +r $4%,$4%,1,1,0 [-1]x{$1-1} rand[^0] 0,1 stencil[^0] $5,0 49146 if $3 [1] fi 49147 morph[^0] $2,$6,0 49148 stencil[^0] $5,0 49149 r[^0] $w,$h,1,1,3 b[^0] 10 >=[^0] 50% *[^0] 255 49150 r[^0] 100%,100%,1,4 j[^0] [0] rm[0] 49151 if $3 rm. fi 49152 endl done 49153 if !$7 repeat $! l[$>] split_opacity n. 0,1 *[^-1] . rm. endl done fi 49154 49155fx_lavalampbw_preview : 49156 fx_lavalampbw 2,2,1,$4,$5,$6,$7 k[0] 49157 49158#@gui Lissajous [Animated] : fx_animate_lissajous, fx_animate_lissajous_preview(1) 49159#@gui : Frames = _int(10,2,100) 49160#@gui : Output as Frames = _bool(1) 49161#@gui : Output as Files = _bool(0) 49162#@gui : Output Folder = _folder() 49163#@gui : sep = separator() 49164#@gui : note = note{"<b>Starting parameters :</b>"} 49165#@gui : Resolution = int(4096,2,8192) 49166#@gui : X-Size = float(0.9,0,2) 49167#@gui : Y-Size = float(0.9,0,2) 49168#@gui : Z-Size = float(3,1,10) 49169#@gui : X-Multiplier = float(8,0,32) 49170#@gui : Y-Multiplier = float(7,0,32) 49171#@gui : Z-Multiplier = float(0,0,32) 49172#@gui : X-Offset = float(0,0,1) 49173#@gui : Y-Offset = float(0,0,1) 49174#@gui : Z-Offset = float(0,0,1) 49175#@gui : X-Angle = float(0,0,360) 49176#@gui : Y-Angle = float(0,0,360) 49177#@gui : Z-Angle = float(0,0,360) 49178#@gui : Thickness = float(0,0,50) 49179#@gui : Color = color(255,255,255,255) 49180#@gui : sep = separator() 49181#@gui : note = note{"<b>Ending parameters :</b>"} 49182#@gui : Resolution = int(4096,2,8192) 49183#@gui : X-Size = float(0.9,0,2) 49184#@gui : Y-Size = float(0.9,0,2) 49185#@gui : Z-Size = float(3,1,10) 49186#@gui : X-Multiplier = float(8,0,32) 49187#@gui : Y-Multiplier = float(7,0,32) 49188#@gui : Z-Multiplier = float(0,0,32) 49189#@gui : X-Offset = float(0,0,1) 49190#@gui : Y-Offset = float(0,0,1) 49191#@gui : Z-Offset = float(0,0,1) 49192#@gui : X-Angle = float(0,0,360) 49193#@gui : Y-Angle = float(0,0,360) 49194#@gui : Z-Angle = float(0,0,360) 49195#@gui : Thickness = float(0,0,50) 49196#@gui : Color = color(255,255,255,255) 49197#@gui : sep = separator() 49198#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/18/04</i>.</small>") 49199fx_animate_lissajous : skip "${4=}" 49200 if $3 filename="$4/gmic_lissajous.png" else filename="" fi 49201 animate fx_lissajous,"${5-22}",\ 49202 "${23-40}",$1,$2,{``$filename} 49203 49204fx_animate_lissajous_preview : skip "${4=}" 49205 fx_animate_preview fx_lissajous,"${5-22}",\ 49206 "${23-40}",0 49207 49208#@gui Moiré Animation : fx_moire, fx_moire_preview(1)+ : * 49209#@gui : Stripe orientation = choice(1,"Horizontal","Vertical") 49210#@gui : Input Transparency = choice("Replace With White","Reconstruct From Previous Frames") 49211#@gui : Output Format = choice{2,"Same as Input","A4 / 75 PPI","A4 / 100 PPI (Recommended)", 49212#@gui : "A4 / 150 PPI","A4 / 300 PPI"} 49213#@gui : Auto-Reduce Number of Frames = bool(1) 49214#@gui : Landscape = bool(1) 49215#@gui : Margin (%) = float(2,0,30) 49216#@gui : sep = separator() 49217#@gui : Print Frame Numbers = choice(1,"Disable","Top Left","Top Right","Bottom Left","Bottom Right") 49218#@gui : Size of Frame Numbers (%) = float(5,0,30) 49219#@gui : sep = separator() 49220#@gui : note = note{"<small><b><span color="#EE5500">Instructions:</span></b>\n\n 49221#@gui : This filter renders Moire Animations, as shown on 49222#@gui : <a href="https://www.youtube.com/watch?v=f5plDb_JRq4">this video</a>.\n 49223#@gui : To make the animation visible:\n\n 49224#@gui : • Before running the filter, ensure that all frames are aligned and have the same size 49225#@gui : (and preferably without alpha)!\n 49226#@gui : • Run the filter. It is recommended to keep the number of frames <=6.\n 49227#@gui : • Print the first layer (merged frames) on a A4 blank paper, at 300 PPI.\n 49228#@gui : • Print the second layer (mask) on a A4 transparent sheet, at 300 PPI.\n 49229#@gui : • Drag the transparent layer over the A4 paper to render the animation effect. 49230#@gui : "} 49231#@gui : sep = separator() 49232#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/03/02</i>.</small>") 49233fx_moire : 49234 if 0$_is_preview" && "!narg($_preview_width) _preview_width,_preview_height=512 fi 49235 49236 # Reconstruct frames from base image. 49237 if $2 repeat $! if $>" && "{$<,s==2||s==4} blend[$<] [{$<+1}],alpha,1,1 fi done fi 49238 49239 # Auto-reduce number of frames (4, 5 or 6). 49240 if $4 49241 skip={" 49242 l<=6?1:( 49243 const l5 = int(l/5); 49244 const l4 = int(l/4); 49245 const l6 = int(l/6); 49246 5*l5==l?l5: 49247 6*l6==l?l6: 49248 4*l4==l?l4:( 49249 const r6 = abs(6*l6 - l); 49250 const r5 = abs(5*l5 - l); 49251 const r4 = abs(4*l4 - l); 49252 r5<=r4 && r5<=r6?l5: 49253 r6<=r4 && r6<=r5?l6: 49254 l4 49255 ) 49256 )"} 49257 k[^:$skip] 49258 if $!>6 rm[6--1] fi 49259 fi 49260 N=$! 49261 49262 # Blend with white background. 49263 repeat $! l[$>] if s==2||s==4 drgba 255 fi endl done 49264 49265 # Constrain size of frames. 49266 if 0$_is_preview 49267 W,H=$_preview_width,$_preview_height 49268 if $3 49269 if $W>$H W={$H/sqrt(2)} else H={$W*sqrt(2)} fi 49270 fW,fH=$W,$H 49271 W,H/={arg($3,4,3,2,1)} 49272 fi 49273 elif $3 49274 W,H,fW,fH={"$3==1?[620,877]:$3==2?[827,1169]:$3==3?[1240,1754]:[2480,3508]"},2480,3508 49275 W,H,fW,fH={round([$W,$H,$fW,$fH]*0.95)} # Take printer margins into account 49276 else 49277 W,H=${-max_wh} 49278 fi 49279 49280 if $3" && "$5 # Landscape mode 49281 W,H=$H,$W fW,fH=$fH,$fW 49282 fi 49283 if !narg($fW) fW,fH=$W,$H fi 49284 repeat $! l[$>] if [w,h]!=[$W,$H] 49285 - 255 49286 rr2d {(100-$6)%*[$W,$H]},2,2 49287 r $W,$H,1,100%,0,0,0.5,0.5 49288 + 255 49289 fi endl done 49290 49291 # Generate merged image and mask. 49292 if $1 # Vertical stripes 49293 100%,100%,1,100%,"i(#x%"$N",x,y,z,c)" rm[^-1] 49294 100%,100%,1,1,"x%"$N"?0:255" 49295 else # Horizontal stripes 49296 100%,100%,1,100%,"i(#y%"$N",x,y,z,c)" rm[^-1] 49297 100%,100%,1,1,"y%"$N"?0:255" 49298 fi 49299 49300 # Upscale with nearest-neighbor for printing. 49301 if $3 49302 ir={round(max($fW/$W,$fH/$H))*100} 49303 r $ir%,$ir%,1,100%,1 49304 r $fW,$fH,1,100%,0,1,0.5,0.5 49305 fi 49306 49307 # Insert frame number label. 49308 if $7" && "$8 49309 ax,ay={a=$7-1;[a%2?0.95:0.05,int(a/2)?0.95:0.05]} 49310 0 t. "#"$N,0,0,{0,h*$8%},1,255 autocrop. frame. 5%,15%,0 negate. to_rgb. j[^-1] .,$ax~,$ay~ rm. 49311 fi 49312 nm "name(Merged Frames),pos(0,0),opacity(100),mode(alpha)","name(Mask),pos(0,0),opacity(100),mode(alpha)" 49313 u $N 49314 49315fx_moire_preview : 49316 _is_preview=1 49317 fx_moire $* 49318 49319#@gui Rodilius [Animated] : fx_animate_rodilius, fx_animate_rodilius_preview(1) 49320#@gui : Frames = _int(10,2,100) 49321#@gui : Output as Frames = _bool(1) 49322#@gui : Output as Files = _bool(0) 49323#@gui : Output Folder = _folder() 49324#@gui : Color Mode = choice(1,"Darker","Lighter") 49325#@gui : note = note{"\n<b>Starting Parameters :</b>"} 49326#@gui : Amplitude = float(10,0,30) 49327#@gui : Thickness = float(10,0,100) 49328#@gui : Sharpness = float(300,0,1000) 49329#@gui : Orientations = int(5,2,20) 49330#@gui : Offset = float(0,0,180) 49331#@gui : note = note{"\n<b>Ending Parameters :</b>"} 49332#@gui : Amplitude = float(10,0,30) 49333#@gui : Thickness = float(10,0,100) 49334#@gui : Sharpness = float(300,0,1000) 49335#@gui : Orientations = int(5,2,20) 49336#@gui : Offset = float(180,0,180) 49337#@gui : sep = separator() 49338#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49339fx_animate_rodilius : skip "${4=}" 49340 if $3 filename="$4/gmic_rodilius.png" else filename="" fi 49341 animate rodilius,"${6-10},$5",\ 49342 "${11-15},$5",$1,$2,{``$filename} 49343 49344fx_animate_rodilius_preview : skip "${4=}" 49345 fx_animate_preview rodilius,"${6-10},$5",\ 49346 "${11-15},$5" 49347 49348#@gui Soft Glow [Animated] : fx_animate_glow, fx_animate_glow_preview(1) 49349#@gui : Frames = _int(10,2,100) 49350#@gui : Output as Frames = _bool(1) 49351#@gui : Output as Files = _bool(0) 49352#@gui : Output Folder = _folder() 49353#@gui : note = note{"\n<b>Starting Parameters :</b>"} 49354#@gui : Amplitude = float(0,0,8) 49355#@gui : note = note{"\n<b>Ending Parameters :</b>"} 49356#@gui : Amplitude = float(3,0,8) 49357#@gui : sep = separator() 49358#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49359fx_animate_glow : skip "${4=}" 49360 if $3 filename="$4/gmic_glow.png" else filename="" fi 49361 animate glow,"$5",\ 49362 "$6",$1,$2,{``$filename} 49363 49364fx_animate_glow_preview : skip "${4=}" 49365 fx_animate_preview glow,"$5",\ 49366 "$6" 49367 49368#@gui Spatial Transition : fx_spatial_transition, fx_spatial_transition_preview(1) 49369#@gui : Number of Added Frames = _int(10,1,256) 49370#@gui : Shading (%) = float(0,0,100) 49371#@gui : Transition Shape = choice(7,"Bottom Layer","Top Layer","Custom Formula","Horizontal","Vertical", 49372#@gui : "Angular","Radial","Plasma") 49373#@gui : Custom Formula = text{"cos(x*y/(16+32*A))"}_1 49374#@gui : A-Value = float(0,0,1) 49375#@gui : sep = separator() 49376#@gui : Preview Type = choice(1,"Transition Map","Timed Image","Sequence x4","Sequence x6","Sequence x8") 49377#@gui : Preview Time = float(0.5,0,1) 49378#@gui : Preview = value(0) 49379#@gui : sep = separator() 49380#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/10/04</i>.</small>") 49381fx_spatial_transition : 49382 to_rgba r ${-max_wh},1,100%,0,0,0.5,0.5 49383 shape=-1 formula= 49384 if $3==0 # Do nothing. 49385 elif $3==1 shape=0 49386 elif $3==2 formula="$4" 49387 elif $3==3 formula="sin(x*0.5*pi/w*(1+100*A))" 49388 elif $3==4 formula="sin(y*0.5*pi/h*(1+100*A))" 49389 elif $3==5 formula="atan2(y-h/2,x-w/2)%((1-A)*2*pi+0.001)" 49390 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))" 49391 elif $3==7 100%,100% plasma. 1,1,{8/(1+$5)} equalize. 1024 49392 fi 49393 if narg($formula) 49394 {w},{h},1,1,"A=$5;"$formula fi 49395 if $-1 # Preview mode. 49396 if $6==0 k[$shape] norm n 0,255 49397 elif $6==1" && "$7==0 rm[$shape] rm. 49398 elif $6==1" && "$7==1 rm[$shape] rm[0] 49399 elif $6==1 49400 transition[^$shape] [$shape],$1,$2,$7*($1-1) rm[$shape] rm[0--1:2] 49401 else 49402 transition[^$shape] [$shape],{$6*2},$2 rm[$shape] to_rgba 49403 fi 49404 if $!>1 to_rgba frame 2%,2%,0,0,0,0 append_tiles , fi 49405 else # Apply mode. 49406 transition[^$shape] [$shape],$1,$2 49407 rm. 49408 fi 49409 nm name(transition),pos(0,0) 49410 if narg($formula) u "{$1}{$2}{$3}{"$formula"}_"{$3==2?2:1}"{$5}{$6}{$7}{0}" fi 49411 49412fx_spatial_transition_preview : 49413 if ($3<=1" && "$!<3)" || "($3>1" && "$!<2) 49414 gui_print_preview "Warning:",,"This filter requires more input layers to work properly." 49415 return 49416 fi 49417 fx_spatial_transition ${1-3},"$4",${5-7},1 49418 49419 49420#@gui ____<b>Silhouettes</b> 49421#--------------------------- 49422 49423#@gui <i>Misc</i> 49424 49425#@gui Cupid : fx_cupid, fx_cupid_preview 49426#@gui : Size (%) = float(75,0,100) 49427#@gui : Smoothness = float(0,0,10) 49428#@gui : Color = color(255,255,255,255) 49429#@gui : Antialiasing = bool(1) 49430#@gui : sep = separator() 49431#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/08</i>.</small>") 49432fx_cupid : 49433 max_wh={$!>0?[${-max_wh}]:[512,512]} 49434 w,h={S=[$max_wh]*$1%;[max(S[0],1),max(S[1],1)]} 49435 l[] 49436 shape_cupid {($7?2:1)*min($w,$h)} 49437 if $7 r2dx 50% fi 49438 frame {2.5*$2}%,{2.5*$2}%,0 b $2% * $6 round c 0,255 autocrop 49439 100%,100%,1,3 fc. ${3-5} rv[-2,-1] a c 49440 gui_set_layer_name "Heart" 49441 gui_set_layer_pos {0.5*([$max_wh]-[w,h])} 49442 endl 49443 mv. 0 49444 49445fx_cupid_preview : 49446 fx_cupid $* blend[^0] [0],alpha rm[0] 49447 49448#@gui Gear : fx_gear, fx_gear_preview 49449#@gui : Size (%) = float(75,0,100) 49450#@gui : Number of Teeth = int(12,1,96) 49451#@gui : Elevation (%) = float(15,0,100) 49452#@gui : Angle (%) = float(0,0,100) 49453#@gui : Inner Radius (%) = float(40,0,100) 49454#@gui : Smoothness = float(0,0,10) 49455#@gui : Color = color(255,255,255,255) 49456#@gui : Antialiasing = bool(1) 49457#@gui : sep = separator() 49458#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/08</i>.</small>") 49459fx_gear : 49460 max_wh={$!>0?[${-max_wh}]:[512,512]} 49461 w,h={S=[$max_wh]*$1%;[max(S[0],1),max(S[1],1)]} 49462 l[] 49463 shape_gear {($11?2:1)*min($w,$h)},${2-5} 49464 if $11 r2dx 50% fi 49465 frame {2.5*$6}%,{2.5*$6}%,0 b $6% * $10 round c 0,255 autocrop 49466 100%,100%,1,3 fc. ${7-9} rv[-2,-1] a c 49467 gui_set_layer_name "Gear" 49468 gui_set_layer_pos {0.5*([$max_wh]-[w,h])} 49469 endl 49470 mv. 0 49471 49472fx_gear_preview : 49473 fx_gear $* blend[^0] [0],alpha rm[0] 49474 49475#@gui Heart : fx_heart, fx_heart_preview 49476#@gui : Size (%) = float(75,0,100) 49477#@gui : Smoothness = float(0,0,10) 49478#@gui : Color = color(255,255,255,255) 49479#@gui : Antialiasing = bool(1) 49480#@gui : sep = separator() 49481#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2018/01/08</i>.</small>") 49482fx_heart : 49483 max_wh={$!>0?[${-max_wh}]:[512,512]} 49484 w,h={S=[$max_wh]*$1%;[max(S[0],1),max(S[1],1)]} 49485 l[] 49486 shape_heart {($7?2:1)*min($w,$h)} 49487 if $7 r2dx 50% fi 49488 frame {2.5*$2}%,{2.5*$2}%,0 b $2% * $6 round c 0,255 autocrop 49489 100%,100%,1,3 fc. ${3-5} rv[-2,-1] a c 49490 gui_set_layer_name "Heart" 49491 gui_set_layer_pos {0.5*([$max_wh]-[w,h])} 49492 endl 49493 mv. 0 49494 49495fx_heart_preview : 49496 fx_heart $* blend[^0] [0],alpha rm[0] 49497 49498#@gui Sierpinski Triangle : fx_sierpinski, fx_sierpinski(1) 49499#@gui : Recursions = int(6,0,10) 49500#@gui : 1st X-Coord = float(50,0,100) 49501#@gui : 1st Y-Coord = float(0,0,100) 49502#@gui : 2nd X-Coord = float(0,0,100) 49503#@gui : 2nd Y-Coord = float(100,0,100) 49504#@gui : 3rd X-Coord = float(100,0,100) 49505#@gui : 3rd Y-Coord = float(100,0,100) 49506#@gui : Color = color(255,255,255) 49507#@gui : Opacity = float(1,0,1) 49508#@gui : sep = separator() 49509#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49510fx_sierpinski : 49511 repeat $! l[$>] split_opacity l[0] 49512 100%,100% sierpinski. ${1-7} 49513 +fc.. $8,$9,$10 j[0] .,0,0,0,0,$11,..,255 rm[-2,-1] 49514 endl a c endl done 49515 49516#@gui _<i>Nature</i> 49517 49518#@gui Barnsley Fern : fx_barnsley_fern, fx_barnsley_fern_preview(1) 49519#@gui : Type = choice("Asplenium Adiantum-Nigrum","Thelypteridaceae") 49520#@gui : Density (%) = float(100,0,300) 49521#@gui : Angle = float(30,-180,180) 49522#@gui : Opacity (%) = float(40,0,100) 49523#@gui : Color = color(10,178,0,255) 49524#@gui : Add as a New Layer = _bool(1) 49525#@gui : sep = separator() 49526#@gui : note = note("This filter renders the Barnsley fern fractal, described here:") 49527#@gui : url = link("https://en.wikipedia.org/wiki/Barnsley_fern") 49528#@gui : sep = separator() 49529#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/18/10</i>.</small>") 49530fx_barnsley_fern : 49531 repeat $! l[$<] 49532 shape_fern {min(w,h)},$2%,$3,{$4%},$1 *. 255 49533 100%,100%,1,3,[${5-7}] 49534 rv[-2,-1] a[-2,-1] c 49535 if !$9 blend alpha,{$8/255} 49536 else nm. "name(Barnsley Fern),opacity("{round($8*100/255)})")" rv[-2,-1] 49537 fi 49538 endl done 49539 49540fx_barnsley_fern_preview : 49541 fx_barnsley_fern ${1-8},0 49542 49543#@gui Snowflake : fx_snowflake, fx_snowflake(1) 49544#@gui : Recursions = int(5,0,6) 49545#@gui : Opacity = float(1,0,1) 49546#@gui : Color = color(255,255,255) 49547#@gui : sep = separator() 49548#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49549fx_snowflake : 49550 repeat $! l[$>] to_color split_opacity l[0] 49551 shape_snowflake {min(w,h)},$1 100%,100%,1,3,[${3-5}] 49552 j[0] .,{([w#0,h#0]-[w#1,h#1])/2},0,0,$2,.. k[0] 49553 endl a c endl done 49554 49555#@gui _<i>Others</i> 49556 49557#@gui Dragon Curve : fx_dragoncurve, fx_dragoncurve(1) 49558#@gui : Recursions = int(20,0,30) 49559#@gui : Angle = float(0,-180,180) 49560#@gui : Opacity = float(1,0,1) 49561#@gui : Color = color(255,255,255) 49562#@gui : sep = separator() 49563#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2019/01/29</i>.</small>") 49564fx_dragoncurve : 49565 repeat $! l[$>] to_color split_opacity l[0] 49566 shape_dragon {min(w,h)},$1,$2 100%,100%,1,3,[${4-6}] 49567 j[0] .,{([w#0,h#0]-[w#1,h#1])/2},0,0,$3,.. k[0] 49568 endl a c endl done 49569 49570#@gui ____<b>Various</b> 49571#------------------------ 49572 49573#@gui Custom Code [Global] : fx_custom_code, fx_custom_code_preview(1) 49574#@gui : Code = text(1,"repeat $! l[$>]\n\n to_rgb\n +deform 20\n blend_edges 3\n\nendl done\n\n\n") 49575#@gui : sep = separator() 49576#@gui : Channel(s) = choice{"None (Allows Multi-layers)","All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]", 49577#@gui : "RGB [Blue]","RGBA [Alpha]","Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]", 49578#@gui : "YCbCr [Luminance]","YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 49579#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 49580#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 49581#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 49582#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]"} 49583#@gui : Value Action = choice("None","Cut","Normalize") 49584#@gui : Display Debug Info on Preview = bool(0) 49585#@gui : Debug Font Size = choice(2,"Tiny","Small","Normal","Large") 49586#@gui : sep = separator() 49587#@gui : Preview Type = choice{"Full (Allows Multi-Layers)","Forward Horizontal","Forward Vertical", 49588#@gui : "Backward Horizontal","Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom", 49589#@gui : "Duplicate Right","Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse"} 49590#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 49591#@gui : sep = separator() 49592#@gui : note = note{"<small><b>Note: </b> 49593#@gui : This filter can execute any set of instructions understood by the <b>G'MIC</b> language interpreter. 49594#@gui : Here, you can then test some commands before creating your own G'MIC custom commands and plug-in 49595#@gui : menu entries.\n\n 49596#@gui : Please look at the documentation reference web page :</small>"} 49597#@gui : url = link("https://gmic.eu/reference/") 49598#@gui : note = note{"<small> 49599#@gui : to learn more about available <b>G'MIC</b> commands. 49600#@gui : </small>"} 49601#@gui : sep = separator() 49602#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/03/10</i>.</small>") 49603 49604#@gui Custom Code [Local] : fx_custom_code, fx_custom_code_preview(0) 49605#@gui : Code = text(1,"repeat $! l[$>]\n\n to_rgb\n +deform 20\n blend_edges 3\n\nendl done\n\n\n") 49606#@gui : sep = separator() 49607#@gui : Channel(s) = choice{"None (Allows Multi-layers)","All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]", 49608#@gui : "RGB [Blue]","RGBA [Alpha]","Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]", 49609#@gui : "YCbCr [Luminance]","YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 49610#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 49611#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 49612#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 49613#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]"} 49614#@gui : Value Action = choice("None","Cut","Normalize") 49615#@gui : Display Debug Info on Preview = bool(0) 49616#@gui : Debug Font Size = choice(2,"Tiny","Small","Normal","Large") 49617#@gui : sep = separator() 49618#@gui : Preview Type = choice{"Full (Allows Multi-Layers)","Forward Horizontal","Forward Vertical", 49619#@gui : "Backward Horizontal","Backward Vertical","Duplicate Top","Duplicate Left","Duplicate Bottom", 49620#@gui : "Duplicate Right","Duplicate Horizontal","Duplicate Vertical","Checkered","Checkered Inverse"} 49621#@gui : Preview Split = point(50,50,0,0,200,200,200,0,10)_0 49622#@gui : sep = separator() 49623#@gui : note = note{"<small><b>Note: </b> 49624#@gui : This filter can execute any set of instructions understood by the <b>G'MIC</b> language interpreter. 49625#@gui : Here, you can then test some commands before creating your own G'MIC custom commands and 49626#@gui : plug-in menu entries.\n\n 49627#@gui : Please look at the documentation reference web page :</small>"} 49628#@gui : url = link("https://gmic.eu/reference/") 49629#@gui : note = note{"<small> 49630#@gui : to learn more about available <b>G'MIC</b> commands. 49631#@gui : </small>"} 49632#@gui : sep = separator() 49633#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/03/10</i>.</small>") 49634fx_custom_code : skip "${1=-skip ,}" 49635 ({'{/"$1"}'}) discard. 92,10 _gcp_arg={t} rm. 49636 m "_fx_custom_code_start : "$_gcp_arg 49637 if $4 49638 _nb_in=$! 49639 _dim_in="" sep="" 49640 repeat $! l[$>] 49641 _dim_in=$_dim_in$sep"["$>"] = "{w}x{h}x{d}x{s}", in ["{_round([im,iM],0.1)}"]" sep="\n" 49642 endl done 49643 fi 49644 if $2 49645 ac "_fx_custom_code_start _status_out=${}",{$2-1},$3 49646 else 49647 _fx_custom_code_start _status_out=${} 49648 if $3==1 c 0,255 elif $3==2 n 0,255 fi 49649 fi 49650 if $4 49651 _nb_out=$! 49652 _dim_out="" sep="" repeat $! l[$>] 49653 _dim_out=$_dim_out$sep"["$>"] = "{w}x{h}x{d}x{s}", in ["{_round([im,iM],0.1)}"]" sep="\n" endl done 49654 fi 49655 um _fx_custom_code_start 49656 49657fx_custom_code_preview : skip "${1=-skip ,}" 49658 w={w} h={h} 49659 l 49660 ({'{/"$1"}'}) discard. 92,10 _gcp_arg={t} rm. 49661 if $6 gui_split_preview "fx_custom_code $_gcp_arg,${2--2}",${-3--1} 49662 else fx_custom_code $_gcp_arg,${2--2} 49663 fi 49664 onfail 49665 error_msg=${} 49666 rr2d $w,$h,2,1 49667 gui_print_preview "Syntax error:",,{``$error_msg},20,40 49668 endl 49669 if $4 # Display debug infos on preview 49670 if !$3 % 256 fi 49671 if $_preview_mode>=4 gui_preview fi 49672 siz0=13 siz1=17 siz2=19 siz3=22 49673 if ['$_status_out']==0 _status_out=(empty) fi 49674 info="Input images: "#$_nb_in"\n"\ 49675 $_dim_in"\n\n"\ 49676 "Output images: "#$_nb_out"\n"\ 49677 $_dim_out"\n\n"\ 49678 "Output status: "$_status_out 49679 0 t. {``$info},0,0,${siz$5},1,255 expand_xy. 5,0 +dilate. 3 a[-2,-1] c 49680 rr2d[^-1] ${-max_wh},2,2 49681 r. ..,..,1,100%,0 drgba[^-1] 49682 /[^-1] 2 blend[^-1] .,alpha rm. 49683 fi 49684 49685#@gui Export RGB-565 File : fx_output_565,_none_ 49686#@gui : Filename = _fileout("out565.rgb") 49687#@gui : Reverse endianness = _bool(0) 49688#@gui : sep = separator() 49689#@gui : note = note{"<b>Note:</b> This filter saves your selected layer as a raw RGB-565 file. Keep in mind that 49690#@gui : you have to remember the image dimension if you want to reload the image file afterwards!"} 49691#@gui : sep = separator() 49692#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/05/03</i>.</small>") 49693fx_output_565 : 49694 output_565 "$1",$2 49695 49696#@gui Games & Demos : fx_gmic_demos, fx_gmic_demos_preview 49697#@gui : Selection = choice("2048","Blobs Editor","Bouncing Balls","Connect-Four","Fire Effect","Fireworks", 49698#@gui : "Fish-Eye Effect","Fourier Filtering","Hanoi Tower", 49699#@gui : "Histogram","Hough Transform","Jawbreaker","Virtual Landscape","The Game of Life","Light Effect", 49700#@gui : "Mandelbrot Explorer","3D Metaballs","Minesweeper", 49701#@gui : "Minimal Path","Pacman","Paint","Plasma Effect","RGB Quantization","3D Reflection","3D Rubber Object", 49702#@gui : "Shadebobs","Spline Editor", 49703#@gui : "3D Starfield","Tetris","Tic-Tac-Toe","3D Waves","Fractal Whirl") 49704#@gui : sep = separator() 49705#@gui : note = note("<small><b>Note:</b> This filter proposes a showcase of some interactive demos, all written 49706#@gui : as G'MIC scripts.</small>") 49707#@gui : note = note{"<small>On most demos, you can use the keyboard shortcut <b>CTRL+D</b> to double the window 49708#@gui : size (and <b>CTRL+C</b> to go back to the original size). 49709#@gui : Also, feel free to use the mouse buttons, as they are often used to perform an action. 49710#@gui : </small>"} 49711#@gui : sep = separator() 49712#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2014/10/09</i>.</small>") 49713fx_gmic_demos : 49714 coms=2048,blobs,bouncing,connect4,fire,fireworks,fisheye,fourier,hanoi,histogram,hough,jawbreaker,landscape,life,\ 49715 light,mandelbrot,metaballs3d,minesweeper,minimal_path,pacman,paint,plasma,quantize_rgb,reflection3d,\ 49716 rubber3d,shadebobs,spline,starfield3d,tetris,tictactoe,waves,whirl 49717 com=${arg\ {1+$1},$coms} 49718 if $!>0 sel=0 else sel= fi 49719 +l[$sel] m "foo : x_"$com foo rm um foo endl 49720 49721fx_gmic_demos_preview : 49722 rm filename=${-path_tmp}gmic_demos.cimgz 49723 if isfile(['{/$filename}']) $filename 49724 else l[] https://gmic.eu/img/gmic_demos.cimgz o $filename endl 49725 fi 49726 k[$1,-1] rows. $1 map[0] [1] k[0] 49727 49728#@gui Histogram Analysis : _none_, fx_display_histogram(1) 49729#@gui : Number of Clusters = int(256,2,1024) 49730#@gui : sep = separator() 49731#@gui : Channel(s) = choice("All","RGBA [All]","RGB [All]","RGB [Red]","RGB [Green]","RGB [Blue]","RGBA [Alpha]", 49732#@gui : "Linear RGB [All]","Linear RGB [Red]","Linear RGB [Green]","Linear RGB [Blue]","YCbCr [Luminance]", 49733#@gui : "YCbCr [Blue-Red Chrominances]","YCbCr [Blue Chrominance]","YCbCr [Red Chrominance]", 49734#@gui : "YCbCr [Green Chrominance]","Lab [Lightness]","Lab [ab-Chrominances]","Lab [a-Chrominance]", 49735#@gui : "Lab [b-Chrominance]","Lch [ch-Chrominances]","Lch [c-Chrominance]","Lch [h-Chrominance]","HSV [Hue]", 49736#@gui : "HSV [Saturation]","HSV [Value]","HSI [Intensity]","HSL [Lightness]","CMYK [Cyan]","CMYK [Magenta]", 49737#@gui : "CMYK [Yellow]","CMYK [Key]","YIQ [Luma]","YIQ [Chromas]","RYB [All]","RYB [Red]","RYB [Yellow]","RYB [Blue]") 49738#@gui : sep = separator() 49739#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2016/20/06</i>.</small>") 49740fx_display_histogram : 49741 mode=${arg\ 1+$2,all,rgba,rgb,rgb_r,rgb_g,rgb_b,rgba_a,\ 49742 lrgb,lrgb_r,lrgb_g,lrgb_b,\ 49743 ycbcr_y,ycbcr_cbcr,ycbcr_cb,ycbcr_cr,ycbcr_cg,\ 49744 lab_l,lab_ab,lab_a,lab_b,\ 49745 lch_ch,lch_c,lch_h,\ 49746 hsv_h,hsv_s,hsv_v,hsi_i,hsl_l,\ 49747 cmyk_c,cmyk_m,cmyk_y,cmyk_k,\ 49748 yiq_y,yiq_iq} 49749 _ac_$mode m "_ac_precond : "$_p m "_ac_forward : "$_f m "_ac_backward : "$_b 49750 repeat $! l[$>] 49751 _ac_precond _ac_forward[0] channels $_s 49752 display_histogram {w},{h},$1,0,255 49753 if s==2" || "s==4 channels 0,2 fi 49754 endl done 49755 49756#@gui Import Data : fx_import_image, gui_no_preview 49757#@gui : Filename = filein() 49758#@gui : Normalize = bool(1) 49759#@gui : note = note{"\n<small><b>Note: </b> 49760#@gui : This filter can import any image data read by the <b>G'MIC</b> language interpreter. 49761#@gui : It includes exotic formats as : <i>Pandore, CImg, Inrimage, AVI/MPEG (requires FFMPEG installed), ...</i> 49762#@gui : </small>"} 49763#@gui : sep = separator() 49764#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2010/29/12</i>.</small>") 49765fx_import_image : skip "${1=}" 49766 rm i "$1" s z if $2 n 0,255 else c 0,255 fi 49767 49768#@gui Import RGB-565 File : fx_input_565 49769#@gui : Filename = filein() 49770#@gui : Width = text("800") 49771#@gui : Height = text("600") 49772#@gui : Reverse endianness = bool(0) 49773#@gui : sep = separator() 49774#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2020/05/03</i>.</small>") 49775fx_input_565 : skip "${1=}" 49776 l[] check "isint($2) && $2>0 && isint($3) && $3>0" 49777 onfail error "Invalid Specified Dimensions" 49778 endl 49779 if ['"$1"']==0 gui_warning_preview "Choose a filename" 49780 elif !isfile(['"$1"']) gui_warning_preview "Filename not found!" 49781 else input_565 "$1",${2-4} mv. 0 49782 fi 49783 49784#@gui Intarsia : fx_intarsia, fx_intarsia_preview 49785#@gui : note = note{"<small><b>Note:</b> 49786#@gui : Intarsia is a method of Crochet/Knitting with a number of colours, in which a separate ball of yarn 49787#@gui : is used for each area of colour. 49788#@gui : This filter creates a HTML version of a graph chart which is solely used for this purpose 49789#@gui : </small>"} 49790#@gui : sep = separator() 49791#@gui : Output Directory = _folder("") 49792#@gui : Output HTML File = _text("intarsia.html") 49793#@gui : sep = separator() 49794#@gui : Maximum Image Size = int(512,2,1024) 49795#@gui : Maximum Number of Image Colors = _int(12,2,64) 49796#@gui : Starting Point = choice(1,"Top Left","Top Right","Bottom Left","Bottom Right") 49797#@gui : Loop Method = choice("Row by Row","Column by Column") 49798#@gui : sep = separator() 49799#@gui : Add Comment Area in HTML Page = _bool(1) 49800#@gui : Preview Progress (%) = float(100,0,100) 49801#@gui : sep = separator() 49802#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2015/09/07</i>.</small>") 49803fx_intarsia : 49804 to_rgb repeat $! nm=${gui_layer_name[$>]} +l[$>] 49805 49806 # Constrain image for size and number of colors, and index it with colormap. 49807 if max(w,h)>$3 rr2d $3,$3,0 fi 49808 +colormap 0 49809 if w>$4 rm. +colormap $4,1 fi 49810 round[1] index[0] [1] 49811 49812 # Output header and title. 49813 0 nm. $nm ('{b}') f. 'if(x,i,if(i>=97&&i<=122,i-32,i))' image_basename={t} rm[-2,-1] 49814 ('"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\ 49815 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n\ 49816 <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n\ 49817 <head></head><body bgcolor=\"#FFFDFF\"><center><font size=\"-1\">\n\ 49818 <h2>"$image_basename" ("{0,w}x{0,h}")</h2>\n\ 49819 <table cellpadding=\"8\"><tr><td>\n\ 49820 <table cellpadding=\"4\">\n"') 49821 49822 # Render image of colors. 49823 0 nm. "$2" image_name={b} rm. 49824 nb_cols={1,w} 49825 repeat $nb_cols 49826 color={1,I($>)} 49827 R={arg(1,$color)} G={arg(2,$color)} B={arg(3,$color)} 49828 ('${dec2hex\ {$R*65536+$G*256+$B}}') -. {'0'} r. 6,1,1,1,0,0,1,0 +. {'0'} 49829 f. if(i>=_'a'" && "i<=_'z',i+_'A'-_'a',i) 49830 hcolor={t} rm. 49831 48,32,1,4 fc. $color,255 frame. 1,1,0,0,0,255 o. "$1/"${image_name}_$>.png rm. 49832 ('"<tr><td><b>Colour "$>"</b></td><td><img src=\""${image_name}_$>.png"\" /></td><td>#"$hcolor"</td></tr>\n"') 49833 done 49834 ('"</table>\n</td><td>"') 49835 49836 # Render result and overview images. 49837 starting=${"arg {1+$5},\"Top left\",\"Top right\",\"Bottom left\",\"Bottom right\""} 49838 label=${"arg {1+$6},Row,Column"} 49839 if $6 dir0="T → B" dir1="B → T" else dir0="L → R" dir1="R → L" fi 49840 dir={arg(1+2*$5+$6,0,0,1,0,0,1,1,1)} 49841 49842 +map[0] [1] 49843 +fx_intarsia_preview. ${1-7},63 drgba. 49844 rr2d.. 200,200,1,1 49845 to_rgba[-2,-1] frame[-2,-1] 1,1,0,0,0,255 frame[-2,-1] 0,20,0,0,0,0 49846 t.. "Result",0,0,16,1,0,0,0,255 49847 t. "Ordering overview",0,0,16,1,0,0,0,255 49848 frame[-2,-1] 20,20,0,0,0,0 49849 49850 o.. "$1/"${image_name}_A.png 49851 o. "$1/"${image_name}_B.png 49852 rm[-2,-1] 49853 49854 ('"<table><tr><td><img src=\""${image_name}_A.png"\" /></td></tr><tr><td>"\ 49855 "<img src=\""${image_name}_B.png"\" /></td></tr></table></td></tr></table>\n"') 49856 if $7 ('"<p><b>Additional comments:</b><br/><textarea cols=\"80\" rows=\"10\" 49857 placeholder=\"Enter comments here...\"></textarea></p>\n"') fi 49858 ('"<p><b>Starting point:</b> "$starting"\ 49859 <b>Orientation:</b> "$label" by "$label"</p>\n"') 49860 rm[1] 49861 49862 # Output geometry. 49863 ('"<table cellspacing=\"0\" cellpadding=\"4\" border=\"1\">\n"') 49864 49865 _fx_intarsia[0] $5,$6,0 49866 +l[0] 49867 s y 49868 repeat $! l[$>] 49869 if $>%2 mirror. x fi 49870 im={im} compress_rle 0,0 rows 6,100% 49871 ('"<tr><td valign=\"top\"><b>"$label" "{1+$>}"</b></td><td valign=\"top\">"${dir$dir}"</td><td>\n"') 49872 i=0 n=0 do 49873 val={0,i[$i]} i+=1 49874 if $val>=0 occ=1 49875 else 49876 occ={-$val} 49877 val={0,i[$i]} 49878 if $val<0 val=0 else i+=1 fi 49879 fi 49880 val+=$im 49881 ('"colour:<b>"$val"</b> "$occ') 49882 if {0,$i<h} ('", "') fi 49883 n+=1 49884 if !($n%8) ('"<br/>\n"') fi 49885 while $i<h#0 49886 ('"</td></tr>\n"') 49887 rm[0] a x 49888 dir={!$dir} 49889 endl done 49890 a x 49891 endl 49892 rm[0] 49893 49894 ('"</table>\n</font></center>\n</body>"') 49895 a x ot "$1/$2" 49896 rm 49897 endl done 49898 49899fx_intarsia_preview : 49900 to_rgb repeat $! l[$>] 49901 if max(w,h)>$3 rr2d $3,$3,0 fi 49902 to_rgba 49903 _fx_intarsia $5,$6,0 49904 100%,100%,1,1,'if(y%2,y*w+w-1-x,y*w+x)<$8*wh/100' * 49905 if min(w,h)<140 rr2d 140,140,1,1 fi 49906 expand_xy 16,0 49907 49908 100%,100% circle. 16,16,1%,1,1 49909 arrow3d. 0,0,0,{w/4},0,0,2%,15%,10% col3d. 1 j3d.. .,16,16,0,1,2,0,0 rm. 49910 +dilate. 3 r.. 100%,100%,1,3,0,0,0,0,0,0.5 a[-2,-1] c *. 255 49911 blend alpha 49912 49913 _fx_intarsia $5,$6,1 49914 endl done 49915 49916_fx_intarsia : 49917 if $3" && "$2 transpose fi 49918 if $1==0 # Start from top left. 49919 elif $1==1 # Start from top right. 49920 mirror x 49921 elif $1==2 # Start from bottom left. 49922 mirror y 49923 elif $1==3 # Start from bottom right. 49924 mirror xy 49925 fi 49926 if !$3" && "$2 transpose fi 49927 49928#@gui Sample Image : fx_image_sample, fx_image_sample_preview 49929#@gui : Input = choice{"Random","Apples","Balloons","Barbara","Boats","Bottles","Butterfly","Cameraman","Car","Cat", 49930#@gui : "Chick","Cliff","Colorful","David","Dog","Duck","Eagle","Elephant","Earth","Flower","Fruits", 49931#@gui : "Gmicky (Deevad)","Gmicky (Mahvin)","Gmicky & Wilber","Greece","Gummy","House","Inside","Landscape","Leaf", 49932#@gui : "Lena","Leno","Lion","Mandrill","Mona Lisa","Monkey","Parrots","Pencils","Peppers","Portrait0","Portrait1", 49933#@gui : "Portrait2","Portrait3","Portrait4","Portrait5","Portrait6","Portrait7","Portrait8","Portrait9", 49934#@gui : "Roddy","Rooster","Rose","Square","Swan","Teddy","Tiger","Tulips","Wall","Waterfall","Zelda"} 49935#@gui : note = note("<small>Choosing <b>0</b> for parameters <i>Width</i> or <i>Height</i> means <i>Automatic</i>. 49936#@gui : </small>") 49937#@gui : Width = _int(0,0,1024) 49938#@gui : Height = _int(0,0,1024) 49939#@gui : sep = separator() 49940#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2017/16/01</i>.</small>") 49941fx_image_sample : 49942 if $1 sp {$1-1},$2,$3 else sp ?,$2,$3 fi 49943 mv. 0 49944 49945fx_image_sample_preview : 49946 w={w} h={h} rm 49947 fx_image_sample $1,{$w>$h?$w:0},{$h>$w?$h:0} 49948 49949#@gui Solve Maze : fx_solve_maze, fx_solve_maze_preview(1) 49950#@gui : Starting Point (%) = point(5,5) 49951#@gui : Ending Point (%) = point(95,95) 49952#@gui : Smoothness = float(0.1,0,1) 49953#@gui : Thickness = int(3,1,10) 49954#@gui : Color = color(255,0,0) 49955#@gui : Maze Type = choice("Dark Walls","White Walls") 49956#@gui : sep = separator() 49957#@gui : note = note("<small>Author: <i>David Tschumperlé</i>. Latest Update: <i>2011/01/09</i>.</small>") 49958fx_solve_maze : 49959 repeat $! 49960 +norm. >=. 50% 49961 if !$10 negate. fi 49962 *. 255 +b. $5% *.. 1e10 +[-2,-1] 49963 minimal_path. $1%,$2%,0,$3%,$4%,0 49964 pointcloud. 0 dilate. $6 r. ..,..,1,1,0 49965 to_rgba. 49966 replace_color. 0,0,1,1,1,255,${7-9},255 49967 replace_color. 0,0,0,0,0,255,0,0,0,0 49968 ellipse. $1%,$2%,5,5,0,1,${7-9},255 49969 ellipse. $3%,$4%,5,5,0,1,${7-9},255 49970 rv[-2,-1] 49971 mv[-2,-1] 0 done 49972 49973fx_solve_maze_preview : 49974 drgba 49975 line $1%,$2%,$3%,$4%,1,0xCCCCCCCC,${7-9} 49976 ellipse $1%,$2%,3,3,0,1,${7-9} 49977 ellipse $1%,$2%,3,3,0,1,0x1,0 49978 ellipse $3%,$4%,3,3,0,1,${7-9} 49979 ellipse $3%,$4%,3,3,0,1,0x1,0 49980 49981#@gui _ 49982 49983#--------------------------------- 49984# 49985#@cli :: Additional Gallery Images 49986# 49987#--------------------------------- 49988#@cli _gallery_arrays 49989#@cli : This entry defines some examples of array filters for the G'MIC gallery page. 49990#@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]" 49991#@cli : $ sample tiger,leno,monkey,duck,eagle frame 3,3,0 frame 3,3,255 montage A _label="Montage" 49992#@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" 49993 49994#@cli _gallery_artistic 49995#@cli : This entry defines some examples of artistic filters for the G'MIC gallery page. 49996#@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" 49997#@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" 49998#@cli : $ image.jpg fx_8bits 25,800,16,0 _label="Oldschool~8bits" 49999#@cli : $ image.jpg fire_edges 0.7,0.25,0.5,25,20 _fps=6 _label="Edges~on~fire" 50000#@cli : $ image.jpg fx_diffusiontensors 10,5,3,1,0.15,1,0,3,0 _label="Diffusion~tensors" 50001#@cli : $ image.jpg fx_dreamsmooth 3,1,1,0.8,0,0.8,1,24,0 _label="Dream~smoothing" 50002#@cli : $ image.jpg fx_feltpen 300,50,1,0.1,20,5,0 _label="Felt~pen" 50003#@cli : $ image.jpg gtutor_fpaint 0.5,0.5,0,0,45,0.5,0.5,0.5,0 _label="Finger~paint" 50004#@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 \ 50005# _label="Novel~FX" 50006#@cli : $ image.jpg fx_illustration_look 100,0,0,0,0 _label="Illustration~look" 50007#@cli : $ image.jpg fx_lylejk_painting 10,2,4,10,0 _label="Lylejk~painting" 50008#@cli : $ image.jpg fx_painting 5,2.5,1.5,50,1,0 _label="Painting" 50009#@cli : $ image.jpg fx_posterize 150,30,1,6,0,0,1,0 _label="Posterize" 50010#@cli : $ image.jpg fx_quadtree 2,1024,1.05,0,2.33,0.68,0.39,1,0 _label="Quadtree~variations" 50011#@cli : $ image.jpg fx_vector_painting 9.37,0 _label="Vector~painting" 50012 50013#@cli _gallery_blackandwhite 50014#@cli : This entry defines some examples of black-and-white filters for the G'MIC gallery page. 50015#@cli : $ image.jpg fx_freaky_bw 90,20,0,0,0,0 _label="Freaky~B&W" 50016#@cli : $ image.jpg fx_engrave 0.5,50,0,8,40,0,0,0,10,1,0,0,0,1,0 _label="Engrave" 50017#@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" 50018#@cli : $ image.jpg fx_pencil_portraitbw 30,120,1,0.5,144,79,21,0 _label="Pencil~portrait" 50019#@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" 50020 50021#@cli _gallery_colors 50022#@cli : This entry defines some examples of color filters for the G'MIC gallery page. 50023#@cli : $ image.jpg fx_color_abstraction 1,10,0.2,0 _label="Color~abstraction" 50024#@cli : $ image.jpg fx_boost_chroma 90,0,0 _label="Boost~chromaticity" 50025#@cli : $ image.jpg fx_retrofade 20,6,40,0 _label="Retro~fade" 50026#@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,\ 50027# 0,0,100,0,0.3,25,0,0 _label="Vintage~style" 50028 50029#@cli _gallery_deformations 50030#@cli : This entry defines some examples of deformation filters for the G'MIC gallery page. 50031#@cli : $ image.jpg animate "flower","30,10,0,0","30,10,0,360",10 rm. _fps=6 _label="flower" 50032#@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" \ 50033# _label="Conformal~maps" 50034#@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 \ 50035# _label="Continuous~droste" 50036#@cli : $ image.jpg fx_crease 30,10,3 _label="Crease" 50037#@cli : $ image.jpg fx_distort_lens 0.29,0,0.23,50,50,0,0 _label="Distort~lens" 50038#@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 \ 50039# _label="Drop~water" 50040#@cli : $ image.jpg fx_reflect 50,1,110,160,190,64,0,1.5,0,-3.3,7,1.5 _label="Reflection" 50041#@cli : $ image.jpg fx_square_circle 0,1,0,0,0,0,0,0 _label="Square~to~circle" 50042#@cli : $ image.jpg fx_textured_glass 40,40,1,1,0,2,0,0 _label="Textured~glass" 50043#@cli : $ sample lena,leno,320 morph 40 _fps=5 _label="morph" 50044 50045#@cli _gallery_filtering 50046#@cli : This entry defines some examples of filters for the G'MIC gallery page. 50047#@cli : $ image.jpg fx_gcd_crt 1.8,1.8,0,0 equalize 256 _label="CRT~sub-pixels" 50048#@cli : $ image.jpg fx_dirty 30,1,0,0,0 _label="Dirty" 50049#@cli : $ image.jpg fx_freaky_details 2,10,1,11,0,32,0 _label="Freaky~details" 50050#@cli : $ image.jpg jeje_normalize_local_variance 50,5,5,1,0,0 _label="Local~variance~normalization" 50051#@cli : $ image.jpg fx_mighty_details 25,1,25,1,11,0 _label="Mighty~details" 50052 50053#@cli _gallery_patterns 50054#@cli : This entry defines some examples of pattern filters for the G'MIC gallery page. 50055#@cli : $ image.jpg fx_rain 65,10,50,0.1,1,1,0 gui_merge_layers _label="Rain~&~snow" 50056#@cli : $ 400,400,1,3 fx_camouflage 9,12,100,30,46,33,75,90,65,179,189,117,255,246,158 _label="Camouflage" 50057#@cli : $ image.jpg jeje_clouds 50,0.5 _label="Clouds" 50058#@cli : $ image.jpg fx_crystal 50,0.2,20,0 _label="Crystal" 50059#@cli : $ 400,400,1,3 fx_crystal_background 10,25,0,100,1 _label="Crystal~background" 50060#@cli : $ image.jpg fx_marble 0.5,1,0,0,0.4,0.6,0.6,1.1,0,100 _label="Marble" 50061#@cli : $ image.jpg fx_mineral_mosaic 1,2,1,100,0 _label="Mineral~mosaic" 50062#@cli : $ image.jpg fx_shapes 1,16,10,2,5,106.8,2,0,0,1,0 _label="Op~art" 50063#@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" 50064#@cli : $ 400,400,1,3 fx_seamless_turbulence 15,20,0,1,3,1 _label="Seamless~turbulence" 50065#@cli : $ image.jpg fx_shockwaves 10,10,20,0,0 _label="Shock~waves" 50066#@cli : $ 400,400,1,3 fx_equation_parametric "sin(t)*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)",\ 50067# "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]" 50068#@cli : $ 400,400,1,3 KittyRings 30,8,0,1,113,0,113,0,255,0 _label="Kitaoka~spin~illusion" 50069#@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" 50070#@cli : $ image.jpg fx_lava 8,5,3,0,0 _label="Lava" 50071#@cli : $ sample monkey,lion,monkey 100%,100% plasma. equalize. 256 transition[0,1,2] [3],10 rm. _fps=10 \ 50072# _label="transition" 50073#@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" 50074 50075#@cli _gallery_3dmeshes 50076#@cli : This entry defines some examples of 3D rendering filters for the G'MIC gallery page. 50077#@cli : $ sample leno,lion,leno resize 400,400 transition3d 20,5,5 rm. _fps=10 _label="transition3d" 50078#@cli : $ 256,192 fx_text_pointcloud3d 64,"G'MIC","Rocks!",1,200,220,255,255,255,255,255,2,2,1,19 _fps=10 \ 50079# _label="3D~text~pointcloud" 50080 50081#@cli _gallery_stylization 50082#@cli : This entry defines some examples of image stylization for the G'MIC gallery page. 50083#@cli : $ sample car _fx_stylize starrynight _output_mode=1 \ 50084# +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 _label="from~Van~Gogh:~Starry~Night" 50085#@cli : $ sample car _fx_stylize graytree _output_mode=1 \ 50086# +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,20,2,1.85,0 _label="from~Mondrian:~Gray~Tree" 50087#@cli : $ sample car _fx_stylize yellowredblue _output_mode=1 \ 50088# +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 \ 50089# _label="from~Kandinsky:~Yellow-Red-Blue" 50090#@cli : $ sample car _fx_stylize littlebayatlaciotat _output_mode=1 \ 50091# +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 \ 50092# _label="from~Braque:~Little~Bay~at~La~Ciotat" 50093#@cli : $ sample car _fx_stylize leviaducalestaque _output_mode=1 \ 50094# +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,0,2,1.85,0 \ 50095# _label="from~Braque:~Le~Viaduc~a~l'Estaque" 50096#@cli : $ sample car _fx_stylize greatwave _output_mode=1 \ 50097# +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" 50098#@cli : $ sample elephant input ../img/hatching.png _output_mode=1 \ 50099# +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,0,2,1.85,0 _label="from~Hatch~Drawing" 50100#@cli : $ sample cat input ../img/hatching.png _output_mode=1 \ 50101# +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,0,2,1.85,0 _label="from~Hatch~Drawing" 50102#@cli : $ sample bottles _fx_stylize starrynight _output_mode=1 \ 50103# +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" 50104#@cli : $ sample cat _fx_stylize summertime9a _output_mode=1 \ 50105# +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,100,2,1.85,0 _label="from~Pollock:~Summertime~No~9A" 50106#@cli : $ sample cat _fx_stylize greatwave _output_mode=1 \ 50107# +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" 50108#@cli : $ sample dog _fx_stylize convergence _output_mode=1 \ 50109# +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,50,2,1.85,0 _label="from~Pollock:~Convergence" 50110#@cli : $ sample dog _fx_stylize irises _output_mode=1 \ 50111# +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,200,2,1.85,0 _label="from~Van~Gogh:~Irises" 50112#@cli : $ sample mandrill _fx_stylize themandola _output_mode=1 \ 50113# +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,10,2,1.85,0 _label="from~Braque:~The~Mandola" 50114#@cli : $ sample square _fx_stylize orientalpleasuregardenanagoria _output_mode=1 \ 50115# +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,40,2,1.85,0 \ 50116# _label="from~Klee:~Oriental~Pleasure~Garden~Anagoria" 50117#@cli : $ sample monalisa _fx_stylize squareswithconcentriccircles _output_mode=1 \ 50118# +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,10,2,1.85,0 \ 50119# _label="from~Kandisnky:~Squares~with~Concentric~Circles" 50120#@cli : $ sample monalisa _fx_stylize inthestyleofkairouan _output_mode=1 \ 50121# +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,50,2,1.85,0 \ 50122# _label="from~Klee:~In~the~Style~of~Kairouan" 50123#@cli : $ sample square _fx_stylize polyphony2 _output_mode=1 \ 50124# +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,10,2,1.85,0 _label="from~Klee:~Polyphony~2" 50125#@cli : $ sample square _fx_stylize wheatstacksendofsummer _output_mode=1 \ 50126# +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,10,2,1.85,0 \ 50127# _label="from~Monet:~Wheatstacks~-~End~of~Summer" 50128#@cli : $ sample square _fx_stylize portraitdemetzinger _output_mode=1 \ 50129# +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,500,2,1.85,0 \ 50130# _label="from~Delaunay:~Portrait~de~Metzinger" 50131#@cli : $ sample monalisa input ../img/mandelbrot.jpg _output_mode=1 \ 50132# +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,50,2,1.85,0 _label="from~Mandelbrot~Fractal~Set" 50133#@cli : $ sample bottles _fx_stylize redtree _output_mode=1 \ 50134# +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,5,2,1.85,0 \ 50135# _label="from~Mondrian:~Evening;~Red~Tree" 50136#@cli : $ sample bottles _fx_stylize redwaistcoat _output_mode=1 \ 50137# +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,0,2.05,1.85,0 \ 50138# _label="from~Klee:~Red~Waistcoat" 50139#@cli : $ sample bottles _fx_stylize reservoirhortadeebro _output_mode=1 \ 50140# +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 _label="from~Picasso:~The~Reservoir" 50141#@cli : $ sample bottles _fx_stylize almondblossom _output_mode=1 \ 50142# +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,10,2,1.85,0 _label="from~Van~Gogh:~Almond~Blossom" 50143#@cli : $ sample bottles _fx_stylize landscapenearantwerp _output_mode=1 \ 50144# +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,10,2,1.85,0 \ 50145# _label="from~Braque:~Landscape~near~Antwerp" 50146#@cli : $ sample bottles _fx_stylize wheatfieldwithcrows _output_mode=1 \ 50147# +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,10,5,1.85,0 \ 50148# _label="from~Van~Gogh:~Wheat~Field~with~Crows" 50149 50150#@cli _gallery_codesamples 50151#@cli : This entry defines some examples of coding fun filters for the G'MIC gallery page. 50152#@cli : $ https://gmic.eu/samples/lissajous.gmic go _fps=10 _label="Lissajous" 50153#@cli : $ https://gmic.eu/samples/torus3d.gmic go _fps=10 _label="3D~torus" 50154#@cli : $ https://gmic.eu/samples/pacman.gmic go _fps=25 _label="Pacman" 50155#@cli : $ https://gmic.eu/samples/scrolling.gmic go _fps=25 _label="Scrolling" 50156#@cli : $ https://gmic.eu/samples/landscape.gmic go _fps=12 _label="Landscape" 50157#@cli : $ https://gmic.eu/samples/mandelbrot.gmic go _fps=8 _label="Mandelbrot" 50158#@cli : $ https://gmic.eu/samples/heart.gmic go _fps=15 _label="Heart" 50159#@cli : $ https://gmic.eu/samples/distortion.gmic go _fps=20 _label="Distortion" 50160#@cli : $ https://gmic.eu/samples/rotozoom.gmic go _fps=15 _label="Rotozoom" 50161 50162#--------------------------- 50163# Test programs for NN lib. 50164#--------------------------- 50165 50166#------------------------------ 50167# Test program for FC networks. 50168#------------------------------ 50169nn_test_fc : check "${1=1e-4}>0 && isbool(${2=1})" 50170 50171 # Build neural network. 50172 #---------------------- 50173 nn_init 50174 nn_layer_input X,2 50175 nn_layer_batchnorm BN,X 50176 nn_layer_fcnl FC1,BN,100 50177 nn_layer_fcnl FC2,FC1,50 50178 nn_layer_fcnl FC3,FC2,50 50179 nn_layer_fcnl FC4,FC3,30 50180 nn_layer_fcnl FC5,FC4,30 50181 nn_layer_fcnl FC6,FC5,3 50182 nn_layer_rename OUT,FC6 50183 nn_loss_mse L,OUT,Y,$1,$2 50184 sp lena,128 nm. img 50185 50186 # Optimize network. 50187 #------------------- 50188 size_batch=1024 50189 repeat inf,_nn_iter 50190 e[] "ITER = "$_nn_iter 50191 50192 # Build mini-batch. 50193 $size_batch,1,1,5," 50194 const ind = $img; 50195 px = u(0,w#ind)%w#ind; 50196 py = u(0,h#ind)%h#ind; 50197 val = I(#$img,px,py,0,0,1); 50198 [ px,py,val ]" 50199 nm. batch 50200 50201 # Mini-batch stochastic gradient descent. 50202 _nn_batch_iteration=0 50203 _nn_is_training=1 50204 repeat 128,batch_iter 50205 eval[batch] *${-nn_lib}" 50206 batch = I; 50207 X = batch[0,2]; # Input 50208 Y = batch[2,3]; "\ # Ground-truth 50209 ${_nn_forward}${_nn_backward}${_nn_update}" 50210 end( 50211 !($batch_iter%20)?print([L_out,nn_learning_rate,L_trend,L_trend_moment]); 50212 ); I" 50213 done 50214 rm[batch] 50215 50216 # Render image from network. 50217 _nn_is_training=0 50218 {img,[w,h]},1,3,*${-nn_lib}" 50219 X = [ x,y ]; 50220 "${_nn_forward}" 50221 cut(OUT_out,0,255)" 50222# on. frame.png,$_nn_iter 50223 w. 600,600 rm. 50224 50225 done 50226 50227#-------------------------------- 50228# Test program for CONV networks. 50229#-------------------------------- 50230nn_test_conv : 50231 50232 # Build neural network. 50233 #---------------------- 50234 nn_init 50235 nn_layer_input X,32,32,1,3 50236 nn_layer_conv2dnl L1,X,3 50237 nn_layer_rename OUT,L1 50238 nn_loss_mse L,OUT,Y 50239 sp lena,32 nm. img 50240 [img] nm. res 50241 50242 # Optimize network. 50243 #------------------- 50244 size_batch=1 50245 repeat inf,_nn_iter 50246 e[] "ITER = "$_nn_iter 50247 50248 _nn_batch_iteration=0 50249 repeat 10,batch_iter 50250 eval ${-nn_lib}" 50251 X = crop(#$img); # Input 50252 Y = crop(#$res); # Ground-truth 50253 "${_nn_forward}${_nn_backward}${_nn_update}" 50254 store(X,'vX',32,32,1,3); 50255 store(Y,'vY',32,32,1,3); 50256 store(OUT_out,'vOUT',32,32,1,3); 50257 run('l[] $vOUT r2dx 200,1 a x w. rm. endl'); 50258 50259 end( 50260 print([L_out,nn_learning_rate]); 50261 ); I" 50262 done 50263 done 50264 50265# nn_layer_res : name,in 50266# Define a custom residual CONV module. 50267nn_layer_res : nn_check_layer "$2" check ${"is_variable_name $1"}" && isint(${3=16}) && $3>0" 50268 nn_layer_clone $1_CL0,$1_CL1,$2 50269 nn_layer_conv2dnl $1_CONV1,$1_CL0,$3 50270 nn_layer_conv2d $1_CONV2,$1_CONV1,{[$_nn_$2_out_size][3]} 50271 nn_layer_add $1_ADD,$1_CONV2,$1_CL1 50272 nn_layer_nl $1,$1_ADD 50273 50274nn_layer_res2 : nn_check_layer "$2" check ${"is_variable_name $1"}" && isint(${3=16}) && $3>0" 50275 nn_layer_clone $1_CL0,$1_CL1,$2 50276 nn_layer_conv2dnl $1_CONV1,$1_CL0,$3 50277 nn_layer_conv2dnl $1_CONV2,$1_CONV1,$3 50278 nn_layer_conv2d $1_CONV3,$1_CONV2,{[$_nn_$2_out_size][3]} 50279 nn_layer_add $1_ADD,$1_CONV3,$1_CL1 50280 nn_layer_nl $1,$1_ADD 50281 50282# Main test procedure. 50283nn_test : skip ${1=1e-4} 50284 50285 # Build neural network. 50286 #---------------------- 50287 if isfile('network.gmz') nn_load network.gmz 50288 else 50289 nn_init 50290 nn_layer_input X,32,32,1,1 50291 nn_unet 50292 nn_loss_mse L,OUT,Y,$1 50293 fi 50294 50295 l[] images.gmz s z luminance n 0,255 +mirror x +mirror y a z endl nm. res 50296 +l[res] s c noise 0 c 0,255 a z endl nm. img 50297 50298 if isfile('stats.gmz') stats.gmz else 0 fi nm. stats 50299 50300 _nn_optimizer=2 50301 50302 # Optimize network. 50303 #------------------ 50304 size_batch=1 50305 repeat inf,iter 50306 e[] "ITER = "$iter 50307 50308 srand 100 50309 50310 # Build mini-batch. 50311 32,32,$size_batch,1 nm. batch_X 50312 32,32,$size_batch,1 nm. batch_Y 50313 1,1,$size_batch,1,"> 50314 const img = $img; 50315 const res = $res; 50316 const siz = 32*32; 50317 p = u<0.15?0:30; 50318 do ( 50319 ni = int(u(d#img))%d#img; 50320 nx = int(u(0,w#img - 1 - 32)); 50321 ny = int(u(0,h#img - 1 - 32)); 50322 X = crop(#img,nx,ny,0,0,32,32,1,1); 50323 Y = crop(#res,nx,ny,0,0,32,32,1,1); 50324 _(while); std(Y)<p); 50325 draw(#$batch_X,X,0,0,z,0,32,32,1,1); 50326 draw(#$batch_Y,Y,0,0,z,0,32,32,1,1)" 50327 rm. 50328 50329 # Mini-batch stochastic gradient. 50330 _nn_is_training=1 50331 _nn_batch_iteration=0 50332 repeat 10,batch_iter 50333 1,1,{batch_X,d},1,*${-nn_lib}" 50334 X = crop(#$batch_X,0,0,z,0,32,32,1,1); 50335 Y = crop(#$batch_Y,0,0,z,0,32,32,1,1); 50336 "${_nn_forward}" 50337 "${_nn_backward}" 50338 "${_nn_update}" 50339 z<4 && !("$batch_iter"%10)?( 50340 var = string(#256,'IN',t); 50341 store(X,var,32,32,1,1); 50342 var = string(#256,'OUT',t); 50343 store(OUT_out,var,32,32,1,1); 50344 var = string(#256,'REF',t); 50345 store(Y,var,32,32,1,1); 50346 run('l[] $IN',t,' $OUT',t,' $REF',t,' c 0,255 a x w',z+1,'. 600,200,0 rm endl'); 50347 ); 50348 end( 50349 print([ sqrt(L_out),nn_learning_rate ]); 50350 set(L_out,'loss'); 50351 set(nn_learning_rate,'nn_learning_rate'); 50352 ); I" 50353 rm. 50354 done 50355 rm[batch_X,batch_Y] 50356 50357 if !($iter%20) nn_save network.gmz fi 50358 l[stats] 50359 ($loss^$nn_learning_rate) 50360 a x 50361 o stats.gmz 50362 endl 50363 50364 # Visualize convolution kernels. 50365# +z[CONV1_0] 0,{CONV1_0,w-2} l. s y n 0,255 repeat $! l[$>] s x,-9 N=$! r {v=sqrt(w);[v,v]},1,1,-1 50366# r2dx 128,1 frame 1,1,0 frame 2,2,200 append_tiles $N endl done a y w6. rm endl 50367 50368 done 50369 50370 50371nn_foo : 50372 l[] 50373 nn_init 50374 network.gmz 50375 nn_layer_input X,64,64,1,1 50376 nn_unet 50377 store network 50378 endl 50379 repeat $! l[$>] 50380 w,h,s={[w,h,s]} 50381 50382 # Extract overlapping 64x64 tiles. 50383 nx,ny={ceil([w,h]/60)} 50384 64,64,{$nx*$ny},$s 50385 1,1,{d},1,"* 50386 const boundary = 1; 50387 ix = z%$nx; 50388 iy = int(z/$nx); 50389 X = round(lerp(-1,$w - 64,ix/($nx-1))); 50390 Y = round(lerp(-1,$h - 64,iy/($ny-1))); 50391 V = crop(#0,X,Y,0,0,64,64,1,"$s"); 50392 draw(#-1,V,0,0,z,0,64,64,1,"$s")" 50393 k.. 50394 50395 # Denoise 64x64 tiles. 50396 $network 50397 1,1,{0,d},1,*${-nn_lib}${_nn_init_forward}" 50398 repeat ("$s",c, 50399 X = crop(#0,0,0,z,c,64,64,1,1);"${_nn_forward}" 50400 draw(#0,OUT_out,0,0,z,c,64,64,1,1); 50401 )" 50402 k[0] 50403 50404 # Reconstruct image from tiles. 50405 $w,$h,1,{$s+1} 50406 1,1,{0,d},1,">begin(one = vector(#(64 - 2)*(64 - 2),1)); 50407 const boundary = 1; 50408 ix = z%$nx; 50409 iy = int(z/$nx); 50410 X = round(lerp(-1,$w - 64,ix/($nx-1))); 50411 Y = round(lerp(-1,$h - 64,iy/($ny-1))); 50412 V = crop(#0,1,1,z,0,64 - 2,64 - 2,1,"$s"); 50413 draw(#1,V,X + 1,Y + 1,0,0,64 - 2,64 - 2,1,"$s",-1); 50414 draw(#1,one,X + 1,Y + 1,0,"$s",64 - 2,64 - 2,1,1,-1)" 50415 k.. 50416 s c,-$s 50417 max. 1 / 50418 c 0,255 50419 50420 endl done 50421 50422nn_unet : 50423 nn_layer_conv2dnl lA,X,64 50424 nn_layer_conv2dnl lB,lA,64 50425 nn_layer_clone lB0,lB1,lB 50426 50427 nn_layer_maxpool2d lC,lB0 50428 nn_layer_conv2dnl lD,lC,128 50429 nn_layer_conv2dnl lE,lD,128 50430 nn_layer_clone lE0,lE1,lE 50431 50432 nn_layer_maxpool2d lF,lE0 50433 nn_layer_conv2dnl lG,lF,256 50434 nn_layer_conv2dnl lH,lG,256 50435 50436 nn_layer_upsample2d lI,lH,1 50437 nn_layer_append lJ,lI,lE1 50438 nn_layer_conv2dnl lK,lJ,128 50439 nn_layer_conv2dnl lL,lK,128 50440 50441 nn_layer_upsample2d lM,lL,1 50442 nn_layer_append lN,lM,lB1 50443 nn_layer_conv2dnl lO,lN,64 50444 nn_layer_conv2dnl lP,lO,64 50445 nn_layer_conv2d OUT,lP,1,1 50446 50447 50448nn_unet_small : 50449 nn_layer_conv2dnl lA,X,8 50450 nn_layer_conv2dnl lB,lA,8 50451 nn_layer_clone lB0,lB1,lB 50452 50453 nn_layer_maxpool2d lC,lB0 50454 nn_layer_conv2dnl lD,lC,16 50455 nn_layer_conv2dnl lE,lD,16 50456 nn_layer_clone lE0,lE1,lE 50457 50458 nn_layer_maxpool2d lF,lE0 50459 nn_layer_conv2dnl lG,lF,32 50460 nn_layer_conv2dnl lH,lG,32 50461 50462 nn_layer_upsample2d lI,lH,1 50463 nn_layer_append lJ,lI,lE1 50464 nn_layer_conv2dnl lK,lJ,16 50465 nn_layer_conv2dnl lL,lK,16 50466 50467 nn_layer_upsample2d lM,lL,1 50468 nn_layer_append lN,lM,lB1 50469 nn_layer_conv2dnl lO,lN,8 50470 nn_layer_conv2dnl lP,lO,8 50471 nn_layer_conv2d OUT,lP,1,1 50472 50473nn_resnet : 50474 nn_layer_conv2d lA,X,16 50475 nn_layer_res lB,lA,16 50476 nn_layer_res lC,lB,16 50477 nn_layer_res lD,lC,16 50478 nn_layer_res lE,lD,16 50479 nn_layer_conv2d lF,lE,1 50480 nn_layer_rename OUT,lF 50481 50482 50483# Local Variables: 50484# mode: sh 50485# End: 50486# 50487# (End of G'MIC custom commands) 50488