Advertisement
Guest User

Untitled

a guest
May 30th, 2012
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
TCL 8.89 KB | None | 0 0
  1. # showimage.tcl (c) 2012 Fermion <fermion_ph@jabber.ru>
  2. # Show images from URLs in a Tkabber chat window
  3. #
  4. # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  5. # 0. You just DO WHAT THE FUCK YOU WANT TO.
  6. #
  7. # TODO: fix multiple urls error, imagemagick image resizing
  8.  
  9. package require http
  10. package require msgcat
  11.  
  12. namespace eval showimage {
  13.     variable tmpdir [pwd]
  14.     variable null ""
  15.     switch -- $tcl_platform(platform) {
  16.          windows {
  17.              catch { set tmpdir $::env(TMP) }
  18.              catch { set tmpdir $::env(TEMP) }
  19.              set null "2>NUL"
  20.          }
  21.          unix {
  22.              set tmpdir "/tmp"
  23.              catch { set tmpdir $::env(TMPDIR) }
  24.              set null "2>/dev/null"
  25.          }
  26.          macintosh {
  27.              # In case when someone would like to implement it
  28.              set tmpdir $::env(TRASH_FOLDER)
  29.              return
  30.          }
  31.     }
  32.  
  33.     custom::defgroup Plugins "Plugins options." -group Tkabber
  34.  
  35.     custom::defgroup ShowImage "ShowImage plugin options." -group Plugins
  36.  
  37.     custom::defvar options(showimage_width) 0  \
  38.     "Max image width." \
  39.     -group ShowImage -type integer
  40.     custom::defvar options(showimage_height) 0  \
  41.     "Max image height." \
  42.     -group ShowImage -type integer
  43. }
  44.  
  45. proc showimage::draw_image_text {chatid from type body x} {
  46.     variable tmpdir
  47.     variable options
  48.  
  49.     ### Before nickname
  50.     if {[chat::is_our_jid $chatid $from]} {
  51.          set tag me
  52.     } else {
  53.          set tag they
  54.     }
  55.  
  56.     set connid [chat::get_connid $chatid]
  57.     set chatw [chat::chat_win $chatid]
  58.     set nick [chat::get_nick $connid $from $type]
  59.     set cw [chat::winid $chatid]
  60.  
  61.     $chatw insert end "<$nick>" [list $tag NICK-$nick] " "
  62.     ###
  63.  
  64.     # Find all urls to images in a message
  65.     foreach {str path ext} [regexp -all -inline {(http://.*\.)(jpg|png|gif)} $body] {
  66.         set imageurl $str
  67.  
  68.         set dirname [file join $tmpdir showimage]
  69.         file mkdir $dirname
  70.         set fname [file join $dirname out.jpg]
  71.  
  72.         if {[catch {fetch $imageurl $fname} err]} {
  73.            debugmsg showimage "Got fetch error: $err"
  74.         }
  75.    
  76.         set image_error 0
  77.         if {[catch {set src [image create photo -file $fname]} err]} {
  78.             debugmsg showimage "Got create image error: $err"
  79.             set image_error 1
  80.         }
  81.  
  82.         if {$image_error == 0} {
  83.             # Replace url from the body
  84.             string map {$imageurl ""} $body
  85.  
  86.             # Resize image if necessary
  87.             if {$options(showimage_width) > 0 || $options(showimage_height) > 0} {
  88.                 set $src [resize $src $options(showimage_width) $options(showimage_height)]
  89.             }
  90.  
  91.             # Insert image
  92.             $chatw insert end "\n"
  93.             $chatw image create end -image $src
  94.             $chatw insert end "\n"
  95.         }
  96.     }
  97.  
  98.     $chatw mark set MSGLEFT "end - 1 char"
  99.     $chatw mark gravity MSGLEFT left
  100.  
  101.     if {[cequal $type groupchat]} {
  102.          set myjid [chat::our_jid $chatid]
  103.          set mynick [chat::get_nick $connid $myjid $type]
  104.  
  105.          ::richtext::property_add mynick $mynick
  106.          ::richtext::render_message $chatw $body ""
  107.     } else {
  108.          ::richtext::render_message $chatw $body ""
  109.     }
  110.  
  111.     $chatw tag add MSG-$nick MSGLEFT "end - 1 char"
  112.  
  113.     if {![catch {::plugins::mucignore::is_ignored $connid $from $type} ignore] && \
  114.         $ignore != ""} {
  115.          $chatw tag add $ignore {MSGLEFT linestart} {end - 1 char}
  116.     }
  117.  
  118.     return stop
  119. }
  120.  
  121. hook::add draw_message_hook [namespace current]::showimage::draw_image_text 86
  122.  
  123. proc showimage::fetch {url fname} {
  124.     set Stat "skip"
  125.  
  126.     set f [open $fname w]
  127.     fconfigure $f -translation binary
  128.     set imgtok [http::geturl "$url" -binary true -channel $f]
  129.     set Stat [::http::status $imgtok]
  130.     flush $f
  131.     close $f
  132.    
  133.     http::cleanup $imgtok
  134. }
  135.  
  136. # Very slow. Tcl is not fast enough by itself to process images
  137. proc showimage::resize {src newx newy {dest ""} } {
  138.    
  139.     set mx [image width $src]
  140.     set my [image height $src]
  141.    
  142.     if { "$dest" == ""} {
  143.          set dest [image create photo]
  144.     }
  145.  
  146.     # Calculate other side if one of sides is not set
  147.     if {$newy == 0} {
  148.         set newy [expr {$my*$newx / $mx}]
  149.     }
  150.     if {$newx == 0} {
  151.         set newx [expr {$mx*$newy / $my}]
  152.     }
  153.  
  154.     if {[expr {$my*$my}] <= [expr {$newx*$newy}]} {
  155.         return $src
  156.     }
  157.  
  158.     $dest configure -width $newx -height $newy
  159.    
  160.     # Check if we can just zoom using -zoom option on copy
  161.     if { $newx % $mx == 0 && $newy % $my == 0} {
  162.    
  163.          set ix [expr {$newx / $mx}]
  164.          set iy [expr {$newy / $my}]
  165.          $dest copy $src -zoom $ix $iy
  166.          return $dest
  167.     }
  168.  
  169.     set ny 0
  170.     set ytot $my
  171.    
  172.     for {set y 0} {$y < $my} {incr y} {
  173.          
  174.          #
  175.          # Do horizontal resize
  176.          #  
  177.          foreach {pr pg pb} [$src get 0 $y] {break}
  178.          
  179.          set row [list]
  180.          set thisrow [list]
  181.          
  182.          set nx 0
  183.          set xtot $mx
  184.          
  185.          for {set x 1} {$x < $mx} {incr x} {
  186.            
  187.             # Add whole pixels as necessary
  188.             while { $xtot <= $newx } {
  189.                 lappend row [format "#%02x%02x%02x" $pr $pg $pb]
  190.                 lappend thisrow $pr $pg $pb
  191.                 incr xtot $mx
  192.                 incr nx
  193.             }
  194.            
  195.             # Now add mixed pixels
  196.             foreach {r g b} [$src get $x $y] {break}
  197.            
  198.             # Calculate ratios to use
  199.             set xtot [expr {$xtot - $newx}]
  200.             set rn $xtot
  201.             set rp [expr {$mx - $xtot}]
  202.            
  203.             # This section covers shrinking an image where
  204.             # more than 1 source pixel may be required to
  205.             # define the destination pixel
  206.             set xr 0
  207.             set xg 0
  208.             set xb 0
  209.            
  210.             while { $xtot > $newx } {
  211.                 incr xr $r
  212.                 incr xg $g
  213.                 incr xb $b
  214.                
  215.                 set xtot [expr {$xtot - $newx}]
  216.                 incr x
  217.                 foreach {r g b} [$src get $x $y] {break}
  218.             }
  219.            
  220.             # Work out the new pixel colours
  221.             set tr [expr {int( ($rn*$r + $xr + $rp*$pr) / $mx)}]
  222.             set tg [expr {int( ($rn*$g + $xg + $rp*$pg) / $mx)}]
  223.             set tb [expr {int( ($rn*$b + $xb + $rp*$pb) / $mx)}]
  224.            
  225.             if {$tr > 255} {set tr 255}
  226.             if {$tg > 255} {set tg 255}
  227.             if {$tb > 255} {set tb 255}
  228.            
  229.             # Output the pixel
  230.             lappend row [format "#%02x%02x%02x" $tr $tg $tb]
  231.             lappend thisrow $tr $tg $tb
  232.             incr xtot $mx
  233.             incr nx
  234.            
  235.             set pr $r
  236.             set pg $g
  237.             set pb $b
  238.          }
  239.          
  240.          # Finish off pixels on this row
  241.          while { $nx < $newx } {
  242.             lappend row [format "#%02x%02x%02x" $r $g $b]
  243.             lappend thisrow $r $g $b
  244.             incr nx
  245.          }
  246.          
  247.          #
  248.          # Do vertical resize
  249.          #
  250.          if {[info exists prevrow]} {
  251.            
  252.             set nrow [list]
  253.            
  254.             # Add whole lines as necessary
  255.             while { $ytot <= $newy } {
  256.                
  257.                 $dest put -to 0 $ny [list $prow]
  258.                
  259.                 incr ytot $my
  260.                 incr ny
  261.             }
  262.            
  263.             # Now add mixed line
  264.             # Calculate ratios to use
  265.             set ytot [expr {$ytot - $newy}]
  266.             set rn $ytot
  267.             set rp [expr {$my - $rn}]
  268.            
  269.             # This section covers shrinking an image
  270.             # where a single pixel is made from more than
  271.             # 2 others.  Actually we cheat and just remove
  272.             # a line of pixels which is not as good as it should be
  273.             while { $ytot > $newy } {
  274.                
  275.                 set ytot [expr {$ytot - $newy}]
  276.                 incr y
  277.                 continue
  278.             }
  279.            
  280.             # Calculate new row
  281.             foreach {pr pg pb} $prevrow {r g b} $thisrow {
  282.                
  283.                 set tr [expr {int( ($rn*$r + $rp*$pr) / $my)}]
  284.                 set tg [expr {int( ($rn*$g + $rp*$pg) / $my)}]
  285.                 set tb [expr {int( ($rn*$b + $rp*$pb) / $my)}]
  286.                
  287.                 lappend nrow [format "#%02x%02x%02x" $tr $tg $tb]
  288.             }
  289.            
  290.             $dest put -to 0 $ny [list $nrow]
  291.            
  292.             incr ytot $my
  293.             incr ny
  294.          }
  295.          
  296.          set prevrow $thisrow
  297.          set prow $row
  298.          
  299.          update idletasks
  300.     }
  301.    
  302.     # Finish off last rows
  303.     while { $ny < $newy } {
  304.          $dest put -to 0 $ny [list $row]
  305.          incr ny
  306.     }
  307.     update idletasks
  308.  
  309.     return $dest
  310. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement