mirror of
https://github.com/vichan-devel/vichan.git
synced 2024-11-23 23:20:57 +01:00
Better image processing. Add support for GraphicsMagick (a fork of ImageMagick) and exiftool
(for stripping EXIF metadata quickly).
This commit is contained in:
parent
a3fbff2259
commit
5300ffadf1
@ -63,6 +63,10 @@
|
|||||||
// Use `host` via shell_exec() to lookup hostnames, avoiding query timeouts. May not work on your system.
|
// Use `host` via shell_exec() to lookup hostnames, avoiding query timeouts. May not work on your system.
|
||||||
// Requires safe_mode to be disabled.
|
// Requires safe_mode to be disabled.
|
||||||
$config['dns_system'] = false;
|
$config['dns_system'] = false;
|
||||||
|
|
||||||
|
// When executing most command-line tools (such as `convert` for ImageMagick image processing), add this
|
||||||
|
// to the environment path (seperated by :).
|
||||||
|
$config['shell_path'] = '/usr/local/bin';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ====================
|
* ====================
|
||||||
@ -487,7 +491,11 @@
|
|||||||
* 'convert' The command line version of ImageMagick (`convert`). Fixes most of the bugs in
|
* 'convert' The command line version of ImageMagick (`convert`). Fixes most of the bugs in
|
||||||
* PHP Imagick. `convert` produces the best still thumbnails and is highly recommended.
|
* PHP Imagick. `convert` produces the best still thumbnails and is highly recommended.
|
||||||
*
|
*
|
||||||
* 'convert+gifsicle' Same as above, with the exception of using `gifsicle` (command line application)
|
* 'gm' GraphicsMagick (`gm`) is a fork of ImageMagick with many improvements. It is more
|
||||||
|
* efficient and gets thumbnailing done using fewer resources.
|
||||||
|
*
|
||||||
|
* 'convert+gifscale'
|
||||||
|
* OR 'gm+gifsicle' Same as above, with the exception of using `gifsicle` (command line application)
|
||||||
* instead of `convert` for resizing GIFs. It's faster and resulting animated
|
* instead of `convert` for resizing GIFs. It's faster and resulting animated
|
||||||
* thumbnails have less artifacts than if resized with ImageMagick.
|
* thumbnails have less artifacts than if resized with ImageMagick.
|
||||||
*/
|
*/
|
||||||
@ -496,10 +504,24 @@
|
|||||||
|
|
||||||
// Command-line options passed to ImageMagick when using `convert` for thumbnailing. Don't touch the
|
// Command-line options passed to ImageMagick when using `convert` for thumbnailing. Don't touch the
|
||||||
// placement of "%s" and "%d".
|
// placement of "%s" and "%d".
|
||||||
$config['convert_args'] = '-background transparent %s -strip -thumbnail %dx%d -quality 65';
|
$config['convert_args'] = '-size %dx%d %s -thumbnail %dx%d +profile "*" %s';
|
||||||
|
|
||||||
// Strip EXIF metadata from JPEG files.
|
// Strip EXIF metadata from JPEG files.
|
||||||
$config['strip_exif'] = false;
|
$config['strip_exif'] = false;
|
||||||
|
// Use the command-line `exiftool` tool to strip EXIF metadata without decompressing/recompressing JPEGs.
|
||||||
|
// Ignored when $config['redraw_image'] is true.
|
||||||
|
$config['strip_with_exiftool'] = false;
|
||||||
|
|
||||||
|
// Redraw the image to strip any excess data (commonly ZIP archives) WARNING: This might strip the
|
||||||
|
// animation of GIFs, depending on the chosen thumbnailing method. It also requires recompressing
|
||||||
|
// the image, so more processing power is required.
|
||||||
|
$config['redraw_image'] = false;
|
||||||
|
|
||||||
|
// Automatically correct the orientation of JPEG files using -auto-orient in `convert`. This only works
|
||||||
|
// when `convert` or `gm` is selected for thumbnailing. Again, requires more processing power because
|
||||||
|
// this basically does the same thing as $config['redraw_image']. (If $config['redraw_image'] is enabled,
|
||||||
|
// this value doesn't matter as $config['redraw_image'] attempts to correct orientation too.)
|
||||||
|
$config['convert_auto_orient'] = false;
|
||||||
|
|
||||||
// Regular expression to check for an XSS exploit with IE 6 and 7. To disable, set to false.
|
// Regular expression to check for an XSS exploit with IE 6 and 7. To disable, set to false.
|
||||||
// Details: https://github.com/savetheinternet/Tinyboard/issues/20
|
// Details: https://github.com/savetheinternet/Tinyboard/issues/20
|
||||||
@ -562,10 +584,6 @@
|
|||||||
// Display image identification links using regex.info/exif, TinEye and Google Images.
|
// Display image identification links using regex.info/exif, TinEye and Google Images.
|
||||||
$config['image_identification'] = false;
|
$config['image_identification'] = false;
|
||||||
|
|
||||||
// Redraw the image to strip any excess data (commonly ZIP archives) WARNING: This might strip the
|
|
||||||
// animation of GIFs, depending on the chosen thumbnailing method.
|
|
||||||
$config['redraw_image'] = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ====================
|
* ====================
|
||||||
* Board settings
|
* Board settings
|
||||||
|
@ -79,7 +79,7 @@ function loadConfig() {
|
|||||||
|
|
||||||
if ($config['debug']) {
|
if ($config['debug']) {
|
||||||
if (!isset($debug)) {
|
if (!isset($debug)) {
|
||||||
$debug = array('sql' => array(), 'purge' => array(), 'cached' => array(), 'write' => array());
|
$debug = array('sql' => array(), 'exec' => array(), 'purge' => array(), 'cached' => array(), 'write' => array());
|
||||||
$debug['start'] = microtime(true);
|
$debug['start'] = microtime(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -848,7 +848,7 @@ function bumpThread($id) {
|
|||||||
|
|
||||||
if ($config['try_smarter'])
|
if ($config['try_smarter'])
|
||||||
$build_pages[] = thread_find_page($id);
|
$build_pages[] = thread_find_page($id);
|
||||||
|
|
||||||
$query = prepare(sprintf("UPDATE ``posts_%s`` SET `bump` = :time WHERE `id` = :id AND `thread` IS NULL", $board['uri']));
|
$query = prepare(sprintf("UPDATE ``posts_%s`` SET `bump` = :time WHERE `id` = :id AND `thread` IS NULL", $board['uri']));
|
||||||
$query->bindValue(':time', time(), PDO::PARAM_INT);
|
$query->bindValue(':time', time(), PDO::PARAM_INT);
|
||||||
$query->bindValue(':id', $id, PDO::PARAM_INT);
|
$query->bindValue(':id', $id, PDO::PARAM_INT);
|
||||||
@ -1282,7 +1282,7 @@ function buildIndex() {
|
|||||||
|
|
||||||
for ($page = 1; $page <= $config['max_pages']; $page++) {
|
for ($page = 1; $page <= $config['max_pages']; $page++) {
|
||||||
$filename = $board['dir'] . ($page == 1 ? $config['file_index'] : sprintf($config['file_page'], $page));
|
$filename = $board['dir'] . ($page == 1 ? $config['file_index'] : sprintf($config['file_page'], $page));
|
||||||
|
|
||||||
if ($config['try_smarter'] && isset($build_pages) && count($build_pages) && !in_array($page, $build_pages) && is_file($filename))
|
if ($config['try_smarter'] && isset($build_pages) && count($build_pages) && !in_array($page, $build_pages) && is_file($filename))
|
||||||
continue;
|
continue;
|
||||||
$content = index($page);
|
$content = index($page);
|
||||||
@ -1928,3 +1928,24 @@ function DNS($host) {
|
|||||||
|
|
||||||
return $ip_addr;
|
return $ip_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shell_exec_error($command) {
|
||||||
|
global $config, $debug;
|
||||||
|
|
||||||
|
if ($config['debug'])
|
||||||
|
$start = microtime(true);
|
||||||
|
|
||||||
|
$return = trim(shell_exec('PATH="' . escapeshellcmd($config['shell_path']) . ':$PATH";' . $command . ' 2>&1 && echo "TB_SUCCESS"'));
|
||||||
|
$return = preg_replace('/TB_SUCCESS$/', '', $return);
|
||||||
|
|
||||||
|
if ($config['debug']) {
|
||||||
|
$time = round((microtime(true) - $start) * 1000, 2) . 'ms';
|
||||||
|
$debug['exec'][] = array(
|
||||||
|
'command' => $command,
|
||||||
|
'time' => '~' . $time,
|
||||||
|
'response' => $return ? $return : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return === 'TB_SUCCESS' ? false : $return;
|
||||||
|
}
|
||||||
|
@ -19,7 +19,7 @@ class Image {
|
|||||||
|
|
||||||
if ($config['thumb_method'] == 'imagick') {
|
if ($config['thumb_method'] == 'imagick') {
|
||||||
$classname = 'ImageImagick';
|
$classname = 'ImageImagick';
|
||||||
} elseif ($config['thumb_method'] == 'convert' || $config['thumb_method'] == 'convert+gifsicle') {
|
} elseif (in_array($config['thumb_method'], array('convert', 'convert+gifsicle', 'gm', 'gm+gifsicle'))) {
|
||||||
$classname = 'ImageConvert';
|
$classname = 'ImageConvert';
|
||||||
} else {
|
} else {
|
||||||
$classname = 'Image' . strtoupper($this->format);
|
$classname = 'Image' . strtoupper($this->format);
|
||||||
@ -44,8 +44,6 @@ class Image {
|
|||||||
|
|
||||||
public function resize($extension, $max_width, $max_height) {
|
public function resize($extension, $max_width, $max_height) {
|
||||||
global $config;
|
global $config;
|
||||||
|
|
||||||
$gifsicle = false;
|
|
||||||
|
|
||||||
if ($config['thumb_method'] == 'imagick') {
|
if ($config['thumb_method'] == 'imagick') {
|
||||||
$classname = 'ImageImagick';
|
$classname = 'ImageImagick';
|
||||||
@ -54,6 +52,13 @@ class Image {
|
|||||||
} elseif ($config['thumb_method'] == 'convert+gifsicle') {
|
} elseif ($config['thumb_method'] == 'convert+gifsicle') {
|
||||||
$classname = 'ImageConvert';
|
$classname = 'ImageConvert';
|
||||||
$gifsicle = true;
|
$gifsicle = true;
|
||||||
|
} elseif ($config['thumb_method'] == 'gm') {
|
||||||
|
$classname = 'ImageConvert';
|
||||||
|
$gm = true;
|
||||||
|
} elseif ($config['thumb_method'] == 'gm+gifsicle') {
|
||||||
|
$classname = 'ImageConvert';
|
||||||
|
$gm = true;
|
||||||
|
$gifsicle = true;
|
||||||
} else {
|
} else {
|
||||||
$classname = 'Image' . strtoupper($extension);
|
$classname = 'Image' . strtoupper($extension);
|
||||||
if (!class_exists($classname)) {
|
if (!class_exists($classname)) {
|
||||||
@ -81,7 +86,6 @@ class Image {
|
|||||||
$height = $max_height;
|
$height = $max_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
$thumb->gifsicle = $gifsicle;
|
|
||||||
$thumb->_resize($this->image->image, $width, $height);
|
$thumb->_resize($this->image->image, $width, $height);
|
||||||
|
|
||||||
return $thumb;
|
return $thumb;
|
||||||
@ -227,15 +231,20 @@ class ImageImagick extends ImageBase {
|
|||||||
|
|
||||||
|
|
||||||
class ImageConvert extends ImageBase {
|
class ImageConvert extends ImageBase {
|
||||||
public $width, $height, $temp, $gifsicle;
|
public $width, $height, $temp, $gm = false, $gifsicle = false;
|
||||||
|
|
||||||
public function init() {
|
public function init() {
|
||||||
global $config;
|
global $config;
|
||||||
|
|
||||||
|
if ($config['thumb_method'] == 'gm' || $config['thumb_method'] == 'gm+gifsicle')
|
||||||
|
$this->gm = true;
|
||||||
|
if ($config['thumb_method'] == 'convert+gifsicle' || $config['thumb_method'] == 'gm+gifsicle')
|
||||||
|
$this->gifsicle = true;
|
||||||
|
|
||||||
$this->temp = false;
|
$this->temp = false;
|
||||||
}
|
}
|
||||||
public function from() {
|
public function from() {
|
||||||
$size = trim(shell_exec('identify -format "%w %h" ' . escapeshellarg($this->src . '[0]')));
|
$size = shell_exec_error(($this->gm ? 'gm ' : '') . 'identify -format "%w %h" ' . escapeshellarg($this->src . '[0]'));
|
||||||
if (preg_match('/^(\d+) (\d+)$/', $size, $m)) {
|
if (preg_match('/^(\d+) (\d+)$/', $size, $m)) {
|
||||||
$this->width = $m[1];
|
$this->width = $m[1];
|
||||||
$this->height = $m[2];
|
$this->height = $m[2];
|
||||||
@ -251,9 +260,17 @@ class ImageConvert extends ImageBase {
|
|||||||
|
|
||||||
if (!$this->temp) {
|
if (!$this->temp) {
|
||||||
if ($config['strip_exif']) {
|
if ($config['strip_exif']) {
|
||||||
shell_exec('convert ' . escapeshellarg($this->src) . ' -auto-orient -strip ' . escapeshellarg($src));
|
if($error = shell_exec_error(($this->gm ? 'gm ' : '') . 'convert ' .
|
||||||
|
escapeshellarg($this->src) . ' -auto-orient -strip ' . escapeshellarg($src))) {
|
||||||
|
$this->destroy();
|
||||||
|
error('Failed to resize image!', null, $error);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
shell_exec('convert ' . escapeshellarg($this->src) . ' -auto-orient ' . escapeshellarg($src));
|
if($error = shell_exec_error(($this->gm ? 'gm ' : '') . 'convert ' .
|
||||||
|
escapeshellarg($this->src) . ' -auto-orient ' . escapeshellarg($src))) {
|
||||||
|
$this->destroy();
|
||||||
|
error('Failed to resize image!', null, $error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rename($this->temp, $src);
|
rename($this->temp, $src);
|
||||||
@ -289,13 +306,25 @@ class ImageConvert extends ImageBase {
|
|||||||
escapeshellarg($this->temp) . '2>&1 &&echo $?') !== '0') || !file_exists($this->temp))
|
escapeshellarg($this->temp) . '2>&1 &&echo $?') !== '0') || !file_exists($this->temp))
|
||||||
error('Failed to resize image!', null, $error);
|
error('Failed to resize image!', null, $error);
|
||||||
} else {
|
} else {
|
||||||
if (trim($error = shell_exec('convert ' . sprintf($config['convert_args'], '', $this->width, $this->height) . ' ' .
|
if ($error = shell_exec_error(($this->gm ? 'gm ' : '') . 'convert ' .
|
||||||
escapeshellarg($this->src) . ' ' . escapeshellarg($this->temp) . ' 2>&1 &&echo $?')) !== '0' || !file_exists($this->temp))
|
sprintf($config['convert_args'],
|
||||||
|
$this->width,
|
||||||
|
$this->height,
|
||||||
|
escapeshellarg($this->src),
|
||||||
|
$this->width,
|
||||||
|
$this->height,
|
||||||
|
escapeshellarg($this->temp))) || !file_exists($this->temp))
|
||||||
error('Failed to resize image!', null, $error);
|
error('Failed to resize image!', null, $error);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (trim($error = shell_exec('convert ' . sprintf($config['convert_args'], '-flatten', $this->width, $this->height) . ' ' .
|
if ($error = shell_exec_error(($this->gm ? 'gm ' : '') . 'convert ' .
|
||||||
escapeshellarg($this->src . '[0]') . " " . escapeshellarg($this->temp) . ' 2>&1 &&echo $?')) !== '0' || !file_exists($this->temp))
|
sprintf($config['convert_args'],
|
||||||
|
$this->width,
|
||||||
|
$this->height,
|
||||||
|
escapeshellarg($this->src . '[0]'),
|
||||||
|
$this->width,
|
||||||
|
$this->height,
|
||||||
|
escapeshellarg($this->temp))) || !file_exists($this->temp))
|
||||||
error('Failed to resize image!', null, $error);
|
error('Failed to resize image!', null, $error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
post.php
21
post.php
@ -447,14 +447,17 @@ if (isset($_POST['delete'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg') {
|
if ($config['convert_auto_orient'] && ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg')) {
|
||||||
// The following code corrects the image orientation.
|
// The following code corrects the image orientation.
|
||||||
// Currently only works with the 'convert' option selected but it could easily be expanded to work with the rest if you can be bothered.
|
// Currently only works with the 'convert' option selected but it could easily be expanded to work with the rest if you can be bothered.
|
||||||
if (!($config['redraw_image'] || ($config['strip_exif'] && ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg')))) {
|
if (!($config['redraw_image'] || ($config['strip_exif'] && ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg')))) {
|
||||||
if ($config['thumb_method'] == 'convert' || $config['thumb_method'] == 'convert+gifsicle') {
|
if (in_array($config['thumb_method'], array('convert', 'convert+gifsicle', 'gm', 'gm+gifsicle'))) {
|
||||||
$exif = exif_read_data($upload);
|
$exif = exif_read_data($upload);
|
||||||
|
$gm = in_array($config['thumb_method'], array('gm', 'gm+gifsicle'));
|
||||||
if (isset($exif['Orientation']) && $exif['Orientation'] != 1) {
|
if (isset($exif['Orientation']) && $exif['Orientation'] != 1) {
|
||||||
shell_exec('convert ' . escapeshellarg($upload) . ' -auto-orient ' . escapeshellarg($upload));
|
if($error = shell_exec_error(($gm ? 'gm ' : '') . 'convert ' .
|
||||||
|
escapeshellarg($upload) . ' -auto-orient ' . escapeshellarg($upload)))
|
||||||
|
error('Could not auto-orient image!', null, $error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -462,7 +465,6 @@ if (isset($_POST['delete'])) {
|
|||||||
|
|
||||||
// create image object
|
// create image object
|
||||||
$image = new Image($upload, $post['extension']);
|
$image = new Image($upload, $post['extension']);
|
||||||
|
|
||||||
if ($image->size->width > $config['max_width'] || $image->size->height > $config['max_height']) {
|
if ($image->size->width > $config['max_width'] || $image->size->height > $config['max_height']) {
|
||||||
$image->delete();
|
$image->delete();
|
||||||
error($config['error']['maxsize']);
|
error($config['error']['maxsize']);
|
||||||
@ -503,8 +505,13 @@ if (isset($_POST['delete'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($config['redraw_image'] || ($config['strip_exif'] && ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg'))) {
|
if ($config['redraw_image'] || ($config['strip_exif'] && ($post['extension'] == 'jpg' || $post['extension'] == 'jpeg'))) {
|
||||||
$image->to($post['file']);
|
if (!$config['redraw_image'] && $config['strip_with_exiftool']) {
|
||||||
$dont_copy_file = true;
|
if($error = shell_exec_error('exiftool -q -all= ' . escapeshellarg($upload)))
|
||||||
|
error('Could not strip EXIF metadata!', null, $error);
|
||||||
|
} else {
|
||||||
|
$image->to($post['file']);
|
||||||
|
$dont_copy_file = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$image->destroy();
|
$image->destroy();
|
||||||
} else {
|
} else {
|
||||||
@ -518,7 +525,7 @@ if (isset($_POST['delete'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($dont_copy_file) || !$dont_copy_file) {
|
if (!isset($dont_copy_file) || !$dont_copy_file) {
|
||||||
if (!@move_uploaded_file($_FILES['file']['tmp_name'], $post['file']))
|
if (!@move_uploaded_file($upload, $post['file']))
|
||||||
error($config['error']['nomove']);
|
error($config['error']['nomove']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user