Image filtering

Richard Suchenwirth 2004-08-18 - This routine takes a photo image and creates a new one, in which pixels whose color (an {r g b} list) is contained in a list of wanted colors are left unchanged; other pixels are set to the specified background colour. Additionally, you can specify a "dropout" color: pixels in this color are changed to the previous pixel's color (wanted or background) - that was helpful to filter out meridians from a timezone map. The filtered image handle is returned.

proc image'filter {img bg colors {dropout ""}} {
    set w [image width $img]
    set h [image height $img]
    set res [image create photo -width $w -height $h]
    for {set row 0} {$row<$h} {incr row} {
        set outrow {}
        set last $bg
        for {set col 0} {$col<$w} {incr col} {
            set rgb [$img get $col $row]
            if {$rgb eq $dropout} {set rgb $last}
            if {[lsearch -exact $colors $rgb]>=0} {
                lappend outrow [rgb2color $rgb]
                set last $rgb
            } else {
                lappend outrow $bg
                set last $bg
            }
        }
        $res put [list $outrow] -to 0 $row [expr {$w-1}] [expr {$row+1}]
    }
    set res
}

proc rgb2color rgb {
    foreach {r g b} $rgb break
    format #%02X%02X%02X $r $g $b
}