Skip to content

Commit

Permalink
Fix PR comments
Browse files Browse the repository at this point in the history
  • Loading branch information
tobias-93 committed Feb 13, 2024
1 parent ca14a91 commit 2e8d9eb
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 23 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![StyleCI](https://styleci.io/repos/38419604/shield?branch=master)](https://styleci.io/repos/38419604)
[![Total Downloads](https://img.shields.io/packagist/dt/spatie/pdf-to-image.svg?style=flat-square)](https://packagist.org/packages/spatie/pdf-to-image)

This package provides an easy to work with class to convert PDF's to images.
This package provides an easy to work with class to convert PDF's to images. It is based on the [`spatie/pdf-to-image`](https://github.com/spatie/pdf-to-image) library, which relied on Imagick for the conversion. This library relies on GD instead.

## Requirements

Expand Down Expand Up @@ -50,7 +50,7 @@ $pdf->setOutputFormat(ExportFormatEnum::PNG)
->saveImage($pathToWhereImageShouldBeStored); //the output wil be a png, no matter what
```

You can set the quality of compression. This depends on the export format, see the GD documentation for more info:
You can set the quality of compression (this depends on the export format, see the GD documentation for more details):
```php
$pdf->setCompressionQuality(100); // sets the compression quality to maximum
```
Expand Down
20 changes: 16 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,26 @@
{
"name": "Freek Van der Herten",
"email": "[email protected]",
"homepage": "https://spatie.be",
"role": "Developer"
"homepage": "https://spatie.be"
},
{
"name": "Tobias Feijten",
"email": "[email protected]",
"homepage": "https://drenso.nl"
},
{
"name": "Bob van de Vijver",
"email": "[email protected]",
"homepage": "https://drenso.nl"
}
],
"require": {
"php" : "^8.2",
"php": ">=8.2",
"ext-gd": "*",
"ext-random": "*"
"ext-random": "*",
"symfony/filesystem": "^5.4 || ^6.4 || ^7.0",
"symfony/finder": "^5.4 || ^6.4 || ^7.0",
"symfony/process": "^5.4 || ^6.4 || ^7.0"
},
"require-dev": {
"pestphp/pest": "^1.21"
Expand Down
48 changes: 36 additions & 12 deletions src/Pdf.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,26 @@
use Drenso\PdfToImage\Exceptions\PdfDoesNotExist;
use GdImage;
use Random\Engine\Secure;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\Process;

class Pdf
{
protected string $cacheDir;
protected ?string $cacheDir = null;
protected ?int $width = null;
protected ?ExportFormatEnum $outputFormat = null;
protected int $page = 1;
protected int $compressionQuality = -1;
private ?int $numberOfPages = null;
private Filesystem $filesystem;

public function __construct(private readonly string $pdfFile, protected readonly int $resolution = 144)
{
if (! file_exists($pdfFile)) {
$this->filesystem = new Filesystem();
if (! $this->filesystem->exists($pdfFile)) {
throw new PdfDoesNotExist("File `{$pdfFile}` does not exist");
}

// Convert to PNG files, so GD can be used for the following processing
$this->cacheDir = '/tmp/pdftoimage/' . bin2hex((new Secure())->generate());
@mkdir($this->cacheDir, recursive: true);
exec(sprintf('gs -dSAFER -dBATCH -sDEVICE=png16m -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -r%s -sOutputFile=%s %s', $this->resolution, $this->cacheDir . '/%03d.png', $this->pdfFile));
}

public function setWidth(int $width): self
Expand Down Expand Up @@ -61,8 +61,8 @@ public function setPage(int $page): self
public function getNumberOfPages(): int
{
if ($this->numberOfPages === null) {
$files = scandir($this->cacheDir);
$this->numberOfPages = count(array_filter($files, fn (string $filename) => str_ends_with($filename, '.png')));
$this->prepareImages();
$this->numberOfPages = (new Finder())->in($this->cacheDir)->name('*.png')->count();
}

return $this->numberOfPages;
Expand All @@ -88,7 +88,7 @@ public function saveAllPagesAsImages(string $directory, string $prefix = ''): ar

return array_map(function ($pageNumber) use ($directory, $prefix) {
$this->setPage($pageNumber);
$destination = "{$directory}/{$prefix}{$pageNumber}.{$this->outputFormat}";
$destination = "{$directory}".DIRECTORY_SEPARATOR."{$prefix}{$pageNumber}.{$this->outputFormat}";
$this->saveImage($destination);

return $destination;
Expand All @@ -97,8 +97,9 @@ public function saveAllPagesAsImages(string $directory, string $prefix = ''): ar

public function getImageData(string $pathToImage): GdImage
{
$this->prepareImages();
$this->outputFormat ??= ExportFormatEnum::fromFileName($pathToImage);
$pageName = $this->cacheDir . sprintf('/%03d.png', $this->page);
$pageName = $this->cacheDir . DIRECTORY_SEPARATOR . sprintf('%03d.png', $this->page);
$originalImage = imagecreatefrompng($pageName);

if ($this->width === null) {
Expand All @@ -111,7 +112,7 @@ public function getImageData(string $pathToImage): GdImage
return $originalImage;
}
// Calculate scaled height
$newHeight = $imageSize[1] * ($this->width / $imageSize[0]);
$newHeight = round((float)$imageSize[1] * ($this->width / $imageSize[0]));
// Resize in new image
$resizedImage = imagecreatetruecolor($this->width, $newHeight);
imagecopyresampled($resizedImage, $originalImage, 0, 0, 0, 0, $this->width, $newHeight, $imageSize[0], $imageSize[1]);
Expand All @@ -125,4 +126,27 @@ public function setCompressionQuality(int $compressionQuality): self

return $this;
}

public function prepareImages(): void
{
if ($this->cacheDir) {
return;
}

// Convert to PNG files, so GD can be used for the following processing
$this->cacheDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'pdftoimage' . DIRECTORY_SEPARATOR . bin2hex((new Secure())->generate());
$this->filesystem->mkdir($this->cacheDir);
(new Process([
'gs',
'-dSAFER',
'-dBATCH',
'-dNOPAUSE',
'-sDEVICE=png16m',
'-dTextAlphaBits=4',
'-dGraphicsAlphaBits=4',
'-r' . $this->resolution,
'-sOutputFile=' . $this->cacheDir . DIRECTORY_SEPARATOR . '%03d.png',
$this->pdfFile])
)->mustRun();
}
}
12 changes: 7 additions & 5 deletions tests/PdfTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@


it('will throw an exception when try to convert a non existing file', function () {
new Pdf('pdfdoesnotexists.pdf');
new Pdf('pdfdoesnotexist.pdf');
})->throws(PdfDoesNotExist::class);

it('will throw an exception when passed an invalid page number', function ($invalidPage) {
it('will throw an exception when passed an invalid page number', function () {
(new Pdf($this->testFile))->setPage(100);
})
->throws(PageDoesNotExist::class)
Expand All @@ -31,8 +31,9 @@
$image = (new Pdf($this->testFile, resolution: 150))
->getImageData('test.jpg');

expect(imageresolution($image)[0])->toEqual(150)
->and(imageresolution($image)[1])->toEqual(150);
$resolution = imageresolution($image);
expect($resolution[0])->toEqual(150)
->and($resolution[1])->toEqual(150);
});

it('will convert a specified page', function () {
Expand All @@ -48,5 +49,6 @@
->setWidth(400)
->getImageData('test.jpg');

expect(imagesx($image))->toBe(400);
expect(imagesx($image))->toBe(400)
->and(imagesy($image))->toBe(283); // round(210*400/297)
});

0 comments on commit 2e8d9eb

Please sign in to comment.