Completed
Push — master ( 1871ac...3bb31d )
by Freek
01:09
created

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