/* * * Copyright (C) 1994-2021, OFFIS e.V. * All rights reserved. See COPYRIGHT file for details. * * This software and supporting documentation were developed by * * OFFIS e.V. * R&D Division Health * Escherweg 2 * D-26121 Oldenburg, Germany * * * Module: dcmdata * * Author: Gerd Ehlers, Andreas Barth * * Purpose: Implementation of class DcmOtherByteOtherWord * */ #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */ #include "dcmtk/ofstd/ofstd.h" #include "dcmtk/ofstd/ofstream.h" #include "dcmtk/ofstd/ofuuid.h" #include "dcmtk/ofstd/offile.h" #include "dcmtk/dcmdata/dcjson.h" #include "dcmtk/dcmdata/dcvrobow.h" #include "dcmtk/dcmdata/dcdeftag.h" #include "dcmtk/dcmdata/dcswap.h" #include "dcmtk/dcmdata/dcuid.h" /* for UID generation */ // ******************************** DcmOtherByteOtherWord::DcmOtherByteOtherWord(const DcmTag &tag) : DcmElement(tag, 0) , compactAfterTransfer(OFFalse) { } DcmOtherByteOtherWord::DcmOtherByteOtherWord(const DcmTag &tag, const Uint32 len) : DcmElement(tag, len) , compactAfterTransfer(OFFalse) { } DcmOtherByteOtherWord::DcmOtherByteOtherWord(const DcmOtherByteOtherWord &old) : DcmElement(old) , compactAfterTransfer(old.compactAfterTransfer) { } DcmOtherByteOtherWord::~DcmOtherByteOtherWord() { } DcmOtherByteOtherWord &DcmOtherByteOtherWord::operator=(const DcmOtherByteOtherWord &obj) { DcmElement::operator=(obj); compactAfterTransfer = obj.compactAfterTransfer; return *this; } int DcmOtherByteOtherWord::compare(const DcmElement& rhs) const { int result = DcmElement::compare(rhs); if (result != 0) { return result; } /* cast away constness (dcmdata is not const correct...) */ DcmOtherByteOtherWord* myThis = NULL; DcmOtherByteOtherWord* myRhs = NULL; myThis = OFconst_cast(DcmOtherByteOtherWord*, this); myRhs = OFstatic_cast(DcmOtherByteOtherWord*, OFconst_cast(DcmElement*, &rhs)); /* compare length */ unsigned long thisLength = myThis->getLength(); unsigned long rhsLength= myRhs->getLength(); if (thisLength < rhsLength) { return -1; } else if (thisLength > rhsLength) { return 1; } /* finally, check equality of values. getValue() makes sure byte * swapping is applied as necessary. */ void* thisData = myThis->getValue(); void* rhsData = myRhs->getValue(); return memcmp(thisData, rhsData, thisLength); } OFCondition DcmOtherByteOtherWord::copyFrom(const DcmObject& rhs) { if (this != &rhs) { if (rhs.ident() != ident()) return EC_IllegalCall; *this = OFstatic_cast(const DcmOtherByteOtherWord &, rhs); } return EC_Normal; } // ******************************** DcmEVR DcmOtherByteOtherWord::ident() const { return getTag().getEVR(); } OFCondition DcmOtherByteOtherWord::checkValue(const OFString & /*vm*/, const OFBool /*oldFormat*/) { /* currently no checks are performed */ return EC_Normal; } unsigned long DcmOtherByteOtherWord::getVM() { /* value multiplicity for OB/OW is defined as 1 */ return 1; } unsigned long DcmOtherByteOtherWord::getNumberOfValues() { const DcmEVR evr = getTag().getEVR(); unsigned long result = OFstatic_cast(unsigned long, getLengthField()); /* check whether values are stored as 16 bit */ if ((evr == EVR_OW) || (evr == EVR_lt)) result /= 2; return result; } OFCondition DcmOtherByteOtherWord::setVR(DcmEVR vr) { setTagVR(vr); return EC_Normal; } // ******************************** void DcmOtherByteOtherWord::print(STD_NAMESPACE ostream &out, const size_t flags, const int level, const char * /*pixelFileName*/, size_t * /*pixelCounter*/) { if (valueLoaded()) { const DcmEVR evr = getTag().getEVR(); Uint16 *wordValues = NULL; Uint8 *byteValues = NULL; /* get 8 or 16 bit data respectively */ if (evr == EVR_OW || evr == EVR_lt) errorFlag = getUint16Array(wordValues); else errorFlag = getUint8Array(byteValues); /* check data */ if ((wordValues != NULL) || (byteValues != NULL)) { const unsigned long count = getNumberOfValues(); /* double-check length field for valid value */ if (count > 0) { /* determine number of values to be printed */ const unsigned int vrSize = (evr == EVR_OW || evr == EVR_lt) ? 4 : 2; unsigned long expectedLength = count * (vrSize + 1) - 1; const unsigned long printCount = ((expectedLength > DCM_OptPrintLineLength) && (flags & DCMTypes::PF_shortenLongTagValues)) ? (DCM_OptPrintLineLength - 3 /* for "..." */ + 1 /* for last "\" */) / (vrSize + 1) : count; unsigned long printedLength = printCount * (vrSize + 1) - 1; /* print line start with tag and VR */ printInfoLineStart(out, flags, level); /* print multiple values */ if (printCount > 0) { out << STD_NAMESPACE hex << STD_NAMESPACE setfill('0'); if (evr == EVR_OW || evr == EVR_lt) { /* print word values in hex mode */ out << STD_NAMESPACE setw(vrSize) << (*(wordValues++)); for (unsigned long i = 1; i < printCount; i++) out << "\\" << STD_NAMESPACE setw(vrSize) << (*(wordValues++)); } else { /* print byte values in hex mode */ out << STD_NAMESPACE setw(vrSize) << OFstatic_cast(int, *(byteValues++)); for (unsigned long i = 1; i < printCount; i++) out << "\\" << STD_NAMESPACE setw(vrSize) << OFstatic_cast(int, *(byteValues++)); } /* reset i/o manipulators */ out << STD_NAMESPACE dec << STD_NAMESPACE setfill(' '); } /* print trailing "..." if data has been truncated */ if (printCount < count) { out << "..."; printedLength += 3; } /* print line end with length, VM and tag name */ printInfoLineEnd(out, flags, printedLength); } else { /* count can be zero if we have an invalid OW element with less than two bytes length */ printInfoLine(out, flags, level, "(invalid value)"); } } else printInfoLine(out, flags, level, "(no value available)"); } else printInfoLine(out, flags, level, "(not loaded)"); } void DcmOtherByteOtherWord::printPixel(STD_NAMESPACE ostream &out, const size_t flags, const int level, const char *pixelFileName, size_t *pixelCounter) { if (pixelFileName != NULL) { /* create filename for pixel data file */ OFString fname = pixelFileName; fname += "."; if (pixelCounter != NULL) { char num[20]; sprintf(num, "%ld", OFstatic_cast(long, (*pixelCounter)++)); fname += num; } fname += ".raw"; /* create reference to pixel data file in dump output */ OFString str = "="; str += fname; printInfoLine(out, flags, level, str.c_str(), NULL /*tag*/, OFFalse /*isInfo*/); /* check whether pixel data file already exists */ if (!OFStandard::fileExists(fname)) { /* create binary file for pixel data */ FILE *file = fopen(fname.c_str(), "wb"); if (file != NULL) { if (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt) { /* write 16 bit data in little endian byte-order */ Uint16 *data = NULL; getUint16Array(data); if (data != NULL) { swapIfNecessary(EBO_LittleEndian, gLocalByteOrder, data, getLengthField(), sizeof(Uint16)); setByteOrder(EBO_LittleEndian); const size_t tobewritten = OFstatic_cast(size_t, getLengthField() / sizeof(Uint16)); const size_t written = fwrite(data, sizeof(Uint16), tobewritten, file); if (written != tobewritten) DCMDATA_WARN("DcmOtherByteOtherWord: Some bytes were not written: " << (tobewritten - written)); } } else { Uint8 *data = NULL; getUint8Array(data); if (data != NULL) { const size_t tobewritten = OFstatic_cast(size_t, getLengthField()); const size_t written = fwrite(data, sizeof(Uint8), tobewritten, file); if (written != tobewritten) DCMDATA_WARN("DcmOtherByteOtherWord: Some bytes were not written: " << (tobewritten - written)); } } fclose(file); } else { DCMDATA_WARN("DcmOtherByteOtherWord: Can't open output file for pixel data: " << fname); } } else { DCMDATA_WARN("DcmOtherByteOtherWord: Output file for pixel data already exists, skipping: " << fname); } } else DcmOtherByteOtherWord::print(out, flags, level, pixelFileName, pixelCounter); } // ******************************** OFCondition DcmOtherByteOtherWord::alignValue() { errorFlag = EC_Normal; if ((getTag().getEVR() != EVR_OW && getTag().getEVR() != EVR_lt) && (getLengthField() > 0) && ((getLengthField() & 1) != 0)) { // We have an odd number of bytes. This should never happen and is certainly not allowed in DICOM. // To fix this problem, we will add a zero pad byte at the end of the value field. // This requires us to load the value field into memory, which may very well be a problem // if this is part of a very large multi-frame object. Uint8 *bytes = OFstatic_cast(Uint8 *, getValue(getByteOrder())); // getValue() could call loadValue() which then calls postLoadValue() // which in turn calls this function again. Thus, we have to make sure // that the length field is still odd after getValue() returns. if (bytes && (getLengthField() & 1) != 0) { // newValueField always allocates an even number of bytes // and sets the pad byte to zero, so we can safely increase Length here setLengthField(getLengthField() + 1); } } return errorFlag; } void DcmOtherByteOtherWord::postLoadValue() { if (dcmEnableAutomaticInputDataCorrection.get()) alignValue(); } // ******************************** OFCondition DcmOtherByteOtherWord::putUint8Array(const Uint8 *byteValue, const unsigned long numBytes) { errorFlag = EC_Normal; if (numBytes > 0) { /* check for valid 8 bit data */ if ((byteValue != NULL) && (getTag().getEVR() != EVR_OW && getTag().getEVR() != EVR_lt)) { errorFlag = putValue(byteValue, OFstatic_cast(Uint32, sizeof(Uint8) * OFstatic_cast(size_t, numBytes))); alignValue(); } else errorFlag = EC_CorruptedData; } else putValue(NULL, 0); return errorFlag; } OFCondition DcmOtherByteOtherWord::putUint16Array(const Uint16 *wordValue, const unsigned long numWords) { errorFlag = EC_Normal; if (numWords > 0) { /* check for valid 16 bit data */ if ((wordValue != NULL) && (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt)) errorFlag = putValue(wordValue, OFstatic_cast(Uint32, sizeof(Uint16) * OFstatic_cast(size_t, numWords))); else errorFlag = EC_CorruptedData; } else errorFlag = putValue(NULL, 0); return errorFlag; } // ******************************** OFCondition DcmOtherByteOtherWord::createUint8Array(const Uint32 numBytes, Uint8 *&bytes) { /* check value representation */ if ((getTag().getEVR() != EVR_OW) && (getTag().getEVR() != EVR_lt)) errorFlag = createEmptyValue(OFstatic_cast(Uint32, sizeof(Uint8) * OFstatic_cast(size_t, numBytes))); else errorFlag = EC_CorruptedData; if (errorFlag.good()) bytes = OFstatic_cast(Uint8 *, this->getValue()); else bytes = NULL; return errorFlag; } OFCondition DcmOtherByteOtherWord::createUint16Array(const Uint32 numWords, Uint16 *&words) { /* check value representation */ if ((getTag().getEVR() == EVR_OW) || (getTag().getEVR() == EVR_lt)) { Uint32 bytesRequired = 0; OFBool size_fits = OFStandard::safeMult(numWords, OFstatic_cast(Uint32, sizeof(Uint16)), bytesRequired); if (size_fits) errorFlag = createEmptyValue(bytesRequired); else errorFlag = EC_CorruptedData; } else errorFlag = EC_CorruptedData; if (errorFlag.good()) words = OFstatic_cast(Uint16 *, this->getValue()); else words = NULL; return errorFlag; } // ******************************** OFCondition DcmOtherByteOtherWord::putString(const char *stringVal) { /* determine length of the string value */ const size_t stringLen = (stringVal != NULL) ? strlen(stringVal) : 0; /* call the real function */ return putString(stringVal, OFstatic_cast(Uint32, stringLen)); } OFCondition DcmOtherByteOtherWord::putString(const char *stringVal, const Uint32 stringLen) { errorFlag = EC_Normal; /* determine VM of the string */ unsigned long vm = DcmElement::determineVM(stringVal, stringLen); if (vm > 0) { const DcmEVR evr = getTag().getEVR(); Uint8 *byteField = NULL; Uint16 *wordField = NULL; /* create new value field */ if (evr == EVR_OW || evr == EVR_lt) wordField = new Uint16[vm]; else byteField = new Uint8[vm]; Uint16 intVal = 0; OFString value; size_t pos = 0; /* retrieve binary data from hexa-decimal string */ for (unsigned long i = 0; (i < vm) && errorFlag.good(); i++) { /* get specified value from multi-valued string */ pos = DcmElement::getValueFromString(stringVal, pos, stringLen, value); if (!value.empty()) { /* integer overflow is currently not checked! */ if (sscanf(value.c_str(), "%hx", &intVal) != 1) errorFlag = EC_CorruptedData; else if (evr == EVR_OW || evr == EVR_lt) wordField[i] = OFstatic_cast(Uint16, intVal); else byteField[i] = OFstatic_cast(Uint8, intVal); } else errorFlag = EC_CorruptedData; } /* set binary data as the element value */ if (errorFlag.good()) { if (evr == EVR_OW || evr == EVR_lt) errorFlag = putUint16Array(wordField, vm); else errorFlag = putUint8Array(byteField, vm); } /* delete temporary buffers */ delete[] byteField; delete[] wordField; } else putValue(NULL, 0); return errorFlag; } // ******************************** OFCondition DcmOtherByteOtherWord::getUint8(Uint8 &byteVal, const unsigned long pos) { /* get 8 bit data */ Uint8 *uintValues = NULL; errorFlag = getUint8Array(uintValues); /* check data before returning */ if (errorFlag.good()) { if (uintValues == NULL) errorFlag = EC_IllegalCall; else if (pos >= getLength() /*bytes*/) errorFlag = EC_IllegalParameter; else byteVal = uintValues[pos]; } /* clear value in case of error */ if (errorFlag.bad()) byteVal = 0; return errorFlag; } OFCondition DcmOtherByteOtherWord::getUint8Array(Uint8 *&byteVals) { errorFlag = EC_Normal; if (getTag().getEVR() != EVR_OW && getTag().getEVR() != EVR_lt) byteVals = OFstatic_cast(Uint8 *, getValue()); else errorFlag = EC_IllegalCall; return errorFlag; } // ******************************** OFCondition DcmOtherByteOtherWord::getUint16(Uint16 &wordVal, const unsigned long pos) { Uint16 *uintValues = NULL; errorFlag = getUint16Array(uintValues); /* check data before returning */ if (errorFlag.good()) { if (uintValues == NULL) errorFlag = EC_IllegalCall; else if (pos >= getLength() / sizeof(Uint16) /*words*/) errorFlag = EC_IllegalParameter; else wordVal = uintValues[pos]; } /* clear value in case of error */ if (errorFlag.bad()) wordVal = 0; return errorFlag; } OFCondition DcmOtherByteOtherWord::getUint16Array(Uint16 *&wordVals) { errorFlag = EC_Normal; if (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt) wordVals = OFstatic_cast(Uint16 *, getValue()); else errorFlag = EC_IllegalCall; return errorFlag; } // ******************************** OFCondition DcmOtherByteOtherWord::getOFString(OFString &stringVal, const unsigned long pos, OFBool /*normalize*/) { if (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt) { Uint16 uint16Val; /* get the specified numeric value (16 bit) */ errorFlag = getUint16(uint16Val, pos); if (errorFlag.good()) { /* ... and convert it to a character string (hex mode) */ char buffer[32]; sprintf(buffer, "%4.4hx", uint16Val); /* assign result */ stringVal = buffer; } } else { Uint8 uint8Val; /* get the specified numeric value (8 bit) */ errorFlag = getUint8(uint8Val, pos); if (errorFlag.good()) { /* ... and convert it to a character string (hex mode) */ char buffer[32]; sprintf(buffer, "%2.2hx", OFstatic_cast(unsigned short, uint8Val)); /* assign result */ stringVal = buffer; } } return errorFlag; } OFCondition DcmOtherByteOtherWord::getOFStringArray(OFString &stringVal, OFBool /*normalize*/) { if (getTag().getEVR() == EVR_OW || getTag().getEVR() == EVR_lt) { /* get array of 16 bit values */ Uint16 *uint16Vals = OFstatic_cast(Uint16 *, getValue()); const size_t count = OFstatic_cast(size_t, getLength() / sizeof(Uint16)); if ((uint16Vals != NULL) && (count > 0)) { OFOStringStream stream; /* output first value in hexadecimal format */ stream << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(4) << *(uint16Vals++); /* for all other array elements ... */ for (size_t i = 1; i < count; i++) stream << "\\" << STD_NAMESPACE setw(4) << *(uint16Vals++); stream << OFStringStream_ends; /* convert string stream into a character string */ OFSTRINGSTREAM_GETSTR(stream, buffer_str) stringVal.assign(buffer_str); OFSTRINGSTREAM_FREESTR(buffer_str) errorFlag = EC_Normal; } else errorFlag = EC_IllegalCall; } else { /* get array of 8 bit values */ Uint8 *uint8Vals = OFstatic_cast(Uint8 *, getValue()); const size_t count = OFstatic_cast(size_t, getLength()); if ((uint8Vals != NULL) && (count > 0)) { OFOStringStream stream; /* output first value in hexadecimal format */ stream << STD_NAMESPACE hex << STD_NAMESPACE setfill('0') << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(uint8Vals++)); /* for all other array elements ... */ for (size_t i = 1; i < count; i++) stream << "\\" << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(uint8Vals++)); stream << OFStringStream_ends; /* convert string stream into a character string */ OFSTRINGSTREAM_GETSTR(stream, buffer_str) stringVal.assign(buffer_str); OFSTRINGSTREAM_FREESTR(buffer_str) errorFlag = EC_Normal; } else errorFlag = EC_IllegalCall; } return errorFlag; } // ******************************** OFCondition DcmOtherByteOtherWord::verify(const OFBool autocorrect) { errorFlag = EC_Normal; if (autocorrect) errorFlag = alignValue(); return errorFlag; } // ******************************** OFBool DcmOtherByteOtherWord::canWriteXfer(const E_TransferSyntax newXfer, const E_TransferSyntax /*oldXfer*/) { DcmXfer newXferSyn(newXfer); return (getTag() != DCM_PixelData) || !newXferSyn.isEncapsulated(); } // ******************************** OFCondition DcmOtherByteOtherWord::write( DcmOutputStream &outStream, const E_TransferSyntax oxfer, const E_EncodingType enctype, DcmWriteCache *wcache) { if (getTransferState() == ERW_notInitialized) errorFlag = EC_IllegalCall; else { if (getTransferState() == ERW_init) { // if the attribute value is in file, we should call compact() if the write // operation causes the value to be loaded into main memory, which can happen // for odd length attributes. compactAfterTransfer = ! valueLoaded(); // this call may cause the attribute to be loaded into memory alignValue(); } // call inherited method errorFlag = DcmElement::write(outStream, oxfer, enctype, wcache); } // if the write operation has completed successfully, call compact if the // attribute value resided in file prior to the write operation. if (errorFlag.good() && compactAfterTransfer) compact(); // return error status return errorFlag; } OFCondition DcmOtherByteOtherWord::writeSignatureFormat( DcmOutputStream &outStream, const E_TransferSyntax oxfer, const E_EncodingType enctype, DcmWriteCache *wcache) { if (getTransferState() == ERW_notInitialized) errorFlag = EC_IllegalCall; else { if (getTransferState() == ERW_init) { // if the attribute value is in file, we should call compact() if the write // operation causes the value to be loaded into main memory, which can happen // for odd length attributes. compactAfterTransfer = ! valueLoaded(); // this call may cause the attribute to be loaded into memory alignValue(); } // call inherited method errorFlag = DcmElement::writeSignatureFormat(outStream, oxfer, enctype, wcache); } // if the write operation has completed successfully, call compact if the // attribute value resided in file prior to the write operation. if (errorFlag.good() && compactAfterTransfer) compact(); // return error status return errorFlag; } // ******************************** OFCondition DcmOtherByteOtherWord::writeXML(STD_NAMESPACE ostream &out, const size_t flags) { /* OB/OW data requires special handling in the Native DICOM Model format */ if (flags & DCMTypes::XF_useNativeModel) { /* write XML start tag */ writeXMLStartTag(out, flags); /* for an empty value field, we do not need to do anything */ if (getLengthField() > 0) { /* encode binary data as Base64 */ if (flags & DCMTypes::XF_encodeBase64) { const DcmEVR evr = getTag().getEVR(); out << ""; Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); if ((evr == EVR_OW) || (evr == EVR_lt)) { /* Base64 encoder requires big endian input data */ swapIfNecessary(EBO_BigEndian, gLocalByteOrder, byteValues, getLengthField(), sizeof(Uint16)); /* update the byte order indicator variable correspondingly */ setByteOrder(EBO_BigEndian); } OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); out << "" << OFendl; } else { /* generate a new UID but the binary data is not (yet) written. */ OFUUID uuid; out << "" << OFendl; } } /* write XML end tag */ writeXMLEndTag(out, flags); } else { /* XML start tag: */ if (!(flags & DCMTypes::XF_writeBinaryData)) writeXMLStartTag(out, flags, "binary=\"hidden\""); else if (flags & DCMTypes::XF_encodeBase64) writeXMLStartTag(out, flags, "binary=\"base64\""); else writeXMLStartTag(out, flags, "binary=\"yes\""); /* write element value (if loaded) */ if (valueLoaded() && (flags & DCMTypes::XF_writeBinaryData)) { const DcmEVR evr = getTag().getEVR(); /* encode binary data as Base64 */ if (flags & DCMTypes::XF_encodeBase64) { Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue()); if ((evr == EVR_OW) || (evr == EVR_lt)) { /* Base64 encoder requires big endian input data */ swapIfNecessary(EBO_BigEndian, gLocalByteOrder, byteValues, getLengthField(), sizeof(Uint16)); /* update the byte order indicator variable correspondingly */ setByteOrder(EBO_BigEndian); } OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); } else { if ((evr == EVR_OW) || (evr == EVR_lt)) { /* get and check 16 bit data */ Uint16 *wordValues = NULL; if (getUint16Array(wordValues).good() && (wordValues != NULL)) { const unsigned long count = getLengthField() / OFstatic_cast(unsigned long, sizeof(Uint16)); /* count can be zero if we have an invalid element with less than two bytes length */ if (count > 0) { out << STD_NAMESPACE hex << STD_NAMESPACE setfill('0'); /* print word values in hex mode */ out << STD_NAMESPACE setw(4) << (*(wordValues++)); for (unsigned long i = 1; i < count; i++) out << "\\" << STD_NAMESPACE setw(4) << (*(wordValues++)); /* reset i/o manipulators */ out << STD_NAMESPACE dec << STD_NAMESPACE setfill(' '); } } } else { /* get and check 8 bit data */ Uint8 *byteValues = NULL; if (getUint8Array(byteValues).good() && (byteValues != NULL)) { const unsigned long count = getLengthField(); out << STD_NAMESPACE hex << STD_NAMESPACE setfill('0'); /* print byte values in hex mode */ out << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(byteValues++)); for (unsigned long i = 1; i < count; i++) out << "\\" << STD_NAMESPACE setw(2) << OFstatic_cast(int, *(byteValues++)); /* reset i/o manipulators */ out << STD_NAMESPACE dec << STD_NAMESPACE setfill(' '); } } } } /* XML end tag: */ writeXMLEndTag(out, flags); } /* always report success */ return EC_Normal; } // ******************************** OFCondition DcmOtherByteOtherWord::writeJson(STD_NAMESPACE ostream &out, DcmJsonFormat &format) { /* write JSON Opener */ writeJsonOpener(out, format); /* for an empty value field, we do not need to do anything */ if (getLengthField() > 0) { OFString value; if (format.asBulkDataURI(getTag(), value)) { /* return defined BulkDataURI */ format.printBulkDataURIPrefix(out); DcmJsonFormat::printString(out, value); } else { /* encode binary data as Base64 */ format.printInlineBinaryPrefix(out); out << "\""; /* adjust byte order to little endian */ Uint8 *byteValues = OFstatic_cast(Uint8 *, getValue(EBO_LittleEndian)); OFStandard::encodeBase64(out, byteValues, OFstatic_cast(size_t, getLengthField())); out << "\""; } } /* write JSON Closer */ writeJsonCloser(out, format); /* always report success */ return EC_Normal; }