diff --git a/CHANGELOG.md b/CHANGELOG.md index 69cf7f85..bce10232 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to `php-vips` will be documented in this file. - suppress autodoc of `composite` and `DemandStyle` [jcupitt] - update docs for 8.17 [jcupitt] - update docs for 8.18 [jcupitt] +- add getGainmap [jcupitt] ## 2.5.0 - 2025-04-04 diff --git a/src/FFI.php b/src/FFI.php index 8083adc6..722065d5 100644 --- a/src/FFI.php +++ b/src/FFI.php @@ -792,6 +792,12 @@ private static function init(): void CPP; } + if (self::atLeast(8, 18)) { + $vips_decls = $vips_decls . <<<'CPP' +VipsImage* vips_image_get_gainmap(const VipsImage* image); +CPP; + } + Utils::debugLog("init", ["binding ..."]); /** diff --git a/src/Image.php b/src/Image.php index afc9b452..ecfa512d 100644 --- a/src/Image.php +++ b/src/Image.php @@ -1267,6 +1267,37 @@ public function getFields(): array return $fields; } + /** + * Get the gainmap attached to an image, or null for no gainmap. + * + * After modifying the gainmap, you'll need to use Image::set() to + * write it back to the image again under the name "gainmap", for example: + * + * ```php + * $gainmap = $image->getGainmap(); + * if ($gainmap != null) { + * $new_gainmap = $gainmap->crop(0, 0, 10, 10); + * $image = $image->copy(); + * $image->set("gainmap", $new_gainmap); + * } + * ``` + * + * @return ?Image + */ + public function getGainmap(): ?Image + { + if (FFI::atLeast(8, 18)) { + $pointer = FFI::vips()->vips_image_get_gainmap($this->pointer); + if ($pointer == null) { + return null; + } else { + return new Image($pointer); + } + } else { + return null; + } + } + /** * Set any property on the underlying image. * diff --git a/tests/GainmapTest.php b/tests/GainmapTest.php new file mode 100644 index 00000000..29fba6e5 --- /dev/null +++ b/tests/GainmapTest.php @@ -0,0 +1,61 @@ +vips_type_find('VipsOperation', 'uhdrload') == 0) { + $this->markTestSkipped('requires libvips built with Ultra HDR support'); + } + + $filename = __DIR__ . '/images/ultra-hdr.jpg'; + $this->image = Vips\Image::newFromFile($filename); + + $filename = __DIR__ . '/images/img_0076.jpg'; + $this->no_gainmap_image = Vips\Image::newFromFile($filename); + } + + protected function tearDown(): void + { + unset($this->image); + unset($this->no_gainmap_image); + } + + public function testVipsGetGainmap() + { + $gainmap = $this->image->getGainmap(); + $this->assertEquals($gainmap->width, 960); + + $gainmap = $this->no_gainmap_image->getGainmap(); + $this->assertEquals($gainmap, null); + } + + public function testVipsSetGainmap() + { + $gainmap = $this->image->getGainmap(); + $new_gainmap = $gainmap->crop(0, 0, 10, 10); + $image = $this->image->copy(); + $image->set("gainmap", $new_gainmap); + + $gainmap = $image->getGainmap(); + $this->assertEquals($gainmap->width, 10); + } +} diff --git a/tests/images/ultra-hdr.jpg b/tests/images/ultra-hdr.jpg new file mode 100644 index 00000000..2e9a7ccb Binary files /dev/null and b/tests/images/ultra-hdr.jpg differ