pixel sorting — 行の中で並べ替える
ピクセルを混ぜるのでなく、並べ替える。各行を左から見て、明るさがある範囲に入った連続した区間(スパン)を見つけ、その区間だけを明るさ順に並べ直す。区間がにゅるっと引き伸ばされて、グリッチの筋になる。
pixel sorting。画像の行(または列)を区間ごとに明るさで整列させるグリッチ技法。どこを並べ替えるかをしきい値で決める——明るさが帯 [lo, hi] に入った連続区間だけを切り出してソートする。帯の外は触らないので、元の輪郭は残りつつ、特定の明度帯だけが筋に伸びる。Kim Asendorf の処理が知られていて、しきい値の取り方(明るさ・色相・コントラスト)で崩れ方が変わる。
並べ替える前に、並べ替える元の絵がいる。sin と cos と中心からの距離を混ぜた場を Float32Array に書き、0〜1 の明るさとして塗る。帯 [lo, hi] を時間で上下させて、その帯に入ったセルだけ枠の輝度を持ち上げる。どの明度帯がソート対象になるかが、明るく浮いた区間で見える。
帯の通った所が明るい区間として走り、帯が上下するとその区間が伸び縮みする。区間の始まりと終わりは、明るさが lo を上回って hi を下回るかどうかだけで決まる。明るい区間はばらばらの長さで、行ごとに切れ目の位置が違う。
その区間の中だけを明るさ順に並べ替える。行を左から走査し、帯に入ったセルが続くあいだ end を伸ばして区間の右端を探す。区間の値を取り出して sort で昇順に並べ、同じ位置へ書き戻す。帯の外のセルは順序を変えずに飛ばす。
let x = 0
while (x < n) {
if (row[x] >= lo && row[x] <= hi) {
let end = x
while (end < n && row[end] >= lo && row[end] <= hi) end++
const span = []
for (let i = x; i < end; i++) span.push(row[i])
span.sort((a, b) => a - b) // 暗い順に並べ直す
for (let i = x; i < end; i++) row[i] = span[i - x]
x = end
} else {
x++ // 帯の外は触らない
}
}行を一本ずつこの並べ替えにかけてから塗る。row に明るさを写し、区間ソートを通し、row を輝度に伸ばして横一列を描く。帯を時間で動かすと、ソートされる区間が画面の上を移って崩れ方が変わる。
帯に入った区間が暗い側から明るい側へ並び、横方向の筋になって伸びる。帯の外は元のまま残るので、絵の骨格を保ったまま一部だけが流れる。hi - lo の幅を広げると一行のほとんどが一つの区間に繋がって長い筋になり、狭めると短い断片に割れる。span.sort の比較を (a, b) => b - a に裏返すと、明るい側から並んで筋の向きが反転する。
画像処理というより画像破壊に近いが、しきい値で範囲を切り出す操作はディザや bloom と同じ部品になる。明るさで仕分ける発想を、丸めにでなく並べ替えに使っている。