From 29870055e5931a7bd362547f13685f6fa6f9e536 Mon Sep 17 00:00:00 2001 From: Timothee Date: Wed, 6 Aug 2025 11:39:06 +0200 Subject: [PATCH 1/5] =?UTF-8?q?N=C2=B03124=20-=20Refactorize=20ResizeImage?= =?UTF-8?q?ToFit=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/cmdbabstract.class.inc.php | 25 ++---- application/utils.inc.php | 81 +----------------- core/inlineimage.class.inc.php | 80 +---------------- core/ormdocument.class.inc.php | 85 +++++++++++++++++++ .../Controller/UserProfileBrickController.php | 7 +- pages/ajax.render.php | 6 +- 6 files changed, 107 insertions(+), 177 deletions(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index ebdad6b025..88f878817a 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -4313,24 +4313,15 @@ protected function PrepareValueFromPostedForm($sFormPrefix, $sAttCode, $sClass = case 'Image': $value = null; + $aDimensions = null; $oImage = utils::ReadPostedDocument("attr_{$sFormPrefix}{$sAttCode}", 'fcontents'); - if (!is_null($oImage->GetData())) - { - $aSize = utils::GetImageSize($oImage->GetData()); - if (is_array($aSize) && $aSize[0] > 0 && $aSize[1] > 0) - { - $oImage = utils::ResizeImageToFit( - $oImage, - $aSize[0], - $aSize[1], - $oAttDef->Get('storage_max_width'), - $oAttDef->Get('storage_max_height') - ); - } - else - { - IssueLog::Warning($sClass . ':' . $this->GetKey() . '/' . $sAttCode . ': Image could not be resized. Mimetype: ' . $oImage->GetMimeType() . ', filename: ' . $oImage->GetFileName()); - } + $oImage = $oImage->ResizeImageToFit( + $oAttDef->Get('storage_max_width'), + $oAttDef->Get('storage_max_height'), + $aDimensions + ); + if (is_null($aDimensions)) { + IssueLog::Warning($sClass . ':' . $this->GetKey() . '/' . $sAttCode . ': Image could not be resized. Mimetype: ' . $oImage->GetMimeType() . ', filename: ' . $oImage->GetFileName()); } $aOtherData = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null, 'raw_data'); if (is_array($aOtherData)) diff --git a/application/utils.inc.php b/application/utils.inc.php index ce2669ef93..5d7c84b8fd 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -2323,87 +2323,12 @@ public static function GetImageSize($sImageData) * @param int $iMaxImageWidth Maximum width for the resized image * @param int $iMaxImageHeight Maximum height for the resized image * @return ormDocument The resampled image + * + * @deprecated Replaced by ormDocument::ResizeImageToFit */ public static function ResizeImageToFit(ormDocument $oImage, $iWidth, $iHeight, $iMaxImageWidth, $iMaxImageHeight) { - // If image size smaller than maximums, we do nothing - if (($iWidth <= $iMaxImageWidth) && ($iHeight <= $iMaxImageHeight)) - { - return $oImage; - } - - - // If gd extension is not loaded, we put a warning in the log and return the image as is - if (extension_loaded('gd') === false) - { - IssueLog::Warning('Image could not be resized as the "gd" extension does not seem to be loaded. It will remain as ' . $iWidth . 'x' . $iHeight . ' instead of ' . $iMaxImageWidth . 'x' . $iMaxImageHeight); - return $oImage; - } - - - switch($oImage->GetMimeType()) - { - case 'image/gif': - case 'image/jpeg': - case 'image/png': - $img = @imagecreatefromstring($oImage->GetData()); - break; - - default: - // Unsupported image type, return the image as-is - //throw new Exception("Unsupported image type: '".$oImage->GetMimeType()."'. Cannot resize the image, original image will be used."); - return $oImage; - } - if ($img === false) - { - //throw new Exception("Warning: corrupted image: '".$oImage->GetFileName()." / ".$oImage->GetMimeType()."'. Cannot resize the image, original image will be used."); - return $oImage; - } - else - { - // Let's scale the image, preserving the transparency for GIFs and PNGs - - $fScale = min($iMaxImageWidth / $iWidth, $iMaxImageHeight / $iHeight); - - $iNewWidth = $iWidth * $fScale; - $iNewHeight = $iHeight * $fScale; - - $new = imagecreatetruecolor($iNewWidth, $iNewHeight); - - // Preserve transparency - if(($oImage->GetMimeType() == "image/gif") || ($oImage->GetMimeType() == "image/png")) - { - imagecolortransparent($new, imagecolorallocatealpha($new, 0, 0, 0, 127)); - imagealphablending($new, false); - imagesavealpha($new, true); - } - - imagecopyresampled($new, $img, 0, 0, 0, 0, $iNewWidth, $iNewHeight, $iWidth, $iHeight); - - ob_start(); - switch ($oImage->GetMimeType()) - { - case 'image/gif': - imagegif($new); // send image to output buffer - break; - - case 'image/jpeg': - imagejpeg($new, null, 80); // null = send image to output buffer, 80 = good quality - break; - - case 'image/png': - imagepng($new, null, 5); // null = send image to output buffer, 5 = medium compression - break; - } - $oResampledImage = new ormDocument(ob_get_contents(), $oImage->GetMimeType(), $oImage->GetFileName()); - @ob_end_clean(); - - imagedestroy($img); - imagedestroy($new); - - return $oResampledImage; - } - + return $oImage->ResizeImageToFit($iMaxImageWidth, $iMaxImageHeight); } /** diff --git a/core/inlineimage.class.inc.php b/core/inlineimage.class.inc.php index bc59cb7ddd..6d99363d9c 100644 --- a/core/inlineimage.class.inc.php +++ b/core/inlineimage.class.inc.php @@ -407,86 +407,12 @@ public static function IsImage($sMimeType) * Resize an image so that it fits the maximum width/height defined in the config file * @param ormDocument $oImage The original image stored as an array (content / mimetype / filename) * @return ormDocument The resampled image (or the original one if it already fit) + * @deprecated Replaced by ormDocument::ResizeImageToFit */ public static function ResizeImageToFit(ormDocument $oImage, &$aDimensions = null) { - $img = false; - switch($oImage->GetMimeType()) - { - case 'image/gif': - case 'image/jpeg': - case 'image/png': - $img = @imagecreatefromstring($oImage->GetData()); - break; - - default: - // Unsupported image type, return the image as-is - $aDimensions = null; - return $oImage; - } - if ($img === false) - { - $aDimensions = null; - return $oImage; - } - else - { - // Let's scale the image, preserving the transparency for GIFs and PNGs - $iWidth = imagesx($img); - $iHeight = imagesy($img); - $aDimensions = array('width' => $iWidth, 'height' => $iHeight); - $iMaxImageSize = (int)MetaModel::GetConfig()->Get('inline_image_max_storage_width', 0); - - if (($iMaxImageSize > 0) && ($iWidth <= $iMaxImageSize) && ($iHeight <= $iMaxImageSize)) - { - // No need to resize - return $oImage; - } - - $fScale = min($iMaxImageSize / $iWidth, $iMaxImageSize / $iHeight); - - $iNewWidth = (int) ($iWidth * $fScale); - $iNewHeight = (int) ($iHeight * $fScale); - - $aDimensions['width'] = $iNewWidth; - $aDimensions['height'] = $iNewHeight; - - $new = imagecreatetruecolor($iNewWidth, $iNewHeight); - - // Preserve transparency - if(($oImage->GetMimeType() == "image/gif") || ($oImage->GetMimeType() == "image/png")) - { - imagecolortransparent($new, imagecolorallocatealpha($new, 0, 0, 0, 127)); - imagealphablending($new, false); - imagesavealpha($new, true); - } - - imagecopyresampled($new, $img, 0, 0, 0, 0, $iNewWidth, $iNewHeight, $iWidth, $iHeight); - - ob_start(); - switch ($oImage->GetMimeType()) - { - case 'image/gif': - imagegif($new); // send image to output buffer - break; - - case 'image/jpeg': - imagejpeg($new, null, 80); // null = send image to output buffer, 80 = good quality - break; - - case 'image/png': - imagepng($new, null, 5); // null = send image to output buffer, 5 = medium compression - break; - } - $oNewImage = new ormDocument(ob_get_contents(), $oImage->GetMimeType(), $oImage->GetFileName()); - @ob_end_clean(); - - imagedestroy($img); - imagedestroy($new); - - return $oNewImage; - } - + $iMaxImageSize = (int)MetaModel::GetConfig()->Get('inline_image_max_storage_width', 0); + return $oImage->ResizeImageToFit($iMaxImageSize, $iMaxImageSize, $aDimensions); } /** diff --git a/core/ormdocument.class.inc.php b/core/ormdocument.class.inc.php index 27af2d9704..cefd205224 100644 --- a/core/ormdocument.class.inc.php +++ b/core/ormdocument.class.inc.php @@ -405,6 +405,89 @@ public static function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, } } + /** + * Resize an image so that it fits in the given dimensions + * @param int $iMaxImageWidth Maximum width for the resized image + * @param int $iMaxImageHeight Maximum height for the resized image + * @param array|null $aFinalDimensions Image dimensions after resizing or null if unable to read the image + * @return ormDocument The resampled image + * + */ + public function ResizeImageToFit(int $iMawWidth, int $iMaxHeight, array|null &$aFinalDimensions = null) : static + { + $aFinalDimensions = null; + // If gd extension is not loaded, we put a warning in the log and return the image as is + if (extension_loaded('gd') === false) { + IssueLog::Warning('Image could not be resized as the "gd" extension does not seem to be loaded. Its dimensions will remain the same instead of ' . $iMawWidth . 'x' . $iMaxHeight); + return $this; + } + $oGdImage = false; + switch($this->GetMimeType()) { + case 'image/gif': + case 'image/jpeg': + case 'image/png': + $oGdImage = @imagecreatefromstring($this->GetData()); + break; + default: + // Unsupported image type, return the image as-is + return $this; + } + + if ($oGdImage === false) { + IssueLog::Warning('Image could not be resized as . It will remain as imagecreatefromstring could not read its data.Its dimensions will remain the same instead of ' . $iMawWidth . 'x' . $iMaxHeight); + return $this; + } + + $iWidth = imagesx($oGdImage); + $iHeight = imagesy($oGdImage); + + if ( ($iMawWidth === 0 || $iWidth <= $iMawWidth) && ($iMaxHeight === 0 || $iHeight <= $iMaxHeight)) { + // No need to resize + $aFinalDimensions = [ + 'width' => $iWidth, + 'height' =>$iHeight + ]; + return $this; + } + + $fScale = min($iMawWidth / $iWidth, $iMaxHeight / $iHeight); + $iNewWidth = $iWidth * $fScale; + $iNewHeight = $iHeight * $fScale; + + $oNewGdImage = imagecreatetruecolor($iNewWidth, $iNewHeight); + + // Preserve transparency + if($this->GetMimeType() == "image/gif" || $this->GetMimeType() == "image/png") { + imagecolortransparent($oNewGdImage, imagecolorallocatealpha($new, 0, 0, 0, 127)); + imagealphablending($new, false); + imagesavealpha($new, true); + } + imagecopyresampled($oNewGdImage, $oGdImage, 0, 0, 0, 0, $iNewWidth, $iNewHeight, $iWidth, $iHeight); + + ob_start(); + switch ($this->GetMimeType()) { + case 'image/gif': + imagegif($oNewGdImage); // send image to output buffer + break; + + case 'image/jpeg': + imagejpeg($oNewGdImage, null, 80); // null = send image to output buffer, 80 = good quality + break; + + case 'image/png': + imagepng($oNewGdImage, null, 5); // null = send image to output buffer, 5 = medium compression + break; + } + $oResampledImage = new ormDocument(ob_get_contents(), $this->GetMimeType(), $this->GetFileName()); + @ob_end_clean(); + + imagedestroy($oGdImage); + imagedestroy($oNewGdImage); + + return $oResampledImage; + + } + /** * @return string */ @@ -412,4 +495,6 @@ public function GetSignature(): string { return md5($this->GetData() ?? ''); } + + } diff --git a/datamodels/2.x/itop-portal-base/portal/src/Controller/UserProfileBrickController.php b/datamodels/2.x/itop-portal-base/portal/src/Controller/UserProfileBrickController.php index 32f9c21840..6dcd59c788 100644 --- a/datamodels/2.x/itop-portal-base/portal/src/Controller/UserProfileBrickController.php +++ b/datamodels/2.x/itop-portal-base/portal/src/Controller/UserProfileBrickController.php @@ -433,9 +433,10 @@ public function HandlePictureForm(Request $oRequest) $oCurContact = UserRights::GetContactObject(); // Resizing image $oAttDef = MetaModel::GetAttributeDef(get_class($oCurContact), $sPictureAttCode); - $aSize = utils::GetImageSize($oImage->GetData()); - $oImage = utils::ResizeImageToFit($oImage, $aSize[0], $aSize[1], $oAttDef->Get('storage_max_width'), - $oAttDef->Get('storage_max_height')); + $oImage = $oImage->ResizeImageToFit( + $oAttDef->Get('storage_max_width'), + $oAttDef->Get('storage_max_height') + ); // Setting it to the contact $oCurContact->Set($sPictureAttCode, $oImage); // Forcing allowed writing on the object if necessary. diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 457232f010..3ffa14d81d 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -2002,7 +2002,8 @@ function(data){ $oDoc = utils::ReadPostedDocument('upload'); if (InlineImage::IsImage($oDoc->GetMimeType())) { $aDimensions = null; - $oDoc = InlineImage::ResizeImageToFit($oDoc, $aDimensions); + $iMaxImageSize = (int)MetaModel::GetConfig()->Get('inline_image_max_storage_width', 0); + $oDoc = $oDoc->ResizeImageToFit($iMaxImageSize, $iMaxImageSize, $aDimensions); /** @var InlineImage $oAttachment */ $oAttachment = MetaModel::NewObject('InlineImage'); $oAttachment->Set('expire', time() + MetaModel::GetConfig()->Get('draft_attachments_lifetime')); @@ -2059,7 +2060,8 @@ function(data){ )); } else { $aDimensions = null; - $oDoc = InlineImage::ResizeImageToFit($oDoc, $aDimensions); + $iMaxImageSize = (int)MetaModel::GetConfig()->Get('inline_image_max_storage_width', 0); + $oDoc = $oDoc->ResizeImageToFit($iMaxImageSize, $iMaxImageSize, $aDimensions); /** @var InlineImage $oAttachment */ $oAttachment = MetaModel::NewObject('InlineImage'); $oAttachment->Set('expire', time() + MetaModel::GetConfig()->Get('draft_attachments_lifetime')); From 8e64277cf4d09bbddaf0bcbda0917aa71d4819b9 Mon Sep 17 00:00:00 2001 From: Timothee Date: Wed, 6 Aug 2025 17:40:55 +0200 Subject: [PATCH 2/5] =?UTF-8?q?N=C2=B03124=20-=20Refactorize=20ResizeImage?= =?UTF-8?q?ToFit=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/ormdocument.class.inc.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/core/ormdocument.class.inc.php b/core/ormdocument.class.inc.php index cefd205224..d339e55abc 100644 --- a/core/ormdocument.class.inc.php +++ b/core/ormdocument.class.inc.php @@ -451,16 +451,22 @@ public function ResizeImageToFit(int $iMawWidth, int $iMaxHeight, array|null &$a } $fScale = min($iMawWidth / $iWidth, $iMaxHeight / $iHeight); - $iNewWidth = $iWidth * $fScale; - $iNewHeight = $iHeight * $fScale; + $iNewWidth = (int)($iWidth * $fScale); + $iNewHeight = (int)($iHeight * $fScale); $oNewGdImage = imagecreatetruecolor($iNewWidth, $iNewHeight); + + $aFinalDimensions = [ + 'width' => $iNewWidth, + 'height' =>$iNewHeight + ]; + // Preserve transparency if($this->GetMimeType() == "image/gif" || $this->GetMimeType() == "image/png") { - imagecolortransparent($oNewGdImage, imagecolorallocatealpha($new, 0, 0, 0, 127)); - imagealphablending($new, false); - imagesavealpha($new, true); + imagecolortransparent($oNewGdImage, imagecolorallocatealpha($oNewGdImage, 0, 0, 0, 127)); + imagealphablending($oNewGdImage, false); + imagesavealpha($oNewGdImage, true); } imagecopyresampled($oNewGdImage, $oGdImage, 0, 0, 0, 0, $iNewWidth, $iNewHeight, $iWidth, $iHeight); From b975fc86fe39c53d796dcb1d8465157b30073417 Mon Sep 17 00:00:00 2001 From: Timothee Date: Thu, 7 Aug 2025 16:18:12 +0200 Subject: [PATCH 3/5] =?UTF-8?q?N=C2=B03124=20-=20Refactorize=20ResizeImage?= =?UTF-8?q?ToFit=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unitary-tests/core/ormDocumentTest.php | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/php-unit-tests/unitary-tests/core/ormDocumentTest.php b/tests/php-unit-tests/unitary-tests/core/ormDocumentTest.php index 9d2c82319e..9c9834228c 100644 --- a/tests/php-unit-tests/unitary-tests/core/ormDocumentTest.php +++ b/tests/php-unit-tests/unitary-tests/core/ormDocumentTest.php @@ -139,4 +139,84 @@ public function EqualsExceptDownloadsCountProvider(): array ], ]; } + + + + public function testResizeImageToFitShouldResizeImageWhenImageIsTooBig() + { + $sImageData = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAIAAABPmPnhAAAAe0lEQVQI132OMQoCMRRE3/9Z3M126V0kB9BCvICnziXs7QIWlttqpWMRFQT1VcMbGMb4xPoQ18uWL4eTxxglSaq1Au8OwM1TSi3nnLGnzxKA4fM8N1VKQVyPZ6Br6s4Xhj7st9OwcNy61yUsGEK3Nmu+mUawcbfiN85fHsBoHdXt5HATAAAAAElFTkSuQmCC'); + $sMimeType = 'image/png'; + $sFileName = 'MyImage.png'; + $oDoc = new ormDocument($sImageData, $sMimeType, $sFileName); + $iMawWidth = 6; + $iMaxHeight = 5; + + $oResult = $oDoc->ResizeImageToFit($iMawWidth, $iMaxHeight, $aDimensions); + + $this->assertNotSame( $oDoc, $oResult, 'ResizeImageToFit should return a new object when there have been some modifications'); + $this->assertIsArray( $aDimensions, 'ResizeImageToFit should fill aDimension with the dimensions of the new image when there are no issues'); + $this->assertEquals( $aDimensions, $this->getImageDimensions($oResult), 'The returned dimensions should match the real dimensions of the image'); + $this->assertLessThanOrEqual($iMawWidth, $aDimensions['width'], 'The new width should be less than or equal to max width'); + $this->assertLessThanOrEqual($iMaxHeight, $aDimensions['height'], 'The new height should be less than or equal to max height'); + } + + public function testResizeImageToFitShouldDoNothingWhenImageIsAlreadySmallEnough() + { + $sImageData = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAIAAABPmPnhAAAAe0lEQVQI132OMQoCMRRE3/9Z3M126V0kB9BCvICnziXs7QIWlttqpWMRFQT1VcMbGMb4xPoQ18uWL4eTxxglSaq1Au8OwM1TSi3nnLGnzxKA4fM8N1VKQVyPZ6Br6s4Xhj7st9OwcNy61yUsGEK3Nmu+mUawcbfiN85fHsBoHdXt5HATAAAAAElFTkSuQmCC'); + $sMimeType = 'image/png'; + $sFileName = 'MyImage.png'; + $oDoc = new ormDocument($sImageData, $sMimeType, $sFileName); + $iMawWidth = 10; + $iMaxHeight = 8; + + $oResult = $oDoc->ResizeImageToFit($iMawWidth, $iMaxHeight, $aDimensions); + + $this->assertSame( $oDoc, $oResult, 'ResizeImageToFit should return the same object when there have been no modifications'); + $this->assertIsArray( $aDimensions, 'ResizeImageToFit should fill aDimension with the dimensions of the image when there are no issues'); + } + + public function testResizeImageToFitShouldDoNothingWhenItCannotReadTheImage() + { + $sImageData = 'garbagedata'; + $sMimeType = 'image/png'; + $sFileName = 'MyImage.png'; + $oDoc = new ormDocument($sImageData, $sMimeType, $sFileName); + $iMawWidth = 10; + $iMaxHeight = 8; + + $oResult = $oDoc->ResizeImageToFit($iMawWidth, $iMaxHeight, $aDimensions); + + $this->assertSame( $oDoc, $oResult, 'ResizeImageToFit should return the same object when there have been no modifications'); + $this->assertNull( $aDimensions, 'ResizeImageToFit should fill aDimension with null when there are issues'); + } + + public function testResizeImageToFitShouldDoNothingWhenItDoesNotHandleTheMimeType() + { + $sImageData = base64_decode('Qk3mAAAAAAAAAEYAAAA4AAAACgAAAAgAAAABABAAAwAAAKAAAAAjLgAAIy4AAAAAAAAAAAAAAHwAAOADAAAfAAAAAAAAAMQExATEBMQExATEBMQExATEBMQExATEBMQExATEBMQExATEBMQExAQAAAAAAAAAAAAAAAAgBMQgxATEBAAAAAAAAAAAAAAAACAExCAgBAAAIQT/f/9/1loAACAAxATEGMQEAABjDP9//3//fwAAxATEBMQUxAQAACEE/3//f3tvAADEBMQExATEBAAAAAAAAAAAAAAAACAAxATEBMQEAAA='); + $sMimeType = 'image/bmp'; + $sFileName = 'MyImage.bmp'; + $oDoc = new ormDocument($sImageData, $sMimeType, $sFileName); + $iMawWidth = 5; + $iMaxHeight = 5; + + $oResult = $oDoc->ResizeImageToFit($iMawWidth, $iMaxHeight, $aDimensions); + + $this->assertSame( $oDoc, $oResult, 'ResizeImageToFit should return the same object when there have been no modifications'); + $this->assertNull( $aDimensions, 'ResizeImageToFit should fill aDimension with null when there are issues'); + } + + public function getImageDimensions($oOrmDocument) + { + $oGdImage = @imagecreatefromstring($oOrmDocument->GetData()); + if ($oGdImage === false) { + return null; + } + $iWidth = imagesx($oGdImage); + $iHeight = imagesy($oGdImage); + return [ + 'width' => $iWidth, + 'height' => $iHeight + ]; + } + } From 8594f6682e9b658b595594a7cd9cdf241cc2a336 Mon Sep 17 00:00:00 2001 From: Timothee Date: Thu, 7 Aug 2025 17:15:50 +0200 Subject: [PATCH 4/5] =?UTF-8?q?N=C2=B03124=20-=20Remove=20utils::ResizeIma?= =?UTF-8?q?geToFit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/utils.inc.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/application/utils.inc.php b/application/utils.inc.php index 5d7c84b8fd..5e9d8fb3a3 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -2315,22 +2315,6 @@ public static function GetImageSize($sImageData) return @getimagesizefromstring($sImageData); } - /** - * Resize an image attachment so that it fits in the given dimensions - * @param ormDocument $oImage The original image stored as an ormDocument - * @param int $iWidth Image's original width - * @param int $iHeight Image's original height - * @param int $iMaxImageWidth Maximum width for the resized image - * @param int $iMaxImageHeight Maximum height for the resized image - * @return ormDocument The resampled image - * - * @deprecated Replaced by ormDocument::ResizeImageToFit - */ - public static function ResizeImageToFit(ormDocument $oImage, $iWidth, $iHeight, $iMaxImageWidth, $iMaxImageHeight) - { - return $oImage->ResizeImageToFit($iMaxImageWidth, $iMaxImageHeight); - } - /** * Create a 128 bit UUID in the format: {########-####-####-####-############} * From a58b16466061e57325dfd5c498d750f024d1d7a8 Mon Sep 17 00:00:00 2001 From: Timothee Date: Fri, 8 Aug 2025 10:39:57 +0200 Subject: [PATCH 5/5] =?UTF-8?q?N=C2=B03124=20-=20Refactorize=20ResizeImage?= =?UTF-8?q?ToFit=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/ormdocument.class.inc.php | 16 ++++-- .../unitary-tests/core/ormDocumentTest.php | 57 ++++++++++++++----- 2 files changed, 55 insertions(+), 18 deletions(-) diff --git a/core/ormdocument.class.inc.php b/core/ormdocument.class.inc.php index d339e55abc..45a5730966 100644 --- a/core/ormdocument.class.inc.php +++ b/core/ormdocument.class.inc.php @@ -413,12 +413,12 @@ public static function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, * @return ormDocument The resampled image * */ - public function ResizeImageToFit(int $iMawWidth, int $iMaxHeight, array|null &$aFinalDimensions = null) : static + public function ResizeImageToFit(int $iMaxWidth, int $iMaxHeight, array|null &$aFinalDimensions = null) : static { $aFinalDimensions = null; // If gd extension is not loaded, we put a warning in the log and return the image as is if (extension_loaded('gd') === false) { - IssueLog::Warning('Image could not be resized as the "gd" extension does not seem to be loaded. Its dimensions will remain the same instead of ' . $iMawWidth . 'x' . $iMaxHeight); + IssueLog::Warning('Image could not be resized as the "gd" extension does not seem to be loaded. Its dimensions will remain the same instead of ' . $iMaxWidth . 'x' . $iMaxHeight); return $this; } $oGdImage = false; @@ -434,14 +434,14 @@ public function ResizeImageToFit(int $iMawWidth, int $iMaxHeight, array|null &$a } if ($oGdImage === false) { - IssueLog::Warning('Image could not be resized as . It will remain as imagecreatefromstring could not read its data.Its dimensions will remain the same instead of ' . $iMawWidth . 'x' . $iMaxHeight); + IssueLog::Warning('Image could not be resized as . It will remain as imagecreatefromstring could not read its data.Its dimensions will remain the same instead of ' . $iMaxWidth . 'x' . $iMaxHeight); return $this; } $iWidth = imagesx($oGdImage); $iHeight = imagesy($oGdImage); - if ( ($iMawWidth === 0 || $iWidth <= $iMawWidth) && ($iMaxHeight === 0 || $iHeight <= $iMaxHeight)) { + if ( ($iMaxWidth === 0 || $iWidth <= $iMaxWidth) && ($iMaxHeight === 0 || $iHeight <= $iMaxHeight)) { // No need to resize $aFinalDimensions = [ 'width' => $iWidth, @@ -450,7 +450,13 @@ public function ResizeImageToFit(int $iMawWidth, int $iMaxHeight, array|null &$a return $this; } - $fScale = min($iMawWidth / $iWidth, $iMaxHeight / $iHeight); + $fScale = 1.0; + if ($iMaxWidth > 0) { + $fScale = min($fScale, $iMaxWidth / $iWidth); + } + if ($iMaxHeight > 0) { + $fScale = min($fScale, $iMaxHeight / $iHeight); + } $iNewWidth = (int)($iWidth * $fScale); $iNewHeight = (int)($iHeight * $fScale); diff --git a/tests/php-unit-tests/unitary-tests/core/ormDocumentTest.php b/tests/php-unit-tests/unitary-tests/core/ormDocumentTest.php index 9c9834228c..b6a33d4f0f 100644 --- a/tests/php-unit-tests/unitary-tests/core/ormDocumentTest.php +++ b/tests/php-unit-tests/unitary-tests/core/ormDocumentTest.php @@ -153,11 +153,17 @@ public function testResizeImageToFitShouldResizeImageWhenImageIsTooBig() $oResult = $oDoc->ResizeImageToFit($iMawWidth, $iMaxHeight, $aDimensions); + $aRealDimensions = \utils::GetImageSize($oResult->GetData()); + $aActualDimensions = [ + 'width' => $aRealDimensions[0], + 'height' => $aRealDimensions[1], + ]; + $this->assertNotSame( $oDoc, $oResult, 'ResizeImageToFit should return a new object when there have been some modifications'); $this->assertIsArray( $aDimensions, 'ResizeImageToFit should fill aDimension with the dimensions of the new image when there are no issues'); - $this->assertEquals( $aDimensions, $this->getImageDimensions($oResult), 'The returned dimensions should match the real dimensions of the image'); - $this->assertLessThanOrEqual($iMawWidth, $aDimensions['width'], 'The new width should be less than or equal to max width'); - $this->assertLessThanOrEqual($iMaxHeight, $aDimensions['height'], 'The new height should be less than or equal to max height'); + $this->assertEquals( $aDimensions, $aActualDimensions, 'The returned dimensions should match the real dimensions of the image'); + $this->assertLessThanOrEqual($iMawWidth, $aActualDimensions['width'], 'The new width should be less than or equal to max width'); + $this->assertLessThanOrEqual($iMaxHeight, $aActualDimensions['height'], 'The new height should be less than or equal to max height'); } public function testResizeImageToFitShouldDoNothingWhenImageIsAlreadySmallEnough() @@ -205,18 +211,43 @@ public function testResizeImageToFitShouldDoNothingWhenItDoesNotHandleTheMimeTyp $this->assertNull( $aDimensions, 'ResizeImageToFit should fill aDimension with null when there are issues'); } - public function getImageDimensions($oOrmDocument) + public function testResizeImageToFitShouldNotResizeWhenMaximumIs0() { - $oGdImage = @imagecreatefromstring($oOrmDocument->GetData()); - if ($oGdImage === false) { - return null; - } - $iWidth = imagesx($oGdImage); - $iHeight = imagesy($oGdImage); - return [ - 'width' => $iWidth, - 'height' => $iHeight + $sImageData = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAIAAABPmPnhAAAAe0lEQVQI132OMQoCMRRE3/9Z3M126V0kB9BCvICnziXs7QIWlttqpWMRFQT1VcMbGMb4xPoQ18uWL4eTxxglSaq1Au8OwM1TSi3nnLGnzxKA4fM8N1VKQVyPZ6Br6s4Xhj7st9OwcNy61yUsGEK3Nmu+mUawcbfiN85fHsBoHdXt5HATAAAAAElFTkSuQmCC'); + $sMimeType = 'image/png'; + $sFileName = 'MyImage.png'; + $oDoc = new ormDocument($sImageData, $sMimeType, $sFileName); + $iMawWidth = 0; + $iMaxHeight = 0; + + $oResult = $oDoc->ResizeImageToFit($iMawWidth, $iMaxHeight, $aDimensions); + + $this->assertSame( $oDoc, $oResult, 'ResizeImageToFit should return the same object when there have been no modifications'); + $this->assertIsArray( $aDimensions, 'ResizeImageToFit should fill aDimension with the dimensions of the image when there are no issues'); + } + + public function testResizeImageToFitShouldIgnoreMaximum0Axis() + { + $sImageData = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAIAAABPmPnhAAAAe0lEQVQI132OMQoCMRRE3/9Z3M126V0kB9BCvICnziXs7QIWlttqpWMRFQT1VcMbGMb4xPoQ18uWL4eTxxglSaq1Au8OwM1TSi3nnLGnzxKA4fM8N1VKQVyPZ6Br6s4Xhj7st9OwcNy61yUsGEK3Nmu+mUawcbfiN85fHsBoHdXt5HATAAAAAElFTkSuQmCC'); + $sMimeType = 'image/png'; + $sFileName = 'MyImage.png'; + $oDoc = new ormDocument($sImageData, $sMimeType, $sFileName); + $iMawWidth = 5; + $iMaxHeight = 0; + + $oResult = $oDoc->ResizeImageToFit($iMawWidth, $iMaxHeight, $aDimensions); + + $aRealDimensions = \utils::GetImageSize($oResult->GetData()); + $aActualDimensions = [ + 'width' => $aRealDimensions[0], + 'height' => $aRealDimensions[1], ]; + + $this->assertNotSame( $oDoc, $oResult, 'ResizeImageToFit should return a new object when there have been some modifications'); + $this->assertIsArray( $aDimensions, 'ResizeImageToFit should fill aDimension with the dimensions of the new image when there are no issues'); + $this->assertEquals( $aDimensions, $aActualDimensions, 'The returned dimensions should match the real dimensions of the image'); + $this->assertEquals($iMawWidth, $aActualDimensions['width'], 'The new width should be exactly the max width'); + $this->assertGreaterThanOrEqual($iMaxHeight, $aActualDimensions['height'], 'The new height should not be 0'); } }