For a while, I wondered how exactly how can one sort images transversing through all channels. I didn’t exactly have an O(n log n) algorithm which I can understand (I don’t get quicksort, so I used heap sort, and I’ll use insertion sort for smaller arrays). So, for code reviews and idea, I’ll just leave that G’MIC thread alone until I manage to do something big. I’m still figuring out things and improving my old codes.
Here’s the current code:
Code
#@cli rep_sort_colors:
#@cli : Sort pixels by their color.
rep_sort_colors:
old_status=${}
foreach {
n={n}
w,h,d,s,c,diff={[w#-1,h#-1,d#-1,s#-1]},0,0
rep_uniq_cols 1 # Reduce the number of colors to sort, and preserve counts of colors
+channels 0 pixelsort[-2] +,x,[-1] rm.
if $s==1
__$0_fill
continue
fi
mc={$s-1}
__$0_filter # Used to aid into sorting segments of matching values of previous channel.
repeat (!$break_out)?$s-1 {
eval[-1] "
const diff=$diff;
pos=from_base_float=i0<<24|i1;
end=from_base_float=i2<<24|i3;
size_of_selection=end-pos+1;
for(p=1,p<size_of_selection,++p,
if(i[#-2,pos+p]>i[#-2,pos+((p-1)>>1)],
q=p;
while(i[#-2,pos_a=pos+q]>i[#-2,pos_b=pos+(nq=(q-1)>>1)],
swap(I[#-2,pos_a-diff],I[#-2,pos_b-diff]);
q=nq;
);
);
);
for(p=size_of_selection-1,p>0,--p,
swap(I[#-2,pos-diff],I[#-2,pos+p-diff]);
q=ind=0;
do(
ind=2*q+1;
if(i[#-2,pos+ind]<i[#-2,pos+ind+1]&&ind<(p-1),
++ind;
);
if(i[#-2,pos+q]<i[#-2,pos+ind]&&ind<p,
swap(I[#-2,q+pos-diff],I[#-2,ind+pos-diff]);
);
q=ind;
,ind<p);
);
I;
"
__$0_filter
if $break_out
rm.
break
fi
}
__$0_fill
}
u $old_status
__rep_sort_colors_fill:
$w,$h,$d,$s
eval[-2] >"begin(
pos=0;
const ds=s-1;
);
copy_pos=pos;
values=I;
copy_count=values[ds];
repeat(s-1,p,
copy(i[#-1,copy_pos],values[p],copy_count,1,0);
copy_pos+=whd#-1;
);
pos+=copy_count;
I;
"
rm[-2]
__rep_sort_colors_filter:
if !$c
1,1,1,4,[0,0,(whd#-1-1)>>24,(whd#-1-1)&0xffffff]
elif $c==$mc
rm. return
fi
1,{whd#-1+1},1,4
eval[-2] >"begin(
to_base_float(v)=[v>>24,v&0xffffff];
const next_level=whd#-3;
);
pos=from_base_float=i0<<24|i1;
end=from_base_float=i2<<24|i3;
old_value=nan;
last_old_value_pos=nan;
initialized_per_section=0;
while(pos<=end,
initialized_per_section?(
if(i[#-3,pos]!=old_value,
if((pos-last_old_value_pos)>1,
da_push(#-1,[to_base_float(last_old_value_pos+next_level),to_base_float(pos-1+next_level)]);
);
old_value=i[#-3,pos];
last_old_value_pos=pos;
);
):(
old_value=i[#-3,pos];
last_old_value_pos=pos;
initialized_per_section=1;
);
++pos;
);
if((pos-last_old_value_pos)>1,
da_push(#-1,[to_base_float(last_old_value_pos+next_level),to_base_float(pos-1+next_level)]);
);
set('break_out',!da_size(#-1));
da_freeze(#-1);
I;
"
rm[-2]
diff+={whd#-2}
c+=1
C:\Windows\System32>gmic sp dog tic rep_sort_colors toc
[gmic]./ Start G'MIC interpreter (v.3.6.0).
[gmic]./ Input sample image 'dog' (1 image 1024x685x1x3).
[gmic]./ Initialize timer.
[gmic]./ Elapsed time: 0.068 s.
[gmic]./ Display image [0] = '[unnamed]'.
[0] = '[unnamed]':
size = (1024,685,1,3) [8220 Kio of float32].
data = (2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, ... ,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253).
min = 2, max = 254, mean = 119.113, std = 53.8004, coords_min = (0,0,0,0), coords_max = (1013,678,0,0).
[gmic]./ End G'MIC interpreter.