diff --git a/src/Model/Photo.php b/src/Model/Photo.php index 213551b11..f9940f51e 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -346,11 +346,14 @@ class Photo * @param string $url Image URL * @param int $uid User ID of the requesting person * @param string $mimetype Image mime type. Is guessed by file name when empty. + * @param string $blurhash The blurhash that will be used to generate a picture when the original picture can't be fetched + * @param int $width Image width + * @param int $height Image height * * @return array * @throws \Exception */ - public static function createPhotoForExternalResource(string $url, int $uid = 0, string $mimetype = ''): array + public static function createPhotoForExternalResource(string $url, int $uid = 0, string $mimetype = '', string $blurhash = null, int $width = null, int $height = null): array { if (empty($mimetype)) { $mimetype = Images::guessTypeByExtension($url); @@ -364,6 +367,9 @@ class Photo $photo['backend-ref'] = json_encode(['url' => $url, 'uid' => $uid]); $photo['type'] = $mimetype; $photo['cacheable'] = true; + $photo['blurhash'] = $blurhash; + $photo['width'] = $width; + $photo['height'] = $height; return $photo; } diff --git a/src/Module/Photo.php b/src/Module/Photo.php index 1847b4f70..a4ef6ab41 100644 --- a/src/Module/Photo.php +++ b/src/Module/Photo.php @@ -153,8 +153,12 @@ class Photo extends BaseModule $stamp = microtime(true); $imgdata = MPhoto::getImageDataForPhoto($photo); - if (empty($imgdata)) { + if (empty($imgdata) && empty($photo['blurhash'])) { throw new HTTPException\NotFoundException(); + } elseif (empty($imgdata) && !empty($photo['blurhash'])) { + $image = New Image('', 'image/png'); + $image->getFromBlurHash($photo['blurhash'], $photo['width'], $photo['height']); + $imgdata = $image->asString(); } // The mimetype for an external or system resource can only be known reliably after it had been fetched @@ -240,14 +244,18 @@ class Photo extends BaseModule { switch($type) { case 'preview': - $media = DBA::selectFirst('post-media', ['preview', 'url', 'mimetype', 'type', 'uri-id'], ['id' => $id]); + $media = DBA::selectFirst('post-media', ['preview', 'url', 'preview-height', 'preview-width', 'height', 'width', 'mimetype', 'type', 'uri-id', 'blurhash'], ['id' => $id]); if (empty($media)) { return false; } - $url = $media['preview']; + $url = $media['preview']; + $width = $media['preview-width']; + $height = $media['preview-height']; if (empty($url) && ($media['type'] == Post\Media::IMAGE)) { - $url = $media['url']; + $url = $media['url']; + $width = $media['width']; + $height = $media['height']; } if (empty($url)) { @@ -258,9 +266,9 @@ class Photo extends BaseModule return MPhoto::getPhoto($matches[1], $matches[2]); } - return MPhoto::createPhotoForExternalResource($url, (int)DI::userSession()->getLocalUserId(), $media['mimetype'] ?? ''); + return MPhoto::createPhotoForExternalResource($url, (int)DI::userSession()->getLocalUserId(), $media['mimetype'] ?? '', $media['blurhash'], $width, $height); case 'media': - $media = DBA::selectFirst('post-media', ['url', 'mimetype', 'uri-id'], ['id' => $id, 'type' => Post\Media::IMAGE]); + $media = DBA::selectFirst('post-media', ['url', 'height', 'width', 'mimetype', 'uri-id', 'blurhash'], ['id' => $id, 'type' => Post\Media::IMAGE]); if (empty($media)) { return false; } @@ -269,7 +277,7 @@ class Photo extends BaseModule return MPhoto::getPhoto($matches[1], $matches[2]); } - return MPhoto::createPhotoForExternalResource($media['url'], (int)DI::userSession()->getLocalUserId(), $media['mimetype']); + return MPhoto::createPhotoForExternalResource($media['url'], (int)DI::userSession()->getLocalUserId(), $media['mimetype'], $media['blurhash'], $media['width'], $media['height']); case 'link': $link = DBA::selectFirst('post-link', ['url', 'mimetype'], ['id' => $id]); if (empty($link)) { diff --git a/src/Object/Image.php b/src/Object/Image.php index c2cfa9e2f..87401304d 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -780,13 +780,21 @@ class Image return; } - $pixels = Blurhash::decode($blurhash, $width, $height); - $this->image = imagecreatetruecolor($width, $height); - for ($y = 0; $y < $height; ++$y) { - for ($x = 0; $x < $width; ++$x) { + $scaled = Images::getScalingDimensions($width, $height, 90); + $pixels = Blurhash::decode($blurhash, $scaled['width'], $scaled['height']); + + $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]; imagesetpixel($this->image, $x, $y, imagecolorallocate($this->image, $r, $g, $b)); } } + + $this->width = imagesx($this->image); + $this->height = imagesy($this->image); + $this->valid = true; + + $this->scaleUp(min($width, $height)); } }