Skip to content

Commit

Permalink
perf: add option to use RGB instead of RGBA (cornerstonejs#457)
Browse files Browse the repository at this point in the history
* feat: add transferSyntaxUID return via metadata

* perf: add option to use RGB instead of RGBA

* fix: build

* fix: properly fixes the useRGBA option
  • Loading branch information
sedghi committed Jul 25, 2022
1 parent 6865c70 commit 0bfea34
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ function convertLUTto8Bit(lut, shift) {
* Convert pixel data with PALETTE COLOR Photometric Interpretation to RGBA
*
* @param {ImageFrame} imageFrame
* @param {Uint8ClampedArray} rgbaBuffer
* @param {Uint8ClampedArray} colorBuffer
* @returns {void}
*/
export default function (imageFrame, rgbaBuffer) {
export default function (imageFrame, colorBuffer, useRGBA) {
const numPixels = imageFrame.columns * imageFrame.rows;
const pixelData = imageFrame.pixelData;
const rData = imageFrame.redPaletteColorLookupTableData;
Expand All @@ -28,7 +28,7 @@ export default function (imageFrame, rgbaBuffer) {

let palIndex = 0;

let rgbaIndex = 0;
let bufferIndex = 0;

const start = imageFrame.redPaletteColorLookupTableDescriptor[1];
const shift =
Expand All @@ -38,6 +38,27 @@ export default function (imageFrame, rgbaBuffer) {
const gDataCleaned = convertLUTto8Bit(gData, shift);
const bDataCleaned = convertLUTto8Bit(bData, shift);

if (useRGBA) {
for (let i = 0; i < numPixels; ++i) {
let value = pixelData[palIndex++];

if (value < start) {
value = 0;
} else if (value > start + len - 1) {
value = len - 1;
} else {
value -= start;
}

colorBuffer[bufferIndex++] = rDataCleaned[value];
colorBuffer[bufferIndex++] = gDataCleaned[value];
colorBuffer[bufferIndex++] = bDataCleaned[value];
colorBuffer[bufferIndex++] = 255;
}

return;
}

for (let i = 0; i < numPixels; ++i) {
let value = pixelData[palIndex++];

Expand All @@ -49,9 +70,8 @@ export default function (imageFrame, rgbaBuffer) {
value -= start;
}

rgbaBuffer[rgbaIndex++] = rDataCleaned[value];
rgbaBuffer[rgbaIndex++] = gDataCleaned[value];
rgbaBuffer[rgbaIndex++] = bDataCleaned[value];
rgbaBuffer[rgbaIndex++] = 255;
colorBuffer[bufferIndex++] = rDataCleaned[value];
colorBuffer[bufferIndex++] = gDataCleaned[value];
colorBuffer[bufferIndex++] = bDataCleaned[value];
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function (imageFrame, rgbaBuffer) {
export default function (imageFrame, colorBuffer, useRGBA) {
if (imageFrame === undefined) {
throw new Error('decodeRGB: rgbBuffer must not be undefined');
}
Expand All @@ -10,12 +10,19 @@ export default function (imageFrame, rgbaBuffer) {

let rgbIndex = 0;

let rgbaIndex = 0;
let bufferIndex = 0;

for (let i = 0; i < numPixels; i++) {
rgbaBuffer[rgbaIndex++] = imageFrame[rgbIndex++]; // red
rgbaBuffer[rgbaIndex++] = imageFrame[rgbIndex++]; // green
rgbaBuffer[rgbaIndex++] = imageFrame[rgbIndex++]; // blue
rgbaBuffer[rgbaIndex++] = 255; // alpha
if (useRGBA) {
for (let i = 0; i < numPixels; i++) {
colorBuffer[bufferIndex++] = imageFrame[rgbIndex++]; // red
colorBuffer[bufferIndex++] = imageFrame[rgbIndex++]; // green
colorBuffer[bufferIndex++] = imageFrame[rgbIndex++]; // blue
colorBuffer[bufferIndex++] = 255; // alpha
}

return;
}

// if RGB buffer
colorBuffer.set(imageFrame);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function (imageFrame, rgbaBuffer) {
export default function (imageFrame, colorBuffer, useRGBA) {
if (imageFrame === undefined) {
throw new Error('decodeRGB: rgbBuffer must not be undefined');
}
Expand All @@ -8,18 +8,25 @@ export default function (imageFrame, rgbaBuffer) {

const numPixels = imageFrame.length / 3;

let rgbaIndex = 0;
let bufferIndex = 0;

let rIndex = 0;

let gIndex = numPixels;

let bIndex = numPixels * 2;

for (let i = 0; i < numPixels; i++) {
rgbaBuffer[rgbaIndex++] = imageFrame[rIndex++]; // red
rgbaBuffer[rgbaIndex++] = imageFrame[gIndex++]; // green
rgbaBuffer[rgbaIndex++] = imageFrame[bIndex++]; // blue
rgbaBuffer[rgbaIndex++] = 255; // alpha
if (useRGBA) {
for (let i = 0; i < numPixels; i++) {
colorBuffer[bufferIndex++] = imageFrame[rIndex++]; // red
colorBuffer[bufferIndex++] = imageFrame[gIndex++]; // green
colorBuffer[bufferIndex++] = imageFrame[bIndex++]; // blue
colorBuffer[bufferIndex++] = 255; // alpha
}

return;
}

// if RGB buffer
colorBuffer.set(imageFrame);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function (imageFrame, rgbaBuffer) {
export default function (imageFrame, colorBuffer, useRGBA) {
if (imageFrame === undefined) {
throw new Error('decodeRGB: ybrBuffer must not be undefined');
}
Expand All @@ -10,22 +10,45 @@ export default function (imageFrame, rgbaBuffer) {

let ybrIndex = 0;

let rgbaIndex = 0;
let bufferIndex = 0;

if (useRGBA) {
for (let i = 0; i < numPixels; i += 2) {
const y1 = imageFrame[ybrIndex++];
const y2 = imageFrame[ybrIndex++];
const cb = imageFrame[ybrIndex++];
const cr = imageFrame[ybrIndex++];

colorBuffer[bufferIndex++] = y1 + 1.402 * (cr - 128); // red
colorBuffer[bufferIndex++] =
y1 - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
colorBuffer[bufferIndex++] = y1 + 1.772 * (cb - 128); // blue
colorBuffer[bufferIndex++] = 255; // alpha

colorBuffer[bufferIndex++] = y2 + 1.402 * (cr - 128); // red
colorBuffer[bufferIndex++] =
y2 - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
colorBuffer[bufferIndex++] = y2 + 1.772 * (cb - 128); // blue
colorBuffer[bufferIndex++] = 255; // alpha
}

return;
}

for (let i = 0; i < numPixels; i += 2) {
const y1 = imageFrame[ybrIndex++];
const y2 = imageFrame[ybrIndex++];
const cb = imageFrame[ybrIndex++];
const cr = imageFrame[ybrIndex++];

rgbaBuffer[rgbaIndex++] = y1 + 1.402 * (cr - 128); // red
rgbaBuffer[rgbaIndex++] = y1 - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
rgbaBuffer[rgbaIndex++] = y1 + 1.772 * (cb - 128); // blue
rgbaBuffer[rgbaIndex++] = 255; // alpha
colorBuffer[bufferIndex++] = y1 + 1.402 * (cr - 128); // red
colorBuffer[bufferIndex++] =
y1 - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
colorBuffer[bufferIndex++] = y1 + 1.772 * (cb - 128); // blue

rgbaBuffer[rgbaIndex++] = y2 + 1.402 * (cr - 128); // red
rgbaBuffer[rgbaIndex++] = y2 - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
rgbaBuffer[rgbaIndex++] = y2 + 1.772 * (cb - 128); // blue
rgbaBuffer[rgbaIndex++] = 255; // alpha
colorBuffer[bufferIndex++] = y2 + 1.402 * (cr - 128); // red
colorBuffer[bufferIndex++] =
y2 - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
colorBuffer[bufferIndex++] = y2 + 1.772 * (cb - 128); // blue
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function (imageFrame, rgbaBuffer) {
export default function (imageFrame, colorBuffer, useRGBA) {
if (imageFrame === undefined) {
throw new Error('decodeRGB: ybrBuffer must not be undefined');
}
Expand All @@ -10,16 +10,32 @@ export default function (imageFrame, rgbaBuffer) {

let ybrIndex = 0;

let rgbaIndex = 0;
let bufferIndex = 0;

if (useRGBA) {
for (let i = 0; i < numPixels; i++) {
const y = imageFrame[ybrIndex++];
const cb = imageFrame[ybrIndex++];
const cr = imageFrame[ybrIndex++];

colorBuffer[bufferIndex++] = y + 1.402 * (cr - 128); // red
colorBuffer[bufferIndex++] =
y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
colorBuffer[bufferIndex++] = y + 1.772 * (cb - 128); // blue
colorBuffer[bufferIndex++] = 255; // alpha
}

return;
}

for (let i = 0; i < numPixels; i++) {
const y = imageFrame[ybrIndex++];
const cb = imageFrame[ybrIndex++];
const cr = imageFrame[ybrIndex++];

rgbaBuffer[rgbaIndex++] = y + 1.402 * (cr - 128); // red
rgbaBuffer[rgbaIndex++] = y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
rgbaBuffer[rgbaIndex++] = y + 1.772 * (cb - 128); // blue
rgbaBuffer[rgbaIndex++] = 255; // alpha
colorBuffer[bufferIndex++] = y + 1.402 * (cr - 128); // red
colorBuffer[bufferIndex++] =
y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
colorBuffer[bufferIndex++] = y + 1.772 * (cb - 128); // blue
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function (imageFrame, rgbaBuffer) {
export default function (imageFrame, colorBuffer, useRGBA) {
if (imageFrame === undefined) {
throw new Error('decodeRGB: ybrBuffer must not be undefined');
}
Expand All @@ -8,22 +8,38 @@ export default function (imageFrame, rgbaBuffer) {

const numPixels = imageFrame.length / 3;

let rgbaIndex = 0;
let bufferIndex = 0;

let yIndex = 0;

let cbIndex = numPixels;

let crIndex = numPixels * 2;

if (useRGBA) {
for (let i = 0; i < numPixels; i++) {
const y = imageFrame[yIndex++];
const cb = imageFrame[cbIndex++];
const cr = imageFrame[crIndex++];

colorBuffer[bufferIndex++] = y + 1.402 * (cr - 128); // red
colorBuffer[bufferIndex++] =
y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
colorBuffer[bufferIndex++] = y + 1.772 * (cb - 128); // blue
colorBuffer[bufferIndex++] = 255; // alpha
}

return;
}

for (let i = 0; i < numPixels; i++) {
const y = imageFrame[yIndex++];
const cb = imageFrame[cbIndex++];
const cr = imageFrame[crIndex++];

rgbaBuffer[rgbaIndex++] = y + 1.402 * (cr - 128); // red
rgbaBuffer[rgbaIndex++] = y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
rgbaBuffer[rgbaIndex++] = y + 1.772 * (cb - 128); // blue
rgbaBuffer[rgbaIndex++] = 255; // alpha
colorBuffer[bufferIndex++] = y + 1.402 * (cr - 128); // red
colorBuffer[bufferIndex++] =
y - 0.34414 * (cb - 128) - 0.71414 * (cr - 128); // green
colorBuffer[bufferIndex++] = y + 1.772 * (cb - 128); // blue
}
}
28 changes: 13 additions & 15 deletions packages/dicomImageLoader/src/imageLoader/convertColorSpace.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,36 @@ import {
convertPALETTECOLOR,
} from './colorSpaceConverters/index.js';

function convertRGB(imageFrame, rgbaBuffer) {
function convertRGB(imageFrame, colorBuffer, useRGBA) {
if (imageFrame.planarConfiguration === 0) {
convertRGBColorByPixel(imageFrame.pixelData, rgbaBuffer);
convertRGBColorByPixel(imageFrame.pixelData, colorBuffer, useRGBA);
} else {
convertRGBColorByPlane(imageFrame.pixelData, rgbaBuffer);
convertRGBColorByPlane(imageFrame.pixelData, colorBuffer, useRGBA);
}
}

function convertYBRFull(imageFrame, rgbaBuffer) {
function convertYBRFull(imageFrame, colorBuffer, useRGBA) {
if (imageFrame.planarConfiguration === 0) {
convertYBRFullByPixel(imageFrame.pixelData, rgbaBuffer);
convertYBRFullByPixel(imageFrame.pixelData, colorBuffer, useRGBA);
} else {
convertYBRFullByPlane(imageFrame.pixelData, rgbaBuffer);
convertYBRFullByPlane(imageFrame.pixelData, colorBuffer, useRGBA);
}
}

export default function convertColorSpace(imageFrame, imageData) {
const rgbaBuffer = imageData.data;
export default function convertColorSpace(imageFrame, colorBuffer, useRGBA) {
// convert based on the photometric interpretation

if (imageFrame.photometricInterpretation === 'RGB') {
convertRGB(imageFrame, rgbaBuffer);
convertRGB(imageFrame, colorBuffer, useRGBA);
} else if (imageFrame.photometricInterpretation === 'YBR_RCT') {
convertRGB(imageFrame, rgbaBuffer);
convertRGB(imageFrame, colorBuffer, useRGBA);
} else if (imageFrame.photometricInterpretation === 'YBR_ICT') {
convertRGB(imageFrame, rgbaBuffer);
convertRGB(imageFrame, colorBuffer, useRGBA);
} else if (imageFrame.photometricInterpretation === 'PALETTE COLOR') {
convertPALETTECOLOR(imageFrame, rgbaBuffer);
convertPALETTECOLOR(imageFrame, colorBuffer, useRGBA);
} else if (imageFrame.photometricInterpretation === 'YBR_FULL_422') {
convertYBRFull422ByPixel(imageFrame.pixelData, rgbaBuffer);
convertYBRFull422ByPixel(imageFrame.pixelData, colorBuffer, useRGBA);
} else if (imageFrame.photometricInterpretation === 'YBR_FULL') {
convertYBRFull(imageFrame, rgbaBuffer);
convertYBRFull(imageFrame, colorBuffer, useRGBA);
} else {
throw new Error(
`No color space conversion for photometric interpretation ${imageFrame.photometricInterpretation}`
Expand Down
Loading

0 comments on commit 0bfea34

Please sign in to comment.