G'MIC exercises

I changed | to : and it didn’t fix it. But, I think i’ll stick with the fixed code I made. Easier said than done.

That being said, I would like to call python in gmic and return value executed from python. Any examples? I want to see if I can use python to bypass some limits of gmic.

@grosgood @myselfhimself

Calling those two as they have some experience with python, but myselfhimself might be able to help on calling python to gmic.

For example, I’d like to return the output of number_three this as a image in gmic:

import random
import time

start_time = time.time()

digits=8000
number_one=random.randint(10**(digits - 1), 10**digits - 1)
number_two=random.randint(10**(digits - 1), 10**digits - 1)
number_three=number_one*number_two

print("--- %s seconds ---" % (time.time() - start_time))

Is there a more elegant way of doing this? Ideally, I would like to have a button next to Color with X in it which does the same as “Delete Color” button.

image

GUI Code
#@gui Transfer Color [Reduced Colors]: fx_rep_transfer_color_reduced,fx_rep_transfer_color_reduced_preview
#@gui:_=separator()
#@gui:_=note("<b>Preliminary Setup</b>")
#@gui:Style of Dithering=choice(0,"Indexing","Ordered")
#@gui:Special Effect=choice(0,"None","Horizontal","Vertical")_0
#@gui:Special Effect Factor (%)=float(50,0,100)_0
#@gui:_=separator()
#@gui:_=note("<b>Palette</b>")
#@gui:Palette Method=choice(0,"Premade","Auto","Import","Custom")
#@gui:Palette to Use=choice(10,"BW-{2}","RGB-{3}","B-RGB-{4}","BW-RGB-{5}","CMY-{3}","CMYK-{4}","WCMYK-{5}","RGBCMY-{6}","1-Bit RGB-{8}","Aurora-{256}","Zenit-241","Game Builder Garage: Texture-Sprite Editor Palette-{117}","Duel-{256}","Hocus Pocus-{256}","PLAYPAl-{249}","Sonic Robo Blast 2-{256}","Uzebox-{256}","Andrew Kensler - 16","Andrew Kensler - 32","Andrew Kensler - 54","AAP-Micro 12","AAP-16","AAP-64","AAP-RadiantPLUS-{96}","AAP-SPLENDOR128","AAP-DGA16","Cheerful-32","DB8","DB16","DB32","DB-ISO22","DimWiddy 17","DimWiddy 23","Endesga-4","Endesga-8","Endesga-16","Endesga-32","Endesga-36","Endesga-64","Famicube","Juicy-32","Juicy-56","XAIUE-22","15P-DX","20P-DX","24P-DX","Cabana-64","Fantasy 16","Fantasy 24","Tranquil Fantasy 23","Tranquility Plus 39","Faraway 48","Fleja Master Palette","Koni32","Linear Color Palette Basic","LEGO colors-{43}","Lego Colours 2021-{40}","Vines Flexible Linear Ramps-{38}","Arcade Standard 29","ARQ16","Atom-8","BLK 36","BLK-NEO","Broken Facility-{40}","Bubblegum-16","CPC BOY-{32}","Cade 15","Calder 8","CD-BAC-{16}","CG Arne-{16}","Dinoknight 16","||||-22","FZT Ethereal 16","Indecision-{17}","Island Joy 16","Journey-{64}","Shallowmarsh26","Lago Nenufar [Lake Water Lily]-{19}","Juicy 17","ChocolateGanache-{96}","Bright Winter 1-{74}","Bright Winter 2-{83}","Kawaii16","0xdb-01-{17}","GZXP-{11}","Chromatic16","Piet-{20}","Matrix-{96}","Material Design-{96}","Rainbow A-{88}","Rainbow B-{96}","SCRJ-XXXVI-{36}","Pxls Default-{32}","Moderna-{24}","Oak21-{21}","Nature's Embrace 55","RBYPGO-{94}","New Worlds 46","Nauris-16","Dynamite-{40}","Interstate 28","Downgraded 32","Pear 36","Pineapple 32","Peachy Pop 16","Resurrect 32","Rosy 42","SLSO-CLR17","Softy 15","SPEC12","The Roarin 80s-{8}","Starmancer-{52}","SuperFuture25","SUNSHINE 35","Sweetie 16","Calm 48","Optimism-{32}","Taffy 16","Todayland Palette V2-{25}","TriRampo-{12}","r\place 2022-{32}","Tropical Cone 24","Vivid-17","SHIDO50+-{72}","Intacto14","Itatsi-{23}","ENOS16","Grixel Grotto-{16}","Superb 8","Undertones-17","Tango-{28}","Cheese Palette-{28}","Equpix 15","Zughy 32","Voodo34","Franzston 30","Night 16","Star 29","Star 34","Still-Life-{14}","SimpleJPC-16","Acid 15","Battery 24","Clumpy 18","Cthulhu-{16}","Crimso 11-{16}","Copper-Tech-{16}","DRZ15A-{15}","Eggy 15","Europa 16","GreyT-bit-{8}","Jewel-{15}","Polar 11","Sheltzy 32","Wyrm 24","Yume Nikki-{24}","Rube-Goldberg-{9}","BoomBoom-{7}","Generic-8","Crayola Blind-{9}","Matriax8c","NT1H-{26}","JerryPie 22","Nineties Nine-{9}","On70-{35}","ANB16","Retrocal-8","Punolit-{21}","Luap 40","Autum Villan 6","Autum 15","Autum 15 [Yellow]","Galaxy Flame-{16}","Antiquity16","Mushroom-{14}","Aerugo-{32}","Hotel Paintings 6","Nopal-12","Brightness GPY-{3}","Blessing-{5}","Fairydust 8","Fuzzy Four-{4}","Fairy Tales-{8}","Naji 16","Easter Island-{16}","Pastel and Darks 58","17 Pastels","NOSTALGIA15","Ocaso-{17}","Oh Hell Pastel-{15}","Pollen-8","KULE-16","Hydrangea 11","Fluffy8","ST 8 R&B Remake","Neon Space-{10}","Cyclope6","Sy17","Syz15","TUI-15","Cave-{8}","Psygnosia-{16}","MarshMellow32","Lost Century 24","Finlal 11","Industrial Factory 16","Murder Mystery 16","Fate & Destiny 12","Vinik 24","YKB-22","Halloween-{7}","Graveyard-21","Steam Lords-{16}","Frostical-{18}","DeuteroSpill-{9}","Cool Bone 7","Muted Ally 6","EPHEMERA-{12}","Ink-{5}","Violet Dreams-{8}","Tinyfolks-{5}","Old Gold 7","Rosemoss-8","AAP-RadiantXV-{15}","AAP-Majesty XVII-{17}","Dead Weight-8","Mojave20","Petite-8","Petite-8 Afterdark","XAIUE-Radiant-{22}","Daruda 22","Firestorm-{9}","Borkfest-{8}","Spicy 07","Rust-6","Apricot-{6}","SuperNova 7","Pastry-{5}","Sandy 06","Illumination-{5}","NYX8","Dream Haze 8","OIL6","Regal10","Soft Demon 7","SGM-Palette 2-{17}","Midnight ablaze-{7}","Black Cherry-{5}","Sunset Red-{5}","INKPINK-{6}","Brash Pink-{5}","Pink Neon Sign 6","Enchanted Purple-{12}","Arch-{11}","Spacey Easter-{17}","Fornax Void I-{256}","Fornax Void II-{128}","Pixelwave-{12}","S1-6","Berry Nebula-{8}","ABYSS-9","Moonlight 15","Moonlit-39","H2O-{10}","Magic Waters 9","Bluem0ld-{4}","Moss-{5}","DEEP MAZE-{7}","Toxic Slime-{5}","Lush Green-{6}","Tsunami-{5}","Cryptic Ocean-{6}","Marsh Madness-{5}","OXYD-{8}","Pink&Green-{8}","Walking in the Woods 8","Paper 8","Sahara Pastell-{7}","Sunflower Painting 7","Art Hoe Aesthetic 7","Sky5-{8}","Ocean Glass-{8}","RoyalGuard-{6}","Eulbink-{8}","Winter Wonderland-{8}","Moon Squid 7","Stratus-{5}","Arctic Dust-{5}","CL8UDS","Lilac Skies 5","Sea of Fire-{6}","Autochrome 3","Autochrome 5","GB Default 1-{4}","GB Default 2-{4}","GB Andrade-{4}","GB Blue Seni-{4}","GB Blackzone-{4}","GB Suburb-{4}","GB Crimson-{4}","GB Didi-{4}","GB Dirty-{4}","GB Arne-{4}","GB Easy-{4}","GB Forest-{4}","GB Harsh Green-{4}","GB Light Green-{4}","GB Nostalgia-{4}","GB Platinum-{4}","GB Kirokaze-{4}","GB Cyber-{4}","GB Wish-{4}","GB Grapefruit-{4}","GB Ice Cream-{4}","GB Red_Blue-{4}","Gold GB-{4}","GB Chocolate-{4}","GB Gray-{4}","GB Spacehaze-{4}","GB Purple Dawn-{4}","Moon Crystal-{4}","ARNE4","Autumn Chill-{4}","CherryMelon-{4}","HallowPumpkin-{4}","Hollow-{4}","Lavender4","MAW-{4}","Voltage Warning-{4}","Tritanopia-{4}","Rabbit 7-{4}","Amiga 2600 NTSC-{128}","Amiga 2600 PAL-{108}","Amiga 2600 SECAM-{8}","Amiga 7800 M.E.S.S-{256}","Amiga 7800-{256}","Amstrad CPC-{27}","Apple II-{15}","Atari 8-Bit Series-{256}","CGA-{16}","CGA Mode 0 [Low]-{4}","CGA Mode 0 [High]-{4}","CGA Mode 1 [Low]-{4}","CGA Mode 1 [High]-{4}","CGA Mode 2 [Low]-{4}","CGA Mode 2 [High]-{4}","C64[Pepto]-{16}","C64[Colodore]-{16}","Commodore VIC-20-{16}","Colecovision-{15}","Japanese Machine Palette-{16}","Macintosh II-{16}","Macintosh 8-Bit System-{256}","MSX-{15}","NES-{55}","PICO-8-{16}","RISC OS-{16}","SAM Coupe-{128}","Thomson MO5-{16}","TRS-80 Color Computer Palette-{4}","Virtual Boy interpreted-{4}","VGA-{256}","Win95-{256}","ZX Spectrum-{15}","GNOME 32","Electronic Crayon 22","Chip16","Deluxe Paint-{222}","FlatUI-{20}","MakeCode Arcade Palette-{15}","Oekaki-{20}","Legacy Paint-{16}","XP Paint-{28}","Vista Paint-{28}","Human Faces-{94}","MadjikHSV-{96}","ST24 Christmas","Reds-{24}","Dullish Rainbow-{6}")
#@gui:Send to Custom Palette=button()
#@gui:Import Palette File=file()
#@gui:Number of Color=int(8,2,256)
#@gui:Display Custom Palette Colors=bool(1)
#@gui:Color 1=color(247,244,191)
#@gui:Delete Color 1=button()
#@gui:Color 2=color(255,240,43)
#@gui:Delete Color 2=button()
#@gui:Color 3=color(255,207,5)
#@gui:Delete Color 3=button()
#@gui:Color 4=color(255,177,8)
#@gui:Delete Color 4=button()
#@gui:Color 5=color(233,134,39)
#@gui:Delete Color 5=button()
#@gui:Color 6=color(191,90,62)
#@gui:Delete Color 6=button()
#@gui:Color 7=color(156,51,39)
#@gui:Delete Color 7=button()
#@gui:Color 8=color(114,28,3)
#@gui:Delete Color 8=button()
#@gui:Color 9=color(255,226,207)
#@gui:Delete Color 9=button()
#@gui:Color 10=color(212,174,170)
#@gui:Delete Color 10=button()
fx_rep_transfer_color_reduced:
skip "$*"
error devel
fx_rep_transfer_color_reduced_preview:
skip "$*"

I made a issue to this as I don’t see an out to this in its current state - https://github.com/c-koi/gmic-qt/issues/158

Also, saving the gui code generator here -

C:\Windows\System32>gmic +pal duel mirror x repeat w echo \"\#@gui:Color \"{"$>"+1}=color({I("$>")}) echo \"\#@gui:Delete Color \"{"$>"+1}=button() done

Looking into the solution, I spot this in Colormap:

#@gui :1st Color=color(#000000)_0
#@gui :2nd Color=color(#ffffff)_0
#@gui :3rd Color=color(#ff0000)_0
#@gui :4th Color=color(#00ff00)_0
#@gui :5th Color=color(#0000ff)_0
#@gui :6th Color=color(#ffff00)_0
#@gui :7th Color=color(#ff00ff)_0
#@gui :8th Color=color(#00ffff)_0+

But, it doesn’t have that plus thing on the GUI.

Quick-and-dirty reply: forgive me, no examples — just a brief sketch of the idea.
rethree.py:

import sys

sys.exit(3)

passes an unsigned, eight bit quantity to the shell: its process exit status. In this example, it is equal to 3, aka: 0x00000011. If G’MIC executes this python fragment in the context of exec, then the process exit status appears in G’MIC in ${} as a sixteen bit unsigned with the one byte process exit status right-padded with a zero byte. It is not clear to me why that is so. However:

$ gmic x 0,'./retthree.py' '({${}/256})'

creates a one pixel image, set to the status value. Division by 256 is to right-shift the bits eight places.

If I wanted to exchange bytes at wholesale volumes, I’d create a temporary file name in G’MIC, pass it as an argument to the python script, run it via exec, which creates the file, fills it with data, then closes it. When exec finishes, I query the filesystem through G’MIC if the temporary file actually exists, and if it does, open it.

Hope this helps. Time to get in the subway…

1 Like

Every little help. However, 0-255 sys output seem limited. Do I really need to create temp file to get around that limitation?

On the python side, you are probably looking for something like mmap, which wraps around a lower level system call. For linux: mmap; I’m sure Windows has something similar.

Difficulty is, so far as i know, G’MIC pretty much seals off low-level file opening-and-closing from the command line interpreter; And, on the G’MIC side, the closest thing to direct memory manipulation are math expression vectors, but I do not see any mechanism to ensure that the memory block backing a vector also corresponds to the memory block of the mapped file — assuming you could map a file in G’MIC in the first place. Methinks G’MIC is not built for sharing a block of memory between processes.

I should pay more attention to what you have been doing here — but `tis a busy time here in NYC. I’ll try to catch up.

1 Like

You’re not actually missing much. At the moment, I’m in a long process of refactoring and improving existing code. A few new filters, and tools (this one doesn’t output anything as opposed to filters) on the GUI side of thing. In the latest quest of improvement as of now, an upgraded GUI filter will have over 1300+ variables.

Here is a more interesting example along the lines of exchanging bytes at wholesale volumes:

  1. Create a temporary file name in G’MIC,
  2. Pass it as an argument to the python script that is run by exec
  3. Python creates the file with the file name given by G’MIC , fills it with data, then closes it.
  4. Following exec G’MIC checks if a file with the temporary file name actually exists.
  5. If it does, G’MIC opens it – here, as a 2 × n comma separated values file and runs with it.

The use case is giving G’MIC access to Structured Vector Graphics data through a delegate, a Python script which has access to svgpathtools, a pretty mature and robust module for accessing SVG files. The motivation for reaching out to Python is not performance, but accessing functionality — right now! — without re-inventing that particular wheel in G’MIC.

Here’s the Python delegate, svghelper.py:

svghelper.py
 #! /usr/bin/python

import argparse
import svgpathtools
import sys

RESOL = 10

def normalize(dest) :
    """deset: Scale the dataset so that the greatest translation
       goes to 1.0; center of gravity goes to origin."""
    # Center of gravity
    xc     = yc = 0.0
    dl     = len(dset)
    min_r  = sys.maxsize
    max_r  = -sys.maxsize
    min_i  = sys.maxsize
    max_i  = -sys.maxsize
    
    for k in range(0, dl, 1) :
        xc += dset[k].real
        yc += dset[k].imag
        if min_r > dset[k].real :
            min_r = dset[k].real
        if max_r < dset[k].real :
            max_r = dset[k].real
        if min_i > dset[k].imag :
            min_i = dset[k].imag
        if max_i < dset[k].imag :
            max_i = dset[k].imag
    cen  = complex(xc/dl, yc/dl)
    ur   = complex(max_r, max_i)
    ll   = complex(min_r, min_i)
    maxd = abs(ur - ll)
    for k in range(0, dl, 1) :
        dset[k]     = (dset[k] - cen)/maxd 

if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='Plot points from SVG Path.')
    parser.add_argument('-d', '--density', type=int, action='store',  help='Plot point quantity as powers of two; 4 → 2⁴ → 16. Larger → denser. Defaults to 10 (1024)', default=RESOL)
    parser.add_argument('-o', '--output',  type=str, action='store',  help='Text file for output plots.')
    parser.add_argument('-n', '--normalize',         action='store_const', const='y', default=None, help='Normalize plots. (1) Center of gravity maps to origin. (2) Scaling of largest distance to 1, (3) Preserves aspect ratio.')
    parser.add_argument('fname', type=str, nargs=1, help='SVG file, 1.1 or lower')
    args=parser.parse_args()
    fresolv      = 2**int(args.density)
    paths, attrs = svgpathtools.svg2paths(args.fname[0])
    path_0       = paths[0]
    scale        = 1.0/(fresolv-1)
    dset         = [path_0.point(k).conjugate() for k in [scale*j for j in range(fresolv)]]
    if type(args.normalize) == type('y') and args.normalize == 'y':
        normalize(dset)
    fd           = open(args.output, 'w', encoding='UTF-8')
    for i in range(len(dset)):
        fd.write("{0:03.9g},{1:03.9g}\n".format(dset[i].real, dset[i].imag))
    fd.close()
args.output[0]

This G’MIC module uses svghelper.py to read an SVG file and compute plots. Coupling between G’MIC and Python is very loose — they exchange a temporary file and have no idea or concern how the other operates. G’MIC’s exec runs Python as a child process and rendezvous on the temporary file. To the extent that there is coordination between the two, it’s the agreement that the rendezvous file follows a text-based, comma separated value format. G’MIC has a dedicated reader for .csv files.

svg2plots.gmic
#@cli gtutor_getsvg : "file",_resolution
#@cli (1) Retrieve the first path in the SVG 1.1 $file
#@cli argument and render it (2) at the indicated
#@cli resolution, a power of 2: $_resolution = 8 → 2⁸ → 256.
#@cli Resolution defaults to 10; paths are plotted
#@cli with 1,204 points.
gtutor_getsvg:
   check "isfile('${1}') && isint(${2=10}) && ${2}>0"

   # Python helper writes plots to a text file.
   # We furnish a temporary file to receive its
   # output.
   
      file_rand
      outfile=${}
      fname=$1
      res=$2
   
      # Put "svghelper.py" in a folder on your path.
      # Mark it executable.
      # See svghelper.py for details.
   
       helpercommand="svghelper.py                \
                      --normalize                 \
                      --density "$res"            \
                      --output "$outfile" "$fname
    
       exec $helpercommand
       if !isfile('$outfile')
          error "Could not process "$outfile"!"
       fi
       input_csv $outfile,0
       delete $outfile


#@cli gtutor_plot : [plotdata]
#@cli Draw on the selected image the polygon plotted on an
#@cli origin-centered unit square with the diagonal
#@cli [-1,-1]…[1,1].
gtutor_plot :
      is_img=${"is_image_arg $1"}
      if ${is_img}
         pass$1
         => canvas,plotdata
      else
         error "Provide image parameter."
      fi
      sz={0.9*min(w#$canvas,h#$canvas)}
      ox={(w#$canvas-$sz)/2}
      oy={(h#$canvas-$sz)/2}
      permute[plotdata] cyzx
      fill[plotdata] "begin(
                        sw=get('sz');
                        ox=get('ox');
                        oy=get('oy');
                        id=eye(3);
                        id[0]=sw;
                        id[2]=ox+sw/2;
                        id[4]=-sw;
                        id[5]=sw/2+oy;
                       );
                  (id*[I(x,y),1])[0,2]
                 "
      permute[plotdata] cyzx
      eval[canvas] "begin(PV=crop(#$plotdata);
                    polygon(#$canvas,
                            -int(size(PV)/2),
                            PV,
                            1,
                            0xffffffff,
                            255
                           )
                         )
                   "
      keep[canvas]

Here’s a typical command line:

gmic svg2plots.gmic gtutor_getsvg "ampersand_circ.svg",10 1024,1024,1,1 gtutor_plot. [-2] keep[-1]

Here’s a SVG play file — yes, the dreaded Goudy Bookletter 1911 ampersand, which I will never cease afflicting on people.

ampersand_circ

That’s it for now. There’s a half-baked tutorial on this Python - G`MIC exchange on the skids, coming down the ways I-don’t-know-when. Tomorrow looks quiet. Might get some writing done.

2 Likes

I will have to look at the tutorial later. Also, this tutorial might solve the long standing thread I made ago in which I asked for Python users help.

How should I simplify this?

Note that color_n has 3 variables and each 3 variables are next to each other. Each group of variables are separated by 5.

  color_1=${27-29}
  color_2=${32-34}
  color_3=${37-39}
  color_4=${42-44}
  color_5=${47-49}
  color_6=${52-54}
  color_7=${57-59}
  color_8=${62-64}
  color_9=${67-69}
  color_10=${72-74}
  color_11=${77-79}
  color_12=${82-84}
  color_13=${87-89}
  color_14=${92-94}
  color_15=${97-99}
  color_16=${102-104}
  color_17=${107-109}
  color_18=${112-114}
  color_19=${117-119}
  color_20=${122-124}
  color_21=${127-129}
  color_22=${132-134}
  color_23=${137-139}
  color_24=${142-144}
  color_25=${147-149}
  color_26=${152-154}
  color_27=${157-159}
  color_28=${162-164}
  color_29=${167-169}
  color_30=${172-174}
  color_31=${177-179}
  color_32=${182-184}
  color_33=${187-189}
  color_34=${192-194}
  color_35=${197-199}
  color_36=${202-204}
  color_37=${207-209}
  color_38=${212-214}
  color_39=${217-219}
  color_40=${222-224}
  color_41=${227-229}
  color_42=${232-234}
  color_43=${237-239}
  color_44=${242-244}
  color_45=${247-249}
  color_46=${252-254}
  color_47=${257-259}
  color_48=${262-264}
  color_49=${267-269}
  color_50=${272-274}
  color_51=${277-279}
  color_52=${282-284}
  color_53=${287-289}
  color_54=${292-294}
  color_55=${297-299}
  color_56=${302-304}
  color_57=${307-309}
  color_58=${312-314}
  color_59=${317-319}
  color_60=${322-324}
  color_61=${327-329}
  color_62=${332-334}
  color_63=${337-339}
  color_64=${342-344}
  color_65=${347-349}
  color_66=${352-354}
  color_67=${357-359}
  color_68=${362-364}
  color_69=${367-369}
  color_70=${372-374}
  color_71=${377-379}
  color_72=${382-384}
  color_73=${387-389}
  color_74=${392-394}
  color_75=${397-399}
  color_76=${402-404}
  color_77=${407-409}
  color_78=${412-414}
  color_79=${417-419}
  color_80=${422-424}
  color_81=${427-429}
  color_82=${432-434}
  color_83=${437-439}
  color_84=${442-444}
  color_85=${447-449}
  color_86=${452-454}
  color_87=${457-459}
  color_88=${462-464}
  color_89=${467-469}
  color_90=${472-474}
  color_91=${477-479}
  color_92=${482-484}
  color_93=${487-489}
  color_94=${492-494}
  color_95=${497-499}
  color_96=${502-504}
  color_97=${507-509}
  color_98=${512-514}
  color_99=${517-519}
  color_100=${522-524}
  color_101=${527-529}
  color_102=${532-534}
  color_103=${537-539}
  color_104=${542-544}
  color_105=${547-549}
  color_106=${552-554}
  color_107=${557-559}
  color_108=${562-564}
  color_109=${567-569}
  color_110=${572-574}
  color_111=${577-579}
  color_112=${582-584}
  color_113=${587-589}
  color_114=${592-594}
  color_115=${597-599}
  color_116=${602-604}
  color_117=${607-609}
  color_118=${612-614}
  color_119=${617-619}
  color_120=${622-624}
  color_121=${627-629}
  color_122=${632-634}
  color_123=${637-639}
  color_124=${642-644}
  color_125=${647-649}
  color_126=${652-654}
  color_127=${657-659}
  color_128=${662-664}
  color_129=${667-669}
  color_130=${672-674}
  color_131=${677-679}
  color_132=${682-684}
  color_133=${687-689}
  color_134=${692-694}
  color_135=${697-699}
  color_136=${702-704}
  color_137=${707-709}
  color_138=${712-714}
  color_139=${717-719}
  color_140=${722-724}
  color_141=${727-729}
  color_142=${732-734}
  color_143=${737-739}
  color_144=${742-744}
  color_145=${747-749}
  color_146=${752-754}
  color_147=${757-759}
  color_148=${762-764}
  color_149=${767-769}
  color_150=${772-774}
  color_151=${777-779}
  color_152=${782-784}
  color_153=${787-789}
  color_154=${792-794}
  color_155=${797-799}
  color_156=${802-804}
  color_157=${807-809}
  color_158=${812-814}
  color_159=${817-819}
  color_160=${822-824}
  color_161=${827-829}
  color_162=${832-834}
  color_163=${837-839}
  color_164=${842-844}
  color_165=${847-849}
  color_166=${852-854}
  color_167=${857-859}
  color_168=${862-864}
  color_169=${867-869}
  color_170=${872-874}
  color_171=${877-879}
  color_172=${882-884}
  color_173=${887-889}
  color_174=${892-894}
  color_175=${897-899}
  color_176=${902-904}
  color_177=${907-909}
  color_178=${912-914}
  color_179=${917-919}
  color_180=${922-924}
  color_181=${927-929}
  color_182=${932-934}
  color_183=${937-939}
  color_184=${942-944}
  color_185=${947-949}
  color_186=${952-954}
  color_187=${957-959}
  color_188=${962-964}
  color_189=${967-969}
  color_190=${972-974}
  color_191=${977-979}
  color_192=${982-984}
  color_193=${987-989}
  color_194=${992-994}
  color_195=${997-999}
  color_196=${1002-1004}
  color_197=${1007-1009}
  color_198=${1012-1014}
  color_199=${1017-1019}
  color_200=${1022-1024}
  color_201=${1027-1029}
  color_202=${1032-1034}
  color_203=${1037-1039}
  color_204=${1042-1044}
  color_205=${1047-1049}
  color_206=${1052-1054}
  color_207=${1057-1059}
  color_208=${1062-1064}
  color_209=${1067-1069}
  color_210=${1072-1074}
  color_211=${1077-1079}
  color_212=${1082-1084}
  color_213=${1087-1089}
  color_214=${1092-1094}
  color_215=${1097-1099}
  color_216=${1102-1104}
  color_217=${1107-1109}
  color_218=${1112-1114}
  color_219=${1117-1119}
  color_220=${1122-1124}
  color_221=${1127-1129}
  color_222=${1132-1134}
  color_223=${1137-1139}
  color_224=${1142-1144}
  color_225=${1147-1149}
  color_226=${1152-1154}
  color_227=${1157-1159}
  color_228=${1162-1164}
  color_229=${1167-1169}
  color_230=${1172-1174}
  color_231=${1177-1179}
  color_232=${1182-1184}
  color_233=${1187-1189}
  color_234=${1192-1194}
  color_235=${1197-1199}
  color_236=${1202-1204}
  color_237=${1207-1209}
  color_238=${1212-1214}
  color_239=${1217-1219}
  color_240=${1222-1224}
  color_241=${1227-1229}
  color_242=${1232-1234}
  color_243=${1237-1239}
  color_244=${1242-1244}
  color_245=${1247-1249}
  color_246=${1252-1254}
  color_247=${1257-1259}
  color_248=${1262-1264}
  color_249=${1267-1269}
  color_250=${1272-1274}
  color_251=${1277-1279}
  color_252=${1282-1284}
  color_253=${1287-1289}
  color_254=${1292-1294}
  color_255=${1297-1299}
  color_256=${1302-1304}

Do you mean you want to condense this code? If so, wouldn’t looping work?

Yes, I would like to condense the code.

The solution I came up with:

(${27-1306})
split. x,-5
a[-256--1] y
permute. yzcx
channels. 0,2
repeat 256 {
 p={$>+1}
 color_$p={I(#-1,$>)}
}
rm.

Is there another way?

Something like this ?

  (${27-1304})
  l. { s x,-3 foreach color_$>={^} } rm }

Or, (probably faster):

  (${27-1304})
  repeat w/3 { color_$>:=crop(3*$>,3) } rm.

I remember @afre and @garagecoder talked about reordering images on a list given permutation.

Let’s say the inputs were 2,0,1 on a 3 images list.

[0] → move to [1]
[1] → move to [2]
[2] → move to [0]

How should this be done again?

I made a command for that but it has long since been broken by the multiplicity of updates. Feel free to make your own. As usual, show your work here and any one of us will be glad to nudge you in the right direction.

I think I’m on the right-direction though it eliminates names which I don’t like, but alas here goes:

$ sp tiger s x,3 name[0] 2 name[1] 0 name[2] 1 +sort_list +,n

In your case, my command still works:

sp tiger s x,3 nm good,evening,rep afre_reorder 2,0,1

(I haven’t checked my commands in a while but I was sure it had issues…)

There does seem to be an answer here: Permute the elements of an array following given order - GeeksforGeeks

Just gotta figure out how to implement it.

Didn’t do the above, best attempt here:

#@cli rep_reorder: permutation
#@cli : Reposition images according to a list of values of any length. Must be positive integers with no repeat (including 0), and fits in [0-num_of_vars).
rep_reorder:
if $#!=$! error inv_args_cnt fi

if $#>1
 if sort([$*])==expr('x',$#)
  if [$*]==expr('x',$#) return
  else
   dec_imgs={$!-1}
   (${1--1})
   ({expr('x',$#)})
   repeat $dec_imgs {
    move[{i(#-1,i(#-2,$>))}] {$>}
    eval "swap(i(#-1,i(#-2,$>)),i(#-1,$>))"
   }
   rm[-2,-1]
  fi
 else
  error inv_args
 fi
fi
C:\Windows\System32>gmic (0,1,2,3,4,5,6) s x rep_reorder 3,2,1,5,0,6,4 a x
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Input image at position 0, with values (0,1,2,3,4,5,6) (1 image 7x1x1x1).
[gmic]-1./ Split image [0] along the 'x'-axis.
[gmic_math_parser] crop(#-1) = (uninitialized) (compiled as 'vector7', memslot = 34)
[gmic_math_parser] crop(#-1) = [ 4,1,2,5,3,6,0 ] (size: 7)
[gmic]-7./ Append images [0,1,2,3,4,5,6] along the 'x'-axis, with alignment 0.
[gmic]-1./ Display image [0] = '(0,1,2,3,4,5,6)_c1'.
[0] = '(0,1,2,3,4,5,6)_c1':
  size = (7,1,1,1) [28 b of float32].
  data = (3,1,0,5,2,6,4).
  min = 0, max = 6, mean = 3, std = 2.16025, coords_min = (2,0,0,0), coords_max = (5,0,0,0).
[gmic]-1./ End G'MIC interpreter.

Is there a easy way to check which variables with math parser is like a constant? I mean, checking which one could likely be moved to const without error?

Well, a constant is :

  • either an explicit value, like const a = 0.23.
  • or an expression that involves only constants, like const b = max(0,1,abs(5-cos(4)),sqrt(a))

It’s a value that can be evaluated as a regular number at compile time (when the math parser compiles the expression into bytecodes).

I know what a const is, what I would like to know if there is a easy way to check which variables in math parser code can be changed to a const without errors.