So, I’m not making much filters as I used to as I’m reworking on old ones. But, I think this counts as new, or just reworked rep_skew.
During the road trip, a light bulb moment came when I wanted to implement a few things missing in rep_skew filter, but decided to recode from scratch and made a new rep_shear which will replace it. I didn’t have my other G’MIC code as it is in my desktop, and I had my laptop, so I made this to speed up the time.
I’ll make the GUI version soon and push it to gmic-community.
Just 85 lines of code.
#@cli rep_shear: combined_axis={ 0,xy | 1,xz | 2,xc | 3,yx | 4,yz | 5,yc | 6,zx | 7,zy | 8,zc | 9,cx | 10,cy | 11,cz },angle,centre,_boundary={ 0=none | 1=neumann | 2=periodic | 3=mirror },_interpolation={ 0=nearest | 1=linear | 2=bicubic },_output_mode={ 0=cropped | 1=full }
#@cli : Shear Image Based on angle.
#@cli : Default values: '_boundary=2','_interpolation=2','_output_mode=0'
rep_shear:
skip ${4=2},${5=2},${6=0}
check inrange($2,-90,90,0,0)&&isfinite($3)&&isint($4,0,3)&&isint($5,0,2)&&isbool($6)
if !$2 return fi
x,y,z,c,centre=0,1,2,3,{ispercentage($3)?$3:($3+1)/2}
check inrange($centre,0,1,1,1)
if isnum($1)
check isint($1,0,11)
loc=${arg\ $1+1,xy,xz,xc,yx,yz,yc,zx,zy,zc,cx,cy,cz}
else
loc={'xyzc'}
check v='$1';size(v)==2?(isin(v[0],$loc)&&isin(v[1],$loc)&&v[0]!=v[1]);
loc=$1
fi
d,l={`v='$loc';[v[0],_',',v[1]]`} # distance/distancia & line/linea
t_length,t_mult=${arg0\ ${$l},w,h,d,s},{tan($2°)}
ref_length,shift_scale=$t_length-1,$t_mult*half_ref_length
c_interpolation_mode={${$d}==3}
# Workaround as G'MIC JIT compiler doesn't support interpolation within non-spatial dimension c
if $c_interpolation_mode&&$5
p_arg,s_arg=${arg0\ ${$l},xczy,cyzx,xycz},${arg0\ ${$l},yx,xy,zc}
permute $p_arg
rep_shear $s_arg,${2-6}
permute $p_arg
return
fi
contain_c={same(_'$d',_'c')||same(_'$l',_'c')}
c0,c1,c2,c3=0
d0,d1,d2,d3=w,h,d,s
if $6
ins_l=#-1,
t_dim=${arg0\ ${$d},w,h,d,s}
df=ceil($t_dim+(abs($t_mult)*$t_length))
c${$d}=($l-half_ref_length)/half_ref_length*shift_scale-offset
else
c${$d}=($l-centre)/half_ref_length*shift_scale
fi
if $contain_c
skew_expr=j($ins_l$c0,$c1,$c2,$c3,$5,$4)
else
skew_expr=J($ins_l$c0,$c1,$c2,$5,$4)
fi
if $6
foreach {
dist={$df}
d${$d}=$dist
offset={($dist-$t_dim)/2}
if prod($d0,$d1,$d2,$d3)/$_cpus>0x400000 error exc_dim_lim fi
{[$d0,$d1,$d2,$d3]},"begin(
const ref_length=max(1,"$ref_length");
const half_ref_length=ref_length/2;
const offset=$offset;
const shift_scale="$shift_scale";
);
"$skew_expr";
"
rm..
}
else
fill "begin(
const ref_length="$ref_length";
const half_ref_length=ref_length/2;
const centre=ref_length*$centre;
const shift_scale="$shift_scale";
);
"$skew_expr";"
fi
- Some picture examples -
Shear color channels perpendicular to x/y axis respectively
Left shears within x-axis perpendicular to y axis, and the right is the inverse.
And that’s not all, you can also have a non-cropped version:
Even z axis can be sheared. So, you can shear along z perpendicular to a different axis too!


