]> Creatis software - gdcm.git/blob - src/gdcmJpegIdo.cxx
*ENH: Added CharEvent to browse throught a multiframe volume, press any key it will...
[gdcm.git] / src / gdcmJpegIdo.cxx
1 #include "iddcmjpeg.h"
2 #include <stdlib.h>     
3         
4 static ClbJpeg* ClbJpegAlloc(void);
5 static void     ClbJpegInit (ClbJpeg *); 
6 static int      ClbJpegDecodeDiff(ClbJpeg *);
7 static BOOL     ClbJpegDecodeData(ClbJpeg *);
8 static int      ClbJpegReadBit(ClbJpeg *);
9 static BOOL     ClbJpegReadHeader(ClbJpeg *);
10 static BOOL     ClbJpegStart(ClbJpeg *,FILE *); 
11 static BOOL     ClbJpegFillHuffTable(ClbJpeg *);
12
13 void _IdDcmJpegFree(ClbJpeg *jpg) {
14    free(jpg->DataImg);
15    free(jpg);
16 }
17
18 ClbJpeg * _IdDcmJpegRead (FILE * fp){
19    ClbJpeg * jpg=NULL;
20    //printf("entree ds _IdDcmJpegRead depuis gdcm\n");
21    jpg=ClbJpegAlloc();
22    if(!jpg) {
23       printf("Fail to ClbJpegAlloc \n");
24       return(NULL);
25          }
26    ClbJpegInit (jpg); 
27    if(!ClbJpegStart(jpg, fp)) {
28       printf("Fail to ClbJpegStart \n");
29       return (NULL);
30    }
31    return (jpg);
32 }
33         
34 static void ClbJpegInit (ClbJpeg *jpg) {
35    int n;
36    for (n=0;n<256;n++) {
37       jpg->lHuffTable[n].HufCode=0;
38       jpg->lHuffTable[n].HufSz  =0;
39       jpg->lHuffTable[n].HufVal =0;
40    }
41    jpg->ValCurByte     =0;
42    jpg->PosCurBit      =10;
43    jpg->MarkerFound    =0;
44    jpg->RestartInterval=0;
45 }
46
47 static ClbJpeg *ClbJpegAlloc(void) {
48    ClbJpeg * jpg;
49    jpg = (ClbJpeg *)malloc(sizeof(ClbJpeg));
50    ClbJpegInit(jpg);    
51    return jpg;
52 }
53
54 static BOOL ClbJpegFillHuffTable(ClbJpeg *jpg) {
55    unsigned char c;
56    //int testindex=0;
57    int n=0;
58    int NiDHT=0;
59    int indexY=0;
60    int k, Code, Si, i;
61
62    for (c=0;c<255;c++)
63       jpg->RawDHTstart[c]=0;
64
65    c=fgetc(jpg->infp);
66
67    jpg->MaxHuffSz =0;
68    jpg->MaxHuffVal=0;
69
70    for (n=1;n<17;n++) {
71       jpg->RawDHT[n]=fgetc(jpg->infp);
72       NiDHT+=jpg->RawDHT[n];
73       if (jpg->RawDHT[n]!=0)
74          jpg->MaxHuffSz=n;
75       }
76    for(n=1;n<16;n++) {
77       if(jpg->RawDHT[n]>0) {
78          jpg->RawDHTstart[n]=indexY+1;
79          for (i=1;i<(jpg->RawDHT[n]+1);i++) {
80             indexY+=1;
81             c=fgetc(jpg->infp);
82             jpg->lHuffTable[indexY].HufVal=c;
83             jpg->MaxHuffVal=c;
84             jpg->lHuffTable[indexY].HufSz=n;
85          }
86       }
87    }
88    k=1;
89    Code=0;
90         
91    Si=jpg->lHuffTable[k].HufSz;
92
93    while(1) {
94       if (k>=NiDHT) break;
95       while( Si==jpg->lHuffTable[k].HufSz) {
96          jpg->lHuffTable[k].HufCode=Code;
97          Code+=1;
98          k+=1;
99       }
100       if (k<NiDHT) {
101          while (jpg->lHuffTable[k].HufSz>Si) {
102             Code=Code<<1;
103             Si+=1;
104          }
105       }
106    }
107    return 1;
108 }       
109
110 static BOOL ClbJpegStart(ClbJpeg *jpg, FILE *inputfp) {
111    jpg->infp=inputfp;
112    if (!ClbJpegReadHeader(jpg)) {
113       printf("Fail to ClbJpegReadHeader\n");
114       return 0;
115    }
116    //printf("sortie ClbJpegReadHeader\n");
117    if (!ClbJpegDecodeData(jpg)) {
118       printf("Fail to ClbJpegDecodeData\n");
119       return 0;
120    }    
121    //printf("sortie ClbJpegDecodeData\n");
122    return 1;
123 }
124
125 static BOOL ClbJpegReadHeader(ClbJpeg *jpg) {
126    unsigned char gr;
127    unsigned char el;
128    unsigned char l1, l2;
129    unsigned int sztag;
130    long ouca=0;
131    BOOL HeaderEnd=0;
132    BOOL isLossLess=0;
133         
134    int tp;
135
136    gr=fgetc(jpg->infp);  //FF
137    el=fgetc(jpg->infp);  //D8
138
139    while(!HeaderEnd) {
140       gr=fgetc(jpg->infp);  
141       if(gr!=0xFF) {
142          printf("gr!=0xFF (=%02x)\n",gr);
143          return 0;
144       }
145       el=fgetc(jpg->infp);
146
147       if ( (el==0xFF) || (el==0x01) || (el==0xD8) ||(el==0xD9) ||( (el>=0xD0) && (el<=0xD7) ))
148                         ;
149       else {
150          l1=fgetc(jpg->infp);
151          l2=fgetc(jpg->infp);
152          sztag=(l1*256)+l2-2; //tag length
153          ouca=ftell(jpg->infp);
154
155          if (el==0xC3) {
156             jpg->lSof.precision=fgetc(jpg->infp);
157
158             l1=fgetc(jpg->infp);
159             l2=fgetc(jpg->infp);
160             jpg->lSof.Himg=(l1*256)+l2;
161                                 
162             //printf("%x %x Himg %d\n",l1,l2,jpg->lSof.Himg);
163
164             l1=fgetc(jpg->infp);
165             l2=fgetc(jpg->infp);
166             jpg->lSof.Wimg=(l1*256)+l2;
167
168             //printf("%x %x Wimg %d\n",l1,l2,jpg->lSof.Wimg);
169
170             jpg->lSof.NbComponent=fgetc(jpg->infp); 
171             //printf("NbComponent %d\n", jpg->lSof.NbComponent);
172
173             jpg->lSof.SofTabPos=ftell(jpg->infp);
174
175             isLossLess=1; // TRUE
176          }
177
178          if (el==0xC4) {
179             ClbJpegFillHuffTable(jpg);
180          }
181          if (el==0xDA) {
182             jpg->lSos.CompCount=fgetc(jpg->infp);
183             for (tp=0;tp<jpg->lSos.CompCount;tp++) {
184                jpg->lSos.CompId=fgetc(jpg->infp);
185                jpg->lSos.CompDc=fgetc(jpg->infp);
186             }
187             jpg->lSos.SpectralSelStart=fgetc(jpg->infp);
188             jpg->lSos.SpectralSelEnd=fgetc(jpg->infp);
189             jpg->lSos.SuccessiveAp=fgetc(jpg->infp);
190             jpg->lSos.Sospttrans=(jpg->lSos.SuccessiveAp & 16);
191             HeaderEnd=1;
192          }
193          if (el==0xDD) {
194             l1=fgetc(jpg->infp);
195             l2=fgetc(jpg->infp);
196             jpg->RestartInterval=(l1*256)+l2;
197          }
198
199          fseek(jpg->infp,(ouca+sztag),0);
200       }
201    }
202
203    if (!isLossLess) {
204       printf("NOT isLossLess\n");
205       return 0;
206    }
207    return 1;
208 }
209
210 static int ClbJpegReadBit(ClbJpeg *jpg) {
211         int r=0;
212         unsigned char c;
213         if(jpg->PosCurBit>8) // need lire octet suivant
214         {
215                 jpg->ValCurByte=fgetc(jpg->infp);
216                 if (jpg->ValCurByte==0xFF)
217                 {
218                         c=fgetc(jpg->infp);// est 00 ou restart marker: a skiper
219                         if (c!=0)
220                         {
221                                 jpg->ValCurByte=fgetc(jpg->infp);
222                                 jpg->PosCurBit=1;
223                                 jpg->MarkerFound=1;
224                                 return 0; 
225                         }
226                 }
227                 jpg->PosCurBit=2;
228                 return (jpg->ValCurByte>>7);
229         }
230         else
231         {
232                 r=(1&(jpg->ValCurByte>>(8-jpg->PosCurBit)));
233                 jpg->PosCurBit+=1;
234                 return r;
235         }
236 }
237
238
239 static BOOL ClbJpegDecodeData(ClbJpeg *jpg)
240 {
241         int iX,iY;
242         int lbInc=0;
243         unsigned int mask; 
244         int dimX;
245           
246         int lPredicted=(1<<(jpg->lSof.precision-1-jpg->lSos.Sospttrans));
247         dimX=jpg->lSof.Wimg;
248
249         jpg->ValCurByte=jpg->lSos.SuccessiveAp;
250         jpg->PosCurBit=9;
251         
252         if (jpg->lSof.precision==8)
253                 mask=0xFF;
254         if (jpg->lSof.precision==12)
255                 mask=0xFFF;
256         if (jpg->lSof.precision==16)
257                 mask=0xFFFF;
258
259 //printf("jpg->lSof.precision : %d\n",jpg->lSof.precision );
260 //printf("sizeof(*jpg->DataImg) : %d\n",sizeof(*jpg->DataImg) );
261
262         jpg->DataImg=(int*)malloc(jpg->lSof.Himg*dimX*sizeof(*jpg->DataImg)*jpg->lSof.NbComponent);    // *3
263         memset( jpg->DataImg,0,(jpg->lSof.Himg * dimX * sizeof(*jpg->DataImg)*jpg->lSof.NbComponent)); // *3
264
265         if (!jpg->RestartInterval)
266         {
267         //printf("il N'y a PAS un define interval\n");
268                 for(iX=0;iX<dimX*jpg->lSof.NbComponent;iX++) // lit première ligne // *3
269                 {
270                         lbInc+=1;
271                         if (lbInc>1)
272                                 lPredicted= jpg->DataImg[lbInc-1];
273                          jpg->DataImg[lbInc]=lPredicted+ClbJpegDecodeDiff(jpg);
274
275                         if (  jpg->DataImg[lbInc] > ((1<<(jpg->lSof.precision))-1) )
276                                  jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
277                         if ( jpg->DataImg[lbInc]<0) 
278                                  jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
279                 }
280
281                 for (iY=1;iY<jpg->lSof.Himg;iY++) //lit la suite
282                 {
283                         lbInc+=1;
284                         if (lbInc>(jpg->lSof.Himg*dimX*jpg->lSof.NbComponent-1)) break; //*3
285                         lPredicted= jpg->DataImg[lbInc-jpg->lSof.Wimg*jpg->lSof.NbComponent];//*3       // se base % premier é ligne d'avant
286                          jpg->DataImg[lbInc]=lPredicted+ClbJpegDecodeDiff(jpg);
287
288                         if (  jpg->DataImg[lbInc] > ((1<<(jpg->lSof.precision))-1) ) 
289                                  jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
290                         if ( jpg->DataImg[lbInc]<0) 
291                                  jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
292
293                         for(iX=1;iX<jpg->lSof.Wimg*jpg->lSof.NbComponent;iX++) //*3
294                         {
295                                 lbInc+=1;
296                                 if (lbInc>(jpg->lSof.Himg*jpg->lSof.Wimg*jpg->lSof.NbComponent-1)) break;//*3
297                                 if (jpg->lSos.SpectralSelStart==7) // si spectral
298                                         lPredicted=( jpg->DataImg[lbInc-1]+ jpg->DataImg[lbInc-jpg->lSof.Wimg*jpg->lSof.NbComponent])>>1; //*3
299                                 else
300                                         lPredicted= jpg->DataImg[lbInc-1];              // se base%pixel juste avant
301                                  jpg->DataImg[lbInc]=lPredicted+ClbJpegDecodeDiff(jpg);
302
303                                 if (  jpg->DataImg[lbInc] > ((1<<(jpg->lSof.precision))-1) ) 
304                                          jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
305                                 if ( jpg->DataImg[lbInc]<0) 
306                                          jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
307
308                         }
309                 }
310         }
311         else // il y a un define interval
312         {
313                 //printf("il y a un define interval\n");
314                 while(1)
315                 {
316                         jpg->MarkerFound=0;
317                         lPredicted=(1<<(jpg->lSof.precision - 1 - jpg->lSos.Sospttrans));
318                         for (iY=0;iY<jpg->RestartInterval;iY++) 
319                         {
320                                  jpg->DataImg[lbInc]=lPredicted+ClbJpegDecodeDiff(jpg);
321
322                                 if (  jpg->DataImg[lbInc] > ((1<<(jpg->lSof.precision))-1) ) 
323                                          jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
324                                 if ( jpg->DataImg[lbInc]<0) 
325                                          jpg->DataImg[lbInc]= jpg->DataImg[lbInc]&mask;
326
327                                 lbInc+=1;
328                                 if (lbInc>(jpg->lSof.Himg*jpg->lSof.Wimg*jpg->lSof.NbComponent-1)) return 1; //*3
329
330                                 if (jpg->lSos.SpectralSelStart==7) // si spectral
331                                         lPredicted=( jpg->DataImg[lbInc-1]+ jpg->DataImg[lbInc-jpg->lSof.Wimg*jpg->lSof.NbComponent])>>1; //*3
332                                 else
333                                         lPredicted= jpg->DataImg[lbInc-1];
334                         }
335                         while (!jpg->MarkerFound)
336                         {
337                                 ClbJpegReadBit(jpg); // skip bits restant avant restart marker
338                         }
339                 }
340         }
341         return 1;
342 }
343
344 static int ClbJpegDecodeDiff(ClbJpeg *jpg) {
345    int lInput;
346    int lInputBits;
347    int lHufVal;
348    int lDiff;
349    int lI;
350    int resultat;
351    lHufVal = 666;
352    lInput = 0;
353    lInputBits = 0;
354
355    while (1) {
356       lInputBits+=1;
357       lInput=(lInput<<1)+ClbJpegReadBit(jpg);
358       if (jpg->RawDHT[lInputBits]!=0) {
359          for(lI=jpg->RawDHTstart[lInputBits];lI<(jpg->RawDHTstart[lInputBits]+jpg->RawDHT[lInputBits]);lI++) {
360             if (lInput==jpg->lHuffTable[lI].HufCode)
361                lHufVal=jpg->lHuffTable[lI].HufVal;
362          }
363       }
364       if (lInputBits>=jpg->MaxHuffSz)
365          lHufVal=jpg->MaxHuffVal;
366       if (lHufVal<255) break;
367    }
368    if (lHufVal==0) resultat= 0;
369
370    if ( (lHufVal>0) && (lHufVal<16)) {
371       lDiff=0;
372       if( ClbJpegReadBit(jpg)==1) {
373          for (lI=1;lI<lHufVal;lI++) {
374             lDiff=(lDiff<<1)+ClbJpegReadBit(jpg);
375          }
376          resultat= (lDiff+(1<<(lHufVal-1)));
377       } else {
378          for (lI=1;lI<lHufVal;lI++)
379             lDiff=(lDiff<<1)+1-ClbJpegReadBit(jpg);
380          resultat= -(lDiff+(1<<(lHufVal-1)));
381       }
382    }
383    return resultat;     
384 }