summaryrefslogtreecommitdiffstats
path: root/vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php')
-rw-r--r--vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php187
1 files changed, 187 insertions, 0 deletions
diff --git a/vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php b/vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php
new file mode 100644
index 0000000..bedb5b7
--- /dev/null
+++ b/vendor/setasign/fpdi/src/PdfParser/Filter/Lzw.php
@@ -0,0 +1,187 @@
+<?php
+
+/**
+ * This file is part of FPDI
+ *
+ * @package setasign\Fpdi
+ * @copyright Copyright (c) 2020 Setasign GmbH & Co. KG (https://www.setasign.com)
+ * @license http://opensource.org/licenses/mit-license The MIT License
+ */
+
+namespace setasign\Fpdi\PdfParser\Filter;
+
+/**
+ * Class for handling LZW encoded data
+ */
+class Lzw implements FilterInterface
+{
+ /**
+ * @var null|string
+ */
+ protected $data;
+
+ /**
+ * @var array
+ */
+ protected $sTable = [];
+
+ /**
+ * @var int
+ */
+ protected $dataLength = 0;
+
+ /**
+ * @var int
+ */
+ protected $tIdx;
+
+ /**
+ * @var int
+ */
+ protected $bitsToGet = 9;
+
+ /**
+ * @var int
+ */
+ protected $bytePointer;
+
+ /**
+ * @var int
+ */
+ protected $nextData = 0;
+
+ /**
+ * @var int
+ */
+ protected $nextBits = 0;
+
+ /**
+ * @var array
+ */
+ protected $andTable = [511, 1023, 2047, 4095];
+
+ /**
+ * Method to decode LZW compressed data.
+ *
+ * @param string $data The compressed data
+ * @return string The uncompressed data
+ * @throws LzwException
+ */
+ public function decode($data)
+ {
+ if ($data[0] === "\x00" && $data[1] === "\x01") {
+ throw new LzwException(
+ 'LZW flavour not supported.',
+ LzwException::LZW_FLAVOUR_NOT_SUPPORTED
+ );
+ }
+
+ $this->initsTable();
+
+ $this->data = $data;
+ $this->dataLength = \strlen($data);
+
+ // Initialize pointers
+ $this->bytePointer = 0;
+
+ $this->nextData = 0;
+ $this->nextBits = 0;
+
+ $oldCode = 0;
+
+ $uncompData = '';
+
+ while (($code = $this->getNextCode()) !== 257) {
+ if ($code === 256) {
+ $this->initsTable();
+ $code = $this->getNextCode();
+
+ if ($code === 257) {
+ break;
+ }
+
+ $uncompData .= $this->sTable[$code];
+ $oldCode = $code;
+ } else {
+ if ($code < $this->tIdx) {
+ $string = $this->sTable[$code];
+ $uncompData .= $string;
+
+ $this->addStringToTable($this->sTable[$oldCode], $string[0]);
+ $oldCode = $code;
+ } else {
+ $string = $this->sTable[$oldCode];
+ $string .= $string[0];
+ $uncompData .= $string;
+
+ $this->addStringToTable($string);
+ $oldCode = $code;
+ }
+ }
+ }
+
+ return $uncompData;
+ }
+
+ /**
+ * Initialize the string table.
+ */
+ protected function initsTable()
+ {
+ $this->sTable = [];
+
+ for ($i = 0; $i < 256; $i++) {
+ $this->sTable[$i] = \chr($i);
+ }
+
+ $this->tIdx = 258;
+ $this->bitsToGet = 9;
+ }
+
+ /**
+ * Add a new string to the string table.
+ *
+ * @param string $oldString
+ * @param string $newString
+ */
+ protected function addStringToTable($oldString, $newString = '')
+ {
+ $string = $oldString . $newString;
+
+ // Add this new String to the table
+ $this->sTable[$this->tIdx++] = $string;
+
+ if ($this->tIdx === 511) {
+ $this->bitsToGet = 10;
+ } elseif ($this->tIdx === 1023) {
+ $this->bitsToGet = 11;
+ } elseif ($this->tIdx === 2047) {
+ $this->bitsToGet = 12;
+ }
+ }
+
+ /**
+ * Returns the next 9, 10, 11 or 12 bits.
+ *
+ * @return integer
+ */
+ protected function getNextCode()
+ {
+ if ($this->bytePointer === $this->dataLength) {
+ return 257;
+ }
+
+ $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff);
+ $this->nextBits += 8;
+
+ if ($this->nextBits < $this->bitsToGet) {
+ $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff);
+ $this->nextBits += 8;
+ }
+
+ $code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable[$this->bitsToGet - 9];
+ $this->nextBits -= $this->bitsToGet;
+
+ return $code;
+ }
+}