|
|
|
@ -59,7 +59,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
// Default quality for webp images
|
|
|
|
|
protected const DEFAULT_WEBP_QUALITY = 80;
|
|
|
|
|
|
|
|
|
|
/** @var false|resource|\GdImage */
|
|
|
|
|
/** @var false|\GdImage */
|
|
|
|
|
protected $resource = false; // tmp resource.
|
|
|
|
|
/** @var int */
|
|
|
|
|
protected $imageType = IMAGETYPE_PNG; // Default to png if file type isn't evident.
|
|
|
|
@ -67,20 +67,20 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
protected $mimeType = 'image/png'; // Default to png
|
|
|
|
|
/** @var null|string */
|
|
|
|
|
protected $filePath = null;
|
|
|
|
|
/** @var finfo */
|
|
|
|
|
private $fileInfo;
|
|
|
|
|
/** @var ?finfo */
|
|
|
|
|
private $fileInfo = null;
|
|
|
|
|
/** @var \OCP\ILogger */
|
|
|
|
|
private $logger;
|
|
|
|
|
/** @var \OCP\IConfig */
|
|
|
|
|
private $config;
|
|
|
|
|
/** @var array */
|
|
|
|
|
private $exif;
|
|
|
|
|
/** @var ?array */
|
|
|
|
|
private $exif = null;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Constructor.
|
|
|
|
|
*
|
|
|
|
|
* @param resource|string|\GdImage $imageRef The path to a local file, a base64 encoded string or a resource created by
|
|
|
|
|
* an imagecreate* function.
|
|
|
|
|
* @param mixed $imageRef Deprecated, should be null
|
|
|
|
|
* @psalm-assert null $imageRef
|
|
|
|
|
* @param \OCP\ILogger $logger
|
|
|
|
|
* @param \OCP\IConfig $config
|
|
|
|
|
* @throws \InvalidArgumentException in case the $imageRef parameter is not null
|
|
|
|
@ -107,11 +107,11 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
/**
|
|
|
|
|
* Determine whether the object contains an image resource.
|
|
|
|
|
*
|
|
|
|
|
* @psalm-assert-if-true \GdImage $this->resource
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
public function valid(): bool {
|
|
|
|
|
if ((is_resource($this->resource) && get_resource_type($this->resource) === 'gd') ||
|
|
|
|
|
(is_object($this->resource) && get_class($this->resource) === \GdImage::class)) {
|
|
|
|
|
if (is_object($this->resource) && get_class($this->resource) === \GdImage::class) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -134,10 +134,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
*/
|
|
|
|
|
public function width(): int {
|
|
|
|
|
if ($this->valid()) {
|
|
|
|
|
$width = imagesx($this->resource);
|
|
|
|
|
if ($width !== false) {
|
|
|
|
|
return $width;
|
|
|
|
|
}
|
|
|
|
|
return imagesx($this->resource);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
@ -149,10 +146,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
*/
|
|
|
|
|
public function height(): int {
|
|
|
|
|
if ($this->valid()) {
|
|
|
|
|
$height = imagesy($this->resource);
|
|
|
|
|
if ($height !== false) {
|
|
|
|
|
return $height;
|
|
|
|
|
}
|
|
|
|
|
return imagesy($this->resource);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
@ -338,25 +332,14 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param resource|\GdImage $resource
|
|
|
|
|
* @throws \InvalidArgumentException in case the supplied resource does not have the type "gd"
|
|
|
|
|
* @param \GdImage $resource
|
|
|
|
|
*/
|
|
|
|
|
public function setResource($resource) {
|
|
|
|
|
// For PHP<8
|
|
|
|
|
if (is_resource($resource) && get_resource_type($resource) === 'gd') {
|
|
|
|
|
$this->resource = $resource;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// PHP 8 has real objects for GD stuff
|
|
|
|
|
if (is_object($resource) && get_class($resource) === \GdImage::class) {
|
|
|
|
|
$this->resource = $resource;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
throw new \InvalidArgumentException('Supplied resource is not of type "gd".');
|
|
|
|
|
public function setResource(\GdImage $resource): void {
|
|
|
|
|
$this->resource = $resource;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return false|resource|\GdImage Returns the image resource if any
|
|
|
|
|
* @return false|\GdImage Returns the image resource if any
|
|
|
|
|
*/
|
|
|
|
|
public function resource() {
|
|
|
|
|
return $this->resource;
|
|
|
|
@ -394,8 +377,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
$res = imagepng($this->resource);
|
|
|
|
|
break;
|
|
|
|
|
case "image/jpeg":
|
|
|
|
|
/** @psalm-suppress InvalidScalarArgument */
|
|
|
|
|
imageinterlace($this->resource, (PHP_VERSION_ID >= 80000 ? true : 1));
|
|
|
|
|
imageinterlace($this->resource, true);
|
|
|
|
|
$quality = $this->getJpegQuality();
|
|
|
|
|
$res = imagejpeg($this->resource, null, $quality);
|
|
|
|
|
break;
|
|
|
|
@ -584,7 +566,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
* It is the responsibility of the caller to position the pointer at the correct place and to close the handle again.
|
|
|
|
|
*
|
|
|
|
|
* @param resource $handle
|
|
|
|
|
* @return resource|\GdImage|false An image resource or false on error
|
|
|
|
|
* @return \GdImage|false An image resource or false on error
|
|
|
|
|
*/
|
|
|
|
|
public function loadFromFileHandle($handle) {
|
|
|
|
|
$contents = stream_get_contents($handle);
|
|
|
|
@ -663,7 +645,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
* Loads an image from a local file.
|
|
|
|
|
*
|
|
|
|
|
* @param bool|string $imagePath The path to a local file.
|
|
|
|
|
* @return bool|resource|\GdImage An image resource or false on error
|
|
|
|
|
* @return bool|\GdImage An image resource or false on error
|
|
|
|
|
*/
|
|
|
|
|
public function loadFromFile($imagePath = false) {
|
|
|
|
|
// exif_imagetype throws "read error!" if file is less than 12 byte
|
|
|
|
@ -801,7 +783,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
* Loads an image from a string of data.
|
|
|
|
|
*
|
|
|
|
|
* @param string $str A string of image data as read from a file.
|
|
|
|
|
* @return bool|resource|\GdImage An image resource or false on error
|
|
|
|
|
* @return bool|\GdImage An image resource or false on error
|
|
|
|
|
*/
|
|
|
|
|
public function loadFromData(string $str) {
|
|
|
|
|
if (!$this->checkImageDataSize($str)) {
|
|
|
|
@ -827,7 +809,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
* Loads an image from a base64 encoded string.
|
|
|
|
|
*
|
|
|
|
|
* @param string $str A string base64 encoded string of image data.
|
|
|
|
|
* @return bool|resource|\GdImage An image resource or false on error
|
|
|
|
|
* @return bool|\GdImage An image resource or false on error
|
|
|
|
|
*/
|
|
|
|
|
public function loadFromBase64(string $str) {
|
|
|
|
|
$data = base64_decode($str);
|
|
|
|
@ -868,7 +850,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param $maxSize
|
|
|
|
|
* @return resource|bool|\GdImage
|
|
|
|
|
* @return bool|\GdImage
|
|
|
|
|
*/
|
|
|
|
|
private function resizeNew(int $maxSize) {
|
|
|
|
|
if (!$this->valid()) {
|
|
|
|
@ -909,7 +891,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
/**
|
|
|
|
|
* @param int $width
|
|
|
|
|
* @param int $height
|
|
|
|
|
* @return resource|bool|\GdImage
|
|
|
|
|
* @return bool|\GdImage
|
|
|
|
|
*/
|
|
|
|
|
public function preciseResizeNew(int $width, int $height) {
|
|
|
|
|
if (!($width > 0) || !($height > 0)) {
|
|
|
|
@ -985,13 +967,13 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
|
|
|
|
|
// preserve transparency
|
|
|
|
|
if ($this->imageType == IMAGETYPE_GIF or $this->imageType == IMAGETYPE_PNG) {
|
|
|
|
|
imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127));
|
|
|
|
|
imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127) ?: null);
|
|
|
|
|
imagealphablending($process, false);
|
|
|
|
|
imagesavealpha($process, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $targetWidth, $targetHeight, $width, $height);
|
|
|
|
|
if ($process === false) {
|
|
|
|
|
$result = imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $targetWidth, $targetHeight, $width, $height);
|
|
|
|
|
if ($result === false) {
|
|
|
|
|
$this->logger->debug('OC_Image->centerCrop, Error re-sampling process image ' . $width . 'x' . $height, ['app' => 'core']);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -1027,7 +1009,7 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
* @param int $y Vertical position
|
|
|
|
|
* @param int $w Width
|
|
|
|
|
* @param int $h Height
|
|
|
|
|
* @return resource|\GdImage|false
|
|
|
|
|
* @return \GdImage|false
|
|
|
|
|
*/
|
|
|
|
|
public function cropNew(int $x, int $y, int $w, int $h) {
|
|
|
|
|
if (!$this->valid()) {
|
|
|
|
@ -1042,13 +1024,13 @@ class OC_Image implements \OCP\IImage {
|
|
|
|
|
|
|
|
|
|
// preserve transparency
|
|
|
|
|
if ($this->imageType == IMAGETYPE_GIF or $this->imageType == IMAGETYPE_PNG) {
|
|
|
|
|
imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127));
|
|
|
|
|
imagecolortransparent($process, imagecolorallocatealpha($process, 0, 0, 0, 127) ?: null);
|
|
|
|
|
imagealphablending($process, false);
|
|
|
|
|
imagesavealpha($process, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $w, $h, $w, $h);
|
|
|
|
|
if ($process === false) {
|
|
|
|
|
$result = imagecopyresampled($process, $this->resource, 0, 0, $x, $y, $w, $h, $w, $h);
|
|
|
|
|
if ($result === false) {
|
|
|
|
|
$this->logger->debug(__METHOD__ . '(): Error re-sampling process image ' . $w . 'x' . $h, ['app' => 'core']);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|