Completed
Push — master ( 90db12...775e91 )
by Freek
07:40
created

Pdf::getRemoteImageData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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