r7061: initial property settings
[ctsim.git] / libctsim / ctndicom.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **      Name:           ctndicomp.cpp
5 **  Purpose:      Interface to CTN Dicom classes
6 **      Programmer:   Kevin Rosenberg
7 **      Date Started: March 2001
8 **
9 **  This is part of the CTSim program
10 **  Copyright (c) 1983-2001 Kevin Rosenberg
11 **
12 **  $Id$
13 **
14 **  This program is free software; you can redistribute it and/or modify
15 **  it under the terms of the GNU General Public License (version 2) as
16 **  published by the Free Software Foundation.
17 **
18 **  This program is distributed in the hope that it will be useful,
19 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 **  GNU General Public License for more details.
22 **
23 **  You should have received a copy of the GNU General Public License
24 **  along with this program; if not, write to the Free Software
25 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 ******************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #ifdef HAVE_CTN_DICOM
33
34 #include "ctndicom.h" 
35 #include "imagefile.h"
36 #include "projections.h"
37
38
39 DicomImporter::DicomImporter (const char* const pszFile)
40   : m_strFilename(pszFile), m_bFail(false), m_iContents(DICOM_CONTENTS_INVALID), 
41     m_pImageFile(NULL), m_pProjections(NULL), m_pFile(NULL)
42 {
43   unsigned long lOptions = DCM_ORDERLITTLEENDIAN | DCM_FORMATCONVERSION;
44   DCM_Debug (FALSE);
45
46   CONDITION cond = DCM_OpenFile (pszFile, lOptions, &m_pFile);
47   if (cond != DCM_NORMAL) {
48     m_bFail = true;
49     char textbuf [2048]; 
50     CONDITION cond2 = COND_TopCondition (&cond, textbuf, sizeof(textbuf));
51     cond2 = DCM_NORMAL; // testing
52     if (cond2 != DCM_NORMAL) {
53       m_strFailMessage = "DCM_OpenFile failure: ";
54       m_strFailMessage += m_strFilename;
55     } else
56       m_strFailMessage = textbuf;
57
58     return;
59   }
60
61   unsigned short iNRows, iNCols, iBitsAllocated, iBitsStored, iHighBit, iPixRep;
62   DCM_ELEMENT aElemRequired[] = {
63     {DCM_IMGROWS, DCM_US, "", 1, sizeof(iNRows), 
64      {reinterpret_cast<char*>(&iNRows)}},
65     {DCM_IMGCOLUMNS, DCM_US, "", 1, sizeof(iNCols), 
66      {reinterpret_cast<char*>(&iNCols)}},
67     {DCM_IMGBITSALLOCATED, DCM_US, "", 1, sizeof(iBitsAllocated), 
68      {reinterpret_cast<char*>(&iBitsAllocated)}},
69     {DCM_IMGBITSSTORED, DCM_US, "", 1, sizeof(iBitsStored), 
70      {reinterpret_cast<char*>(&iBitsStored)}},
71     {DCM_IMGHIGHBIT, DCM_US, "", 1, sizeof(iHighBit), 
72      {reinterpret_cast<char*>(&iHighBit)}},
73     {DCM_IMGPIXELREPRESENTATION, DCM_US, "", 1, sizeof(iPixRep), 
74      {reinterpret_cast<char*>(&iPixRep)}},
75   };
76   int nElemRequired = sizeof (aElemRequired) / sizeof(DCM_ELEMENT);
77
78   if (DCM_ParseObject (&m_pFile, aElemRequired, nElemRequired, NULL, 0, NULL) == DCM_NORMAL) {
79     loadImage (iNRows, iNCols, iBitsAllocated, iBitsStored, iHighBit, iPixRep);
80     return;
81   }
82   U32 lRtnLength;
83   DCM_TAG somatomTag = DCM_MAKETAG(TAG_GROUP_SOMATOM, TAG_MEMBER_SOMATOM_DATA);
84   if (DCM_GetElementSize (&m_pFile, somatomTag, &lRtnLength) == DCM_NORMAL)
85     loadProjections();
86 }
87
88 void
89 DicomImporter::loadImage(unsigned short iNRows, unsigned short iNCols, unsigned short iBitsAllocated, 
90                          unsigned short iBitsStored, unsigned short iHighBit, unsigned short iPixRep)
91 {
92   U32 lRtnLength;
93   unsigned short iSamplesPerPixel, iPlanarConfig;
94   
95   DCM_ELEMENT elemPlanarConfig = 
96     {DCM_IMGPLANARCONFIGURATION, DCM_US, "", 1, sizeof(iPlanarConfig), 
97      {reinterpret_cast<char*>(&iPlanarConfig)}};
98   DCM_ELEMENT elemSamplesPerPixel = 
99     {DCM_IMGSAMPLESPERPIXEL, DCM_US, "", 1, 
100      sizeof(iSamplesPerPixel), {reinterpret_cast<char*>(&iSamplesPerPixel)}};
101
102   if (DCM_ParseObject (&m_pFile, &elemSamplesPerPixel, 1, NULL, 0, NULL) != DCM_NORMAL)
103     iSamplesPerPixel = 1;  // default value
104
105   if (iSamplesPerPixel > 1) {
106     void* ctx = NULL;
107     if (DCM_GetElementValue (&m_pFile, &elemPlanarConfig, &lRtnLength, &ctx) != DCM_NORMAL) {
108       m_bFail = true;
109       m_strFailMessage = "Planar Configuration not specified when iSamplesPerPixel > 1";
110     }
111   }
112
113   char szRescaleSlope[17];
114   char szRescaleIntercept[17];
115   double dRescaleSlope = 1;
116   double dRescaleIntercept = 0;
117   DCM_ELEMENT elemRescaleSlope = 
118     {DCM_IMGRESCALESLOPE, DCM_DS, "", 1, strlen(szRescaleSlope), 
119      {szRescaleSlope}};
120   DCM_ELEMENT elemRescaleIntercept = 
121     {DCM_IMGRESCALEINTERCEPT, DCM_DS, "", 1, strlen(szRescaleIntercept), 
122      {szRescaleIntercept}};
123   if (DCM_ParseObject (&m_pFile, &elemRescaleSlope, 1, NULL, 0, NULL) == DCM_NORMAL) {
124     if (sscanf (szRescaleSlope, "%lf", &dRescaleSlope) != 1)
125       sys_error (ERR_SEVERE, "Error parsing rescale slope");
126   }
127   if (DCM_ParseObject (&m_pFile, &elemRescaleIntercept, 1, NULL, 0, NULL) == DCM_NORMAL) {
128     if (sscanf (szRescaleIntercept, "%lf", &dRescaleIntercept) != 1)
129       sys_error (ERR_SEVERE, "Error parsing rescale intercept");
130   }
131
132   DCM_ELEMENT elemPixelData = {DCM_PXLPIXELDATA, DCM_OT, "", 1, 0, {NULL}};
133   // Get the actual  pixel data (the only other required element)
134   if (DCM_GetElementSize (&m_pFile, elemPixelData.tag, &lRtnLength) != DCM_NORMAL) {
135     m_bFail = true;
136     m_strFailMessage = "Can't get pixel data size";
137     return;
138   }
139
140   // Check the size of the pixel data to make sure we have the correct amount...
141   unsigned long lRealLength = lRtnLength;
142   unsigned long lCheckLengthInBytes = iNRows * iNCols * iSamplesPerPixel;
143   if (iBitsAllocated == 16)
144     lCheckLengthInBytes *= 2;
145   if (lCheckLengthInBytes > lRealLength) {
146     m_bFail = true;
147     m_strFailMessage = "Too little pixel data supplied";
148     return;
149   }
150   // Now allocate the memory to hold the pixel data and get it from the DICOM file...
151
152   unsigned char* pRawPixels = new unsigned char [lCheckLengthInBytes];
153   elemPixelData.length = lCheckLengthInBytes;
154   elemPixelData.d.ot = pRawPixels;
155   
156   void* ctx = NULL;
157   CONDITION cond = DCM_GetElementValue (&m_pFile, &elemPixelData, &lRtnLength, &ctx);
158   if ((cond != DCM_NORMAL) && (cond != DCM_GETINCOMPLETE)) {
159     m_bFail = true;
160     m_strFailMessage = "Can't read pixel data";
161     delete pRawPixels;
162     return;
163   }
164   if ((lCheckLengthInBytes < lRealLength) && (cond != DCM_GETINCOMPLETE)) {
165     m_bFail = true;
166     m_strFailMessage = "Should have gooten incomplete message reading pixel data";
167     delete pRawPixels;
168     return;
169   }
170
171   m_pImageFile = new ImageFile (iNCols, iNRows);
172   ImageFileArray v = m_pImageFile->getArray();
173   double dScale = 1 << iBitsStored;
174   unsigned int iMaskLength = iBitsStored;
175   if (iMaskLength > 8)
176     iMaskLength -= 8;
177   unsigned int iMask = (1 << iMaskLength) - 1;
178   for (int iy = 0; iy < iNRows; iy++) {
179     for (int ix = 0; ix < iNCols; ix++) {
180       if (iBitsAllocated == 8)  {
181         unsigned char cV = pRawPixels[iy * iNRows + ix];
182         v[ix][iy] = (cV & iMask) / dScale;
183       } else if (iBitsAllocated == 16) {
184         unsigned long lBase = (iy * iNRows + ix) * 2;
185         unsigned char cV1 = pRawPixels[lBase];
186         unsigned char cV2 = pRawPixels[lBase+1] & iMask;
187         int iV = cV1 + (cV2 << 8);
188         v[ix][iNRows - 1 - iy] = iV * dRescaleSlope + dRescaleIntercept;
189       }
190     }
191   }
192   m_iContents = DICOM_CONTENTS_IMAGE;
193 }
194
195 void
196 DicomImporter::loadProjections()
197 {
198   U32 lRtnLength;
199   void* ctx = NULL;
200
201   unsigned short iNViews, iNDets;
202   DCM_ELEMENT aElemRequired[] = {
203     {DCM_IMGROWS, DCM_US, "", 1, sizeof(iNViews), 
204      {reinterpret_cast<char*>(&iNViews)}},
205     {DCM_IMGCOLUMNS, DCM_US, "", 1, sizeof(iNDets), 
206      {reinterpret_cast<char*>(&iNDets)}},
207   };
208   int nElemRequired = sizeof (aElemRequired) / sizeof(DCM_ELEMENT);
209
210   if (DCM_ParseObject (&m_pFile, aElemRequired, nElemRequired, NULL, 0, NULL) != DCM_NORMAL) {
211     m_bFail = true;
212     m_strFailMessage = "Unable to read header for projections";
213     return;
214   }
215
216   DCM_TAG somatomTag = DCM_MAKETAG(TAG_GROUP_SOMATOM, TAG_MEMBER_SOMATOM_DATA);
217   DCM_ELEMENT elemProjections = {somatomTag, DCM_UN, "", 1, 0, {NULL}};
218   if (DCM_GetElementSize (&m_pFile, elemProjections.tag, &lRtnLength) != DCM_NORMAL) {
219     m_bFail = true;
220     m_strFailMessage = "Can't find projection data";
221     return;
222   }
223
224   unsigned char* pRawProjections = new unsigned char [lRtnLength];
225   elemProjections.length = lRtnLength;
226   elemProjections.d.ot = pRawProjections;
227   
228   ctx = NULL;
229   CONDITION cond = DCM_GetElementValue (&m_pFile, &elemProjections, &lRtnLength, &ctx);
230   if ((cond != DCM_NORMAL) && (cond != DCM_GETINCOMPLETE)) {
231     m_bFail = true;
232     m_strFailMessage = "Can't read projections data";
233     delete pRawProjections;
234     return;
235   }
236   m_iContents = DICOM_CONTENTS_PROJECTIONS;
237   m_pProjections = new Projections;
238   if (! m_pProjections->initFromSomatomAR_STAR (iNViews, iNDets, pRawProjections, lRtnLength)) {
239     m_bFail = true;
240     m_strFailMessage = "Error converting raw projection data";
241     delete m_pProjections;
242     m_pProjections = NULL;
243   }
244
245   delete pRawProjections;
246 }
247
248
249 DicomImporter::~DicomImporter()
250 {
251   if (m_pFile)
252     DCM_CloseObject (&m_pFile);
253 }
254
255
256 DicomExporter::DicomExporter (ImageFile* pImageFile)
257 : m_pImageFile(pImageFile), m_pObject(NULL)
258 {
259   DCM_Debug (FALSE);
260   if (! pImageFile) {
261     m_bFail = true;
262     m_strFailMessage = "Initialized DicomExported with NULL imagefile";
263     return;
264   }
265   m_bFail = ! createDicomObject();
266 }
267
268 DicomExporter::~DicomExporter ()
269 {
270   if (m_pObject)
271     DCM_CloseObject (&m_pObject);
272 }
273
274 bool
275 DicomExporter::writeFile (const char* const pszFilename)
276 {
277   if (! m_pObject)
278     return false;
279
280   m_strFilename = pszFilename;
281
282   CONDITION cond = DCM_WriteFile (&m_pObject, DCM_ORDERLITTLEENDIAN, pszFilename);
283   if (cond != DCM_NORMAL) {
284     m_bFail = true;
285     m_strFailMessage = "Error writing DICOM file ";
286     m_strFailMessage += pszFilename;
287     return false;
288   }
289
290   return true;
291 }
292
293 bool
294 DicomExporter::createDicomObject()
295 {
296   CONDITION cond = DCM_CreateObject (&m_pObject, 0);
297   if (cond != DCM_NORMAL) {
298     m_bFail = true;
299     m_strFailMessage = "Error creating DICOM object";
300     return false;
301   }
302
303   double dMin, dMax;
304   m_pImageFile->getMinMax (dMin, dMax);
305   double dWidth = dMax - dMin;
306   if (dWidth == 0.)
307     dWidth = 1E-7;
308   double dScale = 65535. / dWidth;
309
310   double dRescaleIntercept = dMin;
311   double dRescaleSlope = 1 / dScale;
312   char szRescaleIntercept[17];
313   char szRescaleSlope[17];
314   snprintf (szRescaleIntercept, sizeof(szRescaleIntercept), "%e", dRescaleIntercept);
315   snprintf (szRescaleSlope, sizeof(szRescaleIntercept), "%e", dRescaleSlope);
316
317   char szCTSimRoot[] = "1.2.826.0.1.3680043.2.284.";
318   char szModality[] = "CT";
319   char szSOPClassUID[65] = "1.2.840.10008.5.4.1.1.2";
320   char szImgPhotometricInterp[] = "MONOCHROME2";
321   char szPixelSpacing[33] = "0\\0";
322   char szRelImageOrientationPatient[100] = "1\\0\\0\\0\\1\\0";
323   char szRelImagePositionPatient[49] = "0\\0\\0";
324   char szAcqKvp[] = "0";
325   char szRelAcquisitionNumber[] = "1";
326   char szRelImageNumber[] = "1";
327   char szIDSOPInstanceUID[65] = "";
328   char szIDManufacturer[] = "CTSim";
329   char szRelPositionRefIndicator[] = "0";
330   char szRelFrameOfReferenceUID[65] = "";
331   char szRelSeriesNumber[] = "1";
332   char szIDAccessionNumber[] = "0";
333   char szRelStudyID[] = "1";
334   char szIDReferringPhysician[] = "NONE";
335   char szIDStudyTime[] = "000000.0";
336   char szIDStudyDate[] = "00000000";
337   char szRelStudyInstanceUID[65] = "";
338   char szPatSex[] = "O";
339   char szPatBirthdate[] = "0000000";
340   char szPatID[] = "NONE";
341   char szPatName[] = "NONE";
342   char szIDImageType[] = "ORIGINAL";
343   char szIDManufacturerModel[65] = "";
344
345   std::ostringstream osPatComments;
346   m_pImageFile->printLabelsBrief (osPatComments);
347   size_t sizePatComments = osPatComments.str().length();
348   char* pszPatComments = new char [sizePatComments+1];
349   strncpy (pszPatComments, osPatComments.str().c_str(), sizePatComments);
350
351   snprintf (szIDSOPInstanceUID, sizeof(szIDSOPInstanceUID), "%s.2.1.6.1", szCTSimRoot);
352   snprintf (szRelStudyInstanceUID, sizeof(szRelStudyInstanceUID), "%s.2.1.6.1.1", szCTSimRoot);
353   snprintf (szRelFrameOfReferenceUID, sizeof(szRelFrameOfReferenceUID), "%s.99", szCTSimRoot);
354 #ifdef VERSION
355   snprintf (szIDManufacturerModel, sizeof(szIDManufacturerModel), "VERSION %s", VERSION);
356 #endif
357   snprintf (szPixelSpacing, sizeof(szPixelSpacing), "%e\\%e", m_pImageFile->axisIncrementX(), m_pImageFile->axisIncrementY());
358   double minX, maxX, minY, maxY;
359   if (m_pImageFile->getAxisExtent(minX, maxX, minY, maxY)) {
360     minX += m_pImageFile->axisIncrementX() / 2;
361     minY += m_pImageFile->axisIncrementY() / 2;
362     snprintf(szRelImagePositionPatient, sizeof(szRelImagePositionPatient), "%e\\%e\\0", minX, minY);
363   }
364
365   unsigned short iNRows = m_pImageFile->ny();
366   unsigned short iNCols = m_pImageFile->nx();
367   unsigned short iBitsAllocated = 16;
368   unsigned short iBitsStored = 16;
369   unsigned short iHighBit = 15;
370   unsigned short iPixRep = 0;
371   unsigned short iSamplesPerPixel = 1;
372   DCM_ELEMENT aElemRequired[] = {
373     {DCM_IMGROWS, DCM_US, "", 1, sizeof(iNRows), 
374      {reinterpret_cast<char*>(&iNRows)}},
375     {DCM_IMGCOLUMNS, DCM_US, "", 1, sizeof(iNCols), 
376      {reinterpret_cast<char*>(&iNCols)}},
377     {DCM_IMGBITSALLOCATED, DCM_US, "", 1, sizeof(iBitsAllocated), 
378      {reinterpret_cast<char*>(&iBitsAllocated)}},
379     {DCM_IMGBITSSTORED, DCM_US, "", 1, sizeof(iBitsStored), 
380      {reinterpret_cast<char*>(&iBitsStored)}},
381     {DCM_IMGHIGHBIT, DCM_US, "", 1, sizeof(iHighBit), 
382      {reinterpret_cast<char*>(&iHighBit)}},
383     {DCM_IMGPIXELREPRESENTATION, DCM_US, "", 1, sizeof(iPixRep), 
384      {reinterpret_cast<char*>(&iPixRep)}},
385     {DCM_IMGSAMPLESPERPIXEL, DCM_US, "", 1, sizeof(iSamplesPerPixel), 
386      {reinterpret_cast<char*>(&iSamplesPerPixel)}},
387     {DCM_IMGRESCALESLOPE, DCM_DS, "", 1, strlen(szRescaleSlope), 
388      {szRescaleSlope}},
389     {DCM_IMGRESCALEINTERCEPT, DCM_DS, "", 1, strlen(szRescaleIntercept), 
390      {szRescaleIntercept}},
391     {DCM_IMGPHOTOMETRICINTERP, DCM_CS, "", 1, strlen(szImgPhotometricInterp), 
392      {szImgPhotometricInterp}},
393     {DCM_IMGPIXELSPACING, DCM_DS, "", 1, strlen(szPixelSpacing), 
394      {szPixelSpacing}},
395     {DCM_RELIMAGEORIENTATIONPATIENT, DCM_DS, "", 1, 
396      strlen(szRelImageOrientationPatient), {szRelImageOrientationPatient}},
397     {DCM_RELIMAGEPOSITIONPATIENT, DCM_DS, "", 1, 
398      strlen(szRelImagePositionPatient), {szRelImagePositionPatient}},
399     {DCM_ACQKVP, DCM_DS, "", 1, strlen(szAcqKvp), {szAcqKvp}},
400     {DCM_RELACQUISITIONNUMBER, DCM_IS, "", 1, strlen(szRelAcquisitionNumber), 
401      {szRelAcquisitionNumber}},
402     {DCM_ACQSLICETHICKNESS, DCM_DS, "", 1, strlen(szRelAcquisitionNumber), 
403      {szRelAcquisitionNumber}},
404     {DCM_RELIMAGENUMBER, DCM_IS, "", 1, strlen(szRelImageNumber), 
405      {szRelImageNumber}},
406     {DCM_IDSOPINSTANCEUID, DCM_UI, "", 1, strlen(szIDSOPInstanceUID), 
407      {szIDSOPInstanceUID}},
408     {DCM_IDMANUFACTURER, DCM_LO, "", 1, strlen(szIDManufacturer), 
409      {szIDManufacturer}},
410     {DCM_RELPOSITIONREFINDICATOR, DCM_LO, "", 1, 
411      strlen(szRelPositionRefIndicator), {szRelPositionRefIndicator}},
412     {DCM_RELFRAMEOFREFERENCEUID, DCM_UI, "", 1, 
413      strlen(szRelFrameOfReferenceUID), {szRelFrameOfReferenceUID}},
414     {DCM_RELSERIESNUMBER, DCM_IS, "", 1, strlen(szRelSeriesNumber), 
415      {szRelSeriesNumber}},
416     {DCM_RELSERIESINSTANCEUID, DCM_UI, "", 1, strlen(szIDAccessionNumber), 
417      {szIDAccessionNumber}},
418     {DCM_IDACCESSIONNUMBER, DCM_SH, "", 1, strlen(szIDAccessionNumber), 
419      {szIDAccessionNumber}},
420     {DCM_RELSTUDYID, DCM_SH, "", 1, strlen(szRelStudyID), {szRelStudyID}},
421     {DCM_IDREFERRINGPHYSICIAN, DCM_PN, "", 1, strlen(szIDReferringPhysician), 
422      {szIDReferringPhysician}},
423     {DCM_IDSTUDYTIME, DCM_TM, "", 1, strlen(szIDStudyTime), {szIDStudyTime}},
424     {DCM_IDSTUDYDATE, DCM_DA, "", 1, strlen(szIDStudyDate), {szIDStudyDate}},
425     {DCM_RELSTUDYINSTANCEUID, DCM_UI, "", 1, strlen(szRelStudyInstanceUID), 
426      {szRelStudyInstanceUID}},
427     {DCM_PATSEX, DCM_CS, "", 1, strlen(szPatSex), {szPatSex}},
428     {DCM_PATBIRTHDATE, DCM_DA, "", 1, strlen(szPatBirthdate), {szPatBirthdate}},
429     {DCM_PATID, DCM_LO, "", 1, strlen(szPatID), {szPatID}},
430     {DCM_PATNAME, DCM_PN, "", 1, strlen(szPatName), {szPatName}},
431     {DCM_IDIMAGETYPE, DCM_CS, "", 1, strlen(szIDImageType), {szIDImageType}},
432     {DCM_IDMODALITY, DCM_CS, "", 1, strlen(szModality), {szModality}},
433     {DCM_IDSOPCLASSUID, DCM_UI, "", 1, strlen(szSOPClassUID), {szSOPClassUID}},
434     {DCM_IDMANUFACTURERMODEL, DCM_LO, "", 1, strlen(szIDManufacturerModel), 
435      {szIDManufacturerModel}},
436     {DCM_PATCOMMENTS, DCM_LT, "", 1, strlen(pszPatComments), {pszPatComments}},
437   };
438   int nElemRequired = sizeof (aElemRequired) / sizeof(DCM_ELEMENT);
439
440   int iUpdateCount;
441   cond = DCM_ModifyElements (&m_pObject, aElemRequired, nElemRequired, NULL, 0, &iUpdateCount);
442
443   DCM_ELEMENT elemPixelData = {DCM_PXLPIXELDATA, DCM_OT, "", 1, 0, {NULL}};
444
445   unsigned long lRealLength = 2 * m_pImageFile->nx() * m_pImageFile->ny();
446
447   unsigned char* pRawPixels = new unsigned char [lRealLength];
448   elemPixelData.length = lRealLength;
449   elemPixelData.d.ot = pRawPixels;
450   
451   ImageFileArray v = m_pImageFile->getArray();
452   for (int iy = 0; iy < iNRows; iy++) {
453     for (int ix = 0; ix < iNCols; ix++) {
454         unsigned long lBase = (iy * iNRows + ix) * 2;
455         unsigned int iValue = nearest<int>(dScale * (v[ix][iNRows - 1 - iy] - dMin));
456         pRawPixels[lBase] = iValue & 0xFF;
457         pRawPixels[lBase+1] = (iValue & 0xFF00) >> 8;
458     }
459   }
460   cond = DCM_ModifyElements (&m_pObject, &elemPixelData, 1, NULL, 0, &iUpdateCount);
461   delete pRawPixels;
462
463   delete pszPatComments;
464
465   if (cond != DCM_NORMAL || iUpdateCount != 1) {
466     m_bFail = true;
467     m_strFailMessage = "Error modifying pixel data";
468     return false;
469   }
470
471   return true;
472 }
473
474 #endif // HAVE_CTN_DICOM
475
476