originalFile = $originalFile; if (!$originalFile) { return; } $requestedWidth = floatval($requestedWidth); $requestedHeight = floatval($requestedHeight); ini_set('memory_limit', '-1'); $getimagesize = @getimagesize($originalFile); if (!$getimagesize) { return; } $this->originalWidth = $getimagesize[0]; $this->originalHeight = $getimagesize[1]; $this->requestedWidth = $requestedWidth ? $requestedWidth : $this->originalWidth; $this->requestedHeight = $requestedHeight ? $requestedHeight : $this->originalHeight; $this->type = $getimagesize['mime']; $this->crop = $crop; // Get the possible size for the generated image (based on crop and original size). $this->calculateSize(); // Get the filename hash, based on the given settings, to check later, if the file exists. $this->file = $this->getImageCacheFilePath(); $this->fileFullPath = AM_BASE_DIR . $this->file; // Check if an image with the generated hash exists already and create the file, when neccassary. $this->verifyCachedImage(); } /** * Calculate the size and pixels to crop for the generated image. */ private function calculateSize(): void { if (!$this->originalWidth || !$this->originalHeight || !$this->requestedWidth || !$this->requestedHeight) { return; } $originalAspect = $this->originalWidth / $this->originalHeight; $requestedAspect = $this->requestedWidth / $this->requestedHeight; if ($this->crop) { // Crop image if ($originalAspect > $requestedAspect) { if ($this->requestedWidth < $this->originalWidth) { $w = $this->requestedWidth; } else { $w = $this->originalWidth; } $h = $w / $requestedAspect; if ($h > $this->originalHeight) { $h = $this->originalHeight; $requestedAspect = $w / $h; } // crop X $x = ($this->originalWidth - ($this->originalHeight * $requestedAspect)) / 2; $y = 0; } else { if ($this->requestedHeight < $this->originalHeight) { $h = $this->requestedHeight; } else { $h = $this->originalHeight; } $w = $h * $requestedAspect; if ($w > $this->originalWidth) { $w = $this->originalWidth; $requestedAspect = $w / $h; } // crop X $x = 0; $y = ($this->originalHeight - ($this->originalWidth / $requestedAspect)) / 2; } } else { // No cropping $x = 0; $y = 0; if ($originalAspect > $requestedAspect) { if ($this->requestedWidth < $this->originalWidth) { $w = $this->requestedWidth; } else { $w = $this->originalWidth; } $h = $w / $originalAspect; } else { if ($this->requestedHeight < $this->originalHeight) { $h = $this->requestedHeight; } else { $h = $this->originalHeight; } $w = $h * $originalAspect; } } $this->width = (int) round($w); $this->height = (int) round($h); $this->cropX = (int) round($x); $this->cropY = (int) round($y); } /** * Create a new (resized and cropped) image from the source image and save that image in the cache directory. */ private function createImage(): void { switch ($this->type) { case 'image/jpeg': $src = imagecreatefromjpeg($this->originalFile); break; case 'image/gif': $src = imagecreatefromgif($this->originalFile); break; case 'image/png': $src = imagecreatefrompng($this->originalFile); break; case 'image/webp': $src = imagecreatefromwebp($this->originalFile); break; default: $src = false; break; } if (!$src) { return; } $dest = imagecreatetruecolor($this->width, $this->height); imagealphablending($dest, false); imagesavealpha($dest, true); imagecopyresampled( $dest, $src, 0, 0, $this->cropX, $this->cropY, $this->width, $this->height, (int) round($this->originalWidth - (2 * $this->cropX)), (int) round($this->originalHeight - (2 * $this->cropY)) ); Debug::log($this, 'Saving "' . $this->fileFullPath . '"'); // Create cache directory, if not existing. FileSystem::makeDir(AM_BASE_DIR . Cache::DIR_IMAGES); switch ($this->type) { case 'image/jpeg': imagejpeg($dest, $this->fileFullPath, AM_IMG_JPG_QUALITY); break; case 'image/gif': imagegif($dest, $this->fileFullPath); break; case 'image/png': imagepng($dest, $this->fileFullPath); break; case 'image/webp': imagewebp($dest, $this->fileFullPath); break; } chmod($this->fileFullPath, AM_PERM_FILE); } /** * Determine the corresponding image file to a source file based on a md5 hash. * That hash is based on the source image's path, mtime, the new width and height and the cropping parameter. * If one parameter changes, the hash will be different, which will result in recreating an image. * Since the mtime is part of the hash, also any modification to the source image will be reflected in a different name. * For each size and cropping setting, a unique filename will be returned, to clearly identify that setting. * * @return string The matching filename for the requested source image, based on its parameters */ private function getImageCacheFilePath(): string { $extension = strtolower(pathinfo($this->originalFile, PATHINFO_EXTENSION)); if ($extension == 'jpeg') { $extension = 'jpg'; } // Create unique filename in the cache folder: // The hash makes it possible to clearly identify an unchanged file in the cache, // since the given hashData will always result in the same hash. // So if a file gets requested, the hash is generated from the path, calculated width x height, the mtime from the original and the cropping setting. $hashData = $this->originalFile . '-' . $this->width . 'x' . $this->height . '-' . filemtime($this->originalFile) . '-' . var_export($this->crop, true); $hash = sha1($hashData); $file = Cache::DIR_IMAGES . '/' . $hash . '.' . $extension; Debug::log($hashData, 'Hash data for ' . $hash); return $file; } /** * To verify, if the requested image is up to date, only the existence has to be tested, * since any changes in the source image will be reflected in the filename's hash. */ private function verifyCachedImage(): void { if (!file_exists($this->fileFullPath)) { $this->createImage(); } } } __halt_compiler();----SIGNATURE:----OyJi4J1W7PPWYxXvKNDIxGlcb9EPb39/WGGNfkPDDC1qW36A7EII0vDVwzf37rVgv0aqWz6opt/2ksppa/6LlXex7mruJUvQP7PgfxZVaFOCoIVPsMyMu/S4OSV0E6T2juY2oVjEUfBppODjrI6A5pIrgHyWjKB4FmX2PA5PectA+9dX6B+4k2UcUrKTJGPxAheFP7KUf0QyyLqhUMdfI9Q4H741jRpvR0k/DpBZa5tlJF1/dBnWbMHDTdx4o/jDPqXpDUdC++07A47c4pfL3tbneMaQfyc9wV3VxBUTsn25Seks1eb6NxIJqsZLzCK+O8+ofwPGcDsqqqlT7WeauEEg8aEdu+oP5Cmc2GUUJmDb+AeVM9So9FDN7DrOewPV9deUUlSgyASYEcQouJUqqo5e+1q4FWYX0SW5mS/1ouN9vKVWreviaQRAv1N7XdJmzv41c9Guw3IfFxiPBQ6tAIdQllcuwIODphk7ILJ1oz4O/SvyalfOuRs3j80ZWAI05gAxr5cYLby1N4M3E0RrROqMNAYSjFbOTGYDycOw8Jfm1DPT7JNE5i8LdDRoxhTELRj7voBy2RB4Wsojrxg+kiuDNRFthUTCjWwSp7JPxrqfg1bmI5C4XydIrkjuStCuHYwljL/AZ3Av22sZnd0qbLlvxjVBV/nNOje1Wsqc+uI=----ATTACHMENT:----NTQ1MDQyMTkyMTk1MTE2NSA5NDY5NzM5ODM2MTA2Mzc2IDQwODY0MTgwMTI2NDcxNDM=