Completed
Push — master ( ff372e...9fa0f7 )
by Freek
01:13
created

Pdf::setCompressionQuality()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
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
    protected $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
     * Sets the layer method for Imagick::mergeImageLayers()
87
     * If int, should correspond to a predefined LAYERMETHOD constant.
88
     * If null, Imagick::mergeImageLayers() will not be called.
89
     *
90
     * @param int|null
91
     *
92
     * @return $this
93
     *
94
     * @throws \Spatie\PdfToImage\Exceptions\InvalidLayerMethod
95
     *
96
     * @see https://secure.php.net/manual/en/imagick.constants.php
97
     * @see Pdf::getImageData()
98
     */
99
    public function setLayerMethod($layerMethod)
100
    {
101
        if (
102
            is_int($layerMethod) === false &&
103
            is_null($layerMethod) === false
104
        ) {
105
            throw new InvalidLayerMethod('LayerMethod must be an integer or null');
106
        }
107
108
        $this->layerMethod = $layerMethod;
109
110
        return $this;
111
    }
112
113
    /**
114
     * Determine if the given format is a valid output format.
115
     *
116
     * @param $outputFormat
117
     *
118
     * @return bool
119
     */
120
    public function isValidOutputFormat($outputFormat)
121
    {
122
        return in_array($outputFormat, $this->validOutputFormats);
123
    }
124
125
    /**
126
     * Set the page number that should be rendered.
127
     *
128
     * @param int $page
129
     *
130
     * @return $this
131
     *
132
     * @throws \Spatie\PdfToImage\Exceptions\PageDoesNotExist
133
     */
134
    public function setPage($page)
135
    {
136
        if ($page > $this->getNumberOfPages()) {
137
            throw new PageDoesNotExist("Page {$page} does not exist");
138
        }
139
140
        $this->page = $page;
141
142
        return $this;
143
    }
144
145
    /**
146
     * Get the number of pages in the pdf file.
147
     *
148
     * @return int
149
     */
150
    public function getNumberOfPages()
151
    {
152
        return $this->numberOfPages;
153
    }
154
155
    /**
156
     * Save the image to the given path.
157
     *
158
     * @param string $pathToImage
159
     *
160
     * @return bool
161
     */
162
    public function saveImage($pathToImage)
163
    {
164
        $imageData = $this->getImageData($pathToImage);
165
166
        return file_put_contents($pathToImage, $imageData) !== false;
167
    }
168
169
    /**
170
     * Save the file as images to the given directory.
171
     *
172
     * @param string $directory
173
     * @param string $prefix
174
     *
175
     * @return array $files the paths to the created images
176
     */
177
    public function saveAllPagesAsImages($directory, $prefix = '')
178
    {
179
        $numberOfPages = $this->getNumberOfPages();
180
181
        if ($numberOfPages === 0) {
182
            return [];
183
        }
184
185
        return array_map(function ($pageNumber) use ($directory, $prefix) {
186
            $this->setPage($pageNumber);
187
188
            $destination = "{$directory}/{$prefix}{$pageNumber}.{$this->outputFormat}";
189
190
            $this->saveImage($destination);
191
192
            return $destination;
193
        }, range(1, $numberOfPages));
194
    }
195
196
    /**
197
     * Return raw image data.
198
     *
199
     * @param string $pathToImage
200
     *
201
     * @return \Imagick
202
     */
203
    public function getImageData($pathToImage)
204
    {
205
        /*
206
         * Reinitialize imagick because the target resolution must be set
207
         * before reading the actual image.
208
         */
209
        $this->imagick = new Imagick();
210
211
        $this->imagick->setResolution($this->resolution, $this->resolution);
212
213
        if ($this->colorspace !== null) {
214
            $this->imagick->setColorspace($this->colorspace);
215
        }
216
217
        if ($this->colorspace !== null) {
218
            $this->imagick->setCompressionQuality($this->compressionQuality);
219
        }
220
221
        if (filter_var($this->pdfFile, FILTER_VALIDATE_URL)) {
222
            return $this->getRemoteImageData($pathToImage);
223
        }
224
225
        $this->imagick->readImage(sprintf('%s[%s]', $this->pdfFile, $this->page - 1));
226
227
        if (is_int($this->layerMethod)) {
228
            $this->imagick = $this->imagick->mergeImageLayers($this->layerMethod);
229
        }
230
231
        $this->imagick->setFormat($this->determineOutputFormat($pathToImage));
232
233
        return $this->imagick;
234
    }
235
236
    /**
237
     * @param int $colorspace
238
     *
239
     * @return $this
240
     */
241
    public function setColorspace(int $colorspace)
242
    {
243
        $this->colorspace = $colorspace;
244
245
        return $this;
246
    }
247
248
    /**
249
     * @param int $compressionQuality
250
     *
251
     * @return $this
252
     */
253
    public function setCompressionQuality(int $compressionQuality)
254
    {
255
        $this->compressionQuality = $compressionQuality;
256
257
        return $this;
258
    }
259
260
    /**
261
     * Return remote raw image data.
262
     *
263
     * @param string $pathToImage
264
     *
265
     * @return \Imagick
266
     */
267
    protected function getRemoteImageData($pathToImage)
268
    {
269
        $this->imagick->readImage($this->pdfFile);
270
271
        $this->imagick->setIteratorIndex($this->page - 1);
272
273
        if (is_int($this->layerMethod)) {
274
            $this->imagick = $this->imagick->mergeImageLayers($this->layerMethod);
275
        }
276
277
        $this->imagick->setFormat($this->determineOutputFormat($pathToImage));
278
279
        return $this->imagick;
280
    }
281
282
    /**
283
     * Determine in which format the image must be rendered.
284
     *
285
     * @param $pathToImage
286
     *
287
     * @return string
288
     */
289
    protected function determineOutputFormat($pathToImage)
290
    {
291
        $outputFormat = pathinfo($pathToImage, PATHINFO_EXTENSION);
292
293
        if ($this->outputFormat != '') {
294
            $outputFormat = $this->outputFormat;
295
        }
296
297
        $outputFormat = strtolower($outputFormat);
298
299
        if (! $this->isValidOutputFormat($outputFormat)) {
300
            $outputFormat = 'jpg';
301
        }
302
303
        return $outputFormat;
304
    }
305
}
306