]> git.mxchange.org Git - friendica.git/blobdiff - src/Object/Image.php
Merge pull request #12390 from annando/fixes
[friendica.git] / src / Object / Image.php
index 866ac268fab4d95d0a0f905ef46a86ad9ca0eb13..06498f963fcb859b78d4d96c5381824ddd6b0794 100644 (file)
@@ -25,14 +25,17 @@ use Exception;
 use Friendica\DI;
 use Friendica\Util\Images;
 use Imagick;
+use ImagickDraw;
 use ImagickPixel;
+use GDImage;
+use kornrunner\Blurhash\Blurhash;
 
 /**
  * Class to handle images
  */
 class Image
 {
-       /** @var Imagick|resource */
+       /** @var GDImage|Imagick|resource */
        private $image;
 
        /*
@@ -62,7 +65,7 @@ class Image
                }
                $this->type = $type;
 
-               if ($this->isImagick() && $this->loadData($data)) {
+               if ($this->isImagick() && (empty($data) || $this->loadData($data))) {
                        return;
                } else {
                        // Failed to load with Imagick, fallback
@@ -695,14 +698,13 @@ class Image
                        try {
                                /* Clean it */
                                $this->image = $this->image->deconstructImages();
-                               $string = $this->image->getImagesBlob();
-                               return $string;
+                               return $this->image->getImagesBlob();
                        } catch (Exception $e) {
                                return false;
                        }
                }
 
-               ob_start();
+               $stream = fopen('php://memory','r+');
 
                // Enable interlacing
                imageinterlace($this->image, true);
@@ -710,18 +712,110 @@ class Image
                switch ($this->getType()) {
                        case 'image/png':
                                $quality = DI::config()->get('system', 'png_quality');
-                               imagepng($this->image, null, $quality);
+                               imagepng($this->image, $stream, $quality);
                                break;
 
                        case 'image/jpeg':
                        case 'image/jpg':
                                $quality = DI::config()->get('system', 'jpeg_quality');
-                               imagejpeg($this->image, null, $quality);
+                               imagejpeg($this->image, $stream, $quality);
                                break;
                }
-               $string = ob_get_contents();
-               ob_end_clean();
+               rewind($stream);
+               return stream_get_contents($stream);
+       }
+
+       /**
+        * Create a blurhash out of a given image string
+        *
+        * @param string $img_str
+        * @return string
+        */
+       public function getBlurHash(): string
+       {
+               $image = New Image($this->asString());
+               if (empty($image)) {
+                       return '';
+               }
+
+               $width = $image->getWidth();
+               $height = $image->getHeight();
+
+               if (max($width, $height) > 90) {
+                       $image->scaleDown(90);
+                       $width = $image->getWidth();
+                       $height = $image->getHeight();
+               }
+
+               $pixels = [];
+               for ($y = 0; $y < $height; ++$y) {
+                       $row = [];
+                       for ($x = 0; $x < $width; ++$x) {
+                               if ($image->isImagick()) {
+                                       try {
+                                               $colors = $image->image->getImagePixelColor($x, $y)->getColor();
+                                       } catch (\Throwable $th) {
+                                               return '';
+                                       }
+                                       $row[] = [$colors['r'], $colors['g'], $colors['b']];
+                               } else {
+                                       $index = imagecolorat($image->image, $x, $y);
+                                       $colors = @imagecolorsforindex($image->image, $index);
+                                       $row[] = [$colors['red'], $colors['green'], $colors['blue']];
+                               }
+                       }
+                       $pixels[] = $row;
+               }
+
+               // The components define the amount of details (1 to 9).
+               $components_x = 9;
+               $components_y = 9;
+
+               return Blurhash::encode($pixels, $components_x, $components_y);
+       }
+
+       /**
+        * Create an image out of a blurhash
+        *
+        * @param string $blurhash
+        * @param integer $width
+        * @param integer $height
+        * @return void
+        */
+       public function getFromBlurHash(string $blurhash, int $width, int $height)
+       {
+               $scaled = Images::getScalingDimensions($width, $height, 90);
+               $pixels = Blurhash::decode($blurhash, $scaled['width'], $scaled['height']);
+
+               if ($this->isImagick()) {
+                       $this->image = new Imagick();
+                       $draw  = new ImagickDraw();
+                       $this->image->newImage($scaled['width'], $scaled['height'], '', 'png');
+               } else {
+                       $this->image = imagecreatetruecolor($scaled['width'], $scaled['height']);
+               }
+
+               for ($y = 0; $y < $scaled['height']; ++$y) {
+                       for ($x = 0; $x < $scaled['width']; ++$x) {
+                               [$r, $g, $b] = $pixels[$y][$x];
+                               if ($this->isImagick()) {
+                                       $draw->setFillColor("rgb($r, $g, $b)");
+                                       $draw->point($x, $y);
+                               } else {
+                                       imagesetpixel($this->image, $x, $y, imagecolorallocate($this->image, $r, $g, $b));
+                               }
+                       }
+               }
+
+               if ($this->isImagick()) {
+                       $this->image->drawImage($draw);
+               } else {
+                       $this->width  = imagesx($this->image);
+                       $this->height = imagesy($this->image);
+               }
+
+               $this->valid = true;
 
-               return $string;
+               $this->scaleUp(min($width, $height));
        }
 }