Browse Source

+ basic ImageMagick support for image resizing

emanuele 12 years ago
parent
commit
e674b1382c

+ 1 - 0
Sources/Admin.php

@@ -528,6 +528,7 @@ function AdminHome()
 	require_once($sourcedir . '/Subs-Admin.php');
 	$checkFor = array(
 		'gd',
+		'imagick',
 		'db_server',
 		'mmcache',
 		'eaccelerator',

+ 6 - 6
Sources/ManageAttachments.php

@@ -90,8 +90,8 @@ function ManageAttachmentSettings($return_config = false)
 
 	$context['valid_upload_dir'] = is_dir($modSettings['attachmentUploadDir']) && is_writable($modSettings['attachmentUploadDir']);
 
-	// Perform a test to see if the GD module is installed.
-	$testGD = get_extension_funcs('gd');
+	// Perform a test to see if the GD module or ImageMagick are installed.
+	$testImg = get_extension_funcs('gd') || class_exists('Imagick');
 	$txt['attachmentUploadDir_multiple_configure'] = '<a href="' . $scripturl . '?action=admin;area=manageattachments;sa=attachpaths">[' . $txt['attachmentUploadDir_multiple_configure'] . ']</a>';
 	
 	// See if we can find if the server is set up to support the attacment limits
@@ -123,7 +123,7 @@ function ManageAttachmentSettings($return_config = false)
 			array('text', 'attachmentExtensions', 40),
 		'',
 			// Image checks.
-			array('warning', empty($testGD) ? 'attachment_gd_warning' : ''),
+			array('warning', empty($testImg) ? 'attachment_img_enc_warning' : ''),
 			array('check', 'attachment_image_reencode'),
 		'',
 			array('warning', 'attachment_image_paranoid_warning'),
@@ -178,8 +178,8 @@ function ManageAvatarSettings($return_config = false)
 {
 	global $txt, $context, $modSettings, $sourcedir, $scripturl;
 
-	// Perform a test to see if the GD module is installed.
-	$testGD = get_extension_funcs('gd');
+	// Perform a test to see if the GD module or ImageMagick are installed.
+	$testImg = get_extension_funcs('gd') || class_exists('Imagick');
 
 	$context['valid_avatar_dir'] = is_dir($modSettings['avatar_directory']);
 	$context['valid_custom_avatar_dir'] = empty($modSettings['custom_avatar_enabled']) || (!empty($modSettings['custom_avatar_dir']) && is_dir($modSettings['custom_avatar_dir']) && is_writable($modSettings['custom_avatar_dir']));
@@ -187,7 +187,7 @@ function ManageAvatarSettings($return_config = false)
 	$config_vars = array(
 		// Server stored avatars!
 		array('title', 'avatar_server_stored'),
-			array('warning', empty($testGD) ? 'avatar_gd_warning' : ''),
+			array('warning', empty($testImg) ? 'avatar_img_enc_warning' : ''),
 			array('permissions', 'profile_server_avatar', 0, $txt['avatar_server_stored_groups']),
 			array('text', 'avatar_directory', 40, 'invalid' => !$context['valid_avatar_dir']),
 			array('text', 'avatar_url', 40),

+ 8 - 0
Sources/Subs-Admin.php

@@ -35,6 +35,14 @@ function getServerVersions($checkFor)
 		$versions['gd'] = array('title' => $txt['support_versions_gd'], 'version' => $temp['GD Version']);
 	}
 
+	// Why not have a look at ImageMagick? If it is, we should show version information for it too.
+	if (in_array('imagick', $checkFor) && class_exists('Imagick'))
+	{
+		$temp = New Imagick;
+		$temp2 = $temp->getVersion();
+		$versions['imagick'] = array('title' => $txt['support_versions_imagick'], 'version' => $temp2['versionString']);
+	}
+
 	// Now lets check for the Database.
 	if (in_array('db_server', $checkFor))
 	{

+ 101 - 70
Sources/Subs-Graphics.php

@@ -184,10 +184,6 @@ function createThumbnail($source, $max_width, $max_height)
  */
 function reencodeImage($fileName, $preferred_format = 0)
 {
-	// There is nothing we can do without GD, sorry!
-	if (!checkGD())
-		return false;
-
 	if (!resizeImageFile($fileName, $fileName . '.tmp', null, null, $preferred_format))
 	{
 		if (file_exists($fileName . '.tmp'))
@@ -201,8 +197,6 @@ function reencodeImage($fileName, $preferred_format = 0)
 
 	if (!rename($fileName . '.tmp', $fileName))
 		return false;
-
-	return true;
 }
 
 /**
@@ -270,6 +264,23 @@ function checkGD()
 	return true;
 }
 
+/**
+ * Checks whether the Imagick class is present.
+ *
+ * @return whether or not Imagick is available.
+ */
+function checkIM()
+{
+	static $IM;
+
+	if (isset($IM))
+		return $IM;
+
+	$IM = class_exists('Imagick');
+
+	return $IM;
+}
+
 /**
  * See if we have enough memory to thumbnail an image
  *
@@ -312,8 +323,8 @@ function resizeImageFile($source, $destination, $max_width, $max_height, $prefer
 {
 	global $sourcedir;
 
-	// Nothing to do without GD
-	if (!checkGD())
+	// Nothing to do without GD or IM
+	if (!checkGD() || !checkIM())
 		return false;
 
 	static $default_formats = array(
@@ -326,8 +337,6 @@ function resizeImageFile($source, $destination, $max_width, $max_height, $prefer
 
 	require_once($sourcedir . '/Subs-Package.php');
 
-	$success = false;
-
 	// Get the image file, we have to work with something after all
 	$fp_destination = fopen($destination, 'wb');
 	if ($fp_destination && substr($source, 0, 7) == 'http://')
@@ -359,22 +368,25 @@ function resizeImageFile($source, $destination, $max_width, $max_height, $prefer
 		$sizes = array(-1, -1, -1);
 		
 	// See if we have -or- can get the needed memory for this operation
-	if (!imageMemoryCheck($sizes))
+	if (checkGD() && !imageMemoryCheck($sizes))
 		return false;
 
 	// A known and supported format?
 	// @todo test PSD and gif.
-	if (isset($default_formats[$sizes[2]]) && function_exists('imagecreatefrom' . $default_formats[$sizes[2]]))
+	if (checkIM() && isset($default_formats[$sizes[2]]))
+	{
+		return resizeImage(null, $destination, null, null, $max_width, $max_height, true, $preferred_format);
+	}
+	elseif (checkGD() && isset($default_formats[$sizes[2]]) && function_exists('imagecreatefrom' . $default_formats[$sizes[2]]))
 	{
 		$imagecreatefrom = 'imagecreatefrom' . $default_formats[$sizes[2]];
 		if ($src_img = @$imagecreatefrom($destination))
 		{
-			resizeImage($src_img, $destination, imagesx($src_img), imagesy($src_img), $max_width === null ? imagesx($src_img) : $max_width, $max_height === null ? imagesy($src_img) : $max_height, true, $preferred_format);
-			$success = true;
+			return resizeImage($src_img, $destination, imagesx($src_img), imagesy($src_img), $max_width === null ? imagesx($src_img) : $max_width, $max_height === null ? imagesy($src_img) : $max_height, true, $preferred_format);
 		}
 	}
 
-	return $success;
+	return false;
 }
 
 /**
@@ -398,71 +410,95 @@ function resizeImage($src_img, $destName, $src_width, $src_height, $max_width, $
 {
 	global $gd2, $modSettings;
 
-	// Without GD, no image resizing at all.
-	if (!checkGD())
-		return false;
+	if (checkIM())
+	{
+		static $default_formats = array(
+			'1' => 'gif',
+			'2' => 'jpeg',
+			'3' => 'png',
+			'6' => 'bmp',
+			'15' => 'wbmp'
+		);
+		$preferred_format = empty($preferred_format) || !isset($default_formats[$preferred_format]) ? 2 : $preferred_format;
 
-	$success = false;
+		$imagick = New Imagick($destName);
+		$src_width = empty($src_width) ? $imagick->getImageWidth() : $src_width;
+		$src_height = empty($src_height) ? $imagick->getImageHeight() : $src_height;
+		$dest_width = empty($max_width) ? $src_width : $max_width;
+		$dest_height = empty($max_height) ? $src_height : $max_height;
 
-	// Determine whether to resize to max width or to max height (depending on the limits.)
-	if (!empty($max_width) || !empty($max_height))
+		$imagick->setImageFormat($default_formats[$preferred_format]);
+		$success = $imagick->writeImage($destName);
+
+		return !empty($success);
+	}
+	elseif (checkGD())
 	{
-		if (!empty($max_width) && (empty($max_height) || $src_height * $max_width / $src_width <= $max_height))
-		{
-			$dst_width = $max_width;
-			$dst_height = floor($src_height * $max_width / $src_width);
-		}
-		elseif (!empty($max_height))
-		{
-			$dst_width = floor($src_width * $max_height / $src_height);
-			$dst_height = $max_height;
-		}
+		$success = false;
 
-		// Don't bother resizing if it's already smaller...
-		if (!empty($dst_width) && !empty($dst_height) && ($dst_width < $src_width || $dst_height < $src_height || $force_resize))
+		// Determine whether to resize to max width or to max height (depending on the limits.)
+		if (!empty($max_width) || !empty($max_height))
 		{
-			// (make a true color image, because it just looks better for resizing.)
-			if ($gd2)
+			if (!empty($max_width) && (empty($max_height) || $src_height * $max_width / $src_width <= $max_height))
+			{
+				$dst_width = $max_width;
+				$dst_height = floor($src_height * $max_width / $src_width);
+			}
+			elseif (!empty($max_height))
 			{
-				$dst_img = imagecreatetruecolor($dst_width, $dst_height);
+				$dst_width = floor($src_width * $max_height / $src_height);
+				$dst_height = $max_height;
+			}
 
-				// Deal nicely with a PNG - because we can.
-				if ((!empty($preferred_format)) && ($preferred_format == 3))
+			// Don't bother resizing if it's already smaller...
+			if (!empty($dst_width) && !empty($dst_height) && ($dst_width < $src_width || $dst_height < $src_height || $force_resize))
+			{
+				// (make a true color image, because it just looks better for resizing.)
+				if ($gd2)
 				{
-					imagealphablending($dst_img, false);
-					if (function_exists('imagesavealpha'))
-						imagesavealpha($dst_img, true);
+					$dst_img = imagecreatetruecolor($dst_width, $dst_height);
+
+					// Deal nicely with a PNG - because we can.
+					if ((!empty($preferred_format)) && ($preferred_format == 3))
+					{
+						imagealphablending($dst_img, false);
+						if (function_exists('imagesavealpha'))
+							imagesavealpha($dst_img, true);
+					}
 				}
-			}
-			else
-				$dst_img = imagecreate($dst_width, $dst_height);
+				else
+					$dst_img = imagecreate($dst_width, $dst_height);
 
-			// Resize it!
-			if ($gd2)
-				imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
+				// Resize it!
+				if ($gd2)
+					imagecopyresampled($dst_img, $src_img, 0, 0, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
+				else
+					imagecopyresamplebicubic($dst_img, $src_img, 0, 0, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
+			}
 			else
-				imagecopyresamplebicubic($dst_img, $src_img, 0, 0, 0, 0, $dst_width, $dst_height, $src_width, $src_height);
+				$dst_img = $src_img;
 		}
 		else
 			$dst_img = $src_img;
+
+		// Save the image as ...
+		if (!empty($preferred_format) && ($preferred_format == 3) && function_exists('imagepng'))
+			$success = imagepng($dst_img, $destName);
+		elseif (!empty($preferred_format) && ($preferred_format == 1) && function_exists('imagegif'))
+			$success = imagegif($dst_img, $destName);
+		elseif (function_exists('imagejpeg'))
+			$success = imagejpeg($dst_img, $destName);
+
+		// Free the memory.
+		imagedestroy($src_img);
+		if ($dst_img != $src_img)
+			imagedestroy($dst_img);
+
+		return $success;
 	}
 	else
-		$dst_img = $src_img;
-
-	// Save the image as ...
-	if (!empty($preferred_format) && ($preferred_format == 3) && function_exists('imagepng'))
-		$success = imagepng($dst_img, $destName);
-	elseif (!empty($preferred_format) && ($preferred_format == 1) && function_exists('imagegif'))
-		$success = imagegif($dst_img, $destName);
-	elseif (function_exists('imagejpeg'))
-		$success = imagejpeg($dst_img, $destName);
-
-	// Free the memory.
-	imagedestroy($src_img);
-	if ($dst_img != $src_img)
-		imagedestroy($dst_img);
-
-	return $success;
+		// Without GD, no image resizing at all.
+		return false;
 }
 
 /**
@@ -735,7 +771,7 @@ function gif_outputAsPng($gif, $lpszFileName, $background_color = -1)
  */
 function showCodeImage($code)
 {
-	global $settings, $user_info, $modSettings;
+	global $gd2, $settings, $user_info, $modSettings;
 
 	// Note: The higher the value of visual_verification_type the harder the verification is - from 0 as disabled through to 4 as "Very hard".
 
@@ -773,11 +809,6 @@ function showCodeImage($code)
 	// Give the image a border?
 	$hasBorder = $simpleBGColor;
 
-	// Is this GD2? Needed for pixel size.
-	$testGD = get_extension_funcs('gd');
-	$gd2 = in_array('imagecreatetruecolor', $testGD) && function_exists('imagecreatetruecolor');
-	unset($testGD);
-
 	// The amount of pixels inbetween characters.
 	$character_spacing = 1;
 

+ 4 - 3
Themes/default/languages/Admin.english.php

@@ -299,6 +299,7 @@ $txt['support_versions_php'] = 'PHP version';
 $txt['support_versions_db'] = '%1$s version';
 $txt['support_versions_server'] = 'Server version';
 $txt['support_versions_gd'] = 'GD version';
+$txt['support_versions_imagick'] = 'Imagick version';
 $txt['support_versions'] = 'Version Information';
 $txt['support_resources'] = 'Support Resources';
 $txt['support_resources_p1'] = 'Our <a href="%1$s">Online Manual</a> provides the main documentation for SMF. The SMF Online Manual has many documents to help answer support questions and explain <a href="%2$s">Features</a>, <a href="%3$s">Settings</a>, <a href="%4$s">Themes</a>, <a href="%5$s">Packages</a>, etc. The Online Manual documents each area of SMF thoroughly and should answer most questions quickly.';
@@ -358,11 +359,11 @@ $txt['attachmentDirSizeLimit'] = 'Max attachment folder space';
 $txt['attachmentPostLimit'] = 'Max attachment size per post';
 $txt['attachmentSizeLimit'] = 'Max size per attachment';
 $txt['attachmentNumPerPostLimit'] = 'Max number of attachments per post';
-$txt['attachment_gd_warning'] = 'The GD module is currently not installed. Image re-encoding is not possible.';
+$txt['attachment_img_enc_warning'] = 'Neither the GD module nor ImageMagick are currently installed. Image re-encoding is not possible.';
 $txt['attachment_postsize_warning'] = 'The current php.ini setting \'post_max_size\' may not support this.';
 $txt['attachment_filesize_warning'] = 'The current php.ini setting \'upload_max_filesize\' may not support this.';
 $txt['attachment_image_reencode'] = 'Re-encode potentially dangerous image attachments';
-$txt['attachment_image_reencode_note'] = '(requires GD module)';
+$txt['attachment_image_reencode_note'] = '(requires GD module or ImageMagick)';
 $txt['attachment_image_paranoid_warning'] = 'The extensive security checks can result in a large number of rejected attachments.';
 $txt['attachment_image_paranoid'] = 'Perform extensive security checks on uploaded image attachments';
 $txt['attachmentThumbnails'] = 'Resize images when showing under posts';
@@ -406,7 +407,7 @@ $txt['avatar_max_height_upload'] = 'Maximum height of uploaded avatar';
 $txt['avatar_resize_upload'] = 'Resize oversized large avatars';
 $txt['avatar_resize_upload_note'] = '(requires GD module)';
 $txt['avatar_download_png'] = 'Use PNG for resized avatars';
-$txt['avatar_gd_warning'] = 'The GD module is currently not installed. Some avatar features are disabled.';
+$txt['avatar_img_enc_warning'] = 'Neither the GD module nor ImageMagick are currently installed. Some avatar features are disabled.';
 $txt['avatar_external'] = 'External avatars';
 $txt['avatar_upload'] = 'Uploadable avatars';
 $txt['avatar_server_stored'] = 'Server-stored avatars';