Pdf::getImageData()   A
last analyzed

Complexity

Conditions 5
Paths 12

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 32
rs 9.0968
cc 5
nc 12
nop 1
1
<?php
2
3
namespace Spatie\PdfToImage;
4
5
use Imagick;
6
use Spatie\PdfToImage\Exceptions\InvalidFormat;
7
use Spatie\PdfToImage\Exceptions\PageDoesNotExist;
8
use Spatie\PdfToImage\Exceptions\PdfDoesNotExist;
9
10
class Pdf
11
{
12
    protected $pdfFile;
13
14
    protected $resolution = 144;
15
16
    protected $outputFormat = 'jpg';
17
18
    protected $page = 1;
19
20
    public $imagick;
21
22
    protected $numberOfPages;
23
24
    protected $validOutputFormats = ['jpg', 'jpeg', 'png'];
25
26
    protected $layerMethod = Imagick::LAYERMETHOD_FLATTEN;
27
28
    protected $colorspace;
29
30
    protected $compressionQuality;
31
32
    public function __construct(string $pdfFile)
33
    {
34
        if (! file_exists($pdfFile)) {
35
            throw new PdfDoesNotExist("File `{$pdfFile}` does not exist");
36
        }
37
38
        $this->imagick = new Imagick();
39
40
        $this->imagick->pingImage($pdfFile);
41
42
        $this->numberOfPages = $this->imagick->getNumberImages();
43
44
        $this->pdfFile = $pdfFile;
45
    }
46
47
    public function setResolution(int $resolution)
48
    {
49
        $this->resolution = $resolution;
50
51
        return $this;
52
    }
53
54
    public function setOutputFormat(string $outputFormat)
55
    {
56
        if (! $this->isValidOutputFormat($outputFormat)) {
57
            throw new InvalidFormat("Format {$outputFormat} is not supported");
58
        }
59
60
        $this->outputFormat = $outputFormat;
61
62
        return $this;
63
    }
64
65
    public function getOutputFormat(): string
66
    {
67
        return $this->outputFormat;
68
    }
69
70
    /**
71
     * Sets the layer method for Imagick::mergeImageLayers()
72
     * If int, should correspond to a predefined LAYERMETHOD constant.
73
     * If null, Imagick::mergeImageLayers() will not be called.
74
     *
75
     * @param int|null
76
     *
77
     * @return $this
78
     *
79
     * @throws \Spatie\PdfToImage\Exceptions\InvalidLayerMethod
80
     *
81
     * @see https://secure.php.net/manual/en/imagick.constants.php
82
     * @see Pdf::getImageData()
83
     */
84
    public function setLayerMethod(?int $layerMethod)
85
    {
86
        $this->layerMethod = $layerMethod;
87
88
        return $this;
89
    }
90
91
    public function isValidOutputFormat(string $outputFormat): bool
92
    {
93
        return in_array($outputFormat, $this->validOutputFormats);
94
    }
95
96
    public function setPage(int $page)
97
    {
98
        if ($page > $this->getNumberOfPages() || $page < 1) {
99
            throw new PageDoesNotExist("Page {$page} does not exist");
100
        }
101
102
        $this->page = $page;
103
104
        return $this;
105
    }
106
107
    public function getNumberOfPages(): int
108
    {
109
        return $this->numberOfPages;
110
    }
111
112
    public function saveImage(string $pathToImage): bool
113
    {
114
        if (is_dir($pathToImage)) {
115
            $pathToImage = rtrim($pathToImage, '\/').DIRECTORY_SEPARATOR.$this->page.'.'.$this->outputFormat;
116
        }
117
118
        $imageData = $this->getImageData($pathToImage);
119
120
        return file_put_contents($pathToImage, $imageData) !== false;
121
    }
122
123
    public function saveAllPagesAsImages(string $directory, string $prefix = ''): array
124
    {
125
        $numberOfPages = $this->getNumberOfPages();
126
127
        if ($numberOfPages === 0) {
128
            return [];
129
        }
130
131
        return array_map(function ($pageNumber) use ($directory, $prefix) {
132
            $this->setPage($pageNumber);
133
134
            $destination = "{$directory}/{$prefix}{$pageNumber}.{$this->outputFormat}";
135
136
            $this->saveImage($destination);
137
138
            return $destination;
139
        }, range(1, $numberOfPages));
140
    }
141
142
    public function getImageData(string $pathToImage): Imagick
143
    {
144
        /*
145
         * Reinitialize imagick because the target resolution must be set
146
         * before reading the actual image.
147
         */
148
        $this->imagick = new Imagick();
149
150
        $this->imagick->setResolution($this->resolution, $this->resolution);
151
152
        if ($this->colorspace !== null) {
153
            $this->imagick->setColorspace($this->colorspace);
154
        }
155
156
        if ($this->compressionQuality !== null) {
157
            $this->imagick->setCompressionQuality($this->compressionQuality);
158
        }
159
160
        if (filter_var($this->pdfFile, FILTER_VALIDATE_URL)) {
161
            return $this->getRemoteImageData($pathToImage);
162
        }
163
164
        $this->imagick->readImage(sprintf('%s[%s]', $this->pdfFile, $this->page - 1));
165
166
        if (is_int($this->layerMethod)) {
167
            $this->imagick = $this->imagick->mergeImageLayers($this->layerMethod);
168
        }
169
170
        $this->imagick->setFormat($this->determineOutputFormat($pathToImage));
171
172
        return $this->imagick;
173
    }
174
175
    public function setColorspace(int $colorspace)
176
    {
177
        $this->colorspace = $colorspace;
178
179
        return $this;
180
    }
181
182
    public function setCompressionQuality(int $compressionQuality)
183
    {
184
        $this->compressionQuality = $compressionQuality;
185
186
        return $this;
187
    }
188
189
    protected function getRemoteImageData(string $pathToImage): Imagick
190
    {
191
        $this->imagick->readImage($this->pdfFile);
192
193
        $this->imagick->setIteratorIndex($this->page - 1);
194
195
        if (is_int($this->layerMethod)) {
196
            $this->imagick = $this->imagick->mergeImageLayers($this->layerMethod);
197
        }
198
199
        $this->imagick->setFormat($this->determineOutputFormat($pathToImage));
200
201
        return $this->imagick;
202
    }
203
204
    protected function determineOutputFormat(string $pathToImage): string
205
    {
206
        $outputFormat = pathinfo($pathToImage, PATHINFO_EXTENSION);
207
208
        if ($this->outputFormat != '') {
209
            $outputFormat = $this->outputFormat;
210
        }
211
212
        $outputFormat = strtolower($outputFormat);
213
214
        if (! $this->isValidOutputFormat($outputFormat)) {
215
            $outputFormat = 'jpg';
216
        }
217
218
        return $outputFormat;
219
    }
220
}
221