2541 lines
61 KiB
C++
2541 lines
61 KiB
C++
/**
|
|
* Orthanc - A Lightweight, RESTful DICOM Store
|
|
* Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
|
|
* Department, University Hospital of Liege, Belgium
|
|
* Copyright (C) 2017-2023 Osimis S.A., Belgium
|
|
* Copyright (C) 2024-2025 Orthanc Team SRL, Belgium
|
|
* Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium
|
|
*
|
|
* This program is free software: you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation, either version 3 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this program. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
|
|
#include "PrecompiledHeaders.h"
|
|
#include "Enumerations.h"
|
|
|
|
#include "Logging.h"
|
|
#include "MultiThreading/Mutex.h"
|
|
#include "OrthancException.h"
|
|
#include "Toolbox.h"
|
|
|
|
#include <string.h>
|
|
#include <cassert>
|
|
#include <boost/algorithm/string/replace.hpp>
|
|
|
|
namespace Orthanc
|
|
{
|
|
// This function is autogenerated by the script
|
|
// "Resources/CodeGeneration/GenerateErrorCodes.py"
|
|
const char* EnumerationToString(ErrorCode error)
|
|
{
|
|
switch (error)
|
|
{
|
|
case ErrorCode_InternalError:
|
|
return "Internal error";
|
|
|
|
case ErrorCode_Success:
|
|
return "Success";
|
|
|
|
case ErrorCode_Plugin:
|
|
return "Error encountered within the plugin engine";
|
|
|
|
case ErrorCode_NotImplemented:
|
|
return "Not implemented yet";
|
|
|
|
case ErrorCode_ParameterOutOfRange:
|
|
return "Parameter out of range";
|
|
|
|
case ErrorCode_NotEnoughMemory:
|
|
return "The server hosting Orthanc is running out of memory";
|
|
|
|
case ErrorCode_BadParameterType:
|
|
return "Bad type for a parameter";
|
|
|
|
case ErrorCode_BadSequenceOfCalls:
|
|
return "Bad sequence of calls";
|
|
|
|
case ErrorCode_InexistentItem:
|
|
return "Accessing an inexistent item";
|
|
|
|
case ErrorCode_BadRequest:
|
|
return "Bad request";
|
|
|
|
case ErrorCode_NetworkProtocol:
|
|
return "Error in the network protocol";
|
|
|
|
case ErrorCode_SystemCommand:
|
|
return "Error while calling a system command";
|
|
|
|
case ErrorCode_Database:
|
|
return "Error with the database engine";
|
|
|
|
case ErrorCode_UriSyntax:
|
|
return "Badly formatted URI";
|
|
|
|
case ErrorCode_InexistentFile:
|
|
return "Inexistent file";
|
|
|
|
case ErrorCode_CannotWriteFile:
|
|
return "Cannot write to file";
|
|
|
|
case ErrorCode_BadFileFormat:
|
|
return "Bad file format";
|
|
|
|
case ErrorCode_Timeout:
|
|
return "Timeout";
|
|
|
|
case ErrorCode_UnknownResource:
|
|
return "Unknown resource";
|
|
|
|
case ErrorCode_IncompatibleDatabaseVersion:
|
|
return "Incompatible version of the database";
|
|
|
|
case ErrorCode_FullStorage:
|
|
return "The file storage is full";
|
|
|
|
case ErrorCode_CorruptedFile:
|
|
return "Corrupted file (e.g. inconsistent MD5 hash)";
|
|
|
|
case ErrorCode_InexistentTag:
|
|
return "Inexistent tag";
|
|
|
|
case ErrorCode_ReadOnly:
|
|
return "Cannot modify a read-only data structure";
|
|
|
|
case ErrorCode_IncompatibleImageFormat:
|
|
return "Incompatible format of the images";
|
|
|
|
case ErrorCode_IncompatibleImageSize:
|
|
return "Incompatible size of the images";
|
|
|
|
case ErrorCode_SharedLibrary:
|
|
return "Error while using a shared library (plugin)";
|
|
|
|
case ErrorCode_UnknownPluginService:
|
|
return "Plugin invoking an unknown service";
|
|
|
|
case ErrorCode_UnknownDicomTag:
|
|
return "Unknown DICOM tag";
|
|
|
|
case ErrorCode_BadJson:
|
|
return "Cannot parse a JSON document";
|
|
|
|
case ErrorCode_Unauthorized:
|
|
return "Bad credentials were provided to an HTTP request";
|
|
|
|
case ErrorCode_BadFont:
|
|
return "Badly formatted font file";
|
|
|
|
case ErrorCode_DatabasePlugin:
|
|
return "The plugin implementing a custom database back-end does not fulfill the proper interface";
|
|
|
|
case ErrorCode_StorageAreaPlugin:
|
|
return "Error in the plugin implementing a custom storage area";
|
|
|
|
case ErrorCode_EmptyRequest:
|
|
return "The request is empty";
|
|
|
|
case ErrorCode_NotAcceptable:
|
|
return "Cannot send a response which is acceptable according to the Accept HTTP header";
|
|
|
|
case ErrorCode_NullPointer:
|
|
return "Cannot handle a NULL pointer";
|
|
|
|
case ErrorCode_DatabaseUnavailable:
|
|
return "The database is currently not available (probably a transient situation)";
|
|
|
|
case ErrorCode_CanceledJob:
|
|
return "This job was canceled";
|
|
|
|
case ErrorCode_BadGeometry:
|
|
return "Geometry error encountered in Stone";
|
|
|
|
case ErrorCode_SslInitialization:
|
|
return "Cannot initialize SSL encryption, check out your certificates";
|
|
|
|
case ErrorCode_DiscontinuedAbi:
|
|
return "Calling a function that has been removed from the Orthanc Framework";
|
|
|
|
case ErrorCode_BadRange:
|
|
return "Incorrect range request";
|
|
|
|
case ErrorCode_DatabaseCannotSerialize:
|
|
return "Database could not serialize access due to concurrent update, the transaction should be retried";
|
|
|
|
case ErrorCode_Revision:
|
|
return "A bad revision number was provided, which might indicate conflict between multiple writers";
|
|
|
|
case ErrorCode_MainDicomTagsMultiplyDefined:
|
|
return "A main DICOM Tag has been defined multiple times for the same resource level";
|
|
|
|
case ErrorCode_ForbiddenAccess:
|
|
return "Access to a resource is forbidden";
|
|
|
|
case ErrorCode_DuplicateResource:
|
|
return "Duplicate resource";
|
|
|
|
case ErrorCode_IncompatibleConfigurations:
|
|
return "Your configuration file contains configuration that are mutually incompatible";
|
|
|
|
case ErrorCode_SQLiteNotOpened:
|
|
return "SQLite: The database is not opened";
|
|
|
|
case ErrorCode_SQLiteAlreadyOpened:
|
|
return "SQLite: Connection is already open";
|
|
|
|
case ErrorCode_SQLiteCannotOpen:
|
|
return "SQLite: Unable to open the database";
|
|
|
|
case ErrorCode_SQLiteStatementAlreadyUsed:
|
|
return "SQLite: This cached statement is already being referred to";
|
|
|
|
case ErrorCode_SQLiteExecute:
|
|
return "SQLite: Cannot execute a command";
|
|
|
|
case ErrorCode_SQLiteRollbackWithoutTransaction:
|
|
return "SQLite: Rolling back a nonexistent transaction (have you called Begin()?)";
|
|
|
|
case ErrorCode_SQLiteCommitWithoutTransaction:
|
|
return "SQLite: Committing a nonexistent transaction";
|
|
|
|
case ErrorCode_SQLiteRegisterFunction:
|
|
return "SQLite: Unable to register a function";
|
|
|
|
case ErrorCode_SQLiteFlush:
|
|
return "SQLite: Unable to flush the database";
|
|
|
|
case ErrorCode_SQLiteCannotRun:
|
|
return "SQLite: Cannot run a cached statement";
|
|
|
|
case ErrorCode_SQLiteCannotStep:
|
|
return "SQLite: Cannot step over a cached statement";
|
|
|
|
case ErrorCode_SQLiteBindOutOfRange:
|
|
return "SQLite: Bind a value while out of range (serious error)";
|
|
|
|
case ErrorCode_SQLitePrepareStatement:
|
|
return "SQLite: Cannot prepare a cached statement";
|
|
|
|
case ErrorCode_SQLiteTransactionAlreadyStarted:
|
|
return "SQLite: Beginning the same transaction twice";
|
|
|
|
case ErrorCode_SQLiteTransactionCommit:
|
|
return "SQLite: Failure when committing the transaction";
|
|
|
|
case ErrorCode_SQLiteTransactionBegin:
|
|
return "SQLite: Cannot start a transaction";
|
|
|
|
case ErrorCode_DirectoryOverFile:
|
|
return "The directory to be created is already occupied by a regular file";
|
|
|
|
case ErrorCode_FileStorageCannotWrite:
|
|
return "Unable to create a subdirectory or a file in the file storage";
|
|
|
|
case ErrorCode_DirectoryExpected:
|
|
return "The specified path does not point to a directory";
|
|
|
|
case ErrorCode_HttpPortInUse:
|
|
return "The TCP port of the HTTP server is privileged or already in use";
|
|
|
|
case ErrorCode_DicomPortInUse:
|
|
return "The TCP port of the DICOM server is privileged or already in use";
|
|
|
|
case ErrorCode_BadHttpStatusInRest:
|
|
return "This HTTP status is not allowed in a REST API";
|
|
|
|
case ErrorCode_RegularFileExpected:
|
|
return "The specified path does not point to a regular file";
|
|
|
|
case ErrorCode_PathToExecutable:
|
|
return "Unable to get the path to the executable";
|
|
|
|
case ErrorCode_MakeDirectory:
|
|
return "Cannot create a directory";
|
|
|
|
case ErrorCode_BadApplicationEntityTitle:
|
|
return "An application entity title (AET) cannot be empty or be longer than 16 characters";
|
|
|
|
case ErrorCode_NoCFindHandler:
|
|
return "No request handler factory for DICOM C-FIND SCP";
|
|
|
|
case ErrorCode_NoCMoveHandler:
|
|
return "No request handler factory for DICOM C-MOVE SCP";
|
|
|
|
case ErrorCode_NoCStoreHandler:
|
|
return "No request handler factory for DICOM C-STORE SCP";
|
|
|
|
case ErrorCode_NoApplicationEntityFilter:
|
|
return "No application entity filter";
|
|
|
|
case ErrorCode_NoSopClassOrInstance:
|
|
return "DicomUserConnection: Unable to find the SOP class and instance";
|
|
|
|
case ErrorCode_NoPresentationContext:
|
|
return "DicomUserConnection: No acceptable presentation context for modality";
|
|
|
|
case ErrorCode_DicomFindUnavailable:
|
|
return "DicomUserConnection: The C-FIND command is not supported by the remote SCP";
|
|
|
|
case ErrorCode_DicomMoveUnavailable:
|
|
return "DicomUserConnection: The C-MOVE command is not supported by the remote SCP";
|
|
|
|
case ErrorCode_CannotStoreInstance:
|
|
return "Cannot store an instance";
|
|
|
|
case ErrorCode_CreateDicomNotString:
|
|
return "Only string values are supported when creating DICOM instances";
|
|
|
|
case ErrorCode_CreateDicomOverrideTag:
|
|
return "Trying to override a value inherited from a parent module";
|
|
|
|
case ErrorCode_CreateDicomUseContent:
|
|
return "Use \"Content\" to inject an image into a new DICOM instance";
|
|
|
|
case ErrorCode_CreateDicomNoPayload:
|
|
return "No payload is present for one instance in the series";
|
|
|
|
case ErrorCode_CreateDicomUseDataUriScheme:
|
|
return "The payload of the DICOM instance must be specified according to Data URI scheme";
|
|
|
|
case ErrorCode_CreateDicomBadParent:
|
|
return "Trying to attach a new DICOM instance to an inexistent resource";
|
|
|
|
case ErrorCode_CreateDicomParentIsInstance:
|
|
return "Trying to attach a new DICOM instance to an instance (must be a series, study or patient)";
|
|
|
|
case ErrorCode_CreateDicomParentEncoding:
|
|
return "Unable to get the encoding of the parent resource";
|
|
|
|
case ErrorCode_UnknownModality:
|
|
return "Unknown modality";
|
|
|
|
case ErrorCode_BadJobOrdering:
|
|
return "Bad ordering of filters in a job";
|
|
|
|
case ErrorCode_JsonToLuaTable:
|
|
return "Cannot convert the given JSON object to a Lua table";
|
|
|
|
case ErrorCode_CannotCreateLua:
|
|
return "Cannot create the Lua context";
|
|
|
|
case ErrorCode_CannotExecuteLua:
|
|
return "Cannot execute a Lua command";
|
|
|
|
case ErrorCode_LuaAlreadyExecuted:
|
|
return "Arguments cannot be pushed after the Lua function is executed";
|
|
|
|
case ErrorCode_LuaBadOutput:
|
|
return "The Lua function does not give the expected number of outputs";
|
|
|
|
case ErrorCode_NotLuaPredicate:
|
|
return "The Lua function is not a predicate (only true/false outputs allowed)";
|
|
|
|
case ErrorCode_LuaReturnsNoString:
|
|
return "The Lua function does not return a string";
|
|
|
|
case ErrorCode_StorageAreaAlreadyRegistered:
|
|
return "Another plugin has already registered a custom storage area";
|
|
|
|
case ErrorCode_DatabaseBackendAlreadyRegistered:
|
|
return "Another plugin has already registered a custom database back-end";
|
|
|
|
case ErrorCode_DatabaseNotInitialized:
|
|
return "Plugin trying to call the database during its initialization";
|
|
|
|
case ErrorCode_SslDisabled:
|
|
return "Orthanc has been built without SSL support";
|
|
|
|
case ErrorCode_CannotOrderSlices:
|
|
return "Unable to order the slices of the series";
|
|
|
|
case ErrorCode_NoWorklistHandler:
|
|
return "No request handler factory for DICOM C-Find Modality SCP";
|
|
|
|
case ErrorCode_AlreadyExistingTag:
|
|
return "Cannot override the value of a tag that already exists";
|
|
|
|
case ErrorCode_NoStorageCommitmentHandler:
|
|
return "No request handler factory for DICOM N-ACTION SCP (storage commitment)";
|
|
|
|
case ErrorCode_NoCGetHandler:
|
|
return "No request handler factory for DICOM C-GET SCP";
|
|
|
|
case ErrorCode_DicomGetUnavailable:
|
|
return "DicomUserConnection: The C-GET command is not supported by the remote SCP";
|
|
|
|
case ErrorCode_UnsupportedMediaType:
|
|
return "Unsupported media type";
|
|
|
|
default:
|
|
if (error >= ErrorCode_START_PLUGINS)
|
|
{
|
|
return "Error encountered within some plugin";
|
|
}
|
|
else
|
|
{
|
|
return "Unknown error code";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(HttpMethod method)
|
|
{
|
|
switch (method)
|
|
{
|
|
case HttpMethod_Get:
|
|
return "GET";
|
|
|
|
case HttpMethod_Post:
|
|
return "POST";
|
|
|
|
case HttpMethod_Delete:
|
|
return "DELETE";
|
|
|
|
case HttpMethod_Put:
|
|
return "PUT";
|
|
|
|
default:
|
|
return "?";
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(HttpStatus status)
|
|
{
|
|
switch (status)
|
|
{
|
|
case HttpStatus_100_Continue:
|
|
return "Continue";
|
|
|
|
case HttpStatus_101_SwitchingProtocols:
|
|
return "Switching Protocols";
|
|
|
|
case HttpStatus_102_Processing:
|
|
return "Processing";
|
|
|
|
case HttpStatus_200_Ok:
|
|
return "OK";
|
|
|
|
case HttpStatus_201_Created:
|
|
return "Created";
|
|
|
|
case HttpStatus_202_Accepted:
|
|
return "Accepted";
|
|
|
|
case HttpStatus_203_NonAuthoritativeInformation:
|
|
return "Non-Authoritative Information";
|
|
|
|
case HttpStatus_204_NoContent:
|
|
return "No Content";
|
|
|
|
case HttpStatus_205_ResetContent:
|
|
return "Reset Content";
|
|
|
|
case HttpStatus_206_PartialContent:
|
|
return "Partial Content";
|
|
|
|
case HttpStatus_207_MultiStatus:
|
|
return "Multi-Status";
|
|
|
|
case HttpStatus_208_AlreadyReported:
|
|
return "Already Reported";
|
|
|
|
case HttpStatus_226_IMUsed:
|
|
return "IM Used";
|
|
|
|
case HttpStatus_300_MultipleChoices:
|
|
return "Multiple Choices";
|
|
|
|
case HttpStatus_301_MovedPermanently:
|
|
return "Moved Permanently";
|
|
|
|
case HttpStatus_302_Found:
|
|
return "Found";
|
|
|
|
case HttpStatus_303_SeeOther:
|
|
return "See Other";
|
|
|
|
case HttpStatus_304_NotModified:
|
|
return "Not Modified";
|
|
|
|
case HttpStatus_305_UseProxy:
|
|
return "Use Proxy";
|
|
|
|
case HttpStatus_307_TemporaryRedirect:
|
|
return "Temporary Redirect";
|
|
|
|
case HttpStatus_400_BadRequest:
|
|
return "Bad Request";
|
|
|
|
case HttpStatus_401_Unauthorized:
|
|
return "Unauthorized";
|
|
|
|
case HttpStatus_402_PaymentRequired:
|
|
return "Payment Required";
|
|
|
|
case HttpStatus_403_Forbidden:
|
|
return "Forbidden";
|
|
|
|
case HttpStatus_404_NotFound:
|
|
return "Not Found";
|
|
|
|
case HttpStatus_405_MethodNotAllowed:
|
|
return "Method Not Allowed";
|
|
|
|
case HttpStatus_406_NotAcceptable:
|
|
return "Not Acceptable";
|
|
|
|
case HttpStatus_407_ProxyAuthenticationRequired:
|
|
return "Proxy Authentication Required";
|
|
|
|
case HttpStatus_408_RequestTimeout:
|
|
return "Request Timeout";
|
|
|
|
case HttpStatus_409_Conflict:
|
|
return "Conflict";
|
|
|
|
case HttpStatus_410_Gone:
|
|
return "Gone";
|
|
|
|
case HttpStatus_411_LengthRequired:
|
|
return "Length Required";
|
|
|
|
case HttpStatus_412_PreconditionFailed:
|
|
return "Precondition Failed";
|
|
|
|
case HttpStatus_413_RequestEntityTooLarge:
|
|
return "Request Entity Too Large";
|
|
|
|
case HttpStatus_414_RequestUriTooLong:
|
|
return "Request-URI Too Long";
|
|
|
|
case HttpStatus_415_UnsupportedMediaType:
|
|
return "Unsupported Media Type";
|
|
|
|
case HttpStatus_416_RequestedRangeNotSatisfiable:
|
|
return "Requested Range Not Satisfiable";
|
|
|
|
case HttpStatus_417_ExpectationFailed:
|
|
return "Expectation Failed";
|
|
|
|
case HttpStatus_422_UnprocessableEntity:
|
|
return "Unprocessable Entity";
|
|
|
|
case HttpStatus_423_Locked:
|
|
return "Locked";
|
|
|
|
case HttpStatus_424_FailedDependency:
|
|
return "Failed Dependency";
|
|
|
|
case HttpStatus_426_UpgradeRequired:
|
|
return "Upgrade Required";
|
|
|
|
case HttpStatus_500_InternalServerError:
|
|
return "Internal Server Error";
|
|
|
|
case HttpStatus_501_NotImplemented:
|
|
return "Not Implemented";
|
|
|
|
case HttpStatus_502_BadGateway:
|
|
return "Bad Gateway";
|
|
|
|
case HttpStatus_503_ServiceUnavailable:
|
|
return "Service Unavailable";
|
|
|
|
case HttpStatus_504_GatewayTimeout:
|
|
return "Gateway Timeout";
|
|
|
|
case HttpStatus_505_HttpVersionNotSupported:
|
|
return "HTTP Version Not Supported";
|
|
|
|
case HttpStatus_506_VariantAlsoNegotiates:
|
|
return "Variant Also Negotiates";
|
|
|
|
case HttpStatus_507_InsufficientStorage:
|
|
return "Insufficient Storage";
|
|
|
|
case HttpStatus_509_BandwidthLimitExceeded:
|
|
return "Bandwidth Limit Exceeded";
|
|
|
|
case HttpStatus_510_NotExtended:
|
|
return "Not Extended";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(ResourceType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ResourceType_Patient:
|
|
return "Patient";
|
|
|
|
case ResourceType_Study:
|
|
return "Study";
|
|
|
|
case ResourceType_Series:
|
|
return "Series";
|
|
|
|
case ResourceType_Instance:
|
|
return "Instance";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(ImageFormat format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case ImageFormat_Png:
|
|
return "Png";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(Encoding encoding)
|
|
{
|
|
switch (encoding)
|
|
{
|
|
case Encoding_Ascii:
|
|
return "Ascii";
|
|
|
|
case Encoding_Utf8:
|
|
return "Utf8";
|
|
|
|
case Encoding_Latin1:
|
|
return "Latin1";
|
|
|
|
case Encoding_Latin2:
|
|
return "Latin2";
|
|
|
|
case Encoding_Latin3:
|
|
return "Latin3";
|
|
|
|
case Encoding_Latin4:
|
|
return "Latin4";
|
|
|
|
case Encoding_Latin5:
|
|
return "Latin5";
|
|
|
|
case Encoding_Cyrillic:
|
|
return "Cyrillic";
|
|
|
|
case Encoding_Windows1251:
|
|
return "Windows1251";
|
|
|
|
case Encoding_Arabic:
|
|
return "Arabic";
|
|
|
|
case Encoding_Greek:
|
|
return "Greek";
|
|
|
|
case Encoding_Hebrew:
|
|
return "Hebrew";
|
|
|
|
case Encoding_Thai:
|
|
return "Thai";
|
|
|
|
case Encoding_Japanese:
|
|
return "Japanese";
|
|
|
|
case Encoding_Chinese:
|
|
return "Chinese";
|
|
|
|
case Encoding_Korean:
|
|
return "Korean";
|
|
|
|
case Encoding_JapaneseKanji:
|
|
return "JapaneseKanji";
|
|
|
|
case Encoding_SimplifiedChinese:
|
|
return "SimplifiedChinese";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(PhotometricInterpretation photometric)
|
|
{
|
|
switch (photometric)
|
|
{
|
|
case PhotometricInterpretation_RGB:
|
|
return "RGB";
|
|
|
|
case PhotometricInterpretation_Monochrome1:
|
|
return "MONOCHROME1";
|
|
|
|
case PhotometricInterpretation_Monochrome2:
|
|
return "MONOCHROME2";
|
|
|
|
case PhotometricInterpretation_ARGB:
|
|
return "ARGB";
|
|
|
|
case PhotometricInterpretation_CMYK:
|
|
return "CMYK";
|
|
|
|
case PhotometricInterpretation_HSV:
|
|
return "HSV";
|
|
|
|
case PhotometricInterpretation_Palette:
|
|
return "PALETTE COLOR";
|
|
|
|
case PhotometricInterpretation_YBRFull:
|
|
return "YBR_FULL";
|
|
|
|
case PhotometricInterpretation_YBRFull422:
|
|
return "YBR_FULL_422";
|
|
|
|
case PhotometricInterpretation_YBRPartial420:
|
|
return "YBR_PARTIAL_420";
|
|
|
|
case PhotometricInterpretation_YBRPartial422:
|
|
return "YBR_PARTIAL_422";
|
|
|
|
case PhotometricInterpretation_YBR_ICT:
|
|
return "YBR_ICT";
|
|
|
|
case PhotometricInterpretation_YBR_RCT:
|
|
return "YBR_RCT";
|
|
|
|
case PhotometricInterpretation_Unknown:
|
|
return "Unknown";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(RequestOrigin origin)
|
|
{
|
|
switch (origin)
|
|
{
|
|
case RequestOrigin_Unknown:
|
|
return "Unknown";
|
|
|
|
case RequestOrigin_DicomProtocol:
|
|
return "DicomProtocol";
|
|
|
|
case RequestOrigin_RestApi:
|
|
return "RestApi";
|
|
|
|
case RequestOrigin_Plugins:
|
|
return "Plugins";
|
|
|
|
case RequestOrigin_Lua:
|
|
return "Lua";
|
|
|
|
case RequestOrigin_WebDav:
|
|
return "WebDav";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(PixelFormat format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case PixelFormat_RGB24:
|
|
return "RGB24";
|
|
|
|
case PixelFormat_RGBA32:
|
|
return "RGBA32";
|
|
|
|
case PixelFormat_BGRA32:
|
|
return "BGRA32";
|
|
|
|
case PixelFormat_Grayscale8:
|
|
return "Grayscale (unsigned 8bpp)";
|
|
|
|
case PixelFormat_Grayscale16:
|
|
return "Grayscale (unsigned 16bpp)";
|
|
|
|
case PixelFormat_SignedGrayscale16:
|
|
return "Grayscale (signed 16bpp)";
|
|
|
|
case PixelFormat_Float32:
|
|
return "Grayscale (float 32bpp)";
|
|
|
|
case PixelFormat_Grayscale32:
|
|
return "Grayscale (unsigned 32bpp)";
|
|
|
|
case PixelFormat_Grayscale64:
|
|
return "Grayscale (unsigned 64bpp)";
|
|
|
|
case PixelFormat_RGB48:
|
|
return "RGB48";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(ModalityManufacturer manufacturer)
|
|
{
|
|
switch (manufacturer)
|
|
{
|
|
case ModalityManufacturer_Generic:
|
|
return "Generic";
|
|
|
|
case ModalityManufacturer_GenericNoWildcardInDates:
|
|
return "GenericNoWildcardInDates";
|
|
|
|
case ModalityManufacturer_GenericNoUniversalWildcard:
|
|
return "GenericNoUniversalWildcard";
|
|
|
|
case ModalityManufacturer_Vitrea:
|
|
return "Vitrea";
|
|
|
|
case ModalityManufacturer_GE:
|
|
return "GE";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(DicomRequestType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case DicomRequestType_Echo:
|
|
return "Echo";
|
|
break;
|
|
|
|
case DicomRequestType_Find:
|
|
return "Find";
|
|
break;
|
|
|
|
case DicomRequestType_FindWorklist:
|
|
return "FindWorklist";
|
|
break;
|
|
|
|
case DicomRequestType_Get:
|
|
return "Get";
|
|
break;
|
|
|
|
case DicomRequestType_Move:
|
|
return "Move";
|
|
break;
|
|
|
|
case DicomRequestType_Store:
|
|
return "Store";
|
|
break;
|
|
|
|
case DicomRequestType_NAction:
|
|
return "N-ACTION";
|
|
break;
|
|
|
|
case DicomRequestType_NEventReport:
|
|
return "N-EVENT-REPORT";
|
|
break;
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(DicomVersion version)
|
|
{
|
|
switch (version)
|
|
{
|
|
case DicomVersion_2008:
|
|
return "2008";
|
|
|
|
case DicomVersion_2017c:
|
|
return "2017c";
|
|
|
|
case DicomVersion_2021b:
|
|
return "2021b";
|
|
|
|
case DicomVersion_2023b:
|
|
return "2023b";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(ValueRepresentation vr)
|
|
{
|
|
switch (vr)
|
|
{
|
|
case ValueRepresentation_ApplicationEntity: // AE
|
|
return "AE";
|
|
|
|
case ValueRepresentation_AgeString: // AS
|
|
return "AS";
|
|
|
|
case ValueRepresentation_AttributeTag: // AT (2 x uint16_t)
|
|
return "AT";
|
|
|
|
case ValueRepresentation_CodeString: // CS
|
|
return "CS";
|
|
|
|
case ValueRepresentation_Date: // DA
|
|
return "DA";
|
|
|
|
case ValueRepresentation_DecimalString: // DS
|
|
return "DS";
|
|
|
|
case ValueRepresentation_DateTime: // DT
|
|
return "DT";
|
|
|
|
case ValueRepresentation_FloatingPointSingle: // FL (float)
|
|
return "FL";
|
|
|
|
case ValueRepresentation_FloatingPointDouble: // FD (double)
|
|
return "FD";
|
|
|
|
case ValueRepresentation_IntegerString: // IS
|
|
return "IS";
|
|
|
|
case ValueRepresentation_LongString: // LO
|
|
return "LO";
|
|
|
|
case ValueRepresentation_LongText: // LT
|
|
return "LT";
|
|
|
|
case ValueRepresentation_OtherByte: // OB
|
|
return "OB";
|
|
|
|
case ValueRepresentation_OtherDouble: // OD
|
|
return "OD";
|
|
|
|
case ValueRepresentation_OtherFloat: // OF
|
|
return "OF";
|
|
|
|
case ValueRepresentation_OtherLong: // OL
|
|
return "OL";
|
|
|
|
case ValueRepresentation_OtherWord: // OW
|
|
return "OW";
|
|
|
|
case ValueRepresentation_PersonName: // PN
|
|
return "PN";
|
|
|
|
case ValueRepresentation_ShortString: // SH
|
|
return "SH";
|
|
|
|
case ValueRepresentation_SignedLong: // SL (int32_t)
|
|
return "SL";
|
|
|
|
case ValueRepresentation_Sequence: // SQ
|
|
return "SQ";
|
|
|
|
case ValueRepresentation_SignedShort: // SS (int16_t)
|
|
return "SS";
|
|
|
|
case ValueRepresentation_ShortText: // ST
|
|
return "ST";
|
|
|
|
case ValueRepresentation_Time: // TM
|
|
return "TM";
|
|
|
|
case ValueRepresentation_UnlimitedCharacters: // UC
|
|
return "UC";
|
|
|
|
case ValueRepresentation_UniqueIdentifier: // UI (UID)
|
|
return "UI";
|
|
|
|
case ValueRepresentation_UnsignedLong: // UL (uint32_t)
|
|
return "UL";
|
|
|
|
case ValueRepresentation_Unknown: // UN
|
|
return "UN";
|
|
|
|
case ValueRepresentation_UniversalResource: // UR (URI or URL)
|
|
return "UR";
|
|
|
|
case ValueRepresentation_UnsignedShort: // US (uint16_t)
|
|
return "US";
|
|
|
|
case ValueRepresentation_UnlimitedText: // UT
|
|
return "UT";
|
|
|
|
case ValueRepresentation_NotSupported:
|
|
return "Not supported";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(JobState state)
|
|
{
|
|
switch (state)
|
|
{
|
|
case JobState_Pending:
|
|
return "Pending";
|
|
|
|
case JobState_Running:
|
|
return "Running";
|
|
|
|
case JobState_Success:
|
|
return "Success";
|
|
|
|
case JobState_Failure:
|
|
return "Failure";
|
|
|
|
case JobState_Paused:
|
|
return "Paused";
|
|
|
|
case JobState_Retry:
|
|
return "Retry";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(MimeType mime)
|
|
{
|
|
switch (mime)
|
|
{
|
|
case MimeType_Binary:
|
|
return MIME_BINARY;
|
|
|
|
case MimeType_Dicom:
|
|
return MIME_DICOM;
|
|
|
|
case MimeType_Jpeg:
|
|
return MIME_JPEG;
|
|
|
|
case MimeType_Jpeg2000:
|
|
return MIME_JPEG2000;
|
|
|
|
case MimeType_Json:
|
|
return MIME_JSON;
|
|
|
|
case MimeType_Pdf:
|
|
return MIME_PDF;
|
|
|
|
case MimeType_Png:
|
|
return MIME_PNG;
|
|
|
|
case MimeType_Xml:
|
|
return MIME_XML;
|
|
|
|
case MimeType_PlainText:
|
|
return MIME_PLAIN_TEXT;
|
|
|
|
case MimeType_Pam:
|
|
return MIME_PAM;
|
|
|
|
case MimeType_Html:
|
|
return MIME_HTML;
|
|
|
|
case MimeType_Gzip:
|
|
return MIME_GZIP;
|
|
|
|
case MimeType_JavaScript:
|
|
return MIME_JAVASCRIPT;
|
|
|
|
case MimeType_Css:
|
|
return MIME_CSS;
|
|
|
|
case MimeType_WebAssembly:
|
|
return MIME_WEB_ASSEMBLY;
|
|
|
|
case MimeType_Gif:
|
|
return MIME_GIF;
|
|
|
|
case MimeType_Zip:
|
|
return MIME_ZIP;
|
|
|
|
case MimeType_NaCl:
|
|
return MIME_NACL;
|
|
|
|
case MimeType_PNaCl:
|
|
return MIME_PNACL;
|
|
|
|
case MimeType_Svg:
|
|
return MIME_SVG;
|
|
|
|
case MimeType_Woff:
|
|
return MIME_WOFF;
|
|
|
|
case MimeType_Woff2:
|
|
return MIME_WOFF2;
|
|
|
|
case MimeType_PrometheusText:
|
|
// https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format
|
|
return "text/plain; version=0.0.4";
|
|
|
|
case MimeType_DicomWebJson:
|
|
return MIME_DICOM_WEB_JSON;
|
|
|
|
case MimeType_DicomWebXml:
|
|
return MIME_DICOM_WEB_XML;
|
|
|
|
case MimeType_Ico:
|
|
return MIME_ICO;
|
|
|
|
case MimeType_Obj:
|
|
return MIME_OBJ;
|
|
|
|
case MimeType_Mtl:
|
|
return MIME_MTL;
|
|
|
|
case MimeType_Stl:
|
|
return MIME_STL;
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(Endianness endianness)
|
|
{
|
|
switch (endianness)
|
|
{
|
|
case Endianness_Little:
|
|
return "Little-endian";
|
|
|
|
case Endianness_Big:
|
|
return "Big-endian";
|
|
|
|
case Endianness_Unknown:
|
|
return "Unknown endianness";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(StorageCommitmentFailureReason reason)
|
|
{
|
|
switch (reason)
|
|
{
|
|
case StorageCommitmentFailureReason_Success:
|
|
return "Success";
|
|
|
|
case StorageCommitmentFailureReason_ProcessingFailure:
|
|
return "A general failure in processing the operation was encountered";
|
|
|
|
case StorageCommitmentFailureReason_NoSuchObjectInstance:
|
|
return "One or more of the elements in the Referenced SOP "
|
|
"Instance Sequence was not available";
|
|
|
|
case StorageCommitmentFailureReason_ResourceLimitation:
|
|
return "The SCP does not currently have enough resources to "
|
|
"store the requested SOP Instance(s)";
|
|
|
|
case StorageCommitmentFailureReason_ReferencedSOPClassNotSupported:
|
|
return "Storage Commitment has been requested for a SOP Instance "
|
|
"with a SOP Class that is not supported by the SCP";
|
|
|
|
case StorageCommitmentFailureReason_ClassInstanceConflict:
|
|
return "The SOP Class of an element in the Referenced SOP Instance Sequence "
|
|
"did not correspond to the SOP class registered for this SOP Instance at the SCP";
|
|
|
|
case StorageCommitmentFailureReason_DuplicateTransactionUID:
|
|
return "The Transaction UID of the Storage Commitment Request is already in use";
|
|
|
|
default:
|
|
return "Unknown failure reason";
|
|
}
|
|
}
|
|
|
|
|
|
const char* EnumerationToString(DicomToJsonFormat format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case DicomToJsonFormat_Full:
|
|
return "Full";
|
|
|
|
case DicomToJsonFormat_Human:
|
|
return "Simplify";
|
|
|
|
case DicomToJsonFormat_Short:
|
|
return "Short";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
Encoding StringToEncoding(const char* encoding)
|
|
{
|
|
std::string s(encoding);
|
|
Toolbox::ToUpperCase(s);
|
|
|
|
if (s == "UTF8")
|
|
{
|
|
return Encoding_Utf8;
|
|
}
|
|
|
|
if (s == "ASCII")
|
|
{
|
|
return Encoding_Ascii;
|
|
}
|
|
|
|
if (s == "LATIN1")
|
|
{
|
|
return Encoding_Latin1;
|
|
}
|
|
|
|
if (s == "LATIN2")
|
|
{
|
|
return Encoding_Latin2;
|
|
}
|
|
|
|
if (s == "LATIN3")
|
|
{
|
|
return Encoding_Latin3;
|
|
}
|
|
|
|
if (s == "LATIN4")
|
|
{
|
|
return Encoding_Latin4;
|
|
}
|
|
|
|
if (s == "LATIN5")
|
|
{
|
|
return Encoding_Latin5;
|
|
}
|
|
|
|
if (s == "CYRILLIC")
|
|
{
|
|
return Encoding_Cyrillic;
|
|
}
|
|
|
|
if (s == "WINDOWS1251")
|
|
{
|
|
return Encoding_Windows1251;
|
|
}
|
|
|
|
if (s == "ARABIC")
|
|
{
|
|
return Encoding_Arabic;
|
|
}
|
|
|
|
if (s == "GREEK")
|
|
{
|
|
return Encoding_Greek;
|
|
}
|
|
|
|
if (s == "HEBREW")
|
|
{
|
|
return Encoding_Hebrew;
|
|
}
|
|
|
|
if (s == "THAI")
|
|
{
|
|
return Encoding_Thai;
|
|
}
|
|
|
|
if (s == "JAPANESE")
|
|
{
|
|
return Encoding_Japanese;
|
|
}
|
|
|
|
if (s == "CHINESE")
|
|
{
|
|
return Encoding_Chinese;
|
|
}
|
|
|
|
if (s == "KOREAN")
|
|
{
|
|
return Encoding_Korean;
|
|
}
|
|
|
|
if (s == "JAPANESEKANJI")
|
|
{
|
|
return Encoding_JapaneseKanji;
|
|
}
|
|
|
|
if (s == "SIMPLIFIEDCHINESE")
|
|
{
|
|
return Encoding_SimplifiedChinese;
|
|
}
|
|
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
|
|
|
|
ResourceType StringToResourceType(const char* type)
|
|
{
|
|
std::string s(type);
|
|
Toolbox::ToUpperCase(s);
|
|
|
|
if (s == "PATIENT" || s == "PATIENTS")
|
|
{
|
|
return ResourceType_Patient;
|
|
}
|
|
else if (s == "STUDY" || s == "STUDIES")
|
|
{
|
|
return ResourceType_Study;
|
|
}
|
|
else if (s == "SERIES")
|
|
{
|
|
return ResourceType_Series;
|
|
}
|
|
else if (s == "INSTANCE" || s == "IMAGE" ||
|
|
s == "INSTANCES" || s == "IMAGES")
|
|
{
|
|
return ResourceType_Instance;
|
|
}
|
|
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange, std::string("Invalid resource type '") + type + "'");
|
|
}
|
|
|
|
const char* ResourceTypeToDicomQueryRetrieveLevel(ResourceType type)
|
|
{
|
|
if (type == ResourceType_Patient)
|
|
{
|
|
return "PATIENT";
|
|
}
|
|
else if (type == ResourceType_Study)
|
|
{
|
|
return "STUDY";
|
|
}
|
|
else if (type == ResourceType_Series)
|
|
{
|
|
return "SERIES";
|
|
}
|
|
else if (type == ResourceType_Instance)
|
|
{
|
|
return "IMAGE";
|
|
}
|
|
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
|
|
ImageFormat StringToImageFormat(const char* format)
|
|
{
|
|
std::string s(format);
|
|
Toolbox::ToUpperCase(s);
|
|
|
|
if (s == "PNG")
|
|
{
|
|
return ImageFormat_Png;
|
|
}
|
|
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
|
|
|
|
ValueRepresentation StringToValueRepresentation(const std::string& vr,
|
|
bool throwIfUnsupported)
|
|
{
|
|
if (vr == "AE")
|
|
{
|
|
return ValueRepresentation_ApplicationEntity;
|
|
}
|
|
else if (vr == "AS")
|
|
{
|
|
return ValueRepresentation_AgeString;
|
|
}
|
|
else if (vr == "AT")
|
|
{
|
|
return ValueRepresentation_AttributeTag;
|
|
}
|
|
else if (vr == "CS")
|
|
{
|
|
return ValueRepresentation_CodeString;
|
|
}
|
|
else if (vr == "DA")
|
|
{
|
|
return ValueRepresentation_Date;
|
|
}
|
|
else if (vr == "DS")
|
|
{
|
|
return ValueRepresentation_DecimalString;
|
|
}
|
|
else if (vr == "DT")
|
|
{
|
|
return ValueRepresentation_DateTime;
|
|
}
|
|
else if (vr == "FL")
|
|
{
|
|
return ValueRepresentation_FloatingPointSingle;
|
|
}
|
|
else if (vr == "FD")
|
|
{
|
|
return ValueRepresentation_FloatingPointDouble;
|
|
}
|
|
else if (vr == "IS")
|
|
{
|
|
return ValueRepresentation_IntegerString;
|
|
}
|
|
else if (vr == "LO")
|
|
{
|
|
return ValueRepresentation_LongString;
|
|
}
|
|
else if (vr == "LT")
|
|
{
|
|
return ValueRepresentation_LongText;
|
|
}
|
|
else if (vr == "OB")
|
|
{
|
|
return ValueRepresentation_OtherByte;
|
|
}
|
|
else if (vr == "OD")
|
|
{
|
|
return ValueRepresentation_OtherDouble;
|
|
}
|
|
else if (vr == "OF")
|
|
{
|
|
return ValueRepresentation_OtherFloat;
|
|
}
|
|
else if (vr == "OL")
|
|
{
|
|
return ValueRepresentation_OtherLong;
|
|
}
|
|
else if (vr == "OW")
|
|
{
|
|
return ValueRepresentation_OtherWord;
|
|
}
|
|
else if (vr == "PN")
|
|
{
|
|
return ValueRepresentation_PersonName;
|
|
}
|
|
else if (vr == "SH")
|
|
{
|
|
return ValueRepresentation_ShortString;
|
|
}
|
|
else if (vr == "SL")
|
|
{
|
|
return ValueRepresentation_SignedLong;
|
|
}
|
|
else if (vr == "SQ")
|
|
{
|
|
return ValueRepresentation_Sequence;
|
|
}
|
|
else if (vr == "SS")
|
|
{
|
|
return ValueRepresentation_SignedShort;
|
|
}
|
|
else if (vr == "ST")
|
|
{
|
|
return ValueRepresentation_ShortText;
|
|
}
|
|
else if (vr == "TM")
|
|
{
|
|
return ValueRepresentation_Time;
|
|
}
|
|
else if (vr == "UC")
|
|
{
|
|
return ValueRepresentation_UnlimitedCharacters;
|
|
}
|
|
else if (vr == "UI")
|
|
{
|
|
return ValueRepresentation_UniqueIdentifier;
|
|
}
|
|
else if (vr == "UL")
|
|
{
|
|
return ValueRepresentation_UnsignedLong;
|
|
}
|
|
else if (vr == "UN")
|
|
{
|
|
return ValueRepresentation_Unknown;
|
|
}
|
|
else if (vr == "UR")
|
|
{
|
|
return ValueRepresentation_UniversalResource;
|
|
}
|
|
else if (vr == "US")
|
|
{
|
|
return ValueRepresentation_UnsignedShort;
|
|
}
|
|
else if (vr == "UT")
|
|
{
|
|
return ValueRepresentation_UnlimitedText;
|
|
}
|
|
else
|
|
{
|
|
std::string s = "Unsupported value representation encountered: " + vr;
|
|
|
|
if (throwIfUnsupported)
|
|
{
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange, s);
|
|
}
|
|
else
|
|
{
|
|
LOG(INFO) << s;
|
|
return ValueRepresentation_NotSupported;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
PhotometricInterpretation StringToPhotometricInterpretation(const char* value)
|
|
{
|
|
// http://dicom.nema.org/medical/dicom/2017a/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.2
|
|
std::string s(value);
|
|
|
|
if (s == "MONOCHROME1")
|
|
{
|
|
return PhotometricInterpretation_Monochrome1;
|
|
}
|
|
|
|
if (s == "MONOCHROME2")
|
|
{
|
|
return PhotometricInterpretation_Monochrome2;
|
|
}
|
|
|
|
if (s == "PALETTE COLOR")
|
|
{
|
|
return PhotometricInterpretation_Palette;
|
|
}
|
|
|
|
if (s == "RGB")
|
|
{
|
|
return PhotometricInterpretation_RGB;
|
|
}
|
|
|
|
if (s == "HSV")
|
|
{
|
|
return PhotometricInterpretation_HSV;
|
|
}
|
|
|
|
if (s == "ARGB")
|
|
{
|
|
return PhotometricInterpretation_ARGB;
|
|
}
|
|
|
|
if (s == "CMYK")
|
|
{
|
|
return PhotometricInterpretation_CMYK;
|
|
}
|
|
|
|
if (s == "YBR_FULL")
|
|
{
|
|
return PhotometricInterpretation_YBRFull;
|
|
}
|
|
|
|
if (s == "YBR_FULL_422")
|
|
{
|
|
return PhotometricInterpretation_YBRFull422;
|
|
}
|
|
|
|
if (s == "YBR_PARTIAL_422")
|
|
{
|
|
return PhotometricInterpretation_YBRPartial422;
|
|
}
|
|
|
|
if (s == "YBR_PARTIAL_420")
|
|
{
|
|
return PhotometricInterpretation_YBRPartial420;
|
|
}
|
|
|
|
if (s == "YBR_ICT")
|
|
{
|
|
return PhotometricInterpretation_YBR_ICT;
|
|
}
|
|
|
|
if (s == "YBR_RCT")
|
|
{
|
|
return PhotometricInterpretation_YBR_RCT;
|
|
}
|
|
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
|
|
|
|
ModalityManufacturer StringToModalityManufacturer(const std::string& manufacturer)
|
|
{
|
|
ModalityManufacturer result;
|
|
bool obsolete = false;
|
|
|
|
if (manufacturer == "Generic")
|
|
{
|
|
return ModalityManufacturer_Generic;
|
|
}
|
|
else if (manufacturer == "GenericNoWildcardInDates")
|
|
{
|
|
return ModalityManufacturer_GenericNoWildcardInDates;
|
|
}
|
|
else if (manufacturer == "GenericNoUniversalWildcard")
|
|
{
|
|
return ModalityManufacturer_GenericNoUniversalWildcard;
|
|
}
|
|
else if (manufacturer == "Vitrea")
|
|
{
|
|
return ModalityManufacturer_Vitrea;
|
|
}
|
|
else if (manufacturer == "GE")
|
|
{
|
|
return ModalityManufacturer_GE;
|
|
}
|
|
else if (manufacturer == "AgfaImpax" ||
|
|
manufacturer == "SyngoVia")
|
|
{
|
|
result = ModalityManufacturer_GenericNoWildcardInDates;
|
|
obsolete = true;
|
|
}
|
|
else if (manufacturer == "EFilm2" ||
|
|
manufacturer == "MedInria" ||
|
|
manufacturer == "ClearCanvas" ||
|
|
manufacturer == "Dcm4Chee"
|
|
)
|
|
{
|
|
result = ModalityManufacturer_Generic;
|
|
obsolete = true;
|
|
}
|
|
else
|
|
{
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange,
|
|
"Unknown modality manufacturer: \"" + manufacturer + "\"");
|
|
}
|
|
|
|
if (obsolete)
|
|
{
|
|
LOG(WARNING) << "The \"" << manufacturer << "\" manufacturer is now obsolete. "
|
|
<< "To guarantee compatibility with future Orthanc "
|
|
<< "releases, you should replace it by \""
|
|
<< EnumerationToString(result)
|
|
<< "\" in your configuration file.";
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
DicomVersion StringToDicomVersion(const std::string& version)
|
|
{
|
|
if (version == "2008")
|
|
{
|
|
return DicomVersion_2008;
|
|
}
|
|
else if (version == "2017c")
|
|
{
|
|
return DicomVersion_2017c;
|
|
}
|
|
else if (version == "2021b")
|
|
{
|
|
return DicomVersion_2021b;
|
|
}
|
|
else if (version == "2023b")
|
|
{
|
|
return DicomVersion_2023b;
|
|
}
|
|
else
|
|
{
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange,
|
|
"Unknown specific version of the DICOM standard: " + version);
|
|
}
|
|
}
|
|
|
|
|
|
JobState StringToJobState(const std::string& state)
|
|
{
|
|
if (state == "Pending")
|
|
{
|
|
return JobState_Pending;
|
|
}
|
|
else if (state == "Running")
|
|
{
|
|
return JobState_Running;
|
|
}
|
|
else if (state == "Success")
|
|
{
|
|
return JobState_Success;
|
|
}
|
|
else if (state == "Failure")
|
|
{
|
|
return JobState_Failure;
|
|
}
|
|
else if (state == "Paused")
|
|
{
|
|
return JobState_Paused;
|
|
}
|
|
else if (state == "Retry")
|
|
{
|
|
return JobState_Retry;
|
|
}
|
|
else
|
|
{
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
RequestOrigin StringToRequestOrigin(const std::string& origin)
|
|
{
|
|
if (origin == "Unknown")
|
|
{
|
|
return RequestOrigin_Unknown;
|
|
}
|
|
else if (origin == "DicomProtocol")
|
|
{
|
|
return RequestOrigin_DicomProtocol;
|
|
}
|
|
else if (origin == "RestApi")
|
|
{
|
|
return RequestOrigin_RestApi;
|
|
}
|
|
else if (origin == "Plugins")
|
|
{
|
|
return RequestOrigin_Plugins;
|
|
}
|
|
else if (origin == "Lua")
|
|
{
|
|
return RequestOrigin_Lua;
|
|
}
|
|
else if (origin == "WebDav")
|
|
{
|
|
return RequestOrigin_WebDav;
|
|
}
|
|
else
|
|
{
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
bool LookupMimeType(MimeType& target,
|
|
const std::string& source)
|
|
{
|
|
if (source == MIME_BINARY)
|
|
{
|
|
target = MimeType_Binary;
|
|
return true;
|
|
}
|
|
else if (source == MIME_DICOM)
|
|
{
|
|
target = MimeType_Dicom;
|
|
return true;
|
|
}
|
|
else if (source == MIME_JPEG ||
|
|
source == "image/jpg")
|
|
{
|
|
// Note the tolerance for "image/jpg", which is *not* a standard MIME type
|
|
// https://groups.google.com/g/orthanc-users/c/Y5x37UFKiDg/m/1zI260KTAwAJ
|
|
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Image_types
|
|
target = MimeType_Jpeg;
|
|
return true;
|
|
}
|
|
else if (source == MIME_JPEG2000)
|
|
{
|
|
target = MimeType_Jpeg2000;
|
|
return true;
|
|
}
|
|
else if (source == MIME_JSON)
|
|
{
|
|
target = MimeType_Json;
|
|
return true;
|
|
}
|
|
else if (source == MIME_PDF)
|
|
{
|
|
target = MimeType_Pdf;
|
|
return true;
|
|
}
|
|
else if (source == MIME_PNG)
|
|
{
|
|
target = MimeType_Png;
|
|
return true;
|
|
}
|
|
else if (source == MIME_XML ||
|
|
source == MIME_XML_2)
|
|
{
|
|
target = MimeType_Xml;
|
|
return true;
|
|
}
|
|
else if (source == MIME_PLAIN_TEXT)
|
|
{
|
|
target = MimeType_PlainText;
|
|
return true;
|
|
}
|
|
else if (source == MIME_PAM)
|
|
{
|
|
target = MimeType_Pam;
|
|
return true;
|
|
}
|
|
else if (source == MIME_HTML)
|
|
{
|
|
target = MimeType_Html;
|
|
return true;
|
|
}
|
|
else if (source == MIME_GZIP)
|
|
{
|
|
target = MimeType_Gzip;
|
|
return true;
|
|
}
|
|
else if (source == MIME_JAVASCRIPT)
|
|
{
|
|
target = MimeType_JavaScript;
|
|
return true;
|
|
}
|
|
else if (source == MIME_CSS)
|
|
{
|
|
target = MimeType_Css;
|
|
return true;
|
|
}
|
|
else if (source == MIME_WEB_ASSEMBLY)
|
|
{
|
|
target = MimeType_WebAssembly;
|
|
return true;
|
|
}
|
|
else if (source == MIME_GIF)
|
|
{
|
|
target = MimeType_Gif;
|
|
return true;
|
|
}
|
|
else if (source == MIME_ZIP)
|
|
{
|
|
target = MimeType_Zip;
|
|
return true;
|
|
}
|
|
else if (source == MIME_NACL)
|
|
{
|
|
target = MimeType_NaCl;
|
|
return true;
|
|
}
|
|
else if (source == MIME_PNACL)
|
|
{
|
|
target = MimeType_PNaCl;
|
|
return true;
|
|
}
|
|
else if (source == MIME_SVG)
|
|
{
|
|
target = MimeType_Svg;
|
|
return true;
|
|
}
|
|
else if (source == MIME_WOFF)
|
|
{
|
|
target = MimeType_Woff;
|
|
return true;
|
|
}
|
|
else if (source == MIME_WOFF2)
|
|
{
|
|
target = MimeType_Woff2;
|
|
return true;
|
|
}
|
|
else if (source == MIME_DICOM_WEB_JSON)
|
|
{
|
|
target = MimeType_DicomWebJson;
|
|
return true;
|
|
}
|
|
else if (source == MIME_DICOM_WEB_XML)
|
|
{
|
|
target = MimeType_DicomWebXml;
|
|
return true;
|
|
}
|
|
else if (source == MIME_ICO)
|
|
{
|
|
target = MimeType_Ico;
|
|
return true;
|
|
}
|
|
else if (source == MIME_OBJ)
|
|
{
|
|
target = MimeType_Obj;
|
|
return true;
|
|
}
|
|
else if (source == MIME_MTL)
|
|
{
|
|
target = MimeType_Mtl;
|
|
return true;
|
|
}
|
|
else if (source == MIME_STL)
|
|
{
|
|
target = MimeType_Stl;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
MimeType StringToMimeType(const std::string& mime)
|
|
{
|
|
MimeType result;
|
|
if (LookupMimeType(result, mime))
|
|
{
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
DicomToJsonFormat StringToDicomToJsonFormat(const std::string& format)
|
|
{
|
|
if (format == "Full")
|
|
{
|
|
return DicomToJsonFormat_Full;
|
|
}
|
|
else if (format == "Short")
|
|
{
|
|
return DicomToJsonFormat_Short;
|
|
}
|
|
else if (format == "Simplify")
|
|
{
|
|
return DicomToJsonFormat_Human;
|
|
}
|
|
else
|
|
{
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
unsigned int GetBytesPerPixel(PixelFormat format)
|
|
{
|
|
switch (format)
|
|
{
|
|
case PixelFormat_Grayscale8:
|
|
return 1;
|
|
|
|
case PixelFormat_Grayscale16:
|
|
case PixelFormat_SignedGrayscale16:
|
|
return 2;
|
|
|
|
case PixelFormat_RGB24:
|
|
return 3;
|
|
|
|
case PixelFormat_RGBA32:
|
|
case PixelFormat_BGRA32:
|
|
case PixelFormat_Grayscale32:
|
|
return 4;
|
|
|
|
case PixelFormat_Float32:
|
|
assert(sizeof(float) == 4);
|
|
return 4;
|
|
|
|
case PixelFormat_RGB48:
|
|
return 6;
|
|
|
|
case PixelFormat_Grayscale64:
|
|
case PixelFormat_RGBA64:
|
|
return 8;
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
bool GetDicomEncoding(Encoding& encoding,
|
|
const char* specificCharacterSet)
|
|
{
|
|
std::string s = Toolbox::StripSpaces(specificCharacterSet);
|
|
Toolbox::ToUpperCase(s);
|
|
|
|
// handle common spelling mistakes
|
|
boost::replace_all(s, "ISO_IR_", "ISO_IR ");
|
|
boost::replace_all(s, "ISO_2022_IR_", "ISO 2022 IR ");
|
|
|
|
|
|
// http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2
|
|
// https://github.com/dcm4che/dcm4che/blob/master/dcm4che-core/src/main/java/org/dcm4che3/data/SpecificCharacterSet.java
|
|
if (s == "ISO_IR 6" ||
|
|
s == "ISO 2022 IR 6")
|
|
{
|
|
encoding = Encoding_Ascii;
|
|
}
|
|
else if (s == "ISO_IR 192")
|
|
{
|
|
encoding = Encoding_Utf8;
|
|
}
|
|
else if (s == "ISO_IR 100" ||
|
|
s == "ISO 2022 IR 100")
|
|
{
|
|
encoding = Encoding_Latin1;
|
|
}
|
|
else if (s == "ISO_IR 101" ||
|
|
s == "ISO 2022 IR 101")
|
|
{
|
|
encoding = Encoding_Latin2;
|
|
}
|
|
else if (s == "ISO_IR 109" ||
|
|
s == "ISO 2022 IR 109")
|
|
{
|
|
encoding = Encoding_Latin3;
|
|
}
|
|
else if (s == "ISO_IR 110" ||
|
|
s == "ISO 2022 IR 110")
|
|
{
|
|
encoding = Encoding_Latin4;
|
|
}
|
|
else if (s == "ISO_IR 148" ||
|
|
s == "ISO 2022 IR 148")
|
|
{
|
|
encoding = Encoding_Latin5;
|
|
}
|
|
else if (s == "ISO_IR 144" ||
|
|
s == "ISO 2022 IR 144")
|
|
{
|
|
encoding = Encoding_Cyrillic;
|
|
}
|
|
else if (s == "ISO_IR 127" ||
|
|
s == "ISO 2022 IR 127")
|
|
{
|
|
encoding = Encoding_Arabic;
|
|
}
|
|
else if (s == "ISO_IR 126" ||
|
|
s == "ISO 2022 IR 126")
|
|
{
|
|
encoding = Encoding_Greek;
|
|
}
|
|
else if (s == "ISO_IR 138" ||
|
|
s == "ISO 2022 IR 138")
|
|
{
|
|
encoding = Encoding_Hebrew;
|
|
}
|
|
else if (s == "ISO_IR 166" ||
|
|
s == "ISO 2022 IR 166")
|
|
{
|
|
encoding = Encoding_Thai;
|
|
}
|
|
else if (s == "ISO_IR 13" ||
|
|
s == "ISO 2022 IR 13")
|
|
{
|
|
encoding = Encoding_Japanese;
|
|
}
|
|
else if (s == "GB18030" || s == "GBK")
|
|
{
|
|
/**
|
|
* According to tumashu@163.com, "In China, many dicom file's
|
|
* 0008,0005 tag is set as "GBK", instead of "GB18030", GBK is a
|
|
* subset of GB18030, and which is used frequently in China,
|
|
* suggest support it."
|
|
* https://groups.google.com/d/msg/orthanc-users/WMM8LMbjpUc/02-1f_yFCgAJ
|
|
**/
|
|
encoding = Encoding_Chinese;
|
|
}
|
|
else if (s == "ISO 2022 IR 149")
|
|
{
|
|
encoding = Encoding_Korean;
|
|
}
|
|
else if (s == "ISO 2022 IR 87")
|
|
{
|
|
encoding = Encoding_JapaneseKanji;
|
|
}
|
|
else if (s == "ISO 2022 IR 58")
|
|
{
|
|
encoding = Encoding_SimplifiedChinese;
|
|
}
|
|
/*
|
|
else if (s == "ISO 2022 IR 159")
|
|
{
|
|
TODO - Supplementary Kanji set
|
|
}
|
|
*/
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// The encoding was properly detected
|
|
return true;
|
|
}
|
|
|
|
|
|
ResourceType GetChildResourceType(ResourceType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ResourceType_Patient:
|
|
return ResourceType_Study;
|
|
|
|
case ResourceType_Study:
|
|
return ResourceType_Series;
|
|
|
|
case ResourceType_Series:
|
|
return ResourceType_Instance;
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
ResourceType GetParentResourceType(ResourceType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ResourceType_Study:
|
|
return ResourceType_Patient;
|
|
|
|
case ResourceType_Series:
|
|
return ResourceType_Study;
|
|
|
|
case ResourceType_Instance:
|
|
return ResourceType_Series;
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
bool IsResourceLevelAboveOrEqual(ResourceType level,
|
|
ResourceType reference)
|
|
{
|
|
switch (reference)
|
|
{
|
|
case ResourceType_Patient:
|
|
return (level == ResourceType_Patient);
|
|
|
|
case ResourceType_Study:
|
|
return (level == ResourceType_Patient ||
|
|
level == ResourceType_Study);
|
|
|
|
case ResourceType_Series:
|
|
return (level == ResourceType_Patient ||
|
|
level == ResourceType_Study ||
|
|
level == ResourceType_Series);
|
|
|
|
case ResourceType_Instance:
|
|
return (level == ResourceType_Patient ||
|
|
level == ResourceType_Study ||
|
|
level == ResourceType_Series ||
|
|
level == ResourceType_Instance);
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
DicomModule GetModule(ResourceType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ResourceType_Patient:
|
|
return DicomModule_Patient;
|
|
|
|
case ResourceType_Study:
|
|
return DicomModule_Study;
|
|
|
|
case ResourceType_Series:
|
|
return DicomModule_Series;
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const char* GetDicomSpecificCharacterSet(Encoding encoding)
|
|
{
|
|
// http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2
|
|
switch (encoding)
|
|
{
|
|
case Encoding_Ascii:
|
|
return "ISO_IR 6";
|
|
|
|
case Encoding_Utf8:
|
|
return "ISO_IR 192";
|
|
|
|
case Encoding_Latin1:
|
|
return "ISO_IR 100";
|
|
|
|
case Encoding_Latin2:
|
|
return "ISO_IR 101";
|
|
|
|
case Encoding_Latin3:
|
|
return "ISO_IR 109";
|
|
|
|
case Encoding_Latin4:
|
|
return "ISO_IR 110";
|
|
|
|
case Encoding_Latin5:
|
|
return "ISO_IR 148";
|
|
|
|
case Encoding_Cyrillic:
|
|
return "ISO_IR 144";
|
|
|
|
case Encoding_Arabic:
|
|
return "ISO_IR 127";
|
|
|
|
case Encoding_Greek:
|
|
return "ISO_IR 126";
|
|
|
|
case Encoding_Hebrew:
|
|
return "ISO_IR 138";
|
|
|
|
case Encoding_Japanese:
|
|
return "ISO_IR 13";
|
|
|
|
case Encoding_Chinese:
|
|
return "GB18030";
|
|
|
|
case Encoding_Thai:
|
|
return "ISO_IR 166";
|
|
|
|
case Encoding_Korean:
|
|
return "ISO 2022 IR 149";
|
|
|
|
case Encoding_JapaneseKanji:
|
|
return "ISO 2022 IR 87";
|
|
|
|
case Encoding_SimplifiedChinese:
|
|
return "ISO 2022 IR 58";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
// This function is autogenerated by the script
|
|
// "Resources/CodeGeneration/GenerateErrorCodes.py"
|
|
HttpStatus ConvertErrorCodeToHttpStatus(ErrorCode error)
|
|
{
|
|
switch (error)
|
|
{
|
|
case ErrorCode_Success:
|
|
return HttpStatus_200_Ok;
|
|
|
|
case ErrorCode_ParameterOutOfRange:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_BadParameterType:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_InexistentItem:
|
|
return HttpStatus_404_NotFound;
|
|
|
|
case ErrorCode_BadRequest:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_UriSyntax:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_InexistentFile:
|
|
return HttpStatus_404_NotFound;
|
|
|
|
case ErrorCode_BadFileFormat:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_UnknownResource:
|
|
return HttpStatus_404_NotFound;
|
|
|
|
case ErrorCode_InexistentTag:
|
|
return HttpStatus_404_NotFound;
|
|
|
|
case ErrorCode_BadJson:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_Unauthorized:
|
|
return HttpStatus_401_Unauthorized;
|
|
|
|
case ErrorCode_NotAcceptable:
|
|
return HttpStatus_406_NotAcceptable;
|
|
|
|
case ErrorCode_DatabaseUnavailable:
|
|
return HttpStatus_503_ServiceUnavailable;
|
|
|
|
case ErrorCode_BadRange:
|
|
return HttpStatus_416_RequestedRangeNotSatisfiable;
|
|
|
|
case ErrorCode_DatabaseCannotSerialize:
|
|
return HttpStatus_503_ServiceUnavailable;
|
|
|
|
case ErrorCode_Revision:
|
|
return HttpStatus_409_Conflict;
|
|
|
|
case ErrorCode_ForbiddenAccess:
|
|
return HttpStatus_403_Forbidden;
|
|
|
|
case ErrorCode_DuplicateResource:
|
|
return HttpStatus_409_Conflict;
|
|
|
|
case ErrorCode_CreateDicomNotString:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_CreateDicomOverrideTag:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_CreateDicomUseContent:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_CreateDicomNoPayload:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_CreateDicomUseDataUriScheme:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_CreateDicomBadParent:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_CreateDicomParentIsInstance:
|
|
return HttpStatus_400_BadRequest;
|
|
|
|
case ErrorCode_UnsupportedMediaType:
|
|
return HttpStatus_415_UnsupportedMediaType;
|
|
|
|
default:
|
|
return HttpStatus_500_InternalServerError;
|
|
}
|
|
}
|
|
|
|
|
|
bool IsUserContentType(FileContentType type)
|
|
{
|
|
return (type >= FileContentType_StartUser &&
|
|
type <= FileContentType_EndUser);
|
|
}
|
|
|
|
|
|
bool IsBinaryValueRepresentation(ValueRepresentation vr)
|
|
{
|
|
// http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html
|
|
|
|
switch (vr)
|
|
{
|
|
case ValueRepresentation_ApplicationEntity: // AE
|
|
case ValueRepresentation_AgeString: // AS
|
|
case ValueRepresentation_CodeString: // CS
|
|
case ValueRepresentation_Date: // DA
|
|
case ValueRepresentation_DecimalString: // DS
|
|
case ValueRepresentation_DateTime: // DT
|
|
case ValueRepresentation_IntegerString: // IS
|
|
case ValueRepresentation_LongString: // LO
|
|
case ValueRepresentation_LongText: // LT
|
|
case ValueRepresentation_PersonName: // PN
|
|
case ValueRepresentation_ShortString: // SH
|
|
case ValueRepresentation_ShortText: // ST
|
|
case ValueRepresentation_Time: // TM
|
|
case ValueRepresentation_UnlimitedCharacters: // UC
|
|
case ValueRepresentation_UniqueIdentifier: // UI (UID)
|
|
case ValueRepresentation_UniversalResource: // UR (URI or URL)
|
|
case ValueRepresentation_UnlimitedText: // UT
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Below are all the VR whose character repertoire is tagged as
|
|
* "not applicable"
|
|
**/
|
|
case ValueRepresentation_AttributeTag: // AT (2 x uint16_t)
|
|
case ValueRepresentation_FloatingPointSingle: // FL (float)
|
|
case ValueRepresentation_FloatingPointDouble: // FD (double)
|
|
case ValueRepresentation_OtherByte: // OB
|
|
case ValueRepresentation_OtherDouble: // OD
|
|
case ValueRepresentation_OtherFloat: // OF
|
|
case ValueRepresentation_OtherLong: // OL
|
|
case ValueRepresentation_OtherWord: // OW
|
|
case ValueRepresentation_SignedLong: // SL (int32_t)
|
|
case ValueRepresentation_Sequence: // SQ
|
|
case ValueRepresentation_SignedShort: // SS (int16_t)
|
|
case ValueRepresentation_UnsignedLong: // UL (uint32_t)
|
|
case ValueRepresentation_Unknown: // UN
|
|
case ValueRepresentation_UnsignedShort: // US (uint16_t)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
case ValueRepresentation_NotSupported:
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
|
|
|
|
static Mutex defaultEncodingMutex_; // Should not be necessary
|
|
static Encoding defaultEncoding_ = ORTHANC_DEFAULT_DICOM_ENCODING;
|
|
|
|
Encoding GetDefaultDicomEncoding()
|
|
{
|
|
Mutex::ScopedLock lock(defaultEncodingMutex_);
|
|
return defaultEncoding_;
|
|
}
|
|
|
|
void SetDefaultDicomEncoding(Encoding encoding)
|
|
{
|
|
std::string name = EnumerationToString(encoding);
|
|
|
|
{
|
|
Mutex::ScopedLock lock(defaultEncodingMutex_);
|
|
defaultEncoding_ = encoding;
|
|
}
|
|
|
|
LOG(INFO) << "Default encoding for DICOM was changed to: " << name;
|
|
}
|
|
|
|
|
|
const char* GetResourceTypeText(ResourceType type,
|
|
bool isPlural,
|
|
bool isUpperCase)
|
|
{
|
|
if (isPlural && !isUpperCase)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ResourceType_Patient:
|
|
return "patients";
|
|
|
|
case ResourceType_Study:
|
|
return "studies";
|
|
|
|
case ResourceType_Series:
|
|
return "series";
|
|
|
|
case ResourceType_Instance:
|
|
return "instances";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
else if (isPlural && isUpperCase)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ResourceType_Patient:
|
|
return "Patients";
|
|
|
|
case ResourceType_Study:
|
|
return "Studies";
|
|
|
|
case ResourceType_Series:
|
|
return "Series";
|
|
|
|
case ResourceType_Instance:
|
|
return "Instances";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
else if (!isPlural && !isUpperCase)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ResourceType_Patient:
|
|
return "patient";
|
|
|
|
case ResourceType_Study:
|
|
return "study";
|
|
|
|
case ResourceType_Series:
|
|
return "series";
|
|
|
|
case ResourceType_Instance:
|
|
return "instance";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
else if (!isPlural && isUpperCase)
|
|
{
|
|
switch (type)
|
|
{
|
|
case ResourceType_Patient:
|
|
return "Patient";
|
|
|
|
case ResourceType_Study:
|
|
return "Study";
|
|
|
|
case ResourceType_Series:
|
|
return "Series";
|
|
|
|
case ResourceType_Instance:
|
|
return "Instance";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw OrthancException(ErrorCode_InternalError);
|
|
}
|
|
}
|
|
|
|
DicomTransferSyntax GetTransferSyntax(const std::string& value)
|
|
{
|
|
DicomTransferSyntax syntax;
|
|
if (LookupTransferSyntax(syntax, value))
|
|
{
|
|
return syntax;
|
|
}
|
|
else
|
|
{
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange,
|
|
"Unknown transfer syntax: " + value);
|
|
}
|
|
}
|
|
|
|
RetrieveMethod StringToRetrieveMethod(const std::string& str)
|
|
{
|
|
if (str == "C-MOVE")
|
|
{
|
|
return RetrieveMethod_Move;
|
|
}
|
|
else if (str == "C-GET")
|
|
{
|
|
return RetrieveMethod_Get;
|
|
}
|
|
else if (str == "SystemDefault")
|
|
{
|
|
return RetrieveMethod_SystemDefault;
|
|
}
|
|
else
|
|
{
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange,
|
|
"RetrieveMethod can be \"C-MOVE\", \"C-GET\" or \"SystemDefault\": " + str);
|
|
}
|
|
}
|
|
|
|
const char* EnumerationToString(RetrieveMethod method)
|
|
{
|
|
switch (method)
|
|
{
|
|
case RetrieveMethod_Get:
|
|
return "C-GET";
|
|
|
|
case RetrieveMethod_Move:
|
|
return "C-MOVE";
|
|
|
|
case RetrieveMethod_SystemDefault:
|
|
return "SystemDefault";
|
|
|
|
default:
|
|
throw OrthancException(ErrorCode_ParameterOutOfRange);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#include "./Enumerations_TransferSyntaxes.impl.h"
|