--- image.module	Wed Jan  5 14:28:23 2005
+++ image_square_thumb.module	Wed Jan  5 14:27:08 2005
@@ -118,6 +118,8 @@ function image_settings() {
 
   $output .= form_textfield(t("Default thumbnail resolution"), "image_default_thumb_size", variable_get("image_default_thumb_size", "100"), 10, 255, t("Default size of thumbnails: format will be the same as original image. Use just one dimension, and put a \"x\" to specify height. Examples: \"100\" for width of 100; \"x200\" for height of 200."));
 
+$output .= form_select(t('Default thumbnail square region'), 'image_default_thumb_squaring_region', variable_get('image_default_thumb_squaring_region', 'none'), array('none'=>'none', 'left'=>'left/top', 'middle'=>'middle', 'right'=>'right/bottom'), t('Select a region that will be used by default to generate square thumbnails.  Select none to generate regular thumbnails.'));
+
   // Check which version of the GD library is available
   $libraries = array("imagemagick" => "imagemagick");
   if (function_exists("imagick_readimage")) {
@@ -1110,25 +1112,132 @@ function _image_make_thumbnail($imagenam
   if (($image = image_open($imagename)) != false) {
     list($thx, $thy) = split('x', variable_get('image_default_thumb_size', '100'));
     $size = getimagesize($imagename);
-    if (!is_numeric($thy)) {
-      // Set default thumbnail width to 100 if nothing was specified
-      $thx = is_numeric($thx) ? $thx : 100;
-      // Compute thumbnail height to keep aspect ratio
-      $thy = round($size[1] * $thx / $size[0]);
-    }
-    else if (!is_numeric($thx)){
-      // Compute thumbnail width to keep aspect ratio
-      $thx = round($size[0] * $thy / $size[1]);
+    $sizex = $size[0]; // size[0] = width
+    $sizey = $size[1]; // size[1] = height
+    // Query what type of thumbnail squaring/clipping to perform (if any).
+    $clipregion = variable_get('image_default_thumb_squaring_region', 'none');
+    if ($clipregion == 'none')
+    {
+      // This thumbnail generation algorithm keeps the original
+      // aspect ratio of the image intact and scales the image to the
+      // requested width or height.
+      if (!is_numeric($thy)) {
+        // Set default thumbnail width to 100 if nothing was specified
+        $thx = is_numeric($thx) ? $thx : 100;
+        // Compute thumbnail height to keep aspect ratio
+        $thy = round($sizey * $thx / $sizex);
+      }
+      else if (!is_numeric($thx)){
+        // Compute thumbnail width to keep aspect ratio
+        $thx = round($sizex * $thy / $sizey);
+      }
+      // A thumbnail should never be larger than the actual image.
+      // Some sanity checking is performed here to assure that upward
+      // scaling doesn't occur.
+      if (($thx < $sizex) && ($thy < $sizey))
+      {
+         image_scale($image, $thx, $thy);
+      }
+    } else {
+      // This thumbnail generation algorithm makes a square thumbnail.
+      // More often than not images are rectangular, so we may have to
+      // perform some computational shenanigans to assure that a
+      // square thumbnail can be generated for the requested x or y dimension.
+      if (!is_numeric($thy)) {
+        // user specified a width for the thumbnail
+        if ($sizex >= $sizey) {
+          // This image is "landscape" oriented  meaning that the x
+          // axis is longer than the y.  In this case, if we scale the x axis as
+          // requested, the y axis will be too short to crop into a square of the
+          // requested size.  In this case we scale the image
+          // along the y axis and crop it along the x.
+          // This code still works in the case of a square image, thus
+          // we fall into here if x = y.
+          $thy = is_numeric($thx) ? $thx : 100;
+          // compute the y dimension to be in the aspect ratio of the
+          // original image.  we'll crop it square later.
+          $thx = round($sizex * $thy / $sizey);
+          $th_orientation = 'landscape';
+        } else {
+          // this image is "portrait" oriented.  scale the image along the x
+          // axis and crop it along the y.
+          $thx = is_numeric($thx) ? $thx : 100;
+          // Compute thumbnail height to keep aspect ratio
+          $thy = round($sizey * $thx / $sizex);
+          $th_orientation = 'portrait';
+        } 
+      } else if (!is_numeric($thx)) {
+        // user specified a height for the thumbnail
+        if ($sizex >= $sizey) {
+          // this image is "landscape" oriented (or square).  scale the image
+          // along the y axis and crop it along the x.
+          $thx = round($sizex * $thy / $sizey);
+          $th_orientation = 'landscape';
+        } else {
+          // this image is "portrait" oriented.  scale the image along the x
+          // axis and crop it along the y.
+          $thx = is_numeric($thy) ? $thy : 100;
+          // Compute thumbnail height to keep aspect ratio
+          $thy = round($sizey * $thx / $sizex);
+          $th_orientation = 'portrait';
+        }
+      }    
+      // A thumbnail should never be larger than the actual image.
+      // Some sanity checking is performed here to assure that upward
+      // scaling doesn't occur.
+      if (($thx < $sizex) && ($thy < $sizey)) {
+        image_scale($image, $thx, $thy);
+      } else {
+        $thx = $sizex;
+        $thy = $sizey;
+      }
+      // clip the scaled image into a square thumbnail
+      if ($thx <= $thy) {
+         $minxy = $thx;
+         $maxxy = $thy;
+      } else {
+         $minxy = $thy;
+         $maxxy = $thx;
+      }
+      switch ($clipregion) {
+        case 'left':
+          // "left" is also the case for "top"
+          // in portrait oriented images.
+          $offset = 0;
+          break;
+        case 'middle':
+          // "middle" is middle any way you turn it.
+          $offset = round(($maxxy - $minxy) / 2);
+          break;
+        case 'right':
+          // "right" is also the case for bottom
+          // in portrait oriented images.
+          $offset = ($maxxy - $minxy);
+          break;
+      }
+      if ($th_orientation == 'landscape') {
+        image_crop($image, $offset, 0, $minxy, $minxy);
+      } else {
+        // Okay, this is wacky, but image_crop doesn't work correctly
+        // on portrait images, so we'll rotate the image to be landscape
+        // then rotate it back to be portrait.  Code-wise a more optimal solution
+        // would be to do the rotation earlier and then consider all images to be
+        // landscape, but I'm hoping the issue with cropping portrait images
+        // will get figured out and the rotations can be removed as they can
+        // somewhat degrade the quality of the thumbnail.
+        image_rotate($image, 270);
+        image_crop($image, $offset, 0, $minxy, $minxy);
+        image_rotate($image, 90);
+      }
     }
-    image_scale($image, $thx, $thy);
     image_close($image, $thumbname);
-  }
-  else {
+  } else {
     $error = t("unable to open image %img", array("%img" => $imagename));
   }
   return $error;
 }
 
+
 function _image_add_static($node, $res) {
   $fname = _image_filename($node, $res);
   $image = db_fetch_object(db_query("SELECT image_list FROM {image} WHERE nid = '%s'", $node->nid));
