]> Creatis software - gdcm.git/blob - src/gdcmRLEFrame.cxx
ENH: Yet another pass to get RLE stuff similar to JPEG. I am still unhappy with the...
[gdcm.git] / src / gdcmRLEFrame.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmRLEFrame.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/01/31 06:17:22 $
7   Version:   $Revision: 1.4 $
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 /**
26  * \brief        Print self.
27  * @param indent Indentation string to be prepended during printing.
28  * @param os     Stream to print to.
29  */
30 void RLEFrame::Print( std::ostream &os, std::string indent )
31 {
32    os << indent
33       << "--- fragments"
34       << std::endl;
35    for ( unsigned int i = 0; i < NumberOfFragments; i++ )
36    {
37       os << indent
38          << "   offset : " <<  Offset[i]
39          << "   length : " <<  Length[i]
40          << std::endl;
41    }
42 }
43
44 void RLEFrame::SetOffset(unsigned int id,long offset)
45 {
46    gdcmAssertMacro(id<15);
47    Offset[id] = offset;
48 }
49
50 long RLEFrame::GetOffset(unsigned int id)
51 {
52    gdcmAssertMacro(id<15);
53    return Offset[id];
54 }
55
56 void RLEFrame::SetLength(unsigned int id,long length)
57 {
58    gdcmAssertMacro(id<15);
59    Length[id] = length;
60 }
61
62 long RLEFrame::GetLength(unsigned int id)
63 {
64    gdcmAssertMacro(id<15);
65    return Length[id];
66 }
67
68 uint8_t *RLEFrame::ReadAndDecompressRLEFrame( uint8_t *subRaw,
69                                           long rawSegmentSize,
70                                           std::ifstream *fp )
71 {
72    // Loop on the fragments
73    for( unsigned int k = 1; k <= NumberOfFragments; k++ )
74    {
75       // First thing need to reset file to proper position:
76       fp->seekg(Offset[k], std::ios::beg);
77       ReadAndDecompressRLEFragment(subRaw, Length[k],
78                                    rawSegmentSize, fp);
79       subRaw += rawSegmentSize;
80    }
81
82    return subRaw;
83 }
84
85 /**
86  * \brief Implementation of the RLE decoding algorithm for decompressing
87  *        a RLE fragment. [refer to PS 3.5-2003, section G.3.2 p 86]
88  * @param subRaw Sub region of \ref Raw where the decoded fragment
89  *        should be placed.
90  * @param fragmentSize The length of the binary fragment as found on the disk.
91  * @param RawSegmentSize The expected length of the fragment ONCE
92  *        Raw.
93  * @param fp File Pointer: on entry the position should be the one of
94  *        the fragment to be decoded.
95  */
96 bool RLEFrame::ReadAndDecompressRLEFragment( uint8_t *subRaw,
97                                              long fragmentSize,
98                                              long rawSegmentSize,
99                                              std::ifstream *fp )
100 {
101    int8_t count;
102    long numberOfOutputBytes = 0;
103    long numberOfReadBytes = 0;
104
105
106    while( numberOfOutputBytes < rawSegmentSize )
107    {
108       fp->read( (char*)&count, 1 );
109       numberOfReadBytes += 1;
110       if ( count >= 0 )
111       // Note: count <= 127 comparison is always true due to limited range
112       //       of data type int8_t [since the maximum of an exact width
113       //       signed integer of width N is 2^(N-1) - 1, which for int8_t
114       //       is 127].
115       {
116          fp->read( (char*)subRaw, count + 1);
117          numberOfReadBytes   += count + 1;
118          subRaw     += count + 1;
119          numberOfOutputBytes += count + 1;
120       }
121       else
122       {
123          if ( count <= -1 && count >= -127 )
124          {
125             int8_t newByte;
126             fp->read( (char*)&newByte, 1);
127             numberOfReadBytes += 1;
128             for( int i = 0; i < -count + 1; i++ )
129             {
130                subRaw[i] = newByte;
131             }
132             subRaw     += -count + 1;
133             numberOfOutputBytes += -count + 1;
134          }
135       }
136       // if count = 128 output nothing
137                                                                                 
138       if ( numberOfReadBytes > fragmentSize )
139       {
140          gdcmVerboseMacro( "Read more bytes than the segment size.");
141          return false;
142       }
143    }
144    return true;
145 }
146
147
148 } // end namespace gdcm
149