Skip to content

Commit

Permalink
perf: add option to use RGB instead of RGBA (#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 authored Jul 25, 2022
1 parent deb1780 commit 5583aa5
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 76 deletions.
34 changes: 27 additions & 7 deletions src/imageLoader/colorSpaceConverters/convertPALETTECOLOR.js
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];
}
}
21 changes: 14 additions & 7 deletions src/imageLoader/colorSpaceConverters/convertRGBColorByPixel.js
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);
}
21 changes: 14 additions & 7 deletions src/imageLoader/colorSpaceConverters/convertRGBColorByPlane.js
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);
}
43 changes: 33 additions & 10 deletions src/imageLoader/colorSpaceConverters/convertYBRFull422ByPixel.js
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
}
}
28 changes: 22 additions & 6 deletions src/imageLoader/colorSpaceConverters/convertYBRFullByPixel.js
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
}
}
28 changes: 22 additions & 6 deletions src/imageLoader/colorSpaceConverters/convertYBRFullByPlane.js
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 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 5583aa5

Please sign in to comment.