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