Mercurial > hg > orthanc
comparison OrthancFramework/Sources/Images/PamWriter.cpp @ 4044:d25f4c0fa160 framework
splitting code into OrthancFramework and OrthancServer
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 10 Jun 2020 20:30:34 +0200 |
parents | Core/Images/PamWriter.cpp@94f4a18a79cc |
children | bf7b9edf6b81 |
comparison
equal
deleted
inserted
replaced
4043:6c6239aec462 | 4044:d25f4c0fa160 |
---|---|
1 /** | |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium | |
6 * | |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU General Public License as | |
9 * published by the Free Software Foundation, either version 3 of the | |
10 * License, or (at your option) any later version. | |
11 * | |
12 * In addition, as a special exception, the copyright holders of this | |
13 * program give permission to link the code of its release with the | |
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
15 * that use the same license as the "OpenSSL" library), and distribute | |
16 * the linked executables. You must obey the GNU General Public License | |
17 * in all respects for all of the code used other than "OpenSSL". If you | |
18 * modify file(s) with this exception, you may extend this exception to | |
19 * your version of the file(s), but you are not obligated to do so. If | |
20 * you do not wish to do so, delete this exception statement from your | |
21 * version. If you delete this exception statement from all source files | |
22 * in the program, then also delete it here. | |
23 * | |
24 * This program is distributed in the hope that it will be useful, but | |
25 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
27 * General Public License for more details. | |
28 * | |
29 * You should have received a copy of the GNU General Public License | |
30 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
31 **/ | |
32 | |
33 | |
34 #include "../PrecompiledHeaders.h" | |
35 #include "PamWriter.h" | |
36 | |
37 #include "../Endianness.h" | |
38 #include "../OrthancException.h" | |
39 #include "../Toolbox.h" | |
40 | |
41 #include <boost/lexical_cast.hpp> | |
42 | |
43 | |
44 namespace Orthanc | |
45 { | |
46 static void GetPixelFormatInfo(const PixelFormat& format, | |
47 unsigned int& maxValue, | |
48 unsigned int& channelCount, | |
49 unsigned int& bytesPerChannel, | |
50 std::string& tupleType) | |
51 { | |
52 switch (format) | |
53 { | |
54 case PixelFormat_Grayscale8: | |
55 maxValue = 255; | |
56 channelCount = 1; | |
57 bytesPerChannel = 1; | |
58 tupleType = "GRAYSCALE"; | |
59 break; | |
60 | |
61 case PixelFormat_SignedGrayscale16: | |
62 case PixelFormat_Grayscale16: | |
63 maxValue = 65535; | |
64 channelCount = 1; | |
65 bytesPerChannel = 2; | |
66 tupleType = "GRAYSCALE"; | |
67 break; | |
68 | |
69 case PixelFormat_RGB24: | |
70 maxValue = 255; | |
71 channelCount = 3; | |
72 bytesPerChannel = 1; | |
73 tupleType = "RGB"; | |
74 break; | |
75 | |
76 case PixelFormat_RGB48: | |
77 maxValue = 255; | |
78 channelCount = 3; | |
79 bytesPerChannel = 2; | |
80 tupleType = "RGB"; | |
81 break; | |
82 | |
83 default: | |
84 throw OrthancException(ErrorCode_NotImplemented); | |
85 } | |
86 } | |
87 | |
88 | |
89 void PamWriter::WriteToMemoryInternal(std::string& target, | |
90 unsigned int width, | |
91 unsigned int height, | |
92 unsigned int sourcePitch, | |
93 PixelFormat format, | |
94 const void* buffer) | |
95 { | |
96 unsigned int maxValue, channelCount, bytesPerChannel; | |
97 std::string tupleType; | |
98 GetPixelFormatInfo(format, maxValue, channelCount, bytesPerChannel, tupleType); | |
99 | |
100 target = (std::string("P7") + | |
101 std::string("\nWIDTH ") + boost::lexical_cast<std::string>(width) + | |
102 std::string("\nHEIGHT ") + boost::lexical_cast<std::string>(height) + | |
103 std::string("\nDEPTH ") + boost::lexical_cast<std::string>(channelCount) + | |
104 std::string("\nMAXVAL ") + boost::lexical_cast<std::string>(maxValue) + | |
105 std::string("\nTUPLTYPE ") + tupleType + | |
106 std::string("\nENDHDR\n")); | |
107 | |
108 if (bytesPerChannel != 1 && | |
109 bytesPerChannel != 2) | |
110 { | |
111 throw OrthancException(ErrorCode_NotImplemented); | |
112 } | |
113 | |
114 size_t targetPitch = channelCount * bytesPerChannel * width; | |
115 size_t offset = target.size(); | |
116 | |
117 target.resize(offset + targetPitch * height); | |
118 | |
119 assert(target.size() != 0); | |
120 | |
121 if (Toolbox::DetectEndianness() == Endianness_Little && | |
122 bytesPerChannel == 2) | |
123 { | |
124 // Byte swapping | |
125 for (unsigned int h = 0; h < height; ++h) | |
126 { | |
127 const uint16_t* p = reinterpret_cast<const uint16_t*> | |
128 (reinterpret_cast<const uint8_t*>(buffer) + h * sourcePitch); | |
129 uint16_t* q = reinterpret_cast<uint16_t*> | |
130 (reinterpret_cast<uint8_t*>(&target[offset]) + h * targetPitch); | |
131 | |
132 for (unsigned int w = 0; w < width * channelCount; ++w) | |
133 { | |
134 // memcpy() is necessary to avoid segmentation fault if the | |
135 // "pixel" pointer is not 16-bit aligned (which is the case | |
136 // if "offset" is an odd number). Check out issue #99: | |
137 // https://bitbucket.org/sjodogne/orthanc/issues/99 | |
138 uint16_t v = htobe16(*p); | |
139 memcpy(q, &v, sizeof(uint16_t)); | |
140 | |
141 p++; | |
142 q++; | |
143 } | |
144 } | |
145 } | |
146 else | |
147 { | |
148 // Either "bytesPerChannel == 1" (and endianness is not | |
149 // relevant), or we run on a big endian architecture (and no | |
150 // byte swapping is necessary, as PAM uses big endian) | |
151 | |
152 for (unsigned int h = 0; h < height; ++h) | |
153 { | |
154 const void* p = reinterpret_cast<const uint8_t*>(buffer) + h * sourcePitch; | |
155 void* q = reinterpret_cast<uint8_t*>(&target[offset]) + h * targetPitch; | |
156 memcpy(q, p, targetPitch); | |
157 } | |
158 } | |
159 } | |
160 } |