Completed
Pull Request — master (#155)
by
unknown
01:01
created

Pdf::setAlphaChannel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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