How it works
It works by adding and subtracting the neighbor pixels: 0 1 2 .--.--.--. 0 |-1|-1|+1| .--.--.--. 1 |-1|-1|+1| .--.--.--. 2 |+1|+1|+1| .--.--.--. The central pixel is computed from all pixels: p11 = -p00 - p01 + p02 - p10 - p11 + p12 + p20 + p21 + p22
The proc
namespace eval ::emboss \ { namespace export emboss package require Tk proc emboss {image} \ { # get the old image content set width [image width $image] set height [image height $image] if {$width * $height == 0} { error "bad image" } # create corresponding planes for {set y 0} {$y < $height} {incr y} \ { set r:row {} set g:row {} set b:row {} for {set x 0} {$x < $width} {incr x} \ { foreach {r g b} [$image get $x $y] break foreach c {r g b} { lappend $c:row [set $c] } } foreach c {r g b} { lappend $c:data [set $c:row] } } # embossing for {set y 0} {$y < $height} {incr y} \ { set row2 {} for {set x 0} {$x < $width} {incr x} \ { foreach c {r g b} \ { set c00 [lindex [set $c:data] [expr {$y - 1}] [expr {$x - 1}]] set c01 [lindex [set $c:data] [expr {$y - 1}] [expr {$x - 0}]] set c02 [lindex [set $c:data] [expr {$y - 1}] [expr {$x + 1}]] set c10 [lindex [set $c:data] [expr {$y + 0}] [expr {$x - 1}]] set c11 [lindex [set $c:data] [expr {$y + 0}] [expr {$x - 0}]] set c12 [lindex [set $c:data] [expr {$y + 0}] [expr {$x + 1}]] set c20 [lindex [set $c:data] [expr {$y + 1}] [expr {$x - 1}]] set c21 [lindex [set $c:data] [expr {$y + 1}] [expr {$x - 0}]] set c22 [lindex [set $c:data] [expr {$y + 1}] [expr {$x + 1}]] foreach v {c00 c01 c02 c10 c12 c20 c21 c22} { if {[set $v] == ""} { set $v 0.0 } } set c0 [expr {128 + (-$c00 - $c01 + $c02 - $c10 - $c11 + $c12 + $c20 + $c21 + $c22)}] if {$c0 < 0} { set c0 0 } if {$c0 > 255} { set c0 255 } set $c $c0 } set c [expr {int(($r + $g + $b) / 3.0)}] lappend row2 [format #%02x%02x%02x $c $c $c] } lappend data2 $row2 } # create the new image set image2 [image create photo] # fill the new image $image2 put $data2 # return the new image return $image2 } }
The demo
# to download the image: # http://perso.wanadoo.fr/maurice.ulis/tcl/image5.png package require Img image create photo Photo -file image5.png namespace import ::emboss::emboss set image [emboss Photo] wm title . "emboss" canvas .c -bd 0 -highlightt 0 .c create image 0 0 -anchor nw -image $image foreach {- - width height} [.c bbox all] break .c config -width $width -height $height pack .c
Minor AlterationRemoved the second for y loop, improved speed by roughly 40%. fixed line...
foreach v {c00 c01 c02 c10 c12 c20 c21 c22} { if {[set $v] == ""} { set $v 0.0 } }to...
foreach v {c00 c01 c02 c10 c12 c20 c21 c22} { if {[set $v] == ""} { set $v [lindex [set $c:data] $y $x] } }This correct a problem with the image getting darker through the effect.
proc Emboss { data } { if {[catch {set width [image width $data]} blah]} {return 0} set height [image height $data] for {set y 0} {$y < $height} {incr y} { set r:row {}; set g:row {}; set b:row {}; update for {set x 0} {$x < $width} {incr x} { foreach {r g b} [$data get $x $y] break foreach c {r g b} { lappend $c:row [set $c] } } foreach c {r g b} { lappend $c:data [set $c:row] } set row2 {} update for {set x 0} {$x < $width} {incr x} { foreach c {r g b} { set c00 [lindex [set $c:data] [expr {$y - 1}] [expr {$x - 1}]] set c01 [lindex [set $c:data] [expr {$y - 1}] [expr {$x - 0}]] set c02 [lindex [set $c:data] [expr {$y - 1}] [expr {$x + 1}]] set c10 [lindex [set $c:data] [expr {$y + 0}] [expr {$x - 1}]] set c11 [lindex [set $c:data] [expr {$y + 0}] [expr {$x - 0}]] set c12 [lindex [set $c:data] [expr {$y + 0}] [expr {$x + 1}]] set c20 [lindex [set $c:data] [expr {$y + 1}] [expr {$x - 1}]] set c21 [lindex [set $c:data] [expr {$y + 1}] [expr {$x - 0}]] set c22 [lindex [set $c:data] [expr {$y + 1}] [expr {$x + 1}]] foreach v {c00 c01 c02 c10 c12 c20 c21 c22} { if {[set $v] == ""} { set $v [lindex [set $c:data] $y $x] } } set c0 [expr {128 + (-$c00 - $c01 + $c02 - $c10 - $c11 + $c12 + $c20 + $c21 + $c22)}] if {$c0 < 0} { set c0 0 } if {$c0 > 255} { set c0 255 } set $c $c0 } set c [expr {int(($r + $g + $b) / 3.0)}] lappend row2 [format #%02x%02x%02x $c $c $c] } lappend data2 $row2 } set embossed [image create photo] $embossed put $data2 unset data data2 c row2 r g b c00 c01 c02 c10 c11 c12 c20 c21 c22 v height width return $embossed }* modified by: Barry Skidmore---See also