]> Creatis software - gdcm.git/blob - gdcmRLEFrame.cxx
1fa42311aed0b7303deac16744828e7fbe864842
[gdcm.git] / gdcmRLEFrame.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmRLEFrame.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/11/28 15:20:34 $
7   Version:   $Revision: 1.10 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18                                                                                 
19 #include "gdcmRLEFrame.h"
20 #include "gdcmDebug.h"
21                                                                                 
22 namespace gdcm
23 {
24 //-------------------------------------------------------------------------
25 // Constructor / Destructor
26
27 //-----------------------------------------------------------------------------
28 // Public
29 void RLEFrame::SetOffset(unsigned int id,long offset)
30 {
31    gdcmStaticAssertMacro(id<15);
32    Offset[id] = offset;
33 }
34
35 long RLEFrame::GetOffset(unsigned int id)
36 {
37    gdcmStaticAssertMacro(id<15);
38    return Offset[id];
39 }
40
41 void RLEFrame::SetLength(unsigned int id,long length)
42 {
43    gdcmStaticAssertMacro(id<15);
44    Length[id] = length;
45 }
46
47 long RLEFrame::GetLength(unsigned int id)
48 {
49    gdcmStaticAssertMacro(id<15);
50    return Length[id];
51 }
52
53 uint8_t *RLEFrame::ReadAndDecompressRLEFrame( uint8_t *subRaw,
54                                           long rawSegmentSize,
55                                           std::ifstream *fp )
56 {
57    // Loop on the fragments
58    for( unsigned int k = 1; k <= NumberOfFragments; k++ )
59    {
60       // First thing need to reset file to proper position:
61       fp->seekg(Offset[k], std::ios::beg);
62       ReadAndDecompressRLEFragment(subRaw, Length[k],
63                                    rawSegmentSize, fp);
64       subRaw += rawSegmentSize;
65    }
66
67    return subRaw;
68 }
69
70 /**
71  * \brief Implementation of the RLE decoding algorithm for decompressing
72  *        a RLE fragment. [refer to PS 3.5-2003, section G.3.2 p 86]
73  * @param subRaw Sub region where the decoded fragment should be placed.
74  * @param fragmentSize The length of the binary fragment as found on the disk.
75  * @param rawSegmentSize The expected length of the fragment ONCE Raw.
76  * @param fp File Pointer: on entry the position should be the one of
77  *        the fragment to be decoded.
78  */
79 bool RLEFrame::ReadAndDecompressRLEFragment( uint8_t *subRaw,
80                                              long fragmentSize,
81                                              long rawSegmentSize,
82                                              std::ifstream *fp )
83 {
84    int8_t count;
85    long numberOfOutputBytes = 0;
86    long numberOfReadBytes = 0;
87
88    while( numberOfOutputBytes < rawSegmentSize )
89    {
90       fp->read( (char*)&count, 1 );
91       numberOfReadBytes += 1;
92       if ( count >= 0 )
93       // Note: count <= 127 comparison is always true due to limited range
94       //       of data type int8_t [since the maximum of an exact width
95       //       signed integer of width N is 2^(N-1) - 1, which for int8_t
96       //       is 127].
97       {
98          fp->read( (char*)subRaw, count + 1);
99          numberOfReadBytes   += count + 1;
100          subRaw     += count + 1;
101          numberOfOutputBytes += count + 1;
102       }
103       else
104       {
105          if ( count <= -1 && count >= -127 )
106          {
107             int8_t newByte;
108             fp->read( (char*)&newByte, 1);
109             numberOfReadBytes += 1;
110             for( int i = 0; i < -count + 1; i++ )
111             {
112                subRaw[i] = newByte;
113             }
114             subRaw     += -count + 1;
115             numberOfOutputBytes += -count + 1;
116          }
117       }
118       // if count = 128 output nothing
119                                                                                 
120       if ( numberOfReadBytes > fragmentSize )
121       {
122          gdcmStaticWarningMacro( "Read more bytes (" << numberOfReadBytes
123                               << " ) than the segment size. (" 
124                               << fragmentSize << ")" );
125          return false;
126       }
127    }
128    return true;
129 }
130
131 //-----------------------------------------------------------------------------
132 // Protected
133
134 //-----------------------------------------------------------------------------
135 // Private
136
137 //-----------------------------------------------------------------------------
138 // Print
139 /**
140  * \brief        Print self.
141  * @param indent Indentation string to be prepended during printing.
142  * @param os     Stream to print to.
143  */
144 void RLEFrame::Print( std::ostream &os, std::string indent )
145 {
146    os << indent
147       << "--- fragments"
148       << std::endl;
149    for ( unsigned int i = 0; i < NumberOfFragments; i++ )
150    {
151       os << indent
152          << "   offset : " <<  Offset[i]
153          << "   length : " <<  Length[i]
154          << std::endl;
155    }
156 }
157
158 //-----------------------------------------------------------------------------
159 } // end namespace gdcm
160