Commit 37cd2b25 authored by Benni Mack's avatar Benni Mack Committed by Christian Kuhn
Browse files

[!!!][TASK] Remove processor_path_lzw option

LZW enabled compression for GIF and TIF is now removed
in favor of just using convert which is available most of
the time. This was needed back in 200x when TIFF was
super-big, but is usually now properly bundled in IM/GM.

Resolves: #97797
Releases: main
Change-Id: Iba4d19f27cde90ee910048f12ec27ede13282c16
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/74918


Tested-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Tested-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Christian Kuhn's avatarChristian Kuhn <lolli@schwarzbu.ch>
parent c4b3e9d7
...@@ -2178,7 +2178,6 @@ class GraphicalFunctions ...@@ -2178,7 +2178,6 @@ class GraphicalFunctions
$info = $this->getImageDimensions($info[3]); $info = $this->getImageDimensions($info[3]);
} }
if ($info[2] == $this->gifExtension && !$this->dontCompress) { if ($info[2] == $this->gifExtension && !$this->dontCompress) {
// Compress with IM (lzw) or GD (rle) (Workaround for the absence of lzw-compression in GD)
self::gifCompress($info[3], ''); self::gifCompress($info[3], '');
} }
return $info; return $info;
...@@ -2538,12 +2537,12 @@ class GraphicalFunctions ...@@ -2538,12 +2537,12 @@ class GraphicalFunctions
} }
/** /**
* Compressing a GIF file if not already LZW compressed. * Compressing a GIF file if not already compressed.
* This function is a workaround for the fact that ImageMagick and/or GD does not compress GIF-files to their minimum size (that is RLE or no compression used) * This function is a workaround for the fact that ImageMagick and/or GD does not compress GIF-files to their minimum size (that is RLE or no compression used)
* *
* The function takes a file-reference, $theFile, and saves it again through GD or ImageMagick in order to compress the file * The function takes a file-reference, $theFile, and saves it again through GD or ImageMagick in order to compress the file
* GIF: * GIF:
* If $type is not set, the compression is done with ImageMagick (provided that $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path_lzw'] is pointing to the path of a lzw-enabled version of 'convert') else with GD (should be RLE-enabled!) * If $type is not set, the compression is done with ImageMagick
* If $type is set to either 'IM' or 'GD' the compression is done with ImageMagick and GD respectively * If $type is set to either 'IM' or 'GD' the compression is done with ImageMagick and GD respectively
* PNG: * PNG:
* No changes. * No changes.
...@@ -2562,7 +2561,7 @@ class GraphicalFunctions ...@@ -2562,7 +2561,7 @@ class GraphicalFunctions
return ''; return '';
} }
if (($type === 'IM' || !$type) && $gfxConf['processor_enabled'] && $gfxConf['processor_path_lzw']) { if (($type === 'IM' || !$type) && $gfxConf['processor_enabled']) {
// Use temporary file to prevent problems with read and write lock on same file on network file systems // Use temporary file to prevent problems with read and write lock on same file on network file systems
$temporaryName = PathUtility::dirname($theFile) . '/' . md5(StringUtility::getUniqueId()) . '.gif'; $temporaryName = PathUtility::dirname($theFile) . '/' . md5(StringUtility::getUniqueId()) . '.gif';
// Rename could fail, if a simultaneous thread is currently working on the same thing // Rename could fail, if a simultaneous thread is currently working on the same thing
...@@ -2570,7 +2569,7 @@ class GraphicalFunctions ...@@ -2570,7 +2569,7 @@ class GraphicalFunctions
$cmd = CommandUtility::imageMagickCommand( $cmd = CommandUtility::imageMagickCommand(
'convert', 'convert',
ImageMagickFile::fromFilePath($temporaryName) . ' ' . CommandUtility::escapeShellArgument($theFile), ImageMagickFile::fromFilePath($temporaryName) . ' ' . CommandUtility::escapeShellArgument($theFile),
$gfxConf['processor_path_lzw'] $gfxConf['processor_path']
); );
CommandUtility::exec($cmd); CommandUtility::exec($cmd);
unlink($temporaryName); unlink($temporaryName);
......
...@@ -39,7 +39,7 @@ use TYPO3\CMS\Core\Core\Environment; ...@@ -39,7 +39,7 @@ use TYPO3\CMS\Core\Core\Environment;
* checkCommand() returns TRUE if a command is available * checkCommand() returns TRUE if a command is available
* *
* Search paths that are included: * Search paths that are included:
* $TYPO3_CONF_VARS['GFX']['processor_path_lzw'] or $TYPO3_CONF_VARS['GFX']['processor_path'] * $TYPO3_CONF_VARS['GFX']['processor_path']
* $TYPO3_CONF_VARS['SYS']['binPath'] * $TYPO3_CONF_VARS['SYS']['binPath']
* $GLOBALS['_SERVER']['PATH'] * $GLOBALS['_SERVER']['PATH']
* '/usr/bin/,/usr/local/bin/' on Unix * '/usr/bin/,/usr/local/bin/' on Unix
...@@ -377,8 +377,7 @@ class CommandUtility ...@@ -377,8 +377,7 @@ class CommandUtility
$sysPathArr = []; $sysPathArr = [];
// Image magick paths first // Image magick paths first
// processor_path_lzw take precedence over processor_path if ($imPath = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path']) {
if ($imPath = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path_lzw'] ?: $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path']) {
$imPath = self::fixPath($imPath); $imPath = self::fixPath($imPath);
$pathsArr[$imPath] = $imPath; $pathsArr[$imPath] = $imPath;
} }
......
...@@ -31,7 +31,6 @@ return [ ...@@ -31,7 +31,6 @@ return [
'gdlib_png' => false, 'gdlib_png' => false,
'processor_enabled' => true, 'processor_enabled' => true,
'processor_path' => '/usr/bin/', 'processor_path' => '/usr/bin/',
'processor_path_lzw' => '/usr/bin/',
'processor' => 'ImageMagick', 'processor' => 'ImageMagick',
'processor_effects' => false, 'processor_effects' => false,
'processor_allowUpscaling' => true, 'processor_allowUpscaling' => true,
......
...@@ -26,9 +26,6 @@ GFX: ...@@ -26,9 +26,6 @@ GFX:
processor_path: processor_path:
type: text type: text
description: 'Path to the IM tools ''convert'', ''combine'', ''identify''.' description: 'Path to the IM tools ''convert'', ''combine'', ''identify''.'
processor_path_lzw:
type: text
description: 'Path to the IM tool ''convert'' with LZW enabled! See ''gif_compress''. If your version 4.2.9 of ImageMagick is compiled with LZW you may leave this field blank AND disable the flag ''gif_compress''! Tip: You can call LZW ''convert'' with a prefix like ''myver_convert'' by setting this path with it, eg. <code>/usr/bin/myver_</code> instead of just <code>/usr/bin/</code>.'
processor: processor:
type: dropdown type: dropdown
allowedValues: allowedValues:
......
.. include:: /Includes.rst.txt
.. _breaking-97797-1655730428:
=========================================================
Breaking: #97797 - GFX setting processor_path_lzw removed
=========================================================
See :issue:`97797`
Description
===========
The global configuration option :php:`$GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path_lzw']`
which was used to compress GIF and TIFF files with a different ImageMagick version,
as LZW compression was removed from the distributed ImageMagick binaries back in
2004-2006.
Since then, both GIF and TIFF have had reduced impact on the web we know today.
For this reason, the value is removed. If GIF compression via LZW is wanted,
it should be pointing to the main `processor_path` setting.
Impact
======
Compression via LZW for GIF files is now only applied when the corresponding
ImageMagick version, found in `processor_path` is supporting LZW compression.
The GFX setting `processor_path_lzw` is not used anymore, and can safely be
removed. When accessing the Install Tool, the setting is automatically removed
from :file:`LocalConfiguration.php`.
Affected installations
======================
TYPO3 installations actively using GIF compression or GIF thumbnails over PNG
thumbnails (if `GFX/thumbnails_png` is set to false), which might result in
GIF files with a larger file size.
Migration
=========
It is recommended to switch to PNG thumbnails (TYPO3 setting `GFX/thumbnails_png`),
or use a ImageMagick version supporting LZW compression for GIF files, if this
functionality is explicitly needed.
In addition, solutions such as `gifsicle` can be used instead to optimize
GIF images.
.. index:: Frontend, PartiallyScanned, ext:core
...@@ -56,7 +56,7 @@ abstract class AbstractImagePreset extends AbstractPreset ...@@ -56,7 +56,7 @@ abstract class AbstractImagePreset extends AbstractPreset
/** /**
* Check is preset is currently active on the system. * Check is preset is currently active on the system.
* Overwrites parent method to ignore processor_path and processor_path_lzw settings * Overwrites parent method to ignore processor_path setting
* *
* @return bool TRUE if preset is active * @return bool TRUE if preset is active
*/ */
...@@ -64,9 +64,7 @@ abstract class AbstractImagePreset extends AbstractPreset ...@@ -64,9 +64,7 @@ abstract class AbstractImagePreset extends AbstractPreset
{ {
$isActive = true; $isActive = true;
foreach ($this->configurationValues as $configurationKey => $configurationValue) { foreach ($this->configurationValues as $configurationKey => $configurationValue) {
if ($configurationKey !== 'GFX/processor_path' if ($configurationKey !== 'GFX/processor_path') {
&& $configurationKey !== 'GFX/processor_path_lzw'
) {
$currentValue = $this->configurationManager->getConfigurationValueByPath($configurationKey); $currentValue = $this->configurationManager->getConfigurationValueByPath($configurationKey);
if ($currentValue !== $configurationValue) { if ($currentValue !== $configurationValue) {
$isActive = false; $isActive = false;
...@@ -98,7 +96,6 @@ abstract class AbstractImagePreset extends AbstractPreset ...@@ -98,7 +96,6 @@ abstract class AbstractImagePreset extends AbstractPreset
$this->findExecutableInPath($this->getSearchPaths()); $this->findExecutableInPath($this->getSearchPaths());
$configurationValues = $this->configurationValues; $configurationValues = $this->configurationValues;
$configurationValues['GFX/processor_path'] = $this->getFoundPath(); $configurationValues['GFX/processor_path'] = $this->getFoundPath();
$configurationValues['GFX/processor_path_lzw'] = $this->getFoundPath();
return $configurationValues; return $configurationValues;
} }
...@@ -126,13 +123,6 @@ abstract class AbstractImagePreset extends AbstractPreset ...@@ -126,13 +123,6 @@ abstract class AbstractImagePreset extends AbstractPreset
array_unshift($searchPaths, $path); array_unshift($searchPaths, $path);
} }
// Add configured processor_path_lzw on top
$imLzwSearchPath = $GLOBALS['TYPO3_CONF_VARS']['GFX']['processor_path_lzw'];
if ((string)$imLzwSearchPath !== '' && !in_array($imLzwSearchPath, $searchPaths)) {
$path = $this->cleanUpPath($imLzwSearchPath);
array_unshift($searchPaths, $path);
}
// Add additional search path from form if given // Add additional search path from form if given
if (isset($this->postValues['additionalSearchPath']) if (isset($this->postValues['additionalSearchPath'])
&& (string)$this->postValues['additionalSearchPath'] !== '' && (string)$this->postValues['additionalSearchPath'] !== ''
......
...@@ -30,7 +30,6 @@ class CustomPreset extends AbstractCustomPreset implements CustomPresetInterface ...@@ -30,7 +30,6 @@ class CustomPreset extends AbstractCustomPreset implements CustomPresetInterface
protected $configurationValues = [ protected $configurationValues = [
'GFX/processor_enabled' => false, 'GFX/processor_enabled' => false,
'GFX/processor_path' => '', 'GFX/processor_path' => '',
'GFX/processor_path_lzw' => '',
'GFX/processor' => '', 'GFX/processor' => '',
'GFX/processor_effects' => false, 'GFX/processor_effects' => false,
'GFX/processor_allowTemporaryMasksAsPng' => true, 'GFX/processor_allowTemporaryMasksAsPng' => true,
......
...@@ -39,9 +39,8 @@ class GraphicsMagickPreset extends AbstractImagePreset ...@@ -39,9 +39,8 @@ class GraphicsMagickPreset extends AbstractImagePreset
*/ */
protected $configurationValues = [ protected $configurationValues = [
'GFX/processor_enabled' => true, 'GFX/processor_enabled' => true,
// processor_path and processor_path_lzw are determined and set by path lookup methods // processor_path is determined and set by path lookup methods
'GFX/processor_path' => '', 'GFX/processor_path' => '',
'GFX/processor_path_lzw' => '',
'GFX/processor' => 'GraphicsMagick', 'GFX/processor' => 'GraphicsMagick',
'GFX/processor_effects' => false, 'GFX/processor_effects' => false,
'GFX/processor_allowTemporaryMasksAsPng' => false, 'GFX/processor_allowTemporaryMasksAsPng' => false,
......
...@@ -39,9 +39,8 @@ class ImageMagick6Preset extends AbstractImagePreset ...@@ -39,9 +39,8 @@ class ImageMagick6Preset extends AbstractImagePreset
*/ */
protected $configurationValues = [ protected $configurationValues = [
'GFX/processor_enabled' => true, 'GFX/processor_enabled' => true,
// processor_path and processor_path_lzw are determined and set by path lookup methods // processor_path is determined and set by path lookup methods
'GFX/processor_path' => '', 'GFX/processor_path' => '',
'GFX/processor_path_lzw' => '',
'GFX/processor' => 'ImageMagick', 'GFX/processor' => 'ImageMagick',
'GFX/processor_effects' => true, 'GFX/processor_effects' => true,
'GFX/processor_allowTemporaryMasksAsPng' => false, 'GFX/processor_allowTemporaryMasksAsPng' => false,
......
...@@ -1183,7 +1183,7 @@ class EnvironmentController extends AbstractController ...@@ -1183,7 +1183,7 @@ class EnvironmentController extends AbstractController
return new FlashMessage( return new FlashMessage(
'ImageMagick / GraphicsMagick handling is enabled, but the execute' 'ImageMagick / GraphicsMagick handling is enabled, but the execute'
. ' command returned an error. Please check your settings, especially' . ' command returned an error. Please check your settings, especially'
. ' [\'GFX\'][\'processor_path\'] and [\'GFX\'][\'processor_path_lzw\'] and ensure Ghostscript is installed on your server.', . ' [\'GFX\'][\'processor_path\'] and ensure Ghostscript is installed on your server.',
'Image generation failed', 'Image generation failed',
FlashMessage::ERROR FlashMessage::ERROR
); );
......
...@@ -175,6 +175,9 @@ class SilentConfigurationUpgradeService ...@@ -175,6 +175,9 @@ class SilentConfigurationUpgradeService
'EXT/allowLocalInstall', 'EXT/allowLocalInstall',
// #97265 // #97265
'BE/explicitADmode', 'BE/explicitADmode',
// Please note that further migrations in this file are kept in order to remove the setting at the very end
// #97797
'GFX/processor_path_lzw',
]; ];
public function __construct(ConfigurationManager $configurationManager) public function __construct(ConfigurationManager $configurationManager)
...@@ -475,12 +478,6 @@ class SilentConfigurationUpgradeService ...@@ -475,12 +478,6 @@ class SilentConfigurationUpgradeService
$currentPathValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_path'); $currentPathValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_path');
} }
try {
$currentPathLzwValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/processor_path_lzw');
} catch (MissingArrayPathException $e) {
$currentPathLzwValue = $this->configurationManager->getDefaultConfigurationValueByPath('GFX/processor_path_lzw');
}
try { try {
$currentImageFileExtValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/imagefile_ext'); $currentImageFileExtValue = $this->configurationManager->getLocalConfigurationValueByPath('GFX/imagefile_ext');
} catch (MissingArrayPathException $e) { } catch (MissingArrayPathException $e) {
...@@ -497,9 +494,6 @@ class SilentConfigurationUpgradeService ...@@ -497,9 +494,6 @@ class SilentConfigurationUpgradeService
if ($currentPathValue != '') { if ($currentPathValue != '') {
$changedValues['GFX/processor_path'] = ''; $changedValues['GFX/processor_path'] = '';
} }
if ($currentPathLzwValue != '') {
$changedValues['GFX/processor_path_lzw'] = '';
}
if ($currentImageFileExtValue !== 'gif,jpg,jpeg,png') { if ($currentImageFileExtValue !== 'gif,jpg,jpeg,png') {
$changedValues['GFX/imagefile_ext'] = 'gif,jpg,jpeg,png'; $changedValues['GFX/imagefile_ext'] = 'gif,jpg,jpeg,png';
} }
......
...@@ -755,4 +755,9 @@ return [ ...@@ -755,4 +755,9 @@ return [
'Feature-97737-PSR-14EventsWhenPageRootlineInFrontendIsResolved.rst', 'Feature-97737-PSR-14EventsWhenPageRootlineInFrontendIsResolved.rst',
], ],
], ],
'$GLOBALS[\'TYPO3_CONF_VARS\'][\'GFX\'][\'processor_path_lzw\']' => [
'restFiles' => [
'Breaking-97797-GFXSettingProcessor_path_lzwRemoved.rst',
],
],
]; ];
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
<h3>Writing gif, png, webp</h3> <h3>Writing gif, png, webp</h3>
<p> <p>
This verifies that ImageMagick is able to write GIF and PNG and WEBP files. This verifies that ImageMagick is able to write GIF and PNG and WEBP files.
The GIF-file is attempted compressed with LZW by the The GIF-file is attempted compressed by the
<code>\TYPO3\CMS\Core\Imaging\GraphicalFunctions::gifCompress()</code> function. <code>\TYPO3\CMS\Core\Imaging\GraphicalFunctions::gifCompress()</code> function.
</p> </p>
<h4>Write gif</h4> <h4>Write gif</h4>
......
These comparison images was generated by Kasper Skårhøj, using:
- TYPO3 3.8.0
- Image Magick 5.5.7 / FreeType 2 / PHP4
- This localconf.php configuration:
$TYPO3_CONF_VARS['GFX']['processor_path_lzw'] = '';
$TYPO3_CONF_VARS['GFX']['TTFdpi'] = '96';
$TYPO3_CONF_VARS['GFX']['gdlib_png'] = '1';
$TYPO3_CONF_VARS['GFX']['processor_path'] = '/usr/bin/';
$TYPO3_CONF_VARS['GFX']['processor'] = 'im5';
$TYPO3_CONF_VARS['GFX']['processor_effects'] = true;
$TYPO3_CONF_VARS['GFX']['gdlib_2'] = 1;
- PHP / GD configuration:
GD Support enabled
GD Version 2.0 or higher
FreeType Support enabled
FreeType Linkage with freetype
T1Lib Support enabled
GIF Read Support enabled
GIF Create Support enabled
JPG Support enabled
PNG Support enabled
WBMP Support enabled
- I was not able to create GIF files for reference so I just converted them directly with ImageMagick
- Also LZW compression has NOT been used anywhere except the GD test images since ImageMagick doesn't support it.
...@@ -385,7 +385,6 @@ class SilentConfigurationUpgradeServiceTest extends UnitTestCase ...@@ -385,7 +385,6 @@ class SilentConfigurationUpgradeServiceTest extends UnitTestCase
$currentLocalConfiguration = [ $currentLocalConfiguration = [
['GFX/im', 0], ['GFX/im', 0],
['GFX/im_path', ''], ['GFX/im_path', ''],
['GFX/im_path_lzw', ''],
['GFX/imagefile_ext', 'gif,jpg,png'], ['GFX/imagefile_ext', 'gif,jpg,png'],
['GFX/thumbnails', 0], ['GFX/thumbnails', 0],
]; ];
...@@ -396,7 +395,7 @@ class SilentConfigurationUpgradeServiceTest extends UnitTestCase ...@@ -396,7 +395,7 @@ class SilentConfigurationUpgradeServiceTest extends UnitTestCase
'setLocalConfigurationValuesByPathValuePairs', 'setLocalConfigurationValuesByPathValuePairs',
] ]
); );
$this->configurationManager->expects(self::exactly(5)) $this->configurationManager->expects(self::exactly(4))
->method('getLocalConfigurationValueByPath') ->method('getLocalConfigurationValueByPath')
->willReturnMap($currentLocalConfiguration); ->willReturnMap($currentLocalConfiguration);
$this->configurationManager->expects(self::never()) $this->configurationManager->expects(self::never())
...@@ -430,7 +429,6 @@ class SilentConfigurationUpgradeServiceTest extends UnitTestCase ...@@ -430,7 +429,6 @@ class SilentConfigurationUpgradeServiceTest extends UnitTestCase
$currentLocalConfiguration = [ $currentLocalConfiguration = [
['GFX/im', 1], ['GFX/im', 1],
['GFX/im_path', ''], ['GFX/im_path', ''],
['GFX/im_path_lzw', ''],
['GFX/imagefile_ext', 'gif,jpg,jpeg,png'], ['GFX/imagefile_ext', 'gif,jpg,jpeg,png'],
['GFX/thumbnails', 0], ['GFX/thumbnails', 0],
]; ];
...@@ -441,7 +439,7 @@ class SilentConfigurationUpgradeServiceTest extends UnitTestCase ...@@ -441,7 +439,7 @@ class SilentConfigurationUpgradeServiceTest extends UnitTestCase
'setLocalConfigurationValuesByPathValuePairs', 'setLocalConfigurationValuesByPathValuePairs',
] ]
); );
$this->configurationManager->expects(self::exactly(5)) $this->configurationManager->expects(self::exactly(4))
->method('getLocalConfigurationValueByPath') ->method('getLocalConfigurationValueByPath')
->willReturnMap($currentLocalConfiguration); ->willReturnMap($currentLocalConfiguration);
$this->configurationManager->expects(self::never()) $this->configurationManager->expects(self::never())
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment