#!/users/fdc/bin/wermit + #!/net/u/1/f/fdc/bin/wermit + #!/usr/local/bin/kermit + # .version = 3.15 # Version of this script .date = 2023/01/26 # Date of this version forward :START # Jump around all the comments # Creates a photo gallery from a collection of JPG images. # Requires C-Kermit 9.0 or later (free): # http://www.kermitproject.org/ckermit.html # # TO USE: EDIT THE TOP LINE TO SHOW THE FULL PATH OF C-KERMIT ON YOUR COMPUTER # (FOLLOWED BY SPACE AND PLUS SIGN) AND GIVE THIS FILE EXECUTE PERMISSION. # OR (easier) INSTALL IT USING THE getkermitscript SCRIPT: # http://www.kermitproject.org/getkermitscript.html # # Author: Frank da Cruz, Bronx NY # Email: fdc@columbia.edu # License: https://www.kermitproject.org/scriptlicense.html # Documentation: https://www.kermitproject.org/photogallery.html # # Makes an index page with thumbnails and then a page for each image with # forward, back, and index links, with an button to click to see the original # image in full size. Pages can be in Spanish or English. # # To use, put the desired image files in an empty directory, # cd to the directory, and run this script with the desired options # (you can also make a gallery in a directory that has other files in # it but for that you need to read read the documentation). # # Usage: photogallery [ keyword=value [ keyword=value [ ... ] ] ] # # If a PARAMS file exists, runs with those parameters. # If an IMAGES file exists, creates the gallery from the given list. # Otherwise, and no parameters are given on command line, a help message # is printed. Command-line parameters override PARAMS file parameters. # ############################################################################# # THUMBNAILS AND RESIZING: # # If ImageMagick 'convert' is available and you have not specified otherwise, # it is used to generate thumbnails for the index page. Otherwise the # thumbnails are the original images, scaled by the browser to the default or # specified thumbnail height. ImageMagick can be found here: # # http://www.imagemagick.org/ # # Alternatively if you can make thumbnails some other way; they will be used # if they are already there. For each image file xxx.jpg, the corresponding # thumbnail must be called xxx-t.jpg; all thumbnails should be the same height. # # Image Magick is also used, if available and desired, to resize the original # images so the sub-pages fit browser windows of the target size and don't # take forever to download. Or the originals can be shown as is, with scaling # by the browser. Resized images are named xxx-r.jpg. # # NOTE: 'convert' geometry (e.g. 1600x1200) is width x height. # ############################################################################# # # EDIT HISTORY # xx Dec 2001: Initial creation for private use. # 09 Jul 2006: Converted for general use and installed as photoalbum.ksc. # 10 Jul 2006: Fixed some typos and fixed the test for Windows. # 11 Jul 2006: Added RESIZE option (RESIZE=n, pixels, default=760). # 11 Jul 2006: Reduced disk size of thumbnails by factor of 10. # 12 Jul 2006: Don't give HTML HEIGHT or WIDTH attributes for resized images. # 12 Jul 2006: Keep and link to original when resizing rather than replacing. # 15 Sep 2006: Fix NOSCALE result; add "arrows" option for navigation links. # 16 Nov 2006: Colors for links; fix help text; allow "-help". # 12 Dec 2009: Nicer default colors; give usage message if no arguments. # 07 Aug 2010: Put alts and better titles on images; new default colors # 05 Oct 2010: Change defaults for most common usage # 01 Oct 2011: Kermit Project becomes independent of Columbia University. # 07 Aug 2012: Custom version for parades # 14 Aug 2012: Changes to allow editing of pictures and captions while # waiting for more pictures to arrive: # . Create resized file only if original is newer # . Take captions from external files # . Read index text from index.txt file. # . Fix permissions on index.html. # 09 Sep 2012: Allow importation of head and tail HTML. # 16 Sep 2012: Make caption same width as picture and underline URLs. # xx Jul 2013: Add tool tips for arrows; take parameters from PARAMS file. # 30 Jul 2013: Allow for deletion of originals. # 07 Aug 2013: Merge the different versions of this script into one. # Supply head and tail code if no external head or tail files. # Allow for BASE and non-BASE linking. # Polish for general use. Call this Photogallery 1.00. # 07 Sep 2013: 1.01: Allow image names to be taken from a file named IMAGES. # 08 Sep 2013: 1.02: Normalize image filenames if asked; allow image sorting. # 09 Sep 2013: 1.03: Fixed some bugs in adding new images to gallery. # 14 Sep 2013: 1.04: Added Javascript to make image scaling work in IE. # 15 Sep 2013: 1.05: Make Javascript optional # 18 Sep 2013: 1.06: IMAGES file can specify images in other directories. # Allow specificaton of permissions for gallery files. # Allow specificaton of names of PARAMS and IMAGES files. # Allow specificaton of name for index file. # 27 Sep 2013: 1.07: Fix bug in finding index.txt file. # 29 Sep 2013: 1.08: Fix a typo in the previous fix. # 16 Oct 2013: 1.09: Fix duplicate thumbnail after editing an image. # 20 Oct 2013: 1.10: Fix the previous fix which broke adding new images. # xx Nov 2013: 1.11: Change Uplink on main page to .. if ../index.html exists. # 12 Jan 2014: 1.12: Allow uplink to be a parameter. # Exit if images file list specified but no images found. # Add "dontenlarge" parameter for small originals. # 07 Feb 2014: 1.13: Add index2 parameter (text to put below thumbnails). # Don't assume return code of \fpictureinfo() is index # into array element holding length of longer side because # new third element is "date taken". # 23 Jul 2014: 1.14 Fix a bug when image is square (return code of \fpicture); # Allow specification of subsections and subtitles. # 13 Aug 2014: 1.15 Allow specification of labels for subsections. # 24 Apr 2015: 2.00 Make it "mobile friendly" (viewport, fluid design, etc). # Allow specification of stylesheet and favicon. # 18 May 2015: 2.01 Handle thumbnails that are too wide for screen. # 19 May 2015: 2.02 Click on image always goes to next image; # there's a new Enlarge button to enlarge the image. # Change default for dontenlarge from 0 to 1. # 27 May 2015: 2.03 Eliminate space after top subtitle. # 20 Jun 2015: 2.04 Make Enlarge button optional # 25 Jun 2015: 2.05 Fix glitch in identifying non-default index.txt file # 18 Jul 2015: 2.06 Fix typo in stylesheet code (writing to wrong channel) # 16 Aug 2015: 2.07 Resize portrait images smaller than landscape to # increase the chances that the caption will be visible. # 18 Aug 2015: 2.08 Found a better way to scale portrait images. # 19 Aug 2015: 2.09 Added a way to put some text after a subtitle. # 25 Feb 2016: 2.10 Allow for misbehaving 'convert' version that always # returns a failure code even when it works right. # Also don't assume that \v(tmpdir) directory exists. # Don't execute CHANGE command unless it's available. # Take scale=n out of help text because we always scale now. # 30 Apr 2016: 2.11 Fix a typo in APPENDFILE (extraneous closing brace) # 25 May 2017: 2.12 Fluid design improvements for main gallery page: # Don't put width attributes with thumbnails because # it inhibits the use of @media scaling in CSS done in # external 'head' file. When no head file is specified, # add @media statements to generated } def PINTERESTJS { # Include Javascript pinit() function local src if dopinterest { .src := \m(pinterest_js) fwrite /line \%1 } } # Command-line processing - title and options .lp := \fchar(40) # Left paren .rp := \fchar(41) # Right paren .lb := \fchar(123) # Left bracket .rb := \fchar(125) # Right bracket .ncmdline = 0 for \%i 1 \v(argc)-1 1 { # Parse each keyword option void \fkeywordvalue(\&_[\%i]) # This function does it if eq "\v(lastkwval)" "help" usage # If keyword was "help" give help if eq "\v(lastkwval)" "-help" usage # If keyword was "-help" give help if eq "\v(lastkwval)" "-h" usage # If keyword was "-h" give help if \findex(|\v(lastkwval)|,|-version|version|-v|) { echo \m(myname) \m(version) \m(date) incr ncmdline exit 0 } if eq "\v(lastkwval)" "resize" { # If "resize" given without argument if not def resize .resize := \m(defsize) # supply default incr ncmdline } if \m(resize) if < \m(resize) 80 { echo RESIZE TOO SMALL: \m(resize) echo Minumum resize size: 80 echo Or 0 to not resize exit 1 } else incr ncmdline if eq "\v(lastkwval)" "noscale" { # If "noscale" given without argument if not def noscale .scale = 1 # supply default. if noscale { .scale = 0 } else { .scale = 1 } } if eq "\v(lastkwval)" "arrows" { # If "arrows" given without argument if not def arrows .arrows = 1 # supply default. if arrows { .noarrows = 0 } else { .noarrows = 1 } incr ncmdline } if eq "\v(lastkwval)" "noarrows" { if not def noarrows .noarrows = 1 # supply default. if noarrows { .arrows = 0 } else { .arrows = 1 } incr ncmdline } if eq "\v(lastkwval)" "pinterest" { if not def pinterest exit 1 - {Usage: pinterest=http://www.thiswebsite.com/ (full URL for this website)} if not def myurl .myurl := \m(pinterest) if match \m(myurl) http*://* { if not equ "\fright(\m(myurl),1)" "/" .myurl := \m(myurl)/ .dopinterest = 1 .javascript = 1 incr ncmdline } else { fatal "Pinterest requires full URL of this website" } } } if \m(ncmdline) addmsg {Parameters set from command line: \m(ncmdline)} echo Photogallery \m(version) \m(date) if def height .thumbhgt := \m(height) if not def dontenlarge .dontenlarge = 1 if not numeric \m(dontenlarge) { exit 1 Fatal - Dontenlarge not numeric: \m(dontenlarge) } if not def enlargebutton .enlargebutton = 1 if not numeric \m(enlargebutton) { exit 1 Fatal - Enlargebutton not numeric: \m(enlargebutton) } if not def noscale .noscale = 1 if not numeric \m(resize) exit 1 Fatal - Resize not numeric: \m(resize) if not numeric \m(thumbhgt) exit 1 Fatal - Thumbhgt not numeric: \m(thumbhgt) if not numeric \m(noscale) exit 1 Fatal - Noscale not numeric: \m(noscale) if match english \m(language)* .language = English else if match spanish \m(language)* .language = Spanish else exit 1 Fatal - Language "\m(language)" not supported if not def title { .title = "Image Gallery" if equ "\m(language)" "Spanish" .title = "Galería de imágenes" } if not def shorttitle .shorttitle := \m(title) if not def hover { .hover := \m(color) switch \m(color) { :darkmagenta, .hover = fuchsia, break :deeppink, .hover = pink, break :gold, .hover = yellow, break :black, .linkcolor = purple, .hover = fuchsia, break :blue, .hover = lightblue, break :red, .hover = pink } } if not def uplink { # Uplink from gallery main page if exist ../index.html .uplink = ../index.html else .uplink = / } echo echo title = \m(title) echo shorttitle = \m(shorttitle) show macro - convertpath - uplink - arrows - bannerfile - imagesfile - copyright - dontenlarge - dopinterest - enlargebutton - favicon - hover - indexfile - index2 - javascript - language - maxwidth - permissions - resize - sort - strip - stylesheet - thumbhgt pwd # Check for IMAGES file, which contains a list of the images to be # included in the gallery. If it doesn't exist, all images in the # current directory will be included. # if not \m(noimagesfile) { # Unless suppressed for testing if def imagesfile { # If imagesfile parameter defined if exist \m(imagesfile) { .have_imagefile = 1 } else { if equ "\m(imagesfile)" "IMAGES" { if not exist IMAGES { if exist images { # Maybe lowercase? rename /list images IMAGES # Convert it. if fail .imagesfile = images } } else if exist images { if newer images IMAGES { rename /list images IMAGES # Convert it. if fail .imagesfile = images } } if exist \m(imagesfile) .have_imagefile = 1 } else if not exist \m(imagesfile) { exit 1 "IMAGES file \m(imagesfile) not found" } } } else if exist IMAGES .have_imagefile = 1 } # If there was no IMAGES file get filenames from reading disk directory # if not def have_images exit 1 "INTERNAL ERROR: have_images not defined" if have_imagefile { do DOIMAGESFILE } else { # Make a list of original images. # Note: Even if we are not making thumbnails with IM we still have to # skip *-t.* and *-r.* files in case we used IM on a previous run. # .ndiskimages = 0 dir /nolinks /array:&q *.\m(extp) # Array Q has ALL image files dcl \&t[\fdim(&q)] # Array T has only originals .q = 0 # with only the original files for i 1 \fdim(&q) 1 { .thisname := \fcontents(\&q[i]) # Suppress any recursion on filename parsename {\m(thisname)} # Parse the name into its pieces if def backup continue # Skip backup files if equ "\m(suffix)" "-t" continue # Skip thumbnails if equ "\m(suffix)" "-r" { # Resized file if exist \m(namepart).\m(ext) continue } incr q # Add original image to list .\&t[q] := \m(thisname) } if not \m(q) exit 1 NO IMAGES FOUND: \v(dir) array resize &t q # Remove empty elements from end .ndiskimages := \fdim(&t) # How many images we're doing .showdir := \v(directory) # Direct name might be loooong if > \flen(\m(showdir)) \v(cols)-40 { # so truncate it to fit on one line .\%9 := \fright(\m(showdir),\v(cols)-35) .\%8 := \findex(/,\%9) .showdir := ...\fsubstr(\%9,\%8) } addmsg {Included \m(ndiskimages) images from \m(showdir)} } if sort { # If sorting by Date Taken... dcl \&x[\fdim(&t)] xecho Sorting by date taken... if == sort 1 echo [chronological] if > sort 1 echo [reverse chronological] # Note: can also use ImageMagick 'identify' for this: # identify -verbose image.jpg | grep "exif:DateTime:" # But it's sloooooow... for i 1 \fdim(&x) 1 { # Make parallel array of photo dates void \fpictureinfo(\&t[i],&d) if not def \&d[3] { echo "Date Taken not available for \&t[i] - Sorting not possible" addmsg {Images not sorted because \&t[i] lacks Date Taken} .sort = 0 undeclare &x break } .\&x[i] := \&d[3] } if \fdim(&x) { # Sort names array by date taken if == sort 1 array sort &x &t # Ascending else array sort /reverse &x &t # Descending undecl &x # Dispose of date-taken array } undeclare &d if sort addmsg {Images sorted by Date Taken} } .need_thumbnails = 1 # Assume we want to make thumbnails .have_convert = 0 # Do we have Image Magick convert? if noimagemagick { # IM not wanted .need_thumbnails = 0 # so we don't make thumbnails.. .have_convert = 0 # we don't have 'convert'.. .resize = 0 # and we don't resize originals addmsg {ImageMagick Convert was not used} } else { if def convertpath { # User supplied path for convert if exist \m(convertpath) { .have_convert = 1 addmsg {ImageMagick Convert path given as \m(convertpath)} } else { addmsg {\m(convertpath) not found - will proceed without it} } } else { .convertpath := \fcommand(which convert) # Try to find it if \v(pexitstat) undefine convertpath # Not found if ( not def convertpath || not exist \m(convertpath) ) { .convertpath = convert } if exist \m(convertpath) { .ignoreconverterrors = 0 # Some versions of 'convert' return a spurious failure code !\m(convertpath) -version > /dev/null 2> /dev/null if success { .have_convert = 1 } else { .cversion := \fcommand(\m(convertpath) -version) if \findex(ImageMagick,\m(cversion)) { .ignoreconverterrors = 1 .have_convert = 1 } } } else { .have_convert = 0 } if have_convert { addmsg {ImageMagick Convert was found at \m(convertpath)} } else { .resize = 0 # Don't do any requested resizing .need_thumbnails = 0 # Don't try to make thumbnails addmsg {ImageMagick Convert not found} } } } # IF WE ARE RESIZING and *-r.xxx does not exist, we create one. If a # *-r.xxx file already exists then either it's an orphan (the original has # been deleted), or the original still exists. In the latter case, the # original might have been updated, in which case we need to resize again. .nresize = 0 # How many were resized if resize { # If resizing originals... local fn buf &y[] y echo echo RESIZING... addmsg {Resize width: \m(resize) pixels} # The &t[] array contains original image names except in the case # where a resized image exists and the original is gone so, for # example, foo.jpg, bar.jpg, baz-r.jpg (if baz.jpg doesn't exist). for i 1 \fdim(&t) 1 { # Go through non-thumbnail images... .fn := \fcontents(\&t[i]) if not def fn continue checkimagename \m(fn) if fail { addmsg {WARNING: "\m(fn)" has problematic name (skipped)} continue } parsename {\m(fn)} # Parse the filename if exist \m(tr) { # If resized version already exists getdimensions {\m(tr)} # Get dimensions of resized image .width := \m(wid) # Its width .height := \m(hgt) # Its height .alreadyexists = 1 # remember that it does if exist \m(to) { # If original still exists # If original hasn't been edited and resizing to the same size if ( newer \m(tr) \m(fn) && == \m(resize) \m(width) ) { echo "SKIPPING: \m(tr) (already desired size)" continue # Go on to next image. } } } else { # Resized version doesn't exist # Or it wasn't resized because it's already too small... getdimensions {\m(to)} # Get dimensions of original image if ( dontenlarge && < \m(wid) \m(resize) ) { .tr := \m(to) .width := \m(wid) } } # Don't try to resize an animated GIF - it doesn't work .animated = 0 # Nonzero indicates animited GIF if equ "\m(ext)" "gif" { # Gif file? checkanimated \m(to) # Animated? if animated { # If animated don't try to resize echo "SKIPPING \m(to) (animated GIF) " .tr := \m(to) continue } } # Not animated GIF... .doresize = 0 if exist \m(tr) { if dontenlarge { # If "don't enlarge" if < \m(width) \m(resize) { # Original too small echo "SKIPPING: \m(fn) (dontenlarge)" # don't resize it continue } } if newer \m(to) \m(tr) .doresize = 1 else if != \m(resize) \m(width) .doresize = 1 else if not animated .doresize = 1 } else .doresize = 1 if not doresize continue if doresize { xecho \m(fn): \fsize(\m(fn))... # Resize the original # Quotes are in case the filenames contain spaces !\m(convertpath) "\m(fn)" -resize \m(resize)x\m(resize) -auto-orient "\m(tr)" if fail { echo {CONVERT FAILED: \m(fn)=>\m(tr)} .tr := \m(fn) } else incr nresize # Count resized image } echo \fsize(\m(tr)) } echo # Resizing complete. if nresize { .\%9 = images if == \m(nresize) 1 .\%9 = image addmsg {Used ImageMagick 'convert' to resize \m(nresize) subpage \%9} } else { addmsg {No images needed resizing} } } else { if \m(noimagemagick) { addmsg{Subpage images were not resized because noimagemagick = 1} } else { addmsg {Subpage images were not resized because resize = 0} } } .have_thumbnails := \m(need_thumbnails) # (two names for same thing) # MAKE THUMBNAILS if not \m(need_thumbnails) { # Not making thumbnails addmsg {Browser-scaled originals will serve as thumbnails} } else { # Need to and can make thumbnails... addmsg {Thumbnail height: \m(thumbhgt) pixels} echo Doing thumbnails (\fdim(&t))... # \&t[] = array of originals and -r's (e.g. foo.jpg or foo-r.jpg) # t = image filename without extension (e.g. foo or foo-r) # tt = thumbnail filename (e.g. foo-t.jpg) # tr = name of image file to be converted to thumbnail .nthumbs = 0 # Count how many we make for i 1 \fdim(&t) 1 { # Go through non-thumbnail images... .fn := \fcontents(\&t[i]) # Original images's filename .thisname := \fcontents(\&t[i]) # Suppress any recursion on filename parsename {\m(thisname)} # Get the parts of the name (sets 'to') if not have_convert { # No ImageMagick? incr nthumbs continue } # tr is the source image to make the thumbnail from. # If we are resizing the subpage images we use the resized image # because in most cases it is smaller than the original. If we are # not resizing we make the thumbnail from the original. if resize { # Resizing? if not exist \m(tr) .tr := \m(to) # Use original if none } else { # Not resizing .tr := \m(to) # Use original } if not def tr exit 1 - "INTERNAL ERROR: tr not defined for thumbnail \m(tt)" if not exist \m(tr) { # This can happen if we're using an IMAGES file that contains # files with pathnames. .tr := \m(fn) } if not exist \m(tr) { exit 1 "NO SOURCE IMAGE \m(tr) FOR THUMBNAIL \m(tt)" } xecho "\m(tr) => " if equ "\m(ext)" "gif" { # Animated GIFs can't be resized checkanimated \m(to) # If it's animated if animated { # use the original as the thumbnail echo " (animated GIF)" .tt := \m(to) continue } } # Not animated and not GIF... if exist \m(tt) { # Thumbnail already exists? # See if a new thumbnail is needed (e.g. if original changed) getdimensions {\m(tt)} # Get its dimensions .ttwid := \m(wid) .tthgt := \m(hgt) if == \m(thumbhgt) \m(tthgt) { # Height same as requested height? if newer \m(tt) \m(tr) { # Yes and if thumbnail is newer echo (Thumbnail \m(tt) up to date) continue # this one is OK - go check next one } } del /quiet \m(tt) # Need new one - delete current } # Quotes are in case the filenames contain spaces !\m(convertpath) "\m(tr)" -thumbnail x\m(thumbhgt) -auto-orient "\m(tt)" if fail { copy /list \m(tr) \m(tt) # Just use the original } else { incr nthumbs echo \m(tt) # Create new thumbnail } dochmod \m(permissions) {\m(tt)} } if nthumbs { .\%9 = thumbnails if == \m(nthumbs) 1 .\%9 = thumbnail addmsg {Used ImageMagick 'convert' to create or update \m(nthumbs) \%9} } else addmsg {All thumbnails were already up to date} echo # Done with thumbnails } dochmod \m(permissions) {*.\m(extp)} # Set image permissions # Localization (Spanish or English)... switch \m(language) { # Text messages for selected language :spanish .langtag = { lang="es"} # HTML language tag if not def title .title = Fotos # Default title .enlarge = Agrandar # Enlarge button label .enlargelegend = "Haz clic para ampliar la imagen" .pinitlegend = "Pinear esta foto en Pinterest" .photo = Foto # Individual page title .next = Adelante # Forward .nexttitle = Adelante # Forward tool tip .prev = Atrás # Back .prevtitle = Atrás # Back tool tip .index = Ver todas # Index .indextitle = Ver todas # Index tool tip .up = Arriba .uptitle = Arriba .msg1 = Haz clic en cualquier foto para entrar .createdby = Creado por .tooltip1 = Haz clic para seguir adelante break :english .langtag = { lang="en"} # HTML language tag if not def title .title = Photos # Default title .enlarge = Enlarge # Enlarge button label .enlargelegend = "Click to enlarge the image" .pinitlegend = "Pin this photo on Pinterest" .photo = Photo # Individual page title .next = Next # Forward .nexttitle = Next # Forward tool tip .prev = Prev # Back .prevtitle = Prev # Back tool tip .index = See all # Index .indextitle = See all # Index tool tip .up = Up .uptitle = Up .msg1 = Click on any photo to enter .createdby = Created by .tooltip1 = Click to go to next image break :default fatal "No language!" } .td = "" if arrows { undef lp rp .index = .up := \m(index) .next = .prev = .td = style="text-decoration:none" } echo Creating Web pages... # Copy HTML prologue... if not def font { .font = "font-family:calibri,arial narrow,arial,sans-serif; font-size:15px" } if not def head .head := \$(HEAD_HTML) if ( def head && exist \m(head) ) { # If external head file exists... if exist \m(indexfile) delete /quiet \m(indexfile) if fail fatal "Can't replace \m(indexfile)" appendfile \m(head) "_PAGETITLE_" "\m(title)" \m(indexfile) # append it fopen /append \%o \m(indexfile) if fail fatal "FOPEN \m(indexfile) failed[1]" } else { # Otherwise supply standard head fopen /write \%o \m(indexfile) if fail fatal "FOPEN \m(indexfile) failed[2]" .what = INDEX fwrite /line \%o {} fwrite /line \%o {} fwrite /line \%o {} if def charset fwrite /line \%o {} else fwrite /line \%o {} if def stylesheet fwrite /line \%o - {} if def favicon fwrite /line \%o - {} fwrite /line \%o - {} fwrite /line \%o {\m(title)} do STYLE \%o fwrite /line \%o {} .bodystyle := margin:0; background:\m(background); color:\m(color); fwrite /line \%o } # Banner file to be included e.g. site title and menu if ( def bannerfile && exist \m(bannerfile) ) { fopen /read \%b \m(bannerfile) if fail exit 1 \m(bannerfile) while 1 { fread /line \%b line if fail break fwrite /line \%o \m(line) } fclose \%b } if def strip { if not exist \m(strip) exit 1 {Strip '\m(strip)' not found} if not match \m(strip) *.\m(extp) { exit 1 {Unsupported image filetype for strip '\m(strip)'} } getdimensions {\m(strip)} # Get dimensions of strip .stwid := \m(wid) .sthgt := \m(hgt) if sthgt { fwrite /line \%o {
 
} } } fwrite /line \%o {
} if def supertitle { fwrite /line \%o {\m(supertitle)} fwrite /line \%o - {

\m(title)

} } else { fwrite /line \%o {

\m(title)

} } } .sep = if exist \m(indextxt) { # If index.txt exists fwrite /line \%o {
} fclose \%o copy /append \m(indextxt) \m(indexfile) # append it to index file. fopen /append \%o \m(indexfile) # (re)open index file. if fail fatal "FOPEN \m(indextxt) failed[3]" .sep = { style="border-top:1px solid grey"} fwrite /line \%o {
} } # The first line is to allow us to identify our own index.html files. # fwrite /line \%o {} fwrite /line \%o {} # And write the contents fwrite /line \%o {\m(up) } fwrite /line \%o {   } fwrite /line \%o {(\m(msg1))} fwrite /line \%o {
} fwrite /line \%o {
} .\%n := \fdim(&t) # How many non-thumbnail JPGs # MAKE SUBPAGES # # We can have original images, resized images, and thumbnail images. # It is possible, however, to build a gallery from originals and then # delete them. The following code allows the gallery to be rebuilt # even after the originals have been deleted by treating the resized # images as originals. def DOSUBTITLE { if nsttl { # If we have any subtitles .tmpsttl := \m(SUBTTL<\%i>) # Check for associated subtitle .tmplbl := \m(LABEL<\%i>) # and label .tmptxt := \m(SUBTXT<\%i>) # and text file if def tmpsttl { # If we have one for this image local tmpline tmpstyle .sttl := \m(tmpsttl) # Put a subheading in the index page if def tmplbl .tmplbl := { id="\m(tmplbl)" } .tmpstyle = {style="margin:8px 0 0px 0; border-top:1px solid grey"} if == \%i 1 .tmpstyle = { style="margin:0"} .tmpline :=

\m(sttl)

fwrite /line \%o "\m(tmpline)" echo "---------------------------------" echo SUBTITLE \m(tmpsttl) echo "---------------------------------" } if def tmptxt { # Have some text to put here? if not exist \m(tmptxt) { # Specified file exists? echo SUBTITLE text file not found: \m(tmptxt) } else { local tmpline fopen /read \%9 \m(tmptxt) # Open the specified file if success { # If OK fwrite /line \%o {
} #
while 1 { # Copy text to the index file fread /line \%9 tmpline if fail break fwrite /line \%o \m(tmpline) } fclose \%9 # Close subtext file fwrite /line \%o {
} # Close div } } } } } # Put Back, Next, and Up links on a subpage, plus an Enlarge button. # define PUTLINKS { local \%i \%n \%c .\%i := \%1 .\%n := \%2 .\%c := \%3 undef nextpage if == \%i \%n { # Last subpage... .x := \m(indexfile) # Has only Up and Prev links .x := \freplace(\m(x),\32,%20) # No spaces allowed .whatsnext := \m(x) fwrite /line \%c \m(lp) \m(up) \m(rp) } else { # Not last image .x := \fstripx(\fbasename(\&t[\%i+1])).html .x := \freplace(\m(x),\32,%20) # No spaces allowed .nextpage := \m(x) fwrite /line \%c - {\m(lp) \m(next) \m(rp)} } .xnext := \m(x) # Remember this for later undef prevpage if != \%i 1 { # Not first image? .prevpage = 1 .x := \fstripx(\fbasename(\&t[\%i-1])).html # Not 1 so link to previous .x := \freplace(\m(x),\32,%20) # No spaces allowed .prevpage := \m(x) fwrite /line \%c {  \m(lp) \m(prev) \m(rp)  } } if != \%i \%n { # If not last subpage fwrite /line \%c \m(lp) \m(index) \m(rp) } .original := \m(namepart).\m(ext) if ( exist \m(original) && \m(enlargebutton) ) { # Enlarge button fwrite /line \%c fwrite \%c {} fwrite /line \%c \m(enlarge) } if dopinterest { fwrite /line \%c fwrite /line \%c {} } fwrite /line \%c # End of "navigation bar" fwrite /line \%c
} # DO THE SUBPAGE IMAGES if not have_convert addmsg - {Browser-scaled originals will serve as subpage images} for \%i 1 \%n 1 { # Loop through all non-thumbnails dosubtitle \%i # Handle any subtitles .animated = 0 # Unset this in case set (per file) .fn := \fcontents(\&t[\%i]) # Suppress any recursion on filename parsename {\m(fn)} # Get the pieces of the name if resize .subpageimage := \m(tr) if ( not exist \m(subpageimage) || not resize ) { .subpageimage := \m(to) } if not exist \m(subpageimage) { .subpageimage := \m(fn) } if not exist \m(subpageimage) { exit 1 SUBPAGE IMAGE \m(subpageimage) not found. } .filemsg := "\m(fn) => " # Beginning of subpage message getdimensions {\m(subpageimage)} # Get subpage image width and height .width := \m(wid) # Copy 'em .height := \m(hgt) if == 0 height .height := 1 # Prevent divide by zero below .captionfile := \m(subpagetext) # Caption file if not exist \m(captionfile) .captionfile := default.txt if exist \m(captionfile) { # If it exists checkcset \m(captionfile) # detect its character set .subcharset := \v(return) # and declare it for this subpage if not def subcharset .subcharset := \m(charset) if equ "\m(subcharset)" "us-ascii" .subcharset = utf-8 } # Until version 2.21, portrait images would often have their bottoms truncated. # You'd have to scroll down to see the rest of the image and to see if there # was a caption. In 2.22-2.24 I tried various math tricks based on the image's # aspect ratio, but they were not satisfying. In version 2.25 I use the vmin # viewport-scaling unit to do the job, but that works only for the image # itself, so I still need to apply the aspect ratio to the caption text. # I'm not worrying about old browsers because these days most browsers # update themselves automatically. -fdc 2018/02/10 .dimensions := \m(width)×\m(height) .realwidth := \m(width).0 # Width as floating-point number .realheight := \m(height).0 # Height as floating-point number # Make width fit in minwidth..maxwidth range if maxwidth if > \m(width) \m(maxwidth) .width := \m(maxwidth) if minwidth if < \m(width) \m(minwidth) .width := \m(minwidth) # Get aspect ratio... See how we do floating-point arithmetic in Kermit: .hscale = 0 (setq ratio (/ realwidth realheight)) # Ratio of width to height if < \m(ratio) 1.2 { # 0.72 = Leave space for the top matter and (some of) the caption. # (setq width (truncate (* width ratio 0.72))) .hscale = 1 # Narrow image needs horizontal scaling } .titlefile := \m(namepart).ttl # Title file for this image if any undef titleline # Default title line for this subpage if def sttl .titleline := \m(sttl) # Use this if given if exist \m(titlefile) { # Title file for this image local \%d # takes precedence. fopen /read \%d \m(titlefile) if success { fread /line \%d titleline fclose \%d } } if def titleline { .thistitle := \m(shorttitle) - \m(photo) \#\%i - \m(titleline) } else { .thistitle := \m(shorttitle) - \m(photo) \#\%i } .filemsg := \m(filemsg)\m(url) (\m(orientation)) # Finish progress message echo \fleft(\m(filemsg),\v(cols)-1) # Echo so it fits on screen fopen /write \%c \m(subpagename) # Create page for this image if fail exit 1 OPEN failed: \m(subpagename) .what = SUBPAGE # (for STYLE macro) fwrite /line \%c # Write HTML prologue fwrite /line \%c fwrite /line \%c fwrite /line \%c - if def subcharset fwrite /line \%c {} else fwrite /line \%c {} if def stylesheet fwrite /line \%c - if def favicon fwrite /line \%c - fwrite /line \%c \m(thistitle) do STYLE \%c # Write out style section do pinterestjs \%c # Include Pinterest Javascript fwrite /line \%c # Close the section .bodystyle := margin:12px; background:\m(background); color:\m(color); fwrite /line \%c } fwrite /line \%c

\m(thistitle)

fwrite /line \%c {
} putlinks \%i \%n \%c # Put next/prev/up links on subpage .whatsnext := \m(xnext) # What the image itself links to .nexttooltip := \m(tooltip1) # NOTE: Chrome 66 ignores the max-width clause and wrecks the aspect ratio. fwrite /line \%c {
} fwrite /line \%c {\fbasename(\m(namepart))} # This sets the width for any and all text written below the image. fwrite /line \%c {
} # Captions are in separate .txt files. Doing it this way allows the content # of the gallery to change during construction without having to edit the # .html files, which would be destroyed in the next run (e.g. when inserting # or deleting photos, because all the previous/next links have to be # recalculated). # # If a caption file does not exist for particular image, a default # caption will be used if a default.txt file exists. if exist \m(captionfile) { # Insert caption if any fopen /read \%d \m(captionfile) if success { # Have caption file fwrite /line \%c # (cosmetic) while true { # Copy the text line by line fread /line \%d textline if fail { fclose \%d, break } fwrite /line \%c \m(textline) } fwrite /line \%c # (cosmetic) } } .have_copyright = 0 if not def copyright .copyright := \$(COPYRIGHT_HTML) if ( def copyright && exist \m(copyright) ) { .have_copyright = 1 } .footer = 0 if ( have_copyright || validate ) .footer = 1 if footer { fwrite /line \%c {} fwrite /line \%c {} fwrite /line \%c {
} if have_copyright { fclose \%c # Close page so we can append to it appendfile \m(copyright) "_YEAR_" "\fword(\v(date),3)" \m(ht) fopen /append \%c \m(ht) # Reopen the page } fwrite /line \%c {} if validate { fwrite /line \%c {} if footer { fwrite /line \%c
} } } fwrite /line \%c
fwrite /line \%c
fwrite /line \%c # End of image-caption section if dopinterest { fwrite /line \%c {} } # Insert Javascript to allow navigation by arrow keys if ( doarrowkeys && equ "\m(what)" "SUBPAGE" ) { if not def prevpage .prevpage := \m(indexfile) if not def nextpage .nextpage := \m(indexfile) fwrite /line \%c " } fwrite /line \%c # End of subpage body fwrite /line \%c # End of html fclose \%c # Close it the subpage increment subpages # Count it dochmod \m(permissions) {\m(subpagename)} # Give it the desired permissions # ADD THUMBNAIL TO INDEX PAGE... if not have_convert .tt := \m(namepart).\m(ext) # Use original image checkanimated \m(subpageimage) # Animated GIF? if animated .tt := \m(subpageimage) # Use original if exist \m(tt) { # Have thumbnail image? # Make entry in index page. fwrite /line \%o - {\m(namepart)} } else { # No thumbnail - put text link fwrite /line \%o [ \m(ht) ] } } # Finish and close Index page fwrite /line \%o {} if def index2 { if exist \m(index2) { fwrite /line \%o
fclose \%o copy /append \m(index2) \m(indexfile) fopen /append \%o \m(indexfile) fwrite /line \%o
} else { addmsg {WARNING: index2 \m(index2) not found - skipping...} } } if have_locale { # Get today's date local day .day := \fword(\v(date),1) if equ "\m(language)" "Spanish" { set locale es_ES.UTF-8 .fulldate := el \m(day) de \fmonthname(\v(nmonth),0) del \v(year) } else { set locale en_US.UTF-8 if fail set locale .fulldate := \fmonthname(\v(nmonth),0) \m(day)\, \v(year) } } else { .fulldate := \v(date) } if not def tail .tail := \$(TAIL_HTML) if ( def tail && exist \m(tail) ) { # If external tail file exists... fclose \%o # Close index file appendfile \m(tail) "_PAGEDATE_" "\m(fulldate)" \m(indexfile) # append tail } else { .pgurl = http://www.kermitproject.org/photogallery.html fwrite /line \%o {

} fwrite /line \%o {

} # End of page fwrite /line \%o {} fwrite /line \%o {} fwrite /line \%o {
} fwrite /line \%o {\m(createdby) - C-Kermit Photogallery \m(version)} fwrite /line \%o { \m(fulldate)} fwrite /line \%o {} if validate { fwrite /line \%o {} fwrite /line \%o {} } fwrite /line \%o {
} fwrite /line \%o {
} fwrite /line \%o {} if doarrowkeys { fwrite /line \%o " } fwrite /line \%o {} fwrite /line \%o {} fclose \%o } dochmod \m(permissions) {\m(indexfile)} addmsg {Images in gallery: \m(subpages)} ! echo \m(subpages) > imgcount if nsttl addmsg {Sections: \m(nsttl)} echo "---------------------------------" echo "SUMMARY \fcvtdate(,2)..." .testversion := \v(test) if equ "\m(testversion)" "0" undef testversion echo "Interpreter: \v(program) version \v(version) \m(testversion)" if def convertpath { echo Convert path: \m(convertpath) } else if not \m(have_convert) { echo "Convert not found - no resizing was done" } else { echo "Convert from default path used for resizing" } echo "Supported graphics file extensions:" echo "\m(extensions)" xecho "This directory:" if > \flen(\v(dir)) 63 echo "" echo " \v(dir)" echo "Title: \m(title)" echo "Index file name: \m(indexfile)" for i 1 mx 1 { # Show accumulated messages at end echo \&m[i] # (summary of Photogallery session) } echo "---------------------------------" if defined atend do atend # Execute ATEND macro if defined else if exist imgcount del /quiet imgcount echo "\m(myname): \m(thisdir)/\m(indexfile) OK" exit ; Local Variables: ; comment-column:40 ; comment-start:"# " ; End: