libvips/php-vips

How to create an image that is the maximum of each band?

axkirillov opened this issue ยท 4 comments

For further math operations I need something like

// $image is a 3-band RGB
// $max is a one-band image where each pixel is the max of RGB
$max =  $image->max();

So far I have come up with:

[$r, $g, $b] = $image->bandsplit();
$rvg = $r->more($g);
$rvb = $r->more($b);
$rvgarvb = $rvg->andimage($rvb);

$gvr = $g->more($r);
$gvb = $g->more($b);
$gvragvb = $gvr->andimage($gvb);

$max = $rvgarvb->ifthenelse($r, $gvragvb->ifthenelse($g, $b));

But maybe there is a more efficient way of doing that?

Hi again @axkirillov,

You need bandrank:

https://www.libvips.org/API/current/libvips-conversion.html#vips-bandrank

So eg.:

$max_at_each_pixel = $image->bandrank(["index" => $image->bands - 1]);

The function list is handy for finding things like this:

https://www.libvips.org/API/current/func-list.html

I saw bandrank but I didn't quite understand what it does at first. It seems to be that in your example there is a missing $other parameter. I'm not sure what that should be since it doesn't quite match what is there in documentation

Ooop, you're right, there was a bug in php-vips. I've fixed it in head and credited you.

This now works for me:

#!/usr/bin/env php
<?php

require __DIR__ . '/vendor/autoload.php';
use Jcupitt\Vips;

if(count($argv) != 3) {
    echo("usage: ./maxband.php input-image output-image\n");
    exit(1);
}

$image = Vips\Image::newFromFile($argv[1], ["access" => "sequential"]);

[$r, $g, $b] = $image->bandsplit();

$image = $r->bandrank([$g, $b], ["index" => $image->bands - 1]);

$image->writeToFile($argv[2]);

Thanks ๐Ÿ™‚! I am happy to have helped find a bug, albeit rather accidentally ๐Ÿ˜… .