A piece of code to add brightness, color and contrast

If you want to add to your controls the parameters mentioned in the title of this post, go to the firs tab (zheng_ca3 (image)), switch to the Rendering tab in the right panel and replace the content of the Shader textfield to this:

#uicontrol vec3 color color(default="white")
#uicontrol float brightness slider(min=-1, max=1)
#uicontrol float contrast slider(min=-3, max=3, step=0.01)
#uicontrol invlerp normalized

void main() {
  emitRGB(color * (normalized() + brightness) * exp(contrast));
}

It will add all the controls below the textfield and the result should look like this (ofc, you can change the color - set to white for the “normal” settings):

The code is basically a copy-paste from here:

I’ve just removed the channels, since we have only one channel.
Also re-added the “normalized” parameter, which exists in the default shader, but doesn’t in the code from the link.

I’ve tried to add some more advanced features like Sobel edge detecting or Laplacian sharpening, but the results weren’t great and, most important, weren’t consistent (some tiles were changed slightly while other weren’t touch at all).

If you want to go back to the default shader, here the code:

#uicontrol invlerp normalized
void main() {
  emitGrayscale(normalized());
}

P.S.
The code should also work for Flywire and BANC and anything based on Neuroglancer.

4 Likes

This is going to be very useful, thank you!

(and for a gaff-)

1 Like

Man :smiling_face_with_tear: this will be very usefull !

Behold the King !

1 Like

Woooohooo i did not knew neuroglancer was opensource on Github ! And Python written ? I’m in a python C++ developement with AI assistance for writing an app. think i’ll give it a try ! :star_struck:

2 Likes

It’s written in TypeScript. It’s basically a client for any large datasets. The server side is independent from Neuroglancer. In our case I believe the server is done in CAVE and can be accessed using any language, for example Python: FlyConnectome/CAVE tutorial.ipynb at main · seung-lab/FlyConnectome · GitHub
And yes, you can write a pretty good application in Python (for example, with CTKinter) for managing all the annotations, segments, etc. :slight_smile:

2 Likes

Added sharpness:

#uicontrol vec3 color color(default="white")
#uicontrol float brightness slider(min=-1, max=1)
#uicontrol float contrast slider(min=-3, max=3, step=0.01)
#uicontrol float sharpness slider(min=0.0, max=1.0, default=0.5, step=0.01)
#uicontrol invlerp normalized


void main() {
  float value = toNormalized(getDataValue());
  
  float top = toNormalized(getDataValueAt(ivec3(0, 1, 0)));
  float bottom = toNormalized(getDataValueAt(ivec3(0, -1, 0)));
  float left = toNormalized(getDataValueAt(ivec3(-1, 0, 0)));
  float right = toNormalized(getDataValueAt(ivec3(1, 0, 0)));

  float sharpened = value * (1.0 + sharpness) - (top + bottom + left + right - 4.0 * value) * sharpness;
  
  emitRGB(color * (sharpened + brightness) * exp(contrast));
}

1 Like

I know it’s probably not possible, but any way through this method to ‘tell’/force neuroglancer to never stop rendering/unbluring the 2D? lol

As in this bug: Bugs, glitches and things not working as they should - #8 by JousterL

1 Like

Unfortunately the issue with rendering is probably somewhere else. With the shader code we can only tell, how to display each pixel (the shader is called for each pixel separately). If there’s no info, the shader can’t create it.

Anyway, here’s another functionality: inverse colors. Probably not very useful during normal play, but might be useful to spot difficult traces sometimes (when the colors are switched it’s sort of a fresh look).

#uicontrol vec3 color color(default="white")
#uicontrol float brightness slider(min=-1, max=1)
#uicontrol float contrast slider(min=-3, max=3, step=0.01)
#uicontrol float sharpness slider(min=0.0, max=1.0, default=0.5, step=0.01)
#uicontrol invlerp normalized
#uicontrol bool inverse_colors checkbox(default=false)


void main() {
  float value = toNormalized(getDataValue());
  
  float top = toNormalized(getDataValueAt(ivec3(0, 1, 0)));
  float bottom = toNormalized(getDataValueAt(ivec3(0, -1, 0)));
  float left = toNormalized(getDataValueAt(ivec3(-1, 0, 0)));
  float right = toNormalized(getDataValueAt(ivec3(1, 0, 0)));

  float sharpened = value * (1.0 + sharpness) - (top + bottom + left + right - 4.0 * value) * sharpness;
  vec3 enhanced = color * (sharpened + brightness) * exp(contrast);
  
  if (inverse_colors) {
    enhanced = enhanced * -1.0 + 1.0;
  }
  
  emitRGB(enhanced);
}

1 Like

Thanks for creating this! I was just wondering - there’s some code used in spelunker (looks like not autogenerated in pyr) that controls for black and white contrast –

#uicontrol float black slider(min=0, max=1, default=0.0)
#uicontrol float white slider(min=0, max=1, default=1.0)
float rescale(float value) {
return (value - black) / (white - black);
}
void main() {
float val = toNormalized(getDataValue());
if (val < black) {
emitRGB(vec3(0,0,0));
} else if (val > white) {
emitRGB(vec3(1.0, 1.0, 1.0));
} else {
emitGrayscale(rescale(val));
}
}

I was just wondering, for clarity, if you could note if there’s any overlap with this code and the code you’ve recommended for value/brightness? Mostly asking in case I recommend those using base spelunker to paste in this code if it should override the default black/white code or should be included on top of it. TIA!

3 Likes

Nice piece of code, here’s a little simplier version of it (it does exactly the same, is just shorter):

#uicontrol float black slider(min=0, max=1, default=0.0)
#uicontrol float white slider(min=0, max=1, default=1.0)

void main() {
  float val = toNormalized(getDataValue());
  emitGrayscale(clamp((val - black) / (white - black), 0.0, 1.0));
}

As for the functionality - your code would be a replacement for brightness, contrast and inversion of colors in a way.
One could combine both shaders to something like this (thanks to chatGPT :wink: ):

#uicontrol float black slider(min=0, max=1, default=0.0)
#uicontrol float white slider(min=0, max=1, default=1.0)
#uicontrol vec3 color color(default="white")
#uicontrol float brightness slider(min=-1, max=1)
#uicontrol float contrast slider(min=-3, max=3, step=0.01)
#uicontrol float sharpness slider(min=0.0, max=1.0, default=0.0, step=0.01)
#uicontrol invlerp normalized
#uicontrol bool inverse_colors checkbox(default=false)

void main() {
  float value = toNormalized(getDataValue());

  // Neighbor sampling for sharpening
  float top = toNormalized(getDataValueAt(ivec3(0, 1, 0)));
  float bottom = toNormalized(getDataValueAt(ivec3(0, -1, 0)));
  float left = toNormalized(getDataValueAt(ivec3(-1, 0, 0)));
  float right = toNormalized(getDataValueAt(ivec3(1, 0, 0)));

  // Apply sharpening filter
  float sharpened = value * (1.0 + sharpness) - (top + bottom + left + right - 4.0 * value) * sharpness;

  // Rescale based on black/white levels and adjust brightness/contrast
  float scaled = clamp((sharpened - black) / (white - black), 0.0, 1.0);
  vec3 enhanced = color * (scaled + brightness) * exp(contrast);

  // Invert colors if selected
  if (inverse_colors) {
    enhanced = 1.0 - enhanced;
  }

  emitRGB(enhanced);
}
3 Likes