Issue #2492 Implemented support for colormapping in different units than the data comes in as. Other changes include NPE fix in RecordTileSetRenderable, glsl cleanup to use structs for code sharing, a topo display fix, and moved viirs colormaps to common
Amend: Fixed precision issue with float comparison, made factory better synchronized. Change-Id: Ie72d8d26ca5dc5ee1a0b5c14ca726edbee3bc1a2 Former-commit-id: ae724ecce3d4c65f8845f3278f9b5eeb5b04908a
This commit is contained in:
parent
7156ac5d4f
commit
3369fbec2d
35 changed files with 1934 additions and 907 deletions
|
@ -195,25 +195,28 @@ public class RecordTileSetRenderable extends TileSetRenderable {
|
||||||
// All the images need staging, do bulk request
|
// All the images need staging, do bulk request
|
||||||
ColorMapData data = retrieveRecordData(bigTile);
|
ColorMapData data = retrieveRecordData(bigTile);
|
||||||
|
|
||||||
Rectangle bigTileRect = bigTile.getRectangle();
|
if (data != null) {
|
||||||
for (int i = 0; i < numTiles; i += 1) {
|
Rectangle bigTileRect = bigTile.getRectangle();
|
||||||
Tile tile = subTiles.get(i);
|
for (int i = 0; i < numTiles; i += 1) {
|
||||||
DrawableImage image = images.get(i);
|
Tile tile = subTiles.get(i);
|
||||||
if (image != null) {
|
DrawableImage image = images.get(i);
|
||||||
if (image.getImage().getStatus() == Status.UNLOADED) {
|
if (image != null) {
|
||||||
Rectangle tileRect = tile.getRectangle();
|
if (image.getImage().getStatus() == Status.UNLOADED) {
|
||||||
ColorMapData subData = new ColorMapData(
|
Rectangle tileRect = tile.getRectangle();
|
||||||
BufferSlicer.slice(data.getBuffer(),
|
ColorMapData subData = new ColorMapData(
|
||||||
tileRect, bigTileRect), new int[] {
|
BufferSlicer.slice(data.getBuffer(),
|
||||||
tileRect.width, tileRect.height },
|
tileRect, bigTileRect),
|
||||||
data.getDataType(), data.getDataUnit());
|
new int[] { tileRect.width,
|
||||||
|
tileRect.height },
|
||||||
|
data.getDataType(), data.getDataUnit());
|
||||||
|
|
||||||
callbacks.get(i).setRetrievedData(subData);
|
callbacks.get(i).setRetrievedData(subData);
|
||||||
try {
|
try {
|
||||||
image.getImage().stage();
|
image.getImage().stage();
|
||||||
} catch (VizException e) {
|
} catch (VizException e) {
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
e.getLocalizedMessage(), e);
|
e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -424,6 +424,7 @@ public class VIIRSResource extends
|
||||||
}
|
}
|
||||||
|
|
||||||
colorMapParameters.setDataUnit(dataUnit);
|
colorMapParameters.setDataUnit(dataUnit);
|
||||||
|
colorMapParameters.setColorMapUnit(dataUnit);
|
||||||
colorMapParameters.setDisplayUnit(displayUnit);
|
colorMapParameters.setDisplayUnit(displayUnit);
|
||||||
|
|
||||||
colorMapParameters.setColorMapMin(colorMapParameters.getDataMin());
|
colorMapParameters.setColorMapMin(colorMapParameters.getDataMin());
|
||||||
|
@ -433,12 +434,14 @@ public class VIIRSResource extends
|
||||||
if (scale != null) {
|
if (scale != null) {
|
||||||
UnitConverter displayToData = colorMapParameters
|
UnitConverter displayToData = colorMapParameters
|
||||||
.getDisplayToDataConverter();
|
.getDisplayToDataConverter();
|
||||||
|
UnitConverter displayToColorMap = colorMapParameters
|
||||||
|
.getDisplayToColorMapConverter();
|
||||||
if (scale.getMinValue() != null) {
|
if (scale.getMinValue() != null) {
|
||||||
colorMapParameters.setColorMapMin((float) displayToData
|
colorMapParameters.setColorMapMin((float) displayToColorMap
|
||||||
.convert(scale.getMinValue()));
|
.convert(scale.getMinValue()));
|
||||||
}
|
}
|
||||||
if (scale.getMaxValue() != null) {
|
if (scale.getMaxValue() != null) {
|
||||||
colorMapParameters.setColorMapMax((float) displayToData
|
colorMapParameters.setColorMapMax((float) displayToColorMap
|
||||||
.convert(scale.getMaxValue()));
|
.convert(scale.getMaxValue()));
|
||||||
}
|
}
|
||||||
if (scale.getMinValue2() != null) {
|
if (scale.getMinValue2() != null) {
|
||||||
|
|
|
@ -1,90 +1,89 @@
|
||||||
#include <colorUtil>
|
#include <mapping>
|
||||||
#include <indexing>
|
|
||||||
|
|
||||||
// Multiplier used to store bit mask safely between 0-1
|
// Multiplier used to store bit mask safely between 0-1
|
||||||
const float maskMultiplier = 8.0;
|
const float maskMultiplier = 8.0;
|
||||||
|
const int RED_BAND = 0;
|
||||||
|
const int GREEN_BAND = 1;
|
||||||
|
const int BLUE_BAND = 2;
|
||||||
|
|
||||||
uniform sampler2D rawTex;
|
uniform DataTexture rawData;
|
||||||
uniform float naturalMin;
|
uniform DataMapping dataMapping;
|
||||||
uniform float naturalMax;
|
uniform ColorMapping colorMapping;
|
||||||
uniform float cmapMin;
|
|
||||||
uniform float cmapMax;
|
|
||||||
uniform int isFloat;
|
|
||||||
|
|
||||||
uniform int band;
|
|
||||||
|
|
||||||
uniform sampler2D trueColorTexture;
|
uniform sampler2D trueColorTexture;
|
||||||
uniform int height;
|
uniform float height;
|
||||||
uniform int width;
|
uniform float width;
|
||||||
|
|
||||||
uniform float noDataValue;
|
uniform int band;
|
||||||
uniform float alphaStep;
|
|
||||||
uniform int expectedMask;
|
uniform int expectedMask;
|
||||||
|
|
||||||
int toBitMask(float alpha) {
|
int toBitMask(float alpha) {
|
||||||
return int((alpha * maskMultiplier) + 0.5);
|
return int((alpha * maskMultiplier) + 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
float getIndex(sampler2D rawTex, float cmapMin, float cmapMax, float naturalMin, float naturalMax, int isFloat) {
|
float fromBitMask(int bitMask) {
|
||||||
vec4 textureValue = texture2D(rawTex, gl_TexCoord[0].st);
|
return bitMask / maskMultiplier;
|
||||||
float naturalVal = textureValue.r;
|
|
||||||
if ( isFloat == 0 ) {
|
|
||||||
naturalVal = ((naturalVal * (naturalMax - naturalMin)) + naturalMin);
|
|
||||||
}
|
|
||||||
|
|
||||||
float index = -1.0;
|
|
||||||
if (naturalVal != noDataValue && naturalVal == naturalVal) {
|
|
||||||
index = findIndex(naturalVal, cmapMin, cmapMax);
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void)
|
vec4 getFinalColor() {
|
||||||
{
|
vec4 imageVal = texture2D(trueColorTexture, gl_TexCoord[0].st);
|
||||||
if ( band == -1 ) {
|
float r = imageVal.r;
|
||||||
vec4 imageVal = texture2D(rawTex,gl_TexCoord[0].st);
|
float g = imageVal.g;
|
||||||
float r = imageVal.r;
|
float b = imageVal.b;
|
||||||
float g = imageVal.g;
|
float a = imageVal.a;
|
||||||
float b = imageVal.b;
|
|
||||||
float a = imageVal.a;
|
// Round because of 8-bit floating point precision
|
||||||
|
int bitMask = toBitMask(a);
|
||||||
// Round because of 8-bit floating point precision
|
if (expectedMask > 0 && bitMask == expectedMask) {
|
||||||
int bitMask = toBitMask(a);
|
a = 1.0;
|
||||||
if (expectedMask > 0 && bitMask == expectedMask ) {
|
|
||||||
a = 1.0;
|
|
||||||
} else {
|
|
||||||
a = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_FragColor = vec4(r,g,b,a);
|
|
||||||
} else {
|
} else {
|
||||||
vec2 xy = gl_FragCoord.xy;
|
a = 0.0;
|
||||||
vec4 imageVal = texture2D(rawTex,gl_TexCoord[0].st);
|
}
|
||||||
vec4 curVal = texture2D(trueColorTexture, vec2((xy.x / float(width)), (xy.y / float(height))));
|
|
||||||
|
return vec4(r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 applyColorBand(int colorband) {
|
||||||
|
vec2 xy = gl_FragCoord.xy;
|
||||||
|
vec4 curVal = texture2D(trueColorTexture,
|
||||||
|
vec2((xy.x / width), (xy.y / height)));
|
||||||
|
|
||||||
|
// Lookup raw data value
|
||||||
|
float dataValue = getDataValue(rawData, gl_TexCoord[0].st);
|
||||||
|
|
||||||
|
float r = curVal.r;
|
||||||
|
float g = curVal.g;
|
||||||
|
float b = curVal.b;
|
||||||
|
float a = curVal.a;
|
||||||
|
|
||||||
|
if (dataValue != rawData.noDataValue && dataValue == dataValue) {
|
||||||
|
// Convert dataValue to cmapValue
|
||||||
|
float cmapValue = dataToColorMapValue(dataValue, dataMapping);
|
||||||
|
float index = getColorMappingIndex(cmapValue, colorMapping);
|
||||||
|
|
||||||
float r = curVal.r;
|
int currentMask = toBitMask(a);
|
||||||
float g = curVal.g;
|
int bitValue = (1 << band);
|
||||||
float b = curVal.b;
|
if (colorband == RED_BAND && index > r) {
|
||||||
float a = curVal.a;
|
r = index;
|
||||||
|
} else if (colorband == GREEN_BAND && index > g) {
|
||||||
float index = getIndex(rawTex, cmapMin, cmapMax, naturalMin, naturalMax, isFloat);
|
g = index;
|
||||||
if ( index != -1.0 ) {
|
} else if (colorband == BLUE_BAND && index > b) {
|
||||||
int currentMask = toBitMask(a);
|
b = index;
|
||||||
int bitValue = (1 << band);
|
|
||||||
if ( band == 0 && index > r ) {
|
|
||||||
r = index;
|
|
||||||
} else if ( band == 1 && index > g ) {
|
|
||||||
g = index;
|
|
||||||
} else if ( band == 2 && index > b ) {
|
|
||||||
b = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( (currentMask & bitValue) == 0 ) {
|
|
||||||
// alpha does not contain this bit yet!
|
|
||||||
a = (currentMask | bitValue) / maskMultiplier;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_FragColor = vec4(r,g,b,a);
|
if ((currentMask & bitValue) == 0) {
|
||||||
|
// alpha does not contain this bit yet!
|
||||||
|
a = fromBitMask(currentMask | bitValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec4(r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
if (band == -1) {
|
||||||
|
gl_FragColor = getFinalColor();
|
||||||
|
} else {
|
||||||
|
gl_FragColor = applyColorBand(band);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -35,10 +35,13 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension;
|
import com.raytheon.uf.viz.truecolor.extension.ITrueColorImagingExtension;
|
||||||
import com.raytheon.uf.viz.truecolor.gl.image.GLTrueColorImage;
|
import com.raytheon.uf.viz.truecolor.gl.image.GLTrueColorImage;
|
||||||
import com.raytheon.viz.core.gl.ext.GLOffscreenRenderingExtension;
|
import com.raytheon.viz.core.gl.ext.GLOffscreenRenderingExtension;
|
||||||
|
import com.raytheon.viz.core.gl.ext.imaging.GLColormappedImageExtension;
|
||||||
|
import com.raytheon.viz.core.gl.ext.imaging.GLDataMappingFactory.GLDataMapping;
|
||||||
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
||||||
|
import com.raytheon.viz.core.gl.glsl.GLSLStructFactory;
|
||||||
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
||||||
|
import com.raytheon.viz.core.gl.images.AbstractGLColormappedImage;
|
||||||
import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
||||||
import com.raytheon.viz.core.gl.images.GLColormappedImage;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GL implementation of the {@link ITrueColorImagingExtension}
|
* GL implementation of the {@link ITrueColorImagingExtension}
|
||||||
|
@ -64,9 +67,6 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
|
||||||
|
|
||||||
private Channel renderingChannel;
|
private Channel renderingChannel;
|
||||||
|
|
||||||
/** The current rendering bit mask, specifies what bands we rendered */
|
|
||||||
private int currentMask = 0;
|
|
||||||
|
|
||||||
private Map<ColorMapParameters, Object> parameters = new IdentityHashMap<ColorMapParameters, Object>();
|
private Map<ColorMapParameters, Object> parameters = new IdentityHashMap<ColorMapParameters, Object>();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -111,7 +111,6 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
|
||||||
GLTrueColorImage trueColorImage = (GLTrueColorImage) image;
|
GLTrueColorImage trueColorImage = (GLTrueColorImage) image;
|
||||||
if (trueColorImage.isRepaint()) {
|
if (trueColorImage.isRepaint()) {
|
||||||
// Reset current bit mask
|
// Reset current bit mask
|
||||||
currentMask = 0;
|
|
||||||
parameters.clear();
|
parameters.clear();
|
||||||
writeToImage = trueColorImage;
|
writeToImage = trueColorImage;
|
||||||
GLOffscreenRenderingExtension extension = target
|
GLOffscreenRenderingExtension extension = target
|
||||||
|
@ -125,9 +124,6 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
|
||||||
DrawableImage[] imagesToDraw = trueColorImage
|
DrawableImage[] imagesToDraw = trueColorImage
|
||||||
.getImages(channel);
|
.getImages(channel);
|
||||||
if (imagesToDraw != null && imagesToDraw.length > 0) {
|
if (imagesToDraw != null && imagesToDraw.length > 0) {
|
||||||
// Mark the channel bit in the current bit mask
|
|
||||||
currentMask |= (1 << channel.ordinal());
|
|
||||||
|
|
||||||
// Make sure images are staged before we mosaic them
|
// Make sure images are staged before we mosaic them
|
||||||
ImagingSupport.prepareImages(target, imagesToDraw);
|
ImagingSupport.prepareImages(target, imagesToDraw);
|
||||||
|
|
||||||
|
@ -160,12 +156,17 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
|
||||||
imageCoverage));
|
imageCoverage));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (image instanceof AbstractGLColormappedImage) {
|
||||||
GL gl = target.getGl();
|
GL gl = target.getGl();
|
||||||
|
|
||||||
|
GLColormappedImageExtension.setupDataMapping(gl,
|
||||||
|
(AbstractGLColormappedImage) image, GL.GL_TEXTURE2,
|
||||||
|
GL.GL_TEXTURE3);
|
||||||
// bind on GL_TEXTURE1 as 0 is channel image
|
// bind on GL_TEXTURE1 as 0 is channel image
|
||||||
writeToImage.bind(gl, GL.GL_TEXTURE1);
|
writeToImage.bind(gl, GL.GL_TEXTURE1);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -190,6 +191,13 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
|
||||||
// Unbind the writeToImage from GL_TEXTURE1
|
// Unbind the writeToImage from GL_TEXTURE1
|
||||||
gl.glActiveTexture(GL.GL_TEXTURE1);
|
gl.glActiveTexture(GL.GL_TEXTURE1);
|
||||||
gl.glBindTexture(writeToImage.getTextureStorageType(), 0);
|
gl.glBindTexture(writeToImage.getTextureStorageType(), 0);
|
||||||
|
|
||||||
|
// Unbind the data mapped textures
|
||||||
|
gl.glActiveTexture(GL.GL_TEXTURE2);
|
||||||
|
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
|
||||||
|
|
||||||
|
gl.glActiveTexture(GL.GL_TEXTURE3);
|
||||||
|
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,36 +214,41 @@ public class GLTrueColorImagingExtension extends AbstractGLSLImagingExtension
|
||||||
public void loadShaderData(GLShaderProgram program, IImage image,
|
public void loadShaderData(GLShaderProgram program, IImage image,
|
||||||
PaintProperties paintProps) throws VizException {
|
PaintProperties paintProps) throws VizException {
|
||||||
if (image instanceof GLTrueColorImage) {
|
if (image instanceof GLTrueColorImage) {
|
||||||
|
GLTrueColorImage glImage = (GLTrueColorImage) image;
|
||||||
program.setUniform("band", -1);
|
program.setUniform("band", -1);
|
||||||
program.setUniform("rawTex", 0);
|
program.setUniform("trueColorTexture", 0);
|
||||||
program.setUniform("expectedMask", currentMask);
|
program.setUniform("expectedMask", glImage.getColorMask());
|
||||||
} else {
|
} else {
|
||||||
if (image instanceof GLColormappedImage == false) {
|
if (image instanceof AbstractGLColormappedImage == false) {
|
||||||
throw new VizException(
|
throw new VizException(
|
||||||
"Can only render colormapped images in true color");
|
"Can only render colormapped images in true color");
|
||||||
}
|
}
|
||||||
|
|
||||||
GLColormappedImage cmapImage = (GLColormappedImage) image;
|
AbstractGLColormappedImage cmapImage = (AbstractGLColormappedImage) image;
|
||||||
ColorMapParameters colorMapParameters = cmapImage
|
ColorMapParameters colorMapParameters = cmapImage
|
||||||
.getColorMapParameters();
|
.getColorMapParameters();
|
||||||
parameters.put(colorMapParameters, null);
|
|
||||||
int textureType = cmapImage.getTextureType();
|
|
||||||
|
|
||||||
// Set the band image data
|
parameters.put(colorMapParameters, null);
|
||||||
program.setUniform("rawTex", 0);
|
|
||||||
program.setUniform("naturalMin", colorMapParameters.getDataMin());
|
GLSLStructFactory.createDataTexture(program, "rawData", 0,
|
||||||
program.setUniform("naturalMax", colorMapParameters.getDataMax());
|
cmapImage.getDataFormat(),
|
||||||
program.setUniform("cmapMin", colorMapParameters.getColorMapMin());
|
|
||||||
program.setUniform("cmapMax", colorMapParameters.getColorMapMax());
|
|
||||||
program.setUniform("isFloat", textureType == GL.GL_FLOAT
|
|
||||||
|| textureType == GL.GL_HALF_FLOAT_ARB ? 1 : 0);
|
|
||||||
program.setUniform("noDataValue",
|
|
||||||
colorMapParameters.getNoDataValue());
|
colorMapParameters.getNoDataValue());
|
||||||
|
|
||||||
|
int numMappingValues = 0;
|
||||||
|
GLDataMapping mapping = cmapImage.getDataMapping();
|
||||||
|
if (mapping != null && mapping.isValid()) {
|
||||||
|
numMappingValues = mapping.getNumMappingValues();
|
||||||
|
}
|
||||||
|
GLSLStructFactory.createDataMapping(program, "dataMapping", 2, 3,
|
||||||
|
numMappingValues);
|
||||||
|
|
||||||
|
GLSLStructFactory.createColorMapping(program, "colorMapping", -1,
|
||||||
|
-1, colorMapParameters);
|
||||||
|
|
||||||
// Set the composite image data
|
// Set the composite image data
|
||||||
program.setUniform("trueColorTexture", 1);
|
program.setUniform("trueColorTexture", 1);
|
||||||
program.setUniform("width", writeToImage.getWidth());
|
program.setUniform("width", (float) writeToImage.getWidth());
|
||||||
program.setUniform("height", writeToImage.getHeight());
|
program.setUniform("height", (float) writeToImage.getHeight());
|
||||||
|
|
||||||
// Set the band we are rendering to
|
// Set the band we are rendering to
|
||||||
program.setUniform("band", renderingChannel.ordinal());
|
program.setUniform("band", renderingChannel.ordinal());
|
||||||
|
|
|
@ -97,6 +97,22 @@ public class GLTrueColorImage extends GLDelegateImage<GLImage> implements
|
||||||
this.imageExtent = imageExtent;
|
this.imageExtent = imageExtent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a bitmask of the expected RGB components to render
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getColorMask() {
|
||||||
|
int colorMask = 0;
|
||||||
|
for (Channel channel : Channel.values()) {
|
||||||
|
DrawableImage[] images = getImages(channel);
|
||||||
|
if (images != null && images.length > 0) {
|
||||||
|
colorMask |= (1 << channel.ordinal());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return colorMask;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the imageExtent
|
* @return the imageExtent
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,24 +1,21 @@
|
||||||
// Simple shader program for applying alpha,brightness, and contrast to the
|
// Simple shader program for applying alpha,brightness, and contrast to the
|
||||||
// colormap in the same way they are applied to data
|
// colormap in the same way they are applied to data
|
||||||
|
#include <mapping>
|
||||||
|
#include <coloring>
|
||||||
|
|
||||||
#include <colorUtil>
|
uniform ColorMapping colorMapping;
|
||||||
#include <indexing>
|
uniform ColorModifiers modifiers;
|
||||||
|
|
||||||
uniform float brightness;
|
|
||||||
uniform float contrast;
|
|
||||||
uniform float alphaVal;
|
|
||||||
|
|
||||||
uniform float bkgrndRed;
|
uniform float bkgrndRed;
|
||||||
uniform float bkgrndGreen;
|
uniform float bkgrndGreen;
|
||||||
uniform float bkgrndBlue;
|
uniform float bkgrndBlue;
|
||||||
|
|
||||||
uniform sampler1D colorMap;
|
|
||||||
uniform sampler2D alphaMask;
|
|
||||||
|
|
||||||
uniform int applyMask;
|
|
||||||
uniform float logFactor;
|
|
||||||
|
|
||||||
void main(void){
|
void main(void){
|
||||||
|
sampler1D colorMap = colorMapping.colorMap;
|
||||||
|
float logFactor = colorMapping.logFactor;
|
||||||
|
int applyMask = colorMapping.applyMask;
|
||||||
|
sampler1D alphaMask = colorMapping.alphaMask;
|
||||||
|
|
||||||
// Lookup color in colorMap for index
|
// Lookup color in colorMap for index
|
||||||
float index = gl_TexCoord[0].s;
|
float index = gl_TexCoord[0].s;
|
||||||
if ( logFactor > 0.0 ) {
|
if ( logFactor > 0.0 ) {
|
||||||
|
@ -29,10 +26,11 @@ void main(void){
|
||||||
// Apply alpha mask if set
|
// Apply alpha mask if set
|
||||||
float alpha = color.a;
|
float alpha = color.a;
|
||||||
if ( applyMask == 1 ) {
|
if ( applyMask == 1 ) {
|
||||||
if ( texture2D(alphaMask , vec2(index,index) ).r != 0.0 ) {
|
if ( texture1D(alphaMask , index ).r != 0.0 ) {
|
||||||
color = vec4(bkgrndRed, bkgrndGreen, bkgrndBlue, alpha);
|
color = vec4(bkgrndRed, bkgrndGreen, bkgrndBlue, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(alpha < 1.0){
|
if(alpha < 1.0){
|
||||||
// blend the color with background color, the colorbar should not be transparent
|
// blend the color with background color, the colorbar should not be transparent
|
||||||
alpha = 1.0;
|
alpha = 1.0;
|
||||||
|
@ -42,5 +40,5 @@ void main(void){
|
||||||
alpha);
|
alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_FragColor = applyContrastAlphaBrightness(color, alphaVal, brightness, contrast);
|
gl_FragColor = applyColorModifiers(color, modifiers);
|
||||||
}
|
}
|
|
@ -1,56 +1,24 @@
|
||||||
#include <colorUtil>
|
#include <mapping>
|
||||||
#include <indexing>
|
#include <coloring>
|
||||||
|
|
||||||
uniform float alpha;
|
uniform DataTexture rawData;
|
||||||
uniform float brightness;
|
uniform DataMapping dataMapping;
|
||||||
uniform float contrast;
|
uniform ColorMapping colorMapping;
|
||||||
uniform int applyMask;
|
uniform ColorModifiers modifiers;
|
||||||
uniform float naturalMin;
|
|
||||||
uniform float naturalMax;
|
|
||||||
uniform float cmapMin;
|
|
||||||
uniform float cmapMax;
|
|
||||||
uniform sampler1D colorMap;
|
|
||||||
uniform sampler2D alphaMask;
|
|
||||||
uniform sampler2D rawTex;
|
|
||||||
uniform float colorMapSz;
|
|
||||||
uniform int isFloat;
|
|
||||||
uniform int logarithmic;
|
|
||||||
uniform int mirror;
|
|
||||||
uniform float logFactor;
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 textureColor = texture2D(rawTex, gl_TexCoord[0].st);
|
float dataValue = getDataValue(rawData, gl_TexCoord[0].st);
|
||||||
float index = 0.0;
|
|
||||||
float rawValue = textureColor.r;
|
// No data check/special NaN check
|
||||||
if ( isFloat == 1 ) {
|
if (dataValue == rawData.noDataValue || dataValue != dataValue) {
|
||||||
if ( logarithmic == 1 ) {
|
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||||
index = findFloatIndexLog(rawValue, cmapMin, cmapMax, mirror);
|
return;
|
||||||
} else {
|
|
||||||
index = findFloatIndex(rawValue, cmapMin, cmapMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special float handling, -1.0 is NaN
|
|
||||||
if (index == -1.0){
|
|
||||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
float naturalValue = ((rawValue * (naturalMax - naturalMin)) + naturalMin);
|
|
||||||
index = findIndex(naturalValue, cmapMin, cmapMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup color in colorMap for index
|
|
||||||
if ( logFactor > 0.0 ) {
|
|
||||||
index = getLogFactorIndex(index, logFactor);
|
|
||||||
}
|
|
||||||
textureColor = texture1D(colorMap, index).rgba;
|
|
||||||
|
|
||||||
// Apply alpha mask
|
|
||||||
if ( applyMask == 1 ) {
|
|
||||||
if ( texture2D(alphaMask , vec2(index,index) ).r != 0.0 ) {
|
|
||||||
textureColor = vec4(textureColor.rgb, 0.0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gl_FragColor = applyContrastAlphaBrightness(textureColor, alpha, brightness, contrast);
|
// Convert dataValue to cmapValue
|
||||||
|
float cmapValue = dataToColorMapValue(dataValue, dataMapping);
|
||||||
|
// Get color for colormapping, given value
|
||||||
|
vec4 textureColor = getColorByValue(cmapValue, colorMapping);
|
||||||
|
// Apply the color modifiers into gl_FragColor
|
||||||
|
gl_FragColor = applyColorModifiers(textureColor, modifiers);
|
||||||
}
|
}
|
|
@ -1,34 +0,0 @@
|
||||||
|
|
||||||
vec3 AvgLuminance = vec3(0.5, 0.5, 0.5);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function applies the specified alpha, brightness, and contrast values
|
|
||||||
* to the color passed in
|
|
||||||
*/
|
|
||||||
vec4 applyContrastAlphaBrightness(vec4 color, float alpha, float brightness, float contrast){
|
|
||||||
vec3 textureColor3 = vec3(color);
|
|
||||||
vec3 adjustedColor = mix(AvgLuminance, textureColor3, contrast);
|
|
||||||
float curAlpha = min(color.a, alpha);
|
|
||||||
return vec4(adjustedColor.r * brightness, adjustedColor.g * brightness, adjustedColor.b * brightness, curAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function calculates a new index to use based on the logFactor
|
|
||||||
*/
|
|
||||||
float getLogFactorIndex(float index, float logFactor) {
|
|
||||||
if (logFactor > 0.0){
|
|
||||||
float minLog = log(logFactor);
|
|
||||||
float maxLog = log(logFactor + 1.0);
|
|
||||||
|
|
||||||
float lg = log(logFactor + index);
|
|
||||||
|
|
||||||
index = (lg - minLog) / (maxLog - minLog);
|
|
||||||
if (index < 0.0){
|
|
||||||
index = 0.0;
|
|
||||||
}
|
|
||||||
else if (index > 1.0){
|
|
||||||
index = 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
struct ColorModifiers {
|
||||||
|
float alpha;
|
||||||
|
float brightness;
|
||||||
|
float contrast;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec3 AvgLuminance = vec3(0.5, 0.5, 0.5);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function applies the specified ColorModifier values to the
|
||||||
|
* color passed in
|
||||||
|
*/
|
||||||
|
vec4 applyColorModifiers(vec4 color, ColorModifiers modifiers){
|
||||||
|
float alpha = modifiers.alpha;
|
||||||
|
float brightness = modifiers.brightness;
|
||||||
|
float contrast = modifiers.contrast;
|
||||||
|
|
||||||
|
vec3 textureColor3 = vec3(color);
|
||||||
|
vec3 adjustedColor = mix(AvgLuminance, textureColor3, contrast);
|
||||||
|
float curAlpha = min(color.a, alpha);
|
||||||
|
return vec4(adjustedColor.r * brightness, adjustedColor.g * brightness, adjustedColor.b * brightness, curAlpha);
|
||||||
|
}
|
|
@ -1,104 +0,0 @@
|
||||||
|
|
||||||
float HALF_FLOAT_NaN = 65504.0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function takes an index number and caps it to the range 0-1
|
|
||||||
*/
|
|
||||||
float capIndex(float index) {
|
|
||||||
if ( index < 0.0 ) {
|
|
||||||
index = 0.0;
|
|
||||||
} else if ( index > 1.0 ) {
|
|
||||||
index = 1.0;
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function linearly finds the index for the rawValue into cmapMin/cmapMax.
|
|
||||||
* 65504.0 is treated as NaN for half floats and -1 is returned as special case
|
|
||||||
*/
|
|
||||||
float findFloatIndex(float rawValue, float cmapMin, float cmapMax) {
|
|
||||||
if ( rawValue == HALF_FLOAT_NaN || rawValue != rawValue) {
|
|
||||||
return -1.0;
|
|
||||||
}
|
|
||||||
float index = ((rawValue - cmapMin) / abs(cmapMax-cmapMin));
|
|
||||||
return capIndex(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function logarithmically finds the index for the rawValue into cmapMin/cmapMax.
|
|
||||||
* 65504.0 is treated as NaN for half floats and -1 is returned as special case
|
|
||||||
*/
|
|
||||||
float findFloatIndexLog(float rawValue, float cmapMin, float cmapMax, int mirror) {
|
|
||||||
if ( rawValue == HALF_FLOAT_NaN ) {
|
|
||||||
return -1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float index = 0.0;
|
|
||||||
// is this strictly negative, strictly positive or neg to pos scaling?
|
|
||||||
if ( cmapMin >= 0.0 && cmapMax >= 0.0 && mirror!=1) {
|
|
||||||
if(rawValue < cmapMin){
|
|
||||||
index = 0.0;
|
|
||||||
}else{
|
|
||||||
// simple calculation
|
|
||||||
index = ((log(rawValue) - log(cmapMin)) / abs(log(cmapMax)-log(cmapMin)));
|
|
||||||
}
|
|
||||||
} else if (cmapMin <= 0.0 && cmapMax <= 0.0 && mirror!=1) {
|
|
||||||
index = ((log(rawValue) - log(cmapMax)) / abs(log(cmapMin)-log(cmapMax)));
|
|
||||||
} else {
|
|
||||||
// special case, neg to pos:
|
|
||||||
float colorMapMin = cmapMin;
|
|
||||||
float colorMapMax = cmapMax;
|
|
||||||
float zeroVal = max(colorMapMax, abs(colorMapMin)) * 0.0001;
|
|
||||||
if (mirror==1 && (colorMapMin > 0.0 || colorMapMax < 0.0)) {
|
|
||||||
if (colorMapMax < 0.0) {
|
|
||||||
colorMapMax = -cmapMax;
|
|
||||||
rawValue = -rawValue;
|
|
||||||
zeroVal = -colorMapMin;
|
|
||||||
} else {
|
|
||||||
zeroVal = cmapMin;
|
|
||||||
}
|
|
||||||
colorMapMin = -cmapMax;
|
|
||||||
}
|
|
||||||
float leftZero = 0.0;
|
|
||||||
float rightZero = 0.0;
|
|
||||||
float absLogZeroVal = abs(log(zeroVal));
|
|
||||||
|
|
||||||
rightZero = absLogZeroVal + log(colorMapMax);
|
|
||||||
|
|
||||||
float cmapMax2 = abs(colorMapMin);
|
|
||||||
|
|
||||||
leftZero = absLogZeroVal + log(cmapMax2);
|
|
||||||
|
|
||||||
float zeroIndex = leftZero / (leftZero + rightZero);
|
|
||||||
|
|
||||||
// figure out index for texture val
|
|
||||||
float absTextureColor = abs(rawValue);
|
|
||||||
if (absTextureColor <= zeroVal) {
|
|
||||||
index = zeroIndex;
|
|
||||||
} else if (rawValue > 0.0) {
|
|
||||||
// positive texture color value, find index from 0 to
|
|
||||||
// cmapMax:
|
|
||||||
float logTexColor = absLogZeroVal + log(rawValue);
|
|
||||||
|
|
||||||
float texIndex = logTexColor / rightZero;
|
|
||||||
index = (zeroIndex + ((1.0 - zeroIndex) * texIndex));
|
|
||||||
} else {
|
|
||||||
// negative texture color value, find index from 0 to
|
|
||||||
// cmapMax:
|
|
||||||
float logTexColor = absLogZeroVal + log(absTextureColor);
|
|
||||||
|
|
||||||
float texIndex = logTexColor / leftZero;
|
|
||||||
index = (zeroIndex - (zeroIndex * texIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return capIndex(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a raw data value linearly determine the index(0-1) into cmapMin/cmapMax
|
|
||||||
*/
|
|
||||||
float findIndex(float rawValue, float cmapMin, float cmapMax) {
|
|
||||||
float index = ((rawValue - cmapMin) / abs(cmapMax-cmapMin));
|
|
||||||
return capIndex(index);
|
|
||||||
}
|
|
|
@ -0,0 +1,299 @@
|
||||||
|
/**
|
||||||
|
* Mapping glsl library for use by other glsl programs. Defines
|
||||||
|
* commonly used structures and functions for data and color mapping
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields for the raw texture mapping is applied to. isScaled
|
||||||
|
* implied data will range 0-1 and need scaling to get raw value
|
||||||
|
* where scaleMin maps to 0 and scaleMax maps to 1.
|
||||||
|
*/
|
||||||
|
struct DataTexture {
|
||||||
|
sampler2D rawTex;
|
||||||
|
float noDataValue;
|
||||||
|
int isScaled;
|
||||||
|
float scaleMin;
|
||||||
|
float scaleMax;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields used for converting from image data values to
|
||||||
|
* colormapping data values. Done to avoid conversions in
|
||||||
|
* application code. dmv[i] -> cmv[i]. Linear interpolation
|
||||||
|
* is done where non-exact matches are found. Mappings should
|
||||||
|
* be uploaded as floats so no scaling is needed
|
||||||
|
*/
|
||||||
|
struct DataMapping {
|
||||||
|
sampler1D dataMappingValues;
|
||||||
|
sampler1D colorMappingValues;
|
||||||
|
int numMappingValues;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorMapping {
|
||||||
|
/** Fields for color map and size. colorMap contains colors to
|
||||||
|
* use for mapping. cmapMin/Max is range colormap is applied over */
|
||||||
|
sampler1D colorMap;
|
||||||
|
float cmapMin;
|
||||||
|
float cmapMax;
|
||||||
|
|
||||||
|
/** Field for alpha masking the colors. alphaMask is a texture the
|
||||||
|
* same size as colorMap and contains 0s and 1s, 1 indicating alpha
|
||||||
|
* should be set to completely transparent */
|
||||||
|
int applyMask;
|
||||||
|
sampler1D alphaMask;
|
||||||
|
|
||||||
|
/** Fields for logarithmic and mirrored indexing into the colorMap */
|
||||||
|
int isMirrored;
|
||||||
|
float logFactor;
|
||||||
|
int isLogarithmic;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data value for the DataTexture at location.
|
||||||
|
*/
|
||||||
|
float getDataValue(DataTexture texture, vec2 location) {
|
||||||
|
vec4 textureValue = texture2D(texture.rawTex, location);
|
||||||
|
float dataValue = textureValue.r;
|
||||||
|
|
||||||
|
if (texture.isScaled == 1) {
|
||||||
|
// Convert to non-scaled value
|
||||||
|
dataValue = ((dataValue * (texture.scaleMax - texture.scaleMin))
|
||||||
|
+ texture.scaleMin);
|
||||||
|
}
|
||||||
|
return dataValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up a value in a mapping texture given an index [0-numMappingValues).
|
||||||
|
*/
|
||||||
|
float lookupMappingValue(sampler1D mappingTex, int index,
|
||||||
|
int numMappingValues) {
|
||||||
|
return texture1D(mappingTex, float(index) / float(numMappingValues - 1)).r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a data value into a colorMap value given the DataMapping
|
||||||
|
*/
|
||||||
|
float dataToColorMapValue(float dataValue, DataMapping mapping) {
|
||||||
|
int numMappingValues = mapping.numMappingValues;
|
||||||
|
if (numMappingValues == 0) {
|
||||||
|
// Short circuit if no mapping is needed
|
||||||
|
return dataValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to colormap value
|
||||||
|
int lowIndex = 0;
|
||||||
|
int highIndex = numMappingValues - 1;
|
||||||
|
|
||||||
|
float lowValue = lookupMappingValue(mapping.dataMappingValues, lowIndex,
|
||||||
|
numMappingValues);
|
||||||
|
float highValue = lookupMappingValue(mapping.dataMappingValues, highIndex,
|
||||||
|
numMappingValues);
|
||||||
|
int reversed = 0;
|
||||||
|
if (lowValue > highValue) {
|
||||||
|
reversed = 1;
|
||||||
|
float tmp = lowValue;
|
||||||
|
lowValue = highValue;
|
||||||
|
highValue = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int done = 0;
|
||||||
|
// While there is at least one index to check
|
||||||
|
while (done == 0) {
|
||||||
|
int nextIndex = lowIndex + ((highIndex - lowIndex) / 2);
|
||||||
|
if (nextIndex > lowIndex && nextIndex < highIndex) {
|
||||||
|
// Look up next value and determine if it is a high or low
|
||||||
|
float nextValue = lookupMappingValue(mapping.dataMappingValues, nextIndex,
|
||||||
|
numMappingValues);
|
||||||
|
if (nextValue < dataValue) {
|
||||||
|
if (reversed == 0) {
|
||||||
|
lowIndex = nextIndex;
|
||||||
|
} else {
|
||||||
|
highIndex = nextIndex;
|
||||||
|
}
|
||||||
|
lowValue = nextValue;
|
||||||
|
} else {
|
||||||
|
if (reversed == 0) {
|
||||||
|
highIndex = nextIndex;
|
||||||
|
} else {
|
||||||
|
lowIndex = nextIndex;
|
||||||
|
}
|
||||||
|
highValue = nextValue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
done = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Percentage dataValue is linearly between low and high value
|
||||||
|
float factor = (dataValue - lowValue) / (highValue - lowValue);
|
||||||
|
if (reversed == 1) {
|
||||||
|
// Reverse factor for high->low indexing
|
||||||
|
factor = 1.0 - factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
float lowCmapValue = lookupMappingValue(mapping.colorMappingValues, lowIndex,
|
||||||
|
numMappingValues);
|
||||||
|
float highCmapValue = lookupMappingValue(mapping.colorMappingValues, highIndex,
|
||||||
|
numMappingValues);
|
||||||
|
|
||||||
|
return lowCmapValue + (highCmapValue - lowCmapValue) * factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function takes an index number and caps it to the range 0-1
|
||||||
|
*/
|
||||||
|
float capIndex(float index) {
|
||||||
|
if (index < 0.0) {
|
||||||
|
index = 0.0;
|
||||||
|
} else if (index > 1.0) {
|
||||||
|
index = 1.0;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a colorMap value linearly determine the index (capped at 0-1)
|
||||||
|
* into cmapMin/cmapMax
|
||||||
|
*/
|
||||||
|
float getLinearIndex(float cmapValue, float cmapMin, float cmapMax) {
|
||||||
|
float index = (cmapValue - cmapMin) / (cmapMax - cmapMin);
|
||||||
|
return capIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function logarithmically finds the index for the cmapValue into
|
||||||
|
* cmapMin/cmapMax (capped at 0-1).
|
||||||
|
*/
|
||||||
|
float getLogIndex(float cmapValue, float cmapMin, float cmapMax, int mirror) {
|
||||||
|
float index = 0.0;
|
||||||
|
// is this strictly negative, strictly positive or neg to pos scaling?
|
||||||
|
if (cmapMin >= 0.0 && cmapMax >= 0.0 && mirror != 1) {
|
||||||
|
if (cmapValue < cmapMin) {
|
||||||
|
index = 0.0;
|
||||||
|
} else {
|
||||||
|
// simple calculation
|
||||||
|
index = ((log(cmapValue) - log(cmapMin))
|
||||||
|
/ abs(log(cmapMax) - log(cmapMin)));
|
||||||
|
}
|
||||||
|
} else if (cmapMin <= 0.0 && cmapMax <= 0.0 && mirror != 1) {
|
||||||
|
index = ((log(cmapValue) - log(cmapMax))
|
||||||
|
/ abs(log(cmapMin) - log(cmapMax)));
|
||||||
|
} else {
|
||||||
|
// special case, neg to pos:
|
||||||
|
float colorMapMin = cmapMin;
|
||||||
|
float colorMapMax = cmapMax;
|
||||||
|
float zeroVal = max(colorMapMax, abs(colorMapMin)) * 0.0001;
|
||||||
|
if (mirror == 1 && (colorMapMin > 0.0 || colorMapMax < 0.0)) {
|
||||||
|
if (colorMapMax < 0.0) {
|
||||||
|
colorMapMax = -cmapMax;
|
||||||
|
cmapValue = -cmapValue;
|
||||||
|
zeroVal = -colorMapMin;
|
||||||
|
} else {
|
||||||
|
zeroVal = cmapMin;
|
||||||
|
}
|
||||||
|
colorMapMin = -cmapMax;
|
||||||
|
}
|
||||||
|
float leftZero = 0.0;
|
||||||
|
float rightZero = 0.0;
|
||||||
|
float absLogZeroVal = abs(log(zeroVal));
|
||||||
|
|
||||||
|
rightZero = absLogZeroVal + log(colorMapMax);
|
||||||
|
|
||||||
|
float cmapMax2 = abs(colorMapMin);
|
||||||
|
|
||||||
|
leftZero = absLogZeroVal + log(cmapMax2);
|
||||||
|
|
||||||
|
float zeroIndex = leftZero / (leftZero + rightZero);
|
||||||
|
|
||||||
|
// figure out index for texture val
|
||||||
|
float absTextureColor = abs(cmapValue);
|
||||||
|
if (absTextureColor <= zeroVal) {
|
||||||
|
index = zeroIndex;
|
||||||
|
} else if (cmapValue > 0.0) {
|
||||||
|
// positive texture color value, find index from 0 to
|
||||||
|
// cmapMax:
|
||||||
|
float logTexColor = absLogZeroVal + log(cmapValue);
|
||||||
|
|
||||||
|
float texIndex = logTexColor / rightZero;
|
||||||
|
index = (zeroIndex + ((1.0 - zeroIndex) * texIndex));
|
||||||
|
} else {
|
||||||
|
// negative texture color value, find index from 0 to
|
||||||
|
// cmapMax:
|
||||||
|
float logTexColor = absLogZeroVal + log(absTextureColor);
|
||||||
|
|
||||||
|
float texIndex = logTexColor / leftZero;
|
||||||
|
index = (zeroIndex - (zeroIndex * texIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return capIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function calculates a new index to use based on the logFactor
|
||||||
|
* and passed in index
|
||||||
|
*/
|
||||||
|
float getLogFactorIndex(float index, float logFactor) {
|
||||||
|
if (logFactor > 0.0) {
|
||||||
|
float minLog = log(logFactor);
|
||||||
|
float maxLog = log(logFactor + 1.0);
|
||||||
|
|
||||||
|
float lg = log(logFactor + index);
|
||||||
|
|
||||||
|
index = (lg - minLog) / (maxLog - minLog);
|
||||||
|
if (index < 0.0) {
|
||||||
|
index = 0.0;
|
||||||
|
} else if (index > 1.0) {
|
||||||
|
index = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an index for the cmapValue based on the ColorMapping
|
||||||
|
*/
|
||||||
|
float getColorMappingIndex(float cmapValue, ColorMapping colorMapping) {
|
||||||
|
int logarithmic = colorMapping.isLogarithmic;
|
||||||
|
int mirror = colorMapping.isMirrored;
|
||||||
|
float logFactor = colorMapping.logFactor;
|
||||||
|
float cmapMin = colorMapping.cmapMin;
|
||||||
|
float cmapMax = colorMapping.cmapMax;
|
||||||
|
|
||||||
|
float index;
|
||||||
|
if (logarithmic == 1) {
|
||||||
|
index = getLogIndex(cmapValue, cmapMin, cmapMax, mirror);
|
||||||
|
} else {
|
||||||
|
index = getLinearIndex(cmapValue, cmapMin, cmapMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply logFactor if set
|
||||||
|
if (logFactor > 0.0) {
|
||||||
|
index = getLogFactorIndex(index, logFactor);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a color for the index based on the ColorMapping
|
||||||
|
*/
|
||||||
|
vec4 getColorByIndex(float index, ColorMapping colorMapping) {
|
||||||
|
// Lookup color in colorMap for index
|
||||||
|
vec4 textureColor = texture1D(colorMapping.colorMap, index).rgba;
|
||||||
|
|
||||||
|
// Apply alpha mask
|
||||||
|
if (colorMapping.applyMask == 1) {
|
||||||
|
if (texture1D(colorMapping.alphaMask, index).r != 0.0) {
|
||||||
|
textureColor = vec4(textureColor.rgb, 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return textureColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a color for the cmapValue based on the ColorMapping
|
||||||
|
*/
|
||||||
|
vec4 getColorByValue(float cmapValue, ColorMapping colorMapping) {
|
||||||
|
return getColorByIndex(getColorMappingIndex(cmapValue, colorMapping),
|
||||||
|
colorMapping);
|
||||||
|
}
|
|
@ -1,11 +1,9 @@
|
||||||
#include <colorUtil>
|
#include <coloring>
|
||||||
|
|
||||||
uniform float brightness;
|
|
||||||
uniform float contrast;
|
|
||||||
uniform float alpha;
|
|
||||||
uniform sampler2D rawTex;
|
uniform sampler2D rawTex;
|
||||||
|
uniform ColorModifiers modifiers;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 textureColor = texture2D(rawTex, gl_TexCoord[0].st);
|
vec4 textureColor = texture2D(rawTex, gl_TexCoord[0].st);
|
||||||
gl_FragColor = applyContrastAlphaBrightness(textureColor, alpha, brightness, contrast);
|
gl_FragColor = applyColorModifiers(textureColor, modifiers);
|
||||||
}
|
}
|
|
@ -1,13 +1,11 @@
|
||||||
#include <colorUtil>
|
#include <coloring>
|
||||||
|
|
||||||
uniform float brightness;
|
|
||||||
uniform float contrast;
|
|
||||||
uniform float alpha;
|
|
||||||
uniform sampler2D rawTex;
|
uniform sampler2D rawTex;
|
||||||
uniform vec3 color;
|
uniform vec3 color;
|
||||||
|
uniform ColorModifiers modifiers;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
vec4 textureColor = texture2D(rawTex, gl_TexCoord[0].st);
|
vec4 textureColor = texture2D(rawTex, gl_TexCoord[0].st);
|
||||||
textureColor.rgb = color;
|
textureColor.rgb = color;
|
||||||
gl_FragColor = applyContrastAlphaBrightness(textureColor, alpha, brightness, contrast);
|
gl_FragColor = applyColorModifiers(textureColor, modifiers);
|
||||||
}
|
}
|
|
@ -217,7 +217,7 @@ public abstract class AbstractGLColorMapDataFormat {
|
||||||
protected Buffer handleBufferSizing(GLColorMapData data, Buffer buffer,
|
protected Buffer handleBufferSizing(GLColorMapData data, Buffer buffer,
|
||||||
int[] dimensions) {
|
int[] dimensions) {
|
||||||
int sliceWidth = dimensions[0] * getValuesPerPixel();
|
int sliceWidth = dimensions[0] * getValuesPerPixel();
|
||||||
int sliceHeight = dimensions[1];
|
int sliceHeight = dimensions.length > 1 ? dimensions[1] : 1;
|
||||||
int paddedSliceWidth = getAlignedWidth(sliceWidth);
|
int paddedSliceWidth = getAlignedWidth(sliceWidth);
|
||||||
|
|
||||||
int totalDataSize = buffer.capacity();
|
int totalDataSize = buffer.capacity();
|
||||||
|
|
|
@ -54,6 +54,10 @@ public class GLColorMapData {
|
||||||
this.dimensions = dimensions;
|
this.dimensions = dimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AbstractGLColorMapDataFormat getDataFormat() {
|
||||||
|
return dataFormat;
|
||||||
|
}
|
||||||
|
|
||||||
public int getTextureFormat() {
|
public int getTextureFormat() {
|
||||||
return dataFormat.getTextureFormat();
|
return dataFormat.getTextureFormat();
|
||||||
}
|
}
|
||||||
|
@ -93,6 +97,10 @@ public class GLColorMapData {
|
||||||
return dimensions[index];
|
return dimensions[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getNumDimensions() {
|
||||||
|
return dimensions.length;
|
||||||
|
}
|
||||||
|
|
||||||
public int[] getDimensions() {
|
public int[] getDimensions() {
|
||||||
return dimensions;
|
return dimensions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,11 @@ package com.raytheon.viz.core.gl.ext.imaging;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import javax.measure.unit.Unit;
|
||||||
import javax.media.opengl.GL;
|
import javax.media.opengl.GL;
|
||||||
|
|
||||||
import com.raytheon.uf.common.colormap.image.ColorMapData;
|
import com.raytheon.uf.common.colormap.image.ColorMapData;
|
||||||
|
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
|
||||||
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
||||||
import com.raytheon.uf.viz.core.PixelCoverage;
|
import com.raytheon.uf.viz.core.PixelCoverage;
|
||||||
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
|
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
|
||||||
|
@ -32,10 +34,15 @@ import com.raytheon.uf.viz.core.drawables.IImage;
|
||||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||||
import com.raytheon.uf.viz.core.drawables.ext.colormap.IColormappedImageExtension;
|
import com.raytheon.uf.viz.core.drawables.ext.colormap.IColormappedImageExtension;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
|
import com.raytheon.viz.core.gl.dataformat.GLByteDataFormat;
|
||||||
|
import com.raytheon.viz.core.gl.ext.imaging.GLDataMappingFactory.GLDataMapping;
|
||||||
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
||||||
|
import com.raytheon.viz.core.gl.glsl.GLSLStructFactory;
|
||||||
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
||||||
import com.raytheon.viz.core.gl.images.AbstractGLColormappedImage;
|
import com.raytheon.viz.core.gl.images.AbstractGLColormappedImage;
|
||||||
import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
||||||
|
import com.raytheon.viz.core.gl.images.GLBufferCMTextureData;
|
||||||
|
import com.raytheon.viz.core.gl.images.GLCMTextureData;
|
||||||
import com.raytheon.viz.core.gl.images.GLColormappedImage;
|
import com.raytheon.viz.core.gl.images.GLColormappedImage;
|
||||||
import com.raytheon.viz.core.gl.objects.GLTextureObject;
|
import com.raytheon.viz.core.gl.objects.GLTextureObject;
|
||||||
|
|
||||||
|
@ -53,7 +60,8 @@ import com.raytheon.viz.core.gl.objects.GLTextureObject;
|
||||||
* Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap
|
* Feb 14, 2013 1616 bsteffen Add option for interpolation of colormap
|
||||||
* parameters, disable colormap interpolation
|
* parameters, disable colormap interpolation
|
||||||
* by default.
|
* by default.
|
||||||
* Oct 16, 2013 2333 mschenke Cleaned up load shader method, used isScaled
|
* Oct 16, 2013 2333 mschenke Cleaned up load shader method, used isScaled.
|
||||||
|
* Added support for colormapping in non-data unit.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -65,7 +73,7 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
|
||||||
implements IColormappedImageExtension {
|
implements IColormappedImageExtension {
|
||||||
|
|
||||||
private static class GLColormappedImageExtensionData {
|
private static class GLColormappedImageExtensionData {
|
||||||
public GLColormappedImage alphaMaskTexture;
|
public GLCMTextureData alphaMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -108,31 +116,10 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usedColorMapParameters.isUseMask()) {
|
|
||||||
final byte[] mask = usedColorMapParameters.getAlphaMask();
|
|
||||||
data.alphaMaskTexture = initializeRaster(
|
|
||||||
new IColorMapDataRetrievalCallback() {
|
|
||||||
@Override
|
|
||||||
public ColorMapData getColorMapData()
|
|
||||||
throws VizException {
|
|
||||||
return new ColorMapData(ByteBuffer.wrap(mask),
|
|
||||||
new int[] { mask.length, 1 });
|
|
||||||
}
|
|
||||||
}, usedColorMapParameters);
|
|
||||||
data.alphaMaskTexture.stage();
|
|
||||||
data.alphaMaskTexture.target(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get and stage colormap texture
|
// Get and stage colormap texture
|
||||||
GLTextureObject cmapTexture = target
|
GLTextureObject cmapTexture = target
|
||||||
.getColorMapTexture(usedColorMapParameters);
|
.getColorMapTexture(usedColorMapParameters);
|
||||||
|
|
||||||
if (data.alphaMaskTexture != null) {
|
|
||||||
gl.glActiveTexture(GL.GL_TEXTURE2);
|
|
||||||
gl.glBindTexture(data.alphaMaskTexture.getTextureStorageType(),
|
|
||||||
data.alphaMaskTexture.getTextureid());
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.glActiveTexture(GL.GL_TEXTURE1);
|
gl.glActiveTexture(GL.GL_TEXTURE1);
|
||||||
cmapTexture.bind(gl, GL.GL_TEXTURE_1D);
|
cmapTexture.bind(gl, GL.GL_TEXTURE_1D);
|
||||||
|
|
||||||
|
@ -147,10 +134,97 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
|
||||||
gl.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_MAG_FILTER,
|
gl.glTexParameteri(GL.GL_TEXTURE_1D, GL.GL_TEXTURE_MAG_FILTER,
|
||||||
GL.GL_NEAREST);
|
GL.GL_NEAREST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (usedColorMapParameters.isUseMask()) {
|
||||||
|
data.alphaMask = setupAlphaMasking(gl, GL.GL_TEXTURE2,
|
||||||
|
usedColorMapParameters.getAlphaMask());
|
||||||
|
}
|
||||||
|
|
||||||
|
setupDataMapping(gl, glImage, GL.GL_TEXTURE3, GL.GL_TEXTURE4);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a {@link GLCMTextureData} for an alpha mask for use in image
|
||||||
|
* rendering
|
||||||
|
*
|
||||||
|
* @param gl
|
||||||
|
* @param maskTexBinding
|
||||||
|
* @param mask
|
||||||
|
* @return The GLCMTextureData the alpha mask is bound to or null if the
|
||||||
|
* texture failed to initialize
|
||||||
|
* @throws VizException
|
||||||
|
*/
|
||||||
|
public static GLCMTextureData setupAlphaMasking(GL gl, int maskTexBinding,
|
||||||
|
byte[] mask) throws VizException {
|
||||||
|
GLBufferCMTextureData maskData = new GLBufferCMTextureData(
|
||||||
|
new ColorMapData(ByteBuffer.wrap(mask),
|
||||||
|
new int[] { mask.length }, ColorMapDataType.BYTE),
|
||||||
|
new GLByteDataFormat());
|
||||||
|
gl.glActiveTexture(maskTexBinding);
|
||||||
|
if (maskData.loadTexture(gl)) {
|
||||||
|
gl.glBindTexture(maskData.getTextureStorageType(),
|
||||||
|
maskData.getTexId());
|
||||||
|
} else {
|
||||||
|
maskData.dispose();
|
||||||
|
maskData = null;
|
||||||
|
}
|
||||||
|
return maskData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a {@link GLDataMapping} for use in image rendering
|
||||||
|
*
|
||||||
|
* @param gl
|
||||||
|
* @param glImage
|
||||||
|
* @param dataMappedTexBinding
|
||||||
|
* @param colorMappedTexBinding
|
||||||
|
* @throws VizException
|
||||||
|
*/
|
||||||
|
public static void setupDataMapping(GL gl,
|
||||||
|
AbstractGLColormappedImage glImage, int dataMappedTexBinding,
|
||||||
|
int colorMappedTexBinding) throws VizException {
|
||||||
|
ColorMapParameters colorMapParameters = glImage.getColorMapParameters();
|
||||||
|
// Get GLDataMapping and generate if datamapping is not set. If
|
||||||
|
// datamapping is not set, the data has already been mapped to
|
||||||
|
// colorMapUnits and we need not do anything
|
||||||
|
GLDataMapping dataMapping = glImage.getDataMapping();
|
||||||
|
if (dataMapping == null && colorMapParameters.getDataMapping() == null) {
|
||||||
|
Unit<?> colorMapUnit = colorMapParameters.getColorMapUnit();
|
||||||
|
Unit<?> dataUnit = colorMapParameters.getDataUnit();
|
||||||
|
int colorMapSize = colorMapParameters.getColorMap().getSize();
|
||||||
|
float colorMapMin = colorMapParameters.getColorMapMin();
|
||||||
|
float colorMapMax = colorMapParameters.getColorMapMax();
|
||||||
|
dataMapping = GLDataMappingFactory.constructGLDataMapping(gl,
|
||||||
|
dataUnit, colorMapUnit, colorMapMin, colorMapMax,
|
||||||
|
colorMapSize);
|
||||||
|
glImage.setDataMapping(dataMapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataMapping != null && dataMapping.isValid()) {
|
||||||
|
GLCMTextureData glDataMapping = dataMapping.getDataMapping();
|
||||||
|
gl.glActiveTexture(dataMappedTexBinding);
|
||||||
|
if (glDataMapping.isLoaded() == false) {
|
||||||
|
glDataMapping.loadTexture(gl);
|
||||||
|
}
|
||||||
|
if (glDataMapping.isLoaded()) {
|
||||||
|
gl.glBindTexture(glDataMapping.getTextureStorageType(),
|
||||||
|
glDataMapping.getTexId());
|
||||||
|
}
|
||||||
|
|
||||||
|
GLCMTextureData glColorMapping = dataMapping.getColorMapping();
|
||||||
|
gl.glActiveTexture(colorMappedTexBinding);
|
||||||
|
if (glColorMapping.isLoaded() == false) {
|
||||||
|
glColorMapping.loadTexture(gl);
|
||||||
|
}
|
||||||
|
if (glColorMapping.isLoaded()) {
|
||||||
|
gl.glBindTexture(glColorMapping.getTextureStorageType(),
|
||||||
|
glColorMapping.getTexId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
|
@ -164,16 +238,22 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
|
||||||
AbstractGLImage image, Object data) throws VizException {
|
AbstractGLImage image, Object data) throws VizException {
|
||||||
GLColormappedImageExtensionData imageData = (GLColormappedImageExtensionData) data;
|
GLColormappedImageExtensionData imageData = (GLColormappedImageExtensionData) data;
|
||||||
GL gl = target.getGl();
|
GL gl = target.getGl();
|
||||||
if (imageData.alphaMaskTexture != null) {
|
|
||||||
gl.glActiveTexture(GL.GL_TEXTURE2);
|
|
||||||
gl.glBindTexture(
|
|
||||||
imageData.alphaMaskTexture.getTextureStorageType(), 0);
|
|
||||||
|
|
||||||
imageData.alphaMaskTexture.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.glActiveTexture(GL.GL_TEXTURE1);
|
gl.glActiveTexture(GL.GL_TEXTURE1);
|
||||||
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
|
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
|
||||||
|
|
||||||
|
if (imageData.alphaMask != null) {
|
||||||
|
gl.glActiveTexture(GL.GL_TEXTURE2);
|
||||||
|
gl.glBindTexture(imageData.alphaMask.getTextureStorageType(), 0);
|
||||||
|
|
||||||
|
imageData.alphaMask.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
gl.glActiveTexture(GL.GL_TEXTURE3);
|
||||||
|
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
|
||||||
|
|
||||||
|
gl.glActiveTexture(GL.GL_TEXTURE4);
|
||||||
|
gl.glBindTexture(GL.GL_TEXTURE_1D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -210,40 +290,22 @@ public class GLColormappedImageExtension extends AbstractGLSLImagingExtension
|
||||||
|
|
||||||
ColorMapParameters colorMapParameters = image.getColorMapParameters();
|
ColorMapParameters colorMapParameters = image.getColorMapParameters();
|
||||||
|
|
||||||
program.setUniform("colorMapSz", colorMapParameters.getColorMap()
|
GLSLStructFactory.createDataTexture(program, "rawData", 0,
|
||||||
.getSize());
|
image.getDataFormat(), colorMapParameters.getNoDataValue());
|
||||||
boolean isScaled = image.isImageFormatScaled();
|
|
||||||
double dataMin = colorMapParameters.getDataMin();
|
int numMappingValues = 0;
|
||||||
double dataMax = colorMapParameters.getDataMax();
|
GLDataMapping mapping = image.getDataMapping();
|
||||||
if (isScaled) {
|
if (mapping != null && mapping.isValid()) {
|
||||||
// get format from image and get data min/max from it
|
numMappingValues = mapping.getNumMappingValues();
|
||||||
dataMin = image.getDataMin();
|
|
||||||
dataMax = image.getDataMax();
|
|
||||||
}
|
}
|
||||||
|
GLSLStructFactory.createDataMapping(program, "dataMapping", 3, 4,
|
||||||
|
numMappingValues);
|
||||||
|
|
||||||
double cmapMin = colorMapParameters.getColorMapMin();
|
GLSLStructFactory.createColorMapping(program, "colorMapping", 1, 2,
|
||||||
double cmapMax = colorMapParameters.getColorMapMax();
|
colorMapParameters);
|
||||||
|
|
||||||
program.setUniform("isFloat", !isScaled);
|
GLSLStructFactory.createColorModifiers(program, "modifiers",
|
||||||
program.setUniform("logarithmic",
|
paintProps.getAlpha(), image.getBrightness(),
|
||||||
colorMapParameters.isLogarithmic() ? 1 : 0);
|
image.getContrast());
|
||||||
program.setUniform("logFactor", colorMapParameters.getLogFactor());
|
|
||||||
program.setUniform("mirror", colorMapParameters.isMirror() ? 1 : 0);
|
|
||||||
|
|
||||||
program.setUniform("applyMask", colorMapParameters.isUseMask() ? 1 : 0);
|
|
||||||
|
|
||||||
program.setUniform("naturalMin", dataMin);
|
|
||||||
program.setUniform("naturalMax", dataMax);
|
|
||||||
program.setUniform("cmapMin", cmapMin);
|
|
||||||
program.setUniform("cmapMax", cmapMax);
|
|
||||||
|
|
||||||
program.setUniform("alphaMask", 2);
|
|
||||||
program.setUniform("colorMap", 1);
|
|
||||||
program.setUniform("rawText", 0);
|
|
||||||
|
|
||||||
program.setUniform("brightness", image.getBrightness());
|
|
||||||
program.setUniform("contrast", image.getContrast());
|
|
||||||
program.setUniform("alpha", paintProps.getAlpha());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,343 @@
|
||||||
|
/**
|
||||||
|
* This software was developed and / or modified by Raytheon Company,
|
||||||
|
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||||
|
*
|
||||||
|
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||||
|
* This software product contains export-restricted data whose
|
||||||
|
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||||
|
* to non-U.S. persons whether in the United States or abroad requires
|
||||||
|
* an export license or other authorization.
|
||||||
|
*
|
||||||
|
* Contractor Name: Raytheon Company
|
||||||
|
* Contractor Address: 6825 Pine Street, Suite 340
|
||||||
|
* Mail Stop B8
|
||||||
|
* Omaha, NE 68106
|
||||||
|
* 402.291.0100
|
||||||
|
*
|
||||||
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
|
* further licensing information.
|
||||||
|
**/
|
||||||
|
package com.raytheon.viz.core.gl.ext.imaging;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.measure.converter.UnitConverter;
|
||||||
|
import javax.measure.unit.Unit;
|
||||||
|
import javax.media.opengl.GL;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.colormap.image.ColorMapData;
|
||||||
|
import com.raytheon.viz.core.gl.dataformat.GLBufferColorMapData;
|
||||||
|
import com.raytheon.viz.core.gl.dataformat.GLFloatDataFormat;
|
||||||
|
import com.raytheon.viz.core.gl.images.GLBufferCMTextureData;
|
||||||
|
import com.raytheon.viz.core.gl.images.GLCMTextureData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory class for creation {@link GLDataMapping} objects that can convert
|
||||||
|
* between units
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Oct 24, 2013 2492 mschenke Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author mschenke
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GLDataMappingFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key for {@link GLDataMappingFactory#mappingCache}. Stores fields needed
|
||||||
|
* to generate unique mappings
|
||||||
|
*
|
||||||
|
* @author mschenke
|
||||||
|
*/
|
||||||
|
private static class GLDataMappingKey {
|
||||||
|
|
||||||
|
private final Unit<?> dataUnit;
|
||||||
|
|
||||||
|
private final Unit<?> colorMapUnit;
|
||||||
|
|
||||||
|
private final float colorMapMin;
|
||||||
|
|
||||||
|
private final float colorMapMax;
|
||||||
|
|
||||||
|
private final int colorMapSize;
|
||||||
|
|
||||||
|
public GLDataMappingKey(Unit<?> dataUnit, Unit<?> colorMapUnit,
|
||||||
|
float colorMapMin, float colorMapMax, int colorMapSize) {
|
||||||
|
this.dataUnit = dataUnit;
|
||||||
|
this.colorMapUnit = colorMapUnit;
|
||||||
|
this.colorMapMin = colorMapMin;
|
||||||
|
this.colorMapMax = colorMapMax;
|
||||||
|
this.colorMapSize = colorMapSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Unit<?> getDataUnit() {
|
||||||
|
return dataUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Unit<?> getColorMapUnit() {
|
||||||
|
return colorMapUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getColorMapMin() {
|
||||||
|
return colorMapMin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getColorMapMax() {
|
||||||
|
return colorMapMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getColorMapSize() {
|
||||||
|
return colorMapSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + Float.floatToIntBits(colorMapMax);
|
||||||
|
result = prime * result + Float.floatToIntBits(colorMapMin);
|
||||||
|
result = prime * result + colorMapSize;
|
||||||
|
result = prime * result
|
||||||
|
+ ((colorMapUnit == null) ? 0 : colorMapUnit.hashCode());
|
||||||
|
result = prime * result
|
||||||
|
+ ((dataUnit == null) ? 0 : dataUnit.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
GLDataMappingKey other = (GLDataMappingKey) obj;
|
||||||
|
if (Float.floatToIntBits(colorMapMax) != Float
|
||||||
|
.floatToIntBits(other.colorMapMax))
|
||||||
|
return false;
|
||||||
|
if (Float.floatToIntBits(colorMapMin) != Float
|
||||||
|
.floatToIntBits(other.colorMapMin))
|
||||||
|
return false;
|
||||||
|
if (colorMapSize != other.colorMapSize)
|
||||||
|
return false;
|
||||||
|
if (colorMapUnit == null) {
|
||||||
|
if (other.colorMapUnit != null)
|
||||||
|
return false;
|
||||||
|
} else if (!colorMapUnit.equals(other.colorMapUnit))
|
||||||
|
return false;
|
||||||
|
if (dataUnit == null) {
|
||||||
|
if (other.dataUnit != null)
|
||||||
|
return false;
|
||||||
|
} else if (!dataUnit.equals(other.dataUnit))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GL data mapping object, represents a mapping between units for use in GL
|
||||||
|
*
|
||||||
|
* @author mschenke
|
||||||
|
*/
|
||||||
|
public static class GLDataMapping {
|
||||||
|
|
||||||
|
private final GLDataMappingKey key;
|
||||||
|
|
||||||
|
private GLCMTextureData colorMapping;
|
||||||
|
|
||||||
|
private GLCMTextureData dataMapping;
|
||||||
|
|
||||||
|
private int numMappingValues;
|
||||||
|
|
||||||
|
private int refCount = 1;
|
||||||
|
|
||||||
|
private boolean initialized = false;
|
||||||
|
|
||||||
|
public GLDataMapping(GLDataMappingKey key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GLCMTextureData getColorMapping() {
|
||||||
|
return colorMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GLCMTextureData getDataMapping() {
|
||||||
|
return dataMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumMappingValues() {
|
||||||
|
return numMappingValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return numMappingValues > 0 && colorMapping != null
|
||||||
|
&& dataMapping != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
synchronized (mappingCache) {
|
||||||
|
refCount -= 1;
|
||||||
|
if (refCount <= 0) {
|
||||||
|
mappingCache.remove(key);
|
||||||
|
if (colorMapping != null) {
|
||||||
|
colorMapping.dispose();
|
||||||
|
}
|
||||||
|
if (dataMapping != null) {
|
||||||
|
dataMapping.dispose();
|
||||||
|
}
|
||||||
|
refCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void use() {
|
||||||
|
if (refCount == 0) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"GLDataMapping has already been disposed");
|
||||||
|
}
|
||||||
|
refCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void initialize(GL gl) {
|
||||||
|
if (initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Unit<?> dataUnit = key.getDataUnit();
|
||||||
|
Unit<?> colorMapUnit = key.getColorMapUnit();
|
||||||
|
int colorMapSize = key.getColorMapSize();
|
||||||
|
double colorMapMin = key.getColorMapMin();
|
||||||
|
double colorMapMax = key.getColorMapMax();
|
||||||
|
int numMappings = 0;
|
||||||
|
if (dataUnit != null && colorMapUnit != null
|
||||||
|
&& dataUnit.equals(colorMapUnit) == false
|
||||||
|
&& dataUnit.isCompatible(colorMapUnit)) {
|
||||||
|
// Worst case scenario, one mapping per color
|
||||||
|
double[] colorMapping = new double[colorMapSize];
|
||||||
|
Arrays.fill(colorMapping, Float.NaN);
|
||||||
|
double[] dataMapping = new double[colorMapping.length];
|
||||||
|
Arrays.fill(dataMapping, Float.NaN);
|
||||||
|
|
||||||
|
UnitConverter colorMapToData = colorMapUnit
|
||||||
|
.getConverterTo(dataUnit);
|
||||||
|
double dataMin = colorMapToData.convert(colorMapMin);
|
||||||
|
double dataMax = colorMapToData.convert(colorMapMax);
|
||||||
|
colorMapping[0] = colorMapMin;
|
||||||
|
colorMapping[colorMapping.length - 1] = colorMapMax;
|
||||||
|
dataMapping[0] = dataMin;
|
||||||
|
dataMapping[dataMapping.length - 1] = dataMax;
|
||||||
|
|
||||||
|
numMappings = 2;
|
||||||
|
if (colorMapToData.isLinear() == false) {
|
||||||
|
// Populate the dataMapping/colorMapping arrays
|
||||||
|
double increment = (colorMapMax - colorMapMin)
|
||||||
|
/ (colorMapping.length - 1);
|
||||||
|
for (int i = 1; i < colorMapping.length - 1; ++i) {
|
||||||
|
colorMapping[i] = colorMapMin + (i * increment);
|
||||||
|
dataMapping[i] = colorMapToData
|
||||||
|
.convert(colorMapping[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for linearness in the dataMappings.
|
||||||
|
int currEndIndex = 1;
|
||||||
|
double currEndValue = dataMapping[currEndIndex];
|
||||||
|
float currDelta = (float) (currEndValue - dataMapping[0]);
|
||||||
|
for (int i = 2; i < dataMapping.length; ++i) {
|
||||||
|
double nextValue = dataMapping[i];
|
||||||
|
float nextDelta = (float) ((nextValue - currEndValue) / (i - currEndIndex));
|
||||||
|
if (nextDelta == currDelta) {
|
||||||
|
// Remove linear entries
|
||||||
|
dataMapping[currEndIndex] = colorMapping[currEndIndex] = Double.NaN;
|
||||||
|
currEndValue = nextValue;
|
||||||
|
currEndIndex = i;
|
||||||
|
} else {
|
||||||
|
// Non-linear entry found, add mapping
|
||||||
|
numMappings += 1;
|
||||||
|
currEndIndex = i;
|
||||||
|
currEndValue = nextValue;
|
||||||
|
currDelta = nextDelta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Condense the mapping arrays removing nans
|
||||||
|
float[] condensedColorMapping = new float[numMappings];
|
||||||
|
float[] condensedDataMapping = new float[numMappings];
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < colorMapSize && index < numMappings; ++i) {
|
||||||
|
double colorMapVal = colorMapping[i];
|
||||||
|
double dataMapVal = dataMapping[i];
|
||||||
|
if (Double.isNaN(colorMapVal) == false
|
||||||
|
&& Double.isNaN(dataMapVal) == false) {
|
||||||
|
condensedColorMapping[index] = (float) colorMapVal;
|
||||||
|
condensedDataMapping[index] = (float) dataMapVal;
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == numMappings) {
|
||||||
|
this.numMappingValues = numMappings;
|
||||||
|
this.colorMapping = new GLBufferCMTextureData(
|
||||||
|
new GLBufferColorMapData(new ColorMapData(
|
||||||
|
FloatBuffer.wrap(condensedColorMapping),
|
||||||
|
new int[] { numMappings }),
|
||||||
|
new GLFloatDataFormat()));
|
||||||
|
this.dataMapping = new GLBufferCMTextureData(
|
||||||
|
new GLBufferColorMapData(new ColorMapData(
|
||||||
|
FloatBuffer.wrap(condensedDataMapping),
|
||||||
|
new int[] { numMappings }),
|
||||||
|
new GLFloatDataFormat()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<GLDataMappingKey, GLDataMapping> mappingCache = new HashMap<GLDataMappingKey, GLDataMapping>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link GLDataMapping} object given the dataUnit, colorMapUnit,
|
||||||
|
* color map min/max, and size of the colormap. Object must be disposed of
|
||||||
|
* when no longer used
|
||||||
|
*
|
||||||
|
* @param gl
|
||||||
|
* @param dataUnit
|
||||||
|
* @param colorMapUnit
|
||||||
|
* @param colorMapMin
|
||||||
|
* @param colorMapMax
|
||||||
|
* @param colorMapSize
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static GLDataMapping constructGLDataMapping(GL gl, Unit<?> dataUnit,
|
||||||
|
Unit<?> colorMapUnit, float colorMapMin, float colorMapMax,
|
||||||
|
int colorMapSize) {
|
||||||
|
GLDataMapping mapping;
|
||||||
|
synchronized (mappingCache) {
|
||||||
|
GLDataMappingKey key = new GLDataMappingKey(dataUnit, colorMapUnit,
|
||||||
|
colorMapMin, colorMapMax, colorMapSize);
|
||||||
|
mapping = mappingCache.get(key);
|
||||||
|
if (mapping == null) {
|
||||||
|
mapping = new GLDataMapping(key);
|
||||||
|
mappingCache.put(key, mapping);
|
||||||
|
} else {
|
||||||
|
mapping.use();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapping.initialize(gl);
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ package com.raytheon.viz.core.gl.ext.imaging;
|
||||||
import com.raytheon.uf.viz.core.drawables.IImage;
|
import com.raytheon.uf.viz.core.drawables.IImage;
|
||||||
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
|
import com.raytheon.viz.core.gl.glsl.GLSLStructFactory;
|
||||||
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
||||||
import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
||||||
|
|
||||||
|
@ -34,7 +35,9 @@ import com.raytheon.viz.core.gl.images.AbstractGLImage;
|
||||||
*
|
*
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Dec 16, 2011 mschenke Initial creation
|
* Dec 16, 2011 mschenke Initial creation
|
||||||
|
* Nov 4, 2013 2492 mschenke Switched to use GLSLStructFactory for
|
||||||
|
* common shader structure use
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -76,10 +79,10 @@ public class GLDefaultImagingExtension extends AbstractGLImagingExtension {
|
||||||
}
|
}
|
||||||
image = (AbstractGLImage) iimage;
|
image = (AbstractGLImage) iimage;
|
||||||
|
|
||||||
program.setUniform("alpha", paintProps.getAlpha());
|
|
||||||
program.setUniform("brightness", image.getBrightness());
|
|
||||||
program.setUniform("contrast", image.getContrast());
|
|
||||||
program.setUniform("rawTex", 0);
|
program.setUniform("rawTex", 0);
|
||||||
|
GLSLStructFactory.createColorModifiers(program, "modifiers",
|
||||||
|
paintProps.getAlpha(), image.getBrightness(),
|
||||||
|
image.getContrast());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import com.raytheon.uf.viz.core.drawables.PaintProperties;
|
||||||
import com.raytheon.uf.viz.core.drawables.ext.ISingleColorImageExtension;
|
import com.raytheon.uf.viz.core.drawables.ext.ISingleColorImageExtension;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
import com.raytheon.viz.core.gl.glsl.AbstractGLSLImagingExtension;
|
||||||
|
import com.raytheon.viz.core.gl.glsl.GLSLStructFactory;
|
||||||
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
||||||
import com.raytheon.viz.core.gl.images.GLSingleColorImage;
|
import com.raytheon.viz.core.gl.images.GLSingleColorImage;
|
||||||
|
|
||||||
|
@ -40,7 +41,9 @@ import com.raytheon.viz.core.gl.images.GLSingleColorImage;
|
||||||
*
|
*
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Dec 15, 2011 mschenke Initial creation
|
* Dec 15, 2011 mschenke Initial creation
|
||||||
|
* Nov 4, 2013 2492 mschenke Switched to use GLSLStructFactory for
|
||||||
|
* common shader structure use
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -97,11 +100,11 @@ public class GLSingleColorImageExtension extends AbstractGLSLImagingExtension
|
||||||
|
|
||||||
image = (GLSingleColorImage) iimage;
|
image = (GLSingleColorImage) iimage;
|
||||||
|
|
||||||
program.setUniform("brightness", image.getBrightness());
|
|
||||||
program.setUniform("contrast", image.getContrast());
|
|
||||||
program.setUniform("alpha", paintProps.getAlpha());
|
|
||||||
program.setUniform("color", image.getColor());
|
program.setUniform("color", image.getColor());
|
||||||
program.setUniform("rawTex", 0);
|
program.setUniform("rawTex", 0);
|
||||||
|
GLSLStructFactory.createColorModifiers(program, "modifiers",
|
||||||
|
paintProps.getAlpha(), image.getBrightness(),
|
||||||
|
image.getContrast());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/**
|
||||||
|
* This software was developed and / or modified by Raytheon Company,
|
||||||
|
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||||
|
*
|
||||||
|
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||||
|
* This software product contains export-restricted data whose
|
||||||
|
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||||
|
* to non-U.S. persons whether in the United States or abroad requires
|
||||||
|
* an export license or other authorization.
|
||||||
|
*
|
||||||
|
* Contractor Name: Raytheon Company
|
||||||
|
* Contractor Address: 6825 Pine Street, Suite 340
|
||||||
|
* Mail Stop B8
|
||||||
|
* Omaha, NE 68106
|
||||||
|
* 402.291.0100
|
||||||
|
*
|
||||||
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
|
* further licensing information.
|
||||||
|
**/
|
||||||
|
package com.raytheon.viz.core.gl.glsl;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
||||||
|
import com.raytheon.viz.core.gl.dataformat.AbstractGLColorMapDataFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for creating GLSL struct mappings
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Oct 31, 2013 2492 mschenke Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author mschenke
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GLSLStructFactory {
|
||||||
|
|
||||||
|
private static final String FIELD_SEPERATOR = ".";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DataTexture structure in the program with the given name
|
||||||
|
*
|
||||||
|
* @param program
|
||||||
|
* @param name
|
||||||
|
* @param texBinding
|
||||||
|
* @param dataFormat
|
||||||
|
* @param noDataValue
|
||||||
|
*/
|
||||||
|
public static void createDataTexture(GLShaderProgram program, String name,
|
||||||
|
int texBinding, AbstractGLColorMapDataFormat dataFormat,
|
||||||
|
double noDataValue) {
|
||||||
|
setFieldUniform(program, name, "rawTex", texBinding);
|
||||||
|
setFieldUniform(program, name, "noDataValue", noDataValue);
|
||||||
|
setFieldUniform(program, name, "isScaled", dataFormat.isScaled());
|
||||||
|
if (dataFormat.isScaled()) {
|
||||||
|
setFieldUniform(program, name, "scaleMin",
|
||||||
|
dataFormat.getDataFormatMin());
|
||||||
|
setFieldUniform(program, name, "scaleMax",
|
||||||
|
dataFormat.getDataFormatMax());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DataMapping structure in the program with the given name
|
||||||
|
*
|
||||||
|
* @param program
|
||||||
|
* @param name
|
||||||
|
* @param dataMappingTexBinding
|
||||||
|
* @param colorMappingTexBinding
|
||||||
|
* @param numMappingValues
|
||||||
|
*/
|
||||||
|
public static void createDataMapping(GLShaderProgram program, String name,
|
||||||
|
int dataMappingTexBinding, int colorMappingTexBinding,
|
||||||
|
int numMappingValues) {
|
||||||
|
setFieldUniform(program, name, "dataMappingValues",
|
||||||
|
dataMappingTexBinding);
|
||||||
|
setFieldUniform(program, name, "colorMappingValues",
|
||||||
|
colorMappingTexBinding);
|
||||||
|
setFieldUniform(program, name, "numMappingValues", numMappingValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ColorMapping structure in the program with the given name
|
||||||
|
*
|
||||||
|
* @param program
|
||||||
|
* @param name
|
||||||
|
* @param colorMapTexBinding
|
||||||
|
* @param alphaMaskTexBinding
|
||||||
|
* @param parameters
|
||||||
|
*/
|
||||||
|
public static void createColorMapping(GLShaderProgram program, String name,
|
||||||
|
int colorMapTexBinding, int alphaMaskTexBinding,
|
||||||
|
ColorMapParameters parameters) {
|
||||||
|
setFieldUniform(program, name, "colorMap", colorMapTexBinding);
|
||||||
|
setFieldUniform(program, name, "cmapMin", parameters.getColorMapMin());
|
||||||
|
setFieldUniform(program, name, "cmapMax", parameters.getColorMapMax());
|
||||||
|
|
||||||
|
setFieldUniform(program, name, "applyMask", parameters.isUseMask());
|
||||||
|
setFieldUniform(program, name, "alphaMask", alphaMaskTexBinding);
|
||||||
|
|
||||||
|
setFieldUniform(program, name, "isMirrored", parameters.isMirror());
|
||||||
|
setFieldUniform(program, name, "isLogarithmic",
|
||||||
|
parameters.isLogarithmic());
|
||||||
|
setFieldUniform(program, name, "logFactor", parameters.getLogFactor());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a ColorModifiers structure in the program with the given name
|
||||||
|
*
|
||||||
|
* @param program
|
||||||
|
* @param name
|
||||||
|
* @param alpha
|
||||||
|
* @param brightness
|
||||||
|
* @param contrast
|
||||||
|
*/
|
||||||
|
public static void createColorModifiers(GLShaderProgram program,
|
||||||
|
String name, float alpha, float brightness, float contrast) {
|
||||||
|
setFieldUniform(program, name, "alpha", alpha);
|
||||||
|
setFieldUniform(program, name, "brightness", brightness);
|
||||||
|
setFieldUniform(program, name, "contrast", contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setFieldUniform(GLShaderProgram program,
|
||||||
|
String structName, String fieldName, Object fieldValue) {
|
||||||
|
program.setUniform(structName + FIELD_SEPERATOR + fieldName, fieldValue);
|
||||||
|
}
|
||||||
|
}
|
|
@ -155,7 +155,6 @@ public class GLShaderProgram {
|
||||||
gl.glUseProgram(0);
|
gl.glUseProgram(0);
|
||||||
state = State.INITIALIZED;
|
state = State.INITIALIZED;
|
||||||
}
|
}
|
||||||
loadedUniforms.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -358,6 +357,7 @@ public class GLShaderProgram {
|
||||||
glslContext = -1;
|
glslContext = -1;
|
||||||
}
|
}
|
||||||
state = State.INVALID;
|
state = State.INVALID;
|
||||||
|
loadedUniforms.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
||||||
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
import com.raytheon.uf.viz.core.drawables.IColormappedImage;
|
||||||
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
import com.raytheon.uf.viz.core.drawables.ext.IImagingExtension;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
|
import com.raytheon.viz.core.gl.dataformat.AbstractGLColorMapDataFormat;
|
||||||
|
import com.raytheon.viz.core.gl.ext.imaging.GLDataMappingFactory.GLDataMapping;
|
||||||
import com.sun.opengl.util.texture.TextureCoords;
|
import com.sun.opengl.util.texture.TextureCoords;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,6 +54,8 @@ public abstract class AbstractGLColormappedImage extends AbstractGLImage
|
||||||
|
|
||||||
protected GLCMTextureData data;
|
protected GLCMTextureData data;
|
||||||
|
|
||||||
|
private GLDataMapping dataMapping;
|
||||||
|
|
||||||
public AbstractGLColormappedImage(GLCMTextureData data,
|
public AbstractGLColormappedImage(GLCMTextureData data,
|
||||||
ColorMapParameters params,
|
ColorMapParameters params,
|
||||||
Class<? extends IImagingExtension> extensionClass) {
|
Class<? extends IImagingExtension> extensionClass) {
|
||||||
|
@ -143,6 +147,15 @@ public abstract class AbstractGLColormappedImage extends AbstractGLImage
|
||||||
return data.getTexId();
|
return data.getTexId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the GL format of the texture data
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public AbstractGLColorMapDataFormat getDataFormat() {
|
||||||
|
return data.getDataFormat();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the absolute minimum value of a pixel in this image. {@link Double#NaN}
|
* the absolute minimum value of a pixel in this image. {@link Double#NaN}
|
||||||
* if no absolute minimum exists
|
* if no absolute minimum exists
|
||||||
|
@ -233,6 +246,18 @@ public abstract class AbstractGLColormappedImage extends AbstractGLImage
|
||||||
data.dispose();
|
data.dispose();
|
||||||
data = null;
|
data = null;
|
||||||
}
|
}
|
||||||
|
if (dataMapping != null) {
|
||||||
|
dataMapping.dispose();
|
||||||
|
dataMapping = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataMapping(GLDataMapping dataMapping) {
|
||||||
|
this.dataMapping = dataMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GLDataMapping getDataMapping() {
|
||||||
|
return dataMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
/**
|
||||||
|
* This software was developed and / or modified by Raytheon Company,
|
||||||
|
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||||||
|
*
|
||||||
|
* U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||||||
|
* This software product contains export-restricted data whose
|
||||||
|
* export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||||||
|
* to non-U.S. persons whether in the United States or abroad requires
|
||||||
|
* an export license or other authorization.
|
||||||
|
*
|
||||||
|
* Contractor Name: Raytheon Company
|
||||||
|
* Contractor Address: 6825 Pine Street, Suite 340
|
||||||
|
* Mail Stop B8
|
||||||
|
* Omaha, NE 68106
|
||||||
|
* 402.291.0100
|
||||||
|
*
|
||||||
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
|
* further licensing information.
|
||||||
|
**/
|
||||||
|
package com.raytheon.viz.core.gl.images;
|
||||||
|
|
||||||
|
import java.nio.Buffer;
|
||||||
|
|
||||||
|
import javax.measure.unit.Unit;
|
||||||
|
import javax.media.opengl.GL;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.colormap.image.ColorMapData;
|
||||||
|
import com.raytheon.viz.core.gl.dataformat.AbstractGLColorMapDataFormat;
|
||||||
|
import com.raytheon.viz.core.gl.dataformat.GLBufferColorMapData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link GLCMTextureData} backed by a {@link Buffer}. The initial functions in
|
||||||
|
* here were moved here from {@link GLRetrievableCMTextureData}
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Oct 23, 2013 2492 mschenke Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author mschenke
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GLBufferCMTextureData extends GLCMTextureData {
|
||||||
|
|
||||||
|
public GLBufferCMTextureData(ColorMapData data,
|
||||||
|
AbstractGLColorMapDataFormat format) {
|
||||||
|
this(new GLBufferColorMapData(data, format));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GLBufferCMTextureData(GLBufferColorMapData data) {
|
||||||
|
super(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GLBufferColorMapData getDataObject() {
|
||||||
|
return (GLBufferColorMapData) super.getDataObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see com.raytheon.viz.core.gl.images.GLCMTextureData#isStaged()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean isStaged() {
|
||||||
|
GLBufferColorMapData data = getDataObject();
|
||||||
|
// Override since we have our required data
|
||||||
|
return data != null && data.getData() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
if (isStaged()) {
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* com.raytheon.viz.core.gl.images.GLCMTextureData#uploadTexture2D(javax
|
||||||
|
* .media.opengl.GL, int, int, int)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void createTexture2D(GL gl, int type, int w, int h) {
|
||||||
|
gl.glTexImage2D(type, 0, getTextureInternalFormat(), w, h, 0,
|
||||||
|
getTextureFormat(), getTextureType(), getDataObject().getData()
|
||||||
|
.rewind());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* com.raytheon.viz.core.gl.images.GLCMTextureData#uploadTexture1D(javax
|
||||||
|
* .media.opengl.GL, int, int)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void createTexture1D(GL gl, int type, int w) {
|
||||||
|
gl.glTexImage1D(type, 0, getTextureInternalFormat(), w, 0,
|
||||||
|
getTextureFormat(), getTextureType(), getDataObject().getData()
|
||||||
|
.rewind());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the data value at the given coordinates. TODO: Add support for 1D
|
||||||
|
* texture sampling, change x,y to int[] index?
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public double getValue(int x, int y) {
|
||||||
|
double value = Double.NaN;
|
||||||
|
if (isStaged()) {
|
||||||
|
value = getDataObject().getValue(x, y).doubleValue();
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Unit} associated with the data
|
||||||
|
*
|
||||||
|
* @return the dataUnit
|
||||||
|
*/
|
||||||
|
public Unit<?> getDataUnit() {
|
||||||
|
GLBufferColorMapData data = getDataObject();
|
||||||
|
return data != null ? data.getDataUnit() : null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import javax.media.opengl.GL;
|
||||||
|
|
||||||
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
|
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
|
import com.raytheon.viz.core.gl.dataformat.AbstractGLColorMapDataFormat;
|
||||||
import com.raytheon.viz.core.gl.dataformat.GLColorMapData;
|
import com.raytheon.viz.core.gl.dataformat.GLColorMapData;
|
||||||
import com.raytheon.viz.core.gl.objects.GLTextureObject;
|
import com.raytheon.viz.core.gl.objects.GLTextureObject;
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ import com.raytheon.viz.core.gl.objects.GLTextureObject;
|
||||||
* format for offscreen textures.
|
* format for offscreen textures.
|
||||||
* Oct 16, 2013 2333 mschenke Moved retrievable/Buffer parts out and
|
* Oct 16, 2013 2333 mschenke Moved retrievable/Buffer parts out and
|
||||||
* into separate class.
|
* into separate class.
|
||||||
|
* Oct 23, 2013 2492 mschenke Added support for 1D textures
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -116,6 +118,9 @@ public class GLCMTextureData {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int type = getTextureStorageType();
|
int type = getTextureStorageType();
|
||||||
|
if (type == GL.GL_NONE) {
|
||||||
|
throw new VizException("Unsupported dimension size for texture");
|
||||||
|
}
|
||||||
|
|
||||||
tex = new GLTextureObject(this);
|
tex = new GLTextureObject(this);
|
||||||
tex.bind(gl, type);
|
tex.bind(gl, type);
|
||||||
|
@ -125,7 +130,8 @@ public class GLCMTextureData {
|
||||||
gl.glTexParameteri(type, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
|
gl.glTexParameteri(type, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
|
||||||
gl.glTexParameteri(type, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
|
gl.glTexParameteri(type, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
|
||||||
|
|
||||||
if (isDataFormatScaled() && isDataFormatSigned()) {
|
boolean changeScaleAndBias = isDataFormatScaled() && isDataFormatSigned();
|
||||||
|
if (changeScaleAndBias) {
|
||||||
// GL maps signed data into the range -1 to 1, but gl trims
|
// GL maps signed data into the range -1 to 1, but gl trims
|
||||||
// this to a valid range of 0 to 1, essentially removing
|
// this to a valid range of 0 to 1, essentially removing
|
||||||
// negative values. Adding a scale and bias remaps this from
|
// negative values. Adding a scale and bias remaps this from
|
||||||
|
@ -135,20 +141,23 @@ public class GLCMTextureData {
|
||||||
gl.glPixelTransferf(GL.GL_RED_BIAS, 0.5f);
|
gl.glPixelTransferf(GL.GL_RED_BIAS, 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
int w = getDimensionSize(0);
|
if (type == GL.GL_TEXTURE_1D) {
|
||||||
int h = getDimensionSize(1);
|
createTexture1D(gl, type, getDimensionSize(0));
|
||||||
|
} else if (type == GL.GL_TEXTURE_2D) {
|
||||||
|
createTexture2D(gl, type, getDimensionSize(0), getDimensionSize(1));
|
||||||
|
}
|
||||||
|
|
||||||
createTexture2D(gl, type, w, h);
|
if (changeScaleAndBias) {
|
||||||
|
gl.glPixelTransferf(GL.GL_RED_SCALE, 1.0f);
|
||||||
gl.glPixelTransferf(GL.GL_RED_SCALE, 1.0f);
|
gl.glPixelTransferf(GL.GL_RED_BIAS, 0.0f);
|
||||||
gl.glPixelTransferf(GL.GL_RED_BIAS, 0.0f);
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a 2D texture for type, with width/height w/h. Texture object must
|
* Creates a 2D texture for type, with width/height, w/h. Texture object
|
||||||
* be bound for this call to work using
|
* must be bound for this call to work using
|
||||||
* {@link GLTextureObject#bind(GL, int)}
|
* {@link GLTextureObject#bind(GL, int)}
|
||||||
*
|
*
|
||||||
* @param gl
|
* @param gl
|
||||||
|
@ -163,6 +172,22 @@ public class GLCMTextureData {
|
||||||
getTextureFormat(), getTextureType(), null);
|
getTextureFormat(), getTextureType(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a 1D texture for type, with width, w. Texture object must be
|
||||||
|
* bound for this call to work using {@link GLTextureObject#bind(GL, int)}
|
||||||
|
*
|
||||||
|
* @param gl
|
||||||
|
* @param type
|
||||||
|
* @param w
|
||||||
|
* @param h
|
||||||
|
*/
|
||||||
|
protected void createTexture1D(GL gl, int type, int w) {
|
||||||
|
// Allocate our space on the graphics card, no buffer to upload so it
|
||||||
|
// will be filled with default values initially (0s)
|
||||||
|
gl.glTexImage1D(type, 0, getTextureInternalFormat(), w, 0,
|
||||||
|
getTextureFormat(), getTextureType(), null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if texture data is staged. If false, a call to
|
* Checks if texture data is staged. If false, a call to
|
||||||
* {@link #stageTexture()} is needed before texture can be loaded
|
* {@link #stageTexture()} is needed before texture can be loaded
|
||||||
|
@ -184,6 +209,15 @@ public class GLCMTextureData {
|
||||||
return tex != null && tex.isValid();
|
return tex != null && tex.isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the GL format of the texture data
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public AbstractGLColorMapDataFormat getDataFormat() {
|
||||||
|
return data.getDataFormat();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size of the dimension index passed in (0=width,1=height)
|
* Returns the size of the dimension index passed in (0=width,1=height)
|
||||||
*
|
*
|
||||||
|
@ -272,12 +306,20 @@ public class GLCMTextureData {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The texture storage type of the data (TEXTURE_2D)
|
* The texture storage type of the data. Will return {@link GL#GL_NONE} if
|
||||||
|
* unsupported dimension is detected
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public int getTextureStorageType() {
|
public int getTextureStorageType() {
|
||||||
return GL.GL_TEXTURE_2D;
|
switch (data.getNumDimensions()) {
|
||||||
|
case 1:
|
||||||
|
return GL.GL_TEXTURE_1D;
|
||||||
|
case 2:
|
||||||
|
return GL.GL_TEXTURE_2D;
|
||||||
|
default:
|
||||||
|
return GL.GL_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -38,8 +38,9 @@ import com.raytheon.viz.core.gl.internal.cache.ImageCache;
|
||||||
import com.raytheon.viz.core.gl.internal.cache.ImageCache.CacheType;
|
import com.raytheon.viz.core.gl.internal.cache.ImageCache.CacheType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object that represents a colormapped texture that can be unloaded and
|
* {@link GLCMTextureData} that's backed by a {@link Buffer} that represents a
|
||||||
* reloaded from main/graphics memory using a retrieval callback
|
* colormapped texture that is cacheable and can be unloaded and reloaded from
|
||||||
|
* main/graphics memory using a retrieval callback
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
|
@ -47,7 +48,8 @@ import com.raytheon.viz.core.gl.internal.cache.ImageCache.CacheType;
|
||||||
*
|
*
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Jun 24, 2013 mschenke Initial creation
|
* Jun 24, 2013 mschenke Initial creation
|
||||||
|
* Oct 23, 2013 2492 mschenke Extracted Buffer backing into super class
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -55,7 +57,7 @@ import com.raytheon.viz.core.gl.internal.cache.ImageCache.CacheType;
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class GLRetrievableCMTextureData extends GLCMTextureData implements
|
public class GLRetrievableCMTextureData extends GLBufferCMTextureData implements
|
||||||
IImageCacheable {
|
IImageCacheable {
|
||||||
|
|
||||||
private static Map<IColorMapDataRetrievalCallback, GLRetrievableCMTextureData> texMap = new HashMap<IColorMapDataRetrievalCallback, GLRetrievableCMTextureData>();
|
private static Map<IColorMapDataRetrievalCallback, GLRetrievableCMTextureData> texMap = new HashMap<IColorMapDataRetrievalCallback, GLRetrievableCMTextureData>();
|
||||||
|
@ -95,11 +97,6 @@ public class GLRetrievableCMTextureData extends GLCMTextureData implements
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected GLBufferColorMapData getDataObject() {
|
|
||||||
return (GLBufferColorMapData) super.getDataObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
|
@ -224,18 +221,6 @@ public class GLRetrievableCMTextureData extends GLCMTextureData implements
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see com.raytheon.viz.core.gl.images.GLCMTextureData#isStaged()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isStaged() {
|
|
||||||
GLBufferColorMapData data = getDataObject();
|
|
||||||
// Override since we have our required data
|
|
||||||
return data != null && data.getData() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getValue(int x, int y) {
|
public double getValue(int x, int y) {
|
||||||
GLBufferColorMapData data = getDataObject();
|
GLBufferColorMapData data = getDataObject();
|
||||||
double value = Double.NaN;
|
double value = Double.NaN;
|
||||||
|
@ -265,27 +250,4 @@ public class GLRetrievableCMTextureData extends GLCMTextureData implements
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see
|
|
||||||
* com.raytheon.viz.core.gl.images.GLCMTextureData#uploadTexture2D(javax
|
|
||||||
* .media.opengl.GL, int, int, int)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void createTexture2D(GL gl, int type, int w, int h) {
|
|
||||||
gl.glTexImage2D(type, 0, getTextureInternalFormat(), w, h, 0,
|
|
||||||
getTextureFormat(), getTextureType(), getDataObject().getData()
|
|
||||||
.rewind());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link Unit} associated with the data
|
|
||||||
*
|
|
||||||
* @return the dataUnit
|
|
||||||
*/
|
|
||||||
public Unit<?> getDataUnit() {
|
|
||||||
GLBufferColorMapData data = getDataObject();
|
|
||||||
return data != null ? data.getDataUnit() : null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||||
import com.raytheon.uf.common.colormap.ColorMap;
|
import com.raytheon.uf.common.colormap.ColorMap;
|
||||||
import com.raytheon.uf.common.colormap.IColorMap;
|
import com.raytheon.uf.common.colormap.IColorMap;
|
||||||
import com.raytheon.uf.common.colormap.image.ColorMapData;
|
import com.raytheon.uf.common.colormap.image.ColorMapData;
|
||||||
|
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
|
||||||
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
|
@ -67,7 +68,6 @@ import com.raytheon.uf.viz.core.DrawableString;
|
||||||
import com.raytheon.uf.viz.core.IExtent;
|
import com.raytheon.uf.viz.core.IExtent;
|
||||||
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
import com.raytheon.uf.viz.core.IGraphicsTarget;
|
||||||
import com.raytheon.uf.viz.core.IView;
|
import com.raytheon.uf.viz.core.IView;
|
||||||
import com.raytheon.uf.viz.core.data.IColorMapDataRetrievalCallback;
|
|
||||||
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
import com.raytheon.uf.viz.core.data.IRenderedImageCallback;
|
||||||
import com.raytheon.uf.viz.core.drawables.IDescriptor;
|
import com.raytheon.uf.viz.core.drawables.IDescriptor;
|
||||||
import com.raytheon.uf.viz.core.drawables.IFont;
|
import com.raytheon.uf.viz.core.drawables.IFont;
|
||||||
|
@ -86,11 +86,12 @@ import com.raytheon.viz.core.gl.GLDisposalManager;
|
||||||
import com.raytheon.viz.core.gl.GLStats;
|
import com.raytheon.viz.core.gl.GLStats;
|
||||||
import com.raytheon.viz.core.gl.IGLFont;
|
import com.raytheon.viz.core.gl.IGLFont;
|
||||||
import com.raytheon.viz.core.gl.IGLTarget;
|
import com.raytheon.viz.core.gl.IGLTarget;
|
||||||
import com.raytheon.viz.core.gl.ext.imaging.GLColormappedImageExtension;
|
import com.raytheon.viz.core.gl.dataformat.GLByteDataFormat;
|
||||||
import com.raytheon.viz.core.gl.ext.imaging.GLDefaultImagingExtension;
|
import com.raytheon.viz.core.gl.ext.imaging.GLDefaultImagingExtension;
|
||||||
import com.raytheon.viz.core.gl.glsl.GLSLFactory;
|
import com.raytheon.viz.core.gl.glsl.GLSLFactory;
|
||||||
|
import com.raytheon.viz.core.gl.glsl.GLSLStructFactory;
|
||||||
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
import com.raytheon.viz.core.gl.glsl.GLShaderProgram;
|
||||||
import com.raytheon.viz.core.gl.images.GLColormappedImage;
|
import com.raytheon.viz.core.gl.images.GLBufferCMTextureData;
|
||||||
import com.raytheon.viz.core.gl.images.GLImage;
|
import com.raytheon.viz.core.gl.images.GLImage;
|
||||||
import com.raytheon.viz.core.gl.objects.GLTextureObject;
|
import com.raytheon.viz.core.gl.objects.GLTextureObject;
|
||||||
import com.sun.opengl.util.Screenshot;
|
import com.sun.opengl.util.Screenshot;
|
||||||
|
@ -128,6 +129,7 @@ import com.sun.opengl.util.j2d.TextRenderer;
|
||||||
* strings are always readable despite extent
|
* strings are always readable despite extent
|
||||||
* May 28, 2013 1638 mschenke Made sure {@link TextStyle#BLANKED} text is drawing correct size
|
* May 28, 2013 1638 mschenke Made sure {@link TextStyle#BLANKED} text is drawing correct size
|
||||||
* box around text
|
* box around text
|
||||||
|
* Nov 4, 2013 2492 mschenke Switched colormap drawing to use 1D texture object for alpha mask
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -517,28 +519,19 @@ public class GLTarget extends AbstractGraphicsTarget implements IGLTarget {
|
||||||
|
|
||||||
GLTextureObject i = getColorMapTexture(colorMapParams);
|
GLTextureObject i = getColorMapTexture(colorMapParams);
|
||||||
|
|
||||||
GLColormappedImage alphaMaskTexture = null;
|
GLBufferCMTextureData alphaMaskTexture = null;
|
||||||
if (colorMapParams.isUseMask() && capabilities.cardSupportsShaders) {
|
if (colorMapParams.isUseMask() && capabilities.cardSupportsShaders) {
|
||||||
final byte[] mask = colorMapParams.getAlphaMask();
|
byte[] mask = colorMapParams.getAlphaMask();
|
||||||
alphaMaskTexture = getExtension(
|
alphaMaskTexture = new GLBufferCMTextureData(new ColorMapData(
|
||||||
GLColormappedImageExtension.class).initializeRaster(
|
ByteBuffer.wrap(mask), new int[] { mask.length },
|
||||||
new IColorMapDataRetrievalCallback() {
|
ColorMapDataType.BYTE), new GLByteDataFormat());
|
||||||
@Override
|
|
||||||
public ColorMapData getColorMapData()
|
|
||||||
throws VizException {
|
|
||||||
return new ColorMapData(ByteBuffer.wrap(mask),
|
|
||||||
new int[] { mask.length, 1 });
|
|
||||||
}
|
|
||||||
|
|
||||||
}, colorMapParams);
|
|
||||||
alphaMaskTexture.stage();
|
|
||||||
alphaMaskTexture.target(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alphaMaskTexture != null) {
|
|
||||||
gl.glActiveTexture(GL.GL_TEXTURE1);
|
gl.glActiveTexture(GL.GL_TEXTURE1);
|
||||||
gl.glBindTexture(alphaMaskTexture.getTextureStorageType(),
|
if (alphaMaskTexture.loadTexture(gl)) {
|
||||||
alphaMaskTexture.getTextureid());
|
gl.glBindTexture(alphaMaskTexture.getTextureStorageType(),
|
||||||
|
alphaMaskTexture.getTexId());
|
||||||
|
} else {
|
||||||
|
alphaMaskTexture.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.glPolygonMode(GL.GL_BACK, GL.GL_FILL);
|
gl.glPolygonMode(GL.GL_BACK, GL.GL_FILL);
|
||||||
|
@ -573,14 +566,11 @@ public class GLTarget extends AbstractGraphicsTarget implements IGLTarget {
|
||||||
"colormap");
|
"colormap");
|
||||||
if (program != null) {
|
if (program != null) {
|
||||||
program.startShader();
|
program.startShader();
|
||||||
program.setUniform("alphaVal", blendAlpha);
|
|
||||||
program.setUniform("brightness", brightness);
|
GLSLStructFactory.createColorMapping(program,
|
||||||
program.setUniform("contrast", contrast);
|
"colorMapping", 0, 1, colorMapParams);
|
||||||
program.setUniform("colorMap", 0);
|
GLSLStructFactory.createColorModifiers(program,
|
||||||
program.setUniform("logFactor", logFactor);
|
"modifiers", blendAlpha, brightness, contrast);
|
||||||
program.setUniform("alphaMask", 1);
|
|
||||||
program.setUniform("applyMask",
|
|
||||||
colorMapParams.isUseMask() ? 1 : 0);
|
|
||||||
program.setUniform("bkgrndRed",
|
program.setUniform("bkgrndRed",
|
||||||
backgroundColor.red / 255.0f);
|
backgroundColor.red / 255.0f);
|
||||||
program.setUniform("bkgrndGreen",
|
program.setUniform("bkgrndGreen",
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.text.DecimalFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import javax.measure.converter.UnitConverter;
|
import javax.measure.converter.UnitConverter;
|
||||||
import javax.measure.unit.NonSI;
|
|
||||||
import javax.measure.unit.SI;
|
import javax.measure.unit.SI;
|
||||||
import javax.measure.unit.Unit;
|
import javax.measure.unit.Unit;
|
||||||
import javax.measure.unit.UnitFormat;
|
import javax.measure.unit.UnitFormat;
|
||||||
|
@ -40,10 +39,10 @@ import com.raytheon.uf.common.datastorage.IDataStore;
|
||||||
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
||||||
import com.raytheon.uf.common.style.LabelingPreferences;
|
import com.raytheon.uf.common.style.LabelingPreferences;
|
||||||
import com.raytheon.uf.common.style.ParamLevelMatchCriteria;
|
import com.raytheon.uf.common.style.ParamLevelMatchCriteria;
|
||||||
|
import com.raytheon.uf.common.style.StyleException;
|
||||||
import com.raytheon.uf.common.style.StyleManager;
|
import com.raytheon.uf.common.style.StyleManager;
|
||||||
import com.raytheon.uf.common.style.StyleManager.StyleType;
|
import com.raytheon.uf.common.style.StyleManager.StyleType;
|
||||||
import com.raytheon.uf.common.style.StyleRule;
|
import com.raytheon.uf.common.style.StyleRule;
|
||||||
import com.raytheon.uf.common.style.StyleException;
|
|
||||||
import com.raytheon.uf.common.style.image.DataScale;
|
import com.raytheon.uf.common.style.image.DataScale;
|
||||||
import com.raytheon.uf.common.style.image.ImagePreferences;
|
import com.raytheon.uf.common.style.image.ImagePreferences;
|
||||||
import com.raytheon.uf.common.style.image.SamplePreferences;
|
import com.raytheon.uf.common.style.image.SamplePreferences;
|
||||||
|
@ -148,7 +147,8 @@ public class TopoResource extends
|
||||||
|
|
||||||
// Set data unit, specify in resource data? Look up in data record?
|
// Set data unit, specify in resource data? Look up in data record?
|
||||||
params.setDataUnit(SI.METER);
|
params.setDataUnit(SI.METER);
|
||||||
params.setDisplayUnit(NonSI.FOOT);
|
params.setDisplayUnit(SI.METER);
|
||||||
|
params.setColorMapUnit(SI.METER);
|
||||||
params.setColorMapMin(-19);
|
params.setColorMapMin(-19);
|
||||||
params.setColorMapMax(5000);
|
params.setColorMapMax(5000);
|
||||||
params.setDataMin(Short.MIN_VALUE);
|
params.setDataMin(Short.MIN_VALUE);
|
||||||
|
@ -169,15 +169,17 @@ public class TopoResource extends
|
||||||
|
|
||||||
DataScale scale = prefs.getDataScale();
|
DataScale scale = prefs.getDataScale();
|
||||||
if (scale != null) {
|
if (scale != null) {
|
||||||
|
UnitConverter displayToColorMap = params
|
||||||
|
.getDisplayToColorMapConverter();
|
||||||
Double minVal = scale.getMinValue();
|
Double minVal = scale.getMinValue();
|
||||||
Double maxVal = scale.getMaxValue();
|
Double maxVal = scale.getMaxValue();
|
||||||
if (minVal != null) {
|
if (minVal != null) {
|
||||||
params.setColorMapMin((float) params
|
params.setColorMapMin((float) displayToColorMap
|
||||||
.getDisplayToDataConverter().convert(minVal));
|
.convert(minVal));
|
||||||
}
|
}
|
||||||
if (maxVal != null) {
|
if (maxVal != null) {
|
||||||
params.setColorMapMax((float) params
|
params.setColorMapMax((float) displayToColorMap
|
||||||
.getDisplayToDataConverter().convert(maxVal));
|
.convert(maxVal));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,21 +35,27 @@ import java.nio.IntBuffer;
|
||||||
import java.nio.ShortBuffer;
|
import java.nio.ShortBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.measure.converter.UnitConverter;
|
||||||
|
import javax.measure.unit.Unit;
|
||||||
|
|
||||||
import com.raytheon.uf.common.colormap.Color;
|
import com.raytheon.uf.common.colormap.Color;
|
||||||
import com.raytheon.uf.common.colormap.IColorMap;
|
import com.raytheon.uf.common.colormap.IColorMap;
|
||||||
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
|
import com.raytheon.uf.common.colormap.image.ColorMapData.ColorMapDataType;
|
||||||
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
import com.raytheon.uf.common.colormap.prefs.ColorMapParameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Colormapper class
|
* Colormapper class, written to mimic colormapRaster.glsl in java. Any changes
|
||||||
|
* to files mapping.glsl or colormapRaster.glsl will probably need to be
|
||||||
|
* reflected here
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
*
|
*
|
||||||
* SOFTWARE HISTORY
|
* SOFTWARE HISTORY
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Aug 13, 2010 mschenke Initial creation
|
* Aug 13, 2010 mschenke Initial creation
|
||||||
* Feb 15, 2013 1638 mschenke Moved IndexColorModel creation to common.colormap utility
|
* Feb 15, 2013 1638 mschenke Moved IndexColorModel creation to common.colormap utility
|
||||||
|
* Nov 4, 2013 2492 mschenke Rewritten to model glsl equivalent
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -77,39 +83,42 @@ public class Colormapper {
|
||||||
int width = cmapData.getDimensions()[0];
|
int width = cmapData.getDimensions()[0];
|
||||||
int height = cmapData.getDimensions()[1];
|
int height = cmapData.getDimensions()[1];
|
||||||
Buffer buf = cmapData.getBuffer();
|
Buffer buf = cmapData.getBuffer();
|
||||||
ColorMapDataType dataType = cmapData.getDataType();
|
|
||||||
|
|
||||||
// Parameters ported from raster.glsl
|
|
||||||
boolean log = parameters.isLogarithmic();
|
|
||||||
double logFactor = parameters.getLogFactor();
|
|
||||||
boolean mirror = parameters.isMirror();
|
|
||||||
double cmapMin = parameters.getColorMapMin();
|
|
||||||
double cmapMax = parameters.getColorMapMax();
|
|
||||||
int colorMapSz = parameters.getColorMap().getSize();
|
|
||||||
|
|
||||||
double diff = Math.abs(cmapMax - cmapMin);
|
|
||||||
|
|
||||||
int dataSize = buf.capacity();
|
int dataSize = buf.capacity();
|
||||||
byte[] cmapedData = new byte[buf.capacity()];
|
ColorMapDataType dataType = cmapData.getDataType();
|
||||||
|
double noDataValue = parameters.getNoDataValue();
|
||||||
|
Unit<?> dataUnit = cmapData.getDataUnit();
|
||||||
|
if (dataUnit == null) {
|
||||||
|
dataUnit = parameters.getDataUnit();
|
||||||
|
}
|
||||||
|
Unit<?> colorMapUnit = parameters.getColorMapUnit();
|
||||||
|
UnitConverter converter = null;
|
||||||
|
if (dataUnit != null && colorMapUnit != null
|
||||||
|
&& parameters.getDataMapping() == null
|
||||||
|
&& dataUnit.equals(colorMapUnit) == false
|
||||||
|
&& dataUnit.isCompatible(colorMapUnit) == true) {
|
||||||
|
converter = dataUnit.getConverterTo(colorMapUnit);
|
||||||
|
}
|
||||||
|
int numColors = parameters.getColorMap().getSize();
|
||||||
|
byte[] indexArray = new byte[dataSize];
|
||||||
|
|
||||||
for (int i = 0; i < dataSize; ++i) {
|
for (int i = 0; i < dataSize; ++i) {
|
||||||
double value = getValue(buf, i, dataType);
|
double dataValue = getDataValue(buf, i, dataType);
|
||||||
double index = 0.0f;
|
if (Double.isNaN(dataValue) || dataValue == noDataValue) {
|
||||||
if (log) {
|
// Skip, need equivalent of setting alpha to 0
|
||||||
index = findIndexLog(value, logFactor, cmapMin, cmapMax, mirror);
|
continue;
|
||||||
} else {
|
|
||||||
index = ((value - cmapMin) / diff);
|
|
||||||
}
|
}
|
||||||
if (index < 0.0) {
|
double cmapValue = dataValue;
|
||||||
index = 0.0;
|
if (converter != null) {
|
||||||
} else if (index > 1.0) {
|
cmapValue = converter.convert(dataValue);
|
||||||
index = 1.0;
|
|
||||||
}
|
}
|
||||||
cmapedData[i] = findColorIndex(index, logFactor, colorMapSz);
|
|
||||||
|
double index = getColorMappingIndex(cmapValue, parameters);
|
||||||
|
indexArray[i] = (byte) (capIndex(index) * (numColors - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
IndexColorModel cm = buildColorModel(parameters.getColorMap());
|
IndexColorModel cm = buildColorModel(parameters.getColorMap());
|
||||||
|
|
||||||
DataBufferByte byteArray = new DataBufferByte(cmapedData, width
|
DataBufferByte byteArray = new DataBufferByte(indexArray, width
|
||||||
* height);
|
* height);
|
||||||
|
|
||||||
MultiPixelPackedSampleModel sample = new MultiPixelPackedSampleModel(
|
MultiPixelPackedSampleModel sample = new MultiPixelPackedSampleModel(
|
||||||
|
@ -123,114 +132,6 @@ public class Colormapper {
|
||||||
return bi;
|
return bi;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double getValue(Buffer buffer, int idx,
|
|
||||||
ColorMapDataType dataType) {
|
|
||||||
switch (dataType) {
|
|
||||||
case BYTE: {
|
|
||||||
return ((ByteBuffer) buffer).get(idx) & 0xFF;
|
|
||||||
}
|
|
||||||
case SIGNED_BYTE: {
|
|
||||||
return ((ByteBuffer) buffer).get(idx);
|
|
||||||
}
|
|
||||||
case SHORT: {
|
|
||||||
return ((ShortBuffer) buffer).get(idx);
|
|
||||||
}
|
|
||||||
case UNSIGNED_SHORT: {
|
|
||||||
return ((ShortBuffer) buffer).get(idx) & 0xFFFF;
|
|
||||||
}
|
|
||||||
case INT: {
|
|
||||||
return ((IntBuffer) buffer).get(idx);
|
|
||||||
}
|
|
||||||
case FLOAT: {
|
|
||||||
return ((FloatBuffer) buffer).get(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double findIndexLog(double value, double logFactor,
|
|
||||||
double cmapMin, double cmapMax, boolean mirror) {
|
|
||||||
double index = 0.0;
|
|
||||||
// is this strictly negative, strictly positive or neg to pos scaling?
|
|
||||||
if (cmapMin >= 0.0 && cmapMax >= 0.0 && mirror == false) {
|
|
||||||
if (value < cmapMin) {
|
|
||||||
index = 0.0;
|
|
||||||
} else {
|
|
||||||
// simple calculation
|
|
||||||
index = ((Math.log(value) - Math.log(cmapMin)) / Math.abs(Math
|
|
||||||
.log(cmapMax) - Math.log(cmapMin)));
|
|
||||||
}
|
|
||||||
} else if (cmapMin <= 0.0 && cmapMax <= 0.0 && mirror == false) {
|
|
||||||
index = ((Math.log(value) - Math.log(cmapMax)) / Math.abs(Math
|
|
||||||
.log(cmapMin) - Math.log(cmapMax)));
|
|
||||||
} else {
|
|
||||||
// special case, neg to pos:
|
|
||||||
double colorMapMin = cmapMin;
|
|
||||||
double colorMapMax = cmapMax;
|
|
||||||
double zeroVal = Math.max(colorMapMax, Math.abs(colorMapMin)) * 0.0001;
|
|
||||||
if (mirror && (colorMapMin > 0.0 || colorMapMax < 0.0)) {
|
|
||||||
if (colorMapMax < 0.0) {
|
|
||||||
colorMapMax = -cmapMax;
|
|
||||||
value = -value;
|
|
||||||
zeroVal = -colorMapMin;
|
|
||||||
} else {
|
|
||||||
zeroVal = cmapMin;
|
|
||||||
}
|
|
||||||
colorMapMin = -cmapMax;
|
|
||||||
}
|
|
||||||
double leftZero = 0.0;
|
|
||||||
double rightZero = 0.0;
|
|
||||||
double absLogZeroVal = Math.abs(Math.log(zeroVal));
|
|
||||||
|
|
||||||
rightZero = absLogZeroVal + Math.log(colorMapMax);
|
|
||||||
|
|
||||||
double cmapMax2 = Math.abs(colorMapMin);
|
|
||||||
|
|
||||||
leftZero = absLogZeroVal + Math.log(cmapMax2);
|
|
||||||
|
|
||||||
double zeroIndex = leftZero / (leftZero + rightZero);
|
|
||||||
|
|
||||||
// figure out index for texture val
|
|
||||||
double absTextureColor = Math.abs(value);
|
|
||||||
if (absTextureColor <= zeroVal) {
|
|
||||||
index = zeroIndex;
|
|
||||||
} else if (value > 0.0) {
|
|
||||||
// positive texture color value, find index from 0 to
|
|
||||||
// cmapMax:
|
|
||||||
double logTexColor = absLogZeroVal + Math.log(value);
|
|
||||||
|
|
||||||
double texIndex = logTexColor / rightZero;
|
|
||||||
index = (zeroIndex + ((1.0 - zeroIndex) * texIndex));
|
|
||||||
} else {
|
|
||||||
// negative texture color value, find index from 0 to
|
|
||||||
// cmapMax:
|
|
||||||
double logTexColor = absLogZeroVal + Math.log(absTextureColor);
|
|
||||||
|
|
||||||
double texIndex = logTexColor / leftZero;
|
|
||||||
index = (zeroIndex - (zeroIndex * texIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte findColorIndex(double index, double logFactor,
|
|
||||||
int colorMapSz) {
|
|
||||||
if (logFactor > 0.0) {
|
|
||||||
double minLog = Math.log(logFactor);
|
|
||||||
double maxLog = Math.log(logFactor + 1.0);
|
|
||||||
|
|
||||||
double lg = Math.log(logFactor + index);
|
|
||||||
|
|
||||||
index = (lg - minLog) / (maxLog - minLog);
|
|
||||||
if (index < 0.0) {
|
|
||||||
index = 0.0;
|
|
||||||
} else if (index > 1.0) {
|
|
||||||
index = 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (byte) (index * (colorMapSz - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a color model from a color map
|
* Builds a color model from a color map
|
||||||
*
|
*
|
||||||
|
@ -256,4 +157,264 @@ public class Colormapper {
|
||||||
return new IndexColorModel(COLOR_MODEL_NUMBER_BITS, size, red, green,
|
return new IndexColorModel(COLOR_MODEL_NUMBER_BITS, size, red, green,
|
||||||
blue, alpha);
|
blue, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an index value into the indexArray for use in a Raster with
|
||||||
|
* IndexColorModel set
|
||||||
|
*
|
||||||
|
* @param dataArray
|
||||||
|
* @param idx
|
||||||
|
* @param idxValue
|
||||||
|
*/
|
||||||
|
public static void setIndexValue(Object dataArray, int idx, int idxValue) {
|
||||||
|
if (dataArray instanceof byte[]) {
|
||||||
|
((byte[]) dataArray)[idx] = (byte) idxValue;
|
||||||
|
} else if (dataArray instanceof short[]) {
|
||||||
|
((short[]) dataArray)[idx] = (short) idxValue;
|
||||||
|
} else if (dataArray instanceof int[]) {
|
||||||
|
((int[]) dataArray)[idx] = idxValue;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unsupported dataArray type: "
|
||||||
|
+ (dataArray != null ? dataArray.getClass() : null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the double representation of the data value for the Buffer at the
|
||||||
|
* given index
|
||||||
|
*
|
||||||
|
* @param buffer
|
||||||
|
* @param idx
|
||||||
|
* @param dataType
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double getDataValue(Buffer buffer, int idx,
|
||||||
|
ColorMapDataType dataType) {
|
||||||
|
switch (dataType) {
|
||||||
|
case BYTE: {
|
||||||
|
return ((ByteBuffer) buffer).get(idx) & 0xFF;
|
||||||
|
}
|
||||||
|
case SIGNED_BYTE: {
|
||||||
|
return ((ByteBuffer) buffer).get(idx);
|
||||||
|
}
|
||||||
|
case SHORT: {
|
||||||
|
return ((ShortBuffer) buffer).get(idx);
|
||||||
|
}
|
||||||
|
case UNSIGNED_SHORT: {
|
||||||
|
return ((ShortBuffer) buffer).get(idx) & 0xFFFF;
|
||||||
|
}
|
||||||
|
case INT: {
|
||||||
|
return ((IntBuffer) buffer).get(idx);
|
||||||
|
}
|
||||||
|
case FLOAT: {
|
||||||
|
return ((FloatBuffer) buffer).get(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function takes an index value and caps it to the range 0-1
|
||||||
|
*/
|
||||||
|
public static double capIndex(double index) {
|
||||||
|
if (index < 0.0) {
|
||||||
|
index = 0.0;
|
||||||
|
} else if (index > 1.0) {
|
||||||
|
index = 1.0;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a colorMap value linearly determine the index into cmapMin/cmapMax
|
||||||
|
*
|
||||||
|
* @param cmapValue
|
||||||
|
* @param cmapMin
|
||||||
|
* @param cmapMax
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double getLinearIndex(double cmapValue, double cmapMin,
|
||||||
|
double cmapMax) {
|
||||||
|
return (cmapValue - cmapMin) / (cmapMax - cmapMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function logarithmically finds the index for the cmapValue into
|
||||||
|
* cmapMin/cmapMax.
|
||||||
|
*
|
||||||
|
* @param cmapValue
|
||||||
|
* @param cmapMin
|
||||||
|
* @param cmapMax
|
||||||
|
* @param mirror
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double getLogIndex(double cmapValue, double cmapMin,
|
||||||
|
double cmapMax, boolean mirror) {
|
||||||
|
double index = 0.0;
|
||||||
|
// is this strictly negative, strictly positive or neg to pos scaling?
|
||||||
|
if (cmapMin >= 0.0 && cmapMax >= 0.0 && !mirror) {
|
||||||
|
if (cmapValue < cmapMin) {
|
||||||
|
index = 0.0;
|
||||||
|
} else {
|
||||||
|
// simple calculation
|
||||||
|
index = ((Math.log(cmapValue) - Math.log(cmapMin)) / Math
|
||||||
|
.abs(Math.log(cmapMax) - Math.log(cmapMin)));
|
||||||
|
}
|
||||||
|
} else if (cmapMin <= 0.0 && cmapMax <= 0.0 && !mirror) {
|
||||||
|
index = ((Math.log(cmapValue) - Math.log(cmapMax)) / Math.abs(Math
|
||||||
|
.log(cmapMin) - Math.log(cmapMax)));
|
||||||
|
} else {
|
||||||
|
// special case, neg to pos:
|
||||||
|
double colorMapMin = cmapMin;
|
||||||
|
double colorMapMax = cmapMax;
|
||||||
|
double zeroVal = Math.max(colorMapMax, Math.abs(colorMapMin)) * 0.0001;
|
||||||
|
if (mirror && (colorMapMin > 0.0 || colorMapMax < 0.0)) {
|
||||||
|
if (colorMapMax < 0.0) {
|
||||||
|
colorMapMax = -cmapMax;
|
||||||
|
cmapValue = -cmapValue;
|
||||||
|
zeroVal = -colorMapMin;
|
||||||
|
} else {
|
||||||
|
zeroVal = cmapMin;
|
||||||
|
}
|
||||||
|
colorMapMin = -cmapMax;
|
||||||
|
}
|
||||||
|
double leftZero = 0.0;
|
||||||
|
double rightZero = 0.0;
|
||||||
|
double absLogZeroVal = Math.abs(Math.log(zeroVal));
|
||||||
|
|
||||||
|
rightZero = absLogZeroVal + Math.log(colorMapMax);
|
||||||
|
|
||||||
|
double cmapMax2 = Math.abs(colorMapMin);
|
||||||
|
|
||||||
|
leftZero = absLogZeroVal + Math.log(cmapMax2);
|
||||||
|
|
||||||
|
double zeroIndex = leftZero / (leftZero + rightZero);
|
||||||
|
|
||||||
|
// figure out index for texture val
|
||||||
|
double absTextureColor = Math.abs(cmapValue);
|
||||||
|
if (absTextureColor <= zeroVal) {
|
||||||
|
index = zeroIndex;
|
||||||
|
} else if (cmapValue > 0.0) {
|
||||||
|
// positive texture color value, find index from 0 to
|
||||||
|
// cmapMax:
|
||||||
|
double logTexColor = absLogZeroVal + Math.log(cmapValue);
|
||||||
|
|
||||||
|
double texIndex = logTexColor / rightZero;
|
||||||
|
index = (zeroIndex + ((1.0 - zeroIndex) * texIndex));
|
||||||
|
} else {
|
||||||
|
// negative texture color value, find index from 0 to
|
||||||
|
// cmapMax:
|
||||||
|
double logTexColor = absLogZeroVal + Math.log(absTextureColor);
|
||||||
|
|
||||||
|
double texIndex = logTexColor / leftZero;
|
||||||
|
index = (zeroIndex - (zeroIndex * texIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function calculates a new index to use based on the logFactor and
|
||||||
|
* passed in index
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* @param logFactor
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double getLogFactorIndex(double index, double logFactor) {
|
||||||
|
if (logFactor > 0.0) {
|
||||||
|
double minLog = Math.log(logFactor);
|
||||||
|
double maxLog = Math.log(logFactor + 1.0);
|
||||||
|
|
||||||
|
double lg = Math.log(logFactor + index);
|
||||||
|
|
||||||
|
index = (lg - minLog) / (maxLog - minLog);
|
||||||
|
if (index < 0.0) {
|
||||||
|
index = 0.0;
|
||||||
|
} else if (index > 1.0) {
|
||||||
|
index = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an index for the cmapValue based on the
|
||||||
|
* {@link ColorMapParameters}
|
||||||
|
*
|
||||||
|
* @param cmapValue
|
||||||
|
* @param colorMapping
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double getColorMappingIndex(double cmapValue,
|
||||||
|
ColorMapParameters colorMapParameters) {
|
||||||
|
double logFactor = colorMapParameters.getLogFactor();
|
||||||
|
double cmapMin = colorMapParameters.getColorMapMin();
|
||||||
|
double cmapMax = colorMapParameters.getColorMapMax();
|
||||||
|
|
||||||
|
double index;
|
||||||
|
if (colorMapParameters.isLogarithmic()) {
|
||||||
|
index = getLogIndex(cmapValue, cmapMin, cmapMax,
|
||||||
|
colorMapParameters.isMirror());
|
||||||
|
} else {
|
||||||
|
index = getLinearIndex(cmapValue, cmapMin, cmapMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply logFactor if set
|
||||||
|
if (logFactor > 0.0) {
|
||||||
|
index = getLogFactorIndex(index, logFactor);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link Color} from the color map in the parameters at the index
|
||||||
|
* (capped 0-1) passed in
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* @param colorMapParameters
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Color getColorByIndex(double index,
|
||||||
|
ColorMapParameters colorMapParameters) {
|
||||||
|
index = capIndex(index);
|
||||||
|
IColorMap colorMap = colorMapParameters.getColorMap();
|
||||||
|
if (colorMapParameters.isInterpolate()) {
|
||||||
|
index = 0.5f;
|
||||||
|
index = (index * (colorMap.getSize() - 1));
|
||||||
|
int lowIndex = (int) Math.floor(index);
|
||||||
|
int highIndex = (int) Math.ceil(index);
|
||||||
|
double lowWeight = highIndex - index;
|
||||||
|
double highWeight = 1.0f - lowWeight;
|
||||||
|
Color low = colorMap.getColors().get(lowIndex);
|
||||||
|
Color high = colorMap.getColors().get(highIndex);
|
||||||
|
float r = (float) (lowWeight * low.getRed() + highWeight
|
||||||
|
* high.getRed());
|
||||||
|
float g = (float) (lowWeight * low.getGreen() + highWeight
|
||||||
|
* high.getGreen());
|
||||||
|
float b = (float) (lowWeight * low.getBlue() + highWeight
|
||||||
|
* high.getBlue());
|
||||||
|
float a = (float) (lowWeight * low.getAlpha() + highWeight
|
||||||
|
* high.getAlpha());
|
||||||
|
return new Color(r, g, b, a);
|
||||||
|
} else {
|
||||||
|
return colorMap.getColors().get(
|
||||||
|
(int) (index * (colorMap.getSize() - 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link Color} for the cmapValue based on the
|
||||||
|
* {@link ColorMapParameters}
|
||||||
|
*
|
||||||
|
* @param cmapValue
|
||||||
|
* @param colorMapParameters
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Color getColorByValue(double cmapValue,
|
||||||
|
ColorMapParameters colorMapParameters) {
|
||||||
|
return getColorByIndex(
|
||||||
|
getColorMappingIndex(cmapValue, colorMapParameters),
|
||||||
|
colorMapParameters);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,9 @@ package com.raytheon.uf.common.colormap.prefs;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.measure.converter.UnitConverter;
|
import javax.measure.converter.UnitConverter;
|
||||||
|
@ -35,8 +37,8 @@ import javax.xml.bind.annotation.XmlElement;
|
||||||
import com.raytheon.uf.common.colormap.AbstractColorMap;
|
import com.raytheon.uf.common.colormap.AbstractColorMap;
|
||||||
import com.raytheon.uf.common.colormap.Color;
|
import com.raytheon.uf.common.colormap.Color;
|
||||||
import com.raytheon.uf.common.colormap.IColorMap;
|
import com.raytheon.uf.common.colormap.IColorMap;
|
||||||
|
import com.raytheon.uf.common.colormap.image.Colormapper;
|
||||||
import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences.DataMappingEntry;
|
import com.raytheon.uf.common.colormap.prefs.DataMappingPreferences.DataMappingEntry;
|
||||||
import com.raytheon.uf.common.serialization.ISerializableObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Colormap Parameters
|
* Colormap Parameters
|
||||||
|
@ -56,14 +58,15 @@ import com.raytheon.uf.common.serialization.ISerializableObject;
|
||||||
* Jun 14, 2013 DR 16070 jgerth Utilize data mapping
|
* Jun 14, 2013 DR 16070 jgerth Utilize data mapping
|
||||||
* Aug 2, 2013 2211 mschenke Backed out 16070 changes, made
|
* Aug 2, 2013 2211 mschenke Backed out 16070 changes, made
|
||||||
* dataUnit/imageUnit properly commutative.
|
* dataUnit/imageUnit properly commutative.
|
||||||
*
|
* Nov 4, 2013 2492 mschenke Cleaned up variable naming to make purpose
|
||||||
|
* clear (image->colormap)
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author chammack
|
* @author chammack
|
||||||
* @version 1
|
* @version 1
|
||||||
*/
|
*/
|
||||||
@XmlAccessorType(XmlAccessType.NONE)
|
@XmlAccessorType(XmlAccessType.NONE)
|
||||||
public class ColorMapParameters implements Cloneable, ISerializableObject {
|
public class ColorMapParameters {
|
||||||
|
|
||||||
@XmlAccessorType(XmlAccessType.NONE)
|
@XmlAccessorType(XmlAccessType.NONE)
|
||||||
public static class PersistedParameters {
|
public static class PersistedParameters {
|
||||||
|
@ -123,13 +126,13 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
|
|
||||||
protected Set<IColorMapParametersListener> listeners = new HashSet<IColorMapParametersListener>();
|
protected Set<IColorMapParametersListener> listeners = new HashSet<IColorMapParametersListener>();
|
||||||
|
|
||||||
/** Units of the colormap parameters (min/max) */
|
/** Units colormapping should be displayed in */
|
||||||
protected Unit<?> displayUnit;
|
protected Unit<?> displayUnit;
|
||||||
|
|
||||||
/** Units of the image pixel values */
|
/** Units colormapping will occur in */
|
||||||
protected Unit<?> imageUnit;
|
protected Unit<?> colorMapUnit;
|
||||||
|
|
||||||
/** Units of the data values */
|
/** Units of the data values to colormap */
|
||||||
protected Unit<?> dataUnit;
|
protected Unit<?> dataUnit;
|
||||||
|
|
||||||
/** The maximum value used to apply the colormap */
|
/** The maximum value used to apply the colormap */
|
||||||
|
@ -158,23 +161,23 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
@XmlAttribute
|
@XmlAttribute
|
||||||
protected String colorMapName;
|
protected String colorMapName;
|
||||||
|
|
||||||
/** The converter that converts data values to display values * */
|
/** The converter that converts data values to {@link #displayUnit} * */
|
||||||
protected UnitConverter dataToDisplayConverter;
|
protected UnitConverter dataToDisplayConverter;
|
||||||
|
|
||||||
/** The converter that converts display values to data values * */
|
/** The converter that converts display values to {@link #dataUnit} * */
|
||||||
protected UnitConverter displayToDataConverter;
|
protected UnitConverter displayToDataConverter;
|
||||||
|
|
||||||
/** The converter that converts data values to image pixels */
|
/** The converter that converts data values to {@link #colorMapUnit} */
|
||||||
protected UnitConverter dataToImageConverter;
|
protected UnitConverter dataToColorMapConverter;
|
||||||
|
|
||||||
/** The converter that converts image pixels to data values */
|
/** The converter that converts color map unit values to {@link #dataUnit} */
|
||||||
protected UnitConverter imageToDataConverter;
|
protected UnitConverter colorMapToDataConverter;
|
||||||
|
|
||||||
/** The converter that converts image pixels to display values */
|
/** The converter that converts color map unit values to {@link #displayUnit} */
|
||||||
protected UnitConverter imageToDisplayConverter;
|
protected UnitConverter colorMapToDisplayConverter;
|
||||||
|
|
||||||
/** The converter that converts display values to image pixels */
|
/** The converter that converts display values to {@link #colorMapUnit} */
|
||||||
protected UnitConverter displayToImageConverter;
|
protected UnitConverter displayToColorMapConverter;
|
||||||
|
|
||||||
protected DataMappingPreferences dataMapping;
|
protected DataMappingPreferences dataMapping;
|
||||||
|
|
||||||
|
@ -201,7 +204,7 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
/** Specify whether the colormap should be interpolated */
|
/** Specify whether the colormap should be interpolated */
|
||||||
protected boolean interpolate = false;
|
protected boolean interpolate = false;
|
||||||
|
|
||||||
public static class LabelEntry {
|
public static class LabelEntry implements Comparable<LabelEntry> {
|
||||||
private float location;
|
private float location;
|
||||||
|
|
||||||
private String text;
|
private String text;
|
||||||
|
@ -258,8 +261,25 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.lang.Comparable#compareTo(java.lang.Object)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compareTo(LabelEntry o) {
|
||||||
|
return Double.compare(getLocation(), o.getLocation());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link UnitConverter} converting the from unit to the to unit.
|
||||||
|
*
|
||||||
|
* @param from
|
||||||
|
* @param to
|
||||||
|
* @return The unit converter or null of units are not compatible
|
||||||
|
*/
|
||||||
private UnitConverter constructConverter(Unit<?> from, Unit<?> to) {
|
private UnitConverter constructConverter(Unit<?> from, Unit<?> to) {
|
||||||
UnitConverter converter = null;
|
UnitConverter converter = null;
|
||||||
|
|
||||||
|
@ -270,22 +290,34 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
return converter;
|
return converter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addLabel(float dispValue, String s) {
|
/**
|
||||||
float index = getIndexByValue(dispValue);
|
* Adds a label for a {@link #displayUnit} value
|
||||||
|
*
|
||||||
|
* @param colorMapValue
|
||||||
|
* @param s
|
||||||
|
*/
|
||||||
|
private void addDisplayValueLabel(float dispValue, String s) {
|
||||||
|
float colorMapValue = dispValue;
|
||||||
|
UnitConverter displayToColorMap = getDisplayToColorMapConverter();
|
||||||
|
if (displayToColorMap != null) {
|
||||||
|
colorMapValue = (float) displayToColorMap.convert(dispValue);
|
||||||
|
}
|
||||||
|
addColorMapValueLabel(colorMapValue, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a label for a {@link #colorMapUnit} value
|
||||||
|
*
|
||||||
|
* @param colorMapValue
|
||||||
|
* @param s
|
||||||
|
*/
|
||||||
|
private void addColorMapValueLabel(float colorMapValue, String s) {
|
||||||
|
double index = Colormapper.getColorMappingIndex(colorMapValue, this);
|
||||||
if (index > 1.0 || index < 0.0) {
|
if (index > 1.0 || index < 0.0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
labels.add(new LabelEntry(s, index));
|
labels.add(new LabelEntry(s, (float) index));
|
||||||
}
|
|
||||||
|
|
||||||
private void addLabel(int pixelValue, String s) {
|
|
||||||
float location = (float) pixelValue / 255;
|
|
||||||
if (location > 1.0 || location < 0.0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
labels.add(new LabelEntry(s, location));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void computeLabels() {
|
private void computeLabels() {
|
||||||
|
@ -298,7 +330,7 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
if (colorMapRange != 0.0) {
|
if (colorMapRange != 0.0) {
|
||||||
for (float label : colorBarIntervals) {
|
for (float label : colorBarIntervals) {
|
||||||
String s = format.format(label);
|
String s = format.format(label);
|
||||||
addLabel(label, s);
|
addDisplayValueLabel(label, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (dataMapping != null) {
|
} else if (dataMapping != null) {
|
||||||
|
@ -309,14 +341,15 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
s = format.format(dispValue);
|
s = format.format(dispValue);
|
||||||
}
|
}
|
||||||
addLabel(dispValue, s);
|
addDisplayValueLabel(dispValue, s);
|
||||||
} else if (entry.getPixelValue() != null
|
} else if (entry.getPixelValue() != null
|
||||||
&& !"NO DATA".equals(s)) {
|
&& !"NO DATA".equals(s)) {
|
||||||
double pixelValue = entry.getPixelValue();
|
float pixelValue = entry.getPixelValue().floatValue();
|
||||||
addLabel((int) pixelValue, s);
|
addColorMapValueLabel(pixelValue, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Collections.sort(labels);
|
||||||
recomputeLabels = false;
|
recomputeLabels = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,22 +390,26 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the unit
|
* Returns the display unit
|
||||||
|
*
|
||||||
|
* @return The unit colormapping should be displayed in
|
||||||
*/
|
*/
|
||||||
public Unit<?> getDisplayUnit() {
|
public Unit<?> getDisplayUnit() {
|
||||||
return displayUnit;
|
return displayUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the display units
|
||||||
|
*
|
||||||
* @param unit
|
* @param unit
|
||||||
* the unit to set
|
* The unit colormapping should be displayed in
|
||||||
*/
|
*/
|
||||||
public void setDisplayUnit(Unit<?> unit) {
|
public void setDisplayUnit(Unit<?> unit) {
|
||||||
this.displayUnit = unit;
|
this.displayUnit = unit;
|
||||||
recomputeLabels = true;
|
recomputeLabels = true;
|
||||||
|
|
||||||
displayToImageConverter = null;
|
displayToColorMapConverter = null;
|
||||||
imageToDisplayConverter = null;
|
colorMapToDisplayConverter = null;
|
||||||
|
|
||||||
displayToDataConverter = null;
|
displayToDataConverter = null;
|
||||||
dataToDisplayConverter = null;
|
dataToDisplayConverter = null;
|
||||||
|
@ -380,25 +417,32 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the colorMapMax
|
* Returns the maximum range value the colormapping occurs over
|
||||||
|
*
|
||||||
|
* @return the maximum range value in {@link #colorMapUnit}
|
||||||
*/
|
*/
|
||||||
public float getColorMapMax() {
|
public float getColorMapMax() {
|
||||||
return colorMapMax;
|
return colorMapMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the maximum range value the colormapping occurs over
|
||||||
|
*
|
||||||
* @param colorMapMax
|
* @param colorMapMax
|
||||||
* the colorMapMax to set
|
* the maximum range value in {@link #colorMapUnit}
|
||||||
*/
|
*/
|
||||||
public void setColorMapMax(float colorMapMax) {
|
public void setColorMapMax(float colorMapMax) {
|
||||||
setColorMapMax(colorMapMax, false);
|
setColorMapMax(colorMapMax, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the maximum range value the colormapping occurs over
|
||||||
|
*
|
||||||
* @param colorMapMax
|
* @param colorMapMax
|
||||||
* the colorMapMax to set
|
* the maximum range value in {@link #colorMapUnit}
|
||||||
* @param persist
|
* @param persist
|
||||||
* specifies whether to persist this value when saved
|
* true indicates colorMapMax should be persisted through
|
||||||
|
* serialization
|
||||||
*/
|
*/
|
||||||
public void setColorMapMax(float colorMapMax, boolean persist) {
|
public void setColorMapMax(float colorMapMax, boolean persist) {
|
||||||
this.colorMapMax = colorMapMax;
|
this.colorMapMax = colorMapMax;
|
||||||
|
@ -410,25 +454,32 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the colorMapMin
|
* Returns the minimum range value the colormapping occurs over
|
||||||
|
*
|
||||||
|
* @return the minimum range value in {@link #colorMapUnit}
|
||||||
*/
|
*/
|
||||||
public float getColorMapMin() {
|
public float getColorMapMin() {
|
||||||
return colorMapMin;
|
return colorMapMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the minimum range value the colormapping occurs over
|
||||||
|
*
|
||||||
* @param colorMapMin
|
* @param colorMapMin
|
||||||
* the colorMapMin to set
|
* the minimum range value in {@link #colorMapUnit}
|
||||||
*/
|
*/
|
||||||
public void setColorMapMin(float colorMapMin) {
|
public void setColorMapMin(float colorMapMin) {
|
||||||
setColorMapMin(colorMapMin, false);
|
setColorMapMin(colorMapMin, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the minimum range value the colormapping occurs over
|
||||||
|
*
|
||||||
* @param colorMapMin
|
* @param colorMapMin
|
||||||
* the colorMapMin to set
|
* the minimum range value in {@link #colorMapUnit}
|
||||||
* @param persist
|
* @param persist
|
||||||
* specifies whether to persist this value when saved
|
* true indicates colorMapMin should be persisted through
|
||||||
|
* serialization
|
||||||
*/
|
*/
|
||||||
public void setColorMapMin(float colorMapMin, boolean persist) {
|
public void setColorMapMin(float colorMapMin, boolean persist) {
|
||||||
this.colorMapMin = colorMapMin;
|
this.colorMapMin = colorMapMin;
|
||||||
|
@ -510,6 +561,8 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns the unit data values to be colormapped are in
|
||||||
|
*
|
||||||
* @return the dataUnit
|
* @return the dataUnit
|
||||||
*/
|
*/
|
||||||
public Unit<?> getDataUnit() {
|
public Unit<?> getDataUnit() {
|
||||||
|
@ -517,18 +570,20 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the unit data values to be colormapped are in
|
||||||
|
*
|
||||||
* @param dataUnit
|
* @param dataUnit
|
||||||
* the dataUnit to set
|
* the dataUnit to set
|
||||||
*/
|
*/
|
||||||
public void setDataUnit(Unit<?> dataUnit) {
|
public void setDataUnit(Unit<?> dataUnit) {
|
||||||
this.dataUnit = dataUnit;
|
this.dataUnit = dataUnit;
|
||||||
|
|
||||||
if (dataUnit != null && imageUnit == null) {
|
if (dataUnit != null && colorMapUnit == null) {
|
||||||
setImageUnit(dataUnit);
|
setColorMapUnit(dataUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
dataToImageConverter = null;
|
dataToColorMapConverter = null;
|
||||||
imageToDataConverter = null;
|
colorMapToDataConverter = null;
|
||||||
|
|
||||||
dataToDisplayConverter = null;
|
dataToDisplayConverter = null;
|
||||||
displayToDataConverter = null;
|
displayToDataConverter = null;
|
||||||
|
@ -537,6 +592,9 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns the {@link UnitConverter} from {@link #dataUnit} to
|
||||||
|
* {@link #displayUnit}
|
||||||
|
*
|
||||||
* @return the dataToDisplayConverter
|
* @return the dataToDisplayConverter
|
||||||
*/
|
*/
|
||||||
public UnitConverter getDataToDisplayConverter() {
|
public UnitConverter getDataToDisplayConverter() {
|
||||||
|
@ -550,6 +608,9 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Returns the {@link UnitConverter} from {@link #displayUnit} to
|
||||||
|
* {@link #dataUnit}
|
||||||
|
*
|
||||||
* @return the displayToDataConverter
|
* @return the displayToDataConverter
|
||||||
*/
|
*/
|
||||||
public UnitConverter getDisplayToDataConverter() {
|
public UnitConverter getDisplayToDataConverter() {
|
||||||
|
@ -562,7 +623,7 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
return displayToDataConverter;
|
return displayToDataConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public java.util.List<LabelEntry> getLabels() {
|
public List<LabelEntry> getLabels() {
|
||||||
if (recomputeLabels) {
|
if (recomputeLabels) {
|
||||||
computeLabels();
|
computeLabels();
|
||||||
notifyListener();
|
notifyListener();
|
||||||
|
@ -570,10 +631,22 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the colormapping is logarithmically scaled from
|
||||||
|
* {@link #colorMapMin} to {@link #colorMapMax}
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public boolean isLogarithmic() {
|
public boolean isLogarithmic() {
|
||||||
return logarithmic;
|
return logarithmic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to true if the colormapping should logarithmically scaled from
|
||||||
|
* {@link #colorMapMin} to {@link #colorMapMax}
|
||||||
|
*
|
||||||
|
* @param logarithmic
|
||||||
|
*/
|
||||||
public void setLogarithmic(boolean logarithmic) {
|
public void setLogarithmic(boolean logarithmic) {
|
||||||
recomputeLabels = recomputeLabels | this.logarithmic != logarithmic;
|
recomputeLabels = recomputeLabels | this.logarithmic != logarithmic;
|
||||||
this.logarithmic = logarithmic;
|
this.logarithmic = logarithmic;
|
||||||
|
@ -581,83 +654,162 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the dataToImageConverter
|
* @deprecated Use {@link #getDataToColorMapConverter()} instead
|
||||||
|
*
|
||||||
|
* @return the dataToColorMapConverter
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public UnitConverter getDataToImageConverter() {
|
public UnitConverter getDataToImageConverter() {
|
||||||
if (dataToImageConverter == null) {
|
return getDataToColorMapConverter();
|
||||||
dataToImageConverter = constructConverter(dataUnit, imageUnit);
|
|
||||||
if (dataToImageConverter != null) {
|
|
||||||
notifyListener();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return dataToImageConverter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the imageToDisplayConverter
|
* Returns a {@link UnitConverter} converting {@link #dataUnit} values to
|
||||||
|
* the {@link #colorMapUnit} if compatible or null otherwise
|
||||||
|
*
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
|
public UnitConverter getDataToColorMapConverter() {
|
||||||
|
if (dataToColorMapConverter == null) {
|
||||||
|
dataToColorMapConverter = constructConverter(dataUnit, colorMapUnit);
|
||||||
|
if (dataToColorMapConverter != null) {
|
||||||
|
notifyListener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataToColorMapConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getColorMapToDisplayConverter()} instead
|
||||||
|
*
|
||||||
|
* @return the colorMapToDisplayConverter
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public UnitConverter getImageToDisplayConverter() {
|
public UnitConverter getImageToDisplayConverter() {
|
||||||
if (imageToDisplayConverter == null) {
|
return getColorMapToDisplayConverter();
|
||||||
imageToDisplayConverter = constructConverter(imageUnit, displayUnit);
|
}
|
||||||
if (imageToDisplayConverter != null) {
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link UnitConverter} converting {@link #colorMapUnit} values
|
||||||
|
* to the {@link #displayUnit} if compatible or null otherwise
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public UnitConverter getColorMapToDisplayConverter() {
|
||||||
|
if (colorMapToDisplayConverter == null) {
|
||||||
|
colorMapToDisplayConverter = constructConverter(colorMapUnit,
|
||||||
|
displayUnit);
|
||||||
|
if (colorMapToDisplayConverter != null) {
|
||||||
notifyListener();
|
notifyListener();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return imageToDisplayConverter;
|
return colorMapToDisplayConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the imageUnit
|
* @deprecated Use {@link #getColorMapUnit()} instead
|
||||||
|
*
|
||||||
|
* @return the colorMapUnit
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public Unit<?> getImageUnit() {
|
public Unit<?> getImageUnit() {
|
||||||
return imageUnit;
|
return getColorMapUnit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param imageUnit
|
* Returns the unit colormapping will occur in
|
||||||
* the imageUnit to set
|
*
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
public void setImageUnit(Unit<?> imageUnit) {
|
public Unit<?> getColorMapUnit() {
|
||||||
this.imageUnit = imageUnit;
|
return colorMapUnit;
|
||||||
|
}
|
||||||
|
|
||||||
if (imageUnit != null && dataUnit == null) {
|
/**
|
||||||
setDataUnit(imageUnit);
|
* @deprecated Use {@link #setColorMapUnit(Unit)} instead
|
||||||
|
*
|
||||||
|
* @param imageUnit
|
||||||
|
* the colorMapUnit to set
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void setImageUnit(Unit<?> imageUnit) {
|
||||||
|
setColorMapUnit(imageUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the unit colormapping will occur in. {@link #colorMapMin} and
|
||||||
|
* {@link #colorMapMax} are expected to be in this unit
|
||||||
|
*
|
||||||
|
* @param colorMapUnit
|
||||||
|
*/
|
||||||
|
public void setColorMapUnit(Unit<?> colorMapUnit) {
|
||||||
|
this.colorMapUnit = colorMapUnit;
|
||||||
|
|
||||||
|
if (colorMapUnit != null && dataUnit == null) {
|
||||||
|
setDataUnit(colorMapUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
recomputeLabels = true;
|
recomputeLabels = true;
|
||||||
|
|
||||||
imageToDataConverter = null;
|
colorMapToDataConverter = null;
|
||||||
dataToImageConverter = null;
|
dataToColorMapConverter = null;
|
||||||
|
|
||||||
imageToDisplayConverter = null;
|
colorMapToDisplayConverter = null;
|
||||||
displayToImageConverter = null;
|
displayToColorMapConverter = null;
|
||||||
notifyListener();
|
notifyListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the imageToDataConverter
|
* @deprecated Use {@link #getColorMapToDataConverter()} instead
|
||||||
|
*
|
||||||
|
* @return the colorMapToDataConverter
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public UnitConverter getImageToDataConverter() {
|
public UnitConverter getImageToDataConverter() {
|
||||||
if (imageToDataConverter == null) {
|
return getColorMapToDataConverter();
|
||||||
imageToDataConverter = constructConverter(imageUnit, dataUnit);
|
|
||||||
if (imageToDataConverter != null) {
|
|
||||||
notifyListener();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return imageToDataConverter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the displayToImageConverter
|
* Returns a {@link UnitConverter} converting {@link #colorMapUnit} values
|
||||||
|
* to the {@link #dataUnit} if compatible or null otherwise
|
||||||
|
*
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
public UnitConverter getDisplayToImageConverter() {
|
public UnitConverter getColorMapToDataConverter() {
|
||||||
if (displayToImageConverter == null) {
|
if (colorMapToDataConverter == null) {
|
||||||
displayToImageConverter = constructConverter(displayUnit, imageUnit);
|
colorMapToDataConverter = constructConverter(colorMapUnit, dataUnit);
|
||||||
if (displayToImageConverter != null) {
|
if (colorMapToDataConverter != null) {
|
||||||
notifyListener();
|
notifyListener();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return displayToImageConverter;
|
return colorMapToDataConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getDisplayToColorMapConverter()} instead
|
||||||
|
*
|
||||||
|
* @return the displayToColorMapConverter
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public UnitConverter getDisplayToImageConverter() {
|
||||||
|
return getDisplayToColorMapConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a {@link UnitConverter} converting {@link #displayUnit} values to
|
||||||
|
* the {@link #colorMapUnit} if compatible or null otherwise
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public UnitConverter getDisplayToColorMapConverter() {
|
||||||
|
if (displayToColorMapConverter == null) {
|
||||||
|
displayToColorMapConverter = constructConverter(displayUnit,
|
||||||
|
colorMapUnit);
|
||||||
|
if (displayToColorMapConverter != null) {
|
||||||
|
notifyListener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return displayToColorMapConverter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -668,7 +820,7 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
this.dataMapping = dataMapping;
|
this.dataMapping = dataMapping;
|
||||||
recomputeLabels = true;
|
recomputeLabels = true;
|
||||||
if (dataMapping != null && displayUnit != null) {
|
if (dataMapping != null && displayUnit != null) {
|
||||||
setImageUnit(dataMapping.getImageUnit(displayUnit));
|
setColorMapUnit(dataMapping.getImageUnit(displayUnit));
|
||||||
}
|
}
|
||||||
notifyListener();
|
notifyListener();
|
||||||
}
|
}
|
||||||
|
@ -707,12 +859,12 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
cmp.dataMax = dataMax;
|
cmp.dataMax = dataMax;
|
||||||
cmp.dataMin = dataMin;
|
cmp.dataMin = dataMin;
|
||||||
cmp.dataToDisplayConverter = dataToDisplayConverter;
|
cmp.dataToDisplayConverter = dataToDisplayConverter;
|
||||||
cmp.dataToImageConverter = dataToImageConverter;
|
cmp.dataToColorMapConverter = dataToColorMapConverter;
|
||||||
cmp.dataUnit = dataUnit;
|
cmp.dataUnit = dataUnit;
|
||||||
cmp.formatString = formatString;
|
cmp.formatString = formatString;
|
||||||
cmp.imageToDataConverter = imageToDataConverter;
|
cmp.colorMapToDataConverter = colorMapToDataConverter;
|
||||||
cmp.imageToDisplayConverter = imageToDisplayConverter;
|
cmp.colorMapToDisplayConverter = colorMapToDisplayConverter;
|
||||||
cmp.imageUnit = imageUnit;
|
cmp.colorMapUnit = colorMapUnit;
|
||||||
cmp.labels = labels;
|
cmp.labels = labels;
|
||||||
cmp.recomputeLabels = recomputeLabels;
|
cmp.recomputeLabels = recomputeLabels;
|
||||||
cmp.persisted = persisted.clone();
|
cmp.persisted = persisted.clone();
|
||||||
|
@ -779,196 +931,19 @@ public class ColorMapParameters implements Cloneable, ISerializableObject {
|
||||||
return mirror;
|
return mirror;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
float[] testValues = { -3.622782E-10f, -1.6778468E-8f, -3.3110254E-8f,
|
|
||||||
-3.7973948E-8f, -2.7633986E-8f, -9.904648E-9f, -7.5229956E-10f,
|
|
||||||
7.5189455E-10f, 1.20609505E-8f, 2.9364383E-8f, 2.7346168E-8f,
|
|
||||||
1.3699442E-10f, -2.9937E-8f, -3.6884128E-8f, -1.6217847E-8f,
|
|
||||||
1.1931893E-8f, 2.252287E-8f, 1.3290519E-8f, -2.4843547E-9f,
|
|
||||||
-1.0386745E-8f, -6.1300884E-9f, 3.266153E-9f, 1.078073E-8f,
|
|
||||||
1.2696603E-8f, 4.315502E-9f, -7.2422215E-9f, -1.2054819E-8f,
|
|
||||||
-9.100724E-9f, -2.2520505E-9f, 4.031535E-9f, 6.908326E-9f,
|
|
||||||
4.5536255E-9f, 5.3565863E-10f, -6.767242E-11f, 1.7508048E-9f,
|
|
||||||
1.2594312E-9f, -3.5915362E-9f, -6.42762E-9f, -6.295979E-9f,
|
|
||||||
-3.857202E-9f, -2.2052171E-9f, 6.51567E-10f, 3.1020404E-9f,
|
|
||||||
3.2179108E-9f, 2.080211E-9f, 2.5326197E-10f, -2.181367E-9f,
|
|
||||||
-3.2126295E-9f, -2.2162419E-9f, -5.682299E-10f, 7.367537E-11f,
|
|
||||||
1.7393351E-9f, 3.2000091E-9f, 2.82146E-9f, 1.9214115E-9f,
|
|
||||||
1.2637547E-9f, 1.1449517E-9f, 9.570286E-10f, 2.4719807E-10f,
|
|
||||||
7.4189294E-11f, -1.9902982E-10f, -1.6482227E-9f, -2.645924E-9f,
|
|
||||||
-1.4331059E-9f, -2.6336155E-10f, -1.5215194E-9f,
|
|
||||||
-1.5059594E-9f, 2.014035E-10f, 3.565288E-10f, -1.5582429E-9f,
|
|
||||||
-1.3200975E-9f, 1.2632209E-10f, 1.0882992E-9f, 1.5682087E-9f,
|
|
||||||
4.24027E-9f, 3.1678654E-10f, -3.9073598E-9f, -3.4730894E-9f,
|
|
||||||
-9.989449E-10f, -4.0364423E-9f, -6.3506116E-9f, -2.8335263E-9f,
|
|
||||||
-3.1253768E-9f, -1.1271912E-9f, -3.0793168E-10f, 2.2091975E-9f,
|
|
||||||
4.9031823E-9f, 1.0454194E-8f, 1.6462849E-8f, 1.339688E-8f,
|
|
||||||
6.4451755E-9f, 3.820775E-9f, 1.7874671E-9f, -4.5423043E-9f,
|
|
||||||
-4.7599173E-9f, -3.718451E-9f, 2.086526E-10f, 4.4792867E-9f,
|
|
||||||
-5.1967337E-9f, -1.0332604E-8f };
|
|
||||||
|
|
||||||
ColorMapParameters colorMapParameters = new ColorMapParameters();
|
|
||||||
float min = -2.6945168e-7f;
|
|
||||||
float max = 2.1146788e-7f;
|
|
||||||
colorMapParameters.setColorMapMin(-2.6945168e-7f);
|
|
||||||
colorMapParameters.setColorMapMax(2.1146788e-7f);
|
|
||||||
colorMapParameters.setLogarithmic(true);
|
|
||||||
DecimalFormat format = new DecimalFormat("0.###");
|
|
||||||
int i = 0;
|
|
||||||
for (float dispValue : testValues) {
|
|
||||||
String s = format.format(dispValue);
|
|
||||||
colorMapParameters.addLabel(dispValue, s);
|
|
||||||
if (dispValue > max) {
|
|
||||||
System.out.println(colorMapParameters.labels.get(i).location
|
|
||||||
+ "to high");
|
|
||||||
} else if (dispValue < min) {
|
|
||||||
System.out.println(colorMapParameters.labels.get(i).location
|
|
||||||
+ "to low");
|
|
||||||
} else {
|
|
||||||
System.out.println(colorMapParameters.labels.get(i).location);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private float getIndexByValue(float dispValue) {
|
|
||||||
UnitConverter displayToImage = getDisplayToImageConverter();
|
|
||||||
float colorMapRange;
|
|
||||||
if (logarithmic) {
|
|
||||||
// float colorMapMin = this.colorMapMin * 1.25f;
|
|
||||||
// float colorMapMax = this.colorMapMax * 1.25f;
|
|
||||||
if (displayToImage != null) {
|
|
||||||
dispValue = (float) displayToImage.convert(dispValue);
|
|
||||||
}
|
|
||||||
float index = 0.0f;
|
|
||||||
// is this strictly negative, strictly positive or neg to pos
|
|
||||||
// scaling?
|
|
||||||
if (colorMapMin >= 0.0 && colorMapMax >= 0.0 && !isMirror()) {
|
|
||||||
// simple calculation
|
|
||||||
index = ((float) Math.log(dispValue) - (float) Math
|
|
||||||
.log(colorMapMin))
|
|
||||||
/ (float) Math.abs((float) Math.log(colorMapMax)
|
|
||||||
- (float) Math.log(colorMapMin));
|
|
||||||
} else if (colorMapMin <= 0.0 && colorMapMax <= 0.0 && !isMirror()) {
|
|
||||||
index = ((float) (Math.log(dispValue) - (float) Math
|
|
||||||
.log(colorMapMax)) / (float) Math.abs((float) Math
|
|
||||||
.log(colorMapMin) - (float) Math.log(colorMapMax)));
|
|
||||||
} else {
|
|
||||||
// special case, neg to pos:
|
|
||||||
float cmapMin = colorMapMin;
|
|
||||||
float cmapMax = colorMapMax;
|
|
||||||
float zeroVal = (float) Math.max(cmapMax,
|
|
||||||
(float) Math.abs(cmapMin)) * 0.0001f;
|
|
||||||
;
|
|
||||||
|
|
||||||
if (isMirror() && (cmapMin > 0 || cmapMax < 0)) {
|
|
||||||
if (cmapMax < 0) {
|
|
||||||
cmapMax = -cmapMax;
|
|
||||||
dispValue = -dispValue;
|
|
||||||
zeroVal = -cmapMin;
|
|
||||||
} else {
|
|
||||||
zeroVal = cmapMin;
|
|
||||||
}
|
|
||||||
cmapMin = -cmapMax;
|
|
||||||
|
|
||||||
}
|
|
||||||
float leftZero = 0;
|
|
||||||
float rightZero = 0;
|
|
||||||
float absLogZeroVal = (float) Math.abs((float) Math
|
|
||||||
.log(zeroVal));
|
|
||||||
|
|
||||||
rightZero = absLogZeroVal + (float) Math.log(cmapMax);
|
|
||||||
|
|
||||||
float cmapMax2 = -1 * cmapMin;
|
|
||||||
|
|
||||||
leftZero = absLogZeroVal + (float) Math.log(cmapMax2);
|
|
||||||
|
|
||||||
float zeroIndex = leftZero / (leftZero + rightZero);
|
|
||||||
|
|
||||||
// figure out index for texture val
|
|
||||||
float absTextureColor = (float) Math.abs(dispValue);
|
|
||||||
if (dispValue == 0) {
|
|
||||||
index = zeroIndex;
|
|
||||||
} else if (absTextureColor <= zeroVal) {
|
|
||||||
index = (float) zeroIndex;
|
|
||||||
} else if (dispValue > 0.0) {
|
|
||||||
// positive texture color value, find index from 0 to
|
|
||||||
// cmapMax:
|
|
||||||
float logTexColor = absLogZeroVal
|
|
||||||
+ (float) Math.log(dispValue);
|
|
||||||
|
|
||||||
float texIndex = logTexColor / rightZero;
|
|
||||||
index = (float) (zeroIndex + ((1.0 - zeroIndex) * texIndex));
|
|
||||||
} else {
|
|
||||||
// negative texture color value, find index from 0 to
|
|
||||||
// cmapMax:
|
|
||||||
float logTexColor = absLogZeroVal
|
|
||||||
+ (float) Math.log(absTextureColor);
|
|
||||||
|
|
||||||
float texIndex = logTexColor / leftZero;
|
|
||||||
index = (zeroIndex - (zeroIndex * texIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
} else {
|
|
||||||
colorMapRange = colorMapMax - colorMapMin;
|
|
||||||
|
|
||||||
if (colorMapRange != 0.0) {
|
|
||||||
double pixelValue;
|
|
||||||
if (displayToImage != null) {
|
|
||||||
pixelValue = displayToImage.convert(dispValue);
|
|
||||||
} else {
|
|
||||||
pixelValue = dispValue;
|
|
||||||
}
|
|
||||||
float location;
|
|
||||||
if (logarithmic) {
|
|
||||||
location = (float) ((Math.log(pixelValue) - Math
|
|
||||||
.log(colorMapMin)) / colorMapRange);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
location = ((float) pixelValue - colorMapMin)
|
|
||||||
/ colorMapRange;
|
|
||||||
}
|
|
||||||
return location;
|
|
||||||
} else {
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Color object of the value
|
* Get the Color object of the value
|
||||||
*
|
*
|
||||||
* @param value
|
* @param value
|
||||||
|
* value to get Color for in {@link #displayUnit}
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Color getColorByValue(float value) {
|
public Color getColorByValue(float value) {
|
||||||
float index = getIndexByValue(value);
|
UnitConverter displayToColorMap = getDisplayToColorMapConverter();
|
||||||
if (index < 0.0f) {
|
if (displayToColorMap != null) {
|
||||||
index = 0.0f;
|
value = (float) displayToColorMap.convert(value);
|
||||||
} else if (index > 1.0f) {
|
|
||||||
index = 1.0f;
|
|
||||||
}
|
|
||||||
if (isInterpolate()) {
|
|
||||||
index = 0.5f;
|
|
||||||
index = (index * (colorMap.getSize() - 1));
|
|
||||||
int lowIndex = (int) Math.floor(index);
|
|
||||||
int highIndex = (int) Math.ceil(index);
|
|
||||||
float lowWeight = highIndex - index;
|
|
||||||
float highWeight = 1.0f - lowWeight;
|
|
||||||
Color low = colorMap.getColors().get(lowIndex);
|
|
||||||
Color high = colorMap.getColors().get(highIndex);
|
|
||||||
float r = lowWeight * low.getRed() + highWeight * high.getRed();
|
|
||||||
float g = lowWeight * low.getGreen() + highWeight * high.getGreen();
|
|
||||||
float b = lowWeight * low.getBlue() + highWeight * high.getBlue();
|
|
||||||
float a = lowWeight * low.getAlpha() + highWeight * high.getAlpha();
|
|
||||||
return new Color(r, g, b, a);
|
|
||||||
} else {
|
|
||||||
return colorMap.getColors().get(
|
|
||||||
(int) (index * (colorMap.getSize() - 1)));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return Colormapper.getColorByValue(value, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -378,7 +378,7 @@ public class FileLocker {
|
||||||
// locking, can't do any locking
|
// locking, can't do any locking
|
||||||
if (parentDir.canWrite() == false) {
|
if (parentDir.canWrite() == false) {
|
||||||
UFStatus.getHandler()
|
UFStatus.getHandler()
|
||||||
.handle(Priority.PROBLEM,
|
.handle(Priority.DEBUG,
|
||||||
"Cannot write to directory: "
|
"Cannot write to directory: "
|
||||||
+ parentDir.getAbsolutePath());
|
+ parentDir.getAbsolutePath());
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<displayUnits>kft</displayUnits>
|
<displayUnits>kft</displayUnits>
|
||||||
<range scale="LINEAR">
|
<range scale="LINEAR">
|
||||||
<!-- This kft range matches original -19m to 5000m from code -->
|
<!-- This kft range matches original -19m to 5000m from code -->
|
||||||
<minValue>-0.0062</minValue>
|
<minValue>-0.062</minValue>
|
||||||
<maxValue>16.404</maxValue>
|
<maxValue>16.404</maxValue>
|
||||||
</range>
|
</range>
|
||||||
<defaultColormap>topo</defaultColormap>
|
<defaultColormap>topo</defaultColormap>
|
||||||
|
|
Loading…
Add table
Reference in a new issue