]> Creatis software - gdcm.git/blob - src/gdcmRLE.cxx
ENH: change malloc/calloc/free with there c++ equivalent
[gdcm.git] / src / gdcmRLE.cxx
1 // gdcmRLE.cxx
2 //-----------------------------------------------------------------------------
3 #include <stdio.h>
4 #include "gdcmFile.h"
5 #include <ctype.h>              // to declare isprint()
6
7 #define str2num(str, typeNum) *((typeNum *)(str))
8
9 //-----------------------------------------------------------------------------
10 /**
11  * \ingroup   gdcmFile
12  * \brief     Reads a 'Run Length Encoded' Dicom encapsulated file
13  * @param     fp already open File Pointer
14  * @param     image_buffer destination Address (in caller's memory space) 
15  *            at which the pixel data should be copied 
16  * @return    Boolean 
17  */
18 bool gdcmFile::gdcm_read_RLE_file (FILE *fp,void * image_buffer) {
19    long fragmentBegining; // for ftell, fseek
20    char * im = (char *)image_buffer;
21
22    long RleSegmentLength[15],fragmentLength,uncompressedSegmentSize;;
23    long ftellRes, ln;
24    guint32 nbRleSegments;
25    guint32 RleSegmentOffsetTable[15];
26    guint16 ItemTagGr,ItemTagEl;
27    uncompressedSegmentSize=Header->GetXSize()*Header->GetYSize();
28    ftellRes=ftell(fp);
29    // Basic Offset Table with Item Value
30       // Item Tag
31    fread(&ItemTagGr,2,1,fp);  // Reading (fffe):Basic Offset Table Item Tag Gr
32    fread(&ItemTagEl,2,1,fp);  // Reading (e000):Basic Offset Table Item Tag El
33    if(Header->GetSwapCode()) {
34       ItemTagGr=Header->SwapShort(ItemTagGr); 
35       ItemTagEl=Header->SwapShort(ItemTagEl);      
36    }
37       // Item Length
38    ftellRes=ftell(fp);
39    fread(&ln,4,1,fp); 
40    if(Header->GetSwapCode()) 
41       ln=Header->SwapLong(ln);    // Basic Offset Table Item Lentgh
42    if (ln != 0) {
43       // What is it used for ??
44       char * BasicOffsetTableItemValue= new char[ln+1];
45       fread(BasicOffsetTableItemValue,ln,1,fp); 
46       guint32 a;
47       for (int i=0;i<ln;i+=4){
48          a=str2num(&BasicOffsetTableItemValue[i],guint32);
49       }        
50    }
51
52    ftellRes=ftell(fp);
53    fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
54    fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
55    if(Header->GetSwapCode()) {
56       ItemTagGr=Header->SwapShort(ItemTagGr); 
57       ItemTagEl=Header->SwapShort(ItemTagEl);      
58    }  
59
60    // while 'Sequence Delimiter Item' (fffe,e0dd) not found
61    while (  ( ItemTagGr == 0xfffe) && (ItemTagEl != 0xe0dd) ) { 
62    // Parse fragments of the current Fragment (Frame)    
63       ftellRes=ftell(fp);
64       fread(&fragmentLength,4,1,fp); 
65       if(Header->GetSwapCode()) 
66          fragmentLength=Header->SwapLong(fragmentLength);    // length
67
68           //------------------ scanning (not reading) fragment pixels
69  
70       fread(&nbRleSegments,4,1,fp);  // Reading : Number of RLE Segments        
71       if(Header->GetSwapCode()) 
72          nbRleSegments=Header->SwapLong(nbRleSegments);
73  
74       for(int k=1; k<=15; k++) { // Reading RLE Segments Offset Table
75          ftellRes=ftell(fp);
76          fread(&RleSegmentOffsetTable[k],4,1,fp);
77          if(Header->GetSwapCode())
78             RleSegmentOffsetTable[k]=Header->SwapLong(RleSegmentOffsetTable[k]);
79       }
80
81       if (nbRleSegments>1) { 
82          for(unsigned int k=1; k<=nbRleSegments-1; k++) { // reading RLE Segments
83             RleSegmentLength[k]=RleSegmentOffsetTable[k+1]-RleSegmentOffsetTable[k];
84             ftellRes=ftell(fp);
85             fragmentBegining=ftell(fp);   
86             gdcm_read_RLE_fragment (&im, RleSegmentLength[k],uncompressedSegmentSize,fp);
87             fseek(fp,fragmentBegining,SEEK_SET);  
88             fseek(fp,RleSegmentLength[k],SEEK_CUR);        
89          }
90       }
91       RleSegmentLength[nbRleSegments] = fragmentLength - RleSegmentOffsetTable[nbRleSegments];
92       ftellRes=ftell(fp);
93       fragmentBegining=ftell(fp);
94       gdcm_read_RLE_fragment (&im, RleSegmentLength[nbRleSegments],uncompressedSegmentSize, fp);
95       fseek(fp,fragmentBegining,SEEK_SET);  
96       fseek(fp,RleSegmentLength[nbRleSegments],SEEK_CUR);    
97       
98       // end of scanning fragment pixels       
99    
100       ftellRes=ftell(fp);
101       fread(&ItemTagGr,2,1,fp);  // Reading (fffe) : Item Tag Gr
102       fread(&ItemTagEl,2,1,fp);  // Reading (e000) : Item Tag El
103       if(Header->GetSwapCode()) {
104          ItemTagGr=Header->SwapShort(ItemTagGr); 
105          ItemTagEl=Header->SwapShort(ItemTagEl);      
106       }
107    } 
108    
109    if (Header->GetBitsAllocated()==16) { // try to deal with RLE 16 Bits
110    
111       im = (char *)image_buffer;
112          //  need to make 16 Bits Pixels from Low Byte and Hight Byte 'Planes'
113
114       int l = Header->GetXSize()*Header->GetYSize();
115       int nbFrames = Header->GetZSize();
116
117       char * newDest = new char[l*nbFrames*2];
118       char *x  = newDest;
119       char * a = (char *)image_buffer;
120       char * b = a + l;
121
122       for (int i=0;i<nbFrames;i++) {
123          for (int j=0;j<l; j++) {
124             *(x++) = *(a++);
125             *(x++) = *(b++);
126          }
127       }
128       memmove(image_buffer,newDest,lgrTotale);
129       delete[] newDest;
130    }
131       
132    return(true);
133 }
134
135
136 // ----------------------------------------------------------------------------
137 // RLE LossLess Fragment
138 int gdcmFile::gdcm_read_RLE_fragment(char **areaToRead, long lengthToDecode, 
139                                      long uncompressedSegmentSize, FILE *fp) {
140          (void)lengthToDecode;  //FIXME
141    long ftellRes;
142    int count;
143    long numberOfOutputBytes=0;
144    char n, car;
145    ftellRes =ftell(fp);
146
147    while(numberOfOutputBytes<uncompressedSegmentSize) {
148       ftellRes =ftell(fp);
149       fread(&n,sizeof(char),1,fp);
150       count=n;
151       if (count >= 0 && count <= 127) {
152          fread(*areaToRead,(count+1)*sizeof(char),1,fp);
153          *areaToRead+=count+1;
154          numberOfOutputBytes+=count+1;
155       } else {
156          if (count <= -1 && count >= -127) {
157             fread(&car,sizeof(char),1,fp);
158             for(int i=0; i<-count+1; i++) {
159                (*areaToRead)[i]=car;  
160             }
161             *areaToRead+=(-count+1);
162             numberOfOutputBytes+=(-count+1); 
163          }
164       } 
165       // if count = 128 output nothing (See : PS 3.5-2003 Page 86)
166    } 
167    return 1;
168 }
169
170 // ----------------------------------------------------------------------------