@cosyte/dicom 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ var __export = (target, all) => {
9
9
  };
10
10
 
11
11
  // src/version.ts
12
- var VERSION = "0.1.4";
12
+ var VERSION = "0.1.6";
13
13
 
14
14
  // src/dictionary/index.ts
15
15
  var dictionary_exports = {};
@@ -11139,8 +11139,24 @@ function directoryRecords(source) {
11139
11139
  }
11140
11140
  function csValues(el) {
11141
11141
  if (el === void 0) return void 0;
11142
- const text = el.rawBytes.toString("latin1").replace(/[\0 ]+$/u, "");
11143
- return Object.freeze(text === "" ? [] : text.split("\\").map((v) => v.replace(/^ +| +$/gu, "")));
11142
+ const text = stripTrailingPad(el.rawBytes.toString("latin1"));
11143
+ return Object.freeze(text === "" ? [] : text.split("\\").map(trimSpaces));
11144
+ }
11145
+ function stripTrailingPad(text) {
11146
+ let end = text.length;
11147
+ while (end > 0) {
11148
+ const code = text.charCodeAt(end - 1);
11149
+ if (code !== 0 && code !== 32) break;
11150
+ end--;
11151
+ }
11152
+ return text.slice(0, end);
11153
+ }
11154
+ function trimSpaces(value) {
11155
+ let start = 0;
11156
+ let end = value.length;
11157
+ while (start < end && value.charCodeAt(start) === 32) start++;
11158
+ while (end > start && value.charCodeAt(end - 1) === 32) end--;
11159
+ return value.slice(start, end);
11144
11160
  }
11145
11161
  function analyzeDirectory(source) {
11146
11162
  if (!isDicomdir(source.fileMeta)) return void 0;
@@ -13799,7 +13815,7 @@ function stripPad(bytes, tag, vr, position, warnings) {
13799
13815
  }
13800
13816
  return bytes.subarray(0, end);
13801
13817
  }
13802
- function trimSpaces(value) {
13818
+ function trimSpaces2(value) {
13803
13819
  let start = 0;
13804
13820
  let end = value.length;
13805
13821
  while (start < end && value.charCodeAt(start) === SPACE2) start++;
@@ -13858,7 +13874,7 @@ function decodeElementValue(element) {
13858
13874
  }
13859
13875
  if (vr === "LO" || vr === "SH" || vr === "UC") {
13860
13876
  const text = decodeCharsetString(trimmed, tag, vr, charset, position, warnings);
13861
- const values = text.split("\\").map(trimSpaces);
13877
+ const values = text.split("\\").map(trimSpaces2);
13862
13878
  return attachWarnings({ kind: "strings", values }, warnings);
13863
13879
  }
13864
13880
  if (vr === "LT" || vr === "ST" || vr === "UT") {
@@ -13871,7 +13887,7 @@ function decodeElementValue(element) {
13871
13887
  }
13872
13888
  if (vr === "AE" || vr === "CS" || vr === "AS" || vr === "UI") {
13873
13889
  const text = decodeAsciiString(trimmed, tag, vr, position, warnings);
13874
- const values = text.split("\\").map(trimSpaces);
13890
+ const values = text.split("\\").map(trimSpaces2);
13875
13891
  return attachWarnings({ kind: "strings", values }, warnings);
13876
13892
  }
13877
13893
  if (vr === "DS") {
@@ -14941,6 +14957,7 @@ function toDate(value, options) {
14941
14957
  return Number.isNaN(instant.getTime()) ? void 0 : instant;
14942
14958
  }
14943
14959
  var UNDEFINED_LENGTH4 = 4294967295;
14960
+ var MAX_SHORT_FORM_LENGTH = 65534;
14944
14961
  var NULL_PAD_VRS = /* @__PURE__ */ new Set(["UI", "OB", "OW", "OF", "OD", "OL", "OV", "UN"]);
14945
14962
  function padValue(value, vr) {
14946
14963
  if (value.length % 2 === 0) return Buffer.from(value);
@@ -14959,6 +14976,19 @@ function uint32(n, littleEndian) {
14959
14976
  else buf.writeUInt32BE(n, 0);
14960
14977
  return buf;
14961
14978
  }
14979
+ function littleEndianValue(value, vr, littleEndian) {
14980
+ const stride = BE_VR_STRIDE[vr];
14981
+ if (littleEndian || stride === 0) return value;
14982
+ const swapped = Buffer.from(value);
14983
+ const whole = swapped.subarray(0, swapped.length - swapped.length % stride);
14984
+ if (stride === 2) whole.swap16();
14985
+ else if (stride === 4) whole.swap32();
14986
+ else whole.swap64();
14987
+ return swapped;
14988
+ }
14989
+ function isPrivateCreator(group, element) {
14990
+ return group % 2 === 1 && element >= 16 && element <= 255;
14991
+ }
14962
14992
  function isFullSpanElement(el, encoding) {
14963
14993
  if (el.length === UNDEFINED_LENGTH4) return true;
14964
14994
  return el.vr === "SQ" && encoding !== "implicit";
@@ -14990,6 +15020,17 @@ function encodeDatasetElement(el, encoding, rawBytes = el.rawBytes) {
14990
15020
  value
14991
15021
  ]);
14992
15022
  }
15023
+ if (value.length > MAX_SHORT_FORM_LENGTH && !isPrivateCreator(group, element)) {
15024
+ return Buffer.concat([
15025
+ uint16(group, littleEndian),
15026
+ uint16(element, littleEndian),
15027
+ Buffer.from("UN", "ascii"),
15028
+ Buffer.from([0, 0]),
15029
+ // reserved (PS3.5 §7.1.2)
15030
+ uint32(value.length, littleEndian),
15031
+ littleEndianValue(value, el.vr, littleEndian)
15032
+ ]);
15033
+ }
14993
15034
  return Buffer.concat([
14994
15035
  uint16(group, littleEndian),
14995
15036
  uint16(element, littleEndian),
@@ -16739,14 +16780,19 @@ function dummyBytes(vr) {
16739
16780
  const buf = Buffer.from(text, "latin1");
16740
16781
  return buf.length % 2 === 0 ? buf : Buffer.concat([buf, Buffer.from([32])]);
16741
16782
  }
16783
+ function stripTrailingNulls(text) {
16784
+ let end = text.length;
16785
+ while (end > 0 && text.charCodeAt(end - 1) === 0) end--;
16786
+ return text.slice(0, end);
16787
+ }
16742
16788
  function remapUidBytes(rawBytes, remap) {
16743
- const raw = rawBytes.toString("latin1").replace(/\0+$/, "");
16789
+ const raw = stripTrailingNulls(rawBytes.toString("latin1"));
16744
16790
  const remapped = raw.split("\\").map((uid2) => remap(uid2.trim())).join("\\");
16745
16791
  const buf = Buffer.from(remapped, "latin1");
16746
16792
  return buf.length % 2 === 0 ? buf : Buffer.concat([buf, Buffer.from([0])]);
16747
16793
  }
16748
16794
  function uidValueMultiplicity(rawBytes) {
16749
- const raw = rawBytes.toString("latin1").replace(/\0+$/, "");
16795
+ const raw = stripTrailingNulls(rawBytes.toString("latin1"));
16750
16796
  if (raw.length === 0) return 0;
16751
16797
  return raw.split("\\").length;
16752
16798
  }
@@ -17148,7 +17194,7 @@ function insertedSequence(tag, items, encoding) {
17148
17194
  });
17149
17195
  }
17150
17196
  function decodeCreator(el) {
17151
- return el.rawBytes.toString("latin1").replace(/[\0 ]+$/, "").trim();
17197
+ return trimTrailingPad(el.rawBytes).toString("latin1").trim();
17152
17198
  }
17153
17199
  function isPrivateCreatorElement(tag) {
17154
17200
  const { element } = splitTag(tag);
@@ -17276,7 +17322,7 @@ function declarationKey(group, creator) {
17276
17322
  return `${String(group)}:${creator}`;
17277
17323
  }
17278
17324
  function decodeEnumerated(el) {
17279
- return el.rawBytes.toString("latin1").replace(/[\0 ]+$/, "").trim();
17325
+ return trimTrailingPad(el.rawBytes).toString("latin1").trim();
17280
17326
  }
17281
17327
  function readUnsignedShorts(el) {
17282
17328
  const values = [];
@@ -17713,7 +17759,7 @@ function hasUncleanedBurnedIn(ds) {
17713
17759
  if (!ds.has(TAG_PIXEL_DATA)) return false;
17714
17760
  const flag = ds.get(TAG_BURNED_IN_ANNOTATION);
17715
17761
  if (flag === void 0) return true;
17716
- return flag.rawBytes.toString("latin1").replace(/[\0 ]+$/, "").trim().toUpperCase() !== "NO";
17762
+ return trimTrailingPad(flag.rawBytes).toString("latin1").trim().toUpperCase() !== "NO";
17717
17763
  }
17718
17764
  function deidentify(ds, options = {}) {
17719
17765
  if (isRefusedTransferSyntax(ds.fileMeta?.transferSyntaxUID)) {