Skip to content

Commit

Permalink
added ImageUtils::compress
Browse files Browse the repository at this point in the history
  • Loading branch information
brainfoolong committed Sep 4, 2024
1 parent 7d381e0 commit 3cab85e
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 19 deletions.
72 changes: 55 additions & 17 deletions appdata/modules/Framelix/src/Utils/ImageUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

use Framelix\Framelix\Exception\FatalError;

use function end;
use function explode;
use function file_exists;
use function file_put_contents;
use function implode;
use function is_numeric;
use function strtolower;
use function unlink;

class ImageUtils
{
Expand Down Expand Up @@ -40,26 +42,49 @@ public static function getImageData(string $path): ?array
* @param string $dstPath destination path of image
* @param int $maxWidth Max width of image in pixels
* @param int $maxHeight Max height of image in pixels
* @param string $fit Sharp parameter, see https://sharp.pixelplumbing.com/api-resize#resize
* @param string $position Sharp parameter, see https://sharp.pixelplumbing.com/api-resize#resize
* @return Shell Return the shell command that have been executed
*/
public static function resize(string $srcPath, string $dstPath, int $maxWidth, int $maxHeight): Shell
public static function resize(string $srcPath, string $dstPath, int $maxWidth, int $maxHeight, string $fit = "inside", string $position = "centre"): Shell
{
$pathParts = explode(".", mb_strtolower($srcPath));
$extension = end($pathParts);

$shell = Shell::prepare(
'convert {*}',
[
$srcPath . ($extension == "gif" ? '[0]' : ''),
'-resize',
"{$maxWidth}x{$maxHeight}>",
'-quality',
'85',
$dstPath,
]
if (file_exists($dstPath)) {
unlink($dstPath);
}
return self::executeNodeJsSharpCmd(
/**@lang JavaScript */ '
sharp(' . JsonUtils::encode($srcPath) . ').resize(' . JsonUtils::encode(
["width" => $maxWidth, "height" => $maxHeight, "fit" => $fit, "position" => $position]
) . ').toFile(' . JsonUtils::encode($dstPath) . ')
'
);
$shell->execute();
return $shell;
}

/**
* Compress an image, can also convert on the file to new filetype
* @param string $srcPath source path of image
* @param string $dstPath destination path of image Only png, jpeg, jpg, gif and webp is supported
* @return Shell Return the shell command that have been executed
*/
public static function compress(string $srcPath, string $dstPath): Shell
{
$extension = strtolower(pathinfo($dstPath, PATHINFO_EXTENSION));
$code = /**@lang JavaScript */
'const img = sharp(' . JsonUtils::encode($srcPath) . ');';
if ($extension === "png") {
$code .= "img.png({quality:80});";
}
if ($extension === "jpg" || $extension === "jpeg") {
$code .= "img.jpeg({quality:80, mozjpeg:true});";
}
if ($extension === "gif") {
$code .= "img.gif();";
}
if ($extension === "webp") {
$code .= "img.webp({quality:80});";
}
$code .= "img.toFile(" . JsonUtils::encode($dstPath) . ");";
return self::executeNodeJsSharpCmd($code);
}

/**
Expand Down Expand Up @@ -121,4 +146,17 @@ public static function compareImages(
return $diff <= $threshold;
}

public static function executeNodeJsSharpCmd(string $jsCode): Shell
{
$tmpFolder = FileUtils::getTmpFolder();
$tmpFile = $tmpFolder . "/sharp.js";

$jsCode = 'const sharp = require("' . (__DIR__ . "/../../node_modules/sharp/lib/index.js") . '");' . "\n" . $jsCode;
file_put_contents($tmpFile, $jsCode);

$shell = Shell::prepare("node {*}", [$tmpFile]);
$shell->execute();
return $shell;
}

}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 31 additions & 2 deletions appdata/modules/FramelixTests/tests/Utils/ImageUtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
use Framelix\Framelix\Utils\ImageUtils;
use Framelix\FramelixTests\TestCase;

use function filesize;
use function unlink;

use const FRAMELIX_TMP_FOLDER;

final class ImageUtilsTest extends TestCase
{

public function testCompare(): void
{
$this->assertTrue(
Expand Down Expand Up @@ -47,12 +49,11 @@ public function testResize(): void
{
$testImage = __DIR__ . "/../../test-files/imageutils/test-image.jpg";
$testResizedImage = FRAMELIX_TMP_FOLDER . "/test-image-resized.jpg";
ImageUtils::resize($testImage, $testResizedImage, 100, 100);
$shell = ImageUtils::resize($testImage, $testResizedImage, 100, 100);
$this->assertEquals(['type' => 'jpeg', 'width' => 100, 'height' => 67],
ImageUtils::getImageData($testResizedImage));
unlink($testResizedImage);


$testImage = __DIR__ . "/../../test-files/imageutils/test-image.png";
$testResizedImage = FRAMELIX_TMP_FOLDER . "/test-image-resized.png";
ImageUtils::resize($testImage, $testResizedImage, 100, 100);
Expand All @@ -61,6 +62,33 @@ public function testResize(): void
unlink($testResizedImage);
}

public function testCompress(): void
{
$testImage = __DIR__ . "/../../test-files/imageutils/test-image-uncompressed.jpg";
$testImageCompressed = FRAMELIX_TMP_FOLDER . "/test-image-compressed.jpg";
ImageUtils::compress($testImage, $testImageCompressed);
$this->assertTrue(filesize($testImageCompressed) < filesize($testImage));
unlink($testImageCompressed);

$testImage = __DIR__ . "/../../test-files/imageutils/test-image-uncompressed.png";
$testImageCompressed = FRAMELIX_TMP_FOLDER . "/test-image-compressed.png";
ImageUtils::compress($testImage, $testImageCompressed);
$this->assertTrue(filesize($testImageCompressed) < filesize($testImage));
unlink($testImageCompressed);

$testImage = __DIR__ . "/../../test-files/imageutils/test-image-uncompressed.png";
$testImageCompressed = FRAMELIX_TMP_FOLDER . "/test-image-compressed.webp";
ImageUtils::compress($testImage, $testImageCompressed);
$this->assertTrue(filesize($testImageCompressed) < filesize($testImage));
unlink($testImageCompressed);

$testImage = __DIR__ . "/../../test-files/imageutils/test-image-uncompressed.png";
$testImageCompressed = FRAMELIX_TMP_FOLDER . "/test-image-compressed.gif";
ImageUtils::compress($testImage, $testImageCompressed);
$this->assertTrue(filesize($testImageCompressed) < filesize($testImage));
unlink($testImageCompressed);
}

public function testPdfToImage(): void
{
$testPdf = __DIR__ . "/../../test-files/imageutils/test-pdf.pdf";
Expand All @@ -76,4 +104,5 @@ public function testPdfToImage(): void
ImageUtils::getImageData($testResizedImage));
unlink($testResizedImage);
}

}

0 comments on commit 3cab85e

Please sign in to comment.