]> Creatis software - gdcm.git/blob - src/gdcmRLE.cxx
7bdcee608734f544bf3e5fbb531c1c362d386602
[gdcm.git] / src / gdcmRLE.cxx
1 //This is needed when compiling in debug mode
2 #ifdef _MSC_VER
3 // 'identifier' : class 'type' needs to have dll-interface to be used by
4 // clients of class 'type2'
5 #pragma warning ( disable : 4251 )
6 // 'identifier' : identifier was truncated to 'number' characters in the
7 // debug information
8 #pragma warning ( disable : 4786 )
9 #endif //_MSC_VER
10
11 #include <stdio.h>
12 #include "gdcmFile.h"
13 #include <ctype.h>              /* to declare isprint() */
14
15 #define str2num(str, typeNum) *((typeNum *)(str))
16
17 static int _gdcm_read_RLE_fragment (char ** image_buffer, 
18                                     long lengthToDecode,
19                                     long uncompressedSegmentSize, 
20                                     FILE* fp);
21 // static because nothing but gdcm_read_RLE_file may call it
22
23 #define DEBUG 0
24 // Will be removed
25
26 // ----------------------------------------------------------------------------
27 /**
28  * \ingroup   gdcmFile
29  * \brief     Reads a 'Run Length Encoded' Dicom encapsulated file
30  * @param     image_buffer destination Address (in caller's memory space) 
31  *            at which the
32  *            pixel data should be copied
33  * @return    int acts as a Boolean 
34  */
35
36 // This is a debug version.
37 // Forget the printf as they will be removed
38 // as soon as the last Heuristics are checked
39
40 int
41 gdcmFile::gdcm_read_RLE_file (void * image_buffer) {
42    long fragmentBegining; // for ftell, fseek
43    char * im = (char *)image_buffer;
44    if (DEBUG)std::cout << "RLE image" << std::endl;
45
46    long RleSegmentLength[15],fragmentLength,uncompressedSegmentSize;;
47    long ftellRes, ln;
48    guint32 nbRleSegments;
49    guint32 RleSegmentOffsetTable[15];
50    guint16 ItemTagGr,ItemTagEl;
51    uncompressedSegmentSize=GetXSize()*GetYSize();
52    if (DEBUG)printf("uncompressedSegmentSize %d\n",uncompressedSegmentSize);
53    ftellRes=ftell(fp);
54    // Basic Offset Table with Item Value
55       // Item Tag
56    fread(&ItemTagGr,2,1,fp);  // Reading (fffe):Basic Offset Table Item Tag Gr
57    fread(&ItemTagEl,2,1,fp);  // Reading (e000):Basic Offset Table Item Tag El
58    if(GetSwapCode()) {
59       ItemTagGr=SwapShort(ItemTagGr); 
60       ItemTagEl=SwapShort(ItemTagEl);      
61    }
62    if (DEBUG)printf ("at %x : ItemTag (should be fffe,e000): %04x,%04x\n",
63           ftellRes,ItemTagGr,ItemTagEl );
64       // Item Length
65    ftellRes=ftell(fp);
66    fread(&ln,4,1,fp); 
67    if(GetSwapCode()) 
68       ln=SwapLong(ln);    // Basic Offset Table Item Lentgh
69    if (DEBUG)printf("at %x : Basic Offset Table Item Lentgh (??) %d x(%08x)\n",
70          ftellRes,ln,ln);
71    if (ln != 0) {
72       // What is it used for ??
73       char * BasicOffsetTableItemValue= (char *)malloc(ln+1);
74       fread(BasicOffsetTableItemValue,ln,1,fp); 
75       guint32 a;
76       for (int i=0;i<ln;i+=4){
77          a=str2num(&BasicOffsetTableItemValue[i],guint32);
78         if (DEBUG)printf("      x(%08x)  %d\n",a,a);
79       }        
80    }
81
82    ftellRes=ftell(fp);
83    fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
84    fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
85    if(GetSwapCode()) {
86       ItemTagGr=SwapShort(ItemTagGr); 
87       ItemTagEl=SwapShort(ItemTagEl);      
88    }  
89    if (DEBUG)printf ("at %x : ItemTag (should be fffe,e000 or e0dd): %04x,%04x\n",
90          ftellRes,ItemTagGr,ItemTagEl );
91
92    // while 'Sequence Delimiter Item' (fffe,e0dd) not found
93    while (  ( ItemTagGr == 0xfffe) && (ItemTagEl != 0xe0dd) ) { 
94    // Parse fragments of the current Fragment (Frame)    
95       ftellRes=ftell(fp);
96       fread(&fragmentLength,4,1,fp); 
97       if(GetSwapCode()) 
98          fragmentLength=SwapLong(fragmentLength);    // length
99       if (DEBUG)printf("      at %x : fragment length %d x(%08x)\n",
100              ftellRes, fragmentLength,fragmentLength);
101
102           //------------------ scanning (not reading) fragment pixels
103  
104       fread(&nbRleSegments,4,1,fp);  // Reading : Number of RLE Segments        
105       if(GetSwapCode()) 
106          nbRleSegments=SwapLong(nbRleSegments);
107          if (DEBUG)printf("         Nb of RLE Segments : %d\n",nbRleSegments);
108  
109       for(int k=1; k<=15; k++) { // Reading RLE Segments Offset Table
110          ftellRes=ftell(fp);
111          fread(&RleSegmentOffsetTable[k],4,1,fp);
112          if(GetSwapCode())
113             RleSegmentOffsetTable[k]=SwapLong(RleSegmentOffsetTable[k]);
114          if (DEBUG)printf("        at : %x Offset Segment %d : %d (%x)\n",
115                  ftellRes,k,RleSegmentOffsetTable[k],RleSegmentOffsetTable[k]);
116       }
117
118       if (nbRleSegments>1) { 
119          for(int k=1; k<=nbRleSegments-1; k++) { // reading RLE Segments
120             RleSegmentLength[k]=RleSegmentOffsetTable[k+1]-RleSegmentOffsetTable[k];
121             ftellRes=ftell(fp);
122             if (DEBUG)printf ("       (in) Segment %d : Length = %d  x(%x) Start at %x\n",
123                                  k,RleSegmentLength[k],RleSegmentLength[k], ftellRes);
124             fragmentBegining=ftell(fp);   
125             _gdcm_read_RLE_fragment (&im, RleSegmentLength[k],uncompressedSegmentSize,fp);
126             fseek(fp,fragmentBegining,SEEK_SET);  
127             fseek(fp,RleSegmentLength[k],SEEK_CUR);        
128          }
129       }
130       RleSegmentLength[nbRleSegments] = fragmentLength - RleSegmentOffsetTable[nbRleSegments];
131       ftellRes=ftell(fp);
132       if (DEBUG)printf ("        (out)Segment %d : Length = %d  x(%x) Start at %x\n",
133                        nbRleSegments,
134                        RleSegmentLength[nbRleSegments],RleSegmentLength[nbRleSegments],
135                        ftellRes);
136       fragmentBegining=ftell(fp);
137       _gdcm_read_RLE_fragment (&im, RleSegmentLength[nbRleSegments],uncompressedSegmentSize, fp);
138       fseek(fp,fragmentBegining,SEEK_SET);  
139       fseek(fp,RleSegmentLength[nbRleSegments],SEEK_CUR);    
140       
141       // end of scanning fragment pixels       
142    
143       ftellRes=ftell(fp);
144       fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
145       fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
146       if(GetSwapCode()) {
147          ItemTagGr=SwapShort(ItemTagGr); 
148          ItemTagEl=SwapShort(ItemTagEl);      
149       }
150       if (DEBUG)printf ("at %x : ItemTag (should be fffe,e000 or e0dd): %04x,%04x\n",
151             ftellRes,ItemTagGr,ItemTagEl );
152    } 
153    return (1);
154 }
155
156
157  /* -------------------------------------------------------------------- */
158  //
159  // RLE LossLess Fragment
160  //
161  /* -------------------------------------------------------------------- */
162
163    // static because nothing but gdcm_read_RLE_file can call it
164    // DO NOT doxygen !
165
166 static int
167 _gdcm_read_RLE_fragment (char ** areaToRead, 
168                          long lengthToDecode, 
169                          long uncompressedSegmentSize, 
170                          FILE* fp) {
171    long ftellRes;
172    int count;
173    long numberOfOutputBytes=0;
174    char n, car;
175    ftellRes =ftell(fp);
176
177    while(numberOfOutputBytes<uncompressedSegmentSize) {
178
179       ftellRes =ftell(fp);
180       fread(&n,sizeof(char),1,fp);
181       count=n;
182       if (count >= 0 && count <= 127) {
183          fread(*areaToRead,(count+1)*sizeof(char),1,fp);
184          *areaToRead+=count+1;
185          numberOfOutputBytes+=count+1;
186       } else {
187          if (count <= -1 && count >= -127) {
188             fread(&car,sizeof(char),1,fp);
189             for(int i=0; i<-count+1; i++) {
190                (*areaToRead)[i]=car;  
191             }
192             *areaToRead+=(-count+1);
193             numberOfOutputBytes+=(-count+1); 
194          }
195       } 
196       // if count = 128 output nothing (See : PS 3.5-2003 Page 86)
197    } 
198    return 1;
199 }