Mercurial > hg > orthanc
comparison OrthancServer/FromDcmtkBridge.cpp @ 319:760d0f32cb34
PMSCT_RLE1
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 03 Jan 2013 13:19:51 +0100 |
parents | b83d85a85d69 |
children | 80011cd589e6 |
comparison
equal
deleted
inserted
replaced
318:b83d85a85d69 | 319:760d0f32cb34 |
---|---|
1075 w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), | 1075 w.WriteToMemory(result, accessor.GetWidth(), accessor.GetHeight(), |
1076 accessor.GetWidth() * sizeof(T), format, &image[0]); | 1076 accessor.GetWidth() * sizeof(T), format, &image[0]); |
1077 } | 1077 } |
1078 | 1078 |
1079 | 1079 |
1080 static bool DecodePsmctRle1(std::string& output, | |
1081 DcmDataset& dataset) | |
1082 { | |
1083 static const DicomTag tagContent(0x07a1, 0x100a); | |
1084 static const DicomTag tagCompressionType(0x07a1, 0x1011); | |
1085 | |
1086 DcmElement* e; | |
1087 char* c; | |
1088 | |
1089 // Check whether the DICOM instance contains an image encoded with | |
1090 // the PMSCT_RLE1 scheme. | |
1091 if (!dataset.findAndGetElement(ToDcmtkBridge::Convert(tagCompressionType), e).good() || | |
1092 e == NULL || | |
1093 !e->isaString() || | |
1094 !e->getString(c).good() || | |
1095 c == NULL || | |
1096 strcmp("PMSCT_RLE1", c)) | |
1097 { | |
1098 return false; | |
1099 } | |
1100 | |
1101 // OK, this is a custom RLE encoding from Philips. Get the pixel | |
1102 // data from the appropriate private DICOM tag. | |
1103 Uint8* pixData = NULL; | |
1104 if (!dataset.findAndGetElement(ToDcmtkBridge::Convert(tagContent), e).good() || | |
1105 e == NULL || | |
1106 e->getUint8Array(pixData) != EC_Normal) | |
1107 { | |
1108 return false; | |
1109 } | |
1110 | |
1111 // The "unsigned" below IS VERY IMPORTANT | |
1112 const uint8_t* inbuffer = reinterpret_cast<const uint8_t*>(pixData); | |
1113 const size_t length = e->getLength(); | |
1114 | |
1115 /** | |
1116 * The code below is an adaptation of a sample code for GDCM by | |
1117 * Mathieu Malaterre (under a BSD license). | |
1118 * http://gdcm.sourceforge.net/html/rle2img_8cxx-example.html | |
1119 **/ | |
1120 | |
1121 // RLE pass | |
1122 std::vector<uint8_t> temp; | |
1123 temp.reserve(length); | |
1124 for (size_t i = 0; i < length; i++) | |
1125 { | |
1126 if (inbuffer[i] == 0xa5) | |
1127 { | |
1128 temp.push_back(inbuffer[i+2]); | |
1129 for (uint8_t repeat = inbuffer[i + 1]; repeat != 0; repeat--) | |
1130 { | |
1131 temp.push_back(inbuffer[i+2]); | |
1132 } | |
1133 i += 2; | |
1134 } | |
1135 else | |
1136 { | |
1137 temp.push_back(inbuffer[i]); | |
1138 } | |
1139 } | |
1140 | |
1141 // Delta encoding pass | |
1142 uint16_t delta = 0; | |
1143 output.clear(); | |
1144 output.reserve(temp.size()); | |
1145 for (size_t i = 0; i < temp.size(); i++) | |
1146 { | |
1147 uint16_t value; | |
1148 | |
1149 if (temp[i] == 0x5a) | |
1150 { | |
1151 uint16_t v1 = temp[i + 1]; | |
1152 uint16_t v2 = temp[i + 2]; | |
1153 value = (v2 << 8) + v1; | |
1154 i += 2; | |
1155 } | |
1156 else | |
1157 { | |
1158 value = delta + (int8_t) temp[i]; | |
1159 } | |
1160 | |
1161 output.push_back(value & 0xff); | |
1162 output.push_back(value >> 8); | |
1163 delta = value; | |
1164 } | |
1165 | |
1166 if (output.size() % 2) | |
1167 { | |
1168 output.resize(output.size() - 1); | |
1169 } | |
1170 | |
1171 return true; | |
1172 } | |
1173 | |
1174 | |
1080 void FromDcmtkBridge::ExtractPngImage(std::string& result, | 1175 void FromDcmtkBridge::ExtractPngImage(std::string& result, |
1081 DcmDataset& dataset, | 1176 DcmDataset& dataset, |
1082 unsigned int frame, | 1177 unsigned int frame, |
1083 ImageExtractionMode mode) | 1178 ImageExtractionMode mode) |
1084 { | 1179 { |
1086 | 1181 |
1087 std::auto_ptr<DicomIntegerPixelAccessor> accessor; | 1182 std::auto_ptr<DicomIntegerPixelAccessor> accessor; |
1088 | 1183 |
1089 DicomMap m; | 1184 DicomMap m; |
1090 FromDcmtkBridge::Convert(m, dataset); | 1185 FromDcmtkBridge::Convert(m, dataset); |
1186 | |
1187 std::string privateContent; | |
1091 | 1188 |
1092 DcmElement* e; | 1189 DcmElement* e; |
1093 if (dataset.findAndGetElement(ToDcmtkBridge::Convert(DICOM_TAG_PIXEL_DATA), e).good() && | 1190 if (dataset.findAndGetElement(ToDcmtkBridge::Convert(DICOM_TAG_PIXEL_DATA), e).good() && |
1094 e != NULL) | 1191 e != NULL) |
1095 { | 1192 { |
1097 if (e->getUint8Array(pixData) == EC_Normal) | 1194 if (e->getUint8Array(pixData) == EC_Normal) |
1098 { | 1195 { |
1099 accessor.reset(new DicomIntegerPixelAccessor(m, pixData, e->getLength())); | 1196 accessor.reset(new DicomIntegerPixelAccessor(m, pixData, e->getLength())); |
1100 accessor->SetCurrentFrame(frame); | 1197 accessor->SetCurrentFrame(frame); |
1101 } | 1198 } |
1199 } | |
1200 else if (DecodePsmctRle1(privateContent, dataset)) | |
1201 { | |
1202 LOG(INFO) << "The PMSCT_RLE1 decoding has succeeded"; | |
1203 Uint8* pixData = NULL; | |
1204 if (privateContent.size() > 0) | |
1205 pixData = reinterpret_cast<Uint8*>(&privateContent[0]); | |
1206 accessor.reset(new DicomIntegerPixelAccessor(m, pixData, privateContent.size())); | |
1207 accessor->SetCurrentFrame(frame); | |
1102 } | 1208 } |
1103 | 1209 |
1104 PixelFormat format; | 1210 PixelFormat format; |
1105 switch (mode) | 1211 switch (mode) |
1106 { | 1212 { |
1264 for (DicomMap::Map::const_iterator | 1370 for (DicomMap::Map::const_iterator |
1265 it = m.map_.begin(); it != m.map_.end(); it++) | 1371 it = m.map_.begin(); it != m.map_.end(); it++) |
1266 { | 1372 { |
1267 DicomTag t = it->first; | 1373 DicomTag t = it->first; |
1268 std::string s = it->second->AsString(); | 1374 std::string s = it->second->AsString(); |
1269 printf("0x%04x 0x%04x (%s) [%s]\n", t.GetGroup(), t.GetElement(), GetName(t).c_str(), s.c_str()); | 1375 fprintf(fp, "0x%04x 0x%04x (%s) [%s]\n", t.GetGroup(), t.GetElement(), GetName(t).c_str(), s.c_str()); |
1270 } | 1376 } |
1271 } | 1377 } |
1272 | 1378 |
1273 | 1379 |
1274 void FromDcmtkBridge::ToJson(Json::Value& result, | 1380 void FromDcmtkBridge::ToJson(Json::Value& result, |