<|start_filename|>src/version.js<|end_filename|>
export default '2.2.8';


<|start_filename|>src/webgl/shaders/rgb.js<|end_filename|>
const rgbShader = {};

/**
 * Convert stored pixel data to image data.
 *
 * Pack RGB images into a 3-channel RGB texture
 *
 * @param {Image} image A Cornerstone Image Object
 * @returns {Uint8Array} The image data for use by the WebGL shader
 * @memberof WebGLRendering
 */
function storedPixelDataToImageData (image) {
  const minPixelValue = image.minPixelValue;
  let canvasImageDataIndex = 0;
  let storedPixelDataIndex = 0;
  // Only 3 channels, since we use WebGL's RGB texture format
  const numStoredPixels = image.width * image.height * 4;
  const numOutputPixels = image.width * image.height * 3;
  const storedPixelData = image.getPixelData();
  const data = new Uint8Array(numOutputPixels);

  // NOTE: As of Nov 2014, most javascript engines have lower performance when indexing negative indexes.
  // We have a special code path for this case that improves performance.  Thanks to @jpambrun for this enhancement
  if (minPixelValue < 0) {
    while (storedPixelDataIndex < numStoredPixels) {
      data[canvasImageDataIndex++] = storedPixelData[storedPixelDataIndex++] + (-minPixelValue); // Red
      data[canvasImageDataIndex++] = storedPixelData[storedPixelDataIndex++] + (-minPixelValue); // Green
      data[canvasImageDataIndex++] = storedPixelData[storedPixelDataIndex++] + (-minPixelValue); // Blue
      storedPixelDataIndex += 1; // The stored pixel data has 4 channels
    }
  } else {
    while (storedPixelDataIndex < numStoredPixels) {
      data[canvasImageDataIndex++] = storedPixelData[storedPixelDataIndex++]; // Red
      data[canvasImageDataIndex++] = storedPixelData[storedPixelDataIndex++]; // Green
      data[canvasImageDataIndex++] = storedPixelData[storedPixelDataIndex++]; // Blue
      storedPixelDataIndex += 1; // The stored pixel data has 4 channels
    }
  }

  return data;
}

export const rgbDataUtilities = {
  storedPixelDataToImageData
};

rgbShader.frag = 'precision mediump float;' +
    'uniform sampler2D u_image;' +
    'uniform float ww;' +
    'uniform float wc;' +
    'uniform float slope;' +
    'uniform float intercept;' +
    'uniform float minPixelValue;' +
    'uniform int invert;' +
    'varying vec2 v_texCoord;' +

    'void main() {' +

        // Get texture
        'vec3 color = texture2D(u_image, v_texCoord).xyz;' +

        // Rescale based on slope and intercept
        'color = color * 256.0 * slope + intercept;' +

        // Apply window settings
        'float center0 = wc - 0.5 - minPixelValue;' +
        'float width0 = max(ww, 1.0);' +
        'color = (color - center0) / width0 + 0.5;' +

        // RGBA output
        'gl_FragColor = vec4(color, 1);' +

        // Apply any inversion necessary
        'if (invert == 1)' +
            'gl_FragColor.rgb = 1. - gl_FragColor.rgb;' +
    '}';

export { rgbShader };


<|start_filename|>src/getImage.js<|end_filename|>
import { getEnabledElement } from './enabledElements.js';

/**
 * Returns the currently displayed image for an element or undefined if no image has
 * been displayed yet
 *
 * @param {HTMLElement} element The DOM element enabled for Cornerstone
 * @returns {Image} The Cornerstone Image Object displayed in this element
 */
export default function (element) {
  const enabledElement = getEnabledElement(element);

  return enabledElement.image;
}


<|start_filename|>src/metaData.js<|end_filename|>
// This module defines a way to access various metadata about an imageId.  This layer of abstraction exists
// So metadata can be provided in different ways (e.g. by parsing DICOM P10 or by a WADO-RS document)

const providers = [];

/**
 * @module Metadata
 */

/**
 * Adds a metadata provider with the specified priority
 * @param {Function} provider Metadata provider function
 * @param {Number} [priority=0] - 0 is default/normal, > 0 is high, < 0 is low
 *
 * @returns {void}
 * @memberof Metadata
 */
export function addProvider (provider, priority = 0) {
  let i;

  // Find the right spot to insert this provider based on priority
  for (i = 0; i < providers.length; i++) {
    if (providers[i].priority <= priority) {
      break;
    }
  }

  // Insert the decode task at position i
  providers.splice(i, 0, {
    priority,
    provider
  });
}

/**
 * Removes the specified provider
 *
 * @param {Function} provider Metadata provider function
 *
 * @returns {void}
 * @memberof Metadata
 */
export function removeProvider (provider) {
  for (let i = 0; i < providers.length; i++) {
    if (providers[i].provider === provider) {
      providers.splice(i, 1);

      break;
    }
  }
}

/**
 * Gets metadata from the registered metadata providers.  Will call each one from highest priority to lowest
 * until one responds
 *
 * @param {String} type The type of metadata requested from the metadata store
 * @param {String} imageId The Cornerstone Image Object's imageId
 *
 * @returns {*} The metadata retrieved from the metadata store
 * @memberof Metadata
 */
function getMetaData (type, imageId) {
  // Invoke each provider in priority order until one returns something
  for (let i = 0; i < providers.length; i++) {
    const result = providers[i].provider(type, imageId);

    if (result !== undefined) {
      return result;
    }
  }
}

export default {
  addProvider,
  removeProvider,
  get: getMetaData
};


<|start_filename|>src/webgl/shaders/int8.js<|end_filename|>
const int8Shader = {};

/**
 * Convert stored pixel data to image data.
 *
 * Store data in Uint8Array
 *
 * @param {Image} image A Cornerstone Image Object
 * @returns {Uint8Array} The image data for use by the WebGL shader
 * @memberof WebGLRendering
 */
function storedPixelDataToImageData (image) {
  // Transfer image data to alpha channel of WebGL texture
  // Store data in Uint8Array
  const pixelData = image.getPixelData();
  const numberOfChannels = 2;
  const data = new Uint8Array(image.width * image.height * numberOfChannels);
  let offset = 0;

  for (let i = 0; i < pixelData.length; i++) {
    data[offset++] = pixelData[i];
    data[offset++] = pixelData[i] < 0 ? 0 : 1; // 0 For negative, 1 for positive
  }

  return data;
}

export const int8DataUtilities = {
  storedPixelDataToImageData
};

int8Shader.frag = 'precision mediump float;' +
    'uniform sampler2D u_image;' +
    'uniform float ww;' +
    'uniform float wc;' +
    'uniform float slope;' +
    'uniform float intercept;' +
    'uniform int invert;' +
    'varying vec2 v_texCoord;' +

    'void main() {' +
        // Get texture
        'vec4 color = texture2D(u_image, v_texCoord);' +

        // Calculate luminance from packed texture
        'float intensity = color.r*256.;' +

        'if (color.a == 0.0)' +
            'intensity = -intensity;' +

        // Rescale based on slope and window settings
        'intensity = intensity * slope + intercept;' +
        'float center0 = wc - 0.5;' +
        'float width0 = max(ww, 1.0);' +
        'intensity = (intensity - center0) / width0 + 0.5;' +

        // Clamp intensity
        'intensity = clamp(intensity, 0.0, 1.0);' +

        // RGBA output
        'gl_FragColor = vec4(intensity, intensity, intensity, 1.0);' +

        // Apply any inversion necessary
        'if (invert == 1)' +
            'gl_FragColor.rgb = 1.0 - gl_FragColor.rgb;' +
    '}';

export { int8Shader };


<|start_filename|>test/getViewport_test.js<|end_filename|>
import { assert } from 'chai'; // eslint-disable-line import/extensions

import enable from '../src/enable.js';
import getViewport from '../src/getViewport.js';
import disable from '../src/disable.js';

describe('Set an enabled element\'s viewport', function () {
  beforeEach(function () {
    // Arrange
    this.element = document.createElement('div');
    enable(this.element);
  });

  it('should fail silently if no viewport settings are present', function () {
    const element = this.element;

    // Act
    const viewport = getViewport(element);

    // Assert
    assert.isUndefined(viewport);
  });

  afterEach(function () {
    disable(this.element);
  });
});


<|start_filename|>example/displayedArea/test-cases/DISA_P03.json<|end_filename|>
{
  "imageId": "example//DISA_P03",
  "minPixelValue": 0,
  "maxPixelValue": 255,
  "slope": 1.0,
  "intercept": 0,
  "windowCenter": 127.5,
  "windowWidth": 255,
  "rows": 1024,
  "columns": 1024,
  "height": 1024,
  "width": 1024,
  "color": false,
  "columnPixelSpacing": 1,
  "rowPixelSpacing": 1,
  "sizeInBytes": 1048576,
  "testCase": {
    "image": "SC image containing SMPTE pattern (magnified by factor 2.0), Columns 1024, Rows 1024, Bits Allocated 8, Bits Stored 8, Pixel Range 0 to +255, Pixel Representation is unsigned, Photometric Interpretation is MONOCHROME2, no LUTs",
    "pState": "Presentation Size Mode: MAGNIFY, Displayed Area Top Left Hand Corner 1\\1, Displayed Area Bottom Right Hand Corner 1024\\1024, Presentation Pixel Aspect Ratio 1\\1, Presentation Pixel Magnification Ratio 0.5",
    "result": "Display should be a normal SMPTE pattern (fixed size: 512*512 pixel)",
    "displayedArea": {
      "tlhc": {
        "x": 1,
        "y": 1
      },
      "brhc": {
        "x": 1024,
        "y": 1024
      },
      "rowPixelSpacing": 0.5,
      "columnPixelSpacing": 0.5,
      "presentationSizeMode": "MAGNIFY"
    }
  }
}

<|start_filename|>test/internal/storedPixelDataToCanvasImageDataColorLUT_test.js<|end_filename|>
import { should } from 'chai'; // eslint-disable-line import/extensions
import storedPixelDataToCanvasImageDataColorLUT from '../../src/internal/storedPixelDataToCanvasImageDataColorLUT.js';

should();

describe('storedPixelDataToCanvasImageDataColorLUT', function () {
  before(function () {
    this.colorLut = [[3, 2, 1, 1], [7, 6, 5, 4], [6, 1, 2, 8]];
    this.image = {
      stats: {}
    };
  });

  beforeEach(function () {
    this.canvasImageData = [255, 255, 255, 128, 255, 255, 255, 128];
  });

  it('should get LUT values equal to its pixels when minPixelValue == 0', function () {
    this.image.minPixelValue = 0;
    this.image.getPixelData = function () {
      return [0, 1];
    };

    storedPixelDataToCanvasImageDataColorLUT(this.image, this.colorLut, this.canvasImageData);

    this.canvasImageData.should.be.deep.equal([3, 2, 1, 1, 7, 6, 5, 4]);
  });

  it('should get LUT values equal to its pixels minus its minimun pixel value when minPixelValue < 0', function () {
    this.image.minPixelValue = -1;
    this.image.getPixelData = function () {
      return [-1, 1];
    };

    storedPixelDataToCanvasImageDataColorLUT(this.image, this.colorLut, this.canvasImageData);

    this.canvasImageData.should.be.deep.equal([3, 2, 1, 1, 6, 1, 2, 8]);
  });
});


<|start_filename|>src/rendering/saveLastRendered.js<|end_filename|>
/**
 * Saves the parameters of the last render into renderingTools, used later to decide if data can be reused.
 *
 * @param {Object} enabledElement Cornerstone EnabledElement
 * @returns {Object} enabledElement.renderingTools
 * @memberof rendering
 */

export default function (enabledElement) {
  const imageId = enabledElement.image.imageId;
  const viewport = enabledElement.viewport;
  const isColor = enabledElement.image.color;

  enabledElement.renderingTools.lastRenderedImageId = imageId;
  enabledElement.renderingTools.lastRenderedIsColor = isColor;
  enabledElement.renderingTools.lastRenderedViewport = {
    windowCenter: viewport.voi.windowCenter,
    windowWidth: viewport.voi.windowWidth,
    invert: viewport.invert,
    rotation: viewport.rotation,
    hflip: viewport.hflip,
    vflip: viewport.vflip,
    modalityLUT: viewport.modalityLUT,
    voiLUT: viewport.voiLUT,
    colormap: viewport.colormap
  };

  return enabledElement.renderingTools;
}


<|start_filename|>src/webgl/shaders/index.js<|end_filename|>
import { int16Shader, int16DataUtilities } from './int16.js';
import { int8Shader, int8DataUtilities } from './int8.js';
import { rgbShader, rgbDataUtilities } from './rgb.js';
import { uint16Shader, uint16DataUtilities } from './uint16.js';
import { uint8Shader, uint8DataUtilities } from './uint8.js';

const shaders = {
  int16: int16Shader,
  int8: int8Shader,
  rgb: rgbShader,
  uint16: uint16Shader,
  uint8: uint8Shader
};

const dataUtilities = {
  int16: int16DataUtilities,
  int8: int8DataUtilities,
  rgb: rgbDataUtilities,
  uint16: uint16DataUtilities,
  uint8: uint8DataUtilities
};

export { shaders, dataUtilities };


<|start_filename|>example/displayedArea/test-cases/DISA_P04.json<|end_filename|>
{
  "imageId": "example//DISA_P04",
  "minPixelValue": 0,
  "maxPixelValue": 255,
  "slope": 1.0,
  "intercept": 0,
  "windowCenter": 127.5,
  "windowWidth": 255,
  "rows": 1536,
  "columns": 1024,
  "height": 1536,
  "width": 1024,
  "color": false,
  "columnPixelSpacing": 1,
  "rowPixelSpacing": 1,
  "sizeInBytes": 1572864,
  "testCase": {
    "image": "SC image containing SMPTE pattern (magnified by factor 2.0 and 3.0 respectively), Columns 1024, Rows 1536, Bits Allocated 8, Bits Stored 8, Pixel Range 0 to +255, Pixel Representation is unsigned, Photometric Interpretation is MONOCHROME2, no LUTs",
    "pState": "Presentation Size Mode: TRUE SIZE, Displayed Area Top Left Hand Corner 1\\1, Displayed Area Bottom Right Hand Corner 1024\\1536, Presentation Pixel Aspect Ratio 0.1302089\\0.1953125",
    "result": "Display should be a normal SMPTE pattern (size: 200*200 mm)",
    "displayedArea": {
      "tlhc": {
        "x": 1,
        "y": 1
      },
      "brhc": {
        "x": 1024,
        "y": 1536
      },
      "rowPixelSpacing": 0.1302089,
      "columnPixelSpacing": 0.1953125,
      "presentationSizeMode": "TRUE SIZE"
    }
  }
}

<|start_filename|>src/colors/index.js<|end_filename|>
import { getColormap, getColormapsList } from './colormap.js';
import LookupTable from './lookupTable.js';

export default {
  getColormap,
  getColormapsList,
  LookupTable
};


<|start_filename|>src/internal/guid.js<|end_filename|>
function s4 () {
  return Math.floor((1 + Math.random()) * 0x10000).toString(16).
    substring(1);
}

/**
 * Generate a unique identifier
 *
 * @return {string} A unique identifier
 * @memberof Internal
 */
export default function () {
  return `${s4() + s4()}-${s4()}-${s4()}-${
    s4()}-${s4()}${s4()}${s4()}`;
}


<|start_filename|>src/imageLoader.js<|end_filename|>
import { getImageLoadObject, putImageLoadObject } from './imageCache.js';
import EVENTS, { events } from './events.js';
import triggerEvent from './triggerEvent.js';

/**
 * This module deals with ImageLoaders, loading images and caching images
 * @module ImageLoader
 */


const imageLoaders = {};

let unknownImageLoader;

/**
 * Load an image using a registered Cornerstone Image Loader.
 *
 * The image loader that is used will be
 * determined by the image loader scheme matching against the imageId.
 *
 * @param {String} imageId A Cornerstone Image Object's imageId
 * @param {Object} [options] Options to be passed to the Image Loader
 *
 * @returns {ImageLoadObject} An Object which can be used to act after an image is loaded or loading fails
 * @memberof ImageLoader
 */
function loadImageFromImageLoader (imageId, options) {
  const colonIndex = imageId.indexOf(':');
  const scheme = imageId.substring(0, colonIndex);
  const loader = imageLoaders[scheme];

  if (loader === undefined || loader === null) {
    if (unknownImageLoader !== undefined) {
      return unknownImageLoader(imageId);
    }

    throw new Error('loadImageFromImageLoader: no image loader for imageId');
  }

  const imageLoadObject = loader(imageId, options);

  // Broadcast an image loaded event once the image is loaded
  imageLoadObject.promise.then(function (image) {
    triggerEvent(events, EVENTS.IMAGE_LOADED, { image });
  }, function (error) {
    const errorObject = {
      imageId,
      error
    };

    triggerEvent(events, EVENTS.IMAGE_LOAD_FAILED, errorObject);
  });

  return imageLoadObject;
}

/**
 * Loads an image given an imageId and optional priority and returns a promise which will resolve to
 * the loaded image object or fail if an error occurred.  The loaded image is not stored in the cache.
 *
 * @param {String} imageId A Cornerstone Image Object's imageId
 * @param {Object} [options] Options to be passed to the Image Loader
 *
 * @returns {ImageLoadObject} An Object which can be used to act after an image is loaded or loading fails
 * @memberof ImageLoader
 */
export function loadImage (imageId, options) {
  if (imageId === undefined) {
    throw new Error('loadImage: parameter imageId must not be undefined');
  }

  const imageLoadObject = getImageLoadObject(imageId);

  if (imageLoadObject !== undefined) {
    return imageLoadObject.promise;
  }

  return loadImageFromImageLoader(imageId, options).promise;
}

//

/**
 * Loads an image given an imageId and optional priority and returns a promise which will resolve to
 * the loaded image object or fail if an error occurred. The image is stored in the cache.
 *
 * @param {String} imageId A Cornerstone Image Object's imageId
 * @param {Object} [options] Options to be passed to the Image Loader
 *
 * @returns {ImageLoadObject} Image Loader Object
 * @memberof ImageLoader
 */
export function loadAndCacheImage (imageId, options) {
  if (imageId === undefined) {
    throw new Error('loadAndCacheImage: parameter imageId must not be undefined');
  }

  let imageLoadObject = getImageLoadObject(imageId);

  if (imageLoadObject !== undefined) {
    return imageLoadObject.promise;
  }

  imageLoadObject = loadImageFromImageLoader(imageId, options);

  putImageLoadObject(imageId, imageLoadObject);

  return imageLoadObject.promise;
}

/**
 * Registers an imageLoader plugin with cornerstone for the specified scheme
 *
 * @param {String} scheme The scheme to use for this image loader (e.g. 'dicomweb', 'wadouri', 'http')
 * @param {Function} imageLoader A Cornerstone Image Loader function
 * @returns {void}
 * @memberof ImageLoader
 */
export function registerImageLoader (scheme, imageLoader) {
  imageLoaders[scheme] = imageLoader;
}

/**
 * Registers a new unknownImageLoader and returns the previous one
 *
 * @param {Function} imageLoader A Cornerstone Image Loader
 *
 * @returns {Function|Undefined} The previous Unknown Image Loader
 * @memberof ImageLoader
 */
export function registerUnknownImageLoader (imageLoader) {
  const oldImageLoader = unknownImageLoader;

  unknownImageLoader = imageLoader;

  return oldImageLoader;
}


<|start_filename|>test/internal/setDefaultViewport_test.js<|end_filename|>
import { expect, should } from 'chai'; // eslint-disable-line import/extensions
import setDefaultViewport, { state } from '../../src/internal/setDefaultViewport.js';

should();

describe('setDefaultViewport', function () {
  beforeEach(function () {
    state.viewport = {};
  });

  it('should default to an empty object if no value is provided', function () {
    setDefaultViewport();

    const currentDefaultViewport = state.viewport;
    const expectedDefaultViewport = {};

    expect(currentDefaultViewport).to.deep.equal(expectedDefaultViewport);
  });

  it('should equal the value of the provided object', function () {
    const exampleViewportDefaults = {
      pixelReplication: true,
      someOtherProperty: 'hello'
    };

    setDefaultViewport(exampleViewportDefaults);

    const currentDefaultViewport = state.viewport;
    const expectedDefaultViewport = exampleViewportDefaults;

    expect(currentDefaultViewport).to.deep.equal(expectedDefaultViewport);
  });
});


<|start_filename|>test/internal/transform_test.js<|end_filename|>
import { assert } from 'chai'; // eslint-disable-line import/extensions

import { Transform } from '../../src/internal/transform.js';

describe('Transform', function () {
  it('clone', function () {
    // Act
    const transformObject = new Transform();
    const clonedObject = transformObject.clone();

    transformObject.m[0] = 0;

    // Assert
    assert.deepEqual(clonedObject.m, [1, 0, 0, 1, 0, 0], 'cloned identity matrix.');
  });
  it('multiply', function () {
    // Act
    const transformObject = new Transform();
    const newTransformObject = new Transform();

    newTransformObject.m = [1, 2, 3, 4, 5, 6];
    transformObject.multiply(newTransformObject);
    // Assert
    assert.deepEqual(newTransformObject.m, transformObject.m, 'Multiplication works.');
  });
  it('invert', function () {
    // Act
    const transformObject = new Transform();
    const clonedObject = new Transform();

    transformObject.m = [1, 2, 3, 4, 5, 6];
    clonedObject.m = [1, 1, 1, 1, 1, 2];
    transformObject.invert();
    clonedObject.invert();
    // Assert
    assert.deepEqual(transformObject.m, [-2, 1, 3 / 2, -1 / 2, 1, -2], 'Inversion works.');
    assert.deepEqual(clonedObject.m, [Infinity, -Infinity, -Infinity, Infinity, Infinity, -Infinity], 'Noninvertible inversion.');
  });
  it('transform point', function () {
    // Act
    const transformObject = new Transform();

    transformObject.m = [6, 5, 4, 3, 2, 1];
    const transformedPoints = transformObject.transformPoint(2, 3);

    // Assert
    assert.deepEqual([transformedPoints.x, transformedPoints.y], [26, 20], 'Point transformation works.');
  });
});


<|start_filename|>src/pageToPixel.js<|end_filename|>
import { getEnabledElement } from './enabledElements.js';
import getTransform from './internal/getTransform.js';

/**
 * Converts a point in the page coordinate system to the pixel coordinate
 * system
 *
 * @param {HTMLElement} element The Cornerstone element within which the input point lies
 * @param {Number} pageX The x value in the page coordinate system
 * @param {Number} pageY The y value in the page coordinate system
 *
 * @returns {{x: Number, y: Number}} The transformed point in the pixel coordinate system
 */
export default function (element, pageX, pageY) {
  const enabledElement = getEnabledElement(element);

  if (enabledElement.image === undefined) {
    throw new Error('image has not been loaded yet');
  }

  // Convert the pageX and pageY to the canvas client coordinates
  const rect = element.getBoundingClientRect();
  const clientX = pageX - rect.left - window.pageXOffset;
  const clientY = pageY - rect.top - window.pageYOffset;

  const pt = { x: clientX,
    y: clientY };
  const transform = getTransform(enabledElement);

  transform.invert();

  return transform.transformPoint(pt.x, pt.y);
}


<|start_filename|>src/falseColorMapping.js<|end_filename|>
import { getEnabledElement } from './enabledElements.js';
import pixelDataToFalseColorData from './pixelDataToFalseColorData.js';
import { getColormap } from './colors/colormap.js';

/**
 * Retrieves the minimum and maximum pixel values from an Array of pixel data
 *
 * @param {Array} pixelData The input pixel data array
 *
 * @returns {{minPixelValue: Number, maxPixelValue: Number}} The minimum and maximum pixel values in the input Array
 */
function getPixelValues (pixelData) {
  let minPixelValue = Number.MAX_VALUE;
  let maxPixelValue = Number.MIN_VALUE;
  const len = pixelData.length;
  let pixel;

  for (let i = 0; i < len; i++) {
    pixel = pixelData[i];
    minPixelValue = minPixelValue < pixel ? minPixelValue : pixel;
    maxPixelValue = maxPixelValue > pixel ? maxPixelValue : pixel;
  }

  return {
    minPixelValue,
    maxPixelValue
  };
}

/**
 * Retrieve a function that will allow an image object to be reset to its original form
 * after a false color mapping transformation
 *
 * @param {Image} image A Cornerstone Image Object
 *
 * @return {Function} A function for resetting an Image Object to its original form
 */
function getRestoreImageMethod (image) {
  if (image.restore) {
    return image.restore;
  }

  const color = image.color;
  const rgba = image.rgba;
  const cachedLut = image.cachedLut;
  const slope = image.slope;
  const windowWidth = image.windowWidth;
  const windowCenter = image.windowCenter;
  const minPixelValue = image.minPixelValue;
  const maxPixelValue = image.maxPixelValue;

  return function () {
    image.color = color;
    image.rgba = rgba;
    image.cachedLut = cachedLut;
    image.slope = slope;
    image.windowWidth = windowWidth;
    image.windowCenter = windowCenter;
    image.minPixelValue = minPixelValue;
    image.maxPixelValue = maxPixelValue;

    if (image.origPixelData) {
      const pixelData = image.origPixelData;

      image.getPixelData = () => pixelData;
    }

    // Remove some attributes added by false color mapping
    image.origPixelData = undefined;
    image.colormapId = undefined;
    image.falseColor = undefined;
  };
}

//
// Then we need to make sure it will be converted into a colormap object if it's as string.

/**
 * User can pass a colormap or its id as string to some of these public functions.
 * Then we need to make sure it will be converted into a colormap object if it's a string.
 *
 * @param {*} colormap A colormap ID or Object
 * @return {*} The colormap
 */
function ensuresColormap (colormap) {
  if (colormap && (typeof colormap === 'string')) {
    colormap = getColormap(colormap);
  }

  return colormap;
}

/**
 * Restores a false color image to its original version
 *
 * @param {Image} image A Cornerstone Image Object
 * @returns {Boolean} True if the image object had a valid restore function, which was run. Otherwise, false.
 */
function restoreImage (image) {
  if (image.restore && (typeof image.restore === 'function')) {
    image.restore();

    return true;
  }

  return false;
}

/**
 * Convert an image to a false color image
 *
 * @param {Image} image A Cornerstone Image Object
 * @param {String|Object} colormap - it can be a colormap object or a colormap id (string)
 *
 * @returns {Boolean} - Whether or not the image has been converted to a false color image
 */
function convertImageToFalseColorImage (image, colormap) {
  if (image.color && !image.falseColor) {
    throw new Error('Color transforms are not implemented yet');
  }

  // User can pass a colormap id or a colormap object
  colormap = ensuresColormap(colormap);

  const colormapId = colormap.getId();

  // Doesn't do anything if colormapId hasn't changed
  if (image.colormapId === colormapId) {
    // It has already being converted into a false color image
    // Using the colormapId passed as parameter
    return false;
  }

  // Restore the image attributes updated when converting to a false color image
  restoreImage(image);

  // Convert the image to a false color image
  if (colormapId) {
    const minPixelValue = image.minPixelValue || 0;
    const maxPixelValue = image.maxPixelValue || 255;

    image.restore = getRestoreImageMethod(image);

    const lookupTable = colormap.createLookupTable();

    lookupTable.setTableRange(minPixelValue, maxPixelValue);

    // Update the pixel data and render the new image
    pixelDataToFalseColorData(image, lookupTable);

    // Update min and max pixel values
    const pixelValues = getPixelValues(image.getPixelData());

    image.minPixelValue = pixelValues.minPixelValue;
    image.maxPixelValue = pixelValues.maxPixelValue;

    image.windowWidth = 255;
    image.windowCenter = 128;

    // Cache the last colormapId used for performance
    // Then it doesn't need to be re-rendered on next
    // Time if the user hasn't updated it
    image.colormapId = colormapId;
  }

  // Return `true` to tell the caller that the image has got updated
  return true;
}

/**
 * Convert the image of a element to a false color image
 *
 * @param {HTMLElement} element The Cornerstone element
 * @param {*} colormap - it can be a colormap object or a colormap id (string)
 *
 * @returns {void}
 */
function convertToFalseColorImage (element, colormap) {
  const enabledElement = getEnabledElement(element);


  return convertImageToFalseColorImage(enabledElement.image, colormap);
}

export { convertImageToFalseColorImage,
  convertToFalseColorImage,
  restoreImage };


<|start_filename|>test/internal/getCanvas_test.js<|end_filename|>
import { assert } from 'chai'; // eslint-disable-line import/extensions

import getCanvas from '../../src/internal/getCanvas.js';

describe('getCanvas', function () {
  beforeEach(function () {
    this.parentElement = document.createElement('div');
  });

  describe('when a canvas is not available in the DOM', function () {
    it('should create a canvas and append it to the parent element', function () {
      const canvasCreated = getCanvas(this.parentElement);
      const canvasSelected = this.parentElement.querySelector('canvas.cornerstone-canvas');

      assert.exists(canvasCreated);
      assert.equal(canvasCreated, canvasSelected);
    });

    it('should return the same canvas if called twice', function () {
      const firstCanvas = getCanvas(this.parentElement);
      const secondCanvas = getCanvas(this.parentElement);
      const canvasCount = this.parentElement.getElementsByTagName('canvas').length;

      assert.equal(canvasCount, 1);
      assert.equal(firstCanvas, secondCanvas);
    });
  });

  describe('when a canvas is already available in the DOM', function () {
    beforeEach(function () {
      this.canvas = document.createElement('canvas');
      this.canvas.classList.add('cornerstone-canvas');
      this.parentElement.appendChild(this.canvas);
    });

    it('should return the canvas that already exists instead of creating a new one', function () {
      const canvasReturned = getCanvas(this.parentElement);
      const canvasCount = this.parentElement.getElementsByTagName('canvas').length;

      assert.equal(canvasCount, 1);
      assert.equal(canvasReturned, this.canvas);
    });
  });
});


<|start_filename|>test/internal/getModalityLUT_test.js<|end_filename|>
import { assert } from 'chai'; // eslint-disable-line import/extensions

import getModalityLUT from '../../src/internal/getModalityLUT.js';

describe('getModalityLUT', function () {
  beforeEach(function () {
    // Arrange
    this.slope = 2;
    this.intercept = 5;
    this.modalityLUT = {
      firstValueMapped: 0,
      lut: [0, 128, 255]
    };
  });

  it('should create a linear modality LUT function', function () {
    // Arrange
    // Act
    const mlutfn = getModalityLUT(this.slope, this.intercept);

    // Assert
    assert.equal(mlutfn(-1), 3);
    assert.equal(mlutfn(0), 5);
    assert.equal(mlutfn(1), 7);
    assert.equal(mlutfn(2), 9);
    assert.equal(mlutfn(3), 11);
  });

  it('should create a non-linear modality LUT function', function () {
    // Act
    const mlutfn = getModalityLUT(this.slope, this.intercept, this.modalityLUT);

    // Assert
    assert.equal(mlutfn(-1), 0);
    assert.equal(mlutfn(0), 0);
    assert.equal(mlutfn(1), 128);
    assert.equal(mlutfn(2), 255);
    assert.equal(mlutfn(3), 255);
  });
});


<|start_filename|>src/getDefaultViewportForImage.js<|end_filename|>
import { getEnabledElement } from './enabledElements.js';
import getDefaultViewport from './internal/getDefaultViewport.js';

/**
 * Returns a default viewport for display the specified image on the specified
 * enabled element.  The default viewport is fit to window
 *
 * @param {HTMLElement} element The DOM element enabled for Cornerstone
 * @param {Image} image A Cornerstone Image Object
 *
 * @returns {Viewport} The default viewport for the image
 */
export default function (element, image) {
  const enabledElement = getEnabledElement(element);

  return getDefaultViewport(enabledElement.canvas, image);
}


<|start_filename|>src/internal/getImageSize.js<|end_filename|>
import { validateParameterUndefinedOrNull } from './validator.js';

/**
 * Check if the angle is rotated
 * @param {Number} rotation the rotation angle
 * @returns {Boolean} true if the angle is rotated; Otherwise, false.
 * @memberof Internal
 */
function isRotated (rotation) {
  return !(rotation === null || rotation === undefined || rotation === 0 || rotation === 180);
}

/**
 * Retrieves the current image dimensions given an enabled element
 *
 * @param {any} image The Cornerstone image.
 * @param {Number} rotation Optional. The rotation angle of the image.
 * @return {{width:Number, height:Number}} The Image dimensions
 * @memberof Internal
 */
export default function (image, rotation = null) {

  validateParameterUndefinedOrNull(image, 'getImageSize: parameter image must not be undefined');
  validateParameterUndefinedOrNull(image.width, 'getImageSize: parameter image must have width');
  validateParameterUndefinedOrNull(image.height, 'getImageSize: parameter image must have height');


  if (isRotated(rotation)) {
    return {
      height: image.width,
      width: image.height
    };
  }

  return {
    width: image.width,
    height: image.height
  };
}


<|start_filename|>src/rendering/renderToCanvas.js<|end_filename|>
import triggerEvent from '../triggerEvent.js';
import EVENTS from '../events.js';
import drawImageSync from '../internal/drawImageSync.js';
import getDefaultViewport from '../internal/getDefaultViewport.js';
import tryEnableWebgl from '../internal/tryEnableWebgl.js';

/**
 * @typedef {Object} EnabledElementStub
 * @property {HTMLElement} element  The enabled element
 * @property {HTMLCanvasElement} canvas The current canvas
 * @property {Object} image Currently displayed image
 * @property {Boolean} invalid Whether or not the image pixel data has been changed
 * @property {Boolean} needsRedraw  A flag for triggering a redraw of the canvas without re-retrieving the pixel data, since it remains valid
 * @property {Object} options Layer drawing options
 * @property {Object[]} layers Layers added to the EnabledElement
 * @property {Object} data
 * @property {Object} renderingTools
 * @property {Object} viewport The current viewport
 * @memberof rendering
 */

/**
 * creates a dummy enabled element
 *
 * @param {HTMLCanvasElement} canvas the canvas that will be assigned to the enabled element.
 * @param {any} image An Image loaded by a Cornerstone Image Loader
 * @param { any } options Options for rendering the image (e.g.enable webgl by {renderer: 'webgl' })
 * @param { any } viewport A set of Cornerstone viewport parameters
 * @returns {EnabledElementStub} a dummy enabled element
 * @memberof rendering
 */
function createEnabledElementStub (canvas, image, options, viewport) {
  return {
    element: canvas,
    canvas,
    image,
    invalid: true, // True if image needs to be drawn, false if not
    needsRedraw: true,
    options,
    layers: [],
    data: {},
    renderingTools: {},
    viewport
  };
}

/**
 * Render the image to the provided canvas immediately.
 * @param {any} canvas The HTML canvas where the image will be rendered.
 * @param {any} image An Image loaded by a Cornerstone Image Loader
 * @param {any} [viewport = null] A set of Cornerstone viewport parameters
 * @param {any} [options = null] Options for rendering the image (e.g. enable webgl by {renderer: 'webgl'})
 * @returns {void}
 * @memberof rendering
 */
export default function (canvas, image, viewport = null, options = null) {
  if (canvas === undefined) {
    throw new Error('renderToCanvas: parameter canvas cannot be undefined');
  }

  // If this enabled element has the option set for WebGL, we should
  // Check if this device actually supports it
  if (options && options.renderer && options.renderer.toLowerCase() === 'webgl') {
    tryEnableWebgl(options);
  }

  const defaultViewport = getDefaultViewport(canvas, image);

  if (viewport) {
    Object.assign(defaultViewport, viewport);
  }

  const enabledElementStub = createEnabledElementStub(canvas, image, options, defaultViewport);

  const eventDetails = {
    enabledElement: enabledElementStub,
    timestamp: Date.now()
  };

  triggerEvent(enabledElementStub.element, EVENTS.PRE_RENDER, eventDetails);

  drawImageSync(enabledElementStub, enabledElementStub.invalid);
}


<|start_filename|>src/enabledElementData.js<|end_filename|>
import { getEnabledElement } from './enabledElements.js';

/**
 * Retrieves any data for a Cornerstone enabledElement for a specific string
 * dataType
 *
 * @param {HTMLElement} element An HTML Element enabled for Cornerstone
 * @param {string} dataType A string name for an arbitrary set of data
 * @returns {*} Whatever data is stored for this enabled element
 */
export function getElementData (element, dataType) {
  const ee = getEnabledElement(element);

  if (ee.data.hasOwnProperty(dataType) === false) {
    ee.data[dataType] = {};
  }

  return ee.data[dataType];
}

/**
 * Clears any data for a Cornerstone enabledElement for a specific string
 * dataType
 *
 * @param {HTMLElement} element An HTML Element enabled for Cornerstone
 * @param {string} dataType A string name for an arbitrary set of data
 *
 * @returns {void}
 */
export function removeElementData (element, dataType) {
  const ee = getEnabledElement(element);

  delete ee.data[dataType];
}


<|start_filename|>src/internal/index.js<|end_filename|>
import { Transform } from './transform.js';
import calculateTransform from './calculateTransform.js';
import drawImage from './drawImage.js';
import generateLut from './generateLut.js';
import getDefaultViewport from './getDefaultViewport.js';
import getTransform from './getTransform.js';
import requestAnimationFrame from './requestAnimationFrame.js';
import setDefaultViewport from './setDefaultViewport.js';
import storedColorPixelDataToCanvasImageData from './storedColorPixelDataToCanvasImageData.js';
import storedPixelDataToCanvasImageData from './storedPixelDataToCanvasImageData.js';
import storedPixelDataToCanvasImageDataColorLUT from './storedPixelDataToCanvasImageDataColorLUT.js';
import storedPixelDataToCanvasImageDataPseudocolorLUT from './storedPixelDataToCanvasImageDataPseudocolorLUT.js';
import storedPixelDataToCanvasImageDataRGBA from './storedPixelDataToCanvasImageDataRGBA.js';

/**
 * @module Internal
 */
export default {
  drawImage,
  generateLut,
  getDefaultViewport,
  requestAnimationFrame,
  setDefaultViewport,
  storedPixelDataToCanvasImageData,
  storedPixelDataToCanvasImageDataRGBA,
  storedPixelDataToCanvasImageDataColorLUT,
  storedPixelDataToCanvasImageDataPseudocolorLUT,
  storedColorPixelDataToCanvasImageData,
  getTransform,
  calculateTransform,
  Transform
};


<|start_filename|>example/displayedArea/test-cases/DISA_P05.json<|end_filename|>
{
  "imageId": "example//DISA_P05",
  "minPixelValue": 0,
  "maxPixelValue": 255,
  "slope": 1.0,
  "intercept": 0,
  "windowCenter": 127.5,
  "windowWidth": 255,
  "rows": 1024,
  "columns": 512,
  "height": 1024,
  "width": 512,
  "color": false,
  "columnPixelSpacing": 1,
  "rowPixelSpacing": 1,
  "sizeInBytes": 524288,
  "testCase": {
    "image": "SC image containing SMPTE pattern (height magnified by factor 2.0), Columns 512, Rows 1024, Bits Allocated 8, Bits Stored 8, Pixel Range 0 to +255, Pixel Representation is unsigned, Photometric Interpretation is MONOCHROME2, no LUTs",
    "pState": "Presentation Size Mode: SCALE TO FIT, Displayed Area Top Left Hand Corner 1\\1, Displayed Area Bottom Right Hand Corner 512\\1024, Presentation Pixel Aspect Ratio 1\\2",
    "result": "Display should be a normal SMPTE pattern (full screen)",
    "displayedArea": {
      "tlhc": {
        "x": 1,
        "y": 1
      },
      "brhc": {
        "x": 512,
        "y": 1024
      },
      "rowPixelSpacing": 1,
      "columnPixelSpacing": 2,
      "presentationSizeMode": "SCALE TO FIT"
    }
  }
}

<|start_filename|>src/internal/getModalityLUT.js<|end_filename|>
/**
 * Generates a linear modality transformation function
 *
 * See DICOM PS3.3 C.11.1 Modality LUT Module
 *
 * http://dicom.nema.org/medical/Dicom/current/output/chtml/part03/sect_C.11.html
 *
 * @param {Number} slope m in the equation specified by Rescale Intercept (0028,1052).
 * @param {Number} intercept The value b in relationship between stored values (SV) and the output units specified in Rescale Type (0028,1054).

 Output units = m*SV + b.
 * @return {function(*): *} A linear modality LUT function. Given a stored pixel it returns the modality pixel value
 * @memberof Internal
 */
function generateLinearModalityLUT (slope, intercept) {
  return (storedPixelValue) => storedPixelValue * slope + intercept;
}

function generateNonLinearModalityLUT (modalityLUT) {
  const minValue = modalityLUT.lut[0];
  const maxValue = modalityLUT.lut[modalityLUT.lut.length - 1];
  const maxValueMapped = modalityLUT.firstValueMapped + modalityLUT.lut.length;

  return (storedPixelValue) => {
    if (storedPixelValue < modalityLUT.firstValueMapped) {
      return minValue;
    } else if (storedPixelValue >= maxValueMapped) {
      return maxValue;
    }

    return modalityLUT.lut[storedPixelValue];
  };
}

/**
 * Get the appropriate Modality LUT for the current situation.
 *
 * @param {Number} [slope] m in the equation specified by Rescale Intercept (0028,1052).
 * @param {Number} [intercept] The value b in relationship between stored values (SV) and the output units specified in Rescale Type (0028,1054).
 * @param {Function} [modalityLUT] A modality LUT function. Given a stored pixel it returns the modality pixel value.
 *
 * @return {function(*): *} A modality LUT function. Given a stored pixel it returns the modality pixel value.
 * @memberof Internal
 */
export default function (slope, intercept, modalityLUT) {
  if (modalityLUT) {
    return generateNonLinearModalityLUT(modalityLUT);
  }

  return generateLinearModalityLUT(slope, intercept);
}


<|start_filename|>src/internal/requestAnimationFrame.js<|end_filename|>
function requestFrame (callback) {
  window.setTimeout(callback, 1000 / 60);
}

/**
 * Polyfills requestAnimationFrame for older browsers.
 *
 * @param {Function} callback A parameter specifying a function to call when it's time to update your animation for the next repaint. The callback has one single argument, a DOMHighResTimeStamp, which indicates the current time (the time returned from performance.now() ) for when requestAnimationFrame starts to fire callbacks.
 *
 * @return {Number} A long integer value, the request id, that uniquely identifies the entry in the callback list. This is a non-zero value, but you may not make any other assumptions about its value. You can pass this value to window.cancelAnimationFrame() to cancel the refresh callback request.
 * @memberof Polyfills
 */
export default function (callback) {
  return window.requestAnimationFrame(callback) ||
    window.webkitRequestAnimationFrame(callback) ||
    window.mozRequestAnimationFrame(callback) ||
    window.oRequestAnimationFrame(callback) ||
    window.msRequestAnimationFrame(callback) ||
    requestFrame(callback);
}


<|start_filename|>src/internal/getCanvas.js<|end_filename|>
const CANVAS_CSS_CLASS = 'cornerstone-canvas';

/**
 * Create a canvas and append it to the element
 *
 * @param {HTMLElement} element An HTML Element
 * @return {HTMLElement} canvas A Canvas DOM element
 */
function createCanvas (element) {
  const canvas = document.createElement('canvas');

  canvas.style.display = 'block';
  canvas.classList.add(CANVAS_CSS_CLASS);
  element.appendChild(canvas);

  return canvas;
}

/**
 * Create a canvas or returns the one that already exists for a given element
 *
 * @param {HTMLElement} element An HTML Element
 * @return {HTMLElement} canvas A Canvas DOM element
 */
export default function getCanvas (element) {
  const selector = `canvas.${CANVAS_CSS_CLASS}`;

  return element.querySelector(selector) || createCanvas(element);
}


<|start_filename|>src/internal/getTransform.js<|end_filename|>
import calculateTransform from './calculateTransform.js';

export default function (enabledElement) {
  // For now we will calculate it every time it is requested.
  // In the future, we may want to cache it in the enabled element to speed things up.
  return calculateTransform(enabledElement);
}


<|start_filename|>src/webgl/vertexShader.js<|end_filename|>
export const vertexShader = 'attribute vec2 a_position;' +
    'attribute vec2 a_texCoord;' +
    'uniform vec2 u_resolution;' +
    'varying vec2 v_texCoord;' +
    'void main() {' +
        'vec2 zeroToOne = a_position / u_resolution;' +
        'vec2 zeroToTwo = zeroToOne * 2.0;' +
        'vec2 clipSpace = zeroToTwo - 1.0;' +
        'gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);' +
        'v_texCoord = a_texCoord;' +
    '}';


<|start_filename|>src/getViewport.js<|end_filename|>
import { getEnabledElement } from './enabledElements.js';

/**
 * Retrieves the viewport for the specified enabled element
 *
 * @param {HTMLElement} element The DOM element enabled for Cornerstone
 * @returns {Viewport|undefined} The Cornerstone Viewport settings for this element, if they exist. Otherwise, undefined
 * @memberof ViewportSettings
 */
export default function (element) {
  const enabledElement = getEnabledElement(element);
  const viewport = enabledElement.viewport;

  if (viewport === undefined) {
    return;
  }

  // Return a copy of the viewport
  return Object.assign({}, viewport);
}


<|start_filename|>src/rendering/doesImageNeedToBeRendered.js<|end_filename|>
/**
 * Determine whether or not an Enabled Element needs to be re-rendered.
 *
 * If the imageId has changed, or if any of the last rendered viewport
 * parameters have changed, this function will return true.
 *
 * @param {EnabledElement} enabledElement An Enabled Element
 * @param {Image} image An Image
 * @return {boolean} Whether or not the Enabled Element needs to re-render its image
 * @memberof rendering
 */
export default function (enabledElement, image) {
  const lastRenderedImageId = enabledElement.renderingTools.lastRenderedImageId;
  const lastRenderedViewport = enabledElement.renderingTools.lastRenderedViewport;

  return (
    image.imageId !== lastRenderedImageId ||
    !lastRenderedViewport ||
    lastRenderedViewport.windowCenter !== enabledElement.viewport.voi.windowCenter ||
    lastRenderedViewport.windowWidth !== enabledElement.viewport.voi.windowWidth ||
    lastRenderedViewport.invert !== enabledElement.viewport.invert ||
    lastRenderedViewport.rotation !== enabledElement.viewport.rotation ||
    lastRenderedViewport.hflip !== enabledElement.viewport.hflip ||
    lastRenderedViewport.vflip !== enabledElement.viewport.vflip ||
    lastRenderedViewport.modalityLUT !== enabledElement.viewport.modalityLUT ||
    lastRenderedViewport.voiLUT !== enabledElement.viewport.voiLUT ||
    lastRenderedViewport.colormap !== enabledElement.viewport.colormap
  );
}


<|start_filename|>src/internal/computeAutoVoi.js<|end_filename|>
/**
 * Computes the VOI to display all the pixels if no VOI LUT data (Window Width/Window Center or voiLUT) exists on the viewport object.
 *
 * @param {Viewport} viewport - Object containing the viewport properties
 * @param {Object} image An Image loaded by a Cornerstone Image Loader
 * @returns {void}
 * @memberof Internal
 */
export default function computeAutoVoi (viewport, image) {
  if (hasVoi(viewport)) {
    return;
  }

  const maxVoi = image.maxPixelValue * image.slope + image.intercept;
  const minVoi = image.minPixelValue * image.slope + image.intercept;
  const ww = maxVoi - minVoi;
  const wc = (maxVoi + minVoi) / 2;

  if (viewport.voi === undefined) {
    viewport.voi = {
      windowWidth: ww,
      windowCenter: wc
    };
  } else {
    viewport.voi.windowWidth = ww;
    viewport.voi.windowCenter = wc;
  }
}

/**
 * Check if viewport has voi LUT data
 * @param {any} viewport The viewport to check for voi LUT data
 * @returns {Boolean} true viewport has LUT data (Window Width/Window Center or voiLUT). Otherwise, false.
 * @memberof Internal
 */
function hasVoi (viewport) {
  const hasLut = viewport.voiLUT && viewport.voiLUT.lut && viewport.voiLUT.lut.length > 0;

  return hasLut || (viewport.voi.windowWidth !== undefined && viewport.voi.windowCenter !== undefined);
}


<|start_filename|>example/tools/all/index.html<|end_filename|>
<!DOCTYPE HTML>
<html>
<head>
    <!-- twitter bootstrap CSS stylesheet - not required by cornerstone -->
    <link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container">

    <h1>
        tools/all/index.html
    </h1>

    Tools have been refactored out of this library and into the <a href="https://github.com/cornerstonejs/cornerstoneTools">cornerstoneTools</a> library.  You can
    find relevant examples <a href="https://rawgithub.com/cornerstonejs/cornerstoneTools/master/examples/index.html">here</a>

</div>
</body>
</html>


<|start_filename|>test/internal/storedColorPixelDataToCanvasImageData_test.js<|end_filename|>
import { should } from 'chai'; // eslint-disable-line import/extensions
import storedColorPixelDataToCanvasImageData from '../../src/internal/storedColorPixelDataToCanvasImageData.js';

should();

describe('storedColorPixelDataToCanvasImageData', function () {
  before(function () {
    this.image = {
      getPixelData () {
        return [1, 2, 3, 4, 2, 0, 1, 0];
      },
      stats: {}
    };
    this.lut = [1, 2, 3, 4, 5, 6, 7, 8];
  });

  describe('pixel value less than 0', function () {
    before(function () {
      this.image.minPixelValue = -3;
    });

    it('should generate the image subtracting the minimum pixel value', function () {
      const canvasImageDataData = [0, 0, 0, 0, 0, 0, 0, 0];

      storedColorPixelDataToCanvasImageData(this.image, this.lut, canvasImageDataData);

      canvasImageDataData.should.be.deep.equal([5, 6, 7, 0, 6, 4, 5, 0]);
    });
  });

  describe('pixel value is equal to or greater than 0', function () {
    before(function () {
      this.image.minPixelValue = 0;
    });

    it('should generate the image just using the lookup table', function () {
      const canvasImageDataData = [0, 0, 0, 0, 0, 0, 0, 0];

      storedColorPixelDataToCanvasImageData(this.image, this.lut, canvasImageDataData);

      canvasImageDataData.should.be.deep.equal([2, 3, 4, 0, 3, 1, 2, 0]);
    });
  });
});


<|start_filename|>test/internal/generateLut_test.js<|end_filename|>
import { assert } from 'chai'; // eslint-disable-line import/extensions

import generateLut from '../../src/internal/generateLut.js';

describe('generateLut', function () {
  it('min pixel < 0', function () {
    // Arrange
    const image = {
      minPixelValue: -1,
      maxPixelValue: 1,
      slope: 1.0,
      intercept: 0,
      windowCenter: 0,
      windowWidth: 2
    };

    // Act
    const lut = generateLut(image, 2, 0, false);

    // Assert
    assert.equal(lut.length, 3, 'lut length is 3');
    assert.equal(lut[0], 0, 'lut entry -1 is 0');
    assert.equal(lut[1], 128, 'lut entry 0 is 128');
    assert.equal(lut[2], 255, 'lut entry 1 is 255');
  });

  it('min pixel = 0', function () {
    // Arrange
    const image = {
      minPixelValue: 0,
      maxPixelValue: 2,
      slope: 1.0,
      intercept: 0,
      windowCenter: 1,
      windowWidth: 2
    };

    // Act
    const lut = generateLut(image, 2, 1, false);

    // Assert
    assert.equal(lut.length, 3, 'lut length is 3');
    assert.equal(lut[0], 0, 'lut entry 0 is 0');
    assert.equal(lut[1], 128, 'lut entry 1 is 128');
    assert.equal(lut[2], 255, 'lut entry 2 is 255');
  });

  it('min pixel > 0', function () {
    // Arrange
    const image = {
      minPixelValue: 1,
      maxPixelValue: 3,
      slope: 1.0,
      intercept: 0,
      windowCenter: 2,
      windowWidth: 2
    };

    // Act
    const lut = generateLut(image, 2, 2, false);

    // Assert
    assert.equal(lut.length, 4, 'lut length is 4');
    assert.equal(lut[0], 0, 'lut entry 0 is 0');
    assert.equal(lut[1], 0, 'lut entry 1 is 0');
    assert.equal(lut[2], 128, 'lut entry 2 is 128');
    assert.equal(lut[3], 255, 'lut entry 3 is 255');
  });

  it('slope and intercept', function () {
    // Arrange
    const image = {
      minPixelValue: 0,
      maxPixelValue: 2,
      slope: 2.0,
      intercept: 1,
      windowCenter: 3,
      windowWidth: 4
    };

    // Act
    const lut = generateLut(image, 4, 3, false);

    // Assert
    assert.equal(lut.length, 3, 'lut length is 3');
    assert.equal(lut[0], 0, 'lut entry 0 is 0');
    assert.equal(lut[1], 128, 'lut entry 1 is 128');
    assert.equal(lut[2], 255, 'lut entry 2 is 255');
  });

  it('should handle inverted images correctly', function () {
    // Arrange
    const image = {
      minPixelValue: 0,
      maxPixelValue: 2,
      slope: 2.0,
      intercept: 1,
      windowCenter: 3,
      windowWidth: 4
    };

    // Act
    const lut = generateLut(image, 4, 3, true);

    // Assert
    assert.equal(lut.length, 3, 'lut length is 3');
    assert.equal(lut[0], 255, 'lut entry 0 is 255');
    assert.equal(lut[1], 128, 'lut entry 1 is 128');
    assert.equal(lut[2], 0, 'lut entry 2 is 0');
  });
});


<|start_filename|>src/internal/validator.js<|end_filename|>

/**
 * Check if the supplied parameter is undefined and throws and error
 * @param {any} checkParam the parameter to validate for undefined
 * @param {any} errorMsg the error message to be thrown
 * @returns {void}
 * @memberof internal
 */
export function validateParameterUndefined (checkParam, errorMsg) {
  if (checkParam === undefined) {
    throw new Error(errorMsg);
  }
}


/**
 * Check if the supplied parameter is undefined or null and throws and error
 * @param {any} checkParam the parameter to validate for undefined
 * @param {any} errorMsg the error message to be thrown
 * @returns {void}
 * @memberof internal
 */
export function validateParameterUndefinedOrNull (checkParam, errorMsg) {
  if (checkParam === undefined || checkParam === null) {
    throw new Error(errorMsg);
  }
}


<|start_filename|>test/internal/storedPixelDataToCanvasImageData_test.js<|end_filename|>
import { should } from 'chai'; // eslint-disable-line import/extensions
import storedPixelDataToCanvasImageData from '../../src/internal/storedPixelDataToCanvasImageData.js';

should();

describe('storedPixelDataToCanvasImageData', function () {
  before(function () {
    this.lut = [0, 255];
    // Arrange
    this.image = {
      maxPixelValue: 1,
      width: 1,
      height: 2,
      stats: {}
    };
  });

  beforeEach(function () {
    this.canvasImageDataData = [255, 255, 255, 128, 255, 255, 255, 128];
  });

  describe('Uint16Array', function () {
    before(function () {
      this.image.getPixelData = function () {
        return new Uint16Array([0, 1]);
      };
    });

    it('storedPixelDataToCanvasImageData minPixel = 0', function () {
      this.image.minPixelValue = 0;

      // Act
      storedPixelDataToCanvasImageData(this.image, this.lut, this.canvasImageDataData);

      this.canvasImageDataData.should.be.deep.equal([255, 255, 255, 0, 255, 255, 255, 255]);
    });

    it('storedPixelDataToCanvasImageData minPixel > 0', function () {
      this.image.minPixelValue = 1;
      this.image.getPixelData = function () {
        return new Uint16Array([1, 1]);
      };

      // Act
      storedPixelDataToCanvasImageData(this.image, this.lut, this.canvasImageDataData);

      this.canvasImageDataData.should.be.deep.equal([255, 255, 255, 255, 255, 255, 255, 255]);
    });
  });

  describe('int16Array', function () {
    before(function () {
      // Arrange
      this.lut = [0, 255];
      this.image = {
        minPixelValue: -1,
        maxPixelValue: 0,
        width: 1,
        height: 2,
        getPixelData () {
          return new Int16Array([-1, 0]);
        },
        stats: {}
      };
    });

    beforeEach(function () {
      this.canvasImageDataData = [255, 255, 255, 128, 255, 255, 255, 128];
    });

    it('storedPixelDataToCanvasImageData minPixel < 0', function () {
      // Act
      storedPixelDataToCanvasImageData(this.image, this.lut, this.canvasImageDataData);

      this.canvasImageDataData.should.be.deep.equal([255, 255, 255, 0, 255, 255, 255, 255]);
    });

    it('storedPixelDataToCanvasImageData minPixel > 0', function () {
      this.image.minPixelValue = 1;
      this.image.getPixelData = function () {
        return new Int16Array([1, 0]);
      };

      // Act
      storedPixelDataToCanvasImageData(this.image, this.lut, this.canvasImageDataData);

      this.canvasImageDataData.should.be.deep.equal([255, 255, 255, 255, 255, 255, 255, 0]);
    });
  });

  describe('regular Array', function () {
    it('storedPixelDataToCanvasImageData minPixel < 0', function () {
      this.image.minPixelValue = -1;
      this.image.maxPixelValue = 0;
      this.image.getPixelData = function () {
        return [-1, 0];
      };

      storedPixelDataToCanvasImageData(this.image, this.lut, this.canvasImageDataData);

      this.canvasImageDataData.should.be.deep.equal([255, 255, 255, 0, 255, 255, 255, 255]);
    });
  });
});


<|start_filename|>test/internal/getImageSize_test.js<|end_filename|>
import { should, expect } from 'chai'; // eslint-disable-line import/extensions

import getImageSize from '../../src/internal/getImageSize.js';

should();

describe('getImageSize', function () {

  describe('when image parameters is not passed', function () {
    it('should throw an error', function () {

      expect(function () {
        getImageSize();
      }).to.throw('getImageSize: parameter image must not be undefined');

      expect(function () {
        getImageSize({ width: 50 });
      }).to.throw('getImageSize: parameter image must have height');

      expect(function () {
        getImageSize({ height: 100 });
      }).to.throw('getImageSize: parameter image must have width');
    });
  });

  describe('when an image is passed with no rotation', function () {
    it('should return the image width/height', function () {
      const image = {
        width: 50,
        height: 100
      };

      const imageSizeNoRotationParameter = getImageSize(image);
      const imageSize0RotationParameter = getImageSize(image, 0);
      const imageSize180RotationParameter = getImageSize(image, 180);

      imageSizeNoRotationParameter.should.be.deep.equal(image);
      imageSize0RotationParameter.should.be.deep.equal(image);
      imageSize180RotationParameter.should.be.deep.equal(image);
    });
  });

  describe('when an image is passed rotated', function () {
    it('should return the image width/height rotated', function () {
      const image = {
        width: 50,
        height: 100
      };

      const returnedImageSize = getImageSize(image, 90);

      // rotate
      image.width = 100;
      image.height = 50;

      returnedImageSize.should.be.deep.equal(image);
    });
  });
});


<|start_filename|>src/getPixels.js<|end_filename|>
import { getEnabledElement } from './enabledElements.js';
import getStoredPixels from './getStoredPixels.js';
import getModalityLUT from './internal/getModalityLUT.js';

/**
 * Retrieves an array of pixels from a rectangular region with modality LUT transformation applied
 *
 * @param {HTMLElement} element The DOM element enabled for Cornerstone
 * @param {Number} x The x coordinate of the top left corner of the sampling rectangle in image coordinates
 * @param {Number} y The y coordinate of the top left corner of the sampling rectangle in image coordinates
 * @param {Number} width The width of the of the sampling rectangle in image coordinates
 * @param {Number} height The height of the of the sampling rectangle in image coordinates
 * @returns {Array} The modality pixel value of the pixels in the sampling rectangle
 */
export default function (element, x, y, width, height) {
  const storedPixels = getStoredPixels(element, x, y, width, height);
  const ee = getEnabledElement(element);
  const mlutfn = getModalityLUT(ee.image.slope, ee.image.intercept, ee.viewport.modalityLUT);

  return storedPixels.map(mlutfn);
}


<|start_filename|>src/rendering/lutMatches.js<|end_filename|>
/**
 * Check if two lookup tables match
 *
 * @param {LUT} a A lookup table function
 * @param {LUT} b Another lookup table function
 * @return {boolean} Whether or not they match
 * @memberof rendering
 */
export default function (a, b) {
  // If undefined, they are equal
  if (!a && !b) {
    return true;
  }
  // If one is undefined, not equal
  if (!a || !b) {
    return false;
  }

  // Check the unique ids
  return (a.id === b.id);
}


<|start_filename|>test/internal/generateLutNew_test.js<|end_filename|>
// import { assert } from 'chai'; // eslint-disable-line import/extensions

import generateLut from '../../src/internal/generateLut.js';

describe('generateLutNew', function () {
  beforeEach(function () {
    this.windowWidth = 255;
    this.windowCenter = 127;

    this.voiLUT = {
      firstValueMapped: 0,
      numBitsPerEntry: 8,
      lut: [0, 128, 255]
    };

  });

  it('min pixel < 0', function () {
    // Arrange
    const image = {
      minPixelValue: -2,
      maxPixelValue: 2,
      slope: 1.0,
      intercept: 0,
      windowCenter: 1,
      windowWidth: 2
    };

    const invert = false;

    // Act
    generateLut(image, this.windowWidth, this.windowCenter, invert, this.modalityLUT, this.voiLUT);

    // Assert
    // assert.equal(lut.length, 3, 'lut length is 3');
    // assert.equal(lut[0], 0, 'lut entry 0 is 0');
    // assert.equal(lut[1], 128, 'lut entry 1 is 128');
    // assert.equal(lut[2], 255, 'lut entry 2 is 255');
  });

  it('min pixel = 0', function () {
    // Arrange
    const image = {
      minPixelValue: 0,
      maxPixelValue: 2,
      slope: 1.0,
      intercept: 0,
      windowCenter: 1,
      windowWidth: 2
    };

    const invert = false;

    // Act
    generateLut(image, this.windowWidth, this.windowCenter, invert, this.modalityLUT, this.voiLUT);

    // Assert
    // assert.equal(lut.length, 3, 'lut length is 3');
    // assert.equal(lut[0], 0, 'lut entry 0 is 0');
    // assert.equal(lut[1], 128, 'lut entry 1 is 128');
    // assert.equal(lut[2], 255, 'lut entry 2 is 255');
  });

  it('should handle inverted images', function () {
    // Arrange
    const image = {
      minPixelValue: 0,
      maxPixelValue: 2,
      slope: 1.0,
      intercept: 0,
      windowCenter: 1,
      windowWidth: 2
    };

    const invert = true;

    // Act
    generateLut(image, this.windowWidth, this.windowCenter, invert, this.modalityLUT, this.voiLUT);

    // Assert
    // assert.equal(lut.length, 3, 'lut length is 3');
    // assert.equal(lut[0], 255, 'lut entry 0 is 255');
    // assert.equal(lut[1], 127, 'lut entry 1 is 127');
    // assert.equal(lut[2], 0, 'lut entry 2 is 0');
  });
});


<|start_filename|>src/internal/setDefaultViewport.js<|end_filename|>
const state = {
  viewport: {}
};

/**
 * Sets new default values for `getDefaultViewport`
 *
 * @param {Object} viewport - Object that sets new default values for getDefaultViewport
 * @returns {undefined}
 */
export default function (viewport) {
  state.viewport = viewport || {};
}

export { state };


<|start_filename|>test/internal/getImageFitScale_test.js<|end_filename|>
import { should, assert } from 'chai'; // eslint-disable-line import/extensions
import getImageFitScale from '../../src/internal/getImageFitScale.js';

should();

describe('getImageScale', function () {
  it('should throw an error if we don\'t have a canvas', function () {
    getImageFitScale.should.throw('getImageScale: parameter windowSize must not be undefined');
  });

  describe('when provided an image that is larger than the canvas and magnified', function () {
    beforeEach(function () {
      this.canvas = document.createElement('canvas');

      this.canvas.width = 100;
      this.canvas.height = 100;

      this.imageViewport = {
        width: 200,
        height: 200,
        columnPixelSpacing: 2,
        rowPixelSpacing: 1
      };
    });

    it('should return a viewport with a scale factor to make the image smaller.', function () {
      const viewport = getImageFitScale(this.canvas, this.imageViewport, 90);

      assert.equal(viewport.verticalScale, 0.5);
      assert.equal(viewport.horizontalScale, 0.25);
      assert.equal(viewport.scaleFactor, 0.25);
    });

  });
});


<|start_filename|>test/internal/drawComposite_test.js<|end_filename|>
import { assert } from 'chai'; // eslint-disable-line import/extensions

import enable from '../../src/enable.js';
import draw from '../../src/draw.js';
import drawCompositeImage from '../../src/internal/drawCompositeImage.js';
import disable from '../../src/disable.js';
import setViewport from '../../src/setViewport.js';
import getViewport from '../../src/getViewport.js';
import { getEnabledElement } from '../../src/enabledElements.js';

import {
  addLayer, getLayer
} from '../../src/layers.js';

describe('layers', function () {
  beforeEach(function () {
    // Arrange
    this.element = document.createElement('div');
    // Need to set width/height to properly calculate the scale
    this.element.style.width = '2px';
    this.element.style.height = '2px';
    this.element.style.position = 'absolute';
    document.body.appendChild(this.element);

    const height = 2;
    const width = 2;

    const getPixelData = () => new Uint8Array([0, 255, 255, 0]);

    this.image1 = {
      imageId: 'exampleImageId1',
      minPixelValue: 0,
      maxPixelValue: 255,
      slope: 1.0,
      intercept: 0,
      windowCenter: 127,
      windowWidth: 256,
      getPixelData,
      rows: height,
      columns: width,
      height,
      width,
      color: false,
      sizeInBytes: width * height * 2,
      columnPixelSpacing: 1,
      rowPixelSpacing: 1
    };

    const getPixelData2 = () => new Uint8Array([5, 6, 7, 8]);

    this.image2 = {
      imageId: 'exampleImageId2',
      minPixelValue: 0,
      maxPixelValue: 255,
      slope: 1.0,
      intercept: 0,
      windowCenter: 127,
      windowWidth: 256,
      getPixelData: getPixelData2,
      rows: height,
      columns: width,
      height,
      width,
      color: false,
      sizeInBytes: width * height * 2,
      columnPixelSpacing: 2,
      rowPixelSpacing: 2
    };

    enable(this.element);
  });

  it('drawComposite: should draw a composite image', function (done) {
    // Arrange
    addLayer(this.element, this.image1);
    addLayer(this.element, this.image2);

    this.element.addEventListener('cornerstoneimagerendered', (event) => {
      // Assert
      assert.equal(event.target, this.element);
      done();
    });

    // Act
    draw(this.element);
  });

  it('drawComposite: should draw a composite image with optional opacity', function (done) {
    // Arrange
    addLayer(this.element, this.image1);
    addLayer(this.element, this.image2, {
      opacity: 0.7
    });

    this.element.addEventListener('cornerstoneimagerendered', (event) => {
      // Assert
      assert.equal(event.target, this.element);
      done();
    });

    // Act
    draw(this.element);
  });

  it('drawComposite: should draw a composite image with optional colormap', function (done) {
    // Arrange
    addLayer(this.element, this.image1);
    addLayer(this.element, this.image2, {
      colormap: 'Blues'
    });

    this.element.addEventListener('cornerstoneimagerendered', (event) => {
      // Assert
      assert.equal(event.target, this.element);
      done();
    });

    // Act
    draw(this.element);
  });

  it('drawComposite: should sync the layers scale', function () {
    // Arrange
    const layerId1 = addLayer(this.element, this.image1);
    const layerId2 = addLayer(this.element, this.image2);
    const layer1 = getLayer(this.element, layerId1);
    const layer2 = getLayer(this.element, layerId2);
    const layerScale1 = layer1.viewport.scale;
    const layerScale2 = layer2.viewport.scale;
    const factor = 2;
    const expectedLayerScale1 = layerScale1 * factor;
    const expectedLayerScale2 = layerScale2 * factor;
    const enabledElement = getEnabledElement(this.element);
    const viewport = getViewport(this.element);

    // Act
    // Must render the layers at least 1 time before scaling to setup the initial scale ratio
    drawCompositeImage(enabledElement, true);

    viewport.scale *= factor;
    setViewport(this.element, viewport);

    drawCompositeImage(enabledElement, true);

    // Assert
    assert.equal(layer1.viewport.scale, expectedLayerScale1);
    assert.equal(layer2.viewport.scale, expectedLayerScale2);
  });

  it('drawComposite: should NOT sync the layers scale', function () {
    // Arrange
    const layerId1 = addLayer(this.element, this.image1);
    const layerId2 = addLayer(this.element, this.image2);
    const layer1 = getLayer(this.element, layerId1);
    const layer2 = getLayer(this.element, layerId2);
    const layerScale1 = layer1.viewport.scale;
    const layerScale2 = layer2.viewport.scale;
    const factor = 2;
    const expectedLayerScale1 = layerScale1 * factor;
    const expectedLayerScale2 = layerScale2;
    const enabledElement = getEnabledElement(this.element);
    const viewport = getViewport(this.element);

    enabledElement.syncViewports = false;

    // Act
    // Must render the layers at least 1 time before scaling to setup the initial scale ratio
    drawCompositeImage(enabledElement, true);

    viewport.scale *= factor;
    setViewport(this.element, viewport);

    drawCompositeImage(enabledElement, true);

    // Assert
    assert.equal(layer1.viewport.scale, expectedLayerScale1);
    assert.equal(layer2.viewport.scale, expectedLayerScale2);
  });

  afterEach(function () {
    disable(this.element);
  });
});
