Filter Image fun

Keith Vetter 2019-01-24 : Recently I needed to darken an image and I didn't have access to ImageMagick. All I needed to do was to run ::tk::Darken on every pixel, and to store the result back into the image. After writing the scaffolding for processing each pixel, I realized that I could generalize the code to call not just ::tk::Darken but any arbitrary filter command.

So here's a fun little tool that lets you play with some simple pixel-base image processing. You can swap the various red, green and blue color channels, you can drop any red, green or blue color channel or darken (or brighten) an image. The filters are accumulative--each filter works on the output of the previous filter--until you press the reset button.

KPV 2019-01-28 : added a filter to create sepia toned images.

filter_image_fun_screen2

##+##########################################################################
#
# Filter Image Fun -- some simple image processing
# by Keith Vetter 2019-01-07
# Sepia code: https://groups.google.com/forum/#!topic/comp.lang.java.programmer/nSCnLECxGdA
#

package require Tk
package require Img

set CTRL(fname,msg) "Image: <builtin>"

proc DoDisplay {} {
    wm title . "Image Filtering Fun"
    image create photo ::img::org
    image create photo ::img::post
    ::ttk::label .org -image ::img::org -text "Original Image" -compound top
    ::ttk::label .post -image ::img::post -text "Processed Image" -compound top
    ::ttk::frame .ctrl -borderwidth 2 -relief solid

    ::ttk::label .msg -textvariable CTRL(message) -anchor c
    ::ttk::label .time -textvariable CTRL(time) -anchor c

    grid .org .post -sticky n
    grid .ctrl - -sticky ew
    grid .msg - -sticky ew
    pack .time -in .msg -side right -padx {0 5}

    ControlPanel .ctrl
}
proc ProcessImage {img out cmd} {
    # Scaffolding for filtering an image, it handles walking through all the pixel
    # data and calling $cmd to filter that pixel. It also calls $cmd at various
    # points for status updates.
    #   {*}$cmd status [start|row #|done]
    #   {*}$cmd filter pixel

    set w [image width $img]
    set h [image height $img]

    set stepSize 10
    {*}$cmd $img $out status start

    for {set row 0} {$row < $h} {incr row $stepSize} {
        set row2 [expr {min($h, $row + $stepSize)}]
        set data [$img data -from 0 $row $w $row2]

        set newData {}
        foreach rowData $data {
            set newRowData [lmap color $rowData {{*}$cmd $img $out filter $color}]
            lappend newData $newRowData
        }
        $out put $newData -to 0 $row
        {*}$cmd $img $out status $row
    }
    {*}$cmd $img $out status done
    return $out
}
proc MEMOIZE {} {
    global MEM
    set cmd [info level -1]
    if {[info level] > 2 && [lindex [info level -2] 0] eq {MEMOIZE}} return
    if {![info exists MEM($cmd)]} {set MEM($cmd) [eval $cmd]}
    return -code return $MEM($cmd)
}
proc FilterCmd {filterArg img out cmd arg} {
    # Procedure to actually filter an image

    if {$cmd ni {status filter}} { error "unknown command $cmd: must be status or filter" }
    if {$cmd eq "status"} {
        if {$arg eq "start"} { $out blank ; set ::START [clock milliseconds] }
        if {$arg eq "done" } {
            set delta [expr {[clock milliseconds] - $::START}]
            if {$delta > 1000} {
                set ::CTRL(time) [format "%.1f sec" [expr {$delta / 1000.}]]
            } else {
                set ::CTRL(time) "$delta ms"
            }
        }
        update
        return
    }
    MEMOIZE

    set color $arg

    # Handle darken## argument
    if {[string match "darken*" $filterArg]} {
        set percent [string range $filterArg 6 end]
        set result [::tk::Darken $color $percent]
        return $result
    }

    # Handle swap and drop
    lassign [winfo rgb . $color] red green blue
    set red [expr {min(255, $red/256)}]
    set green [expr {min(255, $green/256)}]
    set blue [expr {min(255, $blue/256)}]

    array set RGB {
        rgb {red green blue} rbg {red blue green} grb {green red blue}
        gbr {green blue red} brg {blue red green} bgr {blue green red}
    }

    if {[regexp {^sepia(\d+),(\d+)$} $filterArg . depth intensity]} {
        # depth: 0 is b/w, 20 works well
        # intensity: 0-255, 30 is nice

        set gray [expr {($red + $green + $blue) / 3}]
        set red [expr {min(255, $gray + 2 * $depth)}]
        set green [expr {min(255, $gray + $depth)}]
        # Darken blue to increase sepia effect
        set blue [expr {max(0, $gray - $intensity)}]
    } elseif {$filterArg in [array names RGB]} {
        lassign [list $red $green $blue] {*}$RGB($filterArg)
    } else {
        foreach fcolor $filterArg {
            set $fcolor 0
        }
    }
    set result [format "#%02x%02x%02x" $red $green $blue]

    return $result
}
proc ControlPanel {f} {
    global CTRL

    destroy {*}[winfo child $f]

    set w $f.new
    if {1} {
        ::ttk::labelframe $w -text "Image"
        pack $w -side left -anchor n -expand 1 -fill y
        ::ttk::button $w.reset -text "Reset Image" -command {Controller reset}
        ::ttk::button $w.show -text "Show Filters" -command {Controller filter}
        ::ttk::button $w.new -text "New Image" -command {Controller new}
        pack {*}[winfo child $w] -side top
        pack config $w.new -pady {.1i 0}
    }

    set w $f.drop
    if {1} {
        ::ttk::labelframe $w -text "Drop Color"
        pack $w -side left -anchor n -expand 1 -fill y
        set w $f.drop.f
        ::ttk::frame $w
        pack $w -side top -anchor c

        foreach clr {red green blue} {
            set w1 $w.$clr
            ::ttk::checkbutton $w1 -text [string totitle $clr] -variable CTRL(drop,$clr)
            set CTRL(drop,$clr) [expr {$clr eq "red"}]
            pack $w1 -side top -anchor w
        }
        ::ttk::button $f.drop.go -text Go -command {Controller drop}
        pack $f.drop.go -side bottom
    }


    set w $f.swap
    if {1} {
        ::ttk::labelframe $w -text "Swap Colors"
        pack $w -side left -anchor n -expand 1 -fill y
        set w $f.swap.f
        ::ttk::frame $w
        pack $w -side top -anchor c
        foreach swap {rgb  rbg  grb gbr  brg  bgr} {
            ::ttk::radiobutton $w.$swap -text [string toupper $swap] -variable CTRL(swap) -value $swap
        }
        grid $w.rgb $w.rbg
        grid $w.grb $w.gbr
        grid $w.brg $w.bgr
        set CTRL(swap) grb
        ::ttk::button $f.swap.go -text Go -command {Controller swap}
        pack $f.swap.go -side bottom
    }

    set w $f.darken
    if {1} {
        ::ttk::labelframe $w -text "Darken"
        pack $w -side left -anchor n -expand 1 -fill y
        set w $f.darken.f
        ::ttk::frame $w
        pack $w -side top -anchor c
        set row 0
        set col 0
        foreach darken {10 25 50 75 100 110 125 150 200} {
            ::ttk::radiobutton $w.$darken -text "${darken}%" -variable CTRL(darken) -value $darken
            grid $w.$darken -row $row -column $col
            if {[incr col] >= 3} { incr row; set col 0}
        }
        set CTRL(darken) 50
        ::ttk::button $f.darken.go -text Go -command {Controller darken}
        pack $f.darken.go -side bottom
    }

    set w $f.sepia
    if {1} {
        ::ttk::labelframe $w -text "Sepia"
        pack $w -side left -anchor n -expand 1 -fill y

        set CTRL(sepia,depth) 20
        set CTRL(sepia,intensity) 30
        ::ttk::label $w.ldepth -textvariable CTRL(sepia,label,depth)
        ::ttk::scale $w.depth -from 0 -to 255 -orient h -variable CTRL(sepia,depth) \
            -command ControlPanelSepia
        ::ttk::label $w.lintensity -textvariable CTRL(sepia,label,intensity)
        ::ttk::scale $w.intensity -from 0 -to 255 -orient h -variable CTRL(sepia,intensity) \
            -command ControlPanelSepia
        ControlPanelSepia 0

        pack $w.ldepth $w.depth $w.lintensity $w.intensity -side top -fill x
        ::ttk::button $f.sepia.go -text Go -command {Controller sepia}
        pack $f.sepia.go -side top
    }
}
proc ControlPanelSepia {value} {
    global CTRL
    set CTRL(sepia,label,depth) "Depth: [expr {round($CTRL(sepia,depth))}]"
    set CTRL(sepia,label,intensity) "Intensity: [expr {round($CTRL(sepia,intensity))}]"
}

proc Controller {cmd} {
    global CTRL

    set ::cmd $cmd
    if {$cmd eq "drop"} {
        set colors [lmap c {red green blue} { if {$CTRL(drop,$c)} {set c} else continue}]
        if {[llength $colors] == 0} {
            set CTRL(message) "Dropping colors: none"
            lappend CTRL(filters) "Drop: none"
        } elseif {[llength $colors] == 3} {
            set CTRL(message) "Dropping color: all"
            lappend CTRL(filters) "Drop: all"
        } else {
            set CTRL(message) "Dropping color: [join $colors {, }]"
            lappend CTRL(filters) "Drop: $colors"
        }
        set CTRL(cmd) [list FilterCmd $colors]
    } elseif {$cmd eq "swap"} {
        array set msgs {
            rgb {no color swap} rbg {blue <-> green} grb {green <-> red}
            gbr {red -> green -> blue} brg {red -> blue -> green} bgr {red <-> blue}
        }
        set CTRL(message) "Swapping colors: $msgs($CTRL(swap))"
        lappend CTRL(filters) "Swap: rgb <-> $CTRL(swap)"
        set CTRL(cmd) [list FilterCmd $CTRL(swap)]
    } elseif {$cmd eq "darken"} {
        if {$CTRL(darken) <= 100} {
            set CTRL(message) "Darkening colors: $CTRL(darken)%"
        } else {
            set CTRL(message) "Brightening colors: $CTRL(darken)%"
        }
        lappend CTRL(filters) "Darken $CTRL(darken)%"
        set CTRL(cmd) [list FilterCmd darken$CTRL(darken)]
    } elseif {$cmd eq "sepia"} {
        set depth [expr {round($CTRL(sepia,depth))}]
        set intensity [expr {round($CTRL(sepia,intensity))}]

        set CTRL(cmd) [list FilterCmd "sepia${depth},${intensity}"]
        set CTRL(message) "Sepia depth:$depth intensity:$intensity"
        lappend CTRL(filters) "Sepia: $depth $intensity"
    } elseif {$cmd eq "reset"} {
        ::img::post copy ::img::org
        set CTRL(message) ""
        set CTRL(time) ""
        set CTRL(filters) {}
        return
    } elseif {$cmd eq "filter"} {
        set msg $CTRL(fname,msg)
        append msg "\nFilters:\n  "
        if {$CTRL(filters) eq {}} {
            append msg "no filters yet"
        } else {
            append msg [join $CTRL(filters) "\n  "]
        }
        tk_messageBox -message $msg -title "Image Filtering Fun Filters"
        return
    } elseif {$cmd eq "new"} {
        set fname [GetNewImage]
        if {$fname eq ""} return
        set CTRL(fname,msg) "Image: [file tail $fname]"

        ::img::org config -file $fname
        set w [image width ::img::org]
        set h [image height ::img::org]
        ::img::post config -width $w -height $h
        Controller reset
        return
    }
    image create photo ::img::source
    ::img::source copy ::img::post
    ProcessImage ::img::source ::img::post $CTRL(cmd)
}

proc GetNewImage {} {
    global CTRL

    set ftypes {{"Images" {.jpg .png .gif}} {all *}}
    set fname [tk_getOpenFile -defaultextension ".jpg" \
                   -title "Open Image" -filetypes $ftypes]
    return $fname
}

set imageData {
    /9j/4AAQSkZJRgABAQAAAQABAAD/7QBIUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAA8cAVoAAxslRxwC
    AAACAAIAOEJJTQQlAAAAAAAQ/OEfici3yXgvNGI0B1h36//hABhFeGlmAABJSSoACAAAAAAAAAAAAAAA
    /+EDZ2h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJX
    NU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRh
    LyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4zLWMwMTEgNjYuMTQ1NjYxLCAyMDEyLzAyLzA2LTE0
    OjU2OjI3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkv
    MDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4
    bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9u
    cy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25z
    LmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJBN0EyNjdDMjBBMkUw
    Q0RENURBNzFBMjVERTYzQzA2NiIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoxN0IwMDhGQTA4OTgx
    MUUyOUJGOEY5MjI0QjQwNUZCMiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoxN0IwMDhGOTA4OTgx
    MUUyOUJGOEY5MjI0QjQwNUZCMiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IE1h
    Y2ludG9zaCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjAzODAx
    MTc0MDcyMDY4MTE4MDgzOUJEQTFGNDhBNDdGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjA0ODAx
    MTc0MDcyMDY4MTE4MDgzRTI1RjZGNDkwRDdCIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+
    IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZ
    EhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sAQwEJCQkMCwwYDQ0YMiEc
    ITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy/8AAEQgA1QFA
    AwERAAIRAQMRAf/EABwAAAIDAQEBAQAAAAAAAAAAAAMEAQIFBgAHCP/EAEUQAAIBAwIEAwUHAgQDBQkA
    AAECAwAEERIhBRMxQSJRYQYycYGRFCNCobHB0RVScuHw8QdDYhYXJDOTJTQ1U2NzgpKi/8QAGwEAAwEB
    AQEBAAAAAAAAAAAAAQIDAAQFBgf/xAAwEQACAgEDBAEDAwQCAwEAAAAAAQIRAxIhMQQTQVEUBSJhMpGh
    FUJScYGxwdHwI//aAAwDAQACEQMRAD8A4dgVavTs5aLLMQcHrWs1BBLmjZi5lLjBzWMLs2DkUGwkCfFC
    zUTrLbVrNRIiD1qMSbcgdKFBKCFicAHNYJcQyY6GsYKsMmMgGsYsrzIe9YwRrqUx6WzRswNbhxQswZJn
    fbzomHIlTcs4JHamSBZoW97FbKSACcYG3SmoVlFvs3BlON+1YwebiCXQVFjUN/dQoIxNeT23KJfw4AXT
    tSNDo2Vvobm3Tx4YjOGPepvYZIwrm+ljuyVXABwD2rBPf1iTmh0wGH5UGFFn4zK6sNRJPU5pKootwEfF
    5UfKMcmllRSKZqcIlkvJCrHBJ7nGTXLllW5141ZuycMWCRVkk8R7VBZpNWO8cUaBEMcSIJAgxjST+dTU
    pN2M0gUbWwu8DUR5571WpNWJqinRYzRa2Zc46DfrVEn5EckIXnEFbKKQfMCpzL4tjJubsyqzsdKkdjtt
    QiqKuRhtxQ282tW3zXT29SpnP3tDtAH4u5JZXIJ8qKxJCvqG9wTX8jZLOSTTaUuBHNvkot+YmyM5o0Lq
    oeg42zEa9yNht0pHAZZA/wDVm56kjJ6b70unYOodk45y0xgjI2oaQ6tz5RB7RxNETPAyvjI0nINdS6j2
    eS8foeXivDWj1faUG2SpyCKp3o+xdDPR8Y4WRn7Uoz2ZTn9KKzQ9m0M0rWa2nTXFIkq+anOKpGalwK00
    Oi2tpUAxg+YpqMJyWkayEAH0NCjEC2CkEEYrUaxlIdJDYyKJhuARs2kDrQewVuFa3jQamAyTQTsaqKFF
    znbFEAaIR5wVG9CzUXkgh0lsDPbFFGaoy7hFJ8Ox70zQtgYlGrDChRrGFhCE5NGgWDZlUkbgigEE0pJ2
    JoWGi6ZJ2atZqGI1AYHJo2ahppGcKrN4V6CgxkMxzhmXbpUpFIjt48MqJGBsfIVNN+SrivBiyq0UhUqQ
    R2o6gaXYW10nJPapTkXxwGYbcMQxX3j5VNyKqJvcLtEW4V9Ryu4PTeoTbexVUjVaR2kMpIJUYXO9NHHt
    RKWTeyDNHy9Uhw46k96Pbp7AWS0ADiZywJCjy701AsBc8QjgXxHcnCihY6iZhuo4i8i5Z275wBU3Gy6d
    CUt7A8Lgt2wMHrTKLA5qjAuGXVtXQmcsluC5mDW1ASLqzudhS2MkySoHvHetZtJKMEOd6NmR4zOxyuaF
    hpsJBHNM4yWNJKaHjBs+apArENE+sAdCcFaW/ZwFk6BsEDvprGJ5McijG2/XP6itdB2LRJPauHhmZXBx
    lTg0VOt0Bqzc4d7SPAnLvUZ8ZxIgyx+INdOPqK/UTli9GzFxSzuwvJuI2ZjgIdmzjPQ10LLF8Mk4tBOZ
    huvQZp9SBQRbo9KNmDRTYYHNKxo7DU0p0DNBDSArLRFQQSsR4etAJYyuB4mpkwMGhjOWzuDRFBz3ECga
    BuDufOsAD9o1LtWsIGTfxZ3pWFA1YZ3pRg8bgU1gGRMuK1mLcwaetK2OkGh5jsAgJJ6VGUi0ItnVez3B
    5Li5H2lNMYG+e/wrh6nqNK+07sGHfcLxjhEIkdox42OAfOlw5W1uNlgkzLsuGgS4f3QSCfOqSYsUkdEe
    GRQ2kbkjX2UeVTg7lQ03StF41EedKLk7YParaUc7m/J64P2e2aUg4UZFNdCVqYlEi3sKu5IPUgHHypXM
    qoil9JLHpjhXIHYUuqx1EymtL2Z+YULP13GwrakOkKTQXellZCu+5xW1IOliP2OUtjBo60L22e/p8hbB
    BoPIHtMat+DyOR4DjzpHkHWL2Hfhph7fSl7g/bXgUks2J904p1NCPGTDYB85oSyUaOI1YOCAqDiueWZ+
    C0ccUaVtwkqwVVA8jUZZH5LJLwfDoVSaLUkgHbpvXc20z59F+VMgCkhl9Ns/LzoWmYHKrkhViznAKkYz
    RTMFMZC55ZG2cgihZhdopWnB1AgDfTufpTpqjKyTb5RjIvbbtijYyjZEV5d2spW3uHAA6E6h9DTxnJcC
    uCOj4bxqC7IguQILnpg7Kx9PI+ldWPMnyRlCuDV9075FWsUs92cAZBrWYhLjzoWYYjnGaAQpZWOaYBRg
    pOBRAWFmmjUw60QFTw9SMxyfKtQQJsJ2yAQcdN6WmZATZTKASNzQoYC6SRHelZkSszA7k0rkNQVZWY7d
    KRyHSNbh5fWpBOc0j3Lw2O2XiAJQRD7zAA1bY2rkeF+TrWT0K3qXcjCSVysancn+KaCS2QG2+QFlFzpD
    GGxp3G/WjIy4s3oopJApbsMUFsTluM8lYx5tjNHWLobFppEkUx9V6Glch1GgSwqRpVcfCkscpNyrKPmz
    5OOgo3YUmZ8vtGgGiO2YHzo0FLcNDJcXyA8oFT5jFScqLJB34TEWBcooX3j5VOWTbYpBW6ZWKCyMjLlS
    R0I6GhGTfI2RJfpD82GFsaV0jvT66I6GxC+ZCVVFXLNjbepuVlVForJw53RdWAO9Lr9B/wBhrThaa/cB
    pJza5CvwOSNbwrgZ2/t71HWymgWi4hCs4ijRmJ28RpJuTKxjFHwArhSE2J7rsRXsnzJ6CMqBqcs4HXrk
    eRFCT9ADSQA5kWV0Y+9v/NKpeDF3dYgGckHGAxXIopWMgElyZAsY+q7ZqiSQdiotrs6gNLeQJzW1I25C
    wYl1sGSQdfL40HI3kmWHmZYAnz2zWTozQex41d2aiMgywj8LdQPQ1eOVxJOKZ0VlPbcSi1RSaZerIeo/
    kV0QyKRNxaCNbSq2M04CdM0Qzg4rGLx3Dttg0bMG1uu+MedGwUS1+WXGelGzUeW6bG5xQ1GoYtnd5Bg5
    FazUb0dqksJ5g1HyHWmCLT8LglBYMEA65rVZjLbh8CMRryPOkcAqQ1DYRquoYx5ml0D6zYsIoVZWK4Ud
    Se9K4jxmCnv4Yb7Uu6L2z1radja97Gm4vJxH7g7I7A1FwUd0dEJuXJrQGz4ZIqyEu5GdQGdNc9OW5Zva
    jVF/EyKyOCG2GBU3sZRsWkuoyWDzKCNzk0u46SQnNxK3tFLOScmmjFyM6iVtuMpeTCK3XSGOAx/PNaa0
    8hj9w/PawXpwjiUr0GrIFQc65KKIO34MgdQ8YLHoM96lLMWUTSSwlgQroAGO1SeYZRRzXFk4ldKQkXLh
    z+LqarjywXJpY34M+2trlImEiMH/AAn96eWWN7GWN1uaVrwKa6iaS9uSgG+Ouwrly9Vp/SisMK8mibSM
    QpHDEWGd3YYxUIZJN2y80kqHQsOkIIjgVZzaObTZKoyJJEihWbYFu1SlNtjqKQN+EJH95NcAk9lpdTGT
    RQ8PtbYBlIOry60LZrPztCiacSSE7Y3TFe6/wfNpHuYkgKFwWztpOSPnQprcDJYIY9D6vj2rb8oAKCxV
    hqkb7vso7+tGWSuDDYgTSFUjA6DGKnqZiGiKMCq5OcElqZbjpMiaZhGWBxjpnAz86yiGmC5iShQT4+oI
    I3p9NBSsowjkOHJjk8/OtuhWiGtpI9BQkMD7y/lTKQtGtYe0csCiG8haYLtrXZh8fOrwzNciOFm/b8Us
    r1RyZVPYq2zD5V0RyRZNxaGgsO+wB86cAJxhSgcHNEFgTaRt7pwa1Gso9u8LZZdS+YoUaxuC5CLhVANM
    jGxYSuCHYnTjvTAsveXcRwiKDk5b1rBsHBBEwZ2fO2cHoKARe64gmoKgBx3AoNmFbjiMjIqpqxjGaW6G
    oHbNzJPvcjPnU27HSNixeJJMhC5HQUklZeDopeX9xKzZhfJ2yRSpJDtthbVmhgMtxIyHGVTzpJPU6Q8Y
    uKtis/FWkdsHAo1FAuTFml5zZaVs/wDVQcvQyjfJ0nAY7WIFrqULqAC4HWuLM5Pg68cUkdhw2zsoyLmA
    6VPTfGa4pyb2LJUONdxxylsxrg4Hp/nUmPpbRe1mknkcBseW3WkozSS3BTcNa4kJnl27DFMk/BtaSGou
    GWgkAIGcZJNbRJiPK1wEksLdXCnDAbgdqjODoMc0qtAp0hZlUnbp6CtjjSGUnW4G4g5JUJp33Bz1pqCp
    2LJBcySa+eNJ6r6UrQ+pUVuIEyCZSdRwADWNZf8ApYKqNeAw33pHI2pH5i5gcgu7BfxEV9DR87ZLAEao
    ZEbbbO2TWv2BtAxDdp94zAEds9RitcXsKMxznA1AZPqAKRxDRJJBJVScnqc/SskFIlptSHUo/SnopZKs
    k8QRwCCcYrcMZMrLCrOzImMdO21aw2inJ5iEOSpPun1ouVCtpi88s0RXIJUjGQciiqZNstFJ+Ft++MVm
    jIpJGqrkHfPQb4ooA5BxS/hCLHKXj7BxkfDzp45ZIVxTH4eOqSRcI0TDuNxVo5/YjxmnBd8yMSxHWn9y
    1VTT4EcaHIZ2kHjyBTpgDRrCr6upPnTIA5LdfdaYzjbHWnsUU1sWyZNx5ClCMxyJINLvkHrg1kGwyrYx
    kaYu+5JrUjKRE1zbBwFRQtK0h1Io0lk+5UA+hpGkOmzy3UMIxG5waTYom2Fjvyxwpx6k0jplU2FEkrnS
    5Vh5mkaLJm1wewspHLXPJjQdSTtXm9ZPKo1jVs9DpowScpDrcP4JxKdoYo2Vl8KyhsA+uO1csJdRiSc2
    X0wyeAUns5awFRJeHLe6FPQetV+RJrYVYVY6jW/DrOUI7506VZjkg57Vy3Oc9zpcIxjsCsLmKWcc5ZHY
    9Hds4pM6klaHhFNHVNxCHhtrEzsIy+3i6saXBmuPG5yTxOcn6FYuMPeXXJQDWRkY74p/kaeUGfTKKu9i
    ZJZ+viFB9QhVhQPnzMMZNK8qHWMq5mcY3ON+lJ3BtJMfPDDwaiP7q2ts1JFp54LZSbq4KKQAFB8X+1Tb
    nwhlC+DLk4zw8MAEl0IThydiPXvR05P+Sixe2KNx8S3GdWi2XoWByafsS078jrSuD8/RSQpIQjkt0XAr
    6JpnyOwz4JFxGV5vTxLik45MzyG5ifSIEdztu2x+G9B6X5FPch3lV5IlDYyWBx+/50dW1IwUSJGdiWLd
    fQ0KY6FJ2kWQqpDA9O+1URgBuXUKg8LbDOKNGsaSY5YM3T50rRrCJM6sgDd85oNGIkuEjm0lcs25AGNq
    FNoDKrpkbmR4Ixsds4xR4AWhilRyDG2G3yR/FFtBTD81dByuCOx65oIYCssNw4RlyzbDfpRpoGzLRySW
    JYwyuh7gHY/GmjJ+AUvIw/GLyVWVWVSRjIGMfCqd2QNCH7Xi0CWi/aXYTKACeuv1qscyrcnLHvsM2/EY
    7qMOr6T3QncVWORSEcGi54gqsUDrnOME03cQNLKNxZIgS0yKF64NDupB0MoeNQGQJ9oUknGR0+tK8yCs
    bGA7yDUMsDWcxlBllEh/CaRyKKIeOORj2pHIvCNjsdpckjQCSe2Kk8qReOBvwOrw6+Uq0kqRZ6a2wfpU
    n1K8HRHpX52Nnh3s9PxGdV+2oxPZTv8AKuHN1ujwdUenilqk9jci9m/sIkYzbKNmc4BNcU+qczoxxgns
    Yd5P9ru9PMDRx+FSBjby9atCWmI8oXIZfLWogSHWoOVJB2qHeipW2W7bqqBW9rfiQaYyNXTIoZOpxyVA
    jicd7NO7tjJahLly0iHOA5IFc0M2mVopoUkX9no5lZ5UjA0+FM7/AJUnU5NWyJSjFRqR1S62i8WzHqQK
    lFN7s43SexXkL5VZMbWTywq6ME57Dah5Bfkk27tGQqkHtgdKpvWwNaT3OdvPZLi1/ePMuNBO2rPSnx64
    qlEpLqcK5kNQexcxthDOwdQc6cd6yjlctSRn1uJLSEPsJbkYfWw8meqaM/gn83H6Py00sBOVtwM4xhiK
    +ipnzuxJdk0uDnO5UdaFWCwvOQ+LcA+vT+KGkUmSRveV+vbVj61kjHjcOSoXGwz5kVqGTBvcEXZ+9ZV2
    yaZLYN7lZLhmiCuWOW2bA/WtQGz3O8ROT2wCO3rWo1jluUSPXIRlt84+uKSV+AoZdbSeMM0jKR0I2qdy
    QHuLtby8vSqpIgOxUjPxp9SAWMU8B1AMy9ih6VrTMXEz4KywFiV6lcEDyoV6ZrBxRqhDrDpcdADkj+aL
    YUAuLovKF0sD3DbZNOkaz0DBdZKAOD1PSszIPhZyFOx6HTQ4GLC1ySVcpuQK2o1HjZy++ZFIPrR1G0lW
    tlQlCpPQgnpWs1HhEA+jz8h0rBD8y8WNeXPJysZGDsO1azWwq8VuggVppDjfdsZo2GwkXGbjXgzyrkbl
    WNBjxm0P2PH7+MZt72UAHOGbV+uanLHGXKOjH1E48M3bLj7XUoW9CljtzF2x8RUJw0rY7cWbW/uO99nb
    d+bkBk0kFnC5wP2rxuqyJs9FLTDc6Hiy200XLZtZzsqbg9+vSuJ5EuGDp1K91+5nQez8LsJYFkweoVMk
    Goz6qb2W5WWeOPZ0dbw3gdsbRWeYkMOgU7GrdN0yyrXOdL/TPK6jrcmukhwcJttgDLgDHuV1LpIeG/2O
    d9Xk/H7gF9lrPm6+VIw/tK/rvVI/T23tf7FH9Sy1Vo0IuF20KaeUcdN2C4+ldEOjhFbr+Uc0+pySd2FF
    rCqgBItu5JJqi6eCXC/cm8s2+Wee3hVgDGN+6psPrTPDji90ZZJNbP8AkE89lbyxxsyB5DhQEyfnSuWG
    DUXVsdQyzTkuEAuOLWcDiNbmPVnBxnC/Eip5OphB0mimPpsk1biLTu11LHMl3IIhhuWFO5+dQyZO401L
    YtjWhOLjuBbi9lw1Sk8zu7MT4yNW9ZdTHGqdsb42TK7jSQFvazhCFdccihujHBFUj1cJLZMEuhzR8o/H
    Z9OgPcV9AeKNLbM3VAoxgkNvSthIEUTatImDZxqxnNa2AoygDJ1hhv4lNEx5JFGxzjGcgfsaxiwnQKoI
    V/FkBl3FaghJY2lTUAcHoFAx8AKCdGFgRpGpW170wA6hWhDKcNju2w38qXyEPCsgyVlVgD0DmldALs0v
    4AmoDOnff1zQVGIWdItxExXrqQHT9T1rOLZikkjBdS3LFM5IwfpRS/BjxuQCGUHYVtJi32xJQAvjcDoy
    5I+BNHTRheWc8tTpXLE5xTJGLWrmW4xuFG2x6Cg9kFGlDbiNSGbVuTmkbHSASGRTliQuehGc/KijBzJz
    bY5Cuw3DdCKHkL4KQXf4SnhPb1pmgJlp0WTVIkpAAwVWsmFgAcDI8eNsHfFECJaMuyldj332rBIgmFvN
    nds+E0Bk6NKK4j1ghxmkastCdM7DhPtvxGytEtPtgaBV0qrnGBnzG5+deZn6GMnqS3PTwdTC/v3O24fx
    Kz4nbLInGbJWAGYWchlz2Ixvj518/wBRiyYv7T1I9Rjb+2Lf7f8As3V9qrexYW78ZspGOPBENgO3iIwO
    lThLqIQuC2/0ccunx5Helr/b/wDB0nCvamzubh7Zry2bSq6PvgSfn+Ik16nR/VMibWZVFLZv8f8Ad+zz
    ep6CUYqUU/zt/wDUbbXMhjBQKjnqGGcfTrXVl+q1BOFX+/8A0cSxxvfgVR58Zmuixz/8vTj5Zrih1s5b
    yyfxX/ks4w4jH+Ra5QzEYuZFGcnAG/pipZMjm95stjen+1HpL1YnVMZQjGpQMg/Dyq3ylFqPj/g0cLkm
    /JUvHKpEpdgTjB2zR7sZfqbYdMo/pAwmwJPLAYqcEaiMGhGeLwUksy5Lc6zwWATSP+vb9aOrH6Bpy8C0
    l5A8LpZiJpB0DMdJ/OllkVVFFI4ppp5LoGnE4GdxJBApQbqw8Wcevb1pe5f9qGfTy8SZnnjlkurmwxau
    xVelaC9otLBJcSPzRP7IcWgXIVJh/wDTOT9K+oXUQZ4kukmhaDgXFWk5f2WRcfiZDimeSHsRYMl1Rpp7
    G8SuN5JVTbGCDU/kQRVdHNjaewnEF9y/jT0AJpfkx9DfBl7Ib/h/xAj/AN8iI/wGj8qPo3wZewX/AHf8
    RDBhcQfDBo/KiD4U/ZB9huKadPPhIBzsT/Fb5ETfDn7K/wDYjiuTmaEg+ZNHvwF+JMofYjio6Pbf/tR7
    8TfEmej9ieLo2pJLdT5iSg88AfEmEk9ieJSlTJcW4KjGA1ZZoo3xZeyY/ZG+iUrzrZgdj96Rn5UHlTB8
    aQKX2S4hp8Elsh/6ZDg/lTLLED6eQNPZLiqE6JoAMY2l7Ue7EHx5EyeyfERuBasfPnAftWWVAeCYJvZj
    i5VQLWJtPTRMuP1pu5EHZmUj4Bxa1kaV7XcjswP5Cs5xexu1JC8xubdiutVYdQTvn50yihd0HhtpruF7
    iWRlWLfK/wA0dNBW4MxOH1xuxhwCp2y3nn50KMybe3hvLlg12kDHpzRjJ+VZpo0Un5Nq29mLvlMUureV
    T0YMD+9LTfgao+z0fspfKCGkiA9M/lRafoyUfZZvZy+Qe8HxthVzQp+g/b7FT7NX/NB0DT3ONxTUwbDC
    +yl3jPPjBPYqc0rsdJeww9lbxQCLmIn4GkZRQYWPgF9EwK3MYYdCpYEflU5RjJborHVF7MJ/Qb85bnxt
    5+9/FI4RQ6c3uO2vBuJxMpSdAdiCNX8Vy5ceOSpnXilli9mdrw72r9o+HQNC8lvIXOdTqxI2xtmvGyfS
    scn9smi8o4sjTnHf8bF5fbf2hY5P2QDPvcvfHoDQh9GxrfU/3F04VxH+Qcntfx+V9SyWoGcqvIJwPrV1
    9MguWzLQuEGs/bDisc+q9ihkh07iGMq2exySRWl9OVfbLc32+hqX21ix4rK6x/jAoL6fP/JB1xj4/gAP
    bG3yWWyusnYnminX06a/uD31xX8AT7YWgx/7On695BvVF9Pl/kD5IP8A7YW6yCROH3CkbgiYU39Pl/kB
    9UqpoiT2uhmbL8Mmc+ZlFFfT2v7grqktkgDe1FqR/wDCZP8A1addDL/IHy16FVghJybyIDvlOn510duf
    o5+7j9jKx2yAZ4hEPXC4/Wj2ZsHycS8kl7JQwbisPn1QUfjyFfWYl5APdcMVcNxgHy0Y2/Km+NIm+vwr
    yLScR4YoJXjExPz/AGFN8WRN/UsK8iz8W4Xk67qeTfszAfSnXSSZGX1bAuWDXinCcnIuzt+FM5+pFVXR
    S8kZfWsC4Lf1bhONrK/f0Ohf3NUXQ/7IS+uYlwQOLWOPDwe5Y4wQZ1wf/wCaf4BP+u4wX9StCfFwZseR
    ucD8lp10P4/knL67F8Eji9sq6F4PbkH+6diaddCv/mTf1x+EQOJQEbcMtVPnrc/vT/AiL/W5+j32+PtZ
    23wOr+aK6GBv6xkfor/VWQeC3tV8sIf5pvhY/QP6tl8ME/GbthhY4f8A0s/vW+Hj9C/1XN7Are3JOWWE
    H/7IFMukxrwL/Usz8h4b283GUKnqCq4+W1FdNBeA/PzPllntzcT82RpCuAOWr6V+go9mPgddXLyNxQWg
    sDaNYRcsnfQdGaDwopHq2Xto47OBre2gRIWbUVkPM3+YoLEkZ9S2GMZlADkMB20j+KziFZWwyx4TT7i+
    hxUnEvHI6LhEI3I275pGOmVMaY7lvSkbKopy/wDpb6UjHRVdIYqFYj4UrKRCR6CCBzST5dPyqE2zqx0V
    kKA4IkBzupAP61O2WpHoiFnKEQAE5BZjnP0xU5y2spBb1sPpalSNU2jOMgnSvwBrhnl/B0qKXkae0ZDg
    6yTsA0h3HfFRWWx6BJaqoIAOtmG8jt1p3l8iqNbCzbnSLhCSdlUFsY88iqqX4FZLW8hDjkOwOD4MEDzO
    x6UFNezNAzbDbVG4UbjIO/xIzTrJ+RXH8FHgi05ZVyTjYY+uRTqb8CtIr9iLqpiCj1Izij3K5F0Xwelt
    CwICjIO+Rj9aKyGcBZreMYYRhs7HG312qimxHFAJLaB0LKFXB6+fxplNpiuMWciOd3kYn0avZ+PH0fFv
    q5+GXCuOrNj/ABGm7CXgk+pyPyXGQOpx6mmWNIlLJKXLLLpB91d6KgibbfkkDrhV9cUdAL/JIQ5wQfjT
    LGBsnk7DLHPkaPbQU2+EXEfYLqP1ptKF+4IIyDugA+GKZQJthFUAbLn5U6iI3YUEd+nxxTUKSGiHbP8A
    +VHY1S9l1CucJGp3rUMjxSQnaMbnY1qHRV7STSSeUQOuHzWoL2L/ANNuo9/s6FT0K7/vQoenzQVLe4A3
    Qr5DRQaKRbGooZ+yk5/10oUWTCAEDdTv69KWiiaLrEzL4QQT60Ghk0GjgYblhjyJyanJFoyL8mFttzv/
    AHYqUrOmLTDBAfcXf54qLOhFgrBcGMemP3qTLRLDUye5px2PWkZRM8ukuNUTsCNtIBqci0GgcsqoWUxP
    068oD96i02dMZJGfcXkrKeXExPTqR9QBSqC8jvK62QKC64i2qP7NJIW66FO3w8VJkxwW9hhlyPajZtLz
    ikbBXs52B2CmA5HwO2a8/LjxPiS/c6lKXlDeeIs6SSwxxMRlUmLIR64JIP5VCsa2THTb3Ko/FxM64trc
    DH/ODH5HrTViq92ZOTZDRcSlkCi4VZCcjQAMgeeRTKUEuDNNjAS9UhnIMi9XVSdv0pbh4DuXUTvqE7yM
    PJYBjHXr1+ta14BXsVkt5GJklmcZ3Vnddh5bfxVYyXCFaZb7IzLqjZdA31aj19RW1ezUKzWmqLQDGD3G
    MCqKe9iuO1Cz20eCkZjXbfMex9TVFJ+RHFeAItDE+UkDKxxsmAo+eaZztAUKexxH2y0RQS7Y9E/zr6ju
    wPgfhdQ/H8ghxe0yAuW+WKXvxHX07M+WkebikSknkr9c0vfXop/TJeZFX4vzIzyUCkYyQNWkfChLqPQ+
    P6Wk7nK0BF7dMBzJmVSuRhQD19OlSeeb8nbHoMC30gjJcacNczMSSuAd8Y2IB7UjnJvktHBiitooVVJZ
    JBpmcluikEEH5ilbY6SXAwlrcFCZJJN1ypRgWJFK5sZYxlHnDKEmnSTuHBGr+DQjmmnszS6bHNU4r9h5
    LribIrtaMwzjKbn44+NWXU5W6RyS+l9Mlcl/J0NnwU8QtRNzrm1fo0c0JB+IA7V1Kc5LfY5vh4IPZWTc
    8LfhxMbXodD1JDLn6r+9FNryaWKH+KAxwINxJnbGVJNOn+SEscapRJkMSZUzt8D2qqkck8MQBCfhbPlg
    VROzjyQ0llUHufkaYjqaDR4QghunmxFakBTaYyt0SdifLrml0llmfkvz3O+T/FBoqspYXHi317D1pHEs
    s3gsswOD4yepORSNFY5PRoQyaYtQRsY9ahJHdjntZPPDMOoHcDpUZROqOQsCuokOT30hd/lUmi8ZBGUv
    jlkoOp22+dTZVMvDEBIG1lgBjw42+f8AlUp8HRj5CzwSlgY4kY9vvDv9K5W15Z2xT8ITZLskoYBgnoXO
    QKm3Hmy0dfFC8iz6wXjkYDqY5Nj8Rik+2tgvVe44I40P3EcLYIYcyRkIOO2wFcrt/qZWl/agk11fPbKi
    21sFGNIOpt/Skjix3dsLcq2QGGPizq4EKgk7lNiKo1iXkVa/Q1/TJovHNDMp7EnI+YpHJPgZUMRWqlNS
    a0fvpBGaRsP/ACW5GkFJY7hk/CEOR+YoqXoGktCsJlEaNIAfeDrpx88fpRbfJkjz8MB08lUBx0Z1z+ZF
    NGXsDSQReHEgF9QcjHgkVfyyf1rajUFm4bE0R1SED8QkGAfmBQUmgszpraOBz/5QC9CrnP0xTptg2R8C
    Os6S5VZCM5Y6j9POvorPmiSJinhck57qM/XyrGPcuZiFkjYP3LN1HwoWGhy2xpAnaIoPwsME/wAdaVlI
    /kLy1iUyQhSzAZJIO3lQ1G0+Ry2k0gS8sSIGIJLkj642oOTHjFDNnYX3EJi8VpIYpXK81mwD6E4/Ot28
    kuDaop7nUWvsKsaCXitw0KkatjgfAk7nr2FVXTvyI80TQhTgnCiTaXGTpwWmiLtn093aqxxKIks7apFD
    7TyxgGKKHwe7rRT+fWqKlwc88jfJl3PGLi6naSS4CAn8JJx6CntkJNC0t40jFQ7MnUautOrZz5MkY8sH
    l32bJHljFUUDin1S8HhGNs4qiSOOWaTCCJdJG+T60aJObssE0nIx8cUQXYaI77qH26HO30oitpB4nVGB
    aENv3zREUqdmhILWJEYI5LdtK4/ypPuOq8aSf/oGV5wQwxAHuWIxQ45HVSrSEEVwNkUEDsen1qbaOmCf
    gKouEGJG0DzzkfrUpKzphJrkYhE0g+70SY23b9POoSXs68c34CRXCsW5sTAqeykkVKUfR0Y8q8jkc9kT
    4pGBP9wK1BxkdcZw9hTb20uOS2564k/mpttcnRCnwQbQxxaSojwdismM/lXNLdnXB0g0dkGGoOxHmZA2
    fniuabOuAccMnCs0axhewzv9K5pSXkqi8NpMUxIYmXG6vFqH6/nUZSXgzQVeHWBUmaKMEf2KRS65h0oU
    uhwq4QILh9Q2Gkt/vTxWRO6NcWqG7CCOFQcyTqfxDfHx70JWbbwacd3GxePDb9C4P8UqEcWSptdZXU2v
    G41ZHy2ptgfcVktYHxy5985xzcj8xR2MpS8lf6fwxCJGWONm38LZ/fFNbF3vYFNPZxqUjmMmT0JBPyOK
    1DK/IF0ijYMbm7XbOMqP5ooO7EL5rN1OtrktjOtlH6gU8b8Af5PzsbG52KozsNzjevoqZ83Zow8Kv7iN
    FWCUqp8W+M/CsoyY1o0bfgN3JKFeeOJeulfGy/E460yxNsDyJDLeysMcymcSyRH/AJhOx+IG4qnZoTuJ
    nUWS8MsLXRBw6xWYDGt11EH4naqLFFAeelsikPFVinVooYOYpyObCGGf8IGKdqBJZZEXnGru5BEskCkb
    AxIEx8MChdbI2q+TLNy7Elp5Gx0w2cUqsDkLSSJknDEnuTmswWCJZtsH0z0oqNkp5FFFkUk4HzwKtGB5
    +bqfQwqsvUE/FqqlRwylq8hVbV5n4DNGxNDfCLBwvXUMVlJG7U34LKyvvkbetMmmI8c4+AiocfhI+OaZ
    Im2FUAnf9KIjsC99a29xyZJ1STTqweg+dJLLCLps6MfR580NcI7BrG/try7a3icvIoyRnAI8we9BZoSe
    lFZfT8+OOuS2HRxu14dfrb6HkWM/+J04PL22A33Oevl061z5ctOken0fRNwcpbGlwXjUN/fusnDbiC1M
    erVK6qxwdyBjsuTjY7GuTL1Dik6PSw9DHywvCvaDgvFL+5txaSxW0b8sTiUEnfAJHYHtjNTzdS8bXovh
    6GE0/Y9Yv7O8Vufs/C+LATdRqQjXv0UkDPyqjne7JLp0tka8XAHmTQJtejqdHX60sk0x4xTVEv7KTBF1
    BnzuArft/nU7KKBQ8IfQqxxjIO4CnP71Jo6Ugy8PuBIRoYgjJ0kfvUJwZ0QkGNhNFbao0QN1IIJI+VRe
    JyLrKlsUguHaQazHn8Sg7gfI7VzZena8F4ZVJcjstnDIFlhLpkZyGyBXG4v0UjN+TOngSeVuTeyow848
    jPxG9PFKK3QG23sKy2vLUpK0sxOxKHP64q0UnugNvhgY7qC1jOu4u4xnGhoTgfMA00sLb4FWVImK6iJL
    x3YXPU3ET/utI8T8oZZUwySguc3FrKAO50H8/wCaV4/wMpjEMio2I4iqAYDbED5jrSOIbsHpDtmKfU4/
    tU5z8aP+0Yo3OgbLyOc75PQflityEvFfFZR/4nUAuBq0kD9K1fgBBiS4fVpZsdTG38ULoaj41HJeNHuh
    VfI4G9fXKMj45ziXZ7t1AZ3QHZQpNGmDurwEiQKCCxB7gvvR0g7ljbX7iExCUaG2OT2ot+AqwCS6TpEu
    RjYelLQbI58265YL2zWo2wJjI4xrZ/ILvWow1bWV5dyKkUDPk4GRn/KmSYp1vD/+H/E7zZlwfJR7tFyS
    5D22zet/+GcNqga6laRz0jTxZP6UFlXgD6dPkPL7Cxx/+ba6s+7ED+tFZr4Yj6SF7oyOI+x0FpHJNdPy
    3xhUz09MVtWoZYIw8GFc2axW7tgxwDG5G5PliklZaEYrwX4fNbTWU0AtyZV3jkH4c7b0FY7UX4LWXs3x
    Hicpis7Y/djxtqwB64G9bW1yK8MH4N0ewVvFba73imlyM6Ioi5J+tVjOfhHPPpsb5ON4nGeGW082nWFY
    xxbNgnPUjAGKaeWcVZGPQ4ZPdbnIzXsrXobUGQsNTYwT8vI74Fcrm27Z3wxxhHTFbId+12wjmuIbUpcx
    p4JE1AE5G2On1oN+UOvTMpb2NneQIisRlsDJ657996XUMoomPjWuVYZ5pHiUYj3yFJ6/Xb6UItJ2GTvY
    pcyGKZprXUqmPEuk9Rn+cUrpuwq4oHb8QMcYEcaq8TAo2TkGje1AXNn6B9gfbBON2zxS3UEl+h1EAYbR
    67b4O2fhSwTrSymSm9UTsW4k/MIkhxGNskVXtKtmQ7rsNIVdFIbSvUMqk1LSXUwIjgjYltieuQRmtobD
    3K8AuVaSNjlknGPFg4o9utzdxvYUfg0POaRYUIb3gDpz/NBqLGUmiz2XD442WeUqvveHPh+m9TeG/A/f
    a8is3AEuVLW11NGgPVQenrk1KUNq0plVN3bk0Zt1wCVAdN9cMAc6UJJP1Ncr1LdYzoi09nMyDbMmXMd0
    OX1NxJsd/wC3P60YZYp1OI0sTq4SAztLltZ0KDgMp2P0rrjihNWjllknB0xaSxkmRSzSOCcg6lB/18af
    sRXAvdk+RaV76xGIOZ8dar+hqcsMHyOsskJpxW4SbLaEc7kyEn8waV9PFoKzys1eHe0ciSYljjKd2DkH
    865cvSqtmdGPqL5NkcR4VckFuQWA/E1cjxZI+DpWSD8jWq0VAyNEgHQjBGanpkPaPj6PbxZIdjkfAGvt
    KSPg6kyhulBBA1Edz+1K2ikYMG92+QQwT1C0rKJJATKSf78+YxQofUjwkcNhV38lH+jWpi60N2FvC8mL
    qRVBO+psfzmmjD2B5Udfww8AtJFLtFIAN8nb9aooqga1Z1Flx3hUL4trdWLdHAwPqa2lsfuR8Gyvtbbx
    hhkKiDdIxnP81N4h+6qDL7UQRRxzRPoJGzSscD4jFK8LfIyyotF7WQ6D9mnNxcH3pZl6f4V8qV4fYyy+
    hCa4sL24517NrlDeJZfCc+i9viaoo0qQjabNQ2nB1sA1pbQTFnJyz+FW+PWp/de4/wBtbGFeezcwDEsA
    wGrSqERj543p00xWmisK8b4dZlLe5tR4dAcABgPQdabSnyK5Mz7tP6daLecSvW3OpY4kJd/LA75proXk
    4T2k9rZOLXxWIpHw5QY0gkQ+M/3MeoPX12+NRlkvZcFYwrk4+WVW1ZnLJqHjyABv9SKgVGrTkzgpBdDm
    atgxIJHw7isFCfFLF4pVOkoSNj2/2oNBM1bd1u41KEEvjfv3NKDya8OXuXQJqAUKSDkdc7fP9KyGZSWy
    aISSJGrKG1B8Yypo0AZ4FxKbhnEftNtsHDReF9JII9KFcDJ0fRbX234ueHhEngjaPKGW6jKMRgEb5xqU
    Hfbfrg4NPGbWzBLGnukbfBPafjVnBFO17b8VtH94RMv2hflsGI9OtLe1sLhvsd3wr2h4bxizE0FxHKhO
    hkbwsD5EHcH0pLTew1SS3KmxhhumlEzBD+Bl3Wrfc1QqpOwfFvajhns/wx7iVJJWGAkUYy7sdgAP3Owq
    bxS5HU0y3CeLcP8AaG1SVHCT6dTwgqWX446j1FCpRDqixxpRZqxj1v8AL9c0jhKTuhlOKVWRDd8wZaPt
    0ABoOFBUrE761tLtSz2hBGQZBgEVKcE0WhNpmVa+z3CbKV50ttcsgw24H+/61OOSUWUlBSCPwFJj9ogk
    aJQSRqQeXfvTfLl5Qvx1xZgcQs5YpQrXuok4wIioPzxikl1MWVjgkjOfgTXLkS2SSgfjUKcfpUflRXDK
    Pp2+UZ957EuoaSCRYs7k6GOPpV8fVqXKOfJ0lfpZmt7O38YLpIJV80UH9RXZGUZHLLHOPAa2tLuHfVKD
    6LinfTxkIs8onFlirZxkn6V3UeL3EULMxHQD6ChQHlIKdMZP+LpW0ivMwyRSH3jgflTKJGWZ+AyykDTH
    0+A/Wm2Ec35KySMwGpy3oe1ZmTZQSFTkHf0Ga1hthxeXKrgzkZ+VMbW/BdJ5QCea3wBrNpDRcmF+1zSk
    BndiOgJ6VJzOuK23G4OLXduhWNtAO2x/1vQ1Ma6HLbiQSUmXLKxGvJ6/EmmTQLZ0w4obayaaG9CRp03D
    MufL1qjiqsKk+By145LLZgLdSFQwJ5oyf1oaUNqZHHPa4cEsM2ojfiEx0prwBGD1c+f8mkyKkPDdnzHi
    fEOJcWvJLuRPtJPikCSDKkkjYZx8sVzSk7OhRVGFc8qRyJNXJYFmVmyYm9DsN/nUxiCsF48cEFwQqrkA
    jBJHYUGwpGfd6kmCsQWAHiG2fKgYfs+JNPZyWd25kQ+KJm6qw6jPqKxkx5+HXFpEojj57ga4w4ycAeID
    HXbt6Vmmgoi3hW6tIpLfEThCzg78zHUfHvSRUm6GdVY0Emls0DQAxOpxIp6ds/Xt61nOtmFRvgQMEllq
    EsLRjQHCnfbrt8qKsV0elvL23++V+bbT4Z07HyOeoPrRaMpNDlhYyXjwx2lwSrHAEqeJT5Zzj+aWLd1I
    etrR1PFPZy+4BwZr5+OXrK8qJIIsAEnudzkYGOlWyYYqN8snDNLVXBmcL9qJ/t8FxNxGYpC2MO5zGue2
    d65JqVbHVjmr+7g+pD204ZFDBZ8buLW6uZWGp7cawiMMq0hwADg7qM1XHklHexcmOEtqoJP7Qez1o8aw
    6pEJIE8WnCY2yBnJHwFF9dFuqbFXRSSu0a9tx7nBYo7mC6UnGk5En0NPCWOe8dhJ48kP1GlLErWvNiiO
    R1C9RT+aZKzkr/iUrT6oDKxX3kU7jH50JYkXx5WeTir3VsguUmQdnAyR+4rlniZ1RmkLy3HE7Vz9mlMk
    bH33JYAf4SP3rnlja3ZdST4Nq0v47m30XUaOxGPAcj6H+ak4QkNc48A3MEA1wQMo/EwzpB/PFceXA+Ud
    MMqezLLeyIPCUCkd8kH9ajBb8lJENcCTd4kwPxIw2/Q134pziubOXJCMvwJSC1llzzoN+7ZDfUbGu/H1
    DSOLJ06fJ8V5bY3X55r2KZ8hqRdIo85D/IDf61kkK5S9Fg7ISqjf4UUwNJ7s8+XOOWBRasy23sro28fS
    hXsOr0Udo190AH13NBtDJN8lOYx6lgPX+KFjaV4PBjq8Iz8qDlRSGPVyFVHY5I+lI22dKSXARCwxlmC/
    ClGolptyARjrWsOkJFcAEqyk5B90Z7UUw6QsTOU0kMYzuR1o2wpI6m247a8M4QrvyV8Qj0FfExIzsflV
    e5GMbZljbZw/HH+38Tkv55g/MOTECSUT8INck5anZ0xjpVCaQQxzaGzoddgPdzn0qY6E7u0MkgCF22Og
    dvgKFhaBQW7hVkRtRGDgHo37GjQpqI1rOdd1aDmEkHL42z28q2wQB4XZxXjqk+uNVyoOx6d8dcf6FDY1
    DEfELo2ywRqrqo2lPXboR8BsTWbtUNFU7Os4fwmw1w8uUxzEAmN1yGbHi0n18qtiUdSFyKVMBe+zv2K7
    SHWxtmfmRaDjIOx/g0cnT77cCQy7GX7RXVrDfzIJAWhjCMFGc5PQeg6VPL9sqXgeG8bYm19bcStmhjRY
    umELbn4HvUZSaKRSZlRGS2uopGj1iJxhQwy2OlHUCtzsuI+0v2rg0lvBCJA2FuCSVYjY6sdDjoT/AL0v
    3LZMq5Ra4MniVja3HDo5bUsGCkHbZvMj9CKnjbum7GnFONoVs9awaJUKSR4B9R2qzVEkwsqkFXjOATqz
    ncN8KFBs63gvEJZbOGdGPMg8EgHbfY/A/wA0uNachaUtWM+n8E4lJKADN2yoO/yzXbp2OGfNmpNb2124
    N3AokU5WVcAj50u/gC5sWvLBY4GQAFTsrdR/IqaVO0dCnapnP3dw/DQwh5gUY1EEkqf3FTyK1wXxbeTM
    XjQaQMwZiTnUBp+oNcu3o6d/YweNggmFuW5OAGGot8x+9B6KCtSYSO2upWEhBhRsEHbxehA3qXZhLwP3
    ZRCPb3seSrmRM/8AL6geXWpy6dLgdZ75F5SkqNE9qJF6ZyVYeurGRU6lB7Me4yW6PkugI2ZNR+eK+rpL
    k/P7b/SSZo8EHOPIVrQNEgZbB+7QKPU5NL/oev8AJlgzk4L/AFo2xWkvBLE498H5UWZf6LCzfk84k6M4
    JJxijo2sHc3pIrMn2d1BGoMMqV9elBqho/cWt5YtOXZ0bOCRgg/KpujrhxsWe6QkiLXjPUtnP5bUkn6L
    qILmkjr8qSx1EtyMjIOfPFAdIbQIkCJLG5wuoGIDJG/U0yNRIuY4w7yxZVUJwOmewrWOomXfcdadUWG3
    G248OlR8qjKbZZRSMWW5nmdw4ALnU+V6nzpDFFlmAGmU6VGAvXAoGJ5txIu7HAOAD39awd2VSaYSa85I
    b4ZrADO90xZyxUEfDbz2rBpkwI3LMjLkZ2I7/Kgwodi+/nj8WvcagCB32H5CshjtbOO5s+KG4uXJjikV
    UJGc9c4+XeuhRadoS09mzoN7krE4DxmXXG2PcY9R6Z2NduN6lucmVKL2OB45w1ZuMl5k2kAG229c2XHc
    ykJ/aYC2rW9+NJ06HwN65ZxrYtF3uemie3mlLldQBQAHoT2zS1Y3DJjvZY3DxgjUc9A31zWMdBwOYTwt
    DJgIGIjJJwM9FG/wxUZKpakdOPeNM6e2sIb3hQnMA1H7skjoRuN69PtqUDh16Z7mSOHBdMbIck4AH51D
    tu9yutVsESyn4dd86GNiCQkvcMhxkHH+tqbtuwdxUbaG54VxMIrMYmwVIJwQe4rqhGnRyTntZ2XDeNs0
    XJuQcqcqxPb4008flCQy+GdBFIVGnOUbfSw6iuaUTpjKjF4tAZQzQsWxswG21ScTohOzjOKIijIXlyjq
    Rsr+uPOoziuToUmZEXEBFKAy4OeoO5HzqLx2OstGtHxtlzoK79g/U+fXr8KlLGVjlQxD7TSkgRSkP0KM
    d/8AX1pNMkOpRkNP7S3aRh5hNpx7wcAfxQ0uXkNxj4Pl/Ld01duxJ619HTZ8NqSdHordpWwTtWULNLIo
    8BDbRopyceWO9NoSE7kmyjIEJC438qWqHTvkGwIwdqDGVFlldc63znoDRTfkDinwgOo5xnNI2VjG2RnL
    YAqLZ2QjseLFRg/lSsskQrbbA5pRg8E7QMTt8M0U6M0Gkv3ddJcMR5bbfKm1GopnmAggDV6UBkxGaFYg
    Sqd6m4jqRnyBS5OT5nalaGslHieEAnDA+eKWg2iseGkOoeAHzxWo1hXjhV8KNIPl2rUG0GEK8ssSxU7D
    +K2lmtDNpbRhssWRm6jJxp+FHSzKSNjhFnG3EFKprCDY43B7VTHjbYs8kUj6RxWwkn4XDK6eKPc+eAOt
    d+lM4u4zPtWC3YVsgYBB89qeMaJznZk8esQ1z90p9/K/PFGULFjkOW4zYzxXMBgUag+o5HUVxZsTvY68
    OVUeu+Em4tXmiQa1xzOg+dQeJo6VkizJjtkEitpU9mzUqGRs8OtY1ZGWQhS3hC7HUVIzQ06nRVNRVn0b
    h/BHmhdLCXEbkHlOdw3oe9etGoo8qUnJmrdcFeEo88IBPXI/Ee9KqkxpNqJqcOsLcRF+TGync47N8KEn
    uCD2GpOGWLHDwghTkKR7vwpdTGpCzcJhYusYCtjwjqpFHuPyDtrwHhVoSiBt9vCT0oOmFXEteqoJm0Eg
    jf8AmoSi/B0QmvJzXFIrQtqGnD76JNhn0Nc88czthkgzmbvh3B7yN0F01ldJuOYMpn4iuf8A/WLurRVr
    DJVdM4a4kvrDirW08WyksHGCCOuQe4roj96tHHNuEqZpRcXAiOkltQxoYA5+XalePcosvopZ3EstyUF4
    0atlTE2wP7VRY0T7r9iDXOsktuSPhXoOdnzSx1siBcuqldRwRjFbWwvGmVMh6k5rWFRRIYncmtZmkUeT
    PT60GxlEHqwPI0LGoqHy+D070kmXxRLcwKc7CptnSkQX3ySMUo6ILj0rBIBDNuBisYuMg+EeGjRrGYtW
    +kH1pqBZdyhGD19azQFISntl1ArGSD5VNxHUgEdiGJGNvQdaGkbUNnhfLh1yDSvXbqabRtuLrB2vCnuJ
    f7FG7HyFaOO2aU0jatuHQzYQtgKMjPkKusSZF5Whk2UWWbAA6DJwPnR7SN3WdF7McPtlkE02DGSMEDY1
    0Y4JLY58mRt0zvrie1EDEkFMaAPj1/Ssk7A5Kjm+dZnjJSSIhACQxHX0qqWxBz3EeNTWphR4feQg58z2
    rPYMHfBh3CrcpDc4Ok7P5gGpT33OiDrYosTRao2X7thjPp/FScSykYnEeE/Zbv3SARsw7GuWeOmdMJ2j
    V4HFLG6opBI3IIyCP9ZrQgrDObqj6DwGQ63SNt86l3/I11PdHIrTOvRkvrCS2kQa/JuxqDuMrRZVJUzA
    sY7mwknQhkC4YZ371ZyUiKhKA4t8/MDtGSudLHyPn8K2hUDW0wt1r5aywkHbOBSqK4Yzm+UXsrq2u0WO
    caH6BhSyhKO6HjkjLZjRgeNSmc+THoaTVZTTXBhcR4dHdHl6Ahb8GPC/w8j6Uz4Gi96ZxfFfZonJR3UE
    dGH5VyZHKLOyEYzWzOdXhHEYpgkWJVXYasMMHsQe1Ljy07RsmBtUOXPCDawgi2UNn/lDUM/CrvLFkFhk
    kITWkckmlkMMw7sMA/xW7kQPFIx7hrQuRGGwAAoHQbfnXbLSfPRU+QQlwmBGufMihY2nfkoxIXLHGemB
    QGW/AIt8fnSjpEFvOsagbN/vStlIxKlwPdpGdMUV5tKULAsd6wbLIjn4nuayQNQ5b2zSSLGqly3kPzqi
    hYkp0PrHDCSQqysBgMdwPWn0pE9Vi7uHODkKO3SloOo9yuYQFX9q1B1BjCjfdodWe5/X4VnEKkMwWawL
    kjUT2oqNG1BZWjaJnIAGenljpRYUBiI+zBE3Zu47mhE0hxALcp4SdS4q62OeTsI6tcKkCjdjmi1Zk6Nk
    aLaxjjgkX7pd8Hqf96otlQklbHbO9e4j0s2lYoySPM9KZOyckDa4UTYODhT+mKInJkl2mVkkAOgEj1xS
    SdjwVA7RiLWaPIOjxL8On8VNcF0zT4IVu4JImwJodQGe9BDoWCrNOY5cEEYGf0pHuU4EYsW98rRsQy5X
    Y4Oak1TKpnUcKvI7gqD91Ou4kxsfjVE2TkkzuLa7SS3UNhZh1z39M1KXJWK2GHuAo5kxwBswK5zn/XWh
    pvgLnp5CiDh3EUIIMUmMGheSH5BWOYuvDmtJNPNDRnpv1FN3b8C9mvJSbgsqM0sQDxnfY9DRWZcMD6d8
    oagEwiOoY8snrSuSY8YSQY2ZmQvGiyL1aM9QfSl1pcjaGI39lDMmoRnV0Zeh+tHZ7MKbW6OXvOGKpaWI
    aiOuRuPjjeozwrlHVjz3tIyWtjpMjRIyk++CP1GPzFQcW9mXjJcoPa8MWZC6HIHdWDY+hqfbfsrrTPk5
    hdYuay6VPTO2flXsVtZ8hqV0C1kZApbH0oIIZCAxA/im0sXWiwSJdXMODjoN61JcguT4BSPDpAAJI8hi
    g2h4qXkWc5bIGKmy0SjeI4pWXiyyoo6nJoUNYxBbvO6JGpLMcDanUbFcqNQW8NkMSgSSH3M9PjiqKKRJ
    zbJMxSBjpIZhvg/lTXsIxIvI22o48h0pTWMQs5IQLqB6A1hrGdcQjZFZQceJuvyFHYAxbvaRRpgiSbqQ
    3c9vgBRVB3G0hnvIpFg2YeIsNsgdh6elGm+DXQveW6wW6Ryk7jUdPU0JRpDKVmdHecpCIokQDbJOanqr
    gdq+T0HE7hWAaZZQvQOOlZZGBwTCT8VmkkymlSNhjufWmeRmUEOyXCvAsZXSSQSQdsD/ADpnLYWh21vB
    bI3iyhwD5etPGVE5xs0Z3iniEqbDYZ8zjp+VWvY563FEkBuCQRoIPyyKUdAYW5F3KjDIGxB7jyqd0yvg
    YtpDZ3sqqd5BlT/d/uKVvceIOR3S85pGY36r3pWyqRa5tGd+egxJjJx+LypHuUSGeH3fImjuQoKE4kQ/
    hPQ/KmW4rtHSvdMJYZLcloztpPVT0xTUvJrfKC2/tHImlZULx5wy9foaV4l4D3a5OitLq0u1Sa0lzt4k
    bY1P7o7SHqMlcDRkuTGoXO4/C3f4VlFMDbQJuJKqa4mVdsEYo9q9mBZ63RlTe0LwTkTxx6TvqQ9R50V0
    22zEfWU/uQ2ntJFGVJILHoQdJqb6eRZdXAK/tFZzgiXDjuyjDL8RSrFJDvNFmbd3cQcNhWjI8E6kkH0b
    uKfSwKaFFtIJy7wlST7yAZHzHX5ipyj7LQmYt3ww29yZbaR4JR1Udf8AMVJwLxmuUfJQZZSC5YjzJru3
    fJ849MeAoC4wmD5mmr0TbfkrJI5IGQAOw7UG2GMULs2o9qVlUqKMcdSKUZFSC5C7knsKAy2CCE6snwgd
    STR0jKQSGISyqkcTPk469aKVhch0XAs3ePJZ2Glih90eQp7oR7lQ7EB5EbceFmPUeVYxY84gSBgSdlUd
    cedGmL5KSa4m2UEHrq6Gg9grctHJLI+kDGdsUFY9IENQlAUFvhSjKjQtFCYMiHUTjFPFCyZvcNtp45Vu
    JG5ajxKq7ZHYVaMXySlIQv5hJKWJyi5ApJKxoyMl7cFtIx5nHaouJVSLLboFzjetpNqJGmMAqo2rDXYS
    aXB0bZ0gbeeaNgovHc+AxkHx9KykBxNCCfVZzQB9IBDLk9D6VVT2J6Nytkz6CSCQD06UIyC4Ap7j/wAe
    5CtvvhjvWb3MkUe9LaS43Q4B9PKlsY27aeO/hKscEHdv3rbDpscSYRt4ympRgKejelLpVFVLc9JJYlkk
    OY1kO/8A0t/FSaa4LqUHya9naLNHqgkUum3hb9q3da5CsClwZCpcWNzIrklGO/mvkRTxypkpYGhqC+kB
    DQMVuUOodtY7g1TWvJHttfpOn4f7RR3UKx30Emn3S6jxIam65gyqviaG5V0nUrLPC3SRdmH+IUyye9hJ
    Yt9tzKueFz3MZIQSRA5BUatP8U3yFH8E/iOX5EEsrhFME9rK0flnIx6bb0j6xIZfT21VAJuEzRS8y2uH
    TyR0IPyzWfURkFdHKHDGIftUcWp0O5wwPut/FTllSLwwvyUlt7kKJ4BLEwPuP+zCpvMiywvlA14pcvmO
    8DMo6Z95fnWtPgaOpP7j42k7s2CdvKqqTPJcEkNR5KZ1HOe1VRCVWQzYONIoMKRQ9KAUQAvlQoNsuJTr
    0KAvQZFGzUem+5nZBvg9TvWewyJEjgaQ7eu/Wsa7LKASqjbJxmiGw1vGbiVlLEBVJHy7UUrA2b3BLSO5
    id22IV2yPJVJxXRjSaIZHTM5og7KckZOPhk4pGhlJ0M8Wt04ZKIYcky41OeuPL4UJrTwNDfkz4547Yqw
    hDuR1Zjj6VNOitWMcNka5md3ONONh33psbtiz2R0l1cGMRQBcmYAtJnfHkK6GRMbiOEkYDonSps1mehO
    ck52zU6HvYK03LjB05Jo1RlJtiyXDO+ogYHQVMsuAkr8wjKjIA3rBssbhyVbYEDFKxkVMjMNWem1AIza
    3sgBj/CRv61rGPTzFpo8jtitbNSIkYxptuG2INawUX4ZcvHckDcYIPrW1MKW41JdlJShTUM43NG9g1uX
    Ls22o48qVjo0bC5fnxAEqWwpKnFI2VjydDn7YrRTbyAeGUbMKm9uDpj92zMiaMXA0uTrQga12Joqbq0I
    4Rbpma13c8PlWWOZmDEhlbfNPGV+CM4teTo+HcdkeZUeLUHOk+M/lVW9tiS3e49xG+uuD3StDMzBtwG6
    j502NRyLdE80pYXs7Cwe0t1dCQSBlZPxRyFc0mTpIMpi67JwaEkUk9lHO1xIyuNRR9/zGK4KSlpPSTco
    6mKzWwCKA7ZbzAIHyxTUCynNkit2jVzpUZ6Df9vyplii1YvcadHOXh5oSdWkRn32fpTOCihNbkf/2Q==
}

DoDisplay
::img::org config -data $imageData
Controller reset

return