1<?php 2 3namespace Mpdf\Writer; 4 5use Mpdf\Strict; 6use Mpdf\Mpdf; 7 8final class ImageWriter 9{ 10 11 use Strict; 12 13 /** 14 * @var \Mpdf\Mpdf 15 */ 16 private $mpdf; 17 18 /** 19 * @var \Mpdf\Writer\BaseWriter 20 */ 21 private $writer; 22 23 public function __construct(Mpdf $mpdf, BaseWriter $writer) 24 { 25 $this->mpdf = $mpdf; 26 $this->writer = $writer; 27 } 28 29 public function writeImages() 30 { 31 $filter = $this->mpdf->compress ? '/Filter /FlateDecode ' : ''; 32 33 foreach ($this->mpdf->images as $file => $info) { 34 35 $this->writer->object(); 36 37 $this->mpdf->images[$file]['n'] = $this->mpdf->n; 38 39 $this->writer->write('<</Type /XObject'); 40 $this->writer->write('/Subtype /Image'); 41 $this->writer->write('/Width ' . $info['w']); 42 $this->writer->write('/Height ' . $info['h']); 43 44 if (isset($info['interpolation']) && $info['interpolation']) { 45 $this->writer->write('/Interpolate true'); // mPDF 6 - image interpolation shall be performed by a conforming reader 46 } 47 48 if (isset($info['masked'])) { 49 $this->writer->write('/SMask ' . ($this->mpdf->n - 1) . ' 0 R'); 50 } 51 52 // set color space 53 $icc = false; 54 if (isset($info['icc']) && ( $info['icc'] !== false)) { 55 // ICC Colour Space 56 $icc = true; 57 $this->writer->write('/ColorSpace [/ICCBased ' . ($this->mpdf->n + 1) . ' 0 R]'); 58 } elseif ($info['cs'] === 'Indexed') { 59 if ($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace === 3)) { 60 throw new \Mpdf\MpdfException('PDFA1-b and PDFX/1-a files do not permit using mixed colour space (' . $file . ').'); 61 } 62 $this->writer->write('/ColorSpace [/Indexed /DeviceRGB ' . (strlen($info['pal']) / 3 - 1) . ' ' . ($this->mpdf->n + 1) . ' 0 R]'); 63 } else { 64 $this->writer->write('/ColorSpace /' . $info['cs']); 65 if ($info['cs'] === 'DeviceCMYK') { 66 if ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace !== 3) { 67 throw new \Mpdf\MpdfException('PDFA1-b does not permit Images using mixed colour space (' . $file . ').'); 68 } 69 if ($info['type'] === 'jpg') { 70 $this->writer->write('/Decode [1 0 1 0 1 0 1 0]'); 71 } 72 } elseif (($this->mpdf->PDFX || ($this->mpdf->PDFA && $this->mpdf->restrictColorSpace === 3)) && $info['cs'] === 'DeviceRGB') { 73 throw new \Mpdf\MpdfException('PDFA1-b and PDFX/1-a files do not permit using mixed colour space (' . $file . ').'); 74 } 75 } 76 77 $this->writer->write('/BitsPerComponent ' . $info['bpc']); 78 79 if (isset($info['f']) && $info['f']) { 80 $this->writer->write('/Filter /' . $info['f']); 81 } 82 83 if (isset($info['parms'])) { 84 $this->writer->write($info['parms']); 85 } 86 87 if (isset($info['trns']) && is_array($info['trns'])) { 88 $trns = ''; 89 $maskCount = count($info['trns']); 90 for ($i = 0; $i < $maskCount; $i++) { 91 $trns .= $info['trns'][$i] . ' ' . $info['trns'][$i] . ' '; 92 } 93 $this->writer->write('/Mask [' . $trns . ']'); 94 } 95 96 $this->writer->write('/Length ' . strlen($info['data']) . '>>'); 97 $this->writer->stream($info['data']); 98 99 unset($this->mpdf->images[$file]['data']); 100 101 $this->writer->write('endobj'); 102 103 if ($icc) { // ICC colour profile 104 $this->writer->object(); 105 $icc = $this->mpdf->compress ? gzcompress($info['icc']) : $info['icc']; 106 $this->writer->write('<</N ' . $info['ch'] . ' ' . $filter . '/Length ' . strlen($icc) . '>>'); 107 $this->writer->stream($icc); 108 $this->writer->write('endobj'); 109 } elseif ($info['cs'] === 'Indexed') { // Palette 110 $this->writer->object(); 111 $pal = $this->mpdf->compress ? gzcompress($info['pal']) : $info['pal']; 112 $this->writer->write('<<' . $filter . '/Length ' . strlen($pal) . '>>'); 113 $this->writer->stream($pal); 114 $this->writer->write('endobj'); 115 } 116 } 117 } 118 119} 120