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,