Refactored thumbnail creation 🌄 (#1249)

* Refactored thumbnail creation

* Updated

* Updated

* Updated

* Updated

* Updated

* Update functions_thumbs.php

* Update functions_thumbs.php

* Update displaying.php

* Update mysql.sql

* Update mysql.sql

* Update CHANGELOG.md
This commit is contained in:
Roman Kelesidis 2023-12-23 00:42:59 +07:00 committed by GitHub
commit 65c7903b21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 160 additions and 477 deletions

View file

@ -5,7 +5,7 @@
**Merged pull requests:**
- Release 2.4.0 🔥 ([belomaxorka](https://github.com/belomaxorka))
- Release 2.4.0 🔥 ([belomaxorka](https://github.com/belomaxorka), [kovalensky](https://github.com/kovalensky))
- Updated copyright year [\#1201](https://github.com/torrentpier/torrentpier/pull/1201) ([belomaxorka](https://github.com/belomaxorka))
- Update file_list_v2.php [\#1202](https://github.com/torrentpier/torrentpier/pull/1202) ([kovalensky](https://github.com/kovalensky))
- Updated TorrentPier footer text (: [\#1204](https://github.com/torrentpier/torrentpier/pull/1204) ([kovalensky](https://github.com/kovalensky))
@ -32,6 +32,7 @@
- Little improvements [\#1244](https://github.com/torrentpier/torrentpier/pull/1244) ([kovalensky](https://github.com/kovalensky))
- Improved handling errors while uploading [\#1246](https://github.com/torrentpier/torrentpier/pull/1246)
- Use hardcoded dictionary names for better counting result in file listing [\#1247](https://github.com/torrentpier/torrentpier/pull/1247) ([kovalensky](https://github.com/kovalensky))
- Refactored thumbnail creation 🌄 [\#1249](https://github.com/torrentpier/torrentpier/pull/1249) ([belomaxorka](https://github.com/belomaxorka))
- New Crowdin updates [\#1203](https://github.com/torrentpier/torrentpier/pull/1203), [\#1222](https://github.com/torrentpier/torrentpier/pull/1222) ([Exileum](https://github.com/Exileum))
## [v2.4.0-rc2](https://github.com/torrentpier/torrentpier/tree/v2.4.0-rc2) (2023-12-12)

View file

@ -37,7 +37,6 @@ $pm_size = request_var('pm_size', '');
$submit = isset($_POST['submit']);
$check_upload = isset($_POST['settings']);
$check_image_cat = isset($_POST['cat_settings']);
$search_imagick = isset($_POST['search_imagick']);
// Re-evaluate the Attachment Configuration
$sql = 'SELECT * FROM ' . BB_ATTACH_CONFIG;
@ -130,44 +129,6 @@ $select_size_mode = size_select('size', $size);
$select_quota_size_mode = size_select('quota_size', $quota_size);
$select_pm_size_mode = size_select('pm_size', $pm_size);
// Search Imagick
if ($search_imagick) {
$imagick = '';
if (false !== stripos($imagick, "convert")) {
return true;
}
if ($imagick != 'none') {
if (!false !== stripos(PHP_OS, "WIN")) {
$retval = @exec('whereis convert');
$paths = explode(' ', $retval);
if (is_array($paths)) {
foreach ($paths as $i => $iValue) {
$path = basename($paths[$i]);
if ($path == 'convert') {
$imagick = $iValue;
}
}
}
} elseif (false !== stripos(PHP_OS, "WIN")) {
$path = 'c:/imagemagick/convert.exe';
if (file_exists(amod_realpath($path))) {
$imagick = $path;
}
}
}
if (file_exists(amod_realpath(trim($imagick)))) {
$new_attach['img_imagick'] = trim($imagick);
} else {
$new_attach['img_imagick'] = '';
}
}
// Check Settings
if ($check_upload) {
// Some tests...
@ -287,11 +248,8 @@ if ($mode == 'cats') {
$create_thumbnail_yes = ($new_attach['img_create_thumbnail'] != '0') ? 'checked' : '';
$create_thumbnail_no = ($new_attach['img_create_thumbnail'] == '0') ? 'checked' : '';
$use_gd2_yes = ($new_attach['use_gd2'] != '0') ? 'checked' : '';
$use_gd2_no = ($new_attach['use_gd2'] == '0') ? 'checked' : '';
// Check Thumbnail Support
if (!is_imagick() && !extension_loaded('gd')) {
if (!extension_loaded('gd')) {
$new_attach['img_create_thumbnail'] = '0';
} else {
$template->assign_block_vars('switch_thumbnail_support', []);
@ -304,13 +262,10 @@ if ($mode == 'cats') {
'IMAGE_LINK_HEIGHT' => $new_attach['img_link_height'],
'IMAGE_LINK_WIDTH' => $new_attach['img_link_width'],
'IMAGE_MIN_THUMB_FILESIZE' => $new_attach['img_min_thumb_filesize'],
'IMAGE_IMAGICK_PATH' => $new_attach['img_imagick'],
'DISPLAY_INLINED_YES' => $display_inlined_yes,
'DISPLAY_INLINED_NO' => $display_inlined_no,
'CREATE_THUMBNAIL_YES' => $create_thumbnail_yes,
'CREATE_THUMBNAIL_NO' => $create_thumbnail_no,
'USE_GD2_YES' => $use_gd2_yes,
'USE_GD2_NO' => $use_gd2_no,
'S_ASSIGNED_GROUP_IMAGES' => implode(', ', $s_assigned_group_images),
'S_ATTACH_ACTION' => 'admin_attachments.php?mode=cats',
));

View file

@ -39,6 +39,7 @@
"php": "^8.1",
"arokettu/bencode": "^4.1.0",
"bugsnag/bugsnag": "^v3.29.1",
"claviska/simpleimage": "^4.0",
"egulias/email-validator": "^4.0.1",
"filp/whoops": "^2.15",
"gigablah/sphinxphp": "2.0.8",

116
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1579104ffbdcad0fe85f622bb946ca2d",
"content-hash": "12bfaad3f49dbe7d7f7b5c349076ab87",
"packages": [
{
"name": "arokettu/bencode",
@ -199,6 +199,59 @@
},
"time": "2023-05-10T11:07:22+00:00"
},
{
"name": "claviska/simpleimage",
"version": "4.0.6",
"source": {
"type": "git",
"url": "https://github.com/claviska/SimpleImage.git",
"reference": "969de5e61810ef91f6f83c475b192c4841367dfa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/claviska/SimpleImage/zipball/969de5e61810ef91f6f83c475b192c4841367dfa",
"reference": "969de5e61810ef91f6f83c475b192c4841367dfa",
"shasum": ""
},
"require": {
"ext-gd": "*",
"league/color-extractor": "0.4.*",
"php": ">=8.0"
},
"require-dev": {
"laravel/pint": "^1.5",
"phpstan/phpstan": "^1.10"
},
"type": "library",
"autoload": {
"psr-0": {
"claviska": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Cory LaViska",
"homepage": "http://www.abeautifulsite.net/",
"role": "Developer"
}
],
"description": "A PHP class that makes working with images as simple as possible.",
"support": {
"issues": "https://github.com/claviska/SimpleImage/issues",
"source": "https://github.com/claviska/SimpleImage/tree/4.0.6"
},
"funding": [
{
"url": "https://github.com/claviska",
"type": "github"
}
],
"time": "2023-07-27T16:48:12+00:00"
},
{
"name": "composer/ca-bundle",
"version": "1.3.7",
@ -1048,6 +1101,67 @@
],
"time": "2022-08-10T22:19:41+00:00"
},
{
"name": "league/color-extractor",
"version": "0.4.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/color-extractor.git",
"reference": "21fcac6249c5ef7d00eb83e128743ee6678fe505"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/color-extractor/zipball/21fcac6249c5ef7d00eb83e128743ee6678fe505",
"reference": "21fcac6249c5ef7d00eb83e128743ee6678fe505",
"shasum": ""
},
"require": {
"ext-gd": "*",
"php": "^7.3 || ^8.0"
},
"replace": {
"matthecat/colorextractor": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2",
"phpunit/phpunit": "^9.5"
},
"suggest": {
"ext-curl": "To download images from remote URLs if allow_url_fopen is disabled for security reasons"
},
"type": "library",
"autoload": {
"psr-4": {
"League\\ColorExtractor\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mathieu Lechat",
"email": "math.lechat@gmail.com",
"homepage": "http://matthecat.com",
"role": "Developer"
}
],
"description": "Extract colors from an image as a human would do.",
"homepage": "https://github.com/thephpleague/color-extractor",
"keywords": [
"color",
"extract",
"human",
"image",
"palette"
],
"support": {
"issues": "https://github.com/thephpleague/color-extractor/issues",
"source": "https://github.com/thephpleague/color-extractor/tree/0.4.0"
},
"time": "2022-09-24T15:57:16+00:00"
},
{
"name": "longman/ip-tools",
"version": "1.2.1",

View file

@ -46,18 +46,15 @@ VALUES ('upload_dir', 'data/torrent_files'),
('max_attachments_pm', '1'),
('disable_mod', '0'),
('allow_pm_attach', '1'),
('attach_version', '2.3.14'),
('default_upload_quota', '0'),
('default_pm_quota', '0'),
('img_display_inlined', '1'),
('img_max_width', '200'),
('img_max_height', '200'),
('img_max_width', '2000'),
('img_max_height', '2000'),
('img_link_width', '600'),
('img_link_height', '400'),
('img_create_thumbnail', '1'),
('img_min_thumb_filesize', '12000'),
('img_imagick', '/usr/bin/convert'),
('use_gd2', '1'),
('wma_autoplay', '0'),
('flash_autoplay', '0');

View file

@ -15,7 +15,6 @@ require ATTACH_DIR . '/includes/functions_includes.php';
require ATTACH_DIR . '/includes/functions_attach.php';
require ATTACH_DIR . '/includes/functions_delete.php';
require ATTACH_DIR . '/includes/functions_thumbs.php';
require ATTACH_DIR . '/includes/functions_filetypes.php';
if (defined('ATTACH_INSTALL')) {
return;

View file

@ -183,6 +183,11 @@ function display_attachments($post_id)
$filename = $upload_dir . '/' . basename($attachments['_' . $post_id][$i]['physical_filename']);
$thumbnail_filename = $upload_dir . '/' . THUMB_DIR . '/t_' . basename($attachments['_' . $post_id][$i]['physical_filename']);
// Checks the file existence
if (!is_file($filename)) {
continue;
}
$upload_image = '';
if ($attach_config['upload_img'] && empty($upload_icons[$attachments['_' . $post_id][$i]['extension']])) {
@ -214,7 +219,12 @@ function display_attachments($post_id)
if (@(int)$display_categories[$attachments['_' . $post_id][$i]['extension']] == IMAGE_CAT && (int)$attach_config['img_display_inlined']) {
if ((int)$attach_config['img_link_width'] != 0 || (int)$attach_config['img_link_height'] != 0) {
[$width, $height] = image_getdimension($filename);
// Checks the thumbnail existence
if (!is_file($thumbnail_filename)) {
continue;
}
[$width, $height] = getimagesize($filename);
if ($width == 0 && $height == 0) {
$image = true;

View file

@ -1,248 +0,0 @@
<?php
/**
* TorrentPier Bull-powered BitTorrent tracker engine
*
* @copyright Copyright (c) 2005-2024 TorrentPier (https://torrentpier.com)
* @link https://github.com/torrentpier/torrentpier for the canonical source repository
* @license https://github.com/torrentpier/torrentpier/blob/master/LICENSE MIT License
*/
/**
* All Attachment Functions needed to determine Special Files/Dimensions
*/
/**
* Read Long Int (4 Bytes) from File
*/
function read_longint($fp)
{
$data = fread($fp, 4);
$value = ord($data[0]) + (ord($data[1]) << 8) + (ord($data[2]) << 16) + (ord($data[3]) << 24);
if ($value >= 4294967294) {
$value -= 4294967296;
}
return $value;
}
/**
* Read Word (2 Bytes) from File - Note: It's an Intel Word
*/
function read_word($fp)
{
$data = fread($fp, 2);
return ord($data[1]) * 256 + ord($data[0]);
}
/**
* Read Byte
*/
function read_byte($fp)
{
$data = fread($fp, 1);
return ord($data);
}
/**
* Get Image Dimensions
*/
function image_getdimension($file)
{
$xmax = null;
$xmin = null;
$ymax = null;
$ymin = null;
$size = @getimagesize($file);
if ($size[0] != 0 || $size[1] != 0) {
return $size;
}
// Try to get the Dimension manually, depending on the mimetype
$fp = @fopen($file, 'rb');
if (!$fp) {
return $size;
}
$error = false;
// BMP - IMAGE
$tmp_str = fread($fp, 2);
if ($tmp_str == 'BM') {
$length = read_longint($fp);
if ($length <= 6) {
$error = true;
}
if (!$error) {
$i = read_longint($fp);
if ($i != 0) {
$error = true;
}
}
if (!$error) {
$i = read_longint($fp);
if ($i != 0x3E && $i != 0x76 && $i != 0x436 && $i != 0x36) {
$error = true;
}
}
if (!$error) {
$tmp_str = fread($fp, 4);
$width = read_longint($fp);
$height = read_longint($fp);
if ($width > 3000 || $height > 3000) {
$error = true;
}
}
} else {
$error = true;
}
if (!$error) {
fclose($fp);
return [
$width,
$height,
6
];
}
$error = false;
fclose($fp);
// GIF - IMAGE
$fp = @fopen($file, 'rb');
$tmp_str = fread($fp, 3);
if ($tmp_str == 'GIF') {
$width = read_word($fp);
$height = read_word($fp);
$info_byte = fread($fp, 1);
$info_byte = ord($info_byte);
if (($info_byte & 0x80) != 0x80 && ($info_byte & 0x80) != 0) {
$error = true;
}
if (!$error) {
if (($info_byte & 8) != 0) {
$error = true;
}
}
} else {
$error = true;
}
if (!$error) {
fclose($fp);
return [
$width,
$height,
1
];
}
$error = false;
fclose($fp);
// JPG - IMAGE
$fp = @fopen($file, 'rb');
$w1 = read_word($fp);
if ((int)$w1 < 16) {
$error = true;
}
if (!$error) {
$tmp_str = fread($fp, 4);
if ($tmp_str == 'JFIF') {
$o_byte = fread($fp, 1);
if ((int)$o_byte != 0) {
$error = true;
}
if (!$error) {
$b = read_byte($fp);
if ($b != 0 && $b != 1 && $b != 2) {
$error = true;
}
}
if (!$error) {
$width = read_word($fp);
$height = read_word($fp);
if ($width <= 0 || $height <= 0) {
$error = true;
}
}
}
} else {
$error = true;
}
if (!$error) {
fclose($fp);
return [
$width,
$height,
2
];
}
$error = false;
fclose($fp);
// PCX - IMAGE
$fp = @fopen($file, 'rb');
$tmp_str = fread($fp, 3);
if ((ord($tmp_str[0]) == 10) && (ord($tmp_str[1]) == 0 || ord($tmp_str[1]) == 2 || ord($tmp_str[1]) == 3 || ord($tmp_str[1]) == 4 || ord($tmp_str[1]) == 5) && (ord($tmp_str[2]) == 1)) {
$b = fread($fp, 1);
if (ord($b) != 1 && ord($b) != 2 && ord($b) != 4 && ord($b) != 8 && ord($b) != 24) {
$error = true;
}
if (!$error) {
$xmin = read_word($fp);
$ymin = read_word($fp);
$xmax = read_word($fp);
$ymax = read_word($fp);
$b = fread($fp, 1);
if ($b != 0) {
$error = true;
}
}
if (!$error) {
$width = $xmax - $xmin + 1;
$height = $ymax - $ymin + 1;
}
} else {
$error = true;
}
if (!$error) {
fclose($fp);
return [
$width,
$height,
7
];
}
fclose($fp);
return $size;
}

View file

@ -11,177 +11,46 @@ if (!defined('BB_ROOT')) {
die(basename(__FILE__));
}
$imagick = '';
/**
* Calculate the needed size for Thumbnail
*/
function get_img_size_format($width, $height)
{
// Maximum Width the Image can take
$max_width = 400;
if ($width > $height) {
return [
round($width * ($max_width / $width)),
round($height * ($max_width / $width))
];
}
return [
round($width * ($max_width / $height)),
round($height * ($max_width / $height))
];
}
/**
* Check if imagick is present
*/
function is_imagick()
{
global $imagick, $attach_config;
if ($attach_config['img_imagick'] != '') {
$imagick = $attach_config['img_imagick'];
return true;
}
return false;
}
/**
* Get supported image types
*/
function get_supported_image_types($type)
{
// Check GD extension installed
if (!extension_loaded('gd')) {
return ['gd' => false];
}
$format = imagetypes();
$new_type = 0;
switch ($type) {
case IMAGETYPE_GIF:
$new_type = ($format & IMG_GIF) ? IMG_GIF : 0;
break;
case IMAGETYPE_JPEG:
$new_type = ($format & IMG_JPG) ? IMG_JPG : 0;
break;
case IMAGETYPE_PNG:
$new_type = ($format & IMG_PNG) ? IMG_PNG : 0;
break;
case IMAGETYPE_BMP:
$new_type = ($format & IMG_BMP) ? IMG_BMP : 0;
break;
case IMAGETYPE_WEBP:
$new_type = ($format & IMG_WEBP) ? IMG_WEBP : 0;
break;
}
return [
'gd' => (bool)$new_type,
'format' => $new_type,
'version' => (function_exists('imagecreatetruecolor')) ? 2 : 1
];
}
/**
* Create thumbnail
*
* @param string $source
* @param string $newFile
* @param string $mimeType
* @return bool
* @throws Exception
*/
function create_thumbnail($source, $new_file, $mimetype)
function createThumbnail(string $source, string $newFile, string $mimeType): bool
{
global $attach_config, $imagick;
$image = null;
global $attach_config;
// Get the file information
$source = amod_realpath($source);
$min_filesize = (int)$attach_config['img_min_thumb_filesize'];
$img_filesize = (@file_exists($source)) ? @filesize($source) : false;
$img_filesize = file_exists($source) ? filesize($source) : false;
// Checks the max allowed filesize
if (!$img_filesize || $img_filesize <= $min_filesize) {
return false;
}
[$width, $height, $type,] = getimagesize($source);
// Making the thumbnail image
try {
$image = new \claviska\SimpleImage();
$image
->fromFile($source)
->autoOrient()
->resize(150)
->toFile($newFile, $mimeType, ['quality' => 85]);
} catch (Exception $e) {
// Handle errors
throw new Exception($e->getMessage());
}
if (!$width || !$height) {
// Check the thumbnail existence after creating
if (!file_exists($newFile)) {
return false;
}
[$new_width, $new_height] = get_img_size_format($width, $height);
$used_imagick = false;
if (is_imagick()) {
passthru($imagick . ' -quality 85 -antialias -sample ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" +profile "*" "' . str_replace('\\', '/', $new_file) . '"');
if (@file_exists($new_file)) {
$used_imagick = true;
}
}
if (!$used_imagick) {
$type = get_supported_image_types($type);
if ($type['gd']) {
switch ($type['format']) {
case IMG_GIF:
$image = imagecreatefromgif($source);
break;
case IMG_JPG:
$image = imagecreatefromjpeg($source);
break;
case IMG_PNG:
$image = imagecreatefrompng($source);
break;
case IMG_BMP:
$image = imagecreatefrombmp($source);
break;
case IMG_WEBP:
$image = imagecreatefromwebp($source);
break;
default:
throw new Exception('Unknown file format: ' . $type['format']);
}
if ($type['version'] == 1 || !$attach_config['use_gd2']) {
$new_image = imagecreate($new_width, $new_height);
imagecopyresized($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
} else {
$new_image = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
}
switch ($type['format']) {
case IMG_GIF:
imagegif($new_image, $new_file);
break;
case IMG_JPG:
imagejpeg($new_image, $new_file, 90);
break;
case IMG_PNG:
imagepng($new_image, $new_file);
break;
case IMG_BMP:
imagebmp($new_image, $new_file);
break;
case IMG_WEBP:
imagewebp($new_image, $new_file);
break;
default:
throw new Exception('Unknown file format: ' . $type['format']);
}
imagedestroy($new_image);
}
}
if (!@file_exists($new_file)) {
return false;
}
@chmod($new_file, 0664);
return true;
}

View file

@ -2183,15 +2183,8 @@ $lang['IMAGE_LINK_SIZE_EXPLAIN'] = 'If this defined Dimension of an Image is rea
$lang['ASSIGNED_GROUP'] = 'Assigned Group';
$lang['IMAGE_CREATE_THUMBNAIL'] = 'Create Thumbnail';
$lang['IMAGE_CREATE_THUMBNAIL_EXPLAIN'] = 'Always create a Thumbnail. This feature overrides nearly all Settings within this Special Category, except of the Maximum Image Dimensions. With this Feature a Thumbnail will be displayed within the post, the User can click it to open the real Image.<br />Please Note that this feature requires Imagick to be installed, if it\'s not installed or if Safe-Mode is enabled the GD-Extension of PHP will be used. If the Image-Type is not supported by PHP, this Feature will be not used.';
$lang['IMAGE_MIN_THUMB_FILESIZE'] = 'Minimum Thumbnail Filesize';
$lang['IMAGE_MIN_THUMB_FILESIZE_EXPLAIN'] = 'If a Image is smaller than this defined Filesize, no Thumbnail will be created, because it\'s small enough.';
$lang['IMAGE_IMAGICK_PATH'] = 'Imagick Program (Complete Path)';
$lang['IMAGE_IMAGICK_PATH_EXPLAIN'] = 'Enter the Path to the convert program of imagick, normally /usr/bin/convert (on windows: c:/imagemagick/convert.exe).';
$lang['IMAGE_SEARCH_IMAGICK'] = 'Search Imagick';
$lang['USE_GD2'] = 'Make use of GD2 Extension';
$lang['USE_GD2_EXPLAIN'] = 'PHP is able to be compiled with the GD1 or GD2 Extension for image manipulating. To correctly create Thumbnails without imagemagick the Attachment Mod uses two different methods, based on your selection here. If your thumbnails are in a bad quality or screwed up, try to change this setting.';
// Extensions -> Forbidden Extensions
$lang['MANAGE_FORBIDDEN_EXTENSIONS'] = 'Manage Forbidden Extensions';

View file

@ -925,7 +925,7 @@ class Attach
// Check Image Size, if it's an image
if (!$error && !IS_ADMIN && $cat_id === IMAGE_CAT) {
[$width, $height] = image_getdimension($upload_dir . '/' . $this->attach_filename);
[$width, $height] = getimagesize($upload_dir . '/' . $this->attach_filename);
if ($width && $height && (int)$attach_config['img_max_width'] && (int)$attach_config['img_max_height']) {
if ($width > (int)$attach_config['img_max_width'] || $height > (int)$attach_config['img_max_height']) {
@ -1085,8 +1085,8 @@ class Attach
$dest_file = amod_realpath($upload_dir);
$dest_file .= '/' . THUMB_DIR . '/t_' . basename($this->attach_filename);
if (!create_thumbnail($source, $dest_file, $this->type)) {
if (!$file || !create_thumbnail($file, $dest_file, $this->type)) {
if (!createThumbnail($source, $dest_file, $this->type)) {
if (!$file || !createThumbnail($file, $dest_file, $this->type)) {
$this->thumbnail = 0;
}
}

View file

@ -17,22 +17,14 @@
</tr>
<!-- BEGIN switch_thumbnail_support -->
<tr>
<td class="row1" width="80%">{L_IMAGE_CREATE_THUMBNAIL}<br /><span class="small">{L_IMAGE_CREATE_THUMBNAIL_EXPLAIN}</span></td>
<td class="row1" width="80%">{L_IMAGE_CREATE_THUMBNAIL}<br /></td>
<td class="row2"><input type="radio" name="img_create_thumbnail" value="1" {CREATE_THUMBNAIL_YES} /> {L_YES}&nbsp;&nbsp;<input type="radio" name="img_create_thumbnail" value="0" {CREATE_THUMBNAIL_NO} /> {L_NO}</td>
</tr>
<tr>
<td class="row1" width="80%">{L_IMAGE_MIN_THUMB_FILESIZE}<br /><span class="small">{L_IMAGE_MIN_THUMB_FILESIZE_EXPLAIN}</span></td>
<td class="row2"><input type="text" size="7" maxlength="15" name="img_min_thumb_filesize" value="{IMAGE_MIN_THUMB_FILESIZE}" class="post" /> {L_BYTES}</td>
</tr>
<tr>
<td class="row1" width="80%">{L_USE_GD2}<br /><span class="small">{L_USE_GD2_EXPLAIN}</span></td>
<td class="row2"><input type="radio" name="use_gd2" value="1" {USE_GD2_YES} /> {L_YES}&nbsp;&nbsp;<input type="radio" name="use_gd2" value="0" {USE_GD2_NO} /> {L_NO}</td>
</tr>
<!-- END switch_thumbnail_support -->
<tr>
<td class="row1" width="80%">{L_IMAGE_IMAGICK_PATH}<br /><span class="small">{L_IMAGE_IMAGICK_PATH_EXPLAIN}</span></td>
<td class="row2"><input type="text" size="20" maxlength="200" name="img_imagick" value="{IMAGE_IMAGICK_PATH}" class="post" /></td>
</tr>
<tr>
<td class="row1" width="80%">{L_MAX_IMAGE_SIZE} <br /><span class="small">{L_MAX_IMAGE_SIZE_EXPLAIN}</span></td>
<td class="row2"><input type="text" size="3" maxlength="4" name="img_max_width" value="{IMAGE_MAX_WIDTH}" class="post" /> x <input type="text" size="3" maxlength="4" name="img_max_height" value="{IMAGE_MAX_HEIGHT}" class="post" /></td>