Completed
Push — master ( 5f1ced...8f0440 )
by Freek
01:25
created

Pdf::getOutputFormat()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Spatie\PdfToImage;
4
5
use Imagick;
6
use Spatie\PdfToImage\Exceptions\InvalidFormat;
7
use Spatie\PdfToImage\Exceptions\PdfDoesNotExist;
8
use Spatie\PdfToImage\Exceptions\PageDoesNotExist;
9
use Spatie\PdfToImage\Exceptions\InvalidLayerMethod;
10
11
class Pdf
12
{
13
    protected $pdfFile;
14
15
    protected $resolution = 144;
16
17
    protected $outputFormat = 'jpg';
18
19
    protected $page = 1;
20
21
    public $imagick;
22
23
    protected $numberOfPages;
24
25
    protected $validOutputFormats = ['jpg', 'jpeg', 'png'];
26
27
    protected $layerMethod = Imagick::LAYERMETHOD_FLATTEN;
28
29
    protected $colorspace;
30
31
    protected $compressionQuality;
32
33
    /**
34
     * @param string $pdfFile The path or url to the pdffile.
35
     *
36
     * @throws \Spatie\PdfToImage\Exceptions\PdfDoesNotExist
37
     */
38
    public function __construct($pdfFile)
39
    {
40
        if (! filter_var($pdfFile, FILTER_VALIDATE_URL) && ! file_exists($pdfFile)) {
41
            throw new PdfDoesNotExist();
42
        }
43
44
        $this->imagick = new Imagick($pdfFile);
45
46
        $this->numberOfPages = $this->imagick->getNumberImages();
47
48
        $this->pdfFile = $pdfFile;
49
    }
50
51
    /**
52
     * Set the raster resolution.
53
     *
54
     * @param int $resolution
55
     *
56
     * @return $this
57
     */
58
    public function setResolution($resolution)
59
    {
60
        $this->resolution = $resolution;
61
62
        return $this;
63
    }
64
65
    /**
66
     * Set the output format.
67
     *
68
     * @param string $outputFormat
69
     *
70
     * @return $this
71
     *
72
     * @throws \Spatie\PdfToImage\Exceptions\InvalidFormat
73
     */
74
    public function setOutputFormat($outputFormat)
75
    {
76
        if (! $this->isValidOutputFormat($outputFormat)) {
77
            throw new InvalidFormat("Format {$outputFormat} is not supported");
78
        }
79
80
        $this->outputFormat = $outputFormat;
81
82
        return $this;
83
    }
84
85
    /**
86
     * Get the output format.
87
     *
88
     * @return string
89
     */
90
    public function getOutputFormat()
91
    {
92
        return $this->outputFormat;
93
    }
94
    
95
    /**
96
     * Sets the layer method for Imagick::mergeImageLayers()
97
     * If int, should correspond to a predefined LAYERMETHOD constant.
98
     * If null, Imagick::mergeImageLayers() will not be called.
99
     *
100
     * @param int|null
101
     *
102
     * @return $this
103
     *
104
     * @throws \Spatie\PdfToImage\Exceptions\InvalidLayerMethod
105
     *
106
     * @see https://secure.php.net/manual/en/imagick.constants.php
107
     * @see Pdf::getImageData()
108
     */
109
    public function setLayerMethod($layerMethod)
110
    {
111
        if (
112
            is_int($layerMethod) === false &&
113
            is_null($layerMethod) === false
114
        ) {
115
            throw new InvalidLayerMethod('LayerMethod must be an integer or null');
116
        }
117
118
        $this->layerMethod = $layerMethod;
119
120
        return $this;
121
    }
122
123
    /**
124
     * Determine if the given format is a valid output format.
125
     *
126
     * @param $outputFormat
127
     *
128
     * @return bool
129
     */
130
    public function isValidOutputFormat($outputFormat)
131
    {
132
        return in_array($outputFormat, $this->validOutputFormats);
133
    }
134
135
    /**
136
     * Set the page number that should be rendered.
137
     *
138
     * @param int $page
139
     *
140
     * @return $this
141
     *
142
     * @throws \Spatie\PdfToImage\Exceptions\PageDoesNotExist
143
     */
144
    public function setPage($page)
145
    {
146
        if ($page > $this->getNumberOfPages()) {
147
            throw new PageDoesNotExist("Page {$page} does not exist");
148
        }
149
150
        $this->page = $page;
151
152
        return $this;
153
    }
154
155
    /**
156
     * Get the number of pages in the pdf file.
157
     *
158
     * @return int
159
     */
160
    public function getNumberOfPages()
161
    {
162
        return $this->numberOfPages;
163
    }
164
165
    /**
166
     * Save the image to the given path.
167
     *
168
     * @param string $pathToImage
169
     *
170
     * @return bool
171
     */
172
    public function saveImage($pathToImage)
173
    {
174
        if (is_dir($pathToImage)) {
175
            $pathToImage = rtrim($pathToImage, '\/') . DIRECTORY_SEPARATOR . $this->page . '.' . $this->outputFormat;
176
        }
177
        
178
        $imageData = $this->getImageData($pathToImage);
179
180
        return file_put_contents($pathToImage, $imageData) !== false;
181
    }
182
183
    /**
184
     * Save the file as images to the given directory.
185
     *
186
     * @param string $directory
187
     * @param string $prefix
188
     *
189
     * @return array $files the paths to the created images
190
     */
191
    public function saveAllPagesAsImages($directory, $prefix = '')
192
    {
193
        $numberOfPages = $this->getNumberOfPages();
194
195
        if ($numberOfPages === 0) {
196
            return [];
197
        }
198
199
        return array_map(function ($pageNumber) use ($directory, $prefix) {
200
            $this->setPage($pageNumber);
201
202
            $destination = "{$directory}/{$prefix}{$pageNumber}.{$this->outputFormat}";
203
204
            $this->saveImage($destination);
205
206
            return $destination;
207
        }, range(1, $numberOfPages));
208
    }
209
210
    /**
211
     * Return raw image data.
212
     *
213
     * @param string $pathToImage
214
     *
215
     * @return \Imagick
216
     */
217
    public function getImageData($pathToImage)
218
    {
219
        /*
220
         * Reinitialize imagick because the target resolution must be set
221
         * before reading the actual image.
222
         */
223
        $this->imagick = new Imagick();
224
225
        $this->imagick->setResolution($this->resolution, $this->resolution);
226
227
        if ($this->colorspace !== null) {
228
            $this->imagick->setColorspace($this->colorspace);
229
        }
230
231
        if ($this->compressionQuality !== null) {
232
            $this->imagick->setCompressionQuality($this->compressionQuality);
233
        }
234
235
        if (filter_var($this->pdfFile, FILTER_VALIDATE_URL)) {
236
            return $this->getRemoteImageData($pathToImage);
237
        }
238
239
        $this->imagick->readImage(sprintf('%s[%s]', $this->pdfFile, $this->page - 1));
240
241
        if (is_int($this->layerMethod)) {
242
            $this->imagick = $this->imagick->mergeImageLayers($this->layerMethod);
243
        }
244
245
        $this->imagick->setFormat($this->determineOutputFormat($pathToImage));
246
247
        return $this->imagick;
248
    }
249
250
    /**
251
     * @param int $colorspace
252
     *
253
     * @return $this
254
     */
255
    public function setColorspace(int $colorspace)
256
    {
257
        $this->colorspace = $colorspace;
258
259
        return $this;
260
    }
261
262
    /**
263
     * @param int $compressionQuality
264
     *
265
     * @return $this
266
     */
267
    public function setCompressionQuality(int $compressionQuality)
268
    {
269
        $this->compressionQuality = $compressionQuality;
270
271
        return $this;
272
    }
273
274
    /**
275
     * Return remote raw image data.
276
     *
277
     * @param string $pathToImage
278
     *
279
     * @return \Imagick
280
     */
281
    protected function getRemoteImageData($pathToImage)
282
    {
283
        $this->imagick->readImage($this->pdfFile);
284
285
        $this->imagick->setIteratorIndex($this->page - 1);
286
287
        if (is_int($this->layerMethod)) {
288
            $this->imagick = $this->imagick->mergeImageLayers($this->layerMethod);
289
        }
290
291
        $this->imagick->setFormat($this->determineOutputFormat($pathToImage));
292
293
        return $this->imagick;
294
    }
295
296
    /**
297
     * Determine in which format the image must be rendered.
298
     *
299
     * @param $pathToImage
300
     *
301
     * @return string
302
     */
303
    protected function determineOutputFormat($pathToImage)
304
    {
305
        $outputFormat = pathinfo($pathToImage, PATHINFO_EXTENSION);
306
307
        if ($this->outputFormat != '') {
308
            $outputFormat = $this->outputFormat;
309
        }
310
311
        $outputFormat = strtolower($outputFormat);
312
313
        if (! $this->isValidOutputFormat($outputFormat)) {
314
            $outputFormat = 'jpg';
315
        }
316
317
        return $outputFormat;
318
    }
319
}
320