Skip to content

Commit 0166162

Browse files
authored
Add support for LUTs in rasterized images (#274)
1 parent f5f4c4a commit 0166162

2 files changed

Lines changed: 33 additions & 14 deletions

File tree

src/Document/Image/ColorSpace/ColorSpace.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ColorSpace {
1717
public function __construct(
1818
public readonly bool $isIndexed,
1919
public readonly DeviceColorSpaceNameValue|CIEColorSpaceNameValue|SpecialColorSpaceNameValue $nameValue,
20-
public readonly DecoratedObject|null $objOrInlineValueLUT,
20+
public readonly DecoratedObject|null $LUTObj,
2121
public readonly string|null $fallbackLUT,
2222
public readonly ?int $maxIndexLUT,
2323
) {
@@ -32,9 +32,9 @@ public function getComponents(): Components {
3232
return $this->components = $this->nameValue->getComponents();
3333
}
3434

35-
if ($this->objOrInlineValueLUT?->getDictionary()->getTypeForKey(DictionaryKey::N) !== null) {
35+
if ($this->LUTObj?->getDictionary()->getTypeForKey(DictionaryKey::N) !== null) {
3636
return $this->components = Components::tryFrom(
37-
$this->objOrInlineValueLUT
37+
$this->LUTObj
3838
->getDictionary()
3939
->getValueForKey(DictionaryKey::N, IntegerValue::class)
4040
->value ?? throw new RuntimeException('Unable to determine number of components for color space')

src/Document/Image/RasterizedImage.php

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,23 +29,42 @@ public static function toPNG(ColorSpace $colorSpace, int $width, int $height, in
2929
$pixelIndex = 0;
3030
for ($y = 0; $y < $height; $y++) {
3131
for ($x = 0; $x < $width; $x++) {
32-
$color = match ($colorSpace->getComponents()) {
33-
Components::RGB => imagecolorallocate($image, ord($content->read($pixelIndex, 1)), ord($content->read($pixelIndex + 1, 1)), ord($content->read($pixelIndex + 2, 1))),
34-
Components::Gray => imagecolorallocate($image, $value = ord($content->read($pixelIndex, 1)), $value, $value),
35-
Components::CMYK => imagecolorallocate(
36-
$image,
37-
min(255, max(0, (int)(255 * (1 - (ord($content->read($pixelIndex, 1)) / 255)) * (1 - (ord($content->read($pixelIndex + 3, 1)) / 255))))),
38-
min(255, max(0, (int)(255 * (1 - (ord($content->read($pixelIndex + 1, 1)) / 255)) * (1 - (ord($content->read($pixelIndex + 3, 1)) / 255))))),
39-
min(255, max(0, (int)(255 * (1 - (ord($content->read($pixelIndex + 2, 1)) / 255)) * (1 - (ord($content->read($pixelIndex + 3, 1)) / 255))))),
40-
),
41-
};
32+
if ($colorSpace->isIndexed && $colorSpace->LUTObj !== null) {
33+
$indexInLUT = ord($content->read($pixelIndex, 1));
34+
if ($indexInLUT > $colorSpace->maxIndexLUT) {
35+
throw new ParseFailureException('Index in LUT is too large');
36+
}
37+
38+
$color = match ($colorSpace->getComponents()) {
39+
Components::RGB => imagecolorallocate($image, ord($colorSpace->LUTObj->getStream()->read($indexInLUT, 1)), ord($colorSpace->LUTObj->getStream()->read($indexInLUT + 1, 1)), ord($colorSpace->LUTObj->getStream()->read($indexInLUT + 2, 1))),
40+
Components::Gray => imagecolorallocate($image, $value = ord($colorSpace->LUTObj->getStream()->read($indexInLUT, 1)), $value, $value),
41+
Components::CMYK => imagecolorallocate(
42+
$image,
43+
min(255, max(0, (int)(255 * (1 - (ord($colorSpace->LUTObj->getStream()->read($indexInLUT, 1)) / 255)) * (1 - (ord($colorSpace->LUTObj->getStream()->read($indexInLUT + 3, 1)) / 255))))),
44+
min(255, max(0, (int)(255 * (1 - (ord($colorSpace->LUTObj->getStream()->read($indexInLUT + 1, 1)) / 255)) * (1 - (ord($colorSpace->LUTObj->getStream()->read($indexInLUT + 3, 1)) / 255))))),
45+
min(255, max(0, (int)(255 * (1 - (ord($colorSpace->LUTObj->getStream()->read($indexInLUT + 2, 1)) / 255)) * (1 - (ord($colorSpace->LUTObj->getStream()->read($indexInLUT + 3, 1)) / 255))))),
46+
),
47+
};
48+
$pixelIndex++;
49+
} else {
50+
$color = match ($colorSpace->getComponents()) {
51+
Components::RGB => imagecolorallocate($image, ord($content->read($pixelIndex, 1)), ord($content->read($pixelIndex + 1, 1)), ord($content->read($pixelIndex + 2, 1))),
52+
Components::Gray => imagecolorallocate($image, $value = ord($content->read($pixelIndex, 1)), $value, $value),
53+
Components::CMYK => imagecolorallocate(
54+
$image,
55+
min(255, max(0, (int)(255 * (1 - (ord($content->read($pixelIndex, 1)) / 255)) * (1 - (ord($content->read($pixelIndex + 3, 1)) / 255))))),
56+
min(255, max(0, (int)(255 * (1 - (ord($content->read($pixelIndex + 1, 1)) / 255)) * (1 - (ord($content->read($pixelIndex + 3, 1)) / 255))))),
57+
min(255, max(0, (int)(255 * (1 - (ord($content->read($pixelIndex + 2, 1)) / 255)) * (1 - (ord($content->read($pixelIndex + 3, 1)) / 255))))),
58+
),
59+
};
60+
$pixelIndex += $colorSpace->getComponents()->value;
61+
}
4262

4363
if ($color === false) {
4464
throw new ParseFailureException('Unable to allocate color');
4565
}
4666

4767
imagesetpixel($image, $x, $y, $color);
48-
$pixelIndex += $colorSpace->getComponents()->value;
4968
}
5069
}
5170

0 commit comments

Comments
 (0)