libvips / php-vips

php binding for libvips
MIT License
606 stars 24 forks source link

no known route from 'multiband' to 'srgb' #204

Closed axkirillov closed 1 year ago

axkirillov commented 1 year ago

When applying the following function

    private function applyGamma(Vips\Image $image): Vips\Image
    {
        if ($this->gammar === 0 && $this->gammag === 0 && $this->gammab === 0) {
            return $image;
        }

        $lutR = $this->getGammaLUT($this->gammar);
        $lutG = $this->getGammaLUT($this->gammag);
        $lutB = $this->getGammaLUT($this->gammab);

        return $image->maplut($lutR->bandjoin([$lutG, $lutB]))->cast(Vips\BandFormat::UCHAR);
    }

    public function getGammaLUT(int $value): Vips\Image
    {
        if ($value === 0) {
            return Vips\Image::identity();
        }

        $value = $value / 100;

        $valueIsNegative = $value <= 0;

        $value = \abs($value);

        $value += 1;

        $value = $valueIsNegative ? $value : 1.0 / $value;

        return Vips\Image::identity()->divide(255)->pow($value)->multiply(255);
    }

interpretation seems to change from srgb to histogram, which prevents further composite with error "libvips error: vips_colourspace: no known route from 'multiband' to 'srgb'\n" what should I do to convert this image back to srgb space?

jcupitt commented 1 year ago

Hi @axkirillov, sorry for the delay, I was trapped in crunch.

You can set the interpretation with copy, eg.:

$image = $image->copy(["interpretation" => "srgb"]);

That'll copy the image unaltered (it just copies a pointer, no pixels are copied), and tag it as srgb.

You could make your code a little faster with:

        public function getGammaLUT(array $value): Vips\Image
    {
        return Vips\Image::identity()
                    ->divide(255)
                    ->pow($value)
                    ->multiply(255)
                    ->cast(Vips\BandFormat::UCHAR)
                    ->copy(["interpretation" => "srgb"]);
    }

Then use it with maybe:

        $power_factors = intGammaToFloatGamma([$this->gammar, $this->gammag, $this->gammab]);
                return $image->maplut(getGammaLUT($power_factors)); 

ie. do the cast on the LUT, not the result, and use an array of constants for pow().

axkirillov commented 1 year ago

Thank you!