Skip to content

[Bug] i.his.rgb: incorrect RGB values for grayscale and primary hue inputs #5659

@jayneel-shah18

Description

@jayneel-shah18

Description

The i.his.rgb module fails to produce correct RGB outputs in key scenarios involving grayscale and pure hue inputs. The newly added regression test suite linked below demonstrates the failure across the following cases:


Affected Cases

1. Grayscale conversion (saturation = 0)

Expected:
When saturation = 0, all RGB output bands should match the intensity input.

Actual:
All bands are 0, even when intensity is 255.

Suspected Cause:
In his2rgb.c, grayscale logic is gated by:

if (scales == 0.0) {
    if (hue == -1.0) {
        red = scalei;
        ...

This prevents grayscale assignment unless hue is exactly -1.0, which does not align with standard HIS to RGB behavior.


2. Primary hues (H = 0°, 120°, 240°)

Expected:
At full saturation and intensity:

  • H = 0 → Red = 255, Green = Blue = 0
  • H = 120 → Green = 255, Red = Blue = 0
  • H = 240 → Blue = 255, Red = Green = 0

Actual:
All three output bands are 255, regardless of hue.

Suspected Cause:
When both intensity = 255 and saturation = 255, the internal scale calculations cause m1 == m2 == 1.0, collapsing all RGB interpolations to the same value.

m2 = scalei + scales - (scalei * scales) = 1.0
m1 = 2 * scalei - m2 = 1.0

Steps to Reproduce

Run the following in GRASS:

# Grayscale case
r.mapcalc "intensity = 255"
r.mapcalc "saturation = 0"
r.mapcalc "hue = -1"
i.his.rgb hue=hue intensity=intensity saturation=saturation red=R green=G blue=B
r.univar R
r.univar G
r.univar B  

# Primary color case (e.g., red)
r.mapcalc "intensity = 255"
r.mapcalc "saturation = 255"
r.mapcalc "hue = 0"
i.his.rgb hue=hue intensity=intensity saturation=saturation red=R green=G blue=B
r.univar R
r.univar G
r.univar B

Screenshots

Image

Image

Image

Image

System Description

  • Operating System: Windows Subsystem for Linux (WSL)
  • GRASS GIS version: 8.4
  • details about further software components
    • GRASS 8.5.0dev
    • Python verison: 3.10.12
    • wxPython version: 4.2.2

Suggested Fixes

  • Grayscale: Remove hue == -1.0 check and assign RGB = intensity when saturation == 0.0.
  • Primary hues: Clamp intensity or saturation slightly below 1.0 (e.g., scalei = fmin(scalei, 0.999)) to avoid m1 == m2. I am unsure about this fix, but suggestions welcome from maintainers or module authors on the most robust approach.

Linked PR

#5660

This PR contains failing tests that demonstrate all the bugs listed above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions