Skip to content

Commit

Permalink
Issue-15: Extend color palette API for shading values
Browse files Browse the repository at this point in the history
  • Loading branch information
gwlucastrig committed Sep 4, 2023
1 parent 3239bae commit 009f4ae
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,33 @@ abstract ColorPaletteRecord copyWithModifiedRange(
*/
public abstract int getArgb(double z);

/**
* Gets an ARGB value for the specified parameters, if available.
* Implementations of this method generally expect that the value
* for z will be in the range of values that was specified to their
* constructor. The behavior of this method when supplied values out
* of range is undefined, though in many cases classes will simply
* constrain the input value to the supported range.
* <p>
* The shade value is intended to support applications that vary the
* intensity of the color based on a shade value. It value is expected
* to be in the range 0 (dark) to 1.0 (fully illuminated). When the
* shade value is set to 1.0, the results from this method are identical
* to those from the standard getArgb. Note that the behavior of this
* method is undefined for cases where it receives an out-of-range shade value.
* For reasons of efficiency, some implementations may elect to not
* add extra operations for range-checking. Thus the onus is on the
* calling application to always pass in valid shade values.
*
* @param z a valid floating point value
* @param shade a value in the range 0 to 1
* @return if a color is defined for z, its associated ARGB value;
* otherwise the null-value code.
*/
public abstract int getArgbWithShade(double z, double shade);



/**
* Gets a Color instance for the specified parameter, if available.
* Implementations of this method generally expect that the value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,34 @@ public int getArgb(double z) {
return Color.HSBtoRGB(h, s, v);
}


@Override
public int getArgbWithShade(double z, double shade) {
double t = (z - range0) / (range1 - range0);
if (t < 0) {
t = 0;
} else if (t > 1) {
t = 1;
}

double a = deltaH * t + h0;
// check for wrap-around cases
if (wrapAround) {
if (a < 0.0) {
a += 360.0;
} else if (a > 360.0) {
a -= 360.0;
}
}

float s = (float) (deltaS * t + s0);
float v = (float) ((deltaV * t + v0)*shade);
float h = (float) (a / 360.0);
return Color.HSBtoRGB(h, s, v);
}



@Override
public Color getColor(double v) {
return new Color(getArgb(v));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ ColorPaletteRecord copyWithModifiedRange(double minRangeSpec, double maxRangeSpe
record.setLabel(label);
return record;
}

@Override
public int getArgb(double z) {
double t = (z - range0) / (range1 - range0);
Expand All @@ -100,12 +100,27 @@ public int getArgb(double z) {
} else if (t > 1) {
t = 1;
}
int r = (int) (deltaR * t + 0.5) + r0;
int g = (int) (deltaG * t + 0.5) + g0;
int b = (int) (deltaB * t + 0.5) + b0;
int r = (int) (deltaR * t + r0 + 0.5);
int g = (int) (deltaG * t + g0 + 0.5);
int b = (int) (deltaB * t + b0 + 0.5);
return 0xff000000 | (r << 16) | (g << 8) | b;
}

@Override
public int getArgbWithShade(double z, double shade) {
double t = (z - range0) / (range1 - range0);
if (t < 0) {
t = 0;
} else if (t > 1) {
t = 1;
}
int r = (int) (shade * (deltaR * t + r0) + 0.5);
int g = (int) (shade * (deltaG * t + g0) + 0.5);
int b = (int) (shade * (deltaB * t + b0) + 0.5);
return 0xff000000 | (r << 16) | (g << 8) | b;
}


@Override
public Color getColor(double z) {
return new Color(getArgb(z));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,14 +455,110 @@ public int getArgb(double zTarget) {
return argbForNull;
}

/**

/**
* Gets an ARGB value for the specified parameters, if available.
* If the color table does not define a color value for the specified
* parameter, this method will return the ARGB code for a null value.
* If the value is outside the specified range of values for the
* palette, this method will return the ARGB code for a null value.
* <p>
* The shade value is intended to support applications that vary the
* intensity of the color based on a shade value. It value is expected
* to be in the range 0 (dark) to 1.0 (fully illuminated). When the
* shade value is set to 1.0, the results from this method are identical
* to those from the standard getArgb. Note that the behavior of this
* method is undefined for cases where it receives an out-of-range shade value.
* For reasons of efficiency, some implementations may elect to not
* add extra operations for range-checking. Thus the onus is on the
* calling application to always pass in valid shade values.
*
* @param zTarget a valid floating point value
* @param shade a value in the range 0 to 1.0, inclusive
* @return if a color is defined for z, its associated ARGB value;
* otherwise the null-value code.
*/
public int getArgbWithShade(double zTarget, double shade) {
// It is expected that this method will be called for every pixel in
// a data field. Since the number of pixels can be quite large,
// this method is heavily optimized for speed. Note also, that we
// always start with a binary search. No special coding is implemented
// for range checks or for small key lists since we assume:
// 1) The majority palettes will have at least four or five entries
// 2) Most of the time, the z values will be in range, otherwise
// we wouldn't be likely to be using the palette in the first place.
double z = zTarget;
if(normalized){
if(hinge){
if(z<hingeValue){
double t = (z-normalizedRangeMin)/(hingeValue-normalizedRangeMin);
z = t*(records[hingeIndex-1].range1-records[0].range0)+records[0].range0;
}else{
double t = (z-hingeValue)/(normalizedRangeMax-hingeValue);
int i0 = hingeIndex;
int i1 = records.length-1;
z = t*(records[i1].range1-records[i0].range0)+records[i0].range0;
}
}else{
double t = (z-normalizedRangeMin)/(normalizedRangeMax-normalizedRangeMin);
z = t*(records[records.length-1].range1-records[0].range0)+records[0].range0;
}
}


int index = Arrays.binarySearch(keys, z);
if (index >= 0) {
// an exact match for the lower range value of this color record
// TO DO: no interpolation is needed. perhaps we could expedite this.
return records[index].getArgbWithShade(z, shade);
}
if (index == -1) {
// the target value is less than the minimum supported value
return argbForNull;
}

// The Java binary search operated on the range0 value of each record.
// It returned a negative index, indicating
// the the value would be inserted into the key list at array position
// -(index+1). This means that the record at -(index+1)-1 has a range0
// value less than z. But we don't know if the range1 value is greater
// than z. So we have to check. Note that the maximum value of
// this adjusted index value is always between zero and keys.length-1.
// So we don't need to check whether it is in range.
index = -(index + 1) - 1;

// the binary search already established that the value z is
// greater than the range0 value of the record. but we don't
// know if it is less than or equal to the range1. Incidentally
// if range1 equals the range0 of the next record, the binary search
// would have found the next record. So we don't need to test
// for a termination condition.
ColorPaletteRecord record = records[index];
if (record.range1 >= z) {
return record.getArgbWithShade(z, shade);
}
return argbForNull;
}


/**
* Gets an ARGB value for the specified parameter, if available.
* If the target value is outside the range supported by this
* palette, the return value will be the ARGB associated with
* either the minimum or maximum values supported by the palette.
* If the palette features gaps in its coverage, it is still possible
* that a target value map fall within one of the gaps.
* But no limit is imposed for the range of supported values.
* <p>
* The shade value is intended to support applications that vary the
* intensity of the color based on a shade value. It value is expected
* to be in the range 0 (dark) to 1.0 (fully illuminated). When the
* shade value is set to 1.0, the results from this method are identical
* to those from the standard getArgb. Note that the behavior of this
* method is undefined for cases where it receives an out-of-range shade value.
* For reasons of efficiency, some implementations may elect to not
* add extra operations for range-checking. Thus the onus is on the
* calling application to always pass in valid shade values.
*
* @param zTarget a valid floating point value
* @return if a color is defined for z, its associated ARGB value;
Expand All @@ -478,6 +574,30 @@ public int getArgbUnlimitedRange(double zTarget) {
}


/**
* Gets an ARGB value for the specified parameter,
* if available.If the target value is outside the range supported by this
* palette, the return value will be the ARGB associated with
* either the minimum or maximum values supported by the palette.
* If the palette features gaps in its coverage, it is still possible
* that a target value map fall within one of the gaps.
* But no limit is imposed for the range of supported values.
*
* @param zTarget a valid floating point value
* @param shade a value in the range 0 to 1, inclusive.
* @return if a color is defined for z, its associated ARGB value;
* otherwise the null-value code.
*/
public int getArgbUnlimitedRangeWithShade(double zTarget, double shade) {
if(zTarget<rangeMin){
return getArgbWithShade(rangeMin, shade);
}else if(zTarget>rangeMax){
return getArgbWithShade(rangeMax, shade);
}
return getArgbWithShade(zTarget, shade);
}



/**
* Gets the color associated with the parameter z; if no color is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
* A discussion of the CPT file format can be found at the
* "CPT Designer" web page in an article by Tim Makins and MapAbility.com
* https://www.mapability.com/cptd/help/hs70.htm
*
*
* -----------------------------------------------------------------------
*/
package org.gridfour.demo.utils.palette;
Expand Down

0 comments on commit 009f4ae

Please sign in to comment.