;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; hotspots.scm ; ; ; ; Provides Hotspot-functions for HTML-Imagemaps ; ; ; ; Simon Budig, ; ; http://www.home.unix-ag.org/simon/ ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This Script-Fu provides two functions: ; "script-fu-selection-to-hotspot" interprets the current selection as a ; Hotspot. It stores information about how to interpret the selection-bounds, ; and what HREF and ALT options are assigned to the Hotspot. ; The selection-bounds can be interpreted in two ways: ; 1. As a rectangle (straight-forward). ; 2. As a circle. Since HTML doesnt support elliptical hotspots ; the minimum of (width|height)/2 will be interpreted as the radius. ; "script-fu-save-hotspots" saves the previously added hotspots ; as a HTML-fragment in a file. If no filename is given ("") the map ; will be written to stdout - useful for cut'n'paste. ; This file is ready to be included in the HTML-file, where the imagemap ; should be placed. ; Then add a at the right ; place and the imagemap is complete. ; - It is a nice feature, that the hotspots will respect a rescaling/resizing ; of the Image, since the coordinates of the hotspots are calculated, ; when saving the hotspots. ; ; - To check, which area is covered by a hotspot, open the Layers&Channels ; Dialog and make the associated channel visible. The hotspot-area ; will appear lighter. This is always correct for unscaled Images, ; but is incorrect, if a circular hotspot has been rescaled. Then ; the hotspot will appear elliptical. The inner circle will be used ; for the hotspot in the imagemap. ; ; - To remove a hotspot simply remove the associated channel. ; ; - The informations about the hotspots will be preserved, when you save ; the image as an XCF-File. ; ; - HTML supports polygonal bounded hotspots. This is IMHO hard to implement. ; I dont want to program a trace-program to restore the selected polygon, ; especially not in scheme. So this option has to wait for a plug-in. ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; OK - Here we go: (define (script-fu-selection-to-hotspot inImage inLayer inURL inALT inType inKeepSel) (gimp-undo-push-group-start inImage) (let* ( ; Store the current selection and calculate some coords (orig-selection (car (gimp-selection-save inImage))) (dummy (gimp-selection-sharpen inImage)) (selection (gimp-selection-bounds inImage)) (center-x (/ (+ (nth 1 selection) (nth 3 selection)) 2)) (center-y (/ (+ (nth 2 selection) (nth 4 selection)) 2)) ; In Imagemaps are only real circles allowed, so we have to ; calculate the min. (radius (/ (min (- (nth 3 selection) (nth 1 selection)) (- (nth 4 selection) (nth 2 selection))) 2)) ; Select the really used hotspot (dummy (if (= inType TRUE) (gimp-rect-select inImage (nth 1 selection) (nth 2 selection) (- (nth 3 selection) (nth 1 selection)) (- (nth 4 selection) (nth 2 selection)) 2 0 0) (gimp-ellipse-select inImage (- center-x radius) (- center-y radius) (* 2 radius) (* 2 radius) 2 0 0 0) ) ) ; Save selected Hotspot (hotspotchannel (car (gimp-selection-save inImage))) ) ; Store Type, URL and ALT-Text in the Channel-Name: ; "Hotspot (Rectangle|Circle): {***}" ; (It is impossible to enter URLs with an {***} - but they are rare :-) (gimp-channel-set-name hotspotchannel (string-append "Hotspot (" (if (= inType TRUE) "Rectangle" "Circle") "): " inURL "{***}" inALT ) ) ; If the user doesnt want to see the real selected Hotspot, restore ; the original selection (if (= TRUE inKeepSel) (gimp-selection-load inImage orig-selection)) (gimp-image-unset-active-channel inImage) (gimp-image-remove-channel inImage orig-selection) ) (gimp-undo-push-group-end inImage) (gimp-displays-flush inImage) ) ; Register the function with the GIMP: (script-fu-register "script-fu-selection-to-hotspot" "/Select/Save as Hotspot" "Mark selection as hotspot" "Simon Budig" "1998 Simon Budig, " "23. May 1998" "*" SF-IMAGE "The Image" 0 SF-DRAWABLE "The Layer" 0 SF-VALUE "URL" "\"http://www.gimp.org/\"" SF-VALUE "ALT-Text" "\"Gimp-Homepage\"" SF-TOGGLE "Type: Rectangle (TRUE) / Circle (FALSE)" TRUE SF-TOGGLE "Keep Selection" FALSE ) ; the save-function... (define (script-fu-save-hotspots inImage inLayer inMapName inFile) (gimp-undo-push-group-start inImage) (let* ( ; Save current selection, open file, initialize some Vars... (orig-selection (car (gimp-selection-save inImage))) (outFile (if (> (string-length inFile) 0) (fopen inFile "w") ())) (chanArray (cadr (gimp-image-get-channels inImage))) (chanNr (car (gimp-image-get-channels inImage))) (chanName "") (chanArea "") (chanURL "") (chanALT "") (chanCoords "") (chanType 0) (chanIndex 0) (chanCurr 0) (selection ()) ) (fwrite (string-append "\n\n") outFile) (fwrite (string-append "\n")) ; For each channel (while (< chanIndex chanNr) ; gain information about the current channel (set! chanType 0) (set! chanCurr (aref chanArray chanIndex)) (set! chanName (car (gimp-channel-get-name chanCurr))) ; Check if it is a Hotspot-channel (Well, most probably) (if (and (= 0 (string-search "Hotspot (" chanName)) (not (= () (string-search "{***}" chanName)))) (begin ; select the hotspot-area and get the selection-bounds (gimp-selection-load inImage chanCurr) (set! selection (gimp-selection-bounds inImage)) ; if it is a rectangular hotspot... (if (= 8 (string-search "(Rectangle): " chanName)) (begin (set! chanType 1) ; extract URL from Channel-name (set! chanURL (substring chanName 21 (string-search "{***}" chanName)) ) ; extract ALT-Text from Channel-name (set! chanALT (substring chanName (+ 5 (string-search "{***}" chanName)) (string-length chanName)) ) ; extract Rect-Coords from selection-bounds (set! chanCoords (string-append (number->string (nth 1 selection)) "," (number->string (nth 2 selection)) "," (number->string (nth 3 selection)) "," (number->string (nth 4 selection)) ) ) ) () ) ; if it is a circular hotspot... (if (= 8 (string-search "(Circle): " chanName)) (begin (set! chanType 2) ; extract URL from Channel-name (set! chanURL (substring chanName 18 (string-search "{***}" chanName))) (set! chanALT (substring chanName (+ 5 (string-search "{***}" chanName)) (string-length chanName)) ) ; extract Circle-Coords from selection-bounds, ; get the minimal radius, because HTML can ; only handle round cicles... (set! chanCoords (string-append (number->string (/ (+ (nth 1 selection) (nth 3 selection)) 2)) "," (number->string (/ (+ (nth 2 selection) (nth 4 selection)) 2)) "," (number->string (/ (min (- (nth 3 selection) (nth 1 selection)) (- (nth 4 selection) (nth 2 selection))) 2) ) ) ) ) () ) ; if it was a selection, write the AREA-Tag to the file (if (not (= chanType 0)) (fwrite (string-append " (string-length chanURL) 0) "\"\n HREF=\"" "") chanURL ; if there was an ALT-Text... (if (> (string-length chanALT) 0) "\"\n ALT=\"" "") chanALT "\">\n" ) outFile ) () ) ) () ) ; Next Channel... (set! chanIndex (+ chanIndex 1)) ) ; Finish the file and restore the previous selection (fwrite "\n\n" outFile) (if (> (string-length inFile) 0) (fclose outFile) ()) (gimp-selection-load inImage orig-selection) (gimp-image-unset-active-channel inImage) (gimp-image-remove-channel inImage orig-selection) ) (gimp-undo-push-group-end inImage) (gimp-displays-flush inImage) ) ; Register the function with the GIMP: (script-fu-register "script-fu-save-hotspots" "/File/Save Hotspots" "Save marked hotspots to disk" "Simon Budig" "1998 Simon Budig, " "23. May 1998" "*" SF-IMAGE "The Image" 0 SF-DRAWABLE "The Layer" 0 SF-VALUE "Map-name" "\"IMAGEMAP\"" SF-VALUE "Filename, (\"\" = stdout)" "\"\"" )