comparison Core/DicomFormat/DicomIntegerPixelAccessor.cpp @ 78:10bf2cd24d1d

move
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 20 Sep 2012 13:41:55 +0200
parents OrthancServer/DicomIntegerPixelAccessor.cpp@b8dfde8d64e8
children 297bad4e1019
comparison
equal deleted inserted replaced
77:b8dfde8d64e8 78:10bf2cd24d1d
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012 Medical Physics Department, CHU of Liege,
4 * Belgium
5 *
6 * This program is free software: you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 **/
19
20
21 #include "DicomIntegerPixelAccessor.h"
22
23 #ifndef NOMINMAX
24 #define NOMINMAX
25 #endif
26
27 #include "../Core/OrthancException.h"
28 #include <boost/lexical_cast.hpp>
29 #include <limits>
30
31 namespace Orthanc
32 {
33 static const DicomTag COLUMNS(0x0028, 0x0011);
34 static const DicomTag ROWS(0x0028, 0x0010);
35 static const DicomTag SAMPLES_PER_PIXEL(0x0028, 0x0002);
36 static const DicomTag BITS_ALLOCATED(0x0028, 0x0100);
37 static const DicomTag BITS_STORED(0x0028, 0x0101);
38 static const DicomTag HIGH_BIT(0x0028, 0x0102);
39 static const DicomTag PIXEL_REPRESENTATION(0x0028, 0x0103);
40
41 DicomIntegerPixelAccessor::DicomIntegerPixelAccessor(const DicomMap& values,
42 const void* pixelData,
43 size_t size) :
44 pixelData_(pixelData),
45 size_(size)
46 {
47 unsigned int bitsAllocated;
48 unsigned int bitsStored;
49 unsigned int highBit;
50 unsigned int pixelRepresentation;
51
52 try
53 {
54 width_ = boost::lexical_cast<unsigned int>(values.GetValue(COLUMNS).AsString());
55 height_ = boost::lexical_cast<unsigned int>(values.GetValue(ROWS).AsString());
56 samplesPerPixel_ = boost::lexical_cast<unsigned int>(values.GetValue(SAMPLES_PER_PIXEL).AsString());
57 bitsAllocated = boost::lexical_cast<unsigned int>(values.GetValue(BITS_ALLOCATED).AsString());
58 bitsStored = boost::lexical_cast<unsigned int>(values.GetValue(BITS_STORED).AsString());
59 highBit = boost::lexical_cast<unsigned int>(values.GetValue(HIGH_BIT).AsString());
60 pixelRepresentation = boost::lexical_cast<unsigned int>(values.GetValue(PIXEL_REPRESENTATION).AsString());
61 }
62 catch (boost::bad_lexical_cast)
63 {
64 throw OrthancException(ErrorCode_NotImplemented);
65 }
66
67 frame_ = 0;
68 try
69 {
70 numberOfFrames_ = boost::lexical_cast<unsigned int>(values.GetValue(DicomTag::NUMBER_OF_FRAMES).AsString());
71 }
72 catch (OrthancException)
73 {
74 // If the tag "NumberOfFrames" is absent, assume there is a single frame
75 numberOfFrames_ = 1;
76 }
77 catch (boost::bad_lexical_cast)
78 {
79 throw OrthancException(ErrorCode_NotImplemented);
80 }
81
82 if ((bitsAllocated != 8 && bitsAllocated != 16 &&
83 bitsAllocated != 24 && bitsAllocated != 32) ||
84 numberOfFrames_ == 0)
85 {
86 throw OrthancException(ErrorCode_NotImplemented);
87 }
88
89 if (bitsAllocated > 32 ||
90 bitsStored >= 32)
91 {
92 // Not available, as the accessor internally uses int32_t values
93 throw OrthancException(ErrorCode_NotImplemented);
94 }
95
96 if (samplesPerPixel_ != 1)
97 {
98 throw OrthancException(ErrorCode_NotImplemented);
99 }
100
101 if (width_ * height_ * bitsAllocated / 8 * numberOfFrames_ != size)
102 {
103 throw OrthancException(ErrorCode_NotImplemented);
104 }
105
106 /*printf("%d %d %d %d %d %d %d %d\n", width_, height_, samplesPerPixel_, bitsAllocated,
107 bitsStored, highBit, pixelRepresentation, numberOfFrames_);*/
108
109 bytesPerPixel_ = bitsAllocated / 8;
110 shift_ = highBit + 1 - bitsStored;
111
112 if (pixelRepresentation)
113 {
114 mask_ = (1 << (bitsStored - 1)) - 1;
115 signMask_ = (1 << (bitsStored - 1));
116 }
117 else
118 {
119 mask_ = (1 << bitsStored) - 1;
120 signMask_ = 0;
121 }
122
123 rowOffset_ = width_ * bytesPerPixel_;
124 frameOffset_ = height_ * width_ * bytesPerPixel_;
125 }
126
127
128 void DicomIntegerPixelAccessor::GetExtremeValues(int32_t& min,
129 int32_t& max) const
130 {
131 if (height_ == 0 || width_ == 0)
132 {
133 min = max = 0;
134 return;
135 }
136
137 min = std::numeric_limits<int32_t>::max();
138 max = std::numeric_limits<int32_t>::min();
139
140 for (unsigned int y = 0; y < height_; y++)
141 {
142 for (unsigned int x = 0; x < width_; x++)
143 {
144 int32_t v = GetValue(x, y);
145 if (v < min)
146 min = v;
147 if (v > max)
148 max = v;
149 }
150 }
151 }
152
153
154 int32_t DicomIntegerPixelAccessor::GetValue(unsigned int x, unsigned int y) const
155 {
156 assert(x < width_ && y < height_);
157
158 const uint8_t* pixel = reinterpret_cast<const uint8_t*>(pixelData_) +
159 y * rowOffset_ + x * bytesPerPixel_ + frame_ * frameOffset_;
160
161 int32_t v;
162 v = pixel[0];
163 if (bytesPerPixel_ >= 2)
164 v = v + (static_cast<int32_t>(pixel[1]) << 8);
165 if (bytesPerPixel_ >= 3)
166 v = v + (static_cast<int32_t>(pixel[2]) << 16);
167 if (bytesPerPixel_ >= 4)
168 v = v + (static_cast<int32_t>(pixel[3]) << 24);
169
170 v = (v >> shift_) & mask_;
171
172 if (v & signMask_)
173 {
174 // Signed value: Not implemented yet
175 //throw OrthancException(ErrorCode_NotImplemented);
176 v = 0;
177 }
178
179 return v;
180 }
181
182
183 void DicomIntegerPixelAccessor::SetCurrentFrame(unsigned int frame)
184 {
185 if (frame >= numberOfFrames_)
186 {
187 throw OrthancException(ErrorCode_ParameterOutOfRange);
188 }
189
190 frame_ = frame;
191 }
192
193 }