Shadow Photo

Keith Vetter 2006-03-01 : Here's a nice visual effect that you can use when displaying photographs. It displays an image with a nice looking shadow border giving a raised, 3-d look.

WikiDbImage shadow.jpg

The demo shows the earth rise photo from the tcl distribution with and without the shadow affect.

PWQ 8 Mar 06, Whats with the \# ? (a rhetorical question). - RS: To Tcl, \# is # (if not first character of a place where a command is expected), so the backslashes are redundant. However, some editors get confused with # not indicating a comment, so maybe that's why the backslashes were added. KPV: yes, in my case for emacs.


KPV : In Photo Gallery you can find a modification of this code which creates a single image composed of the eight border images and the main image rather than a frame with nine label widgets.


##+##########################################################################
#
# Shadow Photo -- displays an image with shadow border
# by Keith Vetter, March 2006
#
package require Tk

proc ShadowPhoto {w img} {
    MakeBorders
    set width [image width $img]
    set height [image height $img]
 
    # Create top, left, bottom, right images of the correct size
    # then tile in the shadow images
    image create photo ::img::border::t$w -width $width -height 25
    ::img::border::t$w copy ::img::border::T -to 0 0 $width 25
    image create photo ::img::border::b$w -width $width -height 25
    ::img::border::b$w copy ::img::border::B -to 0 0 $width 25
    image create photo ::img::border::l$w -width 25 -height $height
    ::img::border::l$w copy ::img::border::L -to 0 0 25 $height
    image create photo ::img::border::r$w -width 25 -height $height
    ::img::border::r$w copy ::img::border::R -to 0 0 25 $height
 
    # Create the frame and 9 image labels 
    frame $w -bg red
    label $w.tl -image ::img::border::TL -bd 0
    label $w.t -image ::img::border::t$w -bd 0
    label $w.tr -image ::img::border::TR -bd 0
    label $w.l -image ::img::border::l$w -bd 0
    label $w.c -image $img -bd 0
    label $w.r -image ::img::border::r$w -bd 0
    label $w.bl -image ::img::border::BL -bd 0
    label $w.b -image ::img::border::b$w -bd 0
    label $w.br -image ::img::border::BR -bd 0
 
    grid $w.tl $w.t $w.tr -sticky news
    grid $w.l $w.c $w.r -sticky news
    grid $w.bl $w.b $w.br -sticky news
 
    return $w
}
##+##########################################################################
# 
# MakeBorders -- makes 8 images which forming the shadow gradient for the
# four sides and four corners.
#
proc MakeBorders {} {
    if {[info commands ::img::border::T] ne ""} return

    set gradient {\#ffffff \#ffffff \#ffffff \#ffffff \#ffffff \#8d8d8d \#999999
        \#a6a6a6 \#b2b2b2 \#bebebe \#c8c8c8 \#d0d0d0 \#dadada \#e2e2e2 \#e8e8e8
        \#eeeeee \#f2f2f2 \#f7f7f7 \#fcfcfc \#fdfdfd \#fdfdfd \#ffffff \#ffffff
        \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff
        \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff \#ffffff}
 
    image create photo ::img::border::T -width 1 -height 25
    image create photo ::img::border::B -width 1 -height 25
    image create photo ::img::border::L -width 25 -height 1
    image create photo ::img::border::R -width 25 -height 1
    image create photo ::img::border::TR -width 25 -height 25
    image create photo ::img::border::TL -width 25 -height 25
    image create photo ::img::border::BR -width 25 -height 25
    image create photo ::img::border::BL -width 25 -height 25
 
    for {set x 0} {$x < 25} {incr x} {
        ::img::border::B put [lindex $gradient $x] -to 0 $x
        ::img::border::R put [lindex $gradient $x] -to $x 0
        
        for {set y 0} {$y < 25} {incr y} {
            set idx [expr {$x<5&& $y<5 ? 0 : round(hypot($x,$y))}]
            ::img::border::BR put [lindex $gradient $idx] -to $x $y
        }
    }
    ::img::border::TL copy ::img::border::BR -subsample -1 -1
    ::img::border::TR copy ::img::border::BR -subsample 1 -1
    ::img::border::BL copy ::img::border::BR -subsample -1 1
 
    ::img::border::L copy ::img::border::R -subsample -1 1
    ::img::border::T copy ::img::border::B -subsample 1 -1
}

 Demonstration code
#################################################################
#
# Demo code below
#
set idata {
    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
    HUtUWPmxAkqURBcKCAgAOw==
}
. config -bg white
image create photo ::img::img -data $idata
ShadowPhoto .fp ::img::img
label .l -image ::img::img -bd 0
pack .fp .l -side top -pady 10 -padx 10
 
return