Software, your way.
burger menu icon
WillMaster

WillMaster > LibraryWebsite Owner Tools

FREE! Coding tips, tricks, and treasures.

Possibilities weekly ezine

Get the weekly email website developers read:

 

Your email address

name@example.com
YES! Send Possibilities every week!

Automatic Image and Thumbnail Display

When you need to provide large or many images to someone, what do you do?

One way is to send several emails, each with some of the images attached, until all are sent. Another is to upload the images at the website of a third-party service and send instructions on how to access them.

Or, you could upload the images at your own website and send a viewing URL to the person.

Tap here for a live demo. The demo uses the very same web page and software that comes with this article.

To implement, do this:

  1. Create a subdirectory on your server and make a note of the subdirectory's URL.

  2. Upload the images into the subdirectory.

    NOTE: The largest file size for an image that the software will process is 10 megabytes.

  3. Upload the index.php web page and the publishimages.php PHP script into the subdirectory.

    Here is the source code of an index.php web page you may use. The style and content may be changed, but the PHP include() directive needs to remain on the page where the image thumbnails shall be inserted. You'll see the include() directive three text lines from the bottom of the following source code.

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Images</title>
    <style type="text/css">
    * { box-sizing:border-box; }
    html, body { font-size:100%; font-family:sans-serif; }
    code { font-size:125%; padding-left:2px; padding-right:1px; }
    </style>
    </head>
    <body><div style="max-width:6in; margin:.5in auto;">
    <div><a href="https://www.willmaster.com/"><img src="https://www.willmaster.com/images/wmlogo_icon.gif"></a></div>
    <h1>
    Images &nbsp; &nbsp; 
    <!--<a href="/AIimages/index.html">(home)</a>-->
    </h1>
    <p>
    If images appear sideways, 
    <a href="<?php echo($_SERVER['PHP_SELF'] . (isset($_GET['rotate'])?'':'?rotate=1') ) ?>">tap&nbsp;here</a> 
    to reorient them.
    </p>
    <p>
    Below the thumbnail is the original image file name. 
    Tap a thumbnail to pop up the original image within the dimensions of the browser window. 
    For a larger image or to prepare for saving an image, tap the "new tab" icon on the left of the image file name.
    </p>
    </div>
    
    <?php include('publishimages.php') ?>
    
    </body>
    </html>
    

    Note that the <?php include('publishimages.php') ?> line needs to be somewhere on the index page. It is the spot where the thumbnail images will be inserted. The publishimages.php is the file name of the PHP script. If the PHP script file name is changed, then <?php include('publishimages.php') ?> needs to be changed accordingly.

    Both the index page and the publishimages.php PHP script need to be in the subdirectory with the images.

    Here is the source code for the publishimages.php PHP script. No customization is required.

    <?php
    /*
    Display Thumbnails for Images in Directory
    Version 1.0
    May 18, 2024
    Will Bontrager Software LLC
    https://www.willmaster.com/
    */
    $BackgroundForLightbox = 'rgba(0,0,0,.5)';
    $Resize['max-width'] = 200;
    $Resize['max-height'] = 200;
    $Resize['namechars'] = '_resized';
    $Resize['MaxFileSizeForResizing'] = 10485760;
    $EmbeddedImageSRC = 'data:image/jpeg;base64,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';
    $ImageDisplayTemplate = <<<TEMPLATE
    <div id="D{{INCREMENT}}" style="display:inline-block; position:relative; margin:1em;">
    <div style="position:relative; width:{{W}}px; height:{{H}}px; outline:0px solid gold;"><img 
    onclick="WillMaster_MakeImageBox('{{FILENAME}}')"
    src="{{THUMBNAME}}" 
    style="{{IMGSTYLE}}"></div>
    <div><a target="_blank" href="{{FILENAME}}"><img src="$EmbeddedImageSRC" style="height:1em;"></a> {{FILENAME}}</div>
    </div>
    TEMPLATE;
    
    function ResizeAllNonresizedImages()
    {
       global $Resize;
       $needsResizing = array();
       $alreadyDone = array();
       foreach(glob('*.jpeg') as $f)
       {
          if( filesize($f)>$Resize['MaxFileSizeForResizing'] ) { continue; }
          if( preg_match('/'.$Resize['namechars'].'\.jpeg$/',$f) ) { $alreadyDone[preg_replace('/'.$Resize['namechars'].'\.jpeg$/','.jpeg',$f)] = true; }
          else { $needsResizing[$f] = true; }
       }
       foreach(glob('*.jpg') as $f)
       {
          if( filesize($f)>$Resize['MaxFileSizeForResizing'] ) { continue; }
          if( preg_match('/'.$Resize['namechars'].'\.jpg$/',$f) ) { $alreadyDone[preg_replace('/'.$Resize['namechars'].'\.jpg$/','.jpg',$f)] = true; }
          else { $needsResizing[$f] = true; }
       }
       foreach(glob('*.png') as $f)
       {
          if( filesize($f)>$Resize['MaxFileSizeForResizing'] ) { continue; }
          if( preg_match('/'.$Resize['namechars'].'\.png$/',$f) ) { $alreadyDone[preg_replace('/'.$Resize['namechars'].'\.png$/','.png',$f)] = true; }
          else { $needsResizing[$f] = true; }
       }
       foreach(glob('*.gif') as $f)
       {
          if( filesize($f)>$Resize['MaxFileSizeForResizing'] ) { continue; }
          if( preg_match('/'.$Resize['namechars'].'\.gif$/',$f) ) { $alreadyDone[preg_replace('/'.$Resize['namechars'].'\.gif$/','.gif',$f)] = true; }
          else { $needsResizing[$f] = true; }
       }
       foreach(glob('*.JPEG') as $f)
       {
          if( filesize($f)>$Resize['MaxFileSizeForResizing'] ) { continue; }
          if( preg_match('/'.$Resize['namechars'].'\.JPEG$/',$f) ) { $alreadyDone[preg_replace('/'.$Resize['namechars'].'\.JPEG$/','.JPEG',$f)] = true; }
          else { $needsResizing[$f] = true; }
       }
       foreach(glob('*.JPG') as $f)
       {
          if( filesize($f)>$Resize['MaxFileSizeForResizing'] ) { continue; }
          if( preg_match('/'.$Resize['namechars'].'\.JPG$/',$f) ) { $alreadyDone[preg_replace('/'.$Resize['namechars'].'\.JPG$/','.JPG',$f)] = true; }
          else { $needsResizing[$f] = true; }
       }
       foreach(glob('*.PNG') as $f)
       {
          if( filesize($f)>$Resize['MaxFileSizeForResizing'] ) { continue; }
          if( preg_match('/'.$Resize['namechars'].'\.PNG$/',$f) ) { $alreadyDone[preg_replace('/'.$Resize['namechars'].'\.PNG$/','.PNG',$f)] = true; }
          else { $needsResizing[$f] = true; }
       }
       foreach(glob('*.GIF') as $f)
       {
          if( filesize($f)>$Resize['MaxFileSizeForResizing'] ) { continue; }
          if( preg_match('/'.$Resize['namechars'].'\.GIF$/',$f) ) { $alreadyDone[preg_replace('/'.$Resize['namechars'].'\.GIF$/','.GIF',$f)] = true; }
          else { $needsResizing[$f] = true; }
       }
       foreach( $alreadyDone as $kk => $b ) { if(isset($needsResizing[$kk])) { unset($needsResizing[$kk]); } }
       $Resize['files'] = array_keys($needsResizing);
       ResizeImagesWithinArray($Resize);
    } # function ResizeAllNonresizedImages()
    
    function ResizeImagesWithinArray($data)
    {
       global $Resize;
       $arr = array();
       $arr['width'] = $data['max-width'];
       $arr['height'] = $data['max-height'];
       $count = count($data['files']);
       for( $i=0; $i<$count; $i++ ) //$data['files'] as $f );
       {
          $filename=__DIR__.'/' . $data['files'][$i];
          $ext = imprintGetFileNameExtension($filename);
          $fname = preg_replace('/\.[^\.]+$/','',$filename);
          $arr['filename'] = $filename;
          $arr['ext'] = $ext;
          $arr['fname'] = $fname;
          $arr['source'] = "$fname.$ext";
          $arr['dest'] = "$fname{$Resize['namechars']}.$ext";
          ResizeTheImage($arr);
       }
    } # function ResizeImagesWithinArray()
    
    function ResizeTheImage($arr)
    {
       global $Resize;
       $src = trim($arr['source']);
       $dest = $arr['dest'];
       $destWidth = $arr['width'];
       $destHeight = $arr['height'];
       $th = getimagesize($src);
       $srcWidth = $th[0];
       $srcHeight = $th[1];
       if($srcWidth<=$Resize['max-width'] and $srcHeight<=$Resize['max-height'])
       {
          copy($arr['source'],$arr['dest']);
          return;
       }
       $arr = array();
       $ta = explode('/',$th['mime']);
       if( count($ta)>1 ) { $type = array_pop($ta); }
       else { $type = imprintGetFileNameExtension($src); }
       $type = strtolower($type);
       $th = array();
       $ta = array();
       $adjustment = min( ( $destWidth / $srcWidth ), ( $destHeight / $srcHeight ) );
       $destWidth = number_format( $srcWidth * $adjustment );
       $destHeight = number_format( $srcHeight * $adjustment );
       if( $srcWidth <= $destWidth and $srcHeight <= $destHeight ) { return; }
       // Start new image.
       $newimg = imagecreatetruecolor($destWidth, $destHeight);
       switch($type)
       {
           case 'jpeg': 
           case 'jpg' : $oldimg = imagecreatefromjpeg($src); break;
           case 'png' : $oldimg = imagecreatefrompng($src);  break;
           case 'gif' : $oldimg = imagecreatefromgif($src);  break;
           default    : return "Error: Unsupported image type.";
       }
       // Handle any transparency in GIF or PNG.
       if($type == "gif" or $type == "png")
       {
           imagecolortransparent( $newimg, imagecolorallocatealpha($newimg, 0, 0, 0, 127) );
           imagealphablending( $newimg, false );
           imagesavealpha( $newimg, true );
       }
       // Create image.
       imagecopyresampled($newimg, $oldimg, 0, 0, 0, 0, $destWidth, $destHeight, $srcWidth, $srcHeight);
       $outtype = $type;
       switch($outtype)
       {
           case 'jpeg':
           case 'jpg' : imagejpeg( $newimg, $dest, 100 ); break;
           case 'png' : imagepng( $newimg, $dest, 9 );  break;
           case 'gif' : imagegif( $newimg, $dest );  break;
       }
       return true;
    } # function ResizeTheImage()
    
    function imprintGetFileNameExtension($p)
    {
       $ta = explode('.',$p);
       $ext = array_pop($ta);
       return $ext;
    } # function imprintGetFileNameExtension()
    
    ResizeAllNonresizedImages();
    
    echo <<<PAGEPART
    <script type="text/javascript">
    /*
    Function WillMaster_MakeImageBox obtained from "Simple Image Lightbox" article at
    https://www.willmaster.com/library/optimization/simple-image-lightbox.php
    */
    var WillMaster_ImageBoxNode;
    function WillMaster_MakeImageBox(url)
    {  /* Will Bontrager Software LLC */
       /* Simple Image Lightbox       */
       /* Version 1.0                 */
       /* January 18, 2020            */
    
       /* Customization section. */
       // Variable BackgroundColor needs to be assigned 
       //    the complete color for the background behind 
       //    the image in the lightbox. The value may be 
       //    rgba() or hsla() with valid parameters.
       // Examples: rgba(0,0,0,.5) and hsla(0,0%,0%,.5)
       
       var BackgroundColor = "$BackgroundForLightbox";
    
       /* End of customization section. */
    
       var DivIDvalue = "WillMaster_ImageBoxID";
       if( url == DivIDvalue )
       {
          document.body.removeChild(WillMaster_ImageBoxNode);
          return;
       }
       WillMaster_ImageBoxNode = document.createElement("div");
       WillMaster_ImageBoxNode.id = DivIDvalue;
       WillMaster_ImageBoxNode.style.width = "100vw";
       WillMaster_ImageBoxNode.style.height = "100vh";
       WillMaster_ImageBoxNode.style.backgroundColor = BackgroundColor;
       WillMaster_ImageBoxNode.style.position = "fixed";
       WillMaster_ImageBoxNode.style.left = "0";
       WillMaster_ImageBoxNode.style.top = "0";
       WillMaster_ImageBoxNode.setAttribute("onclick",arguments.callee.name+"('"+DivIDvalue+"')");
       WillMaster_ImageBoxNode.innerHTML='<img src="'+url+'" style=" border:none; outline:none; max-width:100%; max-height:100%; position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);" alt="lightbox image">';
       document.body.appendChild(WillMaster_ImageBoxNode);
    }
    </script>
    PAGEPART;
    $FileList = array();
    foreach(glob('*'.$Resize['namechars'].'.jpeg') as $f) { $FileList[] = $f; }
    foreach(glob('*'.$Resize['namechars'].'.jpg') as $f) { $FileList[] = $f; }
    foreach(glob('*'.$Resize['namechars'].'.png') as $f) { $FileList[] = $f; }
    foreach(glob('*'.$Resize['namechars'].'.gif') as $f) { $FileList[] = $f; }
    foreach(glob('*'.$Resize['namechars'].'.JPEG') as $f) { $FileList[] = $f; }
    foreach(glob('*'.$Resize['namechars'].'.JPG') as $f) { $FileList[] = $f; }
    foreach(glob('*'.$Resize['namechars'].'.PNG') as $f) { $FileList[] = $f; }
    foreach(glob('*'.$Resize['namechars'].'.GIF') as $f) { $FileList[] = $f; }
    sort($FileList);
    $i = strlen("yyyymmdd\t");
    $increment = 1;
    $inclist = array();
    foreach( $FileList as $f )
    {
       $large = str_replace($Resize['namechars'],'',$f);
       $size = getimagesize($f);
       $w = $size[0];
       $h = $size[1];
       $imgstyle = '';
       if( isset($_GET['rotate']) )
       {
          $t = $w;
          $w = $h;
          $h = $t;
          $imgstyle = "transform-origin:top left; transform:rotate(90deg); position:absolute; top:0; left:{$w}px;";
       }
       $chunk = str_replace('{{THUMBNAME}}',$f,$ImageDisplayTemplate);
       $chunk = str_replace('{{FILENAME}}',$large,$chunk);
       $chunk = str_replace('{{IMGSTYLE}}',$imgstyle,$chunk);
       $chunk = str_replace('{{INCREMENT}}',$increment,$chunk);
       $chunk = str_replace('{{W}}',$w,$chunk);
       $chunk = str_replace('{{H}}',$h,$chunk);
       $inclist[] = $increment;
       $increment++;
       echo $chunk;
    }
    ?>
    

    Save the source code of the PHP script as filename publishimages.php. If the script is saved as a different *.php file name, the include() directive in the index.php file needs to be changed accordingly.

  4. Send your person the subdirectory's URL. As an example, if your subdirectory is named /mythumbs and your domain is example.com, then the subdirectory's URL would be https://example.com/mythumbs

The first time the index page is loaded into a browser, the software will create thumbnail images from the images it finds in the directory. (The largest file size for an image that the software will process is 10 megabytes.)

If you have many images, it could take a while for the thumbnails to be created. If the software times out, simply reload the page and the software will continue making thumbnails.

When all the thumbnails are created, the page will load and publish the thumbnail images.

Every time the software runs, it looks for images that need to have thumbnails made. But it won't re-make thumbnails that already exist.

After the software is installed, you can still add and delete images in the subdirectory at any time. When deleting certain images, also delete the thumbnail version.

The software could be used to present images related to, as examples, holidays, special personal events, or product images. The really nice part of this whole thing is that the software automatically creates thumbnails as needed.

(This content first appeared in Possibilities newsletter.)

Will Bontrager

Was this article helpful to you?
(anonymous form)

Support This Website

Some of our support is from people like you who see the value of all that's offered for FREE at this website.

"Yes, let me contribute."

Amount (USD):

Tap to Choose
Contribution
Method

All information in WillMaster Library articles is presented AS-IS.

We only suggest and recommend what we believe is of value. As remuneration for the time and research involved to provide quality links, we generally use affiliate links when we can. Whenever we link to something not our own, you should assume they are affiliate links or that we benefit in some way.

How Can We Help You? balloons
How Can We Help You?
bullet Custom Programming
bullet Ready-Made Software
bullet Technical Support
bullet Possibilities Newsletter
bullet Website "How-To" Info
bullet Useful Information List

© 1998-2001 William and Mari Bontrager
© 2001-2011 Bontrager Connection, LLC
© 2011-2024 Will Bontrager Software LLC