Skip to content

Commit a7dcc5c

Browse files
committed
fix(blurhash): Use preview API to generate the previews
This allows to benefit from all the checks done by the preview API. This also use the newly introduced `cacheResult` argument to limit disk usage. Signed-off-by: Louis Chemineau <louis@chmn.me>
1 parent f7315ef commit a7dcc5c

4 files changed

Lines changed: 22 additions & 74 deletions

File tree

build/psalm-baseline.xml

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2455,24 +2455,9 @@
24552455
</InvalidReturnStatement>
24562456
</file>
24572457
<file src="lib/private/Preview/Generator.php">
2458-
<InvalidArgument>
2459-
<code><![CDATA[$maxPreviewImage]]></code>
2460-
</InvalidArgument>
24612458
<LessSpecificReturnType>
24622459
<code><![CDATA[null|string]]></code>
24632460
</LessSpecificReturnType>
2464-
<MismatchingDocblockParamType>
2465-
<code><![CDATA[ISimpleFile]]></code>
2466-
</MismatchingDocblockParamType>
2467-
<UndefinedInterfaceMethod>
2468-
<code><![CDATA[height]]></code>
2469-
<code><![CDATA[height]]></code>
2470-
<code><![CDATA[preciseResizeCopy]]></code>
2471-
<code><![CDATA[resizeCopy]]></code>
2472-
<code><![CDATA[valid]]></code>
2473-
<code><![CDATA[width]]></code>
2474-
<code><![CDATA[width]]></code>
2475-
</UndefinedInterfaceMethod>
24762461
</file>
24772462
<file src="lib/private/Preview/ProviderV1Adapter.php">
24782463
<InvalidReturnStatement>

lib/private/Blurhash/Listener/GenerateBlurhashMetadata.php

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use OCP\FilesMetadata\AMetadataEvent;
2020
use OCP\FilesMetadata\Event\MetadataBackgroundEvent;
2121
use OCP\FilesMetadata\Event\MetadataLiveEvent;
22+
use OCP\IPreview;
2223
use OCP\Lock\LockedException;
2324

2425
/**
@@ -27,11 +28,14 @@
2728
* @template-implements IEventListener<AMetadataEvent>
2829
*/
2930
class GenerateBlurhashMetadata implements IEventListener {
30-
private const RESIZE_BOXSIZE = 30;
31-
3231
private const COMPONENTS_X = 4;
3332
private const COMPONENTS_Y = 3;
3433

34+
public function __construct(
35+
private IPreview $preview,
36+
) {
37+
}
38+
3539
/**
3640
* @throws NotPermittedException
3741
* @throws GenericFileException
@@ -64,7 +68,9 @@ public function handle(Event $event): void {
6468
return;
6569
}
6670

67-
$image = $this->resizedImageFromFile($file);
71+
$preview = $this->preview->getPreview($file, 64, 64, cacheResult: false);
72+
$image = @imagecreatefromstring($preview->getContent());
73+
6874
if (!$image) {
6975
return;
7076
}
@@ -73,35 +79,6 @@ public function handle(Event $event): void {
7379
->setEtag('blurhash', $currentEtag);
7480
}
7581

76-
/**
77-
* @param File $file
78-
*
79-
* @return GdImage|false
80-
* @throws GenericFileException
81-
* @throws NotPermittedException
82-
* @throws LockedException
83-
*/
84-
private function resizedImageFromFile(File $file): GdImage|false {
85-
$image = @imagecreatefromstring($file->getContent());
86-
if ($image === false) {
87-
return false;
88-
}
89-
90-
$currX = imagesx($image);
91-
$currY = imagesy($image);
92-
93-
if ($currX > $currY) {
94-
$newX = self::RESIZE_BOXSIZE;
95-
$newY = intval($currY * $newX / $currX);
96-
} else {
97-
$newY = self::RESIZE_BOXSIZE;
98-
$newX = intval($currX * $newY / $currY);
99-
}
100-
101-
$newImage = @imagescale($image, $newX, $newY);
102-
return ($newImage !== false) ? $newImage : $image;
103-
}
104-
10582
/**
10683
* @param GdImage $image
10784
*

lib/private/Preview/Generator.php

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public function generatePreviews(File $file, array $specifications, ?string $mim
166166
$maxPreviewImage = $this->helper->getImage($maxPreview);
167167
}
168168

169-
$preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion);
169+
$preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion, $cacheResult);
170170
// New file, augment our array
171171
$previewFiles[] = $preview;
172172
}
@@ -345,11 +345,10 @@ private function generateProviderPreview(ISimpleFolder $previewFolder, File $fil
345345

346346
$path = $this->generatePath($preview->width(), $preview->height(), $crop, $max, $preview->dataMimeType(), $prefix);
347347
try {
348-
$file = $previewFolder->newFile($path);
349348
if ($preview instanceof IStreamImage) {
350-
$file->putContent($preview->resource());
349+
return $previewFolder->newFile($path, $preview->resource());
351350
} else {
352-
$file->putContent($preview->data());
351+
return $previewFolder->newFile($path, $preview->data());
353352
}
354353
} catch (NotPermittedException $e) {
355354
throw new NotFoundException();
@@ -535,14 +534,13 @@ private function generatePreview(
535534
$path = $this->generatePath($width, $height, $crop, false, $preview->dataMimeType(), $prefix);
536535
try {
537536
if ($cacheResult) {
538-
$file = $previewFolder->newFile($path, $preview->data());
537+
return $previewFolder->newFile($path, $preview->data());
539538
} else {
540539
return new InMemoryFile($path, $preview->data());
541540
}
542541
} catch (NotPermittedException $e) {
543542
throw new NotFoundException();
544543
}
545-
546544
return $file;
547545
}
548546

tests/lib/Preview/GeneratorTest.php

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,19 @@
2121
use OCP\Preview\IProviderV2;
2222

2323
class GeneratorTest extends \Test\TestCase {
24-
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
24+
/** @var IConfig&\PHPUnit\Framework\MockObject\MockObject */
2525
private $config;
2626

27-
/** @var IPreview|\PHPUnit\Framework\MockObject\MockObject */
27+
/** @var IPreview&\PHPUnit\Framework\MockObject\MockObject */
2828
private $previewManager;
2929

30-
/** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */
30+
/** @var IAppData&\PHPUnit\Framework\MockObject\MockObject */
3131
private $appData;
3232

33-
/** @var GeneratorHelper|\PHPUnit\Framework\MockObject\MockObject */
33+
/** @var GeneratorHelper&\PHPUnit\Framework\MockObject\MockObject */
3434
private $helper;
3535

36-
/** @var IEventDispatcher|\PHPUnit\Framework\MockObject\MockObject */
36+
/** @var IEventDispatcher&\PHPUnit\Framework\MockObject\MockObject */
3737
private $eventDispatcher;
3838

3939
/** @var Generator */
@@ -191,18 +191,10 @@ public function testGetNewPreview() {
191191
$previewFolder->method('getDirectoryListing')
192192
->willReturn([]);
193193
$previewFolder->method('newFile')
194-
->willReturnCallback(function ($filename) use ($maxPreview, $previewFile) {
195-
if ($filename === '2048-2048-max.png') {
196-
return $maxPreview;
197-
} elseif ($filename === '256-256.png') {
198-
return $previewFile;
199-
}
200-
$this->fail('Unexpected file');
201-
});
202-
203-
$maxPreview->expects($this->once())
204-
->method('putContent')
205-
->with($this->equalTo('my data'));
194+
->willReturnMap([
195+
['2048-2048-max.png', 'my data', $maxPreview],
196+
['256-256.png', 'my resized data', $previewFile],
197+
]);
206198

207199
$previewFolder->method('getFile')
208200
->with($this->equalTo('256-256.png'))
@@ -213,10 +205,6 @@ public function testGetNewPreview() {
213205
->with($this->equalTo($maxPreview))
214206
->willReturn($image);
215207

216-
$previewFile->expects($this->once())
217-
->method('putContent')
218-
->with('my resized data');
219-
220208
$this->eventDispatcher->expects($this->once())
221209
->method('dispatchTyped')
222210
->with(new BeforePreviewFetchedEvent($file, 100, 100, false, IPreview::MODE_FILL));

0 commit comments

Comments
 (0)