HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptMinor

How to speed up window leveling (brightness, contrast)?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
contrastlevelingbrightnesshowwindowspeed

Problem

I have to apply window leveling on Canvas Medical Image (CR). I have to get a pixel array from C# Component.lutArr, which is a lookup table array coming as a C# component and which I use in JavaScript. On click of the button, I have to call the function ApplyWLCust(). In this function, all process done getting result perfect. For window leveling, use bit shifting, which takes around 585ms. I have to reduce this time. What should I do?

```
var imagewc = document.getElementById("text1").value;
var imageww = document.getElementById("text2").value;
pixelArr = [11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11..]
if (pixelArr != null)
{
for (var i = 0, n = pixelArr.length; i > 16;
v = i * 4;
imagedata[v] = pix & 0xff;
imagedata[v + 1] = (pix >>> 8) & 0xff;
imagedata[v + 2] = (pix >>> 16) & 0xff;
imagedata[v + 3] = 255;
}
// offscreenCtx.imageSmoothingEnabled = true;
offscreenCtx.putImageData(g, 0, 0);
}
function ApplyWL(value, _valwindowCenter, _valwindowWidth)
{
Recalculate(_valwindowCenter, _valwindowWidth);
if (value _windowEnd)
value = _maximumOutputValue;
else
{
value = Math.round((((value - _windowCenterMin05) / _windowWidthMin1) + 0.5) * 255.0);
}
return value;
}

var _minimumOutputValue = 0;
var _maximumOutputValue = 255;
function Recalculate(_valwindowCenter, _valwindowWidth)
{
if (!_valid)
{
_windowCenterMin05 = _valwindowCenter - 0.5;
_windowWidthMin1 = _valwindowWidth - 1;
_windowWidthDiv2 = _windowWidthMin1 / 2;
_windowStart = (_windowCenterMin05 - _windowW

Solution

I think we need more code,

  • Where are imagewc, imageww, and lutArr defined ? Those are all 3 unfortunate variable names by the way



Regardless, I think a large speed up should be gained from calling Recalculate once before the loop on pixelArr since imagewc and imageww never change in that loop.

Furthermore, since value is cut of between 0 and 255, you should pre-calculate the array of values.

var lookup= [] , i;
for( var i = _minimumOutputValue  ; i < _maximumOutputValue+1; i++ )
    lookup[i] = Math.round((((i- _windowCenterMin05) / _windowWidthMin1) + 0.5) * 255.0);


then your function would be:

function ApplyWL(value, _valwindowCenter, _valwindowWidth)
{
   if (value  _windowEnd)
      return lookup[_maximumOutputValue];
   return lookup[value]
}


I might be wrong about the ranges of lookup, your table might have to be larger, but I am sure you realize the value of a lookup table at this point.

EDIT:

I wrote some code to look at it, some notes:
* I moved the variables to the top, please make sure that all variables are declared with var
* Only constructors should start with an uppercase letter

var imagewc = document.getElementById("text1").value,
    imageww = document.getElementById("text2").value,
    _minimumOutputValue = 0,
    _maximumOutputValue = 255,    
    _valid,
    cacheWL = [],
    pixelArr = [11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11]; 

if (pixelArr != null)
{
  //Move this out of the for loop
  recalculate(_valwindowCenter, _valwindowWidth);
  //Then set the cache which needs the results of `recalculate`
  cacheWL();
  for (var i = 0, n = pixelArr.length,v = 0,i >> 8) & 0xff;
    imagedata[v + 2] = (pix >>> 16) & 0xff;
    imagedata[v + 3] = 255;
    //Instead of doing a multiplication, you can keep adding 4
    v += 4; 
  }
  offscreenCtx.putImageData(g, 0, 0);
}

function setCacheWL()
{
  for( var i = _minimumOutputValue ; i  _windowEnd)
      return cacheWL[_maximumOutputValue];
   return cacheWL[value]
}

function recalculate(_valwindowCenter, _valwindowWidth)
{
  if (!_valid)
  {
    _windowCenterMin05 = _valwindowCenter - 0.5;
    _windowWidthMin1 = _valwindowWidth - 1;
    _windowWidthDiv2 = _windowWidthMin1 / 2;
    _windowStart = (_windowCenterMin05 - _windowWidthDiv2);
    _windowEnd = (_windowCenterMin05 + _windowWidthDiv2);
    _valid = true;
  }
}

Code Snippets

var lookup= [] , i;
for( var i = _minimumOutputValue  ; i < _maximumOutputValue+1; i++ )
    lookup[i] = Math.round((((i- _windowCenterMin05) / _windowWidthMin1) + 0.5) * 255.0);
function ApplyWL(value, _valwindowCenter, _valwindowWidth)
{
   if (value <= _windowStart)
     return lookup[_minimumOutputValue  ];
   if (value > _windowEnd)
      return lookup[_maximumOutputValue];
   return lookup[value]
}
var imagewc = document.getElementById("text1").value,
    imageww = document.getElementById("text2").value,
    _minimumOutputValue = 0,
    _maximumOutputValue = 255,    
    _valid,
    cacheWL = [],
    pixelArr = [11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11]; 

if (pixelArr != null)
{
  //Move this out of the for loop
  recalculate(_valwindowCenter, _valwindowWidth);
  //Then set the cache which needs the results of `recalculate`
  cacheWL();
  for (var i = 0, n = pixelArr.length,v = 0,i < n; i++)
  {
    pix = pixelArr[i];
    pix = ApplyWL(pix, imagewc, imageww);
    pix = lutArr[pix];

    imagedata[v] = pix & 0xff;
    imagedata[v + 1] = (pix >>> 8) & 0xff;
    imagedata[v + 2] = (pix >>> 16) & 0xff;
    imagedata[v + 3] = 255;
    //Instead of doing a multiplication, you can keep adding 4
    v += 4; 
  }
  offscreenCtx.putImageData(g, 0, 0);
}

function setCacheWL()
{
  for( var i = _minimumOutputValue ; i <= _maximumOutputValue ; i++ )
    cacheWL[i] = Math.round((((i - _windowCenterMin05) / _windowWidthMin1) + 0.5) * 255.0);
}


function ApplyWL(value, _valwindowCenter, _valwindowWidth)
{
   if (value <= _windowStart)
     return cacheWL[_minimumOutputValue];
   if (value > _windowEnd)
      return cacheWL[_maximumOutputValue];
   return cacheWL[value]
}

function recalculate(_valwindowCenter, _valwindowWidth)
{
  if (!_valid)
  {
    _windowCenterMin05 = _valwindowCenter - 0.5;
    _windowWidthMin1 = _valwindowWidth - 1;
    _windowWidthDiv2 = _windowWidthMin1 / 2;
    _windowStart = (_windowCenterMin05 - _windowWidthDiv2);
    _windowEnd = (_windowCenterMin05 + _windowWidthDiv2);
    _valid = true;
  }
}

Context

StackExchange Code Review Q#44656, answer score: 2

Revisions (0)

No revisions yet.