I have been working on a command which is aided to create palette when suitable or when requested, in addition to manipulating GUI. This command is named gui_util_pal, it is meant to be used within GUI filters, and this does the work behind the scene. So, I started this thread to see if it works well, and whether there should be new features.
Codewise problem:
_gui_util_pal_set needs to be set via global. Oh well. Not a big deal. Just one of them.
Possible solution involve using BIGINT. I have a few commands that supports numbers much larger than double can store, so I will use this. But really, this makes me want to have BIGINT support within CIMG.h, but you can’t have everything I guess.
Some features I have in mind:
- Built-in HSV manipulation. That means to manipulate existing palettes within gui_util_pal.
- Using palette to change GUI settings via image. Yes, that means passing a palette image, then gui_util_pal will change the color.
GUI Sample:
#@gui GUI Utility Demo Palette Demo:__none__,fx_rep_gui_toolkit_demo
#@gui:_=note("This filter is to demonstrate the use of the cli command <b>gui_util_pal</b> being in used in GUI filters.")
#@gui:_=separator()
#@gui:1.Display Custom Palette Colors=bool(1)
#@gui:2.Multi-Select Palette Color=bool(0)
#@gui:_=separator()
#@gui:3.Delete All Selected Palette=button(0)
#@gui:4.Number of Color=int(4,2,8)
#@gui:5.Old Number of Color=int(4,2,8)
#@gui:_=separator()
#@gui:6.7.8.Palette Color 1=color(247,244,191)
#@gui:9. Delete Color 1 =button(0)
#@gui:10.Color 1 Selected=_bool(0)
#@gui:11.12.13.Palette Color 2=color(255,240,43)
#@gui:14. Delete Color 2 =button(0)
#@gui:15.Color 2 Selected=_bool(0)
#@gui:16.17.18.Palette Color 3=color(255,207,5)
#@gui:19. Delete Color 3 =button(0)
#@gui:20.Color 3 Selected=_bool(0)
#@gui:21.22.23.Palette Color 4=color(255,177,8)
#@gui:24. Delete Color 4 =button(0)
#@gui:25.23.Color 4 Selected=_bool(0)
#@gui:26.27.28.Palette Color 5=color(233,134,39)
#@gui:29. Delete Color 5 =button(0)
#@gui:30.Color 5 Selected=_bool(0)
#@gui:31.32.33.Palette Color 6=color(191,90,62)
#@gui:34. Delete Color 6 =button(0)
#@gui:35.Color 6 Selected=_bool(0)
#@gui:36.37.38.Palette Color 7=color(156,51,39)
#@gui:39. Delete Color 7 =button(0)
#@gui:40.Color 7 Selected=_bool(0)
#@gui:41.42.43.Palette Color 8=color(114,28,3)
#@gui:44. Delete Color 8 =button(0)
#@gui:45.Color 8 Selected=_bool(0)
#@gui:_=separator()
#@gui:46. Add Palette Color =button(0)
#@gui:47.Palette Color Count Change Effect=choice(0,"Random","Farthest","Rescale")
#@gui:48.Mask Size=float(1,.01,1)
#@gui:49.Cube Size=int(29,14,256)
#@gui:50.Interpolation Method A=choice(2,"None","Nearest","Average","Linear","Grid","Bicubic","Lanczos")
#@gui:51.Interpolation Method B=choice(5,"None","Nearest","Average","Linear","Grid","Bicubic","Lanczos")
#@gui:52.Delete All Selected Palette=button(0)
#@gui:53.Old GUI visible=bool(0)
#@gui:54.Old Selection State=bool(0)
#@gui:55.Old Information=text("")
#@gui:56.Old GUI Setting=text("")
fx_rep_gui_toolkit_demo:
skip ${55=},${56=}
## Optional Part - It's up to you to use this ##
farthest_visible,interpolation_visible=0
if $47 ${arg\ $47,farthest_visible,interpolation_visible}=2 fi
## ---------- End of Optional Part ---------- ##
is_gui_visible=$1
allow_multiple_selection=$2
delete_all_selected={$3||$42}
current_number_of_colors={($4+[0,1])[$46]}
old_number_of_colors=$5
method=$47
method_a,method_b:=[0,0,${48-51}][$method*2,2]
old_gui_visible=$53
old_selection_state=$54
_gui_util_pal_set=$56
gui_util_pal ,\ # Your name of palette goes here. Only useful for multiple palette cases
3,\ # Size of Spectrum. Here it is 3
$allow_multiple_selection,\ # This alter whether you are able to select multiple colors at once
$old_selection_state,\ # This enable swapping of selection states
$delete_all_selected,\ # This is a button-related variable to delete checkmarked colors
2,8,\ # 2,8 here are minimum colors possible, and maximum possible color
$old_number_of_colors,$current_number_of_colors,\ # This determines whether current number of colors is different from the old numer of colors
$method,$method_a,$method_b,\ # How changes in palettes are influenced by changes in palette size
$is_gui_visible,\ # Changes in whether palette is visible
$old_gui_visible,\ # Changes in visibility of GUI
0,\ # This setting affects whether new palette is always created
0,\ # This setting skips checking GUI. Useful when using multiple palettes or when avoiding checking GUI when irrelevant GUI button is manipulated.
"$55",\ # Insert numerical argument here. This is old_information.
${6-45} # Associated with Color and Palette related GUI elements
# Below set status variable to a string which then changes GUI output
u "{"$is_gui_visible"}"\
"{"$allow_multiple_selection"}"\
"{0}"\
"{"$_gui_util_pal_color_counts"}"\ # _gui_util_pal_color_counts global variable is created by gui_util_pal. This part is involved in changes of colors which is automatically managed by gui_util_pal
"{"$_gui_util_pal_color_counts"}"\ # Yes, a copy is needed so that another run can check the difference
$_gui_util_pal_set\ # _gui_util_pal_set global variable is created by gui_util_pal. This handles everything related to colors and visibility of colors.
"{0}"_$_gui_util_pal_enable_add_button\ # This affect whether the to enable a button to add a new color into palette
"{$47}"\
"{$48}"_$farthest_visible\
"{$49}"_$farthest_visible\
"{$50}"_$interpolation_visible\
"{$51}"_$interpolation_visible\
"{0}"\
"{"$is_gui_visible"}"\ # Store current Color Selection State
"{"$allow_multiple_selection"}"\ # Store current Multiple Selection Option State
"{"$_gui_util_pal_old_info"}"\ # _gui_util_pal_old_info is created by gui_util_pal. This stores color information only.
"{"$_gui_util_pal_encoded_set"}" # Store GUI setting. This gets pass-through next iteration.
And the relevant companion command:
#@cli gui_util_pal: name,number_of_channels,selection_state,old_selection_state,delete_selected,minimum_number_of_colors,maximum_number_of_colors,current_number_of_colors,new_number_of_colors,method={ 0=random | 1=farthest (slow) | 2=rescale },method_arg_1,method_arg_2,gui_visible,old_gui_visible,always_generate_new_palette,skip_gui_check,0<=color_0_channel_0<=255,0<=color_0_channel_1<=255,0<=color_0_channel_2<=255,...,delete_color_0={ 0=keep | 1=delete_this }...0<=color_n_channel_c<=255,...,delete_color_n={ 0=keep | 1=delete_this }..
#@cli : Command to be used in GUI filter code in conjunction with specific GUI code. This is not for CLI filters except for debugging!
#@cli :
#@cli : Here's a GUI code example.
#@cli : @--------------------------------------@
#@cli : #@gui:Multi-Select Palette Color=bool(0)
#@cli : #@gui:_=separator()
#@cli : #@gui:Delete All Selected Palette=button(0)
#@cli : #@gui:_=separator()
#@cli : #@gui:Palette Color 1=color(247,244,191)
#@cli : #@gui: Delete Color 1 =button(0)
#@cli : #@gui:Color 1 Selected=_bool(0)
#@cli : #@gui:Palette Color 2=color(255,240,43)
#@cli : #@gui: Delete Color 2 =button(0)
#@cli : #@gui:Color 2 Selected=_bool(0)
#@cli : #@gui:Old Information=text("")
#@cli : @--------------------------------------@
#@cli :
#@cli : $ gui_util_pal test,3,0,0,0,1,5,3,3,1,2,1,1,0,0,0,,,216,255,220,1,0,120,160,199,0,0,210,222,230,0,0,150,199,122,0,0,125,240,33,0,0 echo $_gui_util_pal_set_test
#@cli : $ gui_util_pal test,3,0,0,0,1,5,3,5,0,1,29,1,0,0,0,"216,255,220,120,160,199,210,222,230",,216,255,220,1,0,120,160,199,0,0,210,222,230,0,0,150,199,122,0,0,125,240,33,0,0 echo $_gui_util_pal_set_test
gui_util_pal:
skip "${1=}","${11=}","${12=}","${13=}","${14=}","${17=}","${18=}"
old_status=${}
print_global_vars:=same('$_host','cli') # When debugging via CLI, global variables will be printed!
command_args=number_of_channels,\
selection_state,\
old_selection_state,\
delete,\
minimum_number_of_colors,\
maximum_number_of_colors,\
current_number_of_colors,\
new_number_of_colors,\
method,\
method_arg_1,\
method_arg_2,\
gui_visible,\
old_gui_visible,\
always_generate_new_palette,\
skip_gui_check
$command_args=${2-16}
check "isint($number_of_channels,1)
&& isbool($selection_state)
&& isbool($delete)
&& isint($minimum_number_of_colors,1) # && isfinite($minimum_number_of_colors)
&& isint($maximum_number_of_colors,1) # && isfinite($maximum_number_of_colors)
&& isint($current_number_of_colors,1) # && isfinite($current_number_of_colors)
&& isint($current_number_of_colors,$minimum_number_of_colors,$maximum_number_of_colors)
&& isint($method,0,2)
&& narg($gui_visible)"
name=$1
if narg($1)
name..=_
fi
__gui_util_pal_store_global_vars _$0_set$name
_$0_old_info$name=${__gui_util_pal_decode\ $17}
__gui_util_pal_store_global_vars _$0_old_info$name
_$0_create_new_palette$name=0
__gui_util_pal_store_global_vars _$0_create_new_palette$name
if $method==2
interpolation_less_than,\
interpolation_more_than\
=$method_arg_1,$method_arg_2
else
mask_factor,\
cube_size\
=$method_arg_1,$method_arg_2
fi
if !narg(${_$0_old_info$name}) # New Palette From Scratch
_$0_create_new_pal$name=1
(${18--1})
group_spectrum_and_delete_info_size:=$number_of_channels+2
resize. $group_spectrum_and_delete_info_size,{w#-1/$group_spectrum_and_delete_info_size},1,1,-1
crop. 0,{$number_of_channels-1}
permute. yzcx
crop. 0,{$current_number_of_colors-1}
__gui_util_pal_new_gui_output_from_palette
elif $new_number_of_colors!=$current_number_of_colors # Adjust Palette Size
_$0_create_new_pal${name}=1
random,farthest,resize=0,1,2
__gui_util_pal_create_new_pal_from_old_info
if $method==$resize
resize. $new_number_of_colors,100%,100%,100%,${arg\ 1+($new_number_of_colors>$current_number_of_colors),$method_arg_1,$method_arg_2}
round.
cut. 0,255
__gui_util_pal_new_gui_output_from_palette
elif isin($method,$random,$farthest)
if $new_number_of_colors>$current_number_of_colors
rep_nonexistent_colors_pal. {$new_number_of_colors-$current_number_of_colors},1,$method,$method_arg_1,$method_arg_2
rotate. -90
else
crop. 0,{$new_number_of_colors-1}
fi
m __$0_list_of_checkmark_selection:$""=checkmark
__$0_list_of_checkmark_selection {[${18--1}][$number_of_channels,$new_number_of_colors,{$number_of_channels+2}]}
um __$0_list_of_checkmark_selection
__gui_util_pal_new_gui_output_from_palette_and_preserve_state
fi
elif $selection_state!=$old_selection_state
__gui_util_pal_selection_state_switch ${18--1}
elif $skip_gui_check
skip , # This does nothing. Used to skip the GUI check below
else
__gui_util_pal_check_gui_change $selection_state,${18--1}
fi
_$0_old_info$name=${__gui_util_pal_encode\ ${_$0_old_info$name}}
_$0_encoded_set$name:='${_$0_set$name}'
__gui_util_pal_store_global_vars _$0_encoded_set$name
_$0_color_counts$name=$new_number_of_colors
__gui_util_pal_store_global_vars _$0_color_counts$name
_$0_enable_add_button$name:=$gui_visible?1+($new_number_of_colors<$maximum_number_of_colors)
__gui_util_pal_store_global_vars _$0_enable_add_button$name
if $print_global_vars
echo $global_vars
fi
status $old_status
__gui_util_pal_store_global_vars:
if $print_global_vars
if narg($global_vars)
global_vars.=\n$1
else
global_vars.=$1
fi
fi
__gui_util_pal_encode:
($*) uint82base64. rm.
__gui_util_pal_decode:
skip "${1=}"
if narg($1) base642uint8 $1 u {crop(#-1)} rm. fi
__gui_util_pal_new_gui_output_from_palette:
visibility_mode:=$gui_visible<<($new_number_of_colors>$minimum_number_of_colors)
gui_visible<<=1
delete_button_state,select_checkmark:=$selection_state?[0,$visibility_mode]:[$visibility_mode,0]
set,old_info=_gui_util_pal_set$name,_gui_util_pal_old_info$name
$set,$old_info=
sep=
repeat $new_number_of_colors {
current_color={I[#-1,$>]}
$old_info.=$sep$current_color
$set.=\{$current_color\}_$gui_visible
$set.=\{0\}_$delete_button_state
$set.=\{0\}_$select_checkmark
sep=,
}
m=$new_number_of_colors
zero_values_color:=vector(#$number_of_channels,0)
for $m<$maximum_number_of_colors {
$set.=\{$zero_values_color\}_0\{0\}_0\{0\}_0
m+=1
}
__gui_util_pal_new_gui_output_from_palette_and_preserve_state:
visibility_mode:=$gui_visible<<($new_number_of_colors>$minimum_number_of_colors)
delete_button_state,select_checkmark:=$selection_state?[0,$visibility_mode]:[$visibility_mode,0]
set,old_info=_gui_util_pal_set$name,_gui_util_pal_old_info$name
$set,$old_info=
sep=
repeat $new_number_of_colors {
current_color={I[#-1,$>]}
$old_info.=$sep$current_color
$set.=\{$current_color\}_2
$set.=\{${checkmark{$>+1}}\}_$delete_button_state
$set.=\{0\}_$select_checkmark
sep=,
}
zero_values_color:=vector(#$number_of_channels,0)
repeat $maximum_number_of_colors-$new_number_of_colors { $set.=\{$zero_values_color\}_0\{0\}_0\{0\}_0 }
__gui_util_pal_selection_state_switch:
(${1--1})
visibility_mode:=$gui_visible<<($new_number_of_colors>$minimum_number_of_colors)
gui_visible<<=1
delete_button_state,select_checkmark:=$selection_state?[0,$visibility_mode]:[$visibility_mode,0]
set=_gui_util_pal_set$name
$set=
sep=
step_size:=$number_of_channels+2
limit:=$step_size*$current_number_of_colors
current_pos=0
for $current_pos<$limit {
current_color={crop(#-1,$current_pos,0,0,0,$number_of_channels,1,1,1)}
$set.=\{$current_color\}_$visibility_mode
$set.=\{{i[#-1,$current_pos+$number_of_channels]}\}_$delete_button_state
$set.=\{0\}_$select_checkmark
current_pos+=$step_size
}
rm.
zero_values_color:=vector(#$number_of_channels,0)
repeat $maximum_number_of_colors-$new_number_of_colors { $set.=\{$zero_values_color\}_0\{0\}_0\{0\}_0 }
__gui_util_pal_check_gui_change:
create_new_palette=1
$current_number_of_colors,1,1,$number_of_channels
eval "
const number_of_channels=$number_of_channels;
const section_size=number_of_channels+2;
const current_number_of_colors=$current_number_of_colors;
const selection_state=$1;
old_info=["${_gui_util_pal_old_info$name}"];
current_gui_elements=[${2--1}];
color_changed=delete_found=new_number_of_colors=0;
insertion_pos=0;
for(pos=[0,0,number_of_channels+selection_state],pos[0]<size(old_info),pos+=[number_of_channels,section_size,section_size],
current_gui_elements[pos[2]]?(
delete_found=1;
):(
current_gui_color=current_gui_elements[pos[1],number_of_channels];
if(current_gui_color!=old_info[pos[0],number_of_channels],color_changed=1;);
I[#-1,new_number_of_colors]=current_gui_color;
++new_number_of_colors;
);
);
gui_changed=color_changed||delete_found;
set('new_number_of_colors',new_number_of_colors);
set('gui_changed',gui_changed);
"
if $new_number_of_colors<$minimum_number_of_colors
if !$new_number_of_colors
1,1,1,$number_of_channels,v(0,255)
fi
count_of_new_colors:=$minimum_number_of_colors-w#-1
if $count_of_new_colors>0
if $method==2&&($count_of_new_colors>1)
resize. $new_number_of_colors,100%,100%,100%,${arg\ 1+($new_number_of_colors>$current_number_of_colors),$method_arg_1,$method_arg_2}
round.
elif isin($method,0,1)
rep_nonexistent_colors_pal. $count_of_new_colors,1,$method,$method_arg_1,$method_arg_2
rotate. -90
fi
fi
new_number_of_colors=$minimum_number_of_colors
fi
if $gui_changed
crop. 0,{$new_number_of_colors-1}
elif !$always_generate_new_palette
create_new_palette=0
fi
__gui_util_pal_new_gui_output_from_palette
if $create_new_palette
_gui_util_pal_create_new_pal$name=1
else
rm.
fi
__gui_util_pal_create_new_pal_from_old_info:
(${_gui_util_pal_old_info$name})
resize. $number_of_channels,{w#-1/$number_of_channels},1,1,-1
permute. yzcx