Hmm, the solution is to change the picture input. But, that’s up to the user. I ended up making the decision to simply remove RYB indexing. There’s CMYK mode, but I put it as last option for the CLI filter because almost no one is going to use that, and it’s there because I do have a policy to support CMYK mode as a option as it isn’t intrusive if it isn’t accessible or rarely used.
I think I’m finished with the CLI version of Photomosaic. GUI is next to be addressed. One can play with the code:
CLI version of Photomosaic Index
#@cli rep_photomosaic_index: { foldername | [images] },tile_width>0,tile_height>0,0<=_dithering[%]<=100%,_channel_indexing_mode={ 0=color_only | 1=all_channels | all_channels_alpha_max },_alpha_threshold>=0,_crop_alpha_mode={ 0=no_changes | 1=crop_to_alpha_then_crop_to_dim | 2=resize_alp_img_to_fit },_use_alpha_on_imp_imgs={ 0=do_not_use_alp | 1=use_alp_on_imp_imgs },_tile_out_of_boundary_mode={ 0=none | 1=neumann | 2=periodic | 3=continuous },_image_boundary={ 0=neumann | 1=periodic | 2=mirror },_max_alpha_value,_cmyk_mode={ 0=rgb | 1=cmyk }
#@cli : Generate Photographic Mosaic using the indexing approach. This means to generate a picture from multiple set of picture to match target picture(s) using indexed color as reference. The color are chosen by dithering. CMYK is supported by this filter.
#@cli :
#@cli : -----
#@cli : dithering refers to the degree of error diffusion for indexing color
#@cli : _channel_indexing_mode is the mode in which the tiles are assigned into the image
#@cli : _alpha_threshold determines how dithering within alpha, and all tiles are set to the maximum alpha. Only active if and only if variable is set.
#@cli : _crop_alpha_mode determines how input images are to be cropped.
#@cli : _use_alpha_on_imp_imgs is used to determine whether alpha is to be used in the final image.
#@cli : _tile_out_of_boundary_mode is used to determine how out-of-boundary pixels are treated per tiles.
#@cli : _image_boundary refers to how images pixels are treated out-of-boundary in case of tiles not fitting exactly onto the image.
#@cli : _max_alpha_value refers to the maximum alpha value.
#@cli : _cmyk_mode is used to tell the filter to assume images are CMYK in case of 4 channels. 5 Channels is already treated as CMYKA regardless of this setting.
#@cli : -----
#@cli :
#@cli : Author: Reptorian.
#@cli : Default values: 'dithering=100%','_channel_indexing_mode=2','_alpha_threshold=n/a','_crop_alpha_mode=2','_use_alpha_on_imp_imgs=1','_tile_out_of_boundary_mode=0','image_boundary=2','_max_alpha_value=255','_cmyk_mode=0'
rep_photomosaic_index:
skip ${2=},${3=},${4=100%},${5=1},${6=},${7=2},${8=1},${9=0},${10=2},${11=255},${12=0}
# Preliminary variables for use for later. Preliminary condition to make things easier.
remove_duplicates
is_img_arg=${is_image_arg\ $1}
t_w_arg,t_h_arg,dithering,channel_indexing_mode,use_thresholded_alpha_on_target_images,crop_alpha_mode,use_alpha_on_imp_imgs,tile_out_of_boundary_mode,image_boundary,max_alpha_value,use_cmyk_mode={[narg($2)?round(abs($2)),narg($3)?round(abs($3)),cut($4,0,1),int($5)%3,narg($6),int($7)%3,$8&1,int($9)%4,($10%3)+1,$11?abs($11):255,$12&1]}
multi_channel_alpha_maximum_indexing={$channel_indexing_mode==2}
generate_extra_image={$use_alpha_on_imp_imgs?($multi_channel_alpha_maximum_indexing&&!$use_thresholded_alpha_on_target_images)}
imp_imgs_contain_five,number_of_color_channels={[0,3+($use_cmyk_mode?1)]}
if $use_thresholded_alpha_on_target_images
alpha_threshold_dither={cut(abs($7),0,1)}
fi
foreach {
variance=0
image_contain_alpha:=s==2||s>3
repeat s {
shared $<
if iv
rm.
variance=1 break
else
if !$>&&$image_contain_alpha
if !im rm. break fi
if im<0 error alpha_>=0==F fi
fi
fi
rm.
}
if !$variance rm fi # 2a. Remove image if the image contains a single color or if image contains alpha of value zero
}
init_imgs,d_imgs={$!-[0,1]}
names_of_images=${lof\ n}
# 1. Make a list of all images with depth of 1 and make a list of color mode arrays, and check if any images contain alpha.
if $init_imgs>1
1 => target_images_list
1 => spectrum_count_list
eval "
const use_cmyk_mode=$use_cmyk_mode;
const target_images_list=$target_images_list;
const spectrum_count_list=$spectrum_count_list;
const max_col_ind=$number_of_color_channels;
const dec_col_ind=max_col_ind-1;
const n_imgs=$init_imgs;
test_full_arr=n_imgs>4;
num_of_chan_arr=vector(#5,0);
v=is_valid=contain_alpha=has_been_pushed=0;
repeat(n_imgs,p,
d#p==1?(
is_valid=1;
da_push(#target_images_list,p);
chan_count=s#p;
if(!contain_alpha,
if(chan_count==2||chan_count>max_col_ind,contain_alpha=1;);
);
test_full_arr?(
pos=chan_count-1;
test_index=num_of_chan_arr[pos];
if(!test_index,
num_of_chan_arr[pos]=1;
++v;
);
if(v==5,test_full_arr=0;);
):(
num_of_chan_arr[chan_count-1]=1;
);
);
);
if(!is_valid,run('error d([0])==1=F'););
contain_alpha?(
use_cmyk_mode?(
contain_five=0;
repeat(2,p,
pos=p*4;
inc_pos=pos+1;
if(num_of_chan_arr[pos]||num_of_chan_arr[inc_pos],
contain_five=1;
da_push(#spectrum_count_list,2+3*p);
);
);
if(num_of_chan_arr[2],
if(contain_five
,da_insert(#spectrum_count_list,da_size(#spectrum_count_list)-1,4);
,da_push(#spectrum_count_list,4)
);
);
):(
repeat(2,p,
pos=p*2;
inc_pos=pos+1;
if(num_of_chan_arr[pos]||num_of_chan_arr[inc_pos],da_push(#spectrum_count_list,2<<p););
);
if(num_of_chan_arr[4],da_push(#spectrum_count_list,5));
);
):(
use_cmyk_mode?(
if(num_of_chan_arr[0],da_push(#spectrum_count_list,1));
if(num_of_chan_arr[2],da_push(#spectrum_count_list,3));
if(num_of_chan_arr[3],da_push(#spectrum_count_list,4));
):(
repeat(2,p,
pos=p*2;
if(num_of_chan_arr[pos],da_push(#spectrum_count_list,pos+1););
);
);
);
da_freeze(#target_images_list);
da_freeze(#spectrum_count_list);
contain_alpha;
"
target_images={crop(#-2)}
list_of_available_specs={crop(#-1)}
num_of_available_specs={narg($list_of_available_specs)}
size_of_target_images_list={narg($target_images)}
target_images_contain_alpha=${}
rm[-2,-1]
elif $init_imgs==1
if ${-max_d}>1 error d([0])==1=F fi
target_images,target_images_contain_alpha,list_of_available_specs,num_of_available_specs,size_of_target_images_list=0,{s==2||s>$number_of_color_channels},{s},1,1
else
error needs_images
fi
# 2. Define tile width and images
if $t_w_arg&&$t_h_arg
tile_width,tile_height=$t_w_arg,$t_h_arg
elif $t_w_arg||$t_h_arg
tile_width,tile_height:=round($t_w_arg?vector(#2,$t_w_arg):vector(#2,$t_h_arg))
else
error tile_no_def_dim
fi
# 3. Convert Color Space of Images if applicable
# 4. Resize images
if $use_thresholded_alpha_on_target_images
if $alpha_threshold_dither
(0,$max_alpha_value) store. thresholded_values
fi
fi
foreach[$target_images] {
mini_w,mini_h,p_w,p_h={tile_v=[$tile_width,$tile_height];mini_wh=ceil([w,h]/tile_v);[mini_wh,mini_wh*tile_v]}
contain_alpha=0
if s==2||s>$number_of_color_channels
+channels {s-1}
if iv
gt. 0
shared.. 0,{s#-2-2}
*. ..
remove.
append[-2,-1] c
contain_alpha=1
else rm. fi
fi
resize $p_w,$p_h,100%,100%,0,$image_boundary,.5,.5
resize $mini_w,$mini_h,100%,100%,2
if $contain_alpha
shared 0,{s-3}
shared.. {s+1}
/.. .
replace_nan.. 0
remove[-2,-1]
channels 0,{s-2}
if $use_thresholded_alpha_on_target_images
shared {s-1}
if $alpha_threshold_dither
contain_variable_alpha=0
$thresholded_values
index.. .,$alpha_threshold_dither,$channel_indexing_mode
if iv#-2 contain_variable_alpha=1 fi
rm[-2,-1]
if !$contain_variable_alpha channels 0,{s-2} fi
else
gt. 0
if $channel_indexing_mode *. $max_alpha_value fi
rm.
fi
fi
fi
}
# 5. Import Images
if $is_img_arg
pass$1 0
else
input_glob $1
fi
if $generate_extra_image $tile_width,$tile_height,1,2 fi
# 6. Check if there is more than 1 imported image, and if any images contains more than 5 channels
imp_imgs={$!-$init_imgs-$generate_extra_image}
max_imp_spec,max_imp_spec_5=${-max_s[$init_imgs--{1+$generate_extra_image}]},0
if $max_imp_spec==5 max_imp_spec_5=1
elif $max_imp_spec_5>5 error exc_chan
fi
if ($!-$init_imgs<2) error "_"#"imps>=2==F" fi
if ${-max_d[$init_imgs--1]}>1 error inv_dep_imp_imgs fi
# 7. Check which imported image contains alpha
# 7a-note. Temporary Image to insert dynamic pushing to find the list of images with alpha with variance, and remove unused alpha.
imp_imgs_contain_alp=0
1,$imp_imgs,1,1,"begin(
const n_imgs=$init_imgs;
const max_col_ind=$number_of_color_channels;
);
p=y+n_imgs;
s_size=s#p;
s_size==2||s_size>max_col_ind?p;"
if iM#-1
discard. 0
repeat h#-1-$generate_extra_image {
pos={i(#-1,0,$<)}
sh[$pos] 100%
if !iv&&!im
rm[-1,$pos]
imp_imgs-=1
else
rm.
fi
}
rm.
if ($!-$init_imgs<2) error "_"#"imps_after_alp_test>=2==F" fi
1,$imp_imgs,1,1,"begin(
const n_imgs=$init_imgs;
const max_col_ind=$number_of_color_channels;
);
p=y+n_imgs;
s_size=s#p;
s_size==2||s_size>max_col_ind?p;"
if iM#-1
discard. 0
imp_imgs_contain_alp={h}
else
rm.
fi
fi
# 8. When imported images has alpha, crop them accordingly to crop mode if applied.
utilize_crop_alpha={$imp_imgs_contain_alp&&$crop_alpha_mode}
if $imp_imgs_contain_alp
list_imp_img_contain_alp={crop(#-1)}
else
if $generate_extra_image
rm.
fi
fi rm.
m "rep_photomosaic_fix_color:
sh 0,{s-3}
sh.. {s+1}
/.. .
replace_nan.. 0
rm[-2,-1]
channels 0,{s-2}"
if $utilize_crop_alpha
if $use_alpha_on_imp_imgs
if $crop_alpha_mode==2
m "rep_photomosaic_resize_output:
resize2din $""1,$""2,2
rep_photomosaic_fix_color
resize $""1,$""2,100%,100%,0,$""3,.5,.5"
else
m "rep_photomosaic_resize_output:
rep_aspect_crop_2d $""1,$""2
resize $""1,$""2,100%,100%,2,$""3
rep_photomosaic_fix_color"
fi
else
if $crop_alpha_mode==2
m "rep_photomosaic_resize_output:
resize2din $""1,$""2,2
resize $""1,$""2,100%,100%,0,$""3,.5,.5"
else
m "rep_photomosaic_resize_output:
rep_aspect_crop_2d $""1,$""2
resize $""1,$""2,100%,100%,2,$""3"
fi
fi
foreach[$list_imp_img_contain_alp] {
sh {s-1}
if iv#-1
autocrop_coords ,
rm.
crop ${}
sh {s-1}
if iv#-1
rm.
if $use_alpha_on_imp_imgs +channels {s-1} gt. 0 sh.. 0,{s#-2-2} *. .. rm. a[-2,-1] c fi
rep_photomosaic_resize_output $tile_width,$tile_height,$tile_out_of_boundary_mode
else
imp_imgs_contain_alp-=1
rm.
channels 0,{s-2}
rep_aspect_crop_2d $tile_width,$tile_height
resize $tile_width,$tile_height,100%,100%,2,$tile_out_of_boundary_mode
fi
else
rm.
rep_aspect_crop_2d $tile_width,$tile_height
resize $tile_width,$tile_height,100%,100%,2,$tile_out_of_boundary_mode
fi
}
local[^0-$d_imgs,$list_imp_img_contain_alp] {
rep_aspect_crop_2d $tile_width,$tile_height
resize $tile_width,$tile_height,100%,100%,2,$tile_out_of_boundary_mode
}
imp_imgs_contain_five:=${-max_s[$init_imgs--1]}==5
um rep_photomosaic_resize_output
else
if $imp_imgs_contain_alp&&$use_alpha_on_imp_imgs
foreach[$list_imp_img_contain_alp] {
+channels {s-1} gt. 0 sh.. 0,{s#-2-2} *. .. rm. a[-2,-1] c
}
rep_aspect_crop_2d[$init_imgs--1] $tile_width,$tile_height
resize[$init_imgs--1] $tile_width,$tile_height,100%,100%,2
foreach[$list_imp_img_contain_alp] { rep_photomosaic_fix_color }
else
rep_aspect_crop_2d[$init_imgs--1] $tile_width,$tile_height
resize[$init_imgs--1] $tile_width,$tile_height,100%,100%,2
fi
fi
um rep_photomosaic_fix_color
remove_duplicates[$init_imgs--1]
imp_imgs={$!-$init_imgs}
end_imp_ind={$init_imgs+$imp_imgs}
# 9. Tree Path for each condition
if $imp_imgs_contain_alp&&$use_alpha_on_imp_imgs
{$!-$init_imgs-$generate_extra_image},1,1,1,"begin(
const init_imgs=$init_imgs;
const number_of_color_channels=$number_of_color_channels;
);
pos=x+init_imgs;
spec_size=s#pos;
spec_size==2||spec_size>number_of_color_channels;"
store. image_bool_has_alpha
if !$target_images_contain_alpha list_of_available_specs:=[$list_of_available_specs]+1 fi
if $imp_imgs_contain_five _rep_photomosaic_create_tiles_contain_five[$init_imgs--1] $list_of_available_specs
else _rep_photomosaic_create_strip_for_less_than_five[$init_imgs--1] $list_of_available_specs
fi
repeat narg($list_of_available_specs) {
image_target=-$num_of_available_specs
$imp_imgs,1,1,{s#$image_target},:"begin(
const img_target=$image_target;
const color_chan_count=s>=3?max(3,s-1):1;
const contain_alpha=s==2||s>color_chan_count;
const tw=$tile_width;
const th=$tile_height;
const tile_dimensions=wh#img_target;
const whc=tw*th*color_chan_count;
contain_alpha?(
output()=(
color_data=crop(#img_target,0,0,x,0,tw,th,1,color_chan_count);
alpha_data=crop(#img_target,0,0,x,color_chan_count,tw,th,1,1);
var(alpha_data)?(
sum_alpha=sum(alpha_data);
alpha_value=avg(alpha_data);
color_vector_output=vector(#color_chan_count,0);
alpha_data/=sum_alpha;
repeat(color_chan_count,p,
color_vector_output[p]=sum((color_data)[p*tile_dimensions,tile_dimensions]*alpha_data);
);
[color_vector_output,alpha_value];
):(
[resize(color_data,tw,th,1,color_chan_count,1,1,1,color_chan_count,2,0,0,0,0,0),alpha_data[0]];
);
);
):(
output()=(
color_data=crop(#img_target,0,0,x,0,tw,th,1,color_chan_count);
resize(color_data,tw,th,1,color_chan_count,1,1,1,color_chan_count,2,0,0,0,0,0);
);
);
);
output();
"
}
2,1,1,$size_of_target_images_list,"
target_image_spec_list=["$target_images"];
if(x,
tile_spec_list=["$list_of_available_specs"];
const size_tile_spec_list=size(tile_spec_list);
const use_cmyk_mode=$use_cmyk_mode;
output=vector(#s,0);
use_cmyk_mode?(
const last_tile_pos=size_tile_spec_list-1;
repeat(s,a,
tv=target_image_spec_list[a];
num_of_chan=s#tv;
if(num_of_chan>=4
,output[a]=last_tile_pos;
,
repeat(size_tile_spec_list,b,
if(num_of_chan<=tile_spec_list[b],break(););
);
output[a]=b;
);
);
):(
repeat(s,a,
tv=target_image_spec_list[a];
num_of_chan=s#tv;
repeat(size_tile_spec_list,b,
if(num_of_chan<=tile_spec_list[b],break(););
);
output[a]=b;
);
);
output;
,
target_image_spec_list;
);
"
repeat $size_of_target_images_list {
contain_alpha,pos_target_image=0,{i(#-1,0,0,0,$>)}
s1,pos_reference_tile={[s#$pos_target_image,$init_imgs+i(#-1,1,0,0,$>)]}
s2,palette_position={[s#$pos_reference_tile,$pos_reference_tile+$num_of_available_specs]}
simplify_final_spectrum=0
if $s1==2||$s1>$number_of_color_channels contain_alpha=1 fi
if $generate_extra_image
shared[$palette_position] 0,{$s2-2}
if $contain_alpha
eval "
const spectrum_size=s#-1;
const last_index=w-1;
const image_reference=$pos_target_image;
const width=w#image_reference;
const height=h#image_reference;
I[#-1,last_index]=resize(crop(#image_reference,0,0,0,0,width,height,1,spectrum_size,0),spectrum_size,2,0);
"
else
eval "
const spectrum_size=s#-1;
const last_index=w-1;
I[#-1,last_index]=vector(#spectrum_size,0);
"
fi
rm.
fi
if $contain_alpha&&!$channel_indexing_mode?$s1==$s2
split[$pos_target_image] c,-{$s1-1}
shared[{$palette_position+1}] 0,{$s2-2}
index[$pos_target_image] [-1],$dithering,0
remove[-1]
+colormap[$pos_target_image] 0,0,0
$image_bool_has_alpha
map[-2] [-1]
if !iM#-2 simplify_final_spectrum=1 fi
remove[-2,-1]
append[$pos_target_image,{$pos_target_image+1}] c
elif $s1==$s2
if $contain_alpha&&$channel_indexing_mode
+channels[$pos_target_image] {$s1-1}
index[$pos_target_image] [$palette_position],$dithering,0
if $multi_channel_indexing
+colormap[$pos_target_image] 0,0,0
$image_bool_has_alpha
map[-2] [-1]
if !iM#-2 simplify_final_spectrum=1 fi
rm[-2,-1]
fi
append[$pos_target_image,-1] c
else
index[$pos_target_image] [$palette_position],$dithering,0
if !$contain_alpha?1:$multi_channel_indexing
+colormap[$pos_target_image] 0,0,0
$image_bool_has_alpha
map[-2] [-1]
if !iM#-2 simplify_final_spectrum=1 fi
remove[-2,-1]
fi
fi
else
if $channel_indexing_mode
{target_image=$pos_target_image;[w#target_image,h#target_image]},1,1,$max_alpha_value
append[$pos_target_image,-1] c
if $generate_extra_image
+crop[$palette_position] 0,{w#$palette_position-2}
index[$pos_target_image] [-1],$dithering,0
remove[-1]
else
index[$pos_target_image] [$palette_position],$dithering,0
fi
if !$contain_alpha?1:$multi_channel_indexing
+colormap[$pos_target_image] 0,0,0
$image_bool_has_alpha
map[-2] [-1]
if !iM#-2 simplify_final_spectrum=1 fi
remove[-2,-1]
fi
else
shared[$palette_position] 0,{$s2-2}
index[$pos_target_image] [-1],$dithering,0
if !$contain_alpha
+colormap[$pos_target_image] 0,0,0
$image_bool_has_alpha
map[-2] [-1]
if !iM#-2 simplify_final_spectrum=1 fi
remove[-2,-1]
fi
remove[-1]
fi
fi
final_spectrum={s#$pos_reference_tile}
if !$contain_alpha?(final_spectrum=$final_spectrum;(final_spectrum==2||final_spectrum>$number_of_color_channels)&&$simplify_final_spectrum)
final_spectrum-=1
fi
{prt=$pos_target_image;d_wh=[$tile_width,$tile_height]*[w#prt,h#prt];[d_wh,1,$final_spectrum];}
eval[$pos_target_image] :"begin(
const multi_channel_alpha_maximum_indexing=$multi_channel_alpha_maximum_indexing;
const max_alpha_value=$max_alpha_value;
const use_thresholded_alpha_on_target_images=$use_thresholded_alpha_on_target_images;
const tile_pos=$pos_reference_tile;
const tw=$tile_width;
const th=$tile_height;
const ss=$final_spectrum;
const d_ss=ss-1;
const use_multi_mode=s>1;
use_multi_mode?(
use_thresholded_alpha_on_target_images||multi_channel_alpha_maximum_indexing?(
action()=(
if(img_val[1],
color_tile=crop(#tile_pos,0,0,img_val[0],0,tw,th,1,d_ss);
alpha_tile=crop(#tile_pos,0,0,img_val[0],d_ss,tw,th,1,1);
draw(#-1,color_tile,x*tw,y*th,0,0,tw,th,1,d_ss);
draw(#-1,alpha_tile,x*tw,y*th,0,d_ss,tw,th,1,1);
);
);
):(
const palette_position=$palette_position;
action()=(
mini_tile_alpha=img_val[1];
palette_alpha=i(#palette_position,img_val[0],0,0,d_ss);
if(mini_tile_alpha,
color_tile=crop(#tile_pos,0,0,img_val[0],0,tw,th,1,d_ss);
alpha_tile=crop(#tile_pos,0,0,img_val[0],d_ss,tw,th,1,1);
if(mini_tile_alpha<palette_alpha,
alpha_tile*=mini_tile_alpha/palette_alpha;
);
draw(#-1,color_tile,x*tw,y*th,0,0,tw,th,1,d_ss);
draw(#-1,alpha_tile,x*tw,y*th,0,d_ss,tw,th,1,1);
);
);
);
):(
action()=(
tile=crop(#tile_pos,0,0,img_val[0],0,tw,th,1,ss);
draw(#-1,tile,x*tw,y*th,0,0,tw,th,1,ss);
);
);
);
img_val=I;
action();
I;
"
reverse[$pos_target_image,-1]
remove[-1]
}
else
if $target_images_contain_alpha list_of_available_specs:=[$list_of_available_specs]-1 fi
if $use_cmyk_mode _rep_photomosaic_create_strip_for_nonalp_tiles_on_cmyk_mode[$init_imgs--1] $list_of_available_specs
else _rep_photomosaic_create_strip_for_less_than_five[$init_imgs--1] $list_of_available_specs
fi
if $target_images_contain_alpha&&(!$use_alpha_on_imp_imgs||!$imp_imgs_contain_alp) list_of_available_specs:=[$list_of_available_specs]+1 fi
repeat narg($list_of_available_specs) {
image_target=-$num_of_available_specs
$imp_imgs,1,1,{s#$image_target},:"begin(
const img_target=$image_target;
const tw=$tile_width;
const th=$tile_height;
);
color_data=crop(#img_target,0,0,x,0,tw,th,1,s);
resize(color_data,tw,th,1,s,1,1,1,s,2,0,0,0,0,0);
"
}
2,1,1,$size_of_target_images_list,"
target_image_spec_list=["$target_images"];
output=vector(#s,0);
if(x,
tile_spec_list=["$list_of_available_specs"];
const size_tile_spec_list=size(tile_spec_list);
const last_tile_pos=size_tile_spec_list-1;
repeat(s,a,
tv=target_image_spec_list[a];
num_of_chan=s#tv;
if(num_of_chan==4||num_of_chan==5
,output[a]=last_tile_pos;
,
repeat(size_tile_spec_list,b,
if(num_of_chan<=tile_spec_list[b],break(););
);
output[a]=b;
);
);
output;
,
target_image_spec_list;
);
"
repeat $size_of_target_images_list {
pos_target_image={i(#-1,0,0,0,$>)}
s1,pos_reference_tile={[s#$pos_target_image,$init_imgs+i(#-1,1,0,0,$>)]}
s2={s#$pos_reference_tile}
if $s1>$s2
split[$pos_target_image] c,-{$s1-1}
index[$pos_target_image] [{$pos_reference_tile+$num_of_available_specs+1}],$dithering,0
a[$pos_target_image,{$pos_target_image+1}] c
elif $s1<$s2
split[$pos_target_image] c,{$s1-2}
index[$pos_target_image] [{$pos_reference_tile+$num_of_available_specs}],$dithering,0
a[$pos_target_image,{$pos_target_image+1}] c
else
index[$pos_target_image] [{$pos_reference_tile+$num_of_available_specs}],$dithering,0
fi
{prt=$pos_target_image;d_wh=[$tile_width,$tile_height]*[w#prt,h#prt];[d_wh,1,$s1];}
eval[$pos_target_image] :"begin(
const max_alpha_value=$max_alpha_value;
const tile_pos=$pos_reference_tile;
const tw=$tile_width;
const th=$tile_height;
const t_wh=tw*th;
const ss=$s1;
const d_ss=ss-1;
const use_multi_mode=s>1;
const use_thresholded_alpha_on_target_images=$use_thresholded_alpha_on_target_images;
use_multi_mode?(
use_thresholded_alpha_on_target_images?(
action()=(
alpha=img_val[1];
alpha?(
tile=[crop(#tile_pos,0,0,img_val[0],0,tw,th,1,d_ss),vector(#t_wh,max_alpha_value)];
draw(#-1,tile,x*tw,y*th,0,0,tw,th,1,ss);
);
);
):(
action()=(
alpha=img_val[1];
alpha?(
tile=[crop(#tile_pos,0,0,img_val[0],0,tw,th,1,d_ss),vector(#t_wh,alpha)];
draw(#-1,tile,x*tw,y*th,0,0,tw,th,1,ss);
);
);
);
):(
action()=(
tile=crop(#tile_pos,0,0,img_val[0],0,tw,th,1,ss);
draw(#-1,tile,x*tw,y*th,0,0,tw,th,1,ss);
);
);
);
img_val=I;
action();
I;
"
reverse[$pos_target_image,-1] rm.
}
fi
keep[0-{$init_imgs-1}]
name[0--1] $names_of_images
_rep_photomosaic_create_strip_for_nonalp_tiles_on_cmyk_mode:
images={$!}
fin_img_ind={$!-1}
$=p
repeat $# {
spec_size=${p{$>+1}}
if $spec_size==4
+foreach[0-$fin_img_ind] {
if s==1 to_rgb fi
rgb2cmyk
}
elif $spec_size==3
+to_rgb[0-%fin_img_ind]
else
to_gray[0-%fin_img_ind]
fi
append[-$images--1] z
}
remove[0-$fin_img_ind]
_rep_photomosaic_create_strip_for_less_than_five:
images={$!}
fin_img_ind={$!-1}
$=p
m "loc_tmp_cmd_rgb2cmyka:
foreach {
if s==1 to_rgb rgb2cmyk 100%,100%,100%,1,255 a c
elif s==2 to_rgba s. c,-3 rgb2cmyk.. a c
elif s==3 rgb2cmyk 100%,100%,100%,1,255 a c
elif s==4 s. c,-3 rgb2cmyk.. a c
fi
}"
repeat $# {
spec_size=${p{$>+1}}
cs_convert=${arg\ $spec_size,to_gray,to_graya,to_rgb,to_rgba,loc_tmp_cmd_rgb2cmyka}
+$cs_convert[0-$fin_img_ind]
append[-$images--1] z
}
remove[0-$fin_img_ind]
uncommand loc_tmp_cmd_rgb2cmyka
_rep_photomosaic_create_tiles_contain_five:
images={$!}
fin_img_ind={$!-1}
$=p
repeat $# {
spec_size=${p{$>+1}}
if $spec_size==5
+foreach[0-$fin_img_ind] {
if s==1 to_rgb rgb2cmyk 100%,100%,100%,1,255 a c
elif s==2 to_rgba s. c,-3 rgb2cmyk.. a c
elif s==3 rgb2cmyk 100%,100%,100%,1,255 a c
elif s==4 s. c,-3 rgb2cmyk.. a c
fi
}
elif $spec_size==4
+foreach[0-$fin_img_ind] {
if s<3 to_rgba
elif s==5 s c,-4 cmyk2rgb.. a c
fi
}
elif $spec_size==3
+foreach[0-$fin_img_ind] {
if s==5 channels 0,3 cmyk2rgb
elif s!=3 to_rgb
fi
}
elif $spec_size==2
+foreach[0-$fin_img_ind] {
if s==5 s c,-4 cmyk2rgb.. a c to_graya
elif s!=2 to_graya
fi
}
elif $spec_size==1
+foreach[0-$fin_img_ind] {
if s!=1&&s<5 to_gray
elif s==5 s. c,-4 cmyk2rgb..
}
else error inv_spec_size_found
fi
a[-$images--1] z
}
remove[0-$fin_img_ind]
And yes, reading the code is a doozy.
ig imports images from a folder. alpha_images is the name of the folder you’re going to be using as image input.