clojure2d.extra.signal

Image pixels as signal

Pixels as Signal

Pixels (Image) can be treated as signal. Conversion to signal is based on strategies of converting image to RAW and then converting to audio. It includes channel data layout and packing into integer, encoding, endianess, etc.

To convert Pixels to signal use pixels->signal function. To convert back use signal->pixels. signal->pixels requires target Pixels object to store result of conversion. Target is mutated then.

To filter Pixels directly (without explicit conversion to and from Signals) you can use filter-channels with effects-filter.

Code snippets

Save pixels to image.

(defn saver
  [f params & opts]
  (let [n (str "images/signal/" (first opts) ".jpg")]
    (save (f (p/load-pixels "docs/cockatoo.jpg")) (str "docs/" n))
    (str "../" n)))

Image with applied effect

(defn draw-effect-on-pixels
  [f params & opts]
  (let [n (str "images/signal/" (first opts) ".jpg")
        pix
        (apply-effects-to-pixels f (p/load-pixels "docs/cockatoo.jpg"))]
    (save pix (str "docs/" n))
    (str "../" n)))

apply-effects-to-pixels

(apply-effects-to-pixels effects config config-back reset pixels)(apply-effects-to-pixels effects pixels)(apply-effects-to-pixels effects reset pixels)(apply-effects-to-pixels effects config config-back pixels)

Apply effects directly to Pixels.

Provide configurations to properly convert Pixels to Signal and back. Optionally set reset value (reinit effects’ state after reset samples).

If you prefer operating through filter-channels use effect-filter.

Examples

Apply hpf to all channels

(saver
 (fn [in]
   (apply-effects-to-pixels (s/effect :simple-highpass {:cutoff 10})
                            {:channels :all, :bits 16}
                            {:channels :all, :planar? false, :bits 16}
                            in))
 ...)

:simple-lowpass

(draw-effect-on-pixels (s/effect :simple-lowpass {:rate 200, :cutoff 2})
                       ...)

:simple-highpass

(draw-effect-on-pixels (s/effect :simple-highpass
                                 {:rate 200, :cutoff 10})
                       ...)

:biquad-eq

(draw-effect-on-pixels (s/effect :biquad-eq
                                 {:fs 200, :fc 10, :gain -10, :bw 4.0})
                       ...)

:biquad-hs

(draw-effect-on-pixels
 (s/effect :biquad-hs {:fs 200, :fc 2, :gain -10, :slope 2.0})
 ...)

:biquad-ls

(draw-effect-on-pixels (s/effect :biquad-ls
                                 {:fs 200, :fc 5, :gain 5, :slope 2.0})
                       ...)

:biquad-bp

(draw-effect-on-pixels (s/effect :biquad-bp {:fs 200, :fc 15, :bw 2})
                       ...)

:biquad-lp

(draw-effect-on-pixels (s/effect :biquad-lp {:fs 200, :fc 15, :bw 2})
                       ...)

:biquad-hp

(draw-effect-on-pixels (s/effect :biquad-hp {:fs 200, :fc 15, :bw 2})
                       ...)

:dj-eq

(draw-effect-on-pixels (s/effect :dj-eq
                                 {:rate 200,
                                  :high -10,
                                  :low -20,
                                  :mid 5.0,
                                  :peak-bw 5,
                                  :shelf-slope 5})
                       ...)

:phaser-allpass

(draw-effect-on-pixels (s/effect :phaser-allpass {:delay 0.1}) ...)

:divider

(draw-effect-on-pixels (s/effect :divider {:denom 1}) ...)

:fm

(draw-effect-on-pixels
 (s/effect :fm {:quant 0.0, :omega 0.025, :phase 0.05})
 ...)

:bandwidth-limit

(draw-effect-on-pixels (s/effect :bandwidth-limit {:rate 200, :freq 10})
                       ...)

:distort

(draw-effect-on-pixels (s/effect :distort {:factor 0.1}) ...)

:foverdrive

(draw-effect-on-pixels (s/effect :foverdrive {:drive 3.0}) ...)

:decimator

(draw-effect-on-pixels (s/effect :decimator
                                 {:bits 4, :rate 200, :fs 10})
                       ...)

:basstreble

(draw-effect-on-pixels (s/effect :basstreble
                                 {:rate 200,
                                  :treble-freq 60,
                                  :bass-freq 2.0,
                                  :bass -5,
                                  :treble -5,
                                  :gain 2.0,
                                  :slope 1.0})
                       ...)

:echo

(draw-effect-on-pixels (s/effect :echo
                                 {:delay 0.912, :decay 0.3, :rate 200})
                       ...)

:vcf303

(draw-effect-on-pixels (s/effect :vcf303
                                 {:gain 3.0,
                                  :rate 200,
                                  :trigger false,
                                  :cutoff 0.1,
                                  :resonance 1.1,
                                  :env-mod 0.9})
                       ...)

:slew-limit

(draw-effect-on-pixels (s/effect :slew-limit
                                 {:rate 200, :maxrise 2, :maxfall 10})
                       ...)

:mda-thru-zero

(draw-effect-on-pixels (s/effect :mda-thru-zero
                                 {:rate 200,
                                  :speed 0.9,
                                  :depth 1.0,
                                  :mix 0.8,
                                  :depth-mod 1.9,
                                  :feedback 0.9})
                       ...)

effects-filter

(effects-filter effects config config-back reset)(effects-filter effects)(effects-filter effects reset)(effects-filter effects config config-back)

Creates filter to process Pixels as Signal using filter-channels.

Provide configurations to properly convert Pixels to Signal and back. Optionally set reset value (reinit effects’ state after reset samples).

Filter operates on one channel at time and is defined to be used with filter-channels. If you want to operate on Pixels directly, use apply-effects-to-pixels.

Examples

Apply lpf to the image

(saver (fn [in]
         (let [lpf (effects-filter (s/effect :simple-highpass
                                             {:cutoff 1000}))]
           (p/filter-channels lpf in)))
       ...)

Apply lpf to the image, with some conversion parametrization

(saver
 (fn [in]
   (let [lpf (effects-filter (s/effect :simple-lowpass {:cutoff 500})
                             {:signed? true}
                             {:signed? true}
                             15)]
     (p/filter-channels lpf in)))
 ...)

pixels->signal

(pixels->signal p {:keys [planar? signed? little-endian? bits channels coding], :or {planar? true, little-endian? true, bits 8, signed? false, channels [0 1 2], coding :none}})(pixels->signal p)

Convert Pixels to Signal for given specifications.

Specification for conversion is based on Audacity importing options and image to RAW conversions practices. Spec contains:

  • planar? - layout of channels data, planar (true, default) or interleaved (false)
  • signed? - channel data are encoded as signed (true, default) or unsigned (false) integer.
  • little-endian? - for 16 and 24 bits pack channel data with little-endian order (true, default) or big-endian (false)
  • bits - pack channel data in 8 (default), 16 or 24 bits.
  • channels - list of channels to convert to signal, default [0 1 2] (for all you can use :all keyword).
  • coding - encode signal with one of the encoders: :alaw, :alaw-rev, :ulaw, :ulaw-rev or :none (default).

Pixels can be restored from Signal with signal->pixels function.

Examples

Basic usage

(pixels->signal (p/load-pixels "docs/cockatoo.jpg"))
;;=> [D@332aaf6

Custom configuration

(pixels->signal (p/load-pixels "docs/cockatoo.jpg")
                {:planar? false,
                 :signed? true,
                 :bits 24,
                 :coding :ulaw,
                 :channels [2 1]})
;;=> [D@6428f7d7

signal->pixels

(signal->pixels sig target {:keys [planar? signed? little-endian? bits channels coding], :or {planar? true, little-endian? true, bits 8, signed? false, channels [0 1 2], coding :none}})(signal->pixels sig target)

Convert Signal to Pixels storing result into target (mutating it!).

Specification is the same as in pixels-signal functions.

Examples

Basic usage

(let [p (p/load-pixels "docs/cockatoo.jpg")
      target (p/clone-pixels p)]
  (signal->pixels (pixels->signal p) target))
;;=> pixels (150, 150)

Custom configuration

(let [p (p/load-pixels "docs/cockatoo.jpg")
      target (p/clone-pixels p)
      conf-in {:planar? false,
               :signed? true,
               :bits 24,
               :coding :alaw,
               :channels [2 1]}
      conf-out (merge conf-in {:coding :alaw-rev})]
  (signal->pixels (pixels->signal p conf-in) target conf-out))
;;=> pixels (150, 150)