Index: imageapi_imagemagick.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/imageapi/imageapi_imagemagick.module,v retrieving revision 1.17.2.5 diff -d -u -r1.17.2.5 imageapi_imagemagick.module --- imageapi_imagemagick.module 29 May 2009 17:48:32 -0000 1.17.2.5 +++ imageapi_imagemagick.module 18 May 2010 18:22:22 -0000 @@ -127,9 +127,65 @@ $bgcolor = str_replace('0x', '#', $bgcolor); } $image->ops[] = '-background '. escapeshellarg($bgcolor) .' -rotate '. (float) $degrees; + + // Need to update the dimensions for later operations in the pipeline + // otherwise (eg) rotate then scale is badly wrong. + $dimensions = imageapi_imagemagick_calculate_rotated_dimensions($image->info['width'], $image->info['height'], $degrees); + $image->info['width'] = $dimensions['width']; + $image->info['height'] = $dimensions['height']; return TRUE; } +/** + * Calculate the new dimensions of a rotated image. + * + * Given the dimensions of a box, and an angle, return the dimensions of a new + * containing box. + * + * @return a named array containing values for width and height. + */ +function imageapi_imagemagick_calculate_rotated_dimensions($width, $height, $degrees) { + // There may be several maths short cuts, eg matrices, + // but doing it the long way like this is clear code and geometry. + // Compressing things just made it 'clever' in a bad way. + // + // @see stackoverflow.com/questions/622140/calculate-bounding-box-coordinates-from-a-rotated-rectangle-picture-inside + // + $theta = deg2rad($degrees); + // Set up a box. + $points = array( + array(0, 0), + array($width, 0), + array(0, $height), + array($width, $height), + ); + $bounding_box = array( + 'left' => 0, + 'right' => 0, + 'top' => 0, + 'bottom' => 0, + ); + // Rotate each point in the box + foreach ($points as $p => $point) { + $x = $point[0]; + $y = $point[1]; + $new_x = ($x)*cos($theta)+($y)*sin($theta); + $new_y = ($x)*sin($theta)+($y)*cos($theta); + // Note the bounds + $bounding_box['left'] = min($bounding_box['left'], $new_x); + $bounding_box['right'] = max($bounding_box['right'], $new_x); + $bounding_box['top'] = min($bounding_box['top'], $new_y); + $bounding_box['bottom'] = max($bounding_box['bottom'], $new_y); + } + + // And how big is the new box? + $dimensions = array( + 'width' => (int)abs($bounding_box['right'] - $bounding_box['left']), + 'height' => (int)abs($bounding_box['bottom'] - $bounding_box['top']), + ); + return $dimensions; +} + function imageapi_imagemagick_image_sharpen(&$image, $radius, $sigma, $amount, $threshold) { $unsharp_arg = $radius .'x'. $sigma .'+'. $amount/100 .'+'. $threshold; $image->ops[] = '-unsharp '. $unsharp_arg;