All files / dicomImageLoader/src/imageLoader/wadouri/metaData getImagePixelModule.ts

82.05% Statements 32/39
83.33% Branches 15/18
100% Functions 5/5
81.57% Lines 31/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142        48x       48x               48x 48x   48x   12288x 6144x   6144x       48x             16x       16x       16x               16x                             16x 16x 16x     16x                     16x         16x         16x                     360x   360x 304x 304x   56x 56x         360x                         360x   360x       16x     360x        
import type { Types } from '@cornerstonejs/core';
import type { DataSet } from 'dicom-parser';
 
function getLutDescriptor(dataSet: DataSet, tag: string) {
  Iif (!dataSet.elements[tag] || dataSet.elements[tag].length !== 6) {
    return;
  }
 
  return [
    dataSet.uint16(tag, 0),
    dataSet.uint16(tag, 1),
    dataSet.uint16(tag, 2),
  ];
}
 
function getLutData(lutDataSet: DataSet, tag: string, lutDescriptor): number[] {
  const lut = [];
  const lutData = lutDataSet.elements[tag];
 
  for (let i = 0; i < lutDescriptor[0]; i++) {
    // Output range is always unsigned
    if (lutDescriptor[2] === 16) {
      lut[i] = lutDataSet.uint16(tag, i);
    } else {
      lut[i] = lutDataSet.byteArray[i + lutData.dataOffset];
    }
  }
 
  return lut;
}
 
function populatePaletteColorLut(
  dataSet: DataSet,
  imagePixelModule: Types.ImagePixelModuleMetadata
) {
  imagePixelModule.redPaletteColorLookupTableDescriptor = getLutDescriptor(
    dataSet,
    'x00281101'
  );
  imagePixelModule.greenPaletteColorLookupTableDescriptor = getLutDescriptor(
    dataSet,
    'x00281102'
  );
  imagePixelModule.bluePaletteColorLookupTableDescriptor = getLutDescriptor(
    dataSet,
    'x00281103'
  );
 
  // The first Palette Color Lookup Table Descriptor value is the number of entries in the lookup table.
  // When the number of table entries is equal to 2ˆ16 then this value shall be 0.
  // See http://dicom.nema.org/MEDICAL/DICOM/current/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.5
  Iif (imagePixelModule.redPaletteColorLookupTableDescriptor[0] === 0) {
    imagePixelModule.redPaletteColorLookupTableDescriptor[0] = 65536;
    imagePixelModule.greenPaletteColorLookupTableDescriptor[0] = 65536;
    imagePixelModule.bluePaletteColorLookupTableDescriptor[0] = 65536;
  }
 
  // The third Palette Color Lookup Table Descriptor value specifies the number of bits for each entry in the Lookup Table Data.
  // It shall take the value of 8 or 16.
  // The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1.
  // The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors.
  //
  // Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits;
  // this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry.
  // The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16.
  const numLutEntries =
    imagePixelModule.redPaletteColorLookupTableDescriptor[0];
  const lutData = dataSet.elements.x00281201;
  const lutBitsAllocated = lutData.length === numLutEntries ? 8 : 16;
 
  // If the descriptors do not appear to have the correct values, correct them
  Iif (
    imagePixelModule.redPaletteColorLookupTableDescriptor[2] !==
    lutBitsAllocated
  ) {
    imagePixelModule.redPaletteColorLookupTableDescriptor[2] = lutBitsAllocated;
    imagePixelModule.greenPaletteColorLookupTableDescriptor[2] =
      lutBitsAllocated;
    imagePixelModule.bluePaletteColorLookupTableDescriptor[2] =
      lutBitsAllocated;
  }
 
  imagePixelModule.redPaletteColorLookupTableData = getLutData(
    dataSet,
    'x00281201',
    imagePixelModule.redPaletteColorLookupTableDescriptor
  );
  imagePixelModule.greenPaletteColorLookupTableData = getLutData(
    dataSet,
    'x00281202',
    imagePixelModule.greenPaletteColorLookupTableDescriptor
  );
  imagePixelModule.bluePaletteColorLookupTableData = getLutData(
    dataSet,
    'x00281203',
    imagePixelModule.bluePaletteColorLookupTableDescriptor
  );
}
 
function populateSmallestLargestPixelValues(
  dataSet: DataSet,
  imagePixelModule: Types.ImagePixelModuleMetadata
) {
  const pixelRepresentation = dataSet.uint16('x00280103');
 
  if (pixelRepresentation === 0) {
    imagePixelModule.smallestPixelValue = dataSet.uint16('x00280106');
    imagePixelModule.largestPixelValue = dataSet.uint16('x00280107');
  } else {
    imagePixelModule.smallestPixelValue = dataSet.int16('x00280106');
    imagePixelModule.largestPixelValue = dataSet.int16('x00280107');
  }
}
 
function getImagePixelModule(dataSet: DataSet): Types.ImagePixelModuleMetadata {
  const imagePixelModule = {
    samplesPerPixel: dataSet.uint16('x00280002'),
    photometricInterpretation: dataSet.string('x00280004'),
    rows: dataSet.uint16('x00280010'),
    columns: dataSet.uint16('x00280011'),
    bitsAllocated: dataSet.uint16('x00280100'),
    bitsStored: dataSet.uint16('x00280101'),
    highBit: dataSet.uint16('x00280102'),
    pixelRepresentation: dataSet.uint16('x00280103'),
    planarConfiguration: dataSet.uint16('x00280006'),
    pixelAspectRatio: dataSet.string('x00280034'),
  } as Types.ImagePixelModuleMetadata;
 
  populateSmallestLargestPixelValues(dataSet, imagePixelModule);
 
  if (
    imagePixelModule.photometricInterpretation === 'PALETTE COLOR' &&
    dataSet.elements.x00281101
  ) {
    populatePaletteColorLut(dataSet, imagePixelModule);
  }
 
  return imagePixelModule;
}
 
export default getImagePixelModule;