@cosyte/dicom 0.0.8 โ 0.0.11
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/CHANGELOG.md +747 -0
- package/README.md +12 -5
- package/dist/index.cjs +229 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +127 -14
- package/dist/index.d.ts +127 -14
- package/dist/index.mjs +229 -55
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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.0.
|
|
12
|
+
var VERSION = "0.0.11";
|
|
13
13
|
|
|
14
14
|
// src/dictionary/index.ts
|
|
15
15
|
var dictionary_exports = {};
|
|
@@ -11701,15 +11701,24 @@ var BE_VR_STRIDE = Object.freeze({
|
|
|
11701
11701
|
UT: 0,
|
|
11702
11702
|
SQ: 0
|
|
11703
11703
|
});
|
|
11704
|
+
var KNOWN_VRS = Object.freeze(
|
|
11705
|
+
new Set(Object.keys(BE_VR_STRIDE))
|
|
11706
|
+
);
|
|
11707
|
+
function isRecognizedVr(vr) {
|
|
11708
|
+
return KNOWN_VRS.has(vr);
|
|
11709
|
+
}
|
|
11704
11710
|
|
|
11705
11711
|
// src/parser/warnings.ts
|
|
11706
11712
|
var WARNING_CODES = {
|
|
11707
11713
|
// === Phase 2 actively emits (D-08 active list - alphabetical-within-prefix per CONTEXT specifics ยง) ===
|
|
11714
|
+
DICOM_DUPLICATE_FILE_META_ELEMENT: "DICOM_DUPLICATE_FILE_META_ELEMENT",
|
|
11715
|
+
DICOM_DUPLICATE_TAG_IN_DATA_SET: "DICOM_DUPLICATE_TAG_IN_DATA_SET",
|
|
11708
11716
|
DICOM_EMPTY_ITEM_IN_SEQUENCE: "DICOM_EMPTY_ITEM_IN_SEQUENCE",
|
|
11709
11717
|
DICOM_FILE_META_GROUP_LENGTH_MISMATCH: "DICOM_FILE_META_GROUP_LENGTH_MISMATCH",
|
|
11710
11718
|
DICOM_FILE_META_GROUP_LENGTH_MISSING: "DICOM_FILE_META_GROUP_LENGTH_MISSING",
|
|
11711
11719
|
DICOM_GROUP_LENGTH_IN_DATASET: "DICOM_GROUP_LENGTH_IN_DATASET",
|
|
11712
11720
|
DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR: "DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR",
|
|
11721
|
+
DICOM_ITEM_CROSSES_SEQUENCE_END: "DICOM_ITEM_CROSSES_SEQUENCE_END",
|
|
11713
11722
|
DICOM_MISSING_PREAMBLE: "DICOM_MISSING_PREAMBLE",
|
|
11714
11723
|
DICOM_NONZERO_RESERVED_BYTES: "DICOM_NONZERO_RESERVED_BYTES",
|
|
11715
11724
|
DICOM_ODD_LENGTH_VALUE_PADDED: "DICOM_ODD_LENGTH_VALUE_PADDED",
|
|
@@ -11735,6 +11744,10 @@ var WARNING_CODES = {
|
|
|
11735
11744
|
// reserved by Phase 7 - not emitted in Phase 2
|
|
11736
11745
|
DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED: "DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED",
|
|
11737
11746
|
// emitted by deidentify(), never by the parser
|
|
11747
|
+
DICOM_DEIDENT_METHOD_NOT_ADDED: "DICOM_DEIDENT_METHOD_NOT_ADDED",
|
|
11748
|
+
// emitted by deidentify(), never by the parser
|
|
11749
|
+
DICOM_DEIDENT_METHOD_PRIOR_RETAINED: "DICOM_DEIDENT_METHOD_PRIOR_RETAINED",
|
|
11750
|
+
// emitted by deidentify(), never by the parser
|
|
11738
11751
|
DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE: "DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE",
|
|
11739
11752
|
// emitted by deidentify(), never by the parser
|
|
11740
11753
|
DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE: "DICOM_DEIDENT_UNDEFINED_VR_NOT_AUDITABLE",
|
|
@@ -11751,10 +11764,44 @@ var WARNING_MESSAGES = Object.freeze({
|
|
|
11751
11764
|
DICOM_VR_MISMATCH: "Element ({tag}) on-wire VR is {vr2}; dictionary lists {vr}. Trusting on-wire VR.",
|
|
11752
11765
|
DICOM_PRIVATE_TAG_NO_CREATOR: "Private element ({tag}) has no Private Creator registered for its block; treating as VR=UN.",
|
|
11753
11766
|
DICOM_GROUP_LENGTH_IN_DATASET: "Retired Group Length element ({tag}) encountered in dataset; preserved as-is.",
|
|
11754
|
-
|
|
11767
|
+
// The tag is deliberately absent, and this is the only *parser* message where
|
|
11768
|
+
// that is true. See `nonzeroReservedBytes`. Kept terse for the same reason the
|
|
11769
|
+
// de-identify messages are: it is emitted once per element, and element count
|
|
11770
|
+
// is attacker-chosen.
|
|
11771
|
+
DICOM_NONZERO_RESERVED_BYTES: "Non-zero reserved bytes between VR and length (first byte {n}, second byte {n2}); ignoring. Tag withheld; the byte offset identifies the element.",
|
|
11755
11772
|
DICOM_SQ_NOT_DESCENDED: "Element ({tag}) resolved to VR=SQ from the dictionary but its defined-length value is not a valid item stream; kept as opaque bytes and NOT descended, so nothing nested inside it is visible to navigation, and deidentify() cannot audit it. See DICOM_DEIDENT_SEQUENCE_NOT_AUDITABLE.",
|
|
11756
11773
|
DICOM_UN_PARSED_AS_SQ: "Element ({tag}) has VR=UN with undefined length; descended as Implicit VR LE sequence per CP-246.",
|
|
11757
11774
|
DICOM_EMPTY_ITEM_IN_SEQUENCE: "Sequence ({tag}) contains an empty item (length=0); tolerated.",
|
|
11775
|
+
// Neither the tag nor the replaced element's value is here, and the tag's
|
|
11776
|
+
// absence is specific to this code rather than caution. See
|
|
11777
|
+
// `duplicateTagInDataSet`. Short by measurement rather than by intention: one
|
|
11778
|
+
// is raised per collision and the collision count is chosen by the input, so a
|
|
11779
|
+
// 400-character draft was measured at 50 M characters over a 1 MiB file and
|
|
11780
|
+
// cut. The reasoning lives in the factory's JSDoc, not in the string.
|
|
11781
|
+
DICOM_DUPLICATE_TAG_IN_DATA_SET: "A Data Element carrying a tag this Data Set already holds replaced the earlier one at this byte offset; that element's value is not in the parsed object. PS3.5 7.1 and 7.5.1. Tag withheld.",
|
|
11782
|
+
// The tag is deliberately absent for the same reason as the code above, and
|
|
11783
|
+
// the surviving copy is named because the File Meta group resolves a repeat
|
|
11784
|
+
// the OPPOSITE way round to a Data Set: first copy wins here, last read wins
|
|
11785
|
+
// there. Short for the same measured reason - one is raised per repeat and the
|
|
11786
|
+
// repeat count is chosen by the input.
|
|
11787
|
+
// ๐ NO SPEC CITATION HERE, AND ITS ABSENCE IS DELIBERATE. A draft ended this
|
|
11788
|
+
// string "PS3.5 7.1.", which asserts that section's "at most once in a Data
|
|
11789
|
+
// Set" governs the File Meta group - the applicability this slice states it
|
|
11790
|
+
// cannot establish, because PS3.10 governs that group and is not vendored
|
|
11791
|
+
// here. Under `{ strict: true }` this string is also the thrown message, so an
|
|
11792
|
+
// unqualified citation there is the claim, not a footnote. Do not put it back.
|
|
11793
|
+
DICOM_DUPLICATE_FILE_META_ELEMENT: "A File Meta Data Element repeats a (0002,xxxx) tag the group already carries; the copy at this byte offset is not in the parsed File Meta, and the FIRST copy of that tag is the one projected. Tag withheld.",
|
|
11794
|
+
// No value and no length: the prior value is the file's own text. The tag is a
|
|
11795
|
+
// constant of this code rather than composed from input, as in the two
|
|
11796
|
+
// (0002,0000) messages above.
|
|
11797
|
+
DICOM_DEIDENT_METHOD_NOT_ADDED: "The De-identification Method this run recorded could not be added beside the value (0012,0063) already carried without exceeding the largest Value Length that VR can encode, so the earlier value was replaced (PS3.15 E.1.1). The replaced text is not in the output.",
|
|
11798
|
+
// No value and no length, for the same reason as the code above: the retained
|
|
11799
|
+
// text is the file's own. The tag is a constant of this code.
|
|
11800
|
+
DICOM_DEIDENT_METHOD_PRIOR_RETAINED: "A De-identification Method (0012,0063) value the source file already carried was kept beside the one this run recorded, as PS3.15 E.1.1 requires. That attribute is not in Table E.1-1, so no rule in this run inspected, audited or redacted those bytes: if the sender wrote identifying text there it is in the de-identified output, under (0012,0062) = YES. The text is withheld from this message.",
|
|
11801
|
+
// The Item's own declared length is deliberately absent. See
|
|
11802
|
+
// `itemCrossesSequenceEnd`; `{n2}` stays because the emit site's
|
|
11803
|
+
// `endLimit < buffer.length` conjunct bounds it by the buffer.
|
|
11804
|
+
DICOM_ITEM_CROSSES_SEQUENCE_END: "Item ({tag}) declares a length reaching past its enclosing sequence's declared end, so it reads the enclosing Data Set's bytes; {n2} bytes remained inside the sequence. The file's two length fields disagree (PS3.5 7.5.1 and 7.5.2 govern them); the item's is used. The declared length is withheld; the byte offset locates the item.",
|
|
11758
11805
|
DICOM_PIXEL_DATA_LENGTH_MISMATCH: "(7FE0,0010) PixelData declared length {n} does not match computed {n2} bytes.",
|
|
11759
11806
|
DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR: "Private element ({tag}) under Implicit VR LE has no VR override; falling back to UN.",
|
|
11760
11807
|
DICOM_PRIVATE_CREATOR_UNKNOWN: "Private element ({tag}) has a Private Creator the active profile's private dictionary does not name; falling back to UN. The creator string is not reproduced here - read the (gggg,00EE) element if you need it.",
|
|
@@ -11786,7 +11833,6 @@ var WARNING_MESSAGES = Object.freeze({
|
|
|
11786
11833
|
DICOM_UNSUPPORTED_CHARSET: "(0008,0005) Specific Character Set value {n} names a defined term this build does not support; decoding text as UTF-8 best-effort. The term is not reproduced here - read the element if you need it.",
|
|
11787
11834
|
DICOM_CHARSET_AMBIGUOUS_SEPARATOR: "(0008,0005) Specific Character Set value {n} is ambiguous under the active code extensions; decoding text as UTF-8 best-effort."
|
|
11788
11835
|
});
|
|
11789
|
-
var KNOWN_VRS = new Set(Object.keys(BE_VR_STRIDE));
|
|
11790
11836
|
var TAG_SHAPE = /^[0-9A-F]{8}$/u;
|
|
11791
11837
|
function renderTag(tag) {
|
|
11792
11838
|
return tag !== void 0 && TAG_SHAPE.test(tag) ? tag : WITHHELD;
|
|
@@ -11828,9 +11874,8 @@ function privateTagNoCreator(position, tag) {
|
|
|
11828
11874
|
function groupLengthInDataset(position, tag) {
|
|
11829
11875
|
return build(WARNING_CODES.DICOM_GROUP_LENGTH_IN_DATASET, position, { tag });
|
|
11830
11876
|
}
|
|
11831
|
-
function nonzeroReservedBytes(position,
|
|
11877
|
+
function nonzeroReservedBytes(position, first, second) {
|
|
11832
11878
|
return build(WARNING_CODES.DICOM_NONZERO_RESERVED_BYTES, position, {
|
|
11833
|
-
tag,
|
|
11834
11879
|
n: first,
|
|
11835
11880
|
n2: second
|
|
11836
11881
|
});
|
|
@@ -11841,9 +11886,21 @@ function unParsedAsSQ(position, tag) {
|
|
|
11841
11886
|
function sqNotDescended(position, tag) {
|
|
11842
11887
|
return build(WARNING_CODES.DICOM_SQ_NOT_DESCENDED, position, { tag });
|
|
11843
11888
|
}
|
|
11889
|
+
function itemCrossesSequenceEnd(position, tag, availableLength) {
|
|
11890
|
+
return build(WARNING_CODES.DICOM_ITEM_CROSSES_SEQUENCE_END, position, {
|
|
11891
|
+
tag,
|
|
11892
|
+
n2: availableLength
|
|
11893
|
+
});
|
|
11894
|
+
}
|
|
11844
11895
|
function emptyItemInSequence(position, tag) {
|
|
11845
11896
|
return build(WARNING_CODES.DICOM_EMPTY_ITEM_IN_SEQUENCE, position, { tag });
|
|
11846
11897
|
}
|
|
11898
|
+
function duplicateTagInDataSet(position) {
|
|
11899
|
+
return build(WARNING_CODES.DICOM_DUPLICATE_TAG_IN_DATA_SET, position);
|
|
11900
|
+
}
|
|
11901
|
+
function duplicateFileMetaElement(position) {
|
|
11902
|
+
return build(WARNING_CODES.DICOM_DUPLICATE_FILE_META_ELEMENT, position);
|
|
11903
|
+
}
|
|
11847
11904
|
function implicitVRForPrivateTagWithoutVR(position, tag) {
|
|
11848
11905
|
return build(WARNING_CODES.DICOM_IMPLICIT_VR_FOR_PRIVATE_TAG_WITHOUT_VR, position, { tag });
|
|
11849
11906
|
}
|
|
@@ -11853,6 +11910,12 @@ function privateCreatorUnknown(position, tag) {
|
|
|
11853
11910
|
function burnedInAnnotationNotRemoved(position) {
|
|
11854
11911
|
return build(WARNING_CODES.DICOM_BURNED_IN_ANNOTATION_NOT_REMOVED, position);
|
|
11855
11912
|
}
|
|
11913
|
+
function deidentMethodNotAdded(position) {
|
|
11914
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_NOT_ADDED, position);
|
|
11915
|
+
}
|
|
11916
|
+
function deidentMethodPriorRetained(position) {
|
|
11917
|
+
return build(WARNING_CODES.DICOM_DEIDENT_METHOD_PRIOR_RETAINED, position);
|
|
11918
|
+
}
|
|
11856
11919
|
function embeddedAttributeRemoved(position, tag, vr, count) {
|
|
11857
11920
|
return build(WARNING_CODES.DICOM_DEIDENT_EMBEDDED_ATTRIBUTE_REMOVED, position, {
|
|
11858
11921
|
tag,
|
|
@@ -12034,12 +12097,12 @@ function readExplicitElementHeader(cursor, _ctx, emit) {
|
|
|
12034
12097
|
const vr = vrSlice.toString("ascii");
|
|
12035
12098
|
let length;
|
|
12036
12099
|
let headerLength;
|
|
12037
|
-
if (LONG_FORM_VRS.has(vr)) {
|
|
12100
|
+
if (LONG_FORM_VRS.has(vr) || !isRecognizedVr(vr)) {
|
|
12038
12101
|
const reserved0 = cursor.buffer[cursor.position];
|
|
12039
12102
|
const reserved1 = cursor.buffer[cursor.position + 1];
|
|
12040
12103
|
cursor.position += 2;
|
|
12041
12104
|
if ((reserved0 ?? 0) !== 0 || (reserved1 ?? 0) !== 0) {
|
|
12042
|
-
emit(nonzeroReservedBytes({ byteOffset: headerStart },
|
|
12105
|
+
emit(nonzeroReservedBytes({ byteOffset: headerStart }, reserved0 ?? 0, reserved1 ?? 0));
|
|
12043
12106
|
}
|
|
12044
12107
|
length = cursor.readUInt32();
|
|
12045
12108
|
headerLength = 12;
|
|
@@ -12147,6 +12210,16 @@ function parseFileMeta(buffer, datasetStart, ctx, emit) {
|
|
|
12147
12210
|
fmElements.push(next);
|
|
12148
12211
|
}
|
|
12149
12212
|
}
|
|
12213
|
+
const seenModeledTags = /* @__PURE__ */ new Set();
|
|
12214
|
+
if (declaredFmLength !== void 0) seenModeledTags.add("00020000");
|
|
12215
|
+
for (const e of fmElements) {
|
|
12216
|
+
if (!MODELED_FM_TAGS.has(e.tag)) continue;
|
|
12217
|
+
if (seenModeledTags.has(e.tag)) {
|
|
12218
|
+
emit(duplicateFileMetaElement({ byteOffset: e.byteOffset, fileMeta: true }));
|
|
12219
|
+
continue;
|
|
12220
|
+
}
|
|
12221
|
+
seenModeledTags.add(e.tag);
|
|
12222
|
+
}
|
|
12150
12223
|
const tsElement = fmElements.find((e) => e.tag === "00020010");
|
|
12151
12224
|
if (tsElement === void 0 || tsElement.vr !== "UI") {
|
|
12152
12225
|
throw new DicomParseError(
|
|
@@ -12177,7 +12250,7 @@ function readExplicitLeElement(cursor) {
|
|
|
12177
12250
|
const vr = cursor.slice(2).toString("ascii");
|
|
12178
12251
|
let length;
|
|
12179
12252
|
let headerLength;
|
|
12180
|
-
if (LONG_FORM_VRS.has(vr)) {
|
|
12253
|
+
if (LONG_FORM_VRS.has(vr) || !isRecognizedVr(vr)) {
|
|
12181
12254
|
cursor.slice(2);
|
|
12182
12255
|
length = cursor.readUInt32();
|
|
12183
12256
|
headerLength = 12;
|
|
@@ -12193,7 +12266,7 @@ function readExplicitLeElement(cursor) {
|
|
|
12193
12266
|
if (bytesConsumed !== headerLength + length) {
|
|
12194
12267
|
throw new RangeError("File Meta element accounting mismatch");
|
|
12195
12268
|
}
|
|
12196
|
-
return { tag, vr, value, bytesConsumed };
|
|
12269
|
+
return { tag, vr, value, bytesConsumed, byteOffset: headerStart };
|
|
12197
12270
|
}
|
|
12198
12271
|
function trimUI(buf) {
|
|
12199
12272
|
let end = buf.length;
|
|
@@ -12633,6 +12706,14 @@ var Element = class {
|
|
|
12633
12706
|
}
|
|
12634
12707
|
};
|
|
12635
12708
|
|
|
12709
|
+
// src/parser/data-set-map.ts
|
|
12710
|
+
function defineElement(elements, element, emit) {
|
|
12711
|
+
if (elements.has(element.tag)) {
|
|
12712
|
+
emit(duplicateTagInDataSet({ byteOffset: element.byteOffset }));
|
|
12713
|
+
}
|
|
12714
|
+
elements.set(element.tag, element);
|
|
12715
|
+
}
|
|
12716
|
+
|
|
12636
12717
|
// src/dataset/item.ts
|
|
12637
12718
|
var Item = class extends Dataset {
|
|
12638
12719
|
index;
|
|
@@ -12754,6 +12835,15 @@ function parseSequence(buffer, valueStart, ctx, emit, opts) {
|
|
|
12754
12835
|
items.push(new Item({ warnings: [], elements: inner.elements, index: itemIndex }));
|
|
12755
12836
|
cursor.position = inner.endOffset;
|
|
12756
12837
|
} else {
|
|
12838
|
+
if (opts.explicitLength !== void 0 && endLimit < buffer.length && cursor.position + itemLength > endLimit) {
|
|
12839
|
+
emit(
|
|
12840
|
+
itemCrossesSequenceEnd(
|
|
12841
|
+
{ byteOffset: itemHeaderStart },
|
|
12842
|
+
itemTag,
|
|
12843
|
+
Math.max(0, endLimit - cursor.position)
|
|
12844
|
+
)
|
|
12845
|
+
);
|
|
12846
|
+
}
|
|
12757
12847
|
if (cursor.position + itemLength > buffer.length) {
|
|
12758
12848
|
throw new DicomParseError(
|
|
12759
12849
|
FATAL_CODES.INVALID_FILE_META,
|
|
@@ -12889,8 +12979,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12889
12979
|
cursor.position = seq.endOffset;
|
|
12890
12980
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(valueRawStart, cursor.position)) : buffer.subarray(valueRawStart, cursor.position);
|
|
12891
12981
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
12892
|
-
|
|
12893
|
-
|
|
12982
|
+
defineElement(
|
|
12983
|
+
elements,
|
|
12894
12984
|
new Element({
|
|
12895
12985
|
tag,
|
|
12896
12986
|
vr,
|
|
@@ -12901,7 +12991,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12901
12991
|
littleEndian: true,
|
|
12902
12992
|
items: seq.items,
|
|
12903
12993
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
12904
|
-
})
|
|
12994
|
+
}),
|
|
12995
|
+
emit
|
|
12905
12996
|
);
|
|
12906
12997
|
continue;
|
|
12907
12998
|
}
|
|
@@ -12920,8 +13011,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12920
13011
|
cursor.position = cp246.endOffset;
|
|
12921
13012
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(valueRawStart, cursor.position)) : buffer.subarray(valueRawStart, cursor.position);
|
|
12922
13013
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
12923
|
-
|
|
12924
|
-
|
|
13014
|
+
defineElement(
|
|
13015
|
+
elements,
|
|
12925
13016
|
new Element({
|
|
12926
13017
|
tag,
|
|
12927
13018
|
vr: "SQ",
|
|
@@ -12934,7 +13025,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12934
13025
|
littleEndian: true,
|
|
12935
13026
|
items: cp246.items,
|
|
12936
13027
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
12937
|
-
})
|
|
13028
|
+
}),
|
|
13029
|
+
emit
|
|
12938
13030
|
);
|
|
12939
13031
|
continue;
|
|
12940
13032
|
}
|
|
@@ -12970,8 +13062,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12970
13062
|
);
|
|
12971
13063
|
if (seq.success) {
|
|
12972
13064
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
12973
|
-
|
|
12974
|
-
|
|
13065
|
+
defineElement(
|
|
13066
|
+
elements,
|
|
12975
13067
|
new Element({
|
|
12976
13068
|
tag,
|
|
12977
13069
|
vr,
|
|
@@ -12982,7 +13074,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12982
13074
|
littleEndian: true,
|
|
12983
13075
|
items: seq.items,
|
|
12984
13076
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
12985
|
-
})
|
|
13077
|
+
}),
|
|
13078
|
+
emit
|
|
12986
13079
|
);
|
|
12987
13080
|
continue;
|
|
12988
13081
|
}
|
|
@@ -12995,8 +13088,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
12995
13088
|
}
|
|
12996
13089
|
applySpecificCharacterSet(tag, valueSlice, ctx, emit, position);
|
|
12997
13090
|
const privateCreator = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
12998
|
-
|
|
12999
|
-
|
|
13091
|
+
defineElement(
|
|
13092
|
+
elements,
|
|
13000
13093
|
new Element({
|
|
13001
13094
|
tag,
|
|
13002
13095
|
vr,
|
|
@@ -13008,7 +13101,8 @@ function parseImplicitLE(buffer, datasetStart, ctx, emit, opts = {}) {
|
|
|
13008
13101
|
littleEndian: true,
|
|
13009
13102
|
...ctx.currentCharset !== void 0 ? { specificCharacterSet: ctx.currentCharset } : {},
|
|
13010
13103
|
...privateCreator !== void 0 ? { privateCreator } : {}
|
|
13011
|
-
})
|
|
13104
|
+
}),
|
|
13105
|
+
emit
|
|
13012
13106
|
);
|
|
13013
13107
|
}
|
|
13014
13108
|
return { elements, endOffset: cursor.position };
|
|
@@ -13115,8 +13209,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13115
13209
|
cursor.position = seqResult.endOffset;
|
|
13116
13210
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, cursor.position)) : buffer.subarray(headerStart, cursor.position);
|
|
13117
13211
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
13118
|
-
|
|
13119
|
-
|
|
13212
|
+
defineElement(
|
|
13213
|
+
elements,
|
|
13120
13214
|
new Element({
|
|
13121
13215
|
tag,
|
|
13122
13216
|
vr: "SQ",
|
|
@@ -13127,7 +13221,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13127
13221
|
littleEndian: mode.littleEndian,
|
|
13128
13222
|
items: seqResult.items,
|
|
13129
13223
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
13130
|
-
})
|
|
13224
|
+
}),
|
|
13225
|
+
emit
|
|
13131
13226
|
);
|
|
13132
13227
|
continue;
|
|
13133
13228
|
}
|
|
@@ -13142,8 +13237,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13142
13237
|
const result = parseSequence(buffer, valueStart2, ctx, emit, seqOpts);
|
|
13143
13238
|
cursor.position = result.endOffset;
|
|
13144
13239
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, cursor.position)) : buffer.subarray(headerStart, cursor.position);
|
|
13145
|
-
|
|
13146
|
-
|
|
13240
|
+
defineElement(
|
|
13241
|
+
elements,
|
|
13147
13242
|
new Element({
|
|
13148
13243
|
tag,
|
|
13149
13244
|
vr: "OB",
|
|
@@ -13154,7 +13249,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13154
13249
|
byteOffset: headerStart,
|
|
13155
13250
|
littleEndian: mode.littleEndian,
|
|
13156
13251
|
items: result.items
|
|
13157
|
-
})
|
|
13252
|
+
}),
|
|
13253
|
+
emit
|
|
13158
13254
|
);
|
|
13159
13255
|
continue;
|
|
13160
13256
|
}
|
|
@@ -13173,8 +13269,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13173
13269
|
cursor.position = cp246.endOffset;
|
|
13174
13270
|
const rawBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, cursor.position)) : buffer.subarray(headerStart, cursor.position);
|
|
13175
13271
|
const privateCreator3 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
13176
|
-
|
|
13177
|
-
|
|
13272
|
+
defineElement(
|
|
13273
|
+
elements,
|
|
13178
13274
|
new Element({
|
|
13179
13275
|
tag,
|
|
13180
13276
|
vr: "SQ",
|
|
@@ -13187,15 +13283,16 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13187
13283
|
littleEndian: mode.littleEndian,
|
|
13188
13284
|
items: cp246.items,
|
|
13189
13285
|
...privateCreator3 !== void 0 ? { privateCreator: privateCreator3 } : {}
|
|
13190
|
-
})
|
|
13286
|
+
}),
|
|
13287
|
+
emit
|
|
13191
13288
|
);
|
|
13192
13289
|
continue;
|
|
13193
13290
|
}
|
|
13194
13291
|
const privateCreator2 = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
13195
13292
|
const fallbackEnd = buffer.length;
|
|
13196
13293
|
const fallbackBytes = ctx.copyValues ? copyValueBytes(buffer.subarray(headerStart, fallbackEnd)) : buffer.subarray(headerStart, fallbackEnd);
|
|
13197
|
-
|
|
13198
|
-
|
|
13294
|
+
defineElement(
|
|
13295
|
+
elements,
|
|
13199
13296
|
new Element({
|
|
13200
13297
|
tag,
|
|
13201
13298
|
vr: "UN",
|
|
@@ -13205,7 +13302,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13205
13302
|
byteOffset: headerStart,
|
|
13206
13303
|
littleEndian: mode.littleEndian,
|
|
13207
13304
|
...privateCreator2 !== void 0 ? { privateCreator: privateCreator2 } : {}
|
|
13208
|
-
})
|
|
13305
|
+
}),
|
|
13306
|
+
emit
|
|
13209
13307
|
);
|
|
13210
13308
|
cursor.position = fallbackEnd;
|
|
13211
13309
|
continue;
|
|
@@ -13240,8 +13338,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13240
13338
|
applySpecificCharacterSet(tag, valueSlice, ctx, emit, position);
|
|
13241
13339
|
const privateCreator = safeModelCreator(resolvePrivateCreator(tag, ctx), ctx);
|
|
13242
13340
|
const finalVr = vr;
|
|
13243
|
-
|
|
13244
|
-
|
|
13341
|
+
defineElement(
|
|
13342
|
+
elements,
|
|
13245
13343
|
new Element({
|
|
13246
13344
|
tag,
|
|
13247
13345
|
vr: finalVr,
|
|
@@ -13253,7 +13351,8 @@ function _parseExplicit(buffer, datasetStart, ctx, emit, mode, opts = {}) {
|
|
|
13253
13351
|
littleEndian: mode.littleEndian,
|
|
13254
13352
|
...ctx.currentCharset !== void 0 ? { specificCharacterSet: ctx.currentCharset } : {},
|
|
13255
13353
|
...privateCreator !== void 0 ? { privateCreator } : {}
|
|
13256
|
-
})
|
|
13354
|
+
}),
|
|
13355
|
+
emit
|
|
13257
13356
|
);
|
|
13258
13357
|
}
|
|
13259
13358
|
return { elements, endOffset: cursor.position };
|
|
@@ -13451,7 +13550,7 @@ function encodeDatasetElement(el, encoding) {
|
|
|
13451
13550
|
}
|
|
13452
13551
|
const littleEndian = encoding === "explicitLE";
|
|
13453
13552
|
const vrBuf = Buffer.from(el.vr, "ascii");
|
|
13454
|
-
if (LONG_FORM_VRS.has(el.vr)) {
|
|
13553
|
+
if (LONG_FORM_VRS.has(el.vr) || !isRecognizedVr(el.vr)) {
|
|
13455
13554
|
return Buffer.concat([
|
|
13456
13555
|
uint16(group, littleEndian),
|
|
13457
13556
|
uint16(element, littleEndian),
|
|
@@ -13502,7 +13601,7 @@ function encodeMetaElement(tag, vr, rawValue) {
|
|
|
13502
13601
|
const elementBuf = Buffer.alloc(2);
|
|
13503
13602
|
elementBuf.writeUInt16LE(element, 0);
|
|
13504
13603
|
const vrBuf = Buffer.from(vr, "ascii");
|
|
13505
|
-
if (LONG_FORM_VRS.has(vr)) {
|
|
13604
|
+
if (LONG_FORM_VRS.has(vr) || !isRecognizedVr(vr)) {
|
|
13506
13605
|
const lengthBuf2 = Buffer.alloc(4);
|
|
13507
13606
|
lengthBuf2.writeUInt32LE(value.length, 0);
|
|
13508
13607
|
return Buffer.concat([
|
|
@@ -14697,7 +14796,6 @@ function uidValueMultiplicity(rawBytes) {
|
|
|
14697
14796
|
}
|
|
14698
14797
|
|
|
14699
14798
|
// src/deident/embedded.ts
|
|
14700
|
-
var KNOWN_VRS2 = new Set(Object.keys(BE_VR_STRIDE));
|
|
14701
14799
|
var UNDEFINED_LENGTH4 = 4294967295;
|
|
14702
14800
|
var FFFE_GROUP = 65534;
|
|
14703
14801
|
var SCANNABLE_CARRIER_VRS = /* @__PURE__ */ new Set([
|
|
@@ -14758,7 +14856,7 @@ function decodeAt(value, off, encoding) {
|
|
|
14758
14856
|
return next2 > value.length ? void 0 : { next: next2, tag };
|
|
14759
14857
|
}
|
|
14760
14858
|
const vr = value.toString("latin1", off + 4, off + 6);
|
|
14761
|
-
if (!
|
|
14859
|
+
if (!KNOWN_VRS.has(vr)) return void 0;
|
|
14762
14860
|
if (LONG_FORM_VRS.has(vr)) {
|
|
14763
14861
|
if (off + 12 > value.length) return void 0;
|
|
14764
14862
|
if (value[off + 6] !== 0 || value[off + 7] !== 0) return void 0;
|
|
@@ -14895,7 +14993,6 @@ var BODY_ENCODING2 = {
|
|
|
14895
14993
|
};
|
|
14896
14994
|
var MAX_UNAUDITABLE_SEQUENCE_FINDINGS = 64;
|
|
14897
14995
|
var MAX_UNDEFINED_VR_FINDINGS = 64;
|
|
14898
|
-
var KNOWN_VRS3 = new Set(Object.keys(BE_VR_STRIDE));
|
|
14899
14996
|
function validateRetain(retain) {
|
|
14900
14997
|
const valid = new Set(DEIDENTIFY_OPTIONS);
|
|
14901
14998
|
const active = /* @__PURE__ */ new Set();
|
|
@@ -15016,7 +15113,7 @@ function actsOnTag(tag, ctx) {
|
|
|
15016
15113
|
return resolveAction(effectiveCode(action, ctx.active)) !== "K";
|
|
15017
15114
|
}
|
|
15018
15115
|
function hasUndefinedVr(el) {
|
|
15019
|
-
return !
|
|
15116
|
+
return !KNOWN_VRS.has(el.vr);
|
|
15020
15117
|
}
|
|
15021
15118
|
function keepOrEmpty(el, ctx, contextPath, out) {
|
|
15022
15119
|
if (hasUndefinedVr(el)) {
|
|
@@ -15080,6 +15177,26 @@ function creatorFor(tag, creators) {
|
|
|
15080
15177
|
const { group, element } = splitTag(tag);
|
|
15081
15178
|
return creators.get(`${String(group)}:${String(element >> 8 & 255)}`);
|
|
15082
15179
|
}
|
|
15180
|
+
var UNDEFINED_LENGTH5 = 4294967295;
|
|
15181
|
+
var EXPLICIT_SQ_HEADER_BYTES = 12;
|
|
15182
|
+
function itemStreamOverrunsSequence(el, encoding) {
|
|
15183
|
+
if (el.vr !== "SQ" || el.length === UNDEFINED_LENGTH5) return false;
|
|
15184
|
+
const headerBytes = encoding === "implicit" ? 0 : EXPLICIT_SQ_HEADER_BYTES;
|
|
15185
|
+
return el.rawBytes.length - headerBytes > el.length;
|
|
15186
|
+
}
|
|
15187
|
+
function settledBound(source, encoding) {
|
|
15188
|
+
let index = source.length;
|
|
15189
|
+
let byteOffset;
|
|
15190
|
+
for (const [at, el] of source.entries()) {
|
|
15191
|
+
if (!itemStreamOverrunsSequence(el, encoding) && !isUnauditableSequence(el)) continue;
|
|
15192
|
+
if (index === source.length) index = at + 1;
|
|
15193
|
+
if (byteOffset === void 0 || el.byteOffset < byteOffset) byteOffset = el.byteOffset;
|
|
15194
|
+
}
|
|
15195
|
+
return { index, byteOffset };
|
|
15196
|
+
}
|
|
15197
|
+
function isSettled(el, at, bound) {
|
|
15198
|
+
return at < bound.index && (bound.byteOffset === void 0 || el.byteOffset <= bound.byteOffset);
|
|
15199
|
+
}
|
|
15083
15200
|
function keepsPrivate(el, ctx, creators) {
|
|
15084
15201
|
if (!ctx.active.has("RetainSafePrivate") || ctx.profile === void 0) return false;
|
|
15085
15202
|
if (isPrivateCreatorElement(el.tag)) {
|
|
@@ -15089,7 +15206,7 @@ function keepsPrivate(el, ctx, creators) {
|
|
|
15089
15206
|
if (creator === void 0) return false;
|
|
15090
15207
|
return resolvePrivateTag(ctx.profile, el.tag, creator) !== void 0;
|
|
15091
15208
|
}
|
|
15092
|
-
function processElements(source, ctx, contextPath) {
|
|
15209
|
+
function processElements(source, ctx, contextPath, reservationsUsable) {
|
|
15093
15210
|
const out = {
|
|
15094
15211
|
elements: /* @__PURE__ */ new Map(),
|
|
15095
15212
|
attributes: [],
|
|
@@ -15099,10 +15216,12 @@ function processElements(source, ctx, contextPath) {
|
|
|
15099
15216
|
undefinedVrElements: [],
|
|
15100
15217
|
warnings: []
|
|
15101
15218
|
};
|
|
15102
|
-
const
|
|
15103
|
-
|
|
15219
|
+
const bound = settledBound(source, ctx.encoding);
|
|
15220
|
+
const creators = creatorsInScope(source.filter((el, at) => isSettled(el, at, bound)));
|
|
15221
|
+
for (const [at, el] of source.entries()) {
|
|
15104
15222
|
if (isPrivateTag(el.tag)) {
|
|
15105
|
-
if (
|
|
15223
|
+
if (reservationsUsable && isSettled(el, at, bound) && keepsPrivate(el, ctx, creators))
|
|
15224
|
+
keepOrEmpty(el, ctx, contextPath, out);
|
|
15106
15225
|
else out.removedPrivateTags.push(el.tag);
|
|
15107
15226
|
continue;
|
|
15108
15227
|
}
|
|
@@ -15110,7 +15229,8 @@ function processElements(source, ctx, contextPath) {
|
|
|
15110
15229
|
if (action === void 0) {
|
|
15111
15230
|
if (el.vr === "SQ") {
|
|
15112
15231
|
if (isUnauditableSequence(el)) emptyUnauditableSequence(el, ctx, contextPath, out);
|
|
15113
|
-
else
|
|
15232
|
+
else
|
|
15233
|
+
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out, reservationsUsable));
|
|
15114
15234
|
} else {
|
|
15115
15235
|
keepOrEmpty(el, ctx, contextPath, out);
|
|
15116
15236
|
}
|
|
@@ -15118,7 +15238,7 @@ function processElements(source, ctx, contextPath) {
|
|
|
15118
15238
|
}
|
|
15119
15239
|
const resolved = resolveAction(effectiveCode(action, ctx.active));
|
|
15120
15240
|
if (el.vr === "SQ") {
|
|
15121
|
-
applySequenceAction(el, resolved, action, ctx, contextPath, out);
|
|
15241
|
+
applySequenceAction(el, resolved, action, ctx, contextPath, out, reservationsUsable);
|
|
15122
15242
|
continue;
|
|
15123
15243
|
}
|
|
15124
15244
|
let applied;
|
|
@@ -15159,11 +15279,12 @@ function processElements(source, ctx, contextPath) {
|
|
|
15159
15279
|
}
|
|
15160
15280
|
return out;
|
|
15161
15281
|
}
|
|
15162
|
-
function descendSequence(el, ctx, contextPath, out) {
|
|
15282
|
+
function descendSequence(el, ctx, contextPath, out, reservationsUsable) {
|
|
15283
|
+
const childReservationsUsable = reservationsUsable && !itemStreamOverrunsSequence(el, ctx.encoding);
|
|
15163
15284
|
const newItems = [];
|
|
15164
15285
|
(el.items ?? []).forEach((item, index) => {
|
|
15165
15286
|
const childPath = [...contextPath, `${el.tag}[${String(index)}]`];
|
|
15166
|
-
const inner = processElements(item.elements(), ctx, childPath);
|
|
15287
|
+
const inner = processElements(item.elements(), ctx, childPath, childReservationsUsable);
|
|
15167
15288
|
out.attributes.push(...inner.attributes);
|
|
15168
15289
|
out.removedPrivateTags.push(...inner.removedPrivateTags);
|
|
15169
15290
|
out.embeddedAttributes.push(...inner.embeddedAttributes);
|
|
@@ -15174,7 +15295,7 @@ function descendSequence(el, ctx, contextPath, out) {
|
|
|
15174
15295
|
});
|
|
15175
15296
|
return rebuildSequence(el, newItems, ctx.encoding);
|
|
15176
15297
|
}
|
|
15177
|
-
function applySequenceAction(el, resolved, action, ctx, contextPath, out) {
|
|
15298
|
+
function applySequenceAction(el, resolved, action, ctx, contextPath, out, reservationsUsable) {
|
|
15178
15299
|
let applied;
|
|
15179
15300
|
switch (resolved) {
|
|
15180
15301
|
case "X":
|
|
@@ -15190,7 +15311,7 @@ function applySequenceAction(el, resolved, action, ctx, contextPath, out) {
|
|
|
15190
15311
|
emptyUnauditableSequence(el, ctx, contextPath, out);
|
|
15191
15312
|
applied = "emptied";
|
|
15192
15313
|
} else {
|
|
15193
|
-
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out));
|
|
15314
|
+
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out, reservationsUsable));
|
|
15194
15315
|
applied = "cleaned";
|
|
15195
15316
|
}
|
|
15196
15317
|
break;
|
|
@@ -15200,7 +15321,7 @@ function applySequenceAction(el, resolved, action, ctx, contextPath, out) {
|
|
|
15200
15321
|
emptyUnauditableSequence(el, ctx, contextPath, out);
|
|
15201
15322
|
applied = "emptied";
|
|
15202
15323
|
} else {
|
|
15203
|
-
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out));
|
|
15324
|
+
out.elements.set(el.tag, descendSequence(el, ctx, contextPath, out, reservationsUsable));
|
|
15204
15325
|
applied = "kept";
|
|
15205
15326
|
}
|
|
15206
15327
|
break;
|
|
@@ -15232,6 +15353,47 @@ function defaultMethod(active) {
|
|
|
15232
15353
|
const base = "Cosyte @cosyte/dicom: PS3.15 Basic Application Level Confidentiality Profile";
|
|
15233
15354
|
return active.size === 0 ? base : `${base} + ${[...active].join(", ")}`;
|
|
15234
15355
|
}
|
|
15356
|
+
var VALUE_DELIMITER = 92;
|
|
15357
|
+
var MAX_SHORT_FORM_VALUE_BYTES = 65534;
|
|
15358
|
+
function addDeidentificationMethod(existing, method) {
|
|
15359
|
+
const added = trimTrailingPad(Buffer.from(method, "latin1"));
|
|
15360
|
+
if (existing === void 0 || existing.vr !== "LO") {
|
|
15361
|
+
return { value: added, replacedPrior: false, retainedPrior: false };
|
|
15362
|
+
}
|
|
15363
|
+
const kept = Buffer.from(trimTrailingPad(existing.rawBytes));
|
|
15364
|
+
if (kept.length === 0) return { value: added, replacedPrior: false, retainedPrior: false };
|
|
15365
|
+
const keptValues = splitValues(kept).map(trimTrailingPad);
|
|
15366
|
+
const missing = added.length === 0 ? [] : splitValues(added).filter((v) => !keptValues.some((k) => k.equals(trimTrailingPad(v))));
|
|
15367
|
+
const parts = [kept];
|
|
15368
|
+
for (const value2 of missing) {
|
|
15369
|
+
parts.push(Buffer.from([VALUE_DELIMITER]), value2);
|
|
15370
|
+
}
|
|
15371
|
+
const value = trimTrailingPad(Buffer.concat(parts));
|
|
15372
|
+
if (value.length > MAX_SHORT_FORM_VALUE_BYTES) {
|
|
15373
|
+
return { value: added, replacedPrior: true, retainedPrior: false };
|
|
15374
|
+
}
|
|
15375
|
+
return { value, replacedPrior: false, retainedPrior: true };
|
|
15376
|
+
}
|
|
15377
|
+
function trimTrailingPad(value) {
|
|
15378
|
+
let end = value.length;
|
|
15379
|
+
while (end > 0) {
|
|
15380
|
+
const last = value[end - 1];
|
|
15381
|
+
if (last === 32 || last === 0) end--;
|
|
15382
|
+
else break;
|
|
15383
|
+
}
|
|
15384
|
+
return value.subarray(0, end);
|
|
15385
|
+
}
|
|
15386
|
+
function splitValues(value) {
|
|
15387
|
+
const out = [];
|
|
15388
|
+
let start = 0;
|
|
15389
|
+
for (let i = 0; i <= value.length; i++) {
|
|
15390
|
+
if (i === value.length || value[i] === VALUE_DELIMITER) {
|
|
15391
|
+
out.push(value.subarray(start, i));
|
|
15392
|
+
start = i + 1;
|
|
15393
|
+
}
|
|
15394
|
+
}
|
|
15395
|
+
return out;
|
|
15396
|
+
}
|
|
15235
15397
|
function hasUncleanedBurnedIn(ds) {
|
|
15236
15398
|
if (!ds.has(TAG_PIXEL_DATA)) return false;
|
|
15237
15399
|
const flag = ds.get(TAG_BURNED_IN_ANNOTATION);
|
|
@@ -15251,7 +15413,7 @@ function deidentify(ds, options = {}) {
|
|
|
15251
15413
|
encoding,
|
|
15252
15414
|
budget: { unauditableSequences: 0, undefinedVrElements: 0 }
|
|
15253
15415
|
};
|
|
15254
|
-
const processed = processElements(ds.elements(), ctx, []);
|
|
15416
|
+
const processed = processElements(ds.elements(), ctx, [], true);
|
|
15255
15417
|
const {
|
|
15256
15418
|
elements,
|
|
15257
15419
|
attributes,
|
|
@@ -15265,11 +15427,23 @@ function deidentify(ds, options = {}) {
|
|
|
15265
15427
|
insertedScalar(TAG_PATIENT_IDENTITY_REMOVED, "CS", Buffer.from("YES", "latin1"), littleEndian)
|
|
15266
15428
|
);
|
|
15267
15429
|
const method = options.deidentificationMethod ?? defaultMethod(active);
|
|
15430
|
+
const priorMethod = elements.get(TAG_DEIDENTIFICATION_METHOD);
|
|
15431
|
+
const deidentMethod = addDeidentificationMethod(priorMethod, method);
|
|
15268
15432
|
elements.set(
|
|
15269
15433
|
TAG_DEIDENTIFICATION_METHOD,
|
|
15270
|
-
insertedScalar(TAG_DEIDENTIFICATION_METHOD, "LO",
|
|
15434
|
+
insertedScalar(TAG_DEIDENTIFICATION_METHOD, "LO", deidentMethod.value, littleEndian)
|
|
15271
15435
|
);
|
|
15272
15436
|
const warnings = [...processed.warnings];
|
|
15437
|
+
if (deidentMethod.replacedPrior) {
|
|
15438
|
+
warnings.push(
|
|
15439
|
+
deidentMethodNotAdded({ byteOffset: priorMethod?.byteOffset ?? 0, fileMeta: false })
|
|
15440
|
+
);
|
|
15441
|
+
}
|
|
15442
|
+
if (deidentMethod.retainedPrior) {
|
|
15443
|
+
warnings.push(
|
|
15444
|
+
deidentMethodPriorRetained({ byteOffset: priorMethod?.byteOffset ?? 0, fileMeta: false })
|
|
15445
|
+
);
|
|
15446
|
+
}
|
|
15273
15447
|
if (hasUncleanedBurnedIn(ds)) {
|
|
15274
15448
|
const offset = ds.get(TAG_PIXEL_DATA)?.byteOffset ?? 0;
|
|
15275
15449
|
warnings.push(burnedInAnnotationNotRemoved({ byteOffset: offset, fileMeta: false }));
|