Example a_backup/colour_transform: Uses colour_lookup_spectrum to adjust brightness and contrast.

Screenshot of example a_backup/colour_transform


The comfile run by this example is as follows:

# Example a/colour_transform:  Use a spectrum to update the brightness and contrast of an image.

{
 use strict;
 use Cmiss::Example_path qw($example $TESTING);

sub set_colour_lookup
{
  #An offset applied to the colour values after the contrast
  my $brightness = shift;  #Sensible values from -1 to +1

  #Apply a sigmoid filter of the form x/sqrt(1+x^2)
  my $contrast = shift;    #Sensible values from -1 to +1

  #Controls the centre of the contrast curve by doing an offset
  #before the contrast whereas the brightness is applied afterwards.
  my $offset = shift

  if (defined $brightness)
	 {
 		gfx define field brightness constant $brightness;
	 }
  else
	 {
 		gfx define field brightness constant 0.0;
	 }
  if (defined $contrast)
	 {
 		gfx define field contrast constant $contrast;
	 }
  else
	 {
 		gfx define field contrast constant 0.0;
	 }
  if (defined $offset)
	 {
 		gfx define field offset constant $offset;
	 }
  else
	 {
 		gfx define field offset constant 0.0;
	 }

  #We shouldn't have to modify the spectrum to get it to update,
  #it should register for computed field change events.
  gfx modify spectrum colour_lookup;

}

sub define_colour_lookup_fields
{
  use Cmiss::Cmiss_context;
  use Cmiss::Region;
  use Cmiss::Field;

  #When running inside Cmgui application this will return the reference
  #to the command data the application has created.
  my $cmiss_context = new Cmiss::Cmiss_context();

  my $default_region = $cmiss_context->get_default_region();

  my $field_module = $default_region->get_field_module();

  #We need a dummy input field to base our computed field calculation on.
  
  my $colour = $field_module->create_constant(0.5);
  $colour->set_name("colour");

  my $brightness = $field_module->create_constant(0.0);
  $brightness->set_name("brightness");

  my $contrast = $field_module->create_constant(0.0);
  $contrast->set_name("contrast");

  my $offset = $field_module->create_constant(0.0);
  $offset->set_name("offset");

  my $offset_colour = $colour + $offset;

  #gfx define field offset_colour add fields colour offset;

  #Apply a sigmoid filter x sqrt(1 -c)/sqrt( 1 - c x^2)

  #Make an alias for the input = 2 x -1
  my $contrast_colour_input = 2 * $offset_colour - 1;

  #Make e^c
  my $contrast_exp = exp($contrast);

  #If e^c > 1 then we can get imaginary solutions which we need to filter out
  my $contrast_exp_imaginary = $contrast_exp > 1;

  #If we can get imaginary solutions then they are input greater than
  # sqrt(1 / (e^c - 1)) and less than -sqrt(1 / (e^c - 1))
  my $contrast_exp_C = sqrt(1 / ($contrast_exp - 1));

  my $contrast_colour_imaginary_A = $contrast_colour_input > $contrast_exp_C;
  my $contrast_colour_imaginary_B = $contrast_colour_input < -$contrast_exp_C;

  #Make x sqrt(e^c)/sqrt( 1 - c x^2)
  my $contrast_colour_H = $contrast_colour_input * sqrt($contrast_exp) / sqrt(1 - $contrast * $contrast_colour_input * $contrast_colour_input);

  #Scale from -1 to 1 back to 0 to 1
  my $contrast_colour_output_B = ($contrast_colour_H + 1) / 2.0;

  #If greater than the imaginary limit then clamp to 1.0
  my $contrast_colour_output_E = Cmiss::Field::if($contrast_colour_imaginary_A, 1.0, $contrast_colour_output_B);
  #If less than the imaginary limit then clamp to -1.0
  my $contrast_colour_output_F = Cmiss::Field::if($contrast_colour_imaginary_B, -1.0, $contrast_colour_output_E);

  #If possibly imaginary then use the clamped values otherwise just use the rescaled value.
  my $contrast_colour = Cmiss::Field::if($contrast_exp_imaginary, $contrast_colour_output_F, $contrast_colour_output_B);

  my $brightness_colour = $contrast_colour + $brightness;
  $brightness_colour->set_name("brightness_colour");

  gfx create spectrum colour_lookup field monochrome input colour output brightness_colour;

}

# Read in some geometry to hold our texture and define coordinates.
gfx read node $example/SamplePlane_1.exnode;
gfx read element $example/Slice.exelem;

# Read in the first texture
gfx create texture input_image image "$example/torso_gray.png" width 1 height 1;
gfx create material input_image texture input_image;

#Set up the spectrum.  Initially don't change the colour.
define_colour_lookup_fields();
set_colour_lookup(0, 0);

#Specifying a 1 component spectrum with 3 input components will apply
#the same lookup independently to each colour component.
#As this image is gray we could have just looked up one of the colours
#however this material will also work for colour images.
gfx modify material input_image colour_lookup_spectrum colour_lookup per_pixel_mode colour_lookup_red colour_lookup_green colour_lookup_blue;

gfx modify g_element slice general clear circle_discretization 6 default_coordinate coordinates element_discretization "4*4*4" native_discretization none;
gfx modify g_element slice lines select_on material default selected_material default_selected;
gfx modify g_element slice surfaces select_on material input_image selected_material default_selected render_shaded texture_coordinates xi;

gfx create window 1 double_buffer;
gfx modify window 1 image scene default light_model default;
gfx modify window 1 image add_light default;
gfx modify window 1 layout 2d ortho_axes z -y eye_spacing 0.25 width 400 height 400;
gfx modify window 1 set current_pane 1;
gfx modify window 1 background colour 0 0 0 texture none;
gfx modify window 1 view parallel eye_point 25 25 155.782 interest_point 25 25 0 up_vector -0 1 0 view_angle 28.8189 near_clipping_plane 1.55782 far_clipping_plane 556.712 relative_viewport ndc_placement -1 1 2 2 viewport_coordinates 0 0 1 1;
gfx modify window 1 set transform_tool current_pane 1 std_view_angle 40 normal_lines no_antialias fast_transparency blend_normal;

#Change the brightness
set_colour_lookup(0.1, 0.1, 0.0);

if ($TESTING)
  {
	 #Force the computed fields to be evaluated over and over
	 #to give us a small stress test for field evaluations.
	 gfx create texture output_image;
	 for (my $i = 0 ; $i < 20 ; $i++)
		{
		  set_colour_lookup(0.1, $i/20, 0.0);
		  gfx modify texture output_image linear width 1 height 1 evaluate_image field input_image spectrum colour_lookup texture_coord xi element_group slice;
		}
  }
}

Files used by this example are:

Name                  Modified     Size

colour_transform.com 20-Apr-2012 6.1k COPYRIGHT 19-Apr-2012 504 SamplePlane_1.exnode 20-Apr-2012 351 Slice.exelem 20-Apr-2012 1.5k torso_gray.png 20-Apr-2012 15k

Download the entire example:

Name                                       Modified     Size

examples_a_backup_colour_transform.tar.gz 12-Aug-2014 98k

Testing status by version:

StatusTestedReal time (s)
i686-linux
cmgui-wxSuccessSun Mar 6 00:38:56 201623
cmgui-wx-debugSuccessSun Mar 6 01:05:30 201639
cmgui-wx-debug-memorycheckSuccessSun Mar 6 01:15:13 201657
cmgui-wx-debug-valgrindFailureSun Mar 6 04:21:19 20161841
last breakSun Mar 6 03:50:00 20161841
last successTue Feb 10 03:32:00 20151974
x86_64-linux
cmgui-wxFailureSun Mar 6 00:01:37 20161
last breakSun Mar 6 00:01:00 20161
last successWed Jun 3 00:12:00 201513
cmgui-wx-debugFailureSun Mar 6 00:01:36 20160
last breakSun Mar 6 00:01:00 20160
last successWed Jun 3 00:21:00 201525
cmgui-wx-debug-memorycheckFailureSun Mar 6 00:01:37 20161
last breakSun Mar 6 00:01:00 20161
last successWed Jun 3 00:31:00 201534
cmgui-wx-debug-valgrindFailureSun Mar 6 00:02:35 20169
last breakSun Mar 6 00:02:00 20169
last successWed Jun 3 02:30:00 20151443

Testing status by file:


Html last generated: Sun Mar 6 05:50:53 2016

Input last modified: Fri Apr 20 15:56:51 2012


CMISS Help / Examples / a_backup / colour_transform